Exemple #1
0
    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
Exemple #2
0
    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]
            )
Exemple #3
0
 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
Exemple #4
0
    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
Exemple #5
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):
            # 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)
Exemple #6
0
 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,
     )
Exemple #7
0
    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]
Exemple #8
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
                ],
            )
Exemple #9
0
    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)
Exemple #10
0
    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]
Exemple #11
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
Exemple #12
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
Exemple #13
0
    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]
Exemple #14
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)
Exemple #15
0
    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)
Exemple #16
0
 def _side_name(self, side):
     return get_side_name(self.tournament, side, 'full')
Exemple #17
0
    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
Exemple #18
0
    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)
Exemple #19
0
    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)
Exemple #20
0
    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
Exemple #21
0
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
Exemple #22
0
    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)
Exemple #23
0
 def _side_name(self, side):
     return get_side_name(self.tournament, side, 'full')
Exemple #24
0
    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)
Exemple #25
0
    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()
Exemple #26
0
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