Problems with a block of code in my script, arithmetic issues for a leaderboard

local dataStoreService = game:GetService("DataStoreService")
local leaderboardStore = dataStoreService:GetOrderedDataStore("MainLeaderboard4")

replicatedStorage.BestTime.OnServerEvent:Connect(function(player, time)
	time = math.floor(time * 1000)
	leaderboardStore:UpdateAsync(player.UserId, function(oldTime)
		oldTime = oldTime or 0
		return math.max(oldTime, time) -- put the bigger time to the leaderboard.
	end)
end)

local LeaderboardPart = workspace:WaitForChild("LeaderBoard")
local surfacegui = LeaderboardPart.LeaderboardGui
local positionLabels = {
	surfacegui:WaitForChild(1),
	surfacegui:WaitForChild(2),
	surfacegui:WaitForChild(3),
	surfacegui:WaitForChild(4),
	surfacegui:WaitForChild(5),
	surfacegui:WaitForChild(6),
	surfacegui:WaitForChild(7),
	surfacegui:WaitForChild(8),
	surfacegui:WaitForChild(9),
	surfacegui:WaitForChild(10),
}

local function updateLeaderboard()
	local leaderboardData = leaderboardStore:GetSortedAsync(true, 10)
	local currentPage = leaderboardData:GetCurrentPage()
	for i, data in ipairs(currentPage) do
		print(time)
		local time = data.value/1000
		local positionLabel = positionLabels[i]
		if positionLabel then
			local player = game:GetService("Players"):GetNameFromUserIdAsync(data.key)
			if player then
				positionLabel.Text = string.format("%d. %s - %d", i, player, time)
			else
				positionLabel.Text = ""
			end
		end
	end
end

replicatedStorage.BestTime.OnServerEvent:Connect(function(player, time)
	time = math.floor(time * 1000)
	leaderboardStore:SetAsync(player.UserId, time)
	updateLeaderboard()
end)

updateLeaderboard()

just change the capital V to lower case. lol

1 Like

Damn… How could I have forgotten that, it all works out now its just the format of the leaderboard does not quite work as I want it to,


It should show the exact time as the personal best as it does on the leaderboard.

assuming that your game is an obby, is the leaderboard changing before and after you somehow made a personal best?

Wait, the leaderboard works it is just that it does not give the exact value, only a whole number

can you explain it more detailed and perhaps attach some images so i can understand better

Sure, so say the value of the best time is 5.359, in the output data key it responds with 5359 but the actual leaderboard only rounds it to the nearest whole number which is 5, is there a way to just make it so that it shows the entire value instead of the whole number? The value uses your personal best score and puts it onto the leaderboard, if your personal best is lower than your new time score it will not update the personal best.

look what’s related to “rounding numbers”,

replicatedStorage.BestTime.OnServerEvent:Connect(function(player, time)
	time = math.floor(time * 1000)
	leaderboardStore:UpdateAsync(player.UserId, function(oldTime)
		oldTime = oldTime or 0
		return math.max(oldTime, time) -- put the bigger time to the leaderboard.
	end)
end)

there’s clearly a math.floor there, which probably caused the issue. try removing math.floor and change the line to time = time * 1000

Done, nothing had changed the exact same outcome had been shown as the last image, I’m checking the script right now for more rounding or arithmetic let me know if you found anything.

sorry for asking again (again) but can you give me the current script?

No worries,

local dataStoreService = game:GetService("DataStoreService")
local leaderboardStore = dataStoreService:GetOrderedDataStore("MainLeaderboard5")

replicatedStorage.BestTime.OnServerEvent:Connect(function(player, time)
   time = time * 1000
   leaderboardStore:UpdateAsync(player.UserId, function(oldTime)
   	oldTime = oldTime or 0
   	return math.max(oldTime, time) -- put the bigger time to the leaderboard.
   end)
end)

local LeaderboardPart = workspace:WaitForChild("LeaderBoard")
local surfacegui = LeaderboardPart.LeaderboardGui
local positionLabels = {
   surfacegui:WaitForChild(1),
   surfacegui:WaitForChild(2),
   surfacegui:WaitForChild(3),
   surfacegui:WaitForChild(4),
   surfacegui:WaitForChild(5),
   surfacegui:WaitForChild(6),
   surfacegui:WaitForChild(7),
   surfacegui:WaitForChild(8),
   surfacegui:WaitForChild(9),
   surfacegui:WaitForChild(10),
}

local function updateLeaderboard()
   local leaderboardData = leaderboardStore:GetSortedAsync(true, 10)
   local currentPage = leaderboardData:GetCurrentPage()
   for i, data in ipairs(currentPage) do
   	print(data)
   	print(time)
   	local time = data.value/1000
   	local positionLabel = positionLabels[i]
   	if positionLabel then
   		local player = game:GetService("Players"):GetNameFromUserIdAsync(data.key)
   		if player then
   			positionLabel.Text = string.format("%d. %s - %d", i, player, time)
   		else
   			positionLabel.Text = ""
   		end
   	end
   end
