Skip to content

Commit

Permalink
feat: list submission (#44)
Browse files Browse the repository at this point in the history
* feat: list submission by user or contest or user and contest

* release: bump version

* fix: correct the URL and rename the var

* fix: use map instead of match

* Update .changes/submission.md

* test: submisson

* fix: correct URL

* test: submission

* fix: Update the deprecated test program

* Modify the variable type

* fix: Update the variable type

* fix: change test

* fix: lint

---------

Co-authored-by: 苏向夜 <[email protected]>
  • Loading branch information
K0nnyaku and fu050409 authored Dec 3, 2024
1 parent 1a6e441 commit 1bee9b5
Show file tree
Hide file tree
Showing 5 changed files with 413 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changes/submission.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"algohub-server": patch:feat
---

Support list submissions by user or contest or user and contest
5 changes: 3 additions & 2 deletions src/models/submission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ pub enum Status {
Ready,
}

#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Debug)]
pub struct Submission {
pub id: Option<Thing>,

pub lang: Language,
pub problem_id: String,
pub problem: Thing,
pub code: String,
pub status: Status,
pub results: Vec<JudgeResult>,
pub creator: Thing,
pub contest: Option<Thing>,

pub created_at: chrono::NaiveDateTime,
pub updated_at: chrono::NaiveDateTime,
Expand Down
81 changes: 76 additions & 5 deletions src/routes/submission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ pub async fn submit(

let data = data.into_inner();
let submission = submission::create(db, &data.auth.id, id, data.code, data.lang)
.await
.map_err(|e| Error::ServerError(Json(e.to_string().into())))?
.await?
.ok_or(Error::ServerError(Json(
"Failed to submit, please try again later.".into(),
)))?;
Expand All @@ -57,8 +56,7 @@ pub async fn get(
_auth: Json<Credentials<'_>>,
) -> Result<Submission> {
let submission = submission::get_by_id(db, id)
.await
.map_err(|e| Error::ServerError(Json(e.to_string().into())))?
.await?
.ok_or(Error::NotFound(Json("Submission not found".into())))?;

Ok(Json(Response {
Expand All @@ -68,7 +66,80 @@ pub async fn get(
}))
}

#[post("/list/user/<id>", data = "<_auth>")]
pub async fn list_by_user(
db: &State<Surreal<Client>>,
id: &str,
_auth: Json<Credentials<'_>>,
) -> Result<Vec<Submission>> {
let submissions = submission::list_by_user(db, ("account", id).into()).await?;

Ok(Json(Response {
success: true,
message: "submission fetched successfully".to_string(),
data: Some(submissions),
}))
}

#[post("/list/contest/<id>", data = "<_auth>")]
pub async fn list_by_contest(
db: &State<Surreal<Client>>,
id: &str,
_auth: Json<Credentials<'_>>,
) -> Result<Vec<Submission>> {
let submissions = submission::list_by_contest(db, ("contest", id).into()).await?;

Ok(Json(Response {
success: true,
message: "submission fetched successfully".to_string(),
data: Some(submissions),
}))
}

#[post("/list/problem/<id>", data = "<_auth>")]
pub async fn list_by_problem(
db: &State<Surreal<Client>>,
id: &str,
_auth: Json<Credentials<'_>>,
) -> Result<Vec<Submission>> {
let submissions = submission::list_by_problem(db, ("problem", id).into()).await?;

Ok(Json(Response {
success: true,
message: "submission fetched successfully".to_string(),
data: Some(submissions),
}))
}

#[post("/list/contest/<contest_id>/<user_id>", data = "<_auth>")]
pub async fn list_within_contest(
db: &State<Surreal<Client>>,
contest_id: &str,
user_id: &str,
_auth: Json<Credentials<'_>>,
) -> Result<Vec<Submission>> {
let submissions = submission::list_within_contest(
db,
("contest", contest_id).into(),
("account", user_id).into(),
)
.await?;

Ok(Json(Response {
success: true,
message: "submission fetched successfully".to_string(),
data: Some(submissions),
}))
}

pub fn routes() -> Vec<rocket::Route> {
use rocket::routes;
routes![submit, get]
routes![
submit,
get,
list_by_user,
list_by_contest,
list_within_contest,
list_by_problem,
]
}
48 changes: 44 additions & 4 deletions src/utils/submission.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::models::submission::Status;
use crate::models::submission::Submission;
use anyhow::Result;
use eval_stack::compile::Language;
use surrealdb::{engine::remote::ws::Client, Surreal};
use surrealdb::{engine::remote::ws::Client, sql::Thing, Surreal};

pub async fn create(
db: &Surreal<Client>,
account_id: &str,
problem_id: &str,
problem: &str,
code: String,
lang: Language,
) -> Result<Option<Submission>> {
Expand All @@ -16,12 +17,14 @@ pub async fn create(
id: None,
lang,
code,
problem_id: problem_id.to_string(),
status: crate::models::submission::Status::InQueue,
problem: ("problem", problem).into(),
status: Status::InQueue,

creator: ("account", account_id).into(),
results: vec![],

contest: None,

created_at: chrono::Local::now().naive_local(),
updated_at: chrono::Local::now().naive_local(),
})
Expand All @@ -31,3 +34,40 @@ pub async fn create(
pub async fn get_by_id(db: &Surreal<Client>, id: &str) -> Result<Option<Submission>> {
Ok(db.select(("submission", id)).await?)
}

pub async fn list_by_user(db: &Surreal<Client>, creator: Thing) -> Result<Vec<Submission>> {
Ok(db
.query("SELECT * FROM submission WHERE creator = $creator")
.bind(("creator", creator))
.await?
.take(0)?)
}

pub async fn list_by_contest(db: &Surreal<Client>, contest: Thing) -> Result<Vec<Submission>> {
Ok(db
.query("SELECT * FROM submission WHERE contest = $contest")
.bind(("contest", contest))
.await?
.take(0)?)
}

pub async fn list_within_contest(
db: &Surreal<Client>,
contest: Thing,
creator: Thing,
) -> Result<Vec<Submission>> {
Ok(db
.query("SELECT * FROM submission WHERE contest = $contest AND creator = $creator")
.bind(("contest", contest))
.bind(("creator", creator))
.await?
.take(0)?)
}

pub async fn list_by_problem(db: &Surreal<Client>, problem: Thing) -> Result<Vec<Submission>> {
Ok(db
.query("SELECT * FROM submission WHERE problem = $problem")
.bind(("problem", problem))
.await?
.take(0)?)
}
Loading

0 comments on commit 1bee9b5

Please sign in to comment.