(function () { let magickManifestCache = null; let magickDataCache = null; const DATA_ROOT = "data"; const MAGICK_ROOT = DATA_ROOT; const TAROT_TRUMP_NUMBER_BY_NAME = { "the fool": 0, fool: 0, "the magus": 1, magus: 1, magician: 1, "the high priestess": 2, "high priestess": 2, "the empress": 3, empress: 3, "the emperor": 4, emperor: 4, "the hierophant": 5, hierophant: 5, "the lovers": 6, lovers: 6, "the chariot": 7, chariot: 7, strength: 8, lust: 8, "the hermit": 9, hermit: 9, fortune: 10, "wheel of fortune": 10, justice: 11, "the hanged man": 12, "hanged man": 12, death: 13, temperance: 14, art: 14, "the devil": 15, devil: 15, "the tower": 16, tower: 16, "the star": 17, star: 17, "the moon": 18, moon: 18, "the sun": 19, sun: 19, aeon: 20, judgement: 20, judgment: 20, universe: 21, world: 21, "the world": 21 }; const HEBREW_BY_TRUMP_NUMBER = { 0: { hebrewLetterId: "alef", kabbalahPathNumber: 11 }, 1: { hebrewLetterId: "bet", kabbalahPathNumber: 12 }, 2: { hebrewLetterId: "gimel", kabbalahPathNumber: 13 }, 3: { hebrewLetterId: "dalet", kabbalahPathNumber: 14 }, 4: { hebrewLetterId: "he", kabbalahPathNumber: 15 }, 5: { hebrewLetterId: "vav", kabbalahPathNumber: 16 }, 6: { hebrewLetterId: "zayin", kabbalahPathNumber: 17 }, 7: { hebrewLetterId: "het", kabbalahPathNumber: 18 }, 8: { hebrewLetterId: "tet", kabbalahPathNumber: 19 }, 9: { hebrewLetterId: "yod", kabbalahPathNumber: 20 }, 10: { hebrewLetterId: "kaf", kabbalahPathNumber: 21 }, 11: { hebrewLetterId: "lamed", kabbalahPathNumber: 22 }, 12: { hebrewLetterId: "mem", kabbalahPathNumber: 23 }, 13: { hebrewLetterId: "nun", kabbalahPathNumber: 24 }, 14: { hebrewLetterId: "samekh", kabbalahPathNumber: 25 }, 15: { hebrewLetterId: "ayin", kabbalahPathNumber: 26 }, 16: { hebrewLetterId: "pe", kabbalahPathNumber: 27 }, 17: { hebrewLetterId: "tsadi", kabbalahPathNumber: 28 }, 18: { hebrewLetterId: "qof", kabbalahPathNumber: 29 }, 19: { hebrewLetterId: "resh", kabbalahPathNumber: 30 }, 20: { hebrewLetterId: "shin", kabbalahPathNumber: 31 }, 21: { hebrewLetterId: "tav", kabbalahPathNumber: 32 } }; const ICHING_PLANET_BY_PLANET_ID = { sol: "Sun", luna: "Moon", mercury: "Mercury", venus: "Venus", mars: "Mars", jupiter: "Jupiter", saturn: "Saturn", earth: "Earth", uranus: "Uranus", neptune: "Neptune", pluto: "Pluto" }; async function fetchJson(path) { const response = await fetch(path); if (!response.ok) { throw new Error(`Failed to load ${path} (${response.status})`); } return response.json(); } function buildObjectPath(target, pathParts, value) { let cursor = target; for (let index = 0; index < pathParts.length - 1; index += 1) { const part = pathParts[index]; if (!cursor[part] || typeof cursor[part] !== "object") { cursor[part] = {}; } cursor = cursor[part]; } cursor[pathParts[pathParts.length - 1]] = value; } function normalizeTarotName(value) { return String(value || "") .trim() .toLowerCase() .replace(/\s+/g, " "); } function resolveTarotTrumpNumber(cardName) { const key = normalizeTarotName(cardName); if (!key) { return null; } if (Object.prototype.hasOwnProperty.call(TAROT_TRUMP_NUMBER_BY_NAME, key)) { return TAROT_TRUMP_NUMBER_BY_NAME[key]; } const withoutLeadingThe = key.replace(/^the\s+/, ""); if (Object.prototype.hasOwnProperty.call(TAROT_TRUMP_NUMBER_BY_NAME, withoutLeadingThe)) { return TAROT_TRUMP_NUMBER_BY_NAME[withoutLeadingThe]; } return null; } function enrichAssociation(associations) { if (!associations || typeof associations !== "object") { return associations; } const next = { ...associations }; if (next.tarotCard) { const trumpNumber = resolveTarotTrumpNumber(next.tarotCard); if (trumpNumber != null) { if (!Number.isFinite(Number(next.tarotTrumpNumber))) { next.tarotTrumpNumber = trumpNumber; } const hebrew = HEBREW_BY_TRUMP_NUMBER[trumpNumber]; if (hebrew) { if (!next.hebrewLetterId) { next.hebrewLetterId = hebrew.hebrewLetterId; } if (!Number.isFinite(Number(next.kabbalahPathNumber))) { next.kabbalahPathNumber = hebrew.kabbalahPathNumber; } } } } const planetId = String(next.planetId || "").trim().toLowerCase(); if (!next.iChingPlanetaryInfluence && planetId) { const influence = ICHING_PLANET_BY_PLANET_ID[planetId]; if (influence) { next.iChingPlanetaryInfluence = influence; } } return next; } function enrichCalendarMonth(month) { const events = Array.isArray(month?.events) ? month.events.map((event) => ({ ...event, associations: enrichAssociation(event?.associations) })) : []; return { ...month, associations: enrichAssociation(month?.associations), events }; } function enrichCelestialHoliday(holiday) { return { ...holiday, associations: enrichAssociation(holiday?.associations) }; } function enrichCalendarHoliday(holiday) { return { ...holiday, associations: enrichAssociation(holiday?.associations) }; } async function loadMagickManifest() { if (magickManifestCache) { return magickManifestCache; } magickManifestCache = await fetchJson(`${MAGICK_ROOT}/MANIFEST.json`); return magickManifestCache; } async function loadMagickDataset() { if (magickDataCache) { return magickDataCache; } const manifest = await loadMagickManifest(); const files = Array.isArray(manifest?.files) ? manifest.files : []; const jsonFiles = files.filter((file) => file.endsWith(".json")); const entries = await Promise.all( jsonFiles.map(async (relativePath) => { const data = await fetchJson(`${MAGICK_ROOT}/${relativePath}`); return [relativePath, data]; }) ); const grouped = {}; entries.forEach(([relativePath, data]) => { const noExtensionPath = relativePath.replace(/\.json$/i, ""); const pathParts = noExtensionPath.split("/").filter(Boolean); if (!pathParts.length) { return; } buildObjectPath(grouped, pathParts, data); }); magickDataCache = { manifest, grouped, files: Object.fromEntries(entries) }; return magickDataCache; } async function loadReferenceData() { const { groupDecansBySign } = window.TarotCalc; const [ planetsJson, signsJson, decansJson, sabianJson, planetScienceJson, iChingJson, calendarMonthsJson, celestialHolidaysJson, calendarHolidaysJson, astronomyCyclesJson, tarotDatabaseJson, hebrewCalendarJson, islamicCalendarJson, wheelOfYearJson ] = await Promise.all([ fetchJson(`${DATA_ROOT}/planetary-correspondences.json`), fetchJson(`${DATA_ROOT}/signs.json`), fetchJson(`${DATA_ROOT}/decans.json`), fetchJson(`${DATA_ROOT}/sabian-symbols.json`), fetchJson(`${DATA_ROOT}/planet-science.json`), fetchJson(`${DATA_ROOT}/i-ching.json`), fetchJson(`${DATA_ROOT}/calendar-months.json`), fetchJson(`${DATA_ROOT}/celestial-holidays.json`), fetchJson(`${DATA_ROOT}/calendar-holidays.json`).catch(() => ({})), fetchJson(`${DATA_ROOT}/astronomy-cycles.json`).catch(() => ({})), fetchJson(`${DATA_ROOT}/tarot-database.json`).catch(() => ({})), fetchJson(`${DATA_ROOT}/hebrew-calendar.json`).catch(() => ({})), fetchJson(`${DATA_ROOT}/islamic-calendar.json`).catch(() => ({})), fetchJson(`${DATA_ROOT}/wheel-of-year.json`).catch(() => ({})) ]); const planets = planetsJson.planets || {}; const signs = signsJson.signs || []; const decans = decansJson.decans || []; const sabianSymbols = Array.isArray(sabianJson?.symbols) ? sabianJson.symbols : []; const planetScience = Array.isArray(planetScienceJson?.planets) ? planetScienceJson.planets : []; const iChing = { trigrams: Array.isArray(iChingJson?.trigrams) ? iChingJson.trigrams : [], hexagrams: Array.isArray(iChingJson?.hexagrams) ? iChingJson.hexagrams : [], correspondences: { meta: iChingJson?.correspondences?.meta && typeof iChingJson.correspondences.meta === "object" ? iChingJson.correspondences.meta : {}, tarotToTrigram: Array.isArray(iChingJson?.correspondences?.tarotToTrigram) ? iChingJson.correspondences.tarotToTrigram : [] } }; const calendarMonths = Array.isArray(calendarMonthsJson?.months) ? calendarMonthsJson.months.map((month) => enrichCalendarMonth(month)) : []; const celestialHolidays = Array.isArray(celestialHolidaysJson?.holidays) ? celestialHolidaysJson.holidays.map((holiday) => enrichCelestialHoliday(holiday)) : []; const calendarHolidays = Array.isArray(calendarHolidaysJson?.holidays) ? calendarHolidaysJson.holidays.map((holiday) => enrichCalendarHoliday(holiday)) : []; const astronomyCycles = astronomyCyclesJson && typeof astronomyCyclesJson === "object" ? astronomyCyclesJson : {}; const tarotDatabase = tarotDatabaseJson && typeof tarotDatabaseJson === "object" ? tarotDatabaseJson : {}; const sourceMeanings = tarotDatabase.meanings && typeof tarotDatabase.meanings === "object" ? tarotDatabase.meanings : {}; if (!sourceMeanings.majorByTrumpNumber || typeof sourceMeanings.majorByTrumpNumber !== "object") { sourceMeanings.majorByTrumpNumber = {}; } const existingByCardName = sourceMeanings.byCardName && typeof sourceMeanings.byCardName === "object" ? sourceMeanings.byCardName : {}; sourceMeanings.byCardName = existingByCardName; tarotDatabase.meanings = sourceMeanings; const hebrewCalendar = hebrewCalendarJson && typeof hebrewCalendarJson === "object" ? hebrewCalendarJson : {}; const islamicCalendar = islamicCalendarJson && typeof islamicCalendarJson === "object" ? islamicCalendarJson : {}; const wheelOfYear = wheelOfYearJson && typeof wheelOfYearJson === "object" ? wheelOfYearJson : {}; return { planets, signs, decansBySign: groupDecansBySign(decans), sabianSymbols, planetScience, iChing, calendarMonths, celestialHolidays, calendarHolidays, astronomyCycles, tarotDatabase, hebrewCalendar, islamicCalendar, wheelOfYear }; } window.TarotDataService = { loadReferenceData, loadMagickManifest, loadMagickDataset }; })();