Roblox/luau_corpus huggingface dataset:
--check mass to see if object is large enough to spray blood on
if dmg<1000 then
	for x = 1, math.floor(dmg*(math.random(1,7)*.105)) do
		local bloodRay = Ray.new(origin,(game.Players.LocalPlayer.Character.Torso.CFrame.p.unit * Vector3.new(math.random(-7,7)/60,math.random(-7,7)/60,math.random(-7,7)/60)).unit * 12)
		local hitPart, hitPoint = workspace:FindPartOnRayWithIgnoreList(bloodRay,{workspace.CurrentCamera,humanoid.Parent})
		if hitPart and hitPart.Transparency==0 and hitPart:GetMass() > 5 and hitPart.Anchored then
			local blood = Instance.new("Part",game.Workspace["Ray_Ignore"])

			blood.formFactor = "Custom"
			blood.Size = Vector3.new(math.random(1,3600)*.001,0.2,math.random(1,3600)*.001)
			blood.BrickColor = BrickColor.new("Bright red")
			blood.Anchored = true
			blood.CanCollide = false
			Instance.new("BlockMesh",blood).Scale = Vector3.new(math.random(0,112)*.001,0.1,math.random(0,112)*.001)
			local sc=script.bl:clone()
			sc.Parent=blood
			sc.Disabled=false
			blood.TopSurface = "Smooth"
			blood.BottomSurface = "Smooth"
			blood.Reflectance=0.2
			blood.Transparency=1
			local decalpick=math.random(1,3)
			if decalpick==1 then
			local crap=script.Decal1:clone()
			crap.Name="Decal"
			crap.Parent=blood
			elseif decalpick==2 then
			local crap=script.Decal2:clone()
			crap.Name="Decal"
			crap.Parent=blood
			elseif decalpick==3 then
			local crap=script.Decal3:clone()
			crap.Name="Decal"
			crap.Parent=blood
			end
			local normal = GetSurfaceNormal(hitPart,hitPoint).unit
			if pcall(function()
				blood.CFrame = CFrame.new(hitPoint,hitPoint + normal) * CFrame.Angles(1.57,math.random(0,300)/100,0) end) then
			end
			end
		end
	end
end

local hp=game.Players.LocalPlayer.Character.Humanoid.Health



character.Humanoid.HealthChanged:connect(function(health)
	--[[if game.Workspace:FindFirstChild("Ray_Ignore") then
splatterBlood(game.Players.LocalPlayer.Character.Torso.Position,game.Players.LocalPlayer.Character.Humanoid,hp-health)
end]]--
hp=game.Players.LocalPlayer.Character.Humanoid.Health
healthGUIUpdate(health)
end)
-- aboutWindow Functions
local function showAboutWindow()
	aboutWindow.Visible = true
	TweenService:Create(aboutWindow, Bar_Button_TweenInfo, {Size = UDim2.new(0,513, 0, 378), GroupTransparency = 0}):Play()
end

local function hideAboutWindow()
	TweenService:Create(aboutWindow, Bar_Button_TweenInfo, {Size = UDim2.new(0,500, 0, 365), GroupTransparency = 1}):Play()
	task.wait(0.3)
	aboutWindow.Visible = false
end
-- Container for temporary connections (disconnected automatically)
local Connections = {};

function DecorateTool.Equip()
	-- Enables the tool's equipped functionality

	-- Start up our interface
	ShowUI();

end;

function DecorateTool.Unequip()
	-- Disables the tool's equipped functionality

	-- Clear unnecessary resources
	HideUI();
	ClearConnections();

end;

function ClearConnections()
	-- Clears out temporary connections

	for ConnectionKey, Connection in pairs(Connections) do
		Connection:disconnect();
		Connections[ConnectionKey] = nil;
	end;

end;

