// Smart Environmental & Civil Engineering Calculators // Comprehensive calculation library with exception handling interface CalculationResult { value: number; unit: string; category: string; recommendation?: string; confidence: number; warnings?: string[]; } interface WaterQualityParams { pH?: number; bod?: number; cod?: number; tds?: number; turbidity?: number; chloride?: number; hardness?: number; temperature?: number; } interface AirQualityParams { pm25?: number; pm10?: number; so2?: number; no2?: number; co?: number; o3?: number; temperature?: number; humidity?: number; } interface SoilParams { ph?: number; nitrogen?: number; phosphorus?: number; potassium?: number; organicCarbon?: number; moisture?: number; electricalConductivity?: number; } class SmartCalculators { // Water Quality Analysis calculateWaterQuality(params: WaterQualityParams): CalculationResult[] { try { const results: CalculationResult[] = []; const warnings: string[] = []; // Validate inputs this.validateNumericParams(params, 'Water Quality'); // pH Analysis if (params.pH !== undefined) { const phResult = this.analyzePH(params.pH); results.push(phResult); if (phResult.warnings) warnings.push(...phResult.warnings); } // BOD Analysis if (params.bod !== undefined) { const bodResult = this.analyzeBOD(params.bod); results.push(bodResult); if (bodResult.warnings) warnings.push(...bodResult.warnings); } // COD Analysis if (params.cod !== undefined) { const codResult = this.analyzeCOD(params.cod); results.push(codResult); if (codResult.warnings) warnings.push(...codResult.warnings); } // TDS Analysis if (params.tds !== undefined) { const tdsResult = this.analyzeTDS(params.tds); results.push(tdsResult); if (tdsResult.warnings) warnings.push(...tdsResult.warnings); } // Overall Water Quality Index if (results.length > 0) { const wqiResult = this.calculateWQI(params); results.push(wqiResult); } return results; } catch (error) { throw new Error(`Water quality calculation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } // Air Quality Analysis calculateAirQuality(params: AirQualityParams): CalculationResult[] { try { const results: CalculationResult[] = []; this.validateNumericParams(params, 'Air Quality'); // PM2.5 Analysis if (params.pm25 !== undefined) { results.push(this.analyzePM25(params.pm25)); } // PM10 Analysis if (params.pm10 !== undefined) { results.push(this.analyzePM10(params.pm10)); } // Overall AQI if (params.pm25 !== undefined || params.pm10 !== undefined) { const aqiResult = this.calculateAQI(params); results.push(aqiResult); } return results; } catch (error) { throw new Error(`Air quality calculation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } // Soil Quality Analysis calculateSoilQuality(params: SoilParams): CalculationResult[] { try { const results: CalculationResult[] = []; this.validateNumericParams(params, 'Soil Quality'); // Soil pH Analysis if (params.ph !== undefined) { results.push(this.analyzeSoilPH(params.ph)); } // NPK Analysis if (params.nitrogen !== undefined || params.phosphorus !== undefined || params.potassium !== undefined) { results.push(this.analyzeNPK(params)); } // Soil Health Index const soilHealthIndex = this.calculateSoilHealthIndex(params); results.push(soilHealthIndex); return results; } catch (error) { throw new Error(`Soil quality calculation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } // NDVI Calculation calculateNDVI(redBand: number, nirBand: number): CalculationResult { try { if (redBand === undefined || nirBand === undefined) { throw new Error('Red and NIR band values are required for NDVI calculation'); } if (redBand < 0 || nirBand < 0) { throw new Error('Band values cannot be negative'); } if (redBand + nirBand === 0) { throw new Error('Cannot calculate NDVI: sum of bands is zero'); } const ndvi = (nirBand - redBand) / (nirBand + redBand); let category = 'Unknown'; let recommendation = ''; let confidence = 85; if (ndvi < 0) { category = 'Water/Snow'; recommendation = 'Indicates water bodies or snow-covered areas'; } else if (ndvi < 0.2) { category = 'Bare Soil/Rock'; recommendation = 'Low vegetation coverage, consider soil conservation measures'; } else if (ndvi < 0.5) { category = 'Sparse Vegetation'; recommendation = 'Moderate vegetation, suitable for grassland or agricultural areas'; } else if (ndvi < 0.8) { category = 'Dense Vegetation'; recommendation = 'Healthy vegetation coverage, good for forest or agricultural productivity'; } else { category = 'Very Dense Vegetation'; recommendation = 'Excellent vegetation health, optimal growing conditions'; } return { value: parseFloat(ndvi.toFixed(4)), unit: 'index', category, recommendation, confidence, warnings: ndvi < 0.1 ? ['Very low vegetation coverage detected'] : undefined }; } catch (error) { throw new Error(`NDVI calculation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } // Load Estimation for Structures calculateLoadEstimation(params: { deadLoad?: number; liveLoad?: number; windLoad?: number; seismicLoad?: number; structureType?: string; }): CalculationResult { try { this.validateNumericParams(params, 'Load Estimation'); const { deadLoad = 0, liveLoad = 0, windLoad = 0, seismicLoad = 0, structureType = 'general' } = params; // Load combinations as per IS 875 const combinations = [ 1.5 * (deadLoad + liveLoad), // Basic combination 1.2 * (deadLoad + liveLoad + windLoad), // Wind combination 1.2 * (deadLoad + liveLoad + seismicLoad), // Seismic combination 0.9 * deadLoad + 1.5 * windLoad, // Wind uplift ]; const designLoad = Math.max(...combinations); let recommendation = ''; const safetyFactor = designLoad / (deadLoad + liveLoad || 1); if (safetyFactor > 2.5) { recommendation = 'Over-designed structure, consider optimization'; } else if (safetyFactor > 1.5) { recommendation = 'Safe design with adequate safety margin'; } else { recommendation = 'Consider increasing safety factors or reviewing design'; } return { value: parseFloat(designLoad.toFixed(2)), unit: 'kN', category: 'Structural Load', recommendation, confidence: 90, warnings: safetyFactor < 1.5 ? ['Low safety factor detected'] : undefined }; } catch (error) { throw new Error(`Load estimation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } // Stormwater Management calculateStormwaterRunoff(params: { area?: number; rainfallIntensity?: number; runoffCoefficient?: number; timeOfConcentration?: number; }): CalculationResult { try { this.validateNumericParams(params, 'Stormwater'); const { area, rainfallIntensity, runoffCoefficient = 0.5, timeOfConcentration } = params; if (!area || !rainfallIntensity) { throw new Error('Area and rainfall intensity are required for stormwater calculation'); } if (area <= 0 || rainfallIntensity <= 0) { throw new Error('Area and rainfall intensity must be positive values'); } if (runoffCoefficient < 0 || runoffCoefficient > 1) { throw new Error('Runoff coefficient must be between 0 and 1'); } // Rational method: Q = CiA const runoff = runoffCoefficient * rainfallIntensity * area; let recommendation = ''; if (runoffCoefficient > 0.8) { recommendation = 'High runoff coefficient - consider implementing green infrastructure'; } else if (runoffCoefficient > 0.5) { recommendation = 'Moderate runoff - adequate drainage system required'; } else { recommendation = 'Low runoff coefficient - natural infiltration is significant'; } return { value: parseFloat(runoff.toFixed(2)), unit: 'm³/hr', category: 'Stormwater Runoff', recommendation, confidence: 85, warnings: runoff > 1000 ? ['High runoff volume - flood risk assessment recommended'] : undefined }; } catch (error) { throw new Error(`Stormwater calculation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } // Noise Level Analysis calculateNoiseLevel(params: { soundLevels?: number[]; timeWeighted?: boolean; zoneType?: 'residential' | 'commercial' | 'industrial' | 'silent'; }): CalculationResult { try { const { soundLevels, timeWeighted = false, zoneType = 'residential' } = params; if (!soundLevels || soundLevels.length === 0) { throw new Error('Sound level measurements are required'); } soundLevels.forEach((level, index) => { if (typeof level !== 'number' || level < 0 || level > 150) { throw new Error(`Invalid sound level at position ${index + 1}: must be between 0-150 dB`); } }); // Calculate equivalent noise level let leq: number; if (timeWeighted) { // Time-weighted average const sum = soundLevels.reduce((acc, level) => acc + Math.pow(10, level / 10), 0); leq = 10 * Math.log10(sum / soundLevels.length); } else { // Simple average leq = soundLevels.reduce((acc, level) => acc + level, 0) / soundLevels.length; } // Noise limits as per CPCB norms const limits = { residential: { day: 55, night: 45 }, commercial: { day: 65, night: 55 }, industrial: { day: 75, night: 70 }, silent: { day: 50, night: 40 } }; const limit = limits[zoneType]; let recommendation = ''; let warnings: string[] = []; if (leq > limit.day) { warnings.push(`Exceeds daytime noise limit for ${zoneType} zone (${limit.day} dB)`); recommendation = 'Noise control measures required - consider sound barriers or source control'; } else if (leq > limit.night) { warnings.push(`Exceeds nighttime noise limit for ${zoneType} zone (${limit.night} dB)`); recommendation = 'Moderate noise levels - monitor during night hours'; } else { recommendation = 'Noise levels within acceptable limits'; } return { value: parseFloat(leq.toFixed(1)), unit: 'dB(A)', category: 'Noise Level', recommendation, confidence: 88, warnings: warnings.length > 0 ? warnings : undefined }; } catch (error) { throw new Error(`Noise level calculation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } // Private helper methods private validateNumericParams(params: any, calculationType: string): void { for (const [key, value] of Object.entries(params)) { if (value !== undefined && typeof value !== 'number') { throw new Error(`${calculationType}: Parameter '${key}' must be a number`); } if (value !== undefined && (isNaN(value) || !isFinite(value))) { throw new Error(`${calculationType}: Parameter '${key}' must be a valid finite number`); } } } private analyzePH(ph: number): CalculationResult { let category = ''; let recommendation = ''; const warnings: string[] = []; if (ph < 0 || ph > 14) { throw new Error('pH must be between 0 and 14'); } if (ph < 6.5) { category = 'Acidic'; recommendation = 'Consider pH adjustment with lime or alkaline treatment'; if (ph < 4) warnings.push('Highly acidic - may be corrosive'); } else if (ph > 8.5) { category = 'Alkaline'; recommendation = 'Consider pH adjustment with acid treatment'; if (ph > 11) warnings.push('Highly alkaline - may be harmful'); } else { category = 'Neutral'; recommendation = 'pH within acceptable range for most applications'; } return { value: ph, unit: 'pH units', category, recommendation, confidence: 95, warnings: warnings.length > 0 ? warnings : undefined }; } private analyzeBOD(bod: number): CalculationResult { if (bod < 0) throw new Error('BOD cannot be negative'); let category = ''; let recommendation = ''; const warnings: string[] = []; if (bod < 3) { category = 'Clean Water'; recommendation = 'Excellent water quality'; } else if (bod < 6) { category = 'Slightly Polluted'; recommendation = 'Good water quality with minor treatment needed'; } else if (bod < 30) { category = 'Moderately Polluted'; recommendation = 'Secondary treatment required'; warnings.push('Moderate pollution detected'); } else { category = 'Heavily Polluted'; recommendation = 'Advanced treatment required before discharge'; warnings.push('High pollution levels - immediate action needed'); } return { value: bod, unit: 'mg/L', category, recommendation, confidence: 90, warnings: warnings.length > 0 ? warnings : undefined }; } private analyzeCOD(cod: number): CalculationResult { if (cod < 0) throw new Error('COD cannot be negative'); let category = ''; let recommendation = ''; if (cod < 10) { category = 'Clean Water'; recommendation = 'Excellent water quality'; } else if (cod < 50) { category = 'Lightly Polluted'; recommendation = 'Minor treatment may be required'; } else if (cod < 150) { category = 'Moderately Polluted'; recommendation = 'Treatment required before discharge'; } else { category = 'Heavily Polluted'; recommendation = 'Advanced treatment necessary'; } return { value: cod, unit: 'mg/L', category, recommendation, confidence: 90 }; } private analyzeTDS(tds: number): CalculationResult { if (tds < 0) throw new Error('TDS cannot be negative'); let category = ''; let recommendation = ''; if (tds < 500) { category = 'Excellent'; recommendation = 'Suitable for drinking and most applications'; } else if (tds < 1000) { category = 'Good'; recommendation = 'Generally acceptable for most uses'; } else if (tds < 2000) { category = 'Fair'; recommendation = 'May require treatment for drinking water'; } else { category = 'Poor'; recommendation = 'Treatment required before use'; } return { value: tds, unit: 'mg/L', category, recommendation, confidence: 88 }; } private calculateWQI(params: WaterQualityParams): CalculationResult { let wqi = 100; let factors = 0; // Simplified WQI calculation if (params.pH !== undefined) { const phScore = params.pH >= 6.5 && params.pH <= 8.5 ? 100 : Math.max(0, 100 - Math.abs(7 - params.pH) * 20); wqi = (wqi * factors + phScore) / (factors + 1); factors++; } if (params.bod !== undefined) { const bodScore = Math.max(0, 100 - params.bod * 3); wqi = (wqi * factors + bodScore) / (factors + 1); factors++; } let category = ''; if (wqi > 80) category = 'Excellent'; else if (wqi > 60) category = 'Good'; else if (wqi > 40) category = 'Fair'; else category = 'Poor'; return { value: parseFloat(wqi.toFixed(1)), unit: 'WQI', category: `Water Quality: ${category}`, recommendation: wqi > 60 ? 'Water quality is acceptable' : 'Water treatment recommended', confidence: 85 }; } private analyzePM25(pm25: number): CalculationResult { if (pm25 < 0) throw new Error('PM2.5 cannot be negative'); let category = ''; let recommendation = ''; const warnings: string[] = []; if (pm25 <= 12) { category = 'Good'; recommendation = 'Air quality is satisfactory'; } else if (pm25 <= 35.4) { category = 'Moderate'; recommendation = 'Acceptable for most people'; } else if (pm25 <= 55.4) { category = 'Unhealthy for Sensitive Groups'; recommendation = 'Sensitive individuals should limit outdoor exposure'; warnings.push('Sensitive groups should take precautions'); } else { category = 'Unhealthy'; recommendation = 'Everyone should limit outdoor activities'; warnings.push('Poor air quality - health advisory in effect'); } return { value: pm25, unit: 'μg/m³', category, recommendation, confidence: 92, warnings: warnings.length > 0 ? warnings : undefined }; } private analyzePM10(pm10: number): CalculationResult { if (pm10 < 0) throw new Error('PM10 cannot be negative'); let category = ''; let recommendation = ''; if (pm10 <= 54) { category = 'Good'; recommendation = 'Air quality is satisfactory'; } else if (pm10 <= 154) { category = 'Moderate'; recommendation = 'Acceptable for most people'; } else if (pm10 <= 254) { category = 'Unhealthy for Sensitive Groups'; recommendation = 'Sensitive individuals should limit outdoor exposure'; } else { category = 'Unhealthy'; recommendation = 'Everyone should limit outdoor activities'; } return { value: pm10, unit: 'μg/m³', category, recommendation, confidence: 90 }; } private calculateAQI(params: AirQualityParams): CalculationResult { let maxAqi = 0; let dominantPollutant = ''; if (params.pm25 !== undefined) { const pm25Aqi = this.convertToAQI(params.pm25, 'PM2.5'); if (pm25Aqi > maxAqi) { maxAqi = pm25Aqi; dominantPollutant = 'PM2.5'; } } if (params.pm10 !== undefined) { const pm10Aqi = this.convertToAQI(params.pm10, 'PM10'); if (pm10Aqi > maxAqi) { maxAqi = pm10Aqi; dominantPollutant = 'PM10'; } } let category = ''; if (maxAqi <= 50) category = 'Good'; else if (maxAqi <= 100) category = 'Moderate'; else if (maxAqi <= 150) category = 'Unhealthy for Sensitive Groups'; else if (maxAqi <= 200) category = 'Unhealthy'; else category = 'Very Unhealthy'; return { value: Math.round(maxAqi), unit: 'AQI', category: `Air Quality: ${category}`, recommendation: `Dominant pollutant: ${dominantPollutant}. ${category === 'Good' ? 'Air quality is acceptable' : 'Consider limiting outdoor activities'}`, confidence: 88 }; } private convertToAQI(concentration: number, pollutant: string): number { // Simplified AQI calculation based on EPA standards const breakpoints = { 'PM2.5': [ [0, 12, 0, 50], [12.1, 35.4, 51, 100], [35.5, 55.4, 101, 150], [55.5, 150.4, 151, 200] ], 'PM10': [ [0, 54, 0, 50], [55, 154, 51, 100], [155, 254, 101, 150], [255, 354, 151, 200] ] }; const points = breakpoints[pollutant as keyof typeof breakpoints]; if (!points) return 0; for (const [cLow, cHigh, aqiLow, aqiHigh] of points) { if (concentration >= cLow && concentration <= cHigh) { return ((aqiHigh - aqiLow) / (cHigh - cLow)) * (concentration - cLow) + aqiLow; } } return points[points.length - 1][3]; // Return max AQI if above all ranges } private analyzeSoilPH(ph: number): CalculationResult { if (ph < 0 || ph > 14) throw new Error('Soil pH must be between 0 and 14'); let category = ''; let recommendation = ''; if (ph < 5.5) { category = 'Highly Acidic'; recommendation = 'Lime application recommended to raise pH'; } else if (ph < 6.5) { category = 'Moderately Acidic'; recommendation = 'Consider lime application for most crops'; } else if (ph < 7.5) { category = 'Neutral'; recommendation = 'Optimal pH range for most crops'; } else if (ph < 8.5) { category = 'Slightly Alkaline'; recommendation = 'Generally acceptable, monitor nutrient availability'; } else { category = 'Highly Alkaline'; recommendation = 'Consider sulfur application to lower pH'; } return { value: ph, unit: 'pH units', category, recommendation, confidence: 94 }; } private analyzeNPK(params: SoilParams): CalculationResult { const { nitrogen = 0, phosphorus = 0, potassium = 0 } = params; if (nitrogen < 0 || phosphorus < 0 || potassium < 0) { throw new Error('NPK values cannot be negative'); } // NPK rating based on typical soil test values const nRating = nitrogen > 40 ? 'High' : nitrogen > 20 ? 'Medium' : 'Low'; const pRating = phosphorus > 25 ? 'High' : phosphorus > 15 ? 'Medium' : 'Low'; const kRating = potassium > 150 ? 'High' : potassium > 100 ? 'Medium' : 'Low'; const totalNPK = nitrogen + phosphorus + potassium; let recommendation = `N: ${nRating}, P: ${pRating}, K: ${kRating}. `; if (nRating === 'Low') recommendation += 'Nitrogen fertilization recommended. '; if (pRating === 'Low') recommendation += 'Phosphorus supplementation needed. '; if (kRating === 'Low') recommendation += 'Potassium application suggested.'; return { value: parseFloat(totalNPK.toFixed(1)), unit: 'kg/ha', category: 'NPK Analysis', recommendation: recommendation.trim(), confidence: 87 }; } private calculateSoilHealthIndex(params: SoilParams): CalculationResult { let score = 0; let factors = 0; // pH contribution if (params.ph !== undefined) { const phScore = params.ph >= 6.0 && params.ph <= 7.5 ? 100 : Math.max(0, 100 - Math.abs(6.75 - params.ph) * 20); score += phScore; factors++; } // Organic carbon contribution if (params.organicCarbon !== undefined) { const ocScore = Math.min(100, params.organicCarbon * 20); score += ocScore; factors++; } // Moisture contribution if (params.moisture !== undefined) { const moistureScore = params.moisture >= 15 && params.moisture <= 25 ? 100 : Math.max(0, 100 - Math.abs(20 - params.moisture) * 5); score += moistureScore; factors++; } const healthIndex = factors > 0 ? score / factors : 50; let category = ''; if (healthIndex > 80) category = 'Excellent'; else if (healthIndex > 60) category = 'Good'; else if (healthIndex > 40) category = 'Fair'; else category = 'Poor'; return { value: parseFloat(healthIndex.toFixed(1)), unit: 'index', category: `Soil Health: ${category}`, recommendation: healthIndex > 60 ? 'Soil health is adequate' : 'Soil improvement measures recommended', confidence: 83 }; } } export const smartCalculators = new SmartCalculators(); export { CalculationResult, WaterQualityParams, AirQualityParams, SoilParams };