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

cwicr-location-factor

Apply geographic location factors to CWICR estimates. Adjust costs for regional labor rates, material prices, and market conditions.

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

SKILL.md

# CWICR Location Factor

## Business Case

### Problem Statement
Construction costs vary by location:
- Labor rates differ by region
- Material prices vary geographically
- Market conditions affect costs
- Remote locations have premiums

### Solution
Apply location-based cost factors to CWICR estimates, adjusting for regional differences in labor, materials, and overall market conditions.

### Business Value
- **Regional accuracy** - Location-specific estimates
- **Market awareness** - Current conditions
- **Comparison support** - Normalize across locations
- **Planning** - Multi-location projects

## Technical Implementation

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


class CostComponent(Enum):
    """Cost components for factors."""
    LABOR = "labor"
    MATERIAL = "material"
    EQUIPMENT = "equipment"
    TOTAL = "total"


@dataclass
class LocationFactor:
    """Location adjustment factor."""
    location_code: str
    location_name: str
    country: str
    region: str
    labor_factor: float
    material_factor: float
    equipment_factor: float
    total_factor: float
    currency: str
    notes: str = ""


@dataclass
class AdjustedEstimate:
    """Estimate with location adjustment."""
    base_cost: float
    base_location: str
    target_location: str
    labor_adjustment: float
    material_adjustment: float
    equipment_adjustment: float
    total_adjustment: float
    adjusted_cost: float
    adjustment_percent: float


# Location factors (relative to US national average = 1.00)
LOCATION_FACTORS = {
    # USA
    'US-NYC': LocationFactor('US-NYC', 'New York City', 'USA', 'Northeast', 1.35, 1.15, 1.10, 1.22, 'USD'),
    'US-LA': LocationFactor('US-LA', 'Los Angeles', 'USA', 'West', 1.25, 1.10, 1.05, 1.15, 'USD'),
    'US-CHI': LocationFactor('US-CHI', 'Chicago', 'USA', 'Midwest', 1.20, 1.05, 1.05, 1.12, 'USD'),
    'US-HOU': LocationFactor('US-HOU', 'Houston', 'USA', 'South', 0.95, 0.98, 0.95, 0.96, 'USD'),
    'US-PHX': LocationFactor('US-PHX', 'Phoenix', 'USA', 'Southwest', 0.90, 0.95, 0.95, 0.93, 'USD'),
    'US-DEN': LocationFactor('US-DEN', 'Denver', 'USA', 'Mountain', 1.00, 1.02, 1.00, 1.01, 'USD'),
    'US-SEA': LocationFactor('US-SEA', 'Seattle', 'USA', 'Northwest', 1.18, 1.08, 1.05, 1.12, 'USD'),
    'US-MIA': LocationFactor('US-MIA', 'Miami', 'USA', 'Southeast', 0.98, 1.05, 1.00, 1.01, 'USD'),
    'US-ATL': LocationFactor('US-ATL', 'Atlanta', 'USA', 'Southeast', 0.92, 0.98, 0.95, 0.95, 'USD'),
    'US-NAT': LocationFactor('US-NAT', 'US National Average', 'USA', 'National', 1.00, 1.00, 1.00, 1.00, 'USD'),

    # Europe
    'UK-LON': LocationFactor('UK-LON', 'London', 'UK', 'Southeast', 1.45, 1.20, 1.15, 1.30, 'GBP'),
    'DE-BER': LocationFactor('DE-BER', 'Berlin', 'Germany', 'East', 1.15, 1.10, 1.10, 1.12, 'EUR'),
    'DE-MUN': LocationFactor('DE-MUN', 'Munich', 'Germany', 'South', 1.25, 1.15, 1.12, 1.18, 'EUR'),
    'FR-PAR': LocationFactor('FR-PAR', 'Paris', 'France', 'Ile-de-France', 1.30, 1.18, 1.15, 1.22, 'EUR'),
    'NL-AMS': LocationFactor('NL-AMS', 'Amsterdam', 'Netherlands', 'North Holland', 1.20, 1.12, 1.10, 1.15, 'EUR'),

    # Middle East
    'AE-DXB': LocationFactor('AE-DXB', 'Dubai', 'UAE', 'Dubai', 0.85, 1.25, 1.10, 1.05, 'AED'),
    'SA-RIY': LocationFactor('SA-RIY', 'Riyadh', 'Saudi Arabia', 'Central', 0.80, 1.20, 1.05, 1.00, 'SAR'),
    'QA-DOH': LocationFactor('QA-DOH', 'Doha', 'Qatar', 'Qatar', 0.88, 1.30, 1.12, 1.08, 'QAR'),

    # Asia
    'SG-SIN': LocationFactor('SG-SIN', 'Singapore', 'Singapore', 'Central', 1.10, 1.15, 1.08, 1.12, 'SGD'),
    'HK-HKG': LocationFactor('HK-HKG', 'Hong Kong', 'Hong Kong', 'Hong Kong', 1.20, 1.25, 1.15, 1.20, 'HKD'),
    'JP-TKY': LocationFactor('JP-TKY', 'Tokyo', 'Japan', 'Kanto', 1.35, 1.20, 1.18, 1.25, 'JPY'),

    # Australia
    'AU-SYD': LocationFactor('AU-SYD', 'Sydney', 'Australia', 'NSW', 1.25, 1.15, 1.12, 1.18, 'AUD'),
    'AU-MEL': LocationFactor('AU-MEL', 'Melbourne', 'Australia', 'Victoria', 1.20, 1.12, 1.10, 1.15, 'AUD'),
}


class CWICRLocationFactor:
    """Apply location factors to CWICR estimates."""

    def __init__(self,
                 cwicr_data: pd.DataFrame = None,
                 base_location: str = 'US-NAT'):
        self.cwicr = cwicr_data
        self.base_location = base_location
        self._factors = LOCATION_FACTORS.copy()

        if cwicr_data is not None:
            self._index_cwicr()

    def _index_cwicr(self):
        """Index CWICR data."""
        if 'work_item_code' in self.cwicr.columns:
            self._cwicr_index = self.cwicr.set_index('work_item_code')
        else:
            self._cwicr_index = None

    def get_factor(self, location_code: str) -> Optional[LocationFactor]:
        """Get location factor."""
        return self._factors.get(location_code)

    def list_locations(self, country: str = None) -> List[Dict[str, Any]]:
        """List available locations."""
        factors = self._factors.values()

        if country:
            factors = [f for f in factors if f.country.lower() == country.lower()]

        return [
            {
                'code': f.location_code,
                'name': f.location_name,
                'country': f.country,
                'region': f.region,
                'total_factor': f.total_factor,
                'currency': f.currency
            }
            for f in factors
        ]

    def add_location(self, factor: LocationFactor):
        """Add custom location factor."""
        self._factors[factor.location_code] = factor

    def adjust_cost(self,
                    base_cost: float,
                    target_location: str,
                    cost_breakdown: Dict[str, float] = None) -> AdjustedEstimate:
        """Adjust cost from base to target location."""

        base_factor = self._factors.get(self.base_location)
        target_factor = self._factors.get(target_location)

        if not base_factor or n