Пример #1
0
def latest_matches(uid = None, cid = None, limit = 8):
    query = {}

    if uid:
        query['users'] =  { '$elemMatch': { 'uid': uid } }

    if cid:
        query['cid'] = cid

    matches = list( mongodb.matches.find(query).sort([('datetime', -1)]).limit(limit) )
    challenges = list( mongodb.challenges.find({ 'cid': { '$in': [ match['cid'] for match in matches ] } }) )
    users = list( mongodb.users.find({ 'uid': { '$in': [ user['uid'] for user in chain.from_iterable(match['users'] for match in matches) ] } }) )
    username_for_given_uid = ([user['username'] for user in users if user['uid'] == uid] or [None])[0]
    # Maybe we should be using SQL :)

    latest = []

    for match in matches:
        match['challenge_name'] = next( challenge['name'] for challenge in challenges if challenge['cid'] == match['cid'] )
        match['usernames'] = [ user['username'] for user in users if user['uid'] in [match_user['uid'] for match_user in match['users']] ]
        match['opponents'] = [ username for username in match['usernames'] if username != username_for_given_uid ]

        time_delta = datetime.datetime.utcnow() - match['datetime']
        match['time_since'] = time_since_from_seconds( time_delta.total_seconds() )

        latest.append(match)

    return latest
Пример #2
0
def match(mid):
    """
    Page to visualize a match.
    """
    match = mongodb.matches.find_one({ 'mid': mid })
    if not match:
        abort(404)

    challenge = mongodb.challenges.find_one({ 'cid': match['cid'] })

    if not challenge:
        raise Exception("Couldn't find a challenge with cid " + match['cid'])

    users = list(mongodb.users.find({'uid': {'$in': [user['uid'] for user in match['users']]}}))
    users_dict = {user['uid']: user for user in users}

    time_delta = datetime.datetime.utcnow() - match['datetime']
    match['time_since'] = time_since_from_seconds(time_delta.total_seconds())
    match['challenge_name'] = challenge['name']
    match['visualizer'] = challenge['visualizer']
    match['usernames'] = [users_dict[user['uid']]['username'] for user in match['users']]

    if match['challenge_name'] == 'Wumpus':
        match['winner'] = 'Score: ' + str(match['users'][0]['rank'])
    else:
        if match['users'][0]['rank'] == 1 and match['users'][1]['rank'] == 2:
            match['winner'] = 'Winner: ' + match['usernames'][0]
        elif match['users'][0]['rank'] == 2 and match['users'][1]['rank'] == 1:
            match['winner'] = 'Winner: ' + match['usernames'][1]
        else: 
            match['winner'] = 'Tie!'

    match['users'] = users

    # Checking for errors
    if 'errors' in match:
        errors = match['errors']
        culprits = []
        if 'server' in errors:
            culprits.append('on the server')
            errors.remove('server')
        culprits.extend([('on the %s solution' % users_dict[uid]['username']) for uid in errors])
        if len(culprits) > 1:
            s = ', '.join(culprits[:-1]) + ' and ' + culprits[-1]
        else:
            s = culprits[0]
        match['error_message'] = 'There was an error %s during this match.' % s
    else:
        match['error_message'] = None

    custom_title = ' vs '.join(match['usernames']) + ' on ' + match['challenge_name']

    return render_template('match.html', match = match, custom_title = custom_title)
