/datum/polloption var/optionid var/optiontext /mob/dead/new_player/proc/handle_player_polling() if(!SSdbcore.IsConnected()) to_chat(usr, "Failed to establish database connection.") return var/datum/DBQuery/query_poll_get = SSdbcore.NewQuery("SELECT id, question FROM [format_table_name("poll_question")] WHERE Now() BETWEEN starttime AND endtime [(client.holder ? "" : "AND adminonly = false")]") if(!query_poll_get.warn_execute()) return var/output = "
Player polls
" var/i = 0 while(query_poll_get.NextRow()) var/pollid = query_poll_get.item[1] var/pollquestion = query_poll_get.item[2] output += "" i++ output += "
[pollquestion]
" src << browse(output,"window=playerpolllist;size=500x300") /mob/dead/new_player/proc/poll_player(pollid) if(!pollid) return if (!SSdbcore.Connect()) to_chat(usr, "Failed to establish database connection.") return var/datum/DBQuery/query_poll_get_details = SSdbcore.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM [format_table_name("poll_question")] WHERE id = [pollid]") if(!query_poll_get_details.warn_execute()) return var/pollstarttime = "" var/pollendtime = "" var/pollquestion = "" var/polltype = "" var/multiplechoiceoptions = 0 if(query_poll_get_details.NextRow()) pollstarttime = query_poll_get_details.item[1] pollendtime = query_poll_get_details.item[2] pollquestion = query_poll_get_details.item[3] polltype = query_poll_get_details.item[4] multiplechoiceoptions = text2num(query_poll_get_details.item[5]) switch(polltype) if(POLLTYPE_OPTION) var/datum/DBQuery/query_option_get_votes = SSdbcore.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'") if(!query_option_get_votes.warn_execute()) return var/votedoptionid = 0 if(query_option_get_votes.NextRow()) votedoptionid = text2num(query_option_get_votes.item[1]) var/list/datum/polloption/options = list() var/datum/DBQuery/query_option_options = SSdbcore.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]") if(!query_option_options.warn_execute()) return while(query_option_options.NextRow()) var/datum/polloption/PO = new() PO.optionid = text2num(query_option_options.item[1]) PO.optiontext = query_option_options.item[2] options += PO var/output = "
Player poll
" output += "Question: [pollquestion]
" output += "Poll runs from [pollstarttime] until [pollendtime]

" if(!votedoptionid) output += "

" output += "" output += "" output += "" output += "
" for(var/datum/polloption/O in options) if(O.optionid && O.optiontext) if(votedoptionid) if(votedoptionid == O.optionid) output += "[O.optiontext]
" else output += "[O.optiontext]
" else output += "[O.optiontext]
" output += "
" if(!votedoptionid) output += "

" output += "

" output += "
" src << browse(null ,"window=playerpolllist") src << browse(output,"window=playerpoll;size=500x250") if(POLLTYPE_TEXT) var/datum/DBQuery/query_text_get_votes = SSdbcore.NewQuery("SELECT replytext FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] AND ckey = '[ckey]'") if(!query_text_get_votes.warn_execute()) return var/vote_text = "" if(query_text_get_votes.NextRow()) vote_text = query_text_get_votes.item[1] var/output = "
Player poll
" output += "Question: [pollquestion]
" output += "Feedback gathering runs from [pollstarttime] until [pollendtime]

" if(!vote_text) output += "

" output += "" output += "" output += "" output += "Please provide feedback below. You can use any letters of the English alphabet, numbers and the symbols: . , ! ? : ; -
" output += "" output += "

" output += "
" output += "" output += "" output += "" output += "" output += "
" else vote_text = replacetext(vote_text, "\n", "
") output += "[vote_text]" src << browse(null ,"window=playerpolllist") src << browse(output,"window=playerpoll;size=500x500") if(POLLTYPE_RATING) var/datum/DBQuery/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 = [pollid] AND v.ckey = '[ckey]' AND o.id = v.optionid") if(!query_rating_get_votes.warn_execute()) 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]" if(!rating) output += "

" output += "" output += "" output += "" var/minid = 999999 var/maxid = 0 var/datum/DBQuery/query_rating_options = SSdbcore.NewQuery("SELECT id, text, minval, maxval, descmin, descmid, descmax FROM [format_table_name("poll_option")] WHERE pollid = [pollid]") if(!query_rating_options.warn_execute()) return while(query_rating_options.NextRow()) var/optionid = text2num(query_rating_options.item[1]) var/optiontext = query_rating_options.item[2] var/minvalue = text2num(query_rating_options.item[3]) var/maxvalue = text2num(query_rating_options.item[4]) var/descmin = query_rating_options.item[5] var/descmid = query_rating_options.item[6] var/descmax = query_rating_options.item[7] if(optionid < minid) minid = optionid if(optionid > maxid) maxid = optionid var/midvalue = round( (maxvalue + minvalue) / 2) output += "
[optiontext]: " output += "" output += "" output += "

