diff --git a/app/features/sendouq-settings/banned-maps.ts b/app/features/sendouq-settings/banned-maps.ts index bea96b82a..bcb84e920 100644 --- a/app/features/sendouq-settings/banned-maps.ts +++ b/app/features/sendouq-settings/banned-maps.ts @@ -1,16 +1,38 @@ import type { ModeShort, StageId } from "~/modules/in-game-lists"; import { stagesObj as s } from "~/modules/in-game-lists/stage-ids"; -export const COMMON_BANNED_MAPS = [ - s.HAMMERHEAD_BRIDGE, - s.WAHOO_WORLD, - s.MINCEMEAT_METALWORKS, - s.EELTAIL_ALLEY, -]; +export const COMMON_BANNED_MAPS = [s.HAMMERHEAD_BRIDGE]; export const BANNED_MAPS: Record = { - TW: [...COMMON_BANNED_MAPS], - SZ: [...COMMON_BANNED_MAPS], - TC: [...COMMON_BANNED_MAPS, s.BRINEWATER_SPRINGS, s.FLOUNDER_HEIGHTS], - RM: [...COMMON_BANNED_MAPS, s.BRINEWATER_SPRINGS, s.UM_AMI_RUINS], - CB: [...COMMON_BANNED_MAPS, s.STURGEON_SHIPYARD, s.FLOUNDER_HEIGHTS], + TW: [...COMMON_BANNED_MAPS, s.WAHOO_WORLD], + SZ: [ + ...COMMON_BANNED_MAPS, + s.SCORCH_GORGE, + s.EELTAIL_ALLEY, + s.MINCEMEAT_METALWORKS, + ], + TC: [ + ...COMMON_BANNED_MAPS, + s.WAHOO_WORLD, + s.BRINEWATER_SPRINGS, + s.FLOUNDER_HEIGHTS, + s.UM_AMI_RUINS, + s.MINCEMEAT_METALWORKS, + ], + RM: [ + ...COMMON_BANNED_MAPS, + s.WAHOO_WORLD, + s.BRINEWATER_SPRINGS, + s.UM_AMI_RUINS, + s.EELTAIL_ALLEY, + s.MINCEMEAT_METALWORKS, + ], + CB: [ + ...COMMON_BANNED_MAPS, + s.WAHOO_WORLD, + s.STURGEON_SHIPYARD, + s.FLOUNDER_HEIGHTS, + s.EELTAIL_ALLEY, + s.MINCEMEAT_METALWORKS, + s.UNDERTOW_SPILLWAY, + ], }; diff --git a/package.json b/package.json index e54d4443f..ad30fb75d 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "skip-plus": "node --experimental-specifier-resolution=node -r @swc-node/register -r tsconfig-paths/register scripts/skip-plus.ts", "season-initial-powers": "node --experimental-specifier-resolution=node -r @swc-node/register -r tsconfig-paths/register scripts/season-initial-powers.ts", "map-popularity": "node --experimental-specifier-resolution=node -r @swc-node/register -r tsconfig-paths/register scripts/map-popularity.ts", + "map-popularity-q": "node --experimental-specifier-resolution=node -r @swc-node/register -r tsconfig-paths/register scripts/map-popularity-q.ts", "transfer-weapon-pools": "node --experimental-specifier-resolution=node -r @swc-node/register -r tsconfig-paths/register scripts/transfer-weapon-pools.ts", "refresh-prod-db": "node --experimental-specifier-resolution=node -r @swc-node/register -r tsconfig-paths/register scripts/refresh-prod-db.ts && npm run migrate up", "lint:ts": "eslint . --ext .ts,.tsx", diff --git a/scripts/map-popularity-q.ts b/scripts/map-popularity-q.ts new file mode 100644 index 000000000..687706ac1 --- /dev/null +++ b/scripts/map-popularity-q.ts @@ -0,0 +1,128 @@ +/* eslint-disable no-console */ +import "dotenv/config"; +import { db } from "~/db/sql"; +import type { ModeShort, StageId } from "~/modules/in-game-lists"; +import { modesShort, stageIds } from "~/modules/in-game-lists"; +import names from "../public/locales/en/game-misc.json"; +import { + databaseTimestampToDate, + dateToDatabaseTimestamp, +} from "~/utils/dates"; +import { + BANNED_MAPS, + COMMON_BANNED_MAPS, +} from "~/features/sendouq-settings/banned-maps"; + +const SEASON_1_START = new Date("2023-09-11T17:00:00.000Z"); + +async function main() { + const appearance = await db + .selectFrom("GroupMatchMap") + .innerJoin("GroupMatch", "GroupMatchMap.matchId", "GroupMatch.id") + .select(({ fn }) => [ + "GroupMatchMap.mode", + "GroupMatchMap.stageId", + fn.countAll().as("count"), + ]) + .groupBy(["GroupMatchMap.stageId", "GroupMatchMap.mode"]) + .where("GroupMatch.createdAt", ">", dateToDatabaseTimestamp(SEASON_1_START)) + .execute(); + + const usage: Record< + ModeShort | "ALL", + { stageId: StageId; count: number }[] + > = { + TW: [], + SZ: [], + TC: [], + RM: [], + CB: [], + ALL: [], + }; + + const ageRow = await db + .selectFrom("Build") + .select((eb) => eb.fn.max("Build.updatedAt").as("age")) + .executeTakeFirstOrThrow(); + + const dbAgeDate = databaseTimestampToDate(ageRow.age); + + for (const mode of modesShort) { + for (const stageId of stageIds) { + const count = + appearance.find((row) => row.stageId === stageId && row.mode === mode) + ?.count ?? 0; + + usage[mode].push({ + stageId, + count, + }); + + const existingAllCount = usage.ALL.find((row) => row.stageId === stageId); + + if (!existingAllCount) { + usage.ALL.push({ + stageId, + count, + }); + } else { + existingAllCount.count += count; + } + } + + usage[mode].sort((a, b) => b.count - a.count); + } + + usage.ALL.sort((a, b) => b.count - a.count); + + console.log(`DB Age: ${dbAgeDate.toISOString()}\n`); + + // all modes + + console.log("All"); + let banCount = 0; + for (const [i, { stageId, count }] of usage["ALL"].entries()) { + const name = names[`STAGE_${stageId}`]; + + const isBanned = COMMON_BANNED_MAPS.includes(stageId as any); + if (isBanned) banCount++; + + const partlyBanned = + !isBanned && + Object.values(BANNED_MAPS).some((arr) => arr.includes(stageId as any)); + + console.log( + `${i < 9 ? " " : ""}${i + 1}) ${ + isBanned ? "❌" : partlyBanned ? "🔴" : " " + } ${name}: ${count}`, + ); + } + + console.log("Banned maps: " + banCount); + console.log(); + + // modes + for (const mode of modesShort) { + // if (usage[mode].every((e) => e.count === 0)) continue; + + console.log(mode); + let banCount = 0; + for (const [i, { stageId, count }] of usage[mode].entries()) { + const name = names[`STAGE_${stageId}`]; + + const isBanned = BANNED_MAPS[mode].includes(stageId); + if (isBanned) banCount++; + + console.log( + `${i < 9 ? " " : ""}${i + 1}) ${ + isBanned ? "❌" : " " + } ${name}: ${count}`, + ); + } + + console.log("Banned maps: " + banCount); + console.log(); + } +} + +void main();