Example #1
0
def unregister_for_competition(cid):
    """ Called when a user wants to unregister for a competition.

    All the user has to do is submit a post to this url with no form data.
    From their logged-in status, we'll go ahead and remove them from the
    competiton.

    Similar to the <code>/register</code> endpoint, an admin can post a list of
    users to unregister from the competition.
    """
    if session.query(Competition).filter(Competition.cid == cid).first() \
            is None:
        return serve_error('Competition does not exist', response_code=404)

    if current_user.admin == 1 and 'users' in request.data:
        try:
            registrants = loads(request.data['users'])
        except ValueError:
            return serve_error('JSON data for \'users\' not properly formatted',
                    response_code=400)
    else:
        registrants = [current_user.username]

    for user in registrants:
        (session.query(CompUser)
                .filter(CompUser.username == user, CompUser.cid == cid)
                .delete())
    session.flush()
    session.commit()

    return serve_response({})
Example #2
0
def put_competition_teams(cid):
    """ Update the teams for a competition

    If a user is an admin, they can update the competition's users, doing a PUT.
    This will take the JSON data in the 'teams' part of the request form and
    store it to the database. Any teams or users not included in the JSON data
    will not be a part of the competition and will have to re-register; however
    it should not be used for the solely purpose of de-registering participants.
    """
    try:
        teams = loads(request.form['teams'])
    except KeyError as err:
        return serve_error('You must include the parameter \'teams\'.',
                response_code=400)
    except ValueError:
        return serve_error('JSON data for \'teams\' not properly formatted',
                response_code=400)

    # Delete all of the old CompUser rows for this competition
    database.session.query(CompUser).filter(CompUser.cid == cid).delete()

    for team in teams:
        for user in teams[team]:
            database.session.add(
                CompUser(
                    cid=cid,
                    username=user,
                    team=team
                )
            )

    database.session.flush()
    database.session.commit()

    return serve_response({})
Example #3
0
def submit():
    """
    Retrieves the submission information from the request, creates a submission, then begins the submissions execution.
    The response simply returns an empty object for data. (In the future, this will return the handle to a web socket).

    :return: serves a 200 request code and an empty object if it is a good request, 403 if the filetype is unsupproted,
            400 if the required fields are missing.
    """

    uploaded_file = request.files['file']
    if not uploaded_file:
        return serve_error('file must be uploaded', response_code=400)
    if not judge.allowed_filetype(uploaded_file.filename):
        return serve_error('filename not allowed', response_code=403)
    if not request.form['pid']:
        return serve_error('the field \'pid\' must be specified', response_code=400)

    attempt = models.Submission(
        username=current_user.username,
        pid=request.form['pid'].lower(),
        submit_time=int(time.time()),
        auto_id=0,
        file_type=uploaded_file.filename.split('.')[-1].lower(),
        result='start')
    attempt.commit_to_session()
    thread = Thread(
        target=judge.evaluate, args=(attempt, uploaded_file))
    thread.daemon = False
    thread.start()
    return serve_response({
        'submissionId': attempt.job
    })
Example #4
0
def create_competition():
    data = request.form
    if current_user.admin == 0:
        return serve_error('Only admins can create competitions', 401)

    try:
        competition = Competition(
            name=data['name'],
            start=int(data['start_time']),
            stop=(int(data['start_time']) + int(data['length'])),
            closed=1 if bool(data['closed']) else 0
        )
        competition.commit_to_session()

        comp_problems = loads(data['problems'])
    except KeyError as err:
        return serve_error('You must specify name, startTime, length, and'
                ' problem attributes. ' + err[0] + ' not found.',
                response_code=400)
    except ValueError:
        return serve_error('JSON data for \'problems\' not properly formatted',
                response_code=400)

    for problem in comp_problems:
        session.add(CompProblem(
            label=problem['label'][:2],
            cid=competition.cid,
            pid=problem['pid']
        ))
    session.flush()
    session.commit()

    return serve_response(competition.to_dict())
