From f3cffbc85356e93131b74bf7a4edfdb13301c914 Mon Sep 17 00:00:00 2001 From: CBRSightings Date: Sun, 10 Dec 2017 22:21:13 +1100 Subject: [PATCH] Cleaning up code and adding small features, heading towards public release --- 100iv.json | 5 + channels.txt | 18 - config.example.ini | 2 + config.ini | 13 +- create-geocoding.sql | 13 +- data/base_stats.json | 3210 +++++++++++ data/moves.json | 1826 +++++++ data/pokemon.json | 4678 +++++++++++++++++ formatting.ini | 3 +- pokechannels.ini | 43 +- pokefilter.json | 860 ++- presets.ini | 7 + raidchannels.ini | 27 + .../{PokeChannel.java => AlertChannel.java} | 9 +- src/core/Config.java | 817 ++- src/core/DBManager.java | 225 +- src/core/FeedChannel.java | 47 - src/core/FeedChannels.java | 100 - src/core/Format.java | 23 + src/core/Location.java | 97 +- src/core/LocationType.java | 1 - src/core/MessageListener.java | 429 +- src/core/NotificationLimit.java | 6 +- src/core/Preset.java | 11 + src/core/RaidChannel.java | 10 + src/core/Reason.java | 20 - src/core/Region.java | 122 +- src/core/RotatingSet.java | 2 +- src/core/ScheduledExecutor.java | 4 +- src/core/Spawn.java | 67 + src/core/SuburbManager.java | 6 +- src/core/Team.java | 49 + src/core/Types.java | 129 + src/core/UserPref.java | 116 +- src/maps/GeocodedLocation.java | 2 +- src/maps/GeofenceIdentifier.java | 4 +- src/maps/Geofencing.java | 4 +- src/maps/ReverseGeocoder.java | 7 +- src/nests/NestSheetManager.java | 2 +- src/notifier/PokeNotificationSender.java | 105 +- src/notifier/PokeNotifier.java | 2 +- src/notifier/RaidNotificationSender.java | 64 +- src/notifier/RaidNotifier.java | 2 +- src/notifier/UserNotifier.java | 2 +- src/parser/ArgType.java | 6 +- src/parser/Command.java | 2 +- src/parser/Commands.java | 26 +- src/parser/InputError.java | 98 +- src/parser/Parser.java | 63 +- src/pokemon/PokeSpawn.java | 185 +- src/pokemon/Pokemon.java | 107 +- src/raids/LobbyManager.java | 8 +- src/raids/LobbyMonitor.java | 4 +- src/raids/Raid.java | 204 +- src/raids/RaidLobby.java | 16 +- src/raids/RaidSpawn.java | 175 +- test.json | 4 + ultrarare.json | 403 +- unown.json | 3 + 59 files changed, 12187 insertions(+), 2306 deletions(-) create mode 100644 100iv.json delete mode 100644 channels.txt create mode 100644 data/base_stats.json create mode 100644 data/moves.json create mode 100644 data/pokemon.json create mode 100644 presets.ini create mode 100644 raidchannels.ini rename src/core/{PokeChannel.java => AlertChannel.java} (73%) delete mode 100644 src/core/FeedChannel.java delete mode 100644 src/core/FeedChannels.java create mode 100644 src/core/Format.java create mode 100644 src/core/Preset.java create mode 100644 src/core/RaidChannel.java delete mode 100644 src/core/Reason.java create mode 100644 src/core/Spawn.java create mode 100644 src/core/Team.java create mode 100644 src/core/Types.java create mode 100644 test.json create mode 100644 unown.json diff --git a/100iv.json b/100iv.json new file mode 100644 index 0000000..1eb8803 --- /dev/null +++ b/100iv.json @@ -0,0 +1,5 @@ +{ + "Default": { + "min_iv": "100" + } +} \ No newline at end of file diff --git a/channels.txt b/channels.txt deleted file mode 100644 index 05736e8..0000000 --- a/channels.txt +++ /dev/null @@ -1,18 +0,0 @@ -271941245826236418 = [inner-north,innernorth] -271802012713222145 = [inner-south,innersouth] -271802067893354497 = [gungahlin-region,gungahlinregion] -271827572386562050 = [belconnen-region,belconnenregion] -271802221224525836 = [woden-weston-region,wodenwestonregion] -271802248189837313 = [tuggeranong-region,tuggeranong] -285439247744368640 = [queanbeyan-region,queanbeyan] -287376190434705409 = [100-iv,100iv,hundrediv] -300098060602703883 = [0-iv,0iv,zeroiv] -285467455290212353 = [dratini-candy,dratinicandy] -291780357114691585 = [mareep-candy,mareepcandy] -274521056780484608 = [snorlax-candy,snorlaxcandy] -282424395849400320 = [larvitar-candy,larvitarcandy] -291750334169350144 = [legacy-rare,legacyrare] -291781579976736768 = [ultra-rare,ultrarare] -280115501122846741 = [event] -300229482126770177 = [dex-filler,dexfiller] -299903745775370240 = [unown-alphabet,unownalphabet] \ No newline at end of file diff --git a/config.example.ini b/config.example.ini index d01ff11..506ac7e 100644 --- a/config.example.ini +++ b/config.example.ini @@ -1,11 +1,13 @@ [config] token = MjkzMzI4Mjc0MDk0ODE3Mjgw.DM8vyg.JUXHgZwuPoO1KfCol9b2iwhOfEM blacklist = [13, 16, 19, 21, 23, 29, 32, 41, 48, 60, 98, 115, 118, 120, 183, 161, 165, 167, 177, 194, 198] +raidBosses = [2,5,8,11,28,31,34,38,62,65,68,71,73,76,82,91,94,105,123,129,131,137,139,143,144,145,146,150,243,244,245,248,249,302] channels = true useRmDb = false standardRaidTable = false googleSuburbField = city pokemon = true +waitForIV = 10 raids = true minRaidLevel = 3 raidChannels = false diff --git a/config.ini b/config.ini index 0407e9f..e62fcde 100644 --- a/config.ini +++ b/config.ini @@ -1,10 +1,12 @@ [config] token = MjkzMzI4Mjc0MDk0ODE3Mjgw.DDDm3w.AcvLVtE9W6GfmLzwmVH5gKoj_gU blacklist = [13, 16, 19, 21, 23, 29, 32, 41, 48, 60, 98, 115, 118, 120, 183, 161, 165, 167, 177, 194, 198] +raidBosses = [2,5,8,11,28,31,34,38,62,65,68,71,73,76,82,91,94,105,123,129,131,137,139,143,144,145,146,150,243,244,245,248,249,302,303,359] useRmDb = false standardRaidTable = false googleSuburbField = city pokemon = true +waitForIV = 10 raids = true minRaidLevel = 3 raidChannels = false @@ -34,18 +36,7 @@ password = mimi ip = localhost port = 3306 dbName = pokemongomapdb -;user = novabot -;password = Password123 -;ip = 192.168.200.210 -;port = 3306 -;dbName = pokemongomapdb -;[novabot db] -;user = novabot -;password = Password123 -;ip = 192.168.200.210 -;port = 3306 -;dbName = pokealerts [novabot db] user = root password = mimi diff --git a/create-geocoding.sql b/create-geocoding.sql index 2698730..dcb82dc 100644 --- a/create-geocoding.sql +++ b/create-geocoding.sql @@ -11,4 +11,15 @@ CREATE TABLE geocoding sublocality VARCHAR(50), country VARCHAR(50), CONSTRAINT `PRIMARY` PRIMARY KEY (lat, lon) -); \ No newline at end of file +); + +create table preset +( + user_id varchar(50) not null, + preset_name varchar(50) not null, + location varchar(50) not null, + primary key (user_id, preset_name, location), + constraint preset_users_id_fk + foreign key (user_id) references users (id) +); + diff --git a/data/base_stats.json b/data/base_stats.json new file mode 100644 index 0000000..ae24395 --- /dev/null +++ b/data/base_stats.json @@ -0,0 +1,3210 @@ +{ + "1" : { + "weight": 6.9, + "height": 0.71 + }, + "2": { + "weight": 13.0, + "height": 0.99 + }, + "3": { + "weight": 100.0, + "height": 2.01 + }, + "4": { + "weight": 8.5, + "height": 0.61 + }, + "5": { + "weight": 19.0, + "height": 1.09 + }, + "6": { + "weight": 90.5, + "height": 1.7 + }, + "7": { + "weight": 9.0, + "height": 0.51 + }, + "8": { + "weight": 22.5, + "height": 0.99 + }, + "9": { + "weight": 85.5, + "height": 1.6 + }, + "10": { + "weight": 2.9, + "height": 0.3 + }, + "11": { + "weight": 9.9, + "height": 0.71 + }, + "12": { + "weight": 32.0, + "height": 1.09 + }, + "13": { + "weight": 3.2, + "height": 0.3 + }, + "14": { + "weight": 10.0, + "height": 0.61 + }, + "15": { + "weight": 29.5, + "height": 0.99 + }, + "16": { + "weight": 1.8, + "height": 0.3 + }, + "17": { + "weight": 30.0, + "height": 1.09 + }, + "18": { + "weight": 39.5, + "height": 1.5 + }, + "19": { + "weight": 3.5, + "height": 0.3 + }, + "20": { + "weight": 18.5, + "height": 0.71 + }, + "21": { + "weight": 2.0, + "height": 0.3 + }, + "22": { + "weight": 38.0, + "height": 1.19 + }, + "23": { + "weight": 6.9, + "height": 2.01 + }, + "24": { + "weight": 65.0, + "height": 3.51 + }, + "25": { + "weight": 6.0, + "height": 0.41 + }, + "26": { + "weight": 30.0, + "height": 0.79 + }, + "27": { + "weight": 12.0, + "height": 0.61 + }, + "28": { + "weight": 29.5, + "height": 0.99 + }, + "29": { + "weight": 7.0, + "height": 0.41 + }, + "30": { + "weight": 20.0, + "height": 0.79 + }, + "31": { + "weight": 60.0, + "height": 1.3 + }, + "32": { + "weight": 9.0, + "height": 0.51 + }, + "33": { + "weight": 19.5, + "height": 0.89 + }, + "34": { + "weight": 62.0, + "height": 1.4 + }, + "35": { + "weight": 7.5, + "height": 0.61 + }, + "36": { + "weight": 40.0, + "height": 1.3 + }, + "37": { + "weight": 9.9, + "height": 0.61 + }, + "38": { + "weight": 19.9, + "height": 1.09 + }, + "39": { + "weight": 5.5, + "height": 0.51 + }, + "40": { + "weight": 12.0, + "height": 0.99 + }, + "41": { + "weight": 7.5, + "height": 0.79 + }, + "42": { + "weight": 55.0, + "height": 1.6 + }, + "43": { + "weight": 5.4, + "height": 0.51 + }, + "44": { + "weight": 8.6, + "height": 0.79 + }, + "45": { + "weight": 18.6, + "height": 1.19 + }, + "46": { + "weight": 5.4, + "height": 0.3 + }, + "47": { + "weight": 29.5, + "height": 0.99 + }, + "48": { + "weight": 30.0, + "height": 0.99 + }, + "49": { + "weight": 12.5, + "height": 1.5 + }, + "50": { + "weight": 0.8, + "height": 0.2 + }, + "51": { + "weight": 33.3, + "height": 0.71 + }, + "52": { + "weight": 4.2, + "height": 0.41 + }, + "53": { + "weight": 32.0, + "height": 0.99 + }, + "54": { + "weight": 19.6, + "height": 0.79 + }, + "55": { + "weight": 76.6, + "height": 1.7 + }, + "56": { + "weight": 28.0, + "height": 0.51 + }, + "57": { + "weight": 32.0, + "height": 0.99 + }, + "58": { + "weight": 19.0, + "height": 0.71 + }, + "59": { + "weight": 155.0, + "height": 1.91 + }, + "60": { + "weight": 12.4, + "height": 0.61 + }, + "61": { + "weight": 20.0, + "height": 0.99 + }, + "62": { + "weight": 54.0, + "height": 1.3 + }, + "63": { + "weight": 19.5, + "height": 0.89 + }, + "64": { + "weight": 56.5, + "height": 1.3 + }, + "65": { + "weight": 48.0, + "height": 1.5 + }, + "66": { + "weight": 19.5, + "height": 0.79 + }, + "67": { + "weight": 70.5, + "height": 1.5 + }, + "68": { + "weight": 130.0, + "height": 1.6 + }, + "69": { + "weight": 4.0, + "height": 0.71 + }, + "70": { + "weight": 6.4, + "height": 0.99 + }, + "71": { + "weight": 15.5, + "height": 1.7 + }, + "72": { + "weight": 45.5, + "height": 0.89 + }, + "73": { + "weight": 55.0, + "height": 1.6 + }, + "74": { + "weight": 20.0, + "height": 0.41 + }, + "75": { + "weight": 105.0, + "height": 0.99 + }, + "76": { + "weight": 300.0, + "height": 1.4 + }, + "77": { + "weight": 30.0, + "height": 0.99 + }, + "78": { + "weight": 95.0, + "height": 1.7 + }, + "79": { + "weight": 36.0, + "height": 1.19 + }, + "80": { + "weight": 78.5, + "height": 1.6 + }, + "81": { + "weight": 6.0, + "height": 0.3 + }, + "82": { + "weight": 60.0, + "height": 0.99 + }, + "83": { + "weight": 15.0, + "height": 0.79 + }, + "84": { + "weight": 39.2, + "height": 1.4 + }, + "85": { + "weight": 85.2, + "height": 1.8 + }, + "86": { + "weight": 90.0, + "height": 1.09 + }, + "87": { + "weight": 120.0, + "height": 1.7 + }, + "88": { + "weight": 30.0, + "height": 0.89 + }, + "89": { + "weight": 30.0, + "height": 1.19 + }, + "90": { + "weight": 4.0, + "height": 0.3 + }, + "91": { + "weight": 132.5, + "height": 1.5 + }, + "92": { + "weight": 0.1, + "height": 1.3 + }, + "93": { + "weight": 0.1, + "height": 1.6 + }, + "94": { + "weight": 40.5, + "height": 1.5 + }, + "95": { + "weight": 210.0, + "height": 8.79 + }, + "96": { + "weight": 32.4, + "height": 0.99 + }, + "97": { + "weight": 75.6, + "height": 1.6 + }, + "98": { + "weight": 6.5, + "height": 0.41 + }, + "99": { + "weight": 60.0, + "height": 1.3 + }, + "100": { + "weight": 10.4, + "height": 0.51 + }, + "101": { + "weight": 66.6, + "height": 1.19 + }, + "102": { + "weight": 2.5, + "height": 0.41 + }, + "103": { + "weight": 120.0, + "height": 2.01 + }, + "104": { + "weight": 6.5, + "height": 0.41 + }, + "105": { + "weight": 45.0, + "height": 0.99 + }, + "106": { + "weight": 49.8, + "height": 1.5 + }, + "107": { + "weight": 50.2, + "height": 1.4 + }, + "108": { + "weight": 65.5, + "height": 1.19 + }, + "109": { + "weight": 1.0, + "height": 0.61 + }, + "110": { + "weight": 9.5, + "height": 1.19 + }, + "111": { + "weight": 115.0, + "height": 0.99 + }, + "112": { + "weight": 120.0, + "height": 1.91 + }, + "113": { + "weight": 34.6, + "height": 1.09 + }, + "114": { + "weight": 35.0, + "height": 0.99 + }, + "115": { + "weight": 80.0, + "height": 2.21 + }, + "116": { + "weight": 8.0, + "height": 0.41 + }, + "117": { + "weight": 25.0, + "height": 1.19 + }, + "118": { + "weight": 15.0, + "height": 0.61 + }, + "119": { + "weight": 39.0, + "height": 1.3 + }, + "120": { + "weight": 34.5, + "height": 0.79 + }, + "121": { + "weight": 80.0, + "height": 1.09 + }, + "122": { + "weight": 54.5, + "height": 1.3 + }, + "123": { + "weight": 56.0, + "height": 1.5 + }, + "124": { + "weight": 40.6, + "height": 1.4 + }, + "125": { + "weight": 30.0, + "height": 1.09 + }, + "126": { + "weight": 44.5, + "height": 1.3 + }, + "127": { + "weight": 55.0, + "height": 1.5 + }, + "128": { + "weight": 88.4, + "height": 1.4 + }, + "129": { + "weight": 10.0, + "height": 0.89 + }, + "130": { + "weight": 235.0, + "height": 6.5 + }, + "131": { + "weight": 220.0, + "height": 2.49 + }, + "132": { + "weight": 4.0, + "height": 0.3 + }, + "133": { + "weight": 6.5, + "height": 0.3 + }, + "134": { + "weight": 29.0, + "height": 0.99 + }, + "135": { + "weight": 24.5, + "height": 0.79 + }, + "136": { + "weight": 25.0, + "height": 0.89 + }, + "137": { + "weight": 36.5, + "height": 0.79 + }, + "138": { + "weight": 7.5, + "height": 0.41 + }, + "139": { + "weight": 35.0, + "height": 0.99 + }, + "140": { + "weight": 11.5, + "height": 0.51 + }, + "141": { + "weight": 40.5, + "height": 1.3 + }, + "142": { + "weight": 59.0, + "height": 1.8 + }, + "143": { + "weight": 460.0, + "height": 2.11 + }, + "144": { + "weight": 55.4, + "height": 1.7 + }, + "145": { + "weight": 52.6, + "height": 1.6 + }, + "146": { + "weight": 60.0, + "height": 2.01 + }, + "147": { + "weight": 3.3, + "height": 1.8 + }, + "148": { + "weight": 16.5, + "height": 3.99 + }, + "149": { + "weight": 210.0, + "height": 2.21 + }, + "150": { + "weight": 122.0, + "height": 2.01 + }, + "151": { + "weight": 4.0, + "height": 0.41 + }, + "152": { + "weight": 6.4, + "height": 0.89 + }, + "153": { + "weight": 15.8, + "height": 1.19 + }, + "154": { + "weight": 100.5, + "height": 1.8 + }, + "155": { + "weight": 7.9, + "height": 0.51 + }, + "156": { + "weight": 19.0, + "height": 0.89 + }, + "157": { + "weight": 79.5, + "height": 1.7 + }, + "158": { + "weight": 9.5, + "height": 0.61 + }, + "159": { + "weight": 25.0, + "height": 1.09 + }, + "160": { + "weight": 88.8, + "height": 2.31 + }, + "161": { + "weight": 6.0, + "height": 0.79 + }, + "162": { + "weight": 32.5, + "height": 1.8 + }, + "163": { + "weight": 21.2, + "height": 0.71 + }, + "164": { + "weight": 40.8, + "height": 1.6 + }, + "165": { + "weight": 10.8, + "height": 0.99 + }, + "166": { + "weight": 35.6, + "height": 1.4 + }, + "167": { + "weight": 8.5, + "height": 0.51 + }, + "168": { + "weight": 33.5, + "height": 1.09 + }, + "169": { + "weight": 75.0, + "height": 1.8 + }, + "170": { + "weight": 12.0, + "height": 0.51 + }, + "171": { + "weight": 22.5, + "height": 1.19 + }, + "172": { + "weight": 2.0, + "height": 0.3 + }, + "173": { + "weight": 3.0, + "height": 0.3 + }, + "174": { + "weight": 1.0, + "height": 0.3 + }, + "175": { + "weight": 1.5, + "height": 0.3 + }, + "176": { + "weight": 3.2, + "height": 0.61 + }, + "177": { + "weight": 2.0, + "height": 0.2 + }, + "178": { + "weight": 15.0, + "height": 1.5 + }, + "179": { + "weight": 7.8, + "height": 0.61 + }, + "180": { + "weight": 13.3, + "height": 0.79 + }, + "181": { + "weight": 61.5, + "height": 1.4 + }, + "182": { + "weight": 5.8, + "height": 0.41 + }, + "183": { + "weight": 8.5, + "height": 0.41 + }, + "184": { + "weight": 28.5, + "height": 0.79 + }, + "185": { + "weight": 38.0, + "height": 1.19 + }, + "186": { + "weight": 33.9, + "height": 1.09 + }, + "187": { + "weight": 0.5, + "height": 0.41 + }, + "188": { + "weight": 1.0, + "height": 0.61 + }, + "189": { + "weight": 3.0, + "height": 0.79 + }, + "190": { + "weight": 11.5, + "height": 0.79 + }, + "191": { + "weight": 1.8, + "height": 0.3 + }, + "192": { + "weight": 8.5, + "height": 0.79 + }, + "193": { + "weight": 38.0, + "height": 1.19 + }, + "194": { + "weight": 8.5, + "height": 0.41 + }, + "195": { + "weight": 75.0, + "height": 1.4 + }, + "196": { + "weight": 26.5, + "height": 0.89 + }, + "197": { + "weight": 27.0, + "height": 0.99 + }, + "198": { + "weight": 2.1, + "height": 0.51 + }, + "199": { + "weight": 79.5, + "height": 2.01 + }, + "200": { + "weight": 1.0, + "height": 0.71 + }, + "201": { + "weight": 5.0, + "height": 0.51 + }, + "202": { + "weight": 28.5, + "height": 1.3 + }, + "203": { + "weight": 41.5, + "height": 1.5 + }, + "204": { + "weight": 7.2, + "height": 0.61 + }, + "205": { + "weight": 125.8, + "height": 1.19 + }, + "206": { + "weight": 14.0, + "height": 1.5 + }, + "207": { + "weight": 64.8, + "height": 1.09 + }, + "208": { + "weight": 400.0, + "height": 9.19 + }, + "209": { + "weight": 7.8, + "height": 0.61 + }, + "210": { + "weight": 48.7, + "height": 1.4 + }, + "211": { + "weight": 3.9, + "height": 0.51 + }, + "212": { + "weight": 118.0, + "height": 1.8 + }, + "213": { + "weight": 20.5, + "height": 0.61 + }, + "214": { + "weight": 54.0, + "height": 1.5 + }, + "215": { + "weight": 28.0, + "height": 0.89 + }, + "216": { + "weight": 8.8, + "height": 0.61 + }, + "217": { + "weight": 125.8, + "height": 1.8 + }, + "218": { + "weight": 35.0, + "height": 0.71 + }, + "219": { + "weight": 55.0, + "height": 0.79 + }, + "220": { + "weight": 6.5, + "height": 0.41 + }, + "221": { + "weight": 55.8, + "height": 1.09 + }, + "222": { + "weight": 5.0, + "height": 0.61 + }, + "223": { + "weight": 12.0, + "height": 0.61 + }, + "224": { + "weight": 28.5, + "height": 0.89 + }, + "225": { + "weight": 16.0, + "height": 0.89 + }, + "226": { + "weight": 220.0, + "height": 2.11 + }, + "227": { + "weight": 50.5, + "height": 1.7 + }, + "228": { + "weight": 10.8, + "height": 0.61 + }, + "229": { + "weight": 35.0, + "height": 1.4 + }, + "230": { + "weight": 152.0, + "height": 1.8 + }, + "231": { + "weight": 33.5, + "height": 0.51 + }, + "232": { + "weight": 120.0, + "height": 1.09 + }, + "233": { + "weight": 32.5, + "height": 0.61 + }, + "234": { + "weight": 71.2, + "height": 1.4 + }, + "235": { + "weight": 58.0, + "height": 1.19 + }, + "236": { + "weight": 21.0, + "height": 0.71 + }, + "237": { + "weight": 48.0, + "height": 1.4 + }, + "238": { + "weight": 6.0, + "height": 0.41 + }, + "239": { + "weight": 23.5, + "height": 0.61 + }, + "240": { + "weight": 21.4, + "height": 0.71 + }, + "241": { + "weight": 75.5, + "height": 1.19 + }, + "242": { + "weight": 46.8, + "height": 1.5 + }, + "243": { + "weight": 178.0, + "height": 1.91 + }, + "244": { + "weight": 198.0, + "height": 2.11 + }, + "245": { + "weight": 187.0, + "height": 2.01 + }, + "246": { + "weight": 72.0, + "height": 0.61 + }, + "247": { + "weight": 152.0, + "height": 1.19 + }, + "248": { + "weight": 202.0, + "height": 2.01 + }, + "249": { + "weight": 216.0, + "height": 5.21 + }, + "250": { + "weight": 199.0, + "height": 3.81 + }, + "251": { + "weight": 5.0, + "height": 0.61 + }, + "252": { + "weight": 5.0, + "height": 0.51 + }, + "253": { + "weight": 21.6, + "height": 0.89 + }, + "254": { + "weight": 52.2, + "height": 1.7 + }, + "255": { + "weight": 2.5, + "height": 0.41 + }, + "256": { + "weight": 19.5, + "height": 0.89 + }, + "257": { + "weight": 52.0, + "height": 1.91 + }, + "258": { + "weight": 7.6, + "height": 0.41 + }, + "259": { + "weight": 28.0, + "height": 0.71 + }, + "260": { + "weight": 81.9, + "height": 1.5 + }, + "261": { + "weight": 13.6, + "height": 0.51 + }, + "262": { + "weight": 37.0, + "height": 0.99 + }, + "263": { + "weight": 17.5, + "height": 0.41 + }, + "264": { + "weight": 32.5, + "height": 0.51 + }, + "265": { + "weight": 3.6, + "height": 0.3 + }, + "266": { + "weight": 10.0, + "height": 0.61 + }, + "267": { + "weight": 28.4, + "height": 0.99 + }, + "268": { + "weight": 11.5, + "height": 0.71 + }, + "269": { + "weight": 31.6, + "height": 1.19 + }, + "270": { + "weight": 2.6, + "height": 0.51 + }, + "271": { + "weight": 32.5, + "height": 1.19 + }, + "272": { + "weight": 55.0, + "height": 1.5 + }, + "273": { + "weight": 4.0, + "height": 0.51 + }, + "274": { + "weight": 28.0, + "height": 0.99 + }, + "275": { + "weight": 59.6, + "height": 1.3 + }, + "276": { + "weight": 2.3, + "height": 0.3 + }, + "277": { + "weight": 19.8, + "height": 0.71 + }, + "278": { + "weight": 9.5, + "height": 0.61 + }, + "279": { + "weight": 28.0, + "height": 1.19 + }, + "280": { + "weight": 6.6, + "height": 0.41 + }, + "281": { + "weight": 20.2, + "height": 0.79 + }, + "282": { + "weight": 48.4, + "height": 1.6 + }, + "283": { + "weight": 1.7, + "height": 0.51 + }, + "284": { + "weight": 3.6, + "height": 0.79 + }, + "285": { + "weight": 4.5, + "height": 0.41 + }, + "286": { + "weight": 39.2, + "height": 1.19 + }, + "287": { + "weight": 24.0, + "height": 0.79 + }, + "288": { + "weight": 46.5, + "height": 1.4 + }, + "289": { + "weight": 130.5, + "height": 2.01 + }, + "290": { + "weight": 5.5, + "height": 0.51 + }, + "291": { + "weight": 12.0, + "height": 0.79 + }, + "292": { + "weight": 1.2, + "height": 0.79 + }, + "293": { + "weight": 16.3, + "height": 0.61 + }, + "294": { + "weight": 40.5, + "height": 0.99 + }, + "295": { + "weight": 84.0, + "height": 1.5 + }, + "296": { + "weight": 86.4, + "height": 0.99 + }, + "297": { + "weight": 253.8, + "height": 2.31 + }, + "298": { + "weight": 2.0, + "height": 0.2 + }, + "299": { + "weight": 97.0, + "height": 0.99 + }, + "300": { + "weight": 11.0, + "height": 0.61 + }, + "301": { + "weight": 32.6, + "height": 1.09 + }, + "302": { + "weight": 11.0, + "height": 0.51 + }, + "303": { + "weight": 11.5, + "height": 0.61 + }, + "304": { + "weight": 60.0, + "height": 0.41 + }, + "305": { + "weight": 120.0, + "height": 0.89 + }, + "306": { + "weight": 360.0, + "height": 2.11 + }, + "307": { + "weight": 11.2, + "height": 0.61 + }, + "308": { + "weight": 31.5, + "height": 1.3 + }, + "309": { + "weight": 15.2, + "height": 0.61 + }, + "310": { + "weight": 40.2, + "height": 1.5 + }, + "311": { + "weight": 4.2, + "height": 0.41 + }, + "312": { + "weight": 4.2, + "height": 0.41 + }, + "313": { + "weight": 17.7, + "height": 0.71 + }, + "314": { + "weight": 17.7, + "height": 0.61 + }, + "315": { + "weight": 2.0, + "height": 0.3 + }, + "316": { + "weight": 10.3, + "height": 0.41 + }, + "317": { + "weight": 80.0, + "height": 1.7 + }, + "318": { + "weight": 20.8, + "height": 0.79 + }, + "319": { + "weight": 88.8, + "height": 1.8 + }, + "320": { + "weight": 130.0, + "height": 2.01 + }, + "321": { + "weight": 398.0, + "height": 14.5 + }, + "322": { + "weight": 24.0, + "height": 0.71 + }, + "323": { + "weight": 220.0, + "height": 1.91 + }, + "324": { + "weight": 80.4, + "height": 0.51 + }, + "325": { + "weight": 30.6, + "height": 0.71 + }, + "326": { + "weight": 71.5, + "height": 0.89 + }, + "327": { + "weight": 5.0, + "height": 1.09 + }, + "328": { + "weight": 15.0, + "height": 0.71 + }, + "329": { + "weight": 15.3, + "height": 1.09 + }, + "330": { + "weight": 82.0, + "height": 2.01 + }, + "331": { + "weight": 51.3, + "height": 0.41 + }, + "332": { + "weight": 77.4, + "height": 1.3 + }, + "333": { + "weight": 1.2, + "height": 0.41 + }, + "334": { + "weight": 20.6, + "height": 1.09 + }, + "335": { + "weight": 40.3, + "height": 1.3 + }, + "336": { + "weight": 52.5, + "height": 2.69 + }, + "337": { + "weight": 168.0, + "height": 0.99 + }, + "338": { + "weight": 154.0, + "height": 1.19 + }, + "339": { + "weight": 1.9, + "height": 0.41 + }, + "340": { + "weight": 23.6, + "height": 0.89 + }, + "341": { + "weight": 11.5, + "height": 0.61 + }, + "342": { + "weight": 32.8, + "height": 1.09 + }, + "343": { + "weight": 21.5, + "height": 0.51 + }, + "344": { + "weight": 108.0, + "height": 1.5 + }, + "345": { + "weight": 23.8, + "height": 0.99 + }, + "346": { + "weight": 60.4, + "height": 1.5 + }, + "347": { + "weight": 12.5, + "height": 0.71 + }, + "348": { + "weight": 68.2, + "height": 1.5 + }, + "349": { + "weight": 7.4, + "height": 0.61 + }, + "350": { + "weight": 162.0, + "height": 6.2 + }, + "351": { + "weight": 0.8, + "height": 0.3 + }, + "352": { + "weight": 22.0, + "height": 0.99 + }, + "353": { + "weight": 2.3, + "height": 0.61 + }, + "354": { + "weight": 12.5, + "height": 1.09 + }, + "355": { + "weight": 15.0, + "height": 0.79 + }, + "356": { + "weight": 30.6, + "height": 1.6 + }, + "357": { + "weight": 100.0, + "height": 2.01 + }, + "358": { + "weight": 1.0, + "height": 0.61 + }, + "359": { + "weight": 47.0, + "height": 1.19 + }, + "360": { + "weight": 14.0, + "height": 0.61 + }, + "361": { + "weight": 16.8, + "height": 0.71 + }, + "362": { + "weight": 256.5, + "height": 1.5 + }, + "363": { + "weight": 39.5, + "height": 0.79 + }, + "364": { + "weight": 87.6, + "height": 1.09 + }, + "365": { + "weight": 150.6, + "height": 1.4 + }, + "366": { + "weight": 52.5, + "height": 0.41 + }, + "367": { + "weight": 27.0, + "height": 1.7 + }, + "368": { + "weight": 22.6, + "height": 1.8 + }, + "369": { + "weight": 23.4, + "height": 0.99 + }, + "370": { + "weight": 8.7, + "height": 0.61 + }, + "371": { + "weight": 42.1, + "height": 0.61 + }, + "372": { + "weight": 110.5, + "height": 1.09 + }, + "373": { + "weight": 102.6, + "height": 1.5 + }, + "374": { + "weight": 95.2, + "height": 0.61 + }, + "375": { + "weight": 202.5, + "height": 1.19 + }, + "376": { + "weight": 550.0, + "height": 1.6 + }, + "377": { + "weight": 230.0, + "height": 1.7 + }, + "378": { + "weight": 175.0, + "height": 1.8 + }, + "379": { + "weight": 205.0, + "height": 1.91 + }, + "380": { + "weight": 40.0, + "height": 1.4 + }, + "381": { + "weight": 60.0, + "height": 2.01 + }, + "382": { + "weight": 352.0, + "height": 4.5 + }, + "383": { + "weight": 950.0, + "height": 3.51 + }, + "384": { + "weight": 206.5, + "height": 7.01 + }, + "385": { + "weight": 1.1, + "height": 0.3 + }, + "386": { + "weight": 60.8, + "height": 1.7 + }, + "387": { + "weight": 10.2, + "height": 0.41 + }, + "388": { + "weight": 97.0, + "height": 1.09 + }, + "389": { + "weight": 310.0, + "height": 2.21 + }, + "390": { + "weight": 6.2, + "height": 0.51 + }, + "391": { + "weight": 22.0, + "height": 0.89 + }, + "392": { + "weight": 55.0, + "height": 1.19 + }, + "393": { + "weight": 5.2, + "height": 0.41 + }, + "394": { + "weight": 23.0, + "height": 0.79 + }, + "395": { + "weight": 84.5, + "height": 1.7 + }, + "396": { + "weight": 2.0, + "height": 0.3 + }, + "397": { + "weight": 15.5, + "height": 0.61 + }, + "398": { + "weight": 24.9, + "height": 1.19 + }, + "399": { + "weight": 20.0, + "height": 0.51 + }, + "400": { + "weight": 31.5, + "height": 0.99 + }, + "401": { + "weight": 2.2, + "height": 0.3 + }, + "402": { + "weight": 25.5, + "height": 0.99 + }, + "403": { + "weight": 9.5, + "height": 0.51 + }, + "404": { + "weight": 30.5, + "height": 0.89 + }, + "405": { + "weight": 42.0, + "height": 1.4 + }, + "406": { + "weight": 1.2, + "height": 0.2 + }, + "407": { + "weight": 14.5, + "height": 0.89 + }, + "408": { + "weight": 31.5, + "height": 0.89 + }, + "409": { + "weight": 102.5, + "height": 1.6 + }, + "410": { + "weight": 57.0, + "height": 0.51 + }, + "411": { + "weight": 149.5, + "height": 1.3 + }, + "412": { + "weight": 3.4, + "height": 0.2 + }, + "413": { + "weight": 6.5, + "height": 0.51 + }, + "414": { + "weight": 23.3, + "height": 0.89 + }, + "415": { + "weight": 5.5, + "height": 0.3 + }, + "416": { + "weight": 38.5, + "height": 1.19 + }, + "417": { + "weight": 3.9, + "height": 0.41 + }, + "418": { + "weight": 29.5, + "height": 0.71 + }, + "419": { + "weight": 33.5, + "height": 1.09 + }, + "420": { + "weight": 3.3, + "height": 0.41 + }, + "421": { + "weight": 9.3, + "height": 0.51 + }, + "422": { + "weight": 6.3, + "height": 0.3 + }, + "423": { + "weight": 29.9, + "height": 0.89 + }, + "424": { + "weight": 20.3, + "height": 1.19 + }, + "425": { + "weight": 1.2, + "height": 0.41 + }, + "426": { + "weight": 15.0, + "height": 1.19 + }, + "427": { + "weight": 5.5, + "height": 0.41 + }, + "428": { + "weight": 33.3, + "height": 1.19 + }, + "429": { + "weight": 4.4, + "height": 0.89 + }, + "430": { + "weight": 27.3, + "height": 0.89 + }, + "431": { + "weight": 3.9, + "height": 0.51 + }, + "432": { + "weight": 43.8, + "height": 0.99 + }, + "433": { + "weight": 0.6, + "height": 0.2 + }, + "434": { + "weight": 19.2, + "height": 0.41 + }, + "435": { + "weight": 38.0, + "height": 0.99 + }, + "436": { + "weight": 60.5, + "height": 0.51 + }, + "437": { + "weight": 187.0, + "height": 1.3 + }, + "438": { + "weight": 15.0, + "height": 0.51 + }, + "439": { + "weight": 13.0, + "height": 0.61 + }, + "440": { + "weight": 24.4, + "height": 0.61 + }, + "441": { + "weight": 1.9, + "height": 0.51 + }, + "442": { + "weight": 108.0, + "height": 0.99 + }, + "443": { + "weight": 20.5, + "height": 0.71 + }, + "444": { + "weight": 56.0, + "height": 1.4 + }, + "445": { + "weight": 95.0, + "height": 1.91 + }, + "446": { + "weight": 105.0, + "height": 0.61 + }, + "447": { + "weight": 20.2, + "height": 0.71 + }, + "448": { + "weight": 54.0, + "height": 1.19 + }, + "449": { + "weight": 49.5, + "height": 0.79 + }, + "450": { + "weight": 300.0, + "height": 2.01 + }, + "451": { + "weight": 12.0, + "height": 0.79 + }, + "452": { + "weight": 61.5, + "height": 1.3 + }, + "453": { + "weight": 23.0, + "height": 0.71 + }, + "454": { + "weight": 44.4, + "height": 1.3 + }, + "455": { + "weight": 27.0, + "height": 1.4 + }, + "456": { + "weight": 7.0, + "height": 0.41 + }, + "457": { + "weight": 24.0, + "height": 1.19 + }, + "458": { + "weight": 65.0, + "height": 0.99 + }, + "459": { + "weight": 50.5, + "height": 0.99 + }, + "460": { + "weight": 135.5, + "height": 2.21 + }, + "461": { + "weight": 34.0, + "height": 1.09 + }, + "462": { + "weight": 180.0, + "height": 1.19 + }, + "463": { + "weight": 140.0, + "height": 1.7 + }, + "464": { + "weight": 282.8, + "height": 2.39 + }, + "465": { + "weight": 128.6, + "height": 2.01 + }, + "466": { + "weight": 138.6, + "height": 1.8 + }, + "467": { + "weight": 68.0, + "height": 1.6 + }, + "468": { + "weight": 38.0, + "height": 1.5 + }, + "469": { + "weight": 51.5, + "height": 1.91 + }, + "470": { + "weight": 25.5, + "height": 0.99 + }, + "471": { + "weight": 25.9, + "height": 0.79 + }, + "472": { + "weight": 42.5, + "height": 2.01 + }, + "473": { + "weight": 291.0, + "height": 2.49 + }, + "474": { + "weight": 34.0, + "height": 0.89 + }, + "475": { + "weight": 52.0, + "height": 1.6 + }, + "476": { + "weight": 340.0, + "height": 1.4 + }, + "477": { + "weight": 106.6, + "height": 2.21 + }, + "478": { + "weight": 26.6, + "height": 1.3 + }, + "479": { + "weight": 0.3, + "height": 0.3 + }, + "480": { + "weight": 0.3, + "height": 0.3 + }, + "481": { + "weight": 0.3, + "height": 0.3 + }, + "482": { + "weight": 0.3, + "height": 0.3 + }, + "483": { + "weight": 683.0, + "height": 5.41 + }, + "484": { + "weight": 336.0, + "height": 4.19 + }, + "485": { + "weight": 430.0, + "height": 1.7 + }, + "486": { + "weight": 420.0, + "height": 3.71 + }, + "487": { + "weight": 750.0, + "height": 4.5 + }, + "488": { + "weight": 85.6, + "height": 1.5 + }, + "489": { + "weight": 3.1, + "height": 0.41 + }, + "490": { + "weight": 1.4, + "height": 0.3 + }, + "491": { + "weight": 50.5, + "height": 1.5 + }, + "492": { + "weight": 5.2, + "height": 0.41 + }, + "493": { + "weight": 320.0, + "height": 3.2 + }, + "494": { + "weight": 4.0, + "height": 0.41 + }, + "495": { + "weight": 8.1, + "height": 0.61 + }, + "496": { + "weight": 16.0, + "height": 0.79 + }, + "497": { + "weight": 63.0, + "height": 3.3 + }, + "498": { + "weight": 9.9, + "height": 0.51 + }, + "499": { + "weight": 55.5, + "height": 0.99 + }, + "500": { + "weight": 150.0, + "height": 1.6 + }, + "501": { + "weight": 5.9, + "height": 0.51 + }, + "502": { + "weight": 24.5, + "height": 0.79 + }, + "503": { + "weight": 94.6, + "height": 1.5 + }, + "504": { + "weight": 11.6, + "height": 0.51 + }, + "505": { + "weight": 27.0, + "height": 1.09 + }, + "506": { + "weight": 4.1, + "height": 0.41 + }, + "507": { + "weight": 14.7, + "height": 0.89 + }, + "508": { + "weight": 61.0, + "height": 1.19 + }, + "509": { + "weight": 10.1, + "height": 0.41 + }, + "510": { + "weight": 37.5, + "height": 1.09 + }, + "511": { + "weight": 10.5, + "height": 0.61 + }, + "512": { + "weight": 30.5, + "height": 1.09 + }, + "513": { + "weight": 11.0, + "height": 0.61 + }, + "514": { + "weight": 28.0, + "height": 0.99 + }, + "515": { + "weight": 13.5, + "height": 0.61 + }, + "516": { + "weight": 29.0, + "height": 0.99 + }, + "517": { + "weight": 23.3, + "height": 0.61 + }, + "518": { + "weight": 60.5, + "height": 1.09 + }, + "519": { + "weight": 2.1, + "height": 0.3 + }, + "520": { + "weight": 15.0, + "height": 0.61 + }, + "521": { + "weight": 29.0, + "height": 1.19 + }, + "522": { + "weight": 29.8, + "height": 0.79 + }, + "523": { + "weight": 79.5, + "height": 1.6 + }, + "524": { + "weight": 18.0, + "height": 0.41 + }, + "525": { + "weight": 102.0, + "height": 0.89 + }, + "526": { + "weight": 260.0, + "height": 1.7 + }, + "527": { + "weight": 2.1, + "height": 0.41 + }, + "528": { + "weight": 10.5, + "height": 0.89 + }, + "529": { + "weight": 8.5, + "height": 0.3 + }, + "530": { + "weight": 40.4, + "height": 0.71 + }, + "531": { + "weight": 31.0, + "height": 1.09 + }, + "532": { + "weight": 12.5, + "height": 0.61 + }, + "533": { + "weight": 40.0, + "height": 1.19 + }, + "534": { + "weight": 87.0, + "height": 1.4 + }, + "535": { + "weight": 4.5, + "height": 0.51 + }, + "536": { + "weight": 17.0, + "height": 0.79 + }, + "537": { + "weight": 62.0, + "height": 1.5 + }, + "538": { + "weight": 55.5, + "height": 1.3 + }, + "539": { + "weight": 51.0, + "height": 1.4 + }, + "540": { + "weight": 2.5, + "height": 0.3 + }, + "541": { + "weight": 7.3, + "height": 0.51 + }, + "542": { + "weight": 20.5, + "height": 1.19 + }, + "543": { + "weight": 5.3, + "height": 0.41 + }, + "544": { + "weight": 58.5, + "height": 1.19 + }, + "545": { + "weight": 200.5, + "height": 2.49 + }, + "546": { + "weight": 0.6, + "height": 0.3 + }, + "547": { + "weight": 6.6, + "height": 0.71 + }, + "548": { + "weight": 6.6, + "height": 0.51 + }, + "549": { + "weight": 16.3, + "height": 1.09 + }, + "550": { + "weight": 18.0, + "height": 0.99 + }, + "551": { + "weight": 15.2, + "height": 0.71 + }, + "552": { + "weight": 33.4, + "height": 0.99 + }, + "553": { + "weight": 96.3, + "height": 1.5 + }, + "554": { + "weight": 37.5, + "height": 0.61 + }, + "555": { + "weight": 92.9, + "height": 1.3 + }, + "556": { + "weight": 28.0, + "height": 0.99 + }, + "557": { + "weight": 14.5, + "height": 0.3 + }, + "558": { + "weight": 200.0, + "height": 1.4 + }, + "559": { + "weight": 11.8, + "height": 0.61 + }, + "560": { + "weight": 30.0, + "height": 1.09 + }, + "561": { + "weight": 14.0, + "height": 1.4 + }, + "562": { + "weight": 1.5, + "height": 0.51 + }, + "563": { + "weight": 76.5, + "height": 1.7 + }, + "564": { + "weight": 16.5, + "height": 0.71 + }, + "565": { + "weight": 81.0, + "height": 1.19 + }, + "566": { + "weight": 9.5, + "height": 0.51 + }, + "567": { + "weight": 32.0, + "height": 1.4 + }, + "568": { + "weight": 31.0, + "height": 0.61 + }, + "569": { + "weight": 107.3, + "height": 1.91 + }, + "570": { + "weight": 12.5, + "height": 0.71 + }, + "571": { + "weight": 81.1, + "height": 1.6 + }, + "572": { + "weight": 5.8, + "height": 0.41 + }, + "573": { + "weight": 7.5, + "height": 0.51 + }, + "574": { + "weight": 5.8, + "height": 0.41 + }, + "575": { + "weight": 18.0, + "height": 0.71 + }, + "576": { + "weight": 44.0, + "height": 1.5 + }, + "577": { + "weight": 1.0, + "height": 0.3 + }, + "578": { + "weight": 8.0, + "height": 0.61 + }, + "579": { + "weight": 20.1, + "height": 0.99 + }, + "580": { + "weight": 5.5, + "height": 0.51 + }, + "581": { + "weight": 24.2, + "height": 1.3 + }, + "582": { + "weight": 5.7, + "height": 0.41 + }, + "583": { + "weight": 41.0, + "height": 1.09 + }, + "584": { + "weight": 57.5, + "height": 1.3 + }, + "585": { + "weight": 19.5, + "height": 0.61 + }, + "586": { + "weight": 92.5, + "height": 1.91 + }, + "587": { + "weight": 5.0, + "height": 0.41 + }, + "588": { + "weight": 5.9, + "height": 0.51 + }, + "589": { + "weight": 33.0, + "height": 0.99 + }, + "590": { + "weight": 1.0, + "height": 0.2 + }, + "591": { + "weight": 10.5, + "height": 0.61 + }, + "592": { + "weight": 33.0, + "height": 1.19 + }, + "593": { + "weight": 135.0, + "height": 2.21 + }, + "594": { + "weight": 31.6, + "height": 1.19 + }, + "595": { + "weight": 0.6, + "height": 0.1 + }, + "596": { + "weight": 14.3, + "height": 0.79 + }, + "597": { + "weight": 18.8, + "height": 0.61 + }, + "598": { + "weight": 110.0, + "height": 0.99 + }, + "599": { + "weight": 21.0, + "height": 0.3 + }, + "600": { + "weight": 51.0, + "height": 0.61 + }, + "601": { + "weight": 81.0, + "height": 0.61 + }, + "602": { + "weight": 0.3, + "height": 0.2 + }, + "603": { + "weight": 22.0, + "height": 1.19 + }, + "604": { + "weight": 80.5, + "height": 2.11 + }, + "605": { + "weight": 9.0, + "height": 0.51 + }, + "606": { + "weight": 34.5, + "height": 0.99 + }, + "607": { + "weight": 3.1, + "height": 0.3 + }, + "608": { + "weight": 13.0, + "height": 0.61 + }, + "609": { + "weight": 34.3, + "height": 0.99 + }, + "610": { + "weight": 18.0, + "height": 0.61 + }, + "611": { + "weight": 36.0, + "height": 0.99 + }, + "612": { + "weight": 105.5, + "height": 1.8 + }, + "613": { + "weight": 8.5, + "height": 0.51 + }, + "614": { + "weight": 260.0, + "height": 2.59 + }, + "615": { + "weight": 148.0, + "height": 1.09 + }, + "616": { + "weight": 7.7, + "height": 0.41 + }, + "617": { + "weight": 25.3, + "height": 0.79 + }, + "618": { + "weight": 11.0, + "height": 0.71 + }, + "619": { + "weight": 20.0, + "height": 0.89 + }, + "620": { + "weight": 35.5, + "height": 1.4 + }, + "621": { + "weight": 139.0, + "height": 1.6 + }, + "622": { + "weight": 92.0, + "height": 0.99 + }, + "623": { + "weight": 330.0, + "height": 2.79 + }, + "624": { + "weight": 10.2, + "height": 0.51 + }, + "625": { + "weight": 70.0, + "height": 1.6 + }, + "626": { + "weight": 94.6, + "height": 1.6 + }, + "627": { + "weight": 10.5, + "height": 0.51 + }, + "628": { + "weight": 41.0, + "height": 1.5 + }, + "629": { + "weight": 9.0, + "height": 0.51 + }, + "630": { + "weight": 39.5, + "height": 1.19 + }, + "631": { + "weight": 58.0, + "height": 1.4 + }, + "632": { + "weight": 33.0, + "height": 0.3 + }, + "633": { + "weight": 17.3, + "height": 0.79 + }, + "634": { + "weight": 50.0, + "height": 1.4 + }, + "635": { + "weight": 160.0, + "height": 1.8 + }, + "636": { + "weight": 28.8, + "height": 1.09 + }, + "637": { + "weight": 46.0, + "height": 1.6 + }, + "638": { + "weight": 250.0, + "height": 2.11 + }, + "639": { + "weight": 260.0, + "height": 1.91 + }, + "640": { + "weight": 200.0, + "height": 2.01 + }, + "641": { + "weight": 63.0, + "height": 1.4 + }, + "642": { + "weight": 61.0, + "height": 3.0 + }, + "643": { + "weight": 330.0, + "height": 3.2 + }, + "644": { + "weight": 345.0, + "height": 2.9 + }, + "645": { + "weight": 68.0, + "height": 1.5 + }, + "646": { + "weight": 325.0, + "height": 3.0 + }, + "647": { + "weight": 48.5, + "height": 1.4 + }, + "648": { + "weight": 6.5, + "height": 0.61 + }, + "649": { + "weight": 82.5, + "height": 1.5 + }, + "650": { + "weight": 9.0, + "height": 0.41 + }, + "651": { + "weight": 29.0, + "height": 0.71 + }, + "652": { + "weight": 90.0, + "height": 1.6 + }, + "653": { + "weight": 9.4, + "height": 0.41 + }, + "654": { + "weight": 14.5, + "height": 0.99 + }, + "655": { + "weight": 39.0, + "height": 1.5 + }, + "656": { + "weight": 7.0, + "height": 0.3 + }, + "657": { + "weight": 10.9, + "height": 0.61 + }, + "658": { + "weight": 40.0, + "height": 1.5 + }, + "659": { + "weight": 5.0, + "height": 0.41 + }, + "660": { + "weight": 42.4, + "height": 0.99 + }, + "661": { + "weight": 1.7, + "height": 0.3 + }, + "662": { + "weight": 16.0, + "height": 0.71 + }, + "663": { + "weight": 24.5, + "height": 1.19 + }, + "664": { + "weight": 2.5, + "height": 0.3 + }, + "665": { + "weight": 8.4, + "height": 0.3 + }, + "666": { + "weight": 17.0, + "height": 1.19 + }, + "667": { + "weight": 13.5, + "height": 0.61 + }, + "668": { + "weight": 81.5, + "height": 1.5 + }, + "669": { + "weight": 0.1, + "height": 0.1 + }, + "670": { + "weight": 0.9, + "height": 0.2 + }, + "671": { + "weight": 10.0, + "height": 1.09 + }, + "672": { + "weight": 31.0, + "height": 0.89 + }, + "673": { + "weight": 91.0, + "height": 1.7 + }, + "674": { + "weight": 8.0, + "height": 0.61 + }, + "675": { + "weight": 136.0, + "height": 2.11 + }, + "676": { + "weight": 28.0, + "height": 1.19 + }, + "677": { + "weight": 3.5, + "height": 0.3 + }, + "678": { + "weight": 8.5, + "height": 0.61 + }, + "679": { + "weight": 2.0, + "height": 0.79 + }, + "680": { + "weight": 4.5, + "height": 0.84 + }, + "681": { + "weight": 53.0, + "height": 1.7 + }, + "682": { + "weight": 0.5, + "height": 0.2 + }, + "683": { + "weight": 15.5, + "height": 0.79 + }, + "684": { + "weight": 3.5, + "height": 0.41 + }, + "685": { + "weight": 5.0, + "height": 0.79 + }, + "686": { + "weight": 3.5, + "height": 0.41 + }, + "687": { + "weight": 47.0, + "height": 1.5 + }, + "688": { + "weight": 31.0, + "height": 0.51 + }, + "689": { + "weight": 96.0, + "height": 1.3 + }, + "690": { + "weight": 7.3, + "height": 0.51 + }, + "691": { + "weight": 81.5, + "height": 1.8 + }, + "692": { + "weight": 8.3, + "height": 0.51 + }, + "693": { + "weight": 35.3, + "height": 1.3 + }, + "694": { + "weight": 6.0, + "height": 0.51 + }, + "695": { + "weight": 21.0, + "height": 0.99 + }, + "696": { + "weight": 26.0, + "height": 0.79 + }, + "697": { + "weight": 270.0, + "height": 2.49 + }, + "698": { + "weight": 25.2, + "height": 1.3 + }, + "699": { + "weight": 225.0, + "height": 2.69 + }, + "700": { + "weight": 23.5, + "height": 0.99 + }, + "701": { + "weight": 21.5, + "height": 0.79 + }, + "702": { + "weight": 2.2, + "height": 0.2 + }, + "703": { + "weight": 5.7, + "height": 0.3 + }, + "704": { + "weight": 2.8, + "height": 0.3 + }, + "705": { + "weight": 17.5, + "height": 0.79 + }, + "706": { + "weight": 150.5, + "height": 2.01 + }, + "707": { + "weight": 3.0, + "height": 0.2 + }, + "708": { + "weight": 7.0, + "height": 0.41 + }, + "709": { + "weight": 71.0, + "height": 1.5 + }, + "710": { + "weight": 5.0, + "height": 0.41 + }, + "711": { + "weight": 39.0, + "height": 1.7 + }, + "712": { + "weight": 99.5, + "height": 0.99 + }, + "713": { + "weight": 505.0, + "height": 2.01 + }, + "714": { + "weight": 8.0, + "height": 0.51 + }, + "715": { + "weight": 85.0, + "height": 1.5 + }, + "716": { + "weight": 215.0, + "height": 3.0 + }, + "717": { + "weight": 203.0, + "height": 5.79 + }, + "718": { + "weight": 33.5, + "height": 1.19 + }, + "719": { + "weight": 8.8, + "height": 0.71 + }, + "720": { + "weight": 9.0, + "height": 0.51 + }, + "721": { + "weight": 195.0, + "height": 1.7 + }, + "722": { + "weight": 1.5, + "height": 0.3 + }, + "723": { + "weight": 16.0, + "height": 0.71 + }, + "724": { + "weight": 36.6, + "height": 1.6 + }, + "725": { + "weight": 4.3, + "height": 0.41 + }, + "726": { + "weight": 25.0, + "height": 0.71 + }, + "727": { + "weight": 83.0, + "height": 1.8 + }, + "728": { + "weight": 7.5, + "height": 0.41 + }, + "729": { + "weight": 17.5, + "height": 0.61 + }, + "730": { + "weight": 44.0, + "height": 1.8 + }, + "731": { + "weight": 1.2, + "height": 0.3 + }, + "732": { + "weight": 14.8, + "height": 0.61 + }, + "733": { + "weight": 26.0, + "height": 1.09 + }, + "734": { + "weight": 6.0, + "height": 0.41 + }, + "735": { + "weight": 14.2, + "height": 0.71 + }, + "736": { + "weight": 4.4, + "height": 0.41 + }, + "737": { + "weight": 10.5, + "height": 0.51 + }, + "738": { + "weight": 45.0, + "height": 1.5 + }, + "739": { + "weight": 7.0, + "height": 0.61 + }, + "740": { + "weight": 180.0, + "height": 1.7 + }, + "741": { + "weight": 3.4, + "height": 0.61 + }, + "742": { + "weight": 0.2, + "height": 0.1 + }, + "743": { + "weight": 0.5, + "height": 0.2 + }, + "744": { + "weight": 9.2, + "height": 0.51 + }, + "745": { + "weight": 25.0, + "height": 0.79 + }, + "746": { + "weight": 0.3, + "height": 0.2 + }, + "747": { + "weight": 8.0, + "height": 0.41 + }, + "748": { + "weight": 14.5, + "height": 0.71 + }, + "749": { + "weight": 110.0, + "height": 0.99 + }, + "750": { + "weight": 920.0, + "height": 2.49 + }, + "751": { + "weight": 4.0, + "height": 0.3 + }, + "752": { + "weight": 82.0, + "height": 1.8 + }, + "753": { + "weight": 1.5, + "height": 0.3 + }, + "754": { + "weight": 18.5, + "height": 0.89 + }, + "755": { + "weight": 1.5, + "height": 0.2 + }, + "756": { + "weight": 11.5, + "height": 0.99 + }, + "757": { + "weight": 4.8, + "height": 0.61 + }, + "758": { + "weight": 22.2, + "height": 1.19 + }, + "759": { + "weight": 6.8, + "height": 0.51 + }, + "760": { + "weight": 135.0, + "height": 2.11 + }, + "761": { + "weight": 3.2, + "height": 0.3 + }, + "762": { + "weight": 8.2, + "height": 0.71 + }, + "763": { + "weight": 21.4, + "height": 1.14 + }, + "764": { + "weight": 0.3, + "height": 0.1 + }, + "765": { + "weight": 76.0, + "height": 1.5 + }, + "766": { + "weight": 82.8, + "height": 2.01 + }, + "767": { + "weight": 12.0, + "height": 0.51 + }, + "768": { + "weight": 108.0, + "height": 2.01 + }, + "769": { + "weight": 70.0, + "height": 0.51 + }, + "770": { + "weight": 250.0, + "height": 1.3 + }, + "771": { + "weight": 1.2, + "height": 0.3 + }, + "772": { + "weight": 120.5, + "height": 1.91 + }, + "773": { + "weight": 100.5, + "height": 2.31 + }, + "774": { + "weight": 40.0, + "height": 0.3 + }, + "775": { + "weight": 19.9, + "height": 0.41 + }, + "776": { + "weight": 212.0, + "height": 2.01 + }, + "777": { + "weight": 3.3, + "height": 0.3 + }, + "778": { + "weight": 0.7, + "height": 0.2 + }, + "779": { + "weight": 19.0, + "height": 0.89 + }, + "780": { + "weight": 185.0, + "height": 3.0 + }, + "781": { + "weight": 210.0, + "height": 3.91 + }, + "782": { + "weight": 29.7, + "height": 0.61 + }, + "783": { + "weight": 47.0, + "height": 1.14 + }, + "784": { + "weight": 78.2, + "height": 1.6 + }, + "785": { + "weight": 20.5, + "height": 1.8 + }, + "786": { + "weight": 18.6, + "height": 1.19 + }, + "787": { + "weight": 45.5, + "height": 1.91 + }, + "788": { + "weight": 21.2, + "height": 1.3 + }, + "789": { + "weight": 0.1, + "height": 0.2 + }, + "790": { + "weight": 999.9, + "height": 0.1 + }, + "791": { + "weight": 230.0, + "height": 3.4 + }, + "792": { + "weight": 120.0, + "height": 3.99 + }, + "793": { + "weight": 55.5, + "height": 1.19 + }, + "794": { + "weight": 333.6, + "height": 2.39 + }, + "795": { + "weight": 25.0, + "height": 1.8 + }, + "796": { + "weight": 100.0, + "height": 3.81 + }, + "797": { + "weight": 999.9, + "height": 9.19 + }, + "798": { + "weight": 0.1, + "height": 0.3 + }, + "799": { + "weight": 888.0, + "height": 5.51 + }, + "800": { + "weight": 230.0, + "height": 2.39 + }, + "801": { + "weight": 80.5, + "height": 0.99 + }, + "802": { + "weight": 22.2, + "height": 0.71 + } +} \ No newline at end of file diff --git a/data/moves.json b/data/moves.json new file mode 100644 index 0000000..604dc1f --- /dev/null +++ b/data/moves.json @@ -0,0 +1,1826 @@ +{ + "1": { + "name": "Thunder Shock", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "2": { + "name": "Quick Attack", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "3": { + "name": "Scratch", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "4": { + "name": "Ember", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "5": { + "name": "Vine Whip", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "6": { + "name": "Tackle", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "7": { + "name": "Razor Leaf", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "8": { + "name": "Take Down", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "9": { + "name": "Water Gun", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "10": { + "name": "Bite", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "11": { + "name": "Pound", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "12": { + "name": "Double Slap", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "13": { + "name": "Wrap", + "type": "Normal", + "damage": 60, + "duration": 2900, + "energy": 33, + "dps": 20.69 + }, + "14": { + "name": "Hyper Beam", + "type": "Normal", + "damage": 150, + "duration": 3800, + "energy": 100, + "dps": 39.47 + }, + "15": { + "name": "Lick", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "16": { + "name": "Dark Pulse", + "type": "Dark", + "damage": 80, + "duration": 3000, + "energy": 50, + "dps": 26.67 + }, + "17": { + "name": "Smog", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "18": { + "name": "Sludge", + "type": "Poison", + "damage": 50, + "duration": 2100, + "energy": 33, + "dps": 23.81 + }, + "19": { + "name": "Metal Claw", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "20": { + "name": "Vice Grip", + "type": "Normal", + "damage": 35, + "duration": 1900, + "energy": 33, + "dps": 18.42 + }, + "21": { + "name": "Flame Wheel", + "type": "Fire", + "damage": 60, + "duration": 2700, + "energy": 50, + "dps": 22.22 + }, + "22": { + "name": "Megahorn", + "type": "Bug", + "damage": 90, + "duration": 2200, + "energy": 100, + "dps": 40.91 + }, + "23": { + "name": "Wing Attack", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "24": { + "name": "Flamethrower", + "type": "Fire", + "damage": 70, + "duration": 2200, + "energy": 50, + "dps": 31.82 + }, + "25": { + "name": "Sucker Punch", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "26": { + "name": "Dig", + "type": "Ground", + "damage": 100, + "duration": 4700, + "energy": 50, + "dps": 21.28 + }, + "27": { + "name": "Low Kick", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "28": { + "name": "Cross Chop", + "type": "Fighting", + "damage": 50, + "duration": 1500, + "energy": 50, + "dps": 33.33 + }, + "29": { + "name": "Psycho Cut", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "30": { + "name": "Psybeam", + "type": "Psychic", + "damage": 70, + "duration": 3200, + "energy": 50, + "dps": 21.88 + }, + "31": { + "name": "Earthquake", + "type": "Ground", + "damage": 120, + "duration": 3600, + "energy": 100, + "dps": 33.33 + }, + "32": { + "name": "Stone Edge", + "type": "Rock", + "damage": 100, + "duration": 2300, + "energy": 100, + "dps": 43.48 + }, + "33": { + "name": "Ice Punch", + "type": "Ice", + "damage": 50, + "duration": 1900, + "energy": 33, + "dps": 26.32 + }, + "34": { + "name": "Heart Stamp", + "type": "Psychic", + "damage": 40, + "duration": 1900, + "energy": 33, + "dps": 21.05 + }, + "35": { + "name": "Discharge", + "type": "Electric", + "damage": 65, + "duration": 2500, + "energy": 33, + "dps": 26 + }, + "36": { + "name": "Flash Cannon", + "type": "Steel", + "damage": 100, + "duration": 2700, + "energy": 100, + "dps": 37.04 + }, + "37": { + "name": "Peck", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "38": { + "name": "Drill Peck", + "type": "Flying", + "damage": 60, + "duration": 2300, + "energy": 33, + "dps": 26.09 + }, + "39": { + "name": "Ice Beam", + "type": "Ice", + "damage": 90, + "duration": 3300, + "energy": 50, + "dps": 27.27 + }, + "40": { + "name": "Blizzard", + "type": "Ice", + "damage": 130, + "duration": 3100, + "energy": 100, + "dps": 41.94 + }, + "41": { + "name": "Air Slash", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "42": { + "name": "Heat Wave", + "type": "Fire", + "damage": 95, + "duration": 3000, + "energy": 100, + "dps": 31.67 + }, + "43": { + "name": "Twineedle", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "44": { + "name": "Poison Jab", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "45": { + "name": "Aerial Ace", + "type": "Flying", + "damage": 55, + "duration": 2400, + "energy": 33, + "dps": 22.92 + }, + "46": { + "name": "Drill Run", + "type": "Ground", + "damage": 80, + "duration": 2800, + "energy": 50, + "dps": 28.57 + }, + "47": { + "name": "Petal Blizzard", + "type": "Grass", + "damage": 110, + "duration": 2600, + "energy": 100, + "dps": 42.31 + }, + "48": { + "name": "Mega Drain", + "type": "Grass", + "damage": 25, + "duration": 2600, + "energy": 50, + "dps": 9.62 + }, + "49": { + "name": "Bug Buzz", + "type": "Bug", + "damage": 90, + "duration": 3700, + "energy": 50, + "dps": 24.32 + }, + "50": { + "name": "Poison Fang", + "type": "Poison", + "damage": 35, + "duration": 1700, + "energy": 33, + "dps": 20.59 + }, + "51": { + "name": "Night Slash", + "type": "Dark", + "damage": 50, + "duration": 2200, + "energy": 33, + "dps": 22.73 + }, + "52": { + "name": "Slash", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "53": { + "name": "Bubble Beam", + "type": "Water", + "damage": 45, + "duration": 1900, + "energy": 33, + "dps": 23.68 + }, + "54": { + "name": "Submission", + "type": "Fighting", + "damage": 60, + "duration": 2200, + "energy": 50, + "dps": 27.27 + }, + "55": { + "name": "Karate Chop", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "56": { + "name": "Low Sweep", + "type": "Fighting", + "damage": 40, + "duration": 1900, + "energy": 33, + "dps": 21.05 + }, + "57": { + "name": "Aqua Jet", + "type": "Water", + "damage": 45, + "duration": 2600, + "energy": 33, + "dps": 17.31 + }, + "58": { + "name": "Aqua Tail", + "type": "Water", + "damage": 50, + "duration": 1900, + "energy": 33, + "dps": 26.32 + }, + "59": { + "name": "Seed Bomb", + "type": "Grass", + "damage": 55, + "duration": 2100, + "energy": 33, + "dps": 26.19 + }, + "60": { + "name": "Psyshock", + "type": "Psychic", + "damage": 65, + "duration": 2700, + "energy": 33, + "dps": 24.07 + }, + "61": { + "name": "Rock Throw", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "62": { + "name": "Ancient Power", + "type": "Rock", + "damage": 70, + "duration": 3500, + "energy": 33, + "dps": 20 + }, + "63": { + "name": "Rock Tomb", + "type": "Rock", + "damage": 70, + "duration": 3200, + "energy": 50, + "dps": 21.88 + }, + "64": { + "name": "Rock Slide", + "type": "Rock", + "damage": 80, + "duration": 2700, + "energy": 50, + "dps": 29.63 + }, + "65": { + "name": "Power Gem", + "type": "Rock", + "damage": 80, + "duration": 2900, + "energy": 50, + "dps": 27.59 + }, + "66": { + "name": "Shadow Sneak", + "type": "Ghost", + "damage": 50, + "duration": 2900, + "energy": 33, + "dps": 17.24 + }, + "67": { + "name": "Shadow Punch", + "type": "Ghost", + "damage": 40, + "duration": 1700, + "energy": 33, + "dps": 23.53 + }, + "68": { + "name": "Shadow Claw", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "69": { + "name": "Ominous Wind", + "type": "Ghost", + "damage": 50, + "duration": 2300, + "energy": 33, + "dps": 21.74 + }, + "70": { + "name": "Shadow Ball", + "type": "Ghost", + "damage": 100, + "duration": 3000, + "energy": 50, + "dps": 33.33 + }, + "71": { + "name": "Bullet Punch", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "72": { + "name": "Magnet Bomb", + "type": "Steel", + "damage": 70, + "duration": 2800, + "energy": 33, + "dps": 25 + }, + "73": { + "name": "Steel Wing", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "74": { + "name": "Iron Head", + "type": "Steel", + "damage": 60, + "duration": 1900, + "energy": 50, + "dps": 31.58 + }, + "75": { + "name": "Parabolic Charge", + "type": "Electric", + "damage": 25, + "duration": 2800, + "energy": 50, + "dps": 8.93 + }, + "76": { + "name": "Spark", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "77": { + "name": "Thunder Punch", + "type": "Electric", + "damage": 45, + "duration": 1800, + "energy": 33, + "dps": 25 + }, + "78": { + "name": "Thunder", + "type": "Electric", + "damage": 100, + "duration": 2400, + "energy": 100, + "dps": 41.67 + }, + "79": { + "name": "Thunderbolt", + "type": "Electric", + "damage": 80, + "duration": 2500, + "energy": 50, + "dps": 32 + }, + "80": { + "name": "Twister", + "type": "Dragon", + "damage": 45, + "duration": 2800, + "energy": 33, + "dps": 16.07 + }, + "81": { + "name": "Dragon Breath", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "82": { + "name": "Dragon Pulse", + "type": "Dragon", + "damage": 90, + "duration": 3600, + "energy": 50, + "dps": 25 + }, + "83": { + "name": "Dragon Claw", + "type": "Dragon", + "damage": 50, + "duration": 1700, + "energy": 33, + "dps": 29.41 + }, + "84": { + "name": "Disarming Voice", + "type": "Fairy", + "damage": 70, + "duration": 3900, + "energy": 33, + "dps": 17.95 + }, + "85": { + "name": "Draining Kiss", + "type": "Fairy", + "damage": 60, + "duration": 2600, + "energy": 50, + "dps": 23.08 + }, + "86": { + "name": "Dazzling Gleam", + "type": "Fairy", + "damage": 100, + "duration": 3500, + "energy": 50, + "dps": 28.57 + }, + "87": { + "name": "Moonblast", + "type": "Fairy", + "damage": 130, + "duration": 3900, + "energy": 100, + "dps": 33.33 + }, + "88": { + "name": "Play Rough", + "type": "Fairy", + "damage": 90, + "duration": 2900, + "energy": 50, + "dps": 31.03 + }, + "89": { + "name": "Cross Poison", + "type": "Poison", + "damage": 40, + "duration": 1500, + "energy": 33, + "dps": 26.67 + }, + "90": { + "name": "Sludge Bomb", + "type": "Poison", + "damage": 80, + "duration": 2300, + "energy": 50, + "dps": 34.78 + }, + "91": { + "name": "Sludge Wave", + "type": "Poison", + "damage": 110, + "duration": 3200, + "energy": 100, + "dps": 34.38 + }, + "92": { + "name": "Gunk Shot", + "type": "Poison", + "damage": 130, + "duration": 3100, + "energy": 100, + "dps": 41.94 + }, + "93": { + "name": "Mud Shot", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "94": { + "name": "Bone Club", + "type": "Ground", + "damage": 40, + "duration": 1600, + "energy": 33, + "dps": 25 + }, + "95": { + "name": "Bulldoze", + "type": "Ground", + "damage": 80, + "duration": 3500, + "energy": 50, + "dps": 22.86 + }, + "96": { + "name": "Mud Bomb", + "type": "Ground", + "damage": 55, + "duration": 2300, + "energy": 33, + "dps": 23.91 + }, + "97": { + "name": "Fury Cutter", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "98": { + "name": "Bug Bite", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "99": { + "name": "Signal Beam", + "type": "Bug", + "damage": 75, + "duration": 2900, + "energy": 50, + "dps": 25.86 + }, + "100": { + "name": "X-Scissor", + "type": "Bug", + "damage": 45, + "duration": 1600, + "energy": 33, + "dps": 28.13 + }, + "101": { + "name": "Flame Charge", + "type": "Fire", + "damage": 70, + "duration": 3800, + "energy": 33, + "dps": 18.42 + }, + "102": { + "name": "Flame Burst", + "type": "Fire", + "damage": 70, + "duration": 2600, + "energy": 50, + "dps": 26.92 + }, + "103": { + "name": "Fire Blast", + "type": "Fire", + "damage": 140, + "duration": 4200, + "energy": 100, + "dps": 33.33 + }, + "104": { + "name": "Brine", + "type": "Water", + "damage": 60, + "duration": 2300, + "energy": 50, + "dps": 26.09 + }, + "105": { + "name": "Water Pulse", + "type": "Water", + "damage": 70, + "duration": 3200, + "energy": 50, + "dps": 21.88 + }, + "106": { + "name": "Scald", + "type": "Water", + "damage": 82, + "duration": 3700, + "energy": 50, + "dps": 21.62 + }, + "107": { + "name": "Hydro Pump", + "type": "Water", + "damage": 130, + "duration": 3300, + "energy": 100, + "dps": 39.39 + }, + "108": { + "name": "Psychic", + "type": "Psychic", + "damage": 100, + "duration": 2800, + "energy": 100, + "dps": 35.71 + }, + "109": { + "name": "Psystrike", + "type": "Psychic", + "damage": 100, + "duration": 4400, + "energy": 50, + "dps": 22.73 + }, + "110": { + "name": "Ice Shard", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "111": { + "name": "Icy Wind", + "type": "Ice", + "damage": 60, + "duration": 3300, + "energy": 33, + "dps": 18.18 + }, + "112": { + "name": "Frost Breath", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "113": { + "name": "Absorb", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "114": { + "name": "Giga Drain", + "type": "Grass", + "damage": 50, + "duration": 3900, + "energy": 100, + "dps": 12.82 + }, + "115": { + "name": "Fire Punch", + "type": "Fire", + "damage": 55, + "duration": 2200, + "energy": 33, + "dps": 25 + }, + "116": { + "name": "Solar Beam", + "type": "Grass", + "damage": 180, + "duration": 4900, + "energy": 100, + "dps": 36.73 + }, + "117": { + "name": "Leaf Blade", + "type": "Grass", + "damage": 70, + "duration": 2400, + "energy": 33, + "dps": 29.17 + }, + "118": { + "name": "Power Whip", + "type": "Grass", + "damage": 90, + "duration": 2600, + "energy": 50, + "dps": 34.62 + }, + "119": { + "name": "Splash", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "120": { + "name": "Acid", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "121": { + "name": "Air Cutter", + "type": "Flying", + "damage": 60, + "duration": 2700, + "energy": 50, + "dps": 22.22 + }, + "122": { + "name": "Hurricane", + "type": "Flying", + "damage": 110, + "duration": 2700, + "energy": 100, + "dps": 40.74 + }, + "123": { + "name": "Brick Break", + "type": "Fighting", + "damage": 40, + "duration": 1600, + "energy": 33, + "dps": 25 + }, + "124": { + "name": "Cut", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "125": { + "name": "Swift", + "type": "Normal", + "damage": 60, + "duration": 2800, + "energy": 50, + "dps": 21.43 + }, + "126": { + "name": "Horn Attack", + "type": "Normal", + "damage": 40, + "duration": 1850, + "energy": 33, + "dps": 21.62 + }, + "127": { + "name": "Stomp", + "type": "Normal", + "damage": 55, + "duration": 1700, + "energy": 50, + "dps": 32.35 + }, + "128": { + "name": "Headbutt", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "129": { + "name": "Hyper Fang", + "type": "Normal", + "damage": 80, + "duration": 2500, + "energy": 50, + "dps": 32 + }, + "130": { + "name": "Slam", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "131": { + "name": "Body Slam", + "type": "Normal", + "damage": 50, + "duration": 1900, + "energy": 33, + "dps": 26.32 + }, + "132": { + "name": "Rest", + "type": "Normal", + "damage": 50, + "duration": 1900, + "energy": 33, + "dps": 26.32 + }, + "133": { + "name": "Struggle", + "type": "Normal", + "damage": 35, + "duration": 2200, + "energy": 0, + "dps": 15.91 + }, + "134": { + "name": "Scald (Blastoise)", + "type": "Water", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "135": { + "name": "Hydro Pump (Blastoise)", + "type": "Water", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "136": { + "name": "Wrap Green", + "type": "Normal", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "137": { + "name": "Wrap Pink", + "type": "Normal", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "200": { + "name": "Fury Cutter", + "type": "Bug", + "damage": 3, + "duration": 400, + "energy": 6, + "dps": 7.5 + }, + "201": { + "name": "Bug Bite", + "type": "Bug", + "damage": 5, + "duration": 500, + "energy": 6, + "dps": 10 + }, + "202": { + "name": "Bite", + "type": "Dark", + "damage": 6, + "duration": 500, + "energy": 4, + "dps": 12 + }, + "203": { + "name": "Sucker Punch", + "type": "Dark", + "damage": 7, + "duration": 700, + "energy": 8, + "dps": 10 + }, + "204": { + "name": "Dragon Breath", + "type": "Dragon", + "damage": 6, + "duration": 500, + "energy": 4, + "dps": 12 + }, + "205": { + "name": "Thunder Shock", + "type": "Electric", + "damage": 5, + "duration": 600, + "energy": 8, + "dps": 8.33 + }, + "206": { + "name": "Spark", + "type": "Electric", + "damage": 6, + "duration": 700, + "energy": 9, + "dps": 8.57 + }, + "207": { + "name": "Low Kick", + "type": "Fighting", + "damage": 6, + "duration": 600, + "energy": 6, + "dps": 10 + }, + "208": { + "name": "Karate Chop", + "type": "Fighting", + "damage": 8, + "duration": 800, + "energy": 10, + "dps": 10 + }, + "209": { + "name": "Ember", + "type": "Fire", + "damage": 10, + "duration": 1000, + "energy": 10, + "dps": 10 + }, + "210": { + "name": "Wing Attack", + "type": "Flying", + "damage": 8, + "duration": 800, + "energy": 9, + "dps": 10 + }, + "211": { + "name": "Peck", + "type": "Flying", + "damage": 10, + "duration": 1000, + "energy": 10, + "dps": 10 + }, + "212": { + "name": "Lick", + "type": "Ghost", + "damage": 5, + "duration": 500, + "energy": 6, + "dps": 10 + }, + "213": { + "name": "Shadow Claw", + "type": "Ghost", + "damage": 9, + "duration": 700, + "energy": 6, + "dps": 12.86 + }, + "214": { + "name": "Vine Whip", + "type": "Grass", + "damage": 7, + "duration": 600, + "energy": 6, + "dps": 11.67 + }, + "215": { + "name": "Razor Leaf", + "type": "Grass", + "damage": 13, + "duration": 1000, + "energy": 7, + "dps": 13 + }, + "216": { + "name": "Mud Shot", + "type": "Ground", + "damage": 5, + "duration": 600, + "energy": 7, + "dps": 8.33 + }, + "217": { + "name": "Ice Shard", + "type": "Ice", + "damage": 12, + "duration": 1200, + "energy": 12, + "dps": 10 + }, + "218": { + "name": "Frost Breath", + "type": "Ice", + "damage": 10, + "duration": 900, + "energy": 8, + "dps": 11.11 + }, + "219": { + "name": "Quick Attack", + "type": "Normal", + "damage": 8, + "duration": 800, + "energy": 10, + "dps": 10 + }, + "220": { + "name": "Scratch", + "type": "Normal", + "damage": 6, + "duration": 500, + "energy": 4, + "dps": 12 + }, + "221": { + "name": "Tackle", + "type": "Normal", + "damage": 5, + "duration": 500, + "energy": 5, + "dps": 10 + }, + "222": { + "name": "Pound", + "type": "Normal", + "damage": 7, + "duration": 600, + "energy": 6, + "dps": 11.67 + }, + "223": { + "name": "Cut", + "type": "Normal", + "damage": 5, + "duration": 500, + "energy": 5, + "dps": 10 + }, + "224": { + "name": "Poison Jab", + "type": "Poison", + "damage": 10, + "duration": 800, + "energy": 7, + "dps": 12.5 + }, + "225": { + "name": "Acid", + "type": "Poison", + "damage": 9, + "duration": 800, + "energy": 8, + "dps": 11.25 + }, + "226": { + "name": "Psycho Cut", + "type": "Psychic", + "damage": 5, + "duration": 600, + "energy": 8, + "dps": 8.33 + }, + "227": { + "name": "Rock Throw", + "type": "Rock", + "damage": 12, + "duration": 900, + "energy": 7, + "dps": 13.33 + }, + "228": { + "name": "Metal Claw", + "type": "Steel", + "damage": 8, + "duration": 700, + "energy": 7, + "dps": 11.43 + }, + "229": { + "name": "Bullet Punch", + "type": "Steel", + "damage": 9, + "duration": 900, + "energy": 10, + "dps": 10 + }, + "230": { + "name": "Water Gun", + "type": "Water", + "damage": 5, + "duration": 500, + "energy": 5, + "dps": 10 + }, + "231": { + "name": "Splash", + "type": "Water", + "damage": 0, + "duration": 1730, + "energy": 20, + "dps": 0 + }, + "232": { + "name": "Water Gun (Blastoise)", + "type": "", + "damage": 0, + "duration": 0, + "energy": 0, + "dps": 0 + }, + "233": { + "name": "Mud Slap", + "type": "Ground", + "damage": 15, + "duration": 1400, + "energy": 12, + "dps": 10.71 + }, + "234": { + "name": "Zen Headbutt", + "type": "Psychic", + "damage": 12, + "duration": 1100, + "energy": 10, + "dps": 10.91 + }, + "235": { + "name": "Confusion", + "type": "Psychic", + "damage": 20, + "duration": 1600, + "energy": 15, + "dps": 12.5 + }, + "236": { + "name": "Poison Sting", + "type": "Poison", + "damage": 5, + "duration": 600, + "energy": 7, + "dps": 8.33 + }, + "237": { + "name": "Bubble", + "type": "Water", + "damage": 12, + "duration": 1200, + "energy": 14, + "dps": 10 + }, + "238": { + "name": "Feint Attack", + "type": "Dark", + "damage": 10, + "duration": 900, + "energy": 9, + "dps": 11.11 + }, + "239": { + "name": "Steel Wing", + "type": "Steel", + "damage": 11, + "duration": 800, + "energy": 6, + "dps": 13.75 + }, + "240": { + "name": "Fire Fang", + "type": "Fire", + "damage": 11, + "duration": 900, + "energy": 8, + "dps": 12.22 + }, + "241": { + "name": "Rock Smash", + "type": "Fighting", + "damage": 15, + "duration": 1300, + "energy": 10, + "dps": 11.54 + }, + "242": { + "name": "Transform", + "type": "Normal", + "damage": 0, + "duration": 2230, + "energy": 0, + "dps": 0 + }, + "243": { + "name": "Counter", + "type": "Fighting", + "damage": 8, + "duration": 900, + "energy": 12, + "dps": 13.33 + }, + "244": { + "name": "Powder Snow", + "type": "Ice", + "damage": 6, + "duration": 1000, + "energy": 15, + "dps": 6 + }, + "245": { + "name": "Close Combat", + "type": "Fighting", + "damage": 100, + "duration": 2300, + "energy": 100, + "dps": 43.48 + }, + "246": { + "name": "Dynamic Punch", + "type": "Fighting", + "damage": 90, + "duration": 2700, + "energy": 50, + "dps": 33.33 + }, + "247": { + "name": "Focus Blast", + "type": "Fighting", + "damage": 140, + "duration": 3500, + "energy": 140, + "dps": 40 + }, + "248": { + "name": "Aurora Beam", + "type": "Ice", + "damage": 80, + "duration": 3550, + "energy": 50, + "dps": 22.54 + }, + "249": { + "name": "Charge Beam", + "type": "Electric", + "damage": 8, + "duration": 1100, + "energy": 15, + "dps": 7.27 + }, + "250": { + "name": "Volt Switch", + "type": "Electric", + "damage": 20, + "duration": 2300, + "energy": 25, + "dps": 8.7 + }, + "251": { + "name": "Wild Charge", + "type": "Electric", + "damage": 90, + "duration": 2600, + "energy": 50, + "dps": 34.62 + }, + "252": { + "name": "Zap Cannon", + "type": "Electric", + "damage": 140, + "duration": 3700, + "energy": 100, + "dps": 37.84 + }, + "253": { + "name": "Dragon Tail", + "type": "Dragon", + "damage": 15, + "duration": 1100, + "energy": 9, + "dps": 13.64 + }, + "254": { + "name": "Avalanche", + "type": "Ice", + "damage": 90, + "duration": 2700, + "energy": 50, + "dps": 33.33 + }, + "255": { + "name": "Air Slash", + "type": "Flying", + "damage": 14, + "duration": 1200, + "energy": 10, + "dps": 11.67 + }, + "256": { + "name": "Brave Bird", + "type": "Flying", + "damage": 90, + "duration": 2000, + "energy": 100, + "dps": 45 + }, + "257": { + "name": "Sky Attack", + "type": "Flying", + "damage": 70, + "duration": 2000, + "energy": 50, + "dps": 35 + }, + "258": { + "name": "Sand Tomb", + "type": "Ground", + "damage": 80, + "duration": 4000, + "energy": 50, + "dps": 20 + }, + "259": { + "name": "Rock Blast", + "type": "Rock", + "damage": 50, + "duration": 2100, + "energy": 33, + "dps": 23.81 + }, + "260": { + "name": "Infestation", + "type": "Bug", + "damage": 10, + "duration": 1100, + "energy": 14, + "dps": 9.09 + }, + "261": { + "name": "Struggle Bug", + "type": "Bug", + "damage": 15, + "duration": 1500, + "energy": 15, + "dps": 10 + }, + "262": { + "name": "Silver Wind", + "type": "Bug", + "damage": 70, + "duration": 3700, + "energy": 33, + "dps": 18.92 + }, + "263": { + "name": "Astonish", + "type": "Ghost", + "damage": 8, + "duration": 1100, + "energy": 14, + "dps": 7.27 + }, + "264": { + "name": "Hex", + "type": "Ghost", + "damage": 10, + "duration": 1200, + "energy": 15, + "dps": 8.33 + }, + "265": { + "name": "Night Shade", + "type": "Ghost", + "damage": 60, + "duration": 2600, + "energy": 50, + "dps": 23.08 + }, + "266": { + "name": "Iron Tail", + "type": "Steel", + "damage": 15, + "duration": 1100, + "energy": 7, + "dps": 13.64 + }, + "267": { + "name": "Gyro Ball", + "type": "Steel", + "damage": 80, + "duration": 3300, + "energy": 50, + "dps": 24.24 + }, + "268": { + "name": "Heavy Slam", + "type": "Steel", + "damage": 70, + "duration": 2100, + "energy": 50, + "dps": 33.33 + }, + "269": { + "name": "Fire Spin", + "type": "Fire", + "damage": 14, + "duration": 1100, + "energy": 10, + "dps": 12.73 + }, + "270": { + "name": "Overheat", + "type": "Fire", + "damage": 160, + "duration": 4000, + "energy": 100, + "dps": 40 + }, + "271": { + "name": "Bullet Seed", + "type": "Grass", + "damage": 8, + "duration": 1100, + "energy": 14, + "dps": 7.27 + }, + "272": { + "name": "Grass Knot", + "type": "Grass", + "damage": 90, + "duration": 2600, + "energy": 50, + "dps": 34.62 + }, + "273": { + "name": "Energy Ball", + "type": "Grass", + "damage": 90, + "duration": 3900, + "energy": 50, + "dps": 23.08 + }, + "274": { + "name": "Extrasensory", + "type": "Psychic", + "damage": 12, + "duration": 1100, + "energy": 12, + "dps": 10.91 + }, + "275": { + "name": "Future Sight", + "type": "Psychic", + "damage": 120, + "duration": 2700, + "energy": 100, + "dps": 44.44 + }, + "276": { + "name": "Mirror Coat", + "type": "Psychic", + "damage": 60, + "duration": 2600, + "energy": 50, + "dps": 23.08 + }, + "277": { + "name": "Outrage", + "type": "Dragon", + "damage": 110, + "duration": 3900, + "energy": 50, + "dps": 28.21 + }, + "278": { + "name": "Snarl", + "type": "Dark", + "damage": 12, + "duration": 1100, + "energy": 12, + "dps": 10.91 + }, + "279": { + "name": "Crunch", + "type": "Dark", + "damage": 70, + "duration": 3200, + "energy": 33, + "dps": 21.88 + }, + "280": { + "name": "Foul Play", + "type": "Dark", + "damage": 70, + "duration": 2000, + "energy": 50, + "dps": 35 + }, + "281": { + "name": "Hidden Power", + "type": "Normal", + "damage": 15, + "duration": 1500, + "energy": 15, + "dps": 10 + }, + "282": { + "name": "Take Down", + "type": "Normal", + "damage": 8, + "duration": 1200, + "energy": 10, + "dps": 6.7 + }, + "283": { + "name": "Waterfall", + "type": "Water", + "damage": 16, + "duration": 1200, + "energy": 8, + "dps": 13.33 + }, + "284": { + "name": "Surf", + "type": "Water", + "damage": 65, + "duration": 1700, + "energy": 50, + "dps": 29.5 + }, + "285": { + "name": "Draco Meteor", + "type": "Dragon", + "damage": 150, + "duration": 3600, + "energy": 100, + "dps": 36.6 + }, + "286": { + "name": "Doom Desire", + "type": "Steel", + "damage": 80, + "duration": 1700, + "energy": 50, + "dps": 36.4 + }, + "287": { + "name": "Yawn", + "type": "Normal", + "damage": 0, + "duration": 1700, + "energy": 15, + "dps": 0 + }, + "288": { + "name": "Psycho Boost", + "type": "Psychic", + "damage": 70, + "duration": 4000, + "energy": 50, + "dps": 15.6 + }, + "289": { + "name": "Origin Pulse", + "type": "Water", + "damage": 130, + "duration": 1700, + "energy": 100, + "dps": 59.1 + }, + "290": { + "name": "Precipice Blades", + "type": "Ground", + "damage": 130, + "duration": 1700, + "energy": 100, + "dps": 59.1 + } +} \ No newline at end of file diff --git a/data/pokemon.json b/data/pokemon.json new file mode 100644 index 0000000..90dbfad --- /dev/null +++ b/data/pokemon.json @@ -0,0 +1,4678 @@ +{ + "1": { + "name": "Bulbasaur", + "types": [ + "Grass", + "Poison" + ] + }, + "2": { + "name": "Ivysaur", + "types": [ + "Grass", + "Poison" + ] + }, + "3": { + "name": "Venusaur", + "types": [ + "Grass", + "Poison" + ] + }, + "4": { + "name": "Charmander", + "types": [ + "Fire" + ] + }, + "5": { + "name": "Charmeleon", + "types": [ + "Fire" + ] + }, + "6": { + "name": "Charizard", + "types": [ + "Fire", + "Flying" + ] + }, + "7": { + "name": "Squirtle", + "types": [ + "Water" + ] + }, + "8": { + "name": "Wartortle", + "types": [ + "Water" + ] + }, + "9": { + "name": "Blastoise", + "types": [ + "Water" + ] + }, + "10": { + "name": "Caterpie", + "types": [ + "Bug" + ] + }, + "11": { + "name": "Metapod", + "types": [ + "Bug" + ] + }, + "12": { + "name": "Butterfree", + "types": [ + "Bug", + "Flying" + ] + }, + "13": { + "name": "Weedle", + "types": [ + "Bug", + "Poison" + ] + }, + "14": { + "name": "Kakuna", + "types": [ + "Bug", + "Poison" + ] + }, + "15": { + "name": "Beedrill", + "types": [ + "Bug", + "Poison" + ] + }, + "16": { + "name": "Pidgey", + "types": [ + "Normal", + "Flying" + ] + }, + "17": { + "name": "Pidgeotto", + "types": [ + "Normal", + "Flying" + ] + }, + "18": { + "name": "Pidgeot", + "types": [ + "Normal", + "Flying" + ] + }, + "19": { + "name": "Rattata", + "types": [ + "Normal" + ] + }, + "20": { + "name": "Raticate", + "types": [ + "Normal" + ] + }, + "21": { + "name": "Spearow", + "types": [ + "Normal", + "Flying" + ] + }, + "22": { + "name": "Fearow", + "types": [ + "Normal", + "Flying" + ] + }, + "23": { + "name": "Ekans", + "types": [ + "Poison" + ] + }, + "24": { + "name": "Arbok", + "types": [ + "Poison" + ] + }, + "25": { + "name": "Pikachu", + "types": [ + "Electric" + ] + }, + "26": { + "name": "Raichu", + "types": [ + "Electric" + ] + }, + "27": { + "name": "Sandshrew", + "types": [ + "Ground" + ] + }, + "28": { + "name": "Sandslash", + "types": [ + "Ground" + ] + }, + "29": { + "name": "Nidoranf", + "types": [ + "Poison" + ] + }, + "30": { + "name": "Nidorina", + "types": [ + "Poison" + ] + }, + "31": { + "name": "Nidoqueen", + "types": [ + "Poison", + "Ground" + ] + }, + "32": { + "name": "Nidoranm", + "types": [ + "Poison" + ] + }, + "33": { + "name": "Nidorino", + "types": [ + "Poison" + ] + }, + "34": { + "name": "Nidoking", + "types": [ + "Poison", + "Ground" + ] + }, + "35": { + "name": "Clefairy", + "types": [ + "Fairy" + ] + }, + "36": { + "name": "Clefable", + "types": [ + "Fairy" + ] + }, + "37": { + "name": "Vulpix", + "types": [ + "Fire" + ] + }, + "38": { + "name": "Ninetales", + "types": [ + "Fire" + ] + }, + "39": { + "name": "Jigglypuff", + "types": [ + "Normal", + "Fairy" + ] + }, + "40": { + "name": "Wigglytuff", + "types": [ + "Normal", + "Fairy" + ] + }, + "41": { + "name": "Zubat", + "types": [ + "Poison", + "Flying" + ] + }, + "42": { + "name": "Golbat", + "types": [ + "Poison", + "Flying" + ] + }, + "43": { + "name": "Oddish", + "types": [ + "Grass", + "Poison" + ] + }, + "44": { + "name": "Gloom", + "types": [ + "Grass", + "Poison" + ] + }, + "45": { + "name": "Vileplume", + "types": [ + "Grass", + "Poison" + ] + }, + "46": { + "name": "Paras", + "types": [ + "Bug", + "Grass" + ] + }, + "47": { + "name": "Parasect", + "types": [ + "Bug", + "Grass" + ] + }, + "48": { + "name": "Venonat", + "types": [ + "Bug", + "Poison" + ] + }, + "49": { + "name": "Venomoth", + "types": [ + "Bug", + "Poison" + ] + }, + "50": { + "name": "Diglett", + "types": [ + "Ground" + ] + }, + "51": { + "name": "Dugtrio", + "types": [ + "Ground" + ] + }, + "52": { + "name": "Meowth", + "types": [ + "Normal" + ] + }, + "53": { + "name": "Persian", + "types": [ + "Normal" + ] + }, + "54": { + "name": "Psyduck", + "types": [ + "Water" + ] + }, + "55": { + "name": "Golduck", + "types": [ + "Water" + ] + }, + "56": { + "name": "Mankey", + "types": [ + "Fighting" + ] + }, + "57": { + "name": "Primeape", + "types": [ + "Fighting" + ] + }, + "58": { + "name": "Growlithe", + "types": [ + "Fire" + ] + }, + "59": { + "name": "Arcanine", + "types": [ + "Fire" + ] + }, + "60": { + "name": "Poliwag", + "types": [ + "Water" + ] + }, + "61": { + "name": "Poliwhirl", + "types": [ + "Water" + ] + }, + "62": { + "name": "Poliwrath", + "types": [ + "Water", + "Fighting" + ] + }, + "63": { + "name": "Abra", + "types": [ + "Psychic" + ] + }, + "64": { + "name": "Kadabra", + "types": [ + "Psychic" + ] + }, + "65": { + "name": "Alakazam", + "types": [ + "Psychic" + ] + }, + "66": { + "name": "Machop", + "types": [ + "Fighting" + ] + }, + "67": { + "name": "Machoke", + "types": [ + "Fighting" + ] + }, + "68": { + "name": "Machamp", + "types": [ + "Fighting" + ] + }, + "69": { + "name": "Bellsprout", + "types": [ + "Grass", + "Poison" + ] + }, + "70": { + "name": "Weepinbell", + "types": [ + "Grass", + "Poison" + ] + }, + "71": { + "name": "Victreebel", + "types": [ + "Grass", + "Poison" + ] + }, + "72": { + "name": "Tentacool", + "types": [ + "Water", + "Poison" + ] + }, + "73": { + "name": "Tentacruel", + "types": [ + "Water", + "Poison" + ] + }, + "74": { + "name": "Geodude", + "types": [ + "Rock", + "Ground" + ] + }, + "75": { + "name": "Graveler", + "types": [ + "Rock", + "Ground" + ] + }, + "76": { + "name": "Golem", + "types": [ + "Rock", + "Ground" + ] + }, + "77": { + "name": "Ponyta", + "types": [ + "Fire" + ] + }, + "78": { + "name": "Rapidash", + "types": [ + "Fire" + ] + }, + "79": { + "name": "Slowpoke", + "types": [ + "Water", + "Psychic" + ] + }, + "80": { + "name": "Slowbro", + "types": [ + "Water", + "Psychic" + ] + }, + "81": { + "name": "Magnemite", + "types": [ + "Electric", + "Steel" + ] + }, + "82": { + "name": "Magneton", + "types": [ + "Electric", + "Steel" + ] + }, + "83": { + "name": "Farfetch'd", + "types": [ + "Normal", + "Flying" + ] + }, + "84": { + "name": "Doduo", + "types": [ + "Normal", + "Flying" + ] + }, + "85": { + "name": "Dodrio", + "types": [ + "Normal", + "Flying" + ] + }, + "86": { + "name": "Seel", + "types": [ + "Water" + ] + }, + "87": { + "name": "Dewgong", + "types": [ + "Water", + "Ice" + ] + }, + "88": { + "name": "Grimer", + "types": [ + "Poison" + ] + }, + "89": { + "name": "Muk", + "types": [ + "Poison" + ] + }, + "90": { + "name": "Shellder", + "types": [ + "Water" + ] + }, + "91": { + "name": "Cloyster", + "types": [ + "Water", + "Ice" + ] + }, + "92": { + "name": "Gastly", + "types": [ + "Ghost", + "Poison" + ] + }, + "93": { + "name": "Haunter", + "types": [ + "Ghost", + "Poison" + ] + }, + "94": { + "name": "Gengar", + "types": [ + "Ghost", + "Poison" + ] + }, + "95": { + "name": "Onix", + "types": [ + "Rock", + "Ground" + ] + }, + "96": { + "name": "Drowzee", + "types": [ + "Psychic" + ] + }, + "97": { + "name": "Hypno", + "types": [ + "Psychic" + ] + }, + "98": { + "name": "Krabby", + "types": [ + "Water" + ] + }, + "99": { + "name": "Kingler", + "types": [ + "Water" + ] + }, + "100": { + "name": "Voltorb", + "types": [ + "Electric" + ] + }, + "101": { + "name": "Electrode", + "types": [ + "Electric" + ] + }, + "102": { + "name": "Exeggcute", + "types": [ + "Grass", + "Psychic" + ] + }, + "103": { + "name": "Exeggutor", + "types": [ + "Grass", + "Psychic" + ] + }, + "104": { + "name": "Cubone", + "types": [ + "Ground" + ] + }, + "105": { + "name": "Marowak", + "types": [ + "Ground" + ] + }, + "106": { + "name": "Hitmonlee", + "types": [ + "Fighting" + ] + }, + "107": { + "name": "Hitmonchan", + "types": [ + "Fighting" + ] + }, + "108": { + "name": "Lickitung", + "types": [ + "Normal" + ] + }, + "109": { + "name": "Koffing", + "types": [ + "Poison" + ] + }, + "110": { + "name": "Weezing", + "types": [ + "Poison" + ] + }, + "111": { + "name": "Rhyhorn", + "types": [ + "Ground", + "Rock" + ] + }, + "112": { + "name": "Rhydon", + "types": [ + "Ground", + "Rock" + ] + }, + "113": { + "name": "Chansey", + "types": [ + "Normal" + ] + }, + "114": { + "name": "Tangela", + "types": [ + "Grass" + ] + }, + "115": { + "name": "Kangaskhan", + "types": [ + "Normal" + ] + }, + "116": { + "name": "Horsea", + "types": [ + "Water" + ] + }, + "117": { + "name": "Seadra", + "types": [ + "Water" + ] + }, + "118": { + "name": "Goldeen", + "types": [ + "Water" + ] + }, + "119": { + "name": "Seaking", + "types": [ + "Water" + ] + }, + "120": { + "name": "Staryu", + "types": [ + "Water" + ] + }, + "121": { + "name": "Starmie", + "types": [ + "Water", + "Psychic" + ] + }, + "122": { + "name": "Mr. Mime", + "types": [ + "Psychic", + "Fairy" + ] + }, + "123": { + "name": "Scyther", + "types": [ + "Bug", + "Flying" + ] + }, + "124": { + "name": "Jynx", + "types": [ + "Ice", + "Psychic" + ] + }, + "125": { + "name": "Electabuzz", + "types": [ + "Electric" + ] + }, + "126": { + "name": "Magmar", + "types": [ + "Fire" + ] + }, + "127": { + "name": "Pinsir", + "types": [ + "Bug" + ] + }, + "128": { + "name": "Tauros", + "types": [ + "Normal" + ] + }, + "129": { + "name": "Magikarp", + "types": [ + "Water" + ] + }, + "130": { + "name": "Gyarados", + "types": [ + "Water", + "Flying" + ] + }, + "131": { + "name": "Lapras", + "types": [ + "Water", + "Ice" + ] + }, + "132": { + "name": "Ditto", + "types": [ + "Normal" + ] + }, + "133": { + "name": "Eevee", + "types": [ + "Normal" + ] + }, + "134": { + "name": "Vaporeon", + "types": [ + "Water" + ] + }, + "135": { + "name": "Jolteon", + "types": [ + "Electric" + ] + }, + "136": { + "name": "Flareon", + "types": [ + "Fire" + ] + }, + "137": { + "name": "Porygon", + "types": [ + "Normal" + ] + }, + "138": { + "name": "Omanyte", + "types": [ + "Rock", + "Water" + ] + }, + "139": { + "name": "Omastar", + "types": [ + "Rock", + "Water" + ] + }, + "140": { + "name": "Kabuto", + "types": [ + "Rock", + "Water" + ] + }, + "141": { + "name": "Kabutops", + "types": [ + "Rock", + "Water" + ] + }, + "142": { + "name": "Aerodactyl", + "types": [ + "Rock", + "Flying" + ] + }, + "143": { + "name": "Snorlax", + "types": [ + "Normal" + ] + }, + "144": { + "name": "Articuno", + "types": [ + "Ice", + "Flying" + ] + }, + "145": { + "name": "Zapdos", + "types": [ + "Electric", + "Flying" + ] + }, + "146": { + "name": "Moltres", + "types": [ + "Fire", + "Flying" + ] + }, + "147": { + "name": "Dratini", + "types": [ + "Dragon" + ] + }, + "148": { + "name": "Dragonair", + "types": [ + "Dragon" + ] + }, + "149": { + "name": "Dragonite", + "types": [ + "Dragon", + "Flying" + ] + }, + "150": { + "name": "Mewtwo", + "types": [ + "Psychic" + ] + }, + "151": { + "name": "Mew", + "types": [ + "Psychic" + ] + }, + "152": { + "name": "Chikorita", + "types": [ + "Grass" + ] + }, + "153": { + "name": "Bayleef", + "types": [ + "Grass" + ] + }, + "154": { + "name": "Meganium", + "types": [ + "Grass" + ] + }, + "155": { + "name": "Cyndaquil", + "types": [ + "Fire" + ] + }, + "156": { + "name": "Quilava", + "types": [ + "Fire" + ] + }, + "157": { + "name": "Typhlosion", + "types": [ + "Fire" + ] + }, + "158": { + "name": "Totodile", + "types": [ + "Water" + ] + }, + "159": { + "name": "Croconaw", + "types": [ + "Water" + ] + }, + "160": { + "name": "Feraligatr", + "types": [ + "Water" + ] + }, + "161": { + "name": "Sentret", + "types": [ + "Normal" + ] + }, + "162": { + "name": "Furret", + "types": [ + "Normal" + ] + }, + "163": { + "name": "Hoothoot", + "types": [ + "Normal", + "Flying" + ] + }, + "164": { + "name": "Noctowl", + "types": [ + "Normal", + "Flying" + ] + }, + "165": { + "name": "Ledyba", + "types": [ + "Bug", + "Flying" + ] + }, + "166": { + "name": "Ledian", + "types": [ + "Bug", + "Flying" + ] + }, + "167": { + "name": "Spinarak", + "types": [ + "Bug", + "Poison" + ] + }, + "168": { + "name": "Ariados", + "types": [ + "Bug", + "Poison" + ] + }, + "169": { + "name": "Crobat", + "types": [ + "Poison", + "Flying" + ] + }, + "170": { + "name": "Chinchou", + "types": [ + "Water", + "Electric" + ] + }, + "171": { + "name": "Lanturn", + "types": [ + "Water", + "Electric" + ] + }, + "172": { + "name": "Pichu", + "types": [ + "Electric" + ] + }, + "173": { + "name": "Cleffa", + "types": [ + "Fairy" + ] + }, + "174": { + "name": "Igglybuff", + "types": [ + "Normal", + "Fairy" + ] + }, + "175": { + "name": "Togepi", + "types": [ + "Fairy" + ] + }, + "176": { + "name": "Togetic", + "types": [ + "Fairy", + "Flying" + ] + }, + "177": { + "name": "Natu", + "types": [ + "Psychic", + "Flying" + ] + }, + "178": { + "name": "Xatu", + "types": [ + "Psychic", + "Flying" + ] + }, + "179": { + "name": "Mareep", + "types": [ + "Electric" + ] + }, + "180": { + "name": "Flaaffy", + "types": [ + "Electric" + ] + }, + "181": { + "name": "Ampharos", + "types": [ + "Electric" + ] + }, + "182": { + "name": "Bellossom", + "types": [ + "Grass" + ] + }, + "183": { + "name": "Marill", + "types": [ + "Water", + "Fairy" + ] + }, + "184": { + "name": "Azumarill", + "types": [ + "Water", + "Fairy" + ] + }, + "185": { + "name": "Sudowoodo", + "types": [ + "Rock" + ] + }, + "186": { + "name": "Politoed", + "types": [ + "Water" + ] + }, + "187": { + "name": "Hoppip", + "types": [ + "Grass", + "Flying" + ] + }, + "188": { + "name": "Skiploom", + "types": [ + "Grass", + "Flying" + ] + }, + "189": { + "name": "Jumpluff", + "types": [ + "Grass", + "Flying" + ] + }, + "190": { + "name": "Aipom", + "types": [ + "Normal" + ] + }, + "191": { + "name": "Sunkern", + "types": [ + "Grass" + ] + }, + "192": { + "name": "Sunflora", + "types": [ + "Grass" + ] + }, + "193": { + "name": "Yanma", + "types": [ + "Bug", + "Flying" + ] + }, + "194": { + "name": "Wooper", + "types": [ + "Water", + "Ground" + ] + }, + "195": { + "name": "Quagsire", + "types": [ + "Water", + "Ground" + ] + }, + "196": { + "name": "Espeon", + "types": [ + "Psychic" + ] + }, + "197": { + "name": "Umbreon", + "types": [ + "Dark" + ] + }, + "198": { + "name": "Murkrow", + "types": [ + "Dark", + "Flying" + ] + }, + "199": { + "name": "Slowking", + "types": [ + "Water", + "Psychic" + ] + }, + "200": { + "name": "Misdreavus", + "types": [ + "Ghost" + ] + }, + "201": { + "name": "Unown", + "types": [ + "Psychic" + ] + }, + "202": { + "name": "Wobbuffet", + "types": [ + "Psychic" + ] + }, + "203": { + "name": "Girafarig", + "types": [ + "Normal", + "Psychic" + ] + }, + "204": { + "name": "Pineco", + "types": [ + "Bug" + ] + }, + "205": { + "name": "Forretress", + "types": [ + "Bug", + "Steel" + ] + }, + "206": { + "name": "Dunsparce", + "types": [ + "Normal" + ] + }, + "207": { + "name": "Gligar", + "types": [ + "Ground", + "Flying" + ] + }, + "208": { + "name": "Steelix", + "types": [ + "Steel", + "Ground" + ] + }, + "209": { + "name": "Snubbull", + "types": [ + "Fairy" + ] + }, + "210": { + "name": "Granbull", + "types": [ + "Fairy" + ] + }, + "211": { + "name": "Qwilfish", + "types": [ + "Water", + "Poison" + ] + }, + "212": { + "name": "Scizor", + "types": [ + "Bug", + "Steel" + ] + }, + "213": { + "name": "Shuckle", + "types": [ + "Bug", + "Rock" + ] + }, + "214": { + "name": "Heracross", + "types": [ + "Bug", + "Fighting" + ] + }, + "215": { + "name": "Sneasel", + "types": [ + "Dark", + "Ice" + ] + }, + "216": { + "name": "Teddiursa", + "types": [ + "Normal" + ] + }, + "217": { + "name": "Ursaring", + "types": [ + "Normal" + ] + }, + "218": { + "name": "Slugma", + "types": [ + "Fire" + ] + }, + "219": { + "name": "Magcargo", + "types": [ + "Fire", + "Rock" + ] + }, + "220": { + "name": "Swinub", + "types": [ + "Ice", + "Ground" + ] + }, + "221": { + "name": "Piloswine", + "types": [ + "Ice", + "Ground" + ] + }, + "222": { + "name": "Corsola", + "types": [ + "Water", + "Rock" + ] + }, + "223": { + "name": "Remoraid", + "types": [ + "Water" + ] + }, + "224": { + "name": "Octillery", + "types": [ + "Water" + ] + }, + "225": { + "name": "Delibird", + "types": [ + "Ice", + "Flying" + ] + }, + "226": { + "name": "Mantine", + "types": [ + "Water", + "Flying" + ] + }, + "227": { + "name": "Skarmory", + "types": [ + "Steel", + "Flying" + ] + }, + "228": { + "name": "Houndour", + "types": [ + "Dark", + "Fire" + ] + }, + "229": { + "name": "Houndoom", + "types": [ + "Dark", + "Fire" + ] + }, + "230": { + "name": "Kingdra", + "types": [ + "Water", + "Dragon" + ] + }, + "231": { + "name": "Phanpy", + "types": [ + "Ground" + ] + }, + "232": { + "name": "Donphan", + "types": [ + "Ground" + ] + }, + "233": { + "name": "Porygon2", + "types": [ + "Normal" + ] + }, + "234": { + "name": "Stantler", + "types": [ + "Normal" + ] + }, + "235": { + "name": "Smeargle", + "types": [ + "Normal" + ] + }, + "236": { + "name": "Tyrogue", + "types": [ + "Fighting" + ] + }, + "237": { + "name": "Hitmontop", + "types": [ + "Fighting" + ] + }, + "238": { + "name": "Smoochum", + "types": [ + "Ice", + "Psychic" + ] + }, + "239": { + "name": "Elekid", + "types": [ + "Electric" + ] + }, + "240": { + "name": "Magby", + "types": [ + "Fire" + ] + }, + "241": { + "name": "Miltank", + "types": [ + "Normal" + ] + }, + "242": { + "name": "Blissey", + "types": [ + "Normal" + ] + }, + "243": { + "name": "Raikou", + "types": [ + "Electric" + ] + }, + "244": { + "name": "Entei", + "types": [ + "Fire" + ] + }, + "245": { + "name": "Suicune", + "types": [ + "Water" + ] + }, + "246": { + "name": "Larvitar", + "types": [ + "Rock", + "Ground" + ] + }, + "247": { + "name": "Pupitar", + "types": [ + "Rock", + "Ground" + ] + }, + "248": { + "name": "Tyranitar", + "types": [ + "Rock", + "Dark" + ] + }, + "249": { + "name": "Lugia", + "types": [ + "Psychic", + "Flying" + ] + }, + "250": { + "name": "Ho-Oh", + "types": [ + "Fire", + "Flying" + ] + }, + "251": { + "name": "Celebi", + "types": [ + "Psychic", + "Grass" + ] + }, + "252": { + "name": "Treecko", + "types": [ + "Grass" + ] + }, + "253": { + "name": "Grovyle", + "types": [ + "Grass" + ] + }, + "254": { + "name": "Sceptile", + "types": [ + "Grass" + ] + }, + "255": { + "name": "Torchic", + "types": [ + "Fire" + ] + }, + "256": { + "name": "Combusken", + "types": [ + "Fire", + "Fighting" + ] + }, + "257": { + "name": "Blaziken", + "types": [ + "Fire", + "Fighting" + ] + }, + "258": { + "name": "Mudkip", + "types": [ + "Water" + ] + }, + "259": { + "name": "Marshtomp", + "types": [ + "Water", + "Ground" + ] + }, + "260": { + "name": "Swampert", + "types": [ + "Water", + "Ground" + ] + }, + "261": { + "name": "Poochyena", + "types": [ + "Dark" + ] + }, + "262": { + "name": "Mightyena", + "types": [ + "Dark" + ] + }, + "263": { + "name": "Zigzagoon", + "types": [ + "Normal" + ] + }, + "264": { + "name": "Linoone", + "types": [ + "Normal" + ] + }, + "265": { + "name": "Wurmple", + "types": [ + "Bug" + ] + }, + "266": { + "name": "Silcoon", + "types": [ + "Bug" + ] + }, + "267": { + "name": "Beautifly", + "types": [ + "Bug", + "Flying" + ] + }, + "268": { + "name": "Cascoon", + "types": [ + "Bug" + ] + }, + "269": { + "name": "Dustox", + "types": [ + "Bug", + "Poison" + ] + }, + "270": { + "name": "Lotad", + "types": [ + "Water", + "Grass" + ] + }, + "271": { + "name": "Lombre", + "types": [ + "Water", + "Grass" + ] + }, + "272": { + "name": "Ludicolo", + "types": [ + "Water", + "Grass" + ] + }, + "273": { + "name": "Seedot", + "types": [ + "Grass" + ] + }, + "274": { + "name": "Nuzleaf", + "types": [ + "Grass", + "Dark" + ] + }, + "275": { + "name": "Shiftry", + "types": [ + "Grass", + "Dark" + ] + }, + "276": { + "name": "Taillow", + "types": [ + "Normal", + "Flying" + ] + }, + "277": { + "name": "Swellow", + "types": [ + "Normal", + "Flying" + ] + }, + "278": { + "name": "Wingull", + "types": [ + "Water", + "Flying" + ] + }, + "279": { + "name": "Pelipper", + "types": [ + "Water", + "Flying" + ] + }, + "280": { + "name": "Ralts", + "types": [ + "Psychic", + "Fairy" + ] + }, + "281": { + "name": "Kirlia", + "types": [ + "Psychic", + "Fairy" + ] + }, + "282": { + "name": "Gardevoir", + "types": [ + "Psychic", + "Fairy" + ] + }, + "283": { + "name": "Surskit", + "types": [ + "Bug", + "Water" + ] + }, + "284": { + "name": "Masquerain", + "types": [ + "Bug", + "Flying" + ] + }, + "285": { + "name": "Shroomish", + "types": [ + "Grass" + ] + }, + "286": { + "name": "Breloom", + "types": [ + "Grass", + "Fighting" + ] + }, + "287": { + "name": "Slakoth", + "types": [ + "Normal" + ] + }, + "288": { + "name": "Vigoroth", + "types": [ + "Normal" + ] + }, + "289": { + "name": "Slaking", + "types": [ + "Normal" + ] + }, + "290": { + "name": "Nincada", + "types": [ + "Bug", + "Ground" + ] + }, + "291": { + "name": "Ninjask", + "types": [ + "Bug", + "Flying" + ] + }, + "292": { + "name": "Shedinja", + "types": [ + "Bug", + "Ghost" + ] + }, + "293": { + "name": "Whismur", + "types": [ + "Normal" + ] + }, + "294": { + "name": "Loudred", + "types": [ + "Normal" + ] + }, + "295": { + "name": "Exploud", + "types": [ + "Normal" + ] + }, + "296": { + "name": "Makuhita", + "types": [ + "Fighting" + ] + }, + "297": { + "name": "Hariyama", + "types": [ + "Fighting" + ] + }, + "298": { + "name": "Azurill", + "types": [ + "Normal", + "Fairy" + ] + }, + "299": { + "name": "Nosepass", + "types": [ + "Rock" + ] + }, + "300": { + "name": "Skitty", + "types": [ + "Normal" + ] + }, + "301": { + "name": "Delcatty", + "types": [ + "Normal" + ] + }, + "302": { + "name": "Sableye", + "types": [ + "Dark", + "Ghost" + ] + }, + "303": { + "name": "Mawile", + "types": [ + "Steel", + "Fairy" + ] + }, + "304": { + "name": "Aron", + "types": [ + "Steel", + "Rock" + ] + }, + "305": { + "name": "Lairon", + "types": [ + "Steel", + "Rock" + ] + }, + "306": { + "name": "Aggron", + "types": [ + "Steel", + "Rock" + ] + }, + "307": { + "name": "Meditite", + "types": [ + "Fighting", + "Psychic" + ] + }, + "308": { + "name": "Medicham", + "types": [ + "Fighting", + "Psychic" + ] + }, + "309": { + "name": "Electrike", + "types": [ + "Electric" + ] + }, + "310": { + "name": "Manectric", + "types": [ + "Electric" + ] + }, + "311": { + "name": "Plusle", + "types": [ + "Electric" + ] + }, + "312": { + "name": "Minun", + "types": [ + "Electric" + ] + }, + "313": { + "name": "Volbeat", + "types": [ + "Bug" + ] + }, + "314": { + "name": "Illumise", + "types": [ + "Bug" + ] + }, + "315": { + "name": "Roselia", + "types": [ + "Grass", + "Poison" + ] + }, + "316": { + "name": "Gulpin", + "types": [ + "Poison" + ] + }, + "317": { + "name": "Swalot", + "types": [ + "Poison" + ] + }, + "318": { + "name": "Carvanha", + "types": [ + "Water", + "Dark" + ] + }, + "319": { + "name": "Sharpedo", + "types": [ + "Water", + "Dark" + ] + }, + "320": { + "name": "Wailmer", + "types": [ + "Water" + ] + }, + "321": { + "name": "Wailord", + "types": [ + "Water" + ] + }, + "322": { + "name": "Numel", + "types": [ + "Fire", + "Ground" + ] + }, + "323": { + "name": "Camerupt", + "types": [ + "Fire", + "Ground" + ] + }, + "324": { + "name": "Torkoal", + "types": [ + "Fire" + ] + }, + "325": { + "name": "Spoink", + "types": [ + "Psychic" + ] + }, + "326": { + "name": "Grumpig", + "types": [ + "Psychic" + ] + }, + "327": { + "name": "Spinda", + "types": [ + "Normal" + ] + }, + "328": { + "name": "Trapinch", + "types": [ + "Ground" + ] + }, + "329": { + "name": "Vibrava", + "types": [ + "Ground", + "Dragon" + ] + }, + "330": { + "name": "Flygon", + "types": [ + "Ground", + "Dragon" + ] + }, + "331": { + "name": "Cacnea", + "types": [ + "Grass" + ] + }, + "332": { + "name": "Cacturne", + "types": [ + "Grass", + "Dark" + ] + }, + "333": { + "name": "Swablu", + "types": [ + "Normal", + "Flying" + ] + }, + "334": { + "name": "Altaria", + "types": [ + "Dragon", + "Flying" + ] + }, + "335": { + "name": "Zangoose", + "types": [ + "Normal" + ] + }, + "336": { + "name": "Seviper", + "types": [ + "Poison" + ] + }, + "337": { + "name": "Lunatone", + "types": [ + "Rock", + "Psychic" + ] + }, + "338": { + "name": "Solrock", + "types": [ + "Rock", + "Psychic" + ] + }, + "339": { + "name": "Barboach", + "types": [ + "Water", + "Ground" + ] + }, + "340": { + "name": "Whiscash", + "types": [ + "Water", + "Ground" + ] + }, + "341": { + "name": "Corphish", + "types": [ + "Water" + ] + }, + "342": { + "name": "Crawdaunt", + "types": [ + "Water", + "Dark" + ] + }, + "343": { + "name": "Baltoy", + "types": [ + "Ground", + "Psychic" + ] + }, + "344": { + "name": "Claydol", + "types": [ + "Ground", + "Psychic" + ] + }, + "345": { + "name": "Lileep", + "types": [ + "Rock", + "Grass" + ] + }, + "346": { + "name": "Cradily", + "types": [ + "Rock", + "Grass" + ] + }, + "347": { + "name": "Anorith", + "types": [ + "Rock", + "Bug" + ] + }, + "348": { + "name": "Armaldo", + "types": [ + "Rock", + "Bug" + ] + }, + "349": { + "name": "Feebas", + "types": [ + "Water" + ] + }, + "350": { + "name": "Milotic", + "types": [ + "Water" + ] + }, + "351": { + "name": "Castform", + "types": [ + "Normal" + ] + }, + "352": { + "name": "Kecleon", + "types": [ + "Normal" + ] + }, + "353": { + "name": "Shuppet", + "types": [ + "Ghost" + ] + }, + "354": { + "name": "Banette", + "types": [ + "Ghost" + ] + }, + "355": { + "name": "Duskull", + "types": [ + "Ghost" + ] + }, + "356": { + "name": "Dusclops", + "types": [ + "Ghost" + ] + }, + "357": { + "name": "Tropius", + "types": [ + "Grass", + "Flying" + ] + }, + "358": { + "name": "Chimecho", + "types": [ + "Psychic" + ] + }, + "359": { + "name": "Absol", + "types": [ + "Dark" + ] + }, + "360": { + "name": "Wynaut", + "types": [ + "Psychic" + ] + }, + "361": { + "name": "Snorunt", + "types": [ + "Ice" + ] + }, + "362": { + "name": "Glalie", + "types": [ + "Ice" + ] + }, + "363": { + "name": "Spheal", + "types": [ + "Ice", + "Water" + ] + }, + "364": { + "name": "Sealeo", + "types": [ + "Ice", + "Water" + ] + }, + "365": { + "name": "Walrein", + "types": [ + "Ice", + "Water" + ] + }, + "366": { + "name": "Clamperl", + "types": [ + "Water" + ] + }, + "367": { + "name": "Huntail", + "types": [ + "Water" + ] + }, + "368": { + "name": "Gorebyss", + "types": [ + "Water" + ] + }, + "369": { + "name": "Relicanth", + "types": [ + "Water", + "Rock" + ] + }, + "370": { + "name": "Luvdisc", + "types": [ + "Water" + ] + }, + "371": { + "name": "Bagon", + "types": [ + "Dragon" + ] + }, + "372": { + "name": "Shelgon", + "types": [ + "Dragon" + ] + }, + "373": { + "name": "Salamence", + "types": [ + "Dragon", + "Flying" + ] + }, + "374": { + "name": "Beldum", + "types": [ + "Steel", + "Psychic" + ] + }, + "375": { + "name": "Metang", + "types": [ + "Steel", + "Psychic" + ] + }, + "376": { + "name": "Metagross", + "types": [ + "Steel", + "Psychic" + ] + }, + "377": { + "name": "Regirock", + "types": [ + "Rock" + ] + }, + "378": { + "name": "Regice", + "types": [ + "Ice" + ] + }, + "379": { + "name": "Registeel", + "types": [ + "Steel" + ] + }, + "380": { + "name": "Latias", + "types": [ + "Dragon", + "Psychic" + ] + }, + "381": { + "name": "Latios", + "types": [ + "Dragon", + "Psychic" + ] + }, + "382": { + "name": "Kyogre", + "types": [ + "Water" + ] + }, + "383": { + "name": "Groudon", + "types": [ + "Ground" + ] + }, + "384": { + "name": "Rayquaza", + "types": [ + "Dragon", + "Flying" + ] + }, + "385": { + "name": "Jirachi", + "types": [ + "Steel", + "Psychic" + ] + }, + "386": { + "name": "Deoxys", + "types": [ + "Psychic" + ] + }, + "387": { + "name": "Turtwig", + "types": [ + "Grass" + ] + }, + "388": { + "name": "Grotle", + "types": [ + "Grass" + ] + }, + "389": { + "name": "Torterra", + "types": [ + "Grass", + "Ground" + ] + }, + "390": { + "name": "Chimchar", + "types": [ + "Fire" + ] + }, + "391": { + "name": "Monferno", + "types": [ + "Fire", + "Fighting" + ] + }, + "392": { + "name": "Infernape", + "types": [ + "Fire", + "Fighting" + ] + }, + "393": { + "name": "Piplup", + "types": [ + "Water" + ] + }, + "394": { + "name": "Prinplup", + "types": [ + "Water" + ] + }, + "395": { + "name": "Empoleon", + "types": [ + "Water", + "Steel" + ] + }, + "396": { + "name": "Starly", + "types": [ + "Normal", + "Flying" + ] + }, + "397": { + "name": "Staravia", + "types": [ + "Normal", + "Flying" + ] + }, + "398": { + "name": "Staraptor", + "types": [ + "Normal", + "Flying" + ] + }, + "399": { + "name": "Bidoof", + "types": [ + "Normal" + ] + }, + "400": { + "name": "Bibarel", + "types": [ + "Normal", + "Water" + ] + }, + "401": { + "name": "Kricketot", + "types": [ + "Bug" + ] + }, + "402": { + "name": "Kricketune", + "types": [ + "Bug" + ] + }, + "403": { + "name": "Shinx", + "types": [ + "Electric" + ] + }, + "404": { + "name": "Luxio", + "types": [ + "Electric" + ] + }, + "405": { + "name": "Luxray", + "types": [ + "Electric" + ] + }, + "406": { + "name": "Budew", + "types": [ + "Grass", + "Poison" + ] + }, + "407": { + "name": "Roserade", + "types": [ + "Grass", + "Poison" + ] + }, + "408": { + "name": "Cranidos", + "types": [ + "Rock" + ] + }, + "409": { + "name": "Rampardos", + "types": [ + "Rock" + ] + }, + "410": { + "name": "Shieldon", + "types": [ + "Rock", + "Steel" + ] + }, + "411": { + "name": "Bastiodon", + "types": [ + "Rock", + "Steel" + ] + }, + "412": { + "name": "Burmy", + "types": [ + "Bug" + ] + }, + "413": { + "name": "Wormadam", + "types": [ + "Bug", + "Grass" + ] + }, + "414": { + "name": "Mothim", + "types": [ + "Bug", + "Flying" + ] + }, + "415": { + "name": "Combee", + "types": [ + "Bug", + "Flying" + ] + }, + "416": { + "name": "Vespiquen", + "types": [ + "Bug", + "Flying" + ] + }, + "417": { + "name": "Pachirisu", + "types": [ + "Electric" + ] + }, + "418": { + "name": "Buizel", + "types": [ + "Water" + ] + }, + "419": { + "name": "Floatzel", + "types": [ + "Water" + ] + }, + "420": { + "name": "Cherubi", + "types": [ + "Grass" + ] + }, + "421": { + "name": "Cherrim", + "types": [ + "Grass" + ] + }, + "422": { + "name": "Shellos", + "types": [ + "Water" + ] + }, + "423": { + "name": "Gastrodon", + "types": [ + "Water", + "Ground" + ] + }, + "424": { + "name": "Ambipom", + "types": [ + "Normal" + ] + }, + "425": { + "name": "Drifloon", + "types": [ + "Ghost", + "Flying" + ] + }, + "426": { + "name": "Drifblim", + "types": [ + "Ghost", + "Flying" + ] + }, + "427": { + "name": "Buneary", + "types": [ + "Normal" + ] + }, + "428": { + "name": "Lopunny", + "types": [ + "Normal" + ] + }, + "429": { + "name": "Mismagius", + "types": [ + "Ghost" + ] + }, + "430": { + "name": "Honchkrow", + "types": [ + "Dark", + "Flying" + ] + }, + "431": { + "name": "Glameow", + "types": [ + "Normal" + ] + }, + "432": { + "name": "Purugly", + "types": [ + "Normal" + ] + }, + "433": { + "name": "Chingling", + "types": [ + "Psychic" + ] + }, + "434": { + "name": "Stunky", + "types": [ + "Poison", + "Dark" + ] + }, + "435": { + "name": "Skuntank", + "types": [ + "Poison", + "Dark" + ] + }, + "436": { + "name": "Bronzor", + "types": [ + "Steel", + "Psychic" + ] + }, + "437": { + "name": "Bronzong", + "types": [ + "Steel", + "Psychic" + ] + }, + "438": { + "name": "Bonsly", + "types": [ + "Rock" + ] + }, + "439": { + "name": "Mime Jr.", + "types": [ + "Psychic", + "Fairy" + ] + }, + "440": { + "name": "Happiny", + "types": [ + "Normal" + ] + }, + "441": { + "name": "Chatot", + "types": [ + "Normal", + "Flying" + ] + }, + "442": { + "name": "Spiritomb", + "types": [ + "Ghost", + "Dark" + ] + }, + "443": { + "name": "Gible", + "types": [ + "Dragon", + "Ground" + ] + }, + "444": { + "name": "Gabite", + "types": [ + "Dragon", + "Ground" + ] + }, + "445": { + "name": "Garchomp", + "types": [ + "Dragon", + "Ground" + ] + }, + "446": { + "name": "Munchlax", + "types": [ + "Normal" + ] + }, + "447": { + "name": "Riolu", + "types": [ + "Fighting" + ] + }, + "448": { + "name": "Lucario", + "types": [ + "Fighting", + "Steel" + ] + }, + "449": { + "name": "Hippopotas", + "types": [ + "Ground" + ] + }, + "450": { + "name": "Hippowdon", + "types": [ + "Ground" + ] + }, + "451": { + "name": "Skorupi", + "types": [ + "Poison", + "Bug" + ] + }, + "452": { + "name": "Drapion", + "types": [ + "Poison", + "Dark" + ] + }, + "453": { + "name": "Croagunk", + "types": [ + "Poison", + "Fighting" + ] + }, + "454": { + "name": "Toxicroak", + "types": [ + "Poison", + "Fighting" + ] + }, + "455": { + "name": "Carnivine", + "types": [ + "Grass" + ] + }, + "456": { + "name": "Finneon", + "types": [ + "Water" + ] + }, + "457": { + "name": "Lumineon", + "types": [ + "Water" + ] + }, + "458": { + "name": "Mantyke", + "types": [ + "Water", + "Flying" + ] + }, + "459": { + "name": "Snover", + "types": [ + "Grass", + "Ice" + ] + }, + "460": { + "name": "Abomasnow", + "types": [ + "Grass", + "Ice" + ] + }, + "461": { + "name": "Weavile", + "types": [ + "Dark", + "Ice" + ] + }, + "462": { + "name": "Magnezone", + "types": [ + "Electric", + "Steel" + ] + }, + "463": { + "name": "Lickilicky", + "types": [ + "Normal" + ] + }, + "464": { + "name": "Rhyperior", + "types": [ + "Ground", + "Rock" + ] + }, + "465": { + "name": "Tangrowth", + "types": [ + "Grass" + ] + }, + "466": { + "name": "Electivire", + "types": [ + "Electric" + ] + }, + "467": { + "name": "Magmortar", + "types": [ + "Fire" + ] + }, + "468": { + "name": "Togekiss", + "types": [ + "Fairy", + "Flying" + ] + }, + "469": { + "name": "Yanmega", + "types": [ + "Bug", + "Flying" + ] + }, + "470": { + "name": "Leafeon", + "types": [ + "Grass" + ] + }, + "471": { + "name": "Glaceon", + "types": [ + "Ice" + ] + }, + "472": { + "name": "Gliscor", + "types": [ + "Ground", + "Flying" + ] + }, + "473": { + "name": "Mamoswine", + "types": [ + "Ice", + "Ground" + ] + }, + "474": { + "name": "Porygon-Z", + "types": [ + "Normal" + ] + }, + "475": { + "name": "Gallade", + "types": [ + "Psychic", + "Fighting" + ] + }, + "476": { + "name": "Probopass", + "types": [ + "Rock", + "Steel" + ] + }, + "477": { + "name": "Dusknoir", + "types": [ + "Ghost" + ] + }, + "478": { + "name": "Froslass", + "types": [ + "Ice", + "Ghost" + ] + }, + "479": { + "name": "Rotom", + "types": [ + "Electric", + "Ghost" + ] + }, + "480": { + "name": "Uxie", + "types": [ + "Psychic" + ] + }, + "481": { + "name": "Mesprit", + "types": [ + "Psychic" + ] + }, + "482": { + "name": "Azelf", + "types": [ + "Psychic" + ] + }, + "483": { + "name": "Dialga", + "types": [ + "Steel", + "Dragon" + ] + }, + "484": { + "name": "Palkia", + "types": [ + "Water", + "Dragon" + ] + }, + "485": { + "name": "Heatran", + "types": [ + "Fire", + "Steel" + ] + }, + "486": { + "name": "Regigigas", + "types": [ + "Normal" + ] + }, + "487": { + "name": "Giratina", + "types": [ + "Ghost", + "Dragon" + ] + }, + "488": { + "name": "Cresselia", + "types": [ + "Psychic" + ] + }, + "489": { + "name": "Phione", + "types": [ + "Water" + ] + }, + "490": { + "name": "Manaphy", + "types": [ + "Water" + ] + }, + "491": { + "name": "Darkrai", + "types": [ + "Dark" + ] + }, + "492": { + "name": "Shaymin", + "types": [ + "Grass" + ] + }, + "493": { + "name": "Arceus", + "types": [ + "Normal" + ] + }, + "494": { + "name": "Victini", + "types": [ + "Psychic", + "Fire" + ] + }, + "495": { + "name": "Snivy", + "types": [ + "Grass" + ] + }, + "496": { + "name": "Servine", + "types": [ + "Grass" + ] + }, + "497": { + "name": "Serperior", + "types": [ + "Grass" + ] + }, + "498": { + "name": "Tepig", + "types": [ + "Fire" + ] + }, + "499": { + "name": "Pignite", + "types": [ + "Fire", + "Fighting" + ] + }, + "500": { + "name": "Emboar", + "types": [ + "Fire", + "Fighting" + ] + }, + "501": { + "name": "Oshawott", + "types": [ + "Water" + ] + }, + "502": { + "name": "Dewott", + "types": [ + "Water" + ] + }, + "503": { + "name": "Samurott", + "types": [ + "Water" + ] + }, + "504": { + "name": "Patrat", + "types": [ + "Normal" + ] + }, + "505": { + "name": "Watchog", + "types": [ + "Normal" + ] + }, + "506": { + "name": "Lillipup", + "types": [ + "Normal" + ] + }, + "507": { + "name": "Herdier", + "types": [ + "Normal" + ] + }, + "508": { + "name": "Stoutland", + "types": [ + "Normal" + ] + }, + "509": { + "name": "Purrloin", + "types": [ + "Dark" + ] + }, + "510": { + "name": "Liepard", + "types": [ + "Dark" + ] + }, + "511": { + "name": "Pansage", + "types": [ + "Grass" + ] + }, + "512": { + "name": "Simisage", + "types": [ + "Grass" + ] + }, + "513": { + "name": "Pansear", + "types": [ + "Fire" + ] + }, + "514": { + "name": "Simisear", + "types": [ + "Fire" + ] + }, + "515": { + "name": "Panpour", + "types": [ + "Water" + ] + }, + "516": { + "name": "Simipour", + "types": [ + "Water" + ] + }, + "517": { + "name": "Munna", + "types": [ + "Psychic" + ] + }, + "518": { + "name": "Musharna", + "types": [ + "Psychic" + ] + }, + "519": { + "name": "Pidove", + "types": [ + "Normal", + "Flying" + ] + }, + "520": { + "name": "Tranquill", + "types": [ + "Normal", + "Flying" + ] + }, + "521": { + "name": "Unfezant", + "types": [ + "Normal", + "Flying" + ] + }, + "522": { + "name": "Blitzle", + "types": [ + "Electric" + ] + }, + "523": { + "name": "Zebstrika", + "types": [ + "Electric" + ] + }, + "524": { + "name": "Roggenrola", + "types": [ + "Rock" + ] + }, + "525": { + "name": "Boldore", + "types": [ + "Rock" + ] + }, + "526": { + "name": "Gigalith", + "types": [ + "Rock" + ] + }, + "527": { + "name": "Woobat", + "types": [ + "Psychic", + "Flying" + ] + }, + "528": { + "name": "Swoobat", + "types": [ + "Psychic", + "Flying" + ] + }, + "529": { + "name": "Drilbur", + "types": [ + "Ground" + ] + }, + "530": { + "name": "Excadrill", + "types": [ + "Ground", + "Steel" + ] + }, + "531": { + "name": "Audino", + "types": [ + "Normal" + ] + }, + "532": { + "name": "Timburr", + "types": [ + "Fighting" + ] + }, + "533": { + "name": "Gurdurr", + "types": [ + "Fighting" + ] + }, + "534": { + "name": "Conkeldurr", + "types": [ + "Fighting" + ] + }, + "535": { + "name": "Tympole", + "types": [ + "Water" + ] + }, + "536": { + "name": "Palpitoad", + "types": [ + "Water", + "Ground" + ] + }, + "537": { + "name": "Seismitoad", + "types": [ + "Water", + "Ground" + ] + }, + "538": { + "name": "Throh", + "types": [ + "Fighting" + ] + }, + "539": { + "name": "Sawk", + "types": [ + "Fighting" + ] + }, + "540": { + "name": "Sewaddle", + "types": [ + "Bug", + "Grass" + ] + }, + "541": { + "name": "Swadloon", + "types": [ + "Bug", + "Grass" + ] + }, + "542": { + "name": "Leavanny", + "types": [ + "Bug", + "Grass" + ] + }, + "543": { + "name": "Venipede", + "types": [ + "Bug", + "Poison" + ] + }, + "544": { + "name": "Whirlipede", + "types": [ + "Bug", + "Poison" + ] + }, + "545": { + "name": "Scolipede", + "types": [ + "Bug", + "Poison" + ] + }, + "546": { + "name": "Cottonee", + "types": [ + "Grass", + "Fairy" + ] + }, + "547": { + "name": "Whimsicott", + "types": [ + "Grass", + "Fairy" + ] + }, + "548": { + "name": "Petilil", + "types": [ + "Grass" + ] + }, + "549": { + "name": "Lilligant", + "types": [ + "Grass" + ] + }, + "550": { + "name": "Basculin", + "types": [ + "Water" + ] + }, + "551": { + "name": "Sandile", + "types": [ + "Ground", + "Dark" + ] + }, + "552": { + "name": "Krokorok", + "types": [ + "Ground", + "Dark" + ] + }, + "553": { + "name": "Krookodile", + "types": [ + "Ground", + "Dark" + ] + }, + "554": { + "name": "Darumaka", + "types": [ + "Fire" + ] + }, + "555": { + "name": "Darmanitan", + "types": [ + "Fire" + ] + }, + "556": { + "name": "Maractus", + "types": [ + "Grass" + ] + }, + "557": { + "name": "Dwebble", + "types": [ + "Bug", + "Rock" + ] + }, + "558": { + "name": "Crustle", + "types": [ + "Bug", + "Rock" + ] + }, + "559": { + "name": "Scraggy", + "types": [ + "Dark", + "Fighting" + ] + }, + "560": { + "name": "Scrafty", + "types": [ + "Dark", + "Fighting" + ] + }, + "561": { + "name": "Sigilyph", + "types": [ + "Psychic", + "Flying" + ] + }, + "562": { + "name": "Yamask", + "types": [ + "Ghost" + ] + }, + "563": { + "name": "Cofagrigus", + "types": [ + "Ghost" + ] + }, + "564": { + "name": "Tirtouga", + "types": [ + "Water", + "Rock" + ] + }, + "565": { + "name": "Carracosta", + "types": [ + "Water", + "Rock" + ] + }, + "566": { + "name": "Archen", + "types": [ + "Rock", + "Flying" + ] + }, + "567": { + "name": "Archeops", + "types": [ + "Rock", + "Flying" + ] + }, + "568": { + "name": "Trubbish", + "types": [ + "Poison" + ] + }, + "569": { + "name": "Garbodor", + "types": [ + "Poison" + ] + }, + "570": { + "name": "Zorua", + "types": [ + "Dark" + ] + }, + "571": { + "name": "Zoroark", + "types": [ + "Dark" + ] + }, + "572": { + "name": "Minccino", + "types": [ + "Normal" + ] + }, + "573": { + "name": "Cinccino", + "types": [ + "Normal" + ] + }, + "574": { + "name": "Gothita", + "types": [ + "Psychic" + ] + }, + "575": { + "name": "Gothorita", + "types": [ + "Psychic" + ] + }, + "576": { + "name": "Gothitelle", + "types": [ + "Psychic" + ] + }, + "577": { + "name": "Solosis", + "types": [ + "Psychic" + ] + }, + "578": { + "name": "Duosion", + "types": [ + "Psychic" + ] + }, + "579": { + "name": "Reuniclus", + "types": [ + "Psychic" + ] + }, + "580": { + "name": "Ducklett", + "types": [ + "Water", + "Flying" + ] + }, + "581": { + "name": "Swanna", + "types": [ + "Water", + "Flying" + ] + }, + "582": { + "name": "Vanillite", + "types": [ + "Ice" + ] + }, + "583": { + "name": "Vanillish", + "types": [ + "Ice" + ] + }, + "584": { + "name": "Vanilluxe", + "types": [ + "Ice" + ] + }, + "585": { + "name": "Deerling", + "types": [ + "Normal", + "Grass" + ] + }, + "586": { + "name": "Sawsbuck", + "types": [ + "Normal", + "Grass" + ] + }, + "587": { + "name": "Emolga", + "types": [ + "Electric", + "Flying" + ] + }, + "588": { + "name": "Karrablast", + "types": [ + "Bug" + ] + }, + "589": { + "name": "Escavalier", + "types": [ + "Bug", + "Steel" + ] + }, + "590": { + "name": "Foongus", + "types": [ + "Grass", + "Poison" + ] + }, + "591": { + "name": "Amoonguss", + "types": [ + "Grass", + "Poison" + ] + }, + "592": { + "name": "Frillish", + "types": [ + "Water", + "Ghost" + ] + }, + "593": { + "name": "Jellicent", + "types": [ + "Water", + "Ghost" + ] + }, + "594": { + "name": "Alomomola", + "types": [ + "Water" + ] + }, + "595": { + "name": "Joltik", + "types": [ + "Bug", + "Electric" + ] + }, + "596": { + "name": "Galvantula", + "types": [ + "Bug", + "Electric" + ] + }, + "597": { + "name": "Ferroseed", + "types": [ + "Grass", + "Steel" + ] + }, + "598": { + "name": "Ferrothorn", + "types": [ + "Grass", + "Steel" + ] + }, + "599": { + "name": "Klink", + "types": [ + "Steel" + ] + }, + "600": { + "name": "Klang", + "types": [ + "Steel" + ] + }, + "601": { + "name": "Klinklang", + "types": [ + "Steel" + ] + }, + "602": { + "name": "Tynamo", + "types": [ + "Electric" + ] + }, + "603": { + "name": "Eelektrik", + "types": [ + "Electric" + ] + }, + "604": { + "name": "Eelektross", + "types": [ + "Electric" + ] + }, + "605": { + "name": "Elgyem", + "types": [ + "Psychic" + ] + }, + "606": { + "name": "Beheeyem", + "types": [ + "Psychic" + ] + }, + "607": { + "name": "Litwick", + "types": [ + "Ghost", + "Fire" + ] + }, + "608": { + "name": "Lampent", + "types": [ + "Ghost", + "Fire" + ] + }, + "609": { + "name": "Chandelure", + "types": [ + "Ghost", + "Fire" + ] + }, + "610": { + "name": "Axew", + "types": [ + "Dragon" + ] + }, + "611": { + "name": "Fraxure", + "types": [ + "Dragon" + ] + }, + "612": { + "name": "Haxorus", + "types": [ + "Dragon" + ] + }, + "613": { + "name": "Cubchoo", + "types": [ + "Ice" + ] + }, + "614": { + "name": "Beartic", + "types": [ + "Ice" + ] + }, + "615": { + "name": "Cryogonal", + "types": [ + "Ice" + ] + }, + "616": { + "name": "Shelmet", + "types": [ + "Bug" + ] + }, + "617": { + "name": "Accelgor", + "types": [ + "Bug" + ] + }, + "618": { + "name": "Stunfisk", + "types": [ + "Ground", + "Electric" + ] + }, + "619": { + "name": "Mienfoo", + "types": [ + "Fighting" + ] + }, + "620": { + "name": "Mienshao", + "types": [ + "Fighting" + ] + }, + "621": { + "name": "Druddigon", + "types": [ + "Dragon" + ] + }, + "622": { + "name": "Golett", + "types": [ + "Ground", + "Ghost" + ] + }, + "623": { + "name": "Golurk", + "types": [ + "Ground", + "Ghost" + ] + }, + "624": { + "name": "Pawniard", + "types": [ + "Dark", + "Steel" + ] + }, + "625": { + "name": "Bisharp", + "types": [ + "Dark", + "Steel" + ] + }, + "626": { + "name": "Bouffalant", + "types": [ + "Normal" + ] + }, + "627": { + "name": "Rufflet", + "types": [ + "Normal", + "Flying" + ] + }, + "628": { + "name": "Braviary", + "types": [ + "Normal", + "Flying" + ] + }, + "629": { + "name": "Vullaby", + "types": [ + "Dark", + "Flying" + ] + }, + "630": { + "name": "Mandibuzz", + "types": [ + "Dark", + "Flying" + ] + }, + "631": { + "name": "Heatmor", + "types": [ + "Fire" + ] + }, + "632": { + "name": "Durant", + "types": [ + "Bug", + "Steel" + ] + }, + "633": { + "name": "Deino", + "types": [ + "Dark", + "Dragon" + ] + }, + "634": { + "name": "Zweilous", + "types": [ + "Dark", + "Dragon" + ] + }, + "635": { + "name": "Hydreigon", + "types": [ + "Dark", + "Dragon" + ] + }, + "636": { + "name": "Larvesta", + "types": [ + "Bug", + "Fire" + ] + }, + "637": { + "name": "Volcarona", + "types": [ + "Bug", + "Fire" + ] + }, + "638": { + "name": "Cobalion", + "types": [ + "Steel", + "Fighting" + ] + }, + "639": { + "name": "Terrakion", + "types": [ + "Rock", + "Fighting" + ] + }, + "640": { + "name": "Virizion", + "types": [ + "Grass", + "Fighting" + ] + }, + "641": { + "name": "Tornadus", + "types": [ + "Flying" + ] + }, + "642": { + "name": "Thundurus", + "types": [ + "Electric", + "Flying" + ] + }, + "643": { + "name": "Reshiram", + "types": [ + "Dragon", + "Fire" + ] + }, + "644": { + "name": "Zekrom", + "types": [ + "Dragon", + "Electric" + ] + }, + "645": { + "name": "Landorus", + "types": [ + "Ground", + "Flying" + ] + }, + "646": { + "name": "Kyurem", + "types": [ + "Dragon", + "Ice" + ] + }, + "647": { + "name": "Keldeo", + "types": [ + "Water", + "Fighting" + ] + }, + "648": { + "name": "Meloetta", + "types": [ + "Normal", + "Psychic" + ] + }, + "649": { + "name": "Genesect", + "types": [ + "Bug", + "Steel" + ] + }, + "650": { + "name": "Chespin", + "types": [ + "Grass" + ] + }, + "651": { + "name": "Quilladin", + "types": [ + "Grass" + ] + }, + "652": { + "name": "Chesnaught", + "types": [ + "Grass", + "Fighting" + ] + }, + "653": { + "name": "Fennekin", + "types": [ + "Fire" + ] + }, + "654": { + "name": "Braixen", + "types": [ + "Fire" + ] + }, + "655": { + "name": "Delphox", + "types": [ + "Fire", + "Psychic" + ] + }, + "656": { + "name": "Froakie", + "types": [ + "Water" + ] + }, + "657": { + "name": "Frogadier", + "types": [ + "Water" + ] + }, + "658": { + "name": "Greninja", + "types": [ + "Water", + "Dark" + ] + }, + "659": { + "name": "Bunnelby", + "types": [ + "Normal" + ] + }, + "660": { + "name": "Diggersby", + "types": [ + "Normal", + "Ground" + ] + }, + "661": { + "name": "Fletchling", + "types": [ + "Normal", + "Flying" + ] + }, + "662": { + "name": "Fletchinder", + "types": [ + "Fire", + "Flying" + ] + }, + "663": { + "name": "Talonflame", + "types": [ + "Fire", + "Flying" + ] + }, + "664": { + "name": "Scatterbug", + "types": [ + "Bug" + ] + }, + "665": { + "name": "Spewpa", + "types": [ + "Bug" + ] + }, + "666": { + "name": "Vivillon", + "types": [ + "Bug", + "Flying" + ] + }, + "667": { + "name": "Litleo", + "types": [ + "Fire", + "Normal" + ] + }, + "668": { + "name": "Pyroar", + "types": [ + "Fire", + "Normal" + ] + }, + "669": { + "name": "Flabébé", + "types": [ + "Fairy" + ] + }, + "670": { + "name": "Floette", + "types": [ + "Fairy" + ] + }, + "671": { + "name": "Florges", + "types": [ + "Fairy" + ] + }, + "672": { + "name": "Skiddo", + "types": [ + "Grass" + ] + }, + "673": { + "name": "Gogoat", + "types": [ + "Grass" + ] + }, + "674": { + "name": "Pancham", + "types": [ + "Fighting" + ] + }, + "675": { + "name": "Pangoro", + "types": [ + "Fighting", + "Dark" + ] + }, + "676": { + "name": "Furfrou", + "types": [ + "Normal" + ] + }, + "677": { + "name": "Espurr", + "types": [ + "Psychic" + ] + }, + "678": { + "name": "Meowstic", + "types": [ + "Psychic" + ] + }, + "679": { + "name": "Honedge", + "types": [ + "Steel", + "Ghost" + ] + }, + "680": { + "name": "Doublade", + "types": [ + "Steel", + "Ghost" + ] + }, + "681": { + "name": "Aegislash", + "types": [ + "Steel", + "Ghost" + ] + }, + "682": { + "name": "Spritzee", + "types": [ + "Fairy" + ] + }, + "683": { + "name": "Aromatisse", + "types": [ + "Fairy" + ] + }, + "684": { + "name": "Swirlix", + "types": [ + "Fairy" + ] + }, + "685": { + "name": "Slurpuff", + "types": [ + "Fairy" + ] + }, + "686": { + "name": "Inkay", + "types": [ + "Dark", + "Psychic" + ] + }, + "687": { + "name": "Malamar", + "types": [ + "Dark", + "Psychic" + ] + }, + "688": { + "name": "Binacle", + "types": [ + "Rock", + "Water" + ] + }, + "689": { + "name": "Barbaracle", + "types": [ + "Rock", + "Water" + ] + }, + "690": { + "name": "Skrelp", + "types": [ + "Poison", + "Water" + ] + }, + "691": { + "name": "Dragalge", + "types": [ + "Poison", + "Dragon" + ] + }, + "692": { + "name": "Clauncher", + "types": [ + "Water" + ] + }, + "693": { + "name": "Clawitzer", + "types": [ + "Water" + ] + }, + "694": { + "name": "Helioptile", + "types": [ + "Electric", + "Normal" + ] + }, + "695": { + "name": "Heliolisk", + "types": [ + "Electric", + "Normal" + ] + }, + "696": { + "name": "Tyrunt", + "types": [ + "Rock", + "Dragon" + ] + }, + "697": { + "name": "Tyrantrum", + "types": [ + "Rock", + "Dragon" + ] + }, + "698": { + "name": "Amaura", + "types": [ + "Rock", + "Ice" + ] + }, + "699": { + "name": "Aurorus", + "types": [ + "Rock", + "Ice" + ] + }, + "700": { + "name": "Sylveon", + "types": [ + "Fairy" + ] + }, + "701": { + "name": "Hawlucha", + "types": [ + "Fighting", + "Flying" + ] + }, + "702": { + "name": "Dedenne", + "types": [ + "Electric", + "Fairy" + ] + }, + "703": { + "name": "Carbink", + "types": [ + "Rock", + "Fairy" + ] + }, + "704": { + "name": "Goomy", + "types": [ + "Dragon" + ] + }, + "705": { + "name": "Sliggoo", + "types": [ + "Dragon" + ] + }, + "706": { + "name": "Goodra", + "types": [ + "Dragon" + ] + }, + "707": { + "name": "Klefki", + "types": [ + "Steel", + "Fairy" + ] + }, + "708": { + "name": "Phantump", + "types": [ + "Ghost", + "Grass" + ] + }, + "709": { + "name": "Trevenant", + "types": [ + "Ghost", + "Grass" + ] + }, + "710": { + "name": "Pumpkaboo", + "types": [ + "Ghost", + "Grass" + ] + }, + "711": { + "name": "Gourgeist", + "types": [ + "Ghost", + "Grass" + ] + }, + "712": { + "name": "Bergmite", + "types": [ + "Ice" + ] + }, + "713": { + "name": "Avalugg", + "types": [ + "Ice" + ] + }, + "714": { + "name": "Noibat", + "types": [ + "Flying", + "Dragon" + ] + }, + "715": { + "name": "Noivern", + "types": [ + "Flying", + "Dragon" + ] + }, + "716": { + "name": "Xerneas", + "types": [ + "Fairy" + ] + }, + "717": { + "name": "Yveltal", + "types": [ + "Dark", + "Flying" + ] + }, + "718": { + "name": "Zygarde", + "types": [ + "Dragon", + "Ground" + ] + }, + "719": { + "name": "Diancie", + "types": [ + "Rock", + "Fairy" + ] + }, + "720": { + "name": "Hoopa", + "types": [ + "Psychic", + "Ghost" + ] + }, + "721": { + "name": "Volcanion", + "types": [ + "Fire", + "Water" + ] + } +} \ No newline at end of file diff --git a/formatting.ini b/formatting.ini index b02ee3a..8672a89 100644 --- a/formatting.ini +++ b/formatting.ini @@ -1,5 +1,6 @@ [pokemon] -title = <> []
+encounteredTitle = [] +title = [] titleUrl = encounteredBody = **Available until: <24h_time> ()**\n\nLvl30+ IVs: A/D/S (%)\nLvl30+ CP: (lvl )\nLvl30+ Moveset: - \nGender: , Height: , Weight: body = **Available until: <24h_time> ()**\n\n diff --git a/pokechannels.ini b/pokechannels.ini index 83a80f0..310dd26 100644 --- a/pokechannels.ini +++ b/pokechannels.ini @@ -1,6 +1,7 @@ [271827572386562050] geofences = belconnen-region filter = pokefilter.json +formatting = magikarp.ini [271802067893354497] geofences = gungahlin-region @@ -26,6 +27,46 @@ filter = pokefilter.json geofences = queanbeyan filter = pokefilter.json +[276669937446158337] +geofences = belconnen-region +filter = pokefilter.json + +[276668496232841216] +geofences = gungahlin-region +filter = pokefilter.json + +[276670191956393984] +geofences = inner-north +filter = pokefilter.json + +[276670290484789248] +geofences = inner-south +filter = pokefilter.json + +[276670490335248385] +geofences = tuggeranong +filter = pokefilter.json + +[276670370134884353] +geofences = [woden,weston-region] +filter = pokefilter.json + +[285439771319336960] +geofences = queanbeyan +filter = pokefilter.json + +[291781601447247872] +geofences = all +filter = ultrarare.json + [291781579976736768] geofences = all -filter = ultrarare.json \ No newline at end of file +filter = ultrarare.json + +[287376223418580992] +geofences = all +filter = 100iv.json + +[299903745775370240] +geofences = all +filter = unown.json diff --git a/pokefilter.json b/pokefilter.json index 4873a29..7fcc3c1 100644 --- a/pokefilter.json +++ b/pokefilter.json @@ -1,433 +1,431 @@ { - "pokemon": { - "Bulbasaur": "False", - "Ivysaur": "False", - "Venusaur": { - "min_iv": "90" - }, - "Charmander": "False", - "Charmeleon": "False", - "Charizard": { - "min_iv": "90" - }, - "Squirtle": "False", - "Wartortle": "False", - "Blastoise": { - "min_iv": "90" - }, - "Caterpie": "False", - "Metapod": "False", - "Butterfree": "False", - "Weedle": "False", - "Kakuna": "False", - "Beedrill": "False", - "Pidgey": "False", - "Pidgeotto": "False", - "Pidgeot": "False", - "Rattata": "False", - "Spearow": "False", - "Fearow": "False", - "Ekans": "False", - "Arbok": "False", - "Pikachu": "False", - "Raichu": "False", - "Sandshrew": "False", - "Sandslash": "False", - "Nidoran♀": "False", - "Nidorina": "False", - "Nidoqueen": "False", - "Nidoran♂": "False", - "Nidorino": "False", - "Nidoking": "False", - "Clefairy": "False", - "Clefable": "False", - "Vulpix": "False", - "Ninetales": "False", - "Jigglypuff": "False", - "Wigglytuff": "False", - "Zubat": "False", - "Golbat": "False", - "Oddish": "False", - "Gloom": "False", - "Vileplume": "False", - "Paras": "False", - "Parasect": "False", - "Venonat": "False", - "Venomoth": "False", - "Diglett": "False", - "Dugtrio": "False", - "Meowth": "False", - "Persian": "False", - "Psyduck": "False", - "Golduck": "False", - "Mankey": "False", - "Primeape": "False", - "Growlithe": "False", - "Arcanine": { - "min_iv": "90" - }, - "Poliwag": "False", - "Poliwhirl": "False", - "Poliwrath": "False", - "Abra": "False", - "Kadabra": "False", - "Alakazam": "True", - "Machop": "False", - "Machoke": "False", - "Machamp": "True", - "Bellsprout": "False", - "Weepinbell": "False", - "Victreebel": "False", - "Tentacool": "False", - "Tentacruel": "False", - "Geodude": { - "min_iv": "90" - }, - "Graveler": { - "min_iv": "90" - }, - "Golem": "True", - "Ponyta": "False", - "Rapidash": "False", - "Slowpoke": "False", - "Slowbro": "False", - "Magnemite": "False", - "Magneton": "False", - "Farfetch'd": "True", - "Doduo": "False", - "Dodrio": "False", - "Seel": "False", - "Dewgong": "False", - "Grimer": "False", - "Muk": "False", - "Shellder": "False", - "Cloyster": "False", - "Gastly": "False", - "Haunter": "False", - "Gengar": "False", - "Onix": "False", - "Drowzee": "False", - "Hypno": "False", - "Krabby": "False", - "Kingler": "False", - "Voltorb": "False", - "Electrode": "False", - "Exeggcute": "False", - "Exeggutor": { - "min_iv": "90" - }, - "Cubone": "False", - "Marowak": "False", - "Hitmonlee": "False", - "Hitmonchan": "False", - "Lickitung": "False", - "Koffing": "False", - "Weezing": "False", - "Rhyhorn": "False", - "Rhydon": { - "min_iv": "90" - }, - "Chansey": "True", - "Tangela": "False", - "Kangaskhan": "False", - "Horsea": "False", - "Seadra": "False", - "Goldeen": "False", - "Seaking": "False", - "Staryu": "False", - "Starmie": "False", - "Mr. Mime": "True", - "Scyther": { - "min_iv": "82" - }, - "Jynx": "False", - "Electabuzz": "False", - "Magmar": "False", - "Pinsir": "False", - "Tauros": "True", - "Magikarp": { - "min_iv": "95" - }, - "Gyarados": "True", - "Lapras": "True", - "Ditto": "False", - "Eevee": { - "min_iv": "95" - }, - "Vaporeon": { - "min_iv": "90" - }, - "Jolteon": { - "min_iv": "90" - }, - "Flareon": { - "min_iv": "90" - }, - "Porygon": "False", - "Omanyte": "False", - "Omastar": "False", - "Kabuto": "False", - "Kabutops": "False", - "Aerodactyl": "False", - "Snorlax": "True", - "Articuno": "True", - "Zapdos": "True", - "Moltres": "True", - "Dratini": { - "min_iv": "90" - }, - "Dragonair": { - "min_iv": "90" - }, - "Dragonite": "True", - "Mewtwo": "True", - "Mew": "True", - "Chikorita": "False", - "Bayleef": "False", - "Meganium": { - "min_iv": "60" - }, - "Cyndaquil": "False", - "Quilava": "False", - "Typhlosion": "True", - "Totodile": "False", - "Croconaw": "False", - "Feraligatr": { - "min_iv": "60" - }, - "Sentret": "False", - "Furret": "False", - "Hoothoot": "False", - "Noctowl": "False", - "Ledyba": "False", - "Ledian": "False", - "Spinarak": "False", - "Ariados": "False", - "Crobat": "False", - "Chinchou": "False", - "Lanturn": "False", - "Pichu": "False", - "Cleffa": "False", - "Igglybuff": "False", - "Togepi": "False", - "Togetic": "False", - "Natu": "False", - "Xatu": "False", - "Mareep": "True", - "Flaaffy": "True", - "Ampharos": "True", - "Bellossom": "True", - "Marill": "False", - "Azumarill": "False", - "Sudowoodo": "False", - "Politoed": "True", - "Hoppip": "False", - "Skiploom": "False", - "Jumpluff": "False", - "Aipom": "False", - "Sunkern": "False", - "Sunflora": "True", - "Yanma": "False", - "Wooper": "False", - "Quagsire": "False", - "Espeon": "True", - "Umbreon": "True", - "Murkrow": "False", - "Slowking": "True", - "Misdreavus": "False", - "Unown": "True", - "Wobbuffet": "False", - "Girafarig": "False", - "Pineco": "False", - "Forretress": "False", - "Dunsparce": "False", - "Gligar": "False", - "Steelix": "True", - "Snubbull": "False", - "Granbull": "False", - "Qwilfish": "False", - "Scizor": "True", - "Shuckle": "False", - "Heracross": "True", - "Sneasel": "False", - "Teddiursa": "False", - "Ursaring": "False", - "Slugma": "False", - "Magcargo": "False", - "Swinub": "False", - "Piloswine": "True", - "Corsola": "False", - "Remoraid": "False", - "Octillery": "False", - "Delibird": "True", - "Mantine": "False", - "Skarmory": "False", - "Houndour": "False", - "Houndoom": { - "min_iv": "82" - }, - "Kingdra": "True", - "Phanpy": "False", - "Donphan": { - "min_iv": "82" - }, - "Porygon2": "True", - "Stantler": "False", - "Smeargle": "True", - "Tyrogue": "True", - "Hitmontop": "True", - "Smoochum": "False", - "Elekid": "False", - "Magby": "False", - "Miltank": "True", - "Blissey": "True", - "Raikou": "True", - "Entei": "True", - "Suicune": "True", - "Larvitar": { - "min_iv": "90" - }, - "Pupitar": { - "min_iv": "90" - }, - "Tyranitar": "True", - "Lugia": "True", - "Ho-Oh": "True", - "Celebi": "True", - "Treecko": "False", - "Grovyle": "False", - "Sceptile": "False", - "Torchic": "False", - "Combusken": "False", - "Blaziken": "False", - "Mudkip": "False", - "Marshtomp": "False", - "Swampert": "False", - "Poochyena": "False", - "Mightyena": "False", - "Zigzagoon": "False", - "Linoone": "False", - "Wurmple": "False", - "Silcoon": "False", - "Beautifly": "False", - "Cascoon": "False", - "Dustox": "False", - "Lotad": "False", - "Lombre": "False", - "Ludicolo": "False", - "Seedot": "False", - "Nuzleaf": "False", - "Shiftry": "False", - "Taillow": "False", - "Swellow": "False", - "Wingull": "False", - "Pelipper": "False", - "Ralts": "False", - "Kirlia": "False", - "Gardevoir": "False", - "Surskit": "False", - "Masquerain": "False", - "Shroomish": "False", - "Breloom": "False", - "Slakoth": "False", - "Vigoroth": "False", - "Slaking": "False", - "Nincada": "False", - "Ninjask": "False", - "Shedinja": "False", - "Whismur": "False", - "Loudred": "False", - "Exploud": "False", - "Makuhita": "False", - "Hariyama": "False", - "Azurill": "False", - "Nosepass": "False", - "Skitty": "False", - "Delcatty": "False", - "Sableye": "False", - "Mawile": "False", - "Aron": "False", - "Lairon": "False", - "Aggron": "False", - "Meditite": "False", - "Medicham": "False", - "Electrike": "False", - "Manectric": "False", - "Plusle": "False", - "Minun": "False", - "Volbeat": "False", - "Illumise": "False", - "Roselia": "False", - "Gulpin": "False", - "Swalot": "False", - "Carvanha": "False", - "Sharpedo": "False", - "Wailmer": "False", - "Wailord": "False", - "Numel": "False", - "Camerupt": "False", - "Torkoal": "False", - "Spoink": "False", - "Grumpig": "False", - "Spinda": "False", - "Trapinch": "False", - "Vibrava": "False", - "Flygon": "False", - "Cacnea": "False", - "Cacturne": "False", - "Swablu": "False", - "Altaria": "False", - "Zangoose": "False", - "Seviper": "False", - "Lunatone": "False", - "Solrock": "False", - "Barboach": "False", - "Whiscash": "False", - "Corphish": "False", - "Crawdaunt": "False", - "Baltoy": "False", - "Claydol": "False", - "Lileep": "False", - "Cradily": "False", - "Anorith": "False", - "Armaldo": "False", - "Feebas": "False", - "Milotic": "False", - "Castform": "False", - "Kecleon": "False", - "Shuppet": "False", - "Banette": "False", - "Duskull": "False", - "Dusclops": "False", - "Tropius": "False", - "Chimecho": "False", - "Absol": "False", - "Wynaut": "False", - "Snorunt": "False", - "Glalie": "False", - "Spheal": "False", - "Sealeo": "False", - "Walrein": "False", - "Clamperl": "False", - "Huntail": "False", - "Gorebyss": "False", - "Relicanth": "False", - "Luvdisc": "False", - "Bagon": "False", - "Shelgon": "False", - "Salamence": "False", - "Beldum": "False", - "Metang": "False", - "Metagross": "False", - "Regirock": "False", - "Regice": "False", - "Registeel": "False", - "Latias": "False", - "Latios": "False", - "Kyogre": "False", - "Groudon": "False", - "Rayquaza": "False", - "Jirachi": "False", - "Deoxys": "False" - } + "Bulbasaur": "False", + "Ivysaur": "False", + "Venusaur": { + "min_iv": "90" + }, + "Charmander": "False", + "Charmeleon": "False", + "Charizard": { + "min_iv": "90" + }, + "Squirtle": "False", + "Wartortle": "False", + "Blastoise": { + "min_iv": "90" + }, + "Caterpie": "False", + "Metapod": "False", + "Butterfree": "False", + "Weedle": "False", + "Kakuna": "False", + "Beedrill": "False", + "Pidgey": "False", + "Pidgeotto": "False", + "Pidgeot": "False", + "Rattata": "False", + "Spearow": "False", + "Fearow": "False", + "Ekans": "False", + "Arbok": "False", + "Pikachu": "False", + "Raichu": "False", + "Sandshrew": "False", + "Sandslash": "False", + "Nidoran♀": "False", + "Nidorina": "False", + "Nidoqueen": "False", + "Nidoran♂": "False", + "Nidorino": "False", + "Nidoking": "False", + "Clefairy": "False", + "Clefable": "False", + "Vulpix": "False", + "Ninetales": "False", + "Jigglypuff": "False", + "Wigglytuff": "False", + "Zubat": "False", + "Golbat": "False", + "Oddish": "False", + "Gloom": "False", + "Vileplume": "False", + "Paras": "False", + "Parasect": "False", + "Venonat": "False", + "Venomoth": "False", + "Diglett": "False", + "Dugtrio": "False", + "Meowth": "False", + "Persian": "False", + "Psyduck": "False", + "Golduck": "False", + "Mankey": "False", + "Primeape": "False", + "Growlithe": "False", + "Arcanine": { + "min_iv": "90" + }, + "Poliwag": "False", + "Poliwhirl": "False", + "Poliwrath": "False", + "Abra": "False", + "Kadabra": "False", + "Alakazam": "True", + "Machop": "False", + "Machoke": "False", + "Machamp": "True", + "Bellsprout": "False", + "Weepinbell": "False", + "Victreebel": "False", + "Tentacool": "False", + "Tentacruel": "False", + "Geodude": { + "min_iv": "90" + }, + "Graveler": { + "min_iv": "90" + }, + "Golem": "True", + "Ponyta": "False", + "Rapidash": "False", + "Slowpoke": "False", + "Slowbro": "False", + "Magnemite": "False", + "Magneton": "False", + "Farfetch'd": "True", + "Doduo": "False", + "Dodrio": "False", + "Seel": "False", + "Dewgong": "False", + "Grimer": "False", + "Muk": "False", + "Shellder": "False", + "Cloyster": "False", + "Gastly": "False", + "Haunter": "False", + "Gengar": "False", + "Onix": "False", + "Drowzee": "False", + "Hypno": "False", + "Krabby": "False", + "Kingler": "False", + "Voltorb": "False", + "Electrode": "False", + "Exeggcute": "False", + "Exeggutor": { + "min_iv": "90" + }, + "Cubone": "False", + "Marowak": "False", + "Hitmonlee": "False", + "Hitmonchan": "False", + "Lickitung": "False", + "Koffing": "False", + "Weezing": "False", + "Rhyhorn": "False", + "Rhydon": { + "min_iv": "90" + }, + "Chansey": "True", + "Tangela": "False", + "Kangaskhan": "False", + "Horsea": "False", + "Seadra": "False", + "Goldeen": "False", + "Seaking": "False", + "Staryu": "False", + "Starmie": "False", + "Mr. Mime": "True", + "Scyther": { + "min_iv": "82" + }, + "Jynx": "False", + "Electabuzz": "False", + "Magmar": "False", + "Pinsir": "False", + "Tauros": "True", + "Magikarp": { + "min_iv": "95" + }, + "Gyarados": "True", + "Lapras": "True", + "Ditto": "False", + "Eevee": { + "min_iv": "95" + }, + "Vaporeon": { + "min_iv": "90" + }, + "Jolteon": { + "min_iv": "90" + }, + "Flareon": { + "min_iv": "90" + }, + "Porygon": "False", + "Omanyte": "False", + "Omastar": "False", + "Kabuto": "False", + "Kabutops": "False", + "Aerodactyl": "False", + "Snorlax": "True", + "Articuno": "True", + "Zapdos": "True", + "Moltres": "True", + "Dratini": { + "min_iv": "90" + }, + "Dragonair": { + "min_iv": "90" + }, + "Dragonite": "True", + "Mewtwo": "True", + "Mew": "True", + "Chikorita": "False", + "Bayleef": "False", + "Meganium": { + "min_iv": "60" + }, + "Cyndaquil": "False", + "Quilava": "False", + "Typhlosion": "True", + "Totodile": "False", + "Croconaw": "False", + "Feraligatr": { + "min_iv": "60" + }, + "Sentret": "False", + "Furret": "False", + "Hoothoot": "False", + "Noctowl": "False", + "Ledyba": "False", + "Ledian": "False", + "Spinarak": "False", + "Ariados": "False", + "Crobat": "False", + "Chinchou": "False", + "Lanturn": "False", + "Pichu": "False", + "Cleffa": "False", + "Igglybuff": "False", + "Togepi": "False", + "Togetic": "False", + "Natu": "False", + "Xatu": "False", + "Mareep": "True", + "Flaaffy": "True", + "Ampharos": "True", + "Bellossom": "True", + "Marill": "False", + "Azumarill": "False", + "Sudowoodo": "False", + "Politoed": "True", + "Hoppip": "False", + "Skiploom": "False", + "Jumpluff": "False", + "Aipom": "False", + "Sunkern": "False", + "Sunflora": "True", + "Yanma": "False", + "Wooper": "False", + "Quagsire": "False", + "Espeon": "True", + "Umbreon": "True", + "Murkrow": "False", + "Slowking": "True", + "Misdreavus": "False", + "Unown": "True", + "Wobbuffet": "False", + "Girafarig": "False", + "Pineco": "False", + "Forretress": "False", + "Dunsparce": "False", + "Gligar": "False", + "Steelix": "True", + "Snubbull": "False", + "Granbull": "False", + "Qwilfish": "False", + "Scizor": "True", + "Shuckle": "False", + "Heracross": "True", + "Sneasel": "False", + "Teddiursa": "False", + "Ursaring": "False", + "Slugma": "False", + "Magcargo": "False", + "Swinub": "False", + "Piloswine": "True", + "Corsola": "False", + "Remoraid": "False", + "Octillery": "False", + "Delibird": "True", + "Mantine": "False", + "Skarmory": "False", + "Houndour": "False", + "Houndoom": { + "min_iv": "82" + }, + "Kingdra": "True", + "Phanpy": "False", + "Donphan": { + "min_iv": "82" + }, + "Porygon2": "True", + "Stantler": "False", + "Smeargle": "True", + "Tyrogue": "True", + "Hitmontop": "True", + "Smoochum": "False", + "Elekid": "False", + "Magby": "False", + "Miltank": "True", + "Blissey": "True", + "Raikou": "True", + "Entei": "True", + "Suicune": "True", + "Larvitar": { + "min_iv": "90" + }, + "Pupitar": { + "min_iv": "90" + }, + "Tyranitar": "True", + "Lugia": "True", + "Ho-Oh": "True", + "Celebi": "True", + "Treecko": "False", + "Grovyle": "False", + "Sceptile": "False", + "Torchic": "False", + "Combusken": "False", + "Blaziken": "False", + "Mudkip": "False", + "Marshtomp": "False", + "Swampert": "False", + "Poochyena": "False", + "Mightyena": "False", + "Zigzagoon": "False", + "Linoone": "False", + "Wurmple": "False", + "Silcoon": "False", + "Beautifly": "False", + "Cascoon": "False", + "Dustox": "False", + "Lotad": "False", + "Lombre": "False", + "Ludicolo": "False", + "Seedot": "False", + "Nuzleaf": "False", + "Shiftry": "False", + "Taillow": "False", + "Swellow": "False", + "Wingull": "False", + "Pelipper": "False", + "Ralts": "False", + "Kirlia": "False", + "Gardevoir": "False", + "Surskit": "False", + "Masquerain": "False", + "Shroomish": "False", + "Breloom": "False", + "Slakoth": "False", + "Vigoroth": "False", + "Slaking": "False", + "Nincada": "False", + "Ninjask": "False", + "Shedinja": "False", + "Whismur": "False", + "Loudred": "False", + "Exploud": "False", + "Makuhita": "False", + "Hariyama": "False", + "Azurill": "False", + "Nosepass": "False", + "Skitty": "False", + "Delcatty": "False", + "Sableye": "False", + "Mawile": "False", + "Aron": "False", + "Lairon": "False", + "Aggron": "False", + "Meditite": "False", + "Medicham": "False", + "Electrike": "False", + "Manectric": "False", + "Plusle": "False", + "Minun": "False", + "Volbeat": "False", + "Illumise": "False", + "Roselia": "False", + "Gulpin": "False", + "Swalot": "False", + "Carvanha": "False", + "Sharpedo": "False", + "Wailmer": "False", + "Wailord": "False", + "Numel": "False", + "Camerupt": "False", + "Torkoal": "False", + "Spoink": "False", + "Grumpig": "False", + "Spinda": "False", + "Trapinch": "False", + "Vibrava": "False", + "Flygon": "False", + "Cacnea": "False", + "Cacturne": "False", + "Swablu": "False", + "Altaria": "False", + "Zangoose": "False", + "Seviper": "False", + "Lunatone": "False", + "Solrock": "False", + "Barboach": "False", + "Whiscash": "False", + "Corphish": "False", + "Crawdaunt": "False", + "Baltoy": "False", + "Claydol": "False", + "Lileep": "False", + "Cradily": "False", + "Anorith": "False", + "Armaldo": "False", + "Feebas": "False", + "Milotic": "False", + "Castform": "False", + "Kecleon": "False", + "Shuppet": "False", + "Banette": "False", + "Duskull": "False", + "Dusclops": "False", + "Tropius": "False", + "Chimecho": "False", + "Absol": "False", + "Wynaut": "False", + "Snorunt": "False", + "Glalie": "False", + "Spheal": "False", + "Sealeo": "False", + "Walrein": "False", + "Clamperl": "False", + "Huntail": "False", + "Gorebyss": "False", + "Relicanth": "False", + "Luvdisc": "False", + "Bagon": "False", + "Shelgon": "False", + "Salamence": "False", + "Beldum": "False", + "Metang": "False", + "Metagross": "False", + "Regirock": "False", + "Regice": "False", + "Registeel": "False", + "Latias": "False", + "Latios": "False", + "Kyogre": "False", + "Groudon": "False", + "Rayquaza": "False", + "Jirachi": "False", + "Deoxys": "False" } \ No newline at end of file diff --git a/presets.ini b/presets.ini new file mode 100644 index 0000000..8248ae5 --- /dev/null +++ b/presets.ini @@ -0,0 +1,7 @@ +[100iv] +type = pokemon +filter = 100iv.json + +[test] +type = raid +filter = test.json \ No newline at end of file diff --git a/raidchannels.ini b/raidchannels.ini new file mode 100644 index 0000000..ac42c69 --- /dev/null +++ b/raidchannels.ini @@ -0,0 +1,27 @@ +[329593125909561344] +geofences = belconnen-region +filter = raidfilter.json + +[329593100425232384] +geofences = gungahlin-region +filter = raidfilter.json + +[329592919092887552] +geofences = inner-north +filter = raidfilter.json + +[329593058284929025] +geofences = inner-south +filter = raidfilter.json + +[329593205836218368] +geofences = tuggeranong +filter = raidfilter.json + +[329593166833516544] +geofences = [woden,weston-region] +filter = raidfilter.json + +[329593232927490050] +geofences = queanbeyan +filter = raidfilter.json diff --git a/src/core/PokeChannel.java b/src/core/AlertChannel.java similarity index 73% rename from src/core/PokeChannel.java rename to src/core/AlertChannel.java index 8ff0d36..e3c443a 100644 --- a/src/core/PokeChannel.java +++ b/src/core/AlertChannel.java @@ -7,21 +7,22 @@ import static core.MessageListener.jda; -public class PokeChannel { +public class AlertChannel { - public String channelId; + public final String channelId; private TextChannel channel = null; public String filterName; HashSet geofences = null; + public String formattingName; - public PokeChannel (String channelId){ + public AlertChannel(String channelId){ this.channelId = channelId; } - public PokeChannel (String channelId, String filterName){ + public AlertChannel(String channelId, String filterName){ this(channelId); this.filterName = filterName; } diff --git a/src/core/Config.java b/src/core/Config.java index 1a87721..2b65bde 100644 --- a/src/core/Config.java +++ b/src/core/Config.java @@ -1,6 +1,6 @@ package core; -import com.google.gson.Gson; +import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -10,9 +10,13 @@ import net.dv8tion.jda.core.entities.Icon; import net.dv8tion.jda.core.entities.Member; import net.dv8tion.jda.core.entities.Role; +import notifier.PokeNotificationSender; +import notifier.RaidNotificationSender; import org.ini4j.Ini; +import pokemon.PokeSpawn; import pokemon.Pokemon; import raids.Raid; +import raids.RaidSpawn; import java.io.File; import java.io.FileNotFoundException; @@ -22,6 +26,8 @@ import static core.MessageListener.guild; import static core.MessageListener.jda; +import static net.dv8tion.jda.core.utils.SimpleLog.Level.INFO; +import static net.dv8tion.jda.core.utils.SimpleLog.Level.WARNING; import static raids.Raid.emotes; /** @@ -31,79 +37,77 @@ public class Config { private final boolean standardRaidTable; private final String googleSuburbField; - private NotificationLimit nonSupporterLimit; - Ini ini; + private final NotificationLimit nonSupporterLimit; + private final Ini ini; - ArrayList GMAPS_KEYS = new ArrayList<>(); + private ArrayList GMAPS_KEYS = new ArrayList<>(); - ArrayList blacklist = new ArrayList<>(); - private ArrayList supporterRoles; + private final ArrayList blacklist = new ArrayList<>(); + private ArrayList supporterRoles = new ArrayList<>(); - private String token; - private boolean geofences; - private boolean logging; - private boolean nests; - private boolean stats; - private boolean startupMessage; - private boolean supporterOnly; - private boolean countLocationsInLimits; + private final String token; + private final boolean geofences; + private final boolean logging; + private final boolean nests; + private final boolean stats; + private final boolean startupMessage; + private final boolean supporterOnly; + private final boolean countLocationsInLimits; - private String timeZone; + private final String timeZone; - private String footerText; + private final String footerText; - private String adminRole; + private final String adminRole; - private String commandChannelId; + private final String commandChannelId; private String roleLogId; private String userUpdatesId; - private long pokePollingRate; - private long raidPollingRate; + private final long pokePollingRate; + private final long raidPollingRate; - private String rmUser; - private String rmPass; - private String rmIp; - private String rmPort; - private String rmDbName; + private final String rmUser; + private final String rmPass; + private final String rmIp; + private final String rmPort; + private final String rmDbName; - private String nbUser; - private String nbPass; - private String nbIp; - private String nbPort; - private String nbDbName; + private final String nbUser; + private final String nbPass; + private final String nbIp; + private final String nbPort; + private final String nbDbName; - private HashMap bodyFormatting = new HashMap<>(); - private String encounterBodyFormatting; - private HashMap titleFormatting = new HashMap<>(); - private HashMap titleUrl = new HashMap<>(); + private final boolean useRmDb; - private HashMap mapZoom = new HashMap<>(); - private HashMap mapWidth = new HashMap<>(); - private HashMap mapHeight = new HashMap<>(); + private final boolean raidsEnabled; + private final boolean pokemonEnabled; - private HashMap showMap = new HashMap<>(); + private final boolean raidOrganisationEnabled; - private boolean useRmDb; + private final HashMap geofencedChannelIds = new HashMap<>(); + private final String novabotRoleId; - private boolean raidsEnabled; - private boolean raidChannelsEnabled; - private boolean pokemonEnabled; + private final HashMap roleLimits = new HashMap<>(); + private HashMap raidChats = new HashMap<>(); - private boolean raidOrganisationEnabled; + public final HashMap pokeFilters = new HashMap<>(); + private final HashMap formats = new HashMap<>(); - private HashMap geofencedChannelIds = new HashMap<>(); - private String novabotRoleId; + private final ArrayList pokeChannels = new ArrayList<>(); + private final ArrayList raidChannels = new ArrayList<>(); - HashMap roleLimits = new HashMap<>(); - private HashMap raidChats = new HashMap<>(); - private int minRaidLevel; - public HashMap filters = new HashMap<>(); - private ArrayList pokeChannels = new ArrayList<>(); + private static final String[] formatKeys = new String[]{"pokemon", "raidEgg", "raidBoss"}; + private static final String[] formattingVars = new String[]{"title", "titleUrl", "body", "showMap", "mapZoom", "mapWidth", "mapHeight"}; + public final ArrayList raidBosses = new ArrayList<>(); + public final HashMap raidFilters = new HashMap<>(); - public Config(Ini configIni, File gkeys, Ini formattingIni){ + public final HashMap presets = new HashMap<>(); + + public Config(Ini configIni, File gkeys) { this.ini = configIni; Ini.Section config = ini.get("config"); @@ -116,6 +120,12 @@ public Config(Ini configIni, File gkeys, Ini formattingIni){ blacklist.add(Integer.valueOf(s)); } + String raidBossStr = config.get("raidBosses"); + + for (String s : Util.parseList(raidBossStr)) { + raidBosses.add(Integer.valueOf(s)); + } + geofences = Boolean.parseBoolean(config.get("geofences")); useRmDb = Boolean.parseBoolean(config.get("useRmDb")); @@ -126,14 +136,12 @@ public Config(Ini configIni, File gkeys, Ini formattingIni){ raidsEnabled = Boolean.parseBoolean(config.get("raids")); - minRaidLevel = Integer.parseInt(config.get("minRaidLevel")); - raidOrganisationEnabled = Boolean.parseBoolean(config.get("raidOrganisation")); - raidChannelsEnabled = Boolean.parseBoolean(config.get("raidChannels")); - pokemonEnabled = Boolean.parseBoolean(config.get("pokemon")); +// waitForIV = Integer.parseInt(config.get("waitForIV")); + pokePollingRate = Long.parseLong(config.get("pokePollingRate")); raidPollingRate = Long.parseLong(config.get("raidPollingRate")); @@ -146,15 +154,23 @@ public Config(Ini configIni, File gkeys, Ini formattingIni){ countLocationsInLimits = Boolean.parseBoolean(config.get("countLocationsInLimits")); - supporterRoles = Util.parseList(config.get("supporterRoles")); + String supporterRolesLine = config.get("supporterRoles"); + + if(supporterRolesLine.contains("[")){ + supporterRoles = Util.parseList(config.get("supporterRoles")); + }else { + supporterRoles.add(supporterRolesLine.trim()); + } commandChannelId = config.get("commandChannel"); logging = Boolean.parseBoolean(config.get("logging")); - roleLogId = config.get("roleLogChannel"); + if (logging) { + roleLogId = config.get("roleLogChannel"); - userUpdatesId = config.get("userUpdatesChannel"); + userUpdatesId = config.get("userUpdatesChannel"); + } timeZone = config.get("timezone"); @@ -184,43 +200,297 @@ public Config(Ini configIni, File gkeys, Ini formattingIni){ GMAPS_KEYS = loadKeys(gkeys); - String[] formatKeys = new String[] {"pokemon","raidEgg","raidBoss"}; + loadFormatting("formatting.ini"); - for (String formatKey : formatKeys) { - Ini.Section format = formattingIni.get(formatKey); + if (raidsEnabled()) { + loadRaidChannels(); + } + + if (raidOrganisationEnabled) { + loadRaidChats(); + } - titleFormatting.put(formatKey,format.get("title")); - titleUrl.put(formatKey,format.get("titleUrl")); - bodyFormatting.put(formatKey,format.get("body")); + loadSupporterRoles(); - if(formatKey.equals("pokemon")) { - encounterBodyFormatting = format.get("encounteredBody"); + loadPokemonChannels(); + + loadPresets(); + } + + private void loadPresets() { + File file = new File("presets.ini"); + + try (Scanner in = new Scanner(file)) { + + String presetName = null; + String filterName = null; + Boolean pokemon = null; + + boolean first = true; + + while (in.hasNext()) { + String line = in.nextLine().toLowerCase(); + + if (line.length() == 0 || line.charAt(0) == ';') { + continue; + } + + if (line.charAt(0) == '[') { + + if (presetName != null) { + if (filterName != null) { + if (pokemon != null) { + if (pokemon) { + if (!pokeFilters.containsKey(filterName)) { + loadFilter(filterName,pokeFilters); + } + } else { + if (!raidFilters.containsKey(filterName)) { + loadFilter(filterName,raidFilters); + } + } + + presets.put(presetName, filterName); + }else{ + System.out.println("couldn't find type value"); + } + } else { + System.out.println("couldn't find filter name"); + } + + } else if (!first) { + System.out.println("couldn't find preset name"); + } + + int end = line.indexOf("]"); + presetName = line.substring(1, end).trim(); + + first = false; + } else { + int equalsIndex = line.indexOf("="); + + if (!(equalsIndex == -1)) { + + String parameter = line.substring(0, equalsIndex).trim(); + String value = line.substring(equalsIndex + 1).trim(); + + switch (parameter){ + case "type": + pokemon = value.equals("pokemon"); + break; + case "filter": + filterName = value; + break; + } + } + } } - showMap.put(formatKey,Boolean.parseBoolean(format.get("showMap"))); + if (presetName != null) { + if (filterName != null) { + if (pokemon != null) { - mapZoom.put(formatKey,format.get("mapZoom")); - mapWidth.put(formatKey,format.get("mapWidth")); - mapHeight.put(formatKey,format.get("mapHeight")); - } + if (pokemon) { + if (!pokeFilters.containsKey(filterName)) { + loadFilter(filterName,pokeFilters); + } + } else { + if (!raidFilters.containsKey(filterName)) { + loadFilter(filterName,raidFilters); + } + } - if(raidsEnabled()) { - loadGeofenceChannels(); + presets.put(presetName, filterName); + }else{ + System.out.println("couldn't find type value"); + } + } else { + System.out.println("couldn't find filter name"); + } + + } else { + System.out.println("couldn't find preset name"); + } + + } catch (FileNotFoundException e) { + e.printStackTrace(); } + } - if(raidOrganisationEnabled){ - loadRaidChats(); + private void loadRaidChannels() { + if (!Geofencing.loaded) Geofencing.loadGeofences(); + + File file = new File("raidchannels.ini"); + + try (Scanner in = new Scanner(file)) { + + String channelId = null; + String filterName = null; +// Integer minLevel = null; + String formattingName = "formatting.ini"; + HashSet geofenceIdentifiers = null; + + boolean first = true; + + while (in.hasNext()) { + String line = in.nextLine().toLowerCase(); + + if (line.length() == 0 || line.charAt(0) == ';') { + continue; + } + + if (line.charAt(0) == '[') { + AlertChannel channel; + + if (channelId != null) { + channel = new AlertChannel(channelId); + + if (filterName != null) { + channel.filterName = filterName; + +// channel.minLevel = minLevel; + + channel.geofences = geofenceIdentifiers; + + channel.formattingName = formattingName; + + raidChannels.add(channel); + } else { + System.out.println("couldn't find filter name"); + } + + } else if (!first) { + System.out.println("couldn't find channel id"); + } + + int end = line.indexOf("]"); + channelId = line.substring(1, end).trim(); + + first = false; + } else { + int equalsIndex = line.indexOf("="); + + if (!(equalsIndex == -1)) { + String parameter = line.substring(0, equalsIndex).trim(); + String value = line.substring(equalsIndex + 1).trim(); + + switch (parameter) { + case "geofences": + if (value.equals("all")) { + geofenceIdentifiers = null; + continue; + } + geofenceIdentifiers = new HashSet<>(); + + ArrayList geofences; + + if (value.charAt(0) == '[') { + geofences = Util.parseList(value); + } else { + geofences = new ArrayList<>(); + geofences.add(value); + } + + for (String s : geofences) { + geofenceIdentifiers.addAll(GeofenceIdentifier.fromString(s)); + } + break; +// case "minLevel": +// minLevel = Integer.parseInt(value); +// break; + case "filter": + filterName = value; + + if (!raidFilters.containsKey(filterName)) { + loadFilter(filterName, raidFilters); + } + break; + case "formatting": + formattingName = value; + + if (!formats.containsKey(formattingName)) { + loadFormatting(formattingName); + } + break; + } + } + } + } + + AlertChannel channel; + if (channelId != null) { + channel = new RaidChannel(channelId); + + if (filterName != null) { + channel.filterName = filterName; + +// channel.minLevel = minLevel; + + channel.formattingName = formattingName; + + channel.geofences = geofenceIdentifiers; + + raidChannels.add(channel); + } else { + System.out.println("couldn't find filter name"); + } + + } else { + System.out.println("couldn't find channel id"); + } + + } catch (FileNotFoundException e) { + e.printStackTrace(); } + } + + private void loadFilter(String filterName, HashMap filterMap) { + JsonObject filter = null; + JsonParser parser = new JsonParser(); - if(!supporterOnly){ - loadSupporterRoles(); + try { + JsonElement element = parser.parse(new FileReader(filterName)); + + if (element.isJsonObject()) { + filter = element.getAsJsonObject(); + } + + filterMap.put(filterName, filter); + System.out.println(String.format("Loaded filter %s: %s",filterName,filter)); + } catch (FileNotFoundException e) { + e.printStackTrace(); } + } - loadPokemonChannels(); + private void loadFormatting(String fileName) { + + Ini formatting = null; + try { + formatting = new Ini(new File(fileName)); + + Format format = new Format(); + + for (String formatKey : formatKeys) { + Ini.Section section = formatting.get(formatKey); + + for (String var : formattingVars) { + format.addFormatting(formatKey, var, section.get(var)); + } + + if (formatKey.equals("pokemon")) { + format.addFormatting(formatKey, "encounteredBody", section.get("encounteredBody")); + format.addFormatting(formatKey,"encounteredTitle",section.get("encounteredTitle")); + } + } + + formats.put(fileName, format); + } catch (IOException e) { + e.printStackTrace(); + } } private void loadPokemonChannels() { - if(!Geofencing.loaded) Geofencing.loadGeofences(); + if (!Geofencing.loaded) Geofencing.loadGeofences(); File file = new File("pokechannels.ini"); @@ -228,50 +498,53 @@ private void loadPokemonChannels() { String channelId = null; String filterName = null; + String formattingName = "formatting.ini"; HashSet geofenceIdentifiers = null; boolean first = true; - while(in.hasNext()){ + while (in.hasNext()) { String line = in.nextLine().toLowerCase(); - if(line.length() == 0 || line.charAt(0) == ';'){ + if (line.length() == 0 || line.charAt(0) == ';') { continue; } - if(line.charAt(0) == '['){ - PokeChannel channel; + if (line.charAt(0) == '[') { + AlertChannel channel; - if (channelId != null){ - channel = new PokeChannel(channelId); + if (channelId != null) { + channel = new AlertChannel(channelId); - if (filterName != null){ + if (filterName != null) { channel.filterName = filterName; channel.geofences = geofenceIdentifiers; + channel.formattingName = formattingName; + pokeChannels.add(channel); - }else{ + } else { System.out.println("couldn't find filter name"); } - }else if (!first){ + } else if (!first) { System.out.println("couldn't find channel id"); } int end = line.indexOf("]"); - channelId = line.substring(1,end).trim(); + channelId = line.substring(1, end).trim(); first = false; - }else{ + } else { int equalsIndex = line.indexOf("="); - if(!(equalsIndex == -1)){ - String parameter = line.substring(0,equalsIndex).trim(); - String value = line.substring(equalsIndex+1).trim(); + if (!(equalsIndex == -1)) { + String parameter = line.substring(0, equalsIndex).trim(); + String value = line.substring(equalsIndex + 1).trim(); - if(parameter.equals("geofences")){ - if(value.equals("all")){ + if (parameter.equals("geofences")) { + if (value.equals("all")) { geofenceIdentifiers = null; continue; } @@ -279,9 +552,9 @@ private void loadPokemonChannels() { ArrayList geofences; - if(value.charAt(0) == '['){ + if (value.charAt(0) == '[') { geofences = Util.parseList(value); - }else{ + } else { geofences = new ArrayList<>(); geofences.add(value); } @@ -289,32 +562,40 @@ private void loadPokemonChannels() { for (String s : geofences) { geofenceIdentifiers.addAll(GeofenceIdentifier.fromString(s)); } - }else if (parameter.equals("filter")){ + } else if (parameter.equals("filter")) { filterName = value; - if(!filters.containsKey(filterName)){ - filters.put(filterName, loadPokeFilter(filterName)); + if (!pokeFilters.containsKey(filterName)) { + loadFilter(filterName, pokeFilters); + } + } else if (parameter.equals("formatting")) { + formattingName = value; + + if (!formats.containsKey(formattingName)) { + loadFormatting(formattingName); } } } } } - PokeChannel channel; - if (channelId != null){ - channel = new PokeChannel(channelId); + AlertChannel channel; + if (channelId != null) { + channel = new AlertChannel(channelId); - if (filterName != null){ + if (filterName != null) { channel.filterName = filterName; channel.geofences = geofenceIdentifiers; + channel.formattingName = formattingName; + pokeChannels.add(channel); - }else{ + } else { System.out.println("couldn't find filter name"); } - }else { + } else { System.out.println("couldn't find channel id"); } @@ -323,34 +604,17 @@ private void loadPokemonChannels() { } } - private JsonObject loadPokeFilter(String fileName) { - JsonObject filter = null; - - Gson g = new Gson(); - JsonParser parser = new JsonParser(); - - try { - JsonElement element = parser.parse(new FileReader(fileName)); - - if (element.isJsonObject()) { - filter = (JsonObject) element.getAsJsonObject().get("pokemon"); - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - return filter; - } - - public JsonElement searchPokemonFilter(JsonObject filter,int id){ - return filter.get(Util.capitaliseFirst(Pokemon.idToName(id))); + private JsonElement searchFilter(JsonObject filter, String search) { + if (filter == null || search == null) return null; + return filter.get(Util.capitaliseFirst(search)); } private void loadRaidChats() { - if(!Geofencing.loaded) Geofencing.loadGeofences(); + if (!Geofencing.loaded) Geofencing.loadGeofences(); File file = new File("raidchats.txt"); - raidChats = loadGeofencedChannels(file,raidChats); + raidChats = loadGeofencedChannels(file, raidChats); } private void loadSupporterRoles() { @@ -366,22 +630,18 @@ private void loadSupporterRoles() { String roleId = split[0].trim(); - roleLimits.put(roleId,NotificationLimit.fromString(line)); + roleLimits.put(roleId, NotificationLimit.fromString(line)); } } catch (FileNotFoundException e) { - e.printStackTrace(); + MessageListener.novabotLog.log(WARNING,"Couldn't find supporterlevels.txt, ignoring"); } } - public String getGeofenceChannelId(GeofenceIdentifier identifier){ - return geofencedChannelIds.get(identifier); - } - - private HashMap loadGeofencedChannels(File file, HashMap map){ - try{ + private HashMap loadGeofencedChannels(File file, HashMap map) { + try { Scanner sc = new Scanner(file); - while(sc.hasNext()){ + while (sc.hasNext()) { String line = sc.nextLine().toLowerCase(); String[] split = line.split("="); @@ -391,7 +651,7 @@ private HashMap loadGeofencedChannels(File file, Hash String channelId = split[1].trim(); for (GeofenceIdentifier geofenceIdentifier : geofenceIdentifiers) { - map.put(geofenceIdentifier,channelId); + map.put(geofenceIdentifier, channelId); } } @@ -402,18 +662,8 @@ private HashMap loadGeofencedChannels(File file, Hash return map; } - private void loadGeofenceChannels() { - - if(!Geofencing.loaded) Geofencing.loadGeofences(); - - File file = new File("raidalerts.txt"); - - geofencedChannelIds = loadGeofencedChannels(file,geofencedChannelIds); - - } - - public String getTitleUrl(String formatKey) { - return titleUrl.get(formatKey); + public String getTitleUrl(String fileName, String formatKey) { + return formats.get(fileName).getFormatting(formatKey, "titleUrl"); } private ArrayList loadKeys(File gkeys) { @@ -423,7 +673,7 @@ private ArrayList loadKeys(File gkeys) { try { Scanner in = new Scanner(gkeys); - while (in.hasNext()){ + while (in.hasNext()) { String key = in.nextLine(); keys.add(key); } @@ -439,10 +689,9 @@ public static void main(String[] args) { try { Config config = new Config( new Ini(new File("config.ini")), - new File("gkeys.txt"), - new Ini(new File("formatting.ini"))); + new File("gkeys.txt")); - System.out.println("hi"); + System.out.println(config.matchesFilter(config.raidFilters.get("raidfilter.json"),new RaidSpawn(3,true))); } catch (IOException e) { e.printStackTrace(); } @@ -552,42 +801,46 @@ public boolean showStartupMessage() { return startupMessage; } - public String formatStr(HashMap pokeProperties, String toFormat){ + public String formatStr(HashMap properties, String toFormat) { final String[] str = {toFormat}; - pokeProperties.forEach((key, value) -> { - str[0] = str[0].replace(String.format("<%s>", key),value); + properties.forEach((key, value) -> { + str[0] = str[0].replace(String.format("<%s>", key), value); }); return str[0]; } - public String getTitleFormatting(String formatKey) { - return titleFormatting.get(formatKey); + public String getTitleFormatting(String fileName, String formatKey) { + return formats.get(fileName).getFormatting(formatKey, "title"); } - public String getBodyFormatting(String formatKey) { - return bodyFormatting.get(formatKey); + public String getBodyFormatting(String fileName, String formatKey) { + return formats.get(fileName).getFormatting(formatKey, "body"); } - public String getEncounterBodyFormatting() { - return encounterBodyFormatting; + public String getEncounterBodyFormatting(String fileName) { + return formats.get(fileName).getFormatting("pokemon", "encounteredBody"); } - public String getMapZoom(String formatKey) { - return mapZoom.get(formatKey); + public String getEncounterTitleFormatting(String fileName) { + return formats.get(fileName).getFormatting("pokemon", "encounteredTitle"); } - public String getMapWidth(String formatKey) { - return mapWidth.get(formatKey); + public String getMapZoom(String fileName, String formatKey) { + return formats.get(fileName).getFormatting(formatKey, "mapZoom"); } - public String getMapHeight(String formatKey) { - return mapHeight.get(formatKey); + public String getMapWidth(String fileName, String formatKey) { + return formats.get(fileName).getFormatting(formatKey, "mapWidth"); } - public boolean showMap(String formatKey) { - return showMap.get(formatKey); + public String getMapHeight(String fileName, String formatKey) { + return formats.get(fileName).getFormatting(formatKey, "mapHeight"); + } + + public boolean showMap(String fileName, String formatKey) { + return Boolean.parseBoolean(formats.get(fileName).getFormatting(formatKey, "showMap")); } public String getAdminRole() { @@ -611,7 +864,7 @@ public boolean pokemonEnabled() { } public boolean isRaidChannelsEnabled() { - return raidChannelsEnabled; + return raidChannels.size() > 0; } public String novabotRole() { @@ -625,7 +878,7 @@ public boolean isRaidOrganisationEnabled() { public NotificationLimit getNotificationLimit(Member member) { for (Role role : member.getRoles()) { NotificationLimit notificationLimit = roleLimits.get(role.getId()); - if(notificationLimit != null){ + if (notificationLimit != null) { return notificationLimit; } } @@ -636,7 +889,7 @@ public ArrayList getRaidChatGeofences(String id) { ArrayList geofenceIdentifiers = new ArrayList<>(); for (Map.Entry entry : raidChats.entrySet()) { - if(entry.getValue().equals(id)){ + if (entry.getValue().equals(id)) { geofenceIdentifiers.add(entry.getKey()); } } @@ -645,13 +898,13 @@ public ArrayList getRaidChatGeofences(String id) { } public String raidChatsList() { - String str = ""; + StringBuilder str = new StringBuilder(); for (String s : geofencedChannelIds.values()) { - str += String.format(" %s%n",guild.getTextChannelById(s).getAsMention()); + str.append(String.format(" %s%n", guild.getTextChannelById(s).getAsMention())); } - return str; + return str.toString(); } public String[] getRaidChats(ArrayList geofences) { @@ -660,8 +913,8 @@ public String[] getRaidChats(ArrayList geofences) { for (Map.Entry entry : raidChats.entrySet()) { boolean added = false; for (GeofenceIdentifier geofence : geofences) { - if(added) break; - if(entry.getKey().equals(geofence)){ + if (added) break; + if (entry.getKey().equals(geofence)) { chatIds.add(entry.getValue()); added = true; } @@ -682,7 +935,7 @@ public NotificationLimit getNonSupporterLimit() { public boolean isRaidChannel(String id) { for (String s : raidChats.values()) { - if(id.equals(s)) return true; + if (id.equals(s)) return true; } return false; } @@ -691,52 +944,218 @@ public boolean standardRaidTable() { return standardRaidTable; } - public String getGoogleSuburbField(){ + public String getGoogleSuburbField() { return googleSuburbField; } public void loadEmotes() { for (String type : Raid.TYPES) { - List found = jda.getEmotesByName(type,true); - if(found.size() == 0) try { + List found = jda.getEmotesByName(type, true); + if (found.size() == 0) try { guild.getController().createEmote(type, Icon.from(getClass().getResourceAsStream(type + ".png"))).queue(emote -> emotes.put(type, emote)); } catch (IOException e) { e.printStackTrace(); - }else{ - emotes.put(type,found.get(0)); + } + else { + emotes.put(type, found.get(0)); } } } - public int getMinRaidLevel() { - return minRaidLevel; + public ArrayList getAlertChannels(GeofenceIdentifier identifier) { + ArrayList channels = null; + + for (AlertChannel alertChannel : pokeChannels) { + if (alertChannel.geofences != null && alertChannel.geofences.contains(identifier)) { + if (channels == null) channels = new ArrayList<>(); + channels.add(alertChannel); + } + } + return channels; } - public ArrayList getPokeChannels(GeofenceIdentifier identifier) { - ArrayList channels = null; + public ArrayList getRaidChannels(GeofenceIdentifier identifier) { + ArrayList channels = null; + + for (AlertChannel alertChannel : raidChannels) { + if (alertChannel.geofences != null && alertChannel.geofences.contains(identifier)) { + if (channels == null) channels = new ArrayList<>(); + channels.add(alertChannel); + } + } + return channels; + } - for (PokeChannel pokeChannel : pokeChannels) { - if (pokeChannel.geofences.contains(identifier)){ - if(channels == null) channels = new ArrayList<>(); + public ArrayList getNonGeofencedPokeChannels() { + ArrayList channels = null; - channels.add(pokeChannel); + for (AlertChannel alertChannel : pokeChannels) { + if (alertChannel.geofences == null) { + if (channels == null) channels = new ArrayList<>(); + channels.add(alertChannel); } + } return channels; } - public ArrayList getNonGeofencedChannels() { - ArrayList channels = null; + public ArrayList getNonGeofencedRaidChannels() { + ArrayList channels = null; - for (PokeChannel pokeChannel : pokeChannels) { - if (pokeChannel.geofences == null){ - channels = new ArrayList<>(); - channels.add(pokeChannel); + for (AlertChannel alertChannel : raidChannels) { + if (alertChannel.geofences == null) { + if (channels == null) channels = new ArrayList<>(); + channels.add(alertChannel); } + } return channels; } + + public ArrayList findMatchingPresets(RaidSpawn raidSpawn) { + ArrayList matching = new ArrayList<>(); + + for (Map.Entry entry : presets.entrySet()) { + if (matchesFilter(raidFilters.get(entry.getValue()),raidSpawn)){ + matching.add(entry.getKey()); + } + } + return matching; + } + + public ArrayList findMatchingPresets(PokeSpawn pokeSpawn) { + ArrayList matching = new ArrayList<>(); + + for (Map.Entry entry : presets.entrySet()) { + JsonObject filter = pokeFilters.get(entry.getValue()); + if (filter != null && matchesFilter(filter,pokeSpawn,entry.getValue())){ + matching.add(entry.getKey()); + } + } + return matching; + } + + public boolean matchesFilter(JsonObject filter, RaidSpawn raidSpawn) { + String searchStr = (raidSpawn.bossId >= 1) ? Pokemon.getFilterName(raidSpawn.bossId) : "Egg"+raidSpawn.raidLevel; + + JsonElement raidFilter =searchFilter(filter, searchStr); + if (raidFilter == null) { +// System.out.println(String.format("raidFilter %s is null for %s for channel with id %s", channel.filterName, searchStr,channel.channelId)); + raidFilter = searchFilter(filter,"Level"+raidSpawn.raidLevel); + + if(raidFilter == null) return false; + } + + if (raidFilter.isJsonObject()) { + System.out.println("objects as raid filters not supported yet"); + return false; + } else { + if (raidFilter.getAsBoolean()) { + return true; + } else { + RaidNotificationSender.notificationLog.log(INFO, "raid not enabled in filter, not posting"); + return false; + } + } + } + + public boolean matchesFilter(JsonObject filter, PokeSpawn pokeSpawn, String filterName){ + JsonElement pokeFilter = searchFilter(filter, Pokemon.getFilterName(pokeSpawn.getFilterId())); + if (pokeFilter == null) { + PokeNotificationSender.notificationLog.log(INFO,String.format("pokeFilter %s is null for %s", filterName, pokeSpawn.properties.get("pkmn"))); +// System.out.println(String.format("pokeFilter %s is null for %s for channel with id %s", channel.filterName, pokeSpawn.properties.get("pkmn"),channel.channelId)); + + pokeFilter = searchFilter(filter,"Default"); + + if (pokeFilter == null) { + return false; + } + } + if (pokeFilter.isJsonObject()) { + JsonObject obj = pokeFilter.getAsJsonObject(); + + JsonElement maxObj = obj.get("max_iv"); + JsonElement minObj = obj.get("min_iv"); + + float max = maxObj == null ? 100 : maxObj.getAsFloat(); + float min = minObj == null ? 0 : minObj.getAsFloat(); + + if (pokeSpawn.iv <= max && pokeSpawn.iv >= min) { + PokeNotificationSender.notificationLog.log(INFO, String.format("Pokemon between specified ivs (%s,%s)", min, max)); + } else { + PokeNotificationSender.notificationLog.log(INFO, String.format("Pokemon (%s%%) not between specified ivs (%s,%s). filter %s", pokeSpawn.iv, min, max, filterName)); + return false; + } + + maxObj = obj.get("max_cp"); + minObj = obj.get("min_cp"); + + max = maxObj == null ? Integer.MAX_VALUE : maxObj.getAsFloat(); + min = minObj == null ? 0 : minObj.getAsFloat(); + + if (pokeSpawn.cp <= max && pokeSpawn.cp >= min){ + PokeNotificationSender.notificationLog.log(INFO, String.format("Pokemon between specified cp (%s,%s)", min, max)); + }else { + PokeNotificationSender.notificationLog.log(INFO, String.format("Pokemon (%sCP) not between specified cp (%s,%s)", pokeSpawn.cp, min, max)); + return false; + } + + maxObj = obj.get("max_level"); + minObj = obj.get("min_level"); + + max = maxObj == null ? 30 : maxObj.getAsInt(); + min = minObj == null ? 0 : minObj.getAsFloat(); + + if (pokeSpawn.level <= max && pokeSpawn.level >= min){ + PokeNotificationSender.notificationLog.log(INFO, String.format("Pokemon between specified level (%s,%s)", min, max)); + }else { + PokeNotificationSender.notificationLog.log(INFO, String.format("Pokemon (level %s) not between specified level (%s,%s)", pokeSpawn.level, min, max)); + return false; + } + + JsonArray sizes = obj.getAsJsonArray("size"); + + if (sizes != null){ + String spawnSize = pokeSpawn.properties.get("size"); + boolean passed = false; + + for (JsonElement size : sizes) { + if (size.getAsString().equals(spawnSize)){ + PokeNotificationSender.notificationLog.log(INFO, String.format("Pokemon size %s passed filter", spawnSize)); + passed = true; + break; + } + } + + if (!passed){ + PokeNotificationSender.notificationLog.log(INFO, String.format("Pokemon size %s did not pass filter", spawnSize)); + return false; + } + } + return true; + } else { + if (pokeFilter.getAsBoolean()) { + PokeNotificationSender.notificationLog.log(INFO, "Pokemon enabled in filter, posting to Discord"); + return true; + } else { + PokeNotificationSender.notificationLog.log(INFO, "Pokemon not enabled in filter, not posting"); + return false; + } + } + } + + public String getPresetsList() { + StringBuilder list = new StringBuilder("```"); + + for (String presetName : presets.keySet()) { + list.append(String.format(" %s%n", presetName)); + } + + list.append("```"); + return list.toString(); + } + } diff --git a/src/core/DBManager.java b/src/core/DBManager.java index d0a0883..c9daa36 100644 --- a/src/core/DBManager.java +++ b/src/core/DBManager.java @@ -12,12 +12,9 @@ import raids.RaidSpawn; import java.sql.*; -import java.util.ArrayList; +import java.util.*; import java.util.Date; -import java.util.HashMap; -import java.util.TimeZone; -import static core.FeedChannels.loadChannels; import static core.MessageListener.*; import static net.dv8tion.jda.core.utils.SimpleLog.Level.*; @@ -27,11 +24,11 @@ public class DBManager { private static Timestamp lastChecked = getCurrentTime(); private static Timestamp lastCheckedRaids = getCurrentTime(); - private static RotatingSet hashCodes = new RotatingSet<>(2000); + private static final RotatingSet hashCodes = new RotatingSet<>(2000); - public static HashMap knownRaids = new HashMap<>(); + public static final HashMap knownRaids = new HashMap<>(); - static SimpleLog dbLog = SimpleLog.getLog("DB"); + private static final SimpleLog dbLog = SimpleLog.getLog("DB"); private static String blacklistQMarks; public static void main(final String[] args) { @@ -43,13 +40,17 @@ public static void main(final String[] args) { loadConfig(); loadSuburbs(); - loadChannels(); novabotdbConnect(); - PokeSpawn pokeSpawn = new PokeSpawn(143,35,149,new Timestamp(DBManager.getCurrentTime().getTime() + 504000), 15,15,15,"","",0,0,0,0,200,.1); - - getUserIDsToNotify(pokeSpawn).forEach(System.out::println); + System.out.println(getUserPref("107730875596169216").allPresetsToString()); +// System.out.println(config.findMatchingPresets(new RaidSpawn("raid","123",145,35,Team.Uncontested,DBManager.getCurrentTime(),DBManager.getCurrentTime(),3,1,1,1,3))); +// +// System.out.println(getUserIDsToNotify("test",new RaidSpawn("raid","123",145,35,Team.Uncontested,DBManager.getCurrentTime(),DBManager.getCurrentTime(),1,1,1,1,2))); +// +// PokeSpawn pokeSpawn = new PokeSpawn(143,35,149,new Timestamp(DBManager.getCurrentTime().getTime() + 504000), 15,15,15,"","",0,0,0,0,200,.1); +// +// getUserIDsToNotify(pokeSpawn).forEach(System.out::println); // RaidSpawn spawn = new RaidSpawn("gym", // "12345", -35.265134, 149.122796, // new Timestamp(DBManager.getCurrentTime().getTime() + 504000), @@ -125,7 +126,7 @@ public static ArrayList getCurrentRaids() { ArrayList knownIds = new ArrayList<>(); - knownRaids.keySet().forEach(knownIds::add); + knownIds.addAll(knownRaids.keySet()); if (knownRaids.containsKey(null)) { System.out.println("NULL, OH NO KNOWNRAIDS CONTAINS NULL? WHY???"); @@ -139,6 +140,7 @@ public static ArrayList getCurrentRaids() { " `gymdetails`.gym_id," + " `gym`.latitude," + " `gym`.longitude," + + " `gym`.team_id," + " (CONVERT_TZ(`raid`.end, 'UTC', '" + config.getTimeZone() + "')) AS end," + " (CONVERT_TZ(`raid`.start, 'UTC', '" + config.getTimeZone() + "')) AS battle," + " `raid`.pokemon_id," + @@ -155,6 +157,7 @@ public static ArrayList getCurrentRaids() { " `gymdetails`.gym_id," + " `gym`.latitude," + " `gym`.longitude," + + " `gym`.team_id," + " (CONVERT_TZ(`raidinfo`.raid_end_ms, 'UTC', '" + config.getTimeZone() + "')) AS end," + " (CONVERT_TZ(`raidinfo`.raid_battle_ms, 'UTC', '" + config.getTimeZone() + "')) AS battle," + " `raidinfo`.pokemon_id," + @@ -184,15 +187,16 @@ public static ArrayList getCurrentRaids() { String gymId = rs.getString(2); double lat = rs.getDouble(3); double lon = rs.getDouble(4); - Timestamp raidEnd = rs.getTimestamp(5); - Timestamp battleStart = rs.getTimestamp(6); - int bossId = rs.getInt(7); - int bossCp = rs.getInt(8); - int raidLevel = rs.getInt(9); - String move_1 = PokeMove.idToName(rs.getInt(10)); - String move_2 = PokeMove.idToName(rs.getInt(11)); + Team team = Team.fromId(rs.getInt(5)); + Timestamp raidEnd = rs.getTimestamp(6); + Timestamp battleStart = rs.getTimestamp(7); + int bossId = rs.getInt(8); + int bossCp = rs.getInt(9); + int raidLevel = rs.getInt(10); + int move_1 = rs.getInt(11); + int move_2 = rs.getInt(12); - RaidSpawn raidSpawn = new RaidSpawn(name, gymId, lat, lon, raidEnd, battleStart, bossId, bossCp, move_1, move_2, raidLevel); + RaidSpawn raidSpawn = new RaidSpawn(name, gymId, lat, lon, team, raidEnd, battleStart, bossId, bossCp, move_1, move_2, raidLevel); dbLog.log(DEBUG, raidSpawn); @@ -266,12 +270,12 @@ public static ArrayList getNewPokemon() { " cp, " + " cp_multiplier " + "FROM pokemon " + - "WHERE pokemon_id NOT IN " + blacklistQMarks + " AND last_modified >= DATE_SUB(CONVERT_TZ(?,'" + config.getTimeZone() + "','UTC'),INTERVAL 1 SECOND)");) { + "WHERE pokemon_id NOT IN " + blacklistQMarks + " AND last_modified >= DATE_SUB(CONVERT_TZ(?,'" + config.getTimeZone() + "','UTC'),INTERVAL 1 SECOND)")) { for (int i = 1; i <= config.getBlacklist().size(); ++i) { statement.setString(i, String.valueOf(config.getBlacklist().get(i - 1))); } statement.setTimestamp(config.getBlacklist().size() + 1, DBManager.lastChecked); - dbLog.log(INFO, "Executing query:"); + dbLog.log(INFO, "Executing query:" + statement); final ResultSet rs = statement.executeQuery(); dbLog.log(DEBUG, statement); dbLog.log(INFO, "Query complete"); @@ -331,21 +335,6 @@ public static boolean containsUser(final String userID) { return true; } - public static Timestamp getJoinDate(final String userID) { - Timestamp timestamp = null; - try (Connection connection = getConnection(DBManager.novabotDataSource); - Statement statement = connection.createStatement()) { - statement.executeQuery(String.format("SELECT joindate FROM users WHERE id=%s;", userID)); - final ResultSet rs = statement.getResultSet(); - if (rs.next()) { - timestamp = rs.getTimestamp(1); - } - } catch (SQLException e) { - e.printStackTrace(); - } - return timestamp; - } - public static void logNewUser(final String userID) { try (Connection connection = getConnection(DBManager.novabotDataSource); Statement statement = connection.createStatement()) { @@ -442,7 +431,7 @@ public static void clearRaid(final String id, final ArrayList raids) { public static ArrayList getUserIDsToNotify(final RaidSpawn raidSpawn) { final ArrayList ids = new ArrayList<>(); - int geofences = raidSpawn.getGeofenceIds().size(); + int geofences = raidSpawn.getGeofences().size(); String geofenceQMarks = ""; for (int i = 0; i < geofences; ++i) { @@ -465,7 +454,7 @@ public static ArrayList getUserIDsToNotify(final RaidSpawn raidSpawn) { PreparedStatement statement = connection.prepareStatement(sql) ) { for (int i = 0; i < geofences; i++) { - statement.setString(i + 1, raidSpawn.getGeofenceIds().get(i).name.toLowerCase()); + statement.setString(i + 1, raidSpawn.getGeofences().get(i).name.toLowerCase()); } // statement.setString(geofences + 1, raidSpawn.properties.get("sublocality").toLowerCase()); @@ -489,7 +478,8 @@ public static void addPokemon(final String userID, final Pokemon pokemon) { try (Connection connection = getConnection(DBManager.novabotDataSource); PreparedStatement statement = connection.prepareStatement("" + "INSERT INTO pokemon (user_id, id, location, max_iv, min_iv) " + - "VALUES (?,?,?,?,?)")) { + "VALUES (?,?,?,?,?)")) + { statement.setString(1, userID); statement.setInt(2, pokemon.getID()); statement.setString(3, pokemon.getLocation().toDbString()); @@ -505,6 +495,43 @@ public static void addPokemon(final String userID, final Pokemon pokemon) { } } + public static void addPreset (final String userID, String preset, Location location) { + try (Connection connection = getConnection(DBManager.novabotDataSource); + PreparedStatement statement = connection.prepareStatement("" + + "INSERT INTO preset (user_id, preset_name, location) " + + "VALUES (?,?,?)")) + { + statement.setString(1, userID); + statement.setString(2, preset); + statement.setString(3, location.toDbString()); + + dbLog.log(INFO, statement); + statement.executeUpdate(); + } catch (MySQLIntegrityConstraintViolationException e) { + dbLog.log(SimpleLog.Level.WARNING, e.getMessage()); + } catch (SQLException e2) { + e2.printStackTrace(); + } + } + + public static void deletePreset (String userId, String preset, Location location) { + try (Connection connection = getConnection(DBManager.novabotDataSource); + PreparedStatement statement = connection.prepareStatement("" + + "DELETE FROM preset " + + "WHERE ((user_id=?) " + + "AND (LOWER(location)=LOWER(?)) " + + "AND (preset_name=?))")) { + statement.setString(1, userId); + statement.setString(2, location.toDbString()); + statement.setString(3, preset); + + dbLog.log(INFO, statement); + statement.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + public static void deletePokemon(final String userID, final Pokemon pokemon) { try (Connection connection = getConnection(DBManager.novabotDataSource); @@ -568,59 +595,85 @@ public static void resetPokemon(String id) { } } + + public static ArrayList getUserIDsToNotify(String preset, Spawn spawn) { + ArrayList ids = new ArrayList<>(); + + int geofences = spawn.getGeofences().size(); + + StringBuilder geofenceQMarks = new StringBuilder(); + for (int i = 0; i < geofences; ++i) { + geofenceQMarks.append("?"); + if (i != geofences - 1) { + geofenceQMarks.append(","); + } + } + if (geofences > 0) geofenceQMarks.append(","); + + String sql = String.format( + "SELECT user_id " + + "FROM preset " + + "WHERE (SELECT paused FROM users WHERE users.id = preset.user_id) = FALSE " + + "AND (LOWER(location) IN (%s?,'all'))" + + "AND (preset_name = ?)", geofenceQMarks.toString() + ); + + try (Connection connection = getConnection(DBManager.novabotDataSource); + PreparedStatement statement = connection.prepareStatement( + sql) + ) { + for (int i = 0; i < geofences; i++) { + statement.setString(i + 1, spawn.getGeofences().get(i).name.toLowerCase()); + } + statement.setString(geofences + 1, spawn.properties.get(config.getGoogleSuburbField()).toLowerCase()); + statement.setString(geofences + 2, preset); + + dbLog.log(INFO, statement); + final ResultSet rs = statement.executeQuery(); + while (rs.next()) { + ids.add(rs.getString(1)); + } + } catch (SQLException e) { + e.printStackTrace(); + } + + return ids; + } + public static ArrayList getUserIDsToNotify(final PokeSpawn pokeSpawn) { final ArrayList ids = new ArrayList<>(); - int geofences = pokeSpawn.getGeofenceIds().size(); + int geofences = pokeSpawn.getGeofences().size(); - String geofenceQMarks = ""; + StringBuilder geofenceQMarks = new StringBuilder(); for (int i = 0; i < geofences; ++i) { - geofenceQMarks += "?"; + geofenceQMarks.append("?"); if (i != geofences - 1) { - geofenceQMarks += ","; + geofenceQMarks.append(","); } } - if (geofences > 0) geofenceQMarks += ","; + if (geofences > 0) geofenceQMarks.append(","); - String sql; - - if (pokeSpawn.feedChannel == null) { - sql = String.format( - "SELECT DISTINCT(user_id) " + - "FROM pokemon " + - "WHERE (SELECT paused FROM users WHERE users.id = pokemon.user_id) = FALSE " + - "AND ((LOWER(location) IN (%s?,'all')) " + - "AND (id=? OR id=?) " + - "AND (min_iv <= ?) " + - "AND (max_iv >= ?));", geofenceQMarks - ); - } else { - sql = String.format( + String sql = String.format( "SELECT DISTINCT(user_id) " + - "FROM pokemon " + - "WHERE (SELECT paused FROM users WHERE users.id = pokemon.user_id) = FALSE " + - "AND ((LOWER(location) IN (%s?,?,'all')) " + - "AND (id=? OR id=?) " + - "AND (min_iv <= ?) " + - "AND (max_iv >= ?));", geofenceQMarks - ); - } + "FROM pokemon " + + "WHERE (SELECT paused FROM users WHERE users.id = pokemon.user_id) = FALSE " + + "AND ((LOWER(location) IN (%s?,'all')) " + + "AND (id=? OR id=?) " + + "AND (min_iv <= ?) " + + "AND (max_iv >= ?));", geofenceQMarks.toString() + ); try (Connection connection = getConnection(DBManager.novabotDataSource); PreparedStatement statement = connection.prepareStatement(sql) ) { for (int i = 0; i < geofences; i++) { - statement.setString(i + 1, pokeSpawn.getGeofenceIds().get(i).name.toLowerCase()); - } - - if (pokeSpawn.feedChannel != null) { - statement.setString(geofences + 1, pokeSpawn.feedChannel.getName().toLowerCase()); - geofences++; + statement.setString(i + 1, pokeSpawn.getGeofences().get(i).name.toLowerCase()); } // statement.setString(geofences + 1, pokeSpawn.getSuburb().toLowerCase()); -// statement.setString(geofences + 1, pokeSpawn.pokeProperties.get("sublocality").toLowerCase()); - statement.setString(geofences + 1, pokeSpawn.pokeProperties.get(config.getGoogleSuburbField()).toLowerCase()); +// statement.setString(geofences + 1, pokeSpawn.properties.get("sublocality").toLowerCase()); + statement.setString(geofences + 1, pokeSpawn.properties.get(config.getGoogleSuburbField()).toLowerCase()); statement.setInt(geofences + 2, pokeSpawn.id); statement.setInt(geofences + 3, (pokeSpawn.form != null) ? 201 : pokeSpawn.id); statement.setDouble(geofences + 4, pokeSpawn.iv); @@ -638,7 +691,7 @@ public static ArrayList getUserIDsToNotify(final PokeSpawn pokeSpawn) { } public static UserPref getUserPref(final String id) { - final UserPref userPref = new UserPref(isSupporter(id)); + final UserPref userPref = new UserPref(); try (Connection connection = getConnection(DBManager.novabotDataSource); Statement statement = connection.createStatement()) { @@ -647,10 +700,14 @@ public static UserPref getUserPref(final String id) { while (rs.next()) { final int pokemon_id = rs.getInt(1); - final Location location = Location.fromDbString(rs.getString(2).toLowerCase(), isSupporter(id)); + final Location location = Location.fromDbString(rs.getString(2).toLowerCase()); final float max_iv = rs.getFloat(3); final float min_iv = rs.getFloat(4); - userPref.addPokemon(new Pokemon(pokemon_id, location, min_iv, max_iv)); + if (location == null){ + novabotLog.log(SimpleLog.Level.WARNING, "Location null fromDbString " + rs.getString(2).toLowerCase()); + }else { + userPref.addPokemon(new Pokemon(pokemon_id, location, min_iv, max_iv)); + } } statement.executeQuery(String.format("SELECT boss_id,location FROM raid WHERE user_id='%s'", id)); @@ -659,9 +716,19 @@ public static UserPref getUserPref(final String id) { while (rs.next()) { final int bossId = rs.getInt(1); - final Location location = Location.fromDbString(rs.getString(2).toLowerCase(), isSupporter(id)); + final Location location = Location.fromDbString(rs.getString(2).toLowerCase()); userPref.addRaid(new Raid(bossId, location)); } + + statement.executeQuery(String.format("SELECT preset_name, location FROM preset WHERE user_id = '%s'",id)); + + rs = statement.getResultSet(); + + while (rs.next()){ + String presetName = rs.getString(1); + Location location = Location.fromDbString(rs.getString(2).toLowerCase()); + userPref.addPreset(presetName,location); + } } catch (SQLException e) { e.printStackTrace(); } diff --git a/src/core/FeedChannel.java b/src/core/FeedChannel.java deleted file mode 100644 index 93268f0..0000000 --- a/src/core/FeedChannel.java +++ /dev/null @@ -1,47 +0,0 @@ -package core; - -import net.dv8tion.jda.core.entities.TextChannel; - -import java.util.ArrayList; - -public class FeedChannel -{ - public String channelId; - public TextChannel channel = null; - public ArrayList aliases; - - public FeedChannel(final TextChannel channel, final ArrayList aliases) { - this.channel = channel; - this.aliases = aliases; - } - - public FeedChannel(String id, ArrayList aliases) { - this.channelId = id; - this.aliases = aliases; - } - - @Override - public String toString() { - return (channel == null ? channelId : channel.getName()) + ", aliases: " + aliases; - } - - public String getName() { - if(channel == null){ - return aliases.get(0); - }else{ - return String.format("#%s",channel.getName()); - } - } - - public String getAliasList() { - String str = ""; - - for (int i = 0; i < aliases.size(); i++) { - str += aliases.get(i); - if(i != aliases.size() - 1){ - str += ", "; - } - } - return str; - } -} diff --git a/src/core/FeedChannels.java b/src/core/FeedChannels.java deleted file mode 100644 index f9e588a..0000000 --- a/src/core/FeedChannels.java +++ /dev/null @@ -1,100 +0,0 @@ -package core; - -import net.dv8tion.jda.core.JDA; -import net.dv8tion.jda.core.utils.SimpleLog; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.Scanner; - -import static net.dv8tion.jda.core.utils.SimpleLog.Level.DEBUG; -import static net.dv8tion.jda.core.utils.SimpleLog.Level.INFO; - -public class FeedChannels -{ - private static ArrayList channels = new ArrayList<>(); - - private static SimpleLog feedChannelsLog = SimpleLog.getLog("FeedChannels"); - - public static void main(String[] args) { - loadChannels(); - } - - public static FeedChannel fromString(final String str) { - feedChannelsLog.log(DEBUG,"Converting string: " + str + " to FeedChannel"); - - for (FeedChannel channel : channels) { - if(channel.aliases.contains(str)) return channel; - } - - return null; - } - - public static FeedChannel fromDbString(String str) { - return null; - } - - public static void loadChannels() { - File file = new File("channels.txt"); - - channels = new ArrayList<>(); - - try (Scanner in = new Scanner(file)) { - - String id = null; - ArrayList aliases = new ArrayList<>(); - - while(in.hasNext()){ - String line = in.nextLine(); - - int idEnd = line.indexOf("="); - - id = line.substring(0,idEnd).trim(); - - int aliasesStart = line.indexOf("["); - int aliasesEnd = line.indexOf("]") + 1; - - aliases = Util.parseList(line.substring(aliasesStart,aliasesEnd)); - - channels.add(new FeedChannel(id,aliases)); - } - - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - - feedChannelsLog.log(INFO,channels); - } - - public static FeedChannel fromId(String id) { - for (FeedChannel channel : channels) { - if(channel.channel.getId().equals(id)) return channel; - } - - return null; - } - - public static void updateDiscordChannels(JDA jda) { - feedChannelsLog.log(INFO,"Fetching discord channels by IDs"); - for (FeedChannel channel : channels) { - channel.channel = jda.getTextChannelById(channel.channelId); - - if(!channel.aliases.contains(channel.channel.getName())){ - channel.aliases.add(channel.channel.getName()); - } - } - feedChannelsLog.log(INFO, "Done"); - feedChannelsLog.log(INFO, channels); - } - - public static String getListMessage() { - String str = ""; - - for (FeedChannel channel : channels) { - str += String.format(" %s, aliases: %s%n",channel.getName(),channel.getAliasList()); - } - - return str; - } -} diff --git a/src/core/Format.java b/src/core/Format.java new file mode 100644 index 0000000..59ff561 --- /dev/null +++ b/src/core/Format.java @@ -0,0 +1,23 @@ +package core; + +import java.util.HashMap; + +class Format { + + private final HashMap> formatting = new HashMap<>(); + + public Format (){ + formatting.put("pokemon",new HashMap<>()); + formatting.put("raidEgg",new HashMap<>()); + formatting.put("raidBoss",new HashMap<>()); + } + + public void addFormatting (String type, String key, String value){ + formatting.get(type).put(key,value); + } + + public String getFormatting (String type, String key){ + return formatting.get(type).get(key); + } + +} diff --git a/src/core/Location.java b/src/core/Location.java index 47a1564..1ef0490 100644 --- a/src/core/Location.java +++ b/src/core/Location.java @@ -1,7 +1,7 @@ package core; import maps.GeofenceIdentifier; -import maps.Geofencing; +import net.dv8tion.jda.core.utils.SimpleLog; import java.util.ArrayList; @@ -10,21 +10,14 @@ public class Location { private static final Location ALL = new Location(Region.All); - private static final Location UNUSABLE = new Location(); public ArrayList geofenceIdentifiers; private Region region; public LocationType locationType; - private FeedChannel channel; private String suburb; - public boolean usable = true; - public Reason reason; + public final boolean usable = true; +// public Reason reason; - public Location(final FeedChannel channel) { - this.locationType = LocationType.Channel; - this.channel = channel; - } - - public Location(final String suburb) { + private Location(final String suburb) { this.locationType = LocationType.Suburb; this.suburb = suburb; } @@ -40,7 +33,7 @@ public Location(Region region) { this.region = region; } - public Location() { + private Location() { } @@ -49,17 +42,6 @@ public Location(ArrayList identifiers) { this.geofenceIdentifiers = identifiers; } - public static void main(final String[] args) { - FeedChannels.loadChannels(); - Geofencing.loadGeofences(); - MessageListener.loadConfig(); - MessageListener.loadSuburbs(); - System.out.println(new Location(FeedChannels.fromDbString("TuggeranongRegion"))); - } - - public FeedChannel getFeedChannel() { - return this.channel; - } public String getSuburb() { return this.suburb; @@ -69,8 +51,6 @@ public String getSuburb() { public String toString() { switch(locationType){ - case Channel: - return this.channel.toString(); case Suburb: return this.suburb; case Geofence: @@ -96,7 +76,7 @@ public static String listToString(final Location[] locations) { return str; } - public static Location fromString(final String str, boolean supporter) { + public static Location fromString(final String str) { if(str.equalsIgnoreCase("all")) return new Location(Region.All); @@ -108,48 +88,16 @@ public static Location fromString(final String str, boolean supporter) { } } - - if(config.useChannels()){ - final FeedChannel channel = FeedChannels.fromString(str); - - if(!config.isSupporterOnly() && !supporter) { - if (channel != null) { - return new Location(channel); - } - }else if(!config.isSupporterOnly() && supporter){ - if(channel != null){ - return Location.UNUSABLE(Reason.SupporterAttemptedPublic,str,LocationType.Channel); - } - } - - } if (MessageListener.suburbs.isSuburb(str)) { return new Location(str); } return null; } - public static Location fromDbString(final String str) { - final FeedChannel channel = FeedChannels.fromDbString(str); - if (channel != null) { - return new Location(channel); - } - if (MessageListener.suburbs.isSuburb(str)) { - return new Location(str); - } - if (str.equals("civic")) { - return new Location("city"); - } - System.out.println(str + ", from db string is null"); - return null; - } - public String toWords() { switch(locationType){ case Suburb: return this.suburb; - case Channel: - return this.channel.getName(); case Geofence: return GeofenceIdentifier.listToString(this.geofenceIdentifiers); case Region: @@ -158,10 +106,10 @@ public String toWords() { return ""; } - public static Location fromDbString(String str, boolean supporter) { + public static Location fromDbString(String str) { if(str.equals("all")) return Location.ALL; - if(config.useGeofences() && supporter){ + if(config.useGeofences()){ ArrayList identifiers = GeofenceIdentifier.fromString(str); if(identifiers.size() != 0){ @@ -169,37 +117,28 @@ public static Location fromDbString(String str, boolean supporter) { } } - if(config.useChannels()) { - final FeedChannel channel = FeedChannels.fromString(str); - if (channel != null) { - return new Location(channel); - } - } - if (MessageListener.suburbs.isSuburb(str)) { return new Location(str); } if (str.equals("civic")) { return new Location("city"); } - System.out.println(str + ", from db string is null"); + MessageListener.novabotLog.log(SimpleLog.Level.WARNING,str + ", from db string is null"); return null; } - - private static Location UNUSABLE(Reason reason, String str, LocationType type) { - Location location = new Location(); - location.usable = false; - location.locationType = type; - location.suburb = str; - location.reason = reason; - return location; - } +// +// private static Location UNUSABLE(Reason reason, String str, LocationType type) { +// Location location = new Location(); +// location.usable = false; +// location.locationType = type; +// location.suburb = str; +// location.reason = reason; +// return location; +// } public String toDbString() { switch(locationType){ - case Channel: - return this.channel.aliases.get(0); case Suburb: return this.suburb; case Geofence: diff --git a/src/core/LocationType.java b/src/core/LocationType.java index 7b1f0cf..5daf02b 100644 --- a/src/core/LocationType.java +++ b/src/core/LocationType.java @@ -4,7 +4,6 @@ * Created by Owner on 25/06/2017. */ public enum LocationType { - Channel, Suburb, Region, Geofence } diff --git a/src/core/MessageListener.java b/src/core/MessageListener.java index b56f184..93ed408 100644 --- a/src/core/MessageListener.java +++ b/src/core/MessageListener.java @@ -25,7 +25,6 @@ import notifier.RaidNotifier; import org.ini4j.Ini; import parser.*; -import pokemon.PokeSpawn; import pokemon.Pokemon; import raids.LobbyManager; import raids.Raid; @@ -40,7 +39,8 @@ import java.util.*; import java.util.concurrent.TimeUnit; -import static net.dv8tion.jda.core.utils.SimpleLog.Level.*; +import static net.dv8tion.jda.core.utils.SimpleLog.Level.DEBUG; +import static net.dv8tion.jda.core.utils.SimpleLog.Level.INFO; public class MessageListener extends ListenerAdapter { @@ -50,24 +50,20 @@ public class MessageListener extends ListenerAdapter private static TextChannel nestsReports; public static Guild guild; public static boolean testing; - private final String regionHelp = "Accepted channels are:\n\nall\nwodenweston = woden-weston = woden-weston-region = woden-weston-supporter\ngungahlin = gungahlin-region = gungahlin-supporter\ninnernorth = inner-north = inner-north-region = inner-north-supporter\nbelconnen = belconnen-region = belconnen-supporter\ninnersouth = inner-south = inner-south-region = inner-south-supporter\ntuggeranong = tuggeranong-region = tuggeranong-supporter\nqueanbeyan = queanbeyan-region = queanbeyan-supporter\nlegacy = legacyrare = legacy-rare = legacy-rare-supporter\nlarvitar = larvitarcandy = larvitar-candy = larvitar-candy-supporter\ndratini = dratinicandy = dratini-candy = dratini-candy-supporter\nmareep = mareepcandy = mareep-candy = mareep-candy-supporter\nultrarare = ultra-rare = ultra-rare-supporter\n100iv = 100-iv = 100% = 100-iv-supporter\nsnorlax = snorlax-supporter\nevent\n0iv = 0-iv = 0% = 0-iv-supporter\ndexfiller = dex-filler\nbigfishlittlerat = big-fish-little-rat = big-fish-little-rat-cardboard-box\n"; - private final String inputFormat = "```!addpokemon ```\nFor as many pokemon and channels as you want. Make sure you include the <>. For more information on regions use the !channellis command"; - private final String nestHelp = "My nest commands are: \n```!nest \n!nest pokemon status\n!nest pokemon\n!reportnest [your text here]\n!confirmed\n!suspected\n!fb or !nestfb\n!map or !nestmap\n!help\n```"; - private final String helpStr = "My commands are: \n```!addpokemon \n!addpokemon pokemon\n!delpokemon \n!delpokemon pokemon\n!clearpokemon \n!clearlocation \n!reset\n!settings\n!help\n!channellist or !channels```"; private static MessageChannel userUpdatesLog; public static final String WHITE_GREEN_CHECK = "\u2705"; - private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); public static Config config; public static SuburbManager suburbs; - HashMap messageMap = new HashMap<>(); + private final HashMap messageMap = new HashMap<>(); public static ArrayList invites = new ArrayList<>(); - static SimpleLog novabotLog = SimpleLog.getLog("novabot"); + public static final SimpleLog novabotLog = SimpleLog.getLog("novabot"); public static JDA jda; public static LobbyManager lobbyManager; @@ -78,7 +74,7 @@ public static void main(final String[] args) { SimpleLog.addFileLogs(new File("std.log"),new File("err.log")); } catch (IOException e) { e.printStackTrace(); - }; + } // DBManager.dbLog.setLevel(DEBUG); @@ -281,8 +277,7 @@ public static void loadConfig() { try { config = new Config( new Ini(new File(testing ? "config.example.ini" : "config.ini")), - new File("gkeys.txt"), - new Ini(new File("formatting.ini")) + new File("gkeys.txt") ); } catch (IOException e) { e.printStackTrace(); @@ -365,7 +360,6 @@ private void alertRaidChats(String[] raidChatIds, String message) { public void onMessageDelete(MessageDeleteEvent event) { if(!config.loggingEnabled()) return; - JDA jda = event.getJDA(); final long id = event.getMessageIdLong(); TextChannel channel = event.getGuild().getTextChannelById(event.getChannel().getId()); @@ -425,8 +419,6 @@ public void onGuildMemberRoleRemove(final GuildMemberRoleRemoveEvent event) { public void onGuildMemberJoin(final GuildMemberJoinEvent event) { if(!config.loggingEnabled()) return; - - final JDA jda = event.getJDA(); final Member member = event.getMember(); guild.getInvites().queue(success -> { @@ -480,7 +472,6 @@ public void onGuildMemberJoin(final GuildMemberJoinEvent event) { public void onUserNameUpdate(UserNameUpdateEvent event) { if(!config.loggingEnabled()) return; - final JDA jda = event.getJDA(); final User user = event.getUser(); MessageListener.userUpdatesLog.sendMessage(user.getAsMention() + " has changed their username from " + event.getOldName() + " to " + event.getUser().getName()).queue(); @@ -496,7 +487,6 @@ public void onUserNameUpdate(UserNameUpdateEvent event) { public void onGuildMemberNickChange(final GuildMemberNickChangeEvent event) { if(!config.loggingEnabled()) return; - final JDA jda = event.getJDA(); final User user = event.getMember().getUser(); MessageListener.userUpdatesLog.sendMessage(user.getAsMention() + " has changed their nickname from " + event.getPrevNick() + " to " + event.getNewNick()).queue(); @@ -511,7 +501,6 @@ public void onGuildMemberNickChange(final GuildMemberNickChangeEvent event) { @Override public void onMessageReceived(final MessageReceivedEvent event) { - final JDA jda = event.getJDA(); final User author = event.getAuthor(); final Message message = event.getMessage(); final MessageChannel channel = event.getChannel(); @@ -576,7 +565,6 @@ else if (event.isFromType(ChannelType.PRIVATE)) { if (config.nestsEnabled()) { parseNestMsg(msg,author,channel,ChannelType.PRIVATE); // channel.sendMessage("My nest commands are: \n```!nest \n!nest pokemon status\n!nest pokemon\n!reportnest [your text here]\n!confirmed\n!suspected\n!fb or !nestfb\n!map or !nestmap\n!help\n```").queue(); - return; } } } @@ -597,7 +585,6 @@ private void parseRaidChatMsg(User author, String msg, TextChannel textChannel) if(lobby == null){ textChannel.sendMessageFormat("%s sorry, there are no active raid lobbies with the lobby code `%s`",author,groupCode).queue(); - return; }else{ if(lobby.containsUser(author.getId())){ textChannel.sendMessageFormat("%s you are already in that raid lobby!",author).queue(); @@ -626,7 +613,6 @@ private void parseRaidChatMsg(User author, String msg, TextChannel textChannel) } - return; }else if(msg.equals("!activeraids")) { ArrayList geofences = config.getRaidChatGeofences(textChannel.getId()); @@ -658,7 +644,6 @@ private void parseRaidChatMsg(User author, String msg, TextChannel textChannel) textChannel.sendMessage(noLobbiesMsg).queue(); } - return; } } } @@ -724,7 +709,6 @@ private void parseRaidLobbyMsg(User author, String msg, TextChannel textChannel) if(msg.equals("!code")){ textChannel.sendMessageFormat("This lobby can be joined using the command `!joinraid %s`",lobby.lobbyCode).queue(); - return; } } @@ -746,76 +730,76 @@ private void parseModMsg(Message msg, TextChannel channel) { } } - private void processPokeAlert(FeedChannel feedChannel, Message message) { - MessageEmbed embed = message.getEmbeds().get(0); - - final String msgTitle = embed.getTitle(); - - final int suburbStart = msgTitle.indexOf("[") + 1; - final int suburbEnd = msgTitle.indexOf("]"); - final String suburb = msgTitle.substring(suburbStart, suburbEnd); - - final int pokeStart = suburbEnd + 2; - final int pokeEnd; - if (!msgTitle.contains("Unown")) { - pokeEnd = msgTitle.length(); - } else { - pokeEnd = msgTitle.substring(pokeStart).indexOf(" ") + pokeStart; - } - final String pokeName = msgTitle.substring(pokeStart, pokeEnd).toLowerCase().trim(); - - String form = null; - if (pokeName.equals("Unown")) { - final int formStart = msgTitle.substring(pokeEnd).indexOf("[") + pokeEnd; - form = msgTitle.substring(formStart, formStart + 1); - } - - final String msgBody = embed.getDescription(); - - final int timeEnd = msgBody.indexOf(")**"); - - final int ivStart = msgBody.substring(timeEnd).indexOf("(") + timeEnd + 1; - final int ivEnd = msgBody.indexOf("%"); - final String ivStr = msgBody.substring(ivStart, ivEnd); - final float pokeIV = ivStr.equals("?") ? 0 : Float.parseFloat(msgBody.substring(ivStart, ivEnd)); - - final int cpStart = msgBody.indexOf("CP: ") + 4; - int cpEnd; - if (msgBody.contains("(lvl ")) { - cpEnd = msgBody.substring(cpStart).indexOf("(lvl") + cpStart; - }else{ - cpEnd = msgBody.substring(cpStart).indexOf("Lvl") + cpStart; - } - - final String cpStr = msgBody.substring(cpStart, cpEnd).trim(); - int cp = 0; - - try { - cp = cpStr.equals("?") ? 0 : Integer.parseInt(cpStr); - } catch (NumberFormatException e) { - novabotLog.log(FATAL, feedChannel + ", " + msgTitle); - novabotLog.log(FATAL, msgBody); - e.printStackTrace(); - } - - final int moveSetStart = msgBody.indexOf("Moveset: ") + 9; - final int moveSetEnd = msgBody.indexOf("Gender: "); - final int moveSetSplit = msgBody.substring(moveSetStart, moveSetEnd).indexOf("-") + moveSetStart; - - final String move_1 = msgBody.substring(moveSetStart, moveSetSplit).trim().toLowerCase(); - final String move_2 = msgBody.substring(moveSetSplit + 2, moveSetEnd).trim().toLowerCase(); - - final PokeSpawn pokeSpawn = new PokeSpawn(Pokemon.nameToID(pokeName), feedChannel, suburb, pokeIV, move_1, move_2, form, cp); - novabotLog.log(DEBUG, pokeSpawn.toString()); - final ArrayList ids = DBManager.getUserIDsToNotify(pokeSpawn); - - if (!testing) { - novabotLog.log(DEBUG, "alerting non-supporters"); - this.alertPublic(message, ids); - } else { - jda.getUserById("107730875596169216").openPrivateChannel().queue(success -> success.sendMessage(message).queue()); - } - } +// private void processPokeAlert(FeedChannel feedChannel, Message message) { +// MessageEmbed embed = message.getEmbeds().get(0); +// +// final String msgTitle = embed.getTitle(); +// +// final int suburbStart = msgTitle.indexOf("[") + 1; +// final int suburbEnd = msgTitle.indexOf("]"); +// final String suburb = msgTitle.substring(suburbStart, suburbEnd); +// +// final int pokeStart = suburbEnd + 2; +// final int pokeEnd; +// if (!msgTitle.contains("Unown")) { +// pokeEnd = msgTitle.length(); +// } else { +// pokeEnd = msgTitle.substring(pokeStart).indexOf(" ") + pokeStart; +// } +// final String pokeName = msgTitle.substring(pokeStart, pokeEnd).toLowerCase().trim(); +// +// String form = null; +// if (pokeName.equals("Unown")) { +// final int formStart = msgTitle.substring(pokeEnd).indexOf("[") + pokeEnd; +// form = msgTitle.substring(formStart, formStart + 1); +// } +// +// final String msgBody = embed.getDescription(); +// +// final int timeEnd = msgBody.indexOf(")**"); +// +// final int ivStart = msgBody.substring(timeEnd).indexOf("(") + timeEnd + 1; +// final int ivEnd = msgBody.indexOf("%"); +// final String ivStr = msgBody.substring(ivStart, ivEnd); +// final float pokeIV = ivStr.equals("?") ? 0 : Float.parseFloat(msgBody.substring(ivStart, ivEnd)); +// +// final int cpStart = msgBody.indexOf("CP: ") + 4; +// int cpEnd; +// if (msgBody.contains("(lvl ")) { +// cpEnd = msgBody.substring(cpStart).indexOf("(lvl") + cpStart; +// }else{ +// cpEnd = msgBody.substring(cpStart).indexOf("Lvl") + cpStart; +// } +// +// final String cpStr = msgBody.substring(cpStart, cpEnd).trim(); +// int cp = 0; +// +// try { +// cp = cpStr.equals("?") ? 0 : Integer.parseInt(cpStr); +// } catch (NumberFormatException e) { +// novabotLog.log(FATAL, feedChannel + ", " + msgTitle); +// novabotLog.log(FATAL, msgBody); +// e.printStackTrace(); +// } +// +// final int moveSetStart = msgBody.indexOf("Moveset: ") + 9; +// final int moveSetEnd = msgBody.indexOf("Gender: "); +// final int moveSetSplit = msgBody.substring(moveSetStart, moveSetEnd).indexOf("-") + moveSetStart; +// +// final String move_1 = msgBody.substring(moveSetStart, moveSetSplit).trim().toLowerCase(); +// final String move_2 = msgBody.substring(moveSetSplit + 2, moveSetEnd).trim().toLowerCase(); +// +// final PokeSpawn pokeSpawn = new PokeSpawn(Pokemon.nameToID(pokeName), suburb, pokeIV, move_1, move_2, form, cp); +// novabotLog.log(DEBUG, pokeSpawn.toString()); +// final ArrayList ids = DBManager.getUserIDsToNotify(pokeSpawn); +// +// if (!testing) { +// novabotLog.log(DEBUG, "alerting non-supporters"); +// this.alertPublic(message, ids); +// } else { +// jda.getUserById("107730875596169216").openPrivateChannel().queue(success -> success.sendMessage(message).queue()); +// } +// } private void parseNestMsg(final String msg, final User author, final MessageChannel channel, final ChannelType channelType) { if (!msg.startsWith("!")) { @@ -824,11 +808,11 @@ private void parseNestMsg(final String msg, final User author, final MessageChan switch (msg) { case "!fb": case "!nestfb": - channel.sendMessage("https://www.facebook.com/groups/PogoCBRNests/").queue(); + channel.sendMessage(NEST_FB_GROUP).queue(); break; case "!map": case "!nestmap": - channel.sendMessage("http://www.google.com/maps/d/u/0/viewer?mid=1d-QuaDK1tJRiHKODXErTQIDqIAY").queue(); + channel.sendMessage(NEST_MAP).queue(); break; case "!help": channel.sendMessage("My nest commands are: \n```!nest \n!nest pokemon status\n!nest pokemon\n!reportnest [your text here]\n!confirmed\n!suspected\n!fb or !nestfb\n!map or !nestmap\n!help\n```").queue(); @@ -843,6 +827,7 @@ private void parseNestMsg(final String msg, final User author, final MessageChan if (msg.startsWith("!reportnest")) { final String report = msg.substring(msg.indexOf(" ") + 1); MessageListener.nestsReports.sendMessage(author.getAsMention() + " reported: \"" + report + "\"").queue(); + channel.sendMessageFormat("Thanks for your report, %s! It's been passed on to our team.",author).queue(); return; } if (msg.startsWith("!confirmed")) { @@ -961,7 +946,7 @@ private void alertPublic(final Message message, final ArrayList userIDs) } if (DBManager.countPokemon(userID, config.countLocationsInLimits()) > 3) { Member member = MessageListener.guild.getMemberById(userID); - if(member == null) continue;; + if(member == null) continue; final User user = member.getUser(); if (!user.hasPrivateChannel()) { @@ -1049,7 +1034,7 @@ private void parseMsg(final String msg, final User author, final MessageChannel return; } - if(msg.startsWith("!joinraid")){ + if(msg.startsWith("!joinraid") && config.isRaidOrganisationEnabled()){ String groupCode = msg.substring(msg.indexOf("raid ") + 5).trim(); RaidLobby lobby = lobbyManager.getLobby(groupCode); @@ -1106,7 +1091,7 @@ private void parseMsg(final String msg, final User author, final MessageChannel } } return; - }else if (msg.equals("!pokemonsettings")){ + }else if (msg.equals("!pokemonsettings") && config.pokemonEnabled()){ final UserPref userPref = DBManager.getUserPref(author.getId()); novabotLog.log(DEBUG,"!pokemonsettings"); if (userPref == null || userPref.isPokeEmpty()) { @@ -1123,7 +1108,7 @@ private void parseMsg(final String msg, final User author, final MessageChannel } } return; - }else if(msg.equals("!raidsettings")){ + }else if(msg.equals("!raidsettings") && config.raidsEnabled()){ final UserPref userPref = DBManager.getUserPref(author.getId()); novabotLog.log(DEBUG,"!raidsettings"); if (userPref == null || userPref.isRaidEmpty()) { @@ -1140,16 +1125,40 @@ private void parseMsg(final String msg, final User author, final MessageChannel } } return; + }else if(config.presets.size() > 0 && (msg.equals("!presetsettings"))){ + UserPref userPref = DBManager.getUserPref(author.getId()); + novabotLog.log(DEBUG,"!presetsettings"); + if (userPref == null || userPref.isPresetEmpty()){ + channel.sendMessage(String.format("%s, you don't have any presets loaded. Add some with the !loadpreset command.",author.getAsMention())).queue(); + }else{ + String toSend = String.format("%s, you are currently set to receive notifications from these presets:%n%n%s",author.getAsMention(),userPref.allPresetsToString()); + MessageBuilder builder = new MessageBuilder(); + builder.append(toSend); + Queue messages = builder.buildAll(MessageBuilder.SplitPolicy.NEWLINE); + for (final Message message : messages) { + channel.sendMessage(message).queue(); + } + } + return; + }else if(config.presets.size() > 0 && (msg.equals("!presets") || msg.equals("!presetlist"))){ + MessageBuilder builder = new MessageBuilder(); + builder.appendFormat("%s, accepted presets are:%n%s",author,config.getPresetsList()); + + Queue messages = builder.buildAll(MessageBuilder.SplitPolicy.NEWLINE); + for (final Message message : messages) { + channel.sendMessage(message).queue(); + } + return; } else if (msg.equals("!reset")) { DBManager.resetUser(author.getId()); channel.sendMessage(author.getAsMention() + ", all your notification settings have been reset").queue(); return; - }else if(msg.equals("!resetpokemon")){ + }else if(msg.equals("!resetpokemon") && config.pokemonEnabled()){ DBManager.resetPokemon(author.getId()); channel.sendMessage(author.getAsMention() + ", your pokemon notification settings have been reset").queue(); return; - }else if(msg.equals("!resetraids")){ + }else if(msg.equals("!resetraids") && config.raidsEnabled()){ DBManager.resetRaids(author.getId()); channel.sendMessage(author.getAsMention() + ", your raid notification settings have been reset").queue(); return; @@ -1214,6 +1223,12 @@ else if (msg.equals("!help")) { "!clearraidlocation \n" + "!raidsettings\n" + "!resetraids```" : "") + + (config.presets.size() > 0 ? + "**Preset Commands:**" + + "```!loadpreset \n" + + "!delpreset \n" + + "!presetsettings\n" + + "!presetlist or !presets```" : "") + "**Other Commands:**" + "```!clearlocation \n" + "!pause\n" + @@ -1224,11 +1239,11 @@ else if (msg.equals("!help")) { || channel.getType() == ChannelType.PRIVATE ? "!joinraid \n" : "") + - (config.isRaidOrganisationEnabled() - && config.getRaidChatGeofences(channel.getLatestMessageId()).size() > 0 - || channel.getType() == ChannelType.PRIVATE - ? "!!activeraids\n" - : "") + +// (config.isRaidOrganisationEnabled() +// && config.getRaidChatGeofences(channel.getLatestMessageId()).size() > 0 +// || channel.getType() == ChannelType.PRIVATE +// ? "!!activeraids\n" +// : "") + "!reset\n" + "!settings\n" + (config.useGeofences() ? "!regionlist or !regions\n" : "") + @@ -1260,7 +1275,7 @@ else if (msg.equals("!help")) { if(cmdStr.equals("!stats")){ Pokemon[] pokemons = userCommand.buildPokemon(); - String str = author.getAsMention() + ", here's what I found:\n\n"; + StringBuilder str = new StringBuilder(author.getAsMention() + ", here's what I found:\n\n"); for (Pokemon pokemon : pokemons) { @@ -1270,16 +1285,16 @@ else if (msg.equals("!help")) { int count = DBManager.countSpawns(pokemon.getID(),timeUnit,intervalLength); - str+= String.format(" %s %s%s have been seen in the last %s %s%n%n", + str.append(String.format(" %s %s%s have been seen in the last %s %s%n%n", count, pokemon.name, count == 1 ? "" : "s", intervalLength, - timeUnit.toString().toLowerCase()); + timeUnit.toString().toLowerCase())); } - channel.sendMessage(str).queue(); + channel.sendMessage(str.toString()).queue(); return; } @@ -1290,100 +1305,106 @@ else if (msg.equals("!help")) { ArrayList nonRaidBosses = new ArrayList<>(); for (Pokemon pokemon : userCommand.getUniquePokemon()) { - if(!Raid.POSSIBLE_BOSSES.contains(pokemon.getID())){ + if(!config.raidBosses.contains(pokemon.getID())){ nonRaidBosses.add(Pokemon.idToName(pokemon.getID())); } } if(nonRaidBosses.size() != 0){ - String message = author.getAsMention() + " I had a problem reading your input.\n\n" + - "The following pokemon you entered are not possible raid bosses:\n\n"; + StringBuilder message = new StringBuilder(author.getAsMention() + " I had a problem reading your input.\n\n" + + "The following pokemon you entered are not possible raid bosses:\n\n"); for (String nonRaidBoss : nonRaidBosses) { - message += String.format(" %s%n", nonRaidBoss); + message.append(String.format(" %s%n", nonRaidBoss)); } - channel.sendMessage(message).queue(); + channel.sendMessage(message.toString()).queue(); return; } - if(cmdStr.equals("!addraid")){ - NotificationLimit limit = config.getNotificationLimit(guild.getMember(author)); + switch (cmdStr) { + case "!addraid": { + NotificationLimit limit = config.getNotificationLimit(guild.getMember(author)); - boolean isSupporter = isSupporter(author.getId()); - if ((!isSupporter || limit == null) && - DBManager.countRaids(author.getId(), config.countLocationsInLimits()) + raids.length - > config.getNonSupporterLimit().raidLimit) { - channel.sendMessageFormat("%s as a non-supporter, you may have a maximum of %s raid notifications set up. " + - "What you tried to add would put you over this limit, please remove some raids with the !delraid command or try adding fewer raids.", - author,config.getNonSupporterLimit().raidLimit).queue(); - return; - } + boolean isSupporter = isSupporter(author.getId()); + if ((!isSupporter || limit == null) && + DBManager.countRaids(author.getId(), config.countLocationsInLimits()) + raids.length + > config.getNonSupporterLimit().raidLimit) { + channel.sendMessageFormat("%s as a non-supporter, you may have a maximum of %s raid notifications set up. " + + "What you tried to add would put you over this limit, please remove some raids with the !delraid command or try adding fewer raids.", + author, config.getNonSupporterLimit().raidLimit).queue(); + return; + } - if(limit != null && limit.raidLimit != -1 && DBManager.countRaids(author.getId(), config.countLocationsInLimits()) + raids.length > limit.raidLimit) { - channel.sendMessageFormat("%s at your supporter level you may have a maximum of %s raid notifications set up. " + - "What you tried to add would take you over this limit, please remove some raids with the !delraid command or try adding fewer raids.",author,limit.raidLimit).queue(); - return; - }else if(limit == null && isSupporter){ - novabotLog.fatal(String.format("LIMIT IS NULL: %s, is supporter: %s", author.getName(),isSupporter)); - } + if (limit != null && limit.raidLimit != -1 && DBManager.countRaids(author.getId(), config.countLocationsInLimits()) + raids.length > limit.raidLimit) { + channel.sendMessageFormat("%s at your supporter level you may have a maximum of %s raid notifications set up. " + + "What you tried to add would take you over this limit, please remove some raids with the !delraid command or try adding fewer raids.", author, limit.raidLimit).queue(); + return; + } else if (limit == null && isSupporter) { + novabotLog.fatal(String.format("LIMIT IS NULL: %s, is supporter: %s", author.getName(), isSupporter)); + } - if(!DBManager.containsUser(author.getId())){ - DBManager.addUser(author.getId()); - } + if (!DBManager.containsUser(author.getId())) { + DBManager.addUser(author.getId()); + } - for (Raid raid : raids) { - novabotLog.log(DEBUG,"adding raid " + raid); - DBManager.addRaid(author.getId(),raid); - } + for (Raid raid : raids) { + novabotLog.log(DEBUG, "adding raid " + raid); + DBManager.addRaid(author.getId(), raid); + } - String message2 = author.getAsMention() + " you will now be notified of " + Pokemon.listToString(userCommand.getUniquePokemon()); + String message2 = author.getAsMention() + " you will now be notified of " + Pokemon.listToString(userCommand.getUniquePokemon()); - final Argument locationsArg = userCommand.getArg(ArgType.Locations); - Location[] locations = {new Location(Region.All)}; - if (locationsArg != null) { - locations = userCommand.getLocations(); - } - message2 = message2 + " raids in " + Location.listToString(locations); - channel.sendMessage(message2).queue(); + final Argument locationsArg = userCommand.getArg(ArgType.Locations); + Location[] locations = {new Location(Region.All)}; + if (locationsArg != null) { + locations = userCommand.getLocations(); + } + message2 = message2 + " raids in " + Location.listToString(locations); + channel.sendMessage(message2).queue(); - return; - }else if(cmdStr.equals("!delraid")){ - if(!DBManager.containsUser(author.getId())){ - DBManager.addUser(author.getId()); + return; } + case "!delraid": { + if (!DBManager.containsUser(author.getId())) { + DBManager.addUser(author.getId()); + } - for (Raid raid : raids) { - novabotLog.log(DEBUG,"deleting raid " + raid); - DBManager.deleteRaid(author.getId(),raid); - } + for (Raid raid : raids) { + novabotLog.log(DEBUG, "deleting raid " + raid); + DBManager.deleteRaid(author.getId(), raid); + } - String message2 = author.getAsMention() + " you will no longer be notified of " + Pokemon.listToString(userCommand.getUniquePokemon()); + String message2 = author.getAsMention() + " you will no longer be notified of " + Pokemon.listToString(userCommand.getUniquePokemon()); - final Argument locationsArg = userCommand.getArg(ArgType.Locations); - Location[] locations = {new Location(Region.All)}; - if (locationsArg != null) { - locations = userCommand.getLocations(); - } - message2 = message2 + " raids in " + Location.listToString(locations); - channel.sendMessage(message2).queue(); + final Argument locationsArg = userCommand.getArg(ArgType.Locations); + Location[] locations = {new Location(Region.All)}; + if (locationsArg != null) { + locations = userCommand.getLocations(); + } + message2 = message2 + " raids in " + Location.listToString(locations); + channel.sendMessage(message2).queue(); - return; - }else if(cmdStr.equals("!clearraid")){ - if(!DBManager.containsUser(author.getId())){ - DBManager.addUser(author.getId()); + return; } - novabotLog.log(DEBUG,"clearing raids " + raids); - DBManager.clearRaid(author.getId(),new ArrayList<>(Arrays.asList(raids))); + case "!clearraid": { + if (!DBManager.containsUser(author.getId())) { + DBManager.addUser(author.getId()); + } + novabotLog.log(DEBUG, "clearing raids " + raids); + DBManager.clearRaid(author.getId(), new ArrayList<>(Arrays.asList(raids))); - String message2 = String.format("%s you will no longer be notified of %s in any location", author.getAsMention(), Pokemon.listToString(userCommand.getUniquePokemon())); - channel.sendMessage(message2).queue(); - return; - }else if(cmdStr.equals("!clearraidlocation")){ - final Location[] locations2 = userCommand.getLocations(); - DBManager.clearLocationsRaids(author.getId(), locations2); - final String message2 = author.getAsMention() + " you will no longer be notified of any raids in " + Location.listToString(locations2); - channel.sendMessage(message2).queue(); + String message2 = String.format("%s you will no longer be notified of %s in any location", author.getAsMention(), Pokemon.listToString(userCommand.getUniquePokemon())); + channel.sendMessage(message2).queue(); + return; + } + case "!clearraidlocation": { + final Location[] locations2 = userCommand.getLocations(); + DBManager.clearLocationsRaids(author.getId(), locations2); + final String message2 = author.getAsMention() + " you will no longer be notified of any raids in " + Location.listToString(locations2); + channel.sendMessage(message2).queue(); + break; + } } } @@ -1399,24 +1420,24 @@ else if (msg.equals("!help")) { && DBManager.countPokemon(author.getId(), config.countLocationsInLimits()) + pokemons.length > config.getNonSupporterLimit().pokemonLimit) { channel.sendMessageFormat("%s as a non-supporter, you may have a maximum of %s pokemon notifications set up." + - " What you tried to add would put you over this limit, please remove some pokemon with the !delpokemon command or try adding fewer pokemon.", - author,config.getNonSupporterLimit().pokemonLimit).queue(); + " What you tried to add would put you over this limit, please remove some pokemon with the !delpokemon command or try adding fewer pokemon.", + author, config.getNonSupporterLimit().pokemonLimit).queue(); return; } - if(limit != null && limit.pokemonLimit != -1 && DBManager.countPokemon(author.getId(), config.countLocationsInLimits()) + pokemons.length > limit.pokemonLimit) { + if (limit != null && limit.pokemonLimit != -1 && DBManager.countPokemon(author.getId(), config.countLocationsInLimits()) + pokemons.length > limit.pokemonLimit) { channel.sendMessageFormat("%s at your supporter level you may have a maximum of %s pokemon notifications set up. " + - "What you tried to add would take you over this limit, please remove some pokemon with the !delpokemon command or try adding fewer pokemon.",author,limit.pokemonLimit).queue(); + "What you tried to add would take you over this limit, please remove some pokemon with the !delpokemon command or try adding fewer pokemon.", author, limit.pokemonLimit).queue(); return; - }else if(limit == null && isSupporter){ - novabotLog.fatal(String.format("LIMIT IS NULL: %s, is supporter: %s", author.getName(),isSupporter)); + } else if (limit == null && isSupporter) { + novabotLog.fatal(String.format("LIMIT IS NULL: %s, is supporter: %s", author.getName(), isSupporter)); } if (!DBManager.containsUser(author.getId())) { DBManager.addUser(author.getId()); } for (final Pokemon pokemon : pokemons) { - novabotLog.log(DEBUG,"adding pokemon " + pokemon); + novabotLog.log(DEBUG, "adding pokemon " + pokemon); DBManager.addPokemon(author.getId(), pokemon); } String message2 = author.getAsMention() + " you will now be notified of " + Pokemon.listToString(userCommand.getUniquePokemon()); @@ -1460,6 +1481,44 @@ else if (msg.equals("!help")) { channel.sendMessage(message2).queue(); } } + }else if (cmdStr.contains("preset")){ + switch (cmdStr){ + case "!loadpreset": { + String presetName = (String) userCommand.getArg(ArgType.Preset).getParams()[0]; + String message = String.format("%s you will now be notified of anything in the %s preset", author.getAsMention(), presetName); + + final Argument locationsArg = userCommand.getArg(ArgType.Locations); + Location[] locations = {new Location(Region.All)}; + if (locationsArg != null) { + locations = userCommand.getLocations(); + } + + for (Location location : locations) { + DBManager.addPreset(author.getId(), presetName, location); + } + + message += " in " + Location.listToString(locations); + channel.sendMessage(message).queue(); + return; + } + case "!delpreset":{ + String presetName = (String) userCommand.getArg(ArgType.Preset).getParams()[0]; + String message = String.format("%s you will no longer be notified of anything in the %s preset",author.getAsMention(),presetName); + + final Argument locationsArg = userCommand.getArg(ArgType.Locations); + Location[] locations = {new Location(Region.All)}; + if (locationsArg != null) { + locations = userCommand.getLocations(); + } + + for (Location location : locations) { + DBManager.deletePreset(author.getId(),presetName,location); + } + + message += " in " + Location.listToString(locations); + channel.sendMessage(message).queue(); + } + } }else if(cmdStr.equals("!clearlocation")){ final Location[] locations2 = userCommand.getLocations(); DBManager.clearLocationsPokemon(author.getId(), locations2); diff --git a/src/core/NotificationLimit.java b/src/core/NotificationLimit.java index ff6f350..8c2e73e 100644 --- a/src/core/NotificationLimit.java +++ b/src/core/NotificationLimit.java @@ -5,10 +5,10 @@ */ public class NotificationLimit { - public int pokemonLimit; - public int raidLimit; + public final int pokemonLimit; + public final int raidLimit; - public NotificationLimit(int pokemonLimit, int raidLimit){ + private NotificationLimit(int pokemonLimit, int raidLimit){ this.pokemonLimit = pokemonLimit; this.raidLimit = raidLimit; } diff --git a/src/core/Preset.java b/src/core/Preset.java new file mode 100644 index 0000000..458e947 --- /dev/null +++ b/src/core/Preset.java @@ -0,0 +1,11 @@ +package core; + +class Preset { + private final String presetName; + private final Location location; + + public Preset (String name, Location location){ + this.presetName = name; + this.location = location; + } +} diff --git a/src/core/RaidChannel.java b/src/core/RaidChannel.java new file mode 100644 index 0000000..156e330 --- /dev/null +++ b/src/core/RaidChannel.java @@ -0,0 +1,10 @@ +package core; + +class RaidChannel extends AlertChannel { + + public Integer minLevel; + + public RaidChannel(String channelId) { + super(channelId); + } +} diff --git a/src/core/Reason.java b/src/core/Reason.java deleted file mode 100644 index 5556279..0000000 --- a/src/core/Reason.java +++ /dev/null @@ -1,20 +0,0 @@ -package core; - -/** - * Created by Owner on 27/06/2017. - */ -public enum Reason { - SupporterAttemptedPublic, - PublicAttemptedGeofence; - - @Override - public String toString() { - switch (this){ - case SupporterAttemptedPublic: - return "Trying to use a public channel as a supporter"; - case PublicAttemptedGeofence: - return "Trying to use a geofence region as a public user"; - } - return ""; - } -} diff --git a/src/core/Region.java b/src/core/Region.java index 9e02a82..2ba2384 100644 --- a/src/core/Region.java +++ b/src/core/Region.java @@ -5,32 +5,6 @@ public enum Region All, Regional, QueanbeyanRegion, TuggeranongRegion, BelconnenRegion, GungahlinRegion, InnerNorth, InnerSouth, WodenWeston; - public static Region fromDbString(final String regionStr) { - switch (regionStr) { -// case "dratini": { -// return Region.DratiniCandy; -// } -// case "larvitar": { -// return Region.LarvitarCandy; -// } -// case "snorlax": { -// return Region.SnorlaxCandy; -// } -// case "mareep": { -// return Region.MareepCandy; -// } -// case "hundrediv": { -// return Region.Hundrediv; -// } -// case "zeroiv": { -// return Region.Zeroiv; -// } - default: { - return fromString(regionStr); - } - } - } - public static Region fromNestString(final String regionStr) { switch (regionStr) { case "gungahlin": { @@ -60,114 +34,20 @@ public static Region fromNestString(final String regionStr) { } } - public static Region fromString(final String regionStr) { + private static Region fromString(final String regionStr) { if (regionStr.equals("all")) { return Region.All; } if (regionStr.equals("regional")) { return Region.Regional; } -// if (regionStr.equals("woden-weston") || regionStr.equals("wodenweston") || regionStr.equals("woden-weston-supporter") || regionStr.equals("woden-weston-region") || regionStr.equals("woden/weston")) { -// return Region.Wodenweston; -// } -// if (regionStr.equals("belconnenregion") || regionStr.equals("belconnen-supporter") || regionStr.equals("belconnen-region")) { -// return Region.BelconnenRegion; -// } -// if (regionStr.equals("innernorth") || regionStr.equals("inner-north") || regionStr.equals("inner-north-supporter") || regionStr.equals("inner-north-region") || regionStr.equals("inner north")) { -// return Region.Innernorth; -// } -// if (regionStr.equals("innersouth") || regionStr.equals("inner-south") || regionStr.equals("inner-south-supporter") || regionStr.equals("inner-south-region") || regionStr.equals("inner south")) { -// return Region.Innersouth; -// } -// if (regionStr.equals("gungahlinregion") || regionStr.equals("gungahlin-region") || regionStr.equals("gungahlin-supporter")) { -// return Region.GungahlinRegion; -// } -// if (regionStr.equals("tuggeranongregion") || regionStr.equals("tuggeranong-region") || regionStr.equals("tuggeranong-supporter")) { -// return Region.TuggeranongRegion; -// } -// if (regionStr.equals("queanbeyanregion") || regionStr.equals("queanbeyan-region") || regionStr.equals("queanbeyan-supporter")) { -// return Region.QueanbeyanRegion; -// } -// if (regionStr.equals("legacy") || regionStr.equals("legacyrare") || regionStr.equals("legacy-rare") || regionStr.equals("legacy-rare-supporters")) { -// return Region.Legacyrare; -// } -// if (regionStr.equals("larvitarcandy") || regionStr.equals("larvitar-candy") || regionStr.equals("larvitar-candy-supporter")) { -// return Region.LarvitarCandy; -// } -// if (regionStr.equals("dratinicandy") || regionStr.equals("dratini-candy") || regionStr.equals("dratini-candy-supporter")) { -// return Region.DratiniCandy; -// } -// if (regionStr.equals("mareepcandy") || regionStr.equals("mareep-candy") || regionStr.equals("mareep-candy-supporter")) { -// return Region.MareepCandy; -// } -// if (regionStr.equals("ultrarare") || regionStr.equals("ultra-rare") || regionStr.equals("ultra-rare-supporter")) { -// return Region.Ultrarare; -// } -// if (regionStr.equals("100iv") || regionStr.equals("100%") || regionStr.equals("100-iv-supporter") || regionStr.equals("100-iv")) { -// return Region.Hundrediv; -// } -// if (regionStr.equals("snorlaxcandy") || regionStr.equals("snorlax-supporter") || regionStr.equals("snorlax-candy")) { -// return Region.SnorlaxCandy; -// } -// if (regionStr.equals("event")) { -// return Region.Event; -// } -// if (regionStr.equals("0iv") || regionStr.equals("0%") || regionStr.equals("0-iv") || regionStr.equals("0-iv-supporter")) { -// return Region.Zeroiv; -// } -// if (regionStr.equals("dexfiller") || regionStr.equals("dex-filler")) { -// return Region.Dexfiller; -// } -// if (regionStr.equals("bigfishlittlerat") || regionStr.equals("big-fish-little-rat") || regionStr.equals("big-fish-little-rat-cardboard-box")) { -// return Region.BigFishLittleRat; -// } -// if (regionStr.equals("unownalphabet") || regionStr.equals("unown-alphabet")) -// return UnownAlphabet; return null; } public String toWords() { switch (this) { -// case Innernorth: -// return "inner north"; -// case Innersouth: -// return "inner south"; -// case GungahlinRegion: -// return "gungahlin region"; -// case BelconnenRegion: -// return "belconnen region"; -// case Wodenweston: -// return "woden-weston"; -// case TuggeranongRegion: -// return "tuggeranong region"; -// case QueanbeyanRegion: -// return "queanbeyan region"; -// case Hundrediv: -// return "100% iv"; -// case DratiniCandy: -// return "dratini candy"; -// case MareepCandy: -// return "mareep candy"; -// case SnorlaxCandy: -// return "snorlax"; -// case LarvitarCandy: -// return "larvitar candy"; -// case Legacyrare: -// return "legacy rare"; -// case Ultrarare: -// return "ultra rare"; -// case Event: -// return "event"; case All: return "all"; -// case Zeroiv: -// return "0% iv"; -// case Dexfiller: -// return "dex filler"; -// case BigFishLittleRat: -// return "big fish little rat"; -// case UnownAlphabet: -// return "unown alphabet"; default: return ""; } diff --git a/src/core/RotatingSet.java b/src/core/RotatingSet.java index 0757f5c..6e2665d 100644 --- a/src/core/RotatingSet.java +++ b/src/core/RotatingSet.java @@ -11,7 +11,7 @@ public class RotatingSet extends HashSet { private final int maxSize; - private ArrayList objects; + private final ArrayList objects; public RotatingSet(int size){ this.maxSize = size; diff --git a/src/core/ScheduledExecutor.java b/src/core/ScheduledExecutor.java index 79fd07b..fda240f 100644 --- a/src/core/ScheduledExecutor.java +++ b/src/core/ScheduledExecutor.java @@ -33,9 +33,9 @@ private Runnable wrapRunnable(Runnable command) { } private class LogOnExceptionRunnable implements Runnable { - private Runnable theRunnable; + private final Runnable theRunnable; - public LogOnExceptionRunnable(Runnable theRunnable) { + LogOnExceptionRunnable(Runnable theRunnable) { super(); this.theRunnable = theRunnable; } diff --git a/src/core/Spawn.java b/src/core/Spawn.java new file mode 100644 index 0000000..e9d6a3d --- /dev/null +++ b/src/core/Spawn.java @@ -0,0 +1,67 @@ +package core; + +import maps.GeofenceIdentifier; +import net.dv8tion.jda.core.entities.Message; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; + +import static core.MessageListener.config; + +public class Spawn { + public final HashMap properties = new HashMap<>(); + + private String imageUrl; + + protected double lat; + protected double lon; + + public String move_1; + public String move_2; + protected String formatKey = "pokemon"; + + protected ArrayList geofenceIdentifiers = new ArrayList<>(); + + private static int lastKey; + + protected final HashMap builtMessages = new HashMap<>(); + + protected static final SimpleDateFormat printFormat = new SimpleDateFormat("HH:mm:ss"); + + static { + lastKey = 0; + } + + public String getSuburb() { + return properties.get("city"); + } + + public ArrayList getGeofences() { + return geofenceIdentifiers; + } + + public String getImage(String formatFile) { + if (this.imageUrl == null) { + return this.imageUrl = "https://maps.googleapis.com/maps/api/staticmap?" + String.format("zoom=%s&size=%sx%s&markers=color:red|%s,%s&key=%s", config.getMapZoom(formatFile, formatKey), config.getMapWidth(formatFile, formatKey), config.getMapHeight(formatFile, formatKey), this.lat, this.lon, getNextKey()); + } + return this.imageUrl; + } + + private static String getNextKey() { + if (lastKey == config.getKeys().size() - 1) { + lastKey = 0; + return config.getKeys().get(lastKey); + } + ++lastKey; + return config.getKeys().get(lastKey); + } + + protected String getAppleMapsLink() { + return String.format("http://maps.apple.com/maps?daddr=%s,%s&z=10&t=s&dirflg=w", this.lat, this.lon); + } + + protected String getGmapsLink() { + return String.format("https://www.google.com/maps?q=loc:%s,%s", this.lat, this.lon); + } +} diff --git a/src/core/SuburbManager.java b/src/core/SuburbManager.java index 24ffa89..dc3192a 100644 --- a/src/core/SuburbManager.java +++ b/src/core/SuburbManager.java @@ -1,5 +1,7 @@ package core; +import net.dv8tion.jda.core.utils.SimpleLog; + import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; @@ -7,7 +9,7 @@ public class SuburbManager { - private final ArrayList suburbs = new ArrayList(); + private final ArrayList suburbs = new ArrayList<>(); public SuburbManager(File file) { try { @@ -20,7 +22,7 @@ public SuburbManager(File file) { } } catch (FileNotFoundException e) { - e.printStackTrace(); + MessageListener.novabotLog.log(SimpleLog.Level.WARNING, "Couldn't find suburbs.txt, ignoring"); } } diff --git a/src/core/Team.java b/src/core/Team.java new file mode 100644 index 0000000..28b2f75 --- /dev/null +++ b/src/core/Team.java @@ -0,0 +1,49 @@ +package core; + +public enum Team { + Uncontested, + Valor, + Instinct, + Mystic; + + public Team fromString (String s) { + switch (s.toLowerCase()){ + case "valor": + return Valor; + case "instinct": + return Instinct; + case "mystic": + return Mystic; + } + return null; + } + + public static Team fromId(int i) { + switch (i){ + case 0: + return Uncontested; + case 1: + return Mystic; + case 2: + return Valor; + case 3: + return Instinct; + } + return null; + } + + @Override + public String toString() { + switch (this){ + case Uncontested: + return "Uncontested"; + case Valor: + return "Valor"; + case Mystic: + return "Mystic"; + case Instinct: + return "Instinct"; + } + return null; + } +} diff --git a/src/core/Types.java b/src/core/Types.java new file mode 100644 index 0000000..35f6222 --- /dev/null +++ b/src/core/Types.java @@ -0,0 +1,129 @@ +package core; + +import java.util.ArrayList; +import java.util.Arrays; + +public class Types { + + public static ArrayList getStrengths (String type){ + String types[] = new String[0]; + switch (type.toLowerCase()) { + case "normal": + break; + case "fighting": + types = new String[]{"normal","rock","steel","ice","dark"}; + break; + case "flying": + types = new String[]{"fighting", "bug", "grass"}; + break; + case "poison": + types = new String[]{"grass", "fairy"}; + break; + case "ground": + types = new String[]{"poison", "rock", "steel","fire","electric"}; + break; + case "rock": + types = new String[]{"flying", "bug", "fire", "ice"}; + break; + case "bug": + types = new String[]{"grass","psychic","dark"}; + break; + case "ghost": + types = new String[]{"ghost","psychic"}; + break; + case "steel": + types = new String[]{"rock","ice"}; + break; + case "fire": + types = new String[]{"bug","steel","grass","ice"}; + break; + case "water": + types = new String[]{"ground","rock","fire"}; + break; + case "grass": + types = new String[]{"ground","rock","water"}; + break; + case "electric": + types = new String[]{"flying","water"}; + break; + case "psychic": + types = new String[]{"fighting","poison"}; + break; + case "ice": + types = new String[]{"flying","ground","grass","dragon"}; + break; + case "dragon": + types = new String[]{"dragon"}; + break; + case "dark": + types = new String[]{"ghost","psychic"}; + break; + case "fairy": + types = new String[]{"fighting","dragon","dark"}; + break; + } + return new ArrayList<>(Arrays.asList(types)); + } + + public static ArrayList getWeaknesses (String type){ + String types[] = new String[0]; + switch (type.toLowerCase()) { + case "normal": + types = new String[]{"fighting"}; + break; + case "fighting": + types = new String[]{"flying", "psychic", "fairy"}; + break; + case "flying": + types = new String[]{"rock", "electric", "ice"}; + break; + case "poison": + types = new String[]{"ground", "psychic"}; + break; + case "ground": + types = new String[]{"water", "grass", "ice"}; + break; + case "rock": + types = new String[]{"fighting", "ground", "steel", "water", "grass"}; + break; + case "bug": + types = new String[]{"flying", "rock", "fire"}; + break; + case "ghost": + types = new String[]{"ghost", "dark"}; + break; + case "steel": + types = new String[]{"fighting", "ground", "fire"}; + break; + case "fire": + types = new String[]{"ground", "rock", "water"}; + break; + case "water": + types = new String[]{"grass", "electric"}; + break; + case "grass": + types = new String[]{"flying", "poison", "bug", "fire", "ice"}; + break; + case "electric": + types = new String[]{"ground"}; + break; + case "psychic": + types = new String[]{"bug", "ghost", "dark"}; + break; + case "ice": + types = new String[]{"fighting", "rock", "steel", "fire"}; + break; + case "dragon": + types = new String[]{"ice", "dragon", "fairy"}; + break; + case "dark": + types = new String[]{"fighting", "bug", "fairy"}; + break; + case "fairy": + types = new String[]{"poison", "steel"}; + break; + } + return new ArrayList<>(Arrays.asList(types)); + } + +} diff --git a/src/core/UserPref.java b/src/core/UserPref.java index ed43a38..f2ece09 100644 --- a/src/core/UserPref.java +++ b/src/core/UserPref.java @@ -9,22 +9,28 @@ public class UserPref { - public HashMap> pokemonPrefs = new HashMap<>(); - public HashMap> raidPrefs = new HashMap<>(); - private boolean supporter; + private final HashMap> pokemonPrefs = new HashMap<>(); + private final HashMap> raidPrefs = new HashMap<>(); + private final HashMap> presetPrefs = new HashMap<>(); - public UserPref(boolean supporter){ - this.supporter = supporter; + public UserPref() { } - public UserPref() { + public void addPreset(String presetName, Location location){ + if(!this.presetPrefs.containsKey(location.toWords())){ + Set set = new HashSet<>(); + set.add(presetName); + this.presetPrefs.put(location.toWords(),set); + }else{ + presetPrefs.get(location.toWords()).add(presetName); + } } public void addPokemon(final Pokemon pokemon) { Location location = pokemon.getLocation(); if (!this.pokemonPrefs.containsKey(location.toWords())) { - final Set set = new HashSet(); + final Set set = new HashSet<>(); set.add(pokemon); this.pokemonPrefs.put(location.toWords(), set); } @@ -46,40 +52,64 @@ public void addRaid(final Raid raid) { } } + public static void main(String[] args) { + MessageListener.loadConfig(); + MessageListener.loadSuburbs(); + System.out.println(Location.fromDbString("inner-north")); + } + + public String allPresetsToString(){ + StringBuilder str = new StringBuilder(); + for (String locname : presetPrefs.keySet()) { + Location location = Location.fromString(locname); + + String locStr = locname; + if (location != null) { + locStr = location.toWords(); + } + str.append("**").append(locname).append("**:\n"); + for (String preset : presetPrefs.get(locStr)) { + str.append(String.format(" %s%n", preset)); + } + str.append("\n"); + } + return str.toString(); + } + public String allRaidsToString(){ - String str = ""; + StringBuilder str = new StringBuilder(); for (String locname : this.raidPrefs.keySet()) { - Location location = Location.fromString(locname, supporter); + Location location = Location.fromString(locname); String locStr = locname; if (location != null) { locStr = location.toWords(); } - str = str + "**" + locname + "**:\n"; + str.append("**").append(locname).append("**:\n"); for (final Raid raid : this.raidPrefs.get(locStr)) { - str += String.format(" %s%n", Pokemon.idToName(raid.bossId)); + str.append(String.format(" %s%n", Pokemon.idToName(raid.bossId))); } - str += "\n"; + str.append("\n"); } - return str; + return str.toString(); } public String allPokemonToString() { - String str = ""; + StringBuilder str = new StringBuilder(); for (String locname : this.pokemonPrefs.keySet()) { - Location location = Location.fromString(locname, supporter); + Location location = Location.fromString(locname); String locStr = locname; if (location != null) { locStr = location.toWords(); } - str = str + "**" + locname + "**:\n"; + str.append("**").append(locname).append("**:\n"); for (final Pokemon pokemon : this.pokemonPrefs.get(locStr)) { - str += String.format(" %s%n", pokePrefString(pokemon)); + str.append(String.format(" %s%n", pokePrefString(pokemon))); } - str += "\n"; + str.append("\n"); } - return str; + return str.toString(); } private String pokePrefString(Pokemon pokemon) { @@ -101,6 +131,10 @@ private String pokePrefString(Pokemon pokemon) { return str; } + private String presetString(String preset) { + return preset + " preset"; + } + public String allSettingsToString() { HashMap> prefMap = new HashMap<>(); @@ -136,41 +170,65 @@ public String allSettingsToString() { } }); - String str = ""; + presetPrefs.forEach((location,presets) -> { + if (!prefMap.containsKey(location)) { + Set set = new HashSet<>(); + + for (String preset : presets) { + set.add(presetString(preset)); + } + prefMap.put(location,set); + }else{ + for (String preset : presets) { + prefMap.get(location).add(presetString(preset)); + } + } + }); + + StringBuilder str = new StringBuilder(); for (String locname : prefMap.keySet()) { - Location location = Location.fromString(locname, supporter); + Location location = Location.fromString(locname); String locStr = locname; if (location != null) { locStr = location.toWords(); } - str = str + "**" + locname + "**:\n"; + str.append("**").append(locname).append("**:\n"); for (final String string : prefMap.get(locStr)) { - str += String.format(" %s%n", string); + str.append(String.format(" %s%n", string)); } - str += "\n"; + str.append("\n"); } - return str; + return str.toString(); } + public boolean isRaidEmpty() { - final boolean[] empty = { true }; + boolean[] empty = { true }; raidPrefs.forEach((loc, obj) -> { if (obj.size() > 0) { empty[0] = false; } - return; }); return empty[0]; } public boolean isPokeEmpty() { - final boolean[] empty = { true }; + boolean[] empty = { true }; pokemonPrefs.forEach((loc, obj) -> { if (obj.size() > 0) { empty[0] = false; } - return; + }); + return empty[0]; + } + + public boolean isPresetEmpty() { + boolean[] empty = { true }; + presetPrefs.forEach((loc, obj) -> { + if (obj.size() > 0) { + empty[0] = false; + } }); return empty[0]; } diff --git a/src/maps/GeocodedLocation.java b/src/maps/GeocodedLocation.java index 0b000d8..f62be63 100644 --- a/src/maps/GeocodedLocation.java +++ b/src/maps/GeocodedLocation.java @@ -7,7 +7,7 @@ */ public class GeocodedLocation { - private HashMap locationProperties; + private final HashMap locationProperties; public GeocodedLocation(){ locationProperties = new HashMap<>(); diff --git a/src/maps/GeofenceIdentifier.java b/src/maps/GeofenceIdentifier.java index 5c800b9..2026220 100644 --- a/src/maps/GeofenceIdentifier.java +++ b/src/maps/GeofenceIdentifier.java @@ -9,9 +9,9 @@ */ public class GeofenceIdentifier { - public String name; + public final String name; - ArrayList aliases; + private final ArrayList aliases; public GeofenceIdentifier(String name, ArrayList aliases) { this.name = name; diff --git a/src/maps/Geofencing.java b/src/maps/Geofencing.java index 1d2785d..8977e4e 100644 --- a/src/maps/Geofencing.java +++ b/src/maps/Geofencing.java @@ -26,9 +26,9 @@ public class Geofencing // private static final GeoPolygon tuggeranong; // private static final HashMap geofences; - static HashMap geofencesMap = new HashMap<>(); + static final HashMap geofencesMap = new HashMap<>(); - private static SimpleLog geofenceLog = SimpleLog.getLog("Geofencing"); + private static final SimpleLog geofenceLog = SimpleLog.getLog("Geofencing"); public static boolean loaded = false; public static void main(final String[] args) { diff --git a/src/maps/ReverseGeocoder.java b/src/maps/ReverseGeocoder.java index 46287ca..a9c61b5 100644 --- a/src/maps/ReverseGeocoder.java +++ b/src/maps/ReverseGeocoder.java @@ -11,6 +11,7 @@ import static core.MessageListener.config; import static core.MessageListener.loadConfig; +import static net.dv8tion.jda.core.utils.SimpleLog.Level.INFO; public class ReverseGeocoder { @@ -43,9 +44,10 @@ public static GeocodedLocation geocodedLocation(double lat, double lon){ location.set("sublocality","unkn"); location.set("country","unkn"); + String key = getNextKey(); final GeoApiContext context = new GeoApiContext(); try { - context.setApiKey(getNextKey()); + context.setApiKey(key); final GeocodingResult[] results = (GeocodingApi.reverseGeocode(context, new LatLng(lat, lon))).await(); for (final AddressComponent addressComponent : results[0].addressComponents) { final AddressComponentType[] types = addressComponent.types; @@ -80,6 +82,9 @@ public static GeocodedLocation geocodedLocation(double lat, double lon){ } } } + catch (com.google.maps.errors.OverDailyLimitException e){ + MessageListener.novabotLog.log(INFO, String.format("Exceeded daily limit with key %s", key)); + } catch (Exception e) { e.printStackTrace(); } diff --git a/src/nests/NestSheetManager.java b/src/nests/NestSheetManager.java index 0a97154..0903d5a 100644 --- a/src/nests/NestSheetManager.java +++ b/src/nests/NestSheetManager.java @@ -32,7 +32,7 @@ public class NestSheetManager private static HttpTransport HTTP_TRANSPORT; private static final List SCOPES; - private static SimpleLog nestsLog = SimpleLog.getLog("nests"); + private static final SimpleLog nestsLog = SimpleLog.getLog("nests"); public static void main(final String[] args) { final String spreadsheetId = "1Scx_49MhfziXhugkW1SK-6X4gDZ7pA-EMSL-WlV17CM"; diff --git a/src/notifier/PokeNotificationSender.java b/src/notifier/PokeNotificationSender.java index 03b5d06..d34b055 100644 --- a/src/notifier/PokeNotificationSender.java +++ b/src/notifier/PokeNotificationSender.java @@ -1,10 +1,8 @@ package notifier; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; +import core.AlertChannel; import core.DBManager; import core.MessageListener; -import core.PokeChannel; import maps.GeofenceIdentifier; import net.dv8tion.jda.core.JDA; import net.dv8tion.jda.core.entities.Message; @@ -14,19 +12,17 @@ import pokemon.Pokemon; import java.util.ArrayList; -import java.util.Random; +import java.util.HashSet; import static core.MessageListener.config; import static net.dv8tion.jda.core.utils.SimpleLog.Level.INFO; -class PokeNotificationSender implements Runnable { +public class PokeNotificationSender implements Runnable { private final JDA jda; private final ArrayList newPokemon; private final boolean testing; - Random random = new Random(); - - private static SimpleLog notificationLog = SimpleLog.getLog("Poke-Notif-Sender"); + public static final SimpleLog notificationLog = SimpleLog.getLog("Poke-Notif-Sender"); public PokeNotificationSender(final JDA jda, final ArrayList newPokemon, boolean testing) { this.jda = jda; @@ -51,92 +47,65 @@ public void run() { } if (!testing) { - final ArrayList userIDs = DBManager.getUserIDsToNotify(pokeSpawn); - if (userIDs.size() == 0) { + HashSet toNotify = new HashSet<>(DBManager.getUserIDsToNotify(pokeSpawn)); + + ArrayList matchingPresets = config.findMatchingPresets(pokeSpawn); + + for (String preset : matchingPresets) { + toNotify.addAll(DBManager.getUserIDsToNotify(preset,pokeSpawn)); + } + + if (toNotify.size() == 0) { notificationLog.log(INFO, "no-one wants this pokemon"); } else { - final Message message = pokeSpawn.buildMessage(); + final Message message = pokeSpawn.buildMessage("formatting.ini"); notificationLog.log(INFO, "Built message for pokespawn"); if (config.isSupporterOnly()) { - userIDs.stream().filter(MessageListener::isSupporter).forEach(userID -> this.notifyUser(userID, message)); + toNotify.stream().filter(MessageListener::isSupporter).forEach(userID -> this.notifyUser(userID, message)); } else { - userIDs.forEach(userID -> this.notifyUser(userID, message)); + toNotify.forEach(userID -> this.notifyUser(userID, message)); } } - if (pokeSpawn.getGeofenceIds().size() == 0) { - ArrayList noGeofences = config.getNonGeofencedChannels(); - if (noGeofences != null) { - for (PokeChannel channel : config.getNonGeofencedChannels()) { - postToChannel(channel, pokeSpawn); - } + for (GeofenceIdentifier geofenceIdentifier : pokeSpawn.getGeofences()) { + ArrayList channels = config.getAlertChannels(geofenceIdentifier); + if(channels == null) continue; + for (AlertChannel channel : channels) { + checkChannelFilter(channel, pokeSpawn); } - } else { - for (GeofenceIdentifier geofenceIdentifier : pokeSpawn.getGeofenceIds()) { - ArrayList channels = config.getPokeChannels(geofenceIdentifier); - if(channels == null) continue; - for (PokeChannel channel : channels) { - postToChannel(channel, pokeSpawn); - } + } + ArrayList noGeofences = config.getNonGeofencedPokeChannels(); + + if (noGeofences != null) { + for (AlertChannel channel : noGeofences) { + checkChannelFilter(channel, pokeSpawn); } } } else { if (DBManager.shouldNotify("107730875596169216", pokeSpawn)) { - final Message message = pokeSpawn.buildMessage(); + final Message message = pokeSpawn.buildMessage("formatting.ini"); notificationLog.log(INFO, "Built message for pokespawn"); notifyUser("107730875596169216", message); } } } - } - private void postToChannel(PokeChannel channel, PokeSpawn pokeSpawn) { - JsonElement pokeFilter = config.searchPokemonFilter(config.filters.get(channel.filterName), pokeSpawn.id); - if (pokeFilter == null) { - System.out.println(String.format("wtf pokeFilter %s is null for channel with id %s", channel.filterName, channel.channelId)); - return; - } - if (pokeFilter.isJsonObject()) { - JsonObject obj = pokeFilter.getAsJsonObject(); - - JsonElement maxObj = obj.get("max_iv"); - JsonElement minObj = obj.get("min_iv"); - - float max = maxObj == null ? 100 : maxObj.getAsFloat(); - float min = minObj == null ? 0 : minObj.getAsFloat(); - - if (pokeSpawn.iv <= max && pokeSpawn.iv >= min) { - notificationLog.log(INFO, String.format("Pokemon between specified ivs (%s,%s), posting to Discord", min, max)); - sendPublicAlert(pokeSpawn.buildMessage(), pokeSpawn.getGeofenceIds()); - } else { - notificationLog.log(INFO, String.format("Pokemon not specified ivs (%s,%s), posting to Discord", min, max)); - - } - } else { - if (pokeFilter.getAsBoolean()) { - notificationLog.log(INFO, "Pokemon enabled in filter, posting to Discord"); - sendPublicAlert(pokeSpawn.buildMessage(), pokeSpawn.getGeofenceIds()); - } else { - notificationLog.log(INFO, "Pokemon not enabled in filter, not posting"); - } + private void checkChannelFilter(AlertChannel channel, PokeSpawn pokeSpawn) { + if (config.matchesFilter(config.pokeFilters.get(channel.filterName),pokeSpawn, channel.filterName)){ + notificationLog.log(INFO, "Pokemon passed filter, posting to Discord"); + sendPublicAlert(pokeSpawn.buildMessage(channel.formattingName),channel.channelId); + }else{ + notificationLog.log(INFO, String.format("Pokemon didn't pass %s filter, not posting", channel.filterName)); } } - private void sendPublicAlert(Message message, ArrayList geofences) { - notificationLog.log(INFO, "Sending public alert message to geofenced channels"); - for (GeofenceIdentifier identifier : geofences) { - for (PokeChannel channel : config.getPokeChannels(identifier)) { - - notificationLog.log(INFO, String.format("Sending message to channel %s from geofence %s", channel.channelId, identifier)); - - channel.getChannel().sendMessage(message).queue(m -> notificationLog.log(INFO, "Successfully sent message.")); - - } - } + private void sendPublicAlert(Message message, String channelId) { + notificationLog.log(INFO, "Sending public alert message to channel " + channelId); + jda.getTextChannelById(channelId).sendMessage(message).queue(m -> notificationLog.log(INFO, "Successfully sent message.")); } } diff --git a/src/notifier/PokeNotifier.java b/src/notifier/PokeNotifier.java index 62cf96d..0f652aa 100644 --- a/src/notifier/PokeNotifier.java +++ b/src/notifier/PokeNotifier.java @@ -14,7 +14,7 @@ public class PokeNotifier implements Runnable private final JDA jda; private final boolean testing; - private static SimpleLog notifierLog = SimpleLog.getLog("PokeNotifier"); + private static final SimpleLog notifierLog = SimpleLog.getLog("PokeNotifier"); public PokeNotifier(final JDA jda, boolean testing) { this.jda = jda; diff --git a/src/notifier/RaidNotificationSender.java b/src/notifier/RaidNotificationSender.java index a752eab..5934b27 100644 --- a/src/notifier/RaidNotificationSender.java +++ b/src/notifier/RaidNotificationSender.java @@ -1,5 +1,6 @@ package notifier; +import core.AlertChannel; import core.DBManager; import core.MessageListener; import maps.GeofenceIdentifier; @@ -11,10 +12,9 @@ import raids.RaidSpawn; import java.util.ArrayList; +import java.util.HashSet; -import static core.MessageListener.WHITE_GREEN_CHECK; -import static core.MessageListener.config; -import static core.MessageListener.lobbyManager; +import static core.MessageListener.*; import static net.dv8tion.jda.core.utils.SimpleLog.Level.INFO; /** @@ -23,7 +23,7 @@ public class RaidNotificationSender implements Runnable { - private static SimpleLog notificationLog = SimpleLog.getLog("Raid-Notif-Sender"); + public static final SimpleLog notificationLog = SimpleLog.getLog("Raid-Notif-Sender"); private final JDA jda; private final ArrayList currentRaids; private final boolean testing; @@ -98,31 +98,48 @@ public void run() { } } + HashSet toNotify = new HashSet<>(); + if (raidSpawn.bossId != 0) { notificationLog.log(INFO, "Checking if anyone wants: " + raidSpawn); - DBManager.getUserIDsToNotify(raidSpawn).forEach(id -> notifyUser(id, raidSpawn.buildMessage(),raidSpawn.raidLevel >= 3)); + toNotify.addAll(DBManager.getUserIDsToNotify(raidSpawn)); } - if(!config.isRaidChannelsEnabled() || raidSpawn.raidLevel < config.getMinRaidLevel()) continue; + ArrayList matchingPresets = config.findMatchingPresets(raidSpawn); + + for (String preset : matchingPresets) { + toNotify.addAll(DBManager.getUserIDsToNotify(preset,raidSpawn)); + } + + toNotify.forEach(id -> notifyUser(id, raidSpawn.buildMessage("formatting.ini"),raidSpawn.raidLevel >= 3)); + + if(!config.isRaidChannelsEnabled()) continue; // notifyUser("107730875596169216",raidSpawn.buildMessage(),true); for (GeofenceIdentifier identifier : raidSpawn.getGeofences()) { - String id = config.getGeofenceChannelId(identifier); + ArrayList channels = config.getRaidChannels(identifier); - if(id != null){ - jda.getTextChannelById(id).sendMessage(raidSpawn.buildMessage()).queue(m -> { - if(config.isRaidOrganisationEnabled() && raidSpawn.raidLevel >= 3) { - System.out.println(String.format("adding reaction to raid with raidlevel %s", raidSpawn.raidLevel)); - m.addReaction(WHITE_GREEN_CHECK).queue(); - } - }); + if(channels == null) continue; + + for (AlertChannel channel : channels) { + if(channel != null){ + checkAndPost(channel,raidSpawn); + } + } + } + + ArrayList noGeofences = config.getNonGeofencedRaidChannels(); + + if (noGeofences != null){ + for (AlertChannel channel : noGeofences) { + checkAndPost(channel, raidSpawn); } } //// if(raidSpawn.bossId == 249){ - jda.getTextChannelById(345259921790468097L).sendMessage(raidSpawn.buildMessage()).queue(m -> { + jda.getTextChannelById(345259921790468097L).sendMessage(raidSpawn.buildMessage("formatting.ini")).queue(m -> { if(config.isRaidOrganisationEnabled() && raidSpawn.raidLevel >= 3) { System.out.println(String.format("adding reaction to raid with raidlevel %s", raidSpawn.raidLevel)); m.addReaction(WHITE_GREEN_CHECK).queue(); @@ -149,4 +166,21 @@ public void run() { // } } } + + private void checkAndPost(AlertChannel channel, RaidSpawn raidSpawn) { + if (config.matchesFilter(config.raidFilters.get(channel.filterName),raidSpawn)){ + notificationLog.log(INFO, "Raid passed filter, posting to Discord"); + sendPublicAlert(raidSpawn.buildMessage(channel.formattingName),channel.channelId, raidSpawn.raidLevel); + } + } + + private void sendPublicAlert(Message message, String channelId, int raidLevel) { + notificationLog.log(INFO, "Sending public alert message to channel " + channelId); + jda.getTextChannelById(channelId).sendMessage(message).queue(m -> { + if(config.isRaidOrganisationEnabled() && raidLevel >= 3) { + System.out.println(String.format("adding reaction to raid with raidlevel %s", raidLevel)); + m.addReaction(WHITE_GREEN_CHECK).queue(); + } + }); + } } diff --git a/src/notifier/RaidNotifier.java b/src/notifier/RaidNotifier.java index ff14a4c..d78a4de 100644 --- a/src/notifier/RaidNotifier.java +++ b/src/notifier/RaidNotifier.java @@ -15,7 +15,7 @@ public class RaidNotifier implements Runnable private final JDA jda; private final boolean testing; - private static SimpleLog notifierLog = SimpleLog.getLog("RaidNotifier"); + private static final SimpleLog notifierLog = SimpleLog.getLog("RaidNotifier"); public RaidNotifier(final JDA jda, boolean testing) { this.jda = jda; diff --git a/src/notifier/UserNotifier.java b/src/notifier/UserNotifier.java index d05b2e8..d9dbb63 100644 --- a/src/notifier/UserNotifier.java +++ b/src/notifier/UserNotifier.java @@ -20,7 +20,7 @@ public UserNotifier(final User user, final Message message, boolean showTick) { @Override public void run() { - if(user == null)return;; + if(user == null)return; if (!user.hasPrivateChannel()) { user.openPrivateChannel().complete(); diff --git a/src/parser/ArgType.java b/src/parser/ArgType.java index 7b8735f..c29f4eb 100644 --- a/src/parser/ArgType.java +++ b/src/parser/ArgType.java @@ -11,7 +11,7 @@ public enum ArgType Unknown, TimeUnit, Status, - Int; + Int, Preset; public static void main(final String[] args) { final HashSet hashSet = new HashSet(Arrays.asList(ArgType.CommandStr, ArgType.Pokemon, ArgType.Locations)); @@ -35,6 +35,10 @@ public String toString() { return "time unit"; case Int: return "whole number"; + case Preset: + return "preset"; + case CommandStr: + return "command"; default: return null; } diff --git a/src/parser/Command.java b/src/parser/Command.java index ebd3331..307ef51 100644 --- a/src/parser/Command.java +++ b/src/parser/Command.java @@ -8,7 +8,7 @@ public class Command int maxArgs; HashSet validArgTypes; private HashSet requiredArgTypes; - boolean allowDuplicateArgs; + final boolean allowDuplicateArgs; private Argument[] arguments; public Command() { diff --git a/src/parser/Commands.java b/src/parser/Commands.java index 0edee07..b131e93 100644 --- a/src/parser/Commands.java +++ b/src/parser/Commands.java @@ -27,6 +27,21 @@ public static Command get(final String firstArg) { Commands.commands.put("!clearlocation", clearLocation); + if(config.pokemonEnabled() || config.raidsEnabled()){ + Command loadPreset = new Command() + .setValidArgTypes(new HashSet<>(Arrays.asList(ArgType.CommandStr,ArgType.Preset,ArgType.Locations))) + .setRequiredArgTypes(new HashSet<>(Arrays.asList(ArgType.CommandStr,ArgType.Preset))) + .setArgRange(1,3); + + Command delPreset = new Command() + .setValidArgTypes(new HashSet<>(Arrays.asList(ArgType.CommandStr,ArgType.Preset,ArgType.Locations))) + .setRequiredArgTypes(new HashSet<>(Arrays.asList(ArgType.CommandStr,ArgType.Preset))) + .setArgRange(1,3); + + Commands.commands.put("!loadpreset",loadPreset); + Commands.commands.put("!delpreset",delPreset); + } + if(config.pokemonEnabled()) { final Command addPokemon = new Command() .setValidArgTypes(new HashSet(Arrays.asList(ArgType.CommandStr, ArgType.Pokemon, ArgType.Locations, ArgType.Float, ArgType.Int))) @@ -43,7 +58,6 @@ public static Command get(final String firstArg) { .setRequiredArgTypes(new HashSet(Arrays.asList(ArgType.CommandStr, ArgType.Pokemon))) .setArgRange(1, 1); - Commands.commands.put("!addpokemon", addPokemon); Commands.commands.put("!delpokemon", delPokemon); Commands.commands.put("!clearpokemon", clearPokemon); @@ -72,16 +86,6 @@ public static Command get(final String firstArg) { Commands.commands.put("!clearraidlocation", clearLocation); } - - if(config.useChannels()) { - final Command addChannel = new Command() - .setValidArgTypes(new HashSet(Arrays.asList(ArgType.CommandStr, ArgType.Locations))) - .setRequiredArgTypes(new HashSet(Arrays.asList(ArgType.CommandStr, ArgType.Locations))) - .setArgRange(1, 1); - - Commands.commands.put("!addchannel", addChannel); - } - if(config.nestsEnabled()) { final Command nest = new Command() .setValidArgTypes(new HashSet(Arrays.asList(ArgType.CommandStr, ArgType.Pokemon, ArgType.Status))) diff --git a/src/parser/InputError.java b/src/parser/InputError.java index 6776517..a46dfb2 100644 --- a/src/parser/InputError.java +++ b/src/parser/InputError.java @@ -1,14 +1,8 @@ package parser; -import core.Location; -import core.Reason; - import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; -import static core.MessageListener.config; - public enum InputError { InvalidArg, @@ -29,44 +23,44 @@ public String getErrorMessage(final UserCommand userCommand) { str = str + ArgType.setToString(argTypes) + ""; return str; } - case UnusableLocation: { - String str = "You specified one or more locations unusable by your access level.\n\n"; - - Argument argument = userCommand.getArg(ArgType.Locations); - - HashMap> unusableMap = new HashMap<>(); - - for (Object o : argument.getParams()) { - Location location = (Location) o; - - if(!location.usable){ - if(!unusableMap.containsKey(location.reason)){ - unusableMap.put(location.reason,new ArrayList<>()); - } - unusableMap.get(location.reason).add(location); - } - } - - for (Reason reason : unusableMap.keySet()) { - str += String.format("**%s:**%n",reason); - - for (Location location : unusableMap.get(reason)) { - str += String.format(" %s%n",location.getSuburb()); - } - - str += "\n"; - } - - if(unusableMap.containsKey(Reason.SupporterAttemptedPublic)){ - str += "Instead of using Discord channels for notifications, supporters have direct access to ALL pokemon spawns," + - " and instead can subscribe to all spawns or filter them based on suburb"; - - if(config.useGeofences()) str += " or geofences"; - - str += "."; - } - return str; - } +// case UnusableLocation: { +// String str = "You specified one or more locations unusable by your access level.\n\n"; +// +// Argument argument = userCommand.getArg(ArgType.Locations); +// +// HashMap> unusableMap = new HashMap<>(); +// +// for (Object o : argument.getParams()) { +// Location location = (Location) o; +// +// if(!location.usable){ +// if(!unusableMap.containsKey(location.reason)){ +// unusableMap.put(location.reason,new ArrayList<>()); +// } +// unusableMap.get(location.reason).add(location); +// } +// } +// +// for (Reason reason : unusableMap.keySet()) { +// str += String.format("**%s:**%n",reason); +// +// for (Location location : unusableMap.get(reason)) { +// str += String.format(" %s%n",location.getSuburb()); +// } +// +// str += "\n"; +// } +// +// if(unusableMap.containsKey(Reason.SupporterAttemptedPublic)){ +// str += "Instead of using Discord channels for notifications, supporters have direct access to ALL pokemon spawns," + +// " and instead can subscribe to all spawns or filter them based on suburb"; +// +// if(config.useGeofences()) str += " or geofences"; +// +// str += "."; +// } +// return str; +// } case BlacklistedPokemon: { String str = "One or more pokemon you entered aren't being scanned for: \n\n"; for (final String s : userCommand.getBlacklisted()) { @@ -75,13 +69,12 @@ public String getErrorMessage(final UserCommand userCommand) { return str; } case TooManyArgs: { - final int max = Commands.get((String)userCommand.getArg(0).getParams()[0]).getMaxArgs(); - final String str = "You entered too many options. That command can have at most " + max + ((max == 1) ? " option" : " options"); - return str; + int max = Commands.get((String)userCommand.getArg(0).getParams()[0]).getMaxArgs(); + return "You entered too many options. That command can have at most " + max + ((max == 1) ? " option" : " options"); } case NotEnoughArgs: { - final int min = Commands.get((String)userCommand.getArg(0).getParams()[0]).getMinArgs(); - final String str = "You didn't specify enough options. That command needs at least " + min + ((min == 1) ? " option" : " options"); + int min = Commands.get((String)userCommand.getArg(0).getParams()[0]).getMinArgs(); + String str = "You didn't specify enough options. That command needs at least " + min + ((min == 1) ? " option" : " options"); return str + "\n\n"; } case DuplicateArgs: { @@ -110,13 +103,10 @@ public String getErrorMessage(final UserCommand userCommand) { return str + "\n\n"; } case MalformedArg: { - String str = "I couldn't recognise the following things:\n\n"; - str += Argument.malformedToString(userCommand.getMalformedArgs()); - return str; + return "I couldn't recognise the following things:\n\n" + Argument.malformedToString(userCommand.getMalformedArgs()); } case InvalidCommand: { - final String str = "I don't recognise that command. Use the `!help` command for a list of my commands"; - return str; + return "I don't recognise that command. Use the `!help` command for a list of my commands"; } default: return null; diff --git a/src/parser/Parser.java b/src/parser/Parser.java index 2c12f7a..70634b1 100644 --- a/src/parser/Parser.java +++ b/src/parser/Parser.java @@ -11,6 +11,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static core.MessageListener.config; + public class Parser { private static final Pattern PATTERN; @@ -107,7 +109,7 @@ else if (Pokemon.nameToID(s.trim()) != 0) { } else { final Location location; - if ((location = Location.fromString(s.trim(),supporter)) != null) { + if ((location = Location.fromString(s.trim())) != null) { argument.setType(ArgType.Locations); ArrayList locations = new ArrayList<>(); @@ -139,6 +141,10 @@ else if (getFloat(s.trim()) != null) { argument.setType(ArgType.Float); argument.setParams(new Object[] { getFloat(s.trim()) }); } + else if (config.presets.get(s.trim()) != null){ + argument.setType(ArgType.Preset); + argument.setParams(new Object[] { s.trim()}); + } else { argument.setType(ArgType.Unknown); argument.setParams(new Object[] { null }); @@ -173,20 +179,20 @@ private static Argument parseList(final String group, boolean supporter) { final String[] strings = toSplit.split(","); final ArrayList args = new ArrayList<>(); final ArrayList malformed = new ArrayList(); - for (int i = 0; i < strings.length; ++i) { - Location loc = Location.fromString(strings[i].trim(), supporter); + for (String string2 : strings) { + Location loc = Location.fromString(string2.trim()); if (loc == null) { - malformed.add(strings[i].trim()); - args.add(loc); + malformed.add(string2.trim()); + args.add(null); continue; } - if(loc.locationType == LocationType.Geofence){ + if (loc.locationType == LocationType.Geofence) { for (GeofenceIdentifier geofenceIdentifier : loc.geofenceIdentifiers) { args.add(new Location(geofenceIdentifier)); } - }else{ + } else { args.add(loc); } @@ -194,10 +200,10 @@ private static Argument parseList(final String group, boolean supporter) { if (allNull(args.toArray())) { args.clear(); malformed.clear(); - for (int i = 0; i < strings.length; ++i) { - final Pokemon pokemon = new Pokemon(strings[i].trim()); + for (String string1 : strings) { + final Pokemon pokemon = new Pokemon(string1.trim()); if (pokemon.name == null) { - malformed.add(strings[i].trim()); + malformed.add(string1.trim()); } args.add(pokemon.name); } @@ -208,29 +214,44 @@ private static Argument parseList(final String group, boolean supporter) { args.clear(); malformed.clear(); if (strings.length == 1 || strings.length == 2) { - for (int i = 0; i < strings.length; ++i) { - args.add(getInt(strings[i].trim())); + for (String string : strings) { + args.add(getInt(string.trim())); } if (!allNull(new ArrayList[]{args})) { argument.setType(ArgType.Int); }else{ - for (int i = 0; i < strings.length; ++i) { - args.add(getFloat(strings[i].trim())); + for (String string : strings) { + args.add(getFloat(string.trim())); } if (!allNull(new ArrayList[]{args})) { argument.setType(ArgType.Float); } } }else{ - for (int i = 0; i < strings.length; ++i) { - NestStatus status = NestStatus.fromString(strings[i].trim()); + for (String string : strings) { + NestStatus status = NestStatus.fromString(string.trim()); args.add(status); if (status == null) { - malformed.add(strings[i].trim()); + malformed.add(string.trim()); } } if (!allNull(args.toArray())) { argument.setType(ArgType.Status); + }else { + args.clear(); + malformed.clear(); + + for (String string : strings) { + String presetFilter = config.presets.get(string.trim()); + args.add(string.trim()); + if(presetFilter == null){ + malformed.add(string.trim()); + } + } + + if (!allNull(args.toArray())) { + argument.setType(ArgType.Preset); + } } } } @@ -262,17 +283,13 @@ private static boolean allNull(final Object[] args) { public static void main(String[] args) { MessageListener.loadConfig(); - if(MessageListener.config.useChannels()){ - FeedChannels.loadChannels(); - } - - if(MessageListener.config.useGeofences()){ + if(config.useGeofences()){ Geofencing.loadGeofences(); } MessageListener.loadSuburbs(); // System.out.println(Location.fromString("turner",true)); - UserCommand command = parseInput("!nest pikachu",true); + UserCommand command = parseInput("!loadpreset 100iv",true); // command.buildPokemon(); System.out.println(command.getExceptions()); } diff --git a/src/pokemon/PokeSpawn.java b/src/pokemon/PokeSpawn.java index 86777be..4f4b0a7 100644 --- a/src/pokemon/PokeSpawn.java +++ b/src/pokemon/PokeSpawn.java @@ -1,8 +1,8 @@ package pokemon; import core.DBManager; -import core.FeedChannel; import core.Region; +import core.Spawn; import core.Util; import maps.GeofenceIdentifier; import maps.ReverseGeocoder; @@ -14,27 +14,20 @@ import java.math.RoundingMode; import java.sql.Timestamp; import java.text.DecimalFormat; -import java.text.SimpleDateFormat; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.HashMap; import static core.MessageListener.*; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static maps.Geofencing.getGeofence; import static maps.Geofencing.loadGeofences; -public class PokeSpawn +public class PokeSpawn extends Spawn { private static final String STATIC_MAPS_BASE = "https://maps.googleapis.com/maps/api/staticmap?"; - public FeedChannel feedChannel; - private int level; private String imageUrl; public Timestamp disappearTime; - private double lat; - private double lon; private float weight; private float height; private int gender; @@ -42,23 +35,20 @@ public class PokeSpawn public int id; private String suburb; public Region region; - private ArrayList geofenceIdentifiers = new ArrayList<>(); public float iv; - private String move_1; - private String move_2; private static final DecimalFormat df; private int iv_attack; private int iv_defense; private int iv_stamina; - private static int lastKey; - private int cp; + public int cp; + public int level; - public HashMap pokeProperties = new HashMap<>(); - - public static final SimpleDateFormat printFormat = new SimpleDateFormat("HH:mm:ss"); - private Message builtMessage = null; + public PokeSpawn(){ + formatKey = "pokemon"; + } public PokeSpawn(final int id, final String suburb, final Region region, final float iv, final String move_1, final String move_2) { + super(); this.imageUrl = null; this.disappearTime = null; this.form = null; @@ -72,6 +62,11 @@ public PokeSpawn(final int id, final String suburb, final Region region, final f this.move_2 = move_2; } + public PokeSpawn(int i) { + super(); + this.id = i; + } + public static void main(final String[] args) { System.out.println(ZonedDateTime.ofInstant(Instant.now(), ZoneId.of("Australia/Adelaide"))); @@ -101,47 +96,32 @@ public static void main(final String[] args) { 0, 0); - System.out.println(spawn.pokeProperties.get("geofence")); + System.out.println(spawn.properties.get("geofence")); System.out.println(spawn.encountered()); -// System.out.println(config.formatStr(spawn.pokeProperties,config.getTitleFormatting())); +// System.out.println(config.formatStr(spawn.properties,config.getTitleFormatting())); // if(spawn.encountered()){ -// System.out.println(config.formatStr(spawn.pokeProperties,config.getEncounterBodyFormatting())); +// System.out.println(config.formatStr(spawn.properties,config.getEncounterBodyFormatting())); // }else { -// System.out.println(config.formatStr(spawn.pokeProperties, config.getBodyFormatting())); +// System.out.println(config.formatStr(spawn.properties, config.getBodyFormatting())); // } // System.out.println(new PokeSpawn(12, -35.0, 149.0, new Time(1L), 1, 1, 1, "", "", 13.0f, 13.0f, 3, 1, 2142,0.743 ).hashCode()); // System.out.println(new PokeSpawn(12, -35.0, 149.0, new Time(214L), 1, 1, 1, "", "", 13.0f, 13.0f, 3, 1, 2142,.743 ).hashCode()); } - public PokeSpawn(int id, FeedChannel feedChannel, String suburb, float pokeIV, String move_1, String move_2, String form, int cp) { - this.imageUrl = null; - this.disappearTime = null; - this.form = null; - this.suburb = null; - this.feedChannel = feedChannel; - this.id = id; - this.suburb = suburb; - this.pokeProperties.put("city",suburb); - this.iv = pokeIV; - this.move_2 = move_2; - this.move_1 = move_1; - this.form = form; - this.cp = cp; - } - public PokeSpawn(final int id, final double lat, final double lon, final Timestamp disappearTime, final int attack, final int defense, final int stamina, final String move1, final String move2, final float weight, final float height, final int gender, final int form, int cp, double cpModifier) { + super(); this.imageUrl = null; this.disappearTime = null; this.form = null; this.suburb = null; this.region = null; this.disappearTime = disappearTime; - pokeProperties.put("24h_time",getDespawnTime()); - pokeProperties.put("time_left",timeLeft()); + properties.put("24h_time",getDespawnTime()); + properties.put("time_left",timeLeft()); this.id = id; - pokeProperties.put("pkmn_id", String.valueOf(id)); + properties.put("pkmn_id", String.valueOf(id)); String name = Util.capitaliseFirst(Pokemon.idToName(this.id)); @@ -149,67 +129,70 @@ public PokeSpawn(final int id, final double lat, final double lon, final Timesta name = "Unown"; } - pokeProperties.put("pkmn",name); + properties.put("pkmn",name); this.lat = lat; - pokeProperties.put("lat", String.valueOf(lat)); + properties.put("lat", String.valueOf(lat)); this.lon = lon; - pokeProperties.put("lng", String.valueOf(lon)); + properties.put("lng", String.valueOf(lon)); ReverseGeocoder.geocodedLocation(lat,lon).getProperties().forEach((key,value)->{ - pokeProperties.put(key,value); + properties.put(key,value); }); this.geofenceIdentifiers = getGeofence(lat,lon); - pokeProperties.put("geofence", GeofenceIdentifier.listToString(geofenceIdentifiers)); + properties.put("geofence", GeofenceIdentifier.listToString(geofenceIdentifiers)); - pokeProperties.put("gmaps",getGmapsLink()); + properties.put("gmaps",getGmapsLink()); - pokeProperties.put("applemaps",getAppleMapsLink()); + properties.put("applemaps",getAppleMapsLink()); this.iv_attack = attack; - pokeProperties.put("atk", String.valueOf(iv_attack)); + properties.put("atk", String.valueOf(iv_attack)); this.iv_defense = defense; - pokeProperties.put("def", String.valueOf(iv_defense)); + properties.put("def", String.valueOf(iv_defense)); this.iv_stamina = stamina; - pokeProperties.put("sta", String.valueOf(iv_stamina)); + properties.put("sta", String.valueOf(iv_stamina)); this.iv = (attack + defense + stamina) / 45.0f * 100.0f; - pokeProperties.put("iv", getIv()); + properties.put("iv", getIv()); this.move_1 = ((move1 == null) ? "unkn" : move1); - pokeProperties.put("quick_move", move_1); + properties.put("quick_move", move_1); this.move_2 = ((move2 == null) ? "unkn" : move2); - pokeProperties.put("charge_move", move_2); + properties.put("charge_move", move_2); this.weight = weight; - pokeProperties.put("weight", getWeight()); + properties.put("weight", getWeight()); this.height = height; - pokeProperties.put("height", getHeight()); + properties.put("height", getHeight()); + + properties.put("size",getSize()); this.gender = gender; - pokeProperties.put("gender", getGender()); + properties.put("gender", getGender()); if (form != 0 && id == 201) { this.id = id * 10 + form; } this.form = ((Pokemon.intToForm(form) == null) ? null : String.valueOf(Pokemon.intToForm(form))); - pokeProperties.put("form", (this.form == null ? "" : this.form)); + properties.put("form", (this.form == null ? "" : this.form)); this.cp = cp; - pokeProperties.put("cp", cp == 0 ? "?" : String.valueOf(cp)); + properties.put("cp", cp == 0 ? "?" : String.valueOf(cp)); - this.level = getLevel(cpModifier); - pokeProperties.put("level", String.valueOf(level)); + level = getLevel(cpModifier); + properties.put("level", String.valueOf(level)); } public PokeSpawn(final int id, final String suburb, final float pokeIV, final String move_1, final String move_2, final String form, int cp) { + super(); this.imageUrl = null; this.disappearTime = null; this.form = null; @@ -224,7 +207,7 @@ public PokeSpawn(final int id, final String suburb, final float pokeIV, final St this.cp = cp; } - public static int getLevel(double cpModifier){ + private static int getLevel(double cpModifier){ double unRoundedLevel; if(cpModifier < 0.734){ @@ -236,26 +219,6 @@ public static int getLevel(double cpModifier){ return (int) Math.round(unRoundedLevel); } - public String getSuburb() { - - return pokeProperties.get("city"); - -// if (this.suburb != null) { -// return this.suburb; -// } -// final String foundSuburb = ReverseGeocoder.getSuburb(this.lat, this.lon); -// if (foundSuburb.equals("")) { -// return this.suburb = "Unknown"; -// } -// return this.suburb = ReverseGeocoder.getSuburb(this.lat, this.lon); - } - -// public Region getRegion() { -// if (this.region == null) { -// return this.region = Geofencing.getRegion(this.lat, this.lon); -// } -// return this.region; -// } @Override public String toString() { @@ -290,23 +253,24 @@ private String timeLeft() { return time; } - public Message buildMessage() { - if(builtMessage == null) { + public Message buildMessage(String formatFile) { + if(builtMessages.get(formatFile) == null) { final MessageBuilder messageBuilder = new MessageBuilder(); final EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setColor(getColor()); - embedBuilder.setTitle(config.formatStr(pokeProperties, config.getTitleFormatting("pokemon")), config.formatStr(pokeProperties, config.getTitleUrl("pokemon"))); - embedBuilder.setDescription(config.formatStr(pokeProperties, (encountered()) ? config.getEncounterBodyFormatting() : config.getBodyFormatting("pokemon"))); + embedBuilder.setTitle(config.formatStr(properties, (encountered()) ? config.getEncounterTitleFormatting(formatFile) : (config.getTitleFormatting(formatFile,"pokemon"))), config.formatStr(properties, config.getTitleUrl(formatFile,"pokemon"))); + embedBuilder.setDescription(config.formatStr(properties, (encountered()) ? config.getEncounterBodyFormatting(formatFile) : config.getBodyFormatting(formatFile,"pokemon"))); embedBuilder.setThumbnail(Pokemon.getIcon(this.id)); - if (config.showMap("pokemon")) { - embedBuilder.setImage(this.getImage()); + if (config.showMap(formatFile,"pokemon")) { + embedBuilder.setImage(this.getImage(formatFile)); } embedBuilder.setFooter(config.getFooterText(), null); embedBuilder.setTimestamp(Instant.now()); messageBuilder.setEmbed(embedBuilder.build()); - builtMessage = messageBuilder.build(); + builtMessages.put(formatFile,messageBuilder.build()); } - return builtMessage; + + return builtMessages.get(formatFile); } private boolean encountered() { @@ -351,34 +315,13 @@ private String getWeight() { return PokeSpawn.df.format(this.weight); } - private String getImage() { - - if (this.imageUrl == null) { - return this.imageUrl = "https://maps.googleapis.com/maps/api/staticmap?" + String.format("zoom=%s&size=%sx%s&markers=color:red|%s,%s&key=%s", config.getMapZoom("pokemon"), config.getMapWidth("pokemon"), config.getMapHeight("pokemon"), this.lat, this.lon, getNextKey()); - } - return this.imageUrl; - } - - public static String getNextKey() { - if (PokeSpawn.lastKey == config.getKeys().size() - 1) { - PokeSpawn.lastKey = 0; - return config.getKeys().get(PokeSpawn.lastKey); - } - ++PokeSpawn.lastKey; - return config.getKeys().get(PokeSpawn.lastKey); - } - - private String getGmapsLink() { - return String.format("https://www.google.com/maps?q=loc:%s,%s", this.lat, this.lon); - } - private String getIv() { return PokeSpawn.df.format(this.iv); } static { (df = new DecimalFormat("#.##")).setRoundingMode(RoundingMode.CEILING); - PokeSpawn.lastKey = 0; + } @Override @@ -406,15 +349,23 @@ public int hashCode() { return hash; } - public String getDespawnTime() { + private String getDespawnTime() { return printFormat.format(disappearTime); } - public String getAppleMapsLink() { - return String.format("http://maps.apple.com/maps?daddr=%s,%s&z=10&t=s&dirflg=w", this.lat, this.lon); + private String getSize() { + if ((weight == 0) && (height == 0)) { + return "?"; + } + + return Pokemon.getSize(id,height,weight); } - public ArrayList getGeofenceIds() { - return geofenceIdentifiers; + public int getFilterId() { + if (id >= 2011){ + return 201; + }else{ + return id; + } } } diff --git a/src/pokemon/Pokemon.java b/src/pokemon/Pokemon.java index f34e912..47ccd8e 100644 --- a/src/pokemon/Pokemon.java +++ b/src/pokemon/Pokemon.java @@ -1,9 +1,17 @@ package pokemon; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import core.Location; import core.Region; +import core.Types; -import java.util.*; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.Arrays; public class Pokemon { @@ -13,6 +21,39 @@ public class Pokemon public float maxiv; private Location location; + private static JsonObject baseStats; + private static JsonObject pokemonInfo; + private static JsonObject movesInfo; + + static { +// VALID_NAMES = new ArrayList(Arrays.asList("bulbasaur", "ivysaur", "venusaur", "charmander", "charmeleon", "charizard", "squirtle", "wartortle", "blastoise", "caterpie", "metapod", "butterfree", "weedle", "kakuna", "beedrill", "pidgey", "pidgeotto", "pidgeot", "rattata", "raticate", "spearow", "fearow", "ekans", "arbok", "pikachu", "raichu", "sandshrew", "sandslash", "nidoran\u2640", "nidorina", "nidoqueen", "nidoran\u2642", "nidorino", "nidoking", "clefairy", "clefable", "vulpix", "ninetales", "jigglypuff", "wigglytuff", "zubat", "golbat", "oddish", "gloom", "vileplume", "paras", "parasect", "venonat", "venomoth", "diglett", "dugtrio", "meowth", "persian", "psyduck", "golduck", "mankey", "primeape", "growlithe", "arcanine", "poliwag", "poliwhirl", "poliwrath", "abra", "kadabra", "alakazam", "machop", "machoke", "machamp", "bellsprout", "weepinbell", "victreebel", "tentacool", "tentacruel", "geodude", "graveler", "golem", "ponyta", "rapidash", "slowpoke", "slowbro", "magnemite", "magneton", "farfetch'd", "doduo", "dodrio", "seel", "dewgong", "grimer", "muk", "shellder", "cloyster", "gastly", "haunter", "gengar", "onix", "drowzee", "krabby", "kingler","hypno", "voltorb", "electrode", "exeggcute", "exeggutor", "cubone", "marowak", "hitmonlee", "hitmonchan", "lickitung", "koffing", "weezing", "rhyhorn", "rhydon", "chansey", "tangela", "kangaskhan", "horsea", "seadra", "goldeen", "seaking", "staryu", "starmie", "mr. mime", "scyther", "jynx", "electabuzz", "magmar", "pinsir", "tauros", "magikarp", "gyarados", "lapras", "ditto", "eevee", "vaporeon", "jolteon", "flareon", "porygon", "omanyte", "omastar", "kabuto", "kabutops", "aerodactyl", "snorlax", "articuno", "zapdos", "moltres", "dratini", "dragonair", "dragonite", "mewtwo", "mew", "chikorita", "bayleef", "meganium", "cyndaquil", "quilava", "typhlosion", "totodile", "croconaw", "feraligatr", "sentret", "furret", "hoothoot", "noctowl", "ledyba", "ledian", "spinarak", "ariados", "crobat", "chinchou", "lanturn", "pichu", "cleffa", "igglybuff", "togepi", "togetic", "natu", "xatu", "mareep", "flaaffy", "ampharos", "bellossom", "marill", "azumarill", "sudowoodo", "politoed", "hoppip", "skiploom", "jumpluff", "aipom", "sunkern", "sunflora", "yanma", "wooper", "quagsire", "espeon", "umbreon", "murkrow", "slowking", "misdreavus", "unown", "wobbuffet", "girafarig", "pineco", "forretress", "dunsparce", "gligar", "steelix", "snubbull", "granbull", "qwilfish", "scizor", "shuckle", "heracross", "sneasel", "teddiursa", "ursaring", "slugma", "magcargo", "swinub", "piloswine", "corsola", "remoraid", "octillery", "delibird", "mantine", "skarmory", "houndour", "houndoom", "kingdra", "phanpy", "donphan", "porygon2", "stantler", "smeargle", "tyrogue", "hitmontop", "smoochum", "elekid", "magby", "miltank", "blissey", "raikou", "entei", "suicune", "larvitar", "pupitar", "tyranitar", "lugia", "ho-oh", "celebi", "treecko", "grovyle", "sceptile", "torchic", "combusken", "blaziken", "mudkip", "marshtomp", "swampert", "poochyena", "mightyena", "zigzagoon", "linoone", "wurmple", "silcoon", "beautifly", "cascoon", "dustox", "lotad", "lombre", "ludicolo", "seedot", "nuzleaf", "shiftry", "taillow", "swellow", "wingull", "pelipper", "ralts", "kirlia", "gardevoir", "surskit", "masquerain", "shroomish", "breloom", "slakoth", "vigoroth", "slaking", "nincada", "ninjask", "shedinja", "whismur", "loudred", "exploud", "makuhita", "hariyama", "azurill", "nosepass", "skitty", "delcatty", "sableye", "mawile", "aron", "lairon", "aggron", "meditite", "medicham", "electrike", "manectric", "plusle", "minun", "volbeat", "illumise", "roselia", "gulpin", "swalot", "carvanha", "sharpedo", "wailmer", "wailord", "numel", "camerupt", "torkoal", "spoink", "grumpig", "spinda", "trapinch", "vibrava", "flygon", "cacnea", "cacturne", "swablu", "altaria", "zangoose", "seviper", "lunatone", "solrock", "barboach", "whiscash", "corphish", "crawdaunt", "baltoy", "claydol", "lileep", "cradily", "anorith", "armaldo", "feebas", "milotic", "castform", "kecleon", "shuppet", "banette", "duskull", "dusclops", "tropius", "chimecho", "absol", "wynaut", "snorunt", "glalie", "spheal", "sealeo", "walrein", "clamperl", "huntail", "gorebyss", "relicanth", "luvdisc", "bagon", "shelgon", "salamence", "beldum", "metang", "metagross", "regirock", "regice", "registeel", "latias", "latios", "kyogre", "groudon", "rayquaza", "jirachi", "deoxys", "turtwig", "grotle", "torterra", "chimchar", "monferno", "infernape", "piplup", "prinplup", "empoleon", "starly", "staravia", "staraptor", "bidoof", "bibarel", "kricketot", "kricketune", "shinx", "luxio", "luxray", "budew", "roserade", "cranidos", "rampardos", "shieldon", "bastiodon", "burmy", "wormadam", "mothim", "combee", "vespiquen", "pachirisu", "buizel", "floatzel", "cherubi", "cherrim", "shellos", "gastrodon", "ambipom", "drifloon", "drifblim", "buneary", "lopunny", "mismagius", "honchkrow", "glameow", "purugly", "chingling", "stunky", "skuntank", "bronzor", "bronzong", "bonsly", "mime jr.", "happiny", "chatot", "spiritomb", "gible", "gabite", "garchomp", "munchlax", "riolu", "lucario", "hippopotas", "hippowdon", "skorupi", "drapion", "croagunk", "toxicroak", "carnivine", "finneon", "lumineon", "mantyke", "snover", "abomasnow", "weavile", "magnezone", "lickilicky", "rhyperior", "tangrowth", "electivire", "magmortar", "togekiss", "yanmega", "leafeon", "glaceon", "gliscor", "mamoswine", "porygon-z", "gallade", "probopass", "dusknoir", "froslass", "rotom", "uxie", "mesprit", "azelf", "dialga", "palkia", "heatran", "regigigas", "giratina", "cresselia", "phione", "manaphy", "darkrai", "shaymin", "arceus", "victini", "snivy", "servine", "serperior", "tepig", "pignite", "emboar", "oshawott", "dewott", "samurott", "patrat", "watchog", "lillipup", "herdier", "stoutland", "purrloin", "liepard", "pansage", "simisage", "pansear", "simisear", "panpour", "simipour", "munna", "musharna", "pidove", "tranquill", "unfezant", "blitzle", "zebstrika", "roggenrola", "boldore", "gigalith", "woobat", "swoobat", "drilbur", "excadrill", "audino", "timburr", "gurdurr", "conkeldurr", "tympole", "palpitoad", "seismitoad", "throh", "sawk", "sewaddle", "swadloon", "leavanny", "venipede", "whirlipede", "scolipede", "cottonee", "whimsicott", "petilil", "lilligant", "basculin", "sandile", "krokorok", "krookodile", "darumaka", "darmanitan", "maractus", "dwebble", "crustle", "scraggy", "scrafty", "sigilyph", "yamask", "cofagrigus", "tirtouga", "carracosta", "archen", "archeops", "trubbish", "garbodor", "zorua", "zoroark", "minccino", "cinccino", "gothita", "gothorita", "gothitelle", "solosis", "duosion", "reuniclus", "ducklett", "swanna", "vanillite", "vanillish", "vanilluxe", "deerling", "sawsbuck", "emolga", "karrablast", "escavalier", "foongus", "amoonguss", "frillish", "jellicent", "alomomola", "joltik", "galvantula", "ferroseed", "ferrothorn", "klink", "klang", "klinklang", "tynamo", "eelektrik", "eelektross", "elgyem", "beheeyem", "litwick", "lampent", "chandelure", "axew", "fraxure", "haxorus", "cubchoo", "beartic", "cryogonal", "shelmet", "accelgor", "stunfisk", "mienfoo", "mienshao", "druddigon", "golett", "golurk", "pawniard", "bisharp", "bouffalant", "rufflet", "braviary", "vullaby", "mandibuzz", "heatmor", "durant", "deino", "zweilous", "hydreigon", "larvesta", "volcarona", "cobalion", "terrakion", "virizion", "tornadus", "thundurus", "reshiram", "zekrom", "landorus", "kyurem", "keldeo", "meloetta", "genesect", "chespin", "quilladin", "chesnaught", "fennekin", "braixen", "delphox", "froakie", "frogadier", "greninja", "bunnelby", "diggersby", "fletchling", "fletchinder", "talonflame", "scatterbug", "spewpa", "vivillon", "litleo", "pyroar", "flab\u00e9b\u00e9", "floette", "florges", "skiddo", "gogoat", "pancham", "pangoro", "furfrou", "espurr", "meowstic", "honedge", "doublade", "aegislash", "spritzee", "aromatisse", "swirlix", "slurpuff", "inkay", "malamar", "binacle", "barbaracle", "skrelp", "dragalge", "clauncher", "clawitzer", "helioptile", "heliolisk", "tyrunt", "tyrantrum", "amaura", "aurorus", "sylveon", "hawlucha", "dedenne", "carbink", "goomy", "sliggoo", "goodra", "klefki", "phantump", "trevenant", "pumpkaboo", "gourgeist", "bergmite", "avalugg", "noibat", "noivern", "xerneas", "yveltal", "zygarde", "diancie", "hoopa", "volcanion")); + VALID_NAMES = new ArrayList(Arrays.asList("bulbasaur","ivysaur","venusaur","charmander","charmeleon","charizard","squirtle","wartortle","blastoise","caterpie","metapod","butterfree","weedle","kakuna","beedrill","pidgey","pidgeotto","pidgeot","rattata","raticate","spearow","fearow","ekans","arbok","pikachu","raichu","sandshrew","sandslash","nidoran♀","nidorina","nidoqueen","nidoran♂","nidorino","nidoking","clefairy","clefable","vulpix","ninetales","jigglypuff","wigglytuff","zubat","golbat","oddish","gloom","vileplume","paras","parasect","venonat","venomoth","diglett","dugtrio","meowth","persian","psyduck","golduck","mankey","primeape","growlithe","arcanine","poliwag","poliwhirl","poliwrath","abra","kadabra","alakazam","machop","machoke","machamp","bellsprout","weepinbell","victreebel","tentacool","tentacruel","geodude","graveler","golem","ponyta","rapidash","slowpoke","slowbro","magnemite","magneton","farfetch'd","doduo","dodrio","seel","dewgong","grimer","muk","shellder","cloyster","gastly","haunter","gengar","onix","drowzee","hypno","krabby","kingler","voltorb","electrode","exeggcute","exeggutor","cubone","marowak","hitmonlee","hitmonchan","lickitung","koffing","weezing","rhyhorn","rhydon","chansey","tangela","kangaskhan","horsea","seadra","goldeen","seaking","staryu","starmie","mr. mime","scyther","jynx","electabuzz","magmar","pinsir","tauros","magikarp","gyarados","lapras","ditto","eevee","vaporeon","jolteon","flareon","porygon","omanyte","omastar","kabuto","kabutops","aerodactyl","snorlax","articuno","zapdos","moltres","dratini","dragonair","dragonite","mewtwo","mew","chikorita","bayleef","meganium","cyndaquil","quilava","typhlosion","totodile","croconaw","feraligatr","sentret","furret","hoothoot","noctowl","ledyba","ledian","spinarak","ariados","crobat","chinchou","lanturn","pichu","cleffa","igglybuff","togepi","togetic","natu","xatu","mareep","flaaffy","ampharos","bellossom","marill","azumarill","sudowoodo","politoed","hoppip","skiploom","jumpluff","aipom","sunkern","sunflora","yanma","wooper","quagsire","espeon","umbreon","murkrow","slowking","misdreavus","unown","wobbuffet","girafarig","pineco","forretress","dunsparce","gligar","steelix","snubbull","granbull","qwilfish","scizor","shuckle","heracross","sneasel","teddiursa","ursaring","slugma","magcargo","swinub","piloswine","corsola","remoraid","octillery","delibird","mantine","skarmory","houndour","houndoom","kingdra","phanpy","donphan","porygon2","stantler","smeargle","tyrogue","hitmontop","smoochum","elekid","magby","miltank","blissey","raikou","entei","suicune","larvitar","pupitar","tyranitar","lugia","ho-oh","celebi","treecko","grovyle","sceptile","torchic","combusken","blaziken","mudkip","marshtomp","swampert","poochyena","mightyena","zigzagoon","linoone","wurmple","silcoon","beautifly","cascoon","dustox","lotad","lombre","ludicolo","seedot","nuzleaf","shiftry","taillow","swellow","wingull","pelipper","ralts","kirlia","gardevoir","surskit","masquerain","shroomish","breloom","slakoth","vigoroth","slaking","nincada","ninjask","shedinja","whismur","loudred","exploud","makuhita","hariyama","azurill","nosepass","skitty","delcatty","sableye","mawile","aron","lairon","aggron","meditite","medicham","electrike","manectric","plusle","minun","volbeat","illumise","roselia","gulpin","swalot","carvanha","sharpedo","wailmer","wailord","numel","camerupt","torkoal","spoink","grumpig","spinda","trapinch","vibrava","flygon","cacnea","cacturne","swablu","altaria","zangoose","seviper","lunatone","solrock","barboach","whiscash","corphish","crawdaunt","baltoy","claydol","lileep","cradily","anorith","armaldo","feebas","milotic","castform","kecleon","shuppet","banette","duskull","dusclops","tropius","chimecho","absol","wynaut","snorunt","glalie","spheal","sealeo","walrein","clamperl","huntail","gorebyss","relicanth","luvdisc","bagon","shelgon","salamence","beldum","metang","metagross","regirock","regice","registeel","latias","latios","kyogre","groudon","rayquaza","jirachi","deoxys")); + + JsonParser parser = new JsonParser(); + + try { + JsonElement element = parser.parse(new FileReader("data/base_stats.json")); + + if (element.isJsonObject()) { + baseStats = element.getAsJsonObject(); + } + + element = parser.parse(new FileReader("data/pokemon.json")); + + if (element.isJsonObject()){ + pokemonInfo = element.getAsJsonObject(); + } + + element = parser.parse(new FileReader("data/moves.json")); + + if (element.isJsonObject()){ + movesInfo = element.getAsJsonObject(); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + public Pokemon(final String name) { this.miniv = 0.0f; this.maxiv = 100.0f; @@ -73,13 +114,7 @@ public Pokemon(final int id, final Location location, final float miniv, final f } public static void main(final String[] args) { - System.out.println(getIcon(new Pokemon("unown").getID())); - for (int i = 1; i <= 26; ++i) { - System.out.println(getIcon(new Pokemon(2010 + i).getID())); - } - for (int i = 1; i < 251; ++i) { - System.out.println(getIcon(new Pokemon(i).getID())); - } + System.out.println(Types.getStrengths(getMoveType(279))); } public static int nameToID(final String pokeName) { @@ -254,6 +289,47 @@ public static String idToName(final int id) { } } + public static String getFilterName(int id){ + + if (id > 2010) return "Unown"; + + return Pokemon.pokemonInfo.getAsJsonObject(Integer.toString(id)).get("name").getAsString(); + } + + public static String getSize(int id, float height, float weight){ + float baseStats[] = getBaseStats(id); + + float weightRatio = weight / baseStats[0]; + float heightRatio = height / baseStats[1]; + + float size = heightRatio + weightRatio; + + if (size < 1.5){ + return "tiny"; + } + if (size <= 1.75){ + return "small"; + } + if (size < 2.25){ + return "normal"; + } + if (size <= 2.5){ + return "large"; + } + return "big"; + } + + private static float[] getBaseStats(int id) { + JsonObject statsObj = baseStats.getAsJsonObject(Integer.toString(id)); + + float stats[] = new float[2]; + + stats[0] = statsObj.get("weight").getAsFloat(); + stats[1] = statsObj.get("height").getAsFloat(); + + return stats; + } + public static String listToString(final Pokemon[] pokemon) { String str = ""; if (pokemon.length == 1) { @@ -324,7 +400,18 @@ public Location getLocation() { return this.location; } - static { - VALID_NAMES = new ArrayList(Arrays.asList("bulbasaur","ivysaur","venusaur","charmander","charmeleon","charizard","squirtle","wartortle","blastoise","caterpie","metapod","butterfree","weedle","kakuna","beedrill","pidgey","pidgeotto","pidgeot","rattata","raticate","spearow","fearow","ekans","arbok","pikachu","raichu","sandshrew","sandslash","nidoran♀","nidorina","nidoqueen","nidoran♂","nidorino","nidoking","clefairy","clefable","vulpix","ninetales","jigglypuff","wigglytuff","zubat","golbat","oddish","gloom","vileplume","paras","parasect","venonat","venomoth","diglett","dugtrio","meowth","persian","psyduck","golduck","mankey","primeape","growlithe","arcanine","poliwag","poliwhirl","poliwrath","abra","kadabra","alakazam","machop","machoke","machamp","bellsprout","weepinbell","victreebel","tentacool","tentacruel","geodude","graveler","golem","ponyta","rapidash","slowpoke","slowbro","magnemite","magneton","farfetch'd","doduo","dodrio","seel","dewgong","grimer","muk","shellder","cloyster","gastly","haunter","gengar","onix","drowzee","hypno","krabby","kingler","voltorb","electrode","exeggcute","exeggutor","cubone","marowak","hitmonlee","hitmonchan","lickitung","koffing","weezing","rhyhorn","rhydon","chansey","tangela","kangaskhan","horsea","seadra","goldeen","seaking","staryu","starmie","mr. mime","scyther","jynx","electabuzz","magmar","pinsir","tauros","magikarp","gyarados","lapras","ditto","eevee","vaporeon","jolteon","flareon","porygon","omanyte","omastar","kabuto","kabutops","aerodactyl","snorlax","articuno","zapdos","moltres","dratini","dragonair","dragonite","mewtwo","mew","chikorita","bayleef","meganium","cyndaquil","quilava","typhlosion","totodile","croconaw","feraligatr","sentret","furret","hoothoot","noctowl","ledyba","ledian","spinarak","ariados","crobat","chinchou","lanturn","pichu","cleffa","igglybuff","togepi","togetic","natu","xatu","mareep","flaaffy","ampharos","bellossom","marill","azumarill","sudowoodo","politoed","hoppip","skiploom","jumpluff","aipom","sunkern","sunflora","yanma","wooper","quagsire","espeon","umbreon","murkrow","slowking","misdreavus","unown","wobbuffet","girafarig","pineco","forretress","dunsparce","gligar","steelix","snubbull","granbull","qwilfish","scizor","shuckle","heracross","sneasel","teddiursa","ursaring","slugma","magcargo","swinub","piloswine","corsola","remoraid","octillery","delibird","mantine","skarmory","houndour","houndoom","kingdra","phanpy","donphan","porygon2","stantler","smeargle","tyrogue","hitmontop","smoochum","elekid","magby","miltank","blissey","raikou","entei","suicune","larvitar","pupitar","tyranitar","lugia","ho-oh","celebi","treecko","grovyle","sceptile","torchic","combusken","blaziken","mudkip","marshtomp","swampert","poochyena","mightyena","zigzagoon","linoone","wurmple","silcoon","beautifly","cascoon","dustox","lotad","lombre","ludicolo","seedot","nuzleaf","shiftry","taillow","swellow","wingull","pelipper","ralts","kirlia","gardevoir","surskit","masquerain","shroomish","breloom","slakoth","vigoroth","slaking","nincada","ninjask","shedinja","whismur","loudred","exploud","makuhita","hariyama","azurill","nosepass","skitty","delcatty","sableye","mawile","aron","lairon","aggron","meditite","medicham","electrike","manectric","plusle","minun","volbeat","illumise","roselia","gulpin","swalot","carvanha","sharpedo","wailmer","wailord","numel","camerupt","torkoal","spoink","grumpig","spinda","trapinch","vibrava","flygon","cacnea","cacturne","swablu","altaria","zangoose","seviper","lunatone","solrock","barboach","whiscash","corphish","crawdaunt","baltoy","claydol","lileep","cradily","anorith","armaldo","feebas","milotic","castform","kecleon","shuppet","banette","duskull","dusclops","tropius","chimecho","absol","wynaut","snorunt","glalie","spheal","sealeo","walrein","clamperl","huntail","gorebyss","relicanth","luvdisc","bagon","shelgon","salamence","beldum","metang","metagross","regirock","regice","registeel","latias","latios","kyogre","groudon","rayquaza","jirachi","deoxys")); + public static ArrayList getTypes(int bossId) { + JsonArray types = pokemonInfo.getAsJsonObject(Integer.toString(bossId)).getAsJsonArray("types"); + + ArrayList typesList = new ArrayList<>(); + + for (JsonElement type : types) { + typesList.add(type.getAsString()); + } + return typesList; + } + + public static String getMoveType(int moveId) { + return movesInfo.getAsJsonObject(Integer.toString(moveId)).get("type").getAsString(); } } diff --git a/src/raids/LobbyManager.java b/src/raids/LobbyManager.java index e378e33..964d0af 100644 --- a/src/raids/LobbyManager.java +++ b/src/raids/LobbyManager.java @@ -16,10 +16,10 @@ */ public class LobbyManager { - HashMap activeLobbies = new HashMap<>(); - private static SimpleLog lobbyManagerLog = SimpleLog.getLog("Lobby-Manager"); + final HashMap activeLobbies = new HashMap<>(); + private static final SimpleLog lobbyManagerLog = SimpleLog.getLog("Lobby-Manager"); - RotatingSet oldLobbyRoleIds = new RotatingSet<>(200); + private final RotatingSet oldLobbyRoleIds = new RotatingSet<>(200); public LobbyManager(){ @@ -116,7 +116,7 @@ public void addLobbies(ArrayList lobbies) { } } - public void addLobby(RaidLobby raidLobby) { + private void addLobby(RaidLobby raidLobby) { activeLobbies.put(raidLobby.lobbyCode,raidLobby); } } diff --git a/src/raids/LobbyMonitor.java b/src/raids/LobbyMonitor.java index 8ec583e..d147c1b 100644 --- a/src/raids/LobbyMonitor.java +++ b/src/raids/LobbyMonitor.java @@ -19,13 +19,13 @@ public class LobbyMonitor implements Runnable { private final LobbyManager lobbyManager; - static SimpleLog lobbyMonitorLog = SimpleLog.getLog("Lobby-Monitor"); + private static final SimpleLog lobbyMonitorLog = SimpleLog.getLog("Lobby-Monitor"); public LobbyMonitor(LobbyManager lobbyManager){ this.lobbyManager = lobbyManager; lobbyMonitorLog.setLevel(DEBUG); try { - lobbyMonitorLog.addFileLogs(new File("std.log"),new File("err.log")); + SimpleLog.addFileLogs(new File("std.log"),new File("err.log")); } catch (IOException e) { e.printStackTrace(); } diff --git a/src/raids/Raid.java b/src/raids/Raid.java index 701ba52..4bdc4ad 100644 --- a/src/raids/Raid.java +++ b/src/raids/Raid.java @@ -1,50 +1,17 @@ package raids; import core.Location; +import core.Types; import net.dv8tion.jda.core.entities.Emote; +import pokemon.Pokemon; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; +import java.util.*; /** * Created by Owner on 27/06/2017. */ public class Raid { - public static final HashSet POSSIBLE_BOSSES = new HashSet<>( - Arrays.asList( - 3, - 6, - 9, - 59, - 65, - 68, - 89, - 94, - 103, - 110, - 112, - 125, - 126, - 131, - 129, - 134, - 135, - 136, - 143, - 144, - 145, - 146, - 150, - 153, - 156, - 159, - 243, - 244, - 245, - 248, - 249) - ); + private static final HashMap SPECIAL_NAMES = new HashMap<>(); public static final String[] TYPES = new String[] { "bugtype", @@ -67,11 +34,18 @@ public class Raid { "water" }; - public static HashMap emotes = new HashMap<>(); + public static final HashMap emotes = new HashMap<>(); public int bossId; public Location location; + static { + SPECIAL_NAMES.put("bug","bugtype"); + SPECIAL_NAMES.put("dragon","dragontype"); + SPECIAL_NAMES.put("fire","firetype"); + SPECIAL_NAMES.put("ghost","ghosttype"); + } + public Raid(){ } @@ -87,135 +61,39 @@ public String toString() { } public static String[] getBossWeaknessEmotes(int bossId){ - switch(bossId){ - case 3: //venusaur - return new String[] {"firetype", "psychic", "flying", "ice"}; - case 6: //charizard - return new String[] {"rock", "water", "electric"}; - case 9: //blastoise - return new String[] {"grass", "electric"}; - case 59: //arcanine - return new String[] {"ground", "water", "rock"}; - case 65: //alakazam - return new String[] {"dark", "bugtype", "ghosttype"}; - case 68: //machamp - return new String[] {"fairy", "flying", "psychic"}; - case 89: //muk - return new String[] {"psychic", "ground"}; - case 94: //gengar - return new String[] {"psychic", "dark", "ghosttype"}; - case 110: //weezing - return new String[] {"psychic"}; - case 112: //rhydon - return new String[] {"water", "grass:ground", "fighting", "ice", "steel"}; - case 125: //electabuzz - return new String[] {"ground"}; - case 126: //magmar - return new String[] {"ground", "water", "rock"}; - case 131: //lapras - return new String[] {"grass", "electric", "rock", "fighting"}; - case 129: //magikarp - return new String[] {"electric", "grass"}; - case 134: //vaporeon - return new String[] {"electric", "grass"}; - case 135: //flareon - return new String[] {"ground", "water", "rock"}; - case 136: //jolteon - return new String[] {"ground"}; - case 143: //snorlax - return new String[] {"fighting"}; - case 144: //articuno - return new String[] {"rock","steel","firetype","electric"}; - case 145: //zapdos - return new String[] {"rock","ice"}; - case 146: //moltres - return new String[] {"rock","water","electric"}; - case 150: //mewtwo - return new String[] {"bugtype","ghosttype","dark"}; - case 153: //bayleef - return new String[] {"ice", "firetype", "bugtype", "poison"}; - case 156: //quilava - return new String[] {"ground", "water", "rock"}; - case 159: //croconaw - return new String[] {"electric", "grass"}; - case 243: //raikou - return new String[] {"ground"}; - case 244: //entei - return new String[] {"ground", "water", "rock"}; - case 245: //suicine - return new String[] {"electric", "grass"}; - case 248: //tyranitar - return new String[] {"fighting", "grass", "bugtype", "ground", "water", "steel", "fairy"}; - case 249: //lugia - return new String[] {"rock","ghosttype","electric","ice","dark"}; + HashSet weaknesses = new HashSet<>(); + for (String type : Pokemon.getTypes(bossId)) { + weaknesses.addAll(Types.getWeaknesses(type)); + } + + for (String toReplace : SPECIAL_NAMES.keySet()) { + int oldSize = weaknesses.size(); + weaknesses.remove(toReplace); + if (weaknesses.size() < oldSize) { + weaknesses.add(SPECIAL_NAMES.get(toReplace)); + } } - return new String[]{}; + + String weaknessArray[] = new String[weaknesses.size()]; + return weaknesses.toArray(weaknessArray); } - public static String[] getBossStrengthsEmote(int bossId){ - switch(bossId){ - case 3: //venusaur - return new String[] {"water", "fairy"}; - case 6: //charizard - return new String[] {"fighting", "bugtype", "grass", "ice"}; - case 9: //blastoise - return new String[] {"ground", "rock", "firetype"}; - case 59: //arcanine - return new String[] {"bugtype", "steel", "grass", "ice"}; - case 65: //alakazam - return new String[] {"fighting", "poison"}; - case 68: //machamp - return new String[] {"normal", "rock", "steel", "ice", "dark"}; - case 89: //muk - return new String[] {"grass", "fair"}; - case 94: //gengar - return new String[] {"grass", "psychic", "fairy"}; - case 110: //weezing - return new String[] {"grass", "fairy"}; - case 112: //rhydon - return new String[] {"poison", "rock", "firetype", "electric", "ice"}; - case 125: //electabuzz - return new String[] {"flying", "water"}; - case 126: //magmar - return new String[] {"bugtype", "steel", "grass", "ice"}; - case 131: //lapras - return new String[] {"flying", "ground", "grass", "dragontype", "rock", "firetype"}; - case 129: //magikarp - return new String[] {"ground", "rock", "firetype"}; - case 134: //vaporeon - return new String[] {"ground", "rock", "firetype"}; - case 135: //flareon - return new String[] {"bugtype", "steel", "grass", "ice"}; - case 136: //jolteon - return new String[] {"flying", "water"}; - case 143: //snorlax - return new String[] {}; - case 144: //articuno - return new String[] {"fighting","flying","ground","bug","grass"}; - case 145: //zapdos - return new String[] {"fighting","flying","bugtype","water"}; - case 146: //moltres - return new String[] {"fighting","bugtype","grass","ice"}; - case 150: //mewtwo - return new String[] {"fighting","poison"}; - case 153: //bayleef - return new String[] {"ground", "rock", "water"}; - case 156: //quilava - return new String[] {"bugtype", "steel", "grass", "ice"}; - case 159: //croconaw - return new String[] {"ground", "rock", "firetype"}; - case 243: //raikou - return new String[] {"flying","water"}; - case 244: //entei - return new String[] {"bugtype","steel","grass","ice"}; - case 245: //suicine - return new String[] {"ground", "rock", "firetype"}; - case 248: //tyranitar - return new String[] {"flying", "bugtype", "ghosttype", "firetype", "psychic", "ice"}; - case 249: //lugia - return new String[] {"fighting","poison","bugtype","grass"}; + public static String[] getBossStrengthsEmote(int move1, int move2){ + HashSet strengths = new HashSet<>(); + + strengths.addAll(Types.getStrengths(Pokemon.getMoveType(move1))); + strengths.addAll(Types.getStrengths(Pokemon.getMoveType(move2))); + + for (String toReplace : SPECIAL_NAMES.keySet()) { + int oldSize = strengths.size(); + strengths.remove(toReplace); + if (strengths.size() < oldSize) { + strengths.add(SPECIAL_NAMES.get(toReplace)); + } } - return new String[]{}; + + String strengthsArray[] = new String[strengths.size()]; + return strengths.toArray(strengthsArray); } diff --git a/src/raids/RaidLobby.java b/src/raids/RaidLobby.java index 92ae612..5425f47 100644 --- a/src/raids/RaidLobby.java +++ b/src/raids/RaidLobby.java @@ -24,13 +24,13 @@ public class RaidLobby { String roleId = null; String channelId = null; - public String lobbyCode; + public final String lobbyCode; public RaidSpawn spawn; - HashSet memberIds = new HashSet<>(); + private final HashSet memberIds = new HashSet<>(); - static SimpleLog raidLobbyLog = SimpleLog.getLog("raid-lobbies"); + private static final SimpleLog raidLobbyLog = SimpleLog.getLog("raid-lobbies"); ScheduledExecutor shutDownService = null; @@ -165,7 +165,7 @@ public void joinLobby(String userId){ DBManager.updateLobby(lobbyCode,memberCount(), (int) nextTimeLeftUpdate,inviteCode); } - public Role getRole() { + private Role getRole() { return guild.getRoleById(roleId); } @@ -251,7 +251,7 @@ public Message getStatusMessage(){ String strengthEmoteStr = ""; - for (String s : Raid.getBossStrengthsEmote(spawn.bossId)) { + for (String s : Raid.getBossStrengthsEmote(spawn.move1Id,spawn.move2Id)) { Emote emote = Raid.emotes.get(s); strengthEmoteStr += (emote == null ? "" :emote.getAsMention()); } @@ -259,7 +259,7 @@ public Message getStatusMessage(){ embedBuilder.addField("Strong Against", strengthEmoteStr, true); embedBuilder.setThumbnail(spawn.getIcon()); - embedBuilder.setImage(spawn.getImage()); + embedBuilder.setImage(spawn.getImage("formatting.ini")); }else{ embedBuilder.setTitle(String.format("Raid status for level %s egg in %s - Lobby %s", spawn.properties.get("level"), @@ -281,7 +281,7 @@ public Message getStatusMessage(){ false); embedBuilder.setThumbnail(spawn.getIcon()); - embedBuilder.setImage(spawn.getImage()); + embedBuilder.setImage(spawn.getImage("formatting.ini")); } MessageBuilder messageBuilder = new MessageBuilder().setEmbed(embedBuilder.build()); @@ -306,7 +306,7 @@ public Message getBossInfoMessage() { String strengthEmoteStr = ""; - for (String s : Raid.getBossStrengthsEmote(spawn.bossId)) { + for (String s : Raid.getBossStrengthsEmote(spawn.move1Id,spawn.move2Id)) { Emote emote = Raid.emotes.get(s); strengthEmoteStr += (emote == null ? "" :emote.getAsMention()); } diff --git a/src/raids/RaidSpawn.java b/src/raids/RaidSpawn.java index 542451f..697ffc4 100644 --- a/src/raids/RaidSpawn.java +++ b/src/raids/RaidSpawn.java @@ -1,55 +1,61 @@ package raids; import core.DBManager; +import core.Spawn; +import core.Team; import core.Util; import maps.GeofenceIdentifier; import maps.ReverseGeocoder; import net.dv8tion.jda.core.EmbedBuilder; import net.dv8tion.jda.core.MessageBuilder; import net.dv8tion.jda.core.entities.Message; +import pokemon.PokeMove; import pokemon.Pokemon; import java.awt.*; import java.sql.Timestamp; import java.time.Instant; -import java.util.ArrayList; import java.util.HashMap; -import static core.MessageListener.*; +import static core.MessageListener.config; +import static core.MessageListener.loadConfig; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static maps.Geofencing.getGeofence; import static maps.Geofencing.loadGeofences; -import static pokemon.PokeSpawn.getNextKey; -import static pokemon.PokeSpawn.printFormat; /** * Created by Owner on 27/06/2017. */ -public class RaidSpawn { - - static final String NORMAL_EGG = "https://raw.githubusercontent.com/ZeChrales/PogoAssets/master/static_assets/png/ic_raid_egg_normal.png"; - static final String RARE_EGG = "https://raw.githubusercontent.com/ZeChrales/PogoAssets/master/static_assets/png/ic_raid_egg_rare.png"; - static final String LEGENDARY_EGG = "https://raw.githubusercontent.com/ZeChrales/PogoAssets/master/static_assets/png/ic_raid_egg_legendary.png"; - - final String name; - final double lat; - final double lon; - public final Timestamp raidEnd; - public final Timestamp battleStart; - public final int bossId; - final int bossCp; - final String move_1; - final String move_2; - public final int raidLevel; - public final String gymId; - private final ArrayList geofenceIdentifiers; - - public HashMap properties = new HashMap<>(); +public class RaidSpawn extends Spawn +{ + + private static final String NORMAL_EGG = "https://raw.githubusercontent.com/ZeChrales/PogoAssets/master/static_assets/png/ic_raid_egg_normal.png"; + private static final String RARE_EGG = "https://raw.githubusercontent.com/ZeChrales/PogoAssets/master/static_assets/png/ic_raid_egg_rare.png"; + private static final String LEGENDARY_EGG = "https://raw.githubusercontent.com/ZeChrales/PogoAssets/master/static_assets/png/ic_raid_egg_legendary.png"; + + private String name; + public Timestamp raidEnd; + public Timestamp battleStart; + public int bossId; + private int bossCp; + public int raidLevel; + public String gymId; + private String imageUrl; - private String formatKey; - private Message builtMessage = null; + private final HashMap builtMessages = new HashMap<>(); private int lobbyCode; + public int move1Id; + public int move2Id; + + public RaidSpawn(int id, boolean egg) { + super(); + if (egg){ + raidLevel = id; + }else{ + bossId = id; + } + } public static void main(String[] args) { @@ -58,18 +64,18 @@ public static void main(String[] args) { DBManager.novabotdbConnect(); RaidSpawn spawn = new RaidSpawn("gym", "123",-35.34200996278955,149.05508042811897, - new Timestamp(DBManager.getCurrentTime().getTime() + 504000), + Team.Valor, new Timestamp(DBManager.getCurrentTime().getTime() + 504000), new Timestamp(DBManager.getCurrentTime().getTime() + 6000000), 6, 11003, - "fire", - "fire blast", + 2, + 4, 3); spawn.setLobbyCode(1); // System.out.println(spawn.getLobbyCode()); - Message message = spawn.buildMessage(); + Message message = spawn.buildMessage("formatting.ini"); System.out.println(message.getEmbeds().get(0).getTitle()); System.out.println(message.getEmbeds().get(0).getDescription()); @@ -89,14 +95,20 @@ public static void main(String[] args) { // jda.getUserById("107730875596169216").openPrivateChannel().queue(success -> success.sendMessage(message).queue(m -> m.addReaction(WHITE_GREEN_CHECK).queue())); } - public RaidSpawn(String name, String gymId, double lat, double lon, Timestamp raidEnd, Timestamp battleStart, int bossId, int bossCp,String move_1, String move_2, int raidLevel) { + public RaidSpawn(String name, String gymId, double lat, double lon, Team team, Timestamp raidEnd, Timestamp battleStart, int bossId, int bossCp, int move_1, int move_2, int raidLevel) { this.name = name; properties.put("gym_name",name); this.gymId = gymId; this.lat = lat; + properties.put("lat", String.valueOf(lat)); + this.lon = lon; + properties.put("lng", String.valueOf(lon)); + + Team team1 = team; + properties.put("team_name",team.toString()); this.geofenceIdentifiers = getGeofence(lat,lon); @@ -120,13 +132,16 @@ public RaidSpawn(String name, String gymId, double lat, double lon, Timestamp ra this.bossId = bossId; this.bossCp = bossCp; - this.move_1 = move_1; - this.move_2 = move_2; + this.move1Id = move_1; + this.move2Id = move_2; + this.move_1 = PokeMove.idToName(move1Id); + this.move_2 = PokeMove.idToName(move2Id); + if(bossId != 0) { properties.put("pkmn", Util.capitaliseFirst(Pokemon.idToName(bossId))); properties.put("cp", String.valueOf(bossCp)); - properties.put("quick_move",move_1); - properties.put("charge_move",move_2); + properties.put("quick_move",this.move_1); + properties.put("charge_move",this.move_2); } this.raidLevel = raidLevel; @@ -135,13 +150,6 @@ public RaidSpawn(String name, String gymId, double lat, double lon, Timestamp ra properties.put("lobbycode","unkn"); } - private String getAppleMapsLink() { - return String.format("http://maps.apple.com/maps?daddr=%s,%s&z=10&t=s&dirflg=w", this.lat, this.lon); - } - - private String getGmapsLink() { - return String.format("https://www.google.com/maps?q=loc:%s,%s", this.lat, this.lon); - } public String timeLeft(Timestamp untilTime) { Timestamp currentTime = DBManager.getCurrentTime(); @@ -176,38 +184,40 @@ public String toString() { return String.format("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s", name,gymId,lat,lon,raidEnd,battleStart,bossId,bossCp,raidLevel,move_1,move_2); } - public Message buildMessage() { - if(builtMessage != null) return builtMessage; - - final MessageBuilder messageBuilder = new MessageBuilder(); - final EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setColor(getColor()); + public Message buildMessage(String formatFile) { + + if(builtMessages.get(formatFile) == null) { + + final MessageBuilder messageBuilder = new MessageBuilder(); + final EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(getColor()); + + if(bossId == 0) { + formatKey = "raidEgg"; + embedBuilder.setTitle(config.formatStr(properties,config.getTitleFormatting(formatFile, formatKey)),config.formatStr(properties,config.getTitleUrl(formatFile, formatKey))); + embedBuilder.setDescription(config.formatStr(properties,config.getBodyFormatting(formatFile, formatKey)+ ( + raidLevel >= 3 && config.isRaidOrganisationEnabled() + ? "\n\nJoin the discord lobby to coordinate with other players, and be alerted when this egg hatches. Join by clicking the ✅ emoji below this post, or by typing `!joinraid ` in any novabot channel." + : ""))); + }else{ + formatKey = "raidBoss"; + embedBuilder.setTitle(config.formatStr(properties,config.getTitleFormatting(formatFile, formatKey)),config.formatStr(properties,config.getTitleUrl(formatFile, formatKey))); + embedBuilder.setDescription(config.formatStr(properties,config.getBodyFormatting(formatFile, formatKey) + ( + raidLevel >= 3 && config.isRaidOrganisationEnabled() + ? "\n\nJoin the discord lobby to coordinate with other players by clicking the ✅ emoji below this post, or by typing `!joinraid ` in any novabot channel." + : ""))); + } + embedBuilder.setThumbnail(getIcon()); + if (config.showMap(formatFile, formatKey)) { + embedBuilder.setImage(getImage(formatFile)); + } + embedBuilder.setFooter(config.getFooterText(), null); + embedBuilder.setTimestamp(Instant.now()); + messageBuilder.setEmbed(embedBuilder.build()); - if(bossId == 0) { - formatKey = "raidEgg"; - embedBuilder.setTitle(config.formatStr(properties,config.getTitleFormatting(formatKey)),config.formatStr(properties,config.getTitleUrl(formatKey))); - embedBuilder.setDescription(config.formatStr(properties,config.getBodyFormatting(formatKey)+ ( - raidLevel >= 3 && config.isRaidOrganisationEnabled() - ? "\n\nJoin the discord lobby to coordinate with other players, and be alerted when this egg hatches. Join by clicking the ✅ emoji below this post, or by typing `!joinraid ` in any novabot channel." - : ""))); - }else{ - formatKey = "raidBoss"; - embedBuilder.setTitle(config.formatStr(properties,config.getTitleFormatting(formatKey)),config.formatStr(properties,config.getTitleUrl(formatKey))); - embedBuilder.setDescription(config.formatStr(properties,config.getBodyFormatting(formatKey) + ( - raidLevel >= 3 && config.isRaidOrganisationEnabled() - ? "\n\nJoin the discord lobby to coordinate with other players by clicking the ✅ emoji below this post, or by typing `!joinraid ` in any novabot channel." - : ""))); - } - embedBuilder.setThumbnail(getIcon()); - if (config.showMap(formatKey)) { - embedBuilder.setImage(getImage()); + builtMessages.put(formatFile,messageBuilder.build()); } - embedBuilder.setFooter(config.getFooterText(), null); - embedBuilder.setTimestamp(Instant.now()); - messageBuilder.setEmbed(embedBuilder.build()); - - this.builtMessage = messageBuilder.build(); - return builtMessage; + return builtMessages.get(formatFile); } public String getStartTime() { @@ -218,14 +228,7 @@ public String getDisappearTime() { return printFormat.format(raidEnd); } - public String getImage() { - if (this.imageUrl == null) { - return this.imageUrl = "https://maps.googleapis.com/maps/api/staticmap?" + String.format("zoom=%s&size=%sx%s&markers=color:red|%s,%s&key=%s", config.getMapZoom(formatKey), config.getMapWidth(formatKey), config.getMapHeight(formatKey), this.lat, this.lon, getNextKey()); - } - return this.imageUrl; - } - - public Color getColor() { + private Color getColor() { switch(raidLevel) { case 1: return new Color(0x9d9d9d); @@ -257,18 +260,6 @@ public String getIcon() { return Pokemon.getIcon(bossId); } - public ArrayList getGeofences() { - return geofenceIdentifiers; - } - - public ArrayList getGeofenceIds() { - return geofenceIdentifiers; - } - - public String getSuburb() { - return properties.get("city"); - } - public void setLobbyCode(int id) { this.lobbyCode = id; diff --git a/test.json b/test.json new file mode 100644 index 0000000..ca350b7 --- /dev/null +++ b/test.json @@ -0,0 +1,4 @@ +{ + "Egg2": "True", + "Level3": "True" +} \ No newline at end of file diff --git a/ultrarare.json b/ultrarare.json index 7688f1a..0bf6861 100644 --- a/ultrarare.json +++ b/ultrarare.json @@ -1,394 +1,13 @@ { - "pokemon": { - "Bulbasaur": "False", - "Ivysaur": "False", - "Venusaur": "False", - "Charmander": "False", - "Charmeleon": "False", - "Charizard": "False", - "Squirtle": "False", - "Wartortle": "False", - "Blastoise": "False", - "Caterpie": "False", - "Metapod": "False", - "Butterfree": "False", - "Weedle": "False", - "Kakuna": "False", - "Beedrill": "False", - "Pidgey": "False", - "Pidgeotto": "False", - "Pidgeot": "False", - "Rattata": "False", - "Raticate": "False", - "Spearow": "False", - "Fearow": "False", - "Ekans": "False", - "Arbok": "False", - "Pikachu": "False", - "Raichu": "False", - "Sandshrew": "False", - "Sandslash": "False", - "Nidoran♀": "False", - "Nidorina": "False", - "Nidoqueen": "False", - "Nidoran♂": "False", - "Nidorino": "False", - "Nidoking": "False", - "Clefairy": "False", - "Clefable": "False", - "Vulpix": "False", - "Ninetales": "False", - "Jigglypuff": "False", - "Wigglytuff": "False", - "Zubat": "False", - "Golbat": "False", - "Oddish": "False", - "Gloom": "False", - "Vileplume": "False", - "Paras": "False", - "Parasect": "False", - "Venonat": "False", - "Venomoth": "False", - "Diglett": "False", - "Dugtrio": "False", - "Meowth": "False", - "Persian": "False", - "Psyduck": "False", - "Golduck": "False", - "Mankey": "False", - "Primeape": "False", - "Growlithe": "False", - "Arcanine": "False", - "Poliwag": "False", - "Poliwhirl": "False", - "Poliwrath": "False", - "Abra": "False", - "Kadabra": "False", - "Alakazam": "False", - "Machop": "False", - "Machoke": "False", - "Machamp": "False", - "Bellsprout": "False", - "Weepinbell": "False", - "Victreebel": "False", - "Tentacool": "False", - "Tentacruel": "False", - "Geodude": "False", - "Graveler": "False", - "Golem": "False", - "Ponyta": "False", - "Rapidash": "False", - "Slowpoke": "False", - "Slowbro": "False", - "Magnemite": "False", - "Magneton": "False", - "Farfetch'd": "False", - "Doduo": "False", - "Dodrio": "False", - "Seel": "False", - "Dewgong": "False", - "Grimer": "False", - "Muk": "False", - "Shellder": "False", - "Cloyster": "False", - "Gastly": "False", - "Haunter": "False", - "Gengar": "False", - "Onix": "False", - "Drowzee": "False", - "Hypno": "False", - "Krabby": "False", - "Kingler": "False", - "Voltorb": "False", - "Electrode": "False", - "Exeggcute": "False", - "Exeggutor": "False", - "Cubone": "False", - "Marowak": "False", - "Hitmonlee": "False", - "Hitmonchan": "False", - "Lickitung": "False", - "Koffing": "False", - "Weezing": "False", - "Rhyhorn": "False", - "Rhydon": "False", - "Chansey": "False", - "Tangela": "False", - "Kangaskhan": "False", - "Horsea": "False", - "Seadra": "False", - "Goldeen": "False", - "Seaking": "False", - "Staryu": "False", - "Starmie": "False", - "Mr. Mime": "False", - "Scyther": "False", - "Jynx": "False", - "Electabuzz": "False", - "Magmar": "False", - "Pinsir": "False", - "Tauros": "False", - "Magikarp": "False", - "Gyarados": "False", - "Lapras": "True", - "Ditto": "False", - "Eevee": "False", - "Vaporeon": "False", - "Jolteon": "False", - "Flareon": "False", - "Porygon": "False", - "Omanyte": "False", - "Omastar": "False", - "Kabuto": "False", - "Kabutops": "False", - "Aerodactyl": "False", - "Snorlax": { - "min_iv": "90" - }, - "Articuno": "False", - "Zapdos": "False", - "Moltres": "False", - "Dratini": "False", - "Dragonair": "False", - "Dragonite": { - "min_iv": "90" - }, - "Mewtwo": "False", - "Mew": "False", - "Chikorita": "False", - "Bayleef": "False", - "Meganium": "False", - "Cyndaquil": "False", - "Quilava": "False", - "Typhlosion": "False", - "Totodile": "False", - "Croconaw": "False", - "Feraligatr": "False", - "Sentret": "False", - "Furret": "False", - "Hoothoot": "False", - "Noctowl": "False", - "Ledyba": "False", - "Ledian": "False", - "Spinarak": "False", - "Ariados": "False", - "Crobat": "False", - "Chinchou": "False", - "Lanturn": "False", - "Pichu": "False", - "Cleffa": "False", - "Igglybuff": "False", - "Togepi": "False", - "Togetic": "False", - "Natu": "False", - "Xatu": "False", - "Mareep": "False", - "Flaaffy": "False", - "Ampharos": "True", - "Bellossom": "False", - "Marill": "False", - "Azumarill": "False", - "Sudowoodo": "False", - "Politoed": "False", - "Hoppip": "False", - "Skiploom": "False", - "Jumpluff": "False", - "Aipom": "False", - "Sunkern": "False", - "Sunflora": "False", - "Yanma": "False", - "Wooper": "False", - "Quagsire": "False", - "Espeon": "False", - "Umbreon": "False", - "Murkrow": "False", - "Slowking": "False", - "Misdreavus": "False", - "Unown": "True", - "Wobbuffet": "False", - "Girafarig": "False", - "Pineco": "False", - "Forretress": "False", - "Dunsparce": "False", - "Gligar": "False", - "Steelix": "False", - "Snubbull": "False", - "Granbull": "False", - "Qwilfish": "False", - "Scizor": "False", - "Shuckle": "False", - "Heracross": "False", - "Sneasel": "False", - "Teddiursa": "False", - "Ursaring": "False", - "Slugma": "False", - "Magcargo": "False", - "Swinub": "False", - "Piloswine": "False", - "Corsola": "False", - "Remoraid": "False", - "Octillery": "False", - "Delibird": "False", - "Mantine": "False", - "Skarmory": "False", - "Houndour": "False", - "Houndoom": "False", - "Kingdra": "False", - "Phanpy": "False", - "Donphan": "False", - "Porygon2": "False", - "Stantler": "False", - "Smeargle": "False", - "Tyrogue": "False", - "Hitmontop": "False", - "Smoochum": "False", - "Elekid": "False", - "Magby": "False", - "Miltank": "False", - "Blissey": "True", - "Raikou": "False", - "Entei": "False", - "Suicune": "False", - "Larvitar": "False", - "Pupitar": "False", - "Tyranitar": "True", - "Lugia": "False", - "Ho-Oh": "False", - "Celebi": "False", - "Treecko": "False", - "Grovyle": "False", - "Sceptile": "False", - "Torchic": "False", - "Combusken": "False", - "Blaziken": "False", - "Mudkip": "False", - "Marshtomp": "False", - "Swampert": "False", - "Poochyena": "False", - "Mightyena": "False", - "Zigzagoon": "False", - "Linoone": "False", - "Wurmple": "False", - "Silcoon": "False", - "Beautifly": "False", - "Cascoon": "False", - "Dustox": "False", - "Lotad": "False", - "Lombre": "False", - "Ludicolo": "False", - "Seedot": "False", - "Nuzleaf": "False", - "Shiftry": "False", - "Taillow": "False", - "Swellow": "False", - "Wingull": "False", - "Pelipper": "False", - "Ralts": "False", - "Kirlia": "False", - "Gardevoir": "False", - "Surskit": "False", - "Masquerain": "False", - "Shroomish": "False", - "Breloom": "False", - "Slakoth": "False", - "Vigoroth": "False", - "Slaking": "False", - "Nincada": "False", - "Ninjask": "False", - "Shedinja": "False", - "Whismur": "False", - "Loudred": "False", - "Exploud": "False", - "Makuhita": "False", - "Hariyama": "False", - "Azurill": "False", - "Nosepass": "False", - "Skitty": "False", - "Delcatty": "False", - "Sableye": "False", - "Mawile": "False", - "Aron": "False", - "Lairon": "False", - "Aggron": "False", - "Meditite": "False", - "Medicham": "False", - "Electrike": "False", - "Manectric": "False", - "Plusle": "False", - "Minun": "False", - "Volbeat": "False", - "Illumise": "False", - "Roselia": "False", - "Gulpin": "False", - "Swalot": "False", - "Carvanha": "False", - "Sharpedo": "False", - "Wailmer": "False", - "Wailord": "False", - "Numel": "False", - "Camerupt": "False", - "Torkoal": "False", - "Spoink": "False", - "Grumpig": "False", - "Spinda": "False", - "Trapinch": "False", - "Vibrava": "False", - "Flygon": "False", - "Cacnea": "False", - "Cacturne": "False", - "Swablu": "False", - "Altaria": "False", - "Zangoose": "False", - "Seviper": "False", - "Lunatone": "False", - "Solrock": "False", - "Barboach": "False", - "Whiscash": "False", - "Corphish": "False", - "Crawdaunt": "False", - "Baltoy": "False", - "Claydol": "False", - "Lileep": "False", - "Cradily": "False", - "Anorith": "False", - "Armaldo": "False", - "Feebas": "False", - "Milotic": "False", - "Castform": "False", - "Kecleon": "False", - "Shuppet": "False", - "Banette": "False", - "Duskull": "False", - "Dusclops": "False", - "Tropius": "False", - "Chimecho": "False", - "Absol": "False", - "Wynaut": "False", - "Snorunt": "False", - "Glalie": "False", - "Spheal": "False", - "Sealeo": "False", - "Walrein": "False", - "Clamperl": "False", - "Huntail": "False", - "Gorebyss": "False", - "Relicanth": "False", - "Luvdisc": "False", - "Bagon": "False", - "Shelgon": "False", - "Salamence": "False", - "Beldum": "False", - "Metang": "False", - "Metagross": "False", - "Regirock": "False", - "Regice": "False", - "Registeel": "False", - "Latias": "False", - "Latios": "False", - "Kyogre": "False", - "Groudon": "False", - "Rayquaza": "False", - "Jirachi": "False", - "Deoxys": "False" - } + "Lapras": "True", + "Snorlax": { + "min_iv": "90" + }, + "Dragonite": { + "min_iv": "90" + }, + "Ampharos": "True", + "Unown": "True", + "Blissey": "True", + "Tyranitar": "True" } \ No newline at end of file diff --git a/unown.json b/unown.json new file mode 100644 index 0000000..e7cdcae --- /dev/null +++ b/unown.json @@ -0,0 +1,3 @@ +{ + "Unown": "True" +} \ No newline at end of file