Splatoon 3 XP badges

This commit is contained in:
Kalle 2023-07-01 13:14:29 +03:00
parent efb95bd93f
commit 4162bb76e2
35 changed files with 91 additions and 1 deletions

View File

@ -73,3 +73,16 @@ export const CUSTOMIZED_CSS_VARS_NAME = "css";
export const MAX_AP = 57;
export const ONE_HOUR_IN_MS = 60 * 60 * 1000;
export const SPLATOON_3_XP_BADGE_VALUES = [
3400, 3300, 3200, 3100, 3000, 2900, 2800, 2700, 2600,
] as const;
export const findSplatoon3XpBadgeValue = (xPower: number) => {
for (const value of SPLATOON_3_XP_BADGE_VALUES) {
if (xPower >= value) {
return value;
}
}
return null;
};

View File

@ -34,6 +34,7 @@ import forcePatronSql from "./forcePatron.sql";
import makeVideoAdderSql from "./makeVideoAdder.sql";
import linkPlayerSql from "./linkPlayer.sql";
import unlinkPlayerSql from "./unlinkPlayer.sql";
import { syncXPBadges } from "~/features/badges";
const upsertStm = sql.prepare(upsertSql);
export function upsert(
@ -279,4 +280,5 @@ export function linkPlayer({
}) {
unlinkPlayerStm.run({ userId });
linkPlayerStm.run({ userId, playerId });
syncXPBadges();
}

View File

@ -0,0 +1 @@
export { syncXPBadges } from "./queries/syncXPBadges.server";

View File

@ -0,0 +1,60 @@
import invariant from "tiny-invariant";
import {
SPLATOON_3_XP_BADGE_VALUES,
findSplatoon3XpBadgeValue,
} from "~/constants";
import { sql } from "~/db/sql";
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",
max("XRankPlacement"."power") as "xPower"
from
"SplatoonPlayer"
left join "XRankPlacement" on "XRankPlacement"."playerId" = "SplatoonPlayer"."id"
where "SplatoonPlayer"."userId" is not null
group by "SplatoonPlayer"."userId"
`);
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
.pluck()
.get({ code: String(value) }) 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 });
}
});

View File

@ -18,6 +18,7 @@ import { BADGES_PAGE } from "~/utils/urls";
import { type BadgesLoaderData } from "../badges";
import { type TFunction } from "react-i18next";
import { useTranslation } from "~/hooks/useTranslation";
import { SPLATOON_3_XP_BADGE_VALUES } from "~/constants";
export interface BadgeDetailsContext {
badgeName: string;
@ -104,7 +105,10 @@ export function badgeExplanationText(
if (badge.code === "patreon_plus") {
return t("patreon+");
}
if (badge.code.startsWith("xp")) {
if (
badge.code.startsWith("xp") ||
SPLATOON_3_XP_BADGE_VALUES.includes(Number(badge.code) as any)
) {
return t("xp", { xpText: badge.displayName });
}

View File

@ -24,6 +24,7 @@
"replace-weapon-names": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/replace-weapon-names.ts",
"placements": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/placements/index.ts",
"hex-to-filter": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/hex-to-filter.ts",
"sync-xp-badges": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/sync-xp-badges.ts",
"lint:ts": "eslint . --ext .ts,.tsx",
"lint:css": "stylelint \"app/styles/**/*.css\"",
"prettier:check": "prettier --check . --loglevel warn",

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -6,6 +6,7 @@ import { sql } from "~/db/sql";
import type { XRankPlacement } from "~/db/types";
import { type MainWeaponId, mainWeaponIds } from "~/modules/in-game-lists";
import { xRankSchema } from "./schemas";
import { syncXPBadges } from "~/features/badges";
const rawJsonNumber = process.argv[2]?.trim();
invariant(rawJsonNumber, "jsonNumber is required (argument 1)");
@ -50,6 +51,7 @@ async function main() {
}
addPlacements(placements);
syncXPBadges();
console.log(`done reading in ${placements.length} placements`);
}

View File

@ -0,0 +1,7 @@
/* eslint-disable no-console */
import "dotenv/config";
import { syncXPBadges } from "~/features/badges";
syncXPBadges();
console.log("Synced XP badges");