コード例 #1
0
class Problem(db.Model):
    __table_args__ = {'schema':'moodle'}
    __tablename__ = 'mdl_problems'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode(255))
    content = db.Column(db.Text)
    review = db.Column(db.Text)
    hidden = db.Column(db.Boolean)
    timelimit = db.Column(db.Float)
    memorylimit = db.Column(db.Integer)
    description = db.Column(db.Text)
    analysis = db.Column(db.Text)
    sample_tests = db.Column(db.Unicode(255))
    sample_tests_html = db.Column(db.Text)
    sample_tests_json = db.Column(JsonType)
    show_limits = db.Column(db.Boolean)
    output_only = db.Column(db.Boolean)
    pr_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_ejudge_problem.id'))
    ejudge_problem = relationship('EjudgeProblem', lazy='select')

    def __init__(self, *args, **kwargs):
        super(Problem, self).__init__(*args, **kwargs)
        self.hidden = 1
        self.show_limits = True
コード例 #2
0
class Resource(CourseModuleInstance, db.Model):
    """
    Модуль курса, описывающий ссылку
    """
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_resource'
    __mapper_args__ = {
        'polymorphic_identity': 'resource',
        'concrete': True,
    }

    MODULE = 13

    id = db.Column(db.Integer, primary_key=True)
    course_id = db.Column('course', db.Integer)
    name = db.Column(db.Unicode(255))
    type_ = db.Column('type', db.Unicode(30))
    reference = db.Column(db.Unicode(255))
    summary = db.Column(db.UnicodeText())

    def serialize(self):
        serialized = attrs_to_dict(
            self,
            'id',
            'course_id',
            'name',
            'type',
            'reference',
            'summary',
        )
        serialized['type'] = self.type_
        return serialized
コード例 #3
0
class SimpleUser(db.Model):
    RESET_PASSWORD_LENGTH = 20

    __table_args__ = (db.Index('ej_id', 'ej_id'), {'schema': 'moodle'})
    __tablename__ = 'mdl_user'

    id = db.Column(db.Integer, primary_key=True)
    firstname = db.Column(db.Unicode(100))
    lastname = db.Column(db.Unicode(100))
    login = db.Column('ej_login', db.Unicode(50))
    password = db.Column('ej_password', db.Unicode(50))
    deleted = db.Column('deleted', db.Boolean)
    ejudge_id = db.Column('ej_id', db.Integer)
    problems_solved = db.Column(db.Integer)
    password_md5 = db.Column('password', db.Unicode(32))

    statement = db.relationship(
        'Statement',
        secondary=StatementUser.__table__,
        backref='StatementUsers1',
        lazy='dynamic',
    )
    statements = association_proxy('StatementUsers2', 'statement')

    def reset_password(self):
        """
        Генерирует случайный пароль для пользователя и возвращает его
        """
        new_password = random_password(self.RESET_PASSWORD_LENGTH)
        self.password_md5 = hash_password(new_password)
        return new_password
コード例 #4
0
class Course(db.Model):
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_course'

    id = db.Column(db.Integer, primary_key=True)

    full_name = db.Column('fullname', db.Unicode(254))
    short_name = db.Column('shortname', db.Unicode(100))

    category = db.Column(db.Integer)
    password = db.Column(db.Unicode(50))
    visible = db.Column(db.Boolean)

    def require_password(self):
        return bool(self.password)

    @deprecated('view.serializers.course.CourseSchema')
    def serialize(self):
        serialized = attrs_to_dict(
            self,
            'id',
            'full_name',
            'short_name',
        )
        serialized['require_password'] = self.require_password()

        if not self.require_password():
            serialized['sections'] = [
                section.serialize() for section in self.sections.all()
                if section.visible
            ]
        return serialized
