use wasm_bindgen::prelude::*;
use serde::{Serialize, Deserialize};
use alloc::string::ToString;
use crate::astronomy::planets::{sun_longitude, moon_longitude};
use crate::astronomy::solver::find_angle_crossing;
pub const FIXED_KARANAS: [&str; 4] = ["Shakuni", "Chatushpada", "Naga", "Kimstughna"];
pub const CYCLING_KARANAS: [&str; 7] = [
"Bava", "Balava", "Kaulava", "Taitila", "Gara", "Vanija", "Vishti"
];
#[derive(Debug, Clone, Serialize, Deserialize)]
#[wasm_bindgen(getter_with_clone)]
pub struct KaranaInfo {
pub index: u8,
pub name: alloc::string::String,
pub half: u8,
}
#[wasm_bindgen]
pub fn calculate_karana(jd: f64) -> KaranaInfo {
let sun_long = sun_longitude(jd);
let moon_long = moon_longitude(jd);
let mut diff = moon_long - sun_long;
if diff < 0.0 {
diff += 360.0;
}
let karana_index = (diff / 6.0).floor() as u8 + 1;
let half = if (karana_index % 2) == 1 { 1 } else { 2 };
let name = match karana_index {
1 => FIXED_KARANAS[3].to_string(), 58 => FIXED_KARANAS[0].to_string(), 59 => FIXED_KARANAS[1].to_string(), 60 => FIXED_KARANAS[2].to_string(), n => {
let cycle_idx = ((n - 2) % 7) as usize;
CYCLING_KARANAS[cycle_idx].to_string()
}
};
KaranaInfo {
index: karana_index,
name,
half,
}
}
#[wasm_bindgen]
pub fn karana_end_time(jd: f64) -> f64 {
let current = calculate_karana(jd);
let target_angle = current.index as f64 * 6.0;
let start_search = jd;
let end_search = jd + 0.6;
find_angle_crossing(
|t| {
let sl = sun_longitude(t);
let ml = moon_longitude(t);
let mut diff = ml - sl;
if diff < 0.0 { diff += 360.0; }
diff
},
start_search,
end_search,
target_angle
).unwrap_or(jd)
}
#[wasm_bindgen]
pub fn karana_start_time(jd: f64) -> f64 {
let current = calculate_karana(jd);
let target_angle = (current.index as f64 - 1.0) * 6.0;
let start_search = jd - 0.6;
let end_search = jd;
find_angle_crossing(
|t| {
let sl = sun_longitude(t);
let ml = moon_longitude(t);
let mut diff = ml - sl;
if diff < 0.0 { diff += 360.0; }
diff
},
start_search,
end_search,
target_angle
).unwrap_or(jd)
}