Skip to content

Commit

Permalink
Merge pull request #884 from hove-io/occupancy
Browse files Browse the repository at this point in the history
feat: add 'occupancies.txt' support (ntfs:v0.13.0)
  • Loading branch information
woshilapin authored Jan 9, 2023
2 parents a364952 + 715b88d commit 9bd0b64
Show file tree
Hide file tree
Showing 15 changed files with 222 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/add_prefix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ impl AddPrefix for Collections {
self.grid_exception_dates.prefix(prefix_conf);
self.grid_periods.prefix(prefix_conf);
self.grid_rel_calendar_line.prefix(prefix_conf);
self.occupancies.prefix(prefix_conf);
self.stop_time_headsigns =
add_prefix_on_vehicle_journey_ids(&self.stop_time_headsigns, prefix_conf);
self.stop_time_ids =
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub mod vptranslator;
pub(crate) const STOP_TIMES_INIT_CAPACITY: usize = 50;

/// Current version of the NTFS format
pub const NTFS_VERSION: &str = "0.12.1";
pub const NTFS_VERSION: &str = "0.13.0";

/// The max distance in meters to compute the transfer
pub const TRANSFER_MAX_DISTANCE: &str = "300";
Expand Down
25 changes: 25 additions & 0 deletions src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ pub struct Collections {
pub grid_periods: Collection<GridPeriod>,
pub grid_rel_calendar_line: Collection<GridRelCalendarLine>,
pub addresses: CollectionWithId<Address>,
pub occupancies: Collection<Occupancy>,
}

impl Collections {
Expand Down Expand Up @@ -553,6 +554,30 @@ impl Collections {
.retain(|address| addresses_used.contains(&address.id));
self.admin_stations
.retain(|admin_station| stop_area_ids_used.contains(&admin_station.stop_id));
self.occupancies.retain(|occupancy| {
if !line_ids_used.contains(&occupancy.line_id) {
debug!(
"Occupancy with 'line_id={}' has been removed because line is not used",
occupancy.line_id
);
return false;
}
if !stop_area_ids_used.contains(&occupancy.from_stop_area) {
debug!(
"Occupancy with 'from_stop_area={}' has been removed because stop area is not used",
occupancy.from_stop_area
);
return false;
}
if !stop_area_ids_used.contains(&occupancy.to_stop_area){
debug!(
"Occupancy with 'to_stop_area={}' has been removed because stop area is not used",
occupancy.to_stop_area
);
return false;
}
true
});

self.frequencies = dedup_collection(&mut self.frequencies);
self.transfers = dedup_collection(&mut self.transfers);
Expand Down
4 changes: 3 additions & 1 deletion src/ntfs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ where
read::manage_object_properties(&mut collections, file_handler)?;
read::manage_fares_v1(&mut collections, file_handler)?;
read::manage_companies_on_vj(&mut collections)?;
read::manage_occupancies(&mut collections, file_handler)?;
Ok(collections)
}

Expand Down Expand Up @@ -406,6 +407,7 @@ pub fn write<P: AsRef<path::Path>>(
write_collection_with_id(path, "pathways.txt", &model.pathways)?;
write_collection_with_id(path, "levels.txt", &model.levels)?;
write_collection_with_id(path, "addresses.txt", &model.addresses)?;
write_collection(path, "occupancies.txt", &model.occupancies)?;

Ok(())
}
Expand Down Expand Up @@ -513,7 +515,7 @@ mod tests {
("feed_end_date".to_string(), "20180131".to_string()),
("feed_publisher_name".to_string(), "Nicaragua".to_string()),
("feed_start_date".to_string(), "20180130".to_string()),
("ntfs_version".to_string(), "0.12.1".to_string()),
("ntfs_version".to_string(), "0.13.0".to_string()),
("tartare_platform".to_string(), "dev".to_string()),
],
collections
Expand Down
47 changes: 47 additions & 0 deletions src/ntfs/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,53 @@ where
Ok(())
}

pub(crate) fn manage_occupancies<H>(
collections: &mut Collections,
file_handler: &mut H,
) -> Result<()>
where
for<'a> &'a mut H: FileHandler,
{
let file = "occupancies.txt";
let ntfs_occupancies = read_objects_loose::<_, Occupancy>(file_handler, file, false)?;
let mut occupancies = Collection::default();
for occupancy in ntfs_occupancies {
if collections.lines.get(&occupancy.line_id).is_none() {
warn!(
"Problem reading 'occupancies.txt': line_id={} not found",
&occupancy.line_id
);
continue;
}
if collections
.stop_areas
.get(&occupancy.from_stop_area)
.is_none()
{
warn!(
"Problem reading 'occupancies.txt': from_stop_area={} not found",
&occupancy.from_stop_area
);
continue;
}
if collections
.stop_areas
.get(&occupancy.to_stop_area)
.is_none()
{
warn!(
"Problem reading 'occupancies.txt': to_stop_area={} not found",
&occupancy.to_stop_area
);
continue;
}
occupancies.push(occupancy);
}

collections.occupancies = occupancies;
Ok(())
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
79 changes: 79 additions & 0 deletions src/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1900,6 +1900,85 @@ impl AddPrefix for Address {
}
}

#[derive(Debug, Serialize, Deserialize, Clone, Copy, Default)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum OccupancyStatus {
Empty,
ManySeatsAvailable,
FewSeatsAvailable,
StandingRoomOnly,
CrushedStandingRoomOnly,
Full,
NotAcceptingPassengers,
#[default]
NoDataAvailable,
NotBoardable,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Occupancy {
pub line_id: String,
pub from_stop_area: String,
pub to_stop_area: String,
#[serde(
deserialize_with = "de_from_date_string",
serialize_with = "ser_from_naive_date"
)]
pub from_date: Date,
#[serde(
deserialize_with = "de_from_date_string",
serialize_with = "ser_from_naive_date"
)]
pub to_date: Date,
pub from_time: Time,
pub to_time: Time,
#[serde(
deserialize_with = "de_opt_bool_from_str",
serialize_with = "ser_from_opt_bool"
)]
pub monday: Option<bool>,
#[serde(
deserialize_with = "de_opt_bool_from_str",
serialize_with = "ser_from_opt_bool"
)]
pub tuesday: Option<bool>,
#[serde(
deserialize_with = "de_opt_bool_from_str",
serialize_with = "ser_from_opt_bool"
)]
pub wednesday: Option<bool>,
#[serde(
deserialize_with = "de_opt_bool_from_str",
serialize_with = "ser_from_opt_bool"
)]
pub thursday: Option<bool>,
#[serde(
deserialize_with = "de_opt_bool_from_str",
serialize_with = "ser_from_opt_bool"
)]
pub friday: Option<bool>,
#[serde(
deserialize_with = "de_opt_bool_from_str",
serialize_with = "ser_from_opt_bool"
)]
pub saturday: Option<bool>,
#[serde(
deserialize_with = "de_opt_bool_from_str",
serialize_with = "ser_from_opt_bool"
)]
pub sunday: Option<bool>,
pub occupancy: OccupancyStatus,
}
impl_id!(Occupancy, Line, line_id);

