Files
TaroTime/app/ui-zodiac-references.js
2026-03-07 13:38:13 -08:00

246 lines
7.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ui-zodiac-references.js — Month and cube reference builders for the zodiac section */
(function () {
"use strict";
const MONTH_NAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
function cap(value) {
return String(value || "").charAt(0).toUpperCase() + String(value || "").slice(1);
}
function formatDateRange(rulesFrom) {
if (!Array.isArray(rulesFrom) || rulesFrom.length < 2) return "—";
const [from, to] = rulesFrom;
const fMonth = MONTH_NAMES[(from[0] || 1) - 1];
const tMonth = MONTH_NAMES[(to[0] || 1) - 1];
return `${fMonth} ${from[1]} ${tMonth} ${to[1]}`;
}
function buildMonthReferencesBySign(referenceData) {
const map = new Map();
const months = Array.isArray(referenceData?.calendarMonths) ? referenceData.calendarMonths : [];
const holidays = Array.isArray(referenceData?.celestialHolidays) ? referenceData.celestialHolidays : [];
const signs = Array.isArray(referenceData?.signs) ? referenceData.signs : [];
const monthById = new Map(months.map((month) => [month.id, month]));
const monthByOrder = new Map(
months
.filter((month) => Number.isFinite(Number(month?.order)))
.map((month) => [Number(month.order), month])
);
function parseMonthDay(value) {
const [month, day] = String(value || "").split("-").map((part) => Number(part));
if (!Number.isFinite(month) || !Number.isFinite(day)) {
return null;
}
return { month, day };
}
function monthOrdersInRange(startMonth, endMonth) {
const orders = [];
let cursor = startMonth;
let guard = 0;
while (guard < 13) {
orders.push(cursor);
if (cursor === endMonth) {
break;
}
cursor = cursor === 12 ? 1 : cursor + 1;
guard += 1;
}
return orders;
}
function pushRef(signId, month) {
const key = String(signId || "").trim().toLowerCase();
if (!key || !month?.id) {
return;
}
if (!map.has(key)) {
map.set(key, []);
}
const rows = map.get(key);
if (rows.some((entry) => entry.id === month.id)) {
return;
}
rows.push({
id: month.id,
name: month.name || month.id,
order: Number.isFinite(Number(month.order)) ? Number(month.order) : 999
});
}
months.forEach((month) => {
pushRef(month?.associations?.zodiacSignId, month);
const events = Array.isArray(month?.events) ? month.events : [];
events.forEach((event) => {
pushRef(event?.associations?.zodiacSignId, month);
});
});
holidays.forEach((holiday) => {
const month = monthById.get(holiday?.monthId);
if (!month) {
return;
}
pushRef(holiday?.associations?.zodiacSignId, month);
});
signs.forEach((sign) => {
const start = parseMonthDay(sign?.start);
const end = parseMonthDay(sign?.end);
if (!start || !end || !sign?.id) {
return;
}
monthOrdersInRange(start.month, end.month).forEach((monthOrder) => {
const month = monthByOrder.get(monthOrder);
if (month) {
pushRef(sign.id, month);
}
});
});
map.forEach((rows, key) => {
rows.sort((left, right) => left.order - right.order || left.name.localeCompare(right.name));
map.set(key, rows);
});
return map;
}
function buildCubeSignPlacements(magickDataset) {
const placements = new Map();
const cube = magickDataset?.grouped?.kabbalah?.cube || {};
const walls = Array.isArray(cube?.walls)
? cube.walls
: [];
const edges = Array.isArray(cube?.edges)
? cube.edges
: [];
const paths = Array.isArray(magickDataset?.grouped?.kabbalah?.["kabbalah-tree"]?.paths)
? magickDataset.grouped.kabbalah["kabbalah-tree"].paths
: [];
function normalizeLetterId(value) {
const key = String(value || "").toLowerCase().replace(/[^a-z]/g, "").trim();
const aliases = {
aleph: "alef",
beth: "bet",
zain: "zayin",
cheth: "het",
chet: "het",
daleth: "dalet",
teth: "tet",
peh: "pe",
tzaddi: "tsadi",
tzadi: "tsadi",
tzade: "tsadi",
tsaddi: "tsadi",
qoph: "qof",
taw: "tav",
tau: "tav"
};
return aliases[key] || key;
}
function edgeWalls(edge) {
const explicitWalls = Array.isArray(edge?.walls)
? edge.walls.map((wallId) => String(wallId || "").trim().toLowerCase()).filter(Boolean)
: [];
if (explicitWalls.length >= 2) {
return explicitWalls.slice(0, 2);
}
return String(edge?.id || "")
.trim()
.toLowerCase()
.split("-")
.map((wallId) => wallId.trim())
.filter(Boolean)
.slice(0, 2);
}
function edgeLabel(edge) {
const explicitName = String(edge?.name || "").trim();
if (explicitName) {
return explicitName;
}
return edgeWalls(edge)
.map((part) => cap(part))
.join(" ");
}
function resolveCubeDirectionLabel(wallId, edge) {
const normalizedWallId = String(wallId || "").trim().toLowerCase();
const edgeId = String(edge?.id || "").trim().toLowerCase();
if (!normalizedWallId || !edgeId) {
return "";
}
const cubeUi = window.CubeSectionUi;
if (cubeUi && typeof cubeUi.getEdgeDirectionLabelForWall === "function") {
const directionLabel = String(cubeUi.getEdgeDirectionLabelForWall(normalizedWallId, edgeId) || "").trim();
if (directionLabel) {
return directionLabel;
}
}
return edgeLabel(edge);
}
const wallById = new Map(
walls.map((wall) => [String(wall?.id || "").trim().toLowerCase(), wall])
);
const pathByLetterId = new Map(
paths
.map((path) => [normalizeLetterId(path?.hebrewLetter?.transliteration), path])
.filter(([letterId]) => Boolean(letterId))
);
edges.forEach((edge) => {
const letterId = normalizeLetterId(edge?.hebrewLetterId || edge?.associations?.hebrewLetterId);
const path = pathByLetterId.get(letterId) || null;
const signId = path?.astrology?.type === "zodiac"
? String(path?.astrology?.name || "").trim().toLowerCase()
: "";
if (!signId || placements.has(signId)) {
return;
}
const wallsForEdge = edgeWalls(edge);
const primaryWallId = wallsForEdge[0] || "";
const primaryWall = wallById.get(primaryWallId);
placements.set(signId, {
wallId: primaryWallId,
edgeId: String(edge?.id || "").trim().toLowerCase(),
wallName: primaryWall?.name || cap(primaryWallId || "wall"),
edgeName: resolveCubeDirectionLabel(primaryWallId, edge)
});
});
return placements;
}
function cubePlacementLabel(placement) {
const wallName = placement?.wallName || "Wall";
const edgeName = placement?.edgeName || "Direction";
return `Cube: ${wallName} Wall - ${edgeName}`;
}
window.ZodiacReferenceBuilders = {
buildCubeSignPlacements,
buildMonthReferencesBySign,
cubePlacementLabel,
formatDateRange
};
})();