-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdataUtils.ts
More file actions
118 lines (99 loc) · 3.24 KB
/
Copy pathdataUtils.ts
File metadata and controls
118 lines (99 loc) · 3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { DailySensorData, FarmField, CropType, DateRangeOption } from '../types';
export const filterSensorData = (
data: DailySensorData[],
selectedField: 'All Fields' | FarmField,
selectedCrop: 'All Crops' | CropType,
dateRange: DateRangeOption
): DailySensorData[] => {
let filtered = [...data];
if (selectedField !== 'All Fields') {
filtered = filtered.filter((item) => item.field === selectedField);
}
if (selectedCrop !== 'All Crops') {
filtered = filtered.filter((item) => item.crop === selectedCrop);
}
// Calculate days filter
const daysMap: Record<DateRangeOption, number> = {
'7d': 7,
'30d': 30,
'90d': 90,
'365d': 365,
};
const limitDays = daysMap[dateRange];
// Get latest date from dataset
const maxDateStr = filtered.length > 0 ? filtered[filtered.length - 1].date : '2026-07-24';
const maxDate = new Date(maxDateStr);
const minDate = new Date(maxDate);
minDate.setDate(minDate.getDate() - limitDays);
return filtered.filter((item) => {
const itemDate = new Date(item.date);
return itemDate >= minDate && itemDate <= maxDate;
});
};
export const formatTemperature = (valInC: number, unit: 'C' | 'F'): string => {
if (unit === 'F') {
const valF = Math.round((valInC * 9) / 5 + 32);
return `${valF}°F`;
}
return `${valInC}°C`;
};
export const formatMoisture = (valInPercent: number, unit: 'percentage' | 'cb'): string => {
if (unit === 'cb') {
// Centibars estimate (lower cb is wetter)
const cbVal = Math.round(Math.max(5, (100 - valInPercent) * 1.5));
return `${cbVal} cb`;
}
return `${valInPercent}%`;
};
// Aggregate metrics summary for filtered dataset
export const calculateDataMetrics = (data: DailySensorData[]) => {
if (data.length === 0) {
return {
avgMoisture: 0,
minMoisture: 0,
maxMoisture: 0,
avgTemp: 0,
minTemp: 0,
maxTemp: 0,
avgNitrogen: 0,
avgPhosphorus: 0,
avgPotassium: 0,
avgSoilHealth: 0,
};
}
let totalMoisture = 0;
let minMoisture = Infinity;
let maxMoisture = -Infinity;
let totalTemp = 0;
let minTemp = Infinity;
let maxTemp = -Infinity;
let totalN = 0;
let totalP = 0;
let totalK = 0;
let totalHealth = 0;
data.forEach((d) => {
totalMoisture += d.soilMoisture;
if (d.soilMoisture < minMoisture) minMoisture = d.soilMoisture;
if (d.soilMoisture > maxMoisture) maxMoisture = d.soilMoisture;
totalTemp += d.temperature;
if (d.temperature < minTemp) minTemp = d.temperature;
if (d.temperature > maxTemp) maxTemp = d.temperature;
totalN += d.nitrogen;
totalP += d.phosphorus;
totalK += d.potassium;
totalHealth += d.soilHealthScore;
});
const count = data.length;
return {
avgMoisture: Math.round((totalMoisture / count) * 10) / 10,
minMoisture: Math.round(minMoisture * 10) / 10,
maxMoisture: Math.round(maxMoisture * 10) / 10,
avgTemp: Math.round((totalTemp / count) * 10) / 10,
minTemp: Math.round(minTemp * 10) / 10,
maxTemp: Math.round(maxTemp * 10) / 10,
avgNitrogen: Math.round((totalN / count) * 10) / 10,
avgPhosphorus: Math.round((totalP / count) * 10) / 10,
avgPotassium: Math.round((totalK / count) * 10) / 10,
avgSoilHealth: Math.round(totalHealth / count),
};
};