コード例 #1
0
ファイル: mixins.py プロジェクト: zengik/tabbycat
    def get_extra_info(self):
        """ Unlike meta_info everything under extra info is json serialised
        automatically. Designed for simple key/value pairs"""
        extra_info = {}  # Set by view for top bar toggles
        extra_info['codeNames'] = self.tournament.pref('team_code_names')
        extra_info['highlights'] = {}

        bcs = self.tournament.breakcategory_set.all()
        serialised_bcs = []
        for bc in bcs:
            safe, dead = calculate_live_thresholds(bc, self.tournament,
                                                   self.round)
            serialised_bc = {
                'pk': bc.id,
                'fields': {
                    'name': bc.name,
                    'safe': safe,
                    'dead': dead
                },
            }
            serialised_bcs.append(serialised_bc)

        extra_info['highlights']['break'] = serialised_bcs

        extra_info['backUrl'] = reverse_round('draw', self.round)
        extra_info['backLabel'] = _("Return to Draw")
        return extra_info
コード例 #2
0
 def break_thresholds(self):
     t = self.get_tournament()
     r = self.get_round()
     return {
         bc.id: calculate_live_thresholds(bc, t, r)
         for bc in self.break_categories
     }
コード例 #3
0
ファイル: utils.py プロジェクト: czlee/tabbycat
def teams_to_json(teams, regions, categories, t, r):
    thresholds = {bc["id"]: calculate_live_thresholds(bc, t, r) for bc in categories}

    # populate team categories
    tbcs = Team.break_categories.through.objects.filter(team__in=teams)
    break_category_ids_by_team = {team.id: [] for team in teams}
    for tbc in tbcs:
        break_category_ids_by_team[tbc.team_id].append(tbc.breakcategory_id)

    populate_win_counts(teams)

    data = {}
    for team in teams:
        team_categories = break_category_ids_by_team[team.id]
        break_categories = [
            {
                "id": bc["id"],
                "name": bc["name"],
                "seq": bc["seq"],
                "will_break": determine_liveness(thresholds[bc["id"]], team.wins_count),
            }
            for bc in categories
            if bc["id"] in team_categories
        ]

        data[team.id] = {
            "type": "team",
            "id": team.id,
            "name": team.short_name,
            "long_name": team.long_name,
            "uses_prefix": team.use_institution_prefix,
            "speakers": [{"name": s.name, "gender": s.gender} for s in team.speakers],
            "gender_show": False,
            "wins": team.wins_count,
            "region": [r for r in regions if r["id"] is team.institution.region_id][0]
            if team.institution.region_id
            else "",
            "region_show": False,
            # TODO: Searching for break cats here incurs extra queries; should be done earlier
            "categories": break_categories,
            "category_show": False,
            "institution": {
                "id": team.institution.id,
                "name": team.institution.code,
                "code": team.institution.code,
                "abbreviation": team.institution.abbreviation,
            },
            "histories": team.histories,
            "conflicts": {
                "teams": [],  # No team-team conflicts
                "institutions": team.institutional_institutions,
                "adjudicators": team.personal_adjudicators,
            },
            "conflicted": {
                "hover": {"personal": False, "institutional": False, "history": False, "history_ago": 99},
                "panel": {"personal": False, "institutional": False, "history": False, "history_ago": 99},
            },
        }
    return json.dumps(data)
コード例 #4
0
    def prioritise_debates(self, event):
        # TODO: Debates and panels should really be unified in a single function
        round = Round.objects.get(pk=event['extra']['round_id'])
        debates = round.debate_set_with_prefetches(teams=True,
                                                   adjudicators=False,
                                                   speakers=False,
                                                   divisions=False,
                                                   venues=False)

        priority_method = event['extra']['settings']['type']
        if priority_method == 'liveness':
            populate_win_counts(
                [team for debate in debates for team in debate.teams],
                round.prev)
            open_category = round.tournament.breakcategory_set.filter(
                is_general=True).first()
            if open_category:
                safe, dead = calculate_live_thresholds(open_category,
                                                       round.tournament, round)
                for debate in debates:
                    points_now = [team.points_count for team in debate.teams]
                    highest = max(points_now)
                    lowest = min(points_now)
                    if lowest >= safe:
                        debate.importance = 0
                    elif highest <= dead:
                        debate.importance = -2
                    else:
                        debate.importance = 1
                    debate.save()
            else:
                self.return_error(
                    event['extra']['group_name'],
                    _("You have no break category set as 'is general' so debate importances can't be calculated."
                      ))
                return

        elif priority_method == 'bracket':
            self._prioritise_by_bracket(debates, 'bracket')

        self.log_action(event['extra'], round,
                        ActionLogEntry.ACTION_TYPE_DEBATE_IMPORTANCE_AUTO)
        content = self.reserialize_debates(SimpleDebateImportanceSerializer,
                                           round, debates)
        msg = _("Succesfully auto-prioritised debates.")
        self.return_response(content, event['extra']['group_name'], msg,
                             'success')
