use crate::kundli::astro::AstroError;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ZodiacType {
Sidereal,
Tropical,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Ayanamsha {
Lahiri,
Raman,
Krishnamurti,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum HouseSystem {
Placidus,
Koch,
Equal,
WholeSign,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum NodeType {
Mean,
True,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum AstroBody {
Sun,
Moon,
Mars,
Mercury,
Jupiter,
Venus,
Saturn,
Rahu,
Ketu,
}
impl AstroBody {
pub const ALL: [Self; 9] = [
Self::Sun,
Self::Moon,
Self::Mars,
Self::Mercury,
Self::Jupiter,
Self::Venus,
Self::Saturn,
Self::Rahu,
Self::Ketu,
];
pub const fn index(self) -> usize {
match self {
Self::Sun => 0,
Self::Moon => 1,
Self::Mars => 2,
Self::Mercury => 3,
Self::Jupiter => 4,
Self::Venus => 5,
Self::Saturn => 6,
Self::Rahu => 7,
Self::Ketu => 8,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstroRequest {
pub jd_ut: f64,
pub latitude: f64,
pub longitude: f64,
pub zodiac: ZodiacType,
pub ayanamsha: Ayanamsha,
pub house_system: HouseSystem,
pub node_type: NodeType,
}
impl AstroRequest {
pub fn new(jd_ut: f64, latitude: f64, longitude: f64) -> Self {
Self {
jd_ut,
latitude,
longitude,
zodiac: ZodiacType::Sidereal,
ayanamsha: Ayanamsha::Lahiri,
house_system: HouseSystem::WholeSign,
node_type: NodeType::True,
}
}
pub fn with_zodiac(mut self, zodiac: ZodiacType) -> Self {
self.zodiac = zodiac;
self
}
pub fn with_ayanamsha(mut self, ayanamsha: Ayanamsha) -> Self {
self.ayanamsha = ayanamsha;
self
}
pub fn with_house_system(mut self, house_system: HouseSystem) -> Self {
self.house_system = house_system;
self
}
pub fn with_node_type(mut self, node_type: NodeType) -> Self {
self.node_type = node_type;
self
}
pub fn validate(&self) -> Result<(), AstroError> {
if !self.jd_ut.is_finite() {
return Err(AstroError::InvalidJulianDay(self.jd_ut));
}
if !self.latitude.is_finite()
|| !self.longitude.is_finite()
|| self.latitude < -90.0
|| self.latitude > 90.0
|| self.longitude < -180.0
|| self.longitude > 180.0
{
return Err(AstroError::InvalidCoordinates {
latitude: self.latitude,
longitude: self.longitude,
});
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
fn sample_request() -> AstroRequest {
AstroRequest::new(2451545.0, 37.5665, 126.978)
}
#[test]
fn validate_accepts_valid_request() {
assert!(sample_request().validate().is_ok());
}
#[test]
fn validate_rejects_out_of_range_coordinates() {
let mut request = sample_request();
request.latitude = 120.0;
assert!(matches!(
request.validate(),
Err(AstroError::InvalidCoordinates { .. })
));
}
}