Initial QAML question data

This commit is contained in:
2026-05-19 13:08:48 +02:00
commit 259a84c4b2
8 changed files with 365 additions and 0 deletions

17
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,17 @@
## Co zmieniasz?
- [ ] poprawiam treść pytania
- [ ] poprawiam odpowiedź
- [ ] dodaję nowe pytanie
- [ ] dodaję/zmieniam obrazek w `img/`
- [ ] usuwam duplikat albo błąd
## Źródło / uzasadnienie
Opisz krótko skąd pochodzi poprawka albo dlaczego obecna wersja jest błędna.
## Checklist
- [ ] każde pytanie i każda odpowiedź mieści się w jednej linii
- [ ] każda odpowiedź zaczyna się od `-` albo `-|`
- [ ] obrazki użyte jako `img/...` istnieją w repozytorium

15
.github/workflows/deploy.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: Deploy Quiz Data
on:
push:
branches: [main]
jobs:
deploy:
runs-on: qaml-deploy
steps:
- uses: actions/checkout@v4
- name: Validate pytania.txt
run: php tools/validate_qaml.php pytania.txt
- name: Deploy data
run: deploy-quiz-data statystyka

14
.github/workflows/validate.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
name: Validate QAML
on:
pull_request:
push:
branches: [main]
jobs:
validate:
runs-on: qaml-validate
steps:
- uses: actions/checkout@v4
- name: Validate pytania.txt
run: php tools/validate_qaml.php pytania.txt

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
ip.txt
ip.txt.old
*.log
*.bak
*.old
.DS_Store

13
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,13 @@
# Jak zgłaszać poprawki
Poprawki zgłaszamy przez Pull Request.
Najczęstsze dobre zmiany:
- poprawienie literówki,
- oznaczenie prawidłowej odpowiedzi jako `-|`,
- usunięcie błędnej odpowiedzi,
- dopisanie źródła w komentarzu `//`,
- dodanie brakującego obrazka do `img/`.
Nie zmieniaj formatu pliku na pełny Markdown, JSON, CSV ani HTML. To repozytorium używa prostego formatu QAML opisanego w `README.md`.

203
README.md Normal file
View File

@@ -0,0 +1,203 @@
# Baza pytań quizu
To repozytorium zawiera dane quizu: `pytania.txt` oraz opcjonalny katalog `img/` z obrazkami używanymi w pytaniach.
Kod aplikacji nie jest częścią tego repozytorium. Zmiany w pytaniach należy zgłaszać przez Pull Request.
## QAML — Question Answer Markdown Lines
QAML to prosty liniowy format zapisu pytań testowych wielokrotnego wyboru.
Format wygląda jak Markdown, ale jego składnia strukturalna jest znacznie prostsza. Parser nie analizuje pełnego Markdowna. Interpretuje wyłącznie początki linii:
- linia pytania,
- linia odpowiedzi błędnej,
- linia odpowiedzi poprawnej,
- komentarz,
- pusta linia.
Treść pytania i odpowiedzi może zawierać Markdown, HTML oraz inline LaTeX, ale parser traktuje je jako zwykły tekst.
## Minimalny przykład
```text
// Przykładowa sekcja
Zaznacz zdania prawdziwe
- To jest odpowiedź błędna.
-| To jest odpowiedź poprawna.
- To jest kolejna odpowiedź błędna.
Ile wynosi $2 + 2$?
- 3
-| 4
- 5
```
## Reguły składni
### 1. Pytanie
Pytaniem jest każda niepusta linia, która:
- nie zaczyna się od znaku `-`,
- nie zaczyna się od `//`.
Pytanie musi mieścić się w jednej linii.
Poprawnie:
```text
Zaznacz zdania prawdziwe dotyczące indukcji matematycznej.
```
Niepoprawnie:
```text
Zaznacz zdania prawdziwe
dotyczące indukcji matematycznej.
```
Drugi zapis zostanie zinterpretowany jako dwa osobne pytania.
### 2. Odpowiedź błędna
Odpowiedź błędna zaczyna się od pojedynczego myślnika `-`.
Poprawne są oba style:
```text
- Odpowiedź błędna
-Odpowiedź błędna
```
Parser usuwa znak `-`, a następnie przycina białe znaki z początku i końca odpowiedzi.
### 3. Odpowiedź poprawna
Odpowiedź poprawna zaczyna się od `-|`.
Poprawne są oba style:
```text
-| Odpowiedź poprawna
-|Odpowiedź poprawna
```
Parser usuwa prefiks `-|`, a następnie przycina białe znaki z początku i końca odpowiedzi.
### 4. Pytania jednokrotnego i wielokrotnego wyboru
Format dopuszcza dowolną liczbę poprawnych odpowiedzi, w tym zero poprawnych odpowiedzi albo wszystkie odpowiedzi poprawne.
Pytanie jednokrotnego wyboru:
```text
Ile wynosi $2 + 2$?
- 3
-| 4
- 5
```
Pytanie wielokrotnego wyboru:
```text
Wskaż liczby pierwsze
-| 2
-| 3
- 4
-| 5
```
Parser nie narzuca liczby poprawnych odpowiedzi. Zero poprawnych odpowiedzi może oznaczać zadanie, w którym żadna odpowiedź nie jest prawdziwa, a oznaczenie wszystkich odpowiedzi jako `-|` może oznaczać zadanie, w którym wszystkie odpowiedzi są prawdziwe.
### 5. Komentarze
Komentarzem jest linia zaczynająca się od `//`.
Przykłady:
```text
// Sterna 2024/2025 B
// Formanowicz 2021-2022
```
Komentarze są ignorowane przez parser demonstracyjny. Można ich używać jako nagłówków sekcji, źródeł, dat albo notatek.
### 6. Puste linie
Puste linie są ignorowane. Można ich używać do oddzielania pytań, odpowiedzi lub sekcji.
## LaTeX
Dozwolony jest inline LaTeX między pojedynczymi znakami dolara:
```text
Ile wynosi $\binom{n}{k}$?
```
Dozwolony przykład:
```text
-| Liczba kombinacji wynosi $\binom{n}{k}$.
```
Nie jest częścią formalnej składni:
```text
$$
a^2 + b^2 = c^2
$$
```
oraz:
```text
\[ a^2 + b^2 = c^2 \]
```
Parser demonstracyjny nie waliduje poprawności LaTeX-a. Traktuje zapis `$...$` jako zwykły fragment tekstu.
## HTML i obrazki
HTML jest dopuszczony jako część treści pytania lub odpowiedzi.
Przykład:
```text
Zaznacz funkcję odpowiadającą obrazkowi <img src="img/example.png" height="100" />
-| $f(x) = x^2$
- $f(x) = x$
```
Jeżeli `pytania.txt` odwołuje się do obrazka przez `img/...`, plik musi istnieć w katalogu `img/` w tym repozytorium.
## Jedna linia = jeden element
To najważniejsza zasada formatu.
Każde pytanie i każda odpowiedź muszą mieścić się w jednej fizycznej linii.
Poprawnie:
```text
Zaznacz zdania prawdziwe dotyczące funkcji $f(x) = x^2$.
-| Funkcja jest parzysta.
- Funkcja jest nieparzysta.
```
Niepoprawnie:
```text
Zaznacz zdania prawdziwe dotyczące funkcji
$f(x) = x^2$.
-| Funkcja jest parzysta.
```
Parser potraktuje drugą linię jako nowe pytanie.
## Walidacja lokalna
```bash
php tools/validate_qaml.php pytania.txt
```