コード例 #5
0
    def prioritise_panels(self, event):
        rd = Round.objects.get(pk=event['extra']['round_id'])
        panels = rd.preformedpanel_set.all()
        priority_method = event['extra']['settings']['type']

        if priority_method == 'liveness':
            open_category = rd.tournament.breakcategory_set.filter(
                is_general=True).first()
            if open_category:
                safe, dead = calculate_live_thresholds(open_category,
                                                       rd.tournament, rd)
                for panel in panels:
                    if panel.liveness > 0:
                        panel.importance = 1
                    elif panel.bracket_min >= safe:
                        panel.importance = 0
                    else:
                        panel.importance = -2
                    panel.save()
            else:
                self.return_error(
                    event['extra']['group_name'],
                    _("You have no break category set as 'is general' so panel importances can't be calculated."
                      ))
                return

        elif priority_method == 'bracket':
            panels = panels.annotate(
                bracket_mid=(F('bracket_max') + F('bracket_min')) / 2)
            self._prioritise_by_bracket(panels, 'bracket_mid')

        self.log_action(
            event['extra'], rd,
            ActionLogEntry.ACTION_TYPE_PREFORMED_PANELS_IMPORTANCE_AUTO)
        content = self.reserialize_panels(SimplePanelImportanceSerializer, rd,
                                          panels)
        msg = _("Succesfully auto-prioritised preformed panels.")
        self.return_response(content, event['extra']['group_name'], msg,
                             'success')
コード例 #6
0
ファイル: anticipated.py プロジェクト: vicbab/tabbycat
def calculate_anticipated_draw(round):
    """Calculates an anticipated draw for the next round, based on the draw for
    the last round. Returns a list of tuples
        `(bracket_min, bracket_max, liveness)`,
    being the minimum and maximum brackets possible for that room, and the
    maximum number of teams that might be live in it. If the previous round's
    draw doesn't exist, it will just return an empty list.

    Procedure:
      1. Take the (actual) draw of the last round, with team points
      2. For each room, compute a (min, max) of outcomes for each team.
      3. Take the min, divide into rooms to make the `bracket_min` for each room.
      4. Take the max, divide into rooms to make the `bracket_max` for each room.

    `round` should be the round for which you want an anticipated draw (the
    "next round").
    """

    nteamsindebate = 4 if round.tournament.pref(
        'teams_in_debate') == 'bp' else 2

    if round.prev is None or not round.prev.debate_set.exists():
        # Special case: If this is the first round, everyone will be on zero.
        # Just take all teams, rounded down -- if this is done, it'll typically
        # be done before availability is locked down. Also do this if the last
        # round hasn't yet been drawn, since that's premature for bracket
        # predictions.
        npanels = round.tournament.team_set.count() // nteamsindebate
        return [(0, 0, 0) for i in range(npanels)]

    # 1. Take the (actual) draw of the last round, with team points
    debates = round.prev.debate_set_with_prefetches(ordering=('room_rank', ),
                                                    teams=True,
                                                    adjudicators=False,
                                                    speakers=False,
                                                    divisions=False,
                                                    venues=False)
    if round.prev.prev:
        populate_win_counts(
            [team for debate in debates for team in debate.teams],
            round=round.prev.prev)
    else:
        # just say everyone is on zero (since no rounds have finished yet)
        for debate in debates:
            for team in debate.teams:
                team._points = 0

    # 2. Compute a (min, max) of outcomes for each team
    team_points_after = []
    for debate in debates:
        points_now = [team.points_count for team in debate.teams]
        highest = max(points_now)
        lowest = min(points_now)

        # Most cases will be single-point rooms or rooms with pull-ups from only
        # one bracket; in these cases it's easy to prove this closed-form
        # guarantee for what the teams in that room will look like afterwards.
        if highest - lowest <= 1:
            points_after = [(lowest + i, highest + i)
                            for i in range(nteamsindebate)]

        # For more complicated rooms (e.g. [9, 8, 8, 7]), it gets harder; just
        # use brute force. For few enough rooms this won't be too bad a hit.
        else:
            possible_outcomes = []
            for result in itertools.permutations(range(nteamsindebate)):
                outcome = [n + r for n, r in zip(points_now, result)]
                outcome.sort(reverse=True)
                possible_outcomes.append(outcome)
            points_after = [(min(team_after), max(team_after))
                            for team_after in zip(*possible_outcomes)]

        team_points_after.extend(points_after)

    # 3. Take the min, divide into rooms to make the `bracket_min` for each room.
    # 4. Take the max, divide into rooms to make the `bracket_max` for each room.
    lowers, uppers = [sorted(x, reverse=True) for x in zip(*team_points_after)]
    brackets_min = [max(r) for r in zip(*([iter(lowers)] * nteamsindebate))]
    brackets_max = [max(r) for r in zip(*([iter(uppers)] * nteamsindebate))]

    open_category = round.tournament.breakcategory_set.filter(
        is_general=True).first()
    if open_category:
        live_thresholds = calculate_live_thresholds(open_category,
                                                    round.tournament, round)
        liveness_by_lower = [
            determine_liveness(live_thresholds, x) for x in lowers
        ]
        liveness_by_upper = [
            determine_liveness(live_thresholds, x) for x in uppers
        ]
        liveness_by_team = [
            x == 'live' or y == 'live'
            for x, y in zip(liveness_by_lower, liveness_by_upper)
        ]
        liveness = [
            x.count(True)
            for x in zip(*([iter(liveness_by_team)] * nteamsindebate))
        ]
    else:
        liveness = [0] * len(debates)

    return zip(brackets_min, brackets_max, liveness)