コード例 #5
0
class Ideal(db.Model):
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_ideal_solution'

    id = db.Column(db.Integer, primary_key=True)
    problem_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_problems.id'))
    run_id = db.Column(db.Integer, db.ForeignKey('ejudge.runs.run_id'))
    contest_id = db.Column(db.Integer, db.ForeignKey('ejudge.runs.contest_id'))
    lang_id = db.Column(db.Integer)
    lang = db.Column(db.Unicode(100))
    code = db.Column(db.UnicodeText)
    author_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_user.id'))
    author_name = db.Column(db.Unicode(200))
    comment = db.Column(db.UnicodeText)
    status = db.Column(db.Integer)

    def __init__(self,
                 problem_id,
                 run_id,
                 contest_id,
                 author_id,
                 comment,
                 status=0):
        self.problem_id = problem_id
        self.run_id = run_id
        self.contest_id = contest_id
        run = db.session.query(EjudgeRun) \
            .filter_by(contest_id=contest_id) \
            .filter_by(run_id=run_id) \
            .one()
        user = db.session.query(User) \
            .filter_by(id=author_id) \
            .one()
        self.lang_id = run.lang_id
        self.lang = LANG[self.lang_id]
        self.code = get_run_code(run_id, contest_id)
        self.author_id = author_id
        self.author_name = user.firstname + ' ' + user.lastname
        self.comment = comment
        self.status = status

    def __json__(self, request):
        return {
            'id': self.id,
            'problem_id': self.problem_id,
            'lang': self.lang,
            'code': self.code,
            'author_name': self.author_name,
            'author_id': self.author_id,
            'comment': self.comment,
        }
コード例 #6
0
class Group(db.Model):
    __table_args__ = (db.ForeignKeyConstraint(['owner_id'],
                                              ['moodle.mdl_user.id']), {
                                                  'schema': 'moodle'
                                              })
    __tablename__ = 'mdl_ejudge_group'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode(100))
    description = db.Column(db.Text)
    owner_id = db.Column(db.Integer)
    visible = db.Column(db.Integer)

    owner = db.relationship('SimpleUser',
                            backref=db.backref('groups', lazy='select'),
                            lazy='joined')

    def serialize(self, attributes=None):
        if not attributes:
            attributes = (
                'name',
                'description',
                'owner_id',
                'visible',
            )
        serialized = attrs_to_dict(self, *attributes)
        return serialized
コード例 #7
0
class User(SimpleUser):
    __mapper_args__ = {'polymorphic_identity': 'user'}
    username = db.Column(db.Unicode(100))
    email = db.Column(db.Unicode(100))
    city = db.Column(db.Unicode(20))
    school = db.Column(db.Unicode(255))
    problems_week_solved = db.Column(db.Integer)

    @classmethod
    def search(cls,
               filter_func: Callable[[Query], Query],
               filter_deleted=True):
        if filter_deleted:
            users_query = filter_func(
                db.session.query(cls).filter(cls.deleted == False))
        else:
            users_query = filter_func(db.session.query(cls))
        return users_query

    @classmethod
    def search_by_string(cls, search_string):
        def filter_func(query: Query):
            if search_string.count(' '):
                str1, str2 = search_string.split(' ', 1)
                query = query.filter(
                    or_(
                        and_(cls.firstname.like("%{}%".format(str1)),
                             cls.lastname.like("%{}%".format(str2))),
                        and_(cls.lastname.like("%{}%".format(str1)),
                             cls.firstname.like("%{}%".format(str2))),
                    ))
            else:
                query = query.filter(
                    or_(
                        cls.email.like("%{}%".format(search_string)),
                        cls.username.like("%{}%".format(search_string)),
                        cls.firstname.like("%{}%".format(search_string)),
                        cls.lastname.like("%{}%".format(search_string)),
                    ))
            return query

        return cls.search(filter_func)

    @lazy
    def _get_current_olymp(self):
        return None
コード例 #8
0
class EjudgeContest(db.Model):
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_ejudge_contest'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode(255))
    ejudge_id = db.Column(db.Unicode(10))
    ejudge_int_id = db.Column(db.Integer,
                              nullable=False,
                              primary_key=True,
                              autoincrement=False)
    load_time = db.Column(db.DateTime)
    cloned = db.Column(db.Boolean, nullable=False)

    def __init__(self, name='', ejudge_int_id=0):
        self.name = name
        self.ejudge_id = get_contest_str_id(ejudge_int_id)
        self.ejudge_int_id = ejudge_int_id
        self.load_time = datetime.datetime.now()
        self.cloned = False
