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) -> (NaiveTime, bool) {
605 let route = self.route();
606 let index = route
607 .iter()
608 .position(|route_entry| route_entry.stop_id() == stop_id)
609 .unwrap();
610 let departure_time = route[index].departure_time().unwrap();
611
612 (
613 departure_time,
614 departure_time < route.first().unwrap().departure_time().unwrap(),
616 )
617 }
618
619 pub fn departure_at_of(&self, stop_id: i32, date: NaiveDate) -> HResult<NaiveDateTime> {
623 match self.departure_time_of(stop_id) {
624 (departure_time, false) => Ok(NaiveDateTime::new(date, departure_time)),
625 (departure_time, true) => Ok(NaiveDateTime::new(add_1_day(date)?, departure_time)),
626 }
627 }
628
629 pub fn departure_at_of_with_origin(
632 &self,
633 stop_id: i32,
634 date: NaiveDate,
635 is_departure_date: bool,
637 origin_stop_id: i32,
638 ) -> HResult<NaiveDateTime> {
639 let (departure_time, is_next_day) = self.departure_time_of(stop_id);
640 let (_, origin_is_next_day) = if is_departure_date {
641 self.departure_time_of(origin_stop_id)
642 } else {
643 self.arrival_time_of(origin_stop_id)
644 };
645
646 match (is_next_day, origin_is_next_day) {
647 (true, false) => Ok(NaiveDateTime::new(add_1_day(date)?, departure_time)),
648 (false, true) => Ok(NaiveDateTime::new(sub_1_day(date)?, departure_time)),
649 _ => Ok(NaiveDateTime::new(date, departure_time)),
650 }
651 }
652
653 pub fn arrival_time_of(&self, stop_id: i32) -> (NaiveTime, bool) {
656 let route = self.route();
657 let index = route
658 .iter()
659 .skip(1)
661 .position(|route_entry| route_entry.stop_id() == stop_id)
662 .map(|i| i + 1)
663 .unwrap();
664 let arrival_time = route[index].arrival_time().unwrap();
665
666 (
667 arrival_time,
668 arrival_time < route.first().unwrap().departure_time().unwrap(),
670 )
671 }
672
673 pub fn arrival_at_of_with_origin(
675 &self,
676 stop_id: i32,
677 date: NaiveDate,
678 is_departure_date: bool,
680 origin_stop_id: i32,
681 ) -> HResult<NaiveDateTime> {
682 let (arrival_time, is_next_day) = self.arrival_time_of(stop_id);
683 let (_, origin_is_next_day) = if is_departure_date {
684 self.departure_time_of(origin_stop_id)
685 } else {
686 self.arrival_time_of(origin_stop_id)
687 };
688
689 match (is_next_day, origin_is_next_day) {
690 (true, false) => Ok(NaiveDateTime::new(add_1_day(date)?, arrival_time)),
691 (false, true) => Ok(NaiveDateTime::new(sub_1_day(date)?, arrival_time)),
692 _ => Ok(NaiveDateTime::new(date, arrival_time)),
693 }
694 }
695
696 pub fn route_section(
698 &self,
699 departure_stop_id: i32,
700 arrival_stop_id: i32,
701 ) -> Vec<&JourneyRouteEntry> {
702 let mut route_iter = self.route().iter();
703
704 for route_entry in route_iter.by_ref() {
705 if route_entry.stop_id() == departure_stop_id {
706 break;
707 }
708 }
709
710 let mut result = Vec::new();
711
712 for route_entry in route_iter {
713 result.push(route_entry);
714
715 if route_entry.stop_id() == arrival_stop_id {
716 break;
717 }
718 }
719
720 result
721 }
722}
723
724type JResult<T> = Result<T, JourneyError>;
725
726#[derive(Debug, Error)]
727pub enum JourneyError {
728 #[error("Missing MitField Metadata")]
729 MissingBitFieldMetadata,
730 #[error("JourneyMetaData is empty")]
731 EmptyJourneyMetadata,
732 #[error("Missing Transport Type Metadata")]
733 MissingTransportType,
734 #[error("Missing Reoussirce Id")]
735 MissingRessourceId,
736 #[error("Transport Id: {0} not found")]
737 TransportIdNotFound(i32),
738 #[error("Empty Route")]
739 EmptyRoute,
740 #[error("Stop Id: {0} not found")]
741 StopIdNotFound(i32),
742}
743
744#[derive(Clone, Copy, Debug, Default, Display, Eq, Hash, PartialEq, Serialize, Deserialize)]
749pub enum JourneyMetadataType {
750 #[default]
751 Attribute,
752 BitField,
753 Direction,
754 InformationText,
755 Line,
756 ExchangeTimeBoarding,
757 ExchangeTimeDisembarking,
758 TransportType,
759}
760
761#[derive(Debug, Serialize, Deserialize)]
766pub struct JourneyMetadataEntry {
767 from_stop_id: Option<i32>,
768 until_stop_id: Option<i32>,
769 resource_id: Option<i32>,
770 bit_field_id: Option<i32>,
771 departure_time: Option<NaiveTime>,
772 arrival_time: Option<NaiveTime>,
773 extra_field_1: Option<String>,
774 extra_field_2: Option<i32>,
775}
776
777impl JourneyMetadataEntry {
778 #[allow(clippy::too_many_arguments)]
779 pub fn new(
780 from_stop_id: Option<i32>,
781 until_stop_id: Option<i32>,
782 resource_id: Option<i32>,
783 bit_field_id: Option<i32>,
784 departure_time: Option<NaiveTime>,
785 arrival_time: Option<NaiveTime>,
786 extra_field_1: Option<String>,
787 extra_field_2: Option<i32>,
788 ) -> Self {
789 Self {
790 from_stop_id,
791 until_stop_id,
792 resource_id,
793 bit_field_id,
794 departure_time,
795 arrival_time,
796 extra_field_1,
797 extra_field_2,
798 }
799 }
800}
801
802#[derive(Debug, Serialize, Deserialize)]
807pub struct JourneyRouteEntry {
808 stop_id: i32,
809 arrival_time: Option<NaiveTime>,
810 departure_time: Option<NaiveTime>,
811}
812
813impl JourneyRouteEntry {
814 pub fn new(
815 stop_id: i32,
816 arrival_time: Option<NaiveTime>,
817 departure_time: Option<NaiveTime>,
818 ) -> Self {
819 Self {
820 stop_id,
821 arrival_time,
822 departure_time,
823 }
824 }
825
826 pub fn stop_id(&self) -> i32 {
829 self.stop_id
830 }
831
832 pub fn arrival_time(&self) -> &Option<NaiveTime> {
833 &self.arrival_time
834 }
835
836 pub fn departure_time(&self) -> &Option<NaiveTime> {
837 &self.departure_time
838 }
839
840 pub fn stop<'a>(&'a self, data_storage: &'a DataStorage) -> HResult<&'a Stop> {
843 let stop_id = self.stop_id();
844 data_storage
845 .stops()
846 .find(stop_id)
847 .ok_or(JourneyError::StopIdNotFound(stop_id).into())
848 }
849}
850
851#[derive(Debug, Serialize, Deserialize)]
856pub struct JourneyPlatform {
857 journey_legacy_id: i32,
858 administration: String,
859 platform_id: i32,
860 time: Option<NaiveTime>,
861 bit_field_id: Option<i32>,
862}
863
864impl JourneyPlatform {
865 pub fn new(
866 journey_legacy_id: i32,
867 administration: String,
868 platform_id: i32,
869 time: Option<NaiveTime>,
870 bit_field_id: Option<i32>,
871 ) -> Self {
872 Self {
873 journey_legacy_id,
874 administration,
875 platform_id,
876 time,
877 bit_field_id,
878 }
879 }
880}
881
882impl Model<JourneyPlatform> for JourneyPlatform {
883 type K = (i32, i32);
884
885 fn id(&self) -> Self::K {
886 (self.journey_legacy_id, self.platform_id)
887 }
888}
889
890#[derive(
895 Clone, Copy, Debug, Default, Display, Eq, Hash, PartialEq, EnumString, Serialize, Deserialize,
896)]
897pub enum Language {
898 #[default]
899 #[strum(serialize = "deu", serialize = "DE")]
900 German,
901
902 #[strum(serialize = "fra", serialize = "FR")]
903 French,
904
905 #[strum(serialize = "ita", serialize = "IT")]
906 Italian,
907
908 #[strum(serialize = "eng", serialize = "EN")]
909 English,
910}
911
912#[derive(Debug, Default, Serialize, Deserialize)]
917pub struct Line {
918 id: i32,
919 name: String,
920 short_name: String,
921 long_name: String,
922 internal_designation: String,
923 text_color: Color,
924 background_color: Color,
925}
926
927impl_Model!(Line);
928
929impl Line {
930 pub fn new(id: i32, name: String) -> Self {
931 Self {
932 id,
933 name,
934 short_name: String::default(),
935 long_name: String::default(),
936 internal_designation: String::default(),
937 text_color: Color::default(),
938 background_color: Color::default(),
939 }
940 }
941
942 pub fn set_short_name(&mut self, value: String) {
945 self.short_name = value;
946 }
947
948 pub fn set_long_name(&mut self, value: String) {
949 self.long_name = value;
950 }
951
952 pub fn set_internal_designation(&mut self, value: String) {
953 self.internal_designation = value;
954 }
955
956 pub fn set_text_color(&mut self, value: Color) {
957 self.text_color = value;
958 }
959
960 pub fn set_background_color(&mut self, value: Color) {
961 self.background_color = value;
962 }
963}
964
965#[derive(Debug, Serialize, Deserialize)]
970pub struct Platform {
971 id: i32,
972 name: String,
973 sectors: Option<String>,
974 stop_id: i32,
975 sloid: String,
976 lv95_coordinates: Coordinates,
977 wgs84_coordinates: Coordinates,
978}
979
980impl_Model!(Platform);
981
982impl Platform {
983 pub fn new(id: i32, name: String, sectors: Option<String>, stop_id: i32) -> Self {
984 Self {
985 id,
986 name,
987 sectors,
988 stop_id,
989 sloid: String::default(),
990 lv95_coordinates: Coordinates::default(),
991 wgs84_coordinates: Coordinates::default(),
992 }
993 }
994
995 pub fn set_sloid(&mut self, value: String) {
998 self.sloid = value;
999 }
1000
1001 pub fn set_lv95_coordinates(&mut self, value: Coordinates) {
1002 self.lv95_coordinates = value;
1003 }
1004
1005 pub fn set_wgs84_coordinates(&mut self, value: Coordinates) {
1006 self.wgs84_coordinates = value;
1007 }
1008}
1009
1010#[derive(Debug, Serialize, Deserialize)]
1015pub struct Stop {
1016 id: i32,
1017 name: String,
1018 long_name: Option<String>,
1019 abbreviation: Option<String>,
1020 synonyms: Option<Vec<String>>,
1021 lv95_coordinates: Option<Coordinates>,
1022 wgs84_coordinates: Option<Coordinates>,
1023 exchange_priority: i16,
1024 exchange_flag: i16,
1025 exchange_time: Option<(i16, i16)>, restrictions: i16,
1027 sloid: String,
1028 boarding_areas: Vec<String>,
1029}
1030
1031impl_Model!(Stop);
1032
1033impl Stop {
1034 pub fn new(
1035 id: i32,
1036 name: String,
1037 long_name: Option<String>,
1038 abbreviation: Option<String>,
1039 synonyms: Option<Vec<String>>,
1040 ) -> Self {
1041 Self {
1042 id,
1043 name,
1044 long_name,
1045 abbreviation,
1046 synonyms,
1047 lv95_coordinates: None,
1048 wgs84_coordinates: None,
1049 exchange_priority: 8, exchange_flag: 0,
1051 exchange_time: None,
1052 restrictions: 0,
1053 sloid: String::default(),
1054 boarding_areas: Vec::new(),
1055 }
1056 }
1057
1058 pub fn name(&self) -> &str {
1061 &self.name
1062 }
1063
1064 pub fn lv95_coordinates(&self) -> Option<Coordinates> {
1065 self.lv95_coordinates
1066 }
1067
1068 pub fn set_lv95_coordinates(&mut self, value: Coordinates) {
1069 self.lv95_coordinates = Some(value);
1070 }
1071
1072 pub fn wgs84_coordinates(&self) -> Option<Coordinates> {
1073 self.wgs84_coordinates
1074 }
1075
1076 pub fn set_wgs84_coordinates(&mut self, value: Coordinates) {
1077 self.wgs84_coordinates = Some(value);
1078 }
1079
1080 pub fn set_exchange_priority(&mut self, value: i16) {
1081 self.exchange_priority = value;
1082 }
1083
1084 pub fn exchange_flag(&self) -> i16 {
1085 self.exchange_flag
1086 }
1087
1088 pub fn set_exchange_flag(&mut self, value: i16) {
1089 self.exchange_flag = value;
1090 }
1091
1092 pub fn exchange_time(&self) -> Option<(i16, i16)> {
1093 self.exchange_time
1094 }
1095
1096 pub fn set_exchange_time(&mut self, value: Option<(i16, i16)>) {
1097 self.exchange_time = value;
1098 }
1099
1100 pub fn set_restrictions(&mut self, value: i16) {
1101 self.restrictions = value;
1102 }
1103
1104 pub fn set_sloid(&mut self, value: String) {
1105 self.sloid = value;
1106 }
1107
1108 pub fn add_boarding_area(&mut self, value: String) {
1111 self.boarding_areas.push(value);
1112 }
1113
1114 pub fn can_be_used_as_exchange_point(&self) -> bool {
1115 self.exchange_flag() != 0
1116 }
1117}
1118
1119#[derive(Debug, Default, Serialize, Deserialize)]
1124pub struct StopConnection {
1125 id: i32,
1126 stop_id_1: i32,
1127 stop_id_2: i32,
1128 duration: i16, attribute: i32,
1130}
1131
1132impl_Model!(StopConnection);
1133
1134impl StopConnection {
1135 pub fn new(id: i32, stop_id_1: i32, stop_id_2: i32, duration: i16) -> Self {
1136 Self {
1137 id,
1138 stop_id_1,
1139 stop_id_2,
1140 duration,
1141 attribute: 0,
1142 }
1143 }
1144
1145 pub fn stop_id_1(&self) -> i32 {
1148 self.stop_id_1
1149 }
1150
1151 pub fn stop_id_2(&self) -> i32 {
1152 self.stop_id_2
1153 }
1154
1155 pub fn duration(&self) -> i16 {
1156 self.duration
1157 }
1158
1159 pub fn set_attribute(&mut self, value: i32) {
1160 self.attribute = value;
1161 }
1162}
1163
1164#[derive(Debug, Serialize, Deserialize)]
1169pub struct ThroughService {
1170 id: i32,
1171 journey_1_id: JourneyId,
1172 journey_1_stop_id: i32, journey_2_id: JourneyId,
1174 journey_2_stop_id: i32, bit_field_id: i32,
1176}
1177
1178impl_Model!(ThroughService);
1179
1180impl ThroughService {
1181 pub fn new(
1182 id: i32,
1183 journey_1_id: JourneyId,
1184 journey_1_stop_id: i32,
1185 journey_2_id: JourneyId,
1186 journey_2_stop_id: i32,
1187 bit_field_id: i32,
1188 ) -> Self {
1189 Self {
1190 id,
1191 journey_1_id,
1192 journey_1_stop_id,
1193 journey_2_id,
1194 journey_2_stop_id,
1195 bit_field_id,
1196 }
1197 }
1198
1199 pub fn journey_1_id(&self) -> &JourneyId {
1200 &self.journey_1_id
1201 }
1202
1203 pub fn journey_1_stop_id(&self) -> i32 {
1204 self.journey_1_stop_id
1205 }
1206
1207 pub fn journey_2_id(&self) -> &JourneyId {
1208 &self.journey_2_id
1209 }
1210
1211 pub fn journey_2_stop_id(&self) -> i32 {
1212 self.journey_2_stop_id
1213 }
1214
1215 pub fn bit_field_id(&self) -> i32 {
1216 self.bit_field_id
1217 }
1218}
1219
1220#[derive(Debug, Serialize, Deserialize)]
1225pub struct TimetableMetadataEntry {
1226 id: i32,
1227 key: String,
1228 value: String,
1229}
1230
1231impl_Model!(TimetableMetadataEntry);
1232
1233impl TimetableMetadataEntry {
1234 pub fn new(id: i32, key: String, value: String) -> Self {
1235 Self { id, key, value }
1236 }
1237
1238 pub fn key(&self) -> &str {
1241 &self.key
1242 }
1243
1244 pub fn value(&self) -> &str {
1245 &self.value
1246 }
1247
1248 pub fn value_as_naive_date(&self) -> NaiveDate {
1250 NaiveDate::parse_from_str(self.value(), "%Y-%m-%d").unwrap()
1251 }
1252}
1253
1254#[derive(Debug, Serialize, Deserialize)]
1259pub struct TransportCompany {
1260 id: i32,
1261 short_name: FxHashMap<Language, String>,
1262 long_name: FxHashMap<Language, String>,
1263 full_name: FxHashMap<Language, String>,
1264 administrations: Vec<String>,
1265}
1266
1267impl_Model!(TransportCompany);
1268
1269impl TransportCompany {
1270 pub fn new(id: i32) -> Self {
1271 Self {
1272 id,
1273 short_name: FxHashMap::default(),
1274 long_name: FxHashMap::default(),
1275 full_name: FxHashMap::default(),
1276 administrations: Vec::new(),
1277 }
1278 }
1279
1280 pub fn set_administrations(&mut self, administrations: Vec<String>) {
1283 self.administrations = administrations;
1284 }
1285
1286 pub fn set_short_name(&mut self, language: Language, value: &str) {
1287 self.short_name.insert(language, value.to_string());
1288 }
1289
1290 pub fn set_long_name(&mut self, language: Language, value: &str) {
1291 self.long_name.insert(language, value.to_string());
1292 }
1293
1294 pub fn set_full_name(&mut self, language: Language, value: &str) {
1295 self.full_name.insert(language, value.to_string());
1296 }
1297}
1298
1299#[derive(Debug, Default, Serialize, Deserialize)]
1304pub struct TransportType {
1305 id: i32,
1306 designation: String,
1307 product_class_id: i16,
1308 tariff_group: String,
1309 output_control: i16,
1310 short_name: String,
1311 surcharge: i16,
1312 flag: String,
1313 product_class_name: FxHashMap<Language, String>,
1314 category_name: FxHashMap<Language, String>,
1315}
1316
1317impl_Model!(TransportType);
1318
1319impl TransportType {
1320 #[allow(clippy::too_many_arguments)]
1321 pub fn new(
1322 id: i32,
1323 designation: String,
1324 product_class_id: i16,
1325 tariff_group: String,
1326 output_control: i16,
1327 short_name: String,
1328 surcharge: i16,
1329 flag: String,
1330 ) -> Self {
1331 Self {
1332 id,
1333 designation,
1334 product_class_id,
1335 tariff_group,
1336 output_control,
1337 short_name,
1338 surcharge,
1339 flag,
1340 product_class_name: FxHashMap::default(),
1341 category_name: FxHashMap::default(),
1342 }
1343 }
1344
1345 pub fn designation(&self) -> &str {
1348 &self.designation
1349 }
1350
1351 pub fn product_class_id(&self) -> i16 {
1352 self.product_class_id
1353 }
1354
1355 pub fn set_product_class_name(&mut self, language: Language, value: &str) {
1356 self.product_class_name.insert(language, value.to_string());
1357 }
1358
1359 pub fn set_category_name(&mut self, language: Language, value: &str) {
1360 self.category_name.insert(language, value.to_string());
1361 }
1362}
1363
1364#[derive(Clone, Copy, Debug, Display, Eq, Hash, PartialEq, Serialize, Deserialize)]
1369#[allow(non_camel_case_types)]
1370pub enum Version {
1371 V_5_40_41_2_0_4,
1372 V_5_40_41_2_0_5,
1373 V_5_40_41_2_0_6,
1374 V_5_40_41_2_0_7,
1375}