diff options
| author | Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> | 2024-10-31 00:29:37 +0300 |
|---|---|---|
| committer | Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> | 2024-10-31 00:29:37 +0300 |
| commit | 7e63ef2fd6ce429d63ef73ee54199bc530da84fe (patch) | |
| tree | 6f23d82c0cb113ce21728ce0fdf789e5b763de11 /backend/database/functions.sql | |
| parent | frontend: fix coop map categories (diff) | |
| download | lphub-7e63ef2fd6ce429d63ef73ee54199bc530da84fe.tar.gz lphub-7e63ef2fd6ce429d63ef73ee54199bc530da84fe.tar.bz2 lphub-7e63ef2fd6ce429d63ef73ee54199bc530da84fe.zip | |
backend: fix all rankings and placements, use sql funcs
Diffstat (limited to 'backend/database/functions.sql')
| -rw-r--r-- | backend/database/functions.sql | 212 |
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 @@ | |||
| 1 | CREATE OR REPLACE FUNCTION get_rankings_singleplayer() | ||
| 2 | RETURNS TABLE ( | ||
| 3 | steam_id TEXT, | ||
| 4 | user_name TEXT, | ||
| 5 | avatar_link TEXT, | ||
| 6 | total_min_score_count BIGINT | ||
| 7 | ) AS $$ | ||
| 8 | BEGIN | ||
| 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; | ||
| 35 | END; | ||
| 36 | $$ LANGUAGE plpgsql; | ||
| 37 | |||
| 38 | |||
| 39 | |||
| 40 | CREATE OR REPLACE FUNCTION get_rankings_multiplayer() | ||
| 41 | RETURNS TABLE ( | ||
| 42 | steam_id TEXT, | ||
| 43 | user_name TEXT, | ||
| 44 | avatar_link TEXT, | ||
| 45 | total_min_score_count BIGINT | ||
| 46 | ) AS $$ | ||
| 47 | BEGIN | ||
| 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; | ||
| 90 | END; | ||
| 91 | $$ LANGUAGE plpgsql; | ||
| 92 | |||
| 93 | |||
| 94 | |||
| 95 | CREATE OR REPLACE FUNCTION get_placements_singleplayer(player_id TEXT) | ||
| 96 | RETURNS TABLE ( | ||
| 97 | map_id SMALLINT, | ||
| 98 | placement BIGINT | ||
| 99 | ) AS $$ | ||
| 100 | BEGIN | ||
| 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; | ||
| 145 | END; | ||
| 146 | $$ LANGUAGE plpgsql; | ||
| 147 | |||
| 148 | |||
| 149 | |||
| 150 | CREATE OR REPLACE FUNCTION get_placements_multiplayer(player_id TEXT) | ||
| 151 | RETURNS TABLE ( | ||
| 152 | map_id SMALLINT, | ||
| 153 | placement BIGINT | ||
| 154 | ) AS $$ | ||
| 155 | BEGIN | ||
| 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; | ||
| 211 | END; | ||
| 212 | $$ LANGUAGE plpgsql; | ||