You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
5.9 KiB

extends Control
# A scene displaying the poll results as linear merit profiles.
# This scene is updated dynamically as the poll receives new judgments.
const MeritProfileScene = preload("res://addons/majority_judgment/nodes/MajorityJudgmentMeritProfileControl.tscn")
export(Resource) var poll setget set_poll, get_poll
export(int) var vertical_gap := 4 # pixels
export(int) var candidates_labels_width := 200 # pixels
onready var ProfilesContainer = find_node("ProfilesContainer", true)
var providers:Array # of MajorityJudgmentAbstractJudgmentsProvider
#var provider:MajorityJudgmentAbstractJudgmentsProvider
func _input(_event):
if Input.is_action_just_pressed("ui_cancel"):
exit_poll()
func exit_poll():
# Check if we want to save or discard?
# …
# Close things up
# stop_providers()
App.go_to_main_menu()
func get_poll() -> MajorityJudgmentPoll:
return poll
func set_poll(__poll:MajorityJudgmentPoll):
poll = __poll
craft_nodes()
update_nodes()
self.providers = App.get_providers()
for provider in self.providers:
start_provider(provider)
# var provider = MajorityJudgmentDemoProvider.new()
# var provider = MajorityJudgmentTwitchChatProvider.new()
# start_provider(provider)
var candidates_lines_nodes := Array()
var profiles_nodes := Array()
func craft_nodes():
var tally : MajorityJudgmentPollTally = get_poll().tally()
var candidate_index = 0 # as they were initially written, before the sort
for candidate in get_poll().get_candidates():
var profile = create_merit_profile_scene(6)
if tally:
profile.refresh(tally.get_tally_of_candidate(candidate).merit_profile)
var height = profile.compute_height()
profile.rect_min_size = Vector2(400, height)
var container = self.ProfilesContainer
var wrapper = HBoxContainer.new()
wrapper.name = "Candidate%sLine" % char(candidate_index+65)
wrapper.anchor_right = 1.0
# wrapper.rect_min_size = Vector2(400, height)
var position = candidate_index
if tally:
position = tally.get_position_of_candidate(candidate, true)
wrapper.margin_top = position * (height + vertical_gap)
wrapper.margin_bottom = wrapper.margin_top + height
self.candidates_lines_nodes.append(wrapper)
var candidate_label = Label.new()
candidate_label.name = "CandidateLabel"
candidate_label.text = candidate.get_name()
candidate_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
# candidate_label.size_flags_vertical = Control.SIZE_EXPAND_FILL
candidate_label.rect_min_size = Vector2(candidates_labels_width, height)
candidate_label.rect_size = Vector2(candidates_labels_width, height)
candidate_label.clip_text = true
candidate_label.autowrap = true
candidate_label.valign = Label.VALIGN_CENTER
candidate_label.align = Label.ALIGN_RIGHT
wrapper.add_child(candidate_label)
wrapper.add_child(profile)
container.add_child(wrapper)
# wrapper.margin_top = position * height
# wrapper.margin_bottom = wrapper.margin_top + height
# separator.owner = self
candidate_label.owner = self
profile.owner = self
wrapper.owner = self
self.profiles_nodes.append(profile)
candidate_index += 1
# perhaps update_scene()?
func update_nodes():
$Tween.remove_all()
var tally : MajorityJudgmentPollTally = get_poll().tally()
var candidate_index = 0 # as they were initially written, before the sort
for candidate in get_poll().get_candidates():
var profile = profiles_nodes[candidate_index]
var candidate_line_node = self.candidates_lines_nodes[candidate_index]
var position = candidate_index
var height = profile.compute_height()
if tally:
position = tally.get_position_of_candidate(candidate, true)
var tween_transition = Tween.TRANS_SINE
var tween_ease = Tween.EASE_IN_OUT
var tween_duration = 0.818
var tween_delay = 0
var cln_margin_top = position * (height + vertical_gap)
$Tween.interpolate_property(
candidate_line_node,
"margin_top",
candidate_line_node.margin_top,
cln_margin_top,
tween_duration,
tween_transition,
tween_ease,
tween_delay
)
$Tween.interpolate_property(
candidate_line_node,
"margin_bottom",
candidate_line_node.margin_bottom,
cln_margin_top + height,
tween_duration,
tween_transition,
tween_ease,
tween_delay
)
$Tween.start()
# candidate_line_node.margin_top = position * (height + vertical_gap)
# candidate_line_node.margin_bottom = wrapper.margin_top + height
if tally:
var merit = tally.get_tally_of_candidate(candidate).merit_profile
profile.refresh(merit)
else:
var merit = poll.get_dummy_merit_profile(candidate)
profile.refresh(merit)
candidate_index += 1
func create_merit_profile_scene(gradation_size:int):
var mps = MeritProfileScene.instance()
mps.set_poll(get_poll())
mps.craft_nodes(gradation_size)
return mps
func start_provider(__provider):
# self.provider = __provider
var connected = __provider.connect(
"judgment_emitted",
self, "__on_judgment_emitted"
)
__provider.start_providing()
var known_participants := Dictionary() # id => Participant
func get_or_create_participant(identifier:String) -> MajorityJudgmentParticipant:
if not known_participants.has(identifier):
known_participants[identifier] = MajorityJudgmentParticipant.make(identifier)
return known_participants[identifier]
func __on_judgment_emitted(author_identifier, grade_index, candidate_index):
# Data comes from userland, best be careful here
if (
grade_index < 0
or
grade_index >= poll.grading.grades.size()
):
# printerr("Ignoring grade #%d since it's out of range.")
return
if (
candidate_index < 0
or
candidate_index >= poll.candidates.size()
):
# printerr("Ignoring candidate %s since it's out of range." % [char(candidate_index)])
return
var j = MajorityJudgmentJudgment.new()
j.set_participant(get_or_create_participant(author_identifier))
j.set_grade(poll.grading.grades[grade_index])
j.set_candidate(poll.candidates[candidate_index])
poll.add_judgment(j)
update_nodes()