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. 80
      ui/workers/gather_pokemon_forms_worker.py
  6. 12
      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 = { data = {
"name": name, "name": name,
"form_name": form_name, "form_name": form_name,
@ -61,6 +61,7 @@ class DBController:
"sprite_url": sprite_url, "sprite_url": sprite_url,
"is_baby_form": False, "is_baby_form": False,
"storable_in_home": False, "storable_in_home": False,
"gender_relevant": gender_relevant
} }
with self.lock: with self.lock:
@ -70,31 +71,50 @@ class DBController:
self.conn.commit() self.conn.commit()
print(f"Added: {pfic}, {name}") 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): def get_pokemon_details(self, pfic):
self.cursor.execute(''' fields = [
SELECT JSON_EXTRACT(data, '$.name') AS name, "name",
JSON_EXTRACT(data, '$.form_name') AS form_name, "form_name",
JSON_EXTRACT(data, '$.national_dex') AS national_dex, "national_dex",
JSON_EXTRACT(data, '$.generation') AS generation, "generation",
JSON_EXTRACT(data, '$.is_baby_form') AS is_baby_form, "is_baby_form",
JSON_EXTRACT(data, '$.storable_in_home') AS storable_in_home "storable_in_home",
FROM pokemon_forms ]
WHERE PFIC = ? query = self.craft_pokemon_json_query(fields, pfic)
''', (pfic,)) self.cursor.execute(query)
results = self.cursor.fetchone() results = self.cursor.fetchone()
return dict(results) return dict(results)
def get_list_of_pokemon_forms(self): def get_list_of_pokemon_forms(self):
self.cursor.execute(''' fields = [
SELECT JSON_EXTRACT(data, '$.name') AS name, "pfic",
JSON_EXTRACT(data, '$.form_name') AS form_name, "name",
JSON_EXTRACT(data, '$.national_dex') AS national_dex, "form_name",
JSON_EXTRACT(data, '$.generation') AS generation, "national_dex",
JSON_EXTRACT(data, '$.is_baby_form') AS is_baby_form, "generation",
JSON_EXTRACT(data, '$.storable_in_home') AS storable_in_home, "is_baby_form",
PFIC as pfic "storable_in_home",
FROM pokemon_forms "gender_relevant"
''',) ]
query = self.craft_pokemon_json_query(fields)
self.cursor.execute(query)
results = self.cursor.fetchall() results = self.cursor.fetchall()
return [dict(row) for row in results] 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_home_storage_status_worker import GatherHomeStorageStatus
from ui.workers.gather_pokemon_forms_worker import GatherPokemonFormsWorker from ui.workers.gather_pokemon_forms_worker import GatherPokemonFormsWorker
from utility.functions import get_display_name
from db import db from db import db
class MainWindowController: class MainWindowController:
@ -21,6 +22,7 @@ class MainWindowController:
def initialize_pokemon_list(self, data): def initialize_pokemon_list(self, data):
self.pokemon_data_cache = data self.pokemon_data_cache = data
self.view.update_pokemon_forms(data) self.view.update_pokemon_forms(data)
self.apply_filters()
def filter_pokemon_list(self): def filter_pokemon_list(self):
self.filter_timer.start() self.filter_timer.start()
@ -29,9 +31,12 @@ class MainWindowController:
search_text = self.view.search_bar.text().lower() search_text = self.view.search_bar.text().lower()
show_only_home_storable = self.view.filter_home_storable.isChecked() show_only_home_storable = self.view.filter_home_storable.isChecked()
show_only_missing_encounters = self.view.highlight_no_encounters.isChecked() show_only_missing_encounters = self.view.highlight_no_encounters.isChecked()
gender_relevant = False
filtered_data = [] 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 # Check if the item matches the search text
text_match = search_text in display_name.lower() text_match = search_text in display_name.lower()
@ -47,9 +52,13 @@ class MainWindowController:
# TODO: reimplement this check. # TODO: reimplement this check.
has_encounters = True 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 both conditions are met, add to filtered data
if text_match and home_storable: if text_match and home_storable and include_gender:
filtered_data.append((pfic, display_name)) filtered_data.append(pokemon)
# Update the view with the filtered data # Update the view with the filtered data
self.view.update_pokemon_forms(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 # This method will be called in the main thread when the worker finishes
# Update the UI with the gathered forms # Update the UI with the gathered forms
for pokemon in data: 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.pokemon_data_cache = data
self.view.update_pokemon_forms(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 PyQt6.QtGui import QPixmap, QFontMetrics, QColor, QAction
from .main_window_controller import MainWindowController from .main_window_controller import MainWindowController
from utility.functions import get_display_name
from db import db from db import db
class PokemonUI(QWidget): class PokemonUI(QWidget):
@ -217,9 +218,7 @@ class PokemonUI(QWidget):
self.pokemon_list.clear() self.pokemon_list.clear()
for pokemon in data: for pokemon in data:
display_name = f"{pokemon["national_dex"]:04d} - {pokemon["name"]}" display_name = get_display_name(pokemon, not pokemon["gender_relevant"])
if pokemon["form_name"]:
display_name += f" ({pokemon["form_name"]})"
item = QListWidgetItem(display_name) item = QListWidgetItem(display_name)
item.setData(Qt.ItemDataRole.UserRole, pokemon["pfic"]) item.setData(Qt.ItemDataRole.UserRole, pokemon["pfic"])
self.pokemon_list.addItem(item) 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

80
ui/workers/gather_pokemon_forms_worker.py

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

12
utility/functions.py

@ -75,4 +75,14 @@ def sanitize_filename(filename):
return re.sub(r'[<>:"/\\|?*]', '', filename) return re.sub(r'[<>:"/\\|?*]', '', filename)
def get_objects_by_number(array, target_number): def get_objects_by_number(array, target_number):
return [obj for obj in array if obj['number'] == 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