cwicr-escalation
Apply price escalation to CWICR estimates over time. Calculate inflation adjustments, material price indices, and labor rate increases.
What this skill does
# CWICR Escalation Calculator
## Business Case
### Problem Statement
Construction costs change over time:
- Inflation affects all costs
- Material prices fluctuate
- Labor rates increase annually
- Long projects need escalation
### Solution
Time-based cost escalation using historical indices, projected rates, and category-specific escalation factors.
### Business Value
- **Future pricing** - Estimate costs at construction time
- **Budget planning** - Account for inflation
- **Contract pricing** - Escalation clauses
- **Historical analysis** - Adjust past costs to current
## Technical Implementation
```python
import pandas as pd
import numpy as np
from typing import Dict, Any, List, Optional, Tuple
from dataclasses import dataclass
from datetime import datetime, date
from dateutil.relativedelta import relativedelta
from enum import Enum
class EscalationType(Enum):
"""Types of escalation."""
LABOR = "labor"
MATERIAL = "material"
EQUIPMENT = "equipment"
GENERAL = "general"
@dataclass
class EscalationIndex:
"""Escalation index for a period."""
period: str # YYYY-MM
labor_index: float
material_index: float
equipment_index: float
general_index: float
@dataclass
class EscalationResult:
"""Result of escalation calculation."""
base_cost: float
base_date: date
target_date: date
months: int
escalation_rate: float
escalation_amount: float
escalated_cost: float
by_category: Dict[str, Dict[str, float]]
# Historical escalation rates (annual %)
HISTORICAL_RATES = {
2020: {'labor': 2.5, 'material': 1.8, 'equipment': 1.5, 'general': 2.0},
2021: {'labor': 3.2, 'material': 8.5, 'equipment': 2.0, 'general': 4.5},
2022: {'labor': 4.5, 'material': 12.0, 'equipment': 3.5, 'general': 7.0},
2023: {'labor': 4.0, 'material': 5.0, 'equipment': 3.0, 'general': 4.0},
2024: {'labor': 3.5, 'material': 3.0, 'equipment': 2.5, 'general': 3.0},
2025: {'labor': 3.0, 'material': 2.5, 'equipment': 2.0, 'general': 2.5},
}
# Material-specific escalation factors
MATERIAL_ESCALATION = {
'steel': 1.20, # Higher volatility
'lumber': 1.30, # High volatility
'concrete': 0.90, # Lower volatility
'copper': 1.25, # Commodity driven
'aluminum': 1.15,
'plastic': 1.10,
'glass': 0.95,
'default': 1.00
}
class CWICREscalation:
"""Calculate cost escalation over time."""
def __init__(self,
cwicr_data: pd.DataFrame = None,
custom_rates: Dict[int, Dict[str, float]] = None):
self.cost_data = cwicr_data
self.rates = custom_rates or HISTORICAL_RATES
if cwicr_data is not None:
self._index_data()
def _index_data(self):
"""Index cost data."""
if 'work_item_code' in self.cost_data.columns:
self._code_index = self.cost_data.set_index('work_item_code')
else:
self._code_index = None
def get_rate(self,
year: int,
category: EscalationType = EscalationType.GENERAL) -> float:
"""Get escalation rate for year and category."""
year_rates = self.rates.get(year, self.rates.get(max(self.rates.keys())))
return year_rates.get(category.value, year_rates.get('general', 3.0))
def calculate_compound_factor(self,
base_date: date,
target_date: date,
category: EscalationType = EscalationType.GENERAL) -> float:
"""Calculate compound escalation factor between dates."""
if target_date <= base_date:
return 1.0
factor = 1.0
current = base_date
while current < target_date:
year = current.year
annual_rate = self.get_rate(year, category) / 100
# Calculate months in this year
year_end = date(year + 1, 1, 1)
if target_date < year_end:
months = (target_date.year - current.year) * 12 + target_date.month - current.month
else:
months = (year_end.year - current.year) * 12 + year_end.month - current.month
# Apply monthly compound rate
monthly_rate = (1 + annual_rate) ** (1/12) - 1
factor *= (1 + monthly_rate) ** months
current = year_end
return factor
def escalate_cost(self,
base_cost: float,
base_date: date,
target_date: date,
cost_breakdown: Dict[str, float] = None) -> EscalationResult:
"""Escalate cost from base date to target date."""
if cost_breakdown is None:
cost_breakdown = {
'labor': base_cost * 0.40,
'material': base_cost * 0.45,
'equipment': base_cost * 0.15
}
months = (target_date.year - base_date.year) * 12 + target_date.month - base_date.month
# Escalate each category
by_category = {}
total_escalated = 0
for category, amount in cost_breakdown.items():
esc_type = EscalationType.LABOR if category == 'labor' else \
EscalationType.MATERIAL if category == 'material' else \
EscalationType.EQUIPMENT if category == 'equipment' else \
EscalationType.GENERAL
factor = self.calculate_compound_factor(base_date, target_date, esc_type)
escalated = amount * factor
escalation = escalated - amount
by_category[category] = {
'base': round(amount, 2),
'factor': round(factor, 4),
'escalated': round(escalated, 2),
'escalation': round(escalation, 2)
}
total_escalated += escalated
total_escalation = total_escalated - base_cost
esc_rate = (total_escalation / base_cost * 100) if base_cost > 0 else 0
return EscalationResult(
base_cost=round(base_cost, 2),
base_date=base_date,
target_date=target_date,
months=months,
escalation_rate=round(esc_rate, 2),
escalation_amount=round(total_escalation, 2),
escalated_cost=round(total_escalated, 2),
by_category=by_category
)
def escalate_estimate(self,
items: List[Dict[str, Any]],
base_date: date,
target_date: date) -> Dict[str, Any]:
"""Escalate entire estimate."""
escalated_items = []
total_base = 0
total_escalated = 0
for item in items:
code = item.get('work_item_code', item.get('code'))
qty = item.get('quantity', 0)
# Get costs from CWICR
labor = 0
material = 0
equipment = 0
if self._code_index is not None and code in self._code_index.index:
wi = self._code_index.loc[code]
labor = float(wi.get('labor_cost', 0) or 0) * qty
material = float(wi.get('material_cost', 0) or 0) * qty
equipment = float(wi.get('equipment_cost', 0) or 0) * qty
base = labor + material + equipment
breakdown = {'labor': labor, 'material': material, 'equipment': equipment}
result = self.escalate_cost(base, base_date, target_date, breakdown)
escalated_items.append({
'code': code,
'base_cost': result.base_cost,
'escalated_cost': result.escalated_cost,
'escalation': result.escalation_amount
})
total_base += base
total_escalated += result.escalated_cost
return {
'items': escalated_items,
'total_base': round(total_base, 2),
'total_escalated': roRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.