diff --git a/app.py b/app.py index aa4f200..40a1528 100644 --- a/app.py +++ b/app.py @@ -136,6 +136,10 @@ class LearnApp(object): return self.online[uid]['state'].get_topic_progress() # ------------------------------------------------------------------------ + def get_student_question(self, uid): + return self.online[uid]['state'].get_current_question() # dict + + # ------------------------------------------------------------------------ def get_title(self): return self.depgraph.graph['title'] @@ -150,11 +154,8 @@ class LearnApp(object): return path.join(p, topic, 'public') # ------------------------------------------------------------------------ - # def get_current_question(self, uid): - # return self.online[uid]['state'].current_question - - # ------------------------------------------------------------------------ # check answer and if correct returns new question, otherwise returns None + # ------------------------------------------------------------------------ def check_answer(self, uid, answer): knowledge = self.online[uid]['state'] current_question = knowledge.check_answer(answer) diff --git a/knowledge.py b/knowledge.py index 20e550e..33ace37 100644 --- a/knowledge.py +++ b/knowledge.py @@ -14,31 +14,34 @@ import questions logger = logging.getLogger(__name__) # ---------------------------------------------------------------------------- -# contains the kowledge state of each student. +# kowledge state of each student....?? +# ---------------------------------------------------------------------------- class Knowledge(object): def __init__(self, depgraph, state={}, student=''): - self.student = student self.depgraph = depgraph - self.topic_sequence = nx.topological_sort(self.depgraph) # FIXME + self.state = state # {'topic_id': {'level':0.5, 'date': datetime}, ...} + self.student = student - # state = {'topic_id': {'level':0.5, 'date': datetime}, ...} - self.state = state + # compute recommended sequence of topics (FIXME) + self.topic_sequence = nx.topological_sort(self.depgraph) # select a topic to do self.new_topic() # ------------------------------------------------------------------------ + # Start a new topic. If not provided, selects the first with level < 0.8 + # If all levels > 0.8, will stay in the last one forever... + # ------------------------------------------------------------------------ def new_topic(self, topic=None): if topic is None: - # select the first topic that has level < 0.8 for topic in self.topic_sequence: if topic not in self.state or self.state[topic]['level'] < 0.8: break - logger.debug(f'Student {self.student}: new_topic({topic})') - # FIXME if all are > 0.9, will stay in the last one forever... + logger.info(f'Student {self.student} new topic "{topic}"') + self.current_topic = topic - self.current_topic_idx = self.topic_sequence.index(topic) + # self.current_topic_idx = self.topic_sequence.index(topic) self.questions = self.generate_questions_for_topic(topic) self.current_question = None self.finished_questions = [] @@ -47,10 +50,8 @@ class Knowledge(object): # ------------------------------------------------------------------------ def generate_questions_for_topic(self, topic): - logger.debug(f'Student {self.student}: generate_questions_for_topic "{topic}"') - - factory_list = self.depgraph.node[topic]['factory'] - return [q.generate() for q in factory_list] + factory = self.depgraph.node[topic]['factory'] + return [q.generate() for q in factory] # ------------------------------------------------------------------------ def get_current_question(self): @@ -62,7 +63,7 @@ class Knowledge(object): # ------------------------------------------------------------------------ def get_knowledge_state(self): - ts = [] + ts = [] # FIXME why list?? for t in self.topic_sequence: if t in self.state: ts.append((t, self.state[t]['level'])) @@ -97,8 +98,9 @@ class Knowledge(object): logger.debug(f'Student {self.student}: new_question({self.current_question["ref"]})') return self.current_question - # --- checks answer ------------------------------------------------------ - # returns current question with correction, time and comments updated + # ------------------------------------------------------------------------ + # returns the current question with correction, time and comments updated + # ------------------------------------------------------------------------ def check_answer(self, answer): question = self.current_question if question is not None: diff --git a/serve.py b/serve.py index 7814d77..f78f0ee 100755 --- a/serve.py +++ b/serve.py @@ -161,6 +161,35 @@ class QuestionHandler(BaseHandler): } @tornado.web.authenticated + def get(self): + user = self.current_user + state = self.learn.get_student_state(user) # all topics + progress = self.learn.get_student_progress(user) # float + question = self.learn.get_current_question(user) + print(question) # FIXME cant get current question + + question_html = self.render_string( + self.templates[question['type']], + question=question, # dictionary with the question + md=md, # function that renders markdown to html + ) + topics_html = self.render_string('topics.html', + state=state, + topicname=self.learn.get_topic_name, # translate ref to names + ) + print(topics_html) + print(question_html) + self.write({ + 'method': 'new_question', + 'params': { + 'question': tornado.escape.to_unicode(question_html), + 'state': tornado.escape.to_unicode(topics_html), + 'progress': progress, + } + }) + + # posting can change state and return new question + @tornado.web.authenticated def post(self): user = self.current_user answer = self.get_body_arguments('answer') diff --git a/templates/learn.html b/templates/learn.html index 65b7d0a..5457a91 100644 --- a/templates/learn.html +++ b/templates/learn.html @@ -163,20 +163,20 @@ function updateQuestion(response){ MathJax.Hub.Queue(["Typeset",MathJax.Hub,"question_div"]); - + // enable shift+enter to submit and tab to spaces conversion $("input:text, input:radio, input:checkbox").keydown(function (e) { if (e.keyCode == 13 && e.shiftKey) { e.preventDefault(); - getQuestion(); + postQuestion(); } }); - $("textarea").keydown(function (e) { if (e.keyCode == 13 && e.shiftKey) { // shift enter e.preventDefault(); - getQuestion(); + postQuestion(); } else if (e.keyCode === 9) { // tab + e.preventDefault(); // prevent loosing focus // get caret position/selection var start = this.selectionStart; var end = this.selectionEnd; @@ -187,9 +187,9 @@ function updateQuestion(response){ // put caret at right position again (add one for the tab) this.selectionStart = this.selectionEnd = start + 4; - e.preventDefault(); // prevent the focus lose } }); + // var audio = new Audio('/static/sounds/correct.mp3'); // audio.play(); $('#question_div').animateCSS('zoomIn'); @@ -205,7 +205,7 @@ function updateQuestion(response){ // Send answer and receive a response. // The response can be a new_question or a shake if the answer is wrong. -function getQuestion() { +function postQuestion() { $.ajax({ type: "POST", url: "/question", @@ -217,6 +217,20 @@ function getQuestion() { }); } +// Send answer and receive a response. +// The response can be a new_question or a shake if the answer is wrong. +function getQuestion() { + $.ajax({ + // type: "GET", + url: "/question", + // headers: {"X-XSRFToken": token}, + // data: $("#question_form").serialize(), // {'a':10,'b':20}, + dataType: "json", // expected from server + success: updateQuestion, + error: function() {alert("O servidor não responde.");} + }); +} + function change_password() { $.ajax({ type: "POST", @@ -240,7 +254,7 @@ $(document).ready(function() { // var audio = new Audio('/static/sounds/intro.mp3'); // audio.play(); getQuestion(); - $("#submit").click(getQuestion); + $("#submit").click(postQuestion); $('[data-toggle=offcanvas]').click(function() { $('.row-offcanvas').toggleClass('active'); }); -- libgit2 0.21.2