diff --git a/src/api/mod.rs b/src/api/mod.rs index b016ecc..1e5e90a 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -11,7 +11,7 @@ use scraper::{Html, Selector}; use serde::Deserialize; use serde_json::json; use sha1::{Digest, Sha1}; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::ops::Range; use std::{fs, process::Command}; @@ -21,7 +21,9 @@ pub fn get_routes() -> Router { Router::new() .route("/pdf", get(pdf)) .route("/classi", get(get_classes)) - .route("/professori", get(get_teachers)), + .route("/professori", get(get_teachers)) + .route("/classe", get(get_class)) + .route("/professore", get(get_teacher)), ) } @@ -94,7 +96,7 @@ pub struct Header { weekdays: HashMap>, } -pub async fn get_classes(Query(params): Query) -> impl IntoResponse { +pub async fn get_class(Query(params): Query) -> impl IntoResponse { let filename = match download_pdf(params.id).await { Ok(x) => x, Err(_) => { @@ -136,7 +138,7 @@ pub struct FilterByClassQuery { classe: String, } -pub async fn get_teachers(Query(params): Query) -> impl IntoResponse { +pub async fn get_teacher(Query(params): Query) -> impl IntoResponse { let filename = match download_pdf(params.id).await { Ok(x) => x, Err(_) => { @@ -222,3 +224,106 @@ pub fn get_header(record: &StringRecord) -> Header { weekdays, } } + +#[derive(Deserialize)] +pub struct GetTeachersQuery { + id: u8, +} + +pub async fn get_teachers(Query(params): Query) -> impl IntoResponse { + let filename = match download_pdf(params.id).await { + Ok(x) => x, + Err(_) => { + return ( + StatusCode::UNPROCESSABLE_ENTITY, + Json(json!({ "errore": "ID non valido"})), + ) + } + }; + + let csv_content = fs::read_to_string(&filename).unwrap(); + let mut rdr = csv::Reader::from_reader(csv_content.as_bytes()); + let header = get_header(rdr.headers().unwrap()); + + let mut teachers = Vec::new(); + + for record in rdr.records() { + let record = match record { + Ok(x) => x, + Err(_) => { + return ( + StatusCode::UNPROCESSABLE_ENTITY, + Json(json!({ "errore": "Formato non supportato"})), + ) + } + }; + + if let Some(teacher) = record.get(header.teacher as usize) { + if !teacher.is_empty() { + teachers.push(teacher.to_owned()); + } + } + } + + if !teachers.is_empty() { + (StatusCode::OK, Json(json!(teachers))) + } else { + ( + StatusCode::UNPROCESSABLE_ENTITY, + Json(json!({ "errore": "classe non trovata"})), + ) + } +} + +#[derive(Deserialize)] +pub struct GetClassesQuery { + id: u8, +} + +fn is_valid_class(class: &str) -> bool { + class.len() == 5 + && class.chars().next().unwrap().is_digit(6) + && class.chars().skip(1).all(|x| x.is_alphabetic()) +} + +pub async fn get_classes(Query(params): Query) -> impl IntoResponse { + let filename = match download_pdf(params.id).await { + Ok(x) => x, + Err(_) => { + return ( + StatusCode::UNPROCESSABLE_ENTITY, + Json(json!({ "errore": "ID non valido"})), + ) + } + }; + let csv_content = fs::read_to_string(&filename).unwrap(); + + let mut rdr = csv::Reader::from_reader(csv_content.as_bytes()); + let header = get_header(rdr.headers().unwrap()); + + let mut classes: Vec>> = vec![HashMap::new(); 5]; + + for record in rdr.records() { + let record = record.unwrap(); + for (i, cell) in record.iter().enumerate() { + for (_, range) in header.weekdays.clone() { + if range.contains(&i) && is_valid_class(cell) { + let value = classes + [cell.chars().next().unwrap().to_digit(6).unwrap() as usize - 1usize] + .entry(cell.chars().nth(1).unwrap()) + .or_default(); + value.insert(cell[2..].to_string().to_lowercase()); + } + } + } + } + + if classes.is_empty() { + ( + StatusCode::UNPROCESSABLE_ENTITY, + Json(json!({ "errore": "classe non trovata"})), + ) + } else { + (StatusCode::OK, Json(json!(classes))) + } +}