This commit is contained in:
team3
2026-07-13 06:07:09 +02:00
parent 8926f87185
commit 32d7ad9ea1
15 changed files with 552 additions and 115 deletions

View File

@@ -5,6 +5,7 @@ Synchronen Zugriff bewusst: DB-Arbeit ist gegen LLM-Latenz vernachlässigbar.
`on_change` (von main.py gesetzt) meldet Statuswechsel ans Live-Board."""
import json
import re
import sqlite3
import threading
from pathlib import Path
@@ -112,6 +113,14 @@ CREATE TABLE IF NOT EXISTS lernstand(
topic TEXT NOT NULL, baustein_id INTEGER NOT NULL,
status TEXT NOT NULL DEFAULT 'aktiv', xp INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY(topic, baustein_id));
CREATE TABLE IF NOT EXISTS auftraege(
id INTEGER PRIMARY KEY, baustein_id INTEGER NOT NULL,
art TEXT NOT NULL CHECK(art IN ('falsch','luecke','stil')),
detail TEXT NOT NULL, quelle TEXT NOT NULL DEFAULT 'pruefer',
status TEXT NOT NULL DEFAULT 'offen'
CHECK(status IN ('offen','behoben','kein_mangel','eskaliert')),
runden INTEGER NOT NULL DEFAULT 0);
CREATE INDEX IF NOT EXISTS idx_auftraege ON auftraege(baustein_id, status);
"""
# Tabellen, deren Änderungen das Live-Board interessieren.
@@ -160,9 +169,41 @@ def _init_schema(con: sqlite3.Connection) -> None:
"INSERT INTO artefakte SELECT * FROM artefakte_alt;"
"DROP TABLE artefakte_alt;"
"CREATE INDEX IF NOT EXISTS idx_artefakte_atom ON artefakte(atom_id);")
# Auftrags-Migration: Freitext-JSON in sections.befunde → auftraege-Zeilen.
# Nur KRITISCH-Arten überleben — det-/Stil-Aufträge werden ohnehin jede Runde
# frisch berechnet, und die Prüfer-Paraphrasen waren genau die Krankheit.
if any(sp[1] == "befunde" for sp in con.execute("PRAGMA table_info(sections)")):
for row in con.execute("SELECT baustein_id, befunde FROM sections"
" WHERE befunde NOT IN ('', '[]')").fetchall():
try:
alte = json.loads(row[1])
except ValueError:
alte = []
for a in alte:
p = alt_auftrag(a)
if p and not con.execute(
"SELECT 1 FROM auftraege WHERE baustein_id=? AND detail=?",
(row[0], p[1])).fetchone():
con.execute("INSERT INTO auftraege(baustein_id, art, detail, quelle)"
" VALUES(?,?,?,?)", (row[0], *p))
con.execute("ALTER TABLE sections DROP COLUMN befunde")
con.commit()
_ALT_AUFTRAG = re.compile(r"^KRITISCH \((falsch|luecke|fachlich_falsch)\): (.+)$", re.S)
def alt_auftrag(text) -> tuple[str, str, str] | None:
"""Alt-Format aus sections.befunde → (art, detail, quelle) oder None (verwerfen).
Auch der Transfer-Import alter Exporte nutzt dies."""
m = _ALT_AUFTRAG.match(str(text))
if not m:
return None
art, detail = m.group(1), m.group(2).strip()
return ("falsch" if art == "fachlich_falsch" else art, detail,
"qa" if art == "fachlich_falsch" else "pruefer")
def _notify(tabelle: str, row: dict) -> None:
if on_change is not None and tabelle in _LIVE_TABELLEN:
try: