aboutsummaryrefslogtreecommitdiff
path: root/backend/database
diff options
context:
space:
mode:
authorArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2024-10-31 00:29:37 +0300
committerArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2024-10-31 00:29:37 +0300
commit7e63ef2fd6ce429d63ef73ee54199bc530da84fe (patch)
tree6f23d82c0cb113ce21728ce0fdf789e5b763de11 /backend/database
parentfrontend: fix coop map categories (diff)
downloadlphub-7e63ef2fd6ce429d63ef73ee54199bc530da84fe.tar.gz
lphub-7e63ef2fd6ce429d63ef73ee54199bc530da84fe.tar.bz2
lphub-7e63ef2fd6ce429d63ef73ee54199bc530da84fe.zip
backend: fix all rankings and placements, use sql funcs
Diffstat (limited to 'backend/database')
-rw-r--r--backend/database/functions.sql212
1 files changed, 212 insertions, 0 deletions
diff --git a/backend/database/functions.sql b/backend/database/functions.sql
new file mode 100644
index 0000000..ca33a60
--- /dev/null
+++ b/backend/database/functions.sql
@@ -0,0 +1,212 @@
1CREATE OR REPLACE FUNCTION get_rankings_singleplayer()
2RETURNS TABLE (
3 steam_id TEXT,
4 user_name TEXT,
5 avatar_link TEXT,
6 total_min_score_count BIGINT
7) AS $$
8BEGIN
9 RETURN QUERY
10 SELECT
11 u.steam_id,
12 u.user_name,
13 u.avatar_link,
14 (
15 SELECT SUM(min_score_count) AS total_min_score_count
16 FROM (
17 SELECT sp.user_id, MIN(sp.score_count) AS min_score_count
18 FROM records_sp sp
19 WHERE sp.is_deleted = false
20 GROUP BY sp.user_id, sp.map_id
21 ) AS subquery
22 WHERE user_id = u.steam_id
23 )
24 FROM records_sp sp
25 JOIN users u ON u.steam_id = sp.user_id
26 WHERE sp.is_deleted = false
27 GROUP BY u.steam_id, u.user_name, u.avatar_link
28 HAVING COUNT(DISTINCT sp.map_id) = (
29 SELECT COUNT(m.name)
30 FROM maps m
31 INNER JOIN games g ON m.game_id = g.id
32 WHERE g.id = 1 AND m.is_disabled = false
33 )
34 ORDER BY total_min_score_count ASC;
35END;
36$$ LANGUAGE plpgsql;
37
38
39
40CREATE OR REPLACE FUNCTION get_rankings_multiplayer()
41RETURNS TABLE (
42 steam_id TEXT,
43 user_name TEXT,
44 avatar_link TEXT,
45 total_min_score_count BIGINT
46) AS $$
47BEGIN
48 RETURN QUERY
49 SELECT
50 u.steam_id,
51 u.user_name,
52 u.avatar_link,
53 (
54 SELECT SUM(min_score_count) AS total_min_score_count
55 FROM (
56 SELECT DISTINCT ON (map_id, player_id)
57 map_id,
58 player_id,
59 MIN(score_count) AS min_score_count
60 FROM (
61 SELECT
62 mp.map_id,
63 mp.host_id AS player_id,
64 mp.score_count
65 FROM records_mp mp
66 WHERE mp.is_deleted = false
67 UNION ALL
68 SELECT
69 mp.map_id,
70 mp.partner_id AS player_id,
71 mp.score_count
72 FROM records_mp mp
73 WHERE mp.is_deleted = false
74 ) AS player_scores
75 GROUP BY map_id, player_id
76 ) AS subquery
77 WHERE player_id = u.steam_id
78 )
79 FROM records_mp mp
80 JOIN users u ON u.steam_id = mp.host_id OR u.steam_id = mp.partner_id
81 WHERE mp.is_deleted = false
82 GROUP BY u.steam_id, u.user_name, u.avatar_link
83 HAVING COUNT(DISTINCT mp.map_id) = (
84 SELECT COUNT(m.name)
85 FROM maps m
86 INNER JOIN games g ON m.game_id = g.id
87 WHERE g.id = 2 AND m.is_disabled = false
88 )
89 ORDER BY total_min_score_count ASC;
90END;
91$$ LANGUAGE plpgsql;
92
93
94
95CREATE OR REPLACE FUNCTION get_placements_singleplayer(player_id TEXT)
96RETURNS TABLE (
97 map_id SMALLINT,
98 placement BIGINT
99) AS $$
100BEGIN
101 RETURN QUERY
102 WITH ranked_scores AS (
103 SELECT
104 sp.map_id,
105 sp.user_id,
106 sp.score_count,
107 sp.score_time,
108 ROW_NUMBER() OVER (
109 PARTITION BY sp.map_id, sp.user_id
110 ORDER BY sp.score_count ASC, sp.score_time ASC
111 ) AS rank
112 FROM records_sp sp
113 WHERE sp.is_deleted = false
114 ),
115 best_scores AS (
116 SELECT
117 rs.map_id,
118 rs.user_id,
119 rs.score_count,
120 rs.score_time
121 FROM ranked_scores rs
122 WHERE rs.rank = 1
123 ),
124 min_placements AS (
125 SELECT
126 bs.map_id,
127 bs.user_id,
128 (SELECT COUNT(*) + 1
129 FROM best_scores AS inner_scores
130 WHERE inner_scores.map_id = bs.map_id
131 AND (inner_scores.score_count < bs.score_count
132 OR (inner_scores.score_count = bs.score_count
133 AND inner_scores.score_time < bs.score_time)
134 )
135 ) AS placement
136 FROM best_scores AS bs
137 )
138 SELECT
139 minp.map_id,
140 MIN(minp.placement) AS placement
141 FROM min_placements minp
142 WHERE minp.user_id = get_placements_singleplayer.player_id
143 GROUP BY minp.map_id
144 ORDER BY minp.map_id, placement;
145END;
146$$ LANGUAGE plpgsql;
147
148
149
150CREATE OR REPLACE FUNCTION get_placements_multiplayer(player_id TEXT)
151RETURNS TABLE (
152 map_id SMALLINT,
153 placement BIGINT
154) AS $$
155BEGIN
156 RETURN QUERY
157 WITH ranked_scores AS (
158 SELECT
159 mp.map_id,
160 mp.host_id,
161 mp.partner_id,
162 mp.score_count,
163 mp.score_time,
164 ROW_NUMBER() OVER (
165 PARTITION BY mp.map_id, mp.host_id, mp.partner_id
166 ORDER BY mp.score_count ASC, mp.score_time ASC
167 ) AS rank
168 FROM records_mp mp
169 WHERE mp.is_deleted = false
170 ),
171 best_scores AS (
172 SELECT
173 rs.map_id,
174 rs.host_id,
175 rs.partner_id,
176 rs.score_count,
177 rs.score_time
178 FROM ranked_scores rs
179 WHERE rs.rank = 1
180 ),
181 min_placements AS (
182 SELECT
183 bs.map_id,
184 bs.host_id,
185 bs.partner_id,
186 (SELECT COUNT(*) + 1
187 FROM best_scores AS inner_scores
188 WHERE inner_scores.map_id = bs.map_id
189 AND (inner_scores.score_count < bs.score_count
190 OR (inner_scores.score_count = bs.score_count
191 AND inner_scores.score_time < bs.score_time)
192 )
193 ) AS placement
194 FROM best_scores AS bs
195 ),
196 distinct_min_placements AS (
197 SELECT unified_placements.map_id, unified_placements.player_id, MIN(unified_placements.placement) AS min_placement
198 FROM (
199 SELECT minp.map_id, minp.host_id AS player_id, minp.placement FROM min_placements minp
200 UNION ALL
201 SELECT minp.map_id, minp.partner_id AS player_id, minp.placement FROM min_placements minp
202 ) AS unified_placements
203 WHERE unified_placements.player_id = get_placements_multiplayer.player_id
204 GROUP BY unified_placements.map_id, unified_placements.player_id
205 )
206 SELECT
207 dminp.map_id,
208 dminp.min_placement AS placement
209 FROM distinct_min_placements dminp
210 ORDER BY dminp.map_id, placement;
211END;
212$$ LANGUAGE plpgsql;