Commit f3635fa022e624a62b9941073656563a3ecec6e3

Authored by Miguel Barão
1 parent a0ab1672
Exists in master and in 1 other branch dev

minor reorganization

update BUGS
  1 +# Perguntations
1 2
2 -# BUGS 3 +## BUGS
3 4
4 -- correct devia poder ser corrido mais que uma vez (por exemplo para alterar cotacoes, corrigir perguntas)  
5 -- guardar testes em JSON assim que sao atribuidos aos alunos (ou guardados inicialmente com um certo nome, e atribuidos posteriormente ao aluno).  
6 -- cookies existe um perguntations_user e um user. De onde vem o user?  
7 -- QuestionCode falta reportar nos comments os vários erros que podem ocorrer (timeout, etc)  
8 -- algumas vezes a base de dados guarda o mesmo teste em duplicado. ver se dois submits dao origem a duas correcções.  
9 -talvez a base de dados devesse ter como chave do teste um id que fosse único desse teste particular (não um auto counter, nem ref do teste)  
10 -- em caso de timeout na submissão (e.g. JOBE ou script nao responde) a correcção não termina e o teste não é guardado.  
11 -- grade gives internal server error?? 5 +- talvez a base de dados devesse ter como chave do teste um id que fosse único
  6 + desse teste particular (não um auto counter, nem ref do teste)
  7 +- em caso de timeout na submissão (e.g. JOBE ou script nao responde) a correcção
  8 + não termina e o teste não é guardado.
12 - reload do teste recomeça a contagem no inicio do tempo. 9 - reload do teste recomeça a contagem no inicio do tempo.
13 -- em admin, quando scale_max não é 20, as cores das barras continuam a reflectir a escala 0,20. a tabela teste na DB não tem a escala desse teste.  
14 -- em grade.html as barras estao normalizadas para os limites scale_min e max do teste actual e nao dos testes realizados no passado (tabela test devia guardar a escala).  
15 -- codigo `hello world` nao esta a preservar o whitespace. O renderer de markdown gera a tag <code> que não preserva whitespace. Necessario adicionar <pre>.  
16 -- mensagems de erro do assembler aparecem na mesma linha na correcao e nao fazerm rendering do `$t`, ver se servidor faz parse do markdown dessas mensagens.  
17 -- a revisao do teste não mostra as imagens.  
18 -- Test.reset_answers() unused.  
19 -- teste nao esta a mostrar imagens de vez em quando.???  
20 -- show-ref nao esta a funcionar na correccao (pelo menos) 10 +- em admin, quando scale_max não é 20, as cores das barras continuam a reflectir
  11 + a escala 0,20. a tabela teste na DB não tem a escala desse teste.
  12 +- mensagems de erro do assembler aparecem na mesma linha na correcao e nao
  13 + fazerm rendering do `$t`, ver se servidor faz parse do markdown dessas
  14 + mensagens.
  15 +- a revisao do teste não mostra as imagens que nao estejam ja em cache.
21 16
22 -# TODO 17 +## TODO
23 18
24 -- JOBE correct async  
25 -- esta a corrigir código JOBE mesmo que nao tenha respondido???  
26 -- permitir remover alunos que estão online para poderem comecar de novo.  
27 -- guardar nota final grade truncado em zero e sem ser truncado (quando é necessário fazer correcções à mão às perguntas, é necessário o valor não truncado)  
28 -- stress tests. use https://locust.io  
29 -- wait for admin to start test. (students can be allowed earlier)  
30 -- impedir os eventos copy/paste. alunos usam isso para trazer codigo ja feito nos computadores. Obrigar a fazer reset? fazer um copy automaticamente?  
31 -- na pagina admin, mostrar com cor vermelha as horas de entrada dos alunos que ja tenham excedido o tempo  
32 -- retornar None quando nao ha alteracoes relativamente à última vez.  
33 -ou usar push (websockets?) 19 +- QuestionTextArea falta reportar nos comments os vários erros que podem ocorrer
  20 + (timeout, etc)
  21 +- pergunta com varias partes.
  22 +- /review incluir identificacao do aluno no jumbotron (para poder gerar pdf).
  23 +- corrir mais que uma vez (por ex. para alterar cotacoes, corrigir perguntas)
  24 +- guardar testes em JSON assim que sao atribuidos aos alunos.
  25 +- impedir os eventos copy/paste. alunos usam isso para trazer codigo ja feito
  26 + nos computadores. Obrigar a fazer reset? fazer um copy automaticamente?
  27 +- na pagina admin, mostrar com cor vermelha as horas de entrada dos alunos que
  28 + ja tenham excedido o tempo
  29 +- /admin long pooling.
34 - mudar ref do test para test_id (ref já é usado nas perguntas) 30 - mudar ref do test para test_id (ref já é usado nas perguntas)
35 - servidor ntpd no x220 para configurar a data/hora dos portateis dell 31 - servidor ntpd no x220 para configurar a data/hora dos portateis dell
36 -- sala de espera: autorização dada, mas teste não disponível até que seja dada ordem para começar.  
37 -- alunos com necessidades especiais nao podem ter autosubmit. ter um autosubmit_exceptions: ['123', '456']  
38 -- submissao fazer um post ajax?  
39 -- adicionar opcao para eliminar um teste em curso. 32 +- sala de espera: autorização dada, mas teste não disponível até que seja dada
  33 + ordem para começar.
  34 +- alunos com necessidades especiais nao podem ter autosubmit. ter um
  35 + autosubmit_exceptions: ['123', '456']
40 - enviar resposta de cada pergunta individualmente. 36 - enviar resposta de cada pergunta individualmente.
41 -- experimentar gerador de svg que inclua no markdown da pergunta e ver se funciona.  
42 -- quando ha varias perguntas para escolher, escolher sucessivamente em vez de aleatoriamente.  
43 -- como refrescar a tabela de admin sem fazer reload da pagina?  
44 -- botao "testar resposta" que valida codigo relativamente a syntax, mas nao classifica. perguntas devem ter opcao validate: script.py. Aluno pressiona botao e codigo é enviado para servidor para validação, feedback é mostrado na pagina de teste.  
45 -- test: botao submeter valida se esta online com um post willing_to_submit, se estiver online, mostra mensagem de confirmacao, caso contrario avisa que nao esta online. 37 +- experimentar gerador de svg que inclua no markdown da pergunta.
  38 +- botao "testar resposta" que valida syntax mas nao classifica.
  39 + perguntas devem ter opcao validate: script.py.
  40 + Aluno pressiona botao e codigo é enviado para servidor para validação,
  41 +- test: botao submeter valida se esta online com um post willing_to_submit,
  42 + se estiver online, mostra mensagem de confirmacao, caso contrario avisa que
  43 + nao esta online.
46 - test: Cada pergunta respondida é logo submetida. 44 - test: Cada pergunta respondida é logo submetida.
47 -- test: calculadora javascript.  
48 - admin: histograma das notas. 45 - admin: histograma das notas.
49 - admin: mostrar as horas a que o teste terminou para os testes terminados. 46 - admin: mostrar as horas a que o teste terminou para os testes terminados.
50 - admin: histograma das notas. 47 - admin: histograma das notas.
51 - admin: mostrar teste gerado para aluno (tipo review). 48 - admin: mostrar teste gerado para aluno (tipo review).
52 -- fazer renderer para formulas com mathjax serverside (mathjax-node) ou usar katex.  
53 -- fazer renderer para imagens, com links /file?ref=xpto;name=zzz.jpg  
54 -- fazer renderer para linguagem assembly mips?  
55 -- cancelar teste no menu admin. Dado o numero de aluno remove teste e faz logout do aluno. 49 +- admin: Cancelar teste e fazer logout do aluno (e.g. fraude)
56 - mathjax-node: 50 - mathjax-node:
57 sudo pkg install node npm 51 sudo pkg install node npm
58 npm install mathjax-node mathjax-node-cli # pacotes em ~/node_modules 52 npm install mathjax-node mathjax-node-cli # pacotes em ~/node_modules
59 node_modules/mathjax-node-cli/bin/tex2svg '\sqrt{x}' 53 node_modules/mathjax-node-cli/bin/tex2svg '\sqrt{x}'
60 - usar isto para gerar svg que passa a fazer parte do texto da pergunta (markdown suporta tags svg?) 54 + usar isto para gerar svg que passa a fazer parte do texto da pergunta
  55 + (markdown suporta tags svg?)
61 fazer funçao tex() que recebe formula e converte para svg. exemplo: 56 fazer funçao tex() que recebe formula e converte para svg. exemplo:
62 fr'''A formula é {tex("\sqrt{x]}")}''' 57 fr'''A formula é {tex("\sqrt{x]}")}'''
63 -- Gerar pdf's com todos os testes no final (pdfkit).  
64 -- manter registo dos unfocus durante o teste e de qual a pergunta visivel nesse momento 58 +- Gerar pdf's com todos os testes no final (pdfkit, firefox marionette).
  59 +- registos unfocus durante o teste e qual a pergunta visivel nesse momento
