From d1410958a5c4b53c8654156d31541831d01d3d52 Mon Sep 17 00:00:00 2001 From: Miguel Barão Date: Tue, 28 Nov 2017 00:12:18 +0000 Subject: [PATCH] - starts do do something... - many topics do not work yet. --- knowledge.py | 40 ++++++++++++++++++++++------------------ learnapp.py | 10 +++++----- questions.py | 7 +++++-- serve.py | 73 +++++++++++++++++++++++++++++-------------------------------------------- static/trophy.png | Bin 0 -> 166752 bytes templates/maintopics.html | 1 - templates/topic.html | 69 +++++++++++++++++++++++++++++++++++++++++++++++---------------------- templates/topics.html | 40 ---------------------------------------- 8 files changed, 108 insertions(+), 132 deletions(-) create mode 100644 static/trophy.png delete mode 100644 templates/topics.html diff --git a/knowledge.py b/knowledge.py index 051ed42..8c09164 100644 --- a/knowledge.py +++ b/knowledge.py @@ -20,7 +20,6 @@ class StudentKnowledge(object): # ======================================================================= # methods that update state # ======================================================================= - def __init__(self, deps, state={}): # graph with topic dependencies shared between all students self.deps = deps @@ -38,12 +37,9 @@ class StudentKnowledge(object): # compute recommended sequence of topics ['a', 'b', ...] self.topic_sequence = list(nx.topological_sort(self.deps)) - # select a topic to do and initialize questions - # self.start_topic() - # ------------------------------------------------------------------------ - # Unlock all topics whose dependencies are satisfied + # Unlock topics whose dependencies are satisfied (> min_level) # ------------------------------------------------------------------------ def unlock_topics(self): min_level = 0.01 # minimum level to unlock @@ -60,9 +56,10 @@ class StudentKnowledge(object): # ------------------------------------------------------------------------ # Recommends a topic to practice/learn from the state. + # FIXME untested # ------------------------------------------------------------------------ def recommended_topic(self): - return min(self.state.items(), key=lambda x: x[1])[0] + return min(self.state.items(), key=lambda x: x[1]['level'])[0] # if not topic: @@ -81,14 +78,15 @@ class StudentKnowledge(object): # logger.debug(f'Can\'t start topic "{topic}".') # return + # ------------------------------------------------------------------------ - # 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... + # Start a new topic. If not provided, gets a recommendation. + # questions: list of generated questions to do in the topic + # finished_questions: [] will contain correctly answered questions + # current_question: the current question to be presented # ------------------------------------------------------------------------ - def start_topic(self, topic=''): - # unlock topics whose dependencies are done - - self.unlock_topics() + def init_topic(self, topic=''): + # self.unlock_topics() # FIXME needed? if not topic: topic = self.recommended_topic() @@ -97,26 +95,30 @@ class StudentKnowledge(object): self.current_topic = topic logger.info(f'Topic set to "{topic}"') - # generate question instances for current topic factory = self.deps.node[topic]['factory'] questionlist = self.deps.node[topic]['questions'] self.questions = [factory[qref].generate() for qref in questionlist] - self.current_question = self.questions.pop(0) # FIXME crashes if questions==[] - self.current_question['start_time'] = datetime.now() self.finished_questions = [] + self.current_question = self.questions.pop(0) # FIXME crash if empty + self.current_question['start_time'] = datetime.now() + # ------------------------------------------------------------------------ # returns the current question with correction, time and comments updated # ------------------------------------------------------------------------ def check_answer(self, answer): + logger.debug('StudentKnowledge.check_answer()') + q = self.current_question q['finish_time'] = datetime.now() - grade = q.correct(answer) + q['answer'] = answer + grade = q.correct() + logger.debug(f'Grade = {grade:.2} ({q["ref"]})') - # new question if answer is correct + # if answer is correct, get next question if grade > 0.999: self.finished_questions.append(q) try: @@ -127,13 +129,15 @@ class StudentKnowledge(object): 'level': 1.0, 'date': datetime.now() } - self.start_topic() else: self.current_question['start_time'] = datetime.now() + + # if answer is wrong, keep same question and add a similar one at the end else: factory = self.deps.node[self.current_topic]['factory'] self.questions.append(factory[q['ref']].generate()) + # returns answered and corrected question return q diff --git a/learnapp.py b/learnapp.py index be9e621..1e2e18b 100644 --- a/learnapp.py +++ b/learnapp.py @@ -60,8 +60,8 @@ class LearnApp(object): # success logger.info(f'User "{uid}" logged in') - state = {} tt = s.query(StudentTopic).filter(StudentTopic.student_id == uid) + state = {} for t in tt: state[t.topic_id] = { 'level': t.level, @@ -141,7 +141,7 @@ class LearnApp(object): # Start new topic # ------------------------------------------------------------------------ def start_topic(self, uid, topic): - self.online[uid]['state'].start_topic(topic) + self.online[uid]['state'].init_topic(topic) # ------------------------------------------------------------------------ # Fill db table 'Topic' with topics from the graph if not already there. @@ -276,13 +276,13 @@ def build_dependency_graph(config_file): fullpath = path.expanduser(path.join(prefix, tref)) filename = path.join(fullpath, 'questions.yaml') - loaded_questions = load_yaml(filename, default=[]) + loaded_questions = load_yaml(filename, default=[]) # list - # if questions not in configuration then load all, preserve order + # if questions not in configuration then load all, preserving order if not tnode['questions']: tnode['questions'] = [q['ref'] for q in loaded_questions] - # make questions factory (without repeting same question) + # make questions factory (without repeating same question) tnode['factory'] = {} for q in loaded_questions: if q['ref'] in tnode['questions']: diff --git a/questions.py b/questions.py index f927867..9d745cd 100644 --- a/questions.py +++ b/questions.py @@ -11,9 +11,11 @@ import yaml # this project from tools import run_script + # regular expressions in yaml files, e.g. correct: !regex '[aA]zul' yaml.add_constructor('!regex', lambda l, n: re.compile(l.construct_scalar(n))) + # setup logger for this module logger = logging.getLogger(__name__) @@ -39,8 +41,9 @@ class Question(dict): 'files': {}, }) - def updateAnswer(answer=None): - self['answer'] = answer + # FIXME unused. does childs need do override this? + # def updateAnswer(answer=None): + # self['answer'] = answer def correct(self): self['grade'] = 0.0 diff --git a/serve.py b/serve.py index fc324b4..00f94f3 100755 --- a/serve.py +++ b/serve.py @@ -129,9 +129,9 @@ class TopicHandler(BaseHandler): @tornado.web.authenticated def get(self, topic): uid = self.current_user - # topic = self.get_query_argument('topic', default='') self.learn.start_topic(uid, topic) + self.render('topic.html', uid=uid, name=self.learn.get_student_name(uid), @@ -159,12 +159,12 @@ class FileHandler(BaseHandler): # ---------------------------------------------------------------------------- class QuestionHandler(BaseHandler): templates = { - 'checkbox': 'question-checkbox.html', - 'radio': 'question-radio.html', - 'text': 'question-text.html', - 'text-regex': 'question-text.html', + 'checkbox': 'question-checkbox.html', + 'radio': 'question-radio.html', + 'text': 'question-text.html', + 'text-regex': 'question-text.html', 'numeric-interval': 'question-text.html', - 'textarea': 'question-textarea.html', + 'textarea': 'question-textarea.html', # -- information panels -- 'information': 'question-information.html', 'info': 'question-information.html', @@ -175,24 +175,23 @@ class QuestionHandler(BaseHandler): } def new_question(self, user): - state = self.learn.get_student_state(user) # all topics [('a', 0.1), ...] - current_topic = self.learn.get_student_topic(user) # str - progress = self.learn.get_student_progress(user) # float - question = self.learn.get_student_question(user) # dict? - question_html = self.render_string(self.templates[question['type']],question=question, md=md) - topics_html = self.render_string('topics.html', state=state, current_topic=current_topic, gettopicname=self.learn.get_topic_name) + # state = self.learn.get_student_state(user) # [{ref, name, level},...] + # current_topic = self.learn.get_student_topic(user) # str + + question = self.learn.get_student_question(user) # Question + template = self.templates[question['type']] + question_html = self.render_string(template, question=question, md=md) return { 'method': 'new_question', 'params': { 'question': tornado.escape.to_unicode(question_html), - 'state': tornado.escape.to_unicode(topics_html), - 'progress': progress, + 'progress': self.learn.get_student_progress(user), } } - def shake(self, user): + def wrong_answer(self, user): progress = self.learn.get_student_progress(user) # in the current topic return { 'method': 'shake', @@ -202,68 +201,54 @@ class QuestionHandler(BaseHandler): } def finished_topic(self, user): - state = self.learn.get_student_state(user) # all topics - current_topic = self.learn.get_student_topic(uid) + # state = self.learn.get_student_state(user) # all topics + # current_topic = self.learn.get_student_topic(uid) - topics_html = self.render_string('topics.html', - state=state, - current_topic=current_topic, - topicname=self.learn.get_topic_name, # translate ref to names - ) return { 'method': 'finished_topic', 'params': { - 'state': tornado.escape.to_unicode(topics_html), + 'question': 'trophy', + 'progress': 1.0, } } @tornado.web.authenticated def get(self): logging.debug('QuestionHandler.get') + user = self.current_user - uid = self.current_user - - question = self.learn.get_student_question(uid) - print(question) # FIXME its returning different questions on reload... + question = self.learn.get_student_question(user) template = self.templates[question['type']] question_html = self.render_string(template, question=question, md=md) - print(question_html) self.write({ 'method': 'new_question', 'params': { 'question': tornado.escape.to_unicode(question_html), - 'progress': 0.3, #self.learn.get_student_progress(uid) , + 'progress': self.learn.get_student_progress(user) , } }) - - # question_html = self.render_string(self.templates[question['type']],question=question, md=md) - # response = { - # 'method': 'new_question', - # 'params': { - # 'question': tornado.escape.to_unicode(question_html), - # 'progress': progress, - # } - # } - # self.write(response) - # handles answer posted @tornado.web.authenticated def post(self): logging.debug('QuestionHandler.post') - user = self.current_user - answer = self.get_body_arguments('answer') + + # if self.learn.get_student_question(user) is None: + + answer = self.get_body_argument('answer') + + # check answer and get next question (same, new or None) grade = self.learn.check_answer(user, answer) - question = self.learn.get_student_question(user) # same, new or None + question = self.learn.get_student_question(user) if question is None: self.write(self.finished_topic(user)) elif grade > 0.999: self.write(self.new_question(user)) else: - self.write(self.shake(user)) + self.write(self.wrong_answer(user)) # ------------------------------------------------------------------------- diff --git a/static/trophy.png b/static/trophy.png new file mode 100644 index 0000000..14df155 Binary files /dev/null and b/static/trophy.png differ diff --git a/templates/maintopics.html b/templates/maintopics.html index 23b7a46..9b75deb 100644 --- a/templates/maintopics.html +++ b/templates/maintopics.html @@ -149,4 +149,3 @@ - diff --git a/templates/topic.html b/templates/topic.html index 7b28693..db5275f 100644 --- a/templates/topic.html +++ b/templates/topic.html @@ -52,17 +52,24 @@ - + @@ -71,18 +78,18 @@ -
+
{% module xsrf_form_html() %} -
Question goes here!!!!
+
-
+
@@ -93,6 +100,15 @@ diff --git a/templates/topics.html b/templates/topics.html deleted file mode 100644 index cda0331..0000000 --- a/templates/topics.html +++ /dev/null @@ -1,40 +0,0 @@ -{% autoescape %} - -

Tópicos

- - -- libgit2 0.21.2