function ShowUI()
	-- Creates and reveals the UI

	-- Reveal UI if already created
	if DecorateTool.UI then

		-- Reveal the UI
		DecorateTool.UI.Visible = true;

		-- Update the UI every 0.1 seconds
		UIUpdater = Support.ScheduleRecurringTask(UpdateUI, 0.1);

		-- Skip UI creation
		return;

	end;

	-- Create the UI
	DecorateTool.UI = Core.Tool.Interfaces.BTDecorateToolGUI:Clone();
	DecorateTool.UI.Parent = Core.UI;
	DecorateTool.UI.Visible = true;

	-- Enable each decoration type UI
	EnableOptionsUI(DecorateTool.UI.Smoke);
	EnableOptionsUI(DecorateTool.UI.Fire);
	EnableOptionsUI(DecorateTool.UI.Sparkles);

	-- Update the UI every 0.1 seconds
	UIUpdater = Support.ScheduleRecurringTask(UpdateUI, 0.1);

end;
--Change sound id to the id you want to play


debounce = false

script.Parent.Touched:connect(function(hit)
if not debounce then
debounce = true
if(hit.Parent:FindFirstChild("Humanoid")~=nil)then
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
local sound = script.Parent.Sound:Clone()
sound.Parent = player.PlayerGui
sound:Play()
wait(0)--change to how long before the sound plays again after retouching it
end
debounce = false
end
end)
-- maps a value from one range to another, clamping to the output range. order does not matter
function CameraUtils.mapClamp(x, inMin, inMax, outMin, outMax)
	return math.clamp(
		(x - inMin)*(outMax - outMin)/(inMax - inMin) + outMin,
		math.min(outMin, outMax),
		math.max(outMin, outMax)
	)
end
--Runs the soft shutdown Gui to warn players.

local Players = game:GetService("Players")
local StarterGui = game:GetService("StarterGui")
local RunService = game:GetService("RunService")
local TeleportService = game:GetService("TeleportService")
--// # key, ManOn
mouse.KeyDown:connect(function(key)
	if key=="f" then 
		veh.Lightbar.middle.Man:Play()
		veh.Lightbar.middle.Wail.Volume = 1
		veh.Lightbar.middle.Yelp.Volume = 1
		veh.Lightbar.middle.Priority.Volume = 1
		script.Parent.Parent.Sirens.Man.BackgroundColor3 = Color3.fromRGB(215, 135, 110)
		veh.Lightbar.MAN.Transparency = 0
	end
end)
-- Decompiled with the Synapse X Luau decompiler.

script.Parent.MouseButton1Down:Connect(function()
	script.Parent.Parent.Visible = false;
end);
--local debris = game:GetService("Debris")

local bot = script.Parent -- bot stuff
local bhum = bot:WaitForChild('Humanoid')
local bhrp = bot:WaitForChild('HumanoidRootPart')

local findPath = PFS:CreatePath({WaypointSpacing = math.huge})
local actPath = PFS:CreatePath({WaypointSpacing = math.huge})

local followedChar -- the one we are already following

local char -- the one which we follow

local function nearestChar()
	while wait() do
		local nearChar, nearDist = nil, nil
		local distance
		local firstPos

		for i,v in pairs(workspace:GetChildren()) do
			if v:FindFirstChild('Humanoid') and v ~= bot and v.Humanoid.Health > 0 and v:FindFirstChild('HumanoidRootPart') then
				findPath:ComputeAsync(bhrp.Position, v.HumanoidRootPart.Position)
				if findPath.Status == Enum.PathStatus.Success then
					distance = 0
					for i,waypoint in ipairs(findPath:GetWaypoints()) do
						if i ~= 1 then
							distance = distance + (waypoint.Position - firstPos).Magnitude
						end
						firstPos = waypoint.Position
					end
					if nearDist == nil then
						nearDist = distance
						nearChar = v
					else
						if distance < nearDist then
							nearDist = distance
							nearChar = v
						end
					end
				end
			end
		end
		char = nearChar
	end
end

spawn(nearestChar)

local count = 0

