Browse Source
- Mostly all working, about 7 or so forms not account for, excluding event pokemonplan_generation
6 changed files with 516 additions and 3 deletions
@ -0,0 +1,367 @@ |
|||||
|
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, parse_pfic |
||||
|
|
||||
|
class GeneratePlanWorkerSignals(QObject): |
||||
|
finished = pyqtSignal(dict) |
||||
|
|
||||
|
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 {} |
||||
|
|
||||
|
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: |
||||
|
if pokemon["storable_in_home"] == False: |
||||
|
continue |
||||
|
|
||||
|
pfic = pokemon["PFIC"] |
||||
|
|
||||
|
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) |
||||
|
|
||||
|
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']]) |
||||
|
|
||||
|
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: |
||||
|
output_file = "./temp/"+game["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() |
||||
|
|
||||
|
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 = {} |
||||
|
|
||||
|
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 |
||||
|
|
||||
|
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 |
||||
|
|
||||
|
# 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 |
||||
|
|
||||
|
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 |
||||
Loading…
Reference in new issue