コード例 #7
0
ファイル: utils.py プロジェクト: modale/tabbycat
def teams_to_json(teams, regions, categories, t, r):
    thresholds = {
        bc['id']: calculate_live_thresholds(bc, t, r)
        for bc in categories
    }

    # populate team categories
    tbcs = Team.break_categories.through.objects.filter(team__in=teams)
    break_category_ids_by_team = {team.id: [] for team in teams}
    for tbc in tbcs:
        break_category_ids_by_team[tbc.team_id].append(tbc.breakcategory_id)

    populate_win_counts(teams)

    data = {}
    for team in teams:
        team_categories = break_category_ids_by_team[team.id]
        break_categories = [{
            'id':
            bc['id'],
            'name':
            bc['name'],
            'seq':
            bc['seq'],
            'will_break':
            determine_liveness(thresholds[bc['id']], team.wins_count)
        } for bc in categories if bc['id'] in team_categories]

        data[team.id] = {
            'type':
            'team',
            'id':
            team.id,
            'name':
            team.short_name,
            'long_name':
            team.long_name,
            'uses_prefix':
            team.use_institution_prefix,
            'speakers': [{
                'name': s.name,
                'gender': s.gender
            } for s in team.speakers],
            'gender_show':
            False,
            'wins':
            team.wins_count,
            'region':
            [r for r in regions if r['id'] is team.institution.region_id][0]
            if team.institution.region_id else '',
            'region_show':
            False,
            # TODO: Searching for break cats here incurs extra queries; should be done earlier
            'categories':
            break_categories,
            'category_show':
            False,
            'institution': {
                'id': team.institution.id,
                'name': team.institution.code,
                'code': team.institution.code,
                'abbreviation': team.institution.abbreviation
            },
            'histories':
            team.histories,
            'conflicts': {
                'teams': [],  # No team-team conflicts
                'institutions': team.institutional_institutions,
                'adjudicators': team.personal_adjudicators
            },
            'conflicted': {
                'hover': {
                    'personal': False,
                    'institutional': False,
                    'history': False,
                    'history_ago': 99
                },
                'panel': {
                    'personal': False,
                    'institutional': False,
                    'history': False,
                    'history_ago': 99
                }
            }
        }
    return json.dumps(data)
コード例 #8
0
ファイル: mixins.py プロジェクト: czlee/tabbycat
 def break_thresholds(self):
     t = self.tournament
     r = self.round
     return {bc.id: calculate_live_thresholds(bc, t, r) for bc in self.break_categories}
コード例 #9
0
 def break_thresholds(self):
     return {
         category.id: calculate_live_thresholds(category, self.tournament,
                                                self.round)
         for category in self.break_categories
     }