Eigene Wörterliste für KHangman

In diesem Blogpost beschreibe ich, wie ich meine eigene Wörterliste für KHangman erzeugt habe.
Professor Hastig
KDE
Python
ubuntuusers
Autor:in

Joe Slam

Veröffentlichungsdatum

03 Juli 2025 - 22:53

Geändert

03 Juli 2025 - 22:53

KHangMan ist ein KDE-App, die auf dem klassischen Galgenmännchen-Spiel basiert. Sie ist Teil der KDE Software Compilation, genauer gesagt, des kdeedu-Pakets.

KHangMan funktioniert dabei nicht so, wie ihr vielleicht denkt. Denn die Wörter, die erraten werden sollen, können nicht selbst eingegeben werden. Vielmehr greift KHangman auf eine Reihe von vorinstallierten Wortlisten zurück, die für verschiedene Kategorien bereitgestellt werden, z.B. “Zahlen”, “Hauptstädte”, “Tiere”, usw.

Möchte man eigene Wörter spielen, muss man eine eigene Wortliste erstellen und für KHangMan verfügbar machen.

custom word list

Die Wörterlisten liegen im Verzeichnis /usr/share/apps/kvtml/LANGUAE, wobei LANGUAGE durch den Ländercode ersetzt werden muss. Die deutschen Wörterlisten liegen also unter /usr/share/apps/kvtml/de und haben die Dateiendung .kvtml. Für jede Wörterliste existiert eine eigene .kvtml-Datei.

Die Skelettstruktur einer solchen Wörterliste sieht so aus:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE kvtml PUBLIC "kvtml2.dtd" "http://edu.kde.org/kvtml/kvtml2.dtd">
<kvtml version="2.0">
  <information>
    <generator>converter</generator>
    <title>TITEL DER LISTE</title>
    <comment>DEINE BESCHREIBUNG</comment>
  </information>

  <identifiers>
    <identifier id="0">
      <locale>de</locale>
    </identifier>
  </identifiers>
  
  <entries>
  
    <entry id="0">
      <inactive>false</inactive>
      <inquery>false</inquery>
      <translation id="0">
        <text>DEIN WORT</text>
        <comment>EIN KOMMENTAR</comment>
      </translation>
    </entry>

    </entries>
</kvtml>
  • in Zeile 6 und 7 wird der Name der Liste samt einer kleinen Beschreibung angegeben. Unter diesem Namen ist die Wortliste später in KHangMan auffindbar.
  • in Zeile 12 geben wir an, dass die Sprache der Liste de ist.
  • Die Zeilen 18 bis 25 bilden einen Entry-Block für ein gewünschtes Wort. Dabei wird
    • in Zeile 18 eine eindeutige <entry id> angegeben (hochzählen)
    • in Zeile 22 das eigentliche Wort definiert
    • in Zeile 23 ein kurzer Hilfetext gesetzt.
  • diese Entry-Blöcke müssen für jedes Wort erzeugt werden.

Für ein Statistik-Quiz könnte die vollständige Datei so aussehen:

sudo nano /usr/share/apps/kvtml/statistikquiz.kvtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE kvtml PUBLIC "kvtml2.dtd" "http://edu.kde.org/kvtml/kvtml2.dtd">
<kvtml version="2.0">
  <information>
    <generator>converter</generator>
    <title>Statistik</title>
    <comment>Statistik</comment>
  </information>
  <identifiers>
    <identifier id="0">
      <locale>de</locale>
    </identifier>
  </identifiers>
  <entries>
    <entry id="0">
      <inactive>false</inactive>
      <inquery>false</inquery>
      <translation id="0">
        <text>Boxplot</text>
        <comment>graphische Darstellung einer metrischen Werteverteilung</comment>
      </translation>
    </entry>
    <entry id="1">
      <inactive>false</inactive>
      <inquery>false</inquery>
      <translation id="0">
        <text>Histogram</text>
        <comment>graphische Darstellung klassierter Häufigkeiten</comment>
      </translation>
    </entry>
    <entry id="2">
      <inactive>false</inactive>
      <inquery>false</inquery>
      <translation id="0">
        <text>Kausalität</text>
        <comment>ursächlicher Zusammenhang</comment>
      </translation>
    </entry>
    <entry id="3">
      <inactive>false</inactive>
      <inquery>false</inquery>
      <translation id="0">
        <text>Konfidenzintervall</text>
        <comment>Sicherheitsbereich</comment>
      </translation>
    </entry>
    <entry id="4">
      <inactive>false</inactive>
      <inquery>false</inquery>
      <translation id="0">
        <text>Korrelation</text>
        <comment>Zusammenhang (aber nicht kausal)</comment>
      </translation>
    </entry>
    <entry id="5">
      <inactive>false</inactive>
      <inquery>false</inquery>
      <translation id="0">
        <text>Regressionsgerade</text>
        <comment>Wird beschrieben mit y=a+bx</comment>
      </translation>
    </entry>
    <entry id="6">
      <inactive>false</inactive>
      <inquery>false</inquery>
      <translation id="0">
        <text>Signifikanz</text>
        <comment>liegt vor wenn p kleiner alpha ist</comment>
      </translation>
    </entry>
    <entry id="7">
      <inactive>false</inactive>
      <inquery>false</inquery>
      <translation id="0">
        <text>Standardabweichung</text>
        <comment>Wurzel aus der Varianz</comment>
      </translation>
    </entry>
    <entry id="8">
      <inactive>false</inactive>
      <inquery>false</inquery>
      <translation id="0">
        <text>Varianz</text>
        <comment>Quadrat der Standardabweichung</comment>
      </translation>
    </entry>
  </entries>
