jyotish-calc 1.1.1 → 1.2.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 CHANGED
@@ -5,7 +5,7 @@ A comprehensive JavaScript library for Vedic Astrology (Jyotish) calculations an
5
5
 
6
6
  ## Overview
7
7
 
8
- This package provides tools and utilities for performing various Vedic Astrology calculations, including planetary positions, nakshatras (lunar mansions), rashis (zodiac signs), bhavas (houses), planetary periods (dashas), divisional charts (vargas), and planetary strengths (shadbala). It leverages the Swiss Ephemeris for precise astronomical calculations.
8
+ This package provides tools and utilities for performing various Vedic Astrology calculations, including planetary positions, nakshatras (lunar mansions), rashis (zodiac signs), special lagnas (Bhava, Hora, Ghati, etc.), upagrahas (Gulika, Mandi, Dhuma, etc.), Ashtakavarga (BAV & SAV), planetary periods (dashas), divisional charts (vargas), and planetary strengths (shadbala). It leverages the Swiss Ephemeris for precise astronomical calculations.
9
9
 
10
10
  ## Installation
11
11
 
@@ -16,11 +16,11 @@ npm install jyotish-calc
16
16
  ## Features
17
17
 
18
18
  - **Graha Calculations**: Calculate positions and aspects of the nine planets (grahas)
19
- - **Nakshatra Determinations**: Calculate and interpret the 27 lunar mansions
20
- - **Rashi Calculations**: Determine zodiac sign positions and interpretations
21
- - **Bhava Analysis**: House system calculations and interpretations
19
+ - **Special Lagnas**: Calculate Bhava Lagna, Hora Lagna, Ghati Lagna, etc.
20
+ - **Upagrahas**: Calculate shadow planets like Gulika, Mandi, Dhuma, etc.
21
+ - **Ashtakavarga**: Complete BAV and SAV calculations with house strength analysis
22
22
  - **Dasha Systems**: Full support for 7 dasha systems (Vimshottari, Ashtottari, Yogini, etc.) with 5-level sub-periods
23
- - **Divisional Charts (Vargas)**: Precise calculations for all 21 divisional charts (D1-D60)
23
+ - **Divisional Charts (Vargas)**: Precise calculations for all 21 divisional charts (D1-D60) with no redundant D1 data
24
24
  - **Shadbala & Bhavabala**: Comprehensive 6-fold planetary strength and house strength calculations
25
25
 
26
26
  ## Project Structure
@@ -30,6 +30,9 @@ jyotish
30
30
  ├── index.js # Main entry point
31
31
  ├── package.json # Package configuration
32
32
  └── src
33
+ ├── ashtakavarga # Ashtakavarga (BAV & SAV) calculations
34
+ ├── lagnas # Special Lagna calculations
35
+ ├── upagrahas # Upagraha calculations
33
36
  ├── bhavas # House calculations
34
37
  ├── dashas # Dasha periods (Vimshottari, Jaimini, etc.)
35
38
  ├── grahas # Planetary calculations
