Commit dbdd58fe15e1cd88fb28cf6a13f13b5447cdca79
1 parent
bf8ade7a
Exists in
master
and in
1 other branch
- added option 'append_wrong' to enable/disable appending new instance of questi…
…ons when answered wrong. - added option 'max_tries'. - added option 'shuffle' to que order of the questions in a topic. - images are no longer in a html figure tag, and are now centered.
Showing
6 changed files
with
41 additions
and
21 deletions
Show diff stats
BUGS.md
| 1 | 1 | |
| 2 | 2 | # BUGS |
| 3 | 3 | |
| 4 | +- nos topicos learn.yaml, qd falha acrescenta no fim. nao faz sentido. | |
| 5 | +- ocorreu uma vez o sqlalchemy dar mesg erro a indicar que as threads sao diferents quando se faz o get da primeira pergunta do topico. Muitas vezes nao mostar erro, mas a pagina da erro ou fica em branco... | |
| 6 | + | |
| 7 | +- mathjax, formulas $$f(x)$$ nas opções de escolha multipla, não ficam centradas em toda a coluna mas apenas na largura do parágrafo. | |
| 4 | 8 | - mostrar feedback/solucoes quando acerta, ou excede max tries. |
| 5 | 9 | - default prefix should be obtained from each course (yaml conf)? |
| 6 | 10 | - tabelas nas perguntas radio/checkbox não ocupam todo o espaço como em question. | ... | ... |
knowledge.py
| ... | ... | @@ -71,13 +71,14 @@ class StudentKnowledge(object): |
| 71 | 71 | # questions: list of generated questions to do in the topic |
| 72 | 72 | # current_question: the current question to be presented |
| 73 | 73 | # ------------------------------------------------------------------------ |
| 74 | - async def init_topic(self, topic): | |
| 75 | - logger.debug(f'StudentKnowledge.init_topic({topic})') | |
| 74 | + # FIXME async mas nao tem awaits... | |
| 75 | + async def start_topic(self, topic): | |
| 76 | + logger.debug(f'StudentKnowledge.start_topic({topic})') | |
| 76 | 77 | |
| 77 | 78 | # do not allow locked topics |
| 78 | 79 | if self.is_locked(topic): |
| 79 | 80 | logger.debug(f'Topic {topic} is locked') |
| 80 | - return | |
| 81 | + return False | |
| 81 | 82 | |
| 82 | 83 | # starting new topic |
| 83 | 84 | self.current_topic = topic |
| ... | ... | @@ -85,7 +86,11 @@ class StudentKnowledge(object): |
| 85 | 86 | self.wrong_answers = 0 |
| 86 | 87 | |
| 87 | 88 | t = self.deps.node[topic] |
| 88 | - questions = random.sample(t['questions'], k=t['choose']) | |
| 89 | + k = t['choose'] | |
| 90 | + if t['shuffle']: | |
| 91 | + questions = random.sample(t['questions'], k=k) | |
| 92 | + else: | |
| 93 | + questions = t['questions'][:k] | |
| 89 | 94 | logger.debug(f'Questions: {", ".join(questions)}') |
| 90 | 95 | |
| 91 | 96 | # generate instances of questions |
| ... | ... | @@ -94,6 +99,7 @@ class StudentKnowledge(object): |
| 94 | 99 | |
| 95 | 100 | # get first question |
| 96 | 101 | self.next_question() |
| 102 | + return True | |
| 97 | 103 | |
| 98 | 104 | |
| 99 | 105 | # ------------------------------------------------------------------------ |
| ... | ... | @@ -140,8 +146,10 @@ class StudentKnowledge(object): |
| 140 | 146 | logger.debug(f'Wrong answers = {self.wrong_answers}; Tries = {self.current_question["tries"]}') |
| 141 | 147 | |
| 142 | 148 | if self.current_question['tries'] <= 0: |
| 143 | - logger.debug("Appending new instance of this question to the end") | |
| 144 | - self.questions.append(self.factory[q['ref']].generate()) | |
| 149 | + if self.current_question['append_wrong']: | |
| 150 | + logger.debug("Appending new instance of this question to the end") | |
| 151 | + self.questions.append(self.factory[q['ref']].generate()) | |
| 152 | + | |
| 145 | 153 | if self.next_question() is None: |
| 146 | 154 | action = 'finished_topic' |
| 147 | 155 | else: |
| ... | ... | @@ -165,7 +173,8 @@ class StudentKnowledge(object): |
| 165 | 173 | self.finish_topic() |
| 166 | 174 | else: |
| 167 | 175 | self.current_question['start_time'] = datetime.now() |
| 168 | - self.current_question['tries'] = self.current_question.get('max_tries', 3) # FIXME hardcoded 3 | |
| 176 | + default_maxtries = self.deps.nodes[self.current_topic]['max_tries'] | |
| 177 | + self.current_question['tries'] = self.current_question.get('max_tries', default_maxtries) | |
| 169 | 178 | logger.debug(f'Next question is "{self.current_question["ref"]}"') |
| 170 | 179 | |
| 171 | 180 | return self.current_question # question or None | ... | ... |
learnapp.py
| ... | ... | @@ -186,7 +186,7 @@ class LearnApp(object): |
| 186 | 186 | async def start_topic(self, uid, topic): |
| 187 | 187 | student = self.online[uid]['state'] |
| 188 | 188 | try: |
| 189 | - await student.init_topic(topic) | |
| 189 | + await student.start_topic(topic) | |
| 190 | 190 | except KeyError as e: |
| 191 | 191 | logger.warning(f'User "{uid}" tried to open nonexistent topic: "{topic}"') |
| 192 | 192 | raise e |
| ... | ... | @@ -242,6 +242,8 @@ class LearnApp(object): |
| 242 | 242 | default_shuffle = config.get('shuffle', True) |
| 243 | 243 | default_choose = config.get('choose', 9999) |
| 244 | 244 | default_forgetting_factor = config.get('forgetting_factor', 1.0) |
| 245 | + default_maxtries = config.get('max_tries', 3) | |
| 246 | + default_append_wrong = config.get('append_wrong', True) | |
| 245 | 247 | |
| 246 | 248 | # iterate over topics and populate graph |
| 247 | 249 | topics = config.get('topics', {}) |
| ... | ... | @@ -257,8 +259,10 @@ class LearnApp(object): |
| 257 | 259 | t['path'] = path.join(g.graph['prefix'], tref) # prefix/topic |
| 258 | 260 | t['file'] = attr.get('file', default_file) # questions.yaml |
| 259 | 261 | t['shuffle'] = attr.get('shuffle', default_shuffle) |
| 262 | + t['max_tries'] = attr.get('max_tries', default_maxtries) | |
| 260 | 263 | t['forgetting_factor'] = attr.get('forgetting_factor', default_forgetting_factor) |
| 261 | 264 | t['choose'] = attr.get('choose', default_choose) |
| 265 | + t['append_wrong'] = attr.get('append_wrong', default_append_wrong) | |
| 262 | 266 | t['questions'] = attr.get('questions', []) |
| 263 | 267 | |
| 264 | 268 | logger.info(f'Loaded {g.number_of_nodes()} topics') |
| ... | ... | @@ -286,6 +290,7 @@ class LearnApp(object): |
| 286 | 290 | qref = q.get('ref', str(i)) # ref or number |
| 287 | 291 | q['ref'] = tref + ':' + qref |
| 288 | 292 | q['path'] = topicpath |
| 293 | + q.setdefault('append_wrong', t['append_wrong']) | |
| 289 | 294 | |
| 290 | 295 | # if questions are left undefined, include all. |
| 291 | 296 | if not t['questions']: | ... | ... |
serve.py
| ... | ... | @@ -149,6 +149,8 @@ class RootHandler(BaseHandler): |
| 149 | 149 | # Start a given topic: /topic/... |
| 150 | 150 | # ---------------------------------------------------------------------------- |
| 151 | 151 | class TopicHandler(BaseHandler): |
| 152 | + SUPPORTED_METHODS = ['GET'] | |
| 153 | + | |
| 152 | 154 | @tornado.web.authenticated |
| 153 | 155 | async def get(self, topic): |
| 154 | 156 | uid = self.current_user | ... | ... |
templates/question.html
tools.py
| ... | ... | @@ -102,18 +102,18 @@ class HighlightRenderer(mistune.Renderer): |
| 102 | 102 | def image(self, src, title, alt): |
| 103 | 103 | alt = mistune.escape(alt, quote=True) |
| 104 | 104 | title = mistune.escape(title or '', quote=True) |
| 105 | - if title: | |
| 106 | - caption = f'<figcaption class="figure-caption">{title}</figcaption>' | |
| 107 | - else: | |
| 108 | - caption = '' | |
| 109 | - | |
| 110 | - return f''' | |
| 111 | - <figure class="figure"> | |
| 112 | - <img src="/file/{src}" class="figure-img img-fluid rounded" alt="{alt}" title="{title}"> | |
| 113 | - {caption} | |
| 114 | - </figure> | |
| 115 | - ''' | |
| 116 | - # return f'<img src="/file/{src}" class="img-fluid mx-auto d-block" alt="{alt}" title="{title}">' | |
| 105 | + # if title: | |
| 106 | + # caption = f'<figcaption class="figure-caption">{title}</figcaption>' | |
| 107 | + # else: | |
| 108 | + # caption = '' | |
| 109 | + | |
| 110 | + # return f''' | |
| 111 | + # <figure class="figure"> | |
| 112 | + # <img src="/file/{src}" class="figure-img img-fluid rounded" alt="{alt}" title="{title}"> | |
| 113 | + # {caption} | |
| 114 | + # </figure> | |
| 115 | + # ''' | |
| 116 | + return f'<img src="/file/{src}" class="img-fluid mx-auto d-block" alt="{alt}" title="{title}">' | |
| 117 | 117 | |
| 118 | 118 | # Pass math through unaltered - mathjax does the rendering in the browser |
| 119 | 119 | def block_math(self, text): | ... | ... |