// numerology.jsx - повна матриця долі Azoth AI на 22 аркани const MATRIX_ARCANA = { 1: { name: "Маг", key: "воля, ініціація, здатність запускати процес" }, 2: { name: "Жриця", key: "інтуїція, пам'ять, тиша, приховане знання" }, 3: { name: "Імператриця", key: "творення, тіло, ресурс, плодючість" }, 4: { name: "Імператор", key: "структура, межі, порядок, відповідальність" }, 5: { name: "Ієрофант", key: "традиція, навчання, посвята, моральний закон" }, 6: { name: "Закохані", key: "вибір, союз, цінності, узгодження серця" }, 7: { name: "Колісниця", key: "рух, перемога, воля, дисципліна шляху" }, 8: { name: "Справедливість", key: "закон, рівновага, причинність, чесна міра" }, 9: { name: "Самітник", key: "мудрість, самостійність, внутрішній ліхтар" }, 10: { name: "Колесо Фортуни", key: "цикл, шанс, поворот, ритм долі" }, 11: { name: "Сила", key: "життєва енергія, м'яка влада, приборкання інстинкту" }, 12: { name: "Повішений", key: "пауза, служіння, інший погляд, добровільна жертва" }, 13: { name: "Смерть", key: "завершення, трансформація, очищення форми" }, 14: { name: "Помірність", key: "алхімія, баланс, зцілення, точна пропорція" }, 15: { name: "Диявол", key: "бажання, залежність, матерія, тіньова угода" }, 16: { name: "Вежа", key: "злам, правда удару, звільнення від хибної споруди" }, 17: { name: "Зоря", key: "натхнення, віра, ясність, м'яке відновлення" }, 18: { name: "Місяць", key: "сни, страхи, рідова пам'ять, образи несвідомого" }, 19: { name: "Сонце", key: "сила життя, видимість, радість, щедрість" }, 20: { name: "Суд", key: "поклик, пробудження, голос роду, відповідь душі" }, 21: { name: "Світ", key: "цілісність, завершення, інтеграція, велике коло" }, 22: { name: "Блазень", key: "нульовий крок, свобода, довіра, новий цикл" }, }; const CHAKRAS = [ ["Сахасрара", "Місія"], ["Аджна", "Доля, егрегори"], ["Вішудха", "Доля, егрегори"], ["Анахата", "Стосунки, картина світу"], ["Маніпура", "Статус, відповідальність"], ["Свадхістана", "Дитяча любов та радість"], ["Муладхара", "Тіло, матерія"], ]; function digitSum(value) { return String(Math.abs(Number(value) || 0)).split("").reduce((sum, ch) => sum + Number(ch), 0); } function base22(value) { let n = Math.abs(Number(value) || 0); if (n === 0) return 22; while (n > 22) n = digitSum(n); return n || 22; } function sum22(...values) { return base22(values.reduce((sum, value) => sum + (Number(value) || 0), 0)); } function validBirthDate(day, month, year) { if (year < 1900 || year > 2099 || month < 1 || month > 12 || day < 1 || day > 31) return null; const dt = new Date(Date.UTC(year, month - 1, day)); if (dt.getUTCFullYear() !== year || dt.getUTCMonth() !== month - 1 || dt.getUTCDate() !== day) return null; return { day, month, year }; } function extractBirthDate(text) { const value = String(text || ""); let match = value.match(/\b(\d{1,2})[.\-/](\d{1,2})[.\-/](\d{4})\b/); if (match) return validBirthDate(Number(match[1]), Number(match[2]), Number(match[3])); match = value.match(/\b(\d{4})-(\d{1,2})-(\d{1,2})\b/); if (match) return validBirthDate(Number(match[3]), Number(match[2]), Number(match[1])); return null; } function formatBirthDate(date) { const d = String(date.day).padStart(2, "0"); const m = String(date.month).padStart(2, "0"); return `${d}.${m}.${date.year}`; } function calculateAge(date) { const now = new Date(); let age = now.getFullYear() - date.year; const monthPassed = now.getMonth() + 1 > date.month || (now.getMonth() + 1 === date.month && now.getDate() >= date.day); if (!monthPassed) age -= 1; return Math.max(0, age); } function matrixNode(id, label, short, value, x, y, formula, size = "inner", tone = "") { return { id, label, short, value, arcana: MATRIX_ARCANA[value], x, y, formula, size, tone, }; } function interpolate(p1, p2, ratio) { return { x: p1.x + (p2.x - p1.x) * ratio, y: p1.y + (p2.y - p1.y) * ratio }; } function buildAgeTicks(vertices, center, top, bottom) { const result = []; for (let age = 5; age <= 75; age += 5) { if (age % 10 === 0) continue; const segment = Math.floor(age / 10); const ratio = (age % 10) / 10; const p = interpolate(vertices[segment], vertices[(segment + 1) % vertices.length], ratio); result.push({ age, value: sum22(vertices[segment].value, vertices[(segment + 1) % vertices.length].value, center, age / 5), x: p.x, y: p.y, }); } return [ { age: 0, value: vertices[0].value, x: vertices[0].x, y: vertices[0].y }, ...result, { age: 80, value: sum22(top, bottom), x: vertices[0].x, y: vertices[0].y + 4 }, ]; } function buildAgeBands(vertices, center) { const bands = []; const formatAgePoint = value => Number.isInteger(value) ? String(value) : String(value).replace(".5", ".5"); for (let segment = 0; segment < vertices.length; segment += 1) { const from = vertices[segment]; const to = vertices[(segment + 1) % vertices.length]; const decade = segment * 10; const middle = sum22(from.value, to.value); const left = sum22(from.value, middle); const right = sum22(middle, to.value); const ageSteps = [ { ratio: 0.175, start: 1, end: 2.5, value: sum22(from.value, left) }, { ratio: 0.3, start: 2.5, end: 3.5, value: left }, { ratio: 0.375, start: 3.5, end: 4, value: sum22(left, middle) }, { ratio: 0.5, point: 5, value: middle, major: true }, { ratio: 0.675, start: 6, end: 7.5, value: sum22(middle, right) }, { ratio: 0.8, start: 7.5, end: 8.5, value: right }, { ratio: 0.875, start: 8.5, end: 9, value: sum22(right, to.value) }, ]; ageSteps.forEach((step, index) => { const age = decade + (step.point || ((step.start + step.end) / 2)); const p = interpolate(from, to, step.ratio); const label = step.major ? `${decade + step.point} років` : `${formatAgePoint(decade + step.start)}-${formatAgePoint(decade + step.end)}`; bands.push({ age, label, value: step.value, major: Boolean(step.major), segment, index, x: p.x, y: p.y, }); }); } return bands; } function buildHealthRows(core) { const { a, b, c, d, e, ab, bc, cd } = core; const rows = [ [CHAKRAS[0], a, b, ab], [CHAKRAS[1], sum22(b, e), c, sum22(a, e)], [CHAKRAS[2], sum22(a, e), sum22(b, e), d], [CHAKRAS[3], sum22(a, c), bc, cd], [CHAKRAS[4], e, e, c], [CHAKRAS[5], ab, sum22(b, e), sum22(a, c)], [CHAKRAS[6], c, d, cd], ]; const totals = rows.reduce((acc, row) => { acc[0] += row[1]; acc[1] += row[2]; acc[2] += row[3]; return acc; }, [0, 0, 0]).map(base22); return { rows: rows.map(([chakra, physical, energy, emotion]) => ({ chakra: chakra[0], theme: chakra[1], physical, energy, emotion, })), totals, }; } function buildDestinyMatrix(text) { const date = extractBirthDate(text); if (!date) return null; const a = base22(date.day); const b = base22(date.month); const c = base22(digitSum(date.year)); const d = sum22(a, b, c); const e = sum22(a, b, c, d); const ab = sum22(a, b); const bc = sum22(b, c); const cd = sum22(c, d); const ad = sum22(a, d); const core = { a, b, c, d, e, ab, bc, cd, ad }; const outerNodes = [ matrixNode("day", "День народження / портрет", "0 років", a, 8, 50, "день народження", "outer", "west"), matrixNode("ab", "Вузол 10 років", "10 років", ab, 24, 24, "день + місяць", "outer"), matrixNode("month", "Місяць / душа", "20 років", b, 50, 8, "місяць народження", "outer", "north"), matrixNode("bc", "Вузол 30 років", "30 років", bc, 76, 24, "місяць + рік", "outer"), matrixNode("year", "Рік / соціум", "40 років", c, 92, 50, "сума цифр року", "outer", "east"), matrixNode("cd", "Вузол 50 років", "50 років", cd, 76, 76, "рік + нижній код", "outer"), matrixNode("destiny", "Земний код / підсумок", "60 років", d, 50, 92, "день + місяць + рік", "outer", "south"), matrixNode("ad", "Вузол 70 років", "70 років", ad, 24, 76, "день + нижній код", "outer"), ]; const centerNode = matrixNode("center", "Центр матриці", "центр", e, 50, 50, "день + місяць + рік + нижній код", "center"); const innerNodes = [ matrixNode("v1", "Ментальний ключ", "розум", c, 50, 20, "річна енергія на вертикалі"), matrixNode("v2", "Душевний фільтр", "душа", sum22(b, e), 50, 29, "місяць + центр"), matrixNode("v3", "Верхній ресурс", "ресурс", bc, 50, 39, "місяць + рік"), matrixNode("v4", "Тілесна опора", "тіло", sum22(b, e), 50, 64, "місяць + центр"), matrixNode("v5", "Матеріальна вісь", "матерія", c, 50, 74, "рік"), matrixNode("h1", "Лівий ресурс", "ресурс", sum22(b, e), 18, 50, "місяць + центр"), matrixNode("h2", "Особиста сила", "сила", sum22(a, e), 26, 50, "день + центр"), matrixNode("h3", "Внутрішній конфлікт", "урок", sum22(a, c), 38, 50, "день + рік"), matrixNode("h4", "Соціальний прояв", "прояв", c, 58, 50, "рік"), matrixNode("h5", "Професійний канал", "праця", sum22(c, e), 66, 50, "рік + центр"), matrixNode("h6", "Ресурс реалізації", "ресурс", sum22(c, e), 78, 50, "рік + центр"), matrixNode("h7", "Зовнішній результат", "результат", d, 86, 50, "нижній код"), matrixNode("m1", "Лінія чоловічого роду: вузол 1", "чол.", sum22(ab, d), 28, 36, "верхній лівий вузол + нижній код"), matrixNode("m2", "Лінія чоловічого роду: вузол 2", "чол.", d, 35, 43, "нижній код"), matrixNode("f1", "Лінія жіночого роду: вузол 1", "жін.", bc, 72, 36, "верхній правий вузол"), matrixNode("f2", "Лінія жіночого роду: вузол 2", "жін.", sum22(bc, c), 65, 43, "верхній правий вузол + рік"), matrixNode("love1", "Лінія стосунків", "любов", sum22(b, e), 57, 72, "місяць + центр", "small", "love"), matrixNode("love2", "Серцевий урок", "серце", sum22(a, c), 62, 64, "день + рік", "small", "love"), matrixNode("love3", "Канал любові", "любов", ad, 68, 56, "день + нижній код", "small", "love"), matrixNode("money1", "Грошовий вузол", "гроші", sum22(c, e), 72, 48, "рік + центр", "small", "money"), matrixNode("money2", "Матеріальний ключ", "гроші", sum22(c, d, e), 79, 43, "рік + нижній код + центр", "small", "money"), ]; const channels = [ matrixNode("love", "Канал стосунків", "Любов", ad, 0, 0, "день + нижній код"), matrixNode("money", "Грошовий канал", "Гроші", bc, 0, 0, "місяць + рік"), matrixNode("purpose", "Призначення", "Шлях", sum22(b, e), 0, 0, "місяць + центр"), matrixNode("shadow", "Тіньовий урок", "Тінь", e, 0, 0, "центр матриці"), ]; const health = buildHealthRows(core); const purpose = [ { title: "Особисте", value: e, rows: [ ["Небо", sum22(b, d)], ["Земля", sum22(a, c)], ["Синтез", sum22(e, a, c)], ], }, { title: "Соціальне", value: c, rows: [ ["Чоловічий рід", sum22(ab, cd)], ["Жіночий рід", sum22(bc, ad)], ["Реалізація", sum22(c, e)], ], }, ]; const allNodes = [...outerNodes, centerNode, ...innerNodes, ...channels]; return { type: "destiny_matrix", date: formatBirthDate(date), age: calculateAge(date), rawDate: date, method: "Azoth Matrix 22 full: день A, місяць B, рік C; нижній код D=A+B+C; центр E=A+B+C+D; кутові вузли AB, BC, CD, AD; усі значення приводяться до 1-22 через суму цифр, 22 зберігається як окремий аркан.", core, outerNodes, centerNode, innerNodes, nodes: allNodes, channels, health, purpose, ageTicks: buildAgeTicks(outerNodes, e, b, d), ageBands: buildAgeBands(outerNodes, e), byId: Object.fromEntries(allNodes.map(node => [node.id, node])), }; } function shouldBuildDestinyMatrix(active, text) { const lc = String(text || "").toLowerCase(); if (!extractBirthDate(text)) return false; const explicitMatrix = /матриц|матриця|матрица|matrix\s*(xxii|22|of destiny)|матриц\w*\s+(дол|судьб)|дол[іи]\s+матриц|судьб\w*\s+матриц|карта\s+дол[іи]/.test(lc); if (explicitMatrix) return true; const explicitNatal = /натал|natal|birth chart|карта народження|карта рождения|астро(?:логічн|логическ|logical)?\s*карт|гороскоп|асценд|ascendant|mc\b|доми|houses|планет/.test(lc); if (explicitNatal) return false; return active === "numero" && /(матриц|матриця|матрица|дол[іи]|судьб)/.test(lc); } function nodeContext(node) { return `${node.label}: ${node.value} (${node.arcana.name}) - ${node.arcana.key}; формула: ${node.formula}`; } function buildMatrixContext(matrix) { matrix = ensureFullMatrix(matrix); if (!matrix) return ""; const coreText = matrix.outerNodes.concat([matrix.centerNode]).map(nodeContext).join("; "); const innerText = matrix.innerNodes.map(nodeContext).join("; "); const channelText = matrix.channels.map(nodeContext).join("; "); const healthText = matrix.health.rows .map(row => `${row.chakra} (${row.theme}): фізика ${row.physical}, енергія ${row.energy}, емоція ${row.emotion}`) .join("; "); const purposeText = matrix.purpose .map(block => `${block.title}: ${block.value}; ${block.rows.map(([label, value]) => `${label} ${value}`).join(", ")}`) .join("; "); const ageText = matrix.ageTicks .filter(tick => tick.age % 10 === 0 || tick.age % 15 === 0 || tick.age === matrix.age) .map(tick => `${tick.age} років: ${tick.value}`) .join("; "); const ageBandText = (matrix.ageBands || []) .map(band => `${band.label}: ${band.value}`) .join("; "); return `\n\n[Повна Матриця долі вже розрахована інтерфейсом Azoth AI для дати ${matrix.date}, вік ${matrix.age}. Метод: ${matrix.method} Головний контур: ${coreText}. Внутрішні лінії: ${innerText}. Канали: ${channelText}. Карта здоров'я/чакр як символічна езотерична карта, не медицина: ${healthText}; результат фізика ${matrix.health.totals[0]}, енергія ${matrix.health.totals[1]}, емоція ${matrix.health.totals[2]}. Призначення: ${purposeText}. Вікові акценти: ${ageText}. Малий віковий контур: ${ageBandText}. Тлумач саме ці числа, позиції й канали. Не перераховуй і не підміняй значення. Якщо користувач не просить коротко, дай детальний практичний розбір для езотерика-консультанта: головні осі, зовнішній контур, центр, родові лінії, гроші, стосунки, тінь, здоров'я/чакри як символічні зони, вікові періоди, питання для клієнтської сесії, рекомендації. Пиши без фаталізму.]`; } function ensureFullMatrix(matrix) { if (!matrix) return null; if (matrix.outerNodes && matrix.centerNode && matrix.health && matrix.purpose) return matrix; const seed = matrix.date || (matrix.rawDate ? formatBirthDate(matrix.rawDate) : ""); return buildDestinyMatrix(seed) || matrix; } const MATRIX_CHART_COORDS = { day: { x: 92, y: 500, r: 51 }, ab: { x: 240, y: 240, r: 47 }, month: { x: 500, y: 88, r: 52 }, bc: { x: 760, y: 240, r: 47 }, year: { x: 930, y: 500, r: 50 }, cd: { x: 760, y: 760, r: 47 }, destiny: { x: 500, y: 912, r: 52 }, ad: { x: 240, y: 760, r: 47 }, center: { x: 500, y: 500, r: 56 }, v1: { x: 500, y: 176, r: 28 }, v2: { x: 500, y: 248, r: 28 }, v3: { x: 500, y: 354, r: 27 }, v4: { x: 500, y: 646, r: 27 }, v5: { x: 500, y: 724, r: 28 }, h1: { x: 188, y: 500, r: 27 }, h2: { x: 246, y: 500, r: 29 }, h3: { x: 366, y: 500, r: 28 }, h4: { x: 600, y: 500, r: 28 }, h5: { x: 665, y: 500, r: 28 }, h6: { x: 746, y: 500, r: 28 }, h7: { x: 825, y: 500, r: 27 }, m1: { x: 286, y: 323, r: 29 }, m2: { x: 354, y: 391, r: 28 }, f1: { x: 714, y: 323, r: 29 }, f2: { x: 646, y: 391, r: 28 }, love1: { x: 574, y: 734, r: 26 }, love2: { x: 652, y: 652, r: 26 }, love3: { x: 724, y: 574, r: 26 }, money1: { x: 716, y: 446, r: 26 }, money2: { x: 804, y: 388, r: 26 }, }; function chartCoord(node) { return MATRIX_CHART_COORDS[node.id] || { x: node.x * 10, y: node.y * 10, r: node.size === "small" ? 25 : 28, }; } function chartPoints(nodes, ids) { const byId = Object.fromEntries(nodes.map(node => [node.id, node])); return ids .map(id => byId[id]) .filter(Boolean) .map(node => { const p = chartCoord(node); return `${p.x},${p.y}`; }) .join(" "); } function outwardPoint(item, offset = 54) { const base = { x: item.x * 10, y: item.y * 10 }; const dx = base.x - 500; const dy = base.y - 500; const len = Math.sqrt(dx * dx + dy * dy) || 1; return { x: base.x + (dx / len) * offset, y: base.y + (dy / len) * offset, }; } function MatrixChartNode({ node, index }) { const p = chartCoord(node); const kind = node.size || "inner"; const tone = node.tone ? ` dmatrix__chart-node--${node.tone}` : ""; const showLabel = kind === "outer" || kind === "center"; return ( {`${node.label}: ${node.value} ${node.arcana.name}. ${node.formula}`} {node.value} {showLabel && {node.short}} ); } function MatrixDetailSection({ title, nodes }) { return (
{title}
{nodes.map(node => (
{node.short} {node.value} {node.arcana.name}
))}
); } function MatrixChart({ matrix }) { const nodes = [...matrix.outerNodes, ...matrix.innerNodes, matrix.centerNode]; const outer = chartPoints(nodes, ["day", "ab", "month", "bc", "year", "cd", "destiny", "ad"]); const diamond = chartPoints(nodes, ["day", "month", "year", "destiny", "day"]); const square = chartPoints(nodes, ["ab", "bc", "cd", "ad", "ab"]); const vertical = chartPoints(nodes, ["month", "v1", "v2", "v3", "center", "v4", "v5", "destiny"]); const horizontal = chartPoints(nodes, ["day", "h1", "h2", "h3", "center", "h4", "h5", "h6", "h7", "year"]); const male = chartPoints(nodes, ["ab", "m1", "m2", "center", "love2", "love3", "cd"]); const female = chartPoints(nodes, ["bc", "f1", "f2", "center", "ad"]); const relation = chartPoints(nodes, ["destiny", "v5", "love1", "love2", "love3", "money1", "money2", "year"]); return ( лінія чоловічого роду лінія жіночого роду $ {(matrix.ageBands || []).map((band, i) => { const p = outwardPoint(band, 58); return ( {band.value} {band.label} ); })} {nodes.map((node, i) => )} ); } function MatrixAgeContour({ matrix }) { const decades = matrix.outerNodes.map(node => ({ label: node.short, value: node.value, name: node.arcana.name })); return (
Віковий контур
{decades.map(item => (
{item.label}{item.value}{item.name}
))} {(matrix.ageBands || []).map((band, i) => (
{band.label}{band.value}
))}
); } function DestinyMatrixView({ matrix }) { matrix = ensureFullMatrix(matrix); if (!matrix) return null; if (!matrix.outerNodes || !matrix.centerNode || !matrix.health || !matrix.purpose) return null; const detailSections = [ ["Вертикаль", matrix.innerNodes.filter(node => node.id.startsWith("v"))], ["Горизонталь", matrix.innerNodes.filter(node => node.id.startsWith("h"))], ["Рід", matrix.innerNodes.filter(node => node.id.startsWith("m") || node.id.startsWith("f"))], ["Любов / гроші", matrix.innerNodes.filter(node => node.id.startsWith("love") || node.id.startsWith("money"))], ]; return (
Matrix XXII · повна карта
Матриця долі
{matrix.date} {matrix.age} років
Карта здоров'я
{matrix.health.rows.map(row => ( ))}
ЧакраФізикаЕнергіяЕмоція
{row.chakra}{row.theme} {row.physical}{row.energy}{row.emotion}
РезультатЗагальне поле {matrix.health.totals[0]}{matrix.health.totals[1]}{matrix.health.totals[2]}
{matrix.purpose.map(block => (
{block.title}{block.value}
{block.rows.map(([label, value]) => (
{label}{value}
))}
))}
{matrix.channels.map((node, i) => (
{node.short} {node.value} {node.arcana.name}
))}
{detailSections.map(([title, nodes]) => )}
); } Object.assign(window, { MATRIX_ARCANA, base22, extractBirthDate, buildDestinyMatrix, shouldBuildDestinyMatrix, buildMatrixContext, DestinyMatrixView, });