7
pytania.txt Normal file
View File

@@ -0,0 +1,7 @@
// Przykładowe pytanie startowe
Która miara statystyczna opisuje przeciętną wartość obserwacji w próbie?
- Mediana
- Wariancja
-| Średnia arytmetyczna
- Odchylenie standardowe

90
tools/validate_qaml.php Normal file
View File

@@ -0,0 +1,90 @@
<?php
declare(strict_types=1);
$file = $argv[1] ?? 'pytania.txt';
$baseDir = dirname(__DIR__);
$path = $baseDir . '/' . $file;
if (!is_file($path)) {
fwrite(STDERR, "File not found: {$file}\n");
exit(1);
}
$lines = file($path, FILE_IGNORE_NEW_LINES);
$errors = [];
$question = null;
$questionLine = 0;
$answers = 0;
$questionCount = 0;
$finishQuestion = static function () use (&$errors, &$question, &$questionLine, &$answers, &$questionCount): void {
if ($question === null) {
return;
}
if ($answers === 0) {
$errors[] = "Line {$questionLine}: question has no answers.";
}
$questionCount++;
$question = null;
$questionLine = 0;
$answers = 0;
};
foreach ($lines as $i => $rawLine) {
$lineNo = $i + 1;
$line = trim($rawLine);
if ($line === '' || str_starts_with($line, '//')) {
continue;
}
if (!str_starts_with($line, '-')) {
$finishQuestion();
$question = $line;
$questionLine = $lineNo;
continue;
}
if ($question === null) {
$errors[] = "Line {$lineNo}: answer appears before any question.";
continue;
}
if (str_starts_with($line, '-|')) {
$answer = trim(substr($line, 2));
} else {
$answer = trim(substr($line, 1));
}
if ($answer === '') {
$errors[] = "Line {$lineNo}: answer is empty.";
}
$answers++;
}
$finishQuestion();
$content = file_get_contents($path) ?: '';
preg_match_all('/<img\s+[^>]*src=["\']([^"\']+)["\'][^>]*>/i', $content, $matches);
foreach ($matches[1] ?? [] as $src) {
if (str_starts_with($src, 'img/') && !is_file($baseDir . '/' . $src)) {
$errors[] = "Missing image referenced from pytania.txt: {$src}";
}
}
if ($questionCount === 0) {
$errors[] = 'No questions found.';
}
if ($errors !== []) {
foreach ($errors as $error) {
fwrite(STDERR, $error . PHP_EOL);
}
exit(1);
}
echo "OK: {$questionCount} questions validated.\n";