// Production - The Idle Game: Production Floor View
import { PRODUCTS, SECTORS, getProduct, getNextMilestone, getUnitMilestoneMultiplier } from '../data/products.js';
import { fmtCurrency, fmtNum } from '../core/formatters.js';
export function calculateMultiCost(baseCost, currentCount, multiplier) {
// Standard incremental scaling: cost = baseCost * 1.15^count
// For n purchases: sum(baseCost * 1.15^(count + i))
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; // Will be handled dynamically in loop
}
let totalCost = 0;
for (let i = 0; i < countToBuy; i++) {
totalCost += baseCost * Math.pow(growth, currentCount + i);
}
return { count: countToBuy, cost: totalCost };
}
export function renderProductionFloor(container, state, onAction) {
const selectedSector = state.selectedSector || 'all';
const buyMode = state.buyMode || '1';
const filteredProducts = PRODUCTS.filter(p => {
if (selectedSector === 'all') return true;
return p.sector === selectedSector;
});
let html = `
`;
for (const p of filteredProducts) {
const pState = state.products[p.id] || { unlocked: false, lines: 0, stock: 0, cycleProgress: 0, isBottlenecked: false };
const sector = SECTORS.find(s => s.id === p.sector);
const isSelected = state.selectedProductId === p.id;
if (!pState.unlocked) {
// Locked Card
const canAffordUnlock = state.cash >= p.unlockCost;
html += `
`;
continue;
}
// Unlocked Active Card
const nextM = getNextMilestone(pState.lines);
const milestoneMult = getUnitMilestoneMultiplier(pState.lines);
const calc = calculateMultiCost(p.baseFacilityCost, pState.lines, buyMode);
const canAffordBuy = state.cash >= calc.cost;
const managerCost = p.baseManagerCost;
const canAffordManager = state.cash >= managerCost;
const logisticsCost = p.baseLogisticsCost * Math.pow(1.15, pState.logistics || 0);
const canAffordLogistics = state.cash >= logisticsCost;
// Input Requirements status
const isRaw = !p.inputs || p.inputs.length === 0;
let inputsHtml = '';
if (!isRaw) {
inputsHtml = `
`;
}
let statusBadge = '';
if (pState.isBottlenecked) {
statusBadge = `
Waiting for Inputs`;
} else if (pState.lines > 0) {
statusBadge = `
Operating (${milestoneMult}x Speed)`;
} else {
statusBadge = `
Idle (0 Lines)`;
}
const progressPct = Math.min(100, Math.floor((pState.cycleProgress || 0) * 100));
html += `
Stockpile:
${fmtNum(pState.stock, 0)} ${p.unit}
Wholesale Price:
${fmtCurrency(p.basePrice)}
Logistics Fleet:
${pState.logistics || 0} fleets
${inputsHtml}
${!pState.manager ? `
` : `
Auto
`}
`;
}
html += `
`;
container.innerHTML = html;
// Attach delegated events
container.querySelectorAll('.sector-pill').forEach(btn => {
btn.onclick = () => onAction({ type: 'SELECT_SECTOR', sector: btn.dataset.sector });
});
container.querySelectorAll('.facility-card').forEach(card => {
card.onclick = (e) => {
if (e.target.closest('button')) return; // Ignore clicks on action buttons
onAction({ type: 'SELECT_PRODUCT', productId: card.dataset.product });
};
});
container.querySelectorAll('.btn-unlock').forEach(btn => {
btn.onclick = () => onAction({ type: 'UNLOCK_PRODUCT', productId: btn.dataset.product });
});
container.querySelectorAll('.btn-cycle').forEach(btn => {
btn.onclick = () => onAction({ type: 'MANUAL_CYCLE', productId: btn.dataset.product });
});
container.querySelectorAll('.btn-expand').forEach(btn => {
btn.onclick = () => onAction({ type: 'BUY_LINES', productId: btn.dataset.product });
});
container.querySelectorAll('.btn-hire-mgr').forEach(btn => {
btn.onclick = () => onAction({ type: 'HIRE_MANAGER', productId: btn.dataset.product });
});
container.querySelectorAll('.btn-expand-logistics').forEach(btn => {
btn.onclick = () => onAction({ type: 'BUY_LOGISTICS', productId: btn.dataset.product });
});
}