Example #5
0
def register_for_competition(cid):
    """ Called when a user wants to register for a competition.

    All the user has to do is submit a post to this url with no form data.
    From their logged-in status, we'll go ahead and add them to the competiton
    as an individual (team name is default their display name). A 400 error
    will be returned if the user is already registered for the competition.

    If the user that is submitting this is an admin, they can optionally
    supply a json array of usernames to register for the competition.
    Specifying this will not register the admin, but it will register all users
    that are listed. A 400 error will be returned if any of the users are
    already registered for the competition.
    """
    if database.session.query(Competition).filter(
         Competition.cid == cid).first() is None:
        return serve_error('Competition does not exist', response_code=404)

    if current_user.admin == 1 and 'users' in request.form:
        try:
            registrants = loads(request.form['users'])
        except ValueError:
            return serve_error(
                'JSON data for \'users\' not properly formatted',
                response_code=400)
    else:
        registrants = [current_user.username]

    for user in registrants:
        if database.session.query(CompUser).filter(
            CompUser.cid == cid, CompUser.username == user
            ).first() is not None:
            return serve_error('User ' + user + ' already registered for '
                    'competition', response_code=400)

    for username in registrants:
        user = database.session.query(User).filter(
            User.username == user).first()
        database.session.add(
            CompUser(
                cid=cid,
                username=user.username,
                team=user.display
            )
        )
        Flasknado.emit('new_user', {
            'cid': cid,
            'user': {
                'display': user.display,
                'username': user.username
            }
        })
    database.session.flush()
    database.session.commit()

    return serve_response({})
Example #6
0
def submit():
    """
    Retrieves the submission information from the request, creates a submission,
    then begins the submissions execution. The response is simply a submission
    identifier of the new submission.

    :return: serves a 200 request code and an empty object if it is a good
            request, 403 if the filetype is unsupproted, 400 if the required
            fields are missing.
    """

    uploaded_file = request.files['file']
    if not uploaded_file:
        return serve_error('file must be uploaded', response_code=400)
    if not judge.allowed_filetype(uploaded_file.filename):
        return serve_error('filename not allowed', response_code=403)
    if not request.form['pid']:
        return serve_error('the field \'pid\' must be specified',
            response_code=400)

    # Obtain the time limit for the problem
    time_limit = session.query(ProblemData).\
            options(load_only("pid", "time_limit")).\
            filter(ProblemData.pid==request.form['pid']).\
            first().time_limit


    ext = uploaded_file.filename.split('.')[-1].lower()
    if 'python' in request.form:
        ext = request.form['python']

    attempt = models.Submission(
        username=current_user.username,
        pid=request.form['pid'],
        submit_time=int(time.time()),
        auto_id=0,
        file_type=ext,
        result='start')

    attempt.commit_to_session()

    directory = directory_for_submission(attempt)
    os.mkdir(directory)
    uploaded_file.save(os.path.join(directory, uploaded_file.filename))

    judge.Judge(attempt, uploaded_file, time_limit).run_threaded()

    return serve_response({
        'submissionId': attempt.job
    })
Example #7
0
def update_competition_data(cid):
    """ Adds problems to a competition

    Doing a POST request adds that problem to the competition whereas
    a PUT request will remove all problems that were previously associated
    with that competition and add all of the ones in the form body.

    TODO: form validation to make sure that no duplicates are added.
    """
    if current_user.admin == 0:
        # admins only
        return serve_error('Only admins can modify competitions', 401)

    data = request.form

    try:
        competition = session.query(Competition).filter(Competition.cid == cid)\
                .first()

        competition.name = data['name']
        competition.start=int(data['start_time'])
        competition.stop=(int(data['start_time']) + int(data['length']))
        competition.closed = 0 if bool(data['closed']) else 0
        competition.commit_to_session()

        # If the client sends a PUT request, we need to delete all of the old
        # problems associated with this competition
        session.query(CompProblem).filter(CompProblem.cid == cid).delete()

        comp_problems = loads(data['problems'])
    except KeyError as err:
        return serve_error('You must specify name, startTime, length, and'
                ' and problem attributes. ' + err[0] + ' not found.',
                response_code=400)
    except ValueError:
        return serve_error('JSON data for \'problems\' not properly formatted',
                response_code=400)

    for problem in comp_problems:
        session.add(CompProblem(
            label=problem['label'],
            cid=competition.cid,
            pid=problem['pid']
        ))

    session.flush()
    session.commit()
    return serve_response(competition.to_dict())