end

replicatedStorage.BestTime.OnServerEvent:Connect(function(player, time)
   time = math.floor(time * 1000)
   leaderboardStore:SetAsync(player.UserId, time)
   updateLeaderboard()
end)

updateLeaderboard()

anyway can you make the personal best higher? like make it 10 or any higher number then screenshot the leaderboard

i found another math.floor

replicatedStorage.BestTime.OnServerEvent:Connect(function(player, time)
   time = math.floor(time * 1000) -- remove the math.floor
   leaderboardStore:SetAsync(player.UserId, time)
   updateLeaderboard()
end)
updateLeaderboard()

it’s on the bottom

I just tried it and here is the output and leaderboard, the data key for personal best was “13814”

I tried this before and it said in the output ```double is not allowed in data stores.

I’ve added back the math.floor and there is no longer any output errors although they still show whole numbers in the leaderboard. Here is the script so far,

local dataStoreService = game:GetService("DataStoreService")
local leaderboardStore = dataStoreService:GetOrderedDataStore("MainLeaderboard6")

replicatedStorage.BestTime.OnServerEvent:Connect(function(player, time)
	time = math.floor(time * 1000)
	leaderboardStore:UpdateAsync(player.UserId, function(oldTime)
		oldTime = oldTime or 0
		return math.max(oldTime, time) -- put the bigger time to the leaderboard.
	end)
end)

local LeaderboardPart = workspace:WaitForChild("LeaderBoard")
local surfacegui = LeaderboardPart.LeaderboardGui
local positionLabels = {
	surfacegui:WaitForChild(1),
	surfacegui:WaitForChild(2),
	surfacegui:WaitForChild(3),
	surfacegui:WaitForChild(4),
	surfacegui:WaitForChild(5),
	surfacegui:WaitForChild(6),
	surfacegui:WaitForChild(7),
	surfacegui:WaitForChild(8),
	surfacegui:WaitForChild(9),
	surfacegui:WaitForChild(10),
}

local function updateLeaderboard()
	local leaderboardData = leaderboardStore:GetSortedAsync(true, 10)
	local currentPage = leaderboardData:GetCurrentPage()
	for i, data in ipairs(currentPage) do
		print(data)
		print(time)
		local time = data.value/1000
		local positionLabel = positionLabels[i]
		if positionLabel then
			local player = game:GetService("Players"):GetNameFromUserIdAsync(data.key)
			if player then
				positionLabel.Text = string.format("%d. %s - %d", i, player, time)
			else
				positionLabel.Text = ""
			end
		end
	end
end

replicatedStorage.BestTime.OnServerEvent:Connect(function(player, time)
	time = math.floor(time * 1000)
	leaderboardStore:SetAsync(player.UserId, time)
	updateLeaderboard()
end)

updateLeaderboard()
  1. first thing i noticed, is that you used UpdateAsync and SetAsync at the same time.
    just change the bottom code to
replicatedStorage.BestTime.OnServerEvent:Connect(updateLeaderboard)
updateLeaderboard()
  1. “double” is literally decimal numbers, like 1.23, 4.56 etc. so if you dont want to store doubles then you can limit the digits behind the dot limited to 2 digits (i think 3 is too long) with a trick like: math.floor(time*100)/100
    the logic is like this:
    for an example, time is 1.2345
    if we use math.floor(time), it would return 1.
    but, if we multiply it by 100 first it would be equal to: math.floor(123.45) and it will return 123.
    if we divide 123 by 100, it would be 1.23;
    without using code, if we limit 1.2345 to 2 decimal digits it would be 1.23 too.
    but in this case, datastore doesn’t accept doubles (decimals), so we can divide the time stored by 100 when we update the leaderboard.
local dataStoreService = game:GetService("DataStoreService")
local leaderboardStore = dataStoreService:GetOrderedDataStore("MainLeaderboard5")

replicatedStorage.BestTime.OnServerEvent:Connect(function(player, time)
   time = math.floor(time * 100) -- dont divide it by 100 yet, because it would be a double.
   leaderboardStore:UpdateAsync(player.UserId, function(oldTime)
   	oldTime = oldTime or 0
   	return math.max(oldTime, time) -- put the bigger time to the leaderboard.
   end)
end)

local LeaderboardPart = workspace:WaitForChild("LeaderBoard")
local surfacegui = LeaderboardPart.LeaderboardGui
local positionLabels = {
   surfacegui:WaitForChild(1),
   surfacegui:WaitForChild(2),
   surfacegui:WaitForChild(3),
   surfacegui:WaitForChild(4),
   surfacegui:WaitForChild(5),
   surfacegui:WaitForChild(6),
   surfacegui:WaitForChild(7),
   surfacegui:WaitForChild(8),
   surfacegui:WaitForChild(9),
   surfacegui:WaitForChild(10),
}

local function updateLeaderboard()
   local leaderboardData = leaderboardStore:GetSortedAsync(true, 10)
   local currentPage = leaderboardData:GetCurrentPage()
   for i, data in ipairs(currentPage) do
   	print(data)
   	print(time)
   	local time = data.value/100 -- make it a good looking decimal.
   	local positionLabel = positionLabels[i]
   	if positionLabel then
   		local player = game:GetService("Players"):GetNameFromUserIdAsync(data.key)
   		if player then
   			positionLabel.Text = string.format("%d. %s - %d", i, player, time)
   		else
   			positionLabel.Text = ""
   		end
   	end
   end
end

replicatedStorage.BestTime.OnServerEvent:Connect(updateLeaderboard)

updateLeaderboard()

i noticed that i wrote this reply too long, sorry lol

1 Like

Okay so I just tried the script, and the data key is now stuck on 4598 no matter what,

something looks not right, can you give me the current script? (again)

It’s the exact same script you posted but here you go anyways,

local dataStoreService = game:GetService("DataStoreService")
local leaderboardStore = dataStoreService:GetOrderedDataStore("MainLeaderboard5")

replicatedStorage.BestTime.OnServerEvent:Connect(function(player, time)
	time = math.floor(time * 100) -- dont divide it by 100 yet, because it would be a double.
	leaderboardStore:UpdateAsync(player.UserId, function(oldTime)
		oldTime = oldTime or 0
		return math.max(oldTime, time) -- put the bigger time to the leaderboard.
	end)
end)

local LeaderboardPart = workspace:WaitForChild("LeaderBoard")
local surfacegui = LeaderboardPart.LeaderboardGui
local positionLabels = {
	surfacegui:WaitForChild(1),
	surfacegui:WaitForChild(2),
	surfacegui:WaitForChild(3),
	surfacegui:WaitForChild(4),
	surfacegui:WaitForChild(5),
	surfacegui:WaitForChild(6),
	surfacegui:WaitForChild(7),
	surfacegui:WaitForChild(8),
	surfacegui:WaitForChild(9),
	surfacegui:WaitForChild(10),
}

local function updateLeaderboard()
	local leaderboardData = leaderboardStore:GetSortedAsync(true, 10)
	local currentPage = leaderboardData:GetCurrentPage()
	for i, data in ipairs(currentPage) do
		print(data)
		print(time)
		local time = data.value/100 -- make it a good looking decimal.
		local positionLabel = positionLabels[i]
		if positionLabel then
			local player = game:GetService("Players"):GetNameFromUserIdAsync(data.key)
			if player then
				positionLabel.Text = string.format("%d. %s - %d", i, player, time)
			else
				positionLabel.Text = ""
			end
		end
	end
end

replicatedStorage.BestTime.OnServerEvent:Connect(updateLeaderboard)

updateLeaderboard()

mb it was my mistake from the beginning, it was supposed to be math.min not math.max since the leaderboard is showing people who finished it the quickest.

local dataStoreService = game:GetService("DataStoreService")
local leaderboardStore = dataStoreService:GetOrderedDataStore("MainLeaderboard5")

replicatedStorage.BestTime.OnServerEvent:Connect(function(player, time)
	time = math.floor(time * 100) -- dont divide it by 100 yet, because it would be a double.
	leaderboardStore:UpdateAsync(player.UserId, function(oldTime)
		oldTime = oldTime or 0
		return math.min(oldTime, time) -- put the bigger time to the leaderboard.
	end)
end)

local LeaderboardPart = workspace:WaitForChild("LeaderBoard")
local surfacegui = LeaderboardPart.LeaderboardGui
local positionLabels = {
	surfacegui:WaitForChild(1),
	surfacegui:WaitForChild(2),
	surfacegui:WaitForChild(3),
	surfacegui:WaitForChild(4),
	surfacegui:WaitForChild(5),
	surfacegui:WaitForChild(6),
	surfacegui:WaitForChild(7),
	surfacegui:WaitForChild(8),
	surfacegui:WaitForChild(9),
	surfacegui:WaitForChild(10),
}

local function updateLeaderboard()
	local leaderboardData = leaderboardStore:GetSortedAsync(true, 10)
	local currentPage = leaderboardData:GetCurrentPage()
	for i, data in ipairs(currentPage) do
		print(data)
		print(time)
		local time = data.value/100 -- make it a good looking decimal.
		local positionLabel = positionLabels[i]
		if positionLabel then
			local player = game:GetService("Players"):GetNameFromUserIdAsync(data.key)
			if player then
				positionLabel.Text = string.format("%d. %s - %d", i, player, time)
			else
				positionLabel.Text = ""
			end
		end
	end
end

replicatedStorage.BestTime.OnServerEvent:Connect(updateLeaderboard)

updateLeaderboard()