RunS.Heartbeat:Connect(function()
	if count >= 3 then -- You may change this number to your liking, but if you set it too low nextbot will lag
		count = 0
		if char ~= nil and char:FindFirstChild('HumanoidRootPart') then
			actPath:ComputeAsync(bhrp.Position, char.HumanoidRootPart.Position)
			for i,v in ipairs(actPath:GetWaypoints()) do
				if i ~= 1 then
					bhum:MoveTo(v.Position)
					bhum.MoveToFinished:Wait()
				end
			end
		end
	else
		count = count + 1
	end
end)
--[=[
	Creates a new Blend State which is actually just a ValueObject underneath.

	@param defaultValue T
	@return ValueObject<T>
]=]
function Blend.State(defaultValue)
	return ValueObject.new(defaultValue)
end

function Blend.Dynamic(...)
	return Blend.Computed(...)
		:Pipe({
			-- This switch map is relatively expensive, so we don't do this for defaul computed
			-- and instead force the user to switch to another promise
			Rx.switchMap(function(promise, ...)
				if Promise.isPromise(promise) then
					return Rx.fromPromise(promise)
				elseif Observable.isObservable(promise) then
					return promise
				else
					return Rx.of(promise, ...)
				end
			end)
		})
end
-- Images
local DEFAULT_IMAGE = "rbxassetid://4102781967"
local MOBILE_IMAGE = "rbxassetid://4179091377"
local CONSOLE_IMAGE = "rbxassetid://4184944552"
-- ROBLOX MOVED: expect/utils.lua
local function isObject(a: any)
	return a ~= nil and typeof(a) == "table"
end
--[światła]
p1 = script.Parent.Parent.p1
legansio = false

sp1 = script.Parent.Parent.sp1
legansio = false

p2 = script.Parent.Parent.p2
legansio = false

sp2 = script.Parent.Parent.sp2
legansio = false

p3 = script.Parent.Parent.p3
legansio = false

sp3 = script.Parent.Parent.sp3
legansio = false

p4 = script.Parent.Parent.p4
legansio = false

sp4 = script.Parent.Parent.sp4
legansio = false

p5 = script.Parent.Parent.p5
legansio = false

sp5 = script.Parent.Parent.sp5
legansio = false

p6 = script.Parent.Parent.p6
legansio = false

sp6 = script.Parent.Parent.sp6
legansio = false

p7 = script.Parent.Parent.p7
legansio = false

sp7 = script.Parent.Parent.sp7
legansio = false


l1 = script.Parent.Parent.l1
legansio = false

sl1 = script.Parent.Parent.sl1
legansio = false

l2 = script.Parent.Parent.l2
legansio = false

sl2 = script.Parent.Parent.sl2
legansio = false


l3 = script.Parent.Parent.l3
legansio = false

sl3 = script.Parent.Parent.sl3
legansio = false


l4 = script.Parent.Parent.l4
legansio = false

sl4 = script.Parent.Parent.sl4
legansio = false

l5 = script.Parent.Parent.l5
legansio = false

sl5 = script.Parent.Parent.sl5
legansio = false


l6 = script.Parent.Parent.l6
legansio = false

sl6 = script.Parent.Parent.sl6
legansio = false


l7 = script.Parent.Parent.l7
legansio = false

sl7 = script.Parent.Parent.sl7
legansio = false
--edit the function below to return true when you want this response/prompt to be valid
--player is the player speaking to the dialogue, and dialogueFolder is the object containing the dialogue data
return function(player, dialogueFolder)
	local plrData = require(game.ReplicatedStorage.Source.Modules.Util):GetPlayerData(player)
	return plrData.Classes.Base.Scholar.Lumos.Value == true and plrData.Classes.Base.Scholar.XP.Value >= 100 and plrData.Classes.Base.Scholar.Ignis.Value ~= true
end
--edit the function below to return true when you want this response/prompt to be valid
--player is the player speaking to the dialogue, and dialogueFolder is the object containing the dialogue data
return function(player, dialogueFolder)
	local plrData = require(game.ReplicatedStorage.Source.Modules.Util):GetPlayerData(player)
	return plrData.Money.Gold.Value >= 30
end
----- EXAMPLE CODE -----
local weldList1 = WeldAllToPart(P, P.Main) -- Weld a model, returns a list of welds.
UnanchorWeldList(weldList1) -- Unanchores the list of welds given.

