algohub_server/utils/
contest.rs1use anyhow::Result;
2use surrealdb::{engine::remote::ws::Client, sql::Thing, Surreal};
3
4use crate::models::contest::{Contest, ContestData, ContestProblem};
5
6pub async fn create(
7 db: &Surreal<Client>,
8 creator_id: &str,
9 contest: ContestData,
10) -> Result<Option<Contest>> {
11 Ok(db
12 .create("contest")
13 .content(Contest {
14 id: None,
15 name: contest.name.to_string(),
16 mode: contest.mode,
17 visibility: contest.visibility,
18 description: contest.description,
19 announcement: None,
20 start_time: contest.start_time,
21 end_time: contest.end_time,
22 owner: contest.owner.clone().into(),
23 creator: ("account", creator_id).into(),
24 updaters: vec![("account", creator_id).into()],
25 participants: vec![],
26 created_at: chrono::Utc::now().naive_utc(),
27 updated_at: chrono::Utc::now().naive_utc(),
28 })
29 .await?)
30}
31
32pub async fn get(db: &Surreal<Client>, id: &str) -> Result<Option<Contest>> {
33 Ok(db.select(("contest", id)).await?)
34}
35
36pub async fn list_all(db: &Surreal<Client>) -> Result<Vec<Contest>> {
37 Ok(db.query("SELECT * FROM contest").await?.take(0)?)
38}
39
40pub async fn list_by_owner(db: &Surreal<Client>, id: &str) -> Result<Vec<Contest>> {
41 Ok(db
42 .query("SELECT * FROM contest WHERE record::id(owner) = $id")
43 .bind(("id", id.to_string()))
44 .await?
45 .take(0)?)
46}
47
48const ADD_PROBLEM: &str = r#"
49UPDATE type::thing("contest", $id)
50SET problems = array::union(problems, $problems);
51"#;
52pub async fn add_problems(
53 db: &Surreal<Client>,
54 id: String,
55 problems: Vec<Thing>,
56) -> Result<Option<Contest>> {
57 Ok(db
58 .query(ADD_PROBLEM)
59 .bind(("id", id))
60 .bind(("problems", problems))
61 .await?
62 .take(0)?)
63}
64
65const LIST_PROBLEMS: &str = r#"
66SELECT title, record::id(id) AS id, count(
67 SELECT VALUE true
68 FROM submission WHERE record::id(creator) == $account_id AND problem == $parent.id
69 AND judge_result.status.type == "accepted"
70) > 0 AS solved,
71count(
72 SELECT record::id(creator) FROM submission WHERE problem == $parent.id
73) AS submittedCount,
74count(
75 SELECT record::id(creator)
76 FROM submission WHERE problem == $parent.id
77 AND judge_result.status.type == "accepted"
78) AS acceptedCount
79FROM type::thing("contest", $id).problems;
80"#;
81pub async fn list_problems(
82 db: &Surreal<Client>,
83 id: &str,
84 account_id: &str,
85) -> Result<Vec<ContestProblem>> {
86 Ok(db
87 .query(LIST_PROBLEMS)
88 .bind(("id", id.to_string()))
89 .bind(("account_id", account_id.to_string()))
90 .await?
91 .take(0)?)
92}
93
94const REMOVE_PROBLEM: &str =
95 "UPDATE contest SET problems -= type::thing(\"problem\", $problem) WHERE record::id(id) = $id";
96pub async fn remove_problem(
97 db: &Surreal<Client>,
98 id: String,
99 problem: Thing,
100) -> Result<Option<Contest>> {
101 Ok(db
102 .query(REMOVE_PROBLEM)
103 .bind(("id", id))
104 .bind(("problem", problem))
105 .await?
106 .take(0)?)
107}