</kvtml>

Nachdem die Datei gespeichert ist, wird KHangman gestartet.

Wordlist wechseln

Unten links wird die derzeit aktive Wörterliste angezeigt. In meinem Beispiel ist das “Tiere”.

Wenn man darauf klickt, kann eine andere Wörterliste ausgewählt werden. Da meine Systemsprache deutsch ist, sucht KHangMan im Ordner /usr/share/apps/kvtml/de nach validen .kvtml-Dateien.

eigene Wordlist auswählen

Hier sollte - wenn alles richtig gemacht wurde - die neue eigene Liste auftauchen.

Erstes Wort von der Liste

Ist diese ausgewählt, kann das Spiel beginnen.

:=)

Python-Script

Unter Umständen kann es mühsam sein, eine oder mehrere solcher .kvtml-Dateien zu erstellen und zu pflegen. Beispielsweise ist es mühselig, die entry id nachzuverfolgen, wenn ein Entry-Block zwischen bestehende Blöcke eingeschoben werden soll.

Daher hab ich mir ein kleines naives Python-Script geschrieben, welches mir die Arbeit etwas erleichtert.

Das Script nimmt eine Textdatei entgegen, und erzeugt daraus die passende .kvtml-Datei.

Für das Statistikquiz sieht die Datei so aus:

nano statistik.txt

Boxplot       graphische Darstellung einer metrischen Werteverteilung
Histogram       graphische Darstellung klassierter Häufigkeiten
Kausalität         ursächlicher Zusammenhang
Konfidenzintervall         Sicherheitsbereich
Korrelation        Zusammenhang (aber nicht kausal)
Regressionsgerade        Wird beschrieben mit y=a+bx
Signifikanz        liegt vor wenn p kleiner alpha ist
Standardabweichung       Wurzel aus der Varianz
Varianz        Quadrat der Standardabweichung

Jede Zeile repräsentiert einen Worteintrag. Zuerst kommt das gesuchte Wort, dann mindestens 2 Leerzeichen, und anschließend der Hinweistext.

Hier nun das Python-Script, welches diese Datei ausliest

nano create-wordlist.py

#!/usr/bin/env python3
import sys
import re
import xml.etree.ElementTree as ET
from xml.dom import minidom

def prettify(elem):
    """Return a pretty-printed XML string for the Element."""
    rough_string = ET.tostring(elem, 'utf-8')
    parsed = minidom.parseString(rough_string)
    return parsed.toprettyxml(indent="  ")

def main():
    if len(sys.argv) < 2:
        print("Usage: python3 generate_kvtml.py input.txt")
        sys.exit(1)

    input_file = sys.argv[1]
    output_file = "output.kvtml"

    with open(input_file, "r", encoding="utf-8") as f:
        lines = [line.strip() for line in f if line.strip()]

    kvtml = ET.Element("kvtml", version="2.0")

    info = ET.SubElement(kvtml, "information")
    ET.SubElement(info, "generator").text = "converter"
    ET.SubElement(info, "title").text = "Statistik"
    ET.SubElement(info, "comment").text = "Statistik"

    identifiers = ET.SubElement(kvtml, "identifiers")
    identifier = ET.SubElement(identifiers, "identifier", id="0")
    ET.SubElement(identifier, "locale").text = "de"

    entries = ET.SubElement(kvtml, "entries")

    for idx, line in enumerate(lines):
        parts = re.split(r'\t+| {2,}', line)
        if len(parts) != 2:
            print(f"Warning: Skipping invalid line {idx + 1}: {line}")
            continue
        text, comment = parts
        entry = ET.SubElement(entries, "entry", id=str(idx))
        ET.SubElement(entry, "inactive").text = "false"
        ET.SubElement(entry, "inquery").text = "false"
        trans = ET.SubElement(entry, "translation", id="0")
        ET.SubElement(trans, "text").text = text
        ET.SubElement(trans, "comment").text = comment

    pretty_xml = prettify(kvtml)

    with open(output_file, "w", encoding="utf-8") as f:
        f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        f.write('<!DOCTYPE kvtml PUBLIC "kvtml2.dtd" "http://edu.kde.org/kvtml/kvtml2.dtd">\n')
        f.write('\n'.join(pretty_xml.split('\n')[1:]))  # Überspringt <?xml ...?>

    print(f"✅ KVTML-Datei wurde formatiert geschrieben: {output_file}")

if __name__ == "__main__":
    main()

Das Script wird ausführbar gemacht mittels

chmod +x create-wordlist.py

…und aufgerufen per:

./create-wordlist.py statistik.txt

Das Script erzeugt die Datei output.kvtml, welche alle Entry-Blöcke der Wörterliste enthält. Diese kann nun ins kvtml-Verzeichnis kopiert werden.

cp output.kvtml /usr/share/apps/kvtml/de/MEINE-LISTE.kvtml

Viel Spass beim Ausprobieren!