extends Resource class_name MajorityJudgmentPoll """ A poll with multiple candidates, where each participant gives a single grade to each of the candidates. The candidates are then sorted by their median grade. https://en.wikipedia.org/wiki/Majority_Judgment The constitutive details of the poll are up to you, of course, the poll can be imperative or informative. """ const NOT_OPENED := -1 const NOT_CLOSED := -1 # Minimum length: 4 unicode characters (? TBD) # Maximum length: 256 unicode characters (? TBD) export(String) var title:String setget set_title, get_title # > How do we localize this? # Something like this, perhaps? # title_of_locale = { # 'en_US': "President of the United States of America in 2020", # 'fr_FR': "Président des États-Unis d'Amérique en 2020", # … # } #export(Dictionary) var localized_titles:Dictionary # or perhaps # https://docs.godotengine.org/en/stable/tutorials/i18n/internationalizing_games.html export(Resource) var grading #:MajorityJudgmentGrading # Array of MajorityJudgmentCandidate export(Array, Resource) var candidates:Array setget set_candidates, get_candidates # Array of MajorityJudgmentJudgments export(Array, Resource) var judgments:Array setget set_judgments, get_judgments # Seconds since UNIX EPOCH (01-01-1970) export var opened_at:int = NOT_OPENED export var closed_at:int = NOT_CLOSED # Don't pass parameters in _init(). # ResourceLoader.load() won't like it. func _init(): pass # Instead, use a factory approach. static func make(__title, __grading, __candidates): var poll = load("res://addons/majority_judgment/MajorityJudgmentPoll.gd").new() poll.set_title(__title) poll.set_grading(__grading) poll.set_candidates(__candidates) return poll func set_title(__title:String) -> void: title = __title func get_title() -> String: if null == title: return '' return title func set_grading(__grading:MajorityJudgmentGrading) -> void: grading = __grading func get_grading() -> MajorityJudgmentGrading: assert(grading, "Poll has no grading.") return grading func set_candidates(__candidates:Array) -> void: assert(__candidates, "Poll requires at least one candidate.") candidates = __candidates func add_candidate(candidate:MajorityJudgmentCandidate) -> void: if not candidates: candidates = Array() candidates.append(candidate) func get_candidates() -> Array: assert(candidates, "Poll has no candidates.") return candidates func count_candidates() -> int: if not candidates: return 0 return candidates.size() func has_judgments() -> bool: if not judgments: return false return 0 < judgments.size() func set_judgments(__judgments:Array) -> void: judgments = __judgments func add_judgment(judgment:MajorityJudgmentJudgment) -> void: if not judgments: judgments = Array() for i in range(judgments.size()): var existing_judgment = judgments[i] if ( (existing_judgment.participant == judgment.participant) and (existing_judgment.candidate == judgment.candidate) ): judgments[i] = judgment return judgments.append(judgment) func get_judgments() -> Array: # assert(judgments, "Poll has no judgments.") return judgments func is_open() -> bool: var now = App.get_now() return ( (NOT_OPENED != opened_at and opened_at <= now) and (NOT_CLOSED == closed_at or closed_at >= now) ) func is_closed() -> bool: return not is_open() func open() -> void: assert(NOT_OPENED == opened_at, "Cannot open() an already opened poll.") opened_at = App.get_now() func tally() -> MajorityJudgmentPollTally: if not has_judgments(): return null # Pick relevant tallier from settings later on var tallier = MajorityJudgmentEasyTallier.new() # var tallier = MajorityJudgmentLiquidTallier.new() return tallier.tally(self) func get_participants() -> Array: var participants := Array() for judgment in judgments: var participant : MajorityJudgmentParticipant = judgment.participant if not participants.has(participant): participants.append(participant) return participants func count_participants() -> int: return get_participants().size() func get_dummy_merit_profile(candidate): var merit = MajorityJudgmentCandidateMeritProfile.new() merit.grades = Array() for i in range(get_grading().grades.size()): merit.grades.append(1) merit.colors = get_grading().get_colors() return merit