fix: Ref 게임 로직과 시나리오 풀 호환을 보정
월 경계, 전투 기술 상한, 연감과 베팅·설문·경매 정산 순서를 Ref 계약에 맞춘다.\n\n시나리오 일반 풀을 ENGINE mutation과 logical tick 기반으로 직렬화하고 914·915 catalog 및 조건부 100기 pool 실행 경계를 추가한다.\n\n경매 worker는 세대별 durable event만 만들고 ENGINE이 row lock 후 상태 전이와 정산을 단일 transaction으로 소유한다.
This commit is contained in:
@@ -241,6 +241,49 @@ describe('TurnDaemonLifecycle', () => {
|
||||
expect(observedTargets[0]?.toISOString()).toBe('2042-01-01T02:59:59.999Z');
|
||||
});
|
||||
|
||||
it('limits an explicit manual run target to the next monthly boundary', async () => {
|
||||
const lastTurnTime = new Date('2042-01-01T00:00:00.000Z');
|
||||
const requestedTarget = addMinutes(lastTurnTime, 180);
|
||||
const queue = new InMemoryControlQueue();
|
||||
const processor: TurnProcessor = {
|
||||
run: vi.fn(async (target): Promise<TurnRunResult> => {
|
||||
queue.enqueue({ type: 'shutdown', reason: 'verified' });
|
||||
return {
|
||||
lastTurnTime: target.toISOString(),
|
||||
processedGenerals: 1,
|
||||
processedTurns: 1,
|
||||
durationMs: 0,
|
||||
partial: false,
|
||||
};
|
||||
}),
|
||||
};
|
||||
const lifecycle = new TurnDaemonLifecycle(
|
||||
{
|
||||
clock: new ManualClock(lastTurnTime.getTime()),
|
||||
controlQueue: queue,
|
||||
getNextTickTime: (value) => addMinutes(value, 60),
|
||||
stateStore: {
|
||||
loadLastTurnTime: async () => lastTurnTime,
|
||||
loadNextGeneralTurnTime: async () => addMinutes(lastTurnTime, 30),
|
||||
saveLastTurnTime: async () => {},
|
||||
loadCheckpoint: async () => undefined,
|
||||
saveCheckpoint: async () => {},
|
||||
},
|
||||
processor,
|
||||
},
|
||||
{
|
||||
profile: 'manual-explicit-boundary',
|
||||
defaultBudget: { budgetMs: 100, maxGenerals: 10, catchUpCap: 1 },
|
||||
}
|
||||
);
|
||||
|
||||
lifecycle.requestRun('manual', requestedTarget);
|
||||
await lifecycle.start();
|
||||
|
||||
expect(processor.run).toHaveBeenCalledOnce();
|
||||
expect((processor.run as ReturnType<typeof vi.fn>).mock.calls[0]?.[0]).toEqual(addMinutes(lastTurnTime, 60));
|
||||
});
|
||||
|
||||
it('produces the same command, RNG, and resource state in realtime and manual modes', async () => {
|
||||
const start = new Date('2042-01-01T00:00:00.000Z');
|
||||
const runMode = async (mode: 'realtime' | 'manual') => {
|
||||
|
||||
Reference in New Issue
Block a user