コード例 #9
0
class MonitorCourseModule(CourseModuleInstance, db.Model):
    """
    Модуль курса, описывающий монитор
    """
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_monitor'
    __mapper_args__ = {
        'polymorphic_identity': 'monitor',
        'concrete': True,
    }

    MODULE = 28

    id = db.Column(db.Integer, primary_key=True)
    course_id = db.Column('course', db.Integer)
    name = db.Column(db.Unicode(255), nullable=False, default='')
    monitor_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_monitors.id'))
    group_id = db.Column(db.Integer, nullable=False, default=0)
コード例 #10
0
class Label(CourseModuleInstance, db.Model):
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_label'
    __mapper_args__ = {
        'polymorphic_identity': 'label',
        'concrete': True,
    }

    MODULE = 9

    id = db.Column(db.Integer, primary_key=True)
    course = db.Column(db.Integer)
    name = db.Column(db.Unicode(255))
    content = db.Column(db.UnicodeText)

    def serialize(self):
        return attrs_to_dict(
            self,
            'id',
            'name',
            'content',
        )
コード例 #11
0
class EjudgeProblem(Problem):
    """
    Модель задачи из ejudge

    ejudge_prid -- primary key, на который ссылается Problem.pr_id.
        После инициализации, соответствтующему объекту Problem проставляется корректный pr_id

    contest_id --

    ejudge_contest_id -- соответствует contest_id из ejudge

    secondary_ejudge_contest_id --

    problem_id -- соответствует problem_id из ejudge

    short_id -- короткий id (обычно буква)

    Здесь используется наследование и polymorphic_identity
    Это значит, что можно написать
    problem_id = Problem.id
    query(EjudgeProblem).filter(EjudgeProblem.id == problem_id)  # вернет Problem
    При этом неявно приджойнится Problem.pr_id == EjudgeProblem.id

    Ещё это даёт нам интересные эффекты, например
    query(EjudgeProblem).all() вернёт как EjudgeProblem, так и Problem, a
    query(EjudgeProblem).filter(EjudgeProblem.id == 6).all() -- только Problem
    А вот такое query(EjudgeProblem).get(6) -- вообще вернёт None, потому что join не отработает
    Ещё в Runs у нас ссылка на обе таблицы, и это тоже работает нормально
    """

    __table_args__ = (
        db.Index('ejudge_contest_id_problem_id', 'ejudge_contest_id', 'problem_id'),
        {'schema':'moodle', 'extend_existing': True}
    )
    __tablename__ = 'mdl_ejudge_problem'
    __mapper_args__ = {'polymorphic_identity': 'ejudgeproblem'}

    ejudge_prid = db.Column('id', db.Integer, primary_key=True) #global id in ejudge
    contest_id = db.Column(db.Integer, primary_key=True, nullable=False, autoincrement=False)
    ejudge_contest_id = db.Column(db.Integer, primary_key=True, nullable=False, autoincrement=False)
    secondary_ejudge_contest_id = db.Column(db.Integer, nullable=True)
    problem_id = db.Column(db.Integer, primary_key=True, nullable=False, autoincrement=False) #id in contest
    short_id = db.Column(db.Unicode(50))
    ejudge_name = db.Column('name', db.Unicode(255))

    @staticmethod
    def create(**kwargs):
        """
        При создании EjudgeProblem сначала в базу пишет Problem потом EjudgeProblem,
        из-за чего pr_id не проставляется
        """
        instance = EjudgeProblem(**kwargs)
        db.session.add(instance)
        db.session.flush([instance])

        problem_id = instance.id
        ejudge_problem_id = instance.pr_id
        db.session.commit()

        problem_instance = db.session.query(Problem).filter_by(id=problem_id).one()
        problem_instance.pr_id = ejudge_problem_id
        db.session.commit()

        return db.session.query(EjudgeProblem).filter_by(id=problem_id).one()

    @deprecated('view.serializers.ProblemSchema')
    def serialize(self):
        if self.sample_tests:
            self.generateSamplesJson(force_update=True)

        attrs = [
            'id',
            'name',
            'content',
            'timelimit',
            'memorylimit',
            'show_limits',
            'sample_tests_json',
            'output_only',
        ]
        problem_dict = {
            attr: getattr(self, attr, 'undefined')
            for attr in attrs
        }
        problem_dict['content'] = problem_dict['content'].replace("\\)", "$").replace("\\(", "$")
        # problem_dict['languages'] = context.get_allowed_languages()
        return problem_dict

    def get_test(self, test_num, size=255):
        conf = EjudgeContestCfg(number=self.ejudge_contest_id)
        prob = conf.getProblem(self.problem_id)

        test_file_name = (prob.tests_dir + prob.test_pat) % int(test_num)
        error_str = None
        if os.path.exists(test_file_name):
            res = read_file_unknown_encoding(test_file_name, size)
        else:
            res = test_file_name
        return res

    def get_test_size(self, test_num):
        conf = EjudgeContestCfg(number=self.ejudge_contest_id)
        prob = conf.getProblem(self.problem_id)

        test_file_name = (prob.tests_dir + prob.test_pat) % int(test_num)
        return os.stat(test_file_name).st_size

    def get_corr(self, test_num, size=255):
        conf = EjudgeContestCfg(number = self.ejudge_contest_id)
        prob = conf.getProblem(self.problem_id)

        corr_file_name = (prob.tests_dir + prob.corr_pat) % int(test_num)
        error_str = None
        if os.path.exists(corr_file_name):
            res = read_file_unknown_encoding(corr_file_name, size)
        else:
            res = corr_file_name
        return res

    def get_test_full(self, test_num, size=255):
        """
        Возвращает словарь с полной информацией о тесте
        """
        test = {}
        if self.get_test_size(int(test_num)) <= 255:
            test["input"] = self.get_test(int(test_num), size=size)
            test["big_input"] = False
        else:
            test["input"] = self.get_test(int(test_num), size=size) + "...\n"
            test["big_input"] = True

        if self.get_corr_size(int(test_num)) <= 255:
            test["corr"] = self.get_corr(int(test_num), size=size)
            test["big_corr"] = False
        else:
            test["corr"] = self.get_corr(int(test_num), size=size) + "...\n"
            test["big_corr"] = True
        return test

    def get_corr_size(self, test_num):
        conf = EjudgeContestCfg(number = self.ejudge_contest_id)
        prob = conf.getProblem(self.problem_id)

        corr_file_name = (prob.tests_dir + prob.corr_pat) % int(test_num)
        return os.stat(corr_file_name).st_size

    def get_checker(self):
        conf = EjudgeContestCfg(number = self.ejudge_contest_id)
        prob = conf.getProblem(self.problem_id)

        #generate dir with checker
        checker_dir = None
        if conf.advanced_layout:
            checker_dir = os.path.join(conf.contest_path, "problems", prob.internal_name)
        else:
            checker_dir = os.path.join(conf.contest_path, "checkers")

        #trying to find checker
        find_res = glob.glob(os.path.join(checker_dir, "check_{0}.*".format(prob.internal_name)))
        check_src = None
        checker_ext = None
        if find_res:
            check_src = open(find_res[0], "r").read()
            checker_ext = os.path.splitext(find_res[0])[1]

        #if checker not found then try polygon package
        downloads_dir = os.path.join(conf.contest_path, "download")
        if check_src is None and os.path.exists(downloads_dir):
            download_archive_mask = "{0}-*$linux.zip".format(prob.internal_name)
            find_archive_result = glob.glob(os.path.join(downloads_dir, download_archive_mask))
            download_archive_path = find_archive_result[0] if find_archive_result else None
            archive = None
            if download_archive_path is not None:
                archive = ZipFile(download_archive_path)
            if archive is not None:
                member_path = None
                for file in archive.namelist():
                    if file.startswith("check."):
                        member_path = file
                        break
                try:
                    check_src = archive.open(member_path).read()
                    checker_ext = os.path.splitext(member_path)[1]
                except KeyError:
                    check_src = None

        if check_src is None:
            check_src = "checker not found"

        return check_src, checker_ext

    def generateSamples(self):
        res = ""
        if self.sample_tests != '':
            res = "<div class='problem-statement'><div class='sample-tests'><div class='section-title'>Примеры</div>"

            for i in self.sample_tests.split(","):
                inp = self.get_test(i, 4096)
                if inp[-1] == '\n':
                    inp = inp[:-1]
                corr = self.get_corr(i, 4096)
                if corr[-1] == '\n':
                    corr = corr[:-1]
                res += "<div class='sample-test'>"
                res += "<div class='input'><div class='title'>Входные данные</div><pre class='content'>"
                res += inp
                res += "</pre></div><div class='output'><div class='title'>Выходные данные</div><pre class='content'>"
                res += corr
                res += "</pre></div></div>"

            res += "</div></div>"

        self.sample_tests_html = res
        return self.sample_tests

    def generateSamplesJson(self, force_update=False):
        if self.sample_tests != '':
            if not self.sample_tests_json:
                self.sample_tests_json = {}
            for test in self.sample_tests.split(','):
                if not force_update and test in self.sample_tests_json:
                    continue

                test_input = self.get_test(test, 4096)
                test_correct = self.get_corr(test, 4096)

                self.sample_tests_json[test] = {
                    'input': test_input,
                    'correct': test_correct,
                }
