use serde::{Deserialize, Serialize};
pub use falak::ephemeris;
pub use falak::frame;
pub use falak::kepler;
pub use falak::maneuver;
pub use falak::nbody;
pub use falak::orbit;
pub use falak::perturbation;
pub use falak::propagate;
pub use falak::transfer;
pub use falak::FalakError;
pub use jyotish::calendar;
pub use jyotish::coords;
pub use jyotish::eclipse;
pub use jyotish::moon;
pub use jyotish::nutation;
pub use jyotish::planet;
pub use jyotish::riseset;
pub use jyotish::star as jyotish_star;
pub use jyotish::sun;
pub use jyotish::JyotishError;
pub use tara::atmosphere as stellar_atmosphere;
pub use tara::classification;
pub use tara::evolution;
pub use tara::luminosity;
pub use tara::nucleosynthesis;
pub use tara::spectral as stellar_spectral;
pub use tara::star;
pub use tara::error::TaraError;
pub use brahmanda::cosmic_web;
pub use brahmanda::cosmology;
pub use brahmanda::halo;
pub use brahmanda::morphology as galaxy_morphology;
pub use brahmanda::power_spectrum;
pub use brahmanda::BrahmandaError;
pub use badal::atmosphere as weather_atmosphere;
pub use badal::cloud;
pub use badal::mesoscale;
pub use badal::moisture;
pub use badal::precipitation;
pub use badal::pressure;
pub use badal::radiation;
pub use badal::severe;
pub use badal::stability as atmo_stability;
pub use badal::wind as weather_wind;
pub use badal::BadalError;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CelestialBody {
pub name: String,
pub mass: f64,
pub semi_major_axis: f64,
pub eccentricity: f64,
pub inclination: f64,
pub true_anomaly: f64,
pub active: bool,
}
impl CelestialBody {
pub fn circular(name: impl Into<String>, mass: f64, radius: f64) -> Self {
let name = name.into();
tracing::trace!(%name, mass, radius, "created celestial body (circular)");
Self {
name,
mass,
semi_major_axis: radius,
eccentricity: 0.0,
inclination: 0.0,
true_anomaly: 0.0,
active: true,
}
}
pub fn elliptical(
name: impl Into<String>,
mass: f64,
semi_major_axis: f64,
eccentricity: f64,
) -> Self {
let name = name.into();
tracing::trace!(%name, mass, semi_major_axis, eccentricity, "created celestial body (elliptical)");
Self {
name,
mass,
semi_major_axis,
eccentricity,
inclination: 0.0,
true_anomaly: 0.0,
active: true,
}
}
pub fn with_inclination(mut self, inc: f64) -> Self {
self.inclination = inc;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WeatherZone {
pub temperature: f64,
pub pressure: f64,
pub humidity: f64,
pub wind_speed: f64,
pub wind_direction: f64,
pub cloud_cover: f64,
pub condition: WeatherCondition,
pub active: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[non_exhaustive]
pub enum WeatherCondition {
#[default]
Clear,
PartlyCloudy,
Overcast,
Rain,
Snow,
Thunderstorm,
Fog,
}
impl WeatherZone {
pub fn standard() -> Self {
tracing::trace!(
temperature = 288.15,
pressure = 101325.0,
"created standard weather zone"
);
Self {
temperature: 288.15, pressure: 101325.0, humidity: 0.5,
wind_speed: 0.0,
wind_direction: 0.0,
cloud_cover: 0.0,
condition: WeatherCondition::Clear,
active: true,
}
}
pub fn with_temperature(mut self, t: f64) -> Self {
self.temperature = t;
self
}
pub fn with_humidity(mut self, h: f64) -> Self {
self.humidity = h.clamp(0.0, 1.0);
self
}
pub fn with_wind(mut self, speed: f64, direction: f64) -> Self {
self.wind_speed = speed;
self.wind_direction = direction;
self
}
pub fn with_condition(mut self, condition: WeatherCondition) -> Self {
self.condition = condition;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn celestial_circular() {
let body = CelestialBody::circular("Earth", 5.972e24, 1.496e11);
assert_eq!(body.eccentricity, 0.0);
assert_eq!(body.name, "Earth");
}
#[test]
fn celestial_elliptical() {
let body =
CelestialBody::elliptical("Mars", 6.417e23, 2.279e11, 0.0934).with_inclination(0.032);
assert!(body.eccentricity > 0.0);
assert!(body.inclination > 0.0);
}
#[test]
fn weather_standard() {
let w = WeatherZone::standard();
assert_eq!(w.condition, WeatherCondition::Clear);
assert!((w.temperature - 288.15).abs() < 0.01);
}
#[test]
fn weather_builder() {
let w = WeatherZone::standard()
.with_temperature(260.0)
.with_humidity(0.9)
.with_wind(15.0, std::f64::consts::PI)
.with_condition(WeatherCondition::Snow);
assert_eq!(w.condition, WeatherCondition::Snow);
assert_eq!(w.wind_speed, 15.0);
}
#[test]
fn celestial_as_component() {
let mut world = crate::World::new();
let e = world.spawn();
world
.insert_component(e, CelestialBody::circular("Moon", 7.342e22, 3.844e8))
.unwrap();
assert!(world.has_component::<CelestialBody>(e));
}
#[test]
fn weather_as_component() {
let mut world = crate::World::new();
let e = world.spawn();
world.insert_component(e, WeatherZone::standard()).unwrap();
let w = world.get_component::<WeatherZone>(e).unwrap();
assert_eq!(w.condition, WeatherCondition::Clear);
}
}