updates to pyswiss aspect & aspect application data served over API, incl. seminal invocation of Space parades & Time stellia
This commit is contained in:
@@ -21,10 +21,14 @@ SIGN_ELEMENT = {
|
||||
|
||||
ASPECTS = [
|
||||
('Conjunction', 0, 8.0),
|
||||
('Semisextile', 30, 4.0),
|
||||
('Sextile', 60, 6.0),
|
||||
('Square', 90, 8.0),
|
||||
('Trine', 120, 8.0),
|
||||
('Quincunx', 150, 5.0),
|
||||
('Opposition', 180, 10.0),
|
||||
# ('Semisquare', 45, 4.0),
|
||||
# ('Sesquiquadrate', 135, 4.0),
|
||||
]
|
||||
|
||||
PLANET_CODES = {
|
||||
@@ -67,6 +71,7 @@ def get_planet_positions(jd):
|
||||
planets[name] = {
|
||||
'sign': get_sign(degree),
|
||||
'degree': degree,
|
||||
'speed': pos[3],
|
||||
'retrograde': pos[3] < 0,
|
||||
}
|
||||
return planets
|
||||
@@ -74,30 +79,69 @@ def get_planet_positions(jd):
|
||||
|
||||
def get_element_counts(planets):
|
||||
sign_counts = {s: 0 for s in SIGNS}
|
||||
counts = {'Fire': 0, 'Water': 0, 'Earth': 0, 'Air': 0}
|
||||
sign_planets = {s: [] for s in SIGNS}
|
||||
classic = {'Fire': [], 'Water': [], 'Earth': [], 'Air': []}
|
||||
|
||||
for data in planets.values():
|
||||
for name, data in planets.items():
|
||||
sign = data['sign']
|
||||
counts[SIGN_ELEMENT[sign]] += 1
|
||||
el = SIGN_ELEMENT[sign]
|
||||
classic[el].append({'planet': name, 'sign': sign})
|
||||
sign_counts[sign] += 1
|
||||
sign_planets[sign].append({'planet': name, 'sign': sign})
|
||||
|
||||
# Time: highest planet concentration in a single sign, minus 1
|
||||
counts['Time'] = max(sign_counts.values()) - 1
|
||||
result = {
|
||||
el: {'count': len(contribs), 'contributors': contribs}
|
||||
for el, contribs in classic.items()
|
||||
}
|
||||
|
||||
# Space: longest consecutive run of occupied signs (circular), minus 1
|
||||
indices = [i for i, s in enumerate(SIGNS) if sign_counts[s] > 0]
|
||||
# Time: stellium — highest concentration in one sign, bonus = size - 1.
|
||||
# Collect all signs tied at the maximum.
|
||||
max_in_sign = max(sign_counts.values())
|
||||
stellia = [
|
||||
{'sign': s, 'planets': sign_planets[s]}
|
||||
for s in SIGNS
|
||||
if sign_counts[s] == max_in_sign and max_in_sign > 1
|
||||
]
|
||||
result['Time'] = {
|
||||
'count': max_in_sign - 1,
|
||||
'stellia': stellia,
|
||||
}
|
||||
|
||||
# Space: parade — longest consecutive run of occupied signs (circular),
|
||||
# bonus = run length - 1. Collect all runs tied at the maximum.
|
||||
index_set = {i for i, s in enumerate(SIGNS) if sign_counts[s] > 0}
|
||||
indices = sorted(index_set)
|
||||
max_seq = 0
|
||||
for start in range(len(indices)):
|
||||
seq_len = 1
|
||||
for offset in range(1, len(indices)):
|
||||
if (indices[start] + offset) % len(SIGNS) in indices:
|
||||
if (indices[start] + offset) % len(SIGNS) in index_set:
|
||||
seq_len += 1
|
||||
else:
|
||||
break
|
||||
max_seq = max(max_seq, seq_len)
|
||||
counts['Space'] = max_seq - 1
|
||||
|
||||
return counts
|
||||
parades = []
|
||||
for start in range(len(indices)):
|
||||
run = []
|
||||
for offset in range(max_seq):
|
||||
idx = (indices[start] + offset) % len(SIGNS)
|
||||
if idx not in index_set:
|
||||
break
|
||||
run.append(idx)
|
||||
else:
|
||||
sign_run = [SIGNS[i] for i in run]
|
||||
parade_planets = [
|
||||
p for s in sign_run for p in sign_planets[s]
|
||||
]
|
||||
parades.append({'signs': sign_run, 'planets': parade_planets})
|
||||
|
||||
result['Space'] = {
|
||||
'count': max_seq - 1,
|
||||
'parades': parades,
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def calculate_aspects(planets):
|
||||
@@ -119,12 +163,16 @@ def calculate_aspects(planets):
|
||||
for aspect_name, target, max_orb in ASPECTS:
|
||||
orb = abs(angle - target)
|
||||
if orb <= max_orb:
|
||||
s1 = abs(planets[name1].get('speed', 0))
|
||||
s2 = abs(planets[name2].get('speed', 0))
|
||||
applying = name1 if s1 >= s2 else name2
|
||||
aspects.append({
|
||||
'planet1': name1,
|
||||
'planet2': name2,
|
||||
'type': aspect_name,
|
||||
'angle': round(angle, 2),
|
||||
'orb': round(orb, 2),
|
||||
'applying_planet': applying,
|
||||
})
|
||||
break
|
||||
return aspects
|
||||
|
||||
Reference in New Issue
Block a user