svg-processor/processing/json_builder.py
2025-05-16 18:15:31 +04:00

151 lines
6.3 KiB
Python

import logging
# Assuming svg_utils is in the same directory or path
from . import svg_utils # Use relative import
logger = logging.getLogger(__name__)
def create_element_json(element_name, element_id, element_label, element_count, x, y, svg_type, label_prefix, rotation_angle=0, element_width=None, element_height=None, x_offset=0, y_offset=0, original_name=None, debug_buffer=None, has_prefix_mapping=None, custom_options=None, debug=False):
"""Create a JSON object for an SVG element."""
# Ensure custom_options is a dictionary
custom_options = custom_options or {}
# If not provided, element_width and element_height should be retrieved from custom_options
if element_width is None:
element_width = custom_options.get('width', 10)
if debug:
logger.debug(f"Using fallback width: {element_width}")
if element_height is None:
element_height = custom_options.get('height', 10)
if debug:
logger.debug(f"Using fallback height: {element_height}")
# Store debug buffer contents if provided
debug_messages = []
if debug_buffer is not None:
debug_messages = debug_buffer.copy()
# Log all debug messages to the console for transparency
if debug:
for msg in debug_messages:
logger.debug(msg)
logger.debug("==== END DEBUG ====")
# Get the appropriate element type and props path based on prefix
exact_match = None
fallback_match = None
logger.debug(f"Looking for mapping for svg_type={svg_type}, label_prefix='{label_prefix}'")
available_mappings = custom_options.get('element_mappings', [])
logger.debug(f"Available mappings: {len(available_mappings)}")
# Debug print all available mappings
if debug:
for i, mapping in enumerate(available_mappings):
logger.debug(f" Available mapping #{i+1}: svg_type={mapping.get('svg_type', 'None')}, label_prefix='{mapping.get('label_prefix', '')}'")
if label_prefix:
for mapping in available_mappings:
if mapping.get('svg_type', '') == svg_type and mapping.get('label_prefix', '') == label_prefix:
exact_match = mapping
logger.debug(f"Found exact match: {mapping}")
break
# Then look for a fallback with no prefix
for mapping in available_mappings:
if mapping.get('svg_type', '') == svg_type and not mapping.get('label_prefix', ''):
fallback_match = mapping
if not exact_match: # Only print if we haven't found an exact match
logger.debug(f"Found fallback match: {mapping}")
break
# Use the appropriate mapping
mapping_to_use = exact_match or fallback_match
# Get element type and props path from mapping
element_type = "ia.display.view" # Default
props_path = "Symbol-Views/Equipment-Views/Status" # Default
if mapping_to_use:
element_type = mapping_to_use.get('element_type', element_type)
props_path = mapping_to_use.get('props_path', props_path)
logger.debug(f"Selected mapping: {mapping_to_use}")
logger.debug(f"Using element_type: {element_type} from {'exact match' if exact_match else 'fallback match'}")
logger.debug(f"Using props_path: {props_path} from {'exact match' if exact_match else 'fallback match'}")
else:
warning_msg = f"WARNING: No mapping found for svg_type={svg_type}, label_prefix='{label_prefix}'. Using defaults: type={element_type}, props={props_path}"
logger.warning(warning_msg)
# Only display in UI for specific types or when in debug mode to avoid flooding
if debug or svg_type in ['rect', 'path'] and not label_prefix:
svg_utils.ui_print(warning_msg, logging.WARNING)
# Preserve rotation angle as float for accuracy, just format it for output
try:
rotation_angle = float(rotation_angle)
except (ValueError, TypeError):
rotation_angle = 0
# Create metadata and meta object
meta = {
'id': element_id,
'name': element_name,
'originalName': original_name or element_name, # Preserve original name
'elementPrefix': label_prefix if label_prefix else None,
'elementNumber': element_count # Add element count for reference
}
# Add info about mapping used
if mapping_to_use:
meta['mappingUsed'] = {
'svg_type': mapping_to_use.get('svg_type'),
'label_prefix': mapping_to_use.get('label_prefix')
}
meta['mappingType'] = 'exact' if exact_match else 'fallback'
else:
meta['mappingUsed'] = None
meta['mappingType'] = 'none'
if has_prefix_mapping is not None:
meta['hasPrefixMapping'] = has_prefix_mapping
# Apply final prefix/suffix info to meta if applicable
if mapping_to_use:
final_prefix = mapping_to_use.get('final_prefix', '')
final_suffix = mapping_to_use.get('final_suffix', '')
if final_prefix:
meta['finalPrefixApplied'] = final_prefix
# If we're applying a final prefix, elementPrefix should reflect the original logical prefix
if not meta['elementPrefix']:
meta['elementPrefix'] = mapping_to_use.get('label_prefix', '') # Use the prefix from the mapping that triggered the final_prefix
if debug:
logger.debug(f"Setting elementPrefix to '{meta['elementPrefix']}' based on mapping that provided final_prefix")
if final_suffix:
meta['finalSuffixApplied'] = final_suffix
# Build the element JSON object with the simpler position structure
element_json = {
'type': element_type,
'version': 0,
'props': {
'path': props_path
},
'meta': meta,
'position': {
'x': round(x, 2), # Round coordinates for cleaner output
'y': round(y, 2),
'width': element_width,
'height': element_height
},
'custom': {}
}
# Add rotation if it's not 0 (or very close to 0)
if abs(rotation_angle) > 1e-6:
element_json['position']['rotate'] = {
'angle': f"{round(rotation_angle, 2)}deg", # Round angle
'anchor': '50% 50%'
}
return element_json