forked from Anri/cal8tor
TD/TP always start one week after lectures, and ends one week later
This commit is contained in:
parent
1eaa257dbf
commit
23892ad245
3 changed files with 106 additions and 20 deletions
35
src/info.rs
35
src/info.rs
|
@ -3,14 +3,17 @@ use regex::{Captures, Regex};
|
||||||
use scraper::Selector;
|
use scraper::Selector;
|
||||||
use std::{collections::HashMap, sync::Arc};
|
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(
|
pub async fn info(
|
||||||
level: i8,
|
level: i8,
|
||||||
semester_opt: Option<i8>,
|
semester_opt: Option<i8>,
|
||||||
year_opt: Option<i32>,
|
year_opt: Option<i32>,
|
||||||
user_agent: &str,
|
user_agent: &str,
|
||||||
) -> HashMap<usize, Vec<(DateTime<Utc>, i64)>> {
|
) -> Info {
|
||||||
let semester = get_semester(semester_opt);
|
let semester = get_semester(semester_opt);
|
||||||
let year = get_year(year_opt, semester);
|
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_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
|
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([
|
HashMap::from([
|
||||||
(
|
(
|
||||||
1_usize,
|
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,
|
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
|
/// Turn a french date to an english one
|
||||||
fn anglophonization(date: &str) -> String {
|
fn anglophonization(date: &str) -> String {
|
||||||
let dico = HashMap::from([
|
let dico = HashMap::from([
|
||||||
|
|
|
@ -5,10 +5,12 @@ use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
self, get_hours, get_semester, get_webpage, get_year,
|
self, get_hours, get_semester, get_webpage, get_year,
|
||||||
models::{Position, TabChar},
|
models::{Info, InfoList, Position, TabChar},
|
||||||
Capitalize,
|
Capitalize,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use self::models::Day;
|
||||||
|
|
||||||
pub mod models;
|
pub mod models;
|
||||||
|
|
||||||
/// Fetch the timetable for a class
|
/// Fetch the timetable for a class
|
||||||
|
@ -121,16 +123,8 @@ pub async fn timetable(
|
||||||
(schedules, (semester as usize, 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
|
/// 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();
|
let mut schedules = Vec::new();
|
||||||
// h1 => heure de début | m1 => minute de début
|
// h1 => heure de début | m1 => minute de début
|
||||||
// h2 => heure de fin | m2 => minute de fin
|
// 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
|
// Start date of the back-to-school week
|
||||||
let datetimes = dates.get(&timetable.1 .0).unwrap();
|
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 date = before_break.0;
|
||||||
let mut rep = before_break.1;
|
let mut rep = before_break.1;
|
||||||
// For each weeks
|
// For each weeks
|
||||||
for _ in 0..2 {
|
for _ in 0..2 {
|
||||||
for _ in 0..rep {
|
for _ in 0..rep {
|
||||||
for day in &timetable.1 .1 {
|
for day in days {
|
||||||
for mut course in day.courses.clone().into_iter().flatten() {
|
for mut course in day.courses.iter().flatten().cloned() {
|
||||||
// Get the hours
|
// Get the hours
|
||||||
let start = schedules.get(course.start).unwrap().0;
|
let start = schedules.get(course.start).unwrap().0;
|
||||||
// -1 because we only add when the size is > 1
|
// -1 because we only add when the size is > 1
|
||||||
let end = schedules.get(course.start + course.size - 1).unwrap().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
|
// Add the changed datetimes
|
||||||
course.dtstart = Some(
|
course.dtstart = Some(
|
||||||
Utc.with_ymd_and_hms(
|
Utc.with_ymd_and_hms(
|
||||||
|
@ -206,12 +248,10 @@ pub fn build(timetable: models::Timetable, dates: D) -> Vec<models::Course> {
|
||||||
// From friday to monday
|
// From friday to monday
|
||||||
date += Duration::days(2);
|
date += Duration::days(2);
|
||||||
}
|
}
|
||||||
let after_break = datetimes.get(1).unwrap();
|
let after_break = info.last().unwrap();
|
||||||
date = after_break.0;
|
date = after_break.0;
|
||||||
rep = after_break.1;
|
rep = after_break.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
semester
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Display the timetable
|
/// Display the timetable
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use chrono::Utc;
|
||||||
|
|
||||||
/// Collection of char for the table
|
/// Collection of char for the table
|
||||||
pub enum TabChar {
|
pub enum TabChar {
|
||||||
/// Vertical bar
|
/// Vertical bar
|
||||||
|
@ -49,3 +53,18 @@ pub enum Position {
|
||||||
Middle,
|
Middle,
|
||||||
Bottom,
|
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,
|
||||||
|
>;
|
||||||
|
|
Loading…
Reference in a new issue