prepare for league switching
This commit is contained in:
parent
0abda4387f
commit
a639613694
@ -2,17 +2,16 @@ import * as fs from 'fs';
|
|||||||
import PokemonDescription from 'pokemongo-json-pokedex/output/locales/en-US/pokemon.json';
|
import PokemonDescription from 'pokemongo-json-pokedex/output/locales/en-US/pokemon.json';
|
||||||
import Pokemon from 'pokemongo-json-pokedex/output/pokemon.json';
|
import Pokemon from 'pokemongo-json-pokedex/output/pokemon.json';
|
||||||
|
|
||||||
|
import { ILeaguePokemon, IMaxCpByLeague, League, MaxCpByLeague } from 'app/models/League';
|
||||||
import { LevelMultipliers } from 'app/models/LevelMultipliers';
|
import { LevelMultipliers } from 'app/models/LevelMultipliers';
|
||||||
import { Grade, IBaseStatsRank, ILeaguePokemon, IMaxStats, IPokemon, IStats, League, PokemonId, Type } from 'app/models/Pokemon';
|
import { Grade, IBaseStatsRank, IMaxStats, IPokemon, IStats, PokemonId, Type } from 'app/models/Pokemon';
|
||||||
|
|
||||||
type ICpAndTotalFound = Record<number, Array<IStats>>;
|
type ICpAndTotalFound = Record<number, Array<IStats>>;
|
||||||
interface IStatsDistribution {
|
interface IStatsDistribution {
|
||||||
great : ICpAndTotalFound;
|
great : ICpAndTotalFound;
|
||||||
ultra : ICpAndTotalFound;
|
ultra : ICpAndTotalFound;
|
||||||
}
|
master : ICpAndTotalFound;
|
||||||
interface IMaxCpByLeague {
|
custom : ICpAndTotalFound;
|
||||||
great : number;
|
|
||||||
ultra : number;
|
|
||||||
}
|
}
|
||||||
interface ICalculateRelativeStats {
|
interface ICalculateRelativeStats {
|
||||||
id : string;
|
id : string;
|
||||||
@ -21,11 +20,6 @@ interface ICalculateRelativeStats {
|
|||||||
|
|
||||||
const outPath = './dist/db/';
|
const outPath = './dist/db/';
|
||||||
|
|
||||||
const maxCpByLeague : IMaxCpByLeague = {
|
|
||||||
great: 1500,
|
|
||||||
ultra: 2500
|
|
||||||
};
|
|
||||||
|
|
||||||
const maxPossibleStats : IMaxStats = {
|
const maxPossibleStats : IMaxStats = {
|
||||||
baseStamina: 0,
|
baseStamina: 0,
|
||||||
baseAttack: 0,
|
baseAttack: 0,
|
||||||
@ -140,6 +134,8 @@ Pokemon.forEach((mon) => {
|
|||||||
pvp: {
|
pvp: {
|
||||||
great: [],
|
great: [],
|
||||||
ultra: [],
|
ultra: [],
|
||||||
|
master: [],
|
||||||
|
custom: [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -183,6 +179,8 @@ Pokemon.forEach((mon) => {
|
|||||||
const combinedStatsDistribution : IStatsDistribution = {
|
const combinedStatsDistribution : IStatsDistribution = {
|
||||||
great: {},
|
great: {},
|
||||||
ultra: {},
|
ultra: {},
|
||||||
|
master: {},
|
||||||
|
custom: {},
|
||||||
};
|
};
|
||||||
for (let ivHp = 15; ivHp >= 0; ivHp--) {
|
for (let ivHp = 15; ivHp >= 0; ivHp--) {
|
||||||
for (let ivAtk = 15; ivAtk >= 0; ivAtk--) {
|
for (let ivAtk = 15; ivAtk >= 0; ivAtk--) {
|
||||||
@ -190,9 +188,9 @@ Pokemon.forEach((mon) => {
|
|||||||
let pokemonWithIvs : IStats;
|
let pokemonWithIvs : IStats;
|
||||||
const cpMultiplier = (baseAtk + ivAtk) * Math.sqrt(baseDef + ivDef) * Math.sqrt(baseHp + ivHp);
|
const cpMultiplier = (baseAtk + ivAtk) * Math.sqrt(baseDef + ivDef) * Math.sqrt(baseHp + ivHp);
|
||||||
|
|
||||||
Object.keys(maxCpByLeague).forEach((key) => {
|
Object.keys(MaxCpByLeague).forEach((key) => {
|
||||||
const league = key as League;
|
const league = key as League;
|
||||||
const maxCp = maxCpByLeague[league];
|
const maxCp = MaxCpByLeague[league];
|
||||||
const maxLeagueLevelMultiplierIndex = getClosestCpMultiplierIndex(Math.sqrt((maxCp * 10) / cpMultiplier));
|
const maxLeagueLevelMultiplierIndex = getClosestCpMultiplierIndex(Math.sqrt((maxCp * 10) / cpMultiplier));
|
||||||
const maxLeagueLevelMultiplier = LevelMultipliers[maxLeagueLevelMultiplierIndex];
|
const maxLeagueLevelMultiplier = LevelMultipliers[maxLeagueLevelMultiplierIndex];
|
||||||
const maxLeagueCp = Math.floor((cpMultiplier * Math.pow(maxLeagueLevelMultiplier, 2)) / 10);
|
const maxLeagueCp = Math.floor((cpMultiplier * Math.pow(maxLeagueLevelMultiplier, 2)) / 10);
|
||||||
|
|||||||
@ -46,40 +46,124 @@ $main-border-color: $gray-scale-4;
|
|||||||
|
|
||||||
$main-hover-color: darken($main-background-color, 5%);
|
$main-hover-color: darken($main-background-color, 5%);
|
||||||
|
|
||||||
|
$great-league-color: #4d6ed0;
|
||||||
|
$ultra-league-color: #5e30a3;
|
||||||
|
$master-league-color: #475b5e;
|
||||||
|
$custom-league-color: #f00;
|
||||||
|
$league-colors: (
|
||||||
|
great: (
|
||||||
|
primary: $great-league-color,
|
||||||
|
border: $nes-dark,
|
||||||
|
hover: lighten($great-league-color, 10),
|
||||||
|
// active: #355aca,
|
||||||
|
blur: lighten($great-league-color, 30),
|
||||||
|
blur-border: lighten($nes-dark, 10),
|
||||||
|
shadow: #1a3ea7,
|
||||||
|
contrast: #fff
|
||||||
|
),
|
||||||
|
ultra: (
|
||||||
|
primary: $ultra-league-color,
|
||||||
|
border: $nes-dark,
|
||||||
|
hover: lighten($ultra-league-color, 10),
|
||||||
|
// active: #50298b,
|
||||||
|
blur: lighten($ultra-league-color, 30),
|
||||||
|
blur-border: lighten($nes-dark, 10),
|
||||||
|
shadow: #342085,
|
||||||
|
contrast: #fff
|
||||||
|
),
|
||||||
|
master: (
|
||||||
|
primary: $master-league-color,
|
||||||
|
border: $nes-dark,
|
||||||
|
hover: lighten($master-league-color, 10),
|
||||||
|
// active: #3a4a4d,
|
||||||
|
blur: lighten($master-league-color, 30),
|
||||||
|
blur-border: lighten($nes-dark, 10),
|
||||||
|
shadow: #2f4947,
|
||||||
|
contrast: #fff
|
||||||
|
),
|
||||||
|
custom: (
|
||||||
|
primary: $custom-league-color,
|
||||||
|
border: $nes-dark,
|
||||||
|
hover: lighten($custom-league-color, 10),
|
||||||
|
blur: lighten($custom-league-color, 30),
|
||||||
|
blur-border: lighten($nes-dark, 10),
|
||||||
|
shadow: darkred,
|
||||||
|
contrast: #fff
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// https://bulbapedia.bulbagarden.net/wiki/Category:Type_color_templates
|
// https://bulbapedia.bulbagarden.net/wiki/Category:Type_color_templates
|
||||||
$normal-primary: #a8a878;
|
$type-colors: (
|
||||||
$normal-contrast: #fff;
|
normal: (
|
||||||
$fire-primary: #f08030;
|
primary: #a8a878,
|
||||||
$fire-contrast: #fff;
|
contrast: #fff
|
||||||
$fighting-primary: #c03028;
|
),
|
||||||
$fighting-contrast: #fff;
|
fire: (
|
||||||
$water-primary: #6890f0;
|
primary: #f08030,
|
||||||
$water-contrast: #fff;
|
contrast: #fff
|
||||||
$flying-primary: #a890f0;
|
),
|
||||||
$flying-contrast: #fff;
|
fighting: (
|
||||||
$grass-primary: #78c850;
|
primary: #c03028,
|
||||||
$grass-contrast: #fff;
|
contrast: #fff
|
||||||
$poison-primary: #a040a0;
|
),
|
||||||
$poison-contrast: #fff;
|
water: (
|
||||||
$electric-primary: #f8d030;
|
primary: #6890f0,
|
||||||
$electric-contrast: #fff;
|
contrast: #fff
|
||||||
$ground-primary: #e0c068;
|
),
|
||||||
$ground-contrast: #fff;
|
flying: (
|
||||||
$psychic-primary: #f85888;
|
primary: #a890f0,
|
||||||
$psychic-contrast: #fff;
|
contrast: #fff
|
||||||
$rock-primary: #b8a038;
|
),
|
||||||
$rock-contrast: #fff;
|
grass: (
|
||||||
$ice-primary: #98d8d8;
|
primary: #78c850,
|
||||||
$ice-contrast: #fff;
|
contrast: #fff
|
||||||
$bug-primary: #a8b820;
|
),
|
||||||
$bug-contrast: #fff;
|
poison: (
|
||||||
$dragon-primary: #6f35fc;
|
primary: #a040a0,
|
||||||
$dragon-contrast: #fff;
|
contrast: #fff
|
||||||
$ghost-primary: #705898;
|
),
|
||||||
$ghost-contrast: #fff;
|
electric: (
|
||||||
$dark-primary: #705848;
|
primary: #f8d030,
|
||||||
$dark-contrast: #fff;
|
contrast: #fff
|
||||||
$steel-primary: #b8b8d0;
|
),
|
||||||
$steel-contrast: #fff;
|
ground: (
|
||||||
$fairy-primary: #ee99ac;
|
primary: #e0c068,
|
||||||
$fairy-contrast: #fff;
|
contrast: #fff
|
||||||
|
),
|
||||||
|
psychic: (
|
||||||
|
primary: #f85888,
|
||||||
|
contrast: #fff
|
||||||
|
),
|
||||||
|
rock: (
|
||||||
|
primary: #b8a038,
|
||||||
|
contrast: #fff
|
||||||
|
),
|
||||||
|
ice: (
|
||||||
|
primary: #98d8d8,
|
||||||
|
contrast: #fff
|
||||||
|
),
|
||||||
|
bug: (
|
||||||
|
primary: #a8b820,
|
||||||
|
contrast: #fff
|
||||||
|
),
|
||||||
|
dragon: (
|
||||||
|
primary: #6f35fc,
|
||||||
|
contrast: #fff
|
||||||
|
),
|
||||||
|
ghost: (
|
||||||
|
primary: #705898,
|
||||||
|
contrast: #fff
|
||||||
|
),
|
||||||
|
dark: (
|
||||||
|
primary: #705848,
|
||||||
|
contrast: #fff
|
||||||
|
),
|
||||||
|
steel: (
|
||||||
|
primary: #b8b8d0,
|
||||||
|
contrast: #fff
|
||||||
|
),
|
||||||
|
fairy: (
|
||||||
|
primary: #ee99ac,
|
||||||
|
contrast: #fff
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { AjaxUtils } from 'api/AjaxUtils';
|
import { AjaxUtils } from 'api/AjaxUtils';
|
||||||
|
|
||||||
import { IConfig } from 'app/models/Config';
|
import { IConfig } from 'app/models/Config';
|
||||||
import { ILeaguePokemon, IPokemon, League } from 'app/models/Pokemon';
|
import { ILeaguePokemon, League } from 'app/models/League';
|
||||||
|
import { IPokemon } from 'app/models/Pokemon';
|
||||||
|
|
||||||
interface IPokemonJSON extends IPokemon {}
|
interface IPokemonJSON extends IPokemon {}
|
||||||
interface ILeaguePokemonJSON extends ILeaguePokemon {}
|
interface ILeaguePokemonJSON extends ILeaguePokemon {}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import { League } from 'app/models/League';
|
||||||
|
|
||||||
import { appReducers } from './index';
|
import { appReducers } from './index';
|
||||||
|
|
||||||
import * as ActionsPokemonExplorer from './components/PokemonExplorer/actions';
|
import * as ActionsPokemonExplorer from './components/PokemonExplorer/actions';
|
||||||
@ -43,6 +45,7 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps> {
|
|||||||
filterTerm,
|
filterTerm,
|
||||||
} = this.props.pokemonSelectListState;
|
} = this.props.pokemonSelectListState;
|
||||||
const {
|
const {
|
||||||
|
league,
|
||||||
individualValues,
|
individualValues,
|
||||||
leaguePokemon,
|
leaguePokemon,
|
||||||
} = this.props.pokemonExplorerState;
|
} = this.props.pokemonExplorerState;
|
||||||
@ -60,10 +63,12 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps> {
|
|||||||
{ leaguePokemon !== null &&
|
{ leaguePokemon !== null &&
|
||||||
<PokemonExplorer
|
<PokemonExplorer
|
||||||
isLoading={ this.props.pokemonExplorerState.isLoading }
|
isLoading={ this.props.pokemonExplorerState.isLoading }
|
||||||
|
activeLeague={ league }
|
||||||
leaguePokemon={ leaguePokemon }
|
leaguePokemon={ leaguePokemon }
|
||||||
individualValues={ individualValues }
|
individualValues={ individualValues }
|
||||||
handleChangeIndividualValue={ this.handleChangeIndividualValue }
|
handleChangeIndividualValue={ this.handleChangeIndividualValue }
|
||||||
handleMaximizeLevel={ this.handleMaximizeLevel }
|
handleMaximizeLevel={ this.handleMaximizeLevel }
|
||||||
|
handleChangeLeague={ this.handleChangeLeague }
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@ -118,6 +123,10 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps> {
|
|||||||
private readonly handleMaximizeLevel = () => {
|
private readonly handleMaximizeLevel = () => {
|
||||||
this.props.dispatch(ActionsPokemonExplorer.maximizeLevel());
|
this.props.dispatch(ActionsPokemonExplorer.maximizeLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly handleChangeLeague = (league : League) => {
|
||||||
|
this.props.dispatch(ActionsPokemonExplorer.setActiveLeague(league));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state : ReturnType<typeof appReducers>) : PokemonAppProps => {
|
const mapStateToProps = (state : ReturnType<typeof appReducers>) : PokemonAppProps => {
|
||||||
|
|||||||
54
src/ts/app/components/PokemonExplorer/LeagueSelector.tsx
Normal file
54
src/ts/app/components/PokemonExplorer/LeagueSelector.tsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { League, LeagueLabels } from 'app/models/League';
|
||||||
|
|
||||||
|
import * as styles from './styles/LeagueSelector.scss';
|
||||||
|
|
||||||
|
export interface ILeagueSelectorProps {
|
||||||
|
activeLeague : League;
|
||||||
|
handleLeagueSelect : (league : League) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LeagueSelector extends React.Component<ILeagueSelectorProps, object> {
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const { activeLeague } = this.props;
|
||||||
|
|
||||||
|
const css = classNames(
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={ styles.wrapper }>
|
||||||
|
{
|
||||||
|
LeagueLabels.map((league, index) => {
|
||||||
|
const buttonCss = classNames(
|
||||||
|
'nes-btn',
|
||||||
|
{
|
||||||
|
[ styles.greatLeagueButton ]: league.id === 'great',
|
||||||
|
[ styles.ultraLeagueButton ]: league.id === 'ultra',
|
||||||
|
[ styles.masterLeagueButton ]: league.id === 'master',
|
||||||
|
[ styles.customLeagueButton ]: league.id === 'custom',
|
||||||
|
[ styles.active ]: activeLeague === league.id,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return <button
|
||||||
|
key={ league.id + index }
|
||||||
|
className={ buttonCss }
|
||||||
|
onClick={ this.handleLeagueSelectFactory(league.id) }
|
||||||
|
>
|
||||||
|
{ league.label }
|
||||||
|
</button>;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly handleLeagueSelectFactory = (league : League) => {
|
||||||
|
return () => {
|
||||||
|
this.props.handleLeagueSelect(league);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,12 +2,14 @@ import React from 'react';
|
|||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { Grade, ILeaguePokemon, IMaxStats, IStats, } from 'app/models/Pokemon';
|
import { ILeaguePokemon, League } from 'app/models/League';
|
||||||
|
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 { formatDexNumber } from 'app/utils/formatter';
|
||||||
|
|
||||||
import { IIndividualValues, IndividualValueKey } from './types';
|
import { IIndividualValues, IndividualValueKey } from './types';
|
||||||
|
|
||||||
|
import { LeagueSelector } from './LeagueSelector';
|
||||||
import { LeagueStatsList } from './LeagueStatsList';
|
import { LeagueStatsList } from './LeagueStatsList';
|
||||||
import { StatDisplay } from './StatDisplay';
|
import { StatDisplay } from './StatDisplay';
|
||||||
|
|
||||||
@ -15,11 +17,13 @@ import * as styles from './styles/PokemonExplorer.scss';
|
|||||||
|
|
||||||
export interface IPokemonExplorerProps {
|
export interface IPokemonExplorerProps {
|
||||||
isLoading : boolean;
|
isLoading : boolean;
|
||||||
|
activeLeague : League;
|
||||||
leaguePokemon : ILeaguePokemon;
|
leaguePokemon : ILeaguePokemon;
|
||||||
individualValues : IIndividualValues;
|
individualValues : IIndividualValues;
|
||||||
|
|
||||||
handleChangeIndividualValue : (stat : IndividualValueKey, value : number | null) => void;
|
handleChangeIndividualValue : (stat : IndividualValueKey, value : number | null) => void;
|
||||||
handleMaximizeLevel : () => void;
|
handleMaximizeLevel : () => void;
|
||||||
|
handleChangeLeague : (league : League) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
@ -54,6 +58,7 @@ export class PokemonExplorer extends React.Component<IPokemonExplorerProps, ISta
|
|||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const {
|
const {
|
||||||
|
activeLeague,
|
||||||
individualValues,
|
individualValues,
|
||||||
leaguePokemon
|
leaguePokemon
|
||||||
} = this.props;
|
} = this.props;
|
||||||
@ -236,6 +241,10 @@ export class PokemonExplorer extends React.Component<IPokemonExplorerProps, ISta
|
|||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<LeagueSelector
|
||||||
|
activeLeague={ activeLeague }
|
||||||
|
handleLeagueSelect={ this.handleLeagueSelect }
|
||||||
|
/>
|
||||||
<section className={ formContainerCss }>
|
<section className={ formContainerCss }>
|
||||||
<h5 className={ containerTitleCss }>IVs</h5>
|
<h5 className={ containerTitleCss }>IVs</h5>
|
||||||
<div className={ inlineFieldCss }>
|
<div className={ inlineFieldCss }>
|
||||||
@ -379,4 +388,8 @@ export class PokemonExplorer extends React.Component<IPokemonExplorerProps, ISta
|
|||||||
handleChangeIndividualValue('atk', stats.ivAtk);
|
handleChangeIndividualValue('atk', stats.ivAtk);
|
||||||
handleChangeIndividualValue('def', stats.ivDef);
|
handleChangeIndividualValue('def', stats.ivDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly handleLeagueSelect = (league : League) => {
|
||||||
|
this.props.handleChangeLeague(league);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import * as styles from './styles/PokemonExplorer.scss';
|
import * as styles from './styles/StatDisplay.scss';
|
||||||
|
|
||||||
export interface IStartDisplayProps {
|
export interface IStartDisplayProps {
|
||||||
statLabel : string;
|
statLabel : string;
|
||||||
|
|||||||
@ -5,7 +5,8 @@ import { PokemonExplorerActionTypes } from './types';
|
|||||||
|
|
||||||
import { calculateMaxLevelForLeague } from 'app/utils/calculator';
|
import { calculateMaxLevelForLeague } from 'app/utils/calculator';
|
||||||
|
|
||||||
import { ILeaguePokemon, IMaxStats } from 'app/models/Pokemon';
|
import { ILeaguePokemon, League } from 'app/models/League';
|
||||||
|
import { IMaxStats } from 'app/models/Pokemon';
|
||||||
|
|
||||||
export const setIsLoading = (isLoading : boolean) => action(PokemonExplorerActionTypes.SET_IS_LOADING, { isLoading });
|
export const setIsLoading = (isLoading : boolean) => action(PokemonExplorerActionTypes.SET_IS_LOADING, { isLoading });
|
||||||
|
|
||||||
@ -21,6 +22,8 @@ export const setIvAtk = (atk : number | null) => action(PokemonExplorerActionTyp
|
|||||||
|
|
||||||
export const setIvDef = (def : number | null) => action(PokemonExplorerActionTypes.SET_IV_DEF, { def });
|
export const setIvDef = (def : number | null) => action(PokemonExplorerActionTypes.SET_IV_DEF, { def });
|
||||||
|
|
||||||
|
export const setActiveLeague = (league : League) => action(PokemonExplorerActionTypes.SET_ACTIVE_LEAGUE, { league });
|
||||||
|
|
||||||
export const fetchConfig = (
|
export const fetchConfig = (
|
||||||
) : ThunkResult<Promise<void>> => {
|
) : ThunkResult<Promise<void>> => {
|
||||||
return async (dispatch, getState, extraArguments) => {
|
return async (dispatch, getState, extraArguments) => {
|
||||||
|
|||||||
@ -91,6 +91,14 @@ const reduceSetIvDef = (
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const reduceSetActiveLeague = (
|
||||||
|
state : IPokemonExplorerState,
|
||||||
|
action : ReturnType<typeof Actions.setActiveLeague>
|
||||||
|
) : IPokemonExplorerState => ({
|
||||||
|
...state,
|
||||||
|
league: action.payload.league
|
||||||
|
});
|
||||||
|
|
||||||
export const PokemonExplorerReducers : Reducer<IPokemonExplorerState> = (
|
export const PokemonExplorerReducers : Reducer<IPokemonExplorerState> = (
|
||||||
state : IPokemonExplorerState = initialState,
|
state : IPokemonExplorerState = initialState,
|
||||||
action,
|
action,
|
||||||
@ -110,6 +118,8 @@ export const PokemonExplorerReducers : Reducer<IPokemonExplorerState> = (
|
|||||||
return reduceSetIvAtk(state, action as ReturnType<typeof Actions.setIvAtk>);
|
return reduceSetIvAtk(state, action as ReturnType<typeof Actions.setIvAtk>);
|
||||||
case PokemonExplorerActionTypes.SET_IV_DEF:
|
case PokemonExplorerActionTypes.SET_IV_DEF:
|
||||||
return reduceSetIvDef(state, action as ReturnType<typeof Actions.setIvDef>);
|
return reduceSetIvDef(state, action as ReturnType<typeof Actions.setIvDef>);
|
||||||
|
case PokemonExplorerActionTypes.SET_ACTIVE_LEAGUE:
|
||||||
|
return reduceSetActiveLeague(state, action as ReturnType<typeof Actions.setActiveLeague>);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,76 @@
|
|||||||
|
@import 'styles/Variables.scss';
|
||||||
|
|
||||||
|
@each $league, $colors in $league-colors {
|
||||||
|
$blur: map-get($colors, 'blur');
|
||||||
|
$hover: map-get($colors, 'hover');
|
||||||
|
$primary: map-get($colors, 'primary');
|
||||||
|
$shadow: map-get($colors, 'shadow');
|
||||||
|
$border: map-get($colors, 'border');
|
||||||
|
$blur-border: map-get($colors, 'blur-border');
|
||||||
|
$contrast: map-get($colors, 'contrast');
|
||||||
|
|
||||||
|
:global(.nes-btn).#{$league}LeagueButton {
|
||||||
|
color: $contrast;
|
||||||
|
background-color: $blur;
|
||||||
|
box-shadow: none;
|
||||||
|
// box-shadow: inset -4px -4px darken(saturate(adjust-hue($primary, -12deg), 7), 9);
|
||||||
|
// box-shadow: inset -4px -4px darken(saturate($primary, 14), 18);
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
border-color: $blur-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background-color: $hover;
|
||||||
|
box-shadow: inset -4px -4px $shadow;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
box-shadow: inset 4px 4px $shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
border-color: $border;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: $primary;
|
||||||
|
box-shadow: inset -4px -4px $shadow;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
box-shadow: inset -6px -6px $shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
box-shadow: inset 4px 4px $shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
border-color: $border;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: above won't generate an scss file automatically...
|
||||||
|
|
||||||
|
/* stylelint-disable block-no-empty */
|
||||||
|
.greatLeagueButton,
|
||||||
|
.ultraLeagueButton,
|
||||||
|
.masterLeagueButton,
|
||||||
|
.customLeagueButton {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
/* stylelint-enable block-no-empty */
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
font-size: 0.8em;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
8
src/ts/app/components/PokemonExplorer/styles/LeagueSelector.scss.d.ts
vendored
Normal file
8
src/ts/app/components/PokemonExplorer/styles/LeagueSelector.scss.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// This file is automatically generated.
|
||||||
|
// Please do not change this file!
|
||||||
|
export const active: string;
|
||||||
|
export const customLeagueButton: string;
|
||||||
|
export const greatLeagueButton: string;
|
||||||
|
export const masterLeagueButton: string;
|
||||||
|
export const ultraLeagueButton: string;
|
||||||
|
export const wrapper: string;
|
||||||
@ -76,166 +76,18 @@
|
|||||||
box-shadow: 0 -4px $shadow-color, 0 -8px, 4px 0 $shadow-color, 4px -4px, 8px 0, 0 4px $shadow-color, 0 8px, -4px 0 $shadow-color, -4px 4px, -8px 0, -4px -4px, 4px 4px;
|
box-shadow: 0 -4px $shadow-color, 0 -8px, 4px 0 $shadow-color, 4px -4px, 8px 0, 0 4px $shadow-color, 0 8px, -4px 0 $shadow-color, -4px 4px, -8px 0, -4px -4px, 4px 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:global(.normal) {
|
@each $type, $colors in $type-colors {
|
||||||
color: $normal-contrast;
|
$primary: map-get($colors, 'primary');
|
||||||
background-color: $normal-primary;
|
$contrast: map-get($colors, 'contrast');
|
||||||
|
|
||||||
|
&:global(.#{$type}) {
|
||||||
|
color: $contrast;
|
||||||
|
background-color: $primary;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
@include rounded-box-shadow($normal-primary);
|
@include rounded-box-shadow($primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:global(.fire) {
|
|
||||||
color: $fire-contrast;
|
|
||||||
background-color: $fire-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($fire-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.fighting) {
|
|
||||||
color: $fighting-contrast;
|
|
||||||
background-color: $fighting-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($fighting-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.water) {
|
|
||||||
color: $water-contrast;
|
|
||||||
background-color: $water-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($water-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.flying) {
|
|
||||||
color: $flying-contrast;
|
|
||||||
background-color: $flying-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($flying-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.grass) {
|
|
||||||
color: $grass-contrast;
|
|
||||||
background-color: $grass-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($grass-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.poison) {
|
|
||||||
color: $poison-contrast;
|
|
||||||
background-color: $poison-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($poison-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.electric) {
|
|
||||||
color: $electric-contrast;
|
|
||||||
background-color: $electric-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($electric-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.ground) {
|
|
||||||
color: $ground-contrast;
|
|
||||||
background-color: $ground-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($ground-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.psychic) {
|
|
||||||
color: $psychic-contrast;
|
|
||||||
background-color: $psychic-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($psychic-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.rock) {
|
|
||||||
color: $rock-contrast;
|
|
||||||
background-color: $rock-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($rock-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.ice) {
|
|
||||||
color: $ice-contrast;
|
|
||||||
background-color: $ice-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($ice-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.bug) {
|
|
||||||
color: $bug-contrast;
|
|
||||||
background-color: $bug-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($bug-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.dragon) {
|
|
||||||
color: $dragon-contrast;
|
|
||||||
background-color: $dragon-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($dragon-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.ghost) {
|
|
||||||
color: $ghost-contrast;
|
|
||||||
background-color: $ghost-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($ghost-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.dark) {
|
|
||||||
color: $dark-contrast;
|
|
||||||
background-color: $dark-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($dark-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.steel) {
|
|
||||||
color: $steel-contrast;
|
|
||||||
background-color: $steel-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($steel-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.fairy) {
|
|
||||||
color: $fairy-contrast;
|
|
||||||
background-color: $fairy-primary;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
@include rounded-box-shadow($fairy-primary);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,23 +106,6 @@
|
|||||||
align-self: stretch;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.nes-field.is-inline) .ivInput {
|
:global(.nes-field.is-inline) .ivInput {
|
||||||
width: 4.25em;
|
width: 4.25em;
|
||||||
padding-left: 0.7em;
|
padding-left: 0.7em;
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
// This file is automatically generated.
|
// This file is automatically generated.
|
||||||
// Please do not change this file!
|
// Please do not change this file!
|
||||||
export const baseStatRow: string;
|
|
||||||
export const dexHeader: string;
|
export const dexHeader: string;
|
||||||
export const fieldRow: string;
|
export const fieldRow: string;
|
||||||
export const formHeader: string;
|
export const formHeader: string;
|
||||||
|
|||||||
@ -0,0 +1,16 @@
|
|||||||
|
.baseStatRow {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > progress {
|
||||||
|
flex-shrink: 1;
|
||||||
|
margin-left: 1em;
|
||||||
|
width: 5em;
|
||||||
|
height: 0.5em;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
3
src/ts/app/components/PokemonExplorer/styles/StatDisplay.scss.d.ts
vendored
Normal file
3
src/ts/app/components/PokemonExplorer/styles/StatDisplay.scss.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// This file is automatically generated.
|
||||||
|
// Please do not change this file!
|
||||||
|
export const baseStatRow: string;
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import { ILeaguePokemon, IMaxStats, League } from 'app/models/Pokemon';
|
import { ILeaguePokemon, League } from 'app/models/League';
|
||||||
|
import { IMaxStats } from 'app/models/Pokemon';
|
||||||
|
|
||||||
export type IndividualValueKey = 'level' | 'hp' | 'atk' | 'def';
|
export type IndividualValueKey = 'level' | 'hp' | 'atk' | 'def';
|
||||||
export interface IIndividualValues {
|
export interface IIndividualValues {
|
||||||
@ -24,4 +25,5 @@ export const PokemonExplorerActionTypes = {
|
|||||||
SET_IV_HP: 'POKEMON_EXPLORER/SET_IV_HP',
|
SET_IV_HP: 'POKEMON_EXPLORER/SET_IV_HP',
|
||||||
SET_IV_ATK: 'POKEMON_EXPLORER/SET_IV_ATK',
|
SET_IV_ATK: 'POKEMON_EXPLORER/SET_IV_ATK',
|
||||||
SET_IV_DEF: 'POKEMON_EXPLORER/SET_IV_DEF',
|
SET_IV_DEF: 'POKEMON_EXPLORER/SET_IV_DEF',
|
||||||
|
SET_ACTIVE_LEAGUE: 'POKEMON_EXPLORER/SET_ACTIVE_LEAGUE',
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { action } from 'typesafe-actions';
|
import { action } from 'typesafe-actions';
|
||||||
|
|
||||||
import { ILeaguePokemon, IPokemon } from 'app/models/Pokemon';
|
import { ILeaguePokemon } from 'app/models/League';
|
||||||
|
import { IPokemon } from 'app/models/Pokemon';
|
||||||
|
|
||||||
import { ThunkResult } from 'app/types';
|
import { ThunkResult } from 'app/types';
|
||||||
import { PokemonSelectListActionTypes } from './types';
|
import { PokemonSelectListActionTypes } from './types';
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { ILeaguePokemon, IPokemon } from 'app/models/Pokemon';
|
import { ILeaguePokemon } from 'app/models/League';
|
||||||
|
import { IPokemon } from 'app/models/Pokemon';
|
||||||
|
|
||||||
export interface IPokemonSelectListState {
|
export interface IPokemonSelectListState {
|
||||||
isLoading : boolean;
|
isLoading : boolean;
|
||||||
|
|||||||
40
src/ts/app/models/League.ts
Normal file
40
src/ts/app/models/League.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { IPokemon, IStats } from './Pokemon';
|
||||||
|
|
||||||
|
export type League = 'great' | 'ultra' | 'master' | 'custom';
|
||||||
|
|
||||||
|
export interface IMaxCpByLeague {
|
||||||
|
great : number;
|
||||||
|
ultra : number;
|
||||||
|
master : number;
|
||||||
|
custom : number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MaxCpByLeague : IMaxCpByLeague = {
|
||||||
|
great: 1500,
|
||||||
|
ultra: 2500,
|
||||||
|
master: Infinity,
|
||||||
|
custom: Infinity,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LeagueLabels : Array<{ id : League, label : string }> = [{
|
||||||
|
id: 'great',
|
||||||
|
label: 'Great'
|
||||||
|
}, {
|
||||||
|
id: 'ultra',
|
||||||
|
label: 'Ultra'
|
||||||
|
}, {
|
||||||
|
id: 'master',
|
||||||
|
label: 'Master'
|
||||||
|
}, {
|
||||||
|
id: 'custom',
|
||||||
|
label: 'Custom'
|
||||||
|
}];
|
||||||
|
|
||||||
|
export interface ILeaguePokemon extends IPokemon {
|
||||||
|
pvp : {
|
||||||
|
great : Array<IStats>;
|
||||||
|
ultra : Array<IStats>;
|
||||||
|
master : Array<IStats>;
|
||||||
|
custom : Array<IStats>;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -38,13 +38,6 @@ export interface IPokemon {
|
|||||||
stats : IBaseStats;
|
stats : IBaseStats;
|
||||||
statsRank : IBaseStatsRank;
|
statsRank : IBaseStatsRank;
|
||||||
}
|
}
|
||||||
export type League = 'great' | 'ultra';
|
|
||||||
export interface ILeaguePokemon extends IPokemon {
|
|
||||||
pvp : {
|
|
||||||
great : Array<IStats>;
|
|
||||||
ultra : Array<IStats>;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IStats {
|
export interface IStats {
|
||||||
cp : number;
|
cp : number;
|
||||||
|
|||||||
@ -1,10 +1,6 @@
|
|||||||
|
import { League, MaxCpByLeague } from 'app/models/League';
|
||||||
import { LevelMultipliers } from 'app/models/LevelMultipliers';
|
import { LevelMultipliers } from 'app/models/LevelMultipliers';
|
||||||
import { IBaseStats, League } from 'app/models/Pokemon';
|
import { IBaseStats } from 'app/models/Pokemon';
|
||||||
|
|
||||||
const leagueMaxCp = {
|
|
||||||
great: 1500,
|
|
||||||
ultra: 1500
|
|
||||||
};
|
|
||||||
|
|
||||||
const calculateStatsFormula = (baseStats : IBaseStats, ivHp : number, ivAtk : number, ivDef : number) => Math.sqrt(baseStats.baseStamina + ivHp) * Math.sqrt(baseStats.baseDefense + ivDef) * (baseStats.baseAttack + ivAtk);
|
const calculateStatsFormula = (baseStats : IBaseStats, ivHp : number, ivAtk : number, ivDef : number) => Math.sqrt(baseStats.baseStamina + ivHp) * Math.sqrt(baseStats.baseDefense + ivDef) * (baseStats.baseAttack + ivAtk);
|
||||||
|
|
||||||
@ -22,7 +18,7 @@ export const calculateStatAtLevel = (level : number, baseStatValue : number, ivS
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const calculateMaxLevelForLeague = (baseStats : IBaseStats, ivHp : number, ivAtk : number, ivDef : number, league : League) => {
|
export const calculateMaxLevelForLeague = (baseStats : IBaseStats, ivHp : number, ivAtk : number, ivDef : number, league : League) => {
|
||||||
const maxCp = leagueMaxCp[league];
|
const maxCp = MaxCpByLeague[league];
|
||||||
const statsFormula = calculateStatsFormula(baseStats, ivHp, ivAtk, ivDef);
|
const statsFormula = calculateStatsFormula(baseStats, ivHp, ivAtk, ivDef);
|
||||||
let level = 1;
|
let level = 1;
|
||||||
for (let i = LevelMultipliers.length - 1; i >= 0; i--) {
|
for (let i = LevelMultipliers.length - 1; i >= 0; i--) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user