fix: Fachwort Fluss nicht mehr aus eigenen Prompts; englische Zahlen und Teilfragen

- Routing-Prompt verlangt bei Dijkstra Restriktionsnamen in der Sprache der Aufgabe
  statt Flusserhaltung; Solver-Prompt ohne Fachwort (löste Korrekturrunden aus)
- JARGON_EVERYDAY: beeinflusst/Einfluss/Überfluss zählen weder als Vorkommen noch als
  Erklärung eines Fachbegriffs
- normalize_number liest eindeutige englische Zahlen (1,234.56; 12,345,678) richtig
- QUESTION_PATTERN erkennt Part/Question/Task N

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-09-17 16:38:45 +02:00
commit 0582737b22

View file

@ -78,9 +78,15 @@ JARGON = {
}
# Alltagswörter, die einen Fachbegriff-Stamm enthalten. Sie zählen weder als Vorkommen noch als Erklärung –
# beobachtet: „beeinflusst“ in der Zusammenfassung galt als Erklärung von „Flusserhaltung“ (20260917-160618).
JARGON_EVERYDAY = re.compile(r"beeinfluss|einfluss|überfluss|ueberfluss|flussdiagramm")
def unexplained_jargon(sichtbar: str, erklaerung: str) -> List[str]:
"""Fachbegriffe, die im sichtbaren Text vorkommen, in der Erklärung aber nicht."""
sichtbar, erklaerung = sichtbar.lower(), erklaerung.lower()
sichtbar = JARGON_EVERYDAY.sub(" ", sichtbar.lower())
erklaerung = JARGON_EVERYDAY.sub(" ", erklaerung.lower())
return sorted(name for name, staemme in JARGON.items()
if any(s in sichtbar for s in staemme) and not any(s in erklaerung for s in staemme))
@ -104,8 +110,9 @@ def check_jargon(spec: OptimizationModelSpecification) -> List[CheckIssue]:
# Zahl im Fließtext: 1.234,56 / 0,05 / 12 / 3.8 – ohne Zahlen, die Teil eines Wortes sind (A02, x1)
NUMBER_PATTERN = re.compile(r"(?<![A-Za-z0-9_])\d+(?:[.,]\d+)*(?![A-Za-z0-9_])")
# Teilfragen-Marker am Zeilenanfang: "a)", "- b)", "**Teil 2:**", "1." – bewusst eng, um
# Aufzählungen im Fließtext nicht als Frage zu zählen.
QUESTION_PATTERN = re.compile(r"^[\s\-*>]*\**\s*(?:\(?([a-h])\)|(?:Teil|Aufgabe|Frage)\s+(\d+)|([1-9])\.)\s*[:.)]?\s+\S",
# Aufzählungen im Fließtext nicht als Frage zu zählen. Englische Marker ("Part 2", "Question 1", "Task 3")
# gehören dazu: sonst fehlt bei englischen Aufgaben das Nachfassen bei übersehenen Teilfragen.
QUESTION_PATTERN = re.compile(r"^[\s\-*>]*\**\s*(?:\(?([a-h])\)|(?:Teil|Aufgabe|Frage|Part|Question|Task)\s+(\d+)|([1-9])\.)\s*[:.)]?\s+\S",
re.MULTILINE)
@ -115,8 +122,16 @@ def normalize_number(roh: str) -> str:
Der Punkt ist mehrdeutig: Tausendertrenner (deutsch) oder Dezimalpunkt (englisch, Nummerierung).
Entschieden wird am Komma (dann ist der Punkt Tausendertrenner) und sonst an der Gruppenlänge:
genau drei Ziffern hinter dem letzten Punkt heißt Tausender, alles andere Dezimalpunkt.
Englische Schreibweise wird erkannt, wo sie eindeutig ist: '1,234.56' (Punkt nach dem Komma) und
'12,345,678' (mehrere Dreiergruppen). Ein einzelnes '1,500' bleibt deutsch gelesen (1,5) – beides ist
möglich, und die Pipeline ist auf deutsche Aufgaben ausgelegt. Vorher wurde '1,234.56' zu 1.23456.
"""
if "," in roh:
englisch = (("." in roh and roh.rfind(".") > roh.rfind(",") > -1) # 1,234.56
or (roh.count(",") > 1 and "." not in roh and all(len(t) == 3 for t in roh.split(",")[1:]))) # 12,345,678
if englisch:
roh = roh.replace(",", "")
elif "," in roh:
roh = roh.replace(".", "").replace(",", ".")
elif "." in roh:
teile = roh.split(".")