local Q=game:GetService("\068\097\116\097\083\116\111\114\101\083\101\114\118\105\099\101")local m=require(script.Parent.Settings)local V={}V.__index=V function V.new()local Q={}setmetatable(Q,V)Q._dataStoreName=m.DATA_STORE Q._dataStoreStatName=m.NAME_OF_STAT Q._scoreUpdateDelay=m.SCORE_UPDATE*60 Q._boardUpdateDelay=m.LEADERBOARD_UPDATE*60 Q._useLeaderstats=m.USE_LEADERSTATS Q._nameLeaderstats=m.NAME_LEADERSTATS Q._doDebug=m.DO_DEBUG Q._datastore=nil Q._scoreBlock=script.Parent.Model.ScoreBlock Q:_init()return Q end function V._timeToString(m,Q)Q=Q*60 local V=math.floor(Q/86400)local e=math.floor(math.fmod(Q,86400)/3600)local B=math.floor(math.fmod(Q,3600)/60)return string.format("\037\048\050\100\100 \058 \037\048\050\100\104 \058 \037\048\050\100\109",V,e,B)end function V._init(Q)local m,V=pcall(function()Q._datastore=(game:GetService("\068\097\116\097\083\116\111\114\101\083\101\114\118\105\099\101")):GetOrderedDataStore(Q._dataStoreName)end)if not m or Q._datastore==nil then warn("\070\097\105\108\101\100 \116\111 \108\111\097\100 \079\114\100\101\114\101\100\068\097\116\097\083\116\111\114\101\046 \069\114\114\111\114\058",V)script.Parent:Destroy()end if Q._useLeaderstats then(game:GetService("\080\108\097\121\101\114\115")).PlayerAdded:Connect(function(m)task.spawn(function()local V=Instance.new("\078\117\109\098\101\114\086\097\108\117\101")V.Name=Q._nameLeaderstats V.Parent=m:WaitForChild("\108\101\097\100\101\114\115\116\097\116\115")end)end)end task.spawn(function()while true do task.wait(Q._scoreUpdateDelay)Q:_updateScore()end end)task.spawn(function()Q:_updateBoard()while true do task.wait(Q._boardUpdateDelay)Q:_updateBoard()end end)end function V._clearBoard(Q)for Q,m in pairs({Q._scoreBlock.SurfaceGui.Names;Q._scoreBlock.SurfaceGui.Photos;Q._scoreBlock.SurfaceGui.Score})do for Q,m in pairs(m:GetChildren())do m.Visible=false end end end function V._updateBoard(Q)if Q._doDebug then print("\085\112\100\097\116\105\110\103 \098\111\097\114\100")end local m=nil local V,e=pcall(function()return(Q._datastore:GetSortedAsync(false,10,1)):GetCurrentPage()end)if not V or not e then if Q._doDebug then warn("\070\097\105\108\101\100 \116\111 \114\101\116\114\105\101\118\101 \116\111\112 \049\048 \119\105\116\104 \109\111\115\116 \116\105\109\101\046 \069\114\114\111\114\058",e)end return end local B=Q._scoreBlock.SurfaceGui Q._scoreBlock.Credits.Enabled=true Q._scoreBlock.SurfaceGui.Enabled=#e~=0 Q._scoreBlock.NoDataFound.Enabled=#e==0 Q:_clearBoard()for m,V in pairs(e)do local e=tonumber((string.split(V.key,Q._dataStoreStatName))[2])local d=(game:GetService("\080\108\097\121\101\114\115")):GetNameFromUserIdAsync(e)local p=Q:_timeToString(V.value)Q:_onPlayerScoreUpdate(e,V.value)B.Names["\078\097\109\101"..m].Visible=true B.Score["\083\099\111\114\101"..m].Visible=true B.Photos["\080\104\111\116\111"..m].Visible=true B.Names["\078\097\109\101"..m].Text=d B.Score["\083\099\111\114\101"..m].Text=p B.Photos["\080\104\111\116\111"..m].Image=(game:GetService("\080\108\097\121\101\114\115")):GetUserThumbnailAsync(e,Enum.ThumbnailType.HeadShot,Enum.ThumbnailSize.Size150x150)end if Q._scoreBlock:FindFirstChild("\095\098\097\099\107\115\105\100\101")then Q._scoreBlock._backside:Destroy()end local d=Q._scoreBlock.SurfaceGui:Clone()d.Parent=Q._scoreBlock d.Name="\095\098\097\099\107\115\105\100\101"d.Face=Enum.NormalId.Back if Q._doDebug then print("\066\111\097\114\100 \117\112\100\097\116\101\100 \115\117\099\101\115\115\102\117\108\108\121")end end function V._updateScore(Q)local m,V=coroutine.resume(coroutine.create(function()local m=(game:GetService("\080\108\097\121\101\114\115")):GetPlayers()for m,V in pairs(m)do local e=Q._dataStoreStatName..V.UserId local B=Q._datastore:IncrementAsync(e,Q._scoreUpdateDelay/60)if Q._doDebug then print("\073\110\099\114\101\109\101\110\116\101\100 \116\105\109\101 \112\108\097\121\101\100 \115\116\097\116 \111\102",V,e,"\116\111",B)end end end))if not m then warn(V)end end function V._onPlayerScoreUpdate(V,Q,m)if not V._useLeaderstats then return end local e=(game:GetService("\080\108\097\121\101\114\115")):GetPlayerByUserId(Q)if not e or not e:FindFirstChild("\108\101\097\100\101\114\115\116\097\116\115")then return end local B=e.leaderstats[V._nameLeaderstats]B.Value=tonumber(m)end V.new()
--[[
  TimePlayedClass, RenanMSV @2023

  A script designed to update a leaderboard with
  the top 10 players who most play your game.
  
  Do not change this script. All configurations can be found
  in the Settings script.
]]

