Overhaul dashboard into command center with compute tracking, era-gated sections
CI / build-and-push (push) Successful in 37s
CI / build-and-push (push) Successful in 37s
Add compute history time-series (capacity vs demand chart), revenue vs expenses dual-line chart, enhanced system status (training allocation, network uptime, model freshness), active operations panel, market position bars, and competitor snapshot. Stat cards expand from 3 to 6 as player progresses through eras. Graceful v9→v10 save migration preserves existing games. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type { GameState, ComputeState, InfrastructureState } from '@ai-tycoon/shared';
|
||||
import { FLOPS_TO_TOKENS_MULTIPLIER } from '@ai-tycoon/shared';
|
||||
import { FLOPS_TO_TOKENS_MULTIPLIER, COMPUTE_SNAPSHOT_INTERVAL, MAX_COMPUTE_HISTORY } from '@ai-tycoon/shared';
|
||||
import type { ResearchBonuses } from './researchBonuses';
|
||||
|
||||
export interface CapacityResult {
|
||||
@@ -43,19 +43,36 @@ export function computeCapacity(state: GameState, infrastructure: Infrastructure
|
||||
};
|
||||
}
|
||||
|
||||
export function finalizeCompute(capacity: CapacityResult, totalTokenDemand: number): ComputeState {
|
||||
export function finalizeCompute(capacity: CapacityResult, totalTokenDemand: number, prevHistory: ComputeState['computeHistory'], tickCount: number): ComputeState {
|
||||
const inferenceUtilization = capacity.tokensPerSecondCapacity > 0
|
||||
? Math.min(1, totalTokenDemand / capacity.tokensPerSecondCapacity)
|
||||
: (totalTokenDemand > 0 ? 1 : 0);
|
||||
|
||||
const computeHistory = [...prevHistory];
|
||||
if (tickCount % COMPUTE_SNAPSHOT_INTERVAL === 0) {
|
||||
computeHistory.push({
|
||||
tick: tickCount,
|
||||
totalFlops: capacity.totalFlops,
|
||||
effectiveTrainingFlops: capacity.effectiveTrainingFlops,
|
||||
effectiveInferenceFlops: capacity.effectiveInferenceFlops,
|
||||
inferenceUtilization,
|
||||
tokensPerSecondCapacity: capacity.tokensPerSecondCapacity,
|
||||
tokensPerSecondDemand: totalTokenDemand,
|
||||
});
|
||||
if (computeHistory.length > MAX_COMPUTE_HISTORY) {
|
||||
computeHistory.shift();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...capacity,
|
||||
tokensPerSecondDemand: totalTokenDemand,
|
||||
inferenceUtilization,
|
||||
computeHistory,
|
||||
};
|
||||
}
|
||||
|
||||
export function processCompute(state: GameState, infrastructure: InfrastructureState): ComputeState {
|
||||
const cap = computeCapacity(state, infrastructure);
|
||||
return finalizeCompute(cap, state.compute.tokensPerSecondDemand);
|
||||
return finalizeCompute(cap, state.compute.tokensPerSecondDemand, state.compute.computeHistory, state.meta.tickCount);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ export function processTick(state: GameState): Partial<GameState> {
|
||||
|
||||
const capacity = computeCapacity(state, infrastructure, researchBonuses);
|
||||
const market = processMarket(stateWithModels, capacity.tokensPerSecondCapacity, capacity.effectiveInferenceFlops, researchBonuses);
|
||||
const compute = finalizeCompute(capacity, market.totalTokenDemand);
|
||||
const compute = finalizeCompute(capacity, market.totalTokenDemand, state.compute.computeHistory, state.meta.tickCount);
|
||||
|
||||
const talent = processTalent(stateWithModels);
|
||||
const stateWithTalent = { ...stateWithModels, talent };
|
||||
|
||||
@@ -10,6 +10,8 @@ export const AUTO_SAVE_INTERVAL_TICKS = 60;
|
||||
export const FINANCIAL_SNAPSHOT_INTERVAL = 60;
|
||||
export const MAX_FINANCIAL_HISTORY = 1000;
|
||||
export const MAX_REPUTATION_HISTORY = 500;
|
||||
export const COMPUTE_SNAPSHOT_INTERVAL = 60;
|
||||
export const MAX_COMPUTE_HISTORY = 500;
|
||||
|
||||
export const STARTING_MONEY = 600_000;
|
||||
export const BASE_ENERGY_COST_PER_FLOP = 0.001;
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
export interface ComputeSnapshot {
|
||||
tick: number;
|
||||
totalFlops: number;
|
||||
effectiveTrainingFlops: number;
|
||||
effectiveInferenceFlops: number;
|
||||
inferenceUtilization: number;
|
||||
tokensPerSecondCapacity: number;
|
||||
tokensPerSecondDemand: number;
|
||||
}
|
||||
|
||||
export interface ComputeState {
|
||||
totalFlops: number;
|
||||
totalTrainingFlops: number;
|
||||
@@ -10,6 +20,7 @@ export interface ComputeState {
|
||||
inferenceUtilization: number;
|
||||
tokensPerSecondCapacity: number;
|
||||
tokensPerSecondDemand: number;
|
||||
computeHistory: ComputeSnapshot[];
|
||||
}
|
||||
|
||||
export const INITIAL_COMPUTE: ComputeState = {
|
||||
@@ -24,4 +35,5 @@ export const INITIAL_COMPUTE: ComputeState = {
|
||||
inferenceUtilization: 0,
|
||||
tokensPerSecondCapacity: 0,
|
||||
tokensPerSecondDemand: 0,
|
||||
computeHistory: [],
|
||||
};
|
||||
|
||||
@@ -52,4 +52,4 @@ export const INITIAL_SETTINGS: GameSettings = {
|
||||
musicVolume: 0.5,
|
||||
};
|
||||
|
||||
export const SAVE_VERSION = 9;
|
||||
export const SAVE_VERSION = 10;
|
||||
|
||||
Reference in New Issue
Block a user