def serial_debateteams_ordered(self): t = self.round.tournament for side in t.sides: sdt = {'side': side, 'team': None, 'position': get_side_name(t, side, 'full'), 'abbr': get_side_name(t, side, 'abbr')} try: debate_team = self.get_dt(side) sdt['team'] = debate_team.team.serialize() except ObjectDoesNotExist: pass yield sdt
def _add_break_rank_columns(self, table, draw, category): for side in self.tournament.sides: # Translators: e.g. "Affirmative: Break rank" tooltip = _("%(side_name)s: Break rank") % { 'side_name': get_side_name(self.tournament, side, 'full') } tooltip = tooltip.capitalize() # Translators: "BR" stands for "Break rank" key = format_html("{}<br>{}", get_side_name(self.tournament, side, 'abbr'), _("BR")) table.add_column( {'tooltip': tooltip, 'key': key, 'text': key}, [d.get_team(side).break_rank_for_category(category) for d in draw] )
def get_side_name(self, tournament=None, name_type='full'): """Should be used instead of get_side_display() on views. `tournament` can be passed in if known, for performance.""" try: return get_side_name(tournament or self.debate.round.tournament, self.side, name_type) except KeyError: return self.get_side_display() # fallback
def _prepend_side_header(self, side, name, abbr, text_only=False): # Translators: e.g. "Affirmative: Rank", "Government: Draw strength", # "Opening government: Total speaker score", "Closing opposition: Number of firsts" tooltip = _("%(side_name)s: %(metric_name)s") % { 'side_name': get_side_name(self.tournament, side, 'full'), 'metric_name': name.capitalize(), } tooltip = tooltip.capitalize() key = format_html("{}<br>{}", get_side_name(self.tournament, side, 'abbr'), abbr) # Never use icons in this type of column, because we need to differentiate between sides header = { 'key': key, # no need to translate 'tooltip': tooltip, 'text': abbr if text_only else key } return header
def add_debate_team_columns(self, debates, highlight=[]): all_sides_confirmed = all(debate.sides_confirmed for debate in debates) # should already be fetched for i, side in enumerate(self.tournament.sides, start=1): # For BP team names are often longer than the full position label if self.tournament.pref('teams_in_debate') == 'bp': side_name = get_side_name(self.tournament, side, 'abbr') else: side_name = get_side_name(self.tournament, side, 'full') team_data = [] for debate, hl in zip_longest(debates, highlight): team = debate.get_team(side) subtext = None if (all_sides_confirmed or not debate.sides_confirmed) else side_name team_data.append(self._team_cell(team, subtext=subtext, show_emoji=True, highlight=team == hl)) title = side_name if all_sides_confirmed else _("Team %(num)d") % {'num': i} header = {'key': side, 'title': title} self.add_column(header, team_data)
def create_declared_winner_dropdown(self): """This method creates a drop-down with a list of the teams in the debate""" teams = [(s, _("%(team)s (%(side)s)") % { 'team': self.debate.get_team(s).short_name, 'side': get_side_name(self.tournament, s, 'full') }) for s in self.sides] return forms.TypedChoiceField( label=_("Winner"), required=True, empty_value=None, choices=[(None, _("---------"))] + teams, )
def add_all_columns_for_team(self, side): teams = [debate.get_team(side) for debate in self.debates] side_abbr = get_side_name(self.tournament, side, 'abbr') self.add_team_columns(teams, key=side_abbr, show_emoji=False) # Highlight the team column for row in self.data: row[-1]['class'] = 'highlight-col' # Points of team metric_info = next(self.standings.metrics_info()) header = { 'key': "pts" + side_abbr, # always use 'pts' to make it more predictable 'tooltip': _("%(team)s: %(metric)s") % { 'team': side_abbr, 'metric': metric_info['name'] }, 'icon': 'star' } infos = self.standings.get_standings(teams) self.add_column( header, [metricformat(info.metrics[metric_info['key']]) for info in infos]) # Side history after last round header = self._prepend_side_header(side, _("side history before this round"), _("Sides"), text_only=True) cells = self._side_history_by_team(self.side_histories_before, teams) self.add_column(header, cells) # Position cost incurred, post-weighting header = self._prepend_side_header(side, _("position cost"), _("Cost"), text_only=True) pos = self.tournament.sides.index(side) cells = [ metricformat(self.get_position_cost(pos, team)) for team in teams ] self.add_column(header, cells) # Highlight according to category for row, team in zip(self.data, teams): category = self.get_imbalance_category(team) if category is None: continue for cell in row[-4:]: cell['class'] = cell.get('class', '') + ' table-' + category[0]
def _add_break_rank_columns(self, table, draw, category): for side in self.tournament.sides: # Translators: e.g. "Affirmative: Break rank" tooltip = _("%(side)s: Break rank") % { 'side': get_side_name(self.tournament, side, 'full'), } tooltip = tooltip.capitalize() # Translators: "BR" stands for "Break rank" key = format_html("{}<br>{}", get_side_name(self.tournament, side, 'abbr'), _("BR")) table.add_column( { 'tooltip': tooltip, 'key': key, 'text': key }, [ d.get_team(side).break_rank_for_category(category) for d in draw ], )
def add_debate_results_columns(self, debates): all_sides_confirmed = all(debate.sides_confirmed for debate in debates) # should already be fetched side_abbrs = {side: get_side_name(self.tournament, side, 'abbr') for side in self.tournament.sides} results_data = [] for debate in debates: row = [] for side in self.tournament.sides: debateteam = debate.get_dt(side) team = debate.get_team(side) subtext = None if (all_sides_confirmed or not debate.sides_confirmed) else side_abbrs[side] cell = self._team_cell(team, show_emoji=False, subtext=subtext) if self.tournament.pref('teams_in_debate') == 'two': cell = self._result_cell_class_two(debateteam.win, cell) elif debate.round.is_break_round: cell = self._result_cell_class_four_elim(debateteam.win, cell) else: cell = self._result_cell_class_four(debateteam.points, cell) row.append(cell) results_data.append(row) if all_sides_confirmed: results_header = [{ 'title': get_side_name(self.tournament, side, 'abbr').capitalize(), 'key': get_side_name(self.tournament, side, 'abbr') } for side in self.tournament.sides] else: results_header = [{ 'title': _("Team %(num)d") % {'num': i}, 'key': _("Team %(num)d") % {'num': i} } for i in range(1, len(side_abbrs)+1)] self.add_columns(results_header, results_data)
def add_all_columns_for_team(self, side): teams = [debate.get_team(side) for debate in self.debates] side_abbr = get_side_name(self.tournament, side, 'abbr') self.add_team_columns(teams, key=side_abbr, hide_emoji=True) # Highlight the team column for row in self.data: row[-1]['class'] = 'highlight-col' # Points of team infos = self.standings.get_standings(teams) header = { 'key': _("Pts"), 'tooltip': side_abbr + " " + _("Points"), 'icon': 'star' } self.add_column(header, [info.metrics['points'] for info in infos]) # Side history after last round header = self._prepend_side_header(side, _("side history before this round"), _("Sides"), text_only=True) cells = self._side_history_by_team(self.side_histories_before, teams) self.add_column(header, cells) # Position cost incurred, post-weighting header = self._prepend_side_header(side, _("position cost"), _("Cost"), text_only=True) pos = self.tournament.sides.index(side) cells = [ metricformat(self.get_position_cost(pos, team)) for team in teams ] self.add_column(header, cells) # Highlight according to category for row, team in zip(self.data, teams): category = self.get_imbalance_category(team) if category is None: continue for cell in row[-4:]: cell['class'] = cell.get('class', '') + ' table-' + category[0]
def get_table(self): teams = self.tournament.team_set.all() rounds = self.tournament.prelim_rounds() tsas = dict() for tsa in TeamSideAllocation.objects.filter(round__in=rounds): try: tsas[(tsa.team.id, tsa.round.seq)] = get_side_name(self.tournament, tsa.side, 'abbr') except ValueError: pass table = TabbycatTableBuilder(view=self) table.add_team_columns(teams) headers = [round.abbreviation for round in rounds] data = [[tsas.get((team.id, round.seq), "—") for round in rounds] for team in teams] table.add_columns(headers, data) return table
def get_table(self): teams = self.tournament.team_set.all() rounds = self.tournament.prelim_rounds() tsas = dict() for tsa in TeamSideAllocation.objects.filter(round__in=rounds): try: tsas[(tsa.team.id, tsa.round.seq)] = get_side_name(self.tournament, tsa.side, 'abbr') except ValueError: pass table = TabbycatTableBuilder(view=self) table.add_team_columns(teams) headers = [round.abbreviation for round in rounds] data = [[tsas.get((team.id, round.seq), "—") for round in rounds] for team in teams] table.add_columns(headers, data) return table
def add_all_columns_for_team(self, side): teams = [debate.get_team(side) for debate in self.debates] side_abbr = get_side_name(self.tournament, side, 'abbr') self.add_team_columns(teams, key=side_abbr, show_emoji=False) # Highlight the team column for row in self.data: row[-1]['class'] = 'highlight-col' # Points of team metric_info = next(self.standings.metrics_info()) header = { 'key': "pts", # always use 'pts' to make it more predictable 'tooltip': _("%(team)s: %(metric)s") % {'team': side_abbr, 'metric': metric_info['name']}, 'icon': 'star' } infos = self.standings.get_standings(teams) self.add_column(header, [metricformat(info.metrics[metric_info['key']]) for info in infos]) # Side history after last round header = self._prepend_side_header(side, _("side history before this round"), _("Sides"), text_only=True) cells = self._side_history_by_team(self.side_histories_before, teams) self.add_column(header, cells) # Position cost incurred, post-weighting header = self._prepend_side_header(side, _("position cost"), _("Cost"), text_only=True) pos = self.tournament.sides.index(side) cells = [metricformat(self.get_position_cost(pos, team)) for team in teams] self.add_column(header, cells) # Highlight according to category for row, team in zip(self.data, teams): category = self.get_imbalance_category(team) if category is None: continue for cell in row[-4:]: cell['class'] = cell.get('class', '') + ' table-' + category[0]
def add_debate_team_columns(self, debates, highlight=[]): all_sides_confirmed = all( debate.sides_confirmed for debate in debates) # should already be fetched for i, side in enumerate(self.tournament.sides, start=1): side_abbr = get_side_name(self.tournament, side, 'abbr') team_data = [] for debate, hl in zip_longest(debates, highlight): team = debate.get_team(side) subtext = None if (all_sides_confirmed or not debate.sides_confirmed) else side_abbr team_data.append( self._team_cell(team, subtext=subtext, hide_emoji=False, highlight=team == hl)) key = side_abbr if all_sides_confirmed else _("Team %(num)d") % { 'num': i } self.add_column(key, team_data)
def create_fields(self): """Dynamically generate fields for this ballot: - choose_sides, if sides need to be chosen by the user - motion, if there is more than one motion - <side>_motion_veto, if motion vetoes are being noted, one for each team - <side>_speaker_s#, one for each speaker - <side>_ghost_s#, whether score should be a duplicate Most fields are required, unless forfeits are enabled. """ # 1. Choose sides field if self.choosing_sides: # false in BP regardless of choosing sides setting teams = self.debate.teams assert len(teams) == 2 side_choices = [ (None, _("---------")), (str(teams[0].id) + "," + str(teams[1].id), _("%(aff_team)s affirmed, %(neg_team)s negated") % {'aff_team': teams[0].short_name, 'neg_team': teams[1].short_name}), (str(teams[1].id) + "," + str(teams[0].id), _("%(aff_team)s affirmed, %(neg_team)s negated") % {'aff_team': teams[1].short_name, 'neg_team': teams[0].short_name}) ] self.fields['choose_sides'] = forms.TypedChoiceField( choices=side_choices, coerce=lambda x: tuple(Team.objects.get(id=int(v)) for v in x.split(",")) ) for team in self.debate.teams: self.fields['team_%d' % team.id] = forms.ModelChoiceField(queryset=team.speakers, required=False) # 2. Motions fields if self.using_motions: self.fields['motion'] = MotionModelChoiceField(queryset=self.motions, required=not self.using_forfeits) if self.using_vetoes: for side in self.sides: self.fields[self._fieldname_motion_veto(side)] = MotionModelChoiceField( label=_("%(side_abbr)s's motion veto") % {'side_abbr': get_side_name(self.tournament, side, 'abbr')}, queryset=self.motions, required=False ) # 3. Speaker fields for side, pos in product(self.sides, self.positions): # 3(a). Speaker identity if self.choosing_sides: queryset = Speaker.objects.filter(team__in=self.debate.teams) else: queryset = self.debate.get_team(side).speakers self.fields[self._fieldname_speaker(side, pos)] = forms.ModelChoiceField( queryset=queryset, required=not self.using_forfeits) # 3(b). Ghost fields self.fields[self._fieldname_ghost(side, pos)] = forms.BooleanField(required=False, label=_("Mark as a duplicate speech"), label_suffix="") self.create_score_fields() # 4. Forfeit field if self.using_forfeits: choices = [(side, _("Forfeit by the %(side)s") % {'side': self._side_name(side)}) for side in self.sides] self.fields['forfeit'] = forms.ChoiceField(widget=forms.RadioSelect, choices=choices, required=False)
def _side_name(self, side): return get_side_name(self.tournament, side, 'full')
def _result_cell_bp(self, ts, compress=False, show_score=False, show_ballots=False): if not hasattr(ts, 'debate_team'): return {'text': self.BLANK_TEXT} other_teams = { dt.side: self._team_short_name(dt.team) for dt in ts.debate_team.debate.debateteam_set.all() } other_team_strs = [_("Teams in debate:")] for side in self.tournament.sides: if ts.debate_team.debate.sides_confirmed: line = _("%(team)s (%(side)s)") % { 'team': other_teams.get(side, _("??")), 'side': get_side_name(self.tournament, side, 'abbr'), } else: line = other_teams.get(side, _("??")) if side == ts.debate_team.side: line = "<strong>" + line + "</strong>" other_team_strs.append(line) cell = { 'popover': { 'content': [{ 'text': "<br />".join(other_team_strs) }], 'title': "", 'class': "no-wrap", } } if ts.debate_team.debate.round.is_break_round: cell = self._result_cell_class_four_elim(ts.win, cell) if ts.win is True: cell['text'] = _("advancing") cell['popover']['title'] = _("Advancing") elif ts.win is False: cell['text'] = _("eliminated") cell['popover']['title'] = _("Eliminated") else: cell['text'] = "–" cell['popover']['title'] = _("No result for debate") else: cell = self._result_cell_class_four(ts.points, cell) places = [ordinal(n) for n in reversed(range(1, 5))] if ts.points is not None: place = places[ts.points] if ts.points < 4 else _("??") cell['text'] = place cell['popover']['title'] = _("Placed %(place)s") % { 'place': place } else: cell['text'] = "–" cell['popover']['title'] = _("No result for debate") if show_score and ts.score is not None: score = ts.score if self.tournament.integer_scores( ts.debate_team.debate.round.stage) and score.is_integer(): score = int(ts.score) cell['subtext'] = metricformat(score) cell['popover']['content'].append({ 'text': _("Total speaker score: <strong>%s</strong>") % metricformat(score) }) if show_ballots: if self.admin: cell['popover']['content'].append({ 'text': _("View/edit debate ballot"), 'link': reverse_tournament('results-ballotset-edit', self.tournament, kwargs={'pk': ts.ballot_submission_id}), }) elif self.tournament.pref('ballots_released'): cell['popover']['content'].append({ 'text': _("View debate ballot"), 'link': reverse_tournament('results-public-scoresheet-view', self.tournament, kwargs={'pk': ts.debate_team.debate_id}), }) return cell
def add_debate_results_columns(self, debates, iron=False): all_sides_confirmed = all( debate.sides_confirmed for debate in debates) # should already be fetched side_abbrs = { side: get_side_name(self.tournament, side, 'abbr') for side in self.tournament.sides } results_data = [] for debate in debates: row = [] for side in self.tournament.sides: debateteam = debate.get_dt(side) team = debate.get_team(side) subtext = None if ( all_sides_confirmed or not debate.sides_confirmed) else side_abbrs[side] cell = self._team_cell(team, show_emoji=False, subtext=subtext) if self.tournament.pref('teams_in_debate') == 'two': cell = self._result_cell_class_two(debateteam.win, cell) elif debate.round.is_break_round: cell = self._result_cell_class_four_elim( debateteam.win, cell) else: cell = self._result_cell_class_four( debateteam.points, cell) if iron and (debateteam.iron > 0 or debateteam.iron_prev > 0): cell['text'] = "🗣️" + cell['text'] popover_text = [] if debateteam.iron > 0 and debateteam.iron_prev > 0: popover_text = _( "Team iron-manned this round and the last.") warning_level = "text-info" elif debateteam.iron > 0: popover_text = _("Team iron-manned this round.") warning_level = "text-info" else: popover_text = _("Team iron-manned last round.") warning_level = "text-warning" cell['class'] = "%s strong" % warning_level cell['popover']['content'].append({ 'text': "<span class='%s'>%s</span>" % (warning_level, popover_text) }) row.append(cell) results_data.append(row) if all_sides_confirmed: results_header = [{ 'title': get_side_name(self.tournament, side, 'abbr').capitalize(), 'key': get_side_name(self.tournament, side, 'abbr'), } for side in self.tournament.sides] else: results_header = [{ 'title': _("Team %(num)d") % { 'num': i }, 'key': _("Team %(num)d") % { 'num': i }, } for i in range(1, len(side_abbrs) + 1)] self.add_columns(results_header, results_data)
def build(self, draw, teams, side_histories_before, side_histories_now, standings): self.side_histories_before = side_histories_before self.side_histories_now = side_histories_now self.standings = standings # Filter for just those teams that are "noteworthy" teams = [team for team in teams if self.get_imbalance_category(team) is not None] self.add_team_columns(teams) # First metric metric_info = next(self.standings.metrics_info()) header = { 'key': "pts", # always use 'pts' to make it more predictable 'title': force_text(metric_info['abbr']), 'tooltip': force_text(metric_info['name']), } infos = self.standings.get_standings(teams) cells = [] for info in infos: points = info.metrics[metric_info['key']] cells.append({ 'text': metricformat(points), 'sort': points, }) self.add_column(header, cells) # Sides sides_lookup = {dt.team_id: dt.side for debate in draw for dt in debate.debateteam_set.all()} sides = [sides_lookup[team.id] for team in teams] poses = [self.tournament.sides.index(side) for side in sides] # used later names = {side: get_side_name(self.tournament, side, 'abbr') for side in self.tournament.sides} header = {'key': "side", 'title': _("Side"), 'tooltip': _("Position this round")} self.add_column(header, [names[side] for side in sides]) # Side counts before and now header = {'key': "before", 'title': _("Before"), 'tooltip': _("Side history before this round")} cells = self._side_history_by_team(self.side_histories_before, teams) self.add_column(header, cells) header = {'key': "after", 'title': _("After"), 'tooltip': _("Side history after this round")} side_histories_now_highlighted = [] for team, pos in zip(teams, poses): history = [str(x) for x in self.side_histories_now[team.id]] history[pos] = "<strong>" + history[pos] + "</strong>" history_str = self.side_history_separator.join(history) side_histories_now_highlighted.append(history_str) self.add_column(header, side_histories_now_highlighted) # Position cost header = {'key': "cost", 'title': _("Cost"), 'tooltip': _("Position cost")} cells = [metricformat(self.get_position_cost(pos, team)) for pos, team in zip(poses, teams)] self.add_column(header, cells) # Status cells = [] for team in teams: style, category, sort = self.get_imbalance_category(team) cells.append({ 'text': self.STATUSES[category], 'sort': sort, 'class': 'text-' + style }) self.add_column({'key': 'status', 'title': _("Status")}, cells) # Sort by points as secondary sort (will be sorted by cost in Vue) self.data.sort(key=lambda x: x[1].get('sort', 0), reverse=True)
def _result_cell_bp(self, ts, compress=False, show_score=False, show_ballots=False): if not hasattr(ts, 'debate_team'): return {'text': self.BLANK_TEXT} other_teams = {dt.side: self._team_short_name(dt.team) for dt in ts.debate_team.debate.debateteam_set.all()} other_team_strs = [_("Teams in debate:")] for side in self.tournament.sides: if ts.debate_team.debate.sides_confirmed: line = _("%(team)s (%(side)s)") % { 'team': other_teams.get(side, "??"), 'side': get_side_name(self.tournament, side, 'abbr') } else: line = other_teams.get(side, "??") if side == ts.debate_team.side: line = "<strong>" + line + "</strong>" other_team_strs.append(line) cell = {'popover': { 'content': [{'text': "<br />".join(other_team_strs)}], 'title': "", 'class': "no-wrap", }} if ts.debate_team.debate.round.is_break_round: cell = self._result_cell_class_four_elim(ts.win, cell) if ts.win is True: cell['text'] = _("advancing") cell['popover']['title'] = _("Advancing") elif ts.win is False: cell['text'] = _("eliminated") cell['popover']['title'] = _("Eliminated") else: cell['text'] = "–" cell['popover']['title'] = _("No result for debate") else: cell = self._result_cell_class_four(ts.points, cell) places = {0: _("4th"), 1: _("3rd"), 2: _("2nd"), 3: _("1st")} if ts.points is not None: place = places.get(ts.points, "??") cell['text'] = place cell['popover']['title'] = _("Placed %(place)s") % {'place': place} else: cell['text'] = "–" cell['popover']['title'] = _("No result for debate") if show_score and ts.score is not None: score = ts.score if self.tournament.integer_scores(ts.debate_team.debate.round.stage) and score.is_integer(): score = int(ts.score) cell['subtext'] = metricformat(score) cell['popover']['content'].append( {'text': _("Total speaker score: <strong>%s</strong>") % metricformat(score)}) if show_ballots: if self.admin: cell['popover']['content'].append({ 'text': _("View/edit debate ballot"), 'link': reverse_tournament('results-ballotset-edit', self.tournament, kwargs={'pk': ts.ballot_submission_id}) }) elif self.tournament.pref('ballots_released'): cell['popover']['content'].append({ 'text': _("View debate ballot"), 'link': reverse_tournament('results-public-scoresheet-view', self.tournament, kwargs={'pk': ts.debate_team.debate_id}) }) return cell
def tournament_side_names(tournament, name_type): side_names = [ get_side_name(tournament, 'aff', name_type), get_side_name(tournament, 'neg', name_type) ] return side_names
def build(self, draw, teams, side_histories_before, side_histories_now, standings): self.side_histories_before = side_histories_before self.side_histories_now = side_histories_now self.standings = standings # Filter for just those teams that are "noteworthy" teams = [ team for team in teams if self.get_imbalance_category(team) is not None ] self.add_team_columns(teams) # First metric if len(self.standings.metric_keys ) == 0: # special case: no metrics used header = { 'key': "pts", 'title': "?", 'tooltip': _("No metrics in the team standings precedence"), } self.add_column(header, [0] * len(teams)) else: metric_info = next(self.standings.metrics_info()) header = { 'key': "pts", # always use 'pts' to make it more predictable 'title': force_text(metric_info['abbr']), 'tooltip': force_text(metric_info['name']), } cells = [] infos = self.standings.get_standings(teams) for info in infos: points = info.metrics[metric_info['key']] cells.append({ 'text': metricformat(points), 'sort': points, }) self.add_column(header, cells) # Sides sides_lookup = { dt.team_id: dt.side for debate in draw for dt in debate.debateteam_set.all() } sides = [sides_lookup[team.id] for team in teams] poses = [self.tournament.sides.index(side) for side in sides] # used later names = { side: get_side_name(self.tournament, side, 'abbr') for side in self.tournament.sides } header = { 'key': "side", 'title': _("Side"), 'tooltip': _("Position this round") } self.add_column(header, [names[side] for side in sides]) # Side counts before and now header = { 'key': "before", 'title': _("Before"), 'tooltip': _("Side history before this round") } cells = self._side_history_by_team(self.side_histories_before, teams) self.add_column(header, cells) header = { 'key': "after", 'title': _("After"), 'tooltip': _("Side history after this round") } side_histories_now_highlighted = [] for team, pos in zip(teams, poses): history = [str(x) for x in self.side_histories_now[team.id]] history[pos] = "<strong>" + history[pos] + "</strong>" history_str = self.side_history_separator.join(history) side_histories_now_highlighted.append(history_str) self.add_column(header, side_histories_now_highlighted) # Position cost header = { 'key': "cost", 'title': _("Cost"), 'tooltip': _("Position cost") } cells = [ metricformat(self.get_position_cost(pos, team)) for pos, team in zip(poses, teams) ] self.add_column(header, cells) # Status cells = [] for team in teams: style, category, sort = self.get_imbalance_category(team) cells.append({ 'text': self.STATUSES[category], 'sort': sort, 'class': 'text-' + style, }) self.add_column({'key': 'status', 'title': _("Status")}, cells) # Sort by points as secondary sort (will be sorted by cost in Vue) self.data.sort(key=lambda x: x[1].get('sort', 0), reverse=True)
def _side_name(self, side): return get_side_name(self.tournament, side, 'full')
def build(self, draw, teams, side_histories_before, side_histories_now, standings): self.side_histories_before = side_histories_before self.side_histories_now = side_histories_now self.standings = standings # Filter for just those teams that are "noteworthy" teams = [ team for team in teams if self.get_imbalance_category(team) is not None ] self.add_team_columns(teams) # Points infos = self.standings.get_standings(teams) header = {'key': _("Pts"), 'tooltip': _("Points")} self.add_column(header, [info.metrics['points'] for info in infos]) # Sides sides_lookup = { dt.team_id: dt.side for debate in draw for dt in debate.debateteam_set.all() } sides = [sides_lookup[team.id] for team in teams] poses = [self.tournament.sides.index(side) for side in sides] # used later names = { side: get_side_name(self.tournament, side, 'abbr') for side in self.tournament.sides } header = {'key': _("Side"), 'tooltip': _("Position this round")} self.add_column(header, [names[side] for side in sides]) # Side counts before and now header = { 'key': _("Before"), 'tooltip': _("Side history before this round") } cells = self._side_history_by_team(self.side_histories_before, teams) self.add_column(header, cells) header = { 'key': _("After"), 'tooltip': _("Side history after this round") } side_histories_now_highlighted = [] for team, pos in zip(teams, poses): history = [str(x) for x in self.side_histories_now[team.id]] history[pos] = "<strong>" + history[pos] + "</strong>" history_str = self.side_history_separator.join(history) side_histories_now_highlighted.append(history_str) self.add_column(header, side_histories_now_highlighted) # Position cost header = {'key': _("Cost"), 'tooltip': _("Position cost")} cells = [ metricformat(self.get_position_cost(pos, team)) for pos, team in zip(poses, teams) ] self.add_column(header, cells) # Status cells = [] for team in teams: style, category, sort = self.get_imbalance_category(team) cells.append({ 'text': self.STATUSES[category], 'sort': sort, 'class': 'text-' + style }) self.add_column(_("Status"), cells) # Sort by points as secondary sort (will be sorted by cost in Vue) self.data.sort(key=lambda x: x[1]['sort'], reverse=True)
def create_fields(self): """Dynamically generate fields for this ballot: - choose_sides, if sides need to be chosen by the user - motion, if there is more than one motion - <side>_motion_veto, if motion vetoes are being noted, one for each team - <side>_speaker_s#, one for each speaker - <side>_ghost_s#, whether score should be a duplicate """ # 1. Choose sides field if self.choosing_sides: # false in BP regardless of choosing sides setting teams = self.debate.teams assert len(teams) == 2 side_choices = [ (None, _("---------")), (str(teams[0].id) + "," + str(teams[1].id), _("%(aff_team)s affirmed, %(neg_team)s negated") % { 'aff_team': teams[0].short_name, 'neg_team': teams[1].short_name }), (str(teams[1].id) + "," + str(teams[0].id), _("%(aff_team)s affirmed, %(neg_team)s negated") % { 'aff_team': teams[1].short_name, 'neg_team': teams[0].short_name }), ] self.fields['choose_sides'] = forms.TypedChoiceField( choices=side_choices, coerce=lambda x: tuple( Team.objects.get(id=int(v)) for v in x.split(",")), ) for team in self.debate.teams: self.fields['team_%d' % team.id] = forms.ModelChoiceField( queryset=team.speakers, required=False) # 2. Motions fields if self.using_motions: self.fields['motion'] = MotionModelChoiceField( queryset=self.motions, required=True) if self.using_vetoes: for side in self.sides: self.fields[self._fieldname_motion_veto( side)] = MotionModelChoiceField( label=_("%(side)s's motion veto") % {'side': get_side_name(self.tournament, side, 'abbr')}, queryset=self.motions, required=False, help_text=get_side_name(self.tournament, side, 'full'), ) # 3. Speaker fields for side, pos in product(self.sides, self.positions): # 3(a). Speaker identity if self.choosing_sides: queryset = Speaker.objects.filter(team__in=self.debate.teams) else: queryset = self.debate.get_team(side).speakers self.fields[self._fieldname_speaker( side, pos)] = forms.ModelChoiceField(queryset=queryset, required=True) # 3(b). Ghost fields self.fields[self._fieldname_ghost(side, pos)] = forms.BooleanField( required=False, label=_("Mark as a duplicate speech"), label_suffix="") self.create_score_fields()
def tournament_side_names(tournament, name_type): side_names = [get_side_name(tournament, 'aff', name_type), get_side_name(tournament, 'neg', name_type)] return side_names