labor-rate

Labor Rate Calculator

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "labor-rate" with this command: npx skills add datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/datadrivenconstruction-ddc-skills-for-ai-agents-in-construction-labor-rate

Labor Rate Calculator

Overview

Labor costs account for 30-50% of construction costs. This skill calculates all-in labor rates including wages, benefits, overhead, and regional adjustments.

Python Implementation

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

class LaborCategory(Enum): """Labor skill categories.""" LABORER = "laborer" CARPENTER = "carpenter" ELECTRICIAN = "electrician" PLUMBER = "plumber" IRONWORKER = "ironworker" MASON = "mason" OPERATOR = "equipment_operator" FOREMAN = "foreman" SUPERINTENDENT = "superintendent"

class WorkType(Enum): """Work type for productivity.""" NEW_CONSTRUCTION = "new" RENOVATION = "renovation" DEMOLITION = "demolition" MAINTENANCE = "maintenance"

@dataclass class LaborRate: """Complete labor rate breakdown.""" category: str base_wage: float benefits: float taxes: float insurance: float overhead: float profit: float total_rate: float unit: str = "hour"

@dataclass class CrewComposition: """Crew composition for work.""" name: str workers: List[Dict[str, Any]] total_hourly_cost: float output_per_hour: float unit: str

class LaborRateCalculator: """Calculate construction labor rates."""

# Default burden rates (percent of base wage)
DEFAULT_BURDENS = {
    'benefits': 0.30,        # Health, pension, vacation
    'taxes': 0.10,           # FICA, unemployment
    'insurance': 0.08,       # Workers comp, liability
    'overhead': 0.15,        # General conditions
    'profit': 0.10           # Contractor profit
}

# Base wages by category (USD/hour, US average)
BASE_WAGES = {
    LaborCategory.LABORER: 22,
    LaborCategory.CARPENTER: 32,
    LaborCategory.ELECTRICIAN: 38,
    LaborCategory.PLUMBER: 36,
    LaborCategory.IRONWORKER: 35,
    LaborCategory.MASON: 34,
    LaborCategory.OPERATOR: 40,
    LaborCategory.FOREMAN: 45,
    LaborCategory.SUPERINTENDENT: 55
}

# Regional factors
REGIONAL_FACTORS = {
    'US_National': 1.00,
    'New_York': 1.45,
    'San_Francisco': 1.40,
    'Chicago': 1.15,
    'Houston': 0.95,
    'Atlanta': 0.90,
    'Germany_Berlin': 1.20,
    'UK_London': 1.35
}

def __init__(self, burden_rates: Dict[str, float] = None):
    self.burdens = burden_rates or self.DEFAULT_BURDENS

def calculate_rate(self, category: LaborCategory,
                   region: str = 'US_National',
                   custom_wage: float = None) -> LaborRate:
    """Calculate all-in labor rate."""

    # Get base wage
    base = custom_wage or self.BASE_WAGES.get(category, 25)

    # Apply regional factor
    regional_factor = self.REGIONAL_FACTORS.get(region, 1.0)
    base *= regional_factor

    # Calculate burden components
    benefits = base * self.burdens['benefits']
    taxes = base * self.burdens['taxes']
    insurance = base * self.burdens['insurance']

    # Subtotal before markup
    subtotal = base + benefits + taxes + insurance

    # Overhead and profit
    overhead = subtotal * self.burdens['overhead']
    profit = (subtotal + overhead) * self.burdens['profit']

    total = subtotal + overhead + profit

    return LaborRate(
        category=category.value,
        base_wage=round(base, 2),
        benefits=round(benefits, 2),
        taxes=round(taxes, 2),
        insurance=round(insurance, 2),
        overhead=round(overhead, 2),
        profit=round(profit, 2),
        total_rate=round(total, 2)
    )

def calculate_crew_cost(self, composition: Dict[LaborCategory, int],
                        region: str = 'US_National') -> float:
    """Calculate hourly cost for crew composition."""

    total = 0
    for category, count in composition.items():
        rate = self.calculate_rate(category, region)
        total += rate.total_rate * count

    return round(total, 2)

def get_rate_table(self, region: str = 'US_National') -> pd.DataFrame:
    """Generate rate table for all categories."""

    rates = []
    for category in LaborCategory:
        rate = self.calculate_rate(category, region)
        rates.append({
            'category': rate.category,
            'base_wage': rate.base_wage,
            'benefits': rate.benefits,
            'taxes': rate.taxes,
            'insurance': rate.insurance,
            'overhead': rate.overhead,
            'profit': rate.profit,
            'total_rate': rate.total_rate
        })

    return pd.DataFrame(rates)

class ProductivityFactor: """Calculate productivity factors for labor."""

# Base productivity factors
WORK_TYPE_FACTORS = {
    WorkType.NEW_CONSTRUCTION: 1.0,
    WorkType.RENOVATION: 0.75,
    WorkType.DEMOLITION: 0.90,
    WorkType.MAINTENANCE: 0.65
}

