feat: build compact BO2 grind companion with cumulative ranks
Some checks failed
Test and deploy staging / staging (push) Failing after 2m50s
Some checks failed
Test and deploy staging / staging (push) Failing after 2m50s
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
||||
} from '$lib/server/db/schema';
|
||||
import { loadPokemonProgress } from '$lib/server/tracker-progress';
|
||||
import { challengeProgress, combinedProgress, sumProgress } from '$lib/game-tracker/progress';
|
||||
import { gameRanksProgress, hasReachedMaxLevel } from '$lib/game-tracker/rank-progress';
|
||||
import { summarizeGame } from '$lib/game-tracker/mastery';
|
||||
import { chronologicalPokemon, pokemonRelease } from '$lib/game-tracker/game-art';
|
||||
import type { PageServerLoad } from './$types';
|
||||
@@ -53,13 +54,21 @@ async function callOfDutySummary(userId: string | undefined) {
|
||||
: Promise.resolve([]),
|
||||
userId
|
||||
? db
|
||||
.select({ itemId: trackerWeaponRanks.itemId, prestige: trackerWeaponRanks.prestige })
|
||||
.select({
|
||||
itemId: trackerWeaponRanks.itemId,
|
||||
prestige: trackerWeaponRanks.prestige,
|
||||
level: trackerWeaponRanks.level
|
||||
})
|
||||
.from(trackerWeaponRanks)
|
||||
.where(eq(trackerWeaponRanks.userId, userId))
|
||||
: Promise.resolve([]),
|
||||
userId
|
||||
? db
|
||||
.select({ gameId: trackerRanks.gameId })
|
||||
.select({
|
||||
gameId: trackerRanks.gameId,
|
||||
level: trackerRanks.level,
|
||||
prestige: trackerRanks.prestige
|
||||
})
|
||||
.from(trackerRanks)
|
||||
.where(eq(trackerRanks.userId, userId))
|
||||
: Promise.resolve([]),
|
||||
@@ -86,6 +95,11 @@ async function callOfDutySummary(userId: string | undefined) {
|
||||
const byGame = Map.groupBy(items, (item) => item.gameId);
|
||||
return gamesList.map((game) => {
|
||||
const list = byGame.get(game.id) ?? [];
|
||||
const weapons = list.filter((i) => i.kind === 'weapon');
|
||||
const rankMap = new Map(ranks.map((r) => [r.itemId, r]));
|
||||
for (const weapon of weapons)
|
||||
if (hasReachedMaxLevel(game.rules, weapon, rankMap.get(weapon.id)))
|
||||
done.add(`${weapon.id}:maxLevel`);
|
||||
const summary = summarizeGame(
|
||||
game.rules,
|
||||
list.filter((item) => item.kind === 'weapon'),
|
||||
@@ -98,13 +112,12 @@ async function callOfDutySummary(userId: string | undefined) {
|
||||
challenges.filter((c) => c.gameId === game.id),
|
||||
challengeRows
|
||||
);
|
||||
const ranksProgress = {
|
||||
value:
|
||||
ranks.filter((rank) =>
|
||||
list.some((item) => item.kind === 'weapon' && item.id === rank.itemId)
|
||||
).length + Number(playerRanks.some((rank) => rank.gameId === game.id)),
|
||||
total: list.filter((item) => item.kind === 'weapon').length + 1
|
||||
};
|
||||
const ranksProgress = gameRanksProgress(
|
||||
game.rules,
|
||||
weapons,
|
||||
rankMap,
|
||||
playerRanks.find((r) => r.gameId === game.id)
|
||||
);
|
||||
return {
|
||||
overall: combinedProgress([
|
||||
weaponProgress,
|
||||
|
||||
@@ -145,8 +145,10 @@ export const actions = {
|
||||
.where(
|
||||
and(eq(trackerWeaponRanks.userId, locals.user.id), eq(trackerWeaponRanks.itemId, itemId))
|
||||
);
|
||||
if (!current || current.level < maxLevel || current.prestige >= limits.maxPrestige)
|
||||
if (!current || current.level < maxLevel)
|
||||
return fail(400, { message: `Reach weapon level ${maxLevel} before increasing prestige.` });
|
||||
if (current.prestige >= limits.maxPrestige)
|
||||
return fail(400, { message: `This weapon is already at prestige ${limits.maxPrestige}.` });
|
||||
}
|
||||
// Arithmetic happens in Postgres, so simultaneous taps from different devices cannot lose a level.
|
||||
const [rank] = await db
|
||||
@@ -169,13 +171,18 @@ export const actions = {
|
||||
...(delta > 0 ? { level: 1 } : {})
|
||||
}),
|
||||
updatedAt: new Date()
|
||||
}
|
||||
},
|
||||
setWhere:
|
||||
field === 'prestige' && delta > 0 && limits.canPrestigeOnlyAtMaxLevel
|
||||
? sql`${trackerWeaponRanks.level} >= ${maxLevel} and ${trackerWeaponRanks.prestige} < ${limits.maxPrestige}`
|
||||
: undefined
|
||||
})
|
||||
.returning({
|
||||
itemId: trackerWeaponRanks.itemId,
|
||||
level: trackerWeaponRanks.level,
|
||||
prestige: trackerWeaponRanks.prestige
|
||||
});
|
||||
if (!rank) return fail(400, { message: 'Rank changed. Refresh before prestiging again.' });
|
||||
return { rank };
|
||||
},
|
||||
saveRank: async ({ request, locals, params }) => {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,10 @@
|
||||
import weaponArt from '../../../../../data/cod-art.json';
|
||||
import rankArt from '../../../../../data/cod-rank-art.json';
|
||||
import images from '../../../../../data/game-images.json';
|
||||
import maps from '../../../../../data/pokemon-map-art.json';
|
||||
export function load() {
|
||||
const sources = new Map<string, { source: string; credit: string; count: number }>();
|
||||
for (const image of images) {
|
||||
for (const image of [...images, ...weaponArt, ...rankArt]) {
|
||||
const existing = sources.get(image.source);
|
||||
if (existing) existing.count++;
|
||||
else sources.set(image.source, { source: image.source, credit: image.credit, count: 1 });
|
||||
@@ -10,6 +12,6 @@ export function load() {
|
||||
return {
|
||||
sources: [...sources.values()],
|
||||
maps: Object.values(maps).map(({ name, source, credit }) => ({ name, source, credit })),
|
||||
total: images.length
|
||||
total: images.length + weaponArt.length + rankArt.length
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user