" src << browse(null ,"window=playerpolllist") src << browse(output,"window=playerpoll;size=500x500") if(POLLTYPE_MULTI) var/datum/DBQuery/query_multi_get_votes = SSdbcore.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'") if(!query_multi_get_votes.warn_execute()) return var/list/votedfor = list() while(query_multi_get_votes.NextRow()) votedfor.Add(text2num(query_multi_get_votes.item[1])) var/list/datum/polloption/options = list() var/maxoptionid = 0 var/minoptionid = 0 var/datum/DBQuery/query_multi_options = SSdbcore.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]") if(!query_multi_options.warn_execute()) 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 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 += "" output += "" output += "" output += "" output += "" output += "
" for(var/datum/polloption/O in options) if(O.optionid && O.optiontext) if(votedfor.len) if(O.optionid in votedfor) output += "[O.optiontext]
" else output += "[O.optiontext]
" else output += "[O.optiontext]
" output += "
" 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/simple/IRV) irv_assets.send(src) var/datum/DBQuery/query_irv_get_votes = SSdbcore.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'") if(!query_irv_get_votes.warn_execute()) return var/list/votedfor = list() while(query_irv_get_votes.NextRow()) votedfor.Add(text2num(query_irv_get_votes.item[1])) var/list/datum/polloption/options = list() var/datum/DBQuery/query_irv_options = SSdbcore.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]") if(!query_irv_options.warn_execute()) 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 //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]

Most Preferred
    "} for(var/O in options) var/datum/polloption/PO = options["[O]"] if(PO.optionid && PO.optiontext) output += "
  1. [PO.optiontext]
  2. \n" output += {"
Least Preferred

