Two teams try and fill in any horizontal, vertical, or diagonal line on a bingo board by playing maps on osu!
osu.bingo
osu
1use chrono::{DateTime, Utc};
2use juniper::{FieldError, FieldResult, graphql_object};
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 database::DataContext,
7 schema::{BingoSquare, MapInPool, MapStats},
8};
9
10#[derive(sqlx::FromRow, Serialize, Deserialize)]
11pub struct Map {
12 id: i32,
13 beatmapset_id: i32,
14 fetch_time: DateTime<Utc>,
15 gamemode: Ruleset,
16
17 title: String,
18 artist: String,
19 difficulty_name: String,
20
21 url: String,
22 square_url: String,
23 banner_url: String,
24 status: String,
25 max_combo: i32,
26 last_updated: DateTime<Utc>,
27
28 available: bool,
29}
30
31#[derive(sqlx::Type, Deserialize, Serialize, juniper::GraphQLEnum)]
32#[sqlx(type_name = "ruleset", rename_all = "lowercase")]
33#[serde(rename_all = "lowercase")]
34pub enum Ruleset {
35 Fruits,
36 Mania,
37 Osu,
38 Taiko,
39}
40
41#[graphql_object(description = "Trimmed-down data of a map in osu!'s database", Context = DataContext)]
42impl Map {
43 /// The beatmap ID from osu! servers
44 pub fn id(&self) -> i32 {
45 self.id
46 }
47
48 /// The set ID the map comes from
49 pub fn beatmapset_id(&self) -> i32 {
50 self.beatmapset_id
51 }
52
53 /// When this map was last fetched from the osu! API
54 pub fn fetch_time(&self) -> &DateTime<Utc> {
55 &self.fetch_time
56 }
57
58 /// The primary mode of the map
59 pub fn gamemode(&self) -> &Ruleset {
60 &self.gamemode
61 }
62
63 /// Name of the song
64 pub fn title(&self) -> &str {
65 &self.title
66 }
67
68 /// Name of the song's creator
69 pub fn artist(&self) -> &str {
70 &self.artist
71 }
72
73 /// Name of the difficulty of this id
74 pub fn difficulty_name(&self) -> &str {
75 &self.difficulty_name
76 }
77
78 /// A link to the beatmap
79 pub fn url(&self) -> &str {
80 &self.url
81 }
82
83 /// A square image of the map's background
84 pub fn square_url(&self) -> &str {
85 &self.square_url
86 }
87
88 /// A rectangular image of the map's background
89 pub fn banner_url(&self) -> &str {
90 &self.banner_url
91 }
92
93 /// Whether the map is ranked, loved, graveyarded etc.
94 pub fn status(&self) -> &str {
95 &self.status
96 }
97
98 /// The maximum combo you can achieve on this map
99 pub fn max_combo(&self) -> i32 {
100 self.max_combo
101 }
102
103 /// When the last update to this map was
104 pub fn last_updated(&self) -> &DateTime<Utc> {
105 &self.last_updated
106 }
107
108 /// Whether or not this map can be downloaded from the osu! API
109 pub fn is_available(&self) -> bool {
110 self.available
111 }
112
113 /// The squares this map is a part of
114 pub async fn in_squares(&self, context: &DataContext) -> FieldResult<Vec<BingoSquare>> {
115 context
116 .acquire()
117 .await
118 .get_map_squares(self.id)
119 .await
120 .map_err(FieldError::from)
121 }
122
123 /// The pools this map is in
124 pub async fn in_pools(&self, context: &DataContext) -> FieldResult<Vec<MapInPool>> {
125 context
126 .acquire()
127 .await
128 .get_mapinpool_by_map(self.id)
129 .await
130 .map_err(FieldError::from)
131 }
132
133 /// The stats for every mod combo this map has been used in
134 pub async fn stats(&self, context: &DataContext) -> FieldResult<Vec<MapStats>> {
135 context
136 .acquire()
137 .await
138 .get_map_stats(self.id)
139 .await
140 .map_err(FieldError::from)
141 }
142}