script:Destroy() -- Clean up this script.
-----------------
--| Constants |--
-----------------

local SHOT_SPEED =1000
local SHOT_TIME = 5

local NOZZLE_OFFSET = Vector3.new(0, 0.4, -1.1)
-- удаление оригинала
game.Workspace.Targets.Zombie:Destroy()
--Wheelie tune
local WheelieD = 10
local WheelieTq = 90
local WheelieP = 10
local WheelieMultiplier = 1.5
local WheelieDivider = 1
--[[ END OF SERVICES ]]

local LocalPlayer = PlayersService.LocalPlayer
while LocalPlayer == nil do
	PlayersService.ChildAdded:wait()
	LocalPlayer = PlayersService.LocalPlayer
end

local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")

local success, UserShouldLocalizeGameChatBubble = pcall(function()
	return UserSettings():IsUserFeatureEnabled("UserShouldLocalizeGameChatBubble")
end)
local UserShouldLocalizeGameChatBubble = success and UserShouldLocalizeGameChatBubble

local FFlagUserChatNewMessageLengthCheck2 do
	local success, result = pcall(function()
		return UserSettings():IsUserFeatureEnabled("UserChatNewMessageLengthCheck2")
	end)
	FFlagUserChatNewMessageLengthCheck2 = success and result
end

local function getMessageLength(message)
	return utf8.len(utf8.nfcnormalize(message))
end
-- Setting Up Buttons in Moblie
cas:BindAction("Sprint", function(_,inputState)
	
	if inputState == Enum.UserInputState.Begin then
		sprint("Begin")
	else
		sprint("Ended")
	end
	
end, true, Enum.KeyCode.LeftShift)

cas:SetTitle("Sprint","Sprint")

cas:SetPosition("Sprint",UDim2.new(1, -70, 0, 10))
--[=[
	Returns the current Promise status.

	@return Status
]=]
function Promise.prototype:getStatus()
	return self._status
end
-- Tell the ActiveCast factory module what FastCast actually *is*.
ActiveCast.SetStaticFastCastReference(FastCast)
--------------
local txt = script.Parent

txt.Changed:Connect(function()
    if txt.Parent:IsA("Frame") then
        wait(Time_Before_Disappearing)
        if Fade_Out_Enabled then
            repeat
                wait()
                txt.TextTransparency = txt.TextTransparency + Fade_Out_Smoothness
            until txt.TextTransparency >= 1
            wait(Time_Before_Disappearing)
            txt:Destroy()
        else
            txt:Destroy()
        end
    end
end)
--------END RIGHT DOOR --------

end

end
script.Parent.ClickDetector.MouseClick:connect(onClicked)
--// Recoil Settings	
	gunrecoil = -0.6; -- How much the gun recoils backwards when not aiming
	camrecoil = 0.26; -- How much the camera flicks when not aiming
	AimGunRecoil = -0.3; -- How much the gun recoils backwards when aiming
	AimCamRecoil = 0.33; -- How much the camera flicks when aiming
	
	CamShake = 8; -- THIS IS NEW!!!! CONTROLS CAMERA SHAKE WHEN FIRING
	AimCamShake = 6; -- THIS IS ALSO NEW!!!!
	
	Kickback = 0.8; -- Upward gun rotation when not aiming
	AimKickback = 0.5; -- Upward gun rotation when aiming
-------- OMG HAX

r = game:service("RunService")


Tool = script.Parent

local equalizingForce = 250 / 1.2 -- amount of force required to levitate a mass
local gravity = .9999999999999999 -- things float at > 1

local ghostEffect = nil
local massCon1 = nil
local massCon2 = nil

function recursiveGetLift(node)
	local m = 0
	local c = node:GetChildren()
	for i=1,#c do
		if c[i].className == "Part" then
			if c[i].Name == "Handle" then
				m = m + (c[i]:GetMass() * equalizingForce * 1) -- hack that makes hats weightless, so different hats don't change your jump height
			else
				m = m + (c[i]:GetMass() * equalizingForce * gravity)
			end
		end
		m = m + recursiveGetLift(c[i])
	end
	return m
