Browse Source

WIP new way of extracting the node an edge work for evolutions

feature-new-db-implementation
Quildra 1 year ago
parent
commit
f7cfa89287
  1. 17
      database/db_controller.py
  2. 106
      ui/workers/gather_evolutions_worker.py

17
database/db_controller.py

@ -164,10 +164,11 @@ class DBController:
self.conn.commit() self.conn.commit()
def update_evolution_graph(self, evolutions): def update_evolution_graph(self, evolutions):
for evolution in evolutions: for key in evolutions:
from_pfic = evolution["from_pfic"] value = evolutions[key]
to_pfic = evolution["to_pfic"] from_pfic = value["from_pfic"]
method = evolution["method"] to_pfic = value["to_pfic"]
method = value["method"]
# Add nodes if they do not already exist # Add nodes if they do not already exist
if not self.graph.has_node(from_pfic): if not self.graph.has_node(from_pfic):
@ -187,8 +188,8 @@ class DBController:
# Define a recursive function to traverse the graph # Define a recursive function to traverse the graph
def traverse(current_node, current_path): def traverse(current_node, current_path):
# Add the current node to the path # Add the current node to the path as a tuple (node, None)
current_path.append(current_node) current_path.append((current_node, None))
# Get successors of the current node # Get successors of the current node
successors = list(self.graph.successors(current_node)) successors = list(self.graph.successors(current_node))
@ -200,7 +201,7 @@ class DBController:
# Traverse each successor and add edge metadata # Traverse each successor and add edge metadata
for successor in successors: for successor in successors:
method = self.graph[current_node][successor]["method"] method = self.graph[current_node][successor]["method"]
# Add the edge metadata as a tuple (to_node, method) # Add the successor node and method as a tuple (successor, method)
current_path.append((successor, method)) current_path.append((successor, method))
# Recur for the successor # Recur for the successor
@ -208,6 +209,8 @@ class DBController:
# Backtrack (remove the last node and edge metadata) # Backtrack (remove the last node and edge metadata)
current_path.pop() current_path.pop()
# Remove the initial node tuple when backtracking fully
current_path.pop() current_path.pop()
# Start traversal from the start_node # Start traversal from the start_node

106
ui/workers/gather_evolutions_worker.py

