diff --git a/src/main.rs b/src/main.rs index b1393aa..1f59e5e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,10 +27,6 @@ struct Args { #[clap(short, long, value_name = "FILE NAME")] export: Option, - /// Size of cell of the timetable (irrelevant when exporting) - #[clap(short, long, value_name = "CELL LENGTH", default_value_t = 35)] - cl: usize, - /// Doesn't distinguish TD from TP #[clap(short, long)] td_are_tp: bool, @@ -88,10 +84,8 @@ async fn main() { println!("Fichier .ICS construit et exporté => {filename}"); } else { - println!("\x1b[93mNOTICE: IT WON'T WORK!!!\x1b[0m"); // Show the calendar println!("Affichage..."); - timetable::display(&timetable, args.cl); - println!("Vous devrez peut-être mettre votre terminal en plein écran si ce n'est pas déjà le cas."); + timetable::display(&timetable); } } diff --git a/src/timetable.rs b/src/timetable.rs index d56bf92..e652875 100644 --- a/src/timetable.rs +++ b/src/timetable.rs @@ -6,8 +6,8 @@ use scraper::Selector; use std::{collections::HashMap, sync::Arc}; use crate::utils::{ - self, get_hours, get_semester, get_webpage, get_year, - models::{Info, InfoList, Position, TabChar}, + format_time_slot, get_hours, get_semester, get_webpage, get_year, + models::{Info, InfoList}, Capitalize, }; @@ -271,101 +271,28 @@ fn add_courses( } /// Display the timetable -pub fn display(timetable: &(Arc<[String]>, (usize, Vec)), cell_length: usize) { - // Cell length for hours - let clh = 11; - // Cell number - let cn = 6; - // 3/4 of cell length - let quarter = (3 * cell_length) / 4; +pub fn display(timetable: &(Arc<[String]>, (usize, Vec))) { + for day in &timetable.1 .1 { + for (index, course_option) in day.courses.iter().enumerate() { + if let Some(course) = course_option { + if index == 0 { + println!("\n{}:", day.name); + } - let sep = TabChar::Bv.val(); - - // Top of the tab - utils::line_table(clh, cell_length, cn, &Position::Top, &HashMap::new()); - - // First empty case - print!("{}{:^clh$}{}", sep, "", sep); - - // Print day's of the week - let mut days = HashMap::new(); - for (i, data) in timetable.1 .1.iter().enumerate() { - days.insert(i, &data.name); - print!("{:^cell_length$}{}", &data.name, sep); - } - - // Store the data of the course for utils::line_table - let mut next_skip = HashMap::new(); - // For each hours -- i the hour's number - for (i, hour) in timetable.0.iter().enumerate() { - // Draw separator line - utils::line_table(clh, cell_length, cn, &Position::Middle, &next_skip); - - // Reset - next_skip = HashMap::new(); - - // Print hour - print!("{sep}{hour:^clh$}"); - - // For all the days - `j` the day's number - for (j, day) in timetable.1 .1.iter().enumerate() { - // True if we found something about the slot we are looking for - let mut info_slot = false; - - // For all the courses of each days - `k` the possible course.start - for (k, course_opt) in day.courses.iter().enumerate() { - match course_opt { - // If there is a course - Some(course) => { - // Check the course's hour - if i == course.start { - // If the course uses more than one time slot - if course.size > 1 { - // If the data is too long - if course.name.len() > quarter { - let data = utils::split_half(&course.name); - next_skip.insert(j, data.1.trim()); - print!("{}{:^cell_length$}", sep, data.0.trim()); - } else { - next_skip.insert(j, &course.name); - print!("{}{:^cell_length$}", sep, ""); - } - info_slot = true; - break; - } - - // Else simply print the course - // If the data is too long - if course.name.len() > quarter { - print!("{}{:^cell_length$}", sep, utils::etc_str(&course.name)); - } else { - print!("{}{:^cell_length$}", sep, &course.name); - } - info_slot = true; - break; - } - } - // If no course was found - None => { - // Verify the "no course" is in the correct day and hour - if *days.get(&j).unwrap() == &day.name.to_string() && k == i { - // If yes print empty row because there is no course - print!("{}{:^cell_length$}", sep, ""); - info_slot = true; - break; - } - // Else it was a course of another day/time - } - }; - } - if !info_slot { - // We found nothing about the slot because the precedent course - // takes more place than one slot - print!("{}{:^cell_length$}", sep, ""); + println!( + " {} - {} : {} ({}) // {}", + format_time_slot(course.start, course.size), + course + .category + .iter() + .map(std::string::ToString::to_string) + .collect::>() + .join(", "), + course.name, + course.room, + course.professor.as_deref().unwrap_or("N/A"), + ); } } - print!("{sep}"); } - // Bottom of the table - utils::line_table(clh, cell_length, cn, &Position::Bottom, &HashMap::new()); } diff --git a/src/utils.rs b/src/utils.rs index 0df306a..47bd609 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -16,102 +16,6 @@ pub fn check_errors(html: &String, loc: &str) { } } -/// Print a line for the table -pub fn line_table( - cell_length_hours: usize, - cell_length: usize, - number_cell: usize, - pos: &models::Position, - skip_with: &std::collections::HashMap, -) { - // Left side - let ls = match pos { - models::Position::Top => models::TabChar::Jtl.val(), - models::Position::Middle => models::TabChar::Jl.val(), - models::Position::Bottom => models::TabChar::Jbl.val(), - }; - - // Middle - let ms = match pos { - models::Position::Top => models::TabChar::Jtb.val(), - models::Position::Middle => models::TabChar::Jm.val(), - models::Position::Bottom => models::TabChar::Jtt.val(), - }; - - // Right side - let rs = match pos { - models::Position::Top => models::TabChar::Jtr.val(), - models::Position::Middle => models::TabChar::Jr.val(), - models::Position::Bottom => models::TabChar::Jbr.val(), - }; - - // Right side before big cell - let rs_bbc = models::TabChar::Jr.val(); - // Right side big cell before big cell - let rsbc_bbc = models::TabChar::Bv.val(); - // Right side big cell - let rsbc = models::TabChar::Jl.val(); - - let line = models::TabChar::Bh.val().to_string().repeat(cell_length); - let line_h = models::TabChar::Bh - .val() - .to_string() - .repeat(cell_length_hours); - - // Hours column - match skip_with.get(&0) { - Some(_) => print!("\n{ls}{line_h}{rs_bbc}"), - None => print!("\n{ls}{line_h}{ms}"), - }; - - // Courses columns - let range = number_cell - 1; - let mut last_day = false; - for i in 0..range { - // Check if it's a big cell - if i == range - 1 { - // Friday only - if let Some(text) = skip_with.get(&i) { - println!("{text:^cell_length$}{rsbc_bbc}"); - last_day = true; - } - } else { - match skip_with.get(&i) { - Some(text) => match skip_with.get(&(i + 1)) { - // Match check if the next cell will be big - Some(_) => print!("{text:^cell_length$}{rsbc_bbc}"), - None => print!("{text:^cell_length$}{rsbc}"), - }, - None => match skip_with.get(&(i + 1)) { - // Match check if the next cell will be big - Some(_) => print!("{line}{rs_bbc}"), - None => print!("{line}{ms}"), - }, - } - } - } - if !last_day { - println!("{line}{rs}"); - } -} - -// Split a string in half with respect of words -pub fn split_half(text: &str) -> (&str, &str) { - let mid = text.len() / 2; - for (i, j) in (mid..text.len()).enumerate() { - if text.as_bytes()[j] == b' ' { - return text.split_at(mid + i); - } - } - - text.split_at(mid) -} - -// Reduce size of string by adding etc. to it, and cutting some info -pub fn etc_str(text: &str) -> String { - format!("{}...", split_half(text).0.trim()) -} - /// Get timetable webpage pub async fn get_webpage( level: i8, @@ -257,3 +161,12 @@ pub fn get_count<'a>( (courses, counts) } + +pub fn format_time_slot(start: usize, size: usize) -> String { + let start_hour = 8 + (start * 15) / 60; + let start_minute = (start * 15) % 60; + let end_hour = start_hour + (size * 15) / 60; + let end_minute = (start_minute + (size * 15)) % 60; + + format!("{start_hour:02}h{start_minute:02}-{end_hour:02}h{end_minute:02}") +} diff --git a/src/utils/models.rs b/src/utils/models.rs index 977581b..1f8b49f 100644 --- a/src/utils/models.rs +++ b/src/utils/models.rs @@ -2,58 +2,6 @@ use std::collections::HashMap; use chrono::Utc; -/// Collection of char for the table -pub enum TabChar { - /// Vertical bar - Bv, - /// Horizontal bar - Bh, - /// Joint left - Jl, - /// Joint right - Jr, - /// Joint bottom left - Jbl, - /// Joint bottom right - Jbr, - /// Joint top left - Jtl, - /// Joint top right - Jtr, - /// Joint to top - Jtt, - /// Joint to bottom - Jtb, - /// Joint of the middle - Jm, -} - -impl TabChar { - /// Value of the element - pub fn val(&self) -> char { - match *self { - Self::Bv => '│', - Self::Bh => '─', - Self::Jl => '├', - Self::Jr => '┤', - Self::Jbl => '└', - Self::Jbr => '┘', - Self::Jtl => '┌', - Self::Jtr => '┐', - Self::Jtt => '┴', - Self::Jtb => '┬', - Self::Jm => '┼', - } - } -} - -/// Position for lines inside the table -pub enum Position { - Top, - Middle, - Bottom, -} - pub type InfoList = Vec<(chrono::DateTime, i64)>; pub struct InfoType {