Exemplo n.º 1
0
    def delete_dataset_post(self):
        """
        Deletes a dataset specified by the request id
        """

        try:
            session = self.acquire_sql_session()
        except:
            traceback.print_exc()
            raise HTTPError(500, 'Could not acquire database session.')

        try:
            id = int(self.get_argument('id'))

            dataset = DatasetRepository.get_by_id(session, id)
            problem_id = dataset.problem_id

            session.delete(dataset)
            session.commit()

            # Update the problem's default dataset if necessary
            try:
                ProblemRepository.update_default_dataset(session, problem_id)
                session.commit()
            except SQLAlchemyError:
                raise

        except Exception as e:
            traceback.print_exc()
            raise HTTPError(400)

        finally:
            session.close()

        self.write('Success!')
Exemplo n.º 2
0
    def evaluate(self,
                 problem_id,
                 dataset_id,
                 testcase_id,
                 submission_id,
                 worker_id):
        if problem_id not in self.problems_sandboxes:
            # Lock the entire object to add the dataset

            self.lock.acquire()

            # Recheck for any changes made by other threads
            if problem_id not in self.problems_sandboxes:
                session = self.acquire_sql_session()
                problem = ProblemRepository.get_by_id(session, problem_id)
                session.close()

                # Create subtree for the problem
                sandbox = ProblemSandbox(self.base_path, problem)
                self.problems_sandboxes[problem_id] = sandbox
            self.lock.release()

        sandbox = self.problems_sandboxes[problem_id]

        return submission_id, \
            dataset_id, \
            testcase_id, \
            sandbox.evaluate(dataset_id,
                             testcase_id,
                             submission_id,
                             worker_id)
Exemplo n.º 3
0
    def prepare(self):
        self.lock.acquire()
        session = self.acquire_sql_session()
        problems = ProblemRepository.get_problems_of_active_contests(session)
        session.close()

        self.problems_sandboxes = {}
        for problem in problems:
            sandbox = ProblemSandbox(self.base_path, problem)
            self.problems_sandboxes[str(problem.id)] = sandbox
        self.lock.release()
Exemplo n.º 4
0
    def get(self):
        """
        Handler for submission details. Binded at path /submission?id=<id>
        Throws Tornado 404 error if submission id is invalid in any way.
        """
        submission_id = self.get_argument("id", None)
        if submission_id is None:
            raise tornado.web.HTTPError(404,
                                        "A submission id must be supplied")

        try:
            submission_id = int(submission_id)
        except ValueError:
            raise tornado.web.HTTPError(404, "Submission id must be integer")

        session = self.acquire_sql_session()

        try:
            submission = SubmissionRepository.get_by_id(session, submission_id)
        except SQLAlchemyError:
            raise tornado.web.HTTPError(404, "Must be a valid submission id")

        problem = ProblemRepository.get_by_id(session, submission.problem_id)
        active_dataset_id = problem.active_dataset_id

        results = session.query(Job, Testcase) \
            .filter(Job.submission_id == submission_id) \
            .filter(Job.dataset_id == active_dataset_id) \
            .join(Testcase, Job.testcase_id == Testcase.id)\
            .all()

        if len(results) == 0:
            # Compiling or has already compiled
            results = session.query(Job) \
                .filter(Job.submission_id == submission_id)\
                .one()
            self.render("submission_details.html",
                        submission=submission,
                        testcases=PrettyWrapper(results, None))
            return

        return_list = []
        for row in results:
            job, testcase = row
            return_list.append(PrettyWrapper(job, testcase))

        self.render("submission_details.html",
                    submission=submission,
                    testcases=return_list)
Exemplo n.º 5
0
    def compile(self, submission_id):
        session = self.acquire_sql_session()
        submission = SubmissionRepository.get_by_id(session, submission_id)
        problem = ProblemRepository.get_by_id(session, submission.problem_id)

        sandbox = CompilationSandbox(self.base_path, submission_id)
        result = sandbox.compile(submission, problem)
        del sandbox
        session.commit()
        session.close()

        return submission_id, \
            -1, \
            -1, \
            result