Example #8
0
def delete_competition(cid):
    """Delete a competition and all the data associated with it"""
    competition = (database.session.query(Competition)
                   .filter_by(cid=cid).first())

    if not competition:
        return serve_error('404: Competition not found', 404)

    # Delete the problems from a competition
    competition_problems = (database.session.query(CompProblem)
                            .filter_by(cid=cid).all())
    for competition_problem in competition_problems:
        database.session.delete(competition_problem)

    # Delete the users/tams from a competition
    competition_users = (database.session.query(CompUser)
                         .filter_by(cid=cid).all())
    for user in competition_users:
        database.session.delete(user)

    # Delete the competition itself
    database.session.delete(competition)
    database.session.commit()

    return serve_response('Successfully deleted', 204)
Example #9
0
def create_submission():
    try:
        project = (session.query(Project).filter(
            Project.project_id == int(request.form['project_id'])
            and Project.username == current_user.username).first())

        project.body = request.form['body']
        submission = Submission(username=current_user.username,
                                submit_time=int(time.time()),
                                type=project.type,
                                project_id=int(request.form['project_id']),
                                run=int(request.form['run']))
    except KeyError:
        return serve_error('Form data missing.')

    submission.commit_to_session()
    project.commit_to_session()

    Event.log(current_user.username, 'execute', submission.job)

    directory = directory_for_submission(submission.job)
    os.mkdir(directory)
    file_name = 'submit' + FILE_EXTENSIONS_FROM_TYPE[submission.type]
    source_file = open(os.path.join(directory, file_name), 'w')
    source_file.write(project.body)
    source_file.close()

    runner = Runner(submission, file_name)
    runner.run_queued()

    return serve_response({'job': submission.job})
Example #10
0
def get_one_blog_post(bid):
    """Retrieve a single blog post by its blog id (bid)"""
    post = database.session.query(BlogPost).filter(BlogPost.id == bid).first()
    if not post:
        return serve_error('No blog post id: ' + str(bid), 404)

    return serve_response(create_blog_object(post))
Example #11
0
def create_blog_post():
    if not current_user.admin == 1:
        return serve_error('You must be an admin to submit blog posts', response_code=401)
    if not request.form['title'] or not request.form['subtitle'] or not request.form['body']:
        return serve_error('Must include title, subtitle, and body with request', 
                           response_code=400)
    post = BlogPost(title=request.form['title'],
                    subtitle=request.form['subtitle'],
                    post_time=int(time()),
                    body=request.form['body'],
                    username=current_user.username)
    session.add(post)
    session.flush()
    session.commit()
    session.refresh(post)
    return serve_response(create_blog_object(post))
Example #12
0
def get_submits():
    """
    Return one or more submissions. Can be filtered by user or id, and limited
    to a specific number. Parameters are given in the query string of the
    request. Note that if ID is supplied, the other two parameters will be
    ignored.

    :param username: The user to collect submits for (leaving blank will return
                     submissions from all users).
    :param limit:    The number of submits to pull, max 100
    """

    # Default and max limit is 100
    limit = min(int(request.args.get('limit') or 100), 100)

    submits = (session.query(models.Submission)
               .order_by(models.Submission.submit_time.desc()))

    # Filter by user if provided
    if request.args.get('username'):
        submits = submits.filter(
                models.Submission.username == request.args.get('username'))

    result = submits.limit(limit).all()

    if not result:
        return serve_error('No submissions found', 401)

    return serve_response([s.to_dict() for s in result])
