mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-10-02 08:07:40 -05:00
Adjust calendar event results table to deduplicate
This commit is contained in:
1
TODO.md
1
TODO.md
@@ -23,6 +23,7 @@ Calendar
|
||||
|
||||
## Other
|
||||
|
||||
- [ ] Redirect to event page after submitting results
|
||||
- [x] date input take in account time zone difference between server and client
|
||||
- [x] User selector allow passing users from top level
|
||||
- [x] Constants use CALENDAR_EVENT object
|
||||
|
||||
@@ -7,7 +7,8 @@ import type {
|
||||
Badge,
|
||||
CalendarEventTag,
|
||||
CalendarEventBadge,
|
||||
CalendarEventWinner,
|
||||
CalendarEventResultTeam,
|
||||
CalendarEventResultPlayer,
|
||||
} from "../types";
|
||||
|
||||
const createStm = sql.prepare(`
|
||||
@@ -137,72 +138,108 @@ const updateCalendarEventParticipantsCountStm = sql.prepare(`
|
||||
where "id" = $eventId
|
||||
`);
|
||||
|
||||
const deleteCalendarEventWinnersByEventIdStm = sql.prepare(`
|
||||
delete from "CalendarEventWinner"
|
||||
const deleteCalendarEventResultTeamsByEventIdStm = sql.prepare(`
|
||||
delete from "CalendarEventResultTeam"
|
||||
where "eventId" = $eventId
|
||||
`);
|
||||
|
||||
const insertCalendarEventWinnerStm = sql.prepare(`
|
||||
insert into "CalendarEventWinner" (
|
||||
const insertCalendarEventResultTeamStm = sql.prepare(`
|
||||
insert into "CalendarEventResultTeam" (
|
||||
"eventId",
|
||||
"teamName",
|
||||
"placement",
|
||||
"name",
|
||||
"placement"
|
||||
) values (
|
||||
$eventId,
|
||||
$name,
|
||||
$placement
|
||||
)
|
||||
returning *
|
||||
`);
|
||||
|
||||
const insertCalendarEventResultPlayerStm = sql.prepare(`
|
||||
insert into "CalendarEventResultPlayer" (
|
||||
"teamId",
|
||||
"userId",
|
||||
"name"
|
||||
) values (
|
||||
$eventId,
|
||||
$teamName,
|
||||
$placement,
|
||||
$teamId,
|
||||
$userId,
|
||||
$name
|
||||
)
|
||||
`);
|
||||
|
||||
export const upsertReportedScores = sql.transaction(
|
||||
({
|
||||
eventId,
|
||||
participantCount,
|
||||
winners,
|
||||
results,
|
||||
}: {
|
||||
eventId: CalendarEvent["id"];
|
||||
participantCount: CalendarEvent["participantCount"];
|
||||
winners: Array<
|
||||
Pick<CalendarEventWinner, "teamName" | "placement" | "userId" | "name">
|
||||
>;
|
||||
results: Array<{
|
||||
teamName: CalendarEventResultTeam["name"];
|
||||
placement: CalendarEventResultTeam["placement"];
|
||||
players: Array<{
|
||||
userId: CalendarEventResultPlayer["userId"];
|
||||
name: CalendarEventResultPlayer["name"];
|
||||
}>;
|
||||
}>;
|
||||
}) => {
|
||||
updateCalendarEventParticipantsCountStm.run({ eventId, participantCount });
|
||||
deleteCalendarEventWinnersByEventIdStm.run({ eventId });
|
||||
deleteCalendarEventResultTeamsByEventIdStm.run({ eventId });
|
||||
|
||||
for (const winner of winners) {
|
||||
insertCalendarEventWinnerStm.run({ ...winner, eventId });
|
||||
for (const { players, ...teamArgs } of results) {
|
||||
const teamInDb = insertCalendarEventResultTeamStm.get({
|
||||
eventId,
|
||||
name: teamArgs.teamName,
|
||||
placement: teamArgs.placement,
|
||||
}) as CalendarEventResultTeam;
|
||||
|
||||
for (const playerArgs of players) {
|
||||
insertCalendarEventResultPlayerStm.run({
|
||||
teamId: teamInDb.id,
|
||||
userId: playerArgs.userId,
|
||||
name: playerArgs.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const findWinnersByEventIdStm = sql.prepare(`
|
||||
select
|
||||
"teamName",
|
||||
"placement",
|
||||
"userId",
|
||||
"name"
|
||||
from "CalendarEventWinner"
|
||||
where "eventId" = $eventId
|
||||
"CalendarEventResultTeam"."id",
|
||||
"CalendarEventResultTeam"."name" as "teamName",
|
||||
"CalendarEventResultTeam"."placement",
|
||||
"CalendarEventResultPlayer"."userId" as "playerId",
|
||||
"CalendarEventResultPlayer"."name" as "playerName"
|
||||
from "CalendarEventResultTeam"
|
||||
join
|
||||
"CalendarEventResultPlayer"
|
||||
on
|
||||
"CalendarEventResultPlayer"."teamId" = "CalendarEventResultTeam"."id"
|
||||
where "CalendarEventResultTeam"."eventId" = $eventId
|
||||
order by "placement" asc
|
||||
`);
|
||||
|
||||
export function findWinnersByEventId(eventId: CalendarEvent["id"]) {
|
||||
const rows = findWinnersByEventIdStm.all({ eventId }) as Array<
|
||||
Pick<CalendarEventWinner, "teamName" | "placement" | "userId" | "name">
|
||||
>;
|
||||
const rows = findWinnersByEventIdStm.all({ eventId }) as Array<{
|
||||
id: CalendarEventResultTeam["id"];
|
||||
teamName: CalendarEventResultTeam["name"];
|
||||
placement: CalendarEventResultTeam["placement"];
|
||||
playerId: CalendarEventResultPlayer["userId"];
|
||||
playerName: CalendarEventResultPlayer["name"];
|
||||
}>;
|
||||
|
||||
const result: Array<{
|
||||
teamName: CalendarEventWinner["teamName"];
|
||||
placement: CalendarEventWinner["placement"];
|
||||
teamName: CalendarEventResultTeam["name"];
|
||||
placement: CalendarEventResultTeam["placement"];
|
||||
players: Array<string | { id: number }>;
|
||||
}> = [];
|
||||
|
||||
for (const row of rows) {
|
||||
const team = result.find((team) => team.teamName === row.teamName);
|
||||
const player = row.name ?? { id: row.userId! };
|
||||
const player = row.playerName ?? { id: row.playerId! };
|
||||
|
||||
if (team) {
|
||||
team.players.push(player);
|
||||
|
||||
@@ -19,7 +19,7 @@ const NZAP_TEST_DISCORD_ID = "455039198672453645";
|
||||
const NZAP_TEST_AVATAR = "f809176af93132c3db5f0a5019e96339"; // https://cdn.discordapp.com/avatars/455039198672453645/f809176af93132c3db5f0a5019e96339.webp?size=160
|
||||
const NZAP_TEST_ID = 2;
|
||||
|
||||
const AMOUNT_OF_CALENDAR_EVENTS = 100;
|
||||
const AMOUNT_OF_CALENDAR_EVENTS = 200;
|
||||
|
||||
const basicSeeds = [
|
||||
adminUser,
|
||||
@@ -48,7 +48,8 @@ export function seed() {
|
||||
function wipeDB() {
|
||||
const tablesToDelete = [
|
||||
"CalendarEventDate",
|
||||
"CalendarEventWinner",
|
||||
"CalendarEventResultPlayer",
|
||||
"CalendarEventResultTeam",
|
||||
"CalendarEventBadge",
|
||||
"CalendarEvent",
|
||||
"User",
|
||||
@@ -315,11 +316,15 @@ function patrons() {
|
||||
}
|
||||
}
|
||||
|
||||
function calendarEvents() {
|
||||
const userIds = sql
|
||||
function userIdsInRandomOrder() {
|
||||
return sql
|
||||
.prepare(`select "id" from "User" order by random()`)
|
||||
.all()
|
||||
.map((u) => u.id);
|
||||
}
|
||||
|
||||
function calendarEvents() {
|
||||
const userIds = userIdsInRandomOrder();
|
||||
|
||||
for (let id = 1; id <= AMOUNT_OF_CALENDAR_EVENTS; id++) {
|
||||
const tags = shuffle(Object.keys(allTags)).filter((tag) => tag !== "BADGE");
|
||||
@@ -369,7 +374,8 @@ function calendarEvents() {
|
||||
});
|
||||
|
||||
const twoDayEvent = Math.random() > 0.9;
|
||||
const startTime = faker.date.soon(42);
|
||||
const startTime =
|
||||
id % 2 === 0 ? faker.date.soon(42) : faker.date.recent(42);
|
||||
startTime.setMinutes(0, 0, 0);
|
||||
|
||||
sql
|
||||
|
||||
@@ -100,10 +100,15 @@ export interface CalendarEventDate {
|
||||
startTime: number;
|
||||
}
|
||||
|
||||
export interface CalendarEventWinner {
|
||||
export interface CalendarEventResultTeam {
|
||||
id: number;
|
||||
eventId: number;
|
||||
teamName: string;
|
||||
name: string;
|
||||
placement: number;
|
||||
}
|
||||
|
||||
export interface CalendarEventResultPlayer {
|
||||
teamId: number;
|
||||
userId: number | null;
|
||||
name: string | null;
|
||||
}
|
||||
|
||||
@@ -104,14 +104,14 @@ export const action: ActionFunction = async ({ request, params }) => {
|
||||
db.calendarEvents.upsertReportedScores({
|
||||
eventId: parsedParams.id,
|
||||
participantCount: parsedInput.data.participantCount,
|
||||
winners: parsedInput.data.team.flatMap((t) =>
|
||||
t.players.map((player) => ({
|
||||
teamName: t.teamName,
|
||||
placement: t.placement,
|
||||
userId: typeof player !== "string" ? player.id : null,
|
||||
name: typeof player === "string" ? player : null,
|
||||
}))
|
||||
),
|
||||
results: parsedInput.data.team.map((t) => ({
|
||||
teamName: t.teamName,
|
||||
placement: t.placement,
|
||||
players: t.players.map((p) => ({
|
||||
userId: typeof p === "string" ? null : p.id,
|
||||
name: typeof p === "string" ? p : null,
|
||||
})),
|
||||
})),
|
||||
});
|
||||
|
||||
return null;
|
||||
|
||||
@@ -29,14 +29,24 @@ module.exports.up = function (db) {
|
||||
|
||||
db.prepare(
|
||||
`
|
||||
create table "CalendarEventWinner" (
|
||||
create table "CalendarEventResultTeam" (
|
||||
"id" integer primary key,
|
||||
"eventId" integer not null,
|
||||
"teamName" text not null,
|
||||
"name" text not null,
|
||||
"placement" integer not null,
|
||||
foreign key ("eventId") references "CalendarEvent"("id") on delete cascade
|
||||
) strict
|
||||
`
|
||||
).run();
|
||||
|
||||
db.prepare(
|
||||
`
|
||||
create table "CalendarEventResultPlayer" (
|
||||
"teamId" integer not null,
|
||||
"userId" integer,
|
||||
"name" text,
|
||||
foreign key ("eventId") references "CalendarEvent"("id") on delete cascade,
|
||||
foreign key ("userId") references "User"("id") on delete cascade
|
||||
foreign key ("teamId") references "CalendarEventResultTeam"("id") on delete cascade,
|
||||
foreign key ("userId") references "User"("id") on delete restrict
|
||||
) strict
|
||||
`
|
||||
).run();
|
||||
@@ -57,7 +67,8 @@ module.exports.up = function (db) {
|
||||
module.exports.down = function (db) {
|
||||
for (const table of [
|
||||
"CalendarEventDate",
|
||||
"CalendarEventWinner",
|
||||
"CalendarEventResultPlayer",
|
||||
"CalendarEventResultTeam",
|
||||
"CalendarEventBadge",
|
||||
"CalendarEvent",
|
||||
]) {
|
||||
|
||||
Reference in New Issue
Block a user