feat: Implement database management, main window and card view GUI, and a database debug script, removing verify_fix.py.
This commit is contained in:
@@ -103,6 +103,9 @@ def check_for_updates():
|
|||||||
# Or just check inequality. If different, try to update.
|
# Or just check inequality. If different, try to update.
|
||||||
if db_version != VERSION:
|
if db_version != VERSION:
|
||||||
sync_from_seed(bundled_seed_path)
|
sync_from_seed(bundled_seed_path)
|
||||||
|
|
||||||
|
# Always ensure data integrity
|
||||||
|
cleanup_orphaned_data()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Update check failed: {e}")
|
print(f"Update check failed: {e}")
|
||||||
@@ -552,7 +555,12 @@ def get_owned_count():
|
|||||||
"""Get count of owned cards"""
|
"""Get count of owned cards"""
|
||||||
conn = get_conn()
|
conn = get_conn()
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute("SELECT COUNT(*) FROM owned_cards")
|
# Use JOIN to ensure only valid cards are counted
|
||||||
|
cur.execute("""
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM owned_cards oc
|
||||||
|
JOIN support_cards sc ON oc.card_id = sc.card_id
|
||||||
|
""")
|
||||||
count = cur.fetchone()[0]
|
count = cur.fetchone()[0]
|
||||||
conn.close()
|
conn.close()
|
||||||
return count
|
return count
|
||||||
@@ -692,7 +700,12 @@ def get_database_stats():
|
|||||||
cur.execute("SELECT COUNT(*) FROM support_effects")
|
cur.execute("SELECT COUNT(*) FROM support_effects")
|
||||||
stats['total_effects'] = cur.fetchone()[0]
|
stats['total_effects'] = cur.fetchone()[0]
|
||||||
|
|
||||||
cur.execute("SELECT COUNT(*) FROM owned_cards")
|
# Use JOIN to ensure only valid cards are counted
|
||||||
|
cur.execute("""
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM owned_cards oc
|
||||||
|
JOIN support_cards sc ON oc.card_id = sc.card_id
|
||||||
|
""")
|
||||||
stats['owned_cards'] = cur.fetchone()[0]
|
stats['owned_cards'] = cur.fetchone()[0]
|
||||||
|
|
||||||
cur.execute("SELECT COUNT(*) FROM user_decks")
|
cur.execute("SELECT COUNT(*) FROM user_decks")
|
||||||
@@ -701,6 +714,35 @@ def get_database_stats():
|
|||||||
conn.close()
|
conn.close()
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
|
def cleanup_orphaned_data():
|
||||||
|
"""Remove references to non-existent cards in user data tables"""
|
||||||
|
print("Cleaning up orphaned database records...")
|
||||||
|
conn = get_conn()
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 1. Clean owned_cards
|
||||||
|
cur.execute("""
|
||||||
|
DELETE FROM owned_cards
|
||||||
|
WHERE card_id NOT IN (SELECT card_id FROM support_cards)
|
||||||
|
""")
|
||||||
|
if cur.rowcount > 0:
|
||||||
|
print(f"Removed {cur.rowcount} orphaned owned card records.")
|
||||||
|
|
||||||
|
# 2. Clean deck_slots
|
||||||
|
cur.execute("""
|
||||||
|
DELETE FROM deck_slots
|
||||||
|
WHERE card_id NOT IN (SELECT card_id FROM support_cards)
|
||||||
|
""")
|
||||||
|
if cur.rowcount > 0:
|
||||||
|
print(f"Removed {cur.rowcount} orphaned deck slot records.")
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Cleanup failed: {e}")
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# Skill Search Queries
|
# Skill Search Queries
|
||||||
# ============================================
|
# ============================================
|
||||||
|
|||||||
42
debug_db.py
Normal file
42
debug_db.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import sqlite3
|
||||||
|
import os
|
||||||
|
|
||||||
|
def debug_db():
|
||||||
|
db_path = "database/umamusume.db"
|
||||||
|
if not os.path.exists(db_path):
|
||||||
|
print(f"Database not found at {db_path}")
|
||||||
|
return
|
||||||
|
|
||||||
|
conn = sqlite3.connect(db_path)
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
print("--- Database Debug ---")
|
||||||
|
|
||||||
|
cur.execute("SELECT COUNT(*) FROM support_cards")
|
||||||
|
print(f"Total support cards: {cur.fetchone()[0]}")
|
||||||
|
|
||||||
|
cur.execute("SELECT COUNT(*) FROM owned_cards")
|
||||||
|
owned_count = cur.fetchone()[0]
|
||||||
|
print(f"Owned cards count: {owned_count}")
|
||||||
|
|
||||||
|
cur.execute("""
|
||||||
|
SELECT oc.card_id, sc.name
|
||||||
|
FROM owned_cards oc
|
||||||
|
LEFT JOIN support_cards sc ON oc.card_id = sc.card_id
|
||||||
|
""")
|
||||||
|
rows = cur.fetchall()
|
||||||
|
|
||||||
|
print("\nOwned cards details:")
|
||||||
|
for card_id, name in rows:
|
||||||
|
print(f" ID: {card_id}, Name: {name}")
|
||||||
|
|
||||||
|
orphaned = [row[0] for row in rows if row[1] is None]
|
||||||
|
if orphaned:
|
||||||
|
print(f"\nFound {len(orphaned)} orphaned owned cards (Card IDs: {orphaned})")
|
||||||
|
else:
|
||||||
|
print("\nNo orphaned owned cards found.")
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
debug_db()
|
||||||
@@ -27,9 +27,10 @@ from gui.theme import (
|
|||||||
class CardListFrame(ttk.Frame):
|
class CardListFrame(ttk.Frame):
|
||||||
"""Frame containing card list with search/filter, ownership, and details panel"""
|
"""Frame containing card list with search/filter, ownership, and details panel"""
|
||||||
|
|
||||||
def __init__(self, parent, on_card_selected_callback=None):
|
def __init__(self, parent, on_card_selected_callback=None, on_stats_updated_callback=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.on_card_selected = on_card_selected_callback
|
self.on_card_selected = on_card_selected_callback
|
||||||
|
self.on_stats_updated = on_stats_updated_callback
|
||||||
self.cards = []
|
self.cards = []
|
||||||
self.current_card_id = None
|
self.current_card_id = None
|
||||||
self.card_image = None # Keep reference to prevent garbage collection
|
self.card_image = None # Keep reference to prevent garbage collection
|
||||||
@@ -38,6 +39,8 @@ class CardListFrame(ttk.Frame):
|
|||||||
# Create main layout
|
# Create main layout
|
||||||
self.create_widgets()
|
self.create_widgets()
|
||||||
self.load_cards()
|
self.load_cards()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_widgets(self):
|
def create_widgets(self):
|
||||||
"""Create the card list interface"""
|
"""Create the card list interface"""
|
||||||
@@ -415,6 +418,10 @@ class CardListFrame(ttk.Frame):
|
|||||||
level = int(self.level_var.get())
|
level = int(self.level_var.get())
|
||||||
set_card_owned(self.current_card_id, owned, level)
|
set_card_owned(self.current_card_id, owned, level)
|
||||||
self.filter_cards() # Refresh list to update owned markers
|
self.filter_cards() # Refresh list to update owned markers
|
||||||
|
|
||||||
|
# Notify parent to refresh stats
|
||||||
|
if self.on_stats_updated:
|
||||||
|
self.on_stats_updated()
|
||||||
|
|
||||||
def update_level_buttons(self, rarity, max_level):
|
def update_level_buttons(self, rarity, max_level):
|
||||||
"""Update quick level buttons based on rarity/max level"""
|
"""Update quick level buttons based on rarity/max level"""
|
||||||
|
|||||||
@@ -147,7 +147,9 @@ class MainWindow:
|
|||||||
def create_tabs(self):
|
def create_tabs(self):
|
||||||
"""Create all tab frames"""
|
"""Create all tab frames"""
|
||||||
# Card List Tab
|
# Card List Tab
|
||||||
self.card_frame = CardListFrame(self.notebook, on_card_selected_callback=self.on_card_selected)
|
self.card_frame = CardListFrame(self.notebook,
|
||||||
|
on_card_selected_callback=self.on_card_selected,
|
||||||
|
on_stats_updated_callback=self.refresh_stats)
|
||||||
self.notebook.add(self.card_frame, text=" 📋 Card List ")
|
self.notebook.add(self.card_frame, text=" 📋 Card List ")
|
||||||
|
|
||||||
# Effects Tab
|
# Effects Tab
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
|
|
||||||
import sqlite3
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# Add current dir to path to import utils
|
|
||||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
from utils import resolve_image_path
|
|
||||||
|
|
||||||
DB_PATH = r"y:\Keith\umamusuma card application\database\umamusume.db"
|
|
||||||
print(f"Checking DB at: {DB_PATH}")
|
|
||||||
|
|
||||||
try:
|
|
||||||
conn = sqlite3.connect(DB_PATH)
|
|
||||||
cur = conn.cursor()
|
|
||||||
cur.execute("SELECT card_id, name, image_path FROM support_cards LIMIT 5")
|
|
||||||
rows = cur.fetchall()
|
|
||||||
|
|
||||||
print("\nVerifying Path Resolution:")
|
|
||||||
for row in rows:
|
|
||||||
card_id, name, original_path = row
|
|
||||||
resolved = resolve_image_path(original_path)
|
|
||||||
exists = os.path.exists(resolved) if resolved else False
|
|
||||||
|
|
||||||
print(f"Card: {name}")
|
|
||||||
print(f" Original: {original_path}")
|
|
||||||
print(f" Resolved: {resolved}")
|
|
||||||
print(f" Exists: {exists}")
|
|
||||||
print("-" * 50)
|
|
||||||
|
|
||||||
conn.close()
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error: {e}")
|
|
||||||
Reference in New Issue
Block a user