diff --git a/app/db/tables.ts b/app/db/tables.ts index 96da07cd8..cbbc3c2a2 100644 --- a/app/db/tables.ts +++ b/app/db/tables.ts @@ -452,6 +452,7 @@ export interface ReportedWeapon { mapIndex: number; userId: number; weaponSplId: MainWeaponId; + createdAt: Generated; } export interface Skill { diff --git a/app/features/sendouq-match/ReportedWeaponRepository.server.ts b/app/features/sendouq-match/ReportedWeaponRepository.server.ts index 9502694e2..4b5d2cfdd 100644 --- a/app/features/sendouq-match/ReportedWeaponRepository.server.ts +++ b/app/features/sendouq-match/ReportedWeaponRepository.server.ts @@ -112,9 +112,11 @@ export async function upsertOneTournament({ mapIndex, userId, weaponSplId, + createdAt, }: TablesInsertable["ReportedWeapon"] & { tournamentMatchId: number; mapIndex: number; + createdAt: number; }) { await db .deleteFrom("ReportedWeapon") @@ -125,7 +127,7 @@ export async function upsertOneTournament({ await db .insertInto("ReportedWeapon") - .values({ tournamentMatchId, mapIndex, userId, weaponSplId }) + .values({ tournamentMatchId, mapIndex, userId, weaponSplId, createdAt }) .execute(); } @@ -197,14 +199,14 @@ export async function seasonReportedWeaponsByUserId({ const sendouqWeapons = db .selectFrom("ReportedWeapon") - .innerJoin("GroupMatch", "GroupMatch.id", "ReportedWeapon.groupMatchId") .select(({ fn }) => [ "ReportedWeapon.weaponSplId", fn.countAll().as("count"), ]) .where("ReportedWeapon.userId", "=", userId) - .where("GroupMatch.createdAt", ">=", startsTs) - .where("GroupMatch.createdAt", "<=", endsTs) + .where("ReportedWeapon.groupMatchId", "is not", null) + .where("ReportedWeapon.createdAt", ">=", startsTs) + .where("ReportedWeapon.createdAt", "<=", endsTs) .groupBy("ReportedWeapon.weaponSplId"); const tournamentWeapons = db @@ -220,27 +222,14 @@ export async function seasonReportedWeaponsByUserId({ "TournamentMatch.stageId", ) .innerJoin("Tournament", "Tournament.id", "TournamentStage.tournamentId") - .innerJoin("CalendarEvent", "CalendarEvent.tournamentId", "Tournament.id") - .innerJoin( - (eb) => - eb - .selectFrom("CalendarEventDate") - .select(({ fn }) => [ - "CalendarEventDate.eventId", - fn.min("CalendarEventDate.startTime").as("startTime"), - ]) - .groupBy("CalendarEventDate.eventId") - .as("EventStartTime"), - (join) => join.onRef("EventStartTime.eventId", "=", "CalendarEvent.id"), - ) .select(({ fn }) => [ "ReportedWeapon.weaponSplId", fn.countAll().as("count"), ]) .where("ReportedWeapon.userId", "=", userId) .where("Tournament.isFinalized", "=", 1) - .where("EventStartTime.startTime", ">=", startsTs) - .where("EventStartTime.startTime", "<=", endsTs) + .where("ReportedWeapon.createdAt", ">=", startsTs) + .where("ReportedWeapon.createdAt", "<=", endsTs) .groupBy("ReportedWeapon.weaponSplId"); const rows = await db diff --git a/app/features/tournament-match/actions/to.$id.matches.$mid.server.ts b/app/features/tournament-match/actions/to.$id.matches.$mid.server.ts index e1b8db9e5..ed7040d39 100644 --- a/app/features/tournament-match/actions/to.$id.matches.$mid.server.ts +++ b/app/features/tournament-match/actions/to.$id.matches.$mid.server.ts @@ -24,6 +24,7 @@ import { tournamentWebsocketRoom, } from "~/features/tournament-bracket/tournament-bracket-utils"; import * as TournamentMatchRepository from "~/features/tournament-match/TournamentMatchRepository.server"; +import { dateToDatabaseTimestamp } from "~/utils/dates"; import invariant from "~/utils/invariant"; import { logger } from "~/utils/logger"; import { @@ -784,6 +785,7 @@ export const action: ActionFunction = async ({ params, request }) => { mapIndex: data.mapIndex, userId: user.id, weaponSplId: data.weaponSplId, + createdAt: dateToDatabaseTimestamp(tournament.ctx.startTime), }); break; diff --git a/db-test.sqlite3 b/db-test.sqlite3 index 378de2d99..3d78d6a85 100644 Binary files a/db-test.sqlite3 and b/db-test.sqlite3 differ diff --git a/e2e/seeds/db-seed-AB_RR.sqlite3 b/e2e/seeds/db-seed-AB_RR.sqlite3 index ab7a5fc32..d54121e5a 100644 Binary files a/e2e/seeds/db-seed-AB_RR.sqlite3 and b/e2e/seeds/db-seed-AB_RR.sqlite3 differ diff --git a/e2e/seeds/db-seed-DEFAULT.sqlite3 b/e2e/seeds/db-seed-DEFAULT.sqlite3 index cbe7672f8..7cda91bea 100644 Binary files a/e2e/seeds/db-seed-DEFAULT.sqlite3 and b/e2e/seeds/db-seed-DEFAULT.sqlite3 differ diff --git a/e2e/seeds/db-seed-FINALIZED_BRACKET.sqlite3 b/e2e/seeds/db-seed-FINALIZED_BRACKET.sqlite3 index 53642ba78..78a91aa8d 100644 Binary files a/e2e/seeds/db-seed-FINALIZED_BRACKET.sqlite3 and b/e2e/seeds/db-seed-FINALIZED_BRACKET.sqlite3 differ diff --git a/e2e/seeds/db-seed-IN_SQ_MATCH.sqlite3 b/e2e/seeds/db-seed-IN_SQ_MATCH.sqlite3 index 776e87610..0a06ba5a2 100644 Binary files a/e2e/seeds/db-seed-IN_SQ_MATCH.sqlite3 and b/e2e/seeds/db-seed-IN_SQ_MATCH.sqlite3 differ diff --git a/e2e/seeds/db-seed-NO_SCRIMS.sqlite3 b/e2e/seeds/db-seed-NO_SCRIMS.sqlite3 index e953ad777..0834c38a5 100644 Binary files a/e2e/seeds/db-seed-NO_SCRIMS.sqlite3 and b/e2e/seeds/db-seed-NO_SCRIMS.sqlite3 differ diff --git a/e2e/seeds/db-seed-NO_SQ_GROUPS.sqlite3 b/e2e/seeds/db-seed-NO_SQ_GROUPS.sqlite3 index fad1e1b5e..2416fe361 100644 Binary files a/e2e/seeds/db-seed-NO_SQ_GROUPS.sqlite3 and b/e2e/seeds/db-seed-NO_SQ_GROUPS.sqlite3 differ diff --git a/e2e/seeds/db-seed-NO_TOURNAMENT_TEAMS.sqlite3 b/e2e/seeds/db-seed-NO_TOURNAMENT_TEAMS.sqlite3 index dc063fe31..d2ebbb102 100644 Binary files a/e2e/seeds/db-seed-NO_TOURNAMENT_TEAMS.sqlite3 and b/e2e/seeds/db-seed-NO_TOURNAMENT_TEAMS.sqlite3 differ diff --git a/e2e/seeds/db-seed-NZAP_IN_TEAM.sqlite3 b/e2e/seeds/db-seed-NZAP_IN_TEAM.sqlite3 index c7a9fd16f..c412600de 100644 Binary files a/e2e/seeds/db-seed-NZAP_IN_TEAM.sqlite3 and b/e2e/seeds/db-seed-NZAP_IN_TEAM.sqlite3 differ diff --git a/e2e/seeds/db-seed-REG_OPEN.sqlite3 b/e2e/seeds/db-seed-REG_OPEN.sqlite3 index 93f66a6b1..4dd205c7c 100644 Binary files a/e2e/seeds/db-seed-REG_OPEN.sqlite3 and b/e2e/seeds/db-seed-REG_OPEN.sqlite3 differ diff --git a/e2e/seeds/db-seed-SMALL_SOS.sqlite3 b/e2e/seeds/db-seed-SMALL_SOS.sqlite3 index 049f6a3ba..8e4b0ad27 100644 Binary files a/e2e/seeds/db-seed-SMALL_SOS.sqlite3 and b/e2e/seeds/db-seed-SMALL_SOS.sqlite3 differ diff --git a/e2e/seeds/db-seed-TEAM_MAP_PREFS.sqlite3 b/e2e/seeds/db-seed-TEAM_MAP_PREFS.sqlite3 index 43c2ff607..e14215013 100644 Binary files a/e2e/seeds/db-seed-TEAM_MAP_PREFS.sqlite3 and b/e2e/seeds/db-seed-TEAM_MAP_PREFS.sqlite3 differ diff --git a/migrations/141-reported-weapon-created-at.js b/migrations/141-reported-weapon-created-at.js new file mode 100644 index 000000000..3827f0790 --- /dev/null +++ b/migrations/141-reported-weapon-created-at.js @@ -0,0 +1,87 @@ +export function up(db) { + db.pragma("foreign_keys = OFF"); + + db.transaction(() => { + db.prepare( + /* sql */ ` + create table "ReportedWeapon_new" ( + "groupMatchId" integer, + "tournamentMatchId" integer, + "mapIndex" integer not null, + "weaponSplId" integer not null, + "userId" integer not null, + "createdAt" integer default (strftime('%s', 'now')) not null, + foreign key ("groupMatchId") references "GroupMatch"("id") on delete cascade, + foreign key ("tournamentMatchId") references "TournamentMatch"("id") on delete cascade, + foreign key ("userId") references "User"("id") on delete restrict, + unique("groupMatchId", "mapIndex", "userId") on conflict rollback, + unique("tournamentMatchId", "mapIndex", "userId") on conflict rollback, + check (("groupMatchId" is not null) <> ("tournamentMatchId" is not null)) + ) strict + `, + ).run(); + + db.prepare( + /* sql */ ` + insert into "ReportedWeapon_new" + ("groupMatchId", "tournamentMatchId", "mapIndex", "weaponSplId", "userId", "createdAt") + select + "rw"."groupMatchId", + "rw"."tournamentMatchId", + "rw"."mapIndex", + "rw"."weaponSplId", + "rw"."userId", + case + when "rw"."groupMatchId" is not null then ( + select "GroupMatch"."createdAt" + from "GroupMatch" + where "GroupMatch"."id" = "rw"."groupMatchId" + ) + else coalesce( + ( + select min("CalendarEventDate"."startTime") + from "CalendarEventDate" + inner join "CalendarEvent" + on "CalendarEvent"."id" = "CalendarEventDate"."eventId" + inner join "Tournament" + on "Tournament"."id" = "CalendarEvent"."tournamentId" + inner join "TournamentStage" + on "TournamentStage"."tournamentId" = "Tournament"."id" + inner join "TournamentMatch" + on "TournamentMatch"."stageId" = "TournamentStage"."id" + where "TournamentMatch"."id" = "rw"."tournamentMatchId" + ), + strftime('%s', 'now') + ) + end + from "ReportedWeapon" as "rw" + `, + ).run(); + + db.prepare(/* sql */ `drop table "ReportedWeapon"`).run(); + + db.prepare( + /* sql */ `alter table "ReportedWeapon_new" rename to "ReportedWeapon"`, + ).run(); + + db.prepare( + /* sql */ `create index reported_weapon_group_match_id on "ReportedWeapon"("groupMatchId")`, + ).run(); + + db.prepare( + /* sql */ `create index reported_weapon_tournament_match_id on "ReportedWeapon"("tournamentMatchId")`, + ).run(); + + db.prepare( + /* sql */ `create index reported_weapon_user_id on "ReportedWeapon"("userId")`, + ).run(); + + db.prepare( + /* sql */ `create index reported_weapon_user_created_at_weapon on "ReportedWeapon"("userId", "createdAt", "weaponSplId")`, + ).run(); + + db.pragma("foreign_key_check"); + })(); + + db.pragma("foreign_keys = ON"); +}