--- # ---------------------------------------------------------------------------- - type: information ref: tut-test title: Configuração do teste text: | O teste é configurado num ficheiro `yaml` (ver especificação [aqui](https://yaml.org)). A configuração contém a identificação do teste, base de dados dos alunos, ficheiros de perguntas a importar e uma selecção de perguntas e respectivas cotações. Exemplo: ```yaml --- # -------------------------------------------------------------------------- ref: tutorial # referência, pode ser reusada em vários turnos title: Demonstração # título da prova database: students.db # base de dados previamente criada com initdb answers_dir: ans # directório onde ficam os testes dos alunos # opcionais duration: 60 # duração da prova em minutos (default: inf) autosubmit: true # submissão automática (default: false) show_points: true # mostra cotação das perguntas (default: true) scale: [0, 20] # normaliza cotações para o intervalo indicado. # não normaliza por defeito (default: None) # -------------------------------------------------------------------------- # Ficheiros de perguntas a importar (relativamente a `questions_dir`) files: - tabelas.yaml - topic1/questions.yaml - topic2/part1/questions.yaml - topic2/part2/questions.yaml # -------------------------------------------------------------------------- # Especificação das perguntas do teste e respectivas cotações. # O teste é uma lista de perguntas, onde cada pergunta é especificada num # dicionário com a referência da pergunta e a respectiva cotação. questions: - ref: pergunta1 points: 3.5 - ref: pergunta2 points: 2.0 # por defeinto, a cotação da pergunta é 1.0 valor - ref: pergunta3 # escolhe aleatoriamente uma das variantes da pergunta - ref: [pergunta3a, pergunta3b] points: 0.5 # -------------------------------------------------------------------------- ``` A ordem das perguntas é mantida quando apresentada no teste. O mesmo teste pode ser realizado várias vezes em turnos diferentes, não é necessário alterar nada. # ---------------------------------------------------------------------------- - type: information ref: tut-questions title: Especificação das perguntas text: | As perguntas estão definidas num ou mais ficheiros `yaml` como uma lista de perguntas, onde cada pergunta é um dicionário. Por exemplo, um ficheiro com o conteúdo abaixo contém duas perguntas, uma de escolha múltipla e outra apenas informativa: ```yaml --- #--------------------------------------------------------------------------- - type: radio ref: chave-unica-1 text: Quanto é $1+1$? options: - 1 - 2 - 3 #--------------------------------------------------------------------------- - type: information ref: chave-unica-2 text: | Quando o texto da pergunta tem várias linhas, dá jeito usar o símbolo `|` de pipe, para indicar que tudo o que estiver indentado faz parte do texto. É o caso desta pergunta. O texto das perguntas é escrito em `markdown` e suporta fórmulas em LaTeX. #--------------------------------------------------------------------------- ``` As chaves são usadas para construir o teste e não se podem repetir, mesmo em ficheiros diferentes. De seguida mostram-se exemplos dos vários tipos de perguntas. # ---------------------------------------------------------------------------- - type: radio ref: tut-radio title: Escolha simples, uma opção correcta. text: | As perguntas de escolha simples, permitem fazer uma pergunta e apresentar várias opções de resposta em que apenas uma delas está certa. A utilização mais simples é a seguinte: ```yaml - type: radio ref: pergunta-1 title: Escolha simples, uma opção correcta. text: | Bla bla bla. options: - Opção 0 - Opção 1 - Opção 2 - Opção 3 - Opção 4 ``` Sem outras configurações, assume-se que a primeira opção é a resposta correcta ("Opção 0" neste caso) e as 5 opções são apresentadas por ordem aleatória. Para evitar que os alunos memorizem os textos das opções, podem definir-se várias opções correctas com escrita ligeiramente diferente, sendo escolhida apenas uma delas para apresentação. Por exemplo, se as 2 primeiras opções estiverem correctas e as restantes erradas, e quisermos apresentar ao aluno 3 opções no total, acrescenta-se: ```yaml correct: [1, 1, 0, 0, 0] choose: 3 ``` Neste caso, será escolhida uma opção certa e duas erradas. Os valores em `correct` representam o grau de correcção no intervalo [0, 1] onde 1 representa 100% certo e 0 representa 0%. Podem ser usados valores entre 0 e 1, sendo atribuída a respectiva cotação, mas só o valor 1 representa uma opção certa. Por defeito, as opções são apresentadas por ordem aleatória, mas é possível usar a ordem predefinida. Por exemplo, para manter a ordem e indicar que a resposta correcta é a do meio define-se: ```yaml correct: [0, 0, 1, 0, 0] shuffle: false ``` As respostas erradas descontam, tendo uma cotação de $-1/(n-1)$ do valor da pergunta, onde $n$ é o número de opções apresentadas ao aluno (a ideia é o valor esperado ser zero quando as respostas são aleatórias e uniformemente distribuídas). Para não descontar acrescenta-se: ```yaml discount: false ``` options: - Opção 0 (certa) - Opção 1 (certa) - Opção 2 - Opção 3 - Opção 4 correct: [1, 1, 0, 0, 0] choose: 3 solution: | A solução correcta é a **Opção 0** ou a **Opção 1**. # ---------------------------------------------------------------------------- - type: checkbox ref: tut-checkbox title: Escolha múltipla, várias opções correctas text: | As perguntas de escolha múltipla permitem apresentar um conjunto de opções podendo ser seleccionadas várias em simultâneo. Funcionam como múltiplas perguntas independentes de resposta sim/não. As respostas que devem ou não ser seleccionadas são indicadas com `1` e `0` ou com booleanos `true` e `false`. Cada resposta errada desconta um valor que é o simétrico da resposta certa. Se acertar uma opção ganha `+1`, se errar obtém `-1`. ```yaml - type: checkbox ref: tut-checkbox title: Escolha múltipla, várias opções correctas text: | Bla bla bla. options: - Opção 0 (certa) - Opção 1 - Opção 2 - Opção 3 (certa) - Opção 4 correct: [1, 0, 0, 1, 0] ``` Neste exemplo, seleccionando as opções 0 e 3 obtém-se cotação `+1` em cada uma, enquanto que seleccionando erradamente as opções 1, 2 e 4 obtém-se cotação `-1`. Do mesmo modo, não seleccionando as opções certas 0 e 3 obtém-se a cotação `-1` em cada uma, e não seleccionando (correctamente) as 1, 2 e 4 obtém-se `+1` em cada. *(Neste tipo de perguntas não há forma de responder a apenas algumas delas, são sempre todas corrigidas. Se um aluno só sabe a resposta a algumas das opções, deve ter cuidado porque as restantes também serão classificadas e arrisca-se a ter cotação negativa)* Cada opção pode opcionalmente ser escrita como uma afirmação e o seu contrário, de maneira a aumentar a variabilidade dos textos. Por exemplo: ```yaml options: - ['O céu é azul', 'O céu não é azul'] - ['Um triangulo tem 3 lados', 'Um triangulo tem 2 lados'] - O nosso planeta tem um satélite natural correct: [1, 1, 1] ``` Assume-se que a primeira alternativa de cada opção tem a cotação indicada em `correct`, enquanto a segunda alternativa tem a cotação contrária. Tal como nas perguntas do tipo `radio`, podem ser usadas as configurações `shuffle` e `discount` com valor `false` para as desactivar. Se `discount` é `false` então as respostas erradas têm cotação 0 em vez do simétrico. options: - ['Opção 0 (sim)', 'Opção 0 (não)'] - ['Opção 1 (não)', 'Opção 1 (sim)'] - Opção 2 (não) - Opção 3 (sim) correct: [1, 0, 0, 1] shuffle: false # ---------------------------------------------------------------------------- - type: text ref: tut-text title: Resposta de texto em linha text: | Este tipo de perguntas permite uma resposta numa linha de texto. A resposta está correcta se coincidir exactamente com alguma das respostas admissíveis. ```yaml - type: text ref: tut-text title: Resposta de texto em linha text: | De que cor é o céu? Escreva a resposta em português. correct: ['azul', 'Azul', 'AZUL'] ``` Neste caso, as respostas aceites são `azul`, `Azul` ou `AZUL`. Em alguns casos pode ser conveniente transformar a resposta antes de a comparar, por exemplo para remover espaços ou converter para minúsculas. A opção `transform` permite dar uma sequência de transformações a aplicar à resposta do aluno, por exemplo: ```yaml transform: ['trim', 'lower'] correct: ['azul'] ``` Estão disponíveis as seguintes transformações: * `trim` remove os espaços do início e fim da resposta, os espaços do meio mantêm-se inalterados. * `remove_space` remove todos os espaços (início, meio e fim). * `normalize_space` remove espaços do início e fim (trim), e substitui múltiplos espaços por um único espaço (no meio). * `lower` e `upper` convertem respectivamente para minúsculas e maiúsculas. transform: ['trim', 'lower'] correct: ['azul'] solution: | O céu é `azul`, pelo menos durante o dia e se estiver bom tempo... # --------------------------------------------------------------------------- - type: text-regex ref: tut-text-regex title: Resposta de texto em linha, expressão regular text: | Este tipo de pergunta é semelhante à linha de texto da pergunta anterior. A única diferença é que esta é validada por uma expressão regular. ```yaml - type: text-regex ref: tut-text-regex title: Resposta de texto em linha text: | Bla bla bla correct: '(VERDE|[Vv]erde)' ``` Neste exemplo a expressão regular é `(VERDE|[Vv]erde)`. Também se pode dar uma lista de expressões regulares. Nesse caso a resposta é considerada correcta se fizer match com alguma delas. No exemplo acima, poder-se-ia ter usado uma lista ```yaml correct: - 'VERDE' - '[Vv]erde' ``` --- **Atenção:** A expressão regular deve seguir as convenções da suportadas em python (ver [Regular expression operations](https://docs.python.org/3/library/re.html)). Em particular, a expressão regular acima também aceita a resposta `verde, azul`. Deve marcar-se o início e final `^(VERDE|[Vv]erde)$` para evitar estas situações. correct: '(VERDE|[Vv]erde)' solution: | Deveria ter escrito `VERDE` ou `Verde` ou `verde`. # --------------------------------------------------------------------------- - type: numeric-interval ref: tut-numeric-interval title: Resposta numérica em linha de texto text: | Este tipo de perguntas esperam uma resposta numérica (vírgula flutuante). O resultado é considerado correcto se estiver dentro do intervalo fechado indicado. ```yaml - type: numeric-interval ref: tut-numeric-interval title: Resposta numérica em linha de texto text: | Escreva o número $\pi$ com pelo menos duas casa decimais. correct: [3.14, 3.15] ``` Neste exemplo o intervalo de respostas correctas é o intervalo fechado [3.14, 3.15]. Se em vez de dar um intervalo, apenas for indicado um valor numérico $n$, este é automaticamente convertido para para um intervalo $[n,n]$. **Atenção:** as respostas têm de usar o ponto como separador decimal. Em geral são aceites números inteiros, como `123`, ou em vírgula flutuante, como em `0.23`, `1e-3`. correct: [3.14, 3.15] solution: | Sabemos que $\pi\approx 3.14159265359$. Portanto, um exemplo de uma resposta correcta é `3.1416`. # --------------------------------------------------------------------------- - type: textarea ref: tut-textarea title: Resposta em múltiplas linhas de texto text: | Este tipo de perguntas permitem respostas em múltiplas linhas de texto e são as mais flexíveis. A resposta é enviada para um programa externo para ser avaliada. O programa externo é um programa que tem de ser executável pelo pelo sistema operativo (pode ser um binário ou script desde que o respectivo interpretador instalado). Este programa externo recebe a resposta submetida pelo aluno via `stdin` e devolve a classificação via `stdout`. Exemplo: ```yaml - type: textarea ref: tut-textarea title: Resposta em múltiplas linhas de texto text: | Bla bla bla correct: correct/correct-question.py # programa a executar timeout: 5 ``` Neste exemplo, o programa de avaliação é um script python que verifica se a resposta contém as três palavras red, green e blue, e calcula uma nota no intervalo 0.0 a 1.0. O programa externo é executado num processo separado e a interacção faz-se via stdin/stdout. Se o programa externo exceder o `timeout` indicado (em segundos), este é automaticamente terminado e é atribuída a classificação de 0.0 valores na pergunta. Após terminar a correcção, o programa externo deve enviar a classificação para o stdout. Pode simplesmente fazer `print` da classificação como um número em vírgula flutuante, por exemplo ```yaml 0.75 ``` ou opcionalmente escrever em formato json ou yaml, eventualmente com um comentário que será arquivado com o teste. Exemplo: ```yaml grade: 0.5 comments: | Esqueceu-se de algumas cores. A resposta correcta era `red green blue`. ``` O comentário é mostrado na revisão de prova. answer: | Aqui o aluno escreve a resposta. Esta caixa aumenta de tamanho automaticamente e pode estar previamente preenchida como neste caso (use `answer: texto`). correct: correct/correct-question.py timeout: 5 tests_right: - 'red green blue' # tests_wrong: # - 'blue gray yellow' # --------------------------------------------------------------------------- - type: information ref: tut-information title: Texto informativo text: | As perguntas deste tipo não contam para avaliação. O objectivo é fornecer instruções para os alunos, por exemplo tabelas para consulta, fórmulas, etc. Nesta, tal como em todos os tipos de perguntas podem escrever-se fórmulas em LaTeX. Exemplo: A distribuição gaussiana $\mathcal{N}(x\mid\mu,\sigma^2)$ é definida pela função densidade de probabilidade $$ p(x) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\Big({-\frac{(x-\mu)^2}{2\sigma^2}}\Big). $$ --- ```yaml - type: information ref: tut-information title: Texto informativo text: | A distribuição gaussiana $\mathcal{N}(x\mid\mu,\sigma^2)$ é definida pela função densidade de probabilidade $$ p(x) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\Big({-\frac{(x-\mu)^2}{2\sigma^2}}\Big). $$ ``` # --------------------------------------------------------------------------- - type: success ref: tut-success title: Texto informativo (sucesso) text: | Não conta para avaliação. É apenas o aspecto gráfico que muda. Um pedaço de código em linha, por exemplo `x = sqrt(z)` é marcado com uma fonte e cor diferente. Também se podem escrever troços de código coloridos conforme a linguagem: ```C int main() { printf("Hello world!"); return 0; // comentario } ``` --- ```yaml - type: success ref: tut-success title: Texto informativo (sucesso) text: | Não conta para avaliação. É apenas o aspecto gráfico que muda. Um pedaço de código em linha, por exemplo `x = sqrt(z)` é marcado com uma fonte e cor diferente. Também se podem escrever troços de código coloridos conforme a linguagem: ```C int main() { printf("Hello world!"); return 0; // comentario } ``` ``` # --------------------------------------------------------------------------- - type: warning ref: tut-warning title: Texto informativo (aviso) text: | Não conta para avaliação. Neste exemplo mostramos como se pode construir uma tabela como a seguinte: Left | Center | Right -----------------|:----------------:|----------: *hello* | $\sin(x^2)$ | $1600.00 **world** | $\frac{1}{2\pi}$ | $12.50 `code` | $\sqrt{\pi}$ | $1.99 As tabelas podem conter Markdown e LaTeX e permitem alinhamento das colunas, mas o markdown é muito simples e não permite mais funcionalidades. --- ```yaml - type: warning ref: tut-warning title: Texto informativo (aviso) text: | Bla bla bla Left | Center | Right -----------------|:----------------:|----------: *hello* | $\sin(x^2)$ | $1600.00 **world** | $\frac{1}{2\pi}$ | $12.50 `code` | $\sqrt{\pi}$ | $1.99 ``` # ---------------------------------------------------------------------------- - type: alert ref: tut-alert1 title: Texto informativo (perigo) - versão 1 text: | Não conta para avaliação. Texto importante. ![planetas](planets.png "Planetas do Sistema Solar") As imagens podem ser adicionadas usando a notação standard em markdown. Há duas possibilidads: - Imagens inline: não têm título definido e podem ser incluídas no meio de uma linha de texto usando`![alt text](image.jpg)`. - Imagens centradas com título: `![alt text](image.jpg "Título da imagem")`. O título é colocado por baixo da imagem. Pode ser uma string vazia. - type: alert ref: tut-alert2 title: Texto informativo (perigo) - versão 2 text: | Não conta para avaliação. Texto importante. ![planetas](planets.png "Planetas do Sistema Solar") As imagens podem ser adicionadas usando a notação standard em markdown. Há duas possibilidads: - Imagens inline: não têm título definido e podem ser incluídas no meio de uma linha de texto usando `![alt text](image.jpg)`. - Imagens centradas com título: `![alt text](image.jpg "Título da imagem")`. O título é colocado por baixo da imagem. Pode ser uma string vazia. # ---------------------------------------------------------------------------- - type: information text: | This question is not included in the test and will not show up. It also lacks a "ref" and is automatically named `questions/questions-tutorial.yaml:0013`. A warning is shown on the console about this. The number at the end is the index position of this question. Indices start at 0. # ---------------------------------------------------------------------------- - type: generator ref: tut-generator script: generate-question.py args: [1, 100] # ---------------------------------------------------------------------------- - type: information ref: tut-yamllint title: Sugestões para validar yaml text: | Como os testes e perguntas são ficheiros `yaml`, é conveniente validar se estão correctamente definitos. Um *linter* recomendado é o `yamllint`. Pode ser instalado com `pip install yamllint` e usado do seguinte modo: ```sh yamllint test.yaml yamllint questions.yaml ``` No caso de programas geradores de perguntas e programas de correcção de respostas pode usar-se um *pipe*: ```sh generate-question | yamllint - correct-answer | yamllint - ``` # ---------------------------------------------------------------------------- # - type: code # ref: tut-code # title: Submissão de código (JOBE) # text: | # É possível enviar código para ser compilado e executado por um servidor # JOBE instalado separadamente, ver [JOBE](https://github.com/trampgeek/jobe). # ```yaml # - type: code # ref: tut-code # title: Submissão de código (JOBE) # text: | # Escreva um programa em C que recebe uma string no standard input e # mostra a mensagem `hello ` seguida da string. # Por exemplo, se o input for `Maria`, o output deverá ser `hello Maria`. # language: c # correct: # - stdin: 'Maria' # stdout: 'hello Maria' # - stdin: 'xyz' # stdout: 'hello xyz' # ``` # Existem várias linguagens suportadas pelo servidor JOBE (C, C++, Java, # Python2, Python3, Octave, Pascal, PHP). # O campo `correct` deverá ser uma lista de casos a testar. # Se um caso incluir `stdin`, este será enviado para o programa e o `stdout` # obtido será comparado com o declarado. A pergunta é considerada correcta se # todos os outputs coincidirem. # Por defeito é o usado o servidor JOBE declarado no teste. Para usar outro # diferente nesta pergunta usa-se a opção `server: 127.0.0.1` com o endereço # apropriado. # answer: | # #include # int main() { # char name[20]; # scanf("%s", name); # printf("hello %s", name); # } # # server: 192.168.1.85 # language: c # correct: # - stdin: 'Maria' # stdout: 'hello Maria' # - stdin: 'xyz' # stdout: 'hello xyz'