1#[cfg(feature = "pylib")]
2use pyo3::prelude::*;
3use std::fmt::Display;
4
5mod station_num;
6pub use station_num::StationNumber;
7
8mod state_prov;
9pub use state_prov::StateProv;
10
11#[cfg_attr(feature = "pylib", pyclass(module = "bufkit_data"))]
13#[derive(Clone, Debug, PartialEq, Eq, Hash)]
14pub struct SiteInfo {
15 pub station_num: StationNumber,
17 pub name: Option<String>,
19 pub notes: Option<String>,
21 pub state: Option<StateProv>,
24 pub time_zone: Option<chrono::FixedOffset>,
26}
27
28impl SiteInfo {
29 pub fn incomplete(&self) -> bool {
32 self.name.is_none()
33 || self.state.is_none()
34 || self.time_zone.is_none()
35 || !self.station_num.is_valid()
36 }
37
38 pub fn description(&self) -> String {
40 let mut desc = String::new();
41
42 if let Some(ref nm) = self.name {
43 desc += nm;
44 if let Some(st) = self.state {
45 desc += ", ";
46 desc += st.as_static_str();
47 }
48
49 desc += " ";
50 }
51
52 desc += &format!("({})", self.station_num);
53
54 desc
55 }
56}
57
58impl Display for SiteInfo {
59 fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
60 writeln!(
61 formatter,
62 "Site: station_num - {:6} | name - {:20} | state - {:2} | notes - {}",
63 self.station_num,
64 self.name.as_deref().unwrap_or("None"),
65 self.state.map(|s| s.as_static_str()).unwrap_or("None"),
66 self.notes.as_deref().unwrap_or("None"),
67 )
68 }
69}
70
71impl Default for SiteInfo {
72 fn default() -> Self {
73 SiteInfo {
74 station_num: StationNumber::from(0),
75 name: None,
76 notes: None,
77 state: None,
78 time_zone: None,
79 }
80 }
81}
82
83#[cfg(feature = "pylib")]
84#[cfg_attr(feature = "pylib", pymethods)]
85impl SiteInfo {
86
87 fn __repr__(&self) -> PyResult<String> {
88 Ok(self.description())
89 }
90
91 #[getter]
92 fn get_station_num(&self) -> StationNumber {
93 self.station_num
94 }
95
96 #[getter]
97 fn get_station_name(&self) -> String {
98 self.name.clone().unwrap_or_else(|| "No Name".to_owned())
99 }
100}
101
102#[cfg(test)]
106mod unit {
107 use super::*;
108
109 #[test]
110 fn test_site_incomplete() {
111 let complete_site = SiteInfo {
112 station_num: StationNumber::from(1),
113 name: Some("tv station".to_owned()),
114 state: Some(StateProv::VI),
115 notes: Some("".to_owned()),
116 time_zone: Some(chrono::FixedOffset::west_opt(7 * 3600).unwrap()),
117 };
118
119 let incomplete_site = SiteInfo {
120 station_num: StationNumber::from(1),
121 name: Some("tv station".to_owned()),
122 state: None,
123 notes: None,
124 time_zone: None,
125 };
126
127 assert!(!complete_site.incomplete());
128 assert!(incomplete_site.incomplete());
129 }
130}