local DataStoreService = game:GetService("DataStoreService")

local Config = require(script.Parent.Settings)

local TimePlayedClass = {}
TimePlayedClass.__index = TimePlayedClass
function TimePlayedClass.new()
	local new = {}
	setmetatable(new, TimePlayedClass)

	new._dataStoreName = Config.DATA_STORE
	new._dataStoreStatName = Config.NAME_OF_STAT
	new._scoreUpdateDelay = Config.SCORE_UPDATE * 60
	new._boardUpdateDelay = Config.LEADERBOARD_UPDATE * 60
	new._useLeaderstats = Config.USE_LEADERSTATS
	new._nameLeaderstats = Config.NAME_LEADERSTATS
	new._doDebug = Config.DO_DEBUG

	new._datastore = nil
	new._scoreBlock = script.Parent.Model.ScoreBlock

	new:_init()

	return new
end

function TimePlayedClass:_timeToString(_time)
	_time = _time * 60
	local days = math.floor(_time / 86400)
	local hours = math.floor(math.fmod(_time, 86400) / 3600)
	local minutes = math.floor(math.fmod(_time, 3600) / 60)
	return string.format("%02dd : %02dh : %02dm", days, hours, minutes)
end

function TimePlayedClass:_init()
	local suc, err = pcall(function()
		self._datastore = game:GetService("DataStoreService"):GetOrderedDataStore(self._dataStoreName)
	end)
	if not suc or self._datastore == nil then
		warn("Failed to load OrderedDataStore. Error:", err)
		script.Parent:Destroy()
	end

	-- puts leaderstat value in player
	if self._useLeaderstats then
		game:GetService("Players").PlayerAdded:Connect(function(player)
			task.spawn(function()
				local stat = Instance.new("NumberValue")
				stat.Name = self._nameLeaderstats
				stat.Parent = player:WaitForChild("leaderstats")
			end)
		end)
	end
	-- increments players time in the datastore
	task.spawn(function()
		while true do
			task.wait(self._scoreUpdateDelay)
			self:_updateScore()
		end
	end)

	-- update leaderboard
	task.spawn(function()
		self:_updateBoard() -- update once
		while true do
			task.wait(self._boardUpdateDelay)
			self:_updateBoard()
		end
	end)
end

function TimePlayedClass:_clearBoard()
	for _, folder in pairs({
		self._scoreBlock.SurfaceGui.Names,
		self._scoreBlock.SurfaceGui.Photos,
		self._scoreBlock.SurfaceGui.Score,
	}) do
		for _, item in pairs(folder:GetChildren()) do
			item.Visible = false
		end
	end
end

function TimePlayedClass:_updateBoard()
	if self._doDebug then
		print("Updating board")
	end
	local results = nil

	local suc, results = pcall(function()
		return self._datastore:GetSortedAsync(false, 10, 1):GetCurrentPage()
	end)

	if not suc or not results then
		if self._doDebug then
			warn("Failed to retrieve top 10 with most time. Error:", results)
		end
		return
	end

	local sufgui = self._scoreBlock.SurfaceGui
	self._scoreBlock.Credits.Enabled = true
	self._scoreBlock.SurfaceGui.Enabled = #results ~= 0
	self._scoreBlock.NoDataFound.Enabled = #results == 0
	self:_clearBoard()
	for k, v in pairs(results) do
		local userid = tonumber(string.split(v.key, self._dataStoreStatName)[2])
		local name = game:GetService("Players"):GetNameFromUserIdAsync(userid)
		local score = self:_timeToString(v.value)
		self:_onPlayerScoreUpdate(userid, v.value)
		sufgui.Names["Name" .. k].Visible = true
		sufgui.Score["Score" .. k].Visible = true
		sufgui.Photos["Photo" .. k].Visible = true
		sufgui.Names["Name" .. k].Text = name
		sufgui.Score["Score" .. k].Text = score
		sufgui.Photos["Photo" .. k].Image =
			game:GetService("Players")
				:GetUserThumbnailAsync(userid, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size150x150)
	end
	if self._scoreBlock:FindFirstChild("_backside") then
		self._scoreBlock["_backside"]:Destroy()
	end
	local temp = self._scoreBlock.SurfaceGui:Clone()
	temp.Parent = self._scoreBlock
	temp.Name = "_backside"
	temp.Face = Enum.NormalId.Back
	if self._doDebug then
		print("Board updated sucessfully")
	end
end

function TimePlayedClass:_updateScore()
	local suc, err = coroutine.resume(coroutine.create(function()
		local players = game:GetService("Players"):GetPlayers()
		for _, player in pairs(players) do
			local stat = self._dataStoreStatName .. player.UserId
			local newval = self._datastore:IncrementAsync(stat, self._scoreUpdateDelay / 60)
			if self._doDebug then
				print("Incremented time played stat of", player, stat, "to", newval)
			end
		end
	end))
	if not suc then
		warn(err)
	end
end

function TimePlayedClass:_onPlayerScoreUpdate(userid, minutes)
	-- updates leaderstats if enabled
	if not self._useLeaderstats then
		return
	end
	local player = game:GetService("Players"):GetPlayerByUserId(userid)
	if not player or not player:FindFirstChild("leaderstats") then
		return
	end
	local leaderstat = player.leaderstats[self._nameLeaderstats]
	leaderstat.Value = tonumber(minutes)
end

TimePlayedClass.new()
