예제 #1
0
class SavingThrowProficiency(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    ability_score_id = db.Column(db.Integer,
                                 db.ForeignKey('ability_score.id'),
                                 unique=True)
    ability_score = db.relationship('AbilityScore')
    proficiency_multiplier = db.Column(db.Integer, default=0, nullable=False)
예제 #2
0
class CoinType(ResourceMixin, db.Model):
    id = db.Column(db.Integer, db.ForeignKey('item.id'), primary_key=True)
    item = db.relationship('Item')
    abbreviation = db.Column(db.String(8),
                             nullable=False,
                             unique=True,
                             index=True)
예제 #3
0
class Ability(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32), nullable=False, unique=True, index=True)
    abbreviation = db.Column(db.String(8),
                             nullable=False,
                             unique=True,
                             index=True)
예제 #4
0
class Weapon(ResourceMixin, db.Model):
    id = db.Column(db.Integer, db.ForeignKey('item.id'), primary_key=True)
    item = db.relationship('Item')
    category = db.Column(db.Enum(WeaponCategory, native_enum=False),
                         nullable=False)
    classification = db.Column(db.Enum(WeaponClass, native_enum=False))
    properties = db.relationship('WeaponProperty',
                                 secondary=weapon_weapon_property_map)
예제 #5
0
class ResourceMixin:
    """
    Adds date created and date updated columns to the sources
    """
    db_created_on = db.Column(
        AwareDateTime(),
        default=tz_aware_now,
    )
    db_updated_on = db.Column(
        AwareDateTime(),
        default=tz_aware_now,
    )

    def __setattr__(self, key, value):
        if hasattr(self, key):
            if getattr(self, key) != value:
                super().__setattr__(key, value)
                super().__setattr__('db_updated_on', tz_aware_now())
        else:
            super().__setattr__(key, value)

    def save(self):
        """
        Save a model instance

        :return: model instance
        """
        db.session.add(self)
        db.session.flush()
        db.session.commit()

        return self

    def delete(self):
        """
        Delete a model instance

        :return: the result of the commit
        """
        db.session.delete(self)
        return db.session.commit()

    def __str__(self):
        """
        create a human readable version of the class instance

        :return: string
        """
        obj_id = hex(id(self))
        if hasattr(self, '__table__'):
            columns = self.__table__.c.keys()
        else:
            columns = []
        values = ', '.join('{!s}={!r}'.format(n, getattr(self, n))
                           for n in columns)
        return '<{!s} {!s}({!s})>'.format(obj_id, self.__class__.__name__,
                                          values)
예제 #6
0
class Armor(ResourceMixin, db.Model):
    id = db.Column(db.Integer, db.ForeignKey('item.id'), primary_key=True)
    item = db.relationship('Item')
    category = db.Column(db.Enum(ArmorCategories, native_enum=False),
                         nullable=False)
    base_armor_class = db.Column(db.Integer, nullable=False, index=True)
    strength_requirement = db.Column(db.Integer,
                                     nullable=False,
                                     index=True,
                                     default=0)
    stealth_effect = db.Column(db.String, index=True)
예제 #7
0
class AbilityScore(ResourceMixin, db.Model):
    __table_args__ = (db.UniqueConstraint('ability_id', 'stat_block_id'), )
    id = db.Column(db.Integer, primary_key=True)
    ability_id = db.Column(db.Integer,
                           db.ForeignKey('ability.id'),
                           nullable=False)
    ability = db.relationship('Ability')
    stat_block_id = db.Column(db.Integer,
                              db.ForeignKey('stat_block.id'),
                              nullable=False)
    stat_block = db.relationship('StatBlock', back_populates='ability_scores')
    base_value = db.Column(db.Integer, default=10)
예제 #8
0
class SpeedScore(ResourceMixin, db.Model):
    __table_args__ = (db.UniqueConstraint('speed_type_id', 'stat_block_id'), )
    id = db.Column(db.Integer, primary_key=True)
    speed_type_id = db.Column(db.Integer,
                              db.ForeignKey('speed_type.id'),
                              nullable=False)
    speed_type = db.relationship('SpeedType')
    stat_block_id = db.Column(db.Integer,
                              db.ForeignKey('stat_block.id'),
                              nullable=False)
    stat_block = db.relationship('StatBlock', back_populates='speed_scores')
    base_value = db.Column(db.Integer, default=0, nullable=False, index=True)
예제 #9
0
class SpellComponent(db.Model):
    __table_args__ = (db.UniqueConstraint('type', 'spell_id'), )

    id = db.Column(db.Integer, primary_key=True)
    type_ = db.Column('type',
                      db.Enum('V', 'S', 'M', native_enum=False),
                      nullable=False,
                      index=True)
    spell_id = db.Column(db.Integer,
                         db.ForeignKey('spell.id'),
                         nullable=False,
                         index=True)
    spell = db.relationship('Spell', back_populates='components')
