igor@46: #!/usr/bin/python igor@46: igor@46: import random igor@46: import sys igor@52: import time igor@46: igor@46: # TODO: igor@46: # * persistent weight dict igor@46: # * log igor@46: # * stats (top5, time_total, time_last, correct_answers_rate_total, correct_answers_rate_last) igor@46: igor@46: # DONE: igor@46: # * correct quit (ctrl d) igor@46: igor@52: logfile = "/home/igor/Langs/Deutsch/training-scripts/geschlecht/zubrator.log" igor@52: igor@52: class _Getch: igor@52: """Gets a single character from standard input. Does not echo to the igor@52: screen.""" igor@52: def __init__(self): igor@52: try: igor@52: self.impl = _GetchWindows() igor@52: except ImportError: igor@52: self.impl = _GetchUnix() igor@52: igor@52: def __call__(self): return self.impl() igor@52: igor@52: igor@52: class _GetchUnix: igor@52: def __init__(self): igor@52: import tty, sys igor@52: igor@52: def __call__(self): igor@52: import sys, tty, termios igor@52: fd = sys.stdin.fileno() igor@52: old_settings = termios.tcgetattr(fd) igor@52: try: igor@52: tty.setraw(sys.stdin.fileno()) igor@52: ch = sys.stdin.read(1) igor@52: finally: igor@52: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) igor@52: return ch igor@52: igor@52: igor@52: class _GetchWindows: igor@52: def __init__(self): igor@52: import msvcrt igor@52: igor@52: def __call__(self): igor@52: import msvcrt igor@52: return msvcrt.getch() igor@52: igor@52: igor@52: getch = _Getch() igor@52: igor@52: def log_answer(result, question, correct_answer, given_answer): igor@52: with open(logfile, "a") as f: igor@52: timestamp = time.strftime("%Y-%m-%d %H:%M") igor@52: f.write(" ".join([timestamp, result, question, correct_answer, given_answer])+"\n") igor@52: igor@52: igor@46: def color_for_answer(answer): igor@46: color_table = { igor@46: 'der': 'Blue', igor@46: 'das': 'Green', igor@46: 'die': 'Red', igor@46: } igor@46: if not answer in color_table: igor@46: return 'Normal' igor@46: else: igor@46: return color_table[answer] igor@46: igor@46: def colorprint(string, color=None): igor@46: color_table = { igor@46: 'Gray': '\033[1;30m', igor@46: 'Red': '\033[1;31m', igor@46: 'Green': '\033[1;32m', igor@46: 'Yellow': '\033[1;33m', igor@46: 'Blue': '\033[1;34m', igor@46: 'Magenta': '\033[1;35m', igor@46: 'Cyan': '\033[1;36m', igor@46: 'White': '\033[1;37m', igor@46: 'Crimson': '\033[1;38m', igor@46: 'Highlighted_Red': '\033[1;41m', igor@46: 'Highlighted_Green': '\033[1;42m', igor@46: 'Highlighted_Brown': '\033[1;43m', igor@46: 'Highlighted_Blue': '\033[1;44m', igor@46: 'Highlighted_Magenta': '\033[1;45m', igor@46: 'Highlighted_Cyan': '\033[1;46m', igor@46: 'Highlighted_Gray': '\033[1;47m', igor@46: 'Highlighted_Crimson': '\033[1;48m', igor@46: } igor@46: normal_color_code = '\033[1;m' igor@46: if not color or color == 'Normal' or not color in color_table: igor@46: print string igor@46: else: igor@46: print "%s%s%s" % (color_table[color], string, normal_color_code) igor@46: igor@46: def wrandom(dict): igor@46: total = sum(dict.values()) igor@46: n = random.uniform(0, total) igor@46: igor@46: for key in sorted(dict.keys()): igor@46: item = key igor@46: if n < dict[key]: igor@46: break igor@46: n -= dict[key] igor@46: igor@46: return item igor@46: igor@46: def set_weight(weight, word, new_weight): igor@46: if len(weight) <= 1: igor@46: raise Exception("Can't set weight; weight dictionary is too small; need at least two members") igor@46: sum_before = sum(weight.values()) igor@46: w_before = weight[word] igor@46: w_after = new_weight igor@46: delta = (w_after - w_before)*1.0/(len(weight)-1) igor@46: for k in weight.keys(): igor@46: if k == word: igor@46: weight[k] = w_after igor@46: else: igor@46: weight[k] -= delta igor@46: sum_after = sum(weight.values()) igor@46: if abs(sum_before-sum_after)> 0.0001: igor@46: raise Exception("%s != %s ; function set_weight works incorrectly" % (sum_before, sum_after)) igor@46: return weight igor@46: igor@46: def print_stats(stats, weight, correct_answer): igor@46: print "------------------------" igor@46: print "total questions = %s" % stats['total_questions'] igor@46: print "last questions = %s" % stats['last_questions'] igor@46: print "total errors = %s (%.2f)" % (stats['total_errors'], 1.0*stats['total_errors']/stats['total_questions']) igor@46: print "last errors = %s (%.2f)" % (stats['last_errors'], 1.0*stats['last_errors']/stats['last_questions']) igor@46: print "top 5 questions:" igor@46: for question in sorted(weight.keys(),key=lambda x: weight[x], reverse=True)[:5]: igor@46: colorprint( igor@46: " %s %s %5.2f" % (correct_answer[question], question, weight[question]), igor@46: color_for_answer(correct_answer[question]) igor@46: ) igor@46: igor@46: print "------------------------" igor@46: igor@46: filename = sys.argv[1] igor@46: correct_answer = {} igor@46: with open(filename) as f: igor@46: for line in f.readlines(): igor@46: line = line.rstrip('\n') igor@46: try: igor@46: (q, a) = line.split(' ', 1) igor@46: correct_answer[q] = a igor@46: except: igor@46: pass igor@46: igor@46: saved_weight = { igor@46: 'Auskunft' : 2, igor@46: } igor@46: igor@46: weight = {} igor@46: for word in correct_answer.keys(): igor@46: if word in saved_weight: igor@46: weight[word] = saved_weight[word] igor@46: else: igor@46: weight[word] = 1 igor@46: igor@46: stats = { igor@46: 'total_errors' :0, igor@46: 'last_errors' :0, igor@46: 'total_questions' :0, igor@46: 'last_questions' :0, igor@46: } igor@46: igor@46: while 1: igor@46: question = wrandom(weight) igor@46: colorprint(question, 'Yellow') igor@52: #answer = sys.stdin.readline().rstrip('\n') igor@52: ch = getch() igor@52: codes = { igor@52: 'q': 'der', igor@52: 'w': 'das', igor@52: 'e': 'die', igor@52: igor@52: 'p': 'der', igor@52: '[': 'das', igor@52: ']': 'die' igor@52: } igor@52: if ch in codes: igor@52: answer = codes[ch] igor@52: else: igor@52: answer = '' igor@52: igor@46: if not answer: igor@46: break igor@52: igor@52: result = "OK" igor@46: if answer != correct_answer[question]: igor@52: result = "FAIL" igor@46: colorprint( igor@46: "%s %s" % (correct_answer[question], question), igor@46: color_for_answer(correct_answer[question]) igor@46: ) igor@46: weight = set_weight(weight, question, weight[question]*1.5) igor@46: stats['total_errors'] += 1 igor@46: stats['last_errors'] += 1 igor@46: else: igor@46: weight = set_weight(weight, question, weight[question]*0.8) igor@46: igor@52: log_answer(result, question, correct_answer[question], answer) igor@52: igor@46: stats['total_questions'] += 1 igor@46: stats['last_questions'] += 1 igor@46: igor@46: if stats['last_questions'] == 20: igor@46: print_stats(stats, weight, correct_answer) igor@46: stats['last_questions'] = 0 igor@46: stats['last_errors'] = 0 igor@46: igor@46: print igor@46: