Files
RollCalcPython/static/stddev_calculator.js

121 lines
4.2 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.
/**
* ROLLCALC V14 - STANDARD DEVIATION CALCULATOR
* =============================================
* Calculates diameter & weight ranges (±2σ = 95% confidence)
* For use with article-data.json containing thickness_stddev & area_weight_stddev
*/
class StdDevCalculator {
/**
* Calculate weight ranges from area weight and stddev
* @param {number} areaWeight - Area weight in g/m²
* @param {number} areaWeightStddev - Standard deviation in g/m²
* @param {number} length - Product length in meters
* @param {number} width - Roll width in meters
* @returns {Object} {min, nom, max, aw_min, aw_nom, aw_max}
*/
static calculateWeightRanges(areaWeight, areaWeightStddev, length, width) {
if (!areaWeight || !length || !width) return null;
const sigma = areaWeightStddev || 0;
const aw_min = Math.max(0, areaWeight - 2 * sigma); // Worst case (lightest)
const aw_nom = areaWeight; // Nominal
const aw_max = areaWeight + 2 * sigma; // Best case (heaviest)
return {
min: (aw_min * length * width / 1000), // kg
nom: (aw_nom * length * width / 1000), // kg
max: (aw_max * length * width / 1000), // kg
aw_min: aw_min,
aw_nom: aw_nom,
aw_max: aw_max
};
}
/**
* Calculate diameter ranges from thickness and stddev
* NOTE: Thinner product → larger roll, thicker product → smaller roll
* @param {number} coreDiameter - Core diameter in mm
* @param {number} thickness - Product thickness in mm
* @param {number} thicknessStddev - Standard deviation in mm
* @param {number} productLength - Product length in meters
* @returns {Object} {min, nom, max, t_min, t_nom, t_max}
*/
static calculateDiameterRanges(coreDiameter, thickness, thicknessStddev, productLength) {
if (!coreDiameter || !thickness || !productLength) return null;
const d = coreDiameter;
const L = productLength * 1000; // Convert to mm
const sigma = thicknessStddev || 0;
// ±2σ = 95% confidence interval
const t_min = Math.max(0, thickness - 2 * sigma); // Thinnest product
const t_nom = thickness; // Nominal
const t_max = thickness + 2 * sigma; // Thickest product
// D = √(d² + 4Lt/π)
// Thinner product → larger D
// Thicker product → smaller D
const d_nom = Math.sqrt(d*d + (4*L*t_nom)/Math.PI);
const d_thin = Math.sqrt(d*d + (4*L*t_min)/Math.PI); // LARGEST roll
const d_thick = Math.sqrt(d*d + (4*L*t_max)/Math.PI); // SMALLEST roll
return {
min: d_thick, // SMALLEST (thickest product)
nom: d_nom, // NOMINAL
max: d_thin, // LARGEST (thinnest product)
t_min: t_min,
t_nom: t_nom,
t_max: t_max
};
}
/**
* Format diameter result with ±2σ ranges and tolerance
*/
static formatDiameterResult(diameterRanges, tolerance = 0) {
if (!diameterRanges) return '';
const d_low = Math.min(diameterRanges.min, diameterRanges.max);
const d_high = Math.max(diameterRanges.min, diameterRanges.max);
let text = `${diameterRanges.nom.toFixed(1)} mm (±2σ: ${d_low.toFixed(1)}–${d_high.toFixed(1)} mm)`;
if (tolerance && tolerance > 0) {
const d_tol_min = diameterRanges.nom - tolerance;
const d_tol_max = diameterRanges.nom + tolerance;
text += ` | Tolerance: ${d_tol_min.toFixed(1)}–${d_tol_max.toFixed(1)} mm`;
}
return text;
}
/**
* Format weight result
*/
static formatWeightResult(weightRanges) {
if (!weightRanges) return '';
return `${weightRanges.nom.toFixed(1)} kg (${weightRanges.min.toFixed(1)}–${weightRanges.max.toFixed(1)} kg)`;
}
/**
* Get worst-case weight for safety checks (Forklift, etc.)
*/
static getWorstCaseWeight(weightRanges) {
if (!weightRanges) return 0;
return Math.max(weightRanges.nom, weightRanges.max);
}
/**
* Get nominal weight for capacity planning
*/
static getNominalWeight(weightRanges) {
if (!weightRanges) return 0;
return weightRanges.nom;
}
}
// Export globally
window.StdDevCalculator = StdDevCalculator;
console.log('[StdDevCalculator] Module loaded');