feat: 토너먼트 메타 조정 및 결과 처리 기능 추가
This commit is contained in:
@@ -421,6 +421,17 @@ export const tournamentRouter = router({
|
||||
throw new TRPCError({ code: 'BAD_REQUEST', message: adjustResult.reason });
|
||||
}
|
||||
|
||||
await ctx.turnDaemon.sendCommand({
|
||||
type: 'adjustGeneralMeta',
|
||||
reason: 'tournamentBet',
|
||||
adjustments: [
|
||||
{
|
||||
generalId: general.id,
|
||||
metaDelta: { rank_betgold: input.amount },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await store.appendBettingEntry({
|
||||
generalId: general.id,
|
||||
targetId: input.targetId,
|
||||
|
||||
@@ -33,13 +33,15 @@ import {
|
||||
seedNpcBets,
|
||||
sleepMs,
|
||||
sortByRanking,
|
||||
type TournamentMatchOutcome,
|
||||
type TournamentPrismaClient,
|
||||
} from './workerHelpers.js';
|
||||
|
||||
export const applyBattle = async (
|
||||
store: TournamentStore,
|
||||
state: TournamentState,
|
||||
baseSeed: string
|
||||
baseSeed: string,
|
||||
daemonTransport?: TurnDaemonTransport
|
||||
): Promise<TournamentState> => {
|
||||
const matches = await store.getMatches();
|
||||
const participants = await store.getParticipants();
|
||||
@@ -133,6 +135,16 @@ export const applyBattle = async (
|
||||
const nextMatches = matches.map((entry) => (entry.id === target.id ? updatedMatch : entry));
|
||||
await store.setMatches(nextMatches);
|
||||
|
||||
if (daemonTransport && attacker.id > 0 && defender.id > 0) {
|
||||
await daemonTransport.sendCommand({
|
||||
type: 'tournamentMatchResult',
|
||||
tournamentType: state.type,
|
||||
attackerId: attacker.id,
|
||||
defenderId: defender.id,
|
||||
result: result.draw ? 'draw' : result.winnerId === attacker.id ? 'attacker' : 'defender',
|
||||
});
|
||||
}
|
||||
|
||||
const nextPhase = state.phase + 1;
|
||||
const nextState: TournamentState = {
|
||||
...state,
|
||||
@@ -192,6 +204,7 @@ export const applyPreBattleStage = async (
|
||||
let updated = participants.some((entry) => entry.groupId === undefined)
|
||||
? assignGroupSlots(participants, 8, 8, 0)
|
||||
: participants;
|
||||
const outcomes: TournamentMatchOutcome[] = [];
|
||||
for (let groupId = 0; groupId < 8; groupId += 1) {
|
||||
const groupEntries = updated.filter((entry) => entry.groupId === groupId);
|
||||
const attacker = groupEntries.find((entry) => entry.groupNo === pair[0]);
|
||||
@@ -199,10 +212,28 @@ export const applyPreBattleStage = async (
|
||||
if (!attacker || !defender) {
|
||||
continue;
|
||||
}
|
||||
updated = applyGroupMatch(updated, attacker, defender, state, baseSeed, groupId);
|
||||
const result = applyGroupMatch(updated, attacker, defender, state, baseSeed, groupId);
|
||||
updated = result.participants;
|
||||
outcomes.push(result.outcome);
|
||||
}
|
||||
await store.setParticipants(updated);
|
||||
|
||||
if (outcomes.length > 0) {
|
||||
await Promise.all(
|
||||
outcomes
|
||||
.filter((outcome) => outcome.attackerId > 0 && outcome.defenderId > 0)
|
||||
.map((outcome) =>
|
||||
daemonTransport.sendCommand({
|
||||
type: 'tournamentMatchResult',
|
||||
tournamentType: state.type,
|
||||
attackerId: outcome.attackerId,
|
||||
defenderId: outcome.defenderId,
|
||||
result: outcome.result,
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const maxPhase = 55;
|
||||
const isComplete = state.phase >= maxPhase;
|
||||
if (isComplete) {
|
||||
@@ -310,6 +341,7 @@ export const applyPreBattleStage = async (
|
||||
throw new Error('본선 매치 구성을 찾을 수 없습니다.');
|
||||
}
|
||||
let updated = participants;
|
||||
const outcomes: TournamentMatchOutcome[] = [];
|
||||
for (let groupId = 10; groupId < 18; groupId += 1) {
|
||||
const groupEntries = updated.filter((entry) => entry.groupId === groupId);
|
||||
const attacker = groupEntries.find((entry) => entry.groupNo === pair[0]);
|
||||
@@ -317,10 +349,28 @@ export const applyPreBattleStage = async (
|
||||
if (!attacker || !defender) {
|
||||
continue;
|
||||
}
|
||||
updated = applyGroupMatch(updated, attacker, defender, state, baseSeed, groupId);
|
||||
const result = applyGroupMatch(updated, attacker, defender, state, baseSeed, groupId);
|
||||
updated = result.participants;
|
||||
outcomes.push(result.outcome);
|
||||
}
|
||||
await store.setParticipants(updated);
|
||||
|
||||
if (outcomes.length > 0) {
|
||||
await Promise.all(
|
||||
outcomes
|
||||
.filter((outcome) => outcome.attackerId > 0 && outcome.defenderId > 0)
|
||||
.map((outcome) =>
|
||||
daemonTransport.sendCommand({
|
||||
type: 'tournamentMatchResult',
|
||||
tournamentType: state.type,
|
||||
attackerId: outcome.attackerId,
|
||||
defenderId: outcome.defenderId,
|
||||
result: outcome.result,
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const maxPhase = 5;
|
||||
if (state.phase >= maxPhase) {
|
||||
for (let groupId = 10; groupId < 18; groupId += 1) {
|
||||
@@ -509,7 +559,7 @@ export const runTournamentWorker = async (): Promise<void> => {
|
||||
const baseSeed = (worldState?.meta as Record<string, unknown> | null)?.hiddenSeed ?? 'tournament';
|
||||
let nextState = state;
|
||||
if (isBattleStage(state.stage)) {
|
||||
nextState = await applyBattle(store, state, String(baseSeed));
|
||||
nextState = await applyBattle(store, state, String(baseSeed), daemonTransport);
|
||||
} else if (isPreBattleStage(state.stage)) {
|
||||
nextState = await applyPreBattleStage(
|
||||
store,
|
||||
|
||||
@@ -282,6 +282,12 @@ export const fillParticipants = async (options: {
|
||||
return result;
|
||||
};
|
||||
|
||||
export type TournamentMatchOutcome = {
|
||||
attackerId: number;
|
||||
defenderId: number;
|
||||
result: 'attacker' | 'defender' | 'draw';
|
||||
};
|
||||
|
||||
export const applyGroupMatch = (
|
||||
participants: TournamentParticipantEntry[],
|
||||
attacker: TournamentParticipantEntry,
|
||||
@@ -289,7 +295,7 @@ export const applyGroupMatch = (
|
||||
state: TournamentState,
|
||||
baseSeed: string,
|
||||
matchIndex: number
|
||||
): TournamentParticipantEntry[] => {
|
||||
): { participants: TournamentParticipantEntry[]; outcome: TournamentMatchOutcome } => {
|
||||
const result = resolveTournamentBattle({
|
||||
type: state.type,
|
||||
battleType: 0,
|
||||
@@ -325,7 +331,14 @@ export const applyGroupMatch = (
|
||||
|
||||
const glDelta = Math.round((result.totalDamage.defender - result.totalDamage.attacker) / 50);
|
||||
|
||||
return participants.map((entry) => {
|
||||
const outcome: TournamentMatchOutcome = {
|
||||
attackerId: attacker.id,
|
||||
defenderId: defender.id,
|
||||
result: result.draw ? 'draw' : result.winnerId === attacker.id ? 'attacker' : 'defender',
|
||||
};
|
||||
|
||||
return {
|
||||
participants: participants.map((entry) => {
|
||||
if (entry.id !== attacker.id && entry.id !== defender.id) {
|
||||
return entry;
|
||||
}
|
||||
@@ -348,7 +361,9 @@ export const applyGroupMatch = (
|
||||
next.lose += 1;
|
||||
next.gl -= glDelta;
|
||||
return next;
|
||||
});
|
||||
}),
|
||||
outcome,
|
||||
};
|
||||
};
|
||||
|
||||
export const sortByRanking = (entries: TournamentParticipantEntry[]): TournamentParticipantEntry[] =>
|
||||
@@ -632,5 +647,13 @@ export const seedNpcBets = async (options: {
|
||||
goldDelta: -betGold,
|
||||
})),
|
||||
});
|
||||
await daemonTransport.sendCommand({
|
||||
type: 'adjustGeneralMeta',
|
||||
reason: 'tournamentNpcBet',
|
||||
adjustments: npcBetList.map((npc) => ({
|
||||
generalId: npc.id as number,
|
||||
metaDelta: { rank_betgold: betGold },
|
||||
})),
|
||||
});
|
||||
await store.setBettingEntries(entries);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user