moved to API

This commit is contained in:
2026-03-08 22:24:34 -07:00
parent cf6b2611aa
commit 2caf566bf6
94 changed files with 1257 additions and 40930 deletions

View File

@@ -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();