Browse Source

- Update to get home storage working as before

feature-new-db-implementation
Dan 1 year ago
parent
commit
e08b5b86e1
  1. 25
      database/db_controller.py
  2. 12
      ui/main_window_controller.py
  3. 148
      ui/workers/gather_home_storage_status_worker.py
  4. 0
      ui/workers/gather_pokemon_forms_worker.py
  5. 55
      utility/data.py
  6. 26
      utility/functions.py

25
database/db_controller.py

@ -60,7 +60,7 @@ class DBController:
"generation": generation,
"sprite_url": sprite_url,
"is_baby_form": False,
"storable_in_home": True, # Example additional field
"storable_in_home": False,
}
with self.lock:
@ -98,3 +98,26 @@ class DBController:
results = self.cursor.fetchall()
return [dict(row) for row in results]
def update_home_status(self, pfic, status):
self.update_pokemon_field(pfic, "storable_in_home", status)
pass
def update_pokemon_field(self, pfic, field_name, new_value):
# Fetch the existing record
self.cursor.execute('SELECT data FROM pokemon_forms WHERE PFIC = ?', (pfic,))
result = self.cursor.fetchone()
if result:
# Load the JSON data and update the field
data = json.loads(result[0])
data[field_name] = new_value
# Update the record with the modified JSON
updated_data_str = json.dumps(data)
self.cursor.execute('''
UPDATE pokemon_forms
SET data = ?
WHERE PFIC = ?
''', (updated_data_str, pfic))
self.conn.commit()

12
ui/main_window_controller.py

@ -3,7 +3,8 @@ from PyQt6.QtWidgets import QMenu
from PyQt6.QtGui import QAction
import os
from ui.workers import GatherPokemonFormsWorker
from ui.workers.gather_home_storage_status_worker import GatherHomeStorageStatus
from ui.workers.gather_pokemon_forms_worker import GatherPokemonFormsWorker
from db import db
@ -97,6 +98,15 @@ class MainWindowController:
db.save_changes()
def gather_home_storage_info(self):
worker = GatherHomeStorageStatus()
worker.signals.finished.connect(self.on_home_status_gathered)
self.thread_pool.start(worker)
pass
def on_home_status_gathered(self, data):
print("Works Done!")
for pfic in data:
db.update_home_status(pfic, True)
pass
def gather_evolution_info(self):

148
ui/workers/gather_home_storage_status_worker.py

@ -0,0 +1,148 @@
from PyQt6.QtCore import QObject, pyqtSignal, QRunnable
from bs4 import BeautifulSoup
from cache import cache
from utility.data import regions, default_forms
from utility.functions import get_objects_by_number, compare_pokemon_forms
from db import db
class GatherHomeStorageStatusWorkerSignals(QObject):
finished = pyqtSignal(list)
class GatherHomeStorageStatus(QRunnable):
def __init__(self):
super().__init__()
self.signals = GatherHomeStorageStatusWorkerSignals()
self.base_url = "https://www.serebii.net/pokemonhome/"
def run(self):
try:
gathered_data = self.gather_home_storage_data()
self.signals.finished.emit(gathered_data)
except Exception as e:
print(f"Error gathering Pokémon home storage status: {e}")
def gather_home_storage_data(self):
all_pokemon_forms = db.get_list_of_pokemon_forms()
pokemon_storable_in_home = []
pfics_that_can_go_to_home = []
for region in regions:
pokemon_storable_in_home.extend(self.scrape_region_for_pokemon(region))
for pokemon_form in all_pokemon_forms:
storable_in_home = False
name = pokemon_form["name"]
national_dex = pokemon_form["national_dex"]
working_form = pokemon_form["form_name"]
if working_form and name in working_form:
working_form = working_form.replace(name, "").strip()
# serebii doesn't list gender in the table so we have to assume based on form name.
if working_form and ("male" in working_form.lower() or "working_form" in working_form.lower()):
working_form = None
if name == "Unown" and (working_form != "!" and working_form != "?"):
working_form = None
if name == "Tauros" and working_form == "Combat Breed":
working_form = "Paldean Form"
# serebii just gave up on Alcremie. It has 36 uniquie forms all storable in home.
if name == "Alcremie":
working_form = None
pokemon_by_national_dex = get_objects_by_number(pokemon_storable_in_home, f"{national_dex:04d}")
for pokemon in pokemon_by_national_dex:
if working_form:
parts = pokemon['name'].split(" ")
if len(parts) > 1 and parts[0] == working_form:
storable_in_home = True
brackets = self.extract_bracketed_text(pokemon['name'])
if brackets:
for bracket in brackets:
if name in bracket:
bracket = bracket.replace(name, "").strip()
if compare_pokemon_forms(working_form, bracket):
storable_in_home = True
break
if storable_in_home == False and working_form and working_form in default_forms:
working_form = None
if working_form == None and name.lower() in pokemon['name'].lower():
storable_in_home = True
break
if storable_in_home:
pfics_that_can_go_to_home.append(pokemon_form["pfic"])
return pfics_that_can_go_to_home
def scrape_region_for_pokemon(self, region):
cached_entry = cache.get(f"home_{region}")
if cached_entry != None:
return cached_entry
url = f"{self.base_url}{region}pokemon.shtml"
response = cache.fetch_url(url)
if not response:
return []
soup = BeautifulSoup(response, 'html.parser')
table = soup.find('table', class_='dextable')
if table == None:
return []
pokemon_list = []
rows = table.find_all('tr')[2:] # Skip the header row and the game intro row
for row in rows:
cells = row.find_all('td')
if len(cells) <= 5: # Ensure we have enough cells to check depositability. if only 5 then its not depositable in any game.
continue
number = cells[0].text.strip().lstrip('#')
name = cells[2].text.strip()
# Get the image URL
img_url = cells[1].find('img')['src']
full_img_url = f"https://www.serebii.net{img_url}"
pokemon_list.append({
'number': number,
'name': name,
'image_url': full_img_url
})
cache.set(f"home_{region}", pokemon_list)
return pokemon_list
def extract_bracketed_text(self, string):
results = []
stack = []
start_index = -1
for i, char in enumerate(string):
if char == '(':
if not stack:
start_index = i
stack.append(i)
elif char == ')':
if stack:
stack.pop()
if not stack:
results.append(string[start_index + 1:i])
start_index = -1
else:
#logger.warning(f"Warning: Unmatched closing parenthesis at position {i}")
pass
# Handle any remaining unclosed brackets
if stack:
#logger.warning(f"Warning: {len(stack)} unmatched opening parentheses")
for unmatched_start in stack:
results.append(string[unmatched_start + 1:])
return results

