Commit 2290803dba73b806dfb492d8df0396dceeaff342
1 parent
c74f28c0
Exists in
master
and in
1 other branch
- added demo questions, test and scripts
- changed default question type to 'information'.
Showing
7 changed files
with
178 additions
and
13 deletions
Show diff stats
MANUAL.md
... | ... | @@ -260,7 +260,6 @@ A generator question will run an external program that is expected to print a qu |
260 | 260 | |
261 | 261 | An example of a question generator is the following |
262 | 262 | |
263 | - :::python linenums="True" | |
264 | 263 | #!/usr/bin/env python3.4 |
265 | 264 | from random import randint |
266 | 265 | ... | ... |
... | ... | @@ -0,0 +1,16 @@ |
1 | +#!/usr/bin/env python3.4 | |
2 | + | |
3 | +import sys | |
4 | +s = sys.stdin.read() | |
5 | + | |
6 | +# set of words converted to lowercase lowercase | |
7 | +answer = set(re.findall(r'[\w]+', s.lower())) | |
8 | + | |
9 | +# correct set of colors | |
10 | +rgb_colors = set(['red', 'green', 'blue']) | |
11 | + | |
12 | +if answer == rgb_colors: | |
13 | + print(1.0) | |
14 | +else: | |
15 | + print(0.0) | |
16 | +exit(0) | |
0 | 17 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,21 @@ |
1 | +#!/usr/bin/env python3.4 | |
2 | + | |
3 | +from random import randint | |
4 | + | |
5 | + | |
6 | +q = ''' | |
7 | +type: checkbox | |
8 | +text: Indique quais das seguintes adições resultam em overflow quando se considera a adição de números com sinal (complemento para 2) em registos de 8 bits. | |
9 | +options: | |
10 | +''' | |
11 | + | |
12 | +correct = [] | |
13 | +for i in range(5): | |
14 | + x = randint(11,120) | |
15 | + y = randint(11,120) | |
16 | + q += '- "`{} + {}`"\n'.format(x, y) | |
17 | + correct.append(1 if x + y > 127 else -1) | |
18 | + | |
19 | +q += 'correct: ' + str(correct) | |
20 | + | |
21 | +print(q) | ... | ... |
... | ... | @@ -0,0 +1,72 @@ |
1 | +- | |
2 | + ref: solar-system-mars | |
3 | + type: radio | |
4 | + text: Choose the correct answer | |
5 | + options: | |
6 | + - This one is correct | |
7 | + - Wrong | |
8 | + - Very wrong! | |
9 | + # optional | |
10 | + correct: 0 | |
11 | + shuffle: True | |
12 | + discount: True | |
13 | + hint: Just don't choose the wrong ones | |
14 | +# --------------------------------------------------------------------------- | |
15 | +- | |
16 | + ref: solar-system-jupiter | |
17 | + type: checkbox | |
18 | + text: Which ones are correct? | |
19 | + options: | |
20 | + - Yes | |
21 | + - No | |
22 | + - Yes | |
23 | + - Obvious one, not very important | |
24 | + correct: [1, -1, 1, 0.5] | |
25 | + hint: There are three. | |
26 | +# --------------------------------------------------------------------------- | |
27 | +- | |
28 | + ref: solar-system-venus | |
29 | + type: text | |
30 | + text: What's your favorite basic color? | |
31 | + correct: ['blue', 'green'] | |
32 | + hint: It's not red. | |
33 | +# --------------------------------------------------------------------------- | |
34 | +- | |
35 | + ref: question-v1 | |
36 | + type: text_regex | |
37 | + text: What's your favorite basic color? | |
38 | + correct: '[bB]lue' | |
39 | + hint: It's not red. | |
40 | +# --------------------------------------------------------------------------- | |
41 | +- | |
42 | + ref: question-v2 | |
43 | + type: textarea | |
44 | + text: Write names of the three basic colors. | |
45 | + correct: demo/correct-question.py | |
46 | + hint: They start by RGB and order does not matter. | |
47 | +# --------------------------------------------------------------------------- | |
48 | +- | |
49 | + ref: question-v3 | |
50 | + type: generator | |
51 | + script: demo/generate-question.py | |
52 | + # the script should print a question in yaml format like the ones above. | |
53 | + # Print only the dictionary, not the list (hiffen). | |
54 | +# --------------------------------------------------------------------------- | |
55 | +- | |
56 | + ref: one-question | |
57 | + type: information | |
58 | + text: Please do not cheat. | |
59 | +# --------------------------------------------------------------------------- | |
60 | +- | |
61 | + ref: another-question | |
62 | + # type: information (default) | |
63 | + text: | | |
64 | + The text of questions is parsed as __markdown__ and can include | |
65 | + LaTeX formulas $\sqrt{2\pi}$ and pretty code | |
66 | + | |
67 | + ```.C | |
68 | + int main() { | |
69 | + return 0; | |
70 | + } | |
71 | + ``` | |
72 | + | ... | ... |
... | ... | @@ -0,0 +1,56 @@ |
1 | +#============================================================================= | |
2 | +ref: demo | |
3 | +title: Teste de Demonstração | |
4 | + | |
5 | +# database contains students+passwords, final results of the tests, and questions done | |
6 | +# database: path/to/students.db | |
7 | +database: db/asc1-students.db | |
8 | + | |
9 | +# this will generate a file for each test done. The file is like a replacement | |
10 | +# for a test done in paper. | |
11 | +save_answers: False | |
12 | +# answers_dir: path/to/directory | |
13 | + | |
14 | +show_points: True | |
15 | +show_hints: True | |
16 | +practice: True | |
17 | +# debug: False | |
18 | + | |
19 | +# When in practice mode and an answer is wrong (i.e. less that 0.5 correct), | |
20 | +# an insult is chosen from the list (optional) | |
21 | +offensive: | |
22 | + - Ó meu grande asno, então não sabes esta? | |
23 | + - Pois, pois... não estudes não... | |
24 | + - E eu sou o Elvis Presley... | |
25 | + - Pois, e bróculos também. | |
26 | + | |
27 | +#----------------------------------------------------------------------------- | |
28 | +# List of files containing questions in yaml format. | |
29 | +# Selected questions will be obtained from these files. | |
30 | +files: | |
31 | + - demo/questions.yaml | |
32 | +#----------------------------------------------------------------------------- | |
33 | +# This is the list of questions. If a "ref:" has a list of keys, then | |
34 | +# one question is selected from the list. | |
35 | +# The following example will generate a test with 3 questions. | |
36 | +questions: | |
37 | + # first | |
38 | + - ref: | |
39 | + # choose 1 from the following 3 questions | |
40 | + - solar-system-mars | |
41 | + - solar-system-jupiter | |
42 | + - solar-system-venus | |
43 | + points: 0.5 | |
44 | + | |
45 | + # second | |
46 | + - ref: | |
47 | + - question-v1 | |
48 | + - question-v2 | |
49 | + - question-v3 | |
50 | + # points: 1.0 is the default, if not defined here. | |
51 | + | |
52 | + # third | |
53 | + - ref: one-question | |
54 | + | |
55 | + # fourth | |
56 | + - another-question | ... | ... |
questions.py
... | ... | @@ -3,6 +3,7 @@ import yaml |
3 | 3 | import random |
4 | 4 | import re |
5 | 5 | import subprocess |
6 | +import os | |
6 | 7 | |
7 | 8 | # Example usage: |
8 | 9 | # |
... | ... | @@ -29,8 +30,8 @@ class QuestionsPool(dict): |
29 | 30 | with open(filename, 'r') as f: |
30 | 31 | questions = yaml.load(f) |
31 | 32 | except(FileNotFoundError): |
32 | - print(' * Questions file "%s" not found. Ignoring...' % filename) | |
33 | - return | |
33 | + print(' * Questions file "%s" not found. Aborting...' % filename) | |
34 | + os.sys.exit(1) | |
34 | 35 | |
35 | 36 | # add defaults if missing from sources |
36 | 37 | for i, q in enumerate(questions): |
... | ... | @@ -45,8 +46,8 @@ class QuestionsPool(dict): |
45 | 46 | # ref (if missing, add 'filename.yaml:3') |
46 | 47 | q['ref'] = str(q.get('ref', filename + ':' + str(i))) |
47 | 48 | |
48 | - # type (default type is just '') | |
49 | - q['type'] = str(q.get('type', '')) | |
49 | + # type (default type is 'information') | |
50 | + q['type'] = str(q.get('type', 'information')) | |
50 | 51 | |
51 | 52 | # add question to the pool |
52 | 53 | self[q['ref']] = q |
... | ... | @@ -78,19 +79,19 @@ def create_question(q): |
78 | 79 | 'checkbox' : QuestionCheckbox, |
79 | 80 | 'text' : QuestionText, |
80 | 81 | 'text_regex': QuestionTextRegex, |
81 | - 'text-regex': QuestionTextRegex, | |
82 | - 'regex' : QuestionTextRegex, | |
82 | + # 'text-regex': QuestionTextRegex, | |
83 | + # 'regex' : QuestionTextRegex, | |
83 | 84 | 'textarea' : QuestionTextArea, |
84 | 85 | 'information': QuestionInformation, |
85 | - 'info' : QuestionInformation, | |
86 | - '' : QuestionInformation, # default | |
86 | + # 'info' : QuestionInformation, | |
87 | + # '' : QuestionInformation, # default | |
87 | 88 | } |
88 | 89 | |
89 | 90 | # create instance of given type |
90 | 91 | try: |
91 | 92 | questiontype = types[q['type']] |
92 | 93 | except KeyError: |
93 | - print(' * unsupported question type in "%s:%s".' % (q['filename'], q['ref'])) | |
94 | + print(' * unsupported question type "{0}" in "{1}:{2}".'.format(q['type'], q['filename'], q['ref'])) | |
94 | 95 | questiontype = Question |
95 | 96 | |
96 | 97 | # create question instance and return | ... | ... |
test.py
... | ... | @@ -8,7 +8,7 @@ from datetime import datetime |
8 | 8 | import questions |
9 | 9 | import database |
10 | 10 | |
11 | -# ============================================================================ | |
11 | +# =========================================================================== | |
12 | 12 | def read_configuration(filename, debug=False, show_points=False, show_hints=False, practice=False, save_answers=False): |
13 | 13 | # FIXME validar se ficheiros e directorios existem??? |
14 | 14 | if not os.path.isfile(filename): |
... | ... | @@ -35,7 +35,7 @@ def read_configuration(filename, debug=False, show_points=False, show_hints=Fals |
35 | 35 | |
36 | 36 | if 'database' not in test: |
37 | 37 | print(' * Missing database in the test configuration.') |
38 | - sys.exit(1) | |
38 | + os.sys.exit(1) | |
39 | 39 | |
40 | 40 | if isinstance(test['files'], str): |
41 | 41 | test['files'] = [test['files']] |
... | ... | @@ -67,7 +67,7 @@ def read_configuration(filename, debug=False, show_points=False, show_hints=Fals |
67 | 67 | |
68 | 68 | return test |
69 | 69 | |
70 | -# ============================================================================ | |
70 | +# =========================================================================== | |
71 | 71 | class Test(dict): |
72 | 72 | # ----------------------------------------------------------------------- |
73 | 73 | def __init__(self, d): | ... | ... |