Example #13
0
def create_submission():
    try:
        project = (session.query(Project).filter(
                    Project.project_id == int(request.form['project_id']) and
                    Project.username == current_user.username).first())

        project.body = request.form['body']
        submission = Submission(
            username=current_user.username,
            submit_time=int(time.time()),
            type=project.type,
            project_id=int(request.form['project_id']),
            run=int(request.form['run'])
        )
    except KeyError:
        return serve_error('Form data missing.')

    submission.commit_to_session()
    project.commit_to_session()

    Event.log(current_user.username, 'execute', submission.job)

    directory = directory_for_submission(submission.job)
    os.mkdir(directory)
    file_name = 'submit' + FILE_EXTENSIONS_FROM_TYPE[submission.type]
    source_file = open(os.path.join(directory, file_name), 'w')
    source_file.write(project.body)
    source_file.close()

    runner = Runner(submission, file_name)
    runner.run_queued()

    return serve_response({
        'job': submission.job
    })
Example #14
0
def getCompetitionData(cid):
    competition = session.query(Competition).filter(Competition.cid==cid).first()
    if competition is None:
        return serve_error('competition not found', response_code=404)
    comp_users = session.query(CompUser).filter(CompUser.cid==cid).all()
    comp_problems = [p.pid for p in session.query(CompProblem).filter(CompProblem.cid==cid).all()]
    comp_problems.sort()
    
    submissions = session.query(Submission)\
            .filter(Submission.submit_time>competition.start,\
                    Submission.submit_time<competition.stop)\
            .order_by(asc(Submission.submit_time))\
            .all()
    
    scoreboard = list()
    
    team_users = dict()
    for user in comp_users:
        if not user.team in team_users:
            team_users[user.team] = list()
        team_users[user.team].append(user.username)
    
    for team in team_users.keys():
        team_problems = dict()
        for problem in comp_problems:
            correct = 0
            incorrect = 0
            pointless = 0
            for s in submissions:
                if not s.pid == problem or not s.username in team_users[team]:
                    continue
                elif correct > 0:
                    pointless += 1
                elif s.result == 'good':
                    correct = s.submit_time - competition.start
                else:
                    incorrect += 1
            problem_time = incorrect*20+correct/60
            submit_count = 0
            if (correct > 0):
                submit_count = 1
            submit_count += incorrect+pointless
            team_problems[problem] = {
                'problemTime' : problem_time,
                'submitCount' : submit_count,
                'status' : 'correct' if correct > 0 else 'unattempted' if submit_count == 0 else 'incorrect'
            }
        team_row = dict()
        team_row['name'] = team
        team_row['users'] = team_users[team]
        team_row['problemData'] = team_problems
        scoreboard.append(team_row)
        
    return serve_response({
        'competition' : create_competition_object(competition),
        'compProblems' : comp_problems,
        'teams' : scoreboard
    })
    
Example #15
0
def get_submit_for_id(job_id):
    """Return the submission with this id"""
    submit = (session.query(models.Submission)
              .filter(models.Submission.job == job_id).first())
    if not submit:
        return serve_error('Submission with id ' + str(job_id) +
                           ' not found', 401)
    return serve_response(submit.to_dict())
