Spaces:
Configuration error
Configuration error
| // 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 }; |