@ -11,7 +11,7 @@ from utility.functions import get_form_name, get_display_name, parse_pfic
from utility.data import non_evolution_forms from utility.data import non_evolution_forms
class GatherEvolutionsWorkerSignals(QObject): class GatherEvolutionsWorkerSignals(QObject):
finished = pyqtSignal(list) finished = pyqtSignal(dict)
class GatherEvolutions(QRunnable): class GatherEvolutions(QRunnable):
def __init__(self): def __init__(self):
@ -19,6 +19,8 @@ class GatherEvolutions(QRunnable):
self.signals = GatherEvolutionsWorkerSignals() self.signals = GatherEvolutionsWorkerSignals()
self.base_url = "https://bulbapedia.bulbagarden.net/wiki/" self.base_url = "https://bulbapedia.bulbagarden.net/wiki/"
self.evolution_methods = set()
def run(self): def run(self):
try: try:
gathered_data = self.gather_evolution_data() gathered_data = self.gather_evolution_data()
@ -28,7 +30,6 @@ class GatherEvolutions(QRunnable):
def gather_evolution_data(self, force_refresh = True): def gather_evolution_data(self, force_refresh = True):
all_pokemon_forms = db.get_list_of_pokemon_forms() all_pokemon_forms = db.get_list_of_pokemon_forms()
#evolutions = []
evolutions = {} evolutions = {}
for pokemon_form in all_pokemon_forms: for pokemon_form in all_pokemon_forms:
@ -90,55 +91,15 @@ class GatherEvolutions(QRunnable):
evolution_tree = None evolution_tree = None
if pokemon_name == "Eevee": if pokemon_name == "Eevee":
evolution_tree = self.parse_eevee_evolution_chain(evolution_table, pokemon_form) evolution_tree = self.parse_eevee_evolution_chain(evolution_table, pokemon_form)
#evolutions.append(evolution_chain)
else: else:
evolution_tree = self.parse_evolution_chain(evolution_table, pokemon_form) evolution_tree = self.parse_evolution_chain(evolution_table, pokemon_form)
#evolutions.append(evolution_chain)
if evolution_tree: if evolution_tree:
self.traverse_and_store(evolution_tree, evolutions, gender) self.traverse_and_store(evolution_tree, evolutions, gender)
chain = [] #cache.set(cache_record_name, chain)
for pokemon in evolution_chain:
from_pfic = self.get_pokemon_form_by_name(pokemon["pokemon"], pokemon["form"], gender=gender)
if not from_pfic:
#logger.warning(f"Could not find PFIC for {stage.pokemon} {stage.form}")
continue
stage = pokemon["next_stage"]
if stage:
to_pfic = self.get_pokemon_form_by_name(stage["pokemon"], stage["form"], gender=gender)
if to_pfic:
evolution_info = {
"from_pfic": from_pfic,
"to_pfic": to_pfic,
"method": stage["method"]
}
evolutions[pokemon_form["pfic"]] = evolution_info
chain.append(evolution_info)
#insert_evolution_info(evolution_info)
#if "breed" in stage["next_stage"]["method"].lower():
# update_pokemon_baby_status(from_pfic, True)
for branch in pokemon["branches"]:
to_pfic = self.get_pokemon_form_by_name(branch["pokemon"], branch["form"], gender=gender)
if to_pfic:
evolution_info = {
"from_pfic": from_pfic,
"to_pfic": to_pfic,
"method": branch["method"]
}
evolutions[pokemon_form["pfic"]] = evolution_info
chain.append(evolution_info)
#EvolutionInfo(from_pfic, to_pfic, branch.method)
#insert_evolution_info(evolution_info)
#if "breed" in branch.method.lower():
# update_pokemon_baby_status(from_pfic, True)
cache.set(cache_record_name, chain)
print(self.evolution_methods)
return evolutions return evolutions
def traverse_and_store(self, node, evolutions, gender): def traverse_and_store(self, node, evolutions, gender):
@ -159,7 +120,7 @@ class GatherEvolutions(QRunnable):
evolutions[composite_key] = (evolution_info) evolutions[composite_key] = (evolution_info)
self.traverse_and_store(next_stage, evolutions, gender) self.traverse_and_store(next_stage, evolutions, gender)
def parse_evolution_chain(self, table, pokemon_form, force_refresh = False): def parse_evolution_chain(self, table, pokemon_form, force_refresh = True):
cache_record_name = f"evo_{pokemon_form['pfic']}" cache_record_name = f"evo_{pokemon_form['pfic']}"
if force_refresh: if force_refresh:
cache.purge(cache_record_name) cache.purge(cache_record_name)
@ -178,59 +139,85 @@ class GatherEvolutions(QRunnable):
main_row = rows[0] main_row = rows[0]
branch_rows = rows[1:] branch_rows = rows[1:]
def create_stage(td): def create_stage(td, current_stage_number):
pokemon_name = self.extract_pokemon_name(td) pokemon_name = self.extract_pokemon_name(td)
evolution_form = self.extract_evolution_form(td, pokemon_name) evolution_form = self.extract_evolution_form(td, pokemon_name)
return { return {
"pokemon": pokemon_name, "pokemon": pokemon_name,
"form": evolution_form, "form": evolution_form,
"requirement": None,
"method": None, "method": None,
"evolves_to": [] "evolves_to": [],
"stage": current_stage_number
} }
# Parse main evolution chain # Parse main evolution chain
pending_method = None pending_method = None
pending_method_form = None
root = None root = None
current_stage = None current_stage = None
stage_number = 0
for td in main_row.find_all('td', recursive=False): for td in main_row.find_all('td', recursive=False):
if td.find('table'): if td.find('table'):
new_stage = create_stage(td) new_stage = create_stage(td, stage_number)
new_stage["method"] = pending_method new_stage["method"] = pending_method
new_stage["requirement"] = pending_method_form
pending_method = None pending_method = None
if root is None: if root is None:
root = new_stage # Assign the root node root = new_stage # Assign the root node
if current_stage: if current_stage:
current_stage["evolves_to"].append(new_stage) current_stage["evolves_to"].append(new_stage)
current_stage = new_stage current_stage = new_stage
stage_number += 1
else: else:
pending_method = self.extract_evolution_method(td) pending_method, pending_method_form = self.extract_evolution_method(td)
# reduce by one to account for an accidental increase by the last one in the chain.
stage_number -= 1
# Parse branching evolutions # Parse branching evolutions
for row in branch_rows: for row in branch_rows:
branch_method = None branch_method = None
pending_method_form = None
branch_stage = None branch_stage = None
branch_stage_number = stage_number
for td in row.find_all('td', recursive=False): for td in row.find_all('td', recursive=False):
if td.find('table'): if td.find('table'):
new_stage = create_stage(td) new_stage = create_stage(td, branch_stage_number)
new_stage["method"] = branch_method new_stage["method"] = branch_method
new_stage["requirement"] = pending_method_form
branch_method = None branch_method = None
if branch_stage: if branch_stage:
branch_stage["evolves_to"].append(new_stage) branch_stage["evolves_to"].append(new_stage)
branch_stage = new_stage branch_stage = new_stage
# Find which main chain Pokémon this branches from # Find which main chain Pokémon this branch evolves from
attached = False
for main_stage in self.find_stages(root): for main_stage in self.find_stages(root):
if td.get('rowspan') and main_stage["pokemon"] == new_stage["pokemon"]: if self.should_attach_branch(main_stage, branch_stage):
main_stage["evolves_to"].append(branch_stage) main_stage["evolves_to"].append(branch_stage)
attached = True
break break
if not attached:
print(f"Warning: Could not find a suitable attachment point for branch {branch_stage['pokemon']}")
else: else:
branch_method = self.extract_evolution_method(td) branch_method, pending_method_form = self.extract_evolution_method(td)
cache.set(cache_record_name, root) cache.set(cache_record_name, root)
return root return root
def should_attach_branch(self, main_stage, branch_stage):
# Ensure the main_stage is a valid node to attach a branch
if main_stage["stage"] == branch_stage["stage"] - 1:
return True
# You can add more logic to determine if branch_stage should connect to main_stage
# For instance, check if they are forms of the same evolution or based on other criteria
return False
def find_stages(self, node): def find_stages(self, node):
"""Helper function to find all stages in the evolution chain recursively.""" """Helper function to find all stages in the evolution chain recursively."""
stages = [node] stages = [node]
@ -269,7 +256,14 @@ class GatherEvolutions(QRunnable):
def extract_evolution_method(self, td: Tag) -> str: def extract_evolution_method(self, td: Tag) -> str:
# Extract evolution method from the TD # Extract evolution method from the TD
return td.get_text(strip=True) text = td.get_text()
form = None
if text and "(male)" in text.lower():
form = "male"
elif text and "(female)" in text.lower():
form = "female"
return td.get_text(strip=True), form
def parse_eevee_evolution_chain(self, table, pokemon_form): def parse_eevee_evolution_chain(self, table, pokemon_form):
tbody = table.find('tbody', recursive=False) tbody = table.find('tbody', recursive=False)
@ -376,8 +370,8 @@ class GatherEvolutions(QRunnable):
return entry["pfic"] return entry["pfic"]
# Some times we get a form for a pokemon that doesn't really have one. # Some times we get a form for a pokemon that doesn't really have one.
if len(results) > 1 and form != None: #if len(results) > 1 and form != None and gender and threshold != 100:
return results[0]["pfic"] # return results[0]["pfic"]
return None return None

Loading…
Cancel
Save