#!/usr/bin/env python3 """Extract and compare action mappings from both .set files""" import sys sys.path.insert(0, r'C:\DEV\COPILOT\geutebruck-api\src\api') import grpc import json from protos import configuration_pb2 from protos import configuration_pb2_grpc def parse_set_file(filepath): """Parse a .set file and extract action mappings""" print(f"\nParsing: {filepath}") print("=" * 70) # Read file with open(filepath, 'rb') as f: data = f.read() print(f"File size: {len(data):,} bytes") # Use gRPC to parse (we'll need to temporarily copy the file) # For now, let's just count ules markers and extract basic info ules_positions = [] pos = 0 while True: pos = data.find(b'ules', pos) if pos == -1: break # Include all ules markers ules_positions.append(pos) pos += 4 print(f"Found {len(ules_positions)} action mappings ('ules' markers)") # Extract basic info from each mapping mappings = [] for i, offset in enumerate(ules_positions): # Try to extract some context start = offset # Read up to 500 bytes to capture the mapping end = min(len(data), offset + 500) chunk = data[start:end] # Try to extract actions (07 01 40 pattern) actions = [] pos_in_chunk = 0 while pos_in_chunk < len(chunk) - 10: if chunk[pos_in_chunk:pos_in_chunk+3] == b'\x07\x01\x40': # Found action pattern action_len = int.from_bytes(chunk[pos_in_chunk+3:pos_in_chunk+5], 'little') if action_len > 0 and action_len < 300 and pos_in_chunk + 5 + action_len <= len(chunk): action_str = chunk[pos_in_chunk+5:pos_in_chunk+5+action_len].decode('utf-8', errors='ignore') actions.append(action_str) pos_in_chunk += 5 + action_len else: pos_in_chunk += 1 else: pos_in_chunk += 1 # Try to extract parameters (01 pattern) parameters = [] pos_in_chunk = 5 # Skip initial marker while pos_in_chunk < min(200, len(chunk)) - 10: if chunk[pos_in_chunk] == 0x01: param_name_len = chunk[pos_in_chunk + 1] if param_name_len > 0 and param_name_len < 50 and pos_in_chunk + 2 + param_name_len <= len(chunk): param_name = chunk[pos_in_chunk+2:pos_in_chunk+2+param_name_len].decode('utf-8', errors='ignore') if param_name.startswith('.'): parameters.append(param_name.strip('.')) pos_in_chunk += 2 + param_name_len continue pos_in_chunk += 1 mappings.append({ 'index': i + 1, 'offset': offset, 'actions': actions, 'parameters': parameters }) return mappings def compare_mappings(original_mappings, added_mappings): """Compare two sets of mappings to find differences""" print("\n" + "=" * 70) print("COMPARISON RESULTS:") print("=" * 70) print(f"\nOriginal: {len(original_mappings)} mappings") print(f"Modified: {len(added_mappings)} mappings") print(f"Difference: {len(added_mappings) - len(original_mappings)}") # Create action signatures for comparison def get_signature(mapping): return tuple(sorted(mapping['actions'])) original_sigs = {get_signature(m): m for m in original_mappings} added_sigs = {get_signature(m): m for m in added_mappings} # Find new mappings new_mappings = [] for sig, mapping in added_sigs.items(): if sig not in original_sigs: new_mappings.append(mapping) # Find removed mappings removed_mappings = [] for sig, mapping in original_sigs.items(): if sig not in added_sigs: removed_mappings.append(mapping) if new_mappings: print(f"\n\nNEW MAPPINGS ADDED ({len(new_mappings)}):") print("=" * 70) for mapping in new_mappings: print(f"\nMapping #{mapping['index']} at offset {mapping['offset']} (0x{mapping['offset']:X}):") print(f" Actions ({len(mapping['actions'])}):") for action in mapping['actions']: print(f" - {action}") if mapping['parameters']: print(f" Parameters ({len(mapping['parameters'])}):") for param in mapping['parameters']: print(f" - {param}") if removed_mappings: print(f"\n\nMAPPINGS REMOVED ({len(removed_mappings)}):") print("=" * 70) for mapping in removed_mappings: print(f"\nMapping #{mapping['index']} at offset {mapping['offset']} (0x{mapping['offset']:X}):") print(f" Actions ({len(mapping['actions'])}):") for action in mapping['actions']: print(f" - {action}") # Show all mappings from added file print(f"\n\nALL MAPPINGS IN MODIFIED FILE:") print("=" * 70) for i, mapping in enumerate(added_mappings[:10], 1): # Show first 10 print(f"\n{i}. Offset {mapping['offset']} (0x{mapping['offset']:X})") if mapping['actions']: print(f" Actions: {', '.join(mapping['actions'][:2])}") if len(mapping['actions']) > 2: print(f" ... and {len(mapping['actions']) - 2} more") if mapping['parameters']: print(f" Parameters: {', '.join(mapping['parameters'][:5])}") return new_mappings, removed_mappings if __name__ == '__main__': original_file = 'TestMKS_original.set' added_file = 'TestMKS_added_mapping.set' # Parse both files original_mappings = parse_set_file(original_file) added_mappings = parse_set_file(added_file) # Compare new_mappings, removed_mappings = compare_mappings(original_mappings, added_mappings) # Save results results = { 'original_count': len(original_mappings), 'modified_count': len(added_mappings), 'new_mappings': new_mappings, 'removed_mappings': removed_mappings } with open('mapping_comparison_results.json', 'w', encoding='utf-8') as f: json.dump(results, f, indent=2, ensure_ascii=False) print(f"\n\nResults saved to: mapping_comparison_results.json")