merge: 최종 main을 토너먼트 즉시 조편성 수정에 통합
This commit is contained in:
@@ -165,20 +165,22 @@ const loadGeneralTurns = async (db: DatabaseClient, generalId: number): Promise<
|
||||
return buildTurnListFromRows(rows, MAX_GENERAL_TURNS);
|
||||
};
|
||||
|
||||
const loadGeneralAutorunLimit = async (db: DatabaseClient, generalId: number): Promise<number | null> => {
|
||||
const general = await db.general.findUnique({ where: { id: generalId }, select: { meta: true } });
|
||||
const rawAutorunLimit = isRecord(general?.meta) ? general.meta.autorun_limit : undefined;
|
||||
return typeof rawAutorunLimit === 'number' && Number.isFinite(rawAutorunLimit) ? Math.trunc(rawAutorunLimit) : null;
|
||||
};
|
||||
|
||||
export const getGeneralTurnSnapshot = async (db: DatabaseClient, generalId: number): Promise<ReservedTurnSnapshot> => {
|
||||
const [turns, revisionRow, general] = await Promise.all([
|
||||
const [turns, revisionRow, autorunLimit] = await Promise.all([
|
||||
loadGeneralTurns(db, generalId),
|
||||
db.generalTurnRevision.findUnique({ where: { generalId } }),
|
||||
db.general.findUnique({ where: { id: generalId }, select: { meta: true } }),
|
||||
loadGeneralAutorunLimit(db, generalId),
|
||||
]);
|
||||
const rawAutorunLimit = isRecord(general?.meta) ? general.meta.autorun_limit : undefined;
|
||||
return {
|
||||
revision: revisionRow?.revision ?? 0,
|
||||
turns: serializeTurnList(turns),
|
||||
autorunLimit:
|
||||
typeof rawAutorunLimit === 'number' && Number.isFinite(rawAutorunLimit)
|
||||
? Math.trunc(rawAutorunLimit)
|
||||
: null,
|
||||
autorunLimit,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -331,7 +333,7 @@ export const setGeneralTurns = async (
|
||||
}
|
||||
}
|
||||
await persistGeneralTurns(db, generalId, turns);
|
||||
return { revision, turns: serializeTurnList(turns) };
|
||||
return { revision, turns: serializeTurnList(turns), autorunLimit: await loadGeneralAutorunLimit(db, generalId) };
|
||||
};
|
||||
|
||||
export const setGeneralTurn = async (
|
||||
@@ -357,7 +359,7 @@ export const shiftGeneralTurns = async (
|
||||
const turns = await loadGeneralTurns(db, generalId);
|
||||
const shifted = applyShift(turns, amount);
|
||||
await persistGeneralTurns(db, generalId, shifted);
|
||||
return { revision, turns: serializeTurnList(shifted) };
|
||||
return { revision, turns: serializeTurnList(shifted), autorunLimit: await loadGeneralAutorunLimit(db, generalId) };
|
||||
};
|
||||
|
||||
export const repeatGeneralTurns = async (
|
||||
@@ -372,7 +374,7 @@ export const repeatGeneralTurns = async (
|
||||
const revision = await claimGeneralRevision(db, generalId, expectedRevision);
|
||||
const turns = applyRepeat(await loadGeneralTurns(db, generalId), amount);
|
||||
await persistGeneralTurns(db, generalId, turns);
|
||||
return { revision, turns: serializeTurnList(turns) };
|
||||
return { revision, turns: serializeTurnList(turns), autorunLimit: await loadGeneralAutorunLimit(db, generalId) };
|
||||
};
|
||||
|
||||
export const setNationTurns = async (
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
ReservedTurnRevisionConflictError,
|
||||
} from '../src/turns/reservedTurns.js';
|
||||
|
||||
const buildDb = () => {
|
||||
const buildDb = (autorunLimit: number | null = null) => {
|
||||
const generalTurns = new Map<number, GeneralTurnRow[]>();
|
||||
const nationTurns = new Map<string, NationTurnRow[]>();
|
||||
const generalRevisions = new Map<number, number>();
|
||||
@@ -45,7 +45,7 @@ const buildDb = () => {
|
||||
findFirst: async () => null,
|
||||
},
|
||||
general: {
|
||||
findUnique: async () => null,
|
||||
findUnique: async () => ({ meta: autorunLimit === null ? {} : { autorun_limit: autorunLimit } }),
|
||||
},
|
||||
city: {
|
||||
findUnique: async () => null,
|
||||
@@ -200,22 +200,25 @@ const buildDb = () => {
|
||||
|
||||
describe('reservedTurns', () => {
|
||||
it('sets and shifts general turns', async () => {
|
||||
const { db } = buildDb();
|
||||
const { db } = buildDb(2408);
|
||||
|
||||
const initial = await setGeneralTurn(db, 1, 0, 'che_화계', { destCityId: 10 }, 0);
|
||||
|
||||
expect(initial.revision).toBe(1);
|
||||
expect(initial.turns).toHaveLength(MAX_GENERAL_TURNS);
|
||||
expect(initial.turns[0]?.action).toBe('che_화계');
|
||||
expect(initial.autorunLimit).toBe(2408);
|
||||
|
||||
const pushed = await shiftGeneralTurns(db, 1, 1, initial.revision);
|
||||
expect(pushed.revision).toBe(2);
|
||||
expect(pushed.turns[0]?.action).toBe('휴식');
|
||||
expect(pushed.turns[1]?.action).toBe('che_화계');
|
||||
expect(pushed.autorunLimit).toBe(2408);
|
||||
|
||||
const pulled = await shiftGeneralTurns(db, 1, -1, pushed.revision);
|
||||
expect(pulled.turns[0]?.action).toBe('che_화계');
|
||||
expect(pulled.turns[MAX_GENERAL_TURNS - 1]?.action).toBe('휴식');
|
||||
expect(pulled.autorunLimit).toBe(2408);
|
||||
|
||||
await expect(setGeneralTurn(db, 1, 2, 'che_훈련', {}, 1)).rejects.toBeInstanceOf(
|
||||
ReservedTurnRevisionConflictError
|
||||
@@ -285,7 +288,7 @@ describe('reservedTurns', () => {
|
||||
});
|
||||
|
||||
it('repeats the leading general pattern at the legacy interval', async () => {
|
||||
const { db } = buildDb();
|
||||
const { db } = buildDb(2408);
|
||||
const seeded = await setGeneralTurns(
|
||||
db,
|
||||
4,
|
||||
@@ -309,6 +312,7 @@ describe('reservedTurns', () => {
|
||||
'che_사기진작',
|
||||
'che_징병',
|
||||
]);
|
||||
expect(repeated.autorunLimit).toBe(2408);
|
||||
});
|
||||
|
||||
it('supports nation bulk/repeat and preserves the legacy amount-12 no-op', async () => {
|
||||
|
||||
@@ -869,7 +869,7 @@ describe('appRouter', () => {
|
||||
});
|
||||
|
||||
it('validates and persists general command arguments from the authenticated owner', async () => {
|
||||
const general = buildGeneralRow({ id: 13 });
|
||||
const general = buildGeneralRow({ id: 13, meta: { autorun_limit: 2408 } });
|
||||
const writes: unknown[] = [];
|
||||
const changeJournal = new ChangeJournal();
|
||||
const caller = appRouter.createCaller(
|
||||
@@ -885,6 +885,7 @@ describe('appRouter', () => {
|
||||
});
|
||||
|
||||
expect(response.turns[0]).toMatchObject({ action: 'che_화계', args: { destCityId: 7 } });
|
||||
expect(response.autorunLimit).toBe(2408);
|
||||
expect(writes).toHaveLength(1);
|
||||
const written = writes[0] as { data: unknown[] };
|
||||
expect(written.data).toHaveLength(30);
|
||||
|
||||
Reference in New Issue
Block a user