Browse Source

- A good place for evolutions now. They are tracking in a node graph, and displayed correctly.

feature-new-db-implementation
Dan 1 year ago
parent
commit
107422679b
  1. 110
      database/db_controller.py
  2. 3
      ui/main_window_controller.py
  3. 93
      ui/main_window_view.py
  4. 21
      ui/workers/gather_evolutions_worker.py

110
database/db_controller.py

@ -181,15 +181,34 @@ class DBController:
self.graph.add_edge(from_pfic, to_pfic, method=method) self.graph.add_edge(from_pfic, to_pfic, method=method)
def get_evolution_graph(self, pfic): def get_evolution_graph(self, pfic):
if self.graph.has_node(pfic) == False:
return []
return list(self.graph.successors(pfic)) return list(self.graph.successors(pfic))
def get_previous_evolution(self, pfic):
if self.graph.has_node(pfic) == False:
return None, None
predecessor = next(self.graph.predecessors(pfic), None)
if predecessor:
method = self.graph[predecessor][pfic]["method"]
return predecessor, method
else:
return None, None
def get_evolution_paths(self, start_node): def get_evolution_paths(self, start_node):
paths = [] paths = []
if self.graph.has_node(start_node) == False:
return paths
# 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, is_root=False):
# Add the current node to the path as a tuple (node, None) if is_root:
current_path.append((current_node, None)) # Add the current node to the path as a tuple (node, None)
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))
@ -211,9 +230,90 @@ class DBController:
current_path.pop() current_path.pop()
# Remove the initial node tuple when backtracking fully # Remove the initial node tuple when backtracking fully
current_path.pop() if is_root:
current_path.pop()
# Start traversal from the start_node # Start traversal from the start_node
traverse(start_node, []) traverse(start_node, [], True)
return paths return paths
def get_full_evolution_paths(self, start_node):
"""
Get all evolution paths starting from a given node, including predecessors and successors.
:param start_node: The starting node (e.g., a specific Pokemon form).
:return: A dictionary containing predecessors and successors paths.
"""
full_paths = {
"predecessors": [],
"successors": []
}
if self.graph.has_node(start_node) == False:
return full_paths
# Traverse predecessors
def traverse_predecessors(current_node, current_path, is_root=False):
#if not is_root:
# Add the current node to the path
#current_path.append(current_node)
# Get predecessors of the current node
predecessors = list(self.graph.predecessors(current_node))
if not predecessors:
# If there are no predecessors, add the current path to the list
full_paths["predecessors"].append(current_path.copy())
else:
# Traverse each predecessor
for predecessor in predecessors:
method = self.graph[predecessor][current_node]["method"]
# Add the edge metadata as a tuple (predecessor, method)
current_path.append((predecessor, method))
# Recur for the predecessor
traverse_predecessors(predecessor, current_path)
# Backtrack (remove the last node and edge metadata)
current_path.pop()
#current_path.pop()
# Traverse successors
def traverse_successors(current_node, current_path, is_root=False):
if is_root:
# Add the current node to the path as a tuple (node, None)
predecessor = next(self.graph.predecessors(current_node), None)
if predecessor:
method = self.graph[predecessor][current_node]["method"]
current_path.append((current_node, method))
else:
current_path.append((current_node, None))
# Get successors of the current node
successors = list(self.graph.successors(current_node))
if not successors:
# If there are no successors, add the current path to paths list
full_paths["successors"].append(current_path.copy())
else:
# Traverse each successor and add edge metadata
for successor in successors:
method = self.graph[current_node][successor]["method"]
# Add the successor node and method as a tuple (successor, method)
current_path.append((successor, method))
# Recur for the successor
traverse_successors(successor, current_path)
# Backtrack (remove the last node and edge metadata)
current_path.pop()
if is_root:
# Remove the initial node tuple when backtracking fully
current_path.pop()
# Start traversal from the start_node for both predecessors and successors
traverse_predecessors(start_node, [], True)
traverse_successors(start_node, [], True)
return full_paths

3
ui/main_window_controller.py

@ -174,5 +174,6 @@ class MainWindowController:
self.current_pfic = pfic self.current_pfic = pfic
def load_evolution_chain(self, pfic): def load_evolution_chain(self, pfic):
chain = db.get_evolution_paths(pfic) #chain = db.get_evolution_paths(pfic)
chain = db.get_full_evolution_paths(pfic)
self.view.update_evolution_tree(chain, pfic) self.view.update_evolution_tree(chain, pfic)

93
ui/main_window_view.py

