Roblox/luau_corpus huggingface dataset:
--[[Engine]]
	--Torque Curve
	Tune.Horsepower		= 209		--	[TORQUE CURVE VISUAL]
	Tune.IdleRPM		= 700		--		https://www.desmos.com/calculator/2uo3hqwdhf
	Tune.PeakRPM		= 6000		--		Use sliders to manipulate values
	Tune.Redline		= 6700		--		Copy and paste slider values into the respective tune values
	Tune.EqPoint		= 5500
	Tune.PeakSharpness	= 7.5
	Tune.CurveMult		= 0.16
	
	--Incline Compensation
	Tune.InclineComp	= 1.7			-- Torque compensation multiplier for inclines (applies gradient from 0-90 degrees)
	
	--Misc
	Tune.RevAccel		= 150		-- RPM acceleration when clutch is off
	Tune.RevDecay		= 75		-- RPM decay when clutch is off
	Tune.RevBounce		= 500		-- RPM kickback from redline
	Tune.IdleThrottle	= 3			-- Percent throttle at idle
	Tune.ClutchTol		= 500		-- Clutch engagement threshold (higher = faster response)
-- updates length of the Bezier
function Bezier:UpdateLength()
	-- important values
	local points = self:GetAllPoints()
	local iterations = self.LengthIterations

	-- check if points is less than 2 (need at least 2 points to calculate length)
	if #points < 2 then
		return 0, {{0, 0, 0}, {0, 0, 0}}
	end

	-- start iteration
	local l = 0
	local sums = {}
	for i = 1, iterations do
		local dldt = self:CalculateDerivativeAt((i - 1) / (iterations - 1))
		l += dldt.Magnitude * (1 / iterations)
		table.insert(sums, {((i - 1) / (iterations - 1)), l, dldt})
	end

	-- return length and sum table
	self.Length, self.LengthIndeces = l, sums
end
-- dayLength defines how long, in minutes, a day in your game is. Feel free to alter it.
local dayLength = 4

local cycleTime = dayLength*60
local minutesInADay = 24*60

local lighting = game:GetService("Lighting")

local startTime = tick() - (lighting:getMinutesAfterMidnight() / minutesInADay)*cycleTime
local endTime = startTime + cycleTime

local timeRatio = minutesInADay / cycleTime

if dayLength == 0 then
	dayLength = 1
end

repeat
	local currentTime = tick()
	
	if currentTime > endTime then
		startTime = endTime
		endTime = startTime + cycleTime
	end
	
	lighting:setMinutesAfterMidnight((currentTime - startTime)*timeRatio)
	wait(1/15)
until false
-- ROBLOX deviation: predefine variables
local isTaggedTemplateLiteral, isEmptyString, isEmptyTable, pluralize

type TemplateData = Global_TemplateData

local EXPECTED_COLOR = chalk.green
local RECEIVED_COLOR = chalk.red

local function validateArrayTable(table_: unknown): ()
	if not Array.isArray(table_) then
		error(
			Error.new(
				"`.each` must be called with an Array or Tagged Template Literal.\n\n"
					.. ("Instead was called with: %s\n"):format(pretty(table_, { maxDepth = 1, min = true }))
			)
		)
	end

	if isTaggedTemplateLiteral(table_) then
		if isEmptyString(table_[1]) then
			error(Error.new("Error: `.each` called with an empty Tagged Template Literal of table data.\n"))
		end
		error(
			Error.new(
				"Error: `.each` called with a Tagged Template Literal with no data, remember to interpolate with ${expression} syntax.\n"
			)
		)
	end

	if isEmptyTable(table_) then
		error(Error.new("Error: `.each` called with an empty Array of table data.\n"))
	end
end
exports.validateArrayTable = validateArrayTable

function isTaggedTemplateLiteral(array: any)
	return array.raw ~= nil
end

function isEmptyTable(table_: Array<unknown>)
	return #table_ == 0
end

function isEmptyString(str: string | unknown)
	return typeof(str) == "string" and String.trim(str) == ""
end