65 - permitir varios testes, aluno escolhe qual o teste que quer fazer. 60 - permitir varios testes, aluno escolhe qual o teste que quer fazer.
66 - se ocorrer um erro na correcçao avisar aluno para contactar o professor. 61 - se ocorrer um erro na correcçao avisar aluno para contactar o professor.
67 -- abrir o teste numa janela maximizada e que nao permite que o aluno a redimensione/mova?  
68 -- detectar scroll e enviar posição para servidor (analise de scroll para detectar copianço? ou simplesmente para analisar como os alunos percorrem o teste)  
69 -- aviso na pagina principal para quem usa browser incompativel ou settings esquisitos... Apos login pode ser enviado e submetido um exemplo de teste para verificar se browser consegue submeter? ha alunos com javascript bloqueado?  
70 -- criar perguntas de outros tipos, e.g. associação, ordenação, varios textinput  
71 -- perguntas para professor corrigir mais tarde. permitir que review possa alterar as notas  
72 -- fazer uma calculadora javascript e por no menu. surge como modal  
73 -  
74 -# FIXED  
75 -  
76 -- testar as perguntas todas no início do teste como o aprendizations.  
77 -- adicionar identificacao do aluno no jumbotron inicial do teste, para que ao imprimir para pdf a identificacao do aluno venha escrita no documento.  
78 -- internal server error quando em --review, download csv detalhado.  
79 -- perguntas repetidas (mesma ref) dao asneira, porque a referencia é usada como chave em varios sitios e as chaves nao podem ser dupplicadas.  
80 - da asneira pelo menos na funcao get_questions_csv. na base de dados tem de estar registado tb o numero da pergunta, caso contrario é impossível saber a qual corresponde.  
81 -- mostrar unfocus e window area em /admin  
82 -- CRITICAL se answer for `i<n` a revisão de provas mostra apenas i (interpreta `<` como tag?)  
83 -- botao de autorizar desliga-se, fazer debounce.  
84 -- link na pagina com a nota para voltar ao principio.  
85 -- default logger config mostrar horas com segundos  
86 -- test: mostrar duração do teste com progressbar no navbar.  
87 -- lidar com eventos unfocus.  
88 -- servidor nao esta a lidar com eventos resize.  
89 -- sock.bind(sockaddr) OSError: [Errno 48] Address already in use  
90 -- dizer quanto desconta em cada pergunta de escolha multipla  
91 -- se houver erros a abrir ficheiros .yaml de perguntas, depois dos testes diz "No errors found".  
92 -- se faltarem files na especificação do teste, o check não detecta e factory não gera para essas perguntas.  
93 -- nao esta a usar points das perguntas  
94 -- quando se clica no texto de uma opcao, salta para outro lado na pagina.  
95 -- 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.  
96 -- fazer package para instalar perguntations com pip.  
97 -- pymips: nao pode executar syscalls do spim.  
98 -- exception sqlalchemy relacionada com threads.  
99 -- acrescentar logger.conf que sirva de base.  
100 -- questions.py textarea has a abspath which does not make sense! why is it there? not working for perguntations, but seems to work for aprendizations  
101 -- textarea foi modificado em aprendizations para receber cmd line args. corrigir aqui tb.  
102 -- usar npm para instalar javascript  
103 -- se aluno entrar com l12345 rebenta. numa funcao get_... ver imagem no ipad  
104 -- no test3 está contar 1.0 valores numa pergunta do tipo info? acontece para type: info, e não para type: information  
105 -- default correct in checkbox must be 1.0, so that the pairs (right,wrong) still work with `correct` left undefined.  
106 -- textarea com codemirror  
107 -- decorador para user 0, evita o "if uid==0" em muitas funcoes.  
108 -- numeric interval deve converter respostas que usam virgulas para pontos decimais  
109 -- self.testapp.get_json_filename_of_test(test_id) retorna None quando test_id nao existe.  
110 -- o eventloop está a bloquear. correção do teste é blocking. usar threadpoolexecutor?  
111 -- substituir get_event_loop por get_runnint_loop (ver https://docs.python.org/3/library/asyncio-eventloop.html)  
112 -- review nao esta a funcionar  
113 -- servir imagens das perguntas não funciona. Necessario passar a ref da pergunta no link para poder ajustar o path no FileHandler.  
114 -- a primeira coluna da tabela admin deveria estar sempre ordenada.  
115 -- abortar depois de testar todas as perguntas, caso haja algum erro.  
116 -- imagens jpg/png nas perguntas.  
117 -- initdb está a inicializar com passwords iguais aos numeros. deveria ser vazio para alunos definirem.  
118 -- upgrade popper e fazer link.  
119 -- mover scripts js para head, com defer. ver todos os templates.  
120 -- update fontawesome to 5.  
121 -- mostrar comments e solution na revisao de prova.  
122 -- upgrade para tornado 5.0.  
123 -- ctrl-c should ask for confirmation before exiting.  
124 -- md_to_html() nao usa o segundo argumento q. pode retirar-se dos templates?  
125 -- config/logger.yaml ainda é do cherrypy...  
126 -- uniformizar question.py com a de aprendizations...  
127 -- qual a diferenca entre md_to_html e md_to_html_review, parece desnecessario haver dois.  
128 -- converter markdown para mistune.  
129 -- como alterar configuracao para mostrar logs de debug?  
130 -- espaco no final das tabelas.  
131 -- total do teste aparece negativo.  
132 -- reset password nao funciona no admin  
133 -- reload a intervalos não funciona.  
134 -- allow/deny nao funciona no /admin.  
135 -- Review de um teste que foi apagado rebenta.  
136 -- numeracao das perguntas do teste esta a contar com paineis informativos...  
137 -- markdown no teste nao funciona  
138 -- review de um teste nao funciona (hardcoded...)  
139 -- testar SSL  
140 -- text-numeric não está a gerar a pergunta. faltam templates?  
141 -- testar perguntas warning/warn  
142 -- qd user 0 faz logout rebenta.  
143 -- Quando grava JSON do teste deve usar 'path' tal como definido na configuração e não expandido. Isto porque em OSX /home é /Users e quando se muda de um sistema para outro não encontra os testes. Assim, usando ~ na configuração deveria funcionar sempre.  
144 -- configuração do teste não joga bem com o do aprendizations. Em particular os scripts não ficam com o mesmo path!!!  
145 -- configurar pf em freebsd, port forward 80 -> 8080. documentacao  
146 -- barras com notas em grade estão desalinhadas.  
147 -- erros nos generators devem ser ERROR e não WARNING.  
148 -- se directorio "logs" não existir no directorio actual aborta com mensagem de erro.  
149 -- se um teste tiver a mesma pergunta repetida (ref igual), rebenta na correcçao. As respostas são agregadas numa lista para cada ref. Ex: {'ref1': 'resposta1', 'ref2': ['resposta2a', 'resposta2b']}  
150 -- usar http://fontawesome.io/examples/ em vez dos do bootstrap3  
151 -- se pergunta tiver 'type:' errado, rebenta.  
152 -- se submeter um teste so com information, da divisao por zero.  
153 -- se save_answers nao existir, da warning que nao serao gravados, mas sao sempre gravados! pagina de administracao diz --not being saved--  
154 -- first login é INFO e não WARNING  
155 -- /review não mostra imagens porque precisa que teste esteja a decorrer...  
156 -- visualizar um teste ja realizado na página de administração  
157 -- Depois da correcção, mostra testes realizados que não foram realizados pelo próprio  
158 -- detectar se janela perde focus e alertar o prof (http://stackoverflow.com/questions/1060008/is-there-a-way-to-detect-if-a-browser-window-is-not-currently-active)  
159 -- server nao esta a receber eventos focus/blur dos utilizadores diferentes de '0', estranho...  
160 -- permitir adicionar imagens nas perguntas.  
161 -- detect_unfocus.js so funciona se estiver inline no html. porquê???  
162 -- inserir novo aluno /admin não fecha.  
163 -- se aluno desistir, ainda fica marcado como online  
164 -- give dá None em vez de 0.0  
165 -- debug mode: log levels not working  
166 -- Se aluno fizer logout, o teste não é gravado e ficamos sem registo do teste que o aluno viu.  
167 -- criar sqlalchemy sessions dentro de app de modo a estarem associadas a requests. ver se é facil usar with db:(...) para criar e fechar sessão.  
168 -- sqlalchemy queixa-se de threads.  
169 -- SQLAlchemy em vez da classe database.  
170 -- replace sys.exit calls  
171 -- if does not find questions, aborts silently  
172 -- argumentos da linha de comando a funcionar.  
173 -- configuracao dos logs cherrypy para se darem bem com os outros  
174 -- browser e ip usados gravado no test.  
175 -- botões allow all/deny all.  
176 -- mostrar botão de reset apenas no final da pagina, com edit para escrever o número.  
177 -- aluno faz login, mas fecha browser, ficando no estado (online,deny). Ao tentar login com outro browser está deny e o prof não consegue pô-lo em allow pois já não está na lista. => solucao é manter todos os alunos numa tabela.  
178 -- pagina de login nao esta a apresentar bem. parece que precisa de autorizacao para aceder a /static...  
179 -- Não mostrar Professor nos activos em /admin  
180 -- /admin mostrar actualizações automaticamente?  
181 -- se no teste uma das "ref" nao existir nos ficheiros de perguntas, rebenta.  
182 -- alunos podem estar online, mas browser perder sessao => nao conseguem mais entrar porque a App pensa que estão online. Permitir login e dar o mesmo teste.  
183 -- pagina de management dos alunos.  
184 - mostrar online ordenados por hora de login, offline por número.  
185 - permitir reset da pw e allow/disallow  
186 -- script de correcção pode enviar dicionario yaml com grade e comentarios. ex:  
187 - grade: 0.5  
188 - comments: Falhou na função xpto.  
189 - os comentários são guardados no teste (ficheiro) ou enviados para o browser no modo practice.  
190 -- testar regex na definicao das perguntas. como se faz rawstring em yaml?  
191 - singlequote? problemas de backslash??? sim... necessário fazer \\ em varios casos, mas não é claro! e.g. \n é convertido em espaço mas \w é convertido em \\ e w. Solução (http://stackoverflow.com/questions/10771163/python-interpreting-a-regex-from-a-yaml-config-file) é fazer  
192 - correct: !regex '^(yes|no)' 62 +- abrir o teste numa janela maximizada e que nao permite que o aluno a
  63 + redimensione/mova? modo kiosk?
  64 +- detectar scroll e enviar posição para servidor (analise de scroll para detectar copianço?)
  65 +- criar perguntas de outros tipos, e.g. associação, ordenação.
  66 +- stress tests. use https://locust.io
demo/demo.yaml
@@ -47,7 +47,7 @@ scale: [0, 20] @@ -47,7 +47,7 @@ scale: [0, 20]
47 # ---------------------------------------------------------------------------- 47 # ----------------------------------------------------------------------------
48 # Files to import. Each file contains a list of questions in yaml format. 48 # Files to import. Each file contains a list of questions in yaml format.
49 files: 49 files:
50 - - questions/questions-tutorial.yaml 50 + - questions/tutorial.yaml
51 51
52 # This is the list of questions that will make up the test. 52 # This is the list of questions that will make up the test.
53 # The order is preserved. 53 # The order is preserved.
demo/questions/correct-question.py 0 → 100755
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +#!/usr/bin/env python3
  2 +
  3 +'''
  4 +Demonstação de um script de correcção
  5 +'''
  6 +
  7 +import re
  8 +import sys
  9 +
  10 +s = sys.stdin.read()
  11 +
  12 +ans = set(re.findall(r'[\w]+', s.lower())) # get words in lowercase
  13 +rgb = set(['red', 'green', 'blue']) # the correct answer
  14 +
  15 +# a nota é o número de cores certas menos o número de erradas
  16 +grade = max(0,
  17 + len(rgb.intersection(ans)) - len(ans.difference(rgb))) / 3
  18 +
  19 +if ans == rgb:
  20 + print('---\n'
  21 + 'grade: 1.0\n'
  22 + 'comments: Muito bem!')
  23 +
  24 +else:
  25 + print('---\n'
  26 + f'grade: {grade}\n'
  27 + 'comments: A resposta correcta é "red green blue".')
demo/questions/correct-timeout.py 0 → 100755
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +#!/usr/bin/env python3
  2 +
  3 +import sys
  4 +import time
  5 +
  6 +s = sys.stdin.read()
  7 +
  8 +# sleep a lot of time to generate timeout during correction
  9 +time.sleep(100)
  10 +
  11 +# probably this result will not be seen because the script will be interrupted
  12 +print(0.5)
demo/questions/correct/correct-question.py
@@ -1,27 +0,0 @@ @@ -1,27 +0,0 @@
1 -#!/usr/bin/env python3  
2 -  
3 -'''  
4 -Demonstação de um script de correcção  
5 -'''  
6 -  
7 -import re  
8 -import sys  
9 -  
10 -s = sys.stdin.read()  
11 -  
12 -ans = set(re.findall(r'[\w]+', s.lower())) # get words in lowercase  
13 -rgb = set(['red', 'green', 'blue']) # the correct answer  
14 -  
15 -# a nota é o número de cores certas menos o número de erradas  
16 -grade = max(0,  
17 - len(rgb.intersection(ans)) - len(ans.difference(rgb))) / 3  
18 -  
19 -if ans == rgb:  
20 - print('---\n'  
21 - 'grade: 1.0\n'  
22 - 'comments: Muito bem!')  
23 -  
24 -else:  
25 - print('---\n'  
26 - f'grade: {grade}\n'  
27 - 'comments: A resposta correcta é "red green blue".')  
demo/questions/correct/correct-timeout.py
@@ -1,12 +0,0 @@ @@ -1,12 +0,0 @@
1 -#!/usr/bin/env python3  
2 -  
3 -import sys  
4 -import time  
5 -  
6 -s = sys.stdin.read()  
7 -  
8 -# sleep a lot of time to generate timeout during correction  
9 -time.sleep(100)  
10 -  
11 -# probably this result will not be seen because the script will be interrupted  
12 -print(0.5)  
demo/questions/questions-tutorial.yaml
@@ -1,658 +0,0 @@ @@ -1,658 +0,0 @@
1 ----  
2 -# ----------------------------------------------------------------------------  
3 -- type: information  
4 - ref: tut-test  
5 - title: Configuração do teste  
6 - text: |  
7 - O teste é configurado num ficheiro `yaml`  
8 - (ver especificação [aqui](https://yaml.org)).  
9 - A configuração contém a identificação do teste, base de dados dos alunos,  
10 - ficheiros de perguntas a importar e uma selecção de perguntas e respectivas  
11 - cotações.  
12 -  
13 - Exemplo:  
14 -  
15 - ```yaml  
16 - ---  
17 - # --------------------------------------------------------------------------  
18 - ref: tutorial # referência, pode ser reusada em vários turnos  
19 - title: Demonstração # título da prova  
20 - database: students.db # base de dados previamente criada com initdb  
21 - answers_dir: ans # directório onde ficam os testes dos alunos  
22 -  
23 - # opcionais  
24 - duration: 60 # duração da prova em minutos (default: inf)  
25 - autosubmit: true # submissão automática (default: false)  
26 - show_points: true # mostra cotação das perguntas (default: true)  
27 - scale: [0, 20] # normaliza cotações para o intervalo indicado.  
28 - # não normaliza por defeito (default: None)  
29 -  
30 - # --------------------------------------------------------------------------  
31 - # Ficheiros de perguntas a importar (relativamente a `questions_dir`)  
32 - files:  
33 - - tabelas.yaml  
34 - - topic1/questions.yaml  
35 - - topic2/part1/questions.yaml  
36 - - topic2/part2/questions.yaml  
37 -  
38 - # --------------------------------------------------------------------------  
39 - # Especificação das perguntas do teste e respectivas cotações.  
40 - # O teste é uma lista de perguntas, onde cada pergunta é especificada num  
41 - # dicionário com a referência da pergunta e a respectiva cotação.  
42 - questions:  
43 - - ref: pergunta1  
44 - points: 3.5  
45 -  
46 - - ref: pergunta2  
47 - points: 2.0  
48 -  
49 - # por defeinto, a cotação da pergunta é 1.0 valor  
50 - - ref: pergunta3  
51 -  
52 - # escolhe aleatoriamente uma das variantes da pergunta  
53 - - ref: [pergunta3a, pergunta3b]  
54 - points: 0.5  
55 -  
56 - # --------------------------------------------------------------------------  
57 - ```  
58 -  
59 - A ordem das perguntas é mantida quando apresentada no teste.  
60 -  
61 - O mesmo teste pode ser realizado várias vezes em turnos diferentes, não é  
62 - necessário alterar nada.  
63 -  
64 -# ----------------------------------------------------------------------------  
65 -- type: information  
66 - ref: tut-questions  
67 - title: Especificação das perguntas  
68 - text: |  
69 - As perguntas estão definidas num ou mais ficheiros `yaml` como uma lista de  
70 - perguntas, onde cada pergunta é um dicionário.  
71 -  
72 - Por exemplo, um ficheiro com o conteúdo abaixo contém duas perguntas, uma  
73 - de escolha múltipla e outra apenas informativa:  
74 -  
75 - ```yaml  
76 - ---  
77 - #---------------------------------------------------------------------------  
78 - - type: radio  
79 - ref: chave-unica-1  
80 - text: Quanto é $1+1$?  
81 - options:  
82 - - 1  
83 - - 2  
84 - - 3  
85 -  
86 - #---------------------------------------------------------------------------  
87 - - type: information  
88 - ref: chave-unica-2  
89 - text: |  
90 - Quando o texto da pergunta tem várias linhas, dá jeito usar o símbolo  
91 - `|` de pipe, para indicar que tudo o que estiver indentado faz parte do  
92 - texto. É o caso desta pergunta.  
93 -  
94 - O texto das perguntas é escrito em `markdown` e suporta fórmulas em  
95 - LaTeX.  
96 -  
97 - #---------------------------------------------------------------------------  
98 - ```  
99 -  
100 - As chaves são usadas para construir o teste e não se podem repetir, mesmo  
101 - em ficheiros diferentes.  
102 - De seguida mostram-se exemplos dos vários tipos de perguntas.  
103 -  
104 -# ----------------------------------------------------------------------------  
105 -- type: radio  
106 - ref: tut-radio  
107 - title: Escolha simples, uma opção correcta.  
108 - text: |  
109 - As perguntas de escolha simples, permitem fazer uma pergunta e apresentar  
110 - várias opções de resposta em que apenas uma delas está certa.  
111 - A utilização mais simples é a seguinte:  
112 -  
113 - ```yaml  
114 - - type: radio  
115 - ref: pergunta-1  
116 - title: Escolha simples, uma opção correcta.  
117 - text: |  
118 - Bla bla bla.  
119 - options:  
120 - - Opção 0  
121 - - Opção 1  
122 - - Opção 2  
123 - - Opção 3  
124 - - Opção 4  
125 - ```  
126 -  
127 - Sem outras configurações, assume-se que a primeira opção é a resposta  
128 - correcta ("Opção 0" neste caso) e as 5 opções são apresentadas por ordem  
129 - aleatória.  
130 -  
131 - Para evitar que os alunos memorizem os textos das opções, podem definir-se  
132 - várias opções correctas com escrita ligeiramente diferente, sendo escolhida  
133 - apenas uma delas para apresentação.  
134 - Por exemplo, se as 2 primeiras opções estiverem correctas e as restantes  
135 - erradas, e quisermos apresentar ao aluno 3 opções no total, acrescenta-se:  
136 -  
137 - ```yaml  
138 - correct: [1, 1, 0, 0, 0]  
139 - choose: 3  
140 - ```  
141 -  
142 - Neste caso, será escolhida uma opção certa e duas erradas.  
143 - Os valores em `correct` representam o grau de correcção no intervalo [0, 1]  
144 - onde 1 representa 100% certo e 0 representa 0%. Podem ser usados valores  
145 - entre 0 e 1, sendo atribuída a respectiva cotação, mas só o valor 1  
146 - representa uma opção certa.  
147 -  
148 - Por defeito, as opções são apresentadas por ordem aleatória, mas é possível  
149 - usar a ordem predefinida. Por exemplo, para manter a ordem e indicar que a  
150 - resposta correcta é a do meio define-se:  
151 -  
152 - ```yaml  
153 - correct: [0, 0, 1, 0, 0]  
154 - shuffle: false  
155 - ```  
156 -  
157 - As respostas erradas descontam, tendo uma cotação de $-1/(n-1)$ do valor da  
158 - pergunta, onde $n$ é o número de opções apresentadas ao aluno (a ideia é o  
159 - valor esperado ser zero quando as respostas são aleatórias e uniformemente  
160 - distribuídas). Para não descontar acrescenta-se:  
161 -  
162 - ```yaml  
163 - discount: false  
164 - ```  
165 - options:  
166 - - Opção 0 (certa)  
167 - - Opção 1 (certa)  
168 - - Opção 2  
169 - - Opção 3  
170 - - Opção 4  
171 - correct: [1, 1, 0, 0, 0]  
172 - choose: 3  
173 - solution: |  
174 - A solução correcta é a **Opção 0** ou a **Opção 1**.  
175 -  
176 -# ----------------------------------------------------------------------------  
177 -- type: checkbox  
178 - ref: tut-checkbox  
179 - title: Escolha múltipla, várias opções correctas  
180 - text: |  
181 - As perguntas de escolha múltipla permitem apresentar um conjunto de opções  
182 - podendo ser seleccionadas várias em simultâneo.  
183 - Funcionam como múltiplas perguntas independentes de resposta sim/não.  
184 -  
185 - As respostas que devem ou não ser seleccionadas são indicadas com `1` e `0`  
186 - ou com booleanos `true` e `false`.  
187 - Cada resposta errada desconta um valor que é o simétrico da resposta certa.  
188 - Se acertar uma opção ganha `+1`, se errar obtém `-1`.  
189 -  
190 - ```yaml  
191 - - type: checkbox  
192 - ref: tut-checkbox  
193 - title: Escolha múltipla, várias opções correctas  
194 - text: |  
195 - Bla bla bla.  
196 - options:  
197 - - Opção 0 (certa)  
198 - - Opção 1  
199 - - Opção 2  
200 - - Opção 3 (certa)  
201 - - Opção 4  
202 - correct: [1, 0, 0, 1, 0]  
203 - ```  
204 -  
205 - Neste exemplo, seleccionando as opções 0 e 3 obtém-se cotação `+1` em cada  
206 - uma, enquanto que seleccionando erradamente as opções 1, 2 e 4 obtém-se  
207 - cotação `-1`.  
208 - Do mesmo modo, não seleccionando as opções certas 0 e 3 obtém-se a cotação  
209 - `-1` em cada uma, e não seleccionando (correctamente) as 1, 2 e 4 obtém-se  
210 - `+1` em cada.  
211 -  
212 - *(Neste tipo de perguntas não há forma de responder a apenas algumas delas,  
213 - são sempre todas corrigidas. Se um aluno só sabe a resposta a algumas das  
214 - opções, deve ter cuidado porque as restantes também serão classificadas e  
215 - arrisca-se a ter cotação negativa)*  
216 -  
217 - Cada opção pode opcionalmente ser escrita como uma afirmação e o seu  
218 - contrário, de maneira a aumentar a variabilidade dos textos.  
219 - Por exemplo:  
220 -  
221 - ```yaml  
222 - options:  
223 - - ['O céu é azul', 'O céu não é azul']  
224 - - ['Um triangulo tem 3 lados', 'Um triangulo tem 2 lados']  
225 - - O nosso planeta tem um satélite natural  
226 - correct: [1, 1, 1]  
227 - ```  
228 -  
229 - Assume-se que a primeira alternativa de cada opção tem a cotação indicada  
230 - em `correct`, enquanto a segunda alternativa tem a cotação contrária.  
231 -  
232 - Tal como nas perguntas do tipo `radio`, podem ser usadas as configurações  
233 - `shuffle` e `discount` com valor `false` para as desactivar.  
234 - Se `discount` é `false` então as respostas erradas têm cotação 0 em vez do  
235 - simétrico.  
236 - options:  
237 - - ['Opção 0 (sim)', 'Opção 0 (não)']  
238 - - ['Opção 1 (não)', 'Opção 1 (sim)']  
239 - - Opção 2 (não)  
240 - - Opção 3 (sim)  
241 - correct: [1, 0, 0, 1]  
242 - shuffle: false  
243 -  
244 -# ----------------------------------------------------------------------------  
245 -- type: text  
246 - ref: tut-text  
247 - title: Resposta de texto em linha  
248 - text: |  
249 - Este tipo de perguntas permite uma resposta numa linha de texto. A resposta  
250 - está correcta se coincidir exactamente com alguma das respostas admissíveis.  
251 -  
252 - ```yaml  
253 - - type: text  
254 - ref: tut-text  
255 - title: Resposta de texto em linha  
256 - text: |  
257 - De que cor é o céu?  
258 -  
259 - Escreva a resposta em português.  
260 - correct: ['azul', 'Azul', 'AZUL']  
261 - ```  
262 -  
263 - Neste caso, as respostas aceites são `azul`, `Azul` ou `AZUL`.  
264 -  
265 - Em alguns casos pode ser conveniente transformar a resposta antes de a  
266 - comparar, por exemplo para remover espaços ou converter para minúsculas.  
267 - A opção `transform` permite dar uma sequência de transformações a aplicar à  
268 - resposta do aluno, por exemplo:  
269 -  
270 - ```yaml  
271 - transform: ['trim', 'lower']  
272 - correct: ['azul']  
273 - ```  
274 -  
275 - Estão disponíveis as seguintes transformações:  
276 -  
277 - * `trim` remove os espaços do início e fim da resposta, os espaços do meio  
278 - mantêm-se inalterados.  
279 - * `remove_space` remove todos os espaços (início, meio e fim).  
280 - * `normalize_space` remove espaços do início e fim (trim), e substitui  
281 - múltiplos espaços por um único espaço (no meio).  
282 - * `lower` e `upper` convertem respectivamente para minúsculas e maiúsculas.  
283 - transform: ['trim', 'lower']  
284 - correct: ['azul']  
285 - solution: |  
286 - O céu é `azul`, pelo menos durante o dia e se estiver bom tempo...  
287 -  
288 -# ---------------------------------------------------------------------------  
289 -- type: text-regex  
290 - ref: tut-text-regex  
291 - title: Resposta de texto em linha, expressão regular  
292 - text: |  
293 - Este tipo de pergunta é semelhante à linha de texto da pergunta anterior.  
294 - A única diferença é que esta é validada por uma expressão regular.  
295 -  
296 - ```yaml  
297 - - type: text-regex  
298 - ref: tut-text-regex  
299 - title: Resposta de texto em linha  
300 - text: |  
301 - Bla bla bla  
302 - correct: '(VERDE|[Vv]erde)'  
303 - ```  
304 -  
305 - Neste exemplo a expressão regular é `(VERDE|[Vv]erde)`.  
306 -  
307 - Também se pode dar uma lista de expressões regulares. Nesse caso a resposta  
308 - é considerada correcta se fizer match com alguma delas.  
309 - No exemplo acima, poder-se-ia ter usado uma lista  
310 -  
311 - ```yaml  
312 - correct:  
313 - - 'VERDE'  
314 - - '[Vv]erde'  
315 - ```  
316 -  
317 - ---  
318 -  
319 - **Atenção:** A expressão regular deve seguir as convenções da suportadas em  
320 - python (ver  
321 - [Regular expression operations](https://docs.python.org/3/library/re.html)).  
322 - Em particular, a expressão regular acima também aceita a resposta  
323 - `verde, azul`.  
324 - Deve marcar-se o início e final `^(VERDE|[Vv]erde)$` para evitar estas  
325 - situações.  
326 -  
327 - correct: '(VERDE|[Vv]erde)'  
328 - solution: |  
329 - Deveria ter escrito `VERDE` ou `Verde` ou `verde`.  
330 -  
331 -# ---------------------------------------------------------------------------  
332 -- type: numeric-interval  
333 - ref: tut-numeric-interval  
334 - title: Resposta numérica em linha de texto  
335 - text: |  
336 - Este tipo de perguntas esperam uma resposta numérica (vírgula flutuante).  
337 - O resultado é considerado correcto se estiver dentro do intervalo fechado  
338 - indicado.  
339 -  
340 - ```yaml  
341 - - type: numeric-interval  
342 - ref: tut-numeric-interval  
343 - title: Resposta numérica em linha de texto  
344 - text: |  
345 - Escreva o número $\pi$ com pelo menos duas casa decimais.  
346 - correct: [3.14, 3.15]  
347 - ```  
348 -  
349 - Neste exemplo o intervalo de respostas correctas é o intervalo fechado  
350 - [3.14, 3.15].  
351 -  
352 - Se em vez de dar um intervalo, apenas for indicado um valor numérico $n$,  
353 - este é automaticamente convertido para para um intervalo $[n,n]$.  
354 -  
355 - **Atenção:** as respostas têm de usar o ponto como separador decimal.  
356 - Em geral são aceites números inteiros, como `123`,  
357 - ou em vírgula flutuante, como em `0.23`, `1e-3`.  
358 - correct: [3.14, 3.15]  
359 - solution: |  
360 - Sabemos que $\pi\approx 3.14159265359$.  
361 - Portanto, um exemplo de uma resposta correcta é `3.1416`.  
362 -  
363 -# ---------------------------------------------------------------------------  
364 -- type: textarea  
365 - ref: tut-textarea  
366 - title: Resposta em múltiplas linhas de texto  
367 - text: |  
368 - Este tipo de perguntas permitem respostas em múltiplas linhas de texto e  
369 - são as mais flexíveis.  
370 -  
371 - A resposta é enviada para um programa externo para ser avaliada.  
372 - O programa externo é um programa que tem de ser executável pelo pelo  
373 - sistema operativo (pode ser um binário ou script desde que o respectivo  
374 - interpretador instalado).  
375 - Este programa externo recebe a resposta submetida pelo aluno via `stdin` e  
376 - devolve a classificação via `stdout`.  
377 - Exemplo:  
378 -  
379 - ```yaml  
380 - - type: textarea  
381 - ref: tut-textarea  
382 - title: Resposta em múltiplas linhas de texto  
383 - text: |  
384 - Bla bla bla  
385 - correct: correct/correct-question.py # programa a executar  
386 - timeout: 5  
387 - ```  
388 -  
389 - Neste exemplo, o programa de avaliação é um script python que verifica se a  
390 - resposta contém as três palavras red, green e blue, e calcula uma nota no  
391 - intervalo 0.0 a 1.0.  
392 - O programa externo é executado num processo separado e a interacção faz-se  
393 - via stdin/stdout.  
394 -  
395 - Se o programa externo exceder o `timeout` indicado (em segundos),  
396 - este é automaticamente terminado e é atribuída a classificação de 0.0  
397 - valores na pergunta.  
398 -  
399 - Após terminar a correcção, o programa externo deve enviar a classificação  
400 - para o stdout.  
401 - Pode simplesmente fazer `print` da classificação como um número em vírgula  
402 - flutuante, por exemplo  
403 -  
404 - ```yaml  
405 - 0.75  
406 - ```  
407 -  
408 - ou opcionalmente escrever em formato json ou yaml, eventualmente com um  
409 - comentário que será arquivado com o teste.  
410 - Exemplo:  
411 -  
412 - ```yaml  
413 - grade: 0.5  
414 - comments: |  
415 - Esqueceu-se de algumas cores.  
416 - A resposta correcta era `red green blue`.  
417 - ```  
418 -  
419 - O comentário é mostrado na revisão de prova.  
420 - answer: |  
421 - Aqui o aluno escreve a resposta.  
422 - Esta caixa aumenta de tamanho automaticamente e  
423 - pode estar previamente preenchida como neste caso (use `answer: texto`).  
424 - correct: correct/correct-question.py  
425 - timeout: 5  
426 - tests_right:  
427 - - 'red green blue'  
428 - # tests_wrong:  
429 - # - 'blue gray yellow'  
430 -  
431 -# ---------------------------------------------------------------------------  
432 -- type: information  
433 - ref: tut-information  
434 - title: Texto informativo  
435 - text: |  
436 - As perguntas deste tipo não contam para avaliação. O objectivo é fornecer  
437 - instruções para os alunos, por exemplo tabelas para consulta, fórmulas, etc.  
438 - Nesta, tal como em todos os tipos de perguntas podem escrever-se fórmulas  
439 - em LaTeX. Exemplo:  
440 -  
441 - A distribuição gaussiana $\mathcal{N}(x\mid\mu,\sigma^2)$ é  
442 - definida pela função densidade de probabilidade  
443 -  
444 - $$  
445 - p(x) = \frac{1}{\sqrt{2\pi\sigma^2}}  
446 - \exp\Big({-\frac{(x-\mu)^2}{2\sigma^2}}\Big).  
447 - $$  
448 -  
449 - ---  
450 -  
451 - ```yaml  
452 - - type: information  
453 - ref: tut-information  
454 - title: Texto informativo  
455 - text: |  
456 - A distribuição gaussiana $\mathcal{N}(x\mid\mu,\sigma^2)$ é  
457 - definida pela função densidade de probabilidade  
458 -  
459 - $$  
460 - p(x) = \frac{1}{\sqrt{2\pi\sigma^2}}  
461 - \exp\Big({-\frac{(x-\mu)^2}{2\sigma^2}}\Big).  
462 - $$  
463 - ```  
464 -  
465 -# ---------------------------------------------------------------------------  
466 -- type: success  
467 - ref: tut-success  
468 - title: Texto informativo (sucesso)  
469 - text: |  
470 - Não conta para avaliação. É apenas o aspecto gráfico que muda.  
471 -  
472 - Um pedaço de código em linha, por exemplo `x = sqrt(z)` é marcado com uma  
473 - fonte e cor diferente.  
474 - Também se podem escrever troços de código coloridos conforme a linguagem:  
475 -  
476 - ```C  
477 - int main() {  
478 - printf("Hello world!");  
479 - return 0; // comentario  
480 - }  
481 - ```  
482 -  
483 - ---  
484 -  
485 - ```yaml  
486 - - type: success  
487 - ref: tut-success  
488 - title: Texto informativo (sucesso)  
489 - text: |  
490 - Não conta para avaliação. É apenas o aspecto gráfico que muda.  
491 -  
492 - Um pedaço de código em linha, por exemplo `x = sqrt(z)` é marcado com  
493 - uma fonte e cor diferente.  
494 - Também se podem escrever troços de código coloridos conforme a  
495 - linguagem:  
496 -  
497 - ```C  
498 - int main() {  
499 - printf("Hello world!");  
500 - return 0; // comentario  
501 - }  
502 - ```  
503 -  
504 - ```  
505 -  
506 -# ---------------------------------------------------------------------------  
507 -- type: warning  
508 - ref: tut-warning  
509 - title: Texto informativo (aviso)  
510 - text: |  
511 - Não conta para avaliação.  
512 -  
513 - Neste exemplo mostramos como se pode construir uma tabela como a seguinte:  
514 -  
515 - Left | Center | Right  
516 - -----------------|:----------------:|----------:  
517 - *hello* | $\sin(x^2)$ | $1600.00  
518 - **world** | $\frac{1}{2\pi}$ | $12.50  
519 - `code` | $\sqrt{\pi}$ | $1.99  
520 -  
521 - As tabelas podem conter Markdown e LaTeX e permitem alinhamento das colunas,  
522 - mas o markdown é muito simples e não permite mais funcionalidades.  
523 -  
524 - ---  
525 -  
526 - ```yaml  
527 - - type: warning  
528 - ref: tut-warning  
529 - title: Texto informativo (aviso)  
530 - text: |  
531 - Bla bla bla  
532 -  
533 - Left | Center | Right  
534 - -----------------|:----------------:|----------:  
535 - *hello* | $\sin(x^2)$ | $1600.00  
536 - **world** | $\frac{1}{2\pi}$ | $12.50  
537 - `code` | $\sqrt{\pi}$ | $1.99  
538 - ```  
539 -  
540 -# ----------------------------------------------------------------------------  
541 -- type: alert  
542 - ref: tut-alert1  
543 - title: Texto informativo (perigo) - versão 1  
544 - text: |  
545 - Não conta para avaliação. Texto importante.  
546 -  
547 - ![planetas](planets.png "Planetas do Sistema Solar")  
548 -  
549 - As imagens podem ser adicionadas usando a notação standard em markdown. Há  
550 - duas possibilidads:  
551 -  
552 - - Imagens inline: não têm título definido e podem ser incluídas no meio de  
553 - uma linha de texto usando`![alt text](image.jpg)`.  
554 - - Imagens centradas com título: `![alt text](image.jpg "Título da imagem")`.  
555 - O título é colocado por baixo da imagem. Pode ser uma string vazia.  
556 -  
557 -- type: alert  
558 - ref: tut-alert2  
559 - title: Texto informativo (perigo) - versão 2  
560 - text: |  
561 - Não conta para avaliação. Texto importante.  
562 -  
563 - ![planetas](planets.png "Planetas do Sistema Solar")  
564 -  
565 - As imagens podem ser adicionadas usando a notação standard em markdown. Há  
566 - duas possibilidads:  
567 -  
568 - - Imagens inline: não têm título definido e podem ser incluídas no meio de  
569 - uma linha de texto usando `![alt text](image.jpg)`.  
570 - - Imagens centradas com título: `![alt text](image.jpg "Título da imagem")`.  
571 - O título é colocado por baixo da imagem. Pode ser uma string vazia.  
572 -  
573 -# ----------------------------------------------------------------------------  
574 -- type: information  
575 - text: |  
576 - This question is not included in the test and will not show up.  
577 - It also lacks a "ref" and is automatically named  
578 - `questions/questions-tutorial.yaml:0013`.  
579 - A warning is shown on the console about this.  
580 - The number at the end is the index position of this question.  
581 - Indices start at 0.  
582 -  
583 -# ----------------------------------------------------------------------------  
584 -- type: generator  
585 - ref: tut-generator  
586 - script: generate-question.py  
587 - args: [1, 100]  
588 -  
589 -# ----------------------------------------------------------------------------  
590 -- type: information  
591 - ref: tut-yamllint  
592 - title: Sugestões para validar yaml  
593 - text: |  
594 - Como os testes e perguntas são ficheiros `yaml`, é conveniente validar se  
595 - estão correctamente definitos. Um *linter* recomendado é o `yamllint`. Pode  
596 - ser instalado com `pip install yamllint` e usado do seguinte modo:  
597 -  
598 - ```sh  
599 - yamllint test.yaml  
600 - yamllint questions.yaml  
601 - ```  
602 -  
603 - No caso de programas geradores de perguntas e programas de correcção de  
604 - respostas pode usar-se um *pipe*:  
605 -  
606 - ```sh  
607 - generate-question | yamllint -  
608 - correct-answer | yamllint -  
609 - ```  
610 -  
611 -# ----------------------------------------------------------------------------  
612 -# - type: code  
613 -# ref: tut-code  
614 -# title: Submissão de código (JOBE)  
615 -# text: |  
616 -# É possível enviar código para ser compilado e executado por um servidor  
617 -# JOBE instalado separadamente, ver [JOBE](https://github.com/trampgeek/jobe).  
618 -  
619 -# ```yaml  
620 -# - type: code  
621 -# ref: tut-code  
622 -# title: Submissão de código (JOBE)  
623 -# text: |  
624 -# Escreva um programa em C que recebe uma string no standard input e  
625 -# mostra a mensagem `hello ` seguida da string.  
626 -# Por exemplo, se o input for `Maria`, o output deverá ser `hello Maria`.  
627 -# language: c  
628 -# correct:  
629 -# - stdin: 'Maria'  
630 -# stdout: 'hello Maria'  
631 -# - stdin: 'xyz'  
632 -# stdout: 'hello xyz'  
633 -# ```  
634 -  
635 -# Existem várias linguagens suportadas pelo servidor JOBE (C, C++, Java,  
636 -# Python2, Python3, Octave, Pascal, PHP).  
637 -# O campo `correct` deverá ser uma lista de casos a testar.  
638 -# Se um caso incluir `stdin`, este será enviado para o programa e o `stdout`  
639 -# obtido será comparado com o declarado. A pergunta é considerada correcta se  
640 -# todos os outputs coincidirem.  
641 -  
642 -# Por defeito é o usado o servidor JOBE declarado no teste. Para usar outro  
643 -# diferente nesta pergunta usa-se a opção `server: 127.0.0.1` com o endereço  
644 -# apropriado.  
645 -# answer: |  
646 -# #include <stdio.h>  
647 -# int main() {  
648 -# char name[20];  
649 -# scanf("%s", name);  
650 -# printf("hello %s", name);  
651 -# }  
652 -# # server: 192.168.1.85  
653 -# language: c  
654 -# correct:  
655 -# - stdin: 'Maria'  
656 -# stdout: 'hello Maria'  
657 -# - stdin: 'xyz'  
658 -# stdout: 'hello xyz'  
demo/questions/tutorial.yaml 0 → 100644
@@ -0,0 +1,609 @@ @@ -0,0 +1,609 @@
  1 +---
  2 +# ----------------------------------------------------------------------------
  3 +- type: information
  4 + ref: tut-test
  5 + title: Configuração do teste
  6 + text: |
  7 + O teste é configurado num ficheiro `yaml`
  8 + (ver especificação [aqui](https://yaml.org)).
  9 + A configuração contém a identificação do teste, base de dados dos alunos,
  10 + ficheiros de perguntas a importar e uma selecção de perguntas e respectivas
  11 + cotações.
  12 +
  13 + Exemplo:
  14 +
  15 + ```yaml
  16 + ---
  17 + # --------------------------------------------------------------------------
  18 + ref: tutorial # referência, pode ser reusada em vários turnos
  19 + title: Demonstração # título da prova
  20 + database: students.db # base de dados previamente criada com initdb
  21 + answers_dir: ans # directório onde ficam os testes dos alunos
  22 +
  23 + # opcionais
  24 + duration: 60 # duração da prova em minutos (default: inf)
  25 + autosubmit: true # submissão automática (default: false)
  26 + show_points: true # mostra cotação das perguntas (default: true)
  27 + scale: [0, 20] # normaliza cotações para o intervalo indicado.
  28 + # não normaliza por defeito (default: None)
  29 +
  30 + # --------------------------------------------------------------------------
  31 + # Ficheiros de perguntas a importar (relativamente a `questions_dir`)
  32 + files:
  33 + - tabelas.yaml
  34 + - topic1/questions.yaml
  35 + - topic2/part1/questions.yaml
  36 + - topic2/part2/questions.yaml
  37 +
  38 + # --------------------------------------------------------------------------
  39 + # Especificação das perguntas do teste e respectivas cotações.
  40 + # O teste é uma lista de perguntas, onde cada pergunta é especificada num
  41 + # dicionário com a referência da pergunta e a respectiva cotação.
  42 + questions:
  43 + - ref: pergunta1
  44 + points: 3.5
  45 +
  46 + - ref: pergunta2
  47 + points: 2.0
  48 +
  49 + # por defeinto, a cotação da pergunta é 1.0 valor
  50 + - ref: pergunta3
  51 +
  52 + # escolhe aleatoriamente uma das variantes da pergunta
  53 + - ref: [pergunta3a, pergunta3b]
  54 + points: 0.5
  55 +
  56 + # --------------------------------------------------------------------------
  57 + ```
  58 +
  59 + A ordem das perguntas é mantida quando apresentada no teste.
  60 +
  61 + O mesmo teste pode ser realizado várias vezes em turnos diferentes, não é
  62 + necessário alterar nada.
  63 +
  64 +# ----------------------------------------------------------------------------
  65 +- type: information
  66 + ref: tut-questions
  67 + title: Especificação das perguntas
  68 + text: |
  69 + As perguntas estão definidas num ou mais ficheiros `yaml` como uma lista de
  70 + perguntas, onde cada pergunta é um dicionário.
  71 +
  72 + Por exemplo, um ficheiro com o conteúdo abaixo contém duas perguntas, uma
  73 + de escolha múltipla e outra apenas informativa:
  74 +
  75 + ```yaml
  76 + ---
  77 + #---------------------------------------------------------------------------
  78 + - type: radio
  79 + ref: chave-unica-1
  80 + text: Quanto é $1+1$?
  81 + options:
  82 + - 1
  83 + - 2
  84 + - 3
  85 +
  86 + #---------------------------------------------------------------------------
  87 + - type: information
  88 + ref: chave-unica-2
  89 + text: |
  90 + Quando o texto da pergunta tem várias linhas, dá jeito usar o símbolo
  91 + `|` de pipe, para indicar que tudo o que estiver indentado faz parte do
  92 + texto. É o caso desta pergunta.
  93 +
  94 + O texto das perguntas é escrito em `markdown` e suporta fórmulas em
  95 + LaTeX.
  96 +
  97 + #---------------------------------------------------------------------------
  98 + ```
  99 +
  100 + As chaves são usadas para construir o teste e não se podem repetir, mesmo
  101 + em ficheiros diferentes.
  102 + De seguida mostram-se exemplos dos vários tipos de perguntas.
  103 +
  104 +# ----------------------------------------------------------------------------
  105 +- type: radio
  106 + ref: tut-radio
  107 + title: Escolha simples, uma opção correcta.
  108 + text: |
  109 + As perguntas de escolha simples, permitem fazer uma pergunta e apresentar
  110 + várias opções de resposta em que apenas uma delas está certa.
  111 + A utilização mais simples é a seguinte:
  112 +
  113 + ```yaml
  114 + - type: radio
  115 + ref: pergunta-1
  116 + title: Escolha simples, uma opção correcta.
  117 + text: |
  118 + Bla bla bla.
  119 + options:
  120 + - Opção 0
  121 + - Opção 1
  122 + - Opção 2
  123 + - Opção 3
  124 + - Opção 4
  125 + ```
  126 +
  127 + Sem outras configurações, assume-se que a primeira opção é a resposta
  128 + correcta ("Opção 0" neste caso) e as 5 opções são apresentadas por ordem
  129 + aleatória.
  130 +
  131 + Para evitar que os alunos memorizem os textos das opções, podem definir-se
  132 + várias opções correctas com escrita ligeiramente diferente, sendo escolhida
  133 + apenas uma delas para apresentação.
  134 + Por exemplo, se as 2 primeiras opções estiverem correctas e as restantes
  135 + erradas, e quisermos apresentar ao aluno 3 opções no total, acrescenta-se:
  136 +
  137 + ```yaml
  138 + correct: [1, 1, 0, 0, 0]
  139 + choose: 3
  140 + ```
  141 +
  142 + Neste caso, será escolhida uma opção certa e duas erradas.
  143 + Os valores em `correct` representam o grau de correcção no intervalo [0, 1]
  144 + onde 1 representa 100% certo e 0 representa 0%. Podem ser usados valores
  145 + entre 0 e 1, sendo atribuída a respectiva cotação, mas só o valor 1
  146 + representa uma opção certa.
  147 +
  148 + Por defeito, as opções são apresentadas por ordem aleatória, mas é possível
  149 + usar a ordem predefinida. Por exemplo, para manter a ordem e indicar que a
  150 + resposta correcta é a do meio define-se:
  151 +
  152 + ```yaml
  153 + correct: [0, 0, 1, 0, 0]
  154 + shuffle: false
  155 + ```
  156 +
  157 + As respostas erradas descontam, tendo uma cotação de $-1/(n-1)$ do valor da
  158 + pergunta, onde $n$ é o número de opções apresentadas ao aluno (a ideia é o
  159 + valor esperado ser zero quando as respostas são aleatórias e uniformemente
  160 + distribuídas). Para não descontar acrescenta-se:
  161 +
  162 + ```yaml
  163 + discount: false
  164 + ```
  165 + options:
  166 + - Opção 0 (certa)
  167 + - Opção 1 (certa)
  168 + - Opção 2
  169 + - Opção 3
  170 + - Opção 4
  171 + correct: [1, 1, 0, 0, 0]
  172 + choose: 3
  173 + solution: |
  174 + A solução correcta é a **Opção 0** ou a **Opção 1**.
  175 +
  176 +# ----------------------------------------------------------------------------
  177 +- type: checkbox
  178 + ref: tut-checkbox
  179 + title: Escolha múltipla, várias opções correctas
  180 + text: |
  181 + As perguntas de escolha múltipla permitem apresentar um conjunto de opções
  182 + podendo ser seleccionadas várias em simultâneo.
  183 + Funcionam como múltiplas perguntas independentes de resposta sim/não.
  184 +
  185 + As respostas que devem ou não ser seleccionadas são indicadas com `1` e `0`
  186 + ou com booleanos `true` e `false`.
  187 + Cada resposta errada desconta um valor que é o simétrico da resposta certa.
  188 + Se acertar uma opção ganha `+1`, se errar obtém `-1`.
  189 +
  190 + ```yaml
  191 + - type: checkbox
  192 + ref: tut-checkbox
  193 + title: Escolha múltipla, várias opções correctas
  194 + text: |
  195 + Bla bla bla.
  196 + options:
  197 + - Opção 0 (certa)
  198 + - Opção 1
  199 + - Opção 2
  200 + - Opção 3 (certa)
  201 + - Opção 4
  202 + correct: [1, 0, 0, 1, 0]
  203 + ```
  204 +
  205 + Neste exemplo, seleccionando as opções 0 e 3 obtém-se cotação `+1` em cada
  206 + uma, enquanto que seleccionando erradamente as opções 1, 2 e 4 obtém-se
  207 + cotação `-1`.
  208 + Do mesmo modo, não seleccionando as opções certas 0 e 3 obtém-se a cotação
  209 + `-1` em cada uma, e não seleccionando (correctamente) as 1, 2 e 4 obtém-se
  210 + `+1` em cada.
  211 +
  212 + *(Neste tipo de perguntas não há forma de responder a apenas algumas delas,
  213 + são sempre todas corrigidas. Se um aluno só sabe a resposta a algumas das
  214 + opções, deve ter cuidado porque as restantes também serão classificadas e
  215 + arrisca-se a ter cotação negativa)*
  216 +
  217 + Cada opção pode opcionalmente ser escrita como uma afirmação e o seu
  218 + contrário, de maneira a aumentar a variabilidade dos textos.
  219 + Por exemplo:
  220 +
  221 + ```yaml
  222 + options:
  223 + - ['O céu é azul', 'O céu não é azul']
  224 + - ['Um triangulo tem 3 lados', 'Um triangulo tem 2 lados']
  225 + - O nosso planeta tem um satélite natural
  226 + correct: [1, 1, 1]
  227 + ```
  228 +
  229 + Assume-se que a primeira alternativa de cada opção tem a cotação indicada
  230 + em `correct`, enquanto a segunda alternativa tem a cotação contrária.
  231 +
  232 + Tal como nas perguntas do tipo `radio`, podem ser usadas as configurações
  233 + `shuffle` e `discount` com valor `false` para as desactivar.
  234 + Se `discount` é `false` então as respostas erradas têm cotação 0 em vez do
  235 + simétrico.
  236 + options:
  237 + - ['Opção 0 (sim)', 'Opção 0 (não)']
  238 + - ['Opção 1 (não)', 'Opção 1 (sim)']
  239 + - Opção 2 (não)
  240 + - Opção 3 (sim)
  241 + correct: [1, 0, 0, 1]
  242 + shuffle: false
  243 +
  244 +# ----------------------------------------------------------------------------
  245 +- type: text
  246 + ref: tut-text
  247 + title: Resposta de texto em linha
  248 + text: |
  249 + Este tipo de perguntas permite uma resposta numa linha de texto. A resposta
  250 + está correcta se coincidir exactamente com alguma das respostas admissíveis.
  251 +
  252 + ```yaml
  253 + - type: text
  254 + ref: tut-text
  255 + title: Resposta de texto em linha
  256 + text: |
  257 + De que cor é o céu?
  258 +
  259 + Escreva a resposta em português.
  260 + correct: ['azul', 'Azul', 'AZUL']
  261 + ```
  262 +
  263 + Neste caso, as respostas aceites são `azul`, `Azul` ou `AZUL`.
  264 +
  265 + Em alguns casos pode ser conveniente transformar a resposta antes de a
  266 + comparar, por exemplo para remover espaços ou converter para minúsculas.
  267 + A opção `transform` permite dar uma sequência de transformações a aplicar à
  268 + resposta do aluno, por exemplo:
  269 +
  270 + ```yaml
  271 + transform: ['trim', 'lower']
  272 + correct: ['azul']
  273 + ```
  274 +
  275 + Estão disponíveis as seguintes transformações:
  276 +
  277 + * `trim` remove os espaços do início e fim da resposta, os espaços do meio
  278 + mantêm-se inalterados.
  279 + * `remove_space` remove todos os espaços (início, meio e fim).
  280 + * `normalize_space` remove espaços do início e fim (trim), e substitui
  281 + múltiplos espaços por um único espaço (no meio).
  282 + * `lower` e `upper` convertem respectivamente para minúsculas e maiúsculas.
  283 + transform: ['trim', 'lower']
  284 + correct: ['azul']
  285 + solution: |
  286 + O céu é `azul`, pelo menos durante o dia e se estiver bom tempo...
  287 +
  288 +# ---------------------------------------------------------------------------
  289 +- type: text-regex
  290 + ref: tut-text-regex
  291 + title: Resposta de texto em linha, expressão regular
  292 + text: |
  293 + Este tipo de pergunta é semelhante à linha de texto da pergunta anterior.
  294 + A única diferença é que esta é validada por uma expressão regular.
  295 +
  296 + ```yaml
  297 + - type: text-regex
  298 + ref: tut-text-regex
  299 + title: Resposta de texto em linha
  300 + text: |
  301 + Bla bla bla
  302 + correct: '(VERDE|[Vv]erde)'
  303 + ```
  304 +
  305 + Neste exemplo a expressão regular é `(VERDE|[Vv]erde)`.
  306 +
  307 + Também se pode dar uma lista de expressões regulares. Nesse caso a resposta
  308 + é considerada correcta se fizer match com alguma delas.
  309 + No exemplo acima, poder-se-ia ter usado uma lista
  310 +
  311 + ```yaml
  312 + correct:
  313 + - 'VERDE'
  314 + - '[Vv]erde'
  315 + ```
  316 +
  317 + ---
  318 +
  319 + **Atenção:** A expressão regular deve seguir as convenções da suportadas em
  320 + python (ver
  321 + [Regular expression operations](https://docs.python.org/3/library/re.html)).
  322 + Em particular, a expressão regular acima também aceita a resposta
  323 + `verde, azul`.
  324 + Deve marcar-se o início e final `^(VERDE|[Vv]erde)$` para evitar estas
  325 + situações.
  326 +
  327 + correct: '(VERDE|[Vv]erde)'
  328 + solution: |
  329 + Deveria ter escrito `VERDE` ou `Verde` ou `verde`.
  330 +
  331 +# ---------------------------------------------------------------------------
  332 +- type: numeric-interval
  333 + ref: tut-numeric-interval
  334 + title: Resposta numérica em linha de texto
  335 + text: |
  336 + Este tipo de perguntas esperam uma resposta numérica (vírgula flutuante).
  337 + O resultado é considerado correcto se estiver dentro do intervalo fechado
  338 + indicado.
  339 +
  340 + ```yaml
  341 + - type: numeric-interval
  342 + ref: tut-numeric-interval
  343 + title: Resposta numérica em linha de texto
  344 + text: |
  345 + Escreva o número $\pi$ com pelo menos duas casa decimais.
  346 + correct: [3.14, 3.15]
  347 + ```
  348 +
  349 + Neste exemplo o intervalo de respostas correctas é o intervalo fechado
  350 + [3.14, 3.15].
  351 +
  352 + Se em vez de dar um intervalo, apenas for indicado um valor numérico $n$,
  353 + este é automaticamente convertido para para um intervalo $[n,n]$.
  354 +
  355 + **Atenção:** as respostas têm de usar o ponto como separador decimal.
  356 + Em geral são aceites números inteiros, como `123`,
  357 + ou em vírgula flutuante, como em `0.23`, `1e-3`.
  358 + correct: [3.14, 3.15]
  359 + solution: |
  360 + Sabemos que $\pi\approx 3.14159265359$.
  361 + Portanto, um exemplo de uma resposta correcta é `3.1416`.
  362 +
  363 +# ---------------------------------------------------------------------------
  364 +- type: textarea
  365 + ref: tut-textarea
  366 + title: Resposta em múltiplas linhas de texto
  367 + text: |
  368 + Este tipo de perguntas permitem respostas em múltiplas linhas de texto e
  369 + são as mais flexíveis.
  370 +
  371 + A resposta é enviada para um programa externo para ser avaliada.
  372 + O programa externo é um programa que tem de ser executável pelo pelo
  373 + sistema operativo (pode ser um binário ou script desde que o respectivo
  374 + interpretador instalado).
  375 + Este programa externo recebe a resposta submetida pelo aluno via `stdin` e
  376 + devolve a classificação via `stdout`.
  377 + Exemplo:
  378 +
  379 + ```yaml
  380 + - type: textarea
  381 + ref: tut-textarea
  382 + title: Resposta em múltiplas linhas de texto
  383 + text: |
  384 + Bla bla bla
  385 + correct: correct-question.py # programa a executar
  386 + timeout: 5
  387 + ```
  388 +
  389 + Neste exemplo, o programa de avaliação é um script python que verifica se a
  390 + resposta contém as três palavras red, green e blue, e calcula uma nota no
  391 + intervalo 0.0 a 1.0.
  392 + O programa externo é executado num processo separado e a interacção faz-se
  393 + via stdin/stdout.
  394 +
  395 + Se o programa externo exceder o `timeout` indicado (em segundos),
  396 + este é automaticamente terminado e é atribuída a classificação de 0.0
  397 + valores na pergunta.
  398 +
  399 + Após terminar a correcção, o programa externo deve enviar a classificação
  400 + para o stdout.
  401 + Pode simplesmente fazer `print` da classificação como um número em vírgula
  402 + flutuante, por exemplo
  403 +
  404 + ```yaml
  405 + 0.75
  406 + ```
  407 +
  408 + ou opcionalmente escrever em formato json ou yaml, eventualmente com um
  409 + comentário que será arquivado com o teste.
  410 + Exemplo:
  411 +
  412 + ```yaml
  413 + grade: 0.5
  414 + comments: |
  415 + Esqueceu-se de algumas cores.
  416 + A resposta correcta era `red green blue`.
  417 + ```
  418 +
  419 + O comentário é mostrado na revisão de prova.
  420 + answer: |
  421 + Aqui o aluno escreve a resposta.
  422 + Esta caixa aumenta de tamanho automaticamente e
  423 + pode estar previamente preenchida como neste caso (use `answer: texto`).
  424 + correct: correct-question.py
  425 + timeout: 5
  426 + tests_right:
  427 + - 'red green blue'
  428 + # tests_wrong:
  429 + # - 'blue gray yellow'
  430 +
  431 +# ---------------------------------------------------------------------------
  432 +- type: information
  433 + ref: tut-information
  434 + title: Texto informativo
  435 + text: |
  436 + As perguntas deste tipo não contam para avaliação. O objectivo é fornecer
  437 + instruções para os alunos, por exemplo tabelas para consulta, fórmulas, etc.
  438 + Nesta, tal como em todos os tipos de perguntas podem escrever-se fórmulas
  439 + em LaTeX. Exemplo:
  440 +
  441 + A distribuição gaussiana $\mathcal{N}(x\mid\mu,\sigma^2)$ é
  442 + definida pela função densidade de probabilidade
  443 +
  444 + $$
  445 + p(x) = \frac{1}{\sqrt{2\pi\sigma^2}}
  446 + \exp\Big({-\frac{(x-\mu)^2}{2\sigma^2}}\Big).
  447 + $$
  448 +
  449 + ---
  450 +
  451 + ```yaml
  452 + - type: information
  453 + ref: tut-information
  454 + title: Texto informativo
  455 + text: |
  456 + A distribuição gaussiana $\mathcal{N}(x\mid\mu,\sigma^2)$ é
  457 + definida pela função densidade de probabilidade
  458 +
  459 + $$
  460 + p(x) = \frac{1}{\sqrt{2\pi\sigma^2}}
  461 + \exp\Big({-\frac{(x-\mu)^2}{2\sigma^2}}\Big).
  462 + $$
  463 + ```
  464 +
  465 +# ---------------------------------------------------------------------------
  466 +- type: success
  467 + ref: tut-success
  468 + title: Texto informativo (sucesso)
  469 + text: |
  470 + Não conta para avaliação. É apenas o aspecto gráfico que muda.
  471 +
  472 + Um pedaço de código em linha, por exemplo `x = sqrt(z)` é marcado com uma
  473 + fonte e cor diferente.
  474 + Também se podem escrever troços de código coloridos conforme a linguagem:
  475 +
  476 + ```C
  477 + int main() {
  478 + printf("Hello world!");
  479 + return 0; // comentario
  480 + }
  481 + ```
  482 +
  483 + ---
  484 +
  485 + ```yaml
  486 + - type: success
  487 + ref: tut-success
  488 + title: Texto informativo (sucesso)
  489 + text: |
  490 + Não conta para avaliação. É apenas o aspecto gráfico que muda.
  491 +
  492 + Um pedaço de código em linha, por exemplo `x = sqrt(z)` é marcado com
  493 + uma fonte e cor diferente.
  494 + Também se podem escrever troços de código coloridos conforme a
  495 + linguagem:
  496 +
  497 + ```C
  498 + int main() {
  499 + printf("Hello world!");
  500 + return 0; // comentario
  501 + }
  502 + ```
  503 +
  504 + ```
  505 +
  506 +# ---------------------------------------------------------------------------
  507 +- type: warning
  508 + ref: tut-warning
  509 + title: Texto informativo (aviso)
  510 + text: |
  511 + Não conta para avaliação.
  512 +
  513 + Neste exemplo mostramos como se pode construir uma tabela como a seguinte:
  514 +
  515 + Left | Center | Right
  516 + -----------------|:----------------:|----------:
  517 + *hello* | $\sin(x^2)$ | $1600.00
  518 + **world** | $\frac{1}{2\pi}$ | $12.50
  519 + `code` | $\sqrt{\pi}$ | $1.99
  520 +
  521 + As tabelas podem conter Markdown e LaTeX e permitem alinhamento das colunas,
  522 + mas o markdown é muito simples e não permite mais funcionalidades.
  523 +
  524 + ---
  525 +
  526 + ```yaml
  527 + - type: warning
  528 + ref: tut-warning
  529 + title: Texto informativo (aviso)
  530 + text: |
  531 + Bla bla bla
  532 +
  533 + Left | Center | Right
  534 + -----------------|:----------------:|----------:
  535 + *hello* | $\sin(x^2)$ | $1600.00
  536 + **world** | $\frac{1}{2\pi}$ | $12.50
  537 + `code` | $\sqrt{\pi}$ | $1.99
  538 + ```
  539 +
  540 +# ----------------------------------------------------------------------------
  541 +- type: alert
  542 + ref: tut-alert1
  543 + title: Texto informativo (perigo) - versão 1
  544 + text: |
  545 + Não conta para avaliação. Texto importante.
  546 +
  547 + ![planetas](planets.png "Planetas do Sistema Solar")
  548 +
  549 + As imagens podem ser adicionadas usando a notação standard em markdown. Há
  550 + duas possibilidads:
  551 +
  552 + - Imagens inline: não têm título definido e podem ser incluídas no meio de
  553 + uma linha de texto usando`![alt text](image.jpg)`.
  554 + - Imagens centradas com título: `![alt text](image.jpg "Título da imagem")`.
  555 + O título é colocado por baixo da imagem. Pode ser uma string vazia.
  556 +
  557 +- type: alert
  558 + ref: tut-alert2
  559 + title: Texto informativo (perigo) - versão 2
  560 + text: |
  561 + Não conta para avaliação. Texto importante.
  562 +
  563 + ![planetas](planets.png "Planetas do Sistema Solar")
  564 +
  565 + As imagens podem ser adicionadas usando a notação standard em markdown. Há
  566 + duas possibilidads:
  567 +
  568 + - Imagens inline: não têm título definido e podem ser incluídas no meio de
  569 + uma linha de texto usando `![alt text](image.jpg)`.
  570 + - Imagens centradas com título: `![alt text](image.jpg "Título da imagem")`.
  571 + O título é colocado por baixo da imagem. Pode ser uma string vazia.
  572 +
  573 +# ----------------------------------------------------------------------------
  574 +- type: information
  575 + text: |
  576 + This question is not included in the test and will not show up.
  577 + It also lacks a "ref" and is automatically named
  578 + `questions/questions-tutorial.yaml:0013`.
  579 + A warning is shown on the console about this.
  580 + The number at the end is the index position of this question.
  581 + Indices start at 0.
  582 +
  583 +# ----------------------------------------------------------------------------
  584 +- type: generator
  585 + ref: tut-generator
  586 + script: generate-question.py
  587 + args: [1, 100]
  588 +
  589 +# ----------------------------------------------------------------------------
  590 +- type: information
  591 + ref: tut-yamllint
  592 + title: Sugestões para validar yaml
  593 + text: |
  594 + Como os testes e perguntas são ficheiros `yaml`, é conveniente validar se
  595 + estão correctamente definitos. Um *linter* recomendado é o `yamllint`. Pode
  596 + ser instalado com `pip install yamllint` e usado do seguinte modo:
  597 +
  598 + ```sh
  599 + yamllint test.yaml
  600 + yamllint questions.yaml
  601 + ```
  602 +
  603 + No caso de programas geradores de perguntas e programas de correcção de
  604 + respostas pode usar-se um *pipe*:
  605 +
  606 + ```sh
  607 + generate-question | yamllint -
  608 + correct-answer | yamllint -
  609 + ```