cal7tor/src/filter.rs
2024-01-01 12:09:44 +01:00

157 lines
4.9 KiB
Rust

use dialoguer::MultiSelect;
use crate::timetable::models::Category;
use crate::timetable::models::Timetable;
use crate::utils::get_count;
use crate::utils::get_entry;
use crate::utils::get_selection;
const DISCLAIMER: &str = "(selection avec ESPACE, ENTRER pour valider)";
/// Filter the timetable
pub fn timetable(timetable: Timetable) -> Timetable {
let mut my_timetable = timetable;
choice(&mut my_timetable);
courses(&mut my_timetable);
tdtp(&mut my_timetable);
my_timetable
}
/// Exclude some courses
fn choice(timetable: &mut Timetable) {
let mut multiselected = vec![];
timetable.1 .1.iter().for_each(|day| {
day.courses.iter().for_each(|course_opt| {
if let Some(course) = course_opt {
if !multiselected.contains(&course.name) {
multiselected.push(course.name.to_owned());
}
}
})
});
let defaults = vec![true; multiselected.len()];
let selections = MultiSelect::new()
.with_prompt(format!("Choisis tes matières {}", DISCLAIMER))
.items(&multiselected[..])
.defaults(&defaults[..])
.interact()
.unwrap();
for day in &mut timetable.1 .1 {
day.courses.retain(|course_opt| {
if let Some(course) = course_opt {
// Remove courses not followed
for i in &selections {
if course.name == multiselected[*i] {
return true;
}
}
}
false
});
}
}
/// Filter the multiple courses
fn courses(timetable: &mut Timetable) {
// 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);
let mut multiselected: Vec<String> = courses.iter().map(get_selection).collect();
multiselected.sort();
let mut selections = vec![];
if !multiselected.is_empty() {
let defaults = vec![false; multiselected.len()];
selections = MultiSelect::new()
.with_prompt(format!("Choisis tes horaires de Cours {}", DISCLAIMER))
.items(&multiselected[..])
.defaults(&defaults[..])
.interact()
.unwrap();
}
// Keep only wanted courses
for day in &mut timetable.1 .1 {
day.courses.retain(|course_opt| {
if let Some(course) = course_opt {
// Keep if it's a TD/TP
if course.category == Category::TD || course.category == Category::TP {
return true;
}
// Keep if only one slot is available
if *counts.get(&get_entry(course)).unwrap() == 1 {
return true;
}
// Keep only chosen courses if multiple was available
for i in &selections {
if get_selection(&(course, day.name.to_owned())) == multiselected[*i] {
return true;
}
}
}
false
});
}
}
/// Filter the multiples TD/TP
fn tdtp(timetable: &mut Timetable) {
// 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);
let mut multiselected: Vec<String> = td_or_tp.iter().map(get_selection).collect();
multiselected.sort();
let mut selections = vec![];
if !multiselected.is_empty() {
let defaults = vec![false; multiselected.len()];
selections = MultiSelect::new()
.with_prompt(format!("Choisis tes horaires de TD/TP {}", DISCLAIMER))
.items(&multiselected[..])
.defaults(&defaults[..])
.interact()
.unwrap();
}
// Keep only wanted courses
for day in &mut timetable.1 .1 {
day.courses.retain(|course_opt| {
if let Some(course) = course_opt {
// Keep if it's a course
if course.category == Category::Cours {
return true;
}
// Keep if only one slot is available of the TD/TP
if *counts.get(&get_entry(course)).unwrap() == 1 {
return true;
}
// 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;
}
}
}
false
});
}
}