You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
5.0 KiB
139 lines
5.0 KiB
import sqlite3
|
|
from typing import List, Optional
|
|
from dataclasses import dataclass
|
|
from fuzzywuzzy import fuzz
|
|
import re
|
|
from cache_manager import CacheManager
|
|
from DetermineOriginGame import get_evolution_data_from_bulbapedia
|
|
|
|
@dataclass
|
|
class EvolutionInfo:
|
|
from_pfic: str
|
|
to_pfic: str
|
|
method: str
|
|
|
|
def create_evolution_table():
|
|
conn = sqlite3.connect('pokemon_forms.db')
|
|
cursor = conn.cursor()
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS evolution_chains (
|
|
from_pfic TEXT,
|
|
to_pfic TEXT,
|
|
method TEXT,
|
|
PRIMARY KEY (from_pfic, to_pfic),
|
|
FOREIGN KEY (from_pfic) REFERENCES pokemon_forms (PFIC),
|
|
FOREIGN KEY (to_pfic) REFERENCES pokemon_forms (PFIC)
|
|
)
|
|
''')
|
|
conn.commit()
|
|
return conn
|
|
|
|
def insert_evolution_info(conn, evolution_info: EvolutionInfo):
|
|
cursor = conn.cursor()
|
|
cursor.execute('''
|
|
INSERT OR REPLACE INTO evolution_chains
|
|
(from_pfic, to_pfic, method)
|
|
VALUES (?, ?, ?)
|
|
''', (evolution_info.from_pfic, evolution_info.to_pfic, evolution_info.method))
|
|
conn.commit()
|
|
|
|
def strip_pokemon_name(pokemon_name: str, form_name: str) -> str:
|
|
"""Remove the Pokémon's name from the form name if present."""
|
|
if form_name:
|
|
form_name = form_name.replace("Form", "").strip()
|
|
form_name = re.sub(f'{re.escape(pokemon_name)}\\s*', '', form_name, flags=re.IGNORECASE).strip()
|
|
form_name = form_name.replace(" ", " ")
|
|
return form_name
|
|
return form_name
|
|
|
|
def fuzzy_match_form(form1: str, form2: str, threshold: int = 80) -> bool:
|
|
"""Perform fuzzy matching between two form names."""
|
|
if form1 is None or form2 is None:
|
|
return form1 == form2
|
|
return fuzz.ratio(form1.lower(), form2.lower()) >= threshold
|
|
|
|
def get_pokemon_form_by_name(conn, name: str, form: Optional[str] = None, threshold: int = 80, gender: Optional[str] = None) -> Optional[str]:
|
|
cursor = conn.cursor()
|
|
cursor.execute('SELECT PFIC, name, form_name FROM pokemon_forms WHERE name = ?', (name,))
|
|
results = cursor.fetchall()
|
|
|
|
if not results:
|
|
return None
|
|
|
|
if form is None and gender is None:
|
|
if len(results) > 1:
|
|
if results[0][2] == None:
|
|
return results[0][0]
|
|
else:
|
|
return get_pokemon_form_by_name(conn, name, "Male", threshold=100, gender=gender)
|
|
else:
|
|
return results[0][0] # Return the PFIC of the first result if no form is specified
|
|
|
|
if gender:
|
|
gendered_form = get_pokemon_form_by_name(conn, name, gender, threshold=100)
|
|
if gendered_form:
|
|
return gendered_form
|
|
|
|
stripped_form = strip_pokemon_name(name, form)
|
|
|
|
for pfic, pokemon_name, db_form in results:
|
|
stripped_db_form = strip_pokemon_name(pokemon_name, db_form)
|
|
if fuzzy_match_form(stripped_form, stripped_db_form, threshold):
|
|
return pfic
|
|
|
|
# Some times we get a form for a pokemon that doesn't really have one.
|
|
if len(results) > 1 and form != None:
|
|
return results[0][0]
|
|
|
|
return None
|
|
|
|
def process_evolution_chain(conn, evolution_chain, cache, gender: Optional[str] = None):
|
|
for stage in evolution_chain:
|
|
from_pfic = get_pokemon_form_by_name(conn, stage.pokemon, stage.form, gender=gender)
|
|
if not from_pfic:
|
|
print(f"Warning: Could not find PFIC for {stage.pokemon} {stage.form}")
|
|
continue
|
|
|
|
if stage.next_stage:
|
|
to_pfic = get_pokemon_form_by_name(conn, stage.next_stage.pokemon, stage.next_stage.form, gender=gender)
|
|
if to_pfic:
|
|
evolution_info = EvolutionInfo(from_pfic, to_pfic, stage.next_stage.method)
|
|
insert_evolution_info(conn, evolution_info)
|
|
|
|
for branch in stage.branches:
|
|
to_pfic = get_pokemon_form_by_name(conn, branch.pokemon, branch.form, gender=gender)
|
|
if to_pfic:
|
|
evolution_info = EvolutionInfo(from_pfic, to_pfic, branch.method)
|
|
insert_evolution_info(conn, evolution_info)
|
|
|
|
def update_evolution_chains():
|
|
cache = CacheManager()
|
|
conn = create_evolution_table()
|
|
|
|
cursor = conn.cursor()
|
|
cursor.execute('SELECT DISTINCT name, form_name FROM pokemon_forms')
|
|
pokemon_forms = cursor.fetchall()
|
|
|
|
for name, form in pokemon_forms:
|
|
print(f"Processing {name} {form if form else ''}")
|
|
|
|
if form and name in form:
|
|
form = form.replace(name, "").strip()
|
|
|
|
gender = None
|
|
if form and "male" in form.lower():
|
|
gender = form
|
|
form = None
|
|
|
|
evolution_chain = get_evolution_data_from_bulbapedia(name, form, cache, gender)
|
|
if evolution_chain:
|
|
if name == "Tauros": # Bulbapedia has a weird formatting for Tauros.
|
|
for stage in evolution_chain:
|
|
if stage.form:
|
|
stage.form = stage.form.replace("Paldean Form(", "").replace(")", "").strip()
|
|
process_evolution_chain(conn, evolution_chain, cache, gender)
|
|
|
|
conn.close()
|
|
|
|
if __name__ == "__main__":
|
|
update_evolution_chains()
|
|
|