Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions migrations/20250324133910_list_scoreless_players.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
UPDATE players
SET score = 0.0
WHERE score IS NULL;

ALTER TABLE players
ALTER COLUMN score
SET NOT NULL;

CREATE OR REPLACE FUNCTION record_score(progress FLOAT, demon FLOAT, list_size FLOAT, requirement FLOAT) RETURNS FLOAT AS
$record_score$
SELECT CASE
WHEN progress = 100 THEN
CASE

WHEN 55 < demon AND demon <= 150 THEN
(56.191 * EXP(LN(2) * ((54.147 - (demon + 3.2)) * LN(50.0)) / 99.0)) + 6.273
WHEN 35 < demon AND demon <= 55 THEN
212.61 * (EXP(LN(1.036) * (1 - demon))) + 25.071
WHEN 20 < demon AND demon <= 35 THEN
(250 - 83.389) * (EXP(LN(1.0099685) * (2 - demon))) - 31.152
WHEN demon <= 20 THEN
(250 - 100.39) * (EXP(LN(1.168) * (1 - demon))) + 100.39

END

WHEN progress < requirement THEN
0.0
ELSE
CASE

WHEN 55 < demon AND demon <= 150 THEN
((56.191 * EXP(LN(2) * ((54.147 - (demon + 3.2)) * LN(50.0)) / 99.0)) + 6.273) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10
WHEN 35 < demon AND demon <= 55 THEN
(212.61 * (EXP(LN(1.036) * (1 - demon))) + 25.071) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10
WHEN 20 < demon AND demon <= 35 THEN
((250 - 83.389) * (EXP(LN(1.0099685) * (2 - demon))) - 31.152) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10
WHEN demon <= 20 THEN
((250 - 100.39) * (EXP(LN(1.168) * (1 - demon))) + 100.39) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10

END
END;
$record_score$
LANGUAGE SQL IMMUTABLE;

CREATE OR REPLACE FUNCTION recompute_player_scores() RETURNS void AS $$
UPDATE players
SET score = coalesce(q.score, 0)
FROM players p
LEFT OUTER JOIN (
SELECT player, SUM(record_score(progress, position, 150, requirement)) as score
FROM score_giving
GROUP BY player
) q
ON q.player = p.id
WHERE players.id = p.id;
$$ LANGUAGE SQL;

CREATE OR REPLACE VIEW ranked_players AS
SELECT
ROW_NUMBER() OVER(ORDER BY players.score DESC, id) AS index,
RANK() OVER(ORDER BY players.score DESC) AS rank,
id, name, players.score, subdivision,
nationalities.iso_country_code,
nationalities.nation,
nationalities.continent
FROM players
LEFT OUTER JOIN nationalities
ON players.nationality = nationalities.iso_country_code
WHERE NOT players.banned AND players.score > 0.0;

CREATE OR REPLACE VIEW score_giving AS
SELECT records.progress, demons.position, demons.requirement, records.player
FROM records
INNER JOIN demons
ON demons.id = records.demon
WHERE records.status_ = 'APPROVED' AND (demons.position <= 75 OR records.progress = 100)

UNION

SELECT 100, demons.position, demons.requirement, demons.verifier
FROM demons;


SELECT recompute_player_scores();
SELECT recompute_nation_scores();
SELECT recompute_subdivision_scores();
84 changes: 84 additions & 0 deletions migrations/20250324133910_list_scoreless_players.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
ALTER TABLE players
ALTER COLUMN score
DROP NOT NULL;

CREATE OR REPLACE FUNCTION record_score(progress FLOAT, demon FLOAT, list_size FLOAT, requirement FLOAT) RETURNS FLOAT AS
$record_score$
SELECT CASE
WHEN demon > 150 THEN 0.0

WHEN progress = 100 THEN
CASE

WHEN 55 < demon AND demon <= 150 THEN
(56.191 * EXP(LN(2) * ((54.147 - (demon + 3.2)) * LN(50.0)) / 99.0)) + 6.273
WHEN 35 < demon AND demon <= 55 THEN
212.61 * (EXP(LN(1.036) * (1 - demon))) + 25.071
WHEN 20 < demon AND demon <= 35 THEN
(250 - 83.389) * (EXP(LN(1.0099685) * (2 - demon))) - 31.152
WHEN demon <= 20 THEN
(250 - 100.39) * (EXP(LN(1.168) * (1 - demon))) + 100.39

END

WHEN progress < requirement THEN
0.0
ELSE
CASE

