diff --git a/Cargo.lock b/Cargo.lock index 88c35c8..8c4e8e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,7 +88,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -98,7 +98,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -164,6 +164,7 @@ version = "0.5.0-alpha" dependencies = [ "chrono", "clap", + "dialoguer", "ics", "regex", "reqwest", @@ -198,7 +199,7 @@ dependencies = [ "js-sys", "num-traits", "wasm-bindgen", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -247,6 +248,19 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "console" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.45.0", +] + [[package]] name = "core-foundation" version = "0.9.3" @@ -297,6 +311,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dialoguer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" +dependencies = [ + "console", + "shell-words", + "tempfile", + "thiserror", + "zeroize", +] + [[package]] name = "dtoa" version = "1.0.9" @@ -318,6 +345,12 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591" +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encoding_rs" version = "0.8.33" @@ -335,7 +368,7 @@ checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" dependencies = [ "errno-dragonfly", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -743,7 +776,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "wasi", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -868,7 +901,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -1126,7 +1159,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1141,7 +1174,7 @@ version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1261,6 +1294,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -1308,7 +1347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1381,7 +1420,7 @@ dependencies = [ "fastrand", "redox_syscall", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1395,6 +1434,26 @@ dependencies = [ "utf-8", ] +[[package]] +name = "thiserror" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.31", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -1426,7 +1485,7 @@ dependencies = [ "signal-hook-registry", "socket2 0.5.3", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1687,7 +1746,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", ] [[package]] @@ -1696,7 +1764,22 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -1705,51 +1788,93 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -1763,5 +1888,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ "cfg-if", - "windows-sys", + "windows-sys 0.48.0", ] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" diff --git a/Cargo.toml b/Cargo.toml index 483cca5..bea3741 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,4 @@ chrono = "0.4.28" ics = "0.5" uuid = { version = "1.4", features = ["v4", "fast-rng"] } clap = { version = "4.4", features = ["derive"] } +dialoguer = "0.11" diff --git a/src/filter.rs b/src/filter.rs new file mode 100644 index 0000000..24ece05 --- /dev/null +++ b/src/filter.rs @@ -0,0 +1,108 @@ +use std::collections::HashMap; + +use dialoguer::MultiSelect; + +use crate::timetable::models::Course; +use crate::timetable::models::Timetable; +use crate::timetable::models::Type; + +const DISCLAIMER: &str = "(selection avec ESPACE, ENTRER pour valider)"; + +/// Filter the timetable +pub fn timetable(timetable: Timetable) -> Timetable { + let mut my_timetable = timetable; + + /* courses(&mut my_timetable); */ + tdtp(&mut my_timetable); + + my_timetable +} + +/// Exclude some courses +fn courses(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 multiples TD/TP +fn tdtp(timetable: &mut Timetable) { + let get_entry = |course: &Course| format!("{} - {:?}", course.name, course.typee); + let mut td_or_tp = 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 { + match course.typee { + Type::TD | Type::TP => { + td_or_tp.push(course); + let count = counts.entry(get_entry(course)).or_insert(0); + *count += 1; + } + _ => (), + } + } + }) + }); + // Keep only elements who have multiples TD/TP + td_or_tp.retain(|&course| *counts.get(&get_entry(course)).unwrap() > 1); + + let multiselected = td_or_tp + .iter() + .map(|el| format!("{} - {}", el.name, el.size)) + .collect::>(); + + let defaults = vec![true; multiselected.len()]; + let selections = MultiSelect::new() + .with_prompt(format!("Choisis tes horaires de TD/TP {}", 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 + }); + } +} diff --git a/src/main.rs b/src/main.rs index a2d7b70..f3e1e90 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use clap::Parser; use regex::Regex; +mod filter; mod ics; mod info; mod timetable; @@ -49,7 +50,9 @@ async fn main() { let user_agent = format!("cal7tor/{}", env!("CARGO_PKG_VERSION")); println!("Récupération de l'emploi du temps des M{}...", level,); - let timetable = timetable::timetable(level, args.semester, args.year, &user_agent).await; + let mut timetable = timetable::timetable(level, args.semester, args.year, &user_agent).await; + + timetable = filter::timetable(timetable); println!("Récupération des informations par rapport à l'année..."); let info = info::info(level, args.semester, args.year, &user_agent).await; diff --git a/src/timetable/models.rs b/src/timetable/models.rs index 0091185..77c2d71 100644 --- a/src/timetable/models.rs +++ b/src/timetable/models.rs @@ -1,11 +1,11 @@ -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub enum Type { Cours, TP, TD, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct Course { /// Type du cours pub typee: Type, @@ -37,7 +37,7 @@ pub struct Course { pub dtend: Option>, } -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct Day { /// Day's name pub name: String,