mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-06-23 21:22:04 -05:00
235 lines
5.2 KiB
TypeScript
235 lines
5.2 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
import { db } from "~/db/sql";
|
|
import { dbInsertUsers, dbReset } from "~/utils/Test";
|
|
import type { TournamentSummary } from "../tournament-bracket/core/summarizer.server";
|
|
import * as TournamentRepository from "./TournamentRepository.server";
|
|
|
|
const createTournament = () =>
|
|
db
|
|
.insertInto("Tournament")
|
|
.values({
|
|
mapPickingStyle: "TO",
|
|
settings: JSON.stringify({ bracketProgression: [] }),
|
|
})
|
|
.returning("id")
|
|
.executeTakeFirstOrThrow();
|
|
|
|
const createTeam = (tournamentId: number) =>
|
|
db
|
|
.insertInto("TournamentTeam")
|
|
.values({
|
|
tournamentId,
|
|
name: "team",
|
|
inviteCode: `inv-${tournamentId}`,
|
|
})
|
|
.returning("id")
|
|
.executeTakeFirstOrThrow();
|
|
|
|
const insertPriorSkill = (args: {
|
|
userId: number;
|
|
season: number;
|
|
matchesCount: number;
|
|
}) =>
|
|
db
|
|
.insertInto("Skill")
|
|
.values({
|
|
userId: args.userId,
|
|
season: args.season,
|
|
matchesCount: args.matchesCount,
|
|
mu: 25,
|
|
sigma: 8.333,
|
|
ordinal: 0,
|
|
})
|
|
.execute();
|
|
|
|
const emptySummary = (
|
|
skills: TournamentSummary["skills"],
|
|
): TournamentSummary => ({
|
|
skills,
|
|
seedingSkills: [],
|
|
mapResultDeltas: [],
|
|
playerResultDeltas: [],
|
|
tournamentResults: [],
|
|
spDiffs: null,
|
|
setResults: new Map(),
|
|
});
|
|
|
|
const insertPriorTeamSkill = (args: {
|
|
identifier: string;
|
|
season: number;
|
|
matchesCount: number;
|
|
}) =>
|
|
db
|
|
.insertInto("Skill")
|
|
.values({
|
|
identifier: args.identifier,
|
|
season: args.season,
|
|
matchesCount: args.matchesCount,
|
|
mu: 25,
|
|
sigma: 8.333,
|
|
ordinal: 0,
|
|
})
|
|
.execute();
|
|
|
|
describe("TournamentRepository.finalize", () => {
|
|
beforeEach(async () => {
|
|
await dbInsertUsers(2);
|
|
});
|
|
afterEach(() => {
|
|
dbReset();
|
|
});
|
|
|
|
test("matchesCount on a new season's Skill row does not include prior seasons", async () => {
|
|
await insertPriorSkill({ userId: 1, season: 0, matchesCount: 100 });
|
|
|
|
const { id: tournamentId } = await createTournament();
|
|
|
|
await TournamentRepository.finalize({
|
|
tournamentId,
|
|
season: 1,
|
|
summary: emptySummary([
|
|
{
|
|
userId: 1,
|
|
identifier: null,
|
|
mu: 25,
|
|
sigma: 8.333,
|
|
matchesCount: 5,
|
|
},
|
|
]),
|
|
});
|
|
|
|
const inserted = await db
|
|
.selectFrom("Skill")
|
|
.select("matchesCount")
|
|
.where("userId", "=", 1)
|
|
.where("season", "=", 1)
|
|
.executeTakeFirstOrThrow();
|
|
|
|
expect(inserted.matchesCount).toBe(5);
|
|
});
|
|
|
|
test("team matchesCount on a new season's Skill row does not include prior seasons", async () => {
|
|
await insertPriorTeamSkill({
|
|
identifier: "1-2",
|
|
season: 0,
|
|
matchesCount: 100,
|
|
});
|
|
|
|
const { id: tournamentId } = await createTournament();
|
|
|
|
await TournamentRepository.finalize({
|
|
tournamentId,
|
|
season: 1,
|
|
summary: emptySummary([
|
|
{
|
|
userId: null,
|
|
identifier: "1-2",
|
|
mu: 25,
|
|
sigma: 8.333,
|
|
matchesCount: 5,
|
|
},
|
|
]),
|
|
});
|
|
|
|
const inserted = await db
|
|
.selectFrom("Skill")
|
|
.select("matchesCount")
|
|
.where("identifier", "=", "1-2")
|
|
.where("season", "=", 1)
|
|
.executeTakeFirstOrThrow();
|
|
|
|
expect(inserted.matchesCount).toBe(5);
|
|
});
|
|
|
|
test("finalizes and records placements when season is undefined (between-seasons tournament)", async () => {
|
|
await insertPriorSkill({ userId: 1, season: 0, matchesCount: 100 });
|
|
|
|
const { id: tournamentId } = await createTournament();
|
|
const { id: tournamentTeamId } = await createTeam(tournamentId);
|
|
|
|
await TournamentRepository.finalize({
|
|
tournamentId,
|
|
season: undefined,
|
|
summary: {
|
|
skills: [],
|
|
seedingSkills: [],
|
|
mapResultDeltas: [],
|
|
playerResultDeltas: [],
|
|
tournamentResults: [
|
|
{
|
|
userId: 1,
|
|
placement: 1,
|
|
participantCount: 1,
|
|
tournamentTeamId,
|
|
div: null,
|
|
},
|
|
],
|
|
spDiffs: null,
|
|
setResults: new Map([[1, ["W"]]]),
|
|
},
|
|
});
|
|
|
|
const tournament = await db
|
|
.selectFrom("Tournament")
|
|
.select("isFinalized")
|
|
.where("id", "=", tournamentId)
|
|
.executeTakeFirstOrThrow();
|
|
const newSkills = await db
|
|
.selectFrom("Skill")
|
|
.select("id")
|
|
.where("tournamentId", "=", tournamentId)
|
|
.execute();
|
|
const placement = await db
|
|
.selectFrom("TournamentResult")
|
|
.select("placement")
|
|
.where("tournamentId", "=", tournamentId)
|
|
.where("userId", "=", 1)
|
|
.executeTakeFirstOrThrow();
|
|
|
|
expect(tournament.isFinalized).toBe(1);
|
|
expect(newSkills).toHaveLength(0);
|
|
expect(placement.placement).toBe(1);
|
|
});
|
|
|
|
test("matchesCount accumulates across tournaments within the same season", async () => {
|
|
const { id: firstTournamentId } = await createTournament();
|
|
await TournamentRepository.finalize({
|
|
tournamentId: firstTournamentId,
|
|
season: 1,
|
|
summary: emptySummary([
|
|
{
|
|
userId: 1,
|
|
identifier: null,
|
|
mu: 25,
|
|
sigma: 8.333,
|
|
matchesCount: 5,
|
|
},
|
|
]),
|
|
});
|
|
|
|
const { id: secondTournamentId } = await createTournament();
|
|
await TournamentRepository.finalize({
|
|
tournamentId: secondTournamentId,
|
|
season: 1,
|
|
summary: emptySummary([
|
|
{
|
|
userId: 1,
|
|
identifier: null,
|
|
mu: 25,
|
|
sigma: 8.333,
|
|
matchesCount: 3,
|
|
},
|
|
]),
|
|
});
|
|
|
|
const second = await db
|
|
.selectFrom("Skill")
|
|
.select("matchesCount")
|
|
.where("userId", "=", 1)
|
|
.where("tournamentId", "=", secondTournamentId)
|
|
.executeTakeFirstOrThrow();
|
|
|
|
expect(second.matchesCount).toBe(8);
|
|
});
|
|
});
|