use std::{option::Option, vec::Vec};
use serde::{Deserialize, Serialize};
use serde_with::serde_conv;
use crate::{
mycqu::course::CourseDayTime,
utils::{ApiModel, datetimes::parse_weekday, models::Period},
};
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
pub struct EnrollCourseTimetable {
pub weeks: Vec<Period>,
pub time: Option<CourseDayTime>,
pub pos: Option<String>,
}
serde_conv!(
pub(crate) EnrollCourseTimetableHelper,
Vec<EnrollCourseTimetable>,
|timetable: &Vec<EnrollCourseTimetable>| {
let mut result = String::new();
for (i, item) in timetable.iter().enumerate() {
if i > 0 {
result.push(';');
}
result.push_str(
&item
.weeks
.iter()
.map(|p| p.to_string())
.collect::<Vec<String>>()
.join(","),
);
result.push_str("周");
if let Some(time) = &item.time {
result.push_str(&format!(
" 星期{} {}-{}小节",
time.short_weekday(),
time.period.start,
time.period.end
));
}
if let Some(pos) = &item.pos {
result.push_str(&format!(" &{}", pos));
}
}
result
},
|timetable: &str| -> Result<_, std::convert::Infallible> {
Ok(EnrollCourseTimetable::parse_timetable_str(timetable))
}
);
impl EnrollCourseTimetable {
pub fn parse_timetable_str(data: &str) -> Vec<EnrollCourseTimetable> {
data.split(';')
.map(|item| EnrollCourseTimetable {
weeks: regex!(r"^(.*)周")
.captures(item)
.map(|mat| Period::parse_week_str(&mat[1]))
.unwrap_or(Vec::new()),
time: regex!(r"星期(.) ([0-9])-([0-9])小节")
.captures(item)
.and_then(|mat| {
let weekday = parse_weekday(&mat[1]);
let (start, end) = (mat[2].parse(), mat[3].parse());
if let (Some(weekday), Ok(start), Ok(end)) = (weekday, start, end) {
Some(CourseDayTime {
weekday,
period: Period { start, end },
})
} else {
None
}
}),
pos: regex!(r"&(.*)$")
.captures(item)
.map(|mat| mat[1].trim().to_string()),
})
.collect()
}
}
impl ApiModel for EnrollCourseTimetable {}