Browse Source

- Made the switch to store all genders in the db if they have a unique sprite or not to help preserve the evolution lines

feature-new-db-implementation
Dan 1 year ago
parent
commit
db5661f4b3
  1. 62
      database/db_controller.py
  2. 17
      ui/main_window_controller.py
  3. 5
      ui/main_window_view.py
  4. 29
      ui/workers/gather_evolutions_worker.py
  5. 64
      ui/workers/gather_pokemon_forms_worker.py
  6. 10
      utility/functions.py

62
database/db_controller.py

@ -52,7 +52,7 @@ class DBController:
)
''')
def add_pokemon_form(self, pfic, name, form_name, national_dex, generation, sprite_url):
def add_pokemon_form(self, pfic, name, form_name, national_dex, generation, sprite_url, gender_relevant):
data = {
"name": name,
"form_name": form_name,
@ -61,6 +61,7 @@ class DBController:
"sprite_url": sprite_url,
"is_baby_form": False,
"storable_in_home": False,
"gender_relevant": gender_relevant
}
with self.lock:
@ -70,31 +71,50 @@ class DBController:
self.conn.commit()
print(f"Added: {pfic}, {name}")
def craft_pokemon_json_query(self, fields_to_include, pfic = None):
query = f"SELECT "
extracts = []
for field in fields_to_include:
if field == "pfic":
extracts.append("PFIC as pfic")
else:
extracts.append(f"JSON_EXTRACT(data, '$.{field}') AS {field}")
query = query + ", ".join(extracts)
query = query + " FROM pokemon_forms"
if pfic is not None:
query = query + f" WHERE PFIC = '{pfic}'"
return query
def get_pokemon_details(self, pfic):
self.cursor.execute('''
SELECT JSON_EXTRACT(data, '$.name') AS name,
JSON_EXTRACT(data, '$.form_name') AS form_name,
JSON_EXTRACT(data, '$.national_dex') AS national_dex,
JSON_EXTRACT(data, '$.generation') AS generation,
JSON_EXTRACT(data, '$.is_baby_form') AS is_baby_form,
JSON_EXTRACT(data, '$.storable_in_home') AS storable_in_home
FROM pokemon_forms
WHERE PFIC = ?
''', (pfic,))
fields = [
"name",
"form_name",
"national_dex",
"generation",
"is_baby_form",
"storable_in_home",
]
query = self.craft_pokemon_json_query(fields, pfic)
self.cursor.execute(query)
results = self.cursor.fetchone()
return dict(results)
def get_list_of_pokemon_forms(self):
self.cursor.execute('''
SELECT JSON_EXTRACT(data, '$.name') AS name,
JSON_EXTRACT(data, '$.form_name') AS form_name,
JSON_EXTRACT(data, '$.national_dex') AS national_dex,
JSON_EXTRACT(data, '$.generation') AS generation,
JSON_EXTRACT(data, '$.is_baby_form') AS is_baby_form,
JSON_EXTRACT(data, '$.storable_in_home') AS storable_in_home,
PFIC as pfic
FROM pokemon_forms
''',)
fields = [
"pfic",
"name",
"form_name",
"national_dex",
"generation",
"is_baby_form",
"storable_in_home",
"gender_relevant"
]
query = self.craft_pokemon_json_query(fields)
self.cursor.execute(query)
results = self.cursor.fetchall()
return [dict(row) for row in results]

17
ui/main_window_controller.py

@ -6,6 +6,7 @@ import os
from ui.workers.gather_home_storage_status_worker import GatherHomeStorageStatus
from ui.workers.gather_pokemon_forms_worker import GatherPokemonFormsWorker
from utility.functions import get_display_name
from db import db
class MainWindowController:
@ -21,6 +22,7 @@ class MainWindowController:
def initialize_pokemon_list(self, data):
self.pokemon_data_cache = data
self.view.update_pokemon_forms(data)
self.apply_filters()
def filter_pokemon_list(self):
self.filter_timer.start()
@ -29,9 +31,12 @@ class MainWindowController:
search_text = self.view.search_bar.text().lower()
show_only_home_storable = self.view.filter_home_storable.isChecked()
show_only_missing_encounters = self.view.highlight_no_encounters.isChecked()
gender_relevant = False
filtered_data = []
for pfic, display_name in self.pokemon_data_cache:
for pokemon in self.pokemon_data_cache:
display_name = get_display_name(pokemon)
pfic = pokemon["pfic"]
# Check if the item matches the search text
text_match = search_text in display_name.lower()
@ -47,9 +52,13 @@ class MainWindowController:
# TODO: reimplement this check.
has_encounters = True
include_gender = True
if gender_relevant == False and pokemon["gender_relevant"] == False:
include_gender = not any(item["pfic"][:-2] == pfic[:-2] for item in filtered_data)
# If both conditions are met, add to filtered data
if text_match and home_storable:
filtered_data.append((pfic, display_name))
if text_match and home_storable and include_gender:
filtered_data.append(pokemon)
# Update the view with the filtered data
self.view.update_pokemon_forms(filtered_data)
@ -91,7 +100,7 @@ class MainWindowController:
# This method will be called in the main thread when the worker finishes
# Update the UI with the gathered forms
for pokemon in data:
db.add_pokemon_form(pokemon["pfic"], pokemon["name"], pokemon["form_name"], pokemon["national_dex"], pokemon["generation"], pokemon["sprite_url"])
db.add_pokemon_form(pokemon["pfic"], pokemon["name"], pokemon["form_name"], pokemon["national_dex"], pokemon["generation"], pokemon["sprite_url"], pokemon["gender_relevant"])
self.pokemon_data_cache = data
self.view.update_pokemon_forms(data)

5
ui/main_window_view.py

@ -6,6 +6,7 @@ from PyQt6.QtCore import Qt, QSize, QTimer, QMetaObject
from PyQt6.QtGui import QPixmap, QFontMetrics, QColor, QAction
from .main_window_controller import MainWindowController
from utility.functions import get_display_name
from db import db
class PokemonUI(QWidget):
@ -217,9 +218,7 @@ class PokemonUI(QWidget):
self.pokemon_list.clear()
for pokemon in data:
display_name = f"{pokemon["national_dex"]:04d} - {pokemon["name"]}"
if pokemon["form_name"]:
display_name += f" ({pokemon["form_name"]})"
display_name = get_display_name(pokemon, not pokemon["gender_relevant"])
item = QListWidgetItem(display_name)
item.setData(Qt.ItemDataRole.UserRole, pokemon["pfic"])
self.pokemon_list.addItem(item)

29
ui/workers/gather_evolutions_worker.py

@ -0,0 +1,29 @@
from PyQt6.QtCore import QObject, pyqtSignal, QRunnable
from bs4 import BeautifulSoup
from cache import cache
from db import db
class GatherEvolutionsWorkerSignals(QObject):
finished = pyqtSignal(list)
class GatherHEvolutions(QRunnable):
def __init__(self):
super().__init__()
self.signals = GatherEvolutionsWorkerSignals()
self.base_url = "https://www.serebii.net/pokemonhome/"
def run(self):
try:
gathered_data = self.gather_evolution_data()
self.signals.finished.emit(gathered_data)
except Exception as e:
print(f"Error gathering Pokémon home storage status: {e}")
def gather_evolution_data(self):
all_pokemon_forms = db.get_list_of_pokemon_forms()
evolutions = []
for pokemon_form in all_pokemon_forms:
pass
return evolutions

64
ui/workers/gather_pokemon_forms_worker.py

@ -108,15 +108,21 @@ class GatherPokemonFormsWorker(QRunnable):
form_name = self.extract_form_name(sprite)
#logger.info(f'{sprite_url}, {form_name}')
record_male_form = False
record_female_form = False
record_genderless_form = False
gender_relevant = False
if form_name != "None":
form_index += 1
gender = 0
if form_name.startswith("Male"):
form_index -= 1
gender = 1
gender_relevant = True
elif form_name.startswith("Female"):
form_index -= 1
gender = 2
gender_relevant = True
dex_page_data = self.get_pokemon_dex_page(url_name)
if dex_page_data:
@ -156,13 +162,69 @@ class GatherPokemonFormsWorker(QRunnable):
if generation_found:
break
if not gender_relevant:
# see if we can find gender info on the page to see if it has male and female forms anyway.
gender_header = dex_soup.find('th', string="Gender")
if gender_header:
gender_info = gender_header.findNext('td').getText().replace(",", "").split()
skip_next = False
for info in gender_info:
if skip_next:
skip_next = False
continue
if info.lower().startswith("0%"):
skip_next = True
continue
if info.lower() == "male":
record_male_form = True
elif info.lower() == "female":
record_female_form = True
if not record_female_form and not record_male_form:
record_genderless_form = True
if gender_relevant or record_genderless_form:
pokemon_form = {
"pfic":format_pokemon_id(national_dex_number, generation, form_index, gender),
"name":pokemon_name,
"form_name":form_name if form_name != "None" else None,
"sprite_url":sprite_url,
"national_dex":national_dex_number,
"generation":generation
"generation":generation,
"gender_relevant": gender_relevant
}
found_forms.append(pokemon_form)
else:
if record_male_form:
gendered_form = form_name
if gendered_form == "None":
gendered_form = "Male"
else:
gendered_form = "Male " + gendered_form
pokemon_form = {
"pfic":format_pokemon_id(national_dex_number, generation, form_index, 1),
"name":pokemon_name,
"form_name":gendered_form if gendered_form != "None" else None,
"sprite_url":sprite_url,
"national_dex":national_dex_number,
"generation":generation,
"gender_relevant": gender_relevant
}
found_forms.append(pokemon_form)
if record_female_form:
gendered_form = form_name
if gendered_form == "None":
gendered_form = "Female"
else:
gendered_form = "Female " + gendered_form
pokemon_form = {
"pfic":format_pokemon_id(national_dex_number, generation, form_index, 2),
"name":pokemon_name,
"form_name":gendered_form if gendered_form != "None" else None,
"sprite_url":sprite_url,
"national_dex":national_dex_number,
"generation":generation,
"gender_relevant": gender_relevant
}
found_forms.append(pokemon_form)

10
utility/functions.py

@ -76,3 +76,13 @@ def sanitize_filename(filename):
def get_objects_by_number(array, target_number):
return [obj for obj in array if obj['number'] == target_number]
def get_display_name(pokemon, strip_gender = False):
display_name = f"{pokemon["national_dex"]:04d} - {pokemon["name"]}"
if pokemon["form_name"]:
form = pokemon["form_name"]
if strip_gender:
form = form.replace("Female", "").replace("Male", "").strip()
if form != "":
display_name += f" ({form})"
return display_name
Loading…
Cancel
Save