lehrkraefte:blc:informatik:glf22:python:woertlitrainer

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
lehrkraefte:blc:informatik:glf22:python:woertlitrainer [2022/12/07 07:03]
Ivo Blöchliger [Intelligenteres Abfragen]
lehrkraefte:blc:informatik:glf22:python:woertlitrainer [2022/12/16 07:02] (current)
Ivo Blöchliger [Python Snippets]
Line 54: Line 54:
  
 Hinweis: wenn ''paar'' ein Wortpaar ist, dann ist ''paar[0]'' das deutsche und ''paar[1]'' das französische Wort. Hinweis: wenn ''paar'' ein Wortpaar ist, dann ist ''paar[0]'' das deutsche und ''paar[1]'' das französische Wort.
 +
 +<hidden Lösungsvorschlag>
 +<code python>
 +import sys 
 +voci = [ ["ein Byte", "un octet"], ["ein Computer", "un ordinateur"], ["eine Software", "un logiciel"] ]
 +
 +# Wiederholen, für jedes paar in der Liste
 +for paar in voci:
 +    ok = False # Benutzer hat noch nicht richtig geantwortet
 +    anzahlfehler = 0  # Für dieses Wort, noch keinen Fehler
 +    while not ok:
 +        # Wort auf Deutsch anzeigen
 +        print(f"Übersetze: {paar[0]}")
 +        if anzahlfehler>2:  # Mehr als zwei Fehler? Dann Wort anzeigen
 +            print(f"   Hinweis: {paar[1]}")
 +        # Eingabe vom Benutzer einlesen (Zeilenumbruch abschneiden mit strip)
 +        eingabe = sys.stdin.readline().strip()
 +
 +        if eingabe==paar[1]:  # gleich dem Fremdwort?
 +            ok  = True        # Damit wird die Schleife dann beendet
 +        else:
 +            anzahlfehler = anzahlfehler + 1    # Fehlerzähler erhöhen
 +</code>
 +</hidden>
 </WRAP> </WRAP>
  
Line 85: Line 109:
         {"d":"ein Computer", "f":"un ordinateur"},\         {"d":"ein Computer", "f":"un ordinateur"},\
         {"d":"eine Software", "f":"un logiciel"}]         {"d":"eine Software", "f":"un logiciel"}]
-with open("voci.json", "w") as f: +with open("voci.json", "w") as f:   # Datei zum Schreiben öffnen 
-  f.write(json.dumps(voci, indent=2))+  f.write(json.dumps(voci, indent=2))    # Daten in Datei schreiben
   f.write("\n")   f.write("\n")
 </code> </code>
Line 97: Line 121:
 <code python> <code python>
 import json import json
-with open("voci.json", "r") as f: +with open("voci.json", "r") as f:   # Datei zum Lesen öffnen 
-  voci = json.loads(f.read())+  voci = json.loads(f.read())       # Inhalt lesen, interpretieren und in die Variable voci speichern. 
 +   
 +# Jetzt kann mit der Variablen voci wie vorhin gearbeitet werden:
 print(voci) print(voci)
 </code> </code>
Line 131: Line 157:
 </WRAP> </WRAP>
  
 +
 +<hidden Lösungsvorschlag>
 +<code pyton voci-mit-dict-von-datei.py>
 +import sys 
 +import os
 +import json
 +
 +##################
 +# Daten einlesen #
 +##################
 +
 +# Datei bestimmen (default oder von der Kommandozeile)
 +datei = "voci.json"
 +if len(sys.argv)>1:  # Falls es ein zusätzliches Kommandozeilenargument gibt
 +    datei = sys.argv[1]
 +print(f"Versuche Daten aus der Datei {datei} einzulesen")
 +if not os.path.exists(datei):   # Falls die Datei nicht existiert, abbrechen
 +    print(f"Sorry, die Datei {datei} existiert nicht!")
 +    exit(-1)  # Abbruch mit Fehler
 +
 +# Daten einlesen
 +with open(datei, "r") as f:   # Datei zum Lesen öffnen
 +  voci = json.loads(f.read())       # Inhalt lesen, interpretieren und in die Variable voci speichern.
 + 
 +##########
 +# Lernen #
 +##########
 +
 +# Wiederholen, für jedes paar in der Liste
 +for paar in voci:
 +    ok = False # Benutzer hat noch nicht richtig geantwortet
 +    anzahlfehler = 0
 +    while not ok:
 +        # Wort auf Deutsch anzeigen
 +        print(f"Übersetze: {paar['d']}")
 +        if anzahlfehler>2:
 +            print(f"   Hinweis: {paar['f']}")
 +        # Eingabe vom Benutzer
 +        eingabe = sys.stdin.readline().strip()
 +
 +        if eingabe==paar['f']:  # gleich dem Fremdwort?
 +            ok  = True
 +        else:
 +            anzahlfehler = anzahlfehler + 1
 +</code>
 +</hidden>
 ====== Intelligenteres Abfragen ====== ====== Intelligenteres Abfragen ======
 Wörter, die man schon gut kann, sollten nicht (oder kaum) abgefragt werden. Andere sollten hingegen häufiger abgefragt werden. Auch sollte die Reihenfolge der Wörter zufällig sein. Wörter, die man schon gut kann, sollten nicht (oder kaum) abgefragt werden. Andere sollten hingegen häufiger abgefragt werden. Auch sollte die Reihenfolge der Wörter zufällig sein.
