sendou.ink/app/features/sendouq-match/core/summarizer.server.ts
Kalle 7b71abfe53
Some checks are pending
E2E Tests / e2e (push) Waiting to run
Tests and checks on push / run-checks-and-tests (push) Waiting to run
Updates translation progress / update-translation-progress-issue (push) Waiting to run
Migrate SQ match queries to Kysely (#2782)
2026-02-21 13:48:18 +02:00

157 lines
3.5 KiB
TypeScript

import type { Tables } from "~/db/tables";
import * as Seasons from "~/features/mmr/core/Seasons";
import type { ModeShort, StageId } from "~/modules/in-game-lists/types";
import invariant from "~/utils/invariant";
import { winnersArrayToWinner } from "../q-match-utils";
type MatchForSummarizing = {
mapList: Array<{ mode: ModeShort; stageId: StageId }>;
groupAlpha: { id: number };
groupBravo: { id: number };
};
export function summarizeMaps({
match,
winners,
members,
}: {
match: MatchForSummarizing;
winners: ("ALPHA" | "BRAVO")[];
members: { id: number; groupId: number }[];
}) {
const season = Seasons.currentOrPrevious()?.nth;
invariant(typeof season === "number", "No ranked season for skills");
const result: Array<Tables["MapResult"]> = [];
const playedMaps = match.mapList.slice(0, winners.length);
for (const [i, map] of playedMaps.entries()) {
const winnerSide = winners[i];
const winnerGroupId =
winnerSide === "ALPHA" ? match.groupAlpha.id : match.groupBravo.id;
const winnerPlayers = members.filter((p) => p.groupId === winnerGroupId);
const loserPlayers = members.filter((p) => p.groupId !== winnerGroupId);
for (const winner of winnerPlayers) {
result.push({
userId: winner.id,
wins: 1,
losses: 0,
mode: map.mode,
stageId: map.stageId,
season,
});
}
for (const loser of loserPlayers) {
result.push({
userId: loser.id,
wins: 0,
losses: 1,
mode: map.mode,
stageId: map.stageId,
season,
});
}
}
return result;
}
export function summarizePlayerResults({
match,
winners,
members,
}: {
match: MatchForSummarizing;
winners: ("ALPHA" | "BRAVO")[];
members: { id: number; groupId: number }[];
}) {
const season = Seasons.currentOrPrevious()?.nth;
invariant(typeof season === "number", "No ranked season for skills");
const result: Array<Tables["PlayerResult"]> = [];
const addMapResult = ({
outcome,
type,
ownerUserId,
otherUserId,
}: {
outcome: "win" | "loss";
type: "MATE" | "ENEMY";
ownerUserId: number;
otherUserId: number;
}) => {
const existing = result.find(
(r) => r.ownerUserId === ownerUserId && r.otherUserId === otherUserId,
);
if (existing) {
if (outcome === "win") {
existing.mapWins++;
} else existing.mapLosses++;
} else {
result.push({
ownerUserId,
otherUserId,
type,
mapWins: outcome === "win" ? 1 : 0,
mapLosses: outcome === "win" ? 0 : 1,
season,
setLosses: 0,
setWins: 0,
});
}
};
for (const winner of winners) {
for (const member of members) {
for (const member2 of members) {
if (member.id === member2.id) continue;
const type = member.groupId === member2.groupId ? "MATE" : "ENEMY";
const won =
winner === "ALPHA"
? member.groupId === match.groupAlpha.id
: member.groupId === match.groupBravo.id;
addMapResult({
ownerUserId: member.id,
otherUserId: member2.id,
type,
outcome: won ? "win" : "loss",
});
}
}
}
const winner = winnersArrayToWinner(winners);
for (const member of members) {
for (const member2 of members) {
if (member.id === member2.id) continue;
const type = member.groupId === member2.groupId ? "MATE" : "ENEMY";
const won =
winner === "ALPHA"
? member.groupId === match.groupAlpha.id
: member.groupId === match.groupBravo.id;
result.push({
ownerUserId: member.id,
otherUserId: member2.id,
type,
mapWins: 0,
mapLosses: 0,
season,
setWins: won ? 1 : 0,
setLosses: won ? 0 : 1,
});
}
}
return result;
}