Exemplo n.º 1
0
    def put(self, run_id: int):
        """ View for updating run """
        data = request.get_json(force=True, silent=False)

        run = db.session.query(Run).get(run_id)
        if run is None:
            raise NotFound(f'Run with id #{run_id} is not found')

        only_fields = ['ejudge_status', 'ejudge_test_num', 'ejudge_score']
        load_run_schema = RunSchema(only=only_fields, context={'instance': run})
        _, errors = load_run_schema.load(data)

        if errors:
            raise BadRequest(errors)

        invalidate_monitor_cache_by_run(run)

        # Avoid excess DB queries
        excludes = ['user', 'problem']
        dump_run_schema = RunSchema(exclude=excludes)
        data, _ = dump_run_schema.dump(run)

        db.session.add(run)
        db.session.commit()

        return jsonify(data)
Exemplo n.º 2
0
    def get(self, run_id: int):
        args = parser.parse(self.get_args, request)
        is_admin = args.get('is_admin')
        user_id = args.get('user_id')

        run_q = db.session.query(Run)
        if not is_admin:
            run_q = run_q.filter(Run.user_id == user_id)

        run = run_q.filter(Run.id == run_id).one_or_none()

        if run is None:
            raise NotFound(f'Run with id #{run_id} is not found')

        language_id = run.ejudge_language_id

        source = run.source or b''
        for encoding in POSSIBLE_SOURCE_ENCODINGS:
            try:
                source = source.decode(encoding)
                break
            except UnicodeDecodeError:
                pass

        return jsonify({'source': source, 'language_id': language_id})
Exemplo n.º 3
0
    def post(self, run_id: int):
        """ View for rejudge run"""
        run = db.session.query(Run).get(run_id)
        if run is None:
            raise NotFound(f'Run with id #{run_id} is not found')

        # If ejudge_url is None submission failed by error inside workers
        # And we shouldn't really rejudge the solution
        if run.ejudge_url is None:
            run.ejudge_url = current_app.config['EJUDGE_NEW_CLIENT_URL']
            db.session.add(run)
        else:
            rejudge = Rejudge(run_id=run.id,
                              ejudge_contest_id=run.ejudge_contest_id,
                              ejudge_url=run.ejudge_url
                              or 'rmatics_failed_submission')
            db.session.add(rejudge)
            db.session.flush([rejudge])

            run.move_protocol_to_rejudge_collection(rejudge.id)

        queue_submit(run.id, run.ejudge_url)

        run.ejudge_status = 377
        run.ejudge_test_num = None
        run.ejudge_score = None
        db.session.add(run)
        db.session.commit()

        return jsonify({})
Exemplo n.º 4
0
    def get(self, run_id: int):
        args = parser.parse(self.get_args, request)
        is_admin = args.get('is_admin')
        user_id = args.get('user_id')
        # if user_id == 399362 and not is_admin:
        #     import random as rdm
        #     return jsonify({'source': rdm.choice(['Нет', 'Отстань', 'Сори', 'Кончились', 'Попробуйте в другой раз', 'Ваш запрос очень важен для нас, оставайтесь на линии']), 'language_id': 2})

        run_q = db.session.query(Run)
        if not is_admin:
            run_q = run_q.filter(Run.user_id == user_id)

        run = run_q.filter(Run.id == run_id).one_or_none()

        if run is None:
            raise NotFound(f'Run with id #{run_id} is not found')

        language_id = run.ejudge_language_id

        source = run.source or b''
        for encoding in POSSIBLE_SOURCE_ENCODINGS:
            try:
                source = source.decode(encoding)
                break
            except UnicodeDecodeError:
                pass

        return jsonify({'source': source, 'language_id': language_id})
Exemplo n.º 5
0
    def post(self, problem_id: int):
        args = parser.parse(self.post_args)

        language_id = args['lang_id']
        statement_id = args.get('statement_id')
        user_id = args.get('user_id')
        file = parser.parse_files(request, 'file', 'file')

        # Здесь НЕЛЬЗЯ использовать .get(problem_id), см EjudgeProblem.__doc__
        problem = db.session.query(EjudgeProblem) \
            .filter_by(id=problem_id) \
            .one_or_none()

        if not problem:
            raise NotFound('Problem with this id is not found')

        try:
            text = self.check_file_restriction(file)
        except ValueError as e:
            raise BadRequest(e.args[0])
        source_hash = Run.generate_source_hash(text)

        duplicate = db.session.query(Run).filter(Run.user_id == user_id) \
            .filter(Run.problem_id == problem_id) \
            .order_by(Run.id.desc()).first()
        if duplicate is not None and duplicate.source_hash == source_hash:
            raise BadRequest('Source file is duplicate of your previous submission')

        # TODO: разобраться, есть ли там constraint на statement_id
        run = Run(
            user_id=user_id,
            problem_id=problem_id,
            statement_id=statement_id,
            ejudge_contest_id=problem.ejudge_contest_id,
            ejudge_language_id=language_id,
            ejudge_status=377,  # In queue
            source_hash=source_hash,
        )

        db.session.add(run)
        db.session.flush()

        run.update_source(text)

        run_id = run.id
        ejudge_url = current_app.config['EJUDGE_NEW_CLIENT_URL']

        # Коммит должен быть до отправки в очередь иначе это гонка
        db.session.commit()

        queue_submit(run_id, ejudge_url)
        return jsonify({
            'run_id': run_id
        })
