chart2txt 0.5.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -34
- package/dist/chart2txt.d.ts +9 -0
- package/dist/chart2txt.js +30 -0
- package/dist/chart2txt.min.js +1 -1
- package/dist/config/ChartSettings.d.ts +13 -6
- package/dist/config/ChartSettings.js +36 -10
- package/dist/constants.d.ts +17 -2
- package/dist/constants.js +301 -32
- package/dist/core/analysis.d.ts +6 -0
- package/dist/core/analysis.js +235 -0
- package/dist/core/aspectPatterns.d.ts +10 -0
- package/dist/core/aspectPatterns.js +460 -0
- package/dist/core/aspects.d.ts +14 -11
- package/dist/core/aspects.js +142 -40
- package/dist/core/astrology.d.ts +8 -2
- package/dist/core/astrology.js +23 -6
- package/dist/core/dignities.d.ts +2 -0
- package/dist/core/dignities.js +71 -0
- package/dist/core/dispositors.d.ts +9 -0
- package/dist/core/dispositors.js +57 -0
- package/dist/core/grouping.d.ts +9 -0
- package/dist/core/grouping.js +45 -0
- package/dist/core/signDistributions.d.ts +21 -0
- package/dist/core/signDistributions.js +50 -0
- package/dist/core/stelliums.d.ts +10 -0
- package/dist/core/stelliums.js +108 -0
- package/dist/formatters/text/sections/angles.js +4 -4
- package/dist/formatters/text/sections/aspectPatterns.d.ts +9 -0
- package/dist/formatters/text/sections/aspectPatterns.js +199 -0
- package/dist/formatters/text/sections/aspects.d.ts +3 -6
- package/dist/formatters/text/sections/aspects.js +35 -49
- package/dist/formatters/text/sections/birthdata.js +1 -1
- package/dist/formatters/text/sections/dispositors.d.ts +8 -0
- package/dist/formatters/text/sections/dispositors.js +19 -0
- package/dist/formatters/text/sections/houseOverlays.d.ts +11 -6
- package/dist/formatters/text/sections/houseOverlays.js +38 -69
- package/dist/formatters/text/sections/houses.d.ts +6 -0
- package/dist/formatters/text/sections/houses.js +36 -0
- package/dist/formatters/text/sections/metadata.d.ts +2 -0
- package/dist/formatters/text/sections/metadata.js +54 -0
- package/dist/formatters/text/sections/planets.d.ts +3 -5
- package/dist/formatters/text/sections/planets.js +12 -38
- package/dist/formatters/text/sections/signDistributions.d.ts +9 -0
- package/dist/formatters/text/sections/signDistributions.js +21 -0
- package/dist/formatters/text/textFormatter.d.ts +4 -5
- package/dist/formatters/text/textFormatter.js +86 -112
- package/dist/index.d.ts +7 -4
- package/dist/index.js +11 -6
- package/dist/types.d.ts +159 -13
- package/dist/types.js +15 -0
- package/dist/utils/formatting.d.ts +10 -0
- package/dist/utils/formatting.js +56 -0
- package/dist/utils/houseCalculations.d.ts +10 -0
- package/dist/utils/houseCalculations.js +23 -0
- package/dist/utils/precision.d.ts +49 -0
- package/dist/utils/precision.js +71 -0
- package/dist/utils/validation.d.ts +37 -0
- package/dist/utils/validation.js +181 -0
- package/package.json +2 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectStelliums = detectStelliums;
|
|
4
|
+
exports.formatStellium = formatStellium;
|
|
5
|
+
const astrology_1 = require("./astrology");
|
|
6
|
+
const houseCalculations_1 = require("../utils/houseCalculations");
|
|
7
|
+
const formatting_1 = require("../utils/formatting");
|
|
8
|
+
/**
|
|
9
|
+
* Convert Point to PlanetPosition
|
|
10
|
+
*/
|
|
11
|
+
function pointToPlanetPosition(point, houseCusps) {
|
|
12
|
+
const sign = (0, astrology_1.getDegreeSign)(point.degree);
|
|
13
|
+
const house = houseCusps
|
|
14
|
+
? (0, houseCalculations_1.getHouseForPoint)(point.degree, houseCusps) || undefined
|
|
15
|
+
: undefined;
|
|
16
|
+
return {
|
|
17
|
+
name: point.name,
|
|
18
|
+
degree: point.degree,
|
|
19
|
+
sign,
|
|
20
|
+
house,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Detect Stellium patterns (3+ planets in same sign or adjacent houses)
|
|
25
|
+
* This function requires house information and is specific to single-chart analysis
|
|
26
|
+
*/
|
|
27
|
+
function detectStelliums(planets, houseCusps, minPlanets = 3) {
|
|
28
|
+
const patterns = [];
|
|
29
|
+
// Group by sign
|
|
30
|
+
const signGroups = new Map();
|
|
31
|
+
planets.forEach((planet) => {
|
|
32
|
+
const sign = (0, astrology_1.getDegreeSign)(planet.degree);
|
|
33
|
+
if (!signGroups.has(sign)) {
|
|
34
|
+
signGroups.set(sign, []);
|
|
35
|
+
}
|
|
36
|
+
signGroups.get(sign).push(planet);
|
|
37
|
+
});
|
|
38
|
+
// Check sign-based stelliums
|
|
39
|
+
signGroups.forEach((planetsInSign, sign) => {
|
|
40
|
+
if (planetsInSign.length >= minPlanets) {
|
|
41
|
+
const planetPositions = planetsInSign.map((p) => pointToPlanetPosition(p, houseCusps));
|
|
42
|
+
const houses = planetPositions
|
|
43
|
+
.map((p) => p.house)
|
|
44
|
+
.filter((h) => h !== undefined);
|
|
45
|
+
const degrees = planetsInSign.map((p) => p.degree);
|
|
46
|
+
const span = Math.max(...degrees) - Math.min(...degrees);
|
|
47
|
+
patterns.push({
|
|
48
|
+
type: 'Stellium',
|
|
49
|
+
planets: planetPositions,
|
|
50
|
+
sign,
|
|
51
|
+
houses: [...new Set(houses)].sort(),
|
|
52
|
+
span,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
// Check house-based stelliums (if house cusps available)
|
|
57
|
+
if (houseCusps) {
|
|
58
|
+
const houseGroups = new Map();
|
|
59
|
+
planets.forEach((planet) => {
|
|
60
|
+
const house = (0, houseCalculations_1.getHouseForPoint)(planet.degree, houseCusps);
|
|
61
|
+
if (house) {
|
|
62
|
+
if (!houseGroups.has(house)) {
|
|
63
|
+
houseGroups.set(house, []);
|
|
64
|
+
}
|
|
65
|
+
houseGroups.get(house).push(planet);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
houseGroups.forEach((planetsInHouse, house) => {
|
|
69
|
+
if (planetsInHouse.length >= minPlanets) {
|
|
70
|
+
const planetPositions = planetsInHouse.map((p) => pointToPlanetPosition(p, houseCusps));
|
|
71
|
+
const degrees = planetsInHouse.map((p) => p.degree);
|
|
72
|
+
const span = Math.max(...degrees) - Math.min(...degrees);
|
|
73
|
+
// Only add if not already covered by sign stellium
|
|
74
|
+
const existingSignStellium = patterns.find((p) => p.type === 'Stellium' &&
|
|
75
|
+
p.planets.some((planet) => planetPositions.some((pp) => pp.name === planet.name)));
|
|
76
|
+
if (!existingSignStellium) {
|
|
77
|
+
patterns.push({
|
|
78
|
+
type: 'Stellium',
|
|
79
|
+
planets: planetPositions,
|
|
80
|
+
houses: [house],
|
|
81
|
+
span,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return patterns;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Format a Stellium pattern for display in compact format
|
|
91
|
+
*/
|
|
92
|
+
function formatStellium(pattern) {
|
|
93
|
+
const planetNames = pattern.planets.map((p) => p.name).join(', ');
|
|
94
|
+
let location = '';
|
|
95
|
+
if (pattern.sign) {
|
|
96
|
+
location = pattern.sign;
|
|
97
|
+
}
|
|
98
|
+
if (pattern.houses && pattern.houses.length > 0) {
|
|
99
|
+
const houseStr = pattern.houses.length === 1
|
|
100
|
+
? `${(0, formatting_1.getOrdinal)(pattern.houses[0])} House`
|
|
101
|
+
: pattern.houses.map((h) => `${(0, formatting_1.getOrdinal)(h)} House`).join('-');
|
|
102
|
+
location += location ? ` (${houseStr})` : houseStr;
|
|
103
|
+
}
|
|
104
|
+
const locationStr = location ? ` in ${location}` : '';
|
|
105
|
+
return [
|
|
106
|
+
`Stellium (${pattern.span.toFixed(1)}°): ${planetNames}${locationStr}`,
|
|
107
|
+
];
|
|
108
|
+
}
|
|
@@ -11,16 +11,16 @@ const astrology_1 = require("../../../core/astrology");
|
|
|
11
11
|
function generateAnglesOutput(ascDegree, mcDegree) {
|
|
12
12
|
const output = ['[ANGLES]'];
|
|
13
13
|
if (ascDegree !== undefined) {
|
|
14
|
-
output.push(`
|
|
14
|
+
output.push(`Ascendant: ${Math.floor((0, astrology_1.getDegreeInSign)(ascDegree))}° ${(0, astrology_1.getDegreeSign)(ascDegree)}`);
|
|
15
15
|
}
|
|
16
16
|
else {
|
|
17
|
-
output.push('
|
|
17
|
+
output.push('Ascendant: Not available');
|
|
18
18
|
}
|
|
19
19
|
if (mcDegree !== undefined) {
|
|
20
|
-
output.push(`
|
|
20
|
+
output.push(`Midheaven: ${Math.floor((0, astrology_1.getDegreeInSign)(mcDegree))}° ${(0, astrology_1.getDegreeSign)(mcDegree)}`);
|
|
21
21
|
}
|
|
22
22
|
else {
|
|
23
|
-
output.push('
|
|
23
|
+
output.push('Midheaven: Not available');
|
|
24
24
|
}
|
|
25
25
|
return output;
|
|
26
26
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AspectPattern } from '../../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Generates the [ASPECT PATTERNS] section of the chart output.
|
|
4
|
+
* @param patterns Array of detected aspect patterns
|
|
5
|
+
* @param customTitle Optional custom title for the section
|
|
6
|
+
* @param showChartNames Whether to show chart names for planets (false for single charts, true for multi-chart)
|
|
7
|
+
* @returns An array of strings for the output.
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateAspectPatternsOutput(patterns: AspectPattern[], customTitle?: string, showChartNames?: boolean): string[];
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateAspectPatternsOutput = generateAspectPatternsOutput;
|
|
4
|
+
const astrology_1 = require("../../../core/astrology");
|
|
5
|
+
const formatting_1 = require("../../../utils/formatting");
|
|
6
|
+
/**
|
|
7
|
+
* Format a planet position for display
|
|
8
|
+
*/
|
|
9
|
+
function formatPlanetPosition(planet, includeHouse = false, showChartNames = true) {
|
|
10
|
+
const degInSign = Math.floor((0, astrology_1.getDegreeInSign)(planet.degree));
|
|
11
|
+
const houseStr = includeHouse && planet.house ? ` (${(0, formatting_1.getOrdinal)(planet.house)} house)` : '';
|
|
12
|
+
const chartPrefix = showChartNames && planet.chartName ? `${planet.chartName}'s ` : '';
|
|
13
|
+
return `${chartPrefix}${planet.name} ${degInSign}° ${planet.sign}${houseStr}`;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Format a T-Square pattern in compact format
|
|
17
|
+
*/
|
|
18
|
+
function formatTSquare(pattern, showChartNames = true) {
|
|
19
|
+
if (pattern.type !== 'T-Square')
|
|
20
|
+
return [];
|
|
21
|
+
const apex = formatPlanetPosition(pattern.apex, false, showChartNames);
|
|
22
|
+
const opp1 = formatPlanetPosition(pattern.opposition[0], false, showChartNames);
|
|
23
|
+
const opp2 = formatPlanetPosition(pattern.opposition[1], false, showChartNames);
|
|
24
|
+
return [
|
|
25
|
+
`T-Square (${pattern.mode}, ${pattern.averageOrb.toFixed(1)}°): ${apex} ← ${opp1} ↔ ${opp2}`,
|
|
26
|
+
];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Format a Grand Trine pattern in compact format
|
|
30
|
+
*/
|
|
31
|
+
function formatGrandTrine(pattern, showChartNames = true) {
|
|
32
|
+
if (pattern.type !== 'Grand Trine')
|
|
33
|
+
return [];
|
|
34
|
+
const planets = pattern.planets
|
|
35
|
+
.map((p) => formatPlanetPosition(p, false, showChartNames))
|
|
36
|
+
.join(' △ ');
|
|
37
|
+
return [
|
|
38
|
+
`Grand Trine (${pattern.element}, ${pattern.averageOrb.toFixed(1)}°): ${planets}`,
|
|
39
|
+
];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Format a Grand Cross pattern in compact format
|
|
43
|
+
*/
|
|
44
|
+
function formatGrandCross(pattern, showChartNames = true) {
|
|
45
|
+
if (pattern.type !== 'Grand Cross')
|
|
46
|
+
return [];
|
|
47
|
+
const planets = pattern.planets
|
|
48
|
+
.map((p) => formatPlanetPosition(p, false, showChartNames))
|
|
49
|
+
.join(' ⨯ ');
|
|
50
|
+
return [
|
|
51
|
+
`Grand Cross (${pattern.mode}, ${pattern.averageOrb.toFixed(1)}°): ${planets}`,
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Format a Yod pattern in compact format
|
|
56
|
+
*/
|
|
57
|
+
function formatYod(pattern, showChartNames = true) {
|
|
58
|
+
if (pattern.type !== 'Yod')
|
|
59
|
+
return [];
|
|
60
|
+
const apex = formatPlanetPosition(pattern.apex, false, showChartNames);
|
|
61
|
+
const base1 = formatPlanetPosition(pattern.base[0], false, showChartNames);
|
|
62
|
+
const base2 = formatPlanetPosition(pattern.base[1], false, showChartNames);
|
|
63
|
+
return [
|
|
64
|
+
`Yod (${pattern.averageOrb.toFixed(1)}°): ${apex} ← ${base1} • ${base2}`,
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Format a Mystic Rectangle pattern in compact format
|
|
69
|
+
*/
|
|
70
|
+
function formatMysticRectangle(pattern, showChartNames = true) {
|
|
71
|
+
if (pattern.type !== 'Mystic Rectangle')
|
|
72
|
+
return [];
|
|
73
|
+
const opp1_1 = formatPlanetPosition(pattern.oppositions[0][0], false, showChartNames);
|
|
74
|
+
const opp1_2 = formatPlanetPosition(pattern.oppositions[0][1], false, showChartNames);
|
|
75
|
+
const opp2_1 = formatPlanetPosition(pattern.oppositions[1][0], false, showChartNames);
|
|
76
|
+
const opp2_2 = formatPlanetPosition(pattern.oppositions[1][1], false, showChartNames);
|
|
77
|
+
return [
|
|
78
|
+
`Mystic Rectangle (${pattern.averageOrb.toFixed(1)}°): ${opp1_1} ↔ ${opp1_2} | ${opp2_1} ↔ ${opp2_2}`,
|
|
79
|
+
];
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Format a Kite pattern in compact format
|
|
83
|
+
*/
|
|
84
|
+
function formatKite(pattern, showChartNames = true) {
|
|
85
|
+
if (pattern.type !== 'Kite')
|
|
86
|
+
return [];
|
|
87
|
+
const grandTrineStr = pattern.grandTrine
|
|
88
|
+
.map((p) => formatPlanetPosition(p, false, showChartNames))
|
|
89
|
+
.join(' △ ');
|
|
90
|
+
const oppositionPlanet = formatPlanetPosition(pattern.opposition, false, showChartNames);
|
|
91
|
+
// Get the element from the first planet's sign for context
|
|
92
|
+
const element = pattern.grandTrine[0].sign
|
|
93
|
+
? getElementFromSign(pattern.grandTrine[0].sign)
|
|
94
|
+
: '';
|
|
95
|
+
const elementStr = element ? `${element}, ` : '';
|
|
96
|
+
return [
|
|
97
|
+
`Kite (${elementStr}${pattern.averageOrb.toFixed(1)}°): [${grandTrineStr}] ← ${oppositionPlanet}`,
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Helper function to get element from sign
|
|
102
|
+
*/
|
|
103
|
+
function getElementFromSign(sign) {
|
|
104
|
+
const fireSigns = ['Aries', 'Leo', 'Sagittarius'];
|
|
105
|
+
const earthSigns = ['Taurus', 'Virgo', 'Capricorn'];
|
|
106
|
+
const airSigns = ['Gemini', 'Libra', 'Aquarius'];
|
|
107
|
+
const waterSigns = ['Cancer', 'Scorpio', 'Pisces'];
|
|
108
|
+
if (fireSigns.includes(sign))
|
|
109
|
+
return 'Fire';
|
|
110
|
+
if (earthSigns.includes(sign))
|
|
111
|
+
return 'Earth';
|
|
112
|
+
if (airSigns.includes(sign))
|
|
113
|
+
return 'Air';
|
|
114
|
+
if (waterSigns.includes(sign))
|
|
115
|
+
return 'Water';
|
|
116
|
+
return '';
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Check if a Grand Trine is part of any Kite pattern within the same analysis context
|
|
120
|
+
* Uses exact planet identity matching (chart name + planet name + degree)
|
|
121
|
+
*/
|
|
122
|
+
function isGrandTrinePartOfKite(grandTrine, patterns) {
|
|
123
|
+
if (grandTrine.type !== 'Grand Trine')
|
|
124
|
+
return false;
|
|
125
|
+
return patterns.some((pattern) => {
|
|
126
|
+
if (pattern.type !== 'Kite')
|
|
127
|
+
return false;
|
|
128
|
+
// Create unique identifiers for exact planet identity matching
|
|
129
|
+
const createPlanetId = (p) => `${p.chartName || ''}-${p.name}-${p.degree}`;
|
|
130
|
+
const kiteGrandTrinePlanets = pattern.grandTrine.map(createPlanetId);
|
|
131
|
+
const grandTrinePlanets = grandTrine.planets.map(createPlanetId);
|
|
132
|
+
// Check if the sets of planets are identical (same planets, same count)
|
|
133
|
+
return (kiteGrandTrinePlanets.length === grandTrinePlanets.length &&
|
|
134
|
+
kiteGrandTrinePlanets.every((kp) => grandTrinePlanets.includes(kp)));
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Generates the [ASPECT PATTERNS] section of the chart output.
|
|
139
|
+
* @param patterns Array of detected aspect patterns
|
|
140
|
+
* @param customTitle Optional custom title for the section
|
|
141
|
+
* @param showChartNames Whether to show chart names for planets (false for single charts, true for multi-chart)
|
|
142
|
+
* @returns An array of strings for the output.
|
|
143
|
+
*/
|
|
144
|
+
function generateAspectPatternsOutput(patterns, customTitle, showChartNames = true) {
|
|
145
|
+
const output = [
|
|
146
|
+
customTitle ? `[ASPECT PATTERNS: ${customTitle}]` : '[ASPECT PATTERNS]',
|
|
147
|
+
];
|
|
148
|
+
if (patterns.length === 0) {
|
|
149
|
+
output.push('No T-Squares detected.');
|
|
150
|
+
output.push('No Grand Trines detected.');
|
|
151
|
+
return output;
|
|
152
|
+
}
|
|
153
|
+
// Filter out Grand Trines that are part of Kites to avoid duplication
|
|
154
|
+
const filteredPatterns = patterns.filter((pattern) => {
|
|
155
|
+
if (pattern.type === 'Grand Trine') {
|
|
156
|
+
return !isGrandTrinePartOfKite(pattern, patterns);
|
|
157
|
+
}
|
|
158
|
+
return true;
|
|
159
|
+
});
|
|
160
|
+
// Sort patterns by type for consistent output
|
|
161
|
+
const sortOrder = [
|
|
162
|
+
'T-Square',
|
|
163
|
+
'Grand Trine',
|
|
164
|
+
'Grand Cross',
|
|
165
|
+
'Yod',
|
|
166
|
+
'Mystic Rectangle',
|
|
167
|
+
'Kite',
|
|
168
|
+
];
|
|
169
|
+
const sortedPatterns = filteredPatterns.sort((a, b) => {
|
|
170
|
+
return sortOrder.indexOf(a.type) - sortOrder.indexOf(b.type);
|
|
171
|
+
});
|
|
172
|
+
sortedPatterns.forEach((pattern) => {
|
|
173
|
+
switch (pattern.type) {
|
|
174
|
+
case 'T-Square':
|
|
175
|
+
output.push(...formatTSquare(pattern, showChartNames));
|
|
176
|
+
break;
|
|
177
|
+
case 'Grand Trine':
|
|
178
|
+
output.push(...formatGrandTrine(pattern, showChartNames));
|
|
179
|
+
break;
|
|
180
|
+
case 'Grand Cross':
|
|
181
|
+
output.push(...formatGrandCross(pattern, showChartNames));
|
|
182
|
+
break;
|
|
183
|
+
case 'Yod':
|
|
184
|
+
output.push(...formatYod(pattern, showChartNames));
|
|
185
|
+
break;
|
|
186
|
+
case 'Mystic Rectangle':
|
|
187
|
+
output.push(...formatMysticRectangle(pattern, showChartNames));
|
|
188
|
+
break;
|
|
189
|
+
case 'Kite':
|
|
190
|
+
output.push(...formatKite(pattern, showChartNames));
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
// Remove trailing empty line
|
|
195
|
+
if (output[output.length - 1] === '') {
|
|
196
|
+
output.pop();
|
|
197
|
+
}
|
|
198
|
+
return output;
|
|
199
|
+
}
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { AspectData } from '../../../types';
|
|
2
|
-
import { ChartSettings } from '../../../config/ChartSettings';
|
|
3
2
|
/**
|
|
4
|
-
* Generates aspect sections
|
|
3
|
+
* Generates aspect sections from a pre-grouped map of aspects.
|
|
5
4
|
* @param title The main title for this aspect block (e.g., "[ASPECTS]").
|
|
6
|
-
* @param
|
|
7
|
-
* @param settings The chart settings, containing aspect categories.
|
|
5
|
+
* @param groupedAspects A map of category names to aspect data arrays.
|
|
8
6
|
* @param p1ChartName Optional: Name of the first chart/entity for synastry/transit aspects.
|
|
9
7
|
* @param p2ChartName Optional: Name of the second chart/entity for synastry aspects.
|
|
10
8
|
* @param p2IsTransit Optional: Boolean indicating if p2 represents transiting points.
|
|
11
9
|
* @returns An array of strings for the output.
|
|
12
10
|
*/
|
|
13
|
-
export declare function generateAspectsOutput(title: string,
|
|
14
|
-
p2IsTransit?: boolean): string[];
|
|
11
|
+
export declare function generateAspectsOutput(title: string, groupedAspects?: Map<string, AspectData[]>, p1ChartName?: string, p2ChartName?: string, p2IsTransit?: boolean): string[];
|
|
@@ -2,63 +2,49 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateAspectsOutput = generateAspectsOutput;
|
|
4
4
|
/**
|
|
5
|
-
* Generates
|
|
5
|
+
* Generates the output for a single aspect line.
|
|
6
|
+
* @param asp The aspect data.
|
|
7
|
+
* @param p1ChartName Optional name of the first chart.
|
|
8
|
+
* @param p2ChartName Optional name of the second chart.
|
|
9
|
+
* @param p2IsTransit Optional flag if the second chart is for transits.
|
|
10
|
+
* @returns A formatted string for the aspect.
|
|
11
|
+
*/
|
|
12
|
+
function formatAspectLine(asp, p1ChartName, p2ChartName, p2IsTransit = false) {
|
|
13
|
+
const p1NameStr = p1ChartName
|
|
14
|
+
? `${p1ChartName}'s ${asp.planetA}`
|
|
15
|
+
: asp.planetA;
|
|
16
|
+
let p2NameStr = asp.planetB;
|
|
17
|
+
if (p2IsTransit) {
|
|
18
|
+
p2NameStr = `transiting ${asp.planetB}`;
|
|
19
|
+
}
|
|
20
|
+
else if (p2ChartName) {
|
|
21
|
+
p2NameStr = `${p2ChartName}'s ${asp.planetB}`;
|
|
22
|
+
}
|
|
23
|
+
const applicationStr = asp.application && asp.application !== 'exact'
|
|
24
|
+
? ` (${asp.application})`
|
|
25
|
+
: '';
|
|
26
|
+
return `${p1NameStr} ${asp.aspectType} ${p2NameStr}: ${asp.orb.toFixed(1)}°${applicationStr}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Generates aspect sections from a pre-grouped map of aspects.
|
|
6
30
|
* @param title The main title for this aspect block (e.g., "[ASPECTS]").
|
|
7
|
-
* @param
|
|
8
|
-
* @param settings The chart settings, containing aspect categories.
|
|
31
|
+
* @param groupedAspects A map of category names to aspect data arrays.
|
|
9
32
|
* @param p1ChartName Optional: Name of the first chart/entity for synastry/transit aspects.
|
|
10
33
|
* @param p2ChartName Optional: Name of the second chart/entity for synastry aspects.
|
|
11
34
|
* @param p2IsTransit Optional: Boolean indicating if p2 represents transiting points.
|
|
12
35
|
* @returns An array of strings for the output.
|
|
13
36
|
*/
|
|
14
|
-
function generateAspectsOutput(title,
|
|
15
|
-
p2IsTransit = false) {
|
|
37
|
+
function generateAspectsOutput(title, groupedAspects, p1ChartName, p2ChartName, p2IsTransit = false) {
|
|
16
38
|
const output = [title];
|
|
17
|
-
|
|
18
|
-
settings.aspectCategories.forEach((category) => {
|
|
19
|
-
const categoryAspects = aspects.filter((asp) => {
|
|
20
|
-
const orb = asp.orb;
|
|
21
|
-
const minOrbCheck = category.minOrb === undefined ? true : orb > category.minOrb;
|
|
22
|
-
const maxOrbCheck = orb <= category.maxOrb;
|
|
23
|
-
return minOrbCheck && maxOrbCheck;
|
|
24
|
-
});
|
|
25
|
-
if (categoryAspects.length > 0) {
|
|
26
|
-
aspectsFoundInAnyCategory = true;
|
|
27
|
-
let orbRangeStr = `orb < ${category.maxOrb.toFixed(1)}°`;
|
|
28
|
-
if (category.minOrb !== undefined) {
|
|
29
|
-
// Ensure minOrb is less than maxOrb for sensible range string
|
|
30
|
-
orbRangeStr =
|
|
31
|
-
category.minOrb < category.maxOrb
|
|
32
|
-
? `orb ${category.minOrb.toFixed(1)}-${category.maxOrb.toFixed(1)}°`
|
|
33
|
-
: `orb > ${category.minOrb.toFixed(1)}° & < ${category.maxOrb.toFixed(1)}°`; // Fallback for unusual category def
|
|
34
|
-
}
|
|
35
|
-
output.push(`[${category.name.toUpperCase()}: ${orbRangeStr}]`);
|
|
36
|
-
categoryAspects.sort((a, b) => a.orb - b.orb); // Sort by orb tightness
|
|
37
|
-
categoryAspects.forEach((asp) => {
|
|
38
|
-
const p1NameStr = p1ChartName
|
|
39
|
-
? `${p1ChartName}'s ${asp.planetA}`
|
|
40
|
-
: asp.planetA;
|
|
41
|
-
let p2NameStr = asp.planetB;
|
|
42
|
-
if (p2IsTransit) {
|
|
43
|
-
// For "Transit Aspects: Alice", p1 is Alice, p2 is the transiting planet.
|
|
44
|
-
// Example: "Alice's Mercury opposition transiting Neptune: 0.3°" - here p2ChartName is not used for the planet itself.
|
|
45
|
-
p2NameStr = `transiting ${asp.planetB}`;
|
|
46
|
-
}
|
|
47
|
-
else if (p2ChartName) {
|
|
48
|
-
// For "Synastry: Alice-Bob", "Planet-Planet Aspects"
|
|
49
|
-
// Example: "Alice's Mercury opposition Bob's Neptune: 0.3°"
|
|
50
|
-
p2NameStr = `${p2ChartName}'s ${asp.planetB}`;
|
|
51
|
-
}
|
|
52
|
-
// If neither p2IsTransit nor p2ChartName, it's a natal chart aspect, e.g. "Venus opposition Pluto: 1.2°"
|
|
53
|
-
output.push(`${p1NameStr} ${asp.aspectType} ${p2NameStr}: ${asp.orb.toFixed(1)}°`);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
if (!aspectsFoundInAnyCategory && aspects.length > 0) {
|
|
58
|
-
output.push('No aspects within defined categories.');
|
|
59
|
-
}
|
|
60
|
-
else if (aspects.length === 0) {
|
|
39
|
+
if (!groupedAspects || groupedAspects.size === 0) {
|
|
61
40
|
output.push('None');
|
|
41
|
+
return output;
|
|
62
42
|
}
|
|
43
|
+
groupedAspects.forEach((categoryAspects, categoryName) => {
|
|
44
|
+
output.push(categoryName); // The category name is the pre-formatted key from the map
|
|
45
|
+
categoryAspects.forEach((asp) => {
|
|
46
|
+
output.push(formatAspectLine(asp, p1ChartName, p2ChartName, p2IsTransit));
|
|
47
|
+
});
|
|
48
|
+
});
|
|
63
49
|
return output;
|
|
64
50
|
}
|
|
@@ -16,6 +16,6 @@ function generateBirthdataOutput(location, timestamp, settings, sectionTitle = '
|
|
|
16
16
|
const dateStr = (0, datetime_1.formatDateCustom)(timestamp, settings.dateFormat);
|
|
17
17
|
const timeStr = (0, datetime_1.formatTime)(timestamp);
|
|
18
18
|
return [
|
|
19
|
-
`${sectionTitle} ${location || 'Unknown Location'}
|
|
19
|
+
`${sectionTitle} ${location || 'Unknown Location'} | ${dateStr} | ${timeStr}`,
|
|
20
20
|
];
|
|
21
21
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates the [DISPOSITOR TREE] section of the chart output.
|
|
3
|
+
* @param dispositors A map of planet names to their full dispositor chain string.
|
|
4
|
+
* @returns An array of strings for the output.
|
|
5
|
+
*/
|
|
6
|
+
export declare function generateDispositorsOutput(dispositors: {
|
|
7
|
+
[key: string]: string;
|
|
8
|
+
}): string[];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateDispositorsOutput = generateDispositorsOutput;
|
|
4
|
+
/**
|
|
5
|
+
* Generates the [DISPOSITOR TREE] section of the chart output.
|
|
6
|
+
* @param dispositors A map of planet names to their full dispositor chain string.
|
|
7
|
+
* @returns An array of strings for the output.
|
|
8
|
+
*/
|
|
9
|
+
function generateDispositorsOutput(dispositors) {
|
|
10
|
+
const output = ['[DISPOSITOR TREE]'];
|
|
11
|
+
if (Object.keys(dispositors).length === 0) {
|
|
12
|
+
output.push('No dispositor data available.');
|
|
13
|
+
return output;
|
|
14
|
+
}
|
|
15
|
+
for (const planet in dispositors) {
|
|
16
|
+
output.push(dispositors[planet]);
|
|
17
|
+
}
|
|
18
|
+
return output;
|
|
19
|
+
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { ChartData } from '../../../types';
|
|
2
|
-
import { ChartSettings } from '../../../config/ChartSettings';
|
|
3
1
|
/**
|
|
4
2
|
* Generates the [HOUSE OVERLAYS] section for synastry.
|
|
5
|
-
* @param
|
|
6
|
-
* @param
|
|
7
|
-
* @param
|
|
3
|
+
* @param overlays The pre-calculated house overlay data.
|
|
4
|
+
* @param chart1Name The name of the first chart.
|
|
5
|
+
* @param chart2Name The name of the second chart.
|
|
8
6
|
* @returns An array of strings for the output.
|
|
9
7
|
*/
|
|
10
|
-
export declare function generateHouseOverlaysOutput(
|
|
8
|
+
export declare function generateHouseOverlaysOutput(overlays: {
|
|
9
|
+
chart1InChart2Houses: {
|
|
10
|
+
[key: string]: number;
|
|
11
|
+
};
|
|
12
|
+
chart2InChart1Houses: {
|
|
13
|
+
[key: string]: number;
|
|
14
|
+
};
|
|
15
|
+
}, chart1Name: string, chart2Name: string): string[];
|
|
@@ -1,85 +1,54 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateHouseOverlaysOutput = generateHouseOverlaysOutput;
|
|
4
|
-
|
|
5
|
-
function getHouseForPoint(pointDegree, houseCusps) {
|
|
6
|
-
if (!houseCusps || houseCusps.length !== 12) {
|
|
7
|
-
// console.error("Invalid or missing houseCusps array for getHouseForPoint.");
|
|
8
|
-
return 0; // Indicate failure or inability to calculate
|
|
9
|
-
}
|
|
10
|
-
for (let i = 0; i < 12; i++) {
|
|
11
|
-
const cuspStart = houseCusps[i]; // Cusp of current house (e.g., for House 1, i=0, cuspStart = Cusp 1)
|
|
12
|
-
const cuspEnd = houseCusps[(i + 1) % 12]; // Cusp of next house (e.g., for House 1, cuspEnd = Cusp 2)
|
|
13
|
-
// Check if the point degree falls between cuspStart and cuspEnd
|
|
14
|
-
if (cuspStart < cuspEnd) {
|
|
15
|
-
// Normal case: e.g., Cusp1=10, Cusp2=40. Point is between 10 and 40.
|
|
16
|
-
if (pointDegree >= cuspStart && pointDegree < cuspEnd) {
|
|
17
|
-
return i + 1; // House number is i+1 (cusps are 0-indexed, houses 1-indexed)
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
// Wrap-around case: e.g., Cusp12=330, Cusp1=20. Point is >=330 OR <20.
|
|
22
|
-
if (pointDegree >= cuspStart || pointDegree < cuspEnd) {
|
|
23
|
-
return i + 1; // House number is i+1
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
// console.warn(`Point ${pointDegree} did not fall into any house with cusps: ${houseCusps.join(', ')}.`);
|
|
28
|
-
return 0; // Should ideally not be reached if cusps correctly cover 360 degrees
|
|
29
|
-
}
|
|
4
|
+
const formatting_1 = require("../../../utils/formatting");
|
|
30
5
|
/**
|
|
31
6
|
* Generates the [HOUSE OVERLAYS] section for synastry.
|
|
32
|
-
* @param
|
|
33
|
-
* @param
|
|
34
|
-
* @param
|
|
7
|
+
* @param overlays The pre-calculated house overlay data.
|
|
8
|
+
* @param chart1Name The name of the first chart.
|
|
9
|
+
* @param chart2Name The name of the second chart.
|
|
35
10
|
* @returns An array of strings for the output.
|
|
36
11
|
*/
|
|
37
|
-
function generateHouseOverlaysOutput(
|
|
12
|
+
function generateHouseOverlaysOutput(overlays, chart1Name, chart2Name) {
|
|
38
13
|
const output = ['[HOUSE OVERLAYS]'];
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (chart2.houseCusps && chart2.houseCusps.length === 12) {
|
|
43
|
-
output.push(`${c1Name}'s planets in ${c2Name}'s houses:`);
|
|
44
|
-
if (chart1.planets && chart1.planets.length > 0) {
|
|
45
|
-
chart1.planets.forEach((planet) => {
|
|
46
|
-
const houseNumber = getHouseForPoint(planet.degree, chart2.houseCusps);
|
|
47
|
-
if (houseNumber > 0) {
|
|
48
|
-
output.push(`${planet.name}: House ${houseNumber}`);
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
output.push(`${planet.name}: (Could not determine house in ${c2Name})`);
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
output.push('(No planets listed for overlay)');
|
|
57
|
-
}
|
|
14
|
+
output.push(`${chart1Name}'s planets in ${chart2Name}'s houses:`);
|
|
15
|
+
if (Object.keys(overlays.chart1InChart2Houses).length > 0) {
|
|
16
|
+
output.push(formatHouseOverlayCompact(overlays.chart1InChart2Houses));
|
|
58
17
|
}
|
|
59
18
|
else {
|
|
60
|
-
output.push(
|
|
19
|
+
output.push(`(${chart2Name} house cusps not available)`);
|
|
61
20
|
}
|
|
62
|
-
output.push('
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
output.push(`${c2Name}'s planets in ${c1Name}'s houses:`);
|
|
66
|
-
if (chart2.planets && chart2.planets.length > 0) {
|
|
67
|
-
chart2.planets.forEach((planet) => {
|
|
68
|
-
const houseNumber = getHouseForPoint(planet.degree, chart1.houseCusps);
|
|
69
|
-
if (houseNumber > 0) {
|
|
70
|
-
output.push(`${planet.name}: House ${houseNumber}`);
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
output.push(`${planet.name}: (Could not determine house in ${c1Name})`);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
output.push('(No planets listed for overlay)');
|
|
79
|
-
}
|
|
21
|
+
output.push(`${chart2Name}'s planets in ${chart1Name}'s houses:`);
|
|
22
|
+
if (Object.keys(overlays.chart2InChart1Houses).length > 0) {
|
|
23
|
+
output.push(formatHouseOverlayCompact(overlays.chart2InChart1Houses));
|
|
80
24
|
}
|
|
81
25
|
else {
|
|
82
|
-
output.push(
|
|
26
|
+
output.push(`(${chart1Name} house cusps not available)`);
|
|
83
27
|
}
|
|
84
28
|
return output;
|
|
85
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Formats house overlays in a compact format, grouping by house.
|
|
32
|
+
* @param overlays Object mapping planet names to house numbers.
|
|
33
|
+
* @returns A compact string representation.
|
|
34
|
+
*/
|
|
35
|
+
function formatHouseOverlayCompact(overlays) {
|
|
36
|
+
// Group planets by house
|
|
37
|
+
const houseGroups = {};
|
|
38
|
+
for (const planet in overlays) {
|
|
39
|
+
const house = overlays[planet];
|
|
40
|
+
if (!houseGroups[house]) {
|
|
41
|
+
houseGroups[house] = [];
|
|
42
|
+
}
|
|
43
|
+
houseGroups[house].push(planet);
|
|
44
|
+
}
|
|
45
|
+
// Sort houses numerically and format
|
|
46
|
+
const sortedHouses = Object.keys(houseGroups)
|
|
47
|
+
.map(Number)
|
|
48
|
+
.sort((a, b) => a - b);
|
|
49
|
+
const houseStrings = sortedHouses.map((house) => {
|
|
50
|
+
const planets = houseGroups[house].join(', ');
|
|
51
|
+
return `${(0, formatting_1.getOrdinal)(house)}: ${planets}`;
|
|
52
|
+
});
|
|
53
|
+
return houseStrings.join(' | ');
|
|
54
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates the [HOUSE CUSPS] section of the chart output.
|
|
3
|
+
* @param houseCusps Array of 12 house cusp degrees (0-360), or undefined if not available.
|
|
4
|
+
* @returns An array of strings for the output.
|
|
5
|
+
*/
|
|
6
|
+
export declare function generateHousesOutput(houseCusps?: number[]): string[];
|