New store + view (linked from Settings > Your data): one card per active hunt with a big +1 counter, the method's odds, and the running cumulative chance (1 - (1-p)^count). Nine methods with shiny-charm variants (Full odds, Masuda, SOS, Radar, DexNav, Catch Combo, Dynamax Adventure, Mass/Massive Outbreak). "Found it" marks the Pokémon caught and clears the hunt; per-hunt notes field. Also: JSON export/import now covers team, formTracking and shinyHunts alongside settings/selection; openPokemonPicker gains a `closeAfterPick` option (used by the shiny + breeding single-pick flows). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Ve7HLspzeG2xDPtJQ8vmu
40 lines
1.1 KiB
JavaScript
40 lines
1.1 KiB
JavaScript
import { createStore } from './createStore.js';
|
|
|
|
/**
|
|
* Shiny hunts: one entry per Pokémon you're actively hunting, with an
|
|
* encounter counter and the method's odds. Lives in localStorage next to
|
|
* the other tracking data; rides along in the JSON export.
|
|
*/
|
|
export const shinyHunts = createStore('pdx.shinyHunts', { hunts: [] });
|
|
|
|
let seq = Date.now();
|
|
const uid = () => `h${(seq++).toString(36)}`;
|
|
|
|
export function addHunt({ speciesId, method, charm }) {
|
|
shinyHunts.set((s) => ({
|
|
...s,
|
|
hunts: [
|
|
{ id: uid(), speciesId, method, charm: !!charm, count: 0, notes: '', startedAt: new Date().toISOString() },
|
|
...s.hunts,
|
|
],
|
|
}));
|
|
}
|
|
|
|
export function updateHunt(id, patch) {
|
|
shinyHunts.set((s) => ({
|
|
...s,
|
|
hunts: s.hunts.map((h) => (h.id === id ? { ...h, ...patch } : h)),
|
|
}));
|
|
}
|
|
|
|
export function bumpHunt(id, delta) {
|
|
shinyHunts.set((s) => ({
|
|
...s,
|
|
hunts: s.hunts.map((h) => (h.id === id ? { ...h, count: Math.max(0, h.count + delta) } : h)),
|
|
}));
|
|
}
|
|
|
|
export function removeHunt(id) {
|
|
shinyHunts.set((s) => ({ ...s, hunts: s.hunts.filter((h) => h.id !== id) }));
|
|
}
|