diff --git a/templates/roll_calculator.html b/templates/roll_calculator.html index b38ddc1..5463d08 100644 --- a/templates/roll_calculator.html +++ b/templates/roll_calculator.html @@ -297,9 +297,23 @@ font-size: 13px; } .lo-summary-item:last-child { margin-bottom: 0; } + .lo-summary-item.lo-governing-summary { + background: #eef8f2; + border-left: 3px solid #2BAC70; + padding: 8px 10px; + border-radius: 4px; + } .lo-value-highlight { color: #2BAC70; font-weight: bold; font-size: 16px; } .lo-value-number { color: #1F5438; font-weight: bold; } .lo-util-group { display: flex; flex-direction: column; gap: 4px; text-align: right; } + .lo-reserve-note { + margin-top: 4px; + color: #666; + font-size: 12px; + line-height: 1.35; + text-align: right; + max-width: 300px; + } .lo-results-table { background: white; padding: 16px; @@ -315,10 +329,15 @@ font-weight: 600; color: #333; border-bottom: 2px solid #2BAC70; + white-space: normal; } .lo-results-table td { padding: 8px; border-bottom: 1px solid #e0e0e0; } .lo-results-table tbody tr:hover { background: #f9f9f9; } - .lo-results-table tbody tr.lo-recommended { background: #fffacd; font-weight: bold; } + .lo-results-table tbody tr.lo-governing { + background: #eef8f2; + font-weight: 600; + border-left: 3px solid #2BAC70; + } .lo-warning { background: #fff8e1; border: 1px solid #f0b429; @@ -807,9 +826,9 @@
-

Results:

-
- Limiting Factor: +

Capacity Summary:

+
+ Governing Constraint: –
@@ -827,18 +846,27 @@
Product: – m²
+
+ Remaining Capacity: +
+
Payload: – kg
+
Unused Payload: – %
+
Unused Volume: – %
+
+
+
-

Comparison Table:

+

Capacity Analysis:

- - - - - + + + + + @@ -1350,6 +1378,14 @@ class LoadOptimizerUI { showResults(res, maxW) { const m2PerRoll = this.optimizer.state.m2PerRoll || 0; + const remainingPayload = Math.max(0, maxW - res.finalWeight); + const unusedPayload = Math.max(0, 100 - res.utilizationWeight); + const unusedVolume = Math.max(0, 100 - res.utilizationVolume); + const interpretations = { + geometry: 'Payload remains available; no additional roll fits geometrically.', + weight: 'Payload limit is reached before volume or geometry.', + volume: 'Volume capacity is reached before payload or geometry.' + }; document.getElementById('limitingFactorValue').textContent = res.limiting.name; document.getElementById('totalRollsValue').textContent = res.finalRolls; document.getElementById('rollsDetailValue').textContent = @@ -1357,16 +1393,21 @@ class LoadOptimizerUI { document.getElementById('weightUtilValue').textContent = this.optimizer.fmt(res.utilizationWeight); document.getElementById('volumeUtilValue').textContent = this.optimizer.fmt(res.utilizationVolume); document.getElementById('productM2Value').textContent = this.optimizer.fmt(res.finalM2, 0); + document.getElementById('remainingPayloadValue').textContent = this.optimizer.fmt(remainingPayload, 0); + document.getElementById('unusedPayloadValue').textContent = this.optimizer.fmt(unusedPayload); + document.getElementById('unusedVolumeValue').textContent = this.optimizer.fmt(unusedVolume); + document.getElementById('capacityInterpretationValue').textContent = + interpretations[res.limiting.type] || ''; const tbody = document.querySelector('#comparisonTable tbody'); tbody.innerHTML = ''; res.scenarios.forEach(sc => { const tr = document.createElement('tr'); const lim = (sc.type === res.limiting.type); - if (lim) tr.classList.add('lo-recommended'); + if (lim) tr.classList.add('lo-governing'); const util = maxW > 0 ? (sc.weight / maxW * 100).toFixed(1) : '–'; const scM2 = isFinite(sc.rolls) && m2PerRoll > 0 ? Math.round(sc.rolls * m2PerRoll) : '–'; tr.innerHTML = - ''+ + ''+ ''+ ''+ ''+
ScenarioRollskgm²Util. %ConstraintTheoretical Max RollsTheoretical Total WeightTransported Area [m²]Payload Util. %
'+ sc.name +(lim?' ★':'')+''+ sc.name +(lim?' → Governing Constraint':'')+''+ (sc.rolls === Infinity ? '–' : sc.rolls) +''+ (isFinite(sc.weight) ? Math.round(sc.weight) : '–') +''+ scM2 +'