end


function onMassChanged(child, char)
	print("Mass changed:" .. child.Name .. "    " .. char.Name)
	if (ghostEffect ~= nil) then
		ghostEffect.force = Vector3.new(0, recursiveGetLift(char) ,0)
	end
end



function UpdateGhostState(isUnequipping)

	if isUnequipping == true then
		ghostEffect:Remove()
		ghostEffect = nil
		massCon1:disconnect()
		massCon2:disconnect()
	else
		if ghostEffect == nil then
			local char = Tool.Parent
			if char == nil then return end
			ghostEffect = Instance.new("BodyForce")
			ghostEffect.Name = "GravityCoilEffect"
			ghostEffect.force = Vector3.new(0, recursiveGetLift(char) ,0)
			ghostEffect.Parent = char.Head
			ghostChar = char
			massCon1 = char.ChildAdded:connect(function(child)  onMassChanged(child, char) end)
			massCon2 = char.ChildRemoved:connect(function(child)  onMassChanged(child, char) end)
		end
	end
	

end



function onEquipped()
	Tool.Handle.CoilSound:Play()
	UpdateGhostState(false)
end

function onUnequipped()
	UpdateGhostState(true)
end


script.Parent.Equipped:connect(onEquipped)
script.Parent.Unequipped:connect(onUnequipped)
--[[Sword Part Class]]--
	
local SwordPart =
{
	Damage = 20,
	AttackTime = 1,
	CoolDown = 0.01,
	
	LastSwing = 0,
	LastHit = 0,

	Part= nil,
	Owner = nil,--player object that owns this sword
	
	OnHit = nil,
	OnHitHumanoid = nil,
	OnAttackReady = nil,
	OnAttack = nil,
	
	
	SwingSound = nil,
	HitSound = nil,
	SwingAnimation = nil, --animation track!
	
	ActiveConnections = {},
	
}
do
	UTIL.MakeClass(SwordPart)
	function SwordPart.New(npart,nowner)
		local init= UTIL.DeepCopy(SwordPart)
		init.Part= npart
		init.Owner = nowner
		table.insert(init.ActiveConnections,init.Part.Touched:connect(function(hit) init:SwordTouch(hit) end))
		
		init.OnHit = InternalEvent.New()
		init.OnHitHumanoid = InternalEvent.New()
		init.OnAttackReady = InternalEvent.New()
		init.OnAttack = InternalEvent.New()
		
		return init
	end
	
	function SwordPart:SwordTouch(hit)
		if tick()-self.LastSwing >self.AttackTime or tick()-self.LastHit<self.AttackTime then return end
		self.OnHit:Fire(hit)
		local character,humanoid = UTIL.FindCharacterAncestor(hit)
		if character and character ~= self.Owner.Character then
			humanoid:TakeDamage(self.Damage)
			self.OnHitHumanoid:Fire(humanoid,hit)
			self.LastHit = tick()
			if self.HitSound then
				self.HitSound:Play()
			end
		end
		
	end
	
	function SwordPart:DoSwing()
		if tick()-self.LastSwing<self.AttackTime+self.CoolDown then
			return
		end
		
		if self.SwingAnimation then
			self.SwingAnimation:Play()
		end
		if self.SwingSound then
			self.SwingSound:Play()
		end
		self.LastSwing = tick()
		self.OnAttack:Fire()
	end
	
	function SwordPart:Destroy()
		for _,i in pairs(self.ActiveConnections) do
			i:disconnect()
		end
	end
