mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-12-29 11:26:13 +08:00
84 lines
No EOL
2.5 KiB
Lua
84 lines
No EOL
2.5 KiB
Lua
-- Helper to split CSV string into a list
|
|
local function split_csv(csv)
|
|
local result = {}
|
|
for user_id in string.gmatch(csv, '([^,]+)') do
|
|
table.insert(result, user_id)
|
|
end
|
|
return result
|
|
end
|
|
|
|
local redis_call = redis.call
|
|
local leaderboard_scores_key, leaderboard_results_key = KEYS[1], KEYS[2]
|
|
|
|
local min_rank = tonumber(ARGV[1])
|
|
local max_rank = tonumber(ARGV[2])
|
|
local include_scores = ARGV[3]
|
|
local user_ids_csv = ARGV[4]
|
|
|
|
local results = {}
|
|
local scores = {}
|
|
local ranks = {}
|
|
local count = nil
|
|
local min_score = {user_id = nil, score = nil}
|
|
|
|
|
|
-- filtered leaderboard
|
|
if user_ids_csv ~= "" then
|
|
|
|
local filtered_user_ids = split_csv(user_ids_csv)
|
|
local scored_users = {}
|
|
for _, user_id in ipairs(filtered_user_ids) do
|
|
local score = redis_call('ZSCORE', leaderboard_scores_key, user_id)
|
|
if score then
|
|
local number_score = tonumber(score)
|
|
table.insert(scored_users, {user_id = user_id, score = number_score})
|
|
end
|
|
end
|
|
table.sort(scored_users, function(a, b) return a.score > b.score end)
|
|
|
|
|
|
if #scored_users > 0 then
|
|
min_score = {scored_users[#scored_users].user_id, scored_users[#scored_users].score}
|
|
end
|
|
count = #scored_users
|
|
|
|
for i = min_rank + 1, math.min(max_rank + 1, #scored_users) do
|
|
local entry = scored_users[i]
|
|
local user_id = entry.user_id
|
|
local score = tostring(entry.score)
|
|
|
|
local result_data = redis_call('HGET', leaderboard_results_key, user_id)
|
|
|
|
if result_data ~= nil then
|
|
results[#results + 1] = result_data
|
|
|
|
local global_rank = redis_call('ZREVRANK', leaderboard_scores_key, user_id)
|
|
ranks[#ranks + 1] = global_rank or -1 -- -1 if not found
|
|
end
|
|
|
|
if include_scores == "true" then
|
|
scores[#scores + 1] = score
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
-- global leaderboard
|
|
local scores_in_range = redis_call('ZRANGE', leaderboard_scores_key, min_rank, max_rank, 'REV')
|
|
min_score = redis_call('ZRANGE', leaderboard_scores_key, 0, 0, 'WITHSCORES')
|
|
count = redis_call('ZCARD', leaderboard_scores_key)
|
|
|
|
for _, user_id in ipairs(scores_in_range) do
|
|
local result_data = redis_call('HGET', leaderboard_results_key, user_id)
|
|
|
|
if (include_scores == "true") then
|
|
scores[#scores + 1] = redis_call('ZSCORE', leaderboard_scores_key, user_id)
|
|
end
|
|
|
|
if (result_data ~= nil) then
|
|
results[#results + 1] = result_data
|
|
end
|
|
end
|
|
end
|
|
|
|
return {results, scores, count, min_score, ranks} |