Files
RollCalcPython/static/direct_calc_handler.js

212 lines
8.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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');
});