/* ui-quiz-bank-builtins.js — Built-in quiz template generation */ (function () { "use strict"; const quizQuestionBankBuiltInDomains = window.QuizQuestionBankBuiltInDomains || {}; if (typeof quizQuestionBankBuiltInDomains.appendBuiltInQuestionBankDomains !== "function") { throw new Error("QuizQuestionBankBuiltInDomains module must load before ui-quiz-bank-builtins.js"); } function buildBuiltInQuestionBank(context) { const { referenceData, magickDataset, helpers } = context || {}; const { toTitleCase, normalizeOption, toUniqueOptionList, createQuestionTemplate } = helpers || {}; if ( typeof toTitleCase !== "function" || typeof normalizeOption !== "function" || typeof toUniqueOptionList !== "function" || typeof createQuestionTemplate !== "function" ) { return []; } const grouped = magickDataset?.grouped || {}; const alphabets = grouped.alphabets || {}; const englishLetters = Array.isArray(alphabets?.english) ? alphabets.english : []; const hebrewLetters = Array.isArray(alphabets?.hebrew) ? alphabets.hebrew : []; const kabbalahTree = grouped?.kabbalah?.["kabbalah-tree"] || {}; const treePaths = Array.isArray(kabbalahTree?.paths) ? kabbalahTree.paths : []; const treeSephiroth = Array.isArray(kabbalahTree?.sephiroth) ? kabbalahTree.sephiroth : []; const sephirotById = grouped?.kabbalah?.sephirot && typeof grouped.kabbalah.sephirot === "object" ? grouped.kabbalah.sephirot : {}; const cube = grouped?.kabbalah?.cube && typeof grouped.kabbalah.cube === "object" ? grouped.kabbalah.cube : {}; const cubeWalls = Array.isArray(cube?.walls) ? cube.walls : []; const cubeEdges = Array.isArray(cube?.edges) ? cube.edges : []; const cubeCenter = cube?.center && typeof cube.center === "object" ? cube.center : null; const playingCardsData = grouped?.["playing-cards-52"]; const playingCards = Array.isArray(playingCardsData) ? playingCardsData : (Array.isArray(playingCardsData?.entries) ? playingCardsData.entries : []); const signs = Array.isArray(referenceData?.signs) ? referenceData.signs : []; const planetsById = referenceData?.planets && typeof referenceData.planets === "object" ? referenceData.planets : {}; const planets = Object.values(planetsById); const decansBySign = referenceData?.decansBySign && typeof referenceData.decansBySign === "object" ? referenceData.decansBySign : {}; const normalizeId = (value) => String(value || "").trim().toLowerCase(); const toRomanNumeral = (value) => { const numeric = Number(value); if (!Number.isFinite(numeric) || numeric <= 0) { return String(value || ""); } const intValue = Math.trunc(numeric); const lookup = [ [1000, "M"], [900, "CM"], [500, "D"], [400, "CD"], [100, "C"], [90, "XC"], [50, "L"], [40, "XL"], [10, "X"], [9, "IX"], [5, "V"], [4, "IV"], [1, "I"] ]; let current = intValue; let result = ""; lookup.forEach(([size, symbol]) => { while (current >= size) { result += symbol; current -= size; } }); return result || String(intValue); }; const labelFromId = (value) => { const id = String(value || "").trim(); if (!id) { return ""; } return id .replace(/[_-]+/g, " ") .replace(/\s+/g, " ") .trim() .split(" ") .map((part) => part ? part.charAt(0).toUpperCase() + part.slice(1) : "") .join(" "); }; const getPlanetLabelById = (planetId) => { const normalized = normalizeId(planetId); if (!normalized) { return ""; } const directPlanet = planetsById[normalized]; if (directPlanet?.name) { return directPlanet.name; } if (normalized === "primum-mobile") { return "Primum Mobile"; } if (normalized === "olam-yesodot") { return "Earth / Elements"; } return labelFromId(normalized); }; const hebrewById = new Map( hebrewLetters .filter((entry) => entry?.hebrewLetterId) .map((entry) => [normalizeId(entry.hebrewLetterId), entry]) ); const formatHebrewLetterLabel = (entry, fallbackId = "") => { if (entry?.name && entry?.char) { return `${entry.name} (${entry.char})`; } if (entry?.name) { return entry.name; } if (entry?.char) { return entry.char; } return labelFromId(fallbackId); }; const sephiraNameByNumber = new Map( treeSephiroth .filter((entry) => Number.isFinite(Number(entry?.number)) && entry?.name) .map((entry) => [Math.trunc(Number(entry.number)), String(entry.name)]) ); const sephiraNameById = new Map( treeSephiroth .filter((entry) => entry?.sephiraId && entry?.name) .map((entry) => [normalizeId(entry.sephiraId), String(entry.name)]) ); const getSephiraName = (numberValue, idValue) => { const numberKey = Number(numberValue); if (Number.isFinite(numberKey)) { const byNumber = sephiraNameByNumber.get(Math.trunc(numberKey)); if (byNumber) { return byNumber; } } const byId = sephiraNameById.get(normalizeId(idValue)); if (byId) { return byId; } if (Number.isFinite(numberKey)) { return `Sephira ${Math.trunc(numberKey)}`; } return labelFromId(idValue); }; const formatPathLetter = (path) => { const transliteration = String(path?.hebrewLetter?.transliteration || "").trim(); const glyph = String(path?.hebrewLetter?.char || "").trim(); if (transliteration && glyph) { return `${transliteration} (${glyph})`; } if (transliteration) { return transliteration; } if (glyph) { return glyph; } return ""; }; const flattenDecans = Object.values(decansBySign) .flatMap((entries) => (Array.isArray(entries) ? entries : [])); const signNameById = new Map( signs .filter((entry) => entry?.id && entry?.name) .map((entry) => [normalizeId(entry.id), String(entry.name)]) ); const formatDecanLabel = (decan) => { const signName = signNameById.get(normalizeId(decan?.signId)) || labelFromId(decan?.signId); const index = Number(decan?.index); if (!signName || !Number.isFinite(index)) { return ""; } return `${signName} Decan ${toRomanNumeral(index)}`; }; const bank = []; const englishGematriaPool = englishLetters .map((item) => (Number.isFinite(Number(item?.pythagorean)) ? String(item.pythagorean) : "")) .filter(Boolean); const hebrewNumerologyPool = hebrewLetters .map((item) => (Number.isFinite(Number(item?.numerology)) ? String(item.numerology) : "")) .filter(Boolean); const hebrewNameAndCharPool = hebrewLetters .filter((item) => item?.name && item?.char) .map((item) => `${item.name} (${item.char})`); const hebrewCharPool = hebrewLetters .map((item) => item?.char) .filter(Boolean); const planetNamePool = planets .map((planet) => planet?.name) .filter(Boolean); const planetWeekdayPool = planets .map((planet) => planet?.weekday) .filter(Boolean); const zodiacElementPool = signs .map((sign) => toTitleCase(sign?.element)) .filter(Boolean); const zodiacTarotPool = signs .map((sign) => sign?.tarot?.majorArcana) .filter(Boolean); const pathNumberPool = toUniqueOptionList( treePaths .map((path) => { const pathNo = Number(path?.pathNumber); return Number.isFinite(pathNo) ? String(Math.trunc(pathNo)) : ""; }) ); const pathLetterPool = toUniqueOptionList(treePaths.map((path) => formatPathLetter(path))); const pathTarotPool = toUniqueOptionList(treePaths.map((path) => normalizeOption(path?.tarot?.card))); const sephirotPlanetPool = toUniqueOptionList( Object.values(sephirotById).map((entry) => getPlanetLabelById(entry?.planetId)) ); const decanLabelPool = toUniqueOptionList(flattenDecans.map((decan) => formatDecanLabel(decan))); const decanRulerPool = toUniqueOptionList( flattenDecans.map((decan) => getPlanetLabelById(decan?.rulerPlanetId)) ); const cubeWallLabelPool = toUniqueOptionList( cubeWalls.map((wall) => `${String(wall?.name || labelFromId(wall?.id)).trim()} Wall`) ); const cubeEdgeLabelPool = toUniqueOptionList( cubeEdges.map((edge) => `${String(edge?.name || labelFromId(edge?.id)).trim()} Edge`) ); const cubeLocationPool = toUniqueOptionList([ ...cubeWallLabelPool, ...cubeEdgeLabelPool, "Center" ]); const cubeHebrewLetterPool = toUniqueOptionList([ ...cubeWalls.map((wall) => { const hebrew = hebrewById.get(normalizeId(wall?.hebrewLetterId)); return formatHebrewLetterLabel(hebrew, wall?.hebrewLetterId); }), ...cubeEdges.map((edge) => { const hebrew = hebrewById.get(normalizeId(edge?.hebrewLetterId)); return formatHebrewLetterLabel(hebrew, edge?.hebrewLetterId); }), formatHebrewLetterLabel(hebrewById.get(normalizeId(cubeCenter?.hebrewLetterId)), cubeCenter?.hebrewLetterId) ]); const playingTarotPool = toUniqueOptionList( playingCards.map((entry) => normalizeOption(entry?.tarotCard)) ); quizQuestionBankBuiltInDomains.appendBuiltInQuestionBankDomains({ bank, englishLetters, hebrewLetters, hebrewById, signs, planets, planetsById, treePaths, sephirotById, flattenDecans, cubeWalls, cubeEdges, cubeCenter, playingCards, pools: { englishGematriaPool, hebrewNumerologyPool, hebrewNameAndCharPool, hebrewCharPool, planetNamePool, planetWeekdayPool, zodiacElementPool, zodiacTarotPool, pathNumberPool, pathLetterPool, pathTarotPool, sephirotPlanetPool, decanLabelPool, decanRulerPool, cubeLocationPool, cubeHebrewLetterPool, playingTarotPool }, helpers: { createQuestionTemplate, normalizeId, normalizeOption, toTitleCase, formatHebrewLetterLabel, getPlanetLabelById, getSephiraName, formatPathLetter, formatDecanLabel, labelFromId } }); return bank; } window.QuizQuestionBankBuiltins = { buildBuiltInQuestionBank }; })();