Skip to content

Commit 11be6a2

Browse files
pvanassenGrover-c13
authored andcommitted
Added CP based calculations (#272)
* Added CP based calculations * Implemented method instead of lookup * Added check if meta info exists. Swapped map * #272 (comment)
1 parent 800e16f commit 11be6a2

File tree

2 files changed

+300
-1
lines changed

2 files changed

+300
-1
lines changed

src/main/java/com/pokegoapi/api/pokemon/Pokemon.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import com.pokegoapi.api.inventory.Item;
4242
import com.pokegoapi.api.map.pokemon.EvolutionResult;
4343
import com.pokegoapi.exceptions.LoginFailedException;
44+
import com.pokegoapi.exceptions.NoSuchItemException;
4445
import com.pokegoapi.exceptions.RemoteServerException;
4546
import com.pokegoapi.main.ServerRequest;
4647
import com.pokegoapi.util.Log;
@@ -195,7 +196,7 @@ public UpgradePokemonResponse.Result powerUp() throws LoginFailedException, Remo
195196
}
196197
}
197198

198-
/**
199+
/**dus
199200
* Evolve evolution result.
200201
*
201202
* @return the evolution result
@@ -397,6 +398,48 @@ public double getBaseFleeRate() {
397398
return getMeta().getBaseFleeRate();
398399
}
399400

401+
public float getLevel() {
402+
return PokemonCpUtils.getLevelFromCpMultiplier(proto.getCpMultiplier() + proto.getAdditionalCpMultiplier());
403+
}
404+
405+
/**
406+
* @return The maximum CP for this pokemon
407+
*/
408+
public int getMaxCp() throws NoSuchItemException {
409+
PokemonMeta pokemonMeta = PokemonMetaRegistry.getMeta(proto.getPokemonId());
410+
if (pokemonMeta == null) {
411+
throw new NoSuchItemException("Cannot find meta data for " + proto.getPokemonId().name());
412+
}
413+
int attack = proto.getIndividualAttack() + pokemonMeta.getBaseAttack();
414+
int defense = proto.getIndividualDefense() + pokemonMeta.getBaseDefense();
415+
int stamina = proto.getIndividualStamina() + pokemonMeta.getBaseStamina();
416+
return PokemonCpUtils.getMaxCp(attack, defense, stamina);
417+
}
418+
419+
/**
420+
* @return The CP for this pokemon after powerup
421+
*/
422+
public int getCpAfterPowerup() {
423+
return PokemonCpUtils.getCpAfterPowerup(proto.getCp(),
424+
proto.getCpMultiplier() + proto.getAdditionalCpMultiplier());
425+
}
426+
427+
/**
428+
* @return Cost of candy for a powerup
429+
*/
430+
public int getCandyCostsForPowerup() {
431+
return PokemonCpUtils.getCandyCostsForPowerup(proto.getCpMultiplier() + proto.getAdditionalCpMultiplier(),
432+
proto.getNumUpgrades());
433+
}
434+
435+
/**
436+
* @return Cost of stardust for a powerup
437+
*/
438+
public int getStardustCostsForPowerup() {
439+
return PokemonCpUtils.getStartdustCostsForPowerup(proto.getCpMultiplier() + proto.getAdditionalCpMultiplier(),
440+
proto.getNumUpgrades());
441+
}
442+
400443
public PokemonIdOuterClass.PokemonId getParent() {
401444
return getMeta().getParentId();
402445
}
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
/*
2+
* This program is free software: you can redistribute it and/or modify
3+
* it under the terms of the GNU General Public License as published by
4+
* the Free Software Foundation, either version 3 of the License, or
5+
* (at your option) any later version.
6+
*
7+
* This program is distributed in the hope that it will be useful,
8+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
* GNU General Public License for more details.
11+
*
12+
* You should have received a copy of the GNU General Public License
13+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
14+
*/
15+
16+
package com.pokegoapi.api.pokemon;
17+
18+
import java.util.HashMap;
19+
import java.util.Map;
20+
21+
/**
22+
* Information in this class is based on:
23+
* http://pokemongo.gamepress.gg/cp-multiplier
24+
* and
25+
* http://pokemongo.gamepress.gg/pokemon-stats-advanced
26+
*/
27+
class PokemonCpUtils {
28+
private static final Map<Float,Float> LEVEL_CPMULTIPLIER = new HashMap<>();
29+
30+
static {
31+
LEVEL_CPMULTIPLIER.put(1f, 0.094f);
32+
LEVEL_CPMULTIPLIER.put(1.5f, 0.135137432f);
33+
LEVEL_CPMULTIPLIER.put(2f, 0.16639787f);
34+
LEVEL_CPMULTIPLIER.put(2.5f, 0.192650919f);
35+
LEVEL_CPMULTIPLIER.put(3f, 0.21573247f);
36+
LEVEL_CPMULTIPLIER.put(3.5f, 0.236572661f);
37+
LEVEL_CPMULTIPLIER.put(4f, 0.25572005f);
38+
LEVEL_CPMULTIPLIER.put(4.5f, 0.273530381f);
39+
LEVEL_CPMULTIPLIER.put(5f, 0.29024988f);
40+
LEVEL_CPMULTIPLIER.put(5.5f, 0.306057377f);
41+
LEVEL_CPMULTIPLIER.put(6f, 0.3210876f);
42+
LEVEL_CPMULTIPLIER.put(6.5f, 0.335445036f);
43+
LEVEL_CPMULTIPLIER.put(7f, 0.34921268f);
44+
LEVEL_CPMULTIPLIER.put(7.5f, 0.362457751f);
45+
LEVEL_CPMULTIPLIER.put(8f, 0.37523559f);
46+
LEVEL_CPMULTIPLIER.put(8.5f, 0.387592406f);
47+
LEVEL_CPMULTIPLIER.put(9f, 0.39956728f);
48+
LEVEL_CPMULTIPLIER.put(9.5f, 0.411193551f);
49+
LEVEL_CPMULTIPLIER.put(10f, 0.42250001f);
50+
LEVEL_CPMULTIPLIER.put(10.5f, 0.432926419f);
51+
LEVEL_CPMULTIPLIER.put(11f, 0.44310755f);
52+
LEVEL_CPMULTIPLIER.put(11.5f, 0.453059958f);
53+
LEVEL_CPMULTIPLIER.put(12f, 0.46279839f);
54+
LEVEL_CPMULTIPLIER.put(12.5f, 0.472336083f);
55+
LEVEL_CPMULTIPLIER.put(13f, 0.48168495f);
56+
LEVEL_CPMULTIPLIER.put(13.5f, 0.4908558f);
57+
LEVEL_CPMULTIPLIER.put(14f, 0.49985844f);
58+
LEVEL_CPMULTIPLIER.put(14.5f, 0.508701765f);
59+
LEVEL_CPMULTIPLIER.put(15f, 0.51739395f);
60+
LEVEL_CPMULTIPLIER.put(15.5f, 0.525942511f);
61+
LEVEL_CPMULTIPLIER.put(16f, 0.53435433f);
62+
LEVEL_CPMULTIPLIER.put(16.5f, 0.542635767f);
63+
LEVEL_CPMULTIPLIER.put(17f, 0.55079269f);
64+
LEVEL_CPMULTIPLIER.put(17.5f, 0.558830576f);
65+
LEVEL_CPMULTIPLIER.put(18f, 0.56675452f);
66+
LEVEL_CPMULTIPLIER.put(18.5f, 0.574569153f);
67+
LEVEL_CPMULTIPLIER.put(19f, 0.58227891f);
68+
LEVEL_CPMULTIPLIER.put(19.5f, 0.589887917f);
69+
LEVEL_CPMULTIPLIER.put(20f, 0.59740001f);
70+
LEVEL_CPMULTIPLIER.put(20.5f, 0.604818814f);
71+
LEVEL_CPMULTIPLIER.put(21f, 0.61215729f);
72+
LEVEL_CPMULTIPLIER.put(21.5f, 0.619399365f);
73+
LEVEL_CPMULTIPLIER.put(22f, 0.62656713f);
74+
LEVEL_CPMULTIPLIER.put(22.5f, 0.633644533f);
75+
LEVEL_CPMULTIPLIER.put(23f, 0.64065295f);
76+
LEVEL_CPMULTIPLIER.put(23.5f, 0.647576426f);
77+
LEVEL_CPMULTIPLIER.put(24f, 0.65443563f);
78+
LEVEL_CPMULTIPLIER.put(24.5f, 0.661214806f);
79+
LEVEL_CPMULTIPLIER.put(25f, 0.667934f);
80+
LEVEL_CPMULTIPLIER.put(25.5f, 0.674577537f);
81+
LEVEL_CPMULTIPLIER.put(26f, 0.68116492f);
82+
LEVEL_CPMULTIPLIER.put(26.5f, 0.687680648f);
83+
LEVEL_CPMULTIPLIER.put(27f, 0.69414365f);
84+
LEVEL_CPMULTIPLIER.put(27.5f, 0.700538673f);
85+
LEVEL_CPMULTIPLIER.put(28f, 0.70688421f);
86+
LEVEL_CPMULTIPLIER.put(28.5f, 0.713164996f);
87+
LEVEL_CPMULTIPLIER.put(29f, 0.71939909f);
88+
LEVEL_CPMULTIPLIER.put(29.5f, 0.725571552f);
89+
LEVEL_CPMULTIPLIER.put(30f, 0.7317f);
90+
LEVEL_CPMULTIPLIER.put(30.5f, 0.734741009f);
91+
LEVEL_CPMULTIPLIER.put(31f, 0.73776948f);
92+
LEVEL_CPMULTIPLIER.put(31.5f, 0.740785574f);
93+
LEVEL_CPMULTIPLIER.put(32f, 0.74378943f);
94+
LEVEL_CPMULTIPLIER.put(32.5f, 0.746781211f);
95+
LEVEL_CPMULTIPLIER.put(33f, 0.74976104f);
96+
LEVEL_CPMULTIPLIER.put(33.5f, 0.752729087f);
97+
LEVEL_CPMULTIPLIER.put(34f, 0.75568551f);
98+
LEVEL_CPMULTIPLIER.put(34.5f, 0.758630378f);
99+
LEVEL_CPMULTIPLIER.put(35f, 0.76156384f);
100+
LEVEL_CPMULTIPLIER.put(35.5f, 0.764486065f);
101+
LEVEL_CPMULTIPLIER.put(36f, 0.76739717f);
102+
LEVEL_CPMULTIPLIER.put(36.5f, 0.770297266f);
103+
LEVEL_CPMULTIPLIER.put(37f, 0.7731865f);
104+
LEVEL_CPMULTIPLIER.put(37.5f, 0.776064962f);
105+
LEVEL_CPMULTIPLIER.put(38f, 0.77893275f);
106+
LEVEL_CPMULTIPLIER.put(38.5f, 0.781790055f);
107+
LEVEL_CPMULTIPLIER.put(39f, 0.78463697f);
108+
LEVEL_CPMULTIPLIER.put(39.5f, 0.787473578f);
109+
LEVEL_CPMULTIPLIER.put(40f, 0.79030001f);
110+
}
111+
112+
private static float getLevel(float cpMuliplier) {
113+
float level;
114+
if (cpMuliplier < 0.734f) {
115+
// compute polynomial approximation obtained by regression
116+
level = 58.35178527f * cpMuliplier * cpMuliplier - 2.838007664f * cpMuliplier + 0.8539209906f;
117+
} else {
118+
// compute linear approximation obtained by regression
119+
level = 171.0112688f * cpMuliplier - 95.20425243f;
120+
}
121+
// round to nearest .5 value and return
122+
return Math.round((level) * 2) / 2.0f;
123+
}
124+
125+
/**
126+
* Get the level from the cp multiplier
127+
* @param cpMultiplier All CP multiplier values combined
128+
* @return Level
129+
*/
130+
static float getLevelFromCpMultiplier(float cpMultiplier) {
131+
return getLevel(cpMultiplier);
132+
}
133+
134+
/**
135+
* Get the maximum CP from the values
136+
* @param attack All attack values combined
137+
* @param defense All defense values combined
138+
* @param stamina All stamina values combined
139+
* @return Maximum CP for these levels
140+
*/
141+
static int getMaxCp(int attack, int defense, int stamina) {
142+
float maxCpMultplier = LEVEL_CPMULTIPLIER.get(40f);
143+
return (int)(attack * Math.pow(defense, 0.5) * Math.pow(stamina, 0.5) * Math.pow(maxCpMultplier,2) / 10f);
144+
}
145+
146+
/**
147+
* Get the CP after powerup
148+
* @param cp Current CP level
149+
* @param cpMultiplier All CP multiplier values combined
150+
* @return New CP level
151+
*/
152+
static int getCpAfterPowerup(float cp, float cpMultiplier) {
153+
// Based on http://pokemongo.gamepress.gg/power-up-costs
154+
float level = getLevelFromCpMultiplier(cpMultiplier);
155+
if (level <= 10) {
156+
return (int)((cp * 0.009426125469) / Math.pow(cpMultiplier, 2));
157+
}
158+
if (level <= 20) {
159+
return (int)((cp * 0.008919025675) / Math.pow(cpMultiplier, 2));
160+
}
161+
if (level <= 30) {
162+
return (int)((cp * 0.008924905903) / Math.pow(cpMultiplier, 2));
163+
}
164+
return (int)((cp * 0.00445946079) / Math.pow(cpMultiplier, 2));
165+
}
166+
167+
/**
168+
* Get the amount of stardust required to do a powerup
169+
* @param cpMultiplier All CP multiplier values combined
170+
* @param powerups Number of previous powerups
171+
* @return Amount of stardust
172+
*/
173+
static int getStartdustCostsForPowerup(float cpMultiplier, int powerups) {
174+
// Based on http://pokemongo.gamepress.gg/power-up-costs
175+
float level = getLevelFromCpMultiplier(cpMultiplier);
176+
if (level <= 3 && powerups <= 4) {
177+
return 200;
178+
}
179+
if (level <= 4 && powerups <= 8) {
180+
return 400;
181+
}
182+
if (level <= 7 && powerups <= 12) {
183+
return 600;
184+
}
185+
if (level <= 8 && powerups <= 16) {
186+
return 800;
187+
}
188+
if (level <= 11 && powerups <= 20) {
189+
return 1000;
190+
}
191+
if (level <= 13 && powerups <= 24) {
192+
return 1300;
193+
}
194+
if (level <= 15 && powerups <= 28) {
195+
return 1600;
196+
}
197+
if (level <= 17 && powerups <= 32) {
198+
return 1900;
199+
}
200+
if (level <= 19 && powerups <= 36) {
201+
return 2200;
202+
}
203+
if (level <= 21 && powerups <= 40) {
204+
return 2500;
205+
}
206+
if (level <= 23 && powerups <= 44) {
207+
return 3000;
208+
}
209+
if (level <= 25 && powerups <= 48) {
210+
return 3500;
211+
}
212+
if (level <= 27 && powerups <= 52) {
213+
return 4000;
214+
}
215+
if (level <= 29 && powerups <= 56) {
216+
return 4500;
217+
}
218+
if (level <= 31 && powerups <= 60) {
219+
return 5000;
220+
}
221+
if (level <= 33 && powerups <= 64) {
222+
return 6000;
223+
}
224+
if (level <= 35 && powerups <= 68) {
225+
return 7000;
226+
}
227+
if (level <= 37 && powerups <= 72) {
228+
return 8000;
229+
}
230+
if (level <= 39 && powerups <= 76) {
231+
return 9000;
232+
}
233+
return 10000;
234+
}
235+
236+
/**
237+
* Get the amount of candy required to do a powerup
238+
* @param cpMultiplier All CP multiplier values combined
239+
* @param powerups Number of previous powerups
240+
* @return Amount of candy
241+
*/
242+
static int getCandyCostsForPowerup(float cpMultiplier, int powerups) {
243+
// Based on http://pokemongo.gamepress.gg/power-up-costs
244+
float level = getLevelFromCpMultiplier(cpMultiplier);
245+
if (level <= 13 && powerups <= 20 ) {
246+
return 1;
247+
}
248+
if (level <= 21 && powerups <= 36 ) {
249+
return 2;
250+
}
251+
if (level <= 31 && powerups <= 60 ) {
252+
return 3;
253+
}
254+
return 4;
255+
}
256+
}

0 commit comments

Comments
 (0)