diff --git a/app/features/admin/AdminRepository.server.ts b/app/features/admin/AdminRepository.server.ts index 8c15c9e4b..6bf5b018b 100644 --- a/app/features/admin/AdminRepository.server.ts +++ b/app/features/admin/AdminRepository.server.ts @@ -79,14 +79,6 @@ export function replacePlusTiers( }); } -export function allPlusTiersFromLatestVoting() { - return db - .selectFrom("FreshPlusTier") - .select(["FreshPlusTier.userId", "FreshPlusTier.tier"]) - .where("FreshPlusTier.tier", "is not", null) - .execute() as Promise<{ userId: number; tier: number }[]>; -} - export function makeVideoAdderByUserId(userId: number) { return db .updateTable("User") diff --git a/app/features/admin/core/plus-tier.server.ts b/app/features/admin/core/plus-tier.server.ts index bbe06e328..c77dbe8f7 100644 --- a/app/features/admin/core/plus-tier.server.ts +++ b/app/features/admin/core/plus-tier.server.ts @@ -1,16 +1,15 @@ -import * as AdminRepository from "~/features/admin/AdminRepository.server"; import { addPendingPlusTiers } from "~/features/leaderboards/core/leaderboards.server"; import { userSPLeaderboard } from "~/features/leaderboards/queries/userSPLeaderboard.server"; import { currentSeason, previousSeason } from "~/features/mmr/season"; +import * as PlusVotingRepository from "~/features/plus-voting/PlusVotingRepository.server"; import { seasonToVotingRange } from "~/features/plus-voting/core/voting-time"; import invariant from "~/utils/invariant"; import { userIsBanned } from "../../ban/core/banned.server"; export async function plusTiersFromVotingAndLeaderboard() { - const newMembersFromLeaderboard = fromLeaderboard(); const newMembersFromVoting = - await AdminRepository.allPlusTiersFromLatestVoting(); - + await PlusVotingRepository.allPlusTiersFromLatestVoting(); + const newMembersFromLeaderboard = fromLeaderboard(newMembersFromVoting); return [ ...newMembersFromLeaderboard, // filter to ensure that user gets their highest tier @@ -23,7 +22,9 @@ export async function plusTiersFromVotingAndLeaderboard() { ].filter(({ userId }) => !userIsBanned(userId)); } -function fromLeaderboard() { +function fromLeaderboard( + newMembersFromVoting: Array<{ userId: number; tier: number }>, +) { const now = new Date(); const lastCompletedSeason = previousSeason(now); invariant(lastCompletedSeason, "No previous season found"); @@ -40,6 +41,7 @@ function fromLeaderboard() { const leaderboard = addPendingPlusTiers( userSPLeaderboard(lastCompletedSeason.nth), + newMembersFromVoting, ); return leaderboard.flatMap((entry) => { diff --git a/app/features/leaderboards/core/leaderboards.server.ts b/app/features/leaderboards/core/leaderboards.server.ts index 09d37283d..1bfbc58a2 100644 --- a/app/features/leaderboards/core/leaderboards.server.ts +++ b/app/features/leaderboards/core/leaderboards.server.ts @@ -4,6 +4,7 @@ import { USER_LEADERBOARD_MIN_ENTRIES_FOR_LEVIATHAN } from "~/features/mmr/mmr-c import { spToOrdinal } from "~/features/mmr/mmr-utils"; import { currentOrPreviousSeason, currentSeason } from "~/features/mmr/season"; import { freshUserSkills, userSkills } from "~/features/mmr/tiered.server"; +import * as PlusVotingRepository from "~/features/plus-voting/PlusVotingRepository.server"; import type { MainWeaponId } from "~/modules/in-game-lists"; import { weaponCategories } from "~/modules/in-game-lists"; import { cache, ttl } from "~/utils/cache.server"; @@ -31,7 +32,10 @@ export async function cachedFullUserLeaderboard(season: number) { season === currentSeason(new Date())?.nth && leaderboard.length >= USER_LEADERBOARD_MIN_ENTRIES_FOR_LEVIATHAN; const withPendingPlusTiers = shouldAddPendingPlusTier - ? addPendingPlusTiers(withTiers) + ? addPendingPlusTiers( + withTiers, + await PlusVotingRepository.allPlusTiersFromLatestVoting(), + ) : withTiers; return addWeapons(withPendingPlusTiers, seasonPopularUsersWeapon(season)); @@ -70,6 +74,10 @@ const PLUS_TIER_QUOTA = { } as const; export function addPendingPlusTiers( entries: T[], + plusTiers: Array<{ + userId: number; + tier: number; + }>, ) { const quota: { "+1": number; "+2": number; "+3": number } = { ...PLUS_TIER_QUOTA, @@ -87,7 +95,9 @@ export function addPendingPlusTiers( const highestPlusTierWithSpace = resolveHighestPlusTierWithSpace(); if (!highestPlusTierWithSpace) break; - if (entry.plusTier && entry.plusTier <= highestPlusTierWithSpace) continue; + const plusTier = plusTiers.find((t) => t.userId === entry.id)?.tier; + + if (plusTier && plusTier <= highestPlusTierWithSpace) continue; if ( entry.plusSkippedForSeasonNth === currentOrPreviousSeason(new Date())?.nth ) { diff --git a/app/features/leaderboards/queries/userSPLeaderboard.server.ts b/app/features/leaderboards/queries/userSPLeaderboard.server.ts index 061aa0a60..d2792cd1a 100644 --- a/app/features/leaderboards/queries/userSPLeaderboard.server.ts +++ b/app/features/leaderboards/queries/userSPLeaderboard.server.ts @@ -13,14 +13,12 @@ const stm = sql.prepare(/* sql */ ` "User"."discordId", "User"."customUrl", "User"."plusSkippedForSeasonNth", - "PlusTier"."tier" as "plusTier", rank () over ( order by "Skill"."Ordinal" desc ) "placementRank" from "Skill" left join "User" on "User"."id" = "Skill"."userId" - left join "PlusTier" on "PlusTier"."userId" = "User"."id" inner join ( select "userId", max("id") as "maxId" from "Skill" @@ -43,7 +41,6 @@ export interface UserSPLeaderboardItem { discordAvatar: User["discordAvatar"]; discordId: User["discordId"]; customUrl: User["customUrl"]; - plusTier?: PlusTier["tier"]; plusSkippedForSeasonNth: number | null; /** Plus tier player is on track to join */ pendingPlusTier?: PlusTier["tier"]; diff --git a/app/features/plus-voting/PlusVotingRepository.server.ts b/app/features/plus-voting/PlusVotingRepository.server.ts index 7c20cc209..56d5d8d72 100644 --- a/app/features/plus-voting/PlusVotingRepository.server.ts +++ b/app/features/plus-voting/PlusVotingRepository.server.ts @@ -30,6 +30,14 @@ type ResultsByMonthYearQueryReturnType = InferResult< ReturnType >; +export function allPlusTiersFromLatestVoting() { + return db + .selectFrom("FreshPlusTier") + .select(["FreshPlusTier.userId", "FreshPlusTier.tier"]) + .where("FreshPlusTier.tier", "is not", null) + .execute() as Promise<{ userId: number; tier: number }[]>; +} + export type ResultsByMonthYearItem = Unwrapped; export async function resultsByMonthYear(args: MonthYear) { const rows = await resultsByMonthYearQuery(args).execute();