@@ -131,6 +134,64 @@ const bhavaStrength = strengths.calculateBhavaBala(positions, ascendant, jd, 28.
131
134
  console.log(bhavaStrength.total);
132
135
  ```
133
136
 
137
+ ### Special Lagnas & Upagrahas
138
+
139
+ Calculate special rising signs and shadow planets for all divisional charts.
140
+
141
+ ```javascript
142
+ const { lagnas, upagrahas, vargas, grahas } = require('jyotish-calc');
143
+
144
+ const birthData = {
145
+ year: 1998, month: 9, date: 11,
146
+ hour: 4, min: 30, sec: 0,
147
+ lat: 13.0827, lng: 80.2707,
148
+ timezone: 5.5
149
+ };
150
+
151
+ // Calculate all special points
152
+ const specialLagnas = lagnas.calculateAllSpecialLagnas(birthData);
153
+ const positions = grahas.getGrahasPosition(birthData);
154
+ const shadowPlanets = upagrahas.calculateAllUpagrahas(birthData, positions);
155
+
156
+ // Integrate with divisional charts
157
+ const allPoints = {
158
+ Sun: positions.Su.longitude,
159
+ Ascendant: positions.La.longitude,
160
+ ...specialLagnas,
161
+ ...shadowPlanets
162
+ };
163
+ const d9Chart = vargas.calculateVargaChart(allPoints, 'D9');
164
+ ```
165
+
166
+ ### Ashtakavarga
167
+
168
+ Complete strength assessment system.
169
+
170
+ ```javascript
171
+ const { ashtakavarga } = require('jyotish-calc');
172
+
173
+ const positions = {
174
+ Sun: 144.188,
175
+ Moon: 26.174,
176
+ Mars: 109.654,
177
+ Mercury: 131.142,
178
+ Jupiter: 329.905,
179
+ Venus: 131.297,
180
+ Saturn: 9.205,
181
+ Ascendant: 122.003
182
+ };
183
+
184
+ // Calculate BAV and SAV
185
+ const results = ashtakavarga.calculateAshtakavarga(positions);
186
+
187
+ console.log(results.sav); // [27, 33, 40, 23, 26, 25, 27, 26, 29, 34, 27, 20]
188
+ console.log(results.interpretations.houses[2]); // "Exceptional" (40 bindus)
189
+
190
+ // Kakshya Analysis
191
+ const kakshya = ashtakavarga.getKakshya(145.5);
192
+ console.log(kakshya.ruler); // "Mars"
193
+ ```
194
+
134
195
  ## Dependencies
135
196
 
136
197
  - [swisseph-v2](https://www.npmjs.com/package/swisseph-v2): v1.0.4 - Swiss Ephemeris library for astronomical calculations
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Complete Package Result Export
3
+ * Birth Chart: Sep 11, 1998, 4:30 AM, Chennai
4
+ */
5
+
6
+ const jyotish = require('./index');
7
+
8
+ const birthData = {
9
+ dateString: '1998-09-11',
10
+ timeString: '04:30:00',
11
+ lat: 13.0827,
12
+ lng: 80.2707,
13
+ timezone: 5.5
14
+ };
15
+
16
+ const planetMap = {
17
+ 'Su': 'Sun', 'Mo': 'Moon', 'Ma': 'Mars', 'Me': 'Mercury',
18
+ 'Ju': 'Jupiter', 'Ve': 'Venus', 'Sa': 'Saturn', 'Ra': 'Rahu', 'Ke': 'Ketu',
19
+ 'La': 'Ascendant'
20
+ };
21
+
22
+ async function getFullResults() {
23
+ const results = {};
24
+
25
+ try {
26
+ // 1. GRAHA POSITIONS
27
+ results.positions = jyotish.grahas.getGrahasPosition(birthData);
28
+
29
+ // Prepare data for other modules
30
+ const moonLong = results.positions.Mo.longitude;
31
+ const lagnaLong = results.positions.La.longitude;
32
+ const planetLongitudes = {};
33
+ const shadbalaPositions = [];
34
+ const shadbalaOrder = ['Su', 'Mo', 'Ma', 'Me', 'Ju', 'Ve', 'Sa'];
35
+
36
+ Object.entries(results.positions).forEach(([key, p]) => {
37
+ if (planetMap[key]) planetLongitudes[planetMap[key]] = p.longitude;
38
+ });
39
+
40
+ shadbalaOrder.forEach(key => {
41
+ const p = results.positions[key];
42
+ shadbalaPositions.push([Math.floor(p.longitude / 30), p.longitude % 30]);
43
+ });
44
+
45
+ // Extract birth date/time components
46
+ const [year, month, date] = birthData.dateString.split('-').map(Number);
47
+ const [hour, min, sec] = birthData.timeString.split(':').map(Number);
48
+
49
+ // 2. SPECIAL LAGNAS
50
+ const lagnaBirthData = {
51
+ year, month, date,
52
+ hour, min, sec,
53
+ lat: birthData.lat,
54
+ lng: birthData.lng,
55
+ timezone: birthData.timezone,
56
+ ayanamsha: 1
57
+ };
58
+ results.specialLagnas = jyotish.lagnas.calculateAllSpecialLagnas(lagnaBirthData);
59
+
60
+ // Add special lagnas to planet longitudes for varga calculation
61
+ Object.entries(results.specialLagnas).forEach(([name, data]) => {
62
+ planetLongitudes[name] = data.longitude;
63
+ });
64
+
65
+ // 3. UPAGRAHAS
66
+ results.upagrahas = jyotish.upagrahas.calculateAllUpagrahas(lagnaBirthData, results.positions);
67
+
68
+ // Add upagrahas to planet longitudes for varga calculation
69
+ Object.entries(results.upagrahas).forEach(([name, data]) => {
70
+ planetLongitudes[name] = data.longitude;
71
+ });
72
+
73
+ // 4. DASHAS (All Active Dashas)
74
+ const birthDateObj = new Date(birthData.dateString);
75
+ const checkDateObj = new Date();
76
+ results.dashas = jyotish.dashas.getAllActiveDashas(
77
+ birthDateObj,
78
+ moonLong,
79
+ lagnaLong,
80
+ checkDateObj,
81
+ planetLongitudes
82
+ );
83
+
84
+ // 5. VARGAS (Complete Portfolio for all standard divisions)
85
+ // Now includes special lagnas and upagrahas
86
+ results.vargas = {};
87
+ const vargaList = jyotish.vargas.getSupportedVargas(); // D1, D2, ..., D60
88
+ vargaList.forEach(vId => {
89
+ results.vargas[vId] = jyotish.vargas.calculateVargaChart(planetLongitudes, vId);
90
+ });
91
+
92
+ // 6. STRENGTHS (Shadbala & Bhavabala)
93
+ const localHourDecimal = hour + min / 60;
94
+ const utHourDecimal = localHourDecimal - birthData.timezone;
95
+ const jdUT = jyotish.strengths.julianDayNumber(
96
+ [year, month, date],
97
+ [Math.floor(utHourDecimal), (utHourDecimal % 1) * 60, 0]
98
+ );
99
+
100
+ results.strengths = {
101
+ shadbala: jyotish.strengths.calculateShadbala(
102
+ shadbalaPositions,
103
+ Math.floor(lagnaLong / 30),
104
+ jdUT,
105
+ birthData.lat,
106
+ birthData.lng
107
+ ),
108
+ bhavabala: jyotish.strengths.calculateBhavaBala(
109
+ shadbalaPositions,
110
+ Math.floor(lagnaLong / 30),
111
+ jdUT,
112
+ birthData.lat,
113
+ birthData.lng
114
+ )
115
+ };
116
+
117
+ // 7. ASHTAKAVARGA (BAV & SAV)
118
+ const ashtakavargaPositions = {
119
+ Sun: results.positions.Su.longitude,
120
+ Moon: results.positions.Mo.longitude,
121
+ Mars: results.positions.Ma.longitude,
122
+ Mercury: results.positions.Me.longitude,
123
+ Jupiter: results.positions.Ju.longitude,
124
+ Venus: results.positions.Ve.longitude,
125
+ Saturn: results.positions.Sa.longitude,
126
+ Ascendant: results.positions.La.longitude
127
+ };
128
+ results.ashtakavarga = jyotish.ashtakavarga.calculateDetailedAshtakavarga(ashtakavargaPositions);
129
+
130
+ // Write to file directly
131
+ const fs = require('fs');
132
+ fs.writeFileSync('results.json', JSON.stringify(results, null, 2), 'utf8');
133
+ console.log('Results written to results.json');
134
+
135
+ } catch (err) {
136
+ console.error(JSON.stringify({ error: err.message, stack: err.stack }, null, 2));
137
+ }
138
+ }
139
+
140
+ getFullResults();
package/index.js CHANGED
@@ -5,6 +5,9 @@ const utils = require('./src/utils/index');
5
5
  const dashas = require('./src/dashas/index');
6
6
  const vargas = require('./src/vargas/index');
7
7
  const strengths = require('./src/strengths/index');
8
+ const lagnas = require('./src/lagnas/index');
9
+ const upagrahas = require('./src/upagrahas/index');
10
+ const ashtakavarga = require('./src/ashtakavarga/index');
8
11
 
9
12
  module.exports = {
10
13
  grahas,
@@ -13,5 +16,8 @@ module.exports = {
13
16
  utils,
14
17
  dashas,
15
18
  vargas,
16
- strengths
19
+ strengths,
20
+ lagnas,
21
+ upagrahas,
22
+ ashtakavarga
17
23
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jyotish-calc",
3
- "version": "1.1.1",
4
- "description": "Comprehensive Vedic Astrology library with Planet Positions, Dashas, Vargas (Divisional Charts), and Shadbala (Strengths)",
3
+ "version": "1.2.0",
4
+ "description": "Comprehensive Vedic Astrology library with Special Lagnas, Upagrahas, Ashtakavarga, Dashas, Vargas, and Shadbala",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "test": "jest",
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Bhinnashtakavarga (BAV) Calculator
3
+ * Individual planetary Ashtakavarga charts
4
+ */
5
+
6
+ const { CONTRIBUTIONS, PLANET_TOTALS, PLANET_NAMES, REFERENCE_POINTS } = require('./constants');
7
+
8
+ /**
9
+ * Get house number (1-12) from longitude
10
+ */
11
+ function getHouseNumber(longitude) {
12
+ return Math.floor(longitude / 30) + 1;
13
+ }
14
+
15
+ /**
16
+ * Calculate house offset from reference to target
17
+ * Returns 1-12 (not 0-indexed)
18
+ */
19
+ function calculateOffset(targetHouse, referenceHouse) {
20
+ let offset = targetHouse - referenceHouse + 1;
21
+ if (offset <= 0) offset += 12;
22
+ if (offset > 12) offset -= 12;
23
+ return offset;
24
+ }
25
+
26
+ /**
27
+ * Calculate BAV for a single planet
28
+ * @param {string} planet - Planet name (Sun, Moon, Mars, etc.)
29
+ * @param {Object} positions - Planetary positions {Sun: long, Moon: long, ...}
30
+ * @returns {Array} Array of 12 house bindus [house1, house2, ..., house12]
31
+ */
32
+ function calculateBAV(planet, positions) {
33
+ const bindus = Array(12).fill(0);
34
+ const contributions = CONTRIBUTIONS[planet];
35
+
36
+ if (!contributions) {
37
+ throw new Error(`Unknown planet: ${planet}`);
38
+ }
39
+
40
+ const planetHouse = getHouseNumber(positions[planet]);
41
+
42
+ // For each reference point (Sun, Moon, ..., Saturn, Ascendant)
43
+ for (const refPoint of REFERENCE_POINTS) {
44
+ if (!positions[refPoint]) {
45
+ console.warn(`Missing position for ${refPoint}, skipping`);
46
+ continue;
47
+ }
48
+
49
+ const refHouse = getHouseNumber(positions[refPoint]);
50
+ const contributionList = contributions[refPoint];
51
+
52
+ if (!contributionList) {
53
+ continue; // No contributions from this reference point
54
+ }
55
+
56
+ // For each house this reference point contributes to
57
+ for (const offset of contributionList) {
58
+ // Calculate which house gets the bindu
59
+ // offset is counted FROM the reference point
60
+ let targetHouse = refHouse + offset - 1;
61
+ if (targetHouse > 12) targetHouse -= 12;
62
+ if (targetHouse < 1) targetHouse += 12;
63
+
64
+ // Add bindu to the target house (convert to 0-indexed array)
65
+ bindus[targetHouse - 1]++;
66
+ }
67
+ }
68
+
69
+ return bindus;
70
+ }
71
+
72
+ /**
73
+ * Calculate BAV for all planets
74
+ * @param {Object} positions - Planetary positions
75
+ * @returns {Object} BAV charts for all planets
76
+ */
77
+ function calculateAllBAV(positions) {
78
+ const bavCharts = {};
79
+
80
+ for (const planet of PLANET_NAMES) {
81
+ if (!positions[planet]) {
82
+ throw new Error(`Missing position for planet: ${planet}`);
83
+ }
84
+ bavCharts[planet] = calculateBAV(planet, positions);
85
+ }
86
+
87
+ return bavCharts;
88
+ }
89
+
90
+ /**
91
+ * Validate BAV totals
92
+ * Each planet should contribute its expected total bindus
93
+ */
94
+ function validateBAV(bavCharts) {
95
+ const errors = [];
96
+
97
+ for (const planet of PLANET_NAMES) {
98
+ const total = bavCharts[planet].reduce((a, b) => a + b, 0);
99
+ const expected = PLANET_TOTALS[planet];
100
+
101
+ if (total !== expected) {
102
+ errors.push(`${planet}: Expected ${expected} bindus, got ${total}`);
103
+ }
104
+ }
105
+
106
+ return {
107
+ valid: errors.length === 0,
108
+ errors: errors
109
+ };
110
+ }
111
+
112
+ /**
113
+ * Get house strength interpretation for a planet's BAV
114
+ */
115
+ function interpretPlanetaryHouseStrength(bindus) {
116
+ if (bindus >= 5) return 'Very Strong';
117
+ if (bindus >= 4) return 'Strong';
118
+ if (bindus === 3) return 'Moderate';
119
+ if (bindus >= 1) return 'Weak';
120
+ return 'Very Weak';
121
+ }
122
+
123
+ /**
124
+ * Calculate detailed BAV with interpretations
125
+ */
126
+ function calculateDetailedBAV(positions) {
127
+ const bavCharts = calculateAllBAV(positions);
128
+ const validation = validateBAV(bavCharts);
129
+
130
+ // Add interpretations
131
+ const detailed = {};
132
+ for (const planet of PLANET_NAMES) {
133
+ detailed[planet] = {
134
+ bindus: bavCharts[planet],
135
+ total: bavCharts[planet].reduce((a, b) => a + b, 0),
136
+ interpretations: bavCharts[planet].map(b => interpretPlanetaryHouseStrength(b)),
137
+ houses: bavCharts[planet].map((bindus, idx) => ({
138
+ house: idx + 1,
139
+ bindus: bindus,
140
+ strength: interpretPlanetaryHouseStrength(bindus)
141
+ }))
142
+ };
143
+ }
144
+
145
+ return {
146
+ bav: bavCharts,
147
+ detailed: detailed,
148
+ validation: validation
149
+ };
150
+ }
151
+
152
+ module.exports = {
153
+ calculateBAV,
154
+ calculateAllBAV,
155
+ validateBAV,
156
+ interpretPlanetaryHouseStrength,
157
+ calculateDetailedBAV,
158
+ getHouseNumber
159
+ };
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Ashtakavarga Constants
3
+ * Complete bindu contribution tables for all planets
4
+ */
5
+
6
+ // Bindu contribution tables
7
+ // Format: For each planet, specify which houses receive bindus when counted from each reference point
8
+ // Houses are 1-12 (not 0-indexed in the tables for clarity)
9
+
10
+ const CONTRIBUTIONS = {
11
+ Sun: {
12
+ Sun: [1, 2, 4, 7, 8, 9, 10, 11],
13
+ Moon: [3, 6, 10, 11],
14
+ Mars: [1, 2, 4, 7, 8, 9, 10, 11],
15
+ Mercury: [3, 5, 6, 9, 10, 11, 12],
16
+ Jupiter: [5, 6, 9, 11],
17
+ Venus: [6, 7, 12],
18
+ Saturn: [1, 2, 4, 7, 8, 9, 10, 11],
19
+ Ascendant: [3, 4, 6, 10, 11, 12]
20
+ },
21
+ Moon: {
22
+ Moon: [1, 3, 6, 7, 10, 11],
23
+ Sun: [3, 6, 7, 8, 10, 11],
24
+ Mars: [2, 3, 5, 6, 9, 10, 11],
25
+ Mercury: [1, 3, 4, 5, 7, 8, 10, 11],
26
+ Jupiter: [1, 4, 7, 8, 10, 11, 12],
27
+ Venus: [3, 4, 5, 7, 9, 10, 11],
28
+ Saturn: [3, 5, 6, 11],
29
+ Ascendant: [3, 6, 10, 11]
30
+ },
31
+ Mars: {
32
+ Mars: [1, 2, 4, 7, 8, 10, 11],
33
+ Sun: [3, 5, 6, 10, 11],
34
+ Moon: [3, 6, 11],
35
+ Mercury: [3, 5, 6, 11],
36
+ Jupiter: [6, 10, 11, 12],
37
+ Venus: [6, 8, 11, 12],
38
+ Saturn: [1, 4, 7, 8, 10, 11, 12], // Added 12th house (total 7)
39
+ Ascendant: [1, 3, 6, 10, 11]
40
+ },
41
+ Mercury: {
42
+ Mercury: [1, 3, 5, 6, 9, 10, 11, 12],
43
+ Sun: [5, 6, 9, 11, 12],
44
+ Moon: [2, 4, 6, 8, 10, 11],
45
+ Mars: [1, 2, 4, 7, 8, 9, 10, 11],
46
+ Jupiter: [6, 8, 11, 12],
47
+ Venus: [1, 2, 3, 4, 5, 8, 9, 11],
48
+ Saturn: [1, 2, 4, 7, 8, 9, 10, 11],
49
+ Ascendant: [1, 2, 4, 6, 8, 10, 11]
50
+ },
51
+ Jupiter: {
52
+ Jupiter: [1, 2, 3, 4, 7, 8, 10, 11],
53
+ Sun: [1, 2, 3, 4, 7, 8, 9, 10, 11],
54
+ Moon: [2, 5, 7, 9, 11],
55
+ Mars: [1, 2, 4, 7, 8, 10, 11],
56
+ Mercury: [1, 2, 4, 5, 6, 9, 10, 11],
57
+ Venus: [2, 5, 6, 9, 10, 11],
58
+ Saturn: [3, 5, 6, 12],
59
+ Ascendant: [1, 2, 4, 5, 6, 7, 9, 10, 11]
60
+ },
61
+ Venus: {
62
+ Venus: [1, 2, 3, 4, 5, 8, 9, 10, 11],
63
+ Sun: [8, 11, 12],
64
+ Moon: [1, 2, 3, 4, 5, 8, 9, 11, 12],
65
+ Mars: [3, 5, 6, 9, 11, 12],
66
+ Mercury: [3, 5, 6, 9, 11],
67
+ Jupiter: [5, 8, 9, 10, 11],
68
+ Saturn: [3, 4, 5, 8, 9, 10, 11],
69
+ Ascendant: [1, 2, 3, 4, 5, 8, 9, 11]
70
+ },
71
+ Saturn: {
72
+ Saturn: [3, 5, 6, 11],
73
+ Sun: [1, 2, 4, 7, 8, 10, 11],
74
+ Moon: [3, 6, 11],
75
+ Mars: [3, 5, 6, 10, 11], // Added 10th house (total 5)
76
+ Mercury: [6, 8, 9, 10, 11, 12],
77
+ Jupiter: [3, 5, 6, 11, 12], // Added 3rd house (total 5)
78
+ Venus: [6, 11, 12],
79
+ Ascendant: [1, 3, 4, 6, 10, 11]
80
+ }
81
+ };
82
+
83
+ // Expected total bindus per planet (for validation)
84
+ const PLANET_TOTALS = {
85
+ Sun: 48,
86
+ Moon: 49,
87
+ Mars: 39,
88
+ Mercury: 54,
89
+ Jupiter: 56,
90
+ Venus: 52,
91
+ Saturn: 39
92
+ };
93
+
94
+ // Total bindus across all planets = 337
95
+ const TOTAL_BINDUS = 337;
96
+
97
+ // Planet names in standard order
98
+ const PLANET_NAMES = ['Sun', 'Moon', 'Mars', 'Mercury', 'Jupiter', 'Venus', 'Saturn'];
99
+
100
+ // All reference points including Ascendant
101
+ const REFERENCE_POINTS = ['Sun', 'Moon', 'Mars', 'Mercury', 'Jupiter', 'Venus', 'Saturn', 'Ascendant'];
102
+
103
+ module.exports = {
104
+ CONTRIBUTIONS,
105
+ PLANET_TOTALS,
106
+ TOTAL_BINDUS,
107
+ PLANET_NAMES,
108
+ REFERENCE_POINTS
109
+ };
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Ashtakavarga Module
3
+ * Complete implementation of Bhinnashtakavarga (BAV) and Sarvashtakavarga (SAV)
4
+ */
5
+
6
+ const {
7
+ calculateBAV,
8
+ calculateAllBAV,
9
+ validateBAV,
10
+ interpretPlanetaryHouseStrength,
11
+ calculateDetailedBAV,
12
+ getHouseNumber
13
+ } = require('./bav');
14
+
15
+ const {
16
+ calculateSAV,
17
+ validateSAV,
18
+ interpretHouseStrength,
19
+ getStrengthCategory,
20
+ calculateDetailedSAV,
21
+ getHousesByStrength,
22
+ analyzeTransitFavorability
23
+ } = require('./sav');
24
+
25
+ const {
26
+ getKakshya,
27
+ getAllKakshyasInSign,
28
+ analyzeKakshyaTransit,
29
+ getSignTransitKakshyas,
30
+ KAKSHYA_RULERS,
31
+ KAKSHYA_SIZE,
32
+ NUM_KAKSHYAS
33
+ } = require('./kakshya');
34
+
35
+ const {
36
+ CONTRIBUTIONS,
37
+ PLANET_TOTALS,
38
+ TOTAL_BINDUS,
39
+ PLANET_NAMES,
40
+ REFERENCE_POINTS
41
+ } = require('./constants');
42
+
43
+ /**
44
+ * Calculate complete Ashtakavarga (BAV + SAV)
45
+ * Main API function
46
+ * @param {Object} positions - Planetary positions {Sun, Moon, Mars, Mercury, Jupiter, Venus, Saturn, Ascendant}
47
+ * @returns {Object} Complete Ashtakavarga analysis
48
+ */
49
+ function calculateAshtakavarga(positions) {
50
+ // Validate input
51
+ for (const planet of PLANET_NAMES) {
52
+ if (!positions[planet]) {
53
+ throw new Error(`Missing position for planet: ${planet}`);
54
+ }
55
+ }
56
+ if (!positions.Ascendant) {
57
+ throw new Error('Missing Ascendant position');
58
+ }
59
+
60
+ // Calculate BAV for all planets
61
+ const bavCharts = calculateAllBAV(positions);
62
+ const bavValidation = validateBAV(bavCharts);
63
+
64
+ // Calculate SAV
65
+ const sav = calculateSAV(bavCharts);
66
+ const savValidation = validateSAV(sav);
67
+
68
+ // Get interpretations
69
+ const savInterpretations = sav.map(b => interpretHouseStrength(b));
70
+ const housesByStrength = getHousesByStrength(sav);
71
+
72
+ // Calculate statistics
73
+ const total = sav.reduce((a, b) => a + b, 0);
74
+ const average = total / 12;
75
+
76
+ return {
77
+ bav: bavCharts,
78
+ sav: sav,
79
+ interpretations: {
80
+ houses: savInterpretations,
81
+ categories: housesByStrength
82
+ },
83
+ statistics: {
84
+ total: total,
85
+ average: average.toFixed(2),
86
+ max: Math.max(...sav),
87
+ min: Math.min(...sav)
88
+ },
89
+ validation: {
90
+ bav: bavValidation,
91
+ sav: savValidation,
92
+ allValid: bavValidation.valid && savValidation.valid
93
+ }
94
+ };
95
+ }
96
+
97
+ /**
98
+ * Calculate detailed Ashtakavarga with full analysis
99
+ * @param {Object} positions - Planetary positions
100
+ * @returns {Object} Detailed analysis including house-by-house breakdowns
101
+ */
102
+ function calculateDetailedAshtakavarga(positions) {
103
+ const bavDetails = calculateDetailedBAV(positions);
104
+ const savDetails = calculateDetailedSAV(bavDetails.bav);
105
+
106
+ return {
107
+ bav: bavDetails,
108
+ sav: savDetails,
109
+ summary: {
110
+ totalBindus: savDetails.statistics.total,
111
+ averagePerHouse: savDetails.statistics.average,
112
+ strongestHouse: savDetails.statistics.strongestHouse,
113
+ weakestHouse: savDetails.statistics.weakestHouse,
114
+ allValid: bavDetails.validation.valid && savDetails.validation.valid
115
+ }
116
+ };
117
+ }
118
+
119
+ module.exports = {
120
+ // Main API
121
+ calculateAshtakavarga,
122
+ calculateDetailedAshtakavarga,
123
+
124
+ // BAV functions
125
+ calculateBAV,
126
+ calculateAllBAV,
127
+ validateBAV,
128
+ interpretPlanetaryHouseStrength,
129
+ calculateDetailedBAV,
130
+
131
+ // SAV functions
132
+ calculateSAV,
133
+ validateSAV,
134
+ interpretHouseStrength,
135
+ getStrengthCategory,
136
+ calculateDetailedSAV,
137
+ getHousesByStrength,
138
+ analyzeTransitFavorability,
139
+
140
+ // Kakshya functions
141
+ getKakshya,
142
+ getAllKakshyasInSign,
143
+ analyzeKakshyaTransit,
144
+ getSignTransitKakshyas,
145
+
146
+ // Utilities
147
+ getHouseNumber,
148
+
149
+ // Constants
150
+ CONTRIBUTIONS,
151
+ PLANET_TOTALS,
152
+ TOTAL_BINDUS,
153
+ PLANET_NAMES,
154
+ REFERENCE_POINTS,
155
+ KAKSHYA_RULERS,
156
+ KAKSHYA_SIZE,
157
+ NUM_KAKSHYAS
158
+ };