subjective/school/
mod.rs

1/// Bell-related data.
2pub mod bells;
3/// Link-related data.
4pub mod link;
5/// Notice-related data.
6pub mod notice;
7
8use crate::school::{bells::BellTime, link::Link, notice::Notice};
9use colored::Colorize;
10use linked_hash_map::LinkedHashMap;
11use serde::{Deserialize, Deserializer, Serialize};
12use std::fmt::Display;
13
14/// A day of the week, containing bell times for each period.
15pub type Day = Vec<BellTime>;
16
17#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
18#[serde(rename_all = "camelCase")]
19/// School data, including bells, notices, links, and bell times.
20pub struct School {
21    /// Name of the school.
22    pub name: String,
23    /// Notices associated with the school.
24    pub notices: Vec<Notice>,
25    /// Links associated with the school.
26    pub links: Vec<Link>,
27    /// Whether the user created the school.
28    pub user_created: bool,
29    /// Bell times for each week variant.
30    #[serde(deserialize_with = "from_map")]
31    pub bell_times: Vec<(String, [Day; 5])>,
32}
33
34fn from_map<'de, D>(deserializer: D) -> Result<Vec<(String, [Day; 5])>, D::Error>
35where
36    D: Deserializer<'de>,
37{
38    let s: LinkedHashMap<String, Vec<Day>> = Deserialize::deserialize(deserializer)?;
39    Ok(s.into_iter()
40        .map(|(name, week)| (name, week.try_into().unwrap()))
41        .collect())
42}
43
44impl Display for School {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        write!(f, "{: <40} ", self.name)?;
47        write!(
48            f,
49            "{}",
50            format!(
51                "({} notices, {} links, {} weeks, {} bells)",
52                self.notices.len(),
53                self.links.len(),
54                self.bell_times.len(),
55                self.bell_times
56                    .iter()
57                    .map(|(_, days)| days.iter().flatten().count())
58                    .sum::<usize>()
59            )
60            .dimmed()
61        )?;
62        Ok(())
63    }
64}