[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FK1PMZRTPA40HCMBCQFRWR":3,"skill-same:01M6FK1PMZRTPA40HCMBCQFRWR":57},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":24,"linkOnly":25,"markdownContent":26,"markdownBody":27,"frontMatter":28,"refName":30,"commitSha":31,"skillDirectory":32,"forksCount":33,"repositoryHtmlUrl":34,"repositoryHomepageUrl":6,"ownerHtmlUrl":35,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":36,"install":37,"resources":50},"01M6FK1PMZRTPA40HCMBCQFRWR","ontology-mapper",null,"Map construction data to standard ontologies. Create semantic mappings between different data schemas","kbarbel640-del\u002Fskills","kbarbel640-del","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F255315490?v=4","01M6CJPPQGCCESXMG3K7BBGQ5J","01M6CJPPX2PB2BCZERFVM2C2B3",1,"MIT","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fontology-mapper\u002FSKILL.md",[],[18,19,20,21,22,23],"ontology mapper","ontology","create","data","map","semantic","2026-11-10 10:12:30",false,"---\r\nslug: \"ontology-mapper\"\r\ndisplay_name: \"Ontology Mapper\"\r\ndescription: \"Map construction data to standard ontologies. Create semantic mappings between different data schemas\"\r\n---\r\n\r\n# Ontology Mapper\r\n\r\n## Overview\r\n\r\nBased on DDC methodology (Chapter 2.2), this skill maps construction data to standard ontologies like IFC, COBie, Uniclass, and OmniClass, enabling semantic interoperability between systems.\r\n\r\n**Book Reference:** \"Доминирование открытых данных\" \u002F \"Open Data Dominance\"\r\n\r\n## Quick Start\r\n\r\n```python\r\nfrom dataclasses import dataclass, field\r\nfrom enum import Enum\r\nfrom typing import List, Dict, Optional, Set, Tuple\r\nfrom datetime import datetime\r\nimport json\r\nimport re\r\n\r\nclass OntologyType(Enum):\r\n    \"\"\"Standard construction ontologies\"\"\"\r\n    IFC = \"ifc\"                    # Industry Foundation Classes\r\n    COBIE = \"cobie\"                # Construction Operations Building Information Exchange\r\n    UNICLASS = \"uniclass\"          # UK classification\r\n    OMNICLASS = \"omniclass\"        # North American classification\r\n    MASTERFORMAT = \"masterformat\"  # CSI MasterFormat\r\n    UNIFORMAT = \"uniformat\"        # CSI UniFormat\r\n    CUSTOM = \"custom\"              # Custom ontology\r\n\r\nclass MappingConfidence(Enum):\r\n    \"\"\"Confidence level of mapping\"\"\"\r\n    EXACT = \"exact\"        # 100% match\r\n    HIGH = \"high\"          # 90%+ match\r\n    MEDIUM = \"medium\"      # 70-90% match\r\n    LOW = \"low\"            # 50-70% match\r\n    UNCERTAIN = \"uncertain\" # \u003C50% match\r\n\r\nclass RelationType(Enum):\r\n    \"\"\"Types of relationships between concepts\"\"\"\r\n    EQUIVALENT = \"equivalent\"     # Same concept\r\n    BROADER = \"broader\"           # Source is more specific\r\n    NARROWER = \"narrower\"         # Source is more general\r\n    RELATED = \"related\"           # Related but not equivalent\r\n    PART_OF = \"part_of\"           # Component relationship\r\n    HAS_PART = \"has_part\"         # Contains components\r\n\r\n@dataclass\r\nclass OntologyConcept:\r\n    \"\"\"Concept in an ontology\"\"\"\r\n    id: str\r\n    name: str\r\n    ontology: OntologyType\r\n    definition: Optional[str] = None\r\n    parent_id: Optional[str] = None\r\n    synonyms: List[str] = field(default_factory=list)\r\n    properties: Dict[str, str] = field(default_factory=dict)\r\n\r\n@dataclass\r\nclass SemanticMapping:\r\n    \"\"\"Mapping between two concepts\"\"\"\r\n    source_concept: str\r\n    source_ontology: OntologyType\r\n    target_concept: str\r\n    target_ontology: OntologyType\r\n    relation: RelationType\r\n    confidence: MappingConfidence\r\n    notes: Optional[str] = None\r\n    created_by: str = \"auto\"\r\n    created_at: datetime = field(default_factory=datetime.now)\r\n\r\n@dataclass\r\nclass MappingResult:\r\n    \"\"\"Result of ontology mapping operation\"\"\"\r\n    source_field: str\r\n    source_value: str\r\n    mappings: List[SemanticMapping]\r\n    best_match: Optional[SemanticMapping] = None\r\n    unmapped: bool = False\r\n\r\n@dataclass\r\nclass OntologyMappingReport:\r\n    \"\"\"Complete mapping report\"\"\"\r\n    total_fields: int\r\n    mapped_fields: int\r\n    unmapped_fields: int\r\n    mappings: List[MappingResult]\r\n    coverage: float\r\n    confidence_distribution: Dict[str, int]\r\n    recommendations: List[str]\r\n\r\n\r\nclass OntologyMapper:\r\n    \"\"\"\r\n    Map construction data to standard ontologies.\r\n    Based on DDC methodology Chapter 2.2.\r\n    \"\"\"\r\n\r\n    def __init__(self):\r\n        self.ontologies = self._load_ontologies()\r\n        self.mapping_rules = self._load_mapping_rules()\r\n        self.synonym_map = self._build_synonym_map()\r\n\r\n    def _load_ontologies(self) -> Dict[OntologyType, Dict[str, OntologyConcept]]:\r\n        \"\"\"Load standard construction ontologies\"\"\"\r\n        ontologies = {}\r\n\r\n        # IFC Schema (simplified)\r\n        ontologies[OntologyType.IFC] = {\r\n            \"IfcWall\": OntologyConcept(\"IfcWall\", \"Wall\", OntologyType.IFC,\r\n                \"A vertical construction that bounds or subdivides spaces\"),\r\n            \"IfcSlab\": OntologyConcept(\"IfcSlab\", \"Slab\", OntologyType.IFC,\r\n                \"A horizontal planar building element\"),\r\n            \"IfcBeam\": OntologyConcept(\"IfcBeam\", \"Beam\", OntologyType.IFC,\r\n                \"A horizontal structural member\"),\r\n            \"IfcColumn\": OntologyConcept(\"IfcColumn\", \"Column\", OntologyType.IFC,\r\n                \"A vertical structural member\"),\r\n            \"IfcDoor\": OntologyConcept(\"IfcDoor\", \"Door\", OntologyType.IFC,\r\n                \"A building element for access\"),\r\n            \"IfcWindow\": OntologyConcept(\"IfcWindow\", \"Window\", OntologyType.IFC,\r\n                \"A building element for light and ventilation\"),\r\n            \"IfcRoof\": OntologyConcept(\"IfcRoof\", \"Roof\", OntologyType.IFC,\r\n                \"A building element covering a building\"),\r\n            \"IfcStair\": OntologyConcept(\"IfcStair\", \"Stair\", OntologyType.IFC,\r\n                \"A vertical circulation element\"),\r\n            \"IfcSpace\": OntologyConcept(\"IfcSpace\", \"Space\", OntologyType.IFC,\r\n                \"A defined volume of air\"),\r\n            \"IfcBuildingStorey\": OntologyConcept(\"IfcBuildingStorey\", \"Building Storey\",\r\n                OntologyType.IFC, \"A horizontal aggregation of spaces\"),\r\n        }\r\n\r\n        # COBie (simplified)\r\n        ontologies[OntologyType.COBIE] = {\r\n            \"Floor\": OntologyConcept(\"Floor\", \"Floor\", OntologyType.COBIE,\r\n                \"A floor or level in a building\"),\r\n            \"Space\": OntologyConcept(\"Space\", \"Space\", OntologyType.COBIE,\r\n                \"A spatial region\"),\r\n            \"Type\": OntologyConcept(\"Type\", \"Type\", OntologyType.COBIE,\r\n                \"A product type or specification\"),\r\n            \"Component\": OntologyConcept(\"Component\", \"Component\", OntologyType.COBIE,\r\n                \"An individual product instance\"),\r\n            \"Zone\": OntologyConcept(\"Zone\", \"Zone\", OntologyType.COBIE,\r\n                \"A spatial grouping of spaces\"),\r\n            \"System\": OntologyConcept(\"System\", \"System\", OntologyType.COBIE,\r\n                \"A building system or network\"),\r\n        }\r\n\r\n        # Uniclass (simplified)\r\n        ontologies[OntologyType.UNICLASS] = {\r\n            \"Ss_25\": OntologyConcept(\"Ss_25\", \"Wall Systems\", OntologyType.UNICLASS),\r\n            \"Ss_30\": OntologyConcept(\"Ss_30\", \"Roof Systems\", OntologyType.UNICLASS),\r\n            \"Ss_32\": OntologyConcept(\"Ss_32\", \"Floor Systems\", OntologyType.UNICLASS),\r\n            \"Ss_35\": OntologyConcept(\"Ss_35\", \"Stair Systems\", OntologyType.UNICLASS),\r\n            \"Pr_20\": OntologyConcept(\"Pr_20\", \"Structural Products\", OntologyType.UNICLASS),\r\n            \"Pr_30\": OntologyConcept(\"Pr_30\", \"Wall Products\", OntologyType.UNICLASS),\r\n            \"Pr_35\": OntologyConcept(\"Pr_35\", \"Door Products\", OntologyType.UNICLASS),\r\n            \"Pr_40\": OntologyConcept(\"Pr_40\", \"Window Products\", OntologyType.UNICLASS),\r\n        }\r\n\r\n        # MasterFormat (simplified)\r\n        ontologies[OntologyType.MASTERFORMAT] = {\r\n            \"03\": OntologyConcept(\"03\", \"Concrete\", OntologyType.MASTERFORMAT),\r\n            \"04\": OntologyConcept(\"04\", \"Masonry\", OntologyType.MASTERFORMAT),\r\n            \"05\": OntologyConcept(\"05\", \"Metals\", OntologyType.MASTERFORMAT),\r\n            \"06\": OntologyConcept(\"06\", \"Wood and Plastics\", OntologyType.MASTERFORMAT),\r\n            \"07\": OntologyConcept(\"07\", \"Thermal and Moisture Protection\", OntologyType.MASTERFORMAT),\r\n            \"08\": OntologyConcept(\"08\", \"Doors and Windows\", OntologyType.MASTERFORMAT),\r\n            \"09\": OntologyConcept(\"09\", \"Finishes\", OntologyType.MASTERFORMAT),\r\n            \"22\": OntologyConcept(\"22\", \"Plumbing\", OntologyType.MASTERFORMAT),\r\n            \"23\": OntologyConcept(\"23\", \"HVAC\", OntologyType.MASTERFORMAT),\r\n            \"26\": OntologyConcept(\"26\", \"Electrical\", OntologyType.MASTERFORMAT),\r\n        }\r\n\r\n        return ontologies\r\n\r\n    def _load_mapping_rules(self) -> List[SemanticMapping]:\r\n        \"\"\"Load predefined mapping rules between ontologies\"\"\"\r\n        rules = [\r\n            # IFC to COBie\r\n            SemanticMapping(\"IfcBuildingStorey\", OntologyType.IFC, \"Floor\",\r\n                OntologyType.COBIE, RelationType.EQUIVALENT, MappingConfidence.EXACT),\r\n            SemanticMapping(\"IfcSpace\", OntologyType.IFC, \"Space\",\r\n                OntologyType.COBIE, RelationType.EQUIVALENT, MappingConfidence.EXACT),\r\n\r\n            # IFC to Uniclass\r\n            SemanticMapping(\"IfcWall\", OntologyType.IFC, \"Ss_25\",\r\n                OntologyType.UNICLASS, RelationType.RELATED, MappingConfidence.HIGH),\r\n            SemanticMapping(\"IfcRoof\", OntologyType.IFC, \"Ss_30\",\r\n                OntologyType.UNICLASS, RelationType.RELATED, MappingConfidence.HIGH),\r\n            SemanticMapping(\"IfcSlab\", OntologyType.IFC, \"Ss_32\",\r\n                OntologyType.UNICLASS, RelationType.RELATED, MappingConfidence.HIGH),\r\n            SemanticMapping(\"IfcDoor\", OntologyType.IFC, \"Pr_35\",\r\n                OntologyType.UNICLASS, RelationType.RELATED, MappingConfidence.HIGH),\r\n            SemanticMapping(\"IfcWindow\", OntologyType.IFC, \"Pr_40\",\r\n                OntologyType.UNICLASS, RelationType.RELATED, MappingConfidence.HIGH),\r\n\r\n            # IFC to MasterFormat\r\n            SemanticMapping(\"IfcDoor\", OntologyType.IFC, \"08\",\r\n                OntologyType.MASTERFORMAT, RelationType.BROADER, MappingConfidence.MEDIUM),\r\n            SemanticMapping(\"IfcWindow\", OntologyType.IFC, \"08\",\r\n                OntologyType.MASTERFORMAT, RelationType.BROADER, MappingConfidence.MEDIUM),\r\n        ]\r\n        return rules\r\n\r\n    def _build_synonym_map(self) -> Dict[str, List[str]]:\r\n        \"\"\"Build synonym mappings for fuzzy matching\"\"\"\r\n        return {\r\n            \"wall\": [\"partition\", \"barrier\", \"divider\"],\r\n            \"door\": [\"entrance\", \"portal\", \"opening\"],\r\n            \"window\": [\"glazing\", \"fenestration\", \"opening\"],\r\n            \"floor\": [\"slab\", \"deck\", \"storey\", \"level\"],\r\n            \"roof\": [\"roofing\", \"covering\", \"canopy\"],\r\n            \"beam\": [\"girder\", \"joist\", \"lintel\"],\r\n            \"column\": [\"pillar\", \"post\", \"pier\"],\r\n            \"stair\": [\"stairway\", \"staircase\", \"steps\"],\r\n            \"space\": [\"room\", \"area\", \"zone\"],\r\n            \"concrete\": [\"cement\", \"reinforced\"],\r\n            \"steel\": [\"metal\", \"iron\"],\r\n        }\r\n\r\n    def map_field(\r\n        self,\r\n        field_name: str,\r\n        field_value: str,\r\n        source_ontology: Optional[OntologyType] = None,\r\n        target_ontology: OntologyType = OntologyType.IFC\r\n    ) -> MappingResult:\r\n        \"\"\"\r\n        Map a single field to target ontology.\r\n\r\n        Args:\r\n            field_name: Name of the field\r\n            field_value: Value to map\r\n            source_ontology: Source ontology if known\r\n            target_ontology: Target ontology to map to\r\n\r\n        Returns:\r\n            Mapping result with possible matches\r\n        \"\"\"\r\n        mappings = []\r\n\r\n        # Normalize the value\r\n        normalized = self._normalize_value(field_value)\r\n\r\n        # Check direct matches in existing rules\r\n        for rule in self.mapping_rules:\r\n            if rule.target_ontology == target_ontology:\r\n                if self._matches(normalized, rule.source_concept):\r\n                    mappings.append(rule)\r\n\r\n        # Check target ontology directly\r\n        target_concepts = self.ontologies.get(target_ontology, {})\r\n        for concept_id, concept in target_concepts.items():\r\n            similarity = self._calculate_similarity(normalized, concept)\r\n            if similarity > 0.5:\r\n                confidence = self._similarity_to_confidence(similarity)\r\n                mappings.append(SemanticMapping(\r\n                    source_concept=field_value,\r\n                    source_ontology=source_ontology or OntologyType.CUSTOM,\r\n                    target_concept=concept_id,\r\n                    target_ontology=target_ontology,\r\n                    relation=RelationType.EQUIVALENT if similarity > 0.9 else RelationType.RELATED,\r\n                    confidence=confidence\r\n                ))\r\n\r\n        # Sort by confidence\r\n        confidence_order = [\r\n            MappingConfidence.EXACT,\r\n            MappingConfidence.HIGH,\r\n            MappingConfidence.MEDIUM,\r\n            MappingConfidence.LOW,\r\n            MappingConfidence.UNCERTAIN\r\n        ]\r\n        mappings.sort(key=lambda m: confidence_order.index(m.confidence))\r\n\r\n        return MappingResult(\r\n            source_field=field_name,\r\n            source_value=field_value,\r\n            mappings=mappings,\r\n            best_match=mappings[0] if mappings else None,\r\n            unmapped=len(mappings) == 0\r\n        )\r\n\r\n    def _normalize_value(self, value: str) -> str:\r\n        \"\"\"Normalize a value for matching\"\"\"\r\n        # Remove common prefixes\r\n        prefixes = [\"ifc\", \"cobie\", \"type\", \"element\"]\r\n        normalized = value.lower().strip()\r\n\r\n        for prefix in prefixes:\r\n            if normalized.startswith(prefix):\r\n                normalized = normalized[len(prefix):]\r\n\r\n        return normalized.strip(\"_- \")\r\n\r\n    def _matches(self, value: str, concept: str) -> bool:\r\n        \"\"\"Check if value matches concept\"\"\"\r\n        normalized_value = self._normalize_value(value)\r\n        normalized_concept = self._normalize_value(concept)\r\n        return normalized_value == normalized_concept\r\n\r\n    def _calculate_similarity(\r\n        self,\r\n        value: str,\r\n        concept: OntologyConcept\r\n    ) -> float:\r\n        \"\"\"Calculate similarity between value and concept\"\"\"\r\n        value_lower = value.lower()\r\n        concept_name_lower = concept.name.lower()\r\n        concept_id_lower = concept.id.lower()\r\n\r\n        # Exact match\r\n        if value_lower == concept_name_lower or value_lower == concept_id_lower:\r\n            return 1.0\r\n\r\n        # Partial match in name\r\n        if value_lower in concept_name_lower or concept_name_lower in value_lower:\r\n            return 0.8\r\n\r\n        # Check synonyms\r\n        for key, synonyms in self.synonym_map.items():\r\n            if key in value_lower:\r\n                if key in concept_name_lower:\r\n                    return 0.9\r\n                for syn in synonyms:\r\n                    if syn in concept_name_lower:\r\n                        return 0.7\r\n\r\n        # Definition match\r\n        if concept.definition:\r\n            if value_lower in concept.definition.lower():\r\n                return 0.6\r\n\r\n        return 0.0\r\n\r\n    def _similarity_to_confidence(self, similarity: float) -> MappingConfidence:\r\n        \"\"\"Convert similarity score to confidence level\"\"\"\r\n        if similarity >= 0.95:\r\n            return MappingConfidence.EXACT\r\n        elif similarity >= 0.8:\r\n            return MappingConfidence.HIGH\r\n        elif similarity >= 0.6:\r\n            return MappingConfidence.MEDIUM\r\n        elif similarity >= 0.4:\r\n            return MappingConfidence.LOW\r\n        else:\r\n            return MappingConfidence.UNCERTAIN\r\n\r\n    def map_schema(\r\n        self,\r\n        schema: Dict[str, List[str]],\r\n        target_ontology: OntologyType = OntologyType.IFC\r\n    ) -> OntologyMappingReport:\r\n        \"\"\"\r\n        Map entire schema to target ontology.\r\n\r\n        Args:\r\n            schema: Dictionary of field names to sample values\r\n            target_ontology: Target ontology\r\n\r\n        Returns:\r\n            Complete mapping report\r\n        \"\"\"\r\n        all_mappings = []\r\n        confidence_dist = {c.value: 0 for c in MappingConfidence}\r\n\r\n        for field_name, sample_values in schema.items():\r\n            # Use first sample value\r\n            value = sample_values[0] if sample_values else field_name\r\n\r\n            result = self.map_field(field_name, value, target_ontology=target_ontology)\r\n            all_mappings.append(result)\r\n\r\n            if result.best_match:\r\n                confidence_dist[result.best_match.confidence.value] += 1\r\n\r\n        mapped = sum(1 for m in all_mappings if not m.unmapped)\r\n        unmapped = len(all_mappings) - mapped\r\n        coverage = mapped \u002F len(all_mappings) if all_mappings else 0\r\n\r\n        recommendations = self._generate_recommendations(all_mappings, coverage)\r\n\r\n        return OntologyMappingReport(\r\n            total_fields=len(all_mappings),\r\n            mapped_fields=mapped,\r\n            unmapped_fields=unmapped,\r\n            mappings=all_mappings,\r\n            coverage=coverage,\r\n            confidence_distribution=confidence_dist,\r\n            recommendations=recommendations\r\n        )\r\n\r\n    def _generate_recommendations(\r\n        self,\r\n        mappings: List[MappingResult],\r\n        coverage: float\r\n    ) -> List[str]:\r\n        \"\"\"Generate recommendations for improving mappings\"\"\"\r\n        recommendations = []\r\n\r\n        if coverage \u003C 0.7:\r\n            recommendations.append(\r\n                f\"Low mapping coverage ({coverage:.0%}). Consider adding custom mappings.\"\r\n            )\r\n\r\n        low_confidence = [m for m in mappings\r\n                         if m.best_match and m.best_match.confidence\r\n                         in [MappingConfidence.LOW, MappingConfidence.UNCERTAIN]]\r\n        if low_confidence:\r\n            recommendations.append(\r\n                f\"{len(low_confidence)} mappings have low confidence. Review manually.\"\r\n            )\r\n\r\n        unmapped = [m for m in mappings if m.unmapped]\r\n        if unmapped:\r\n            fields = [m.source_field for m in unmapped[:5]]\r\n            recommendations.append(\r\n                f\"Unmapped fields: {', '.join(fields)}. Add custom mappings.\"\r\n            )\r\n\r\n        return recommendations\r\n\r\n    def create_mapping(\r\n        self,\r\n        source: str,\r\n        source_ontology: OntologyType,\r\n        target: str,\r\n        target_ontology: OntologyType,\r\n        relation: RelationType = RelationType.EQUIVALENT,\r\n        notes: Optional[str] = None\r\n    ) -> SemanticMapping:\r\n        \"\"\"Create a new manual mapping\"\"\"\r\n        mapping = SemanticMapping(\r\n            source_concept=source,\r\n            source_ontology=source_ontology,\r\n            target_concept=target,\r\n            target_ontology=target_ontology,\r\n            relation=relation,\r\n            confidence=MappingConfidence.EXACT,\r\n            notes=notes,\r\n            created_by=\"manual\"\r\n        )\r\n        self.mapping_rules.append(mapping)\r\n        return mapping\r\n\r\n    def export_mappings(self, format: str = \"json\") -> str:\r\n        \"\"\"Export all mappings\"\"\"\r\n        if format == \"json\":\r\n            mappings_data = []\r\n            for rule in self.mapping_rules:\r\n                mappings_data.append({\r\n                    \"source\": rule.source_concept,\r\n                    \"source_ontology\": rule.source_ontology.value,\r\n                    \"target\": rule.target_concept,\r\n                    \"target_ontology\": rule.target_ontology.value,\r\n                    \"relation\": rule.relation.value,\r\n                    \"confidence\": rule.confidence.value\r\n                })\r\n            return json.dumps(mappings_data, indent=2)\r\n        else:\r\n            raise ValueError(f\"Unsupported format: {format}\")\r\n\r\n    def generate_report(self, report: OntologyMappingReport) -> str:\r\n        \"\"\"Generate mapping report\"\"\"\r\n        output = f\"\"\"\r\n# Ontology Mapping Report\r\n\r\n## Summary\r\n- **Total Fields:** {report.total_fields}\r\n- **Mapped Fields:** {report.mapped_fields}\r\n- **Unmapped Fields:** {report.unmapped_fields}\r\n- **Coverage:** {report.coverage:.0%}\r\n\r\n## Confidence Distribution\r\n\"\"\"\r\n        for conf, count in report.confidence_distribution.items():\r\n            if count > 0:\r\n                output += f\"- **{conf.title()}:** {count}\\n\"\r\n\r\n        output += \"\\n## Recommendations\\n\"\r\n        for rec in report.recommendations:\r\n            output += f\"- {rec}\\n\"\r\n\r\n        output += \"\\n## Mappings\\n\"\r\n        for mapping in report.mappings[:20]:\r\n            status = \"✓\" if not mapping.unmapped else \"✗\"\r\n            target = mapping.best_match.target_concept if mapping.best_match else \"unmapped\"\r\n            conf = mapping.best_match.confidence.value if mapping.best_match else \"-\"\r\n            output += f\"- {status} {mapping.source_field}: {mapping.source_value} → {target} ({conf})\\n\"\r\n\r\n        return output\r\n```\r\n\r\n## Common Use Cases\r\n\r\n### Map Field to IFC\r\n\r\n```python\r\nmapper = OntologyMapper()\r\n\r\n# Map a single field\r\nresult = mapper.map_field(\r\n    field_name=\"element_type\",\r\n    field_value=\"Wall\",\r\n    target_ontology=OntologyType.IFC\r\n)\r\n\r\nif result.best_match:\r\n    print(f\"Mapped to: {result.best_match.target_concept}\")\r\n    print(f\"Confidence: {result.best_match.confidence.value}\")\r\n```\r\n\r\n### Map Entire Schema\r\n\r\n```python\r\n# Define schema with sample values\r\nschema = {\r\n    \"element_type\": [\"Wall\", \"Door\", \"Window\"],\r\n    \"level\": [\"Level 1\", \"Level 2\"],\r\n    \"material\": [\"Concrete\", \"Steel\"],\r\n    \"room_type\": [\"Office\", \"Corridor\"]\r\n}\r\n\r\nreport = mapper.map_schema(schema, target_ontology=OntologyType.IFC)\r\n\r\nprint(f\"Coverage: {report.coverage:.0%}\")\r\nprint(f\"Mapped: {report.mapped_fields}\u002F{report.total_fields}\")\r\n```\r\n\r\n### Create Custom Mappings\r\n\r\n```python\r\n# Add custom mapping\r\nmapper.create_mapping(\r\n    source=\"CustomWallType\",\r\n    source_ontology=OntologyType.CUSTOM,\r\n    target=\"IfcWall\",\r\n    target_ontology=OntologyType.IFC,\r\n    relation=RelationType.EQUIVALENT,\r\n    notes=\"Custom wall type from legacy system\"\r\n)\r\n```\r\n\r\n## Quick Reference\r\n\r\n| Component | Purpose |\r\n|-----------|---------|\r\n| `OntologyMapper` | Main mapping engine |\r\n| `OntologyType` | Standard ontologies (IFC, COBie, etc.) |\r\n| `SemanticMapping` | Mapping between concepts |\r\n| `MappingResult` | Result of mapping operation |\r\n| `RelationType` | Relationship types |\r\n| `MappingConfidence` | Confidence levels |\r\n\r\n## Resources\r\n\r\n- **Book**: \"Data-Driven Construction\" by Artem Boiko, Chapter 2.2\r\n- **Website**: https:\u002F\u002Fdatadrivenconstruction.io\r\n\r\n## Next Steps\r\n\r\n- Use [open-data-integrator](..\u002Fopen-data-integrator\u002FSKILL.md) for open data\r\n- Use [data-model-designer](..\u002F..\u002FChapter-2.5\u002Fdata-model-designer\u002FSKILL.md) for schema design\r\n- Use [bim-validation-pipeline](..\u002F..\u002FChapter-4.3\u002Fbim-validation-pipeline\u002FSKILL.md) for validation\r\n","# Ontology Mapper\r\n\r\n## Overview\r\n\r\nBased on DDC methodology (Chapter 2.2), this skill maps construction data to standard ontologies like IFC, COBie, Uniclass, and OmniClass, enabling semantic interoperability between systems.\r\n\r\n**Book Reference:** \"Доминирование открытых данных\" \u002F \"Open Data Dominance\"\r\n\r\n## Quick Start\r\n\r\n```python\r\nfrom dataclasses import dataclass, field\r\nfrom enum import Enum\r\nfrom typing import List, Dict, Optional, Set, Tuple\r\nfrom datetime import datetime\r\nimport json\r\nimport re\r\n\r\nclass OntologyType(Enum):\r\n    \"\"\"Standard construction ontologies\"\"\"\r\n    IFC = \"ifc\"                    # Industry Foundation Classes\r\n    COBIE = \"cobie\"                # Construction Operations Building Information Exchange\r\n    UNICLASS = \"uniclass\"          # UK classification\r\n    OMNICLASS = \"omniclass\"        # North American classification\r\n    MASTERFORMAT = \"masterformat\"  # CSI MasterFormat\r\n    UNIFORMAT = \"uniformat\"        # CSI UniFormat\r\n    CUSTOM = \"custom\"              # Custom ontology\r\n\r\nclass MappingConfidence(Enum):\r\n    \"\"\"Confidence level of mapping\"\"\"\r\n    EXACT = \"exact\"        # 100% match\r\n    HIGH = \"high\"          # 90%+ match\r\n    MEDIUM = \"medium\"      # 70-90% match\r\n    LOW = \"low\"            # 50-70% match\r\n    UNCERTAIN = \"uncertain\" # \u003C50% match\r\n\r\nclass RelationType(Enum):\r\n    \"\"\"Types of relationships between concepts\"\"\"\r\n    EQUIVALENT = \"equivalent\"     # Same concept\r\n    BROADER = \"broader\"           # Source is more specific\r\n    NARROWER = \"narrower\"         # Source is more general\r\n    RELATED = \"related\"           # Related but not equivalent\r\n    PART_OF = \"part_of\"           # Component relationship\r\n    HAS_PART = \"has_part\"         # Contains components\r\n\r\n@dataclass\r\nclass OntologyConcept:\r\n    \"\"\"Concept in an ontology\"\"\"\r\n    id: str\r\n    name: str\r\n    ontology: OntologyType\r\n    definition: Optional[str] = None\r\n    parent_id: Optional[str] = None\r\n    synonyms: List[str] = field(default_factory=list)\r\n    properties: Dict[str, str] = field(default_factory=dict)\r\n\r\n@dataclass\r\nclass SemanticMapping:\r\n    \"\"\"Mapping between two concepts\"\"\"\r\n    source_concept: str\r\n    source_ontology: OntologyType\r\n    target_concept: str\r\n    target_ontology: OntologyType\r\n    relation: RelationType\r\n    confidence: MappingConfidence\r\n    notes: Optional[str] = None\r\n    created_by: str = \"auto\"\r\n    created_at: datetime = field(default_factory=datetime.now)\r\n\r\n@dataclass\r\nclass MappingResult:\r\n    \"\"\"Result of ontology mapping operation\"\"\"\r\n    source_field: str\r\n    source_value: str\r\n    mappings: List[SemanticMapping]\r\n    best_match: Optional[SemanticMapping] = None\r\n    unmapped: bool = False\r\n\r\n@dataclass\r\nclass OntologyMappingReport:\r\n    \"\"\"Complete mapping report\"\"\"\r\n    total_fields: int\r\n    mapped_fields: int\r\n    unmapped_fields: int\r\n    mappings: List[MappingResult]\r\n    coverage: float\r\n    confidence_distribution: Dict[str, int]\r\n    recommendations: List[str]\r\n\r\n\r\nclass OntologyMapper:\r\n    \"\"\"\r\n    Map construction data to standard ontologies.\r\n    Based on DDC methodology Chapter 2.2.\r\n    \"\"\"\r\n\r\n    def __init__(self):\r\n        self.ontologies = self._load_ontologies()\r\n        self.mapping_rules = self._load_mapping_rules()\r\n        self.synonym_map = self._build_synonym_map()\r\n\r\n    def _load_ontologies(self) -> Dict[OntologyType, Dict[str, OntologyConcept]]:\r\n        \"\"\"Load standard construction ontologies\"\"\"\r\n        ontologies = {}\r\n\r\n        # IFC Schema (simplified)\r\n        ontologies[OntologyType.IFC] = {\r\n            \"IfcWall\": OntologyConcept(\"IfcWall\", \"Wall\", OntologyType.IFC,\r\n                \"A vertical construction that bounds or subdivides spaces\"),\r\n            \"IfcSlab\": OntologyConcept(\"IfcSlab\", \"Slab\", OntologyType.IFC,\r\n                \"A horizontal planar building element\"),\r\n            \"IfcBeam\": OntologyConcept(\"IfcBeam\", \"Beam\", OntologyType.IFC,\r\n                \"A horizontal structural member\"),\r\n            \"IfcColumn\": OntologyConcept(\"IfcColumn\", \"Column\", OntologyType.IFC,\r\n                \"A vertical structural member\"),\r\n            \"IfcDoor\": OntologyConcept(\"IfcDoor\", \"Door\", OntologyType.IFC,\r\n                \"A building element for access\"),\r\n            \"IfcWindow\": OntologyConcept(\"IfcWindow\", \"Window\", OntologyType.IFC,\r\n                \"A building element for light and ventilation\"),\r\n            \"IfcRoof\": OntologyConcept(\"IfcRoof\", \"Roof\", OntologyType.IFC,\r\n                \"A building element covering a building\"),\r\n            \"IfcStair\": OntologyConcept(\"IfcStair\", \"Stair\", OntologyType.IFC,\r\n                \"A vertical circulation element\"),\r\n            \"IfcSpace\": OntologyConcept(\"IfcSpace\", \"Space\", OntologyType.IFC,\r\n                \"A defined volume of air\"),\r\n            \"IfcBuildingStorey\": OntologyConcept(\"IfcBuildingStorey\", \"Building Storey\",\r\n                OntologyType.IFC, \"A horizontal aggregation of spaces\"),\r\n        }\r\n\r\n        # COBie (simplified)\r\n        ontologies[OntologyType.COBIE] = {\r\n            \"Floor\": OntologyConcept(\"Floor\", \"Floor\", OntologyType.COBIE,\r\n                \"A floor or level in a building\"),\r\n            \"Space\": OntologyConcept(\"Space\", \"Space\", OntologyType.COBIE,\r\n                \"A spatial region\"),\r\n            \"Type\": OntologyConcept(\"Type\", \"Type\", OntologyType.COBIE,\r\n                \"A product type or specification\"),\r\n            \"Component\": OntologyConcept(\"Component\", \"Component\", OntologyType.COBIE,\r\n                \"An individual product instance\"),\r\n            \"Zone\": OntologyConcept(\"Zone\", \"Zone\", OntologyType.COBIE,\r\n                \"A spatial grouping of spaces\"),\r\n            \"System\": OntologyConcept(\"System\", \"System\", OntologyType.COBIE,\r\n                \"A building system or network\"),\r\n        }\r\n\r\n        # Uniclass (simplified)\r\n        ontologies[OntologyType.UNICLASS] = {\r\n            \"Ss_25\": OntologyConcept(\"Ss_25\", \"Wall Systems\", OntologyType.UNICLASS),\r\n            \"Ss_30\": OntologyConcept(\"Ss_30\", \"Roof Systems\", OntologyType.UNICLASS),\r\n            \"Ss_32\": OntologyConcept(\"Ss_32\", \"Floor Systems\", OntologyType.UNICLASS),\r\n            \"Ss_35\": OntologyConcept(\"Ss_35\", \"Stair Systems\", OntologyType.UNICLASS),\r\n            \"Pr_20\": OntologyConcept(\"Pr_20\", \"Structural Products\", OntologyType.UNICLASS),\r\n            \"Pr_30\": OntologyConcept(\"Pr_30\", \"Wall Products\", OntologyType.UNICLASS),\r\n            \"Pr_35\": OntologyConcept(\"Pr_35\", \"Door Products\", OntologyType.UNICLASS),\r\n            \"Pr_40\": OntologyConcept(\"Pr_40\", \"Window Products\", OntologyType.UNICLASS),\r\n        }\r\n\r\n        # MasterFormat (simplified)\r\n        ontologies[OntologyType.MASTERFORMAT] = {\r\n            \"03\": OntologyConcept(\"03\", \"Concrete\", OntologyType.MASTERFORMAT),\r\n            \"04\": OntologyConcept(\"04\", \"Masonry\", OntologyType.MASTERFORMAT),\r\n            \"05\": OntologyConcept(\"05\", \"Metals\", OntologyType.MASTERFORMAT),\r\n            \"06\": OntologyConcept(\"06\", \"Wood and Plastics\", OntologyType.MASTERFORMAT),\r\n            \"07\": OntologyConcept(\"07\", \"Thermal and Moisture Protection\", OntologyType.MASTERFORMAT),\r\n            \"08\": OntologyConcept(\"08\", \"Doors and Windows\", OntologyType.MASTERFORMAT),\r\n            \"09\": OntologyConcept(\"09\", \"Finishes\", OntologyType.MASTERFORMAT),\r\n            \"22\": OntologyConcept(\"22\", \"Plumbing\", OntologyType.MASTERFORMAT),\r\n            \"23\": OntologyConcept(\"23\", \"HVAC\", OntologyType.MASTERFORMAT),\r\n            \"26\": OntologyConcept(\"26\", \"Electrical\", OntologyType.MASTERFORMAT),\r\n        }\r\n\r\n        return ontologies\r\n\r\n    def _load_mapping_rules(self) -> List[SemanticMapping]:\r\n        \"\"\"Load predefined mapping rules between ontologies\"\"\"\r\n        rules = [\r\n            # IFC to COBie\r\n            SemanticMapping(\"IfcBuildingStorey\", OntologyType.IFC, \"Floor\",\r\n                OntologyType.COBIE, RelationType.EQUIVALENT, MappingConfidence.EXACT),\r\n            SemanticMapping(\"IfcSpace\", OntologyType.IFC, \"Space\",\r\n                OntologyType.COBIE, RelationType.EQUIVALENT, MappingConfidence.EXACT),\r\n\r\n            # IFC to Uniclass\r\n            SemanticMapping(\"IfcWall\", OntologyType.IFC, \"Ss_25\",\r\n                OntologyType.UNICLASS, RelationType.RELATED, MappingConfidence.HIGH),\r\n            SemanticMapping(\"IfcRoof\", OntologyType.IFC, \"Ss_30\",\r\n                OntologyType.UNICLASS, RelationType.RELATED, MappingConfidence.HIGH),\r\n            SemanticMapping(\"IfcSlab\", OntologyType.IFC, \"Ss_32\",\r\n                OntologyType.UNICLASS, RelationType.RELATED, MappingConfidence.HIGH),\r\n            SemanticMapping(\"IfcDoor\", OntologyType.IFC, \"Pr_35\",\r\n                OntologyType.UNICLASS, RelationType.RELATED, MappingConfidence.HIGH),\r\n            SemanticMapping(\"IfcWindow\", OntologyType.IFC, \"Pr_40\",\r\n                OntologyType.UNICLASS, RelationType.RELATED, MappingConfidence.HIGH),\r\n\r\n            # IFC to MasterFormat\r\n            SemanticMapping(\"IfcDoor\", OntologyType.IFC, \"08\",\r\n                OntologyType.MASTERFORMAT, RelationType.BROADER, MappingConfidence.MEDIUM),\r\n            SemanticMapping(\"IfcWindow\", OntologyType.IFC, \"08\",\r\n                OntologyType.MASTERFORMAT, RelationType.BROADER, MappingConfidence.MEDIUM),\r\n        ]\r\n        return rules\r\n\r\n    def _build_synonym_map(self) -> Dict[str, List[str]]:\r\n        \"\"\"Build synonym mappings for fuzzy matching\"\"\"\r\n        return {\r\n            \"wall\": [\"partition\", \"barrier\", \"divider\"],\r\n            \"door\": [\"entrance\", \"portal\", \"opening\"],\r\n            \"window\": [\"glazing\", \"fenestration\", \"opening\"],\r\n            \"floor\": [\"slab\", \"deck\", \"storey\", \"level\"],\r\n            \"roof\": [\"roofing\", \"covering\", \"canopy\"],\r\n            \"beam\": [\"girder\", \"joist\", \"lintel\"],\r\n            \"column\": [\"pillar\", \"post\", \"pier\"],\r\n            \"stair\": [\"stairway\", \"staircase\", \"steps\"],\r\n            \"space\": [\"room\", \"area\", \"zone\"],\r\n            \"concrete\": [\"cement\", \"reinforced\"],\r\n            \"steel\": [\"metal\", \"iron\"],\r\n        }\r\n\r\n    def map_field(\r\n        self,\r\n        field_name: str,\r\n        field_value: str,\r\n        source_ontology: Optional[OntologyType] = None,\r\n        target_ontology: OntologyType = OntologyType.IFC\r\n    ) -> MappingResult:\r\n        \"\"\"\r\n        Map a single field to target ontology.\r\n\r\n        Args:\r\n            field_name: Name of the field\r\n            field_value: Value to map\r\n            source_ontology: Source ontology if known\r\n            target_ontology: Target ontology to map to\r\n\r\n        Returns:\r\n            Mapping result with possible matches\r\n        \"\"\"\r\n        mappings = []\r\n\r\n        # Normalize the value\r\n        normalized = self._normalize_value(field_value)\r\n\r\n        # Check direct matches in existing rules\r\n        for rule in self.mapping_rules:\r\n            if rule.target_ontology == target_ontology:\r\n                if self._matches(normalized, rule.source_concept):\r\n                    mappings.append(rule)\r\n\r\n        # Check target ontology directly\r\n        target_concepts = self.ontologies.get(target_ontology, {})\r\n        for concept_id, concept in target_concepts.items():\r\n            similarity = self._calculate_similarity(normalized, concept)\r\n            if similarity > 0.5:\r\n                confidence = self._similarity_to_confidence(similarity)\r\n                mappings.append(SemanticMapping(\r\n                    source_concept=field_value,\r\n                    source_ontology=source_ontology or OntologyType.CUSTOM,\r\n                    target_concept=concept_id,\r\n                    target_ontology=target_ontology,\r\n                    relation=RelationType.EQUIVALENT if similarity > 0.9 else RelationType.RELATED,\r\n                    confidence=confidence\r\n                ))\r\n\r\n        # Sort by confidence\r\n        confidence_order = [\r\n            MappingConfidence.EXACT,\r\n            MappingConfidence.HIGH,\r\n            MappingConfidence.MEDIUM,\r\n            MappingConfidence.LOW,\r\n            MappingConfidence.UNCERTAIN\r\n        ]\r\n        mappings.sort(key=lambda m: confidence_order.index(m.confidence))\r\n\r\n        return MappingResult(\r\n            source_field=field_name,\r\n            source_value=field_value,\r\n            mappings=mappings,\r\n            best_match=mappings[0] if mappings else None,\r\n            unmapped=len(mappings) == 0\r\n        )\r\n\r\n    def _normalize_value(self, value: str) -> str:\r\n        \"\"\"Normalize a value for matching\"\"\"\r\n        # Remove common prefixes\r\n        prefixes = [\"ifc\", \"cobie\", \"type\", \"element\"]\r\n        normalized = value.lower().strip()\r\n\r\n        for prefix in prefixes:\r\n            if normalized.startswith(prefix):\r\n                normalized = normalized[len(prefix):]\r\n\r\n        return normalized.strip(\"_- \")\r\n\r\n    def _matches(self, value: str, concept: str) -> bool:\r\n        \"\"\"Check if value matches concept\"\"\"\r\n        normalized_value = self._normalize_value(value)\r\n        normalized_concept = self._normalize_value(concept)\r\n        return normalized_value == normalized_concept\r\n\r\n    def _calculate_similarity(\r\n        self,\r\n        value: str,\r\n        concept: OntologyConcept\r\n    ) -> float:\r\n        \"\"\"Calculate similarity between value and concept\"\"\"\r\n        value_lower = value.lower()\r\n        concept_name_lower = concept.name.lower()\r\n        concept_id_lower = concept.id.lower()\r\n\r\n        # Exact match\r\n        if value_lower == concept_name_lower or value_lower == concept_id_lower:\r\n            return 1.0\r\n\r\n        # Partial match in name\r\n        if value_lower in concept_name_lower or concept_name_lower in value_lower:\r\n            return 0.8\r\n\r\n        # Check synonyms\r\n        for key, synonyms in self.synonym_map.items():\r\n            if key in value_lower:\r\n                if key in concept_name_lower:\r\n                    return 0.9\r\n                for syn in synonyms:\r\n                    if syn in concept_name_lower:\r\n                        return 0.7\r\n\r\n        # Definition match\r\n        if concept.definition:\r\n            if value_lower in concept.definition.lower():\r\n                return 0.6\r\n\r\n        return 0.0\r\n\r\n    def _similarity_to_confidence(self, similarity: float) -> MappingConfidence:\r\n        \"\"\"Convert similarity score to confidence level\"\"\"\r\n        if similarity >= 0.95:\r\n            return MappingConfidence.EXACT\r\n        elif similarity >= 0.8:\r\n            return MappingConfidence.HIGH\r\n        elif similarity >= 0.6:\r\n            return MappingConfidence.MEDIUM\r\n        elif similarity >= 0.4:\r\n            return MappingConfidence.LOW\r\n        else:\r\n            return MappingConfidence.UNCERTAIN\r\n\r\n    def map_schema(\r\n        self,\r\n        schema: Dict[str, List[str]],\r\n        target_ontology: OntologyType = OntologyType.IFC\r\n    ) -> OntologyMappingReport:\r\n        \"\"\"\r\n        Map entire schema to target ontology.\r\n\r\n        Args:\r\n            schema: Dictionary of field names to sample values\r\n            target_ontology: Target ontology\r\n\r\n        Returns:\r\n            Complete mapping report\r\n        \"\"\"\r\n        all_mappings = []\r\n        confidence_dist = {c.value: 0 for c in MappingConfidence}\r\n\r\n        for field_name, sample_values in schema.items():\r\n            # Use first sample value\r\n            value = sample_values[0] if sample_values else field_name\r\n\r\n            result = self.map_field(field_name, value, target_ontology=target_ontology)\r\n            all_mappings.append(result)\r\n\r\n            if result.best_match:\r\n                confidence_dist[result.best_match.confidence.value] += 1\r\n\r\n        mapped = sum(1 for m in all_mappings if not m.unmapped)\r\n        unmapped = len(all_mappings) - mapped\r\n        coverage = mapped \u002F len(all_mappings) if all_mappings else 0\r\n\r\n        recommendations = self._generate_recommendations(all_mappings, coverage)\r\n\r\n        return OntologyMappingReport(\r\n            total_fields=len(all_mappings),\r\n            mapped_fields=mapped,\r\n            unmapped_fields=unmapped,\r\n            mappings=all_mappings,\r\n            coverage=coverage,\r\n            confidence_distribution=confidence_dist,\r\n            recommendations=recommendations\r\n        )\r\n\r\n    def _generate_recommendations(\r\n        self,\r\n        mappings: List[MappingResult],\r\n        coverage: float\r\n    ) -> List[str]:\r\n        \"\"\"Generate recommendations for improving mappings\"\"\"\r\n        recommendations = []\r\n\r\n        if coverage \u003C 0.7:\r\n            recommendations.append(\r\n                f\"Low mapping coverage ({coverage:.0%}). Consider adding custom mappings.\"\r\n            )\r\n\r\n        low_confidence = [m for m in mappings\r\n                         if m.best_match and m.best_match.confidence\r\n                         in [MappingConfidence.LOW, MappingConfidence.UNCERTAIN]]\r\n        if low_confidence:\r\n            recommendations.append(\r\n                f\"{len(low_confidence)} mappings have low confidence. Review manually.\"\r\n            )\r\n\r\n        unmapped = [m for m in mappings if m.unmapped]\r\n        if unmapped:\r\n            fields = [m.source_field for m in unmapped[:5]]\r\n            recommendations.append(\r\n                f\"Unmapped fields: {', '.join(fields)}. Add custom mappings.\"\r\n            )\r\n\r\n        return recommendations\r\n\r\n    def create_mapping(\r\n        self,\r\n        source: str,\r\n        source_ontology: OntologyType,\r\n        target: str,\r\n        target_ontology: OntologyType,\r\n        relation: RelationType = RelationType.EQUIVALENT,\r\n        notes: Optional[str] = None\r\n    ) -> SemanticMapping:\r\n        \"\"\"Create a new manual mapping\"\"\"\r\n        mapping = SemanticMapping(\r\n            source_concept=source,\r\n            source_ontology=source_ontology,\r\n            target_concept=target,\r\n            target_ontology=target_ontology,\r\n            relation=relation,\r\n            confidence=MappingConfidence.EXACT,\r\n            notes=notes,\r\n            created_by=\"manual\"\r\n        )\r\n        self.mapping_rules.append(mapping)\r\n        return mapping\r\n\r\n    def export_mappings(self, format: str = \"json\") -> str:\r\n        \"\"\"Export all mappings\"\"\"\r\n        if format == \"json\":\r\n            mappings_data = []\r\n            for rule in self.mapping_rules:\r\n                mappings_data.append({\r\n                    \"source\": rule.source_concept,\r\n                    \"source_ontology\": rule.source_ontology.value,\r\n                    \"target\": rule.target_concept,\r\n                    \"target_ontology\": rule.target_ontology.value,\r\n                    \"relation\": rule.relation.value,\r\n                    \"confidence\": rule.confidence.value\r\n                })\r\n            return json.dumps(mappings_data, indent=2)\r\n        else:\r\n            raise ValueError(f\"Unsupported format: {format}\")\r\n\r\n    def generate_report(self, report: OntologyMappingReport) -> str:\r\n        \"\"\"Generate mapping report\"\"\"\r\n        output = f\"\"\"\r\n# Ontology Mapping Report\r\n\r\n## Summary\r\n- **Total Fields:** {report.total_fields}\r\n- **Mapped Fields:** {report.mapped_fields}\r\n- **Unmapped Fields:** {report.unmapped_fields}\r\n- **Coverage:** {report.coverage:.0%}\r\n\r\n## Confidence Distribution\r\n\"\"\"\r\n        for conf, count in report.confidence_distribution.items():\r\n            if count > 0:\r\n                output += f\"- **{conf.title()}:** {count}\\n\"\r\n\r\n        output += \"\\n## Recommendations\\n\"\r\n        for rec in report.recommendations:\r\n            output += f\"- {rec}\\n\"\r\n\r\n        output += \"\\n## Mappings\\n\"\r\n        for mapping in report.mappings[:20]:\r\n            status = \"✓\" if not mapping.unmapped else \"✗\"\r\n            target = mapping.best_match.target_concept if mapping.best_match else \"unmapped\"\r\n            conf = mapping.best_match.confidence.value if mapping.best_match else \"-\"\r\n            output += f\"- {status} {mapping.source_field}: {mapping.source_value} → {target} ({conf})\\n\"\r\n\r\n        return output\r\n```\r\n\r\n## Common Use Cases\r\n\r\n### Map Field to IFC\r\n\r\n```python\r\nmapper = OntologyMapper()\r\n\r\n# Map a single field\r\nresult = mapper.map_field(\r\n    field_name=\"element_type\",\r\n    field_value=\"Wall\",\r\n    target_ontology=OntologyType.IFC\r\n)\r\n\r\nif result.best_match:\r\n    print(f\"Mapped to: {result.best_match.target_concept}\")\r\n    print(f\"Confidence: {result.best_match.confidence.value}\")\r\n```\r\n\r\n### Map Entire Schema\r\n\r\n```python\r\n# Define schema with sample values\r\nschema = {\r\n    \"element_type\": [\"Wall\", \"Door\", \"Window\"],\r\n    \"level\": [\"Level 1\", \"Level 2\"],\r\n    \"material\": [\"Concrete\", \"Steel\"],\r\n    \"room_type\": [\"Office\", \"Corridor\"]\r\n}\r\n\r\nreport = mapper.map_schema(schema, target_ontology=OntologyType.IFC)\r\n\r\nprint(f\"Coverage: {report.coverage:.0%}\")\r\nprint(f\"Mapped: {report.mapped_fields}\u002F{report.total_fields}\")\r\n```\r\n\r\n### Create Custom Mappings\r\n\r\n```python\r\n# Add custom mapping\r\nmapper.create_mapping(\r\n    source=\"CustomWallType\",\r\n    source_ontology=OntologyType.CUSTOM,\r\n    target=\"IfcWall\",\r\n    target_ontology=OntologyType.IFC,\r\n    relation=RelationType.EQUIVALENT,\r\n    notes=\"Custom wall type from legacy system\"\r\n)\r\n```\r\n\r\n## Quick Reference\r\n\r\n| Component | Purpose |\r\n|-----------|---------|\r\n| `OntologyMapper` | Main mapping engine |\r\n| `OntologyType` | Standard ontologies (IFC, COBie, etc.) |\r\n| `SemanticMapping` | Mapping between concepts |\r\n| `MappingResult` | Result of mapping operation |\r\n| `RelationType` | Relationship types |\r\n| `MappingConfidence` | Confidence levels |\r\n\r\n## Resources\r\n\r\n- **Book**: \"Data-Driven Construction\" by Artem Boiko, Chapter 2.2\r\n- **Website**: https:\u002F\u002Fdatadrivenconstruction.io\r\n\r\n## Next Steps\r\n\r\n- Use [open-data-integrator](..\u002Fopen-data-integrator\u002FSKILL.md) for open data\r\n- Use [data-model-designer](..\u002F..\u002FChapter-2.5\u002Fdata-model-designer\u002FSKILL.md) for schema design\r\n- Use [bim-validation-pipeline](..\u002F..\u002FChapter-4.3\u002Fbim-validation-pipeline\u002FSKILL.md) for validation\r\n",{"slug":5,"description":7,"display_name":29},"Ontology Mapper","main","e7e336ac628c3e3bd771aff1aaa469c93778f94a","skills\u002Fdatadrivenconstruction\u002Fontology-mapper",0,"https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del","2026-08-23 22:39:37",{"source":8,"skillName":5,"commands":38,"prompt":48,"zipAvailable":49},[39,42,45],{"tool":40,"command":41},"npx","npx skills add kbarbel640-del\u002Fskills --skill ontology-mapper",{"tool":43,"command":44},"bunx","bunx skills add kbarbel640-del\u002Fskills --skill ontology-mapper",{"tool":46,"command":47},"pnpm","pnpm dlx skills add kbarbel640-del\u002Fskills --skill ontology-mapper","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fontology-mapper\u002FSKILL.md",true,[51],{"path":52,"resourceType":53,"resourceTypeDesc":54,"sizeBytes":55,"sourceHtmlUrl":56},"_meta.json","REFERENCE","参考文档",298,"https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fontology-mapper\u002F_meta.json",[58,89,117,138,144,164],{"skillNo":59,"name":60,"nameZh":6,"description":61,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":62,"categories":63,"keywords":69,"publishedAt":24},"01M6G8J55967D6281ACMKAKTEQ","crowd-prompting","A marketplace where AI agents improve prompts, system instructions, tool descriptions, and other text-based content with domain expertise from real-world operations — and earn tokens for valuable contributions.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzzadrian\u002Fcrowd-prompting\u002FSKILL.md",[64],{"categoryNo":65,"categoryName":66,"taxonomyType":67,"taxonomyTypeDesc":68},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88],"crowd prompting","prompting","api","with","tokens","domain","world","prompts","operations","instructions","text","tool","system","improve","productivity","marketplace","https","content","ai agents",{"skillNo":90,"name":91,"nameZh":6,"description":92,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":93,"categories":94,"keywords":100,"publishedAt":24},"01M6G8J0PKPAYVET6BWE8W4C26","dilemm-ai","Compete in DilemmAI, the prisoner's dilemma AI arena at dilemm.ai. Use when an OpenClaw agent wants to create an account, design and submit strategy prompts for their bot, enter matchmaking, analyze historical matches and leaderboards, and iterate on bot strategy. Requires headless browser automation (no API available yet).","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzyori\u002Fdilemm-ai\u002FSKILL.md",[95],{"categoryNo":96,"categoryName":97,"taxonomyType":98,"taxonomyTypeDesc":99},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[101,72,102,103,104,105,20,106,107,108,109,110,111,112,113,114,115,77,116],"dilemm ai","arena","analyze","browser","openclaw agent","automation","browser automation","bot","openclaw","design","strategy","headless","compete","submit","matchmaking","use",{"skillNo":118,"name":119,"nameZh":6,"description":120,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":121,"categories":122,"keywords":126,"publishedAt":24},"01M6G8HWAF3K9SW7NP3Z83CPJ6","arxiv-paper-reviews","Interact with arXiv Crawler API to fetch papers, read reviews, and submit comments. Use when working with arXiv papers, fetching paper lists by date\u002Fcategory\u002Finterest, viewing paper details with comments, or submitting paper reviews via API at http:\u002F\u002F150.158.152.82:8000.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzxrys\u002Fweak-accept\u002FSKILL.md",[123],{"categoryNo":124,"categoryName":125,"taxonomyType":98,"taxonomyTypeDesc":99},"01JBSEEDCAT000000000000021","资料检索与研究",[127,128,129,130,131,132,133,73,134,114,116,135,72,136,137],"arxiv paper reviews","reviews","arxiv","paper","crawler","papers","comments","fetch","read","http","via",{"skillNo":139,"name":119,"nameZh":6,"description":120,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":143,"publishedAt":24},"01M6G8HQJ7N7WMY6YV7D7SSJ16","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzxrys\u002Farxiv-paper-reviews\u002FSKILL.md",[142],{"categoryNo":124,"categoryName":125,"taxonomyType":98,"taxonomyTypeDesc":99},[130,129,128,127,137,132,133,73,131,114,116,134,135,72,136],{"skillNo":145,"name":146,"nameZh":6,"description":147,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":148,"categories":149,"keywords":150,"publishedAt":24},"01M6G8HM95Y64JNVFC2HN4E2BG","git-summary","Get a quick summary of the current Git repository including status, recent commits, branches, and contributors.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzweack\u002Fgit-summary\u002FSKILL.md",[],[151,152,153,154,155,156,157,158,159,160,161,162,163],"git","summary","git summary","commits","repository","win32","status","linux","contributors","true","quick","get","branches",{"skillNo":165,"name":166,"nameZh":6,"description":167,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":168,"categories":169,"keywords":174,"publishedAt":24},"01M6G8HGEGF05CNEJCGVYFSC4R","agent-constitution","Interact with AgentConstitution governance contracts on Base Sepolia. Check compliance, read rules, log actions, query governance state.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fztsalexey\u002Fagent-constitution\u002FSKILL.md",[170,171],{"categoryNo":96,"categoryName":97,"taxonomyType":98,"taxonomyTypeDesc":99},{"categoryNo":172,"categoryName":173,"taxonomyType":67,"taxonomyTypeDesc":68},"01JBSEEDCAT000000000000037","律师与法务",[175,176,177,178,73,179,180,30,181,135,182,183,184,185,186,86,187,188,189],"agent constitution","constitution","contracts","tree","query","base","log","check","Rules","projects","compliance","actions","state","governance","github"]