WHEN 55 < demon AND demon <= 150 THEN
((56.191 * EXP(LN(2) * ((54.147 - (demon + 3.2)) * LN(50.0)) / 99.0)) + 6.273) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10
WHEN 35 < demon AND demon <= 55 THEN
(212.61 * (EXP(LN(1.036) * (1 - demon))) + 25.071) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10
WHEN 20 < demon AND demon <= 35 THEN
((250 - 83.389) * (EXP(LN(1.0099685) * (2 - demon))) - 31.152) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10
WHEN demon <= 20 THEN
((250 - 100.39) * (EXP(LN(1.168) * (1 - demon))) + 100.39) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10

END
END;
$record_score$
LANGUAGE SQL IMMUTABLE;

CREATE OR REPLACE FUNCTION recompute_player_scores() RETURNS void AS $$
UPDATE players
SET score = q.score
FROM players p
LEFT OUTER JOIN (
SELECT player, SUM(record_score(progress, position, 150, requirement)) as score
FROM score_giving
GROUP BY player
) q
ON q.player = p.id
WHERE players.id = p.id;
$$ LANGUAGE SQL;

CREATE OR REPLACE VIEW ranked_players AS
SELECT
ROW_NUMBER() OVER(ORDER BY players.score DESC, id) AS index,
RANK() OVER(ORDER BY players.score DESC) AS rank,
id, name, players.score, subdivision,
nationalities.iso_country_code,
nationalities.nation,
nationalities.continent
FROM players
LEFT OUTER JOIN nationalities
ON players.nationality = nationalities.iso_country_code
WHERE NOT players.banned AND players.score IS NOT NULL;

CREATE OR REPLACE VIEW score_giving AS
SELECT records.progress, demons.position, demons.requirement, records.player
FROM records
INNER JOIN demons
ON demons.id = records.demon
WHERE records.status_ = 'APPROVED'

UNION

SELECT 100, demons.position, demons.requirement, demons.verifier
FROM demons;


SELECT recompute_player_scores();
SELECT recompute_nation_scores();
SELECT recompute_subdivision_scores();
68 changes: 68 additions & 0 deletions migrations/20250811220551_no_coalesce_score.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
-- Add down migration script here
CREATE OR REPLACE FUNCTION record_score(progress FLOAT, demon FLOAT, list_size FLOAT, requirement FLOAT) RETURNS FLOAT AS
$record_score$
SELECT CASE
WHEN progress = 100 THEN
CASE

WHEN 55 < demon AND demon <= 150 THEN
(56.191 * EXP(LN(2) * ((54.147 - (demon + 3.2)) * LN(50.0)) / 99.0)) + 6.273
WHEN 35 < demon AND demon <= 55 THEN
212.61 * (EXP(LN(1.036) * (1 - demon))) + 25.071
WHEN 20 < demon AND demon <= 35 THEN
(250 - 83.389) * (EXP(LN(1.0099685) * (2 - demon))) - 31.152
WHEN demon <= 20 THEN
(250 - 100.39) * (EXP(LN(1.168) * (1 - demon))) + 100.39

END

WHEN progress < requirement THEN
0.0
ELSE
CASE

WHEN 55 < demon AND demon <= 150 THEN
((56.191 * EXP(LN(2) * ((54.147 - (demon + 3.2)) * LN(50.0)) / 99.0)) + 6.273) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10
WHEN 35 < demon AND demon <= 55 THEN
(212.61 * (EXP(LN(1.036) * (1 - demon))) + 25.071) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10
WHEN 20 < demon AND demon <= 35 THEN
((250 - 83.389) * (EXP(LN(1.0099685) * (2 - demon))) - 31.152) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10
WHEN demon <= 20 THEN
((250 - 100.39) * (EXP(LN(1.168) * (1 - demon))) + 100.39) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10

END
END;
$record_score$
LANGUAGE SQL IMMUTABLE;

CREATE OR REPLACE FUNCTION recompute_player_scores() RETURNS void AS $$
UPDATE players
SET score = coalesce(q.score, 0)
FROM players p
LEFT OUTER JOIN (
SELECT player, SUM(record_score(progress, position, 150, requirement)) as score
FROM score_giving
GROUP BY player
) q
ON q.player = p.id
WHERE players.id = p.id;
$$ LANGUAGE SQL;

CREATE OR REPLACE VIEW ranked_players AS
SELECT
ROW_NUMBER() OVER(ORDER BY players.score DESC, id) AS index,
RANK() OVER(ORDER BY players.score DESC) AS rank,
id, name, players.score, subdivision,
nationalities.iso_country_code,
nationalities.nation,
nationalities.continent
FROM players
LEFT OUTER JOIN nationalities
ON players.nationality = nationalities.iso_country_code
WHERE NOT players.banned AND players.score > 0.0;

