Browse Source

- More WIP for determining the correct origin mark

master
Dan 1 year ago
parent
commit
4e7d292c37
  1. 27
      DBEditor/DBEditor.py
  2. 45
      DBEditor/db_controller.py
  3. 27
      DBEditor/pokemon_db_ui.py
  4. 10
      Determining an origin mark.txt
  5. 128
      Site/OriginDex.py
  6. BIN
      pokemon_forms.db

27
DBEditor/DBEditor.py

@ -95,6 +95,7 @@ class DBEditor(QMainWindow):
event_system.add_listener('gather_evolution_info', self.gather_evolution_info) event_system.add_listener('gather_evolution_info', self.gather_evolution_info)
event_system.add_listener('gather_encounter_info', self.gather_encounter_info) event_system.add_listener('gather_encounter_info', self.gather_encounter_info)
event_system.add_listener('reinitialize_database', self.reinitialize_database) event_system.add_listener('reinitialize_database', self.reinitialize_database)
event_system.add_listener('gather_marks_info', self.gather_marks_info)
self.conn = sqlite3.connect(':memory:', check_same_thread=False) # Use in-memory database for runtime self.conn = sqlite3.connect(':memory:', check_same_thread=False) # Use in-memory database for runtime
self.cursor = self.conn.cursor() self.cursor = self.conn.cursor()
@ -436,6 +437,32 @@ class DBEditor(QMainWindow):
self.logger.info("Database reinitialized successfully.") self.logger.info("Database reinitialized successfully.")
QMessageBox.information(self, 'Database Reinitialized', 'The database has been cleared and reinitialized.') QMessageBox.information(self, 'Database Reinitialized', 'The database has been cleared and reinitialized.')
def gather_marks_info(self, data):
event_system.emit_sync('clear_log_display')
self.logger.info("Starting to gather marks information...")
pokemon_list = event_system.call_sync('get_pokemon_list')
for pfic, name, form_name, national_dex in pokemon_list:
pokemon_data = event_system.call_sync('get_pokemon_data', pfic)
#Rule 1
# 1. If a pokemon form has a previous evolution from within the same generation,
# use the mark of the previous evolution. This should be recursive within the same generation.
chain = event_system.call_sync('get_evolution_chain', pfic)
if chain:
find_me = lambda x: x[0] == pfic
target_index = next((i for i, item in enumerate(chain) if find_me(item)), -1)
base_form_in_generation = None
for i in range(target_index, -1, -1):
chain_pfic, chain_name, chain_form_name, method = chain[i]
chain_pokemon_data = event_system.call_sync('get_pokemon_data', chain_pfic)
if chain_pokemon_data[3] == pokemon_data[3]:
base_form_in_generation = chain_pfic
else:
break
def qt_message_handler(mode, context, message): def qt_message_handler(mode, context, message):

45
DBEditor/db_controller.py

