cjo93 commited on
Commit
03f0588
·
verified ·
1 Parent(s): 37bd413

Create app/engine.py

Browse files
Files changed (1) hide show
  1. app/engine.py +114 -0
app/engine.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import swisseph as swe
2
+ import math
3
+ import datetime
4
+ import os
5
+ from .models import GeoLocation, PlanetPosition, HexagramAddress, CognitiveProfile
6
+
7
+ # CONSTANTS
8
+ ARC_GATE = 5.625
9
+ ARC_LINE = 0.9375
10
+ ARC_COLOR = 0.15625
11
+ ARC_TONE = 0.02604166
12
+ ARC_BASE = 0.00520833
13
+
14
+ class PrecisionEngine:
15
+ def __init__(self):
16
+ # Point to the data files we downloaded in Dockerfile
17
+ ephe_path = os.getenv("SE_EPHE_PATH", "/app/ephe")
18
+ swe.set_ephe_path(ephe_path)
19
+
20
+ def _get_julian_day(self, dt: datetime.datetime) -> float:
21
+ # Calculate UT (Universal Time) Julian Day
22
+ return swe.julday(dt.year, dt.month, dt.day, dt.hour + dt.minute/60.0 + dt.second/3600.0)
23
+
24
+ def _calculate_solar_arc_regression(self, natal_jd: float) -> float:
25
+ """
26
+ Solves for the exact moment the Sun was 88 degrees behind natal position.
27
+ """
28
+ # 1. Get Natal Sun Longitude
29
+ res = swe.calc_ut(natal_jd, swe.SUN)
30
+ natal_sun_long = res[0][0]
31
+
32
+ target_long = (natal_sun_long - 88.0) % 360.0
33
+
34
+ # 2. Estimate 88 days back
35
+ current_jd = natal_jd - 88.0
36
+
37
+ # 3. Newton-Raphson Iteration to zero in
38
+ for _ in range(5):
39
+ res = swe.calc_ut(current_jd, swe.SUN)
40
+ current_long = res[0][0]
41
+
42
+ delta = target_long - current_long
43
+ if delta > 180: delta -= 360
44
+ if delta < -180: delta += 360
45
+
46
+ if abs(delta) < 0.00001:
47
+ break
48
+
49
+ current_jd += delta
50
+
51
+ return current_jd
52
+
53
+ def _decode_fractal(self, longitude: float) -> HexagramAddress:
54
+ l = longitude % 360
55
+ gate = math.floor(l / ARC_GATE) % 64 + 1
56
+ rem_g = l % ARC_GATE
57
+ line = math.floor(rem_g / ARC_LINE) + 1
58
+ rem_l = rem_g % ARC_LINE
59
+ color = math.floor(rem_l / ARC_COLOR) + 1
60
+ rem_c = rem_l % ARC_COLOR
61
+ tone = math.floor(rem_c / ARC_TONE) + 1
62
+ rem_t = rem_c % ARC_TONE
63
+ base = math.floor(rem_t / ARC_BASE) + 1
64
+
65
+ return HexagramAddress(gate=gate, line=line, color=color, tone=tone, base=base)
66
+
67
+ def calculate_chart(self, dt: datetime.datetime, loc: GeoLocation, mode: str = "Personality") -> dict:
68
+ jd_utc = self._get_julian_day(dt)
69
+
70
+ if mode == "Design":
71
+ jd_utc = self._calculate_solar_arc_regression(jd_utc)
72
+
73
+ # Set Topocentric Observer
74
+ swe.set_topo(loc.longitude, loc.latitude, loc.altitude)
75
+
76
+ planets = {}
77
+ bodies = {
78
+ "Sun": swe.SUN, "Moon": swe.MOON, "Mercury": swe.MERCURY,
79
+ "Venus": swe.VENUS, "Mars": swe.MARS, "Jupiter": swe.JUPITER,
80
+ "Saturn": swe.SATURN, "Uranus": swe.URANUS, "Neptune": swe.NEPTUNE,
81
+ "Pluto": swe.PLUTO, "North Node": swe.MEAN_NODE
82
+ }
83
+
84
+ for name, pid in bodies.items():
85
+ flags = swe.FLG_TOPOCTR | swe.FLG_SPEED | swe.FLG_SWIEPH
86
+ res = swe.calc_ut(jd_utc, pid, flags)
87
+
88
+ planets[name] = PlanetPosition(
89
+ name=name,
90
+ longitude=res[0][0],
91
+ latitude=res[0][1],
92
+ speed=res[0][3],
93
+ house=1,
94
+ is_retrograde=res[0][3] < 0
95
+ )
96
+
97
+ return planets
98
+
99
+ def analyze_cognitive(self, p_sun_long, p_node_long, d_sun_long, d_node_long) -> CognitiveProfile:
100
+ d_sun = self._decode_fractal(d_sun_long)
101
+ d_node = self._decode_fractal(d_node_long)
102
+ p_sun = self._decode_fractal(p_sun_long)
103
+ p_node = self._decode_fractal(p_node_long)
104
+
105
+ colors = {1: "Fear", 2: "Hope", 3: "Desire", 4: "Need", 5: "Guilt", 6: "Innocence"}
106
+
107
+ return CognitiveProfile(
108
+ digestion=colors.get(d_sun.color, "Unknown"),
109
+ environment=f"Color {d_node.color}",
110
+ perspective=f"Color {p_node.color}",
111
+ motivation=colors.get(p_sun.color, "Unknown"),
112
+ orientation_body="Left" if d_sun.tone <= 3 else "Right",
113
+ orientation_mind="Left" if p_sun.tone <= 3 else "Right"
114
+ )