Пример #3
0
def group(gid):
    """
    Page to display a group given a gid.
    """
    group = mongodb.groups.find_one({'gid': gid})
    if not group or ( user.username not in group['admins'] and group['admin_only'] ):
        abort(404)

    playForm = PlayForm(csrf_enabled = False, prefix = 'playForm')
    tournamentForm = TournamentForm(csrf_enabled = False, prefix = 'tournamentForm') 
    
    user_id = user.custom_data['uid']

    group_users = list()
    for player in group['users']:
        user_in_db = mongodb.users.find_one({ 'username': player})
        uid = user_in_db['uid']
        name = player

        if group['users_name_type'] == 'full_name':
            # In case the user don't have a full name (old users)
            if 'given_name' in user_in_db and 'surname' in user_in_db:
                name = user_in_db['given_name'] + ' ' + user_in_db['surname']

        # We are considering that players can't play against themselves
        if uid != user_id:
            group_users.append((uid, name))

    limit = 5
    tournaments = list( mongodb.tournaments.find({ 'gid': group['gid']}).sort('datetime_started', pymongo.DESCENDING).limit(limit) )

    challenges = list( mongodb.challenges.find({}) )
    challenges_choices = [(challenge['cid'], challenge['name']) for challenge in challenges]

    for tournament in tournaments:
        time_delta = datetime.datetime.utcnow() - tournament['datetime_started']
        tournament['time_since'] = time_since_from_seconds( time_delta.total_seconds() )

    # Populating playForm drop down lists
    playForm.challenge.choices = challenges_choices
    playForm.player.choices = group_users

    # Populating tournamentForm drop down lists
    tournamentForm.challenge.choices = challenges_choices
    tournamentForm.player1.choices = group_users
    tournamentForm.player2.choices = group_users

    if request.method == 'GET':
        playForm.rounds.data = 1

        tournamentForm.rounds.data = 1
        tournamentForm.all_play.data = False

        return render_template('group.html', group = group, playForm = playForm, tournamentForm = tournamentForm, tournaments = tournaments)

    if playForm.is_submitted() and playForm.form_type.data == "play":
        if playForm.validate():
            rounds = playForm.rounds.data
            cid = playForm.challenge.data
            opponent = playForm.player.data
            challenge = mongodb.challenges.find_one({'cid': cid})

            if challenge['name'] == 'Wumpus':
                error = play(cid = cid, uids = [user_id], rounds = rounds)
            else:
                error = play(cid = cid, uids = [user_id, opponent], rounds = rounds)

            if error:
                return render_template('group.html', group = group, playForm = playForm, tournamentForm = tournamentForm, error = error)

            return redirect(url_for('.matches'))
        else:
            field, errors = playForm.errors.items()[0]
            error = playForm[field].label.text + ': ' + ', '.join(errors)
            return render_template('group.html', group = group, playForm = playForm, tournamentForm = tournamentForm, tournaments = tournament, error = error)


    if tournamentForm.is_submitted() and tournamentForm.form_type.data == 'tournament':
        if tournamentForm.validate():
            rounds = tournamentForm.rounds.data
            cid = tournamentForm.challenge.data
            player1 = tournamentForm.player1.data
            player2 = tournamentForm.player2.data
            all_play = tournamentForm.all_play.data
            challenge = mongodb.challenges.find_one({'cid': cid})

            if all_play:

                if challenge['name'] != 'Wumpus' and len(group['users']) < 2:
                    error = 'This group needs at least one more user to held a tournament with this challenge'
                    return render_template('group.html', group = group, playForm = playForm, tournamentForm = tournamentForm, error = error)

                allPlay(cid = cid, rounds = rounds, group = group, challenge_name = challenge['name'])
                return redirect(url_for('.matches'))

            if challenge['name'] == 'Wumpus':
                error = play(cid = cid, uids = [player1], rounds = rounds)
            else:
                error = play(cid = cid, uids = [player1, player2], rounds = rounds)

            if error:
                return render_template('group.html', group = group, playForm = playForm, tournamentForm = tournamentForm, error = error)

            return redirect(url_for('.matches'))
        else:
            field, errors = tournamentForm.errors.items()[0]
            error = tournamentForm[field].label.text + ': ' + ', '.join(errors)
            return render_template('group.html', group = group, playForm = playForm, tournamentForm = tournamentForm, tournaments = tournaments, error = error)

    # Should never reach this line, since either the method is GET, either it's POST.
    # If it's POST, then either one of the forms has been submitted.
    raise Exception("Should never reach this line")
