75 lines
2.9 KiB
TypeScript
75 lines
2.9 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { chooseShelfItem, customersPerHour, spawnCustomer } from '../../src/sim/customers';
|
|
import { createNewGame, setPrice } from '../../src/sim/state';
|
|
import { issueCard } from '../../src/sim/loyalty';
|
|
import { makeCustomer, stock, testCatalog } from './helpers';
|
|
|
|
const catalog = testCatalog();
|
|
const tetrisNew = { gameId: 'tetris', condition: 'new' as const };
|
|
const smlNew = { gameId: 'sml', condition: 'new' as const };
|
|
|
|
describe('customers', () => {
|
|
it('comes more often with a better reputation', () => {
|
|
expect(customersPerHour(0)).toBeCloseTo(0.5);
|
|
expect(customersPerHour(100)).toBeCloseTo(4.5);
|
|
});
|
|
|
|
it('spawns a mix of intents with valid data', () => {
|
|
const s = createNewGame(99);
|
|
const counts = { buy: 0, request: 0, buy_back: 0, trade: 0 };
|
|
for (let i = 0; i < 2000; i++) {
|
|
const c = spawnCustomer(s, catalog);
|
|
counts[c.intent]++;
|
|
if (c.intent === 'request') expect(['tetris', 'sml']).toContain(c.wantedGameId);
|
|
if (c.intent === 'buy_back' || c.intent === 'trade') {
|
|
expect(c.offered).not.toBeNull();
|
|
expect(c.offered!.condition).not.toBe('new');
|
|
expect(c.offered!.gameId).not.toBe('future');
|
|
}
|
|
}
|
|
expect(counts.buy / 2000).toBeGreaterThan(0.45);
|
|
expect(counts.buy / 2000).toBeLessThan(0.65);
|
|
expect(counts.request).toBeGreaterThan(0);
|
|
expect(counts.buy_back).toBeGreaterThan(0);
|
|
expect(counts.trade).toBeGreaterThan(0);
|
|
expect(s.nextCustomerId).toBe(2001);
|
|
});
|
|
|
|
it('brings back card holders', () => {
|
|
const s = createNewGame(5);
|
|
for (let i = 0; i < 30; i++) issueCard(s.loyalty);
|
|
let returning = 0;
|
|
for (let i = 0; i < 1000; i++) if (spawnCustomer(s, catalog).cardId !== null) returning++;
|
|
expect(returning).toBeGreaterThan(300);
|
|
expect(returning).toBeLessThan(700);
|
|
});
|
|
|
|
it('picks nothing from empty shelves', () => {
|
|
const s = createNewGame(1);
|
|
expect(chooseShelfItem(s, catalog, makeCustomer())).toBeNull();
|
|
});
|
|
|
|
it('never picks an item priced at 150% or more of its reference', () => {
|
|
const s = createNewGame(2);
|
|
stock(s, 'slot-0', tetrisNew, 5);
|
|
setPrice(s, tetrisNew, 3034 * 2);
|
|
for (let i = 0; i < 200; i++) expect(chooseShelfItem(s, catalog, makeCustomer())).toBeNull();
|
|
});
|
|
|
|
it('usually buys well-priced popular games', () => {
|
|
const s = createNewGame(3);
|
|
stock(s, 'slot-0', smlNew, 5);
|
|
stock(s, 'slot-1', tetrisNew, 5);
|
|
let picks = 0;
|
|
for (let i = 0; i < 200; i++) if (chooseShelfItem(s, catalog, makeCustomer()) !== null) picks++;
|
|
expect(picks).toBeGreaterThan(150);
|
|
});
|
|
|
|
it('finds the requested game, or nothing', () => {
|
|
const s = createNewGame(4);
|
|
stock(s, 'slot-3', smlNew, 1);
|
|
expect(chooseShelfItem(s, catalog, makeCustomer({ intent: 'request', wantedGameId: 'sml' }))).toBe('slot-3');
|
|
expect(chooseShelfItem(s, catalog, makeCustomer({ intent: 'request', wantedGameId: 'tetris' }))).toBeNull();
|
|
});
|
|
});
|