class MessageModel(db.Model): __tablename__ = 'message' id = db.Column(db.Integer, primary_key=True) from_user_id = db.Column(db.Integer(), nullable=False, index=True) to_user_id = db.Column(db.Integer(), nullable=False, index=True) title = db.Column(db.String(512), nullable=False) content = db.Column(db.UnicodeText(), nullable=False) is_read = db.Column(db.Boolean(), server_default=sql.false(), nullable=False, index=True) date_created = db.Column(db.DateTime, nullable=False, index=True, server_default=db.func.current_timestamp()) @staticmethod def get_unread_count(user_id): return MessageModel.query.filter( MessageModel.to_user_id == user_id, MessageModel.is_read.is_(False), ).count() def as_dict(self): return { 'id': self.id, 'title': self.title, } def __repr__(self): return '<Message %r>' % self.title
class NewsModel(db.Model): __tablename__ = 'news' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer(), nullable=False, index=True) title = db.Column(db.String(512), nullable=False) content = db.Column(db.UnicodeText(), nullable=False) is_display = db.Column(db.Boolean, default=True, server_default=sql.true(), nullable=False, index=True) date_created = db.Column(db.DateTime, nullable=False, index=True, server_default=db.func.current_timestamp()) @property def url(self): return url_for('news.detail', news_id=self.id) def as_dict(self): return { 'id': self.id, 'title': self.title, } @staticmethod def generate_fake(count=100): from sqlalchemy.exc import IntegrityError from random import seed, randint import forgery_py seed() user_count = UserModel.query.count() if user_count == 0: UserModel.generate_fake() user_count = UserModel.query.count() for i in range(count): u = UserModel.query.offset(randint(0, user_count - 1)).first() n = NewsModel(user_id=u.id, title=forgery_py.lorem_ipsum.title(), content=forgery_py.lorem_ipsum.paragraphs()) db.session.add(n) try: db.session.commit() except IntegrityError: db.session.rollback() def __repr__(self): return '<News %r>' % self.title
class RegistryModel(db.Model): __tablename__ = 'registry' key = db.Column(db.String(100), nullable=False, primary_key=True) name = db.Column(db.Unicode(1024), nullable=False) meta = db.Column(JSON, nullable=False, default=[]) value = db.Column(JSON, default=[]) def as_dict(self): return {'key': self.key, 'name': self.name, 'value': self.value} def save_to_cache(self): if app.config['TESTING']: return redis.set(self.redis_key(self.key), json.dumps(self.value)) @classmethod def get_from_cache(cls, key): if app.config['TESTING']: return raw = redis.get(cls.redis_key(key)) if raw: return json.loads(raw) @classmethod def fetch(cls, key): value = cls.get_from_cache(key) if value is not None: return value registry = cls.query.get(key) if registry: registry.save_to_cache() return registry.value return [] @classmethod def redis_key(cls, key): return 'admin-registry::%s' % key
class RoleModel(db.Model): __tablename__ = 'role' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True, index=True) default = db.Column(db.Boolean, default=False, index=True, server_default=sql.false()) permissions = db.Column(db.Integer) date_created = db.Column(db.DateTime, nullable=False, server_default=db.func.current_timestamp()) @staticmethod def insert_roles(): roles = { 'User': (Permission.SUBMIT, True), 'Teacher': (Permission.SUBMIT | Permission.VIEW_CODE, False), 'Administrator': (0xff, False) } for r in roles: role = RoleModel.query.filter_by(name=r).first() if role is None: role = RoleModel(name=r) role.permissions = roles[r][0] role.default = roles[r][1] db.session.add(role) db.session.commit() def __repr__(self): return '<Role %r>' % self.name def as_dict(self): return { 'id': self.id, 'name': self.name, 'permissions': self.permissions, }
class ProblemModel(db.Model): __tablename__ = 'problem' id = db.Column(db.Integer, Sequence('problem_id_seq', start=1000, increment=1), primary_key=True) title = db.Column(db.String(512), nullable=False) time_limit = db.Column(db.Integer, nullable=False) memory_limit = db.Column(db.Integer, nullable=False) description = db.Column(db.UnicodeText()) input = db.Column(db.UnicodeText()) output = db.Column(db.UnicodeText()) sample_input = db.Column(db.UnicodeText()) sample_output = db.Column(db.UnicodeText()) sample_code = db.Column(db.UnicodeText()) hint = db.Column(db.UnicodeText()) source = db.Column(db.String(512)) author = db.Column(db.String(128)) is_display = db.Column(db.Boolean, default=True, server_default=sql.true(), nullable=True, index=True) is_special_judge = db.Column(db.Boolean, default=False, server_default=sql.false(), nullable=True, index=True) date_modified = db.Column(db.DateTime, nullable=False, index=True, server_default=db.func.current_timestamp()) date_created = db.Column(db.DateTime, nullable=False, index=True, server_default=db.func.current_timestamp()) _statistics = db.relationship( 'ProblemStatisticsModel', primaryjoin='ProblemModel.id==ProblemStatisticsModel.id', foreign_keys='[ProblemStatisticsModel.id]', backref='problem', uselist=False, passive_deletes='all') solutions = db.relationship( 'SolutionModel', primaryjoin='SolutionModel.problem_id==ProblemModel.id', foreign_keys='[SolutionModel.problem_id]', backref=db.backref('problem', uselist=False, lazy=True), order_by='SolutionModel.date_created.desc()', passive_deletes='all', lazy='dynamic') accepts = db.relationship( 'SolutionModel', primaryjoin= 'and_(SolutionModel.problem_id==ProblemModel.id, SolutionModel.result==1)', foreign_keys='[SolutionModel.problem_id]', order_by='SolutionModel.date_created.desc()', passive_deletes='all', lazy='dynamic') solution_users = db.relationship( 'UserModel', secondary=lambda: SolutionModel.__table__, primaryjoin='ProblemModel.id==SolutionModel.problem_id', secondaryjoin='UserModel.id==SolutionModel.user_id', order_by='SolutionModel.date_created.desc()', foreign_keys='[SolutionModel.user_id, SolutionModel.problem_id]', lazy='dynamic') accept_users = db.relationship( 'UserModel', secondary=lambda: SolutionModel.__table__, primaryjoin= 'and_(SolutionModel.problem_id==ProblemModel.id, SolutionModel.result==1)', secondaryjoin='UserModel.id==SolutionModel.user_id', order_by='SolutionModel.date_created.desc()', foreign_keys='[SolutionModel.user_id, SolutionModel.problem_id]', lazy='dynamic') def __init__(self, **kwargs): super(ProblemModel, self).__init__(**kwargs) self._statistics = ProblemStatisticsModel() @staticmethod def generate_fake(count=100): from sqlalchemy.exc import IntegrityError from random import seed, randint, choice import forgery_py seed() for i in range(count): p = ProblemModel(title=forgery_py.lorem_ipsum.title(), time_limit=randint(1, 5) * 1000, memory_limit=choice([2 << 14, 2 << 15]), description=forgery_py.lorem_ipsum.paragraphs(), input=forgery_py.lorem_ipsum.paragraphs(), output=forgery_py.lorem_ipsum.paragraphs(), sample_input=forgery_py.lorem_ipsum.paragraphs(), sample_output=forgery_py.lorem_ipsum.paragraphs(), sample_code=forgery_py.lorem_ipsum.paragraphs(), hint=forgery_py.lorem_ipsum.paragraphs(), source=forgery_py.internet.domain_name(), author=forgery_py.internet.user_name(True), is_display=choice([True, False]), is_special_judge=choice([True, False])) db.session.add(p) try: db.session.commit() except IntegrityError: db.session.rollback() @hybrid_property def solutions_count(self): if self._statistics: return self._statistics.solutions_count else: return 0 @solutions_count.setter def solutions_count_setter(self, value): if not self._statistics: self._statistics = ProblemStatisticsModel() self._statistics.solutions_count = value @solutions_count.expression def solutions_count_expr(cls): return ProblemStatisticsModel.solutions_count @hybrid_property def accepts_count(self): if self._statistics: return self._statistics.accepts_count else: return 0 @accepts_count.setter def accepts_count_setter(self, value): if not self._statistics: self._statistics = ProblemStatisticsModel() self._statistics.accepts_count = value @accepts_count.expression def accepts_count_expr(cls): return ProblemStatisticsModel.accepts_count @hybrid_property def solution_users_count(self): if self._statistics: return self._statistics.solution_users_count else: return 0 @solution_users_count.setter def solution_users_count_setter(self, value): if not self._statistics: self._statistics = ProblemStatisticsModel() self._statistics.solution_users_count = value @solution_users_count.expression def solution_users_count_expr(cls): return ProblemStatisticsModel.solution_users_count @hybrid_property def accept_users_count(self): if self._statistics: return self._statistics.accept_users_count else: return 0 @accept_users_count.setter def accept_users_count_setter(self, value): if not self._statistics: self._statistics = ProblemStatisticsModel() self._statistics.accept_users_count = value @accept_users_count.expression def accept_users_count_expr(cls): return ProblemStatisticsModel.accept_users_count @property def url(self): return url_for('problem.detail', problem_id=self.id) @property def ratio(self): return '%.f%%' % round( self.accepts_count * 100.0 / self.solutions_count if self.solutions_count else 0) @classmethod def __declare_last__(cls): cls.current_user_has_solved = db.column_property(db.and_( db.current_user_id().isnot(None), db.exists().where(SolutionModel.user_id == db.current_user_id()). where(SolutionModel.problem_id == cls.id).where( SolutionModel.result == 1).correlate_except(SolutionModel)), deferred=True) cls.current_user_has_submitted = db.column_property(db.and_( db.current_user_id().isnot(None), db.exists().where( SolutionModel.user_id == db.current_user_id()).where( SolutionModel.problem_id == cls.id).correlate_except( SolutionModel)), deferred=True) def as_dict(self): return { 'id': self.id, 'title': self.title, 'time_limit': self.time_limit, 'memory_limit': self.memory_limit, 'description': self.description, 'input': self.input, 'output': self.output, 'sample_input': self.sample_input, 'sample_output': self.sample_output, 'sample_code': self.sample_code, 'hint': self.hint, 'source': self.source, 'author': self.author, 'is_display': self.is_display, 'is_special_judge': self.is_special_judge, 'date_modified': self.date_modified, 'date_created': self.date_created, 'solutions_count': self.solutions_count, 'accepts_count': self.accepts_count, 'ratio': self.ratio, 'url': self.url, 'current_user_has_solved': self.current_user_has_solved, 'current_user_has_submitted': self.current_user_has_submitted, } def __repr__(self): return '<Problem %r>' % self.title
class UserModel(UserMixin, db.Model): __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(256), unique=True, index=True, nullable=False) nickname = db.Column(db.String(256), unique=True, index=True, nullable=False) email = db.Column(db.String(256), unique=True, index=True, nullable=False) password_hash = db.Column(db.String(128), nullable=False) gender = db.Column(db.Enum('male', 'female', name='user_gender')) school = db.Column(db.String(256)) college = db.Column(db.String(256)) major = db.Column(db.String(256)) grade = db.Column(db.String(64)) clazz = db.Column(db.String(64)) program_language = db.Column( db.Enum('gcc', 'g++', 'java', name='user_program_language_enum')) avatar = db.Column(db.String(256)) qq = db.Column(db.String(64)) phone = db.Column(db.String(64)) address = db.Column(db.String(256)) role_id = db.Column(db.Integer) is_bulk_registration = db.Column(db.Boolean, default=False, server_default=sql.false(), nullable=True) confirmed = db.Column(db.Boolean, default=False, server_default=sql.false(), nullable=False) last_login_ip = db.Column(db.String(64)) current_login_ip = db.Column(db.String(64)) login_count = db.Column(db.Integer()) date_last_login = db.Column(db.DateTime, nullable=False, server_default=db.func.current_timestamp()) date_current_login = db.Column(db.DateTime, nullable=False, server_default=db.func.current_timestamp()) date_created = db.Column(db.DateTime, nullable=False, index=True, server_default=db.func.current_timestamp()) _statistics = db.relationship( 'UserStatisticsModel', primaryjoin='UserModel.id==UserStatisticsModel.id', foreign_keys='[UserStatisticsModel.id]', backref='user', uselist=False, cascade="all, delete-orphan", ) favorites = db.relationship( 'ProblemModel', secondary=lambda: UserFavoritesModel.__table__, primaryjoin='UserModel.id==UserFavoritesModel.user_id', secondaryjoin='ProblemModel.id==UserFavoritesModel.problem_id', order_by='UserFavoritesModel.date_created.desc()', foreign_keys= '[UserFavoritesModel.problem_id, UserFavoritesModel.user_id]', lazy='dynamic') message_sent = db.relationship( 'MessageModel', primaryjoin='MessageModel.from_user_id==UserModel.id', foreign_keys='[MessageModel.from_user_id]', backref=db.backref('user', lazy=True, uselist=False), order_by='MessageModel.date_created.desc()', lazy='dynamic') message_received = db.relationship( 'MessageModel', primaryjoin='MessageModel.to_user_id==UserModel.id', foreign_keys='[MessageModel.to_user_id]', order_by='MessageModel.date_created.desc()', lazy='dynamic') news = db.relationship('NewsModel', primaryjoin='NewsModel.user_id==UserModel.id', foreign_keys='[NewsModel.user_id]', backref=db.backref('user', lazy=True, uselist=False), order_by='NewsModel.date_created.desc()', lazy='dynamic') headlines = db.relationship( 'HeadlineModel', primaryjoin='HeadlineModel.user_id==UserModel.id', foreign_keys='[HeadlineModel.user_id]', backref=db.backref('user', lazy=True, uselist=False), order_by='HeadlineModel.date_created.desc()', lazy='dynamic') solutions = db.relationship( 'SolutionModel', primaryjoin='SolutionModel.user_id==UserModel.id', foreign_keys='[SolutionModel.user_id]', backref=db.backref('user', lazy=True, uselist=False), order_by='SolutionModel.date_created.desc()', passive_deletes='all', lazy='dynamic') accepts = db.relationship( 'SolutionModel', primaryjoin= 'and_(SolutionModel.user_id==UserModel.id, SolutionModel.result==1)', foreign_keys='[SolutionModel.user_id]', order_by='SolutionModel.date_created.desc()', passive_deletes='all', lazy='dynamic') role = db.relationship('RoleModel', primaryjoin='UserModel.role_id==RoleModel.id', foreign_keys='[UserModel.role_id]', backref=db.backref('user', lazy='dynamic'), lazy=True) def __init__(self, **kwargs): super(UserModel, self).__init__(**kwargs) self._statistics = UserStatisticsModel() @property def email_md5(self): email = self.email.strip() if isinstance(email, unicode): email = email.encode('utf-8') return md5(email).hexdigest() def g_avatar(self, size=48, default='retro', rating='g'): return "{url}{hash}?d={default}&s={size}".format( url=current_app.config['GRAVATAR_BASE_URL'], hash=self.email_md5, default=default, size=size, rating=rating) @staticmethod def generate_fake(count=100): from sqlalchemy.exc import IntegrityError from random import seed import forgery_py seed() for i in range(count): u = UserModel(username=forgery_py.internet.user_name(True), nickname=forgery_py.internet.user_name(True), email=forgery_py.internet.email_address(), password='******') db.session.add(u) try: db.session.commit() except IntegrityError: db.session.rollback() @property def url(self): return url_for('profile.profile', user_id=self.id) @property def password(self): raise AttributeError('password is not a readable attribute') @password.setter def password(self, password): self.password_hash = generate_password_hash(password) def verify_password(self, password): return check_password_hash(self.password_hash, password) def generate_reset_token(self, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'reset': self.id}) def reset_password(self, token, new_password): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return False if data.get('reset') != self.id: return False self.password = new_password db.session.add(self) db.session.commit() return True def generate_confirmation_token(self, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'confirm': self.id}) def confirm(self, token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return False if data.get('confirm') != self.id: return False self.confirmed = True db.session.add(self) db.session.commit() return True def generate_email_change_token(self, new_email, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'change_email': self.id, 'new_email': new_email}) def change_email(self, token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return False if data.get('change_email') != self.id: return False new_email = data.get('new_email') if new_email is None: return False self.email = new_email db.session.add(self) db.session.commit() return True @hybrid_property def solutions_count(self): if self._statistics: return self._statistics.solutions_count else: return 0 @solutions_count.setter def solutions_count_setter(self, value): if not self._statistics: self._statistics = UserStatisticsModel() self._statistics.solutions_count = value @solutions_count.expression def solutions_count_expr(cls): return UserStatisticsModel.solutions_count @hybrid_property def accepts_count(self): if self._statistics: return self._statistics.accepts_count else: return 0 @accepts_count.setter def accepts_count_setter(self, value): if not self._statistics: self._statistics = UserStatisticsModel() self._statistics.accepts_count = value @accepts_count.expression def accepts_count_expr(cls): return UserStatisticsModel.accepts_count @property def ratio(self): return '%.f%%' % round( self.accepts_count * 100.0 / self.solutions_count if self.solutions_count else 0) def can(self, permissions): return (self.role is not None and (self.role.permissions & permissions) == permissions) def is_administrator(self): return self.can(Permission.ADMINISTER) def as_dict(self): return { 'id': self.id, 'username': self.username, } def __repr__(self): return '<User %r>' % self.username
class ContestUserModel(db.Model): __tablename__ = 'contest_user' id = db.Column(db.Integer, primary_key=True) contest_id = db.Column(db.Integer(), nullable=False, index=True) team_name = db.Column(db.Unicode(256), nullable=False) status = db.Column(db.Enum('accept', 'waiting', 'reject', 'again', name='contest_user_status_enum'), server_default='waiting', nullable=False, index=True) seat_number = db.Column(db.Unicode(128)) reason = db.Column(db.Unicode(256)) user_id = db.Column(db.Integer(), nullable=False, index=True) student_id = db.Column(db.String(32)) name = db.Column(db.Unicode(256)) school = db.Column(db.Unicode(256)) college = db.Column(db.Unicode(256)) major = db.Column(db.Unicode(256)) clazz = db.Column(db.Unicode(256)) phone = db.Column(db.String(32)) email = db.Column(db.String(256)) student_id1 = db.Column(db.String(32)) name1 = db.Column(db.Unicode(256)) school1 = db.Column(db.Unicode(256)) college1 = db.Column(db.Unicode(256)) major1 = db.Column(db.Unicode(256)) clazz1 = db.Column(db.Unicode(256)) phone1 = db.Column(db.String(32)) email1 = db.Column(db.String(256)) student_id2 = db.Column(db.String(32)) name2 = db.Column(db.Unicode(256)) school2 = db.Column(db.Unicode(256)) college2 = db.Column(db.Unicode(256)) major2 = db.Column(db.Unicode(256)) clazz2 = db.Column(db.Unicode(256)) phone2 = db.Column(db.String(32)) email2 = db.Column(db.String(256)) date_created = db.Column(db.DateTime, nullable=False, index=True, server_default=db.func.current_timestamp()) solutions = db.relationship( 'SolutionModel', primaryjoin= 'and_(SolutionModel.user_id==ContestUserModel.user_id, SolutionModel.contest_id==ContestUserModel.contest_id)', foreign_keys='[SolutionModel.user_id, SolutionModel.contest_id]', backref=db.backref('contest_user', lazy=True), order_by='SolutionModel.date_created.desc()', passive_deletes='all', lazy='dynamic') accepts = db.relationship( 'SolutionModel', primaryjoin= 'and_(SolutionModel.user_id==ContestUserModel.user_id, SolutionModel.contest_id==ContestUserModel.contest_id, SolutionModel.result==1)', foreign_keys='[SolutionModel.user_id, SolutionModel.contest_id]', order_by='SolutionModel.date_created.desc()', passive_deletes='all', lazy='dynamic') def as_dict(self): return { 'id': self.id, } def __repr__(self): return '<ContestUser %r>' % self.id
class ContestModel(db.Model): __tablename__ = 'contest' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.Unicode(512), nullable=False) date_start = db.Column(db.DateTime, nullable=False) date_end = db.Column(db.DateTime, nullable=False) description = db.Column(db.UnicodeText) type = db.Column(db.Enum('public', 'private', 'register', 'diy', name='contest_type_enum'), server_default='public', nullable=False) user_id = db.Column(db.Integer(), nullable=False, index=True) password_hash = db.Column(db.String(128)) date_start_register = db.Column(db.DateTime) date_end_register = db.Column(db.DateTime) is_hidden = db.Column(db.Boolean, default=False, server_default=sql.false(), nullable=True) date_created = db.Column(db.DateTime, nullable=False, index=True, server_default=db.func.current_timestamp()) user = db.relationship('UserModel', primaryjoin='UserModel.id==ContestModel.user_id', foreign_keys='[ContestModel.user_id]', lazy=True) contest_users = db.relationship( 'ContestUserModel', primaryjoin= 'and_(ContestUserModel.contest_id==ContestModel.id, ContestModel.type=="register")', foreign_keys='[ContestUserModel.contest_id]', backref=db.backref('contest', lazy=True), passive_deletes='all', lazy='dynamic') solutions = db.relationship( 'SolutionModel', primaryjoin='SolutionModel.contest_id==ContestModel.id', foreign_keys='[SolutionModel.contest_id]', backref=db.backref('contest', lazy=True, uselist=False), order_by='SolutionModel.date_created.desc()', passive_deletes='all', lazy='dynamic') problems = db.relationship( 'ContestProblemModel', primaryjoin='ContestProblemModel.contest_id==ContestModel.id', foreign_keys='[ContestProblemModel.contest_id]', backref=db.backref('contest', lazy=True), order_by='(ContestProblemModel.ordinal, ContestProblemModel.id)', passive_deletes='all', lazy='dynamic') @staticmethod def generate_fake(count=100): from sqlalchemy.exc import IntegrityError from random import seed, randint, choice import forgery_py seed() now = datetime.datetime.now() user_count = UserModel.query.count() if user_count == 0: UserModel.generate_fake() user_count = UserModel.query.count() for i in range(count): date_start = now + datetime.timedelta(randint(-100, 100)) date_end = date_start + datetime.timedelta(hours=randint(2, 10)) date_end_register = date_start - datetime.timedelta(randint(1, 5)) date_start_register = date_end_register - datetime.timedelta( randint(1, 10)) u = UserModel.query.offset(randint(0, user_count - 1)).first() c = ContestModel( name=forgery_py.lorem_ipsum.title(), date_start=date_start, date_end=date_end, description=forgery_py.lorem_ipsum.paragraph(), type=choice(['public', 'private', 'register', 'diy']), user_id=u.id, password='******', date_start_register=date_start_register, date_end_register=date_end_register, ) db.session.add(c) try: db.session.commit() except IntegrityError: db.session.rollback() @property def url(self): return url_for('contest.detail', contest_id=self.id) @property def status(self): now = datetime.datetime.now() if now < self.date_start: status = 'pending' elif now > self.date_end: status = 'ended' else: status = 'running' return status @property def password(self): raise AttributeError('password is not a readable attribute') @password.setter def password(self, password): self.password_hash = generate_password_hash(password) def verify_password(self, password): return check_password_hash(self.password_hash, password) def as_dict(self): return { 'id': self.id, 'name': self.name, } def __repr__(self): return '<Contest %r>' % self.name