#![no_std]
extern crate alloc;
use alloc::string::String;
use swiss_eph; use alloc::vec::Vec;
use alloc::boxed::Box;
use alloc::vec;
use wasm_bindgen::prelude::*;
use serde::{Deserialize, Serialize};
pub(crate) use swiss_eph as swe_bindings;
pub use vedic::vargas::{VargaType, VargaConfig, VargaPosition, D2Variation, D3Variation, D9Variation, D10Variation};
pub use vedic::shadbala::{ShadbalaResult, ShadbalaProfile};
pub use vedic::jaimini::{KarakaObject, KarakaName, JaiminiProfile, CharaDashaPeriod};
pub use vedic::ashtakavarga::{AshtakavargaResult, Sarvashtakavarga, ReducedAshtakavarga, PrastaraResult};
pub use vedic::special_lagnas::SpecialLagnas;
pub mod astronomy;
pub mod vedic;
pub mod geo;
pub mod muhurat;
pub mod constants;
#[wasm_bindgen]
pub fn get_version() -> String {
String::from(env!("CARGO_PKG_VERSION"))
}
#[wasm_bindgen]
pub fn get_swisseph_version() -> String {
let mut buf = [0i8; 256];
unsafe {
swe_bindings::swe_version(buf.as_mut_ptr());
}
let c_str = unsafe { core::ffi::CStr::from_ptr(buf.as_ptr()) };
String::from(c_str.to_str().unwrap_or("Unknown"))
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[wasm_bindgen]
pub struct Location {
pub latitude: f64,
pub longitude: f64,
pub altitude: f64,
}
#[wasm_bindgen]
impl Location {
#[wasm_bindgen(constructor)]
pub fn new(latitude: f64, longitude: f64, altitude: f64) -> Self {
Self { latitude, longitude, altitude }
}
}
#[wasm_bindgen]
pub fn calculate_sunrise(year: i32, month: u32, day: u32, location: &Location) -> f64 {
geo::sunrise_sunset::calculate_sunrise(year, month, day, location.latitude, location.longitude, location.altitude)
}
#[wasm_bindgen]
pub fn calculate_sunset(year: i32, month: u32, day: u32, location: &Location) -> f64 {
geo::sunrise_sunset::calculate_sunset(year, month, day, location.latitude, location.longitude, location.altitude)
}
pub use astronomy::planets::PlanetData;
#[wasm_bindgen]
pub fn calculate_houses(
jd: f64,
lat: f64,
lon: f64,
hsys: char,
ayan_mode: i32
) -> Result<astronomy::houses::HouseInfo, JsValue> {
let mode = if ayan_mode < 0 {
None
} else {
Some(astronomy::ayanamsha::AyanamshaMode::from_i32(ayan_mode))
};
astronomy::houses::calculate_houses(jd, lat, lon, hsys, mode)
}
#[wasm_bindgen]
pub fn calculate_planets(jd: f64, ayan_mode: i32) -> Result<JsValue, JsValue> {
let mode = astronomy::ayanamsha::AyanamshaMode::from_i32(ayan_mode);
let ayan_val = astronomy::ayanamsha::get_ayanamsha(mode, jd);
let planets = astronomy::planets::get_planet_positions_bulk(jd, ayan_val);
Ok(serde_wasm_bindgen::to_value(&planets)?)
}
#[wasm_bindgen]
pub fn calculate_vimshottari(moon_long: f64, birth_time_ms: f64, current_time_ms: f64) -> vedic::dasha::DashaInfo {
vedic::dasha::calculate_vimshottari(moon_long, birth_time_ms, current_time_ms)
}
#[wasm_bindgen]
pub fn calculate_yogini(moon_long: f64, birth_time_ms: f64, current_time_ms: f64) -> vedic::dasha::YoginiInfo {
vedic::dasha::calculate_yogini(moon_long, birth_time_ms, current_time_ms)
}
#[wasm_bindgen]
pub fn calculate_varga(long: f64, varga_val: i32, config: JsValue) -> Result<VargaPosition, JsValue> {
let v_type = match varga_val {
1 => VargaType::D1,
2 => VargaType::D2,
3 => VargaType::D3,
4 => VargaType::D4,
7 => VargaType::D7,
9 => VargaType::D9,
10 => VargaType::D10,
12 => VargaType::D12,
16 => VargaType::D16,
20 => VargaType::D20,
24 => VargaType::D24,
27 => VargaType::D27,
30 => VargaType::D30,
40 => VargaType::D40,
45 => VargaType::D45,
60 => VargaType::D60,
_ => return Err(JsValue::from_str("Invalid Varga ID")),
};
let default_conf = VargaConfig::new();
let conf: VargaConfig = if config.is_undefined() || config.is_null() {
default_conf
} else {
#[derive(Deserialize)]
struct PartialConfig {
#[serde(default)]
d2_method: Option<i32>,
#[serde(default)]
d3_method: Option<i32>,
#[serde(default)]
d9_method: Option<i32>,
#[serde(default)]
d10_method: Option<i32>,
}
match serde_wasm_bindgen::from_value::<PartialConfig>(config) {
Ok(p) => VargaConfig {
d2_method: p.d2_method.unwrap_or(default_conf.d2_method),
d3_method: p.d3_method.unwrap_or(default_conf.d3_method),
d9_method: p.d9_method.unwrap_or(default_conf.d9_method),
d10_method: p.d10_method.unwrap_or(default_conf.d10_method),
},
Err(e) => return Err(JsValue::from_str(&alloc::format!("Invalid config object: {}", e))),
}
};
Ok(vedic::vargas::calculate_varga_position(long, v_type, &conf))
}
#[wasm_bindgen]
pub fn calculate_planet_strength(
long: f64,
planet_id: i32,
jd: f64,
ascendant: f64
) -> ShadbalaResult {
vedic::shadbala::calculate_planet_shadbala(long, planet_id, jd, ascendant)
}
#[wasm_bindgen]
pub fn calculate_full_shadbala(
planet_longs: &JsValue,
jd: f64,
ascendant: f64
) -> Result<ShadbalaProfile, JsValue> {
let data: Vec<vedic::shadbala::PlanetInput> = serde_wasm_bindgen::from_value(planet_longs.clone())?;
Ok(vedic::shadbala::calculate_shadbala_profile(&data, jd, ascendant))
}
#[wasm_bindgen]
pub fn calculate_jaimini_karakas(
planet_longs: &JsValue, use_8_karakas: bool
) -> Result<Box<[KarakaObject]>, JsValue> {
let data: Vec<(i32, f64)> = serde_wasm_bindgen::from_value(planet_longs.clone())?;
let karakas = vedic::jaimini::calculate_charakarakas(&data, use_8_karakas);
Ok(karakas.into_boxed_slice())
}
#[wasm_bindgen]
pub fn calculate_chara_dasha_periods(
planet_longs: &JsValue,
ascendant_sign: i32,
start_year: f64
) -> Result<Box<[CharaDashaPeriod]>, JsValue> {
let data: Vec<(i32, f64)> = serde_wasm_bindgen::from_value(planet_longs.clone())?;
let periods = vedic::jaimini::calculate_chara_dasha(&data, ascendant_sign as usize, start_year);
Ok(periods.into_boxed_slice())
}
#[wasm_bindgen]
pub fn calculate_ashtakavarga(
planet_longs: &JsValue, ascendant: f64
) -> Result<Sarvashtakavarga, JsValue> {
let data: Vec<vedic::shadbala::PlanetInput> = serde_wasm_bindgen::from_value(planet_longs.clone())?;
let mut longs = vec![0.0; 7];
for p in data {
if p.id >= 0 && p.id <= 6 {
longs[p.id as usize] = p.longitude;
}
}
Ok(vedic::ashtakavarga::calculate_sarvashtakavarga(&longs, ascendant))
}
#[wasm_bindgen]
pub fn calculate_reduced_ashtakavarga(
bindus: &JsValue, planet_longs: &JsValue ) -> Result<ReducedAshtakavarga, JsValue> {
let bindus_vec: Vec<i32> = serde_wasm_bindgen::from_value(bindus.clone())?;
if bindus_vec.len() != 12 {
return Err(JsValue::from_str("Bindus array must have 12 elements."));
}
let data: Vec<(i32, f64)> = serde_wasm_bindgen::from_value(planet_longs.clone())?;
Ok(vedic::ashtakavarga::calculate_reductions(&bindus_vec, &data))
}
#[wasm_bindgen]
pub fn calculate_prastara_ashtakavarga(
planet_id: i32,
planet_longs: &JsValue,
ascendant: f64
) -> Result<PrastaraResult, JsValue> {
let data: Vec<vedic::shadbala::PlanetInput> = serde_wasm_bindgen::from_value(planet_longs.clone())?;
let mut longs = vec![0.0; 7];
for p in data {
if p.id >= 0 && p.id <= 6 {
longs[p.id as usize] = p.longitude;
}
}
Ok(vedic::ashtakavarga::calculate_prastara_av(planet_id, &longs, ascendant))
}
#[wasm_bindgen]
pub fn calculate_special_lagnas(
birth_jd: f64,
sunrise_jd: f64,
sunrise_sun_long: f64,
lagna_long: f64,
moon_long: f64
) -> SpecialLagnas {
vedic::special_lagnas::calculate_special_lagnas(birth_jd, sunrise_jd, sunrise_sun_long, lagna_long, moon_long)
}
pub use vedic::yogas::YogaResult;
#[wasm_bindgen]
pub fn find_active_yogas(
planet_longs: &JsValue,
ascendant: f64
) -> Result<Box<[YogaResult]>, JsValue> {
let data: Vec<vedic::shadbala::PlanetInput> = serde_wasm_bindgen::from_value(planet_longs.clone())?;
let yogas = vedic::yogas::check_yogas(&data, ascendant);
Ok(yogas.into_boxed_slice())
}
#[wasm_bindgen]
pub fn p_julday(year: i32, month: i32, day: i32, hour: f64, gregflag: i32) -> f64 {
unsafe {
swe_bindings::swe_julday(year, month, day, hour, gregflag)
}
}
#[derive(Serialize)]
pub struct PlanetaryPosition {
pub longitude: f64,
pub latitude: f64,
pub distance: f64,
pub speed_long: f64,
pub speed_lat: f64,
pub speed_dist: f64,
}
#[wasm_bindgen]
pub fn p_calc_ut(tjd_ut: f64, ipl: i32, iflag: i32) -> Result<JsValue, JsValue> {
let mut xx = [0.0; 6];
let mut serr = [0i8; 256];
unsafe {
let ret_flag = swe_bindings::swe_calc_ut(tjd_ut, ipl, iflag, xx.as_mut_ptr(), serr.as_mut_ptr());
if ret_flag < 0 {
let c_str = core::ffi::CStr::from_ptr(serr.as_ptr());
return Err(JsValue::from_str(c_str.to_str().unwrap_or("Unknown error")));
}
}
let result = PlanetaryPosition {
longitude: xx[0],
latitude: xx[1],
distance: xx[2],
speed_long: xx[3],
speed_lat: xx[4],
speed_dist: xx[5],
};
Ok(serde_wasm_bindgen::to_value(&result)?)
}