diff --git a/sql/init.sql b/sql/init.sql index e350fd3..b80c45c 100644 --- a/sql/init.sql +++ b/sql/init.sql @@ -23,6 +23,9 @@ CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; \i contests/user_contest_feedback.sql \i contests/contest_functions.sql +-- Leaderboard functions +\i leaderboard/leaderboard_functions.sql + -- Grant necessary permissions GRANT USAGE ON SCHEMA public TO anon, authenticated, service_role; GRANT ALL ON ALL TABLES IN SCHEMA public TO anon, authenticated, service_role; diff --git a/sql/leaderboard/leaderboard_functions.sql b/sql/leaderboard/leaderboard_functions.sql new file mode 100644 index 0000000..118607b --- /dev/null +++ b/sql/leaderboard/leaderboard_functions.sql @@ -0,0 +1,50 @@ +-- Create a function to get leaderboard data +CREATE OR REPLACE FUNCTION get_leaderboard() RETURNS TABLE ( + user_id UUID, + username TEXT, + avatar_url TEXT, + github_url TEXT, + problems_solved BIGINT, + earliest_solves_sum BIGINT, + rank BIGINT + ) AS $$ WITH user_stats AS ( + SELECT u.id AS user_id, + u.raw_user_meta_data->>'user_name' AS username, + u.raw_user_meta_data->>'avatar_url' AS avatar_url, + CASE + WHEN u.raw_user_meta_data->>'html_url' IS NOT NULL THEN u.raw_user_meta_data->>'html_url' + ELSE 'https://github.com/' || (u.raw_user_meta_data->>'user_name') + END AS github_url, + COUNT(usp.problem_id)::BIGINT AS problems_solved, + COALESCE( + SUM( + EXTRACT( + EPOCH + FROM usp.solved_at + )::BIGINT + ), + 0 + ) AS earliest_solves_sum + FROM auth.users u + LEFT JOIN user_solved_problems usp ON u.id = usp.user_id + GROUP BY u.id, + u.raw_user_meta_data + HAVING COUNT(usp.problem_id) > 0 + ) +SELECT user_stats.user_id, + user_stats.username, + user_stats.avatar_url, + user_stats.github_url, + user_stats.problems_solved, + user_stats.earliest_solves_sum, + ROW_NUMBER() OVER ( + ORDER BY user_stats.problems_solved DESC, + user_stats.earliest_solves_sum ASC + )::BIGINT AS rank +FROM user_stats +ORDER BY user_stats.problems_solved DESC, + user_stats.earliest_solves_sum ASC; +$$ LANGUAGE SQL SECURITY DEFINER; +-- Grant permissions +GRANT EXECUTE ON FUNCTION get_leaderboard() TO authenticated, + anon; \ No newline at end of file diff --git a/src/lib/components/Header.svelte b/src/lib/components/Header.svelte index b1b7fb6..7cd0e18 100644 --- a/src/lib/components/Header.svelte +++ b/src/lib/components/Header.svelte @@ -186,6 +186,17 @@ $: if ($page) { >Contests +
| + Rank + | ++ User + | ++ Solves + | +
|---|---|---|
| + + {#if entry.rank === 1} + + {entry.rank} + + {:else if entry.rank === 2} + + {entry.rank} + + {:else if entry.rank === 3} + + {entry.rank} + + {:else} + {entry.rank} + {/if} + | +
+
+ {#if entry.avatarUrl}
+
+
+ {entry.username.substring(0, 2).toUpperCase()}
+
+ {/if}
+
+ @{entry.username}
+
+ |
+ + {formatNumber(entry.problemsSolved)} + | +
| + No data available. Start solving problems to appear on the leaderboard! + | +||
Loading leaderboard...
+{error}
+ +