Exemplo n.º 6
0
    def edit_problem(self):
        """ Edits problem using specified
        parameters in POST request"""

        # Get parameters from request
        try:
            old_name = self.get_argument('old-name')
            new_name = self.get_argument('name')

            active_ds_id = self.get_argument('active-dataset-id', None)

            new_description = self.get_argument('description')
            new_statements = self.request.files.get('statements', [])
            new_attachments = self.request.files.get('attachments', [])
        except:
            raise HTTPError(400)

        # Get database session
        try:
            session = self.acquire_sql_session()
        except:
            raise HTTPError(500, 'Could not acquire session for database')

        try:
            # Find problem in database
            problem = ProblemRepository.get_by_name(session, old_name)

            # Update it with new information
            problem.name = new_name
            problem.description = new_description

            if (active_ds_id is None or not active_ds_id) and \
                    len(problem.datasets) > 0:
                active_ds_id = problem.datasets[0].id

            problem.active_dataset_id = active_ds_id

            self.set_statements_and_attachments(new_attachments,
                                                new_statements,
                                                problem)
            session.commit()
        except SQLAlchemyError as e:
            raise HTTPError(500, 'Database error or invalid arguments.')

        # Redirect to problem edit page after finishing
        self.redirect('/problem/edit?name=' + problem.name)
        session.close()
Exemplo n.º 7
0
    def get_template_namespace(self):
        try:
            session2 = self.acquire_sql_session()
            sidebar_contests = ContestRepository.\
                get_all_contest_order_by_date(session2)
            sidebar_problems = ProblemRepository.get_all_problems(session2)
            sidebar_users = UserRepository.get_all(session2)
            session2.close()
        except:
            raise HTTPError(500)

        dict = super(BaseHandler, self).get_template_namespace()

        dict['sidebar_contests'] = sidebar_contests
        dict['sidebar_problems'] = sidebar_problems
        dict['sidebar_users'] = sidebar_users

        return dict
Exemplo n.º 8
0
    def get(self):
        """ Handles get requests related to problems """

        path_elements = [x for x in self.request.path.split("/") if x]
        action = path_elements[-1]

        # Check if create is asked
        if action == 'create':
            self.render("problem_create.html")
            return

        try:
            session = self.acquire_sql_session()
        except:
            raise HTTPError(500, 'Could not acquire session for database')

        # Get problem name
        name = self.get_argument('name', None)

        if action == 'edit':
            if name is None:
                # If no name specified, redirect to create page
                self.redirect('/problem/create')
                session.close()
                return

            # Find problem in database
            try:
                problem = ProblemRepository.get_by_name(session, name)
            except:
                # If problem does not exist, redirect user to create it
                self.render('problem_create.html',
                            problem_name=name)
                session.close()
                return

            self.render("problem_edit.html",
                        problem=problem)

            session.close()
            return

        raise HTTPError(404, 'Not found')
