1use crate::prelude::*;
2
3#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
4#[cfg_attr(feature = "ts_rs", derive(TS))]
5pub struct SuspectedCheaters {
6 pub id: Uuid,
7 pub user_id: Uuid,
8 pub course_id: Uuid,
9 pub created_at: DateTime<Utc>,
10 pub deleted_at: Option<DateTime<Utc>>,
11 pub updated_at: Option<DateTime<Utc>>,
12 pub total_duration_seconds: Option<i32>,
13 pub total_points: i32,
14 pub is_archived: Option<bool>,
15}
16
17#[derive(Debug, Serialize, Deserialize)]
18#[cfg_attr(feature = "ts_rs", derive(TS))]
19pub struct ThresholdData {
20 pub points: i32,
21 pub duration_seconds: Option<i32>,
22}
23
24#[derive(Debug, Serialize, Deserialize)]
25#[cfg_attr(feature = "ts_rs", derive(TS))]
26pub struct DeletedSuspectedCheater {
27 pub id: i32,
28 pub count: i32,
29}
30
31#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
32#[cfg_attr(feature = "ts_rs", derive(TS))]
33pub struct Threshold {
34 pub id: Uuid,
35 pub course_id: Uuid,
36 pub created_at: DateTime<Utc>,
37 pub updated_at: DateTime<Utc>,
38 pub deleted_at: Option<DateTime<Utc>>,
39 pub points: i32,
40 pub duration_seconds: Option<i32>,
41}
42
43pub async fn insert(
44 conn: &mut PgConnection,
45 user_id: Uuid,
46 course_id: Uuid,
47 total_duration_seconds: Option<i32>,
48 total_points: i32,
49) -> ModelResult<()> {
50 sqlx::query!(
51 "
52 INSERT INTO suspected_cheaters (
53 user_id,
54 total_duration_seconds,
55 total_points,
56 course_id
57 )
58 VALUES ($1, $2, $3, $4)
59 ",
60 user_id,
61 total_duration_seconds,
62 total_points,
63 course_id
64 )
65 .execute(conn)
66 .await?;
67 Ok(())
68}
69
70pub async fn insert_thresholds(
71 conn: &mut PgConnection,
72 course_id: Uuid,
73 duration_seconds: Option<i32>,
74 points: i32,
75) -> ModelResult<Threshold> {
76 let threshold = sqlx::query_as!(
77 Threshold,
78 "
79 INSERT INTO cheater_thresholds (
80 course_id,
81 duration_seconds,
82 points
83 )
84 VALUES ($1, $2, $3)
85 ON CONFLICT (course_id)
86 DO UPDATE SET
87 duration_seconds = EXCLUDED.duration_seconds,
88 points = EXCLUDED.points
89 RETURNING *
90 ",
91 course_id,
92 duration_seconds,
93 points,
94 )
95 .fetch_one(conn)
96 .await?;
97
98 Ok(threshold)
99}
100
101pub async fn update_thresholds_by_point(
102 conn: &mut PgConnection,
103 course_id: Uuid,
104 points: i32,
105) -> ModelResult<()> {
106 sqlx::query!(
107 "
108 UPDATE cheater_thresholds
109 SET points = $2
110 WHERE course_id = $1
111 ",
112 course_id,
113 points
114 )
115 .execute(conn)
116 .await?;
117 Ok(())
118}
119
120pub async fn get_thresholds_by_id(
121 conn: &mut PgConnection,
122 course_id: Uuid,
123) -> ModelResult<Threshold> {
124 let thresholds = sqlx::query_as!(
125 Threshold,
126 "
127 SELECT id,
128 course_id,
129 duration_seconds,
130 points,
131 created_at,
132 updated_at,
133 deleted_at
134 FROM cheater_thresholds
135 WHERE course_id = $1
136 AND deleted_at IS NULL;
137 ",
138 course_id
139 )
140 .fetch_one(conn)
141 .await?;
142 Ok(thresholds)
143}
144
145pub async fn archive_suspected_cheater(conn: &mut PgConnection, id: Uuid) -> ModelResult<()> {
146 sqlx::query!(
147 "
148 UPDATE suspected_cheaters
149 SET is_archived = TRUE
150 WHERE user_id = $1
151 ",
152 id
153 )
154 .execute(conn)
155 .await?;
156 Ok(())
157}
158
159pub async fn approve_suspected_cheater(conn: &mut PgConnection, id: Uuid) -> ModelResult<()> {
160 sqlx::query!(
161 "
162 UPDATE suspected_cheaters
163 SET is_archived = FALSE
164 WHERE user_id = $1
165 ",
166 id
167 )
168 .execute(conn)
169 .await?;
170 Ok(())
171}
172
173pub async fn get_suspected_cheaters_by_id(
174 conn: &mut PgConnection,
175 id: Uuid,
176) -> ModelResult<SuspectedCheaters> {
177 let cheaters = sqlx::query_as!(
178 SuspectedCheaters,
179 "
180 SELECT *
181 FROM suspected_cheaters
182 WHERE user_id = $1
183 AND deleted_at IS NULL;
184 ",
185 id
186 )
187 .fetch_one(conn)
188 .await?;
189 Ok(cheaters)
190}
191
192pub async fn get_all_suspected_cheaters_in_course(
193 conn: &mut PgConnection,
194 course_id: Uuid,
195 archive: bool,
196) -> ModelResult<Vec<SuspectedCheaters>> {
197 let cheaters = sqlx::query_as!(
198 SuspectedCheaters,
199 "
200SELECT *
201FROM suspected_cheaters
202WHERE course_id = $1
203 AND is_archived = $2
204 AND deleted_at IS NULL;
205 ",
206 course_id,
207 archive
208 )
209 .fetch_all(conn)
210 .await?;
211 Ok(cheaters)
212}