use serde_with::serde_as;
use crate::{
errors::mycqu::MyCQUResult,
mycqu::{
course::Course,
utils::{encrypt::encrypt_student_id, mycqu_request_handler},
},
session::{Client, Session},
utils::{ApiModel, consts::MYCQU_API_EXAM_LIST_URL, response_json_map},
};
#[derive(Debug, Eq, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
pub struct Invigilator {
#[serde(alias = "instructor")]
pub name: String,
#[serde(alias = "instDeptShortName")]
pub dept: String,
}
impl ApiModel for Invigilator {}
#[serde_as]
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
pub struct Exam {
#[serde(flatten)]
pub course: Course,
#[serde(alias = "batchName")]
pub batch: String,
#[serde_as(deserialize_as = "serde_with::PickFirst<(_, serde_with::DisplayFromStr)>")]
#[serde(alias = "batchId")]
pub batch_id: u16,
#[serde_as(deserialize_as = "serde_with::DefaultOnNull")]
#[serde(alias = "buildingName")]
#[serde(default)]
pub building: String,
#[serde_as(
deserialize_as = "serde_with::DefaultOnError<Option<serde_with::PickFirst<(_, serde_with::DisplayFromStr)>>>"
)]
#[serde(alias = "floorNum")]
#[serde(default)]
pub floor: Option<u16>,
#[serde_as(deserialize_as = "serde_with::DefaultOnNull")]
#[serde(alias = "roomName")]
#[serde(default)]
pub room: String,
#[serde_as(deserialize_as = "serde_with::PickFirst<(_, serde_with::DisplayFromStr)>")]
#[serde(alias = "examStuNum")]
pub stu_num: u16,
#[serde(alias = "examDate")]
pub date_str: String,
#[serde(alias = "startTime")]
pub start_time_str: String,
#[serde(alias = "endTime")]
pub end_time_str: String,
#[serde_as(deserialize_as = "serde_with::PickFirst<(_, serde_with::DisplayFromStr)>")]
pub week: u16,
#[serde_as(deserialize_as = "serde_with::PickFirst<(_, serde_with::DisplayFromStr)>")]
#[serde(alias = "weekDay")]
pub weekday: u8,
#[serde(alias = "studentId")]
pub stu_id: String,
#[serde_as(deserialize_as = "serde_with::PickFirst<(_, serde_with::DisplayFromStr)>")]
#[serde(alias = "seatNum")]
pub seat_num: u16,
#[serde(alias = "simpleChiefinvigilatorVOS")]
#[serde_as(deserialize_as = "serde_with::DefaultOnNull")]
#[serde(default)]
pub chief_invigilator: Vec<Invigilator>,
#[serde(alias = "simpleAssistantInviVOS")]
#[serde(default)]
pub asst_invigilator: Option<Vec<Invigilator>>,
}
impl Exam {
pub async fn fetch_all(
client: &Client,
session: &Session,
student_id: impl AsRef<str>,
) -> MyCQUResult<Vec<Exam>> {
let response = mycqu_request_handler(client, session, |client| {
client
.get(MYCQU_API_EXAM_LIST_URL)
.query(&[("studentId", encrypt_student_id(student_id))])
})
.await?;
let (mut res, raw_response) = response_json_map(response).await?;
Self::extract_array(&mut res, "data", &raw_response)
}
}
impl ApiModel for Exam {}