impl AddPrefix for Occupancy {
fn prefix(&mut self, prefix_conf: &PrefixConfiguration) {
self.line_id = prefix_conf.referential_prefix(self.line_id.as_str());
self.from_stop_area = prefix_conf.referential_prefix(self.from_stop_area.as_str());
self.to_stop_area = prefix_conf.referential_prefix(self.to_stop_area.as_str());
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
35 changes: 35 additions & 0 deletions src/serde_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,28 @@ where
}
}

/// deserialize optional u8 as Option<bool>
/// returns an error if non boolean value
pub fn de_opt_bool_from_str<'de, D>(deserializer: D) -> Result<Option<bool>, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::{
de::{Error, Unexpected::Other},
Deserialize,
};
let s = <String as Deserialize<'de>>::deserialize(deserializer)?;
match s.trim() {
"0" => Ok(Some(false)),
"1" => Ok(Some(true)),
"" => Ok(None),
_ => Err(D::Error::invalid_value(
Other(&format!("'{}' non boolean value", s)),
&"boolean",
)),
}
}

/// deserialize u8 as bool
/// returns true if non boolean value
pub fn de_from_u8_with_true_default<'de, D>(deserializer: D) -> Result<bool, D::Error>
Expand All @@ -62,6 +84,19 @@ where
serializer.serialize_u8(*v as u8)
}

/// serialize Option<bool> as u8
// The signature of the function must pass by reference for 'serde' to be able to use the function
pub fn ser_from_opt_bool<S>(v: &Option<bool>, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(match v {
None => "",
Some(false) => "0",
Some(true) => "1",
})
}

