(Solved) Edit 2: I heavily edited this post again and deleted unnecessary part so that maybe other people who are having the same problem could read it and actually find the solution. Thanks.
I have a problem to fix a leaderboard that would somehow make players with the worst time of speedrun(the highest in time) to be placed onto the top of the list(still shows the same speedrun time tho).
Here are the relevant scripts
Server
local function fetchGlobalLeaderboardData()
local leaderboardData = {}
local function getDataStorePage()
return orderedDataStore:GetSortedAsync(true, 50):GetCurrentPage() -- Sorting in ascending order (smallest time on top)
end
local success, data = retryWithExponentialBackoff(getDataStorePage, 5, false)
if success then
for _, entry in ipairs(data) do
local userId = tonumber(entry.key)
local username = "Unknown"
if userId then
local success, result = pcall(Players.GetNameFromUserIdAsync, Players, userId)
if success then
username = result
else
warn("Failed to get username for UserId:", userId, ":", result)
end
end
local timeInSeconds = entry.value / 1000
if timeInSeconds > MINIMUM_TIME_THRESHOLD then
table.insert(leaderboardData, {
userId = userId,
username = username,
time = timeInSeconds
})
end
end
else
warn("Failed to fetch global leaderboard data for Tower1:", data)
end
-- Sort data by their time (ascending)
table.sort(leaderboardData, function(a, b)
return a.time < b.time
end)
return leaderboardData
end
-- skip the other unrelevant parts
local function updateLeaderboard()
local success, leaderboardData = pcall(fetchGlobalLeaderboardData)
print("Fetched leaderboard data:", leaderboardData)
if not success then
warn("Failed to update leaderboard:", leaderboardData)
return
end
UpdateLeaderboardEventTower1:FireAllClients(leaderboardData)
for i, data in ipairs(leaderboardData) do
if data.time > MINIMUM_TIME_THRESHOLD then
local userId = data.userId
local username = data.username
local stand
if i == 1 then
stand = FirstPlaceStand
elseif i == 2 then
stand = SecondPlaceStand
elseif i == 3 then
stand = ThirdPlaceStand
end
if stand then
applyAppearanceToDummy(stand, userId, username, i)
local animationId = LeaderboardTower1:WaitForChild("AnimationToPlay").AnimationId
AnimationPlayer.playAnimation(stand, animationId)
-- Check and grant badge if applicable
if userId then
local player = Players:GetPlayerByUserId(userId)
if player then
grantSpeedrunBadge(player, data.time)
end
else
warn("Invalid UserId:", userId)
end
end
end
end
end
while true do
updateLeaderboard()
wait(LEADERBOARD_UPDATE_INTERVAL)
end
Client
local function updateLeaderboardGui(leaderboardData)
print("Received leaderboard data:", leaderboardData)
-- Sort leaderboard data by time (ascending)
table.sort(leaderboardData, function(a, b)
return a.time < b.time
end)
-- Delete the existing entries and then create the new entries afterwards, the problem could be lying here somewhere I believe
for _, data in ipairs(leaderboardData) do
if data.time > MINIMUM_TIME_THRESHOLD then
-- Delete existing entry if it exists
local existingEntry = ListContent.Items:FindFirstChild(data.username)
if existingEntry then
existingEntry:Destroy()
end
-- Create a new entry
local entry = Sample:Clone()
entry.Name = data.username
entry.Values.Username.Text = data.username
entry.Values.Tower1.Text = string.format("%.2f", data.time) -- Format time to 2 decimal
entry.Parent = ListContent.Items
entry.Visible = true
end
end
-- Adjust the position of each entry
local entries = ListContent.Items:GetChildren()
local entryCount = 0 -- This is to track the valid entries to skip the original Sample
for i, entry in ipairs(entries) do
if entry ~= Sample then -- We skip the original Sample entry
if entry:IsA("GuiObject") then
entryCount = entryCount + 1
entry.LayoutOrder = entryCount
if entry:FindFirstChild("Values") and entry.Values:FindFirstChild("Index") then
entry.Values.Index.Text = tostring(entryCount) -- Set the index number
-- Apply special colors based on index basically
if entryCount == 1 then
entry.Values.Index.TextColor3 = Color3.fromRGB(255, 215, 0) -- Gold color
elseif entryCount == 2 then
entry.Values.Index.TextColor3 = Color3.fromRGB(192, 192, 192) -- Silver color
elseif entryCount == 3 then
entry.Values.Index.TextColor3 = Color3.fromRGB(205, 127, 50) -- Bronze color
else
entry.Values.Index.TextColor3 = Color3.fromRGB(0, 0, 0) -- Default color
end
end
end
end
end
end
UpdateLeaderboardEvent.OnClientEvent:Connect(function(leaderboardData)
updateLeaderboardGui(leaderboardData)
end)
Also for anyone wondering what datastore I’m using, it’s Suphi’s Datastore thanks @5uphi !!
TLDR; 1st problem: The leaderboard in my game somehow would show players with the worst ranking to be at the top of the ranking for some reason yet still stores the same data for each username. And it keeps putting the player from the worst rankings to the top(as if it’s trying to recreate the data over again but one by one.). Weird thing is that the worst of the worst(sorry hehe) data doesn’t get updated to the top though.
Edit3: I solved the problem. Look at the marked as solved. Also I believe the exponential backoff is not important at all.