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