diff --git a/frontend/css/views/inspector.css b/frontend/css/views/inspector.css index 27ae850..e504dbf 100644 --- a/frontend/css/views/inspector.css +++ b/frontend/css/views/inspector.css @@ -169,6 +169,25 @@ background: var(--primary-blue-light); } +.chain-item-row.chain-item-two-lines { + flex-direction: column; + align-items: stretch; + gap: 4px; +} + +.chain-item-header-line { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; +} + +.chain-item-sub-line { + display: flex; + align-items: center; + padding-left: 20px; +} + .chain-item-left { display: flex; align-items: center; diff --git a/frontend/js/ui/inspectorView.js b/frontend/js/ui/inspectorView.js index b67bad4..bd1daa9 100644 --- a/frontend/js/ui/inspectorView.js +++ b/frontend/js/ui/inspectorView.js @@ -117,12 +117,16 @@ export function mountInspector(container, state, onAction) { const parent = getProduct(inp.id); const parentStock = state.products[inp.id]?.stock || 0; return ` -
-
- - ${parent.name} +
+
+
+ + ${parent.name} +
+
+
+ ${inp.amount} per unit (${fmtNum(parentStock, 0)} on hand)
- ${inp.amount} per unit (${fmtNum(parentStock, 0)} on hand)
`; }).join('')} diff --git a/frontend/js/ui/production/facilityCard.js b/frontend/js/ui/production/facilityCard.js index 035cdbb..f14948b 100644 --- a/frontend/js/ui/production/facilityCard.js +++ b/frontend/js/ui/production/facilityCard.js @@ -48,17 +48,19 @@ export function renderFacilityCardHtml(p, pState, state, buyMode) { if (!isRaw) { inputsHtml = `
- Inputs per line: + Total Input Requirements (Operating Velocity):
${p.inputs.map(inp => { const inpProduct = getProduct(inp.id); const currentStock = state.products[inp.id]?.stock || 0; - const neededPerLine = inp.amount * pState.lines; - const isLow = currentStock < neededPerLine; + const neededPerBatch = inp.amount * pState.lines; + const reqRatePerSec = inp.amount * pState.lines * (rates.cyclesPerSec || 0); + const isLow = currentStock < neededPerBatch; return ` - + - ${inpProduct?.name}: ${fmtNum(currentStock, 0)} / ${fmtNum(neededPerLine, 0)} + ${inpProduct?.name}: ${fmtNum(currentStock, 0)} / ${fmtNum(neededPerBatch, 0)} + (${fmtNum(reqRatePerSec, 1)}/s) `; }).join('')} @@ -309,8 +311,9 @@ export function updateFacilityCardDom(p, pState, state, buyMode) { } } - // Input Chips Stock + // Input Chips Stock & Real-time Rate if (p.inputs && p.inputs.length > 0) { + const cyclesPerSec = rates.cyclesPerSec || 0; for (const inp of p.inputs) { const currentStock = state.products[inp.id]?.stock || 0; const elChipVal = document.getElementById(`chip-val-${p.id}-${inp.id}`); @@ -320,6 +323,14 @@ export function updateFacilityCardDom(p, pState, state, buyMode) { elChipVal.textContent = textVal; } } + const elChipRate = document.getElementById(`chip-rate-${p.id}-${inp.id}`); + if (elChipRate) { + const reqRatePerSec = inp.amount * pState.lines * cyclesPerSec; + const textRate = `(${fmtNum(reqRatePerSec, 1)}/s)`; + if (elChipRate.textContent !== textRate) { + elChipRate.textContent = textRate; + } + } const elChip = document.getElementById(`chip-${p.id}-${inp.id}`); if (elChip) { const needed = inp.amount * pState.lines; diff --git a/frontend/js/ui/production/ratesCalculator.js b/frontend/js/ui/production/ratesCalculator.js index 7d2d4ba..5a87e4d 100644 --- a/frontend/js/ui/production/ratesCalculator.js +++ b/frontend/js/ui/production/ratesCalculator.js @@ -35,7 +35,8 @@ export function getProductOutputRates(p, pState, state) { const isBottlenecked = !!pState.isBottlenecked; // Output velocity: units per second - const prodRate = isBottlenecked ? 0 : (1 / baseCycleTime) * p.outputAmount * pState.lines; + const cyclesPerSec = (1 / baseCycleTime); + const prodRate = isBottlenecked ? 0 : cyclesPerSec * p.outputAmount * pState.lines; // Logistics revenue rate: items sold passively per second * price const logisticsUnits = pState.logistics || 0; @@ -51,7 +52,7 @@ export function getProductOutputRates(p, pState, state) { revRate = effectiveSellRate * salePrice; } - return { prodRate, revRate, isBottlenecked, milestoneMult }; + return { prodRate, revRate, isBottlenecked, milestoneMult, baseCycleTime, cyclesPerSec }; } /**