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
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)
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")
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
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