Add rack decommission pipeline stage
CI / build-and-push (push) Successful in 39s

Racks can now be marked for decommission from the DC view. The rack
leaves production immediately (freeing slot and power), enters the
pipeline as a timed decommission order, and is removed when complete.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-24 20:15:48 -04:00
parent 03ef94c22c
commit 24278297f0
4 changed files with 69 additions and 13 deletions
@@ -36,6 +36,7 @@ function stageTotal(stage: PipelineStage, order: RackOrder): number {
case 'installation': return timings.installation;
case 'testing': return timings.testing;
case 'repair': return RACK_REPAIR_BASE_TICKS;
case 'decommission': return timings.installation;
default: return 0;
}
}
@@ -44,7 +45,8 @@ function stageSpeed(stage: PipelineStage, engEff: number, opsEff: number): numbe
switch (stage) {
case 'manufacturing': return 1 + engEff * 0.1;
case 'installation':
case 'testing': return 1 + opsEff * 0.1;
case 'testing':
case 'decommission': return 1 + opsEff * 0.1;
case 'repair': return 1 + opsEff * 0.05;
default: return 1;
}
@@ -88,6 +90,16 @@ export function processInfrastructure(state: GameState): InfraTickResult {
continue;
}
if (order.stage === 'decommission') {
const sku = RACK_SKU_CONFIGS[order.skuId];
notifications.push({
title: 'Rack Decommissioned',
message: `${sku.name} rack has been fully decommissioned.`,
type: 'info',
});
continue;
}
if (order.stage === 'repair') {
const total = stageTotal('testing', order);
rackPipeline.push({
@@ -235,7 +247,7 @@ export function processInfrastructure(state: GameState): InfraTickResult {
usedPowerKW += sku.powerDrawKW;
}
const pipelineRacksForDc = rackPipeline.filter(o => o.dataCenterId === dc.id).length;
const pipelineRacksForDc = rackPipeline.filter(o => o.dataCenterId === dc.id && o.stage !== 'decommission').length;
const usedSlots = totalInDc + pipelineRacksForDc;
const energyCostPerTick = (tierConfig.baseEnergyCostPerTick + usedPowerKW * BASE_ENERGY_COST_PER_FLOP)