Exemplo n.º 6
0
    def get(self, problem_id: int):
        problem = db.session.query(EjudgeProblem).get(problem_id)
        if not problem:
            raise NotFound('Problem with this id is not found')

        if not problem.sample_tests:
            schema = ProblemSchema(exclude=['sample_tests_json'])
        else:
            schema = ProblemSchema()

        data = schema.dump(problem)
        return jsonify(data.data)
Exemplo n.º 7
0
    def post(self):
        data = request.get_json(force=True)
        ejudge_run_id = data['run_id']
        ejudge_contest_id = data['contest_id']
        mongo_protocol_id = data.get('mongo_protocol_id', None)

        run = db.session.query(Run) \
            .filter_by(ejudge_run_id=ejudge_run_id,
                       ejudge_contest_id=ejudge_contest_id) \
            .one_or_none()

        if run is None:
            msg = f'Cannot find Run with  \
                    ejudge_contest_id={ejudge_contest_id},  \
                    ejudge_run_id={ejudge_run_id}'

            raise BadRequest(msg)

        run_schema = FromEjudgeRunSchema(context={'instance': run})
        received_run, errors = run_schema.load(data)
        if errors:
            raise BadRequest(errors)

        if mongo_protocol_id:
            # If it is we should invalidate cache
            invalidate_monitor_cache_by_run(run)
            current_app.logger.debug('Cache invalidated')
            try:
                result = mongo.db.protocol.update_one(
                    {'_id': ObjectId(mongo_protocol_id)},
                    {'$set': {
                        'run_id': received_run.id
                    }})
                if not result.modified_count:
                    raise BadRequest(
                        f'Cannot find protocol by _id {mongo_protocol_id}')
            except DuplicateKeyError:
                current_app.logger.exception('Found duplicate key for run_id')

            except PyMongoError:
                current_app.logger.exception('Looks like mongo is shutdown')
                raise InternalServerError(f'Looks like mongo is shutdown')

        db.session.add(received_run)
        db.session.commit()

        return jsonify({}, 200)
Exemplo n.º 8
0
    def get(self):
        args = parser.parse(contest_based_get_args, request)

        course_module_ids = args['contest_id']
        group_id = args['group_id']
        time_before = args['time_before']
        time_after = args['time_after']

        contest_ids = []
        for cm_id in course_module_ids:
            monitor_group_id, statement_ids = self._get_contests(cm_id)
            contest_ids += statement_ids
            group_id = group_id or monitor_group_id

        if group_id:
            users = db.session.query(SimpleUser)\
                .join(UserGroup, UserGroup.user_id == SimpleUser.id)\
                .filter(UserGroup.group_id == group_id)
            user_ids = [user.id for user in users]
        else:
            user_ids = None

        contest_problems = OrderedDict()
        for contest_id in contest_ids:
            contest_problems[contest_id] = get_problems_by_statement_id(
                contest_id)

        contest_problems_runs = []
        for contest_id, problems in contest_problems.items():
            for problem in problems:
                runs = get_runs(problem_id=problem.id,
                                user_ids=user_ids,
                                time_before=time_before,
                                time_after=time_after)
                monitor_data = ContestBasedMonitorData(contest_id, problem,
                                                       runs)
                contest_problems_runs.append(monitor_data)

        schema = ContestBasedMonitorSchema(many=True)

        response = schema.dump(contest_problems_runs)

        # We have to commit session because we may created cache_meta
        db.session.commit()

        return jsonify(response.data)
Exemplo n.º 9
0
    def get(self, run_id: int):
        args = parser.parse(self.get_args, request)
        is_admin = args.get('is_admin')
        user_id = args.get('user_id')

        run_q = db.session.query(Run)
        if not is_admin:
            run_q = run_q.filter(Run.user_id == user_id)

        run = run_q.filter(Run.id == run_id).one_or_none()

        if run is None:
            raise NotFound(f'Run with id #{run_id} is not found')

        protocol = run.protocol
        if not protocol:
            raise NotFound(f'Protocol for run_id: {run_id} not found')

        return jsonify(protocol)
