We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Preformed panels supporting outrounds
I have been having a play with preformed panels and from my quick attempt to generate them for outrounds, it seems to generate preformed panels as if it was generating panels for an additional preliminary round rather than a break round. 

For example this is the preformed panels that generated when I generated preformed panels for quarter finals for one of our tournaments.

![image](https://user-images.githubusercontent.com/3196468/81673981-97c26880-94a0-11ea-8197-2a018682d9bf.png)

We did end up changing some thing to do with the round sequence for these rounds (we added 2 additional in rounds, deleted the octo finals and edited the sequence numbers, but this round is set up as per the settings below:

![image](https://user-images.githubusercontent.com/3196468/81674165-df48f480-94a0-11ea-873d-6239181c248d.png)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `tabbycat/adjallocation/preformed/anticipated.py`
Content:
```
1 """Functions for computing an anticipated draw."""
2 
3 import itertools
4 
5 from breakqual.utils import calculate_live_thresholds, determine_liveness
6 from participants.prefetch import populate_win_counts
7 
8 
9 def calculate_anticipated_draw(round):
10     """Calculates an anticipated draw for the next round, based on the draw for
11     the last round. Returns a list of tuples
12         `(bracket_min, bracket_max, liveness)`,
13     being the minimum and maximum brackets possible for that room, and the
14     maximum number of teams that might be live in it. If the previous round's
15     draw doesn't exist, it will just return an empty list.
16 
17     Procedure:
18       1. Take the (actual) draw of the last round, with team points
19       2. For each room, compute a (min, max) of outcomes for each team.
20       3. Take the min, divide into rooms to make the `bracket_min` for each room.
21       4. Take the max, divide into rooms to make the `bracket_max` for each room.
22 
23     `round` should be the round for which you want an anticipated draw (the
24     "next round").
25     """
26 
27     nteamsindebate = 4 if round.tournament.pref('teams_in_debate') == 'bp' else 2
28 
29     if round.prev is None or not round.prev.debate_set.exists():
30         # Special case: If this is the first round, everyone will be on zero.
31         # Just take all teams, rounded down -- if this is done, it'll typically
32         # be done before availability is locked down. Also do this if the last
33         # round hasn't yet been drawn, since that's premature for bracket
34         # predictions.
35         npanels = round.tournament.team_set.count() // nteamsindebate
36         return [(0, 0, 0) for i in range(npanels)]
37 
38     # 1. Take the (actual) draw of the last round, with team points
39     debates = round.prev.debate_set_with_prefetches(ordering=('room_rank',),
40         teams=True, adjudicators=False, speakers=False, venues=False)
41     if round.prev.prev:
42         populate_win_counts([team for debate in debates for team in debate.teams],
43             round=round.prev.prev)
44     else:
45         # just say everyone is on zero (since no rounds have finished yet)
46         for debate in debates:
47             for team in debate.teams:
48                 team._points = 0
49 
50     # 2. Compute a (min, max) of outcomes for each team
51     team_points_after = []
52     points_available = [round.prev.weight * i for i in range(nteamsindebate)]
53     for debate in debates:
54         points_now = [team.points_count for team in debate.teams]
55         highest = max(points_now)
56         lowest = min(points_now)
57 
58         # Most cases will be single-point rooms or rooms with pull-ups from only
59         # one bracket; in these cases it's easy to prove this closed-form
60         # guarantee for what the teams in that room will look like afterwards.
61         if highest - lowest <= 1:
62             points_after = [(lowest+i, highest+i) for i in points_available]
63 
64         # For more complicated rooms (e.g. [9, 8, 8, 7]), it gets harder; just
65         # use brute force. For few enough rooms this won't be too bad a hit.
66         else:
67             possible_outcomes = []
68             for result in itertools.permutations(points_available):
69                 outcome = [n + r for n, r in zip(points_now, result)]
70                 outcome.sort(reverse=True)
71                 possible_outcomes.append(outcome)
72             points_after = [(min(team_after), max(team_after)) for team_after in zip(*possible_outcomes)]
73 
74         team_points_after.extend(points_after)
75 
76     # 3. Take the min, divide into rooms to make the `bracket_min` for each room.
77     # 4. Take the max, divide into rooms to make the `bracket_max` for each room.
78     lowers, uppers = [sorted(x, reverse=True) for x in zip(*team_points_after)]
79     brackets_min = [max(r) for r in zip(*([iter(lowers)] * nteamsindebate))]
80     brackets_max = [max(r) for r in zip(*([iter(uppers)] * nteamsindebate))]
81 
82     open_category = round.tournament.breakcategory_set.filter(is_general=True).first()
83     if open_category:
84         live_thresholds = calculate_live_thresholds(open_category, round.tournament, round)
85         liveness_by_lower = [determine_liveness(live_thresholds, x) for x in lowers]
86         liveness_by_upper = [determine_liveness(live_thresholds, x) for x in uppers]
87         liveness_by_team = [x == 'live' or y == 'live' for x, y in zip(liveness_by_lower, liveness_by_upper)]
88         liveness = [x.count(True) for x in zip(*([iter(liveness_by_team)] * nteamsindebate))]
89     else:
90         liveness = [0] * len(debates)
91 
92     return zip(brackets_min, brackets_max, liveness)
93
```

Path: `tabbycat/draw/generator/utils.py`
Content:
```
1 """Miscellaneous utilities for the draw."""
2 
3 
4 def ispow2(n):
5     """Returns True if n is a power of 2. Works for positive integers only."""
6     return n & (n - 1) == 0
7 
8 
9 def nextpow2(n):
10     return 1 << (n-1).bit_length()
11 
12 
13 def partial_break_round_split(break_size):
14     """Returns a tuple `(debating, bypassing)`, where `debating` is how many
15     teams will debate in the first break round, and `bypassing` is how many
16     teams will bypass the first break round, qualifying directly for the
17     second."""
18 
19     assert break_size > 1, "break rounds only make sense for break_size > 1 (found %d)" % (break_size,)
20 
21     teams_in_second_break_round = nextpow2(break_size) // 2
22     debates = break_size - teams_in_second_break_round
23     bypassing = teams_in_second_break_round - debates
24 
25     assert 2*debates + bypassing == break_size, "2 * %d teams debating + %d teams bypassing doesn't add to break size %d" % (debates, bypassing, break_size)
26     assert debates > 0, "%d <= 0 debates in first break round (%d teams bypassing)" % (debates, bypassing)
27     assert bypassing >= 0, "%d < 0 teams bypassing (%d debates)" % (bypassing, debates)
28     return debates, bypassing
29
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/tabbycat/adjallocation/preformed/anticipated.py b/tabbycat/adjallocation/preformed/anticipated.py
--- a/tabbycat/adjallocation/preformed/anticipated.py
+++ b/tabbycat/adjallocation/preformed/anticipated.py
@@ -3,6 +3,7 @@
 import itertools
 
 from breakqual.utils import calculate_live_thresholds, determine_liveness
+from draw.generator.utils import ispow2, partial_break_round_split
 from participants.prefetch import populate_win_counts
 
 
@@ -26,13 +27,35 @@
 
     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.
+    if round.prev is None or not round.prev.debate_set.exists() or round.is_break_round:
+        # Special cases: 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
+        #
+        # Also occurs for elimination rounds as everyone is just as live.
+
+        nteams = 0
+        if round.is_break_round:
+            break_size = round.break_category.break_size
+            nprev_rounds = round.break_category.round_set.filter(seq__lt=round.seq).count()
+            partial_two = nteamsindebate == 2 and not ispow2(break_size)
+            partial_bp = nteamsindebate == 4 and ispow2(break_size // 6)
+            if nprev_rounds > 0 and (partial_two or partial_bp):
+                # If using partial elimination rounds, the second round is the first for
+                # the powers of two, so start counting from here.
+                nprev_rounds -= 1
+
+            if nprev_rounds == 0 and nteamsindebate == 2:
+                nteams = partial_break_round_split(break_size)[0] * 2
+            else:
+                # Subsequent rounds are half the previous, but always a power of 2
+                nteams = 1 << (break_size.bit_length() - 1 - nprev_rounds)
+        else:
+            nteams = round.tournament.team_set.count()
+
+        npanels = nteams // nteamsindebate
         return [(0, 0, 0) for i in range(npanels)]
 
     # 1. Take the (actual) draw of the last round, with team points
diff --git a/tabbycat/draw/generator/utils.py b/tabbycat/draw/generator/utils.py
--- a/tabbycat/draw/generator/utils.py
+++ b/tabbycat/draw/generator/utils.py
@@ -11,8 +11,8 @@
 
 
 def partial_break_round_split(break_size):
-    """Returns a tuple `(debating, bypassing)`, where `debating` is how many
-    teams will debate in the first break round, and `bypassing` is how many
+    """Returns a tuple `(debates, bypassing)`, where `debating` is how many
+    debates there is in the first break round, and `bypassing` is how many
     teams will bypass the first break round, qualifying directly for the
     second."""

{"golden_diff": "diff --git a/tabbycat/adjallocation/preformed/anticipated.py b/tabbycat/adjallocation/preformed/anticipated.py\n--- a/tabbycat/adjallocation/preformed/anticipated.py\n+++ b/tabbycat/adjallocation/preformed/anticipated.py\n@@ -3,6 +3,7 @@\n import itertools\n \n from breakqual.utils import calculate_live_thresholds, determine_liveness\n+from draw.generator.utils import ispow2, partial_break_round_split\n from participants.prefetch import populate_win_counts\n \n \n@@ -26,13 +27,35 @@\n \n     nteamsindebate = 4 if round.tournament.pref('teams_in_debate') == 'bp' else 2\n \n-    if round.prev is None or not round.prev.debate_set.exists():\n-        # Special case: If this is the first round, everyone will be on zero.\n+    if round.prev is None or not round.prev.debate_set.exists() or round.is_break_round:\n+        # Special cases: If this is the first round, everyone will be on zero.\n         # Just take all teams, rounded down -- if this is done, it'll typically\n         # be done before availability is locked down. Also do this if the last\n         # round hasn't yet been drawn, since that's premature for bracket\n         # predictions.\n-        npanels = round.tournament.team_set.count() // nteamsindebate\n+        #\n+        # Also occurs for elimination rounds as everyone is just as live.\n+\n+        nteams = 0\n+        if round.is_break_round:\n+            break_size = round.break_category.break_size\n+            nprev_rounds = round.break_category.round_set.filter(seq__lt=round.seq).count()\n+            partial_two = nteamsindebate == 2 and not ispow2(break_size)\n+            partial_bp = nteamsindebate == 4 and ispow2(break_size // 6)\n+            if nprev_rounds > 0 and (partial_two or partial_bp):\n+                # If using partial elimination rounds, the second round is the first for\n+                # the powers of two, so start counting from here.\n+                nprev_rounds -= 1\n+\n+            if nprev_rounds == 0 and nteamsindebate == 2:\n+                nteams = partial_break_round_split(break_size)[0] * 2\n+            else:\n+                # Subsequent rounds are half the previous, but always a power of 2\n+                nteams = 1 << (break_size.bit_length() - 1 - nprev_rounds)\n+        else:\n+            nteams = round.tournament.team_set.count()\n+\n+        npanels = nteams // nteamsindebate\n         return [(0, 0, 0) for i in range(npanels)]\n \n     # 1. Take the (actual) draw of the last round, with team points\ndiff --git a/tabbycat/draw/generator/utils.py b/tabbycat/draw/generator/utils.py\n--- a/tabbycat/draw/generator/utils.py\n+++ b/tabbycat/draw/generator/utils.py\n@@ -11,8 +11,8 @@\n \n \n def partial_break_round_split(break_size):\n-    \"\"\"Returns a tuple `(debating, bypassing)`, where `debating` is how many\n-    teams will debate in the first break round, and `bypassing` is how many\n+    \"\"\"Returns a tuple `(debates, bypassing)`, where `debating` is how many\n+    debates there is in the first break round, and `bypassing` is how many\n     teams will bypass the first break round, qualifying directly for the\n     second.\"\"\"\n", "issue": "Preformed panels supporting outrounds\nI have been having a play with preformed panels and from my quick attempt to generate them for outrounds, it seems to generate preformed panels as if it was generating panels for an additional preliminary round rather than a break round. \r\n\r\nFor example this is the preformed panels that generated when I generated preformed panels for quarter finals for one of our tournaments.\r\n\r\n![image](https://user-images.githubusercontent.com/3196468/81673981-97c26880-94a0-11ea-8197-2a018682d9bf.png)\r\n\r\nWe did end up changing some thing to do with the round sequence for these rounds (we added 2 additional in rounds, deleted the octo finals and edited the sequence numbers, but this round is set up as per the settings below:\r\n\r\n![image](https://user-images.githubusercontent.com/3196468/81674165-df48f480-94a0-11ea-873d-6239181c248d.png)\r\n\n", "before_files": [{"content": "\"\"\"Functions for computing an anticipated draw.\"\"\"\n\nimport itertools\n\nfrom breakqual.utils import calculate_live_thresholds, determine_liveness\nfrom participants.prefetch import populate_win_counts\n\n\ndef calculate_anticipated_draw(round):\n    \"\"\"Calculates an anticipated draw for the next round, based on the draw for\n    the last round. Returns a list of tuples\n        `(bracket_min, bracket_max, liveness)`,\n    being the minimum and maximum brackets possible for that room, and the\n    maximum number of teams that might be live in it. If the previous round's\n    draw doesn't exist, it will just return an empty list.\n\n    Procedure:\n      1. Take the (actual) draw of the last round, with team points\n      2. For each room, compute a (min, max) of outcomes for each team.\n      3. Take the min, divide into rooms to make the `bracket_min` for each room.\n      4. Take the max, divide into rooms to make the `bracket_max` for each room.\n\n    `round` should be the round for which you want an anticipated draw (the\n    \"next round\").\n    \"\"\"\n\n    nteamsindebate = 4 if round.tournament.pref('teams_in_debate') == 'bp' else 2\n\n    if round.prev is None or not round.prev.debate_set.exists():\n        # Special case: If this is the first round, everyone will be on zero.\n        # Just take all teams, rounded down -- if this is done, it'll typically\n        # be done before availability is locked down. Also do this if the last\n        # round hasn't yet been drawn, since that's premature for bracket\n        # predictions.\n        npanels = round.tournament.team_set.count() // nteamsindebate\n        return [(0, 0, 0) for i in range(npanels)]\n\n    # 1. Take the (actual) draw of the last round, with team points\n    debates = round.prev.debate_set_with_prefetches(ordering=('room_rank',),\n        teams=True, adjudicators=False, speakers=False, venues=False)\n    if round.prev.prev:\n        populate_win_counts([team for debate in debates for team in debate.teams],\n            round=round.prev.prev)\n    else:\n        # just say everyone is on zero (since no rounds have finished yet)\n        for debate in debates:\n            for team in debate.teams:\n                team._points = 0\n\n    # 2. Compute a (min, max) of outcomes for each team\n    team_points_after = []\n    points_available = [round.prev.weight * i for i in range(nteamsindebate)]\n    for debate in debates:\n        points_now = [team.points_count for team in debate.teams]\n        highest = max(points_now)\n        lowest = min(points_now)\n\n        # Most cases will be single-point rooms or rooms with pull-ups from only\n        # one bracket; in these cases it's easy to prove this closed-form\n        # guarantee for what the teams in that room will look like afterwards.\n        if highest - lowest <= 1:\n            points_after = [(lowest+i, highest+i) for i in points_available]\n\n        # For more complicated rooms (e.g. [9, 8, 8, 7]), it gets harder; just\n        # use brute force. For few enough rooms this won't be too bad a hit.\n        else:\n            possible_outcomes = []\n            for result in itertools.permutations(points_available):\n                outcome = [n + r for n, r in zip(points_now, result)]\n                outcome.sort(reverse=True)\n                possible_outcomes.append(outcome)\n            points_after = [(min(team_after), max(team_after)) for team_after in zip(*possible_outcomes)]\n\n        team_points_after.extend(points_after)\n\n    # 3. Take the min, divide into rooms to make the `bracket_min` for each room.\n    # 4. Take the max, divide into rooms to make the `bracket_max` for each room.\n    lowers, uppers = [sorted(x, reverse=True) for x in zip(*team_points_after)]\n    brackets_min = [max(r) for r in zip(*([iter(lowers)] * nteamsindebate))]\n    brackets_max = [max(r) for r in zip(*([iter(uppers)] * nteamsindebate))]\n\n    open_category = round.tournament.breakcategory_set.filter(is_general=True).first()\n    if open_category:\n        live_thresholds = calculate_live_thresholds(open_category, round.tournament, round)\n        liveness_by_lower = [determine_liveness(live_thresholds, x) for x in lowers]\n        liveness_by_upper = [determine_liveness(live_thresholds, x) for x in uppers]\n        liveness_by_team = [x == 'live' or y == 'live' for x, y in zip(liveness_by_lower, liveness_by_upper)]\n        liveness = [x.count(True) for x in zip(*([iter(liveness_by_team)] * nteamsindebate))]\n    else:\n        liveness = [0] * len(debates)\n\n    return zip(brackets_min, brackets_max, liveness)\n", "path": "tabbycat/adjallocation/preformed/anticipated.py"}, {"content": "\"\"\"Miscellaneous utilities for the draw.\"\"\"\n\n\ndef ispow2(n):\n    \"\"\"Returns True if n is a power of 2. Works for positive integers only.\"\"\"\n    return n & (n - 1) == 0\n\n\ndef nextpow2(n):\n    return 1 << (n-1).bit_length()\n\n\ndef partial_break_round_split(break_size):\n    \"\"\"Returns a tuple `(debating, bypassing)`, where `debating` is how many\n    teams will debate in the first break round, and `bypassing` is how many\n    teams will bypass the first break round, qualifying directly for the\n    second.\"\"\"\n\n    assert break_size > 1, \"break rounds only make sense for break_size > 1 (found %d)\" % (break_size,)\n\n    teams_in_second_break_round = nextpow2(break_size) // 2\n    debates = break_size - teams_in_second_break_round\n    bypassing = teams_in_second_break_round - debates\n\n    assert 2*debates + bypassing == break_size, \"2 * %d teams debating + %d teams bypassing doesn't add to break size %d\" % (debates, bypassing, break_size)\n    assert debates > 0, \"%d <= 0 debates in first break round (%d teams bypassing)\" % (debates, bypassing)\n    assert bypassing >= 0, \"%d < 0 teams bypassing (%d debates)\" % (bypassing, debates)\n    return debates, bypassing\n", "path": "tabbycat/draw/generator/utils.py"}], "after_files": [{"content": "\"\"\"Functions for computing an anticipated draw.\"\"\"\n\nimport itertools\n\nfrom breakqual.utils import calculate_live_thresholds, determine_liveness\nfrom draw.generator.utils import ispow2, partial_break_round_split\nfrom participants.prefetch import populate_win_counts\n\n\ndef calculate_anticipated_draw(round):\n    \"\"\"Calculates an anticipated draw for the next round, based on the draw for\n    the last round. Returns a list of tuples\n        `(bracket_min, bracket_max, liveness)`,\n    being the minimum and maximum brackets possible for that room, and the\n    maximum number of teams that might be live in it. If the previous round's\n    draw doesn't exist, it will just return an empty list.\n\n    Procedure:\n      1. Take the (actual) draw of the last round, with team points\n      2. For each room, compute a (min, max) of outcomes for each team.\n      3. Take the min, divide into rooms to make the `bracket_min` for each room.\n      4. Take the max, divide into rooms to make the `bracket_max` for each room.\n\n    `round` should be the round for which you want an anticipated draw (the\n    \"next round\").\n    \"\"\"\n\n    nteamsindebate = 4 if round.tournament.pref('teams_in_debate') == 'bp' else 2\n\n    if round.prev is None or not round.prev.debate_set.exists() or round.is_break_round:\n        # Special cases: If this is the first round, everyone will be on zero.\n        # Just take all teams, rounded down -- if this is done, it'll typically\n        # be done before availability is locked down. Also do this if the last\n        # round hasn't yet been drawn, since that's premature for bracket\n        # predictions.\n        #\n        # Also occurs for elimination rounds as everyone is just as live.\n\n        nteams = 0\n        if round.is_break_round:\n            break_size = round.break_category.break_size\n            nprev_rounds = round.break_category.round_set.filter(seq__lt=round.seq).count()\n            partial_two = nteamsindebate == 2 and not ispow2(break_size)\n            partial_bp = nteamsindebate == 4 and ispow2(break_size // 6)\n            if nprev_rounds > 0 and (partial_two or partial_bp):\n                # If using partial elimination rounds, the second round is the first for\n                # the powers of two, so start counting from here.\n                nprev_rounds -= 1\n\n            if nprev_rounds == 0 and nteamsindebate == 2:\n                nteams = partial_break_round_split(break_size)[0] * 2\n            else:\n                # Subsequent rounds are half the previous, but always a power of 2\n                nteams = 1 << (break_size.bit_length() - 1 - nprev_rounds)\n        else:\n            nteams = round.tournament.team_set.count()\n\n        npanels = nteams // nteamsindebate\n        return [(0, 0, 0) for i in range(npanels)]\n\n    # 1. Take the (actual) draw of the last round, with team points\n    debates = round.prev.debate_set_with_prefetches(ordering=('room_rank',),\n        teams=True, adjudicators=False, speakers=False, venues=False)\n    if round.prev.prev:\n        populate_win_counts([team for debate in debates for team in debate.teams],\n            round=round.prev.prev)\n    else:\n        # just say everyone is on zero (since no rounds have finished yet)\n        for debate in debates:\n            for team in debate.teams:\n                team._points = 0\n\n    # 2. Compute a (min, max) of outcomes for each team\n    team_points_after = []\n    for debate in debates:\n        points_now = [team.points_count for team in debate.teams]\n        highest = max(points_now)\n        lowest = min(points_now)\n\n        # Most cases will be single-point rooms or rooms with pull-ups from only\n        # one bracket; in these cases it's easy to prove this closed-form\n        # guarantee for what the teams in that room will look like afterwards.\n        if highest - lowest <= 1:\n            points_after = [(lowest+i, highest+i) for i in range(nteamsindebate)]\n\n        # For more complicated rooms (e.g. [9, 8, 8, 7]), it gets harder; just\n        # use brute force. For few enough rooms this won't be too bad a hit.\n        else:\n            possible_outcomes = []\n            for result in itertools.permutations(range(nteamsindebate)):\n                outcome = [n + r for n, r in zip(points_now, result)]\n                outcome.sort(reverse=True)\n                possible_outcomes.append(outcome)\n            points_after = [(min(team_after), max(team_after)) for team_after in zip(*possible_outcomes)]\n\n        team_points_after.extend(points_after)\n\n    # 3. Take the min, divide into rooms to make the `bracket_min` for each room.\n    # 4. Take the max, divide into rooms to make the `bracket_max` for each room.\n    lowers, uppers = [sorted(x, reverse=True) for x in zip(*team_points_after)]\n    brackets_min = [max(r) for r in zip(*([iter(lowers)] * nteamsindebate))]\n    brackets_max = [max(r) for r in zip(*([iter(uppers)] * nteamsindebate))]\n\n    open_category = round.tournament.breakcategory_set.filter(is_general=True).first()\n    if open_category:\n        live_thresholds = calculate_live_thresholds(open_category, round.tournament, round)\n        liveness_by_lower = [determine_liveness(live_thresholds, x) for x in lowers]\n        liveness_by_upper = [determine_liveness(live_thresholds, x) for x in uppers]\n        liveness_by_team = [x == 'live' or y == 'live' for x, y in zip(liveness_by_lower, liveness_by_upper)]\n        liveness = [x.count(True) for x in zip(*([iter(liveness_by_team)] * nteamsindebate))]\n    else:\n        liveness = [0] * len(debates)\n\n    return zip(brackets_min, brackets_max, liveness)\n", "path": "tabbycat/adjallocation/preformed/anticipated.py"}, {"content": "\"\"\"Miscellaneous utilities for the draw.\"\"\"\n\n\ndef ispow2(n):\n    \"\"\"Returns True if n is a power of 2. Works for positive integers only.\"\"\"\n    return n & (n - 1) == 0\n\n\ndef nextpow2(n):\n    return 1 << (n-1).bit_length()\n\n\ndef partial_break_round_split(break_size):\n    \"\"\"Returns a tuple `(debates, bypassing)`, where `debating` is how many\n    debates there is in the first break round, and `bypassing` is how many\n    teams will bypass the first break round, qualifying directly for the\n    second.\"\"\"\n\n    assert break_size > 1, \"break rounds only make sense for break_size > 1 (found %d)\" % (break_size,)\n\n    teams_in_second_break_round = nextpow2(break_size) // 2\n    debates = break_size - teams_in_second_break_round\n    bypassing = teams_in_second_break_round - debates\n\n    assert 2*debates + bypassing == break_size, \"2 * %d teams debating + %d teams bypassing doesn't add to break size %d\" % (debates, bypassing, break_size)\n    assert debates > 0, \"%d <= 0 debates in first break round (%d teams bypassing)\" % (debates, bypassing)\n    assert bypassing >= 0, \"%d < 0 teams bypassing (%d debates)\" % (bypassing, debates)\n    return debates, bypassing\n", "path": "tabbycat/draw/generator/utils.py"}]}