use wasm_bindgen::prelude::*;
use serde::{Serialize, Deserialize};
use alloc::vec::Vec;
use alloc::vec;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[wasm_bindgen]
pub struct AshtakavargaResult {
pub planet_id: i32,
#[wasm_bindgen(skip)]
pub bindus: Vec<i32>
}
#[wasm_bindgen]
impl AshtakavargaResult {
#[wasm_bindgen(getter)]
pub fn bindus(&self) -> Vec<i32> {
self.bindus.clone()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[wasm_bindgen]
pub struct Sarvashtakavarga {
#[wasm_bindgen(skip)]
pub totals: Vec<i32>
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[wasm_bindgen]
pub struct ReducedAshtakavarga {
#[wasm_bindgen(skip)]
pub reduced_bindus: Vec<i32>,
pub shodaya_pinda: i32,
}
#[wasm_bindgen]
impl ReducedAshtakavarga {
#[wasm_bindgen(getter)]
pub fn reduced_bindus(&self) -> Vec<i32> {
self.reduced_bindus.clone()
}
}
#[wasm_bindgen]
impl Sarvashtakavarga {
#[wasm_bindgen(getter)]
pub fn totals(&self) -> Vec<i32> {
self.totals.clone()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[wasm_bindgen]
pub struct PrastaraResult {
pub planet_id: i32,
#[wasm_bindgen(skip)]
pub grid: Vec<u8>,
}
#[wasm_bindgen]
impl PrastaraResult {
#[wasm_bindgen(getter)]
pub fn grid(&self) -> Vec<u8> {
self.grid.clone()
}
}
fn get_sign(long: f64) -> usize {
(long / 30.0).floor() as usize % 12
}
const SUN_FROM_SUN: &[i32] = &[1, 2, 4, 7, 8, 9, 10, 11];
const SUN_FROM_MOON: &[i32] = &[3, 6, 10, 11];
const SUN_FROM_MARS: &[i32] = &[1, 2, 4, 7, 8, 9, 10, 11];
const SUN_FROM_MERCURY: &[i32] = &[3, 5, 6, 9, 10, 11, 12];
const SUN_FROM_JUPITER: &[i32] = &[5, 6, 9, 11];
const SUN_FROM_VENUS: &[i32] = &[6, 7, 12];
const SUN_FROM_SATURN: &[i32] = &[1, 2, 4, 7, 8, 9, 10, 11];
const SUN_FROM_ASC: &[i32] = &[3, 4, 6, 10, 11, 12];
const MOON_FROM_SUN: &[i32] = &[3, 6, 7, 8, 10, 11];
const MOON_FROM_MOON: &[i32] = &[1, 3, 6, 7, 10, 11];
const MOON_FROM_MARS: &[i32] = &[2, 3, 5, 6, 9, 10, 11];
const MOON_FROM_MERCURY: &[i32] = &[1, 3, 4, 5, 7, 8, 10, 11];
const MOON_FROM_JUPITER: &[i32] = &[1, 4, 7, 8, 10, 11, 12];
const MOON_FROM_VENUS: &[i32] = &[3, 4, 5, 7, 9, 10, 11];
const MOON_FROM_SATURN: &[i32] = &[3, 5, 6, 11]; const MOON_FROM_ASC: &[i32] = &[3, 6, 10, 11];
const MARS_FROM_SUN: &[i32] = &[3, 5, 6, 10, 11];
const MARS_FROM_MOON: &[i32] = &[3, 6, 11];
const MARS_FROM_MARS: &[i32] = &[1, 2, 4, 7, 8, 10, 11];
const MARS_FROM_MERCURY: &[i32] = &[3, 5, 6, 11];
const MARS_FROM_JUPITER: &[i32] = &[6, 10, 11, 12];
const MARS_FROM_VENUS: &[i32] = &[6, 8, 11, 12];
const MARS_FROM_SATURN: &[i32] = &[1, 4, 7, 8, 9, 10, 11];
const MARS_FROM_ASC: &[i32] = &[1, 3, 6, 10, 11];
const MERC_FROM_SUN: &[i32] = &[5, 6, 9, 11, 12];
const MERC_FROM_MOON: &[i32] = &[2, 4, 6, 8, 10, 11];
const MERC_FROM_MARS: &[i32] = &[1, 2, 4, 7, 8, 9, 10, 11];
const MERC_FROM_MERCURY: &[i32] = &[1, 3, 5, 6, 9, 10, 11, 12];
const MERC_FROM_JUPITER: &[i32] = &[6, 8, 11, 12];
const MERC_FROM_VENUS: &[i32] = &[1, 2, 3, 4, 5, 8, 9, 11];
const MERC_FROM_SATURN: &[i32] = &[1, 2, 4, 7, 8, 9, 10, 11];
const MERC_FROM_ASC: &[i32] = &[1, 2, 4, 6, 8, 10, 11];
const JUP_FROM_SUN: &[i32] = &[1, 2, 3, 4, 7, 8, 9, 10, 11];
const JUP_FROM_MOON: &[i32] = &[2, 5, 7, 9, 11];
const JUP_FROM_MARS: &[i32] = &[1, 2, 4, 7, 8, 10, 11];
const JUP_FROM_MERCURY: &[i32] = &[1, 2, 4, 5, 6, 9, 10, 11];
const JUP_FROM_JUPITER: &[i32] = &[1, 2, 3, 4, 7, 8, 10, 11];
const JUP_FROM_VENUS: &[i32] = &[2, 5, 6, 9, 10, 11];
const JUP_FROM_SATURN: &[i32] = &[3, 5, 6, 12];
const JUP_FROM_ASC: &[i32] = &[1, 2, 4, 5, 6, 7, 9, 10, 11];
const VEN_FROM_SUN: &[i32] = &[8, 11, 12];
const VEN_FROM_MOON: &[i32] = &[1, 2, 3, 4, 5, 8, 9, 11, 12];
const VEN_FROM_MARS: &[i32] = &[3, 5, 6, 9, 11, 12]; const VEN_FROM_MERCURY: &[i32] = &[3, 5, 6, 9, 11];
const VEN_FROM_JUPITER: &[i32] = &[5, 8, 9, 10, 11];
const VEN_FROM_VENUS: &[i32] = &[1, 2, 3, 4, 5, 8, 9, 10, 11];
const VEN_FROM_SATURN: &[i32] = &[3, 4, 5, 8, 9, 10, 11];
const VEN_FROM_ASC: &[i32] = &[1, 2, 3, 4, 5, 8, 9, 11];
const SAT_FROM_SUN: &[i32] = &[1, 2, 4, 7, 8, 10, 11];
const SAT_FROM_MOON: &[i32] = &[3, 6, 11];
const SAT_FROM_MARS: &[i32] = &[3, 5, 6, 10, 11, 12];
const SAT_FROM_MERCURY: &[i32] = &[6, 8, 9, 10, 11, 12];
const SAT_FROM_JUPITER: &[i32] = &[5, 6, 11, 12];
const SAT_FROM_VENUS: &[i32] = &[6, 11, 12];
const SAT_FROM_SATURN: &[i32] = &[3, 5, 6, 11];
const SAT_FROM_ASC: &[i32] = &[1, 3, 4, 6, 10, 11];
fn get_points(target_planet: i32, reference_planet: i32) -> &'static [i32] {
match target_planet {
0 => match reference_planet { 0 => SUN_FROM_SUN,
1 => SUN_FROM_MOON,
2 => SUN_FROM_MARS,
3 => SUN_FROM_MERCURY,
4 => SUN_FROM_JUPITER,
5 => SUN_FROM_VENUS,
6 => SUN_FROM_SATURN,
7 => SUN_FROM_ASC,
_ => &[],
},
1 => match reference_planet { 0 => MOON_FROM_SUN,
1 => MOON_FROM_MOON,
2 => MOON_FROM_MARS,
3 => MOON_FROM_MERCURY,
4 => MOON_FROM_JUPITER,
5 => MOON_FROM_VENUS,
6 => MOON_FROM_SATURN,
7 => MOON_FROM_ASC,
_ => &[],
},
2 => match reference_planet { 0 => MARS_FROM_SUN,
1 => MARS_FROM_MOON,
2 => MARS_FROM_MARS,
3 => MARS_FROM_MERCURY,
4 => MARS_FROM_JUPITER,
5 => MARS_FROM_VENUS,
6 => MARS_FROM_SATURN,
7 => MARS_FROM_ASC,
_ => &[],
},
3 => match reference_planet { 0 => MERC_FROM_SUN,
1 => MERC_FROM_MOON,
2 => MERC_FROM_MARS,
3 => MERC_FROM_MERCURY,
4 => MERC_FROM_JUPITER,
5 => MERC_FROM_VENUS,
6 => MERC_FROM_SATURN,
7 => MERC_FROM_ASC,
_ => &[],
},
4 => match reference_planet { 0 => JUP_FROM_SUN,
1 => JUP_FROM_MOON,
2 => JUP_FROM_MARS,
3 => JUP_FROM_MERCURY,
4 => JUP_FROM_JUPITER,
5 => JUP_FROM_VENUS,
6 => JUP_FROM_SATURN,
7 => JUP_FROM_ASC,
_ => &[],
},
5 => match reference_planet { 0 => VEN_FROM_SUN,
1 => VEN_FROM_MOON,
2 => VEN_FROM_MARS,
3 => VEN_FROM_MERCURY,
4 => VEN_FROM_JUPITER,
5 => VEN_FROM_VENUS,
6 => VEN_FROM_SATURN,
7 => VEN_FROM_ASC,
_ => &[],
},
6 => match reference_planet { 0 => SAT_FROM_SUN,
1 => SAT_FROM_MOON,
2 => SAT_FROM_MARS,
3 => SAT_FROM_MERCURY,
4 => SAT_FROM_JUPITER,
5 => SAT_FROM_VENUS,
6 => SAT_FROM_SATURN,
7 => SAT_FROM_ASC,
_ => &[],
},
_ => &[]
}
}
pub fn calculate_binna_av(
target_planet_id: i32,
planet_positions: &[f64], ascendant: f64
) -> AshtakavargaResult {
let mut bindus = vec![0; 12];
for ref_id in 0..=7 {
let ref_long = if ref_id == 7 {
ascendant
} else {
planet_positions[ref_id as usize]
};
let ref_sign = get_sign(ref_long);
let points = get_points(target_planet_id, ref_id);
for &offset in points.iter() {
let target_sign = (ref_sign + (offset as usize) - 1) % 12;
bindus[target_sign] += 1;
}
}
AshtakavargaResult {
planet_id: target_planet_id,
bindus
}
}
pub fn calculate_prastara_av(
target_planet_id: i32,
planet_positions: &[f64],
ascendant: f64
) -> PrastaraResult {
let mut grid = vec![0u8; 96];
for ref_id in 0..=7 {
let ref_long = if ref_id == 7 {
ascendant
} else {
planet_positions[ref_id as usize]
};
let ref_sign = get_sign(ref_long);
let points = get_points(target_planet_id, ref_id);
for &offset in points.iter() {
let target_sign = (ref_sign + (offset as usize) - 1) % 12;
grid[(ref_id as usize) * 12 + target_sign] = 1;
}
}
PrastaraResult {
planet_id: target_planet_id,
grid
}
}
pub fn calculate_sarvashtakavarga(
planet_positions: &[f64], ascendant: f64
) -> Sarvashtakavarga {
let mut totals = vec![0; 12];
for planet_id in 0..7 {
let bav = calculate_binna_av(planet_id, planet_positions, ascendant);
for (i, total) in totals.iter_mut().enumerate().take(12) {
*total += bav.bindus[i];
}
}
Sarvashtakavarga { totals }
}
fn apply_trikona_reduction(bindus: &mut [i32; 12]) {
let trikonas = [
[0, 4, 8],
[1, 5, 9],
[2, 6, 10],
[3, 7, 11]
];
for group in trikonas.iter() {
let v0 = bindus[group[0]];
let v1 = bindus[group[1]];
let v2 = bindus[group[2]];
if v0 == 0 && v1 == 0 && v2 == 0 { continue; }
let zeros = (if v0 == 0 {1} else {0}) + (if v1 == 0 {1} else {0}) + (if v2 == 0 {1} else {0});
if zeros == 1 {
continue;
} else if zeros == 2 {
bindus[group[0]] = 0;
bindus[group[1]] = 0;
bindus[group[2]] = 0;
} else {
let min = v0.min(v1).min(v2);
bindus[group[0]] -= min;
bindus[group[1]] -= min;
bindus[group[2]] -= min;
}
}
}
fn apply_ekadhipatya_reduction(bindus: &mut [i32; 12], planets_in_sign: &[Vec<i32>]) {
let pairs = [
(0, 7), (1, 6), (2, 5), (8, 11), (9, 10) ];
for &(s1, s2) in pairs.iter() {
let v1 = bindus[s1];
let v2 = bindus[s2];
let occ1 = !planets_in_sign[s1].is_empty();
let occ2 = !planets_in_sign[s2].is_empty();
if !occ1 && !occ2 {
if v1 == v2 {
bindus[s1] = 0;
bindus[s2] = 0;
} else {
if v1 > v2 { bindus[s1] = v2; }
else { bindus[s2] = v1; }
}
} else if occ1 && !occ2 {
bindus[s2] = 0;
} else if !occ1 && occ2 {
bindus[s1] = 0;
} else {
}
}
}
pub fn calculate_reductions(
bindus: &[i32], planets: &[(i32, f64)] ) -> ReducedAshtakavarga {
let mut reduced = [0; 12];
for i in 0..12 {
if i < bindus.len() { reduced[i] = bindus[i]; }
}
let mut occupancy: Vec<Vec<i32>> = vec![vec![]; 12];
for &(pid, long) in planets.iter() {
if pid > 8 { continue; } if !(0..=6).contains(&pid) { continue; }
let sign = (long / 30.0).floor() as usize % 12;
occupancy[sign].push(pid);
}
apply_trikona_reduction(&mut reduced);
apply_ekadhipatya_reduction(&mut reduced, &occupancy);
let rasi_multipliers = [7, 10, 8, 4, 10, 5, 7, 8, 9, 5, 11, 12];
let mut rasi_pinda = 0;
for i in 0..12 {
rasi_pinda += reduced[i] * rasi_multipliers[i];
}
let multipliers = [5, 5, 8, 5, 10, 7, 5];
let mut graha_pinda = 0;
for &(pid, long) in planets.iter() {
if (0..=6).contains(&pid) {
let sign = (long / 30.0).floor() as usize % 12;
graha_pinda += reduced[sign] * multipliers[pid as usize];
}
}
ReducedAshtakavarga {
reduced_bindus: reduced.to_vec(),
shodaya_pinda: rasi_pinda + graha_pinda
}
}