ProductionGame/frontend/js/ui/production/ratesCalculator.js

79 lines
3.2 KiB
JavaScript

// Production UI: Cost & Rate Calculations
import { getNextMilestone, getUnitMilestoneMultiplier } from '../../data/products.js';
export function calculateMultiCost(baseCost, currentCount, multiplier) {
const growth = 1.15;
let countToBuy = 1;
if (multiplier === '1') countToBuy = 1;
else if (multiplier === '10') countToBuy = 10;
else if (multiplier === '100') countToBuy = 100;
else if (multiplier === 'next') {
const nextTarget = getNextMilestone(currentCount);
countToBuy = Math.max(1, nextTarget - currentCount);
} else if (multiplier === 'max') {
countToBuy = 1;
}
let totalCost = 0;
for (let i = 0; i < countToBuy; i++) {
totalCost += baseCost * Math.pow(growth, currentCount + i);
}
return { count: countToBuy, cost: totalCost };
}
/**
* Computes live individual factory output rates (units/s and wholesale revenue $/s)
*/
export function getProductOutputRates(p, pState, state) {
if (!pState || !pState.unlocked || !pState.lines || pState.lines <= 0) {
return { prodRate: 0, revRate: 0, isBottlenecked: false };
}
const milestoneMult = getUnitMilestoneMultiplier(pState.lines);
const roboticsMult = state.upgrades?.automated_robotics ? 2.0 : 1.0;
const baseCycleTime = Math.max(0.1, p.baseCycleTime / (milestoneMult * roboticsMult));
const isBottlenecked = !!pState.isBottlenecked;
// Output velocity: units per second
const prodRate = isBottlenecked ? 0 : (1 / baseCycleTime) * p.outputAmount * pState.lines;
// Logistics revenue rate: items sold passively per second * price
const logisticsUnits = pState.logistics || 0;
const logisticsPriceMult = state.upgrades?.global_supply_chain ? 1.5 : 1.0;
const salePrice = p.basePrice * logisticsPriceMult;
const maxSellCapacity = logisticsUnits * 0.75;
// If stockpiled, sells at max fleet capacity; otherwise bottlenecked by production velocity
const effectiveSellRate = Math.min(maxSellCapacity, pState.stock > 0 ? maxSellCapacity : prodRate);
const revRate = effectiveSellRate * salePrice;
return { prodRate, revRate, isBottlenecked, milestoneMult };
}
/**
* Computes global net supply chain flow (Production - Downstream Manufacturing Consumption - Logistics Sales)
*/
export function computeProductNetFlow(product, state) {
if (!state.products || !state.products[product.id]?.unlocked) {
return { netRate: 0, prodRate: 0, consumedRate: 0, soldRate: 0 };
}
const pState = state.products[product.id];
const { prodRate, isBottlenecked } = getProductOutputRates(product, pState, state);
const effectiveProd = isBottlenecked ? 0 : prodRate;
// Calculate how much active downstream factories consume per second
let consumedRate = 0;
// Import PRODUCTS dynamically from caller or check through global/state if needed
// In our architecture, caller passes or we compute from state.products and dependencies
const logisticsUnits = pState.logistics || 0;
const maxSellCapacity = logisticsUnits * 0.75;
const soldRate = Math.min(maxSellCapacity, pState.stock > 0 ? maxSellCapacity : effectiveProd);
return {
prodRate: effectiveProd,
soldRate,
netRate: effectiveProd - soldRate
};
}