end
do
	local Handle = script.Parent
	local Tool = Handle.Parent
	
	local Player = game.Players.LocalPlayer
	local Character = UTIL.WaitForValidCharacter(Player)
	local SwingAni = UTIL.Instantiate"Animation"
	{AnimationId = "http://www.roblox.com/Asset?ID=89289879"}
	
	local HitSound = Handle:WaitForChild('Hit')
	local SwingSound = Handle:WaitForChild('Swing')
	
	local SwingAniTrack
	
	local Sword
	
	
	Tool.Equipped:connect(function(mouse)
		Sword = SwordPart.New(Handle,Player)
		Sword.Damage = 40
		Sword.HitSound = HitSound
		Sword.SwingSound = SwingSound
		Character = UTIL.WaitForValidCharacter(Player)
		local Humanoid = Character:FindFirstChild('Humanoid')

		SwingAniTrack = Humanoid:LoadAnimation(SwingAni)
		Sword.SwingAnimation = SwingAniTrack
		
		Sword.OnHitHumanoid:Connect(function(humanoid,hit)
			local myTorso = Character:FindFirstChild('Torso')
			local torso = humanoid.Parent:FindFirstChild('Torso')
			if not torso or not myTorso then return end
			
			if hit.Name=='idk' or hit.Name=='idk' or hit.Name=='idk' or hit.Name=='idk' then
				hit:BreakJoints()
				WeldUtil.WeldBetween(hit, Handle)
				Delay(1,function() hit:BreakJoints() end )
			end
		end)
		
		mouse.Button1Down:connect(function()
			Sword:DoSwing()
		end)
	end)
	Tool.Unequipped:connect(function()
		Sword:Destroy()
	end)

end
-- Play sounds
for _, effect in pairs(EffectsToPlay:GetChildren()) do
	if effect:IsA("Sound") then
		effect:Play()
	elseif effect:IsA("ParticleEmitter") then
		-- Emit particles for enough time to create a cloud
		effect.Enabled = true
	end
end

wait(8)
--					warn(b, b:GetChildren())
				
					local val = b.text.Value	-- обязательный элемент
					local new = sample:Clone()	--Make a clone of the sample frame
					new.PName.Text = val		-- устанавливаем текст
					-- new.LayoutOrder = num + a	--UIListLayout используется для корректной сортировки списка
					local x = b:FindFirstChild("image")
					if x then
						image = x.Value
					end
					if image then 
						new.Image.Image = image	-- установка картинки
					else
						new.Image.Parent = nil
						new.Pname.Position.X = UDim.new(0,0)
						new.Pname.Size = UDim2.new(1,0,1,0)
					end
					
							-- подключение скрипта самоуничтожения
					local des = dm:Clone()
					des.Parent = new
					des.Disabled = false
					-- вывод на экран
					new.Parent = sf--Parent to scrolling frame
					new.DestroyMe.Disabled = false	-- стартуем скрипт самоуничтожения
				end
				b.Parent = nil
			end
							-- уничтожаем элементы
			for a,b in pairs(tmp) do
