Benutzer:Patrick Oberdoerfer/ZUM-Apps und H5P/Advanced Fill in the Blanks/

Aus ZUM Projektwiki

Einleitung

Im Rahmen der Arbeiten am Angebot Differenzierung bin ich ein großer Fan des Inhaltstypen Advanced Fill in the Blanks geworden.

Allerdings ist die Erstellung verhältnismäßig aufwendig, weshalb ich den Versuch gestartet habe, die Erstellung via CSV-Vorlage und Python zu optimieren.

Das Ergebnis scheint ganz erfolgreich zu sein.

Was brauchen wir hierfür auf dem PC ?

Hierfür benötigen wir Python und es muss (z.B. via Windows PowerShell das Paket pandas installiert sein – das ist eine sehr beliebte Bibliothek, die zum Einlesen von CSV-Dateien verwendet wird.)

Wie installiere ich das pandas Paket?

Öffne deine Eingabeaufforderung / Terminal / PowerShell und gib dort ein: pip install pandas

Wenn du mehrere Versionen von Python installiert hast, und das nicht klappt, versuche stattdessen: python -m pip install pandas

Oder falls du Python 3 mit explizitem Befehl aufrufen musst: python3 -m pip install pandas

Wenn du die Meldung bekommst Requirement already satisfied, ist es schon drauf – alles gut!


Dann muss das Python-Skript und die CSV-Vorlage mit den aktuellen Eingaben in einen Ordner. Über die Windows-Eingabeaufforderung muss jetzt im passenden Ordner

dieser Befehl ausgeführt werden: python generate_content_json.py

Wie geht es weiter?

Erstelle eine H5P Advanced Fill in the Blank mit einer Lücke.

Komplett automatisierte H5P-Datei-Erstellung mit Python

Der Ablauf des Python-Skripts:

  1. Die CSV-Datei wird gelesen
  2. Die content.json automatisch generiert
  3. Eine vorhandene H5P-Datei (deine Vorlage) genutzt
  4. Die content.json austauscht
  5. Eine neue und fertige .h5p-Datei erzeugt

ToDo für die Erstellung

Schritt 1: Was brauchen wir hierfür:

  • Einen eigenen leeren Ordner
  • Deine CSV-Datei
  • Eine H5P-Vorlagendatei, also z. B. eine .h5p, die du manuell erstellt hast (mit dem richtigen Typ: Advanced Fill in the Blanks)

Schritt 2: Die Vorlage umbenennen in: vorlage.h5p

Diese im selben Ordner wie das Skript und die CSV abspeichern.

Schritt 3: Das Python-Skript

<syntaxhighlight lang="python" line="1"> import pandas as pd import json import zipfile import shutil import os

  1. === Pfade definieren ===

csv_path = "Eingabe Advanced Fill in the Blanks - Tabelle.CSV" h5p_vorlage = "vorlage.h5p" neue_h5p = "mein_output.h5p" temp_dir = "temp_h5p"

  1. === Schritt 1: CSV einlesen und content.json erzeugen ===

df = pd.read_csv(csv_path, sep=';', encoding='utf-8') df.columns = df.columns.str.strip()

def create_blanks_text(s):

   return s.replace("*", "____")

content = {

   "blanksText": "",
   "blanksList": []

} blanks = [] texts = []

for _, row in df.iterrows():

   if pd.isna(row['Satz']):
       continue

texts.append(f"

{create_blanks_text(row['Satz'])}

")

   correct = row['Lösung']
   hint = row.get('Tipp', None)
   incorrects = []
   for i in range(1, 5):
       wrong = row.get(f'Vom Nutzer eingegebene falsche Antwort {i}')
       feedback = row.get(f'Rückmeldung.{i-1}')
       if pd.notna(wrong):
           incorrects.append({
               "showHighlight": False,
               "highlight": "-1",
               "incorrectAnswerText": wrong,

"incorrectAnswerFeedback": f"

{feedback or }

"

           })
   entry = {
       "correctAnswerText": correct,
       "incorrectAnswersList": incorrects
   }
   if pd.notna(hint):
       entry["hint"] = hint
   blanks.append(entry)

content["blanksText"] = "\n".join(texts) content["blanksList"] = blanks

full_data = {

   "content": content,
   "behaviour": {
       "mode": "selection",
       "selectAlternatives": "alternatives",
       "selectAlternativeRestriction": 1,
       "spellingErrorBehaviour": "mistake",
       "caseSensitive": False,
       "autoCheck": False,
       "enableSolutionsButton": False,
       "showSolutionsRequiresInput": True,
       "enableRetry": True,
       "enableCheckButton": True
   },
   "showSolutions": "Lösung anzeigen",
   "tryAgain": "Wiederholen",
   "checkAnswer": "Überprüfen",
   "notFilledOut": "Bitte fülle alle Lücken aus, um die Lösung zu sehen",
   "tipLabel": "Tipp",
   "scoreBarLabel": "Du hast :num von :total Punkten erreicht."

}

  1. === Schritt 2: Vorlage entpacken ===

if os.path.exists(temp_dir):

   shutil.rmtree(temp_dir)

with zipfile.ZipFile(h5p_vorlage, 'r') as zip_ref:

   zip_ref.extractall(temp_dir)
  1. === Schritt 3: content.json ersetzen ===

with open(os.path.join(temp_dir, "content", "content.json"), "w", encoding="utf-8") as f:

   json.dump(full_data, f, ensure_ascii=False, indent=2)
  1. === Schritt 4: Alles wieder einpacken ===

with zipfile.ZipFile(neue_h5p, 'w', zipfile.ZIP_DEFLATED) as zipf:

   for root, _, files in os.walk(temp_dir):
       for file in files:
           abs_path = os.path.join(root, file)
           rel_path = os.path.relpath(abs_path, temp_dir)
           zipf.write(abs_path, rel_path)

print("✅ Neue H5P-Datei erfolgreich erstellt:", neue_h5p)