670 lines
32 KiB
Lua
670 lines
32 KiB
Lua
-- The machine requires _three_ touch screens connected: one set to channel "vote", other set to "admin", and third to "submit"
|
|
|
|
-- FIXME: I was sleepy: make sure when entries are added/removed, all mappings are in sync
|
|
-- FIXME: "results" view not opening when there are no votes?
|
|
|
|
local categories = {"Creativity", "Aesthetic Appeal", "Detail & Execution", "Use of space"}
|
|
local num_categories = #categories
|
|
local min_cat_score = 1
|
|
local max_cat_score = 3
|
|
local ENTRIES_PER_PAGE = 8 -- for ballots with large amount of entries
|
|
|
|
function show_vote_welcome()
|
|
-- window shown before player can see the ballot
|
|
-- by making them click the button, we can know their name
|
|
|
|
if mem.vote_active then
|
|
digiline_send("vote",
|
|
{
|
|
{command = "clear"},
|
|
{command = "set",
|
|
width = 10.5,
|
|
height = 7,
|
|
real_coordinates = true,
|
|
},
|
|
{command = "addtextarea", name = "", default = mem.message_welcome_vote, X = 1.8, Y = 1.4, W = 7, H = 2.6},
|
|
{command = "addbutton", name = "start", label = "Begin voting", X = 3.1, Y = 4.6, W = 4.3, H = 1.7},
|
|
}
|
|
)
|
|
else
|
|
digiline_send("vote",
|
|
{
|
|
{command = "clear"},
|
|
{command = "set",
|
|
width = 6,
|
|
height = 2,
|
|
real_coordinates = true,
|
|
},
|
|
{command = "addlabel", label = "Voting is stopped!", X = 0.5, Y = 1.0},
|
|
}
|
|
)
|
|
end
|
|
end
|
|
|
|
|
|
function show_vote_error(voter, offender)
|
|
-- show this when owner of the ballot and clicker do not match
|
|
local msg = string.format("%s has tried to cast a vote instead of %s!\nThey also saw %s's votes, they're naughty!", offender, voter, voter)
|
|
digiline_send("vote",
|
|
{
|
|
{command = "clear"},
|
|
{command = "set",
|
|
width = 10.5,
|
|
height = 11,
|
|
real_coordinates = true,
|
|
},
|
|
{command = "addlabel", label = "ERROR!", X = 4.7, Y = 2.4},
|
|
{command = "addtextarea", name = "", label = "", default = msg, X = 1.3, Y = 3.2, W = 7.9, H = 4.1},
|
|
{command = "addbutton", name = "start", label = "Start", X = 3.8, Y = 9.6, W = 3, H = 0.8},
|
|
{command = "addlabel", label = "Try again:", X = 1.4, Y = 10}
|
|
}
|
|
)
|
|
end
|
|
|
|
|
|
function show_admin_welcome()
|
|
-- just a menu to select from 2 windows
|
|
|
|
local toggle_submit_label = mem.submit_active and "Stop submissions" or "Allow submissions"
|
|
local toggle_vote_label = mem.vote_active and "Disable voting" or "Enable voting"
|
|
digiline_send("admin",
|
|
{
|
|
{command = "clear"},
|
|
{command = "set",
|
|
width = 10.5,
|
|
height = 11,
|
|
real_coordinates = true,
|
|
locked = true,
|
|
},
|
|
{command = "addlabel", label = "Admin only!", X = 4.4, Y = 1.3},
|
|
{command = "addlabel",
|
|
label = "Submissions: " .. (mem.submit_active and "accepting" or "stopped"),
|
|
X = 0.6, Y = 2.0},
|
|
{command = "addlabel",
|
|
label = "Voting: " .. (mem.vote_active and "active" or "stopped"),
|
|
X = 0.6, Y = 2.3},
|
|
{command = "addbutton", name = "edit_entries", label = "Edit entries", X = 3.7, Y = 2.3, W = 3, H = 0.8},
|
|
{command = "addbutton", name = "view_results", label = "View results", X = 3.7, Y = 3.7, W = 3, H = 0.8},
|
|
{command = "addbutton", name = "toggle_submit",
|
|
label = toggle_submit_label,
|
|
X = 3.7, Y = 5.1, W = 3, H = 0.8},
|
|
{command = "addbutton", name = "toggle_vote",
|
|
label = toggle_vote_label,
|
|
X = 3.7, Y = 6.5, W = 3, H = 0.8},
|
|
{command = "addbutton", name = "edit_messages", label = "Edit messages", X = 3.7, Y = 7.9, W = 3, H = 0.8},
|
|
{command = "addbutton", name = "danger_zone", label = "Danger zone", X = 3.7, Y = 9.3, W = 3, H = 0.8},
|
|
|
|
}
|
|
)
|
|
end
|
|
|
|
|
|
function show_admin_edit()
|
|
-- screen for adding/removing entries
|
|
local list_entries = {}
|
|
for _,e in ipairs(mem.entries) do
|
|
table.insert(list_entries, string.format("%s|[%s] - %s", e.accepted and "#00FF00[+]" or "[-]", e.user or "", e.title or ""))
|
|
end
|
|
|
|
local entry = mem.entries[mem.admin_entries_idx] or {}
|
|
digiline_send("admin",
|
|
{
|
|
{command = "clear"},
|
|
{command = "set",
|
|
width = 16,
|
|
height = 12,
|
|
real_coordinates = true,
|
|
locked = true, -- does not prevent someone from looking at it :(
|
|
},
|
|
{command = "addtextlist", name = "entries", listelements = list_entries, transparent = false, selected_id = mem.admin_entries_idx, X = 0.5, Y = 0.5, W = 11.0, H = 6.0},
|
|
{command = "addtextarea", name = "", label = "Coordinates:", default = entry.coords or "<NONE>", X = 0.5, Y = 7.0, W = 11.0, H = 0.5},
|
|
{command = "addtextarea", name = "", label = "Description:", default = entry.description or "<NONE>", X = 0.5, Y = 8, W = 11.0, H = 2.0},
|
|
|
|
{command = "addbutton", name = "edit_accept", label = "Accept/Decline", X = 12.2, Y = 4.3, W = 3, H = 0.8},
|
|
{command = "addfield", name = "new_entry_submitter", label = "New entry submitter", default = "", X = 1.2, Y = 10.4, W = 2.5, H = 0.8},
|
|
{command = "addfield", name = "new_entry_title", label = "New entry title", default = "", X = 4.0, Y = 10.4, W = 8.5, H = 0.8},
|
|
{command = "addbutton", name = "add_entry", label = "Add entry", X = 13.0, Y = 10.4, W = 1.7, H = 0.8},
|
|
{command = "addbutton", name = "delete_entry", label = "Delete", X = 12.7, Y = 8, W = 1.5, H = 0.8},
|
|
{command = "add", element = "field_close_on_enter", name = "new_entry", close_on_enter = false},
|
|
|
|
{command = "addbutton", name = "edit_back", label = "Back", X = 12.7, Y = 0.3, W = 1.7, H = 0.8},
|
|
}
|
|
)
|
|
end
|
|
|
|
|
|
function show_admin_results()
|
|
-- count and show results
|
|
|
|
-- count the votes that we actually cast
|
|
-- local total_scores = {}
|
|
-- for _,player_votes in pairs(mem.votes) do
|
|
-- for entry, cats in pairs(player_votes) do
|
|
-- local entry_scores = total_scores[entry] or {}
|
|
-- total_scores[entry] = entry_scores
|
|
-- for cat, value in pairs(cats) do
|
|
-- local cs = (entry_scores[cat] or 0) + value
|
|
-- entry_scores[cat] = cs
|
|
-- end
|
|
-- end
|
|
-- end
|
|
|
|
-- for all entries, check all known votes and add them up, using defaults if none
|
|
-- TODO can be made more efficient probably
|
|
local total_scores = {}
|
|
for b_i, e in ipairs(mem.ballot_entries) do
|
|
local id = e.id
|
|
local entry_scores = {}
|
|
-- need initial values for when there's no votes yet:
|
|
for c_i = 1, num_categories do
|
|
entry_scores[c_i] = 0
|
|
end
|
|
total_scores[b_i] = entry_scores
|
|
entry_scores.id = id
|
|
for _,player_votes in pairs(mem.votes) do
|
|
local entry_votes = player_votes[id] or {} -- nil if didn't cast any votes for this entry
|
|
for c_i = 1, num_categories do
|
|
local vote = (entry_votes[c_i] or min_cat_score)
|
|
entry_scores[c_i] = (entry_scores[c_i] or 0) + vote
|
|
end
|
|
end
|
|
end
|
|
|
|
-- sort by different fields
|
|
local sorted_by_str = "none"
|
|
if mem.sort_type == "sum" then
|
|
sorted_by_str = "Sorted by sum:"
|
|
table.sort(total_scores, function(a,b) return (a[1] + a[2] + a[3] + a[4]) > (b[1] + b[2] + b[3] + b[4]) end)
|
|
elseif type(mem.sort_type) == "number" then
|
|
sorted_by_str = string.format("Sorted by '%s':", categories[mem.sort_type])
|
|
local idx = mem.sort_type
|
|
table.sort(total_scores, function(a,b) return a[idx] > b[idx] end)
|
|
end
|
|
|
|
-- actually generate strings for the results table
|
|
local entry_list = {}
|
|
for _, s in ipairs(total_scores) do
|
|
local name = mem.entries_by_id[s.id].title
|
|
local sum = s[1] + s[2] + s[3] + s[4]
|
|
table.insert(entry_list, string.format("%03d||%03d|%03d|%03d|%03d -- %s", sum, s[1], s[2], s[3], s[4], name))
|
|
end
|
|
|
|
digiline_send("admin",
|
|
{
|
|
{command = "clear"},
|
|
{command = "set",
|
|
width = 16,
|
|
height = 12,
|
|
real_coordinates = true,
|
|
locked = true, -- does not prevent someone from looking at it :(
|
|
},
|
|
{command = "addlabel", label = sorted_by_str, X = 0.9, Y = 0.6},
|
|
{command = "addbutton", name = "results_update", label = "Update", X = 8.7, Y = 0.3, W = 3, H = 1},
|
|
{command = "addbutton", name = "results_back", label = "Back", X = 12.7, Y = 0.3, W = 3, H = 1},
|
|
{command = "addtextlist", name = "", listelements = entry_list, transparent = false, selected_id = 1, X = 0.3, Y = 1.5, W = 12.3, H = 9.2},
|
|
{command = "addlabel", label = "Sort by:", X = 13.5, Y = 2.6},
|
|
{command = "addbutton", name = "sort_sum", label = "Sum", X = 12.7, Y = 3.1, W = 3, H = 1},
|
|
{command = "addbutton", name = "sort_1", label = categories[1], X = 12.7, Y = 4.2, W = 3, H = 1},
|
|
{command = "addbutton", name = "sort_2", label = categories[2], X = 12.7, Y = 5.3, W = 3, H = 1},
|
|
{command = "addbutton", name = "sort_3", label = categories[3], X = 12.7, Y = 6.4, W = 3, H = 1},
|
|
{command = "addbutton", name = "sort_4", label = categories[4], X = 12.7, Y = 7.5, W = 3, H = 1},
|
|
}
|
|
)
|
|
end
|
|
|
|
|
|
function show_admin_danger()
|
|
digiline_send("admin",
|
|
{
|
|
{command = "clear"},
|
|
{command = "set",
|
|
width = 16,
|
|
height = 12,
|
|
real_coordinates = true,
|
|
locked = true, -- does not prevent someone from looking at it :(
|
|
},
|
|
{command = "addbutton", name = "danger_back", label = "Back", X = 12.7, Y = 0.3, W = 3, H = 1},
|
|
{command = "addbutton", name = "danger_vote_reset", label = "RESET VOTES", X = 1.7, Y = 0.3, W = 3, H = 1},
|
|
{command = "addbutton", name = "danger_memory_reset", label = "WIPE ALL MEMORY", X = 1.7, Y = 2.3, W = 3, H = 1},
|
|
}
|
|
)
|
|
end
|
|
|
|
|
|
function show_admin_messages()
|
|
digiline_send("admin",
|
|
{
|
|
{command = "clear"},
|
|
{command = "set",
|
|
width = 16,
|
|
height = 12,
|
|
real_coordinates = true,
|
|
locked = true, -- does not prevent someone from looking at it :(
|
|
},
|
|
{command = "addlabel", label = "Enter information about vote", X = 1, Y = 0.9},
|
|
{command = "addbutton", name = "messages_back", label = "Back", X = 12.7, Y = 0.3, W = 3, H = 1},
|
|
{command = "addtextarea", name = "message_welcome_vote", label = "Voting welcome", default = mem.message_welcome_vote, X = 0.5, Y = 1.5, W = 15.0, H = 2.5},
|
|
{command = "addtextarea", name = "message_welcome_submission", label = "Submission welcome", default = mem.message_welcome_submission, X = 0.5, Y = 4.5, W = 15.0, H = 2.5},
|
|
{command = "addtextarea", name = "message_submission_instructions", label = "Submission instructions", default = mem.message_submission_instructions, X = 0.5, Y = 7.5, W = 15.0, H = 2.5},
|
|
{command = "addbutton", name = "messages_ok", label = "OK", X = 12.6, Y = 10.7, W = 3, H = 0.8},
|
|
}
|
|
)
|
|
end
|
|
|
|
|
|
|
|
function show_vote_ballot(username)
|
|
local c =
|
|
{
|
|
{command = "clear"},
|
|
{command = "set",
|
|
width = 18,
|
|
height = 14,
|
|
real_coordinates = true,
|
|
},
|
|
|
|
{command = "addtextarea", name='', default = username .. " - " .. mem.message_welcome_vote, X = 0.5, Y = 0.4, W = 9.0, H = 0.8},
|
|
{command = "addtextarea", name='', default = categories[1], X = 10.5, Y = 0.4, W = 1.6, H = 1.0},
|
|
{command = "addtextarea", name='', default = categories[2], X = 12.2, Y = 0.4, W = 1.6, H = 1.0},
|
|
{command = "addtextarea", name='', default = categories[3], X = 13.9, Y = 0.4, W = 1.6, H = 1.0},
|
|
{command = "addtextarea", name='', default = categories[4], X = 15.7, Y = 0.4, W = 1.6, H = 1.0},
|
|
{command = "addlabel", label = "Your choices are saved automatically!", X = 6.8, Y = 12.5},
|
|
{command = "addbutton", name = "vote_done", label = "Done", X = 14.0, Y = 12, W = 3, H = 1},
|
|
}
|
|
local shift = 1.3 -- vertical spacing between entries
|
|
local votes = mem.votes[username] or {}
|
|
local page = mem.ballot_page
|
|
|
|
for i=1,ENTRIES_PER_PAGE do
|
|
local e = mem.ballot_entries[i + ENTRIES_PER_PAGE*page]
|
|
if not e then
|
|
break -- not enough entries to fill the page
|
|
end
|
|
local id = e.id
|
|
local choices = {}
|
|
for idx = 0, (max_cat_score - min_cat_score) do
|
|
choices[idx+1] = tostring(idx + min_cat_score)
|
|
end
|
|
local default_id = min_cat_score == 0 and 0 or 1
|
|
local e_v = votes[id] or {} -- previous votes of this player for this entry (if any)
|
|
table.insert(c, {command = "addimage", texture_name = "halo.png^[colorize:#222233", X = 0.5, Y = 0.4 + shift*i, W = 16.8, H = 1})
|
|
table.insert(c, {command = "addlabel", label = e.title, X = 0.8, Y = 0.9 + shift*i})
|
|
table.insert(c, {command = "adddropdown", name = string.format("v_%d_1", id), index_event = true,
|
|
selected_id = e_v[1] and (e_v[1] - min_cat_score + 1) or default_id,
|
|
choices = choices, X = 10.8, Y = 0.5 + shift*i, W = 0.8, H = 0.8})
|
|
table.insert(c, {command = "adddropdown", name = string.format("v_%d_2", id), index_event = true,
|
|
selected_id = e_v[2] and (e_v[2] - min_cat_score + 1) or default_id,
|
|
choices = choices, X = 12.6, Y = 0.5 + shift*i, W = 0.8, H = 0.8})
|
|
table.insert(c, {command = "adddropdown", name = string.format("v_%d_3", id), index_event = true,
|
|
selected_id = e_v[3] and (e_v[3] - min_cat_score + 1) or default_id,
|
|
choices = choices, X = 14.4, Y = 0.5 + shift*i, W = 0.8, H = 0.8})
|
|
table.insert(c, {command = "adddropdown", name = string.format("v_%d_4", id), index_event = true,
|
|
selected_id = e_v[4] and (e_v[4] - min_cat_score + 1) or default_id,
|
|
choices = choices, X = 16.2, Y = 0.5 + shift*i, W = 0.8, H = 0.8})
|
|
end
|
|
|
|
-- snow number of pages and page flipping buttons
|
|
local total_pages = math.ceil(#mem.ballot_entries / ENTRIES_PER_PAGE)
|
|
table.insert(c, {command = "addlabel", label = string.format("Page %s/%s", mem.ballot_page+1, total_pages), X = 0.8, Y = 12.5})
|
|
if mem.ballot_page > 0 then
|
|
table.insert(c, {command = "addbutton", name = "ballot_page_prev", label = "Prev page", X = 2.5, Y = 12.5, W = 3, H = 1})
|
|
end
|
|
if (mem.ballot_page + 1) < total_pages then
|
|
table.insert(c, {command = "addbutton", name = "ballot_page_next", label = "Next page", X = 5.5, Y = 12.5, W = 3, H = 1})
|
|
end
|
|
|
|
digiline_send("vote", c)
|
|
|
|
end
|
|
|
|
|
|
function show_submit_welcome()
|
|
if mem.submit_active then
|
|
digiline_send("submit",
|
|
{
|
|
{command = "clear"},
|
|
{command = "set",
|
|
width = 10.5,
|
|
height = 7,
|
|
real_coordinates = true,
|
|
},
|
|
{command = "addtextarea", name = "", default = mem.message_welcome_submission, X = 1.8, Y = 1.4, W = 7, H = 2.6},
|
|
{command = "addbutton", name = "start_submission", label = "Enter submission", X = 3.1, Y = 4.6, W = 4.3, H = 1.7},
|
|
}
|
|
)
|
|
else
|
|
digiline_send("submit",
|
|
{
|
|
{command = "clear"},
|
|
{command = "set",
|
|
width = 6,
|
|
height = 2,
|
|
real_coordinates = true,
|
|
},
|
|
{command = "addlabel", label = "Currently not accepting new submissions, sorry!", X = 0.5, Y = 1.0},
|
|
}
|
|
)
|
|
end
|
|
end
|
|
|
|
|
|
function show_submit(username)
|
|
local submission = mem.entries_by_user[username] or {}
|
|
|
|
digiline_send("submit",
|
|
{
|
|
{command = "clear"},
|
|
{command = "set",
|
|
width = 18,
|
|
height = 12,
|
|
real_coordinates = true,
|
|
},
|
|
{command = "add", element = "box", X = 0.6, Y = 10.5, W = 17.0, H = 1.2, color = "#00FF00"},
|
|
{command = "addtextarea", name = "", label = "", default = "Please fill the fields and press 'submit'", X = 0.7, Y = 10.55, W = 13.5, H = 1.05},
|
|
{command = "addlabel", label = string.format("Welcome %s!", username), X = 0.9, Y = 0.7},
|
|
{command = "addtextarea", name = "", label = "", default = mem.message_submission_instructions, X = 0.9, Y = 1.8, W = 16.3, H = 2},
|
|
{command = "addfield", name = "submission_title", label = "Name of submission:", default = submission.title or "", X = 0.7, Y = 3.5, W = 10, H = 0.8},
|
|
{command = "addfield", name = "submission_coords", label = "Coordinates:", default = submission.coords or "", X = 0.7, Y = 5.0, W = 5, H = 0.8},
|
|
{command = "addtextarea", name = "submission_description", label = "Please enter your submission:", default = submission.description or "", X = 0.7, Y = 6.8, W = 16.8, H = 3.5},
|
|
{command = "addbutton", name = "submission_submit", label = mem.entries_by_user[username] and "Update" or "Submit", X = 14.5, Y = 10.7, W = 3, H = 0.8},
|
|
{command = "addbutton", name = "submission_back", label = "Back", X = 14.5, Y = 0.7, W = 3, H = 0.8},
|
|
}
|
|
)
|
|
end
|
|
|
|
if event.type == "program" then
|
|
-- initialize defaults or use stored values
|
|
|
|
mem.id_count = mem.id_count or 1 -- unique entry ID generator
|
|
mem.username = nil -- current voter's name
|
|
mem.entries_by_id = mem.entries_by_id or {} -- mapping from id to entry
|
|
mem.entries_by_user = mem.entries_by_user or {}
|
|
mem.entries = mem.entries or {} -- ordered list of entries
|
|
mem.ballot_entries = mem.ballot_entries or {}
|
|
mem.admin_entries_idx = nil -- stores list selection for "edit" screen
|
|
mem.votes = mem.votes or {} -- user votes
|
|
mem.state_admin = "welcome" -- which admin window is currently displayed
|
|
mem.sort_type = "sum" -- what sort to use ("sum" or 1,2,3,4)
|
|
mem.ballot_page = 0 -- current ballot page
|
|
mem.vote_active = true
|
|
mem.submit_active = true
|
|
mem.submitter_name = nil
|
|
|
|
mem.message_welcome_submission = mem.message_welcome_submission or "Welcome to the entry submission for BOTM 2025 decebruary!"
|
|
mem.message_welcome_vote = mem.message_welcome_vote or "Welcome! Please vote for BOTM 2025 decebruary submissions!"
|
|
mem.message_submission_instructions = mem.message_submission_instructions or "Please enter the coords of your build and describe how to get there (what is the closest city, means of transporation, etc)."
|
|
|
|
-- reset screens
|
|
show_vote_welcome()
|
|
show_admin_welcome()
|
|
show_submit_welcome()
|
|
|
|
elseif event.type == "digiline" then
|
|
if event.channel == "vote" then
|
|
if not mem.vote_active then
|
|
show_vote_welcome()
|
|
end
|
|
if event.msg.start then
|
|
-- show user's ballot
|
|
mem.username = event.msg.clicker
|
|
mem.ballot_page = 0
|
|
show_vote_ballot(mem.username)
|
|
elseif event.msg.quit then
|
|
-- clear screen after user closed the window
|
|
show_vote_welcome()
|
|
elseif event.msg.ballot_page_next then
|
|
-- flip page
|
|
mem.ballot_page = mem.ballot_page + 1
|
|
show_vote_ballot(mem.username)
|
|
elseif event.msg.ballot_page_prev then
|
|
-- flip page
|
|
mem.ballot_page = mem.ballot_page - 1
|
|
show_vote_ballot(mem.username)
|
|
elseif event.msg.vote_done then
|
|
show_vote_welcome()
|
|
else
|
|
-- process vote selection
|
|
if mem.username ~= event.msg.clicker then
|
|
-- clicker is not the currently voting user! abort! :P
|
|
-- TODO show the offender's name on this screen
|
|
local name = mem.username
|
|
mem.username = nil
|
|
show_vote_error(name, event.msg.clicker)
|
|
end
|
|
|
|
local votes = mem.votes[event.msg.clicker] or {}
|
|
mem.votes[event.msg.clicker] = votes
|
|
for k,v in pairs(event.msg) do
|
|
-- find and parse "v_<entry_idx>_<crit_idx>" key
|
|
if k:sub(1,2) == "v_" then
|
|
local vote = k:sub(3)
|
|
local off = vote:find("_", 1, true)
|
|
local e_id = tonumber(vote:sub(1,off-1)) or 0 -- entry ID
|
|
local c_id = tonumber(vote:sub(off+1)) or 0 -- category ID
|
|
local entry = votes[e_id] or {}
|
|
-- store vote
|
|
votes[e_id] = entry
|
|
entry[c_id] = tonumber(v) + min_cat_score - 1 or min_cat_score -- vote value for this category
|
|
end
|
|
end
|
|
--digiline_send("debug", mem.votes) -- TODO remove this
|
|
end
|
|
elseif event.channel == "submit" then
|
|
if event.msg.start_submission then
|
|
show_submit(event.msg.clicker)
|
|
mem.submitter_name = event.msg.clicker
|
|
elseif event.msg.submission_submit then
|
|
local user = event.msg.clicker
|
|
local function show_error(color, msg)
|
|
digiline_send("submit",
|
|
{
|
|
{command = "modify", index = 1, color = color},
|
|
{command = "modify", index = 2, default = msg},
|
|
{command = "modify", index = 5, default = event.msg.submission_title},
|
|
{command = "modify", index = 6, default = event.msg.submission_coords},
|
|
{command = "modify", index = 7, default = event.msg.submission_description},
|
|
}
|
|
)
|
|
end
|
|
if not (event.msg.clicker == mem.submitter_name) then
|
|
show_error("#FF0000", string.format("%s pressed submit!\nYou can't submit for another user! Press 'back' and enter again!", user))
|
|
return
|
|
end
|
|
local sub = mem.entries_by_user[user]
|
|
if not sub then
|
|
local new_id = mem.id_count
|
|
mem.id_count = mem.id_count + 1 -- update unique ID generator
|
|
sub = {
|
|
id = new_id,
|
|
user = user,
|
|
accepted = false,
|
|
}
|
|
mem.entries_by_user[user] = sub
|
|
mem.entries_by_id[new_id] = sub
|
|
table.insert(mem.entries, sub)
|
|
end
|
|
|
|
local title = event.msg.submission_title
|
|
if not title or title == "" then
|
|
-- TODO validate the title (limit length)
|
|
show_error("#FF0000", "ERROR: Please enter the name of submission!")
|
|
return
|
|
end
|
|
-- if title:find(",", 1, true) then
|
|
-- show_error("#FF0000", "ERROR: Submission name can't have commas!")
|
|
-- return
|
|
-- end
|
|
|
|
sub.title = title
|
|
|
|
local coords = event.msg.submission_coords
|
|
if not coords or coords == "" then
|
|
-- TODO validate coords
|
|
show_error("#FF0000", "ERROR: Please enter the coordinates!")
|
|
return
|
|
end
|
|
sub.coords = coords
|
|
|
|
local description = event.msg.submission_description
|
|
if not description or description == "" then
|
|
show_error("#FF0000", "ERROR: Please provide description!")
|
|
return
|
|
end
|
|
sub.description = description
|
|
mem.submitter_name = nil
|
|
show_submit_welcome()
|
|
elseif event.msg.submission_back then
|
|
show_submit_welcome()
|
|
end
|
|
elseif event.channel == "admin" then
|
|
if mem.state_admin == "welcome" then
|
|
if event.msg.edit_entries then
|
|
-- show "edit" window
|
|
mem.state_admin = "edit"
|
|
show_admin_edit()
|
|
elseif event.msg.view_results then
|
|
-- show "results" window
|
|
mem.state_admin = "results"
|
|
show_admin_results()
|
|
elseif event.msg.toggle_vote then
|
|
mem.vote_active = not mem.vote_active
|
|
show_admin_welcome()
|
|
show_vote_welcome()
|
|
elseif event.msg.toggle_submit then
|
|
mem.submit_active = not mem.submit_active
|
|
show_admin_welcome()
|
|
show_submit_welcome()
|
|
elseif event.msg.edit_messages then
|
|
mem.state_admin = "messages"
|
|
show_admin_messages()
|
|
elseif event.msg.danger_zone then
|
|
mem.state_admin = "danger_zone"
|
|
show_admin_danger()
|
|
end
|
|
elseif mem.state_admin == "edit" then
|
|
if event.msg.entries then
|
|
-- changed selection, store index
|
|
local e = event.msg.entries
|
|
if e:sub(1,4) == "CHG:" then
|
|
mem.admin_entries_idx = tonumber(e:sub(5))
|
|
end
|
|
show_admin_edit()
|
|
elseif event.msg.add_entry or (event.msg.key_enter_field == "new_entry_title") then
|
|
-- adding new entry
|
|
local new_title = event.msg.new_entry_title
|
|
if not new_title:find(",", 1, true) then -- can't have "," in names, do nothing if found
|
|
local new_id = mem.id_count
|
|
mem.id_count = mem.id_count + 1 -- update unique ID generator
|
|
if new ~= "" then -- add when not empty
|
|
local entry = {id = new_id, title = new_title, user = event.msg.new_entry_submitter}
|
|
table.insert(mem.entries, entry) -- store in ordered list
|
|
mem.entries_by_id[new_id] = entry -- store in ID -> entry map
|
|
end
|
|
show_admin_edit()
|
|
end
|
|
elseif event.msg.delete_entry then
|
|
-- removing selected entry
|
|
-- TODO either re-index existing votes, or even wipe all of them?!
|
|
local entry = mem.entries[mem.admin_entries_idx]
|
|
if entry then
|
|
table.remove(mem.entries, mem.admin_entries_idx)
|
|
mem.entries_by_id[entry.id] = nil
|
|
for pname, votes in pairs(mem.votes) do
|
|
votes[entry.id] = nil
|
|
end
|
|
-- try to keep stored index up-to-date with what user is seeing
|
|
mem.admin_entries_idx = math.min(mem.admin_entries_idx, #mem.entries)
|
|
show_admin_edit()
|
|
end
|
|
elseif event.msg.edit_accept then
|
|
local entry = mem.entries[mem.admin_entries_idx]
|
|
if entry then
|
|
entry.accepted = not entry.accepted
|
|
if entry.accepted then
|
|
table.insert(mem.ballot_entries, entry)
|
|
else
|
|
for i = #mem.ballot_entries, 1, -1 do
|
|
if mem.ballot_entries[i] == entry then
|
|
table.remove(mem.ballot_entries, i)
|
|
end
|
|
end
|
|
end
|
|
show_admin_edit()
|
|
end
|
|
elseif event.msg.edit_back then
|
|
mem.state_admin = "welcome"
|
|
show_admin_welcome()
|
|
end
|
|
elseif mem.state_admin == "results" then
|
|
if event.msg.results_back then
|
|
mem.state_admin = "welcome"
|
|
show_admin_welcome()
|
|
elseif event.msg.results_update then
|
|
-- just re-generate window (will recalculate results)
|
|
show_admin_results()
|
|
elseif event.msg.sort_sum then
|
|
-- change sorting type and show updated window
|
|
mem.sort_type = "sum"
|
|
show_admin_results()
|
|
elseif event.msg.sort_1 then
|
|
mem.sort_type = 1
|
|
show_admin_results()
|
|
elseif event.msg.sort_2 then
|
|
mem.sort_type = 2
|
|
show_admin_results()
|
|
elseif event.msg.sort_3 then
|
|
mem.sort_type = 3
|
|
show_admin_results()
|
|
elseif event.msg.sort_4 then
|
|
mem.sort_type = 4
|
|
show_admin_results()
|
|
end
|
|
elseif mem.state_admin == "messages" then
|
|
if event.msg.messages_back then
|
|
mem.state_admin = "welcome"
|
|
show_admin_welcome()
|
|
elseif event.msg.messages_ok then
|
|
mem.message_welcome_vote = event.msg.message_welcome_vote
|
|
mem.message_welcome_submission = event.msg.message_welcome_submission
|
|
mem.message_submission_instructions = event.msg.message_submission_instructions
|
|
show_admin_welcome()
|
|
show_vote_welcome()
|
|
show_submit_welcome()
|
|
mem.state_admin = "welcome"
|
|
end
|
|
elseif mem.state_admin == "danger_zone" then
|
|
if event.msg.danger_back then
|
|
mem.state_admin = "welcome"
|
|
show_admin_welcome()
|
|
elseif event.msg.danger_vote_reset then
|
|
mem.votes = {} -- user votes
|
|
elseif event.msg.danger_memory_reset then
|
|
-- reset screens
|
|
show_vote_welcome()
|
|
show_admin_welcome()
|
|
show_submit_welcome()
|
|
|
|
mem.id_count = 1
|
|
mem.username = nil
|
|
mem.entries_by_id = {}
|
|
mem.entries_by_user = {}
|
|
mem.entries = {}
|
|
mem.ballot_entries = {}
|
|
mem.admin_entries_idx = nil
|
|
mem.votes = {}
|
|
mem.state_admin = "welcome"
|
|
mem.sort_type = "sum"
|
|
mem.ballot_page = 0
|
|
mem.vote_active = true
|
|
mem.submit_active = true
|
|
mem.submitter_name = nil
|
|
|
|
mem.message_welcome_submission = "Welcome to the entry submission for BOTM 2025 decebruary!"
|
|
mem.message_welcome_vote = "Welcome! Please vote for BOTM 2025 decebruary submissions!"
|
|
mem.message_submission_instructions = "Please enter the coords of your build and describe how to get there (what is the closest city, means of transporation, etc)."
|
|
|
|
end
|
|
end
|
|
end
|
|
end
|