local function validateTemplateTableArguments(headings: Array<string>, data: TemplateData): ()
	-- ROBLOX deviation START: dealing with arrays instead of a variadic list of values, error if any has less or more elements
	Array.forEach(data, function(array, index)
		local countDifference = #headings - #array
		local missingData = if countDifference >= 0 then countDifference else (countDifference - #headings)

		if missingData ~= 0 then
			error(
				Error.new(
					("%s arguments supplied for given headings:\n"):format(
						if countDifference > 0 then "Not enough" else "Too many"
					)
						.. tostring(EXPECTED_COLOR(Array.join(headings, " | ")))
						.. "\n\n"
						.. "Received:\n"
						.. tostring(RECEIVED_COLOR(pretty(data)))
						.. "\n\n"
						.. ("%s %s %s in row %d"):format(
							if countDifference > 0 then "Missing" else "Remove",
							RECEIVED_COLOR(tostring(missingData)),
							pluralize("argument", missingData),
							index
						)
				)
			)
		end
	end)
	-- ROBLOX deviation END
end
exports.validateTemplateTableArguments = validateTemplateTableArguments

function pluralize(word: string, count: number)
	return word .. (if count == 1 then "" else "s")
end
--NOTE: Ugly!
local function OnKeyDown(key)
	key = string.lower(key)
	if key == 'e' then
		local now = time()
		if now > LastSummonTime + SUMMON_COOLDOWN then
			LastSummonTime = now
			local humanoid = MyModel:FindFirstChild('Humanoid')
			if humanoid then
				humanoid.WalkSpeed = 0
			end
			Spawn(function()
				for i = 1, 3 do
					if GongSound then GongSound:Play() end
					wait(1.5)
				end
			end)
			if SummonTrack then
				SummonTrack:Play()
				wait(3.125)
			end
			RaiseSkeletons()
			wait(1)
			if humanoid then
				humanoid.WalkSpeed = 18
			end
		end
	end
end

local function OnEquipped(mouse)
	MyModel = Tool.Parent
	mouse.KeyDown:connect(OnKeyDown)

	local humanoid = MyModel:FindFirstChild('Humanoid')
	if humanoid then -- Preload animations
		SummonTrack = humanoid:LoadAnimation(SummonAnimation)
	end
end

local function OnUnequipped()
	if SummonTrack then SummonTrack:Stop() end
end
--------|    Reference    |--------
local StarterGui = game:GetService("StarterGui")
--// Damage Settings	
	BaseDamage = 46; -- Torso Damage
	LimbDamage = 39; -- Arms and Legs
	ArmorDamage = 42; -- How much damage is dealt against armor (Name the armor "Armor")
	HeadDamage = 73; -- If you set this to 100, there's a chance the player won't die because of the heal script
-- If you want to know how to retexture a hat, read this:  http://www.roblox.com/Forum/ShowPost.aspx?PostID=10502388








debounce = true

function onTouched(hit)
	if (hit.Parent:findFirstChild("Humanoid") ~= nil and debounce == true) then
		debounce = false
		h = Instance.new("Hat")
		p = Instance.new("Part")
		h.Name = "Hat"   -- It doesn't make a difference, but if you want to make your place in Explorer neater, change this to the name of your hat.
		p.Parent = h
		p.Position = hit.Parent:findFirstChild("Head").Position
		p.Name = "Handle" 
		p.formFactor = 0
		p.Size = Vector3.new(-0,-0,-1) 
		p.BottomSurface = 0 
		p.TopSurface = 0 
		p.Locked = true 
		script.Parent.Mesh:clone().Parent = p
		h.Parent = hit.Parent
		h.AttachmentPos = Vector3.new(0, 0.07, 0.2) -- Change these to change the positiones of your hat, as I said earlier.
		wait(5)		debounce = true
	end
end

script.Parent.Touched:connect(onTouched)
-- Global camera variables
local OFFSET = CFrame.new(0, 8, 40)
local PIVOT = CFrame.new(0, 3.5, -1.1)
-- Public Functions

function DisplayManager:StartIntermission(player)
	if player then
		DisplayIntermission:FireClient(player, true)
	else
		DisplayIntermission:FireAllClients(true)
	end
end

function DisplayManager:StopIntermission(player)
	if player then
		DisplayIntermission:FireClient(player, false)
	else
		DisplayIntermission:FireAllClients(false)
	end
end

function DisplayManager:DisplayNotification(teamColor, message)
	DisplayNotification:FireAllClients(teamColor, message)
end

function DisplayManager:UpdateTimerInfo(isIntermission, waitingForPlayers)
	DisplayTimerInfo:FireAllClients(isIntermission, waitingForPlayers)
end

function DisplayManager:DisplayVictory(winningTeam)
	DisplayVictory:FireAllClients(winningTeam)
end

function DisplayManager:UpdateScore(team, score)
	DisplayScore:FireAllClients(team, score)
end

return DisplayManager
-- 21/5/2018 --
-- SLAPPING INTENSIFIES --
local npc = script.Parent
local hum = npc.Humanoid
local speed = npc.Speed
local decalp = npc.Head

while true do
	local waittime = 2/speed.Value
	local oldwalkspeed = hum.WalkSpeed
	decalp.Beam.Texture = "http://www.roblox.com/asset/?id=1814500416"
	decalp.Slap:Play()
	
	wait(0.4)
	
	hum.WalkSpeed = 0
	decalp.Beam.Texture = "http://www.roblox.com/asset/?id=1814499405"
	
	wait(waittime)
	
	hum.WalkSpeed = oldwalkspeed
end
-- Public Methods

function DraggerClass:Destroy()
	self._Maid:Sweep()
	self.DragChanged = nil
	self.DragStart = nil
	self.DragStop = nil
	self.Element = nil
end
------------------------------------------------------------------------
-- stuff
do
	script.Parent.Equipped:connect(function()
		if player == nil then
			player = game.Players:GetPlayerFromCharacter(script.Parent.Parent)
		end
		if character == nil or character.Parent == nil then
			character = script.Parent.Parent
			humanoid = character.Humanoid
				isR15 = humanoid.RigType == Enum.HumanoidRigType.R15
			rightHand = isR15 and character:WaitForChild("RightHand") or character:WaitForChild("Right Arm")
		end
		local getWeld = rightHand:WaitForChild("RightGrip")		
		
		
		--motor.C0 = getWeld.C0
		--motor.C1 = getWeld.C1
		
		getWeld:Destroy()
	
	end)
end
-- Waits for the child of the specified parent
local function WaitForChild(parent, childName)
	while not parent:FindFirstChild(childName) do parent.ChildAdded:wait() end
	return parent[childName]
end

local Tool = script.Parent

local Animations = {}
local MyHumanoid
local MyCharacter


local function PlayAnimation(animationName)
	if Animations[animationName] then
		Animations[animationName]:Play()
	end
end

local function StopAnimation(animationName)
	if Animations[animationName] then
		Animations[animationName]:Stop()
	end
end


function OnEquipped(mouse)
	MyCharacter = Tool.Parent
	MyHumanoid = WaitForChild(MyCharacter, 'Humanoid')
	if MyHumanoid then
		Animations['EquipAnim'] = MyHumanoid:LoadAnimation(WaitForChild(Tool, 'EquipAnim5'))
	end
	PlayAnimation('EquipAnim')
end

function OnUnequipped()
	for animName, _ in pairs(Animations) do
		StopAnimation(animName)
	end
end

Tool.Equipped:connect(OnEquipped)
Tool.Unequipped:connect(OnUnequipped)

WaitForChild(Tool, 'PlaySlash').Changed:connect(
	function (value)
		--if value then
			PlayAnimation('SlashAnim')
		--else
		--	StopAnimation('SlashAnim')
		--end
	end)

WaitForChild(Tool, 'PlayThrust').Changed:connect(
	function (value)
		--if value then
			PlayAnimation('ThrustAnim')
		--else
		--	StopAnimation('ThrustAnim')
		--end
	end)

WaitForChild(Tool, 'PlayOverhead').Changed:connect(
	function (value)
		--if value then
			PlayAnimation('OverheadAnim')
		--else
		--	StopAnimation('OverheadAnim')
		--end
	end)
-- Seconds before player spawns after death:

			SpawnDelayTime = 3

			-- ROBLOX default is 5
			-- Set to 0 for instant-spawn



OnDeath_Callback = function(player) -- Optional function for anyone who wants some sort of code to run when the player dies and before they spawn

	print(player.Name .. " died. Awaiting respawn.")

end
-----------------------
--| Local Functions |--
-----------------------

local math_abs = math.abs

local function OnCameraSubjectChanged()
	VehicleParts = {}

	local newSubject = Camera.CameraSubject
	if newSubject then
		-- Determine if we should be popping at all
		PopperEnabled = false
		for _, subjectType in pairs(VALID_SUBJECTS) do
			if newSubject:IsA(subjectType) then
				PopperEnabled = true
				break
			end
		end

		-- Get all parts of the vehicle the player is controlling
		if newSubject:IsA('VehicleSeat') then
			VehicleParts = newSubject:GetConnectedParts(true)
		end
	
		if FFlagUserPortraitPopperFix then
			if newSubject:IsA("BasePart") then
				SubjectPart = newSubject
			elseif newSubject:IsA("Model") then
				SubjectPart = newSubject.PrimaryPart
			elseif newSubject:IsA("Humanoid") then
				SubjectPart = newSubject.Torso
  			end
  		end
  	end
end

local function OnCharacterAdded(player, character)
	PlayerCharacters[player] = character
end

local function OnPlayersChildAdded(child)
	if child:IsA('Player') then
		child.CharacterAdded:connect(function(character)
			OnCharacterAdded(child, character)
		end)
		if child.Character then
			OnCharacterAdded(child, child.Character)
		end
	end
end

local function OnPlayersChildRemoved(child)
	if child:IsA('Player') then
		PlayerCharacters[child] = nil
	end
end
 
 local function OnWorkspaceChanged(property)
 	if property == 'CurrentCamera' then
 		local newCamera = workspace.CurrentCamera
  		if newCamera then
  			Camera = newCamera

			if CameraSubjectChangeConn then
				CameraSubjectChangeConn:disconnect()
			end

			CameraSubjectChangeConn = Camera:GetPropertyChangedSignal("CameraSubject"):connect(OnCameraSubjectChanged)
			OnCameraSubjectChanged()
  		end
	end
end
--// # key, ManOn
mouse.KeyDown:connect(function(key)
	if key=="f" then 
		veh.Lightbar.middle.Man:Play()
		veh.Lightbar.middle.Wail.Volume = 2
		veh.Lightbar.middle.Yelp.Volume = 2
		veh.Lightbar.middle.Priority.Volume = 2
		script.Parent.Parent.Sirens.Man.BackgroundColor3 = Color3.fromRGB(215, 135, 110)
		veh.Lightbar.MANUAL.Transparency = 0
	end
end)
-- Do not require this module directly! Use normal `invariant` calls with
-- template literal strings. The messages will be replaced with error codes
-- during build.

local HttpService = game:GetService("HttpService")

local function formatProdErrorMessage(code, ...)
	local url = "https://reactjs.org/docs/error-decoder.html?invariant=" .. tostring(code)
	local argsLength = select("#", ...)
	for i = 1, argsLength, 1 do
		-- deviation: UrlEncode should be equivalent to encodeURIComponent
		url = url .. "&args[]=" .. HttpService:UrlEncode(select(i, ...))
	end
	return string.format(
		"Minified React error #%d; visit %s for the full message or "
			.. "use the non-minified dev environment for full errors and additional "
			.. "helpful warnings.",
		code,
		url
	)
end

return formatProdErrorMessage
---Removing old core handler with new one
script.PlayerStatManager.Parent = script.Parent

local coreHandler = script.Parent:WaitForChild("Core_Handler")
coreHandler:Destroy()
local coreHandlerNew = script:WaitForChild("Core_Handler_New")
local coreHandlerNewClone = coreHandlerNew:Clone()
coreHandlerNewClone.Parent = script.Parent
coreHandlerNewClone.Disabled = false
--	if seat == nil then
--		cnt:disconnect()
--		--print(('no seat')
--		return
--	end
	currentframe = currentframe + 1

	local steer = seat.Steer
	local throttle = seat.Throttle
	local ocu = seat.Occupant

	if ocu ~= nil and ocu.Health > 0 and ocu == game.Players.LocalPlayer.Character.Humanoid then
		if controls.looped ~= nil then
			controls:looped()
		end
		if tick() - pretick >= runTime then
			pretick = tick()
		else
			return
		end
		if throttle == 1 then
			controls:Foward()
		elseif throttle == -1 then
			controls:Backward()
		else
			controls:Idle()
		end
		if steer == 1 then
			controls:RightTurn()
		elseif steer == -1 then
			controls:LeftTurn()
		else
			controls:NormalWheel()
		end
		--if seat.Parent.m.BodyVelocity.Velocity.magnitude <= .001 then
		--	local c = script.Parent.Parent:GetDescendants()
		--	for i = 1,#c do
		--		if c[i]:IsA("BasePart") then
		--			c[i].Velocity = Vector3.new()
		--			c[i].RotVelocity = Vector3.new()
		--		end
		--	end
		--end
	else
		if controls ~= nil and controls.End ~= nil then
			if controls.Anims then
				for i = 1,#controls.Anims do
					controls.Anims[i]:Stop()
				end
			end
			controls:End()
			cnt:Disconnect()
			cnt = nil
		else
			cnt:Disconnect()
			cnt = nil
		end
	end
end)
--
script.Parent.PickLock.MouseButton1Click:Connect(function()
	House.DoAction:InvokeServer('Pick')
end)
--//INSPARE//--
--//WavyGTR//--
local player = game.Players.LocalPlayer
local lightOn = false
--// H key, Man
mouse.KeyUp:connect(function(key)
	if key=="h" then 
		veh.Lightbar.middle.Manual:Stop()
		veh.Lightbar.middle.Wail.Volume = 1
		veh.Lightbar.middle.Yelp.Volume = 1
		veh.Lightbar.middle.Priority.Volume = 1
	end
end)





mouse.KeyDown:connect(function(key)
	if key=="j" then 
		veh.Lightbar.middle.Beep:Play()
veh.Lightbar.RemoteEvent:FireServer(true)
	end
	end)
--			b1.BrickColor = BrickColor.new("Crimson")
--			b1.Material = Enum.Material.SmoothPlastic
			end
			if ((not right) and (not hazards) and (not brake)) then
			b2.BrickColor = BrickColor.new("Crimson")
			b2.Material = Enum.Material.SmoothPlastic
			else
--print("QuickScan Complete")

if fullscan then wait(5) ScanForViruses(game,0,false) end
--variables
local tiles = script.Parent:GetChildren() --tiles/items inside of the model
local tilesize = 6 --diameter of the circle (width)
-- Existance in this list signifies that it is an emote, the value indicates if it is a looping emote
local emoteNames = { wave = false, point = false, dance = true, dance2 = true, dance3 = true, laugh = false, cheer = false}

function configureAnimationSet(name, fileList)
	if (animTable[name] ~= nil) then
		for _, connection in pairs(animTable[name].connections) do
			connection:Disconnect()
		end
	end
	animTable[name] = {}
	animTable[name].count = 0
	animTable[name].totalWeight = 0	
	animTable[name].connections = {}

	-- check for config values
	local config = script:FindFirstChild(name)
	if (config ~= nil) then
--Person299
speed = 80
humanoid = script.Parent.Parent.Parent.Character.Humanoid
script.Parent.Selected:connect(function(m)
	humanoid.WalkSpeed = speed
end)
script.Parent.Deselected:connect(function()
	humanoid.WalkSpeed = 16
end)
--[[
    Generic destroy function
]]
function ClientAvatarComponent:destroy()
end

return ClientAvatarComponent
--Functions
game.Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(char)
		--Varibles
		local head = char.Head
		local newtext = nametag:Clone() --Cloning the text.
		local uppertext = newtext.UpperText
		local humanoid = char.Humanoid
		
		humanoid.DisplayDistanceType = "None"
		
		--Main Text
		newtext.Parent = head
		newtext.Adornee = head
		uppertext.Text = player.Name --Changes the text to the player's name.
		
	end)
