fix: quest tree cleaned up a bit, Key's ratings not saving fixed
This commit is contained in:
141
app.py
141
app.py
@@ -8,9 +8,66 @@ DB_PATH = "tarkov.db"
|
||||
def get_db():
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
conn.row_factory = sqlite3.Row
|
||||
conn.execute("PRAGMA foreign_keys = ON")
|
||||
return conn
|
||||
|
||||
|
||||
def _migrate_key_ids_and_maps():
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
conn.row_factory = sqlite3.Row
|
||||
conn.execute("PRAGMA foreign_keys = OFF")
|
||||
|
||||
# Backfill missing key IDs with their api_id so ratings can join correctly.
|
||||
conn.execute("""
|
||||
UPDATE keys
|
||||
SET id = api_id
|
||||
WHERE id IS NULL AND api_id IS NOT NULL
|
||||
""")
|
||||
|
||||
# If key_maps was created with INTEGER key_id, migrate to TEXT to match keys.id.
|
||||
cols = conn.execute("PRAGMA table_info(key_maps)").fetchall()
|
||||
key_id_type = None
|
||||
if cols:
|
||||
for col in cols:
|
||||
if col["name"] == "key_id":
|
||||
key_id_type = (col["type"] or "").upper()
|
||||
break
|
||||
if key_id_type and key_id_type != "TEXT":
|
||||
conn.execute("ALTER TABLE key_maps RENAME TO key_maps_old")
|
||||
conn.execute("""
|
||||
CREATE TABLE key_maps (
|
||||
key_id TEXT NOT NULL,
|
||||
map_id INTEGER NOT NULL,
|
||||
PRIMARY KEY (key_id, map_id),
|
||||
FOREIGN KEY (key_id) REFERENCES keys(id),
|
||||
FOREIGN KEY (map_id) REFERENCES maps(id)
|
||||
)
|
||||
""")
|
||||
conn.execute("""
|
||||
INSERT OR IGNORE INTO key_maps (key_id, map_id)
|
||||
SELECT CAST(key_id AS TEXT), map_id
|
||||
FROM key_maps_old
|
||||
WHERE key_id IS NOT NULL
|
||||
AND EXISTS (SELECT 1 FROM keys WHERE id = CAST(key_id AS TEXT))
|
||||
""")
|
||||
conn.execute("DROP TABLE key_maps_old")
|
||||
|
||||
# Remove orphaned ratings created with "None" or missing keys.
|
||||
conn.execute("""
|
||||
DELETE FROM key_ratings
|
||||
WHERE key_id IS NULL
|
||||
OR key_id = 'None'
|
||||
OR key_id NOT IN (SELECT id FROM keys)
|
||||
""")
|
||||
|
||||
conn.commit()
|
||||
conn.execute("PRAGMA foreign_keys = ON")
|
||||
conn.close()
|
||||
|
||||
|
||||
_migrate_key_ids_and_maps()
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
conn = get_db()
|
||||
@@ -198,6 +255,7 @@ def rate_all():
|
||||
def quests():
|
||||
conn = get_db()
|
||||
only_collector = request.args.get("collector") == "1"
|
||||
view = request.args.get("view", "flow") # "flow" or "list"
|
||||
|
||||
# All quests + done state
|
||||
all_quests = conn.execute("""
|
||||
@@ -243,7 +301,7 @@ def quests():
|
||||
|
||||
# Filter to collector-only if requested
|
||||
if only_collector:
|
||||
visible = collector_prereqs | {collector_row["id"]}
|
||||
visible = set(collector_prereqs)
|
||||
else:
|
||||
visible = set(quest_by_id.keys())
|
||||
|
||||
@@ -270,12 +328,14 @@ def quests():
|
||||
visible=visible,
|
||||
collector_prereqs=collector_prereqs,
|
||||
only_collector=only_collector,
|
||||
view=view,
|
||||
)
|
||||
|
||||
|
||||
@app.route("/collector")
|
||||
def collector():
|
||||
conn = get_db()
|
||||
view = request.args.get("view", "flow")
|
||||
collector = conn.execute(
|
||||
"SELECT id FROM quests WHERE name = 'Collector'"
|
||||
).fetchone()
|
||||
@@ -284,33 +344,76 @@ def collector():
|
||||
conn.close()
|
||||
return "Run import_quests.py first to populate quest data.", 503
|
||||
|
||||
# Recursive CTE: all transitive prerequisites, then keep only leaves
|
||||
# (quests that are not themselves a dependency of another prereq)
|
||||
prereqs = conn.execute("""
|
||||
# All quests + done state
|
||||
all_quests = conn.execute("""
|
||||
SELECT q.id, q.name, q.trader, q.wiki_link,
|
||||
COALESCE(qp.done, 0) AS done
|
||||
FROM quests q
|
||||
LEFT JOIN quest_progress qp ON q.id = qp.quest_id
|
||||
ORDER BY q.trader, q.name
|
||||
""").fetchall()
|
||||
|
||||
# All dependency edges
|
||||
all_deps = conn.execute("SELECT quest_id, depends_on FROM quest_deps").fetchall()
|
||||
|
||||
# Collector prereq set (transitive)
|
||||
rows = conn.execute("""
|
||||
WITH RECURSIVE deps(quest_id) AS (
|
||||
SELECT depends_on FROM quest_deps WHERE quest_id = ?
|
||||
UNION
|
||||
SELECT qd.depends_on FROM quest_deps qd
|
||||
JOIN deps d ON qd.quest_id = d.quest_id
|
||||
)
|
||||
SELECT q.id, q.name, q.trader, q.wiki_link,
|
||||
COALESCE(qp.done, 0) AS done
|
||||
FROM quests q
|
||||
JOIN deps d ON q.id = d.quest_id
|
||||
LEFT JOIN quest_progress qp ON q.id = qp.quest_id
|
||||
WHERE q.id NOT IN (
|
||||
SELECT qd2.depends_on
|
||||
FROM quest_deps qd2
|
||||
WHERE qd2.quest_id IN (SELECT quest_id FROM deps)
|
||||
AND qd2.depends_on IN (SELECT quest_id FROM deps)
|
||||
)
|
||||
ORDER BY q.trader, q.name
|
||||
SELECT quest_id FROM deps
|
||||
""", (collector["id"],)).fetchall()
|
||||
collector_prereqs = {r[0] for r in rows}
|
||||
|
||||
conn.close()
|
||||
total = len(prereqs)
|
||||
done = sum(1 for q in prereqs if q["done"])
|
||||
return render_template("collector.html", quests=prereqs, total=total, done=done)
|
||||
|
||||
# Build lookup structures
|
||||
quest_by_id = {q["id"]: q for q in all_quests}
|
||||
# children[parent_id] = [child_id, ...] (child depends_on parent)
|
||||
children = {}
|
||||
parents = {}
|
||||
for dep in all_deps:
|
||||
child, parent = dep["quest_id"], dep["depends_on"]
|
||||
children.setdefault(parent, []).append(child)
|
||||
parents.setdefault(child, []).append(parent)
|
||||
# Sort each child list by quest name
|
||||
for parent_id in children:
|
||||
children[parent_id].sort(key=lambda i: quest_by_id[i]["name"] if i in quest_by_id else "")
|
||||
|
||||
visible = set(collector_prereqs)
|
||||
|
||||
# Root quests: in visible set and have no parents also in visible set
|
||||
roots = [
|
||||
qid for qid in visible
|
||||
if not any(p in visible for p in parents.get(qid, []))
|
||||
]
|
||||
|
||||
# Group roots by trader, sorted
|
||||
trader_roots = {}
|
||||
for qid in sorted(roots, key=lambda i: (quest_by_id[i]["trader"], quest_by_id[i]["name"])):
|
||||
t = quest_by_id[qid]["trader"]
|
||||
trader_roots.setdefault(t, []).append(qid)
|
||||
|
||||
traders = sorted(trader_roots.keys())
|
||||
|
||||
total = len(collector_prereqs)
|
||||
done = sum(1 for qid in collector_prereqs if qid in quest_by_id and quest_by_id[qid]["done"])
|
||||
return render_template(
|
||||
"collector.html",
|
||||
quest_by_id=quest_by_id,
|
||||
children=children,
|
||||
trader_roots=trader_roots,
|
||||
traders=traders,
|
||||
visible=visible,
|
||||
collector_prereqs=collector_prereqs,
|
||||
collector_id=collector["id"],
|
||||
total=total,
|
||||
done=done,
|
||||
view=view,
|
||||
)
|
||||
|
||||
|
||||
@app.route("/collector/toggle", methods=["POST"])
|
||||
|
||||
Reference in New Issue
Block a user