예제 #10
0
class Attack(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), nullable=False, unique=True, index=True)
    display_name = db.Column(db.String(64), nullable=False)
    required_number_of_hands = db.Column(db.Integer, nullable=False)
    ability_id = db.Column(db.Integer, db.ForeignKey('ability.id'))
    ability = db.relationship('Ability')
    melee_range = db.Column(db.Integer)
    short_range = db.Column(db.Integer)
    long_range = db.Column(db.Integer)
    uses_proficiency = db.Column(db.Boolean(), default=True)
예제 #11
0
class Feature(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), nullable=False, unique=True, index=True)
    description = db.Column(
        db.String(),
        nullable=False,
    )
    category = db.Column(db.Enum(FeatureCategory, native_enum=False),
                         nullable=False,
                         index=True)
    maximum_uses = db.Column(db.Integer)
    current_uses = db.Column(db.Integer)
    replenishes_on = db.Column(db.Enum(Rest, native_enum=False))
예제 #12
0
class StatBlockClass(ResourceMixin, db.Model):
    __table_args__ = (db.UniqueConstraint('stat_block_id',
                                          'creature_class_id'), )

    id = db.Column(db.Integer, primary_key=True)
    stat_block_id = db.Column(db.Integer, db.ForeignKey('stat_block.id'))
    creature_class_id = db.Column(db.Integer,
                                  db.ForeignKey('creature_class.id'))
    level = db.Column(db.Integer, nullable=False, index=True)
    hit_die = db.Column(db.Enum(DieType))
    creature_class = db.relationship('CreatureClass')
    stat_block = db.relationship('StatBlock', back_populates='classes')
    current_hit_dice = db.Column(db.Integer, nullable=False, default=0)
예제 #13
0
class Item(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), nullable=False, unique=True, index=True)
    description = db.Column(db.String)
    weight = db.Column(db.Float(), default=0)
    value = db.Column(db.Integer, index=True)
예제 #14
0
class DamageType(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32), nullable=False, unique=True, index=True)
예제 #15
0
class Condition(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32), nullable=False, unique=True, index=True)
    description = db.Column(db.String)
예제 #16
0
class StatBlock(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(256), nullable=False, index=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
    user = db.relationship(account.User)
    classes = db.relationship('StatBlockClass')
    background_id = db.Column(db.Integer,
                              db.ForeignKey('background.id'),
                              nullable=True,
                              index=True)
    background = db.relationship('Background')
    race_id = db.Column(db.Integer,
                        db.ForeignKey('race.id'),
                        nullable=False,
                        index=True)
    race = db.relationship('Race')
    alignment = db.Column(db.Enum(Alignment, native_enum=False), index=True)
    experience_points = db.Column(db.Integer, index=True, default=0)

    proficiency_bonus = db.Column(db.Integer)

    ability_scores = db.relationship('AbilityScore',
                                     back_populates='stat_block')

    base_hit_point_max = db.Column(db.Integer)
    current_hit_points = db.Column(db.Integer)
    temporary_hit_points = db.Column(db.Integer)

    speed_scores = db.relationship('SpeedScore', back_populates='stat_block')

    personality_traits = db.Column(db.String)
    ideals = db.Column(db.String)
    bonds = db.Column(db.String)
    flaws = db.Column(db.String)
예제 #17
0
class CreatureClass(db.Model):

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32), unique=True, index=True, nullable=False)
예제 #18
0
class Skill(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32), nullable=False, unique=True)
    default_ability_id = db.Column(db.Integer,
                                   db.ForeignKey('ability.id'),
                                   nullable=False)
예제 #19
0
class WeaponProperty(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(16), nullable=False, unique=True, index=True)
    description = db.Column(db.String())
예제 #20
0
class Spell(ResourceMixin, db.Model):

    id = db.Column(db.Integer, primary_key=True)
    unique_name = db.Column(db.String(256),
                            nullable=False,
                            unique=True,
                            index=True)
    name = db.Column(db.String(256), nullable=False, index=True)
    ritual = db.Column(db.Boolean, nullable=False, index=True)
    level = db.Column(db.Integer, nullable=False, index=True)
    school_id = db.Column(db.Integer,
                          db.ForeignKey('school_of_magic.id'),
                          nullable=False,
                          index=True)
    school = db.relationship('SchoolOfMagic', back_populates='spells')

    casting_time = db.Column(db.Integer, nullable=False, index=True)
    range = db.Column(db.String(64), nullable=False, index=True)
    components = db.relationship('SpellComponent', back_populates='spell')
    material_components = db.Column(db.String(1024), nullable=True)
    description = db.Column(db.String(), nullable=True)
    higher_levels = db.Column(db.String())
    classes = db.relationship('CreatureClass',
                              secondary=creature_class_spell_map,
                              backref=db.backref('spells', lazy='dynamic'))
    damage_types = db.relationship('DamageType',
                                   secondary=damage_type_spell_map,
                                   backref=db.backref('spells',
                                                      lazy='dynamic'))
