diff --git a/src/filter.rs b/src/filter.rs index 662d6f3..655c70a 100644 --- a/src/filter.rs +++ b/src/filter.rs @@ -1,11 +1,10 @@ -use std::collections::HashMap; - use dialoguer::MultiSelect; use crate::timetable::models::Category; -use crate::timetable::models::Course; use crate::timetable::models::Timetable; -use crate::utils::fill_hours; +use crate::utils::get_count; +use crate::utils::get_entry; +use crate::utils::get_selection; const DISCLAIMER: &str = "(selection avec ESPACE, ENTRER pour valider)"; @@ -59,42 +58,9 @@ fn choice(timetable: &mut Timetable) { /// Filter the multiple courses fn courses(timetable: &mut Timetable) { - // Entry's name used for finding duplicates - let get_entry = |course: &Course| format!("{} - {:?}", course.name, course.category); - - let mut hours = vec![]; - fill_hours(&mut hours); - - // Names showed to the users - let get_selection = |data: &(&Course, String)| { - format!( - "{} - {} {}-{}", - data.0.name, - data.1, - hours[data.0.start].split_once('-').unwrap().0, - hours[data.0.start + data.0.size - 1] - .split_once('-') - .unwrap() - .1 - ) - }; - - // List of courses who will be courses - let mut courses = vec![]; - - // Counter of courses appearing to know if multiples slots are available - let mut counts = HashMap::new(); - timetable.1 .1.iter().for_each(|day| { - day.courses.iter().for_each(|course_opt| { - if let Some(course) = course_opt { - if course.category == Category::Cours { - courses.push((course, day.name.to_owned())); - let count = counts.entry(get_entry(course)).or_insert(0); - *count += 1; - } - } - }) - }); + // List of courses and Counter of how much they appears + // to know if multiples slots are available + let (mut courses, counts) = get_count(timetable, &[Category::Cours]); // Keep only elements who have multiples slots courses.retain(|course| *counts.get(&get_entry(course.0)).unwrap() > 1); @@ -127,7 +93,7 @@ fn courses(timetable: &mut Timetable) { return true; } - // Keep only chosen courses + // Keep only chosen courses if multiple was available for i in &selections { if get_selection(&(course, day.name.to_owned())) == multiselected[*i] { return true; @@ -142,45 +108,9 @@ fn courses(timetable: &mut Timetable) { /// Filter the multiples TD/TP fn tdtp(timetable: &mut Timetable) { - // Entry's name used for finding duplicates - let get_entry = |course: &Course| format!("{} - {:?}", course.name, course.category); - - let mut hours = vec![]; - fill_hours(&mut hours); - - // Names showed to the users - let get_selection = |data: &(&Course, String)| { - format!( - "{} - {} {}-{}", - data.0.name, - data.1, - hours[data.0.start].split_once('-').unwrap().0, - hours[data.0.start + data.0.size - 1] - .split_once('-') - .unwrap() - .1 - ) - }; - - // List of courses who will be TP/TD - let mut td_or_tp = vec![]; - - // Counter of appearing of TP/TD to know if a TP/TD have multiple possible course - let mut counts = HashMap::new(); - timetable.1 .1.iter().for_each(|day| { - day.courses.iter().for_each(|course_opt| { - if let Some(course) = course_opt { - match course.category { - Category::TD | Category::TP => { - td_or_tp.push((course, day.name.to_owned())); - let count = counts.entry(get_entry(course)).or_insert(0); - *count += 1; - } - _ => (), - } - } - }) - }); + // List of TP/TD and Counter of how much they appears + // to know if multiples slots are available + let (mut td_or_tp, counts) = get_count(timetable, &[Category::TD, Category::TP]); // Keep only elements who have multiples TD/TP td_or_tp.retain(|course| *counts.get(&get_entry(course.0)).unwrap() > 1); @@ -208,12 +138,12 @@ fn tdtp(timetable: &mut Timetable) { return true; } - // Keep if its an -only one course- TD/TP + // Keep if only one slot is available of the TD/TP if *counts.get(&get_entry(course)).unwrap() == 1 { return true; } - // Remove courses not followed + // Keep only chosen TD/TP if multiple was available for i in &selections { if get_selection(&(course, day.name.to_owned())) == multiselected[*i] { return true; diff --git a/src/utils.rs b/src/utils.rs index d5ca354..afb56a6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,10 @@ +use std::collections::HashMap; + use chrono::{Datelike, Utc}; use scraper::Html; +use crate::timetable::models::{Category, Course, Timetable}; + pub mod models; /// Panic if an error happened @@ -194,3 +198,48 @@ pub fn fill_hours(hours: &mut Vec) { hours.pop(); } } + +/// Names showed to the users +pub fn get_selection(data: &(&Course, String)) -> String { + let mut hours = vec![]; + fill_hours(&mut hours); + + format!( + "{} - {} {}-{}", + data.0.name, + data.1, + hours[data.0.start].split_once('-').unwrap().0, + hours[data.0.start + data.0.size - 1] + .split_once('-') + .unwrap() + .1 + ) +} + +/// Entry's name used for finding duplicates +pub fn get_entry(course: &Course) -> String { + format!("{} - {:?}", course.name, course.category) +} + +pub fn get_count<'a>( + timetable: &'a mut Timetable, + allowed_list: &'a [Category], +) -> (Vec<(&'a Course, String)>, HashMap) { + // List of courses who will be courses + let mut courses = vec![]; + + let mut counts = HashMap::new(); + timetable.1 .1.iter().for_each(|day| { + day.courses.iter().for_each(|course_opt| { + if let Some(course) = course_opt { + if allowed_list.contains(&course.category) { + courses.push((course, day.name.to_owned())); + let count = counts.entry(get_entry(course)).or_insert(0); + *count += 1; + } + } + }) + }); + + (courses, counts) +}