File: //workspace/rebuild_montessori.py
#!/usr/bin/env python3
"""Montessori-Dateien Rebuild Script"""
import os, glob, zipfile
from xml.etree import ElementTree as ET
from docx import Document
from docx.shared import Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH
from pptx import Presentation
from pptx.util import Inches as PptxInches
IMG_DIR = "/mnt/onedrive_write/FOS_Deutsch_Lehrplanvergleich_2026/06_Bilder/"
IMAGE_MAP = {
'AB2_Digitale-Texte_multiple-Dokumente_Montessori.docx': 'VK_Digitale-Texte_Illustration.png',
'AB3_Konstruktives-Feedback_Montessori.docx': 'VK_Funktion1_Einstieg.png',
'AB1_Social-Media-Phänomene_Montessori.docx': 'JG11_Social-Media_Illustration.png',
'AB2_KI-gestütztes-Schreiben_Montessori.docx': 'JG11_Funktion1_Einstieg.png',
'AB3_Podcasts-moderne-Medienformate_Montessori.docx': 'JG11_Podcast-Medien_Illustration.png',
'AB1_Desinformation_erkennen_Montessori.docx': 'JG12_Medienmanipulation_Analyse.png',
'AB2_Framing_Storytelling_Montessori.docx': 'JG12_Framing_Perspektiven.png',
'AB3_KI_gestütztes_Schreiben_Montessori.docx': 'JG12_Funktion1_Einstieg.png',
'AB1_Data_Bias_Montessori.docx': 'JG13_Data_Bias_Algorithmen.png',
'AB2_Wissenschaftliches_Arbeiten_KI_Montessori.docx': 'JG13_Funktion1_Einstieg.png',
'AB3_Mensch_vs_KI_Kreativitaet_Montessori.docx': 'JG13_Mensch_vs_KI_Kreativitaet.png',
}
PPTX_IMAGE_MAP = {
'Arbeitsphasen_Vorklasse_KI-Schreiben_Montessori.pptx': 'VK_KI-Schreiben_Illustration.png',
'Einführung_Vorklasse_Deutsch_2026_Montessori.pptx': 'VK_Digitale-Texte_Illustration.png',
'Arbeitsphasen_Jahrgang11_Social-Media_Montessori.pptx': 'JG11_Social-Media_Illustration.png',
'Einführung_Jahrgang11_Deutsch_2026_Montessori.pptx': 'JG11_Social-Media_Illustration.png',
'Arbeitsphasen_Medienkompetenz_JG12_Montessori.pptx': 'JG12_Medienmanipulation_Analyse.png',
'Einführung_Medienkompetenz_JG12_Montessori.pptx': 'JG12_Framing_Perspektiven.png',
'Arbeitsphasen_KI_Kritik_Kreativitaet_JG13_Montessori.pptx': 'JG13_Mensch_vs_KI_Kreativitaet.png',
'Einführung_KI_Medienkultur_JG13_Montessori.pptx': 'JG13_Data_Bias_Algorithmen.png',
}
def fix_umlauts(text):
r = text
for o,n in [('erschliessen','erschließen'),('Ergaenze','Ergänze'),('ergaenze','ergänze'),
('aendern','ändern'),('Aendern','Ändern'),('ueberarbeiten','überarbeiten'),
('Ueberarbeitung','Überarbeitung'),('fuer','für'),('Fuer','Für'),
('koennen','können'),('koennte','könnte'),('Koennte','Könnte'),
('koenntest','könntest'),('moechtest','möchtest'),('Moechtest','Möchtest'),
('fuenfmal','fünfmal'),('Schueler','Schüler'),('schueler','schüler'),
('Loesung','Lösung'),('loesung','lösung'),('Loesungen','Lösungen'),
('Vorschlaege','Vorschläge'),('Staerken','Stärken'),('Schwaechen','Schwächen'),
('verstaerken','verstärken'),('Verstaerkung','Verstärkung'),
('serios','seriös'),('Seriositaet','Seriosität'),('pruefe','prüfe'),
('Pruefe','Prüfe'),('pruefen','prüfen'),('Pruefung','Prüfung'),
('haeufigsten','häufigsten'),('Haeufigsten','Häufigsten'),('Saetze','Sätze'),
('saetze','sätze'),('regelmaessig','regelmäßig'),('Regelmaessigkeit','Regelmäßigkeit'),
('ueben','üben'),('Uebung','Übung'),('ueber','über'),('Ueber','Über'),
('Ueberblick','Überblick'),('Begriffsklaerung','Begriffsklärung'),
('Praesentation','Präsentation'),('Praesentieren','Präsentieren'),
('Aktivitaet','Aktivität'),('Qualitaet','Qualität'),('Kreativitaet','Kreativität'),
('Authentizitaet','Authentizität'),('Originalitaet','Originalität'),
('Aesthetisch','Ästhetisch'),('aesthetisch','ästhetisch'),
('Gefaehrlich','Gefährlich'),('gefaehrlich','gefährlich'),
('Leistungsschwaechere','Leistungsschwächere'),('Leistungsstaerkere','Leistungsstärkere'),
('Feedbackqualitaet','Feedbackqualität'),('Zusaetzliche','Zusätzliche'),
('zusaetzliche','zusätzliche'),('Faelle','Fälle'),('Unzulaessig','Unzulässig'),
('unzulaessig','unzulässig'),('Zulaessig','Zulässig'),('zulaessig','zulässig'),
('Begruendung','Begründung'),('begruenden','begründen'),('Begruende','Begründe'),
('begruende','begründe'),('Erorterung','Erörterung'),('Woertlich','Wörtlich'),
('woertlich','wörtlich'),('Unverandert','Unverändert'),('Uberarbeitung','Überarbeitung'),
('Ueberarbeitung','Überarbeitung'),('Wahle','Wähle'),('waehle','wähle'),
('Waehle','Wähle'),('Aehnliche','Ähnliche'),('aehnliche','ähnliche'),
('Strasse','Straße'),('strasse','straße'),('Strassen','Straßen'),
('strassen','straßen'),('Gross','Groß'),('gross','groß'),('Mass','Maß'),
('Massstab','Maßstab'),('Ausmass','Ausmaß'),('Gruessen','Grüßen'),
('Zeitunabhaengig','Zeitunabhängig'),('Durchfuehrung','Durchführung'),
('Fussnote','Fußnote'),('Angehoerige','Angehörige'),('Erklaerung','Erklärung'),
('erklaeren','erklären'),('erklaert','erklärt'),('Flaeche','Fläche'),
('flaeche','fläche'),('Baeume','Bäume'),('Baecker','Bäcker'),
('Naechste','Nächste'),('naechste','nächste'),('naechsten','nächsten'),
('Fruehling','Frühling'),('frueh','früh'),('Tuer','Tür'),
('Praegnanz','Prägnanz'),('Uebereinstimmung','Übereinstimmung'),
('Geraete','Geräte')]:
r = r.replace(o,n)
return r
def extract_docx_paragraphs(fp):
ps = []
try:
with zipfile.ZipFile(fp,'r') as z:
xml = z.read('word/document.xml')
tree = ET.fromstring(xml)
for p in tree.iter('{http://schemas.openxmlformats.org/wordprocessingml/2006/main}p'):
ts = [t.text for t in p.iter('{http://schemas.openxmlformats.org/wordprocessingml/2006/main}t') if t.text]
if ts: ps.append(''.join(ts))
except Exception as e: print(f" Fehler: {e}")
return ps
def rebuild_docx(fp, img=None):
ps = extract_docx_paragraphs(fp)
doc = Document()
embedded = False
if ps:
doc.add_heading(fix_umlauts(ps[0][:80]), level=1)
if img and os.path.exists(img):
try:
p = doc.add_paragraph()
r = p.add_run()
r.add_picture(img, width=Inches(5.5))
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
doc.add_paragraph()
embedded = True
print(f" ✓ Bild: {os.path.basename(img)}")
except Exception as e: print(f" ✗ Bild-Fehler: {e}")
skip = ['VK_Digitale-Texte_Illustration','VK_Funktion1_Einstieg','JG11_Social-Media_Illustration',
'JG11_Funktion1_Einstieg','JG11_Podcast-Medien_Illustration','JG12_Medienmanipulation_Analyse',
'JG12_Framing_Perspektiven','JG12_Funktion1_Einstieg','JG13_Data_Bias_Algorithmen',
'JG13_Funktion1_Einstieg','JG13_Mensch_vs_KI_Kreativitaet']
for i,para in enumerate(ps):
if i==0 or '[Bild:' in para or para.strip() in skip or 'Illustration]' in para: continue
f = fix_umlauts(para)
if f.strip(): doc.add_paragraph(f)
doc.save(fp)
return embedded
def rebuild_pptx(fp, img=None):
embedded = False
try:
prs = Presentation(fp)
for s in prs.slides:
for sh in s.shapes:
if sh.has_text_frame:
for p in sh.text_frame.paragraphs:
for r in p.runs:
if r.text: r.text = fix_umlauts(r.text)
if img and os.path.exists(img) and len(prs.slides)>0:
try:
sl = prs.slides[0]
sl.shapes.add_picture(img, PptxInches(5.5), PptxInches(1.5), width=PptxInches(4.0))
embedded = True
print(f" ✓ Bild: {os.path.basename(img)}")
except Exception as e: print(f" ✗ Bild-Fehler: {e}")
prs.save(fp)
except Exception as e: print(f" ✗ Fehler: {e}")
return embedded
if __name__ == "__main__":
base = "/mnt/onedrive_write/FOS_Deutsch_Lehrplanvergleich_2026"
print("="*60 + "\nMONTESORI REBUILD - DOCX\n" + "="*60)
for fp in sorted(glob.glob(f"{base}/**/*_Montessori.docx", recursive=True)):
fn = os.path.basename(fp)
print(f"\n{fn}")
img = IMAGE_MAP.get(fn)
rebuild_docx(fp, os.path.join(IMG_DIR, img) if img else None)
print(" ✓ Gespeichert")
print("\n" + "="*60 + "\nMONTESORI REBUILD - PPTX\n" + "="*60)
for fp in sorted(glob.glob(f"{base}/**/*_Montessori.pptx", recursive=True)):
fn = os.path.basename(fp)
print(f"\n{fn}")
img = PPTX_IMAGE_MAP.get(fn)
rebuild_pptx(fp, os.path.join(IMG_DIR, img) if img else None)
print(" ✓ Gespeichert")
print("\nFERTIG!")