示例#1
0
class StatementProblem(db.Model):
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_statements_problems_correlation'

    id = db.Column(db.Integer, primary_key=True)
    statement_id = db.Column(db.Integer,
                             db.ForeignKey('moodle.mdl_statements.id'))
    problem_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_problems.id'))
    rank = db.Column('rank', db.Integer)
    hidden = db.Column('hidden', db.Integer)

    statement = db.relationship(
        'Statement',
        backref=db.backref(
            'StatementProblems',
            collection_class=attribute_mapped_collection("rank")))

    # reference to the "Keyword" object
    problem = db.relationship('Problem',
                              backref=db.backref('StatementProblems'))

    def __init__(self, statement_id, problem_id, rank):
        self.statement_id = statement_id
        self.problem_id = problem_id
        self.rank = rank
        self.hidden = 0
示例#2
0
class UserGroup(db.Model):
    __table_args__ = (
        db.UniqueConstraint('user_id', 'group_id', name='group_id'),
        {
            'schema': 'moodle'
        },
    )
    __tablename__ = 'mdl_ejudge_group_users'

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_user.id'))
    group_id = db.Column(db.Integer,
                         db.ForeignKey('moodle.mdl_ejudge_group.id'))

    user = db.relationship('SimpleUser',
                           backref=db.backref('user_groups', lazy='select'))
    group = db.relationship('Group',
                            backref=db.backref('user_groups', lazy='select'))

    @staticmethod
    def create_if_not_exists(user_id, group_id):
        user_group = db.session.query(UserGroup).filter_by(
            user_id=user_id, group_id=group_id).first()
        if user_group:
            return None

        return UserGroup(user_id=user_id, group_id=group_id)
示例#3
0
class StatementUser(db.Model):
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_olympiad'

    id = db.Column(db.Integer, primary_key=True)
    statement_id = db.Column('contest_id', db.Integer,
                             db.ForeignKey('moodle.mdl_statements.id'))
    user_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_user.id'))
示例#4
0
class MonitorStatement(db.Model):
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_monitors_statements'

    id = db.Column(db.Integer, primary_key=True)
    statement_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_statements.id'))
    monitor_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_monitors.id'))
    sort = db.Column(db.Integer)
class CourseModule(db.Model):
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_course_modules'

    id = db.Column(db.Integer, primary_key=True)
    course_id = db.Column('course', db.Integer, db.ForeignKey('moodle.mdl_course.id'))
    module = db.Column(db.Integer)
    instance_id = db.Column('instance', db.Integer)
    section_id = db.Column('section', db.Integer, db.ForeignKey('moodle.mdl_course_sections.id'))
    visible = db.Column(db.Boolean)

    course = db.relationship('Course', backref=db.backref('course_modules', lazy='dynamic'))
    section = db.relationship('CourseSection', backref=db.backref('modules', lazy='dynamic'))

    @property
    def instance(self) -> Type['CourseModuleInstance']:
        if not hasattr(self, '_instance'):
            instance_class = next(
                (
                    subclass
                    for subclass in CourseModuleInstance.__subclasses__()
                    if subclass.MODULE == self.module
                ),
                None
            )
            if not instance_class:
                self._instance = None
            else:
                self._instance = db.session.query(instance_class) \
                    .filter_by(id=self.instance_id) \
                    .first()
        return self._instance

    @deprecated(' `Do not use serialize inside model!` ')
    def serialize(self):
        serialized = attrs_to_dict(
            self,
            'id',
            'course_id',
            'module',
            'section_id',
            'visible',
        )
        if self.instance:
            serialized['type'] = self.instance.MODULE_TYPE
            if self.instance.MODULE_TYPE == 'STATEMENT':
                serialized['instance'] = attrs_to_dict(
                    self.instance,
                    'id',
                    'name',
                )
            elif self.instance.MODULE_TYPE in ['BOOK', 'MONITOR']:
                serialized['instance'] = self.instance.serialize(course_module_id=self.id)
            else:
                serialized['instance'] = self.instance.serialize()

        return serialized
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,
        }
