Skip to content

Commit

Permalink
feat: LecturerSubjectSessionMap struct
Browse files Browse the repository at this point in the history
  • Loading branch information
albugowy15 committed Feb 1, 2024
1 parent 0bf5605 commit 0ff90b3
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 101 deletions.
53 changes: 17 additions & 36 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] }
cuid = "1.3.2"
clap = { version = "4.4.11", features = ["derive"] }
anyhow = "1.0.76"
sqlx = { version = "0.7", features = [ "runtime-tokio", "tls-native-tls","mysql" ] }
sqlx = { version = "0.7", features = [
"runtime-tokio",
"tls-native-tls",
"mysql",
] }
indicatif = "0.17.7"
log = "0.4.20"
env_logger = "0.10.1"
env_logger = "0.11.1"
11 changes: 2 additions & 9 deletions src/commands/compare.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use std::path::PathBuf;

use crate::{
commands::prepare_data,
db::{
repository::{
class::{ClassFromSchedule, ClassRepository},
Repository,
prepare_data, Repository,
},
Connection,
},
Expand Down Expand Up @@ -35,13 +34,7 @@ pub async fn compare_handler(file: &PathBuf, sheet: &str, outdir: &PathBuf) {
};

log::info!("Get latest schedule from Excel");
let excel = match Excel::new(
file,
sheet,
repo_data_res.0,
repo_data_res.1,
repo_data_res.2,
) {
let excel = match Excel::new(file, sheet, repo_data_res) {
Ok(excel) => excel,
Err(e) => {
log::error!("Error opening excel file: {}", e);
Expand Down
40 changes: 13 additions & 27 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
use std::{collections::HashMap, path::PathBuf};
use std::path::PathBuf;

use anyhow::Result;
use clap::Subcommand;
use sqlx::{MySql, Pool};

use crate::db::repository::{
lecturer::LecturerRepository, session::SessionRepository, subject::SubjectRepository,
Repository,
};

pub mod clean;
pub mod compare;
Expand All @@ -16,6 +9,9 @@ pub mod update;

#[derive(Subcommand)]
pub enum Commands {
#[command(
long_about = "Compares the class schedule stored in the database with the latest data from an Excel file."
)]
Compare {
#[arg(short, long, value_name = "Required for latest schedule excel file")]
file: PathBuf,
Expand All @@ -26,6 +22,9 @@ pub enum Commands {
#[arg(short, long, value_name = "Required for output path")]
outdir: PathBuf,
},
#[command(
long_about = "Parses all class data from an Excel file and subsequently updates the MySQL database. Alternatively, it provides an option to save the parsed data to an SQL file."
)]
Update {
#[arg(
short,
Expand All @@ -47,25 +46,12 @@ pub enum Commands {
)]
outdir: Option<PathBuf>,
},
#[command(
long_about = "Removes any invalid foreign keys present in the _ClassToPlan and _ClassToLecturer tables."
)]
Clean,
#[command(
long_about = "Synchronizes the taken field in the Class table and the totalSks field in the Plan table to reflect their current values."
)]
Sync,
}

pub async fn prepare_data(
pool: &Pool<MySql>,
) -> Result<(
HashMap<String, String>,
HashMap<String, String>,
HashMap<String, i8>,
)> {
log::info!("Get all subjects from DB");
let lecturer_repo = LecturerRepository::new(pool);
let subject_repo = SubjectRepository::new(pool);
let session_repo = SessionRepository::new(pool);
let (subjects, lecturers, sessions) = tokio::try_join!(
subject_repo.get_all_subjects(),
lecturer_repo.get_all_lecturers(),
session_repo.get_all_sessions()
)?;
Ok((subjects, lecturers, sessions))
}
5 changes: 2 additions & 3 deletions src/commands/update.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use std::{path::PathBuf, sync::Arc};

