TD/TP always start one week after lectures, and ends one week later

This commit is contained in:
Mylloon 2024-01-22 21:46:25 +01:00
parent 1eaa257dbf
commit 23892ad245
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
3 changed files with 106 additions and 20 deletions

View file

@ -3,14 +3,17 @@ use regex::{Captures, Regex};
use scraper::Selector;
use std::{collections::HashMap, sync::Arc};
use crate::utils::{get_semester, get_webpage, get_year};
use crate::utils::{
get_semester, get_webpage, get_year,
models::{Info, InfoList, InfoType},
};
pub async fn info(
level: i8,
semester_opt: Option<i8>,
year_opt: Option<i32>,
user_agent: &str,
) -> HashMap<usize, Vec<(DateTime<Utc>, i64)>> {
) -> Info {
let semester = get_semester(semester_opt);
let year = get_year(year_opt, semester);
@ -45,18 +48,42 @@ pub async fn info(
let date_s2_1 = date_s1_2 + Duration::weeks(weeks_s1_2 + 4); // Get first week - add week of 'christmas/new year holidays'
let date_s2_2 = date_s2_1 + Duration::weeks(weeks_s2_1 + 2); // Back-to-school week - add week of holidays
// Group courses values and derive it for TD/TP
let cours_s1 = vec![(date_s1_1, weeks_s1_1), (date_s1_2, weeks_s1_2)];
let cours_s2 = vec![(date_s2_1, weeks_s2_1), (date_s2_2, weeks_s2_2)];
let tdtp_s1 = derive_from_cours(&cours_s1);
let tdtp_s2 = derive_from_cours(&cours_s2);
HashMap::from([
(
1_usize,
vec![(date_s1_1, weeks_s1_1), (date_s1_2, weeks_s1_2)],
InfoType {
course: cours_s1,
td_tp: tdtp_s1,
},
),
(
2_usize,
vec![(date_s2_1, weeks_s2_1), (date_s2_2, weeks_s2_2)],
InfoType {
course: cours_s2,
td_tp: tdtp_s2,
},
),
])
}
/// Find TD/TP dates, based on the ones from courses
fn derive_from_cours(courses: &InfoList) -> Vec<(DateTime<Utc>, i64)> {
// TD/TP start one week after courses
let before_break = courses.first().unwrap();
let after_break = courses.last().unwrap();
vec![
(before_break.0 + Duration::weeks(1), before_break.1 - 1),
(after_break.0, after_break.1 + 1),
]
}
/// Turn a french date to an english one
fn anglophonization(date: &str) -> String {
let dico = HashMap::from([

View file

@ -5,10 +5,12 @@ use std::{collections::HashMap, sync::Arc};
use crate::utils::{
self, get_hours, get_semester, get_webpage, get_year,
models::{Position, TabChar},
models::{Info, InfoList, Position, TabChar},
Capitalize,
};
use self::models::Day;
pub mod models;
/// Fetch the timetable for a class
@ -121,16 +123,8 @@ pub async fn timetable(
(schedules, (semester as usize, timetable))
}
// Data builded in the info webpage
type D = HashMap<
// Semester
usize,
// List of start and repetition of course weeks
Vec<(chrono::DateTime<Utc>, i64)>,
>;
/// Build the timetable
pub fn build(timetable: models::Timetable, dates: D) -> Vec<models::Course> {
pub fn build(timetable: models::Timetable, dates: Info) -> Vec<models::Course> {
let mut schedules = Vec::new();
// h1 => heure de début | m1 => minute de début
// h2 => heure de fin | m2 => minute de fin
@ -162,19 +156,67 @@ pub fn build(timetable: models::Timetable, dates: D) -> Vec<models::Course> {
// Start date of the back-to-school week
let datetimes = dates.get(&timetable.1 .0).unwrap();
let before_break = datetimes.first().unwrap();
add_courses(
&mut semester,
&schedules,
&timetable.1 .1,
&datetimes.course,
Some(vec![models::Category::Cours]),
None,
);
add_courses(
&mut semester,
&schedules,
&timetable.1 .1,
&datetimes.td_tp,
None,
Some(vec![models::Category::Cours]),
);
semester
}
type Schedule = [((u32, u32), (u32, u32))];
/// Add a course to the semester list
fn add_courses(
// Accumulator of courses of semester
semester: &mut Vec<models::Course>,
// Hours used
schedules: &Schedule,
// List of days
days: &Vec<Day>,
// Current courses list
info: &InfoList,
// List of category allowed
keep: Option<Vec<models::Category>>,
// List of category excluded
exclude: Option<Vec<models::Category>>,
) {
let before_break = info.first().unwrap();
let mut date = before_break.0;
let mut rep = before_break.1;
// For each weeks
for _ in 0..2 {
for _ in 0..rep {
for day in &timetable.1 .1 {
for mut course in day.courses.clone().into_iter().flatten() {
for day in days {
for mut course in day.courses.iter().flatten().cloned() {
// Get the hours
let start = schedules.get(course.start).unwrap().0;
// -1 because we only add when the size is > 1
let end = schedules.get(course.start + course.size - 1).unwrap().1;
// Check keep and exclude filters
if keep
.to_owned()
.is_some_and(|list| !course.category.iter().any(|item| list.contains(item)))
|| exclude.to_owned().is_some_and(|list| {
course.category.iter().all(|item| list.contains(item))
})
{
continue;
}
// Add the changed datetimes
course.dtstart = Some(
Utc.with_ymd_and_hms(
@ -206,12 +248,10 @@ pub fn build(timetable: models::Timetable, dates: D) -> Vec<models::Course> {
// From friday to monday
date += Duration::days(2);
}
let after_break = datetimes.get(1).unwrap();
let after_break = info.last().unwrap();
date = after_break.0;
rep = after_break.1;
}
semester
}
/// Display the timetable

View file

@ -1,3 +1,7 @@
use std::collections::HashMap;
use chrono::Utc;
/// Collection of char for the table
pub enum TabChar {
/// Vertical bar
@ -49,3 +53,18 @@ pub enum Position {
Middle,
Bottom,
}
pub type InfoList = Vec<(chrono::DateTime<Utc>, i64)>;
pub struct InfoType {
pub course: InfoList,
pub td_tp: InfoList,
}
// Info who old the start and end of courses
pub type Info = HashMap<
// Semester
usize,
// List of start and repetition of course and TD/TP weeks
InfoType,
>;