Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Vote v1.0 by Espen
- An example code for a voting system, inspired by ewart4fun
- Thread: http://www.computercraft.info/forums2/index.php?/topic/5807-lua-voting-program/
- --]]
- -- [[ BEGINNING of FUNCTION DEFINITIONS ]] ---------------------------
- -- Writes text centered, x- and y-axis position can be offset, and the line to be written can be cleared beforehand.
- local function writeCentered( sText, nOffsetX, nOffsetY, color, bClearLine )
- local maxX, maxY = term.getSize()
- if nOffsetX == null then nOffsetX = 0 end
- local centeredX = (maxX / 2) - (string.len( sText ) / 2) + nOffsetX
- if nOffsetY == null then nOffsetY = 0 end
- local centeredY = (maxY / 2) + nOffsetY
- term.setCursorPos( centeredX, centeredY )
- if bClearLine then term.clearLine() end
- if color and term.isColor() then term.setTextColor( color ) end
- write( sText )
- if color and term.isColor() then term.setTextColor( colors.white ) end
- end
- --[[
- Returns:
- 0 - If login is ok.
- 1 - If login failed.
- 2 - If user already voted.
- ]]
- local function checkLogin( sUser, sPwd )
- --[[
- ^%a = first char has to be a letter
- %w* = then there can follow an arbitrary number of alphanumeric characters
- : = then a colon follows (which is used in the passwd file to delimit the usernames from their passwords)
- [01] = then either a 0 or a 1 follows
- : = then another colon follows (which is used in the passwd file to delimit the usernames from their passwords)
- .*$ = finally the pattern ends with an arbitrary number of any characters, i.e. empty passwords are allowed as well (use .+$ to ignore users with empty passwords).
- ( ) = Everything we encase in brackets will be extracted and returned as a separate value.
- ]]
- local credentials_pattern = "^(%a%w*):([01]):(.*)$" -- Example: "user123:0:secret"
- local bLoginOk = -1
- local hFile = fs.open( ".passwd", "r" )
- local line = hFile.readLine()
- while line do
- local user, hasVoted, pwd = string.match( line, credentials_pattern )
- if ( user and pwd ) and ( sUser == user ) then
- if ( sPwd == pwd ) then
- if ( hasVoted == "0" ) then
- -- User found and password correct. Has not yet voted.
- bLoginOk = 0
- break
- else
- -- User found and password correct. Has already voted.
- bLoginOk = 1
- break
- end
- else
- -- Password incorrect.
- --bLoginOk = -1 -- Unnecessary in the current code, as bLoginOk will not have changed from -1 when the program reaches this point.
- break
- end
- end
- -- Read the next line.
- line = hFile.readLine()
- end
- hFile:close()
- return bLoginOk
- end
- local function getLogin()
- local usrCurPosX, usrCurPosY, pwdCurPosX, pwdCurPosY
- local username = "", password
- while username == "" do
- writeCentered( "Username: ", -5, 0, nil, true )
- usrCurPosX, usrCurPosY = term.getCursorPos()
- writeCentered( "Password: ", -5, 1, nil, true )
- pwdCurPosX, pwdCurPosY = term.getCursorPos()
- term.setCursorPos( usrCurPosX, usrCurPosY )
- username = read()
- if username == "" then term.clear() end
- end
- term.setCursorPos( pwdCurPosX, pwdCurPosY )
- password = read("*")
- return username, password
- end
- -- Returns a table with candidates.
- local function getCandidates()
- --[[
- [^:]+ = Each candidate name has to be comprised of at least one character, except colon.
- ]]
- local candidate_pattern = "[^:]+"
- local tCandidates = {}
- local candidate = nil
- local hFile = fs.open( ".candidates", "r" )
- local line = hFile.readLine()
- while line do
- candidate = string.match( line, candidate_pattern )
- if candidate then
- table.insert( tCandidates, candidate )
- end
- -- Read the next line.
- line = hFile.readLine()
- end
- hFile:close()
- return tCandidates
- end
- local function printVotingScreen( candidateList )
- term.clear()
- term.setCursorPos(1, 2)
- print( "Place your vote (type the corresponding numbers):\n" )
- for index, candidate in ipairs( candidateList ) do
- print( "\t("..index..") - "..candidate )
- end
- print( "\n\t(X) - Logout (vote later)." )
- end
- local function getVote( candidateList )
- while true do
- printVotingScreen( candidateList )
- local _, sChoice = os.pullEvent( "char" )
- local nChoice = tonumber( sChoice )
- -- Ask for confirmation of choice.
- if candidateList[ nChoice ] then
- write( "\nYou chose: ")
- if term.isColor() then
- term.setTextColor( colors.yellow )
- print (candidateList[ nChoice ] )
- term.setTextColor( colors.white )
- else
- print (candidateList[ nChoice ] )
- end
- print( "(A)ccept or (C)ancel this choice." )
- while true do
- local _, sCommit = os.pullEvent( "char" )
- if sCommit and string.lower(sCommit) == "a" then return nChoice end
- if sCommit and string.lower(sCommit) == "c" then break end
- end
- end
- -- Logout
- if sChoice and string.lower(sChoice) == "x" then break end
- end
- end
- local function setHasVoted( voter )
- local users = {}
- local username, hasVoted, password
- local credentials_pattern = "^(%a%w*):([01]):(.*)$"
- -- Read old values into table 'users'.
- local hFile = fs.open( ".passwd", "r" )
- local line = hFile.readLine()
- while line do
- username, hasVoted, password = string.match( line, credentials_pattern )
- if username and hasVoted and password then
- users[username] = { hasVoted, password }
- end
- line = hFile.readLine()
- end
- hFile.close()
- -- Write changes to file.
- local hFile = fs.open( ".passwd", "w" )
- for user, _ in pairs(users) do
- if user == voter then
- hFile.writeLine(user..":1:"..users[user][2])
- else
- hFile.writeLine(user..":"..users[user][1]..":"..users[user][2]) -- users[user][1] is hasVoted and users[user][2] is password.
- end
- end
- hFile.close()
- end
- local function applyVote( tCandidateList, sVoter, nCandidateNum )
- local vote = nil
- local votes = {}
- local votedCandidate
- local votes_pattern = "^([^:]+):(%d+)$" -- Example: candidate3:27
- local hFile = fs.open( ".votes", "r" )
- local line = hFile.readLine()
- while line do
- candidate, vote = string.match( line, votes_pattern )
- if candidate and vote then votes[candidate] = vote end
- line = hFile.readLine()
- end
- votedCandidate = tCandidateList[ nCandidateNum ]
- if not votedCandidate then print(tCandidateList[ 1 ]) error( "The voted candidate isn't in the list of eligible candidates. This shouldn't happen, please fix me." ) end
- -- Initialize votes for candidate in case there are not votes for him yet.
- if not votes[votedCandidate] then
- votes[votedCandidate] = 0
- end
- -- Now finally increment his votes by 1.
- votes[votedCandidate] = votes[votedCandidate] + 1
- -- Write the changes back to file.
- local hFile = fs.open( ".votes", "w" )
- for candidate, vote in pairs(votes) do
- hFile.writeLine( candidate..":"..vote )
- end
- hFile.close()
- -- Set the hasVoted flag for the voter.
- setHasVoted( sVoter )
- end
- local function main()
- term.clear()
- local sUser, sPassword
- local candidateList
- local vote
- local loginState
- local validLogin = false
- -- Check for valid user.
- while not validLogin do
- sUser, sPassword = getLogin()
- -- Special login which quits the program to console. Remove if unwanted.
- if sUser == "exit to" and sPassword == "console" then return false end
- loginState = checkLogin( sUser, sPassword )
- if loginState == 0 then
- writeCentered( "[ Access Granted ]\n", 0, 3, colors.lime, true )
- validLogin = true
- elseif loginState == -1 then
- writeCentered( "[ Access Denied ]\n", 0, 3, colors.red, true )
- elseif loginState == 1 then
- writeCentered( "[ Already Voted ]\n", 0, 3, colors.purple, true )
- end
- sleep(1) -- artificial cooldown before next try
- end
- -- Get the list of candidates and let the current user make a vote.
- candidateList = getCandidates()
- if #candidateList < 1 then
- term.clear()
- writeCentered( "No candidates to vote for." )
- writeCentered( "Please try again later.", 0, 1 )
- writeCentered( "Press ENTER to dismiss...", 0, 4 )
- local _, enter
- while enter ~= 28 do
- _, enter = os.pullEvent( "key" )
- end
- return
- end
- -- Get a vote and apply it.
- vote = getVote( candidateList )
- if type(vote) == "number" then
- applyVote( candidateList, sUser, vote )
- term.clear()
- writeCentered( "Thank you for voting.", 0, 0, colors.yellow )
- writeCentered( "Have a nice day!", 0, 1, colors.yellow )
- sleep(3)
- end
- return true
- end
- -- [[ END of FUNCTION DEFINITIONS ]] ---------------------------
- -- Prevent termination key-combo
- nativePullEvent = os.pullEvent
- os.pullEvent = os.pullEventRaw
- -- Program loop
- local running = true
- while running do
- running = main()
- end
- -- Restore native os.pullEvent
- os.pullEvent = nativePullEvent
Advertisement
Add Comment
Please, Sign In to add comment