From d1cd3f98c5c1ecb22cb0f363a0b430d84a66919e Mon Sep 17 00:00:00 2001 From: Grover-c13 Date: Mon, 1 Aug 2016 21:33:28 +0800 Subject: [PATCH] Merge branch 'master' into Development (#424) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Refresh the OAuth token when it expires * Fix my siliness and provide API consumers a way to provide their refresh token when using static auth * add query from hatched eggs + rewrite stuff around EggPokemon * fix the explaination for eclipse user * Level enum public for custom loggers * Publish sources jar Fixes #128 * add license to GoogleLoginSecrets * Use a reset instead of using another instance * Fix the checkstyle config to not break other modules * find Pokemon by ID update inventory after hatching eggs add missing license * Meta info on pokemon * add method the incubator * fix typo * Add a callback for when the Initial oAuth completes so that the app can automate the flow * Power up pokemon API * Add info about native google sign in * REAME.md: fix Usefull->Useful typo * README.md: fix PtcLogin classname type * fix force updating inventories * Fix incorrect static statements on point * Added iv calculator (#207) * Added iv calculator * checkstyleMain fix * Fix @returns in doc of getIVRatio() * take care that the candies actually are in the map * forgot that cancerous check style * tweak checkstyle config to be friendly (#226) * Add cause to LoginFailedExceptions. (#220) Signed-off-by: Niklas Walter * Remove printStackTrace from updateProfile (#221) updateProfile, in case of failure, would dump stacktraces to the console and then crash in the next line with a NullPointerException * Added request to add modifiers to forts, for example a lure-module on a pokestop (#217) * implemented request to add fort modifier * added @throws to javadoc for addModifier in Pokestop.java * Added SetFavoritePokemon method (#222) * add lombok to more objects (#212) * add lombok to more objects * add lombok to GoogleAuthJson * add lombok to Team * getItemsCount function (#224) * get total space used by items * get total space used by items * add javadoc * Rewrote and Refactored login logic. Now the credential providers transparently handle providing credentials and refreshing tokens. * Update the protobuf dependency (#235) Includes fix for hatched eggs IndexOutOfBoundsException * WIP: Gym/Battle (#203) * Add info about native google sign in * fix force updating inventories * REAME.md: fix Usefull->Useful typo * README.md: fix PtcLogin classname type * Start Gym + Battle API * Battle API - Example included, utility functions to get state of battle. Can only spam attack right now. * Deprecate pokemon.getFavorite, rename to pokemon.isFavorite (#230) * deprecate getFavorite, rename to isFavorite * Adhere to checkstyle * Use gradle-wrapper instead (#200) * Use gradle-wrapper instead * Changed second gradle usage to use gradlew aswell * Fix typos (#218) * Fix UTF-8 encoding * Fix typo recieved -> received * fix example * Consistently use RemoteServerException for network/server errors (#243) * Redone meta pm, lots of info available, several enums for pokemon (some may be duplicates of proto enums), fix catchable pokemon (#246) * fix #237 + #227 (#240) * Update protobufs to latest version * Add getPoints() to gym wrapper (#247) * Fix #171 - Implement logging levels * Hypno should actually be in FAMILY_DROWZEE (#262) * Update README.md (#257) Clarification on what the function calls do. If we're going to change the API wrapper, we should at least briefly comment on how it works underneath. * added the ability to use potions & revive on pokemon (#236) * inizio pozioni pokemon * inizio pozioni pokemon * fixed space * checkstyle fixes * refresh pokemon stamina after heal/revive * added a request to accept level up rewards and unlocks (#259) * Fix silly error * Rewrite readme with all new stuff - explain the risk of using this api - more examples - got to jitpack to build with maven/graddle - update contributor * abstract time behavior to allow mocking and replacing the time by non-System time (#277) * set time implementation correctly (#282) make old PtcCredentialProvider constructor @Deprecated * settings via DownloadSettings + protobuf update (#285) * inizio pozioni pokemon * inizio pozioni pokemon * fixed space * checkstyle fixes * refresh pokemon stamina after heal/revive * add support for settings * add support for settings * Added CP based calculations (#272) * Added CP based calculations * Implemented method instead of lookup * Added check if meta info exists. Swapped map * https://github.com/Grover-c13/PokeGOAPI-Java/pull/272#discussion_r72429643 * Add usage instructions for Eclipse users (#290) Many will opt for simply copying the lib to the libs folder, but this allows building the API project as necessary, while maintaining an updated version of the lib produced in the target project. ** Intended for only building the target project with Eclipse ** * fix for #279 (#292) * check and equip badges * check and equip badges * Automatic google login with username and password (#265) * Add gpsoauth dependency * Add google auto credentials provider * Add token refresh * svarzee-Development (#297) * Add gpsoauth dependency * Add google auto credentials provider * Add token refresh * Checkstyle will not stop you building now, but you are still expected to correct issues before submitting a PR. (#300) * Checkstyle will not stop you building now, but you are still expected to correct issues before submitting a PR. fixed issue with checkstyle in google auto login. * Checkstyle fix * gdev (#305) * Checkstyle will not stop you building now, but you are still expected to correct issues before submitting a PR. fixed issue with checkstyle in google auto login. * Checkstyle fix * Added time to new provider * added time * added PokemonMoveMeta + Registry (#298) * created PokemonMoveMeta.java * added PokemonMoveMetaRegistry * Update PokemonType.java * modify build process to generate javadoc and one bundled jar + fix checkstyle (#307) * add javadoc link to readme * Added weight getter to Pokemon.java (#309) * trigger bundle after creating the jar * bundle is done for every build now * Added new oauth for google user interaction to supercede GoogleCredentialProvider (example included) added a new hasLure method to Pokestops that is more reliable. Undeprecrated constructors that construct time objects by default (#316) * delete old google token provider since its working + add explain on example * Correct, organize, and format README - Correct spelling, grammar, and punctuation errors - Format lists into individual steps - Break comments into smaller segments - Simplify complex explanations * fix styles * Update the readme example to use the latest google provider * add javadoc * added getter to get refresh token for GoogleAutoProvider + constructor without Time impl in GoogleUserProvider * Feature request Issue 311 * - replaced for loop by iterator because of concurrent modification in MapObjects Update method * update readme with slack invitation link * hotfix spamming request when constructing PokemonGo instance * test * test * -also changed update method of gyms to use iterator * Upgrade gpsoauth * - fixed styling * Cleaned up some doc blocks (#352) * Added Util class to get Name for Pokedex Numbers, Also added Translations (#284) * Added Util class to get NAme for Pokedex Numbers, Also added Translations for those * Adjusted Files According to Pullrequest Review * Removed Double License Headeer, Added Missing License Header * Fixed hasLurePokemon() from always returning false unless the lure module expired and the pokestop was still in memory with a pokemon. It now properly returns true if there is a pokemon at the pokestop and the lure is not expired. * Async implementation based in Futures (#360) * Base for async * Transparent async requests * Converted map * Converted map, may have broken cache * Cleanup leftovers of Rx * Start on catchable pokemon * Did some methods on CatchablePokemon. Implemented NestedFutureWrapper to link Futures * Switched Pokestop * Some tinkering with timings and forgetting to clear lists * Exceptions shoudl accept Throwable * Cleanup of deprecate methods, Removed sleeps * Fixed sending garbage * Actually got it working * Checkstyle update * Checkstyle update * Upped timer a bit because of a few issues with empty requests * Sync list (#370) * Add moves to pokemon meta registry (#368) * Fix get catchablePokemon (#386) * Sync list * Hopefully fix map.getObject/getCatchablePokemon issue * Make constructor lightweight (#388) * Sync list * Hopefully fix map.getObject/getCatchablePokemon issue * Refactor some player profile stuff, make the constructor shorter, made it lazy init (wont call for an update on the server unless you call a method to get data) * The api constructor will not make any server requests, it will lazy load any sections of the api a person needs (ie callling getInventories will get stuff from the server if its yet to happen). Some extra methods now throw RemoteServer/Login exceptions so please keep that in mind. cleaned up a few things (mainly javadoc). * Refactor some player profile stuff, make the constructor shorter, made it lazy init (wont call for an update on the server unless you call a method to get data) * Implemented inventory settings (#376) * added support for incense activation (#314) * Changed private fields to protected to allow extending of the Providers for API users without having to rewrite the whole class. (#350) * Optimize imports (#390) * Optimize imports * Optimize imports * added Japanese pokemon names and fixed garbled characters in Russian and Chinese (#383) * Fort details should be doubles instead of longs (#393) * https://github.com/Grover-c13/PokeGOAPI-Java/issues/378 (#392) * Fix import.*, fix other checkstyle stuff, fix NPE when getting stats (#401) * Add evolution auxiliaries (#400) * fix infinite loop when pokemon flees using catch(), removed pokemon from catchable list after being caught/fleeing * fix infinite loop when pokemon flees using catch(), removed pokemon from catchable list after being caught/fleeing * catchfix (#404) * fix infinite loop when pokemon flees using catch(), removed pokemon from catchable list after being caught/fleeing * fix infinite loop when pokemon flees using catch(), removed pokemon from catchable list after being caught/fleeing * Lucky egg for spinnix yay * useLuckyEgg() in ItemBag for spinnix, Fix NPE on catch result Fix issue when pokemon broke out of ball Fix checkstyle issues * Remove print * Fixes an ArrayOutOfBoundsException (#411) Fixes an ArrayOutOfBoundsException in EvolutionInfo. Currently it takes the length of an array as an index in the array which will result in an exception being thrown anytime this function is called. * Extra log levels: all and none (#409) * Extra log levels: all and none * Fix indentation (tabs only) * Adding Sorting Map Objects (#396) * Adding map util to get distance between two points * Adding sorting function for objects in the map * Adding the check if the user have enough poke ball´s * Adding the check if the user have enough poke ball´s * Adding license * Fixing example class * Fix code style * Updating code style * Updating code style * Fixing import * luresfixesandgoodtimes (#418) * Added lured pokemon to getCatchablePokemon removed DummyFuture Fixed NPE in FutureWrapper when using .just Fixed issue when caught pokemon will still appearing in catchable pokemon Added a little more detail to the PTC login exception Changed exception message from "Error in url" to "Invalid auth status code recieved" * Checkstyle * Travis fix * updated moves (#416) https://www.reddit.com/r/TheSilphRoad/comments/4v99uo/move_powers_have_been_updated/ * Adding the check if the user have enough poke ball´s (#397) * Adding the check if the user have enough poke ball´s * Adding the check if the user have enough poke ball´s * Fixing example class * Fix code style * updating submodule to latest (#419) --- README.md | 136 +- build.gradle | 27 +- .../PokeGOAPI-Java/pokemon_names.properties | 721 +++++++ .../pokemon_names_de.properties | 721 +++++++ .../pokemon_names_en.properties | 721 +++++++ .../pokemon_names_fr.properties | 721 +++++++ .../pokemon_names_ru.properties | 721 +++++++ .../pokemon_names_zh_CN.properties | 721 +++++++ .../pokemon_names_zh_HK.properties | 151 ++ .../java/com/pokegoapi/api/PokemonGo.java | 93 +- .../java/com/pokegoapi/api/gym/Battle.java | 14 +- src/main/java/com/pokegoapi/api/gym/Gym.java | 15 +- .../com/pokegoapi/api/inventory/CandyJar.java | 1 - .../pokegoapi/api/inventory/EggIncubator.java | 3 +- .../com/pokegoapi/api/inventory/Hatchery.java | 1 - .../pokegoapi/api/inventory/Inventories.java | 12 +- .../com/pokegoapi/api/inventory/Item.java | 24 + .../com/pokegoapi/api/inventory/ItemBag.java | 126 +- .../com/pokegoapi/api/inventory/PokeBank.java | 3 +- .../com/pokegoapi/api/inventory/Stats.java | 96 + src/main/java/com/pokegoapi/api/map/Map.java | 478 +++-- .../com/pokegoapi/api/map/MapObjects.java | 37 +- .../java/com/pokegoapi/api/map/Point.java | 3 +- .../com/pokegoapi/api/map/fort/Pokestop.java | 150 +- .../api/map/pokemon/CatchItemResult.java | 1 - .../api/map/pokemon/CatchResult.java | 13 + .../api/map/pokemon/CatchablePokemon.java | 511 +++-- .../encounter/DiskEncounterResult.java | 69 + .../pokemon/encounter/EncounterResult.java | 29 + .../NormalEncounterResult.java} | 29 +- .../pokegoapi/api/player/ContactSettings.java | 15 +- .../com/pokegoapi/api/player/DailyBonus.java | 15 +- .../pokegoapi/api/player/PlayerAvatar.java | 54 +- .../api/player/PlayerLevelUpRewards.java | 53 + .../pokegoapi/api/player/PlayerProfile.java | 254 ++- .../com/pokegoapi/api/pokemon/EggPokemon.java | 4 +- .../pokegoapi/api/pokemon/EvolutionForm.java | 29 + .../pokegoapi/api/pokemon/EvolutionInfo.java | 443 +++++ .../com/pokegoapi/api/pokemon/Pokemon.java | 274 ++- .../pokegoapi/api/pokemon/PokemonCpUtils.java | 256 +++ .../pokegoapi/api/pokemon/PokemonMeta.java | 10 +- .../api/pokemon/PokemonMetaRegistry.java | 1656 +++++++++++++---- .../api/pokemon/PokemonMoveMeta.java | 46 + .../api/pokemon/PokemonMoveMetaRegistry.java | 1412 ++++++++++++++ .../pokegoapi/api/pokemon/PokemonType.java | 8 +- .../pokegoapi/api/settings/FortSettings.java | 10 + .../api/settings/InventorySettings.java | 27 + .../api/settings/LevelUpSettings.java | 13 + .../pokegoapi/api/settings/MapSettings.java | 78 + .../com/pokegoapi/api/settings/Settings.java | 98 + .../pokegoapi/auth/CredentialProvider.java | 1 - .../com/pokegoapi/auth/GoogleAuthJson.java | 1 - .../pokegoapi/auth/GoogleAuthTokenJson.java | 1 - .../auth/GoogleAutoCredentialProvider.java | 124 ++ .../auth/GoogleUserCredentialProvider.java | 249 +++ .../pokegoapi/auth/PtcCredentialProvider.java | 43 +- .../examples/CatchPokemonAtAreaExample.java | 8 +- .../examples/DisplayPokenameExample.java | 56 + .../pokegoapi/examples/FightGymExample.java | 1 - .../GoogleUserInteractionExample.java | 55 + .../examples/TransferOnePidgeyExample.java | 14 +- .../pokegoapi/examples/UseIncenseExample.java | 64 + .../exceptions/AsyncLoginFailedException.java | 30 + .../exceptions/AsyncPokemonGoException.java | 31 + .../AsyncRemoteServerException.java | 30 + .../exceptions/InvalidCurrencyException.java | 2 +- .../exceptions/LoginFailedException.java | 4 +- .../exceptions/NoSuchItemException.java | 2 +- .../exceptions/RemoteServerException.java | 4 +- .../google/common/geometry/R1Interval.java | 61 +- .../pokegoapi/google/common/geometry/S2.java | 89 +- .../google/common/geometry/S2Cap.java | 5 + .../google/common/geometry/S2CellId.java | 12 +- .../google/common/geometry/S2EdgeIndex.java | 12 +- .../google/common/geometry/S2EdgeUtil.java | 2 +- .../google/common/geometry/S2LatLngRect.java | 6 +- .../pokegoapi/main/AsyncServerRequest.java | 58 + .../com/pokegoapi/main/RequestHandler.java | 294 +-- .../com/pokegoapi/main/ResultOrException.java | 39 + .../com/pokegoapi/main/ServerRequest.java | 12 + .../java/com/pokegoapi/util/BaseLogger.java | 8 +- .../com/pokegoapi/util/FutureWrapper.java | 153 ++ src/main/java/com/pokegoapi/util/Log.java | 80 +- .../java/com/pokegoapi/util/MapPoint.java | 36 + src/main/java/com/pokegoapi/util/MapUtil.java | 100 + .../pokegoapi/util/NestedFutureWrapper.java | 55 + .../java/com/pokegoapi/util/PokeNames.java | 36 + .../com/pokegoapi/util/PokemonFuture.java | 25 + .../com/pokegoapi/util/SystemTimeImpl.java | 23 + src/main/java/com/pokegoapi/util/Time.java | 25 + src/main/resources/pokemon_names.properties | 721 +++++++ .../resources/pokemon_names_de.properties | 721 +++++++ .../resources/pokemon_names_en.properties | 721 +++++++ .../resources/pokemon_names_fr.properties | 721 +++++++ .../resources/pokemon_names_ja.properties | 721 +++++++ .../resources/pokemon_names_ru.properties | 721 +++++++ .../resources/pokemon_names_zh_CN.properties | 721 +++++++ .../resources/pokemon_names_zh_HK.properties | 151 ++ 98 files changed, 16996 insertions(+), 1156 deletions(-) create mode 100644 classes/production/PokeGOAPI-Java/pokemon_names.properties create mode 100644 classes/production/PokeGOAPI-Java/pokemon_names_de.properties create mode 100644 classes/production/PokeGOAPI-Java/pokemon_names_en.properties create mode 100644 classes/production/PokeGOAPI-Java/pokemon_names_fr.properties create mode 100644 classes/production/PokeGOAPI-Java/pokemon_names_ru.properties create mode 100644 classes/production/PokeGOAPI-Java/pokemon_names_zh_CN.properties create mode 100644 classes/production/PokeGOAPI-Java/pokemon_names_zh_HK.properties create mode 100644 src/main/java/com/pokegoapi/api/map/pokemon/encounter/DiskEncounterResult.java create mode 100644 src/main/java/com/pokegoapi/api/map/pokemon/encounter/EncounterResult.java rename src/main/java/com/pokegoapi/api/map/pokemon/{EncounterResult.java => encounter/NormalEncounterResult.java} (66%) create mode 100644 src/main/java/com/pokegoapi/api/player/PlayerLevelUpRewards.java create mode 100644 src/main/java/com/pokegoapi/api/pokemon/EvolutionForm.java create mode 100644 src/main/java/com/pokegoapi/api/pokemon/EvolutionInfo.java create mode 100644 src/main/java/com/pokegoapi/api/pokemon/PokemonCpUtils.java create mode 100644 src/main/java/com/pokegoapi/api/pokemon/PokemonMoveMeta.java create mode 100644 src/main/java/com/pokegoapi/api/pokemon/PokemonMoveMetaRegistry.java create mode 100644 src/main/java/com/pokegoapi/api/settings/FortSettings.java create mode 100644 src/main/java/com/pokegoapi/api/settings/InventorySettings.java create mode 100644 src/main/java/com/pokegoapi/api/settings/LevelUpSettings.java create mode 100644 src/main/java/com/pokegoapi/api/settings/MapSettings.java create mode 100644 src/main/java/com/pokegoapi/api/settings/Settings.java create mode 100644 src/main/java/com/pokegoapi/auth/GoogleAutoCredentialProvider.java create mode 100644 src/main/java/com/pokegoapi/auth/GoogleUserCredentialProvider.java create mode 100644 src/main/java/com/pokegoapi/examples/DisplayPokenameExample.java create mode 100644 src/main/java/com/pokegoapi/examples/GoogleUserInteractionExample.java create mode 100644 src/main/java/com/pokegoapi/examples/UseIncenseExample.java create mode 100644 src/main/java/com/pokegoapi/exceptions/AsyncLoginFailedException.java create mode 100644 src/main/java/com/pokegoapi/exceptions/AsyncPokemonGoException.java create mode 100644 src/main/java/com/pokegoapi/exceptions/AsyncRemoteServerException.java create mode 100644 src/main/java/com/pokegoapi/main/AsyncServerRequest.java create mode 100644 src/main/java/com/pokegoapi/main/ResultOrException.java create mode 100644 src/main/java/com/pokegoapi/util/FutureWrapper.java create mode 100644 src/main/java/com/pokegoapi/util/MapPoint.java create mode 100644 src/main/java/com/pokegoapi/util/MapUtil.java create mode 100644 src/main/java/com/pokegoapi/util/NestedFutureWrapper.java create mode 100644 src/main/java/com/pokegoapi/util/PokeNames.java create mode 100644 src/main/java/com/pokegoapi/util/PokemonFuture.java create mode 100644 src/main/java/com/pokegoapi/util/SystemTimeImpl.java create mode 100644 src/main/java/com/pokegoapi/util/Time.java create mode 100644 src/main/resources/pokemon_names.properties create mode 100644 src/main/resources/pokemon_names_de.properties create mode 100644 src/main/resources/pokemon_names_en.properties create mode 100644 src/main/resources/pokemon_names_fr.properties create mode 100644 src/main/resources/pokemon_names_ja.properties create mode 100644 src/main/resources/pokemon_names_ru.properties create mode 100644 src/main/resources/pokemon_names_zh_CN.properties create mode 100644 src/main/resources/pokemon_names_zh_HK.properties diff --git a/README.md b/README.md index c359c85d..0c238e47 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,9 @@ Pokemon GO Java API [![Build Status](https://travis-ci.org/Grover-c13/PokeGOAPI-Java.svg?branch=master)](https://travis-ci.org/Grover-c13/PokeGOAPI-Java) +[![](https://jitpack.io/v/Grover-c13/PokeGOAPI-Java.svg)](https://jitpack.io/#Grover-c13/PokeGOAPI-Java) + +Javadocs : [CLICK ME](https://jitpack.io/com/github/Grover-c13/PokeGOAPI-Java/a2828da60d/javadoc/) See this guide for adding functionality: https://docs.google.com/document/d/1BE8O6Z19sQ54T5T7QauXgA11GbL6D9vx9AAMCM5KlRA @@ -11,47 +14,112 @@ See this spreadsheet for RPC endpoints and progress : https://docs.google.com/spreadsheets/d/1Xv0Gw5PzIRaVou2xrl6r7qySrcmOKjQWLBjJA73YnJM ___ -:exclamation: - -This API may seem unstable. This is because the backend Pokemon GO servers are unstable. +:exclamation: :exclamation: :exclamation: -In case stuff is not working as expected, wait a moment to see if the problem resolves itself automatically. +This API may have issues when the PokemonGO servers are under high load or down, in this case please wait for the official to get back up. You can check the official servers status on [IsPokemonGoDownOrNot.com](http://ispokemongodownornot.com) or [MMOServerStatus.com](http://www.mmoserverstatus.com/pokemon_go). -You may also check the status of the servers on [IsPokemonGoDownOrNot.com](http://ispokemongodownornot.com) or [MMOServerStatus.com](http://www.mmoserverstatus.com/pokemon_go). +This API doesnt fake the official client perfectly, niantic may know that you arent using the official app, we encourage you to use a alternate account to play with this API. -If you just want to use it, wait some days until the server issues are resolved (or if there is a problem with this library, you may fix it and send a PR this way). +If you are using this lib to catch pokemon and loot pokestop, take care that you arent teleporting, the servers may issue a softban against your client (its temporary, between 10 and 30 minutes in general). -:exclamation: +:exclamation: :exclamation: :exclamation: ___ -# Build - - Clone the repo and cd into the folder - - `` git submodule update --init `` - - compile and package - - `` ./gradlew build bundle `` - - you should have the api bundled in ``build/libs/PokeGOAPI-Java_bundle-0.0.1-SNAPSHOT.jar`` +# How to import + + Import from Maven/Gradle/SBT/Leiningen using JitPack : [![](https://jitpack.io/v/Grover-c13/PokeGOAPI-Java.svg)](https://jitpack.io/#Grover-c13/PokeGOAPI-Java) + + After you clicked on this link, jitpack will show you multiple build (try use the latest one since the api grow everyday). + JitPack will show an example for each dependency manager to include our API into your project. - PS : To Eclipse user, you must build once : `` ./gradlew build `` and add the generated java class for proto into eclipse source path : Right click on the project > Build path > Configure Build Path > Source > Add Folder > Select `build/generated/source/proto/main/java` > Finish +OR -# Usage -Include the API as jar from your own build, or use Maven/Gradle/SBT/Leiningen: https://jitpack.io/#Grover-c13/PokeGOAPI-Java/master-SNAPSHOT + Import JAR in Eclipse + - Right click on the project + - Select Build path > Java Build Path + - Select Libraries tab + - Select Add External JARs… + - Select `PokeGOAPI-Java/build/libs/PokeGOAPI-Java-0.0.1-SNAPSHOT.jar` + - Finish -Mostly everything is accessed through the PokemonGo class in the API package. +# Build from source + - Clone the repo and cd into the folder + - `` git submodule update --init `` + - `` ./gradlew build `` + - you should have the api jar in ``build/libs/PokeGOAPI-Java-0.0.1-SNAPSHOT.jar`` -The constructor of PokemonGo class requires a AuthInfo object which can be obtained from GoogleLogin().login or PtcLogin().login, and a OkHttpClient object. +PS : for users who want to import the api into Eclipse IDE, you'll need to : + - build once : `` ./gradlew build `` + - Right click on the project + - Select Build path > Configure Build Path > Source > Add Folder + - Select `build/generated/source/proto/main/java` + - Finish -EG: +# Usage exemple (mostly how to login) : ```java OkHttpClient httpClient = new OkHttpClient(); -//Use Google -//First Ever Login. Persist info when you recieve callback -PokemonGo go = new PokemonGo(new GoogleCredentialProvider(httpClient,listner),httpClient); -//Subsequently -PokemonGo go = new PokemonGo(new GoogleCredentialProvider(httpClient,refreshToken),httpClient); -//Or use PTC + +/** +* Google: +* You will need to redirect your user to GoogleUserCredentialProvider.LOGIN_URL +* Afer this, the user must signin on google and get the token that will be show to him. +* This token will need to be put as argument to login. +*/ +GoogleUserCredentialProvider provider = new GoogleUserCredentialProvider(http); + +// in this url, you will get a code for the google account that is logged +System.out.println("Please go to " + GoogleUserCredentialProvider.LOGIN_URL); +System.out.println("Enter authorisation code:"); + +// Ask the user to enter it in the standart input +Scanner sc = new Scanner(System.in); +String access = sc.nextLine(); + +// we should be able to login with this token +provider.login(access); +PokemonGo go = new PokemonGo(provider, httpClient); + +/** +* After this, if you do not want to re-authorize the google account every time, +* you will need to store the refresh_token that you can get the first time with provider.getRefreshToken() +* ! The API does not store the refresh token for you ! +* log in using the refresh token like this : +*/ +PokemonGo go = new PokemonGo(new GoogleUserCredentialProvider(httpClient, refreshToken), httpClient); + +/** +* PTC is much simpler, but less secure. +* You will need the username and password for each user log in +* This account does not currently support a refresh_token. +* Example log in : +*/ PokemonGo go = new PokemonGo(new PtcCredentialProvider(httpClient,username,password),httpClient); -Log.v(go.getPlayerProfile()); + +// After this you can access the api from the PokemonGo instance : +go.getPlayerProfile(); // to get the user profile +go.getInventories(); // to get all his inventories (Pokemon, backpack, egg, incubator) +go.setLocation(lat, long, alt); // set your position to get stuff around (altitude is not needed, you can use 1 for example) +go.getMap().getCatchablePokemon(); // get all currently Catchable Pokemon around you + +// If you want to go deeper, you can directly send your request with our RequestHandler +// For example, here we are sending a request to get the award for our level +// This applies to any method defined in the protos file as Request/Response) + +LevelUpRewardsMessage msg = LevelUpRewardsMessage.newBuilder().setLevel(yourLVL).build(); +ServerRequest serverRequest = new ServerRequest(RequestType.LEVEL_UP_REWARDS, msg); +go.getRequestHandler().sendServerRequests(serverRequest); + +// and get the response like this : + +LevelUpRewardsResponse response = null; +try { + response = LevelUpRewardsResponse.parseFrom(serverRequest.getData()); +} catch (InvalidProtocolBufferException e) { + // its possible that the parsing fail when servers are in high load for example. + throw new RemoteServerException(e); +} ``` + ##Android Dev FAQ - I can't use the sample code! It just throws a login exception! @@ -75,11 +143,11 @@ You can't. The Google Identity Platform uses the SHA1 fingerprint and package na - Submit a pull request on the `Development` branch :D ## Contributors - - Grover-c13 - - jabbink - - Aphoh - - zeladada - - darakath - - vmarchaud - -You can join us in the slack channel #javaapi on the pkre.slack.com (you should get an invite by a bot posted somewhere in the subreddit /r/pokemongodev) + - @Grover-c13 + - @jabbink + - @Aphoh + - @mjmfighter + - @vmarchaud + - @langerhans + +You can join us in the slack channel #javaapi on the pkre.slack.com ([you can get invited here](https://shielded-earth-81203.herokuapp.com/)) diff --git a/build.gradle b/build.gradle index 9bdb1f71..c5b259a7 100644 --- a/build.gradle +++ b/build.gradle @@ -8,8 +8,6 @@ buildscript { dependencies { classpath 'com.google.protobuf:protobuf-gradle-plugin:0.7.7' } - - } apply plugin: 'idea' @@ -25,6 +23,7 @@ targetCompatibility = 1.7 repositories { mavenCentral() + maven { url "https://jitpack.io" } } sourceSets { @@ -39,13 +38,11 @@ sourceSets { // Remove all .proto definition from the final build processResources { - exclude('**/*') + exclude('POGOProtos/') } // Run this task to bundle all needed dependency task bundle(type: Jar) { - baseName = project.name + '_bundle' - from { configurations.compile.collect { it.isDirectory() && !it.isEmpty() ? it : zipTree(it) @@ -54,6 +51,8 @@ task bundle(type: Jar) { with jar } +jar.finalizedBy(bundle) + protobuf { // Configure the protoc executable protoc { @@ -90,11 +89,15 @@ checkstyle { checkstyleMain.doLast { def outputFile = file(checkstyleOutputDir + "main.xml") if (outputFile.exists() && outputFile.text.contains(" getGymMembers() throws LoginFailedException, RemoteSe * Get a list of pokemon defending this gym. * * @return List of pokemon + * @throws LoginFailedException if the login failed + * @throws RemoteServerException When a buffer exception is thrown */ public List getDefendingPokemon() throws LoginFailedException, RemoteServerException { List data = new ArrayList(); diff --git a/src/main/java/com/pokegoapi/api/inventory/CandyJar.java b/src/main/java/com/pokegoapi/api/inventory/CandyJar.java index 41f7b587..4ad99bb5 100644 --- a/src/main/java/com/pokegoapi/api/inventory/CandyJar.java +++ b/src/main/java/com/pokegoapi/api/inventory/CandyJar.java @@ -17,7 +17,6 @@ import POGOProtos.Enums.PokemonFamilyIdOuterClass.PokemonFamilyId; import com.pokegoapi.api.PokemonGo; -import com.pokegoapi.api.pokemon.Pokemon; import lombok.ToString; import java.util.HashMap; diff --git a/src/main/java/com/pokegoapi/api/inventory/EggIncubator.java b/src/main/java/com/pokegoapi/api/inventory/EggIncubator.java index 1a179512..2c034034 100644 --- a/src/main/java/com/pokegoapi/api/inventory/EggIncubator.java +++ b/src/main/java/com/pokegoapi/api/inventory/EggIncubator.java @@ -26,7 +26,6 @@ import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; import com.pokegoapi.main.ServerRequest; -import lombok.Getter; public class EggIncubator { private final EggIncubatorOuterClass.EggIncubator proto; @@ -124,7 +123,7 @@ public double getKmWalked() { * * @return currently used or not */ - public boolean isInUse() { + public boolean isInUse() throws LoginFailedException, RemoteServerException { return getKmTarget() > pgo.getPlayerProfile().getStats().getKmWalked(); } } diff --git a/src/main/java/com/pokegoapi/api/inventory/Hatchery.java b/src/main/java/com/pokegoapi/api/inventory/Hatchery.java index e621f885..fdaa89c1 100644 --- a/src/main/java/com/pokegoapi/api/inventory/Hatchery.java +++ b/src/main/java/com/pokegoapi/api/inventory/Hatchery.java @@ -25,7 +25,6 @@ import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; import com.pokegoapi.main.ServerRequest; - import lombok.Getter; import java.util.ArrayList; diff --git a/src/main/java/com/pokegoapi/api/inventory/Inventories.java b/src/main/java/com/pokegoapi/api/inventory/Inventories.java index 5929fe11..65a5f5ed 100644 --- a/src/main/java/com/pokegoapi/api/inventory/Inventories.java +++ b/src/main/java/com/pokegoapi/api/inventory/Inventories.java @@ -136,16 +136,16 @@ public void updateInventories(boolean forceUpdate) throws LoginFailedException, } // candyjar - if (itemData.getPokemonFamily().getFamilyId() != PokemonFamilyIdOuterClass.PokemonFamilyId.UNRECOGNIZED - && itemData.getPokemonFamily().getFamilyId() != PokemonFamilyIdOuterClass.PokemonFamilyId.FAMILY_UNSET) { + if (itemData.getCandy().getFamilyId() != PokemonFamilyIdOuterClass.PokemonFamilyId.UNRECOGNIZED + && itemData.getCandy().getFamilyId() != PokemonFamilyIdOuterClass.PokemonFamilyId.FAMILY_UNSET) { candyjar.setCandy( - itemData.getPokemonFamily().getFamilyId(), - itemData.getPokemonFamily().getCandy() + itemData.getCandy().getFamilyId(), + itemData.getCandy().getCandy() ); } // player stats if (itemData.hasPlayerStats()) { - api.getPlayerProfile().setStats(itemData.getPlayerStats()); + api.getPlayerProfile().setStats(new Stats(itemData.getPlayerStats())); } // pokedex @@ -159,7 +159,7 @@ public void updateInventories(boolean forceUpdate) throws LoginFailedException, } } - lastInventoryUpdate = System.currentTimeMillis(); + lastInventoryUpdate = api.currentTimeMillis(); } } } diff --git a/src/main/java/com/pokegoapi/api/inventory/Item.java b/src/main/java/com/pokegoapi/api/inventory/Item.java index f3b744cd..7c863465 100644 --- a/src/main/java/com/pokegoapi/api/inventory/Item.java +++ b/src/main/java/com/pokegoapi/api/inventory/Item.java @@ -38,4 +38,28 @@ public ItemId getItemId() { public boolean isUnseen() { return proto.getUnseen(); } + + /** + * Check if the item it's a potion + * + * @return true if the item it's a potion + */ + public boolean isPotion() { + return getItemId() == ItemId.ITEM_POTION + || getItemId() == ItemId.ITEM_SUPER_POTION + || getItemId() == ItemId.ITEM_HYPER_POTION + || getItemId() == ItemId.ITEM_MAX_POTION + ; + } + + /** + * Check if the item it's a revive + * + * @return true if the item it's a revive + */ + public boolean isRevive() { + return getItemId() == ItemId.ITEM_REVIVE + || getItemId() == ItemId.ITEM_MAX_REVIVE + ; + } } diff --git a/src/main/java/com/pokegoapi/api/inventory/ItemBag.java b/src/main/java/com/pokegoapi/api/inventory/ItemBag.java index 17f18897..cd7272ec 100644 --- a/src/main/java/com/pokegoapi/api/inventory/ItemBag.java +++ b/src/main/java/com/pokegoapi/api/inventory/ItemBag.java @@ -13,25 +13,29 @@ * along with this program. If not, see . */ - package com.pokegoapi.api.inventory; -import POGOProtos.Inventory.Item.ItemDataOuterClass; import POGOProtos.Inventory.Item.ItemDataOuterClass.ItemData; import POGOProtos.Inventory.Item.ItemIdOuterClass.ItemId; import POGOProtos.Networking.Requests.Messages.RecycleInventoryItemMessageOuterClass.RecycleInventoryItemMessage; -import POGOProtos.Networking.Requests.RequestTypeOuterClass; +import POGOProtos.Networking.Requests.Messages.UseIncenseMessageOuterClass.UseIncenseMessage; +import POGOProtos.Networking.Requests.Messages.UseItemXpBoostMessageOuterClass.UseItemXpBoostMessage; +import POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType; import POGOProtos.Networking.Responses.RecycleInventoryItemResponseOuterClass; import POGOProtos.Networking.Responses.RecycleInventoryItemResponseOuterClass.RecycleInventoryItemResponse.Result; +import POGOProtos.Networking.Responses.UseIncenseResponseOuterClass.UseIncenseResponse; +import POGOProtos.Networking.Responses.UseItemXpBoostResponseOuterClass.UseItemXpBoostResponse; import com.google.protobuf.InvalidProtocolBufferException; import com.pokegoapi.api.PokemonGo; import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; import com.pokegoapi.main.ServerRequest; +import com.pokegoapi.util.Log; import java.util.Collection; import java.util.HashMap; + /** * The type Bag. */ @@ -55,11 +59,15 @@ public void addItem(Item item) { /** * Remove item result. * - * @param id the id - * @param quantity the quantity + * @param id + * the id + * @param quantity + * the quantity * @return the result - * @throws RemoteServerException the remote server exception - * @throws LoginFailedException the login failed exception + * @throws RemoteServerException + * the remote server exception + * @throws LoginFailedException + * the login failed exception */ public Result removeItem(ItemId id, int quantity) throws RemoteServerException, LoginFailedException { Item item = getItem(id); @@ -67,32 +75,32 @@ public Result removeItem(ItemId id, int quantity) throws RemoteServerException, throw new IllegalArgumentException("You cannont remove more quantity than you have"); } - RecycleInventoryItemMessage msg = RecycleInventoryItemMessage.newBuilder() - .setItemId(id) - .setCount(quantity) + RecycleInventoryItemMessage msg = RecycleInventoryItemMessage.newBuilder().setItemId(id).setCount(quantity) .build(); - ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.RECYCLE_INVENTORY_ITEM, msg); + ServerRequest serverRequest = new ServerRequest(RequestType.RECYCLE_INVENTORY_ITEM, msg); pgo.getRequestHandler().sendServerRequests(serverRequest); RecycleInventoryItemResponseOuterClass.RecycleInventoryItemResponse response; try { - response = RecycleInventoryItemResponseOuterClass.RecycleInventoryItemResponse.parseFrom(serverRequest.getData()); + response = RecycleInventoryItemResponseOuterClass.RecycleInventoryItemResponse + .parseFrom(serverRequest.getData()); } catch (InvalidProtocolBufferException e) { throw new RemoteServerException(e); } - if (response.getResult() == RecycleInventoryItemResponseOuterClass.RecycleInventoryItemResponse.Result.SUCCESS) { + if (response + .getResult() == RecycleInventoryItemResponseOuterClass.RecycleInventoryItemResponse.Result.SUCCESS) { item.setCount(response.getNewCount()); } return response.getResult(); } - /** * Gets item. * - * @param type the type + * @param type + * the type * @return the item */ public Item getItem(ItemId type) { @@ -108,7 +116,6 @@ public Item getItem(ItemId type) { return items.get(type); } - public Collection getItems() { return items.values(); } @@ -117,6 +124,10 @@ public Collection getItems() { * Get used space inside of player inventory. * * @return used space + * @throws RemoteServerException + * the remote server exception + * @throws LoginFailedException + * the login failed exception */ public int getItemsCount() { int ct = 0; @@ -125,4 +136,87 @@ public int getItemsCount() { } return ct; } + + /** + * use an item with itemID + * @param type type of item + * @throws RemoteServerException + * the remote server exception + * @throws LoginFailedException + * the login failed exception + */ + public void useItem(ItemId type) throws RemoteServerException, LoginFailedException { + if (type == ItemId.UNRECOGNIZED) { + throw new IllegalArgumentException("You cannot use item for UNRECOGNIZED"); + } + + switch (type) { + case ITEM_INCENSE_ORDINARY: + case ITEM_INCENSE_SPICY: + case ITEM_INCENSE_COOL: + case ITEM_INCENSE_FLORAL: + useIncense(type); + break; + default: + break; + } + } + + /** + * use an incense + * @param type type of item + */ + public void useIncense(ItemId type) throws RemoteServerException, LoginFailedException { + UseIncenseMessage useIncenseMessage = + UseIncenseMessage.newBuilder() + .setIncenseType(type) + .setIncenseTypeValue(type.getNumber()) + .build(); + + ServerRequest useIncenseRequest = new ServerRequest(RequestType.USE_INCENSE, + useIncenseMessage); + pgo.getRequestHandler().sendServerRequests(useIncenseRequest); + + UseIncenseResponse response = null; + try { + response = UseIncenseResponse.parseFrom(useIncenseRequest.getData()); + Log.i("Main", "Use incense result: " + response.getResult()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + } + + + /** + * use an item with itemID + */ + public void useIncense() throws RemoteServerException, LoginFailedException { + useIncense(ItemId.ITEM_INCENSE_ORDINARY); + } + + /** + * use a lucky egg + * @returns lucky egg response + */ + public UseItemXpBoostResponse useLuckyEgg() throws RemoteServerException, LoginFailedException { + UseItemXpBoostMessage xpMsg = UseItemXpBoostMessage + .newBuilder() + .setItemId(ItemId.ITEM_LUCKY_EGG) + .build(); + + ServerRequest req = new ServerRequest(RequestType.USE_ITEM_XP_BOOST, + xpMsg); + pgo.getRequestHandler().sendServerRequests(req); + + UseItemXpBoostResponse response = null; + try { + response = UseItemXpBoostResponse.parseFrom(req.getData()); + Log.i("Main", "Use incense result: " + response.getResult()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + + return response; + } + } diff --git a/src/main/java/com/pokegoapi/api/inventory/PokeBank.java b/src/main/java/com/pokegoapi/api/inventory/PokeBank.java index e4e736c6..c1c31100 100644 --- a/src/main/java/com/pokegoapi/api/inventory/PokeBank.java +++ b/src/main/java/com/pokegoapi/api/inventory/PokeBank.java @@ -24,12 +24,13 @@ import lombok.Getter; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class PokeBank { @Getter - List pokemons = new ArrayList(); + List pokemons = Collections.synchronizedList(new ArrayList()); @Getter PokemonGo instance; diff --git a/src/main/java/com/pokegoapi/api/inventory/Stats.java b/src/main/java/com/pokegoapi/api/inventory/Stats.java index 3016e13d..24fbd46d 100644 --- a/src/main/java/com/pokegoapi/api/inventory/Stats.java +++ b/src/main/java/com/pokegoapi/api/inventory/Stats.java @@ -15,6 +15,102 @@ package com.pokegoapi.api.inventory; +import POGOProtos.Data.Player.PlayerStatsOuterClass; +import lombok.Getter; + public class Stats { + @Getter + private PlayerStatsOuterClass.PlayerStats proto; + + public Stats(PlayerStatsOuterClass.PlayerStats proto) { + this.proto = proto; + } + + public int getLevel() { + return proto.getLevel(); + } + + public long getExperience() { + return proto.getExperience(); + } + + public long getPrevLevelXp() { + return proto.getPrevLevelXp(); + } + + public long getNextLevelXp() { + return proto.getNextLevelXp(); + } + + public float getKmWalked() { + return proto.getKmWalked(); + } + + public int getPokemonsEncountered() { + return proto.getPokemonsEncountered(); + } + + public int getUniquePokedexEntries() { + return proto.getUniquePokedexEntries(); + } + + public int getPokemonsCaptured() { + return proto.getPokemonsCaptured(); + } + + public int getEvolutions() { + return proto.getEvolutions(); + } + + public int getPokeStopVisits() { + return proto.getPokeStopVisits(); + } + + public int getPokeballsThrown() { + return proto.getPokeballsThrown(); + } + + public int getEggsHatched() { + return proto.getEggsHatched(); + } + + public int getBigMagikarpCaught() { + return proto.getBigMagikarpCaught(); + } + + public int getBattleAttackWon() { + return proto.getBattleAttackWon(); + } + + public int getBattleAttackTotal() { + return proto.getBattleAttackTotal(); + } + + public int getBattleDefendedWon() { + return proto.getBattleDefendedWon(); + } + + public int getBattleTrainingWon() { + return proto.getBattleTrainingWon(); + } + + public int getBattleTrainingTotal() { + return proto.getBattleTrainingTotal(); + } + + public int getPrestigeRaisedTotal() { + return proto.getPrestigeRaisedTotal(); + } + + public int getPrestigeDroppedTotal() { + return proto.getPrestigeDroppedTotal(); + } + + public int getPokemonDeployed() { + return proto.getPokemonDeployed(); + } + public int getSmallRattataCaught() { + return proto.getSmallRattataCaught(); + } } diff --git a/src/main/java/com/pokegoapi/api/map/Map.java b/src/main/java/com/pokegoapi/api/map/Map.java index b1cf1109..612c130e 100644 --- a/src/main/java/com/pokegoapi/api/map/Map.java +++ b/src/main/java/com/pokegoapi/api/map/Map.java @@ -18,7 +18,8 @@ import POGOProtos.Inventory.Item.ItemIdOuterClass.ItemId; import POGOProtos.Map.Fort.FortDataOuterClass.FortData; import POGOProtos.Map.Fort.FortTypeOuterClass.FortType; -import POGOProtos.Map.MapCellOuterClass; +import POGOProtos.Map.MapCellOuterClass.MapCell; +import POGOProtos.Map.Pokemon.MapPokemonOuterClass; import POGOProtos.Map.Pokemon.MapPokemonOuterClass.MapPokemon; import POGOProtos.Map.Pokemon.NearbyPokemonOuterClass; import POGOProtos.Map.Pokemon.WildPokemonOuterClass; @@ -29,21 +30,22 @@ import POGOProtos.Networking.Requests.Messages.FortSearchMessageOuterClass.FortSearchMessage; import POGOProtos.Networking.Requests.Messages.GetMapObjectsMessageOuterClass; import POGOProtos.Networking.Requests.Messages.GetMapObjectsMessageOuterClass.GetMapObjectsMessage; -import POGOProtos.Networking.Requests.RequestTypeOuterClass; +import POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType; import POGOProtos.Networking.Responses.CatchPokemonResponseOuterClass.CatchPokemonResponse; import POGOProtos.Networking.Responses.EncounterResponseOuterClass.EncounterResponse; import POGOProtos.Networking.Responses.FortDetailsResponseOuterClass; import POGOProtos.Networking.Responses.FortSearchResponseOuterClass.FortSearchResponse; -import POGOProtos.Networking.Responses.GetMapObjectsResponseOuterClass; - +import POGOProtos.Networking.Responses.GetMapObjectsResponseOuterClass.GetMapObjectsResponse; import com.annimon.stream.Collectors; import com.annimon.stream.Stream; import com.annimon.stream.function.Function; import com.annimon.stream.function.Predicate; +import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import com.pokegoapi.api.PokemonGo; -import com.pokegoapi.api.map.fort.FortDetails; import com.pokegoapi.api.gym.Gym; +import com.pokegoapi.api.map.fort.FortDetails; +import com.pokegoapi.api.map.fort.Pokestop; import com.pokegoapi.api.map.pokemon.CatchablePokemon; import com.pokegoapi.api.map.pokemon.NearbyPokemon; import com.pokegoapi.exceptions.LoginFailedException; @@ -51,10 +53,11 @@ import com.pokegoapi.google.common.geometry.MutableInteger; import com.pokegoapi.google.common.geometry.S2CellId; import com.pokegoapi.google.common.geometry.S2LatLng; +import com.pokegoapi.main.AsyncServerRequest; import com.pokegoapi.main.ServerRequest; - -import lombok.Getter; -import lombok.Setter; +import com.pokegoapi.util.FutureWrapper; +import com.pokegoapi.util.MapUtil; +import com.pokegoapi.util.PokemonFuture; import java.util.ArrayList; import java.util.HashSet; @@ -63,93 +66,174 @@ public class Map { - + private static int CELL_WIDTH = 3; + // time between getting a new MapObjects + private static int RESEND_REQUEST = 5000; private final PokemonGo api; private MapObjects cachedMapObjects; - @Getter - @Setter - private boolean useCache; - - @Setter - @Getter - private long mapObjectsExpiry; - + private List cachedCatchable; private long lastMapUpdate; /** * Instantiates a new Map. * * @param api the api + * @throws LoginFailedException if the login failed + * @throws RemoteServerException When a buffer exception is thrown */ - public Map(PokemonGo api) { + public Map(PokemonGo api) throws LoginFailedException, RemoteServerException { this.api = api; cachedMapObjects = new MapObjects(api); lastMapUpdate = 0; - useCache = true; } - public void clearCache() { - this.lastMapUpdate = 0; - this.cachedMapObjects = new MapObjects(api); - } /** * Returns a list of catchable pokemon around the current location. * * @return a List of CatchablePokemon at your current location */ - public List getCatchablePokemon() throws LoginFailedException, RemoteServerException { - Set catchablePokemons = new HashSet<>(); - MapObjects objects = getMapObjects(); - - for (MapPokemon mapPokemon : objects.getCatchablePokemons()) { - catchablePokemons.add(new CatchablePokemon(api, mapPokemon)); - } + public PokemonFuture> getCatchablePokemonAsync() { - for (WildPokemonOuterClass.WildPokemon wildPokemon : objects.getWildPokemons()) { - catchablePokemons.add(new CatchablePokemon(api, wildPokemon)); + if (useCache() && cachedCatchable != null) { + return FutureWrapper.just(cachedCatchable); } - // TODO: Check if this code is correct; merged because this contains many other fixes - /*for (Pokestop pokestop : objects.getPokestops()) { - if (pokestop.inRange() && pokestop.hasLurePokemon()) { - catchablePokemons.add(new CatchablePokemon(api, pokestop.getFortData())); + List cellIds = getDefaultCells(); + return new FutureWrapper>(getMapObjectsAsync(cellIds)) { + @Override + protected List handle(MapObjects mapObjects) throws RemoteServerException { + Set catchablePokemons = new HashSet<>(); + for (MapPokemon mapPokemon : mapObjects.getCatchablePokemons()) { + catchablePokemons.add(new CatchablePokemon(api, mapPokemon)); + } + + for (WildPokemonOuterClass.WildPokemon wildPokemon : mapObjects.getWildPokemons()) { + catchablePokemons.add(new CatchablePokemon(api, wildPokemon)); + } + + /* + TODO: i have more success checking if encounterId > 0 + i don't want to use the hasLure because it do a request every call + */ + for (Pokestop pokestop : mapObjects.getPokestops()) { + if (pokestop.inRange() + && pokestop.getFortData().hasLureInfo() + && pokestop.getFortData().getLureInfo().getEncounterId() > 0) { + //if (pokestop.inRange() && pokestop.hasLurePokemon()) { + catchablePokemons.add(new CatchablePokemon(api, pokestop.getFortData())); + } + } + + cachedCatchable = new ArrayList<>(catchablePokemons); + return cachedCatchable; } - }*/ + }; + } - return new ArrayList<>(catchablePokemons); + /** + * Returns a list of catchable pokemon around the current location. + * + * @return a List of CatchablePokemon at your current location + */ + public List getCatchablePokemon() throws LoginFailedException, RemoteServerException { + return getCatchablePokemonAsync().toBlocking(); + } + + /** + * Gets catchable pokemon sort by distance. + * + * @return the catchable pokemon sort + * @throws LoginFailedException the login failed exception + * @throws RemoteServerException the remote server exception + */ + public java.util.Map getCatchablePokemonSort() + throws LoginFailedException, RemoteServerException { + MapUtil util = new MapUtil<>(); + return util.sortItems(getCatchablePokemon(), api); + } + + /** + * Returns a list of nearby pokemon (non-catchable). + * + * @return a List of NearbyPokemon at your current location + * @throws LoginFailedException if the login failed + * @throws RemoteServerException When a buffer exception is thrown + */ + public PokemonFuture> getNearbyPokemonAsync() { + return new FutureWrapper>(getMapObjectsAsync(getDefaultCells())) { + @Override + protected List handle(MapObjects result) throws RemoteServerException { + List pokemons = new ArrayList<>(); + for (NearbyPokemonOuterClass.NearbyPokemon pokemon : result.getNearbyPokemons()) { + pokemons.add(new NearbyPokemon(pokemon)); + } + + return pokemons; + } + }; } /** * Returns a list of nearby pokemon (non-catchable). * * @return a List of NearbyPokemon at your current location + * @throws LoginFailedException if the login failed + * @throws RemoteServerException When a buffer exception is thrown */ public List getNearbyPokemon() throws LoginFailedException, RemoteServerException { - List pokemons = new ArrayList<>(); - MapObjects objects = getMapObjects(); + return getNearbyPokemonAsync().toBlocking(); + } - for (NearbyPokemonOuterClass.NearbyPokemon pokemon : objects.getNearbyPokemons()) { - pokemons.add(new NearbyPokemon(pokemon)); - } + /** + * Returns a list of spawn points. + * + * @return list of spawn points + */ + public PokemonFuture> getSpawnPointsAsync() { + return new FutureWrapper>(getMapObjectsAsync(getDefaultCells())) { + @Override + protected List handle(MapObjects result) throws RemoteServerException { + List points = new ArrayList<>(); - return pokemons; + for (SpawnPointOuterClass.SpawnPoint point : result.getSpawnPoints()) { + points.add(new Point(point)); + } + + return points; + } + }; } /** * Returns a list of spawn points. * * @return list of spawn points + * @throws LoginFailedException if the login failed + * @throws RemoteServerException When a buffer exception is thrown */ public List getSpawnPoints() throws LoginFailedException, RemoteServerException { - List points = new ArrayList<>(); - MapObjects objects = getMapObjects(); + return getSpawnPointsAsync().toBlocking(); + } - for (SpawnPointOuterClass.SpawnPoint point : objects.getSpawnPoints()) { - points.add(new Point(point)); - } + /** + * Get a list of gyms near the current location. + * + * @return List of gyms + */ + public PokemonFuture> getGymsAsync() { + return new FutureWrapper>(getMapObjectsAsync(getDefaultCells())) { + @Override + protected List handle(MapObjects result) throws RemoteServerException { + List gyms = new ArrayList<>(); - return points; + for (FortData fortdata : result.getGyms()) { + gyms.add(new Gym(api, fortdata)); + } + + return gyms; + } + }; } /** @@ -158,41 +242,156 @@ public List getSpawnPoints() throws LoginFailedException, RemoteServerExc * @return List of gyms */ public List getGyms() throws LoginFailedException, RemoteServerException { - List gyms = new ArrayList<>(); - MapObjects objects = getMapObjects(); - - for (FortData fortdata : objects.getGyms()) { - gyms.add(new Gym(api, fortdata)); - } - - return gyms; + return getGymsAsync().toBlocking(); } + /** + * Gets gym sort by distance. + * + * @return the gym sort + * @throws LoginFailedException the login failed exception + * @throws RemoteServerException the remote server exception + */ + public java.util.Map getGymSort() throws LoginFailedException, RemoteServerException { + MapUtil util = new MapUtil<>(); + return util.sortItems(getGyms(), api); + } + /** + * Returns a list of decimated spawn points at current location. + * + * @return list of spawn points + */ + public PokemonFuture> getDecimatedSpawnPointsAsync() { + return new FutureWrapper>(getMapObjectsAsync(getDefaultCells())) { + @Override + protected List handle(MapObjects result) throws RemoteServerException { + List points = new ArrayList<>(); + for (SpawnPointOuterClass.SpawnPoint point : result.getDecimatedSpawnPoints()) { + points.add(new Point(point)); + } + + return points; + } + }; + } /** * Returns a list of decimated spawn points at current location. * * @return list of spawn points + * @throws LoginFailedException if the login failed + * @throws RemoteServerException When a buffer exception is thrown */ public List getDecimatedSpawnPoints() throws LoginFailedException, RemoteServerException { - List points = new ArrayList<>(); - MapObjects objects = getMapObjects(); + return getDecimatedSpawnPointsAsync().toBlocking(); + } + + + /** + * Gets decimated spawn points sort by distance. + * + * @return the decimated spawn points sort + * @throws LoginFailedException the login failed exception + * @throws RemoteServerException the remote server exception + */ + public java.util.Map getDecimatedSpawnPointsSort() throws LoginFailedException, RemoteServerException { + MapUtil util = new MapUtil<>(); + return util.sortItems(getDecimatedSpawnPoints(), api); + } + + /** + * Returns MapObjects around your current location. + * + * @return MapObjects at your current location + */ + public PokemonFuture getMapObjectsAsync() { + return getMapObjectsAsync(getDefaultCells()); + } - for (SpawnPointOuterClass.SpawnPoint point : objects.getDecimatedSpawnPoints()) { - points.add(new Point(point)); + /** + * Returns MapObjects around your current location within a given width. + * + * @param width width + * @return MapObjects at your current location + */ + public PokemonFuture getMapObjectsAsync(int width) { + return getMapObjectsAsync(getCellIds(api.getLatitude(), api.getLongitude(), width)); + } + + /** + * Returns the cells requested. + * + * @param cellIds List of cellId + * @return MapObjects in the given cells + */ + public PokemonFuture getMapObjectsAsync(List cellIds) { + + if (useCache()) { + return FutureWrapper.just(cachedMapObjects); } - return points; + lastMapUpdate = api.currentTimeMillis(); + GetMapObjectsMessage.Builder builder = GetMapObjectsMessageOuterClass.GetMapObjectsMessage.newBuilder() + .setLatitude(api.getLatitude()) + .setLongitude(api.getLongitude()); + + int index = 0; + for (Long cellId : cellIds) { + builder.addCellId(cellId); + long time = 0; + builder.addSinceTimestampMs(0); + index++; + + } + final AsyncServerRequest asyncServerRequest = new AsyncServerRequest( + RequestType.GET_MAP_OBJECTS, builder.build()); + return new FutureWrapper(api.getRequestHandler() + .sendAsyncServerRequests(asyncServerRequest)) { + @Override + protected MapObjects handle(ByteString byteString) throws RemoteServerException { + GetMapObjectsResponse response; + try { + response = GetMapObjectsResponse.parseFrom(byteString); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + + MapObjects result = new MapObjects(api); + cachedMapObjects = result; + for (MapCell mapCell : response.getMapCellsList()) { + result.addNearbyPokemons(mapCell.getNearbyPokemonsList()); + result.addCatchablePokemons(mapCell.getCatchablePokemonsList()); + result.addWildPokemons(mapCell.getWildPokemonsList()); + result.addDecimatedSpawnPoints(mapCell.getDecimatedSpawnPointsList()); + result.addSpawnPoints(mapCell.getSpawnPointsList()); + + java.util.Map> groupedForts = Stream.of(mapCell.getFortsList()) + .collect(Collectors.groupingBy(new Function() { + @Override + public FortType apply(FortData fortData) { + return fortData.getType(); + } + })); + result.addGyms(groupedForts.get(FortType.GYM)); + result.addPokestops(groupedForts.get(FortType.CHECKPOINT)); + } + + + return result; + } + }; } /** * Returns MapObjects around your current location. * * @return MapObjects at your current location + * @throws LoginFailedException if the login failed + * @throws RemoteServerException When a buffer exception is thrown */ public MapObjects getMapObjects() throws LoginFailedException, RemoteServerException { - return getMapObjects(9); + return getMapObjectsAsync().toBlocking(); } /** @@ -200,29 +399,26 @@ public MapObjects getMapObjects() throws LoginFailedException, RemoteServerExcep * * @param width width * @return MapObjects at your current location + * @throws LoginFailedException If login fails. + * @throws RemoteServerException If request errors occurred. */ public MapObjects getMapObjects(int width) throws LoginFailedException, RemoteServerException { - return getMapObjects( - getCellIds( - api.getLatitude(), - api.getLongitude(), - width), - api.getLatitude(), - api.getLongitude(), - api.getAltitude()); + return getMapObjectsAsync(width).toBlocking(); } /** - * Returns 9x9 cells with the requested lattitude/longitude in the center cell. + * Returns 5x5 cells with the requested lattitude/longitude in the center cell. * * @param latitude latitude * @param longitude longitude * @return MapObjects in the given cells + * @throws LoginFailedException if the login failed + * @throws RemoteServerException When a buffer exception is thrown */ @Deprecated public MapObjects getMapObjects(double latitude, double longitude) throws LoginFailedException, RemoteServerException { - return getMapObjects(latitude, longitude, 9); + return getMapObjects(latitude, longitude, CELL_WIDTH); } /** @@ -232,6 +428,8 @@ public MapObjects getMapObjects(double latitude, double longitude) * @param latitude latitude * @param longitude longitude * @return MapObjects in the given cells + * @throws LoginFailedException if the login failed + * @throws RemoteServerException When a buffer exception is thrown */ @Deprecated public MapObjects getMapObjects(List cellIds, double latitude, double longitude) @@ -246,6 +444,8 @@ public MapObjects getMapObjects(List cellIds, double latitude, double long * @param longitude longitude * @param width width * @return MapObjects in the given cells + * @throws LoginFailedException if the login failed + * @throws RemoteServerException When a buffer exception is thrown */ @Deprecated public MapObjects getMapObjects(double latitude, double longitude, int width) @@ -259,7 +459,10 @@ public MapObjects getMapObjects(double latitude, double longitude, int width) * @param cellIds cellIds * @param latitude latitude * @param longitude longitude + * @param altitude altitude * @return MapObjects in the given cells + * @throws LoginFailedException if the login failed + * @throws RemoteServerException When a buffer exception is thrown */ @Deprecated public MapObjects getMapObjects(List cellIds, double latitude, double longitude, double altitude) @@ -275,66 +478,11 @@ public MapObjects getMapObjects(List cellIds, double latitude, double long * * @param cellIds List of cellId * @return MapObjects in the given cells + * @throws LoginFailedException if the login failed + * @throws RemoteServerException When a buffer exception is thrown */ public MapObjects getMapObjects(List cellIds) throws LoginFailedException, RemoteServerException { - GetMapObjectsMessage.Builder builder = GetMapObjectsMessage.newBuilder(); - - if (useCache && (System.currentTimeMillis() - lastMapUpdate > mapObjectsExpiry)) { - lastMapUpdate = 0; - cachedMapObjects = new MapObjects(api); - } - - builder = GetMapObjectsMessageOuterClass.GetMapObjectsMessage.newBuilder() - .setLatitude(api.getLatitude()) - .setLongitude(api.getLongitude()); - - int index = 0; - for (Long cellId : cellIds) { - builder.addCellId(cellId); - long time = 0; - - builder.addSinceTimestampMs(lastMapUpdate); - index++; - - } - - ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.GET_MAP_OBJECTS, builder.build()); - api.getRequestHandler().sendServerRequests(serverRequest); - GetMapObjectsResponseOuterClass.GetMapObjectsResponse response = null; - try { - response = GetMapObjectsResponseOuterClass.GetMapObjectsResponse.parseFrom(serverRequest.getData()); - } catch (InvalidProtocolBufferException e) { - throw new RemoteServerException(e); - } - - MapObjects result = new MapObjects(api); - for (MapCellOuterClass.MapCell mapCell : response.getMapCellsList()) { - result.addNearbyPokemons(mapCell.getNearbyPokemonsList()); - result.addCatchablePokemons(mapCell.getCatchablePokemonsList()); - result.addWildPokemons(mapCell.getWildPokemonsList()); - result.addDecimatedSpawnPoints(mapCell.getDecimatedSpawnPointsList()); - result.addSpawnPoints(mapCell.getSpawnPointsList()); - - - - java.util.Map> groupedForts = Stream.of(mapCell.getFortsList()) - .collect(Collectors.groupingBy(new Function() { - @Override - public FortType apply(FortData fortData) { - return fortData.getType(); - } - })); - result.addGyms(groupedForts.get(FortType.GYM)); - result.addPokestops(groupedForts.get(FortType.CHECKPOINT)); - } - - if (useCache) { - cachedMapObjects.update(result); - result = cachedMapObjects; - lastMapUpdate = System.currentTimeMillis(); - } - - return result; + return getMapObjectsAsync(cellIds).toBlocking(); } /** @@ -362,7 +510,8 @@ public List getCellIds(double latitude, double longitude, int width) { int halfWidth = (int) Math.floor(width / 2); for (int x = -halfWidth; x <= halfWidth; x++) { for (int y = -halfWidth; y <= halfWidth; y++) { - cells.add(S2CellId.fromFaceIJ(face, index.intValue() + x * size, jindex.intValue() + y * size).parent(15).id()); + cells.add(S2CellId.fromFaceIJ(face, index.intValue() + x * size, jindex.intValue() + y * size) + .parent(15).id()); } } return cells; @@ -375,25 +524,44 @@ public List getCellIds(double latitude, double longitude, int width) { * @param lon the lon * @param lat the lat * @return the fort details - * @throws LoginFailedException the login failed exception - * @throws RemoteServerException the remote server exception */ - public FortDetails getFortDetails(String id, long lon, long lat) throws LoginFailedException, RemoteServerException { + public PokemonFuture getFortDetailsAsync(String id, double lon, double lat) { FortDetailsMessage reqMsg = FortDetailsMessage.newBuilder() .setFortId(id) .setLatitude(lat) .setLongitude(lon) .build(); - ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.FORT_DETAILS, reqMsg); - api.getRequestHandler().sendServerRequests(serverRequest); - FortDetailsResponseOuterClass.FortDetailsResponse response = null; - try { - response = FortDetailsResponseOuterClass.FortDetailsResponse.parseFrom(serverRequest.getData()); - } catch (InvalidProtocolBufferException e) { - throw new RemoteServerException(e); - } - return new FortDetails(response); + AsyncServerRequest serverRequest = new AsyncServerRequest(RequestType.FORT_DETAILS, + reqMsg); + return new FutureWrapper(api.getRequestHandler() + .sendAsyncServerRequests(serverRequest)) { + @Override + protected FortDetails handle(ByteString byteString) throws RemoteServerException { + FortDetailsResponseOuterClass.FortDetailsResponse response; + try { + response = FortDetailsResponseOuterClass.FortDetailsResponse.parseFrom(byteString); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + return new FortDetails(response); + } + }; + } + + /** + * Gets fort details. + * + * @param id the id + * @param lon the lon + * @param lat the lat + * @return the fort details + * @throws LoginFailedException the login failed exception + * @throws RemoteServerException the remote server exception + */ + public FortDetails getFortDetails(String id, double lon, double lat) + throws LoginFailedException, RemoteServerException { + return getFortDetailsAsync(id, lon, lat).toBlocking(); } /** @@ -413,7 +581,7 @@ public FortSearchResponse searchFort(FortData fortData) throws LoginFailedExcept .setPlayerLatitude(api.getLatitude()) .setPlayerLongitude(api.getLongitude()) .build(); - ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.FORT_SEARCH, reqMsg); + ServerRequest serverRequest = new ServerRequest(RequestType.FORT_SEARCH, reqMsg); api.getRequestHandler().sendServerRequests(serverRequest); @@ -444,7 +612,7 @@ public EncounterResponse encounterPokemon(MapPokemon catchablePokemon) .setPlayerLongitude(api.getLongitude()) .setSpawnPointId(catchablePokemon.getSpawnPointId()) .build(); - ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.ENCOUNTER, reqMsg); + ServerRequest serverRequest = new ServerRequest(RequestType.ENCOUNTER, reqMsg); api.getRequestHandler().sendServerRequests(serverRequest); EncounterResponse response; @@ -486,7 +654,7 @@ public CatchPokemonResponse catchPokemon( .setSpinModifier(spinModifier) .setPokeball(pokeball) .build(); - ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.CATCH_POKEMON, reqMsg); + ServerRequest serverRequest = new ServerRequest(RequestType.CATCH_POKEMON, reqMsg); api.getRequestHandler().sendServerRequests(serverRequest); CatchPokemonResponse response; @@ -497,4 +665,18 @@ public CatchPokemonResponse catchPokemon( } return response; } + + /** + * Wether or not to get a fresh copy or use cache; + * + * @return true if enough time has elapsed since the last request, false otherwise + */ + private boolean useCache() { + return (api.currentTimeMillis() - lastMapUpdate) < RESEND_REQUEST; + } + + private List getDefaultCells() { + return getCellIds(api.getLatitude(), api.getLongitude(), CELL_WIDTH); + } + } diff --git a/src/main/java/com/pokegoapi/api/map/MapObjects.java b/src/main/java/com/pokegoapi/api/map/MapObjects.java index 08488170..dd3c16c3 100644 --- a/src/main/java/com/pokegoapi/api/map/MapObjects.java +++ b/src/main/java/com/pokegoapi/api/map/MapObjects.java @@ -15,7 +15,6 @@ package com.pokegoapi.api.map; -import POGOProtos.Map.Fort.FortDataOuterClass; import POGOProtos.Map.Fort.FortDataOuterClass.FortData; import POGOProtos.Map.Pokemon.MapPokemonOuterClass.MapPokemon; import POGOProtos.Map.Pokemon.NearbyPokemonOuterClass.NearbyPokemon; @@ -28,24 +27,25 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; @ToString public class MapObjects { @Getter - Collection nearbyPokemons = new ArrayList(); + Collection nearbyPokemons = Collections.synchronizedCollection(new ArrayList()); @Getter - Collection catchablePokemons = new ArrayList(); + Collection catchablePokemons = Collections.synchronizedCollection(new ArrayList()); @Getter - Collection wildPokemons = new ArrayList(); + Collection wildPokemons = Collections.synchronizedCollection(new ArrayList()); @Getter - Collection decimatedSpawnPoints = new ArrayList(); + Collection decimatedSpawnPoints = Collections.synchronizedCollection(new ArrayList()); @Getter - Collection spawnPoints = new ArrayList(); + Collection spawnPoints = Collections.synchronizedCollection(new ArrayList()); @Getter - Collection gyms = new ArrayList(); + Collection gyms = Collections.synchronizedCollection(new ArrayList()); @Getter - Collection pokestops = new ArrayList<>(); + Collection pokestops = Collections.synchronizedCollection(new ArrayList()); boolean complete = false; private PokemonGo api; @@ -146,7 +146,7 @@ public void addPokestops(Collection pokestops) { return; } complete = true; - for (FortData pokestop : pokestops) { + for (FortData pokestop: pokestops) { this.pokestops.add(new Pokestop(api, pokestop)); } } @@ -164,9 +164,9 @@ public boolean isComplete() { /** * updates the object. - * - * + * @param other Update this {@link MapObjects} data with the provided data. */ + @Deprecated public void update(MapObjects other) { nearbyPokemons.clear(); @@ -184,8 +184,11 @@ public void update(MapObjects other) { spawnPoints.clear(); addSpawnPoints(other.getSpawnPoints()); - for (FortData otherGym : other.getGyms()) { - for (FortData gym : getGyms()) { + + /* for (FortData otherGym: other.getGyms()) { + Iterator iterator = gyms.iterator(); + while (iterator.hasNext()) { + FortData gym = iterator.next(); if (otherGym.getId().equals(gym.getId())) { gyms.remove(gym); break; @@ -194,14 +197,16 @@ public void update(MapObjects other) { gyms.add(otherGym); } - for (Pokestop otherPokestop : other.getPokestops()) { - for (Pokestop pokestop : pokestops) { + /*for (Pokestop otherPokestop: other.getPokestops()) { + Iterator iterator = pokestops.iterator(); + while (iterator.hasNext()) { + Pokestop pokestop = iterator.next(); if (otherPokestop.getId().equals(pokestop.getId())) { pokestops.remove(pokestop); break; } } pokestops.add(otherPokestop); - } + }*/ } } \ No newline at end of file diff --git a/src/main/java/com/pokegoapi/api/map/Point.java b/src/main/java/com/pokegoapi/api/map/Point.java index 6502190d..2ecb3cad 100644 --- a/src/main/java/com/pokegoapi/api/map/Point.java +++ b/src/main/java/com/pokegoapi/api/map/Point.java @@ -16,10 +16,11 @@ package com.pokegoapi.api.map; import POGOProtos.Map.SpawnPointOuterClass; +import com.pokegoapi.util.MapPoint; import lombok.Getter; import lombok.Setter; -public class Point { +public class Point implements MapPoint { @Getter @Setter private double longitude; diff --git a/src/main/java/com/pokegoapi/api/map/fort/Pokestop.java b/src/main/java/com/pokegoapi/api/map/fort/Pokestop.java index 5ab31826..215b392d 100644 --- a/src/main/java/com/pokegoapi/api/map/fort/Pokestop.java +++ b/src/main/java/com/pokegoapi/api/map/fort/Pokestop.java @@ -17,6 +17,7 @@ import POGOProtos.Inventory.Item.ItemIdOuterClass; import POGOProtos.Map.Fort.FortDataOuterClass; +import POGOProtos.Map.Fort.FortModifierOuterClass; import POGOProtos.Networking.Requests.Messages.AddFortModifierMessageOuterClass.AddFortModifierMessage; import POGOProtos.Networking.Requests.Messages.FortDetailsMessageOuterClass.FortDetailsMessage; import POGOProtos.Networking.Requests.Messages.FortSearchMessageOuterClass.FortSearchMessage; @@ -24,14 +25,19 @@ import POGOProtos.Networking.Responses.AddFortModifierResponseOuterClass; import POGOProtos.Networking.Responses.FortDetailsResponseOuterClass; import POGOProtos.Networking.Responses.FortSearchResponseOuterClass; +import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import com.pokegoapi.api.PokemonGo; import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; import com.pokegoapi.google.common.geometry.S2LatLng; -import com.pokegoapi.main.ServerRequest; +import com.pokegoapi.main.AsyncServerRequest; +import com.pokegoapi.util.FutureWrapper; +import com.pokegoapi.util.PokemonFuture; import lombok.Getter; +import java.util.List; + /** * Created by mjmfighter on 7/20/2016. */ @@ -58,6 +64,7 @@ public Pokestop(PokemonGo api, FortDataOuterClass.FortData fortData) { /** * Returns whether or not a pokestop is in range. + * * @return true when in range of player */ public boolean inRange() { @@ -69,6 +76,7 @@ public boolean inRange() { /** * can user loot this from current position. + * * @return true when lootable */ public boolean canLoot() { @@ -82,7 +90,7 @@ public boolean canLoot() { * @return the boolean */ public boolean canLoot(boolean ignoreDistance) { - boolean active = cooldownCompleteTimestampMs < System.currentTimeMillis(); + boolean active = cooldownCompleteTimestampMs < api.currentTimeMillis(); if (!ignoreDistance) { return active && inRange(); } @@ -105,10 +113,8 @@ public double getLongitude() { * Loots a pokestop for pokeballs and other items. * * @return PokestopLootResult - * @throws LoginFailedException if login failed - * @throws RemoteServerException if the server failed to respond */ - public PokestopLootResult loot() throws LoginFailedException, RemoteServerException { + public PokemonFuture lootAsync() { FortSearchMessage searchMessage = FortSearchMessage.newBuilder() .setFortId(getId()) .setFortLatitude(getLatitude()) @@ -117,73 +123,137 @@ public PokestopLootResult loot() throws LoginFailedException, RemoteServerExcept .setPlayerLongitude(api.getLongitude()) .build(); - ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.FORT_SEARCH, searchMessage); - api.getRequestHandler().sendServerRequests(serverRequest); - FortSearchResponseOuterClass.FortSearchResponse response; - try { - response = FortSearchResponseOuterClass.FortSearchResponse.parseFrom(serverRequest.getData()); - } catch (InvalidProtocolBufferException e) { - throw new RemoteServerException(e); - } - cooldownCompleteTimestampMs = response.getCooldownCompleteTimestampMs(); - return new PokestopLootResult(response); + AsyncServerRequest serverRequest = new AsyncServerRequest(RequestTypeOuterClass.RequestType.FORT_SEARCH, + searchMessage); + return new FutureWrapper(api.getRequestHandler() + .sendAsyncServerRequests(serverRequest)) { + @Override + protected PokestopLootResult handle(ByteString result) throws RemoteServerException, LoginFailedException { + FortSearchResponseOuterClass.FortSearchResponse response; + try { + response = FortSearchResponseOuterClass.FortSearchResponse.parseFrom(result); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + cooldownCompleteTimestampMs = response.getCooldownCompleteTimestampMs(); + return new PokestopLootResult(response); + } + }; + } + + /** + * Loots a pokestop for pokeballs and other items. + * + * @return PokestopLootResult + * @throws LoginFailedException if login failed + * @throws RemoteServerException if the server failed to respond + */ + public PokestopLootResult loot() throws LoginFailedException, RemoteServerException { + return lootAsync().toBlocking(); } /** * Adds a modifier to this pokestop. (i.e. add a lure module) * * @param item the modifier to add to this pokestop - * @throws LoginFailedException if login failed - * @throws RemoteServerException if the server failed to respond or the modifier could not be added to this pokestop */ - public void addModifier(ItemIdOuterClass.ItemId item) throws LoginFailedException, RemoteServerException { + public PokemonFuture addModifierAsync(ItemIdOuterClass.ItemId item) { AddFortModifierMessage msg = AddFortModifierMessage.newBuilder() .setModifierType(item) .setFortId(getId()) .setPlayerLatitude(api.getLatitude()) .setPlayerLongitude(api.getLongitude()) .build(); - ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.ADD_FORT_MODIFIER, msg); - api.getRequestHandler().sendServerRequests(serverRequest); - AddFortModifierResponseOuterClass.AddFortModifierResponse response; - try { - //sadly the server response does not contain any information to verify if the request was successful - response = AddFortModifierResponseOuterClass.AddFortModifierResponse.parseFrom(serverRequest.getData()); - } catch (InvalidProtocolBufferException e) { - throw new RemoteServerException(e); - } + AsyncServerRequest serverRequest = new AsyncServerRequest(RequestTypeOuterClass.RequestType.ADD_FORT_MODIFIER, msg); + return new FutureWrapper(api.getRequestHandler().sendAsyncServerRequests(serverRequest)) { + @Override + protected Boolean handle(ByteString result) throws RemoteServerException, LoginFailedException { + try { + //sadly the server response does not contain any information to verify if the request was successful + AddFortModifierResponseOuterClass.AddFortModifierResponse.parseFrom(result); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + return Boolean.TRUE; + } + }; + } + + /** + * Adds a modifier to this pokestop. (i.e. add a lure module) + * + * @param item the modifier to add to this pokestop + * @throws LoginFailedException if login failed + * @throws RemoteServerException if the server failed to respond or the modifier could not be added to this pokestop + */ + public void addModifier(ItemIdOuterClass.ItemId item) throws LoginFailedException, RemoteServerException { + addModifierAsync(item).toBlocking(); } /** * Get more detailed information about a pokestop. * * @return FortDetails - * @throws LoginFailedException if login failed - * @throws RemoteServerException if the server failed to respond */ - public FortDetails getDetails() throws LoginFailedException, RemoteServerException { + public PokemonFuture getDetailsAsync() { FortDetailsMessage reqMsg = FortDetailsMessage.newBuilder() .setFortId(getId()) .setLatitude(getLatitude()) .setLongitude(getLongitude()) .build(); - ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.FORT_DETAILS, reqMsg); - api.getRequestHandler().sendServerRequests(serverRequest); - FortDetailsResponseOuterClass.FortDetailsResponse response = null; - try { - response = FortDetailsResponseOuterClass.FortDetailsResponse.parseFrom(serverRequest.getData()); - } catch (InvalidProtocolBufferException e) { - throw new RemoteServerException(e); - } - return new FortDetails(response); + AsyncServerRequest serverRequest = new AsyncServerRequest(RequestTypeOuterClass.RequestType.FORT_DETAILS, reqMsg); + return new FutureWrapper(api.getRequestHandler().sendAsyncServerRequests(serverRequest)) { + @Override + protected FortDetails handle(ByteString result) throws RemoteServerException, LoginFailedException { + FortDetailsResponseOuterClass.FortDetailsResponse response = null; + try { + response = FortDetailsResponseOuterClass.FortDetailsResponse.parseFrom(result); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + return new FortDetails(response); + } + }; + } + + + /** + * Get more detailed information about a pokestop. + * + * @return FortDetails + * @throws LoginFailedException if login failed + * @throws RemoteServerException if the server failed to respond + */ + public FortDetails getDetails() throws LoginFailedException, RemoteServerException { + return getDetailsAsync().toBlocking(); } /** * Returns whether this pokestop has an active lure. + * * @return lure status */ + @Deprecated public boolean hasLurePokemon() { - return fortData.hasLureInfo() && fortData.getLureInfo().getLureExpiresTimestampMs() < System.currentTimeMillis(); + return fortData.hasLureInfo() && fortData.getLureInfo().getLureExpiresTimestampMs() > api.currentTimeMillis(); + } + + /** + * Returns whether this pokestop has an active lure. + * + * @return lure status + * @throws LoginFailedException If login failed. + * @throws RemoteServerException If server communications failed. + */ + public boolean hasLure() throws LoginFailedException, RemoteServerException { + List modifiers = getDetails().getModifier(); + for (FortModifierOuterClass.FortModifier mod : modifiers) { + if (mod.getItemId() == ItemIdOuterClass.ItemId.ITEM_TROY_DISK) { + return true; + } + } + + return false; } } diff --git a/src/main/java/com/pokegoapi/api/map/pokemon/CatchItemResult.java b/src/main/java/com/pokegoapi/api/map/pokemon/CatchItemResult.java index c4061af5..c09a01dc 100644 --- a/src/main/java/com/pokegoapi/api/map/pokemon/CatchItemResult.java +++ b/src/main/java/com/pokegoapi/api/map/pokemon/CatchItemResult.java @@ -15,7 +15,6 @@ package com.pokegoapi.api.map.pokemon; -import POGOProtos.Networking.Responses.UseItemCaptureResponseOuterClass; import POGOProtos.Networking.Responses.UseItemCaptureResponseOuterClass.UseItemCaptureResponse; public class CatchItemResult { diff --git a/src/main/java/com/pokegoapi/api/map/pokemon/CatchResult.java b/src/main/java/com/pokegoapi/api/map/pokemon/CatchResult.java index 32a1de83..6ed0b02d 100644 --- a/src/main/java/com/pokegoapi/api/map/pokemon/CatchResult.java +++ b/src/main/java/com/pokegoapi/api/map/pokemon/CatchResult.java @@ -28,6 +28,7 @@ public class CatchResult { private CaptureAward captureAward; private CatchPokemonResponse response; + private CatchStatus status; @Setter private boolean failed; @@ -41,7 +42,15 @@ public CatchResult(CatchPokemonResponse response) { this.response = response; } + /** + * Gets a status from response object, or a set one if set + * + * @return catch status + */ public CatchStatus getStatus() { + if (this.status != null) { + return status; + } return response.getStatus(); } @@ -69,6 +78,10 @@ public List getStardustList() { return captureAward.getStardustList(); } + public void setStatus(CatchStatus status) { + this.status = status; + } + /** * Returns whether the catch failed. * diff --git a/src/main/java/com/pokegoapi/api/map/pokemon/CatchablePokemon.java b/src/main/java/com/pokegoapi/api/map/pokemon/CatchablePokemon.java index ef773ba4..1c2dd316 100644 --- a/src/main/java/com/pokegoapi/api/map/pokemon/CatchablePokemon.java +++ b/src/main/java/com/pokegoapi/api/map/pokemon/CatchablePokemon.java @@ -15,36 +15,58 @@ package com.pokegoapi.api.map.pokemon; -import POGOProtos.Enums.PokemonIdOuterClass; + +import POGOProtos.Enums.PokemonIdOuterClass.PokemonId; import POGOProtos.Inventory.Item.ItemIdOuterClass.ItemId; import POGOProtos.Map.Fort.FortDataOuterClass.FortData; import POGOProtos.Map.Pokemon.MapPokemonOuterClass.MapPokemon; import POGOProtos.Map.Pokemon.WildPokemonOuterClass.WildPokemon; import POGOProtos.Networking.Requests.Messages.CatchPokemonMessageOuterClass.CatchPokemonMessage; -import POGOProtos.Networking.Requests.Messages.EncounterMessageOuterClass; -import POGOProtos.Networking.Requests.Messages.UseItemCaptureMessageOuterClass; +import POGOProtos.Networking.Requests.Messages.DiskEncounterMessageOuterClass; +import POGOProtos.Networking.Requests.Messages.DiskEncounterMessageOuterClass.DiskEncounterMessage; +import POGOProtos.Networking.Requests.Messages.EncounterMessageOuterClass.EncounterMessage; import POGOProtos.Networking.Requests.Messages.UseItemCaptureMessageOuterClass.UseItemCaptureMessage; -import POGOProtos.Networking.Requests.RequestTypeOuterClass; +import POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType; import POGOProtos.Networking.Responses.CatchPokemonResponseOuterClass.CatchPokemonResponse; -import POGOProtos.Networking.Responses.EncounterResponseOuterClass; +import POGOProtos.Networking.Responses.CatchPokemonResponseOuterClass.CatchPokemonResponse.CatchStatus; +import POGOProtos.Networking.Responses.DiskEncounterResponseOuterClass.DiskEncounterResponse; import POGOProtos.Networking.Responses.EncounterResponseOuterClass.EncounterResponse; -import POGOProtos.Networking.Responses.UseItemCaptureResponseOuterClass; import POGOProtos.Networking.Responses.UseItemCaptureResponseOuterClass.UseItemCaptureResponse; +import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import com.pokegoapi.api.PokemonGo; import com.pokegoapi.api.inventory.ItemBag; import com.pokegoapi.api.inventory.Pokeball; +import com.pokegoapi.api.map.pokemon.encounter.DiskEncounterResult; +import com.pokegoapi.api.map.pokemon.encounter.EncounterResult; +import com.pokegoapi.api.map.pokemon.encounter.NormalEncounterResult; import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.NoSuchItemException; import com.pokegoapi.exceptions.RemoteServerException; -import com.pokegoapi.main.ServerRequest; +import com.pokegoapi.main.AsyncServerRequest; +import com.pokegoapi.util.FutureWrapper; +import com.pokegoapi.util.MapPoint; +import com.pokegoapi.util.Log; +import com.pokegoapi.util.NestedFutureWrapper; +import com.pokegoapi.util.PokemonFuture; import lombok.Getter; import lombok.ToString; +import java.util.concurrent.Future; + + /** * The type Catchable pokemon. */ @ToString -public class CatchablePokemon { +public class CatchablePokemon implements MapPoint { + + private enum EncounterKind { + NORMAL, + DISK; + } + + private static final String TAG = CatchablePokemon.class.getSimpleName(); private final PokemonGo api; @@ -53,28 +75,28 @@ public class CatchablePokemon { @Getter private final long encounterId; @Getter - private final PokemonIdOuterClass.PokemonId pokemonId; + private final PokemonId pokemonId; @Getter private final long expirationTimestampMs; @Getter private final double latitude; @Getter private final double longitude; + private final EncounterKind encounterKind; + + private Boolean encountered = null; + - @Getter - private boolean encountered = false; /** * Instantiates a new Catchable pokemon. * - * @param api - * the api - * @param proto - * the proto + * @param api the api + * @param proto the proto */ public CatchablePokemon(PokemonGo api, MapPokemon proto) { this.api = api; - + this.encounterKind = EncounterKind.NORMAL; this.spawnPointId = proto.getSpawnPointId(); this.encounterId = proto.getEncounterId(); this.pokemonId = proto.getPokemonId(); @@ -86,13 +108,12 @@ public CatchablePokemon(PokemonGo api, MapPokemon proto) { /** * Instantiates a new Catchable pokemon. * - * @param api - * the api - * @param proto - * the proto + * @param api the api + * @param proto the proto */ public CatchablePokemon(PokemonGo api, WildPokemon proto) { this.api = api; + this.encounterKind = EncounterKind.NORMAL; this.spawnPointId = proto.getSpawnPointId(); this.encounterId = proto.getEncounterId(); this.pokemonId = proto.getPokemonData().getPokemonId(); @@ -104,10 +125,8 @@ public CatchablePokemon(PokemonGo api, WildPokemon proto) { /** * Instantiates a new Catchable pokemon. * - * @param api - * the api - * @param proto - * the proto + * @param api the api + * @param proto the proto */ public CatchablePokemon(PokemonGo api, FortData proto) { if (!proto.hasLureInfo()) { @@ -115,115 +134,199 @@ public CatchablePokemon(PokemonGo api, FortData proto) { } this.api = api; // TODO: does this work? - this.spawnPointId = null; + // seems that spawnPoint it's fortId in catchAPI so it should be safe to just set it in that way + this.spawnPointId = proto.getLureInfo().getFortId(); this.encounterId = proto.getLureInfo().getEncounterId(); this.pokemonId = proto.getLureInfo().getActivePokemonId(); this.expirationTimestampMs = proto.getLureInfo() .getLureExpiresTimestampMs(); this.latitude = proto.getLatitude(); this.longitude = proto.getLongitude(); + this.encounterKind = EncounterKind.DISK; + } + + /** + * Encounter pokemon + * + * @return the encounter result + */ + public EncounterResult encounterPokemon() throws LoginFailedException, RemoteServerException { + return encounterPokemonAsync().toBlocking(); } /** * Encounter pokemon encounter result. * * @return the encounter result - * @throws LoginFailedException - * the login failed exception - * @throws RemoteServerException - * the remote server exception */ - public EncounterResult encounterPokemon() throws LoginFailedException, - RemoteServerException { - EncounterMessageOuterClass.EncounterMessage reqMsg = EncounterMessageOuterClass.EncounterMessage + public PokemonFuture encounterPokemonAsync() { + if (encounterKind == EncounterKind.NORMAL) { + return encounterNormalPokemonAsync(); + } else if (encounterKind == EncounterKind.DISK) { + return encounterDiskPokemonAsync(); + } + + throw new IllegalStateException("Catchable pokemon missing encounter type"); + } + + /** + * Encounter pokemon encounter result. + * + * @return the encounter result + */ + public PokemonFuture encounterNormalPokemonAsync() { + EncounterMessage reqMsg = EncounterMessage .newBuilder().setEncounterId(getEncounterId()) .setPlayerLatitude(api.getLatitude()) .setPlayerLongitude(api.getLongitude()) .setSpawnPointId(getSpawnPointId()).build(); - ServerRequest serverRequest = new ServerRequest( - RequestTypeOuterClass.RequestType.ENCOUNTER, reqMsg); - api.getRequestHandler().sendServerRequests(serverRequest); - EncounterResponseOuterClass.EncounterResponse response = null; - try { - response = EncounterResponseOuterClass.EncounterResponse - .parseFrom(serverRequest.getData()); - } catch (InvalidProtocolBufferException e) { - throw new RemoteServerException(e); - } - encountered = response.getStatus() == EncounterResponse.Status.ENCOUNTER_SUCCESS; - return new EncounterResult(response); + AsyncServerRequest serverRequest = new AsyncServerRequest( + RequestType.ENCOUNTER, reqMsg); + return new FutureWrapper(api.getRequestHandler() + .sendAsyncServerRequests(serverRequest)) { + @Override + protected EncounterResult handle(ByteString result) throws RemoteServerException { + EncounterResponse response; + try { + response = EncounterResponse + .parseFrom(result); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + encountered = response.getStatus() == EncounterResponse.Status.ENCOUNTER_SUCCESS; + return new NormalEncounterResult(response); + } + }; + } + + /** + * Encounter pokemon encounter result. + * + * @return the encounter result + * @throws LoginFailedException the login failed exception + * @throws RemoteServerException the remote server exception + */ + public EncounterResult encounterNormalPokemon() throws LoginFailedException, + RemoteServerException { + return encounterNormalPokemonAsync().toBlocking(); + } + + + + /** + * Encounter pokemon + * + * @return the encounter result + */ + public PokemonFuture encounterDiskPokemonAsync() { + DiskEncounterMessage reqMsg = DiskEncounterMessage + .newBuilder().setEncounterId(getEncounterId()) + .setPlayerLatitude(api.getLatitude()) + .setPlayerLongitude(api.getLongitude()) + .setFortId(getSpawnPointId()).build(); + AsyncServerRequest serverRequest = new AsyncServerRequest(RequestType.DISK_ENCOUNTER, reqMsg); + return new FutureWrapper(api.getRequestHandler() + .sendAsyncServerRequests(serverRequest)) { + @Override + protected EncounterResult handle(ByteString result) throws RemoteServerException { + DiskEncounterResponse response; + try { + response = DiskEncounterResponse.parseFrom(result); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + encountered = response.getResult() == DiskEncounterResponse.Result.SUCCESS; + return new DiskEncounterResult(response); + } + }; } + /** * Tries to catch a pokemon (will attempt to use a pokeball, if you have * none will use greatball etc) and uwill use a single razz berry if available. * * @return CatchResult - * @throws LoginFailedException - * if failed to login - * @throws RemoteServerException - * if the server failed to respond + * @throws LoginFailedException if failed to login + * @throws RemoteServerException if the server failed to respond */ - public CatchResult catchPokemonWithRazzBerry() throws LoginFailedException, - RemoteServerException { - Pokeball pokeball; + public PokemonFuture catchPokemonWithRazzBerryAsync() + throws LoginFailedException, RemoteServerException, NoSuchItemException { + final Pokeball pokeball = getItemBall(); + + + return new NestedFutureWrapper(useItemAsync(ItemId.ITEM_RAZZ_BERRY)) { + @Override + protected Future handleFuture(CatchItemResult result) { + if (!result.getSuccess()) { + return FutureWrapper.just(new CatchResult()); + } + return catchPokemonAsync(pokeball); + } + }; + } + /** + * Gets item ball to catch a pokemon + * + * @return the item ball + * @throws LoginFailedException the login failed exception + * @throws RemoteServerException the remote server exception + * @throws NoSuchItemException the no such item exception + */ + public Pokeball getItemBall() throws LoginFailedException, + RemoteServerException, NoSuchItemException { ItemBag bag = api.getInventories().getItemBag(); if (bag.getItem(ItemId.ITEM_POKE_BALL).getCount() > 0) { - pokeball = Pokeball.POKEBALL; + return Pokeball.POKEBALL; } else if (bag.getItem(ItemId.ITEM_GREAT_BALL).getCount() > 0) { - pokeball = Pokeball.GREATBALL; + return Pokeball.GREATBALL; } else if (bag.getItem(ItemId.ITEM_ULTRA_BALL).getCount() > 0) { - pokeball = Pokeball.ULTRABALL; + return Pokeball.ULTRABALL; + } else if (bag.getItem(ItemId.ITEM_MASTER_BALL).getCount() > 0) { + return Pokeball.MASTERBALL; } else { - pokeball = Pokeball.MASTERBALL; + throw new NoSuchItemException(); } + } + + /** + * Tries to catch a pokemon (will attempt to use a pokeball, if you have + * none will use greatball etc) and uwill use a single razz berry if available. + * + * @return CatchResult + * @throws LoginFailedException if failed to login + * @throws RemoteServerException if the server failed to respond + */ + public CatchResult catchPokemonWithRazzBerry() throws LoginFailedException, + RemoteServerException, NoSuchItemException { + Pokeball pokeball = getItemBall(); useItem(ItemId.ITEM_RAZZ_BERRY); return catchPokemon(pokeball, -1, -1); } - /** * Tries to catch a pokemon (will attempt to use a pokeball, if you have * none will use greatball etc). * * @return CatchResult - * @throws LoginFailedException - * if failed to login - * @throws RemoteServerException - * if the server failed to respond + * @throws LoginFailedException if failed to login + * @throws RemoteServerException if the server failed to respond */ public CatchResult catchPokemon() throws LoginFailedException, - RemoteServerException { - Pokeball pokeball; - - ItemBag bag = api.getInventories().getItemBag(); - if (bag.getItem(ItemId.ITEM_POKE_BALL).getCount() > 0) { - pokeball = Pokeball.POKEBALL; - } else if (bag.getItem(ItemId.ITEM_GREAT_BALL).getCount() > 0) { - pokeball = Pokeball.GREATBALL; - } else if (bag.getItem(ItemId.ITEM_ULTRA_BALL).getCount() > 0) { - pokeball = Pokeball.ULTRABALL; - } else { - pokeball = Pokeball.MASTERBALL; - } + RemoteServerException, NoSuchItemException { - return catchPokemon(pokeball); + return catchPokemon(getItemBall()); } - - /** * Tries to catch a pokeball with the given type. * - * @param pokeball - * Type of pokeball + * @param pokeball Type of pokeball * @return CatchResult - * @throws LoginFailedException - * if failed to login - * @throws RemoteServerException - * if the server failed to respond + * @throws LoginFailedException if failed to login + * @throws RemoteServerException if the server failed to respond */ public CatchResult catchPokemon(Pokeball pokeball) throws LoginFailedException, RemoteServerException { @@ -233,15 +336,11 @@ public CatchResult catchPokemon(Pokeball pokeball) /** * Tried to catch a pokemon with given pokeball and max number of pokeballs. * - * @param pokeball - * Type of pokeball - * @param amount - * Max number of pokeballs to use + * @param pokeball Type of pokeball + * @param amount Max number of pokeballs to use * @return CatchResult - * @throws LoginFailedException - * if failed to login - * @throws RemoteServerException - * if the server failed to respond + * @throws LoginFailedException if failed to login + * @throws RemoteServerException if the server failed to respond */ public CatchResult catchPokemon(Pokeball pokeball, int amount) throws LoginFailedException, RemoteServerException { @@ -252,43 +351,31 @@ public CatchResult catchPokemon(Pokeball pokeball, int amount) /** * Tried to catch a pokemon with given pokeball and max number of pokeballs. * - * @param pokeball - * Type of pokeball - * @param amount - * Max number of pokeballs to use - * @param razberryLimit - * Max number of razberrys to use + * @param pokeball Type of pokeball + * @param amount Max number of pokeballs to use + * @param razberryLimit Max number of razberrys to use * @return CatchResult - * @throws LoginFailedException - * if failed to login - * @throws RemoteServerException - * if the server failed to respond + * @throws LoginFailedException if failed to login + * @throws RemoteServerException if the server failed to respond */ public CatchResult catchPokemon(Pokeball pokeball, int amount, int razberryLimit) throws LoginFailedException, RemoteServerException { return catchPokemon(1.0, 1.95 + Math.random() * 0.05, - 0.85 + Math.random() * 0.15, pokeball, razberryLimit); + 0.85 + Math.random() * 0.15, pokeball, amount, razberryLimit); } /** * Tries to catch a pokemon. * - * @param normalizedHitPosition - * the normalized hit position - * @param normalizedReticleSize - * the normalized hit reticle - * @param spinModifier - * the spin modifier - * @param type - * Type of pokeball to throw - * @param amount - * Max number of Pokeballs to throw, negative number for - * unlimited + * @param normalizedHitPosition the normalized hit position + * @param normalizedReticleSize the normalized hit reticle + * @param spinModifier the spin modifier + * @param type Type of pokeball to throw + * @param amount Max number of Pokeballs to throw, negative number for + * unlimited * @return CatchResult of resulted try to catch pokemon - * @throws LoginFailedException - * if failed to login - * @throws RemoteServerException - * if the server failed to respond + * @throws LoginFailedException if failed to login + * @throws RemoteServerException if the server failed to respond */ public CatchResult catchPokemon(double normalizedHitPosition, double normalizedReticleSize, double spinModifier, Pokeball type, @@ -297,88 +384,128 @@ public CatchResult catchPokemon(double normalizedHitPosition, return catchPokemon(normalizedHitPosition, normalizedReticleSize, spinModifier, type, amount, -1); } + /** * Tries to catch a pokemon. * - * @param normalizedHitPosition - * the normalized hit position - * @param normalizedReticleSize - * the normalized hit reticle - * @param spinModifier - * the spin modifier - * @param type - * Type of pokeball to throw - * @param amount - * Max number of Pokeballs to throw, negative number for - * unlimited - * @param razberriesLimit - * The maximum amount of razberries to use, -1 for unlimited + * @param normalizedHitPosition the normalized hit position + * @param normalizedReticleSize the normalized hit reticle + * @param spinModifier the spin modifier + * @param type Type of pokeball to throw + * @param amount Max number of Pokeballs to throw, negative number for + * unlimited + * @param razberriesLimit The maximum amount of razberries to use, -1 for unlimited * @return CatchResult of resulted try to catch pokemon - * @throws LoginFailedException - * if failed to login - * @throws RemoteServerException - * if the server failed to respond + * @throws LoginFailedException if failed to login + * @throws RemoteServerException if the server failed to respond */ public CatchResult catchPokemon(double normalizedHitPosition, double normalizedReticleSize, double spinModifier, Pokeball type, - int amount, int razberriesLimit) throws LoginFailedException, RemoteServerException { - if (!isEncountered()) { - return new CatchResult(); - } - + int amount, int razberriesLimit) + throws LoginFailedException, RemoteServerException { int razberries = 0; int numThrows = 0; - CatchPokemonResponse response = null; + CatchResult result; do { if (razberries < razberriesLimit || razberriesLimit == -1) { useItem(ItemId.ITEM_RAZZ_BERRY); razberries++; } - - CatchPokemonMessage reqMsg = CatchPokemonMessage.newBuilder() - .setEncounterId(getEncounterId()).setHitPokemon(true) - .setNormalizedHitPosition(normalizedHitPosition) - .setNormalizedReticleSize(normalizedReticleSize) - .setSpawnPointId(getSpawnPointId()) - .setSpinModifier(spinModifier) - .setPokeball(type.getBallType()).build(); - ServerRequest serverRequest = new ServerRequest( - RequestTypeOuterClass.RequestType.CATCH_POKEMON, reqMsg); - api.getRequestHandler().sendServerRequests(serverRequest); - - try { - response = CatchPokemonResponse.parseFrom(serverRequest - .getData()); - } catch (InvalidProtocolBufferException e) { - throw new RemoteServerException(e); + result = catchPokemonAsync(normalizedHitPosition, normalizedReticleSize, spinModifier, type).toBlocking(); + if (result == null) { + Log.wtf(TAG, "Got a null result after catch attempt"); + break; } - - if (response.getStatus() != CatchPokemonResponse.CatchStatus.CATCH_ESCAPE - && response.getStatus() != CatchPokemonResponse.CatchStatus.CATCH_MISSED) { + if (!result.isFailed() && result.getStatus() != CatchStatus.CATCH_ESCAPE + && result.getStatus() != CatchStatus.CATCH_MISSED + || result.getStatus() == CatchStatus.CATCH_FLEE) { break; } numThrows++; } while (amount < 0 || numThrows < amount); - api.getInventories().updateInventories(); + return result; + } + - return new CatchResult(response); + /** + * Tries to catch a pokemon. + * + * @param type Type of pokeball to throw + * @return CatchResult of resulted try to catch pokemon + */ + public PokemonFuture catchPokemonAsync(Pokeball type) { + return catchPokemonAsync(1.0, 1.95 + Math.random() * 0.05, + 0.85 + Math.random() * 0.15, type); + } + + /** + * Tries to catch a pokemon. + * + * @param normalizedHitPosition the normalized hit position + * @param normalizedReticleSize the normalized hit reticle + * @param spinModifier the spin modifier + * @param type Type of pokeball to throw + * @return CatchResult of resulted try to catch pokemon + */ + public PokemonFuture catchPokemonAsync(double normalizedHitPosition, double normalizedReticleSize, + double spinModifier, Pokeball type) { + if (!isEncountered()) { + return FutureWrapper.just(new CatchResult()); + } + + CatchPokemonMessage reqMsg = CatchPokemonMessage.newBuilder() + .setEncounterId(getEncounterId()).setHitPokemon(true) + .setNormalizedHitPosition(normalizedHitPosition) + .setNormalizedReticleSize(normalizedReticleSize) + .setSpawnPointId(getSpawnPointId()) + .setSpinModifier(spinModifier) + .setPokeball(type.getBallType()).build(); + AsyncServerRequest serverRequest = new AsyncServerRequest( + RequestType.CATCH_POKEMON, reqMsg); + return new FutureWrapper(api.getRequestHandler() + .sendAsyncServerRequests(serverRequest)) { + @Override + protected CatchResult handle(ByteString result) throws RemoteServerException, LoginFailedException { + System.out.println("ASYNC CATCH CALL"); + CatchPokemonResponse response; + + try { + response = CatchPokemonResponse.parseFrom(result); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + + if (response.getStatus() == CatchStatus.CATCH_FLEE + || response.getStatus() == CatchStatus.CATCH_SUCCESS) { + api.getMap().getCatchablePokemon().remove(this); + } + + + if (response.getStatus() != CatchStatus.CATCH_ESCAPE + && response.getStatus() != CatchStatus.CATCH_MISSED) { + api.getInventories().updateInventories(); + return new CatchResult(response); + } else { + CatchResult res = new CatchResult(); + res.setStatus(CatchStatus.CATCH_ESCAPE); + return res; + } + } + }; } /** * Tries to use an item on a catchable pokemon (ie razzberry). * - * @param item - * the item ID + * @param item the item ID * @return CatchItemResult info about the new modifiers about the pokemon (can move, item capture multi) eg - * @throws LoginFailedException - * if failed to login - * @throws RemoteServerException - * if the server failed to respond + * @throws LoginFailedException if failed to login + * @throws RemoteServerException if the server failed to respond */ - public CatchItemResult useItem(ItemId item) throws LoginFailedException, RemoteServerException { + public PokemonFuture useItemAsync(ItemId item) { UseItemCaptureMessage reqMsg = UseItemCaptureMessage .newBuilder() @@ -387,16 +514,33 @@ public CatchItemResult useItem(ItemId item) throws LoginFailedException, RemoteS .setItemId(item) .build(); - ServerRequest serverRequest = new ServerRequest( - RequestTypeOuterClass.RequestType.USE_ITEM_CAPTURE, reqMsg); - api.getRequestHandler().sendServerRequests(serverRequest); - UseItemCaptureResponse response = null; - try { - response = UseItemCaptureResponse.parseFrom(serverRequest.getData()); - } catch (InvalidProtocolBufferException e) { - throw new RemoteServerException(e); - } - return new CatchItemResult(response); + AsyncServerRequest serverRequest = new AsyncServerRequest( + RequestType.USE_ITEM_CAPTURE, reqMsg); + return new FutureWrapper(api.getRequestHandler() + .sendAsyncServerRequests(serverRequest)) { + @Override + protected CatchItemResult handle(ByteString result) throws RemoteServerException, LoginFailedException { + UseItemCaptureResponse response; + try { + response = UseItemCaptureResponse.parseFrom(result); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + return new CatchItemResult(response); + } + }; + } + + /** + * Tries to use an item on a catchable pokemon (ie razzberry). + * + * @param item the item ID + * @return CatchItemResult info about the new modifiers about the pokemon (can move, item capture multi) eg + * @throws LoginFailedException if failed to login + * @throws RemoteServerException if the server failed to respond + */ + public CatchItemResult useItem(ItemId item) throws LoginFailedException, RemoteServerException { + return useItemAsync(item).toBlocking(); } @Override @@ -415,4 +559,15 @@ public int hashCode() { return (int) this.getEncounterId(); } + /** + * Encounter check + * + * @return Checks if encounter has happened + */ + public boolean isEncountered() { + if (encountered == null) { + return false; + } + return encountered; + } } diff --git a/src/main/java/com/pokegoapi/api/map/pokemon/encounter/DiskEncounterResult.java b/src/main/java/com/pokegoapi/api/map/pokemon/encounter/DiskEncounterResult.java new file mode 100644 index 00000000..6ec4162d --- /dev/null +++ b/src/main/java/com/pokegoapi/api/map/pokemon/encounter/DiskEncounterResult.java @@ -0,0 +1,69 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.api.map.pokemon.encounter; + + +import POGOProtos.Networking.Responses.DiskEncounterResponseOuterClass.DiskEncounterResponse; +import POGOProtos.Networking.Responses.EncounterResponseOuterClass; +import POGOProtos.Networking.Responses.EncounterResponseOuterClass.EncounterResponse; +import lombok.Getter; + +public class DiskEncounterResult implements EncounterResult { + @Getter + private DiskEncounterResponse response; + + public DiskEncounterResult(DiskEncounterResponse response) { + this.response = response; + } + + @Override + public boolean wasSuccessful() { + return response != null + && response.getResult() == DiskEncounterResponse.Result.SUCCESS; + } + + + //TODO: i have conveted the DiskEncounter response to maintain compatibility, if not required + //i think will be better to remove this method + + /** + * Return the status of the encounter + * + * @return status of results + */ + public EncounterResponse.Status getStatus() { + if (response == null) + return null; + switch (response.getResult()) { + case UNKNOWN: + return EncounterResponse.Status.ENCOUNTER_ERROR; + case SUCCESS: + return EncounterResponse.Status.ENCOUNTER_SUCCESS; + case NOT_AVAILABLE: + return EncounterResponse.Status.ENCOUNTER_NOT_FOUND; + case NOT_IN_RANGE: + return EncounterResponse.Status.ENCOUNTER_NOT_IN_RANGE; + case ENCOUNTER_ALREADY_FINISHED: + return EncounterResponse.Status.ENCOUNTER_ALREADY_HAPPENED; + case POKEMON_INVENTORY_FULL: + return EncounterResponse.Status.POKEMON_INVENTORY_FULL; + case UNRECOGNIZED: + return EncounterResponse.Status.UNRECOGNIZED; + default: + return EncounterResponse.Status.UNRECOGNIZED; + } + } +} diff --git a/src/main/java/com/pokegoapi/api/map/pokemon/encounter/EncounterResult.java b/src/main/java/com/pokegoapi/api/map/pokemon/encounter/EncounterResult.java new file mode 100644 index 00000000..1190a6a2 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/map/pokemon/encounter/EncounterResult.java @@ -0,0 +1,29 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.api.map.pokemon.encounter; + +import POGOProtos.Data.Capture.CaptureProbabilityOuterClass; +import POGOProtos.Map.Pokemon.WildPokemonOuterClass; +import POGOProtos.Networking.Responses.EncounterResponseOuterClass.EncounterResponse; + + + +public interface EncounterResult { + + boolean wasSuccessful(); + + EncounterResponse.Status getStatus(); +} \ No newline at end of file diff --git a/src/main/java/com/pokegoapi/api/map/pokemon/EncounterResult.java b/src/main/java/com/pokegoapi/api/map/pokemon/encounter/NormalEncounterResult.java similarity index 66% rename from src/main/java/com/pokegoapi/api/map/pokemon/EncounterResult.java rename to src/main/java/com/pokegoapi/api/map/pokemon/encounter/NormalEncounterResult.java index 0d4be261..dfd16aec 100644 --- a/src/main/java/com/pokegoapi/api/map/pokemon/EncounterResult.java +++ b/src/main/java/com/pokegoapi/api/map/pokemon/encounter/NormalEncounterResult.java @@ -13,42 +13,49 @@ * along with this program. If not, see . */ -package com.pokegoapi.api.map.pokemon; - -import POGOProtos.Data.Capture.CaptureProbabilityOuterClass; -import POGOProtos.Map.Pokemon.WildPokemonOuterClass; -import POGOProtos.Networking.Responses.EncounterResponseOuterClass.EncounterResponse; +package com.pokegoapi.api.map.pokemon.encounter; -public class EncounterResult { +import POGOProtos.Data.Capture.CaptureProbabilityOuterClass.CaptureProbability; +import POGOProtos.Map.Pokemon.WildPokemonOuterClass.WildPokemon; +import POGOProtos.Networking.Responses.EncounterResponseOuterClass.EncounterResponse; +public class NormalEncounterResult implements EncounterResult { private EncounterResponse response; - public EncounterResult(EncounterResponse response) { + public NormalEncounterResult(EncounterResponse response) { this.response = response; } + /** + * Return the status of the encounter + * + * @return status of results + */ public EncounterResponse.Status getStatus() { return response == null ? null : response.getStatus(); } public boolean wasSuccessful() { - return response != null && getStatus() != null && getStatus().equals(EncounterResponse.Status.ENCOUNTER_SUCCESS); + return response != null + && getStatus() != null && getStatus().equals(EncounterResponse.Status.ENCOUNTER_SUCCESS); } public EncounterResponse.Background getBackground() { return response.getBackground(); } - public CaptureProbabilityOuterClass.CaptureProbability getCaptureProbability() { + public CaptureProbability getCaptureProbability() { return response.getCaptureProbability(); } - public WildPokemonOuterClass.WildPokemon getWildPokemon() { + public WildPokemon getWildPokemon() { return response.getWildPokemon(); } public EncounterResponse toPrimitive() { return response; } -} + + +} \ No newline at end of file diff --git a/src/main/java/com/pokegoapi/api/player/ContactSettings.java b/src/main/java/com/pokegoapi/api/player/ContactSettings.java index b720f956..f16cebb1 100644 --- a/src/main/java/com/pokegoapi/api/player/ContactSettings.java +++ b/src/main/java/com/pokegoapi/api/player/ContactSettings.java @@ -15,11 +15,22 @@ package com.pokegoapi.api.player; +import POGOProtos.Data.Player.ContactSettingsOuterClass; import lombok.Data; @Data public class ContactSettings { + private ContactSettingsOuterClass.ContactSettings proto; - private boolean sendMarketingEmails; - private boolean sendPushNotifications; + public ContactSettings(ContactSettingsOuterClass.ContactSettings proto) { + this.proto = proto; + } + + public boolean getSendMarketingEmails() { + return proto.getSendMarketingEmails(); + } + + public boolean getSendPushNotifications() { + return proto.getSendPushNotifications(); + } } diff --git a/src/main/java/com/pokegoapi/api/player/DailyBonus.java b/src/main/java/com/pokegoapi/api/player/DailyBonus.java index 63a50d47..04e44539 100644 --- a/src/main/java/com/pokegoapi/api/player/DailyBonus.java +++ b/src/main/java/com/pokegoapi/api/player/DailyBonus.java @@ -15,11 +15,22 @@ package com.pokegoapi.api.player; +import POGOProtos.Data.Player.DailyBonusOuterClass; import lombok.Data; @Data public class DailyBonus { + private final DailyBonusOuterClass.DailyBonus proto; - private long nextCollectionTimestamp; - private long nextDefenderBonusCollectTimestamp; + public DailyBonus(DailyBonusOuterClass.DailyBonus proto ) { + this.proto = proto; + } + + public long getNextCollectedTimestampMs() { + return proto.getNextCollectedTimestampMs(); + } + + public long getNextDefenderBonusCollectTimestampMs() { + return proto.getNextDefenderBonusCollectTimestampMs(); + } } diff --git a/src/main/java/com/pokegoapi/api/player/PlayerAvatar.java b/src/main/java/com/pokegoapi/api/player/PlayerAvatar.java index 7b23e694..761b0027 100644 --- a/src/main/java/com/pokegoapi/api/player/PlayerAvatar.java +++ b/src/main/java/com/pokegoapi/api/player/PlayerAvatar.java @@ -15,19 +15,55 @@ package com.pokegoapi.api.player; +import POGOProtos.Data.Player.PlayerAvatarOuterClass; import POGOProtos.Enums.GenderOuterClass; import lombok.Data; @Data public class PlayerAvatar { + private PlayerAvatarOuterClass.PlayerAvatar avatar; - private GenderOuterClass.Gender gender; - private int skin; - private int hair; - private int shirt; - private int pants; - private int hat; - private int shoes; - private int eyes; - private int backpack; + public PlayerAvatar(PlayerAvatarOuterClass.PlayerAvatar data) { + avatar = data; + } + + public int getSkin() { + return avatar.getSkin(); + } + + public int getHair() { + return avatar.getHair(); + } + + public int getShirt() { + return avatar.getShirt(); + } + + public int getPants() { + return avatar.getPants(); + } + + public int getHat() { + return avatar.getHat(); + } + + public int getShoes() { + return avatar.getShoes(); + } + + public int getGenderValue() { + return avatar.getGenderValue(); + } + + public GenderOuterClass.Gender getGender() { + return avatar.getGender(); + } + + public int getEyes() { + return avatar.getEyes(); + } + + public int getBackpack() { + return avatar.getBackpack(); + } } diff --git a/src/main/java/com/pokegoapi/api/player/PlayerLevelUpRewards.java b/src/main/java/com/pokegoapi/api/player/PlayerLevelUpRewards.java new file mode 100644 index 00000000..a2f10229 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/player/PlayerLevelUpRewards.java @@ -0,0 +1,53 @@ +package com.pokegoapi.api.player; + +import POGOProtos.Inventory.Item.ItemAwardOuterClass; +import POGOProtos.Inventory.Item.ItemIdOuterClass; +import POGOProtos.Networking.Responses.LevelUpRewardsResponseOuterClass.LevelUpRewardsResponse; +import lombok.Data; + +import java.util.Collections; +import java.util.List; + +/** + * A data class containing the results of a trainer level up. This includes a list of items received for this level up, + * a list of items which were unlocked by this level up (for example razz berries) + * and the status of these level up results. + * If the rewards for this level up have been + * accepted in the past the status will be ALREADY_ACCEPTED, if this level up has not yet been achieved + * by the player it will be NOT_UNLOCKED_YET otherwise it will be NEW. + * + * @author Alex Schlosser + */ +@Data +public class PlayerLevelUpRewards { + private final Status status; + private final List rewards; + private final List unlockedItems; + + + /** + * Create new empty result object with the specified status. + * + * @param status the status of this result + */ + public PlayerLevelUpRewards(final Status status) { + this.status = status; + this.rewards = Collections.emptyList(); + this.unlockedItems = Collections.emptyList(); + } + + public enum Status { + ALREADY_ACCEPTED, NEW, NOT_UNLOCKED_YET + } + + /** + * Create a new result object based on a server response + * + * @param response the response which contains the request results + */ + public PlayerLevelUpRewards(final LevelUpRewardsResponse response) { + this.rewards = response.getItemsAwardedList(); + this.unlockedItems = response.getItemsUnlockedList(); + this.status = (rewards.isEmpty() ? Status.ALREADY_ACCEPTED : Status.NEW); + } +} diff --git a/src/main/java/com/pokegoapi/api/player/PlayerProfile.java b/src/main/java/com/pokegoapi/api/player/PlayerProfile.java index 0cb58cc3..6c4b4b66 100644 --- a/src/main/java/com/pokegoapi/api/player/PlayerProfile.java +++ b/src/main/java/com/pokegoapi/api/player/PlayerProfile.java @@ -16,55 +16,52 @@ package com.pokegoapi.api.player; import POGOProtos.Data.Player.CurrencyOuterClass; -import POGOProtos.Data.Player.EquippedBadgeOuterClass; +import POGOProtos.Data.Player.EquippedBadgeOuterClass.EquippedBadge; import POGOProtos.Data.Player.PlayerStatsOuterClass; +import POGOProtos.Data.PlayerDataOuterClass.PlayerData; +import POGOProtos.Inventory.Item.ItemAwardOuterClass.ItemAward; +import POGOProtos.Networking.Requests.Messages.CheckAwardedBadgesMessageOuterClass.CheckAwardedBadgesMessage; +import POGOProtos.Networking.Requests.Messages.EquipBadgeMessageOuterClass.EquipBadgeMessage; import POGOProtos.Networking.Requests.Messages.GetPlayerMessageOuterClass.GetPlayerMessage; +import POGOProtos.Networking.Requests.Messages.LevelUpRewardsMessageOuterClass.LevelUpRewardsMessage; import POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType; -import POGOProtos.Networking.Responses.GetPlayerResponseOuterClass; +import POGOProtos.Networking.Responses.CheckAwardedBadgesResponseOuterClass.CheckAwardedBadgesResponse; +import POGOProtos.Networking.Responses.EquipBadgeResponseOuterClass; +import POGOProtos.Networking.Responses.GetPlayerResponseOuterClass.GetPlayerResponse; +import POGOProtos.Networking.Responses.LevelUpRewardsResponseOuterClass.LevelUpRewardsResponse; import com.google.protobuf.InvalidProtocolBufferException; import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.api.inventory.Item; +import com.pokegoapi.api.inventory.ItemBag; +import com.pokegoapi.api.inventory.Stats; import com.pokegoapi.exceptions.InvalidCurrencyException; import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; import com.pokegoapi.main.ServerRequest; import com.pokegoapi.util.Log; -import lombok.Getter; import lombok.Setter; import java.util.HashMap; import java.util.Map; + public class PlayerProfile { private static final String TAG = PlayerProfile.class.getSimpleName(); private final PokemonGo api; - @Getter - private long creationTime; - @Getter - private String username; - @Getter - private Team team; - @Getter - private int pokemonStorage; - @Getter - private int itemStorage; - @Getter - private EquippedBadgeOuterClass.EquippedBadge badge; - - @Getter + private PlayerData playerData; + private EquippedBadge badge; private PlayerAvatar avatar; - @Getter private DailyBonus dailyBonus; - @Getter private ContactSettings contactSettings; - @Getter private Map currencies = new HashMap(); - @Getter @Setter - private PlayerStatsOuterClass.PlayerStats stats; + private Stats stats; + + private boolean init; public PlayerProfile(PokemonGo api) throws LoginFailedException, RemoteServerException { this.api = api; - updateProfile(); + init = false; } /** @@ -74,27 +71,23 @@ public PlayerProfile(PokemonGo api) throws LoginFailedException, RemoteServerExc * @throws RemoteServerException the remote server exception */ public void updateProfile() throws RemoteServerException, LoginFailedException { + GetPlayerMessage getPlayerReqMsg = GetPlayerMessage.newBuilder().build(); ServerRequest getPlayerServerRequest = new ServerRequest(RequestType.GET_PLAYER, getPlayerReqMsg); api.getRequestHandler().sendServerRequests(getPlayerServerRequest); - GetPlayerResponseOuterClass.GetPlayerResponse playerResponse = null; + GetPlayerResponse playerResponse = null; try { - playerResponse = GetPlayerResponseOuterClass.GetPlayerResponse.parseFrom(getPlayerServerRequest.getData()); + playerResponse = GetPlayerResponse.parseFrom(getPlayerServerRequest.getData()); } catch (InvalidProtocolBufferException e) { throw new RemoteServerException(e); } - badge = playerResponse.getPlayerData().getEquippedBadge(); - creationTime = playerResponse.getPlayerData().getCreationTimestampMs(); - itemStorage = playerResponse.getPlayerData().getMaxItemStorage(); - pokemonStorage = playerResponse.getPlayerData().getMaxPokemonStorage(); - team = Team.values()[playerResponse.getPlayerData().getTeamValue()]; - username = playerResponse.getPlayerData().getUsername(); + playerData = playerResponse.getPlayerData(); - final PlayerAvatar avatarApi = new PlayerAvatar(); - final DailyBonus bonusApi = new DailyBonus(); - final ContactSettings contactApi = new ContactSettings(); + avatar = new PlayerAvatar(playerData.getAvatar()); + dailyBonus = new DailyBonus(playerData.getDailyBonus()); + contactSettings = new ContactSettings(playerData.getContactSettings()); // maybe something more graceful? for (CurrencyOuterClass.Currency currency : playerResponse.getPlayerData().getCurrenciesList()) { @@ -105,27 +98,44 @@ public void updateProfile() throws RemoteServerException, LoginFailedException { } } - avatarApi.setGender(playerResponse.getPlayerData().getAvatar().getGender()); - avatarApi.setBackpack(playerResponse.getPlayerData().getAvatar().getBackpack()); - avatarApi.setEyes(playerResponse.getPlayerData().getAvatar().getEyes()); - avatarApi.setHair(playerResponse.getPlayerData().getAvatar().getHair()); - avatarApi.setHat(playerResponse.getPlayerData().getAvatar().getHat()); - avatarApi.setPants(playerResponse.getPlayerData().getAvatar().getPants()); - avatarApi.setShirt(playerResponse.getPlayerData().getAvatar().getShirt()); - avatarApi.setShoes(playerResponse.getPlayerData().getAvatar().getShoes()); - avatarApi.setSkin(playerResponse.getPlayerData().getAvatar().getSkin()); - - bonusApi.setNextCollectionTimestamp( - playerResponse.getPlayerData().getDailyBonus().getNextCollectedTimestampMs() - ); - bonusApi.setNextDefenderBonusCollectTimestamp( - playerResponse.getPlayerData().getDailyBonus().getNextDefenderBonusCollectTimestampMs() - ); - - avatar = avatarApi; - dailyBonus = bonusApi; - + init = true; + } + /** + * Accept the rewards granted and the items unlocked by gaining a trainer level up. Rewards are retained by the + * server until a player actively accepts them. + * The rewarded items are automatically inserted into the players item bag. + * + * @see PlayerLevelUpRewards + * @param level the trainer level that you want to accept the rewards for + * @return a PlayerLevelUpRewards object containing information about the items rewarded and unlocked for this level + * @throws LoginFailedException if the login failed + * @throws RemoteServerException if the server failed to respond + */ + public PlayerLevelUpRewards acceptLevelUpRewards(int level) throws RemoteServerException, LoginFailedException { + // Check if we even have achieved this level yet + if (level > stats.getLevel()) { + return new PlayerLevelUpRewards(PlayerLevelUpRewards.Status.NOT_UNLOCKED_YET); + } + LevelUpRewardsMessage msg = LevelUpRewardsMessage.newBuilder() + .setLevel(level) + .build(); + ServerRequest serverRequest = new ServerRequest(RequestType.LEVEL_UP_REWARDS, msg); + api.getRequestHandler().sendServerRequests(serverRequest); + LevelUpRewardsResponse response; + try { + response = LevelUpRewardsResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + // Add the awarded items to our bag + ItemBag bag = api.getInventories().getItemBag(); + for (ItemAward itemAward : response.getItemsAwardedList()) { + Item item = bag.getItem(itemAward.getItemId()); + item.setCount(item.getCount() + itemAward.getItemCount()); + } + // Build a new rewards object and return it + return new PlayerLevelUpRewards(response); } /** @@ -143,14 +153,56 @@ public void addCurrency(String name, int amount) throws InvalidCurrencyException } } + /** + * Check and equip badges. + * + * @throws LoginFailedException if the login failed + * @throws RemoteServerException When a buffer exception is thrown + */ + + public void checkAndEquipBadges() throws LoginFailedException, RemoteServerException { + CheckAwardedBadgesMessage msg = + CheckAwardedBadgesMessage.newBuilder().build(); + ServerRequest serverRequest = new ServerRequest(RequestType.CHECK_AWARDED_BADGES, msg); + api.getRequestHandler().sendServerRequests(serverRequest); + CheckAwardedBadgesResponse response; + try { + response = CheckAwardedBadgesResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + if (response.getSuccess()) { + for (int i = 0; i < response.getAwardedBadgesCount(); i++) { + EquipBadgeMessage msg1 = EquipBadgeMessage.newBuilder() + .setBadgeType(response.getAwardedBadges(i)) + .setBadgeTypeValue(response.getAwardedBadgeLevels(i)).build(); + ServerRequest serverRequest1 = new ServerRequest(RequestType.EQUIP_BADGE, msg1); + api.getRequestHandler().sendServerRequests(serverRequest1); + EquipBadgeResponseOuterClass.EquipBadgeResponse response1; + try { + response1 = EquipBadgeResponseOuterClass.EquipBadgeResponse.parseFrom(serverRequest1.getData()); + badge = response1.getEquipped(); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + } + } + } + /** * Gets currency. * * @param currency the currency * @return the currency * @throws InvalidCurrencyException the invalid currency exception + * @throws LoginFailedException when the auth is invalid + * @throws RemoteServerException when the server is down/having issues */ - public int getCurrency(Currency currency) throws InvalidCurrencyException { + public int getCurrency(Currency currency) + throws InvalidCurrencyException, LoginFailedException, RemoteServerException { + if (!init) { + updateProfile(); + } if (currencies.containsKey(currency)) { return currencies.get(currency); } else { @@ -161,4 +213,96 @@ public int getCurrency(Currency currency) throws InvalidCurrencyException { public enum Currency { STARDUST, POKECOIN; } + + /** + * Gets raw player data proto + * + * @return Player data + * @throws LoginFailedException when the auth is invalid + * @throws RemoteServerException when the server is down/having issues + */ + public PlayerData getPlayerData() + throws LoginFailedException, RemoteServerException { + if (!init) { + updateProfile(); + } + return playerData; + } + + /** + * Gets avatar + * + * @return Player Avatar object + * @throws LoginFailedException when the auth is invalid + * @throws RemoteServerException when the server is down/having issues + */ + public PlayerAvatar getAvatar() + throws LoginFailedException, RemoteServerException { + if (!init) { + updateProfile(); + } + return avatar; + } + + /** + * Gets daily bonus + * + * @return DailyBonus object + * @throws LoginFailedException when the auth is invalid + * @throws RemoteServerException when the server is down/having issues + */ + public DailyBonus getDailyBonus() + throws LoginFailedException, RemoteServerException { + if (!init) { + updateProfile(); + } + return dailyBonus; + } + + /** + * Gets contact settings + * + * @return ContactSettings object + * @throws LoginFailedException when the auth is invalid + * @throws RemoteServerException when the server is down/having issues + */ + public ContactSettings getContactSettings() + throws LoginFailedException, RemoteServerException { + if (!init) { + updateProfile(); + } + return contactSettings; + } + + /** + * Gets a map of all currencies + * + * @return map of currencies + * @throws LoginFailedException when the auth is invalid + * @throws RemoteServerException when the server is down/having issues + */ + public Map getCurrencies() + throws LoginFailedException, RemoteServerException { + if (!init) { + updateProfile(); + } + return currencies; + } + + + + /** + * Gets player stats + * + * @return stats API objet + * @throws LoginFailedException when the auth is invalid + * @throws RemoteServerException when the server is down/having issues + */ + public Stats getStats() + throws LoginFailedException, RemoteServerException { + if (stats == null) { + api.getInventories().updateInventories(); + } + return stats; + } } diff --git a/src/main/java/com/pokegoapi/api/pokemon/EggPokemon.java b/src/main/java/com/pokegoapi/api/pokemon/EggPokemon.java index be16eb7d..136fbeb9 100644 --- a/src/main/java/com/pokegoapi/api/pokemon/EggPokemon.java +++ b/src/main/java/com/pokegoapi/api/pokemon/EggPokemon.java @@ -17,14 +17,12 @@ import POGOProtos.Data.PokemonDataOuterClass.PokemonData; import POGOProtos.Networking.Responses.UseItemEggIncubatorResponseOuterClass.UseItemEggIncubatorResponse; - import com.annimon.stream.Stream; import com.annimon.stream.function.Predicate; import com.pokegoapi.api.PokemonGo; import com.pokegoapi.api.inventory.EggIncubator; import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; - import lombok.Setter; /** @@ -58,7 +56,7 @@ public UseItemEggIncubatorResponse.Result incubate(EggIncubator incubator) * Get the current distance that has been done with this egg * @return get distance already walked */ - public double getEggKmWalked() { + public double getEggKmWalked() throws LoginFailedException, RemoteServerException { if (!isIncubate()) return 0; EggIncubator incubator = Stream.of(pgo.getInventories().getIncubators()) diff --git a/src/main/java/com/pokegoapi/api/pokemon/EvolutionForm.java b/src/main/java/com/pokegoapi/api/pokemon/EvolutionForm.java new file mode 100644 index 00000000..49fe3301 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/pokemon/EvolutionForm.java @@ -0,0 +1,29 @@ +package com.pokegoapi.api.pokemon; + +import java.util.List; + +import POGOProtos.Enums.PokemonIdOuterClass; + +public class EvolutionForm { + private static PokemonIdOuterClass.PokemonId pokemonId; + + EvolutionForm(PokemonIdOuterClass.PokemonId pokemonId) { + this.pokemonId = pokemonId; + } + + public boolean isFullyEvolved() { + return EvolutionInfo.isFullyEvolved(pokemonId); + } + + public List getEvolutionForms() { + return EvolutionInfo.getEvolutionForms(pokemonId); + } + + public int getEvolutionStage() { + return EvolutionInfo.getEvolutionStage(pokemonId); + } + + public static PokemonIdOuterClass.PokemonId getPokemonId() { + return pokemonId; + } +} diff --git a/src/main/java/com/pokegoapi/api/pokemon/EvolutionInfo.java b/src/main/java/com/pokegoapi/api/pokemon/EvolutionInfo.java new file mode 100644 index 00000000..920a8fd1 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/pokemon/EvolutionInfo.java @@ -0,0 +1,443 @@ +package com.pokegoapi.api.pokemon; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +import POGOProtos.Enums.PokemonIdOuterClass; + +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.ABRA; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.AERODACTYL; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.ALAKAZAM; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.ARBOK; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.ARCANINE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.ARTICUNO; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.BEEDRILL; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.BELLSPROUT; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.BLASTOISE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.BULBASAUR; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.BUTTERFREE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.CATERPIE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.CHANSEY; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.CHARIZARD; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.CHARMANDER; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.CHARMELEON; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.CLEFABLE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.CLEFAIRY; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.CLOYSTER; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.CUBONE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.DEWGONG; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.DIGLETT; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.DITTO; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.DODRIO; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.DODUO; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.DRAGONAIR; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.DRAGONITE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.DRATINI; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.DROWZEE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.DUGTRIO; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.EEVEE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.EKANS; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.ELECTABUZZ; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.ELECTRODE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.EXEGGCUTE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.EXEGGUTOR; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.FARFETCHD; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.FEAROW; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.FLAREON; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.GASTLY; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.GENGAR; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.GEODUDE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.GLOOM; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.GOLBAT; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.GOLDEEN; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.GOLDUCK; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.GOLEM; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.GRAVELER; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.GRIMER; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.GROWLITHE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.GYARADOS; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.HAUNTER; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.HITMONCHAN; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.HITMONLEE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.HORSEA; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.HYPNO; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.IVYSAUR; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.JIGGLYPUFF; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.JOLTEON; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.JYNX; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.KABUTO; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.KABUTOPS; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.KADABRA; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.KAKUNA; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.KANGASKHAN; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.KINGLER; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.KOFFING; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.KRABBY; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.LAPRAS; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.LICKITUNG; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MACHAMP; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MACHOKE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MACHOP; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MAGIKARP; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MAGMAR; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MAGNEMITE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MAGNETON; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MANKEY; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MAROWAK; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MEOWTH; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.METAPOD; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MEW; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MEWTWO; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MOLTRES; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MR_MIME; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.MUK; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.NIDOKING; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.NIDOQUEEN; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.NIDORAN_FEMALE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.NIDORAN_MALE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.NIDORINA; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.NIDORINO; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.NINETALES; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.ODDISH; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.OMANYTE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.OMASTAR; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.ONIX; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.PARAS; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.PARASECT; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.PERSIAN; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.PIDGEOT; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.PIDGEOTTO; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.PIDGEY; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.PIKACHU; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.PINSIR; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.POLIWAG; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.POLIWHIRL; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.POLIWRATH; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.PONYTA; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.PORYGON; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.PRIMEAPE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.PSYDUCK; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.RAICHU; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.RAPIDASH; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.RATICATE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.RATTATA; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.RHYDON; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.RHYHORN; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.SANDSHREW; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.SANDSLASH; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.SCYTHER; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.SEADRA; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.SEAKING; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.SEEL; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.SHELLDER; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.SLOWBRO; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.SLOWPOKE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.SNORLAX; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.SPEAROW; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.SQUIRTLE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.STARMIE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.STARYU; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.TANGELA; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.TAUROS; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.TENTACOOL; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.TENTACRUEL; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.VAPOREON; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.VENOMOTH; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.VENONAT; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.VENUSAUR; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.VICTREEBEL; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.VILEPLUME; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.VOLTORB; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.VULPIX; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.WARTORTLE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.WEEDLE; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.WEEPINBELL; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.WEEZING; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.WIGGLYTUFF; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.ZAPDOS; +import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId.ZUBAT; +import static java.util.Arrays.asList; + +class EvolutionInfo { + private static final PokemonId[] BULBASAUR_EVOLUTION = {BULBASAUR, IVYSAUR, VENUSAUR}; + private static final PokemonId[] CHARMANDER_EVOLUTION = {CHARMANDER, CHARMELEON, CHARIZARD}; + private static final PokemonId[] SQUIRTLE_EVOLUTION = {SQUIRTLE, WARTORTLE, BLASTOISE}; + private static final PokemonId[] CATERPIE_EVOLUTION = {CATERPIE, METAPOD, BUTTERFREE}; + private static final PokemonId[] WEEDLE_EVOLUTION = {WEEDLE, KAKUNA, BEEDRILL}; + private static final PokemonId[] PIDGEY_EVOLUTION = {PIDGEY, PIDGEOTTO, PIDGEOT}; + private static final PokemonId[] RATTATA_EVOLUTION = {RATTATA, RATICATE}; + private static final PokemonId[] SPEAROW_EVOLUTION = {SPEAROW, FEAROW}; + private static final PokemonId[] EKANS_EVOLUTION = {EKANS, ARBOK}; + private static final PokemonId[] PIKACHU_EVOLUTION = {PIKACHU, RAICHU}; + private static final PokemonId[] SANDSHREW_EVOLUTION = {SANDSHREW, SANDSLASH}; + private static final PokemonId[] NIDORAN_FEMALE_EVOLUTION = {NIDORAN_FEMALE, NIDORINA, NIDOQUEEN}; + private static final PokemonId[] NIDORAN_MALE_EVOLUTION = {NIDORAN_MALE, NIDORINO, NIDOKING}; + private static final PokemonId[] CLEFAIRY_EVOLUTION = {CLEFAIRY, CLEFABLE}; + private static final PokemonId[] VULPIX_EVOLUTION = {VULPIX, NINETALES}; + private static final PokemonId[] JIGGLYPUFF_EVOLUTION = {JIGGLYPUFF, WIGGLYTUFF}; + private static final PokemonId[] ZUBAT_EVOLUTION = {ZUBAT, GOLBAT}; + private static final PokemonId[] ODDISH_EVOLUTION = {ODDISH, GLOOM, VILEPLUME}; + private static final PokemonId[] PARAS_EVOLUTION = {PARAS, PARASECT}; + private static final PokemonId[] VENONAT_EVOLUTION = {VENONAT, VENOMOTH}; + private static final PokemonId[] DIGLETT_EVOLUTION = {DIGLETT, DUGTRIO}; + private static final PokemonId[] MEOWTH_EVOLUTION = {MEOWTH, PERSIAN}; + private static final PokemonId[] PSYDUCK_EVOLUTION = {PSYDUCK, GOLDUCK}; + private static final PokemonId[] MANKEY_EVOLUTION = {MANKEY, PRIMEAPE}; + private static final PokemonId[] GROWLITHE_EVOLUTION = {GROWLITHE, ARCANINE}; + private static final PokemonId[] POLIWAG_EVOLUTION = {POLIWAG, POLIWHIRL, POLIWRATH}; + private static final PokemonId[] ABRA_EVOLUTION = {ABRA, KADABRA, ALAKAZAM}; + private static final PokemonId[] MACHOP_EVOLUTION = {MACHOP, MACHOKE, MACHAMP}; + private static final PokemonId[] BELLSPROUT_EVOLUTION = {BELLSPROUT, WEEPINBELL, VICTREEBEL}; + private static final PokemonId[] TENTACOOL_EVOLUTION = {TENTACOOL, TENTACRUEL}; + private static final PokemonId[] GEODUDE_EVOLUTION = {GEODUDE, GRAVELER, GOLEM}; + private static final PokemonId[] PONYTA_EVOLUTION = {PONYTA, RAPIDASH}; + private static final PokemonId[] SLOWPOKE_EVOLUTION = {SLOWPOKE, SLOWBRO}; + private static final PokemonId[] MAGNEMITE_EVOLUTION = {MAGNEMITE, MAGNETON}; + private static final PokemonId[] FARFETCHD_EVOLUTION = {FARFETCHD}; + private static final PokemonId[] DODUO_EVOLUTION = {DODUO, DODRIO}; + private static final PokemonId[] SEEL_EVOLUTION = {SEEL, DEWGONG}; + private static final PokemonId[] GRIMER_EVOLUTION = {GRIMER, MUK}; + private static final PokemonId[] SHELLDER_EVOLUTION = {SHELLDER, CLOYSTER}; + private static final PokemonId[] GASTLY_EVOLUTION = {GASTLY, HAUNTER, GENGAR}; + private static final PokemonId[] ONIX_EVOLUTION = {ONIX}; + private static final PokemonId[] DROWZEE_EVOLUTION = {DROWZEE, HYPNO}; + private static final PokemonId[] KRABBY_EVOLUTION = {KRABBY, KINGLER}; + private static final PokemonId[] VOLTORB_EVOLUTION = {VOLTORB, ELECTRODE}; + private static final PokemonId[] EXEGGCUTE_EVOLUTION = {EXEGGCUTE, EXEGGUTOR}; + private static final PokemonId[] CUBONE_EVOLUTION = {CUBONE, MAROWAK}; + private static final PokemonId[] HITMONLEE_EVOLUTION = {HITMONLEE, HITMONCHAN}; + private static final PokemonId[] LICKITUNG_EVOLUTION = {LICKITUNG}; + private static final PokemonId[] KOFFING_EVOLUTION = {KOFFING, WEEZING}; + private static final PokemonId[] RHYHORN_EVOLUTION = {RHYHORN, RHYDON}; + private static final PokemonId[] CHANSEY_EVOLUTION = {CHANSEY}; + private static final PokemonId[] TANGELA_EVOLUTION = {TANGELA}; + private static final PokemonId[] KANGASKHAN_EVOLUTION = {KANGASKHAN}; + private static final PokemonId[] HORSEA_EVOLUTION = {HORSEA, SEADRA}; + private static final PokemonId[] GOLDEEN_EVOLUTION = {GOLDEEN, SEAKING}; + private static final PokemonId[] STARYU_EVOLUTION = {STARYU, STARMIE}; + private static final PokemonId[] MR_MIME_EVOLUTION = {MR_MIME}; + private static final PokemonId[] SCYTHER_EVOLUTION = {SCYTHER}; + private static final PokemonId[] JYNX_EVOLUTION = {JYNX}; + private static final PokemonId[] ELECTABUZZ_EVOLUTION = {ELECTABUZZ}; + private static final PokemonId[] MAGMAR_EVOLUTION = {MAGMAR}; + private static final PokemonId[] PINSIR_EVOLUTION = {PINSIR}; + private static final PokemonId[] TAUROS_EVOLUTION = {TAUROS}; + private static final PokemonId[] MAGIKARP_EVOLUTION = {MAGIKARP, GYARADOS}; + private static final PokemonId[] LAPRAS_EVOLUTION = {LAPRAS}; + private static final PokemonId[] DITTO_EVOLUTION = {DITTO}; + + // needs to be handled exceptionally + private static final PokemonId[] EEVEE_EVOLUTION = {EEVEE, VAPOREON, JOLTEON, FLAREON}; + + private static final PokemonId[] PORYGON_EVOLUTION = {PORYGON}; + private static final PokemonId[] OMANYTE_EVOLUTION = {OMANYTE, OMASTAR}; + private static final PokemonId[] KABUTO_EVOLUTION = {KABUTO, KABUTOPS}; + private static final PokemonId[] AERODACTYL_EVOLUTION = {AERODACTYL}; + private static final PokemonId[] SNORLAX_EVOLUTION = {SNORLAX}; + private static final PokemonId[] ARTICUNO_EVOLUTION = {ARTICUNO}; + private static final PokemonId[] ZAPDOS_EVOLUTION = {ZAPDOS}; + private static final PokemonId[] MOLTRES_EVOLUTION = {MOLTRES}; + private static final PokemonId[] DRATINI_EVOLUTION = {DRATINI, DRAGONAIR, DRAGONITE}; + private static final PokemonId[] MEWTWO_EVOLUTION = {MEWTWO}; + private static final PokemonId[] MEW_EVOLUTION = {MEW}; + + private static final Map EVOLUTION_INFO = new HashMap<>(); + + static { + EVOLUTION_INFO.put(BULBASAUR, BULBASAUR_EVOLUTION); + EVOLUTION_INFO.put(IVYSAUR, BULBASAUR_EVOLUTION); + EVOLUTION_INFO.put(VENUSAUR, BULBASAUR_EVOLUTION); + EVOLUTION_INFO.put(CHARMANDER, CHARMANDER_EVOLUTION); + EVOLUTION_INFO.put(CHARMELEON, CHARMANDER_EVOLUTION); + EVOLUTION_INFO.put(CHARIZARD, CHARMANDER_EVOLUTION); + EVOLUTION_INFO.put(SQUIRTLE, SQUIRTLE_EVOLUTION); + EVOLUTION_INFO.put(WARTORTLE, SQUIRTLE_EVOLUTION); + EVOLUTION_INFO.put(BLASTOISE, SQUIRTLE_EVOLUTION); + EVOLUTION_INFO.put(CATERPIE, CATERPIE_EVOLUTION); + EVOLUTION_INFO.put(METAPOD, CATERPIE_EVOLUTION); + EVOLUTION_INFO.put(BUTTERFREE, CATERPIE_EVOLUTION); + EVOLUTION_INFO.put(WEEDLE, WEEDLE_EVOLUTION); + EVOLUTION_INFO.put(KAKUNA, WEEDLE_EVOLUTION); + EVOLUTION_INFO.put(BEEDRILL, WEEDLE_EVOLUTION); + EVOLUTION_INFO.put(PIDGEY, PIDGEY_EVOLUTION); + EVOLUTION_INFO.put(PIDGEOTTO, PIDGEY_EVOLUTION); + EVOLUTION_INFO.put(PIDGEOT, PIDGEY_EVOLUTION); + EVOLUTION_INFO.put(RATTATA, RATTATA_EVOLUTION); + EVOLUTION_INFO.put(RATICATE, RATTATA_EVOLUTION); + EVOLUTION_INFO.put(SPEAROW, SPEAROW_EVOLUTION); + EVOLUTION_INFO.put(FEAROW, SPEAROW_EVOLUTION); + EVOLUTION_INFO.put(EKANS, EKANS_EVOLUTION); + EVOLUTION_INFO.put(ARBOK, EKANS_EVOLUTION); + EVOLUTION_INFO.put(PIKACHU, PIKACHU_EVOLUTION); + EVOLUTION_INFO.put(RAICHU, PIKACHU_EVOLUTION); + EVOLUTION_INFO.put(SANDSHREW, SANDSHREW_EVOLUTION); + EVOLUTION_INFO.put(SANDSLASH, SANDSHREW_EVOLUTION); + EVOLUTION_INFO.put(NIDORAN_FEMALE, NIDORAN_FEMALE_EVOLUTION); + EVOLUTION_INFO.put(NIDORINA, NIDORAN_FEMALE_EVOLUTION); + EVOLUTION_INFO.put(NIDOQUEEN, NIDORAN_FEMALE_EVOLUTION); + EVOLUTION_INFO.put(NIDORAN_MALE, NIDORAN_MALE_EVOLUTION); + EVOLUTION_INFO.put(NIDORINO, NIDORAN_MALE_EVOLUTION); + EVOLUTION_INFO.put(NIDOKING, NIDORAN_MALE_EVOLUTION); + EVOLUTION_INFO.put(CLEFAIRY, CLEFAIRY_EVOLUTION); + EVOLUTION_INFO.put(CLEFABLE, CLEFAIRY_EVOLUTION); + EVOLUTION_INFO.put(VULPIX, VULPIX_EVOLUTION); + EVOLUTION_INFO.put(NINETALES, VULPIX_EVOLUTION); + EVOLUTION_INFO.put(JIGGLYPUFF, JIGGLYPUFF_EVOLUTION); + EVOLUTION_INFO.put(WIGGLYTUFF, JIGGLYPUFF_EVOLUTION); + EVOLUTION_INFO.put(ZUBAT, ZUBAT_EVOLUTION); + EVOLUTION_INFO.put(GOLBAT, ZUBAT_EVOLUTION); + EVOLUTION_INFO.put(ODDISH, ODDISH_EVOLUTION); + EVOLUTION_INFO.put(GLOOM, ODDISH_EVOLUTION); + EVOLUTION_INFO.put(VILEPLUME, ODDISH_EVOLUTION); + EVOLUTION_INFO.put(PARAS, PARAS_EVOLUTION); + EVOLUTION_INFO.put(PARASECT, PARAS_EVOLUTION); + EVOLUTION_INFO.put(VENONAT, VENONAT_EVOLUTION); + EVOLUTION_INFO.put(VENOMOTH, VENONAT_EVOLUTION); + EVOLUTION_INFO.put(DIGLETT, DIGLETT_EVOLUTION); + EVOLUTION_INFO.put(DUGTRIO, DIGLETT_EVOLUTION); + EVOLUTION_INFO.put(MEOWTH, MEOWTH_EVOLUTION); + EVOLUTION_INFO.put(PERSIAN, MEOWTH_EVOLUTION); + EVOLUTION_INFO.put(PSYDUCK, PSYDUCK_EVOLUTION); + EVOLUTION_INFO.put(GOLDUCK, PSYDUCK_EVOLUTION); + EVOLUTION_INFO.put(MANKEY, MANKEY_EVOLUTION); + EVOLUTION_INFO.put(PRIMEAPE, MANKEY_EVOLUTION); + EVOLUTION_INFO.put(GROWLITHE, GROWLITHE_EVOLUTION); + EVOLUTION_INFO.put(ARCANINE, GROWLITHE_EVOLUTION); + EVOLUTION_INFO.put(POLIWAG, POLIWAG_EVOLUTION); + EVOLUTION_INFO.put(POLIWHIRL, POLIWAG_EVOLUTION); + EVOLUTION_INFO.put(POLIWRATH, POLIWAG_EVOLUTION); + EVOLUTION_INFO.put(ABRA, ABRA_EVOLUTION); + EVOLUTION_INFO.put(KADABRA, ABRA_EVOLUTION); + EVOLUTION_INFO.put(ALAKAZAM, ABRA_EVOLUTION); + EVOLUTION_INFO.put(MACHOP, MACHOP_EVOLUTION); + EVOLUTION_INFO.put(MACHOKE, MACHOP_EVOLUTION); + EVOLUTION_INFO.put(MACHAMP, MACHOP_EVOLUTION); + EVOLUTION_INFO.put(BELLSPROUT, BELLSPROUT_EVOLUTION); + EVOLUTION_INFO.put(WEEPINBELL, BELLSPROUT_EVOLUTION); + EVOLUTION_INFO.put(VICTREEBEL, BELLSPROUT_EVOLUTION); + EVOLUTION_INFO.put(TENTACOOL, TENTACOOL_EVOLUTION); + EVOLUTION_INFO.put(TENTACRUEL, TENTACOOL_EVOLUTION); + EVOLUTION_INFO.put(GEODUDE, GEODUDE_EVOLUTION); + EVOLUTION_INFO.put(GRAVELER, GEODUDE_EVOLUTION); + EVOLUTION_INFO.put(GOLEM, GEODUDE_EVOLUTION); + EVOLUTION_INFO.put(PONYTA, PONYTA_EVOLUTION); + EVOLUTION_INFO.put(RAPIDASH, PONYTA_EVOLUTION); + EVOLUTION_INFO.put(SLOWPOKE, SLOWPOKE_EVOLUTION); + EVOLUTION_INFO.put(SLOWBRO, SLOWPOKE_EVOLUTION); + EVOLUTION_INFO.put(MAGNEMITE, MAGNEMITE_EVOLUTION); + EVOLUTION_INFO.put(MAGNETON, MAGNEMITE_EVOLUTION); + EVOLUTION_INFO.put(FARFETCHD, FARFETCHD_EVOLUTION); + EVOLUTION_INFO.put(DODUO, DODUO_EVOLUTION); + EVOLUTION_INFO.put(DODRIO, DODUO_EVOLUTION); + EVOLUTION_INFO.put(SEEL, SEEL_EVOLUTION); + EVOLUTION_INFO.put(DEWGONG, SEEL_EVOLUTION); + EVOLUTION_INFO.put(GRIMER, GRIMER_EVOLUTION); + EVOLUTION_INFO.put(MUK, GRIMER_EVOLUTION); + EVOLUTION_INFO.put(SHELLDER, SHELLDER_EVOLUTION); + EVOLUTION_INFO.put(CLOYSTER, SHELLDER_EVOLUTION); + EVOLUTION_INFO.put(GASTLY, GASTLY_EVOLUTION); + EVOLUTION_INFO.put(HAUNTER, GASTLY_EVOLUTION); + EVOLUTION_INFO.put(GENGAR, GASTLY_EVOLUTION); + EVOLUTION_INFO.put(ONIX, ONIX_EVOLUTION); + EVOLUTION_INFO.put(DROWZEE, DROWZEE_EVOLUTION); + EVOLUTION_INFO.put(HYPNO, DROWZEE_EVOLUTION); + EVOLUTION_INFO.put(KRABBY, KRABBY_EVOLUTION); + EVOLUTION_INFO.put(KINGLER, KRABBY_EVOLUTION); + EVOLUTION_INFO.put(VOLTORB, VOLTORB_EVOLUTION); + EVOLUTION_INFO.put(ELECTRODE, VOLTORB_EVOLUTION); + EVOLUTION_INFO.put(EXEGGCUTE, EXEGGCUTE_EVOLUTION); + EVOLUTION_INFO.put(EXEGGUTOR, EXEGGCUTE_EVOLUTION); + EVOLUTION_INFO.put(CUBONE, CUBONE_EVOLUTION); + EVOLUTION_INFO.put(MAROWAK, CUBONE_EVOLUTION); + EVOLUTION_INFO.put(HITMONLEE, HITMONLEE_EVOLUTION); + EVOLUTION_INFO.put(HITMONCHAN, HITMONLEE_EVOLUTION); + EVOLUTION_INFO.put(LICKITUNG, LICKITUNG_EVOLUTION); + EVOLUTION_INFO.put(KOFFING, KOFFING_EVOLUTION); + EVOLUTION_INFO.put(WEEZING, KOFFING_EVOLUTION); + EVOLUTION_INFO.put(RHYHORN, RHYHORN_EVOLUTION); + EVOLUTION_INFO.put(RHYDON, RHYHORN_EVOLUTION); + EVOLUTION_INFO.put(CHANSEY, CHANSEY_EVOLUTION); + EVOLUTION_INFO.put(TANGELA, TANGELA_EVOLUTION); + EVOLUTION_INFO.put(KANGASKHAN, KANGASKHAN_EVOLUTION); + EVOLUTION_INFO.put(HORSEA, HORSEA_EVOLUTION); + EVOLUTION_INFO.put(SEADRA, HORSEA_EVOLUTION); + EVOLUTION_INFO.put(GOLDEEN, GOLDEEN_EVOLUTION); + EVOLUTION_INFO.put(SEAKING, GOLDEEN_EVOLUTION); + EVOLUTION_INFO.put(STARYU, STARYU_EVOLUTION); + EVOLUTION_INFO.put(STARMIE, STARYU_EVOLUTION); + EVOLUTION_INFO.put(MR_MIME, MR_MIME_EVOLUTION); + EVOLUTION_INFO.put(SCYTHER, SCYTHER_EVOLUTION); + EVOLUTION_INFO.put(JYNX, JYNX_EVOLUTION); + EVOLUTION_INFO.put(ELECTABUZZ, ELECTABUZZ_EVOLUTION); + EVOLUTION_INFO.put(MAGMAR, MAGMAR_EVOLUTION); + EVOLUTION_INFO.put(PINSIR, PINSIR_EVOLUTION); + EVOLUTION_INFO.put(TAUROS, TAUROS_EVOLUTION); + EVOLUTION_INFO.put(MAGIKARP, MAGIKARP_EVOLUTION); + EVOLUTION_INFO.put(GYARADOS, MAGIKARP_EVOLUTION); + EVOLUTION_INFO.put(LAPRAS, LAPRAS_EVOLUTION); + EVOLUTION_INFO.put(DITTO, DITTO_EVOLUTION); + + // needs to be handled exceptionally + EVOLUTION_INFO.put(EEVEE, EEVEE_EVOLUTION); + EVOLUTION_INFO.put(VAPOREON, EEVEE_EVOLUTION); + EVOLUTION_INFO.put(JOLTEON, EEVEE_EVOLUTION); + EVOLUTION_INFO.put(FLAREON, EEVEE_EVOLUTION); + + EVOLUTION_INFO.put(PORYGON, PORYGON_EVOLUTION); + EVOLUTION_INFO.put(OMANYTE, OMANYTE_EVOLUTION); + EVOLUTION_INFO.put(OMASTAR, OMANYTE_EVOLUTION); + EVOLUTION_INFO.put(KABUTO, KABUTO_EVOLUTION); + EVOLUTION_INFO.put(KABUTOPS, KABUTO_EVOLUTION); + EVOLUTION_INFO.put(AERODACTYL, AERODACTYL_EVOLUTION); + EVOLUTION_INFO.put(SNORLAX, SNORLAX_EVOLUTION); + EVOLUTION_INFO.put(ARTICUNO, ARTICUNO_EVOLUTION); + EVOLUTION_INFO.put(ZAPDOS, ZAPDOS_EVOLUTION); + EVOLUTION_INFO.put(MOLTRES, MOLTRES_EVOLUTION); + EVOLUTION_INFO.put(DRATINI, DRATINI_EVOLUTION); + EVOLUTION_INFO.put(DRAGONAIR, DRATINI_EVOLUTION); + EVOLUTION_INFO.put(DRAGONITE, DRATINI_EVOLUTION); + EVOLUTION_INFO.put(MEWTWO, MEWTWO_EVOLUTION); + EVOLUTION_INFO.put(MEW, MEW_EVOLUTION); + } + + /** + * Get evolution forms + * + * @param pokemonId pokemon id + * @return ordered evolution forms + */ + public static List getEvolutionForms(PokemonId pokemonId) { + List evolutionForms = new ArrayList<>(); + for (PokemonId id : EVOLUTION_INFO.get(pokemonId)) { + evolutionForms.add(new EvolutionForm(id)); + } + return evolutionForms; + } + + /** + * Tell if a pokemon is fully evolved + * + * @param pokemonId pokemon id + * @return true if a pokemon is fully evolved, false otherwise + */ + public static boolean isFullyEvolved(PokemonId pokemonId) { + PokemonId[] info = EVOLUTION_INFO.get(pokemonId); + return info[info.length - 1] == pokemonId; + } + + /** + * Get evolution stage number + * + * @param pokemonId pokemon id + * @return 0 based evolution stage number + */ + public static int getEvolutionStage(PokemonId pokemonId) { + return asList(VAPOREON, JOLTEON, FLAREON).contains(pokemonId) + ? 1 + : asList(EVOLUTION_INFO.get(pokemonId)).indexOf(pokemonId); + } +} diff --git a/src/main/java/com/pokegoapi/api/pokemon/Pokemon.java b/src/main/java/com/pokegoapi/api/pokemon/Pokemon.java index d13d6e67..2bae1840 100644 --- a/src/main/java/com/pokegoapi/api/pokemon/Pokemon.java +++ b/src/main/java/com/pokegoapi/api/pokemon/Pokemon.java @@ -24,23 +24,28 @@ import POGOProtos.Networking.Requests.Messages.NicknamePokemonMessageOuterClass.NicknamePokemonMessage; import POGOProtos.Networking.Requests.Messages.ReleasePokemonMessageOuterClass.ReleasePokemonMessage; import POGOProtos.Networking.Requests.Messages.SetFavoritePokemonMessageOuterClass.SetFavoritePokemonMessage; -import POGOProtos.Networking.Requests.Messages.UpgradePokemonMessageOuterClass; import POGOProtos.Networking.Requests.Messages.UpgradePokemonMessageOuterClass.UpgradePokemonMessage; +import POGOProtos.Networking.Requests.Messages.UseItemPotionMessageOuterClass; +import POGOProtos.Networking.Requests.Messages.UseItemReviveMessageOuterClass; import POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType; import POGOProtos.Networking.Responses.EvolvePokemonResponseOuterClass.EvolvePokemonResponse; import POGOProtos.Networking.Responses.NicknamePokemonResponseOuterClass.NicknamePokemonResponse; import POGOProtos.Networking.Responses.ReleasePokemonResponseOuterClass.ReleasePokemonResponse; import POGOProtos.Networking.Responses.ReleasePokemonResponseOuterClass.ReleasePokemonResponse.Result; import POGOProtos.Networking.Responses.SetFavoritePokemonResponseOuterClass.SetFavoritePokemonResponse; -import POGOProtos.Networking.Responses.UpgradePokemonResponseOuterClass; import POGOProtos.Networking.Responses.UpgradePokemonResponseOuterClass.UpgradePokemonResponse; +import POGOProtos.Networking.Responses.UseItemPotionResponseOuterClass; +import POGOProtos.Networking.Responses.UseItemReviveResponseOuterClass; import com.google.protobuf.InvalidProtocolBufferException; import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.api.inventory.Item; import com.pokegoapi.api.map.pokemon.EvolutionResult; import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.NoSuchItemException; import com.pokegoapi.exceptions.RemoteServerException; import com.pokegoapi.main.ServerRequest; import com.pokegoapi.util.Log; +import lombok.Getter; import lombok.Setter; /** @@ -52,13 +57,24 @@ public class Pokemon { private final PokemonGo pgo; private PokemonData proto; private PokemonMeta meta; + @Getter + @Setter + private int stamina; // API METHODS // // DELEGATE METHODS BELOW // + + /** + * Creates a Pokemon object with helper functions around the proto. + * + * @param api the api to use + * @param proto the proto from the server + */ public Pokemon(PokemonGo api, PokemonData proto) { this.pgo = api; this.proto = proto; + this.stamina = proto.getStamina(); } /** @@ -124,14 +140,14 @@ public NicknamePokemonResponse.Result renamePokemon(String nickname) } /** - * Function to mark the pokemon as favorite or not. - * - * @param markFavorite Mark Pokemon as Favorite? - * @return the SetFavoritePokemonResponse.Result - * @throws LoginFailedException the login failed exception - * @throws RemoteServerException the remote server exception - */ - public SetFavoritePokemonResponse.Result setFavoritePokemon(boolean markFavorite) + * Function to mark the pokemon as favorite or not. + * + * @param markFavorite Mark Pokemon as Favorite? + * @return the SetFavoritePokemonResponse.Result + * @throws LoginFailedException the login failed exception + * @throws RemoteServerException the remote server exception + */ + public SetFavoritePokemonResponse.Result setFavoritePokemon(boolean markFavorite) throws LoginFailedException, RemoteServerException { SetFavoritePokemonMessage reqMsg = SetFavoritePokemonMessage.newBuilder() .setPokemonId(getId()) @@ -181,6 +197,7 @@ public UpgradePokemonResponse.Result powerUp() throws LoginFailedException, Remo } /** + * dus * Evolve evolution result. * * @return the evolution result @@ -222,7 +239,8 @@ public PokemonMeta getMeta() { return meta; } - public int getCandy() { + + public int getCandy() throws LoginFailedException, RemoteServerException { return pgo.getInventories().getCandyjar().getCandies(getPokemonFamily()); } @@ -250,10 +268,6 @@ public int getCp() { return proto.getCp(); } - public int getStamina() { - return proto.getStamina(); - } - public int getMaxStamina() { return proto.getStaminaMax(); } @@ -294,6 +308,10 @@ public float getHeightM() { return proto.getHeightM(); } + public float getWeightKg() { + return proto.getWeightKg(); + } + public int getIndividualAttack() { return proto.getIndividualAttack(); } @@ -305,9 +323,10 @@ public int getIndividualDefense() { public int getIndividualStamina() { return proto.getIndividualStamina(); } - + /** * Calculates the pokemons IV ratio. + * * @return the pokemons IV ratio as a double between 0 and 1.0, 1.0 being perfect IVs */ public double getIvRatio() { @@ -341,9 +360,10 @@ public String getEggIncubatorId() { public long getCreationTimeMs() { return proto.getCreationTimeMs(); } - + /** * Checks whether the Pokémon is set as favorite. + * * @return true if the Pokémon is set as favorite */ public boolean isFavorite() { @@ -384,7 +404,227 @@ public double getBaseFleeRate() { return getMeta().getBaseFleeRate(); } + public float getLevel() { + return PokemonCpUtils.getLevelFromCpMultiplier(proto.getCpMultiplier() + proto.getAdditionalCpMultiplier()); + } + + /** + * Calculate the maximum CP for this individual pokemon + * + * @return The maximum CP for this pokemon + * @throws NoSuchItemException If the PokemonId value cannot be found in the {@link PokemonMetaRegistry}. + */ + public int getMaxCp() throws NoSuchItemException { + PokemonMeta pokemonMeta = PokemonMetaRegistry.getMeta(proto.getPokemonId()); + if (pokemonMeta == null) { + throw new NoSuchItemException("Cannot find meta data for " + proto.getPokemonId().name()); + } + int attack = proto.getIndividualAttack() + pokemonMeta.getBaseAttack(); + int defense = proto.getIndividualDefense() + pokemonMeta.getBaseDefense(); + int stamina = proto.getIndividualStamina() + pokemonMeta.getBaseStamina(); + return PokemonCpUtils.getMaxCp(attack, defense, stamina); + } + + /** + * Calculates the absolute maximum CP for all pokemons with this PokemonId + * + * @return The absolute maximum CP + * @throws NoSuchItemException If the PokemonId value cannot be found in the {@link PokemonMetaRegistry}. + */ + public int getAbsoluteMaxCp() throws NoSuchItemException { + return getAbsoluteMaxCp(proto.getPokemonId()); + } + + + /** + * Static helper to get the absolute maximum CP for pokemons with their PokemonId. + * @param id The {@link POGOProtos.Enums.PokemonIdOuterClass.PokemonId} of the Pokemon to get CP for. + * @return The absolute maximum CP + * @throws NoSuchItemException If the PokemonId value cannot be found in the {@link PokemonMetaRegistry}. + */ + public static int getAbsoluteMaxCp(PokemonIdOuterClass.PokemonId id) throws NoSuchItemException { + PokemonMeta pokemonMeta = PokemonMetaRegistry.getMeta(id); + if (pokemonMeta == null) { + throw new NoSuchItemException("Cannot find meta data for " + id); + } + int attack = 15 + pokemonMeta.getBaseAttack(); + int defense = 15 + pokemonMeta.getBaseDefense(); + int stamina = 15 + pokemonMeta.getBaseStamina(); + return PokemonCpUtils.getMaxCp(attack, defense, stamina); + } + + + /** + * @return The CP for this pokemon after powerup + */ + public int getCpAfterPowerup() { + return PokemonCpUtils.getCpAfterPowerup(proto.getCp(), + proto.getCpMultiplier() + proto.getAdditionalCpMultiplier()); + } + + /** + * @return Cost of candy for a powerup + */ + public int getCandyCostsForPowerup() { + return PokemonCpUtils.getCandyCostsForPowerup(proto.getCpMultiplier() + proto.getAdditionalCpMultiplier(), + proto.getNumUpgrades()); + } + + /** + * @return Cost of stardust for a powerup + */ + public int getStardustCostsForPowerup() { + return PokemonCpUtils.getStartdustCostsForPowerup(proto.getCpMultiplier() + proto.getAdditionalCpMultiplier(), + proto.getNumUpgrades()); + } + public PokemonIdOuterClass.PokemonId getParent() { return getMeta().getParentId(); } + + /** + * Check if pokemon its injured but not fainted. need potions to heal + * + * @return true if pokemon is injured + */ + public boolean isInjured() { + return !isFainted() && getStamina() < getMaxStamina(); + } + + /** + * check if a pokemon it's died (fainted). need a revive to resurrect + * + * @return true if a pokemon is fainted + */ + public boolean isFainted() { + return getStamina() == 0; + } + + /** + * Heal a pokemon, using various fallbacks for potions + * + * @return Result, ERROR_CANNOT_USE if the requirements arent met + * @throws LoginFailedException If login failed. + * @throws RemoteServerException If server communication issues occurred. + */ + public UseItemPotionResponseOuterClass.UseItemPotionResponse.Result heal() + throws LoginFailedException, RemoteServerException { + + if (!isInjured()) + return UseItemPotionResponseOuterClass.UseItemPotionResponse.Result.ERROR_CANNOT_USE; + + if (pgo.getInventories().getItemBag().getItem(ItemId.ITEM_POTION).getCount() > 0) + return usePotion(ItemId.ITEM_POTION); + + if (pgo.getInventories().getItemBag().getItem(ItemId.ITEM_SUPER_POTION).getCount() > 0) + return usePotion(ItemId.ITEM_SUPER_POTION); + + if (pgo.getInventories().getItemBag().getItem(ItemId.ITEM_HYPER_POTION).getCount() > 0) + return usePotion(ItemId.ITEM_HYPER_POTION); + + if (pgo.getInventories().getItemBag().getItem(ItemId.ITEM_MAX_POTION).getCount() > 0) + return usePotion(ItemId.ITEM_MAX_POTION); + + return UseItemPotionResponseOuterClass.UseItemPotionResponse.Result.ERROR_CANNOT_USE; + } + + /** + * use a potion on that pokemon. Will check if there is enough potions and if the pokemon need + * to be healed. + * @param itemId {@link ItemId} of the potion to use. + * @return Result, ERROR_CANNOT_USE if the requirements aren't met + * @throws LoginFailedException If login failed. + * @throws RemoteServerException If server communications failed. + */ + public UseItemPotionResponseOuterClass.UseItemPotionResponse.Result usePotion(ItemId itemId) + throws LoginFailedException, RemoteServerException { + + Item potion = pgo.getInventories().getItemBag().getItem(itemId); + //some sanity check, to prevent wrong use of this call + if (!potion.isPotion() || potion.getCount() < 1 || !isInjured()) + return UseItemPotionResponseOuterClass.UseItemPotionResponse.Result.ERROR_CANNOT_USE; + + UseItemPotionMessageOuterClass.UseItemPotionMessage reqMsg = UseItemPotionMessageOuterClass.UseItemPotionMessage + .newBuilder() + .setItemId(itemId) + .setPokemonId(getId()) + .build(); + + ServerRequest serverRequest = new ServerRequest(RequestType.USE_ITEM_POTION, reqMsg); + pgo.getRequestHandler().sendServerRequests(serverRequest); + + UseItemPotionResponseOuterClass.UseItemPotionResponse response; + try { + response = UseItemPotionResponseOuterClass.UseItemPotionResponse.parseFrom(serverRequest.getData()); + if (response.getResult() == UseItemPotionResponseOuterClass.UseItemPotionResponse.Result.SUCCESS) { + setStamina(response.getStamina()); + } + return response.getResult(); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + } + + /** + * Revive a pokemon, using various fallbacks for revive items + * + * @return Result, ERROR_CANNOT_USE if the requirements arent met + * @throws LoginFailedException If login failed. + * @throws RemoteServerException If server communications failed. + */ + public UseItemReviveResponseOuterClass.UseItemReviveResponse.Result revive() + throws LoginFailedException, RemoteServerException { + + if (!isFainted()) + return UseItemReviveResponseOuterClass.UseItemReviveResponse.Result.ERROR_CANNOT_USE; + + if (pgo.getInventories().getItemBag().getItem(ItemId.ITEM_REVIVE).getCount() > 0) + return useRevive(ItemId.ITEM_REVIVE); + + if (pgo.getInventories().getItemBag().getItem(ItemId.ITEM_MAX_REVIVE).getCount() > 0) + return useRevive(ItemId.ITEM_MAX_REVIVE); + + return UseItemReviveResponseOuterClass.UseItemReviveResponse.Result.ERROR_CANNOT_USE; + } + + /** + * Use a revive item on the pokemon. Will check if there is enough revive & if the pokemon need + * to be revived. + * @param itemId {@link ItemId} of the Revive to use. + * @return Result, ERROR_CANNOT_USE if the requirements arent met + * @throws LoginFailedException If login failed. + * @throws RemoteServerException If server communications failed. + */ + public UseItemReviveResponseOuterClass.UseItemReviveResponse.Result useRevive(ItemId itemId) + throws LoginFailedException, RemoteServerException { + + Item item = pgo.getInventories().getItemBag().getItem(itemId); + if (!item.isRevive() || item.getCount() < 1 || !isFainted()) + return UseItemReviveResponseOuterClass.UseItemReviveResponse.Result.ERROR_CANNOT_USE; + + UseItemReviveMessageOuterClass.UseItemReviveMessage reqMsg = UseItemReviveMessageOuterClass.UseItemReviveMessage + .newBuilder() + .setItemId(itemId) + .setPokemonId(getId()) + .build(); + + ServerRequest serverRequest = new ServerRequest(RequestType.USE_ITEM_REVIVE, reqMsg); + pgo.getRequestHandler().sendServerRequests(serverRequest); + + UseItemReviveResponseOuterClass.UseItemReviveResponse response; + try { + response = UseItemReviveResponseOuterClass.UseItemReviveResponse.parseFrom(serverRequest.getData()); + if (response.getResult() == UseItemReviveResponseOuterClass.UseItemReviveResponse.Result.SUCCESS) { + setStamina(response.getStamina()); + } + return response.getResult(); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + } + + public EvolutionForm getEvolutionForm() { + return new EvolutionForm(getPokemonId()); + } + } diff --git a/src/main/java/com/pokegoapi/api/pokemon/PokemonCpUtils.java b/src/main/java/com/pokegoapi/api/pokemon/PokemonCpUtils.java new file mode 100644 index 00000000..4bebdba6 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/pokemon/PokemonCpUtils.java @@ -0,0 +1,256 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.api.pokemon; + +import java.util.HashMap; +import java.util.Map; + +/** + * Information in this class is based on: + * http://pokemongo.gamepress.gg/cp-multiplier + * and + * http://pokemongo.gamepress.gg/pokemon-stats-advanced + */ +class PokemonCpUtils { + private static final Map LEVEL_CPMULTIPLIER = new HashMap<>(); + + static { + LEVEL_CPMULTIPLIER.put(1f, 0.094f); + LEVEL_CPMULTIPLIER.put(1.5f, 0.135137432f); + LEVEL_CPMULTIPLIER.put(2f, 0.16639787f); + LEVEL_CPMULTIPLIER.put(2.5f, 0.192650919f); + LEVEL_CPMULTIPLIER.put(3f, 0.21573247f); + LEVEL_CPMULTIPLIER.put(3.5f, 0.236572661f); + LEVEL_CPMULTIPLIER.put(4f, 0.25572005f); + LEVEL_CPMULTIPLIER.put(4.5f, 0.273530381f); + LEVEL_CPMULTIPLIER.put(5f, 0.29024988f); + LEVEL_CPMULTIPLIER.put(5.5f, 0.306057377f); + LEVEL_CPMULTIPLIER.put(6f, 0.3210876f); + LEVEL_CPMULTIPLIER.put(6.5f, 0.335445036f); + LEVEL_CPMULTIPLIER.put(7f, 0.34921268f); + LEVEL_CPMULTIPLIER.put(7.5f, 0.362457751f); + LEVEL_CPMULTIPLIER.put(8f, 0.37523559f); + LEVEL_CPMULTIPLIER.put(8.5f, 0.387592406f); + LEVEL_CPMULTIPLIER.put(9f, 0.39956728f); + LEVEL_CPMULTIPLIER.put(9.5f, 0.411193551f); + LEVEL_CPMULTIPLIER.put(10f, 0.42250001f); + LEVEL_CPMULTIPLIER.put(10.5f, 0.432926419f); + LEVEL_CPMULTIPLIER.put(11f, 0.44310755f); + LEVEL_CPMULTIPLIER.put(11.5f, 0.453059958f); + LEVEL_CPMULTIPLIER.put(12f, 0.46279839f); + LEVEL_CPMULTIPLIER.put(12.5f, 0.472336083f); + LEVEL_CPMULTIPLIER.put(13f, 0.48168495f); + LEVEL_CPMULTIPLIER.put(13.5f, 0.4908558f); + LEVEL_CPMULTIPLIER.put(14f, 0.49985844f); + LEVEL_CPMULTIPLIER.put(14.5f, 0.508701765f); + LEVEL_CPMULTIPLIER.put(15f, 0.51739395f); + LEVEL_CPMULTIPLIER.put(15.5f, 0.525942511f); + LEVEL_CPMULTIPLIER.put(16f, 0.53435433f); + LEVEL_CPMULTIPLIER.put(16.5f, 0.542635767f); + LEVEL_CPMULTIPLIER.put(17f, 0.55079269f); + LEVEL_CPMULTIPLIER.put(17.5f, 0.558830576f); + LEVEL_CPMULTIPLIER.put(18f, 0.56675452f); + LEVEL_CPMULTIPLIER.put(18.5f, 0.574569153f); + LEVEL_CPMULTIPLIER.put(19f, 0.58227891f); + LEVEL_CPMULTIPLIER.put(19.5f, 0.589887917f); + LEVEL_CPMULTIPLIER.put(20f, 0.59740001f); + LEVEL_CPMULTIPLIER.put(20.5f, 0.604818814f); + LEVEL_CPMULTIPLIER.put(21f, 0.61215729f); + LEVEL_CPMULTIPLIER.put(21.5f, 0.619399365f); + LEVEL_CPMULTIPLIER.put(22f, 0.62656713f); + LEVEL_CPMULTIPLIER.put(22.5f, 0.633644533f); + LEVEL_CPMULTIPLIER.put(23f, 0.64065295f); + LEVEL_CPMULTIPLIER.put(23.5f, 0.647576426f); + LEVEL_CPMULTIPLIER.put(24f, 0.65443563f); + LEVEL_CPMULTIPLIER.put(24.5f, 0.661214806f); + LEVEL_CPMULTIPLIER.put(25f, 0.667934f); + LEVEL_CPMULTIPLIER.put(25.5f, 0.674577537f); + LEVEL_CPMULTIPLIER.put(26f, 0.68116492f); + LEVEL_CPMULTIPLIER.put(26.5f, 0.687680648f); + LEVEL_CPMULTIPLIER.put(27f, 0.69414365f); + LEVEL_CPMULTIPLIER.put(27.5f, 0.700538673f); + LEVEL_CPMULTIPLIER.put(28f, 0.70688421f); + LEVEL_CPMULTIPLIER.put(28.5f, 0.713164996f); + LEVEL_CPMULTIPLIER.put(29f, 0.71939909f); + LEVEL_CPMULTIPLIER.put(29.5f, 0.725571552f); + LEVEL_CPMULTIPLIER.put(30f, 0.7317f); + LEVEL_CPMULTIPLIER.put(30.5f, 0.734741009f); + LEVEL_CPMULTIPLIER.put(31f, 0.73776948f); + LEVEL_CPMULTIPLIER.put(31.5f, 0.740785574f); + LEVEL_CPMULTIPLIER.put(32f, 0.74378943f); + LEVEL_CPMULTIPLIER.put(32.5f, 0.746781211f); + LEVEL_CPMULTIPLIER.put(33f, 0.74976104f); + LEVEL_CPMULTIPLIER.put(33.5f, 0.752729087f); + LEVEL_CPMULTIPLIER.put(34f, 0.75568551f); + LEVEL_CPMULTIPLIER.put(34.5f, 0.758630378f); + LEVEL_CPMULTIPLIER.put(35f, 0.76156384f); + LEVEL_CPMULTIPLIER.put(35.5f, 0.764486065f); + LEVEL_CPMULTIPLIER.put(36f, 0.76739717f); + LEVEL_CPMULTIPLIER.put(36.5f, 0.770297266f); + LEVEL_CPMULTIPLIER.put(37f, 0.7731865f); + LEVEL_CPMULTIPLIER.put(37.5f, 0.776064962f); + LEVEL_CPMULTIPLIER.put(38f, 0.77893275f); + LEVEL_CPMULTIPLIER.put(38.5f, 0.781790055f); + LEVEL_CPMULTIPLIER.put(39f, 0.78463697f); + LEVEL_CPMULTIPLIER.put(39.5f, 0.787473578f); + LEVEL_CPMULTIPLIER.put(40f, 0.79030001f); + } + + private static float getLevel(float cpMuliplier) { + float level; + if (cpMuliplier < 0.734f) { + // compute polynomial approximation obtained by regression + level = 58.35178527f * cpMuliplier * cpMuliplier - 2.838007664f * cpMuliplier + 0.8539209906f; + } else { + // compute linear approximation obtained by regression + level = 171.0112688f * cpMuliplier - 95.20425243f; + } + // round to nearest .5 value and return + return Math.round((level) * 2) / 2.0f; + } + + /** + * Get the level from the cp multiplier + * @param cpMultiplier All CP multiplier values combined + * @return Level + */ + static float getLevelFromCpMultiplier(float cpMultiplier) { + return getLevel(cpMultiplier); + } + + /** + * Get the maximum CP from the values + * @param attack All attack values combined + * @param defense All defense values combined + * @param stamina All stamina values combined + * @return Maximum CP for these levels + */ + static int getMaxCp(int attack, int defense, int stamina) { + float maxCpMultplier = LEVEL_CPMULTIPLIER.get(40f); + return (int)(attack * Math.pow(defense, 0.5) * Math.pow(stamina, 0.5) * Math.pow(maxCpMultplier,2) / 10f); + } + + /** + * Get the CP after powerup + * @param cp Current CP level + * @param cpMultiplier All CP multiplier values combined + * @return New CP level + */ + static int getCpAfterPowerup(float cp, float cpMultiplier) { + // Based on http://pokemongo.gamepress.gg/power-up-costs + float level = getLevelFromCpMultiplier(cpMultiplier); + if (level <= 10) { + return (int)((cp * 0.009426125469) / Math.pow(cpMultiplier, 2)); + } + if (level <= 20) { + return (int)((cp * 0.008919025675) / Math.pow(cpMultiplier, 2)); + } + if (level <= 30) { + return (int)((cp * 0.008924905903) / Math.pow(cpMultiplier, 2)); + } + return (int)((cp * 0.00445946079) / Math.pow(cpMultiplier, 2)); + } + + /** + * Get the amount of stardust required to do a powerup + * @param cpMultiplier All CP multiplier values combined + * @param powerups Number of previous powerups + * @return Amount of stardust + */ + static int getStartdustCostsForPowerup(float cpMultiplier, int powerups) { + // Based on http://pokemongo.gamepress.gg/power-up-costs + float level = getLevelFromCpMultiplier(cpMultiplier); + if (level <= 3 && powerups <= 4) { + return 200; + } + if (level <= 4 && powerups <= 8) { + return 400; + } + if (level <= 7 && powerups <= 12) { + return 600; + } + if (level <= 8 && powerups <= 16) { + return 800; + } + if (level <= 11 && powerups <= 20) { + return 1000; + } + if (level <= 13 && powerups <= 24) { + return 1300; + } + if (level <= 15 && powerups <= 28) { + return 1600; + } + if (level <= 17 && powerups <= 32) { + return 1900; + } + if (level <= 19 && powerups <= 36) { + return 2200; + } + if (level <= 21 && powerups <= 40) { + return 2500; + } + if (level <= 23 && powerups <= 44) { + return 3000; + } + if (level <= 25 && powerups <= 48) { + return 3500; + } + if (level <= 27 && powerups <= 52) { + return 4000; + } + if (level <= 29 && powerups <= 56) { + return 4500; + } + if (level <= 31 && powerups <= 60) { + return 5000; + } + if (level <= 33 && powerups <= 64) { + return 6000; + } + if (level <= 35 && powerups <= 68) { + return 7000; + } + if (level <= 37 && powerups <= 72) { + return 8000; + } + if (level <= 39 && powerups <= 76) { + return 9000; + } + return 10000; + } + + /** + * Get the amount of candy required to do a powerup + * @param cpMultiplier All CP multiplier values combined + * @param powerups Number of previous powerups + * @return Amount of candy + */ + static int getCandyCostsForPowerup(float cpMultiplier, int powerups) { + // Based on http://pokemongo.gamepress.gg/power-up-costs + float level = getLevelFromCpMultiplier(cpMultiplier); + if (level <= 13 && powerups <= 20 ) { + return 1; + } + if (level <= 21 && powerups <= 36 ) { + return 2; + } + if (level <= 31 && powerups <= 60 ) { + return 3; + } + return 4; + } +} diff --git a/src/main/java/com/pokegoapi/api/pokemon/PokemonMeta.java b/src/main/java/com/pokegoapi/api/pokemon/PokemonMeta.java index b0b4c9cf..974548f1 100644 --- a/src/main/java/com/pokegoapi/api/pokemon/PokemonMeta.java +++ b/src/main/java/com/pokegoapi/api/pokemon/PokemonMeta.java @@ -15,11 +15,9 @@ package com.pokegoapi.api.pokemon; -import POGOProtos.Enums.PokemonFamilyIdOuterClass; import POGOProtos.Enums.PokemonFamilyIdOuterClass.PokemonFamilyId; -import POGOProtos.Enums.PokemonIdOuterClass; import POGOProtos.Enums.PokemonIdOuterClass.PokemonId; -import lombok.Data; +import POGOProtos.Enums.PokemonMoveOuterClass.PokemonMove; import lombok.Getter; import lombok.Setter; @@ -116,6 +114,12 @@ public class PokemonMeta { private double cylGroundM; @Getter @Setter + private PokemonMove[] quickMoves; + @Getter + @Setter + private PokemonMove[] cinematicMoves; + @Getter + @Setter private int number; diff --git a/src/main/java/com/pokegoapi/api/pokemon/PokemonMetaRegistry.java b/src/main/java/com/pokegoapi/api/pokemon/PokemonMetaRegistry.java index 78cfd50e..659ba555 100644 --- a/src/main/java/com/pokegoapi/api/pokemon/PokemonMetaRegistry.java +++ b/src/main/java/com/pokegoapi/api/pokemon/PokemonMetaRegistry.java @@ -17,6 +17,7 @@ import POGOProtos.Enums.PokemonFamilyIdOuterClass.PokemonFamilyId; import POGOProtos.Enums.PokemonIdOuterClass.PokemonId; +import POGOProtos.Enums.PokemonMoveOuterClass.PokemonMove; import java.util.EnumMap; @@ -67,7 +68,7 @@ public class PokemonMetaRegistry { highestForFamily.put(PokemonFamilyId.FAMILY_SHELLDER, PokemonId.CLOYSTER); highestForFamily.put(PokemonFamilyId.FAMILY_GASTLY, PokemonId.GENGAR); highestForFamily.put(PokemonFamilyId.FAMILY_ONIX, PokemonId.ONIX); - highestForFamily.put(PokemonFamilyId.FAMILY_DROWZEE, PokemonId.DROWZEE); + highestForFamily.put(PokemonFamilyId.FAMILY_DROWZEE, PokemonId.HYPNO); highestForFamily.put(PokemonFamilyId.FAMILY_KRABBY, PokemonId.KINGLER); highestForFamily.put(PokemonFamilyId.FAMILY_VOLTORB, PokemonId.ELECTRODE); highestForFamily.put(PokemonFamilyId.FAMILY_EXEGGCUTE, PokemonId.EXEGGUTOR); @@ -105,7 +106,6 @@ public class PokemonMetaRegistry { highestForFamily.put(PokemonFamilyId.FAMILY_DRATINI, PokemonId.DRAGONITE); highestForFamily.put(PokemonFamilyId.FAMILY_MEWTWO, PokemonId.MEWTWO); highestForFamily.put(PokemonFamilyId.FAMILY_MEW, PokemonId.MEW); - highestForFamily.put(PokemonFamilyId.FAMILY_HYPNO, PokemonId.HYPNO); PokemonMeta metap; metap = new PokemonMeta(); @@ -139,11 +139,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.VINE_WHIP_FAST, + PokemonMove.TACKLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.SEED_BOMB, + PokemonMove.POWER_WHIP + }); metap.setNumber(1); meta.put(PokemonId.BULBASAUR, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0002_POKEMON_IVYSAUR"); metap.setFamily(PokemonFamilyId.FAMILY_BULBASAUR); @@ -175,11 +182,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.08); metap.setParentId(PokemonId.BULBASAUR); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.VINE_WHIP_FAST, + PokemonMove.RAZOR_LEAF_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.POWER_WHIP, + PokemonMove.SOLAR_BEAM + }); metap.setNumber(2); meta.put(PokemonId.IVYSAUR, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0003_POKEMON_VENUSAUR"); metap.setFamily(PokemonFamilyId.FAMILY_BULBASAUR); @@ -211,11 +225,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.04); metap.setParentId(PokemonId.IVYSAUR); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.VINE_WHIP_FAST, + PokemonMove.RAZOR_LEAF_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.PETAL_BLIZZARD, + PokemonMove.SOLAR_BEAM + }); metap.setNumber(3); meta.put(PokemonId.VENUSAUR, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0004_POKEMON_CHARMANDER"); metap.setFamily(PokemonFamilyId.FAMILY_CHARMANDER); @@ -247,11 +268,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.SCRATCH_FAST, + PokemonMove.EMBER_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.FLAME_CHARGE, + PokemonMove.FLAME_BURST, + PokemonMove.FLAMETHROWER + }); metap.setNumber(4); meta.put(PokemonId.CHARMANDER, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0005_POKEMON_CHARMELEON"); metap.setFamily(PokemonFamilyId.FAMILY_CHARMANDER); @@ -283,11 +311,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.08); metap.setParentId(PokemonId.CHARMANDER); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.SCRATCH_FAST, + PokemonMove.EMBER_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.FIRE_PUNCH, + PokemonMove.FLAME_BURST, + PokemonMove.FLAMETHROWER + }); metap.setNumber(5); meta.put(PokemonId.CHARMELEON, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0006_POKEMON_CHARIZARD"); metap.setFamily(PokemonFamilyId.FAMILY_CHARMANDER); @@ -319,11 +354,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.04); metap.setParentId(PokemonId.CHARMELEON); metap.setCylGroundM(0.405); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.WING_ATTACK_FAST, + PokemonMove.EMBER_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DRAGON_CLAW, + PokemonMove.FLAMETHROWER, + PokemonMove.FIRE_BLAST + }); metap.setNumber(6); meta.put(PokemonId.CHARIZARD, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0007_POKEMON_SQUIRTLE"); metap.setFamily(PokemonFamilyId.FAMILY_SQUIRTLE); @@ -355,11 +397,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.TACKLE_FAST, + PokemonMove.BUBBLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.AQUA_TAIL, + PokemonMove.WATER_PULSE, + PokemonMove.AQUA_JET + }); metap.setNumber(7); meta.put(PokemonId.SQUIRTLE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0008_POKEMON_WARTORTLE"); metap.setFamily(PokemonFamilyId.FAMILY_SQUIRTLE); @@ -391,11 +440,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.08); metap.setParentId(PokemonId.SQUIRTLE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.WATER_GUN_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.ICE_BEAM, + PokemonMove.HYDRO_PUMP, + PokemonMove.AQUA_JET + }); metap.setNumber(8); meta.put(PokemonId.WARTORTLE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0009_POKEMON_BLASTOISE"); metap.setFamily(PokemonFamilyId.FAMILY_SQUIRTLE); @@ -427,11 +483,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.04); metap.setParentId(PokemonId.WARTORTLE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.WATER_GUN_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.ICE_BEAM, + PokemonMove.FLASH_CANNON, + PokemonMove.HYDRO_PUMP + }); metap.setNumber(9); meta.put(PokemonId.BLASTOISE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0010_POKEMON_CATERPIE"); metap.setFamily(PokemonFamilyId.FAMILY_CATERPIE); @@ -463,11 +526,16 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BUG_BITE_FAST, + PokemonMove.TACKLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STRUGGLE + }); metap.setNumber(10); meta.put(PokemonId.CATERPIE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0011_POKEMON_METAPOD"); metap.setFamily(PokemonFamilyId.FAMILY_CATERPIE); @@ -499,11 +567,16 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.2); metap.setParentId(PokemonId.CATERPIE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BUG_BITE_FAST, + PokemonMove.TACKLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STRUGGLE + }); metap.setNumber(11); meta.put(PokemonId.METAPOD, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0012_POKEMON_BUTTERFREE"); metap.setFamily(PokemonFamilyId.FAMILY_CATERPIE); @@ -535,11 +608,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.1); metap.setParentId(PokemonId.METAPOD); metap.setCylGroundM(0.555); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST, + PokemonMove.BUG_BITE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.BUG_BUZZ, + PokemonMove.PSYCHIC, + PokemonMove.SIGNAL_BEAM + }); metap.setNumber(12); meta.put(PokemonId.BUTTERFREE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0013_POKEMON_WEEDLE"); metap.setFamily(PokemonFamilyId.FAMILY_WEEDLE); @@ -571,11 +651,16 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POISON_STING_FAST, + PokemonMove.BUG_BITE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STRUGGLE + }); metap.setNumber(13); meta.put(PokemonId.WEEDLE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0014_POKEMON_KAKUNA"); metap.setFamily(PokemonFamilyId.FAMILY_WEEDLE); @@ -607,11 +692,16 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.2); metap.setParentId(PokemonId.WEEDLE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POISON_STING_FAST, + PokemonMove.BUG_BITE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STRUGGLE + }); metap.setNumber(14); meta.put(PokemonId.KAKUNA, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0015_POKEMON_BEEDRILL"); metap.setFamily(PokemonFamilyId.FAMILY_WEEDLE); @@ -643,11 +733,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.1); metap.setParentId(PokemonId.KAKUNA); metap.setCylGroundM(0.385); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BUG_BITE_FAST, + PokemonMove.POISON_JAB_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.AERIAL_ACE, + PokemonMove.X_SCISSOR + }); metap.setNumber(15); meta.put(PokemonId.BEEDRILL, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0016_POKEMON_PIDGEY"); metap.setFamily(PokemonFamilyId.FAMILY_PIDGEY); @@ -679,11 +776,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.TACKLE_FAST, + PokemonMove.QUICK_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.TWISTER, + PokemonMove.AERIAL_ACE, + PokemonMove.AIR_CUTTER + }); metap.setNumber(16); meta.put(PokemonId.PIDGEY, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0017_POKEMON_PIDGEOTTO"); metap.setFamily(PokemonFamilyId.FAMILY_PIDGEY); @@ -715,11 +819,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.2); metap.setParentId(PokemonId.PIDGEY); metap.setCylGroundM(0.395); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.STEEL_WING_FAST, + PokemonMove.WING_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.TWISTER, + PokemonMove.AERIAL_ACE, + PokemonMove.AIR_CUTTER + }); metap.setNumber(17); meta.put(PokemonId.PIDGEOTTO, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0018_POKEMON_PIDGEOT"); metap.setFamily(PokemonFamilyId.FAMILY_PIDGEY); @@ -751,11 +862,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.1); metap.setParentId(PokemonId.PIDGEOTTO); metap.setCylGroundM(0.36); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.STEEL_WING_FAST, + PokemonMove.WING_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.HURRICANE, + PokemonMove.AERIAL_ACE, + PokemonMove.AIR_CUTTER + }); metap.setNumber(18); meta.put(PokemonId.PIDGEOT, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0019_POKEMON_RATTATA"); metap.setFamily(PokemonFamilyId.FAMILY_RATTATA); @@ -787,11 +905,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.QUICK_ATTACK_FAST, + PokemonMove.TACKLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DIG, + PokemonMove.BODY_SLAM, + PokemonMove.HYPER_FANG + }); metap.setNumber(19); meta.put(PokemonId.RATTATA, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0020_POKEMON_RATICATE"); metap.setFamily(PokemonFamilyId.FAMILY_RATTATA); @@ -823,11 +948,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.RATTATA); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.QUICK_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DIG, + PokemonMove.HYPER_BEAM, + PokemonMove.HYPER_FANG + }); metap.setNumber(20); meta.put(PokemonId.RATICATE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0021_POKEMON_SPEAROW"); metap.setFamily(PokemonFamilyId.FAMILY_SPEAROW); @@ -859,11 +991,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.QUICK_ATTACK_FAST, + PokemonMove.PECK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.TWISTER, + PokemonMove.AERIAL_ACE, + PokemonMove.DRILL_PECK + }); metap.setNumber(21); meta.put(PokemonId.SPEAROW, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0022_POKEMON_FEAROW"); metap.setFamily(PokemonFamilyId.FAMILY_SPEAROW); @@ -895,11 +1034,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.SPEAROW); metap.setCylGroundM(0.42); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.STEEL_WING_FAST, + PokemonMove.PECK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.TWISTER, + PokemonMove.AERIAL_ACE, + PokemonMove.DRILL_RUN + }); metap.setNumber(22); meta.put(PokemonId.FEAROW, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0023_POKEMON_EKANS"); metap.setFamily(PokemonFamilyId.FAMILY_EKANS); @@ -931,11 +1077,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POISON_STING_FAST, + PokemonMove.ACID_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.WRAP, + PokemonMove.GUNK_SHOT + }); metap.setNumber(23); meta.put(PokemonId.EKANS, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0024_POKEMON_ARBOK"); metap.setFamily(PokemonFamilyId.FAMILY_EKANS); @@ -967,11 +1120,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.EKANS); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.ACID_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DARK_PULSE, + PokemonMove.GUNK_SHOT, + PokemonMove.SLUDGE_WAVE + }); metap.setNumber(24); meta.put(PokemonId.ARBOK, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0025_POKEMON_PIKACHU"); metap.setFamily(PokemonFamilyId.FAMILY_PIKACHU); @@ -1003,11 +1163,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.QUICK_ATTACK_FAST, + PokemonMove.THUNDER_SHOCK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.THUNDER, + PokemonMove.THUNDERBOLT, + PokemonMove.DISCHARGE + }); metap.setNumber(25); meta.put(PokemonId.PIKACHU, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0026_POKEMON_RAICHU"); metap.setFamily(PokemonFamilyId.FAMILY_PIKACHU); @@ -1039,11 +1206,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.08); metap.setParentId(PokemonId.PIKACHU); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.SPARK_FAST, + PokemonMove.THUNDER_SHOCK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.THUNDER_PUNCH, + PokemonMove.THUNDER, + PokemonMove.BRICK_BREAK + }); metap.setNumber(26); meta.put(PokemonId.RAICHU, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0027_POKEMON_SANDSHREW"); metap.setFamily(PokemonFamilyId.FAMILY_SANDSHREW); @@ -1075,11 +1249,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.SCRATCH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DIG, + PokemonMove.ROCK_SLIDE, + PokemonMove.ROCK_TOMB + }); metap.setNumber(27); meta.put(PokemonId.SANDSHREW, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0028_POKEMON_SANDSLASH"); metap.setFamily(PokemonFamilyId.FAMILY_SANDSHREW); @@ -1111,11 +1292,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.SANDSHREW); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.METAL_CLAW_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.BULLDOZE, + PokemonMove.EARTHQUAKE, + PokemonMove.ROCK_TOMB + }); metap.setNumber(28); meta.put(PokemonId.SANDSLASH, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0029_POKEMON_NIDORAN"); metap.setFamily(PokemonFamilyId.FAMILY_NIDORAN_FEMALE); @@ -1147,11 +1335,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.POISON_STING_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.POISON_FANG, + PokemonMove.SLUDGE_BOMB, + PokemonMove.BODY_SLAM + }); metap.setNumber(29); meta.put(PokemonId.NIDORAN_FEMALE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0030_POKEMON_NIDORINA"); metap.setFamily(PokemonFamilyId.FAMILY_NIDORAN_FEMALE); @@ -1183,11 +1378,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.2); metap.setParentId(PokemonId.NIDORAN_FEMALE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.POISON_STING_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.POISON_FANG, + PokemonMove.DIG, + PokemonMove.SLUDGE_BOMB + }); metap.setNumber(30); meta.put(PokemonId.NIDORINA, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0031_POKEMON_NIDOQUEEN"); metap.setFamily(PokemonFamilyId.FAMILY_NIDORAN_FEMALE); @@ -1219,11 +1421,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.1); metap.setParentId(PokemonId.NIDORINA); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.POISON_JAB_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STONE_EDGE, + PokemonMove.EARTHQUAKE, + PokemonMove.SLUDGE_WAVE + }); metap.setNumber(31); meta.put(PokemonId.NIDOQUEEN, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0032_POKEMON_NIDORAN"); metap.setFamily(PokemonFamilyId.FAMILY_NIDORAN_MALE); @@ -1255,11 +1464,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POISON_STING_FAST, + PokemonMove.PECK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.HORN_ATTACK, + PokemonMove.BODY_SLAM + }); metap.setNumber(32); meta.put(PokemonId.NIDORAN_MALE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0033_POKEMON_NIDORINO"); metap.setFamily(PokemonFamilyId.FAMILY_NIDORAN_MALE); @@ -1291,11 +1507,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.2); metap.setParentId(PokemonId.NIDORAN_MALE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POISON_STING_FAST, + PokemonMove.POISON_JAB_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.DIG, + PokemonMove.HORN_ATTACK + }); metap.setNumber(33); meta.put(PokemonId.NIDORINO, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0034_POKEMON_NIDOKING"); metap.setFamily(PokemonFamilyId.FAMILY_NIDORAN_MALE); @@ -1327,11 +1550,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.1); metap.setParentId(PokemonId.NIDORINO); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.FURY_CUTTER_FAST, + PokemonMove.POISON_JAB_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.MEGAHORN, + PokemonMove.EARTHQUAKE, + PokemonMove.SLUDGE_WAVE + }); metap.setNumber(34); meta.put(PokemonId.NIDOKING, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0035_POKEMON_CLEFAIRY"); metap.setFamily(PokemonFamilyId.FAMILY_CLEFAIRY); @@ -1363,11 +1593,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.24); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POUND_FAST, + PokemonMove.ZEN_HEADBUTT_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DISARMING_VOICE, + PokemonMove.MOONBLAST, + PokemonMove.BODY_SLAM + }); metap.setNumber(35); meta.put(PokemonId.CLEFAIRY, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0036_POKEMON_CLEFABLE"); metap.setFamily(PokemonFamilyId.FAMILY_CLEFAIRY); @@ -1399,11 +1636,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.08); metap.setParentId(PokemonId.CLEFAIRY); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POUND_FAST, + PokemonMove.ZEN_HEADBUTT_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DAZZLING_GLEAM, + PokemonMove.PSYCHIC, + PokemonMove.MOONBLAST + }); metap.setNumber(36); meta.put(PokemonId.CLEFABLE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0037_POKEMON_VULPIX"); metap.setFamily(PokemonFamilyId.FAMILY_VULPIX); @@ -1435,11 +1679,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.24); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.EMBER_FAST, + PokemonMove.QUICK_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.FLAME_CHARGE, + PokemonMove.FLAMETHROWER, + PokemonMove.BODY_SLAM + }); metap.setNumber(37); meta.put(PokemonId.VULPIX, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0038_POKEMON_NINETALES"); metap.setFamily(PokemonFamilyId.FAMILY_VULPIX); @@ -1471,11 +1722,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.08); metap.setParentId(PokemonId.VULPIX); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.FEINT_ATTACK_FAST, + PokemonMove.EMBER_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.FLAMETHROWER, + PokemonMove.HEAT_WAVE, + PokemonMove.FIRE_BLAST + }); metap.setNumber(38); meta.put(PokemonId.NINETALES, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0039_POKEMON_JIGGLYPUFF"); metap.setFamily(PokemonFamilyId.FAMILY_JIGGLYPUFF); @@ -1507,11 +1765,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POUND_FAST, + PokemonMove.FEINT_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DISARMING_VOICE, + PokemonMove.PLAY_ROUGH, + PokemonMove.BODY_SLAM + }); metap.setNumber(39); meta.put(PokemonId.JIGGLYPUFF, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0040_POKEMON_WIGGLYTUFF"); metap.setFamily(PokemonFamilyId.FAMILY_JIGGLYPUFF); @@ -1543,11 +1808,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.JIGGLYPUFF); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POUND_FAST, + PokemonMove.FEINT_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DAZZLING_GLEAM, + PokemonMove.PLAY_ROUGH, + PokemonMove.HYPER_BEAM + }); metap.setNumber(40); meta.put(PokemonId.WIGGLYTUFF, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0041_POKEMON_ZUBAT"); metap.setFamily(PokemonFamilyId.FAMILY_ZUBAT); @@ -1579,11 +1851,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.535); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.QUICK_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.POISON_FANG, + PokemonMove.SLUDGE_BOMB, + PokemonMove.AIR_CUTTER + }); metap.setNumber(41); meta.put(PokemonId.ZUBAT, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0042_POKEMON_GOLBAT"); metap.setFamily(PokemonFamilyId.FAMILY_ZUBAT); @@ -1615,11 +1894,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.ZUBAT); metap.setCylGroundM(1.065); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.WING_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.POISON_FANG, + PokemonMove.AIR_CUTTER, + PokemonMove.OMINOUS_WIND + }); metap.setNumber(42); meta.put(PokemonId.GOLBAT, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0043_POKEMON_ODDISH"); metap.setFamily(PokemonFamilyId.FAMILY_ODDISH); @@ -1651,11 +1937,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.48); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ACID_FAST, + PokemonMove.RAZOR_LEAF_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.SEED_BOMB, + PokemonMove.MOONBLAST + }); metap.setNumber(43); meta.put(PokemonId.ODDISH, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0044_POKEMON_GLOOM"); metap.setFamily(PokemonFamilyId.FAMILY_ODDISH); @@ -1687,11 +1980,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.24); metap.setParentId(PokemonId.ODDISH); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ACID_FAST, + PokemonMove.RAZOR_LEAF_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.PETAL_BLIZZARD, + PokemonMove.MOONBLAST + }); metap.setNumber(44); meta.put(PokemonId.GLOOM, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0045_POKEMON_VILEPLUME"); metap.setFamily(PokemonFamilyId.FAMILY_ODDISH); @@ -1723,11 +2023,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.12); metap.setParentId(PokemonId.GLOOM); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ACID_FAST, + PokemonMove.RAZOR_LEAF_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.MOONBLAST, + PokemonMove.PETAL_BLIZZARD, + PokemonMove.SOLAR_BEAM + }); metap.setNumber(45); meta.put(PokemonId.VILEPLUME, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0046_POKEMON_PARAS"); metap.setFamily(PokemonFamilyId.FAMILY_PARAS); @@ -1759,11 +2066,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.32); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BUG_BITE_FAST, + PokemonMove.SCRATCH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.CROSS_POISON, + PokemonMove.X_SCISSOR, + PokemonMove.SEED_BOMB + }); metap.setNumber(46); meta.put(PokemonId.PARAS, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0047_POKEMON_PARASECT"); metap.setFamily(PokemonFamilyId.FAMILY_PARAS); @@ -1795,11 +2109,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.PARAS); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BUG_BITE_FAST, + PokemonMove.FURY_CUTTER_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.CROSS_POISON, + PokemonMove.X_SCISSOR, + PokemonMove.SOLAR_BEAM + }); metap.setNumber(47); meta.put(PokemonId.PARASECT, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0048_POKEMON_VENONAT"); metap.setFamily(PokemonFamilyId.FAMILY_VENONAT); @@ -1831,11 +2152,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST, + PokemonMove.BUG_BITE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DAZZLING_GLEAM, + PokemonMove.SHADOW_BALL, + PokemonMove.PSYBEAM + }); metap.setNumber(48); meta.put(PokemonId.VENONAT, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0049_POKEMON_VENOMOTH"); metap.setFamily(PokemonFamilyId.FAMILY_VENONAT); @@ -1867,11 +2195,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.VENONAT); metap.setCylGroundM(0.36); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST, + PokemonMove.BUG_BITE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.POISON_FANG, + PokemonMove.PSYCHIC, + PokemonMove.BUG_BUZZ + }); metap.setNumber(49); meta.put(PokemonId.VENOMOTH, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0050_POKEMON_DIGLETT"); metap.setFamily(PokemonFamilyId.FAMILY_DIGLETT); @@ -1903,11 +2238,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.SCRATCH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DIG, + PokemonMove.MUD_BOMB, + PokemonMove.ROCK_TOMB + }); metap.setNumber(50); meta.put(PokemonId.DIGLETT, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0051_POKEMON_DUGTRIO"); metap.setFamily(PokemonFamilyId.FAMILY_DIGLETT); @@ -1939,11 +2281,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.DIGLETT); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.SUCKER_PUNCH_FAST, + PokemonMove.MUD_SHOT_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STONE_EDGE, + PokemonMove.EARTHQUAKE, + PokemonMove.MUD_BOMB + }); metap.setNumber(51); meta.put(PokemonId.DUGTRIO, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0052_POKEMON_MEOWTH"); metap.setFamily(PokemonFamilyId.FAMILY_MEOWTH); @@ -1975,11 +2324,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.SCRATCH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DARK_PULSE, + PokemonMove.NIGHT_SLASH, + PokemonMove.BODY_SLAM + }); metap.setNumber(52); meta.put(PokemonId.MEOWTH, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0053_POKEMON_PERSIAN"); metap.setFamily(PokemonFamilyId.FAMILY_MEOWTH); @@ -2011,11 +2367,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.MEOWTH); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.SCRATCH_FAST, + PokemonMove.FEINT_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PLAY_ROUGH, + PokemonMove.POWER_GEM, + PokemonMove.NIGHT_SLASH + }); metap.setNumber(53); meta.put(PokemonId.PERSIAN, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0054_POKEMON_PSYDUCK"); metap.setFamily(PokemonFamilyId.FAMILY_PSYDUCK); @@ -2047,11 +2410,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.WATER_GUN_FAST, + PokemonMove.ZEN_HEADBUTT_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.AQUA_TAIL, + PokemonMove.PSYBEAM, + PokemonMove.CROSS_CHOP + }); metap.setNumber(54); meta.put(PokemonId.PSYDUCK, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0055_POKEMON_GOLDUCK"); metap.setFamily(PokemonFamilyId.FAMILY_PSYDUCK); @@ -2083,11 +2453,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.PSYDUCK); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST, + PokemonMove.WATER_GUN_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PSYCHIC, + PokemonMove.HYDRO_PUMP, + PokemonMove.ICE_BEAM + }); metap.setNumber(55); meta.put(PokemonId.GOLDUCK, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0056_POKEMON_MANKEY"); metap.setFamily(PokemonFamilyId.FAMILY_MANKEY); @@ -2119,11 +2496,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.KARATE_CHOP_FAST, + PokemonMove.SCRATCH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.LOW_SWEEP, + PokemonMove.BRICK_BREAK, + PokemonMove.CROSS_CHOP + }); metap.setNumber(56); meta.put(PokemonId.MANKEY, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0057_POKEMON_PRIMEAPE"); metap.setFamily(PokemonFamilyId.FAMILY_MANKEY); @@ -2155,11 +2539,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.MANKEY); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.KARATE_CHOP_FAST, + PokemonMove.LOW_KICK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.LOW_SWEEP, + PokemonMove.NIGHT_SLASH, + PokemonMove.CROSS_CHOP + }); metap.setNumber(57); meta.put(PokemonId.PRIMEAPE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0058_POKEMON_GROWLITHE"); metap.setFamily(PokemonFamilyId.FAMILY_GROWLITHE); @@ -2191,11 +2582,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.24); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.EMBER_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.FLAME_WHEEL, + PokemonMove.FLAMETHROWER, + PokemonMove.BODY_SLAM + }); metap.setNumber(58); meta.put(PokemonId.GROWLITHE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0059_POKEMON_ARCANINE"); metap.setFamily(PokemonFamilyId.FAMILY_GROWLITHE); @@ -2227,11 +2625,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.08); metap.setParentId(PokemonId.GROWLITHE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.FIRE_FANG_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.BULLDOZE, + PokemonMove.FLAMETHROWER, + PokemonMove.FIRE_BLAST + }); metap.setNumber(59); meta.put(PokemonId.ARCANINE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0060_POKEMON_POLIWAG"); metap.setFamily(PokemonFamilyId.FAMILY_POLIWAG); @@ -2263,11 +2668,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.BUBBLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.MUD_BOMB, + PokemonMove.BUBBLE_BEAM, + PokemonMove.BODY_SLAM + }); metap.setNumber(60); meta.put(PokemonId.POLIWAG, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0061_POKEMON_POLIWHIRL"); metap.setFamily(PokemonFamilyId.FAMILY_POLIWAG); @@ -2299,11 +2711,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.2); metap.setParentId(PokemonId.POLIWAG); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.BUBBLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SCALD, + PokemonMove.MUD_BOMB, + PokemonMove.BUBBLE_BEAM + }); metap.setNumber(61); meta.put(PokemonId.POLIWHIRL, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0062_POKEMON_POLIWRATH"); metap.setFamily(PokemonFamilyId.FAMILY_POLIWAG); @@ -2335,11 +2754,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.1); metap.setParentId(PokemonId.POLIWHIRL); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.BUBBLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.HYDRO_PUMP, + PokemonMove.SUBMISSION, + PokemonMove.ICE_PUNCH + }); metap.setNumber(62); meta.put(PokemonId.POLIWRATH, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0063_POKEMON_ABRA"); metap.setFamily(PokemonFamilyId.FAMILY_ABRA); @@ -2371,11 +2797,17 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.168); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ZEN_HEADBUTT_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SHADOW_BALL, + PokemonMove.PSYSHOCK, + PokemonMove.SIGNAL_BEAM + }); metap.setNumber(63); meta.put(PokemonId.ABRA, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0064_POKEMON_KADABRA"); metap.setFamily(PokemonFamilyId.FAMILY_ABRA); @@ -2407,11 +2839,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.2); metap.setParentId(PokemonId.ABRA); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST, + PokemonMove.PSYCHO_CUT_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DAZZLING_GLEAM, + PokemonMove.SHADOW_BALL, + PokemonMove.PSYBEAM + }); metap.setNumber(64); meta.put(PokemonId.KADABRA, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0065_POKEMON_ALAKAZAM"); metap.setFamily(PokemonFamilyId.FAMILY_ABRA); @@ -2443,11 +2882,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.1); metap.setParentId(PokemonId.KADABRA); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST, + PokemonMove.PSYCHO_CUT_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PSYCHIC, + PokemonMove.DAZZLING_GLEAM, + PokemonMove.SHADOW_BALL + }); metap.setNumber(65); meta.put(PokemonId.ALAKAZAM, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0066_POKEMON_MACHOP"); metap.setFamily(PokemonFamilyId.FAMILY_MACHOP); @@ -2479,11 +2925,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.KARATE_CHOP_FAST, + PokemonMove.LOW_KICK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.LOW_SWEEP, + PokemonMove.BRICK_BREAK, + PokemonMove.CROSS_CHOP + }); metap.setNumber(66); meta.put(PokemonId.MACHOP, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0067_POKEMON_MACHOKE"); metap.setFamily(PokemonFamilyId.FAMILY_MACHOP); @@ -2515,11 +2968,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.2); metap.setParentId(PokemonId.MACHOP); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.KARATE_CHOP_FAST, + PokemonMove.LOW_KICK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SUBMISSION, + PokemonMove.BRICK_BREAK, + PokemonMove.CROSS_CHOP + }); metap.setNumber(67); meta.put(PokemonId.MACHOKE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0068_POKEMON_MACHAMP"); metap.setFamily(PokemonFamilyId.FAMILY_MACHOP); @@ -2551,11 +3011,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.1); metap.setParentId(PokemonId.MACHOKE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.KARATE_CHOP_FAST, + PokemonMove.BULLET_PUNCH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STONE_EDGE, + PokemonMove.SUBMISSION, + PokemonMove.CROSS_CHOP + }); metap.setNumber(68); meta.put(PokemonId.MACHAMP, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0069_POKEMON_BELLSPROUT"); metap.setFamily(PokemonFamilyId.FAMILY_BELLSPROUT); @@ -2587,11 +3054,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.VINE_WHIP_FAST, + PokemonMove.ACID_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.POWER_WHIP, + PokemonMove.SLUDGE_BOMB, + PokemonMove.WRAP + }); metap.setNumber(69); meta.put(PokemonId.BELLSPROUT, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0070_POKEMON_WEEPINBELL"); metap.setFamily(PokemonFamilyId.FAMILY_BELLSPROUT); @@ -2623,11 +3097,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.2); metap.setParentId(PokemonId.BELLSPROUT); metap.setCylGroundM(0.375); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ACID_FAST, + PokemonMove.RAZOR_LEAF_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.POWER_WHIP, + PokemonMove.SLUDGE_BOMB, + PokemonMove.SEED_BOMB + }); metap.setNumber(70); meta.put(PokemonId.WEEPINBELL, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0071_POKEMON_VICTREEBEL"); metap.setFamily(PokemonFamilyId.FAMILY_BELLSPROUT); @@ -2659,11 +3140,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.1); metap.setParentId(PokemonId.WEEPINBELL); metap.setCylGroundM(0.42); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ACID_FAST, + PokemonMove.RAZOR_LEAF_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.LEAF_BLADE, + PokemonMove.SOLAR_BEAM + }); metap.setNumber(71); meta.put(PokemonId.VICTREEBEL, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0072_POKEMON_TENTACOOL"); metap.setFamily(PokemonFamilyId.FAMILY_TENTACOOL); @@ -2695,11 +3183,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.2625); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POISON_STING_FAST, + PokemonMove.BUBBLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.WATER_PULSE, + PokemonMove.BUBBLE_BEAM, + PokemonMove.WRAP + }); metap.setNumber(72); meta.put(PokemonId.TENTACOOL, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0073_POKEMON_TENTACRUEL"); metap.setFamily(PokemonFamilyId.FAMILY_TENTACOOL); @@ -2731,11 +3226,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.TENTACOOL); metap.setCylGroundM(0.205); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ACID_FAST, + PokemonMove.POISON_JAB_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.BLIZZARD, + PokemonMove.HYDRO_PUMP, + PokemonMove.SLUDGE_WAVE + }); metap.setNumber(73); meta.put(PokemonId.TENTACRUEL, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0074_POKEMON_GEODUDE"); metap.setFamily(PokemonFamilyId.FAMILY_GEODUDE); @@ -2767,11 +3269,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.261); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ROCK_THROW_FAST, + PokemonMove.TACKLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DIG, + PokemonMove.ROCK_SLIDE, + PokemonMove.ROCK_TOMB + }); metap.setNumber(74); meta.put(PokemonId.GEODUDE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0075_POKEMON_GRAVELER"); metap.setFamily(PokemonFamilyId.FAMILY_GEODUDE); @@ -2803,11 +3312,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.2); metap.setParentId(PokemonId.GEODUDE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.ROCK_THROW_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DIG, + PokemonMove.ROCK_SLIDE, + PokemonMove.STONE_EDGE + }); metap.setNumber(75); meta.put(PokemonId.GRAVELER, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0076_POKEMON_GOLEM"); metap.setFamily(PokemonFamilyId.FAMILY_GEODUDE); @@ -2839,11 +3355,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.1); metap.setParentId(PokemonId.GRAVELER); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.ROCK_THROW_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STONE_EDGE, + PokemonMove.EARTHQUAKE, + PokemonMove.ANCIENT_POWER + }); metap.setNumber(76); meta.put(PokemonId.GOLEM, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0077_POKEMON_PONYTA"); metap.setFamily(PokemonFamilyId.FAMILY_PONYTA); @@ -2875,11 +3398,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.32); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.EMBER_FAST, + PokemonMove.TACKLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.FLAME_WHEEL, + PokemonMove.FLAME_CHARGE, + PokemonMove.FIRE_BLAST + }); metap.setNumber(77); meta.put(PokemonId.PONYTA, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0078_POKEMON_RAPIDASH"); metap.setFamily(PokemonFamilyId.FAMILY_PONYTA); @@ -2911,11 +3441,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.12); metap.setParentId(PokemonId.PONYTA); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.LOW_KICK_FAST, + PokemonMove.EMBER_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.HEAT_WAVE, + PokemonMove.DRILL_RUN, + PokemonMove.FIRE_BLAST + }); metap.setNumber(78); meta.put(PokemonId.RAPIDASH, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0079_POKEMON_SLOWPOKE"); metap.setFamily(PokemonFamilyId.FAMILY_SLOWPOKE); @@ -2947,11 +3484,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST, + PokemonMove.WATER_GUN_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PSYCHIC, + PokemonMove.WATER_PULSE, + PokemonMove.PSYSHOCK + }); metap.setNumber(79); meta.put(PokemonId.SLOWPOKE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0080_POKEMON_SLOWBRO"); metap.setFamily(PokemonFamilyId.FAMILY_SLOWPOKE); @@ -2983,11 +3527,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.SLOWPOKE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST, + PokemonMove.WATER_GUN_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PSYCHIC, + PokemonMove.WATER_PULSE, + PokemonMove.ICE_BEAM + }); metap.setNumber(80); meta.put(PokemonId.SLOWBRO, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0081_POKEMON_MAGNEMITE"); metap.setFamily(PokemonFamilyId.FAMILY_MAGNEMITE); @@ -3019,11 +3570,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.912); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.SPARK_FAST, + PokemonMove.THUNDER_SHOCK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.MAGNET_BOMB, + PokemonMove.THUNDERBOLT, + PokemonMove.DISCHARGE + }); metap.setNumber(81); meta.put(PokemonId.MAGNEMITE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0082_POKEMON_MAGNETON"); metap.setFamily(PokemonFamilyId.FAMILY_MAGNEMITE); @@ -3055,11 +3613,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.MAGNEMITE); metap.setCylGroundM(0.44); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.SPARK_FAST, + PokemonMove.THUNDER_SHOCK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.MAGNET_BOMB, + PokemonMove.FLASH_CANNON, + PokemonMove.DISCHARGE + }); metap.setNumber(82); meta.put(PokemonId.MAGNETON, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0083_POKEMON_FARFETCHD"); metap.setFamily(PokemonFamilyId.FAMILY_FARFETCHD); @@ -3091,11 +3656,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.24); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.FURY_CUTTER_FAST, + PokemonMove.CUT_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.AERIAL_ACE, + PokemonMove.LEAF_BLADE, + PokemonMove.AIR_CUTTER + }); metap.setNumber(83); meta.put(PokemonId.FARFETCHD, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0084_POKEMON_DODUO"); metap.setFamily(PokemonFamilyId.FAMILY_DODUO); @@ -3127,11 +3699,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.QUICK_ATTACK_FAST, + PokemonMove.PECK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.AERIAL_ACE, + PokemonMove.DRILL_PECK, + PokemonMove.SWIFT + }); metap.setNumber(84); meta.put(PokemonId.DODUO, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0085_POKEMON_DODRIO"); metap.setFamily(PokemonFamilyId.FAMILY_DODUO); @@ -3163,11 +3742,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.DODUO); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.STEEL_WING_FAST, + PokemonMove.FEINT_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.AERIAL_ACE, + PokemonMove.DRILL_PECK, + PokemonMove.AIR_CUTTER + }); metap.setNumber(85); meta.put(PokemonId.DODRIO, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0086_POKEMON_SEEL"); metap.setFamily(PokemonFamilyId.FAMILY_SEEL); @@ -3199,11 +3785,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.WATER_GUN_FAST, + PokemonMove.ICE_SHARD_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.ICY_WIND, + PokemonMove.AQUA_TAIL, + PokemonMove.AQUA_JET + }); metap.setNumber(86); meta.put(PokemonId.SEEL, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0087_POKEMON_DEWGONG"); metap.setFamily(PokemonFamilyId.FAMILY_SEEL); @@ -3235,11 +3828,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.SEEL); metap.setCylGroundM(0.39375); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ICE_SHARD_FAST, + PokemonMove.FROST_BREATH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.ICY_WIND, + PokemonMove.BLIZZARD, + PokemonMove.AQUA_JET + }); metap.setNumber(87); meta.put(PokemonId.DEWGONG, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0088_POKEMON_GRIMER"); metap.setFamily(PokemonFamilyId.FAMILY_GRIMER); @@ -3271,11 +3871,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SLAP_FAST, + PokemonMove.ACID_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.MUD_BOMB, + PokemonMove.SLUDGE + }); metap.setNumber(88); meta.put(PokemonId.GRIMER, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0089_POKEMON_MUK"); metap.setFamily(PokemonFamilyId.FAMILY_GRIMER); @@ -3307,11 +3914,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.GRIMER); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ACID_FAST, + PokemonMove.POISON_JAB_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DARK_PULSE, + PokemonMove.GUNK_SHOT, + PokemonMove.SLUDGE_WAVE + }); metap.setNumber(89); meta.put(PokemonId.MUK, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0090_POKEMON_SHELLDER"); metap.setFamily(PokemonFamilyId.FAMILY_SHELLDER); @@ -3343,11 +3957,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ICE_SHARD_FAST, + PokemonMove.TACKLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.ICY_WIND, + PokemonMove.WATER_PULSE, + PokemonMove.BUBBLE_BEAM + }); metap.setNumber(90); meta.put(PokemonId.SHELLDER, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0091_POKEMON_CLOYSTER"); metap.setFamily(PokemonFamilyId.FAMILY_SHELLDER); @@ -3379,11 +4000,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.SHELLDER); metap.setCylGroundM(0.42); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ICE_SHARD_FAST, + PokemonMove.FROST_BREATH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.ICY_WIND, + PokemonMove.BLIZZARD, + PokemonMove.HYDRO_PUMP + }); metap.setNumber(91); meta.put(PokemonId.CLOYSTER, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0092_POKEMON_GASTLY"); metap.setFamily(PokemonFamilyId.FAMILY_GASTLY); @@ -3415,11 +4043,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.32); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.6); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.SUCKER_PUNCH_FAST, + PokemonMove.LICK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.DARK_PULSE, + PokemonMove.OMINOUS_WIND + }); metap.setNumber(92); meta.put(PokemonId.GASTLY, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0093_POKEMON_HAUNTER"); metap.setFamily(PokemonFamilyId.FAMILY_GASTLY); @@ -3451,11 +4086,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.GASTLY); metap.setCylGroundM(0.34); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.SHADOW_CLAW_FAST, + PokemonMove.LICK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.SHADOW_BALL, + PokemonMove.DARK_PULSE + }); metap.setNumber(93); meta.put(PokemonId.HAUNTER, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0094_POKEMON_GENGAR"); metap.setFamily(PokemonFamilyId.FAMILY_GASTLY); @@ -3487,11 +4129,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.08); metap.setParentId(PokemonId.HAUNTER); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.SUCKER_PUNCH_FAST, + PokemonMove.SHADOW_CLAW_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SHADOW_BALL, + PokemonMove.DARK_PULSE, + PokemonMove.SLUDGE_WAVE + }); metap.setNumber(94); meta.put(PokemonId.GENGAR, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0095_POKEMON_ONIX"); metap.setFamily(PokemonFamilyId.FAMILY_ONIX); @@ -3523,11 +4172,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ROCK_THROW_FAST, + PokemonMove.TACKLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.IRON_HEAD, + PokemonMove.STONE_EDGE, + PokemonMove.ROCK_SLIDE + }); metap.setNumber(95); meta.put(PokemonId.ONIX, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0096_POKEMON_DROWZEE"); metap.setFamily(PokemonFamilyId.FAMILY_DROWZEE); @@ -3559,14 +4215,21 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST, + PokemonMove.POUND_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PSYCHIC, + PokemonMove.PSYSHOCK, + PokemonMove.PSYBEAM + }); metap.setNumber(96); meta.put(PokemonId.DROWZEE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0097_POKEMON_HYPNO"); - metap.setFamily(PokemonFamilyId.FAMILY_HYPNO); + metap.setFamily(PokemonFamilyId.FAMILY_DROWZEE); metap.setPokemonClass(PokemonClass.UNCOMMON); metap.setType2(PokemonType.NONE); metap.setPokedexHeightM(1.6); @@ -3595,11 +4258,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.DROWZEE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST, + PokemonMove.ZEN_HEADBUTT_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PSYCHIC, + PokemonMove.SHADOW_BALL, + PokemonMove.PSYSHOCK + }); metap.setNumber(97); meta.put(PokemonId.HYPNO, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0098_POKEMON_KRABBY"); metap.setFamily(PokemonFamilyId.FAMILY_KRABBY); @@ -3631,11 +4301,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.BUBBLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.WATER_PULSE, + PokemonMove.VICE_GRIP, + PokemonMove.BUBBLE_BEAM + }); metap.setNumber(98); meta.put(PokemonId.KRABBY, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0099_POKEMON_KINGLER"); metap.setFamily(PokemonFamilyId.FAMILY_KRABBY); @@ -3667,11 +4344,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.KRABBY); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.METAL_CLAW_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.WATER_PULSE, + PokemonMove.X_SCISSOR, + PokemonMove.VICE_GRIP + }); metap.setNumber(99); meta.put(PokemonId.KINGLER, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0100_POKEMON_VOLTORB"); metap.setFamily(PokemonFamilyId.FAMILY_VOLTORB); @@ -3703,11 +4387,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.SPARK_FAST, + PokemonMove.TACKLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SIGNAL_BEAM, + PokemonMove.THUNDERBOLT, + PokemonMove.DISCHARGE + }); metap.setNumber(100); meta.put(PokemonId.VOLTORB, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0101_POKEMON_ELECTRODE"); metap.setFamily(PokemonFamilyId.FAMILY_VOLTORB); @@ -3739,11 +4430,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.VOLTORB); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.SPARK_FAST, + PokemonMove.TACKLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.HYPER_BEAM, + PokemonMove.THUNDERBOLT, + PokemonMove.DISCHARGE + }); metap.setNumber(101); meta.put(PokemonId.ELECTRODE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0102_POKEMON_EXEGGCUTE"); metap.setFamily(PokemonFamilyId.FAMILY_EXEGGCUTE); @@ -3775,11 +4473,17 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PSYCHIC, + PokemonMove.SEED_BOMB, + PokemonMove.ANCIENT_POWER + }); metap.setNumber(102); meta.put(PokemonId.EXEGGCUTE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0103_POKEMON_EXEGGUTOR"); metap.setFamily(PokemonFamilyId.FAMILY_EXEGGCUTE); @@ -3811,11 +4515,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.EXEGGCUTE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST, + PokemonMove.ZEN_HEADBUTT_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PSYCHIC, + PokemonMove.SEED_BOMB, + PokemonMove.SOLAR_BEAM + }); metap.setNumber(103); meta.put(PokemonId.EXEGGUTOR, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0104_POKEMON_CUBONE"); metap.setFamily(PokemonFamilyId.FAMILY_CUBONE); @@ -3847,11 +4558,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.32); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SLAP_FAST, + PokemonMove.ROCK_SMASH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DIG, + PokemonMove.BONE_CLUB, + PokemonMove.BULLDOZE + }); metap.setNumber(104); meta.put(PokemonId.CUBONE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0105_POKEMON_MAROWAK"); metap.setFamily(PokemonFamilyId.FAMILY_CUBONE); @@ -3883,11 +4601,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.12); metap.setParentId(PokemonId.CUBONE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SLAP_FAST, + PokemonMove.ROCK_SMASH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DIG, + PokemonMove.EARTHQUAKE, + PokemonMove.BONE_CLUB + }); metap.setNumber(105); meta.put(PokemonId.MAROWAK, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0106_POKEMON_HITMONLEE"); metap.setFamily(PokemonFamilyId.FAMILY_HITMONLEE); @@ -3919,11 +4644,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.LOW_KICK_FAST, + PokemonMove.ROCK_SMASH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STOMP, + PokemonMove.STONE_EDGE, + PokemonMove.LOW_SWEEP + }); metap.setNumber(106); meta.put(PokemonId.HITMONLEE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0107_POKEMON_HITMONCHAN"); metap.setFamily(PokemonFamilyId.FAMILY_HITMONCHAN); @@ -3955,11 +4687,19 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BULLET_PUNCH_FAST, + PokemonMove.ROCK_SMASH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.THUNDER_PUNCH, + PokemonMove.FIRE_PUNCH, + PokemonMove.BRICK_BREAK, + PokemonMove.ICE_PUNCH + }); metap.setNumber(107); meta.put(PokemonId.HITMONCHAN, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0108_POKEMON_LICKITUNG"); metap.setFamily(PokemonFamilyId.FAMILY_LICKITUNG); @@ -3991,11 +4731,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ZEN_HEADBUTT_FAST, + PokemonMove.LICK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STOMP, + PokemonMove.POWER_WHIP, + PokemonMove.HYPER_BEAM + }); metap.setNumber(108); meta.put(PokemonId.LICKITUNG, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0109_POKEMON_KOFFING"); metap.setFamily(PokemonFamilyId.FAMILY_KOFFING); @@ -4027,11 +4774,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.6); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ACID_FAST, + PokemonMove.TACKLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.DARK_PULSE, + PokemonMove.SLUDGE + }); metap.setNumber(109); meta.put(PokemonId.KOFFING, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0110_POKEMON_WEEZING"); metap.setFamily(PokemonFamilyId.FAMILY_KOFFING); @@ -4063,11 +4817,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.KOFFING); metap.setCylGroundM(0.62); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ACID_FAST, + PokemonMove.TACKLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SLUDGE_BOMB, + PokemonMove.SHADOW_BALL, + PokemonMove.DARK_PULSE + }); metap.setNumber(110); meta.put(PokemonId.WEEZING, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0111_POKEMON_RHYHORN"); metap.setFamily(PokemonFamilyId.FAMILY_RHYHORN); @@ -4099,11 +4860,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SLAP_FAST, + PokemonMove.ROCK_SMASH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STOMP, + PokemonMove.BULLDOZE, + PokemonMove.HORN_ATTACK + }); metap.setNumber(111); meta.put(PokemonId.RHYHORN, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0112_POKEMON_RHYDON"); metap.setFamily(PokemonFamilyId.FAMILY_RHYHORN); @@ -4135,11 +4903,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.RHYHORN); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SLAP_FAST, + PokemonMove.ROCK_SMASH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STONE_EDGE, + PokemonMove.EARTHQUAKE, + PokemonMove.MEGAHORN + }); metap.setNumber(112); meta.put(PokemonId.RHYDON, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0113_POKEMON_CHANSEY"); metap.setFamily(PokemonFamilyId.FAMILY_CHANSEY); @@ -4171,11 +4946,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POUND_FAST, + PokemonMove.ZEN_HEADBUTT_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PSYCHIC, + PokemonMove.DAZZLING_GLEAM, + PokemonMove.PSYBEAM + }); metap.setNumber(113); meta.put(PokemonId.CHANSEY, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0114_POKEMON_TANGELA"); metap.setFamily(PokemonFamilyId.FAMILY_TANGELA); @@ -4207,11 +4989,17 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.32); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.VINE_WHIP_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.POWER_WHIP, + PokemonMove.SLUDGE_BOMB, + PokemonMove.SOLAR_BEAM + }); metap.setNumber(114); meta.put(PokemonId.TANGELA, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0115_POKEMON_KANGASKHAN"); metap.setFamily(PokemonFamilyId.FAMILY_KANGASKHAN); @@ -4243,11 +5031,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SLAP_FAST, + PokemonMove.LOW_KICK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STOMP, + PokemonMove.EARTHQUAKE, + PokemonMove.BRICK_BREAK + }); metap.setNumber(115); meta.put(PokemonId.KANGASKHAN, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0116_POKEMON_HORSEA"); metap.setFamily(PokemonFamilyId.FAMILY_HORSEA); @@ -4279,11 +5074,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.185); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.WATER_GUN_FAST, + PokemonMove.BUBBLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.FLASH_CANNON, + PokemonMove.BUBBLE_BEAM, + PokemonMove.DRAGON_PULSE + }); metap.setNumber(116); meta.put(PokemonId.HORSEA, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0117_POKEMON_SEADRA"); metap.setFamily(PokemonFamilyId.FAMILY_HORSEA); @@ -4315,11 +5117,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.HORSEA); metap.setCylGroundM(0.46); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.DRAGON_BREATH_FAST, + PokemonMove.WATER_GUN_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.BLIZZARD, + PokemonMove.HYDRO_PUMP, + PokemonMove.DRAGON_PULSE + }); metap.setNumber(117); meta.put(PokemonId.SEADRA, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0118_POKEMON_GOLDEEN"); metap.setFamily(PokemonFamilyId.FAMILY_GOLDEEN); @@ -4351,11 +5160,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.3375); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.PECK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.WATER_PULSE, + PokemonMove.HORN_ATTACK, + PokemonMove.AQUA_TAIL + }); metap.setNumber(118); meta.put(PokemonId.GOLDEEN, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0119_POKEMON_SEAKING"); metap.setFamily(PokemonFamilyId.FAMILY_GOLDEEN); @@ -4387,11 +5203,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.GOLDEEN); metap.setCylGroundM(0.33); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POISON_JAB_FAST, + PokemonMove.PECK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.ICY_WIND, + PokemonMove.MEGAHORN, + PokemonMove.DRILL_RUN + }); metap.setNumber(119); meta.put(PokemonId.SEAKING, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0120_POKEMON_STARYU"); metap.setFamily(PokemonFamilyId.FAMILY_STARYU); @@ -4423,11 +5246,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.4); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.WATER_GUN_FAST, + PokemonMove.QUICK_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.POWER_GEM, + PokemonMove.BUBBLE_BEAM, + PokemonMove.SWIFT + }); metap.setNumber(120); meta.put(PokemonId.STARYU, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0121_POKEMON_STARMIE"); metap.setFamily(PokemonFamilyId.FAMILY_STARYU); @@ -4459,11 +5289,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.STARYU); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.WATER_GUN_FAST, + PokemonMove.QUICK_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PSYBEAM, + PokemonMove.HYDRO_PUMP, + PokemonMove.POWER_GEM + }); metap.setNumber(121); meta.put(PokemonId.STARMIE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0122_POKEMON_MR_MIME"); metap.setFamily(PokemonFamilyId.FAMILY_MR_MIME); @@ -4495,11 +5332,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.24); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST, + PokemonMove.ZEN_HEADBUTT_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PSYCHIC, + PokemonMove.SHADOW_BALL, + PokemonMove.PSYBEAM + }); metap.setNumber(122); meta.put(PokemonId.MR_MIME, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0123_POKEMON_SCYTHER"); metap.setFamily(PokemonFamilyId.FAMILY_SCYTHER); @@ -4531,11 +5375,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.24); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.4); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.STEEL_WING_FAST, + PokemonMove.FURY_CUTTER_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.BUG_BUZZ, + PokemonMove.X_SCISSOR, + PokemonMove.NIGHT_SLASH + }); metap.setNumber(123); meta.put(PokemonId.SCYTHER, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0124_POKEMON_JYNX"); metap.setFamily(PokemonFamilyId.FAMILY_JYNX); @@ -4567,11 +5418,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.24); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POUND_FAST, + PokemonMove.FROST_BREATH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PSYSHOCK, + PokemonMove.DRAINING_KISS, + PokemonMove.ICE_PUNCH + }); metap.setNumber(124); meta.put(PokemonId.JYNX, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0125_POKEMON_ELECTABUZZ"); metap.setFamily(PokemonFamilyId.FAMILY_ELECTABUZZ); @@ -4603,11 +5461,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.24); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.LOW_KICK_FAST, + PokemonMove.THUNDER_SHOCK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.THUNDER_PUNCH, + PokemonMove.THUNDER, + PokemonMove.THUNDERBOLT + }); metap.setNumber(125); meta.put(PokemonId.ELECTABUZZ, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0126_POKEMON_MAGMAR"); metap.setFamily(PokemonFamilyId.FAMILY_MAGMAR); @@ -4639,11 +5504,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.24); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.KARATE_CHOP_FAST, + PokemonMove.EMBER_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.FIRE_PUNCH, + PokemonMove.FLAMETHROWER, + PokemonMove.FIRE_BLAST + }); metap.setNumber(126); meta.put(PokemonId.MAGMAR, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0127_POKEMON_PINSIR"); metap.setFamily(PokemonFamilyId.FAMILY_PINSIR); @@ -4675,11 +5547,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.24); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.FURY_CUTTER_FAST, + PokemonMove.ROCK_SMASH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.SUBMISSION, + PokemonMove.X_SCISSOR, + PokemonMove.VICE_GRIP + }); metap.setNumber(127); meta.put(PokemonId.PINSIR, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0128_POKEMON_TAUROS"); metap.setFamily(PokemonFamilyId.FAMILY_TAUROS); @@ -4711,11 +5590,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.24); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ZEN_HEADBUTT_FAST, + PokemonMove.TACKLE_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.IRON_HEAD, + PokemonMove.EARTHQUAKE, + PokemonMove.HORN_ATTACK + }); metap.setNumber(128); meta.put(PokemonId.TAUROS, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0129_POKEMON_MAGIKARP"); metap.setFamily(PokemonFamilyId.FAMILY_MAGIKARP); @@ -4747,11 +5633,15 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.56); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.SPLASH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STRUGGLE + }); metap.setNumber(129); meta.put(PokemonId.MAGIKARP, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0130_POKEMON_GYARADOS"); metap.setFamily(PokemonFamilyId.FAMILY_MAGIKARP); @@ -4783,11 +5673,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.08); metap.setParentId(PokemonId.MAGIKARP); metap.setCylGroundM(0.48); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.DRAGON_BREATH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.TWISTER, + PokemonMove.HYDRO_PUMP, + PokemonMove.DRAGON_PULSE + }); metap.setNumber(130); meta.put(PokemonId.GYARADOS, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0131_POKEMON_LAPRAS"); metap.setFamily(PokemonFamilyId.FAMILY_LAPRAS); @@ -4819,11 +5716,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ICE_SHARD_FAST, + PokemonMove.FROST_BREATH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.BLIZZARD, + PokemonMove.ICE_BEAM, + PokemonMove.DRAGON_PULSE + }); metap.setNumber(131); meta.put(PokemonId.LAPRAS, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0132_POKEMON_DITTO"); metap.setFamily(PokemonFamilyId.FAMILY_DITTO); @@ -4855,11 +5759,15 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POUND_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STRUGGLE + }); metap.setNumber(132); meta.put(PokemonId.DITTO, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0133_POKEMON_EEVEE"); metap.setFamily(PokemonFamilyId.FAMILY_EEVEE); @@ -4891,11 +5799,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.32); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.TACKLE_FAST, + PokemonMove.QUICK_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DIG, + PokemonMove.SWIFT, + PokemonMove.BODY_SLAM + }); metap.setNumber(133); meta.put(PokemonId.EEVEE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0134_POKEMON_VAPOREON"); metap.setFamily(PokemonFamilyId.FAMILY_EEVEE); @@ -4927,11 +5842,17 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.12); metap.setParentId(PokemonId.EEVEE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.WATER_GUN_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.WATER_PULSE, + PokemonMove.HYDRO_PUMP, + PokemonMove.AQUA_TAIL + }); metap.setNumber(134); meta.put(PokemonId.VAPOREON, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0135_POKEMON_JOLTEON"); metap.setFamily(PokemonFamilyId.FAMILY_EEVEE); @@ -4963,11 +5884,17 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.12); metap.setParentId(PokemonId.EEVEE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.THUNDER_SHOCK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.THUNDER, + PokemonMove.THUNDERBOLT, + PokemonMove.DISCHARGE + }); metap.setNumber(135); meta.put(PokemonId.JOLTEON, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0136_POKEMON_FLAREON"); metap.setFamily(PokemonFamilyId.FAMILY_EEVEE); @@ -4999,11 +5926,17 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.12); metap.setParentId(PokemonId.EEVEE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.EMBER_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.FLAMETHROWER, + PokemonMove.HEAT_WAVE, + PokemonMove.FIRE_BLAST + }); metap.setNumber(136); meta.put(PokemonId.FLAREON, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0137_POKEMON_PORYGON"); metap.setFamily(PokemonFamilyId.FAMILY_PORYGON); @@ -5035,11 +5968,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.32); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.55); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.TACKLE_FAST, + PokemonMove.QUICK_ATTACK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DISCHARGE, + PokemonMove.PSYBEAM, + PokemonMove.SIGNAL_BEAM + }); metap.setNumber(137); meta.put(PokemonId.PORYGON, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0138_POKEMON_OMANYTE"); metap.setFamily(PokemonFamilyId.FAMILY_OMANYTE); @@ -5071,11 +6011,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.32); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.WATER_GUN_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.ROCK_TOMB, + PokemonMove.ANCIENT_POWER, + PokemonMove.BRINE + }); metap.setNumber(138); meta.put(PokemonId.OMANYTE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0139_POKEMON_OMASTAR"); metap.setFamily(PokemonFamilyId.FAMILY_OMANYTE); @@ -5107,11 +6054,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.12); metap.setParentId(PokemonId.OMANYTE); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ROCK_THROW_FAST, + PokemonMove.WATER_GUN_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.HYDRO_PUMP, + PokemonMove.ANCIENT_POWER, + PokemonMove.ROCK_SLIDE + }); metap.setNumber(139); meta.put(PokemonId.OMASTAR, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0140_POKEMON_KABUTO"); metap.setFamily(PokemonFamilyId.FAMILY_KABUTO); @@ -5143,11 +6097,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.32); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.SCRATCH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.ANCIENT_POWER, + PokemonMove.AQUA_JET, + PokemonMove.ROCK_TOMB + }); metap.setNumber(140); meta.put(PokemonId.KABUTO, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0141_POKEMON_KABUTOPS"); metap.setFamily(PokemonFamilyId.FAMILY_KABUTO); @@ -5179,11 +6140,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.12); metap.setParentId(PokemonId.KABUTO); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.MUD_SHOT_FAST, + PokemonMove.FURY_CUTTER_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.STONE_EDGE, + PokemonMove.WATER_PULSE, + PokemonMove.ANCIENT_POWER + }); metap.setNumber(141); meta.put(PokemonId.KABUTOPS, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0142_POKEMON_AERODACTYL"); metap.setFamily(PokemonFamilyId.FAMILY_AERODACTYL); @@ -5215,11 +6183,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.855); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.BITE_FAST, + PokemonMove.STEEL_WING_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.IRON_HEAD, + PokemonMove.HYPER_BEAM, + PokemonMove.ANCIENT_POWER + }); metap.setNumber(142); meta.put(PokemonId.AERODACTYL, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0143_POKEMON_SNORLAX"); metap.setFamily(PokemonFamilyId.FAMILY_SNORLAX); @@ -5251,11 +6226,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.16); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.ZEN_HEADBUTT_FAST, + PokemonMove.LICK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.EARTHQUAKE, + PokemonMove.HYPER_BEAM, + PokemonMove.BODY_SLAM + }); metap.setNumber(143); meta.put(PokemonId.SNORLAX, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0144_POKEMON_ARTICUNO"); metap.setFamily(PokemonFamilyId.FAMILY_ARTICUNO); @@ -5287,11 +6269,17 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.66); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.FROST_BREATH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.ICY_WIND, + PokemonMove.BLIZZARD, + PokemonMove.ICE_BEAM + }); metap.setNumber(144); meta.put(PokemonId.ARTICUNO, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0145_POKEMON_ZAPDOS"); metap.setFamily(PokemonFamilyId.FAMILY_ZAPDOS); @@ -5323,11 +6311,17 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.8625); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.THUNDER_SHOCK_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.THUNDER, + PokemonMove.THUNDERBOLT, + PokemonMove.DISCHARGE + }); metap.setNumber(145); meta.put(PokemonId.ZAPDOS, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0146_POKEMON_MOLTRES"); metap.setFamily(PokemonFamilyId.FAMILY_MOLTRES); @@ -5359,11 +6353,17 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.00); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.93); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.EMBER_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.FLAMETHROWER, + PokemonMove.HEAT_WAVE, + PokemonMove.FIRE_BLAST + }); metap.setNumber(146); meta.put(PokemonId.MOLTRES, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0147_POKEMON_DRATINI"); metap.setFamily(PokemonFamilyId.FAMILY_DRATINI); @@ -5395,11 +6395,17 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.32); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.DRAGON_BREATH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.TWISTER, + PokemonMove.WRAP, + PokemonMove.AQUA_TAIL + }); metap.setNumber(147); meta.put(PokemonId.DRATINI, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0148_POKEMON_DRAGONAIR"); metap.setFamily(PokemonFamilyId.FAMILY_DRATINI); @@ -5431,11 +6437,17 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.08); metap.setParentId(PokemonId.DRATINI); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.DRAGON_BREATH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.WRAP, + PokemonMove.AQUA_TAIL, + PokemonMove.DRAGON_PULSE + }); metap.setNumber(148); meta.put(PokemonId.DRAGONAIR, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0149_POKEMON_DRAGONITE"); metap.setFamily(PokemonFamilyId.FAMILY_DRATINI); @@ -5467,11 +6479,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0.04); metap.setParentId(PokemonId.DRAGONAIR); metap.setCylGroundM(0.595); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.STEEL_WING_FAST, + PokemonMove.DRAGON_BREATH_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.DRAGON_CLAW, + PokemonMove.HYPER_BEAM, + PokemonMove.DRAGON_PULSE + }); metap.setNumber(149); meta.put(PokemonId.DRAGONITE, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0150_POKEMON_MEWTWO"); metap.setFamily(PokemonFamilyId.FAMILY_MEWTWO); @@ -5503,11 +6522,18 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.CONFUSION_FAST, + PokemonMove.PSYCHO_CUT_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.PSYCHIC, + PokemonMove.SHADOW_BALL, + PokemonMove.HYPER_BEAM + }); metap.setNumber(150); meta.put(PokemonId.MEWTWO, metap); - - metap = new PokemonMeta(); metap.setTemplateId(" V0151_POKEMON_MEW"); metap.setFamily(PokemonFamilyId.FAMILY_MEWTWO); @@ -5539,18 +6565,25 @@ public class PokemonMetaRegistry { metap.setBaseCaptureRate(0); metap.setParentId(PokemonId.UNRECOGNIZED); metap.setCylGroundM(0.0705); + metap.setQuickMoves(new PokemonMove[]{ + PokemonMove.POUND_FAST + }); + metap.setCinematicMoves(new PokemonMove[]{ + PokemonMove.MOONBLAST, + PokemonMove.FIRE_BLAST, + PokemonMove.SOLAR_BEAM, + PokemonMove.HYPER_BEAM, + PokemonMove.PSYCHIC, + PokemonMove.HURRICANE, + PokemonMove.EARTHQUAKE, + PokemonMove.DRAGON_PULSE, + PokemonMove.THUNDER + }); metap.setNumber(151); meta.put(PokemonId.MEW, metap); - - - - - } - - /** * Return PokemonMeta object containing meta info about a pokemon. * @@ -5572,5 +6605,4 @@ public static PokemonId getHightestForFamily(PokemonFamilyId family) { return highestForFamily.get(family); } - -} \ No newline at end of file +} diff --git a/src/main/java/com/pokegoapi/api/pokemon/PokemonMoveMeta.java b/src/main/java/com/pokegoapi/api/pokemon/PokemonMoveMeta.java new file mode 100644 index 00000000..a605f3da --- /dev/null +++ b/src/main/java/com/pokegoapi/api/pokemon/PokemonMoveMeta.java @@ -0,0 +1,46 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.api.pokemon; + +import POGOProtos.Enums.PokemonMoveOuterClass.PokemonMove; +import lombok.Getter; +import lombok.Setter; + +public class PokemonMoveMeta { + + @Getter + @Setter + private PokemonMove move; + @Getter + @Setter + private PokemonType type; + @Getter + @Setter + private int power; + @Getter + @Setter + private int accuracy; + @Getter + @Setter + private double critChance; + @Getter + @Setter + private int time; + @Getter + @Setter + private int energy; + +} diff --git a/src/main/java/com/pokegoapi/api/pokemon/PokemonMoveMetaRegistry.java b/src/main/java/com/pokegoapi/api/pokemon/PokemonMoveMetaRegistry.java new file mode 100644 index 00000000..35143ea6 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/pokemon/PokemonMoveMetaRegistry.java @@ -0,0 +1,1412 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.api.pokemon; + +import POGOProtos.Enums.PokemonMoveOuterClass.PokemonMove; + +import java.util.EnumMap; + +public class PokemonMoveMetaRegistry { + + private static EnumMap meta = new EnumMap<>(PokemonMove.class); + + static { + + PokemonMoveMeta metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.BODY_SLAM); + metam.setType(PokemonType.NORMAL); + metam.setPower(40); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1560); + metam.setEnergy(-50); + meta.put(PokemonMove.BODY_SLAM, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.CROSS_CHOP); + metam.setType(PokemonType.FIGHTING); + metam.setPower(60); + metam.setAccuracy(1); + metam.setCritChance(0.25); + metam.setTime(2000); + metam.setEnergy(-100); + meta.put(PokemonMove.CROSS_CHOP, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.DRAGON_CLAW); + metam.setType(PokemonType.DRAGON); + metam.setPower(35); + metam.setAccuracy(1); + metam.setCritChance(0.25); + metam.setTime(1500); + metam.setEnergy(-50); + meta.put(PokemonMove.DRAGON_CLAW, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.PSYCHO_CUT_FAST); + metam.setType(PokemonType.PSYCHIC); + metam.setPower(7); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(570); + metam.setEnergy(7); + meta.put(PokemonMove.PSYCHO_CUT_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.MUD_SHOT_FAST); + metam.setType(PokemonType.GROUND); + metam.setPower(6); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(550); + metam.setEnergy(7); + meta.put(PokemonMove.MUD_SHOT_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.POWER_WHIP); + metam.setType(PokemonType.GRASS); + metam.setPower(70); + metam.setAccuracy(1); + metam.setCritChance(0.25); + metam.setTime(2800); + metam.setEnergy(-100); + meta.put(PokemonMove.POWER_WHIP, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.AQUA_TAIL); + metam.setType(PokemonType.WATER); + metam.setPower(45); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2350); + metam.setEnergy(-50); + meta.put(PokemonMove.AQUA_TAIL, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.IRON_HEAD); + metam.setType(PokemonType.STEEL); + metam.setPower(30); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2000); + metam.setEnergy(-33); + meta.put(PokemonMove.IRON_HEAD, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.GUNK_SHOT); + metam.setType(PokemonType.POISON); + metam.setPower(65); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3000); + metam.setEnergy(-100); + meta.put(PokemonMove.GUNK_SHOT, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.LICK_FAST); + metam.setType(PokemonType.GHOST); + metam.setPower(5); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(500); + metam.setEnergy(7); + meta.put(PokemonMove.LICK_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SCRATCH_FAST); + metam.setType(PokemonType.NORMAL); + metam.setPower(6); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(500); + metam.setEnergy(7); + meta.put(PokemonMove.SCRATCH_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.WATER_GUN_FAST); + metam.setType(PokemonType.WATER); + metam.setPower(6); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(500); + metam.setEnergy(7); + meta.put(PokemonMove.WATER_GUN_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.WATER_GUN_FAST_BLASTOISE); + metam.setType(PokemonType.WATER); + metam.setPower(6); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(500); + metam.setEnergy(7); + meta.put(PokemonMove.WATER_GUN_FAST_BLASTOISE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SLUDGE_BOMB); + metam.setType(PokemonType.POISON); + metam.setPower(55); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2600); + metam.setEnergy(-50); + meta.put(PokemonMove.SLUDGE_BOMB, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.METAL_CLAW_FAST); + metam.setType(PokemonType.STEEL); + metam.setPower(8); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(630); + metam.setEnergy(7); + meta.put(PokemonMove.METAL_CLAW_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.HURRICANE); + metam.setType(PokemonType.FLYING); + metam.setPower(80); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3200); + metam.setEnergy(-100); + meta.put(PokemonMove.HURRICANE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.BRICK_BREAK); + metam.setType(PokemonType.FIGHTING); + metam.setPower(30); + metam.setAccuracy(1); + metam.setCritChance(0.25); + metam.setTime(1600); + metam.setEnergy(-33); + meta.put(PokemonMove.BRICK_BREAK, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.THUNDERBOLT); + metam.setType(PokemonType.ELECTRIC); + metam.setPower(55); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2700); + metam.setEnergy(-50); + meta.put(PokemonMove.THUNDERBOLT, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.PSYCHIC); + metam.setType(PokemonType.PSYCHIC); + metam.setPower(55); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2800); + metam.setEnergy(-50); + meta.put(PokemonMove.PSYCHIC, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.STONE_EDGE); + metam.setType(PokemonType.ROCK); + metam.setPower(80); + metam.setAccuracy(1); + metam.setCritChance(0.5); + metam.setTime(3100); + metam.setEnergy(-100); + meta.put(PokemonMove.STONE_EDGE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SLUDGE_WAVE); + metam.setType(PokemonType.POISON); + metam.setPower(70); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3400); + metam.setEnergy(-100); + meta.put(PokemonMove.SLUDGE_WAVE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.FLAMETHROWER); + metam.setType(PokemonType.FIRE); + metam.setPower(55); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2900); + metam.setEnergy(-50); + meta.put(PokemonMove.FLAMETHROWER, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.PLAY_ROUGH); + metam.setType(PokemonType.FAIRY); + metam.setPower(55); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2900); + metam.setEnergy(-50); + meta.put(PokemonMove.PLAY_ROUGH, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.MEGAHORN); + metam.setType(PokemonType.BUG); + metam.setPower(80); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3200); + metam.setEnergy(-100); + meta.put(PokemonMove.MEGAHORN, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SHADOW_CLAW_FAST); + metam.setType(PokemonType.GHOST); + metam.setPower(11); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(950); + metam.setEnergy(7); + meta.put(PokemonMove.SHADOW_CLAW_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.THUNDER_PUNCH); + metam.setType(PokemonType.ELECTRIC); + metam.setPower(40); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2400); + metam.setEnergy(-33); + meta.put(PokemonMove.THUNDER_PUNCH, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.HYPER_FANG); + metam.setType(PokemonType.NORMAL); + metam.setPower(35); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2100); + metam.setEnergy(-33); + meta.put(PokemonMove.HYPER_FANG, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.LEAF_BLADE); + metam.setType(PokemonType.GRASS); + metam.setPower(55); + metam.setAccuracy(1); + metam.setCritChance(0.25); + metam.setTime(2800); + metam.setEnergy(-50); + meta.put(PokemonMove.LEAF_BLADE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.DISCHARGE); + metam.setType(PokemonType.ELECTRIC); + metam.setPower(35); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2500); + metam.setEnergy(-33); + meta.put(PokemonMove.DISCHARGE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.WING_ATTACK_FAST); + metam.setType(PokemonType.FLYING); + metam.setPower(9); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(750); + metam.setEnergy(7); + meta.put(PokemonMove.WING_ATTACK_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.HEAT_WAVE); + metam.setType(PokemonType.FIRE); + metam.setPower(80); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3800); + metam.setEnergy(-100); + meta.put(PokemonMove.HEAT_WAVE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.HYDRO_PUMP); + metam.setType(PokemonType.WATER); + metam.setPower(90); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3800); + metam.setEnergy(-100); + meta.put(PokemonMove.HYDRO_PUMP, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.HYDRO_PUMP_BLASTOISE); + metam.setType(PokemonType.WATER); + metam.setPower(90); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3800); + metam.setEnergy(-100); + meta.put(PokemonMove.HYDRO_PUMP_BLASTOISE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.PETAL_BLIZZARD); + metam.setType(PokemonType.GRASS); + metam.setPower(65); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3200); + metam.setEnergy(-50); + meta.put(PokemonMove.PETAL_BLIZZARD, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.BLIZZARD); + metam.setType(PokemonType.ICE); + metam.setPower(100); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3900); + metam.setEnergy(-100); + meta.put(PokemonMove.BLIZZARD, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.VINE_WHIP_FAST); + metam.setType(PokemonType.GRASS); + metam.setPower(7); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(650); + metam.setEnergy(7); + meta.put(PokemonMove.VINE_WHIP_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.THUNDER); + metam.setType(PokemonType.ELECTRIC); + metam.setPower(100); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(4300); + metam.setEnergy(-100); + meta.put(PokemonMove.THUNDER, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.PSYSHOCK); + metam.setType(PokemonType.PSYCHIC); + metam.setPower(40); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2700); + metam.setEnergy(-33); + meta.put(PokemonMove.PSYSHOCK, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.FROST_BREATH_FAST); + metam.setType(PokemonType.ICE); + metam.setPower(9); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(810); + metam.setEnergy(7); + meta.put(PokemonMove.FROST_BREATH_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.POUND_FAST); + metam.setType(PokemonType.NORMAL); + metam.setPower(7); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(540); + metam.setEnergy(7); + meta.put(PokemonMove.POUND_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.MOONBLAST); + metam.setType(PokemonType.FAIRY); + metam.setPower(85); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(4100); + metam.setEnergy(-100); + meta.put(PokemonMove.MOONBLAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.FIRE_BLAST); + metam.setType(PokemonType.FIRE); + metam.setPower(100); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(4100); + metam.setEnergy(-100); + meta.put(PokemonMove.FIRE_BLAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.EARTHQUAKE); + metam.setType(PokemonType.GROUND); + metam.setPower(100); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(4200); + metam.setEnergy(-100); + meta.put(PokemonMove.EARTHQUAKE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SUBMISSION); + metam.setType(PokemonType.FIGHTING); + metam.setPower(30); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2100); + metam.setEnergy(-33); + meta.put(PokemonMove.SUBMISSION, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.X_SCISSOR); + metam.setType(PokemonType.BUG); + metam.setPower(35); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2100); + metam.setEnergy(-33); + meta.put(PokemonMove.X_SCISSOR, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.POISON_JAB_FAST); + metam.setType(PokemonType.POISON); + metam.setPower(12); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1050); + metam.setEnergy(7); + meta.put(PokemonMove.POISON_JAB_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.ZEN_HEADBUTT_FAST); + metam.setType(PokemonType.PSYCHIC); + metam.setPower(12); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1050); + metam.setEnergy(4); + meta.put(PokemonMove.ZEN_HEADBUTT_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.FLASH_CANNON); + metam.setType(PokemonType.STEEL); + metam.setPower(60); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3900); + metam.setEnergy(-33); + meta.put(PokemonMove.FLASH_CANNON, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.HYPER_BEAM); + metam.setType(PokemonType.NORMAL); + metam.setPower(120); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(5000); + metam.setEnergy(-100); + meta.put(PokemonMove.HYPER_BEAM, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.DRAGON_PULSE); + metam.setType(PokemonType.DRAGON); + metam.setPower(65); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3600); + metam.setEnergy(-50); + meta.put(PokemonMove.DRAGON_PULSE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.POWER_GEM); + metam.setType(PokemonType.ROCK); + metam.setPower(40); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2900); + metam.setEnergy(-33); + meta.put(PokemonMove.POWER_GEM, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.PSYSTRIKE); + metam.setType(PokemonType.PSYCHIC); + metam.setPower(70); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(5100); + metam.setEnergy(-100); + meta.put(PokemonMove.PSYSTRIKE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.ICE_BEAM); + metam.setType(PokemonType.ICE); + metam.setPower(65); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3650); + metam.setEnergy(-50); + meta.put(PokemonMove.ICE_BEAM, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.CROSS_POISON); + metam.setType(PokemonType.POISON); + metam.setPower(25); + metam.setAccuracy(1); + metam.setCritChance(0.25); + metam.setTime(1500); + metam.setEnergy(-25); + meta.put(PokemonMove.CROSS_POISON, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.BUG_BITE_FAST); + metam.setType(PokemonType.BUG); + metam.setPower(5); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(450); + metam.setEnergy(7); + meta.put(PokemonMove.BUG_BITE_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SOLAR_BEAM); + metam.setType(PokemonType.GRASS); + metam.setPower(120); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(4900); + metam.setEnergy(-100); + meta.put(PokemonMove.SOLAR_BEAM, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SHADOW_BALL); + metam.setType(PokemonType.GHOST); + metam.setPower(45); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3080); + metam.setEnergy(-33); + meta.put(PokemonMove.SHADOW_BALL, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.DARK_PULSE); + metam.setType(PokemonType.DARK); + metam.setPower(45); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3500); + metam.setEnergy(-33); + meta.put(PokemonMove.DARK_PULSE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.ICE_PUNCH); + metam.setType(PokemonType.ICE); + metam.setPower(45); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3500); + metam.setEnergy(-33); + meta.put(PokemonMove.ICE_PUNCH, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SEED_BOMB); + metam.setType(PokemonType.GRASS); + metam.setPower(40); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2400); + metam.setEnergy(-33); + meta.put(PokemonMove.SEED_BOMB, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.ROCK_SLIDE); + metam.setType(PokemonType.ROCK); + metam.setPower(40); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3200); + metam.setEnergy(-33); + meta.put(PokemonMove.ROCK_SLIDE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.BONE_CLUB); + metam.setType(PokemonType.GROUND); + metam.setPower(20); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1600); + metam.setEnergy(-25); + meta.put(PokemonMove.BONE_CLUB, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.FIRE_PUNCH); + metam.setType(PokemonType.FIRE); + metam.setPower(40); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2800); + metam.setEnergy(-33); + meta.put(PokemonMove.FIRE_PUNCH, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.BITE_FAST); + metam.setType(PokemonType.DARK); + metam.setPower(6); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(500); + metam.setEnergy(7); + meta.put(PokemonMove.BITE_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.DRAGON_BREATH_FAST); + metam.setType(PokemonType.DRAGON); + metam.setPower(6); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(500); + metam.setEnergy(7); + meta.put(PokemonMove.DRAGON_BREATH_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.FLAME_BURST); + metam.setType(PokemonType.FIRE); + metam.setPower(25); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2100); + metam.setEnergy(-25); + meta.put(PokemonMove.FLAME_BURST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.STOMP); + metam.setType(PokemonType.NORMAL); + metam.setPower(30); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2100); + metam.setEnergy(-25); + meta.put(PokemonMove.STOMP, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.DRILL_RUN); + metam.setType(PokemonType.GROUND); + metam.setPower(50); + metam.setAccuracy(1); + metam.setCritChance(0.25); + metam.setTime(3400); + metam.setEnergy(-33); + meta.put(PokemonMove.DRILL_RUN, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.BUG_BUZZ); + metam.setType(PokemonType.BUG); + metam.setPower(75); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(4250); + metam.setEnergy(-50); + meta.put(PokemonMove.BUG_BUZZ, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.FEINT_ATTACK_FAST); + metam.setType(PokemonType.DARK); + metam.setPower(12); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1040); + metam.setEnergy(7); + meta.put(PokemonMove.FEINT_ATTACK_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SIGNAL_BEAM); + metam.setType(PokemonType.BUG); + metam.setPower(35); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3100); + metam.setEnergy(-33); + meta.put(PokemonMove.SIGNAL_BEAM, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.REST); + metam.setType(PokemonType.NORMAL); + metam.setPower(35); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3100); + metam.setEnergy(-33); + meta.put(PokemonMove.REST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.STEEL_WING_FAST); + metam.setType(PokemonType.STEEL); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1330); + metam.setEnergy(4); + meta.put(PokemonMove.STEEL_WING_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.DRILL_PECK); + metam.setType(PokemonType.FLYING); + metam.setPower(40); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2700); + metam.setEnergy(-33); + meta.put(PokemonMove.DRILL_PECK, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.LOW_SWEEP); + metam.setType(PokemonType.FIGHTING); + metam.setPower(25); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2250); + metam.setEnergy(-25); + meta.put(PokemonMove.LOW_SWEEP, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.TACKLE_FAST); + metam.setType(PokemonType.NORMAL); + metam.setPower(12); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1100); + metam.setEnergy(7); + meta.put(PokemonMove.TACKLE_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.DAZZLING_GLEAM); + metam.setType(PokemonType.FAIRY); + metam.setPower(55); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(4200); + metam.setEnergy(-33); + meta.put(PokemonMove.DAZZLING_GLEAM, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.CUT_FAST); + metam.setType(PokemonType.NORMAL); + metam.setPower(12); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1130); + metam.setEnergy(7); + meta.put(PokemonMove.CUT_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.POISON_STING_FAST); + metam.setType(PokemonType.POISON); + metam.setPower(6); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(575); + metam.setEnergy(4); + meta.put(PokemonMove.POISON_STING_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.RAZOR_LEAF_FAST); + metam.setType(PokemonType.GRASS); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1450); + metam.setEnergy(7); + meta.put(PokemonMove.RAZOR_LEAF_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SUCKER_PUNCH_FAST); + metam.setType(PokemonType.DARK); + metam.setPower(7); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(700); + metam.setEnergy(4); + meta.put(PokemonMove.SUCKER_PUNCH_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SPARK_FAST); + metam.setType(PokemonType.ELECTRIC); + metam.setPower(7); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(700); + metam.setEnergy(4); + meta.put(PokemonMove.SPARK_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.GIGA_DRAIN); + metam.setType(PokemonType.GRASS); + metam.setPower(35); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3600); + metam.setEnergy(-33); + meta.put(PokemonMove.GIGA_DRAIN, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SLUDGE); + metam.setType(PokemonType.POISON); + metam.setPower(25); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2600); + metam.setEnergy(-25); + meta.put(PokemonMove.SLUDGE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.MUD_BOMB); + metam.setType(PokemonType.GROUND); + metam.setPower(30); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2600); + metam.setEnergy(-25); + meta.put(PokemonMove.MUD_BOMB, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SHADOW_PUNCH); + metam.setType(PokemonType.GHOST); + metam.setPower(20); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2100); + metam.setEnergy(-25); + meta.put(PokemonMove.SHADOW_PUNCH, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.EMBER_FAST); + metam.setType(PokemonType.FIRE); + metam.setPower(10); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1050); + metam.setEnergy(7); + meta.put(PokemonMove.EMBER_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.ACID_FAST); + metam.setType(PokemonType.POISON); + metam.setPower(10); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1050); + metam.setEnergy(7); + meta.put(PokemonMove.ACID_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.NIGHT_SLASH); + metam.setType(PokemonType.DARK); + metam.setPower(30); + metam.setAccuracy(1); + metam.setCritChance(0.25); + metam.setTime(2700); + metam.setEnergy(-25); + meta.put(PokemonMove.NIGHT_SLASH, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.PSYBEAM); + metam.setType(PokemonType.PSYCHIC); + metam.setPower(35); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3800); + metam.setEnergy(-25); + meta.put(PokemonMove.PSYBEAM, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.WATER_PULSE); + metam.setType(PokemonType.WATER); + metam.setPower(35); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3300); + metam.setEnergy(-25); + meta.put(PokemonMove.WATER_PULSE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.HORN_ATTACK); + metam.setType(PokemonType.NORMAL); + metam.setPower(20); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2200); + metam.setEnergy(-25); + meta.put(PokemonMove.HORN_ATTACK, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.MAGNET_BOMB); + metam.setType(PokemonType.STEEL); + metam.setPower(25); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2800); + metam.setEnergy(-25); + meta.put(PokemonMove.MAGNET_BOMB, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.STRUGGLE); + metam.setType(PokemonType.NORMAL); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1695); + metam.setEnergy(-20); + meta.put(PokemonMove.STRUGGLE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.BULLDOZE); + metam.setType(PokemonType.GROUND); + metam.setPower(35); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3400); + metam.setEnergy(-25); + meta.put(PokemonMove.BULLDOZE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.ROCK_THROW_FAST); + metam.setType(PokemonType.ROCK); + metam.setPower(12); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1360); + metam.setEnergy(7); + meta.put(PokemonMove.ROCK_THROW_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SCALD); + metam.setType(PokemonType.WATER); + metam.setPower(35); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(4000); + metam.setEnergy(-33); + meta.put(PokemonMove.SCALD, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SCALD_BLASTOISE); + metam.setType(PokemonType.WATER); + metam.setPower(35); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(4000); + metam.setEnergy(-33); + meta.put(PokemonMove.SCALD_BLASTOISE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.PECK_FAST); + metam.setType(PokemonType.FLYING); + metam.setPower(10); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1150); + metam.setEnergy(10); + meta.put(PokemonMove.PECK_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.AERIAL_ACE); + metam.setType(PokemonType.FLYING); + metam.setPower(30); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2900); + metam.setEnergy(-25); + meta.put(PokemonMove.AERIAL_ACE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.BUBBLE_BEAM); + metam.setType(PokemonType.WATER); + metam.setPower(30); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2900); + metam.setEnergy(-25); + meta.put(PokemonMove.BUBBLE_BEAM, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.ANCIENT_POWER); + metam.setType(PokemonType.ROCK); + metam.setPower(35); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3600); + metam.setEnergy(-25); + meta.put(PokemonMove.ANCIENT_POWER, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.BRINE); + metam.setType(PokemonType.WATER); + metam.setPower(20); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2400); + metam.setEnergy(-25); + meta.put(PokemonMove.BRINE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SWIFT); + metam.setType(PokemonType.NORMAL); + metam.setPower(25); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3000); + metam.setEnergy(-25); + meta.put(PokemonMove.SWIFT, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.THUNDER_SHOCK_FAST); + metam.setType(PokemonType.ELECTRIC); + metam.setPower(5); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(600); + metam.setEnergy(7); + meta.put(PokemonMove.THUNDER_SHOCK_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.LOW_KICK_FAST); + metam.setType(PokemonType.FIGHTING); + metam.setPower(5); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(600); + metam.setEnergy(7); + meta.put(PokemonMove.LOW_KICK_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.BULLET_PUNCH_FAST); + metam.setType(PokemonType.STEEL); + metam.setPower(10); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1200); + metam.setEnergy(7); + meta.put(PokemonMove.BULLET_PUNCH_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.FIRE_FANG_FAST); + metam.setType(PokemonType.FIRE); + metam.setPower(10); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(840); + metam.setEnergy(4); + meta.put(PokemonMove.FIRE_FANG_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SPLASH_FAST); + metam.setType(PokemonType.WATER); + metam.setPower(10); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1230); + metam.setEnergy(7); + meta.put(PokemonMove.SPLASH_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.OMINOUS_WIND); + metam.setType(PokemonType.GHOST); + metam.setPower(30); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3100); + metam.setEnergy(-25); + meta.put(PokemonMove.OMINOUS_WIND, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.CONFUSION_FAST); + metam.setType(PokemonType.PSYCHIC); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1510); + metam.setEnergy(7); + meta.put(PokemonMove.CONFUSION_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.HEART_STAMP); + metam.setType(PokemonType.PSYCHIC); + metam.setPower(20); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2550); + metam.setEnergy(-25); + meta.put(PokemonMove.HEART_STAMP, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.DIG); + metam.setType(PokemonType.GROUND); + metam.setPower(70); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(5800); + metam.setEnergy(-33); + meta.put(PokemonMove.DIG, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.FLAME_WHEEL); + metam.setType(PokemonType.FIRE); + metam.setPower(40); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(4600); + metam.setEnergy(-25); + meta.put(PokemonMove.FLAME_WHEEL, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.AIR_CUTTER); + metam.setType(PokemonType.FLYING); + metam.setPower(30); + metam.setAccuracy(1); + metam.setCritChance(0.25); + metam.setTime(3300); + metam.setEnergy(-25); + meta.put(PokemonMove.AIR_CUTTER, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.QUICK_ATTACK_FAST); + metam.setType(PokemonType.NORMAL); + metam.setPower(10); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1330); + metam.setEnergy(7); + meta.put(PokemonMove.QUICK_ATTACK_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.FURY_CUTTER_FAST); + metam.setType(PokemonType.BUG); + metam.setPower(3); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(400); + metam.setEnergy(12); + meta.put(PokemonMove.FURY_CUTTER_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.KARATE_CHOP_FAST); + metam.setType(PokemonType.FIGHTING); + metam.setPower(6); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(800); + metam.setEnergy(7); + meta.put(PokemonMove.KARATE_CHOP_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.ROCK_TOMB); + metam.setType(PokemonType.ROCK); + metam.setPower(25); + metam.setAccuracy(1); + metam.setCritChance(0.25); + metam.setTime(3400); + metam.setEnergy(-25); + meta.put(PokemonMove.ROCK_TOMB, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.ICE_SHARD_FAST); + metam.setType(PokemonType.ICE); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1400); + metam.setEnergy(7); + meta.put(PokemonMove.ICE_SHARD_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.VICE_GRIP); + metam.setType(PokemonType.NORMAL); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2100); + metam.setEnergy(-20); + meta.put(PokemonMove.VICE_GRIP, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.PARABOLIC_CHARGE); + metam.setType(PokemonType.ELECTRIC); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2100); + metam.setEnergy(-20); + meta.put(PokemonMove.PARABOLIC_CHARGE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.BUBBLE_FAST); + metam.setType(PokemonType.WATER); + metam.setType(PokemonType.WATER); + metam.setPower(25); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2300); + metam.setEnergy(15); + meta.put(PokemonMove.BUBBLE_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.FLAME_CHARGE); + metam.setType(PokemonType.FIRE); + metam.setPower(20); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3100); + metam.setEnergy(-20); + meta.put(PokemonMove.FLAME_CHARGE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.AQUA_JET); + metam.setType(PokemonType.WATER); + metam.setPower(25); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2350); + metam.setEnergy(-20); + meta.put(PokemonMove.AQUA_JET, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.POISON_FANG); + metam.setType(PokemonType.POISON); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2400); + metam.setEnergy(-20); + meta.put(PokemonMove.POISON_FANG, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.TWISTER); + metam.setType(PokemonType.DRAGON); + metam.setPower(25); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2700); + metam.setEnergy(-20); + meta.put(PokemonMove.TWISTER, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.DRAINING_KISS); + metam.setType(PokemonType.FAIRY); + metam.setPower(25); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(2800); + metam.setEnergy(-20); + meta.put(PokemonMove.DRAINING_KISS, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.DISARMING_VOICE); + metam.setType(PokemonType.FAIRY); + metam.setPower(20); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3900); + metam.setEnergy(-20); + meta.put(PokemonMove.DISARMING_VOICE, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.SHADOW_SNEAK); + metam.setType(PokemonType.GHOST); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3100); + metam.setEnergy(-20); + meta.put(PokemonMove.SHADOW_SNEAK, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.MEGA_DRAIN); + metam.setType(PokemonType.GRASS); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3200); + metam.setEnergy(-20); + meta.put(PokemonMove.MEGA_DRAIN, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.MUD_SLAP_FAST); + metam.setType(PokemonType.GROUND); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1350); + metam.setEnergy(9); + meta.put(PokemonMove.MUD_SLAP_FAST, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.WRAP_GREEN); + metam.setType(PokemonType.NORMAL); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3700); + metam.setEnergy(-20); + meta.put(PokemonMove.WRAP_GREEN, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.WRAP_PINK); + metam.setType(PokemonType.NORMAL); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3700); + metam.setEnergy(-20); + meta.put(PokemonMove.WRAP_PINK, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.ICY_WIND); + metam.setType(PokemonType.ICE); + metam.setPower(25); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(3800); + metam.setEnergy(-20); + meta.put(PokemonMove.ICY_WIND, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.WRAP); + metam.setType(PokemonType.NORMAL); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(4000); + metam.setEnergy(-20); + meta.put(PokemonMove.WRAP, metam); + + metam = new PokemonMoveMeta(); + metam.setMove(PokemonMove.ROCK_SMASH_FAST); + metam.setType(PokemonType.FIGHTING); + metam.setPower(15); + metam.setAccuracy(1); + metam.setCritChance(0.05); + metam.setTime(1410); + metam.setEnergy(7); + meta.put(PokemonMove.ROCK_SMASH_FAST, metam); + + } + + /** + * Return PokemonMoveMeta object containing meta info about a pokemon move. + * + * @param id + * the id of the pokemon move + * @return PokemonMoveMeta + */ + public static PokemonMoveMeta getMeta(PokemonMove id) { + return meta.get(id); + } + +} diff --git a/src/main/java/com/pokegoapi/api/pokemon/PokemonType.java b/src/main/java/com/pokegoapi/api/pokemon/PokemonType.java index c63d9e12..cd559c22 100644 --- a/src/main/java/com/pokegoapi/api/pokemon/PokemonType.java +++ b/src/main/java/com/pokegoapi/api/pokemon/PokemonType.java @@ -14,5 +14,11 @@ public enum PokemonType { PSYCHIC, FIGHTING, DRAGON, - FLYING, ICE, ROCK, GROUND, GHOST, STEEL; + FLYING, + ICE, + ROCK, + GROUND, + GHOST, + STEEL, + DARK; } diff --git a/src/main/java/com/pokegoapi/api/settings/FortSettings.java b/src/main/java/com/pokegoapi/api/settings/FortSettings.java new file mode 100644 index 00000000..483a4180 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/settings/FortSettings.java @@ -0,0 +1,10 @@ +package com.pokegoapi.api.settings; + +/** + * Created by rama on 27/07/16. + */ +public class FortSettings { + //TODO: parse & save data + public void update(POGOProtos.Settings.FortSettingsOuterClass.FortSettings fortSettings) { + } +} diff --git a/src/main/java/com/pokegoapi/api/settings/InventorySettings.java b/src/main/java/com/pokegoapi/api/settings/InventorySettings.java new file mode 100644 index 00000000..8c8d7525 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/settings/InventorySettings.java @@ -0,0 +1,27 @@ +package com.pokegoapi.api.settings; + +import lombok.Getter; + +/** + * Created by rama on 27/07/16. + */ +public class InventorySettings { + @Getter + private int baseBagItems; + @Getter + private int maxBagItems; + @Getter + private int baseEggs; + @Getter + private int basePokemon; + @Getter + private int maxPokemon; + + protected void update(POGOProtos.Settings.InventorySettingsOuterClass.InventorySettings inventorySettings) { + baseBagItems = inventorySettings.getBaseBagItems(); + maxBagItems = inventorySettings.getMaxBagItems(); + baseEggs = inventorySettings.getBaseEggs(); + maxPokemon = inventorySettings.getMaxPokemon(); + basePokemon = inventorySettings.getBasePokemon(); + } +} diff --git a/src/main/java/com/pokegoapi/api/settings/LevelUpSettings.java b/src/main/java/com/pokegoapi/api/settings/LevelUpSettings.java new file mode 100644 index 00000000..72384f01 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/settings/LevelUpSettings.java @@ -0,0 +1,13 @@ +package com.pokegoapi.api.settings; + +import POGOProtos.Settings.InventorySettingsOuterClass; + +/** + * Created by rama on 27/07/16. + */ +public class LevelUpSettings { + //TODO: parse & save data + protected void update(InventorySettingsOuterClass.InventorySettings mapSettings) { + + } +} diff --git a/src/main/java/com/pokegoapi/api/settings/MapSettings.java b/src/main/java/com/pokegoapi/api/settings/MapSettings.java new file mode 100644 index 00000000..72e09914 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/settings/MapSettings.java @@ -0,0 +1,78 @@ +package com.pokegoapi.api.settings; + +import POGOProtos.Settings.MapSettingsOuterClass; +import lombok.Getter; + +/** + * Created by rama on 27/07/16. + */ +public class MapSettings { + + @Getter + /** + * Google api key used for display map + * + * @return String. + */ + private String googleApiKey; + + @Getter + /** + * Minimum distance between getMapObjects requests + * + * @return distance in meters. + */ + private float minMapObjectDistance; + + @Getter + /** + * Max refresh betweewn getMapObjecs requests + * + * @return value in milliseconds. + */ + private float maxRefresh; + + @Getter + /** + * Min refresh betweewn getMapObjecs requests + * + * @return value in milliseconds. + */ + private float minRefresh; + + @Getter + /** + * NOT SURE: the max distance for encounter pokemon? + * + * @return distance in meters. + */ + private double encoungerRange; + + @Getter + /** + * NOT SURE: the max distance before show pokemon on map? + * + * @return distance in meters. + */ + private double pokemonVisibilityRange; + + @Getter + /** + * NO IDEA + * + * @return distance in meters. + */ + private double pokeNavRange; + + protected void update(MapSettingsOuterClass.MapSettings mapSettings) { + googleApiKey = mapSettings.getGoogleMapsApiKey(); + minMapObjectDistance = mapSettings.getGetMapObjectsMinDistanceMeters(); + maxRefresh = mapSettings.getGetMapObjectsMaxRefreshSeconds() * 1000; + minRefresh = mapSettings.getGetMapObjectsMinRefreshSeconds() * 1000; + encoungerRange = mapSettings.getEncounterRangeMeters(); + pokemonVisibilityRange = mapSettings.getPokemonVisibleRange(); + pokeNavRange = mapSettings.getPokeNavRangeMeters(); + + } + +} diff --git a/src/main/java/com/pokegoapi/api/settings/Settings.java b/src/main/java/com/pokegoapi/api/settings/Settings.java new file mode 100644 index 00000000..9a114610 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/settings/Settings.java @@ -0,0 +1,98 @@ +package com.pokegoapi.api.settings; + +import POGOProtos.Networking.Requests.Messages.DownloadSettingsMessageOuterClass; +import POGOProtos.Networking.Requests.RequestTypeOuterClass; +import POGOProtos.Networking.Responses.DownloadSettingsResponseOuterClass; +import com.google.protobuf.InvalidProtocolBufferException; +import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.main.ServerRequest; +import lombok.Getter; + +/** + * Created by rama on 27/07/16. + */ +public class Settings { + + private final PokemonGo api; + + + @Getter + /** + * Settings for various parameters on map + * + * @return MapSettings instance. + */ + private final MapSettings mapSettings; + + @Getter + /** + * Settings for various parameters during levelup + * + * @return LevelUpSettings instance. + */ + private final LevelUpSettings levelUpSettings; + + @Getter + /** + * Settings for various parameters during levelup + * + * @return LevelUpSettings instance. + */ + private final FortSettings fortSettings; + + + @Getter + /** + * Settings for various parameters during levelup + * + * @return LevelUpSettings instance. + */ + private final InventorySettings inventorySettings; + + + /** + * Settings object that hold different configuration aspect of the game. + * Can be used to simulate the real app behaviour. + * + * @param api api instance + * @throws LoginFailedException If login failed. + * @throws RemoteServerException If server communications failed. + */ + public Settings(PokemonGo api) throws LoginFailedException, RemoteServerException { + this.api = api; + this.mapSettings = new MapSettings(); + this.levelUpSettings = new LevelUpSettings(); + this.fortSettings = new FortSettings(); + this.inventorySettings = new InventorySettings(); + updateSettings(); + } + + /** + * Updates settings latest data. + * + * @throws LoginFailedException the login failed exception + * @throws RemoteServerException the remote server exception + */ + public void updateSettings() throws RemoteServerException, LoginFailedException { + DownloadSettingsMessageOuterClass.DownloadSettingsMessage msg = + DownloadSettingsMessageOuterClass.DownloadSettingsMessage.newBuilder().build(); + ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.DOWNLOAD_SETTINGS, msg); + api.getRequestHandler().sendServerRequests(serverRequest); //here you marked everything as read + DownloadSettingsResponseOuterClass.DownloadSettingsResponse response; + try { + response = DownloadSettingsResponseOuterClass.DownloadSettingsResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + + mapSettings.update(response.getSettings().getMapSettings()); + levelUpSettings.update(response.getSettings().getInventorySettings()); + fortSettings.update(response.getSettings().getFortSettings()); + inventorySettings.update(response.getSettings().getInventorySettings()); + + } + + +} diff --git a/src/main/java/com/pokegoapi/auth/CredentialProvider.java b/src/main/java/com/pokegoapi/auth/CredentialProvider.java index f661de6d..754b9c75 100644 --- a/src/main/java/com/pokegoapi/auth/CredentialProvider.java +++ b/src/main/java/com/pokegoapi/auth/CredentialProvider.java @@ -16,7 +16,6 @@ package com.pokegoapi.auth; import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo; - import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; diff --git a/src/main/java/com/pokegoapi/auth/GoogleAuthJson.java b/src/main/java/com/pokegoapi/auth/GoogleAuthJson.java index 5f8cb59a..9adf4c8a 100644 --- a/src/main/java/com/pokegoapi/auth/GoogleAuthJson.java +++ b/src/main/java/com/pokegoapi/auth/GoogleAuthJson.java @@ -16,7 +16,6 @@ package com.pokegoapi.auth; import com.squareup.moshi.Json; - import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/pokegoapi/auth/GoogleAuthTokenJson.java b/src/main/java/com/pokegoapi/auth/GoogleAuthTokenJson.java index d31c5efc..3678d493 100644 --- a/src/main/java/com/pokegoapi/auth/GoogleAuthTokenJson.java +++ b/src/main/java/com/pokegoapi/auth/GoogleAuthTokenJson.java @@ -16,7 +16,6 @@ package com.pokegoapi.auth; import com.squareup.moshi.Json; - import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/pokegoapi/auth/GoogleAutoCredentialProvider.java b/src/main/java/com/pokegoapi/auth/GoogleAutoCredentialProvider.java new file mode 100644 index 00000000..1447d89a --- /dev/null +++ b/src/main/java/com/pokegoapi/auth/GoogleAutoCredentialProvider.java @@ -0,0 +1,124 @@ +package com.pokegoapi.auth; + +import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.util.SystemTimeImpl; +import com.pokegoapi.util.Time; +import lombok.Getter; +import okhttp3.OkHttpClient; +import svarzee.gps.gpsoauth.AuthToken; +import svarzee.gps.gpsoauth.Gpsoauth; + +import java.io.IOException; + +/** + * Use to login with google username and password + */ +public class GoogleAutoCredentialProvider extends CredentialProvider { + + // from https://github.com/tejado/pgoapi/blob/master/pgoapi/auth_google.py + private static String GOOGLE_LOGIN_ANDROID_ID = "9774d56d682e549c"; + private static String GOOGLE_LOGIN_SERVICE = + "audience:server:client_id:848232511240-7so421jotr2609rmqakceuu1luuq0ptb.apps.googleusercontent.com"; + private static String GOOGLE_LOGIN_APP = "com.nianticlabs.pokemongo"; + private static String GOOGLE_LOGIN_CLIENT_SIG = "321187995bc7cdc2b5fc91b11a96e2baa8602c62"; + + private final Gpsoauth gpsoauth; + private final String username; + private Time time; + + @Getter + private TokenInfo tokenInfo; + + /** + * Constructs credential provider using username and password + * + * @param username - google username + * @param password - google password + * @throws LoginFailedException - login failed possibly due to invalid credentials + * @throws RemoteServerException - some server/network failure + */ + public GoogleAutoCredentialProvider(OkHttpClient httpClient, String username, String password) + throws LoginFailedException, RemoteServerException { + this.gpsoauth = new Gpsoauth(httpClient); + this.username = username; + this.tokenInfo = login(username, password); + this.time = new SystemTimeImpl(); + } + + /** + * + * @param httpClient : the client that will make http call + * @param username : google username + * @param password : google pwd + * @param time : time instance used to refresh token + * @throws LoginFailedException - login failed possibly due to invalid credentials + * @throws RemoteServerException - some server/network failure + */ + public GoogleAutoCredentialProvider(OkHttpClient httpClient, String username, String password, Time time) + throws LoginFailedException, RemoteServerException { + this.gpsoauth = new Gpsoauth(httpClient); + this.username = username; + this.tokenInfo = login(username, password); + this.time = time; + } + + private TokenInfo login(String username, String password) + throws RemoteServerException, LoginFailedException { + try { + String masterToken = gpsoauth.performMasterLoginForToken(username, password, GOOGLE_LOGIN_ANDROID_ID); + AuthToken authToken = gpsoauth.performOAuthForToken(username, masterToken, GOOGLE_LOGIN_ANDROID_ID, + GOOGLE_LOGIN_SERVICE, GOOGLE_LOGIN_APP, GOOGLE_LOGIN_CLIENT_SIG); + return new TokenInfo(authToken, masterToken); + } catch (IOException e) { + throw new RemoteServerException(e); + } catch (Gpsoauth.TokenRequestFailed e) { + throw new LoginFailedException(e); + } + } + + private TokenInfo refreshToken(String username, String refreshToken) + throws RemoteServerException, LoginFailedException { + try { + AuthToken authToken = gpsoauth.performOAuthForToken(username, refreshToken, GOOGLE_LOGIN_ANDROID_ID, + GOOGLE_LOGIN_SERVICE, GOOGLE_LOGIN_APP, GOOGLE_LOGIN_CLIENT_SIG); + return new TokenInfo(authToken, refreshToken); + } catch (IOException e) { + throw new RemoteServerException(e); + } catch (Gpsoauth.TokenRequestFailed e) { + throw new LoginFailedException(e); + } + } + + @Override + public String getTokenId() throws LoginFailedException, RemoteServerException { + if (isTokenIdExpired()) { + this.tokenInfo = refreshToken(username, tokenInfo.refreshToken); + } + return tokenInfo.authToken.getToken(); + } + + @Override + public AuthInfo getAuthInfo() throws LoginFailedException, RemoteServerException { + AuthInfo.Builder builder = AuthInfo.newBuilder(); + builder.setProvider("google"); + builder.setToken(AuthInfo.JWT.newBuilder().setContents(tokenInfo.authToken.getToken()).setUnknown2(59).build()); + return builder.build(); + } + + @Override + public boolean isTokenIdExpired() { + return tokenInfo.authToken.getExpiry() > time.currentTimeMillis() / 1000 - 60; + } + + private static class TokenInfo { + final AuthToken authToken; + final String refreshToken; + + TokenInfo(AuthToken authToken, String refreshToken) { + this.authToken = authToken; + this.refreshToken = refreshToken; + } + } +} diff --git a/src/main/java/com/pokegoapi/auth/GoogleUserCredentialProvider.java b/src/main/java/com/pokegoapi/auth/GoogleUserCredentialProvider.java new file mode 100644 index 00000000..6f3426b4 --- /dev/null +++ b/src/main/java/com/pokegoapi/auth/GoogleUserCredentialProvider.java @@ -0,0 +1,249 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.auth; + +import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.util.Log; +import com.pokegoapi.util.SystemTimeImpl; +import com.pokegoapi.util.Time; +import com.squareup.moshi.Moshi; +import lombok.Getter; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +import java.io.IOException; + +public class GoogleUserCredentialProvider extends CredentialProvider { + + public static final String SECRET = "NCjF1TLi2CcY6t5mt0ZveuL7"; + public static final String CLIENT_ID = "848232511240-73ri3t7plvk96pj4f85uj8otdat2alem.apps.googleusercontent.com"; + public static final String OAUTH_TOKEN_ENDPOINT = "https://www.googleapis.com/oauth2/v4/token"; + public static final String LOGIN_URL = "https://accounts.google.com/o/oauth2/auth?client_id=848232511240-73ri3t7plvk96pj4f85uj8otdat2alem.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_type=code&scope=openid%20email%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email"; + private static final String TAG = GoogleUserCredentialProvider.class.getSimpleName(); + //We try and refresh token 5 minutes before it actually expires + protected static final long REFRESH_TOKEN_BUFFER_TIME = 5 * 60 * 1000; + protected final OkHttpClient client; + + protected final Time time; + + protected long expiresTimestamp; + + protected String tokenId; + + @Getter + protected String refreshToken; + + protected AuthInfo.Builder authbuilder; + + /** + * Used for logging in when one has a persisted refreshToken. + * + * @param client OkHttp client + * @param refreshToken Refresh Token Persisted by user + * @param time a Time implementation + * @throws LoginFailedException When login fails + * @throws RemoteServerException When server fails + */ + public GoogleUserCredentialProvider(OkHttpClient client, String refreshToken, Time time) + throws LoginFailedException, RemoteServerException { + this.time = time; + this.client = client; + this.refreshToken = refreshToken; + + refreshToken(refreshToken); + authbuilder = AuthInfo.newBuilder(); + } + + /** + * Used for logging in when one has a persisted refreshToken. + * + * @param client OkHttp client + * @param refreshToken Refresh Token Persisted by user + * @throws LoginFailedException When login fails + * @throws RemoteServerException When server fails + */ + public GoogleUserCredentialProvider(OkHttpClient client, String refreshToken) + throws LoginFailedException, RemoteServerException { + this.time = new SystemTimeImpl(); + this.client = client; + this.refreshToken = refreshToken; + + refreshToken(refreshToken); + authbuilder = AuthInfo.newBuilder(); + } + + /** + * Used for logging in when you dont have a persisted refresh token. + * + * @param client OkHttp client + * @param time a Time implementation + * @throws LoginFailedException When login fails + * @throws RemoteServerException When server fails + */ + public GoogleUserCredentialProvider(OkHttpClient client, Time time) + throws LoginFailedException, RemoteServerException { + this.time = time; + this.client = client; + + authbuilder = AuthInfo.newBuilder(); + } + + /** + * Used for logging in when you dont have a persisted refresh token. + * + * @param client OkHttp client + * @throws LoginFailedException When login fails + * @throws RemoteServerException When server fails + */ + public GoogleUserCredentialProvider(OkHttpClient client) + throws LoginFailedException, RemoteServerException { + this.time = new SystemTimeImpl(); + this.client = client; + + authbuilder = AuthInfo.newBuilder(); + } + + + /** + * Given the refresh token fetches a new access token and returns AuthInfo. + * + * @param refreshToken Refresh token persisted by the user after initial login + * @throws LoginFailedException If we fail to get tokenId + */ + public void refreshToken(String refreshToken) throws LoginFailedException, RemoteServerException { + HttpUrl url = HttpUrl.parse(OAUTH_TOKEN_ENDPOINT).newBuilder() + .addQueryParameter("client_id", CLIENT_ID) + .addQueryParameter("client_secret", SECRET) + .addQueryParameter("refresh_token", refreshToken) + .addQueryParameter("grant_type", "refresh_token") + .build(); + //Empty request body + RequestBody reqBody = RequestBody.create(null, new byte[0]); + Request request = new Request.Builder() + .url(url) + .method("POST", reqBody) + .build(); + + Response response = null; + try { + response = client.newCall(request).execute(); + + } catch (IOException e) { + throw new RemoteServerException("Network Request failed to fetch refreshed tokenId", e); + } + Moshi moshi = new Moshi.Builder().build(); + GoogleAuthTokenJson googleAuthTokenJson = null; + try { + googleAuthTokenJson = moshi.adapter(GoogleAuthTokenJson.class).fromJson(response.body().string()); + Log.d(TAG, "" + googleAuthTokenJson.getExpiresIn()); + } catch (IOException e) { + throw new RemoteServerException("Failed to unmarshal the Json response to fetch refreshed tokenId", e); + } + if (googleAuthTokenJson.getError() != null) { + throw new LoginFailedException(googleAuthTokenJson.getError()); + } else { + Log.d(TAG, "Refreshed Token " + googleAuthTokenJson.getIdToken()); + expiresTimestamp = time.currentTimeMillis() + + (googleAuthTokenJson.getExpiresIn() * 1000 - REFRESH_TOKEN_BUFFER_TIME); + tokenId = googleAuthTokenJson.getIdToken(); + } + } + + + /** + * Uses an access code to login and get tokens + */ + public void login(String authcode) throws LoginFailedException, RemoteServerException { + + HttpUrl url = HttpUrl.parse(OAUTH_TOKEN_ENDPOINT).newBuilder() + .addQueryParameter("code", authcode) + .addQueryParameter("client_id", CLIENT_ID) + .addQueryParameter("client_secret", SECRET) + .addQueryParameter("grant_type", "authorization_code") + .addQueryParameter("scope", "openid email https://www.googleapis.com/auth/userinfo.email") + .addQueryParameter("redirect_uri", "urn:ietf:wg:oauth:2.0:oob") + .build(); + + //Create empty body + RequestBody reqBody = RequestBody.create(null, new byte[0]); + + Request request = new Request.Builder() + .url(url) + .method("POST", reqBody) + .build(); + Response response = null; + try { + response = client.newCall(request).execute(); + } catch (IOException e) { + throw new RemoteServerException("Network Request failed to fetch tokenId", e); + } + + Moshi moshi = new Moshi.Builder().build(); + + GoogleAuthTokenJson googleAuth = null; + try { + googleAuth = moshi.adapter(GoogleAuthTokenJson.class).fromJson(response.body().string()); + Log.d(TAG, "" + googleAuth.getExpiresIn()); + } catch (IOException e) { + throw new RemoteServerException("Failed to unmarshell the Json response to fetch tokenId", e); + } + + Log.d(TAG, "Got token: " + googleAuth.getAccessToken()); + + expiresTimestamp = time.currentTimeMillis() + + (googleAuth.getExpiresIn() * 1000 - REFRESH_TOKEN_BUFFER_TIME); + tokenId = googleAuth.getIdToken(); + refreshToken = googleAuth.getRefreshToken(); + } + + @Override + public String getTokenId() throws LoginFailedException, RemoteServerException { + if (isTokenIdExpired()) { + refreshToken(refreshToken); + } + return tokenId; + } + + /** + * Refreshes tokenId if it has expired + * + * @return AuthInfo object + * @throws LoginFailedException When login fails + */ + @Override + public AuthInfo getAuthInfo() throws LoginFailedException, RemoteServerException { + if (isTokenIdExpired()) { + refreshToken(refreshToken); + } + authbuilder.setProvider("google"); + authbuilder.setToken(AuthInfo.JWT.newBuilder().setContents(tokenId).setUnknown2(59).build()); + return authbuilder.build(); + } + + @Override + public boolean isTokenIdExpired() { + if (time.currentTimeMillis() > expiresTimestamp) { + return true; + } else { + return false; + } + } +} diff --git a/src/main/java/com/pokegoapi/auth/PtcCredentialProvider.java b/src/main/java/com/pokegoapi/auth/PtcCredentialProvider.java index 216b148a..8733ce83 100644 --- a/src/main/java/com/pokegoapi/auth/PtcCredentialProvider.java +++ b/src/main/java/com/pokegoapi/auth/PtcCredentialProvider.java @@ -18,6 +18,8 @@ import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo; import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.util.SystemTimeImpl; +import com.pokegoapi.util.Time; import com.squareup.moshi.Moshi; import okhttp3.Cookie; import okhttp3.CookieJar; @@ -28,6 +30,7 @@ import okhttp3.RequestBody; import okhttp3.Response; + import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -44,14 +47,15 @@ public class PtcCredentialProvider extends CredentialProvider { public static final String USER_AGENT = "niantic"; private static final String TAG = PtcCredentialProvider.class.getSimpleName(); //We try and refresh token 5 minutes before it actually expires - private static final long REFRESH_TOKEN_BUFFER_TIME = 5 * 60 * 1000; + protected static final long REFRESH_TOKEN_BUFFER_TIME = 5 * 60 * 1000; - private final OkHttpClient client; - private final String username; - private final String password; - private String tokenId; - private long expiresTimestamp; - private AuthInfo.Builder authbuilder; + protected final OkHttpClient client; + protected final String username; + protected final String password; + protected final Time time; + protected String tokenId; + protected long expiresTimestamp; + protected AuthInfo.Builder authbuilder; /** * Instantiates a new Ptc login. @@ -59,9 +63,13 @@ public class PtcCredentialProvider extends CredentialProvider { * @param client the client * @param username Username * @param password password + * @param time a Time implementation + * @throws LoginFailedException When login fails + * @throws RemoteServerException When server fails */ - public PtcCredentialProvider(OkHttpClient client, String username, String password) + public PtcCredentialProvider(OkHttpClient client, String username, String password, Time time) throws LoginFailedException, RemoteServerException { + this.time = time; this.username = username; this.password = password; /* @@ -101,6 +109,19 @@ public Response intercept(Chain chain) throws IOException { login(username, password); } + /** + * Instantiates a new Ptc login. + * Deprecated: specify a Time implementation + * + * @param client the client + * @param username Username + * @param password password + */ + public PtcCredentialProvider(OkHttpClient client, String username, String password) + throws LoginFailedException, RemoteServerException { + this(client, username, password, new SystemTimeImpl()); + } + /** * Starts a login flow for pokemon.com (PTC) using a username and password, * this uses pokemon.com's oauth endpoint and returns a usable AuthInfo without user interaction @@ -213,10 +234,10 @@ private void login(String username, String password) throws LoginFailedException try { params = body.split("&"); this.tokenId = params[0].split("=")[1]; - this.expiresTimestamp = System.currentTimeMillis() + this.expiresTimestamp = time.currentTimeMillis() + (Integer.valueOf(params[1].split("=")[1]) * 1000 - REFRESH_TOKEN_BUFFER_TIME); } catch (Exception e) { - throw new LoginFailedException("Failed to fetch token"); + throw new LoginFailedException("Failed to fetch token, body:" + body); } } @@ -248,7 +269,7 @@ public AuthInfo getAuthInfo() throws LoginFailedException, RemoteServerException @Override public boolean isTokenIdExpired() { - if (System.currentTimeMillis() > expiresTimestamp) { + if (time.currentTimeMillis() > expiresTimestamp) { return true; } else { return false; diff --git a/src/main/java/com/pokegoapi/examples/CatchPokemonAtAreaExample.java b/src/main/java/com/pokegoapi/examples/CatchPokemonAtAreaExample.java index 1c7646dc..3e768509 100644 --- a/src/main/java/com/pokegoapi/examples/CatchPokemonAtAreaExample.java +++ b/src/main/java/com/pokegoapi/examples/CatchPokemonAtAreaExample.java @@ -32,16 +32,15 @@ import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass; - import com.pokegoapi.api.PokemonGo; import com.pokegoapi.api.map.pokemon.CatchResult; import com.pokegoapi.api.map.pokemon.CatchablePokemon; -import com.pokegoapi.api.map.pokemon.EncounterResult; +import com.pokegoapi.api.map.pokemon.encounter.EncounterResult; import com.pokegoapi.auth.PtcCredentialProvider; import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.NoSuchItemException; import com.pokegoapi.exceptions.RemoteServerException; import com.pokegoapi.util.Log; - import okhttp3.OkHttpClient; import java.util.List; @@ -50,6 +49,7 @@ public class CatchPokemonAtAreaExample { /** * Catches a pokemon at an area. + * @param args args */ public static void main(String[] args) { OkHttpClient http = new OkHttpClient(); @@ -79,7 +79,7 @@ public static void main(String[] args) { } - } catch (LoginFailedException | RemoteServerException e) { + } catch (LoginFailedException | NoSuchItemException | RemoteServerException e) { // failed to login, invalid credentials, auth issue or server issue. Log.e("Main", "Failed to login or server issue: ", e); diff --git a/src/main/java/com/pokegoapi/examples/DisplayPokenameExample.java b/src/main/java/com/pokegoapi/examples/DisplayPokenameExample.java new file mode 100644 index 00000000..31b75502 --- /dev/null +++ b/src/main/java/com/pokegoapi/examples/DisplayPokenameExample.java @@ -0,0 +1,56 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.examples; + +import com.pokegoapi.util.Log; +import com.pokegoapi.util.PokeNames; + +import java.util.Locale; + +public class DisplayPokenameExample { + + /** + * Displays All 151 Pokemon Names for all Supported Locales + * @param args Not used + */ + public static void main(String[] args) { + Locale[] supportedLocales = { + Locale.FRENCH, + Locale.GERMAN, + Locale.ENGLISH, + Locale.JAPANESE, + new Locale("zh", "CN"), + new Locale("zh", "HK"), + new Locale("ru"), + }; + for (int i = 1; i < 152; i++) { + //Showcase for Supported Languages + for (Locale l : supportedLocales) { + Log.d("Names-Example", String.format( + l, + "Pokedex Nr# %d is %s in %s", + i, + PokeNames.getDisplayName(i, l), + l.getDisplayName(l))); + } + //Showcase for Fallback Behaviour + Log.d("Names-Example", String.format( + "Pokedex Nr# %d is %s in %s", + i, + PokeNames.getDisplayName(i, new Locale("xx")), "Fallback")); + } + } +} diff --git a/src/main/java/com/pokegoapi/examples/FightGymExample.java b/src/main/java/com/pokegoapi/examples/FightGymExample.java index 96aa5338..565a1786 100644 --- a/src/main/java/com/pokegoapi/examples/FightGymExample.java +++ b/src/main/java/com/pokegoapi/examples/FightGymExample.java @@ -31,7 +31,6 @@ package com.pokegoapi.examples; -import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass; import POGOProtos.Networking.Responses.StartGymBattleResponseOuterClass.StartGymBattleResponse.Result; import com.pokegoapi.api.PokemonGo; import com.pokegoapi.api.gym.Battle; diff --git a/src/main/java/com/pokegoapi/examples/GoogleUserInteractionExample.java b/src/main/java/com/pokegoapi/examples/GoogleUserInteractionExample.java new file mode 100644 index 00000000..3db8f628 --- /dev/null +++ b/src/main/java/com/pokegoapi/examples/GoogleUserInteractionExample.java @@ -0,0 +1,55 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.examples; + + +import com.pokegoapi.auth.GoogleUserCredentialProvider; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import okhttp3.OkHttpClient; + +import java.util.Scanner; + +public class GoogleUserInteractionExample { + + /** + * Example on how to login with Google by asking a token from the user + * @param args stuff + */ + public static void main(String[] args) { + OkHttpClient http = new OkHttpClient(); + try { + // instanciate a provider, it will give an url + GoogleUserCredentialProvider provider = new GoogleUserCredentialProvider(http); + + // in this url, you will get a code for the google account that is logged + System.out.println("Please go to " + provider.LOGIN_URL); + System.out.println("Enter authorisation code:"); + + // Ask the user to enter it in the standart input + Scanner sc = new Scanner(System.in); + String access = sc.nextLine(); + + // we should be able to login with this token + provider.login(access); + System.out.println("Refresh token:" + provider.getRefreshToken()); + + } catch (LoginFailedException | RemoteServerException e) { + e.printStackTrace(); + } + + } +} diff --git a/src/main/java/com/pokegoapi/examples/TransferOnePidgeyExample.java b/src/main/java/com/pokegoapi/examples/TransferOnePidgeyExample.java index c49d20c2..b83d17c0 100644 --- a/src/main/java/com/pokegoapi/examples/TransferOnePidgeyExample.java +++ b/src/main/java/com/pokegoapi/examples/TransferOnePidgeyExample.java @@ -16,34 +16,25 @@ package com.pokegoapi.examples; import POGOProtos.Enums.PokemonIdOuterClass; -import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass; import POGOProtos.Networking.Responses.ReleasePokemonResponseOuterClass; - import com.pokegoapi.api.PokemonGo; import com.pokegoapi.api.pokemon.Pokemon; import com.pokegoapi.auth.PtcCredentialProvider; import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; import com.pokegoapi.util.Log; - import okhttp3.OkHttpClient; import java.util.List; public class TransferOnePidgeyExample { - - /** * Transfers one pidgey from the player's inventory. */ public static void main(String[] args) { OkHttpClient http = new OkHttpClient(); - RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo auth = null; try { - //or google - //new PokemonGo(GoogleCredentialProvider(http,listner)); - //Subsiquently - //new PokemonGo(GoogleCredentialProvider(http,refreshtoken)); + // check readme for other example PokemonGo go = new PokemonGo(new PtcCredentialProvider(http, ExampleLoginDetails.LOGIN, ExampleLoginDetails.PASSWORD), http); @@ -52,6 +43,7 @@ public static void main(String[] args) { if (pidgeys.size() > 0) { Pokemon pest = pidgeys.get(0); + // print the pokemon data pest.debug(); ReleasePokemonResponseOuterClass.ReleasePokemonResponse.Result result = pest.transferPokemon(); @@ -59,8 +51,6 @@ public static void main(String[] args) { } else { Log.i("Main", "You have no pidgeys :O"); } - - } catch (LoginFailedException | RemoteServerException e) { // failed to login, invalid credentials, auth issue or server issue. Log.e("Main", "Failed to login. Invalid credentials or server issue: ", e); diff --git a/src/main/java/com/pokegoapi/examples/UseIncenseExample.java b/src/main/java/com/pokegoapi/examples/UseIncenseExample.java new file mode 100644 index 00000000..53e1035f --- /dev/null +++ b/src/main/java/com/pokegoapi/examples/UseIncenseExample.java @@ -0,0 +1,64 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.examples; + + +import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.auth.GoogleAutoCredentialProvider; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.util.Log; +import com.pokegoapi.util.SystemTimeImpl; +import okhttp3.OkHttpClient; + +public class UseIncenseExample { + + /** + * Catches a pokemon at an area. + */ + public static void main(String[] args) { + OkHttpClient http = new OkHttpClient(); + try { + GoogleAutoCredentialProvider authProvider = + new GoogleAutoCredentialProvider(http, ExampleLoginDetails.LOGIN, ExampleLoginDetails.PASSWORD); + //new PtcLogin(http).login(ExampleLoginDetails.LOGIN, ExampleLoginDetails.PASSWORD); + PokemonGo go = new PokemonGo(authProvider, http, new SystemTimeImpl()); + + go.setLocation(45.817521, 16.028199, 0); + go.getInventories().getItemBag().useIncense(); + + } catch (LoginFailedException | RemoteServerException e) { + // failed to login, invalid credentials, auth issue or server issue. + Log.e("Main", "Failed to login or server issue: ", e); + + } + } +} diff --git a/src/main/java/com/pokegoapi/exceptions/AsyncLoginFailedException.java b/src/main/java/com/pokegoapi/exceptions/AsyncLoginFailedException.java new file mode 100644 index 00000000..3da8efdb --- /dev/null +++ b/src/main/java/com/pokegoapi/exceptions/AsyncLoginFailedException.java @@ -0,0 +1,30 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.exceptions; + +public class AsyncLoginFailedException extends AsyncPokemonGoException { + public AsyncLoginFailedException(String reason) { + super(reason); + } + + public AsyncLoginFailedException(Exception exception) { + super(exception); + } + + public AsyncLoginFailedException(String reason, Exception exception) { + super(reason, exception); + } +} diff --git a/src/main/java/com/pokegoapi/exceptions/AsyncPokemonGoException.java b/src/main/java/com/pokegoapi/exceptions/AsyncPokemonGoException.java new file mode 100644 index 00000000..66744c9c --- /dev/null +++ b/src/main/java/com/pokegoapi/exceptions/AsyncPokemonGoException.java @@ -0,0 +1,31 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.exceptions; + +public class AsyncPokemonGoException extends RuntimeException { + + public AsyncPokemonGoException(String message) { + super(message); + } + + public AsyncPokemonGoException(String message, Throwable cause) { + super(message, cause); + } + + public AsyncPokemonGoException(Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/com/pokegoapi/exceptions/AsyncRemoteServerException.java b/src/main/java/com/pokegoapi/exceptions/AsyncRemoteServerException.java new file mode 100644 index 00000000..b233534b --- /dev/null +++ b/src/main/java/com/pokegoapi/exceptions/AsyncRemoteServerException.java @@ -0,0 +1,30 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.exceptions; + +public class AsyncRemoteServerException extends AsyncPokemonGoException { + public AsyncRemoteServerException(String reason) { + super(reason); + } + + public AsyncRemoteServerException(Exception exception) { + super(exception); + } + + public AsyncRemoteServerException(String reason, Exception exception) { + super(reason, exception); + } +} diff --git a/src/main/java/com/pokegoapi/exceptions/InvalidCurrencyException.java b/src/main/java/com/pokegoapi/exceptions/InvalidCurrencyException.java index dc6f9f07..3593a0ea 100644 --- a/src/main/java/com/pokegoapi/exceptions/InvalidCurrencyException.java +++ b/src/main/java/com/pokegoapi/exceptions/InvalidCurrencyException.java @@ -24,7 +24,7 @@ public InvalidCurrencyException(String reason) { super(reason); } - public InvalidCurrencyException(Exception exception) { + public InvalidCurrencyException(Throwable exception) { super(exception); } } diff --git a/src/main/java/com/pokegoapi/exceptions/LoginFailedException.java b/src/main/java/com/pokegoapi/exceptions/LoginFailedException.java index 85be079e..ca05c0d6 100644 --- a/src/main/java/com/pokegoapi/exceptions/LoginFailedException.java +++ b/src/main/java/com/pokegoapi/exceptions/LoginFailedException.java @@ -24,11 +24,11 @@ public LoginFailedException(String reason) { super(reason); } - public LoginFailedException(Exception exception) { + public LoginFailedException(Throwable exception) { super(exception); } - public LoginFailedException(String reason, Exception exception) { + public LoginFailedException(String reason, Throwable exception) { super(reason, exception); } } diff --git a/src/main/java/com/pokegoapi/exceptions/NoSuchItemException.java b/src/main/java/com/pokegoapi/exceptions/NoSuchItemException.java index 0e537883..6dfa082b 100644 --- a/src/main/java/com/pokegoapi/exceptions/NoSuchItemException.java +++ b/src/main/java/com/pokegoapi/exceptions/NoSuchItemException.java @@ -24,7 +24,7 @@ public NoSuchItemException(String reason) { super(reason); } - public NoSuchItemException(Exception exception) { + public NoSuchItemException(Throwable exception) { super(exception); } } diff --git a/src/main/java/com/pokegoapi/exceptions/RemoteServerException.java b/src/main/java/com/pokegoapi/exceptions/RemoteServerException.java index 5e3ca966..f3edc25c 100644 --- a/src/main/java/com/pokegoapi/exceptions/RemoteServerException.java +++ b/src/main/java/com/pokegoapi/exceptions/RemoteServerException.java @@ -24,11 +24,11 @@ public RemoteServerException(String reason) { super(reason); } - public RemoteServerException(Exception exception) { + public RemoteServerException(Throwable exception) { super(exception); } - public RemoteServerException(String reason, Exception exception) { + public RemoteServerException(String reason, Throwable exception) { super(reason, exception); } } diff --git a/src/main/java/com/pokegoapi/google/common/geometry/R1Interval.java b/src/main/java/com/pokegoapi/google/common/geometry/R1Interval.java index f803296f..06b42a31 100644 --- a/src/main/java/com/pokegoapi/google/common/geometry/R1Interval.java +++ b/src/main/java/com/pokegoapi/google/common/geometry/R1Interval.java @@ -26,14 +26,18 @@ public final strictfp class R1Interval { private final double lo; private final double hi; - /** Interval constructor. If lo > hi, the interval is empty. */ + /** + * Interval constructor. If lo > hi, the interval is empty. + * @param lo lo value + * @param hi hi value + */ public R1Interval(double lo, double hi) { this.lo = lo; this.hi = hi; } /** - * Returns an empty interval. (Any interval where lo > hi is considered + * @return an empty interval. (Any interval where lo > hi is considered * empty.) */ public static R1Interval empty() { @@ -42,6 +46,8 @@ public static R1Interval empty() { /** * Convenience method to construct an interval containing a single point. + * @param p point to get interval for + * @return a new R1Interval from the point. */ public static R1Interval fromPoint(double p) { return new R1Interval(p, p); @@ -51,6 +57,9 @@ public static R1Interval fromPoint(double p) { * Convenience method to construct the minimal interval containing the two * given points. This is equivalent to starting with an empty interval and * calling AddPoint() twice, but it is more efficient. + * @param p1 first point + * @param p2 second point + * @return new R1Interval */ public static R1Interval fromPointPair(double p1, double p2) { if (p1 <= p2) { @@ -69,14 +78,14 @@ public double hi() { } /** - * Return true if the interval is empty, i.e. it contains no points. + * @return true if the interval is empty, i.e. it contains no points. */ public boolean isEmpty() { return lo() > hi(); } /** - * Return the center of the interval. For empty intervals, the result is + * @return the center of the interval. For empty intervals, the result is * arbitrary. */ public double getCenter() { @@ -84,22 +93,35 @@ public double getCenter() { } /** - * Return the length of the interval. The length of an empty interval is + * @return the length of the interval. The length of an empty interval is * negative. */ public double getLength() { return hi() - lo(); } + /** + * + * @param p point + * @return true if p is between lo and hi + */ public boolean contains(double p) { return p >= lo() && p <= hi(); } + /** + * + * @param p point + * @return true if p is inside lo and hi + */ public boolean interiorContains(double p) { return p > lo() && p < hi(); } - /** Return true if this interval contains the interval 'y'. */ + /** + * @param y interval + * @return true if this interval contains the interval 'y'. + */ public boolean contains(R1Interval y) { if (y.isEmpty()) { return true; @@ -108,7 +130,8 @@ public boolean contains(R1Interval y) { } /** - * Return true if the interior of this interval contains the entire interval + * @param y interval + * @return true if the interior of this interval contains the entire interval * 'y' (including its boundary). */ public boolean interiorContains(R1Interval y) { @@ -119,7 +142,8 @@ public boolean interiorContains(R1Interval y) { } /** - * Return true if this interval intersects the given interval, i.e. if they + * @param y interval + * @return true if this interval intersects the given interval, i.e. if they * have any points in common. */ public boolean intersects(R1Interval y) { @@ -131,14 +155,19 @@ public boolean intersects(R1Interval y) { } /** - * Return true if the interior of this interval intersects any point of the + * @param y interval + * @return true if the interior of this interval intersects any point of the * given interval (including its boundary). */ public boolean interiorIntersects(R1Interval y) { return y.lo() < hi() && lo() < y.hi() && lo() < hi() && y.lo() <= y.hi(); } - /** Expand the interval so that it contains the given point "p". */ + /** + * Expand the interval so that it contains the given point "p". + * @param p p + * @return new R1Interval + */ public R1Interval addPoint(double p) { if (isEmpty()) { return R1Interval.fromPoint(p); @@ -152,7 +181,8 @@ public R1Interval addPoint(double p) { } /** - * Return an interval that contains all points with a distance "radius" of a + * @param radius radius + * @return an interval that contains all points with a distance "radius" of a * point in this interval. Note that the expansion of an empty interval is * always empty. */ @@ -165,7 +195,8 @@ public R1Interval expanded(double radius) { } /** - * Return the smallest interval that contains this interval and the given + * @param y interval + * @return the smallest interval that contains this interval and the given * interval "y". */ public R1Interval union(R1Interval y) { @@ -179,7 +210,8 @@ public R1Interval union(R1Interval y) { } /** - * Return the intersection of this interval with the given interval. Empty + * @param y interval + * @return the intersection of this interval with the given interval. Empty * intervals do not need to be special-cased. */ public R1Interval intersection(R1Interval y) { @@ -216,7 +248,8 @@ public boolean approxEquals(R1Interval y) { /** * Return true if length of the symmetric difference between the two intervals * is at most the given tolerance. - * + * @param y y + * @param maxError maxError */ public boolean approxEquals(R1Interval y, double maxError) { if (isEmpty()) { diff --git a/src/main/java/com/pokegoapi/google/common/geometry/S2.java b/src/main/java/com/pokegoapi/google/common/geometry/S2.java index 2862dd36..9ec18be1 100644 --- a/src/main/java/com/pokegoapi/google/common/geometry/S2.java +++ b/src/main/java/com/pokegoapi/google/common/geometry/S2.java @@ -42,7 +42,7 @@ public final strictfp class S2 { /** * If v is non-zero, return an integer {@code exp} such that - * {@code (0.5 <= |v|*2^(-exp) < 1)}. If v is zero, return 0. + * {@code (0.5 <= |v|*2^(-exp) < 1)}. If v is zero, return 0. * *

Note that this arguably a bad definition of exponent because it makes * {@code exp(9) == 4}. In decimal this would be like saying that the @@ -50,6 +50,7 @@ public final strictfp class S2 { * {@code 1.234 x 10^3}. * * TODO(dbeaumont): Replace this with "DoubleUtils.getExponent(v) - 1" ? + * @param v v */ static int exp(double v) { @@ -99,7 +100,7 @@ public static int posToOrientation(int position) { * @param orientation the subcell orientation, in the range [0,3]. * @param position the position of the subcell in the Hilbert traversal, in * the range [0,3]. - * @return the IJ-index where {@code 0->(0,0), 1->(0,1), 2->(1,0), 3->(1,1)}. + * @return the IJ-index where {@code 0->(0,0), 1->(0,1), 2->(1,0), 3->(1,1)}. * @throws IllegalArgumentException if either parameter is out of bounds. */ public static int posToIJ(int orientation, int position) { @@ -125,7 +126,7 @@ public static int posToIJ(int orientation, int position) { * * @param orientation the subcell orientation, in the range [0,3]. * @param ijIndex the subcell index where - * {@code 0->(0,0), 1->(0,1), 2->(1,0), 3->(1,1)}. + * {@code 0->(0,0), 1->(0,1), 2->(1,0), 3->(1,1)}. * @return the position of the subcell in the Hilbert traversal, in the range * [0,3]. * @throws IllegalArgumentException if either parameter is out of bounds. @@ -148,6 +149,8 @@ public static class Metric { /** * Defines a cell metric of the given dimension (1 == length, 2 == area). + * @param dim dim + * @param deriv deriv */ public Metric(int dim, double deriv) { this.deriv = deriv; @@ -157,18 +160,21 @@ public Metric(int dim, double deriv) { /** * The "deriv" value of a metric is a derivative, and must be multiplied by * a length or area in (s,t)-space to get a useful value. + * @return deriv */ public double deriv() { return deriv; } - /** Return the value of a metric for cells at the given level. */ + /** + * @param level value + * @return the value of a metric for cells at the given level. */ public double getValue(int level) { return StrictMath.scalb(deriv, dim * (1 - level)); } /** - * Return the level at which the metric has approximately the given value. + * @return the level at which the metric has approximately the given value. * For example, S2::kAvgEdge.GetClosestLevel(0.1) returns the level at which * the average cell edge length is approximately 0.1. The return value is * always a valid level. @@ -178,7 +184,8 @@ public int getClosestLevel(double value) { } /** - * Return the minimum level such that the metric is at most the given value, + * @param value value + * @return the minimum level such that the metric is at most the given value, * or S2CellId::kMaxLevel if there is no such level. For example, * S2::kMaxDiag.GetMinLevel(0.1) returns the minimum level such that all * cell diagonal lengths are 0.1 or smaller. The return value is always a @@ -200,7 +207,8 @@ public int getMinLevel(double value) { } /** - * Return the maximum level such that the metric is at least the given + * @param value value + * @return the maximum level such that the metric is at least the given * value, or zero if there is no such level. For example, * S2.kMinWidth.GetMaxLevel(0.1) returns the maximum level such that all * cells have a minimum width of 0.1 or larger. The return value is always a @@ -224,7 +232,7 @@ public int getMaxLevel(double value) { } /** - * Return a unique "origin" on the sphere for operations that need a fixed + * @return a unique "origin" on the sphere for operations that need a fixed * reference point. It should *not* be a point that is commonly used in edge * tests in order to avoid triggering code to handle degenerate cases. (This * rules out the north and south poles.) @@ -398,6 +406,9 @@ public static double girardArea(S2Point a, S2Point b, S2Point c) { /** * Like Area(), but returns a positive value for counterclockwise triangles * and a negative value otherwise. + * @param a First point. + * @param b Second point. + * @param c Third point. */ public static double signedArea(S2Point a, S2Point b, S2Point c) { return area(a, b, c) * robustCCW(a, b, c); @@ -672,6 +683,12 @@ private static int expensiveCCW(S2Point a, S2Point b, S2Point c) { } + /** + * + * @param a a + * @param b b + * @return >0 if the edge ab is CCW around the origin. + */ public static int planarCCW(R2Vector a, R2Vector b) { // Return +1 if the edge AB is CCW around the origin, etc. double sab = (a.dotProd(b) > 0) ? -1 : 1; @@ -693,6 +710,13 @@ public static int planarCCW(R2Vector a, R2Vector b) { return 0; } + /** + * + * @param a a + * @param b b + * @param c c + * @return 1, 0, -1 + */ public static int planarOrderedCCW(R2Vector a, R2Vector b, R2Vector c) { int sum = 0; sum += planarCCW(a, b); @@ -710,16 +734,22 @@ public static int planarOrderedCCW(R2Vector a, R2Vector b, R2Vector c) { /** * Return true if the edges OA, OB, and OC are encountered in that order while * sweeping CCW around the point O. You can think of this as testing whether - * A <= B <= C with respect to a continuous CCW ordering around O. + *A <= B <= C with respect to a continuous CCW ordering around O. * * Properties: *

    - *
  1. If orderedCCW(a,b,c,o) && orderedCCW(b,a,c,o), then a == b
  2. - *
  3. If orderedCCW(a,b,c,o) && orderedCCW(a,c,b,o), then b == c
  4. - *
  5. If orderedCCW(a,b,c,o) && orderedCCW(c,b,a,o), then a == b == c
  6. + *
  7. If orderedCCW(a,b,c,o) && orderedCCW(b,a,c,o), then a == b
  8. + *
  9. If orderedCCW(a,b,c,o) && orderedCCW(a,c,b,o), then b == c
  10. + *
  11. If orderedCCW(a,b,c,o) && orderedCCW(c,b,a,o), then a == b == c
  12. *
  13. If a == b or b == c, then orderedCCW(a,b,c,o) is true
  14. *
  15. Otherwise if a == c, then orderedCCW(a,b,c,o) is false
  16. *
+ * + * @param a a + * @param b b + * @param c c + * @param o o + * @return true if RobustCCW sum is >=2 */ public static boolean orderedCCW(S2Point a, S2Point b, S2Point c, S2Point o) { // The last inequality below is ">" rather than ">=" so that we return true @@ -747,6 +777,11 @@ public static boolean orderedCCW(S2Point a, S2Point b, S2Point c, S2Point o) { * The angle is undefined if A or C is diametrically opposite from B, and * becomes numerically unstable as the length of edge AB or BC approaches 180 * degrees. + * + * @param a First point in the triangle. + * @param b Second point in the triangle. + * @param c Third point in the triangle. + * @return angle of the points */ public static double angle(S2Point a, S2Point b, S2Point c) { return S2Point.crossProd(a, b).angle(S2Point.crossProd(c, b)); @@ -759,9 +794,9 @@ public static double angle(S2Point a, S2Point b, S2Point c) { * turns at vertex B (positive = left, negative = right). Ensures that * TurnAngle(a,b,c) == -TurnAngle(c,b,a) for all a,b,c. * - * @param a - * @param b - * @param c + * @param a a + * @param b b + * @param c c * @return the exterior angle at the vertex B in the triangle ABC */ public static double turnAngle(S2Point a, S2Point b, S2Point c) { @@ -774,19 +809,43 @@ public static double turnAngle(S2Point a, S2Point b, S2Point c) { /** * Return true if two points are within the given distance of each other * (mainly useful for testing). + * @param a a + * @param b b + * @param maxError maxError + * @return true if angle of AB is <= maxError. */ public static boolean approxEquals(S2Point a, S2Point b, double maxError) { return a.angle(b) <= maxError; } + /** + * + * @param a a + * @param b b + * @return boolean + */ public static boolean approxEquals(S2Point a, S2Point b) { return approxEquals(a, b, 1e-15); } + /** + * + * @param a a + * @param b b + * @param maxError maxError + * @return true if the difference of AB <= maxError + */ public static boolean approxEquals(double a, double b, double maxError) { return Math.abs(a - b) <= maxError; } + + /** + * + * @param a a + * @param b b + * @return true if the difference of AB <= {@code 1e-15} + */ public static boolean approxEquals(double a, double b) { return approxEquals(a, b, 1e-15); } diff --git a/src/main/java/com/pokegoapi/google/common/geometry/S2Cap.java b/src/main/java/com/pokegoapi/google/common/geometry/S2Cap.java index 094f77ac..f1c95ae9 100644 --- a/src/main/java/com/pokegoapi/google/common/geometry/S2Cap.java +++ b/src/main/java/com/pokegoapi/google/common/geometry/S2Cap.java @@ -48,6 +48,11 @@ private S2Cap() { height = 0; } + /** + * private constructor + * @param axis axis + * @param height height + */ private S2Cap(S2Point axis, double height) { this.axis = axis; this.height = height; diff --git a/src/main/java/com/pokegoapi/google/common/geometry/S2CellId.java b/src/main/java/com/pokegoapi/google/common/geometry/S2CellId.java index a4f5f9e6..d6ae2b8a 100644 --- a/src/main/java/com/pokegoapi/google/common/geometry/S2CellId.java +++ b/src/main/java/com/pokegoapi/google/common/geometry/S2CellId.java @@ -579,7 +579,7 @@ public void getEdgeNeighbors(S2CellId neighbors[]) { * closest vertex may only have three neighbors if it is one of the 8 cube * vertices. * - * Requires: level < this.evel(), so that we can determine which vertex is + * Requires: level < this.evel(), so that we can determine which vertex is * closest (in particular, level == MAX_LEVEL is not allowed). */ public void getVertexNeighbors(int level, List output) { @@ -633,7 +633,7 @@ public void getVertexNeighbors(int level, List output) { * not. In particular, two cells that intersect at a single point are * neighbors. * - * Requires: nbr_level >= this->level(). Note that for cells adjacent to a + * Requires: nbr_level >= this->level(). Note that for cells adjacent to a * face vertex, the same neighbor may be appended more than once. */ public void getAllNeighbors(int nbrLevel, List output) { @@ -808,8 +808,8 @@ public long lowestOnBit() { /** * Return the lowest-numbered bit that is on for this cell id, which is equal - * to (uint64(1) << (2 * (MAX_LEVEL - level))). So for example, a.lsb() <= - * b.lsb() if and only if a.level() >= b.level(), but the first test is more + * to (uint64(1) << (2 * (MAX_LEVEL - level))). So for example, a.lsb() <= + * b.lsb() if and only if a.level() >= b.level(), but the first test is more * efficient. */ public static long lowestOnBitForLevel(int level) { @@ -891,14 +891,14 @@ public boolean equals(Object that) { } /** - * Returns true if x1 < x2, when both values are treated as unsigned. + * @return true if x1 < x2, when both values are treated as unsigned. */ public static boolean unsignedLongLessThan(long x1, long x2) { return (x1 + Long.MIN_VALUE) < (x2 + Long.MIN_VALUE); } /** - * Returns true if x1 > x2, when both values are treated as unsigned. + * @return true if x1 > x2, when both values are treated as unsigned. */ public static boolean unsignedLongGreaterThan(long x1, long x2) { return (x1 + Long.MIN_VALUE) > (x2 + Long.MIN_VALUE); diff --git a/src/main/java/com/pokegoapi/google/common/geometry/S2EdgeIndex.java b/src/main/java/com/pokegoapi/google/common/geometry/S2EdgeIndex.java index 81682d4c..8afbda1f 100644 --- a/src/main/java/com/pokegoapi/google/common/geometry/S2EdgeIndex.java +++ b/src/main/java/com/pokegoapi/google/common/geometry/S2EdgeIndex.java @@ -16,13 +16,7 @@ package com.pokegoapi.google.common.geometry; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; public abstract strictfp class S2EdgeIndex { /** @@ -192,7 +186,7 @@ protected final void incrementQueryCount() { * * When doing one additional query, the differential cost is m * testCost - * costFind(m) With the numbers above, it is better to use the quad tree (if - * we have it) if m >= 100. + * we have it) if m >= 100. * * If m = 100, 30 queries will give m*n*testCost = m * costInsert = 100ms, * while the marginal cost to find is 3ms. Thus, this is a reasonable thing to @@ -529,7 +523,7 @@ private void getEdgesInChildrenCells(S2Point a, S2Point b, List cover, } } - /* + /** * An iterator on data edges that may cross a query edge (a,b). Create the * iterator, call getCandidates(), then hasNext()/next() repeatedly. * diff --git a/src/main/java/com/pokegoapi/google/common/geometry/S2EdgeUtil.java b/src/main/java/com/pokegoapi/google/common/geometry/S2EdgeUtil.java index 2b03f2a0..14e99562 100644 --- a/src/main/java/com/pokegoapi/google/common/geometry/S2EdgeUtil.java +++ b/src/main/java/com/pokegoapi/google/common/geometry/S2EdgeUtil.java @@ -526,7 +526,7 @@ public static boolean simpleCrossing(S2Point a, S2Point b, S2Point c, S2Point d) * (1) robustCrossing(b,a,c,d) == robustCrossing(a,b,c,d) (2) * robustCrossing(c,d,a,b) == robustCrossing(a,b,c,d) (3) * robustCrossing(a,b,c,d) == 0 if a==c, a==d, b==c, b==d (3) - * robustCrossing(a,b,c,d) <= 0 if a==b or c==d + * robustCrossing(a,b,c,d) <= 0 if a==b or c==d * * Note that if you want to check an edge against a *chain* of other edges, * it is much more efficient to use an EdgeCrosser (above). diff --git a/src/main/java/com/pokegoapi/google/common/geometry/S2LatLngRect.java b/src/main/java/com/pokegoapi/google/common/geometry/S2LatLngRect.java index 81793797..55b25471 100644 --- a/src/main/java/com/pokegoapi/google/common/geometry/S2LatLngRect.java +++ b/src/main/java/com/pokegoapi/google/common/geometry/S2LatLngRect.java @@ -29,7 +29,7 @@ public strictfp class S2LatLngRect implements S2Region { /** * Construct a rectangle from minimum and maximum latitudes and longitudes. If - * lo.lng() > hi.lng(), the rectangle spans the 180 degree longitude line. + * lo.lng() > hi.lng(), the rectangle spans the 180 degree longitude line. */ public S2LatLngRect(final S2LatLng lo, final S2LatLng hi) { lat = new R1Interval(lo.lat().radians(), hi.lat().radians()); @@ -70,7 +70,7 @@ public static S1Interval fullLng() { * Construct a rectangle from a center point (in lat-lng space) and size in * each dimension. If size.lng() is greater than 360 degrees it is clamped, * and latitudes greater than +/- 90 degrees are also clamped. So for example, - * FromCenterSize((80,170),(20,20)) -> (lo=(60,150),hi=(90,-170)). + * FromCenterSize((80,170),(20,20)) -> (lo=(60,150),hi=(90,-170)). */ public static S2LatLngRect fromCenterSize(S2LatLng center, S2LatLng size) { return fromPoint(center).expanded(size.mul(0.5)); @@ -186,7 +186,7 @@ public boolean isFull() { } /** - * Return true if lng_.lo() > lng_.hi(), i.e. the rectangle crosses the 180 + * Return true if lng_.lo() > lng_.hi(), i.e. the rectangle crosses the 180 * degree latitude line. */ public boolean isInverted() { diff --git a/src/main/java/com/pokegoapi/main/AsyncServerRequest.java b/src/main/java/com/pokegoapi/main/AsyncServerRequest.java new file mode 100644 index 00000000..8ccd5949 --- /dev/null +++ b/src/main/java/com/pokegoapi/main/AsyncServerRequest.java @@ -0,0 +1,58 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.main; + +import POGOProtos.Networking.Requests.RequestOuterClass; +import POGOProtos.Networking.Requests.RequestTypeOuterClass; +import com.google.protobuf.GeneratedMessage; +import lombok.Getter; + +/** + * The type Server request. + */ +public class AsyncServerRequest { + @Getter + private final long id = System.nanoTime(); + @Getter + private final RequestTypeOuterClass.RequestType type; + @Getter + private final RequestOuterClass.Request request; + + /** + * Instantiates a new Server request. + * + * @param type the type + * @param req the req + */ + public AsyncServerRequest(RequestTypeOuterClass.RequestType type, GeneratedMessage req) { + RequestOuterClass.Request.Builder reqBuilder = RequestOuterClass.Request.newBuilder(); + reqBuilder.setRequestMessage(req.toByteString()); + reqBuilder.setRequestType(type); + this.type = type; + this.request = reqBuilder.build(); + } + + /** + * Instantiates a new Server request. + * + * @param type the type + * @param req the req + */ + AsyncServerRequest(RequestTypeOuterClass.RequestType type, RequestOuterClass.Request req) { + this.type = type; + this.request = req; + } +} diff --git a/src/main/java/com/pokegoapi/main/RequestHandler.java b/src/main/java/com/pokegoapi/main/RequestHandler.java index 53bbd98b..3ecedb57 100644 --- a/src/main/java/com/pokegoapi/main/RequestHandler.java +++ b/src/main/java/com/pokegoapi/main/RequestHandler.java @@ -19,9 +19,12 @@ import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass; import POGOProtos.Networking.Envelopes.ResponseEnvelopeOuterClass; import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.exceptions.AsyncPokemonGoException; import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.util.FutureWrapper; import com.pokegoapi.util.Log; import okhttp3.OkHttpClient; import okhttp3.RequestBody; @@ -31,45 +34,107 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; import java.util.List; - -public class RequestHandler { +import java.util.Map; +import java.util.Random; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class RequestHandler implements Runnable { private static final String TAG = RequestHandler.class.getSimpleName(); private final PokemonGo api; - private RequestEnvelopeOuterClass.RequestEnvelope.Builder builder; - private boolean hasRequests; - private List serverRequests; private String apiEndpoint; private OkHttpClient client; + private Long requestId = new Random().nextLong(); - private AuthTicketOuterClass.AuthTicket lastAuth; + private final Thread asyncHttpThread; + private final BlockingQueue workQueue = new LinkedBlockingQueue<>(); + private final Map resultMap = new HashMap<>(); /** * Instantiates a new Request handler. * * @param api the api * @param client the client + * @throws LoginFailedException When login fails + * @throws RemoteServerException If request errors occur */ public RequestHandler(PokemonGo api, OkHttpClient client) throws LoginFailedException, RemoteServerException { this.api = api; this.client = client; apiEndpoint = ApiSettings.API_ENDPOINT; - serverRequests = new ArrayList<>(); - /* TODO: somehow fix it so people using the deprecated functions will still work, - while not calling this deprecated stuff ourselves */ - resetBuilder(); + asyncHttpThread = new Thread(this, "Async HTTP Thread"); + asyncHttpThread.setDaemon(true); + asyncHttpThread.start(); } /** - * Request. + * Make an async server request. The answer will be provided in the future * - * @param requestIn the request in + * @param serverRequest Request to make + * @return ByteString response to be processed in the future */ - @Deprecated - public void request(ServerRequest requestIn) { - hasRequests = true; - serverRequests.add(requestIn); - builder.addRequests(requestIn.getRequest()); + public Future sendAsyncServerRequests(final AsyncServerRequest serverRequest) { + workQueue.offer(serverRequest); + return new Future() { + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return false; + } + + @Override + public boolean isCancelled() { + return false; + } + + @Override + public boolean isDone() { + return resultMap.containsKey(serverRequest.getId()); + } + + @Override + public ByteString get() throws InterruptedException, ExecutionException { + ResultOrException resultOrException = getResult(1, TimeUnit.MINUTES); + while (resultOrException == null) { + resultOrException = getResult(1, TimeUnit.MINUTES); + } + if (resultOrException.getException() != null) { + throw new ExecutionException(resultOrException.getException()); + } + return resultOrException.getResult(); + } + + @Override + public ByteString get(long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException { + ResultOrException resultOrException = getResult(timeout, unit); + if (resultOrException == null) { + throw new TimeoutException("No result found"); + } + if (resultOrException.getException() != null) { + throw new ExecutionException(resultOrException.getException()); + } + return resultOrException.getResult(); + + } + + private ResultOrException getResult(long timeouut, TimeUnit timeUnit) throws InterruptedException { + long wait = System.currentTimeMillis() + timeUnit.toMillis(timeouut); + while (!isDone()) { + Thread.sleep(10); + if (wait < System.currentTimeMillis()) { + return null; + } + } + return resultMap.remove(serverRequest.getId()); + } + }; } /** @@ -80,11 +145,33 @@ public void request(ServerRequest requestIn) { * @throws LoginFailedException the login failed exception */ public void sendServerRequests(ServerRequest... serverRequests) throws RemoteServerException, LoginFailedException { + List> futures = new ArrayList<>(serverRequests.length); + for (ServerRequest request : serverRequests) { + AsyncServerRequest asyncServerRequest = new AsyncServerRequest(request.getType(), request.getRequest()); + futures.add(sendAsyncServerRequests(asyncServerRequest)); + } + for (int i = 0; i != serverRequests.length; i++) { + serverRequests[i].handleData(FutureWrapper.toBlocking(futures.get(i))); + } + } + + /** + * Sends multiple ServerRequests in a thread safe manner. + * + * @param serverRequests list of ServerRequests to be sent + * @throws RemoteServerException the remote server exception + * @throws LoginFailedException the login failed exception + */ + private AuthTicketOuterClass.AuthTicket internalSendServerRequests(AuthTicketOuterClass.AuthTicket authTicket, + ServerRequest... serverRequests) + throws RemoteServerException, LoginFailedException { + AuthTicketOuterClass.AuthTicket newAuthTicket = authTicket; if (serverRequests.length == 0) { - return; + return authTicket; } - RequestEnvelopeOuterClass.RequestEnvelope.Builder builder = RequestEnvelopeOuterClass.RequestEnvelope.newBuilder(); - resetBuilder(builder); + RequestEnvelopeOuterClass.RequestEnvelope.Builder builder = RequestEnvelopeOuterClass.RequestEnvelope + .newBuilder(); + resetBuilder(builder, authTicket); for (ServerRequest serverRequest : serverRequests) { builder.addRequests(serverRequest.getRequest()); @@ -122,21 +209,20 @@ public void sendServerRequests(ServerRequest... serverRequests) throws RemoteSer } if (responseEnvelop.hasAuthTicket()) { - lastAuth = responseEnvelop.getAuthTicket(); + newAuthTicket = responseEnvelop.getAuthTicket(); } if (responseEnvelop.getStatusCode() == 102) { - throw new LoginFailedException(String.format("Error %s in API Url %s", + throw new LoginFailedException(String.format("Invalud Auth status code recieved, token not refreshed?", responseEnvelop.getApiUrl(), responseEnvelop.getError())); } else if (responseEnvelop.getStatusCode() == 53) { // 53 means that the api_endpoint was not correctly set, should be at this point, though, so redo the request - sendServerRequests(serverRequests); - return; + return internalSendServerRequests(newAuthTicket, serverRequests); } /** * map each reply to the numeric response, - * ie first response = first request and send back to the requests to handle. + * ie first response = first request and send back to the requests to toBlocking. * */ int count = 0; for (ByteString payload : responseEnvelop.getReturnsList()) { @@ -155,99 +241,18 @@ public void sendServerRequests(ServerRequest... serverRequests) throws RemoteSer // catch it, so the auto-close of resources triggers, but don't wrap it in yet another RemoteServer Exception throw e; } + return newAuthTicket; } - /** - * Send server requests. - * - * @throws RemoteServerException the remote server exception - * @throws LoginFailedException the login failed exception - */ - @Deprecated - public void sendServerRequests() throws RemoteServerException, LoginFailedException { - setLatitude(api.getLatitude()); - setLongitude(api.getLongitude()); - setAltitude(api.getAltitude()); - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - RequestEnvelopeOuterClass.RequestEnvelope request = builder.build(); - try { - request.writeTo(stream); - } catch (IOException e) { - Log.wtf(TAG, "Failed to write request to bytearray output stream. This should never happen", e); - } - - RequestBody body = RequestBody.create(null, stream.toByteArray()); - okhttp3.Request httpRequest = new okhttp3.Request.Builder() - .url(apiEndpoint) - .post(body) - .build(); - Response response; - try { - response = client.newCall(httpRequest).execute(); - } catch (IOException e) { - throw new RemoteServerException(e); - } - - if (response.code() != 200) { - throw new RemoteServerException("Got a unexpected http code : " + response.code()); - } - - ResponseEnvelopeOuterClass.ResponseEnvelope responseEnvelop = null; - try (InputStream content = response.body().byteStream()) { - responseEnvelop = ResponseEnvelopeOuterClass.ResponseEnvelope.parseFrom(content); - } catch (IOException e) { - // retrieved garbage from the server - throw new RemoteServerException("Received malformed response : " + e); - } - - if (responseEnvelop.getApiUrl() != null && responseEnvelop.getApiUrl().length() > 0) { - apiEndpoint = "https://" + responseEnvelop.getApiUrl() + "/rpc"; - } - - if (responseEnvelop.hasAuthTicket()) { - lastAuth = responseEnvelop.getAuthTicket(); - } - - if (responseEnvelop.getStatusCode() == 102) { - throw new LoginFailedException(); - } else if (responseEnvelop.getStatusCode() == 53) { - // 53 means that the apiEndpoint was not correctly set, should be at this point, though, so redo the request - sendServerRequests(); - return; - } - - // map each reply to the numeric response, - // ie first response = first request and send back to the requests to handle. - int count = 0; - for (ByteString payload : responseEnvelop.getReturnsList()) { - ServerRequest serverReq = serverRequests.get(count); - // TODO: Probably all other payloads are garbage as well in this case, so might as well throw an exception - if (payload != null) { - serverReq.handleData(payload); - } - count++; - } - - resetBuilder(); - } - - @Deprecated - private void resetBuilder() throws LoginFailedException, RemoteServerException { - builder = RequestEnvelopeOuterClass.RequestEnvelope.newBuilder(); - resetBuilder(builder); - hasRequests = false; - serverRequests.clear(); - } - - private void resetBuilder(RequestEnvelopeOuterClass.RequestEnvelope.Builder builder) + private void resetBuilder(RequestEnvelopeOuterClass.RequestEnvelope.Builder builder, + AuthTicketOuterClass.AuthTicket authTicket) throws LoginFailedException, RemoteServerException { builder.setStatusCode(2); - builder.setRequestId(8145806132888207460L); - if (lastAuth != null - && lastAuth.getExpireTimestampMs() > 0 - && lastAuth.getExpireTimestampMs() > System.currentTimeMillis()) { - builder.setAuthTicket(lastAuth); + builder.setRequestId(getRequestId()); + if (authTicket != null + && authTicket.getExpireTimestampMs() > 0 + && authTicket.getExpireTimestampMs() > api.currentTimeMillis()) { + builder.setAuthTicket(authTicket); } else { Log.d(TAG, "Authenticated with static token"); builder.setAuthInfo(api.getAuthInfo()); @@ -258,29 +263,46 @@ private void resetBuilder(RequestEnvelopeOuterClass.RequestEnvelope.Builder buil builder.setAltitude(api.getAltitude()); } - - /** - * Build request envelope outer class . request envelope. - * - * @return the request envelope outer class . request envelope - */ - public RequestEnvelopeOuterClass.RequestEnvelope build() { - if (!hasRequests) { - throw new IllegalStateException("Attempting to send request envelop with no requests"); - } - return builder.build(); - } - - public void setLatitude(double latitude) { - builder.setLatitude(latitude); + private Long getRequestId() { + return ++requestId; } - public void setLongitude(double longitude) { - builder.setLongitude(longitude); - } - - public void setAltitude(double altitude) { - builder.setAltitude(altitude); + @Override + public void run() { + List requests = new LinkedList<>(); + AuthTicketOuterClass.AuthTicket authTicket = null; + while (true) { + try { + Thread.sleep(350); + } catch (InterruptedException e) { + throw new AsyncPokemonGoException("System shutdown", e); + } + if (workQueue.isEmpty()) { + continue; + } + workQueue.drainTo(requests); + ServerRequest[] serverRequests = new ServerRequest[requests.size()]; + for (int i = 0; i != requests.size(); i++) { + serverRequests[i] = new ServerRequest(requests.get(i).getType(), requests.get(i).getRequest()); + } + try { + authTicket = internalSendServerRequests(authTicket, serverRequests); + for (int i = 0; i != requests.size(); i++) { + try { + resultMap.put(requests.get(i).getId(), ResultOrException.getResult(serverRequests[i].getData())); + } catch (InvalidProtocolBufferException e) { + resultMap.put(requests.get(i).getId(), ResultOrException.getError(e)); + } + } + continue; + } catch (RemoteServerException | LoginFailedException e) { + for (AsyncServerRequest request : requests) { + resultMap.put(request.getId(), ResultOrException.getError(e)); + } + continue; + } finally { + requests.clear(); + } + } } - } diff --git a/src/main/java/com/pokegoapi/main/ResultOrException.java b/src/main/java/com/pokegoapi/main/ResultOrException.java new file mode 100644 index 00000000..416c3fcc --- /dev/null +++ b/src/main/java/com/pokegoapi/main/ResultOrException.java @@ -0,0 +1,39 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.main; + +import com.google.protobuf.ByteString; +import lombok.Getter; + +public class ResultOrException { + @Getter + private final ByteString result; + @Getter + private final Exception exception; + + private ResultOrException(ByteString result, Exception exception) { + this.result = result; + this.exception = exception; + } + + public static ResultOrException getError(Exception exception) { + return new ResultOrException(null, exception); + } + + public static ResultOrException getResult(ByteString result) { + return new ResultOrException(result, null); + } +} diff --git a/src/main/java/com/pokegoapi/main/ServerRequest.java b/src/main/java/com/pokegoapi/main/ServerRequest.java index 3cc07750..06daf630 100644 --- a/src/main/java/com/pokegoapi/main/ServerRequest.java +++ b/src/main/java/com/pokegoapi/main/ServerRequest.java @@ -29,6 +29,7 @@ public class ServerRequest { @Getter RequestOuterClass.Request request; + @Getter private RequestTypeOuterClass.RequestType type; private ByteString data; @@ -46,6 +47,17 @@ public ServerRequest(RequestTypeOuterClass.RequestType type, GeneratedMessage re this.type = type; } + /** + * Instantiates a new Server request. + * + * @param type the type + * @param request the req + */ + ServerRequest(RequestTypeOuterClass.RequestType type, RequestOuterClass.Request request) { + this.request = request; + this.type = type; + } + /** * Handle data. * diff --git a/src/main/java/com/pokegoapi/util/BaseLogger.java b/src/main/java/com/pokegoapi/util/BaseLogger.java index dcfa3559..e7f02abe 100644 --- a/src/main/java/com/pokegoapi/util/BaseLogger.java +++ b/src/main/java/com/pokegoapi/util/BaseLogger.java @@ -15,14 +15,14 @@ package com.pokegoapi.util; -import static com.pokegoapi.util.Log.Level.ASSERT; +import com.pokegoapi.util.Log.Level; + import static com.pokegoapi.util.Log.Level.DEBUG; -import static com.pokegoapi.util.Log.Level.ERROR; import static com.pokegoapi.util.Log.Level.INFO; import static com.pokegoapi.util.Log.Level.VERBOSE; import static com.pokegoapi.util.Log.Level.WARN; - -import com.pokegoapi.util.Log.Level; +import static com.pokegoapi.util.Log.Level.ERROR; +import static com.pokegoapi.util.Log.Level.ASSERT; /** diff --git a/src/main/java/com/pokegoapi/util/FutureWrapper.java b/src/main/java/com/pokegoapi/util/FutureWrapper.java new file mode 100644 index 00000000..043406b3 --- /dev/null +++ b/src/main/java/com/pokegoapi/util/FutureWrapper.java @@ -0,0 +1,153 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.util; + +import com.google.protobuf.InvalidProtocolBufferException; +import com.pokegoapi.exceptions.AsyncPokemonGoException; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public abstract class FutureWrapper implements PokemonFuture { + + protected final Future result; + + public FutureWrapper(Future result) { + this.result = result; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return result.cancel(mayInterruptIfRunning); + } + + @Override + public boolean isCancelled() { + return result.isCancelled(); + } + + @Override + public boolean isDone() { + return result.isDone(); + } + + @Override + public R get() throws InterruptedException, ExecutionException { + R result = getResult(1, TimeUnit.MINUTES); + while (result == null) { + result = getResult(1, TimeUnit.MINUTES); + } + return result; + } + + @Override + public R get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + R result = getResult(timeout, unit); + if (result == null) { + throw new TimeoutException("No result found"); + } + return result; + } + + protected R getResult(long timeouut, TimeUnit timeUnit) throws InterruptedException, ExecutionException { + long wait = System.currentTimeMillis() + timeUnit.toMillis(timeouut); + while (!isDone()) { + Thread.sleep(10); + if (wait < System.currentTimeMillis()) { + return null; + } + } + try { + return handle(result.get()); + } catch (RemoteServerException | LoginFailedException e) { + throw new ExecutionException(e); + } + } + + protected abstract R handle(T result) throws RemoteServerException, LoginFailedException; + + /** + * Convert a future to its result + * + * @return The result or an unwrapped exception + * @throws RemoteServerException the remote server exception + * @throws LoginFailedException the login failed exception + */ + public R toBlocking() throws LoginFailedException, RemoteServerException { + return FutureWrapper.toBlocking(this); + } + + /** + * Convert a future to its result + * + * @param future The future + * @param Result type + * @return The result or an unwrapped exception + * @throws RemoteServerException the remote server exception + * @throws LoginFailedException the login failed exception + */ + public static N toBlocking(Future future) throws LoginFailedException, RemoteServerException { + try { + return future.get(); + } catch (InterruptedException e) { + throw new AsyncPokemonGoException("Shutdown received", e); + } catch (ExecutionException e) { + if (e.getCause() instanceof LoginFailedException) { + throw (LoginFailedException) e.getCause(); + } + if (e.getCause() instanceof RemoteServerException) { + throw (RemoteServerException) e.getCause(); + } + if (e.getCause() instanceof InvalidProtocolBufferException) { + throw new RemoteServerException(e.getCause().getMessage(), e.getCause()); + } + throw new AsyncPokemonGoException("Unknown exception occurred. ", e); + } + } + + + public static FutureWrapper just(R result) { + return new Just<>(result); + } + + private static class Just extends FutureWrapper { + private final R result; + + Just(R result) { + super(null); + this.result = result; + } + + @Override + protected R handle(T ignore) throws RemoteServerException { + return this.result; + } + + @Override + public boolean isDone() { + return true; + } + + @Override + protected R getResult(long timeouut, TimeUnit timeUnit) throws InterruptedException, ExecutionException { + return result; + } + } +} diff --git a/src/main/java/com/pokegoapi/util/Log.java b/src/main/java/com/pokegoapi/util/Log.java index da64d88e..39220d70 100644 --- a/src/main/java/com/pokegoapi/util/Log.java +++ b/src/main/java/com/pokegoapi/util/Log.java @@ -21,10 +21,11 @@ /** * Created by Will on 7/20/16. */ -@SuppressWarnings("checkstyle:methodname") +@SuppressWarnings({ "checkstyle:methodname", "checkstyle:javadocmethod" }) public class Log { private static Logger logger; + private static Level level = Level.VERBOSE; private static Logger getInstance() { if (logger == null) { @@ -33,76 +34,117 @@ private static Logger getInstance() { return logger; } - //Do not call this while logging from a different thread... - //That's asking for trouble... + // Do not call this while logging from a different thread... + // That's asking for trouble... public static void setInstance(Logger logger) { Log.logger = logger; } + /** + * Sets the level of the Logger. For example, if the level is Error, all + * ERROR and ASSERT messages will be logged, but nothing else. + * + * @param level + * the level to log at + */ + public static void setLevel(Level level) { + Log.level = level; + } + public static void v(String tag, String msg) { - getInstance().v(tag, msg); + if (level.level <= Level.VERBOSE.level) { + getInstance().v(tag, msg); + } } public static void v(String tag, String msg, Throwable tr) { - getInstance().v(tag, msg, tr); + if (Log.level.level <= Level.VERBOSE.level) { + getInstance().v(tag, msg, tr); + } } public static void d(String tag, String msg) { - getInstance().d(tag, msg); + if (Log.level.level <= Level.DEBUG.level) { + getInstance().d(tag, msg); + } } public static void d(String tag, String msg, Throwable tr) { - getInstance().d(tag, msg, tr); + if (Log.level.level <= Level.DEBUG.level) { + getInstance().d(tag, msg, tr); + } } public static void i(String tag, String msg) { - getInstance().i(tag, msg); + if (Log.level.level <= Level.INFO.level) { + getInstance().i(tag, msg); + } } public static void i(String tag, String msg, Throwable tr) { - getInstance().i(tag, msg, tr); + if (Log.level.level <= Level.INFO.level) { + getInstance().i(tag, msg, tr); + } } public static void w(String tag, String msg) { - getInstance().w(tag, msg); + if (Log.level.level <= Level.WARN.level) { + getInstance().w(tag, msg); + } } public static void w(String tag, String msg, Throwable tr) { - getInstance().w(tag, msg, tr); + if (Log.level.level <= Level.WARN.level) { + getInstance().w(tag, msg, tr); + } } public static void w(String tag, Throwable tr) { - getInstance().w(tag, tr); + if (Log.level.level <= Level.WARN.level) { + getInstance().w(tag, tr); + } } public static void e(String tag, String msg) { - getInstance().e(tag, msg); + if (Log.level.level <= Level.ERROR.level) { + getInstance().e(tag, msg); + } } public static void e(String tag, String msg, Throwable tr) { - getInstance().e(tag, msg, tr); + if (Log.level.level <= Level.ERROR.level) { + getInstance().e(tag, msg, tr); + } } public static void wtf(String tag, String msg) { - getInstance().wtf(tag, msg); + if (Log.level.level <= Level.ASSERT.level) { + getInstance().wtf(tag, msg); + } } public static void wtf(String tag, Throwable tr) { - getInstance().wtf(tag, tr); + if (Log.level.level <= Level.ASSERT.level) { + getInstance().wtf(tag, tr); + } } public static void wtf(String tag, String msg, Throwable tr) { - getInstance().wtf(tag, msg, tr); + if (Log.level.level <= Level.ASSERT.level) { + getInstance().wtf(tag, msg, tr); + } } public enum Level { + ALL(Integer.MIN_VALUE), VERBOSE(2), DEBUG(3), INFO(4), WARN(5), ERROR(6), - ASSERT(7); + ASSERT(7), + NONE(Integer.MAX_VALUE); private int level; @@ -125,7 +167,7 @@ public void log(Level level, String tag, String msg, Throwable tr) { PrintWriter printWriter = new PrintWriter(sw); tr.printStackTrace(printWriter); body += "\n" + sw.toString(); - //No need to close. No resources taken up + // No need to close. No resources taken up } String result = String.format("%s/%s: %s", prefix, tag, body); System.out.println(result); diff --git a/src/main/java/com/pokegoapi/util/MapPoint.java b/src/main/java/com/pokegoapi/util/MapPoint.java new file mode 100644 index 00000000..d1128a25 --- /dev/null +++ b/src/main/java/com/pokegoapi/util/MapPoint.java @@ -0,0 +1,36 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.util; + +/** + * @author Olaf Braun - Software Development + * @version 1.0 + */ +public interface MapPoint { + /** + * Gets latitude. + * + * @return the latitude + */ + double getLatitude(); + + /** + * Gets longitude. + * + * @return the longitude + */ + double getLongitude(); +} diff --git a/src/main/java/com/pokegoapi/util/MapUtil.java b/src/main/java/com/pokegoapi/util/MapUtil.java new file mode 100644 index 00000000..20384a09 --- /dev/null +++ b/src/main/java/com/pokegoapi/util/MapUtil.java @@ -0,0 +1,100 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.util; + +import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.api.map.Point; + +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.TreeMap; + +/** + * @author Olaf Braun - Software Development + * @version 1.0 + */ +public class MapUtil { + /** + * Random step to a coordinate object + * + * @param point the coordinate + * @return the coordinate + */ + public static Point randomStep(Point point) { + point.setLongitude(point.getLongitude() + randomStep()); + point.setLatitude(point.getLatitude() + randomStep()); + + return point; + } + + /** + * Random step double. + * + * @return the double + */ + public static double randomStep() { + Random random = new Random(); + return random.nextDouble() / 100000.0; + } + + /** + * Dist between coordinates + * + * @param start the start coordinate + * @param end the end coordinate + * @return the double + */ + public static double distFrom(Point start, Point end) { + return distFrom(start.getLatitude(), start.getLongitude(), end.getLatitude(), end.getLongitude()); + } + + /** + * Dist between coordinates + * + * @param lat1 the start latitude coordinate + * @param lng1 the start longitude coordinate + * @param lat2 the end latitude coordinate + * @param lng2 the end longitude coordinate + * @return the double + */ + public static double distFrom(double lat1, double lng1, double lat2, double lng2) { + double earthRadius = 6371000; + double lat = Math.toRadians(lat2 - lat1); + double lng = Math.toRadians(lng2 - lng1); + double haversine = Math.sin(lat / 2) * Math.sin(lat / 2) + + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) + * Math.sin(lng / 2) * Math.sin(lng / 2); + + + return earthRadius * (2 * Math.atan2(Math.sqrt(haversine), Math.sqrt(1 - haversine))); + } + + /** + * Sort items map by distance + * + * @param items the items + * @param api the api + * @return the map + */ + public Map sortItems(List items, PokemonGo api) { + Map result = new TreeMap<>(); + for (K point : items) { + result.put(distFrom(api.getLatitude(), api.getLongitude(), point.getLatitude(), point.getLongitude()), point); + } + return result; + } +} diff --git a/src/main/java/com/pokegoapi/util/NestedFutureWrapper.java b/src/main/java/com/pokegoapi/util/NestedFutureWrapper.java new file mode 100644 index 00000000..5619f9d4 --- /dev/null +++ b/src/main/java/com/pokegoapi/util/NestedFutureWrapper.java @@ -0,0 +1,55 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.util; + +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +public abstract class NestedFutureWrapper extends FutureWrapper { + public NestedFutureWrapper(Future result) { + super(result); + } + + protected R getResult(long timeouut, TimeUnit timeUnit) throws InterruptedException, ExecutionException { + long wait = System.currentTimeMillis() + timeUnit.toMillis(timeouut); + while (!isDone()) { + Thread.sleep(10); + if (wait < System.currentTimeMillis()) { + return null; + } + } + Future future = handleFuture(result.get()); + while (future.isDone()) { + Thread.sleep(10); + if (wait < System.currentTimeMillis()) { + return null; + } + } + return future.get(); + } + + protected abstract Future handleFuture(T result); + + @Override + protected final R handle(T result) throws RemoteServerException, LoginFailedException { + // Because getResult is overiden, this is not called + return null; + } +} diff --git a/src/main/java/com/pokegoapi/util/PokeNames.java b/src/main/java/com/pokegoapi/util/PokeNames.java new file mode 100644 index 00000000..3a1618ff --- /dev/null +++ b/src/main/java/com/pokegoapi/util/PokeNames.java @@ -0,0 +1,36 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.util; + +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * @author Angelo Rüggeberg + */ + +public class PokeNames { + /** + * Returns the Name for a Pokedex ID including known translations. + * @param pokedexNr pokedex number + * @param locale locale + * @return the pokemon name locale + */ + public static String getDisplayName(int pokedexNr, Locale locale) { + ResourceBundle names = ResourceBundle.getBundle("pokemon_names", locale); + return names.getString(String.valueOf(pokedexNr)); + } +} diff --git a/src/main/java/com/pokegoapi/util/PokemonFuture.java b/src/main/java/com/pokegoapi/util/PokemonFuture.java new file mode 100644 index 00000000..8547ad77 --- /dev/null +++ b/src/main/java/com/pokegoapi/util/PokemonFuture.java @@ -0,0 +1,25 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.util; + +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; + +import java.util.concurrent.Future; + +public interface PokemonFuture extends Future { + T toBlocking() throws LoginFailedException, RemoteServerException; +} diff --git a/src/main/java/com/pokegoapi/util/SystemTimeImpl.java b/src/main/java/com/pokegoapi/util/SystemTimeImpl.java new file mode 100644 index 00000000..440f8b43 --- /dev/null +++ b/src/main/java/com/pokegoapi/util/SystemTimeImpl.java @@ -0,0 +1,23 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.util; + +public class SystemTimeImpl implements Time { + @Override + public long currentTimeMillis() { + return System.currentTimeMillis(); + } +} diff --git a/src/main/java/com/pokegoapi/util/Time.java b/src/main/java/com/pokegoapi/util/Time.java new file mode 100644 index 00000000..d31e7d93 --- /dev/null +++ b/src/main/java/com/pokegoapi/util/Time.java @@ -0,0 +1,25 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.util; + +public interface Time { + /** + * Returns the current time in milliseconds. + * + * @return the time + */ + long currentTimeMillis(); +} diff --git a/src/main/resources/pokemon_names.properties b/src/main/resources/pokemon_names.properties new file mode 100644 index 00000000..9ab0cd23 --- /dev/null +++ b/src/main/resources/pokemon_names.properties @@ -0,0 +1,721 @@ +1=Bulbasaur +2=Ivysaur +3=Venusaur +4=Charmander +5=Charmeleon +6=Charizard +7=Squirtle +8=Wartortle +9=Blastoise +10=Caterpie +11=Metapod +12=Butterfree +13=Weedle +14=Kakuna +15=Beedrill +16=Pidgey +17=Pidgeotto +18=Pidgeot +19=Rattata +20=Raticate +21=Spearow +22=Fearow +23=Ekans +24=Arbok +25=Pikachu +26=Raichu +27=Sandshrew +28=Sandslash +29=Nidoran♀ +30=Nidorina +31=Nidoqueen +32=Nidoran♂ +33=Nidorino +34=Nidoking +35=Clefairy +36=Clefable +37=Vulpix +38=Ninetales +39=Jigglypuff +40=Wigglytuff +41=Zubat +42=Golbat +43=Oddish +44=Gloom +45=Vileplume +46=Paras +47=Parasect +48=Venonat +49=Venomoth +50=Diglett +51=Dugtrio +52=Meowth +53=Persian +54=Psyduck +55=Golduck +56=Mankey +57=Primeape +58=Growlithe +59=Arcanine +60=Poliwag +61=Poliwhirl +62=Poliwrath +63=Abra +64=Kadabra +65=Alakazam +66=Machop +67=Machoke +68=Machamp +69=Bellsprout +70=Weepinbell +71=Victreebel +72=Tentacool +73=Tentacruel +74=Geodude +75=Graveler +76=Golem +77=Ponyta +78=Rapidash +79=Slowpoke +80=Slowbro +81=Magnemite +82=Magneton +83=Farfetch'd +84=Doduo +85=Dodrio +86=Seel +87=Dewgong +88=Grimer +89=Muk +90=Shellder +91=Cloyster +92=Gastly +93=Haunter +94=Gengar +95=Onix +96=Drowzee +97=Hypno +98=Krabby +99=Kingler +100=Voltorb +101=Electrode +102=Exeggcute +103=Exeggutor +104=Cubone +105=Marowak +106=Hitmonlee +107=Hitmonchan +108=Lickitung +109=Koffing +110=Weezing +111=Rhyhorn +112=Rhydon +113=Chansey +114=Tangela +115=Kangaskhan +116=Horsea +117=Seadra +118=Goldeen +119=Seaking +120=Staryu +121=Starmie +122=Mr. Mime +123=Scyther +124=Jynx +125=Electabuzz +126=Magmar +127=Pinsir +128=Tauros +129=Magikarp +130=Gyarados +131=Lapras +132=Ditto +133=Eevee +134=Vaporeon +135=Jolteon +136=Flareon +137=Porygon +138=Omanyte +139=Omastar +140=Kabuto +141=Kabutops +142=Aerodactyl +143=Snorlax +144=Articuno +145=Zapdos +146=Moltres +147=Dratini +148=Dragonair +149=Dragonite +150=Mewtwo +151=Mew +152=Chikorita +153=Bayleef +154=Meganium +155=Cyndaquil +156=Quilava +157=Typhlosion +158=Totodile +159=Croconaw +160=Feraligatr +161=Sentret +162=Furret +163=Hoothoot +164=Noctowl +165=Ledyba +166=Ledian +167=Spinarak +168=Ariados +169=Crobat +170=Chinchou +171=Lanturn +172=Pichu +173=Cleffa +174=Igglybuff +175=Togepi +176=Togetic +177=Natu +178=Xatu +179=Mareep +180=Flaaffy +181=Ampharos +182=Bellossom +183=Marill +184=Azumarill +185=Sudowoodo +186=Politoed +187=Hoppip +188=Skiploom +189=Jumpluff +190=Aipom +191=Sunkern +192=Sunflora +193=Yanma +194=Wooper +195=Quagsire +196=Espeon +197=Umbreon +198=Murkrow +199=Slowking +200=Misdreavus +201=Unown +202=Wobbuffet +203=Girafarig +204=Pineco +205=Forretress +206=Dunsparce +207=Gligar +208=Steelix +209=Snubbull +210=Granbull +211=Qwilfish +212=Scizor +213=Shuckle +214=Heracross +215=Sneasel +216=Teddiursa +217=Ursaring +218=Slugma +219=Magcargo +220=Swinub +221=Piloswine +222=Corsola +223=Remoraid +224=Octillery +225=Delibird +226=Mantine +227=Skarmory +228=Houndour +229=Houndoom +230=Kingdra +231=Phanpy +232=Donphan +233=Porygon2 +234=Stantler +235=Smeargle +236=Tyrogue +237=Hitmontop +238=Smoochum +239=Elekid +240=Magby +241=Miltank +242=Blissey +243=Raikou +244=Entei +245=Suicune +246=Larvitar +247=Pupitar +248=Tyranitar +249=Lugia +250=Ho-Oh +251=Celebi +252=Treecko +253=Grovyle +254=Sceptile +255=Torchic +256=Combusken +257=Blaziken +258=Mudkip +259=Marshtomp +260=Swampert +261=Poochyena +262=Mightyena +263=Zigzagoon +264=Linoone +265=Wurmple +266=Silcoon +267=Beautifly +268=Cascoon +269=Dustox +270=Lotad +271=Lombre +272=Ludicolo +273=Seedot +274=Nuzleaf +275=Shiftry +276=Taillow +277=Swellow +278=Wingull +279=Pelipper +280=Ralts +281=Kirlia +282=Gardevoir +283=Surskit +284=Masquerain +285=Shroomish +286=Breloom +287=Slakoth +288=Vigoroth +289=Slaking +290=Nincada +291=Ninjask +292=Shedinja +293=Whismur +294=Loudred +295=Exploud +296=Makuhita +297=Hariyama +298=Azurill +299=Nosepass +300=Skitty +301=Delcatty +302=Sableye +303=Mawile +304=Aron +305=Lairon +306=Aggron +307=Meditite +308=Medicham +309=Electrike +310=Manectric +311=Plusle +312=Minun +313=Volbeat +314=Illumise +315=Roselia +316=Gulpin +317=Swalot +318=Carvanha +319=Sharpedo +320=Wailmer +321=Wailord +322=Numel +323=Camerupt +324=Torkoal +325=Spoink +326=Grumpig +327=Spinda +328=Trapinch +329=Vibrava +330=Flygon +331=Cacnea +332=Cacturne +333=Swablu +334=Altaria +335=Zangoose +336=Seviper +337=Lunatone +338=Solrock +339=Barboach +340=Whiscash +341=Corphish +342=Crawdaunt +343=Baltoy +344=Claydol +345=Lileep +346=Cradily +347=Anorith +348=Armaldo +349=Feebas +350=Milotic +351=Castform +352=Kecleon +353=Shuppet +354=Banette +355=Duskull +356=Dusclops +357=Tropius +358=Chimecho +359=Absol +360=Wynaut +361=Snorunt +362=Glalie +363=Spheal +364=Sealeo +365=Walrein +366=Clamperl +367=Huntail +368=Gorebyss +369=Relicanth +370=Luvdisc +371=Bagon +372=Shelgon +373=Salamence +374=Beldum +375=Metang +376=Metagross +377=Regirock +378=Regice +379=Registeel +380=Latias +381=Latios +382=Kyogre +383=Groudon +384=Rayquaza +385=Jirachi +386=Deoxys +387=Turtwig +388=Grotle +389=Torterra +390=Chimchar +391=Monferno +392=Infernape +393=Piplup +394=Prinplup +395=Empoleon +396=Starly +397=Staravia +398=Staraptor +399=Bidoof +400=Bibarel +401=Kricketot +402=Kricketune +403=Shinx +404=Luxio +405=Luxray +406=Budew +407=Roserade +408=Cranidos +409=Rampardos +410=Shieldon +411=Bastiodon +412=Burmy +413=Wormadam +414=Mothim +415=Combee +416=Vespiquen +417=Pachirisu +418=Buizel +419=Floatzel +420=Cherubi +421=Cherrim +422=Shellos +423=Gastrodon +424=Ambipom +425=Drifloon +426=Drifblim +427=Buneary +428=Lopunny +429=Mismagius +430=Honchkrow +431=Glameow +432=Purugly +433=Chingling +434=Stunky +435=Skuntank +436=Bronzor +437=Bronzong +438=Bonsly +439=Mime Jr. +440=Happiny +441=Chatot +442=Spiritomb +443=Gible +444=Gabite +445=Garchomp +446=Munchlax +447=Riolu +448=Lucario +449=Hippopotas +450=Hippowdon +451=Skorupi +452=Drapion +453=Croagunk +454=Toxicroak +455=Carnivine +456=Finneon +457=Lumineon +458=Mantyke +459=Snover +460=Abomasnow +461=Weavile +462=Magnezone +463=Lickilicky +464=Rhyperior +465=Tangrowth +466=Electivire +467=Magmortar +468=Togekiss +469=Yanmega +470=Leafeon +471=Glaceon +472=Gliscor +473=Mamoswine +474=Porygon-Z +475=Gallade +476=Probopass +477=Dusknoir +478=Froslass +479=Rotom +480=Uxie +481=Mesprit +482=Azelf +483=Dialga +484=Palkia +485=Heatran +486=Regigigas +487=Giratina +488=Cresselia +489=Phione +490=Manaphy +491=Darkrai +492=Shaymin +493=Arceus +494=Victini +495=Snivy +496=Servine +497=Serperior +498=Tepig +499=Pignite +500=Emboar +501=Oshawott +502=Dewott +503=Samurott +504=Patrat +505=Watchog +506=Lillipup +507=Herdier +508=Stoutland +509=Purrloin +510=Liepard +511=Pansage +512=Simisage +513=Pansear +514=Simisear +515=Panpour +516=Simipour +517=Munna +518=Musharna +519=Pidove +520=Tranquill +521=Unfezant +522=Blitzle +523=Zebstrika +524=Roggenrola +525=Boldore +526=Gigalith +527=Woobat +528=Swoobat +529=Drilbur +530=Excadrill +531=Audino +532=Timburr +533=Gurdurr +534=Conkeldurr +535=Tympole +536=Palpitoad +537=Seismitoad +538=Throh +539=Sawk +540=Sewaddle +541=Swadloon +542=Leavanny +543=Venipede +544=Whirlipede +545=Scolipede +546=Cottonee +547=Whimsicott +548=Petilil +549=Lilligant +550=Basculin +551=Sandile +552=Krokorok +553=Krookodile +554=Darumaka +555=Darmanitan +556=Maractus +557=Dwebble +558=Crustle +559=Scraggy +560=Scrafty +561=Sigilyph +562=Yamask +563=Cofagrigus +564=Tirtouga +565=Carracosta +566=Archen +567=Archeops +568=Trubbish +569=Garbodor +570=Zorua +571=Zoroark +572=Minccino +573=Cinccino +574=Gothita +575=Gothorita +576=Gothitelle +577=Solosis +578=Duosion +579=Reuniclus +580=Ducklett +581=Swanna +582=Vanillite +583=Vanillish +584=Vanilluxe +585=Deerling +586=Sawsbuck +587=Emolga +588=Karrablast +589=Escavalier +590=Foongus +591=Amoonguss +592=Frillish +593=Jellicent +594=Alomomola +595=Joltik +596=Galvantula +597=Ferroseed +598=Ferrothorn +599=Klink +600=Klang +601=Klinklang +602=Tynamo +603=Eelektrik +604=Eelektross +605=Elgyem +606=Beheeyem +607=Litwick +608=Lampent +609=Chandelure +610=Axew +611=Fraxure +612=Haxorus +613=Cubchoo +614=Beartic +615=Cryogonal +616=Shelmet +617=Accelgor +618=Stunfisk +619=Mienfoo +620=Mienshao +621=Druddigon +622=Golett +623=Golurk +624=Pawniard +625=Bisharp +626=Bouffalant +627=Rufflet +628=Braviary +629=Vullaby +630=Mandibuzz +631=Heatmor +632=Durant +633=Deino +634=Zweilous +635=Hydreigon +636=Larvesta +637=Volcarona +638=Cobalion +639=Terrakion +640=Virizion +641=Tornadus +642=Thundurus +643=Reshiram +644=Zekrom +645=Landorus +646=Kyurem +647=Keldeo +648=Meloetta +649=Genesect +650=Chespin +651=Quilladin +652=Chesnaught +653=Fennekin +654=Braixen +655=Delphox +656=Froakie +657=Frogadier +658=Greninja +659=Bunnelby +660=Diggersby +661=Fletchling +662=Fletchinder +663=Talonflame +664=Scatterbug +665=Spewpa +666=Vivillon +667=Litleo +668=Pyroar +669=Flabébé +670=Floette +671=Florges +672=Skiddo +673=Gogoat +674=Pancham +675=Pangoro +676=Furfrou +677=Espurr +678=Meowstic +679=Honedge +680=Doublade +681=Aegislash +682=Spritzee +683=Aromatisse +684=Swirlix +685=Slurpuff +686=Inkay +687=Malamar +688=Binacle +689=Barbaracle +690=Skrelp +691=Dragalge +692=Clauncher +693=Clawitzer +694=Helioptile +695=Heliolisk +696=Tyrunt +697=Tyrantrum +698=Amaura +699=Aurorus +700=Sylveon +701=Hawlucha +702=Dedenne +703=Carbink +704=Goomy +705=Sliggoo +706=Goodra +707=Klefki +708=Phantump +709=Trevenant +710=Pumpkaboo +711=Gourgeist +712=Bergmite +713=Avalugg +714=Noibat +715=Noivern +716=Xerneas +717=Yveltal +718=Zygarde +719=Diancie +720=Hoopa +721=Volcanion \ No newline at end of file diff --git a/src/main/resources/pokemon_names_de.properties b/src/main/resources/pokemon_names_de.properties new file mode 100644 index 00000000..6b65b7a0 --- /dev/null +++ b/src/main/resources/pokemon_names_de.properties @@ -0,0 +1,721 @@ +1=Bisasam +2=Bisaknosp +3=Bisaflor +4=Glumanda +5=Glutexo +6=Glurak +7=Schiggy +8=Schillok +9=Turtok +10=Raupy +11=Safcon +12=Smettbo +13=Hornliu +14=Kokuna +15=Bibor +16=Taubsi +17=Tauboga +18=Tauboss +19=Rattfratz +20=Rattikarl +21=Habitak +22=Ibitak +23=Rettan +24=Arbok +25=Pikachu +26=Raichu +27=Sandan +28=Sandamer +29=Nidoran♀ +30=Nidorina +31=Nidoqueen +32=Nidoran♂ +33=Nidorino +34=Nidoking +35=Piepi +36=Pixi +37=Vulpix +38=Vulnona +39=Pummeluff +40=Knuddeluff +41=Zubat +42=Golbat +43=Myrapla +44=Duflor +45=Giflor +46=Paras +47=Parasek +48=Bluzuk +49=Omot +50=Digda +51=Digdri +52=Mauzi +53=Snobilikat +54=Enton +55=Entoron +56=Menki +57=Rasaff +58=Fukano +59=Arkani +60=Quapsel +61=Quaputzi +62=Quappo +63=Abra +64=Kadabra +65=Simsala +66=Machollo +67=Maschock +68=Machomei +69=Knofensa +70=Ultrigaria +71=Sarzenia +72=Tentacha +73=Tentoxa +74=Kleinstein +75=Georok +76=Geowaz +77=Ponita +78=Gallopa +79=Flegmon +80=Lahmus +81=Magnetilo +82=Magneton +83=Porenta +84=Dodu +85=Dodri +86=Jurob +87=Jugong +88=Sleima +89=Sleimok +90=Muschas +91=Austos +92=Nebulak +93=Alpollo +94=Gengar +95=Onix +96=Traumato +97=Hypno +98=Krabby +99=Kingler +100=Voltobal +101=Lektrobal +102=Owei +103=Kokowei +104=Tragosso +105=Knogga +106=Kicklee +107=Nockchan +108=Schlurp +109=Smogon +110=Smogmog +111=Rihorn +112=Rizeros +113=Chaneira +114=Tangela +115=Kangama +116=Seeper +117=Seemon +118=Goldini +119=Golking +120=Sterndu +121=Starmie +122=Pantimos +123=Sichlor +124=Rossana +125=Elektek +126=Magmar +127=Pinsir +128=Tauros +129=Karpador +130=Garados +131=Lapras +132=Ditto +133=Evoli +134=Aquana +135=Blitza +136=Flamara +137=Porygon +138=Amonitas +139=Amoroso +140=Kabuto +141=Kabutops +142=Aerodactyl +143=Relaxo +144=Arktos +145=Zapdos +146=Lavados +147=Dratini +148=Dragonir +149=Dragoran +150=Mewtu +151=Mew +152=Endivie +153=Lorblatt +154=Meganie +155=Feurigel +156=Igelavar +157=Tornupto +158=Karnimani +159=Tyracroc +160=Impergator +161=Wiesor +162=Wiesenior +163=Hoothoot +164=Noctuh +165=Ledyba +166=Ledian +167=Webarak +168=Ariados +169=Iksbat +170=Lampi +171=Lanturn +172=Pichu +173=Pii +174=Fluffeluff +175=Togepi +176=Togetic +177=Natu +178=Xatu +179=Voltilamm +180=Waaty +181=Ampharos +182=Blubella +183=Marill +184=Azumarill +185=Mogelbaum +186=Quaxo +187=Hoppspross +188=Hubelupf +189=Papungha +190=Griffel +191=Sonnkern +192=Sonnflora +193=Yanma +194=Felino +195=Morlord +196=Psiana +197=Nachtara +198=Kramurx +199=Laschoking +200=Traunfugil +201=Icognito +202=Woingenau +203=Girafarig +204=Tannza +205=Forstellka +206=Dummisel +207=Skorgla +208=Stahlos +209=Snubbull +210=Granbull +211=Baldorfish +212=Scherox +213=Pottrott +214=Skaraborn +215=Sniebel +216=Teddiursa +217=Ursaring +218=Schneckmag +219=Magcargo +220=Quiekel +221=Keifel +222=Corasonn +223=Remoraid +224=Octillery +225=Botogel +226=Mantax +227=Panzaeron +228=Hunduster +229=Hundemon +230=Seedraking +231=Phanpy +232=Donphan +233=Porygon2 +234=Damhirplex +235=Farbeagle +236=Rabauz +237=Kapoera +238=Kussilla +239=Elekid +240=Magby +241=Miltank +242=Heiteira +243=Raikou +244=Entei +245=Suicune +246=Larvitar +247=Pupitar +248=Despotar +249=Lugia +250=Ho-Oh +251=Celebi +252=Geckarbor +253=Reptain +254=Gewaldro +255=Flemmli +256=Jungglut +257=Lohgock +258=Hydropi +259=Moorabbel +260=Sumpex +261=Fiffyen +262=Magnayen +263=Zigzachs +264=Geradaks +265=Waumpel +266=Schaloko +267=Papinella +268=Panekon +269=Pudox +270=Loturzel +271=Lombrero +272=Kappalores +273=Samurzel +274=Blanas +275=Tengulist +276=Schwalbini +277=Schwalboss +278=Wingull +279=Pelipper +280=Trasla +281=Kirlia +282=Guardevoir +283=Gehweiher +284=Maskeregen +285=Knilz +286=Kapilz +287=Bummelz +288=Muntier +289=Letarking +290=Nincada +291=Ninjask +292=Ninjatom +293=Flurmel +294=Krakeelo +295=Krawumms +296=Makuhita +297=Hariyama +298=Azurill +299=Nasgnet +300=Eneco +301=Enekoro +302=Zobiris +303=Flunkifer +304=Stollunior +305=Stollrak +306=Stolloss +307=Meditie +308=Meditalis +309=Frizelbliz +310=Voltenso +311=Plusle +312=Minun +313=Volbeat +314=Illumise +315=Roselia +316=Schluppuck +317=Schlukwech +318=Kanivanha +319=Tohaido +320=Wailmer +321=Wailord +322=Camaub +323=Camerupt +324=Qurtel +325=Spoink +326=Groink +327=Pandir +328=Knacklion +329=Vibrava +330=Libelldra +331=Tuska +332=Noktuska +333=Wablu +334=Altaria +335=Sengo +336=Vipitis +337=Lunastein +338=Sonnfel +339=Schmerbe +340=Welsar +341=Krebscorps +342=Krebutack +343=Puppance +344=Lepumentas +345=Liliep +346=Wielie +347=Anorith +348=Armaldo +349=Barschwa +350=Milotic +351=Formeo +352=Kecleon +353=Shuppet +354=Banette +355=Zwirrlicht +356=Zwirrklop +357=Tropius +358=Palimpalim +359=Absol +360=Isso +361=Schneppke +362=Firnontor +363=Seemops +364=Seejong +365=Walraisa +366=Perlu +367=Aalabyss +368=Saganabyss +369=Relicanth +370=Liebiskus +371=Kindwurm +372=Draschel +373=Brutalanda +374=Tanhel +375=Metang +376=Metagross +377=Regirock +378=Regice +379=Registeel +380=Latias +381=Latios +382=Kyogre +383=Groudon +384=Rayquaza +385=Jirachi +386=Deoxys +387=Chelast +388=Chelcarain +389=Chelterrar +390=Panflam +391=Panpyro +392=Panferno +393=Plinfa +394=Pliprin +395=Impoleon +396=Staralili +397=Staravia +398=Staraptor +399=Bidiza +400=Bidifas +401=Zirpurze +402=Zirpeise +403=Sheinux +404=Luxio +405=Luxtra +406=Knospi +407=Roserade +408=Koknodon +409=Rameidon +410=Schilterus +411=Bollterus +412=Burmy +413=Burmadame +414=Moterpel +415=Wadribie +416=Honweisel +417=Pachirisu +418=Bamelin +419=Bojelin +420=Kikugi +421=Kinoso +422=Schalellos +423=Gastrodon +424=Ambidiffel +425=Driftlon +426=Drifzepeli +427=Haspiror +428=Schlapor +429=Traunmagil +430=Kramshef +431=Charmian +432=Shnurgarst +433=Klingplim +434=Skunkapuh +435=Skuntank +436=Bronzel +437=Bronzong +438=Mobai +439=Pantimimi +440=Wonneira +441=Plaudagei +442=Kryppuk +443=Kaumalat +444=Knarksel +445=Knakrack +446=Mampfaxo +447=Riolu +448=Lucario +449=Hippopotas +450=Hippoterus +451=Pionskora +452=Piondragi +453=Glibunkel +454=Toxiquak +455=Venuflibis +456=Finneon +457=Lumineon +458=Mantirps +459=Shnebedeck +460=Rexblisar +461=Snibunna +462=Magnezone +463=Schlurplek +464=Rihornior +465=Tangoloss +466=Elevoltek +467=Magbrant +468=Togekiss +469=Yanmega +470=Folipurba +471=Glaziola +472=Skorgro +473=Mamutel +474=Porygon-Z +475=Galagladi +476=Voluminas +477=Zwirrfinst +478=Frosdedje +479=Rotom +480=Selfe +481=Vesprit +482=Tobutz +483=Dialga +484=Palkia +485=Heatran +486=Regigigas +487=Giratina +488=Cresselia +489=Phione +490=Manaphy +491=Darkrai +492=Shaymin +493=Arceus +494=Victini +495=Serpifeu +496=Efoserp +497=Serpiroyal +498=Floink +499=Ferkokel +500=Flambirex +501=Ottaro +502=Zwottronin +503=Admurai +504=Nagelotz +505=Kukmarda +506=Yorkleff +507=Terribark +508=Bissbark +509=Felilou +510=Kleoparda +511=Vegimak +512=Vegichita +513=Grillmak +514=Grillchita +515=Sodamak +516=Sodachita +517=Somniam +518=Somnivora +519=Dusselgurr +520=Navitaub +521=Fasasnob +522=Elezeba +523=Zebritz +524=Kiesling +525=Sedimantur +526=Brockoloss +527=Fleknoil +528=Fletiamo +529=Rotomurf +530=Stalobor +531=Ohrdoch +532=Praktibalk +533=Strepoli +534=Meistagrif +535=Schallquap +536=Mebrana +537=Branawarz +538=Jiutesto +539=Karadonis +540=Strawickl +541=Folikon +542=Matrifol +543=Toxiped +544=Rollum +545=Cerapendra +546=Waumboll +547=Elfun +548=Lilminip +549=Dressella +550=Barschuft +551=Ganovil +552=Rokkaiman +553=Rabigator +554=Flampion +555=Flampivian +556=Maracamba +557=Lithomith +558=Castellith +559=Zurrokex +560=Irokex +561=Symvolara +562=Makabaja +563=Echnatoll +564=Galapaflos +565=Karippas +566=Flapteryx +567=Aeropteryx +568=Unratütox +569=Deponitox +570=Zorua +571=Zoroark +572=Picochilla +573=Chillabell +574=Mollimorba +575=Hypnomorba +576=Morbitesse +577=Monozyto +578=Mitodos +579=Zytomega +580=Piccolente +581=Swaroness +582=Gelatini +583=Gelatroppo +584=Gelatwino +585=Sesokitz +586=Kronjuwild +587=Emolga +588=Laukaps +589=Cavalanzas +590=Tarnpignon +591=Hutsassa +592=Quabbel +593=Apoquallyp +594=Mamolida +595=Wattzapf +596=Voltula +597=Kastadur +598=Tentantel +599=Klikk +600=Kliklak +601=Klikdiklak +602=Zapplardin +603=Zapplalek +604=Zapplarang +605=Pygraulon +606=Megalon +607=Lichtel +608=Laternecto +609=Skelabra +610=Milza +611=Sharfax +612=Maxax +613=Petznief +614=Siberio +615=Frigometri +616=Schnuthelm +617=Hydragil +618=Flunschlik +619=Lin-Fu +620=Wie-Shu +621=Shardrago +622=Golbit +623=Golgantes +624=Gladiantri +625=Caesurio +626=Bisofank +627=Geronimatz +628=Washakwil +629=Skallyk +630=Grypheldis +631=Furnifraß +632=Fermicula +633=Kapuno +634=Duodino +635=Trikephalo +636=Ignivor +637=Ramoth +638=Kobalium +639=Terrakium +640=Viridium +641=Boreos +642=Voltolos +643=Reshiram +644=Zekrom +645=Demeteros +646=Kyurem +647=Keldeo +648=Meloetta +649=Genesect +650=Igamaro +651=Igastarnish +652=Brigaron +653=Fynx +654=Rutena +655=Fennexis +656=Froxy +657=Amphizel +658=Quajutsu +659=Scoppel +660=Grebbit +661=Dartiri +662=Dartignis +663=Fiaro +664=Purmel +665=Puponcho +666=Vivillon +667=Leufeo +668=Pyroleo +669=Flabébé +670=FLOETTE +671=Florges +672=Mähikel +673=Chevrumm +674=Pam-Pam +675=Pandagro +676=Coiffwaff +677=Psiau +678=Psiaugon +679=Gramokles +680=Duokles +681=Durengard +682=Parfi +683=Parfinesse +684=Flauschling +685=Sabbaione +686=Iscalar +687=Calamanero +688=Bithora +689=Thanathora +690=Algitt +691=Tandrak +692=Scampisto +693=Wummer +694=Eguana +695=Elezard +696=Balgoras +697=Monargoras +698=Amarino +699=Amagarga +700=Feelinara +701=Resladero +702=DEDENNE +703=Rocara +704=Viscora +705=Viscargot +706=Viscogon +707=Clavion +708=Paragoni +709=Trombork +710=Irrbis +711=Pumpdjinn +712=Arktip +713=Arktilas +714=eF-eM +715=UHaFnir +716=Xerneas +717=Yveltal +718=Zygarde +719=Diancie +720=Hoopa +721=Volcanion \ No newline at end of file diff --git a/src/main/resources/pokemon_names_en.properties b/src/main/resources/pokemon_names_en.properties new file mode 100644 index 00000000..9ab0cd23 --- /dev/null +++ b/src/main/resources/pokemon_names_en.properties @@ -0,0 +1,721 @@ +1=Bulbasaur +2=Ivysaur +3=Venusaur +4=Charmander +5=Charmeleon +6=Charizard +7=Squirtle +8=Wartortle +9=Blastoise +10=Caterpie +11=Metapod +12=Butterfree +13=Weedle +14=Kakuna +15=Beedrill +16=Pidgey +17=Pidgeotto +18=Pidgeot +19=Rattata +20=Raticate +21=Spearow +22=Fearow +23=Ekans +24=Arbok +25=Pikachu +26=Raichu +27=Sandshrew +28=Sandslash +29=Nidoran♀ +30=Nidorina +31=Nidoqueen +32=Nidoran♂ +33=Nidorino +34=Nidoking +35=Clefairy +36=Clefable +37=Vulpix +38=Ninetales +39=Jigglypuff +40=Wigglytuff +41=Zubat +42=Golbat +43=Oddish +44=Gloom +45=Vileplume +46=Paras +47=Parasect +48=Venonat +49=Venomoth +50=Diglett +51=Dugtrio +52=Meowth +53=Persian +54=Psyduck +55=Golduck +56=Mankey +57=Primeape +58=Growlithe +59=Arcanine +60=Poliwag +61=Poliwhirl +62=Poliwrath +63=Abra +64=Kadabra +65=Alakazam +66=Machop +67=Machoke +68=Machamp +69=Bellsprout +70=Weepinbell +71=Victreebel +72=Tentacool +73=Tentacruel +74=Geodude +75=Graveler +76=Golem +77=Ponyta +78=Rapidash +79=Slowpoke +80=Slowbro +81=Magnemite +82=Magneton +83=Farfetch'd +84=Doduo +85=Dodrio +86=Seel +87=Dewgong +88=Grimer +89=Muk +90=Shellder +91=Cloyster +92=Gastly +93=Haunter +94=Gengar +95=Onix +96=Drowzee +97=Hypno +98=Krabby +99=Kingler +100=Voltorb +101=Electrode +102=Exeggcute +103=Exeggutor +104=Cubone +105=Marowak +106=Hitmonlee +107=Hitmonchan +108=Lickitung +109=Koffing +110=Weezing +111=Rhyhorn +112=Rhydon +113=Chansey +114=Tangela +115=Kangaskhan +116=Horsea +117=Seadra +118=Goldeen +119=Seaking +120=Staryu +121=Starmie +122=Mr. Mime +123=Scyther +124=Jynx +125=Electabuzz +126=Magmar +127=Pinsir +128=Tauros +129=Magikarp +130=Gyarados +131=Lapras +132=Ditto +133=Eevee +134=Vaporeon +135=Jolteon +136=Flareon +137=Porygon +138=Omanyte +139=Omastar +140=Kabuto +141=Kabutops +142=Aerodactyl +143=Snorlax +144=Articuno +145=Zapdos +146=Moltres +147=Dratini +148=Dragonair +149=Dragonite +150=Mewtwo +151=Mew +152=Chikorita +153=Bayleef +154=Meganium +155=Cyndaquil +156=Quilava +157=Typhlosion +158=Totodile +159=Croconaw +160=Feraligatr +161=Sentret +162=Furret +163=Hoothoot +164=Noctowl +165=Ledyba +166=Ledian +167=Spinarak +168=Ariados +169=Crobat +170=Chinchou +171=Lanturn +172=Pichu +173=Cleffa +174=Igglybuff +175=Togepi +176=Togetic +177=Natu +178=Xatu +179=Mareep +180=Flaaffy +181=Ampharos +182=Bellossom +183=Marill +184=Azumarill +185=Sudowoodo +186=Politoed +187=Hoppip +188=Skiploom +189=Jumpluff +190=Aipom +191=Sunkern +192=Sunflora +193=Yanma +194=Wooper +195=Quagsire +196=Espeon +197=Umbreon +198=Murkrow +199=Slowking +200=Misdreavus +201=Unown +202=Wobbuffet +203=Girafarig +204=Pineco +205=Forretress +206=Dunsparce +207=Gligar +208=Steelix +209=Snubbull +210=Granbull +211=Qwilfish +212=Scizor +213=Shuckle +214=Heracross +215=Sneasel +216=Teddiursa +217=Ursaring +218=Slugma +219=Magcargo +220=Swinub +221=Piloswine +222=Corsola +223=Remoraid +224=Octillery +225=Delibird +226=Mantine +227=Skarmory +228=Houndour +229=Houndoom +230=Kingdra +231=Phanpy +232=Donphan +233=Porygon2 +234=Stantler +235=Smeargle +236=Tyrogue +237=Hitmontop +238=Smoochum +239=Elekid +240=Magby +241=Miltank +242=Blissey +243=Raikou +244=Entei +245=Suicune +246=Larvitar +247=Pupitar +248=Tyranitar +249=Lugia +250=Ho-Oh +251=Celebi +252=Treecko +253=Grovyle +254=Sceptile +255=Torchic +256=Combusken +257=Blaziken +258=Mudkip +259=Marshtomp +260=Swampert +261=Poochyena +262=Mightyena +263=Zigzagoon +264=Linoone +265=Wurmple +266=Silcoon +267=Beautifly +268=Cascoon +269=Dustox +270=Lotad +271=Lombre +272=Ludicolo +273=Seedot +274=Nuzleaf +275=Shiftry +276=Taillow +277=Swellow +278=Wingull +279=Pelipper +280=Ralts +281=Kirlia +282=Gardevoir +283=Surskit +284=Masquerain +285=Shroomish +286=Breloom +287=Slakoth +288=Vigoroth +289=Slaking +290=Nincada +291=Ninjask +292=Shedinja +293=Whismur +294=Loudred +295=Exploud +296=Makuhita +297=Hariyama +298=Azurill +299=Nosepass +300=Skitty +301=Delcatty +302=Sableye +303=Mawile +304=Aron +305=Lairon +306=Aggron +307=Meditite +308=Medicham +309=Electrike +310=Manectric +311=Plusle +312=Minun +313=Volbeat +314=Illumise +315=Roselia +316=Gulpin +317=Swalot +318=Carvanha +319=Sharpedo +320=Wailmer +321=Wailord +322=Numel +323=Camerupt +324=Torkoal +325=Spoink +326=Grumpig +327=Spinda +328=Trapinch +329=Vibrava +330=Flygon +331=Cacnea +332=Cacturne +333=Swablu +334=Altaria +335=Zangoose +336=Seviper +337=Lunatone +338=Solrock +339=Barboach +340=Whiscash +341=Corphish +342=Crawdaunt +343=Baltoy +344=Claydol +345=Lileep +346=Cradily +347=Anorith +348=Armaldo +349=Feebas +350=Milotic +351=Castform +352=Kecleon +353=Shuppet +354=Banette +355=Duskull +356=Dusclops +357=Tropius +358=Chimecho +359=Absol +360=Wynaut +361=Snorunt +362=Glalie +363=Spheal +364=Sealeo +365=Walrein +366=Clamperl +367=Huntail +368=Gorebyss +369=Relicanth +370=Luvdisc +371=Bagon +372=Shelgon +373=Salamence +374=Beldum +375=Metang +376=Metagross +377=Regirock +378=Regice +379=Registeel +380=Latias +381=Latios +382=Kyogre +383=Groudon +384=Rayquaza +385=Jirachi +386=Deoxys +387=Turtwig +388=Grotle +389=Torterra +390=Chimchar +391=Monferno +392=Infernape +393=Piplup +394=Prinplup +395=Empoleon +396=Starly +397=Staravia +398=Staraptor +399=Bidoof +400=Bibarel +401=Kricketot +402=Kricketune +403=Shinx +404=Luxio +405=Luxray +406=Budew +407=Roserade +408=Cranidos +409=Rampardos +410=Shieldon +411=Bastiodon +412=Burmy +413=Wormadam +414=Mothim +415=Combee +416=Vespiquen +417=Pachirisu +418=Buizel +419=Floatzel +420=Cherubi +421=Cherrim +422=Shellos +423=Gastrodon +424=Ambipom +425=Drifloon +426=Drifblim +427=Buneary +428=Lopunny +429=Mismagius +430=Honchkrow +431=Glameow +432=Purugly +433=Chingling +434=Stunky +435=Skuntank +436=Bronzor +437=Bronzong +438=Bonsly +439=Mime Jr. +440=Happiny +441=Chatot +442=Spiritomb +443=Gible +444=Gabite +445=Garchomp +446=Munchlax +447=Riolu +448=Lucario +449=Hippopotas +450=Hippowdon +451=Skorupi +452=Drapion +453=Croagunk +454=Toxicroak +455=Carnivine +456=Finneon +457=Lumineon +458=Mantyke +459=Snover +460=Abomasnow +461=Weavile +462=Magnezone +463=Lickilicky +464=Rhyperior +465=Tangrowth +466=Electivire +467=Magmortar +468=Togekiss +469=Yanmega +470=Leafeon +471=Glaceon +472=Gliscor +473=Mamoswine +474=Porygon-Z +475=Gallade +476=Probopass +477=Dusknoir +478=Froslass +479=Rotom +480=Uxie +481=Mesprit +482=Azelf +483=Dialga +484=Palkia +485=Heatran +486=Regigigas +487=Giratina +488=Cresselia +489=Phione +490=Manaphy +491=Darkrai +492=Shaymin +493=Arceus +494=Victini +495=Snivy +496=Servine +497=Serperior +498=Tepig +499=Pignite +500=Emboar +501=Oshawott +502=Dewott +503=Samurott +504=Patrat +505=Watchog +506=Lillipup +507=Herdier +508=Stoutland +509=Purrloin +510=Liepard +511=Pansage +512=Simisage +513=Pansear +514=Simisear +515=Panpour +516=Simipour +517=Munna +518=Musharna +519=Pidove +520=Tranquill +521=Unfezant +522=Blitzle +523=Zebstrika +524=Roggenrola +525=Boldore +526=Gigalith +527=Woobat +528=Swoobat +529=Drilbur +530=Excadrill +531=Audino +532=Timburr +533=Gurdurr +534=Conkeldurr +535=Tympole +536=Palpitoad +537=Seismitoad +538=Throh +539=Sawk +540=Sewaddle +541=Swadloon +542=Leavanny +543=Venipede +544=Whirlipede +545=Scolipede +546=Cottonee +547=Whimsicott +548=Petilil +549=Lilligant +550=Basculin +551=Sandile +552=Krokorok +553=Krookodile +554=Darumaka +555=Darmanitan +556=Maractus +557=Dwebble +558=Crustle +559=Scraggy +560=Scrafty +561=Sigilyph +562=Yamask +563=Cofagrigus +564=Tirtouga +565=Carracosta +566=Archen +567=Archeops +568=Trubbish +569=Garbodor +570=Zorua +571=Zoroark +572=Minccino +573=Cinccino +574=Gothita +575=Gothorita +576=Gothitelle +577=Solosis +578=Duosion +579=Reuniclus +580=Ducklett +581=Swanna +582=Vanillite +583=Vanillish +584=Vanilluxe +585=Deerling +586=Sawsbuck +587=Emolga +588=Karrablast +589=Escavalier +590=Foongus +591=Amoonguss +592=Frillish +593=Jellicent +594=Alomomola +595=Joltik +596=Galvantula +597=Ferroseed +598=Ferrothorn +599=Klink +600=Klang +601=Klinklang +602=Tynamo +603=Eelektrik +604=Eelektross +605=Elgyem +606=Beheeyem +607=Litwick +608=Lampent +609=Chandelure +610=Axew +611=Fraxure +612=Haxorus +613=Cubchoo +614=Beartic +615=Cryogonal +616=Shelmet +617=Accelgor +618=Stunfisk +619=Mienfoo +620=Mienshao +621=Druddigon +622=Golett +623=Golurk +624=Pawniard +625=Bisharp +626=Bouffalant +627=Rufflet +628=Braviary +629=Vullaby +630=Mandibuzz +631=Heatmor +632=Durant +633=Deino +634=Zweilous +635=Hydreigon +636=Larvesta +637=Volcarona +638=Cobalion +639=Terrakion +640=Virizion +641=Tornadus +642=Thundurus +643=Reshiram +644=Zekrom +645=Landorus +646=Kyurem +647=Keldeo +648=Meloetta +649=Genesect +650=Chespin +651=Quilladin +652=Chesnaught +653=Fennekin +654=Braixen +655=Delphox +656=Froakie +657=Frogadier +658=Greninja +659=Bunnelby +660=Diggersby +661=Fletchling +662=Fletchinder +663=Talonflame +664=Scatterbug +665=Spewpa +666=Vivillon +667=Litleo +668=Pyroar +669=Flabébé +670=Floette +671=Florges +672=Skiddo +673=Gogoat +674=Pancham +675=Pangoro +676=Furfrou +677=Espurr +678=Meowstic +679=Honedge +680=Doublade +681=Aegislash +682=Spritzee +683=Aromatisse +684=Swirlix +685=Slurpuff +686=Inkay +687=Malamar +688=Binacle +689=Barbaracle +690=Skrelp +691=Dragalge +692=Clauncher +693=Clawitzer +694=Helioptile +695=Heliolisk +696=Tyrunt +697=Tyrantrum +698=Amaura +699=Aurorus +700=Sylveon +701=Hawlucha +702=Dedenne +703=Carbink +704=Goomy +705=Sliggoo +706=Goodra +707=Klefki +708=Phantump +709=Trevenant +710=Pumpkaboo +711=Gourgeist +712=Bergmite +713=Avalugg +714=Noibat +715=Noivern +716=Xerneas +717=Yveltal +718=Zygarde +719=Diancie +720=Hoopa +721=Volcanion \ No newline at end of file diff --git a/src/main/resources/pokemon_names_fr.properties b/src/main/resources/pokemon_names_fr.properties new file mode 100644 index 00000000..9125f093 --- /dev/null +++ b/src/main/resources/pokemon_names_fr.properties @@ -0,0 +1,721 @@ +1=Bulbizarre +2=Herbizarre +3=Florizarre +4=Salamèche +5=Reptincel +6=Dracaufeu +7=Carapuce +8=Carabaffe +9=Tortank +10=Chenipan +11=Chrysacier +12=Papilusion +13=Aspicot +14=Coconfort +15=Dardargnan +16=Roucool +17=Roucoups +18=Roucarnage +19=Rattata +20=Rattatac +21=Piafabec +22=Rapasdepic +23=Abo +24=Arbok +25=Pikachu +26=Raichu +27=Sabelette +28=Sablaireau +29=Nidoran♀ +30=Nidorina +31=Nidoqueen +32=Nidoran♂ +33=Nidorino +34=Nidoking +35=Mélofée +36=Mélodelfe +37=Goupix +38=Feunard +39=Rondoudou +40=Grodoudou +41=Nosferapti +42=Nosferalto +43=Mystherbe +44=Ortide +45=Rafflesia +46=Paras +47=Parasect +48=Mimitoss +49=Aéromite +50=Taupiqueur +51=Triopikeur +52=Miaouss +53=Persian +54=Psykokwak +55=Akwakwak +56=Férosinge +57=Colossinge +58=Caninos +59=Arcanin +60=Ptitard +61=Têtarte +62=Tartard +63=Abra +64=Kadabra +65=Alakazam +66=Machoc +67=Machopeur +68=Mackogneur +69=Chétiflor +70=Boustiflor +71=Empiflor +72=Tentacool +73=Tentacruel +74=Racaillou +75=Gravalanch +76=Grolem +77=Ponyta +78=Galopa +79=Ramoloss +80=Flagadoss +81=Magnéti +82=Magnéton +83=Canarticho +84=Doduo +85=Dodrio +86=Otaria +87=Lamantine +88=Tadmorv +89=Grotadmorv +90=Kokiyas +91=Crustabri +92=Fantominus +93=Spectrum +94=Ectoplasma +95=Onix +96=Soporifik +97=Hypnomade +98=Krabby +99=Krabboss +100=Voltorbe +101=Électrode +102=Nœunœuf +103=Noadkoko +104=Osselait +105=Ossatueur +106=Kicklee +107=Tygnon +108=Excelangue +109=Smogo +110=Smogogo +111=Rhinocorne +112=Rhinoféros +113=Leveinard +114=Saquedeneu +115=Kangourex +116=Hypotrempe +117=Hypocéan +118=Poissirène +119=Poissoroy +120=Stari +121=Staross +122=M.Mime +123=Insécateur +124=Lippoutou +125=Élektek +126=Magmar +127=Scarabrute +128=Tauros +129=Magicarpe +130=Léviator +131=Lokhlass +132=Métamorph +133=Évoli +134=Aquali +135=Voltali +136=Pyroli +137=Porygon +138=Amonita +139=Amonistar +140=Kabuto +141=Kabutops +142=Ptéra +143=Ronflex +144=Artikodin +145=Électhor +146=Sulfura +147=Minidraco +148=Draco +149=Dracolosse +150=Mewtwo +151=Mew +152=Germignon +153=Macronium +154=Méganium +155=Héricendre +156=Feurisson +157=Typhlosion +158=Kaiminus +159=Crocrodil +160=Aligatueur +161=Fouinette +162=Fouinar +163=Hoothoot +164=Noarfang +165=Coxy +166=Coxyclaque +167=Mimigal +168=Migalos +169=Nostenfer +170=Loupio +171=Lanturn +172=Pichu +173=Mélo +174=Toudoudou +175=Togepi +176=Togetic +177=Natu +178=Xatu +179=Wattouat +180=Lainergie +181=Pharamp +182=Joliflor +183=Marill +184=Azumarill +185=Simularbre +186=Tarpaud +187=Granivol +188=Floravol +189=Cotovol +190=Capumain +191=Tournegrin +192=Héliatronc +193=Yanma +194=Axoloto +195=Maraiste +196=Mentali +197=Noctali +198=Cornèbre +199=Roigada +200=Feuforêve +201=Zarbi +202=Qulbutoké +203=Girafarig +204=Pomdepic +205=Foretress +206=Insolourdo +207=Scorplane +208=Steelix +209=Snubbull +210=Granbull +211=Qwilfish +212=Cizayox +213=Caratroc +214=Scarhino +215=Farfuret +216=Teddiursa +217=Ursaring +218=Limagma +219=Volcaropod +220=Marcacrin +221=Cochignon +222=Corayon +223=Rémoraid +224=Octillery +225=Cadoizo +226=Démanta +227=Airmure +228=Malosse +229=Démolosse +230=Hyporoi +231=Phanpy +232=Donphan +233=Porygon2 +234=Cerfrousse +235=Queulorior +236=Debugant +237=Kapoera +238=Lippouti +239=Élekid +240=Magby +241=Écrémeuh +242=Leuphorie +243=Raikou +244=Entei +245=Suicune +246=Embrylex +247=Ymphect +248=Tyranocif +249=Lugia +250=Ho-Oh +251=Celebi +252=Arcko +253=Massko +254=Jungko +255=Poussifeu +256=Galifeu +257=Braségali +258=Gobou +259=Flobio +260=Laggron +261=Medhyèna +262=Grahyèna +263=Zigzaton +264=Linéon +265=Chenipotte +266=Armulys +267=Charmillon +268=Blindalys +269=Papinox +270=Nénupiot +271=Lombre +272=Ludicolo +273=Grainipiot +274=Pifeuil +275=Tengalice +276=Nirondelle +277=Hélédelle +278=Goélise +279=Bekipan +280=Tarsal +281=Kirlia +282=Gardevoir +283=Arakdo +284=Maskadra +285=Balignon +286=Chapignon +287=Parecool +288=Vigoroth +289=Monaflèmit +290=Ningale +291=Ninjask +292=Munja +293=Chuchmur +294=Ramboum +295=Brouhabam +296=Makuhita +297=Hariyama +298=Azurill +299=Tarinor +300=Skitty +301=Delcatty +302=Ténéfix +303=Mysdibule +304=Galekid +305=Galegon +306=Galeking +307=Méditikka +308=Charmina +309=Dynavolt +310=Élecsprint +311=Posipi +312=Négapi +313=Muciole +314=Lumivole +315=Rosélia +316=Gloupti +317=Avaltout +318=Carvanha +319=Sharpedo +320=Wailmer +321=Wailord +322=Chamallot +323=Camérupt +324=Chartor +325=Spoink +326=Groret +327=Spinda +328=Kraknoix +329=Vibraninf +330=Libégon +331=Cacnea +332=Cacturne +333=Tylton +334=Altaria +335=Mangriff +336=Séviper +337=Séléroc +338=Solaroc +339=Barloche +340=Barbicha +341=Écrapince +342=Colhomard +343=Balbuto +344=Kaorine +345=Lilia +346=Vacilys +347=Anorith +348=Armaldo +349=Barpau +350=Milobellus +351=Morphéo +352=Kecleon +353=Polichombr +354=Branette +355=Skelénox +356=Téraclope +357=Tropius +358=Éoko +359=Absol +360=Okéoké +361=Stalgamin +362=Oniglali +363=Obalie +364=Phogleur +365=Kaimorse +366=Coquiperl +367=Serpang +368=Rosabyss +369=Relicanth +370=Lovdisc +371=Draby +372=Drackhaus +373=Drattak +374=Terhal +375=Métang +376=Métalosse +377=Regirock +378=Regice +379=Registeel +380=Latias +381=Latios +382=Kyogre +383=Groudon +384=Rayquaza +385=Jirachi +386=Deoxys +387=Tortipouss +388=Boskara +389=Torterra +390=Ouisticram +391=Chimpenfeu +392=Simiabraz +393=Tiplouf +394=Prinplouf +395=Pingoléon +396=Étourmi +397=Étourvol +398=Étouraptor +399=Keunotor +400=Castorno +401=Crikzik +402=Mélokrik +403=Lixy +404=Luxio +405=Luxray +406=Rozbouton +407=Roserade +408=Kranidos +409=Charkos +410=Dinoclier +411=Bastiodon +412=Cheniti +413=Cheniselle +414=Papilord +415=Apitrini +416=Apireine +417=Pachirisu +418=Mustébouée +419=Mustéflott +420=Ceribou +421=Ceriflor +422=Sancoki +423=Tritosor +424=Capidextre +425=Baudrive +426=Grodrive +427=Laporeille +428=Lockpin +429=Magirêve +430=Corboss +431=Chaglam +432=Chaffreux +433=Korillon +434=Moufouette +435=Moufflair +436=Archéomire +437=Archéodong +438=Manzaï +439=Mime Jr +440=Ptiravi +441=Pijako +442=Spiritomb +443=Griknot +444=Carmache +445=Carchacrok +446=Goinfrex +447=Riolu +448=Lucario +449=Hippopotas +450=Hippodocus +451=Rapion +452=Drascore +453=Cradopaud +454=Coatox +455=Vortente +456=Écayon +457=Luminéon +458=Babimanta +459=Blizzi +460=Blizzaroi +461=Dimoret +462=Magnézone +463=Coudlangue +464=Rhinastoc +465=Bouldeneu +466=Élekable +467=Maganon +468=Togekiss +469=Yanméga +470=Phyllali +471=Givrali +472=Scorvol +473=Mammochon +474=Porygon-Z +475=Gallame +476=Tarinorme +477=Noctunoir +478=Momartik +479=Motisma +480=Créhelf +481=Créfollet +482=Créfadet +483=Dialga +484=Palkia +485=Heatran +486=Regigigas +487=Giratina +488=Cresselia +489=Phione +490=Manaphy +491=Darkrai +492=Shaymin +493=Arceus +494=Victini +495=Vipélierre +496=Lianaja +497=Majaspic +498=Gruikui +499=Grotichon +500=Roitiflam +501=Moustillon +502=Mateloutre +503=Clamiral +504=Ratentif +505=Miradar +506=Ponchiot +507=Ponchien +508=Mastouffe +509=Chacripan +510=Léopardus +511=Feuillajou +512=Feuiloutan +513=Flamajou +514=Flamoutan +515=Flotajou +516=Flotoutan +517=Munna +518=Mushana +519=Poichigeon +520=Colombeau +521=Déflaisan +522=Zébribon +523=Zéblitz +524=Nodulithe +525=Géolithe +526=Gigalithe +527=Chovsourir +528=Rhinolove +529=Rototaupe +530=Minotaupe +531=Nanméouïe +532=Charpenti +533=Ouvrifier +534=Bétochef +535=Tritonde +536=Batracné +537=Crapustule +538=Judokrak +539=Karaclée +540=Larveyette +541=Couverdure +542=Manternel +543=Venipatte +544=Scobolide +545=Brutapode +546=Doudouvet +547=Farfaduvet +548=Chlorobule +549=Fragilady +550=Bargantua +551=Mascaïman +552=Escroco +553=Crocorible +554=Darumarond +555=Darumacho +556=Maracachi +557=Crabicoque +558=Crabaraque +559=Baggiguane +560=Baggaïd +561=Cryptéro +562=Tutafeh +563=Tutankafer +564=Carapagos +565=Mégapagos +566=Arkéapti +567=Aéroptéryx +568=Miamiasme +569=Miasmax +570=Zorua +571=Zoroark +572=Chinchidou +573=Pashmilla +574=Scrutella +575=Mesmérella +576=Sidérella +577=Nucléos +578=Méios +579=Symbios +580=Couaneton +581=Lakmécygne +582=Sorbébé +583=Sorboul +584=Sorbouboul +585=Vivaldaim +586=Haydaim +587=Emolga +588=Carabing +589=Lançargot +590=Trompignon +591=Gaulet +592=Viskuse +593=Moyade +594=Mamanbo +595=Statitik +596=Mygavolt +597=Grindur +598=Noacier +599=Tic +600=Clic +601=Cliticlic +602=Anchwatt +603=Lampéroie +604=Ohmassacre +605=Lewsor +606=Neitram +607=Funécire +608=Mélancolux +609=Lugulabre +610=Coupenotte +611=Incisache +612=Tranchodon +613=Polarhume +614=Polagriffe +615=Hexagel +616=Escargaume +617=Limaspeed +618=Limonde +619=Kungfouine +620=Shaofouine +621=Drakkarmin +622=Gringolem +623=Golemastoc +624=Scalpion +625=Scalproie +626=Frison +627=Furaiglon +628=Gueriaigle +629=Vostourno +630=Vaututrice +631=Aflamanoir +632=Fermite +633=Solochi +634=Diamat +635=Trioxhydre +636=Pyronille +637=Pyrax +638=Cobaltium +639=Terrakium +640=Viridium +641=Boréas +642=Fulguris +643=Reshiram +644=Zekrom +645=Démétéros +646=Kyurem +647=Keldeo +648=Meloetta +649=Genesect +650=Marisson +651=Boguérisse +652=Blindépique +653=Feunnec +654=Roussil +655=Goupelin +656=Grenousse +657=Croâporal +658=Amphinobi +659=Sapereau +660=Excavarenne +661=Passerouge +662=Braisillon +663=Flambusard +664=Lépidonille +665=Pérégrain +666=Prismillon +667=Hélionceau +668=Némélios +669=Flabébé +670=Floette +671=Florges +672=Cabriolaine +673=Chevroum +674=Pandespiègle +675=Pandarbare +676=Couafarel +677=Psystigri +678=Mistigrix +679=Monorpale +680=Dimoclès +681=Exagide +682=Fluvetin +683=Cocotine +684=Sucroquin +685=Cupcanaille +686=Sepiatop +687=Sepiatroce +688=Opermine +689=Golgopathe +690=Venalgue +691=Kravarech +692=Flingouste +693=Gamblast +694=Galvaran +695=Iguolta +696=Ptyranidur +697=Rexillius +698=Amagara +699=Dragmara +700=Nymphali +701=Brutalibré +702=Dedenne +703=Strassie +704=Mucuscule +705=Colimucus +706=Muplodocus +707=Trousselin +708=Brocélôme +709=Desséliande +710=Pitrouille +711=Banshitrouye +712=Grelaçon +713=Séracrawl +714=Sonistrelle +715=Bruyverne +716=Xerneas +717=Yveltal +718=Zygarde +719=Diancie +720=Hoopa +721=Volcanion \ No newline at end of file diff --git a/src/main/resources/pokemon_names_ja.properties b/src/main/resources/pokemon_names_ja.properties new file mode 100644 index 00000000..b33e4d21 --- /dev/null +++ b/src/main/resources/pokemon_names_ja.properties @@ -0,0 +1,721 @@ +1=\u30D5\u30B7\u30AE\u30C0\u30CD +2=\u30D5\u30B7\u30AE\u30BD\u30A6 +3=\u30D5\u30B7\u30AE\u30D0\u30CA +4=\u30D2\u30C8\u30AB\u30B2 +5=\u30EA\u30B6\u30FC\u30C9 +6=\u30EA\u30B6\u30FC\u30C9\u30F3 +7=\u30BC\u30CB\u30AC\u30E1 +8=\u30AB\u30E1\u30FC\u30EB +9=\u30AB\u30E1\u30C3\u30AF\u30B9 +10=\u30AD\u30E3\u30BF\u30D4\u30FC +11=\u30C8\u30E9\u30F3\u30BB\u30EB +12=\u30D0\u30BF\u30D5\u30EA\u30FC +13=\u30D3\u30FC\u30C9\u30EB +14=\u30B3\u30AF\u30FC\u30F3 +15=\u30B9\u30D4\u30A2\u30FC +16=\u30DD\u30C3\u30DD +17=\u30D4\u30B8\u30E7\u30F3 +18=\u30D4\u30B8\u30E7\u30C3\u30C8 +19=\u30B3\u30E9\u30C3\u30BF +20=\u30E9\u30C3\u30BF +21=\u30AA\u30CB\u30B9\u30BA\u30E1 +22=\u30AA\u30CB\u30C9\u30EA\u30EB +23=\u30A2\u30FC\u30DC +24=\u30A2\u30FC\u30DC\u30C3\u30AF +25=\u30D4\u30AB\u30C1\u30E5\u30A6 +26=\u30E9\u30A4\u30C1\u30E5\u30A6 +27=\u30B5\u30F3\u30C9 +28=\u30B5\u30F3\u30C9\u30D1\u30F3 +29=\u30CB\u30C9\u30E9\u30F3\u2640 +30=\u30CB\u30C9\u30EA\u30FC\u30CA +31=\u30CB\u30C9\u30AF\u30A4\u30F3 +32=\u30CB\u30C9\u30E9\u30F3\u2642 +33=\u30CB\u30C9\u30EA\u30FC\u30CE +34=\u30CB\u30C9\u30AD\u30F3\u30B0 +35=\u30D4\u30C3\u30D4 +36=\u30D4\u30AF\u30B7\u30FC +37=\u30ED\u30B3\u30F3 +38=\u30AD\u30E5\u30A6\u30B3\u30F3 +39=\u30D7\u30EA\u30F3 +40=\u30D7\u30AF\u30EA\u30F3 +41=\u30BA\u30D0\u30C3\u30C8 +42=\u30B4\u30EB\u30D0\u30C3\u30C8 +43=\u30CA\u30BE\u30CE\u30AF\u30B5 +44=\u30AF\u30B5\u30A4\u30CF\u30CA +45=\u30E9\u30D5\u30EC\u30B7\u30A2 +46=\u30D1\u30E9\u30B9 +47=\u30D1\u30E9\u30BB\u30AF\u30C8 +48=\u30B3\u30F3\u30D1\u30F3 +49=\u30E2\u30EB\u30D5\u30A9\u30F3 +50=\u30C7\u30A3\u30B0\u30C0 +51=\u30C0\u30B0\u30C8\u30EA\u30AA +52=\u30CB\u30E3\u30FC\u30B9 +53=\u30DA\u30EB\u30B7\u30A2\u30F3 +54=\u30B3\u30C0\u30C3\u30AF +55=\u30B4\u30EB\u30C0\u30C3\u30AF +56=\u30DE\u30F3\u30AD\u30FC +57=\u30AA\u30B3\u30EA\u30B6\u30EB +58=\u30AC\u30FC\u30C7\u30A3 +59=\u30A6\u30A4\u30F3\u30C7\u30A3 +60=\u30CB\u30E7\u30ED\u30E2 +61=\u30CB\u30E7\u30ED\u30BE +62=\u30CB\u30E7\u30ED\u30DC\u30F3 +63=\u30B1\u30FC\u30B7\u30A3 +64=\u30E6\u30F3\u30B2\u30E9\u30FC +65=\u30D5\u30FC\u30C7\u30A3\u30F3 +66=\u30EF\u30F3\u30EA\u30AD\u30FC +67=\u30B4\u30FC\u30EA\u30AD\u30FC +68=\u30AB\u30A4\u30EA\u30AD\u30FC +69=\u30DE\u30C0\u30C4\u30DC\u30DF +70=\u30A6\u30C4\u30C9\u30F3 +71=\u30A6\u30C4\u30DC\u30C3\u30C8 +72=\u30E1\u30CE\u30AF\u30E9\u30B2 +73=\u30C9\u30AF\u30AF\u30E9\u30B2 +74=\u30A4\u30B7\u30C4\u30D6\u30C6 +75=\u30B4\u30ED\u30FC\u30F3 +76=\u30B4\u30ED\u30FC\u30CB\u30E3 +77=\u30DD\u30CB\u30FC\u30BF +78=\u30AE\u30E3\u30ED\u30C3\u30D7 +79=\u30E4\u30C9\u30F3 +80=\u30E4\u30C9\u30E9\u30F3 +81=\u30B3\u30A4\u30EB +82=\u30EC\u30A2\u30B3\u30A4\u30EB +83=\u30AB\u30E2\u30CD\u30AE +84=\u30C9\u30FC\u30C9\u30FC +85=\u30C9\u30FC\u30C9\u30EA\u30AA +86=\u30D1\u30A6\u30EF\u30A6 +87=\u30B8\u30E5\u30B4\u30F3 +88=\u30D9\u30C8\u30D9\u30BF\u30FC +89=\u30D9\u30C8\u30D9\u30C8\u30F3 +90=\u30B7\u30A7\u30EB\u30C0\u30FC +91=\u30D1\u30EB\u30B7\u30A7\u30F3 +92=\u30B4\u30FC\u30B9 +93=\u30B4\u30FC\u30B9\u30C8 +94=\u30B2\u30F3\u30AC\u30FC +95=\u30A4\u30EF\u30FC\u30AF +96=\u30B9\u30EA\u30FC\u30D7 +97=\u30B9\u30EA\u30FC\u30D1\u30FC +98=\u30AF\u30E9\u30D6 +99=\u30AD\u30F3\u30B0\u30E9\u30FC +100=\u30D3\u30EA\u30EA\u30C0\u30DE +101=\u30DE\u30EB\u30DE\u30A4\u30F3 +102=\u30BF\u30DE\u30BF\u30DE +103=\u30CA\u30C3\u30B7\u30FC +104=\u30AB\u30E9\u30AB\u30E9 +105=\u30AC\u30E9\u30AC\u30E9 +106=\u30B5\u30EF\u30E0\u30E9\u30FC +107=\u30A8\u30D3\u30EF\u30E9\u30FC +108=\u30D9\u30ED\u30EA\u30F3\u30AC +109=\u30C9\u30AC\u30FC\u30B9 +110=\u30DE\u30BF\u30C9\u30AC\u30B9 +111=\u30B5\u30A4\u30DB\u30FC\u30F3 +112=\u30B5\u30A4\u30C9\u30F3 +113=\u30E9\u30C3\u30AD\u30FC +114=\u30E2\u30F3\u30B8\u30E3\u30E9 +115=\u30AC\u30EB\u30FC\u30E9 +116=\u30BF\u30C3\u30C4\u30FC +117=\u30B7\u30FC\u30C9\u30E9 +118=\u30C8\u30B5\u30AD\u30F3\u30C8 +119=\u30A2\u30BA\u30DE\u30AA\u30A6 +120=\u30D2\u30C8\u30C7\u30DE\u30F3 +121=\u30B9\u30BF\u30FC\u30DF\u30FC +122=\u30D0\u30EA\u30E4\u30FC\u30C9 +123=\u30B9\u30C8\u30E9\u30A4\u30AF +124=\u30EB\u30FC\u30B8\u30E5\u30E9 +125=\u30A8\u30EC\u30D6\u30FC +126=\u30D6\u30FC\u30D0\u30FC +127=\u30AB\u30A4\u30ED\u30B9 +128=\u30B1\u30F3\u30BF\u30ED\u30B9 +129=\u30B3\u30A4\u30AD\u30F3\u30B0 +130=\u30AE\u30E3\u30E9\u30C9\u30B9 +131=\u30E9\u30D7\u30E9\u30B9 +132=\u30E1\u30BF\u30E2\u30F3 +133=\u30A4\u30FC\u30D6\u30A4 +134=\u30B7\u30E3\u30EF\u30FC\u30BA +135=\u30B5\u30F3\u30C0\u30FC\u30B9 +136=\u30D6\u30FC\u30B9\u30BF\u30FC +137=\u30DD\u30EA\u30B4\u30F3 +138=\u30AA\u30E0\u30CA\u30A4\u30C8 +139=\u30AA\u30E0\u30B9\u30BF\u30FC +140=\u30AB\u30D6\u30C8 +141=\u30AB\u30D6\u30C8\u30D7\u30B9 +142=\u30D7\u30C6\u30E9 +143=\u30AB\u30D3\u30B4\u30F3 +144=\u30D5\u30EA\u30FC\u30B6\u30FC +145=\u30B5\u30F3\u30C0\u30FC +146=\u30D5\u30A1\u30A4\u30E4\u30FC +147=\u30DF\u30CB\u30EA\u30E5\u30A6 +148=\u30CF\u30AF\u30EA\u30E5\u30FC +149=\u30AB\u30A4\u30EA\u30E5\u30FC +150=\u30DF\u30E5\u30A6\u30C4\u30FC +151=\u30DF\u30E5\u30A6 +152=\u30C1\u30B3\u30EA\u30FC\u30BF +153=\u30D9\u30A4\u30EA\u30FC\u30D5 +154=\u30E1\u30AC\u30CB\u30A6\u30E0 +155=\u30D2\u30CE\u30A2\u30E9\u30B7 +156=\u30DE\u30B0\u30DE\u30E9\u30B7 +157=\u30D0\u30AF\u30D5\u30FC\u30F3 +158=\u30EF\u30CB\u30CE\u30B3 +159=\u30A2\u30EA\u30B2\u30A4\u30C4 +160=\u30AA\u30FC\u30C0\u30A4\u30EB +161=\u30AA\u30BF\u30C1 +162=\u30AA\u30AA\u30BF\u30C1 +163=\u30DB\u30FC\u30DB\u30FC +164=\u30E8\u30EB\u30CE\u30BA\u30AF +165=\u30EC\u30C7\u30A3\u30D0 +166=\u30EC\u30C7\u30A3\u30A2\u30F3 +167=\u30A4\u30C8\u30DE\u30EB +168=\u30A2\u30EA\u30A2\u30C9\u30B9 +169=\u30AF\u30ED\u30D0\u30C3\u30C8 +170=\u30C1\u30E7\u30F3\u30C1\u30FC +171=\u30E9\u30F3\u30BF\u30FC\u30F3 +172=\u30D4\u30C1\u30E5\u30FC +173=\u30D4\u30A3 +174=\u30D7\u30D7\u30EA\u30F3 +175=\u30C8\u30B2\u30D4\u30FC +176=\u30C8\u30B2\u30C1\u30C3\u30AF +177=\u30CD\u30A4\u30C6\u30A3 +178=\u30CD\u30A4\u30C6\u30A3\u30AA +179=\u30E1\u30EA\u30FC\u30D7 +180=\u30E2\u30B3\u30B3 +181=\u30C7\u30F3\u30EA\u30E5\u30A6 +182=\u30AD\u30EC\u30A4\u30CF\u30CA +183=\u30DE\u30EA\u30EB +184=\u30DE\u30EA\u30EB\u30EA +185=\u30A6\u30BD\u30C3\u30AD\u30FC +186=\u30CB\u30E7\u30ED\u30C8\u30CE +187=\u30CF\u30CD\u30C3\u30B3 +188=\u30DD\u30DD\u30C3\u30B3 +189=\u30EF\u30BF\u30C3\u30B3 +190=\u30A8\u30A4\u30D1\u30E0 +191=\u30D2\u30DE\u30CA\u30C3\u30C4 +192=\u30AD\u30DE\u30EF\u30EA +193=\u30E4\u30F3\u30E4\u30F3\u30DE +194=\u30A6\u30D1\u30FC +195=\u30CC\u30AA\u30FC +196=\u30A8\u30FC\u30D5\u30A3 +197=\u30D6\u30E9\u30C3\u30AD\u30FC +198=\u30E4\u30DF\u30AB\u30E9\u30B9 +199=\u30E4\u30C9\u30AD\u30F3\u30B0 +200=\u30E0\u30A6\u30DE +201=\u30A2\u30F3\u30CE\u30FC\u30F3 +202=\u30BD\u30FC\u30CA\u30F3\u30B9 +203=\u30AD\u30EA\u30F3\u30EA\u30AD +204=\u30AF\u30CC\u30AE\u30C0\u30DE +205=\u30D5\u30A9\u30EC\u30C8\u30B9 +206=\u30CE\u30B3\u30C3\u30C1 +207=\u30B0\u30E9\u30A4\u30AC\u30FC +208=\u30CF\u30AC\u30CD\u30FC\u30EB +209=\u30D6\u30EB\u30FC +210=\u30B0\u30E9\u30F3\u30D6\u30EB +211=\u30CF\u30EA\u30FC\u30BB\u30F3 +212=\u30CF\u30C3\u30B5\u30E0 +213=\u30C4\u30DC\u30C4\u30DC +214=\u30D8\u30E9\u30AF\u30ED\u30B9 +215=\u30CB\u30E5\u30FC\u30E9 +216=\u30D2\u30E1\u30B0\u30DE +217=\u30EA\u30F3\u30B0\u30DE +218=\u30DE\u30B0\u30DE\u30C3\u30B0 +219=\u30DE\u30B0\u30AB\u30EB\u30B4 +220=\u30A6\u30EA\u30E0\u30FC +221=\u30A4\u30CE\u30E0\u30FC +222=\u30B5\u30CB\u30FC\u30B4 +223=\u30C6\u30C3\u30DD\u30A6\u30AA +224=\u30AA\u30AF\u30BF\u30F3 +225=\u30C7\u30EA\u30D0\u30FC\u30C9 +226=\u30DE\u30F3\u30BF\u30A4\u30F3 +227=\u30A8\u30A2\u30FC\u30E0\u30C9 +228=\u30C7\u30EB\u30D3\u30EB +229=\u30D8\u30EB\u30AC\u30FC +230=\u30AD\u30F3\u30B0\u30C9\u30E9 +231=\u30B4\u30DE\u30BE\u30A6 +232=\u30C9\u30F3\u30D5\u30A1\u30F3 +233=\u30DD\u30EA\u30B4\u30F3\uFF12 +234=\u30AA\u30C9\u30B7\u30B7 +235=\u30C9\u30FC\u30D6\u30EB +236=\u30D0\u30EB\u30AD\u30FC +237=\u30AB\u30DD\u30A8\u30E9\u30FC +238=\u30E0\u30C1\u30E5\u30FC\u30EB +239=\u30A8\u30EC\u30AD\u30C3\u30C9 +240=\u30D6\u30D3\u30A3 +241=\u30DF\u30EB\u30BF\u30F3\u30AF +242=\u30CF\u30D4\u30CA\u30B9 +243=\u30E9\u30A4\u30B3\u30A6 +244=\u30A8\u30F3\u30C6\u30A4 +245=\u30B9\u30A4\u30AF\u30F3 +246=\u30E8\u30FC\u30AE\u30E9\u30B9 +247=\u30B5\u30CA\u30AE\u30E9\u30B9 +248=\u30D0\u30F3\u30AE\u30E9\u30B9 +249=\u30EB\u30AE\u30A2 +250=\u30DB\u30A6\u30AA\u30A6 +251=\u30BB\u30EC\u30D3\u30A3 +252=\u30AD\u30E2\u30EA +253=\u30B8\u30E5\u30D7\u30C8\u30EB +254=\u30B8\u30E5\u30AB\u30A4\u30F3 +255=\u30A2\u30C1\u30E3\u30E2 +256=\u30EF\u30AB\u30B7\u30E3\u30E2 +257=\u30D0\u30B7\u30E3\u30FC\u30E2 +258=\u30DF\u30BA\u30B4\u30ED\u30A6 +259=\u30CC\u30DE\u30AF\u30ED\u30FC +260=\u30E9\u30B0\u30E9\u30FC\u30B8 +261=\u30DD\u30C1\u30A8\u30CA +262=\u30B0\u30E9\u30A8\u30CA +263=\u30B8\u30B0\u30B6\u30B0\u30DE +264=\u30DE\u30C3\u30B9\u30B0\u30DE +265=\u30B1\u30E0\u30C3\u30BD +266=\u30AB\u30E9\u30B5\u30EA\u30B9 +267=\u30A2\u30B2\u30CF\u30F3\u30C8 +268=\u30DE\u30E6\u30EB\u30C9 +269=\u30C9\u30AF\u30B1\u30A4\u30EB +270=\u30CF\u30B9\u30DC\u30FC +271=\u30CF\u30B9\u30D6\u30EC\u30ED +272=\u30EB\u30F3\u30D1\u30C3\u30D1 +273=\u30BF\u30CD\u30DC\u30FC +274=\u30B3\u30CE\u30CF\u30CA +275=\u30C0\u30FC\u30C6\u30F3\u30B0 +276=\u30B9\u30D0\u30E1 +277=\u30AA\u30AA\u30B9\u30D0\u30E1 +278=\u30AD\u30E3\u30E2\u30E1 +279=\u30DA\u30EA\u30C3\u30D1\u30FC +280=\u30E9\u30EB\u30C8\u30B9 +281=\u30AD\u30EB\u30EA\u30A2 +282=\u30B5\u30FC\u30CA\u30A4\u30C8 +283=\u30A2\u30E1\u30BF\u30DE +284=\u30A2\u30E1\u30E2\u30FC\u30B9 +285=\u30AD\u30CE\u30B3\u30B3 +286=\u30AD\u30CE\u30AC\u30C3\u30B5 +287=\u30CA\u30DE\u30B1\u30ED +288=\u30E4\u30EB\u30AD\u30E2\u30CE +289=\u30B1\u30C3\u30AD\u30F3\u30B0 +290=\u30C4\u30C1\u30CB\u30F3 +291=\u30C6\u30C3\u30AB\u30CB\u30F3 +292=\u30CC\u30B1\u30CB\u30F3 +293=\u30B4\u30CB\u30E7\u30CB\u30E7 +294=\u30C9\u30B4\u30FC\u30E0 +295=\u30D0\u30AF\u30AA\u30F3\u30B0 +296=\u30DE\u30AF\u30CE\u30B7\u30BF +297=\u30CF\u30EA\u30C6\u30E4\u30DE +298=\u30EB\u30EA\u30EA +299=\u30CE\u30BA\u30D1\u30B9 +300=\u30A8\u30CD\u30B3 +301=\u30A8\u30CD\u30B3\u30ED\u30ED +302=\u30E4\u30DF\u30E9\u30DF +303=\u30AF\u30C1\u30FC\u30C8 +304=\u30B3\u30B3\u30C9\u30E9 +305=\u30B3\u30C9\u30E9 +306=\u30DC\u30B9\u30B4\u30C9\u30E9 +307=\u30A2\u30B5\u30CA\u30F3 +308=\u30C1\u30E3\u30FC\u30EC\u30E0 +309=\u30E9\u30AF\u30E9\u30A4 +310=\u30E9\u30A4\u30DC\u30EB\u30C8 +311=\u30D7\u30E9\u30B9\u30EB +312=\u30DE\u30A4\u30CA\u30F3 +313=\u30D0\u30EB\u30D3\u30FC\u30C8 +314=\u30A4\u30EB\u30DF\u30FC\u30BC +315=\u30ED\u30BC\u30EA\u30A2 +316=\u30B4\u30AF\u30EA\u30F3 +317=\u30DE\u30EB\u30CE\u30FC\u30E0 +318=\u30AD\u30D0\u30CB\u30A2 +319=\u30B5\u30E1\u30CF\u30C0\u30FC +320=\u30DB\u30A8\u30EB\u30B3 +321=\u30DB\u30A8\u30EB\u30AA\u30FC +322=\u30C9\u30F3\u30E1\u30EB +323=\u30D0\u30AF\u30FC\u30C0 +324=\u30B3\u30FC\u30BF\u30B9 +325=\u30D0\u30CD\u30D6\u30FC +326=\u30D6\u30FC\u30D4\u30C3\u30B0 +327=\u30D1\u30C3\u30C1\u30FC\u30EB +328=\u30CA\u30C3\u30AF\u30E9\u30FC +329=\u30D3\u30D6\u30E9\u30FC\u30D0 +330=\u30D5\u30E9\u30A4\u30B4\u30F3 +331=\u30B5\u30DC\u30CD\u30A2 +332=\u30CE\u30AF\u30BF\u30B9 +333=\u30C1\u30EB\u30C3\u30C8 +334=\u30C1\u30EB\u30BF\u30EA\u30B9 +335=\u30B6\u30F3\u30B0\u30FC\u30B9 +336=\u30CF\u30D6\u30CD\u30FC\u30AF +337=\u30EB\u30CA\u30C8\u30FC\u30F3 +338=\u30BD\u30EB\u30ED\u30C3\u30AF +339=\u30C9\u30B8\u30E7\u30C3\u30C1 +340=\u30CA\u30DE\u30BA\u30F3 +341=\u30D8\u30A4\u30AC\u30CB +342=\u30B7\u30B6\u30EA\u30AC\u30FC +343=\u30E4\u30B8\u30ED\u30F3 +344=\u30CD\u30F3\u30C9\u30FC\u30EB +345=\u30EA\u30EA\u30FC\u30E9 +346=\u30E6\u30EC\u30A4\u30C9\u30EB +347=\u30A2\u30CE\u30D7\u30B9 +348=\u30A2\u30FC\u30DE\u30EB\u30C9 +349=\u30D2\u30F3\u30D0\u30B9 +350=\u30DF\u30ED\u30AB\u30ED\u30B9 +351=\u30DD\u30EF\u30EB\u30F3 +352=\u30AB\u30AF\u30EC\u30AA\u30F3 +353=\u30AB\u30B2\u30DC\u30A6\u30BA +354=\u30B8\u30E5\u30DA\u30C3\u30BF +355=\u30E8\u30DE\u30EF\u30EB +356=\u30B5\u30DE\u30E8\u30FC\u30EB +357=\u30C8\u30ED\u30D4\u30A6\u30B9 +358=\u30C1\u30EA\u30FC\u30F3 +359=\u30A2\u30D6\u30BD\u30EB +360=\u30BD\u30FC\u30CA\u30CE +361=\u30E6\u30AD\u30EF\u30E9\u30B7 +362=\u30AA\u30CB\u30B4\u30FC\u30EA +363=\u30BF\u30DE\u30B6\u30E9\u30B7 +364=\u30C8\u30C9\u30B0\u30E9\u30FC +365=\u30C8\u30C9\u30BC\u30EB\u30AC +366=\u30D1\u30FC\u30EB\u30EB +367=\u30CF\u30F3\u30C6\u30FC\u30EB +368=\u30B5\u30AF\u30E9\u30D3\u30B9 +369=\u30B8\u30FC\u30E9\u30F3\u30B9 +370=\u30E9\u30D6\u30AB\u30B9 +371=\u30BF\u30C4\u30D9\u30A4 +372=\u30B3\u30E2\u30EB\u30FC +373=\u30DC\u30FC\u30DE\u30F3\u30C0 +374=\u30C0\u30F3\u30D0\u30EB +375=\u30E1\u30BF\u30F3\u30B0 +376=\u30E1\u30BF\u30B0\u30ED\u30B9 +377=\u30EC\u30B8\u30ED\u30C3\u30AF +378=\u30EC\u30B8\u30A2\u30A4\u30B9 +379=\u30EC\u30B8\u30B9\u30C1\u30EB +380=\u30E9\u30C6\u30A3\u30A2\u30B9 +381=\u30E9\u30C6\u30A3\u30AA\u30B9 +382=\u30AB\u30A4\u30AA\u30FC\u30AC +383=\u30B0\u30E9\u30FC\u30C9\u30F3 +384=\u30EC\u30C3\u30AF\u30A6\u30B6 +385=\u30B8\u30E9\u30FC\u30C1 +386=\u30C7\u30AA\u30AD\u30B7\u30B9 +387=\u30CA\u30A8\u30C8\u30EB +388=\u30CF\u30E4\u30B7\u30AC\u30E1 +389=\u30C9\u30C0\u30A4\u30C8\u30B9 +390=\u30D2\u30B3\u30B6\u30EB +391=\u30E2\u30A6\u30AB\u30B6\u30EB +392=\u30B4\u30A6\u30AB\u30B6\u30EB +393=\u30DD\u30C3\u30C1\u30E3\u30DE +394=\u30DD\u30C3\u30BF\u30A4\u30B7 +395=\u30A8\u30F3\u30DA\u30EB\u30C8 +396=\u30E0\u30C3\u30AF\u30EB +397=\u30E0\u30AF\u30D0\u30FC\u30C9 +398=\u30E0\u30AF\u30DB\u30FC\u30AF +399=\u30D3\u30C3\u30D1 +400=\u30D3\u30FC\u30C0\u30EB +401=\u30B3\u30ED\u30DC\u30FC\u30B7 +402=\u30B3\u30ED\u30C8\u30C3\u30AF +403=\u30B3\u30EA\u30F3\u30AF +404=\u30EB\u30AF\u30B7\u30AA +405=\u30EC\u30F3\u30C8\u30E9\u30FC +406=\u30B9\u30DC\u30DF\u30FC +407=\u30ED\u30BA\u30EC\u30A4\u30C9 +408=\u30BA\u30AC\u30A4\u30C9\u30B9 +409=\u30E9\u30E0\u30D1\u30EB\u30C9 +410=\u30BF\u30C6\u30C8\u30D7\u30B9 +411=\u30C8\u30EA\u30C7\u30D7\u30B9 +412=\u30DF\u30CE\u30E0\u30C3\u30C1 +413=\u30DF\u30CE\u30DE\u30C0\u30E0 +414=\u30AC\u30FC\u30E1\u30A4\u30EB +415=\u30DF\u30C4\u30CF\u30CB\u30FC +416=\u30D3\u30FC\u30AF\u30A4\u30F3 +417=\u30D1\u30C1\u30EA\u30B9 +418=\u30D6\u30A4\u30BC\u30EB +419=\u30D5\u30ED\u30FC\u30BC\u30EB +420=\u30C1\u30A7\u30EA\u30F3\u30DC +421=\u30C1\u30A7\u30EA\u30E0 +422=\u30AB\u30E9\u30CA\u30AF\u30B7 +423=\u30C8\u30EA\u30C8\u30C9\u30F3 +424=\u30A8\u30C6\u30DC\u30FC\u30B9 +425=\u30D5\u30EF\u30F3\u30C6 +426=\u30D5\u30EF\u30E9\u30A4\u30C9 +427=\u30DF\u30DF\u30ED\u30EB +428=\u30DF\u30DF\u30ED\u30C3\u30D7 +429=\u30E0\u30A6\u30DE\u30FC\u30B8 +430=\u30C9\u30F3\u30AB\u30E9\u30B9 +431=\u30CB\u30E3\u30EB\u30DE\u30FC +432=\u30D6\u30CB\u30E3\u30C3\u30C8 +433=\u30EA\u30FC\u30B7\u30E3\u30F3 +434=\u30B9\u30AB\u30F3\u30D7\u30FC +435=\u30B9\u30AB\u30BF\u30F3\u30AF +436=\u30C9\u30FC\u30DF\u30E9\u30FC +437=\u30C9\u30FC\u30BF\u30AF\u30F3 +438=\u30A6\u30BD\u30CF\u30C1 +439=\u30DE\u30CD\u30CD +440=\u30D4\u30F3\u30D7\u30AF +441=\u30DA\u30E9\u30C3\u30D7 +442=\u30DF\u30AB\u30EB\u30B2 +443=\u30D5\u30AB\u30DE\u30EB +444=\u30AC\u30D0\u30A4\u30C8 +445=\u30AC\u30D6\u30EA\u30A2\u30B9 +446=\u30B4\u30F3\u30D9 +447=\u30EA\u30AA\u30EB +448=\u30EB\u30AB\u30EA\u30AA +449=\u30D2\u30DD\u30DD\u30BF\u30B9 +450=\u30AB\u30D0\u30EB\u30C9\u30F3 +451=\u30B9\u30B3\u30EB\u30D4 +452=\u30C9\u30E9\u30D4\u30AA\u30F3 +453=\u30B0\u30EC\u30C3\u30B0\u30EB +454=\u30C9\u30AF\u30ED\u30C3\u30B0 +455=\u30DE\u30B9\u30AD\u30C3\u30D1 +456=\u30B1\u30A4\u30B3\u30A6\u30AA +457=\u30CD\u30AA\u30E9\u30F3\u30C8 +458=\u30BF\u30DE\u30F3\u30BF +459=\u30E6\u30AD\u30AB\u30D6\u30EA +460=\u30E6\u30AD\u30CE\u30AA\u30FC +461=\u30DE\u30CB\u30E5\u30FC\u30E9 +462=\u30B8\u30D0\u30B3\u30A4\u30EB +463=\u30D9\u30ED\u30D9\u30EB\u30C8 +464=\u30C9\u30B5\u30A4\u30C9\u30F3 +465=\u30E2\u30B8\u30E3\u30F3\u30DC +466=\u30A8\u30EC\u30AD\u30D6\u30EB +467=\u30D6\u30FC\u30D0\u30FC\u30F3 +468=\u30C8\u30B2\u30AD\u30C3\u30B9 +469=\u30E1\u30AC\u30E4\u30F3\u30DE +470=\u30EA\u30FC\u30D5\u30A3\u30A2 +471=\u30B0\u30EC\u30A4\u30B7\u30A2 +472=\u30B0\u30E9\u30A4\u30AA\u30F3 +473=\u30DE\u30F3\u30E0\u30FC +474=\u30DD\u30EA\u30B4\u30F3\uFF3A +475=\u30A8\u30EB\u30EC\u30A4\u30C9 +476=\u30C0\u30A4\u30CE\u30FC\u30BA +477=\u30E8\u30CE\u30EF\u30FC\u30EB +478=\u30E6\u30AD\u30E1\u30CE\u30B3 +479=\u30ED\u30C8\u30E0 +480=\u30E6\u30AF\u30B7\u30FC +481=\u30A8\u30E0\u30EA\u30C3\u30C8 +482=\u30A2\u30B0\u30CE\u30E0 +483=\u30C7\u30A3\u30A2\u30EB\u30AC +484=\u30D1\u30EB\u30AD\u30A2 +485=\u30D2\u30FC\u30C9\u30E9\u30F3 +486=\u30EC\u30B8\u30AE\u30AC\u30B9 +487=\u30AE\u30E9\u30C6\u30A3\u30CA +488=\u30AF\u30EC\u30BB\u30EA\u30A2 +489=\u30D5\u30A3\u30AA\u30CD +490=\u30DE\u30CA\u30D5\u30A3 +491=\u30C0\u30FC\u30AF\u30E9\u30A4 +492=\u30B7\u30A7\u30A4\u30DF +493=\u30A2\u30EB\u30BB\u30A6\u30B9 +494=\u30D3\u30AF\u30C6\u30A3\u30CB +495=\u30C4\u30BF\u30FC\u30B8\u30E3 +496=\u30B8\u30E3\u30CE\u30D3\u30FC +497=\u30B8\u30E3\u30ED\u30FC\u30C0 +498=\u30DD\u30AB\u30D6 +499=\u30C1\u30E3\u30AA\u30D6\u30FC +500=\u30A8\u30F3\u30D6\u30AA\u30FC +501=\u30DF\u30B8\u30E5\u30DE\u30EB +502=\u30D5\u30BF\u30C1\u30DE\u30EB +503=\u30C0\u30A4\u30B1\u30F3\u30AD +504=\u30DF\u30CD\u30BA\u30DF +505=\u30DF\u30EB\u30DB\u30C3\u30B0 +506=\u30E8\u30FC\u30C6\u30EA\u30FC +507=\u30CF\u30FC\u30C7\u30EA\u30A2 +508=\u30E0\u30FC\u30E9\u30F3\u30C9 +509=\u30C1\u30E7\u30ED\u30CD\u30B3 +510=\u30EC\u30D1\u30EB\u30C0\u30B9 +511=\u30E4\u30CA\u30C3\u30D7 +512=\u30E4\u30CA\u30C3\u30AD\u30FC +513=\u30D0\u30AA\u30C3\u30D7 +514=\u30D0\u30AA\u30C3\u30AD\u30FC +515=\u30D2\u30E4\u30C3\u30D7 +516=\u30D2\u30E4\u30C3\u30AD\u30FC +517=\u30E0\u30F3\u30CA +518=\u30E0\u30B7\u30E3\u30FC\u30CA +519=\u30DE\u30E1\u30D1\u30C8 +520=\u30CF\u30C8\u30FC\u30DC\u30FC +521=\u30B1\u30F3\u30DB\u30ED\u30A6 +522=\u30B7\u30DE\u30DE +523=\u30BC\u30D6\u30E9\u30A4\u30AB +524=\u30C0\u30F3\u30B4\u30ED +525=\u30AC\u30F3\u30C8\u30EB +526=\u30AE\u30AC\u30A4\u30A2\u30B9 +527=\u30B3\u30ED\u30E2\u30EA +528=\u30B3\u30B3\u30ED\u30E2\u30EA +529=\u30E2\u30B0\u30EA\u30E5\u30FC +530=\u30C9\u30EA\u30E5\u30A6\u30BA +531=\u30BF\u30D6\u30F3\u30CD +532=\u30C9\u30C3\u30B3\u30E9\u30FC +533=\u30C9\u30C6\u30C3\u30B3\u30C4 +534=\u30ED\u30FC\u30D6\u30B7\u30F3 +535=\u30AA\u30BF\u30DE\u30ED +536=\u30AC\u30DE\u30AC\u30EB +537=\u30AC\u30DE\u30B2\u30ED\u30B2 +538=\u30CA\u30B2\u30AD +539=\u30C0\u30B2\u30AD +540=\u30AF\u30EB\u30DF\u30EB +541=\u30AF\u30EB\u30DE\u30E6 +542=\u30CF\u30CF\u30B3\u30E2\u30EA +543=\u30D5\u30B7\u30C7 +544=\u30DB\u30A4\u30FC\u30AC +545=\u30DA\u30F3\u30C9\u30E9\u30FC +546=\u30E2\u30F3\u30E1\u30F3 +547=\u30A8\u30EB\u30D5\u30FC\u30F3 +548=\u30C1\u30E5\u30EA\u30CD +549=\u30C9\u30EC\u30C7\u30A3\u30A2 +550=\u30D0\u30B9\u30E9\u30AA +551=\u30E1\u30B0\u30ED\u30B3 +552=\u30EF\u30EB\u30D3\u30EB +553=\u30EF\u30EB\u30D3\u30A2\u30EB +554=\u30C0\u30EB\u30DE\u30C3\u30AB +555=\u30D2\u30D2\u30C0\u30EB\u30DE +556=\u30DE\u30E9\u30AB\u30C3\u30C1 +557=\u30A4\u30B7\u30BA\u30DE\u30A4 +558=\u30A4\u30EF\u30D1\u30EC\u30B9 +559=\u30BA\u30EB\u30C3\u30B0 +560=\u30BA\u30EB\u30BA\u30AD\u30F3 +561=\u30B7\u30F3\u30DC\u30E9\u30FC +562=\u30C7\u30B9\u30DE\u30B9 +563=\u30C7\u30B9\u30AB\u30FC\u30F3 +564=\u30D7\u30ED\u30C8\u30FC\u30AC +565=\u30A2\u30D0\u30B4\u30FC\u30E9 +566=\u30A2\u30FC\u30B1\u30F3 +567=\u30A2\u30FC\u30B1\u30AA\u30B9 +568=\u30E4\u30D6\u30AF\u30ED\u30F3 +569=\u30C0\u30B9\u30C8\u30C0\u30B9 +570=\u30BE\u30ED\u30A2 +571=\u30BE\u30ED\u30A2\u30FC\u30AF +572=\u30C1\u30E9\u30FC\u30DF\u30A3 +573=\u30C1\u30E9\u30C1\u30FC\u30CE +574=\u30B4\u30C1\u30E0 +575=\u30B4\u30C1\u30DF\u30EB +576=\u30B4\u30C1\u30EB\u30BC\u30EB +577=\u30E6\u30CB\u30E9\u30F3 +578=\u30C0\u30D6\u30E9\u30F3 +579=\u30E9\u30F3\u30AF\u30EB\u30B9 +580=\u30B3\u30A2\u30EB\u30D2\u30FC +581=\u30B9\u30EF\u30F3\u30CA +582=\u30D0\u30CB\u30D7\u30C3\u30C1 +583=\u30D0\u30CB\u30EA\u30C3\u30C1 +584=\u30D0\u30A4\u30D0\u30CB\u30E9 +585=\u30B7\u30AD\u30B8\u30AB +586=\u30E1\u30D6\u30AD\u30B8\u30AB +587=\u30A8\u30E2\u30F3\u30AC +588=\u30AB\u30D6\u30EB\u30E2 +589=\u30B7\u30E5\u30D0\u30EB\u30B4 +590=\u30BF\u30DE\u30B2\u30BF\u30B1 +591=\u30E2\u30ED\u30D0\u30EC\u30EB +592=\u30D7\u30EB\u30EA\u30EB +593=\u30D6\u30EB\u30F3\u30B2\u30EB +594=\u30DE\u30DE\u30F3\u30DC\u30A6 +595=\u30D0\u30C1\u30E5\u30EB +596=\u30C7\u30F3\u30C1\u30E5\u30E9 +597=\u30C6\u30C3\u30B7\u30FC\u30C9 +598=\u30CA\u30C3\u30C8\u30EC\u30A4 +599=\u30AE\u30A2\u30EB +600=\u30AE\u30AE\u30A2\u30EB +601=\u30AE\u30AE\u30AE\u30A2\u30EB +602=\u30B7\u30D3\u30B7\u30E9\u30B9 +603=\u30B7\u30D3\u30D3\u30FC\u30EB +604=\u30B7\u30D3\u30EB\u30C9\u30F3 +605=\u30EA\u30B0\u30EC\u30FC +606=\u30AA\u30FC\u30D9\u30E0 +607=\u30D2\u30C8\u30E2\u30B7 +608=\u30E9\u30F3\u30D7\u30E9\u30FC +609=\u30B7\u30E3\u30F3\u30C7\u30E9 +610=\u30AD\u30D0\u30B4 +611=\u30AA\u30CE\u30F3\u30C9 +612=\u30AA\u30CE\u30CE\u30AF\u30B9 +613=\u30AF\u30DE\u30B7\u30E5\u30F3 +614=\u30C4\u30F3\u30D9\u30A2\u30FC +615=\u30D5\u30EA\u30FC\u30B8\u30AA +616=\u30C1\u30E7\u30DC\u30DE\u30AD +617=\u30A2\u30AE\u30EB\u30C0\u30FC +618=\u30DE\u30C3\u30AE\u30E7 +619=\u30B3\u30B8\u30E7\u30D5\u30FC +620=\u30B3\u30B8\u30E7\u30F3\u30C9 +621=\u30AF\u30EA\u30E0\u30AC\u30F3 +622=\u30B4\u30D3\u30C3\u30C8 +623=\u30B4\u30EB\u30FC\u30B0 +624=\u30B3\u30DE\u30BF\u30CA +625=\u30AD\u30EA\u30AD\u30B6\u30F3 +626=\u30D0\u30C3\u30D5\u30ED\u30F3 +627=\u30EF\u30B7\u30DC\u30F3 +628=\u30A6\u30A9\u30FC\u30B0\u30EB +629=\u30D0\u30EB\u30C1\u30E3\u30A4 +630=\u30D0\u30EB\u30B8\u30FC\u30CA +631=\u30AF\u30A4\u30BF\u30E9\u30F3 +632=\u30A2\u30A4\u30A2\u30F3\u30C8 +633=\u30E2\u30CE\u30BA +634=\u30B8\u30D8\u30C3\u30C9 +635=\u30B5\u30B6\u30F3\u30C9\u30E9 +636=\u30E1\u30E9\u30EB\u30D0 +637=\u30A6\u30EB\u30AC\u30E2\u30B9 +638=\u30B3\u30D0\u30EB\u30AA\u30F3 +639=\u30C6\u30E9\u30AD\u30AA\u30F3 +640=\u30D3\u30EA\u30B8\u30AA\u30F3 +641=\u30C8\u30EB\u30CD\u30ED\u30B9 +642=\u30DC\u30EB\u30C8\u30ED\u30B9 +643=\u30EC\u30B7\u30E9\u30E0 +644=\u30BC\u30AF\u30ED\u30E0 +645=\u30E9\u30F3\u30C9\u30ED\u30B9 +646=\u30AD\u30E5\u30EC\u30E0 +647=\u30B1\u30EB\u30C7\u30A3\u30AA +648=\u30E1\u30ED\u30A8\u30C3\u30BF +649=\u30B2\u30CE\u30BB\u30AF\u30C8 +650=\u30CF\u30EA\u30DE\u30ED\u30F3 +651=\u30CF\u30EA\u30DC\u30FC\u30B0 +652=\u30D6\u30EA\u30AC\u30ED\u30F3 +653=\u30D5\u30A9\u30C3\u30B3 +654=\u30C6\u30FC\u30EB\u30CA\u30FC +655=\u30DE\u30D5\u30A9\u30AF\u30B7\u30FC +656=\u30B1\u30ED\u30DE\u30C4 +657=\u30B2\u30B3\u30AC\u30B7\u30E9 +658=\u30B2\u30C3\u30B3\u30A6\u30AC +659=\u30DB\u30EB\u30D3\u30FC +660=\u30DB\u30EB\u30FC\u30C9 +661=\u30E4\u30E4\u30B3\u30DE +662=\u30D2\u30CE\u30E4\u30B3\u30DE +663=\u30D5\u30A1\u30A4\u30A2\u30ED\u30FC +664=\u30B3\u30D5\u30AD\u30E0\u30B7 +665=\u30B3\u30D5\u30FC\u30E9\u30A4 +666=\u30D3\u30D3\u30E8\u30F3 +667=\u30B7\u30B7\u30B3 +668=\u30AB\u30A8\u30F3\u30B8\u30B7 +669=\u30D5\u30E9\u30D9\u30D9 +670=\u30D5\u30E9\u30A8\u30C3\u30C6 +671=\u30D5\u30E9\u30FC\u30B8\u30A7\u30B9 +672=\u30E1\u30A7\u30FC\u30AF\u30EB +673=\u30B4\u30FC\u30B4\u30FC\u30C8 +674=\u30E4\u30F3\u30C1\u30E3\u30E0 +675=\u30B4\u30ED\u30F3\u30C0 +676=\u30C8\u30EA\u30DF\u30A2\u30F3 +677=\u30CB\u30E3\u30B9\u30D1\u30FC +678=\u30CB\u30E3\u30AA\u30CB\u30AF\u30B9 +679=\u30D2\u30C8\u30C4\u30AD +680=\u30CB\u30C0\u30F3\u30AE\u30EB +681=\u30AE\u30EB\u30AC\u30EB\u30C9 +682=\u30B7\u30E5\u30B7\u30E5\u30D7 +683=\u30D5\u30EC\u30D5\u30EF\u30F3 +684=\u30DA\u30ED\u30C3\u30D1\u30D5 +685=\u30DA\u30ED\u30EA\u30FC\u30E0 +686=\u30DE\u30FC\u30A4\u30FC\u30AB +687=\u30AB\u30E9\u30DE\u30CD\u30ED +688=\u30AB\u30E1\u30C6\u30C6 +689=\u30AC\u30E1\u30CE\u30C7\u30B9 +690=\u30AF\u30BA\u30E2\u30FC +691=\u30C9\u30E9\u30DF\u30C9\u30ED +692=\u30A6\u30C7\u30C3\u30DD\u30A6 +693=\u30D6\u30ED\u30B9\u30BF\u30FC +694=\u30A8\u30EA\u30AD\u30C6\u30EB +695=\u30A8\u30EC\u30B6\u30FC\u30C9 +696=\u30C1\u30B4\u30E9\u30B9 +697=\u30AC\u30C1\u30B4\u30E9\u30B9 +698=\u30A2\u30DE\u30EB\u30B9 +699=\u30A2\u30DE\u30EB\u30EB\u30AC +700=\u30CB\u30F3\u30D5\u30A3\u30A2 +701=\u30EB\u30C1\u30E3\u30D6\u30EB +702=\u30C7\u30C7\u30F3\u30CD +703=\u30E1\u30EC\u30B7\u30FC +704=\u30CC\u30E1\u30E9 +705=\u30CC\u30E1\u30A4\u30EB +706=\u30CC\u30E1\u30EB\u30B4\u30F3 +707=\u30AF\u30EC\u30C3\u30D5\u30A3 +708=\u30DC\u30AF\u30EC\u30FC +709=\u30AA\u30FC\u30ED\u30C3\u30C8 +710=\u30D0\u30B1\u30C3\u30C1\u30E3 +711=\u30D1\u30F3\u30D7\u30B8\u30F3 +712=\u30AB\u30C1\u30B3\u30FC\u30EB +713=\u30AF\u30EC\u30D9\u30FC\u30B9 +714=\u30AA\u30F3\u30D0\u30C3\u30C8 +715=\u30AA\u30F3\u30D0\u30FC\u30F3 +716=\u30BC\u30EB\u30CD\u30A2\u30B9 +717=\u30A4\u30D9\u30EB\u30BF\u30EB +718=\u30B8\u30AC\u30EB\u30C7 +719=\u30C7\u30A3\u30A2\u30F3\u30B7\u30FC +720=\u30D5\u30FC\u30D1 +721=\u30DC\u30EB\u30B1\u30CB\u30AA\u30F3 diff --git a/src/main/resources/pokemon_names_ru.properties b/src/main/resources/pokemon_names_ru.properties new file mode 100644 index 00000000..2cd97e2d --- /dev/null +++ b/src/main/resources/pokemon_names_ru.properties @@ -0,0 +1,721 @@ +1=\u0411\u0443\u043B\u044C\u0431\u0430\u0437\u0430\u0432\u0440 +2=\u0418\u0432\u0438\u0437\u0430\u0432\u0440 +3=\u0412\u0435\u043D\u0443\u0437\u0430\u0432\u0440 +4=\u0427\u0430\u0440\u043C\u0430\u043D\u0434\u0435\u0440 +5=\u0427\u0430\u0440\u043C\u0438\u043B\u0435\u043E\u043D +6=\u0427\u0430\u0440\u0438\u0437\u0430\u0440\u0434 +7=\u0421\u043A\u0432\u0438\u0440\u0442\u043B +8=\u0412\u0430\u0440\u0442\u043E\u0440\u0442\u043B +9=\u0411\u043B\u0430\u0441\u0442\u043E\u0439\u0437 +10=\u041A\u0430\u0442\u0435\u0440\u043F\u0438 +11=\u041C\u0435\u0442\u0430\u043F\u043E\u0434 +12=\u0411\u0430\u0442\u0435\u0440\u0444\u0440\u0438 +13=\u0412\u0438\u0434\u043B +14=\u041A\u0430\u043A\u0443\u043D\u0430 +15=\u0411\u0438\u0434\u0440\u0438\u043B\u043B +16=\u041F\u0438\u0434\u0436\u0438 +17=\u041F\u0438\u0434\u0436\u0435\u043E\u0442\u0442\u043E +18=\u041F\u0438\u0434\u0436\u0438\u0442 +19=\u0420\u0430\u0442\u0442\u0430\u0442\u0430 +20=\u0420\u044D\u0442\u0438\u043A\u0435\u0439\u0442 +21=\u0421\u043F\u0438\u0440\u043E\u0443 +22=\u0424\u0438\u0440\u043E\u0443 +23=\u042D\u043A\u0430\u043D\u0441 +24=\u042D\u0440\u0431\u043E\u043A +25=\u041F\u0438\u043A\u0430\u0447\u0443 +26=\u0420\u0430\u0439\u0447\u0443 +27=\u0421\u044D\u043D\u0434\u0448\u0440\u0443 +28=\u0421\u044D\u043D\u0434\u0441\u043B\u044D\u0448 +29=\u041D\u0438\u0434\u043E\u0440\u0430\u043D\u2640 +30=\u041D\u0438\u0434\u043E\u0440\u0438\u043D\u0430 +31=\u041D\u0438\u0434\u043E\u043A\u0432\u0438\u043D +32=\u041D\u0438\u0434\u043E\u0440\u0430\u043D\u2642 +33=\u041D\u0438\u0434\u043E\u0440\u0438\u043D\u043E +34=\u041D\u0438\u0434\u043E\u043A\u0438\u043D\u0433 +35=\u041A\u043B\u0435\u0444\u0435\u0439\u0440\u0438 +36=\u041A\u043B\u0435\u0444\u0435\u0439\u0431\u043B +37=\u0412\u0443\u043B\u044C\u043F\u0438\u043A\u0441 +38=\u041D\u0430\u0439\u043D\u0442\u0435\u0439\u043B\u0441 +39=\u0414\u0436\u0438\u0433\u043B\u0438\u043F\u0430\u0444 +40=\u0412\u0438\u0433\u043B\u0438\u0442\u0430\u0444 +41=\u0417\u0443\u0431\u0430\u0442 +42=\u0413\u043E\u043B\u0431\u0430\u0442 +43=\u041E\u0434\u0434\u0438\u0448 +44=\u0413\u043B\u0443\u043C +45=\u0412\u0430\u0439\u043B\u043F\u043B\u0443\u043C +46=\u041F\u0430\u0440\u0430\u0441 +47=\u041F\u0430\u0440\u0430\u0441\u0435\u043A\u0442 +48=\u0412\u0435\u043D\u043E\u043D\u0430\u0442 +49=\u0412\u0435\u043D\u043E\u043C\u043E\u0442 +50=\u0414\u0438\u0433\u043B\u0435\u0442\u0442 +51=\u0414\u0430\u0433\u0442\u0440\u0438\u043E +52=\u041C\u044F\u0443\u0442 +53=\u041F\u0435\u0440\u0441\u0438\u0430\u043D +54=\u041F\u0441\u0438\u0434\u0430\u043A +55=\u0413\u043E\u043B\u0434\u0430\u043A +56=\u041C\u0430\u043D\u043A\u0438 +57=\u041F\u0440\u0430\u0439\u043C\u0435\u0439\u043F +58=\u0413\u0440\u043E\u0443\u043B\u0438\u0442 +59=\u0410\u0440\u043A\u0430\u043D\u0430\u0439\u043D +60=\u041F\u043E\u043B\u0438\u0432\u0430\u0433 +61=\u041F\u043E\u043B\u0438\u0432\u0438\u0440\u043B +62=\u041F\u043E\u043B\u0438\u0440\u044D\u0442 +63=\u0410\u0431\u0440\u0430 +64=\u041A\u0430\u0434\u0430\u0431\u0440\u0430 +65=\u0410\u043B\u0430\u043A\u0430\u0437\u0430\u043C +66=\u041C\u0430\u0447\u043E\u043F +67=\u041C\u0430\u0447\u043E\u0443\u043A +68=\u041C\u0430\u0447\u0430\u043C\u043F +69=\u0411\u0435\u043B\u043B\u0441\u043F\u0440\u0430\u0443\u0442 +70=\u0412\u0438\u043F\u0438\u043D\u0431\u0435\u043B\u043B +71=\u0412\u0438\u043A\u0442\u0440\u0438\u0431\u0435\u043B +72=\u0422\u0435\u043D\u0442\u0430\u043A\u0443\u043B +73=\u0422\u0435\u043D\u0442\u0430\u043A\u0440\u0443\u044D\u043B\u044C +74=\u0414\u0436\u0435\u043E\u0434\u0443\u0434 +75=\u0413\u0440\u0430\u0432\u0435\u043B\u0435\u0440 +76=\u0413\u043E\u043B\u0435\u043C +77=\u041F\u043E\u043D\u0438\u0442\u0430 +78=\u0420\u0430\u043F\u0438\u0434\u044D\u0448 +79=\u0421\u043B\u043E\u0443\u043F\u043E\u043A +80=\u0421\u043B\u043E\u0443\u0431\u0440\u043E +81=\u041C\u0430\u0433\u043D\u0435\u043C\u0430\u0439\u0442 +82=\u041C\u0430\u0433\u043D\u0435\u0442\u043E\u043D +83=\u0424\u0430\u0440\u0444\u0435\u0442\u0447\u0434 +84=\u0414\u043E\u0434\u0443\u043E +85=\u0414\u043E\u0434\u0440\u0438\u043E +86=\u0421\u0438\u043B +87=\u0414\u044C\u044E\u0433\u043E\u043D\u0433 +88=\u0413\u0440\u0430\u0439\u043C\u0435\u0440 +89=\u041C\u0430\u043A +90=\u0428\u0435\u043B\u043B\u0434\u0435\u0440 +91=\u041A\u043B\u043E\u0439\u0441\u0442\u0435\u0440 +92=\u0413\u0430\u0441\u0442\u043B\u0438 +93=\u0425\u043E\u043D\u0442\u0435\u0440 +94=\u0413\u0435\u043D\u0433\u0430\u0440 +95=\u041E\u043D\u0438\u043A\u0441 +96=\u0414\u0440\u043E\u0443\u0437\u0438 +97=\u0413\u0438\u043F\u043D\u043E +98=\u041A\u0440\u0430\u0431\u0431\u0438 +99=\u041A\u0438\u043D\u0433\u043B\u0435\u0440 +100=\u0412\u043E\u043B\u0442\u043E\u0440\u0431 +101=\u042D\u043B\u0435\u043A\u0442\u0440\u043E\u0434 +102=\u042D\u0433\u0437\u0435\u0433\u0443\u0442 +103=\u042D\u0433\u0437\u0435\u0433\u0443\u0442\u043E\u0440 +104=\u041A\u044C\u044E\u0431\u043E\u043D +105=\u041C\u0430\u0440\u043E\u0432\u0430\u043A +106=\u0425\u0438\u0442\u043C\u043E\u043D\u043B\u0438 +107=\u0425\u0438\u0442\u043C\u043E\u043D\u0447\u0430\u043D +108=\u041B\u0438\u043A\u0438\u0442\u0443\u043D\u0433 +109=\u041A\u043E\u0444\u0444\u0438\u043D\u0433 +110=\u0412\u0438\u0437\u0438\u043D\u0433 +111=\u0420\u0430\u0439\u0445\u043E\u0440\u043D +112=\u0420\u0430\u0439\u0434\u043E\u043D +113=\u0427\u0435\u043D\u0441\u0438 +114=\u0422\u0430\u043D\u0434\u0436\u0435\u043B\u0430 +115=\u041A\u0430\u043D\u0433\u0430\u0441\u0445\u0430\u043D +116=\u0425\u043E\u0440\u0441\u0438 +117=\u0421\u0438\u0434\u0440\u0430 +118=\u0413\u043E\u043B\u0434\u0438\u043D +119=\u0421\u0438\u043A\u0438\u043D\u0433 +120=\u0421\u0442\u0430\u0440\u044C\u044E +121=\u0421\u0442\u0430\u0440\u043C\u0438 +122=\u041C\u0438\u0441\u0442\u0435\u0440 \u041C\u0430\u0439\u043C +123=\u0421\u0430\u0439\u0442\u0435\u0440 +124=\u0414\u0436\u0438\u043D\u043A\u0441 +125=\u042D\u043B\u0435\u043A\u0442\u0430\u0431\u0430\u0437\u0437 +126=\u041C\u0430\u0433\u043C\u0430\u0440 +127=\u041F\u0438\u043D\u0441\u0438\u0440 +128=\u0422\u043E\u0440\u043E\u0441 +129=\u041C\u044D\u0434\u0436\u0438\u043A\u0430\u0440\u043F +130=\u0413\u0430\u044F\u0440\u0434\u043E\u0441 +131=\u041B\u0430\u043F\u0440\u0430\u0441 +132=\u0414\u0438\u0442\u0442\u043E +133=\u0418\u0432\u0438 +134=\u0412\u0430\u043F\u043E\u0440\u0435\u043E\u043D +135=\u0414\u0436\u043E\u043B\u0442\u0435\u043E\u043D +136=\u0424\u043B\u0430\u0440\u0435\u043E\u043D +137=\u041F\u043E\u0440\u0438\u0433\u043E\u043D +138=\u041E\u043C\u0430\u043D\u0430\u0439\u0442 +139=\u041E\u043C\u0430\u0441\u0442\u0430\u0440 +140=\u041A\u0430\u0431\u0443\u0442\u043E +141=\u041A\u0430\u0431\u0443\u0442\u043E\u043F\u0441 +142=\u0410\u044D\u0440\u043E\u0434\u0430\u043A\u0442\u0438\u043B\u044C +143=\u0421\u043D\u043E\u0440\u043B\u0430\u043A\u0441 +144=\u0410\u0440\u0442\u0438\u043A\u0443\u043D\u043E +145=\u0417\u0430\u043F\u0434\u043E\u0441 +146=\u041C\u043E\u043B\u0434\u0440\u0435\u0441 +147=\u0414\u0440\u0430\u0442\u0438\u043D\u0438 +148=\u0414\u0440\u0430\u0433\u043E\u043D\u044D\u0439\u0440 +149=\u0414\u0440\u0430\u0433\u043E\u043D\u0430\u0439\u0442 +150=\u041C\u044C\u044E\u0442\u0443 +151=\u041C\u044C\u044E +152=\u0427\u0438\u043A\u043E\u0440\u0438\u0442\u0430 +153=\u0411\u0435\u0439\u043B\u0438\u0444 +154=\u041C\u0435\u0433\u0430\u043D\u0438\u0443\u043C +155=\u0421\u0438\u043D\u0434\u0430\u043A\u0432\u0438\u043B +156=\u041A\u0432\u0438\u043B\u0430\u0432\u0430 +157=\u0422\u0430\u0439\u0444\u043B\u043E\u0436\u043D +158=\u0422\u043E\u0442\u043E\u0434\u0430\u0439\u043B +159=\u041A\u0440\u043E\u043A\u043E\u043D\u0430\u0432 +160=\u0424\u0435\u0440\u0430\u043B\u0438\u0433\u0430\u0442\u0440 +161=\u0421\u0435\u043D\u0442\u0440\u0435\u0442 +162=\u0424\u0443\u0440\u0440\u0435\u0442 +163=\u0425\u0443\u0442\u0445\u0443\u0442 +164=\u041D\u043E\u043A\u0442\u0430\u0443\u043B +165=\u041B\u0435\u0434\u0438\u0431\u0430 +166=\u041B\u0435\u0434\u0438\u0430\u043D +167=\u0421\u043F\u0438\u043D\u0430\u0440\u0430\u043A +168=\u0410\u0440\u0438\u0430\u0434\u043E\u0441 +169=\u041A\u0440\u043E\u0431\u0430\u0442 +170=\u0427\u0438\u043D\u0447\u043E\u0443 +171=\u041B\u0430\u043D\u0442\u0443\u0440\u043D +172=\u041F\u0438\u0447\u0443 +173=\u041A\u043B\u0435\u0444\u0444\u0430 +174=\u0418\u0433\u043B\u0438\u0431\u0430\u0444\u0444 +175=\u0422\u043E\u0433\u0435\u043F\u0438 +176=\u0422\u043E\u0433\u0435\u0442\u0438\u043A +177=\u041D\u0430\u0442\u0443 +178=\u041A\u0441\u0430\u0442\u0443 +179=\u041C\u044D\u0440\u0438\u043F +180=\u0424\u043B\u0430\u0444\u0444\u0438 +181=\u0410\u043C\u0444\u0430\u0440\u043E\u0441 +182=\u0411\u0435\u043B\u043B\u043E\u0441\u043E\u043C +183=\u041C\u044D\u0440\u0438\u043B\u043B +184=\u0410\u0437\u0443\u043C\u044D\u0440\u0438\u043B\u043B +185=\u0421\u0443\u0434\u043E\u0432\u0443\u0434\u043E +186=\u041F\u043E\u043B\u0438\u0442\u043E\u0434 +187=\u0425\u043E\u043F\u043F\u0438\u043F +188=\u0421\u043A\u0438\u043F\u043B\u0443\u043C +189=\u0414\u0436\u0430\u043C\u043F\u043B\u0430\u0444\u0444 +190=\u0410\u0439\u043F\u043E\u043C +191=\u0421\u0430\u043D\u043A\u0435\u0440\u043D +192=\u0421\u0430\u043D\u0444\u043B\u043E\u0440\u0430 +193=\u042F\u043D\u043C\u0430 +194=\u0412\u0443\u043F\u0435\u0440 +195=\u041A\u0432\u0430\u0433\u0441\u0430\u0439\u0440 +196=\u042D\u0441\u043F\u0435\u043E\u043D +197=\u0410\u043C\u0431\u0440\u0435\u043E\u043D +198=\u041C\u0430\u0440\u043A\u0440\u043E\u0443 +199=\u0421\u043B\u043E\u0443\u043A\u0438\u043D\u0433 +200=\u041C\u0438\u0441\u0434\u0440\u0438\u0432\u0443\u0441 +201=\u0410\u043D\u043E\u0443\u043D +202=\u0412\u043E\u0431\u0431\u0430\u0444\u0435\u0442 +203=\u0416\u0438\u0440\u0430\u0444\u0430\u0440\u0438\u0433 +204=\u041F\u0430\u0439\u043D\u0435\u043A\u043E +205=\u0424\u043E\u0440\u0440\u0435\u0442\u0440\u0435\u0441\u0441 +206=\u0414\u0430\u043D\u0441\u043F\u0430\u0440\u0441 +207=\u0413\u043B\u0430\u0439\u0433\u0435\u0440 +208=\u0421\u0442\u0438\u043B\u0438\u043A\u0441 +209=\u0421\u043D\u0430\u0431\u0431\u043B +210=\u0413\u0440\u0430\u043D\u0431\u0443\u043B\u043B +211=\u041A\u0432\u0438\u043B\u0444\u0438\u0448 +212=\u0421\u0438\u0437\u043E\u0440 +213=\u0428\u0430\u043A\u043B +214=\u0413\u0435\u0440\u0430\u043A\u0440\u043E\u0441\u0441 +215=\u0421\u043D\u0438\u0437\u0435\u043B +216=\u0422\u0435\u0434\u0434\u0438\u0443\u0440\u0441\u0430 +217=\u0423\u0440\u0441\u0430\u0440\u0438\u043D\u0433 +218=\u0421\u043B\u0430\u0433\u043C\u0430 +219=\u041C\u0430\u0433\u043A\u0430\u0440\u0433\u043E +220=\u0421\u0432\u0430\u0439\u043D\u0430\u0431 +221=\u041F\u0438\u043B\u043E\u0441\u0432\u0430\u0439\u043D +222=\u041A\u043E\u0440\u0441\u043E\u043B\u0430 +223=\u0420\u0435\u043C\u043E\u0440\u0435\u0439\u0434 +224=\u041E\u043A\u0442\u0438\u043B\u043B\u0435\u0440\u0438 +225=\u0414\u044D\u043B\u0438\u0431\u0451\u0440\u0434 +226=\u041C\u0430\u043D\u0442\u0430\u0439\u043D +227=\u0421\u043A\u0430\u0440\u043C\u043E\u0440\u0438 +228=\u0425\u0430\u0443\u043D\u0434\u0430\u0443\u0440 +229=\u0425\u0430\u0443\u043D\u0434\u0443\u043C +230=\u041A\u0438\u043D\u0433\u0434\u0440\u0430 +231=\u0424\u044D\u043D\u043F\u0438 +232=\u0414\u043E\u043D\u0444\u0430\u043D +233=\u041F\u043E\u0440\u0438\u0433\u043E\u043D 2 +234=\u0421\u0442\u044D\u043D\u0442\u043B\u0435\u0440 +235=\u0421\u043C\u0438\u0440\u0433\u043B +236=\u0422\u0438\u0440\u043E\u0433\u0443 +237=\u0425\u0438\u0442\u043C\u043E\u043D\u0442\u043E\u043F +238=\u0421\u043C\u0443\u0447\u0430\u043C +239=\u042D\u043B\u0435\u043A\u0438\u0434 +240=\u041C\u0430\u0433\u0431\u0438 +241=\u041C\u0438\u043B\u0442\u0430\u043D\u043A +242=\u0411\u043B\u0438\u0441\u0441\u0438 +243=\u0420\u0430\u0439\u043A\u043E\u0443 +244=\u042D\u043D\u0442\u0435\u0439 +245=\u0421\u0443\u0439\u043A\u0443\u043D +246=\u041B\u0430\u0440\u0432\u0438\u0442\u0430\u0440 +247=\u041F\u044C\u044E\u043F\u0438\u0442\u0430\u0440 +248=\u0422\u0438\u0440\u0430\u043D\u0438\u0442\u0430\u0440 +249=\u041B\u0443\u0433\u0438\u044F +250=\u0425\u043E-\u041E\u0445 +251=\u0421\u0435\u043B\u0435\u0431\u0438 +252=\u0422\u0440\u0438\u043A\u043E +253=\u0413\u0440\u043E\u0443\u0432\u0430\u0439\u043B +254=\u0421\u043A\u0435\u043F\u0442\u0430\u0439\u043B +255=\u0422\u043E\u0440\u0447\u0438\u043A +256=\u041A\u043E\u043C\u0431\u0443\u0441\u043A\u0435\u043D +257=\u0411\u043B\u0435\u0439\u0437\u0438\u043A\u0435\u043D +258=\u041C\u0430\u0434\u043A\u0438\u043F +259=\u041C\u0430\u0440\u0448\u0442\u043E\u043C\u043F +260=\u0421\u0432\u0430\u043C\u043F\u0435\u0440\u0442 +261=\u041F\u0443\u0447\u0438\u0435\u043D\u0430 +262=\u041C\u0430\u0439\u0442\u0438\u0435\u043D\u0430 +263=\u0417\u0438\u0433\u0437\u0430\u0433\u0443\u043D +264=\u041B\u0430\u0439\u043D\u0443\u043D +265=\u0412\u0451\u0440\u043C\u043F\u043B +266=\u0421\u0438\u043B\u043A\u0443\u043D +267=\u0411\u044C\u044E\u0442\u0438\u0444\u043B\u0430\u0439 +268=\u041A\u0430\u0441\u043A\u0443\u043D +269=\u0414\u0430\u0441\u0442\u043E\u043A\u0441 +270=\u041B\u043E\u0442\u0430\u0434 +271=\u041B\u043E\u043C\u0431\u0440\u0435 +272=\u041B\u0443\u0434\u0438\u043A\u043E\u043B\u043E +273=\u0421\u0438\u0434\u043E\u0442 +274=\u041D\u0430\u0437\u043B\u0438\u0444 +275=\u0428\u0438\u0444\u0442\u0440\u0438 +276=\u0422\u0435\u0439\u043B\u043E\u0443 +277=\u0421\u0432\u0435\u043B\u043B\u043E\u0443 +278=\u0412\u0438\u043D\u0433\u0430\u043B\u043B +279=\u041F\u0435\u043B\u0438\u043F\u043F\u0435\u0440 +280=\u0420\u0430\u043B\u044C\u0442\u0441 +281=\u041A\u0438\u0440\u043B\u0438\u044F +282=\u0413\u0430\u0440\u0434\u0435\u0432\u0443\u0430\u0440 +283=\u0421\u0451\u0440\u0441\u043A\u0438\u0442 +284=\u041C\u0430\u0441\u043A\u0432\u0435\u0440\u0435\u0439\u043D +285=\u0428\u0440\u0443\u043C\u0438\u0448 +286=\u0411\u0440\u0435\u043B\u0443\u043C +287=\u0421\u043B\u044D\u0439\u043A\u043E\u0442 +288=\u0412\u0438\u0433\u043E\u0440\u043E\u0442 +289=\u0421\u043B\u044D\u0439\u043A\u0438\u043D\u0433 +290=\u041D\u0438\u043D\u043A\u0430\u0434\u0430 +291=\u041D\u0438\u043D\u0434\u0436\u0430\u0441\u043A +292=\u0428\u0435\u0434\u0438\u043D\u0434\u0436\u0430 +293=\u0412\u0438\u0441\u043C\u0443\u0440 +294=\u041B\u0430\u0443\u0434\u0440\u0435\u0434 +295=\u042D\u043A\u0441\u043F\u043B\u0430\u0443\u0434 +296=\u041C\u0430\u043A\u0443\u0445\u0438\u0442\u0430 +297=\u0425\u0430\u0440\u0438\u044F\u043C\u0430 +298=\u0410\u0437\u0443\u0440\u0438\u043B\u043B +299=\u041D\u043E\u0443\u0441\u043F\u0430\u0441\u0441 +300=\u0421\u043A\u0438\u0442\u0442\u0438 +301=\u0414\u0435\u043B\u043A\u0430\u0442\u0442\u0438 +302=\u0421\u0430\u0431\u043B\u0430\u0439 +303=\u041C\u044D\u0432\u0430\u0439\u043B +304=\u0410\u0440\u043E\u043D +305=\u041B\u0435\u0439\u0440\u043E\u043D +306=\u0410\u0433\u0433\u0440\u043E\u043D +307=\u041C\u0435\u0434\u0438\u0442\u0430\u0439\u0442 +308=\u041C\u0435\u0434\u0438\u0447\u0430\u043C +309=\u042D\u043B\u0435\u043A\u0442\u0440\u0430\u0439\u043A +310=\u041C\u0430\u043D\u0435\u043A\u0442\u0440\u0438\u043A +311=\u041F\u043B\u044E\u0441\u043B +312=\u041C\u0438\u043D\u0443\u043D +313=\u0412\u043E\u043B\u0431\u0438\u0442 +314=\u0418\u043B\u043B\u044E\u043C\u0438\u0437\u0438 +315=\u0420\u043E\u0437\u0430\u043B\u0438\u044F +316=\u0413\u0430\u043B\u043F\u0438\u043D +317=\u0421\u0432\u0430\u043B\u043E\u0442 +318=\u041A\u0430\u0440\u0432\u0430\u043D\u043D\u0430 +319=\u0428\u0430\u0440\u043F\u0438\u0434\u043E +320=\u0412\u044D\u0439\u043B\u043C\u0435\u0440 +321=\u0412\u044D\u0439\u043B\u043E\u0440\u0434 +322=\u041D\u0430\u043C\u0435\u043B +323=\u041A\u0430\u043C\u0435\u0440\u0430\u043F\u0442 +324=\u0422\u043E\u0440\u043A\u043B +325=\u0421\u043F\u043E\u0438\u043D\u043A +326=\u0413\u0440\u0430\u043C\u043F\u0438\u0433 +327=\u0421\u043F\u0438\u043D\u0434\u0430 +328=\u0422\u0440\u0430\u043F\u0438\u043D\u0447 +329=\u0412\u0438\u0431\u0440\u0430\u0432\u0430 +330=\u0424\u043B\u0430\u0439\u0433\u043E\u043D +331=\u041A\u0430\u043A\u043D\u0438\u044F +332=\u041A\u0430\u043A\u0442\u0443\u0440\u043D +333=\u0421\u0432\u0430\u0431\u043B\u0443 +334=\u0410\u043B\u0442\u0430\u0440\u0438\u044F +335=\u0417\u0430\u043D\u0433\u0443\u0441 +336=\u0421\u0438\u0432\u0430\u0439\u043F\u0435\u0440 +337=\u041B\u0443\u043D\u0430\u0442\u043E\u043D +338=\u0421\u043E\u043B\u0440\u043E\u043A +339=\u0411\u0430\u0440\u0431\u043E\u0430 +340=\u0412\u0438\u0441\u043A\u044D\u0448 +341=\u041A\u043E\u0440\u0444\u0438\u0448 +342=\u041A\u0440\u043E\u0434\u0430\u043D\u0442 +343=\u0411\u0430\u043B\u0442\u043E\u0439 +344=\u041A\u043B\u044D\u0439\u0434\u043E\u043B +345=\u041B\u0438\u043B\u0438\u043F +346=\u041A\u0440\u044D\u0434\u0438\u043B\u0438 +347=\u0410\u043D\u043E\u0440\u0438\u0442 +348=\u0410\u0440\u043C\u0430\u043B\u044C\u0434\u043E +349=\u0424\u0438\u0431\u0430\u0441 +350=\u041C\u0430\u0439\u043B\u043E\u0442\u0438\u043A +351=\u041A\u0430\u0441\u0442\u0444\u043E\u0440\u043C +352=\u041A\u0435\u043A\u043B\u0435\u043E\u043D +353=\u0428\u0430\u043F\u043F\u0435\u0442 +354=\u0411\u044D\u043D\u0435\u0442\u0442 +355=\u0414\u0430\u0441\u043A\u0443\u043B\u043B +356=\u0414\u0430\u0441\u043A\u043B\u043E\u043F\u0441 +357=\u0422\u0440\u043E\u043F\u0438\u0443\u0441 +358=\u0427\u0430\u0439\u043C\u0435\u043A\u043E +359=\u042D\u0431\u0441\u043E\u043B +360=\u0412\u0438\u043D\u0430\u0443\u0442 +361=\u0421\u043D\u043E\u0440\u0430\u043D\u0442 +362=\u0413\u043B\u044D\u0439\u043B\u0438 +363=\u0421\u0444\u0438\u043B +364=\u0421\u0438\u043B\u0435\u043E +365=\u0423\u043E\u043B\u0440\u0435\u0439\u043D +366=\u041A\u043B\u0430\u043C\u043F\u0435\u0440\u043B +367=\u0425\u0430\u043D\u0442\u044D\u0439\u043B +368=\u0413\u043E\u0440\u0435\u0431\u0438\u0441\u0441 +369=\u0420\u0435\u043B\u0438\u043A\u0430\u043D\u0442 +370=\u041B\u044E\u0432\u0434\u0438\u0441\u043A +371=\u0411\u0430\u0433\u043E\u043D +372=\u0428\u0435\u043B\u0433\u043E\u043D +373=\u0421\u0430\u043B\u0430\u043C\u0435\u043D\u0441 +374=\u0411\u0435\u043B\u0434\u0443\u043C +375=\u041C\u0435\u0442\u0430\u043D\u0433 +376=\u041C\u0435\u0442\u0430\u0433\u0440\u043E\u0441\u0441 +377=\u0420\u0435\u0434\u0436\u0438\u0440\u043E\u043A +378=\u0420\u0435\u0434\u0436\u0430\u0439\u0441 +379=\u0420\u0435\u0434\u0436\u0438\u0441\u0442\u0438\u043B +380=\u041B\u0430\u0442\u0438\u0430\u0441 +381=\u041B\u0430\u0442\u0438\u043E\u0441 +382=\u041A\u0430\u0439\u043E\u0433\u0440 +383=\u0413\u0440\u0430\u0443\u0434\u043E\u043D +384=\u0420\u044D\u0439\u043A\u0432\u0430\u0437\u0430 +385=\u0414\u0436\u0438\u0440\u0430\u0447\u0438 +386=\u0414\u0435\u043E\u043A\u0441\u0438\u0441 +387=\u0422\u0443\u0440\u0442\u0432\u0438\u0433 +388=\u0413\u0440\u043E\u0442\u043B +389=\u0422\u043E\u0440\u0442\u0435\u0440\u0440\u0430 +390=\u0427\u0438\u043C\u0447\u0430\u0440 +391=\u041C\u043E\u043D\u0444\u0435\u0440\u043D\u043E +392=\u0418\u043D\u0444\u0435\u0440\u043D\u0435\u0439\u043F +393=\u041F\u0438\u043F\u043B\u0443\u043F +394=\u041F\u0440\u0438\u043D\u043F\u043B\u0443\u043F +395=\u042D\u043C\u043F\u043E\u043B\u0435\u043E\u043D +396=\u0421\u0442\u0430\u0440\u043B\u0438 +397=\u0421\u0442\u0430\u0440\u0430\u0432\u0438\u044F +398=\u0421\u0442\u0430\u0440\u0430\u043F\u0442\u043E\u0440 +399=\u0411\u0438\u0434\u0443\u0444 +400=\u0411\u0438\u0431\u0430\u0440\u0435\u043B +401=\u041A\u0440\u0438\u043A\u0435\u0442\u043E\u0442 +402=\u041A\u0440\u0438\u043A\u0435\u0442\u0443\u043D +403=\u0428\u0438\u043D\u043A\u0441 +404=\u041B\u044E\u043A\u0441\u0438\u043E +405=\u041B\u044E\u043A\u0441\u0440\u0435\u0439 +406=\u0411\u0430\u0434\u044C\u044E +407=\u0420\u043E\u0443\u0437\u0440\u0435\u0439\u0434 +408=\u041A\u0440\u044D\u0439\u043D\u0438\u0434\u043E\u0441 +409=\u0420\u0430\u043C\u043F\u0430\u0440\u0434\u043E\u0441 +410=\u0428\u0438\u043B\u0434\u043E\u043D +411=\u0411\u0430\u0441\u0442\u0438\u043E\u0434\u043E\u043D +412=\u0411\u0443\u0440\u043C\u0438 +413=\u0412\u043E\u0440\u043C\u0430\u0434\u0430\u043C +414=\u041C\u043E\u0442\u0438\u043C +415=\u041A\u043E\u043C\u0431\u0438 +416=\u0412\u0435\u0441\u043F\u0438\u043A\u0432\u0438\u043D +417=\u041F\u0430\u0447\u0438\u0440\u0438\u0441\u0443 +418=\u0411\u0443\u0438\u0437\u0435\u043B +419=\u0424\u043B\u043E\u0442\u0446\u0435\u043B +420=\u0427\u0435\u0440\u0443\u0431\u0438 +421=\u0427\u0435\u0440\u0440\u0438\u043C +422=\u0428\u0435\u043B\u043B\u043E\u0441 +423=\u0413\u0430\u0441\u0442\u0440\u043E\u0434\u043E\u043D +424=\u042D\u043C\u0431\u0438\u043F\u043E\u043C +425=\u0414\u0440\u0438\u0444\u043B\u0443\u043D +426=\u0414\u0440\u0438\u0444\u0431\u043B\u0438\u043C +427=\u0411\u0430\u043D\u0438\u0440\u0438 +428=\u041B\u043E\u043F\u0430\u043D\u043D\u0438 +429=\u041C\u0438\u0441\u043C\u0430\u0433\u0438\u0443\u0441 +430=\u0425\u043E\u043D\u0447\u043A\u0440\u043E\u0443 +431=\u0413\u043B\u0435\u0439\u043C\u044F\u0443 +432=\u041F\u0443\u0440\u0430\u0433\u043B\u0438 +433=\u0427\u0438\u043D\u0433\u043B\u0438\u043D\u0433 +434=\u0421\u0442\u0430\u043D\u043A\u0438 +435=\u0421\u043A\u0443\u043D\u0442\u0430\u043D\u043A +436=\u0411\u0440\u043E\u043D\u0437\u043E\u0440 +437=\u0411\u0440\u043E\u043D\u0437\u043E\u043D\u0433 +438=\u0411\u043E\u043D\u0441\u043B\u0430\u0439 +439=\u041C\u0430\u0439\u043C \u041C\u043B\u0430\u0434\u0448\u0438\u0439 +440=\u0425\u044D\u043F\u043F\u0438\u043D\u0438 +441=\u0427\u0430\u0442\u043E\u0442 +442=\u0421\u043F\u0438\u0440\u0438\u0442\u043E\u043C\u0431 +443=\u0413\u0438\u0431\u043B +444=\u0413\u0430\u0431\u0430\u0439\u0442 +445=\u0413\u0430\u0440\u0447\u043E\u043C\u043F +446=\u041C\u0430\u043D\u0447\u043B\u0430\u043A\u0441 +447=\u0420\u0438\u043E\u043B\u0443 +448=\u041B\u0443\u043A\u0430\u0440\u0438\u043E +449=\u0413\u0438\u043F\u043F\u043E\u043F\u043E\u0442\u0430\u0441 +450=\u0413\u0438\u043F\u043F\u043E\u0434\u043E\u043D +451=\u0421\u043A\u043E\u0440\u0443\u043F\u0438 +452=\u0414\u0440\u0430\u043F\u0438\u043E\u043D +453=\u041A\u0440\u043E\u0433\u0430\u043D\u043A +454=\u0422\u043E\u043A\u0441\u0438\u043A\u0440\u043E\u0443\u043A +455=\u041A\u0430\u0440\u043D\u0438\u0432\u0430\u0439\u043D +456=\u0424\u0438\u043D\u043D\u0435\u043E\u043D +457=\u041B\u044E\u043C\u0438\u043D\u0435\u043E\u043D +458=\u041C\u0430\u043D\u0442\u0438\u043A +459=\u0421\u043D\u043E\u0432\u0435\u0440 +460=\u0410\u0431\u043E\u043C\u0430\u0441\u043D\u043E\u0443 +461=\u0412\u0438\u0432\u0430\u0439\u043B +462=\u041C\u0430\u0433\u043D\u0435\u0437\u043E\u043D +463=\u041B\u0438\u043A\u0438\u043B\u0438\u043A\u0438 +464=\u0420\u0430\u0439\u043F\u0435\u0440\u0438\u043E\u0440 +465=\u0422\u0430\u043D\u0433\u0440\u043E\u0443\u0442 +466=\u042D\u043B\u0435\u043A\u0442\u0438\u0432\u0430\u0439\u0440 +467=\u041C\u0430\u0433\u043C\u043E\u0440\u0442\u0430\u0440 +468=\u0422\u043E\u0433\u0435\u043A\u0438\u0441\u0441 +469=\u042F\u043D\u043C\u0435\u0433\u0430 +470=\u041B\u0438\u0444\u0435\u043E\u043D +471=\u0413\u043B\u0430\u0441\u0435\u043E\u043D +472=\u0413\u043B\u0430\u0439\u0441\u043A\u043E\u0440 +473=\u041C\u0430\u043C\u043E\u0441\u0432\u0430\u0439\u043D +474=\u041F\u043E\u0440\u0438\u0433\u043E\u043D-Z +475=\u0413\u0430\u043B\u043B\u0435\u0439\u0434 +476=\u041F\u0440\u043E\u0431\u043E\u043F\u0430\u0441\u0441 +477=\u0414\u0430\u0441\u043A\u043D\u0443\u0430\u0440 +478=\u0424\u0440\u043E\u0441\u043B\u0430\u0441\u0441 +479=\u0420\u043E\u0442\u043E\u043C +480=\u042E\u043A\u0441\u0438 +481=\u041C\u0435\u0441\u043F\u0440\u0438\u0442 +482=\u0410\u0437\u0435\u043B\u044C\u0444 +483=\u0414\u0438\u0430\u043B\u0433\u0430 +484=\u041F\u0430\u043B\u043A\u0438\u044F +485=\u0425\u0438\u0442\u0440\u0430\u043D +486=\u0420\u0435\u0434\u0436\u0438\u0433\u0438\u0433\u0430\u0441 +487=\u0413\u0438\u0440\u0430\u0442\u0438\u043D\u0430 +488=\u041A\u0440\u0438\u0441\u0441\u0435\u043B\u0438\u044F +489=\u0424\u0438\u043E\u043D +490=\u041C\u0430\u043D\u0430\u043F\u0438 +491=\u0414\u0430\u0440\u043A\u0440\u0430\u0439 +492=\u0428\u0435\u0439\u043C\u0438\u043D +493=\u0410\u0440\u043A\u0435\u0443\u0441 +494=\u0412\u0438\u043A\u0442\u0438\u043D\u0438 +495=\u0421\u043D\u0430\u0439\u0432\u0438 +496=\u0421\u0435\u0440\u0432\u0430\u0439\u043D +497=\u0421\u0435\u0440\u043F\u0435\u0440\u0438\u043E\u0440 +498=\u0422\u0435\u043F\u0438\u0433 +499=\u041F\u0438\u0433\u043D\u0430\u0439\u0442 +500=\u042D\u043C\u0431\u043E\u0440 +501=\u041E\u0448\u0430\u0432\u043E\u0442\u0442 +502=\u0414\u0435\u0432\u043E\u0442\u0442 +503=\u0421\u0430\u043C\u0443\u0440\u043E\u0442\u0442 +504=\u041F\u0430\u0442\u0440\u0430\u0442 +505=\u0423\u043E\u0447\u0445\u043E\u0433 +506=\u041B\u0438\u043B\u043B\u0438\u043F\u0430\u043F +507=\u0425\u0435\u0440\u0434\u0438\u0435\u0440 +508=\u0421\u0442\u0430\u0443\u0442\u043B\u044D\u043D\u0434 +509=\u041F\u0443\u0440\u0440\u043B\u043E\u0439\u043D +510=\u041B\u0430\u0439\u043F\u0430\u0440\u0434 +511=\u041F\u0430\u043D\u0441\u0435\u0439\u0434\u0436 +512=\u0421\u0438\u043C\u0438\u0441\u0435\u0439\u0434\u0436 +513=\u041F\u0430\u043D\u0441\u0438\u0440 +514=\u0421\u0438\u043C\u0438\u0441\u0438\u0440 +515=\u041F\u0430\u043D\u043F\u0443\u0440 +516=\u0421\u0438\u043C\u0438\u043F\u0443\u0440 +517=\u041C\u0443\u043D\u043D\u0430 +518=\u041C\u0443\u0448\u0430\u0440\u043D\u0430 +519=\u041F\u0438\u0434\u0430\u0432 +520=\u0422\u0440\u0430\u043D\u043A\u0432\u0438\u043B\u043B +521=\u0410\u043D\u0444\u0435\u0437\u0430\u043D\u0442 +522=\u0411\u043B\u0438\u0442\u0446\u043B +523=\u0417\u0435\u0431\u0441\u0442\u0440\u0430\u0439\u043A\u0430 +524=\u0420\u043E\u0433\u0433\u0435\u043D\u0440\u043E\u043B\u0430 +525=\u0411\u043E\u043B\u0434\u043E\u0440 +526=\u0413\u0438\u0433\u0430\u043B\u0438\u0442 +527=\u0412\u0443\u0431\u044D\u0442 +528=\u0421\u0432\u0443\u0431\u044D\u0442 +529=\u0414\u0440\u0438\u043B\u0431\u0443\u0440 +530=\u042D\u043A\u0441\u043A\u0430\u0434\u0440\u0438\u043B\u043B +531=\u0410\u0443\u0434\u0438\u043D\u043E +532=\u0422\u0438\u043C\u0431\u0443\u0440\u0440 +533=\u0413\u0443\u0440\u0434\u0443\u0440\u0440 +534=\u041A\u043E\u043D\u043A\u0435\u043B\u044C\u0434\u0443\u0440\u0440 +535=\u0422\u0438\u043C\u043F\u043E\u043B +536=\u041F\u0430\u043B\u043F\u0438\u0442\u043E\u0430\u0434 +537=\u0421\u0435\u0439\u0441\u043C\u0438\u0442\u043E\u0430\u0434 +538=\u0422\u0440\u043E +539=\u0421\u043E\u0443\u043A +540=\u0421\u0435\u0432\u0430\u0434\u043B +541=\u0421\u0432\u0430\u0434\u043B\u0443\u043D +542=\u041B\u0435\u0432\u0430\u043D\u0438 +543=\u0412\u0435\u043D\u0438\u043F\u0438\u0434 +544=\u0412\u0438\u0440\u043B\u0438\u043F\u0438\u0434 +545=\u0421\u043A\u043E\u043B\u0438\u043F\u0438\u0434 +546=\u041A\u043E\u0442\u0442\u043E\u043D\u0438 +547=\u0412\u0438\u043C\u0441\u0438\u0441\u043A\u043E\u0442\u0442 +548=\u041F\u0435\u0442\u0438\u043B\u0438\u043B +549=\u041B\u0438\u043B\u043B\u0438\u0433\u0430\u043D\u0442 +550=\u0411\u0430\u0441\u043A\u0443\u043B\u0438\u043D +551=\u0421\u044D\u043D\u0434\u0430\u0439\u043B +552=\u041A\u0440\u043E\u043A\u043E\u0440\u043E\u043A +553=\u041A\u0440\u0443\u043A\u043E\u0434\u0430\u0439\u043B +554=\u0414\u0430\u0440\u0443\u043C\u0430\u043A\u043A\u0430 +555=\u0414\u0430\u0440\u043C\u0430\u043D\u0438\u0442\u0430\u043D +556=\u041C\u0430\u0440\u0430\u043A\u0442\u0443\u0441 +557=\u0414\u0432\u044D\u0431\u0431\u043B +558=\u041A\u0440\u0430\u0441\u0442\u043B +559=\u0421\u043A\u0440\u044D\u0433\u0433\u0438 +560=\u0421\u043A\u0440\u0430\u0444\u0442\u0438 +561=\u0421\u0438\u0434\u0436\u0438\u043B\u0438\u0444 +562=\u042F\u043C\u0430\u0441\u043A +563=\u041A\u043E\u0444\u0430\u0433\u0440\u0438\u0433\u0443\u0441 +564=\u0422\u0438\u0440\u0442\u0443\u0433\u0430 +565=\u041A\u0430\u0440\u0440\u0430\u043A\u043E\u0441\u0442\u0430 +566=\u0410\u0440\u043A\u0435\u043D +567=\u0410\u0440\u043A\u0435\u043E\u043F\u0441 +568=\u0422\u0440\u0430\u0431\u0431\u0438\u0448 +569=\u0413\u0430\u0440\u0431\u043E\u0434\u043E\u0440 +570=\u0417\u043E\u0440\u0443\u0430 +571=\u0417\u043E\u0440\u043E\u0430\u0440\u043A +572=\u041C\u0438\u043D\u0447\u0438\u043D\u043E +573=\u0427\u0438\u043D\u0447\u0438\u043D\u043E +574=\u0413\u043E\u0444\u0438\u0442\u0430 +575=\u0413\u043E\u0444\u043E\u0440\u0438\u0442\u0430 +576=\u0413\u043E\u0444\u0438\u0442\u0435\u043B\u043B\u044C +577=\u0421\u043E\u043B\u043E\u0437\u0438\u0441 +578=\u0414\u0443\u043E\u0437\u0438\u043E\u043D +579=\u0420\u0435\u043E\u043D\u0438\u043A\u043B\u0443\u0441 +580=\u0414\u0430\u043A\u043B\u0435\u0442\u0442 +581=\u0421\u0432\u0430\u043D\u043D\u0430 +582=\u0412\u0430\u043D\u0438\u043B\u043B\u0430\u0439\u0442 +583=\u0412\u0430\u043D\u0438\u043B\u043B\u0438\u0448 +584=\u0412\u0430\u043D\u0438\u043B\u043B\u0430\u043A\u0441 +585=\u0414\u0438\u0440\u043B\u0438\u043D\u0433 +586=\u0421\u043E\u0443\u0441\u0431\u0430\u043A +587=\u042D\u043C\u043E\u043B\u0433\u0430 +588=\u041A\u0430\u0440\u0440\u0430\u0431\u043B\u0430\u0441\u0442 +589=\u042D\u0441\u043A\u0430\u0432\u0430\u043B\u0438\u0440 +590=\u0424\u0443\u043D\u0433\u0443\u0441 +591=\u0410\u043C\u0443\u043D\u0433\u0443\u0441 +592=\u0424\u0440\u0438\u043B\u0438\u0448 +593=\u0414\u0436\u0435\u043B\u043B\u0438\u0441\u0435\u043D\u0442 +594=\u0410\u043B\u043E\u043C\u043E\u043C\u043E\u043B\u0430 +595=\u0414\u0436\u043E\u043B\u0442\u0438\u043A +596=\u0413\u0430\u043B\u0432\u0430\u043D\u0442\u0443\u043B\u0430 +597=\u0424\u0435\u0440\u0440\u043E\u0441\u0438\u0434 +598=\u0424\u0435\u0440\u0440\u043E\u0442\u043E\u0440\u043D +599=\u041A\u043B\u0438\u043D\u043A +600=\u041A\u043B\u044D\u043D\u0433 +601=\u041A\u043B\u0438\u043D\u043A\u043B\u044D\u043D\u0433 +602=\u0422\u0430\u0439\u043D\u0430\u043C\u043E +603=\u0418\u043B\u0435\u043A\u0442\u0440\u0438\u043A +604=\u0418\u043B\u0435\u043A\u0442\u0440\u043E\u0441\u0441 +605=\u0418\u043B\u0434\u0436\u0438\u0435\u043C +606=\u0411\u0438\u0445\u0438\u0435\u043C +607=\u041B\u0438\u0442\u0432\u0438\u043A +608=\u041B\u0430\u043C\u043F\u0435\u043D\u0442 +609=\u0428\u0430\u043D\u0434\u0435\u043B\u044E\u0440 +610=\u042D\u043A\u0441\u044C\u044E +611=\u0424\u0440\u0430\u043A\u0441\u0443\u0440 +612=\u0413\u0430\u043A\u0441\u043E\u0440\u0443\u0441 +613=\u041A\u0430\u0431\u0447\u0443 +614=\u0411\u0435\u0440\u0442\u0438\u043A +615=\u041A\u0440\u0438\u043E\u0433\u043E\u043D\u0430\u043B +616=\u0428\u0435\u043B\u043C\u0435\u0442 +617=\u0410\u043A\u0441\u0435\u043B\u044C\u0433\u043E\u0440 +618=\u0421\u0442\u0430\u043D\u0444\u0438\u0441\u043A +619=\u041C\u0435\u043D\u044C\u0444\u0443 +620=\u041C\u0435\u043D\u044C\u0448\u0430\u043E +621=\u0414\u0440\u0430\u0434\u0434\u0438\u0433\u043E\u043D +622=\u0413\u043E\u043B\u0435\u0442\u0442 +623=\u0413\u043E\u043B\u0443\u0440\u043A +624=\u041F\u0430\u043E\u043D\u0438\u0430\u0440\u0434 +625=\u0411\u0438\u0448\u0430\u0440\u043F +626=\u0411\u0443\u0444\u0444\u0430\u043B\u0430\u043D\u0442 +627=\u0420\u0430\u0444\u0444\u043B\u0435\u0442 +628=\u0411\u0440\u044D\u0439\u0432\u0438\u0430\u0440\u0438 +629=\u0412\u0430\u043B\u043B\u0430\u0431\u0438 +630=\u041C\u0430\u043D\u0434\u0438\u0431\u0430\u0437\u0437 +631=\u0425\u0438\u0442\u043C\u043E\u0440 +632=\u0414\u044E\u0440\u0430\u043D\u0442 +633=\u0414\u0430\u0439\u043D\u043E +634=\u0417\u0432\u0430\u0439\u043B\u043E\u0441 +635=\u0413\u0438\u0434\u0440\u0430\u0439\u0433\u043E\u043D +636=\u041B\u0430\u0440\u0432\u0435\u0441\u0442\u0430 +637=\u0412\u043E\u043B\u043A\u0430\u0440\u043E\u043D\u0430 +638=\u041A\u043E\u0431\u0430\u043B\u0438\u043E\u043D +639=\u0422\u0435\u0440\u0440\u0430\u043A\u0438\u043E\u043D +640=\u0412\u0438\u0440\u0438\u0437\u0438\u043E\u043D +641=\u0422\u043E\u0440\u043D\u0430\u0434\u0443\u0441 +642=\u0422\u0430\u043D\u0434\u0443\u0440\u0443\u0441 +643=\u0420\u0435\u0448\u0438\u0440\u0430\u043C +644=\u0417\u0435\u043A\u0440\u043E\u043C +645=\u041B\u044D\u043D\u0434\u043E\u0440\u0443\u0441 +646=\u041A\u044E\u0440\u0435\u043C +647=\u041A\u0435\u043B\u0434\u0435\u043E +648=\u041C\u0435\u043B\u043E\u044D\u0442\u0442\u0430 +649=\u0413\u0435\u043D\u0435\u0441\u0435\u043A\u0442 +650=\u0427\u0435\u0441\u043F\u0438\u043D +651=\u041A\u0432\u0438\u043B\u043B\u0430\u0434\u0438\u043D +652=\u0427\u0435\u0441\u043D\u043E\u0442 +653=\u0424\u0435\u043D\u043D\u0435\u043A\u0438\u043D +654=\u0411\u0440\u0430\u0439\u043A\u0441\u0435\u043D +655=\u0414\u0435\u043B\u044C\u0444\u043E\u043A\u0441 +656=\u0424\u0440\u043E\u043A\u0438 +657=\u0424\u0440\u043E\u0433\u0430\u0434\u0438\u0440 +658=\u0413\u0440\u0435\u043D\u0438\u043D\u0434\u0437\u044F +659=\u0411\u0430\u043D\u043D\u0435\u043B\u0431\u0438 +660=\u0414\u0438\u0433\u0433\u0435\u0440\u0437\u0431\u0438 +661=\u0424\u043B\u0435\u0447\u043B\u0438\u043D\u0433 +662=\u0424\u043B\u0435\u0447\u0438\u043D\u0434\u0435\u0440 +663=\u0422\u044D\u0439\u043B\u043E\u043D\u0444\u043B\u0435\u0439\u043C +664=\u0421\u043A\u0430\u0442\u0442\u0435\u0440\u0431\u0430\u0433 +665=\u0421\u043F\u044C\u044E\u043F\u0430 +666=\u0412\u0438\u0432\u0438\u043B\u043B\u043E\u043D +667=\u041B\u0438\u0442\u043B\u0435\u043E +668=\u041F\u0430\u0439\u0440\u043E\u0430\u0440 +669=\u0424\u043B\u0430\u0431\u044D\u0431\u044D +670=\u0424\u043B\u043E\u044D\u0442\u0442 +671=\u0424\u043B\u043E\u0440\u0433\u0435\u0441 +672=\u0421\u043A\u0438\u0434\u0434\u043E +673=\u0413\u043E\u0433\u043E\u0430\u0442 +674=\u041F\u0430\u043D\u0447\u0430\u043C +675=\u041F\u0430\u043D\u0433\u043E\u0440\u043E +676=\u0424\u0443\u0440\u0444\u0440\u0443 +677=\u042D\u0441\u043F\u0443\u0440 +678=\u041C\u044F\u0443\u0441\u0442\u0438\u043A +679=\u0425\u043E\u043D\u044D\u0434\u0436 +680=\u0414\u0430\u0431\u043B\u0435\u0439\u0434 +681=\u0410\u0435\u0433\u0438\u0441\u043B\u044D\u0448 +682=\u0421\u043F\u0440\u0438\u0442\u0437\u0438 +683=\u0410\u0440\u043E\u043C\u0430\u0442\u0438\u0437\u0437 +684=\u0421\u0432\u0438\u0440\u043B\u0438\u043A\u0441 +685=\u0421\u043B\u0430\u0440\u043F\u0430\u0444\u0444 +686=\u0418\u043D\u043A\u0435\u0439 +687=\u041C\u0430\u043B\u0430\u043C\u0430\u0440 +688=\u0411\u0438\u043D\u0430\u043A\u043B +689=\u0411\u0430\u0440\u0431\u0430\u0440\u0430\u043A\u043B +690=\u0421\u043A\u0440\u0435\u043B\u044C\u043F +691=\u0414\u0440\u0430\u0433\u0430\u043B\u0433 +692=\u041A\u043B\u043E\u043D\u0447\u0435\u0440 +693=\u041A\u043B\u043E\u0432\u0438\u0446\u0435\u0440 +694=\u0413\u0435\u043B\u0438\u043E\u043F\u0442\u0430\u0439\u043B +695=\u0413\u0435\u043B\u0438\u043E\u043B\u0438\u0441\u043A +696=\u0422\u0430\u0439\u0440\u0430\u043D\u0442 +697=\u0422\u0430\u0439\u0440\u0435\u043D\u0442\u0440\u0443\u043C +698=\u0410\u043C\u0430\u0443\u0440\u0430 +699=\u0410\u0432\u0440\u043E\u0440\u0443\u0441 +700=\u0421\u0438\u043B\u044C\u0432\u0435\u043E\u043D +701=\u0425\u043E\u043B\u0443\u0447\u0430 +702=\u0414\u0435\u0434\u0435\u043D\u043D\u0435 +703=\u041A\u0430\u0440\u0431\u0438\u043D\u043A +704=\u0413\u0443\u043C\u0438 +705=\u0421\u043B\u0438\u0433\u0443 +706=\u0413\u0443\u0434\u0440\u0430 +707=\u041A\u043B\u0435\u0444\u043A\u0438 +708=\u0424\u0430\u043D\u0442\u0430\u043C\u043F +709=\u0422\u0440\u0438\u0432\u0435\u0440\u043D\u0430\u043D\u0442 +710=\u041F\u0430\u043C\u043F\u0430\u043A\u043C\u0431\u0443 +711=\u0413\u0443\u0440\u0433\u0435\u0439\u0441\u0442 +712=\u0411\u0435\u0440\u0433\u043C\u0430\u0439\u0442 +713=\u0410\u0432\u0430\u043B\u0430\u0433\u0433 +714=\u041D\u043E\u0439\u0431\u0430\u0442 +715=\u041D\u043E\u0439\u0432\u0435\u0440\u043D +716=\u041A\u0441\u0435\u0440\u043D\u0435\u0430\u0441 +717=\u0418\u0432\u0435\u043B\u044C\u0442\u0430\u043B +718=\u0417\u0430\u0439\u0433\u0430\u0440\u0434 +719=\u0414\u0438\u0430\u043D\u0441\u0438 +720=\u0425\u0443\u043F\u0430 +721=\u0412\u0443\u043B\u043A\u0430\u043D\u0438\u043E\u043D \ No newline at end of file diff --git a/src/main/resources/pokemon_names_zh_CN.properties b/src/main/resources/pokemon_names_zh_CN.properties new file mode 100644 index 00000000..10726075 --- /dev/null +++ b/src/main/resources/pokemon_names_zh_CN.properties @@ -0,0 +1,721 @@ +1=\u5999\u86D9\u79CD\u5B50 +2=\u5999\u86D9\u8349 +3=\u5999\u86D9\u82B1 +4=\u5C0F\u706B\u9F99 +5=\u706B\u6050\u9F99 +6=\u55B7\u706B\u9F99 +7=\u6770\u5C3C\u9F9F +8=\u5361\u54AA\u9F9F +9=\u6C34\u7BAD\u9F9F +10=\u7EFF\u6BDB\u866B +11=\u94C1\u7532\u86F9 +12=\u5DF4\u5927\u8776 +13=\u72EC\u89D2\u866B +14=\u94C1\u58F3\u86F9 +15=\u5927\u9488\u8702 +16=\u6CE2\u6CE2 +17=\u6BD4\u6BD4\u9E1F +18=\u5927\u6BD4\u9E1F +19=\u5C0F\u62C9\u8FBE +20=\u62C9\u8FBE +21=\u70C8\u96C0 +22=\u5927\u5634\u96C0 +23=\u963F\u67CF\u86C7 +24=\u963F\u67CF\u602A +25=\u76AE\u5361\u4E18 +26=\u96F7\u4E18 +27=\u7A7F\u5C71\u9F20 +28=\u7A7F\u5C71\u738B +29=\u5C3C\u591A\u5170 +30=\u5C3C\u591A\u5A1C +31=\u5C3C\u591A\u540E +32=\u5C3C\u591A\u6717 +33=\u5C3C\u591A\u529B\u8BFA +34=\u5C3C\u591A\u738B +35=\u76AE\u76AE +36=\u76AE\u53EF\u897F +37=\u516D\u5C3E +38=\u4E5D\u5C3E +39=\u80D6\u4E01 +40=\u80D6\u53EF\u4E01 +41=\u8D85\u97F3\u8760 +42=\u5927\u5634\u8760 +43=\u8D70\u8DEF\u8349 +44=\u81ED\u81ED\u82B1 +45=\u9738\u738B\u82B1 +46=\u6D3E\u62C9\u65AF +47=\u6D3E\u62C9\u65AF\u7279 +48=\u6BDB\u7403 +49=\u6469\u9C81\u86FE +50=\u5730\u9F20 +51=\u4E09\u5730\u9F20 +52=\u55B5\u55B5 +53=\u732B\u8001\u5927 +54=\u53EF\u8FBE\u9E2D +55=\u54E5\u8FBE\u9E2D +56=\u7334\u602A +57=\u706B\u66B4\u7334 +58=\u5361\u8482\u72D7 +59=\u98CE\u901F\u72D7 +60=\u868A\u9999\u874C\u86AA +61=\u868A\u9999\u541B +62=\u868A\u9999\u6CF3\u58EB +63=\u51EF\u897F +64=\u52C7\u57FA\u62C9 +65=\u80E1\u5730 +66=\u8155\u529B +67=\u8C6A\u529B +68=\u602A\u529B +69=\u5587\u53ED\u82BD +70=\u53E3\u5446\u82B1 +71=\u5927\u98DF\u82B1 +72=\u739B\u7459\u6C34\u6BCD +73=\u6BD2\u523A\u6C34\u6BCD +74=\u5C0F\u62F3\u77F3 +75=\u9686\u9686\u77F3 +76=\u9686\u9686\u5CA9 +77=\u5C0F\u706B\u9A6C +78=\u70C8\u7130\u9A6C +79=\u5446\u5446\u517D +80=\u5446\u58F3\u517D +81=\u5C0F\u78C1\u602A +82=\u4E09\u5408\u4E00\u78C1\u602A +83=\u5927\u8471\u9E2D +84=\u561F\u561F +85=\u561F\u561F\u5229 +86=\u5C0F\u6D77\u72EE +87=\u767D\u6D77\u72EE +88=\u81ED\u6CE5 +89=\u81ED\u81ED\u6CE5 +90=\u5927\u820C\u8D1D +91=\u523A\u7532\u8D1D +92=\u9B3C\u65AF +93=\u9B3C\u65AF\u901A +94=\u803F\u9B3C +95=\u5927\u5CA9\u86C7 +96=\u50AC\u7720\u8C98 +97=\u5F15\u68A6\u8C98\u4EBA +98=\u5927\u94B3\u87F9 +99=\u5DE8\u94B3\u87F9 +100=\u9739\u96F3\u7535\u7403 +101=\u987D\u76AE\u96F7\u5F39 +102=\u86CB\u86CB +103=\u6930\u86CB\u6811 +104=\u5361\u62C9\u5361\u62C9 +105=\u560E\u5566\u560E\u5566 +106=\u98DE\u817F\u90CE +107=\u5FEB\u62F3\u90CE +108=\u5927\u820C\u5934 +109=\u74E6\u65AF\u5F39 +110=\u53CC\u5F39\u74E6\u65AF +111=\u72EC\u89D2\u7280\u725B +112=\u94BB\u89D2\u7280\u517D +113=\u5409\u5229\u86CB +114=\u8513\u85E4\u602A +115=\u888B\u517D +116=\u58A8\u6D77\u9A6C +117=\u6D77\u523A\u9F99 +118=\u89D2\u91D1\u9C7C +119=\u91D1\u9C7C\u738B +120=\u6D77\u661F\u661F +121=\u5B9D\u77F3\u6D77\u661F +122=\u9B54\u5899\u4EBA\u5076 +123=\u98DE\u5929\u87B3\u8782 +124=\u8FF7\u5507\u59D0 +125=\u7535\u51FB\u517D +126=\u9E2D\u5634\u706B\u517D +127=\u51EF\u7F57\u65AF +128=\u80AF\u6CF0\u7F57 +129=\u9CA4\u9C7C\u738B +130=\u66B4\u9CA4\u9F99 +131=\u62C9\u666E\u62C9\u65AF +132=\u767E\u53D8\u602A +133=\u4F0A\u5E03 +134=\u6C34\u4F0A\u5E03 +135=\u96F7\u4F0A\u5E03 +136=\u706B\u4F0A\u5E03 +137=\u591A\u8FB9\u517D +138=\u83CA\u77F3\u517D +139=\u591A\u523A\u83CA\u77F3\u517D +140=\u5316\u77F3\u76D4 +141=\u9570\u5200\u76D4 +142=\u5316\u77F3\u7FFC\u9F99 +143=\u5361\u6BD4\u517D +144=\u6025\u51BB\u9E1F +145=\u95EA\u7535\u9E1F +146=\u706B\u7130\u9E1F +147=\u8FF7\u4F60\u9F99 +148=\u54C8\u514B\u9F99 +149=\u5FEB\u9F99 +150=\u8D85\u68A6 +151=\u68A6\u5E7B +152=\u83CA\u8349\u53F6 +153=\u6708\u6842\u53F6 +154=\u5927\u83CA\u82B1 +155=\u706B\u7403\u9F20 +156=\u706B\u5CA9\u9F20 +157=\u706B\u66B4\u517D +158=\u5C0F\u952F\u9CC4 +159=\u84DD\u9CC4 +160=\u5927\u529B\u9CC4 +161=\u5C3E\u7ACB +162=\u5927\u5C3E\u7ACB +163=\u5495\u5495 +164=\u732B\u5934\u591C\u9E70 +165=\u82AD\u74E2\u866B +166=\u5B89\u74E2\u866B +167=\u7EBF\u7403 +168=\u963F\u5229\u591A\u65AF +169=\u53C9\u5B57\u8760 +170=\u706F\u7B3C\u9C7C +171=\u7535\u706F\u602A +172=\u76AE\u4E18 +173=\u76AE\u5B9D\u5B9D +174=\u5B9D\u5B9D\u4E01 +175=\u6CE2\u514B\u6BD4 +176=\u6CE2\u514B\u57FA\u53E4 +177=\u5929\u7136\u96C0 +178=\u5929\u7136\u9E1F +179=\u54A9\u5229\u7F8A +180=\u7EF5\u7EF5 +181=\u7535\u9F99 +182=\u7F8E\u4E3D\u82B1 +183=\u739B\u529B\u9732 +184=\u739B\u529B\u9732\u4E3D +185=\u80E1\u8BF4\u6811 +186=\u725B\u86D9\u541B +187=\u6BFD\u5B50\u8349 +188=\u6BFD\u5B50\u82B1 +189=\u6BFD\u5B50\u7EF5 +190=\u957F\u5C3E\u602A\u624B +191=\u5411\u65E5\u79CD\u5B50 +192=\u5411\u65E5\u82B1\u602A +193=\u9633\u9633\u739B +194=\u4E4C\u6CE2 +195=\u6CBC\u738B +196=\u592A\u9633\u7CBE\u7075 +197=\u6708\u7CBE\u7075 +198=\u9ED1\u6697\u9E26 +199=\u6CB3\u9A6C\u738B +200=\u68A6\u5996 +201=\u672A\u77E5\u56FE\u817E +202=\u679C\u7136\u7FC1 +203=\u9E92\u9E9F\u5947 +204=\u699B\u679C\u7403 +205=\u4F5B\u70C8\u6258\u65AF +206=\u571F\u9F99\u5F1F\u5F1F +207=\u5929\u874E +208=\u5927\u94A2\u86C7 +209=\u5E03\u5362 +210=\u5E03\u5362\u7687 +211=\u5343\u9488\u9C7C +212=\u5DE8\u94B3\u87B3\u8782 +213=\u58F6\u58F6 +214=\u8D6B\u62C9\u514B\u7F57\u65AF +215=\u72C3\u62C9 +216=\u718A\u5B9D\u5B9D +217=\u5708\u5708\u718A +218=\u7194\u5CA9\u866B +219=\u7194\u5CA9\u8717\u725B +220=\u5C0F\u5C71\u732A +221=\u957F\u6BDB\u732A +222=\u592A\u9633\u73CA\u745A +223=\u94C1\u70AE\u9C7C +224=\u7AE0\u9C7C\u6876 +225=\u4FE1\u4F7F\u9E1F +226=\u5DE8\u7FC5\u98DE\u9C7C +227=\u76D4\u7532\u9E1F +228=\u6234\u9C81\u6BD4 +229=\u9ED1\u9C81\u52A0 +230=\u523A\u9F99\u738B +231=\u5C0F\u5C0F\u8C61 +232=\u987F\u7532 +233=3D\u9F99II +234=\u60CA\u89D2\u9E7F +235=\u56FE\u56FE\u72AC +236=\u5DF4\u5C14\u90CE +237=\u67EF\u6CE2\u6717 +238=\u8FF7\u5507\u5A03 +239=\u7535\u51FB\u602A +240=\u5C0F\u9E2D\u5634\u9F99 +241=\u5927\u5976\u7F50 +242=\u5E78\u798F\u86CB +243=\u96F7\u516C +244=\u708E\u5E1D +245=\u6C34\u541B +246=\u7531\u57FA\u62C9 +247=\u6C99\u57FA\u62C9 +248=\u73ED\u5409\u62C9 +249=\u6D1B\u5947\u4E9A +250=\u51E4\u738B +251=\u96EA\u62C9\u6BD4 +252=\u6728\u5B88\u5BAB +253=\u68EE\u6797\u8725\u8734 +254=\u8725\u8734\u738B +255=\u706B\u7A1A\u9E21 +256=\u529B\u58EE\u9E21 +257=\u706B\u7130\u9E21 +258=\u6C34\u8DC3\u9C7C +259=\u6CBC\u8DC3\u9C7C +260=\u5DE8\u6CBC\u602A +261=\u571F\u72FC\u72AC +262=\u5927\u72FC\u72AC +263=\u86C7\u7EB9\u718A +264=\u76F4\u51B2\u718A +265=\u523A\u5C3E\u866B +266=\u7532\u58F3\u86F9 +267=\u72E9\u730E\u51E4\u8776 +268=\u76FE\u7532\u8327 +269=\u6BD2\u7C89\u8776 +270=\u83B2\u53F6\u7AE5\u5B50 +271=\u83B2\u5E3D\u5C0F\u7AE5 +272=\u4E50\u5929\u6CB3\u7AE5 +273=\u6A61\u5B9E\u679C +274=\u957F\u9F3B\u53F6 +275=\u72E1\u733E\u5929\u72D7 +276=\u50B2\u9AA8\u71D5 +277=\u5927\u738B\u71D5 +278=\u957F\u7FC5\u9E25 +279=\u5927\u5634\u9E25 +280=\u62C9\u9C81\u62C9\u4E1D +281=\u5947\u9C81\u8389\u5B89 +282=\u6C99\u5948\u6735 +283=\u6E9C\u6E9C\u7CD6\u7403 +284=\u96E8\u7FC5\u86FE +285=\u8611\u8611\u83C7 +286=\u6597\u7B20\u83C7 +287=\u61D2\u4EBA\u7FC1 +288=\u8FC7\u52A8\u733F +289=\u8BF7\u5047\u738B +290=\u571F\u5C45\u5FCD\u58EB +291=\u94C1\u9762\u5FCD\u8005 +292=\u8131\u58F3\u5FCD\u8005 +293=\u5495\u599E\u599E +294=\u543C\u7206\u5F39 +295=\u7206\u97F3\u602A +296=\u5E55\u4E0B\u529B\u58EB +297=\u8D85\u529B\u738B +298=\u9732\u529B\u4E3D +299=\u671D\u5317\u9F3B +300=\u5411\u5C3E\u55B5 +301=\u4F18\u96C5\u732B +302=\u52FE\u9B42\u773C +303=\u5927\u5634\u5A03 +304=\u53EF\u53EF\u591A\u62C9 +305=\u53EF\u591A\u62C9 +306=\u6CE2\u58EB\u53EF\u591A\u62C9 +307=\u739B\u6C99\u90A3 +308=\u6070\u96F7\u59C6 +309=\u843D\u96F7\u517D +310=\u96F7\u7535\u517D +311=\u6B63\u7535\u62CD\u62CD +312=\u8D1F\u7535\u62CD\u62CD +313=\u7535\u8424\u866B +314=\u751C\u751C\u8424 +315=\u6BD2\u8537\u8587 +316=\u6EB6\u98DF\u517D +317=\u541E\u98DF\u517D +318=\u5229\u7259\u9C7C +319=\u5DE8\u7259\u9CA8 +320=\u543C\u543C\u9CB8 +321=\u543C\u9CB8\u738B +322=\u5446\u706B\u9A7C +323=\u55B7\u706B\u9A7C +324=\u7164\u70AD\u9F9F +325=\u8DF3\u8DF3\u732A +326=\u5657\u5657\u732A +327=\u6643\u6643\u6591 +328=\u5927\u989A\u8681 +329=\u8D85\u97F3\u6CE2\u5E7C\u866B +330=\u6C99\u6F20\u873B\u8713 +331=\u6C99\u6F20\u5948\u4E9A +332=\u68A6\u6B4C\u5948\u4E9A +333=\u9752\u7EF5\u9E1F +334=\u4E03\u5915\u9752\u9E1F +335=\u732B\u9F2C\u65A9 +336=\u996D\u5319\u86C7 +337=\u6708\u77F3 +338=\u592A\u9633\u5CA9 +339=\u6CE5\u6CE5\u9CC5 +340=\u9CB6\u9C7C\u738B +341=\u9F99\u867E\u5C0F\u5175 +342=\u94C1\u87AF\u9F99\u867E +343=\u5929\u79E4\u5076 +344=\u5FF5\u529B\u571F\u5076 +345=\u89E6\u624B\u767E\u5408 +346=\u6447\u7BEE\u767E\u5408 +347=\u592A\u53E4\u7FBD\u866B +348=\u592A\u53E4\u76D4\u7532 +349=\u7B28\u7B28\u9C7C +350=\u7F8E\u7EB3\u65AF +351=\u6F02\u6D6E\u6CE1\u6CE1 +352=\u53D8\u9690\u9F99 +353=\u6028\u5F71\u5A03\u5A03 +354=\u8BC5\u5492\u5A03\u5A03 +355=\u591C\u9AB7\u9885 +356=\u591C\u5DE8\u4EBA +357=\u70ED\u5E26\u9F99 +358=\u98CE\u94C3\u94C3 +359=\u963F\u52C3\u68AD\u9C81 +360=\u5C0F\u679C\u7136 +361=\u96EA\u7AE5\u5B50 +362=\u51B0\u9B3C\u62A4 +363=\u6D77\u8C79\u7403 +364=\u6D77\u9B54\u72EE +365=\u5E1D\u7259\u6D77\u72EE +366=\u73CD\u73E0\u8D1D +367=\u730E\u6591\u9C7C +368=\u6A31\u82B1\u9C7C +369=\u53E4\u7A7A\u68D8\u9C7C +370=\u7231\u5FC3\u9C7C +371=\u5B9D\u8D1D\u9F99 +372=\u7532\u58F3\u9F99 +373=\u66B4\u98DE\u9F99 +374=\u94C1\u54D1\u94C3 +375=\u91D1\u5C5E\u602A +376=\u5DE8\u91D1\u602A +377=\u96F7\u5409\u6D1B\u514B +378=\u96F7\u5409\u827E\u65AF +379=\u96F7\u5409\u65AF\u5947\u9C81 +380=\u62C9\u5E1D\u4E9A\u65AF +381=\u62C9\u5E1D\u6B27\u65AF +382=\u76D6\u6B27\u5361 +383=\u56FA\u62C9\u591A +384=\u70C8\u7A7A\u5750 +385=\u57FA\u62C9\u7948 +386=\u4EE3\u6B27\u5947\u5E0C\u65AF +387=\u8349\u82D7\u9F9F +388=\u6811\u6797\u9F9F +389=\u571F\u53F0\u9F9F +390=\u5C0F\u706B\u7130\u7334 +391=\u731B\u706B\u7334 +392=\u70C8\u7130\u7334 +393=\u6CE2\u52A0\u66FC +394=\u6CE2\u7687\u5B50 +395=\u5E1D\u738B\u62FF\u6CE2 +396=\u59C6\u514B\u513F +397=\u59C6\u514B\u9E1F +398=\u59C6\u514B\u9E70 +399=\u5927\u7259\u72F8 +400=\u5927\u5C3E\u72F8 +401=\u5706\u6CD5\u5E08 +402=\u97F3\u7BB1\u87C0 +403=\u5C0F\u732B\u602A +404=\u52D2\u514B\u732B +405=\u4F26\u7434\u732B +406=\u542B\u7F9E\u82DE +407=\u7F57\u4E1D\u96F7\u6735 +408=\u5934\u76D6\u9F99 +409=\u6218\u69CC\u9F99 +410=\u76FE\u7532\u9F99 +411=\u62A4\u57CE\u9F99 +412=\u7ED3\u8349\u513F +413=\u7ED3\u8349\u8D35\u5987 +414=\u7EC5\u58EB\u86FE +415=\u4E09\u871C\u8702 +416=\u8702\u540E +417=\u5E15\u5947\u5229\u5179 +418=\u6CF3\u6C14\u9F2C +419=\u6D6E\u6F5C\u9F2C +420=\u6A31\u82B1\u5B9D +421=\u6A31\u82B1\u513F +422=\u65E0\u58F3\u6D77\u725B +423=\u6D77\u725B\u517D +424=\u53CC\u5C3E\u602A\u624B +425=\u98D8\u98D8\u7403 +426=\u9644\u548C\u6C14\u7403 +427=\u5377\u5377\u8033 +428=\u957F\u8033\u5154 +429=\u68A6\u5996\u9B54 +430=\u4E4C\u9E26\u5934\u5934 +431=\u9B45\u529B\u55B5 +432=\u4E1C\u65BD\u55B5 +433=\u94C3\u94DB\u54CD +434=\u81ED\u9F2C\u5657 +435=\u5766\u514B\u81ED\u9F2C +436=\u94DC\u955C\u602A +437=\u9752\u94DC\u949F +438=\u7231\u54ED\u6811 +439=\u9B54\u5C3C\u5C3C +440=\u597D\u8FD0\u86CB +441=\u8052\u566A\u9E1F +442=\u82B1\u5CA9\u602A +443=\u5706\u9646\u9CA8 +444=\u5C16\u7259\u9646\u9CA8 +445=\u70C8\u54AC\u9646\u9CA8 +446=\u5C0F\u5361\u6BD4\u517D +447=\u5229\u6B27\u8DEF +448=\u8DEF\u5361\u5229\u6B27 +449=\u602A\u6CB3\u9A6C +450=\u6CB3\u9A6C\u517D +451=\u7D2B\u5929\u874E +452=\u9F99\u738B\u874E +453=\u4E0D\u826F\u86D9 +454=\u6BD2\u9AB7\u86D9 +455=\u5C16\u7259\u7B3C +456=\u8424\u5149\u9C7C +457=\u9713\u8679\u9C7C +458=\u5C0F\u7403\u98DE\u9C7C +459=\u96EA\u7B20\u602A +460=\u66B4\u96EA\u738B +461=\u739B\u72C3\u62C9 +462=\u81EA\u7206\u78C1\u602A +463=\u5927\u820C\u8214 +464=\u8D85\u94C1\u66B4\u9F99 +465=\u5DE8\u8513\u85E4 +466=\u7535\u51FB\u9B54\u517D +467=\u9E2D\u5634\u7130\u9F99 +468=\u6CE2\u514B\u57FA\u65AF +469=\u6885\u5361\u9633\u739B +470=\u53F6\u7CBE\u7075 +471=\u51B0\u7CBE\u7075 +472=\u5929\u874E\u738B +473=\u8C61\u7259\u732A +474=3D\u9F99Z +475=\u827E\u8DEF\u96F7\u6735 +476=\u5927\u671D\u5317\u9F3B +477=\u591C\u9ED1\u9B54\u4EBA +478=\u96EA\u5996\u5973 +479=\u6D1B\u6258\u59C6 +480=\u7531\u514B\u5E0C +481=\u827E\u59C6\u5229\u591A +482=\u4E9A\u514B\u8BFA\u59C6 +483=\u5E1D\u7259\u5362\u5361 +484=\u5E15\u8DEF\u5947\u72BD +485=\u5E2D\u591A\u84DD\u6069 +486=\u96F7\u5409\u5947\u5361\u65AF +487=\u9A91\u62C9\u5E1D\u7EB3 +488=\u514B\u96F7\u8272\u5229\u4E9A +489=\u970F\u6B27\u7EB3 +490=\u739B\u7EB3\u970F +491=\u8FBE\u514B\u83B1\u4F0A +492=\u8C22\u7C73 +493=\u963F\u5C14\u5B99\u65AF +494=\u6BD4\u514B\u63D0\u5C3C +495=\u85E4\u85E4\u86C7 +496=\u9752\u85E4\u86C7 +497=\u541B\u4E3B\u86C7 +498=\u6696\u6696\u732A +499=\u7092\u7092\u732A +500=\u708E\u6B66\u738B +501=\u6C34\u6C34\u736D +502=\u53CC\u5203\u4E38 +503=\u5927\u5251\u9B3C +504=\u63A2\u63A2\u9F20 +505=\u6B65\u54E8\u9F20 +506=\u5C0F\u7EA6\u514B +507=\u54C8\u7EA6\u514B +508=\u957F\u6BDB\u72D7 +509=\u6252\u624B\u732B +510=\u9177\u8C79 +511=\u82B1\u6930\u7334 +512=\u82B1\u6930\u733F +513=\u7206\u9999\u7334 +514=\u7206\u9999\u733F +515=\u51B7\u6C34\u7334 +516=\u51B7\u6C34\u733F +517=\u98DF\u68A6\u68A6 +518=\u68A6\u68A6\u8680 +519=\u8C46\u8C46\u9E3D +520=\u6CE2\u6CE2\u9E3D +521=\u8F70\u9686\u96C9\u9E21 +522=\u6591\u6591\u9A6C +523=\u96F7\u7535\u6591\u9A6C +524=\u77F3\u4E38\u5B50 +525=\u5730\u5E54\u5CA9 +526=\u5E9E\u5CA9\u602A +527=\u6EDA\u6EDA\u8759\u8760 +528=\u5FC3\u8759\u8760 +529=\u87BA\u9489\u5730\u9F20 +530=\u9F99\u5934\u5730\u9F20 +531=\u5DEE\u4E0D\u591A\u5A03\u5A03 +532=\u642C\u8FD0\u5C0F\u5320 +533=\u94C1\u9AA8\u571F\u4EBA +534=\u4FEE\u7F2E\u8001\u5934 +535=\u5706\u874C\u86AA +536=\u84DD\u87FE\u870D +537=\u87FE\u870D\u738B +538=\u6295\u5C04\u9B3C +539=\u6253\u51FB\u9B3C +540=\u866B\u5B9D\u5305 +541=\u5B9D\u5305\u8327 +542=\u4FDD\u6BCD\u866B +543=\u767E\u8DB3\u8708\u86A3 +544=\u8F66\u8F6E\u7403 +545=\u8708\u86A3\u738B +546=\u6728\u68C9\u7403 +547=\u98CE\u5996\u7CBE +548=\u767E\u5408\u6839\u5A03\u5A03 +549=\u88D9\u513F\u5C0F\u59D0 +550=\u52C7\u58EB\u9C88\u9C7C +551=\u9ED1\u773C\u9CC4 +552=\u6DF7\u6DF7\u9CC4 +553=\u6D41\u6C13\u9CC4 +554=\u706B\u7EA2\u4E0D\u5012\u7FC1 +555=\u8FBE\u6469\u72D2\u72D2 +556=\u8857\u5934\u6C99\u94C3 +557=\u77F3\u5C45\u87F9 +558=\u5CA9\u6BBF\u5C45\u87F9 +559=\u6ED1\u5934\u5C0F\u5B50 +560=\u5934\u5DFE\u6DF7\u6DF7 +561=\u8C61\u5F81\u9E1F +562=\u54ED\u54ED\u9762\u5177 +563=\u6B7B\u795E\u68FA +564=\u539F\u76D6\u6D77\u9F9F +565=\u808B\u9AA8\u6D77\u9F9F +566=\u59CB\u7956\u5C0F\u9E1F +567=\u59CB\u7956\u5927\u9E1F +568=\u7834\u7834\u888B +569=\u7070\u5C18\u5C71 +570=\u7D22\u7F57\u4E9A +571=\u7D22\u7F57\u4E9A\u514B +572=\u6CE1\u6CAB\u6817\u9F20 +573=\u5947\u8BFA\u6817\u9F20 +574=\u54E5\u5FB7\u5B9D\u5B9D +575=\u54E5\u5FB7\u5C0F\u7AE5 +576=\u54E5\u5FB7\u5C0F\u59D0 +577=\u5355\u5375\u7EC6\u80DE\u7403 +578=\u53CC\u5375\u7EC6\u80DE\u7403 +579=\u4EBA\u9020\u7EC6\u80DE\u5375 +580=\u9E2D\u5B9D\u5B9D +581=\u9996\u5E2D\u5929\u9E45 +582=\u8FF7\u4F60\u51B0 +583=\u591A\u591A\u51B0 +584=\u53CC\u500D\u591A\u591A\u51B0 +585=\u56DB\u5B63\u9E7F +586=\u82BD\u5439\u9E7F +587=\u7535\u98DE\u9F20 +588=\u76D6\u76D6\u866B +589=\u9A91\u58EB\u8717\u725B +590=\u5B9D\u8D1D\u7403\u83C7 +591=\u66B4\u9732\u83C7 +592=\u8F7B\u98D8\u98D8 +593=\u80D6\u561F\u561F +594=\u4FDD\u6BCD\u66FC\u6CE2 +595=\u7535\u7535\u866B +596=\u7535\u8718\u86DB +597=\u79CD\u5B50\u94C1\u7403 +598=\u575A\u679C\u54D1\u94C3 +599=\u9F7F\u8F6E\u513F +600=\u9F7F\u8F6E\u7EC4 +601=\u9F7F\u8F6E\u602A +602=\u9EBB\u9EBB\u5C0F\u9C7C +603=\u9EBB\u9EBB\u9CD7 +604=\u9EBB\u9EBB\u9CD7\u9C7C\u738B +605=\u5C0F\u7070\u602A +606=\u5927\u5B87\u602A +607=\u70DB\u5149\u7075 +608=\u706F\u706B\u5E7D\u7075 +609=\u6C34\u6676\u706F\u706B\u7075 +610=\u7259\u7259 +611=\u65A7\u7259\u9F99 +612=\u53CC\u65A7\u6218\u9F99 +613=\u55B7\u568F\u718A +614=\u51BB\u539F\u718A +615=\u51E0\u4F55\u96EA\u82B1 +616=\u5C0F\u5634\u8717 +617=\u654F\u6377\u866B +618=\u6CE5\u5DF4\u9C7C +619=\u529F\u592B\u9F2C +620=\u5E08\u7236\u9F2C +621=\u8D64\u9762\u9F99 +622=\u6CE5\u5076\u5C0F\u4EBA +623=\u6CE5\u5076\u5DE8\u4EBA +624=\u9A79\u5200\u5C0F\u5175 +625=\u5288\u65A9\u53F8\u4EE4 +626=\u7206\u7206\u5934\u6C34\u725B +627=\u6BDB\u5934\u5C0F\u9E70 +628=\u52C7\u58EB\u9E70 +629=\u79C3\u9E70\u5C0F\u5B50 +630=\u79C3\u9E70\u5A1C +631=\u98DF\u8681\u7089 +632=\u94C1\u8681 +633=\u5355\u9996\u9F99 +634=\u53CC\u5934\u9F99 +635=\u4E09\u5934\u9F99 +636=\u71C3\u70E7\u866B +637=\u706B\u795E\u866B +638=\u52FE\u5E15\u8DEF\u7FC1 +639=\u4EE3\u62C9\u57FA\u7FC1 +640=\u6BD5\u529B\u5409\u7FC1 +641=\u9F99\u5377\u4E91 +642=\u96F7\u7535\u4E91 +643=\u96F7\u5E0C\u62C9\u59C6 +644=\u6377\u514B\u7F57\u59C6 +645=\u571F\u5730\u4E91 +646=\u914B\u96F7\u59C6 +647=\u51EF\u8DEF\u8FEA\u6B27 +648=\u7F8E\u6D1B\u8036\u5854 +649=\u76D6\u8BFA\u8D5B\u514B\u7279 +650=\u54C8\u529B\u6817 +651=\u80D6\u80D6\u54C8\u529B +652=\u5E03\u91CC\u5361\u9686 +653=\u706B\u72D0\u72F8 +654=\u957F\u5C3E\u706B\u72D0 +655=\u5996\u706B\u7EA2\u72D0 +656=\u5471\u5471\u6CE1\u86D9 +657=\u5471\u5934\u86D9 +658=\u7532\u8D3A\u5FCD\u86D9 +659=\u6398\u6398\u5154 +660=\u6509\u571F\u5154 +661=\u5C0F\u7BAD\u96C0 +662=\u706B\u7BAD\u96C0 +663=\u70C8\u7BAD\u9E5F +664=\u7C89\u86F9 +665=\u7C89\u8776\u86F9 +666=\u78A7\u7C89\u8776 +667=\u5C0F\u72EE\u72EE +668=\u706B\u708E\u72EE +669=\u82B1\u84D3\u84D3 +670=\u82B1\u53F6\u8482 +671=\u82B1\u6D01\u592B\u4EBA +672=\u54A9\u54A9\u7F8A +673=\u5750\u9A91\u5C71\u7F8A +674=\u987D\u76AE\u718A\u732B +675=\u6D41\u6C13\u718A\u732B +676=\u591A\u4E3D\u7C73\u4E9A +677=\u5999\u55B5 +678=\u8D85\u80FD\u5999\u55B5 +679=\u72EC\u5251\u9798 +680=\u53CC\u5251\u9798 +681=\u575A\u76FE\u5251\u602A +682=\u7C89\u9999\u9999 +683=\u82B3\u9999\u7CBE +684=\u7EF5\u7EF5\u6CE1\u8299 +685=\u80D6\u751C\u59AE +686=\u8C6A\u5587\u82B1\u679D +687=\u4E4C\u8D3C\u738B +688=\u9F9F\u811A\u811A +689=\u9F9F\u8DB3\u5DE8\u94E0 +690=\u5783\u5783\u85FB +691=\u6BD2\u62C9\u871C\u59AE +692=\u94C1\u81C2\u67AA\u867E +693=\u94A2\u70AE\u81C2\u867E +694=\u4F1E\u7535\u8725 +695=\u7535\u4F1E\u67E5\u7279 +696=\u5B9D\u5B9D\u66B4\u9F99 +697=\u602A\u989A\u9F99 +698=\u51B0\u96EA\u9F99 +699=\u51B0\u96EA\u5DE8\u9F99 +700=\u4ED9\u5B50\u7CBE\u7075 +701=\u6218\u6597\u98DE\u9E1F +702=\u549A\u549A\u9F20 +703=\u5C0F\u788E\u94BB +704=\u9ECF\u9ECF\u5B9D +705=\u9ECF\u7F8E\u4F0A\u513F +706=\u9ECF\u7F8E\u9732\u9F99 +707=\u94A5\u5708\u513F +708=\u5C0F\u6728\u7075 +709=\u673D\u6728\u5996 +710=\u5357\u74DC\u7CBE +711=\u5357\u74DC\u602A\u4EBA +712=\u51B0\u5B9D +713=\u51B0\u5CA9\u602A +714=\u55E1\u8760 +715=\u97F3\u6CE2\u9F99 +716=\u54F2\u5C14\u5C3C\u4E9A\u65AF +717=\u4F0A\u88F4\u5C14\u5854\u5C14 +718=\u57FA\u683C\u5C14\u5FB7 +719=\u8482\u5B89\u5E0C +720=\u80E1\u5E15 +721=\u6CE2\u5C14\u51EF\u5C3C\u6069 \ No newline at end of file diff --git a/src/main/resources/pokemon_names_zh_HK.properties b/src/main/resources/pokemon_names_zh_HK.properties new file mode 100644 index 00000000..55b629f8 --- /dev/null +++ b/src/main/resources/pokemon_names_zh_HK.properties @@ -0,0 +1,151 @@ +1=\u5947\u7570\u7A2E\u5B50 +2=\u5947\u7570\u8349 +3=\u5947\u7570\u82B1 +4=\u5C0F\u706B\u9F8D +5=\u706B\u6050\u9F8D +6=\u5674\u706B\u9F8D +7=\u8ECA\u5398\u9F9C +8=\u5361\u7F8E\u9F9C +9=\u6C34\u7BAD\u9F9C +10=\u7DA0\u6BDB\u87F2 +11=\u9435\u7532\u87F2 +12=\u5DF4\u4ED6\u8776 +13=\u7368\u89D2\u87F2 +14=\u9435\u6BBC\u86F9 +15=\u5927\u91DD\u8702 +16=\u6CE2\u6CE2 +17=\u6BD4\u6BD4\u9CE5 +18=\u5927\u6BD4\u9CE5 +19=\u5C0F\u54E5\u9054 +20=\u54E5\u9054 +21=\u9B3C\u96C0 +22=\u9B54\u96C0 +23=\u963F\u67CF\u86C7 +24=\u963F\u67CF\u602A +25=\u6BD4\u5361\u8D85 +26=\u96F7\u8D85 +27=\u7A7F\u5C71\u9F20 +28=\u7A7F\u5C71\u738B +29=\u5C3C\u7F8E\u862D +30=\u5C3C\u7F8E\u863F +31=\u5C3C\u7F8E\u540E +32=\u5C3C\u591A\u90CE +33=\u5C3C\u591A\u5229 +34=\u5C3C\u591A\u738B +35=\u76AE\u76AE +36=\u76AE\u53EF\u65AF +37=\u516D\u5C3E +38=\u4E5D\u5C3E +39=\u6CE2\u6CE2\u7403 +40=\u80A5\u6CE2\u7403 +41=\u6CE2\u97F3\u8760 +42=\u5927\u53E3\u8760 +43=\u884C\u8DEF\u8349 +44=\u602A\u5473\u82B1 +45=\u9738\u738B\u82B1 +46=\u8611\u83C7\u87F2 +47=\u5DE8\u83C7\u87F2 +48=\u6BDB\u6BDB\u87F2 +49=\u9B54\u9B6F\u98A8 +50=\u5730\u9F20 +51=\u4E09\u982D\u5730\u9F20 +52=\u55B5\u55B5\u602A +53=\u9AD8\u7AC7\u8C93 +54=\u50BB\u9D28 +55=\u9AD8\u8D85\u9D28 +56=\u7334\u602A +57=\u706B\u7206\u7334 +58=\u8B77\u4E3B\u72AC +59=\u5949\u795E\u72AC +60=\u868A\u9999\u874C\u86AA +61=\u868A\u9999\u86D9 +62=\u5927\u529B\u86D9 +63=\u5361\u65AF +64=\u5C24\u57FA\u7D0D +65=\u5BCC\u8FEA +66=\u9435\u8155 +67=\u5927\u529B +68=\u602A\u529B +69=\u5587\u53ED\u82BD +70=\u53E3\u5446\u82B1 +71=\u5927\u98DF\u82B1 +72=\u5927\u773C\u6C34\u6BCD +73=\u591A\u8173\u6C34\u6BCD +74=\u5C0F\u62F3\u77F3 +75=\u6EFE\u52D5\u77F3 +76=\u6EFE\u52D5\u5CA9 +77=\u5C0F\u706B\u99AC +78=\u70C8\u7130\u99AC +79=\u5C0F\u5446\u7378 +80=\u5927\u5446\u7378 +81=\u5C0F\u78C1\u602A +82=\u4E09\u5408\u4E00\u78C1\u602A +83=\u706B\u8525\u9D28 +84=\u591A\u591A +85=\u591A\u591A\u5229 +86=\u5C0F\u6D77\u7345 +87=\u767D\u6D77\u7345 +88=\u721B\u6CE5\u602A +89=\u721B\u6CE5\u7378 +90=\u8C9D\u6BBC\u602A +91=\u9435\u7532\u8C9D +92=\u9B3C\u65AF +93=\u9B3C\u65AF\u901A +94=\u803F\u9B3C +95=\u5927\u5CA9\u86C7 +96=\u98DF\u5922\u7378 +97=\u50AC\u7720\u7378 +98=\u5927\u9257\u87F9 +99=\u5DE8\u9257\u87F9 +100=\u9739\u9742\u86CB +101=\u96F7\u9706\u86CB +102=\u86CB\u86CB +103=\u6930\u6A39\u7378 +104=\u5361\u62C9\u5361\u62C9 +105=\u683C\u62C9\u683C\u62C9 +106=\u6C99\u53E4\u62C9 +107=\u6BD4\u83EF\u62C9 +108=\u5927\u820C\u982D +109=\u6BD2\u6C23\u4E38 +110=\u6BD2\u6C23\u96D9\u5B50 +111=\u9435\u7532\u7280\u725B +112=\u9435\u7532\u66B4\u9F8D +113=\u5409\u5229\u86CB +114=\u9577\u7C50\u602A +115=\u888B\u7378 +116=\u5674\u58A8\u6D77\u99AC +117=\u98DB\u523A\u6D77\u99AC +118=\u7368\u89D2\u91D1\u9B5A +119=\u91D1\u9B5A\u738B +120=\u6D77\u661F\u661F +121=\u5BF6\u77F3\u6D77\u661F +122=\u5438\u76E4\u5C0F\u4E11 +123=\u98DB\u5929\u87B3\u8782 +124=\u7D05\u5507\u5A03 +125=\u96FB\u64CA\u7378 +126=\u9D28\u5634\u706B\u9F8D +127=\u9257\u5200\u7532\u87F2 +128=\u5927\u96BB\u725B +129=\u9BC9\u9B5A\u738B +130=\u9BC9\u9B5A\u9F8D +131=\u80CC\u80CC\u9F8D +132=\u767E\u8B8A\u602A +133=\u4F0A\u8C9D +134=\u6C34\u4F0A\u8C9D +135=\u96F7\u4F0A\u8C9D +136=\u706B\u4F0A\u8C9D +137=\u7ACB\u65B9\u7378 +138=\u83CA\u77F3\u7378 +139=\u591A\u523A\u83CA\u77F3\u7378 +140=\u842C\u5E74\u87F2 +141=\u942E\u5200\u87F2 +142=\u5316\u77F3\u98DB\u9F8D +143=\u5361\u6BD4\u7378 +144=\u6025\u51CD\u9CE5 +145=\u96F7\u9CE5 +146=\u706B\u9CE5 +147=\u8FF7\u4F60\u9F8D +148=\u54C8\u53E4\u9F8D +149=\u555F\u66B4\u9F8D +150=\u8D85\u5922\u5922 +151=\u5922\u5922 \ No newline at end of file