From f865b05a08c5e9acbe0ab92f4b0dad1d776f789f Mon Sep 17 00:00:00 2001 From: Miguel BarĂ£o Date: Thu, 9 Jan 2020 17:20:44 +0000 Subject: [PATCH] allow admin to reload topic and regenerate QFactory --- aprendizations/learnapp.py | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------- aprendizations/student.py | 4 ++-- 2 files changed, 63 insertions(+), 48 deletions(-) diff --git a/aprendizations/learnapp.py b/aprendizations/learnapp.py index db1037b..c8003cc 100644 --- a/aprendizations/learnapp.py +++ b/aprendizations/learnapp.py @@ -78,7 +78,6 @@ class LearnApp(object): logger.info(f'{len(t):>6} topics in {courses}') for f in config.get('topics_from', []): c = load_yaml(f) # course configuration - # FIXME set defaults?? logger.info(f'{len(c["topics"]):>6} topics imported from {f}') self.populate_graph(c) @@ -302,6 +301,10 @@ class LearnApp(object): # ------------------------------------------------------------------------ async def start_topic(self, uid: str, topic: str) -> None: student = self.online[uid]['state'] + if uid == '0': + logger.warning(f'Reloading "{topic}"') + self.factory.update(self.factory_for(topic)) + try: await student.start_topic(topic) except Exception as e: @@ -393,66 +396,78 @@ class LearnApp(object): # ------------------------------------------------------------------------ # Buils dictionary of question factories + # - visits each topic in the graph, + # - adds factory for each topic. # ------------------------------------------------------------------------ def make_factory(self) -> Dict[str, QFactory]: logger.info('Building questions factory:') - factory = {} + factory = dict() g = self.deps for tref in g.nodes(): - t = g.nodes[tref] + factory.update(self.factory_for(tref)) - # load questions as list of dicts - topicpath: str = path.join(g.graph['prefix'], tref) - try: - fullpath: str = path.join(topicpath, t['file']) - except Exception: - msg1 = f'Invalid topic "{tref}"' - msg2 = f'Check dependencies of {", ".join(g.successors(tref))}' - raise LearnException(f'{msg1}. {msg2}') + logger.info(f'Factory has {len(factory)} questions') + return factory - logger.debug(f' Loading {fullpath}') - try: - questions: List[QDict] = load_yaml(fullpath) - except Exception: - msg = f'Failed to load "{fullpath}"' - logger.error(msg) - raise LearnException(msg) + # ------------------------------------------------------------------------ + # makes factory for a single topic + # ------------------------------------------------------------------------ + def factory_for(self, tref: str) -> Dict[str, QFactory]: + factory = {} + g = self.deps + t = g.nodes[tref] # get node - if not isinstance(questions, list): - msg = f'File "{fullpath}" must be a list of questions' - raise LearnException(msg) + # load questions as list of dicts + topicpath: str = path.join(g.graph['prefix'], tref) + try: + fullpath: str = path.join(topicpath, t['file']) + except Exception: + msg1 = f'Invalid topic "{tref}"' + msg2 = f'Check dependencies of {", ".join(g.successors(tref))}' + raise LearnException(f'{msg1}. {msg2}') - # update refs to include topic as prefix. - # refs are required to be unique only within the file. - # undefined are set to topic:n, where n is the question number - # within the file - localrefs: Set[str] = set() # refs in current file - for i, q in enumerate(questions): - qref = q.get('ref', str(i)) # ref or number - if qref in localrefs: - msg = f'Duplicate ref "{qref}" in "{topicpath}"' - raise LearnException(msg) - localrefs.add(qref) + logger.debug(f' Loading {fullpath}') + try: + questions: List[QDict] = load_yaml(fullpath) + except Exception: + msg = f'Failed to load "{fullpath}"' + logger.error(msg) + raise LearnException(msg) + + if not isinstance(questions, list): + msg = f'File "{fullpath}" must be a list of questions' + raise LearnException(msg) + + # update refs to include topic as prefix. + # refs are required to be unique only within the file. + # undefined are set to topic:n, where n is the question number + # within the file + localrefs: Set[str] = set() # refs in current file + for i, q in enumerate(questions): + qref = q.get('ref', str(i)) # ref or number + if qref in localrefs: + msg = f'Duplicate ref "{qref}" in "{topicpath}"' + raise LearnException(msg) + localrefs.add(qref) - q['ref'] = f'{tref}:{qref}' - q['path'] = topicpath - q.setdefault('append_wrong', t['append_wrong']) + q['ref'] = f'{tref}:{qref}' + q['path'] = topicpath + q.setdefault('append_wrong', t['append_wrong']) - # if questions are left undefined, include all. - if not t['questions']: - t['questions'] = [q['ref'] for q in questions] + # if questions are left undefined, include all. + if not t['questions']: + t['questions'] = [q['ref'] for q in questions] - t['choose'] = min(t['choose'], len(t['questions'])) + t['choose'] = min(t['choose'], len(t['questions'])) - for q in questions: - if q['ref'] in t['questions']: - factory[q['ref']] = QFactory(q) - logger.debug(f' + {q["ref"]}') + for q in questions: + if q['ref'] in t['questions']: + factory[q['ref']] = QFactory(q) + logger.debug(f' + {q["ref"]}') - logger.info(f'{len(t["questions"]):6} questions in {tref}') + logger.info(f'{len(t["questions"]):6} questions in {tref}') - logger.info(f'Factory has {len(factory)} questions') return factory # ------------------------------------------------------------------------ @@ -501,7 +516,7 @@ class LearnApp(object): # ------------------------------------------------------------------------ def get_current_public_dir(self, uid: str) -> str: - topic: str = self.online[uid]['state'].get_current_topic() # FIXME returns None if its the last question in the topic + topic: str = self.online[uid]['state'].get_current_topic() prefix: str = self.deps.graph['prefix'] return path.join(prefix, topic, 'public') diff --git a/aprendizations/student.py b/aprendizations/student.py index 6f747bb..b181fa5 100644 --- a/aprendizations/student.py +++ b/aprendizations/student.py @@ -75,12 +75,12 @@ class StudentState(object): logger.debug(f'start topic "{topic}"') # avoid regenerating questions in the middle of the current topic - if self.current_topic == topic: + if self.current_topic == topic and self.uid != '0': logger.info('Restarting current topic is not allowed.') return # do not allow locked topics - if self.is_locked(topic): + if self.is_locked(topic) and self.uid != '0': logger.debug(f'is locked "{topic}"') return -- libgit2 0.21.2