add catchemall progress bars and hide uncatchable pokemon by default
All checks were successful
Test and deploy staging / staging (push) Successful in 28s
All checks were successful
Test and deploy staging / staging (push) Successful in 28s
This commit is contained in:
58
src/lib/catch-em-all/progress.test.ts
Normal file
58
src/lib/catch-em-all/progress.test.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { availabilityValues } from '$lib/availability';
|
||||
import { summarizeProgress } from './progress';
|
||||
|
||||
const catchable = availabilityValues.indexOf('catchable');
|
||||
const transferOnly = availabilityValues.indexOf('transfer_only');
|
||||
const pokemon = [
|
||||
{
|
||||
id: 1,
|
||||
entries: [
|
||||
[11, 1, catchable],
|
||||
[12, 2, catchable]
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
entries: [
|
||||
[21, 1, catchable],
|
||||
[22, 2, transferOnly]
|
||||
]
|
||||
},
|
||||
{ id: 3, entries: [[31, 2, transferOnly]] }
|
||||
] as const;
|
||||
|
||||
describe('Catchemall progress', () => {
|
||||
it('counts unique Pokémon and completed games only from selected catchable entries', () => {
|
||||
expect(summarizeProgress(pokemon, new Set([1, 2, 3]), new Set([11, 12, 31]))).toEqual({
|
||||
catchableEntries: 3,
|
||||
caughtEntries: 2,
|
||||
catchablePokemon: 2,
|
||||
seenPokemon: 1,
|
||||
completedPokemon: 1,
|
||||
catchableGames: 2,
|
||||
completedGames: 1
|
||||
});
|
||||
});
|
||||
|
||||
it('recomputes all denominators when the selected games change', () => {
|
||||
expect(summarizeProgress(pokemon, new Set([2]), new Set([11, 12, 21]))).toEqual({
|
||||
catchableEntries: 1,
|
||||
caughtEntries: 1,
|
||||
catchablePokemon: 1,
|
||||
seenPokemon: 1,
|
||||
completedPokemon: 1,
|
||||
catchableGames: 1,
|
||||
completedGames: 1
|
||||
});
|
||||
expect(summarizeProgress(pokemon, new Set([3]), new Set([11, 12, 21]))).toEqual({
|
||||
catchableEntries: 0,
|
||||
caughtEntries: 0,
|
||||
catchablePokemon: 0,
|
||||
seenPokemon: 0,
|
||||
completedPokemon: 0,
|
||||
catchableGames: 0,
|
||||
completedGames: 0
|
||||
});
|
||||
});
|
||||
});
|
||||
53
src/lib/catch-em-all/progress.ts
Normal file
53
src/lib/catch-em-all/progress.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { availabilityValues } from '$lib/availability';
|
||||
|
||||
type PokemonWithEntries = {
|
||||
id: number;
|
||||
entries: readonly (readonly [id: number, gameId: number, availability: number, note?: string])[];
|
||||
};
|
||||
|
||||
export function summarizeProgress(
|
||||
pokemon: readonly PokemonWithEntries[],
|
||||
selectedGameIds: ReadonlySet<number>,
|
||||
caughtIds: ReadonlySet<number>
|
||||
) {
|
||||
let catchableEntries = 0;
|
||||
let caughtEntries = 0;
|
||||
let catchablePokemon = 0;
|
||||
let seenPokemon = 0;
|
||||
let completedPokemon = 0;
|
||||
const games = new Map<number, { total: number; caught: number }>();
|
||||
|
||||
for (const species of pokemon) {
|
||||
let speciesEntries = 0;
|
||||
let speciesCaught = 0;
|
||||
for (const [entryId, gameId, availability] of species.entries) {
|
||||
if (!selectedGameIds.has(gameId) || availabilityValues[availability] !== 'catchable')
|
||||
continue;
|
||||
|
||||
speciesEntries++;
|
||||
const game = games.get(gameId) ?? { total: 0, caught: 0 };
|
||||
game.total++;
|
||||
if (caughtIds.has(entryId)) {
|
||||
speciesCaught++;
|
||||
game.caught++;
|
||||
}
|
||||
games.set(gameId, game);
|
||||
}
|
||||
if (speciesEntries === 0) continue;
|
||||
catchableEntries += speciesEntries;
|
||||
caughtEntries += speciesCaught;
|
||||
catchablePokemon++;
|
||||
if (speciesCaught > 0) seenPokemon++;
|
||||
if (speciesCaught === speciesEntries) completedPokemon++;
|
||||
}
|
||||
|
||||
return {
|
||||
catchableEntries,
|
||||
caughtEntries,
|
||||
catchablePokemon,
|
||||
seenPokemon,
|
||||
completedPokemon,
|
||||
catchableGames: games.size,
|
||||
completedGames: [...games.values()].filter((game) => game.caught === game.total).length
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user