adding tests and helper UX to schema
This commit is contained in:
@@ -96,6 +96,7 @@ class CharacterClassAttributeMap(BaseObject, IterableMixin):
|
||||
primaryjoin="CharacterClassAttributeMap.character_id == CharacterClassMap.character_id",
|
||||
secondaryjoin="CharacterClass.id == CharacterClassMap.character_class_id",
|
||||
viewonly=True,
|
||||
uselist=False,
|
||||
)
|
||||
|
||||
|
||||
@@ -117,14 +118,18 @@ class Character(*Bases, SavingThrowsMixin, SkillsMixin):
|
||||
proficiencies = Column(String)
|
||||
|
||||
class_map = relationship("CharacterClassMap", cascade="all,delete,delete-orphan")
|
||||
classes = association_proxy("class_map", "id", creator=class_map_creator)
|
||||
_classes = association_proxy("class_map", "id", creator=class_map_creator)
|
||||
|
||||
character_class_attribute_map = relationship("CharacterClassAttributeMap", cascade="all,delete,delete-orphan")
|
||||
class_attributes = association_proxy("character_class_attribute_map", "id", creator=attr_map_creator)
|
||||
_class_attributes = association_proxy("character_class_attribute_map", "id", creator=attr_map_creator)
|
||||
|
||||
ancestry_id = Column(Integer, ForeignKey("ancestry.id"), nullable=False, default="1")
|
||||
ancestry = relationship("Ancestry", uselist=False)
|
||||
|
||||
@property
|
||||
def classes(self):
|
||||
return dict([(mapping.character_class.name, mapping.character_class) for mapping in self.class_map])
|
||||
|
||||
@property
|
||||
def traits(self):
|
||||
return [mapping.trait for mapping in self.ancestry.traits]
|
||||
@@ -137,6 +142,10 @@ class Character(*Bases, SavingThrowsMixin, SkillsMixin):
|
||||
def levels(self):
|
||||
return dict([(mapping.character_class.name, mapping.level) for mapping in self.class_map])
|
||||
|
||||
@property
|
||||
def class_attributes(self):
|
||||
return dict([(mapping.class_attribute.name, mapping.option) for mapping in self.character_class_attribute_map])
|
||||
|
||||
def add_class(self, newclass, level=1):
|
||||
if level == 0:
|
||||
return self.remove_class(newclass)
|
||||
@@ -145,7 +154,24 @@ class Character(*Bases, SavingThrowsMixin, SkillsMixin):
|
||||
level_in_class = level_in_class[0]
|
||||
level_in_class.level = level
|
||||
return
|
||||
self.classes.append(CharacterClassMap(character_id=self.id, character_class_id=newclass.id, level=level))
|
||||
self._classes.append(CharacterClassMap(character_id=self.id, character_class_id=newclass.id, level=level))
|
||||
|
||||
def remove_class(self, target):
|
||||
self.class_map = [m for m in self.class_map if m.id != target.id]
|
||||
for mapping in self.character_class_attribute_map:
|
||||
if mapping.character_class.id == target.id:
|
||||
self.remove_class_attribute(mapping.class_attribute)
|
||||
|
||||
def remove_class_attribute(self, attribute):
|
||||
self.character_class_attribute_map = [m for m in self.character_class_attribute_map if m.id != attribute.id]
|
||||
|
||||
def add_class_attribute(self, attribute, option):
|
||||
for thisclass in self.classes.values():
|
||||
if attribute.name in thisclass.attributes_by_level.get(self.levels[thisclass.name], {}):
|
||||
self._class_attributes.append(
|
||||
CharacterClassAttributeMap(
|
||||
character_id=self.id, class_attribute_id=attribute.id, option_id=option.id
|
||||
)
|
||||
)
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -16,12 +16,14 @@ class ClassAttributeMap(BaseObject, IterableMixin):
|
||||
class_attribute_id = Column(Integer, ForeignKey("class_attribute.id"), primary_key=True)
|
||||
character_class_id = Column(Integer, ForeignKey("character_class.id"), primary_key=True)
|
||||
level = Column(Integer, nullable=False, info={"min": 1, "max": 20}, default=1)
|
||||
attribute = relationship("ClassAttribute", uselist=False, viewonly=True, lazy="immediate")
|
||||
|
||||
|
||||
class ClassAttribute(BaseObject, IterableMixin):
|
||||
__tablename__ = "class_attribute"
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
name = Column(String, nullable=False)
|
||||
options = relationship("ClassAttributeOption", cascade="all,delete,delete-orphan", lazy="immediate")
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.id}: {self.name}"
|
||||
@@ -32,7 +34,6 @@ class ClassAttributeOption(BaseObject, IterableMixin):
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
name = Column(String, nullable=False)
|
||||
attribute_id = Column(Integer, ForeignKey("class_attribute.id"), nullable=False)
|
||||
# attribute = relationship("ClassAttribute", uselist=False)
|
||||
|
||||
|
||||
class CharacterClass(*Bases, SavingThrowsMixin, SkillsMixin):
|
||||
@@ -42,4 +43,11 @@ class CharacterClass(*Bases, SavingThrowsMixin, SkillsMixin):
|
||||
hit_dice = Column(String, default="1d6")
|
||||
hit_dice_stat = Column(Enum(StatsEnum))
|
||||
proficiencies = Column(String)
|
||||
attributes = relationship("ClassAttributeMap")
|
||||
attributes = relationship("ClassAttributeMap", cascade="all,delete,delete-orphan", lazy="immediate")
|
||||
|
||||
@property
|
||||
def attributes_by_level(self):
|
||||
by_level = {}
|
||||
for mapping in self.attributes:
|
||||
by_level[mapping.level] = {mapping.attribute.name: mapping.attribute}
|
||||
return by_level
|
||||
|
||||
Reference in New Issue
Block a user