2019-01-19 23:43:36 -05:00

248 lines
10 KiB
TypeScript

import React from 'react';
import { Grade, ILeaguePokemon, IStats } from 'app/models/Pokemon';
import { calculateCp, calculateStatAtLevel } from 'app/utils/calculator';
import { IIndividualValues, IndividualValueKey } from './types';
import { LeagueStatsList } from './LeagueStatsList';
export interface IPokemonExplorerProps {
isLoading : boolean;
leaguePokemon : ILeaguePokemon;
individualValues : IIndividualValues;
handleChangeIndividualValue : (stat : IndividualValueKey, value : number | null) => void;
}
interface IState {
form : {
level : string;
};
}
export class PokemonExplorer extends React.Component<IPokemonExplorerProps, IState> {
private readonly MIN_LEVEL = 1;
private readonly MAX_LEVEL = 40;
private readonly MIN_IV = 0;
private readonly MAX_IV = 15;
private handleChangeHp : (event : React.ChangeEvent<HTMLInputElement>) => void;
private handleChangeAtk : (event : React.ChangeEvent<HTMLInputElement>) => void;
private handleChangeDef : (event : React.ChangeEvent<HTMLInputElement>) => void;
constructor(props : IPokemonExplorerProps) {
super(props);
this.state = {
form: {
level: '',
}
};
this.handleChangeHp = this.handleChangeIvFactory('hp');
this.handleChangeAtk = this.handleChangeIvFactory('atk');
this.handleChangeDef = this.handleChangeIvFactory('def');
}
public render() {
const {
individualValues,
leaguePokemon
} = this.props;
const league = 'great'; // TODO: this should be a prop
let rankedPokemon : IStats | null = null;
let placeholderLevel = '';
let placeholderHp = '';
let placeholderAtk = '';
let placeholderDef = '';
const individualValueLevel = this.state.form.level !== '' ? this.state.form.level : individualValues.level;
// default to first pokemon (should be S tier)
if (individualValueLevel === null &&
individualValues.hp === null &&
individualValues.atk === null &&
individualValues.def === null
) {
rankedPokemon = leaguePokemon.pvp[league][0];
placeholderLevel = '' + rankedPokemon.level;
placeholderHp = '' + rankedPokemon.ivHp;
placeholderAtk = '' + rankedPokemon.ivAtk;
placeholderDef = '' + rankedPokemon.ivDef;
// a full spec'd pokemon has been entered
} else if (individualValueLevel !== null && typeof individualValueLevel === 'number' &&
individualValues.hp !== null &&
individualValues.atk !== null &&
individualValues.def !== null
) {
leaguePokemon.pvp[league].some((stats) => {
if (individualValueLevel === stats.level &&
individualValues.hp === stats.ivHp &&
individualValues.atk === stats.ivAtk &&
individualValues.def === stats.ivDef
) {
rankedPokemon = stats;
return true;
}
return false;
});
// we don't have the data for this terrible mon
if (rankedPokemon === null) {
rankedPokemon = {
cp: calculateCp(leaguePokemon.stats, individualValueLevel, individualValues.hp, individualValues.atk, individualValues.def),
level: individualValueLevel,
ivHp: individualValues.hp,
ivAtk: individualValues.atk,
ivDef: individualValues.def,
hp: calculateStatAtLevel(individualValueLevel, leaguePokemon.stats.baseStamina, individualValues.hp),
atk: calculateStatAtLevel(individualValueLevel, leaguePokemon.stats.baseAttack, individualValues.atk),
def: calculateStatAtLevel(individualValueLevel, leaguePokemon.stats.baseDefense, individualValues.def),
total: 0,
speciesGrade: Grade.F,
metaGrade: Grade.F,
};
rankedPokemon.total = rankedPokemon.hp + rankedPokemon.atk + rankedPokemon.def;
}
}
const rankedGrade = rankedPokemon !== null ? Grade[rankedPokemon.speciesGrade] : '-';
const rankedCp = rankedPokemon !== null ? rankedPokemon.cp : '-';
const rankedHp = rankedPokemon !== null ? rankedPokemon.hp : '-';
const rankedAtk = rankedPokemon !== null ? rankedPokemon.atk : '-';
const rankedDef = rankedPokemon !== null ? rankedPokemon.def : '-';
return (
<div id="pokemon-explorer">
<h2 className="pokemon-info">
<span>{ this.formatDexNumber(leaguePokemon.dex) }</span>
{ leaguePokemon.name }
</h2>
<div className="pokemon-base-stats">
<div>Base Stats</div>
<div className="pokemon-type type-1">{ }</div>
<div className="pokemon-type type-2">{ }</div>
<div>{ leaguePokemon.stats.baseStamina }</div>
<div>{ leaguePokemon.stats.baseAttack }</div>
<div>{ leaguePokemon.stats.baseDefense }</div>
</div>
<div className="pokemon-individual-stats">
<div>
<h5>Level</h5>
<input
name="level"
type="number"
min={ this.MIN_LEVEL }
max={ this.MAX_LEVEL }
step={ 0.5 }
onChange={ this.handleChangeLevel }
value={ individualValueLevel !== null ? individualValueLevel : '' }
placeholder={ placeholderLevel }
/>
</div>
<div>
<h5>IVs</h5>
<label>
<input
name="hp"
type="number"
min={ this.MIN_IV }
max={ this.MAX_IV }
maxLength={ 2 }
onChange={ this.handleChangeHp }
value={ individualValues.hp !== null ? individualValues.hp : '' }
placeholder={ placeholderHp }
/> HP
</label>
<label>
<input
name="atk"
type="number"
min={ this.MIN_IV }
max={ this.MAX_IV }
maxLength={ 2 }
onChange={ this.handleChangeAtk }
value={ individualValues.atk !== null ? individualValues.atk : '' }
placeholder={ placeholderAtk }
/> ATK
</label>
<label>
<input
name="def"
type="number"
min={ this.MIN_IV }
max={ this.MAX_IV }
maxLength={ 2 }
onChange={ this.handleChangeDef }
value={ individualValues.def !== null ? individualValues.def : '' }
placeholder={ placeholderDef }
/> DEF
</label>
</div>
</div>
<div className="league-pokemon-rank">
<div className="league-pokemon-stat pokemon-rank"><span>{ rankedGrade }</span> Rank</div>
<div className="league-pokemon-stat pokemon-cp">CP <span>{ rankedCp }</span></div>
<div className="league-pokemon-stat"><span>{ rankedHp }</span> HP</div>
<div className="league-pokemon-stat"><span>{ rankedAtk }</span> ATK</div>
<div className="league-pokemon-stat"><span>{ rankedDef }</span> DEF</div>
</div>
<LeagueStatsList
activeIndividualValues={ individualValues }
leagueStatsList={ leaguePokemon.pvp[league] }
handleActivateLeagueStats={ this.handleActivateLeagueStats }
/>
</div>
);
}
private formatDexNumber(dex : number) {
let prefix : string = '#';
if (dex < 100) {
prefix += '0';
}
if (dex < 10) {
prefix += '0';
}
return prefix + dex;
}
private readonly handleChangeLevel = (event : React.ChangeEvent<HTMLInputElement>) => {
const raw = event.currentTarget.value;
const value = parseFloat(raw);
this.setState({ form: { level: '' } });
if (raw === '' + value && value >= this.MIN_LEVEL && value <= this.MAX_LEVEL && value % 0.5 === 0) {
this.props.handleChangeIndividualValue('level', value);
} else if (raw === '') {
this.props.handleChangeIndividualValue('level', null);
} else if (raw.charAt(raw.length) === '.') {
this.setState({ form: { level: raw } });
}
}
private readonly handleChangeIvFactory = (type : IndividualValueKey) => {
return (event : React.ChangeEvent<HTMLInputElement>) => {
const raw = event.currentTarget.value;
const value = parseInt(raw, 10);
if (raw === '' + value && value >= this.MIN_IV && value <= this.MAX_IV) {
this.props.handleChangeIndividualValue(type, value);
} else if (raw === '') {
this.props.handleChangeIndividualValue(type, null);
}
};
}
private readonly handleActivateLeagueStats = (stats : IStats) => {
const { handleChangeIndividualValue } = this.props;
handleChangeIndividualValue('level', stats.level);
handleChangeIndividualValue('hp', stats.ivHp);
handleChangeIndividualValue('atk', stats.ivAtk);
handleChangeIndividualValue('def', stats.ivDef);
}
}