use super::Sv;
use std::collections::HashMap;
use strum_macros::EnumString;
pub mod record;
pub use record::{Map, Record};
pub mod grid;
pub use grid::{Grid, GridLinspace};
pub mod system;
pub use system::RefSystem;
#[cfg(feature = "serde")]
use serde::Serialize;
#[derive(Debug, Clone, PartialEq, PartialOrd, EnumString)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum MappingFunction {
#[strum(serialize = "COSZ")]
CosZ,
#[strum(serialize = "QFAC")]
QFac,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Hash, Eq, EnumString)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum BiasSource {
SpaceVehicle(Sv),
Station(String),
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct HeaderFields {
pub reference: RefSystem,
pub description: Option<String>,
pub mapping: Option<MappingFunction>,
pub map_dimension: u8,
pub base_radius: f32,
pub grid: grid::Grid,
pub elevation_cutoff: f32,
pub observables: Option<String>,
pub nb_stations: u32,
pub nb_satellites: u32,
pub exponent: i8,
pub dcbs: HashMap<BiasSource, (f64, f64)>,
}
impl Default for HeaderFields {
fn default() -> Self {
Self {
reference: RefSystem::default(),
exponent: -1, map_dimension: 2, mapping: None,
observables: None,
description: None,
elevation_cutoff: 0.0,
base_radius: 0.0,
grid: grid::Grid::default(),
nb_stations: 0,
nb_satellites: 0,
dcbs: HashMap::new(),
}
}
}
impl HeaderFields {
pub fn with_reference_system(&self, reference: RefSystem) -> Self {
let mut s = self.clone();
s.reference = reference;
s
}
pub fn with_exponent(&self, e: i8) -> Self {
let mut s = self.clone();
s.exponent = e;
s
}
pub fn with_description(&self, desc: &str) -> Self {
let mut s = self.clone();
if let Some(ref mut d) = s.description {
d.push_str(" ");
d.push_str(desc)
} else {
s.description = Some(desc.to_string())
}
s
}
pub fn with_mapping_function(&self, mf: MappingFunction) -> Self {
let mut s = self.clone();
s.mapping = Some(mf);
s
}
pub fn with_elevation_cutoff(&self, e: f32) -> Self {
let mut s = self.clone();
s.elevation_cutoff = e;
s
}
pub fn with_observables(&self, o: &str) -> Self {
let mut s = self.clone();
if o.len() > 0 {
s.observables = Some(o.to_string())
}
s
}
pub fn is_theoretical_model(&self) -> bool {
self.observables.is_some()
}
pub fn with_nb_stations(&self, n: u32) -> Self {
let mut s = self.clone();
s.nb_stations = n;
s
}
pub fn with_nb_satellites(&self, n: u32) -> Self {
let mut s = self.clone();
s.nb_satellites = n;
s
}
pub fn with_base_radius(&self, b: f32) -> Self {
let mut s = self.clone();
s.base_radius = b;
s
}
pub fn with_map_dimension(&self, d: u8) -> Self {
let mut s = self.clone();
s.map_dimension = d;
s
}
pub fn with_latitude_grid(&self, grid: GridLinspace) -> Self {
let mut s = self.clone();
s.grid.latitude = grid;
s
}
pub fn with_longitude_grid(&self, grid: GridLinspace) -> Self {
let mut s = self.clone();
s.grid.longitude = grid;
s
}
pub fn with_altitude_grid(&self, grid: GridLinspace) -> Self {
let mut s = self.clone();
s.grid.height = grid;
s
}
pub fn with_dcb(&self, src: BiasSource, value: (f64, f64)) -> Self {
let mut s = self.clone();
s.dcbs.insert(src, value);
s
}
}
#[cfg(test)]
mod test {
use super::*;
use std::str::FromStr;
#[test]
fn test_mapping_func() {
let content = "COSZ";
let func = MappingFunction::from_str(content);
assert_eq!(func.is_ok(), true);
assert_eq!(func.unwrap(), MappingFunction::CosZ);
let content = "QFAC";
let func = MappingFunction::from_str(content);
assert_eq!(func.is_ok(), true);
assert_eq!(func.unwrap(), MappingFunction::QFac);
let content = "DONT";
let func = MappingFunction::from_str(content);
assert_eq!(func.is_err(), true);
}
}