示例#7
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
示例#8
0
class Rejudge(db.Model):
    __table_args__ = {'schema': 'pynformatics'}
    __tablename__ = 'rejudge'
    id = db.Column(db.Integer, primary_key=True)
    run_id = db.Column(db.Integer,
                       db.ForeignKey('pynformatics.runs.id'),
                       nullable=False)
    ejudge_contest_id = db.Column(db.Integer, nullable=False)
    ejudge_url = db.Column(db.String(50))
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)
class CourseSection(db.Model):
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_course_sections'

    id = db.Column(db.Integer, primary_key=True)
    course_id = db.Column('course', db.Integer,
                          db.ForeignKey('moodle.mdl_course.id'))
    section = db.Column(db.Integer)
    summary = db.Column(db.Text)
    sequence_text = db.Column('sequence', db.Text)
    visible = db.Column(db.Boolean)

    course = db.relationship('Course',
                             backref=db.backref(
                                 'sections',
                                 lazy='dynamic',
                                 order_by='CourseSection.section'))

    def __init__(self):
        self._sequence = None

    @property
    def sequence(self):
        if not getattr(self, '_sequence'):
            try:
                self._sequence = list(map(int, self.sequence_text.split(',')))
            except Exception:
                self._sequence = []
        return self._sequence

    @sequence.setter
    def sequence(self, value):
        self._sequence = value
        self.sequence_text = ','.join(list(map(str, value)))

    def serialize(self):
        serialized = attrs_to_dict(
            self,
            'id',
            'course_id',
            'section',
            'summary',
            'sequence',
            'visible',
        )
        serialized['modules'] = [
            module.serialize()
            for module in self.modules.filter_by(visible=True).all()
        ]

        return serialized
示例#11
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)
示例#12
0
class Stars(db.Model):
    __table_args__ = {'schema': 'moodle'}
    __tablename__ = 'mdl_stars'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_user.id'))
    title = db.Column(db.Text)
    link = db.Column(db.Text)

    def __init__(self, user, title, link):
        self.link = link
        self.title = title
        self.user_id = user.id

    def __json__(self, request):
        return {
            'id': self.id,
            'user_id': self.user_id,
            'title': self.title,
            'link': self.link,
        }
示例#13
0
class StatementStandings(StandingsMixin, db.Model):
    __tablename__ = 'statement_standings'

    statement_id = db.Column(db.Integer,
                             db.ForeignKey('moodle.mdl_statements.id'),
                             primary_key=True)
    statement = db.relationship('Statement',
                                backref=db.backref('standings',
                                                   uselist=False,
                                                   lazy='joined'))

    @classmethod
    def create(cls, **kwargs):
        instance = cls(**kwargs)
        db.session.add(instance)

        # Flush, чтобы получить из базы statement
        db.session.flush([instance])

        # Expire, чтобы у statement стал доступен standings
        db.session.expire(instance.statement)

        log.info(
            'StatementStandings(statement_id=%s) Created. Starting updates' %
            instance.statement_id)

        pynformatics_runs = db.session.query(PynformaticsRun) \
            .filter_by(statement_id=instance.statement_id) \
            .all()

        with db.session.no_autoflush:
            for pynformatics_run in pynformatics_runs:
                instance.update(pynformatics_run.run)

        log.info('StatementStandings(statement_id=%s) Updates finished.' %
                 instance.statement_id)

        return instance

    def update(self, run):
        user = run.user
        super(StatementStandings, self).update(user)

        runs = self.json[str(user.id)].get('runs', [])

        replace_index = index_of(
            runs, lambda run_json: run_json['run_id'] == run.run_id and
            run_json['contest_id'] == run.contest_id)

        if replace_index is not None:
            runs[replace_index] = StatementStandings.serialize_run(run)
        else:
            insert_index = index_of(
                runs, lambda run_json: run_json['create_time'] > run.
                create_time.isoformat(), len(runs))
            runs.insert(insert_index, StatementStandings.serialize_run(run))

        self.json[str(user.id)]['runs'] = runs
        self.json.changed()

    # TODO: добавить обработку настроек контеста
    def serialize(self, group_id=None):
        result = self.json
        if group_id:
            try:
                group = db.session.query(Group).filter_by(id=group_id).one()
            except Exception:
                raise ValueError('Group not found')

            result = {
                str(user_group.user_id): result[str(user_group.user_id)]
                for user_group in group.user_groups
                if str(user_group.user_id) in result
            }

        return result
