From a67902ee32a885d84f20f36aeadfabcf9d7c78eb Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 4 Feb 2020 12:43:59 -0800 Subject: [PATCH] Also added instant runoff and renamed schulze. yak shaving --- code/__DEFINES/vote.dm | 3 ++- code/controllers/subsystem/vote.dm | 40 +++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/code/__DEFINES/vote.dm b/code/__DEFINES/vote.dm index 6553447029..b83ea7b8f6 100644 --- a/code/__DEFINES/vote.dm +++ b/code/__DEFINES/vote.dm @@ -1,7 +1,8 @@ #define PLURALITY_VOTING 0 #define APPROVAL_VOTING 1 -#define RANKED_CHOICE_VOTING 2 +#define SCHULZE_VOTING 2 #define SCORE_VOTING 3 #define MAJORITY_JUDGEMENT_VOTING 4 +#define INSTANT_RUNOFF_VOTING 5 GLOBAL_LIST_INIT(vote_score_options,list("Bad","Poor","Acceptable","Good","Great")) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 49f1f3f851..2a7c4401f3 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -204,6 +204,28 @@ SUBSYSTEM_DEF(vote) scores[score_name] = (scores[score_name]-min_score)/(max_score-min_score) SSblackbox.record_feedback("nested tally","voting",scores[score_name],list(blackbox_text,"Total scores",score_name)) +/datum/controller/subsystem/vote/proc/get_runoff_results(var/blackbox_text) + var/already_lost_runoff = list() + var/list/cur_choices = choices.Copy() + for(var/ckey in voted) + choices[choices[voted[ckey][1]]]++ // jesus christ how horrifying + for(var/_this_var_unused_ignore_it in 1 to choices.len) // if it takes more than this something REALLY wrong happened + for(var/ckey in voted) + cur_choices[cur_choices[voted[ckey][1]]]++ // jesus christ how horrifying + var/least_vote = 100000 + var/least_voted + for(var/i in 1 to cur_choices.len) + var/option = cur_choices[i] + if(cur_choices[option] > voted.len/2) + return list(option) + else if(cur_choices[option] < least_vote && !(option in already_lost_runoff)) + least_vote = cur_choices[option] + least_voted = i + already_lost_runoff += cur_choices[least_voted] + for(var/ckey in voted) + voted[ckey] -= least_voted + for(var/option in cur_choices) + cur_choices[option] = 0 /datum/controller/subsystem/vote/proc/announce_result() var/vote_title_text @@ -214,19 +236,19 @@ SUBSYSTEM_DEF(vote) else text += "[capitalize(mode)] Vote" vote_title_text = "[capitalize(mode)] Vote" - if(vote_system == RANKED_CHOICE_VOTING) + if(vote_system == SCHULZE_VOTING) calculate_condorcet_votes(vote_title_text) if(vote_system == SCORE_VOTING) calculate_scores(vote_title_text) if(vote_system == MAJORITY_JUDGEMENT_VOTING) calculate_majority_judgement_vote(vote_title_text) // nothing uses this at the moment - var/list/winners = get_result() + var/list/winners = vote_system == INSTANT_RUNOFF_VOTING ? get_runoff_results() : get_result() var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic" if(winners.len > 0) if(was_roundtype_vote) stored_gamemode_votes = list() if(!obfuscated) - if(vote_system == RANKED_CHOICE_VOTING) + if(vote_system == SCHULZE_VOTING) text += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!" if(vote_system == MAJORITY_JUDGEMENT_VOTING) text += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!" @@ -265,7 +287,7 @@ SUBSYSTEM_DEF(vote) if(APPROVAL_VOTING,PLURALITY_VOTING) for(var/i=1,i<=choices.len,i++) SSblackbox.record_feedback("nested tally","voting",choices[choices[i]],list(vote_title_text,choices[i])) - if(RANKED_CHOICE_VOTING) + if(SCHULZE_VOTING,INSTANT_RUNOFF_VOTING) for(var/i=1,i<=voted.len,i++) var/list/myvote = voted[voted[i]] if(islist(myvote)) @@ -274,7 +296,7 @@ SUBSYSTEM_DEF(vote) if(obfuscated) //CIT CHANGE - adds obfuscated votes. this messages admins with the vote's true results var/admintext = "Obfuscated results" if(vote_system != SCORE_VOTING) - if(vote_system == RANKED_CHOICE_VOTING) + if(vote_system == SCHULZE_VOTING) admintext += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!" else if(vote_system == MAJORITY_JUDGEMENT_VOTING) admintext += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!" @@ -385,7 +407,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = list(vote) choices[choices[vote]]++ return vote - if(RANKED_CHOICE_VOTING) + if(SCHULZE_VOTING,INSTANT_RUNOFF_VOTING) if(usr.ckey in voted) if(vote in voted[usr.ckey]) voted[usr.ckey] -= vote @@ -394,7 +416,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = list() voted[usr.ckey] += vote saved -= usr.ckey - if(SCORE_VOTING) + if(SCORE_VOTING,MAJORITY_JUDGEMENT_VOTING) if(!(usr.ckey in voted)) voted += usr.ckey voted[usr.ckey] = list() @@ -519,7 +541,7 @@ SUBSYSTEM_DEF(vote) . += "

Vote one.

" if(APPROVAL_VOTING) . += "

Vote any number of choices.

" - if(RANKED_CHOICE_VOTING) + if(SCHULZE_VOTING,INSTANT_RUNOFF_VOTING) . += "

Vote by order of preference. Revoting will demote to the bottom. 1 is your favorite, and higher numbers are worse.

" if(SCORE_VOTING,MAJORITY_JUDGEMENT_VOTING) . += "

Grade the candidates by how much you like them.

" @@ -541,7 +563,7 @@ SUBSYSTEM_DEF(vote) if(choice_descs.len >= i) . += "
  • [choice_descs[i]]
  • " . += "
    " - if(RANKED_CHOICE_VOTING) + if(SCHULZE_VOTING,INSTANT_RUNOFF_VOTING) var/list/myvote = voted[C.ckey] for(var/i=1,i<=choices.len,i++) var/vote = (islist(myvote) ? (myvote.Find(i)) : 0)