# Condition factors
CONDITION_FACTORS = {
    'ideal': 1.0,
    'normal': 0.90,
    'difficult': 0.75,
    'hazardous': 0.60,
    'confined_space': 0.50
}

# Weather factors
WEATHER_FACTORS = {
    'clear': 1.0,
    'hot': 0.85,
    'cold': 0.80,
    'rain': 0.60,
    'wind': 0.75
}

def calculate_factor(self, work_type: WorkType,
                     condition: str = 'normal',
                     weather: str = 'clear',
                     overtime_hours: int = 0) -> float:
    """Calculate combined productivity factor."""

    base = self.WORK_TYPE_FACTORS.get(work_type, 1.0)
    cond = self.CONDITION_FACTORS.get(condition, 0.9)
    weath = self.WEATHER_FACTORS.get(weather, 1.0)

    # Overtime degradation (productivity drops after 8 hours)
    overtime_factor = 1.0
    if overtime_hours > 0:
        # Each OT hour is ~15% less productive
        overtime_factor = 1 - (overtime_hours * 0.015)

    combined = base * cond * weath * overtime_factor
    return round(max(combined, 0.3), 2)  # Minimum 30% productivity

def adjust_labor_hours(self, base_hours: float,
                       work_type: WorkType,
                       condition: str = 'normal',
                       weather: str = 'clear') -> float:
    """Adjust labor hours for conditions."""

    factor = self.calculate_factor(work_type, condition, weather)
    return round(base_hours / factor, 1)

class CrewBuilder: """Build and optimize crew compositions."""

# Standard crew compositions
STANDARD_CREWS = {
    'concrete_pour': {
        LaborCategory.FOREMAN: 1,
        LaborCategory.CARPENTER: 2,
        LaborCategory.LABORER: 4,
        LaborCategory.OPERATOR: 1
    },
    'framing': {
        LaborCategory.FOREMAN: 1,
        LaborCategory.CARPENTER: 4,
        LaborCategory.LABORER: 2
    },
    'electrical_rough': {
        LaborCategory.FOREMAN: 1,
        LaborCategory.ELECTRICIAN: 3,
        LaborCategory.LABORER: 1
    },
    'plumbing_rough': {
        LaborCategory.FOREMAN: 1,
        LaborCategory.PLUMBER: 2,
        LaborCategory.LABORER: 1
    },
    'masonry': {
        LaborCategory.FOREMAN: 1,
        LaborCategory.MASON: 4,
        LaborCategory.LABORER: 4
    }
}

def __init__(self, rate_calculator: LaborRateCalculator):
    self.calc = rate_calculator

def get_crew(self, work_type: str,
             region: str = 'US_National') -> CrewComposition:
    """Get standard crew composition with costs."""

    if work_type not in self.STANDARD_CREWS:
        raise ValueError(f"Unknown work type: {work_type}")

    composition = self.STANDARD_CREWS[work_type]
    total_cost = self.calc.calculate_crew_cost(composition, region)

    workers = []
    for category, count in composition.items():
        rate = self.calc.calculate_rate(category, region)
        workers.append({
            'category': category.value,
            'count': count,
            'hourly_rate': rate.total_rate,
            'subtotal': rate.total_rate * count
        })

    return CrewComposition(
        name=work_type,
        workers=workers,
        total_hourly_cost=total_cost,
        output_per_hour=1.0,  # Placeholder
        unit='hour'
    )

def custom_crew(self, workers: Dict[LaborCategory, int],
                region: str = 'US_National') -> CrewComposition:
    """Build custom crew composition."""

    total_cost = self.calc.calculate_crew_cost(workers, region)

    worker_list = []
    for category, count in workers.items():
        rate = self.calc.calculate_rate(category, region)
        worker_list.append({
            'category': category.value,
            'count': count,
            'hourly_rate': rate.total_rate,
            'subtotal': rate.total_rate * count
        })

    return CrewComposition(
        name='custom',
        workers=worker_list,
        total_hourly_cost=total_cost,
        output_per_hour=1.0,
        unit='hour'
    )

Quick Start

calc = LaborRateCalculator()

Get single rate

rate = calc.calculate_rate(LaborCategory.CARPENTER, region='New_York') print(f"Carpenter rate NYC: ${rate.total_rate}/hr")

Rate table

rates = calc.get_rate_table('US_National') print(rates)

Common Use Cases

  1. Crew Cost

builder = CrewBuilder(calc) concrete_crew = builder.get_crew('concrete_pour', 'Chicago') print(f"Crew cost: ${concrete_crew.total_hourly_cost}/hr")

  1. Productivity Adjustment

productivity = ProductivityFactor() factor = productivity.calculate_factor( WorkType.RENOVATION, condition='difficult', weather='hot' ) adjusted_hours = productivity.adjust_labor_hours(100, WorkType.RENOVATION)

Resources

  • DDC Book: Chapter 3.1 - Resource-Based Costing

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

cad-to-data

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

drawing-analyzer

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

cost-estimation-resource

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

daily-progress-report

No summary provided by upstream source.

Repository SourceNeeds Review