0
ui/workers.py → ui/workers/gather_pokemon_forms_worker.py

55
utility/data.py

@ -10,6 +10,7 @@ pokemon_generations = {
9: {"min": 906, "max": 1025},
}
regions = ["kanto", "johto", "hoenn", "sinnoh", "unova", "kalos", "alola", "galar", "paldea", "hisui", "unknown"]
regional_descriptors = ["kantonian", "johtonian", "hoennian", "sinnohan", "unovan", "kalosian", "alolan", "galarian", "hisuian", "paldean"]
yellow = {
@ -248,3 +249,57 @@ main_line_games = [
scarlet, violet,
]
# If a pokemon is in this form then its generally* not refered to as a form
# *I say generally as some do and some don't
default_forms = [
"Male",
"Normal Forme",
"Hero of Many Battles",
"Altered Forme",
"Land Forme",
"Standard Mode",
"Ordinary Forme",
"Aria Forme",
"Natural Form",
"Shield Forme",
"Neutral Mode",
"Hoopa Confined",
"Solo Form",
"Type: Normal",
"Red Core",
"Disguised Form",
"Ice Face",
"Full Belly Mode",
"Zero Form",
"Curly Form",
"Apex Build",
"Ultimate Mode",
"Teal Mask",
"Normal Form",
"Plant Cloak",
"Overcast Form",
"West Sea",
"Normal",
"Red-Striped Form",
"Spring Form",
"Incarnate Forme",
"Meadow Pattern",
"Red Flower",
"Average Size",
"50% Forme",
"Confined",
"Baile Style",
"Midday Form",
"Amped Form",
"Vanilla Cream Strawberry Sweet",
"Single Strike Style",
"Green Plumage",
"Two-Segment Form",
"Standard Form",
"Counterfeit Form",
"Unremarkable Form",
"Antique Form",
"Phony Form",
"Masterpiece Form",
"Chest Form"
]

26
utility/functions.py

@ -1,5 +1,6 @@
from .data import pokemon_generations, main_line_games
import unicodedata
import re
def format_pokemon_id(national_dex: int, region_code: int, form_index: int, gender_code: int) -> str:
return f"{national_dex:04d}-{region_code:02d}-{form_index:03d}-{gender_code}"
@ -50,3 +51,28 @@ def find_game_generation(game_name: str) -> int:
if game_name == game["Name"].lower() or game_name in (name.lower() for name in game["AltNames"]):
return game["Generation"]
return None
def sanitize_filename(filename):
# Define a dictionary of symbol replacements
symbol_replacements = {
'?': 'questionmark',
'*': 'asterisk',
':': 'colon',
'/': 'slash',
'\\': 'backslash',
'|': 'pipe',
'<': 'lessthan',
'>': 'greaterthan',
'"': 'quote',
' ': '_'
}
# Replace symbols with their word equivalents
for symbol, word in symbol_replacements.items():
filename = filename.replace(symbol, word)
# Remove any remaining invalid characters
return re.sub(r'[<>:"/\\|?*]', '', filename)
def get_objects_by_number(array, target_number):
return [obj for obj in array if obj['number'] == target_number]
Loading…
Cancel
Save