local a=require(script.Parent:WaitForChild("\116"))local C={CommaSeparated=function(a)if#a==1 then return tostring(a[1])elseif#a==2 then return a[1]..(" \097\110\100 "..a[2])else local C=table.remove(a)local P=table.concat(a,"\044 ")..("\044 \097\110\100 "..C)table.insert(a,C)return P end end,Map=function(a,C)for P,B in pairs(C)do C[P]=a(B)end return C end}function C.BreadthFirst(a,P,B)if P<=0 or a==nil then return end local Z=a:GetChildren()for a,Z in pairs(Z)do B(Z)C.BreadthFirst(Z,P-1,B)end end C.ContainsValue=function(a,C)for a,P in pairs(a)do if P==C then return a end end return false end C.Length=function(a)local C=0 for a,P in pairs(a)do C=C+1 end return C end C.len=function(a)local C=0 for a,P in pairs(a)do C=C+1 end return C end C.keys=function(a)local C={}for a,P in pairs(a)do table.insert(C,a)end return C end C.values=function(a)local C={}for a,P in pairs(a)do table.insert(C,P)end return C end C.xsort=function(a,P)local B=C.keys(a)table.sort(B,P)return function()if#B==0 then return nil end local C=table.remove(B,1)return C,a[C]end end C.vsort=function(a,P)P=P or function(a,C)return a>C end return C.xsort(a,function(C,B)return P(a[C],a[B])end)end C.choice=function(a,P)P=P or 1 local B={}local Z={}for a,C in pairs(a)do Z[a]=C end local L=C.keys(Z)for C=1,math.min(#a,math.max(P,1)),1 do table.insert(B,a[table.remove(L,math.random(#L))])end return unpack(B)end C.one=function(a)return a[math.random(#a)]end C.shallow=function(a)local C={}for a,P in pairs(a)do C[a]=P end return C end C.deep=function(a)local P={}for a,B in pairs(a)do if typeof(B)=="\116\097\098\108\101"then P[a]=C.deep(B)else P[a]=B end end return P end C.cloneKeys=function(a)local C={}for a,P in pairs(a)do C[a]=true end return C end C.dump=function(a,P)P=P or""for a,B in pairs(a)do print(("\037\115\037\115 \061 \037\115"):format(P,tostring(a),tostring(B)))if typeof(B)=="\116\097\098\108\101"then C.dump(B,("\037\115\046\037\115"):format(P,a))end end end C.merge=function(a,...)local C={}for a,P in pairs({a;...})do for a,P in pairs(P)do table.insert(C,P)end end return C end C._getSortedKeysCheck=a.table function C.GetSortedKeys(a)assert(C._getSortedKeysCheck(a))local P={}for a in pairs(a)do table.insert(P,a)end table.sort(P)return P end return setmetatable(C,{__index=table})
local t = require(script.Parent:WaitForChild("t"))

local module = {
    CommaSeparated = function (list)
        if #list == 1 then
            return tostring(list[1])
        elseif #list == 2 then
            return list[1] .. " and " .. list[2]
        else
            local lastItem = table.remove(list)
            local text = table.concat(list, ", ") .. ", and " .. lastItem
            table.insert(list, lastItem)
            return text
        end
    end,
    Map = function(func, list)
        for index,value in pairs(list) do
            list[index] = func(value)
        end
        
        return list
    end
}
function module.BreadthFirst(entity, levelsRemaining, funcToRunOnEachEntity)
    -- @param [Instance] entity entity to start search
	-- @param [Number] levelsRemaining Levels of entities deep to continue searching
	-- @param [function] The function to run on each entity
	if (levelsRemaining <= 0 or entity == nil) then
		return
	end
	
	local entityChilds = entity:GetChildren()
	
	for _, entitiesChild in pairs(entityChilds) do
		funcToRunOnEachEntity(entitiesChild)
		module.BreadthFirst(entitiesChild, levelsRemaining - 1, funcToRunOnEachEntity)
    end
end

module.ContainsValue = function(tbl, val)
	for i,v in pairs(tbl) do
		if v == val then
			return i
		end
	end
	
	return false
end

module.Length = function(tbl)
	local len = 0
	
	for _,_ in pairs(tbl) do
		len = len + 1
	end
	
	return len
end

module.len = function(tbl)
	local len = 0
	
	for _,_ in pairs(tbl) do
		len = len + 1
	end
	
	return len
end

module.keys = function(tbl)
	local ret = {}
	
	for key,_ in pairs(tbl) do
		table.insert(ret, key)
	end
	
	return ret
end

module.values = function(tbl)
	local ret = {}
	
	for _,val in pairs(tbl) do
		table.insert(ret, val)
	end
	
	return ret
end

--sort by keys
module.xsort = function(tbl, sort)
	local keys = module.keys(tbl)
	
	table.sort(keys, sort)
	
	return function()
		if #keys == 0 then
			return nil
		end
		
		local nextValue = table.remove(keys, 1)
		
		return nextValue, tbl[nextValue]
	end
end

--sort by values
module.vsort = function(tbl, sort)
	sort = sort or function(x, y)
		return x > y
	end
	
	return module.xsort(tbl, function(x, y)
		return sort(tbl[x], tbl[y])
	end)
end

module.choice = function(tbl, resultCount)
	resultCount = resultCount or 1
	
	local results = {}
	
	--clone the table
	local clone = {}
	
	for i,v in pairs(tbl) do
		clone[i] = v
	end
	
	local keys = module.keys(clone)
	
	for i=1,math.min(#tbl, math.max(resultCount, 1)) do
		table.insert(results, tbl[table.remove(keys, math.random(#keys))])
	end
	
	return unpack(results)
end

module.one = function(tbl)
	return tbl[math.random(#tbl)]
end

module.shallow = function(tbl)
	local clone = {}
	
	for key,val in pairs(tbl) do
		clone[key] = val
	end
	
	return clone
end

module.deep = function(tbl)
	local clone = {}
	
	for key,val in pairs(tbl) do
		if typeof(val) == "table" then
			clone[key] = module.deep(val)
		else
			clone[key] = val
		end
	end
	
	return clone
end

module.cloneKeys = function(tbl)
	local ret = {}
	
	for key,_ in pairs(tbl) do
		ret[key] = true
	end
	
	return ret
end

module.dump = function(tbl, prefix)
	prefix = prefix or ""
	
	for key,val in pairs(tbl) do
		print(("%s%s = %s"):format(prefix, tostring(key), tostring(val)))
		
		if typeof(val) == "table" then
			module.dump(val, ("%s.%s"):format(prefix, key))
		end
	end
end

module.merge = function(tbl, ...)
	local ret = {}
	
	for _,tbl in pairs({tbl, ...}) do
		for _,value in pairs(tbl) do
			table.insert(ret, value)
		end
	end
	
	return ret
end



--[[
	Returns an array of keys from the given object, sorted alphabetically.

	This is used so we get a consistent, alphabetical output for tables.
	Typically dicctionary-like tables aren't sorted, so this fixes that.

	Usage:

		local object = {
			delta = true,
			alpha = true,
			bravo = true,
		}

		local keys = getSortedKeys(object)

		for _, key in pairs(keys) do
			print(key)
		end

		-- "alpha"
		-- "bravo"
		-- "delta"
]]

module._getSortedKeysCheck = t.table
function module.GetSortedKeys(object)
	assert(module._getSortedKeysCheck(object))

    local keys = {}

    for k in pairs(object) do
        table.insert(keys, k)
    end

    table.sort(keys)

    return keys
end


return setmetatable(module, {
	__index = table
})