Merge branch 'main' into feature/command-option-context-20260813

This commit is contained in:
2026-08-13 16:13:22 +00:00
65 changed files with 2334 additions and 780 deletions
+30 -2
View File
@@ -137,7 +137,24 @@ export const tournamentRouter = router({
store.getMatches(),
store.getBettingEntries(),
]);
return { state, participants, matches, betCount: bets.length };
const participantIds = [...new Set(participants.map((participant) => participant.id))];
const iconRows =
participantIds.length === 0
? []
: await ctx.db.general.findMany({
where: { id: { in: participantIds } },
select: { id: true, picture: true, imageServer: true },
});
const iconsByGeneralId = new Map(iconRows.map((general) => [general.id, general]));
const publicParticipants = participants.map((participant) => {
const icon = iconsByGeneralId.get(participant.id);
return {
...participant,
picture: icon?.picture ?? null,
imageServer: icon?.imageServer ?? 0,
};
});
return { state, participants: publicParticipants, matches, betCount: bets.length };
}),
getRankings: authedProcedure.query(async ({ ctx }) => {
await getMyGeneral(ctx);
@@ -177,7 +194,16 @@ export const tournamentRouter = router({
}
const generals = await ctx.db.general.findMany({
where: { id: { in: [...rankMap.keys()] } },
select: { id: true, name: true, npcState: true, leadership: true, strength: true, intel: true },
select: {
id: true,
name: true,
npcState: true,
picture: true,
imageServer: true,
leadership: true,
strength: true,
intel: true,
},
});
return tournamentRankTypes.map((prefix) => {
@@ -201,6 +227,8 @@ export const tournamentRouter = router({
generalId: general.id,
name: general.name,
npcState: general.npcState,
picture: general.picture,
imageServer: general.imageServer,
stat,
games: win + draw + lose,
win,
@@ -84,6 +84,8 @@ const buildGeneral = (id: number, userId: string, gold = 2_000): GeneralRow =>
id,
userId,
name: `장수${id}`,
picture: `${id}.jpg`,
imageServer: id % 2,
leadership: 70 + id,
strength: 60 + id,
intel: 50 + id,
@@ -296,6 +298,10 @@ describe('tournament router permissions and mutations', () => {
const sections = await ownerCaller.tournament.getRankings();
expect(sections).toHaveLength(4);
expect(sections[0]?.entries.map((entry) => entry.generalId)).toEqual([second.id, first.id]);
expect(sections[0]?.entries[0]).toMatchObject({
picture: '2.jpg',
imageServer: 0,
});
const generalLessCaller = appRouter.createCaller(
buildContext({ redis, transport, generals: [first, second], userId: 'user-3', rankRows })
@@ -303,6 +309,33 @@ describe('tournament router permissions and mutations', () => {
await expect(generalLessCaller.tournament.getRankings()).rejects.toMatchObject({ code: 'NOT_FOUND' });
});
it('joins current dedicated icon metadata to the public tournament snapshot', async () => {
const redis = new MemoryRedis();
const transport = new TournamentTransport();
const owner = buildGeneral(11, 'user-1');
const rival = buildGeneral(12, 'user-2');
await setTournamentFixture(redis, {
stage: 7,
phase: 0,
type: 0,
auto: true,
openYear: 193,
openMonth: 1,
termSeconds: 60,
nextAt: '2026-07-26T01:00:00.000Z',
});
const caller = appRouter.createCaller(
buildContext({ redis, transport, generals: [owner, rival], userId: 'user-1' })
);
const snapshot = await caller.tournament.getSnapshot();
expect(snapshot.participants).toEqual([
expect.objectContaining({ id: 11, picture: '11.jpg', imageServer: 1 }),
expect.objectContaining({ id: 12, picture: '12.jpg', imageServer: 0 }),
]);
});
it('refunds gold when the tournament bet rank update fails', async () => {
const redis = new MemoryRedis();
const transport = new TournamentTransport();