demeter

Autonomous Hydroponic Intelligence

frontend/src/data/mockData.js (10165B)


  1// MOCK DATA
  2// -- Set USE_MOCK_DATA = true to use local test data
  3// -- Set USE_MOCK_DATA = false to connect to the real backend API
  4export const USE_MOCK_DATA = false;
  5
  6// HELPERS
  7const ts = (daysAgo, hour = 10, min = 0) => {
  8  const d = new Date();
  9  d.setDate(d.getDate() - daysAgo);
 10  d.setHours(hour, min, 0, 0);
 11  return d.toISOString();
 12};
 13
 14const plantedTs = (daysAgo) => {
 15  const d = new Date();
 16  d.setDate(d.getDate() - daysAgo);
 17  return d.toISOString();
 18};
 19
 20// Explanation log samples
 21const EXPLANATION_LOGS = {
 22  lettuce: `1. **Observation**: Sensors show pH 6.1, EC 1.4 dS/m, Temp 23.5°C, Humidity 68%.
 23   All parameters are within acceptable range for Vegetative Lettuce.
 24
 252. **Precedent**: 3 similar past states found. In 2 of those cases, a slight EC boost
 26   improved growth rate by +12%. No disease was detected in the last 5 cycles.
 27
 283. **Logic**: EC at 1.4 is slightly below the 1.5-1.8 target for late vegetative.
 29   A small nutrient dosage increase will push it into the optimal window.
 30   Fan speed is adequate; no VPD concerns at current temp/humidity.
 31
 324. **Conclusion**: Dosing 2.5ml nutrients is the safest, most targeted intervention.
 33   No pH correction needed. Maintain current atmospheric settings.`,
 34
 35  tomato: `1. **Observation**: pH 5.8, EC 2.1 dS/m, Temp 26°C, Humidity 58%.
 36   EC is elevated for flowering stage - approaching upper safe limit of 2.2.
 37
 382. **Precedent**: 2 similar flowering Tomato states found. In one prior case,
 39   EC > 2.2 triggered blossom drop. Acid dosage was effective in 1 case.
 40
 413. **Logic**: pH 5.8 is at the lower end for Tomato flowering (optimal 6.0-6.5).
 42   A controlled acid dose of 1.5ml will bring pH down slightly to 5.9,
 43   while nutrient top-up at 4ml maintains bloom support without pushing EC over limit.
 44
 454. **Conclusion**: Targeted acid dosage + nutrient boost is the correct intervention.
 46   Increased fan speed to 60% to manage VPD in warm conditions.`,
 47
 48  basil: `1. **Observation**: CRITICAL - pH 7.8 (target 5.5-6.5), EC 0.6 (very low), Temp 29.5°C.
 49   Multiple out-of-range parameters detected simultaneously.
 50
 512. **Precedent**: 1 similar critical Basil state found. Previous corrective action
 52   required 8ml acid dosage to restore pH. Recovery took 2 cycles.
 53
 543. **Logic**: pH 7.8 indicates severe alkalinity - likely nutrient lockout.
 55   At this pH, iron and manganese become unavailable causing yellowing.
 56   EC 0.6 confirms nutrient starvation. Aggressive correction required.
 57   High temp (29.5°C) increases risk of bolting.
 58
 594. **Conclusion**: Emergency acid dosage (8ml) is necessary. Fan at 80% to cool.
 60   Nutrient addition deferred until pH stabilizes to avoid compounding stress.`,
 61
 62  strawberry: `1. **Observation**: pH 6.2, EC 1.8 dS/m, Temp 22°C, Humidity 65%.
 63   All parameters within optimal range for Strawberry Vegetative stage.
 64
 652. **Precedent**: 4 similar states found, all showing positive outcomes.
 66   Gentle interventions in this range historically improve runner production by 10-18%.
 67
 683. **Logic**: Conditions are near-ideal. pH 6.2 is perfect for Strawberry (optimal 6.0-6.5).
 69   Light nutrient boost (1.5ml) maintains EC momentum. Water refill supports
 70   root zone hydration without diluting nutrients significantly.
 71
 724. **Conclusion**: Minimal intervention strategy. 1.5ml nutrient + 1.5L water refill.
 73   Fan at 40% maintains gentle airflow - adequate for cooler Strawberry environment.`,
 74};
 75
 76/**
 77 * MOCK_DASHBOARD - Raw MongoDB document shape
 78 * (sensors as arrays, planted_at, cycle_duration_hours, sensor_ids, location)
 79 */
 80export const MOCK_DASHBOARD = [
 81  {
 82    _id: "mongo-001",
 83    crop_id: "Batch_Lettuce_2025A",
 84    crop: "Lettuce",
 85    stage: "vegetative",
 86    sequence_number: 14,
 87    cycle_duration_hours: 1,
 88    planted_at: plantedTs(10),
 89    last_updated: ts(0, 9, 30),
 90    location: "Rack A - Shelf 1",
 91    notes: "Fast-growing batch, increased EC slightly on day 7.",
 92    image_url: "",
 93    sensors: {
 94      pH: [5.9, 6.0, 6.1, 6.1],
 95      EC: [1.3, 1.4, 1.4, 1.4],
 96      temp: [23.0, 23.5, 23.5, 23.5],
 97      humidity: [66, 67, 68, 68],
 98    },
 99    sensor_ids: {
100      ph_sensor: "PH-SEN-A1F3",
101      ec_sensor: "EC-SEN-B2D7",
102      temp_sensor: "TMP-SEN-C4E9",
103      humidity_sensor: "HUM-SEN-D6F1",
104    },
105    action_taken: JSON.stringify({
106      acid_dosage_ml: 0,
107      base_dosage_ml: 0,
108      nutrient_dosage_ml: 2.5,
109      fan_speed_pct: 45,
110      water_refill_l: 0,
111    }),
112    outcome: "IMPROVED | Reward: 0.8",
113    strategic_intent: "MAINTAIN_CURRENT",
114    bandit_action_id: 0,
115    reward_score: 0.8,
116    explanation_log: EXPLANATION_LOGS.lettuce,
117  },
118  {
119    _id: "mongo-002",
120    crop_id: "Batch_Tomato_2025B",
121    crop: "Tomato",
122    stage: "flowering",
123    sequence_number: 22,
124    cycle_duration_hours: 2,
125    planted_at: plantedTs(45),
126    last_updated: ts(0, 8, 15),
127    location: "Rack B - Shelf 2",
128    notes: "",
129    image_url: "",
130    sensors: {
131      pH: [5.7, 5.8, 5.8, 5.8],
132      EC: [2.0, 2.1, 2.1, 2.1],
133      temp: [25.5, 26.0, 26.0, 26.0],
134      humidity: [57, 58, 58, 58],
135    },
136    sensor_ids: {
137      ph_sensor: "PH-SEN-E5A2",
138      ec_sensor: "EC-SEN-F3C8",
139      temp_sensor: "TMP-SEN-G7D1",
140      humidity_sensor: "HUM-SEN-H9B4",
141    },
142    action_taken: JSON.stringify({
143      acid_dosage_ml: 1.5,
144      base_dosage_ml: 0,
145      nutrient_dosage_ml: 4.0,
146      fan_speed_pct: 60,
147      water_refill_l: 0,
148    }),
149    outcome: "STABLE | Reward: 0.4",
150    strategic_intent: "INCREASE_EC_BLOOM",
151    bandit_action_id: 6,
152    reward_score: 0.4,
153    explanation_log: EXPLANATION_LOGS.tomato,
154  },
155  {
156    _id: "mongo-003",
157    crop_id: "Batch_Basil_2025C",
158    crop: "Basil",
159    stage: "seedling",
160    sequence_number: 5,
161    cycle_duration_hours: 1,
162    planted_at: plantedTs(3),
163    last_updated: ts(0, 11, 0),
164    location: "Rack A - Shelf 3",
165    notes: "New batch - watching pH closely.",
166    image_url: "",
167    sensors: {
168      pH: [7.5, 7.7, 7.8, 7.8],
169      EC: [0.7, 0.6, 0.6, 0.6],
170      temp: [28.5, 29.0, 29.5, 29.5],
171      humidity: [80, 81, 82, 82],
172    },
173    sensor_ids: {
174      ph_sensor: "PH-SEN-I2K6",
175      ec_sensor: "EC-SEN-J4L9",
176      temp_sensor: "TMP-SEN-K1M3",
177      humidity_sensor: "HUM-SEN-L8N7",
178    },
179    action_taken: JSON.stringify({
180      acid_dosage_ml: 8.0,
181      base_dosage_ml: 0,
182      nutrient_dosage_ml: 3.0,
183      fan_speed_pct: 80,
184      water_refill_l: 0,
185    }),
186    outcome: "DETERIORATED | Reward: -0.6",
187    strategic_intent: "AGGRESSIVE_PH_DOWN",
188    bandit_action_id: 2,
189    reward_score: -0.6,
190    explanation_log: EXPLANATION_LOGS.basil,
191  },
192  {
193    _id: "mongo-004",
194    crop_id: "Batch_Strawberry_2025D",
195    crop: "Strawberry",
196    stage: "vegetative",
197    sequence_number: 9,
198    cycle_duration_hours: 2,
199    planted_at: plantedTs(18),
200    last_updated: ts(1, 14, 45),
201    location: "Rack C - Shelf 1",
202    notes: "Runner training started on day 12.",
203    image_url: "",
204    sensors: {
205      pH: [6.1, 6.2, 6.2, 6.2],
206      EC: [1.7, 1.8, 1.8, 1.8],
207      temp: [21.5, 22.0, 22.0, 22.0],
208      humidity: [63, 64, 65, 65],
209    },
210    sensor_ids: {
211      ph_sensor: "PH-SEN-M5P2",
212      ec_sensor: "EC-SEN-N7Q4",
213      temp_sensor: "TMP-SEN-O3R8",
214      humidity_sensor: "HUM-SEN-P1S6",
215    },
216    action_taken: JSON.stringify({
217      acid_dosage_ml: 0,
218      base_dosage_ml: 0,
219      nutrient_dosage_ml: 1.5,
220      fan_speed_pct: 40,
221      water_refill_l: 1.5,
222    }),
223    outcome: "IMPROVED | Reward: 0.7",
224    strategic_intent: "GENTLE_PH_BALANCING",
225    bandit_action_id: 4,
226    reward_score: 0.7,
227    explanation_log: EXPLANATION_LOGS.strawberry,
228  },
229];
230
231// Detailed history per crop (multiple snapshots - keeps Qdrant/payload shape for analytics)
232function makeHistory(cropId, cropName, stage, n, baseVals, explanationLog) {
233  return Array.from({ length: n }, (_, i) => {
234    const jitter = (range) => (Math.random() - 0.5) * range;
235    return {
236      id: `${cropId}-seq-${i + 1}`,
237      payload: {
238        crop_id: cropId,
239        crop: cropName,
240        stage,
241        sequence_number: i + 1,
242        timestamp: ts(Math.floor((n - i) / 3), (i * 2) % 24, (i * 7) % 60),
243        sensors: {
244          pH: +(baseVals.ph + jitter(0.4)).toFixed(2),
245          EC: +(baseVals.ec + jitter(0.3)).toFixed(2),
246          temp: +(baseVals.temp + jitter(2)).toFixed(1),
247          humidity: +(baseVals.humidity + jitter(8)).toFixed(1),
248        },
249        action_taken: JSON.stringify({
250          acid_dosage_ml: +(Math.random() * 2).toFixed(1),
251          base_dosage_ml: 0,
252          nutrient_dosage_ml: +(Math.random() * 3 + 1).toFixed(1),
253          fan_speed_pct: Math.round(30 + Math.random() * 40),
254          water_refill_l: +(Math.random() * 2).toFixed(1),
255        }),
256        outcome: [
257          "IMPROVED | Reward: 0.7",
258          "STABLE | Reward: 0.4",
259          "DETERIORATED | Reward: -0.3",
260        ][i % 3],
261        strategic_intent: [
262          "MAINTAIN_CURRENT",
263          "GENTLE_PH_BALANCING",
264          "INCREASE_EC_VEG",
265        ][i % 3],
266        reward_score: [0.7, 0.4, -0.3][i % 3],
267        explanation_log: explanationLog,
268      },
269    };
270  });
271}
272
273export const MOCK_HISTORY = [
274  ...makeHistory(
275    "Batch_Lettuce_2025A",
276    "Lettuce",
277    "vegetative",
278    14,
279    { ph: 6.1, ec: 1.4, temp: 23.5, humidity: 68 },
280    EXPLANATION_LOGS.lettuce,
281  ),
282  ...makeHistory(
283    "Batch_Tomato_2025B",
284    "Tomato",
285    "flowering",
286    22,
287    { ph: 5.8, ec: 2.1, temp: 26.0, humidity: 58 },
288    EXPLANATION_LOGS.tomato,
289  ),
290  ...makeHistory(
291    "Batch_Basil_2025C",
292    "Basil",
293    "seedling",
294    5,
295    { ph: 7.8, ec: 0.6, temp: 29.5, humidity: 82 },
296    EXPLANATION_LOGS.basil,
297  ),
298  ...makeHistory(
299    "Batch_Strawberry_2025D",
300    "Strawberry",
301    "vegetative",
302    9,
303    { ph: 6.2, ec: 1.8, temp: 22.0, humidity: 65 },
304    EXPLANATION_LOGS.strawberry,
305  ),
306];
307
308// Mock search result (for FarmIntelligence)
309export const MOCK_SEARCH_RESULT = {
310  status: "success",
311  results: MOCK_DASHBOARD.slice(0, 2).map((d, i) => ({
312    id: d._id,
313    score: 0.95 - i * 0.08,
314    payload: { ...d, sensors: { pH: 6.1, EC: 1.4, temp: 23.5, humidity: 68 } },
315  })),
316  query_logic: { must: [{ key: "crop", match: "Lettuce" }] },
317};