/** * DIRECT CALCULATION WITH STDDEV INTEGRATION * ========================================== * Replace the d-calc button handler in roll_calculator.html with this code * * This includes: * 1. Diameter calculation with ±2σ ranges * 2. Weight calculation with ±2σ ranges * 3. Forklift check with worst-case weight * 4. Load Optimizer integration with nominal values */ // This code should replace the existing d-calc button handler // Find: document.getElementById('d-calc').addEventListener('click', () => { ... }); // Replace with the code below: document.getElementById('d-calc')?.addEventListener('click', () => { console.log('[DirectCalc] Starting calculation...'); const mode = document.querySelector('.mode-btn.active')?.dataset.mode || 'diameter'; const d_mm = parseFloat(document.getElementById('d-co').value) || 0; const t_mm = parseFloat(document.getElementById('d-th').value) || 0; const tol = parseFloat(document.getElementById('d-tol').value) || 0; const L_m = parseFloat(document.getElementById('d-le').value) || 0; const D_mm = parseFloat(document.getElementById('d-di').value) || 0; const category = (document.getElementById('d-cat')?.value || '').toLowerCase(); const resBox = document.getElementById('d-result'); const resLabel = document.getElementById('d-res-label'); const resVal = document.getElementById('d-res-val'); const resRange = document.getElementById('d-res-range'); // ===================================================== // MODE: DIAMETER CALCULATION (with stddev) // ===================================================== if (mode === 'diameter') { if (!d_mm || !t_mm || !L_m) { alert('Please enter: Core Diameter (d), Product Thickness (t), and Product Length (L).'); return; } // Get stddev from data attribute (set during article selection) const t_stddev = parseFloat(document.getElementById('d-th')?.dataset.stddev || 0); // Calculate diameter ranges using StdDev calculator let diameterRanges = null; if (window.StdDevCalculator && t_stddev > 0) { diameterRanges = window.StdDevCalculator.calculateDiameterRanges(d_mm, t_mm, t_stddev, L_m); console.log('[DirectCalc] Diameter with stddev:', diameterRanges); } else { // Fallback: simple calculation without stddev const D_nom = Math.sqrt(d_mm*d_mm + (4*L_m*1000*t_mm)/Math.PI); diameterRanges = { min: D_nom, nom: D_nom, max: D_nom, t_min: t_mm, t_nom: t_mm, t_max: t_mm }; console.log('[DirectCalc] Diameter without stddev (nominal only):', D_nom.toFixed(1)); } // Display diameter result resLabel.textContent = 'Roll Diameter (D)'; resVal.textContent = diameterRanges.nom.toFixed(1) + ' mm'; if (t_stddev > 0) { const d_low = Math.min(diameterRanges.min, diameterRanges.max); const d_high = Math.max(diameterRanges.min, diameterRanges.max); let rangeText = `Range (±2σ): ${d_low.toFixed(1)}–${d_high.toFixed(1)} mm`; if (tol > 0) { const d_tol_min = diameterRanges.nom - tol; const d_tol_max = diameterRanges.nom + tol; rangeText += ` | Tolerance: ${d_tol_min.toFixed(1)}–${d_tol_max.toFixed(1)} mm`; } resRange.textContent = rangeText; } else { if (tol > 0) { const D_min = Math.sqrt(d_mm*d_mm + (4*L_m*1000*(t_mm-tol))/Math.PI); const D_max = Math.sqrt(d_mm*d_mm + (4*L_m*1000*(t_mm+tol))/Math.PI); resRange.textContent = `Tolerance: ${D_min.toFixed(1)}–${D_max.toFixed(1)} mm`; } else { resRange.textContent = ''; } } document.getElementById('d-di').value = diameterRanges.nom.toFixed(1); resBox.style.display = 'block'; // ===================================================== // WEIGHT CALCULATION WITH STDDEV // ===================================================== const wi = parseFloat(document.getElementById('de-wi').value) || 0; const aw = parseFloat(document.getElementById('d-aw').value) || 0; const aw_stddev = parseFloat(document.getElementById('d-aw')?.dataset.stddev || 0); let weightRanges = null; if (wi > 0 && aw > 0) { if (window.StdDevCalculator && aw_stddev > 0) { weightRanges = window.StdDevCalculator.calculateWeightRanges(aw, aw_stddev, L_m, wi); console.log('[DirectCalc] Weight with stddev:', weightRanges); } else { const w = (aw * L_m * wi / 1000); weightRanges = { min: w, nom: w, max: w }; console.log('[DirectCalc] Weight without stddev:', w.toFixed(1), 'kg'); } // Store weight in field with data attributes const woEl = document.getElementById('d-wo'); woEl.value = weightRanges.nom.toFixed(1); woEl.dataset.weight_nom = weightRanges.nom.toFixed(1); woEl.dataset.weight_min = weightRanges.min.toFixed(1); woEl.dataset.weight_max = weightRanges.max.toFixed(1); } // ===================================================== // FORKLIFT CHECK WITH WORST-CASE WEIGHT // ===================================================== if (window.ForkliftChecker && weightRanges) { const worstCaseWeight = Math.max(weightRanges.nom, weightRanges.max); const allowed = window.ForkliftChecker.evaluate(worstCaseWeight, d_mm, category); if (!allowed) { resBox.style.display = 'none'; // Hide result if blocked } console.log('[DirectCalc] Forklift check:', { nominal: weightRanges.nom.toFixed(1), worst_case: worstCaseWeight.toFixed(1), allowed: allowed }); } // ===================================================== // LOAD OPTIMIZER INTEGRATION (nominal values) // ===================================================== if (window.loadOptimizerUI && diameterRanges && weightRanges) { window.loadOptimizerUI.optimizer.setRollData({ rollDiameter: diameterRanges.nom, coreDiameter: d_mm, rollWidth: wi, rollWeight: weightRanges.nom, // Use nominal for capacity planning m2PerRoll: L_m * wi, productLength: L_m }); console.log('[DirectCalc] Load Optimizer updated with nominal values'); } } // ===================================================== // MODE: PRODUCT LENGTH CALCULATION // ===================================================== else if (mode === 'length') { if (!d_mm || !t_mm || !D_mm) { alert('Please enter: Core Diameter (d), Product Thickness (t), and Roll Diameter (D).'); return; } const L = (Math.PI / (4 * t_mm)) * (D_mm*D_mm - d_mm*d_mm) / 1000; resLabel.textContent = 'Product Length (L)'; resVal.textContent = L.toFixed(2) + ' m'; if (tol > 0) { const L_min = (Math.PI / (4*(t_mm+tol))) * (D_mm*D_mm - d_mm*d_mm) / 1000; const L_max = (Math.PI / (4*(t_mm-tol))) * (D_mm*D_mm - d_mm*d_mm) / 1000; resRange.textContent = `Range: ${L_min.toFixed(2)}–${L_max.toFixed(2)} m`; } else { resRange.textContent = ''; } document.getElementById('d-le').value = L.toFixed(2); resBox.style.display = 'block'; } // ===================================================== // MODE: TARGET DIAMETER // ===================================================== else if (mode === 'target') { if (!d_mm || !t_mm) { alert('Please enter: Core Diameter (d) and Product Thickness (t).'); return; } const D_target = D_mm || 800; const L = (Math.PI / (4 * t_mm)) * (D_target*D_target - d_mm*d_mm) / 1000; resLabel.textContent = `Product Length for Ø ${D_target} mm`; resVal.textContent = L.toFixed(2) + ' m'; resRange.textContent = ''; document.getElementById('d-le').value = L.toFixed(2); resBox.style.display = 'block'; } // ===================================================== // MODE: PRODUCT THICKNESS // ===================================================== else if (mode === 'thickness') { if (!d_mm || !D_mm || !L_m) { alert('Please enter: Core Diameter (d), Roll Diameter (D), and Product Length (L).'); return; } const t = (Math.PI / (4 * L_m * 1000)) * (D_mm*D_mm - d_mm*d_mm); resLabel.textContent = 'Product Thickness (t)'; resVal.textContent = t.toFixed(3) + ' mm'; resRange.textContent = ''; document.getElementById('d-th').value = t.toFixed(3); resBox.style.display = 'block'; } console.log('[DirectCalc] Calculation complete'); });