diff --git a/hooks/play.ts b/hooks/play.ts deleted file mode 100644 index 225d38baa..000000000 --- a/hooks/play.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { GetAllLadderRegisteredTeamsData } from "prisma/queries/getAllLadderRegisteredTeams"; -import useSWR from "swr"; - -export const useLadderTeams = (skip?: boolean) => - useSWR(skip ? null : "/api/play/teams"); diff --git a/pages/api/trpc/[trpc].ts b/pages/api/trpc/[trpc].ts index 291e43638..c2255a5eb 100644 --- a/pages/api/trpc/[trpc].ts +++ b/pages/api/trpc/[trpc].ts @@ -3,7 +3,6 @@ import { inferAsyncReturnType, inferProcedureOutput } from "@trpc/server"; import * as trpcNext from "@trpc/server/adapters/next"; import calendarApi from "routers/calendar"; import freeAgentsApi from "routers/freeagents"; -import playApi from "routers/play"; import plusApi from "routers/plus"; import superjson from "superjson"; import { getMySession } from "utils/api"; @@ -23,8 +22,7 @@ export function createRouter() { export const appRouter = createRouter() .merge("plus.", plusApi) .merge("calendar.", calendarApi) - .merge("freeAgents.", freeAgentsApi) - .merge("play.", playApi); + .merge("freeAgents.", freeAgentsApi); // Exporting type _type_ AppRouter only exposes types that can be used for inference // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export diff --git a/routers/play.ts b/routers/play.ts deleted file mode 100644 index f5c7d6356..000000000 --- a/routers/play.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { createRouter } from "pages/api/trpc/[trpc]"; -import service from "services/play"; - -const playApi = createRouter() - .query("allRegisteredTeams", { - resolve() { - return service.allRegisteredTeams(); - }, - }) - .query("nextLadderDay", { - resolve() { - return service.nextLadderDay(); - }, - }) - .query("previousLadderDay", { - resolve() { - return service.previousLadderDay(); - }, - }); -export default playApi; diff --git a/services/play.ts b/services/play.ts deleted file mode 100644 index 14aa5db50..000000000 --- a/services/play.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { Prisma } from ".prisma/client"; -import prisma from "prisma/client"; - -const allRegisteredTeams = async () => - prisma.ladderRegisteredTeam.findMany({ - include: { - roster: { - select: { - id: true, - discordAvatar: true, - discordId: true, - discriminator: true, - username: true, - team: { - select: { - name: true, - nameForUrl: true, - twitterName: true, - }, - }, - }, - }, - }, - }); - -const allLadderRegisteredTeamsForMatches = async () => - prisma.ladderRegisteredTeam.findMany({ - select: { - id: true, - roster: { - select: { - id: true, - trueSkill: true, - }, - }, - }, - }); - -export type NextLadderDay = Prisma.PromiseReturnType; - -const nextLadderDay = async () => { - return prisma.ladderDay.findFirst({ - where: { date: { gte: new Date() } }, - include: { - matches: { - select: { - order: true, - maplist: true, - teamAScore: true, - teamBScore: true, - players: { - select: { - team: true, - user: { - select: { - id: true, - discordAvatar: true, - discordId: true, - discriminator: true, - username: true, - team: { - select: { - name: true, - nameForUrl: true, - twitterName: true, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }); -}; - -export type PreviousLadderDay = Prisma.PromiseReturnType< - typeof previousLadderDay ->; - -const previousLadderDay = async () => { - return prisma.ladderDay.findFirst({ - where: { date: { lt: new Date() } }, - orderBy: { date: "desc" }, - select: { - date: true, - matches: { - select: { - order: true, - maplist: true, - teamAScore: true, - teamBScore: true, - players: { - select: { - team: true, - user: { - select: { - id: true, - discordAvatar: true, - discordId: true, - discriminator: true, - username: true, - team: { - select: { - name: true, - nameForUrl: true, - twitterName: true, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }); -}; - -const playService = { - allRegisteredTeams, - allLadderRegisteredTeamsForMatches, - nextLadderDay, - previousLadderDay, -}; - -export default playService; diff --git a/utils/play.ts b/utils/play.ts deleted file mode 100644 index a08f39ec8..000000000 --- a/utils/play.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { GetAllLadderRegisteredTeamsForMatchesData } from "prisma/queries/getAllLadderRegisteredTeamsForMatches"; -import { quality, Rating } from "ts-trueskill"; - -type TeamsWithRanking = { - id: number; - roster: { - id: number; - rating: Rating; - }[]; -}; - -export const getLadderRounds = ( - registeredTeams: GetAllLadderRegisteredTeamsForMatchesData -) => { - if (registeredTeams.length < 4) { - throw Error("registeredTeams length less than 4"); - } - const teamsWithRanking: TeamsWithRanking[] = registeredTeams.map( - (registeredTeam) => ({ - id: registeredTeam.id, - roster: registeredTeam.roster.map((user) => ({ - id: user.id, - rating: user.trueSkill - ? new Rating(user.trueSkill.mu, user.trueSkill.sigma) - : new Rating(), - })), - }) - ); - - // this chooses the teams to sit out each round if uneven number of teams - // if even it just returns `teamsWithRanking` in both 0 index and 1 index - const [teamsRoundOne, teamsRoundTwo] = getTeamsForRounds(); - - // helper variable accessed from generatePairings - let bestRound: TeamsWithRanking[][] | undefined; - // helper variable accessed from generatePairings - let bestAverageQuality = -Infinity; - - // first round matches actual - let firstRound: TeamsWithRanking[][] | undefined; - - generatePairings(teamsRoundOne, 0); - - firstRound = bestRound; - bestAverageQuality = -Infinity; - - generatePairings(teamsRoundTwo, 0); - - if (!firstRound || !bestRound || firstRound === bestRound) { - throw Error("unexpected falsy firstRound or bestPairs"); - } - - return [firstRound, bestRound]; - - // https://stackoverflow.com/a/37449857 - // start is the current position in the list, advancing by 2 each time - // pass 0 as start when calling at the top level - function generatePairings(items: TeamsWithRanking[], start: number) { - if (items.length % 2 !== 0) { - throw Error("uneven number of teams in generatePairings"); - } - - // is this a complete pairing? - if (start === items.length) { - if (hasDuplicatePairing()) { - return; - } - - let qualitySum = 0; - for (let i = 0; i < items.length; i += 2) { - const teamAlpha = items[i].roster.map((user) => user.rating); - const teamBravo = items[i + 1].roster.map((user) => user.rating); - - qualitySum += quality([teamAlpha, teamBravo]); - } - - qualitySum /= items.length / 2; - if (qualitySum > bestAverageQuality) { - bestAverageQuality = qualitySum; - bestRound = items - .map((team, i) => (i % 2 !== 0 ? null : [team, items[i + 1]])) - .filter((team) => team) as TeamsWithRanking[][]; - } - - return; - } - - // for the next pair, choose the first element in the list for the - // first item in the pair (meaning we don't have to do anything - // but leave it in place), and each of the remaining elements for - // the second item: - for (let j = start + 1; j < items.length; j++) { - // swap start+1 and j: - let temp = items[start + 1]; - items[start + 1] = items[j]; - items[j] = temp; - - // recurse: - generatePairings(items, start + 2); - - // swap them back: - temp = items[start + 1]; - items[start + 1] = items[j]; - items[j] = temp; - } - - function hasDuplicatePairing() { - if (!firstRound) return false; - - for (let i = 0; i < items.length; i += 2) { - const teamAlpha = items[i]; - const teamBravo = items[i + 1]; - - if ( - firstRound.some( - ([pairsAlpha, pairsBravo]) => - (pairsAlpha.id === teamAlpha.id && - pairsBravo.id === teamBravo.id) || - (pairsAlpha.id === teamBravo.id && pairsBravo.id === teamAlpha.id) - ) - ) { - return true; - } - } - - return false; - } - } - - function getTeamsForRounds() { - if (teamsWithRanking.length % 2 === 0) { - return [teamsWithRanking, teamsWithRanking]; - } - - const firstTeamToSitOut = randomChoiceIndex(); - let secondTeamToSitOut = randomChoiceIndex(); - while (secondTeamToSitOut === firstTeamToSitOut) { - secondTeamToSitOut = randomChoiceIndex(); - } - - return [ - teamsWithRanking.filter((_, i) => i !== firstTeamToSitOut), - teamsWithRanking.filter((_, i) => i !== secondTeamToSitOut), - ]; - - function randomChoiceIndex() { - return Math.floor(Math.random() * teamsWithRanking.length); - } - } -};