示例#14
0
class Run(db.Model):
    __table_args__ = ({'schema': 'pynformatics'}, )
    __tablename__ = 'runs'

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_user.id'))
    problem_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_problems.id'))
    statement_id = db.Column(db.Integer,
                             db.ForeignKey('moodle.mdl_statements.id'))
    score = db.Column(db.Integer)

    user = db.relationship('SimpleUser', backref='runs', lazy='select')
    problem = db.relationship('EjudgeProblem',
                              backref=db.backref('runs', lazy='dynamic'))
    statement = db.relationship('Statement', backref='runs')

    create_time = db.Column(db.DateTime(), default=datetime.datetime.utcnow)

    # Поля скопированные из ejudge.runs
    ejudge_run_id = db.Column('ej_run_id', db.Integer)
    ejudge_contest_id = db.Column('ej_contest_id', db.Integer)
    ejudge_run_uuid = db.Column('ej_run_uuid', db.String(40))

    ejudge_score = db.Column('ej_score', db.Integer)
    ejudge_status = db.Column('ej_status', db.Integer)
    ejudge_language_id = db.Column('ej_lang_id', db.Integer)
    ejudge_test_num = db.Column('ej_test_num', db.Integer)

    ejudge_create_time = db.Column('ej_create_time', db.DateTime)
    ejudge_last_change_time = db.Column('ej_last_change_time', db.DateTime)
    ejudge_url = db.Column(db.String(50))

    source_hash = db.Column(db.String(32))  # We are using md5 hex digest

    def update_source(self, blob: bytes):
        mongo.db.source.insert_one({
            'run_id': self.id,
            'blob': blob,
        })
        return blob

    def remove_source(self):
        mongo.db.source.find_one_and_delete({'run_id': self.id})

    def move_protocol_to_rejudge_collection(self, rejudge_id: int):
        protocol = mongo.db.protocol.find_one({'run_id': self.id})
        if protocol:
            del protocol['_id']
            protocol['rejudge_id'] = rejudge_id
            mongo.db.rejudge.insert_one(protocol)
            mongo.db.protocol.find_one_and_delete({'run_id': self.id})

    @property
    def source(self) -> Optional[bytes]:
        data = mongo.db.source.find_one({'run_id': self.id})
        if data is None:
            logging.error(f'Cannot find source for run #{self.id}')
            return None
        blob = data.get('blob')
        return blob

    @property
    def protocol(self) -> Optional[dict]:
        return mongo.db.protocol.find_one({'run_id': self.id}, {'_id': False})

    @protocol.setter
    def protocol(self, protocol_source: dict):
        mongo.db.protocol.update({'run_id': self.id},
                                 protocol_source,
                                 upsert=True)

    @staticmethod
    def generate_source_hash(blob: bytes) -> str:
        m = hashlib.md5()
        m.update(blob)
        return m.hexdigest()

    @property
    def status(self):
        return self.ejudge_status

    @property
    def language_id(self):
        return self.ejudge_language_id

    @staticmethod
    @deprecated
    def pick_ejudge_columns(ejudge_run):
        return {
            'ejudge_run_id': ejudge_run.run_id,
            'ejudge_contest_id': ejudge_run.contest_id,
            'ejudge_run_uuid': ejudge_run.run_uuid,
            'ejudge_score': ejudge_run.score,
            'ejudge_status': ejudge_run.status,
            'ejudge_language_id': ejudge_run.lang_id,
            'ejudge_test_num': ejudge_run.test_num,
            'ejudge_create_time': ejudge_run.create_time,
            'ejudge_last_change_time': ejudge_run.last_change_time,
        }

    def serialize(self, attributes=None):
        if attributes is None:
            attributes = (
                'id',
                'user',
                'problem_id',
                'statement_id',
                'score',
                'status',
                'language_id',
                'create_time',
                'ejudge_run_id',
                'ejudge_contest_id',
            )
        if hasattr(g, 'user') and g.user.id == self.user_id:
            attributes = (
                *attributes,
                'source',
            )
        serialized = attrs_to_dict(self, *attributes)

        if 'create_time' in attributes:
            serialized['create_time'] = str(self.create_time)

        if 'user' in attributes:
            serialized['user'] = self.user.serialize()

        return serialized
示例#15
0
                'ejudge_contest_id',
            )
        if hasattr(g, 'user') and g.user.id == self.user_id:
            attributes = (
                *attributes,
                'source',
            )
        serialized = attrs_to_dict(self, *attributes)

        if 'create_time' in attributes:
            serialized['create_time'] = str(self.create_time)

        if 'user' in attributes:
            serialized['user'] = self.user.serialize()

        return serialized


# SQLAlchemy Core table to avoiding class instance creation
LightWeightRun = Table('runs',
                       MetaData(),
                       db.Column('id', db.Integer, primary_key=True),
                       db.Column('user_id', None,
                                 db.ForeignKey('moodle.mdl_user.id')),
                       db.Column('problem_id', db.Integer),
                       db.Column('create_time', db.DateTime),
                       db.Column('ej_score', db.Integer),
                       db.Column('ej_status', db.Integer),
                       db.Column('ej_test_num', db.Integer),
                       schema='pynformatics')
示例#16
0
                'source',
            )
        serialized = attrs_to_dict(self, *attributes)

        if 'create_time' in attributes:
            serialized['create_time'] = str(self.create_time)

        if 'user' in attributes:
            serialized['user'] = self.user.serialize()

        return serialized