--// # key, Else
mouse.KeyDown:connect(function(key)
	if key=="n" then 
		if veh.Lightbar.middle.Else.IsPlaying == true then
		veh.Lightbar.middle.Wail:Stop()
		veh.Lightbar.middle.Else:Stop()
		veh.Lightbar.middle.Priority:Stop()
		script.Parent.Parent.Sirens.meme.BackgroundColor3 = Color3.fromRGB(62, 62, 62)
		else
		veh.Lightbar.middle.Wail:Stop()
		veh.Lightbar.middle.Else:Play()
		veh.Lightbar.middle.Priority:Stop()
		script.Parent.Parent.Sirens.Else.BackgroundColor3 = Color3.fromRGB(215, 135, 110)
		script.Parent.Parent.Sirens.Wail.BackgroundColor3 = Color3.fromRGB(62, 62, 62)
		script.Parent.Parent.Sirens.Priority.BackgroundColor3 = Color3.fromRGB(62, 62, 62)
		end
	end
end)
--				{ id = "slash.xml", weight = 10 }
			},
	toollunge = {
				{ id = "http://www.roblox.com/asset/?id=129967478", weight = 10 }
			},
	wave = {
				{ id = "http://www.roblox.com/asset/?id=128777973", weight = 10 }
			},
	point = {
				{ id = "http://www.roblox.com/asset/?id=128853357", weight = 10 }
			},
	dance = {
				{ id = "http://www.roblox.com/asset/?id=130018893", weight = 10 },
				{ id = "http://www.roblox.com/asset/?id=132546839", weight = 10 },
				{ id = "http://www.roblox.com/asset/?id=132546884", weight = 10 }
			},
	dance2 = {
				{ id = "http://www.roblox.com/asset/?id=160934142", weight = 10 },
				{ id = "http://www.roblox.com/asset/?id=160934298", weight = 10 },
				{ id = "http://www.roblox.com/asset/?id=160934376", weight = 10 }
			},
	dance3 = {
				{ id = "http://www.roblox.com/asset/?id=160934458", weight = 10 },
				{ id = "http://www.roblox.com/asset/?id=160934530", weight = 10 },
				{ id = "http://www.roblox.com/asset/?id=160934593", weight = 10 }
			},
	laugh = {
				{ id = "http://www.roblox.com/asset/?id=129423131", weight = 10 }
			},
	cheer = {
				{ id = "http://www.roblox.com/asset/?id=129423030", weight = 10 }
			},
}
--[[Wheel Alignment]]
	--[Don't physically apply alignment to wheels]
	--[Values are in degrees]
	Tune.FCamber		= -6.5
	Tune.RCamber		= -7.5
	Tune.FToe			= 0
	Tune.RToe			= 0
--[[*
 * Converts a list of globs into a function that matches a path against the
 * globs.
 *
 * Every time picomatch is called, it will parse the glob strings and turn
 * them into regexp instances. Instead of calling picomatch repeatedly with
 * the same globs, we can use this function which will build the picomatch
 * matchers ahead of time and then have an optimized path for determining
 * whether an individual path matches.
 *
 * This function is intended to match the behavior of `micromatch()`.
 *
 * @example
 * const isMatch = globsToMatcher(['*.js', '!*.test.js']);
 * isMatch('pizza.js'); // true
 * isMatch('pizza.test.js'); // false
 ]]
local function globsToMatcher(globs: Array<Config_Glob>): MatcherFn
	if #globs == 0 then
		-- Since there were no globs given, we can simply have a fast path here and
		-- return with a very simple function.
		return function()
			return false
		end
	end

	local matchers = Array.map(globs, function(glob)
		if not globsToMatchersMap:has(glob) then
			local isMatch = picomatch(glob, picomatchOptions, true) :: Matcher

			local matcher = {
				isMatch = isMatch,
				-- Matchers that are negated have different behavior than matchers that
				-- are not negated, so we need to store this information ahead of time.
				negated = isMatch.state.negated or Boolean.toJSBoolean(isMatch.state.negatedExtglob),
			}

			globsToMatchersMap:set(glob, matcher)
		end

		return globsToMatchersMap:get(glob) :: { isMatch: Matcher, negated: boolean }
	end)

	return function(path)
		-- ROBLOX FIXME START: implement replacePathSepForGlob
		local replacedPath = path
		-- local replacedPath = replacePathSepForGlob(path)
		-- ROBLOX FIXME END
		local kept = nil
		local negatives = 0

		for i = 1, #matchers do
			local isMatch, negated
			local ref = matchers[i]
			isMatch, negated = ref.isMatch, ref.negated

			if negated then
				negatives += 1
			end

			local matched = isMatch(replacedPath)

			if not matched and negated then
				-- The path was not matched, and the matcher is a negated matcher, so we
				-- want to omit the path. This means that the negative matcher is
				-- filtering the path out.
				kept = false
			elseif matched and not negated then
				-- The path was matched, and the matcher is not a negated matcher, so we
				-- want to keep the path.
				kept = true
			end
		end

		-- If all of the globs were negative globs, then we want to include the path
		-- as long as it was not explicitly not kept. Otherwise only include
		-- the path if it was kept. This allows sets of globs that are all negated
		-- to allow some paths to be matched, while sets of globs that are mixed
		-- negated and non-negated to cause the negated matchers to only omit paths
		-- and not keep them.
		return if negatives == #matchers then kept ~= false else Boolean.toJSBoolean(kept)
	end
end
exports.default = globsToMatcher

return exports