class Participant(db.Model): __table_args__ = {'schema': 'moodle'} __tablename__ = 'mdl_virtualcontest' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_user.id')) statement_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_statements.id')) start = db.Column(db.Integer) duration = db.Column(db.Integer) user = db.relationship('SimpleUser', backref=db.backref('pariticipants', lazy='dynamic')) statement = db.relationship('Statement', backref=db.backref('participants', lazy='dynamic')) def finished(self): return time.time() >= self.start + self.duration def serialize(self): return attrs_to_dict( self, 'start', 'duration', 'statement_id', )
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)
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'))
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): 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 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 GroupInvite(db.Model): __table_args__ = {'schema': 'pynformatics'} __tablename__ = 'group_invite' REDIRECT_COURSE = 'COURSE' REDIRECT_STATEMENT = 'STATEMENT' REDIRECT_TYPES = [ REDIRECT_COURSE, REDIRECT_STATEMENT, ] id = db.Column(db.Integer, primary_key=True) group_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_ejudge_group.id')) creator_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_user.id')) redirect_type = db.Column(db.Enum(*REDIRECT_TYPES)) instance_id = db.Column(db.Integer) disabled = db.Column(db.Boolean, default=False) deleted = db.Column(db.Boolean, default=False) group = db.relationship('Group', backref='group_invites', lazy='joined') creator = db.relationship('SimpleUser', backref='group_invites', lazy='joined') @property def redirect(self): if self.redirect_type == GroupInvite.REDIRECT_COURSE: return {'course_id': self.instance_id} elif self.redirect_type == GroupInvite.REDIRECT_STATEMENT: return {'statement_id': self.instance_id} else: raise NotImplementedError @property def url(self): return encode(self.id) @staticmethod def get_by_url(url): try: id = decode(url) except Exception: raise GroupNotFound group = db.session.query(GroupInvite).filter_by(id=id).first() if not group: raise GroupNotFound return group def serialize(self, attributes=None): if attributes is None: attributes = ('group_id', 'creator_id', 'redirect', 'disabled', 'url') serialized = attrs_to_dict(self, *attributes) 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, }
class RoleAssignment(db.Model): __tablename__ = 'mdl_role_assignments' __table_args__ = {'schema': 'moodle'} id = db.Column(db.Integer, primary_key=True) role_id = db.Column('roleid', db.Integer, db.ForeignKey('moodle.mdl_role.id')) context_id = db.Column('contextid', db.Integer, db.ForeignKey('moodle.mdl_context.id')) user_id = db.Column('userid', db.Integer, db.ForeignKey('moodle.mdl_user.id')) role = db.relationship('Role', lazy='joined') context = db.relationship('Context', lazy='joined')
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')) def __init__(self, *args, **kwargs): super(Problem, self).__init__(*args, **kwargs) self.hidden = 1 self.show_limits = True
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 PynformaticsRun(db.Model): __table_args__ = ( db.ForeignKeyConstraint( ['run_id', 'contest_id'], ['ejudge.runs.run_id', 'ejudge.runs.contest_id'], ), { 'schema': 'pynformatics' }, ) __tablename__ = 'run' run_id = db.Column('run_id', db.ForeignKey('ejudge.runs.run_id'), primary_key=True) contest_id = db.Column('contest_id', db.ForeignKey('ejudge.runs.contest_id'), primary_key=True) statement_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_statements.id')) source = db.Column(db.Text) run = db.relationship( 'EjudgeRun', foreign_keys='[PynformaticsRun.run_id, PynformaticsRun.contest_id]', backref=db.backref('pynformatics_run', lazy='joined', uselist=False), lazy='joined') statement = db.relationship('Statement', backref='pynformatics_runs') AUTHOR_ATTRS = [ 'source', ] def serialize(self, attributes=None): if not attributes: attributes = ('statement_id', ) serialized = attrs_to_dict(self, *attributes) user = getattr(g, 'user', None) if user and self.run.user.id == user.id: serialized.update( attrs_to_dict(self, *PynformaticsRun.AUTHOR_ATTRS)) return serialized
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
class UserOAuthProvider(db.Model): __table_args__ = {'schema': 'pynformatics'} __tablename__ = 'user_oauth_provider' user_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_user.id'), primary_key=True) provider = db.Column(db.String(255), primary_key=True) oauth_id = db.Column(db.String(255)) user = db.relationship('SimpleUser', backref=db.backref('oauth_ids', lazy='dynamic'))
class Log(db.Model): """ Модель лога действия пользователя. """ __table_args__ = {'schema': 'pynformatics'} __tablename__ = 'log' id = db.Column(db.Integer, primary_key=True, autoincrement=True) user_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_user.id')) instance_id = db.Column(db.Integer) action_id = db.Column(db.Integer, db.ForeignKey('pynformatics.action.id')) created_at = db.Column(db.DateTime, default=func.now()) action = db.relationship('Action', backref=db.backref('logs', lazy='select'), lazy='joined') user = db.relationship('SimpleUser', backref=db.backref('logs', lazy='select'), lazy='joined')
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
class Hint(db.Model): __table_args__ = {'schema': 'moodle'} __tablename__ = 'sis_hint' id = db.Column(db.Integer, primary_key=True) problem_id = db.Column(db.Integer, db.ForeignKey('moodle.mdl_problems.id')) contest_id = db.Column(db.Integer, db.ForeignKey('ejudge.runs.contest_id')) lang_id = db.Column(db.Integer) test_signature = db.Column(db.Unicode(255)) comment = db.Column(db.Text) def __init__(self, problem_id, contest_id, lang_id, test_signature, comment): self.problem_id = problem_id self.contest_id = contest_id self.lang_id = lang_id self.test_signature = test_signature self.comment = comment def get_by(contest_id, problem_id, lang_id, signature): try: # lang_id is ignored, cause we don't have hints for each language return db.session.query(Hint) \ .filter(Hint.contest_id == int(contest_id)) \ .filter(Hint.problem_id == int(problem_id)) \ .filter(Hint.test_signature == signature) \ .first() except: return None def __json__(self, request): return { 'id' : self.id, 'problem_id' : self.problem_id, 'contest_id': self.contest_id, 'lang_id' : self.lang_id, 'test_signature' : self.test_signature, 'comment': self.comment, }
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, }
class Run(db.Model): __table_args__ = ( db.ForeignKeyConstraint( ['ej_run_id', 'ej_contest_id'], ['ejudge.runs.run_id', 'ejudge.runs.contest_id'], ), {'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) create_time = db.Column(db.DateTime) user = db.relationship('SimpleUser', backref='runs') problem = db.relationship('EjudgeProblem', backref=db.backref('runs', lazy='dynamic')) statement = db.relationship('Statement', backref='runs') # Поля скопированные из 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_run = db.relationship('EjudgeRun', backref='run') def update_source(self, text=None): if not text: text = self.ejudge_run.get_sources() mongo.db.source.insert_one({ 'run_id': self.id, 'text': text.encode('utf-8'), }) return text @property def source(self): data = mongo.db.source.find_one({'run_id': self.id}) if not data: text = self.update_source() else: text = data.get('text', None) if text: text = text.decode('utf-8') return text @property def status(self): return self.ejudge_status @property def language_id(self): return self.ejudge_language_id @staticmethod 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, } @staticmethod def from_ejudge_run(ejudge_run): run = Run( user=ejudge_run.user, problem=ejudge_run.problem, score=ejudge_run.score, **Run.pick_ejudge_columns(ejudge_run), ) return run @staticmethod def sync(ejudge_run_id, ejudge_contest_id): ejudge_run = db.session.query(EjudgeRun).filter_by( run_id=ejudge_run_id, contest_id=ejudge_contest_id ).first() if not ejudge_run: return run = db.session.query(Run).filter_by( ejudge_run_id=ejudge_run_id, ejudge_contest_id=ejudge_contest_id, ).first() if run: run.score = ejudge_run.score for key, value in Run.pick_ejudge_columns(ejudge_run).items(): setattr(run, key, value) else: run = Run.from_ejudge_run(ejudge_run) db.session.add(run) return run 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
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 @staticmethod def serialize_run(run): serialized = attrs_to_dict( run, 'run_id', 'contest_id', 'create_time', 'score', 'status' ) serialized['create_time'] = serialized['create_time'].isoformat() serialized['problem_id'] = run.problem.id return serialized 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 GroupNotFound 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
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
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
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 StatementSettingsValidationError(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 StatementPasswordIsWrong if self.participants.filter(Participant.user_id == user.id).count(): raise StatementCanOnlyStartOnce if user.get_active_participant(): raise StatementOnlyOneOngoing 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 StatementNothingToFinish active_participant.duration = int(time.time() - active_participant.start) return active_participant def start(self, user, password=None, ): if not self.olympiad: raise StatementNotOlympiad now = time.time() if now < self.time_start: raise StatementNotStarted if now >= self.time_stop: raise StatementFinished return self.start_participant( user=user, duration=self.time_stop - int(time.time()), password=password, ) def finish(self, user): if not self.olympiad: raise StatementNotOlympiad return self.finish_participant(user) def start_virtual(self, user, password=None): if not self.virtual_olympiad: raise StatementNotVirtual return self.start_participant( user=user, duration=self.virtual_duration, password=password, ) def finish_virtual(self, user): if not self.virtual_olympiad: raise StatementNotVirtual 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