This commit is contained in:
team3
2026-06-17 22:56:24 +02:00
parent 0ff33271a0
commit dce9156ac8
17 changed files with 743 additions and 42 deletions

View File

@@ -119,32 +119,81 @@ def _lade_bausteine(text: str) -> dict[int, str]:
_FRAGMENT_KAPITEL_RE = re.compile(r"<!--\s*kapitel\s*:\s*(.*?)\s*-->", re.IGNORECASE)
_FRAGMENT_SECTION_RE = re.compile(r"<!--\s*section\s*:\s*(.*?)\s*-->", re.IGNORECASE)
_FRAGMENT_SUB_RE = re.compile(r"<!--\s*sub\s*:\s*(.*?)\s*-->", re.IGNORECASE)
_FRAGMENT_BAUSTEIN_RE = re.compile(r"<!--\s*baustein\s*:\s*(.*?)\s*-->", re.IGNORECASE)
_STUFEN = ("einfach", "mittel", "schwer")
def _parse_fragment(text: str) -> list[dict]:
"""Parst eine Writer-Datei → [{"kapitel", "titel", "md"}] in Datei-Reihenfolge."""
"""Parst eine Writer-Datei → [{"kapitel", "titel", "md", "subs"}] in Datei-Reihenfolge.
Optionale Subbaustein-Marker `<!-- sub: stufe | Titel -->` innerhalb einer
Section sammeln sich in `sec["subs"] = [{"stufe", "titel", "md"}]`. `sec["md"]`
bleibt der vollständige Body (alle Sub-Texte zusammengesetzt) — auch ohne Subs.
"""
sections: list[dict] = []
kapitel = None
current = None
cur_sub = None
for line in text.splitlines():
s = line.strip()
m = _FRAGMENT_KAPITEL_RE.match(s)
if m:
kapitel = m.group(1)
current = None
cur_sub = None
continue
m = _FRAGMENT_SECTION_RE.match(s)
if m:
current = {"kapitel": kapitel, "titel": m.group(1), "md": []}
current = {"kapitel": kapitel, "titel": m.group(1), "md": [], "subs": []}
cur_sub = None
sections.append(current)
continue
m = _FRAGMENT_SUB_RE.match(s)
if m and current is not None:
teil = m.group(1).split("|", 1)
stufe = teil[0].strip().casefold()
cur_sub = {
"stufe": stufe if stufe in _STUFEN else "einfach",
"titel": teil[1].strip() if len(teil) == 2 else "",
"md": [],
}
current["subs"].append(cur_sub)
continue
if current is not None:
current["md"].append(line)
if cur_sub is not None:
cur_sub["md"].append(line)
for sec in sections:
sec["md"] = "\n".join(sec["md"]).strip()
for sub in sec["subs"]:
sub["md"] = "\n".join(sub["md"]).strip()
sec["subs"] = [sub for sub in sec["subs"] if sub["md"]]
return sections
def _parse_subbausteine(text: str) -> dict[str, list[str]]:
"""Parst eine Subbaustein-Datei → {Baustein-Titel: [Subbaustein, …]} in Reihenfolge.
Format: `<!-- baustein: Titel -->` gefolgt von Listenzeilen `- Subbaustein`.
"""
out: dict[str, list[str]] = {}
current = None
for line in text.splitlines():
s = line.strip()
m = _FRAGMENT_BAUSTEIN_RE.match(s)
if m:
current = m.group(1).strip()
out.setdefault(current, [])
continue
if current is None:
continue
m = re.match(r"[-*]\s+(.*\S)", s)
if m:
out[current].append(m.group(1).strip())
return {k: v for k, v in out.items() if v}
def _split_chunks(chapters: list[dict], n: int) -> list[list[dict]]:
"""Teilt Kapitel in bis zu n zusammenhängende Chunks, balanciert nach Section-Anzahl."""
n = max(1, min(n, len(chapters)))