Example #16
0
def getCompetitionData(cid):
    competition = session.query(Competition).filter(Competition.cid == cid).first()
    if competition is None:
        return serve_error("competition not found", response_code=404)
    comp_users = session.query(CompUser).filter(CompUser.cid == cid).all()
    comp_problems = [p.pid for p in session.query(CompProblem).filter(CompProblem.cid == cid).all()]
    comp_problems.sort()

    submissions = (
        session.query(Submission)
        .filter(Submission.submit_time > competition.start, Submission.submit_time < competition.stop)
        .order_by(asc(Submission.submit_time))
        .all()
    )

    scoreboard = list()

    team_users = dict()
    for user in comp_users:
        if not user.team in team_users:
            team_users[user.team] = list()
        team_users[user.team].append(user.username)

    for team in team_users.keys():
        team_problems = dict()
        for problem in comp_problems:
            correct = 0
            incorrect = 0
            pointless = 0
            for s in submissions:
                if not s.pid == problem or not s.username in team_users[team]:
                    continue
                elif correct > 0:
                    pointless += 1
                elif s.result == "good":
                    correct = s.submit_time - competition.start
                else:
                    incorrect += 1
            problem_time = incorrect * 20 + correct / 60
            submit_count = 0
            if correct > 0:
                submit_count = 1
            submit_count += incorrect + pointless
            team_problems[problem] = {
                "problemTime": problem_time,
                "submitCount": submit_count,
                "status": "correct" if correct > 0 else "unattempted" if submit_count == 0 else "incorrect",
            }
        team_row = dict()
        team_row["name"] = team
        team_row["users"] = team_users[team]
        team_row["problemData"] = team_problems
        scoreboard.append(team_row)

    return serve_response(
        {"competition": create_competition_object(competition), "compProblems": comp_problems, "teams": scoreboard}
    )
Example #17
0
def delete_blog_post(bid):
    """Delete a blog post from the database"""
    post = database.session.query(BlogPost).filter_by(id=bid).first()
    if not post:
        return serve_error('No blog post id: '.format(bid), 404)

    post_id = post.id
    database.session.delete(post)
    database.session.commit()
    return serve_response({'deleted blog id': post_id})
Example #18
0
def change_password():
    """Change the password of an existing user"""
    oldPassword = request.form['oldPassword']
    newPassword = request.form['newPassword']
    if bcrypt.check_password_hash(current_user.passw, oldPassword):
        hashed = bcrypt.generate_password_hash(newPassword)
        current_user.passw = hashed
        current_user.commit_to_session()
        return serve_response({})
    return serve_error('old password does not match', 401)
Example #19
0
def delete_problem(identifier):
    """Delete a specified problem in the database and data folder"""
    # Admin check
    if not current_user.admin == 1:
        return serve_error('You must be an admin to delete a problem',
                           response_code=401)

    pid, problem = None, database.session.query(Problem)
    if is_pid(identifier):
        pid = identifier
        problem = problem.filter(Problem.pid == pid).first()
    else:
        problem = problem.filter(Problem.shortname == identifier).first()
        pid = problem.pid

    # Delete from problem_data table first to satisfy foreign key constraint
    problem_data = database.session.query(ProblemData).\
        filter(ProblemData.pid == pid)
    if not problem_data.first():
        return serve_error('Could not find problem data with pid ' +
                           pid, response_code=401)
    database.session.delete(problem_data.first())

    # Delete any and all sample cases associated w/ problem
    for case in database.session.query(SampleCase).\
            filter(SampleCase.pid == pid).all():
        database.session.delete(case)

    # Delete from problem table
    database.session.delete(problem)

    # Commit changes
    database.session.flush()
    database.session.commit()

    # Delete judge data
    directory = os.path.join(app.config['DATA_FOLDER'], 'problems', pid)
    rmtree(directory)

    return serve_response({
        'deleted_pid': pid
    })
Example #20
0
def log_in():
    username = request.form['username']
    password = request.form['password']
    user = load_user(username)
    if user:
        hashed = user.passw
        if bcrypt.check_password_hash(hashed, password):
            # everything's gucci
            login_user(user)
            return serve_response({})
    return serve_error('invalid username or password', 401)
Example #21
0
def change_password():
    oldPassword = request.form['oldPassword']
    newPassword = request.form['newPassword']
    if bcrypt.check_password_hash(current_user.passw, oldPassword):
        hashed = bcrypt.generate_password_hash(newPassword)
        current_user.passw = hashed
        session.add(current_user)
        session.flush()
        session.commit()
        return serve_response({})
    return serve_error('old password does not match', 401)
