Skip to main content
ClaudeWave
Skill173 estrellas del repoactualizado 3mo ago

weather-impact-scheduler

Analyze weather impact on construction schedule. Predict delays and adjust activities based on forecast.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction /tmp/weather-impact-scheduler && cp -r /tmp/weather-impact-scheduler/1_DDC_Toolkit/Schedule-Integration/weather-impact-scheduler ~/.claude/skills/weather-impact-scheduler
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Weather Impact Scheduler

## Technical Implementation

```python
import pandas as pd
from datetime import date, timedelta
from typing import Dict, Any, List, Optional
from dataclasses import dataclass, field
from enum import Enum


class WeatherCondition(Enum):
    CLEAR = "clear"
    CLOUDY = "cloudy"
    RAIN = "rain"
    HEAVY_RAIN = "heavy_rain"
    SNOW = "snow"
    WIND = "wind"
    EXTREME_HEAT = "extreme_heat"
    EXTREME_COLD = "extreme_cold"


class ActivitySensitivity(Enum):
    HIGH = "high"      # Concrete, painting, roofing
    MEDIUM = "medium"  # Excavation, masonry
    LOW = "low"        # Indoor work


@dataclass
class WeatherForecast:
    forecast_date: date
    condition: WeatherCondition
    high_temp: float
    low_temp: float
    precipitation_mm: float
    wind_speed_kmh: float


@dataclass
class ScheduleActivity:
    activity_id: str
    name: str
    start_date: date
    end_date: date
    sensitivity: ActivitySensitivity
    outdoor: bool
    can_work_in_rain: bool = False
    min_temp: float = 5.0
    max_temp: float = 35.0
    max_wind: float = 50.0


@dataclass
class WeatherImpact:
    activity_id: str
    impact_date: date
    reason: str
    delay_hours: float
    recommendation: str


class WeatherImpactScheduler:
    def __init__(self, project_name: str):
        self.project_name = project_name
        self.activities: Dict[str, ScheduleActivity] = {}
        self.forecasts: Dict[date, WeatherForecast] = {}
        self.impacts: List[WeatherImpact] = []

    def add_activity(self, activity_id: str, name: str, start_date: date,
                    end_date: date, sensitivity: ActivitySensitivity,
                    outdoor: bool = True, can_work_in_rain: bool = False) -> ScheduleActivity:
        activity = ScheduleActivity(
            activity_id=activity_id,
            name=name,
            start_date=start_date,
            end_date=end_date,
            sensitivity=sensitivity,
            outdoor=outdoor,
            can_work_in_rain=can_work_in_rain
        )
        self.activities[activity_id] = activity
        return activity

    def add_forecast(self, forecast_date: date, condition: WeatherCondition,
                    high_temp: float, low_temp: float,
                    precipitation_mm: float = 0, wind_speed_kmh: float = 0):
        forecast = WeatherForecast(
            forecast_date=forecast_date,
            condition=condition,
            high_temp=high_temp,
            low_temp=low_temp,
            precipitation_mm=precipitation_mm,
            wind_speed_kmh=wind_speed_kmh
        )
        self.forecasts[forecast_date] = forecast

    def analyze_impacts(self) -> List[WeatherImpact]:
        self.impacts = []

        for activity in self.activities.values():
            if not activity.outdoor:
                continue

            current = activity.start_date
            while current <= activity.end_date:
                forecast = self.forecasts.get(current)
                if forecast:
                    impact = self._check_impact(activity, forecast)
                    if impact:
                        self.impacts.append(impact)
                current += timedelta(days=1)

        return self.impacts

    def _check_impact(self, activity: ScheduleActivity,
                     forecast: WeatherForecast) -> Optional[WeatherImpact]:
        reasons = []
        delay_hours = 0

        # Check precipitation
        if forecast.condition in [WeatherCondition.RAIN, WeatherCondition.HEAVY_RAIN]:
            if not activity.can_work_in_rain:
                if activity.sensitivity == ActivitySensitivity.HIGH:
                    reasons.append("Rain - high sensitivity activity")
                    delay_hours = 8
                else:
                    reasons.append("Rain delays")
                    delay_hours = 4

        # Check temperature
        if forecast.low_temp < activity.min_temp:
            reasons.append(f"Too cold ({forecast.low_temp}°C)")
            delay_hours = max(delay_hours, 8 if activity.sensitivity == ActivitySensitivity.HIGH else 4)

        if forecast.high_temp > activity.max_temp:
            reasons.append(f"Too hot ({forecast.high_temp}°C)")
            delay_hours = max(delay_hours, 4)

        # Check wind
        if forecast.wind_speed_kmh > activity.max_wind:
            reasons.append(f"High wind ({forecast.wind_speed_kmh} km/h)")
            delay_hours = max(delay_hours, 8)

        if reasons:
            return WeatherImpact(
                activity_id=activity.activity_id,
                impact_date=forecast.forecast_date,
                reason="; ".join(reasons),
                delay_hours=delay_hours,
                recommendation=self._get_recommendation(activity, forecast)
            )
        return None

    def _get_recommendation(self, activity: ScheduleActivity,
                           forecast: WeatherForecast) -> str:
        if forecast.condition in [WeatherCondition.RAIN, WeatherCondition.HEAVY_RAIN]:
            return "Reschedule or plan indoor work"
        if forecast.low_temp < activity.min_temp:
            return "Use heating blankets or delay start"
        if forecast.high_temp > activity.max_temp:
            return "Start early, plan heat breaks"
        if forecast.wind_speed_kmh > activity.max_wind:
            return "Secure materials, delay crane work"
        return "Monitor conditions"

    def get_total_delay_forecast(self) -> Dict[str, Any]:
        total_hours = sum(i.delay_hours for i in self.impacts)
        by_activity = {}
        for impact in self.impacts:
            act = impact.activity_id
            by_activity[act] = by_activity.get(act, 0) + impact.delay_hours

        return {
            'total_impact_hours': total_hours,
            'total_impact_days': round(total_hours / 8, 1),
            'affected_activities': len(by_activity),
            'by_activity': by_activity,
            'impact_count': len(self.impac