You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
423 lines
17 KiB
423 lines
17 KiB
from PyQt6.QtCore import QObject, pyqtSignal, QRunnable
|
|
import json
|
|
|
|
from cache import cache
|
|
from db import db
|
|
|
|
from utility.data import exclusive_choice_pokemon
|
|
from utility.functions import get_shiftable_forms, get_shiftable_forms_bidirectional, parse_pfic, sanitize_filename
|
|
|
|
class GeneratePlanWorkerSignals(QObject):
|
|
finished = pyqtSignal(list)
|
|
|
|
class GeneratePlanWorker(QRunnable):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.signals = GeneratePlanWorkerSignals()
|
|
self.caught_pokemon = {}
|
|
self.group_plan = []
|
|
self.game_plan = []
|
|
|
|
def run(self):
|
|
try:
|
|
gathered_data = self.generate_plan()
|
|
self.signals.finished.emit(gathered_data)
|
|
except Exception as e:
|
|
print(f"Error gathering Pokémon home storage status: {e}")
|
|
|
|
def generate_plan(self):
|
|
generational_groups = [1, 2], [3, 4, 5], [6], [7], [8], [9]
|
|
|
|
for group in generational_groups:
|
|
group_plan = self.plan_for_group(group)
|
|
self.group_plan.append(group_plan)
|
|
|
|
for group in self.group_plan:
|
|
for game in group:
|
|
game_plan = self.plan_for_game(game, group[game])
|
|
self.game_plan.append(game_plan)
|
|
|
|
storable_in_home = db.get_pokemon_home_list()
|
|
|
|
total_accounted_for = 0
|
|
for entry in self.game_plan:
|
|
total_accounted_for += len(entry["pokemon_map"])
|
|
|
|
total_needed = len(storable_in_home)
|
|
|
|
for home_pokemon in storable_in_home:
|
|
found = False
|
|
for game in self.game_plan:
|
|
if home_pokemon["pfic"] in game["pokemon_map"]:
|
|
found = True
|
|
break
|
|
if not found:
|
|
print(home_pokemon)
|
|
|
|
return self.game_plan
|
|
|
|
def plan_for_group(self, group):
|
|
group_plan = []
|
|
needed_pokemon = set()
|
|
games_in_group = []
|
|
game_pokemon = {}
|
|
|
|
for generation in group:
|
|
games_in_group.extend(db.get_games_by_generation(generation))
|
|
pokemon_in_generation = db.get_pokemon_by_generation(generation)
|
|
for pokemon in pokemon_in_generation:
|
|
pfic = pokemon["PFIC"]
|
|
|
|
if pokemon["storable_in_home"] == False:
|
|
continue
|
|
|
|
testing = [
|
|
"0140-01-000-1", "0138-01-000-1", "0140-01-000-2", "0138-01-000-2",
|
|
"0141-01-000-1", "0139-01-000-1", "0141-01-000-2", "0139-01-000-2",
|
|
]
|
|
|
|
#if pfic not in testing:
|
|
# continue
|
|
|
|
if pokemon["gender_relevant"] or pokemon["PFIC"][-1] == '0' or not any(pokemon["PFIC"][:-1] == s[:-1] for s in needed_pokemon):
|
|
needed_pokemon.add(pfic)
|
|
|
|
random = db.get_all_encounters("random")
|
|
static = db.get_all_encounters("static")
|
|
starter = db.get_all_encounters("starter")
|
|
encounters = []
|
|
encounters.extend(random)
|
|
encounters.extend(static)
|
|
encounters.extend(starter)
|
|
|
|
"""
|
|
def thingy(current_pfic):
|
|
evolution_chains = db.get_full_evolution_paths(current_pfic)
|
|
if evolution_chains and (len(evolution_chains["predecessors"]) > 0 or len(evolution_chains["successors"]) > 0):
|
|
for chains in evolution_chains["predecessors"]:
|
|
for evolved_pfic, method in chains:
|
|
if evolved_pfic in needed_pokemon:
|
|
game_pokemon[game['id']].add(evolved_pfic)
|
|
for shiftable_form in get_shiftable_forms_bidirectional(evolved_pfic):
|
|
game_pokemon[game['id']].add(shiftable_form["to_pfic"])
|
|
game_pokemon[game['id']].add(shiftable_form["from_pfic"])
|
|
|
|
for chains in evolution_chains["successors"]:
|
|
for evolved_pfic, method in chains:
|
|
if evolved_pfic in needed_pokemon:
|
|
game_pokemon[game['id']].add(evolved_pfic)
|
|
for shiftable_form in get_shiftable_forms_bidirectional(evolved_pfic):
|
|
game_pokemon[game['id']].add(shiftable_form["to_pfic"])
|
|
game_pokemon[game['id']].add(shiftable_form["from_pfic"])
|
|
|
|
for game in games_in_group:
|
|
game_pokemon[game['id']] = set()
|
|
for encounter in encounters:
|
|
current_pfic = encounter['PFIC']
|
|
if game["id"] == encounter["game_id"]:
|
|
game_pokemon[game['id']].add(current_pfic)
|
|
for shiftable_form in get_shiftable_forms_bidirectional(current_pfic):
|
|
game_pokemon[game['id']].add(shiftable_form["to_pfic"])
|
|
game_pokemon[game['id']].add(shiftable_form["from_pfic"])
|
|
thingy(shiftable_form["from_pfic"])
|
|
thingy(pfic)
|
|
"""
|
|
|
|
for game in games_in_group:
|
|
game_pokemon[game['id']] = set()
|
|
for encounter in encounters:
|
|
if game["id"] == encounter["game_id"]:
|
|
current_pfic = encounter['PFIC']
|
|
game_pokemon[game['id']].add(current_pfic)
|
|
evolution_chains = db.get_full_evolution_paths(current_pfic)
|
|
if evolution_chains and (len(evolution_chains["predecessors"]) > 0 or len(evolution_chains["successors"]) > 0):
|
|
for chains in evolution_chains["predecessors"]:
|
|
for evolved_pfic, method in chains:
|
|
if evolved_pfic in needed_pokemon:
|
|
game_pokemon[game['id']].add(evolved_pfic)
|
|
|
|
for chains in evolution_chains["successors"]:
|
|
for evolved_pfic, method in chains:
|
|
if evolved_pfic in needed_pokemon:
|
|
game_pokemon[game['id']].add(evolved_pfic)
|
|
|
|
selected_games = []
|
|
catch_in_game = {}
|
|
remaining_pokemon = needed_pokemon.copy()
|
|
available_games = games_in_group.copy()
|
|
while remaining_pokemon:
|
|
cache = {}
|
|
for game in available_games:
|
|
cache[game['id']] = self.get_covered_pokemon(game, remaining_pokemon, game_pokemon[game['id']])
|
|
|
|
pokemon_covered = {}
|
|
if cache:
|
|
best_game = max(available_games, key=lambda g: len(cache[g["id"]]))
|
|
pokemon_covered = cache[best_game['id']]
|
|
|
|
if not pokemon_covered:
|
|
print("No more Pokémon can be covered. Breaking loop.")
|
|
break
|
|
|
|
selected_games.append(best_game)
|
|
catch_in_game[best_game["id"]] = pokemon_covered
|
|
remaining_pokemon -= pokemon_covered
|
|
|
|
available_games.remove(best_game)
|
|
|
|
for game in selected_games[:-1]:
|
|
|
|
if game['id'] in cache and all(pokemon in cache[best_game['id']]
|
|
for pokemon in cache[game['id']] ):
|
|
selected_games.remove(game)
|
|
print(f"Removed {game['name']} as it's covered by {best_game['name']}")
|
|
|
|
for game in selected_games:
|
|
file_name = sanitize_filename(game["name"])
|
|
output_file = "./temp/"+file_name+".json"
|
|
with open(output_file, 'w', encoding='utf-8') as f:
|
|
temp = []
|
|
for pfic in catch_in_game[game["id"]]:
|
|
deets = db.get_pokemon_details(pfic, ["pfic", "name", "form_name"])
|
|
temp.append(deets)
|
|
temp.sort(key=lambda x: parse_pfic(x["pfic"]))
|
|
json.dump(temp, f, indent=4, ensure_ascii=False)
|
|
pass
|
|
|
|
return catch_in_game
|
|
|
|
def get_covered_pokemon(self, game, needed_pokemon, available_pokemon):
|
|
exclusive_groups = self.get_exclusive_groups(game['id'])
|
|
pokemon_covered = set()
|
|
|
|
search_value = "0412-04-002-2"
|
|
|
|
if search_value in needed_pokemon:
|
|
pass
|
|
|
|
if search_value in available_pokemon:
|
|
pass
|
|
|
|
evolution_paths = {}
|
|
evolution_predecessors = {}
|
|
all_pokemon = needed_pokemon | available_pokemon
|
|
|
|
for group in exclusive_groups:
|
|
for pfic in group:
|
|
all_pokemon.add(pfic)
|
|
|
|
for pfic in all_pokemon:
|
|
chain = db.get_full_evolution_paths(pfic)
|
|
evolution_paths[pfic] = chain
|
|
|
|
predecessors = set([pfic])
|
|
if chain and chain.get("predecessors"):
|
|
for entry in chain["predecessors"]:
|
|
for evolved_pfic, _ in entry:
|
|
predecessors.add(evolved_pfic)
|
|
evolution_predecessors[pfic] = predecessors
|
|
|
|
exclusive_group_predecessors = []
|
|
for group in exclusive_groups:
|
|
group_pokemon = set()
|
|
for pfic in group:
|
|
group_pokemon.update(evolution_predecessors.get(pfic, set()))
|
|
exclusive_group_predecessors.append(group_pokemon)
|
|
|
|
def record_pokemon(pfic, container, needed):
|
|
container.add(pfic)
|
|
evolution_chains = evolution_paths.get(pfic)
|
|
if evolution_chains and (evolution_chains.get("predecessors") or evolution_chains.get("successors")):
|
|
for chains in evolution_chains.get("predecessors", []):
|
|
for evolved_pfic, _ in chains:
|
|
if evolved_pfic in needed:
|
|
container.add(evolved_pfic)
|
|
for chains in evolution_chains.get("successors", []):
|
|
for evolved_pfic, _ in chains:
|
|
if evolved_pfic in needed:
|
|
container.add(evolved_pfic)
|
|
|
|
for pfic in needed_pokemon & available_pokemon:
|
|
if pfic in pokemon_covered:
|
|
continue
|
|
previous_evolutions = evolution_predecessors.get(pfic, set())
|
|
is_exclusive = False
|
|
for group_pokemon in exclusive_group_predecessors:
|
|
if previous_evolutions & group_pokemon:
|
|
is_exclusive = True
|
|
if not pokemon_covered & group_pokemon:
|
|
record_pokemon(pfic, pokemon_covered, needed_pokemon)
|
|
break
|
|
if not is_exclusive:
|
|
record_pokemon(pfic, pokemon_covered, needed_pokemon)
|
|
|
|
return pokemon_covered
|
|
|
|
def get_exclusive_groups(self, game_id):
|
|
for data in exclusive_choice_pokemon:
|
|
if data["game_id"] == game_id:
|
|
return data["choices"]
|
|
return []
|
|
|
|
def plan_for_game(self, game_id, required_pokemon):
|
|
game = db.get_game_by_id(game_id)
|
|
game_plan = {
|
|
"game_name": game['name'],
|
|
"pokemon_to_catch": {},
|
|
"pokemon_to_breed": {},
|
|
"pokemon_map": {}
|
|
}
|
|
|
|
print(f'Processing {game['name']}')
|
|
|
|
random = db.get_all_encounters("random")
|
|
static = db.get_all_encounters("static")
|
|
starter = db.get_all_encounters("starter")
|
|
encounters = []
|
|
encounters.extend(random)
|
|
encounters.extend(static)
|
|
encounters.extend(starter)
|
|
|
|
encounters_in_game = {}
|
|
|
|
for encounter in encounters:
|
|
if game["id"] == encounter["game_id"]:
|
|
encounters_in_game[encounter["PFIC"]] = encounter
|
|
|
|
pokemon_to_catch = {}
|
|
pokemon_to_breed = {}
|
|
pokemon_map = {}
|
|
other_map = {}
|
|
|
|
def record_catch(pfic, gender, to_get):
|
|
if pfic not in encounters_in_game:
|
|
pass
|
|
|
|
if pfic not in pokemon_to_catch:
|
|
pokemon_to_catch[pfic] = {}
|
|
|
|
data = pokemon_to_catch[pfic]
|
|
if gender not in data:
|
|
data[gender] = 1
|
|
else:
|
|
data[gender] += 1
|
|
|
|
if to_get not in pokemon_map:
|
|
pokemon_map[to_get] = {}
|
|
|
|
pokemon_map[to_get]["ByEvolving"] = pfic
|
|
if pfic not in other_map:
|
|
other_map[pfic] = {}
|
|
other_map[pfic]["EvolveTo"] = []
|
|
other_map[pfic]["BreedFor"] = []
|
|
other_map[pfic]["EvolveTo"].append(to_get)
|
|
|
|
def record_breed(pfic, gender, to_get):
|
|
if pfic not in pokemon_to_breed:
|
|
pokemon_to_breed[pfic] = {}
|
|
|
|
data = pokemon_to_breed[pfic]
|
|
if gender not in data:
|
|
data[gender] = 1
|
|
else:
|
|
data[gender] += 1
|
|
|
|
if to_get not in pokemon_map:
|
|
pokemon_map[to_get] = {}
|
|
|
|
pokemon_map[to_get]["ByBreeding"] = pfic
|
|
if pfic not in other_map:
|
|
other_map[pfic] = {}
|
|
other_map[pfic]["EvolveTo"] = []
|
|
other_map[pfic]["BreedFor"] = []
|
|
other_map[pfic]["BreedFor"].append(to_get)
|
|
|
|
# TODO: Move this to a last pass
|
|
#if pfic not in pokemon_to_catch:
|
|
# record_catch(pfic, gender)
|
|
|
|
def get_gender_string(value):
|
|
value_map = {"0": "Any", "1": "Male", "2": "Female"}
|
|
return value_map.get(str(value), "Unknown")
|
|
|
|
missing_count = 0
|
|
|
|
for pfic in required_pokemon:
|
|
pokemon_data = db.get_pokemon_details(pfic)
|
|
evolution_chain = db.get_full_evolution_paths(pfic)
|
|
if evolution_chain and not any(evolution_chain["predecessors"]):
|
|
if pokemon_data["is_baby_form"]:
|
|
recorded = False
|
|
evolutions = db.get_evolution_graph(pfic)
|
|
for evolution in evolutions:
|
|
if evolution in encounters_in_game:
|
|
bucket = get_gender_string(0)
|
|
record_breed(evolution, bucket, pfic)
|
|
recorded = True
|
|
if not recorded:
|
|
if pfic in encounters_in_game:
|
|
bucket = get_gender_string(pfic[-1])
|
|
record_catch(pfic, bucket, pfic)
|
|
else:
|
|
if pokemon_data["gender_relevant"]:
|
|
bucket = get_gender_string(pfic[-1])
|
|
record_catch(pfic, bucket, pfic)
|
|
else:
|
|
shiftable_forms = get_shiftable_forms(pfic)
|
|
if len(shiftable_forms) > 0:
|
|
shiftable_pfic = shiftable_forms[0]["to_pfic"]
|
|
record_catch(shiftable_pfic, "Any", pfic)
|
|
else:
|
|
record_catch(pfic, "Any", pfic)
|
|
elif evolution_chain:
|
|
bucket = get_gender_string(0)
|
|
if pokemon_data["gender_relevant"]:
|
|
bucket = get_gender_string(pfic[-1])
|
|
first_form = db.find_most_distant_predecessors(pfic)
|
|
if first_form:
|
|
first_form_pfic = first_form[0][0]
|
|
first_form_data = db.get_pokemon_details(first_form_pfic)
|
|
if first_form_data["is_baby_form"] == False:
|
|
shiftable_forms = get_shiftable_forms(first_form_pfic)
|
|
if len(shiftable_forms) > 0:
|
|
shiftable_pfic = shiftable_forms[0]["to_pfic"]
|
|
record_catch(shiftable_pfic, bucket, pfic)
|
|
else:
|
|
record_catch(first_form_pfic, bucket, pfic)
|
|
else:
|
|
recorded = False
|
|
evolutions = db.get_evolution_graph(first_form_pfic)
|
|
for evolution in evolutions:
|
|
if evolution in encounters_in_game:
|
|
record_catch(evolution, bucket, pfic)
|
|
recorded = True
|
|
if not recorded:
|
|
if first_form_pfic in encounters_in_game:
|
|
bucket = get_gender_string(pfic[-1])
|
|
record_catch(first_form_pfic, bucket, pfic)
|
|
|
|
total_catch = 0
|
|
for sub_dict in pokemon_to_catch.values():
|
|
total_catch += sum(sub_dict.values())
|
|
|
|
total_breed = 0
|
|
for sub_dict in pokemon_to_breed.values():
|
|
total_breed += sum(sub_dict.values())
|
|
|
|
all = total_catch + total_breed + missing_count
|
|
|
|
sorted_keys = sorted(pokemon_to_catch.keys())
|
|
|
|
# Create a new dictionary with sorted keys
|
|
sorted_dict = {key: pokemon_to_catch[key] for key in sorted_keys}
|
|
game_plan["pokemon_to_catch"] = pokemon_to_catch
|
|
game_plan["pokemon_to_breed"] = pokemon_to_breed
|
|
game_plan["pokemon_map"] = pokemon_map
|
|
game_plan["other_map"] = other_map
|
|
|
|
for required in required_pokemon:
|
|
if required not in pokemon_map:
|
|
pokemon_data = db.get_pokemon_details(required)
|
|
print(pokemon_data["name"])
|
|
|
|
return game_plan
|