Example #22
0
def log_in():
    username = request.form['username']
    password = request.form['password']
    user = load_user(username)
    if user:
        hashed = user.password
        if bcrypt.check_password_hash(hashed, password):
            # everything's gucci
            login_user(user)
            Event.log(username, 'login')
            return serve_response({})
    return serve_error('invalid username or password', 401)
Example #23
0
def make_template():
    try:
        template = Template(
            title=request.form['title'],
            body=request.form['body'],
            cursor_x=int(request.form['cursor_x']),
            cursor_y=int(request.form['cursor_y']),
            type=request.form['type']
        )
    except KeyError as error:
        return serve_error('Form field not found: ' + error[0])
    template.commit_to_session()
    return serve_response(template.to_dict())
Example #24
0
def update_blog_post(bid):
    """Modify a blog post"""
    post = database.session.query(BlogPost).filter(BlogPost.id == bid).first()
    if not post:
        return serve_error('No blog post id: ' + str(bid), 404)

    post.title = request.form['title']
    post.subtitle = request.form['subtitle']
    post.body = request.form['body']
    post.username = current_user.username
    database.session.commit()

    return serve_response(create_blog_object(post))
Example #25
0
def create_blog_post():
    try:
        post = BlogPost(title=request.form['title'],
                        subtitle=request.form['subtitle'],
                        post_time=int(time()),
                        body=request.form['body'],
                        username=current_user.username)
    except KeyError:
        return serve_error('Must include title, subtitle, and body',
                           response_code=400)

    post.commit_to_session(database.session)
    database.session.refresh(post)
    return serve_response(create_blog_object(post))
Example #26
0
def create_user():
    """Create a new user"""
    # Get form contents
    username = request.form['username']
    password = request.form['password']
    display = request.form['display']

    # Create the user if doesn't already exist
    user = load_user(username)
    if user is None:
        hashed = bcrypt.generate_password_hash(password)
        user = User(username=username, passw=hashed, display=display, admin=0)
        user.commit_to_session()
        return serve_response({})
    return serve_error('username already exists', 401)
Example #27
0
def create_project():
    try:
        project = Project(username=current_user.username,
                          body=request.form['body'],
                          cursor_x=0,
                          cursor_y=0,
                          type=request.form['type'],
                          title=request.form['title'],
                          last_edited=int(time.time()),
                          template_id=int(request.form['template_id']),
                          hide=0)
    except KeyError as error:
        return serve_error('Form field not found: ' + error[0])

    project.commit_to_session()
    return serve_response(project.to_dict())
Example #28
0
def create_project():
    try:
        project = Project(
                username=current_user.username,
                body=request.form['body'],
                cursor_x=0,
                cursor_y=0,
                type=request.form['type'],
                title=request.form['title'],
                last_edited=int(time.time()),
                template_id=int(request.form['template_id']),
                hide=0
        )
    except KeyError as error:
        return serve_error('Form field not found: ' + error[0])

    project.commit_to_session()
    return serve_response(project.to_dict())
Example #29
0
def get_problem(identifier):
    """
    Returns the JSON representation of a specific problem

    If the problem is meant to be released with a competition that has not
    started yet, a 404 error is returned.
    """
    problem = database.session.query(Problem, ProblemData).join(ProblemData)

    if is_pid(identifier):
        problem = problem.filter(Problem.pid == identifier).first()
    else:
        problem = problem.filter(Problem.shortname == identifier).first()

    # Hide unreleased problems to non-admins
    if problem is None or ((current_user.is_anonymous or
                            current_user.admin != 1) and
                           comp_not_released(problem.Problem.comp_release)):
        return serve_error('404: Problem Not Found', 404)

    cases = list()
    for case in (database.session.query(SampleCase)
                 .filter(SampleCase.pid == problem.Problem.pid)
                 .all()):
        cases.append({
            'case_num': case.case_num,
            'input': case.input,
            'output': case.output
        })

    return serve_response({
        'pid': problem.Problem.pid,
        'name': problem.Problem.name,
        'shortname': problem.Problem.shortname,
        'appeared': problem.Problem.appeared,
        'difficulty': problem.Problem.difficulty,
        'added': problem.Problem.added,
        'comp_release': problem.Problem.comp_release,
        'description': problem.ProblemData.description,
        'input_desc': problem.ProblemData.input_desc,
        'output_desc': problem.ProblemData.output_desc,
        'sample_cases': cases
    })