コード例 #12
0
                    ))
            return query

        return cls.search(filter_func)

    @lazy
    def _get_current_olymp(self):
        return None


class PynformaticsUser(User):
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_user_settings'
    __mapper_args__ = {'polymorphic_identity': 'pynformaticsuser'}

    id = db.Column(db.Integer,
                   db.ForeignKey('moodle.mdl_user.id'),
                   primary_key=True)
    main_page_settings = db.Column(db.Text)


# SQLAlchemy Core table to avoiding class instance creation
LightWeightUser = Table('mdl_user',
                        MetaData(),
                        db.Column('id', db.Integer, primary_key=True),
                        db.Column('firstname', db.Unicode(100)),
                        db.Column('lastname', db.Unicode(100)),
                        db.Column('email', db.Unicode(100)),
                        db.Column('username', db.Unicode(100)),
                        schema='moodle')
コード例 #13
0
ファイル: user.py プロジェクト: shestimerov/informatics-alive
                        cls.firstname.like("%{}%".format(search_string)),
                        cls.lastname.like("%{}%".format(search_string)),
                    ))
            return query

        return cls.search(filter_func)

    @lazy
    def _get_current_olymp(self):
        return None


class PynformaticsUser(User):
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_user_settings'
    __mapper_args__ = {'polymorphic_identity': 'pynformaticsuser'}

    id = db.Column(db.Integer,
                   db.ForeignKey('moodle.mdl_user.id'),
                   primary_key=True)
    main_page_settings = db.Column(db.Text)