# SQLAlchemy Core table to avoiding class instance creation
LightWeightRun = Table(
    'runs',
    MetaData(),
    db.Column('id', db.Integer, primary_key=True),
    db.Column('user_id', None, db.ForeignKey('moodle.mdl_user.id')),
    db.Column('problem_id', db.Integer),
    db.Column('create_time', db.DateTime),
    db.Column('ej_score', db.Integer),
    db.Column('ej_status', db.Integer),
    db.Column('ej_test_num', db.Integer),

    # Need for context-related WHERE clause
    db.Column('statement_id', db.Integer),
    db.Column('context_source', db.Integer),
    db.Column('is_visible', db.Boolean),
    schema='pynformatics')
示例#17
0
class ProblemStandings(StandingsMixin, db.Model):
    __tablename__ = 'problem_standings'
    __table_args__ = {'schema': 'pynformatics'}

    problem_id = db.Column(db.Integer,
                           db.ForeignKey('moodle.mdl_problems.id'),
                           primary_key=True)
    problem = db.relationship('EjudgeProblem',
                              backref=db.backref('standings',
                                                 uselist=False,
                                                 lazy='joined'))

    @classmethod
    def create(cls, **kwargs):
        instance = cls(**kwargs)
        db.session.add(instance)

        # Flush, чтобы получить из базы problem
        db.session.flush([instance])

        # Expire, чтобы у задачи стал доступен standings
        db.session.expire(instance.problem)

        log.info('ProblemStandings(problem_id=%s) Created. Starting updates' %
                 instance.problem_id)

        users = db.session.query(SimpleUser) \
            .join(EjudgeRun) \
            .filter(
                and_(
                    EjudgeRun.contest_id == instance.problem.ejudge_contest_id,
                    EjudgeRun.prob_id == instance.problem.problem_id
                )
            ) \
            .distinct() \
            .all()

        with db.session.no_autoflush:
            for i, user in enumerate(users):
                instance.update(user)

        log.info('ProblemStandings(problem_id=%s) Updates finished.' %
                 instance.problem_id)

        return instance

    def update(self, user):
        super(ProblemStandings, self).update(user)

        user_runs = self.problem.ejudge_runs \
            .filter_by(user_id=user.ejudge_id) \
            .order_by(EjudgeRun.create_time) \
            .all()

        processed = {
            'attempts': 0,
            'score': 0,
            'status': None,
        }
        for run in user_runs:
            processed['attempts'] += 1
            if run.score > processed['score']:
                processed['score'] = run.score
                processed['status'] = run.status

            if run.score == 100:
                break

        self.json[user.id].update(processed)

    def serialize(self):
        return self.json
示例#18
0
class Comment(db.Model):
    __table_args__ = (
        db.ForeignKeyConstraint(
            ['run_id', 'contest_id'], 
            ['ejudge.runs.run_id', 'ejudge.runs.contest_id']
        ),
        {'schema':'ejudge'}
    )
    __tablename__ = 'mdl_run_comments'
   
    id = db.Column(db.Integer, primary_key=True)
    date = db.Column(db.DateTime)
    run_id = db.Column(db.Integer)
    contest_id = db.Column(db.Integer)
    user_id = db.Column(db.Integer)
    author_user_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_user.id'))
    lines = db.Column(db.Text)
    comment = db.Column(db.UnicodeText)
    is_read = db.Column(db.Boolean)

    author_user = db.relationship(
        SimpleUser, 
        backref='simpleuser1', 
        uselist=False, 
        lazy=False, 
        primaryjoin=(author_user_id == SimpleUser.id),
    )
    run = db.relationship('EjudgeRun', backref='comment', uselist=False)

    def __init__(self,  run, author, lines='', comment='', date=datetime.datetime.now()):
        self.date = date
        self.run_id = run.run_id
        self.user_id = run.user.id
        self.contest_id = run.contest_id
        self.author_user_id = author.id
        self.lines = lines    
        self.comment = comment    
        self.is_read = False
        
    def __json__(self, request):
        return {
            'date' : str(self.date),
            'id' :  self.id,
            'run_id' : self.run_id,
            'user_id' : self.user_id,
            'contest_id' : self.contest_id,
            'author_user_id' : self.author_user_id,
            'lines' : self.lines,
            'comment' : self.comment,
            'is_read' : self.is_read,
            'problem_id' : self.run.problem.id,
            'problem_name' : self.run.problem.name
        }
    
    @staticmethod
    def get_by(run_id, contest_id):
        try:
            return db.session.query(Comment) \
                .filter(Comment.run.run_id == int(run_id)) \
                .filter(Comment.contest_id == int(contest_id)) \
                .first()            
        except:
            return None       
示例#19
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