0268a58865d8aa20d15420a5969adb5c417ff8a6
[voctrainer.git] / voctrainer.py
1 #!/usr/bin/python
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 footer()
46 exit()
47 if vocfile.endswith(".voc") :
48 for line in data :
49 ln = line.split(";")
50 dt[ln[0].strip()]=(ln[1].strip(),ln[2].strip())
51 elif vocfile.endswith(".conj"):
52 dt = parse_conjfile(data)
53 return dt
54
55 def thead(*c) :
56 r = "<thead><tr>"
57 for i in c:
58 r = r + "<th>%s</th>" % i
59 return r + "</thead>"
60 def td (s) :
61 return "<td>%s</td>" %s
62 def field(nm):
63 return "<input name=\"" + nm +'">'
64 def conj_form (name, conj) :
65 print '<form action="send%s" name="test" ><table>' % name
66 print thead(_("Pronomen"), _("Verbform"))
67 print "<tbody>"
68 pronouns = import_conf(PRONOUNS)
69 for i in sorted(conj) :
70 print "<tr>"
71 print td(pronouns[i])
72 print td(field(i))
73 print "</tbody></table>"
74 print '<input type="submit" value="'+_("Absenden")+'!">'
75 print '</form>'
76 def results_sentence(reached, reachable):
77 return _("Du hast {0:.1f} von {1:d} Punkten erreicht. Das Entspricht {2:d} %.").format(reached, reachable, reached*100/reachable)
78 def score_word(x,y) :
79 sim = match(None, x.strip(), y.strip()).ratio() * (WORDPOINTS -0.5)
80 if sim > 0.9*(WORDPOINTS-0.5):
81 sim = 2
82 elif sim < 0.5 * (WORDPOINTS-0.5) :
83 sim = 0
84 return sim
85
86 def check (sol, user) :
87 genders = import_conf(GENDERS)
88 if not user :
89 print '<b class="error" >' + _('Keine Daten eingesendet!') + '</b><br>'
90 return 0
91 print "<table>"
92 print thead(_("Deutsch"), _("Artikel"), _("Punkte"), _("Wort"), _("Lösung"), _("Punkte"))
93 print "<tbody>"
94 reachable = 0
95 reached = 0
96 for i in sort_sol(sol) :
97 print "<tr><td>",i
98 if not i in user :
99 user[i] = ("","")
100 if sol[i][0] and sol[i][0] in genders.keys():
101 reachable +=1
102 print td(genders[sol[i][0]])
103 if sol[i][0]==user[i][0]:
104 print td("1")
105 reached +=1
106 else :
107 print td("0")
108 else :
109 print "<td>-<td>-"
110 print "<td>", user[i][1] #Eingabe
111 print "<td>", sol[i][1], "<td>" # Lösung
112 reachable +=WORDPOINTS
113 sim = score_word( sol[i][1], user[i][1])
114 reached += sim
115 print "%.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 def header (title="", navbar="") :
169 if title :
170 title = "– " + title
171 print ''' <!DOCTYPE html>
172 <head><title>Vokabeltrainer %s</title>
173 <META HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8" />
174 <meta name="google" content="notranslate" />
175 <link rel="icon" type="image/png" href="/favicon.png" />
176 <link rel="stylesheet" type="text/css" href="/voctrainer.css" />
177 </head>
178 <body>
179 <div id="header">
180 <a href="/voctrainer.py/" ><img style="float:left; width:4em;" src="/logo.png" alt="Vokabeltrainer logo"></a><h1 id="title">Vokabeltrainer</h1>
181 %s
182 <a class="nav" href="/voctrainer.py/">%s</a>
183 <a class="nav" href="/voctrainer.py/export">%s</a>
184 </div>
185 ''' % (title, navbar, _("Hauptmenü"), _("Lösungen Einsehen"))
186
187 print ("Content-Type: text/html; charset=UTF-8\n")
188 try:
189 url=os.environ["PATH_INFO"]
190 except:
191 url="/"
192
193
194 if url == "" or url == "/" :
195 header()
196 list_subjects()
197 footer()
198 exit()
199 if url[1:] in conj :
200 name = conj_name(url[1:])
201 header(name)
202 print "<h2>%s</h2>" %name
203 conj_form(url[1:], build_solutions(url[1:]))
204 footer()
205 exit()
206
207 if url[1:] in themata :
208 header(url[1:])
209 genders = import_conf(GENDERS)
210 print "<h2>%s</h2>" % (url[1:].replace(".voc",""))
211 print "<br>"
212 print '<form action="send%s" name="test" ><table>' % url[1:]
213 sol = build_solutions(url[1:])
214 print thead(_("Deutsch"), _("Artikel"), _("Übersetzung"))
215 print '<tbody>'
216 for i in sort_sol(sol) :
217 print "<tr><td>%s</td><td>" % i,
218 if sol[i][0] and sol[i][0] in genders.keys() : # word has gender
219 for j in genders.keys() :
220 print '<input type="radio" name="%s_g" value="%s">' %(i,j) + genders[j]
221 else :
222 print "—"
223 print '<td><input name="%s">' % i
224 print "</tr>"
225 print '</tbody></table><input type="submit" value="' + _("Absenden!") + '"></form>'
226 footer()
227 exit()
228 if url[1:].startswith("send") :
229 # print "you sent it"
230 form = cgi.FieldStorage()
231 f=url[5:]
232 header(_("Auswertung zu %s") % f, '<a class="nav" href="%s">Zurück zum Test</a>' % f)
233 print "<h2>" + _("Auswertung") + "</h2>"
234 dt = build_solutions(f)
235 ut = {} # User solutions
236 for i in form :
237 if i.endswith("_g") :
238 # Gender
239 j = i[:-2]
240 if j in dt :
241 if not j in ut :
242 ut[j]=[form.getfirst(i,"0"),""]
243 else :
244 ut[j][0] = form.getfirst(i,"0")
245 elif i in dt.keys() :
246 ans = form.getfirst(i, "0").strip()
247 if not i in ut :
248 ut[i] = ["", ans]
249 else :
250 ut[i].append(ans)
251 if f.endswith(".voc"):
252 check(dt, ut)
253 elif f.endswith(".conj"):
254 check_conj(dt, ut)
255 footer()
256 exit()
257 if url[1:].startswith("export") :
258 f=url[7:]
259 header("Export"+f)
260 if f=="" :
261 list_subjects("export")
262 footer()
263 exit()
264 else :
265 sol = build_solutions(f)
266 print "<table>"
267 if f.endswith(".conj"):
268 pronouns = import_conf(PRONOUNS)
269 print thead(_("Pronomen"),_("Verbform"))
270 print "<tbody>"
271 for i in sorted(sol) :
272 print "<tr>", td(pronouns[i]), td(sol[i]), "</tr>"
273 elif f.endswith(".voc"):
274 genders = import_conf(GENDERS)
275 print thead(_("Deutsch"), _("Artikel"), _("Übersetzung"))
276 print "<tbody>"
277 for i in sort_sol(sol) :
278 print "<tr>", td(i)
279 if sol[i][0] in genders.keys() :
280 print td(genders[sol[i][0]])
281 else:
282 print td("—")
283 print td(sol[i][1])
284 print "</tr>"
285 print "</tbody></table>"
286 footer()
287 exit()
288
289
290
291