Moodle (PHP)
|
| reads quiz_attempts/grades/log events via the question engine,
| gradelib, and logstore_standard_log directly
v
Moodle DB
|
+--> classes/quiz/analytics/*.php (Quiz Analytics + Question
| Analytics: STACK/Maxima response parsing, statistics, chart
| JSON, PDF layout)
|
+--> classes/stack/analytics/*.php (Model Analytics + Diagnostics
Analytics: indicators, targets, report builders, PDF layout)
|
v
Plotly.js / KaTeX (client-side rendering) or TCPDF (server-side PDF)
- No CSV round-trip, no external service.
classes/quiz/data_fetcher.phpreads finished attempts straight out ofquiz_attemptsvia Moodle's question engine;classes/stack/local/stack_attempt_reader.phpdoes the same for Model Analytics/Diagnostics Analytics. - STACK question text is rendered through STACK's own CAS engine (
castext2_qa_processor), never read as raw storedquestiontext. - Every computation is pure PHP — no Python, no external service, no Composer dependencies at runtime.
- Caching (Quiz Analytics/Question Analytics only): every fetch/compute path is backed by a Moodle MUC cache area, keyed on a cheap SQL fingerprint (attempt count + latest
timefinish+ summed grades) rather than a fixed TTL — an entry is only ever served while that fingerprint still matches. Model Analytics/Diagnostics Analytics have no result cache; every dashboard view recomputes from scratch. - Analytics API integration (Model Analytics):
db/analytics.phpregisters both prediction models via\core_analytics\manager::update_default_models_for_component(), consumed automatically by core on install/upgrade.
See How Everything Is Calculated for the actual math behind every number this produces, and Privacy & Security for what data this touches and where it stays. The proxy-label circularity caveat referenced throughout How Everything Is Calculated is documented in full there. This plugin is itself the merger of two previously separate, independently installed plugins (local_quizanalytics and local_stackanalytics) — see CHANGELOG.md for the full history of that merge, including the renames along the way.
Known, tracked gaps
Documented rather than hidden — see README.md for the current list, currently:
- Two Model Analytics indicators are documented simplifications of the architecture doc's literal spec —
question_difficulty_irt's classical- test-theory proxy instead of a jointly-fitted 2PL IRT model, andfeedback_ineffectiveness's aggregate log-odds effect size instead of a per-branch paired McNemar's test — both because the fuller version needs a batch step the Analytics API's per-sample indicator model doesn't provide. Detail: How Everything Is Calculated. concept_dependency_report(concept-dependency mapping across questions) is an intentional placeholder, not implemented — the architecture doc frames it as offline sequence-mining work better suited outside a live dashboard page.