"
src << browse(null ,"window=playerpolllist")
src << browse(output,"window=playerpoll;size=500x500")
if(POLLTYPE_RATING)
var/datum/db_query/query_rating_get_votes = SSdbcore.NewQuery({"
SELECT o.text, v.rating FROM [format_table_name("poll_option")] o, [format_table_name("poll_vote")] v
WHERE o.pollid = :id AND v.ckey = :ckey AND o.id = v.optionid
"}, list(
"id" = pollid,
"ckey" = ckey
))
if(!query_rating_get_votes.warn_execute())
qdel(query_rating_get_votes)
return
var/output = "
Player poll
"
output += "
Question: [pollquestion]"
output += "
Poll runs from [pollstarttime] until [pollendtime]"
var/rating
while(query_rating_get_votes.NextRow())
var/optiontext = query_rating_get_votes.item[1]
rating = query_rating_get_votes.item[2]
output += "
[optiontext] - [rating]"
qdel(query_rating_get_votes)
if(!rating)
output += "
"
if(!QDELETED(src))
src << browse(null ,"window=playerpolllist")
src << browse(output,"window=playerpoll;size=500x500")
if(POLLTYPE_MULTI)
var/datum/db_query/query_multi_get_votes = SSdbcore.NewQuery({"
SELECT optionid
FROM [format_table_name("poll_vote")]
WHERE pollid = :id AND ckey = :ckey
"}, list(
"id" = pollid,
"ckey" = ckey
))
if(!query_multi_get_votes.warn_execute())
qdel(query_multi_get_votes)
return
var/list/votedfor = list()
while(query_multi_get_votes.NextRow())
votedfor.Add(text2num(query_multi_get_votes.item[1]))
qdel(query_multi_get_votes)
var/list/datum/polloption/options = list()
var/maxoptionid = 0
var/minoptionid = 0
var/datum/db_query/query_multi_options = SSdbcore.NewQuery({"
SELECT id, text
FROM [format_table_name("poll_option")]
WHERE pollid = :id
"}, list(
"id" = pollid
))
if(!query_multi_options.warn_execute())
qdel(query_multi_options)
return
while(query_multi_options.NextRow())
var/datum/polloption/PO = new()
PO.optionid = text2num(query_multi_options.item[1])
PO.optiontext = query_multi_options.item[2]
if(PO.optionid > maxoptionid)
maxoptionid = PO.optionid
if(PO.optionid < minoptionid || !minoptionid)
minoptionid = PO.optionid
options += PO
qdel(query_multi_options)
var/output = "
Player poll
"
output += "
Question: [pollquestion]You can select up to [multiplechoiceoptions] options. If you select more, the first [multiplechoiceoptions] will be saved.
"
output += "
Poll runs from [pollstarttime] until [pollendtime]"
if(!votedfor.len)
output += "
"
output += "
"
src << browse(null ,"window=playerpolllist")
src << browse(output,"window=playerpoll;size=500x250")
if(POLLTYPE_IRV)
var/datum/asset/irv_assets = get_asset_datum(/datum/asset/group/irv)
irv_assets.send(src)
var/datum/db_query/query_irv_get_votes = SSdbcore.NewQuery({"
SELECT optionid FROM [format_table_name("poll_vote")]
WHERE pollid = :pollid AND ckey = :ckey AND deleted = 0
"}, list("pollid" = pollid, "ckey" = ckey))
if(!query_irv_get_votes.warn_execute())
qdel(query_irv_get_votes)
return
var/list/votedfor = list()
while(query_irv_get_votes.NextRow())
votedfor.Add(text2num(query_irv_get_votes.item[1]))
qdel(query_irv_get_votes)
var/list/datum/polloption/options = list()
var/datum/db_query/query_irv_options = SSdbcore.NewQuery({"
SELECT id, text
FROM [format_table_name("poll_option")]
WHERE pollid = :id
"}, list(
"id" = pollid
))
if(!query_irv_options.warn_execute())
qdel(query_irv_options)
return
while(query_irv_options.NextRow())
var/datum/polloption/PO = new()
PO.optionid = text2num(query_irv_options.item[1])
PO.optiontext = query_irv_options.item[2]
options["[PO.optionid]"] += PO
qdel(query_irv_options)
//if they already voted, use their sort
if (votedfor.len)
var/list/datum/polloption/newoptions = list()
for (var/V in votedfor)
var/datum/polloption/PO = options["[V]"]
if(PO)
newoptions["[V]"] = PO
options -= "[V]"
//add any options that they didn't vote on (some how, some way)
options = shuffle(options)
for (var/V in options)
newoptions["[V]"] = options["[V]"]
options = newoptions
//otherwise, lets shuffle it.
else
var/list/datum/polloption/newoptions = list()
while (options.len)
var/list/local_options = options.Copy()
var/key
//the jist is we randomly remove all options from a copy of options until only one reminds,
// move that over to our new list
// and repeat until we've moved all of them
while (local_options.len)
key = local_options[rand(1, local_options.len)]
local_options -= key
var/value = options[key]
options -= key
newoptions[key] = value
options = newoptions
var/output = {"
Player poll
Question: [pollquestion]Please sort the options in the order of
most preferred to
least preferred
Revoting has been enabled on this poll, if you think you made a mistake, simply revote
Poll runs from [pollstarttime] until [pollendtime]
"}
src << browse(null ,"window=playerpolllist")
src << browse(output,"window=playerpoll;size=500x500")
return
//Returns null on failure, TRUE if already voted, FALSE if not voted yet.
/mob/dead/new_player/proc/poll_check_voted(pollid, text = FALSE, silent = FALSE)
var/table = "poll_vote"
if (text)
table = "poll_textreply"
if (!SSdbcore.Connect())
to_chat(usr, "
Failed to establish database connection.", confidential = TRUE)
return
var/datum/db_query/query_hasvoted = SSdbcore.NewQuery({"
SELECT id
FROM `[format_table_name(table)]`
WHERE pollid = :id AND ckey = :ckey
"}, list(
"id" = pollid,
"ckey" = ckey
))
if(!query_hasvoted.warn_execute())
qdel(query_hasvoted)
return
if(query_hasvoted.NextRow())
qdel(query_hasvoted)
if(!silent)
to_chat(usr, "
You've already replied to this poll.", confidential = TRUE)
return TRUE
qdel(query_hasvoted)
return FALSE
//Returns adminrank for use in polls.
/mob/dead/new_player/proc/poll_rank()
. = "Player"
if(client.holder)
. = client.holder.rank.name
/mob/dead/new_player/proc/vote_rig_check()
if (usr != src)
if (!usr || !src)
return FALSE
//we gots ourselfs a dirty cheater on our hands!
log_game("[key_name(usr)] attempted to rig the vote by voting as [key]")
message_admins("[key_name_admin(usr)] attempted to rig the vote by voting as [key]")
to_chat(usr, "
You don't seem to be [key].")
to_chat(src, "
Something went horribly wrong processing your vote. Please contact an administrator, they should have gotten a message about this")
return FALSE
return TRUE
/mob/dead/new_player/proc/vote_valid_check(pollid, holder, type)
if(!SSdbcore.Connect())
to_chat(src, "
Failed to establish database connection.")
return
pollid = text2num(pollid)
if (!pollid || pollid < 0)
return FALSE
//validate the poll is actually the right type of poll and its still active
var/datum/db_query/query_validate_poll = SSdbcore.NewQuery({"
SELECT id
FROM [format_table_name("poll_question")]
WHERE id = :id AND Now() BETWEEN starttime AND endtime AND polltype = :type [(holder ? "" : "AND adminonly = false")]
"}, list(
"id" = pollid,
"type" = type
))
if(!query_validate_poll.warn_execute())
qdel(query_validate_poll)
return FALSE
if (!query_validate_poll.NextRow())
qdel(query_validate_poll)
return FALSE
qdel(query_validate_poll)
return TRUE
/**
* Processes vote form data and saves results to the database for an IRV type poll.
*
*/
/mob/dead/new_player/proc/vote_on_irv_poll(pollid, list/votelist)
if(!SSdbcore.Connect())
to_chat(src, "
Failed to establish database connection.")
return
if(IsAdminAdvancedProcCall())
return
if(!vote_rig_check())
return
if(!pollid)
return
// var/list/votelist = splittext(href_list["IRVdata"], ",")
if(!length(votelist))
to_chat(src, "
No ordering data found. Please try again or contact an administrator.")
var/admin_rank = "Player"
if(!QDELETED(client) && client.holder)
admin_rank = client.holder.rank.name
if (!vote_valid_check(pollid, client?.holder, POLLTYPE_IRV))
return FALSE
var/list/special_columns = list(
"datetime" = "NOW()",
"ip" = "INET_ATON(?)",
)
var/sql_votes = list()
for(var/o in votelist)
var/voteid = text2num(o)
if(!voteid)
continue
sql_votes += list(list(
"pollid" = pollid,
"optionid" = voteid,
"ckey" = ckey,
"ip" = client.address,
"adminrank" = admin_rank
))
//IRV results are calculated based on id order, we delete all of a user's votes to avoid potential errors caused by revoting and option editing
var/datum/db_query/query_delete_irv_votes = SSdbcore.NewQuery({"
UPDATE [format_table_name("poll_vote")] SET deleted = 1 WHERE pollid = :pollid AND ckey = :ckey
"}, list("pollid" = pollid, "ckey" = ckey))
if(!query_delete_irv_votes.warn_execute())
qdel(query_delete_irv_votes)
return
qdel(query_delete_irv_votes)
SSdbcore.MassInsert(format_table_name("poll_vote"), sql_votes, special_columns = special_columns)
return TRUE
/mob/dead/new_player/proc/vote_on_poll(pollid, optionid)
if(!SSdbcore.Connect())
to_chat(src, "
Failed to establish database connection.")
return
if(!vote_rig_check())
return
if(IsAdminAdvancedProcCall())
return
if(!pollid || !optionid)
return
//validate the poll
if (!vote_valid_check(pollid, client.holder, POLLTYPE_OPTION))
return FALSE
var/voted = poll_check_voted(pollid)
if(isnull(voted) || voted) //Failed or already voted.
return
var/adminrank = poll_rank()
if(!adminrank)
return
var/datum/db_query/query_option_vote = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank)
VALUES (Now(), :pollid, :optionid, :ckey, INET_ATON(:address), :adminrank)
"}, list(
"pollid" = pollid,
"optionid" = optionid,
"ckey" = ckey,
"address" = client.address,
"adminrank" = adminrank
))
if(!query_option_vote.warn_execute())
qdel(query_option_vote)
return
qdel(query_option_vote)
if(!QDELETED(usr))
usr << browse(null,"window=playerpoll")
return TRUE
/mob/dead/new_player/proc/log_text_poll_reply(pollid, replytext)
if(!SSdbcore.Connect())
to_chat(src, "
Failed to establish database connection.")
return
if(!vote_rig_check())
return
if(IsAdminAdvancedProcCall())
return
if(!pollid)
return
//validate the poll
if (!vote_valid_check(pollid, client.holder, POLLTYPE_TEXT))
return FALSE
if(!replytext)
to_chat(usr, "The text you entered was blank. Please correct the text and submit again.")
return
var/voted = poll_check_voted(pollid, text = TRUE, silent = TRUE)
if(isnull(voted))
return
var/adminrank = poll_rank()
if(!adminrank)
return
if(!(length(replytext) > 0) || !(length(replytext) <= 8000))
to_chat(usr, "The text you entered was invalid or too long. Please correct the text and submit again.")
return
var/datum/db_query/query_text_vote
if(!voted)
query_text_vote = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("poll_textreply")] (datetime, pollid, ckey, ip, replytext, adminrank)
VALUES (Now(), :pollid, :ckey, INET_ATON(:address), :replytext, :adminrank)
"}, list("pollid" = pollid, "ckey" = ckey, "address" = client.address, "replytext" = replytext, "adminrank" = adminrank))
else
query_text_vote = SSdbcore.NewQuery({"
UPDATE [format_table_name("poll_textreply")]
SET datetime = Now(), ip = INET_ATON(:address), replytext = :replytext WHERE pollid = :pollid AND ckey = :ckey
"}, list("address" = client.address, "replytext" = replytext, "pollid" = pollid, "ckey" = ckey))
if(!query_text_vote.warn_execute())
qdel(query_text_vote)
return
qdel(query_text_vote)
if(!QDELETED(usr))
usr << browse(null,"window=playerpoll")
return TRUE
/mob/dead/new_player/proc/vote_on_numval_poll(pollid, optionid, rating)
if(!SSdbcore.Connect())
to_chat(src, "
Failed to establish database connection.")
return
if(!vote_rig_check())
return
if(IsAdminAdvancedProcCall())
return
if(!pollid || !optionid || !rating)
return
//validate the poll
if (!vote_valid_check(pollid, client.holder, POLLTYPE_RATING))
return FALSE
var/datum/db_query/query_numval_hasvoted = SSdbcore.NewQuery({"
SELECT id
FROM [format_table_name("poll_vote")]
WHERE optionid = :id AND ckey = :ckey
"}, list(
"id" = optionid,
"ckey" = ckey
))
if(!query_numval_hasvoted.warn_execute())
qdel(query_numval_hasvoted)
return
if(query_numval_hasvoted.NextRow())
qdel(query_numval_hasvoted)
to_chat(usr, "
You've already replied to this poll.")
return
qdel(query_numval_hasvoted)
var/adminrank = "Player"
if(client.holder)
adminrank = client.holder.rank.name
var/datum/db_query/query_numval_vote = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("poll_vote")] (datetime ,pollid ,optionid ,ckey ,ip ,adminrank, rating)
VALUES (Now(), :pollid, :optionid, :ckey, INET_ATON(:address), :adminrank, :rating)
"}, list("pollid" = pollid, "optionid" = optionid, "ckey" = ckey, "address" = client.address, "adminrank" = adminrank, "rating" = isnull(rating) ? "null" : rating))
if(!query_numval_vote.warn_execute())
qdel(query_numval_vote)
return
qdel(query_numval_vote)
if(!QDELETED(usr))
usr << browse(null,"window=playerpoll")
return TRUE
/**
* Processes vote form data and saves results to the database for a multiple choice type poll.
*
*/
/mob/dead/new_player/proc/vote_on_multi_poll(pollid, optionid)
if(!SSdbcore.Connect())
to_chat(src, "
Failed to establish database connection.")
return
if(!vote_rig_check())
return
if(IsAdminAdvancedProcCall())
return
//validate the poll
if(!vote_valid_check(pollid, client.holder, POLLTYPE_MULTI))
return
if(!pollid || !optionid)
return
// if(length(href_list) > 2)
// href_list.Cut(1,3) //first two values aren't options
// else
// to_chat(src, "
No options were selected.")
var/special_columns = list(
"datetime" = "NOW()",
"ip" = "INET_ATON(?)",
)
var/sql_votes = list()
// var/vote_count = 0
// for(var/h in href_list)
// if(vote_count == poll.options_allowed)
// to_chat(src, "
Allowed option count exceeded, only the first [poll.options_allowed] selected options have been saved.")
// break
// vote_count++
// var/datum/poll_option/option = locate(h) in poll.options
var/admin_rank = "Player"
if(!QDELETED(client) && client?.holder)
admin_rank = client.holder.rank.name
sql_votes += list(list(
"pollid" = pollid,
"optionid" = optionid,
"ckey" = ckey,
"ip" = client.address,
"adminrank" = admin_rank
))
/*with revoting and poll editing possible there can be an edge case where a poll is changed to allow less multiple choice options than a user has already voted on
rather than trying to calculate which options should be updated and which deleted, we just delete all of a user's votes and re-insert as needed*/
var/datum/db_query/query_delete_multi_votes = SSdbcore.NewQuery({"
UPDATE [format_table_name("poll_vote")] SET deleted = 1 WHERE pollid = :pollid AND ckey = :ckey
"}, list("pollid" = pollid, "ckey" = ckey))
if(!query_delete_multi_votes.warn_execute())
qdel(query_delete_multi_votes)
return
qdel(query_delete_multi_votes)
SSdbcore.MassInsert(format_table_name("poll_vote"), sql_votes, special_columns = special_columns)
return TRUE