mirror of
https://github.com/n08i40k/schedule-parser-rusted.git
synced 2025-12-06 17:57:47 +03:00
Compare commits
6 Commits
release/v0
...
d75d3fbc97
| Author | SHA1 | Date | |
|---|---|---|---|
|
d75d3fbc97
|
|||
|
|
627cf1a74e | ||
| b508db693e | |||
| 436d08a56a | |||
| aa2618c5f5 | |||
| f0a951ad38 |
6
.github/dependabot.yml
vendored
Normal file
6
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "cargo"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
25
.github/workflows/test.yml
vendored
Normal file
25
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
name: Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "master" ]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
CARGO_TERM_COLOR: always
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Build
|
||||||
|
run: cargo build --verbose
|
||||||
|
- name: Run tests
|
||||||
|
run: cargo test --verbose -p schedule_parser
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
/target
|
/target
|
||||||
.~*.xls
|
.~*.xls
|
||||||
schedule.json
|
schedule.json
|
||||||
|
teachers.json
|
||||||
1211
Cargo.lock
generated
1211
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -3,13 +3,11 @@ members = ["lib/schedule_parser"]
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "schedule-parser-rusted"
|
name = "schedule-parser-rusted"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "4.10.2"
|
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
serde_repr = "0.1.20"
|
|
||||||
serde_json = "1.0.140"
|
serde_json = "1.0.140"
|
||||||
schedule_parser = { path = "./lib/schedule_parser" }
|
schedule_parser = { path = "./lib/schedule_parser" }
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# API для получения расписания политехникума
|
||||||
|
|
||||||
|
[](https://github.com/n08i40k/schedule-parser-rusted/actions/workflows/test.yml)
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "schedule_parser"
|
name = "schedule_parser"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::LessonParseResult::{Lessons, Street};
|
use crate::LessonParseResult::{Lessons, Street};
|
||||||
use crate::schema::LessonType::Break;
|
use crate::schema::LessonType::Break;
|
||||||
use crate::schema::{Day, Group, Lesson, LessonSubGroup, LessonTime, LessonType};
|
use crate::schema::{Day, Lesson, LessonSubGroup, LessonTime, LessonType, ScheduleEntity};
|
||||||
use calamine::{Reader, Xls, open_workbook};
|
use calamine::{Reader, Xls, open_workbook};
|
||||||
use chrono::{Duration, NaiveDateTime};
|
use chrono::{Duration, NaiveDateTime};
|
||||||
use fuzzy_matcher::FuzzyMatcher;
|
use fuzzy_matcher::FuzzyMatcher;
|
||||||
@@ -470,7 +470,80 @@ fn parse_name_and_subgroups(name: &String) -> (String, Vec<LessonSubGroup>) {
|
|||||||
(lesson_name, subgroups)
|
(lesson_name, subgroups)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_xls(path: &Path) -> HashMap<String, Group> {
|
fn convert_groups_to_teachers(
|
||||||
|
groups: &HashMap<String, ScheduleEntity>,
|
||||||
|
) -> HashMap<String, ScheduleEntity> {
|
||||||
|
let mut teachers: HashMap<String, ScheduleEntity> = HashMap::new();
|
||||||
|
|
||||||
|
let empty_days: Vec<Day> = groups
|
||||||
|
.values()
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.days
|
||||||
|
.iter()
|
||||||
|
.map(|day| Day {
|
||||||
|
name: day.name.clone(),
|
||||||
|
street: day.street.clone(),
|
||||||
|
date: day.date.clone(),
|
||||||
|
lessons: vec![],
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for group in groups.values() {
|
||||||
|
for (index, day) in group.days.iter().enumerate() {
|
||||||
|
for group_lesson in &day.lessons {
|
||||||
|
if group_lesson.lesson_type == Break {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if group_lesson.subgroups.is_none() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let subgroups = group_lesson.subgroups.as_ref().unwrap();
|
||||||
|
|
||||||
|
for subgroup in subgroups {
|
||||||
|
if subgroup.teacher == "Ошибка в расписании" {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !teachers.contains_key(&subgroup.teacher) {
|
||||||
|
teachers.insert(
|
||||||
|
subgroup.teacher.clone(),
|
||||||
|
ScheduleEntity {
|
||||||
|
name: subgroup.teacher.clone(),
|
||||||
|
days: empty_days.to_vec(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let teacher_day = teachers
|
||||||
|
.get_mut(&subgroup.teacher)
|
||||||
|
.unwrap()
|
||||||
|
.days
|
||||||
|
.get_mut(index)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
teacher_day.lessons.push({
|
||||||
|
let mut lesson = group_lesson.clone();
|
||||||
|
lesson.group = Some(group.name.clone());
|
||||||
|
|
||||||
|
lesson
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
teachers
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_xls(
|
||||||
|
path: &Path,
|
||||||
|
) -> (
|
||||||
|
HashMap<String, ScheduleEntity>,
|
||||||
|
HashMap<String, ScheduleEntity>,
|
||||||
|
) {
|
||||||
let mut workbook: Xls<_> = open_workbook(path).expect("Can't open workbook");
|
let mut workbook: Xls<_> = open_workbook(path).expect("Can't open workbook");
|
||||||
|
|
||||||
let worksheet: WorkSheet = workbook
|
let worksheet: WorkSheet = workbook
|
||||||
@@ -482,13 +555,13 @@ pub fn parse_xls(path: &Path) -> HashMap<String, Group> {
|
|||||||
|
|
||||||
let (days_markup, groups_markup) = parse_skeleton(&worksheet);
|
let (days_markup, groups_markup) = parse_skeleton(&worksheet);
|
||||||
|
|
||||||
let mut groups: HashMap<String, Group> = HashMap::new();
|
let mut groups: HashMap<String, ScheduleEntity> = HashMap::new();
|
||||||
let mut days_times: Vec<Vec<InternalTime>> = Vec::new();
|
let mut days_times: Vec<Vec<InternalTime>> = Vec::new();
|
||||||
|
|
||||||
let saturday_end_row = worksheet.end().unwrap().0;
|
let saturday_end_row = worksheet.end().unwrap().0;
|
||||||
|
|
||||||
for group_markup in groups_markup {
|
for group_markup in groups_markup {
|
||||||
let mut group = Group {
|
let mut group = ScheduleEntity {
|
||||||
name: group_markup.name,
|
name: group_markup.name,
|
||||||
days: Vec::new(),
|
days: Vec::new(),
|
||||||
};
|
};
|
||||||
@@ -612,7 +685,7 @@ pub fn parse_xls(path: &Path) -> HashMap<String, Group> {
|
|||||||
groups.insert(group.name.clone(), group);
|
groups.insert(group.name.clone(), group);
|
||||||
}
|
}
|
||||||
|
|
||||||
groups
|
(convert_groups_to_teachers(&groups), groups)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -622,6 +695,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn it_works() {
|
fn it_works() {
|
||||||
let result = parse_xls(Path::new("../../schedule.xls"));
|
let result = parse_xls(Path::new("../../schedule.xls"));
|
||||||
assert_ne!(result.len(), 0);
|
|
||||||
|
assert_ne!(result.0.len(), 0);
|
||||||
|
assert_ne!(result.1.len(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
|
||||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct LessonTime {
|
pub struct LessonTime {
|
||||||
pub start: DateTime<Utc>,
|
pub start: DateTime<Utc>,
|
||||||
pub end: DateTime<Utc>,
|
pub end: DateTime<Utc>,
|
||||||
@@ -22,7 +22,7 @@ pub enum LessonType {
|
|||||||
ExamDefault, // Экзамен
|
ExamDefault, // Экзамен
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct LessonSubGroup {
|
pub struct LessonSubGroup {
|
||||||
pub number: u8,
|
pub number: u8,
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ pub struct LessonSubGroup {
|
|||||||
pub teacher: String,
|
pub teacher: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct Lesson {
|
pub struct Lesson {
|
||||||
/**
|
/**
|
||||||
* Тип занятия
|
* Тип занятия
|
||||||
@@ -67,7 +67,7 @@ pub struct Lesson {
|
|||||||
pub group: Option<String>,
|
pub group: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct Day {
|
pub struct Day {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ pub struct Day {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct Group {
|
pub struct ScheduleEntity {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
||||||
pub days: Vec<Day>,
|
pub days: Vec<Day>,
|
||||||
@@ -90,8 +90,18 @@ pub struct Schedule {
|
|||||||
#[serde(rename = "updatedAt")]
|
#[serde(rename = "updatedAt")]
|
||||||
pub updated_at: DateTime<Utc>,
|
pub updated_at: DateTime<Utc>,
|
||||||
|
|
||||||
pub groups: HashMap<String, Group>,
|
pub groups: HashMap<String, ScheduleEntity>,
|
||||||
|
|
||||||
#[serde(rename = "updatedGroups")]
|
#[serde(rename = "updatedGroups")]
|
||||||
pub updated_groups: Vec<Vec<usize>>,
|
pub updated_groups: Vec<Vec<usize>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct TeacherSchedule {
|
||||||
|
#[serde(rename = "updatedAt")]
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
|
||||||
|
pub teacher: ScheduleEntity,
|
||||||
|
|
||||||
|
pub updated: Vec<usize>,
|
||||||
|
}
|
||||||
|
|||||||
12
src/main.rs
12
src/main.rs
@@ -3,13 +3,21 @@ use std::path::Path;
|
|||||||
use schedule_parser::parse_xls;
|
use schedule_parser::parse_xls;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let groups = parse_xls(Path::new("./schedule.xls"));
|
let (teachers, groups) = parse_xls(Path::new("./schedule.xls"));
|
||||||
|
|
||||||
fs::write(
|
fs::write(
|
||||||
"./schedule.json",
|
"./schedule.json",
|
||||||
serde_json::to_string_pretty(&groups)
|
serde_json::to_string_pretty(&groups)
|
||||||
.expect("Failed to serialize schedule!")
|
.expect("Failed to serialize schedule")
|
||||||
.as_bytes(),
|
.as_bytes(),
|
||||||
)
|
)
|
||||||
.expect("Failed to write schedule");
|
.expect("Failed to write schedule");
|
||||||
|
|
||||||
|
fs::write(
|
||||||
|
"./teachers.json",
|
||||||
|
serde_json::to_string_pretty(&teachers)
|
||||||
|
.expect("Failed to serialize teachers schedule")
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
|
.expect("Failed to write teachers schedule");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user