New files for stdev calculation for v0.2
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* 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');
|
||||
});
|
||||
Reference in New Issue
Block a user