prepare("SELECT * FROM soil_records WHERE id = ? AND rand = ?"); $stmt->execute([$record_id, $rand_id]); $row = $stmt->fetch(PDO::FETCH_ASSOC); if (!$row) { die('Soil record not found'); } // Load matching specifications row for this soil type $spec = []; if (!empty($row['soil_type'])) { $stmtSpec = $pdo->prepare("SELECT * FROM soil_specifications WHERE soil_type = ? LIMIT 1"); $stmtSpec->execute([$row['soil_type']]); $spec = $stmtSpec->fetch(PDO::FETCH_ASSOC) ?: []; } } catch (PDOException $e) { error_log("Database error in soil-analysis.php: " . $e->getMessage()); die('Database error occurred'); } // ── Helper: render one analysis row ─────────────────────────────────────── /** * Renders a for a single nutrient with three progress-bar columns. * * Parameters ($p keys): * element string Column name in soil_records * sbl string Chemical symbol (may contain HTML, e.g. "NO3-N") * nutrient string Display name (may contain HTML) * min string Column in soil_records, numeric literal, or '' for no bar * max string Column in soil_records, 'soil_type' (special), numeric literal, or '' * type string Unit label (ppm, %, mS/cm …) * text string Value cell alignment: c|r|l * rec_text string Recommended cell alignment: c|r|l * recV string Recommended display: 'n'=none, 'ph'='6.4', 'max'=max only, else=min–max * decimal int Decimal places for value * graph string CSS class for progress-bar colour */ function soilRow(array $row, array $spec, array $p): void { $element = $p['element'] ?? ''; $sbl = $p['sbl'] ?? ''; $nutrient = $p['nutrient'] ?? ''; $minParam = $p['min'] ?? ''; $maxParam = $p['max'] ?? ''; $type = $p['type'] ?? ''; $text = $p['text'] ?? 'c'; $recText = $p['rec_text'] ?? 'c'; $recV = $p['recV'] ?? ''; $decimal = (int)($p['decimal'] ?? 2); $graph = $p['graph'] ?? ''; $label = ($sbl !== '') ? $sbl . ' - ' . $nutrient : $nutrient; $rawVal = $row[$element] ?? null; $value = ($rawVal !== null && $rawVal !== '') ? (float)$rawVal : 0.0; $valueFmt = number_format($value, $decimal, '.', '') . ($type !== '' ? ' ' . $type : ''); // Resolve min $min = 0.0; if ($minParam !== '') { if (is_numeric($minParam)) { $min = (float)$minParam; } elseif (isset($row[$minParam]) && $row[$minParam] !== '') { $min = (float)$row[$minParam]; } elseif (isset($spec[$minParam]) && $spec[$minParam] !== '') { $min = (float)$spec[$minParam]; } } elseif (isset($spec[$element]) && $spec[$element] !== '') { $min = (float)$spec[$element] / 2; // fallback: half the spec average } // Resolve max + recommended display label $max = 0.0; $maxLabel = ''; if ($maxParam === 'soil_type') { $st = strtolower($row['soil_type'] ?? ''); $maxLabel = match($st) { 'light' => 'Light Soil', 'medium' => 'Medium Soil', 'heavy' => 'Heavy Soil', default => htmlspecialchars($row['soil_type'] ?? '', ENT_QUOTES, 'UTF-8'), }; } elseif ($maxParam !== '') { if (is_numeric($maxParam)) { $max = (float)$maxParam; } elseif (isset($row[$maxParam]) && $row[$maxParam] !== '') { $max = (float)$row[$maxParam]; } elseif (isset($spec[$maxParam]) && $spec[$maxParam] !== '') { $max = (float)$spec[$maxParam]; } } elseif (isset($spec[$element]) && $spec[$element] !== '') { $max = (float)$spec[$element] * 2; // fallback: double the spec average } // Recommended cell text $measurement = ($type !== '') ? ' ' . $type : ''; if ($maxParam === 'soil_type') { $recommended = $maxLabel; } elseif ($recV === 'n') { $recommended = ''; } elseif ($recV === 'ph') { $recommended = '6.4'; } elseif ($recV === 'max') { $recommended = number_format($max, $decimal, '.', '') . $measurement; } else { $recommended = number_format($min, $decimal, '.', '') . ' - ' . number_format($max, $decimal, '.', '') . $measurement; } $alignVal = match($text) { 'r' => 'text-right', 'l' => 'text-left', default => 'text-center' }; $alignRec = match($recText) { 'r' => 'text-right', 'l' => 'text-left', default => 'text-center' }; // Bar calculations (replicates original int-cast logic) $c_min = $min - ($max - $min); $c_max = $max + ($max - $min); $hasValue = ($rawVal !== null && $rawVal !== '' && $rawVal !== '0'); // First bar (deficit zone: c_min → min) if (!$hasValue || (int)($c_min - $min) == 0) { $fb = 0; } else { $fb = (int)($c_min - $value) / (int)($c_min - $min) * 100; } $fb = !$hasValue ? 0 : ($fb > 100 ? 100 : ($fb < 0 ? 2 : $fb)); // Second bar (ideal zone: min → max) if (!$hasValue || (int)($min - $max) == 0) { $sb = 0; } else { $sb = (int)($min - $value) / (int)($min - $max) * 100; } $sbp = ($fb < 100) ? 0 : ($sb < 0 ? 0 : ($sb > 101 ? 100 : $sb)); // Third bar (excess zone: max → c_max) if (!$hasValue || (int)($max - $c_max) == 0) { $tb = 0; } else { $tb = (int)($max - $value) / (int)($max - $c_max) * 100; } $tbp = ($sb < 100) ? 0 : ($tb < 0 ? 0 : ($tb > 101 ? 100 : $tb)); echo "\n"; echo " {$label}\n"; echo " {$recommended}\n"; echo " {$valueFmt}\n"; echo "
\n"; echo "
\n"; echo "
\n"; echo "\n"; } // ── Helper: render a ratio row ───────────────────────────────────────────── /** * Renders a for a calculated ratio (element ÷ elementTwo). * * Parameters ($p keys): * element string Numerator column in soil_records * elementTwo string Denominator column in soil_records * sbl string Chemical symbol * nutrient string Display name * rec string Column in soil_specifications for the recommended ratio * type string Unit suffix (e.g. ':1') * rec_text string Recommended alignment: c|r|l * decimal int Decimal places * graph string CSS class for progress-bar colour */ function soilRatio(array $row, array $spec, array $p): void { $element = $p['element'] ?? ''; $element2 = $p['elementTwo'] ?? ''; $sbl = $p['sbl'] ?? ''; $nutrient = $p['nutrient'] ?? ''; $rec = $p['rec'] ?? ''; $type = $p['type'] ?? ''; $recText = $p['rec_text'] ?? 'c'; $decimal = (int)($p['decimal'] ?? 1); $graph = $p['graph'] ?? ''; $label = ($sbl !== '') ? $sbl . ' - ' . $nutrient : $nutrient; $val1 = isset($row[$element]) && $row[$element] !== '' ? (float)$row[$element] : 0.0; $val2 = isset($row[$element2]) && $row[$element2] !== '' ? (float)$row[$element2] : 0.0; $ratio = ($val2 != 0) ? $val1 / $val2 : 0.0; $valueFmt = number_format($ratio, $decimal, '.', '') . ($type !== '' ? ' ' . $type : ''); $recommended = (isset($spec[$rec]) && $spec[$rec] !== '') ? htmlspecialchars($spec[$rec], ENT_QUOTES, 'UTF-8') : ''; $alignRec = match($recText) { 'r' => 'text-right', 'l' => 'text-left', default => 'text-center' }; echo "\n"; echo " {$label}\n"; echo " {$recommended}\n"; echo " {$valueFmt}\n"; echo "
\n"; echo "
\n"; echo "
\n"; echo "\n"; } // ── Page setup ───────────────────────────────────────────────────────────── $client = htmlspecialchars($row['client_name'] ?? '', ENT_QUOTES, 'UTF-8'); $address = htmlspecialchars($row['site_address'] ?? '', ENT_QUOTES, 'UTF-8'); $state = htmlspecialchars($row['state_postcode'] ?? '', ENT_QUOTES, 'UTF-8'); $email = htmlspecialchars($row['email'] ?? '', ENT_QUOTES, 'UTF-8'); $labNo = htmlspecialchars($row['lab_no'] ?? '', ENT_QUOTES, 'UTF-8'); $sampleDate = htmlspecialchars($row['date_sampled'] ?? '', ENT_QUOTES, 'UTF-8'); $sample = htmlspecialchars($row['site_id'] ?? '', ENT_QUOTES, 'UTF-8'); $crop = htmlspecialchars($row['sample_id'] ?? '', ENT_QUOTES, 'UTF-8'); $today = date('jS F Y'); $pageTitle = 'Soil Analysis Results' . ($client !== '' ? ' - ' . $client : ''); include __DIR__.'/../../../layouts/header.php'; ?>
Crop Monitor
DATE: SAMPLE ID:
CLIENT: DATE SAMPLED:
ADDRESS: LAB NUMBER:
CROP:
Soil Analysis Summary
'cec', 'nutrient'=>'CEC', 'recV'=>'n', 'decimal'=>2, 'graph'=>'lightorangeGraph']); soilRow($row, $spec, ['element'=>'tec', 'nutrient'=>'TEC', 'max'=>'soil_type', 'recV'=>'max', 'rec_text'=>'c', 'decimal'=>2, 'graph'=>'lightorangeGraph']); ?> 'ph_h2o', 'nutrient'=>'pH-level (H20)', 'type'=>'pH', 'recV'=>'ph', 'decimal'=>1, 'graph'=>'lightorangeGraph']); soilRow($row, $spec, ['element'=>'ph_cacl2', 'nutrient'=>'pH-level (CaCl2)', 'type'=>'pH', 'recV'=>'n', 'decimal'=>1, 'graph'=>'lightorangeGraph']); soilRow($row, $spec, ['element'=>'ec', 'nutrient'=>'Conductivity (EC)','type'=>'mS/cm', 'decimal'=>2, 'graph'=>'lightorangeGraph']); soilRow($row, $spec, ['element'=>'ocarbon', 'nutrient'=>'Organic Carbon', 'type'=>'%', 'decimal'=>1, 'graph'=>'lightorangeGraph']); soilRow($row, $spec, ['element'=>'omatter', 'nutrient'=>'Organic Matter', 'type'=>'%', 'decimal'=>1, 'graph'=>'lightorangeGraph']); ?> 'NO3_N', 'sbl'=>'NO3-N', 'nutrient'=>'Nitrate Nitrogen', 'min'=>'10', 'max'=>'20', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreenGraph']); soilRow($row, $spec, ['element'=>'NH3_N', 'sbl'=>'NH3-N', 'nutrient'=>'Ammonium Nitrogen', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreenGraph']); // p_mehlick, p_bray2, p_morgan excluded (commented in original) soilRow($row, $spec, ['element'=>'p_colwell', 'sbl'=>'P', 'nutrient'=>'Phosphate (colwell)', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreenGraph']); soilRow($row, $spec, ['element'=>'BS_ca_ppm', 'sbl'=>'Ca', 'nutrient'=>'Calcium', 'min'=>'ca_ppm_min', 'max'=>'ca_ppm_max', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>0, 'graph'=>'lightgreenGraph']); soilRow($row, $spec, ['element'=>'BS_mg_ppm', 'sbl'=>'Mg', 'nutrient'=>'Magnesium', 'min'=>'mg_ppm_min', 'max'=>'mg_ppm_max', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>0, 'graph'=>'lightgreenGraph']); soilRow($row, $spec, ['element'=>'BS_k_ppm', 'sbl'=>'K', 'nutrient'=>'Potassium', 'min'=>'k_ppm_min', 'max'=>'k_ppm_max', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>0, 'graph'=>'lightgreenGraph']); soilRow($row, $spec, ['element'=>'BS_na_ppm', 'sbl'=>'Na', 'nutrient'=>'Sodium', 'min'=>'na_ppm_min', 'max'=>'na_ppm_max', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>0, 'graph'=>'lightgreenGraph']); ?> 's_morgan', 'sbl'=>'S', 'nutrient'=>'Sulfur', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']); soilRow($row, $spec, ['element'=>'b_cacl2', 'sbl'=>'B', 'nutrient'=>'Boron', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']); soilRow($row, $spec, ['element'=>'mn_dtpa', 'sbl'=>'Mn', 'nutrient'=>'Manganese', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']); soilRow($row, $spec, ['element'=>'cu_dtpa', 'sbl'=>'Cu', 'nutrient'=>'Copper', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']); soilRow($row, $spec, ['element'=>'zn_dtpa', 'sbl'=>'Zn', 'nutrient'=>'Zinc', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']); soilRow($row, $spec, ['element'=>'fe_dtpa', 'sbl'=>'Fe', 'nutrient'=>'Iron', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']); soilRow($row, $spec, ['element'=>'al', 'sbl'=>'Al', 'nutrient'=>'Aluminium', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']); soilRow($row, $spec, ['element'=>'sl_cacl2', 'sbl'=>'Si', 'nutrient'=>'Silicon', 'type'=>'ppm', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>2, 'graph'=>'lightredGraph']); ?> 'BS_ca2', 'sbl'=>'Ca', 'nutrient'=>'Calcium', 'min'=>'cabs_min', 'max'=>'cabs_max', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>2, 'graph'=>'lightpurpleGraph']); soilRow($row, $spec, ['element'=>'BS_mg2', 'sbl'=>'Mg', 'nutrient'=>'Magnesium', 'min'=>'mgbs_min', 'max'=>'mgbs_max', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>2, 'graph'=>'lightpurpleGraph']); soilRow($row, $spec, ['element'=>'BS_k', 'sbl'=>'K', 'nutrient'=>'Potassium', 'min'=>'kbs_min', 'max'=>'kbs_max', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>2, 'graph'=>'lightpurpleGraph']); soilRow($row, $spec, ['element'=>'BS_na', 'sbl'=>'Na', 'nutrient'=>'Sodium', 'min'=>'nabs_min', 'max'=>'nabs_max', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>2, 'graph'=>'lightpurpleGraph']); soilRow($row, $spec, ['element'=>'BS_ob', 'nutrient'=>'Other Bases', 'max'=>'ob_rec', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>2, 'graph'=>'lightpurpleGraph']); soilRow($row, $spec, ['element'=>'BS_h', 'nutrient'=>'Hydrogen', 'max'=>'h_rec', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'recV'=>'max', 'decimal'=>2, 'graph'=>'lightpurpleGraph']); ?> 's_morgan', 'sbl'=>'Ca', 'nutrient'=>'Calcium', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreyGraph']); soilRow($row, $spec, ['element'=>'b_cacl2', 'sbl'=>'Mg', 'nutrient'=>'Magnesium', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreyGraph']); soilRow($row, $spec, ['element'=>'mn_dtpa', 'sbl'=>'K', 'nutrient'=>'Potassium', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreyGraph']); ?> 's_morgan', 'sbl'=>'Ca', 'nutrient'=>'Calcium', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>0, 'graph'=>'lightgreyGraph']); ?> 'ca_mehlick3', 'elementTwo'=>'mg_mehlick3', 'rec'=>'ca_mg_ratio', 'nutrient'=>'Ca:Mg Ratio', 'rec_text'=>'r', 'decimal'=>1, 'graph'=>'lightblueGraph']); soilRow ($row, $spec, ['element'=>'NH3_N', 'nutrient'=>'Total Nitrogen', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>1, 'graph'=>'lightblueGraph']); soilRow ($row, $spec, ['element'=>'ocarbon', 'nutrient'=>'Total Carbon', 'type'=>'%', 'text'=>'c', 'rec_text'=>'r', 'decimal'=>1, 'graph'=>'lightblueGraph']); soilRatio($row, $spec, ['element'=>'ocarbon', 'elementTwo'=>'NO3_N', 'rec'=>'c_n_ratio', 'nutrient'=>'C:N Ratio', 'type'=>':1', 'rec_text'=>'r', 'decimal'=>1, 'graph'=>'lightblueGraph']); ?>
ELEMENT STATUS
DESIRED FOUND LIGHT MEDIUM HEAVY
DEFICIT IDEAL HIGH
MAJOR ELEMENTS
TRACE ELEMENTS
BASE SATURATION
SOLUBLE MORGAN 2 EXTRACT
ADDITIONAL DATA LOW IDEAL EXCELLENT
RATIOS