Commit c3e0209787c7fbbfa278721544d82e6bb422aa68
1 parent
6eac0104
Exists in
master
and in
1 other branch
- fixed default correct for checkbox questions.
- fixed debug messages alignment. - updated codemirror and fontawesome links to latest versions
Showing
8 changed files
with
17 additions
and
13 deletions
Show diff stats
BUGS.md
| 1 | 1 | ||
| 2 | # BUGS | 2 | # BUGS |
| 3 | 3 | ||
| 4 | +- se aluno entrar com l12345 rebenta. numa funcao get_... ver imagem no ipad | ||
| 4 | - a revisao do teste não mostra as imagens. | 5 | - a revisao do teste não mostra as imagens. |
| 5 | - melhorar o botao de autorizar (desliga-se), usar antes um botao? | 6 | - melhorar o botao de autorizar (desliga-se), usar antes um botao? |
| 6 | e.g. retornar None quando nao ha alteracoes relativamente à última vez. | 7 | e.g. retornar None quando nao ha alteracoes relativamente à última vez. |
| @@ -19,7 +20,7 @@ ou usar push (websockets?) | @@ -19,7 +20,7 @@ ou usar push (websockets?) | ||
| 19 | - adicionar opcao para eliminar um teste em curso. | 20 | - adicionar opcao para eliminar um teste em curso. |
| 20 | - gerar teste qd o prof autoriza? melhor nao, pode apagar o teste em curso. gerar previamente e manter uma pool de testes gerados? | 21 | - gerar teste qd o prof autoriza? melhor nao, pode apagar o teste em curso. gerar previamente e manter uma pool de testes gerados? |
| 21 | - enviar resposta de cada pergunta individualmente. | 22 | - enviar resposta de cada pergunta individualmente. |
| 22 | -- experimentar gerador de svg que inclua no markdown da pergunta e ver se funciona. | 23 | +- experimentar gerador de svg que inclua no markdown da pergunta e ver se funciona. |
| 23 | - suportar cotacao to teste diferente de 20 (e.g. para juntar perguntas em papel). opcao "points: 18" que normaliza total para 18 em vez de 20. | 24 | - suportar cotacao to teste diferente de 20 (e.g. para juntar perguntas em papel). opcao "points: 18" que normaliza total para 18 em vez de 20. |
| 24 | - quando ha varias perguntas para escolher, escolher sucessivamente em vez de aleatoriamente. | 25 | - quando ha varias perguntas para escolher, escolher sucessivamente em vez de aleatoriamente. |
| 25 | - como refrescar a tabela de admin sem fazer reload da pagina? | 26 | - como refrescar a tabela de admin sem fazer reload da pagina? |
| @@ -61,6 +62,7 @@ ou usar push (websockets?) | @@ -61,6 +62,7 @@ ou usar push (websockets?) | ||
| 61 | 62 | ||
| 62 | # FIXED | 63 | # FIXED |
| 63 | 64 | ||
| 65 | +- default correct in checkbox must be 1.0, so that the pairs (right,wrong) still work with `correct` left undefined. | ||
| 64 | - textarea com codemirror | 66 | - textarea com codemirror |
| 65 | - decorador para user 0, evita o "if uid==0" em muitas funcoes. | 67 | - decorador para user 0, evita o "if uid==0" em muitas funcoes. |
| 66 | - numeric interval deve converter respostas que usam virgulas para pontos decimais | 68 | - numeric interval deve converter respostas que usam virgulas para pontos decimais |
app.py
| @@ -74,7 +74,6 @@ class App(object): | @@ -74,7 +74,6 @@ class App(object): | ||
| 74 | dbfile = path.expanduser(self.testfactory['database']) | 74 | dbfile = path.expanduser(self.testfactory['database']) |
| 75 | engine = create_engine(f'sqlite:///{dbfile}', echo=False) | 75 | engine = create_engine(f'sqlite:///{dbfile}', echo=False) |
| 76 | self.Session = sessionmaker(bind=engine) | 76 | self.Session = sessionmaker(bind=engine) |
| 77 | - | ||
| 78 | try: | 77 | try: |
| 79 | with self.db_session() as s: | 78 | with self.db_session() as s: |
| 80 | n = s.query(Student).filter(Student.id != '0').count() | 79 | n = s.query(Student).filter(Student.id != '0').count() |
| @@ -117,7 +116,7 @@ class App(object): | @@ -117,7 +116,7 @@ class App(object): | ||
| 117 | else: # check password | 116 | else: # check password |
| 118 | pw_ok = await check_password(try_pw, password) # async bcrypt | 117 | pw_ok = await check_password(try_pw, password) # async bcrypt |
| 119 | 118 | ||
| 120 | - if pw_ok: # success | 119 | + if pw_ok: # success |
| 121 | self.allowed.discard(uid) # remove from set of allowed students | 120 | self.allowed.discard(uid) # remove from set of allowed students |
| 122 | if uid in self.online: | 121 | if uid in self.online: |
| 123 | logger.warning(f'Student {uid}: already logged in.') | 122 | logger.warning(f'Student {uid}: already logged in.') |
config/logger-debug.yaml
| @@ -5,7 +5,7 @@ formatters: | @@ -5,7 +5,7 @@ formatters: | ||
| 5 | void: | 5 | void: |
| 6 | format: '' | 6 | format: '' |
| 7 | standard: | 7 | standard: |
| 8 | - format: '%(asctime)s | %(levelname)-8s | %(name)-14s | %(message)s' | 8 | + format: '%(asctime)s | %(levelname)-8s | %(name)-15s | %(message)s' |
| 9 | 9 | ||
| 10 | handlers: | 10 | handlers: |
| 11 | default: | 11 | default: |
questions.py
| @@ -154,7 +154,7 @@ class QuestionCheckbox(Question): | @@ -154,7 +154,7 @@ class QuestionCheckbox(Question): | ||
| 154 | # set defaults if missing | 154 | # set defaults if missing |
| 155 | self.set_defaults({ | 155 | self.set_defaults({ |
| 156 | 'text': '', | 156 | 'text': '', |
| 157 | - 'correct': [0.0] * n, # useful for questionaries | 157 | + 'correct': [1.0] * n, # Using 0.0 breaks the (right, wrong) options |
| 158 | 'shuffle': True, | 158 | 'shuffle': True, |
| 159 | 'discount': True, | 159 | 'discount': True, |
| 160 | 'choose': n, # number of options | 160 | 'choose': n, # number of options |
| @@ -167,7 +167,7 @@ class QuestionCheckbox(Question): | @@ -167,7 +167,7 @@ class QuestionCheckbox(Question): | ||
| 167 | # FIXME it's possible that all options are chosen wrong | 167 | # FIXME it's possible that all options are chosen wrong |
| 168 | options = [] | 168 | options = [] |
| 169 | correct = [] | 169 | correct = [] |
| 170 | - for o,c in zip(self['options'], self['correct']): | 170 | + for o, c in zip(self['options'], self['correct']): |
| 171 | if isinstance(o, list): | 171 | if isinstance(o, list): |
| 172 | r = random.randint(0,1) | 172 | r = random.randint(0,1) |
| 173 | o = o[r] | 173 | o = o[r] |
| @@ -190,7 +190,7 @@ class QuestionCheckbox(Question): | @@ -190,7 +190,7 @@ class QuestionCheckbox(Question): | ||
| 190 | if self['answer'] is not None: | 190 | if self['answer'] is not None: |
| 191 | sum_abs = sum(abs(p) for p in self['correct']) | 191 | sum_abs = sum(abs(p) for p in self['correct']) |
| 192 | if sum_abs < 1e-6: # case correct [0,...,0] avoid div-by-zero | 192 | if sum_abs < 1e-6: # case correct [0,...,0] avoid div-by-zero |
| 193 | - self['grade'] = 0.0 | 193 | + self['grade'] = 1.0 |
| 194 | 194 | ||
| 195 | else: | 195 | else: |
| 196 | x = 0.0 | 196 | x = 0.0 |
| @@ -332,7 +332,8 @@ class QuestionTextArea(Question): | @@ -332,7 +332,8 @@ class QuestionTextArea(Question): | ||
| 332 | 'correct': '' # trying to execute this will fail => grade 0.0 | 332 | 'correct': '' # trying to execute this will fail => grade 0.0 |
| 333 | }) | 333 | }) |
| 334 | 334 | ||
| 335 | - self['correct'] = path.abspath(path.normpath(path.join(self['path'], self['correct']))) # abspath will prepend cwd, which is plain wrong... | 335 | + # self['correct'] = path.join(self['path'], self['correct']) |
| 336 | + self['correct'] = path.abspath(path.normpath(path.join(self['path'], self['correct']))) | ||
| 336 | 337 | ||
| 337 | #------------------------------------------------------------------------ | 338 | #------------------------------------------------------------------------ |
| 338 | # can return negative values for wrong answers | 339 | # can return negative values for wrong answers |
serve.py
| @@ -10,14 +10,15 @@ import argparse | @@ -10,14 +10,15 @@ import argparse | ||
| 10 | import mimetypes | 10 | import mimetypes |
| 11 | import signal | 11 | import signal |
| 12 | import asyncio | 12 | import asyncio |
| 13 | -import json | ||
| 14 | import functools | 13 | import functools |
| 14 | +import json | ||
| 15 | 15 | ||
| 16 | # user installed libraries | 16 | # user installed libraries |
| 17 | import tornado.ioloop | 17 | import tornado.ioloop |
| 18 | import tornado.web | 18 | import tornado.web |
| 19 | import tornado.httpserver | 19 | import tornado.httpserver |
| 20 | from tornado import template, gen | 20 | from tornado import template, gen |
| 21 | +import yaml | ||
| 21 | 22 | ||
| 22 | # this project | 23 | # this project |
| 23 | from app import App, AppException | 24 | from app import App, AppException |
| @@ -293,7 +294,7 @@ class TestHandler(BaseHandler): | @@ -293,7 +294,7 @@ class TestHandler(BaseHandler): | ||
| 293 | # --- REVIEW ------------------------------------------------------------- | 294 | # --- REVIEW ------------------------------------------------------------- |
| 294 | class ReviewHandler(BaseHandler): | 295 | class ReviewHandler(BaseHandler): |
| 295 | SUPPORTED_METHODS = ['GET'] | 296 | SUPPORTED_METHODS = ['GET'] |
| 296 | - | 297 | + |
| 297 | _templates = { | 298 | _templates = { |
| 298 | 'radio': 'review-question-radio.html', | 299 | 'radio': 'review-question-radio.html', |
| 299 | 'checkbox': 'review-question-checkbox.html', | 300 | 'checkbox': 'review-question-checkbox.html', |
| @@ -327,6 +328,7 @@ class ReviewHandler(BaseHandler): | @@ -327,6 +328,7 @@ class ReviewHandler(BaseHandler): | ||
| 327 | else: | 328 | else: |
| 328 | with f: | 329 | with f: |
| 329 | t = json.load(f) | 330 | t = json.load(f) |
| 331 | + # print(yaml.dump(t, default_flow_style=False)) | ||
| 330 | self.render('review.html', t=t, md=md_to_html, templ=self._templates) | 332 | self.render('review.html', t=t, md=md_to_html, templ=self._templates) |
| 331 | 333 | ||
| 332 | 334 |
static/codemirror
static/fontawesome.min.js
test.py
| @@ -191,7 +191,7 @@ class TestFactory(dict): | @@ -191,7 +191,7 @@ class TestFactory(dict): | ||
| 191 | 'debug': self['debug'], # required by template test.html | 191 | 'debug': self['debug'], # required by template test.html |
| 192 | 'database': self['database'], | 192 | 'database': self['database'], |
| 193 | 'questions_dir': self['questions_dir'], | 193 | 'questions_dir': self['questions_dir'], |
| 194 | - 'files': self['files'], | 194 | + # 'files': self['files'], |
| 195 | }) | 195 | }) |
| 196 | 196 | ||
| 197 | # ----------------------------------------------------------------------- | 197 | # ----------------------------------------------------------------------- |