Exemple #1
0
    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)
Exemple #2
0
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)
Exemple #3
0
    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
Exemple #4
0
    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
Exemple #5
0
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)
Exemple #6
0
    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)
Exemple #7
0
    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
Exemple #8
0
    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)
Exemple #9
0
    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)
Exemple #10
0
    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