diff --git a/capella_ros_tools/data_model.py b/capella_ros_tools/data_model.py index 03d96c6..506cfa5 100644 --- a/capella_ros_tools/data_model.py +++ b/capella_ros_tools/data_model.py @@ -56,16 +56,19 @@ class TypeDef: name: str card: Range - range: Range | None = None package: str | None = None def __str__(self) -> str: """Return string representation of the type.""" out = self.name - if self.range: - out += f"{UPPER_BOUND_TOKEN}{self.range.max}" - if self.card.min != self.card.max: - out += f"[{self.card.max if self.card.max != '*' else ''}]" + if self.card.min == self.card.max: + out += f"[{self.card.max}]" if self.card.max != "1" else "" + else: + out += ( + f"[{UPPER_BOUND_TOKEN}{self.card.max}]" + if self.card.max != "*" + else "[]" + ) if self.package: out = f"{self.package}{PACKAGE_NAME_MESSAGE_TYPE_SEPARATOR}{out}" return out @@ -75,22 +78,23 @@ def from_string(cls, type_str: str) -> TypeDef: """Create a type definition from a string.""" name = type_str card = Range("1", "1") - range = None if type_str.endswith("]"): name, _, max_card = type_str.partition("[") - max_card = max_card.rstrip("]") - max_card = max_card if max_card else "*" - card = Range("0", max_card) - if UPPER_BOUND_TOKEN in name: - name, _, max_value = name.rpartition(UPPER_BOUND_TOKEN) - range = Range("0", max_value) + max_card = max_card.removesuffix("]") + if max_card.startswith(UPPER_BOUND_TOKEN): + max_card = max_card.removeprefix(UPPER_BOUND_TOKEN) + card = Range("0", max_card) + else: + card = ( + Range(max_card, max_card) if max_card else Range("0", "*") + ) if len(temp := name.split(PACKAGE_NAME_MESSAGE_TYPE_SEPARATOR)) == 2: package, name = temp else: package = None - return cls(name, card, range, package) + return cls(name, card, package) @dataclass diff --git a/capella_ros_tools/exporter.py b/capella_ros_tools/exporter.py index d45a81a..8d5f108 100644 --- a/capella_ros_tools/exporter.py +++ b/capella_ros_tools/exporter.py @@ -21,23 +21,24 @@ def export(current_pkg: information.DataPkg, current_path: pathlib.Path): for cls_obj in current_pkg.classes: fields = [] for prop_obj in cls_obj.owned_properties: - type_def = data_model.TypeDef( - name=prop_obj.type.name, - card=data_model.Range( + try: + card = data_model.Range( prop_obj.min_card.value, prop_obj.max_card.value - ), - ) + ) + except AttributeError: + card = data_model.Range("1", "1") + type_def = data_model.TypeDef(name=prop_obj.type.name, card=card) prop_def = data_model.FieldDef( type=type_def, name=prop_obj.name, - description=prop_obj.description, + description=prop_obj.description or "", ) fields.append(prop_def) cls_def = data_model.MessageDef( name=cls_obj.name, fields=fields, enums=[], - description=cls_obj.description, + description=cls_obj.description or "", ) (current_path / f"{_clean_name(cls_obj.name)}.msg").write_text( str(cls_def) @@ -61,13 +62,13 @@ def export(current_pkg: information.DataPkg, current_path: pathlib.Path): type=type_def, name=lit_obj.name, value=literal_value, - description=lit_obj.description, + description=lit_obj.description or "", ) literals.append(lit_def) enum_def = data_model.EnumDef( name=enum_obj.name, literals=literals, - description=enum_obj.description, + description=enum_obj.description or "", ) (current_path / f"{_clean_name(enum_obj.name)}.msg").write_text( str(enum_def) diff --git a/capella_ros_tools/importer.py b/capella_ros_tools/importer.py index db63369..87b08fc 100644 --- a/capella_ros_tools/importer.py +++ b/capella_ros_tools/importer.py @@ -134,13 +134,6 @@ def _convert_class( "LiteralNumericValue", value=field_def.type.card.max ), } - if field_def.type.range: - prop_yml["min_value"] = decl.NewObject( - "LiteralNumericValue", value=field_def.type.range.min - ) - prop_yml["max_value"] = decl.NewObject( - "LiteralNumericValue", value=field_def.type.range.max - ) associations.append( { diff --git a/tests/conftest.py b/tests/conftest.py index b15f9ef..46ad28d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -19,7 +19,7 @@ def sample_class_def(): name="SampleClass", fields=[ FieldDef( - type=TypeDef("uint8", Range("0", "*"), Range("0", "10"), None), + type=TypeDef("uint8", Range("0", "10"), None), name="sample_field1", description="This block comment is added to the " "property description of sample_field1. " @@ -27,21 +27,19 @@ def sample_class_def(): "property description of sample_field1. ", ), FieldDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("SampleClassEnum", Range("0", "*"), "package2"), name="sample_field2", description="This block comment is added to the property " "descriptions of sample_field2 and sample_field3. ", ), FieldDef( - TypeDef("uint8", Range("0", "*"), None, None), + TypeDef("uint8", Range("3", "3"), None), name="sample_field3", description="This block comment is added to the property " "descriptions of sample_field2 and sample_field3. ", ), FieldDef( - type=TypeDef( - "SampleEnum", Range("1", "1"), None, "SampleEnum" - ), + type=TypeDef("SampleEnum", Range("1", "1"), "SampleEnum"), name="sample_field4", description="This block comment is added to the property " "descriptions of sample_field4 and sample_field5. " @@ -52,9 +50,7 @@ def sample_class_def(): "cf. SampleEnum ", ), FieldDef( - type=TypeDef( - "SampleEnumValue", Range("1", "1"), None, "SampleEnum" - ), + type=TypeDef("SampleEnumValue", Range("1", "1"), "SampleEnum"), name="sample_field5", description="This block comment is added to the property " "descriptions of sample_field4 and sample_field5. " @@ -84,13 +80,13 @@ def sample_enum_def(): name="SampleEnumValue", literals=[ ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="RED", value="0", description="", ), ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="BLUE", value="1", description="This inline comment " @@ -99,14 +95,14 @@ def sample_enum_def(): "description of BLUE. ", ), ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="YELLOW", value="2", description="This block comment is added to the " "enum literal descriptions of YELLOW and GREEN. ", ), ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="GREEN", value="3", description="This block comment is added to the " @@ -121,25 +117,25 @@ def sample_enum_def(): name="SampleEnum", literals=[ ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="OK", value="0", description="", ), ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="WARN", value="1", description="", ), ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="ERROR", value="2", description="", ), ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="STALE", value="3", description="", @@ -164,7 +160,6 @@ def sample_class_enum_def(): type=TypeDef( "SampleClassEnumStatus", Range("1", "1"), - None, "SampleClassEnum", ), name="status", @@ -172,14 +167,12 @@ def sample_class_enum_def(): "SampleClassEnumStatus. ", ), FieldDef( - type=TypeDef( - "Color", Range("1", "1"), None, "SampleClassEnum" - ), + type=TypeDef("Color", Range("1", "1"), "SampleClassEnum"), name="color", description="The property color is of type Color. ", ), FieldDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="field", description="", ), @@ -189,25 +182,25 @@ def sample_class_enum_def(): name="SampleClassEnumStatus", literals=[ ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="OK", value="0", description="", ), ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="WARN", value="1", description="", ), ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="ERROR", value="2", description="", ), ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="STALE", value="3", description="", @@ -220,19 +213,19 @@ def sample_class_enum_def(): name="Color", literals=[ ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="RED", value="0", description="", ), ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="BLUE", value="1", description="", ), ConstantDef( - type=TypeDef("uint8", Range("1", "1"), None, None), + type=TypeDef("uint8", Range("1", "1"), None), name="YELLOW", value="2", description="", diff --git a/tests/data/data_model/example_msgs.yaml b/tests/data/data_model/example_msgs.yaml index 39da090..7fb5c49 100644 --- a/tests/data/data_model/example_msgs.yaml +++ b/tests/data/data_model/example_msgs.yaml @@ -23,25 +23,19 @@ _type: LiteralNumericValue value: "0" max_card: !new_object - _type: LiteralNumericValue - value: "*" - min_value: !new_object - _type: LiteralNumericValue - value: "0" - max_value: !new_object _type: LiteralNumericValue value: "10" - promise_id: package1.SampleClass.sample_field2 name: sample_field2 description: "This block comment is added to the property descriptions of sample_field2 and sample_field3. " - type: !promise package1.uint8 + type: !promise package2.SampleClassEnum kind: COMPOSITION min_card: !new_object _type: LiteralNumericValue - value: "1" + value: "0" max_card: !new_object _type: LiteralNumericValue - value: "1" + value: "*" - promise_id: package1.SampleClass.sample_field3 name: sample_field3 description: "This block comment is added to the property descriptions of sample_field2 and sample_field3. " @@ -49,10 +43,10 @@ kind: COMPOSITION min_card: !new_object _type: LiteralNumericValue - value: "0" + value: "3" max_card: !new_object _type: LiteralNumericValue - value: "*" + value: "3" - promise_id: package1.SampleClass.sample_field4 name: sample_field4 description: "This block comment is added to the property descriptions of sample_field4 and sample_field5. Fields in SampleClass can reference enums in other files. The property sample_field4 is of type SampleEnum. cf. SampleEnum " diff --git a/tests/data/data_model/example_msgs/package1/msg/SampleClass.msg b/tests/data/data_model/example_msgs/package1/msg/SampleClass.msg index 74d72af..1a76f01 100644 --- a/tests/data/data_model/example_msgs/package1/msg/SampleClass.msg +++ b/tests/data/data_model/example_msgs/package1/msg/SampleClass.msg @@ -10,12 +10,12 @@ # This block comment is also added to the # property description of sample_field1. -uint8<=10[] sample_field1 +uint8[<=10] sample_field1 # This block comment is added to the property # descriptions of sample_field2 and sample_field3. -uint8 sample_field2 -uint8[] sample_field3 +package2/SampleClassEnum[] sample_field2 +uint8[3] sample_field3 # This block comment is added to the property # descriptions of sample_field4 and sample_field5. diff --git a/tests/data/empty_project_60/empty_project_60.capella b/tests/data/empty_project_60/empty_project_60.capella index cff913f..4dd4adc 100644 --- a/tests/data/empty_project_60/empty_project_60.capella +++ b/tests/data/empty_project_60/empty_project_60.capella @@ -165,6 +165,41 @@ value="0"/> + + + + + + + + + + + + + + + + + + + + + + @@ -201,7 +236,12996 @@ + id="03e7ba96-68f5-4c7f-85ed-8932b65f53a7" name="Data"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +