libellule 0.1.2

Unofficial implementation of the PRONOTE protocol
Documentation
use crate::convert::{TryModelize, TryModelizeWith};
use crate::error::{ConversionError, Error};
use crate::model::Parameters;
use crate::model::{self, LunchBreak};
use crate::protocol;

impl TryModelize<model::Timetable> for protocol::Timetable {
    type Error = Error;

    fn try_modelize(self, parameters: &Parameters) -> Result<model::Timetable, Self::Error> {
        let mut lessons: Vec<model::Lesson> = self
            .lessons
            .into_iter()
            .map(|lesson| lesson.try_modelize_with(parameters, &self.start_place))
            .collect::<Result<_, _>>()?;

        lessons.sort_by_key(|lesson| lesson.start);

        let lunch_break_start = parameters.place_to_time(self.lunch_break_start - self.start_place);
        let lunch_break_end = parameters.place_to_time(self.lunch_break_end - self.start_place);

        let lunch_break = LunchBreak {
            start: lunch_break_start,
            end: lunch_break_end,
        };

        Ok(model::Timetable {
            lessons,
            lunch_break,
        })
    }
}

impl TryModelizeWith<model::Lesson> for protocol::Lesson {
    type With = u32;
    type Error = Error;

    fn try_modelize_with(
        self,
        parameters: &Parameters,
        with: &Self::With,
    ) -> Result<model::Lesson, Self::Error> {
        let start = parameters.place_to_time(self.start - with);
        let end = start + parameters.instance.place_duration * self.length;

        let mut teachers = Vec::new();
        let mut subject = None;
        let mut locations = Vec::new();
        let mut groups = Vec::new();

        for information in self.information.value.into_iter() {
            match information.kind {
                2 => groups.push(model::Group {
                    id: information.id.unwrap(),
                    name: information.label,
                }),
                3 => teachers.push(information.label),
                16 => {
                    subject = Some(model::Subject {
                        id: information.id.unwrap(),
                        name: information.label,
                    })
                }
                17 => locations.push(model::Location {
                    id: information.id.unwrap(),
                    name: information.label,
                }),
                _ => return Err(ConversionError::Parse.into()),
            };
        }

        Ok(model::Lesson {
            id: self.id,
            kind: self.kind,
            start,
            end,
            teachers,
            subject: subject.unwrap(),
            locations,
            groups,
            background: self.background_color,
        })
    }
}