Commit bd2ad2b73a8a0f4de7b7e1dbb42af531712b2680
1 parent
eeb28a09
Exists in
master
and in
1 other branch
- fix references to python3.6/3.7 in README.
- fix and update demo. - fix striping <p></p> tags in certain cases in the md_to_html function.
Showing
8 changed files
with
69 additions
and
44 deletions
Show diff stats
BUGS.md
@@ -3,7 +3,6 @@ | @@ -3,7 +3,6 @@ | ||
3 | 3 | ||
4 | - click numa opcao checkbox fora da checkbox+label não está a funcionar. | 4 | - click numa opcao checkbox fora da checkbox+label não está a funcionar. |
5 | - shift-enter não está a funcionar | 5 | - shift-enter não está a funcionar |
6 | -- nos topicos learn.yaml, qd falha acrescenta no fim. nao faz sentido. | ||
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. | 6 | - 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. |
8 | - default prefix should be obtained from each course (yaml conf)? | 7 | - default prefix should be obtained from each course (yaml conf)? |
9 | - tabelas nas perguntas radio/checkbox não ocupam todo o espaço como em question. | 8 | - tabelas nas perguntas radio/checkbox não ocupam todo o espaço como em question. |
@@ -29,6 +28,8 @@ | @@ -29,6 +28,8 @@ | ||
29 | 28 | ||
30 | # FIXED | 29 | # FIXED |
31 | 30 | ||
31 | +- nos topicos learn.yaml, qd falha acrescenta no fim. nao faz sentido. | ||
32 | +- não esta a fazer render correcto de tabelas nas opcoes checkbox. e.g. information-theory/source-coding-theory/block-codes | ||
32 | - max tries nas perguntas. | 33 | - max tries nas perguntas. |
33 | - mostrar feedback/solucoes quando acerta, ou excede max tries. | 34 | - mostrar feedback/solucoes quando acerta, ou excede max tries. |
34 | - quando se pressiona "responde" rapido (enquanto a animacao dura), a pergunta passa para a seguinte sem haver o correspondente redraw, ou seja a proxima resposta nao é a da pergunta mostrada. | 35 | - quando se pressiona "responde" rapido (enquanto a animacao dura), a pergunta passa para a seguinte sem haver o correspondente redraw, ou seja a proxima resposta nao é a da pergunta mostrada. |
README.md
@@ -37,7 +37,7 @@ python3.7 -m ensurepip --user | @@ -37,7 +37,7 @@ python3.7 -m ensurepip --user | ||
37 | ``` | 37 | ``` |
38 | 38 | ||
39 | This will install pip in your user account under `~/.local/bin`. | 39 | This will install pip in your user account under `~/.local/bin`. |
40 | -In the end you should be able to run `pip3 --version` and `python3 -c "import sqlite3"` without errors (sometimes `pip3` is `pip`, `pip3.6` or `pip-3.6`). | 40 | +In the end you should be able to run `pip3 --version` and `python3 -c "import sqlite3"` without errors (sometimes `pip3` is `pip`, `pip3.7` or `pip-3.7`). |
41 | 41 | ||
42 | If you want to always install python modules on the user account (recommended), edit the pip configuration file `~/.config/pip/pip.conf` (FreeBSD, Linux) or `Library/Application Support/pip/pip.conf` (MacOS) and add the lines | 42 | If you want to always install python modules on the user account (recommended), edit the pip configuration file `~/.config/pip/pip.conf` (FreeBSD, Linux) or `Library/Application Support/pip/pip.conf` (MacOS) and add the lines |
43 | 43 | ||
@@ -93,7 +93,7 @@ cd aprendizations | @@ -93,7 +93,7 @@ cd aprendizations | ||
93 | 93 | ||
94 | We need certificates for https. Certificates can be self-signed or validated by a trusted authority. | 94 | We need certificates for https. Certificates can be self-signed or validated by a trusted authority. |
95 | 95 | ||
96 | -Self-signed can be used locally for development and testing, but browsers will complain. | 96 | +Self-signed can be used locally for development and testing, but browsers will complain. |
97 | LetsEncrypt issues trusted and free certificates, but the server must have a registered publicly accessible domain name. | 97 | LetsEncrypt issues trusted and free certificates, but the server must have a registered publicly accessible domain name. |
98 | 98 | ||
99 | #### Selfsigned | 99 | #### Selfsigned |
demo/demo.yaml
1 | +--- | ||
2 | + | ||
1 | title: Example | 3 | title: Example |
2 | database: students.db | 4 | database: students.db |
3 | -# path: ./demo | 5 | + |
4 | 6 | ||
5 | # values applie to each topic, if undefined there | 7 | # values applie to each topic, if undefined there |
6 | # default values are: file=question.yaml, shuffle=True, choose: all | 8 | # default values are: file=question.yaml, shuffle=True, choose: all |
7 | file: questions.yaml | 9 | file: questions.yaml |
8 | -shuffle: True | 10 | +shuffle: false |
9 | choose: 6 | 11 | choose: 6 |
12 | +max_tries: 2 | ||
10 | forgetting_factor: 0.99 | 13 | forgetting_factor: 0.99 |
11 | 14 | ||
12 | -# Representation of the edges of the dependency graph. | ||
13 | -# Example: A depends on B and C | ||
14 | -# A: | ||
15 | -# name: Topic A | ||
16 | -# deps: | ||
17 | -# - B | ||
18 | -# - C | 15 | +# ---------------------------------------------------------------------------- |
19 | topics: | 16 | topics: |
20 | # topic without dependencies | 17 | # topic without dependencies |
21 | math: | 18 | math: |
22 | name: Matemática | 19 | name: Matemática |
23 | file: questions.yaml | 20 | file: questions.yaml |
24 | choose: 6 | 21 | choose: 6 |
25 | - shuffle: True | 22 | + shuffle: true |
26 | 23 | ||
27 | # topic with one dependency | 24 | # topic with one dependency |
28 | solar_system: | 25 | solar_system: |
demo/solar_system/questions.yaml
1 | --- | 1 | --- |
2 | 2 | ||
3 | # --------------------------------------------------------------------------- | 3 | # --------------------------------------------------------------------------- |
4 | -- ref: solar-system | ||
5 | - type: radio | 4 | +- type: checkbox |
5 | + ref: teste-debug | ||
6 | + title: tabelas em opcoes | ||
7 | + text: ve la se as tabelas estao bem... | ||
8 | + options: | ||
9 | + - | | ||
10 | + x | y | ||
11 | + --|-- | ||
12 | + 1 | 2 | ||
13 | + - | | ||
14 | + x | y | ||
15 | + --|-- | ||
16 | + 1 | 2 | ||
17 | + correct: [1, 1] | ||
18 | + | ||
19 | +# --------------------------------------------------------------------------- | ||
20 | +- type: radio | ||
21 | + ref: teste-debug2 | ||
22 | + title: formuolas em opcoes | ||
23 | + text: ve la se as tabelas estao bem... | ||
24 | + options: | ||
25 | + - A | ||
26 | + - B | ||
27 | +# --------------------------------------------------------------------------- | ||
28 | +- type: text | ||
29 | + ref: home-planet | ||
30 | + title: Sistema solar | ||
31 | + text: O nosso planeta chama-se planeta... | ||
32 | + correct: ['Terra', 'terra'] | ||
33 | + # opcional | ||
34 | + answer: Não é Marte... | ||
35 | + | ||
36 | +# --------------------------------------------------------------------------- | ||
37 | +- type: radio | ||
38 | + ref: solar-system | ||
6 | title: Sistema solar | 39 | title: Sistema solar |
7 | text: | | 40 | text: | |
8 |  | 41 |  |
@@ -16,30 +49,20 @@ | @@ -16,30 +49,20 @@ | ||
16 | - Têm todos o mesmo tamanho | 49 | - Têm todos o mesmo tamanho |
17 | # opcional | 50 | # opcional |
18 | correct: 2 | 51 | correct: 2 |
19 | - shuffle: False | ||
20 | - discount: True | 52 | + shuffle: false |
53 | + discount: true | ||
21 | 54 | ||
22 | -# --------------------------------------------------------------------------- | ||
23 | -- | ||
24 | - ref: home-planet | ||
25 | - type: text | ||
26 | - title: Sistema solar | ||
27 | - text: O nosso planeta chama-se planeta... | ||
28 | - correct: ['Terra', 'terra'] | ||
29 | - # opcional | ||
30 | - answer: Não é Marte... | ||
31 | 55 | ||
32 | # --------------------------------------------------------------------------- | 56 | # --------------------------------------------------------------------------- |
33 | -- | ||
34 | - ref: saturn | ||
35 | - type: text-regex | ||
36 | - title: Sistema solar | ||
37 | - text: O planeta do sistema solar conhecido por ter aneis é o planeta... | ||
38 | - correct: !regex '[Ss]aturno' | 57 | +- type: text-regex |
58 | + ref: saturn | ||
59 | + title: Sistema solar | ||
60 | + text: O planeta do sistema solar conhecido por ter aneis é o planeta... | ||
61 | + correct: !regex '[Ss]aturno' | ||
39 | 62 | ||
40 | # --------------------------------------------------------------------------- | 63 | # --------------------------------------------------------------------------- |
41 | -- ref: first_3_planets | ||
42 | - type: textarea | 64 | +- type: textarea |
65 | + ref: first_3_planets | ||
43 | title: Sistema solar | 66 | title: Sistema solar |
44 | text: Escreva o nome dos três planetas mais próximos do Sol. (Exemplo `A, B e C`) | 67 | text: Escreva o nome dos três planetas mais próximos do Sol. (Exemplo `A, B e C`) |
45 | correct: correct-first_3_planets.py | 68 | correct: correct-first_3_planets.py |
serve.py
@@ -23,7 +23,7 @@ from learnapp import LearnApp | @@ -23,7 +23,7 @@ from learnapp import LearnApp | ||
23 | from tools import load_yaml, md_to_html | 23 | from tools import load_yaml, md_to_html |
24 | 24 | ||
25 | # ---------------------------------------------------------------------------- | 25 | # ---------------------------------------------------------------------------- |
26 | -# Decorator used to restrict access to the administrator | 26 | +# Decorator used to restrict access to the administrator only |
27 | # ---------------------------------------------------------------------------- | 27 | # ---------------------------------------------------------------------------- |
28 | def admin_only(func): | 28 | def admin_only(func): |
29 | @functools.wraps(func) | 29 | @functools.wraps(func) |
@@ -96,7 +96,7 @@ class LoginHandler(BaseHandler): | @@ -96,7 +96,7 @@ class LoginHandler(BaseHandler): | ||
96 | login_ok = await self.learn.login(uid, pw) | 96 | login_ok = await self.learn.login(uid, pw) |
97 | 97 | ||
98 | if login_ok: | 98 | if login_ok: |
99 | - self.set_secure_cookie('user', uid) # expires_days=30 | 99 | + self.set_secure_cookie('user', uid) |
100 | self.set_secure_cookie('counter', str(self.learn.get_login_counter(uid))) | 100 | self.set_secure_cookie('counter', str(self.learn.get_login_counter(uid))) |
101 | self.redirect('/') | 101 | self.redirect('/') |
102 | else: | 102 | else: |
@@ -198,7 +198,6 @@ class FileHandler(BaseHandler): | @@ -198,7 +198,6 @@ class FileHandler(BaseHandler): | ||
198 | self.set_header("Content-Type", content_type) | 198 | self.set_header("Content-Type", content_type) |
199 | self.write(data) | 199 | self.write(data) |
200 | await self.flush() | 200 | await self.flush() |
201 | - # self.flush() | ||
202 | 201 | ||
203 | 202 | ||
204 | # ---------------------------------------------------------------------------- | 203 | # ---------------------------------------------------------------------------- |
@@ -216,8 +215,9 @@ class QuestionHandler(BaseHandler): | @@ -216,8 +215,9 @@ class QuestionHandler(BaseHandler): | ||
216 | 'textarea': 'question-textarea.html', | 215 | 'textarea': 'question-textarea.html', |
217 | # -- information panels -- | 216 | # -- information panels -- |
218 | 'information': 'question-information.html', | 217 | 'information': 'question-information.html', |
219 | - 'info': 'question-information.html', | ||
220 | 'success': 'question-success.html', | 218 | 'success': 'question-success.html', |
219 | + 'warning': 'question-information.html', | ||
220 | + 'alert': 'question-information.html', | ||
221 | } | 221 | } |
222 | 222 | ||
223 | # --- get question to render | 223 | # --- get question to render |
templates/question-checkbox.html
@@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
9 | <div class="custom-control custom-checkbox"> | 9 | <div class="custom-control custom-checkbox"> |
10 | <input type="checkbox" class="custom-control-input" | 10 | <input type="checkbox" class="custom-control-input" |
11 | id="{{ n }}" accesskey="{{ n+1 }}" name="answer" value="{{ n }}"> | 11 | id="{{ n }}" accesskey="{{ n+1 }}" name="answer" value="{{ n }}"> |
12 | - <label for="{{ n }}" class="custom-control-label">{{ md(opt)[3:-5] }}</label> | 12 | + <label for="{{ n }}" class="custom-control-label">{{ md(opt, strip_p_tag=True) }}</label> |
13 | </div> | 13 | </div> |
14 | </a> | 14 | </a> |
15 | {% end %} | 15 | {% end %} |
templates/question-radio.html
@@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
9 | <div class="custom-control custom-radio"> | 9 | <div class="custom-control custom-radio"> |
10 | <input type="radio" class="custom-control-input" | 10 | <input type="radio" class="custom-control-input" |
11 | id="{{ n }}" accesskey="{{ n+1 }}" name="answer" value="{{ n }}"> | 11 | id="{{ n }}" accesskey="{{ n+1 }}" name="answer" value="{{ n }}"> |
12 | - <label for="{{ n }}" class="custom-control-label">{{ md(opt)[3:-5] }}</label> | 12 | + <label for="{{ n }}" class="custom-control-label">{{ md(opt, strip_p_tag=True) }}</label> |
13 | </div> | 13 | </div> |
14 | </a> | 14 | </a> |
15 | {% end %} | 15 | {% end %} |
tools.py
1 | 1 | ||
2 | -# builtin | 2 | +# python standard library |
3 | from os import path | 3 | from os import path |
4 | import subprocess | 4 | import subprocess |
5 | import logging | 5 | import logging |
6 | import re | 6 | import re |
7 | 7 | ||
8 | -# packages | 8 | +# user installed libraries |
9 | import yaml | 9 | import yaml |
10 | import mistune | 10 | import mistune |
11 | from pygments import highlight | 11 | from pygments import highlight |
@@ -117,8 +117,12 @@ class HighlightRenderer(mistune.Renderer): | @@ -117,8 +117,12 @@ class HighlightRenderer(mistune.Renderer): | ||
117 | 117 | ||
118 | markdown = MarkdownWithMath(HighlightRenderer(escape=True)) # hard_wrap=True to insert <br> on newline | 118 | markdown = MarkdownWithMath(HighlightRenderer(escape=True)) # hard_wrap=True to insert <br> on newline |
119 | 119 | ||
120 | -def md_to_html(text, q=None): | ||
121 | - return markdown(text) | 120 | +def md_to_html(text, strip_p_tag=False, q=None): |
121 | + md = markdown(text) | ||
122 | + if strip_p_tag and md.startswith('<p>') and md.endswith('</p>'): | ||
123 | + return md[3:-5] | ||
124 | + else: | ||
125 | + return md | ||
122 | 126 | ||
123 | # --------------------------------------------------------------------------- | 127 | # --------------------------------------------------------------------------- |
124 | # load data from yaml file | 128 | # load data from yaml file |