diff --git a/app/components/tournament/AdminTeamControls.tsx b/app/components/tournament/AdminTeamControls.tsx index ff9eef284..fee28d15d 100644 --- a/app/components/tournament/AdminTeamControls.tsx +++ b/app/components/tournament/AdminTeamControls.tsx @@ -25,6 +25,9 @@ import { checkInHasStarted } from "~/core/tournament/utils"; import type { FindTournamentByNameForUrlI } from "~/services/tournament"; import type { Unpacked } from "~/utils"; +// TODO: https://docs.dndkit.com/presets/sortable#drag-overlay +// TODO: cursor flickers when going down the list +// TODO: grabbing cursor export function AdminTeamControls() { const [, parentRoute] = useMatches(); const { teams, checkInStartTime } = diff --git a/app/core/tournament/utils.test.ts b/app/core/tournament/utils.test.ts new file mode 100644 index 000000000..222e1b830 --- /dev/null +++ b/app/core/tournament/utils.test.ts @@ -0,0 +1,57 @@ +import { test } from "uvu"; +import * as assert from "uvu/assert"; +import { sortTeamsBySeed } from "./utils"; + +test("Sorts teams by seed", () => { + const seeds = ["3", "2", "1"]; + const teamsToSeed = [ + { id: "1", createdAt: "1639036511550" }, + { id: "2", createdAt: "1639036511550" }, + { id: "3", createdAt: "1639036511550" }, + ]; + + assert.equal(teamsToSeed.sort(sortTeamsBySeed(seeds)), [ + { id: "3", createdAt: "1639036511550" }, + { id: "2", createdAt: "1639036511550" }, + { id: "1", createdAt: "1639036511550" }, + ]); +}); + +test("Sorts teams by createdAt", () => { + const seeds: string[] = []; + const teamsToSeed = [ + { id: "1", createdAt: "1639036511550" }, + { id: "2", createdAt: "1639036511540" }, + { id: "3", createdAt: "1639036511530" }, + ]; + + assert.equal(teamsToSeed.sort(sortTeamsBySeed(seeds)), [ + { id: "3", createdAt: "1639036511530" }, + { id: "2", createdAt: "1639036511540" }, + { id: "1", createdAt: "1639036511550" }, + ]); +}); + +test("Sorts teams by seed and createdAt", () => { + const seeds: string[] = ["3"]; + const teamsToSeed = [ + { id: "1", createdAt: "1639036511550" }, + { id: "2", createdAt: "1639036511540" }, + { id: "3", createdAt: "1639036511560" }, + ]; + + assert.equal(teamsToSeed.sort(sortTeamsBySeed(seeds)), [ + { id: "3", createdAt: "1639036511560" }, + { id: "2", createdAt: "1639036511540" }, + { id: "1", createdAt: "1639036511550" }, + ]); +}); + +test("Sorting works with empty arrays", () => { + const seeds: string[] = []; + const teamsToSeed: any = []; + + assert.equal(teamsToSeed.sort(sortTeamsBySeed(seeds)), []); +}); + +test.run(); diff --git a/app/core/tournament/utils.ts b/app/core/tournament/utils.ts index 4edb3d59a..d9a1fa5ff 100644 --- a/app/core/tournament/utils.ts +++ b/app/core/tournament/utils.ts @@ -1,2 +1,26 @@ export const checkInHasStarted = (checkInStartTime: string) => new Date(checkInStartTime) < new Date(); + +export const sortTeamsBySeed = + (seeds: string[]) => + ( + a: { id: string; createdAt: string | Date }, + b: { id: string; createdAt: string | Date } + ) => { + const aSeed = seeds.indexOf(a.id); + const bSeed = seeds.indexOf(b.id); + + // if one team doesn't have seed and the other does + // the one with the seed takes priority + if (aSeed === -1 && bSeed !== -1) return 1; + if (aSeed !== -1 && bSeed === -1) return -1; + + // if both teams are unseeded the one who registered + // first gets to be seeded first as well + if (aSeed === -1 && bSeed === -1) { + return Number(a.createdAt) - Number(b.createdAt); + } + + // finally, consider the seeds + return aSeed - bSeed; + }; diff --git a/prisma/migrations/20211206205152_initial/migration.sql b/prisma/migrations/20211209072403_initial/migration.sql similarity index 99% rename from prisma/migrations/20211206205152_initial/migration.sql rename to prisma/migrations/20211209072403_initial/migration.sql index cfc4922d5..a8ea31629 100644 --- a/prisma/migrations/20211206205152_initial/migration.sql +++ b/prisma/migrations/20211209072403_initial/migration.sql @@ -41,6 +41,7 @@ CREATE TABLE "Tournament" ( "checkInStartTime" TIMESTAMP(3) NOT NULL, "bannerBackground" TEXT NOT NULL, "bannerTextHSLArgs" TEXT NOT NULL, + "seeds" TEXT[], "organizerId" TEXT NOT NULL, CONSTRAINT "Tournament_pkey" PRIMARY KEY ("id") diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 2074a6eb5..017116a1a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -29,7 +29,7 @@ model User { model Organization { id String @id @default(uuid()) name String - /// Name in lower case to show in URL + // Name in lower case to show in URL nameForUrl String @unique ownerId String @unique owner User @relation(fields: [ownerId], references: [id]) @@ -41,15 +41,19 @@ model Organization { model Tournament { id String @id @default(uuid()) name String - /// Name in lower case to show in URL + // Name in lower case to show in URL nameForUrl String description String startTime DateTime checkInStartTime DateTime - /// CSS for tournament banner's background value + // CSS for tournament banner's background value bannerBackground String - /// CSS for tournament banner's color value + // CSS for tournament banner's color value bannerTextHSLArgs String + // Team ID's in an array in the order of the seed. 0 index is 1st seed, 1 index is 2nd seed etc. + // Any team not in the list will be at the bottom in the order of their createdAt time stamp + // (older teams first) + seeds String[] mapPool Stage[] organizerId String organizer Organization @relation(fields: [organizerId], references: [id])