2

Traditionally, each person gets only one vote. I'd like to do the same thing with a voting poll.

I have a bunch of accounts on my Mac OS X at work. We are voting to elect someone as our new department head (no I won't say who) to see if he qualifies for the job. I decided to write a little script that does the job for us. However, I can't seem to do one thing: make sure a user can only vote one time. My script is below (it obviously won't compile):

if the current user has never voted then --pseudo-code
    set the rating_results to (choose from list {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} with prompt "Please rate (anonymous) based on your observations. BE HONEST!")
    email_results(rating_results)
else
    display dialog "You already rated (anonymous)!"
end if

I know you will ask "What have I tried so far?" so I will tell you. I tried get the current user, to no avail. I've tried do shell script "echo $USER" as well, which worked, but I still have know idea how to verify whether or not the user voted.

I guess the question title should be "How do I verify whether or not a user voted?".

Thanks so much,

Bill

fireshadow52
  • 6,298
  • 2
  • 30
  • 46
Bill
  • 21
  • 1
  • 5
    Type all the names in a text document. Print as many copies as there are voters and give each voter a copy. Have them draw a checkmark next to the name of the person they want elected, fold the paper, then put it in a cardboard box. When everyone has voted, count the ballots. The person with the most checkmarks is elected. – Dour High Arch Aug 13 '11 at 01:14
  • Dour High, absolutely brilliant. +1 for the laughs. – BRampersad Aug 13 '11 at 01:40

1 Answers1

2

If I were you, I would make a database in the Database Events application called "Voters". When the script is run, check for a record whose name is the current user's name. If the record exists, the user has voted. Likewise, if the record doesn't exist, the user hasn't voted. Translated into code this paragraph reads:

set user_has_voted to false --inital value

tell application "Database Events"
    try
        get database "Voters"
        open database POSIX path of (path to documents folder) & "/Databases/Voters.dbev"
    on error
        make new database with properties {name:"Voters"}
        save
    end try
end tell
set the current_user to the long user name of (system info)
tell application "Database Events"
    tell database "Voters"
        try
            get record current_user
            --No error, the user has voted
            set user_has_voted to true
        on error
            make new record with properties {name:current_user}
            set user_has_voted to false
        end try
    end tell
    close database "Voters" saving yes
end tell

if user_has_voted then
    ...
else
    vote()
end if

This is more secure than using a property because it can determine if the same user has voted within any time frame.

UPDATE: Per @regulus6633's comment, I have added a subroutine (that you can put at the bottom of the previous script) and another script to help you with the job. The subroutine stores the votes in a database, and the script following the subroutine retrieves the info from the database.

on vote()
    set the rating_results to (choose from list {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} with prompt "Please rate (somebody) based on your observations. BE HONEST!")
    if the rating_results is false then error number -128
    tell application "Database Events"
        try
            get database "Votes"
            open database POSIX path of (path to documents folder) & "/Databases/Votes.dbev"
        on error
            make new database with properties {name:"Votes"}
            save
        end try
        try
            get record "Vote Frequency" of database "Votes"
        on error
            tell database "Votes" to make new record with properties {name:"Vote Frequency"}
        end try
        tell database "Votes"
            tell record "Vote Frequency"
                if exists field rating_results then
                    set the value of field rating_results to the value of field rating_results & the rating_results
                else
                    tell (make new field with properties {name:rating_results, value:{}}) to set the end of the value of it to the rating_results
                end if
            end tell
        end tell
        close database "Votes" saving yes
    end tell
end vote

Here is how you would retrieve the voting information from the Votes database.

tell application "Database Events"
    try
        get database "Votes"
        open database POSIX path of (path to documents folder) & "/Databases/Votes"
    on error
        my nobody_voted_yet() --Database Events doesn't allow any user interaction, so we have to use a subroutine to display information to the user
    end try
    set the votes to {}
    set the vote_total to 0
    tell database "Votes"
        tell record "Vote Frequency"
            repeat with i from 1 to the count of fields
                repeat with this_vote in the value of field i
                    set the end of votes to this_vote
                    set the vote_total to the vote_total + this_vote
                end repeat
            end repeat
        end tell
    end tell
    close database "Votes" saving yes --It is always a good idea to save the database, even if you're just retrieving values. This reduces the risk of the values changing themselves.
    my average_votes(votes, vote_total)
end tell

on nobody_voted_yet()
    display dialog "Nobody voted yet! You can't retrieve information that doesn't exist!" buttons{"Cancel"} default button 1
end nobody_voted_yet

on average_votes(vote_length, vote_total)
    set the voting_result to (the vote_total / (length of the vote_length))
    display dialog "The average rating for (somebody) is: " & (round the voting_result as string)
end average_votes
fireshadow52
  • 6,298
  • 2
  • 30
  • 46
  • 1
    I like this idea of a database. It's easy and effective. I would extend it though. Why not save the vote into the database too? Then you wouldn't have to receive an email of the vote. You could use a second script to retrieve the votes from the database. The second script would sum them for you and divide by the total number of records in the database to get an average rating. – regulus6633 Aug 13 '11 at 05:49
  • @regulus6633 I updated the answer to reflect what you said :) – fireshadow52 Aug 13 '11 at 17:55
  • Very nice fireshadow52, I like it! – regulus6633 Aug 13 '11 at 23:25
  • @regulus6633 I bet you would upvote this again if you could :P – fireshadow52 Aug 13 '11 at 23:39