Exemplo n.º 9
0
    def post(self):
        path_elements = [x for x in self.request.path.split("/") if x]
        contest_id = path_elements[1]
        if len(path_elements) == 2 and contest_id == "create":
            # Create contest from request

            contest_name = self.get_argument('contest_name')
            start_date_string = self.get_argument('start_date')

            start_date = \
                datetime.strptime(start_date_string, '%m/%d/%Y %I:%M %p')

            start_date_utc = calendar.timegm(start_date.timetuple())

            end_date_string = self.get_argument('end_date')
            end_date = datetime.strptime(end_date_string, '%m/%d/%Y %I:%M %p')
            end_date_utc = calendar.timegm(end_date.timetuple())

            try:
                session = self.acquire_sql_session()
            except SQLAlchemyError:
                traceback.print_exc()
                raise HTTPError(500, 'Could not acquire database session.')

            try:
                new_contest = Contest(name=contest_name,
                                      description='',
                                      start_time=start_date_utc,
                                      end_time=end_date_utc)
                session.add(new_contest)
                session.commit()
            except SQLAlchemyError as e:
                self.redirect("create")
                print(e)
                return

            self.redirect_to_settings(self, contest_name + "/settings")
            session.close()
            return

        elif len(path_elements) == 3 and path_elements[2] == 'settings':
            """Changing settings"""

            contest_name = self.get_argument('contest_name')
            contest_description = self.get_argument('contest_description')
            contest_type = self.get_argument('contest_type')

            contest_dict = {'Open': 1, 'Public': 2, 'Private': 3}

            contest_type = contest_dict.get(contest_type, 1)

            try:
                self.get_argument('contest_virtual')
                contest_virtual = True
            except:
                contest_virtual = False
            try:
                self.get_argument('contest_allow_download')
                contest_allow_download = True
            except:
                contest_allow_download = False
            try:
                self.get_argument('contest_allow_questions')
                contest_allow_questions = True
            except:
                contest_allow_questions = False
            try:
                self.get_argument('contest_allow_usertest')
                contest_allow_usertest = True
            except:
                contest_allow_usertest = False

            contest_restricted_ip = \
                self.get_argument('contest_restricted_ip')

            contest_start_time_string = \
                self.get_argument('contest_start_time')

            contest_start_time_non_utc = \
                datetime.strptime(contest_start_time_string,
                                  '%m/%d/%Y %I:%M %p')

            contest_start_time = \
                calendar.timegm(contest_start_time_non_utc.timetuple())

            contest_end_time = \
                self.get_argument('contest_end_time')

            contest_end_time_non_utc = \
                datetime.strptime(contest_end_time, '%m/%d/%Y %I:%M %p')

            contest_end_time = \
                calendar.timegm(contest_end_time_non_utc.timetuple())

            # contest_timezone = \
            # self.get_argument('contest_timezone')# make date time picker boss
            contest_max_submissions = \
                self.get_argument('contest_max_submissions')
            contest_max_user_tests = \
                self.get_argument('contest_max_user_tests')
            contest_submission_delay = \
                self.get_argument('contest_min_submission_interval')
            contest_user_test_delay = \
                self.get_argument('contest_min_user_test_interval')

            try:
                session = self.acquire_sql_session()
            except:
                traceback.print_exc()
                # TODO: handle error
                return

            try:
                contest_old_name = path_elements[1]
                stmt = update(Contest). \
                    where(Contest.name == contest_old_name). \
                    values(name=contest_name,
                           description=contest_description,
                           type=contest_type,
                           virtual=contest_virtual,
                           submission_download_allowed=contest_allow_download,
                           allow_questions=contest_allow_questions,
                           allow_user_test=contest_allow_usertest,
                           restricted_ip=contest_restricted_ip,
                           start_time=contest_start_time,
                           end_time=contest_end_time,
                           max_submissions=contest_max_submissions,
                           max_user_test=contest_max_user_tests,
                           min_submission_interval=contest_submission_delay,
                           min_user_test_interval=contest_user_test_delay,
                           )
                session.execute(stmt)
                session.commit()
            except SQLAlchemyError as e:
                print(e)
                self.redirect_to_settings(self, "settings")
                return
            self.redirect("problems")
            session.close()

        elif len(path_elements) == 3 and path_elements[2] == 'add_problem':
            """Adding problem to contest"""

            contest_name = path_elements[1]
            problem_id = self.get_argument('problem', None)

            if problem_id is None:
                self.redirect('/contest/' + contest_name + '/problems')
                return

            try:
                session = self.acquire_sql_session()
            except SQLAlchemyError:
                self.send_custom_error(500, 'Could not acquire '
                                       'database session')
                return

            try:
                problem = ProblemRepository.get_by_name(session, problem_id)
                contest = ContestRepository.get_by_name(session, contest_name)
            except SQLAlchemyError:
                session.close()
                self.send_custom_error(500, 'Could not find problem.')
                return

            try:
                ContestRepository.add_problem(session, contest, problem)
            except SQLAlchemyError:
                session.close()
                self.send_custom_error(
                    500, 'Could not add problem. '
                    'It already exists in contest.')
                return

            self.write('Success! Refresh page to see changes.')
            session.close()

        elif len(path_elements) == 3 and path_elements[2] == 'remove_problem':
            """Removing problem from contest"""

            print('Entered "remove problem from contest"')

            contest_name = path_elements[1]
            problem_id = int(self.get_argument('id', None))

            if problem_id is None:
                self.send_custom_error(500, 'Problem name not specified')
                return

            try:
                session = self.acquire_sql_session()
            except SQLAlchemyError:
                self.send_custom_error(500, 'Could not acquire '
                                       'database session')
                return

            try:
                problem = ProblemRepository.get_by_id(session, problem_id)
                contest = ContestRepository.get_by_name(session, contest_name)
            except SQLAlchemyError:
                session.close()
                self.send_custom_error(500, 'Could not find '
                                       'problem or contest.')
                return

            try:
                ContestRepository.remove_problem(session, contest, problem)
            except SQLAlchemyError:
                session.close()
                self.send_custom_error(500, 'Could not remove problem...')
                return

            self.write('Success!')
            session.close()

        elif len(path_elements) == 3 and path_elements[2] == 'addusers':
            session = self.acquire_sql_session()
            contest_name = path_elements[1]
            user_name = self.get_argument('username')
            participation_type = self.get_argument('participation_type')
            delay_time = self.get_argument('delay_time')
            extra_time = self.get_argument('extra_time')
            s_password = self.get_argument('special_password')

            if s_password == '':
                s_password = None
            try:
                self.get_argument('unrestricted')
                unrestricted = True
            except:
                unrestricted = False

            try:
                self.get_argument('hidden')
                hidden = True
            except:
                hidden = False

            try:
                contest = ContestRepository.get_by_name(session, contest_name)
                user = UserRepository.get_by_name(session, user_name)
            except SQLAlchemyError as e:
                self.write('User or Contest not found!')
                print(e)
                return
            if contest is None:
                self.write('Contest is None!')
            if user is None:
                self.write('User is None!')

            ok = ParticipationRepository. \
                verif_participation(session, user.id, contest.id)

            if ok is False:
                participation = Participation(user_id=user.id,
                                              contest_id=contest.id,
                                              type=participation_type,
                                              unrestricted=unrestricted,
                                              hidden=hidden,
                                              delay_time=delay_time,
                                              extra_time=extra_time,
                                              special_password=s_password)
                session.add(participation)
                session.commit()
                message = 'registered'
            else:
                stmt = update(Participation). \
                    where(and_(Participation.user_id == user.id,
                               Participation.contest_id == contest.id)). \
                    values(type=participation_type,
                           unrestricted=unrestricted,
                           hidden=hidden,
                           delay_time=delay_time,
                           extra_time=extra_time,
                           special_password=s_password)
                session.execute(stmt)
                session.commit()
                message = 'registered'
            self.write(message)
            return
