Migrated to python 3
[voctrainer.git] / voctrainer.py
1 #!/usr/bin/python3
2 # -*- coding: utf-8 -*-
3 # Copyright (c) 2015, 2016 Gabriel Pérez-Cerezo
4
5 import os
6 #print("Hello World")
7 import cgi
8 import cgitb
9 from difflib import SequenceMatcher as match
10 cgitb.enable()
11 from glob import glob
12 from gettext import gettext as _
13
14
15 WORDPOINTS=2
16 #print "200 Ok"
17 PRONOUNS="pronouns.conf"
18 GENDERS="genders.conf"
19 themata = glob("*.voc")
20 conj = glob("*.conj")
21
22 def parse_conjfile (f) :
23 ret = {}
24 for line in f :
25 try :
26 if line.startswith("#") :
27 continue
28 s = line.split(":")
29 ret[s[0]]=s[1]
30 except :
31 continue # invalid line
32 return ret
33 def conj_name (f):
34 return f.replace(".conj","")
35 def import_conf(f):
36 dt = open(f,"r")
37 return parse_conjfile(dt)
38
39 def build_solutions (vocfile):
40 dt = {}
41 try :
42 data = open(vocfile, "r")
43 except IOError :
44 print(_("%s does not exist") % vocfile)
45 cleanup()
46 if vocfile.endswith(".voc") :
47 for line in data :
48 ln = line.split(";")
49 dt[ln[0].strip()]=(ln[1].strip(),ln[2].strip())
50 elif vocfile.endswith(".conj"):
51 dt = parse_conjfile(data)
52 return dt
53
54 def thead(*c) :
55 r = "<thead><tr>"
56 for i in c:
57 r = r + "<th>%s</th>" % i
58 return r + "</thead>"
59 def td (s) :
60 return "<td>%s</td>" %s
61 def field(nm):
62 return "<input name=\"" + nm +'">'
63 def conj_form (name, conj) :
64 print('<form action="send%s" name="test" ><table>' % name)
65 print(thead(_("Pronomen"), _("Verbform")))
66 print("<tbody>")
67 pronouns = import_conf(PRONOUNS)
68 for i in sorted(conj) :
69 print("<tr>")
70 print(td(pronouns[i]))
71 print(td(field(i)))
72 print("</tbody></table>")
73 print('<input type="submit" value="'+_("Absenden")+'!">')
74 print('</form>')
75 def results_sentence(reached, reachable):
76 return _("Du hast {0:.1f} von {1:d} Punkten erreicht.\
77 Das Entspricht {2:d} %.").format(reached, reachable, int(reached*100/reachable))
78
79 def score_word(x,y) :
80 sim = match(None, x.strip(), y.strip()).ratio() * (WORDPOINTS -0.5)
81 if sim > 0.9*(WORDPOINTS-0.5):
82 sim = 2
83 elif sim < 0.5 * (WORDPOINTS-0.5) :
84 sim = 0
85 return sim
86
87 def check (sol, user) :
88 genders = import_conf(GENDERS)
89 if not user :
90 print('<b class="error" >' + _('Keine Daten eingesendet!') + '</b><br>')
91 return 0
92 print("<table>")
93 print(thead(_("Deutsch"), _("Artikel"), _("Punkte"), _("Wort"), _("Lösung"), _("Punkte")))
94 print("<tbody>")
95 reachable = 0
96 reached = 0
97 for i in sort_sol(sol) :
98 print("<tr>" + td(i))
99 if not i in user :
100 user[i] = ("","")
101 if sol[i][0] and sol[i][0] in list(genders.keys()):
102 reachable +=1
103 print(td(genders[sol[i][0]]))
104 if sol[i][0]==user[i][0]:
105 print(td("1"))
106 reached +=1
107 else :
108 print(td("0"))
109 else :
110 print("<td>-<td>-")
111 print(td(user[i][1]), td(sol[i][1]))
112 reachable +=WORDPOINTS
113 sim = score_word( sol[i][1], user[i][1])
114 reached += sim
115 print(td("%.1f" % sim))
116 print("</tr>")
117 print("</tbody></table>")
118 print(results_sentence(reached, reachable))
119
120 def check_conj (sol,user):
121 pronouns = import_conf(PRONOUNS)
122 reachable = 0
123 reached = 0
124 print("<table>")
125 print(thead(_("Pronomen"), _("Verbform"), _("Lösung"), _("Punkte")))
126 print("<tbody>")
127 for i in sorted(sol) :
128 print("<tr>")
129 print(td(pronouns[i]))
130 if not i in user :
131 user[i] = ("","")
132 print(td(user[i][1]))
133 print(td(sol[i]))
134 reachable +=WORDPOINTS
135 sim = score_word( sol[i], user[i][1])
136 reached += sim
137 print(td("%.1f" %sim))
138 print("</tr>")
139 print("</tbody></table>")
140 print(results_sentence(reached, reachable))
141
142
143
144 def sort_sol (sol):
145 return sorted(sol, cmp=lambda x,y: cmp(x.lower(), y.lower()))
146 def list_subjects (prefix="") :
147 print("<h2>" + _("Bitte wähle ein Thema aus:") + "</h2>")
148 if themata:
149 print('<div class="ls" ><h3>' + _("Vokabeln") + '</h3>')
150 print('<ul class="voc" >')
151 for thema in themata:
152 print("<li><a href=\"%s%s\" >%s</a>" % (prefix,thema, thema.replace(".voc","")))
153 print("</ul></div>")
154 if conj:
155 print('<div class="ls" ><h3>' + _('Konjugationen') +' </h3>')
156 print('<ul class="voc" >')
157 for verb in conj :
158 print("<li><a href=\"%s%s\">%s</a>" % (prefix,verb, conj_name(verb)))
159 print("</ul></div>")
160
161 def footer ():
162 print(_("""<footer>Vokabeltrainer Copyright &copy; 2015, 2016 Gabriel
163 Pérez-Cerezo<br>Freie Software, lizensiert unter der
164 MIT-Lizenz <a href="http://git.gpcf.eu/voctrainer.git">Quellcode herunterladen</a><br>
165 Der Vokabeltrainer ist noch lange nicht fertig: siehe <a href="/TODO.txt">unsere Liste</a>
166 an Sachen, die wir gerne hätten.<br>
167 Fehlermeldungen bitte an gabriel -arroba- gpcf -punto- eu</footer></body></html>"""))
168
169
170 def cleanup () :
171 # Call this when finished
172 footer()
173 exit()
174 def header (title="", navbar="") :
175 if title :
176 title = "– " + title
177 print(''' <!DOCTYPE html>
178 <head><title>Vokabeltrainer %s</title>
179 <META HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8" />
180 <meta name="google" content="notranslate" />
181 <link rel="icon" type="image/png" href="/favicon.png" />
182 <link rel="stylesheet" type="text/css" href="/voctrainer.css" />
183 </head>
184 <body>
185 <div id="header">
186 <a href="/voctrainer.py/" ><img style="float:left; width:4em;" src="/logo.png" alt="Vokabeltrainer logo"></a><h1 id="title">Vokabeltrainer</h1>
187 %s
188 <a class="nav" href="/voctrainer.py/">%s</a>
189 <a class="nav" href="/voctrainer.py/export">%s</a>
190 </div>
191 ''' % (title, navbar, _("Hauptmenü"), _("Lösungen Einsehen")))
192
193 print ("Content-Type: text/html; charset=UTF-8\n")
194 try:
195 url=os.environ["PATH_INFO"]
196 except:
197 url="/"
198
199
200 if url == "" or url == "/" :
201 header()
202 list_subjects()
203 elif url[1:] in conj :
204 name = conj_name(url[1:])
205 header(name)
206 print("<h2>%s</h2>" %name)
207 conj_form(url[1:], build_solutions(url[1:]))
208 elif url[1:] in themata :
209 header(url[1:])
210 genders = import_conf(GENDERS)
211 print("<h2>%s</h2>" % (url[1:].replace(".voc","")))
212 print("<br>")
213 print('<form action="send%s" name="test" ><table>' % url[1:])
214 sol = build_solutions(url[1:])
215 print(thead(_("Deutsch"), _("Artikel"), _("Übersetzung")))
216 print('<tbody>')
217 for i in sort_sol(sol) :
218 print("<tr><td>%s</td><td>" % i)
219 if sol[i][0] and sol[i][0] in list(genders.keys()) : # word has gender
220 for j in list(genders.keys()) :
221 print('<input type="radio" name="%s_g" value="%s">' %(i,j) + genders[j])
222 else :
223 print("—")
224 print('<td><input name="%s">' % i)
225 print("</tr>")
226 print('</tbody></table><input type="submit" value="' + _("Absenden!") + '"></form>')
227 elif url[1:].startswith("send") :
228 # print "you sent it"
229 form = cgi.FieldStorage()
230 f=url[5:]
231 header(_("Auswertung zu %s") % f, '<a class="nav" href="%s">Zurück zum Test</a>' % f)
232 print("<h2>" + _("Auswertung") + "</h2>")
233 dt = build_solutions(f)
234 ut = {} # User solutions
235 for i in form :
236 if i.endswith("_g") :
237 # Gender
238 j = i[:-2]
239 if j in dt :
240 if not j in ut :
241 ut[j]=[form.getfirst(i,"0"),""]
242 else :
243 ut[j][0] = form.getfirst(i,"0")
244 elif i in list(dt.keys()) :
245 ans = form.getfirst(i, "0").strip()
246 if not i in ut :
247 ut[i] = ["", ans]
248 else :
249 ut[i].append(ans)
250 if f.endswith(".voc"):
251 check(dt, ut)
252 elif f.endswith(".conj"):
253 check_conj(dt, ut)
254 elif url[1:].startswith("export") :
255 f=url[7:]
256 header("Export"+f)
257 if f=="" :
258 list_subjects("export")
259 cleanup()
260 else :
261 sol = build_solutions(f)
262 print("<table>")
263 if f.endswith(".conj"):
264 pronouns = import_conf(PRONOUNS)
265 print(thead(_("Pronomen"),_("Verbform")))
266 print("<tbody>")
267 for i in sorted(sol) :
268 print("<tr>", td(pronouns[i]), td(sol[i]), "</tr>")
269 elif f.endswith(".voc"):
270 genders = import_conf(GENDERS)
271 print(thead(_("Deutsch"), _("Artikel"), _("Übersetzung")))
272 print("<tbody>")
273 for i in sort_sol(sol) :
274 print("<tr>", td(i))
275 if sol[i][0] in list(genders.keys()) :
276 print(td(genders[sol[i][0]]))
277 else:
278 print(td("—"))
279 print(td(sol[i][1]))
280 print("</tr>")
281 print("</tbody></table>")
282 cleanup()
283
284
285