예제 #21
0
class CreatureType(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, nullable=False, index=True)
    description = db.Column(db.String)
예제 #22
0
class Race(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, nullable=False, index=True)
    description = db.Column(db.String)
    creature_type_id = db.Column(db.Integer, db.ForeignKey('creature_type.id'))
    creature_type = db.relationship('CreatureType')
예제 #23
0
import enum

from utils.sql import ResourceMixin
from world_manager.extensions import db
from world_manager.model import account


class SchoolOfMagic(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), nullable=False, unique=True, index=True)
    spells = db.relationship('Spell', back_populates='school')


creature_class_spell_map = db.Table(
    'creature_class_spell_map',
    db.Column('spell_id', db.Integer, db.ForeignKey('spell.id')),
    db.Column('creature_class_id', db.Integer,
              db.ForeignKey('creature_class.id')),
    db.PrimaryKeyConstraint('spell_id', 'creature_class_id'))

damage_type_spell_map = db.Table(
    'damage_type_spell_map',
    db.Column('damage_type_id', db.Integer, db.ForeignKey('damage_type.id')),
    db.Column('spell_id', db.Integer, db.ForeignKey('spell.id')),
    db.PrimaryKeyConstraint('damage_type_id', 'spell_id'))


class DieType(enum.Enum):
    d4 = 4
    d6 = 6
    d8 = 8
예제 #24
0
class SchoolOfMagic(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), nullable=False, unique=True, index=True)
    spells = db.relationship('Spell', back_populates='school')
예제 #25
0
class SkillProficiency(ResourceMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    skill_id = db.Column(db.Integer, db.ForeignKey('skill.id'))
    skill = db.relationship('Skill')
    stat_block_id = db.Column(db.Integer, db.ForeignKey('stat_block.id'))
    proficiency_multiplier = db.Column(db.Integer, default=0, nullable=False)
예제 #26
0
class Shield(ResourceMixin, db.Model):
    id = db.Column(db.Integer, db.ForeignKey('item.id'), primary_key=True)
    item = db.relationship('Item')
예제 #27
0
class User(ResourceMixin, db.Model):

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

    # Authentication
    role = db.Column(db.Enum(UserRole,
                             native_enum=False, name='user_role_type'),
                     index=True,
                     nullable=False,
                     server_default='member')
    is_active = db.Column(db.Boolean(),
                          nullable=False,
                          server_default='1')

    username = db.Column(db.String(24),
                         nullable=False,
                         unique=True,
                         index=True)
    email_address = db.Column(db.String(255),
                              nullable=False,
                              unique=True,
                              index=True)
    password = db.Column(db.String(128), nullable=False, server_default='')

    # Activity Tracking
    login_count = db.Column(db.Integer, nullable=False, default=0)
    current_login_time = db.Column(AwareDateTime())
    current_login_ip_address = db.Column(db.String(45))
    last_login_time = db.Column(AwareDateTime())
    last_login_ip_address = db.Column(db.String(45))

    def __init__(self, **kwargs):
        super.__init__(**kwargs)
        self.password = User.encrypt_password(kwargs.get('password', ''))

    @staticmethod
    def find_by_identity(identity: str) -> 'User':
        """
        Find a user by their e-mail or username.

        :param identity: Email or username
        :type identity: str
        :return: User instance
        """
        return User.query.filter(
            (User.email_address == identity)
            | (User.username == identity)).first()

    @staticmethod
    def encrypt_password(plaintext_password: str) -> Optional[str]:
        """
        Hash a plaintext string using PBKDF2. This is good enough according
        to the NIST (National Institute of Standards and Technology).

        In other words while bcrypt might be superior in practice, if you use
        PBKDF2 properly (which we are), then your passwords are safe.

        :param plaintext_password: Password in plain text
        :type plaintext_password: str
        :return: str
        """
        if plaintext_password:
            return generate_password_hash(plaintext_password)
        return None

    @staticmethod
    def deserialize_token(token: str) -> Optional['User']:
        """
        Obtain a user from de-serializing a signed token.

        :param token: Signed token.
        :type token: str
        :return: User instance or None
        """
        private_key = TimedJSONWebSignatureSerializer(
            current_app.config['SECRET_KEY'])
        try:
            decoded_payload = private_key.loads(token)

            return User.find_by_identity(decoded_payload.get('user_email'))
        except Exception:
            return None

    def authenticate(self, password: str='') -> bool:
        """
        Ensure a user is authenticated, and optionally check their password.

        :param password: Optionally verify this as their password
        """
        if password:
            return check_password_hash(self.password, password)

        return True

    def register_login(self, ip_address):
        self.sign_in_count += 1

        self.last_login_ip_address = self.current_login_ip_address
        self.last_login_time = self.current_login_time

        self.current_login_ip_address = ip_address
        self.current_login_time = tz_aware_now()

        return self.save()