Example #30
0
def create_user():
    # Verify that the poster is an admin
    if current_user.admin == 0:
        return server_error('Must be admin to create users', 401)

    # Get form contents
    username = request.form['username']
    password = request.form['password']
    display = request.form['display']

    # Create the user if doesn't already exist
    user = load_user(username)
    if user is None:
        hashed = bcrypt.generate_password_hash(password)
        user = User(username=username, passw=hashed, display=display, admin=0)
        session.add(user)
        session.flush()
        session.commit()
        return serve_response({})
    return serve_error('username already exists', 401)
Example #31
0
def get_competition_data(cid):
    competition = database.session.query(Competition).filter(
        Competition.cid == cid).first()
    if competition is None:
        return serve_error('competition not found', response_code=404)
    comp_users = database.session.query(CompUser).filter(
            CompUser.cid == cid).all()

    comp_problems = dict()
    for prob in (database.session.query(CompProblem, Problem)
                 .join(Problem).filter(CompProblem.cid == cid)
                 .all()):
        comp_problems[prob.CompProblem.label] = {
            'pid': prob.Problem.pid,
            'name': prob.Problem.name,
            'shortname': prob.Problem.shortname
        }

    submissions = (database.session.query(Submission)
                   .filter(Submission.submit_time > competition.start,
                           Submission.submit_time < competition.stop)
                   .order_by(asc(Submission.submit_time))\
                   .all())

    scoreboard = list()

    team_users = dict()
    team_display_names = dict()

    all_users = database.session.query(User).all()
    name_to_display = dict()
    for user in all_users:
        name_to_display[user.username] = user.display

    for user in comp_users:
        if not user.team in team_users:
            team_users[user.team] = list()
            team_display_names[user.team] = list()
        team_users[user.team].append(user.username)
        team_display_names[user.team].append(name_to_display[user.username])

    for team in team_users:
        team_problems = dict()
        for name in comp_problems:
            problem = comp_problems[name]
            correct = 0
            incorrect = 0
            for s in submissions:
                if not s.pid == problem['pid'] or s.username not in team_users[team]:
                    continue
                elif correct > 0:
                    break
                elif s.result == 'good':
                    correct = s.submit_time - competition.start
                else:
                    incorrect += 1
            submit_time = correct // 60
            submit_count = 0
            if correct > 0:
                submit_count = 1
            submit_count += incorrect
            team_problems[comp_problems[name]['pid']] = {
                'label': name,
                'submitTime': submit_time,
                'submitCount': submit_count,
                'status': 'correct' if correct > 0 else 'unattempted' if submit_count == 0 else 'incorrect'
            }
        team_row = dict()
        team_row['name'] = team
        team_row['users'] = team_users[team]
        team_row['display_names'] = team_display_names[team]
        team_row['problemData'] = team_problems
        scoreboard.append(team_row)

    return serve_response({
        'competition': competition.to_dict(),
        'compProblems': comp_problems,
        'teams': scoreboard
    })
