use wasm_bindgen::prelude::*;
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[wasm_bindgen]
pub enum VargaType {
D1 = 1,
D2 = 2,
D3 = 3,
D4 = 4,
D7 = 7,
D9 = 9,
D10 = 10,
D12 = 12,
D16 = 16,
D20 = 20,
D24 = 24,
D27 = 27,
D30 = 30,
D40 = 40,
D45 = 45,
D60 = 60,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[wasm_bindgen]
pub enum D2Variation {
Parashara = 0,
LabhaMandooka = 1,
Kura = 2,
Kashinatha = 3,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[wasm_bindgen]
pub enum D3Variation {
Parashara = 0,
Jagannatha = 1, Somanatha = 2,
Parivritti = 3,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[wasm_bindgen]
pub enum D9Variation {
Parashara = 0,
KrishnaMishra = 1,
Somanatha = 2,
Nadamsa = 3,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[wasm_bindgen]
pub enum D10Variation {
Parashara = 0,
Behari = 1, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VargaConfig {
pub d2_method: i32,
pub d3_method: i32,
pub d9_method: i32,
pub d10_method: i32,
}
impl VargaConfig {
pub fn new() -> Self {
Self {
d2_method: D2Variation::Parashara as i32,
d3_method: D3Variation::Parashara as i32,
d9_method: D9Variation::Parashara as i32,
d10_method: D10Variation::Parashara as i32,
}
}
}
impl Default for VargaConfig {
fn default() -> Self {
Self::new()
}
}
fn to_d2(val: i32) -> D2Variation {
match val {
1 => D2Variation::LabhaMandooka,
2 => D2Variation::Kura,
3 => D2Variation::Kashinatha,
_ => D2Variation::Parashara,
}
}
fn to_d3(val: i32) -> D3Variation {
match val {
1 => D3Variation::Jagannatha,
2 => D3Variation::Somanatha,
3 => D3Variation::Parivritti,
_ => D3Variation::Parashara,
}
}
fn to_d9(val: i32) -> D9Variation {
match val {
1 => D9Variation::KrishnaMishra,
2 => D9Variation::Somanatha,
3 => D9Variation::Nadamsa,
_ => D9Variation::Parashara,
}
}
fn to_d10(val: i32) -> D10Variation {
match val {
1 => D10Variation::Behari,
_ => D10Variation::Parashara,
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[wasm_bindgen]
pub struct VargaPosition {
pub sign: u8,
pub longitude: f64,
pub full_longitude: f64,
}
pub fn calculate_varga_position(
long_deg: f64,
varga_type: VargaType,
config: &VargaConfig,
) -> VargaPosition {
let sign_idx = (long_deg / 30.0).floor() as u8;
match varga_type {
VargaType::D1 => {
VargaPosition {
sign: sign_idx + 1,
longitude: long_deg % 30.0,
full_longitude: long_deg,
}
},
VargaType::D2 => calculate_d2(long_deg, to_d2(config.d2_method)),
VargaType::D3 => calculate_d3(long_deg, to_d3(config.d3_method)),
VargaType::D4 => calculate_d4(long_deg),
VargaType::D7 => calculate_d7(long_deg),
VargaType::D9 => calculate_d9(long_deg, to_d9(config.d9_method)),
VargaType::D10 => calculate_d10(long_deg, to_d10(config.d10_method)),
VargaType::D12 => calculate_d12(long_deg),
VargaType::D16 => calculate_d16(long_deg),
VargaType::D20 => calculate_d20(long_deg),
VargaType::D24 => calculate_d24(long_deg),
VargaType::D27 => calculate_d27(long_deg),
VargaType::D30 => calculate_d30(long_deg),
VargaType::D40 => calculate_d40(long_deg),
VargaType::D45 => calculate_d45(long_deg),
VargaType::D60 => calculate_d60(long_deg),
}
}
fn is_movable(sign_0: u8) -> bool { matches!(sign_0 % 3, 0) } fn is_fixed(sign_0: u8) -> bool { matches!(sign_0 % 3, 1) }
fn create_pos(sign_1: u8, deg_in_sign: f64) -> VargaPosition {
let s = (sign_1 - 1) % 12 + 1;
let full = (s as f64 - 1.0) * 30.0 + deg_in_sign;
VargaPosition {
sign: s,
longitude: deg_in_sign,
full_longitude: full,
}
}
fn calculate_d2(long: f64, method: D2Variation) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8; let deg = long % 30.0;
let is_odd = sign_0 % 2 != 0; let is_first_half = deg < 15.0;
match method {
D2Variation::Parashara => {
let sun_sign = 5; let moon_sign = 4;
let target = if is_odd {
if is_first_half { sun_sign } else { moon_sign }
} else {
if is_first_half { moon_sign } else { sun_sign }
};
let projected_deg = (deg % 15.0) * 2.0;
create_pos(target, projected_deg)
},
D2Variation::LabhaMandooka => {
panic!("Labha Mandooka D2 not yet implemented"); },
_ => calculate_d2(long, D2Variation::Parashara) }
}
fn calculate_d3(long: f64, method: D3Variation) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let drekkana_idx = (deg / 10.0).floor() as u8; let projected_deg = (deg % 10.0) * 3.0;
match method {
D3Variation::Parashara => {
let jump = match drekkana_idx {
0 => 0,
1 => 4, _ => 8, };
let target_0 = (sign_0 + jump) % 12;
create_pos(target_0 + 1, projected_deg)
},
D3Variation::Jagannatha => {
let base_jump = if is_movable(sign_0) {
[0, 4, 8] } else if is_fixed(sign_0) {
[8, 0, 4] } else {
[4, 8, 0] };
let jump = base_jump[drekkana_idx as usize];
let target_0 = (sign_0 + jump) % 12;
create_pos(target_0 + 1, projected_deg)
},
D3Variation::Somanatha => {
calculate_d3(long, D3Variation::Parashara)
},
D3Variation::Parivritti => {
let abs_idx = (sign_0 as i32 * 3) + drekkana_idx as i32;
let target_0 = (abs_idx % 12) as u8;
create_pos(target_0 + 1, projected_deg)
}
}
}
fn calculate_d4(long: f64) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let part = (deg / 7.5).floor() as u8; let projected_deg = (deg % 7.5) * 4.0;
let jump = part * 3;
let target_0 = (sign_0 + jump) % 12;
create_pos(target_0 + 1, projected_deg)
}
fn calculate_d7(long: f64) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let part = (deg / (30.0/7.0)).floor() as u8; let projected_deg = (deg % (30.0/7.0)) * 7.0;
let start_sign_0 = if sign_0 % 2 == 0 { sign_0 } else { (sign_0 + 6) % 12 };
let target_0 = (start_sign_0 + part) % 12;
create_pos(target_0 + 1, projected_deg)
}
fn calculate_d9(long: f64, method: D9Variation) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let part = (deg / (30.0/9.0)).floor() as u8; let projected_deg = (deg % (30.0/9.0)) * 9.0;
match method {
D9Variation::Parashara => {
let start_offset = if is_movable(sign_0) { 0 }
else if is_fixed(sign_0) { 8 } else { 4 };
let start_sign_0 = (sign_0 + start_offset) % 12;
let target_0 = (start_sign_0 + part) % 12;
create_pos(target_0 + 1, projected_deg)
},
D9Variation::KrishnaMishra => {
calculate_d9(long, D9Variation::Parashara)
},
_ => calculate_d9(long, D9Variation::Parashara)
}
}
fn calculate_d10(long: f64, method: D10Variation) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let part = (deg / 3.0).floor() as u8; let projected_deg = (deg % 3.0) * 10.0;
match method {
D10Variation::Parashara => {
let start_offset = if sign_0 % 2 == 0 { 0 } else { 8 };
let start_sign_0 = (sign_0 + start_offset) % 12;
let target_0 = (start_sign_0 + part) % 12;
create_pos(target_0 + 1, projected_deg)
},
_ => calculate_d10(long, D10Variation::Parashara)
}
}
fn calculate_d12(long: f64) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let part = (deg / 2.5).floor() as u8; let projected_deg = (deg % 2.5) * 12.0;
let target_0 = (sign_0 + part) % 12;
create_pos(target_0 + 1, projected_deg)
}
fn calculate_d16(long: f64) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let part = (deg / (30.0/16.0)).floor() as u8;
let projected_deg = (deg % (30.0/16.0)) * 16.0;
let start_sign = if is_movable(sign_0) { 0 }
else if is_fixed(sign_0) { 4 }
else { 8 };
let target_0 = (start_sign + part) % 12;
create_pos(target_0 + 1, projected_deg)
}
fn calculate_d20(long: f64) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let part = (deg / (30.0/20.0)).floor() as u8;
let projected_deg = (deg % (30.0/20.0)) * 20.0;
let start_sign = if is_movable(sign_0) { 0 }
else if is_fixed(sign_0) { 8 }
else { 4 };
let target_0 = (start_sign + part) % 12;
create_pos(target_0 + 1, projected_deg)
}
fn calculate_d24(long: f64) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let part = (deg / (30.0/24.0)).floor() as u8;
let projected_deg = (deg % (30.0/24.0)) * 24.0;
let start_sign = if sign_0 % 2 == 0 { 4 } else { 3 };
let target_0 = (start_sign + part) % 12;
create_pos(target_0 + 1, projected_deg)
}
fn calculate_d27(long: f64) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let part = (deg / (30.0/27.0)).floor() as u8;
let projected_deg = (deg % (30.0/27.0)) * 27.0;
let s = sign_0 % 4; let start = match s {
0 => 0,
1 => 3,
2 => 6,
_ => 9,
};
let target_0 = (start + part) % 12;
create_pos(target_0 + 1, projected_deg)
}
fn calculate_d30(long: f64) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let is_odd = sign_0 % 2 != 0;
let target_sign_0 = if is_odd {
if deg < 5.0 { 0 } else if deg < 10.0 { 10 } else if deg < 18.0 { 8 } else if deg < 25.0 { 2 } else { 6 } } else {
if deg < 5.0 { 1 } else if deg < 12.0 { 5 } else if deg < 20.0 { 11 } else if deg < 25.0 { 9 } else { 7 } };
create_pos(target_sign_0 + 1, 0.0)
}
fn calculate_d40(long: f64) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let part = (deg / (30.0/40.0)).floor() as u8;
let projected_deg = (deg % (30.0/40.0)) * 40.0;
let start = if sign_0 % 2 == 0 { 0 } else { 6 };
let target_0 = (start + part) % 12;
create_pos(target_0 + 1, projected_deg)
}
fn calculate_d45(long: f64) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let part = (deg / (30.0/45.0)).floor() as u8;
let projected_deg = (deg % (30.0/45.0)) * 45.0;
let start = if is_movable(sign_0) { 0 }
else if is_fixed(sign_0) { 4 }
else { 8 };
let target_0 = (start + part) % 12;
create_pos(target_0 + 1, projected_deg)
}
fn calculate_d60(long: f64) -> VargaPosition {
let sign_0 = (long / 30.0).floor() as u8;
let deg = long % 30.0;
let part = (deg / 0.5).floor() as u8; let projected_deg = (deg % 0.5) * 60.0;
let target_0 = (sign_0 + part) % 12;
create_pos(target_0 + 1, projected_deg)
}