Line 164: Line 236:
 for i in range(10):  # 10 mal wiederholen, zum Testen for i in range(10):  # 10 mal wiederholen, zum Testen
     # Vokabular sortieren, wobei ein Eintrag mit score+zufallszahl bewertet wird:     # Vokabular sortieren, wobei ein Eintrag mit score+zufallszahl bewertet wird:
-    voci = sorted(voci, key = lambda eintrag: eintrag['s']+random.random())+    voci.sort(key = lambda eintrag: eintrag['s']+random.random())
     print(f"Erster Eintrag ist jetzt: {voci[0]}")     print(f"Erster Eintrag ist jetzt: {voci[0]}")
 </code> </code>
Line 176: Line 248:
   * Wenn das Programm beendet wird, sollen die Daten wieder geschrieben werden, damit die Scores erhalten bleiben.   * Wenn das Programm beendet wird, sollen die Daten wieder geschrieben werden, damit die Scores erhalten bleiben.
   * Erstellen Sie eine JSON-Datei mit dem aktuellen Französisch-Vokubular (gerne auch kollaborativ, so dass jeder z.B. 10 Wörter einträgt und dann die Dateien vereinigt werden).   * Erstellen Sie eine JSON-Datei mit dem aktuellen Französisch-Vokubular (gerne auch kollaborativ, so dass jeder z.B. 10 Wörter einträgt und dann die Dateien vereinigt werden).
 +
 +<hidden Lösungsvorschlag>
 +<code python voci-v1.py>
 +import sys 
 +import os
 +import json
 +import random
 +
 +##################
 +# Daten einlesen #
 +##################
 +
 +# Datei bestimmen (default oder von der Kommandozeile)
 +datei = "voci.json"
 +if len(sys.argv)>1:  # Falls es ein zusätzliches Kommandozeilenargument gibt
 +    datei = sys.argv[1]
 +print(f"Versuche Daten aus der Datei {datei} einzulesen")
 +if not os.path.exists(datei):   # Falls die Datei nicht existiert, abbrechen
 +    print(f"Sorry, die Datei {datei} existiert nicht!")
 +    exit(-1)  # Abbruch mit Fehler
 +
 +# Daten einlesen
 +with open(datei, "r") as f:   # Datei zum Lesen (read) öffnen
 +  voci = json.loads(f.read())       # Inhalt lesen, interpretieren und in die Variable voci speichern.
 +
 +# Scores hinzufügen, falls nötig
 +for paar in voci:
 +  if not "s" in paar:  # Gibt es den Schlüssel s bereits? Falls nein, hinzufügen.
 +    paar["s"] = 0
 +
 +##########
 +# Lernen #
 +##########
 +
 +# Wiederholen, bis der Benutzer abbricht
 +programmEnde = False
 +print("Hinweis: Durch Eingabe von 'x' kann das Programm beendet werden.")
 +while not programmEnde:  # Endlos-Schleife
 +    # Wörter Sortieren:
 +    voci = sorted(voci, key = lambda eintrag: eintrag['s']+random.random())
 +    # Aktuelles paar ist das erste in der Liste
 +    paar = voci[0]
 +    # Abfrage vorbereiten
 +    ok = False # Benutzer hat noch nicht richtig geantwortet
 +    anzahlfehler = 0
 +    while not ok:  # Wiederholen, bis der Benutzer richtig geantwortet hat.
 +        # Wort auf Deutsch anzeigen
 +        print(f"Übersetze: {paar['d']}     (score {paar['s']})")
 +        if anzahlfehler>2:
 +            print(f"   Hinweis: {paar['f']}")
 +        # Eingabe vom Benutzer
 +        eingabe = sys.stdin.readline().strip()
 +        if eingabe=="x":
 +            programmEnde = True
 +            break     # innere while-Schlaufe verlassen
 +
 +        if eingabe==paar['f']:  # gleich dem Fremdwort?
 +            ok  = True
 +            if anzahlfehler==0:
 +                paar['s']+=2
 +            elif anzahlfehler==1:
 +                paar['s']+=1
 +            else:
 +                paar['s'] -= 1
 +                if (paar['s']<0):
 +                    paar['s']=0
 +        else:
 +            anzahlfehler = anzahlfehler + 1
 +
 +# Daten speichern:
 +with open(datei, "w") as f:   # Datei zum Schreiben (write) öffnen
 +  f.write(json.dumps(voci, indent=2))    # Daten in Datei schreiben
 +  f.write("\n")
 +</code>
 +</hidden>
 </WRAP> </WRAP>
  
 +====== Besserer Programmierstil ======
 +Im Moment ist das Programm ein schon ziemlich unübersichtlicher Klumpen. Um das Programm übersichtlicher zu gestalten, werden wir einzelne Programmteile in Funktionen auslagern, damit das Programm am Schluss in 3 Zeilen passt:
 +
 +<code python>
 +voci, datei = daten_einlesen()
 +abfragen(voci)
 +daten_speichern(voci, datei)
 +</code>
 +
 +Dazu gibt es einen [[https://fginfo.ksbg.ch/~ivo/videos/informatik/22-23/09-woertli-trainer-refactoring.mp4|Screencast]], oder als [[https://bldsg-my.sharepoint.com/:v:/g/personal/ivo_bloechliger_ksbg_ch/EcT9M_iPJspIrRz0shkQa54BrZ2OdumLJKvhopAFmU3Bnw?e=bpmcYw|SharePoint-Stream]] (neu auch für jeden Internauten, zumindest für 18 Monate)
 +
 +<hidden Lösungsvorschlag>
 +<code python voci-refactored.py>
 +import sys 
 +import os
 +import json
 +import random
 +
 +##################
 +# Daten einlesen #
 +##################
 +
 +def dateinamen_bestimmen():
 +    datei = "voci.json"
 +    if len(sys.argv)>1:  # Falls es ein zusätzliches Kommandozeilenargument gibt
 +        datei = sys.argv[1]
 +    print(f"Versuche Daten aus der Datei {datei} einzulesen")
 +    if not os.path.exists(datei):   # Falls die Datei nicht existiert, abbrechen
 +        print(f"Sorry, die Datei {datei} existiert nicht!")
 +        exit(-1)  # Abbruch mit Fehler
 +    return datei
 +
 +
 +def scores_hinzufuegen(voci):
 +    for paar in voci:
 +        if not "s" in paar:  # Gibt es den Schlüssel s bereits? Falls nein, hinzufügen.
 +            paar["s"] = 0
 +
 +
 +def daten_einlesen():
 +    # Datei bestimmen (default oder von der Kommandozeile)
 +    dateinamen = dateinamen_bestimmen()
 +    # Daten einlesen
 +    with open(dateinamen, "r") as f:   # Datei zum Lesen (read) öffnen
 +        voci = json.loads(f.read())       # Inhalt lesen, interpretieren und in die Variable voci speichern.
 +    # Scores hinzufügen, falls nötig
 +    scores_hinzufuegen(voci)
 +    return voci, dateinamen
 +
 +
 +##########
 +# Lernen #
 +##########
 +
 +def hole_eingabe(paar, anzahlfehler):
 +    # Wort auf Deutsch anzeigen
 +    print(f"Übersetze: {paar['d']}     (score {paar['s']})")
 +    if anzahlfehler>2:
 +        print(f"   Hinweis: {paar['f']}")
 +    # Eingabe vom Benutzer
 +    return sys.stdin.readline().strip()
 +
 +
 +def wort_korrekt(eingabe, paar, anzahlfehler):
 +    if eingabe != paar['f']:
 +        return False   # Funktion sofort beenden
 +    # Eingabe ist korrekt
 +    if anzahlfehler>1:
 +        paar['s'] -= 1
 +        if (paar['s']<0):
 +            paar['s']=0
 +        return True
 +    paar['s'] += 2 - anzahlfehler
 +    return True
 +
 +
 +def wort_abfragen(paar):
 +    anzahlfehler = 0
 +    while True:  # Endlos Schleife
 +        eingabe = hole_eingabe(paar, anzahlfehler)
 +        if eingabe=="x":
 +            return True   # Programmabbruch
 +        if wort_korrekt(eingabe, paar, anzahlfehler):
 +            return False  # Wort korrekt, aber Programm nicht beenden
 +        anzahlfehler = anzahlfehler + 1
 +
 +
 +def wort_bestimmen(voci):
 +    voci.sort(key = lambda eintrag: eintrag['s']+random.random())
 +    # Aktuelles paar ist das erste in der Liste
 +    return voci[0]
 +
 +
 +def abfragen(voci):
 +    while True: # Endlosschleife
 +        paar = wort_bestimmen(voci)
 +        programmAbbruch = wort_abfragen(paar)
 +        if programmAbbruch:
 +            return
 +
 +
 +def daten_speichern(voci, dateinamen):
 +    with open(dateinamen, "w") as f:   # Datei zum Schreiben (write) öffnen
 +        f.write(json.dumps(voci, indent=2))    # Daten in Datei schreiben
 +        f.write("\n")
 +
 +
 +voci, dateiname = daten_einlesen()
 +abfragen(voci)
 +daten_speichern(voci, dateiname)
 +</code>
 +</hidden>
  
  • lehrkraefte/blc/informatik/glf22/python/woertlitrainer.1670393038.txt.gz
  • Last modified: 2022/12/07 07:03
  • by Ivo Blöchliger