end)
--------LEFT DOOR --------

game.Workspace.doorleft.l21.BrickColor = BrickColor.new(1)
game.Workspace.doorleft.l22.BrickColor = BrickColor.new(21)
game.Workspace.doorleft.l23.BrickColor = BrickColor.new(1)
game.Workspace.doorleft.l51.BrickColor = BrickColor.new(21)
game.Workspace.doorleft.l52.BrickColor = BrickColor.new(1)
game.Workspace.doorleft.l53.BrickColor = BrickColor.new(21)
-- ROBLOX FIXME: Can we define ClientChatModules statically in the project config
pcall(function() ChatLocalization = require((game:GetService("Chat") :: any).ClientChatModules.ChatLocalization :: any) end)
if ChatLocalization == nil then ChatLocalization = {} function ChatLocalization:Get(key,default) return default end end
--[[ @brief Adds an element to the heap.
     @param element The element to add.
--]]
function Heap:Insert(element)
	rawset(self, #self + 1, element);
	self:_HeapifyBottomUp(#self);
end
--[[ Script Variables ]]--
while not Players.LocalPlayer do
	task.wait()
end
local LocalPlayer = Players.LocalPlayer
local DPadFrame = nil
local TouchObject = nil
local OnInputEnded = nil		-- defined in Create()
----- Functions
local function startBlocking()
	Status = "Blocking"
	game:GetService("SoundService").SFX.Combat.ActivateBlock:Play()

	local vignetteImageLabel = plr.PlayerGui.Vignette.ImageLabel
	game:GetService("TweenService"):Create(vignetteImageLabel, TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0, false, 0), {ImageTransparency = 0}):Play()

	BlockingRemote:FireServer()
	game.TweenService:Create(workspace.CurrentCamera, TweenInfo.new(.3, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, 0, false, 0), {FieldOfView = 60}):Play()
	hum.WalkSpeed = 7
	gaurdingAnimation:Play()
end

local function stopBlocking()
	Status = "nil"
	game:GetService("SoundService").SFX.Combat.ActivateBlock:Play()

	local vignetteImageLabel = plr.PlayerGui.Vignette.ImageLabel
	game:GetService("TweenService"):Create(vignetteImageLabel, TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0, false, 0), {ImageTransparency = 1}):Play()

	debounce = true
	RemoveBlocking:FireServer()
	game.TweenService:Create(workspace.CurrentCamera, TweenInfo.new(.3, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, 0, false, 0), {FieldOfView = 70}):Play()
	hum.WalkSpeed = 16
	gaurdingAnimation:Stop()
	CooldownModule.New("Block", CD)
	task.wait(CD)
	debounce = false
