new-words

annotate misc/zubrator.py @ 52:abd4080ee583

logging (fixme: hardcoded log filename) + answers shorthand (you press key instead of fullanswer)
author Igor Chubin <igor@chub.in>
date Sun May 01 20:27:36 2011 +0200 (2011-05-01)
parents bf0aa8e3c1ce
children
rev   line source
igor@46 1 #!/usr/bin/python
igor@46 2
igor@46 3 import random
igor@46 4 import sys
igor@52 5 import time
igor@46 6
igor@46 7 # TODO:
igor@46 8 # * persistent weight dict
igor@46 9 # * log
igor@46 10 # * stats (top5, time_total, time_last, correct_answers_rate_total, correct_answers_rate_last)
igor@46 11
igor@46 12 # DONE:
igor@46 13 # * correct quit (ctrl d)
igor@46 14
igor@52 15 logfile = "/home/igor/Langs/Deutsch/training-scripts/geschlecht/zubrator.log"
igor@52 16
igor@52 17 class _Getch:
igor@52 18 """Gets a single character from standard input. Does not echo to the
igor@52 19 screen."""
igor@52 20 def __init__(self):
igor@52 21 try:
igor@52 22 self.impl = _GetchWindows()
igor@52 23 except ImportError:
igor@52 24 self.impl = _GetchUnix()
igor@52 25
igor@52 26 def __call__(self): return self.impl()
igor@52 27
igor@52 28
igor@52 29 class _GetchUnix:
igor@52 30 def __init__(self):
igor@52 31 import tty, sys
igor@52 32
igor@52 33 def __call__(self):
igor@52 34 import sys, tty, termios
igor@52 35 fd = sys.stdin.fileno()
igor@52 36 old_settings = termios.tcgetattr(fd)
igor@52 37 try:
igor@52 38 tty.setraw(sys.stdin.fileno())
igor@52 39 ch = sys.stdin.read(1)
igor@52 40 finally:
igor@52 41 termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
igor@52 42 return ch
igor@52 43
igor@52 44
igor@52 45 class _GetchWindows:
igor@52 46 def __init__(self):
igor@52 47 import msvcrt
igor@52 48
igor@52 49 def __call__(self):
igor@52 50 import msvcrt
igor@52 51 return msvcrt.getch()
igor@52 52
igor@52 53
igor@52 54 getch = _Getch()
igor@52 55
igor@52 56 def log_answer(result, question, correct_answer, given_answer):
igor@52 57 with open(logfile, "a") as f:
igor@52 58 timestamp = time.strftime("%Y-%m-%d %H:%M")
igor@52 59 f.write(" ".join([timestamp, result, question, correct_answer, given_answer])+"\n")
igor@52 60
igor@52 61
igor@46 62 def color_for_answer(answer):
igor@46 63 color_table = {
igor@46 64 'der': 'Blue',
igor@46 65 'das': 'Green',
igor@46 66 'die': 'Red',
igor@46 67 }
igor@46 68 if not answer in color_table:
igor@46 69 return 'Normal'
igor@46 70 else:
igor@46 71 return color_table[answer]
igor@46 72
igor@46 73 def colorprint(string, color=None):
igor@46 74 color_table = {
igor@46 75 'Gray': '\033[1;30m',
igor@46 76 'Red': '\033[1;31m',
igor@46 77 'Green': '\033[1;32m',
igor@46 78 'Yellow': '\033[1;33m',
igor@46 79 'Blue': '\033[1;34m',
igor@46 80 'Magenta': '\033[1;35m',
igor@46 81 'Cyan': '\033[1;36m',
igor@46 82 'White': '\033[1;37m',
igor@46 83 'Crimson': '\033[1;38m',
igor@46 84 'Highlighted_Red': '\033[1;41m',
igor@46 85 'Highlighted_Green': '\033[1;42m',
igor@46 86 'Highlighted_Brown': '\033[1;43m',
igor@46 87 'Highlighted_Blue': '\033[1;44m',
igor@46 88 'Highlighted_Magenta': '\033[1;45m',
igor@46 89 'Highlighted_Cyan': '\033[1;46m',
igor@46 90 'Highlighted_Gray': '\033[1;47m',
igor@46 91 'Highlighted_Crimson': '\033[1;48m',
igor@46 92 }
igor@46 93 normal_color_code = '\033[1;m'
igor@46 94 if not color or color == 'Normal' or not color in color_table:
igor@46 95 print string
igor@46 96 else:
igor@46 97 print "%s%s%s" % (color_table[color], string, normal_color_code)
igor@46 98
igor@46 99 def wrandom(dict):
igor@46 100 total = sum(dict.values())
igor@46 101 n = random.uniform(0, total)
igor@46 102
igor@46 103 for key in sorted(dict.keys()):
igor@46 104 item = key
igor@46 105 if n < dict[key]:
igor@46 106 break
igor@46 107 n -= dict[key]
igor@46 108
igor@46 109 return item
igor@46 110
igor@46 111 def set_weight(weight, word, new_weight):
igor@46 112 if len(weight) <= 1:
igor@46 113 raise Exception("Can't set weight; weight dictionary is too small; need at least two members")
igor@46 114 sum_before = sum(weight.values())
igor@46 115 w_before = weight[word]
igor@46 116 w_after = new_weight
igor@46 117 delta = (w_after - w_before)*1.0/(len(weight)-1)
igor@46 118 for k in weight.keys():
igor@46 119 if k == word:
igor@46 120 weight[k] = w_after
igor@46 121 else:
igor@46 122 weight[k] -= delta
igor@46 123 sum_after = sum(weight.values())
igor@46 124 if abs(sum_before-sum_after)> 0.0001:
igor@46 125 raise Exception("%s != %s ; function set_weight works incorrectly" % (sum_before, sum_after))
igor@46 126 return weight
igor@46 127
igor@46 128 def print_stats(stats, weight, correct_answer):
igor@46 129 print "------------------------"
igor@46 130 print "total questions = %s" % stats['total_questions']
igor@46 131 print "last questions = %s" % stats['last_questions']
igor@46 132 print "total errors = %s (%.2f)" % (stats['total_errors'], 1.0*stats['total_errors']/stats['total_questions'])
igor@46 133 print "last errors = %s (%.2f)" % (stats['last_errors'], 1.0*stats['last_errors']/stats['last_questions'])
igor@46 134 print "top 5 questions:"
igor@46 135 for question in sorted(weight.keys(),key=lambda x: weight[x], reverse=True)[:5]:
igor@46 136 colorprint(
igor@46 137 " %s %s %5.2f" % (correct_answer[question], question, weight[question]),
igor@46 138 color_for_answer(correct_answer[question])
igor@46 139 )
igor@46 140
igor@46 141 print "------------------------"
igor@46 142
igor@46 143 filename = sys.argv[1]
igor@46 144 correct_answer = {}
igor@46 145 with open(filename) as f:
igor@46 146 for line in f.readlines():
igor@46 147 line = line.rstrip('\n')
igor@46 148 try:
igor@46 149 (q, a) = line.split(' ', 1)
igor@46 150 correct_answer[q] = a
igor@46 151 except:
igor@46 152 pass
igor@46 153
igor@46 154 saved_weight = {
igor@46 155 'Auskunft' : 2,
igor@46 156 }
igor@46 157
igor@46 158 weight = {}
igor@46 159 for word in correct_answer.keys():
igor@46 160 if word in saved_weight:
igor@46 161 weight[word] = saved_weight[word]
igor@46 162 else:
igor@46 163 weight[word] = 1
igor@46 164
igor@46 165 stats = {
igor@46 166 'total_errors' :0,
igor@46 167 'last_errors' :0,
igor@46 168 'total_questions' :0,
igor@46 169 'last_questions' :0,
igor@46 170 }
igor@46 171
igor@46 172 while 1:
igor@46 173 question = wrandom(weight)
igor@46 174 colorprint(question, 'Yellow')
igor@52 175 #answer = sys.stdin.readline().rstrip('\n')
igor@52 176 ch = getch()
igor@52 177 codes = {
igor@52 178 'q': 'der',
igor@52 179 'w': 'das',
igor@52 180 'e': 'die',
igor@52 181
igor@52 182 'p': 'der',
igor@52 183 '[': 'das',
igor@52 184 ']': 'die'
igor@52 185 }
igor@52 186 if ch in codes:
igor@52 187 answer = codes[ch]
igor@52 188 else:
igor@52 189 answer = ''
igor@52 190
igor@46 191 if not answer:
igor@46 192 break
igor@52 193
igor@52 194 result = "OK"
igor@46 195 if answer != correct_answer[question]:
igor@52 196 result = "FAIL"
igor@46 197 colorprint(
igor@46 198 "%s %s" % (correct_answer[question], question),
igor@46 199 color_for_answer(correct_answer[question])
igor@46 200 )
igor@46 201 weight = set_weight(weight, question, weight[question]*1.5)
igor@46 202 stats['total_errors'] += 1
igor@46 203 stats['last_errors'] += 1
igor@46 204 else:
igor@46 205 weight = set_weight(weight, question, weight[question]*0.8)
igor@46 206
igor@52 207 log_answer(result, question, correct_answer[question], answer)
igor@52 208
igor@46 209 stats['total_questions'] += 1
igor@46 210 stats['last_questions'] += 1
igor@46 211
igor@46 212 if stats['last_questions'] == 20:
igor@46 213 print_stats(stats, weight, correct_answer)
igor@46 214 stats['last_questions'] = 0
igor@46 215 stats['last_errors'] = 0
igor@46 216
igor@46 217 print
igor@46 218