Spaces:
Sleeping
Sleeping
File size: 2,986 Bytes
336fa2c 469b970 6a25ae8 469b970 6a25ae8 336fa2c 469b970 336fa2c 6a25ae8 336fa2c 469b970 6a25ae8 336fa2c 469b970 336fa2c 469b970 336fa2c 469b970 6a25ae8 469b970 336fa2c 469b970 6a25ae8 469b970 336fa2c 469b970 6a25ae8 469b970 6a25ae8 336fa2c 6a25ae8 469b970 6a25ae8 336fa2c 469b970 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | /**
* engine/optimizer.js
* ืื ืืข ืืืืคืืืืฆืื (Imposition Engine) - V2 (Hardened)
* ====================================
* ืชืคืงืื: ืืืฉื ืืชืืืืช ืืื ืืืืืืช ื ืื ืกืืช ืืืืืืื SRA3.
* ืชืืงื: ืืืกืคืช Epsilon Guard ืืื ืืขืช ืืืชืื ืฉืืื ืืืื Floating Point (ืืืฉื ืืื ืข ื-2.99999998 ืืืคืื ื-2).
*/
const MACHINE_SPECS = {
// HP Indigo 7K specs (SRA3)
sheetWidth: 320, // mm
sheetHeight: 450, // mm
margins: 5, // mm (safety margin for gripper/bleed)
gutter: 2 // mm (space between cuts)
};
/**
* ืคืื ืงืฆืืืช ืขืืจ ืืืืืงื ืืืื ืช ืืคื ื ืฉืืืืืช Floating Point
*/
function safeFloorDivision(total, part) {
if (part <= 0) return 0;
// Number.EPSILON ืืืคื ืืืืืง ืขื ืืืกืคืจืื ืฉืืืจืืื ื-0.000000001
return Math.floor((total / part) + Number.EPSILON);
}
/**
* ืืืฉืื ืคืจืืกื ืืืคืืืืืืช (Best Fit)
* @param {number} prodWidth - ืจืืื ืืืฆืจ ืื"ื
* @param {number} prodHeight - ืืืื ืืืฆืจ ืื"ื
* @returns {object} { ups, layout, efficiency }
*/
function calculateImposition(prodWidth, prodHeight) {
// ืฉืื ื ืื ืืืืคืกื (ืืืืจ ืืคืืชืช ืฉืืื ืืืื ื)
const safeW = MACHINE_SPECS.sheetWidth - (MACHINE_SPECS.margins * 2);
const safeH = MACHINE_SPECS.sheetHeight - (MACHINE_SPECS.margins * 2);
// ืืื ื ืืคื ื ืงืื ืื ืชืงืื
if (!prodWidth || !prodHeight || prodWidth <= 0 || prodHeight <= 0) {
return { ups: 0, layout: 'error', efficiency: 0 };
}
// ืืืคืฆืื ื': ืืฉืจ (Portrait)
const fitW_A = safeFloorDivision(safeW, prodWidth + MACHINE_SPECS.gutter);
const fitH_A = safeFloorDivision(safeH, prodHeight + MACHINE_SPECS.gutter);
const total_A = fitW_A * fitH_A;
// ืืืคืฆืื ื': ืืกืืื (Landscape)
const fitW_B = safeFloorDivision(safeW, prodHeight + MACHINE_SPECS.gutter);
const fitH_B = safeFloorDivision(safeH, prodWidth + MACHINE_SPECS.gutter);
const total_B = fitW_B * fitH_B;
// ืืืืจืช ืืื ืฆื (ืืืคื ื ืื ืกืื ืืืชืจ?)
const maxUps = Math.max(total_A, total_B);
const bestLayout = total_A >= total_B ? 'portrait' : 'landscape';
// ืืืคืื ืืืื ืื ืืืืฆืจ ืืืื ืืื (ืืื ื ืขื ืืืขืจืืช ืืงืจืฉ ืขื ืืืืงื ืืืคืก)
if (maxUps === 0) {
return { ups: 0, layout: 'error', efficiency: "0.0%" };
}
// ืืืฉืื ืืืื ื ืืฆืื ืื ืืืจ (Efficiency) - ืืขืจื: ืืืืฉื ืืื ืฉืื ืืจืืื ืืืืื ื ืชืืืื
const usedArea = maxUps * prodWidth * prodHeight;
const totalArea = MACHINE_SPECS.sheetWidth * MACHINE_SPECS.sheetHeight;
const efficiencyNum = ((usedArea / totalArea) * 100).toFixed(1);
return {
ups: maxUps,
layout: bestLayout,
efficiency: efficiencyNum + "%"
};
}
module.exports = { calculateImposition }; |