tabletop-frog/src/ttfrog/db/schema/classes.py

77 lines
3.0 KiB
Python
Raw Normal View History

2024-04-14 11:37:34 -07:00
from collections import defaultdict
from sqlalchemy import ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
2024-02-18 19:30:41 -08:00
from ttfrog.db.base import BaseObject, SavingThrowsMixin, SkillsMixin
2024-02-18 19:30:41 -08:00
__all__ = [
2024-03-26 00:53:21 -07:00
"ClassAttributeMap",
"ClassAttribute",
"ClassAttributeOption",
"CharacterClass",
2024-02-18 19:30:41 -08:00
]
class ClassAttributeMap(BaseObject):
2024-02-18 19:30:41 -08:00
__tablename__ = "class_attribute_map"
class_attribute_id: Mapped[int] = mapped_column(ForeignKey("class_attribute.id"), primary_key=True)
character_class_id: Mapped[int] = mapped_column(ForeignKey("character_class.id"), primary_key=True)
level: Mapped[int] = mapped_column(nullable=False, info={"min": 1, "max": 20}, default=1)
2024-03-26 21:58:04 -07:00
attribute = relationship("ClassAttribute", uselist=False, viewonly=True, lazy="immediate")
2024-02-18 19:30:41 -08:00
class ClassAttribute(BaseObject):
2024-02-18 19:30:41 -08:00
__tablename__ = "class_attribute"
id: Mapped[int] = mapped_column(init=False, primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(nullable=False)
2024-03-26 21:58:04 -07:00
options = relationship("ClassAttributeOption", cascade="all,delete,delete-orphan", lazy="immediate")
2024-05-04 13:15:54 -07:00
def add_option(self, **kwargs):
option = ClassAttributeOption(attribute_id=self.id, **kwargs)
if not self.options or option not in self.options:
option.attribute_id = self.id
if not self.options:
self.options = [option]
else:
self.options.append(option)
return True
return False
def __repr__(self):
return f"{self.id}: {self.name}"
class ClassAttributeOption(BaseObject):
__tablename__ = "class_attribute_option"
id: Mapped[int] = mapped_column(init=False, primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(nullable=False)
2024-05-04 13:15:54 -07:00
attribute_id: Mapped[int] = mapped_column(ForeignKey("class_attribute.id"), nullable=True)
2024-02-18 19:30:41 -08:00
class CharacterClass(BaseObject, SavingThrowsMixin, SkillsMixin):
2024-02-18 19:30:41 -08:00
__tablename__ = "character_class"
id: Mapped[int] = mapped_column(init=False, primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(index=True, unique=True)
hit_dice: Mapped[str] = mapped_column(default="1d6")
hit_dice_stat: Mapped[str] = mapped_column(default="")
proficiencies: Mapped[str] = mapped_column(default="")
2024-03-26 21:58:04 -07:00
attributes = relationship("ClassAttributeMap", cascade="all,delete,delete-orphan", lazy="immediate")
2024-05-04 13:15:54 -07:00
def add_attribute(self, attribute, level=1):
if not self.attributes or attribute not in self.attributes:
mapping = ClassAttributeMap(character_class_id=self.id, class_attribute_id=attribute.id, level=level)
if not self.attributes:
self.attributes = [mapping]
else:
self.attributes.append(mapping)
return True
return False
2024-03-26 21:58:04 -07:00
@property
def attributes_by_level(self):
2024-04-14 11:37:34 -07:00
by_level = defaultdict(list)
2024-03-26 21:58:04 -07:00
for mapping in self.attributes:
by_level[mapping.level] = {mapping.attribute.name: mapping.attribute}
return by_level