[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FK1SBSVTKXTZ4AWRDPASQJ":3,"skill-same:01M6FK1SBSVTKXTZ4AWRDPASQJ":64},{"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":22,"publishedAt":31,"linkOnly":32,"markdownContent":33,"markdownBody":34,"frontMatter":35,"refName":37,"commitSha":38,"skillDirectory":39,"forksCount":40,"repositoryHtmlUrl":41,"repositoryHomepageUrl":6,"ownerHtmlUrl":42,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":43,"install":44,"resources":57},"01M6FK1SBSVTKXTZ4AWRDPASQJ","open-data-integrator",null,"Integrate open construction datasets. Combine open data sources for enhanced analysis","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\u002Fopen-data-integrator\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[23,24,25,26,27,28,29,30],"data","open","open data","open data integrator","analysis","integrate","datasets","sources","2026-11-10 10:12:30",false,"---\r\nslug: \"open-data-integrator\"\r\ndisplay_name: \"Open Data Integrator\"\r\ndescription: \"Integrate open construction datasets. Combine open data sources for enhanced analysis\"\r\n---\r\n\r\n# Open Data Integrator\r\n\r\n## Overview\r\n\r\nBased on DDC methodology (Chapter 2.2), this skill integrates open construction datasets from various sources like government databases, industry benchmarks, weather services, and geospatial data.\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, Any, Callable\r\nfrom datetime import datetime, date\r\nimport json\r\nimport requests\r\nfrom abc import ABC, abstractmethod\r\n\r\nclass DataSourceType(Enum):\r\n    \"\"\"Types of open data sources\"\"\"\r\n    GOVERNMENT = \"government\"           # Government statistics\r\n    INDUSTRY_BENCHMARK = \"benchmark\"    # Industry benchmarks\r\n    WEATHER = \"weather\"                 # Weather data\r\n    GEOSPATIAL = \"geospatial\"           # Geographic data\r\n    MATERIAL_PRICES = \"material_prices\" # Material cost indices\r\n    LABOR_RATES = \"labor_rates\"         # Labor cost data\r\n    BUILDING_PERMITS = \"permits\"        # Permit data\r\n    ENERGY = \"energy\"                   # Energy prices\u002Fdata\r\n    ECONOMIC = \"economic\"               # Economic indicators\r\n\r\nclass UpdateFrequency(Enum):\r\n    \"\"\"Data update frequency\"\"\"\r\n    REALTIME = \"realtime\"\r\n    HOURLY = \"hourly\"\r\n    DAILY = \"daily\"\r\n    WEEKLY = \"weekly\"\r\n    MONTHLY = \"monthly\"\r\n    QUARTERLY = \"quarterly\"\r\n    ANNUAL = \"annual\"\r\n\r\n@dataclass\r\nclass OpenDataSource:\r\n    \"\"\"Definition of an open data source\"\"\"\r\n    id: str\r\n    name: str\r\n    source_type: DataSourceType\r\n    url: str\r\n    api_key_required: bool = False\r\n    update_frequency: UpdateFrequency = UpdateFrequency.DAILY\r\n    format: str = \"json\"\r\n    license: str = \"open\"\r\n    description: Optional[str] = None\r\n    fields: List[str] = field(default_factory=list)\r\n\r\n@dataclass\r\nclass DataRecord:\r\n    \"\"\"A single data record from a source\"\"\"\r\n    source_id: str\r\n    timestamp: datetime\r\n    data: Dict[str, Any]\r\n    metadata: Dict[str, Any] = field(default_factory=dict)\r\n\r\n@dataclass\r\nclass IntegrationResult:\r\n    \"\"\"Result of data integration\"\"\"\r\n    source: str\r\n    records_fetched: int\r\n    records_processed: int\r\n    errors: List[str]\r\n    last_updated: datetime\r\n    sample_data: List[Dict]\r\n\r\n@dataclass\r\nclass EnrichedData:\r\n    \"\"\"Data enriched with open data\"\"\"\r\n    original_data: Dict[str, Any]\r\n    enrichments: Dict[str, Any]\r\n    sources_used: List[str]\r\n    confidence: float\r\n\r\n\r\nclass OpenDataConnector(ABC):\r\n    \"\"\"Base class for open data connectors\"\"\"\r\n\r\n    @abstractmethod\r\n    def fetch(self, params: Dict) -> List[DataRecord]:\r\n        pass\r\n\r\n    @abstractmethod\r\n    def get_metadata(self) -> Dict:\r\n        pass\r\n\r\n\r\nclass WeatherDataConnector(OpenDataConnector):\r\n    \"\"\"Connector for weather data (e.g., OpenWeatherMap)\"\"\"\r\n\r\n    def __init__(self, api_key: Optional[str] = None):\r\n        self.api_key = api_key\r\n        self.base_url = \"https:\u002F\u002Fapi.openweathermap.org\u002Fdata\u002F2.5\"\r\n\r\n    def fetch(\r\n        self,\r\n        params: Dict\r\n    ) -> List[DataRecord]:\r\n        \"\"\"Fetch weather data for location\"\"\"\r\n        lat = params.get(\"lat\")\r\n        lon = params.get(\"lon\")\r\n        start_date = params.get(\"start_date\")\r\n        end_date = params.get(\"end_date\")\r\n\r\n        # Simulate API call (in production, use actual API)\r\n        records = []\r\n\r\n        # Generate sample historical data\r\n        current = start_date\r\n        while current \u003C= end_date:\r\n            records.append(DataRecord(\r\n                source_id=\"openweathermap\",\r\n                timestamp=datetime.combine(current, datetime.min.time()),\r\n                data={\r\n                    \"date\": current.isoformat(),\r\n                    \"temp_max\": 25.0,\r\n                    \"temp_min\": 15.0,\r\n                    \"precipitation\": 0.0,\r\n                    \"wind_speed\": 10.0,\r\n                    \"weather_code\": \"clear\"\r\n                },\r\n                metadata={\"lat\": lat, \"lon\": lon}\r\n            ))\r\n            current = date(current.year, current.month, current.day + 1) if current.day \u003C 28 else date(current.year, current.month + 1 if current.month \u003C 12 else 1, 1)\r\n\r\n        return records[:30]  # Limit for demo\r\n\r\n    def get_metadata(self) -> Dict:\r\n        return {\r\n            \"source\": \"OpenWeatherMap\",\r\n            \"type\": DataSourceType.WEATHER.value,\r\n            \"frequency\": UpdateFrequency.HOURLY.value,\r\n            \"fields\": [\"temp_max\", \"temp_min\", \"precipitation\", \"wind_speed\"]\r\n        }\r\n\r\n\r\nclass MaterialPriceConnector(OpenDataConnector):\r\n    \"\"\"Connector for material price indices\"\"\"\r\n\r\n    def __init__(self, region: str = \"US\"):\r\n        self.region = region\r\n        self.price_indices = self._load_indices()\r\n\r\n    def _load_indices(self) -> Dict[str, Dict]:\r\n        \"\"\"Load material price indices\"\"\"\r\n        return {\r\n            \"concrete\": {\"base\": 100, \"current\": 125, \"trend\": \"up\"},\r\n            \"steel\": {\"base\": 100, \"current\": 145, \"trend\": \"up\"},\r\n            \"lumber\": {\"base\": 100, \"current\": 180, \"trend\": \"stable\"},\r\n            \"copper\": {\"base\": 100, \"current\": 135, \"trend\": \"up\"},\r\n            \"asphalt\": {\"base\": 100, \"current\": 115, \"trend\": \"stable\"},\r\n            \"gypsum\": {\"base\": 100, \"current\": 110, \"trend\": \"stable\"},\r\n            \"glass\": {\"base\": 100, \"current\": 105, \"trend\": \"down\"},\r\n            \"cement\": {\"base\": 100, \"current\": 120, \"trend\": \"up\"},\r\n        }\r\n\r\n    def fetch(self, params: Dict) -> List[DataRecord]:\r\n        \"\"\"Fetch material price data\"\"\"\r\n        materials = params.get(\"materials\", list(self.price_indices.keys()))\r\n\r\n        records = []\r\n        for material in materials:\r\n            if material in self.price_indices:\r\n                records.append(DataRecord(\r\n                    source_id=\"material_prices\",\r\n                    timestamp=datetime.now(),\r\n                    data={\r\n                        \"material\": material,\r\n                        \"region\": self.region,\r\n                        **self.price_indices[material]\r\n                    }\r\n                ))\r\n        return records\r\n\r\n    def get_metadata(self) -> Dict:\r\n        return {\r\n            \"source\": \"Material Price Index\",\r\n            \"type\": DataSourceType.MATERIAL_PRICES.value,\r\n            \"frequency\": UpdateFrequency.MONTHLY.value,\r\n            \"materials\": list(self.price_indices.keys())\r\n        }\r\n\r\n\r\nclass LaborRateConnector(OpenDataConnector):\r\n    \"\"\"Connector for labor rate data\"\"\"\r\n\r\n    def __init__(self, region: str = \"US\"):\r\n        self.region = region\r\n        self.labor_rates = self._load_rates()\r\n\r\n    def _load_rates(self) -> Dict[str, Dict]:\r\n        \"\"\"Load labor rates by trade\"\"\"\r\n        return {\r\n            \"carpenter\": {\"hourly\": 45.00, \"burden_rate\": 1.35},\r\n            \"electrician\": {\"hourly\": 55.00, \"burden_rate\": 1.40},\r\n            \"plumber\": {\"hourly\": 52.00, \"burden_rate\": 1.38},\r\n            \"ironworker\": {\"hourly\": 58.00, \"burden_rate\": 1.42},\r\n            \"laborer\": {\"hourly\": 32.00, \"burden_rate\": 1.30},\r\n            \"operator\": {\"hourly\": 48.00, \"burden_rate\": 1.35},\r\n            \"mason\": {\"hourly\": 50.00, \"burden_rate\": 1.36},\r\n            \"painter\": {\"hourly\": 38.00, \"burden_rate\": 1.32},\r\n            \"hvac_tech\": {\"hourly\": 54.00, \"burden_rate\": 1.38},\r\n            \"welder\": {\"hourly\": 52.00, \"burden_rate\": 1.40},\r\n        }\r\n\r\n    def fetch(self, params: Dict) -> List[DataRecord]:\r\n        \"\"\"Fetch labor rate data\"\"\"\r\n        trades = params.get(\"trades\", list(self.labor_rates.keys()))\r\n\r\n        records = []\r\n        for trade in trades:\r\n            if trade in self.labor_rates:\r\n                rate_data = self.labor_rates[trade]\r\n                records.append(DataRecord(\r\n                    source_id=\"labor_rates\",\r\n                    timestamp=datetime.now(),\r\n                    data={\r\n                        \"trade\": trade,\r\n                        \"region\": self.region,\r\n                        \"hourly_rate\": rate_data[\"hourly\"],\r\n                        \"burden_rate\": rate_data[\"burden_rate\"],\r\n                        \"fully_loaded\": rate_data[\"hourly\"] * rate_data[\"burden_rate\"]\r\n                    }\r\n                ))\r\n        return records\r\n\r\n    def get_metadata(self) -> Dict:\r\n        return {\r\n            \"source\": \"Labor Rate Database\",\r\n            \"type\": DataSourceType.LABOR_RATES.value,\r\n            \"frequency\": UpdateFrequency.QUARTERLY.value,\r\n            \"trades\": list(self.labor_rates.keys())\r\n        }\r\n\r\n\r\nclass BuildingPermitConnector(OpenDataConnector):\r\n    \"\"\"Connector for building permit data\"\"\"\r\n\r\n    def __init__(self, jurisdiction: str = \"default\"):\r\n        self.jurisdiction = jurisdiction\r\n\r\n    def fetch(self, params: Dict) -> List[DataRecord]:\r\n        \"\"\"Fetch permit data\"\"\"\r\n        # Simulate permit data\r\n        permit_types = [\"new_construction\", \"renovation\", \"addition\", \"demolition\"]\r\n\r\n        records = []\r\n        for ptype in permit_types:\r\n            records.append(DataRecord(\r\n                source_id=\"building_permits\",\r\n                timestamp=datetime.now(),\r\n                data={\r\n                    \"permit_type\": ptype,\r\n                    \"jurisdiction\": self.jurisdiction,\r\n                    \"count_ytd\": 150,\r\n                    \"total_value\": 25000000,\r\n                    \"avg_processing_days\": 21\r\n                }\r\n            ))\r\n        return records\r\n\r\n    def get_metadata(self) -> Dict:\r\n        return {\r\n            \"source\": \"Building Permit Database\",\r\n            \"type\": DataSourceType.BUILDING_PERMITS.value,\r\n            \"frequency\": UpdateFrequency.DAILY.value\r\n        }\r\n\r\n\r\nclass OpenDataIntegrator:\r\n    \"\"\"\r\n    Integrate open construction datasets.\r\n    Based on DDC methodology Chapter 2.2.\r\n    \"\"\"\r\n\r\n    def __init__(self, region: str = \"US\"):\r\n        self.region = region\r\n        self.connectors: Dict[str, OpenDataConnector] = {}\r\n        self.cache: Dict[str, List[DataRecord]] = {}\r\n        self.cache_expiry: Dict[str, datetime] = {}\r\n        self._register_default_connectors()\r\n\r\n    def _register_default_connectors(self):\r\n        \"\"\"Register default data connectors\"\"\"\r\n        self.register_connector(\"weather\", WeatherDataConnector())\r\n        self.register_connector(\"material_prices\", MaterialPriceConnector(self.region))\r\n        self.register_connector(\"labor_rates\", LaborRateConnector(self.region))\r\n        self.register_connector(\"permits\", BuildingPermitConnector())\r\n\r\n    def register_connector(\r\n        self,\r\n        name: str,\r\n        connector: OpenDataConnector\r\n    ):\r\n        \"\"\"Register a data connector\"\"\"\r\n        self.connectors[name] = connector\r\n\r\n    def fetch_data(\r\n        self,\r\n        source: str,\r\n        params: Optional[Dict] = None,\r\n        use_cache: bool = True\r\n    ) -> IntegrationResult:\r\n        \"\"\"\r\n        Fetch data from a source.\r\n\r\n        Args:\r\n            source: Name of the data source\r\n            params: Query parameters\r\n            use_cache: Whether to use cached data\r\n\r\n        Returns:\r\n            Integration result with fetched data\r\n        \"\"\"\r\n        if source not in self.connectors:\r\n            return IntegrationResult(\r\n                source=source,\r\n                records_fetched=0,\r\n                records_processed=0,\r\n                errors=[f\"Unknown source: {source}\"],\r\n                last_updated=datetime.now(),\r\n                sample_data=[]\r\n            )\r\n\r\n        # Check cache\r\n        cache_key = f\"{source}_{json.dumps(params or {}, sort_keys=True)}\"\r\n        if use_cache and cache_key in self.cache:\r\n            expiry = self.cache_expiry.get(cache_key)\r\n            if expiry and expiry > datetime.now():\r\n                cached = self.cache[cache_key]\r\n                return IntegrationResult(\r\n                    source=source,\r\n                    records_fetched=len(cached),\r\n                    records_processed=len(cached),\r\n                    errors=[],\r\n                    last_updated=expiry,\r\n                    sample_data=[r.data for r in cached[:5]]\r\n                )\r\n\r\n        # Fetch fresh data\r\n        connector = self.connectors[source]\r\n        errors = []\r\n\r\n        try:\r\n            records = connector.fetch(params or {})\r\n\r\n            # Cache the results\r\n            self.cache[cache_key] = records\r\n            self.cache_expiry[cache_key] = datetime.now()\r\n\r\n            return IntegrationResult(\r\n                source=source,\r\n                records_fetched=len(records),\r\n                records_processed=len(records),\r\n                errors=errors,\r\n                last_updated=datetime.now(),\r\n                sample_data=[r.data for r in records[:5]]\r\n            )\r\n\r\n        except Exception as e:\r\n            errors.append(str(e))\r\n            return IntegrationResult(\r\n                source=source,\r\n                records_fetched=0,\r\n                records_processed=0,\r\n                errors=errors,\r\n                last_updated=datetime.now(),\r\n                sample_data=[]\r\n            )\r\n\r\n    def enrich_project_data(\r\n        self,\r\n        project_data: Dict[str, Any],\r\n        enrichment_sources: Optional[List[str]] = None\r\n    ) -> EnrichedData:\r\n        \"\"\"\r\n        Enrich project data with open data.\r\n\r\n        Args:\r\n            project_data: Original project data\r\n            enrichment_sources: Sources to use for enrichment\r\n\r\n        Returns:\r\n            Enriched data\r\n        \"\"\"\r\n        sources = enrichment_sources or [\"material_prices\", \"labor_rates\", \"weather\"]\r\n        enrichments = {}\r\n        sources_used = []\r\n\r\n        # Material price enrichment\r\n        if \"material_prices\" in sources and \"materials\" in project_data:\r\n            materials = project_data[\"materials\"]\r\n            result = self.fetch_data(\"material_prices\", {\"materials\": materials})\r\n            if result.records_fetched > 0:\r\n                enrichments[\"material_price_indices\"] = result.sample_data\r\n                sources_used.append(\"material_prices\")\r\n\r\n        # Labor rate enrichment\r\n        if \"labor_rates\" in sources and \"trades\" in project_data:\r\n            trades = project_data[\"trades\"]\r\n            result = self.fetch_data(\"labor_rates\", {\"trades\": trades})\r\n            if result.records_fetched > 0:\r\n                enrichments[\"labor_rates\"] = result.sample_data\r\n                sources_used.append(\"labor_rates\")\r\n\r\n        # Weather enrichment\r\n        if \"weather\" in sources and \"location\" in project_data:\r\n            loc = project_data[\"location\"]\r\n            params = {\r\n                \"lat\": loc.get(\"lat\"),\r\n                \"lon\": loc.get(\"lon\"),\r\n                \"start_date\": project_data.get(\"start_date\", date.today()),\r\n                \"end_date\": project_data.get(\"end_date\", date.today())\r\n            }\r\n            result = self.fetch_data(\"weather\", params)\r\n            if result.records_fetched > 0:\r\n                enrichments[\"weather_forecast\"] = result.sample_data\r\n                sources_used.append(\"weather\")\r\n\r\n        # Calculate confidence based on enrichment success\r\n        confidence = len(sources_used) \u002F len(sources) if sources else 0\r\n\r\n        return EnrichedData(\r\n            original_data=project_data,\r\n            enrichments=enrichments,\r\n            sources_used=sources_used,\r\n            confidence=confidence\r\n        )\r\n\r\n    def get_cost_indices(\r\n        self,\r\n        materials: Optional[List[str]] = None,\r\n        trades: Optional[List[str]] = None\r\n    ) -> Dict:\r\n        \"\"\"Get current cost indices\"\"\"\r\n        indices = {\r\n            \"timestamp\": datetime.now().isoformat(),\r\n            \"region\": self.region\r\n        }\r\n\r\n        if materials:\r\n            result = self.fetch_data(\"material_prices\", {\"materials\": materials})\r\n            indices[\"materials\"] = result.sample_data\r\n\r\n        if trades:\r\n            result = self.fetch_data(\"labor_rates\", {\"trades\": trades})\r\n            indices[\"labor\"] = result.sample_data\r\n\r\n        return indices\r\n\r\n    def get_weather_risk(\r\n        self,\r\n        lat: float,\r\n        lon: float,\r\n        start_date: date,\r\n        end_date: date\r\n    ) -> Dict:\r\n        \"\"\"Assess weather risk for project period\"\"\"\r\n        result = self.fetch_data(\"weather\", {\r\n            \"lat\": lat,\r\n            \"lon\": lon,\r\n            \"start_date\": start_date,\r\n            \"end_date\": end_date\r\n        })\r\n\r\n        if result.records_fetched == 0:\r\n            return {\"error\": \"No weather data available\"}\r\n\r\n        # Calculate risk metrics\r\n        rain_days = sum(1 for d in result.sample_data\r\n                       if d.get(\"precipitation\", 0) > 5)\r\n        extreme_temp_days = sum(1 for d in result.sample_data\r\n                               if d.get(\"temp_max\", 0) > 35 or d.get(\"temp_min\", 0) \u003C 0)\r\n\r\n        total_days = len(result.sample_data)\r\n        risk_score = (rain_days + extreme_temp_days) \u002F total_days if total_days > 0 else 0\r\n\r\n        return {\r\n            \"total_days\": total_days,\r\n            \"rain_days\": rain_days,\r\n            \"extreme_temperature_days\": extreme_temp_days,\r\n            \"risk_score\": risk_score,\r\n            \"risk_level\": \"high\" if risk_score > 0.3 else \"medium\" if risk_score > 0.1 else \"low\"\r\n        }\r\n\r\n    def list_sources(self) -> List[Dict]:\r\n        \"\"\"List all available data sources\"\"\"\r\n        sources = []\r\n        for name, connector in self.connectors.items():\r\n            meta = connector.get_metadata()\r\n            sources.append({\r\n                \"name\": name,\r\n                **meta\r\n            })\r\n        return sources\r\n\r\n    def generate_report(self) -> str:\r\n        \"\"\"Generate data availability report\"\"\"\r\n        output = \"\"\"\r\n# Open Data Integration Report\r\n\r\n## Available Sources\r\n\"\"\"\r\n        for source in self.list_sources():\r\n            output += f\"\"\"\r\n### {source['name'].title()}\r\n- **Type:** {source['type']}\r\n- **Update Frequency:** {source['frequency']}\r\n\"\"\"\r\n\r\n        output += \"\"\"\r\n## Cache Status\r\n\"\"\"\r\n        for key, expiry in self.cache_expiry.items():\r\n            status = \"valid\" if expiry > datetime.now() else \"expired\"\r\n            output += f\"- {key}: {status}\\n\"\r\n\r\n        return output\r\n```\r\n\r\n## Common Use Cases\r\n\r\n### Fetch Material Prices\r\n\r\n```python\r\nintegrator = OpenDataIntegrator(region=\"US\")\r\n\r\n# Get material price indices\r\nresult = integrator.fetch_data(\"material_prices\", {\r\n    \"materials\": [\"concrete\", \"steel\", \"lumber\"]\r\n})\r\n\r\nprint(f\"Fetched: {result.records_fetched} records\")\r\nfor record in result.sample_data:\r\n    print(f\"  {record['material']}: index={record['current']}, trend={record['trend']}\")\r\n```\r\n\r\n### Enrich Project Data\r\n\r\n```python\r\nproject = {\r\n    \"name\": \"Office Building\",\r\n    \"materials\": [\"concrete\", \"steel\", \"glass\"],\r\n    \"trades\": [\"carpenter\", \"electrician\", \"plumber\"],\r\n    \"location\": {\"lat\": 40.7128, \"lon\": -74.0060},\r\n    \"start_date\": date(2024, 6, 1),\r\n    \"end_date\": date(2024, 12, 31)\r\n}\r\n\r\nenriched = integrator.enrich_project_data(project)\r\n\r\nprint(f\"Sources used: {enriched.sources_used}\")\r\nprint(f\"Confidence: {enriched.confidence:.0%}\")\r\nprint(f\"Material indices: {enriched.enrichments.get('material_price_indices')}\")\r\n```\r\n\r\n### Assess Weather Risk\r\n\r\n```python\r\nrisk = integrator.get_weather_risk(\r\n    lat=40.7128,\r\n    lon=-74.0060,\r\n    start_date=date(2024, 6, 1),\r\n    end_date=date(2024, 8, 31)\r\n)\r\n\r\nprint(f\"Risk Level: {risk['risk_level']}\")\r\nprint(f\"Rain Days: {risk['rain_days']}\")\r\n```\r\n\r\n## Quick Reference\r\n\r\n| Component | Purpose |\r\n|-----------|---------|\r\n| `OpenDataIntegrator` | Main integration engine |\r\n| `OpenDataConnector` | Base connector class |\r\n| `WeatherDataConnector` | Weather API connector |\r\n| `MaterialPriceConnector` | Material price indices |\r\n| `LaborRateConnector` | Labor rate data |\r\n| `EnrichedData` | Enriched data result |\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 [ontology-mapper](..\u002Fontology-mapper\u002FSKILL.md) for semantic mapping\r\n- Use [cost-prediction](..\u002F..\u002FChapter-4.5\u002Fcost-prediction\u002FSKILL.md) with indices\r\n- Use [weather-impact-analysis](..\u002F..\u002F..\u002FDDC_Innovative\u002Fweather-impact-analysis\u002FSKILL.md) for scheduling\r\n","# Open Data Integrator\r\n\r\n## Overview\r\n\r\nBased on DDC methodology (Chapter 2.2), this skill integrates open construction datasets from various sources like government databases, industry benchmarks, weather services, and geospatial data.\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, Any, Callable\r\nfrom datetime import datetime, date\r\nimport json\r\nimport requests\r\nfrom abc import ABC, abstractmethod\r\n\r\nclass DataSourceType(Enum):\r\n    \"\"\"Types of open data sources\"\"\"\r\n    GOVERNMENT = \"government\"           # Government statistics\r\n    INDUSTRY_BENCHMARK = \"benchmark\"    # Industry benchmarks\r\n    WEATHER = \"weather\"                 # Weather data\r\n    GEOSPATIAL = \"geospatial\"           # Geographic data\r\n    MATERIAL_PRICES = \"material_prices\" # Material cost indices\r\n    LABOR_RATES = \"labor_rates\"         # Labor cost data\r\n    BUILDING_PERMITS = \"permits\"        # Permit data\r\n    ENERGY = \"energy\"                   # Energy prices\u002Fdata\r\n    ECONOMIC = \"economic\"               # Economic indicators\r\n\r\nclass UpdateFrequency(Enum):\r\n    \"\"\"Data update frequency\"\"\"\r\n    REALTIME = \"realtime\"\r\n    HOURLY = \"hourly\"\r\n    DAILY = \"daily\"\r\n    WEEKLY = \"weekly\"\r\n    MONTHLY = \"monthly\"\r\n    QUARTERLY = \"quarterly\"\r\n    ANNUAL = \"annual\"\r\n\r\n@dataclass\r\nclass OpenDataSource:\r\n    \"\"\"Definition of an open data source\"\"\"\r\n    id: str\r\n    name: str\r\n    source_type: DataSourceType\r\n    url: str\r\n    api_key_required: bool = False\r\n    update_frequency: UpdateFrequency = UpdateFrequency.DAILY\r\n    format: str = \"json\"\r\n    license: str = \"open\"\r\n    description: Optional[str] = None\r\n    fields: List[str] = field(default_factory=list)\r\n\r\n@dataclass\r\nclass DataRecord:\r\n    \"\"\"A single data record from a source\"\"\"\r\n    source_id: str\r\n    timestamp: datetime\r\n    data: Dict[str, Any]\r\n    metadata: Dict[str, Any] = field(default_factory=dict)\r\n\r\n@dataclass\r\nclass IntegrationResult:\r\n    \"\"\"Result of data integration\"\"\"\r\n    source: str\r\n    records_fetched: int\r\n    records_processed: int\r\n    errors: List[str]\r\n    last_updated: datetime\r\n    sample_data: List[Dict]\r\n\r\n@dataclass\r\nclass EnrichedData:\r\n    \"\"\"Data enriched with open data\"\"\"\r\n    original_data: Dict[str, Any]\r\n    enrichments: Dict[str, Any]\r\n    sources_used: List[str]\r\n    confidence: float\r\n\r\n\r\nclass OpenDataConnector(ABC):\r\n    \"\"\"Base class for open data connectors\"\"\"\r\n\r\n    @abstractmethod\r\n    def fetch(self, params: Dict) -> List[DataRecord]:\r\n        pass\r\n\r\n    @abstractmethod\r\n    def get_metadata(self) -> Dict:\r\n        pass\r\n\r\n\r\nclass WeatherDataConnector(OpenDataConnector):\r\n    \"\"\"Connector for weather data (e.g., OpenWeatherMap)\"\"\"\r\n\r\n    def __init__(self, api_key: Optional[str] = None):\r\n        self.api_key = api_key\r\n        self.base_url = \"https:\u002F\u002Fapi.openweathermap.org\u002Fdata\u002F2.5\"\r\n\r\n    def fetch(\r\n        self,\r\n        params: Dict\r\n    ) -> List[DataRecord]:\r\n        \"\"\"Fetch weather data for location\"\"\"\r\n        lat = params.get(\"lat\")\r\n        lon = params.get(\"lon\")\r\n        start_date = params.get(\"start_date\")\r\n        end_date = params.get(\"end_date\")\r\n\r\n        # Simulate API call (in production, use actual API)\r\n        records = []\r\n\r\n        # Generate sample historical data\r\n        current = start_date\r\n        while current \u003C= end_date:\r\n            records.append(DataRecord(\r\n                source_id=\"openweathermap\",\r\n                timestamp=datetime.combine(current, datetime.min.time()),\r\n                data={\r\n                    \"date\": current.isoformat(),\r\n                    \"temp_max\": 25.0,\r\n                    \"temp_min\": 15.0,\r\n                    \"precipitation\": 0.0,\r\n                    \"wind_speed\": 10.0,\r\n                    \"weather_code\": \"clear\"\r\n                },\r\n                metadata={\"lat\": lat, \"lon\": lon}\r\n            ))\r\n            current = date(current.year, current.month, current.day + 1) if current.day \u003C 28 else date(current.year, current.month + 1 if current.month \u003C 12 else 1, 1)\r\n\r\n        return records[:30]  # Limit for demo\r\n\r\n    def get_metadata(self) -> Dict:\r\n        return {\r\n            \"source\": \"OpenWeatherMap\",\r\n            \"type\": DataSourceType.WEATHER.value,\r\n            \"frequency\": UpdateFrequency.HOURLY.value,\r\n            \"fields\": [\"temp_max\", \"temp_min\", \"precipitation\", \"wind_speed\"]\r\n        }\r\n\r\n\r\nclass MaterialPriceConnector(OpenDataConnector):\r\n    \"\"\"Connector for material price indices\"\"\"\r\n\r\n    def __init__(self, region: str = \"US\"):\r\n        self.region = region\r\n        self.price_indices = self._load_indices()\r\n\r\n    def _load_indices(self) -> Dict[str, Dict]:\r\n        \"\"\"Load material price indices\"\"\"\r\n        return {\r\n            \"concrete\": {\"base\": 100, \"current\": 125, \"trend\": \"up\"},\r\n            \"steel\": {\"base\": 100, \"current\": 145, \"trend\": \"up\"},\r\n            \"lumber\": {\"base\": 100, \"current\": 180, \"trend\": \"stable\"},\r\n            \"copper\": {\"base\": 100, \"current\": 135, \"trend\": \"up\"},\r\n            \"asphalt\": {\"base\": 100, \"current\": 115, \"trend\": \"stable\"},\r\n            \"gypsum\": {\"base\": 100, \"current\": 110, \"trend\": \"stable\"},\r\n            \"glass\": {\"base\": 100, \"current\": 105, \"trend\": \"down\"},\r\n            \"cement\": {\"base\": 100, \"current\": 120, \"trend\": \"up\"},\r\n        }\r\n\r\n    def fetch(self, params: Dict) -> List[DataRecord]:\r\n        \"\"\"Fetch material price data\"\"\"\r\n        materials = params.get(\"materials\", list(self.price_indices.keys()))\r\n\r\n        records = []\r\n        for material in materials:\r\n            if material in self.price_indices:\r\n                records.append(DataRecord(\r\n                    source_id=\"material_prices\",\r\n                    timestamp=datetime.now(),\r\n                    data={\r\n                        \"material\": material,\r\n                        \"region\": self.region,\r\n                        **self.price_indices[material]\r\n                    }\r\n                ))\r\n        return records\r\n\r\n    def get_metadata(self) -> Dict:\r\n        return {\r\n            \"source\": \"Material Price Index\",\r\n            \"type\": DataSourceType.MATERIAL_PRICES.value,\r\n            \"frequency\": UpdateFrequency.MONTHLY.value,\r\n            \"materials\": list(self.price_indices.keys())\r\n        }\r\n\r\n\r\nclass LaborRateConnector(OpenDataConnector):\r\n    \"\"\"Connector for labor rate data\"\"\"\r\n\r\n    def __init__(self, region: str = \"US\"):\r\n        self.region = region\r\n        self.labor_rates = self._load_rates()\r\n\r\n    def _load_rates(self) -> Dict[str, Dict]:\r\n        \"\"\"Load labor rates by trade\"\"\"\r\n        return {\r\n            \"carpenter\": {\"hourly\": 45.00, \"burden_rate\": 1.35},\r\n            \"electrician\": {\"hourly\": 55.00, \"burden_rate\": 1.40},\r\n            \"plumber\": {\"hourly\": 52.00, \"burden_rate\": 1.38},\r\n            \"ironworker\": {\"hourly\": 58.00, \"burden_rate\": 1.42},\r\n            \"laborer\": {\"hourly\": 32.00, \"burden_rate\": 1.30},\r\n            \"operator\": {\"hourly\": 48.00, \"burden_rate\": 1.35},\r\n            \"mason\": {\"hourly\": 50.00, \"burden_rate\": 1.36},\r\n            \"painter\": {\"hourly\": 38.00, \"burden_rate\": 1.32},\r\n            \"hvac_tech\": {\"hourly\": 54.00, \"burden_rate\": 1.38},\r\n            \"welder\": {\"hourly\": 52.00, \"burden_rate\": 1.40},\r\n        }\r\n\r\n    def fetch(self, params: Dict) -> List[DataRecord]:\r\n        \"\"\"Fetch labor rate data\"\"\"\r\n        trades = params.get(\"trades\", list(self.labor_rates.keys()))\r\n\r\n        records = []\r\n        for trade in trades:\r\n            if trade in self.labor_rates:\r\n                rate_data = self.labor_rates[trade]\r\n                records.append(DataRecord(\r\n                    source_id=\"labor_rates\",\r\n                    timestamp=datetime.now(),\r\n                    data={\r\n                        \"trade\": trade,\r\n                        \"region\": self.region,\r\n                        \"hourly_rate\": rate_data[\"hourly\"],\r\n                        \"burden_rate\": rate_data[\"burden_rate\"],\r\n                        \"fully_loaded\": rate_data[\"hourly\"] * rate_data[\"burden_rate\"]\r\n                    }\r\n                ))\r\n        return records\r\n\r\n    def get_metadata(self) -> Dict:\r\n        return {\r\n            \"source\": \"Labor Rate Database\",\r\n            \"type\": DataSourceType.LABOR_RATES.value,\r\n            \"frequency\": UpdateFrequency.QUARTERLY.value,\r\n            \"trades\": list(self.labor_rates.keys())\r\n        }\r\n\r\n\r\nclass BuildingPermitConnector(OpenDataConnector):\r\n    \"\"\"Connector for building permit data\"\"\"\r\n\r\n    def __init__(self, jurisdiction: str = \"default\"):\r\n        self.jurisdiction = jurisdiction\r\n\r\n    def fetch(self, params: Dict) -> List[DataRecord]:\r\n        \"\"\"Fetch permit data\"\"\"\r\n        # Simulate permit data\r\n        permit_types = [\"new_construction\", \"renovation\", \"addition\", \"demolition\"]\r\n\r\n        records = []\r\n        for ptype in permit_types:\r\n            records.append(DataRecord(\r\n                source_id=\"building_permits\",\r\n                timestamp=datetime.now(),\r\n                data={\r\n                    \"permit_type\": ptype,\r\n                    \"jurisdiction\": self.jurisdiction,\r\n                    \"count_ytd\": 150,\r\n                    \"total_value\": 25000000,\r\n                    \"avg_processing_days\": 21\r\n                }\r\n            ))\r\n        return records\r\n\r\n    def get_metadata(self) -> Dict:\r\n        return {\r\n            \"source\": \"Building Permit Database\",\r\n            \"type\": DataSourceType.BUILDING_PERMITS.value,\r\n            \"frequency\": UpdateFrequency.DAILY.value\r\n        }\r\n\r\n\r\nclass OpenDataIntegrator:\r\n    \"\"\"\r\n    Integrate open construction datasets.\r\n    Based on DDC methodology Chapter 2.2.\r\n    \"\"\"\r\n\r\n    def __init__(self, region: str = \"US\"):\r\n        self.region = region\r\n        self.connectors: Dict[str, OpenDataConnector] = {}\r\n        self.cache: Dict[str, List[DataRecord]] = {}\r\n        self.cache_expiry: Dict[str, datetime] = {}\r\n        self._register_default_connectors()\r\n\r\n    def _register_default_connectors(self):\r\n        \"\"\"Register default data connectors\"\"\"\r\n        self.register_connector(\"weather\", WeatherDataConnector())\r\n        self.register_connector(\"material_prices\", MaterialPriceConnector(self.region))\r\n        self.register_connector(\"labor_rates\", LaborRateConnector(self.region))\r\n        self.register_connector(\"permits\", BuildingPermitConnector())\r\n\r\n    def register_connector(\r\n        self,\r\n        name: str,\r\n        connector: OpenDataConnector\r\n    ):\r\n        \"\"\"Register a data connector\"\"\"\r\n        self.connectors[name] = connector\r\n\r\n    def fetch_data(\r\n        self,\r\n        source: str,\r\n        params: Optional[Dict] = None,\r\n        use_cache: bool = True\r\n    ) -> IntegrationResult:\r\n        \"\"\"\r\n        Fetch data from a source.\r\n\r\n        Args:\r\n            source: Name of the data source\r\n            params: Query parameters\r\n            use_cache: Whether to use cached data\r\n\r\n        Returns:\r\n            Integration result with fetched data\r\n        \"\"\"\r\n        if source not in self.connectors:\r\n            return IntegrationResult(\r\n                source=source,\r\n                records_fetched=0,\r\n                records_processed=0,\r\n                errors=[f\"Unknown source: {source}\"],\r\n                last_updated=datetime.now(),\r\n                sample_data=[]\r\n            )\r\n\r\n        # Check cache\r\n        cache_key = f\"{source}_{json.dumps(params or {}, sort_keys=True)}\"\r\n        if use_cache and cache_key in self.cache:\r\n            expiry = self.cache_expiry.get(cache_key)\r\n            if expiry and expiry > datetime.now():\r\n                cached = self.cache[cache_key]\r\n                return IntegrationResult(\r\n                    source=source,\r\n                    records_fetched=len(cached),\r\n                    records_processed=len(cached),\r\n                    errors=[],\r\n                    last_updated=expiry,\r\n                    sample_data=[r.data for r in cached[:5]]\r\n                )\r\n\r\n        # Fetch fresh data\r\n        connector = self.connectors[source]\r\n        errors = []\r\n\r\n        try:\r\n            records = connector.fetch(params or {})\r\n\r\n            # Cache the results\r\n            self.cache[cache_key] = records\r\n            self.cache_expiry[cache_key] = datetime.now()\r\n\r\n            return IntegrationResult(\r\n                source=source,\r\n                records_fetched=len(records),\r\n                records_processed=len(records),\r\n                errors=errors,\r\n                last_updated=datetime.now(),\r\n                sample_data=[r.data for r in records[:5]]\r\n            )\r\n\r\n        except Exception as e:\r\n            errors.append(str(e))\r\n            return IntegrationResult(\r\n                source=source,\r\n                records_fetched=0,\r\n                records_processed=0,\r\n                errors=errors,\r\n                last_updated=datetime.now(),\r\n                sample_data=[]\r\n            )\r\n\r\n    def enrich_project_data(\r\n        self,\r\n        project_data: Dict[str, Any],\r\n        enrichment_sources: Optional[List[str]] = None\r\n    ) -> EnrichedData:\r\n        \"\"\"\r\n        Enrich project data with open data.\r\n\r\n        Args:\r\n            project_data: Original project data\r\n            enrichment_sources: Sources to use for enrichment\r\n\r\n        Returns:\r\n            Enriched data\r\n        \"\"\"\r\n        sources = enrichment_sources or [\"material_prices\", \"labor_rates\", \"weather\"]\r\n        enrichments = {}\r\n        sources_used = []\r\n\r\n        # Material price enrichment\r\n        if \"material_prices\" in sources and \"materials\" in project_data:\r\n            materials = project_data[\"materials\"]\r\n            result = self.fetch_data(\"material_prices\", {\"materials\": materials})\r\n            if result.records_fetched > 0:\r\n                enrichments[\"material_price_indices\"] = result.sample_data\r\n                sources_used.append(\"material_prices\")\r\n\r\n        # Labor rate enrichment\r\n        if \"labor_rates\" in sources and \"trades\" in project_data:\r\n            trades = project_data[\"trades\"]\r\n            result = self.fetch_data(\"labor_rates\", {\"trades\": trades})\r\n            if result.records_fetched > 0:\r\n                enrichments[\"labor_rates\"] = result.sample_data\r\n                sources_used.append(\"labor_rates\")\r\n\r\n        # Weather enrichment\r\n        if \"weather\" in sources and \"location\" in project_data:\r\n            loc = project_data[\"location\"]\r\n            params = {\r\n                \"lat\": loc.get(\"lat\"),\r\n                \"lon\": loc.get(\"lon\"),\r\n                \"start_date\": project_data.get(\"start_date\", date.today()),\r\n                \"end_date\": project_data.get(\"end_date\", date.today())\r\n            }\r\n            result = self.fetch_data(\"weather\", params)\r\n            if result.records_fetched > 0:\r\n                enrichments[\"weather_forecast\"] = result.sample_data\r\n                sources_used.append(\"weather\")\r\n\r\n        # Calculate confidence based on enrichment success\r\n        confidence = len(sources_used) \u002F len(sources) if sources else 0\r\n\r\n        return EnrichedData(\r\n            original_data=project_data,\r\n            enrichments=enrichments,\r\n            sources_used=sources_used,\r\n            confidence=confidence\r\n        )\r\n\r\n    def get_cost_indices(\r\n        self,\r\n        materials: Optional[List[str]] = None,\r\n        trades: Optional[List[str]] = None\r\n    ) -> Dict:\r\n        \"\"\"Get current cost indices\"\"\"\r\n        indices = {\r\n            \"timestamp\": datetime.now().isoformat(),\r\n            \"region\": self.region\r\n        }\r\n\r\n        if materials:\r\n            result = self.fetch_data(\"material_prices\", {\"materials\": materials})\r\n            indices[\"materials\"] = result.sample_data\r\n\r\n        if trades:\r\n            result = self.fetch_data(\"labor_rates\", {\"trades\": trades})\r\n            indices[\"labor\"] = result.sample_data\r\n\r\n        return indices\r\n\r\n    def get_weather_risk(\r\n        self,\r\n        lat: float,\r\n        lon: float,\r\n        start_date: date,\r\n        end_date: date\r\n    ) -> Dict:\r\n        \"\"\"Assess weather risk for project period\"\"\"\r\n        result = self.fetch_data(\"weather\", {\r\n            \"lat\": lat,\r\n            \"lon\": lon,\r\n            \"start_date\": start_date,\r\n            \"end_date\": end_date\r\n        })\r\n\r\n        if result.records_fetched == 0:\r\n            return {\"error\": \"No weather data available\"}\r\n\r\n        # Calculate risk metrics\r\n        rain_days = sum(1 for d in result.sample_data\r\n                       if d.get(\"precipitation\", 0) > 5)\r\n        extreme_temp_days = sum(1 for d in result.sample_data\r\n                               if d.get(\"temp_max\", 0) > 35 or d.get(\"temp_min\", 0) \u003C 0)\r\n\r\n        total_days = len(result.sample_data)\r\n        risk_score = (rain_days + extreme_temp_days) \u002F total_days if total_days > 0 else 0\r\n\r\n        return {\r\n            \"total_days\": total_days,\r\n            \"rain_days\": rain_days,\r\n            \"extreme_temperature_days\": extreme_temp_days,\r\n            \"risk_score\": risk_score,\r\n            \"risk_level\": \"high\" if risk_score > 0.3 else \"medium\" if risk_score > 0.1 else \"low\"\r\n        }\r\n\r\n    def list_sources(self) -> List[Dict]:\r\n        \"\"\"List all available data sources\"\"\"\r\n        sources = []\r\n        for name, connector in self.connectors.items():\r\n            meta = connector.get_metadata()\r\n            sources.append({\r\n                \"name\": name,\r\n                **meta\r\n            })\r\n        return sources\r\n\r\n    def generate_report(self) -> str:\r\n        \"\"\"Generate data availability report\"\"\"\r\n        output = \"\"\"\r\n# Open Data Integration Report\r\n\r\n## Available Sources\r\n\"\"\"\r\n        for source in self.list_sources():\r\n            output += f\"\"\"\r\n### {source['name'].title()}\r\n- **Type:** {source['type']}\r\n- **Update Frequency:** {source['frequency']}\r\n\"\"\"\r\n\r\n        output += \"\"\"\r\n## Cache Status\r\n\"\"\"\r\n        for key, expiry in self.cache_expiry.items():\r\n            status = \"valid\" if expiry > datetime.now() else \"expired\"\r\n            output += f\"- {key}: {status}\\n\"\r\n\r\n        return output\r\n```\r\n\r\n## Common Use Cases\r\n\r\n### Fetch Material Prices\r\n\r\n```python\r\nintegrator = OpenDataIntegrator(region=\"US\")\r\n\r\n# Get material price indices\r\nresult = integrator.fetch_data(\"material_prices\", {\r\n    \"materials\": [\"concrete\", \"steel\", \"lumber\"]\r\n})\r\n\r\nprint(f\"Fetched: {result.records_fetched} records\")\r\nfor record in result.sample_data:\r\n    print(f\"  {record['material']}: index={record['current']}, trend={record['trend']}\")\r\n```\r\n\r\n### Enrich Project Data\r\n\r\n```python\r\nproject = {\r\n    \"name\": \"Office Building\",\r\n    \"materials\": [\"concrete\", \"steel\", \"glass\"],\r\n    \"trades\": [\"carpenter\", \"electrician\", \"plumber\"],\r\n    \"location\": {\"lat\": 40.7128, \"lon\": -74.0060},\r\n    \"start_date\": date(2024, 6, 1),\r\n    \"end_date\": date(2024, 12, 31)\r\n}\r\n\r\nenriched = integrator.enrich_project_data(project)\r\n\r\nprint(f\"Sources used: {enriched.sources_used}\")\r\nprint(f\"Confidence: {enriched.confidence:.0%}\")\r\nprint(f\"Material indices: {enriched.enrichments.get('material_price_indices')}\")\r\n```\r\n\r\n### Assess Weather Risk\r\n\r\n```python\r\nrisk = integrator.get_weather_risk(\r\n    lat=40.7128,\r\n    lon=-74.0060,\r\n    start_date=date(2024, 6, 1),\r\n    end_date=date(2024, 8, 31)\r\n)\r\n\r\nprint(f\"Risk Level: {risk['risk_level']}\")\r\nprint(f\"Rain Days: {risk['rain_days']}\")\r\n```\r\n\r\n## Quick Reference\r\n\r\n| Component | Purpose |\r\n|-----------|---------|\r\n| `OpenDataIntegrator` | Main integration engine |\r\n| `OpenDataConnector` | Base connector class |\r\n| `WeatherDataConnector` | Weather API connector |\r\n| `MaterialPriceConnector` | Material price indices |\r\n| `LaborRateConnector` | Labor rate data |\r\n| `EnrichedData` | Enriched data result |\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 [ontology-mapper](..\u002Fontology-mapper\u002FSKILL.md) for semantic mapping\r\n- Use [cost-prediction](..\u002F..\u002FChapter-4.5\u002Fcost-prediction\u002FSKILL.md) with indices\r\n- Use [weather-impact-analysis](..\u002F..\u002F..\u002FDDC_Innovative\u002Fweather-impact-analysis\u002FSKILL.md) for scheduling\r\n",{"slug":5,"description":7,"display_name":36},"Open Data Integrator","main","e7e336ac628c3e3bd771aff1aaa469c93778f94a","skills\u002Fdatadrivenconstruction\u002Fopen-data-integrator",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":45,"prompt":55,"zipAvailable":56},[46,49,52],{"tool":47,"command":48},"npx","npx skills add kbarbel640-del\u002Fskills --skill open-data-integrator",{"tool":50,"command":51},"bunx","bunx skills add kbarbel640-del\u002Fskills --skill open-data-integrator",{"tool":53,"command":54},"pnpm","pnpm dlx skills add kbarbel640-del\u002Fskills --skill open-data-integrator","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fopen-data-integrator\u002FSKILL.md",true,[58],{"path":59,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":62,"sourceHtmlUrl":63},"_meta.json","REFERENCE","参考文档",308,"https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fopen-data-integrator\u002F_meta.json",[65,94,123,144,150,170],{"skillNo":66,"name":67,"nameZh":6,"description":68,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":69,"categories":70,"keywords":74,"publishedAt":31},"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",[71],{"categoryNo":72,"categoryName":73,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000036","内容创作者",[75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93],"crowd prompting","prompting","api","with","tokens","domain","world","prompts","operations","instructions","text","tool","system","improve","productivity","marketplace","https","content","ai agents",{"skillNo":95,"name":96,"nameZh":6,"description":97,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":98,"categories":99,"keywords":105,"publishedAt":31},"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",[100],{"categoryNo":101,"categoryName":102,"taxonomyType":103,"taxonomyTypeDesc":104},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[106,77,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,82,122],"dilemm ai","arena","analyze","browser","openclaw agent","create","automation","browser automation","bot","openclaw","design","strategy","headless","compete","submit","matchmaking","use",{"skillNo":124,"name":125,"nameZh":6,"description":126,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":127,"categories":128,"keywords":132,"publishedAt":31},"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",[129],{"categoryNo":130,"categoryName":131,"taxonomyType":103,"taxonomyTypeDesc":104},"01JBSEEDCAT000000000000021","资料检索与研究",[133,134,135,136,137,138,139,78,140,120,122,141,77,142,143],"arxiv paper reviews","reviews","arxiv","paper","crawler","papers","comments","fetch","read","http","via",{"skillNo":145,"name":125,"nameZh":6,"description":126,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":146,"categories":147,"keywords":149,"publishedAt":31},"01M6G8HQJ7N7WMY6YV7D7SSJ16","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzxrys\u002Farxiv-paper-reviews\u002FSKILL.md",[148],{"categoryNo":130,"categoryName":131,"taxonomyType":103,"taxonomyTypeDesc":104},[136,135,134,133,143,138,139,78,137,120,122,140,141,77,142],{"skillNo":151,"name":152,"nameZh":6,"description":153,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":154,"categories":155,"keywords":156,"publishedAt":31},"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",[],[157,158,159,160,161,162,163,164,165,166,167,168,169],"git","summary","git summary","commits","repository","win32","status","linux","contributors","true","quick","get","branches",{"skillNo":171,"name":172,"nameZh":6,"description":173,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":174,"categories":175,"keywords":180,"publishedAt":31},"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",[176,177],{"categoryNo":101,"categoryName":102,"taxonomyType":103,"taxonomyTypeDesc":104},{"categoryNo":178,"categoryName":179,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000037","律师与法务",[181,182,183,184,78,185,186,37,187,141,188,189,190,191,192,91,193,194,195],"agent constitution","constitution","contracts","tree","query","base","log","check","Rules","projects","compliance","actions","state","governance","github"]