Exemplo n.º 10
0
    def create_dataset_post(self):
        """
        Creates a new dataset, using the arguments from
        the post request
        """

        # Get arguments from request
        try:
            problem_id = int(self.get_argument('problem-id'))
            name = self.get_argument('name')
            time_limit = self.get_argument('time-limit')
            memory_limit = self.get_argument('memory-limit')

            # If received empty string, use database default
            try:
                time_limit = float(time_limit) if time_limit else None
                memory_limit = float(memory_limit) if memory_limit else None

                # Validate time and memory limits
                if not self.validate_time_memory(time_limit, memory_limit):
                    raise HTTPError(400, 'Invalid time limit or memory limit')

            except:
                raise HTTPError(400, 'Invalid time limit '
                                     'or memory limit format')

            stdin = self.get_argument('stdin', '')
            stdout = self.get_argument('stdout', '')

            # Get uploaded testcases
            files = self.request.files
            testcases = files.get('testcases', None)

            if testcases is not None:
                testcases_dict = testcases[0]
                testcases_body = testcases_dict['body']
            else:
                testcases_body = None

        except HTTPError:
            raise  # Re-raise exception

        except Exception as e:
            traceback.print_exc()
            raise HTTPError(400)  # Bad request

        try:
            session = self.acquire_sql_session()
        except:
            traceback.print_exc()
            raise HTTPError(500, 'Could not acquire database session.')

        try:
            # Create a new empty dataset (in order to get an ID)
            new_dataset = self.create_empty_dataset(memory_limit,
                                                    name,
                                                    problem_id,
                                                    time_limit,
                                                    stdin,
                                                    stdout,
                                                    session
                                                    )
            # Extract testcases_body
            extracted = self.extract_zip(testcases_body)

            # Go through files and construct testcases
            self.create_testcases(extracted, new_dataset, session)

            # Commit changes (add testcases)
            session.commit()
        except HTTPError:
            traceback.print_exc()
            raise

        except Exception as e:
            traceback.print_exc()
            raise HTTPError(400)

        finally:
            session.rollback()

        # Update the problem's default dataset, if necessary
        try:
            ProblemRepository.update_default_dataset(session, problem_id)
            session.commit()
        except SQLAlchemyError:
            raise

        self.redirect('/problem/edit?name=' + new_dataset.problem.name)
        session.close()
