[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FK88SWZ6TVWA28Y240AD5D":3,"skill-same:01M6FK88SWZ6TVWA28Y240AD5D":71},{"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":27,"publishedAt":38,"linkOnly":39,"markdownContent":40,"markdownBody":41,"frontMatter":42,"refName":44,"commitSha":45,"skillDirectory":46,"forksCount":47,"repositoryHtmlUrl":48,"repositoryHomepageUrl":6,"ownerHtmlUrl":49,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":50,"install":51,"resources":64},"01M6FK88SWZ6TVWA28Y240AD5D","weather-api",null,"Fetch weather data for construction scheduling. Historical data, forecasts, and risk assessment for outdoor work.","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\u002Fweather-api\u002FSKILL.md",[17,22],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":25,"taxonomyTypeDesc":26},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[28,29,30,31,32,33,34,35,36,37],"weather","api","weather api","risk assessment","assessment","data","risk","work","fetch","scheduling","2026-11-10 10:12:30",false,"---\r\nslug: \"weather-api\"\r\ndisplay_name: \"Weather API\"\r\ndescription: \"Fetch weather data for construction scheduling. Historical data, forecasts, and risk assessment for outdoor work.\"\r\n---\r\n\r\n# Weather API for Construction\r\n\r\n## Overview\r\nWeather impacts 50% of construction activities. This skill fetches weather data for scheduling, risk assessment, and productivity adjustments.\r\n\r\n## Python Implementation\r\n\r\n```python\r\nimport requests\r\nimport pandas as pd\r\nfrom typing import Dict, Any, List, Optional\r\nfrom dataclasses import dataclass\r\nfrom datetime import datetime, timedelta\r\nfrom enum import Enum\r\n\r\n\r\nclass WeatherRisk(Enum):\r\n    \"\"\"Weather risk levels for construction.\"\"\"\r\n    LOW = \"low\"\r\n    MODERATE = \"moderate\"\r\n    HIGH = \"high\"\r\n    CRITICAL = \"critical\"\r\n\r\n\r\n@dataclass\r\nclass WeatherCondition:\r\n    \"\"\"Weather condition at a point in time.\"\"\"\r\n    timestamp: datetime\r\n    temperature: float  # Celsius\r\n    humidity: float     # Percent\r\n    wind_speed: float   # m\u002Fs\r\n    precipitation: float  # mm\r\n    conditions: str\r\n\r\n\r\n@dataclass\r\nclass WorkabilityAssessment:\r\n    \"\"\"Assessment of weather workability.\"\"\"\r\n    date: datetime\r\n    risk_level: WeatherRisk\r\n    workable_hours: int\r\n    affected_activities: List[str]\r\n    recommendations: List[str]\r\n\r\n\r\nclass WeatherAPIClient:\r\n    \"\"\"Client for weather APIs.\"\"\"\r\n\r\n    # Free tier endpoints\r\n    OPEN_METEO_BASE = \"https:\u002F\u002Fapi.open-meteo.com\u002Fv1\"\r\n\r\n    def __init__(self, api_key: Optional[str] = None):\r\n        self.api_key = api_key\r\n\r\n    def get_forecast(self, latitude: float, longitude: float,\r\n                     days: int = 7) -> List[WeatherCondition]:\r\n        \"\"\"Get weather forecast.\"\"\"\r\n        url = f\"{self.OPEN_METEO_BASE}\u002Fforecast\"\r\n        params = {\r\n            'latitude': latitude,\r\n            'longitude': longitude,\r\n            'hourly': 'temperature_2m,relative_humidity_2m,wind_speed_10m,precipitation',\r\n            'forecast_days': days\r\n        }\r\n\r\n        response = requests.get(url, params=params)\r\n        if response.status_code != 200:\r\n            raise Exception(f\"API error: {response.status_code}\")\r\n\r\n        data = response.json()\r\n        return self._parse_forecast(data)\r\n\r\n    def get_historical(self, latitude: float, longitude: float,\r\n                       start_date: str, end_date: str) -> List[WeatherCondition]:\r\n        \"\"\"Get historical weather data.\"\"\"\r\n        url = f\"{self.OPEN_METEO_BASE}\u002Farchive\"\r\n        params = {\r\n            'latitude': latitude,\r\n            'longitude': longitude,\r\n            'start_date': start_date,\r\n            'end_date': end_date,\r\n            'hourly': 'temperature_2m,relative_humidity_2m,wind_speed_10m,precipitation'\r\n        }\r\n\r\n        response = requests.get(url, params=params)\r\n        if response.status_code != 200:\r\n            raise Exception(f\"API error: {response.status_code}\")\r\n\r\n        data = response.json()\r\n        return self._parse_forecast(data)\r\n\r\n    def _parse_forecast(self, data: Dict) -> List[WeatherCondition]:\r\n        \"\"\"Parse API response to WeatherCondition list.\"\"\"\r\n        conditions = []\r\n        hourly = data.get('hourly', {})\r\n\r\n        times = hourly.get('time', [])\r\n        temps = hourly.get('temperature_2m', [])\r\n        humidity = hourly.get('relative_humidity_2m', [])\r\n        wind = hourly.get('wind_speed_10m', [])\r\n        precip = hourly.get('precipitation', [])\r\n\r\n        for i in range(len(times)):\r\n            conditions.append(WeatherCondition(\r\n                timestamp=datetime.fromisoformat(times[i]),\r\n                temperature=temps[i] if i \u003C len(temps) else 0,\r\n                humidity=humidity[i] if i \u003C len(humidity) else 0,\r\n                wind_speed=wind[i] if i \u003C len(wind) else 0,\r\n                precipitation=precip[i] if i \u003C len(precip) else 0,\r\n                conditions=self._describe_conditions(\r\n                    temps[i] if i \u003C len(temps) else 0,\r\n                    precip[i] if i \u003C len(precip) else 0,\r\n                    wind[i] if i \u003C len(wind) else 0\r\n                )\r\n            ))\r\n\r\n        return conditions\r\n\r\n    def _describe_conditions(self, temp: float, precip: float, wind: float) -> str:\r\n        \"\"\"Generate weather description.\"\"\"\r\n        conditions = []\r\n\r\n        if temp \u003C 0:\r\n            conditions.append(\"Freezing\")\r\n        elif temp > 35:\r\n            conditions.append(\"Extreme heat\")\r\n        elif temp > 30:\r\n            conditions.append(\"Hot\")\r\n        elif temp \u003C 10:\r\n            conditions.append(\"Cold\")\r\n\r\n        if precip > 10:\r\n            conditions.append(\"Heavy rain\")\r\n        elif precip > 2:\r\n            conditions.append(\"Rain\")\r\n        elif precip > 0:\r\n            conditions.append(\"Light rain\")\r\n\r\n        if wind > 15:\r\n            conditions.append(\"Strong winds\")\r\n        elif wind > 10:\r\n            conditions.append(\"Windy\")\r\n\r\n        return \", \".join(conditions) if conditions else \"Clear\"\r\n\r\n    def to_dataframe(self, conditions: List[WeatherCondition]) -> pd.DataFrame:\r\n        \"\"\"Convert conditions to DataFrame.\"\"\"\r\n        data = [{\r\n            'timestamp': c.timestamp,\r\n            'temperature': c.temperature,\r\n            'humidity': c.humidity,\r\n            'wind_speed': c.wind_speed,\r\n            'precipitation': c.precipitation,\r\n            'conditions': c.conditions\r\n        } for c in conditions]\r\n        return pd.DataFrame(data)\r\n\r\n\r\nclass ConstructionWeatherRisk:\r\n    \"\"\"Assess weather risk for construction activities.\"\"\"\r\n\r\n    # Activity-specific thresholds\r\n    THRESHOLDS = {\r\n        'concrete_pour': {\r\n            'min_temp': 5, 'max_temp': 35,\r\n            'max_wind': 12, 'max_precip': 0.5\r\n        },\r\n        'crane_work': {\r\n            'min_temp': -10, 'max_temp': 40,\r\n            'max_wind': 10, 'max_precip': 5\r\n        },\r\n        'exterior_paint': {\r\n            'min_temp': 10, 'max_temp': 35,\r\n            'max_wind': 8, 'max_precip': 0\r\n        },\r\n        'roofing': {\r\n            'min_temp': 5, 'max_temp': 38,\r\n            'max_wind': 12, 'max_precip': 0\r\n        },\r\n        'earthwork': {\r\n            'min_temp': -5, 'max_temp': 40,\r\n            'max_wind': 20, 'max_precip': 10\r\n        }\r\n    }\r\n\r\n    def assess_workability(self, condition: WeatherCondition,\r\n                           activities: List[str] = None) -> WorkabilityAssessment:\r\n        \"\"\"Assess workability for given conditions.\"\"\"\r\n\r\n        if activities is None:\r\n            activities = list(self.THRESHOLDS.keys())\r\n\r\n        affected = []\r\n        recommendations = []\r\n\r\n        for activity in activities:\r\n            if activity in self.THRESHOLDS:\r\n                thresh = self.THRESHOLDS[activity]\r\n\r\n                reasons = []\r\n                if condition.temperature \u003C thresh['min_temp']:\r\n                    reasons.append(f\"Too cold ({condition.temperature}°C)\")\r\n                if condition.temperature > thresh['max_temp']:\r\n                    reasons.append(f\"Too hot ({condition.temperature}°C)\")\r\n                if condition.wind_speed > thresh['max_wind']:\r\n                    reasons.append(f\"High wind ({condition.wind_speed} m\u002Fs)\")\r\n                if condition.precipitation > thresh['max_precip']:\r\n                    reasons.append(f\"Precipitation ({condition.precipitation} mm)\")\r\n\r\n                if reasons:\r\n                    affected.append(activity)\r\n                    recommendations.append(f\"{activity}: \" + \", \".join(reasons))\r\n\r\n        # Determine overall risk level\r\n        if len(affected) >= len(activities) * 0.8:\r\n            risk = WeatherRisk.CRITICAL\r\n            workable = 0\r\n        elif len(affected) >= len(activities) * 0.5:\r\n            risk = WeatherRisk.HIGH\r\n            workable = 4\r\n        elif len(affected) > 0:\r\n            risk = WeatherRisk.MODERATE\r\n            workable = 6\r\n        else:\r\n            risk = WeatherRisk.LOW\r\n            workable = 8\r\n\r\n        return WorkabilityAssessment(\r\n            date=condition.timestamp,\r\n            risk_level=risk,\r\n            workable_hours=workable,\r\n            affected_activities=affected,\r\n            recommendations=recommendations\r\n        )\r\n\r\n    def weekly_forecast_risk(self, conditions: List[WeatherCondition],\r\n                             activities: List[str] = None) -> pd.DataFrame:\r\n        \"\"\"Assess risk for week of weather data.\"\"\"\r\n\r\n        # Group by date\r\n        daily_conditions = {}\r\n        for c in conditions:\r\n            date = c.timestamp.date()\r\n            if date not in daily_conditions:\r\n                daily_conditions[date] = []\r\n            daily_conditions[date].append(c)\r\n\r\n        assessments = []\r\n        for date, day_conditions in daily_conditions.items():\r\n            # Use midday condition as representative\r\n            midday = [c for c in day_conditions\r\n                      if 10 \u003C= c.timestamp.hour \u003C= 16]\r\n            representative = midday[len(midday)\u002F\u002F2] if midday else day_conditions[0]\r\n\r\n            assessment = self.assess_workability(representative, activities)\r\n            assessments.append({\r\n                'date': date,\r\n                'risk_level': assessment.risk_level.value,\r\n                'workable_hours': assessment.workable_hours,\r\n                'affected_count': len(assessment.affected_activities)\r\n            })\r\n\r\n        return pd.DataFrame(assessments)\r\n```\r\n\r\n## Quick Start\r\n\r\n```python\r\n# Initialize client\r\nweather = WeatherAPIClient()\r\n\r\n# Get forecast for site\r\nconditions = weather.get_forecast(latitude=52.52, longitude=13.41, days=7)\r\ndf = weather.to_dataframe(conditions)\r\nprint(df.head())\r\n\r\n# Assess construction risk\r\nrisk = ConstructionWeatherRisk()\r\nweekly_risk = risk.weekly_forecast_risk(conditions)\r\nprint(weekly_risk)\r\n```\r\n\r\n## Common Use Cases\r\n\r\n### 1. Schedule Planning\r\n```python\r\nconditions = weather.get_forecast(52.52, 13.41, days=14)\r\nrisk = ConstructionWeatherRisk()\r\n\r\n# Check concrete pour window\r\nfor c in conditions:\r\n    assessment = risk.assess_workability(c, ['concrete_pour'])\r\n    if assessment.risk_level == WeatherRisk.LOW:\r\n        print(f\"Good for concrete: {c.timestamp}\")\r\n```\r\n\r\n### 2. Historical Analysis\r\n```python\r\nhistorical = weather.get_historical(52.52, 13.41, '2024-01-01', '2024-03-31')\r\ndf = weather.to_dataframe(historical)\r\n\r\n# Count rain days\r\nrain_days = df[df['precipitation'] > 2]['timestamp'].dt.date.nunique()\r\nprint(f\"Rain days in Q1: {rain_days}\")\r\n```\r\n\r\n## Resources\r\n- **DDC Book**: Chapter 2.2 - Open Data Integration\r\n- **Open-Meteo API**: https:\u002F\u002Fopen-meteo.com\u002F\r\n","# Weather API for Construction\r\n\r\n## Overview\r\nWeather impacts 50% of construction activities. This skill fetches weather data for scheduling, risk assessment, and productivity adjustments.\r\n\r\n## Python Implementation\r\n\r\n```python\r\nimport requests\r\nimport pandas as pd\r\nfrom typing import Dict, Any, List, Optional\r\nfrom dataclasses import dataclass\r\nfrom datetime import datetime, timedelta\r\nfrom enum import Enum\r\n\r\n\r\nclass WeatherRisk(Enum):\r\n    \"\"\"Weather risk levels for construction.\"\"\"\r\n    LOW = \"low\"\r\n    MODERATE = \"moderate\"\r\n    HIGH = \"high\"\r\n    CRITICAL = \"critical\"\r\n\r\n\r\n@dataclass\r\nclass WeatherCondition:\r\n    \"\"\"Weather condition at a point in time.\"\"\"\r\n    timestamp: datetime\r\n    temperature: float  # Celsius\r\n    humidity: float     # Percent\r\n    wind_speed: float   # m\u002Fs\r\n    precipitation: float  # mm\r\n    conditions: str\r\n\r\n\r\n@dataclass\r\nclass WorkabilityAssessment:\r\n    \"\"\"Assessment of weather workability.\"\"\"\r\n    date: datetime\r\n    risk_level: WeatherRisk\r\n    workable_hours: int\r\n    affected_activities: List[str]\r\n    recommendations: List[str]\r\n\r\n\r\nclass WeatherAPIClient:\r\n    \"\"\"Client for weather APIs.\"\"\"\r\n\r\n    # Free tier endpoints\r\n    OPEN_METEO_BASE = \"https:\u002F\u002Fapi.open-meteo.com\u002Fv1\"\r\n\r\n    def __init__(self, api_key: Optional[str] = None):\r\n        self.api_key = api_key\r\n\r\n    def get_forecast(self, latitude: float, longitude: float,\r\n                     days: int = 7) -> List[WeatherCondition]:\r\n        \"\"\"Get weather forecast.\"\"\"\r\n        url = f\"{self.OPEN_METEO_BASE}\u002Fforecast\"\r\n        params = {\r\n            'latitude': latitude,\r\n            'longitude': longitude,\r\n            'hourly': 'temperature_2m,relative_humidity_2m,wind_speed_10m,precipitation',\r\n            'forecast_days': days\r\n        }\r\n\r\n        response = requests.get(url, params=params)\r\n        if response.status_code != 200:\r\n            raise Exception(f\"API error: {response.status_code}\")\r\n\r\n        data = response.json()\r\n        return self._parse_forecast(data)\r\n\r\n    def get_historical(self, latitude: float, longitude: float,\r\n                       start_date: str, end_date: str) -> List[WeatherCondition]:\r\n        \"\"\"Get historical weather data.\"\"\"\r\n        url = f\"{self.OPEN_METEO_BASE}\u002Farchive\"\r\n        params = {\r\n            'latitude': latitude,\r\n            'longitude': longitude,\r\n            'start_date': start_date,\r\n            'end_date': end_date,\r\n            'hourly': 'temperature_2m,relative_humidity_2m,wind_speed_10m,precipitation'\r\n        }\r\n\r\n        response = requests.get(url, params=params)\r\n        if response.status_code != 200:\r\n            raise Exception(f\"API error: {response.status_code}\")\r\n\r\n        data = response.json()\r\n        return self._parse_forecast(data)\r\n\r\n    def _parse_forecast(self, data: Dict) -> List[WeatherCondition]:\r\n        \"\"\"Parse API response to WeatherCondition list.\"\"\"\r\n        conditions = []\r\n        hourly = data.get('hourly', {})\r\n\r\n        times = hourly.get('time', [])\r\n        temps = hourly.get('temperature_2m', [])\r\n        humidity = hourly.get('relative_humidity_2m', [])\r\n        wind = hourly.get('wind_speed_10m', [])\r\n        precip = hourly.get('precipitation', [])\r\n\r\n        for i in range(len(times)):\r\n            conditions.append(WeatherCondition(\r\n                timestamp=datetime.fromisoformat(times[i]),\r\n                temperature=temps[i] if i \u003C len(temps) else 0,\r\n                humidity=humidity[i] if i \u003C len(humidity) else 0,\r\n                wind_speed=wind[i] if i \u003C len(wind) else 0,\r\n                precipitation=precip[i] if i \u003C len(precip) else 0,\r\n                conditions=self._describe_conditions(\r\n                    temps[i] if i \u003C len(temps) else 0,\r\n                    precip[i] if i \u003C len(precip) else 0,\r\n                    wind[i] if i \u003C len(wind) else 0\r\n                )\r\n            ))\r\n\r\n        return conditions\r\n\r\n    def _describe_conditions(self, temp: float, precip: float, wind: float) -> str:\r\n        \"\"\"Generate weather description.\"\"\"\r\n        conditions = []\r\n\r\n        if temp \u003C 0:\r\n            conditions.append(\"Freezing\")\r\n        elif temp > 35:\r\n            conditions.append(\"Extreme heat\")\r\n        elif temp > 30:\r\n            conditions.append(\"Hot\")\r\n        elif temp \u003C 10:\r\n            conditions.append(\"Cold\")\r\n\r\n        if precip > 10:\r\n            conditions.append(\"Heavy rain\")\r\n        elif precip > 2:\r\n            conditions.append(\"Rain\")\r\n        elif precip > 0:\r\n            conditions.append(\"Light rain\")\r\n\r\n        if wind > 15:\r\n            conditions.append(\"Strong winds\")\r\n        elif wind > 10:\r\n            conditions.append(\"Windy\")\r\n\r\n        return \", \".join(conditions) if conditions else \"Clear\"\r\n\r\n    def to_dataframe(self, conditions: List[WeatherCondition]) -> pd.DataFrame:\r\n        \"\"\"Convert conditions to DataFrame.\"\"\"\r\n        data = [{\r\n            'timestamp': c.timestamp,\r\n            'temperature': c.temperature,\r\n            'humidity': c.humidity,\r\n            'wind_speed': c.wind_speed,\r\n            'precipitation': c.precipitation,\r\n            'conditions': c.conditions\r\n        } for c in conditions]\r\n        return pd.DataFrame(data)\r\n\r\n\r\nclass ConstructionWeatherRisk:\r\n    \"\"\"Assess weather risk for construction activities.\"\"\"\r\n\r\n    # Activity-specific thresholds\r\n    THRESHOLDS = {\r\n        'concrete_pour': {\r\n            'min_temp': 5, 'max_temp': 35,\r\n            'max_wind': 12, 'max_precip': 0.5\r\n        },\r\n        'crane_work': {\r\n            'min_temp': -10, 'max_temp': 40,\r\n            'max_wind': 10, 'max_precip': 5\r\n        },\r\n        'exterior_paint': {\r\n            'min_temp': 10, 'max_temp': 35,\r\n            'max_wind': 8, 'max_precip': 0\r\n        },\r\n        'roofing': {\r\n            'min_temp': 5, 'max_temp': 38,\r\n            'max_wind': 12, 'max_precip': 0\r\n        },\r\n        'earthwork': {\r\n            'min_temp': -5, 'max_temp': 40,\r\n            'max_wind': 20, 'max_precip': 10\r\n        }\r\n    }\r\n\r\n    def assess_workability(self, condition: WeatherCondition,\r\n                           activities: List[str] = None) -> WorkabilityAssessment:\r\n        \"\"\"Assess workability for given conditions.\"\"\"\r\n\r\n        if activities is None:\r\n            activities = list(self.THRESHOLDS.keys())\r\n\r\n        affected = []\r\n        recommendations = []\r\n\r\n        for activity in activities:\r\n            if activity in self.THRESHOLDS:\r\n                thresh = self.THRESHOLDS[activity]\r\n\r\n                reasons = []\r\n                if condition.temperature \u003C thresh['min_temp']:\r\n                    reasons.append(f\"Too cold ({condition.temperature}°C)\")\r\n                if condition.temperature > thresh['max_temp']:\r\n                    reasons.append(f\"Too hot ({condition.temperature}°C)\")\r\n                if condition.wind_speed > thresh['max_wind']:\r\n                    reasons.append(f\"High wind ({condition.wind_speed} m\u002Fs)\")\r\n                if condition.precipitation > thresh['max_precip']:\r\n                    reasons.append(f\"Precipitation ({condition.precipitation} mm)\")\r\n\r\n                if reasons:\r\n                    affected.append(activity)\r\n                    recommendations.append(f\"{activity}: \" + \", \".join(reasons))\r\n\r\n        # Determine overall risk level\r\n        if len(affected) >= len(activities) * 0.8:\r\n            risk = WeatherRisk.CRITICAL\r\n            workable = 0\r\n        elif len(affected) >= len(activities) * 0.5:\r\n            risk = WeatherRisk.HIGH\r\n            workable = 4\r\n        elif len(affected) > 0:\r\n            risk = WeatherRisk.MODERATE\r\n            workable = 6\r\n        else:\r\n            risk = WeatherRisk.LOW\r\n            workable = 8\r\n\r\n        return WorkabilityAssessment(\r\n            date=condition.timestamp,\r\n            risk_level=risk,\r\n            workable_hours=workable,\r\n            affected_activities=affected,\r\n            recommendations=recommendations\r\n        )\r\n\r\n    def weekly_forecast_risk(self, conditions: List[WeatherCondition],\r\n                             activities: List[str] = None) -> pd.DataFrame:\r\n        \"\"\"Assess risk for week of weather data.\"\"\"\r\n\r\n        # Group by date\r\n        daily_conditions = {}\r\n        for c in conditions:\r\n            date = c.timestamp.date()\r\n            if date not in daily_conditions:\r\n                daily_conditions[date] = []\r\n            daily_conditions[date].append(c)\r\n\r\n        assessments = []\r\n        for date, day_conditions in daily_conditions.items():\r\n            # Use midday condition as representative\r\n            midday = [c for c in day_conditions\r\n                      if 10 \u003C= c.timestamp.hour \u003C= 16]\r\n            representative = midday[len(midday)\u002F\u002F2] if midday else day_conditions[0]\r\n\r\n            assessment = self.assess_workability(representative, activities)\r\n            assessments.append({\r\n                'date': date,\r\n                'risk_level': assessment.risk_level.value,\r\n                'workable_hours': assessment.workable_hours,\r\n                'affected_count': len(assessment.affected_activities)\r\n            })\r\n\r\n        return pd.DataFrame(assessments)\r\n```\r\n\r\n## Quick Start\r\n\r\n```python\r\n# Initialize client\r\nweather = WeatherAPIClient()\r\n\r\n# Get forecast for site\r\nconditions = weather.get_forecast(latitude=52.52, longitude=13.41, days=7)\r\ndf = weather.to_dataframe(conditions)\r\nprint(df.head())\r\n\r\n# Assess construction risk\r\nrisk = ConstructionWeatherRisk()\r\nweekly_risk = risk.weekly_forecast_risk(conditions)\r\nprint(weekly_risk)\r\n```\r\n\r\n## Common Use Cases\r\n\r\n### 1. Schedule Planning\r\n```python\r\nconditions = weather.get_forecast(52.52, 13.41, days=14)\r\nrisk = ConstructionWeatherRisk()\r\n\r\n# Check concrete pour window\r\nfor c in conditions:\r\n    assessment = risk.assess_workability(c, ['concrete_pour'])\r\n    if assessment.risk_level == WeatherRisk.LOW:\r\n        print(f\"Good for concrete: {c.timestamp}\")\r\n```\r\n\r\n### 2. Historical Analysis\r\n```python\r\nhistorical = weather.get_historical(52.52, 13.41, '2024-01-01', '2024-03-31')\r\ndf = weather.to_dataframe(historical)\r\n\r\n# Count rain days\r\nrain_days = df[df['precipitation'] > 2]['timestamp'].dt.date.nunique()\r\nprint(f\"Rain days in Q1: {rain_days}\")\r\n```\r\n\r\n## Resources\r\n- **DDC Book**: Chapter 2.2 - Open Data Integration\r\n- **Open-Meteo API**: https:\u002F\u002Fopen-meteo.com\u002F\r\n",{"slug":5,"description":7,"display_name":43},"Weather API","main","e7e336ac628c3e3bd771aff1aaa469c93778f94a","skills\u002Fdatadrivenconstruction\u002Fweather-api",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":52,"prompt":62,"zipAvailable":63},[53,56,59],{"tool":54,"command":55},"npx","npx skills add kbarbel640-del\u002Fskills --skill weather-api",{"tool":57,"command":58},"bunx","bunx skills add kbarbel640-del\u002Fskills --skill weather-api",{"tool":60,"command":61},"pnpm","pnpm dlx skills add kbarbel640-del\u002Fskills --skill weather-api","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fweather-api\u002FSKILL.md",true,[65],{"path":66,"resourceType":67,"resourceTypeDesc":68,"sizeBytes":69,"sourceHtmlUrl":70},"_meta.json","REFERENCE","参考文档",290,"https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fweather-api\u002F_meta.json",[72,100,127,147,153,173],{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":81,"publishedAt":38},"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",[78],{"categoryNo":79,"categoryName":80,"taxonomyType":25,"taxonomyTypeDesc":26},"01JBSEEDCAT000000000000036","内容创作者",[82,83,29,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99],"crowd prompting","prompting","with","tokens","domain","world","prompts","operations","instructions","text","tool","system","improve","productivity","marketplace","https","content","ai agents",{"skillNo":101,"name":102,"nameZh":6,"description":103,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":109,"publishedAt":38},"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",[106],{"categoryNo":107,"categoryName":108,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[110,29,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,88,126],"dilemm ai","arena","analyze","browser","openclaw agent","create","automation","browser automation","bot","openclaw","design","strategy","headless","compete","submit","matchmaking","use",{"skillNo":128,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":131,"categories":132,"keywords":136,"publishedAt":38},"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",[133],{"categoryNo":134,"categoryName":135,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000021","资料检索与研究",[137,138,139,140,141,142,143,84,36,124,126,144,29,145,146],"arxiv paper reviews","reviews","arxiv","paper","crawler","papers","comments","read","http","via",{"skillNo":148,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":149,"categories":150,"keywords":152,"publishedAt":38},"01M6G8HQJ7N7WMY6YV7D7SSJ16","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzxrys\u002Farxiv-paper-reviews\u002FSKILL.md",[151],{"categoryNo":134,"categoryName":135,"taxonomyType":20,"taxonomyTypeDesc":21},[140,139,138,137,146,142,143,84,141,124,126,36,144,29,145],{"skillNo":154,"name":155,"nameZh":6,"description":156,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":157,"categories":158,"keywords":159,"publishedAt":38},"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",[],[160,161,162,163,164,165,166,167,168,169,170,171,172],"git","summary","git summary","commits","repository","win32","status","linux","contributors","true","quick","get","branches",{"skillNo":174,"name":175,"nameZh":6,"description":176,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":177,"categories":178,"keywords":183,"publishedAt":38},"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",[179,180],{"categoryNo":107,"categoryName":108,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":181,"categoryName":182,"taxonomyType":25,"taxonomyTypeDesc":26},"01JBSEEDCAT000000000000037","律师与法务",[184,185,186,187,84,188,189,44,190,144,191,192,193,194,195,97,196,197,198],"agent constitution","constitution","contracts","tree","query","base","log","check","Rules","projects","compliance","actions","state","governance","github"]