<< All versions
Skill v1.0.0
currentAutomated scan100/100datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/cwicr-unit-converter
──Details
PublishedSeptember 29, 2026 at 06:09 AM
Content Hashsha256:d4e1a5c62fbcde08...
Git SHAce45bbfbdd63
──Files
Files (1 file, 17.1 KB)
SKILL.md17.1 KBactive
SKILL.md · 441 lines · 17.1 KB
version: "1.0.0" name: "cwicr-unit-converter" description: "Convert between construction measurement units. Handle metric/imperial conversion, area/volume calculations, and unit normalization for CWICR data." homepage: "https://datadrivenconstruction.io" metadata: {"openclaw": {"emoji": "🗄️", "os": ["darwin", "linux", "win32"], "homepage": "https://datadrivenconstruction.io", "requires": {"bins": ["python3"]}}}
CWICR Unit Converter
Business Case
Problem Statement
Construction data comes in various unit systems:
- Metric vs Imperial measurements
- Different unit conventions by trade
- BIM quantities need normalization
- Regional standards differ
Solution
Comprehensive unit conversion for construction quantities, normalizing data for CWICR integration and analysis.
Business Value
- Accuracy - Eliminate unit conversion errors
- Consistency - Standardize across projects
- Integration - BIM to cost data alignment
- Global - Support international projects
Technical Implementation
python
import pandas as pdimport numpy as npfrom typing import Dict, Any, List, Optional, Tuple, Unionfrom dataclasses import dataclassfrom enum import Enumclass UnitCategory(Enum):"""Categories of measurement units."""LENGTH = "length"AREA = "area"VOLUME = "volume"WEIGHT = "weight"TIME = "time"QUANTITY = "quantity"class UnitSystem(Enum):"""Unit systems."""METRIC = "metric"IMPERIAL = "imperial"MIXED = "mixed"@dataclassclass UnitConversion:"""Unit conversion result."""original_value: floatoriginal_unit: strconverted_value: floattarget_unit: strconversion_factor: floatcategory: UnitCategory# Conversion factors to base units# Base units: meter (length), m² (area), m³ (volume), kg (weight), hour (time)CONVERSIONS = {# Length to meters'm': {'factor': 1.0, 'category': UnitCategory.LENGTH, 'base': 'm'},'meter': {'factor': 1.0, 'category': UnitCategory.LENGTH, 'base': 'm'},'meters': {'factor': 1.0, 'category': UnitCategory.LENGTH, 'base': 'm'},'cm': {'factor': 0.01, 'category': UnitCategory.LENGTH, 'base': 'm'},'mm': {'factor': 0.001, 'category': UnitCategory.LENGTH, 'base': 'm'},'km': {'factor': 1000.0, 'category': UnitCategory.LENGTH, 'base': 'm'},'ft': {'factor': 0.3048, 'category': UnitCategory.LENGTH, 'base': 'm'},'feet': {'factor': 0.3048, 'category': UnitCategory.LENGTH, 'base': 'm'},'foot': {'factor': 0.3048, 'category': UnitCategory.LENGTH, 'base': 'm'},'in': {'factor': 0.0254, 'category': UnitCategory.LENGTH, 'base': 'm'},'inch': {'factor': 0.0254, 'category': UnitCategory.LENGTH, 'base': 'm'},'inches': {'factor': 0.0254, 'category': UnitCategory.LENGTH, 'base': 'm'},'yd': {'factor': 0.9144, 'category': UnitCategory.LENGTH, 'base': 'm'},'yard': {'factor': 0.9144, 'category': UnitCategory.LENGTH, 'base': 'm'},'yards': {'factor': 0.9144, 'category': UnitCategory.LENGTH, 'base': 'm'},'mi': {'factor': 1609.344, 'category': UnitCategory.LENGTH, 'base': 'm'},'mile': {'factor': 1609.344, 'category': UnitCategory.LENGTH, 'base': 'm'},'lf': {'factor': 0.3048, 'category': UnitCategory.LENGTH, 'base': 'm'}, # Linear foot# Area to m²'m2': {'factor': 1.0, 'category': UnitCategory.AREA, 'base': 'm2'},'m²': {'factor': 1.0, 'category': UnitCategory.AREA, 'base': 'm2'},'sqm': {'factor': 1.0, 'category': UnitCategory.AREA, 'base': 'm2'},'cm2': {'factor': 0.0001, 'category': UnitCategory.AREA, 'base': 'm2'},'mm2': {'factor': 0.000001, 'category': UnitCategory.AREA, 'base': 'm2'},'ha': {'factor': 10000.0, 'category': UnitCategory.AREA, 'base': 'm2'},'hectare': {'factor': 10000.0, 'category': UnitCategory.AREA, 'base': 'm2'},'ft2': {'factor': 0.092903, 'category': UnitCategory.AREA, 'base': 'm2'},'sf': {'factor': 0.092903, 'category': UnitCategory.AREA, 'base': 'm2'},'sqft': {'factor': 0.092903, 'category': UnitCategory.AREA, 'base': 'm2'},'yd2': {'factor': 0.836127, 'category': UnitCategory.AREA, 'base': 'm2'},'sy': {'factor': 0.836127, 'category': UnitCategory.AREA, 'base': 'm2'}, # Square yard'acre': {'factor': 4046.86, 'category': UnitCategory.AREA, 'base': 'm2'},# Volume to m³'m3': {'factor': 1.0, 'category': UnitCategory.VOLUME, 'base': 'm3'},'m³': {'factor': 1.0, 'category': UnitCategory.VOLUME, 'base': 'm3'},'cbm': {'factor': 1.0, 'category': UnitCategory.VOLUME, 'base': 'm3'},'l': {'factor': 0.001, 'category': UnitCategory.VOLUME, 'base': 'm3'},'liter': {'factor': 0.001, 'category': UnitCategory.VOLUME, 'base': 'm3'},'litre': {'factor': 0.001, 'category': UnitCategory.VOLUME, 'base': 'm3'},'ml': {'factor': 0.000001, 'category': UnitCategory.VOLUME, 'base': 'm3'},'ft3': {'factor': 0.0283168, 'category': UnitCategory.VOLUME, 'base': 'm3'},'cf': {'factor': 0.0283168, 'category': UnitCategory.VOLUME, 'base': 'm3'},'cuft': {'factor': 0.0283168, 'category': UnitCategory.VOLUME, 'base': 'm3'},'yd3': {'factor': 0.764555, 'category': UnitCategory.VOLUME, 'base': 'm3'},'cy': {'factor': 0.764555, 'category': UnitCategory.VOLUME, 'base': 'm3'}, # Cubic yard'cuyd': {'factor': 0.764555, 'category': UnitCategory.VOLUME, 'base': 'm3'},'gal': {'factor': 0.00378541, 'category': UnitCategory.VOLUME, 'base': 'm3'},'gallon': {'factor': 0.00378541, 'category': UnitCategory.VOLUME, 'base': 'm3'},# Weight to kg'kg': {'factor': 1.0, 'category': UnitCategory.WEIGHT, 'base': 'kg'},'kilogram': {'factor': 1.0, 'category': UnitCategory.WEIGHT, 'base': 'kg'},'g': {'factor': 0.001, 'category': UnitCategory.WEIGHT, 'base': 'kg'},'gram': {'factor': 0.001, 'category': UnitCategory.WEIGHT, 'base': 'kg'},'mg': {'factor': 0.000001, 'category': UnitCategory.WEIGHT, 'base': 'kg'},'t': {'factor': 1000.0, 'category': UnitCategory.WEIGHT, 'base': 'kg'},'ton': {'factor': 1000.0, 'category': UnitCategory.WEIGHT, 'base': 'kg'}, # Metric ton'tonne': {'factor': 1000.0, 'category': UnitCategory.WEIGHT, 'base': 'kg'},'mt': {'factor': 1000.0, 'category': UnitCategory.WEIGHT, 'base': 'kg'},'lb': {'factor': 0.453592, 'category': UnitCategory.WEIGHT, 'base': 'kg'},'lbs': {'factor': 0.453592, 'category': UnitCategory.WEIGHT, 'base': 'kg'},'pound': {'factor': 0.453592, 'category': UnitCategory.WEIGHT, 'base': 'kg'},'oz': {'factor': 0.0283495, 'category': UnitCategory.WEIGHT, 'base': 'kg'},'ounce': {'factor': 0.0283495, 'category': UnitCategory.WEIGHT, 'base': 'kg'},'st': {'factor': 907.185, 'category': UnitCategory.WEIGHT, 'base': 'kg'}, # Short ton (US)# Time to hours'hr': {'factor': 1.0, 'category': UnitCategory.TIME, 'base': 'hr'},'hour': {'factor': 1.0, 'category': UnitCategory.TIME, 'base': 'hr'},'hours': {'factor': 1.0, 'category': UnitCategory.TIME, 'base': 'hr'},'h': {'factor': 1.0, 'category': UnitCategory.TIME, 'base': 'hr'},'min': {'factor': 1/60, 'category': UnitCategory.TIME, 'base': 'hr'},'minute': {'factor': 1/60, 'category': UnitCategory.TIME, 'base': 'hr'},'day': {'factor': 8.0, 'category': UnitCategory.TIME, 'base': 'hr'}, # 8-hour workday'days': {'factor': 8.0, 'category': UnitCategory.TIME, 'base': 'hr'},'week': {'factor': 40.0, 'category': UnitCategory.TIME, 'base': 'hr'}, # 40-hour week# Quantity (no conversion, just counting)'ea': {'factor': 1.0, 'category': UnitCategory.QUANTITY, 'base': 'ea'},'each': {'factor': 1.0, 'category': UnitCategory.QUANTITY, 'base': 'ea'},'pc': {'factor': 1.0, 'category': UnitCategory.QUANTITY, 'base': 'ea'},'pcs': {'factor': 1.0, 'category': UnitCategory.QUANTITY, 'base': 'ea'},'piece': {'factor': 1.0, 'category': UnitCategory.QUANTITY, 'base': 'ea'},'pieces': {'factor': 1.0, 'category': UnitCategory.QUANTITY, 'base': 'ea'},'no': {'factor': 1.0, 'category': UnitCategory.QUANTITY, 'base': 'ea'},'nr': {'factor': 1.0, 'category': UnitCategory.QUANTITY, 'base': 'ea'},'set': {'factor': 1.0, 'category': UnitCategory.QUANTITY, 'base': 'ea'},'lot': {'factor': 1.0, 'category': UnitCategory.QUANTITY, 'base': 'ea'},'ls': {'factor': 1.0, 'category': UnitCategory.QUANTITY, 'base': 'ea'}, # Lump sum}class CWICRUnitConverter:"""Convert between construction units."""def __init__(self):self.conversions = CONVERSIONSdef normalize_unit(self, unit: str) -> str:"""Normalize unit string for lookup."""return str(unit).lower().strip().replace(' ', '').replace('.', '')def get_unit_info(self, unit: str) -> Optional[Dict[str, Any]]:"""Get conversion info for unit."""normalized = self.normalize_unit(unit)return self.conversions.get(normalized)def convert(self,value: float,from_unit: str,to_unit: str) -> UnitConversion:"""Convert value between units."""from_info = self.get_unit_info(from_unit)to_info = self.get_unit_info(to_unit)if not from_info:raise ValueError(f"Unknown source unit: {from_unit}")if not to_info:raise ValueError(f"Unknown target unit: {to_unit}")if from_info['category'] != to_info['category']:raise ValueError(f"Cannot convert between {from_info['category'].value} and {to_info['category'].value}")# Convert: source -> base -> targetbase_value = value * from_info['factor']converted_value = base_value / to_info['factor']conversion_factor = from_info['factor'] / to_info['factor']return UnitConversion(original_value=value,original_unit=from_unit,converted_value=round(converted_value, 6),target_unit=to_unit,conversion_factor=conversion_factor,category=from_info['category'])def to_metric(self, value: float, from_unit: str) -> UnitConversion:"""Convert to standard metric unit."""info = self.get_unit_info(from_unit)if not info:raise ValueError(f"Unknown unit: {from_unit}")base_unit = info['base']return self.convert(value, from_unit, base_unit)def to_imperial(self, value: float, from_unit: str) -> UnitConversion:"""Convert to common imperial unit."""info = self.get_unit_info(from_unit)if not info:raise ValueError(f"Unknown unit: {from_unit}")imperial_map = {'m': 'ft','m2': 'sf','m3': 'cy','kg': 'lb','hr': 'hr'}base = info['base']imperial_unit = imperial_map.get(base, base)return self.convert(value, from_unit, imperial_unit)def convert_dataframe(self,df: pd.DataFrame,value_column: str,unit_column: str,target_unit: str,output_column: str = None) -> pd.DataFrame:"""Convert units in DataFrame column."""result = df.copy()if output_column is None:output_column = f"{value_column}_converted"converted_values = []for _, row in df.iterrows():try:conversion = self.convert(row[value_column],row[unit_column],target_unit)converted_values.append(conversion.converted_value)except ValueError:converted_values.append(None)result[output_column] = converted_valuesresult[f'{output_column}_unit'] = target_unitreturn resultdef normalize_units(self,df: pd.DataFrame,value_column: str,unit_column: str) -> pd.DataFrame:"""Normalize all units to base metric units."""result = df.copy()normalized_values = []normalized_units = []for _, row in df.iterrows():try:conversion = self.to_metric(row[value_column], row[unit_column])normalized_values.append(conversion.converted_value)normalized_units.append(conversion.target_unit)except ValueError:normalized_values.append(row[value_column])normalized_units.append(row[unit_column])result[f'{value_column}_normalized'] = normalized_valuesresult[f'{unit_column}_normalized'] = normalized_unitsreturn resultclass ConstructionUnitHelper:"""Helper for construction-specific unit operations."""def __init__(self):self.converter = CWICRUnitConverter()def calculate_area(self,length: float, length_unit: str,width: float, width_unit: str,result_unit: str = 'm2') -> float:"""Calculate area from length and width."""# Convert both to meterslength_m = self.converter.convert(length, length_unit, 'm').converted_valuewidth_m = self.converter.convert(width, width_unit, 'm').converted_value# Calculate area in m²area_m2 = length_m * width_m# Convert to requested unitreturn self.converter.convert(area_m2, 'm2', result_unit).converted_valuedef calculate_volume(self,length: float, length_unit: str,width: float, width_unit: str,height: float, height_unit: str,result_unit: str = 'm3') -> float:"""Calculate volume from dimensions."""# Convert all to meterslength_m = self.converter.convert(length, length_unit, 'm').converted_valuewidth_m = self.converter.convert(width, width_unit, 'm').converted_valueheight_m = self.converter.convert(height, height_unit, 'm').converted_value# Calculate volume in m³volume_m3 = length_m * width_m * height_m# Convert to requested unitreturn self.converter.convert(volume_m3, 'm3', result_unit).converted_valuedef concrete_volume(self,length_ft: float,width_ft: float,thickness_in: float) -> Dict[str, float]:"""Calculate concrete volume (common US method)."""# Convert to meterslength_m = self.converter.convert(length_ft, 'ft', 'm').converted_valuewidth_m = self.converter.convert(width_ft, 'ft', 'm').converted_valuethickness_m = self.converter.convert(thickness_in, 'in', 'm').converted_valuevolume_m3 = length_m * width_m * thickness_mvolume_cy = self.converter.convert(volume_m3, 'm3', 'cy').converted_valuereturn {'m3': round(volume_m3, 3),'cy': round(volume_cy, 2)}def rebar_weight(self,length: float, length_unit: str,bar_size: str) -> Dict[str, float]:"""Calculate rebar weight from length and bar size."""# Rebar weight per meter (kg/m) - US bar sizesrebar_weights = {'#3': 0.561, '#4': 0.996, '#5': 1.556,'#6': 2.24, '#7': 3.049, '#8': 3.982,'#9': 5.06, '#10': 6.41, '#11': 7.91}weight_per_m = rebar_weights.get(bar_size, 1.0)length_m = self.converter.convert(length, length_unit, 'm').converted_valueweight_kg = length_m * weight_per_mweight_lb = self.converter.convert(weight_kg, 'kg', 'lb').converted_valuereturn {'kg': round(weight_kg, 2),'lb': round(weight_lb, 2),'ton': round(weight_kg / 1000, 4)}
Quick Start
python
# Initialize converterconverter = CWICRUnitConverter()# Simple conversionresult = converter.convert(100, 'ft', 'm')print(f"{result.original_value} {result.original_unit} = {result.converted_value} {result.target_unit}")# Convert to metricmetric = converter.to_metric(1000, 'sf')print(f"1000 sf = {metric.converted_value} m²")# Convert DataFramedf = pd.DataFrame({'quantity': [100, 50, 25],'unit': ['cy', 'm3', 'cf']})normalized = converter.normalize_units(df, 'quantity', 'unit')
Common Use Cases
1. Area Calculation
python
helper = ConstructionUnitHelper()area = helper.calculate_area(length=50, length_unit='ft',width=30, width_unit='ft',result_unit='m2')print(f"Area: {area} m²")
2. Concrete Volume
python
volume = helper.concrete_volume(length_ft=20,width_ft=10,thickness_in=6)print(f"Concrete: {volume['cy']} CY = {volume['m3']} m³")
3. Rebar Weight
python
weight = helper.rebar_weight(length=100, length_unit='m', bar_size='#5')print(f"Rebar weight: {weight['kg']} kg")
4. Normalize BIM Quantities
python
bim_data = pd.read_excel("bim_quantities.xlsx")normalized = converter.normalize_units(bim_data, 'Quantity', 'Unit')
Resources
- GitHub: OpenConstructionEstimate-DDC-CWICR
- DDC Book: Chapter 2.3 - Data Standardization