moved to API
This commit is contained in:
102
app/ui-quiz.js
102
app/ui-quiz.js
@@ -2,6 +2,8 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
const dataService = window.TarotDataService || {};
|
||||
|
||||
const state = {
|
||||
initialized: false,
|
||||
scoreCorrect: 0,
|
||||
@@ -15,6 +17,7 @@
|
||||
runRetrySet: new Set(),
|
||||
currentQuestion: null,
|
||||
answeredCurrent: false,
|
||||
loadingQuestion: false,
|
||||
autoAdvanceTimer: null,
|
||||
autoAdvanceDelayMs: 1500
|
||||
};
|
||||
@@ -239,49 +242,15 @@
|
||||
};
|
||||
}
|
||||
|
||||
function instantiateQuestion(template) {
|
||||
if (!template) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const prompt = String(resolveDifficultyValue(template.promptByDifficulty) || "").trim();
|
||||
const answer = normalizeOption(resolveDifficultyValue(template.answerByDifficulty));
|
||||
const pool = toUniqueOptionList(resolveDifficultyValue(template.poolByDifficulty) || []);
|
||||
|
||||
if (!prompt || !answer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const built = buildOptions(answer, pool);
|
||||
if (!built) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
key: template.key,
|
||||
categoryId: template.categoryId,
|
||||
category: template.category,
|
||||
prompt,
|
||||
answer,
|
||||
options: built.options,
|
||||
correctIndex: built.correctIndex
|
||||
};
|
||||
async function buildQuestionBank(referenceData, magickDataset) {
|
||||
const payload = await dataService.loadQuizTemplates?.();
|
||||
return Array.isArray(payload?.templates)
|
||||
? payload.templates
|
||||
: (Array.isArray(payload) ? payload : []);
|
||||
}
|
||||
|
||||
function buildQuestionBank(referenceData, magickDataset) {
|
||||
if (typeof quizQuestionBank.buildQuestionBank !== "function") {
|
||||
return [];
|
||||
}
|
||||
|
||||
return quizQuestionBank.buildQuestionBank(
|
||||
referenceData,
|
||||
magickDataset,
|
||||
DYNAMIC_CATEGORY_REGISTRY
|
||||
);
|
||||
}
|
||||
|
||||
function refreshQuestionBank(referenceData, magickDataset) {
|
||||
state.questionBank = buildQuestionBank(referenceData, magickDataset);
|
||||
async function refreshQuestionBank(referenceData, magickDataset) {
|
||||
state.questionBank = await buildQuestionBank(referenceData, magickDataset);
|
||||
state.templateByKey = new Map(state.questionBank.map((template) => [template.key, template]));
|
||||
|
||||
const hasTemplate = (key) => state.templateByKey.has(key);
|
||||
@@ -380,7 +349,7 @@
|
||||
|| "Category";
|
||||
}
|
||||
|
||||
function startRun(resetScore = false) {
|
||||
async function startRun(resetScore = false) {
|
||||
clearAutoAdvanceTimer();
|
||||
|
||||
if (resetScore) {
|
||||
@@ -425,7 +394,7 @@
|
||||
state.answeredCurrent = true;
|
||||
|
||||
updateScoreboard();
|
||||
showNextQuestion();
|
||||
await showNextQuestion();
|
||||
}
|
||||
|
||||
function popNextTemplateFromRun() {
|
||||
@@ -450,6 +419,7 @@
|
||||
}
|
||||
|
||||
function renderRunCompleteState() {
|
||||
state.loadingQuestion = false;
|
||||
state.currentQuestion = null;
|
||||
state.answeredCurrent = true;
|
||||
questionTypeEl.textContent = getRunLabel();
|
||||
@@ -479,6 +449,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
state.loadingQuestion = false;
|
||||
state.currentQuestion = question;
|
||||
state.answeredCurrent = false;
|
||||
|
||||
@@ -505,6 +476,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
state.loadingQuestion = false;
|
||||
state.currentQuestion = null;
|
||||
state.answeredCurrent = true;
|
||||
|
||||
@@ -514,9 +486,25 @@
|
||||
feedbackEl.textContent = "Try Random/All or switch to another category.";
|
||||
}
|
||||
|
||||
function showNextQuestion() {
|
||||
async function createQuestionFromTemplate(template) {
|
||||
if (!template) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return dataService.pullQuizQuestion?.({
|
||||
templateKey: template.key,
|
||||
difficulty: getActiveDifficulty(),
|
||||
includeAnswer: true
|
||||
});
|
||||
}
|
||||
|
||||
async function showNextQuestion() {
|
||||
clearAutoAdvanceTimer();
|
||||
|
||||
if (state.loadingQuestion) {
|
||||
return;
|
||||
}
|
||||
|
||||
const totalPending = state.runUnseenKeys.length + state.runRetryKeys.length;
|
||||
if (totalPending <= 0) {
|
||||
if (state.questionBank.length) {
|
||||
@@ -528,13 +516,21 @@
|
||||
}
|
||||
|
||||
const maxAttempts = totalPending + 1;
|
||||
state.loadingQuestion = true;
|
||||
feedbackEl.textContent = "Loading question...";
|
||||
|
||||
for (let index = 0; index < maxAttempts; index += 1) {
|
||||
const template = popNextTemplateFromRun();
|
||||
if (!template) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const question = instantiateQuestion(template);
|
||||
let question = null;
|
||||
try {
|
||||
question = await createQuestionFromTemplate(template);
|
||||
} catch (_error) {
|
||||
question = null;
|
||||
}
|
||||
if (question) {
|
||||
renderQuestion(question);
|
||||
return;
|
||||
@@ -589,21 +585,21 @@
|
||||
|
||||
categoryEl.addEventListener("change", () => {
|
||||
state.selectedCategory = String(categoryEl.value || "random");
|
||||
startRun(true);
|
||||
void startRun(true);
|
||||
});
|
||||
|
||||
difficultyEl.addEventListener("change", () => {
|
||||
state.selectedDifficulty = String(difficultyEl.value || "normal").toLowerCase();
|
||||
syncDifficultyControl();
|
||||
startRun(true);
|
||||
void startRun(true);
|
||||
});
|
||||
|
||||
resetEl.addEventListener("click", () => {
|
||||
startRun(true);
|
||||
void startRun(true);
|
||||
});
|
||||
}
|
||||
|
||||
function ensureQuizSection(referenceData, magickDataset) {
|
||||
async function ensureQuizSection(referenceData, magickDataset) {
|
||||
ensureQuizSection._referenceData = referenceData;
|
||||
ensureQuizSection._magickDataset = magickDataset;
|
||||
|
||||
@@ -618,23 +614,23 @@
|
||||
updateScoreboard();
|
||||
}
|
||||
|
||||
refreshQuestionBank(referenceData, magickDataset);
|
||||
await refreshQuestionBank(referenceData, magickDataset);
|
||||
const categoryAdjusted = renderCategoryOptions();
|
||||
syncDifficultyControl();
|
||||
|
||||
if (categoryAdjusted) {
|
||||
startRun(false);
|
||||
await startRun(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const hasRunPending = state.runUnseenKeys.length > 0 || state.runRetryKeys.length > 0;
|
||||
if (!state.currentQuestion && !hasRunPending) {
|
||||
startRun(false);
|
||||
await startRun(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.currentQuestion && hasRunPending) {
|
||||
showNextQuestion();
|
||||
await showNextQuestion();
|
||||
}
|
||||
|
||||
updateScoreboard();
|
||||
|
||||
Reference in New Issue
Block a user