Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Calculate embodied carbon in construction materials. Track CO2 emissions, compare alternatives, and generate sustainability reports.
.claude/skills/datadrivenconstruction-carbon-calculator/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 203% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 72% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 152% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 142% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 243% | 0% |
Sustainability requirements demand:
Calculate and track embodied carbon for construction materials using standard emission factors.
pythonimport pandas as pd from typing import Dict, Any, List, Optional from dataclasses import dataclass from enum import Enum class MaterialCategory(Enum): CONCRETE = "concrete" STEEL = "steel" ALUMINUM = "aluminum" TIMBER = "timber" BRICK = "brick" GLASS = "glass" INSULATION = "insulation" PLASTIC = "plastic" COPPER = "copper" OTHER = "other" @dataclass class CarbonFactor: material: str category: MaterialCategory ec_factor: float # kgCO2e per unit unit: str source: str @dataclass class MaterialInput: material_code: str material_name: str quantity: float unit: str category: MaterialCategory @dataclass class CarbonResult: material_code: str material_name: str quantity: float unit: str ec_factor: float embodied_carbon: float # kgCO2e category: str # Embodied carbon factors (kgCO2e per unit) CARBON_FACTORS = { # Concrete 'concrete_c20': CarbonFactor('Concrete C20', MaterialCategory.CONCRETE, 240, 'm3', 'ICE Database'), 'concrete_c30': CarbonFactor('Concrete C30', MaterialCategory.CONCRETE, 290, 'm3', 'ICE Database'), 'concrete_c40': CarbonFactor('Concrete C40', MaterialCategory.CONCRETE, 350, 'm3', 'ICE Database'), 'concrete_c50': CarbonFactor('Concrete C50', MaterialCategory.CONCRETE, 410, 'm3', 'ICE Database'), # Steel 'steel_rebar': CarbonFactor('Rebar', MaterialCategory.STEEL, 1.99, 'kg', 'ICE Database'), 'steel_section': CarbonFactor('Steel Section', MaterialCategory.STEEL, 1.55, 'kg', 'ICE Database'), 'steel_sheet': CarbonFactor('Steel Sheet', MaterialCategory.STEEL, 2.03, 'kg', 'ICE Database'), 'steel_stainless': CarbonFactor('Stainless Steel', MaterialCategory.STEEL, 6.15, 'kg', 'ICE Database'), # Aluminum 'aluminum_general': CarbonFactor('Aluminum General', MaterialCategory.ALUMINUM, 9.16, 'kg', 'ICE Database'), 'aluminum_recycled': CarbonFactor('Aluminum Recycled', MaterialCategory.ALUMINUM, 1.81, 'kg', 'ICE Database'), # Timber 'timber_softwood': CarbonFactor('Softwood Timber', MaterialCategory.TIMBER, 0.31, 'kg', 'ICE Database'), 'timber_hardwood': CarbonFactor('Hardwood Timber', MaterialCategory.TIMBER, 0.46, 'kg', 'ICE Database'), 'timber_glulam': CarbonFactor('Glulam', MaterialCategory.TIMBER, 0.51, 'kg', 'ICE Database'), 'timber_clt': CarbonFactor('CLT', MaterialCategory.TIMBER, 0.44, 'kg', 'ICE Database'), 'timber_plywood': CarbonFactor('Plywood', MaterialCategory.TIMBER, 0.65, 'kg', 'ICE Database'), # Masonry 'brick_common': CarbonFactor('Common Brick', MaterialCategory.BRICK, 0.24, 'kg', 'ICE Database'), 'block_concrete': CarbonFactor('Concrete Block', MaterialCategory.BRICK, 0.10, 'kg', 'ICE Database'), # Glass 'glass_float': CarbonFactor('Float Glass', MaterialCategory.GLASS, 1.44, 'kg', 'ICE Database'), 'glass_double': CarbonFactor('Double Glazing', MaterialCategory.GLASS, 35.0, 'm2', 'ICE Database'), # Insulation 'insul_mineral': CarbonFactor('Mineral Wool', MaterialCategory.INSULATION, 1.28, 'kg', 'ICE Database'), 'insul_eps': CarbonFactor('EPS', MaterialCategory.INSULATION, 3.29, 'kg', 'ICE Database'), 'insul_xps': CarbonFactor('XPS', MaterialCategory.INSULATION, 3.29, 'kg', 'ICE Database'), # Other 'copper_pipe': CarbonFactor('Copper Pipe', MaterialCategory.COPPER, 2.71, 'kg', 'ICE Database'), 'pvc_pipe': CarbonFactor('PVC Pipe', MaterialCategory.PLASTIC, 3.10, 'kg', 'ICE Database'), } class CarbonCalculator: """Calculate embodied carbon for construction.""" def __init__(self, project_name: str): self.project_name = project_name self.materials: List[MaterialInput] = [] self.results: List[CarbonResult] = [] self.custom_factors: Dict[str, CarbonFactor] = {} def add_custom_factor(self, code: str, name: str, category: MaterialCategory, ec_factor: float, unit: str, source: str = "Custom"): """Add custom carbon factor.""" self.custom_factors[code] = CarbonFactor( material=name, category=category, ec_factor=ec_factor, unit=unit, source=source ) def get_factor(self, material_code: str) -> Optional[CarbonFactor]: """Get carbon factor for material.""" # Check custom first if material_code in self.custom_factors: return self.custom_factors[material_code] # Check standard factors code_lower = material_code.lower().replace('-', '_').replace(' ', '_') return CARBON_FACTORS.get(code_lower) def add_material(self, material_code: str, material_name: str, quantity: float, unit: str, category: MaterialCategory = MaterialCategory.OTHER): """Add material to calculation.""" self.materials.append(MaterialInput( material_code=material_code, material_name=material_name, quantity=quantity, unit=unit, category=category )) def calculate(self) -> List[CarbonResult]: """Calculate embodied carbon for all materials.""" self.results = [] for mat in self.materials: factor = self.get_factor(mat.material_code) if factor: # Check unit compatibility if factor.unit == mat.unit: ec = mat.quantity * factor.ec_factor else: # Assume conversion needed - simplified ec = mat.quantity * factor.ec_factor else: # Use default factor based on category default_factors = { MaterialCategory.CONCRETE: 300, MaterialCategory.STEEL: 1.8, MaterialCategory.ALUMINUM: 9.0, MaterialCategory.TIMBER: 0.4, MaterialCategory.BRICK: 0.2, MaterialCategory.GLASS: 1.5, MaterialCategory.INSULATION: 2.0, MaterialCategory.OTHER: 1.0 } ec_factor = default_factors.get(mat.category, 1.0) ec = mat.quantity * ec_factor self.results.append(CarbonResult( material_code=mat.material_code, material_name=mat.material_name, quantity=mat.quantity, unit=mat.unit, ec_factor=factor.ec_factor if factor else 0, embodied_carbon=round(ec, 2), category=mat.category.value )) return self.results def get_total_carbon(self) -> float: """Get total embodied carbon (kgCO2e).""" return sum(r.embodied_carbon for r in self.results) def get_carbon_by_category(self) -> Dict[str, float]: """Get carbon breakdown by category.""" by_category = {} for r in self.results: if r.category not in by_category: by_category[r.category] = 0 by_category[r.category] += r.embodied_carbon return {k: round(v, 2) for k, v in by_category.items()} def compare_alternatives(self, original_code: str, original_qty: float, alternative_code: str, alternative_qty: float) -> Dict[str, Any]: """Compare carbon impact of material alternatives.""" original_factor = self.get_factor(original_code) alt_factor = self.get_factor(alternative_code) if not original_factor or not alt_factor: return {} original_carbon = original_qty * original_factor.ec_factor alt_carbon = alternative_qty * alt_factor.ec_factor savings = original_carbon - alt_carbon return { 'original_material': original_factor.material, 'original_carbon': round(original_carbon, 2), 'alternative_material': alt_factor.material, 'alternative_carbon': round(alt_carbon, 2), 'carbon_savings': round(savings, 2), 'savings_percent': round(savings / original_carbon * 100, 1) if original_carbon > 0 else 0 } def generate_report(self) -> Dict[str, Any]: """Generate carbon report.""" if not self.results: self.calculate() total = self.get_total_carbon() by_category = self.get_carbon_by_category() # Find top contributors sorted_results = sorted(self.results, key=lambda x: x.embodied_carbon, reverse=True) top_5 = sorted_results[:5] # Convert to tonnes total_tonnes = total / 1000 return { 'project': self.project_name, 'total_kgCO2e': round(total, 2), 'total_tCO2e': round(total_tonnes, 2), 'material_count': len(self.results), 'by_category': by_category, 'top_contributors': [ { 'material': r.material_name, 'carbon': r.embodied_carbon, 'percentage': round(r.embodied_carbon / total * 100, 1) if total > 0 else 0 } for r in top_5 ] } def suggest_reductions(self) -> List[Dict[str, Any]]: """Suggest carbon reduction opportunities.""" if not self.results: self.calculate() suggestions = [] for r in self.results: # Steel -> Timber if r.category == 'steel' and r.embodied_carbon > 1000: suggestions.append({ 'material': r.material_name, 'current_carbon': r.embodied_carbon, 'suggestion': 'Consider timber alternative where structurally feasible', 'potential_reduction': '60-80%' }) # Standard concrete -> Low carbon if r.category == 'concrete' and r.embodied_carbon > 5000: suggestions.append({ 'material': r.material_name, 'current_carbon': r.embodied_carbon, 'suggestion': 'Use low-carbon concrete mix with SCMs', 'potential_reduction': '20-40%' }) # Virgin aluminum -> Recycled if r.category == 'aluminum': suggestions.append({ 'material': r.material_name, 'current_carbon': r.embodied_carbon, 'suggestion': 'Specify recycled aluminum content', 'potential_reduction': '70-80%' }) return suggestions def export_to_excel(self, output_path: str) -> str: """Export carbon calculation to Excel.""" if not self.results: self.calculate() report = self.generate_report() with pd.ExcelWriter(output_path, engine='openpyxl') as writer: # Summary summary_df = pd.DataFrame([{ 'Project': self.project_name, 'Total kgCO2e': report['total_kgCO2e'], 'Total tCO2e': report['total_tCO2e'], 'Materials': report['material_count'] }]) summary_df.to_excel(writer, sheet_name='Summary', index=False) # Details details_df = pd.DataFrame([ { 'Material Code': r.material_code, 'Material': r.material_name, 'Quantity': r.quantity, 'Unit': r.unit, 'EC Factor': r.ec_factor, 'Embodied Carbon (kgCO2e)': r.embodied_carbon, 'Category': r.category } for r in self.results ]) details_df.to_excel(writer, sheet_name='Materials', index=False) # By Category cat_df = pd.DataFrame([ {'Category': k, 'kgCO2e': v} for k, v in report['by_category'].items() ]) cat_df.to_excel(writer, sheet_name='By Category', index=False) # Suggestions suggestions = self.suggest_reductions() if suggestions: sug_df = pd.DataFrame(suggestions) sug_df.to_excel(writer, sheet_name='Reduction Ideas', index=False) return output_path
python# Initialize calculator calc = CarbonCalculator("Office Building A") # Add materials calc.add_material("concrete_c30", "Foundation Concrete", 500, "m3", MaterialCategory.CONCRETE) calc.add_material("steel_rebar", "Reinforcement", 50000, "kg", MaterialCategory.STEEL) calc.add_material("steel_section", "Structural Steel", 200000, "kg", MaterialCategory.STEEL) calc.add_material("glass_double", "Facade Glazing", 1500, "m2", MaterialCategory.GLASS) # Calculate results = calc.calculate() # Get report report = calc.generate_report() print(f"Total: {report['total_tCO2e']} tCO2e")
pythoncomparison = calc.compare_alternatives( "steel_section", 100000, "timber_glulam", 80000 ) print(f"Savings: {comparison['savings_percent']}%")
pythonsuggestions = calc.suggest_reductions() for s in suggestions: print(f"{s['material']}: {s['suggestion']}")
pythonby_category = calc.get_carbon_by_category() for cat, carbon in by_category.items(): print(f"{cat}: {carbon:,.0f} kgCO2e")
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 23,968 | 12,173 | -49% | 1 | 1 | 0% | 1,994 | 6,048 | +203% | 0 | 0 | — |
case-02 | fail→pass | 26,449 | 6,210 | -77% | 1 | 1 | 0% | 2,979 | 5,136 | +72% | 0 | 0 | — |
case-03 | fail→fail | 11,791 | 12,386 | +5% | 1 | 1 | 0% | 2,113 | 6,047 | +186% | 0 | 0 | — |
case-04 | pass→pass | 13,667 | 12,615 | -8% | 1 | 1 | 0% | 2,918 | 6,357 | +118% | 0 | 0 | — |
case-05 | pass→pass | 16,199 | 18,520 | +14% | 1 | 1 | 0% | 3,401 | 7,840 | +131% | 0 | 0 | — |
case-06 | pass→pass | 3,405 | 2,316 | -32% | 1 | 1 | 0% | 740 | 4,352 | +488% | 0 | 0 | — |
case-07 | pass→pass | 7,711 | 6,633 | -14% | 1 | 1 | 0% | 1,533 | 5,308 | +246% | 0 | 0 | — |
case-08 | fail→pass | 12,214 | 8,771 | -28% | 1 | 1 | 0% | 2,241 | 5,653 | +152% | 0 | 0 | — |
case-09 | fail→pass | 14,788 | 11,273 | -24% | 1 | 1 | 0% | 2,521 | 6,110 | +142% | 0 | 0 | — |
case-10 | fail→pass | 9,560 | 8,812 | -8% | 1 | 1 | 0% | 1,627 | 5,581 | +243% | 0 | 0 | — |
case-11 | fail→pass | 10,166 | 3,343 | -67% | 1 | 1 | 0% | 2,072 | 4,492 | +117% | 0 | 0 | — |
case-12 | pass→pass | 9,004 | 4,902 | -46% | 1 | 1 | 0% | 1,681 | 4,738 | +182% | 0 | 0 | — |
case-13 | fail→pass | 15,247 | 5,235 | -66% | 1 | 1 | 0% | 2,968 | 4,880 | +64% | 0 | 0 | — |
case-14 | pass→pass | 8,676 | 3,870 | -55% | 1 | 1 | 0% | 1,684 | 4,517 | +168% | 0 | 0 | — |
case-15 | pass→pass | 9,437 | 4,083 | -57% | 1 | 1 | 0% | 1,749 | 4,613 | +164% | 0 | 0 | — |
case-16 | fail→pass | 8,133 | 3,851 | -53% | 1 | 1 | 0% | 1,469 | 4,590 | +212% | 0 | 0 | — |
case-17 | fail→pass | 9,969 | 2,939 | -71% | 1 | 1 | 0% | 1,611 | 4,409 | +174% | 0 | 0 | — |
case-18 | pass→pass | 11,921 | 5,143 | -57% | 1 | 1 | 0% | 2,141 | 4,883 | +128% | 0 | 0 | — |
case-19 | fail→pass | 10,413 | 4,948 | -52% | 1 | 1 | 0% | 2,188 | 4,931 | +125% | 0 | 0 | — |
case-20 | fail→pass | 15,577 | 7,375 | -53% | 1 | 1 | 0% | 2,795 | 5,435 | +94% | 0 | 0 | — |
case-21 | pass→pass | 8,321 | 4,672 | -44% | 1 | 1 | 0% | 1,671 | 4,741 | +184% | 0 | 0 | — |
case-22 | pass→pass | 8,022 | 3,901 | -51% | 1 | 1 | 0% | 1,597 | 4,621 | +189% | 0 | 0 | — |
case-23 | fail→pass | 7,914 | 3,928 | -50% | 1 | 1 | 0% | 1,497 | 4,544 | +204% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted, and 22 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +52 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.