forked from stadust/pointercrate
-
Notifications
You must be signed in to change notification settings - Fork 1
/
20190708102450_formula_update.down.sql
63 lines (52 loc) · 2.07 KB
/
20190708102450_formula_update.down.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
-- This file should undo anything in `up.sql`
-- Your SQL goes here
DROP VIEW players_with_score;
DROP FUNCTION record_score(FLOAT, FLOAT, FLOAT, FLOAT);
CREATE FUNCTION record_score(progress FLOAT, demon FLOAT, list_size FLOAT) RETURNS FLOAT AS
$record_score$
SELECT (progress / 100.0) ^ demon * list_size / (1.0 + (list_size - 1.0) * EXP(-4.0 * (list_size - demon) * LN(list_size - 1.0)/(3.0 * list_size)));
$record_score$
LANGUAGE SQL IMMUTABLE;
CREATE VIEW players_with_score AS
SELECT players.id,
players.name,
RANK() OVER(ORDER BY scores.total_score DESC) AS rank,
CASE WHEN scores.total_score IS NULL THEN 0.0::FLOAT ELSE scores.total_score END AS score,
ROW_NUMBER() OVER(ORDER BY scores.total_score DESC) AS index,
nationalities.iso_country_code,
nationalities.nation
FROM
(
SELECT pseudo_records.player,
SUM(record_score(pseudo_records.progress::FLOAT, pseudo_records.position::FLOAT, 100::FLOAT)) as total_score
FROM (
SELECT player,
progress,
demons.position
FROM records
INNER JOIN demons
ON demons.name = demon
WHERE demons.position <= 100 AND status_ = 'APPROVED'
UNION
SELECT verifier as player,
CASE WHEN demons.position > 100 THEN 0.0::FLOAT ELSE 100.0::FLOAT END as progress,
position as position
FROM demons
UNION
SELECT publisher as player,
0.0::FLOAT as progress,
position as position
FROM demons
UNION
SELECT creator as player,
0.0::FLOAT as progress,
1.0::FLOAT as position -- doesn't matter
FROM creators
) AS pseudo_records
GROUP BY player
) scores
INNER JOIN players
ON scores.player = players.id
LEFT OUTER JOIN nationalities
ON players.nationality = nationalities.iso_country_code
WHERE NOT players.banned;