Pulled from Notion project docs: overview, architecture, data model, event system, line logic, and implementation notes for the family-tree generator + TTS narrator. Co-Authored-By: Claude <noreply@anthropic.com>
180 lines
4.4 KiB
Markdown
180 lines
4.4 KiB
Markdown
# Data Model
|
||
|
||
All identifiers and code are in English.
|
||
|
||
## Enums
|
||
|
||
```python
|
||
class Gender(IntEnum):
|
||
MALE = 0
|
||
FEMALE = 1
|
||
NONBINARY = 2
|
||
|
||
class PartnerType(IntEnum):
|
||
MARRIAGE = 0
|
||
AFFAIR = 1
|
||
POLITICAL = 2
|
||
ILLEGITIMATE = 3
|
||
|
||
class StageType(IntEnum):
|
||
CHILD = 0
|
||
TEEN = 1
|
||
YOUNG_ADULT = 2
|
||
ADULT = 3
|
||
SENIOR = 4
|
||
|
||
class Event(IntEnum):
|
||
# Category 1 — Death
|
||
DEATH_ILLNESS = 10
|
||
DEATH_ACCIDENT = 11
|
||
DEATH_COMBAT = 12
|
||
DEATH_OLD_AGE = 13
|
||
DEATH_CHILDBIRTH = 14 # mother dies during birth
|
||
|
||
# Category 2 — Partnership
|
||
PARTNER_MARRIAGE = 20
|
||
PARTNER_AFFAIR = 21
|
||
PARTNER_ENGAGEMENT = 22
|
||
PARTNER_POLITICAL = 23
|
||
PARTNER_CHILDHOOD_PROMISE = 24
|
||
|
||
# Category 3 — Offspring
|
||
CHILD_BORN = 30
|
||
CHILD_TWINS = 31
|
||
CHILD_TRIPLETS = 32
|
||
CHILD_STILLBORN = 33
|
||
CHILD_ADOPT = 34 # only path to offspring for NONBINARY; from YOUNG_ADULT onwards
|
||
|
||
# Category 4 — Daily Life
|
||
DAILY_FRIENDSHIP = 40
|
||
DAILY_FAMILY = 41
|
||
DAILY_TEMP_CHAR = 42
|
||
|
||
# Category 5 — Travel
|
||
TRAVEL_NEAR = 50
|
||
TRAVEL_FAR = 51
|
||
TRAVEL_PILGRIMAGE = 52
|
||
|
||
# Category 6 — Learning
|
||
LEARN_APPRENTICESHIP = 60
|
||
LEARN_MENTOR = 61
|
||
LEARN_SELF = 62
|
||
|
||
# Category 7 — Conflict (personal)
|
||
CONFLICT_PERSONAL = 70
|
||
CONFLICT_FIGHT = 71
|
||
CONFLICT_FEUD = 72
|
||
|
||
# Category 8 — Discovery
|
||
DISCOVER_OBJECT = 80
|
||
DISCOVER_SPELL = 81
|
||
DISCOVER_WONDER = 82
|
||
DISCOVER_KNOWLEDGE = 83
|
||
|
||
# Category 9 — Local Conflict
|
||
LOCAL_REBELLION = 90
|
||
LOCAL_PLAGUE = 91
|
||
LOCAL_DISASTER = 92
|
||
LOCAL_CRISIS = 93
|
||
|
||
# Category 10 — Intrigue
|
||
INTRIGUE_POLITICAL = 100
|
||
INTRIGUE_EXILE = 101
|
||
INTRIGUE_CONSPIRACY = 102
|
||
|
||
# Category 11 — Illness / Injury
|
||
ILLNESS_WEAK = 110
|
||
ILLNESS_SEVERE = 111
|
||
ILLNESS_CHRONIC = 112
|
||
INJURY_ACCIDENT = 113
|
||
INJURY_COMBAT = 114
|
||
```
|
||
|
||
`event_type // 10` → category, `event_type % 10` → subtype within category.
|
||
|
||
## Person
|
||
|
||
```python
|
||
Person {
|
||
id: str
|
||
name: str
|
||
gender: Gender
|
||
birth_year: int # absolute, set when person is created via parent event
|
||
death_year: int | None # birth_year + age_at_death
|
||
alive: bool
|
||
appearance: dict
|
||
profession: str | None # set by a LEARN event
|
||
home: str
|
||
is_ancestor: bool # True only for Person 1
|
||
parent_id: str | None # previous active node; None = joined from outside
|
||
generation: int
|
||
partners: PartnerEntry[]
|
||
events: str[] # event IDs in chronological order
|
||
acquaintances: str[] # IDs from person_pool only (not family tree)
|
||
stages: Stage[]
|
||
}
|
||
|
||
PartnerEntry {
|
||
person_id: str
|
||
type: PartnerType
|
||
children_ids: str[] # all children from this union
|
||
}
|
||
```
|
||
|
||
## Stage
|
||
|
||
```python
|
||
Stage {
|
||
type: StageType
|
||
age: { from: int, to: int } # relative to person
|
||
events: str[] # event IDs
|
||
}
|
||
```
|
||
|
||
### Stage Age Ranges
|
||
|
||
| Stage | Age |
|
||
|-------------|----------------|
|
||
| Child | 0–12 |
|
||
| Teen | 12–16 |
|
||
| Young Adult | 16–32 |
|
||
| Adult | 32–50 |
|
||
| Senior | 50–X (LLM decides) |
|
||
|
||
## EventEntry
|
||
|
||
```python
|
||
EventEntry {
|
||
id: str
|
||
type: Event # e.g. Event.ILLNESS_SEVERE
|
||
age: int # age of person at time of event
|
||
# absolute_year: @property -> person.birth_year + self.age
|
||
location: str | None # None = takes place at person.home
|
||
location_is_temp: bool # True = travel destination, False = known location
|
||
participants: str[] # person_ids or pool_ids
|
||
result: dict # predetermined simulation outcome
|
||
context: dict # extra info passed to LLM prompt
|
||
follow_bonus: Event[] # event types made more likely after this event
|
||
# e.g. after TRAVEL_FAR -> [DISCOVER_OBJECT, DISCOVER_WONDER]
|
||
}
|
||
```
|
||
|
||
## FamilyTree & person_pool
|
||
|
||
```python
|
||
FamilyTree {
|
||
persons: dict[str, Person] # all family tree persons
|
||
person_pool: dict[str, Person] # temporary chars with no tree membership
|
||
# e.g. random villager
|
||
# distant cousin -> lives in persons, not here
|
||
world: World
|
||
current_generation: int
|
||
active_node: str # person_id of currently narrated person
|
||
}
|
||
|
||
World {
|
||
start_year: int # randomly generated, max 4 digits, no calendar system stated
|
||
name: str
|
||
epoch_flavor: str # setting keywords passed to LLM
|
||
}
|
||
```
|