/// deserialize date from String
pub fn de_from_date_string<'de, D>(deserializer: D) -> Result<Date, D::Error>
where
Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/gtfs2ntfs/full_output/feed_infos.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ feed_license,DefaultDatasourceLicense
feed_license_url,http://www.default-datasource-website.com
feed_publisher_name,DefaultContributorName
feed_start_date,20180101
ntfs_version,0.12.1
ntfs_version,0.13.0
tartare_contributor_id,DefaultContributorId
tartare_platform,dev
2 changes: 1 addition & 1 deletion tests/fixtures/gtfs2ntfs/minimal/output/feed_infos.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ feed_creation_time,17:19:00
feed_creation_datetime,2019-04-03T17:19:00+00:00
feed_end_date,20180106
feed_start_date,20180101
ntfs_version,0.12.1
ntfs_version,0.13.0
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ feed_creation_time,17:19:00
feed_creation_datetime,2019-04-03T17:19:00+00:00
feed_end_date,20180106
feed_start_date,20180101
ntfs_version,0.12.1
ntfs_version,0.13.0
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ feed_creation_time,17:19:00
feed_creation_datetime,2019-04-03T17:19:00+00:00
feed_end_date,20180106
feed_start_date,20180101
ntfs_version,0.12.1
ntfs_version,0.13.0
10 changes: 10 additions & 0 deletions tests/fixtures/ntfs/occupancies.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
line_id,from_stop_area,to_stop_area,from_date,to_date,from_time,to_time,monday,tuesday,wednesday,thursday,friday,saturday,sunday,occupancy
RERA,NAT,GDL,20180501,20180531,07:00:00,09:00:00,1,1,1,1,1,0,0,STANDING_ROOM_ONLY
RERA,GDL,DEF,20180501,20180531,07:00:00,09:00:00,1,1,1,1,1,,,CRUSHED_STANDING_ROOM_ONLY
# The Occupancy is not a valid enum variant
RERA,GDL,DEF,20180501,20180531,07:00:00,09:00:00,0,0,0,0,0,0,0,UNKNOWN_OCCUPANCY_STATUS
# Unknown Line ID
UnkownLine,GDL,DEF,20180501,20180531,07:00:00,09:00:00,0,0,0,0,0,0,0,EMPTY
# Unknown Stop Area ID
RERA,UnknownStopArea,DEF,20180501,20180531,07:00:00,09:00:00,0,0,0,0,0,0,0,CRUSHED_STANDING_ROOM_ONLY
RERA,GDL,UnknownStopArea,20180501,20180531,07:00:00,09:00:00,0,0,0,0,0,0,0,CRUSHED_STANDING_ROOM_ONLY
3 changes: 3 additions & 0 deletions tests/fixtures/ntfs2ntfs/occupancies/occupancies.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
line_id,from_stop_area,to_stop_area,from_date,to_date,from_time,to_time,monday,tuesday,wednesday,thursday,friday,saturday,sunday,occupancy
RERA,NAT,GDL,20180501,20180531,07:00:00,09:00:00,1,1,1,1,1,0,0,STANDING_ROOM_ONLY
RERA,GDL,DEF,20180501,20180531,07:00:00,09:00:00,1,1,1,1,1,,,CRUSHED_STANDING_ROOM_ONLY
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ feed_creation_time,17:19:00
feed_creation_datetime,2019-04-03T17:19:00+00:00
feed_end_date,20180805
feed_start_date,20180501
ntfs_version,0.12.1
ntfs_version,0.13.0
13 changes: 13 additions & 0 deletions tests/read_ntfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,19 @@ fn preserve_grid() {
});
}

#[test]
fn preserve_occupancies() {
let ntm = transit_model::ntfs::read("tests/fixtures/ntfs/").unwrap();
test_in_tmp_dir(|output_dir| {
transit_model::ntfs::write(&ntm, output_dir, get_test_datetime()).unwrap();
compare_output_dir_with_expected(
output_dir,
Some(vec!["occupancies.txt"]),
"tests/fixtures/ntfs2ntfs/occupancies",
);
});
}

#[test]
fn enhance_lines_opening_time() {
let ntm = transit_model::ntfs::read("tests/fixtures/ntfs2ntfs/lines-opening/input/").unwrap();
Expand Down

0 comments on commit 9bd0b64

Please sign in to comment.