Example #32
0
def submit():
    """
    Retrieves the submission information from the request, creates a submission,
    then begins the submissions execution. The response is simply a submission
    identifier of the new submission.

    :return: serves a 200 request code and an empty object if it is a good
            request, 403 if the filetype is unsupproted, 400 if the required
            fields are missing.
    """

    uploaded_file = request.files['file']
    if not uploaded_file:
        return serve_error('file must be uploaded', response_code=400)
    if not judge.allowed_filetype(uploaded_file.filename):
        return serve_error('filename not allowed', response_code=403)
    if not request.form['pid']:
        return serve_error('the field \'pid\' must be specified',
            response_code=400)

    # Obtain the time limit for the problem
    time_limit = session.query(ProblemData).\
            options(load_only("pid", "time_limit")).\
            filter(ProblemData.pid==request.form['pid']).\
            first().time_limit

    ext = uploaded_file.filename.rsplit('.')[1].lower()
    if 'python' in request.form:
        ext = request.form['python']

    attempt = models.Submission(
        username=current_user.username,
        pid=request.form['pid'],
        submit_time=int(time.time()),
        auto_id=0,
        file_type=ext,
        result='start')

    attempt.commit_to_session()

    submission_path = os.path.join(app.config['DATA_FOLDER'],
                                   'submits', str(attempt.job))
    os.mkdir(submission_path)
    uploaded_file.save(os.path.join(submission_path, uploaded_file.filename))

    def update_status(status, test_number):
        """Updates the status of the submission and notifies the clients that
        the submission has a new status.
        """
        attempt.update_status(status)
        Flasknado.emit('status', {
            'submissionId': attempt.job,
            'problemId': attempt.pid,
            'username': attempt.username,
            'submitTime': attempt.submit_time,
            'testNum': test_number,
            'status': judge.EVENT_STATUS[status]
        })

    judge.Judge(attempt.pid, submission_path, uploaded_file, time_limit,
            update_status).run_threaded()

    return serve_response({
        'submissionId': attempt.job
    })
Example #33
0
def create_problem():
    """Add a new problem to the database and data folder"""
    try:
        # Convert the JSON to python array of dictionaries
        cases = request.form['cases']
        cases = loads(cases)
        for case in cases:
            if 'input' not in case or 'output' not in case:
                return serve_error(
                    'Sample case(s) were not formed correctly',
                    response_code=400)

        # Create the problem
        name = request.form['name'][:32]
        shortname = name.lower().replace(' ', '')
        problem = Problem(
            name=name,
            shortname=shortname
        )
        if 'difficulty' in request.form:
            problem.difficulty = request.form['difficulty']
        if 'appeared_in' in request.form:
            problem.appeared = request.form['appeared_in']
        problem.comp_release = request.form['comp_release'] or None

        # Create the problem data and add it to the database
        problem_data = ProblemData(
            description=request.form['description'],
            input_desc=request.form['input_desc'],
            output_desc=request.form['output_desc']
        )
        if 'time_limit' in request.form:
            problem_data.time_limit = request.form['time_limit']

        # Create list of sample cases
        case_num = 1
        sample_cases = list()
        for case in cases:
            sample = SampleCase(
                case_num=case_num,
                input=case['input'],
                output=case['output']
            )
            case_num += 1
            sample_cases.append(sample)

        in_file = zipfile.ZipFile(request.files['in_file'])
        out_file = zipfile.ZipFile(request.files['out_file'])
        sol_file = request.files['sol_file']

    # If any required values were missing, serve an error
    except KeyError as err:
        return serve_error('Form field not found: ' + err[0],
                           response_code=400)

    # Commit everything to the database
    pid = problem.commit_to_session()
    problem_data.pid = pid
    problem_data.commit_to_session()
    for case in sample_cases:
        case.pid = pid
        case.commit_to_session()

    # Store the judge data
    directory = os.path.join(app.config['DATA_FOLDER'],
                             'problems', str(problem.pid))
    in_file.extractall(directory)
    out_file.extractall(directory)
    os.mkdir(os.path.join(directory, 'test'))
    sol_file.save(os.path.join(directory, 'test', sol_file.filename))

    return serve_response({
        'name': problem.name,
        'shortname': problem.shortname,
        'description': problem_data.description,
        'input_desc': problem_data.input_desc,
        'output_desc': problem_data.output_desc,
        'sample_cases': cases,
        'pid': problem.pid,
        'difficulty': problem.difficulty
    })