#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use qtty::Second;
use tempoch::{Time, TT};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ArcId(String);
impl ArcId {
pub fn new(s: impl Into<String>) -> Self {
Self(s.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl std::fmt::Display for ArcId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ArcDefinition {
pub id: ArcId,
pub start: Time<TT>,
pub stop: Time<TT>,
pub step_hint: Option<Second>,
}
impl ArcDefinition {
pub fn duration(&self) -> Second {
self.stop - self.start
}
pub fn is_valid(&self) -> bool {
self.stop >= self.start
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempoch::J2000Seconds;
fn at(secs: f64) -> Time<TT> {
J2000Seconds::<TT>::try_new(Second::new(secs)).unwrap()
}
#[test]
fn duration_in_seconds_matches_one_day() {
let arc = ArcDefinition {
id: ArcId::new("d"),
start: at(0.0),
stop: at(86_400.0),
step_hint: None,
};
let dt = arc.duration().value();
assert!((dt - 86_400.0).abs() < 1e-6);
assert!(arc.is_valid());
}
#[test]
fn inverted_arc_is_invalid() {
let arc = ArcDefinition {
id: ArcId::new("d"),
start: at(86_400.0),
stop: at(0.0),
step_hint: None,
};
assert!(!arc.is_valid());
}
#[test]
fn arc_id_round_trip() {
let id = ArcId::new("orbit-7");
assert_eq!(id.as_str(), "orbit-7");
assert_eq!(format!("{id}"), "orbit-7");
}
}