def post(self, event_id, bot_id): update_form = AddBotForm(self.request.POST) if update_form.validate(): bot_data = update_form.data del bot_data['id'] # don't want to update this, EVER bot_data['multibot_ind'] = 'Y' if bot_data['multibot_ind'] else 'N' bot = Bot.get_by_id(bot_id) bot.__dict__.update(bot_data) bot.put() response = { 'successful': True, 'message': json.dumps(bot.to_dict()) } else: response = { 'successful': False, 'message': json.dumps(update_form.errors) } context = { 'data': json.dumps(response) } self.render_response('json.json', **context)
def reset(current_user, workspaceId, projectId): """ Publish a playground Playground ID Is mandatory :return: Http Json response """ if request.content_type == 'application/json': playgroundId = request.get_json(force=True).get('playgroundId') if playgroundId: playground = Playground.get_by_id(playgroundId) if playground: bot = Bot.get_by_id(playground.parentMarketplaceBot) playgroundMeta = bot.botMeta playgroundMeta["mediaUrl"] = bot.marketplaceCardMediaUrl playgroundMeta["name"] = playground.playgroundMeta.get("name") playground.playgroundMeta = playgroundMeta playground.save() return response('success', 'playground reset successful', 200) else: return response('failed', 'playground not found', 404) else: return response( 'failed', 'Playground ID is required in the request payload.', 402) else: return response('failed', 'Content-type must be json', 402)
def populate_bot_entities(self): from app.models.bot import Bot # add bot1 and bot2 objects if self.bot1_id: self.bot1 = Bot.get_by_id(self.bot1_id) elif self.bot1_id == 0: self.bot1 = Bot.bye() else: self.bot1 = None if self.bot2_id: self.bot2 = Bot.get_by_id(self.bot2_id) elif self.bot2_id == 0: self.bot2 = Bot.bye() else: self.bot2 = None if self.winning_bot_id: self.winning_bot = Bot.get_by_id(self.winning_bot_id) else: self.winning_bot = None
def create(current_user, workspaceId, projectId): """ Create a playground. Reuires login """ if request.content_type == 'application/json': post_data = request.get_json(force=True) required_keys = ['botId', 'name'] if all(name in post_data for name in required_keys): bot = Bot.get_by_id( post_data.get('botId') ) # bot id is fronteous generated. bot is is for a specific # version of agent from dialogflow if not bot: return response('failed', 'Bot not found in the marketplace', 404) playgroundMeta = bot.botMeta playgroundMeta["mediaUrl"] = bot.marketplaceCardMediaUrl playgroundMeta["name"] = post_data.get("name") playground = Playground(playgroundType='bot', playgroundMeta=playgroundMeta, projectId=projectId, parentMarketplaceBot=bot._id, publishedServiceId=post_data.get( "name", None), createdBy=current_user.email_id) playground.create() # add to project # project = Project.get_by_id(projectId) # project.services.append(playground._id) # project.save() # Replcing _id with id playground_obj = json.loads(playground.to_json()) playground_obj['id'] = playground_obj['_id'] playground_obj.pop('_id', None) return response_with_obj('success', 'Playground created successfully', playground_obj, 200) else: return response('failed', 'Required data not found in POST body.', 402) return response('failed', 'Content-type must be json', 402)
def post(self, event_id, bot_id): bot = Bot.get_by_id(bot_id) if bot: result = bot.register() response = { 'successful': True if result == None else False, 'message': result } else: response = { 'successful': False, 'message': 'Invalid bot id %d' % bot_id } context = { 'data': json.dumps(response) } self.render_response('json.json', **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
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)
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)
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