from sqlalchemy import Column, Integer, String, ForeignKey, Boolean, DateTime, JSON, Enum as SQLEnum, func from sqlalchemy.orm import relationship, foreign, remote from crudkit.core.base import CRUDMixin, Base from enum import Enum class ObjectType(str, Enum): ROOM = "room" THING = "thing" EXIT = "exit" PLAYER = "player" PROGRAM = "program" TYPE_SUFFIXES = { ObjectType.ROOM: "R", ObjectType.EXIT: "E", ObjectType.PLAYER: "P", ObjectType.PROGRAM: "F", ObjectType.THING: "", } class Dbref(Base, CRUDMixin): __tablename__ = "dbref" type = Column(SQLEnum(ObjectType, name="object_type_enum"), nullable=False) name = Column(String, nullable=False) props = Column(JSON, nullable=False, default={}) is_deleted = Column(Boolean, nullable=False, default=False) last_used = Column(DateTime, nullable=False, default=func.now()) use_count = Column(Integer, nullable=False, default=0) location_id = Column(Integer, ForeignKey("dbref.id"), nullable=True, default=0) location = relationship("Dbref", foreign_keys=[location_id], back_populates="contents", primaryjoin=lambda: foreign(Dbref.location_id) == remote(Dbref.id), remote_side=lambda: Dbref.id) contents = relationship("Dbref", foreign_keys=[location_id], back_populates="location") owner_id = Column(Integer, ForeignKey("dbref.id"), nullable=True) owner = relationship("Player", remote_side=[CRUDMixin.id], foreign_keys=[owner_id], primaryjoin=lambda: Dbref.owner_id == remote(Dbref.id), post_update=True) creator_id = Column(Integer, ForeignKey("dbref.id"), nullable=True) creator = relationship("Player", remote_side=[CRUDMixin.id], foreign_keys=[creator_id], primaryjoin=lambda: Dbref.creator_id == remote(Dbref.id), post_update=True) modifier_id = Column(Integer, ForeignKey("dbref.id"), nullable=True) modifier = relationship("Player", remote_side=[CRUDMixin.id], foreign_keys=[modifier_id], primaryjoin=lambda: Dbref.modifier_id == remote(Dbref.id), post_update=True) last_user_id = Column(Integer, ForeignKey("dbref.id"), nullable=True) last_user = relationship("Player", remote_side=[CRUDMixin.id], foreign_keys=[last_user_id], primaryjoin=lambda: Dbref.last_user_id == remote(Dbref.id), post_update=True) __mapper_args__ = { "polymorphic_on": type, "polymorphic_identity": "dbref" } def __str__(self): suffix = TYPE_SUFFIXES.get(self.type, "") return f"#{self.id}{suffix}" def __repr__(self): suffix = TYPE_SUFFIXES.get(self.type, "") return f"" def is_type(self, *types: ObjectType) -> bool: return self.type in types def display_type(self) -> str: return self.type.value.upper() @property def is_room(self): return self.is_type(ObjectType.ROOM) @property def is_thing(self): return self.is_type(ObjectType.THING) @property def is_exit(self): return self.is_type(ObjectType.EXIT) @property def is_player(self): return self.is_type(ObjectType.PLAYER) @property def is_program(self): return self.is_type(ObjectType.PROGRAM)