use super::hh_mm_time_format; use chrono::{Duration, NaiveTime}; use serde::Deserialize; #[derive(Deserialize, Debug, Clone, Copy)] pub struct HourBlock { #[serde(with = "hh_mm_time_format")] pub hour: NaiveTime, pub state: u32, // reservations pub granularity: u32, pub person_count: u32, pub places_available: u32, pub places_bookable: u32, } #[derive(Deserialize, Debug)] pub struct Resource { pub resource_id: u32, pub resource_name: String, pub resource_type: u32, pub granularity: u32, pub time_slot_count: u32, pub static_time_slot: bool, // reservations_by_timeslot pub note_available: bool, pub note_required: bool, pub note_description: String, pub description: String, pub capacity: u32, pub site_timezone: String, pub user_name_required: bool, pub user_phone_required: bool, pub user_name_available: bool, pub user_phone_available: bool, // time_before_reservations_closed // min_places_per_reservation // max_places_per_reservation pub image_url: Option, // services pub slots_state: u32, pub hours: Vec, } impl Resource { pub fn condensed_hours(&self) -> Vec<(&HourBlock, Duration)> { if self.hours.is_empty() { return Default::default(); } let mut start_hour = self.hours.first().unwrap(); let mut duration = Duration::minutes(start_hour.granularity.into()); let mut out: Vec<(&HourBlock, Duration)> = Default::default(); for hour in self.hours.iter().skip(1) { if hour.state == start_hour.state { duration = duration + Duration::minutes(hour.granularity.into()); } else { out.push((start_hour, duration)); start_hour = hour; duration = Duration::minutes(hour.granularity.into()); } } out.push((start_hour, duration)); out } pub fn condensed_available_hours(&self) -> Vec<(&HourBlock, Duration)> { self.condensed_hours() .into_iter() .filter(|(hour, _)| hour.state == 1) .collect() } /// Returns whether a slot with the given state and time bounds is present in the list of /// hours. pub fn has_slot(&self, start_time: NaiveTime, end_time: NaiveTime, state: u32) -> bool { self.condensed_hours() .into_iter() .filter(|(block, _)| block.state == state) .any(|(block, duration)| start_time >= block.hour && end_time <= block.hour + duration) } }