use std::sync::Arc;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::{canvas, CourseInfo, Student};
use crate::submission::Submission;
use serde_json::Value;
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct AssignmentInfo {
pub id: u64,
pub name: String,
pub description: Option<String>,
#[serde(skip)]
pub course_info: Arc<CourseInfo>,
}
#[derive(Debug, Clone)]
pub struct Assignment {
pub info: Arc<AssignmentInfo>,
}
impl Assignment {
pub fn fetch_submissions(&self, students: &Vec<Student>) -> Result<Vec<Submission>, Box<dyn std::error::Error>> {
let client = &reqwest::blocking::Client::new();
match canvas::get_all_submissions(client, self.info.course_info.canvas_info.as_ref(), self.info.course_info.id, self.info.id) {
Ok(submissions_value) => {
let submissions = submissions_value
.iter()
.filter_map(|j| {
Assignment::convert_json_to_submission(students, j)
})
.collect::<Vec<_>>();
Ok(submissions)
}
Err(e) => {
return Err(Box::new(std::io::Error::new(
std::io::ErrorKind::Other,
format!("Failed to fetch submissions with error: {} (a)", e),
)));
}
}
}
fn convert_json_to_submission(
students: &Vec<Student>,
j: &Value,
) -> Option<Submission> {
for student in students {
match j["user_id"].as_u64() {
Some(user_id) => {
if student.info.id == user_id {
return Some(Submission {
id: j["id"].as_u64().unwrap(), assignment_id: j["assignment_id"].as_u64().unwrap(), score: j["score"].as_f64(), submitted_at: j["submitted_at"].as_str().map(|s| DateTime::parse_from_rfc3339(s).unwrap().with_timezone(&Utc)), student: student.info.clone(),
});
}
}
None => {}
}
}
None
}
}