# python standard library import random from datetime import datetime import logging # libraries import networkx as nx # this project import questions # setup logger for this module logger = logging.getLogger(__name__) # ---------------------------------------------------------------------------- # contains the kowledge state of each student. class Knowledge(object): def __init__(self, depgraph, state={}): self.depgraph = depgraph self.state = state # {node: level, node: level, ...} self.topic = self.topic_generator() self.current_topic = next(self.topic) self.questions = self.generate_questions_for_topic(self.current_topic) self.current_question = None self.finished_questions = [] # ------------------------------------------------------------------------ def topic_generator(self): self.topic_sequence = nx.topological_sort(self.depgraph) # FIXME for now... for t in self.topic_sequence: if self.state.get(t, 0.0) > 0.999: continue self.questions = self.generate_questions_for_topic(t) logger.info(f'Generated {len(self.questions)} questions for topic "{t}"') yield t # ------------------------------------------------------------------------ def generate_questions_for_topic(self, topic): factory = self.depgraph.node[topic]['factory'] return [q.generate() for q in factory] # ------------------------------------------------------------------------ def get_current_question(self): return self.current_question # ------------------------------------------------------------------------ def get_current_topic(self): return self.current_topic # ------------------------------------------------------------------------ def get_knowledge_state(self): return [(t, self.state.get(t, 0.0)) for t in self.topic_sequence] # ------------------------------------------------------------------------ def get_topic_progress(self): return len(self.finished_questions) / (len(self.finished_questions) + len(self.questions)) # --- generates a new question given the current state ------------------- def new_question(self): logger.debug('Knowledge.new_question()') if self.current_question is None or self.current_question.get('grade', 0.0) > 0.9999: while not self.questions: # finished topic! self.state[self.current_topic] = 1.0 self.finished_questions = [] try: self.current_topic = next(self.topic) except StopIteration: self.topic = self.topic_generator() self.current_topic = next(self.topic) self.questions = self.generate_questions_for_topic(self.current_topic) self.current_question = self.questions.pop(0) self.current_question['start_time'] = datetime.now() self.finished_questions.append(self.current_question) # FIXME not yet finished... return self.current_question # --- checks answer ------------------------------------------------------ # returns current question with correction, time and comments updated def check_answer(self, answer): logger.debug(f'Knowledge.check_answer({answer})') question = self.current_question if question is not None: question['finish_time'] = datetime.now() question.correct(answer) return question