Feedback on my map voting module

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")

local VotingData = ServerStorage:FindFirstChild("VotingData") and ServerStorage:FindFirstChild("VotingData"):IsA("Folder")

if not VotingData then
	return warn("VotingData not found in ServerStorage")
end

---- Private Functions ----

local function CreatePlayerVotingData(player)
	if player:IsDescendantOf(Players) then 
		local playerData = Instance.new("Folder")
		playerData.Name = player.Name
		playerData.Parent = VotingData
			
		local voted = Instance.new("StringValue")
		voted.Name = "Voted"
		voted.Parent = playerData
	end
end

Players.PlayerAdded:Connect(CreatePlayerVotingData)

local module = {}

function module.StartVoting(player, votePadsFolder, maxVotesPerEachPad, votesToWin)
	assert(typeof(maxVotes) == "number", "StartVoting: 'maxVotesPerEachPad' expected number, got "..tostring(typeof(maxVotesPerEachPad)))
	assert(votesFolder:IsA("Folder"), "StartVoting: 'votesFolder' expected folder, got "..votePadsFolder.Name)

	if player:IsDescendantOf(Players) then
		for _, v in ipairs(votePadsFolder:GetChildren()) do 
			if v:IsA("BasePart") or v:IsA("Part") then
				local votes = v:FindFirstChild("Votes")

				connection = v.Touched:Connect(function(hit)
				local player = Players:GetPlayerFromCharacter(hit.Parent)
				
					if player then
						if ServerStorage.VotingData[player.Name].Voted.Value ~= v.Name then
							if votes.Value < maxVotesPerEachPad then

							if ServerStorage.VotingData[player.Name].Voted.Value ~= "" then
								local previousVotePad = votesFolder[ServerStorage.VotingData[player.Name].Voted.Value]
								previousVotePad.Votes.Value -= 1
							end
								
								votes.Value += 1
								ServerStorage.VotingData[player.Name].Voted.Value = v.Name
							end
						else
							votes.Value -= 1
							ServerStorage.VotingData[player.Name].Voted.Value = ""
						end
					end
				end)
			end
		end
    end
end

function module.CleanVoting(player, votesFolder)
	assert(votesFolder:IsA("Folder"), "CleanVoting: 'votesFolder' expected folder, got "..votesFolder)
	assert(typeof(player) == "Instance", "CleanVoting: 'player' expected Instance, got "..tostring(typeof(player)))
	
    if player:IsDescendantOf(Players) then
		for _, v in ipairs(votesFolder:GetChildren()) do 
			local votes = v:FindFirstChild("Votes")

			if votes.Value >= 1 then
				votes.Value = 0
			end

			if ServerStorage.VotingData[player.Name].Voted.Value ~= "" then
				ServerStorage.VotingData[player.Name].Voted.Value = ""
			end
		end
	end
end

function module.EndVoting(player, votesFolder)
	assert(votesFolder:IsA("Folder"), "EndVoting: 'votesFolder' expected folder, got "..votesFolder)
	assert(typeof(player) == "Instance", "EndVoting: 'player' expected Instance, got "..tostring(typeof(player)))

	if player:IsDescendantOf(Players) then 
		for _, v in ipairs(votesFolder:GetChildren()) do
			local votes = v:FindFirstChild("Votes")

			if votes.Value > 0 then
				votes.Value = 0
			end

		if ServerStorage.VotingData[player.Name].Voted.Value ~= "" then
			ServerStorage.VotingData[player.Name].Voted.Value = ""
		end
		connection:Disconnect()
	end
end

function module.FindHighestPadWithVotes(votesFolder)	
	assert(votesFolder:IsA("Folder"), "FindHighestPadWithVotes: 'votesFolder' expected folder, got "..votesFolder)

    local votes = {}	

    for _, v in ipairs(votesFolder:GetChildren()) do 
		local votes = v:FindFirstChildWhich("Votes")

		table.insert(votes, v.Votes.	Value) -->> {3, 5, 4} The votes value in each pad

		if votes.Value == math.max(unpack(votes)) then
			return v, votes.Value -->> {votePad, 3}
		end
	end 
end

return module
1 Like

Any reason for the “voted” value you are using a StringValue and not just a boolean? It seems overly complex to use strings for something that (if I’m not mistaken, which I could be) you could just use a boolean for.

Using a string value so I know on what pad the player has voted for and remove the vote of that pad for other use cases.

1 Like