Пример #4
0
def replay(params):
    """
    Replays the specified match log. If no log is given, the latest is replayed.
    Parameters: [<match_log>]

    <match_log> - If given, the log to replay. Must have a standard log name.
    """

    # Requirements

    if len(params) > 1:
        logger.err("Wrong number of parameters\n")
        help(["replay"])
        return 1

    # Command execution

    # Choosing match log depending on parameters
    if len(params) == 1:
        match_log = params[0]
        if not path.isfile(match_log):
            logger.err("Could not find match log '%s'" % match_log)
            return 1
        if not log_filename_regex.match(match_log.split(os.sep)[-1]):
            logger.err("The given match_log doesn't match the standard name")
            return 1
    else:
        possibilities = glob(path.join(SOLUTIONSDIR, "*", "logs", "*.log"))
        if not possibilities:
            logger.warn("No logs found")
            return 1

        match_log = max(possibilities, key=path.getctime)
        logger.info("Latest match log found: %s" % match_log)

    # Generating HTML
    if path.isfile(match_log + ".html"):
        logger.info("Html already generated")
    else:
        m = log_filename_regex.match(match_log.split(os.sep)[-1])
        if not m:
            logger.err("Found a log with a strange name: %s" %
                       match_log.split(os.sep)[-1])
            return 1

        logger.info("Generating html...")

        # Getting parameters
        timestamp = datetime(*map(int, m.groups()[:6]))
        solution_names = m.group(7).split(":")[1:]
        challenge_name = path.dirname(path.abspath(match_log)).split("/")[-2]

        values = {
            "match": {
                "challenge_name":
                challenge_name[0].upper() + challenge_name[1:],
                "solution_names":
                solution_names,
                "time_since":
                time_since_from_seconds(
                    (datetime.now() - timestamp).total_seconds()),
                "solutions": [{
                    "id": "p%d" % (idx + 1),
                    "name": solution
                } for idx, solution in enumerate(solution_names)],
                "visualizer":
                challenge_name + ".js",
                "log_json":
                open(match_log, "r").read().strip(),
            },
            "mjollnir_assets": "/MjollnirAssets",
        }

        # Creating html from jinja template
        with open(match_log + ".html", "w") as result:
            result.write(
                jinja.get_template("replay_template.html").render(values))

    logger.info("Opening firefox...")
    Popen(["firefox", match_log + ".html"])

    return 0
Пример #5
0
def replay(params):
    """
    Replays the specified match log. If no log is given, the latest is replayed.
    Parameters: [<match_log>]

    <match_log> - If given, the log to replay. Must have a standard log name.
    """

    # Requirements

    if len(params) > 1:
        logger.err("Wrong number of parameters\n")
        help(["replay"])
        return 1

    # Command execution

    # Choosing match log depending on parameters
    if len(params) == 1:
        match_log = params[0]
        if not path.isfile(match_log):
            logger.err("Could not find match log '%s'" % match_log)
            return 1
        if not log_filename_regex.match(match_log.split(os.sep)[-1]):
            logger.err("The given match_log doesn't match the standard name")
            return 1
    else:
        possibilities = glob(path.join(SOLUTIONSDIR, "*", "logs", "*.log"))
        if not possibilities:
            logger.warn("No logs found")
            return 1

        match_log = max(possibilities, key=path.getctime)
        logger.info("Latest match log found: %s" % match_log)

    # Generating HTML
    if path.isfile(match_log + ".html"):
        logger.info("Html already generated")
    else:
        m = log_filename_regex.match(match_log.split(os.sep)[-1])
        if not m:
            logger.err("Found a log with a strange name: %s" % match_log.split(os.sep)[-1])
            return 1

        logger.info("Generating html...")

        # Getting parameters
        timestamp = datetime(*map(int, m.groups()[:6]))
        solution_names = m.group(7).split(":")[1:]
        challenge_name = path.dirname(path.abspath(match_log)).split("/")[-2]

        values = {
            "match": {
                "challenge_name": challenge_name[0].upper() + challenge_name[1:],
                "solution_names": solution_names,
                "time_since": time_since_from_seconds((datetime.now() - timestamp).total_seconds()),
                "solutions": [{"id": "p%d" % (idx+1), "name": solution} for idx, solution in enumerate(solution_names)],
                "visualizer": challenge_name + ".js",
                "log_json": open(match_log, "r").read().strip(),
            },
            "mjollnir_assets": "/MjollnirAssets",
        }

        # Creating html from jinja template
        with open(match_log + ".html", "w") as result:
            result.write(jinja.get_template("replay_template.html").render(values))

    logger.info("Opening firefox...")
    Popen(["firefox", match_log + ".html"])

    return 0