Skip to content

Commit d563a6e

Browse files
authored
Merge pull request #1 from Osef-me/db-models-reorganization
Db models reorganization
2 parents 452dc20 + b9fc013 commit d563a6e

File tree

263 files changed

+2010
-3802
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

263 files changed

+2010
-3802
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres", "chron
1818
validator = { version = "0.20.0", features = ["derive"] }
1919
regex = "1.0"
2020

21-
lazy_static = "1.4"
21+
lazy_static = "1.4"
22+
uuid = "1.18.1"

src/models/beatmap/beatmap/impl.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use super::query::{find_by_id, find_by_osu_id, insert};
2+
use super::BeatmapRow;
3+
use sqlx::{Error as SqlxError, PgPool};
4+
5+
impl BeatmapRow {
6+
pub async fn insert(self, pool: &PgPool) -> Result<i32, SqlxError> {
7+
insert(pool, self).await
8+
}
9+
10+
pub async fn find_by_id(pool: &PgPool, id: i32) -> Result<Self, SqlxError> {
11+
find_by_id(pool, id).await?.ok_or(SqlxError::RowNotFound)
12+
}
13+
14+
pub async fn find_by_osu_id(pool: &PgPool, osu_id: i32) -> Result<Option<Self>, SqlxError> {
15+
find_by_osu_id(pool, osu_id).await
16+
}
17+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ pub mod validators;
66
#[cfg(test)]
77
mod tests;
88

9-
pub use types::*;
9+
pub use types::BeatmapRow;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use crate::models::beatmap::beatmap::types::BeatmapRow;
2+
use sqlx::{Error as SqlxError, PgPool};
3+
4+
pub async fn find_by_id(pool: &PgPool, id: i32) -> Result<Option<BeatmapRow>, SqlxError> {
5+
sqlx::query_as!(
6+
BeatmapRow,
7+
r#"
8+
SELECT id, osu_id, beatmapset_id, difficulty, count_circles, count_sliders, count_spinners, max_combo, main_pattern, cs, ar, od, hp, mode, status, created_at, updated_at
9+
FROM beatmap
10+
WHERE id = $1
11+
"#,
12+
id
13+
)
14+
.fetch_optional(pool)
15+
.await
16+
}
17+
18+
pub async fn find_by_osu_id(pool: &PgPool, osu_id: i32) -> Result<Option<BeatmapRow>, SqlxError> {
19+
sqlx::query_as!(
20+
BeatmapRow,
21+
r#"
22+
SELECT id, osu_id, beatmapset_id, difficulty, count_circles, count_sliders, count_spinners, max_combo, main_pattern, cs, ar, od, hp, mode, status, created_at, updated_at
23+
FROM beatmap
24+
WHERE osu_id = $1
25+
"#,
26+
osu_id
27+
)
28+
.fetch_optional(pool)
29+
.await
30+
}
Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::define_insert_returning_id;
2-
use crate::models::beatmap::types::BeatmapRow;
2+
use crate::models::beatmap::beatmap::types::BeatmapRow;
3+
// no extra imports needed
34

45
define_insert_returning_id!(
56
insert,
@@ -8,20 +9,15 @@ define_insert_returning_id!(
89
osu_id,
910
beatmapset_id,
1011
difficulty,
11-
difficulty_rating,
1212
count_circles,
1313
count_sliders,
1414
count_spinners,
1515
max_combo,
16-
drain_time,
17-
total_time,
18-
bpm,
16+
main_pattern,
1917
cs,
2018
ar,
2119
od,
2220
hp,
2321
mode,
24-
status,
25-
file_md5,
26-
file_path
22+
status
2723
);
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
pub mod by_id;
2-
pub mod by_score_id;
32
pub mod insert;
43

54
pub use by_id::*;
6-
pub use by_score_id::*;
75
pub use insert::*;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use super::validators::{validate_ar, validate_od_hp_cs, validate_status};
2+
use bigdecimal::BigDecimal;
3+
use chrono::NaiveDateTime;
4+
use serde_json::Value;
5+
use validator::Validate;
6+
7+
#[derive(Debug, Clone, sqlx::FromRow, Validate)]
8+
pub struct BeatmapRow {
9+
/// Unique identifier for the beatmap record.
10+
/// Must be a positive integer (≥ 1).
11+
#[validate(range(min = 1, message = "ID must be positive"))]
12+
pub id: i32,
13+
14+
/// Osu beatmap ID from the official osu! API.
15+
/// Must be a positive integer (≥ 1).
16+
#[validate(range(min = 1, message = "Osu ID must be positive"))]
17+
pub osu_id: Option<i32>,
18+
19+
/// Reference to the beatmapset this beatmap belongs to.
20+
/// Optional field, can be None.
21+
pub beatmapset_id: Option<i32>,
22+
23+
/// Difficulty name of the beatmap.
24+
/// Must be between 1 and 255 characters.
25+
#[validate(length(
26+
min = 1,
27+
max = 255,
28+
message = "Difficulty must be between 1 and 255 characters"
29+
))]
30+
pub difficulty: String,
31+
32+
/// Number of circles in the beatmap.
33+
/// Must be a non-negative integer (≥ 0).
34+
#[validate(range(min = 0, message = "Count circles must be non-negative"))]
35+
pub count_circles: i32,
36+
37+
/// Number of sliders in the beatmap.
38+
/// Must be a non-negative integer (≥ 0).
39+
#[validate(range(min = 0, message = "Count sliders must be non-negative"))]
40+
pub count_sliders: i32,
41+
42+
/// Number of spinners in the beatmap.
43+
/// Must be a non-negative integer (≥ 0).
44+
#[validate(range(min = 0, message = "Count spinners must be non-negative"))]
45+
pub count_spinners: i32,
46+
47+
/// Maximum combo possible in the beatmap.
48+
/// Must be a non-negative integer (≥ 0).
49+
#[validate(range(min = 0, message = "Max combo must be non-negative"))]
50+
pub max_combo: i32,
51+
52+
/// Main pattern data stored as JSON.
53+
/// Must not be null.
54+
pub main_pattern: Value,
55+
56+
/// Circle Size (CS) value.
57+
/// Must be between 0.0 and 10.0.
58+
#[validate(custom(function = "validate_od_hp_cs"))]
59+
pub cs: BigDecimal,
60+
61+
/// Approach Rate (AR) value.
62+
/// Must be between 0.0 and 10.0.
63+
#[validate(custom(function = "validate_ar"))]
64+
pub ar: BigDecimal,
65+
66+
/// Overall Difficulty (OD) value.
67+
/// Must be between 0.0 and 10.0.
68+
#[validate(custom(function = "validate_od_hp_cs"))]
69+
pub od: BigDecimal,
70+
71+
/// HP Drain (HP) value.
72+
/// Must be between 0.0 and 10.0.
73+
#[validate(custom(function = "validate_od_hp_cs"))]
74+
pub hp: BigDecimal,
75+
76+
/// Game mode (0=osu!, 1=Taiko, 2=Catch, 3=Mania).
77+
/// Must be between 0 and 3.
78+
#[validate(range(min = 0, max = 3, message = "Mode must be between 0 and 3"))]
79+
pub mode: i32,
80+
81+
/// Status of the beatmap.
82+
/// Must be one of: 'pending', 'ranked', 'qualified', 'loved', 'graveyard'.
83+
#[validate(custom(function = "validate_status"))]
84+
pub status: String,
85+
86+
/// Timestamp when the beatmap was created.
87+
pub created_at: Option<NaiveDateTime>,
88+
89+
/// Timestamp when the beatmap was last updated.
90+
pub updated_at: Option<NaiveDateTime>,
91+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use bigdecimal::{BigDecimal, FromPrimitive};
2+
use validator::ValidationError;
3+
4+
pub fn validate_status(status: &str) -> Result<(), ValidationError> {
5+
match status {
6+
"pending" | "ranked" | "qualified" | "loved" | "graveyard" => Ok(()),
7+
_ => Err(validator::ValidationError::new("invalid_status")),
8+
}
9+
}
10+
11+
pub fn validate_od_hp_cs(value: &BigDecimal) -> Result<(), ValidationError> {
12+
if value < &BigDecimal::from_f64(0.0).unwrap() || value > &BigDecimal::from_f64(10.0).unwrap() {
13+
return Err(validator::ValidationError::new("invalid_od_hp_cs"));
14+
}
15+
Ok(())
16+
}
17+
18+
pub fn validate_ar(value: &BigDecimal) -> Result<(), ValidationError> {
19+
if value < &BigDecimal::from_f64(0.0).unwrap() || value > &BigDecimal::from_f64(11.0).unwrap() {
20+
return Err(validator::ValidationError::new("invalid_ar"));
21+
}
22+
Ok(())
23+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use super::query::{find_by_id, find_by_osu_id, insert};
2+
use super::BeatmapsetRow;
3+
use sqlx::{Error as SqlxError, PgPool};
4+
5+
impl BeatmapsetRow {
6+
pub async fn insert(self, pool: &PgPool) -> Result<i32, SqlxError> {
7+
insert(pool, self).await
8+
}
9+
10+
pub async fn find_by_id(pool: &PgPool, id: i32) -> Result<Self, SqlxError> {
11+
find_by_id(pool, id).await?.ok_or(SqlxError::RowNotFound)
12+
}
13+
14+
pub async fn find_by_osu_id(pool: &PgPool, osu_id: i32) -> Result<Option<Self>, SqlxError> {
15+
find_by_osu_id(pool, osu_id).await
16+
}
17+
}

0 commit comments

Comments
 (0)