# SQLAlchemy Core table to avoiding class instance creation
LightWeightUser = Table('mdl_user',
                        MetaData(),
                        db.Column('id', db.Integer, primary_key=True),
                        db.Column('firstname', db.Unicode(100)),
                        db.Column('lastname', db.Unicode(100)),
                        schema='moodle')
コード例 #14
0
 def name(cls):
     return db.Column(db.Unicode(255))
コード例 #15
0
class Statement(CourseModuleInstance, db.Model):
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_statements'
    __mapper_args__ = {
        'polymorphic_identity': 'statement',
        'concrete': True,
    }

    MODULE = 19

    id = db.Column(db.Integer, primary_key=True)
    course_id = db.Column('course', db.Integer,
                          db.ForeignKey('moodle.mdl_course.id'))
    name = db.Column(db.Unicode(255))
    summary = db.Column(MEDIUMTEXT)
    numbering = db.Column(db.Integer)
    disable_printing = db.Column('disableprinting', db.Boolean)
    custom_titles = db.Column('customtitles', db.Boolean)
    time_created = db.Column('timecreated', db.Integer)
    time_modified = db.Column('timemodified', db.Integer)
    contest_id = db.Column(db.Integer)
    time_start = db.Column('timestart', db.Integer)
    time_stop = db.Column('timestop', db.Integer)
    olympiad = db.Column(db.Boolean)
    virtual_olympiad = db.Column(db.Boolean)
    virtual_duration = db.Column(db.Integer)
    settings = db.Column(JsonType)

    course = db.relationship('Course',
                             backref=db.backref('statements', lazy='dynamic'))

    problems = association_proxy('StatementProblems', 'problem')
    user = association_proxy('StatementUsers1', 'user')

    SETTINGS_SCHEMA = {
        'type': 'object',
        'properties': {
            'allowed_languages': {
                'type': 'array',
                'uniqueItems': True,
                'items': {
                    'type': 'integer',
                    'enum': list(LANG_NAME_BY_ID.keys()),
                }
            },
            'type': {
                'oneOf': [{
                    'type': 'null',
                }, {
                    'type': 'string',
                    'enum': [
                        'olympiad',
                        'virtual',
                    ],
                }],
            },
            'group': {
                'type': 'integer',
            },
            'team': {
                'type': 'boolean',
            },
            'time_start': {
                'type': 'integer',
            },
            'time_stop': {
                'type': 'integer',
            },
            'freeze_time': {
                'type': 'integer',
            },
            'standings': {
                'type': 'boolean',
            },
            'test_only_samples': {
                'type': 'boolean',
            },
            'reset_submits_on_start': {
                'type': 'boolean',
            },
            'test_until_fail': {
                'type': 'boolean',
            },
            'start_from_scratch': {
                'type': 'boolean',
            },
            'restrict_view': {
                'type': 'boolean',
            }
        },
        'additionalProperties': False,
    }
    SETTINGS_SCHEMA_VALIDATOR = Draft4Validator(SETTINGS_SCHEMA)

    def get_allowed_languages(self):
        if not (self.settings and 'allowed_languages' in self.settings):
            return None
        return self.settings['allowed_languages']

    def set_settings(self, settings):
        validation_error = next(
            self.SETTINGS_SCHEMA_VALIDATOR.iter_errors(settings), None)
        if validation_error:
            raise ValueError(validation_error.message)
        self.settings = settings

        if settings.get('time_start'):
            self.time_start = settings['time_start']

        if settings.get('time_stop'):
            self.time_stop = settings['time_stop']

        if 'type' in settings:
            type_ = settings['type']
            if type_ == None:
                self.olympiad = False
                self.virtual_olympiad = False
            elif type_ == 'olympiad':
                self.olympiad = True
                self.virtual_olympiad = False
            else:
                self.olympiad = False
                self.virtual_olympiad = True

        self.time_modified = int(time.time())

    def start_participant(
        self,
        user,
        duration,
        password=None,
    ):
        if self.course \
                and self.course.require_password() \
                and password != self.course.password:
            raise ValueError()

        if self.participants.filter(Participant.user_id == user.id).count():
            raise ValueError()

        if user.get_active_participant():
            raise ValueError()

        new_participant = Participant(
            user_id=user.id,
            statement_id=self.id,
            start=int(time.time()),
            duration=duration,
        )
        db.session.add(new_participant)

        return new_participant

    def finish_participant(self, user):
        active_participant = user.get_active_participant()
        if not active_participant or active_participant.statement_id != self.id:
            raise ValueError()

        active_participant.duration = int(time.time() -
                                          active_participant.start)
        return active_participant

    def start(
        self,
        user,
        password=None,
    ):
        if not self.olympiad:
            raise ValueError()

        now = time.time()
        if now < self.time_start:
            raise ValueError()
        if now >= self.time_stop:
            raise ValueError()

        return self.start_participant(
            user=user,
            duration=self.time_stop - int(time.time()),
            password=password,
        )

    def finish(self, user):
        if not self.olympiad:
            raise ValueError()

        return self.finish_participant(user)

    def serialize(self, attributes=None):
        if not attributes:
            attributes = (
                'id',
                'name',
                'olympiad',
                'settings',
                'time_start',
                'time_stop',
                'virtual_olympiad',
                'virtual_duration',
                'course_module_id',
                'course',
                'require_password',
            )
        serialized = attrs_to_dict(self, *attributes)
        if 'course' in attributes and self.course:
            serialized['course'] = self.course.serialize()
        serialized['course_module_id'] = getattr(self.course_module, 'id',
                                                 None)

        if 'require_password' in attributes:
            if self.course:
                serialized['require_password'] = self.course.require_password()
            else:
                serialized['require_password'] = False

        user = getattr(g, 'user', None)
        if self.olympiad or self.virtual_olympiad:
            if not user:
                return serialized

            try:
                participant = self.participants.filter_by(
                    user_id=user.id).one()
            except NoResultFound:
                return serialized

            serialized['participant'] = participant.serialize()

        serialized['problems'] = {
            rank: {
                'id': statement_problem.problem.id,
                'name': statement_problem.problem.name,
            }
            for rank, statement_problem in self.StatementProblems.items()
            if statement_problem.problem and not statement_problem.hidden
        }
        return serialized