parse gamemaster, use POGOProtos
This commit is contained in:
parent
58a17849a4
commit
e23a42fea7
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[submodule "externals/pokemongo-game-master"]
|
||||||
|
path = externals/pokemongo-game-master
|
||||||
|
url = https://github.com/pokemongo-dev-contrib/pokemongo-game-master.git
|
||||||
|
[submodule "externals/PokeApi"]
|
||||||
|
path = externals/PokeApi
|
||||||
|
url = https://github.com/PokeAPI/pokeapi.git
|
||||||
1
externals/PokeApi
vendored
Submodule
1
externals/PokeApi
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 739de49807b0c307a54e537b43fbf6ccda55fbbc
|
||||||
1
externals/pokemongo-game-master
vendored
Submodule
1
externals/pokemongo-game-master
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit ddcf5231b560aed7bf611590923e53e925ee60d3
|
||||||
@ -1,10 +1,11 @@
|
|||||||
import * as fs from 'fs';
|
import fs from 'fs';
|
||||||
import PokemonDescription from 'pokemongo-json-pokedex/output/locales/en-US/pokemon.json';
|
import POGOProtos from 'pogo-protos';
|
||||||
import Pokemon from 'pokemongo-json-pokedex/output/pokemon.json';
|
|
||||||
|
|
||||||
import { ILeaguePokemon, IMaxCpByLeague, League, MaxCpByLeague } from 'app/models/League';
|
import { parseGameMaster } from './parseGameMaster';
|
||||||
|
|
||||||
|
import { ILeaguePokemon, League, MaxCpByLeague } from 'app/models/League';
|
||||||
import { LevelMultipliers } from 'app/models/LevelMultipliers';
|
import { LevelMultipliers } from 'app/models/LevelMultipliers';
|
||||||
import { Grade, IBaseStatsRank, IMaxStats, IPokemon, IStats, PokemonId, Type } from 'app/models/Pokemon';
|
import { Grade, IMaxStats, IStats } from 'app/models/Pokemon';
|
||||||
|
|
||||||
type ICpAndTotalFound = Record<number, Array<IStats>>;
|
type ICpAndTotalFound = Record<number, Array<IStats>>;
|
||||||
interface IStatsDistribution {
|
interface IStatsDistribution {
|
||||||
@ -13,10 +14,6 @@ interface IStatsDistribution {
|
|||||||
master : ICpAndTotalFound;
|
master : ICpAndTotalFound;
|
||||||
custom : ICpAndTotalFound;
|
custom : ICpAndTotalFound;
|
||||||
}
|
}
|
||||||
interface ICalculateRelativeStats {
|
|
||||||
id : string;
|
|
||||||
value : number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const outPath = './dist/db/';
|
const outPath = './dist/db/';
|
||||||
|
|
||||||
@ -26,10 +23,6 @@ const maxPossibleStats : IMaxStats = {
|
|||||||
baseDefense: 0,
|
baseDefense: 0,
|
||||||
level: 40,
|
level: 40,
|
||||||
};
|
};
|
||||||
const pokemonOrderById : Record<string, IBaseStatsRank> = {};
|
|
||||||
const pokemonBaseStamina : Array<ICalculateRelativeStats> = [];
|
|
||||||
const pokemonBaseAttack : Array<ICalculateRelativeStats> = [];
|
|
||||||
const pokemonBaseDefense : Array<ICalculateRelativeStats> = [];
|
|
||||||
|
|
||||||
const getClosestCpMultiplierIndex = (value : number) => {
|
const getClosestCpMultiplierIndex = (value : number) => {
|
||||||
let i;
|
let i;
|
||||||
@ -41,96 +34,17 @@ const getClosestCpMultiplierIndex = (value : number) => {
|
|||||||
return Math.max(i - 1, 0);
|
return Math.max(i - 1, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
const familyOrder : Array<string> = [];
|
fs.mkdirSync(outPath, { recursive: true });
|
||||||
const familyEvolutionOrder : Record<string, Array<string>> = {};
|
|
||||||
const familyEncountered : Record<string, Array<ILeaguePokemon>> = {};
|
(async () => {
|
||||||
const parseNameAndForm = (monId : string, monName : string) => {
|
const Pokemon = await parseGameMaster();
|
||||||
if (monId.indexOf('_ALOLA') > -1 ||
|
|
||||||
monId.indexOf('CASTFORM_') > -1 ||
|
|
||||||
monId.indexOf('DEOXYS_') > -1 ||
|
|
||||||
monId.indexOf('WORMADAM_') > -1 ||
|
|
||||||
monId.indexOf('BURMY_') > -1 ||
|
|
||||||
monId.indexOf('CHERRIM_') > -1 ||
|
|
||||||
monId.indexOf('SHELLOS_') > -1 ||
|
|
||||||
monId.indexOf('GASTRODON_') > -1 ||
|
|
||||||
monId.indexOf('ROTOM_') > -1 ||
|
|
||||||
monId.indexOf('GIRATINA_') > -1 ||
|
|
||||||
monId.indexOf('SHAYMIN_') > -1 ||
|
|
||||||
monId.indexOf('ARCEUS_') > -1
|
|
||||||
) {
|
|
||||||
const formTokenIndex = monId.indexOf('_');
|
|
||||||
return {
|
|
||||||
name: monName.substr(0, formTokenIndex),
|
|
||||||
form: monId.substr(formTokenIndex + 1),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
name: monName,
|
|
||||||
form: null,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
Pokemon.forEach((mon) => {
|
Pokemon.forEach((mon) => {
|
||||||
maxPossibleStats.baseStamina = Math.max(mon.stats.baseStamina, maxPossibleStats.baseStamina);
|
const baseHp = mon.stats.baseStamina;
|
||||||
maxPossibleStats.baseAttack = Math.max(mon.stats.baseAttack, maxPossibleStats.baseAttack);
|
|
||||||
maxPossibleStats.baseDefense = Math.max(mon.stats.baseDefense, maxPossibleStats.baseDefense);
|
|
||||||
pokemonBaseStamina.push({
|
|
||||||
id: mon.id,
|
|
||||||
value: mon.stats.baseStamina,
|
|
||||||
});
|
|
||||||
pokemonBaseAttack.push({
|
|
||||||
id: mon.id,
|
|
||||||
value: mon.stats.baseAttack,
|
|
||||||
});
|
|
||||||
pokemonBaseDefense.push({
|
|
||||||
id: mon.id,
|
|
||||||
value: mon.stats.baseDefense,
|
|
||||||
});
|
|
||||||
pokemonOrderById[mon.id] = {
|
|
||||||
staminaRank: -1,
|
|
||||||
attackRank: -1,
|
|
||||||
defenseRank: -1,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
pokemonBaseStamina.sort((a, b) => {
|
|
||||||
return a.value - b.value;
|
|
||||||
});
|
|
||||||
pokemonBaseStamina.forEach((stats, index, array) => {
|
|
||||||
pokemonOrderById[stats.id].staminaRank = Math.floor((index / (array.length - 1)) * 100);
|
|
||||||
});
|
|
||||||
pokemonBaseAttack.sort((a, b) => {
|
|
||||||
return a.value - b.value;
|
|
||||||
});
|
|
||||||
pokemonBaseAttack.forEach((stats, index, array) => {
|
|
||||||
pokemonOrderById[stats.id].attackRank = Math.floor((index / (array.length - 1)) * 100);
|
|
||||||
});
|
|
||||||
pokemonBaseDefense.sort((a, b) => {
|
|
||||||
return a.value - b.value;
|
|
||||||
});
|
|
||||||
pokemonBaseDefense.forEach((stats, index, array) => {
|
|
||||||
pokemonOrderById[stats.id].defenseRank = Math.floor((index / (array.length - 1)) * 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
Pokemon.forEach((mon) => {
|
|
||||||
const { name, form } = parseNameAndForm(mon.id, mon.name);
|
|
||||||
const baseAtk = mon.stats.baseAttack;
|
const baseAtk = mon.stats.baseAttack;
|
||||||
const baseDef = mon.stats.baseDefense;
|
const baseDef = mon.stats.baseDefense;
|
||||||
const baseHp = mon.stats.baseStamina;
|
|
||||||
const pokemonDescription = typeof PokemonDescription[mon.id as PokemonId] !== 'undefined' ? PokemonDescription[mon.id as PokemonId] : {};
|
|
||||||
const pokemon : ILeaguePokemon = {
|
const pokemon : ILeaguePokemon = {
|
||||||
id: mon.id as PokemonId,
|
...mon,
|
||||||
name: pokemonDescription.name || name || 'MissingNo.',
|
|
||||||
category: pokemonDescription.category || '',
|
|
||||||
form,
|
|
||||||
dex: mon.dex,
|
|
||||||
types: {
|
|
||||||
type1: mon.types[0].name.toLowerCase() as Type,
|
|
||||||
type2: mon.types[1] ? mon.types[1].name.toLowerCase() as Type : null,
|
|
||||||
},
|
|
||||||
stats: mon.stats,
|
|
||||||
statsRank: pokemonOrderById[mon.id],
|
|
||||||
family: mon.family.id,
|
|
||||||
pvp: {
|
pvp: {
|
||||||
great: [],
|
great: [],
|
||||||
ultra: [],
|
ultra: [],
|
||||||
@ -139,41 +53,9 @@ Pokemon.forEach((mon) => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// keep track of family order and membership
|
maxPossibleStats.baseStamina = Math.max(baseHp, maxPossibleStats.baseStamina);
|
||||||
if (typeof familyEncountered[pokemon.family] === 'undefined') {
|
maxPossibleStats.baseAttack = Math.max(baseAtk, maxPossibleStats.baseAttack);
|
||||||
familyOrder.push(pokemon.family);
|
maxPossibleStats.baseDefense = Math.max(baseDef, maxPossibleStats.baseDefense);
|
||||||
familyEncountered[pokemon.family] = [];
|
|
||||||
}
|
|
||||||
familyEncountered[pokemon.family].push(pokemon);
|
|
||||||
|
|
||||||
if (typeof mon.evolution.pastBranch === 'undefined' &&
|
|
||||||
typeof familyEvolutionOrder[pokemon.family] === 'undefined' &&
|
|
||||||
pokemon.id.indexOf('_ALOLA') === -1 // because RAICHU_ALOLA shows up before PICHU, but PICHU is the family origin
|
|
||||||
) {
|
|
||||||
familyEvolutionOrder[pokemon.family] = [];
|
|
||||||
if (mon.forms.length > 0) {
|
|
||||||
mon.forms.forEach((monForm) => {
|
|
||||||
familyEvolutionOrder[pokemon.family].push(monForm.id);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
familyEvolutionOrder[pokemon.family].push(pokemon.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: if `mon.forms.length > 0`, there's a chance the order will get weird by doing this:
|
|
||||||
if (typeof mon.evolution.futureBranches !== 'undefined') {
|
|
||||||
(function traverseEvolutionBranches(root) {
|
|
||||||
root.forEach((evolution) => {
|
|
||||||
familyEvolutionOrder[pokemon.family].push(evolution.id);
|
|
||||||
// unfortunate workaround for typescript limitation in JSON parsing being TOO good...
|
|
||||||
// if (typeof evolution !== 'undefined') {
|
|
||||||
if ('futureBranches' in evolution) {
|
|
||||||
// traverseEvolutionBranches(evolution.futureBranches);
|
|
||||||
traverseEvolutionBranches(evolution['futureBranches']);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})(mon.evolution.futureBranches);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate stats for all possible IVs
|
// calculate stats for all possible IVs
|
||||||
const combinedStatsDistribution : IStatsDistribution = {
|
const combinedStatsDistribution : IStatsDistribution = {
|
||||||
@ -213,6 +95,7 @@ Pokemon.forEach((mon) => {
|
|||||||
const combinedStats = maxLeagueCp + pokemonWithIvs.total;
|
const combinedStats = maxLeagueCp + pokemonWithIvs.total;
|
||||||
combinedStatsDistribution[league][combinedStats] = combinedStatsDistribution[league][combinedStats] || [];
|
combinedStatsDistribution[league][combinedStats] = combinedStatsDistribution[league][combinedStats] || [];
|
||||||
combinedStatsDistribution[league][combinedStats].push(pokemonWithIvs);
|
combinedStatsDistribution[league][combinedStats].push(pokemonWithIvs);
|
||||||
|
// console.log(pokemonWithIvs, key);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,7 +114,6 @@ Pokemon.forEach((mon) => {
|
|||||||
for (let index = len; index >= 0; index--) {
|
for (let index = len; index >= 0; index--) {
|
||||||
const combinedStats = orderedCombinedStats[index];
|
const combinedStats = orderedCombinedStats[index];
|
||||||
const percent = (combinedStats - offset) / max;
|
const percent = (combinedStats - offset) / max;
|
||||||
|
|
||||||
// remove all `Grade.F` stats (to save space in the DB)
|
// remove all `Grade.F` stats (to save space in the DB)
|
||||||
if (percent < 0.6) {
|
if (percent < 0.6) {
|
||||||
delete combinedStatsDistribution[league][combinedStats];
|
delete combinedStatsDistribution[league][combinedStats];
|
||||||
@ -266,49 +148,33 @@ Pokemon.forEach((mon) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
fs.mkdir(outPath, { recursive: true }, () => {
|
try {
|
||||||
fs.writeFile(outPath + mon.id + '.json', JSON.stringify(pokemon), (err) => {
|
const filename = mon.form === POGOProtos.Enums.Form.FORM_UNSET ? POGOProtos.Enums.PokemonId[mon.id] : POGOProtos.Enums.Form[mon.form];
|
||||||
if (err) {
|
fs.writeFileSync(outPath + filename + '.json', JSON.stringify(pokemon));
|
||||||
|
} catch (error) {
|
||||||
|
if (error) {
|
||||||
/* tslint:disable-next-line:no-console */
|
/* tslint:disable-next-line:no-console */
|
||||||
return console.error(mon.name, err);
|
return console.error(pokemon.name, error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const pokemonOrder : Array<IPokemon> = [];
|
try {
|
||||||
familyOrder.forEach((familyId) => {
|
fs.writeFileSync(outPath + 'order.json', JSON.stringify(Pokemon));
|
||||||
familyEvolutionOrder[familyId].forEach((id, order) => {
|
} catch (error) {
|
||||||
familyEncountered[familyId].some((pokemon, index) => {
|
if (error) {
|
||||||
if (id === pokemon.id && order !== index) {
|
|
||||||
familyEncountered[familyId].splice(order, 0, familyEncountered[familyId].splice(index, 1)[0]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
familyEncountered[familyId].forEach((leaguePokemon) => {
|
|
||||||
const { pvp, ...pokemon } = leaguePokemon;
|
|
||||||
pokemonOrder.push(pokemon);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
fs.mkdir(outPath, { recursive: true }, () => {
|
|
||||||
fs.writeFile(outPath + 'order.json', JSON.stringify(pokemonOrder), (err) => {
|
|
||||||
if (err) {
|
|
||||||
/* tslint:disable-next-line:no-console */
|
/* tslint:disable-next-line:no-console */
|
||||||
return console.error('order', err);
|
return console.error('order', error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
try {
|
||||||
// TODO: add moves
|
// TODO: add moves
|
||||||
fs.mkdir(outPath, { recursive: true }, () => {
|
fs.writeFileSync(outPath + 'config.json', JSON.stringify({ maxPossibleStats }));
|
||||||
fs.writeFile(outPath + 'config.json', JSON.stringify({ maxPossibleStats }), (err) => {
|
} catch (error) {
|
||||||
if (err) {
|
if (error) {
|
||||||
/* tslint:disable-next-line:no-console */
|
/* tslint:disable-next-line:no-console */
|
||||||
return console.error('order', err);
|
return console.error('config', error);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
});
|
})();
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
"watch": "yarn build -- --config webpack.config.js --colors --debug --output-pathinfo --progress --watch",
|
"watch": "yarn build -- --config webpack.config.js --colors --debug --output-pathinfo --progress --watch",
|
||||||
"build": "node ./node_modules/webpack/bin/webpack.js --cache=true --display-error-details --profile",
|
"build": "node ./node_modules/webpack/bin/webpack.js --cache=true --display-error-details --profile",
|
||||||
"clean": "rm -rf ./dist/*",
|
"clean": "rm -rf ./dist/*",
|
||||||
"tsnode": "./node_modules/.bin/ts-node -r tsconfig-paths/register"
|
"tsnode": "node -r ts-node/register -r tsconfig-paths/register"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.2.2",
|
"@babel/core": "^7.2.2",
|
||||||
@ -30,12 +30,15 @@
|
|||||||
"babel-plugin-transform-builtin-extend": "^1.1.2",
|
"babel-plugin-transform-builtin-extend": "^1.1.2",
|
||||||
"css-loader": "^2.1.0",
|
"css-loader": "^2.1.0",
|
||||||
"css-modules-typescript-loader": "^1.1.1",
|
"css-modules-typescript-loader": "^1.1.1",
|
||||||
|
"csvtojson": "^2.0.8",
|
||||||
"file-loader": "^3.0.1",
|
"file-loader": "^3.0.1",
|
||||||
"fs": "^0.0.1-security",
|
"fs": "^0.0.1-security",
|
||||||
"glob": "^7.1.3",
|
"glob": "^7.1.3",
|
||||||
"mini-css-extract-plugin": "^0.5.0",
|
"mini-css-extract-plugin": "^0.5.0",
|
||||||
"node-sass": "^4.11.0",
|
"node-sass": "^4.11.0",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
|
"pogo-protos": "^2.31.1",
|
||||||
|
"pokemongo-game-master": "^1.0.4",
|
||||||
"sass-loader": "^7.1.0",
|
"sass-loader": "^7.1.0",
|
||||||
"source-map-concat": "^1.0.1",
|
"source-map-concat": "^1.0.1",
|
||||||
"source-map-dummy": "^1.0.0",
|
"source-map-dummy": "^1.0.0",
|
||||||
@ -71,6 +74,7 @@
|
|||||||
"react-window": "^1.5.0",
|
"react-window": "^1.5.0",
|
||||||
"redux": "^4.0.1",
|
"redux": "^4.0.1",
|
||||||
"redux-thunk": "^2.3.0",
|
"redux-thunk": "^2.3.0",
|
||||||
"typesafe-actions": "^3.0.0"
|
"typesafe-actions": "^3.0.0",
|
||||||
|
"xhr2": "^0.1.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
144
parseGameMaster.ts
Normal file
144
parseGameMaster.ts
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
import fs from 'fs';
|
||||||
|
import POGOProtos from 'pogo-protos';
|
||||||
|
|
||||||
|
import { ApiService } from 'api/ApiService';
|
||||||
|
|
||||||
|
import { IBaseStatsRank, IPokemon } from 'app/models/Pokemon';
|
||||||
|
|
||||||
|
interface ICalculateRelativeStats {
|
||||||
|
id : POGOProtos.Enums.PokemonId;
|
||||||
|
form : POGOProtos.Enums.Form;
|
||||||
|
value : number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const parseGameMaster = async () => {
|
||||||
|
const apiService = new ApiService();
|
||||||
|
// const pokemonForms : { [ key in keyof typeof POGOProtos.Enums.PokemonId ]? : Array<POGOProtos.Enums.Form> } = {};
|
||||||
|
const pokemonData : { [ key in keyof typeof POGOProtos.Enums.PokemonId ]? : Array<IPokemon> } = {};
|
||||||
|
|
||||||
|
const pokemonBaseStamina : Array<ICalculateRelativeStats> = [];
|
||||||
|
const pokemonBaseAttack : Array<ICalculateRelativeStats> = [];
|
||||||
|
const pokemonBaseDefense : Array<ICalculateRelativeStats> = [];
|
||||||
|
const pokemonOrderById : Record<string, IBaseStatsRank> = {};
|
||||||
|
|
||||||
|
const GameMasterProto = fs.readFileSync('externals/pokemongo-game-master/versions/latest/GAME_MASTER.protobuf');
|
||||||
|
const GameMaster = POGOProtos.Networking.Responses.DownloadItemTemplatesResponse.decode(GameMasterProto);
|
||||||
|
// fs.writeFileSync('gamemaster.json', JSON.stringify(decoded, null, 2));
|
||||||
|
|
||||||
|
const version = GameMaster.timestamp_ms;
|
||||||
|
|
||||||
|
for (const entry of GameMaster.item_templates) {
|
||||||
|
if (!entry.template_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore *_NORMAL entries
|
||||||
|
if (entry.template_id.match(/^V(\d{4})_POKEMON_(\w+)(?<!_NORMAL)$/) && entry.pokemon_settings) {
|
||||||
|
const pokemonId = entry.pokemon_settings.pokemon_id || POGOProtos.Enums.PokemonId.MISSINGNO;
|
||||||
|
const dex = parseInt(RegExp.$1, 10);
|
||||||
|
|
||||||
|
const speciesInfo = await apiService.getPokemonSpeciesInfo(pokemonId, dex, POGOProtos.Enums.PokemonId[pokemonId]);
|
||||||
|
|
||||||
|
pokemonData[pokemonId] = pokemonData[pokemonId] || [];
|
||||||
|
const mon = {
|
||||||
|
...speciesInfo,
|
||||||
|
id: pokemonId,
|
||||||
|
form: entry.pokemon_settings.form || POGOProtos.Enums.Form.FORM_UNSET,
|
||||||
|
family: entry.pokemon_settings.family_id || POGOProtos.Enums.PokemonFamilyId.FAMILY_UNSET,
|
||||||
|
types: {
|
||||||
|
type1: entry.pokemon_settings.type || POGOProtos.Enums.PokemonType.POKEMON_TYPE_NONE,
|
||||||
|
type2: entry.pokemon_settings.type_2 || null,
|
||||||
|
},
|
||||||
|
stats: {
|
||||||
|
baseAttack: (entry.pokemon_settings.stats || {}).base_attack || 0,
|
||||||
|
baseDefense: (entry.pokemon_settings.stats || {}).base_defense || 0,
|
||||||
|
baseStamina: (entry.pokemon_settings.stats || {}).base_stamina || 0,
|
||||||
|
},
|
||||||
|
statsRank: {
|
||||||
|
attackRank: -1,
|
||||||
|
defenseRank: -1,
|
||||||
|
staminaRank: -1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
pokemonData[pokemonId]!.push(mon);
|
||||||
|
|
||||||
|
const key = POGOProtos.Enums.PokemonId[mon.id] + POGOProtos.Enums.Form[mon.form];
|
||||||
|
|
||||||
|
pokemonBaseStamina.push({
|
||||||
|
id: mon.id,
|
||||||
|
form: mon.form,
|
||||||
|
value: mon.stats.baseStamina,
|
||||||
|
});
|
||||||
|
pokemonBaseAttack.push({
|
||||||
|
id: mon.id,
|
||||||
|
form: mon.form,
|
||||||
|
value: mon.stats.baseAttack,
|
||||||
|
});
|
||||||
|
pokemonBaseDefense.push({
|
||||||
|
id: mon.id,
|
||||||
|
form: mon.form,
|
||||||
|
value: mon.stats.baseDefense,
|
||||||
|
});
|
||||||
|
pokemonOrderById[key] = {
|
||||||
|
staminaRank: -1,
|
||||||
|
attackRank: -1,
|
||||||
|
defenseRank: -1,
|
||||||
|
};
|
||||||
|
// } else if (entry.template_id.indexOf('FORMS_V') === 0 && entry.form_settings) {
|
||||||
|
// const pokemonId = entry.form_settings.pokemon || POGOProtos.Enums.PokemonId.MISSINGNO;
|
||||||
|
// if (entry.form_settings.forms) {
|
||||||
|
// pokemonForms[pokemonId] = entry.form_settings.forms.reduce((output : Array<POGOProtos.Enums.Form>, form) => {
|
||||||
|
// if (form.form) {
|
||||||
|
// output.push(form.form);
|
||||||
|
// }
|
||||||
|
// return output;
|
||||||
|
// }, []);
|
||||||
|
// } else if (pokemonId) {
|
||||||
|
// pokemonForms[pokemonId] = [POGOProtos.Enums.Form.FORM_UNSET];
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// const orderedPokemon = Object.values(pokemonData).sort((a, b) => {
|
||||||
|
const orderedPokemon = (Object.values(pokemonData) as unknown as Array<Array<IPokemon>>).sort((a, b) => {
|
||||||
|
return a[0].order - b[0].order;
|
||||||
|
});
|
||||||
|
orderedPokemon.forEach((value) => {
|
||||||
|
value.sort((a, b) => {
|
||||||
|
return a.form - b.form;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let flatOrderedPokemon : Array<IPokemon> = [];
|
||||||
|
flatOrderedPokemon = flatOrderedPokemon.concat(...orderedPokemon);
|
||||||
|
|
||||||
|
// calculate pokemon relative rankings
|
||||||
|
|
||||||
|
pokemonBaseStamina.sort((a, b) => {
|
||||||
|
return a.value - b.value;
|
||||||
|
});
|
||||||
|
pokemonBaseStamina.forEach((stats, index, array) => {
|
||||||
|
const key = POGOProtos.Enums.PokemonId[stats.id] + POGOProtos.Enums.Form[stats.form];
|
||||||
|
pokemonOrderById[key].staminaRank = Math.floor((index / (array.length - 1)) * 100);
|
||||||
|
});
|
||||||
|
pokemonBaseAttack.sort((a, b) => {
|
||||||
|
return a.value - b.value;
|
||||||
|
});
|
||||||
|
pokemonBaseAttack.forEach((stats, index, array) => {
|
||||||
|
const key = POGOProtos.Enums.PokemonId[stats.id] + POGOProtos.Enums.Form[stats.form];
|
||||||
|
pokemonOrderById[key].attackRank = Math.floor((index / (array.length - 1)) * 100);
|
||||||
|
});
|
||||||
|
pokemonBaseDefense.sort((a, b) => {
|
||||||
|
return a.value - b.value;
|
||||||
|
});
|
||||||
|
pokemonBaseDefense.forEach((stats, index, array) => {
|
||||||
|
const key = POGOProtos.Enums.PokemonId[stats.id] + POGOProtos.Enums.Form[stats.form];
|
||||||
|
pokemonOrderById[key].defenseRank = Math.floor((index / (array.length - 1)) * 100);
|
||||||
|
});
|
||||||
|
flatOrderedPokemon.forEach((mon) => {
|
||||||
|
const key = POGOProtos.Enums.PokemonId[mon.id] + POGOProtos.Enums.Form[mon.form];
|
||||||
|
mon.statsRank = { ...pokemonOrderById[key] };
|
||||||
|
});
|
||||||
|
|
||||||
|
return flatOrderedPokemon;
|
||||||
|
};
|
||||||
@ -91,7 +91,7 @@ a.list-item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nes-container::after,
|
.nes-container::after,
|
||||||
.nes-container.is-rounded::after, {
|
.nes-container.is-rounded::after {
|
||||||
border-color: $main-border-color;
|
border-color: $main-border-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
237
src/ts/api/AjaxRequest.ts
Normal file
237
src/ts/api/AjaxRequest.ts
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
export interface IRestApiRejection {
|
||||||
|
message : string;
|
||||||
|
status : number;
|
||||||
|
xhr : XMLHttpRequest;
|
||||||
|
error : Error | null;
|
||||||
|
type : string | null;
|
||||||
|
content : any | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IAjaxRequest {
|
||||||
|
ajaxGet(url : string, queryObject? : any) : Promise<any>;
|
||||||
|
ajaxPost(url : string, postBody : any, queryObject? : any, type? : 'text' | 'json') : Promise<any>;
|
||||||
|
ajaxPostForm(url : string, formData? : FormData, queryObject? : any) : Promise<any>;
|
||||||
|
ajaxPut(url : string, postBody : any, queryObject? : any) : Promise<any>;
|
||||||
|
ajaxDelete(url : string, queryObject? : any) : Promise<any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AjaxRequest implements IAjaxRequest {
|
||||||
|
private XMLHttpRequest : typeof XMLHttpRequest;
|
||||||
|
|
||||||
|
constructor(xmlHttpRequest : typeof XMLHttpRequest) {
|
||||||
|
this.XMLHttpRequest = xmlHttpRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ajaxGet(url : string, queryObject? : any) : Promise<any> {
|
||||||
|
return new Promise<any>((resolve, reject) => {
|
||||||
|
const xhr = new this.XMLHttpRequest();
|
||||||
|
const cacheBustingQueryObject = (queryObject || {}); // IE 11 caches GET requests
|
||||||
|
cacheBustingQueryObject._cache_busting_arg_ = +new Date(); // this parameter name must be in the backend's excluded parameter set (see api_utils.py)
|
||||||
|
|
||||||
|
xhr.open('GET', url + this.buildQueryString(cacheBustingQueryObject));
|
||||||
|
xhr.withCredentials = true;
|
||||||
|
xhr.onload = () => {
|
||||||
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||||
|
try {
|
||||||
|
return resolve(JSON.parse(xhr.response));
|
||||||
|
} catch (e) {
|
||||||
|
const rejection : IRestApiRejection = {
|
||||||
|
message: e.message,
|
||||||
|
status: xhr.status,
|
||||||
|
xhr,
|
||||||
|
error: e,
|
||||||
|
type: null,
|
||||||
|
content: null,
|
||||||
|
};
|
||||||
|
// tslint:disable-next-line:no-console
|
||||||
|
console.error('Failure to parse response', xhr);
|
||||||
|
return reject(rejection);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return this.handleXhrOnLoadCaughtException(reject, xhr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onerror = (e) => {
|
||||||
|
return this.handleXhrOnLoadCaughtException(reject, xhr);
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ajaxPost(url : string, postBody : any, queryObject? : any, type? : 'text' | 'json') : Promise<any> {
|
||||||
|
return new Promise<any>((resolve, reject) => {
|
||||||
|
const xhr = new this.XMLHttpRequest();
|
||||||
|
xhr.open('POST', url + this.buildQueryString(queryObject));
|
||||||
|
xhr.withCredentials = true;
|
||||||
|
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||||
|
xhr.setRequestHeader('X-CSRFToken', (window as any).CSRF_TOKEN);
|
||||||
|
xhr.onload = () => {
|
||||||
|
if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 201)) {
|
||||||
|
if (type === 'text') {
|
||||||
|
return resolve(xhr.response);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return resolve(JSON.parse(xhr.response));
|
||||||
|
} catch (e) {
|
||||||
|
const rejection : IRestApiRejection = {
|
||||||
|
message: e.message,
|
||||||
|
status: xhr.status,
|
||||||
|
xhr,
|
||||||
|
error: e,
|
||||||
|
type: null,
|
||||||
|
content: null,
|
||||||
|
};
|
||||||
|
// tslint:disable-next-line:no-console
|
||||||
|
console.error('Failure to parse response', xhr);
|
||||||
|
return reject(rejection);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return this.handleXhrOnLoadCaughtException(reject, xhr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onerror = (e) => {
|
||||||
|
return this.handleXhrOnLoadCaughtException(reject, xhr);
|
||||||
|
};
|
||||||
|
xhr.send(JSON.stringify(postBody || undefined));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ajaxPostForm(url : string, formData? : FormData, queryObject? : any) : Promise<any> {
|
||||||
|
// Lesman 4/24/2017
|
||||||
|
// NOTE: you do not set the Content-Type on this request,
|
||||||
|
// the browser will automatically encode the form data and
|
||||||
|
// set the appropriate Content-Type. The encoding is browser
|
||||||
|
// specific so you MUST allow the browser to set the header
|
||||||
|
return new Promise<any>((resolve, reject) => {
|
||||||
|
const xhr = new this.XMLHttpRequest();
|
||||||
|
xhr.open('POST', url + this.buildQueryString(queryObject));
|
||||||
|
xhr.withCredentials = true;
|
||||||
|
xhr.setRequestHeader('X-CSRFToken', (window as any).CSRF_TOKEN);
|
||||||
|
xhr.onload = () => this.handleXhrOnLoad(resolve, reject, xhr);
|
||||||
|
xhr.onerror = (e) => {
|
||||||
|
return this.handleXhrOnLoadCaughtException(reject, xhr);
|
||||||
|
};
|
||||||
|
xhr.send(formData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ajaxPut(url : string, postBody : any, queryObject? : any) : Promise<any> {
|
||||||
|
return new Promise<any>((resolve, reject) => {
|
||||||
|
const xhr = new this.XMLHttpRequest();
|
||||||
|
xhr.open('PUT', url + this.buildQueryString(queryObject));
|
||||||
|
xhr.withCredentials = true;
|
||||||
|
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||||
|
xhr.setRequestHeader('X-CSRFToken', (window as any).CSRF_TOKEN);
|
||||||
|
xhr.onload = () => this.handleXhrOnLoad(resolve, reject, xhr);
|
||||||
|
xhr.onerror = (e) => {
|
||||||
|
return this.handleXhrOnLoadCaughtException(reject, xhr);
|
||||||
|
};
|
||||||
|
xhr.send(JSON.stringify(postBody || undefined));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ajaxDelete(url : string, queryObject? : any) : Promise<any> {
|
||||||
|
return new Promise<any>((resolve, reject) => {
|
||||||
|
const xhr = new this.XMLHttpRequest();
|
||||||
|
xhr.open('DELETE', url + this.buildQueryString(queryObject));
|
||||||
|
xhr.withCredentials = true;
|
||||||
|
xhr.setRequestHeader('X-CSRFToken', (window as any).CSRF_TOKEN);
|
||||||
|
xhr.onload = () => this.handleXhrOnLoad(resolve, reject, xhr);
|
||||||
|
xhr.onerror = (e) => {
|
||||||
|
return this.handleXhrOnLoadCaughtException(reject, xhr);
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildQueryString(queryObject : any) {
|
||||||
|
const queryParameters : Array<string> = [];
|
||||||
|
let queryString = '';
|
||||||
|
Object.keys(queryObject || {}).forEach((key : string) => {
|
||||||
|
queryParameters.push(key + '=' + encodeURIComponent(queryObject[key]));
|
||||||
|
});
|
||||||
|
if (queryParameters.length > 0) {
|
||||||
|
queryString = '?' + queryParameters.join('&');
|
||||||
|
}
|
||||||
|
return queryString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleXhrOnLoad(resolve : (value : any) => void, reject : (reason : any) => void, xhr : XMLHttpRequest) : void {
|
||||||
|
if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 204)) {
|
||||||
|
if (xhr.responseType === '' && xhr.responseText === '') {
|
||||||
|
return resolve(undefined);
|
||||||
|
}
|
||||||
|
if (xhr.responseType === 'text') {
|
||||||
|
return resolve(xhr.response);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const responseJSON = JSON.parse(xhr.response);
|
||||||
|
|
||||||
|
if (typeof(responseJSON.success) !== 'undefined' && !responseJSON.success) {
|
||||||
|
if (responseJSON.error === 'user_required') {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolve(responseJSON);
|
||||||
|
} catch (e) {
|
||||||
|
const rejection : IRestApiRejection = {
|
||||||
|
message: e.message,
|
||||||
|
status: xhr.status,
|
||||||
|
xhr,
|
||||||
|
error: e,
|
||||||
|
type: null,
|
||||||
|
content: null,
|
||||||
|
};
|
||||||
|
// tslint:disable-next-line:no-console
|
||||||
|
console.error('Failed to parse response', xhr);
|
||||||
|
return reject(rejection);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return this.handleXhrOnLoadCaughtException(reject, xhr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleXhrOnLoadCaughtException(reject : (reason : any) => void, xhr : XMLHttpRequest) : void {
|
||||||
|
if (xhr.status === 401) {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xhr.responseType === 'text' || xhr.responseType === '') {
|
||||||
|
const rejection : IRestApiRejection = {
|
||||||
|
message: xhr.responseText || xhr.statusText,
|
||||||
|
status: xhr.status,
|
||||||
|
xhr,
|
||||||
|
error: null,
|
||||||
|
type: null,
|
||||||
|
content: null,
|
||||||
|
};
|
||||||
|
return reject(rejection);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const responseJSON = JSON.parse(xhr.response);
|
||||||
|
|
||||||
|
const rejection : IRestApiRejection = {
|
||||||
|
message: responseJSON.message || xhr.statusText,
|
||||||
|
status: xhr.status,
|
||||||
|
xhr,
|
||||||
|
error: null,
|
||||||
|
type: responseJSON.exception_type,
|
||||||
|
content: responseJSON.content,
|
||||||
|
};
|
||||||
|
return reject(rejection);
|
||||||
|
} catch (e) {
|
||||||
|
const rejection : IRestApiRejection = {
|
||||||
|
message: e.message,
|
||||||
|
status: xhr.status,
|
||||||
|
xhr,
|
||||||
|
error: e,
|
||||||
|
type: null,
|
||||||
|
content: null,
|
||||||
|
};
|
||||||
|
// tslint:disable-next-line:no-console
|
||||||
|
console.error('Failed to parse response', xhr);
|
||||||
|
return reject(rejection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,223 +0,0 @@
|
|||||||
export interface IRestApiRejection {
|
|
||||||
message : string;
|
|
||||||
status : number;
|
|
||||||
xhr : XMLHttpRequest;
|
|
||||||
error : Error | null;
|
|
||||||
type : string | null;
|
|
||||||
content : any | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const buildQueryString = (queryObject : any) => {
|
|
||||||
const queryParameters : Array<string> = [];
|
|
||||||
let queryString = '';
|
|
||||||
Object.keys(queryObject || {}).forEach((key : string) => {
|
|
||||||
queryParameters.push(key + '=' + encodeURIComponent(queryObject[key]));
|
|
||||||
});
|
|
||||||
if (queryParameters.length > 0) {
|
|
||||||
queryString = '?' + queryParameters.join('&');
|
|
||||||
}
|
|
||||||
return queryString;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleXhrOnLoad = (resolve : (value : any) => void, reject : (reason : any) => void, xhr : XMLHttpRequest) : void => {
|
|
||||||
if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 204)) {
|
|
||||||
if (xhr.responseType === '' && xhr.responseText === '') {
|
|
||||||
return resolve(undefined);
|
|
||||||
}
|
|
||||||
if (xhr.responseType === 'text') {
|
|
||||||
return resolve(xhr.response);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const responseJSON = JSON.parse(xhr.response);
|
|
||||||
|
|
||||||
if (typeof(responseJSON.success) !== 'undefined' && !responseJSON.success) {
|
|
||||||
if (responseJSON.error === 'user_required') {
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolve(responseJSON);
|
|
||||||
} catch (e) {
|
|
||||||
const rejection : IRestApiRejection = {
|
|
||||||
message: e.message,
|
|
||||||
status: xhr.status,
|
|
||||||
xhr,
|
|
||||||
error: e,
|
|
||||||
type: null,
|
|
||||||
content: null,
|
|
||||||
};
|
|
||||||
// tslint:disable-next-line:no-console
|
|
||||||
console.error('Failed to parse response', xhr);
|
|
||||||
return reject(rejection);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleXhrOnLoadCaughtException = (reject : (reason : any) => void, xhr : XMLHttpRequest) : void => {
|
|
||||||
if (xhr.status === 401) {
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xhr.responseType === 'text' || xhr.responseType === '') {
|
|
||||||
const rejection : IRestApiRejection = {
|
|
||||||
message: xhr.responseText || xhr.statusText,
|
|
||||||
status: xhr.status,
|
|
||||||
xhr,
|
|
||||||
error: null,
|
|
||||||
type: null,
|
|
||||||
content: null,
|
|
||||||
};
|
|
||||||
return reject(rejection);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const responseJSON = JSON.parse(xhr.response);
|
|
||||||
|
|
||||||
const rejection : IRestApiRejection = {
|
|
||||||
message: responseJSON.message || xhr.statusText,
|
|
||||||
status: xhr.status,
|
|
||||||
xhr,
|
|
||||||
error: null,
|
|
||||||
type: responseJSON.exception_type,
|
|
||||||
content: responseJSON.content,
|
|
||||||
};
|
|
||||||
return reject(rejection);
|
|
||||||
} catch (e) {
|
|
||||||
const rejection : IRestApiRejection = {
|
|
||||||
message: e.message,
|
|
||||||
status: xhr.status,
|
|
||||||
xhr,
|
|
||||||
error: e,
|
|
||||||
type: null,
|
|
||||||
content: null,
|
|
||||||
};
|
|
||||||
// tslint:disable-next-line:no-console
|
|
||||||
console.error('Failed to parse response', xhr);
|
|
||||||
return reject(rejection);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AjaxUtils = {
|
|
||||||
ajaxGet(url : string, queryObject? : any) : Promise<any> {
|
|
||||||
return new Promise<any>((resolve, reject) => {
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
const cacheBustingQueryObject = (queryObject || {}); // IE 11 caches GET requests
|
|
||||||
cacheBustingQueryObject._cache_busting_arg_ = +new Date(); // this parameter name must be in the backend's excluded parameter set (see api_utils.py)
|
|
||||||
|
|
||||||
xhr.open('GET', url + buildQueryString(cacheBustingQueryObject));
|
|
||||||
xhr.withCredentials = true;
|
|
||||||
xhr.onload = () => {
|
|
||||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
|
||||||
try {
|
|
||||||
return resolve(JSON.parse(xhr.response));
|
|
||||||
} catch (e) {
|
|
||||||
const rejection : IRestApiRejection = {
|
|
||||||
message: e.message,
|
|
||||||
status: xhr.status,
|
|
||||||
xhr,
|
|
||||||
error: e,
|
|
||||||
type: null,
|
|
||||||
content: null,
|
|
||||||
};
|
|
||||||
// tslint:disable-next-line:no-console
|
|
||||||
console.error('Failure to parse response', xhr);
|
|
||||||
return reject(rejection);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
xhr.onerror = (e) => {
|
|
||||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
|
||||||
};
|
|
||||||
xhr.send();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
ajaxPost(url : string, postBody : any, queryObject? : any, type? : 'text' | 'json') : Promise<any> {
|
|
||||||
return new Promise<any>((resolve, reject) => {
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('POST', url + buildQueryString(queryObject));
|
|
||||||
xhr.withCredentials = true;
|
|
||||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
|
||||||
xhr.setRequestHeader('X-CSRFToken', (window as any).CSRF_TOKEN);
|
|
||||||
xhr.onload = () => {
|
|
||||||
if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 201)) {
|
|
||||||
if (type === 'text') {
|
|
||||||
return resolve(xhr.response);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return resolve(JSON.parse(xhr.response));
|
|
||||||
} catch (e) {
|
|
||||||
const rejection : IRestApiRejection = {
|
|
||||||
message: e.message,
|
|
||||||
status: xhr.status,
|
|
||||||
xhr,
|
|
||||||
error: e,
|
|
||||||
type: null,
|
|
||||||
content: null,
|
|
||||||
};
|
|
||||||
// tslint:disable-next-line:no-console
|
|
||||||
console.error('Failure to parse response', xhr);
|
|
||||||
return reject(rejection);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
xhr.onerror = (e) => {
|
|
||||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
|
||||||
};
|
|
||||||
xhr.send(JSON.stringify(postBody || undefined));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
ajaxPostForm(url : string, formData? : FormData, queryObject? : any) : Promise<any> {
|
|
||||||
// Lesman 4/24/2017
|
|
||||||
// NOTE: you do not set the Content-Type on this request,
|
|
||||||
// the browser will automatically encode the form data and
|
|
||||||
// set the appropriate Content-Type. The encoding is browser
|
|
||||||
// specific so you MUST allow the browser to set the header
|
|
||||||
return new Promise<any>((resolve, reject) => {
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('POST', url + buildQueryString(queryObject));
|
|
||||||
xhr.withCredentials = true;
|
|
||||||
xhr.setRequestHeader('X-CSRFToken', (window as any).CSRF_TOKEN);
|
|
||||||
xhr.onload = () => handleXhrOnLoad(resolve, reject, xhr);
|
|
||||||
xhr.onerror = (e) => {
|
|
||||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
|
||||||
};
|
|
||||||
xhr.send(formData);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
ajaxPut(url : string, postBody : any, queryObject? : any) : Promise<any> {
|
|
||||||
return new Promise<any>((resolve, reject) => {
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('PUT', url + buildQueryString(queryObject));
|
|
||||||
xhr.withCredentials = true;
|
|
||||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
|
||||||
xhr.setRequestHeader('X-CSRFToken', (window as any).CSRF_TOKEN);
|
|
||||||
xhr.onload = () => handleXhrOnLoad(resolve, reject, xhr);
|
|
||||||
xhr.onerror = (e) => {
|
|
||||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
|
||||||
};
|
|
||||||
xhr.send(JSON.stringify(postBody || undefined));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
ajaxDelete(url : string, queryObject? : any) : Promise<any> {
|
|
||||||
return new Promise<any>((resolve, reject) => {
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('DELETE', url + buildQueryString(queryObject));
|
|
||||||
xhr.withCredentials = true;
|
|
||||||
xhr.setRequestHeader('X-CSRFToken', (window as any).CSRF_TOKEN);
|
|
||||||
xhr.onload = () => handleXhrOnLoad(resolve, reject, xhr);
|
|
||||||
xhr.onerror = (e) => {
|
|
||||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
|
||||||
};
|
|
||||||
xhr.send();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
146
src/ts/api/ApiService.ts
Normal file
146
src/ts/api/ApiService.ts
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
import csv from 'csvtojson';
|
||||||
|
import POGOProtos from 'pogo-protos';
|
||||||
|
import xhr2 from 'xhr2';
|
||||||
|
|
||||||
|
import { AjaxRequest } from 'api/AjaxRequest';
|
||||||
|
|
||||||
|
import { DEFAULT_POKEMON_NAME, IPokemonSpecies } from 'app/models/Pokemon';
|
||||||
|
|
||||||
|
interface IPokeApiSpeciesNameJSON {
|
||||||
|
pokemon_species_id : string;
|
||||||
|
local_language_id : '9' | string;
|
||||||
|
name : string;
|
||||||
|
genus : string;
|
||||||
|
}
|
||||||
|
interface IPokeApiSpeciesJSON {
|
||||||
|
id : string;
|
||||||
|
identifier : string;
|
||||||
|
order : string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ILivePokeApiLanguage {
|
||||||
|
name : 'en' | string;
|
||||||
|
}
|
||||||
|
interface ILivePokeApiSpeciesJSON {
|
||||||
|
id : number;
|
||||||
|
names : Array<{ name : string; language : ILivePokeApiLanguage; }>;
|
||||||
|
order : number;
|
||||||
|
flavor_text_entries : Array<{ description : string; language : ILivePokeApiLanguage; }>;
|
||||||
|
genera : Array<{ genus : string; language : ILivePokeApiLanguage; }>;
|
||||||
|
}
|
||||||
|
interface ILivePokeApiSpeciesListJSON {
|
||||||
|
count : number;
|
||||||
|
results : Array<{ name : string }>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IApiService {
|
||||||
|
getLivePokemonSpeciesKeys() : Promise<Array<string>>;
|
||||||
|
getPokemonSpeciesInfo(pokemonId : POGOProtos.Enums.PokemonId, defaultDex : number, defaultName : string) : Promise<IPokemonSpecies>;
|
||||||
|
getLivePokemonSpeciesInfo(dex : number) : Promise<IPokemonSpecies>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ApiService implements IApiService {
|
||||||
|
private AjaxRequest : AjaxRequest;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.AjaxRequest = new AjaxRequest(xhr2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getPokemonSpeciesInfo(pokemonId : POGOProtos.Enums.PokemonId, defaultDex : number, defaultName : string) {
|
||||||
|
const formattedName = this.formatPokemonIdToPokeApiNameKey(pokemonId);
|
||||||
|
|
||||||
|
const speciesArray : Array<IPokeApiSpeciesJSON> = await csv().fromFile('externals/PokeApi/data/v2/csv/pokemon_species.csv');
|
||||||
|
|
||||||
|
let dex = defaultDex;
|
||||||
|
let order = defaultDex;
|
||||||
|
for (const entry of speciesArray) {
|
||||||
|
if (entry.identifier === formattedName) {
|
||||||
|
dex = parseInt(entry.id, 10);
|
||||||
|
order = parseInt(entry.order, 10);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const namesArray : Array<IPokeApiSpeciesNameJSON> = await csv().fromFile('externals/PokeApi/data/v2/csv/pokemon_species_names.csv');
|
||||||
|
|
||||||
|
let name = defaultName;
|
||||||
|
let genus = '';
|
||||||
|
for (const entry of namesArray) {
|
||||||
|
if (parseInt(entry.pokemon_species_id, 10) === dex && entry.local_language_id === '9') {
|
||||||
|
name = entry.name;
|
||||||
|
genus = entry.genus;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const serializedResponse : IPokemonSpecies = {
|
||||||
|
name,
|
||||||
|
dex,
|
||||||
|
order,
|
||||||
|
genus,
|
||||||
|
};
|
||||||
|
return serializedResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getLivePokemonSpeciesKeys() {
|
||||||
|
const queryParameters = {
|
||||||
|
offset: 0,
|
||||||
|
limit: 9999, // 807 is current max from PokeApi
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://pokeapi.co/docs/v2.html#pokemon-species
|
||||||
|
const response : ILivePokeApiSpeciesListJSON = await this.AjaxRequest.ajaxGet(`https://pokeapi.co/api/v2/pokemon-species/`, queryParameters);
|
||||||
|
|
||||||
|
return response.results.map((listItem) => {
|
||||||
|
return listItem.name;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getLivePokemonSpeciesInfo(pokemonId : POGOProtos.Enums.PokemonId) {
|
||||||
|
const formattedName = this.formatPokemonIdToPokeApiNameKey(pokemonId);
|
||||||
|
|
||||||
|
const queryParameters = {
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://pokeapi.co/docs/v2.html#pokemon-species
|
||||||
|
const response : ILivePokeApiSpeciesJSON = await this.AjaxRequest.ajaxGet(`https://pokeapi.co/api/v2/pokemon-species/${formattedName}/`, queryParameters);
|
||||||
|
|
||||||
|
let name = DEFAULT_POKEMON_NAME;
|
||||||
|
response.names.some((entry) => {
|
||||||
|
if (entry.language.name === 'en') {
|
||||||
|
name = entry.name;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
let genus = '';
|
||||||
|
response.genera.some((entry) => {
|
||||||
|
if (entry.language.name === 'en') {
|
||||||
|
genus = entry.genus;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
const serializedResponse : IPokemonSpecies = {
|
||||||
|
name,
|
||||||
|
dex: response.id,
|
||||||
|
order: response.order,
|
||||||
|
genus,
|
||||||
|
};
|
||||||
|
return serializedResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
private formatPokemonIdToPokeApiNameKey(pokemonId : POGOProtos.Enums.PokemonId) {
|
||||||
|
let key : string;
|
||||||
|
if (pokemonId === POGOProtos.Enums.PokemonId.NIDORAN_MALE) {
|
||||||
|
key = 'nidoran-m';
|
||||||
|
} else if (pokemonId === POGOProtos.Enums.PokemonId.NIDORAN_FEMALE) {
|
||||||
|
key = 'nidoran-f';
|
||||||
|
} else {
|
||||||
|
key = POGOProtos.Enums.PokemonId[pokemonId];
|
||||||
|
}
|
||||||
|
return key.toLowerCase().replace(/_/, '-');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,87 +1,29 @@
|
|||||||
import { AjaxUtils } from 'api/AjaxUtils';
|
import POGOProtos from 'pogo-protos';
|
||||||
|
|
||||||
|
import { AjaxRequest } from 'api/AjaxRequest';
|
||||||
|
|
||||||
import { IConfig } from 'app/models/Config';
|
import { IConfig } from 'app/models/Config';
|
||||||
import { ILeaguePokemon, League } from 'app/models/League';
|
import { ILeaguePokemon } from 'app/models/League';
|
||||||
import { IPokemon } from 'app/models/Pokemon';
|
import { IPokemon } from 'app/models/Pokemon';
|
||||||
|
|
||||||
interface IPokemonJSON extends IPokemon {}
|
interface IPokemonService {
|
||||||
interface ILeaguePokemonJSON extends ILeaguePokemon {}
|
getConfig() : Promise<IConfig>;
|
||||||
interface IPokemonService {}
|
getPokemonList() : Promise<Array<IPokemon>>;
|
||||||
|
getPokemonLeagueStats(pokemonId : POGOProtos.Enums.PokemonId, form : POGOProtos.Enums.Form) : Promise<ILeaguePokemon>;
|
||||||
|
}
|
||||||
|
|
||||||
export class PokemonService implements IPokemonService {
|
export class PokemonService implements IPokemonService {
|
||||||
private static serializePokemonList(jsonPokemonList : Array<IPokemonJSON>) : Array<IPokemon> {
|
private AjaxRequest : AjaxRequest;
|
||||||
const pokemonList = jsonPokemonList.reduce((result : Array<IPokemon>, pokemonJson) => {
|
|
||||||
try {
|
|
||||||
if (typeof pokemonJson.name !== 'string') {
|
|
||||||
throw new Error('pokemon missing name');
|
|
||||||
}
|
|
||||||
if (typeof pokemonJson.id !== 'string') {
|
|
||||||
throw new Error('pokemon missing id');
|
|
||||||
}
|
|
||||||
if (typeof pokemonJson.family !== 'string') {
|
|
||||||
throw new Error('pokemon missing family');
|
|
||||||
}
|
|
||||||
if (typeof pokemonJson.dex !== 'number') {
|
|
||||||
throw new Error('pokemon missing dex');
|
|
||||||
}
|
|
||||||
if (typeof pokemonJson.stats !== 'object') {
|
|
||||||
throw new Error('pokemon missing stats');
|
|
||||||
}
|
|
||||||
const pokemon : IPokemon = { ...pokemonJson };
|
|
||||||
result.push(pokemon);
|
|
||||||
} catch (e) {
|
|
||||||
/* tslint:disable-next-line:no-console */
|
|
||||||
console.error(pokemonJson, e.message);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}, []);
|
|
||||||
return pokemonList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static serializePokemonLeagueStats(jsonPokemonLeagueStats : ILeaguePokemonJSON) : ILeaguePokemon {
|
constructor() {
|
||||||
let pokemonLeagueStats : ILeaguePokemon;
|
this.AjaxRequest = new AjaxRequest(XMLHttpRequest);
|
||||||
try {
|
|
||||||
if (typeof jsonPokemonLeagueStats.name !== 'string') {
|
|
||||||
throw new Error('pokemon league stats missing name');
|
|
||||||
}
|
|
||||||
if (typeof jsonPokemonLeagueStats.id !== 'string') {
|
|
||||||
throw new Error('pokemon league stats missing id');
|
|
||||||
}
|
|
||||||
if (typeof jsonPokemonLeagueStats.family !== 'string') {
|
|
||||||
throw new Error('pokemon league stats missing family');
|
|
||||||
}
|
|
||||||
if (typeof jsonPokemonLeagueStats.dex !== 'number') {
|
|
||||||
throw new Error('pokemon league stats missing dex');
|
|
||||||
}
|
|
||||||
if (typeof jsonPokemonLeagueStats.stats !== 'object') {
|
|
||||||
throw new Error('pokemon league stats missing stats');
|
|
||||||
}
|
|
||||||
if (typeof jsonPokemonLeagueStats.pvp !== 'object') {
|
|
||||||
throw new Error('pokemon league stats missing pvp');
|
|
||||||
}
|
|
||||||
pokemonLeagueStats = { ...jsonPokemonLeagueStats };
|
|
||||||
Object.keys(pokemonLeagueStats.pvp).forEach((key) => {
|
|
||||||
const league = key as League;
|
|
||||||
if (!Array.isArray(pokemonLeagueStats.pvp[league])) {
|
|
||||||
throw new Error('pokemon league not an array');
|
|
||||||
}
|
|
||||||
pokemonLeagueStats.pvp[league] = [ ...jsonPokemonLeagueStats.pvp[league] ];
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
/* tslint:disable-next-line:no-console */
|
|
||||||
console.error(jsonPokemonLeagueStats, e.message);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pokemonLeagueStats;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getConfig() {
|
public async getConfig() {
|
||||||
const queryParameters = {
|
const queryParameters = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const response : IConfig = await AjaxUtils.ajaxGet('/dist/db/config.json', queryParameters);
|
const response : IConfig = await this.AjaxRequest.ajaxGet('/dist/db/config.json', queryParameters);
|
||||||
// TODO: serialize this
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,15 +31,17 @@ export class PokemonService implements IPokemonService {
|
|||||||
const queryParameters = {
|
const queryParameters = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const response : Array<IPokemonJSON> = await AjaxUtils.ajaxGet('/dist/db/order.json', queryParameters);
|
const response : Array<IPokemon> = await this.AjaxRequest.ajaxGet('/dist/db/order.json', queryParameters);
|
||||||
return PokemonService.serializePokemonList(response);
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getPokemonLeagueStats(pokemonId : string) {
|
public async getPokemonLeagueStats(pokemonId : POGOProtos.Enums.PokemonId, form : POGOProtos.Enums.Form) {
|
||||||
|
const fileName = form === POGOProtos.Enums.Form.FORM_UNSET ? POGOProtos.Enums.PokemonId[pokemonId] : POGOProtos.Enums.Form[form];
|
||||||
|
|
||||||
const queryParameters = {
|
const queryParameters = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const response : ILeaguePokemonJSON = await AjaxUtils.ajaxGet(`/dist/db/${ pokemonId }.json`, queryParameters);
|
const response : ILeaguePokemon = await this.AjaxRequest.ajaxGet(`/dist/db/${ fileName }.json`, queryParameters);
|
||||||
return PokemonService.serializePokemonLeagueStats(response);
|
return response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import POGOProtos from 'pogo-protos';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
@ -40,6 +42,7 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps> {
|
|||||||
public render() {
|
public render() {
|
||||||
const {
|
const {
|
||||||
activePokemonId,
|
activePokemonId,
|
||||||
|
activePokemonForm,
|
||||||
pokemonList,
|
pokemonList,
|
||||||
pokemonListFiltered,
|
pokemonListFiltered,
|
||||||
filterTerm,
|
filterTerm,
|
||||||
@ -55,6 +58,7 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps> {
|
|||||||
<PokemonSelectList
|
<PokemonSelectList
|
||||||
isLoading={ this.props.pokemonSelectListState.isLoading }
|
isLoading={ this.props.pokemonSelectListState.isLoading }
|
||||||
activePokemonId={ activePokemonId }
|
activePokemonId={ activePokemonId }
|
||||||
|
activePokemonForm={ activePokemonForm }
|
||||||
pokemonList={ filterTerm === '' ? pokemonList : pokemonListFiltered }
|
pokemonList={ filterTerm === '' ? pokemonList : pokemonListFiltered }
|
||||||
filterTerm={ this.props.pokemonSelectListState.filterTerm }
|
filterTerm={ this.props.pokemonSelectListState.filterTerm }
|
||||||
handleActivatePokemon={ this.handleActivatePokemon }
|
handleActivatePokemon={ this.handleActivatePokemon }
|
||||||
@ -75,12 +79,12 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly handleActivatePokemon = (pokemonId : string) => {
|
private readonly handleActivatePokemon = (pokemonId : POGOProtos.Enums.PokemonId, form : POGOProtos.Enums.Form) => {
|
||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
|
|
||||||
dispatch(ActionsPokemonSelectList.fetchPokemonLeagueStats(pokemonId))
|
dispatch(ActionsPokemonSelectList.fetchPokemonLeagueStats(pokemonId, form))
|
||||||
.then((leaguePokemon) => {
|
.then((leaguePokemon) => {
|
||||||
dispatch(ActionsPokemonSelectList.setActivePokemonId(pokemonId));
|
dispatch(ActionsPokemonSelectList.setActivePokemonId(pokemonId, form));
|
||||||
dispatch(ActionsPokemonExplorer.setIvLevel(null));
|
dispatch(ActionsPokemonExplorer.setIvLevel(null));
|
||||||
dispatch(ActionsPokemonExplorer.setIvHp(null));
|
dispatch(ActionsPokemonExplorer.setIvHp(null));
|
||||||
dispatch(ActionsPokemonExplorer.setIvAtk(null));
|
dispatch(ActionsPokemonExplorer.setIvAtk(null));
|
||||||
|
|||||||
@ -1,16 +1,19 @@
|
|||||||
|
import POGOProtos from 'pogo-protos';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ContentRect, default as Measure } from 'react-measure';
|
import { ContentRect, default as Measure } from 'react-measure';
|
||||||
import { FixedSizeList } from 'react-window';
|
import { FixedSizeList } from 'react-window';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { Grade, IStats, PokemonId } from 'app/models/Pokemon';
|
import { Grade, IStats } from 'app/models/Pokemon';
|
||||||
import { IIndividualValues } from './types';
|
import { IIndividualValues } from './types';
|
||||||
|
|
||||||
import * as styles from './styles/LeagueStatsList.scss';
|
import * as styles from './styles/LeagueStatsList.scss';
|
||||||
|
|
||||||
export interface ILeagueStatsListProps {
|
export interface ILeagueStatsListProps {
|
||||||
activePokemonId : PokemonId;
|
activePokemonId : POGOProtos.Enums.PokemonId;
|
||||||
|
activePokemonForm : POGOProtos.Enums.Form | null;
|
||||||
activeIndividualValues : IIndividualValues;
|
activeIndividualValues : IIndividualValues;
|
||||||
leagueStatsList : Array<IStats>;
|
leagueStatsList : Array<IStats>;
|
||||||
|
|
||||||
@ -49,7 +52,7 @@ export class LeagueStatsList extends React.Component<ILeagueStatsListProps, ISta
|
|||||||
|
|
||||||
public componentWillReceiveProps(nextProps : ILeagueStatsListProps) {
|
public componentWillReceiveProps(nextProps : ILeagueStatsListProps) {
|
||||||
const activeIvs = nextProps.activeIndividualValues;
|
const activeIvs = nextProps.activeIndividualValues;
|
||||||
if (nextProps.activePokemonId !== this.props.activePokemonId) {
|
if (nextProps.activePokemonId !== this.props.activePokemonId || nextProps.activePokemonForm !== this.props.activePokemonForm) {
|
||||||
this.setState({ activeIndex: -1 });
|
this.setState({ activeIndex: -1 });
|
||||||
if (this.listRef.current !== null) {
|
if (this.listRef.current !== null) {
|
||||||
this.listRef.current.scrollToItem(0);
|
this.listRef.current.scrollToItem(0);
|
||||||
@ -125,7 +128,7 @@ export class LeagueStatsList extends React.Component<ILeagueStatsListProps, ISta
|
|||||||
|
|
||||||
private padString(value : string, length : number) {
|
private padString(value : string, length : number) {
|
||||||
let output = value;
|
let output = value;
|
||||||
for (let i = value.length - length - 1; i >= 0; i--) {
|
for (let i = length - value.length; i > 0; i--) {
|
||||||
output += String.fromCharCode(160);
|
output += String.fromCharCode(160);
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import POGOProtos from 'pogo-protos';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
@ -5,7 +7,7 @@ import classNames from 'classnames';
|
|||||||
import { ILeaguePokemon, League } from 'app/models/League';
|
import { ILeaguePokemon, League } from 'app/models/League';
|
||||||
import { Grade, IStats, } from 'app/models/Pokemon';
|
import { Grade, IStats, } from 'app/models/Pokemon';
|
||||||
import { calculateCp, calculateStatAtLevel } from 'app/utils/calculator';
|
import { calculateCp, calculateStatAtLevel } from 'app/utils/calculator';
|
||||||
import { formatDexNumber } from 'app/utils/formatter';
|
import { alolanForms, formatDexNumber, formatForm, formatType } from 'app/utils/formatter';
|
||||||
|
|
||||||
import { IIndividualValues, IndividualValueKey } from './types';
|
import { IIndividualValues, IndividualValueKey } from './types';
|
||||||
|
|
||||||
@ -188,18 +190,14 @@ export class PokemonExplorer extends React.Component<IPokemonExplorerProps, ISta
|
|||||||
const pokemonIconCss = classNames(
|
const pokemonIconCss = classNames(
|
||||||
`pokemon-${dex}`,
|
`pokemon-${dex}`,
|
||||||
{
|
{
|
||||||
alola: leaguePokemon.form === 'ALOLA'
|
alola: alolanForms.indexOf(leaguePokemon.form) > -1
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let type1 : JSX.Element | null = null;
|
const type1 : JSX.Element = <div className={ `${pokemonType} ${formatType(leaguePokemon.types.type1)}` }>{ formatType(leaguePokemon.types.type1) }</div>;
|
||||||
if (leaguePokemon.types.type1) {
|
|
||||||
type1 = <div className={ `${pokemonType} ${leaguePokemon.types.type1}` }>{ leaguePokemon.types.type1 }</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
let type2 : JSX.Element | null = null;
|
let type2 : JSX.Element | null = null;
|
||||||
if (leaguePokemon.types.type2) {
|
if (leaguePokemon.types.type2) {
|
||||||
type2 = <div className={ `${pokemonType} ${leaguePokemon.types.type2}` }>{ leaguePokemon.types.type2 }</div>;
|
type2 = <div className={ `${pokemonType} ${formatType(leaguePokemon.types.type2)}` }>{ formatType(leaguePokemon.types.type2) }</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -209,8 +207,8 @@ export class PokemonExplorer extends React.Component<IPokemonExplorerProps, ISta
|
|||||||
<div className={ styles.pokemonInfoLeftColumn }>
|
<div className={ styles.pokemonInfoLeftColumn }>
|
||||||
<i className={ pokemonIconCss } />
|
<i className={ pokemonIconCss } />
|
||||||
<h4 className={ styles.dexHeader }>No.{ dex }</h4>
|
<h4 className={ styles.dexHeader }>No.{ dex }</h4>
|
||||||
{ leaguePokemon.form &&
|
{ leaguePokemon.form !== POGOProtos.Enums.Form.FORM_UNSET &&
|
||||||
<h6 className={ styles.formHeader }>{ leaguePokemon.form.toLowerCase().replace('_', ' ') } Form</h6>
|
<h6 className={ styles.formHeader }>{ formatForm(leaguePokemon.form) } Form</h6>
|
||||||
}
|
}
|
||||||
<div className={ styles.pokemonTypeWrapper }>
|
<div className={ styles.pokemonTypeWrapper }>
|
||||||
{ type1 }
|
{ type1 }
|
||||||
@ -219,7 +217,7 @@ export class PokemonExplorer extends React.Component<IPokemonExplorerProps, ISta
|
|||||||
</div>
|
</div>
|
||||||
<div className={ styles.pokemonInfoRightColumn }>
|
<div className={ styles.pokemonInfoRightColumn }>
|
||||||
<h2 className={ styles.pokemonName }>{ leaguePokemon.name }</h2>
|
<h2 className={ styles.pokemonName }>{ leaguePokemon.name }</h2>
|
||||||
<h5>{ leaguePokemon.category }</h5>
|
<h5>{ leaguePokemon.genus }</h5>
|
||||||
<section className={ baseStatsCss }>
|
<section className={ baseStatsCss }>
|
||||||
<h3 className={ containerTitleCss }>Base Stats</h3>
|
<h3 className={ containerTitleCss }>Base Stats</h3>
|
||||||
<StatDisplay
|
<StatDisplay
|
||||||
@ -342,6 +340,7 @@ export class PokemonExplorer extends React.Component<IPokemonExplorerProps, ISta
|
|||||||
</div>
|
</div>
|
||||||
<LeagueStatsList
|
<LeagueStatsList
|
||||||
activePokemonId={ leaguePokemon.id }
|
activePokemonId={ leaguePokemon.id }
|
||||||
|
activePokemonForm={ leaguePokemon.form }
|
||||||
activeIndividualValues={ individualValues }
|
activeIndividualValues={ individualValues }
|
||||||
leagueStatsList={ leaguePokemon.pvp[activeLeague] }
|
leagueStatsList={ leaguePokemon.pvp[activeLeague] }
|
||||||
handleActivateLeagueStats={ this.handleActivateLeagueStats }
|
handleActivateLeagueStats={ this.handleActivateLeagueStats }
|
||||||
|
|||||||
@ -1,22 +1,25 @@
|
|||||||
|
import POGOProtos from 'pogo-protos';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ContentRect, default as Measure } from 'react-measure';
|
import { ContentRect, default as Measure } from 'react-measure';
|
||||||
import { VariableSizeList } from 'react-window';
|
import { VariableSizeList } from 'react-window';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { formatDexNumber } from 'app/utils/formatter';
|
import { formatDexNumber, formatForm } from 'app/utils/formatter';
|
||||||
|
|
||||||
import { IPokemon } from 'app/models/Pokemon';
|
import { DEFAULT_POKEMON_NAME, IPokemon } from 'app/models/Pokemon';
|
||||||
|
|
||||||
import * as styles from './styles/PokemonSelectList.scss';
|
import * as styles from './styles/PokemonSelectList.scss';
|
||||||
|
|
||||||
export interface IPokemonSelectListProps {
|
export interface IPokemonSelectListProps {
|
||||||
isLoading : boolean;
|
isLoading : boolean;
|
||||||
activePokemonId : string | null;
|
activePokemonId : POGOProtos.Enums.PokemonId | null;
|
||||||
|
activePokemonForm : POGOProtos.Enums.Form | null;
|
||||||
pokemonList : Array<IPokemon>;
|
pokemonList : Array<IPokemon>;
|
||||||
filterTerm : string;
|
filterTerm : string;
|
||||||
|
|
||||||
handleActivatePokemon : (pokemonId : string) => void;
|
handleActivatePokemon : (pokemonId : POGOProtos.Enums.PokemonId, form : POGOProtos.Enums.Form) => void;
|
||||||
handleChangeFilter : (filterTerm : string) => Promise<void>;
|
handleChangeFilter : (filterTerm : string) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +124,7 @@ export class PokemonSelectList extends React.Component<IPokemonSelectListProps,
|
|||||||
{ listLength === 0 &&
|
{ listLength === 0 &&
|
||||||
<div className={ styles.emptyState }>
|
<div className={ styles.emptyState }>
|
||||||
<i className="pokemon-missing-no" />
|
<i className="pokemon-missing-no" />
|
||||||
<h3>MissingNo.</h3>
|
<h3>{ DEFAULT_POKEMON_NAME }</h3>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@ -134,7 +137,7 @@ export class PokemonSelectList extends React.Component<IPokemonSelectListProps,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly calculateRowHeight = (index : number) => {
|
private readonly calculateRowHeight = (index : number) => {
|
||||||
return this.props.pokemonList[index].form !== null ? 40 : 25;
|
return this.props.pokemonList[index].form === POGOProtos.Enums.Form.FORM_UNSET ? 25 : 40;
|
||||||
}
|
}
|
||||||
|
|
||||||
private rowFactory({ index, style } : IRowFactory) {
|
private rowFactory({ index, style } : IRowFactory) {
|
||||||
@ -143,7 +146,7 @@ export class PokemonSelectList extends React.Component<IPokemonSelectListProps,
|
|||||||
const anchorCss = classNames(
|
const anchorCss = classNames(
|
||||||
'list-item',
|
'list-item',
|
||||||
{
|
{
|
||||||
active: this.props.activePokemonId === pokemon.id
|
active: this.props.activePokemonId === pokemon.id && this.props.activePokemonForm === pokemon.form
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const dexCss = classNames(
|
const dexCss = classNames(
|
||||||
@ -154,7 +157,7 @@ export class PokemonSelectList extends React.Component<IPokemonSelectListProps,
|
|||||||
'de-emphasize',
|
'de-emphasize',
|
||||||
styles.form
|
styles.form
|
||||||
);
|
);
|
||||||
const onClick = () => this.props.handleActivatePokemon(pokemon.id);
|
const onClick = () => this.props.handleActivatePokemon(pokemon.id, pokemon.form);
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
key={ index + pokemon.id }
|
key={ index + pokemon.id }
|
||||||
@ -164,8 +167,8 @@ export class PokemonSelectList extends React.Component<IPokemonSelectListProps,
|
|||||||
>
|
>
|
||||||
<span>{ pokemon.name }</span>
|
<span>{ pokemon.name }</span>
|
||||||
<span className={ dexCss }>#{ dex }</span>
|
<span className={ dexCss }>#{ dex }</span>
|
||||||
{ pokemon.form &&
|
{ pokemon.form !== POGOProtos.Enums.Form.FORM_UNSET &&
|
||||||
<span className={ formCss }>{ pokemon.form.toLowerCase().replace('_', ' ') } Form</span>
|
<span className={ formCss }>{ formatForm(pokemon.form) } Form</span>
|
||||||
}
|
}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import POGOProtos from 'pogo-protos';
|
||||||
|
|
||||||
import { action } from 'typesafe-actions';
|
import { action } from 'typesafe-actions';
|
||||||
|
|
||||||
import { ILeaguePokemon } from 'app/models/League';
|
import { ILeaguePokemon } from 'app/models/League';
|
||||||
@ -12,9 +14,9 @@ export const setPokemonList = (pokemonList : Array<IPokemon>) => action(PokemonS
|
|||||||
|
|
||||||
export const setPokemonListFiltered = (filterTerm : string, pokemonListFiltered : Array<IPokemon>) => action(PokemonSelectListActionTypes.SET_POKEMON_LIST_FILTERED, { filterTerm, pokemonListFiltered });
|
export const setPokemonListFiltered = (filterTerm : string, pokemonListFiltered : Array<IPokemon>) => action(PokemonSelectListActionTypes.SET_POKEMON_LIST_FILTERED, { filterTerm, pokemonListFiltered });
|
||||||
|
|
||||||
export const setActivePokemonId = (activePokemonId : string | null) => action(PokemonSelectListActionTypes.SET_ACTIVE_POKEMON_ID, { activePokemonId });
|
export const setActivePokemonId = (activePokemonId : POGOProtos.Enums.PokemonId | null, activePokemonForm : POGOProtos.Enums.Form | null) => action(PokemonSelectListActionTypes.SET_ACTIVE_POKEMON_ID, { activePokemonId, activePokemonForm });
|
||||||
|
|
||||||
export const setPokemonLeagueStats = (pokemonId : string, pokemonLeagueStats : ILeaguePokemon) => action(PokemonSelectListActionTypes.SET_POKEMON_LEAGUE_STATS, { pokemonId, pokemonLeagueStats });
|
export const setPokemonLeagueStats = (pokemonId : POGOProtos.Enums.PokemonId, pokemonLeagueStats : ILeaguePokemon) => action(PokemonSelectListActionTypes.SET_POKEMON_LEAGUE_STATS, { pokemonId, pokemonLeagueStats });
|
||||||
|
|
||||||
export const filterPokemonList = (
|
export const filterPokemonList = (
|
||||||
filterTerm : string
|
filterTerm : string
|
||||||
@ -27,7 +29,7 @@ export const filterPokemonList = (
|
|||||||
pokemonListFiltered = pokemonList.reduce((result : Array<IPokemon>, pokemon) => {
|
pokemonListFiltered = pokemonList.reduce((result : Array<IPokemon>, pokemon) => {
|
||||||
const pokemonName = pokemon.name.toLowerCase();
|
const pokemonName = pokemon.name.toLowerCase();
|
||||||
const pokemonDex = '' + pokemon.dex;
|
const pokemonDex = '' + pokemon.dex;
|
||||||
const pokemonForm = (pokemon.form || '').toLowerCase();
|
const pokemonForm = pokemon.form === null ? '' : POGOProtos.Enums.Form[pokemon.form].toLowerCase();
|
||||||
if (pokemonName.indexOf(normalizedFilterTerm) === 0 ||
|
if (pokemonName.indexOf(normalizedFilterTerm) === 0 ||
|
||||||
pokemonDex.indexOf(normalizedFilterTerm) === 0 ||
|
pokemonDex.indexOf(normalizedFilterTerm) === 0 ||
|
||||||
normalizedFilterTerm === pokemonForm
|
normalizedFilterTerm === pokemonForm
|
||||||
@ -50,10 +52,11 @@ export const fetchPokemonList = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const fetchPokemonLeagueStats = (
|
export const fetchPokemonLeagueStats = (
|
||||||
pokemonId : string
|
pokemonId : POGOProtos.Enums.PokemonId,
|
||||||
|
form : POGOProtos.Enums.Form
|
||||||
) : ThunkResult<Promise<ILeaguePokemon>> => {
|
) : ThunkResult<Promise<ILeaguePokemon>> => {
|
||||||
return async (dispatch, getState, extraArguments) => {
|
return async (dispatch, getState, extraArguments) => {
|
||||||
const pokemonLeagueStats = await extraArguments.services.pokemonService.getPokemonLeagueStats(pokemonId);
|
const pokemonLeagueStats = await extraArguments.services.pokemonService.getPokemonLeagueStats(pokemonId, form);
|
||||||
dispatch(setPokemonLeagueStats(pokemonId, pokemonLeagueStats));
|
dispatch(setPokemonLeagueStats(pokemonId, pokemonLeagueStats));
|
||||||
return pokemonLeagueStats;
|
return pokemonLeagueStats;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { IPokemonSelectListState, PokemonSelectListActionTypes } from './types';
|
|||||||
export const initialState : IPokemonSelectListState = {
|
export const initialState : IPokemonSelectListState = {
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
activePokemonId: null,
|
activePokemonId: null,
|
||||||
|
activePokemonForm: null,
|
||||||
pokemonList: [],
|
pokemonList: [],
|
||||||
pokemonListFiltered: [],
|
pokemonListFiltered: [],
|
||||||
filterTerm: '',
|
filterTerm: '',
|
||||||
@ -43,6 +44,7 @@ const reduceSetActivePokemonId = (
|
|||||||
) : IPokemonSelectListState => ({
|
) : IPokemonSelectListState => ({
|
||||||
...state,
|
...state,
|
||||||
activePokemonId: action.payload.activePokemonId,
|
activePokemonId: action.payload.activePokemonId,
|
||||||
|
activePokemonForm: action.payload.activePokemonForm,
|
||||||
});
|
});
|
||||||
|
|
||||||
const reduceSetPokemonLeagueStats = (
|
const reduceSetPokemonLeagueStats = (
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
|
import POGOProtos from 'pogo-protos';
|
||||||
|
|
||||||
import { ILeaguePokemon } from 'app/models/League';
|
import { ILeaguePokemon } from 'app/models/League';
|
||||||
import { IPokemon } from 'app/models/Pokemon';
|
import { IPokemon } from 'app/models/Pokemon';
|
||||||
|
|
||||||
export interface IPokemonSelectListState {
|
export interface IPokemonSelectListState {
|
||||||
isLoading : boolean;
|
isLoading : boolean;
|
||||||
activePokemonId : string | null;
|
activePokemonId : POGOProtos.Enums.PokemonId | null;
|
||||||
|
activePokemonForm : POGOProtos.Enums.Form | null;
|
||||||
pokemonList : Array<IPokemon>;
|
pokemonList : Array<IPokemon>;
|
||||||
pokemonListFiltered : Array<IPokemon>;
|
pokemonListFiltered : Array<IPokemon>;
|
||||||
filterTerm : string;
|
filterTerm : string;
|
||||||
pokemonLeagueStats : { [id : string] : ILeaguePokemon };
|
pokemonLeagueStats : { [id in keyof typeof POGOProtos.Enums.PokemonId]? : ILeaguePokemon };
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PokemonSelectListActionTypes = {
|
export const PokemonSelectListActionTypes = {
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
import POGOProtos from 'pogo-protos';
|
||||||
|
|
||||||
|
export const DEFAULT_POKEMON_NAME = 'MissingNo.';
|
||||||
|
|
||||||
export enum Grade {
|
export enum Grade {
|
||||||
'S',
|
'S',
|
||||||
'A',
|
'A',
|
||||||
@ -23,17 +27,20 @@ export interface IMaxStats extends IBaseStats {
|
|||||||
level : number;
|
level : number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Type = 'bug' | 'dark' | 'dragon' | 'electric' | 'fairy' | 'fighting' | 'fire' | 'flying' | 'ghost' | 'grass' | 'ground' | 'ice' | 'normal' | 'poison' | 'psychic' | 'rock' | 'steel' | 'water';
|
export interface IPokemonSpecies {
|
||||||
export interface IPokemon {
|
|
||||||
id : PokemonId;
|
|
||||||
name : string;
|
name : string;
|
||||||
category : string;
|
|
||||||
form : string | null;
|
|
||||||
family : string;
|
|
||||||
dex : number;
|
dex : number;
|
||||||
|
order : number;
|
||||||
|
genus : string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPokemon extends IPokemonSpecies {
|
||||||
|
id : POGOProtos.Enums.PokemonId;
|
||||||
|
form : POGOProtos.Enums.Form;
|
||||||
|
family : POGOProtos.Enums.PokemonFamilyId;
|
||||||
types : {
|
types : {
|
||||||
type1 : Type;
|
type1 : POGOProtos.Enums.PokemonType;
|
||||||
type2 : Type | null;
|
type2 : POGOProtos.Enums.PokemonType | null;
|
||||||
};
|
};
|
||||||
stats : IBaseStats;
|
stats : IBaseStats;
|
||||||
statsRank : IBaseStatsRank;
|
statsRank : IBaseStatsRank;
|
||||||
@ -52,75 +59,3 @@ export interface IStats {
|
|||||||
speciesGrade : Grade;
|
speciesGrade : Grade;
|
||||||
metaGrade : Grade;
|
metaGrade : Grade;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PokemonId = 'BULBASAUR' | 'IVYSAUR' | 'VENUSAUR' | 'CHARMANDER' |
|
|
||||||
'CHARMELEON' | 'CHARIZARD' | 'SQUIRTLE' | 'WARTORTLE' | 'BLASTOISE' |
|
|
||||||
'CATERPIE' | 'METAPOD' | 'BUTTERFREE' | 'WEEDLE' | 'KAKUNA' | 'BEEDRILL' |
|
|
||||||
'PIDGEY' | 'PIDGEOTTO' | 'PIDGEOT' | 'RATTATA' | 'RATTATA_ALOLA' | 'RATICATE' |
|
|
||||||
'RATICATE_ALOLA' | 'SPEAROW' | 'FEAROW' | 'EKANS' | 'ARBOK' | 'PIKACHU' |
|
|
||||||
'RAICHU' | 'RAICHU_ALOLA' | 'SANDSHREW' | 'SANDSHREW_ALOLA' | 'SANDSLASH' |
|
|
||||||
'SANDSLASH_ALOLA' | 'NIDORAN_FEMALE' | 'NIDORINA' | 'NIDOQUEEN' |
|
|
||||||
'NIDORAN_MALE' | 'NIDORINO' | 'NIDOKING' | 'CLEFAIRY' | 'CLEFABLE' | 'VULPIX' |
|
|
||||||
'VULPIX_ALOLA' | 'NINETALES' | 'NINETALES_ALOLA' | 'JIGGLYPUFF' |
|
|
||||||
'WIGGLYTUFF' | 'ZUBAT' | 'GOLBAT' | 'ODDISH' | 'GLOOM' | 'VILEPLUME' |
|
|
||||||
'PARAS' | 'PARASECT' | 'VENONAT' | 'VENOMOTH' | 'DIGLETT' | 'DIGLETT_ALOLA' |
|
|
||||||
'DUGTRIO' | 'DUGTRIO_ALOLA' | 'MEOWTH' | 'MEOWTH_ALOLA' | 'PERSIAN' |
|
|
||||||
'PERSIAN_ALOLA' | 'PSYDUCK' | 'GOLDUCK' | 'MANKEY' | 'PRIMEAPE' | 'GROWLITHE' |
|
|
||||||
'ARCANINE' | 'POLIWAG' | 'POLIWHIRL' | 'POLIWRATH' | 'ABRA' | 'KADABRA' |
|
|
||||||
'ALAKAZAM' | 'MACHOP' | 'MACHOKE' | 'MACHAMP' | 'BELLSPROUT' | 'WEEPINBELL' |
|
|
||||||
'VICTREEBEL' | 'TENTACOOL' | 'TENTACRUEL' | 'GEODUDE' | 'GEODUDE_ALOLA' |
|
|
||||||
'GRAVELER' | 'GRAVELER_ALOLA' | 'GOLEM' | 'GOLEM_ALOLA' | 'PONYTA' |
|
|
||||||
'RAPIDASH' | 'SLOWPOKE' | 'SLOWBRO' | 'MAGNEMITE' | 'MAGNETON' | 'FARFETCHD' |
|
|
||||||
'DODUO' | 'DODRIO' | 'SEEL' | 'DEWGONG' | 'GRIMER' | 'GRIMER_ALOLA' | 'MUK' |
|
|
||||||
'MUK_ALOLA' | 'SHELLDER' | 'CLOYSTER' | 'GASTLY' | 'HAUNTER' | 'GENGAR' |
|
|
||||||
'ONIX' | 'DROWZEE' | 'HYPNO' | 'KRABBY' | 'KINGLER' | 'VOLTORB' | 'ELECTRODE' |
|
|
||||||
'EXEGGCUTE' | 'EXEGGUTOR' | 'EXEGGUTOR_ALOLA' | 'CUBONE' | 'MAROWAK' |
|
|
||||||
'MAROWAK_ALOLA' | 'HITMONLEE' | 'HITMONCHAN' | 'LICKITUNG' | 'KOFFING' |
|
|
||||||
'WEEZING' | 'RHYHORN' | 'RHYDON' | 'CHANSEY' | 'TANGELA' | 'KANGASKHAN' |
|
|
||||||
'HORSEA' | 'SEADRA' | 'GOLDEEN' | 'SEAKING' | 'STARYU' | 'STARMIE' |
|
|
||||||
'MR_MIME' | 'SCYTHER' | 'JYNX' | 'ELECTABUZZ' | 'MAGMAR' | 'PINSIR' |
|
|
||||||
'TAUROS' | 'MAGIKARP' | 'GYARADOS' | 'LAPRAS' | 'DITTO' | 'EEVEE' |
|
|
||||||
'VAPOREON' | 'JOLTEON' | 'FLAREON' | 'PORYGON' | 'OMANYTE' | 'OMASTAR' |
|
|
||||||
'KABUTO' | 'KABUTOPS' | 'AERODACTYL' | 'SNORLAX' | 'ARTICUNO' | 'ZAPDOS' |
|
|
||||||
'MOLTRES' | 'DRATINI' | 'DRAGONAIR' | 'DRAGONITE' | 'MEWTWO' | 'MEW' |
|
|
||||||
'CHIKORITA' | 'BAYLEEF' | 'MEGANIUM' | 'CYNDAQUIL' | 'QUILAVA' | 'TYPHLOSION' |
|
|
||||||
'TOTODILE' | 'CROCONAW' | 'FERALIGATR' | 'SENTRET' | 'FURRET' | 'HOOTHOOT' |
|
|
||||||
'NOCTOWL' | 'LEDYBA' | 'LEDIAN' | 'SPINARAK' | 'ARIADOS' | 'CROBAT' |
|
|
||||||
'CHINCHOU' | 'LANTURN' | 'PICHU' | 'CLEFFA' | 'IGGLYBUFF' | 'TOGEPI' |
|
|
||||||
'TOGETIC' | 'NATU' | 'XATU' | 'MAREEP' | 'FLAAFFY' | 'AMPHAROS' | 'BELLOSSOM' |
|
|
||||||
'MARILL' | 'AZUMARILL' | 'SUDOWOODO' | 'POLITOED' | 'HOPPIP' | 'SKIPLOOM' |
|
|
||||||
'JUMPLUFF' | 'AIPOM' | 'SUNKERN' | 'SUNFLORA' | 'YANMA' | 'WOOPER' |
|
|
||||||
'QUAGSIRE' | 'ESPEON' | 'UMBREON' | 'MURKROW' | 'SLOWKING' | 'MISDREAVUS' |
|
|
||||||
'UNOWN' | 'WOBBUFFET' | 'GIRAFARIG' | 'PINECO' | 'FORRETRESS' | 'DUNSPARCE' |
|
|
||||||
'GLIGAR' | 'STEELIX' | 'SNUBBULL' | 'GRANBULL' | 'QWILFISH' | 'SCIZOR' |
|
|
||||||
'SHUCKLE' | 'HERACROSS' | 'SNEASEL' | 'TEDDIURSA' | 'URSARING' | 'SLUGMA' |
|
|
||||||
'MAGCARGO' | 'SWINUB' | 'PILOSWINE' | 'CORSOLA' | 'REMORAID' | 'OCTILLERY' |
|
|
||||||
'DELIBIRD' | 'MANTINE' | 'SKARMORY' | 'HOUNDOUR' | 'HOUNDOOM' | 'KINGDRA' |
|
|
||||||
'PHANPY' | 'DONPHAN' | 'PORYGON2' | 'STANTLER' | 'SMEARGLE' | 'TYROGUE' |
|
|
||||||
'HITMONTOP' | 'SMOOCHUM' | 'ELEKID' | 'MAGBY' | 'MILTANK' | 'BLISSEY' |
|
|
||||||
'RAIKOU' | 'ENTEI' | 'SUICUNE' | 'LARVITAR' | 'PUPITAR' | 'TYRANITAR' |
|
|
||||||
'LUGIA' | 'HO_OH' | 'CELEBI' | 'TREECKO' | 'GROVYLE' | 'SCEPTILE' | 'TORCHIC' |
|
|
||||||
'COMBUSKEN' | 'BLAZIKEN' | 'MUDKIP' | 'MARSHTOMP' | 'SWAMPERT' |
|
|
||||||
'POOCHYENA' | 'MIGHTYENA' | 'ZIGZAGOON' | 'LINOONE' | 'WURMPLE' | 'SILCOON' |
|
|
||||||
'BEAUTIFLY' | 'CASCOON' | 'DUSTOX' | 'LOTAD' | 'LOMBRE' | 'LUDICOLO' |
|
|
||||||
'SEEDOT' | 'NUZLEAF' | 'SHIFTRY' | 'TAILLOW' | 'SWELLOW' | 'WINGULL' |
|
|
||||||
'PELIPPER' | 'RALTS' | 'KIRLIA' | 'GARDEVOIR' | 'SURSKIT' | 'MASQUERAIN' |
|
|
||||||
'SHROOMISH' | 'BRELOOM' | 'SLAKOTH' | 'VIGOROTH' | 'SLAKING' | 'NINCADA' |
|
|
||||||
'NINJASK' | 'SHEDINJA' | 'WHISMUR' | 'LOUDRED' | 'EXPLOUD' | 'MAKUHITA' |
|
|
||||||
'HARIYAMA' | 'AZURILL' | 'NOSEPASS' | 'SKITTY' | 'DELCATTY' | 'SABLEYE' |
|
|
||||||
'MAWILE' | 'ARON' | 'LAIRON' | 'AGGRON' | 'MEDITITE' | 'MEDICHAM' |
|
|
||||||
'ELECTRIKE' | 'MANECTRIC' | 'PLUSLE' | 'MINUN' | 'VOLBEAT' | 'ILLUMISE' |
|
|
||||||
'ROSELIA' | 'GULPIN' | 'SWALOT' | 'CARVANHA' | 'SHARPEDO' | 'WAILMER' |
|
|
||||||
'WAILORD' | 'NUMEL' | 'CAMERUPT' | 'TORKOAL' | 'SPOINK' | 'GRUMPIG' |
|
|
||||||
'SPINDA' | 'TRAPINCH' | 'VIBRAVA' | 'FLYGON' | 'CACNEA' | 'CACTURNE' |
|
|
||||||
'SWABLU' | 'ALTARIA' | 'ZANGOOSE' | 'SEVIPER' | 'LUNATONE' | 'SOLROCK' |
|
|
||||||
'BARBOACH' | 'WHISCASH' | 'CORPHISH' | 'CRAWDAUNT' | 'BALTOY' | 'CLAYDOL' |
|
|
||||||
'LILEEP' | 'CRADILY' | 'ANORITH' | 'ARMALDO' | 'FEEBAS' | 'MILOTIC' |
|
|
||||||
'CASTFORM' | 'CASTFORM_RAINY' | 'CASTFORM_SNOWY' | 'CASTFORM_SUNNY' |
|
|
||||||
'KECLEON' | 'SHUPPET' | 'BANETTE' | 'DUSKULL' | 'DUSCLOPS' | 'TROPIUS' |
|
|
||||||
'CHIMECHO' | 'ABSOL' | 'WYNAUT' | 'SNORUNT' | 'GLALIE' | 'SPHEAL' | 'SEALEO' |
|
|
||||||
'WALREIN' | 'CLAMPERL' | 'HUNTAIL' | 'GOREBYSS' | 'RELICANTH' | 'LUVDISC' |
|
|
||||||
'BAGON' | 'SHELGON' | 'SALAMENCE' | 'BELDUM' | 'METANG' | 'METAGROSS' |
|
|
||||||
'REGIROCK' | 'REGICE' | 'REGISTEEL' | 'LATIAS' | 'LATIOS' | 'KYOGRE' |
|
|
||||||
'GROUDON' | 'RAYQUAZA' | 'JIRACHI' | 'DEOXYS' | 'DEOXYS_ATTACK' |
|
|
||||||
'DEOXYS_DEFENSE' | 'DEOXYS_SPEED';
|
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import POGOProtos from 'pogo-protos';
|
||||||
|
|
||||||
export const formatDexNumber = (dex : number) => {
|
export const formatDexNumber = (dex : number) => {
|
||||||
let prefix : string = '';
|
let prefix : string = '';
|
||||||
if (dex < 100) {
|
if (dex < 100) {
|
||||||
@ -8,3 +10,75 @@ export const formatDexNumber = (dex : number) => {
|
|||||||
}
|
}
|
||||||
return prefix + dex;
|
return prefix + dex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const formatType = (type : POGOProtos.Enums.PokemonType) => {
|
||||||
|
switch (type) {
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_NORMAL:
|
||||||
|
return 'normal';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_FIGHTING:
|
||||||
|
return 'fighting';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_FLYING:
|
||||||
|
return 'flying';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_POISON:
|
||||||
|
return 'poison';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_GROUND:
|
||||||
|
return 'ground';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_ROCK:
|
||||||
|
return 'rock';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_BUG:
|
||||||
|
return 'bug';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_GHOST:
|
||||||
|
return 'ghost';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_STEEL:
|
||||||
|
return 'steel';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_FIRE:
|
||||||
|
return 'fire';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_WATER:
|
||||||
|
return 'water';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_GRASS:
|
||||||
|
return 'grass';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_ELECTRIC:
|
||||||
|
return 'electric';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_PSYCHIC:
|
||||||
|
return 'psychic';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_ICE:
|
||||||
|
return 'ice';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_DRAGON:
|
||||||
|
return 'dragon';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_DARK:
|
||||||
|
return 'dark';
|
||||||
|
case POGOProtos.Enums.PokemonType.POKEMON_TYPE_FAIRY:
|
||||||
|
return 'fairy';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const alolanForms = [
|
||||||
|
POGOProtos.Enums.Form.RATTATA_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.RATICATE_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.RAICHU_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.SANDSHREW_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.SANDSLASH_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.VULPIX_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.NINETALES_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.DIGLETT_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.DUGTRIO_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.MEOWTH_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.PERSIAN_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.GEODUDE_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.GRAVELER_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.GOLEM_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.GRIMER_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.MUK_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.EXEGGUTOR_ALOLA,
|
||||||
|
POGOProtos.Enums.Form.MAROWAK_ALOLA,
|
||||||
|
];
|
||||||
|
|
||||||
|
export const formatForm = (form : POGOProtos.Enums.Form) => {
|
||||||
|
if (alolanForms.indexOf(form) > -1) {
|
||||||
|
return 'Alola';
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
3
src/ts/common/xhr2/index.d.ts
vendored
Normal file
3
src/ts/common/xhr2/index.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
declare module 'xhr2' {
|
||||||
|
export = XMLHttpRequest;
|
||||||
|
}
|
||||||
@ -9,6 +9,7 @@
|
|||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
|
"lib": ["es2017", "dom"],
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"jsx": "react",
|
"jsx": "react",
|
||||||
"baseUrl": "./",
|
"baseUrl": "./",
|
||||||
@ -17,19 +18,18 @@
|
|||||||
"api/*": ["src/ts/api/*"],
|
"api/*": ["src/ts/api/*"],
|
||||||
"app/*": ["src/ts/app/*"],
|
"app/*": ["src/ts/app/*"],
|
||||||
"common/*": ["src/ts/common/*"],
|
"common/*": ["src/ts/common/*"],
|
||||||
"styles/*": ["src/scss/*"]
|
"externals/*": ["externals/*"],
|
||||||
|
"styles/*": ["src/scss/*"],
|
||||||
|
"xhr2": ["src/ts/common/xhr2"],
|
||||||
},
|
},
|
||||||
"plugins": [{
|
"plugins": [{
|
||||||
"name": "tslint-language-service",
|
"name": "tslint-language-service",
|
||||||
"disableNoUnusedVariableRule": false
|
"disableNoUnusedVariableRule": false
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
"include": [
|
|
||||||
"src/**/*",
|
|
||||||
"."
|
|
||||||
],
|
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules",
|
||||||
"dist"
|
"dist",
|
||||||
|
"externals",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": ["tslint:latest", "tslint-react", "tslint-eslint-rules"],
|
"extends": ["tslint:latest", "tslint-react", "tslint-eslint-rules"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-implicit-dependencies": [true, ["api", "app", "common", "styles"]],
|
"no-implicit-dependencies": [true, "dev", ["api", "app", "common", "externals", "styles"]],
|
||||||
"no-default-export": true,
|
"no-default-export": true,
|
||||||
"no-unused-expression": true,
|
"no-unused-expression": true,
|
||||||
"no-unused-variable": [true, "react"],
|
"no-unused-variable": [true, "react"],
|
||||||
|
|||||||
@ -12,6 +12,7 @@ const typescriptResolve = {
|
|||||||
'api': path.resolve('./src/ts/api'),
|
'api': path.resolve('./src/ts/api'),
|
||||||
'app': path.resolve('./src/ts/app'),
|
'app': path.resolve('./src/ts/app'),
|
||||||
'common': path.resolve('./src/ts/common'),
|
'common': path.resolve('./src/ts/common'),
|
||||||
|
'externals': path.resolve('./externals'),
|
||||||
'styles': path.resolve('./src/scss'),
|
'styles': path.resolve('./src/scss'),
|
||||||
},
|
},
|
||||||
extensions: ['.ts', '.tsx', '.js'],
|
extensions: ['.ts', '.tsx', '.js'],
|
||||||
|
|||||||
108
yarn.lock
108
yarn.lock
@ -726,6 +726,59 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
|
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
|
||||||
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
|
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
|
||||||
|
|
||||||
|
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
|
||||||
|
integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78=
|
||||||
|
|
||||||
|
"@protobufjs/base64@^1.1.2":
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735"
|
||||||
|
integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
|
||||||
|
|
||||||
|
"@protobufjs/codegen@^2.0.4":
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb"
|
||||||
|
integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
|
||||||
|
|
||||||
|
"@protobufjs/eventemitter@^1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70"
|
||||||
|
integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A=
|
||||||
|
|
||||||
|
"@protobufjs/fetch@^1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45"
|
||||||
|
integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=
|
||||||
|
dependencies:
|
||||||
|
"@protobufjs/aspromise" "^1.1.1"
|
||||||
|
"@protobufjs/inquire" "^1.1.0"
|
||||||
|
|
||||||
|
"@protobufjs/float@^1.0.2":
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1"
|
||||||
|
integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=
|
||||||
|
|
||||||
|
"@protobufjs/inquire@^1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089"
|
||||||
|
integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=
|
||||||
|
|
||||||
|
"@protobufjs/path@^1.1.2":
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d"
|
||||||
|
integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=
|
||||||
|
|
||||||
|
"@protobufjs/pool@^1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54"
|
||||||
|
integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=
|
||||||
|
|
||||||
|
"@protobufjs/utf8@^1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
|
||||||
|
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
|
||||||
|
|
||||||
"@types/classnames@^2.2.7":
|
"@types/classnames@^2.2.7":
|
||||||
version "2.2.7"
|
version "2.2.7"
|
||||||
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.7.tgz#fb68cc9be8487e6ea5b13700e759bfbab7e0fefd"
|
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.7.tgz#fb68cc9be8487e6ea5b13700e759bfbab7e0fefd"
|
||||||
@ -736,6 +789,16 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||||
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
||||||
|
|
||||||
|
"@types/long@^4.0.0":
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.0.tgz#719551d2352d301ac8b81db732acb6bdc28dbdef"
|
||||||
|
integrity sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==
|
||||||
|
|
||||||
|
"@types/node@^10.1.0":
|
||||||
|
version "10.12.24"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.24.tgz#b13564af612a22a20b5d95ca40f1bffb3af315cf"
|
||||||
|
integrity sha512-GWWbvt+z9G5otRBW8rssOFgRY87J9N/qbhqfjMZ+gUuL6zoL+Hm6gP/8qQBG4jjimqdaNLCehcVapZ/Fs2WjCQ==
|
||||||
|
|
||||||
"@types/node@^10.12.18":
|
"@types/node@^10.12.18":
|
||||||
version "10.12.18"
|
version "10.12.18"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67"
|
||||||
@ -3575,6 +3638,11 @@ log-symbols@^2.0.0, log-symbols@^2.2.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
chalk "^2.0.1"
|
chalk "^2.0.1"
|
||||||
|
|
||||||
|
long@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
|
||||||
|
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
|
||||||
|
|
||||||
longest-streak@^2.0.1:
|
longest-streak@^2.0.1:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e"
|
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e"
|
||||||
@ -4480,6 +4548,20 @@ pkg-dir@^3.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
find-up "^3.0.0"
|
find-up "^3.0.0"
|
||||||
|
|
||||||
|
pogo-protos@^2.31.1:
|
||||||
|
version "2.31.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/pogo-protos/-/pogo-protos-2.31.1.tgz#5b389faba0ce2278771f04306af186d2c809a930"
|
||||||
|
integrity sha512-/iFoUWrewfBXLp6+7jzRCPSygMGVySiH9677q9AZRWK62xmBScVtEKohEtlVixTg7wX3xqGXsE1ZcNSuhk2NTQ==
|
||||||
|
dependencies:
|
||||||
|
protobufjs "^6.8.8"
|
||||||
|
|
||||||
|
pokemongo-game-master@^1.0.4:
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/pokemongo-game-master/-/pokemongo-game-master-1.0.4.tgz#b5edb22f4b317142fb4dea2ab5645f6af4712ccb"
|
||||||
|
integrity sha512-QyNx47mtVd0y/9FW25Gbrxt9HxwpBpVvdUWk+kljUO/+XXr6n9OVe3yu1RIqgKNG6QBAg+qFgi32kmQ1K+CE9w==
|
||||||
|
dependencies:
|
||||||
|
request "^2.83.0"
|
||||||
|
|
||||||
pokemongo-json-pokedex@^3.4.6:
|
pokemongo-json-pokedex@^3.4.6:
|
||||||
version "3.4.6"
|
version "3.4.6"
|
||||||
resolved "https://registry.yarnpkg.com/pokemongo-json-pokedex/-/pokemongo-json-pokedex-3.4.6.tgz#5d8ad17980cf4088fa573a18224131b65cd5d95b"
|
resolved "https://registry.yarnpkg.com/pokemongo-json-pokedex/-/pokemongo-json-pokedex-3.4.6.tgz#5d8ad17980cf4088fa573a18224131b65cd5d95b"
|
||||||
@ -4676,6 +4758,25 @@ prop-types@^15.6.2:
|
|||||||
loose-envify "^1.3.1"
|
loose-envify "^1.3.1"
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
|
|
||||||
|
protobufjs@^6.8.8:
|
||||||
|
version "6.8.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.8.8.tgz#c8b4f1282fd7a90e6f5b109ed11c84af82908e7c"
|
||||||
|
integrity sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==
|
||||||
|
dependencies:
|
||||||
|
"@protobufjs/aspromise" "^1.1.2"
|
||||||
|
"@protobufjs/base64" "^1.1.2"
|
||||||
|
"@protobufjs/codegen" "^2.0.4"
|
||||||
|
"@protobufjs/eventemitter" "^1.1.0"
|
||||||
|
"@protobufjs/fetch" "^1.1.0"
|
||||||
|
"@protobufjs/float" "^1.0.2"
|
||||||
|
"@protobufjs/inquire" "^1.1.0"
|
||||||
|
"@protobufjs/path" "^1.1.2"
|
||||||
|
"@protobufjs/pool" "^1.1.0"
|
||||||
|
"@protobufjs/utf8" "^1.1.0"
|
||||||
|
"@types/long" "^4.0.0"
|
||||||
|
"@types/node" "^10.1.0"
|
||||||
|
long "^4.0.0"
|
||||||
|
|
||||||
prr@~1.0.1:
|
prr@~1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
|
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
|
||||||
@ -5093,7 +5194,7 @@ replace-ext@1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
|
resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
|
||||||
integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=
|
integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=
|
||||||
|
|
||||||
request@^2.87.0, request@^2.88.0:
|
request@^2.83.0, request@^2.87.0, request@^2.88.0:
|
||||||
version "2.88.0"
|
version "2.88.0"
|
||||||
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
|
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -6457,6 +6558,11 @@ x-is-string@^0.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82"
|
resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82"
|
||||||
integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=
|
integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=
|
||||||
|
|
||||||
|
xhr2@^0.1.4:
|
||||||
|
version "0.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f"
|
||||||
|
integrity sha1-f4dliEdxbbUCYyOBL4GMras4el8=
|
||||||
|
|
||||||
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
|
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
|
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user