end

UserInputService.InputBegan:Connect(function(input, isProcessed)
	if isProcessed then return end

	if input.KeyCode == Enum.KeyCode.F then
		if not char.Values:FindFirstChild("Stunned") and not debounce then
			if Status == "nil" then
				startBlocking()
			end
		end
	end
end)

UserInputService.InputEnded:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.F and Status == "Blocking" then
		stopBlocking()
	end
end)
--[[
	Replaces the need to chain FindFirstChild. Starting at baseInstance, will navigate through tuple string arguments until there is no child to be found. 
]]
function DataModelUtils.findFirstDescendant(baseInstance, ...)
	local returningChild = baseInstance
	for _, childName in ipairs({...}) do
		local nextChild = returningChild:FindFirstChild(childName)

		if not nextChild then
			return
		else
			returningChild = nextChild
		end
	end

	return returningChild
end
--[[
	berezaa's method of saving data (from the dev forum):

	What I do and this might seem a little over-the-top but it's fine as long as you're not using datastores
	excessively elsewhere is have a datastore and an ordereddatastore for each player. When you perform a save,
	add a key (can be anything) with the value of os.time() to the ordereddatastore and save a key with the os.time()
	and the value of the player's data to the regular datastore. Then, when loading data, get the highest number from
	the ordered data store (most recent save) and load the data with that as a key.

	Ever since I implemented this, pretty much no one has ever lost data. There's no caches to worry about either
	because you're never overriding any keys. Plus, it has the added benefit of allowing you to restore lost data,
	since every save doubles as a backup which can be easily found with the ordereddatastore

	edit: while there's no official comment on this, many developers including myself have noticed really bad cache
	times and issues with using the same datastore keys to save data across multiple places in the same game. With
	this method, data is almost always instantly accessible immediately after a player teleports, making it useful
	for multi-place games.
--]]

