@@ -0,0 +1,151 @@
|
||||
import uuid
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
|
||||
|
||||
class MathIdentity(models.Model):
|
||||
code = models.CharField(max_length=8, unique=True)
|
||||
name = models.CharField(max_length=80)
|
||||
clan = models.CharField(max_length=40)
|
||||
mathematician = models.CharField(max_length=80)
|
||||
description = models.TextField(blank=True)
|
||||
initial_abilities = models.JSONField(default=dict, blank=True)
|
||||
portrait = models.CharField(max_length=200, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.code} {self.name}"
|
||||
|
||||
|
||||
class MathBTIAssessment(models.Model):
|
||||
version = models.CharField(max_length=30, unique=True)
|
||||
title = models.CharField(max_length=120)
|
||||
definition = models.JSONField()
|
||||
is_published = models.BooleanField(default=False)
|
||||
published_at = models.DateTimeField(null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class MathBTIResult(models.Model):
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="mathbti_results")
|
||||
assessment = models.ForeignKey(MathBTIAssessment, on_delete=models.PROTECT)
|
||||
identity = models.ForeignKey(MathIdentity, on_delete=models.PROTECT)
|
||||
answers = models.JSONField(default=list)
|
||||
axis_scores = models.JSONField(default=dict)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ["-created_at"]
|
||||
|
||||
|
||||
class Character(models.Model):
|
||||
slug = models.SlugField(unique=True)
|
||||
name = models.CharField(max_length=80)
|
||||
profile = models.TextField(blank=True)
|
||||
metadata = models.JSONField(default=dict, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Story(models.Model):
|
||||
class Kind(models.TextChoices):
|
||||
FLAGSHIP = "flagship", "旗舰人生"
|
||||
SKILL = "skill", "人物 Skill"
|
||||
SPECIAL = "special", "特别篇"
|
||||
|
||||
slug = models.SlugField(unique=True)
|
||||
title = models.CharField(max_length=120)
|
||||
summary = models.TextField(blank=True)
|
||||
kind = models.CharField(max_length=16, choices=Kind.choices, default=Kind.FLAGSHIP)
|
||||
estimated_minutes = models.PositiveIntegerField(default=20)
|
||||
is_visible = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class StoryVersion(models.Model):
|
||||
story = models.ForeignKey(Story, on_delete=models.CASCADE, related_name="versions")
|
||||
version = models.PositiveIntegerField()
|
||||
content = models.JSONField()
|
||||
is_published = models.BooleanField(default=False)
|
||||
published_at = models.DateTimeField(null=True, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=("story", "version"), name="unique_story_version")
|
||||
]
|
||||
ordering = ["story", "-version"]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.story} v{self.version}"
|
||||
|
||||
|
||||
class StoryRun(models.Model):
|
||||
class Status(models.TextChoices):
|
||||
ACTIVE = "active", "进行中"
|
||||
COMPLETED = "completed", "已完成"
|
||||
ABANDONED = "abandoned", "已放弃"
|
||||
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="story_runs")
|
||||
story_version = models.ForeignKey(StoryVersion, on_delete=models.PROTECT, related_name="runs")
|
||||
current_node = models.CharField(max_length=100)
|
||||
state = models.JSONField(default=dict)
|
||||
status = models.CharField(max_length=16, choices=Status.choices, default=Status.ACTIVE)
|
||||
ending_code = models.CharField(max_length=80, blank=True)
|
||||
started_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
completed_at = models.DateTimeField(null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ["-updated_at"]
|
||||
|
||||
|
||||
class StoryChoice(models.Model):
|
||||
run = models.ForeignKey(StoryRun, on_delete=models.CASCADE, related_name="choices")
|
||||
sequence = models.PositiveIntegerField()
|
||||
idempotency_key = models.CharField(max_length=80, null=True, blank=True)
|
||||
node_id = models.CharField(max_length=100)
|
||||
choice_index = models.PositiveIntegerField()
|
||||
choice_text = models.CharField(max_length=300)
|
||||
effects = models.JSONField(default=dict, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=("run", "sequence"), name="unique_run_choice_sequence"),
|
||||
models.UniqueConstraint(
|
||||
fields=("run", "idempotency_key"), name="unique_run_choice_idempotency"
|
||||
),
|
||||
]
|
||||
ordering = ["sequence"]
|
||||
|
||||
|
||||
class UserRelationship(models.Model):
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
|
||||
character = models.ForeignKey(Character, on_delete=models.CASCADE)
|
||||
trust = models.SmallIntegerField(default=0)
|
||||
rivalry = models.SmallIntegerField(default=0)
|
||||
debt = models.SmallIntegerField(default=0)
|
||||
cooperation = models.SmallIntegerField(default=0)
|
||||
metadata = models.JSONField(default=dict, blank=True)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=("user", "character"), name="unique_user_character")
|
||||
]
|
||||
|
||||
|
||||
class SkillPackage(models.Model):
|
||||
story = models.OneToOneField(Story, on_delete=models.CASCADE, related_name="skill_package")
|
||||
real_person = models.CharField(max_length=120)
|
||||
historical_context = models.TextField()
|
||||
fact_sources = models.JSONField(default=list)
|
||||
fictional_scope = models.TextField()
|
||||
creator = models.CharField(max_length=120)
|
||||
Reference in New Issue
Block a user