def add_debates(self, round_tag, motion, debate): debate_tag = SubElement(round_tag, 'debate', { 'id': DEBATE_PREFIX + str(debate.id), }) # Add list of motions as attribute adjs = " ".join([ADJ_PREFIX + str(d_adj.adjudicator_id) for d_adj in debate.debateadjudicator_set.all()]) if adjs != "": debate_tag.set('adjudicators', adjs) chair = debate.debateadjudicator_set.get(type=DebateAdjudicator.TYPE_CHAIR).adjudicator_id debate_tag.set('chair', ADJ_PREFIX + str(chair)) # Venue if debate.venue_id is not None: debate_tag.set('venue', VENUE_PREFIX + str(debate.venue_id)) # Motion is optional if self.t.pref('enable_motions') and debate.confirmed_ballot is not None: motion = debate.confirmed_ballot.motion if motion is not None: debate_tag.set('motion', MOTION_PREFIX + str(motion.id)) if debate.confirmed_ballot is not None: result = DebateResult(debate.confirmed_ballot, tournament=self.t) for side in self.t.sides: side_tag = SubElement(debate_tag, 'side', { 'team': TEAM_PREFIX + str(debate.get_team(side).id), }) dt = debate.get_dt(side) if dt.debateteammotionpreference_set.exists(): side_tag.set('motion-veto', MOTION_PREFIX + str(dt.debateteammotionpreference_set.first().motion_id)) if result.is_voting: for (adj, scoresheet) in result.scoresheets.items(): self.add_team_ballots(side_tag, result, adj, scoresheet, side) elif not result.uses_speakers: adv = side in result.get_winner() ballot_tag = SubElement(side_tag, 'ballot', { 'adjudicators': adjs, 'rank': str(1 if adv else 2), 'ignored': 'false', }) ballot_tag.text = str(adv) else: self.add_team_ballots( side_tag, result, adjs, result.scoresheet, side, ) if result.uses_speakers: self.add_speakers(side_tag, debate, result, side)
def create(self, validated_data): result = DebateResult(validated_data['ballot'], tournament=self.context.get('tournament')) sheets = self.SheetSerializer(context=self.context) for sheet in validated_data['sheets']: sheets._validated_data = sheet sheets.save(result=result) result.save() return result
def serialize_like_actionlog(self): if hasattr(self, '_result'): dr = self._result else: from results.result import DebateResult dr = DebateResult(self) result_winner, result = readable_ballotsub_result(dr) return { 'user': result_winner, 'id': self.id, 'type': result, 'param': '', 'timestamp': badge_datetime_format(self.timestamp), 'confirmed': self.confirmed, 'debate': self.debate.id, 'result_status': self.debate.result_status, }
def ballots_email_generator(to, debate): # "to" is unused emails = [] tournament = debate.round.tournament results = DebateResult(debate.confirmed_ballot) round_name = _("%(tournament)s %(round)s @ %(room)s") % { 'tournament': str(tournament), 'round': debate.round.name, 'room': debate.venue.name } use_codes = use_team_code_names(tournament, False) def _create_ballot(result, scoresheet): ballot = "<ul>" for side, (side_name, pos_names) in zip(tournament.sides, side_and_position_names(tournament)): side_string = "" if tournament.pref('teams_in_debate') == 'bp': side_string += _( "<li>%(side)s: %(team)s (%(points)d points with %(speaks)s total speaks)" ) points = 4 - scoresheet.rank(side) else: side_string += _( "<li>%(side)s: %(team)s (%(points)s - %(speaks)s total speaks)" ) points = _("Win") if side in scoresheet.winners() else _( "Loss") ballot += side_string % { 'side': side_name, 'team': result.debateteams[side].team.code_name if use_codes else result.debateteams[side].team.short_name, 'speaks': formats.localize(scoresheet.get_total(side)), 'points': points, } ballot += "<ul>" for pos, pos_name in zip(tournament.positions, pos_names): ballot += _("<li>%(pos)s: %(speaker)s (%(score)s)</li>") % { 'pos': pos_name, 'speaker': result.get_speaker(side, pos).name, 'score': formats.localize(scoresheet.get_score(side, pos)), } ballot += "</ul></li>" ballot += "</ul>" return mark_safe(ballot) if isinstance(results, DebateResultByAdjudicatorWithScores): for adj, ballot in results.scoresheets.items(): if adj.email is None: # As "to" is None, must check if eligible email continue context = { 'DEBATE': round_name, 'USER': adj.name, 'SCORES': _create_ballot(results, ballot) } emails.append((context, adj)) elif isinstance(results, ConsensusDebateResultWithScores): context = { 'DEBATE': round_name, 'SCORES': _create_ballot(results, results.scoresheet) } for adj in debate.debateadjudicator_set.all().select_related( 'adjudicator'): if adj.adjudicator.email is None: continue context_user = context.copy() context_user['USER'] = adj.adjudicator.name emails.append((context_user, adj.adjudicator)) return emails
def add_result(debate, submitter_type, user, discarded=False, confirmed=False, reply_random=False): """Adds a ballot set to a debate. ``debate`` is the Debate to which the ballot set should be added. ``submitter_type`` is a valid value of BallotSubmission.submitter_type. ``user`` is a User object. ``discarded`` and ``confirmed`` are whether the feedback should be discarded or confirmed, respectively. ``min_score`` and ``max_score`` are the range in which scores should be generated.""" if discarded and confirmed: raise ValueError("Ballot can't be both discarded and confirmed!") t = debate.round.tournament if not debate.sides_confirmed: debate.sides_confirmed = True debate.save() # Create a new BallotSubmission bsub = BallotSubmission(submitter_type=submitter_type, debate=debate) if submitter_type == BallotSubmission.SUBMITTER_TABROOM: bsub.submitter = user bsub.save() # Create relevant scores result = DebateResult(bsub) if result.uses_speakers: for side in t.sides: speakers = list(debate.get_team(side).speakers) # fix order for i in range(1, t.last_substantive_position + 1): result.set_speaker(side, i, speakers[i - 1]) result.set_ghost(side, i, False) if t.reply_position is not None: reply_speaker = random.randint(0, t.last_substantive_position - 2) if reply_random else 0 result.set_speaker(side, t.reply_position, speakers[reply_speaker]) result.set_ghost(side, t.reply_position, False) if result.is_voting: for scoresheet in result.scoresheets.values(): fill_scoresheet_randomly(scoresheet, t) elif result.uses_advancing: result.set_advancing(random.sample(t.sides, 2)) else: fill_scoresheet_randomly(result.scoresheet, t) assert result.is_valid() result.save() # Pick a motion motions = debate.round.motion_set.all() if motions: num_motions = 3 if motions.count() > 3 else motions.count() sample = random.sample(list(motions), k=num_motions) motion = sample[0] bsub.motion = motion if t.pref('motion_vetoes_enabled') and len(sample) == len(t.sides) + 1: for i, side in enumerate(t.sides, 1): dt = debate.get_dt(side) dt.debateteammotionpreference_set.create( motion=sample[i], preference=3, ballot_submission=bsub, ) bsub.discarded = discarded bsub.confirmed = confirmed bsub.save() # Update result status (only takes into account marginal effect, does not "fix") if confirmed: debate.result_status = Debate.STATUS_CONFIRMED elif not discarded and debate.result_status != Debate.STATUS_CONFIRMED: debate.result_status = Debate.STATUS_DRAFT debate.save() if t.pref('teams_in_debate') == 'two': logger.info( "%(debate)s won by %(team)s on %(motion)s", { 'debate': debate.matchup, 'team': result.winning_side(), 'motion': bsub.motion and bsub.motion.reference or "<No motion>" }) elif t.pref('teams_in_debate') == 'bp': if result.uses_advancing: logger.info( "%(debate)s: %(advancing)s on %(motion)s", { 'debate': debate.matchup, 'advancing': ", ".join(result.advancing_sides()), 'motion': bsub.motion and bsub.motion.reference or "<No motion>" }) else: logger.info( "%(debate)s: %(ranked)s on %(motion)s", { 'debate': debate.matchup, 'ranked': ", ".join(result.scoresheet.ranked_sides()), 'motion': bsub.motion and bsub.motion.reference or "<No motion>" }) return result
def add_result(debate, submitter_type, user, discarded=False, confirmed=False, min_score=72, max_score=78, reply_random=False): """Adds a ballot set to a debate. ``debate`` is the Debate to which the ballot set should be added. ``submitter_type`` is a valid value of BallotSubmission.submitter_type. ``user`` is a User object. ``discarded`` and ``confirmed`` are whether the feedback should be discarded or confirmed, respectively. ``min_score`` and ``max_score`` are the range in which scores should be generated.""" if discarded and confirmed: raise ValueError("Ballot can't be both discarded and confirmed!") t = debate.round.tournament # Create a new BallotSubmission bsub = BallotSubmission(submitter_type=submitter_type, debate=debate) if submitter_type == BallotSubmission.SUBMITTER_TABROOM: bsub.submitter = user bsub.save() # Create relevant scores result = DebateResult(bsub) for side in t.sides: speakers = debate.get_team(side).speakers for i in range(1, t.last_substantive_position + 1): result.set_speaker(side, i, speakers[i - 1]) result.set_ghost(side, i, False) if t.reply_position is not None: reply_speaker = random.randint(0, t.last_substantive_position - 1) if reply_random else 0 result.set_speaker(side, t.reply_position, speakers[reply_speaker]) result.set_ghost(side, t.reply_position, False) if result.is_voting: for scoresheet in result.scoresheets.values(): fill_scoresheet_randomly(scoresheet, t) else: fill_scoresheet_randomly(result.scoresheet, t) result.save() # Pick a motion motions = debate.round.motion_set.all() if motions: motion = random.choice(motions) bsub.motion = motion bsub.discarded = discarded bsub.confirmed = confirmed bsub.save() # Update result status (only takes into account marginal effect, does not "fix") if confirmed: debate.result_status = Debate.STATUS_CONFIRMED elif not discarded and debate.result_status != Debate.STATUS_CONFIRMED: debate.result_status = Debate.STATUS_DRAFT debate.save() if t.pref('teams_in_debate') == 'two': logger.info( "%(debate)s won by %(team)s on %(motion)s", { 'debate': debate.matchup, 'team': result.winning_side(), 'motion': bsub.motion and bsub.motion.reference or "<No motion>" }) elif t.pref('teams_in_debate') == 'bp': logger.info( "%(debate)s: %(ranked)s on %(motion)s", { 'debate': debate.matchup, 'ranked': ", ".join(result.scoresheet.ranked_sides()), 'motion': bsub.motion and bsub.motion.reference or "<No motion>" }) return result
def result(self): if not hasattr(self, "_result"): self._result = DebateResult(self) return self._result
def add_result(debate, submitter_type, user, discarded=False, confirmed=False, min_score=72, max_score=78, reply_random=False): """Adds a ballot set to a debate. ``debate`` is the Debate to which the ballot set should be added. ``submitter_type`` is a valid value of BallotSubmission.submitter_type. ``user`` is a User object. ``discarded`` and ``confirmed`` are whether the feedback should be discarded or confirmed, respectively. ``min_score`` and ``max_score`` are the range in which scores should be generated.""" if discarded and confirmed: raise ValueError("Ballot can't be both discarded and confirmed!") t = debate.round.tournament # Create a new BallotSubmission bsub = BallotSubmission(submitter_type=submitter_type, debate=debate) if submitter_type == BallotSubmission.SUBMITTER_TABROOM: bsub.submitter = user bsub.save() # Create relevant scores result = DebateResult(bsub) for side in t.sides: speakers = list(debate.get_team(side).speakers) # fix order for i in range(1, t.last_substantive_position+1): result.set_speaker(side, i, speakers[i-1]) result.set_ghost(side, i, False) if t.reply_position is not None: reply_speaker = random.randint(0, t.last_substantive_position-1) if reply_random else 0 result.set_speaker(side, t.reply_position, speakers[reply_speaker]) result.set_ghost(side, t.reply_position, False) if result.is_voting: for scoresheet in result.scoresheets.values(): fill_scoresheet_randomly(scoresheet, t) else: fill_scoresheet_randomly(result.scoresheet, t) assert result.is_valid() result.save() # Pick a motion motions = debate.round.motion_set.all() if motions: motion = random.choice(motions) bsub.motion = motion bsub.discarded = discarded bsub.confirmed = confirmed bsub.save() # Update result status (only takes into account marginal effect, does not "fix") if confirmed: debate.result_status = Debate.STATUS_CONFIRMED elif not discarded and debate.result_status != Debate.STATUS_CONFIRMED: debate.result_status = Debate.STATUS_DRAFT debate.save() if t.pref('teams_in_debate') == 'two': logger.info("%(debate)s won by %(team)s on %(motion)s", { 'debate': debate.matchup, 'team': result.winning_side(), 'motion': bsub.motion and bsub.motion.reference or "<No motion>" }) elif t.pref('teams_in_debate') == 'bp': logger.info("%(debate)s: %(ranked)s on %(motion)s", { 'debate': debate.matchup, 'ranked': ", ".join(result.scoresheet.ranked_sides()), 'motion': bsub.motion and bsub.motion.reference or "<No motion>" }) return result
def import_results(self): for round in self.root.findall('round'): consensus = self.preliminary_consensus if round.get( 'elimination') == 'false' else self.elimination_consensus for debate in round.findall('debate'): bs_obj = BallotSubmission( version=1, submitter_type=Submission.SUBMITTER_TABROOM, confirmed=True, debate=self.debates[debate.get('id')], motion=self.motions.get(debate.get('motion'))) bs_obj.save() dr = DebateResult(bs_obj) numeric_scores = True try: float(debate.find("side/ballot").text) except ValueError: numeric_scores = False for side, side_code in zip(debate.findall('side'), self.tournament.sides): if side.get('motion-veto') is not None: bs_obj.debateteammotionpreference_set.add( debate_team=self.debateteams.get( (debate.get('id'), side.get('team'))), motion=self.motions.get(side.get('motion-veto')), preference=3) for speech, pos in zip(side.findall('speech'), self.tournament.positions): if numeric_scores: dr.set_speaker( side_code, pos, self.speakers.get(speech.get('speaker'))) if consensus: dr.set_score(side_code, pos, float(speech.find('ballot').text)) else: for ballot in speech.findall('ballot'): for adj in [ self.adjudicators[a] for a in ballot.get( 'adjudicators', "").split(" ") ]: dr.set_score(adj, side_code, pos, float(ballot.text)) # Note: Dependent on #1180 if consensus: if int(side.find('ballot').get('rank')) == 1: dr.add_winner(side_code) else: for ballot in side.findall('ballot'): for adj in [ self.adjudicators.get(a) for a in ballot.get('adjudicators', "").split(" ") ]: if int(ballot.get('rank')) == 1: dr.add_winner(adj, side_code) dr.save()