Source code for docs.hog_contest.main

import json
import os
from datetime import datetime, timedelta
from json import JSONDecodeError

from flask import Flask, abort, jsonify, render_template, request
from pytz import timezone

import tournament
from common.course_config import get_endpoint
from common.db import connect_db
from contest_utils.oauth import get_group
from contest_utils.rate_limiting import ratelimited
from logger import get_log, log
from process_input import record_strat
from tournament import build_ranking, run_tournament

app = Flask(__name__)

ASSIGNMENT = "proj01contest"

with connect_db() as db:
    db("CREATE TABLE IF NOT EXISTS accesses (email VARCHAR(128), last_access INTEGER)")
    db(
        """CREATE TABLE IF NOT EXISTS cached_strategies (
            email VARCHAR(128), name VARCHAR(1024), hash VARCHAR(128), strategy LONGBLOB
        )"""
    )
    db(
        "CREATE TABLE IF NOT EXISTS cached_winrates (hash_0 VARCHAR(128), hash_1 VARCHAR(128), winrate DOUBLE)"
    )


[docs]def expand_semester(short_form): """ Takes in a semester name in condensed notation (eg. sp21, fa20, su18) and expands it into a full version (eg. Spring 2021, Fall 2020, Summer 2018). :param short_form: condensed notation for a semester :type short_form: str :return: expanded notation for semester (str) """ return "{} 20{}".format( {"sp": "Spring", "su": "Summer", "fa": "Fall"}[short_form[:2]], short_form[2:] )
[docs]def semester_key(short_form): """ Construct a key from the SHORT_FORM of the semester :param short_form: condensed notation for a semester :type short_form: str :return: double representing a key value for the semester SHORT_FORM """ return int(short_form[2:]) + 0.2 * {"sp": 1, "su": 2, "fa": 3}[short_form[:2]]
@app.route("/") def index(): links = sorted( ( [x.split(".")[0], expand_semester(x.split(".")[0])] for x in os.listdir("data/leaderboards") ), key=lambda x: semester_key(x[0]), ) return render_template( "hog-template.html", timestamp=tournament.last_updated, ranking=tournament.ranking, team_list=[x[1] for x in tournament.ranking], winrate_mat=tournament.winrates, links=links, ) @app.route("/winners") def winners(): with open("data/winners.json") as f: old_winners = json.load(f) past_winners = [] for semester, winners in old_winners.items(): past_winners.append([expand_semester(semester), winners, semester]) past_winners.sort(key=lambda x: -semester_key(x[2])) return render_template("hog-winners.html", past_winners=past_winners) @app.route("/old_results/<semester>/") def old_results(semester): for datafile in os.listdir("data/leaderboards"): if datafile == semester + ".json": break else: abort(404) return with open(os.path.join("data/leaderboards", datafile)) as f: data = json.load(f) winrate_mat, teams = data["winrate_mat"], data["teams"] teams = [ (team, sum(score > tournament.THRESHOLD for score in team_scores)) for team, team_scores in zip(teams, winrate_mat) ] ranking = build_ranking(teams) return render_template( "hog-template.html", timestamp="the end of the tournament.", ranking=ranking, team_list=[x[1] for x in ranking], winrate_mat=winrate_mat, suffix="({})".format(expand_semester(semester)), ) @app.route("/log") def test(): return "<pre>{}</pre>".format(get_log()) @app.route("/api/submit_strategy", methods=["POST"]) @ratelimited(timedelta(minutes=1)) def submit_strategy(): curr_time = datetime.now().astimezone(timezone("US/Pacific")) end_time = datetime(2021, 2, 23, 23, 59, 0, tzinfo=timezone("US/Pacific")) if curr_time > end_time: abort(423, "The competition has ended.") try: strat = json.loads(request.form["strat"]) except JSONDecodeError: abort(400, "Received malformed JSON strategy") group = get_group(get_endpoint("cs61a") + f"/{ASSIGNMENT}") hashed = record_strat(request.form["name"], group, strat) run_tournament() log("New strategy received, tournament will restart after current match completes.") return jsonify({"success": True, "group": group, "hash": hashed}) log("Main thread starting. If this message is duplicated, something has gone wrong.") tournament.post_tournament() if __name__ == "__main__": app.run()