1use chrono::{NaiveDate, NaiveTime};
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct QsoRecord {
8 pub call: String,
10 pub station_callsign: String,
12 pub qso_date: NaiveDate,
14 pub time_on: NaiveTime,
16 pub time_off: Option<NaiveTime>,
18 pub band: String,
20 pub mode: String,
22 pub freq: Option<f64>,
24 pub rst_sent: Option<String>,
26 pub rst_rcvd: Option<String>,
28 pub qth: Option<String>,
30 pub name: Option<String>,
32 pub comment: Option<String>,
34 pub additional_fields: HashMap<String, String>,
36}
37
38impl QsoRecord {
39 pub fn builder() -> QsoRecordBuilder {
41 QsoRecordBuilder::new()
42 }
43}
44
45#[derive(Debug, Default)]
47pub struct QsoRecordBuilder {
48 call: Option<String>,
49 station_callsign: Option<String>,
50 qso_date: Option<NaiveDate>,
51 time_on: Option<NaiveTime>,
52 time_off: Option<NaiveTime>,
53 band: Option<String>,
54 mode: Option<String>,
55 freq: Option<f64>,
56 rst_sent: Option<String>,
57 rst_rcvd: Option<String>,
58 qth: Option<String>,
59 name: Option<String>,
60 comment: Option<String>,
61 additional_fields: HashMap<String, String>,
62}
63
64impl QsoRecordBuilder {
65 pub fn new() -> Self {
66 Self::default()
67 }
68
69 pub fn call(mut self, call: impl Into<String>) -> Self {
70 self.call = Some(call.into());
71 self
72 }
73
74 pub fn station_callsign(mut self, callsign: impl Into<String>) -> Self {
75 self.station_callsign = Some(callsign.into());
76 self
77 }
78
79 pub fn date(mut self, date: NaiveDate) -> Self {
80 self.qso_date = Some(date);
81 self
82 }
83
84 pub fn time_on(mut self, time: NaiveTime) -> Self {
85 self.time_on = Some(time);
86 self
87 }
88
89 pub fn time_off(mut self, time: NaiveTime) -> Self {
90 self.time_off = Some(time);
91 self
92 }
93
94 pub fn band(mut self, band: impl Into<String>) -> Self {
95 self.band = Some(band.into());
96 self
97 }
98
99 pub fn mode(mut self, mode: impl Into<String>) -> Self {
100 self.mode = Some(mode.into());
101 self
102 }
103
104 pub fn freq(mut self, freq: f64) -> Self {
105 self.freq = Some(freq);
106 self
107 }
108
109 pub fn rst_sent(mut self, rst: impl Into<String>) -> Self {
110 self.rst_sent = Some(rst.into());
111 self
112 }
113
114 pub fn rst_rcvd(mut self, rst: impl Into<String>) -> Self {
115 self.rst_rcvd = Some(rst.into());
116 self
117 }
118
119 pub fn qth(mut self, qth: impl Into<String>) -> Self {
120 self.qth = Some(qth.into());
121 self
122 }
123
124 pub fn name(mut self, name: impl Into<String>) -> Self {
125 self.name = Some(name.into());
126 self
127 }
128
129 pub fn comment(mut self, comment: impl Into<String>) -> Self {
130 self.comment = Some(comment.into());
131 self
132 }
133
134 pub fn additional_field(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
135 self.additional_fields.insert(key.into(), value.into());
136 self
137 }
138
139 pub fn build(self) -> QsoRecord {
140 QsoRecord {
141 call: self.call.unwrap_or_default(),
142 station_callsign: self.station_callsign.unwrap_or_default(),
143 qso_date: self
144 .qso_date
145 .unwrap_or_else(|| NaiveDate::from_ymd_opt(1900, 1, 1).unwrap()),
146 time_on: self
147 .time_on
148 .unwrap_or_else(|| NaiveTime::from_hms_opt(0, 0, 0).unwrap()),
149 time_off: self.time_off,
150 band: self.band.unwrap_or_default(),
151 mode: self.mode.unwrap_or_default(),
152 freq: self.freq,
153 rst_sent: self.rst_sent,
154 rst_rcvd: self.rst_rcvd,
155 qth: self.qth,
156 name: self.name,
157 comment: self.comment,
158 additional_fields: self.additional_fields,
159 }
160 }
161}
162
163#[derive(Debug, Clone)]
165pub struct InsertResponse {
166 pub logid: u64,
167 pub count: u32,
168}
169
170#[derive(Debug, Clone)]
172pub struct DeleteResponse {
173 pub deleted_count: u32,
174 pub not_found_logids: Vec<u64>,
175}
176
177#[derive(Debug, Clone)]
179pub struct StatusResponse {
180 pub data: HashMap<String, String>,
181}
182
183#[derive(Debug, Clone)]
185pub struct FetchResponse {
186 pub count: u32,
187 pub logids: Vec<u64>,
188 pub qsos: Vec<QsoRecord>,
189}
190
191#[derive(Debug, Clone, Default)]
193pub struct FetchOptions {
194 pub all: bool,
196 pub band: Option<String>,
198 pub mode: Option<String>,
200 pub call: Option<String>,
202 pub max: Option<u32>,
204 pub after_logid: Option<u64>,
206 pub date_from: Option<NaiveDate>,
208 pub date_to: Option<NaiveDate>,
210}
211
212impl FetchOptions {
213 pub fn new() -> Self {
214 Self::default()
215 }
216
217 pub fn all() -> Self {
218 Self {
219 all: true,
220 ..Default::default()
221 }
222 }
223
224 pub fn band(mut self, band: impl Into<String>) -> Self {
225 self.band = Some(band.into());
226 self
227 }
228
229 pub fn mode(mut self, mode: impl Into<String>) -> Self {
230 self.mode = Some(mode.into());
231 self
232 }
233
234 pub fn call(mut self, call: impl Into<String>) -> Self {
235 self.call = Some(call.into());
236 self
237 }
238
239 pub fn max(mut self, max: u32) -> Self {
240 self.max = Some(max);
241 self
242 }
243
244 pub fn after_logid(mut self, logid: u64) -> Self {
245 self.after_logid = Some(logid);
246 self
247 }
248
249 pub fn date_range(mut self, from: NaiveDate, to: NaiveDate) -> Self {
250 self.date_from = Some(from);
251 self.date_to = Some(to);
252 self
253 }
254
255 pub fn to_option_string(&self) -> String {
257 let mut options = Vec::new();
258
259 if self.all {
260 options.push("ALL".to_string());
261 }
262
263 if let Some(ref band) = self.band {
264 options.push(format!("BAND:{}", band));
265 }
266
267 if let Some(ref mode) = self.mode {
268 options.push(format!("MODE:{}", mode));
269 }
270
271 if let Some(ref call) = self.call {
272 options.push(format!("CALL:{}", call));
273 }
274
275 if let Some(max) = self.max {
276 options.push(format!("MAX:{}", max));
277 }
278
279 if let Some(logid) = self.after_logid {
280 options.push(format!("AFTERLOGID:{}", logid));
281 }
282
283 if let Some(date) = self.date_from {
284 options.push(format!("DATEFROM:{}", date.format("%Y%m%d")));
285 }
286
287 if let Some(date) = self.date_to {
288 options.push(format!("DATETO:{}", date.format("%Y%m%d")));
289 }
290
291 options.join(",")
292 }
293}