"} src << browse(null ,"window=playerpolllist") src << browse(output,"window=playerpoll;size=500x500") return /mob/dead/new_player/proc/poll_check_voted(pollid, text = FALSE) var/table = "poll_vote" if (text) table = "poll_textreply" if (!SSdbcore.Connect()) to_chat(usr, "Failed to establish database connection.") return var/datum/DBQuery/query_hasvoted = SSdbcore.NewQuery("SELECT id FROM `[format_table_name(table)]` WHERE pollid = [pollid] AND ckey = '[ckey]'") if(!query_hasvoted.warn_execute()) return if(query_hasvoted.NextRow()) to_chat(usr, "You've already replied to this poll.") return . = "Player" if(client.holder) . = client.holder.rank.name return . /mob/dead/new_player/proc/vote_rig_check() if (usr != src) if (!usr || !src) return 0 //we gots ourselfs a dirty cheater on our hands! log_game("[key_name(usr)] attempted to rig the vote by voting as [ckey]") message_admins("[key_name_admin(usr)] attempted to rig the vote by voting as [ckey]") to_chat(usr, "You don't seem to be [ckey].") to_chat(src, "Something went horribly wrong processing your vote. Please contact an administrator, they should have gotten a message about this") return 0 return 1 /mob/dead/new_player/proc/vote_valid_check(pollid, holder, type) if (!SSdbcore.Connect()) to_chat(src, "Failed to establish database connection.") return 0 pollid = text2num(pollid) if (!pollid || pollid < 0) return 0 //validate the poll is actually the right type of poll and its still active var/datum/DBQuery/query_validate_poll = SSdbcore.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime AND polltype = '[type]' [(holder ? "" : "AND adminonly = false")]") if(!query_validate_poll.warn_execute()) return 0 if (!query_validate_poll.NextRow()) return 0 return 1 /mob/dead/new_player/proc/vote_on_irv_poll(pollid, list/votelist) if (!SSdbcore.Connect()) to_chat(src, "Failed to establish database connection.") return 0 if (!vote_rig_check()) return 0 pollid = text2num(pollid) if (!pollid || pollid < 0) return 0 if (!votelist || !istype(votelist) || !votelist.len) return 0 if (!client) return 0 //save these now so we can still process the vote if the client goes away while we process. var/datum/admins/holder = client.holder var/rank = "Player" if (holder) rank = holder.rank.name var/ckey = client.ckey var/address = client.address //validate the poll if (!vote_valid_check(pollid, holder, POLLTYPE_IRV)) return 0 //lets collect the options var/datum/DBQuery/query_irv_id = SSdbcore.NewQuery("SELECT id FROM [format_table_name("poll_option")] WHERE pollid = [pollid]") if(!query_irv_id.warn_execute()) return 0 var/list/optionlist = list() while (query_irv_id.NextRow()) optionlist += text2num(query_irv_id.item[1]) //validate their votes are actually in the list of options and actually numbers var/list/numberedvotelist = list() for (var/vote in votelist) vote = text2num(vote) numberedvotelist += vote if (!vote) //this is fine because voteid starts at 1, so it will never be 0 to_chat(src, "Error: Invalid (non-numeric) votes in the vote data.") return 0 if (!(vote in optionlist)) to_chat(src, "Votes for choices that do not appear to be in the poll detected.") return 0 if (!numberedvotelist.len) to_chat(src, "Invalid vote data") return 0 //lets add the vote, first we generate an insert statement. var/sqlrowlist = "" for (var/vote in numberedvotelist) if (sqlrowlist != "") sqlrowlist += ", " //a comma (,) at the start of the first row to insert will trigger a SQL error sqlrowlist += "(Now(), [pollid], [vote], '[sanitizeSQL(ckey)]', INET_ATON('[sanitizeSQL(address)]'), '[sanitizeSQL(rank)]')" //now lets delete their old votes (if any) var/datum/DBQuery/query_irv_del_old = SSdbcore.NewQuery("DELETE FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'") if(!query_irv_del_old.warn_execute()) return 0 //now to add the new ones. var/datum/DBQuery/query_irv_vote = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank) VALUES [sqlrowlist]") if(!query_irv_vote.warn_execute()) return 0 src << browse(null,"window=playerpoll") return 1 /mob/dead/new_player/proc/vote_on_poll(pollid, optionid) if (!SSdbcore.Connect()) to_chat(src, "Failed to establish database connection.") return 0 if (!vote_rig_check()) return 0 if(!pollid || !optionid) return //validate the poll if (!vote_valid_check(pollid, client.holder, POLLTYPE_OPTION)) return 0 var/adminrank = sanitizeSQL(poll_check_voted(pollid)) if(!adminrank) return var/datum/DBQuery/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('[client.address]'), '[adminrank]')") if(!query_option_vote.warn_execute()) return usr << browse(null,"window=playerpoll") return 1 /mob/dead/new_player/proc/log_text_poll_reply(pollid, replytext) if (!SSdbcore.Connect()) to_chat(src, "Failed to establish database connection.") return 0 if (!vote_rig_check()) return 0 if(!pollid) return //validate the poll if (!vote_valid_check(pollid, client.holder, POLLTYPE_TEXT)) return 0 if(!replytext) to_chat(usr, "The text you entered was blank. Please correct the text and submit again.") return var/adminrank = sanitizeSQL(poll_check_voted(pollid, TRUE)) if(!adminrank) return replytext = sanitizeSQL(replytext) 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/DBQuery/query_text_vote = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_textreply")] (datetime ,pollid ,ckey ,ip ,replytext ,adminrank) VALUES (Now(), [pollid], '[ckey]', INET_ATON('[client.address]'), '[replytext]', '[adminrank]')") if(!query_text_vote.warn_execute()) return usr << browse(null,"window=playerpoll") return 1 /mob/dead/new_player/proc/vote_on_numval_poll(pollid, optionid, rating) if (!SSdbcore.Connect()) to_chat(src, "Failed to establish database connection.") return 0 if (!vote_rig_check()) return 0 if(!pollid || !optionid || !rating) return //validate the poll if (!vote_valid_check(pollid, client.holder, POLLTYPE_RATING)) return 0 var/datum/DBQuery/query_numval_hasvoted = SSdbcore.NewQuery("SELECT id FROM [format_table_name("poll_vote")] WHERE optionid = [optionid] AND ckey = '[ckey]'") if(!query_numval_hasvoted.warn_execute()) return if(query_numval_hasvoted.NextRow()) to_chat(usr, "You've already replied to this poll.") return var/adminrank = "Player" if(client.holder) adminrank = client.holder.rank.name adminrank = sanitizeSQL(adminrank) var/datum/DBQuery/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('[client.address]'), '[adminrank]', [(isnull(rating)) ? "null" : rating])") if(!query_numval_vote.warn_execute()) return usr << browse(null,"window=playerpoll") return 1 /mob/dead/new_player/proc/vote_on_multi_poll(pollid, optionid) if (!SSdbcore.Connect()) to_chat(src, "Failed to establish database connection.") return 0 if (!vote_rig_check()) return 0 if(!pollid || !optionid) return 1 //validate the poll if (!vote_valid_check(pollid, client.holder, POLLTYPE_MULTI)) return 0 var/datum/DBQuery/query_multi_choicelen = SSdbcore.NewQuery("SELECT multiplechoiceoptions FROM [format_table_name("poll_question")] WHERE id = [pollid]") if(!query_multi_choicelen.warn_execute()) return 1 var/i if(query_multi_choicelen.NextRow()) i = text2num(query_multi_choicelen.item[1]) var/datum/DBQuery/query_multi_hasvoted = SSdbcore.NewQuery("SELECT id FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'") if(!query_multi_hasvoted.warn_execute()) return 1 while(i) if(query_multi_hasvoted.NextRow()) i-- else break if(!i) return 2 var/adminrank = "Player" if(client.holder) adminrank = client.holder.rank.name adminrank = sanitizeSQL(adminrank) var/datum/DBQuery/query_multi_vote = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank) VALUES (Now(), [pollid], [optionid], '[ckey]', INET_ATON('[client.address]'), '[adminrank]')") if(!query_multi_vote.warn_execute()) return 1 usr << browse(null,"window=playerpoll") return 0