def check_matches(self): """ loop through all matches checking for byes that can be updated """ matches = Match.get_by_bracket(self.id) for match in matches: match.check()
def __init__(self, name, matches_input, matches_result, time_begin, time_end): """Init turn class.""" self.name = name self.matches = [] self.time_begin = time_begin self.time_end = time_end for match, result in zip(matches_input, matches_result): self.matches.append(Match(match, result))
def delete(self): """ delete a bracket """ # delete any matches that have taken place matches = Match.get_by_bracket(self.id) for match in matches: match.delete() super(Bracket, self).delete()
def get_by_bracket(cls, bracket_id): """ alternative to the method available in BracketSearchMixin, parses through Matches instead """ from app.models.match import Match matches = Match.get_by_bracket_round(bracket_id, 'A') bots = [] for match in matches: bots += [match.bot1_id, match.bot2_id] bots = list(set(bots)) return [cls.get_by_id(bot_id) for bot_id in bots if bot_id]
def get(self, event_id, bracket_id): """ get """ match_id = self.request.get('match_id') winning_bot_id = self.request.get('winning_bot_id') match = Match.get_by_id(match_id) match.winner(winning_bot_id) self.redirect_to('single-bracket', event_id=event_id, bracket_id=bracket_id)
def regenerate(self, format): """ regenerate the bracket """ # delete any matches that have taken place matches = Match.get_by_bracket(self.id) for match in matches: match.delete() self.format_code = format self.put() self.generate()
def scrap(): for page_index in range(1, 2): url = BASE_URL + str(page_index) print("Fetching url = " + url) result = requests.get(url) if(result.status_code == 200): page = result.content soup = BeautifulSoup(page, PARSER) table = soup.find("table", "t2 b3") # print(table.prettify()) # table_body = table.find("tbody") table_rows = table.find_all("tr") for row in table_rows[1:-1]: cells = row.find_all("td") match_id = cells[0].get_text().strip().replace('.', '') match_date = cells[1].get_text().strip().split('.') match_date[0], match_date[2] = match_date[2], match_date[0] match_date = '-'.join(str(x) for x in match_date) match_venue = cells[2].get_text().strip() tournament = cells[3].get_text().strip() # embed score and competitor name score = cells[5].get_text().strip().split(":") score[0] = int(score[0]) score[1] = int(score[1]) competitor_1 = {} competitor_1[cells[4].get_text().strip()] = score[0] competitor_2 = {} competitor_2[cells[6].get_text().strip()] = score[1] result = results.DRAW # draw if(score[0] > score[1]): result = results.WIN # competitor 1 is the winner elif(score[0] < score[1]): result = results.LOSS # competitor 2 is the winner match = Match.create( date=match_date, venue=match_venue, tournament=tournament, competitor_1=competitor_1, competitor_2=competitor_2, result=result ) match.save()
def get(self, event_id): event = Event.get_by_id(event_id) if not event: self.redirect(uri_for('home')) weightclasses = Weightclass.get_by_event(event_id) generate_form = GenerateBracketForm() weightclass_choices = [] brackets = {} for weightclass in weightclasses: bots = Bot.get_by_weightclass_registered(weightclass.code, event.id) if len(bots) > 1: weightclass_choices.append( (weightclass.code, '%s (%d bots)' % (weightclass.name, len(bots)))) brackets[weightclass.name] = [] weightclass_brackets = Bracket.get_by_event_and_class( event_id, weightclass.code) for bracket in weightclass_brackets: matches = Match.get_by_bracket(bracket.id) completed_matches = [ match for match in matches if match.winning_bot_id ] bots = Bot.get_by_bracket(bracket.id) brackets[weightclass.name].append({ 'total_matches': len(matches) if matches else 0, 'completed_matches': len(completed_matches) if completed_matches else 0, 'total_bots': len(bots) if bots else 0, 'bracket': bracket, 'format': FORMATS.get(bracket.format_code) }) generate_form.weightclass.choices = weightclass_choices context = { 'event_brackets': brackets, 'event': event, 'generate_form': generate_form, 'weightclasses': weightclasses } self.render_response('brackets.html', **context)
def creer_tour(self, indice_de_tour): """ Méthode permettant de créer un tour """ nom = f"Round {indice_de_tour + 1}" dico = { 'nom': nom, 'date_heure_debut': util.encode_date_heure(datetime.now()), 'date_heure_fin': '9999-12-31T12:00:00' } tour = Tour(**dico) tour.liste_de_matchs = [ Match(*paire_de_joueurs) for paire_de_joueurs in self.generer_paires_de_joueurs(indice_de_tour) ] self._liste_de_tours.append(tour) for match in tour.liste_de_matchs: cle = f"{match.paire_de_joueurs[0].id} " cle += f"{match.paire_de_joueurs[1].id}" self._matchs_deja_joues[cle] = 1
def detect_faces(self): headers = { 'Content-Type': 'application/octet-stream', 'Ocp-Apim-Subscription-Key': AzureConfig.KEY, } params = urllib.urlencode({ 'returnFaceId': 'true', 'returnFaceLandmarks': 'false', }) # Sending a post request to obtain all of the face ids and face rectangles in the image image = open(self.path, 'rb') response = requests.post(Image.DETECT_URL % params, data=image, headers=headers) # Constructing all of the image's matches' matches = [] for match in response.json(): matches.append(Match(match['faceId'], match['faceRectangle'], self)) return matches
def matches_post(): post_json = request.get_json() new_match = Match(game_id=post_json["game_id"], date=post_json["date"]) db.session.add(new_match) db.session.commit() if "winner_ids" in post_json.keys(): for winner_id in post_json["winner_ids"]: new_play = Play( match_id=new_match.match_id, player_id=winner_id, did_win=True ) db.session.add(new_play) db.session.commit() if "non_winner_ids" in post_json.keys(): for non_winner_id in post_json["non_winner_ids"]: new_play = Play( match_id=new_match.match_id, player_id=non_winner_id, did_win=False ) db.session.add(new_play) db.session.commit() return jsonify(match_dict(new_match)), 201
def get(self, event_id): event = Event.get_by_id(event_id) if not event: self.redirect(uri_for('home')) weightclasses = Weightclass.get_by_event(event_id) generate_form = GenerateBracketForm() weightclass_choices = [] brackets = {} for weightclass in weightclasses: bots = Bot.get_by_weightclass_registered(weightclass.code, event.id) if len(bots) > 1: weightclass_choices.append((weightclass.code, '%s (%d bots)' % (weightclass.name, len(bots)))) brackets[weightclass.name] = [] weightclass_brackets = Bracket.get_by_event_and_class(event_id, weightclass.code) for bracket in weightclass_brackets: matches = Match.get_by_bracket(bracket.id) completed_matches = [match for match in matches if match.winning_bot_id] bots = Bot.get_by_bracket(bracket.id) brackets[weightclass.name].append({ 'total_matches': len(matches) if matches else 0, 'completed_matches': len(completed_matches) if completed_matches else 0, 'total_bots': len(bots) if bots else 0, 'bracket': bracket, 'format': FORMATS.get(bracket.format_code) }) generate_form.weightclass.choices = weightclass_choices context = { 'event_brackets': brackets, 'event': event, 'generate_form': generate_form, 'weightclasses': weightclasses } self.render_response('brackets.html', **context)
def generate(self, seeding=None): """ generate the bracket """ # find all registered bots in the given class bots = Bot.get_by_weightclass_registered(self.weightclass_code, self.event_id, order="id") # defines the order for matches to spread out the byes better, probably a formula for this but didn't take time to figure it out match_ordering = { 2: [1, 2], 4: [1, 3, 2, 4], 8: [1, 8, 5, 4, 3, 6, 7, 2], 16: [1, 16, 9, 8, 5, 12, 13, 4, 3, 14, 11, 6, 7, 10, 15, 2] } # need at least 2 bots to generate a chart if (len(bots) < 2): return False # manual seeding, if passed in (is dumb, assumes # of seeds matches # of bots) if seeding: for i, bot_id in enumerate(seeding): bot = Bot.get_by_id(bot_id) bot.seed_number = i bot.bracket_id = self.id bot.put() else: # generate a random array for the seeding seeds = range(0, len(bots)) shuffle(seeds) # assign the seeds for i, bot in enumerate(bots): bot.seed_number = seeds[i] bot.bracket_id = self.id bot.put() # generate matches if self.format_code.upper() != 'ROUNDROBIN': chart_size = 2 # find the first power of 2 higher than the number of bots in the bracket, this is our chart size num_rounds = 1 while (len(bots) > chart_size): chart_size *= 2 num_rounds += 1 # create first round matches, do our best to avoid a team fighting itself first round # will regenerate up to 5 times until it gives up on avoiding first round team fighting self for _ in xrange(0, 5): matches = [] for i in xrange(0, chart_size / 2): bot1_seed = i bot2_seed = chart_size - 1 - i bot1 = Bot.get_by_bracket_seed(self.event_id, self.id, bot1_seed) bot2 = Bot.get_by_bracket_seed(self.event_id, self.id, bot2_seed) bot1_id = bot1.id bot2_id = bot2.id if bot2 else 0 match = Match(number=match_ordering[chart_size / 2][i], bracket_id=self.id, bracket_side="A", round="A", bot1_id=bot1_id, bot2_id=bot2_id) matches.append(match) conflict = False for match in matches: if match.bot1_id > 0 and match.bot2_id > 0: bot1 = Bot.get_by_id(match.bot1_id) bot2 = Bot.get_by_id(match.bot2_id) if bot1.team_name == bot2.team_name: conflict = True break if not conflict: break [match.put() for match in matches] # create the rest of the A side matches, one round at a time for i in xrange(2, num_rounds + 1): round_letter = chr(63 + (2 * i)) #A,C,E etc for j in xrange(1, chart_size / pow(2, i) + 1): bot1_source = 'W%s%d' % (chr(63 + (2 * i) - 2), (j * 2 - 1) ) # ie WA1 (Winner of A1) bot2_source = 'W%s%d' % (chr(63 + (2 * i) - 2), (j * 2)) match = Match(number=j, bracket_id=self.id, bracket_side="A", round=round_letter, bot1_source_match=bot1_source, bot2_source_match=bot2_source) match.put() # generate B side matches, if necessary if self.format_code.upper( ) == 'DOUBLEELIM' or self.format_code.upper() == 'DOUBLETRUE': num_b_rounds = num_rounds * 2 - 1 for i in xrange(2, num_b_rounds + 1): round_letter = chr(62 + (2 * i)) round_size = int(chart_size / pow(2, math.floor( (i + 2) / 2))) for j in xrange(1, round_size + 1): if i == 2: # only case where a loser moves into bot1 spot bot1_source = 'LA%d' % (j * 2 - 1) bot2_source = 'LA%d' % (j * 2) else: if i % 2 == 1: # means this round's bot2 is sourced from A side # losing source bots need to be from opposite side of chart as to prevent rematches bot1_source = 'W%s%d' % (chr(60 + (2 * i)), j) bot2_source = 'L%s' % (chr(64 + i)) # match order depends how far into B side we are # 3 possibilities: normal, reverse, half shift if i % 7 == 0: # normal bot2_source = '%s%d' % (bot2_source, j) elif i % 5 == 0: # half shift if j < round_size / 2: bot2_source = '%s%d' % ( bot2_source, math.ceil((round_size / 2) + j)) else: bot2_source = '%s%d' % ( bot2_source, math.ceil((0 - (round_size / 2)) + j)) else: # reverse bot2_source = '%s%d' % (bot2_source, round_size + 1 - j) else: bot1_source = 'W%s%d' % (chr(60 + (2 * i)), (j * 2 - 1)) bot2_source = 'W%s%d' % (chr(60 + (2 * 1)), (j * 2)) match = Match(number=j, bracket_id=self.id, bracket_side="B", round=round_letter, bot1_source_match=bot1_source, bot2_source_match=bot2_source) match.put() # insert final A-side match round_letter = chr(63 + (2 * (num_rounds + 1))) bot1_source = 'W%s1' % chr(63 + (2 * num_rounds)) bot2_source = 'W%s1' % chr(60 + (2 * (num_b_rounds + 1))) match = Match(number=1, bracket_id=self.id, bracket_side="A", round=round_letter, bot1_source_match=bot1_source, bot2_source_match=bot2_source) match.put() matches_to_update = Match.get_by_bracket_round(self.id, 'A') for match in matches_to_update: match.check() else: #ROUNDROBIN bot_index = 1 # start at 1 because bot0 can't fight bot0 etc for bot in bots: match_index = 1 for i in xrange(bot_index, len(bots)): match = Match(number=match_index, round=chr(64 + bot_index), bracket_id=self.id, bracket_side="A", bot1_id=bot.id, bot2_id=bots[i].id) match.put() match_index += 1 bot_index += 1 return True
from collections import Counter import app.aggregators.mixed as mixed_games_aggregator from app.constants.outcome import Outcome from app.helpers.aggregation import combine_aggregations from app.models.match import Match from tests.testing_helper import get_empty_match match1 = Match(get_empty_match()) match2 = Match(get_empty_match()) match3 = Match(get_empty_match()) match4 = Match(get_empty_match()) match5 = Match(get_empty_match()) match6 = Match(get_empty_match()) def test_double_win(): match1.outcome1stHalf = Outcome.HOME_WIN match1.outcome2ndHalf = Outcome.HOME_WIN match2.outcome1stHalf = Outcome.AWAY_WIN match2.outcome2ndHalf = Outcome.AWAY_WIN match3.outcome1stHalf = Outcome.AWAY_WIN match3.outcome2ndHalf = Outcome.AWAY_WIN final_aggregation = compute_aggregation(match1, match2, match3) assert final_aggregation['double-win-t1'] == 1 assert final_aggregation['double-win-t2'] == 2
def get_users(): matches = Match.objects().all() return jsonify({'elements': [element.get_data() for element in matches]})
def generate(self, seeding=None): """ generate the bracket """ # find all registered bots in the given class bots = Bot.get_by_weightclass_registered(self.weightclass_code, self.event_id, order="id") # defines the order for matches to spread out the byes better, probably a formula for this but didn't take time to figure it out match_ordering = { 2: [1, 2], 4: [1, 3, 2, 4], 8: [1, 8, 5, 4, 3, 6, 7, 2], 16: [1, 16, 9, 8, 5, 12, 13, 4, 3, 14, 11, 6, 7, 10, 15, 2] } # need at least 2 bots to generate a chart if(len(bots) < 2): return False # manual seeding, if passed in (is dumb, assumes # of seeds matches # of bots) if seeding: for i, bot_id in enumerate(seeding): bot = Bot.get_by_id(bot_id) bot.seed_number = i bot.bracket_id = self.id bot.put() else: # generate a random array for the seeding seeds = range(0, len(bots)) shuffle(seeds) # assign the seeds for i, bot in enumerate(bots): bot.seed_number = seeds[i] bot.bracket_id = self.id bot.put() # generate matches if self.format_code.upper() != 'ROUNDROBIN': chart_size = 2 # find the first power of 2 higher than the number of bots in the bracket, this is our chart size num_rounds = 1 while(len(bots) > chart_size): chart_size *= 2 num_rounds += 1 # create first round matches, do our best to avoid a team fighting itself first round # will regenerate up to 5 times until it gives up on avoiding first round team fighting self for _ in xrange(0,5): matches = [] for i in xrange(0, chart_size/2): bot1_seed = i bot2_seed = chart_size - 1 - i bot1 = Bot.get_by_bracket_seed(self.event_id, self.id, bot1_seed) bot2 = Bot.get_by_bracket_seed(self.event_id, self.id, bot2_seed) bot1_id = bot1.id bot2_id = bot2.id if bot2 else 0 match = Match(number=match_ordering[chart_size/2][i], bracket_id=self.id, bracket_side="A", round="A", bot1_id=bot1_id, bot2_id=bot2_id) matches.append(match) conflict = False for match in matches: if match.bot1_id > 0 and match.bot2_id > 0: bot1 = Bot.get_by_id(match.bot1_id) bot2 = Bot.get_by_id(match.bot2_id) if bot1.team_name == bot2.team_name: conflict = True break if not conflict: break [match.put() for match in matches] # create the rest of the A side matches, one round at a time for i in xrange(2, num_rounds+1): round_letter = chr(63+(2*i)) #A,C,E etc for j in xrange(1, chart_size/pow(2, i)+1): bot1_source = 'W%s%d' % (chr(63+(2*i)-2), (j*2-1)) # ie WA1 (Winner of A1) bot2_source = 'W%s%d' % (chr(63+(2*i)-2), (j*2)) match = Match(number=j, bracket_id=self.id, bracket_side="A", round=round_letter, bot1_source_match=bot1_source, bot2_source_match=bot2_source) match.put() # generate B side matches, if necessary if self.format_code.upper() == 'DOUBLEELIM' or self.format_code.upper() == 'DOUBLETRUE': num_b_rounds = num_rounds * 2 - 1 for i in xrange(2, num_b_rounds + 1): round_letter = chr(62+(2*i)) round_size = int(chart_size/pow(2, math.floor((i+2)/2))) for j in xrange(1, round_size+1): if i==2: # only case where a loser moves into bot1 spot bot1_source = 'LA%d' % (j*2-1) bot2_source = 'LA%d' % (j*2) else: if i%2 == 1: # means this round's bot2 is sourced from A side # losing source bots need to be from opposite side of chart as to prevent rematches bot1_source = 'W%s%d' % (chr(60+(2*i)), j) bot2_source = 'L%s' % (chr(64+i)) # match order depends how far into B side we are # 3 possibilities: normal, reverse, half shift if i%7 == 0: # normal bot2_source = '%s%d' % (bot2_source, j) elif i%5 == 0: # half shift if j < round_size/2: bot2_source = '%s%d' % (bot2_source, math.ceil((round_size/2) + j)) else: bot2_source = '%s%d' % (bot2_source, math.ceil((0-(round_size/2))+j)) else: # reverse bot2_source = '%s%d' % (bot2_source, round_size + 1 - j) else: bot1_source = 'W%s%d' % (chr(60+(2*i)), (j*2-1)) bot2_source = 'W%s%d' % (chr(60+(2*1)), (j*2)) match = Match(number=j, bracket_id=self.id, bracket_side="B", round=round_letter, bot1_source_match=bot1_source, bot2_source_match=bot2_source) match.put() # insert final A-side match round_letter = chr(63+(2*(num_rounds+1))) bot1_source = 'W%s1' % chr(63+(2*num_rounds)) bot2_source = 'W%s1' % chr(60+(2*(num_b_rounds+1))) match = Match(number=1, bracket_id=self.id, bracket_side="A", round=round_letter, bot1_source_match=bot1_source, bot2_source_match=bot2_source) match.put() matches_to_update = Match.get_by_bracket_round(self.id, 'A') for match in matches_to_update: match.check() else: #ROUNDROBIN bot_index = 1 # start at 1 because bot0 can't fight bot0 etc for bot in bots: match_index = 1 for i in xrange(bot_index, len(bots)): match = Match(number=match_index, round=chr(64+bot_index), bracket_id=self.id, bracket_side="A", bot1_id=bot.id, bot2_id=bots[i].id) match.put() match_index += 1 bot_index += 1 return True
def get(self, event_id, bracket_id): event = Event.get_by_id(event_id) bracket = Bracket.get_by_id(bracket_id) weightclass = Weightclass.get_by_code(bracket.weightclass_code) format = FORMATS.get(bracket.format_code) matches = Match.get_by_bracket(bracket_id) bots = Bot.get_by_bracket(bracket_id) bots.sort(key=lambda x: x.id) if bracket.manual_seed and not bracket.generated: self.redirect(uri_for('manual-seed', event_id=event_id, bracket_id=bracket.id)) for match in matches: match.populate_bot_entities() ordered_matches = {'A': []} rounds = {'A': []} a_final_round = None b_final_round = None a_winner = None b_winner = None final_round = None margin_top = None if bracket.format_code != ROUND_ROBIN: if bracket.format_code == DOUBLE_ELIMINATION: ordered_matches['B'] = [] rounds['B'] = [] for match in matches: ordered_matches[match.bracket_side].append(match) # sort A side matches ascending by round, match number ordered_matches['A'] = sorted(ordered_matches['A'], key=attrgetter('round', 'number')) number_first_round_matches = sum(1 for m in ordered_matches['A'] if m.round == 'A') if bracket.format_code == SINGLE_ELIMINATION: a_final_round = chr(65+int((2*math.log(number_first_round_matches, 2)))) final_round = chr(67+int((2*math.log(number_first_round_matches, 2)))) else: a_final_round = chr(67+int((2*math.log(number_first_round_matches, 2)))) final_round = chr(69+int((2*math.log(number_first_round_matches, 2)))) a_winner = ordered_matches['A'][-1].winning_bot_id a_winner = Bot.get_by_id(a_winner) if a_winner else None if ordered_matches.get('B'): # sort B side matches desc by round, match number ordered_matches['B'] = sorted(ordered_matches['B'], key=attrgetter('round', 'number'), reverse=True) b_final_round = chr(66+int((4*(math.log(number_first_round_matches,2))))) for match in ordered_matches.get('B'): if match.round not in rounds['B']: rounds['B'].append(match.round) # determine b side winner, if applicable b_winner = ordered_matches['B'][0].winning_bot_id b_winner = Bot.get_by_id(b_winner) if b_winner else None for match in ordered_matches.get('A'): if match.round not in rounds['A']: rounds['A'].append(match.round) else: # don't care for round robin about sort ordered_matches['A'] = matches number_first_round_matches = sum(1 for m in ordered_matches['A'] if m.round == 'A') if bracket.format_code != SINGLE_ELIMINATION: if number_first_round_matches <= 4: margin_top = "0px" elif number_first_round_matches <= 8: margin_top = "-50px" elif number_first_round_matches <= 16: margin_top = "-150px" elif number_first_round_matches <= 32: margin_top = "-400px" else: margin_top = "0px" context = { 'format': format, 'bracket': bracket, 'weightclass': weightclass, 'matches': ordered_matches, 'rounds': rounds, 'a_final_round': a_final_round, 'b_final_round': b_final_round, 'final_round': final_round, 'a_winner': a_winner, 'b_winner': b_winner, 'number_first_round_matches': number_first_round_matches, 'margin_top': margin_top, 'event': event, 'bots': bots } self.render_response('single-bracket.html', **context)
from tests.testing_helper import get_empty_match from app.models.match import Match from app.constants.outcome import Outcome import app.helpers.outcome as oh match = Match(get_empty_match()) """Tests if expected outcome is equal to actual outcome""" def test_if_outcome_comparison_is_correct(): match.finalOutcome = Outcome.HOME_WIN assert oh.compare(match.finalOutcome, Outcome.HOME_WIN) == 1 def test_if_outcome_comparison_is_not_correct(): match.finalOutcome = Outcome.HOME_WIN assert oh.compare(match.finalOutcome, Outcome.AWAY_WIN) == 0 """Test if double chance matches the expected outcomes""" def test_if_double_chance_comparison_is_correct(): match.finalOutcome = Outcome.HOME_WIN assert oh.double_chance(match.finalOutcome, Outcome.HOME_WIN, Outcome.DRAW) == 1 def test_if_double_chance_comparison_is_not_correct(): match.finalOutcome = Outcome.AWAY_WIN assert oh.double_chance(match.finalOutcome, Outcome.HOME_WIN, Outcome.DRAW) == 0
import app.aggregators.team_goals as team_goals_aggregator from app.helpers.aggregation import combine_aggregations from app.models.match import Match from collections import Counter from tests.testing_helper import get_empty_match match1 = Match(get_empty_match()) match2 = Match(get_empty_match()) def test_both_teams_score(): match1.homeTeamGoals = 2 match1.awayTeamGoals = 3 match2.homeTeamGoals = 0 match2.awayTeamGoals = 1 final_aggregation = compute_both_teams_aggregation(match1, match2) assert final_aggregation['gg'] == 1 def test_one_team_did_not_score(): match1.homeTeamGoals = 0 match1.awayTeamGoals = 3 match2.homeTeamGoals = 0 match2.awayTeamGoals = 1 final_aggregation = compute_both_teams_aggregation(match1, match2) assert final_aggregation['ng'] == 2
from tests.testing_helper import get_empty_match from app.models.match import Match import app.helpers.goals as gh actual_match = Match(get_empty_match()) """Goals sum""" def test_goal_sum_is_equal_or_greater_than_expected_sum(): actual_match.homeTeamGoals = 2 actual_match.awayTeamGoals = 1 match_goals_sum = actual_match.homeTeamGoals + actual_match.awayTeamGoals assert gh.compare_sums(match_goals_sum, 3) == 1 def test_goal_sum_is_not_equal_or_greater_than_expected_sum(): actual_match.homeTeamGoals = 0 actual_match.awayTeamGoals = 1 match_goals_sum = actual_match.homeTeamGoals + actual_match.awayTeamGoals assert gh.compare_sums(match_goals_sum, 2) == 0 """Goals sum exact""" def test_goal_sum_is_exact_the_expected_sum(): actual_match.homeTeamGoals = 2 actual_match.awayTeamGoals = 1 match_goals_sum = actual_match.homeTeamGoals + actual_match.awayTeamGoals assert gh.compare_sums(match_goals_sum, 3, is_exact=True) == 1
def get(self, event_id, bracket_id): event = Event.get_by_id(event_id) bracket = Bracket.get_by_id(bracket_id) weightclass = Weightclass.get_by_code(bracket.weightclass_code) format = FORMATS.get(bracket.format_code) matches = Match.get_by_bracket(bracket_id) bots = Bot.get_by_bracket(bracket_id) bots.sort(key=lambda x: x.id) if bracket.manual_seed and not bracket.generated: self.redirect( uri_for('manual-seed', event_id=event_id, bracket_id=bracket.id)) for match in matches: match.populate_bot_entities() ordered_matches = {'A': []} rounds = {'A': []} a_final_round = None b_final_round = None a_winner = None b_winner = None final_round = None margin_top = None if bracket.format_code != ROUND_ROBIN: if bracket.format_code == DOUBLE_ELIMINATION: ordered_matches['B'] = [] rounds['B'] = [] for match in matches: ordered_matches[match.bracket_side].append(match) # sort A side matches ascending by round, match number ordered_matches['A'] = sorted(ordered_matches['A'], key=attrgetter('round', 'number')) number_first_round_matches = sum(1 for m in ordered_matches['A'] if m.round == 'A') if bracket.format_code == SINGLE_ELIMINATION: a_final_round = chr(65 + int( (2 * math.log(number_first_round_matches, 2)))) final_round = chr(67 + int( (2 * math.log(number_first_round_matches, 2)))) else: a_final_round = chr(67 + int( (2 * math.log(number_first_round_matches, 2)))) final_round = chr(69 + int( (2 * math.log(number_first_round_matches, 2)))) a_winner = ordered_matches['A'][-1].winning_bot_id a_winner = Bot.get_by_id(a_winner) if a_winner else None if ordered_matches.get('B'): # sort B side matches desc by round, match number ordered_matches['B'] = sorted(ordered_matches['B'], key=attrgetter( 'round', 'number'), reverse=True) b_final_round = chr(66 + int( (4 * (math.log(number_first_round_matches, 2))))) for match in ordered_matches.get('B'): if match.round not in rounds['B']: rounds['B'].append(match.round) # determine b side winner, if applicable b_winner = ordered_matches['B'][0].winning_bot_id b_winner = Bot.get_by_id(b_winner) if b_winner else None for match in ordered_matches.get('A'): if match.round not in rounds['A']: rounds['A'].append(match.round) else: # don't care for round robin about sort ordered_matches['A'] = matches number_first_round_matches = sum(1 for m in ordered_matches['A'] if m.round == 'A') if bracket.format_code != SINGLE_ELIMINATION: if number_first_round_matches <= 4: margin_top = "0px" elif number_first_round_matches <= 8: margin_top = "-50px" elif number_first_round_matches <= 16: margin_top = "-150px" elif number_first_round_matches <= 32: margin_top = "-400px" else: margin_top = "0px" context = { 'format': format, 'bracket': bracket, 'weightclass': weightclass, 'matches': ordered_matches, 'rounds': rounds, 'a_final_round': a_final_round, 'b_final_round': b_final_round, 'final_round': final_round, 'a_winner': a_winner, 'b_winner': b_winner, 'number_first_round_matches': number_first_round_matches, 'margin_top': margin_top, 'event': event, 'bots': bots } self.render_response('single-bracket.html', **context)