|
|
|
@ -8,10 +8,14 @@ import sys |
|
|
|
import logging |
|
|
|
import re |
|
|
|
import unicodedata |
|
|
|
from queue import Queue |
|
|
|
from threading import Thread |
|
|
|
import threading |
|
|
|
|
|
|
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
|
|
|
|
|
|
|
from DataGatherers.cache_manager import CacheManager |
|
|
|
from db_controller import DBController |
|
|
|
|
|
|
|
logger = logging.getLogger('ui_feedback') |
|
|
|
|
|
|
|
@ -56,9 +60,8 @@ def initialize_db(): |
|
|
|
create_pokemon_db() |
|
|
|
create_pokemon_storage_db() |
|
|
|
|
|
|
|
def insert_pokemon_form(conn, pokemon_form): |
|
|
|
cursor = conn.cursor() |
|
|
|
cursor.execute(''' |
|
|
|
def insert_pokemon_form(db_controller, pokemon_form): |
|
|
|
db_controller.execute_query_with_commit(''' |
|
|
|
INSERT OR REPLACE INTO pokemon_forms |
|
|
|
(PFIC, name, form_name, national_dex, generation) |
|
|
|
VALUES (?, ?, ?, ?, ?) |
|
|
|
@ -69,25 +72,25 @@ def insert_pokemon_form(conn, pokemon_form): |
|
|
|
pokemon_form.national_dex, |
|
|
|
pokemon_form.generation |
|
|
|
)) |
|
|
|
conn.commit() |
|
|
|
|
|
|
|
def insert_pokemon_storage(conn, pfic: str, storable_in_home: bool): |
|
|
|
cursor = conn.cursor() |
|
|
|
cursor.execute(''' |
|
|
|
def insert_pokemon_storage(db_controller, pfic: str, storable_in_home: bool): |
|
|
|
db_controller.execute_query_with_commit(''' |
|
|
|
INSERT OR REPLACE INTO pokemon_storage |
|
|
|
(PFIC, storable_in_home) |
|
|
|
VALUES (?, ?) |
|
|
|
''', (pfic, storable_in_home)) |
|
|
|
conn.commit() |
|
|
|
|
|
|
|
class PokemonDatabase: |
|
|
|
def __init__(self): |
|
|
|
self.pokemon: Dict[str, List[PokemonForm]] = {} |
|
|
|
self._lock = threading.Lock() |
|
|
|
|
|
|
|
def add_pokemon(self, national_dex: int, name: str, region_code: int, form_index: int, gender_code: int, form_name: Optional[str], sprite_url: str): |
|
|
|
|
|
|
|
pokemon_id = format_pokemon_id(national_dex, region_code, form_index, gender_code) |
|
|
|
pokemon_form = PokemonForm(id=pokemon_id, name=name, form_name=form_name, sprite_url=sprite_url, national_dex=national_dex, generation=region_code) |
|
|
|
|
|
|
|
with self._lock: |
|
|
|
if national_dex not in self.pokemon: |
|
|
|
self.pokemon[national_dex] = [] |
|
|
|
self.pokemon[national_dex].append(pokemon_form) |
|
|
|
@ -156,33 +159,24 @@ def download_image(url, filename): |
|
|
|
with open(filename, 'wb') as f: |
|
|
|
f.write(response.content) |
|
|
|
|
|
|
|
def retrieve_all_pokemon_forms(cache: CacheManager, progress_callback=None): |
|
|
|
db = PokemonDatabase() |
|
|
|
pokemon_db_conn = create_pokemon_db() |
|
|
|
create_pokemon_storage_db() |
|
|
|
|
|
|
|
page_data = get_pokemon_sprites_page(cache) |
|
|
|
if not page_data: |
|
|
|
return None |
|
|
|
|
|
|
|
soup = BeautifulSoup(page_data, 'html.parser') |
|
|
|
def worker(queue: Queue, db: PokemonDatabase, pokemon_generations: dict, db_controller: DBController, |
|
|
|
cache: CacheManager, progress_callback=None): |
|
|
|
while True: |
|
|
|
try: |
|
|
|
# Get task from queue |
|
|
|
task = queue.get() |
|
|
|
if task is None: # Poison pill to stop worker |
|
|
|
break |
|
|
|
|
|
|
|
pokemon = soup.find_all('a', class_='infocard') |
|
|
|
index, mon = task |
|
|
|
process_single_pokemon(index + 1, mon, db, pokemon_generations, db_controller, cache, progress_callback) |
|
|
|
|
|
|
|
pokemon_generations = { |
|
|
|
1: {"min": 1, "max": 151}, |
|
|
|
2: {"min": 152, "max": 251}, |
|
|
|
3: {"min": 252, "max": 386}, |
|
|
|
4: {"min": 387, "max": 493}, |
|
|
|
5: {"min": 494, "max": 649}, |
|
|
|
6: {"min": 650, "max": 721}, |
|
|
|
7: {"min": 722, "max": 809}, |
|
|
|
8: {"min": 810, "max": 905}, |
|
|
|
9: {"min": 906, "max": 1025}, |
|
|
|
} |
|
|
|
except Exception as e: |
|
|
|
logger.error(f"Error processing pokemon: {e}") |
|
|
|
finally: |
|
|
|
queue.task_done() |
|
|
|
|
|
|
|
national_dex_index = 1 |
|
|
|
for mon in pokemon: |
|
|
|
def process_single_pokemon(national_dex_index, mon, db, pokemon_generations, db_controller, cache, progress_callback): |
|
|
|
generation = 1 |
|
|
|
for gen in pokemon_generations: |
|
|
|
if pokemon_generations[gen]["min"] <= national_dex_index <= pokemon_generations[gen]["max"]: |
|
|
|
@ -199,19 +193,19 @@ def retrieve_all_pokemon_forms(cache: CacheManager, progress_callback=None): |
|
|
|
|
|
|
|
sprites_page_data = get_pokemon_sprites_page_data(cache, pokemon_url_name) |
|
|
|
if not sprites_page_data: |
|
|
|
return None |
|
|
|
return |
|
|
|
sprites_soup = BeautifulSoup(sprites_page_data, 'html.parser') |
|
|
|
|
|
|
|
generation_8_header = sprites_soup.find('h2', string='Generation 8') |
|
|
|
if not generation_8_header: |
|
|
|
continue |
|
|
|
return |
|
|
|
generation_8_table = generation_8_header.find_next('table') |
|
|
|
if not generation_8_table: |
|
|
|
continue |
|
|
|
return |
|
|
|
|
|
|
|
generation_8_tbody = generation_8_table.find('tbody') |
|
|
|
if not generation_8_tbody: |
|
|
|
continue |
|
|
|
return |
|
|
|
|
|
|
|
generation_8_rows = generation_8_tbody.find_all('tr') |
|
|
|
|
|
|
|
@ -249,7 +243,7 @@ def retrieve_all_pokemon_forms(cache: CacheManager, progress_callback=None): |
|
|
|
form -= 1 |
|
|
|
gender = 2 |
|
|
|
|
|
|
|
dex_page_data = get_pokemon_dex_page(cache, pokemon_name.replace("'", "").replace(".", "-").replace(" ", "")) |
|
|
|
dex_page_data = get_pokemon_dex_page(cache, pokemon_url_name) |
|
|
|
if dex_page_data: |
|
|
|
dex_soup = BeautifulSoup(dex_page_data, 'html.parser') |
|
|
|
|
|
|
|
@ -284,17 +278,15 @@ def retrieve_all_pokemon_forms(cache: CacheManager, progress_callback=None): |
|
|
|
for i, (regional, game1, game2) in enumerate(matches, 1): |
|
|
|
if compare_forms(test_form, regional): |
|
|
|
target_game = game1.replace("Pokemon", "").strip() |
|
|
|
cursor = pokemon_db_conn.cursor() |
|
|
|
cursor.execute(''' |
|
|
|
result = db_controller.execute_query(''' |
|
|
|
SELECT g.generation |
|
|
|
FROM games g |
|
|
|
LEFT JOIN alternate_game_names agn ON g.id = agn.game_id |
|
|
|
WHERE g.name = ? OR agn.alternate_name = ? |
|
|
|
LIMIT 1 |
|
|
|
''', (target_game, target_game)) |
|
|
|
result = cursor.fetchone() |
|
|
|
if result: |
|
|
|
generation = result[0] |
|
|
|
generation = result[0][0] |
|
|
|
generation_found = True |
|
|
|
break |
|
|
|
if generation_found: |
|
|
|
@ -317,12 +309,58 @@ def retrieve_all_pokemon_forms(cache: CacheManager, progress_callback=None): |
|
|
|
form_name if form_name != "None" else None, |
|
|
|
sprite_url |
|
|
|
) |
|
|
|
insert_pokemon_form(pokemon_db_conn, pokemon_form) |
|
|
|
insert_pokemon_form(db_controller, pokemon_form) |
|
|
|
|
|
|
|
storable_in_home = not any(keyword in form_name.lower() for keyword in ['mega', 'gigantamax']) if form_name else True |
|
|
|
insert_pokemon_storage(pokemon_db_conn, pokemon_form.id, storable_in_home) |
|
|
|
insert_pokemon_storage(db_controller, pokemon_form.id, storable_in_home) |
|
|
|
|
|
|
|
def retrieve_all_pokemon_forms(cache: CacheManager, progress_callback=None): |
|
|
|
db = PokemonDatabase() |
|
|
|
db_controller = DBController('pokemon_forms.db', max_connections=20) |
|
|
|
|
|
|
|
page_data = get_pokemon_sprites_page(cache) |
|
|
|
if not page_data: |
|
|
|
return None |
|
|
|
|
|
|
|
soup = BeautifulSoup(page_data, 'html.parser') |
|
|
|
pokemon = soup.find_all('a', class_='infocard') |
|
|
|
|
|
|
|
pokemon_generations = { |
|
|
|
1: {"min": 1, "max": 151}, |
|
|
|
2: {"min": 152, "max": 251}, |
|
|
|
3: {"min": 252, "max": 386}, |
|
|
|
4: {"min": 387, "max": 493}, |
|
|
|
5: {"min": 494, "max": 649}, |
|
|
|
6: {"min": 650, "max": 721}, |
|
|
|
7: {"min": 722, "max": 809}, |
|
|
|
8: {"min": 810, "max": 905}, |
|
|
|
9: {"min": 906, "max": 1025}, |
|
|
|
} |
|
|
|
|
|
|
|
# Create a queue and workers |
|
|
|
num_workers = 1 # Adjust based on your needs |
|
|
|
task_queue = Queue() |
|
|
|
workers = [] |
|
|
|
|
|
|
|
for _ in range(num_workers): |
|
|
|
worker_thread = Thread(target=worker, |
|
|
|
args=(task_queue, db, pokemon_generations, |
|
|
|
db_controller, cache, progress_callback)) |
|
|
|
worker_thread.daemon = True |
|
|
|
worker_thread.start() |
|
|
|
workers.append(worker_thread) |
|
|
|
|
|
|
|
for index, mon in enumerate(pokemon): |
|
|
|
task_queue.put((index, mon)) |
|
|
|
|
|
|
|
# Add poison pills to stop workers |
|
|
|
for _ in range(num_workers): |
|
|
|
task_queue.put(None) |
|
|
|
|
|
|
|
task_queue.join() |
|
|
|
|
|
|
|
national_dex_index += 1 |
|
|
|
for worker_thread in workers: |
|
|
|
worker_thread.join() |
|
|
|
|
|
|
|
logger.info(f"Total Pokémon forms: {sum(len(forms) for forms in db.pokemon.values())}") |
|
|
|
logger.info(f"Pokémon with multiple forms: {sum(1 for forms in db.pokemon.values() if len(forms) > 1)}") |
|
|
|
@ -339,7 +377,7 @@ def retrieve_all_pokemon_forms(cache: CacheManager, progress_callback=None): |
|
|
|
download_image(form.sprite_url, filename) |
|
|
|
logger.info(f"Downloaded image for {form.id}") |
|
|
|
|
|
|
|
pokemon_db_conn.close() |
|
|
|
db_controller.close() |
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
cache = CacheManager() |
|
|
|
|