@ -11,7 +11,7 @@ import re
import sys
import readline
DATA_DIR = os . environ [ ' XDG_DATA_HOME ' ] + ' /klette '
DATA_DIR = os . environ . get ( ' XDG_DATA_HOME ' , os . environ [ ' HOME ' ] + ' /.local/share ' ) + ' /klette '
VOKABELN_FILE = DATA_DIR + ' /vokabeln.json '
STATUS_FILE = DATA_DIR + ' /status.json '
AUDIO_BASE = DATA_DIR + ' /audio/ '
@ -71,33 +71,54 @@ def vergleiche(respuesta, expecta):
respuesta = ' ¡ ' + respuesta [ 1 : ]
if respuesta [ 0 ] == ' ? ' and expecta [ 0 ] == ' ¿ ' :
respuesta = ' ¿ ' + respuesta [ 1 : ]
respuesta = re . sub ( ' (~n|n~) ' , ' ñ ' , respuesta )
expecta = re . sub ( ' \ ((irr.|pl.) \ ) ' , ' ' , expecta )
respuesta = unicodedata . normalize ( ' NFD ' , respuesta )
expecta = unicodedata . normalize ( ' NFD ' , expecta )
respuesta = re . sub ( ' ?([!?¿¡….]) ? ' , r ' \ 1 ' , respuesta )
expecta = re . sub ( ' ?([!?¿¡….]) ? ' , r ' \ 1 ' , expecta )
respuesta = re . sub ( r ' \ . \ . \ . ' , ' … ' , respuesta )
expecta = re . sub ( r ' \ . \ . \ . ' , ' … ' , expecta )
if respuesta == expecta : return 0
respuesta = re . sub ( ' [!?¿¡…. ] ' , ' ' , respuesta )
expecta = re . sub ( ' [!?¿¡…. ] ' , ' ' , expecta )
if respuesta == expecta : return 1
respuesta = respuesta . encode ( ' ASCII ' , ' ignore ' ) . decode ( ' ASCII ' )
expecta = expecta . encode ( ' ASCII ' , ' ignore ' ) . decode ( ' ASCII ' )
if respuesta == expecta : return 1
if respuesta == expecta : return 2
respuesta = respuesta . casefold ( )
expecta = expecta . casefold ( )
if respuesta == expecta : return 2
respuesta = re . sub ( ' \ W ' , ' ' , respuesta )
expecta = re . sub ( ' \ W ' , ' ' , expecta )
if respuesta == expecta : return 3
return 4
assert vergleiche ( " e " , " e " ) == 0
assert vergleiche ( " é " , " e " ) == 1
assert vergleiche ( " Bien " , " bien " ) == 2
assert vergleiche ( " é " , " e " ) == 2
assert vergleiche ( " Bien " , " bien " ) == 3
assert vergleiche ( " quétal " , " Qué tal " ) == 3
assert vergleiche ( " Buenas Noches " , " ¡Buenas noches! " ) == 3
assert vergleiche ( " Buenas noches " , " ¡Buenas noches! " ) == 1
assert vergleiche ( " ser " , " ser (irr.) " ) == 0
assert vergleiche ( " hacer algo " , " hacer (irr.) algo " ) == 0
assert vergleiche ( " padres " , " padres (pl.) " ) == 0
assert vergleiche ( " ¿De dónde …? " , " ¿De dónde… ? " ) == 0
assert vergleiche ( " el nombre " , " el apellido " ) == 4
assert vergleiche ( " Tengo … a~nos. " , " Tengo... años. " ) == 0
assert vergleiche ( " ¿Cuántos a~nos tienes? " , " ¿Cuántos años tienes? " ) == 0
class Resultado :
CORRECTO = 0
BIEN = 1
MAL = 2
ADIOS = 3
NO_BIEN = 2
MAL = 3
ADIOS = 4
def einzelne_abfrage ( palabra , status ) :
status_text = f " ({status}) " if status > 0 else f " {bcolors.OKGREEN}neu{bcolors.ENDC} "
if status == None :
status_text = f " {bcolors.OKCYAN}neu{bcolors.ENDC} "
status = 0
else :
status_text = f " ({status}) "
try :
respuesta = input ( f " {status_text} {bcolors.BOLD}{palabra[ ' de ' ]}{bcolors.ENDC} {bcolors.OKCYAN} " )
except EOFError :
@ -107,28 +128,89 @@ def einzelne_abfrage(palabra, status):
print ( bcolors . ENDC , end = " " )
print ( ' \033 [{}C \033 [1A ' . format ( 4 + len ( palabra [ ' de ' ] ) + 1 + len ( respuesta ) ) , end = " " )
resultado = vergleiche ( respuesta , palabra [ ' es ' ] )
match status :
case 0 : bien = resultado < 4
case 1 : bien = resultado < 3
case 2 : bien = resultado < 3
case 3 : bien = resultado < 2
case 4 : bien = resultado < 1
if resultado == 0 :
bien = Resultado . CORRECTO
else :
match status :
case 0 : bien = Resultado . BIEN if resultado < 4 else Resultado . NO_BIEN
case 1 : bien = Resultado . BIEN if resultado < 3 else ( Resultado . NO_BIEN if resultado < 4 else Resultado . MAL )
case 2 : bien = Resultado . BIEN if resultado < 2 else ( Resultado . NO_BIEN if resultado < 3 else Resultado . MAL )
case 3 : bien = Resultado . BIEN if resultado < 2 else Resultado . MAL
case 4 : bien = Resultado . BIEN if resultado < 1 else Resultado . MAL
print ( f " {bcolors.LINK_START}file://{AUDIO_BASE}{palabra[ ' audio ' ]}.aac{bcolors.LINK_MIDDLE} " , end = " " )
if bien and resultado == 0 :
if bien == Resultado . CORRECTO :
print ( f " {bcolors.OKGREEN}✓{bcolors.ENDC} " , end = " " )
elif bien :
elif bien == Resultado . BIEN :
print ( f " {bcolors.WARNING}{palabra[ ' es ' ]}{bcolors.ENDC} " , end = " " )
else :
print ( f " {bcolors.FAIL}{palabra[ ' es ' ]}{bcolors.ENDC} " , end = " " )
print ( bcolors . LINK_END , end = " " )
try :
input ( " " )
if input ( " " ) == " + " :
bien = Resultado . CORRECTO
except EOFError :
print ( )
return Resultado . ADIOS
return Resultado . BIEN if bien else Resultado . MAL
return bien
class Sesion :
def __init__ ( self , palabras , status ) :
self . palabras = palabras
self . status = status
self . bien = 0
self . mal = 0
def empezar ( self , quiero_unidad ) :
unidad = False
unidad_no = - 1
paso = False
cur_palabras = False
for palabra in self . palabras :
if paso != palabra [ ' paso ' ] :
if cur_palabras != False and ( quiero_unidad == None or quiero_unidad == unidad_no ) :
c = [ len ( cur_palabras [ x ] ) for x in cur_palabras ]
print ( f " {bcolors.BOLD}{unidad}{bcolors.ENDC}: {paso} ({c[0] + c[6]}/{c[1]}/{c[2]}/{c[3]}/{c[4]}/{bcolors.OKGREEN}{c[5]}{bcolors.ENDC}) " )
for n in range ( 5 ) : # 1..4, no 5
if self . hace_palabras ( cur_palabras [ n ] , n ) == Resultado . ADIOS :
return
n = None
if self . hace_palabras ( cur_palabras [ n ] , n ) == Resultado . ADIOS :
return
cur_palabras = { 0 : [ ] , 1 : [ ] , 2 : [ ] , 3 : [ ] , 4 : [ ] , 5 : [ ] , None : [ ] }
if unidad != palabra [ ' unidad ' ] :
unidad_no + = 1
unidad = palabra [ ' unidad ' ]
paso = palabra [ ' paso ' ]
cur_palabras [ self . status . get ( palabra [ ' id ' ] ) ] . append ( palabra )
def hace_palabras ( self , palabras , status ) :
random . shuffle ( palabras )
for palabra in palabras :
match einzelne_abfrage ( palabra , status ) :
case Resultado . CORRECTO :
self . status [ palabra [ ' id ' ] ] = ( status or 0 ) + ( 2 if ( status or 0 ) < 2 else 1 )
self . bien + = 1
case Resultado . BIEN :
self . status [ palabra [ ' id ' ] ] = ( status or 0 ) + 1
self . bien + = 1
case Resultado . NO_BIEN :
continue
case Resultado . MAL :
self . status [ palabra [ ' id ' ] ] = status - 1
self . mal + = 1
case Resultado . ADIOS :
return Resultado . ADIOS
with open ( STATUS_FILE + ' .new ' , ' w ' ) as f :
json . dump ( self . status , f )
f . flush ( )
os . fsync ( f . fileno ( ) )
with open ( STATUS_FILE + ' .new ' , ' r ' ) as f :
pass
os . replace ( STATUS_FILE + ' .new ' , STATUS_FILE )
def abfrage ( parser ) :
def abfrage ( parser , quiero_unidad ) :
random . seed ( )
try :
with open ( VOKABELN_FILE , ' r ' ) as f :
@ -141,53 +223,16 @@ def abfrage(parser):
parser . print_help ( )
return
unidad = False
paso = False
cur_palabras = False
bien = 0
mal = 0
for palabra in palabras :
if paso != palabra [ ' paso ' ] :
if cur_palabras != False :
c = [ len ( cur_palabras [ x ] ) for x in cur_palabras ]
print ( f " {bcolors.BOLD}{unidad}{bcolors.ENDC}: {paso} ( " , end = " " )
print ( * c , sep = " / " , end = " ) " )
print ( )
for n in range ( 5 ) : # 1..4, no 5
random . shuffle ( cur_palabras [ n ] )
for palabra in cur_palabras [ n ] :
s = status . get ( palabra [ ' id ' ] , 0 )
match einzelne_abfrage ( palabra , s ) :
case Resultado . BIEN :
status [ palabra [ ' id ' ] ] = s + 1
bien + = 1
case Resultado . MAL :
if s > 0 :
status [ palabra [ ' id ' ] ] = s - 1
mal + = 1
continue
case Resultado . ADIOS :
print ( f ' {bcolors.OKGREEN}+{bien}{bcolors.ENDC} / {bcolors.FAIL}-{mal}{bcolors.ENDC} ' )
return
with open ( STATUS_FILE + ' .new ' , ' w ' ) as f :
json . dump ( status , f )
f . flush ( )
os . fsync ( f . fileno ( ) )
with open ( STATUS_FILE + ' .new ' , ' r ' ) as f :
status = json . load ( f )
os . replace ( STATUS_FILE + ' .new ' , STATUS_FILE )
cur_palabras = { 0 : [ ] , 1 : [ ] , 2 : [ ] , 3 : [ ] , 4 : [ ] , 5 : [ ] }
unidad = palabra [ ' unidad ' ]
paso = palabra [ ' paso ' ]
cur_palabras [ status . get ( palabra [ ' id ' ] , 0 ) ] . append ( palabra )
sesion = Sesion ( palabras , status )
sesion . empezar ( quiero_unidad )
print ( f ' {bcolors.OKGREEN}+{sesion.bien}{bcolors.ENDC} / {bcolors.FAIL}-{sesion.mal}{bcolors.ENDC} ' )
parser = argparse . ArgumentParser ( )
default_data_file = os . environ [ ' PWD ' ] + ' /assets/amf/vokabelTrainer147.amf '
parser . add_argument ( ' --import-data ' , type = str , help = " Path to assets " , metavar = " DIR " )
default_status_file = os . environ [ ' HOME ' ] + ' /klett/1266/vokabeltrainerData147 '
parser . add_argument ( ' --import-status ' , type = str , help = " Path to AMF File, defaults to " + default_status_file , metavar = " FILE " , nargs = ' ? ' , const = default_status_file )
parser . add_argument ( ' --unidad ' , type = int )
args = parser . parse_args ( )
if args . import_data :
@ -196,4 +241,4 @@ if args.import_data:
elif args . import_status :
import_status ( args . import_status )
else :
abfrage ( parser )
abfrage ( parser , args . unidad )