Commit 0a96984cde48d2c23d83b0cb8648e3b5391d7123
1 parent
e447d0c2
Exists in
master
and in
1 other branch
database file is now selected as a command line option, defaults to students.db
Showing
5 changed files
with
81 additions
and
47 deletions
Show diff stats
knowledge.py
... | ... | @@ -129,8 +129,10 @@ class StudentKnowledge(object): |
129 | 129 | |
130 | 130 | if grade > 0.999: |
131 | 131 | self.correct_answers += 1 |
132 | - self.next_question() | |
133 | - action = 'new_question' | |
132 | + if self.next_question() is None: | |
133 | + action = 'finished_topic' | |
134 | + else: | |
135 | + action = 'new_question' | |
134 | 136 | |
135 | 137 | else: |
136 | 138 | self.wrong_answers += 1 |
... | ... | @@ -140,13 +142,15 @@ class StudentKnowledge(object): |
140 | 142 | if self.current_question['tries'] <= 0: |
141 | 143 | logger.debug("Appending new instance of this question to the end") |
142 | 144 | self.questions.append(self.factory[q['ref']].generate()) |
143 | - self.next_question() | |
144 | - action = 'new_question' | |
145 | + if self.next_question() is None: | |
146 | + action = 'finished_topic' | |
147 | + else: | |
148 | + action = 'new_question' # FIXME show comments | |
145 | 149 | |
146 | 150 | else: |
147 | - action = 'wrong' | |
151 | + action = 'try_again' | |
148 | 152 | |
149 | - # returns answered and corrected question (not new one) | |
153 | + # returns corrected question (not new one) which might include comments | |
150 | 154 | return q, action |
151 | 155 | |
152 | 156 | ... | ... |
learnapp.py
... | ... | @@ -58,8 +58,8 @@ class LearnApp(object): |
58 | 58 | session.close() |
59 | 59 | |
60 | 60 | # ------------------------------------------------------------------------ |
61 | - def __init__(self, config_files, prefix): | |
62 | - self.db_setup() # setup database and check students | |
61 | + def __init__(self, config_files, prefix, db): | |
62 | + self.db_setup(db) # setup database and check students | |
63 | 63 | self.online = dict() # online students |
64 | 64 | |
65 | 65 | self.deps = nx.DiGraph(prefix=prefix) |
... | ... | @@ -152,7 +152,7 @@ class LearnApp(object): |
152 | 152 | topic_id=topic)) |
153 | 153 | logger.debug(f'Saved "{q["ref"]}" into database') |
154 | 154 | |
155 | - if knowledge.get_current_question() is None: | |
155 | + if action == 'finished_topic': | |
156 | 156 | # finished topic, save into database |
157 | 157 | logger.info(f'User "{uid}" finished "{topic}"') |
158 | 158 | level = knowledge.get_topic_level(topic) |
... | ... | @@ -176,9 +176,8 @@ class LearnApp(object): |
176 | 176 | s.add(a) |
177 | 177 | |
178 | 178 | logger.debug(f'Saved topic "{topic}" into database') |
179 | - action = 'finished_topic' # FIXME | |
180 | 179 | |
181 | - return action | |
180 | + return q, action | |
182 | 181 | |
183 | 182 | |
184 | 183 | # ------------------------------------------------------------------------ |
... | ... | @@ -208,7 +207,7 @@ class LearnApp(object): |
208 | 207 | # ------------------------------------------------------------------------ |
209 | 208 | # setup and check database |
210 | 209 | # ------------------------------------------------------------------------ |
211 | - def db_setup(self, db='students.db'): | |
210 | + def db_setup(self, db): | |
212 | 211 | logger.info(f'Checking database "{db}":') |
213 | 212 | engine = create_engine(f'sqlite:///{db}', echo=False) |
214 | 213 | self.Session = sessionmaker(bind=engine) | ... | ... |
questions.py
serve.py
... | ... | @@ -248,16 +248,17 @@ class QuestionHandler(BaseHandler): |
248 | 248 | answer = answer[0] |
249 | 249 | |
250 | 250 | # check answer in another thread (nonblocking) |
251 | - action = await self.learn.check_answer(user, answer) | |
251 | + # and get corrected question | |
252 | + q, action = await self.learn.check_answer(user, answer) | |
252 | 253 | |
253 | 254 | # get next question (same, new or None) |
254 | 255 | question = self.learn.get_current_question(user) |
255 | 256 | |
256 | - if action == 'wrong': | |
257 | + if action == 'try_again': | |
257 | 258 | comments_html = self.render_string('comments.html', |
258 | 259 | comments=question['comments'], md=md_to_html) |
259 | 260 | self.write({ |
260 | - 'method': action, | |
261 | + 'method': 'try_again', # FIXME js | |
261 | 262 | 'params': { |
262 | 263 | 'progress': self.learn.get_student_progress(user), |
263 | 264 | 'comments': tornado.escape.to_unicode(comments_html), # FIXME |
... | ... | @@ -265,14 +266,20 @@ class QuestionHandler(BaseHandler): |
265 | 266 | } |
266 | 267 | }) |
267 | 268 | |
268 | - elif action == 'finished_topic': # right answer, finished topic | |
269 | - finished_topic_html = self.render_string('finished_topic.html') | |
270 | - self.write({ | |
271 | - 'method': 'finished_topic', | |
272 | - 'params': { | |
273 | - 'question': tornado.escape.to_unicode(finished_topic_html) | |
274 | - } | |
275 | - }) | |
269 | + # if action == 'wrong': | |
270 | + # comments_html = self.render_string('comments.html', | |
271 | + # comments=question['comments'], md=md_to_html) | |
272 | + # template = self.templates[question['type']] | |
273 | + # question_html = self.render_string(template, question=question, md=md_to_html) | |
274 | + # self.write({ | |
275 | + # 'method': 'wrong', # FIXME js | |
276 | + # 'params': { | |
277 | + # 'question': tornado.escape.to_unicode(question_html), | |
278 | + # 'progress': self.learn.get_student_progress(user), | |
279 | + # 'comments': tornado.escape.to_unicode(comments_html), # FIXME | |
280 | + # 'tries': question['tries'], | |
281 | + # } | |
282 | + # }) | |
276 | 283 | |
277 | 284 | elif action == 'new_question': # get next question in the topic |
278 | 285 | template = self.templates[question['type']] |
... | ... | @@ -287,6 +294,15 @@ class QuestionHandler(BaseHandler): |
287 | 294 | } |
288 | 295 | }) |
289 | 296 | |
297 | + elif action == 'finished_topic': # right answer, finished topic | |
298 | + finished_topic_html = self.render_string('finished_topic.html') | |
299 | + self.write({ | |
300 | + 'method': 'finished_topic', | |
301 | + 'params': { | |
302 | + 'question': tornado.escape.to_unicode(finished_topic_html) | |
303 | + } | |
304 | + }) | |
305 | + | |
290 | 306 | else: |
291 | 307 | logger.error(f'Unknown action {action}') |
292 | 308 | |
... | ... | @@ -316,6 +332,8 @@ def main(): |
316 | 332 | help='Path prefix under which the topic directories can be found, e.g. ~/topics') |
317 | 333 | argparser.add_argument('--port', type=int, default=8443, |
318 | 334 | help='Port to be used by the HTTPS server, e.g. 8443') |
335 | + argparser.add_argument('--db', type=str, default='students.db', | |
336 | + help='SQLite3 database file, e.g. students.db') | |
319 | 337 | argparser.add_argument('--debug', action='store_true', |
320 | 338 | help='Enable debug messages') |
321 | 339 | arg = argparser.parse_args() |
... | ... | @@ -336,7 +354,7 @@ def main(): |
336 | 354 | # --- start application |
337 | 355 | logging.info('Starting App') |
338 | 356 | try: |
339 | - learnapp = LearnApp(arg.conffile, prefix=arg.prefix) | |
357 | + learnapp = LearnApp(arg.conffile, prefix=arg.prefix, db=arg.db) | |
340 | 358 | except Exception as e: |
341 | 359 | logging.critical('Failed to start backend application') |
342 | 360 | raise e | ... | ... |
static/js/topic.js
... | ... | @@ -7,31 +7,34 @@ $.fn.extend({ |
7 | 7 | } |
8 | 8 | }); |
9 | 9 | |
10 | + | |
11 | +function new_question(question, tries, progress) { | |
12 | + $("#question_div").html(question); | |
13 | + $("#comments").html(""); | |
14 | + $("#tries").html(tries); | |
15 | + $('#topic_progress').css('width', (100*progress)+'%').attr('aria-valuenow', 100*progress); | |
16 | + MathJax.Hub.Queue(["Typeset",MathJax.Hub,"question_div"]); | |
17 | + $('#question_div').animateCSS('bounceInDown'); | |
18 | + | |
19 | + // enable shift+enter to submit and tab to spaces conversion | |
20 | + $("input:text, input:radio, input:checkbox").keydown(function (e) { | |
21 | + if (e.keyCode == 13) { | |
22 | + e.preventDefault(); | |
23 | + if (e.shiftKey) postQuestion(); | |
24 | + return false; | |
25 | + }}); | |
26 | +} | |
27 | + | |
10 | 28 | // updates question according to the response given by the server |
11 | 29 | function updateQuestion(response){ |
12 | 30 | |
13 | 31 | switch (response["method"]) { |
14 | 32 | case "new_question": |
15 | - $("#question_div").html(response["params"]["question"]); | |
16 | - $("#comments").html(""); | |
17 | - $("#tries").html(response["params"]["tries"]); | |
18 | - | |
19 | - $('#topic_progress').css('width', (100*response["params"]["progress"])+'%').attr('aria-valuenow', 100*response["params"]["progress"]); | |
20 | - | |
21 | - MathJax.Hub.Queue(["Typeset",MathJax.Hub,"question_div"]); | |
22 | - | |
23 | - // enable shift+enter to submit and tab to spaces conversion | |
24 | - $("input:text, input:radio, input:checkbox").keydown(function (e) { | |
25 | - if (e.keyCode == 13) { | |
26 | - e.preventDefault(); | |
27 | - if (e.shiftKey) postQuestion(); | |
28 | - return false; | |
29 | - }}); | |
30 | - | |
31 | - $('#question_div').animateCSS('bounceInDown'); | |
33 | + params = response["params"]; | |
34 | + new_question(params["question"], params["tries"], params["progress"]); | |
32 | 35 | break; |
33 | 36 | |
34 | - case "wrong": | |
37 | + case "try_again": | |
35 | 38 | $('#topic_progress').css('width', (100*response["params"]["progress"])+'%').attr('aria-valuenow', 100*response["params"]["progress"]); |
36 | 39 | $('#question_div').animateCSS('shake'); |
37 | 40 | $('#comments').html(response['params']['comments']); |
... | ... | @@ -39,6 +42,20 @@ function updateQuestion(response){ |
39 | 42 | MathJax.Hub.Queue(["Typeset",MathJax.Hub,"#comments"]); |
40 | 43 | break; |
41 | 44 | |
45 | + // case "wrong": | |
46 | + // $('#topic_progress').css('width', (100*response["params"]["progress"])+'%').attr('aria-valuenow', 100*response["params"]["progress"]); | |
47 | + // $('#question_div').animateCSS('shake'); | |
48 | + // $('#comments').html(response['params']['comments']); | |
49 | + // $("#tries").html(response["params"]["tries"]); | |
50 | + // MathJax.Hub.Queue(["Typeset",MathJax.Hub,"#comments"]); | |
51 | + | |
52 | + // // setTimeout(function(){ | |
53 | + // new_question(response["params"]["question"], response["params"]["tries"], response["params"]["progress"]); | |
54 | + // // }, 5000); | |
55 | + // break; | |
56 | + | |
57 | + | |
58 | + | |
42 | 59 | case "finished_topic": |
43 | 60 | $('#submit').css("visibility", "hidden"); |
44 | 61 | $("#content").html(response["params"]["question"]); |
... | ... | @@ -62,7 +79,7 @@ function getQuestion() { |
62 | 79 | |
63 | 80 | // Send answer and receive a response. |
64 | 81 | // The response can be a new_question or a shake if the answer is wrong, which |
65 | -// is then passed to updateQuestion() | |
82 | +// is then passed to updateQuestion() | |
66 | 83 | function postQuestion() { |
67 | 84 | if (typeof editor === 'object') |
68 | 85 | editor.save(); | ... | ... |