from sqlalchemy import Column, Integer, String, ForeignKey, Boolean, DateTime, JSON, Enum as SQLEnum, func from sqlalchemy.orm import relationship 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=False) location = relationship("Dbref", remote_side=[CRUDMixin.id], foreign_keys=[location_id], back_populates="contents") contents = relationship("Dbref", backref="location", foreign_keys=location_id) exits = relationship("Exit", backref="source", foreign_keys=location_id) owner_id = Column(Integer, ForeignKey("dbref.id"), nullable=False) owner = relationship("Player", remote_side=[CRUDMixin.id], foreign_keys=[owner_id]) creator_id = Column(Integer, ForeignKey("dbref.id"), nullable=False) creator = relationship("Player", remote_side=[CRUDMixin.id], foreign_keys=[creator_id]) modifier_id = Column(Integer, ForeignKey("dbref.id"), nullable=False) modifier = relationship("Player", remote_side=[CRUDMixin.id], foreign_keys=[modifier_id]) last_user_id = Column(Integer, ForeignKey("dbref.id"), nullable=False) last_user = relationship("Player", remote_side=[CRUDMixin.id], foreign_keys=[last_user_id]) __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)