local DataStoreService = game:GetService("DataStoreService")
local Promise = require(script.Parent.Parent.Promise)

local OrderedBackups = {}
OrderedBackups.__index = OrderedBackups

function OrderedBackups:Get()
	return Promise.async(function(resolve)
		resolve(self.orderedDataStore:GetSortedAsync(false, 1):GetCurrentPage()[1])
	end):andThen(function(mostRecentKeyPage)
		if mostRecentKeyPage then
			local recentKey = mostRecentKeyPage.value
			self.dataStore2:Debug("most recent key", mostRecentKeyPage)
			self.mostRecentKey = recentKey

			return Promise.async(function(resolve)
				resolve(self.dataStore:GetAsync(recentKey))
			end)
		else
			self.dataStore2:Debug("no recent key")
			return nil
		end
	end)
end

function OrderedBackups:Set(value)
	local key = (self.mostRecentKey or 0) + 1

	return Promise.async(function(resolve)
		self.dataStore:SetAsync(key, value)
		resolve()
	end):andThen(function()
		return Promise.promisify(function()
			self.orderedDataStore:SetAsync(key, key)
		end)()
	end):andThen(function()
		self.mostRecentKey = key
	end)
end

function OrderedBackups.new(dataStore2)
	local dataStoreKey = dataStore2.Name .. "/" .. dataStore2.UserId

	local info = {
		dataStore2 = dataStore2,
		dataStore = DataStoreService:GetDataStore(dataStoreKey),
		orderedDataStore = DataStoreService:GetOrderedDataStore(dataStoreKey),
	}

	return setmetatable(info, OrderedBackups)
end

return OrderedBackups