SELECT recompute_player_scores();

ALTER TABLE players
ALTER COLUMN score
SET NOT NULL;
70 changes: 70 additions & 0 deletions migrations/20250811220551_no_coalesce_score.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
-- Add up migration script here

ALTER TABLE players
ALTER COLUMN score
DROP NOT NULL;

CREATE OR REPLACE FUNCTION record_score(progress FLOAT, demon FLOAT, list_size FLOAT, requirement FLOAT) RETURNS FLOAT AS
$record_score$
SELECT CASE
WHEN demon > 150 THEN 0.0
WHEN demon > 75 AND progress < 100 THEN 0.0
WHEN progress < requirement THEN 0.0
WHEN progress = 100 THEN
CASE
WHEN 55 < demon AND demon <= 150 THEN
(56.191 * EXP(LN(2) * ((54.147 - (demon + 3.2)) * LN(50.0)) / 99.0)) + 6.273
WHEN 35 < demon AND demon <= 55 THEN
212.61 * (EXP(LN(1.036) * (1 - demon))) + 25.071
WHEN 20 < demon AND demon <= 35 THEN
(250 - 83.389) * (EXP(LN(1.0099685) * (2 - demon))) - 31.152
WHEN demon <= 20 THEN
(250 - 100.39) * (EXP(LN(1.168) * (1 - demon))) + 100.39
ELSE
0.0
END
ELSE
CASE

WHEN 55 < demon AND demon <= 150 THEN
((56.191 * EXP(LN(2) * ((54.147 - (demon + 3.2)) * LN(50.0)) / 99.0)) + 6.273) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10
WHEN 35 < demon AND demon <= 55 THEN
(212.61 * (EXP(LN(1.036) * (1 - demon))) + 25.071) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10
WHEN 20 < demon AND demon <= 35 THEN
((250 - 83.389) * (EXP(LN(1.0099685) * (2 - demon))) - 31.152) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10
WHEN demon <= 20 THEN
((250 - 100.39) * (EXP(LN(1.168) * (1 - demon))) + 100.39) * (EXP(LN(5) * (progress - requirement) / (100 - requirement))) / 10
ELSE
0.0
END
END;
$record_score$
LANGUAGE SQL IMMUTABLE;

CREATE OR REPLACE FUNCTION recompute_player_scores() RETURNS void AS $$
UPDATE players
SET score = q.score
FROM players p
LEFT OUTER JOIN (
SELECT player, SUM(record_score(progress, position, 150, requirement)) as score
FROM score_giving
GROUP BY player
) q
ON q.player = p.id
WHERE players.id = p.id;
$$ LANGUAGE SQL;

CREATE OR REPLACE VIEW ranked_players AS
SELECT
ROW_NUMBER() OVER(ORDER BY players.score DESC, id) AS index,
RANK() OVER(ORDER BY players.score DESC) AS rank,
id, name, players.score, subdivision,
nationalities.iso_country_code,
nationalities.nation,
nationalities.continent
FROM players
LEFT OUTER JOIN nationalities
ON players.nationality = nationalities.iso_country_code
WHERE NOT players.banned AND players.score IS NOT NULL;

SELECT recompute_player_scores();
8 changes: 4 additions & 4 deletions pointercrate-demonlist/src/player/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub struct Player {
/// - Player updates
/// * Player banned
/// * Player objects merged
pub score: f64,
pub score: Option<f64>,
pub rank: Option<i64>,
pub nationality: Option<Nationality>,
}
Expand All @@ -68,7 +68,7 @@ pub struct Player {
impl Hash for Player {
fn hash<H: Hasher>(&self, state: &mut H) {
self.base.hash(state);
((self.score * 100f64) as u64).hash(state);
((self.score.unwrap_or(0.0) * 100f64) as u64).hash(state);
self.nationality.hash(state);
}
}
Expand All @@ -83,10 +83,10 @@ impl Taggable for FullPlayer {

impl DatabasePlayer {
/// Recomputes this player's score and updates it in the database.
pub async fn update_score(&self, connection: &mut PgConnection) -> Result<f64, CoreError> {
pub async fn update_score(&self, connection: &mut PgConnection) -> Result<Option<f64>, CoreError> {
// No need to specially handle banned players - they have no approved records, so `score_of_player` will return 0
let new_score = sqlx::query!(
"UPDATE players SET score = coalesce(score_of_player($1), 0) WHERE id = $1 RETURNING score",
"UPDATE players SET score = score_of_player($1) WHERE id = $1 RETURNING score",
self.id
)
.fetch_one(&mut *connection)
Expand Down
Loading
Loading