1use std::{
2 collections::BTreeSet,
3 hash::{DefaultHasher, Hash, Hasher},
4};
5
6use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
7use rustc_hash::FxHashMap;
8use serde::{Deserialize, Serialize};
9use strum_macros::{self, Display, EnumString};
10
11use thiserror::Error;
12
13use crate::{
14 error::{HResult, HrdfError},
15 storage::DataStorage,
16 utils::{add_1_day, sub_1_day},
17};
18
19pub(crate) type JourneyId = (i32, String); pub trait Model<M: Model<M>> {
26 type K: Copy + Eq + Hash + Serialize + for<'a> Deserialize<'a>;
28
29 fn id(&self) -> M::K;
30}
31
32macro_rules! impl_Model {
33 ($m:ty) => {
34 impl Model<$m> for $m {
35 type K = i32;
36
37 fn id(&self) -> Self::K {
38 self.id
39 }
40 }
41 };
42}
43
44#[derive(Debug, Serialize, Deserialize)]
49pub struct Attribute {
50 id: i32,
51 designation: String,
52 stop_scope: i16,
53 main_sorting_priority: i16,
54 secondary_sorting_priority: i16,
55 description: FxHashMap<Language, String>,
56}
57
58impl_Model!(Attribute);
59
60impl Attribute {
61 pub fn new(
62 id: i32,
63 designation: String,
64 stop_scope: i16,
65 main_sorting_priority: i16,
66 secondary_sorting_priority: i16,
67 ) -> Self {
68 Self {
69 id,
70 designation,
71 stop_scope,
72 main_sorting_priority,
73 secondary_sorting_priority,
74 description: FxHashMap::default(),
75 }
76 }
77
78 pub fn set_description(&mut self, language: Language, value: &str) {
81 self.description.insert(language, value.to_string());
82 }
83}
84
85#[derive(Debug, Serialize, Deserialize)]
90pub struct BitField {
91 id: i32,
92 bits: Vec<u8>,
93}
94
95impl_Model!(BitField);
96
97impl BitField {
98 pub fn new(id: i32, bits: Vec<u8>) -> Self {
99 Self { id, bits }
100 }
101
102 pub fn bits(&self) -> &Vec<u8> {
105 &self.bits
106 }
107}
108
109#[derive(Debug, Default, Serialize, Deserialize)]
114pub struct Color {
115 r: i16,
116 g: i16,
117 b: i16,
118}
119
120#[allow(unused)]
121impl Color {
122 pub fn new(r: i16, g: i16, b: i16) -> Self {
123 Self { r, g, b }
124 }
125
126 pub fn r(&self) -> i16 {
129 self.r
130 }
131
132 pub fn g(&self) -> i16 {
133 self.g
134 }
135
136 pub fn b(&self) -> i16 {
137 self.b
138 }
139}
140
141#[derive(Clone, Copy, Debug, Default, Display, Eq, Hash, PartialEq, Serialize, Deserialize)]
146pub enum CoordinateSystem {
147 #[default]
148 LV95,
149 WGS84,
150}
151
152#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
157pub struct Coordinates {
158 coordinate_system: CoordinateSystem,
159 x: f64,
160 y: f64,
161}
162
163#[allow(unused)]
164impl Coordinates {
165 pub fn new(coordinate_system: CoordinateSystem, x: f64, y: f64) -> Self {
166 Self {
167 coordinate_system,
168 x,
169 y,
170 }
171 }
172
173 pub fn easting(&self) -> Option<f64> {
176 match self.coordinate_system {
177 CoordinateSystem::LV95 => Some(self.x),
178 CoordinateSystem::WGS84 => None,
179 }
180 }
181
182 pub fn northing(&self) -> Option<f64> {
183 match self.coordinate_system {
184 CoordinateSystem::LV95 => Some(self.y),
185 CoordinateSystem::WGS84 => None,
186 }
187 }
188
189 pub fn latitude(&self) -> Option<f64> {
190 match self.coordinate_system {
191 CoordinateSystem::WGS84 => Some(self.x),
192 CoordinateSystem::LV95 => None,
193 }
194 }
195
196 pub fn longitude(&self) -> Option<f64> {
197 match self.coordinate_system {
198 CoordinateSystem::WGS84 => Some(self.y),
199 CoordinateSystem::LV95 => None,
200 }
201 }
202}
203
204#[derive(Debug, Serialize, Deserialize)]
209pub struct Direction {
210 id: i32,
211 name: String,
212}
213
214impl_Model!(Direction);
215
216impl Direction {
217 pub fn new(id: i32, name: String) -> Self {
218 Self { id, name }
219 }
220}
221
222#[derive(
227 Clone, Copy, Debug, Default, Display, Eq, Hash, PartialEq, EnumString, Serialize, Deserialize,
228)]
229pub enum DirectionType {
230 #[default]
231 #[strum(serialize = "R")]
232 Outbound,
233
234 #[strum(serialize = "H")]
235 Return,
236}
237
238#[derive(Debug, Serialize, Deserialize)]
243pub struct Holiday {
244 id: i32,
245 date: NaiveDate,
246 name: FxHashMap<Language, String>,
247}
248
249impl_Model!(Holiday);
250
251impl Holiday {
252 pub fn new(id: i32, date: NaiveDate, name: FxHashMap<Language, String>) -> Self {
253 Self { id, date, name }
254 }
255}
256
257#[derive(Debug, Serialize, Deserialize)]
262pub struct ExchangeTimeAdministration {
263 id: i32,
264 stop_id: Option<i32>, administration_1: String,
266 administration_2: String,
267 duration: i16, }
269
270impl_Model!(ExchangeTimeAdministration);
271
272impl ExchangeTimeAdministration {
273 pub fn new(
274 id: i32,
275 stop_id: Option<i32>,
276 administration_1: String,
277 administration_2: String,
278 duration: i16,
279 ) -> Self {
280 Self {
281 id,
282 stop_id,
283 administration_1,
284 administration_2,
285 duration,
286 }
287 }
288
289 pub fn stop_id(&self) -> Option<i32> {
292 self.stop_id
293 }
294
295 pub fn administration_1(&self) -> &str {
296 &self.administration_1
297 }
298
299 pub fn administration_2(&self) -> &str {
300 &self.administration_2
301 }
302
303 pub fn duration(&self) -> i16 {
304 self.duration
305 }
306}
307
308#[derive(Debug, Serialize, Deserialize)]
313pub struct ExchangeTimeJourney {
314 id: i32,
315 stop_id: i32,
316 journey_legacy_id_1: i32,
317 administration_1: String,
318 journey_legacy_id_2: i32,
319 administration_2: String,
320 duration: i16, is_guaranteed: bool,
322 bit_field_id: Option<i32>,
323}
324
325impl_Model!(ExchangeTimeJourney);
326
327impl ExchangeTimeJourney {
328 pub fn new(
329 id: i32,
330 stop_id: i32,
331 (journey_legacy_id_1, administration_1): JourneyId,
332 (journey_legacy_id_2, administration_2): JourneyId,
333 duration: i16,
334 is_guaranteed: bool,
335 bit_field_id: Option<i32>,
336 ) -> Self {
337 Self {
338 id,
339 stop_id,
340 journey_legacy_id_1,
341 administration_1,
342 journey_legacy_id_2,
343 administration_2,
344 duration,
345 is_guaranteed,
346 bit_field_id,
347 }
348 }
349
350 pub fn stop_id(&self) -> i32 {
353 self.stop_id
354 }
355
356 pub fn journey_legacy_id_1(&self) -> i32 {
357 self.journey_legacy_id_1
358 }
359
360 pub fn administration_1(&self) -> &str {
361 &self.administration_1
362 }
363
364 pub fn journey_legacy_id_2(&self) -> i32 {
365 self.journey_legacy_id_2
366 }
367
368 pub fn administration_2(&self) -> &str {
369 &self.administration_2
370 }
371
372 pub fn duration(&self) -> i16 {
373 self.duration
374 }
375
376 pub fn bit_field_id(&self) -> Option<i32> {
377 self.bit_field_id
378 }
379}
380
381#[derive(Debug, Serialize, Deserialize)]
386pub struct ExchangeTimeLine {
387 id: i32,
388 stop_id: Option<i32>,
389 line_1: LineInfo,
390 line_2: LineInfo,
391 duration: i16, is_guaranteed: bool,
393}
394
395impl_Model!(ExchangeTimeLine);
396
397#[derive(Debug, Serialize, Deserialize)]
398pub(crate) struct LineInfo {
399 administration: String,
400 transport_type_id: i32,
401 line_id: Option<String>,
402 direction: Option<DirectionType>,
403}
404
405impl LineInfo {
406 pub(crate) fn new(
407 administration: String,
408 transport_type_id: i32,
409 line_id: Option<String>,
410 direction: Option<DirectionType>,
411 ) -> Self {
412 Self {
413 administration,
414 transport_type_id,
415 line_id,
416 direction,
417 }
418 }
419}
420
421impl ExchangeTimeLine {
422 pub(crate) fn new(
423 id: i32,
424 stop_id: Option<i32>,
425 line_1: LineInfo,
426 line_2: LineInfo,
427 duration: i16,
428 is_guaranteed: bool,
429 ) -> Self {
430 Self {
431 id,
432 stop_id,
433 line_1,
434 line_2,
435 duration,
436 is_guaranteed,
437 }
438 }
439}
440
441#[derive(Debug, Serialize, Deserialize)]
446pub struct InformationText {
447 id: i32,
448 content: FxHashMap<Language, String>,
449}
450
451impl_Model!(InformationText);
452
453impl InformationText {
454 pub fn new(id: i32) -> Self {
455 Self {
456 id,
457 content: FxHashMap::default(),
458 }
459 }
460
461 pub fn set_content(&mut self, language: Language, value: &str) {
464 self.content.insert(language, value.to_string());
465 }
466}
467
468#[derive(Debug, Default, Serialize, Deserialize)]
473pub struct Journey {
474 id: i32,
475 legacy_id: i32,
476 administration: String,
477 metadata: FxHashMap<JourneyMetadataType, Vec<JourneyMetadataEntry>>,
478 route: Vec<JourneyRouteEntry>,
479}
480
481impl_Model!(Journey);
482
483impl Journey {
484 pub fn new(id: i32, legacy_id: i32, administration: String) -> Self {
485 Self {
486 id,
487 legacy_id,
488 administration,
489 metadata: FxHashMap::default(),
490 route: Vec::new(),
491 }
492 }
493
494 pub fn administration(&self) -> &str {
497 &self.administration
498 }
499
500 pub fn legacy_id(&self) -> i32 {
501 self.legacy_id
502 }
503
504 fn metadata(&self) -> &FxHashMap<JourneyMetadataType, Vec<JourneyMetadataEntry>> {
505 &self.metadata
506 }
507
508 pub fn route(&self) -> &Vec<JourneyRouteEntry> {
509 &self.route
510 }
511
512 pub fn add_metadata_entry(&mut self, k: JourneyMetadataType, v: JourneyMetadataEntry) {
515 self.metadata.entry(k).or_default().push(v);
516 }
517
518 pub fn add_route_entry(&mut self, entry: JourneyRouteEntry) {
519 self.route.push(entry);
520 }
521
522 pub(crate) fn bit_field_id(&self) -> JResult<Option<i32>> {
523 let entry = self
524 .metadata()
525 .get(&JourneyMetadataType::BitField)
526 .ok_or(JourneyError::MissingBitFieldMetadata)?;
527
528 Ok(entry
529 .first()
530 .ok_or(JourneyError::EmptyJourneyMetadata)?
531 .bit_field_id)
532 }
533
534 pub fn transport_type_id(&self) -> HResult<i32> {
535 let entry = self
536 .metadata()
537 .get(&JourneyMetadataType::TransportType)
538 .ok_or(JourneyError::MissingTransportType)?;
539 entry
540 .first()
541 .ok_or::<HrdfError>((JourneyError::EmptyJourneyMetadata).into())?
542 .resource_id
543 .ok_or(JourneyError::MissingRessourceId.into())
544 }
545
546 pub fn transport_type<'a>(
547 &'a self,
548 data_storage: &'a DataStorage,
549 ) -> HResult<&'a TransportType> {
550 let transport_id = self.transport_type_id()?;
551 data_storage
552 .transport_types()
553 .find(transport_id)
554 .ok_or(JourneyError::TransportIdNotFound(transport_id).into())
555 }
556
557 pub fn first_stop_id(&self) -> HResult<i32> {
558 Ok(self
559 .route
560 .first()
561 .ok_or(JourneyError::EmptyRoute)?
562 .stop_id())
563 }
564
565 pub fn last_stop_id(&self) -> HResult<i32> {
566 Ok(self.route.last().ok_or(JourneyError::EmptyRoute)?.stop_id())
567 }
568
569 pub fn is_last_stop(&self, stop_id: i32, ignore_loop: bool) -> HResult<bool> {
570 if ignore_loop && self.first_stop_id()? == self.last_stop_id()? {
571 Ok(false)
572 } else {
573 Ok(stop_id == self.last_stop_id()?)
574 }
575 }
576
577 pub fn count_stops(&self, departure_stop_id: i32, arrival_stop_id: i32) -> usize {
578 self.route()
579 .iter()
580 .skip_while(|stop| stop.stop_id() != departure_stop_id)
581 .take_while(|stop| stop.stop_id() != arrival_stop_id)
582 .count()
583 + 1
584 }
585
586 pub fn hash_route(&self, departure_stop_id: i32) -> Option<u64> {
587 let index = self
588 .route
589 .iter()
590 .position(|route_entry| route_entry.stop_id() == departure_stop_id)?;
591
592 let mut hasher = DefaultHasher::new();
593 self.route
594 .iter()
595 .skip(index)
596 .map(|route_entry| route_entry.stop_id())
597 .collect::<BTreeSet<_>>()
598 .hash(&mut hasher);
599 Some(hasher.finish())
600 }
601
602 pub fn departure_time_of(&self, stop_id: i32) -> HResult<(NaiveTime, bool)> {
605 let route = self.route();
606 let index = route
607 .iter()
608 .position(|route_entry| route_entry.stop_id() == stop_id)
609 .ok_or_else(|| HrdfError::MissingStopId(stop_id))?;
610 let departure_time = route[index]
611 .departure_time()
612 .ok_or_else(|| HrdfError::MissingDepartureTime(index))?;
613
614 Ok((
615 departure_time,
616 departure_time
618 < route
619 .first()
620 .ok_or(HrdfError::MissingRoute)?
621 .departure_time()
622 .ok_or(HrdfError::MissingDepartureTime(0))?,
623 ))
624 }
625
626 pub fn departure_at_of(&self, stop_id: i32, date: NaiveDate) -> HResult<NaiveDateTime> {
630 match self.departure_time_of(stop_id)? {
631 (departure_time, false) => Ok(NaiveDateTime::new(date, departure_time)),
632 (departure_time, true) => Ok(NaiveDateTime::new(add_1_day(date)?, departure_time)),
633 }
634 }
635
636 pub fn departure_at_of_with_origin(
639 &self,
640 stop_id: i32,
641 date: NaiveDate,
642 is_departure_date: bool,
644 origin_stop_id: i32,
645 ) -> HResult<NaiveDateTime> {
646 let (departure_time, is_next_day) = self.departure_time_of(stop_id)?;
647 let (_, origin_is_next_day) = if is_departure_date {
648 self.departure_time_of(origin_stop_id)?
649 } else {
650 self.arrival_time_of(origin_stop_id)?
651 };
652
653 match (is_next_day, origin_is_next_day) {
654 (true, false) => Ok(NaiveDateTime::new(add_1_day(date)?, departure_time)),
655 (false, true) => Ok(NaiveDateTime::new(sub_1_day(date)?, departure_time)),
656 _ => Ok(NaiveDateTime::new(date, departure_time)),
657 }
658 }
659
660 pub fn arrival_time_of(&self, stop_id: i32) -> HResult<(NaiveTime, bool)> {
661 let route = self.route();
662 let index = route
663 .iter()
664 .skip(1)
666 .position(|route_entry| route_entry.stop_id() == stop_id)
667 .map(|i| i + 1)
668 .ok_or_else(|| HrdfError::MissingStopId(stop_id))?;
669 let arrival_time = route[index]
670 .arrival_time()
671 .ok_or_else(|| HrdfError::MissingArrivalTime(index))?;
672
673 Ok((
674 arrival_time,
675 arrival_time
677 < route
678 .first()
679 .ok_or(HrdfError::MissingRoute)?
680 .departure_time()
681 .ok_or(HrdfError::MissingDepartureTime(0))?,
682 ))
683 }
684
685 pub fn arrival_at_of_with_origin(
687 &self,
688 stop_id: i32,
689 date: NaiveDate,
690 is_departure_date: bool,
692 origin_stop_id: i32,
693 ) -> HResult<NaiveDateTime> {
694 let (arrival_time, is_next_day) = self.arrival_time_of(stop_id)?;
695 let (_, origin_is_next_day) = if is_departure_date {
696 self.departure_time_of(origin_stop_id)?
697 } else {
698 self.arrival_time_of(origin_stop_id)?
699 };
700
701 match (is_next_day, origin_is_next_day) {
702 (true, false) => Ok(NaiveDateTime::new(add_1_day(date)?, arrival_time)),
703 (false, true) => Ok(NaiveDateTime::new(sub_1_day(date)?, arrival_time)),
704 _ => Ok(NaiveDateTime::new(date, arrival_time)),
705 }
706 }
707
708 pub fn route_section(
710 &self,
711 departure_stop_id: i32,
712 arrival_stop_id: i32,
713 ) -> Vec<&JourneyRouteEntry> {
714 let mut route_iter = self.route().iter();
715
716 for route_entry in route_iter.by_ref() {
717 if route_entry.stop_id() == departure_stop_id {
718 break;
719 }
720 }
721
722 let mut result = Vec::new();
723
724 for route_entry in route_iter {
725 result.push(route_entry);
726
727 if route_entry.stop_id() == arrival_stop_id {
728 break;
729 }
730 }
731
732 result
733 }
734}
735
736type JResult<T> = Result<T, JourneyError>;
737
738#[derive(Debug, Error)]
739pub enum JourneyError {
740 #[error("Missing MitField Metadata")]
741 MissingBitFieldMetadata,
742 #[error("JourneyMetaData is empty")]
743 EmptyJourneyMetadata,
744 #[error("Missing Transport Type Metadata")]
745 MissingTransportType,
746 #[error("Missing Reoussirce Id")]
747 MissingRessourceId,
748 #[error("Transport Id: {0} not found")]
749 TransportIdNotFound(i32),
750 #[error("Empty Route")]
751 EmptyRoute,
752 #[error("Stop Id: {0} not found")]
753 StopIdNotFound(i32),
754}
755
756#[derive(Clone, Copy, Debug, Default, Display, Eq, Hash, PartialEq, Serialize, Deserialize)]
761pub enum JourneyMetadataType {
762 #[default]
763 Attribute,
764 BitField,
765 Direction,
766 InformationText,
767 Line,
768 ExchangeTimeBoarding,
769 ExchangeTimeDisembarking,
770 TransportType,
771}
772
773#[derive(Debug, Serialize, Deserialize)]
778pub struct JourneyMetadataEntry {
779 from_stop_id: Option<i32>,
780 until_stop_id: Option<i32>,
781 resource_id: Option<i32>,
782 bit_field_id: Option<i32>,
783 departure_time: Option<NaiveTime>,
784 arrival_time: Option<NaiveTime>,
785 extra_field_1: Option<String>,
786 extra_field_2: Option<i32>,
787}
788
789impl JourneyMetadataEntry {
790 #[allow(clippy::too_many_arguments)]
791 pub fn new(
792 from_stop_id: Option<i32>,
793 until_stop_id: Option<i32>,
794 resource_id: Option<i32>,
795 bit_field_id: Option<i32>,
796 departure_time: Option<NaiveTime>,
797 arrival_time: Option<NaiveTime>,
798 extra_field_1: Option<String>,
799 extra_field_2: Option<i32>,
800 ) -> Self {
801 Self {
802 from_stop_id,
803 until_stop_id,
804 resource_id,
805 bit_field_id,
806 departure_time,
807 arrival_time,
808 extra_field_1,
809 extra_field_2,
810 }
811 }
812}
813
814#[derive(Debug, Serialize, Deserialize)]
819pub struct JourneyRouteEntry {
820 stop_id: i32,
821 arrival_time: Option<NaiveTime>,
822 departure_time: Option<NaiveTime>,
823}
824
825impl JourneyRouteEntry {
826 pub fn new(
827 stop_id: i32,
828 arrival_time: Option<NaiveTime>,
829 departure_time: Option<NaiveTime>,
830 ) -> Self {
831 Self {
832 stop_id,
833 arrival_time,
834 departure_time,
835 }
836 }
837
838 pub fn stop_id(&self) -> i32 {
841 self.stop_id
842 }
843
844 pub fn arrival_time(&self) -> &Option<NaiveTime> {
845 &self.arrival_time
846 }
847
848 pub fn departure_time(&self) -> &Option<NaiveTime> {
849 &self.departure_time
850 }
851
852 pub fn stop<'a>(&'a self, data_storage: &'a DataStorage) -> HResult<&'a Stop> {
855 let stop_id = self.stop_id();
856 data_storage
857 .stops()
858 .find(stop_id)
859 .ok_or(JourneyError::StopIdNotFound(stop_id).into())
860 }
861}
862
863#[derive(Debug, Serialize, Deserialize)]
868pub struct JourneyPlatform {
869 journey_legacy_id: i32,
870 administration: String,
871 platform_id: i32,
872 time: Option<NaiveTime>,
873 bit_field_id: Option<i32>,
874}
875
876impl JourneyPlatform {
877 pub fn new(
878 journey_legacy_id: i32,
879 administration: String,
880 platform_id: i32,
881 time: Option<NaiveTime>,
882 bit_field_id: Option<i32>,
883 ) -> Self {
884 Self {
885 journey_legacy_id,
886 administration,
887 platform_id,
888 time,
889 bit_field_id,
890 }
891 }
892}
893
894impl Model<JourneyPlatform> for JourneyPlatform {
895 type K = (i32, i32);
896
897 fn id(&self) -> Self::K {
898 (self.journey_legacy_id, self.platform_id)
899 }
900}
901
902#[derive(
907 Clone, Copy, Debug, Default, Display, Eq, Hash, PartialEq, EnumString, Serialize, Deserialize,
908)]
909pub enum Language {
910 #[default]
911 #[strum(serialize = "deu", serialize = "DE")]
912 German,
913
914 #[strum(serialize = "fra", serialize = "FR")]
915 French,
916
917 #[strum(serialize = "ita", serialize = "IT")]
918 Italian,
919
920 #[strum(serialize = "eng", serialize = "EN")]
921 English,
922}
923
924#[derive(Debug, Default, Serialize, Deserialize)]
929pub struct Line {
930 id: i32,
931 name: String,
932 short_name: String,
933 long_name: String,
934 internal_designation: String,
935 text_color: Color,
936 background_color: Color,
937}
938
939impl_Model!(Line);
940
941impl Line {
942 pub fn new(id: i32, name: String) -> Self {
943 Self {
944 id,
945 name,
946 short_name: String::default(),
947 long_name: String::default(),
948 internal_designation: String::default(),
949 text_color: Color::default(),
950 background_color: Color::default(),
951 }
952 }
953
954 pub fn set_short_name(&mut self, value: String) {
957 self.short_name = value;
958 }
959
960 pub fn set_long_name(&mut self, value: String) {
961 self.long_name = value;
962 }
963
964 pub fn set_internal_designation(&mut self, value: String) {
965 self.internal_designation = value;
966 }
967
968 pub fn set_text_color(&mut self, value: Color) {
969 self.text_color = value;
970 }
971
972 pub fn set_background_color(&mut self, value: Color) {
973 self.background_color = value;
974 }
975}
976
977#[derive(Debug, Serialize, Deserialize)]
982pub struct Platform {
983 id: i32,
984 name: String,
985 sectors: Option<String>,
986 stop_id: i32,
987 sloid: String,
988 lv95_coordinates: Coordinates,
989 wgs84_coordinates: Coordinates,
990}
991
992impl_Model!(Platform);
993
994impl Platform {
995 pub fn new(id: i32, name: String, sectors: Option<String>, stop_id: i32) -> Self {
996 Self {
997 id,
998 name,
999 sectors,
1000 stop_id,
1001 sloid: String::default(),
1002 lv95_coordinates: Coordinates::default(),
1003 wgs84_coordinates: Coordinates::default(),
1004 }
1005 }
1006
1007 pub fn set_sloid(&mut self, value: String) {
1010 self.sloid = value;
1011 }
1012
1013 pub fn set_lv95_coordinates(&mut self, value: Coordinates) {
1014 self.lv95_coordinates = value;
1015 }
1016
1017 pub fn set_wgs84_coordinates(&mut self, value: Coordinates) {
1018 self.wgs84_coordinates = value;
1019 }
1020}
1021
1022#[derive(Debug, Serialize, Deserialize)]
1027pub struct Stop {
1028 id: i32,
1029 name: String,
1030 long_name: Option<String>,
1031 abbreviation: Option<String>,
1032 synonyms: Option<Vec<String>>,
1033 lv95_coordinates: Option<Coordinates>,
1034 wgs84_coordinates: Option<Coordinates>,
1035 exchange_priority: i16,
1036 exchange_flag: i16,
1037 exchange_time: Option<(i16, i16)>, restrictions: i16,
1039 sloid: String,
1040 boarding_areas: Vec<String>,
1041}
1042
1043impl_Model!(Stop);
1044
1045impl Stop {
1046 pub fn new(
1047 id: i32,
1048 name: String,
1049 long_name: Option<String>,
1050 abbreviation: Option<String>,
1051 synonyms: Option<Vec<String>>,
1052 ) -> Self {
1053 Self {
1054 id,
1055 name,
1056 long_name,
1057 abbreviation,
1058 synonyms,
1059 lv95_coordinates: None,
1060 wgs84_coordinates: None,
1061 exchange_priority: 8, exchange_flag: 0,
1063 exchange_time: None,
1064 restrictions: 0,
1065 sloid: String::default(),
1066 boarding_areas: Vec::new(),
1067 }
1068 }
1069
1070 pub fn name(&self) -> &str {
1073 &self.name
1074 }
1075
1076 pub fn lv95_coordinates(&self) -> Option<Coordinates> {
1077 self.lv95_coordinates
1078 }
1079
1080 pub fn set_lv95_coordinates(&mut self, value: Coordinates) {
1081 self.lv95_coordinates = Some(value);
1082 }
1083
1084 pub fn wgs84_coordinates(&self) -> Option<Coordinates> {
1085 self.wgs84_coordinates
1086 }
1087
1088 pub fn set_wgs84_coordinates(&mut self, value: Coordinates) {
1089 self.wgs84_coordinates = Some(value);
1090 }
1091
1092 pub fn set_exchange_priority(&mut self, value: i16) {
1093 self.exchange_priority = value;
1094 }
1095
1096 pub fn exchange_flag(&self) -> i16 {
1097 self.exchange_flag
1098 }
1099
1100 pub fn set_exchange_flag(&mut self, value: i16) {
1101 self.exchange_flag = value;
1102 }
1103
1104 pub fn exchange_time(&self) -> Option<(i16, i16)> {
1105 self.exchange_time
1106 }
1107
1108 pub fn set_exchange_time(&mut self, value: Option<(i16, i16)>) {
1109 self.exchange_time = value;
1110 }
1111
1112 pub fn set_restrictions(&mut self, value: i16) {
1113 self.restrictions = value;
1114 }
1115
1116 pub fn set_sloid(&mut self, value: String) {
1117 self.sloid = value;
1118 }
1119
1120 pub fn add_boarding_area(&mut self, value: String) {
1123 self.boarding_areas.push(value);
1124 }
1125
1126 pub fn can_be_used_as_exchange_point(&self) -> bool {
1127 self.exchange_flag() != 0
1128 }
1129}
1130
1131#[derive(Debug, Default, Serialize, Deserialize)]
1136pub struct StopConnection {
1137 id: i32,
1138 stop_id_1: i32,
1139 stop_id_2: i32,
1140 duration: i16, attribute: i32,
1142}
1143
1144impl_Model!(StopConnection);
1145
1146impl StopConnection {
1147 pub fn new(id: i32, stop_id_1: i32, stop_id_2: i32, duration: i16) -> Self {
1148 Self {
1149 id,
1150 stop_id_1,
1151 stop_id_2,
1152 duration,
1153 attribute: 0,
1154 }
1155 }
1156
1157 pub fn stop_id_1(&self) -> i32 {
1160 self.stop_id_1
1161 }
1162
1163 pub fn stop_id_2(&self) -> i32 {
1164 self.stop_id_2
1165 }
1166
1167 pub fn duration(&self) -> i16 {
1168 self.duration
1169 }
1170
1171 pub fn set_attribute(&mut self, value: i32) {
1172 self.attribute = value;
1173 }
1174}
1175
1176#[derive(Debug, Serialize, Deserialize)]
1181pub struct ThroughService {
1182 id: i32,
1183 journey_1_id: JourneyId,
1184 journey_1_stop_id: i32, journey_2_id: JourneyId,
1186 journey_2_stop_id: i32, bit_field_id: i32,
1188}
1189
1190impl_Model!(ThroughService);
1191
1192impl ThroughService {
1193 pub fn new(
1194 id: i32,
1195 journey_1_id: JourneyId,
1196 journey_1_stop_id: i32,
1197 journey_2_id: JourneyId,
1198 journey_2_stop_id: i32,
1199 bit_field_id: i32,
1200 ) -> Self {
1201 Self {
1202 id,
1203 journey_1_id,
1204 journey_1_stop_id,
1205 journey_2_id,
1206 journey_2_stop_id,
1207 bit_field_id,
1208 }
1209 }
1210
1211 pub fn journey_1_id(&self) -> &JourneyId {
1212 &self.journey_1_id
1213 }
1214
1215 pub fn journey_1_stop_id(&self) -> i32 {
1216 self.journey_1_stop_id
1217 }
1218
1219 pub fn journey_2_id(&self) -> &JourneyId {
1220 &self.journey_2_id
1221 }
1222
1223 pub fn journey_2_stop_id(&self) -> i32 {
1224 self.journey_2_stop_id
1225 }
1226
1227 pub fn bit_field_id(&self) -> i32 {
1228 self.bit_field_id
1229 }
1230}
1231
1232#[derive(Debug, Serialize, Deserialize)]
1237pub struct TimetableMetadataEntry {
1238 id: i32,
1239 key: String,
1240 value: String,
1241}
1242
1243impl_Model!(TimetableMetadataEntry);
1244
1245impl TimetableMetadataEntry {
1246 pub fn new(id: i32, key: String, value: String) -> Self {
1247 Self { id, key, value }
1248 }
1249
1250 pub fn key(&self) -> &str {
1253 &self.key
1254 }
1255
1256 pub fn value(&self) -> &str {
1257 &self.value
1258 }
1259
1260 pub fn value_as_naive_date(&self) -> NaiveDate {
1262 NaiveDate::parse_from_str(self.value(), "%Y-%m-%d").unwrap()
1263 }
1264}
1265
1266#[derive(Debug, Serialize, Deserialize)]
1271pub struct TransportCompany {
1272 id: i32,
1273 short_name: FxHashMap<Language, String>,
1274 long_name: FxHashMap<Language, String>,
1275 full_name: FxHashMap<Language, String>,
1276 administrations: Vec<String>,
1277}
1278
1279impl_Model!(TransportCompany);
1280
1281impl TransportCompany {
1282 pub fn new(id: i32) -> Self {
1283 Self {
1284 id,
1285 short_name: FxHashMap::default(),
1286 long_name: FxHashMap::default(),
1287 full_name: FxHashMap::default(),
1288 administrations: Vec::new(),
1289 }
1290 }
1291
1292 pub fn set_administrations(&mut self, administrations: Vec<String>) {
1295 self.administrations = administrations;
1296 }
1297
1298 pub fn set_short_name(&mut self, language: Language, value: &str) {
1299 self.short_name.insert(language, value.to_string());
1300 }
1301
1302 pub fn set_long_name(&mut self, language: Language, value: &str) {
1303 self.long_name.insert(language, value.to_string());
1304 }
1305
1306 pub fn set_full_name(&mut self, language: Language, value: &str) {
1307 self.full_name.insert(language, value.to_string());
1308 }
1309}
1310
1311#[derive(Debug, Default, Serialize, Deserialize)]
1316pub struct TransportType {
1317 id: i32,
1318 designation: String,
1319 product_class_id: i16,
1320 tariff_group: String,
1321 output_control: i16,
1322 short_name: String,
1323 surcharge: i16,
1324 flag: String,
1325 product_class_name: FxHashMap<Language, String>,
1326 category_name: FxHashMap<Language, String>,
1327}
1328
1329impl_Model!(TransportType);
1330
1331impl TransportType {
1332 #[allow(clippy::too_many_arguments)]
1333 pub fn new(
1334 id: i32,
1335 designation: String,
1336 product_class_id: i16,
1337 tariff_group: String,
1338 output_control: i16,
1339 short_name: String,
1340 surcharge: i16,
1341 flag: String,
1342 ) -> Self {
1343 Self {
1344 id,
1345 designation,
1346 product_class_id,
1347 tariff_group,
1348 output_control,
1349 short_name,
1350 surcharge,
1351 flag,
1352 product_class_name: FxHashMap::default(),
1353 category_name: FxHashMap::default(),
1354 }
1355 }
1356
1357 pub fn designation(&self) -> &str {
1360 &self.designation
1361 }
1362
1363 pub fn product_class_id(&self) -> i16 {
1364 self.product_class_id
1365 }
1366
1367 pub fn set_product_class_name(&mut self, language: Language, value: &str) {
1368 self.product_class_name.insert(language, value.to_string());
1369 }
1370
1371 pub fn set_category_name(&mut self, language: Language, value: &str) {
1372 self.category_name.insert(language, value.to_string());
1373 }
1374}
1375
1376#[derive(Clone, Copy, Debug, Display, Eq, Hash, PartialEq, Serialize, Deserialize)]
1381#[allow(non_camel_case_types)]
1382pub enum Version {
1383 V_5_40_41_2_0_4,
1384 V_5_40_41_2_0_5,
1385 V_5_40_41_2_0_6,
1386 V_5_40_41_2_0_7,
1387}