From 0704a1f967ee696fc88e2bdc782f18759594ed7e Mon Sep 17 00:00:00 2001 From: Hide_D Date: Fri, 23 Jan 2026 17:06:56 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=B0=B8=EA=B0=80=EC=9E=90=20=EC=A0=95?= =?UTF-8?q?=EB=A0=AC=20=EB=B0=8F=20=EC=B0=B8=EA=B0=80=EC=9E=90=20=EB=B3=B4?= =?UTF-8?q?=EC=9E=A5=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/game-api/src/tournament/worker.ts | 61 ++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/app/game-api/src/tournament/worker.ts b/app/game-api/src/tournament/worker.ts index 6171586..e285631 100644 --- a/app/game-api/src/tournament/worker.ts +++ b/app/game-api/src/tournament/worker.ts @@ -1,4 +1,4 @@ -import { createTournamentRng } from '@sammo-ts/common'; +import { asRecord, createTournamentRng } from '@sammo-ts/common'; import { resolveTournamentBattle, TournamentType } from '@sammo-ts/logic'; import { createGamePostgresConnector, @@ -377,6 +377,62 @@ const applyPreBattleStage = async ( return state; }; +const resolveParticipantOrder = (type: TournamentType): Array< + { leadership: 'desc' } | { strength: 'desc' } | { intel: 'desc' } | { id: 'asc' } +> => { + switch (type) { + case TournamentType.LEADERSHIP: + return [{ leadership: 'desc' }, { id: 'asc' }]; + case TournamentType.STRENGTH: + return [{ strength: 'desc' }, { id: 'asc' }]; + case TournamentType.INTEL: + return [{ intel: 'desc' }, { id: 'asc' }]; + case TournamentType.TOTAL: + default: + return [{ leadership: 'desc' }, { strength: 'desc' }, { intel: 'desc' }, { id: 'asc' }]; + } +}; + +const ensureParticipants = async ( + store: TournamentStore, + prisma: ReturnType['prisma'], + state: TournamentState, + limit: number +): Promise => { + const participants = await store.getParticipants(); + if (participants.length > 0) { + return; + } + + const generals = await prisma.general.findMany({ + orderBy: resolveParticipantOrder(state.type), + take: limit, + select: { + id: true, + name: true, + leadership: true, + strength: true, + intel: true, + meta: true, + }, + }); + + const snapshot = generals.map((general) => { + const meta = asRecord(general.meta); + const level = typeof meta.explevel === 'number' ? meta.explevel : 0; + return { + id: general.id, + name: general.name, + leadership: general.leadership, + strength: general.strength, + intel: general.intel, + level, + }; + }); + + await store.setParticipants(snapshot); +}; + export const runTournamentWorker = async (): Promise => { const config = resolveGameApiConfigFromEnv(); const postgres = createGamePostgresConnector(resolvePostgresConfigFromEnv({ schema: config.profile })); @@ -416,6 +472,9 @@ export const runTournamentWorker = async (): Promise => { const worldState = await postgres.prisma.worldState.findFirst(); const baseSeed = (worldState?.meta as Record | null)?.hiddenSeed ?? 'tournament'; let nextState = state; + if (isPreBattleStage(state.stage) && (state.stage === 1 || state.stage === 3 || state.stage === 4)) { + await ensureParticipants(store, postgres.prisma, state, 64); + } if (isBattleStage(state.stage)) { nextState = await applyBattle(store, state, String(baseSeed)); } else if (isPreBattleStage(state.stage)) {