add progress bars to base stats
This commit is contained in:
parent
e43c7edbf2
commit
2a12c1860e
@ -3,7 +3,7 @@ import PokemonDescription from 'pokemongo-json-pokedex/output/locales/en-US/poke
|
||||
import Pokemon from 'pokemongo-json-pokedex/output/pokemon.json';
|
||||
|
||||
import { LevelMultipliers } from 'app/models/LevelMultipliers';
|
||||
import { Grade, ILeaguePokemon, IPokemon, IStats, League, PokemonId, Type } from 'app/models/Pokemon';
|
||||
import { Grade, IBaseStatsRank, ILeaguePokemon, IMaxStats, IPokemon, IStats, League, PokemonId, Type } from 'app/models/Pokemon';
|
||||
|
||||
type ICpAndTotalFound = Record<number, Array<IStats>>;
|
||||
interface IStatsDistribution {
|
||||
@ -14,6 +14,10 @@ interface IMaxCpByLeague {
|
||||
great : number;
|
||||
ultra : number;
|
||||
}
|
||||
interface ICalculateRelativeStats {
|
||||
id : string;
|
||||
value : number;
|
||||
}
|
||||
|
||||
const outPath = './dist/db/';
|
||||
|
||||
@ -22,6 +26,17 @@ const maxCpByLeague : IMaxCpByLeague = {
|
||||
ultra: 2500
|
||||
};
|
||||
|
||||
const maxPossibleStats : IMaxStats = {
|
||||
baseStamina: 0,
|
||||
baseAttack: 0,
|
||||
baseDefense: 0,
|
||||
level: 40,
|
||||
};
|
||||
const pokemonOrderById : Record<string, IBaseStatsRank> = {};
|
||||
const pokemonBaseStamina : Array<ICalculateRelativeStats> = [];
|
||||
const pokemonBaseAttack : Array<ICalculateRelativeStats> = [];
|
||||
const pokemonBaseDefense : Array<ICalculateRelativeStats> = [];
|
||||
|
||||
const getClosestCpMultiplierIndex = (value : number) => {
|
||||
let i;
|
||||
for (i = 0; i < LevelMultipliers.length; i++) {
|
||||
@ -59,7 +74,50 @@ const parseNameAndForm = (monId : string, monName : string) => {
|
||||
name: monName,
|
||||
form: null,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Pokemon.forEach((mon) => {
|
||||
maxPossibleStats.baseStamina = Math.max(mon.stats.baseStamina, maxPossibleStats.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;
|
||||
@ -77,6 +135,7 @@ Pokemon.forEach((mon) => {
|
||||
type2: mon.types[1] ? mon.types[1].name.toLowerCase() as Type : null,
|
||||
},
|
||||
stats: mon.stats,
|
||||
statsRank: pokemonOrderById[mon.id],
|
||||
family: mon.family.id,
|
||||
pvp: {
|
||||
great: [],
|
||||
@ -136,17 +195,17 @@ Pokemon.forEach((mon) => {
|
||||
const maxCp = maxCpByLeague[league];
|
||||
const maxLeagueLevelMultiplierIndex = getClosestCpMultiplierIndex(Math.sqrt((maxCp * 10) / cpMultiplier));
|
||||
const maxLeagueLevelMultiplier = LevelMultipliers[maxLeagueLevelMultiplierIndex];
|
||||
const maxLeagueCp = ~~((cpMultiplier * Math.pow(maxLeagueLevelMultiplier, 2)) / 10);
|
||||
const maxLeagueCp = Math.floor((cpMultiplier * Math.pow(maxLeagueLevelMultiplier, 2)) / 10);
|
||||
const maxLeagueLevel = (maxLeagueLevelMultiplierIndex + 2) / 2;
|
||||
pokemonWithIvs = {
|
||||
cp: maxLeagueCp,
|
||||
level: maxLeagueLevel,
|
||||
ivHp: ivHp,
|
||||
ivAtk: ivAtk,
|
||||
ivDef: ivDef,
|
||||
hp: ~~((baseHp + ivHp) * maxLeagueLevelMultiplier),
|
||||
atk: ~~((baseAtk + ivAtk) * maxLeagueLevelMultiplier),
|
||||
def: ~~((baseDef + ivDef) * maxLeagueLevelMultiplier),
|
||||
ivHp,
|
||||
ivAtk,
|
||||
ivDef,
|
||||
hp: Math.floor((baseHp + ivHp) * maxLeagueLevelMultiplier),
|
||||
atk: Math.floor((baseAtk + ivAtk) * maxLeagueLevelMultiplier),
|
||||
def: Math.floor((baseDef + ivDef) * maxLeagueLevelMultiplier),
|
||||
total: 0,
|
||||
speciesGrade: Grade.F,
|
||||
metaGrade: Grade.F,
|
||||
@ -245,3 +304,13 @@ fs.mkdir(outPath, { recursive: true }, () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: add moves
|
||||
fs.mkdir(outPath, { recursive: true }, () => {
|
||||
fs.writeFile(outPath + 'config.json', JSON.stringify({ maxPossibleStats }), (err) => {
|
||||
if (err) {
|
||||
/* tslint:disable-next-line:no-console */
|
||||
return console.error('order', err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -44,39 +44,40 @@ $main-border-color: $gray-scale-4;
|
||||
|
||||
$main-hover-color: darken($main-background-color, 5%);
|
||||
|
||||
$normal-primary: #a8a77a;
|
||||
// https://bulbapedia.bulbagarden.net/wiki/Category:Type_color_templates
|
||||
$normal-primary: #a8a878;
|
||||
$normal-contrast: #fff;
|
||||
$fire-primary: #ee8130;
|
||||
$fire-primary: #f08030;
|
||||
$fire-contrast: #fff;
|
||||
$fighting-primary: #c22e28;
|
||||
$fighting-primary: #c03028;
|
||||
$fighting-contrast: #fff;
|
||||
$water-primary: #6390f0;
|
||||
$water-primary: #6890f0;
|
||||
$water-contrast: #fff;
|
||||
$flying-primary: #a98ff3;
|
||||
$flying-primary: #a890f0;
|
||||
$flying-contrast: #fff;
|
||||
$grass-primary: #7ac74c;
|
||||
$grass-primary: #78c850;
|
||||
$grass-contrast: #fff;
|
||||
$poison-primary: #a33ea1;
|
||||
$poison-primary: #a040a0;
|
||||
$poison-contrast: #fff;
|
||||
$electric-primary: #f7d02c;
|
||||
$electric-primary: #f8d030;
|
||||
$electric-contrast: #fff;
|
||||
$ground-primary: #e2bf65;
|
||||
$ground-primary: #e0c068;
|
||||
$ground-contrast: #fff;
|
||||
$psychic-primary: #f95587;
|
||||
$psychic-primary: #f85888;
|
||||
$psychic-contrast: #fff;
|
||||
$rock-primary: #b6a136;
|
||||
$rock-primary: #b8a038;
|
||||
$rock-contrast: #fff;
|
||||
$ice-primary: #96d9d6;
|
||||
$ice-primary: #98d8d8;
|
||||
$ice-contrast: #fff;
|
||||
$bug-primary: #a6b91a;
|
||||
$bug-primary: #a8b820;
|
||||
$bug-contrast: #fff;
|
||||
$dragon-primary: #6f35fc;
|
||||
$dragon-contrast: #fff;
|
||||
$ghost-primary: #735797;
|
||||
$ghost-primary: #705898;
|
||||
$ghost-contrast: #fff;
|
||||
$dark-primary: #705746;
|
||||
$dark-primary: #705848;
|
||||
$dark-contrast: #fff;
|
||||
$steel-primary: #b7b7ce;
|
||||
$steel-primary: #b8b8d0;
|
||||
$steel-contrast: #fff;
|
||||
$fairy-primary: #d685ad;
|
||||
$fairy-primary: #ee99ac;
|
||||
$fairy-contrast: #fff;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { AjaxUtils } from 'api/AjaxUtils';
|
||||
|
||||
import { IConfig } from 'app/models/Config';
|
||||
import { ILeaguePokemon, IPokemon, League } from 'app/models/Pokemon';
|
||||
|
||||
interface IPokemonJSON extends IPokemon {}
|
||||
@ -74,23 +75,28 @@ export class PokemonService implements IPokemonService {
|
||||
return pokemonLeagueStats;
|
||||
}
|
||||
|
||||
public getPokemonList() {
|
||||
public async getConfig() {
|
||||
const queryParameters = {
|
||||
};
|
||||
|
||||
return AjaxUtils.ajaxGet('/dist/db/order.json', queryParameters)
|
||||
.then((response : Array<IPokemonJSON>) => {
|
||||
return Promise.resolve(PokemonService.serializePokemonList(response));
|
||||
});
|
||||
const response : IConfig = await AjaxUtils.ajaxGet('/dist/db/config.json', queryParameters);
|
||||
// TODO: serialize this
|
||||
return response;
|
||||
}
|
||||
|
||||
public getPokemonLeagueStats(pokemonId : string) {
|
||||
public async getPokemonList() {
|
||||
const queryParameters = {
|
||||
};
|
||||
|
||||
return AjaxUtils.ajaxGet(`/dist/db/${ pokemonId }.json`, queryParameters)
|
||||
.then((response : ILeaguePokemonJSON) => {
|
||||
return Promise.resolve(PokemonService.serializePokemonLeagueStats(response));
|
||||
});
|
||||
const response : Array<IPokemonJSON> = await AjaxUtils.ajaxGet('/dist/db/order.json', queryParameters);
|
||||
return PokemonService.serializePokemonList(response);
|
||||
}
|
||||
|
||||
public async getPokemonLeagueStats(pokemonId : string) {
|
||||
const queryParameters = {
|
||||
};
|
||||
|
||||
const response : ILeaguePokemonJSON = await AjaxUtils.ajaxGet(`/dist/db/${ pokemonId }.json`, queryParameters);
|
||||
return PokemonService.serializePokemonLeagueStats(response);
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,9 +25,14 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps> {
|
||||
super(props);
|
||||
}
|
||||
|
||||
public componentWillMount() {
|
||||
this.props.dispatch(ActionsPokemonSelectList.fetchPokemonList())
|
||||
.then(() => this.props.dispatch(ActionsPokemonSelectList.setIsLoading(false)));
|
||||
public async componentWillMount() {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
await Promise.all([
|
||||
dispatch(ActionsPokemonExplorer.fetchConfig()),
|
||||
dispatch(ActionsPokemonSelectList.fetchPokemonList())
|
||||
]);
|
||||
dispatch(ActionsPokemonSelectList.setIsLoading(false));
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
||||
@ -2,7 +2,7 @@ import React from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { Grade, ILeaguePokemon, IStats } from 'app/models/Pokemon';
|
||||
import { Grade, ILeaguePokemon, IMaxStats, IStats, } from 'app/models/Pokemon';
|
||||
import { calculateCp, calculateStatAtLevel } from 'app/utils/calculator';
|
||||
import { formatDexNumber } from 'app/utils/formatter';
|
||||
|
||||
@ -182,6 +182,28 @@ export class PokemonExplorer extends React.Component<IPokemonExplorerProps, ISta
|
||||
}
|
||||
);
|
||||
|
||||
const progressStaminaCss = classNames('nes-progress', {
|
||||
'is-success': leaguePokemon.statsRank.staminaRank > 66,
|
||||
'is-warning': leaguePokemon.statsRank.staminaRank >= 34 && leaguePokemon.statsRank.staminaRank <= 66,
|
||||
'is-error': leaguePokemon.statsRank.staminaRank < 34,
|
||||
});
|
||||
|
||||
const progressAttackCss = classNames('nes-progress', {
|
||||
'is-success': leaguePokemon.statsRank.attackRank > 66,
|
||||
'is-warning': leaguePokemon.statsRank.attackRank >= 34 && leaguePokemon.statsRank.attackRank <= 66,
|
||||
'is-error': leaguePokemon.statsRank.attackRank < 34,
|
||||
});
|
||||
|
||||
const progressDefenseCss = classNames('nes-progress', {
|
||||
'is-success': leaguePokemon.statsRank.defenseRank > 66,
|
||||
'is-warning': leaguePokemon.statsRank.defenseRank >= 34 && leaguePokemon.statsRank.defenseRank <= 66,
|
||||
'is-error': leaguePokemon.statsRank.defenseRank < 34,
|
||||
});
|
||||
|
||||
const baseStamina : number = leaguePokemon.stats.baseStamina;
|
||||
const baseAttack : number = leaguePokemon.stats.baseAttack;
|
||||
const baseDefense : number = leaguePokemon.stats.baseDefense;
|
||||
|
||||
let type1 : JSX.Element | null = null;
|
||||
if (leaguePokemon.types.type1) {
|
||||
type1 = <div className={ `${pokemonType} ${leaguePokemon.types.type1}` }>{ leaguePokemon.types.type1 }</div>;
|
||||
@ -212,9 +234,39 @@ export class PokemonExplorer extends React.Component<IPokemonExplorerProps, ISta
|
||||
<h5>{ leaguePokemon.category }</h5>
|
||||
<section className={ baseStatsCss }>
|
||||
<h3 className={ containerTitleCss }>Base Stats</h3>
|
||||
<div>HP { leaguePokemon.stats.baseStamina }</div>
|
||||
<div>ATK { leaguePokemon.stats.baseAttack }</div>
|
||||
<div>DEF { leaguePokemon.stats.baseDefense }</div>
|
||||
<div className={ styles.baseStatRow }>
|
||||
<span>HP { baseStamina < 100 && String.fromCharCode(160) }{ baseStamina }</span>
|
||||
<progress
|
||||
className={ progressStaminaCss }
|
||||
max={ 100 }
|
||||
value={ leaguePokemon.statsRank.staminaRank }
|
||||
title={ `${leaguePokemon.statsRank.staminaRank}%` }
|
||||
>
|
||||
{ leaguePokemon.statsRank.staminaRank }%
|
||||
</progress>
|
||||
</div>
|
||||
<div className={ styles.baseStatRow }>
|
||||
<span>ATK { baseAttack < 100 && String.fromCharCode(160) }{ baseAttack }</span>
|
||||
<progress
|
||||
className={ progressAttackCss }
|
||||
max={ 100 }
|
||||
value={ leaguePokemon.statsRank.attackRank }
|
||||
title={ `${leaguePokemon.statsRank.attackRank}%` }
|
||||
>
|
||||
{ leaguePokemon.statsRank.attackRank }%
|
||||
</progress>
|
||||
</div>
|
||||
<div className={ styles.baseStatRow }>
|
||||
<span>DEF { baseDefense < 100 && String.fromCharCode(160) }{ baseDefense }</span>
|
||||
<progress
|
||||
className={ progressDefenseCss }
|
||||
max={ 100 }
|
||||
value={ leaguePokemon.statsRank.defenseRank }
|
||||
title={ `${leaguePokemon.statsRank.defenseRank}%` }
|
||||
>
|
||||
{ leaguePokemon.statsRank.defenseRank }%
|
||||
</progress>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -5,10 +5,12 @@ import { PokemonExplorerActionTypes } from './types';
|
||||
|
||||
import { calculateMaxLevelForLeague } from 'app/utils/calculator';
|
||||
|
||||
import { ILeaguePokemon } from 'app/models/Pokemon';
|
||||
import { ILeaguePokemon, IMaxStats } from 'app/models/Pokemon';
|
||||
|
||||
export const setIsLoading = (isLoading : boolean) => action(PokemonExplorerActionTypes.SET_IS_LOADING, { isLoading });
|
||||
|
||||
export const setMaxPossibleStats = (maxStats : IMaxStats) => action(PokemonExplorerActionTypes.SET_MAX_STATS, { maxStats });
|
||||
|
||||
export const setLeaguePokemon = (leaguePokemon : ILeaguePokemon | null) => action(PokemonExplorerActionTypes.SET_LEAGUE_POKEMON, { leaguePokemon });
|
||||
|
||||
export const setIvLevel = (level : number | null) => action(PokemonExplorerActionTypes.SET_IV_LEVEL, { level });
|
||||
@ -19,6 +21,14 @@ export const setIvAtk = (atk : number | null) => action(PokemonExplorerActionTyp
|
||||
|
||||
export const setIvDef = (def : number | null) => action(PokemonExplorerActionTypes.SET_IV_DEF, { def });
|
||||
|
||||
export const fetchConfig = (
|
||||
) : ThunkResult<Promise<void>> => {
|
||||
return async (dispatch, getState, extraArguments) => {
|
||||
const config = await extraArguments.services.pokemonService.getConfig();
|
||||
dispatch(setMaxPossibleStats(config.maxPossibleStats));
|
||||
};
|
||||
};
|
||||
|
||||
export const maximizeLevel = (
|
||||
) : ThunkResult<Promise<void>> => {
|
||||
return async (dispatch, getState, extraArguments) => {
|
||||
|
||||
@ -6,6 +6,12 @@ import { IPokemonExplorerState, PokemonExplorerActionTypes } from './types';
|
||||
export const initialState : IPokemonExplorerState = {
|
||||
isLoading: false,
|
||||
leaguePokemon: null,
|
||||
maxPossibleStats: {
|
||||
baseStamina: 0,
|
||||
baseAttack: 0,
|
||||
baseDefense: 0,
|
||||
level: 0,
|
||||
},
|
||||
individualValues: {
|
||||
level: null,
|
||||
hp: null,
|
||||
@ -23,6 +29,16 @@ const reduceSetIsLoading = (
|
||||
isLoading: action.payload.isLoading,
|
||||
});
|
||||
|
||||
const reduceSetMaxPossibleStats = (
|
||||
state : IPokemonExplorerState,
|
||||
action : ReturnType<typeof Actions.setMaxPossibleStats>
|
||||
) : IPokemonExplorerState => ({
|
||||
...state,
|
||||
maxPossibleStats: {
|
||||
...action.payload.maxStats,
|
||||
},
|
||||
});
|
||||
|
||||
const reduceSetLeaguePokemon = (
|
||||
state : IPokemonExplorerState,
|
||||
action : ReturnType<typeof Actions.setLeaguePokemon>
|
||||
@ -82,6 +98,8 @@ export const PokemonExplorerReducers : Reducer<IPokemonExplorerState> = (
|
||||
switch (action.type) {
|
||||
case PokemonExplorerActionTypes.SET_IS_LOADING:
|
||||
return reduceSetIsLoading(state, action as ReturnType<typeof Actions.setIsLoading>);
|
||||
case PokemonExplorerActionTypes.SET_MAX_STATS:
|
||||
return reduceSetMaxPossibleStats(state, action as ReturnType<typeof Actions.setMaxPossibleStats>);
|
||||
case PokemonExplorerActionTypes.SET_LEAGUE_POKEMON:
|
||||
return reduceSetLeaguePokemon(state, action as ReturnType<typeof Actions.setLeaguePokemon>);
|
||||
case PokemonExplorerActionTypes.SET_IV_LEVEL:
|
||||
|
||||
@ -235,6 +235,23 @@
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.baseStatRow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& > * {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
& > progress {
|
||||
flex-shrink: 1;
|
||||
margin-left: 1em;
|
||||
width: 5em;
|
||||
height: 0.5em;
|
||||
padding: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.popkemonIndividualStats {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
export const baseStatRow: string;
|
||||
export const dexHeader: string;
|
||||
export const fieldRow: string;
|
||||
export const formHeader: string;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ILeaguePokemon, League } from 'app/models/Pokemon';
|
||||
import { ILeaguePokemon, IMaxStats, League } from 'app/models/Pokemon';
|
||||
|
||||
export type IndividualValueKey = 'level' | 'hp' | 'atk' | 'def';
|
||||
export interface IIndividualValues {
|
||||
@ -11,12 +11,14 @@ export interface IIndividualValues {
|
||||
export interface IPokemonExplorerState {
|
||||
isLoading : boolean;
|
||||
leaguePokemon : ILeaguePokemon | null;
|
||||
maxPossibleStats : IMaxStats;
|
||||
individualValues : IIndividualValues;
|
||||
league : League;
|
||||
}
|
||||
|
||||
export const PokemonExplorerActionTypes = {
|
||||
SET_IS_LOADING: 'POKEMON_EXPLORER/SET_IS_LOADING',
|
||||
SET_MAX_STATS: 'POKEMON_EXPLORER/SET_MAX_STATS',
|
||||
SET_LEAGUE_POKEMON: 'POKEMON_EXPLORER/SET_LEAGUE_POKEMON',
|
||||
SET_IV_LEVEL: 'POKEMON_EXPLORER/SET_IV_LEVEL',
|
||||
SET_IV_HP: 'POKEMON_EXPLORER/SET_IV_HP',
|
||||
|
||||
5
src/ts/app/models/Config.ts
Normal file
5
src/ts/app/models/Config.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { IMaxStats } from 'app/models/Pokemon';
|
||||
|
||||
export interface IConfig {
|
||||
maxPossibleStats : IMaxStats;
|
||||
}
|
||||
@ -13,6 +13,16 @@ export interface IBaseStats {
|
||||
baseStamina : number;
|
||||
}
|
||||
|
||||
export interface IBaseStatsRank {
|
||||
attackRank : number;
|
||||
defenseRank : number;
|
||||
staminaRank : number;
|
||||
}
|
||||
|
||||
export interface IMaxStats extends IBaseStats {
|
||||
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 IPokemon {
|
||||
id : PokemonId;
|
||||
@ -26,6 +36,7 @@ export interface IPokemon {
|
||||
type2 : Type | null;
|
||||
};
|
||||
stats : IBaseStats;
|
||||
statsRank : IBaseStatsRank;
|
||||
}
|
||||
export type League = 'great' | 'ultra';
|
||||
export interface ILeaguePokemon extends IPokemon {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user