elemes/services
a2nr 81cb9c69ca feat(quiz): taksonomi key quiz per jenis + MCQ berbobot (partial credit)
Fitur B — setiap jenis soal kini punya key sendiri sehingga model
penilaiannya eksplisit, tidak ditebak dari isi konten:

- ---QUIZ_MCQ---      pilihan ganda biner (tepat satu [x]; larang [N])
- ---QUIZ_WEIGHTED--- pilihan ganda berbobot ([N] >= 1, minimal satu [ ],
                      bobot tertinggi unik = kunci; poin parsial)
- ---FLASHCARD---     kartu hafalan tanpa penilaian (larang opsi)
- legacy ---QUIZ_FLASHCARD--- / ---INITIAL_QUIZ--- tetap dibaca tanpa
  perubahan perilaku (regex opsi legacy sengaja tidak berubah — baris
  '- [10]' di konten lama BUKAN opsi); dihapus dari docs/template
- ::diagnostic tetap kategori di dalam QUIZ_MCQ & tetap masuk skor resmi

Model skor: rata-rata persentase per jenis yang ada, Math.round,
lulus >= 75. statusString: "X/Y" bila hanya MCQ/legacy, "P/100" bila ada
weighted, "completed" bila hanya flashcard (auto-lulus). Satu sesi/
attempt untuk semua jenis; soal flat urut dokumen.

Parser (backend & frontend mirror, ekstraksi multi-blok per key urut
dokumen via loop marker-start paling awal; id q-N deterministik):
- lesson_service.py: regex [ xX]?[0-9]* utk key baru, _iter_option_lines
  kind-aware, _validate_quiz_options per kind, _parse_flashcards(kind,
  id_offset), _extract_quiz_sections + guard loop maju (marker end
  hilang tidak lagi infinite loop), get_lesson_quiz_total -> 100 bila
  ada weighted (round-trip CSV "P/100")
- parseFlashcards.ts / index.ts / detectActiveTabs.ts / extractSections.ts:
  mirror perilaku; heading soal <h3> kini fence-aware (fix fixture stale)

Payload attempt baru: quiz_type, earned_points, question_max_points —
opsional di validasi backend supaya klien lama tetap diterima; poin
di-recompute dari konten saat resume/review.

UI: QuizTab skor via statusString + alert berbasis percent, badge
weighted (✓ 10 / 🟡 7/10 / ✗ 0) di review, preview guru badge bobot +
"Berbobot (total N)", laporan guru badge MCQ/Bobot + tooltip, CSV
progress 2 kolom baru per lesson (_quiz_mcq, _quiz_weighted), template
editor konten QUIZ_MCQ/Quiz Bobot/Flashcard.

Tooling & docs: scripts/convert_quiz_keys.py (konversi legacy -> key
baru per run jenis, idempoten, verifikasi parse identik; examples/
content dikonversi), scanner mendukung semua key, docs/07 ditulis ulang,
docs/15 direvisi ke desain final, README/documentation/docs 02/04/09
diperbarui.

Tes: backend 444 lulus (+33: validasi ketat per key, urutan dokumen,
multi-blok, zero regression, field selalu di-emit), frontend 249 lulus
(+13 parser key baru, +11 model skor), parity fixture diregenerasi,
svelte-check 0 error, vite build OK.
2026-10-25 20:16:56 +07:00
..
scripts fix(markdown): sanitasi DOMPurify, perbaikan parser flashcard & kompatibilitas SSR Node 20 2026-08-28 05:24:44 +07:00
storage feat(quiz): taksonomi key quiz per jenis + MCQ berbobot (partial credit) 2026-10-25 20:16:56 +07:00
tests feat(quiz): taksonomi key quiz per jenis + MCQ berbobot (partial credit) 2026-10-25 20:16:56 +07:00
__init__.py
…
database.py
…
docs_service.py fix(docs/api): hilangkan sync berulang di api_reference + UI API Reference di /docs 2026-08-17 16:37:30 +07:00
evaluation.py feat: unified lesson progress — composite score & /api/lesson-progress 2026-08-29 00:22:10 +07:00
image_cache.py feat(assets): optimasi serving gambar (WebP on-the-fly + cache disk) 2026-10-25 19:19:07 +07:00
lesson_registry.py fix(review): address code review findings for dev to master merge 2026-09-06 18:08:58 +07:00
lesson_service.py feat(quiz): taksonomi key quiz per jenis + MCQ berbobot (partial credit) 2026-10-25 20:16:56 +07:00
models.py feat(quiz): izinkan guru melanjutkan attempt terminated dari jawaban tersimpan 2026-10-20 19:24:40 +07:00
progress_status.py feat(progress): composite scoring, roundtrip CSV grammar, and report export 2026-08-30 04:12:23 +07:00
repositories.py feat(quiz): izinkan guru melanjutkan attempt terminated dari jawaban tersimpan 2026-10-20 19:24:40 +07:00
student_roundtrip.py feat(student-management): sync imported progress with composite model and add inline expected format to CSV headers 2026-09-08 19:01:33 +07:00
teacher_auth.py feat(content-editor): konfirmasi ganda file navigasi kritis & hapus narrow sidebar 2026-08-23 08:18:02 +07:00
teacher_bootstrap.py
…
token_hashing.py
…
token_service.py feat(quiz): izinkan guru melanjutkan attempt terminated dari jawaban tersimpan 2026-10-20 19:24:40 +07:00