sendou.ink/app/features/badges/queries/syncXPBadges.server.ts
Kalle 400f5ce301
Denormalize peak XP to SplatoonPlayer table (#2741)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 22:15:20 +02:00

57 lines
1.4 KiB
TypeScript

import { sql } from "~/db/sql";
import invariant from "~/utils/invariant";
import { SPLATOON_3_XP_BADGE_VALUES } from "../badges-constants";
import { findSplatoon3XpBadgeValue } from "../badges-utils";
const badgeCodeToIdStm = sql.prepare(/* sql */ `
select "id"
from "Badge"
where "code" = @code
`);
const deleteBadgeOwnerStm = sql.prepare(/* sql */ `
delete from "TournamentBadgeOwner"
where "badgeId" = @badgeId
`);
const userTopXPowersStm = sql.prepare(/* sql */ `
select
"SplatoonPlayer"."userId",
"SplatoonPlayer"."peakXp" as "xPower"
from
"SplatoonPlayer"
where "SplatoonPlayer"."userId" is not null
and "SplatoonPlayer"."peakXp" is not null
`);
const addXPBadgeStm = sql.prepare(/* sql */ `
insert into "TournamentBadgeOwner" ("badgeId", "userId")
values (
(select "id" from "Badge" where "code" = @code),
@userId
)
`);
export const syncXPBadges = sql.transaction(() => {
for (const value of SPLATOON_3_XP_BADGE_VALUES) {
const badgeId = (badgeCodeToIdStm.get({ code: String(value) }) as any)
.id as number;
invariant(badgeId, `Badge ${value} not found`);
deleteBadgeOwnerStm.run({ badgeId });
}
const userTopXPowers = userTopXPowersStm.all() as Array<{
userId: number;
xPower: number;
}>;
for (const { userId, xPower } of userTopXPowers) {
const badgeValue = findSplatoon3XpBadgeValue(xPower);
if (!badgeValue) continue;
addXPBadgeStm.run({ code: String(badgeValue), userId });
}
});