use crate::{
commands::prepare_data,
db::{
repository::{class::ClassRepository, Repository},
repository::{class::ClassRepository, prepare_data, Repository},
Connection,
},
utils::{
Expand All @@ -28,7 +27,7 @@ pub async fn update_handler(push: &bool, file: &PathBuf, sheet: &String, outdir:
}
};
log::info!("Parse class schedule from Excel");
let excel = match Excel::new(file, sheet, repo_data.0, repo_data.1, repo_data.2) {
let excel = match Excel::new(file, sheet, repo_data) {
Ok(excel) => excel,
Err(e) => {
log::error!(
Expand Down
29 changes: 29 additions & 0 deletions src/db/repository/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
use anyhow::Result;
use sqlx::{MySql, Pool};
use std::collections::HashMap;

use crate::db::repository::{
lecturer::LecturerRepository, session::SessionRepository, subject::SubjectRepository,
};

pub mod class;
pub mod lecturer;
Expand All @@ -10,3 +16,26 @@ pub mod subject;
pub trait Repository<'a> {
fn new(db_pool: &'a Pool<MySql>) -> Self;
}

pub struct LecturerSubjectSessionMap {
pub subjects: HashMap<String, String>,
pub lecturers: HashMap<String, String>,
pub sessions: HashMap<String, i8>,
}

pub async fn prepare_data(pool: &Pool<MySql>) -> Result<LecturerSubjectSessionMap> {
log::info!("Get all subjects from DB");
let lecturer_repo = LecturerRepository::new(pool);
let subject_repo = SubjectRepository::new(pool);
let session_repo = SessionRepository::new(pool);
let (subjects, lecturers, sessions) = tokio::try_join!(
subject_repo.get_all_subjects(),
lecturer_repo.get_all_lecturers(),
session_repo.get_all_sessions()
)?;
Ok(LecturerSubjectSessionMap {
subjects,
lecturers,
sessions,
})
}
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use auto_frs_schedule::{
use clap::Parser;

#[derive(Parser)]
#[command(version, about)]
#[command(version, author, about)]
struct Cli {
#[command(subcommand)]
command: Commands,
Expand Down
1 change: 0 additions & 1 deletion src/utils/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ pub fn setup_env() {
env::set_var("AUTO_FRS_SCHEDULE_LOG_LEVEL", "INFO");
env::set_var("AUTO_FRS_SCHEDULE_LOG_STYLE", "AUTO");
Builder::from_env(env)
.format_timestamp(None)
.format_module_path(false)
.format_target(false)
.init();
Expand Down
15 changes: 5 additions & 10 deletions src/utils/excel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,32 @@ pub mod retrieve;
pub mod schedule_parser;
pub mod schedule_parser_with_id;

use std::collections::HashMap;
use std::path::PathBuf;

use anyhow::{Context, Result};
use calamine::{open_workbook, DataType, Range, Reader, Xlsx};

use crate::db::repository::LecturerSubjectSessionMap;

pub const DAYS: [&str; 5] = ["Senin", "Selasa", "Rabu", "Kamis", "Jum'at"];

pub struct Excel {
range: Range<DataType>,
subject_to_id: HashMap<String, String>,
lecturer_to_id: HashMap<String, String>,
session_to_id: HashMap<String, i8>,
lecturer_subjects_session_map: LecturerSubjectSessionMap,
}

impl Excel {
pub fn new(
file_path: &PathBuf,
sheet_name: &str,
subject_to_id: HashMap<String, String>,
lecturer_to_id: HashMap<String, String>,
session_to_id: HashMap<String, i8>,
lecturer_subjects_session_map: LecturerSubjectSessionMap,
) -> Result<Self> {
let mut excel: Xlsx<_> =
open_workbook(file_path).with_context(|| "Cannot open excel file")?;
let range = excel.worksheet_range(sheet_name)?;
Ok(Self {
range,
subject_to_id,
lecturer_to_id,
session_to_id,
lecturer_subjects_session_map,
})
}
}
Expand Down
22 changes: 16 additions & 6 deletions src/utils/excel/schedule_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use super::{AsStringParser, Excel, Parser, Retrieve, ScheduleParser, SessionPars
impl AsStringParser for Excel {
fn get_subject_with_code(&self, val: &str) -> Option<(String, String)> {
let (subject_name, code) = Self::parse_subject_with_code_2(val)?;
self.subject_to_id
self.lecturer_subjects_session_map
.subjects
.get(&subject_name.to_lowercase())
.map(|_| (subject_name, code))
}
Expand All @@ -16,7 +17,11 @@ impl AsStringParser for Excel {
let lecturers_code: Vec<String> = lecturers
.into_iter()
.flat_map(|lecture_code| {
let code = match self.lecturer_to_id.contains_key(lecture_code.trim()) {
let code = match self
.lecturer_subjects_session_map
.lecturers
.contains_key(lecture_code.trim())
{
true => lecture_code.trim().to_string(),
false => "UNK".to_string(),
};
Expand All @@ -35,7 +40,8 @@ impl SessionParser<String> for Excel {
fn get_session(&self, row_idx: u32) -> Option<String> {
let session_str = self.retrieve_session(row_idx)?;
let session_name = Excel::parse_session(&session_str)?;
self.session_to_id
self.lecturer_subjects_session_map
.sessions
.contains_key(&session_name)
.then_some(session_name)
}
Expand Down Expand Up @@ -82,6 +88,8 @@ mod tests {

use calamine::Range;

use crate::db::repository::LecturerSubjectSessionMap;

use super::*;

#[test]
Expand All @@ -94,9 +102,11 @@ mod tests {
);

let excel = Excel {
subject_to_id,
lecturer_to_id: HashMap::new(),
session_to_id: HashMap::new(),
lecturer_subjects_session_map: LecturerSubjectSessionMap {
subjects: subject_to_id,
lecturers: HashMap::new(),
sessions: HashMap::new(),
},
range: Range::new((0, 0), (100, 100)),
};

Expand Down
Loading

0 comments on commit 0ff90b3

Please sign in to comment.