Exemplo n.º 10
0
    def _process(self, args, user_ids):
        course_module_ids = args['contest_id']
        group_id = args['group_id']
        time_before = args['time_before']
        time_after = args['time_after']

        # Context arguments
        context_source = args.get('context_source')
        show_hidden = args.get('show_hidden')

        contest_ids = []
        for cm_id in course_module_ids:
            monitor_group_id, statement_ids = self._get_contests(cm_id)
            contest_ids += statement_ids
            group_id = group_id or monitor_group_id

        contest_problems = OrderedDict()
        for contest_id in contest_ids:
            contest_problems[contest_id] = get_problems_by_statement_id(
                contest_id)

        contest_problems_runs = []
        for contest_id, problems in contest_problems.items():
            for problem in problems:
                runs = get_runs(problem_id=problem.id,
                                user_ids=user_ids,
                                time_before=time_before,
                                time_after=time_after,
                                context_source=context_source,
                                show_hidden=show_hidden)
                monitor_data = ContestBasedMonitorData(contest_id, problem,
                                                       runs)
                contest_problems_runs.append(monitor_data)

        schema = ContestBasedMonitorSchema(many=True)

        response = schema.dump(contest_problems_runs)

        # We have to commit session because we may created cache_meta
        db.session.commit()

        return jsonify(response.data)
Exemplo n.º 11
0
    def get(self):
        # TODO: Приделать контекст посылки (NFRMTCS-192)
        args = parser.parse(problem_based_get_args, request)
        user_ids = args['user_id']
        problem_ids = args['problem_id']
        time_before = args['time_before']
        time_after = args['time_after']

        problem_runs = []
        for problem_id in problem_ids:
            runs = get_runs(problem_id=problem_id,
                            user_ids=user_ids,
                            time_before=time_before,
                            time_after=time_after)
            problem_runs.append(ProblemBasedMonitorData(problem_id, runs))

        schema = ProblemBasedMonitorSchema(many=True)
        problem_runs = schema.dump(problem_runs)

        # We have to commit session because we may created cache_meta
        db.session.commit()

        return jsonify(problem_runs.data)
Exemplo n.º 12
0
    def get(self):
        args = parser.parse(problem_based_get_args, request)

        user_ids = args['user_id']
        if not user_ids:
            user_ids = args['uid']
        problem_ids = args['problem_id']
        if not problem_ids:
            problem_ids = args['pid']
        time_before = args['time_before']
        time_after = args['time_after']

        # Context arguments
        context_id = args.get('context_id')
        context_source = args.get('context_source')
        show_hidden = args.get('show_hidden')

        problem_runs = []
        for problem_id in problem_ids:
            runs = get_runs(
                problem_id=problem_id,
                user_ids=user_ids,
                time_before=time_before,
                time_after=time_after,
                context_id=context_id,
                context_source=context_source,
                show_hidden=show_hidden,
            )
            problem_runs.append(ProblemBasedMonitorData(problem_id, runs))

        schema = ProblemBasedMonitorSchema(many=True)
        problem_runs = schema.dump(problem_runs)

        # We have to commit session because we may created cache_meta
        db.session.commit()

        return jsonify(problem_runs.data)
Exemplo n.º 13
0
    def post(self, problem_id: int):
        args = parser.parse(self.post_args)

        language_id = args['lang_id']
        statement_id = args.get('statement_id')
        user_id = args.get('user_id')
        file = parser.parse_files(request, 'file', 'file')

        # If context parameters are unavialable,
        # consider it as Moodle submission and set defaults
        context_id = args.get('context_id')
        context_source = args.get('context_source',
                                  DEFAULT_MOODLE_CONTEXT_SOURCE)
        is_visible = args.get('is_visible', True)

        # Здесь НЕЛЬЗЯ использовать .get(problem_id), см EjudgeProblem.__doc__
        problem = db.session.query(EjudgeProblem) \
            .filter_by(id=problem_id) \
            .one_or_none()

        if not problem:
            raise NotFound('Problem with this id is not found')

        if int(user_id) <= 0:
            raise BadRequest('Wrong user status')

        try:
            limit = 64
            if problem.output_only:
                limit = 1024 * 16
            text = self.check_file_restriction(file, limit)
        except ValueError as e:
            raise BadRequest(e.args[0])
        source_hash = Run.generate_source_hash(text)

        duplicate: Run = db.session.query(Run).filter(Run.user_id == user_id) \
            .filter(Run.problem_id == problem_id) \
            .order_by(Run.id.desc()).first()

        if duplicate is not None and \
                duplicate.source_hash == source_hash and \
                duplicate.ejudge_language_id == language_id:
            raise BadRequest(
                'Source file is duplicate of your previous submission')

        # There is not constraint on statement_id
        run = Run(
            user_id=user_id,
            problem_id=problem_id,
            statement_id=statement_id,
            ejudge_contest_id=problem.ejudge_contest_id,
            ejudge_language_id=language_id,
            ejudge_status=377,  # In queue
            source_hash=source_hash,

            # Context related properties
            context_source=context_source,
            is_visible=is_visible,
        )
        # If it's context aware submission,
        # overwrite statement_id with context
        if context_id:
            run.statement_id = context_id

        db.session.add(run)
        db.session.flush()

        run.update_source(text)

        run_id = run.id
        ejudge_url = current_app.config['EJUDGE_NEW_CLIENT_URL']

        # Коммит должен быть до отправки в очередь иначе это гонка
        db.session.commit()

        queue_submit(run_id, ejudge_url)
        return jsonify({'run_id': run_id})