Files
Orchestrator/bahn/project-audit/scripts/inb-analyse.py
ankn a5f8fb49ab Migrate all repos into monorepo context folders
Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
      Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
      Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)

Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
2026-06-30 20:39:52 +02:00

133 lines
4.2 KiB
Python

"""
INB-Analyse: Extrahiert Text aus den INB-PDFs und sucht nach Widerspruechen
zwischen Hauptdokument und Anhaengen.
Fokus:
- Expresstrassen (bekannter Widerspruch)
- NAÄ (Netzausgeloeste Aenderungen)
- Abrechnung / Trassenpreis
- Fristen und Annahme-Prozesse
- Schnittstellen-Definitionen
"""
import PyPDF2
from pathlib import Path
import re
DATA_DIR = Path("project-audit/data")
def extract_pdf(path):
"""Extrahiert Text aus PDF."""
text = ""
try:
with open(path, "rb") as f:
reader = PyPDF2.PdfReader(f)
print(f" {path.name}: {len(reader.pages)} Seiten")
for page in reader.pages:
t = page.extract_text()
if t:
text += t + "\n"
except Exception as e:
print(f" FEHLER bei {path.name}: {e}")
return text
# PDFs laden
print("=== INB-2027 Dokumente laden ===")
docs = {}
for pdf in sorted(DATA_DIR.glob("INB-2027*.pdf")):
docs[pdf.stem] = extract_pdf(pdf)
print(f"\nGesamt: {len(docs)} Dokumente, {sum(len(v) for v in docs.values())} Zeichen")
# Suchbegriffe die fuer pathOS relevant sind
SEARCH_TERMS = [
"Expresstrasse",
"express",
"Netzausgelöst",
"netzausgelöst",
"NAÄ",
"implizit",
"Annahme",
"Frist",
"Abrechnung",
"Trassenpreis",
"Schnittstelle",
"TAF",
"TAP",
"elektronisch",
"IT-System",
"Portal",
"Bestellung",
"Stornierung",
"Änderung",
"Gelegenheitsverkehr",
"20 Stunden",
"20h",
"Verkehrstag",
"Tageswechsel",
"Teilausfall",
"Umleitung",
]
print("\n=== Relevante Stellen pro Dokument ===")
for doc_name, text in docs.items():
print(f"\n--- {doc_name} ({len(text)} Zeichen) ---")
found_terms = {}
for term in SEARCH_TERMS:
matches = [m.start() for m in re.finditer(re.escape(term), text, re.IGNORECASE)]
if matches:
found_terms[term] = len(matches)
if found_terms:
for term, count in sorted(found_terms.items(), key=lambda x: -x[1]):
print(f" {term:<25} {count:>3}x")
else:
print(" (keine relevanten Begriffe gefunden)")
# Detailsuche: Expresstrassen
print("\n\n=== DETAIL: Expresstrassen ===")
for doc_name, text in docs.items():
matches = list(re.finditer(r'(?i)express.{0,200}', text))
if matches:
print(f"\n--- {doc_name} ---")
for i, m in enumerate(matches[:5]):
context = text[max(0, m.start()-50):m.start()+200].replace("\n", " ").strip()
print(f" [{i+1}] ...{context}...")
# Detailsuche: NAÄ / Netzausgeloeste Aenderungen
print("\n\n=== DETAIL: NAÄ / Netzausgelöste Änderungen ===")
for doc_name, text in docs.items():
matches = list(re.finditer(r'(?i)(netzausgelöst|NAÄ|netz.{0,5}ausgelöst).{0,200}', text))
if matches:
print(f"\n--- {doc_name} ---")
for i, m in enumerate(matches[:5]):
context = text[max(0, m.start()-30):m.start()+200].replace("\n", " ").strip()
print(f" [{i+1}] ...{context}...")
# Detailsuche: Fristen / Annahme
print("\n\n=== DETAIL: Fristen und Annahme ===")
for doc_name, text in docs.items():
matches = list(re.finditer(r'(?i)(Annahme|angenommen|Frist).{0,150}', text))
if matches:
print(f"\n--- {doc_name} ({len(matches)} Treffer, zeige 5) ---")
for i, m in enumerate(matches[:5]):
context = text[max(0, m.start()-20):m.start()+150].replace("\n", " ").strip()
print(f" [{i+1}] ...{context}...")
# Detailsuche: Abrechnung / Trassenpreis
print("\n\n=== DETAIL: Abrechnung / Trassenpreis ===")
for doc_name, text in docs.items():
matches = list(re.finditer(r'(?i)(Abrechnung|Trassenpreis|Entgelt|Faktur).{0,150}', text))
if matches:
print(f"\n--- {doc_name} ({len(matches)} Treffer, zeige 5) ---")
for i, m in enumerate(matches[:5]):
context = text[max(0, m.start()-20):m.start()+150].replace("\n", " ").strip()
print(f" [{i+1}] ...{context}...")
# Export als Textdateien fuer spaetere Analyse
print("\n\n=== Export als Text ===")
for doc_name, text in docs.items():
out_path = DATA_DIR / f"{doc_name}.txt"
with open(out_path, "w", encoding="utf-8") as f:
f.write(text)
print(f" {out_path.name}: {len(text)} Zeichen")