use wasm_bindgen::prelude::*;
use serde::{Serialize, Deserialize};
use alloc::vec::Vec;
use alloc::vec;
use alloc::string::String;
use crate::vedic::shadbala::PlanetInput;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[wasm_bindgen]
pub struct YogaResult {
#[wasm_bindgen(skip)]
pub name: String,
#[wasm_bindgen(skip)]
pub description: String,
}
#[wasm_bindgen]
impl YogaResult {
#[wasm_bindgen(constructor)]
pub fn new(name: String, description: String) -> Self {
Self { name, description }
}
#[wasm_bindgen(getter)]
pub fn name(&self) -> String {
self.name.clone()
}
#[wasm_bindgen(getter)]
pub fn description(&self) -> String {
self.description.clone()
}
}
fn get_sign(long: f64) -> usize {
(long / 30.0).floor() as usize % 12
}
fn get_house(asc_sign: usize, planet_sign: usize) -> usize {
let diff = (planet_sign as i32 - asc_sign as i32).rem_euclid(12);
(diff + 1) as usize
}
fn get_lord(sign: usize) -> i32 {
match sign {
0 | 7 => 2, 1 | 6 => 5, 2 | 5 => 3, 3 => 1, 4 => 0, 8 | 11 => 4, 9 | 10 => 6, _ => -1,
}
}
fn is_exalted(planet_id: i32, sign: usize) -> bool {
match planet_id {
0 => sign == 0, 1 => sign == 1, 2 => sign == 9, 3 => sign == 5, 4 => sign == 3, 5 => sign == 11, 6 => sign == 6, _ => false,
}
}
fn is_own_sign(planet_id: i32, sign: usize) -> bool {
get_lord(sign) == planet_id
}
pub fn check_yogas(
planets: &[PlanetInput], ascendant: f64
) -> Vec<YogaResult> {
let mut yogas = Vec::new();
let mut p_longs = [0.0; 7];
let mut p_signs = [0; 7];
let mut p_houses = [0; 7];
for p in planets {
if p.id >= 0 && p.id <= 6 {
p_longs[p.id as usize] = p.longitude;
}
}
let asc_sign = get_sign(ascendant);
for i in 0..7 {
p_signs[i] = get_sign(p_longs[i]);
p_houses[i] = get_house(asc_sign, p_signs[i]);
}
if (is_exalted(2, p_signs[2]) || is_own_sign(2, p_signs[2])) && [1, 4, 7, 10].contains(&p_houses[2]) {
yogas.push(YogaResult::new("Ruchaka Yoga".into(), "Mars in Own/Exalted sign in Kendra.".into()));
}
if (is_exalted(3, p_signs[3]) || is_own_sign(3, p_signs[3])) && [1, 4, 7, 10].contains(&p_houses[3]) {
yogas.push(YogaResult::new("Bhadra Yoga".into(), "Mercury in Own/Exalted sign in Kendra.".into()));
}
if (is_exalted(4, p_signs[4]) || is_own_sign(4, p_signs[4])) && [1, 4, 7, 10].contains(&p_houses[4]) {
yogas.push(YogaResult::new("Hamsa Yoga".into(), "Jupiter in Own/Exalted sign in Kendra.".into()));
}
if (is_exalted(5, p_signs[5]) || is_own_sign(5, p_signs[5])) && [1, 4, 7, 10].contains(&p_houses[5]) {
yogas.push(YogaResult::new("Malavya Yoga".into(), "Venus in Own/Exalted sign in Kendra.".into()));
}
if (is_exalted(6, p_signs[6]) || is_own_sign(6, p_signs[6])) && [1, 4, 7, 10].contains(&p_houses[6]) {
yogas.push(YogaResult::new("Sasa Yoga".into(), "Saturn in Own/Exalted sign in Kendra.".into()));
}
let jup_from_moon = get_house(p_signs[1], p_signs[4]); if [1, 4, 7, 10].contains(&jup_from_moon) {
yogas.push(YogaResult::new("Gaja Kesari Yoga".into(), "Jupiter in Kendra from Moon.".into()));
}
if p_signs[0] == p_signs[3] {
yogas.push(YogaResult::new("Budhaditya Yoga".into(), "Sun and Mercury conjunction.".into()));
}
if p_signs[1] == p_signs[2] {
yogas.push(YogaResult::new("Chandra Mangala Yoga".into(), "Moon and Mars conjunction.".into()));
}
let benefics = [3, 4, 5];
for &b in &benefics {
if p_houses[b] == 10 {
yogas.push(YogaResult::new("Amala Yoga".into(), "Benefic in 10th house from Ascendant.".into()));
break; }
let b_from_moon = get_house(p_signs[1], p_signs[b]);
if b_from_moon == 10 {
yogas.push(YogaResult::new("Amala Yoga".into(), "Benefic in 10th house from Moon.".into()));
break;
}
}
let trik_houses = [6, 8, 12];
let sign_6 = (asc_sign + 5) % 12;
let sign_8 = (asc_sign + 7) % 12;
let sign_12 = (asc_sign + 11) % 12;
let lord_6 = get_lord(sign_6);
let lord_8 = get_lord(sign_8);
let lord_12 = get_lord(sign_12);
let check_placement = |planet_id: i32| -> bool {
if planet_id < 0 { return false; }
let h = p_houses[planet_id as usize];
trik_houses.contains(&(h as i32))
};
if check_placement(lord_6) && check_placement(lord_8) && check_placement(lord_12) {
let l6_ok = check_placement(lord_6);
let l8_ok = check_placement(lord_8);
let l12_ok = check_placement(lord_12);
if l6_ok || l8_ok || l12_ok {
yogas.push(YogaResult::new("Vipareeta Raja Yoga".into(), "Lord of 6/8/12 in 6/8/12.".into()));
}
}
yogas
}