-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathencountersLocation.py
254 lines (196 loc) · 9.92 KB
/
encountersLocation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
import sys
from tabulate import tabulate
import pokeTP_utils as utils
##
DEBUG_MODE = True
class Encounter:
def __init__ (self, method, condition_list, pokemon):
self.method = method
self.condition_list = condition_list
self.pokemon = pokemon
self.min_level = 100
self.max_level = 0
self.rate = 0
def getMethod (self):
return self.method
def getCondition (self):
return self.condition_list
def getPokemon (self):
return self.pokemon
def getRate (self):
return self.rate
def addToRate (self, rate):
self.rate += rate
def updateLevelMargin (self, min_level, max_level):
if (min_level < self.min_level):
self.min_level = min_level
if (max_level > self.max_level):
self.max_level = max_level
def isSameEncounter (self, method, condition_list, pokemon):
return True if (method == self.method and condition_list == self.condition_list and pokemon == self.pokemon) else False
def exportConditionsString (self):
conditions_str = ""
for condition in self.condition_list:
conditions_str += f'{condition}, '
# removing the last ', '
return conditions_str[:-2]
def exportLevelRangeString (self):
level_range_str = f'{self.min_level}-{self.max_level}'
return level_range_str
##
def selectLocationArea (location_query):
location_iterator = 0
locations_list = []
# Collecting each location that matches the location_query onto a list
while True:
results = utils.queryPokeAPI(f'https://pokeapi.co/api/v2/location?offset={location_iterator}&limit=20/')
# Check if the locations on the list match the location_query
for location in results['results']:
if (location_query in location['name']):
location_entry = {
'name': location['name'],
'url': location['url']
}
locations_list.append(location_entry)
# Update the iterator according to the default pokeAPI limit (=20)
location_iterator += 20
# Aborts the search when the last batch is reached (there's no next)
if (results['next'] is None):
break
if (not len(locations_list)):
utils.debugPrint(f"Error: couldn't obtain the locations list\nAborting...", DEBUG_MODE)
sys.exit()
if (len(locations_list) == 1):
# 35 truncates just the location id from the url
utils.debugPrint(f"Location selected: {locations_list[0]['name']} ({locations_list[0]['url'][35:-1]})", DEBUG_MODE)
return locations_list[0]
# If the list has more than one element, the search was not conclusive
# A list of the matches should be displayed so the user can manually pick a location
print(f"Ambiguous location name, did you mean?")
list_iterator = 0
for location in locations_list:
list_iterator += 1
print(f'\t{list_iterator})', location['name'])
# Input sanity check
while True:
selected_location = int(input(f"Please select the desired location [1 - {list_iterator}]: "))
if (selected_location > 0 and selected_location <= len(locations_list)):
break
print(f"Error: your input is outside the allowed selection, please input a number in the following interval: 0 - {list_iterator}\n")
utils.debugPrint(f"Location selected: {locations_list[selected_location-1]['name']} {locations_list[selected_location-1]['url'][35:-1]}", DEBUG_MODE)
return locations_list[selected_location-1]
def generateMethodEncounterList ():
# Generate encounter_method_list
encounter_method_count = 31
encounter_method_list = []
for encounter_method_id in range(1, encounter_method_count):
response = utils.queryPokeAPI(f'https://pokeapi.co/api/v2/encounter-method/{encounter_method_id}/')
encounter_method_list.append(response['name'])
return encounter_method_list
def printEncounterListTable (encounter_method, encounter_list):
# For each element of the encounter_list, search for matches in
# the encounter_list and print them in a nice table
table_title = f"Method: {encounter_method}"
table_entries_list = [
["Pokémon", "Rate", "Levels", "Conditions"]
]
for encounter in encounter_list:
if (encounter.getMethod() == encounter_method):
table_entry = [encounter.getPokemon(), f'{encounter.getRate()}%', encounter.exportLevelRangeString(), encounter.exportConditionsString()]
table_entries_list.append(table_entry)
if (len(table_entries_list) == 1):
return
encounters_table = tabulate(table_entries_list, headers="firstrow", tablefmt="grid")
table_width = len(encounters_table.split("\n")[0])
utils.printTableHead(table_title, table_width)
print(encounters_table)
def generateGameEncounterList (location_area_encounters, game_version):
# Initialize Encounter List
encounter_list = []
# pokeAPI groups encounters in a given location by the game's version_details
for pokemon_encounter in location_area_encounters:
version_encounters = pokemon_encounter['version_details']
# We should only consider the encounters where the
# game's version name is the one we are looking for
for encounters in version_encounters:
if (encounters['version']['name'] == game_version):
# A single encounter can have multiple conditions so these should be
# stored as in list. The other parameters are unique per encounter
for encounter in encounters['encounter_details']:
encounter_pokemon_name = pokemon_encounter['pokemon']['name']
encounter_method = encounter['method']['name']
encounter_conditions = []
for encounter_condition in encounter['condition_values']:
encounter_conditions.append(encounter_condition['name'])
# Composing the encounter_list by checking if an encounter with
# the same pokemon, method and conditions is already on the list
# pokeAPI records separate encounter entries for different pokemon
# levels which come with different rates, I am grouping those in the
# same encounter entry while updating the level margin and adding the rates
isItemFound = False
for item in encounter_list:
if (item.isSameEncounter(encounter_method, encounter_conditions, encounter_pokemon_name)):
item.addToRate(encounter['chance'])
item.updateLevelMargin(encounter['min_level'], encounter['max_level'])
isItemFound = True
if (not isItemFound):
encounter_entry = Encounter(encounter_method, encounter_conditions, encounter_pokemon_name)
encounter_entry.addToRate(encounter['chance'])
encounter_entry.updateLevelMargin(encounter['min_level'], encounter['max_level'])
encounter_list.append(encounter_entry)
return encounter_list
##
def encountersLocation (game_version, location_area_url, debug_flag = True):
# Set debug mode
global DEBUG_MODE
DEBUG_MODE = debug_flag
utils.toggleDebugMode(debug_flag)
full_encounter_list = []
# Search pokeAPI's location-areas belonging to the selected location
location_areas_list = utils.getLocationAreasFromLocation(location_area_url)
# List encounters for each location-area in the location_areas_list
for location_area in location_areas_list:
# Parse location-area information from pokeAPI into a data frame
queried_location_area = utils.queryPokeAPI(f'https://pokeapi.co/api/v2/location-area/{location_area}/')
location_area_encounters = queried_location_area['pokemon_encounters']
# Generate encounter_list of a given location in a given game
encounter_list = generateGameEncounterList(location_area_encounters, game_version)
# Display error message if encounter_list is empty
if (not len(encounter_list)):
utils.debugPrint(f"There are no encounters in {location_area} for {game_version}", DEBUG_MODE)
continue
# Sorting the encounter list by rate
encounter_list = sorted(encounter_list, key=Encounter.getRate, reverse=True)
# Add location_area info to the encounter_list
encounter_dict = {
'location_area': location_area,
'encounter_list': encounter_list
}
full_encounter_list.append(encounter_dict)
return full_encounter_list
def main (argv, argc):
if (argc != 3):
print(f"Invadid arguments: syntax is {{game_version_name}} {{location_area_query}}")
sys.exit()
# game_version = "white"
# location_area_id = "unova-route-6-area"
# game_version = "blue"
# location_area_id = "kanto-route-1-area"
game_version = argv[1]
location_query = argv[2]
# Check game_version query in pokeAPI's game list
game_version = utils.selectGameName(game_version)
# Search pokeAPI's location and select the one corresponding to location_query
location_area = selectLocationArea(location_query)
full_encounter_list = encountersLocation(game_version, location_area['url'])
# Printing the results
utils.printFramedTitle(f".: Encounters in {location_area['name']} :.", new_lines=1)
for encounter_dict in full_encounter_list:
encounter_method_list = generateMethodEncounterList()
utils.printFramedTitle(encounter_dict['location_area'], new_lines=1)
for encounter_method in encounter_method_list:
printEncounterListTable(encounter_method, encounter_dict['encounter_list'])
return
##
if __name__ == '__main__':
main(sys.argv, len(sys.argv))