pvpokemon/generatePokemonData.ts
2019-01-07 23:03:01 -05:00

145 lines
5.4 KiB
TypeScript

import * as fs from 'fs';
import Pokemon from 'pokemongo-json-pokedex/output/pokemon.json';
import { IPokemon, IStats, League, Grade } from './src/ts/models/Pokemon';
interface ICpAndTotalFound {
[ key : number ] : Array<IStats>;
}
interface IStatsDistribution {
great : ICpAndTotalFound;
ultra : ICpAndTotalFound;
}
interface IMaxCpByLeague {
great : number;
ultra : number;
}
const outPath = './dist/db/';
const maxCpByLeague : IMaxCpByLeague = {
great: 1500,
ultra: 2500
};
const cpMultipliers : Array<number> = JSON.parse(fs.readFileSync('src/db/cpMultipliers.json', 'utf8'));
const getClosestCpMultiplierIndex = (value : number) => {
let i;
for (i = 0; i < cpMultipliers.length; i++) {
if (value < cpMultipliers[i]) {
break;
}
}
return Math.max(i - 1, 0);
};
Pokemon.forEach((mon) => {
const baseAtk = mon.stats.baseAttack;
const baseDef = mon.stats.baseDefense;
const baseHp = mon.stats.baseStamina;
const stats : IPokemon = {
name: mon.name,
id: mon.dex,
stats: mon.stats,
pvp: {
great: [],
ultra: [],
},
};
const combinedStatsDistribution : IStatsDistribution = {
great: {},
ultra: {},
};
for (let ivHp = 15; ivHp >= 0; ivHp--) {
for (let ivAtk = 15; ivAtk >= 0; ivAtk--) {
for (let ivDef = 15; ivDef >= 0; ivDef--) {
let pokemonWithIvs : IStats;
const cpMultiplier = (baseAtk + ivAtk) * Math.sqrt(baseDef + ivDef) * Math.sqrt(baseHp + ivHp);
Object.keys(maxCpByLeague).forEach((key) => {
const league = key as League;
const maxCp = maxCpByLeague[league];
const maxLeagueLevelMultiplierIndex = getClosestCpMultiplierIndex(Math.sqrt((maxCp * 10) / cpMultiplier));
const maxLeagueLevelMultiplier = cpMultipliers[maxLeagueLevelMultiplierIndex];
const maxLeagueCp = ~~((cpMultiplier * Math.pow(maxLeagueLevelMultiplier, 2)) / 10);
const maxLeagueLevel = (maxLeagueLevelMultiplierIndex + 2) / 2;
pokemonWithIvs = {
cp: maxLeagueCp,
level: maxLeagueLevel,
ivHp: ivHp,
ivAtk: ivAtk,
ivDef: ivDef,
hp: ~~((baseHp + ivHp) * maxLeagueLevelMultiplier),
atk: ~~((baseAtk + ivAtk) * maxLeagueLevelMultiplier),
def: ~~((baseDef + ivDef) * maxLeagueLevelMultiplier),
total: 0,
speciesGrade: Grade.F,
metaGrade: Grade.F,
};
pokemonWithIvs.total = pokemonWithIvs.hp + pokemonWithIvs.atk + pokemonWithIvs.def;
const combinedStats = maxLeagueCp + pokemonWithIvs.total;
combinedStatsDistribution[league][combinedStats] = combinedStatsDistribution[league][combinedStats] || [];
combinedStatsDistribution[league][combinedStats].push(pokemonWithIvs);
});
}
}
}
// process the pokemon stats for league-worthiness
Object.keys(stats.pvp).forEach((key) => {
const league = key as League;
const orderedCombinedStats = Object.keys(combinedStatsDistribution[league]).map(cpTotal => parseInt(cpTotal)).sort();
const len = orderedCombinedStats.length - 1;
const offset = orderedCombinedStats[1];
const max = orderedCombinedStats[len] - offset; // index 0 is always `Grade.S`
for (let index = len; index >= 0; index--) {
const combinedStats = orderedCombinedStats[index];
const percent = (combinedStats - offset) / max;
// remove all `Grade.F` stats (to save space in the DB)
if (percent < 0.6) {
delete combinedStatsDistribution[league][combinedStats];
continue;
}
combinedStatsDistribution[league][combinedStats].forEach((pokemonStats) => {
if (index === len) {
pokemonStats.speciesGrade = Grade.S;
} else {
if (percent >= 0.9) {
pokemonStats.speciesGrade = Grade.A;
} else if (percent >= 0.8) {
pokemonStats.speciesGrade = Grade.B;
} else if (percent >= 0.7) {
pokemonStats.speciesGrade = Grade.C;
} else if (percent >= 0.6) {
pokemonStats.speciesGrade = Grade.D;
}
}
stats.pvp[league].push(pokemonStats);
});
combinedStatsDistribution[league][combinedStats].sort((a, b) => {
if (a.total !== b.total) {
return a.total < b.total ? -1 : 1;
}
if (a.level !== b.level) {
return a.level < b.level ? -1 : 1;
}
return 0;
});
stats.pvp[league].push(...combinedStatsDistribution[league][combinedStats]);
}
});
fs.mkdir(outPath, {recursive: true}, () => {
fs.writeFile(outPath + mon.id + '.json', JSON.stringify(stats), (err) => {
if(err) {
return console.log(mon.name, err);
}
console.log(mon.name);
});
});
});