Exemplo n.º 11
0
    def get(self):
        """
        Render page with submissions. Parameters:
         * required pg_number: The page number to show
         * user: The name of the username to show submissions of
         * problem: The name of the problem to show submission for
         * contest: The name of the contest where the contest was submitted
        """
        contest_name = self.get_argument("contest", None)  # Contest name
        problem_name = self.get_argument("problem", None)  # Problem name
        user_name = self.get_argument("user", None)  # Problem name
        pg_nr = self.get_argument("page_number", "1")  # Page number
        pg_size = 20  # Defaults to 20 submissions per page

        try:  # Try to fetch page number. Should be integer.
            pg_nr = int(pg_nr)
        except ValueError:
            self.render("submissions.html",
                        submissions=None,
                        error="Invalid page number, "
                              "should be a valid integer")

        try:
            session = self.acquire_sql_session()
        except SQLAlchemyError as err:
            print(str(err))
            self.render("submissions.html",
                        submissions=None,
                        error="Database is down!")
            return

        try:
            # Get problem or None if not required
            if problem_name is not None:
                problem = ProblemRepository.get_by_name(session, problem_name)
                problem_id = problem.id
            else:
                problem_id = None

            # Get contest or None if not required
            if contest_name is not None:
                contest = ContestRepository.get_by_name(session, contest_name)
                contest_id = contest.id
            else:
                contest_id = None

            # Get user or None if not required
            if user_name is not None:
                user = UserRepository.get_by_name(session, user_name)
                user_id = user.id
            else:
                user_id = None
        except MultipleResultsFound:
            session.close()
            self.render("submissions.html",
                        submissions=None,
                        error="Invalid database!")
            return
        except NoResultFound:
            session.close()
            self.render("submissions.html",
                        submissions=None,
                        error="Invalid contest or problem parameters")
            return

        # Done handling errors

        # Create multiple part query
        query = session.query(Submission, Contest, Problem, User) \
            .join(Participation,
                  Submission.participation_id == Participation.id)\
            .join(User, User.id == Participation.user_id)\
            .join(Contest, Contest.id == Participation.contest_id)\
            .join(Problem, Problem.id == Submission.problem_id)

        if user_id is not None:
            query = query.filter(User.id == user_id)

        if contest_id is not None:
            query = query.filter(Contest.id == contest_id)

        if problem_id is not None:
            query = query.filter(Problem.id == problem_id)

        query.order_by(Submission.created_timestamp.desc())\
            .limit(pg_nr * pg_size)\
            .offset((pg_nr - 1) * pg_size)\
            .limit(pg_size)

        results = query.all()
        return_list = []

        results.sort(key=lambda a: a[0].created_timestamp, reverse=True)

        for row in results:
            submission, contest, problem, user = row
            score = SubmissionRepository.get_status(session, submission.id)

            wrapper = PrettyWrap(submission,
                                 contest,
                                 problem,
                                 user,
                                 score[0],  # Message to show
                                 score[1],  # Cpu used
                                 score[2])  # Memory used
            return_list.append(wrapper)

        session.close()

        self.render("submissions.html", submissions=return_list)