I am trying to make a monthly leaderboard. However, it almost never shows a player, and when it does, it displays the all-time survival count, not how many were gained in a given month
The code for the script is below:
local ds = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local DATASTORE_SCOPE = "global"
local SurvivalStats = ds:GetOrderedDataStore("survivalStats", DATASTORE_SCOPE)
local playerStartingSurvivals = {}
local CST_OFFSET = -6 * 3600
local function getCSTTime()
return os.time() + CST_OFFSET
end
local function getCurrentMonthKey()
local dateInfo = os.date("*t", getCSTTime())
return string.format("%04d-%02d", dateInfo.year, dateInfo.month)
end
local function getTimeUntilMonthEnd()
local dateInfo = os.date("*t", getCSTTime())
local nextMonth = dateInfo.month + 1
local nextYear = dateInfo.year
if nextMonth > 12 then
nextMonth = 1
nextYear = nextYear + 1
end
local nextMonthTime = {
year = nextYear,
month = nextMonth,
day = 1,
hour = 0,
min = 0,
sec = 0
}
local nextMonthTimestamp = os.time(nextMonthTime) - CST_OFFSET
local currentTimestamp = getCSTTime()
return nextMonthTimestamp - currentTimestamp
end
local currentMonthKey = getCurrentMonthKey()
local timeUntilReset = getTimeUntilMonthEnd()
local function loadPlayerMonthlySurvival(player)
local dataKey = tostring(player.UserId) .. "_" .. currentMonthKey
local monthlySurvivals = 0
local success, result = pcall(function()
return SurvivalStats:GetAsync(dataKey)
end)
if success and result then
monthlySurvivals = result
end
return monthlySurvivals
end
local function savePlayerSurvival(player)
local leaderstats = player:FindFirstChild("leaderstats")
if leaderstats then
local survivals = leaderstats:FindFirstChild("Survivals")
if survivals then
local startingSurvivals = playerStartingSurvivals[player.UserId] or 0
local monthlySurvivals = math.max(0, survivals.Value - startingSurvivals)
local dataKey = tostring(player.UserId) .. "_" .. currentMonthKey
local success, err = pcall(function()
SurvivalStats:SetAsync(dataKey, monthlySurvivals)
end)
if not success then
warn("Failed to save survival stats for player " .. player.Name .. ": " .. err)
end
end
end
end
local function updateLeaderboardDisplay()
local children = script.Parent:GetChildren()
for i = 1, #children do
local leaderboardRank = children[i]
if leaderboardRank:IsA("Frame") then
leaderboardRank:Destroy()
end
end
local success, errorMsg = pcall(function()
local data = SurvivalStats:GetSortedAsync(false, 10)
local SurvivalsPage = data:GetCurrentPage()
for rankInLB = 1, #SurvivalsPage do
local dataStored = SurvivalsPage[rankInLB]
local dataKey = tostring(dataStored.key)
local underscorePos = dataKey:find("_")
if underscorePos then
local userIdStr = dataKey:sub(1, underscorePos - 1)
local monthKey = dataKey:sub(underscorePos + 1)
if monthKey == currentMonthKey then
local userId = tonumber(userIdStr)
if userId then
local name = Players:GetNameFromUserIdAsync(userId)
if name then
local Survivals = dataStored.value
local template = script:FindFirstChild("Template")
if template then
local newTemplate = template:Clone()
newTemplate.Name = name .. "Leaderboard"
newTemplate.PlrName.Text = name
newTemplate.Rank.Text = "#" .. rankInLB
newTemplate.Survivals.Text = Survivals
newTemplate.Parent = script.Parent
end
end
end
end
end
end
end)
if not success then
warn("Error updating leaderboard: " .. errorMsg)
end
end
local function trackPlayerSurvivals(player)
local leaderstats = player:WaitForChild("leaderstats", 5)
if not leaderstats then return end
local survivals = leaderstats:WaitForChild("Survivals", 5)
if not survivals then return end
if playerStartingSurvivals[player.UserId] == nil then
local existingMonthlySurvivals = loadPlayerMonthlySurvival(player)
playerStartingSurvivals[player.UserId] = survivals.Value - existingMonthlySurvivals
end
savePlayerSurvival(player)
survivals.Changed:Connect(function(newValue)
savePlayerSurvival(player)
updateLeaderboardDisplay()
end)
end
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function()
task.wait(1)
trackPlayerSurvivals(player)
end)
task.spawn(function()
task.wait(2)
trackPlayerSurvivals(player)
end)
end)
for _, player in Players:GetPlayers() do
task.spawn(function()
trackPlayerSurvivals(player)
end)
end
while task.wait(1) do
timeUntilReset = timeUntilReset - 1
local days = math.floor(timeUntilReset / 86400)
local hours = math.floor((timeUntilReset % 86400) / 3600)
local minutes = math.floor((timeUntilReset % 3600) / 60)
local seconds = timeUntilReset % 60
local timeString = string.format("%dd %dh %dm %ds", days, hours, minutes, seconds)
script.Parent.Parent.Parent.ResetTime.Text = "Month ends in: " .. timeString
local newMonthKey = getCurrentMonthKey()
if newMonthKey ~= currentMonthKey or timeUntilReset <= 0 then
currentMonthKey = newMonthKey
timeUntilReset = getTimeUntilMonthEnd()
local players = Players:GetPlayers()
for i = 1, #players do
local plr = players[i]
local leaderstats = plr:FindFirstChild("leaderstats")
if leaderstats then
local survivals = leaderstats:FindFirstChild("Survivals")
if survivals then
playerStartingSurvivals[plr.UserId] = survivals.Value
end
end
end
for i = 1, #players do
local plr = players[i]
savePlayerSurvival(plr)
end
updateLeaderboardDisplay()
end
end
Any and all help is appreciated!