-
Notifications
You must be signed in to change notification settings - Fork 6
/
usage.ts
97 lines (87 loc) · 3.24 KB
/
usage.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/** @file Looks up usage stats. */
import {HpType, StatName} from "./dex";
import {toIdName} from "./helpers";
export type UsageStats = ReadonlyMap<string, PokemonStats>;
export interface PokemonStats {
/** Pokemon's set level. */
level?: number;
/** Ability stats. */
abilities?: ReadonlyMap<string, number>;
/** Item stats. */
items?: ReadonlyMap<string, number>;
/** Moveset stats. Note that move names include hiddenpower type. */
moves?: ReadonlyMap<string, number>;
/** Hidden Power type stats, if provided in {@link moves}. */
hpType?: ReadonlyMap<HpType, number>;
/** EV constraints. */
evs?: {readonly [s in StatName]?: number};
/** IV constraints. */
ivs?: {readonly [s in StatName]?: number};
}
type UsageStatsJson = {readonly [p: string]: PokemonStatsJson};
interface PokemonStatsJson {
level?: number;
abilities?: {readonly [a: string]: number};
items?: {readonly [i: string]: number};
moves?: {readonly [m: string]: number};
evs?: {readonly [s in StatName]?: number};
ivs?: {readonly [s in StatName]?: number};
}
const cache = new Map<string, UsageStats>();
/** Looks up usage stats for the given format. */
export async function lookup(format: string): Promise<UsageStats> {
let usageStats = cache.get(format);
if (usageStats === undefined) {
/* eslint-disable node/no-unsupported-features/es-syntax */
const usageStatsJson = (
(await import(
`../../../vendor/randbats/data/stats/${format}.json`
)) as {readonly default: UsageStatsJson}
).default;
/* eslint-enable node/no-unsupported-features/es-syntax */
usageStats = cleanUsageStats(usageStatsJson);
cache.set(format, usageStats);
}
return usageStats;
}
function cleanUsageStats(usageStats: UsageStatsJson): UsageStats {
return new Map(
Object.entries(usageStats).map(([p, ps]) => [
toIdName(p),
{
...(ps.level && {level: ps.level}),
...(ps.abilities && {abilities: cleanDict(ps.abilities)}),
...(ps.items && {items: cleanDict(ps.items)}),
...(ps.moves && {moves: cleanDict(ps.moves)}),
...(ps.moves &&
Object.keys(ps.moves).some(m =>
m.startsWith("Hidden Power "),
) && {hpType: hpTypeMap(ps.moves)}),
...(ps.evs && {evs: ps.evs}),
...(ps.ivs && {ivs: ps.ivs}),
},
]),
);
}
function cleanDict(dict: {readonly [s: string]: number}): Map<string, number> {
return new Map(Object.entries(dict).map(([s, p]) => [toIdName(s), p]));
}
function hpTypeMap(moves: {readonly [m: string]: number}): Map<HpType, number> {
let probSum = 0.0;
const hpEntries = Object.entries(moves).flatMap<[HpType, number]>(
([m, p]) => {
if (!m.startsWith("Hidden Power ")) {
return [];
}
probSum += p;
return [
[toIdName(m.substring("Hidden Power ".length)) as HpType, p],
];
},
);
// Normalize probabilities.
for (const entry of hpEntries) {
entry[1] /= probSum;
}
return new Map(hpEntries);
}