Moteur de simulation (plan 1/2) #1

Merged
Mahtan merged 29 commits from feat/sim-core into main 2026-10-08 14:05:53 +02:00
2 changed files with 99 additions and 0 deletions
Showing only changes of commit 923b6bf080 - Show all commits

No files matched your search

+74
View File
@@ -0,0 +1,74 @@
import { GameDate, START_DATE } from './calendar';
import { STARTING_CASH_CENTS } from './economy';
import { createInventory, Inventory, ItemRef, itemKey } from './inventory';
import { createLoyaltyState, LoyaltyState } from './loyalty';
export const DAY_START_MINUTES = 8 * 60;
export const OPEN_MINUTES = 9 * 60;
export const CLOSE_MINUTES = 19 * 60;
export const SHELF_SLOT_COUNT = 12;
export interface DayStats {
revenueCents: number;
expensesCents: number;
salesCount: number;
lostRequests: number;
buyBacks: number;
trades: number;
}
export interface PendingOrder {
item: ItemRef;
qty: number;
}
export interface GameState {
saveVersion: 1;
date: GameDate;
minutes: number;
cash: number;
reputation: number; // 0-100
inventory: Inventory;
prices: Record<string, number>;
loyalty: LoyaltyState;
pendingOrders: PendingOrder[];
day: DayStats;
negativeMonthEnds: number;
bankrupt: boolean;
rngState: number;
nextCustomerId: number;
customerAccumulator: number;
}
export function emptyDayStats(): DayStats {
return { revenueCents: 0, expensesCents: 0, salesCount: 0, lostRequests: 0, buyBacks: 0, trades: 0 };
}
export function createNewGame(seed: number): GameState {
return {
saveVersion: 1,
date: { ...START_DATE },
minutes: DAY_START_MINUTES,
cash: STARTING_CASH_CENTS,
reputation: 20,
inventory: createInventory(SHELF_SLOT_COUNT),
prices: {},
loyalty: createLoyaltyState(),
pendingOrders: [],
day: emptyDayStats(),
negativeMonthEnds: 0,
bankrupt: false,
rngState: seed,
nextCustomerId: 1,
customerAccumulator: 0,
};
}
export function setPrice(state: GameState, item: ItemRef, cents: number): void {
if (cents <= 0) throw new Error('Price must be positive');
state.prices[itemKey(item)] = cents;
}
export function adjustReputation(state: GameState, delta: number): void {
state.reputation = Math.min(100, Math.max(0, state.reputation + delta));
}
+25
View File
@@ -0,0 +1,25 @@
import { describe, it, expect } from 'vitest';
import { createNewGame, DAY_START_MINUTES, setPrice, SHELF_SLOT_COUNT } from '../../src/sim/state';
import { START_DATE } from '../../src/sim/calendar';
import { STARTING_CASH_CENTS } from '../../src/sim/economy';
describe('state', () => {
it('creates a new game on 28/09/1990 at 8:00', () => {
const s = createNewGame(123);
expect(s.saveVersion).toBe(1);
expect(s.date).toEqual(START_DATE);
expect(s.minutes).toBe(DAY_START_MINUTES);
expect(s.cash).toBe(STARTING_CASH_CENTS);
expect(s.reputation).toBe(20);
expect(s.inventory.slots).toHaveLength(SHELF_SLOT_COUNT);
expect(s.rngState).toBe(123);
expect(s.bankrupt).toBe(false);
});
it('sets a positive price', () => {
const s = createNewGame(1);
setPrice(s, { gameId: 'tetris', condition: 'new' }, 2500);
expect(s.prices['tetris|new']).toBe(2500);
expect(() => setPrice(s, { gameId: 'tetris', condition: 'new' }, 0)).toThrow('Price must be positive');
});
});