@ -34,6 +34,7 @@ class DBController:
event_system.add_listener('add_new_exclusive_set', self.add_new_exclusive_set) event_system.add_listener('add_new_exclusive_set', self.add_new_exclusive_set)
event_system.add_listener('save_changes', self.save_changes) event_system.add_listener('save_changes', self.save_changes)
event_system.add_listener('export_database', self.export_database) event_system.add_listener('export_database', self.export_database)
event_system.add_listener('assign_mark_to_form', self.assign_mark_to_form)
def init_database(self): def init_database(self):
disk_conn = sqlite3.connect('pokemon_forms.db') disk_conn = sqlite3.connect('pokemon_forms.db')
@ -48,6 +49,7 @@ class DBController:
self.create_encounter_exclusive_group_table(disk_cursor) self.create_encounter_exclusive_group_table(disk_cursor)
self.create_encounters_table(disk_cursor) self.create_encounters_table(disk_cursor)
self.create_mark_table(disk_cursor) self.create_mark_table(disk_cursor)
self.create_form_marks_table(disk_cursor)
# Commit changes to the file-based database # Commit changes to the file-based database
disk_conn.commit() disk_conn.commit()
@ -159,18 +161,20 @@ class DBController:
("Kalos", "images/marks/Blue_pentagon_HOME.png", ["X", "Y", "Omega Ruby", "Alpha Sapphire"]), ("Kalos", "images/marks/Blue_pentagon_HOME.png", ["X", "Y", "Omega Ruby", "Alpha Sapphire"]),
("Alola", "images/marks/Black_clover_HOME.png", ["Sun", "Moon", "Ultra Sun", "Ultra Moon"]), ("Alola", "images/marks/Black_clover_HOME.png", ["Sun", "Moon", "Ultra Sun", "Ultra Moon"]),
("Let's Go", "images/marks/Let's_Go_icon_HOME.png", ["Let's Go Pikachu", "Let's Go Eevee"]), ("Let's Go", "images/marks/Let's_Go_icon_HOME.png", ["Let's Go Pikachu", "Let's Go Eevee"]),
("Galar", "images/marks/Galar_symbol_HOME.png", ["Sword", "Shield"]), ("Galar", "images/marks/Galar_symbol_HOME.png", ["Sword", "Shield", "Expansion Pass"]),
("Sinnoh", "images/marks/BDSP_icon_HOME.png", ["Brilliant Diamond", "Shining Pearl"]), ("Sinnoh", "images/marks/BDSP_icon_HOME.png", ["Brilliant Diamond", "Shining Pearl"]),
("Hisui", "images/marks/Arceus_mark_HOME.png", ["Legends Arceus"]), ("Hisui", "images/marks/Arceus_mark_HOME.png", ["Legends Arceus"]),
("Paldea", "images/marks/Paldea_icon_HOME.png", ["Scarlet", "Violet"]), ("Paldea", "images/marks/Paldea_icon_HOME.png", ["Scarlet", "Violet", "The Teal Mask", "The Hidden Treasure of Area Zero"]),
] ]
# Check if marks already exist # Check if marks already exist
cursor.execute('SELECT COUNT(*) FROM marks') cursor.execute('SELECT COUNT(*) FROM marks')
marks_count = cursor.fetchone()[0] marks_count = cursor.fetchone()[0]
if marks_count == 0:
for mark in marks: for mark in marks:
mark_id = None
if marks_count == 0:
cursor.execute(''' cursor.execute('''
INSERT OR IGNORE INTO marks (name, icon_path) INSERT OR IGNORE INTO marks (name, icon_path)
VALUES (?, ?) VALUES (?, ?)
@ -178,6 +182,12 @@ class DBController:
mark_id = cursor.lastrowid mark_id = cursor.lastrowid
if mark_id == None:
cursor.execute('''
SELECT id FROM marks WHERE name = ?
''', (mark[0],))
mark_id = cursor.fetchone()[0]
for game_name in mark[2]: for game_name in mark[2]:
cursor.execute(''' cursor.execute('''
INSERT OR IGNORE INTO mark_game_associations (mark_id, game_id) INSERT OR IGNORE INTO mark_game_associations (mark_id, game_id)
@ -250,7 +260,13 @@ class DBController:
("Pokémon Go", 99, ["Pokémon GO"]), ("Pokémon Go", 99, ["Pokémon GO"]),
] ]
# Check if marks already exist
cursor.execute('SELECT COUNT(*) FROM games')
games_count = cursor.fetchone()[0]
for game in games: for game in games:
game_id = None
if games_count == 0:
cursor.execute(''' cursor.execute('''
INSERT OR IGNORE INTO games (name, generation) INSERT OR IGNORE INTO games (name, generation)
VALUES (?, ?) VALUES (?, ?)
@ -258,6 +274,12 @@ class DBController:
game_id = cursor.lastrowid game_id = cursor.lastrowid
if game_id == None:
cursor.execute('''
SELECT id FROM games WHERE name = ?
''', (game[0],))
game_id = cursor.fetchone()[0]
# Insert alternate names # Insert alternate names
for alt_name in game[2]: for alt_name in game[2]:
cursor.execute(''' cursor.execute('''
@ -265,6 +287,17 @@ class DBController:
VALUES (?, ?) VALUES (?, ?)
''', (game_id, alt_name)) ''', (game_id, alt_name))
def create_form_marks_table(self, cursor):
cursor.execute('''
CREATE TABLE IF NOT EXISTS form_marks (
pfic TEXT,
mark_id INTEGER,
FOREIGN KEY (pfic) REFERENCES pokemon_forms (PFIC),
FOREIGN KEY (mark_id) REFERENCES marks (id),
PRIMARY KEY (pfic, mark_id)
)
''')
def load_pokemon_details(self, pfic): def load_pokemon_details(self, pfic):
self.cursor.execute(''' self.cursor.execute('''
SELECT pf.name, pf.form_name, pf.national_dex, pf.generation, ps.storable_in_home, pf.is_baby_form SELECT pf.name, pf.form_name, pf.national_dex, pf.generation, ps.storable_in_home, pf.is_baby_form
@ -448,3 +481,9 @@ class DBController:
export_conn = sqlite3.connect('pokemon_forms_production.db') export_conn = sqlite3.connect('pokemon_forms_production.db')
self.conn.backup(export_conn) self.conn.backup(export_conn)
export_conn.close() export_conn.close()
def assign_mark_to_form(self, data):
pfic, mark_id = data
self.cursor.execute('INSERT INTO form_marks (pfic, mark_id) VALUES (?, ?)', (pfic, mark_id))
self.conn.commit()

27
DBEditor/pokemon_db_ui.py

@ -307,6 +307,10 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
gather_encounters_btn.clicked.connect(self.gather_encounter_info) gather_encounters_btn.clicked.connect(self.gather_encounter_info)
db_tab_layout.addWidget(gather_encounters_btn) db_tab_layout.addWidget(gather_encounters_btn)
gather_marks_btn = QPushButton("Gather Marks Information")
gather_marks_btn.clicked.connect(self.gather_marks_info)
db_tab_layout.addWidget(gather_marks_btn)
# Add QTextEdit for progress reporting # Add QTextEdit for progress reporting
self.progress_text = QTextEdit() self.progress_text = QTextEdit()
self.progress_text.setReadOnly(True) self.progress_text.setReadOnly(True)
@ -849,26 +853,6 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
storable_in_home = self.home_checkbox.isChecked() storable_in_home = self.home_checkbox.isChecked()
is_baby_form = self.is_baby_form_checkbox.isChecked() is_baby_form = self.is_baby_form_checkbox.isChecked()
# Update the in-memory database
#self.cursor.execute('''
# UPDATE pokemon_storage
# SET storable_in_home = ?
# WHERE PFIC = ?
#''', (storable_in_home, self.current_pfic))
#self.cursor.execute('''
# UPDATE pokemon_forms
# SET is_baby_form = ?
# WHERE PFIC = ?
#''', (is_baby_form, self.current_pfic))
#self.conn.commit()
# Write the in-memory database to disk
#disk_conn = sqlite3.connect('pokemon_forms.db')
#self.conn.backup(disk_conn)
#disk_conn.close()
event_system.emit_sync('save_changes') event_system.emit_sync('save_changes')
QMessageBox.information(self, "Save Complete", "Changes have been saved to the database.") QMessageBox.information(self, "Save Complete", "Changes have been saved to the database.")
@ -940,4 +924,5 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
def gather_encounter_info(self): def gather_encounter_info(self):
event_system.emit_sync('gather_encounter_info') event_system.emit_sync('gather_encounter_info')
def gather_marks_info(self):
event_system.emit_sync('gather_marks_info')

10
Determining an origin mark.txt

@ -3,8 +3,12 @@ To determine an origin mark:
1. If a pokemon form has a previous evolution from within the same generation, 1. If a pokemon form has a previous evolution from within the same generation,
use the mark of the previous evolution. This should be recursive within the same generation. use the mark of the previous evolution. This should be recursive within the same generation.
2. If a pokemon form has no previous evolution from within the same generation, 2. If a pokemon form has no previous evolution from within the same generation,
look at the encounters of the pokemon form and use the mark of the earliest game you can encounter that form in. look at the encounters of the pokemon form from this generation and use the mark of the earliest
3. If there are no encounters for the pokemon form, game you can encounter that form in from that generation.
3. If there are no encounters for the pokemon form from this generation,
look to see if a previous evolution has an encounter from this generation, and use the mark of the earliest
game from this generation that the previous evolution is encounterable in.
4. If there are no encounters for the pokemon form or its evolution line from this generation,
use the mark of the earliest game of the generation is marked as being introducted in. use the mark of the earliest game of the generation is marked as being introducted in.
4. If there is no mark for the earliest game of the generation, 5. If there is no mark for the earliest game of the generation,
then it has no origin mark. then it has no origin mark.

128
Site/OriginDex.py

@ -13,68 +13,47 @@ def load_pokemon_data():
# First query: Get all Pokémon data # First query: Get all Pokémon data
cursor.execute(''' cursor.execute('''
WITH EarliestGamePerPokemon AS (
SELECT e.pfic, MIN(g.generation) as min_generation, MIN(g.id) as earliest_game_id
FROM encounters e
JOIN games g ON e.game_id = g.id
GROUP BY e.pfic
)
SELECT SELECT
pf.national_dex, pf.name, pf.form_name, pf.PFIC, pf.generation, pf.national_dex, pf.name, pf.form_name, pf.PFIC, pf.generation,
ps.storable_in_home, g.name as earliest_game, ps.storable_in_home
m.icon_path as mark_icon, m.id as mark_id, pf.is_baby_form
FROM pokemon_forms pf FROM pokemon_forms pf
JOIN pokemon_storage ps ON pf.PFIC = ps.PFIC JOIN pokemon_storage ps ON pf.PFIC = ps.PFIC
LEFT JOIN EarliestGamePerPokemon eg ON pf.PFIC = eg.pfic
LEFT JOIN games g ON eg.earliest_game_id = g.id
LEFT JOIN mark_game_associations mga ON g.id = mga.game_id
LEFT JOIN marks m ON mga.mark_id = m.id
WHERE ps.storable_in_home = 1 WHERE ps.storable_in_home = 1
ORDER BY pf.PFIC ORDER BY pf.PFIC
''') ''')
pokemon_data = cursor.fetchall() pokemon_data = cursor.fetchall()
# Second query: Get evolution chain with generation info # Function to get the origin mark for a Pokémon
def get_origin_mark(pfic, generation):
# Step 1: Check for previous evolution in the same generation
cursor.execute(''' cursor.execute('''
WITH RECURSIVE EvolutionChain AS ( WITH RECURSIVE EvolutionChain AS (
SELECT to_pfic AS PFIC, from_pfic, pf.generation SELECT ec.to_pfic, ec.from_pfic, pf_to.generation as to_gen, pf_from.generation as from_gen
FROM evolution_chains ec FROM evolution_chains ec
JOIN pokemon_forms pf ON ec.to_pfic = pf.PFIC JOIN pokemon_forms pf_to ON ec.to_pfic = pf_to.PFIC
JOIN pokemon_forms pf_from ON ec.from_pfic = pf_from.PFIC
WHERE ec.to_pfic = ? AND pf_to.generation = ?
UNION ALL UNION ALL
SELECT ec.to_pfic, e.from_pfic, pf.generation SELECT ec.to_pfic, ec.from_pfic, pf_to.generation, pf_from.generation
FROM evolution_chains ec FROM evolution_chains ec
JOIN EvolutionChain e ON ec.from_pfic = e.PFIC JOIN EvolutionChain e ON ec.to_pfic = e.from_pfic
JOIN pokemon_forms pf ON ec.to_pfic = pf.PFIC JOIN pokemon_forms pf_to ON ec.to_pfic = pf_to.PFIC
JOIN pokemon_forms pf_from ON ec.from_pfic = pf_from.PFIC
WHERE pf_to.generation = ? AND pf_from.generation = ?
) )
SELECT PFIC, MIN(from_pfic) AS base_pfic, MIN(generation) AS base_generation SELECT from_pfic
FROM EvolutionChain FROM EvolutionChain
GROUP BY PFIC WHERE from_pfic IS NOT NULL AND from_gen = ?
''') ORDER BY from_pfic
LIMIT 1
evolution_data = {row[0]: (row[1], row[2]) for row in cursor.fetchall()} ''', (pfic, generation, generation, generation, generation))
base_pfic = cursor.fetchone()
# Process the data if base_pfic:
current_group = [] pfic = base_pfic[0]
current_generation = None
current_dex_number = None
pokemon_forms = []
for row in pokemon_data: # Step 2: Look for the earliest encounter for this form in the current generation
national_dex, name, form_name, pfic, generation, storable_in_home, earliest_game, mark_icon, mark_id, is_baby_form = row
# Find the base form for the mark, considering generation
base_pfic = pfic
base_generation = generation
while base_pfic in evolution_data:
prev_pfic, prev_generation = evolution_data[base_pfic]
if prev_pfic is not None and prev_generation == base_generation:
base_pfic = prev_pfic
else:
break
# If the base form is different, we need to fetch its earliest game and mark
if base_pfic != pfic:
cursor.execute(''' cursor.execute('''
SELECT g.name, m.icon_path, m.id SELECT g.name, m.icon_path, m.id
FROM encounters e FROM encounters e
@ -84,10 +63,62 @@ def load_pokemon_data():
WHERE e.pfic = ? AND g.generation = ? WHERE e.pfic = ? AND g.generation = ?
ORDER BY g.id ORDER BY g.id
LIMIT 1 LIMIT 1
''', (base_pfic, base_generation)) ''', (pfic, generation))
base_data = cursor.fetchone() encounter_data = cursor.fetchone()
if base_data:
earliest_game, mark_icon, mark_id = base_data if encounter_data:
return encounter_data
# Step 3: Look for encounters of previous evolutions in the current generation
cursor.execute('''
WITH RECURSIVE EvolutionChain AS (
SELECT ec.to_pfic, ec.from_pfic
FROM evolution_chains ec
WHERE ec.to_pfic = ?
UNION ALL
SELECT ec.to_pfic, ec.from_pfic
FROM evolution_chains ec
JOIN EvolutionChain e ON ec.to_pfic = e.from_pfic
)
SELECT g.name, m.icon_path, m.id
FROM EvolutionChain ec
JOIN encounters e ON ec.from_pfic = e.pfic
JOIN games g ON e.game_id = g.id
LEFT JOIN mark_game_associations mga ON g.id = mga.game_id
LEFT JOIN marks m ON mga.mark_id = m.id
WHERE g.generation = ?
ORDER BY g.id
LIMIT 1
''', (pfic, generation))
evolution_encounter_data = cursor.fetchone()
if evolution_encounter_data:
return evolution_encounter_data
# Step 4: Use the mark of the earliest game of the generation
cursor.execute('''
SELECT g.name, m.icon_path, m.id
FROM games g
LEFT JOIN mark_game_associations mga ON g.id = mga.game_id
LEFT JOIN marks m ON mga.mark_id = m.id
WHERE g.generation = ?
ORDER BY g.id
LIMIT 1
''', (generation,))
generation_data = cursor.fetchone()
return generation_data if generation_data else (None, None, None)
# Process the data
current_group = []
current_generation = None
current_dex_number = None
pokemon_forms = []
for row in pokemon_data:
national_dex, name, form_name, pfic, generation, storable_in_home = row
earliest_game, mark_icon, mark_id = get_origin_mark(pfic, generation)
pokemon = { pokemon = {
'pfic': pfic, 'pfic': pfic,
@ -103,8 +134,7 @@ def load_pokemon_data():
'MarkID': mark_id 'MarkID': mark_id
} }
# Add the Pokémon to the current group
if national_dex != current_dex_number: if national_dex != current_dex_number:
if pokemon_forms: if pokemon_forms:
for form in pokemon_forms: for form in pokemon_forms:

BIN
pokemon_forms.db

Binary file not shown.
Loading…
Cancel
Save