From 89e08ad8067a6de0b3394f3b35399d2db2dc1b7e Mon Sep 17 00:00:00 2001 From: Miguel BarĂ£o Date: Tue, 30 Jan 2018 12:19:22 +0000 Subject: [PATCH] - added missing comments.html template. - added missing finished_topic.html template. - support information "questions" again. They are useful to finish chapters. --- knowledge.py | 34 ++++++++++++++++++++++------------ learnapp.py | 5 +++-- serve.py | 16 ++++++++++------ templates/comments.html | 9 +++++++++ templates/finished_topic.html | 1 + tools.py | 8 ++++---- 6 files changed, 49 insertions(+), 24 deletions(-) create mode 100644 templates/comments.html create mode 100644 templates/finished_topic.html diff --git a/knowledge.py b/knowledge.py index fed9d5a..6a4e9ee 100644 --- a/knowledge.py +++ b/knowledge.py @@ -15,29 +15,38 @@ logger = logging.getLogger(__name__) # ---------------------------------------------------------------------------- # kowledge state of each student....?? +# Contains: +# state - dict of topics with state of unlocked topics +# deps - dependency graph +# topic_sequence - list with the order of recommended topics # ---------------------------------------------------------------------------- class StudentKnowledge(object): # ======================================================================= # methods that update state # ======================================================================= def __init__(self, deps, state={}): - # graph with topic dependencies shared between all students - self.deps = deps + self.deps = deps # dependency graph shared among students + self.state = state # {'topic': {'level':0.5, 'date': datetime}, ...} + self.update_topic_levels() # forgetting factor + self.topic_sequence = self.recommend_topic_sequence() # ['a', 'b', ...] + self.unlock_topics() - # state only contains unlocked topics - # {'topic_id': {'level':0.5, 'date': datetime}, ...} - self.state = state + # ------------------------------------------------------------------------ + # compute recommended sequence of topics ['a', 'b', ...] + # ------------------------------------------------------------------------ + def recommend_topic_sequence(self): + return list(nx.topological_sort(self.deps)) - # update state level based on the elapsed time (no dependencies... FIXME) + # ------------------------------------------------------------------------ + # Updates the proficiency levels of the topics, with forgetting factor + # FIXME no dependencies are considered yet... + # ------------------------------------------------------------------------ + def update_topic_levels(self): now = datetime.now() - for s in state.values(): + for s in self.state.values(): dt = now - s['date'] s['level'] *= 0.8 ** dt.days # forgetting factor 0.95 - # compute recommended sequence of topics ['a', 'b', ...] - self.topic_sequence = list(nx.topological_sort(self.deps)) - - self.unlock_topics() # ------------------------------------------------------------------------ # Unlock topics whose dependencies are satisfied (> min_level) @@ -86,7 +95,8 @@ class StudentKnowledge(object): try: self.current_question = self.questions.pop(0) # FIXME crash if empty except IndexError: - self.finish_topic() + # self.current_question = None + self.finish_topic() # FIXME if no questions, what should be done? return False else: self.current_question['start_time'] = datetime.now() diff --git a/learnapp.py b/learnapp.py index c523cae..7b331d1 100644 --- a/learnapp.py +++ b/learnapp.py @@ -104,7 +104,7 @@ class LearnApp(object): # ------------------------------------------------------------------------ def check_answer(self, uid, answer): knowledge = self.online[uid]['state'] - grade = knowledge.check_answer(answer) + grade = knowledge.check_answer(answer) # also moves to next question if knowledge.get_current_question() is None: # finished topic, save into database @@ -129,6 +129,7 @@ class LearnApp(object): a.date = date s.add(a) + logger.debug(f'Saved topic "{finished_topic}" into database') # save answered questions from finished_questions list s.add_all([ @@ -140,7 +141,7 @@ class LearnApp(object): student_id=uid, topic_id=finished_topic) for q in finished_questions]) - + logger.debug(f'Saved {len(finished_questions)} answers into database') return grade # ------------------------------------------------------------------------ diff --git a/serve.py b/serve.py index 0fd46c8..3bca462 100755 --- a/serve.py +++ b/serve.py @@ -169,9 +169,9 @@ class QuestionHandler(BaseHandler): 'numeric-interval': 'question-text.html', 'textarea': 'question-textarea.html', # -- information panels -- - # 'information': 'question-information.html', - # 'info': 'question-information.html', - # 'success': 'question-success.html', + 'information': 'question-information.html', + 'info': 'question-information.html', + 'success': 'question-success.html', # 'warning': '', FIXME # 'warn': '', FIXME # 'alert': '', FIXME @@ -270,15 +270,19 @@ def main(): logging.info('====================================================') # --- start application - logging.info('Starting App.') - learnapp = LearnApp(arg.conffile[0]) + logging.info('Starting App') + try: + learnapp = LearnApp(arg.conffile[0]) + except Exception as e: + logging.critical('Failed to start backend application') + raise e # --- create web application logging.info('Starting Web App (tornado)') try: webapp = WebApplication(learnapp, debug=arg.debug) except Exception as e: - logging.critical('Failed to start application.') + logging.critical('Failed to start web application.') raise e # --- create webserver diff --git a/templates/comments.html b/templates/comments.html new file mode 100644 index 0000000..9cf62f4 --- /dev/null +++ b/templates/comments.html @@ -0,0 +1,9 @@ +{% autoescape %} + +{% if comments %} +
+
+

{{md(comments)}}

+
+
+{% end %} diff --git a/templates/finished_topic.html b/templates/finished_topic.html new file mode 100644 index 0000000..bc6634f --- /dev/null +++ b/templates/finished_topic.html @@ -0,0 +1 @@ +trophy \ No newline at end of file diff --git a/tools.py b/tools.py index 4ab1931..b4d0607 100644 --- a/tools.py +++ b/tools.py @@ -137,18 +137,18 @@ def load_yaml(filename, default=None): try: f = open(filename, 'r', encoding='utf-8') except FileNotFoundError: - logger.error(f'Can\'t open "{filename}": not found.') + logger.error(f'Can\'t open "{filename}": not found') except PermissionError: - logger.error(f'Can\'t open "{filename}": no permission.') + logger.error(f'Can\'t open "{filename}": no permission') except IOError: - logger.error(f'Can\'t open file "{filename}".') + logger.error(f'Can\'t open file "{filename}"') else: with f: try: default = yaml.load(f) except yaml.YAMLError as e: mark = e.problem_mark - logger.error(f'In YAML file "{filename}" near line {mark.line}, column {mark.column+1}.') + logger.error(f'In YAML file "{filename}" near line {mark.line}, column {mark.column+1}') finally: return default -- libgit2 0.21.2