Wiki › Module:PraxiaLeaderboard
Module:PraxiaLeaderboard
Documentation for this module may be created at Module:PraxiaLeaderboard/doc
local p = {}
local API =
"https://www.empireofpraxia.online/ws/leaderboard?skill="
local MAX_LEVEL = 140
local SKILLS = {
{ key = "combat", label = "Combat" },
{ key = "mining", label = "Mining" },
{ key = "woodcutting", label = "Woodcutting" },
{ key = "totem_carving", label = "Totem Carving" },
{ key = "forging", label = "Forging" }
}
local function toNumber(value)
return tonumber(value) or 0
end
local function formatNumber(value)
local text =
tostring(
math.floor(
toNumber(value)
)
)
while true do
local formatted, replacements =
text:gsub(
"^(-?%d+)(%d%d%d)",
"%1,%2"
)
text = formatted
if replacements == 0 then
break
end
end
return text
end
local function getLeaderboard(skillKey)
local url =
API .. mw.uri.encode(skillKey)
local data, errors =
mw.ext.externalData.getExternalData(url)
if errors then
return nil,
table.concat(errors, "; ")
end
if not data then
return nil,
"No leaderboard data was returned."
end
local rows =
data.__json
if type(rows) ~= "table" then
return nil,
"The API response was not recognized as JSON."
end
return rows, nil
end
local function findPlayer(rows, username)
local wanted =
mw.ustring.lower(
mw.text.trim(username)
)
for rank, player in ipairs(rows) do
local currentName =
mw.ustring.lower(
mw.text.trim(
tostring(
player.username or ""
)
)
)
if currentName == wanted then
return {
rank = rank,
level = toNumber(player.level),
experience =
toNumber(player.experience)
}
end
end
return nil
end
local function renderSkillRow(skill, player)
local row =
mw.html.create("div")
:addClass("zone-skill")
local top =
row:tag("div")
:addClass("zone-skill-row")
local label =
top:tag("span")
:wikitext(skill.label)
if player then
label
:tag("span")
:addClass("zone-rank")
:wikitext(" #" .. player.rank)
end
local values =
top:tag("span")
local percentage = 0
if player then
values
:tag("b")
:wikitext(player.level)
values
:tag("span")
:addClass("zone-xp")
:wikitext(
" " ..
formatNumber(
player.experience
) ..
" XP"
)
percentage =
math.floor(
math.min(
100,
math.max(
0,
player.level /
MAX_LEVEL *
100
)
) + 0.5
)
else
values
:tag("b")
:wikitext("Unranked")
end
row
:tag("div")
:addClass("zone-track")
:tag("div")
:addClass("zone-fill")
:css(
"--zone-width",
percentage .. "%"
)
return tostring(row)
end
local function getUsername(frame)
return mw.text.trim(
frame.args.player
or frame:getParent().args.player
or ""
)
end
function p.skills(frame)
local username =
getUsername(frame)
if username == "" then
return
'<div class="zone-loading">' ..
'No player username was supplied.' ..
'</div>'
end
local output = {}
local errors = {}
local found = 0
for _, skill in ipairs(SKILLS) do
local rows, fetchError =
getLeaderboard(skill.key)
local player = nil
if rows then
player =
findPlayer(
rows,
username
)
elseif fetchError then
table.insert(
errors,
skill.label ..
": " ..
fetchError
)
end
if player then
found = found + 1
end
table.insert(
output,
renderSkillRow(
skill,
player
)
)
end
if found == 0 and #errors > 0 then
return
'<div class="zone-loading">' ..
'The official leaderboard could not be reached.' ..
'</div>' ..
'<div class="zone-sync-status">' ..
mw.text.nowiki(
table.concat(
errors,
" | "
)
) ..
'</div>'
end
table.insert(
output,
'<div class="zone-sync-status">' ..
'Live from the ' ..
'[https://www.empireofpraxia.online/#ranks ' ..
'official leaderboard]' ..
'</div>'
)
return table.concat(output)
end
function p.level(frame)
local username =
getUsername(frame)
if username == "" then
return "Level unavailable"
end
local rows =
getLeaderboard("combat")
if not rows then
return "Level unavailable"
end
local player =
findPlayer(
rows,
username
)
if not player then
return "Combat unranked"
end
return
"Level " ..
player.level
end
return p