pub mod body; pub mod fleet; pub mod orbit; use self::body::*; use self::fleet::*; use self::orbit::*; use serde::{Deserialize}; use crate::known_stars::*; use crate::timeman::Second; use std::error::Error; const GRAVITATIONAL_CONSTANT: f64 = 6.67408e-20; pub type Kilograms = f64; pub type Kilometers = f64; pub type Percentage = f64; pub type Angle = f64; pub type SystemId = usize; #[derive(Debug, Deserialize)] pub struct CSVOrbitalBody { name: String, orbits: Option, mass: Kilograms, radius: Kilometers, eccentricity: Percentage, inclination: Angle, long_asc_node: Angle, long_periapsis: Angle, sgp: f64, mean_long: Angle, semi_major_axis: Kilometers, } pub trait HasMass { fn mass() -> Kilograms; } pub struct SolarSystem { id: SystemId, name: String, bodies: Vec, fleets: Vec } impl SolarSystem { pub fn new_from_csv( id: SystemId, data: &'static str) -> Result> { let data_reader = stringreader::StringReader::new(data); let mut body_reader = csv::Reader::from_reader(data_reader); let mut bodies = Vec::::new(); for result in body_reader.deserialize() { let mut record: CSVOrbitalBody = result?; match record.orbits { Some(orbits) => { if record.sgp == 0.0 { record.sgp = (bodies[orbits].mass() + record.mass) * GRAVITATIONAL_CONSTANT; } } None => {} } if record.radius == 0.0 { continue; } println!("New body: {:?}", record); bodies.push(OrbitalBody::new_from_record(bodies.len(), record)); } Ok(Self { id: id, name: bodies[0].name().clone(), bodies: bodies, fleets: vec![] }) } pub fn new_from_known_star( id: SystemId, star: &'static str) -> Result> { let star_csv = match KNOWN_STARS.get(star).copied() { Some(csv) => csv, None => return Err(Box::new(StarNotFoundError { star: star })) }; SolarSystem::new_from_csv(id, star_csv) } pub fn id(&self) -> SystemId { self.id } pub fn name(&self) -> &String { &self.name } pub fn bodies(&self) -> &[OrbitalBody] { self.bodies.as_slice() } pub fn body(&self, id: BodyId) -> &OrbitalBody { &self.bodies[id] } pub fn body_position( &self, body: &OrbitalBody) -> cgmath::Vector3 { body.absolute_position(self) } pub fn fleets(&self) -> &[Fleet] { self.fleets.as_slice() } pub fn tick( &mut self, time: Second) { self.bodies.iter_mut().for_each(|body| { body.tick(time); }); self.fleets.iter_mut().for_each(|fleet| { fleet.tick(time); }); } }