class Player(db.Model): __tablename__ = 'player' id = db.Column(db.Integer, unique=True, primary_key=True) gameId = db.Column(db.Integer, db.ForeignKey('game.id'), nullable=False) game = db.relationship('Game', back_populates='players') name = db.Column(db.String(20), nullable=False) money = db.Column(db.Integer, nullable=False) moneyAfterRound = db.Column(db.Integer, nullable=True) hand = db.Column(db.Text, nullable=True) neighbourId = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=True) neighbourRight = db.relationship('Player', backref='neighbourLeft', remote_side='Player.id', uselist=False, post_update=True) isAdmin = db.Column(db.Boolean, nullable=False) isOnline = db.Column(db.Boolean, nullable=False) hasLeft = db.Column(db.Boolean, nullable=False, default=False) __table_args__ = (db.UniqueConstraint('name', 'gameId', name='_name_gameid_uc'), ) def __repr__(self): return '<Player %r>' % self.name
class Game(db.Model): __tablename__ = 'game' id = db.Column(db.Integer, primary_key=True) uniqueCode = db.Column(db.String(20), unique=True, nullable=False) params = db.Column(db.Text, nullable=False) roundsCompleted = db.Column(db.Integer, nullable=False) isComplete = db.Column(db.Boolean, default=False) isStarted = db.Column(db.Boolean, default=False) players = db.relationship('Player', back_populates='game', cascade='all,delete', order_by='asc(Player.id)') deck = db.relationship('DeckEntry', back_populates='game', cascade='all,delete', lazy=True) discard = db.relationship('DiscardEntry', back_populates='game', cascade='all,delete', lazy=True) rounds = db.relationship('GameRound', back_populates='game', cascade='all,delete', order_by='desc(GameRound.roundNo)') lastActionAt = db.Column(db.DateTime, nullable=False) def __repr__(self): return '<Game %r>' % self.uniqueCode
class RoundBattle(db.Model): __tablename__ = 'roundbattle' id = db.Column(db.Integer, primary_key=True) roundId = db.Column(db.Integer, db.ForeignKey('gameround.id'), nullable=False) round = db.relationship('GameRound', back_populates="battles") offendingPlayerId = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=True) offendingPlayer = db.relationship('Player', foreign_keys=[offendingPlayerId]) defendingPlayerId = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=True) defendingPlayer = db.relationship('Player', foreign_keys=[defendingPlayerId]) offensiveCardId = db.Column(db.Integer, db.ForeignKey('card.id'), nullable=True) offensiveCard = db.relationship('Card') defensiveCards = db.Column(db.Text, nullable=True) isComplete = db.Column(db.Boolean, default=False) creationOrder = db.Column(db.Integer, nullable=False)
class Card(db.Model): __tablename__ = 'card' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(40), unique=True, nullable=False) text = db.Column(db.Text, nullable=True) ### TODO imageURL should not be nullable at future imageURL = db.Column(db.Text, nullable=True) popUpText = db.Column(db.Text, nullable=True) popUpURL = db.Column(db.Text, nullable=True) typeId = db.Column(db.Integer, db.ForeignKey('cardtype.id'), nullable=False) type = db.relationship('CardType', back_populates='cards', uselist=False, lazy=False) isCovid = db.Column(db.Boolean, default=False) damage = db.Column(db.Integer, nullable=True) countInDeck = db.Column(db.Integer, nullable=False) offensiveAgainst = db.relationship('Defence', foreign_keys='Defence.offenceCardId', back_populates='offence', lazy=False) defensiveFrom = db.relationship('Defence', foreign_keys='Defence.defenceCardId', back_populates='defence', lazy=False) def __repr__(self): return '<Card %r>' % self.name
class DiscardEntry(db.Model): __tablename__ = 'discardentry' id = db.Column(db.Integer, primary_key=True) cardId = db.Column(db.Integer, db.ForeignKey('card.id'), nullable=False) gameId = db.Column(db.Integer, db.ForeignKey('game.id'), nullable=False) card = db.relationship('Card', lazy=False) game = db.relationship('Game', back_populates='discard', lazy=False)
class DeckEntry(db.Model): #__table_args__ = {'extend_existing': True} __tablename__ = 'deckentry' id = db.Column(db.Integer, primary_key=True) # TODO: Undo nullable cardId = db.Column(db.Integer, db.ForeignKey('card.id'), nullable=True) gameId = db.Column(db.Integer, db.ForeignKey('game.id'), nullable=False) card = db.relationship('Card', lazy=False) game = db.relationship('Game', back_populates='deck', lazy=False) order = db.Column(db.Integer, nullable=False)
class GameRound(db.Model): __tablename__ = 'gameround' # TODO: Add relationships id = db.Column(db.Integer, primary_key=True) game_id = db.Column(db.Integer, db.ForeignKey('game.id'), nullable=False) game = db.relationship('Game', back_populates='rounds') roundNo = db.Column(db.Integer, nullable=False) isComplete = db.Column(db.Boolean, default=False) isAccidentComplete = db.Column(db.Boolean, default=False) currentPlayerId = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=True) currentPlayer = db.relationship('Player') battles = db.relationship('RoundBattle', back_populates="round", cascade='all,delete')
class Location(db.Model): __tablename__ = "location_cache" id = db.Column(db.BigInteger, primary_key=True) latitude = db.Column(db.Float, nullable=False) longitude = db.Column(db.Float, nullable=False) location_rel = db.relationship('LocationToAddress', backref='location', lazy=True) play_time_rel = db.relationship('PlayTime', backref='location', lazy=True) event_play_time_rel = db.relationship('EventPlayTimes', backref='location', lazy=True) @staticmethod def get(id): return Location.query.filter_by(id=id).first() @staticmethod def get_by_location(lat, lng): return Location.query.filter_by(latitude=lat, longitude=lng).first()
class CardType(db.Model): __tablename__ = 'cardtype' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(40), unique=True, nullable=False) color = db.Column(db.String(128), nullable=False) enumType = db.Column(db.Enum(CardTypeEnum), nullable=False) cards = db.relationship('Card', back_populates='type', lazy=True) def __repr__(self): return '<Card Type %r>' % self.name
class Address(db.Model): __tablename__ = "address_cache" id = db.Column(db.BigInteger, primary_key=True) full_address = db.Column(db.String(300), nullable=False) short_address = db.Column(db.String(300), nullable=True) custom_address = db.Column(db.String(300), nullable=True) country = db.Column(db.String, nullable=True) city = db.Column(db.String, nullable=True) street = db.Column(db.String, nullable=True) point_of_interest = db.Column(db.String, nullable=True) building_number = db.Column(db.String, nullable=True) address_rel = db.relationship('LocationToAddress', backref='address', lazy=True) play_time_rel = db.relationship('PlayTime', backref='address', lazy=True) event_play_time_rel = db.relationship('EventPlayTimes', backref='address', lazy=True) @staticmethod def get(id): return Address.query.filter_by(id=id).first() @staticmethod def get_by_query(query: str) -> list: return Address.query.filter( Address.full_address.ilike(query) | Address.short_address.ilike(query) | Address.custom_address.ilike(query) | Address.point_of_interest.ilike(query) ).all() def get_short_address(self): components = [] if self.point_of_interest: components.append(self.point_of_interest) if self.street: components.append(self.street) if self.building_number: components.append(self.building_number) return ', '.join(components) def __repr__(self): return self.short_address
class Defence(db.Model): __tablename__ = 'defence' id = db.Column(db.Integer, primary_key=True) defenceCardId = db.Column(db.Integer, db.ForeignKey('card.id'), nullable=False) offenceCardId = db.Column(db.Integer, db.ForeignKey('card.id'), nullable=False) value = db.Column(db.Integer, nullable=False) defence = db.relationship("Card", back_populates='defensiveFrom', foreign_keys=[defenceCardId], uselist=False) offence = db.relationship("Card", back_populates='offensiveAgainst', foreign_keys=[offenceCardId], uselist=False) def __repr__(self): return '<Defence card value is %r>' % self.value
class Message(db.Model): __tablename__ = 'messages' id = db.Column(db.BigInteger, nullable=False, primary_key=True, autoincrement=True) chat_id = db.Column(db.BigInteger, db.ForeignKey('chats.id'), nullable=False) user_id = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False) time = db.Column(db.TIMESTAMP, default=timestamp()) is_read = db.Column(db.Boolean, default=False) content = db.Column(db.JSON, default=json.dumps({'photos': [], 'audios': [], 'videos': [], 'map_pins': []})) text = db.Column(db.VARCHAR(1000), default="") chat_last_msg_rel = db.relationship( 'Chat', backref='last_message', lazy=True, primaryjoin="Message.id==Chat.last_msg_id" ) @staticmethod def get_or_404(id: int): message = Message.query.get(id) if message is None: abort(404) return message @staticmethod def get_or_none(id: int): return Message.query.get(id) @staticmethod def has_id(id: int) -> bool: return Message.query.get(id) is None @staticmethod def get_history(chat_id: int, limit: int = 50): return Message.query.filter_by(chat_id=chat_id).order_by(Message.time).limit(limit).all() def __repr__(self): return f"Message: from {self.user.username}: {self.text} || {'+' if self.is_read else '-'}"
class Group(db.Model): id = db.Column(db.BigInteger, primary_key=True, autoincrement=True) admin_id = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False) sport = db.Column(db.String(50), nullable=False) name = db.Column(db.String(50), nullable=False) closed = db.Column(db.Boolean, default=False) members_rel = db.relationship('GroupMember', backref='group', lazy=True) chats_rel = db.relationship('Chat', backref='group', lazy=True) event_rel = db.relationship('Event', backref='group', lazy=True) __tablename__ = "groups" def __repr__(self): return f"Group {self.id}: {self.name}, {self.sport}, admin: {self.admin.username};" @staticmethod def get_by_sport(sport): return Group.query.filter_by(sport=sport).all() @staticmethod def get_or_404(id: int): group = Group.query.get(id) if group is None: abort(404) return group @staticmethod def get_or_none(id: int): return Group.query.get(id) def get_members(self): from libs.models.GroupMember import GroupMember members = GroupMember.query.filter_by(group_id=self.id).all() return [i.user for i in members] def add_member(self, user): from libs.models.GroupMember import GroupMember if user.id not in self.get_members(): new_row = GroupMember(user_id=user.id, group_id=self.id, time=timestamp()) db.session.add(new_row) db.session.commit() def get_events(self): from libs.models.Event import Event return Event.query.filter_by(group_id=self.id).all() def delete(self): from libs.models.GroupMember import GroupMember if self is None: return for e in self.get_events(): db.session.delete(e) db.session.commit() for i in GroupMember.query.filter_by(group_id=self.id).all(): db.session.delete(i) db.session.commit() db.session.delete(self) db.session.commit()
class User(db.Model, UserMixin): # from libs.Group import Group # from libs.GroupMember import GroupMember from libs.models.Friend import Friend from libs.models.Chat import Chat from libs.models.EventMember import EventMember from libs.models.PlayTime import PlayTime from libs.models.UserVideos import UserVideos # from libs.ChatMember import ChatMember # from libs.ChatNotification import ChatNotification # from libs.Message import Message # from libs.Event import Event # from libs.EventMember import EventMember id = db.Column(db.BigInteger, primary_key=True, autoincrement=True) name = db.Column(db.String(20), nullable=True) last_name = db.Column(db.String(40), nullable=True) age = db.Column(db.Integer) gender = db.Column(db.String, nullable=True) sport = db.Column(db.ARRAY(db.String)) username = db.Column(db.String(20), unique=True, nullable=False) password = db.Column(db.String(), nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) register_time = db.Column(db.TIMESTAMP, default=timestamp()) last_login = db.Column(db.TIMESTAMP, nullable=False, default=timestamp()) image_file = db.Column(db.String, nullable=False, default='default.jpg') last_login_ip = db.Column(db.String) language = db.Column(db.String, nullable=False, default="en") city = db.Column(db.String(50), nullable=True) groups_rel = db.relationship('Group', backref='admin', lazy=True) members_rel = db.relationship('GroupMember', backref='user', lazy=True) friends_rel_1 = db.relationship('Friend', backref='first', lazy=True, primaryjoin="User.id==Friend.first_id") friends_rel_2 = db.relationship('Friend', backref='second', lazy=True, primaryjoin="User.id==Friend.second_id") chat_admin_rel = db.relationship('Chat', backref='admin', lazy=True) chat_member_rel = db.relationship('ChatMember', backref='user', lazy=True) message_rel = db.relationship('Message', backref='user', lazy=True) notification_rel = db.relationship('ChatNotification', backref='user', lazy=True) event_member_rel = db.relationship('EventMember', backref='user', lazy=True) event_rel = db.relationship('Event', backref='creator', lazy=True) play_time_rel = db.relationship('PlayTime', backref='user', lazy=True) user_sport_videos_rel = db.relationship('UserVideos', backref='user', lazy=True) __tablename__ = "users" def __repr__(self): return f"User {self.id}: {self.username}, {self.name}, {self.last_name}, {self.gender})" @staticmethod def get_or_404(id: int): user = User.query.get(int(id)) if user is None: abort(404) return user @staticmethod def get_or_none(id: int): return User.query.get(int(id)) def friend_add(self, friend_id: int): from libs.models.Friend import Friend Friend.add(self.id, int(friend_id)) def friend_remove(self, friend_id: int): from libs.models.Friend import Friend Friend.remove(self.id, int(friend_id)) def friends_get(self) -> list: from libs.models.Friend import Friend first = Friend.query.filter_by(first_id=self.id).all() first_set = set(map(lambda y: User.get_or_none(y.second_id), first)) second = Friend.query.filter_by(second_id=self.id).all() second_set = set(map(lambda y: User.get_or_none(y.first_id), second)) return list(first_set.union(second_set)) def get_groups(self): return [ i.group for i in GroupMember.query.filter_by(user_id=self.id).all() ] def get_chats(self): from libs.models.ChatMember import ChatMember return list( filter(lambda x: x.deleted is None, [ i.chat for i in ChatMember.query.filter(ChatMember.user_id == self.id and ChatMember.deleted is None).all() ])) def get_notifications(self): from libs.models.ChatNotification import ChatNotification return [i.chat for i in ChatNotification.get_notifications(self.id)] def is_notified(self): return len(self.get_notifications()) != 0 def get_events(self): from libs.models.EventMember import EventMember return [ i.event for i in EventMember.query.filter_by(user_id=self.id).all() ] def get_invitations(self): from libs.models.Invitation import Invitation return Invitation.query.filter_by(recipient_id=self.id).all() def has_invitations(self): return len(list(filter(lambda i: not i.read, self.get_invitations()))) > 0
class Chat(db.Model): from libs.models.ChatMember import ChatMember from libs.models.ChatNotification import ChatNotification from libs.models.Message import Message __tablename__ = 'chats' id = db.Column(db.BigInteger, primary_key=True, autoincrement=True) name = db.Column(db.VARCHAR(100), nullable=True) admin_id = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False) time = db.Column(db.TIMESTAMP, default=timestamp()) last_msg_id = db.Column(db.BigInteger, db.ForeignKey('messages.id'), nullable=True) group_id = db.Column(db.BigInteger, db.ForeignKey('groups.id'), nullable=True) # is_group deleted = db.Column(db.TIMESTAMP, nullable=True, default=None) chat_member_rel = db.relationship('ChatMember', backref='chat', lazy=True) message_rel = db.relationship('Message', backref='chat', lazy=True, primaryjoin="Chat.id==Message.chat_id") notification_rel = db.relationship('ChatNotification', backref='chat', lazy=True) def __repr__(self): return f"{'GroupChat' if self.group_id else 'Chat'}: {self.name}, {self.admin}" + \ " deleted" if self.deleted else "" @staticmethod def get_or_404(id: int): chat = Chat.query.get(id) if chat is None: abort(404) return chat @staticmethod def get_or_none(id: int): return Chat.query.get(id) def get_history(self): from libs.models.Message import Message return Message.get_history(self.id) def get_members(self): from libs.models.ChatMember import ChatMember return [ i.user for i in ChatMember.query.filter_by(chat_id=self.id, deleted=None).all() ] def add_member(self, id: int, is_group=True): from libs.models.ChatMember import ChatMember if id not in [i.id for i in self.get_members()]: new = ChatMember(user_id=id, chat_id=self.id, is_group=is_group, time=timestamp()) db.session.add(new) db.session.commit() def update_last_msg(self, message): self.last_msg_id = message.id db.session.commit() def get_new_messages(self, user_id=None): from libs.models.Message import Message if user_id is None: return Message.query.filter_by(chat_id=self.id, is_read=False).all() else: return list( filter( lambda x: x.user_id != user_id, Message.query.filter_by(chat_id=self.id, is_read=False).all()))
class Event(db.Model): from libs.models.EventPlayTimes import EventPlayTimes __tablename__ = "events" id = db.Column(db.BigInteger, primary_key=True, autoincrement=True) name = db.Column(db.VARCHAR(100), nullable=False) description = db.Column(db.VARCHAR(300), nullable=True) sport = db.Column(db.VARCHAR(50), nullable=False) group_id = db.Column(db.BigInteger, db.ForeignKey('groups.id'), nullable=True) creation_time = db.Column(db.TIMESTAMP, default=timestamp()) creator_id = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False) time = db.Column(db.TIMESTAMP, nullable=True) closed = db.Column(db.Boolean, default=False) recurring = db.Column(db.Boolean, default=False) event_members_rel = db.relationship('EventMember', backref='event', lazy=True) event_play_time_rel = db.relationship('EventPlayTimes', backref='event', lazy=True) def __repr__(self): return f"Event {self.id}: {self.name}, {self.sport}" @staticmethod def get_or_404(id: int): event = Event.query.get(id) if event is None: abort(404) return event @staticmethod def get_or_none(id: int): return Event.query.get(id) def add_member(self, user): from libs.models.EventMember import EventMember res = EventMember.query.filter_by(event_id=self.id, user_id=user.id).first() if res is not None: return new_member = EventMember(event_id=self.id, user_id=user.id, time=timestamp()) db.session.add(new_member) db.session.commit() def get_members(self): from libs.models.EventMember import EventMember return [ i.user for i in EventMember.query.filter_by(event_id=self.id).all() ] def remove_member(self, user): from libs.models.EventMember import EventMember res = EventMember.query.filter_by(event_id=self.id, user_id=user.id).first() if res is not None: db.session.delete(res) db.session.commit() def delete(self): from libs.models.EventMember import EventMember if self is None: return for i in EventMember.query.filter_by(event_id=self.id).all(): db.session.delete(i) db.session.commit() db.session.delete(self) db.session.commit()