@ -223,41 +223,70 @@ class PokemonUI(QWidget):
item.setData(Qt.ItemDataRole.UserRole, pokemon["pfic"]) item.setData(Qt.ItemDataRole.UserRole, pokemon["pfic"])
self.pokemon_list.addItem(item) self.pokemon_list.addItem(item)
def update_evolution_tree(self, evolution_chain, selected_pfic): def update_evolution_tree(self, evolution_chains, selected_pfic):
self.evolution_tree.clear()
tree_items = {} tree_items = {}
#for item in evolution_chain:
# print(item) for chains in evolution_chains["predecessors"]:
for pfic in evolution_chain: for pfic, method in chains:
pokemon_details = db.get_pokemon_details(pfic) pokemon_details = db.get_pokemon_details(pfic)
display_name = get_display_name(pokemon_details, not pokemon_details["gender_relevant"]) display_name = get_display_name(pokemon_details, not pokemon_details["gender_relevant"])
item = QTreeWidgetItem([display_name, method if method else ""]) item = QTreeWidgetItem([display_name, method if method else ""])
item.setData(0, Qt.ItemDataRole.UserRole, current_pfic) item.setData(0, Qt.ItemDataRole.UserRole, pfic)
tree_items[current_pfic] = item tree_items[pfic] = item
if current_pfic == selected_pfic: if pfic == selected_pfic:
item.setBackground(0, QColor(255, 255, 0, 100)) # Highlight selected Pokémon item.setBackground(0, QColor(255, 255, 0, 100)) # Highlight selected Pokémon
# Second pass: build the tree structure # Second pass: build the tree structure
root = None root = None
for current_pfic, name, form_name, method in evolution_chain: for pfic, method in chains:
item = tree_items[current_pfic] item = tree_items[pfic]
# Find the parent of this item # Find the parent of this item
#parent_pfic = event_system.call_sync('get_evolution_parent', data=current_pfic) parent_pfic, method = db.get_previous_evolution(pfic)
parent_pfic = None
if parent_pfic:
if parent_pfic: parent_item = tree_items.get(parent_pfic)
parent_item = tree_items.get(parent_pfic[0]) if parent_item:
if parent_item: parent_item.addChild(item)
parent_item.addChild(item) elif not root:
elif not root: root = item
root = item self.evolution_tree.addTopLevelItem(root)
self.evolution_tree.addTopLevelItem(root)
for chains in evolution_chains["successors"]:
for pfic, method in chains:
pokemon_details = db.get_pokemon_details(pfic)
display_name = get_display_name(pokemon_details, not pokemon_details["gender_relevant"])
item = QTreeWidgetItem([display_name, method if method else ""])
item.setData(0, Qt.ItemDataRole.UserRole, pfic)
tree_items[pfic] = item
if pfic == selected_pfic:
item.setBackground(0, QColor(255, 255, 0, 100)) # Highlight selected Pokémon
# Second pass: build the tree structure
root = None
for pfic, method in chains:
item = tree_items[pfic]
# Find the parent of this item
parent_pfic, method = db.get_previous_evolution(pfic)
if parent_pfic:
parent_item = tree_items.get(parent_pfic)
if parent_item:
parent_item.addChild(item)
elif not root:
root = item
self.evolution_tree.addTopLevelItem(root)
# Expand the entire tree # Expand the entire tree
self.evolution_tree.expandAll() self.evolution_tree.expandAll()
# Scroll to and select the current Pokémon # Scroll to and select the current Pokémon
current_item = tree_items[selected_pfic] if selected_pfic in tree_items:
self.evolution_tree.scrollToItem(current_item) current_item = tree_items[selected_pfic]
self.evolution_tree.setCurrentItem(current_item) self.evolution_tree.scrollToItem(current_item)
self.evolution_tree.setCurrentItem(current_item)

21
ui/workers/gather_evolutions_worker.py

@ -28,7 +28,7 @@ class GatherEvolutions(QRunnable):
except Exception as e: except Exception as e:
print(f"Error gathering Pokémon home storage status: {e}") print(f"Error gathering Pokémon home storage status: {e}")
def gather_evolution_data(self, force_refresh = True): def gather_evolution_data(self, force_refresh = False):
all_pokemon_forms = db.get_list_of_pokemon_forms() all_pokemon_forms = db.get_list_of_pokemon_forms()
evolutions = {} evolutions = {}
@ -44,10 +44,10 @@ class GatherEvolutions(QRunnable):
if force_refresh: if force_refresh:
cache.purge(cache_record_name) cache.purge(cache_record_name)
#cached_entry = cache.get(cache_record_name) cached_entry = cache.get(cache_record_name)
#if cached_entry != None: if cached_entry != None:
# evolutions[pokemon_form["pfic"]] = cached_entry evolutions = evolutions | cached_entry
# continue continue
#form = get_form_name(pokemon_form, not pokemon_form["gender_relevant"]) #form = get_form_name(pokemon_form, not pokemon_form["gender_relevant"])
search_form = form search_form = form
@ -85,19 +85,20 @@ class GatherEvolutions(QRunnable):
if tag.name == 'h3': if tag.name == 'h3':
break break
if not evolution_table: if not evolution_table:
continue continue
evolution_chain = []
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)
else: else:
evolution_tree = self.parse_evolution_chain(evolution_table, pokemon_form) evolution_tree = self.parse_evolution_chain(evolution_table, pokemon_form)
cacheable_container = {}
if evolution_tree: if evolution_tree:
self.traverse_and_store(evolution_tree, evolutions, gender) self.traverse_and_store(evolution_tree, cacheable_container, gender)
#cache.set(cache_record_name, chain) cache.set(cache_record_name, cacheable_container)
evolutions = evolutions | cacheable_container
print(self.evolution_methods) print(self.evolution_methods)
return evolutions return evolutions
@ -120,7 +121,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 = True): def parse_evolution_chain(self, table, pokemon_form, force_refresh = False):
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)

Loading…
Cancel
Save