Skip to content

Commit

Permalink
refactor: remove repetitive impl for excel parse
Browse files Browse the repository at this point in the history
  • Loading branch information
albugowy15 committed Aug 28, 2023
1 parent 813922a commit e1ba2a0
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 275 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "auto-frs-schedule"
version = "2.1.4"
version = "2.2.4"
edition = "2021"
description = "Automatically generate TC FRS schedule from Excel file"
authors = ["Mohamad Kholid Bughowi <[email protected]>"]
Expand Down
105 changes: 58 additions & 47 deletions src/excel/excel.rs
Original file line number Diff line number Diff line change
@@ -1,63 +1,74 @@
use std::path::PathBuf;
use std::{collections::HashMap, path::PathBuf};

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

use super::Excel;

impl Excel {
pub fn new(file_path: &PathBuf, sheet_name: &str) -> Result<Self> {
pub fn new(
file_path: &PathBuf,
sheet_name: &str,
list_subject: HashMap<String, String>,
list_lecture: HashMap<String, String>,
list_session: HashMap<String, i8>,
) -> Result<Self> {
let mut excel: Xlsx<_> =
open_workbook(file_path).with_context(|| "Cannot open excel file")?;
let range = excel
.worksheet_range(sheet_name)
.context("Error opening sheet, make sure sheet name is exists")?
.with_context(|| format!("Could not read excel range from sheet {}", sheet_name))?;
Ok(Self { range })
Ok(Self {
range,
list_lecture,
list_session,
list_subject,
})
}
}

#[cfg(test)]
mod test {
use crate::excel::{Excel, IntoMap};
use std::collections::HashMap;

#[test]
fn test_parse_subject() {
let mut subject_map: HashMap<String, String> = HashMap::new();
subject_map.insert(String::from("jaringan komputer"), String::from("c636gggdd"));
assert_eq!(
Excel::subject_class_to_map("Jaringan Komputer A", &subject_map),
Some(("c636gggdd".to_string(), "A".to_string()))
);

subject_map.insert(String::from("realitas x"), String::from("377hh7cch"));
assert_eq!(
Excel::subject_class_to_map("Realitas X", &subject_map),
Some(("377hh7cch".to_string(), "-".to_string()))
);
subject_map.insert(
String::from("interaksi manusia komputer"),
String::from("wjjfhhfw888"),
);
assert_eq!(
Excel::subject_class_to_map("Interaksi Manusia Komputer D - EN", &subject_map),
Some(("wjjfhhfw888".to_string(), "D - EN".to_string()))
);
assert_eq!(
Excel::subject_class_to_map("Interaksi Manusia Komputer - RKA", &subject_map),
Some(("wjjfhhfw888".to_string(), "RKA".to_string()))
);

assert_eq!(
Excel::subject_class_to_map("Jaringan Komputer - IUP", &subject_map),
Some(("c636gggdd".to_string(), "IUP".to_string()))
);

subject_map.insert(String::from("dasar pemrograman"), String::from("cc773hhe"));
assert_eq!(
Excel::subject_class_to_map("Dasar Pemrograman F", &subject_map),
Some(("cc773hhe".to_string(), "F".to_string()))
);
}
}
// #[cfg(test)]
// mod test {
// use crate::excel::{Excel, IntoMap};
// use std::collections::HashMap;

// #[test]
// fn test_parse_subject() {
// let mut subject_map: HashMap<String, String> = HashMap::new();
// subject_map.insert(String::from("jaringan komputer"), String::from("c636gggdd"));
// assert_eq!(
// Excel::subject_class_to_map("Jaringan Komputer A", &subject_map),
// Some(("c636gggdd".to_string(), "A".to_string()))
// );

// subject_map.insert(String::from("realitas x"), String::from("377hh7cch"));
// assert_eq!(
// Excel::subject_class_to_map("Realitas X", &subject_map),
// Some(("377hh7cch".to_string(), "-".to_string()))
// );
// subject_map.insert(
// String::from("interaksi manusia komputer"),
// String::from("wjjfhhfw888"),
// );
// assert_eq!(
// Excel::subject_class_to_map("Interaksi Manusia Komputer D - EN", &subject_map),
// Some(("wjjfhhfw888".to_string(), "D - EN".to_string()))
// );
// assert_eq!(
// Excel::subject_class_to_map("Interaksi Manusia Komputer - RKA", &subject_map),
// Some(("wjjfhhfw888".to_string(), "RKA".to_string()))
// );

// assert_eq!(
// Excel::subject_class_to_map("Jaringan Komputer - IUP", &subject_map),
// Some(("c636gggdd".to_string(), "IUP".to_string()))
// );

// subject_map.insert(String::from("dasar pemrograman"), String::from("cc773hhe"));
// assert_eq!(
// Excel::subject_class_to_map("Dasar Pemrograman F", &subject_map),
// Some(("cc773hhe".to_string(), "F".to_string()))
// );
// }
// }
107 changes: 25 additions & 82 deletions src/excel/into_map.rs
Original file line number Diff line number Diff line change
@@ -1,93 +1,44 @@
use std::collections::HashMap;

use anyhow::Result;

use crate::repo::Class;

use super::{Excel, IntoMap, DAYS};
use super::{Excel, IntoMap, Parser, DAYS};

impl IntoMap for Excel {
fn subject_class_to_map(
val: &str,
subject_map: &HashMap<String, String>,
) -> Option<(String, String)> {
let splitted = val.split("-").collect::<Vec<&str>>();
let subject_name: String;
let code: String;
if splitted.len() < 2 {
let split_space = val.split_ascii_whitespace().collect::<Vec<&str>>();
let last_str = split_space.last()?.trim();
if last_str.len() == 1 && last_str <= "L" {
subject_name = split_space[0..(split_space.len() - 1)].join(" ");
code = last_str.to_string()
} else {
subject_name = split_space.join(" ");
code = "-".to_owned();
}
} else {
let last_split = splitted.last()?.trim();
if last_split.contains("EN") {
let split_space = splitted[0].split_ascii_whitespace().collect::<Vec<&str>>();
subject_name = split_space[0..(split_space.len() - 1)].join(" ");
code = format!("{} - {}", split_space.last()?, "EN");
} else {
subject_name = splitted[0].trim().to_owned();
code = splitted[1].trim().to_owned();
}
}
match subject_map.get(&subject_name.to_lowercase()) {
fn subject_with_code_to_map(&self, val: &str) -> Option<(String, String)> {
let (subject_name, code) = self.parse_subject_with_code(val)?;
match self.list_subject.get(&subject_name.to_lowercase()) {
Some(val) => Some((val.to_string(), code)),
None => None,
}
}

fn session_to_map(&self, row_idx: u32, session_map: &HashMap<String, i8>) -> Option<i8> {
let session_name = self
.range
.get_value((row_idx, 1))?
.get_string()?
.split(" - ")
.collect::<Vec<&str>>()[0];
match session_map.get(session_name) {
fn session_to_map(&self, row_idx: u32) -> Option<i8> {
let session_name = self.parse_session(row_idx)?;
match self.list_session.get(&session_name) {
Some(val) => Some(*val),
None => None,
}
}

fn lecturer_to_map(
&self,
row: u32,
col: u32,
lecturer_map: &HashMap<String, String>,
) -> Option<Vec<String>> {
let lecturer = self
.range
.get_value((row + 1, col))?
.get_string()?
.split("/")
.collect::<Vec<_>>()[2];
let lecturers_id: Vec<_> = lecturer
.split("-")
fn lecturer_to_map(&self, row: u32, col: u32) -> Option<Vec<String>> {
let lecturers = self.parse_lecturer(row, col)?;
let lecturers_id: Vec<String> = lecturers
.into_iter()
.flat_map(|lecture_code| {
let id = match lecturer_map.get(lecture_code.trim()) {
let id = match self.list_lecture.get(lecture_code.trim()) {
Some(code) => code,
None => lecturer_map.get("UNK").unwrap(),
None => self.list_lecture.get("UNK").unwrap(),
};
vec![id.to_string()]
})
.collect();

match lecturers_id.is_empty() {
true => None,
false => Some(lecturers_id),
}
}

fn parse_excel(
&self,
list_subject: &HashMap<String, String>,
list_lecture: &HashMap<String, String>,
list_session: &HashMap<String, i8>,
) -> Result<Vec<Class>> {
fn parse_excel(&self) -> Vec<Class> {
let mut list_class: Vec<Class> = Vec::with_capacity(self.range.get_size().1 as usize);

for (row_idx, row) in self.range.rows().enumerate() {
Expand All @@ -96,26 +47,19 @@ impl IntoMap for Excel {
Some(val) => val,
None => continue,
};

let (subject_id, class_code) =
match Excel::subject_class_to_map(&val, &list_subject) {
Some(val) => val,
None => continue,
};

let lecturers_id =
match self.lecturer_to_map(row_idx as u32, col_idx as u32, &list_lecture) {
Some(val) => val,
None => continue,
};

let (subject_id, class_code) = match self.subject_with_code_to_map(&val) {
Some(val) => val,
None => continue,
};
let lecturers_id = match self.lecturer_to_map(row_idx as u32, col_idx as u32) {
Some(val) => val,
None => continue,
};
let day = DAYS[row_idx / 14];

let session_id = match self.session_to_map(row_idx as u32, &list_session) {
let session_id = match self.session_to_map(row_idx as u32) {
Some(val) => val,
None => continue,
};

list_class.push(Class {
matkul_id: subject_id,
lecturers_id,
Expand All @@ -125,7 +69,6 @@ impl IntoMap for Excel {
});
}
}

Ok(list_class)
list_class
}
}
Loading

0 comments on commit e1ba2a0

Please sign in to comment.