246 lines
6.4 KiB
Markdown
246 lines
6.4 KiB
Markdown
# Data Model Specification
|
|
|
|
## CId (Canonical Identifier) System
|
|
|
|
### Format Rules
|
|
|
|
CIds are identifiers for saints, feasts, and liturgical elements. They follow these routing rules:
|
|
|
|
| CId Pattern | Target File | Examples | Notes |
|
|
|-------------|-------------|----------|-------|
|
|
| `01XX-01ZZ` | `01.json` | `010101`, `014567` | January saints |
|
|
| `02XX-02ZZ` | `02.json` | `023456`, `027890` | February saints |
|
|
| ... | ... | ... | ... |
|
|
| `12XX-12ZZ` | `12.json` | `123456`, `127890` | December saints |
|
|
| Other CIds | `misc.json` | `772426`, `373`, `868` | Non-month-prefixed |
|
|
|
|
### Routing Logic
|
|
```typescript
|
|
function bundleFileForCid(cid: string): string {
|
|
return /^(0[1-9]|1[0-2])\d+/.test(cid)
|
|
? `${cid.substring(0, 2)}.json`
|
|
: 'misc.json';
|
|
}
|
|
```
|
|
|
|
## Menaion Bundle Structure
|
|
|
|
### Format Definition
|
|
```json
|
|
{
|
|
"MM-DD": [
|
|
{ "id": "CId" },
|
|
{ "id": "CId" }
|
|
]
|
|
}
|
|
```
|
|
|
|
**Key Points**:
|
|
- Each date key: "MM-DD" format (Julian calendar)
|
|
- Array of objects with only "id" field
|
|
- CIds correspond to actual commemorations on that date
|
|
- One per language: `menaion-bundle.json`, `{lang}-menaion-bundle.json`
|
|
|
|
### Example
|
|
```json
|
|
{
|
|
"01-01": [
|
|
{ "id": "010101" },
|
|
{ "id": "772426" },
|
|
{ "id": "010102" }
|
|
]
|
|
}
|
|
```
|
|
|
|
## Life Entry Structure
|
|
|
|
### Format Definition
|
|
```json
|
|
{
|
|
"CId": {
|
|
"name": {
|
|
"nominative": "Прп. Сильвестра Печерского (XII)",
|
|
"short": "Прп. Сильвестра Печерского",
|
|
"genitive": "Прп. Сильвестра Печерского"
|
|
},
|
|
"life": {
|
|
"id": "minei-0101-772426",
|
|
"copyright": "Четьи-Минеи свт. Димитрия Ростовского",
|
|
"text": "<p>Complete life text in HTML...</p>"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Required Fields
|
|
- **`CId`**: String key (the canonical identifier)
|
|
- **`name.nominative`**: Required field (validated by validate-data.ts)
|
|
|
|
### Optional Fields
|
|
- **`name.short`**: Short name variant
|
|
- **`life.text`**: HTML content (only written when empty)
|
|
- **`life.id`**: Source identifier (e.g., "minei-0101-772426")
|
|
- **`life.copyright`**: Copyright string
|
|
|
|
## Service Template Structure
|
|
|
|
### Hierarchical JSON Format
|
|
```json
|
|
{
|
|
"ROYALHOURS": {
|
|
"0": {
|
|
"text": "In the name of the Father...",
|
|
"type": "0"
|
|
}
|
|
},
|
|
"MATINS": {
|
|
"kathisma": {
|
|
"text": "Kathisma content..."
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Conditional Logic Markers
|
|
- **P-prefix nodes**: Optional content that may be included
|
|
- **Var/I-prefix nodes**: Conditional selection logic
|
|
- **Plain nodes**: Required content always included
|
|
|
|
## Chetyi-Minei Source Format
|
|
|
|
### Format Definition
|
|
```json
|
|
{
|
|
"MM-DD": [
|
|
{
|
|
"title": "Память святого X",
|
|
"html": "<p>Content paragraphs...</p>"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Key Characteristics
|
|
- Generated by `convert-mines.ts` from EPUB source
|
|
- Stored in `scripts/output/minei.json` (gitignored, 33MB)
|
|
- Titles and HTML are carefully extracted and parsed
|
|
- Footnotes collected and appended as "Примечания:" blocks
|
|
|
|
## File Organization Rules
|
|
|
|
### Lives Files
|
|
- **Location**: `static/data/{lang}/lives/`
|
|
- **Files**:
|
|
- `01.json` through `12.json` (month-prefixed CIds)
|
|
- `misc.json` (non-month-prefixed CIds)
|
|
- **Routing**: Based on first two digits of CId
|
|
|
|
### Menaion Files
|
|
- **Location**: `static/data/{lang}/menaion/`
|
|
- **Files**: `01-01.json` through `12-31.json` (daily entries)
|
|
- **Purpose**: Daily liturgical readings by date
|
|
|
|
### Service Templates
|
|
- **Location**: `static/data/{lang}/services/`
|
|
- **Shared**: `static/data/shared/services/templates/`
|
|
|
|
### Calendar Data
|
|
- **Location**: `static/data/{lang}/calendar/` and `static/data/shared/calendar/`
|
|
- **Purpose**: Movable feast calculations and metadata
|
|
|
|
## Data Invariants
|
|
|
|
### CId Consistency Rules
|
|
- Same CId must have consistent name across all languages
|
|
- Bundle CIds must have corresponding lives entries
|
|
- CIds that exist in bundle must have lives entries
|
|
- CIds with lives entries must exist in bundle for their date
|
|
|
|
### File Organization Invariants
|
|
- No month file contains CIds with different month prefix
|
|
- `misc.json` contains all CIds outside the 01-12 prefix range
|
|
- All data files are tracked in `static/data/`
|
|
|
|
### Content Validation Invariants
|
|
- All lives entries must have `name.nominative` field
|
|
- HTML content in `life.text` must be properly escaped
|
|
- JSON files must be parseable (no syntax errors)
|
|
- File routing must match CId prefixes consistently
|
|
|
|
## Common Data Mistakes to Avoid
|
|
|
|
### CId Pattern Errors
|
|
- ⚠️ Don't create CIds with invalid prefixes
|
|
- ⚠️ Don't put CIds in wrong month files
|
|
- ⚠️ Don't create duplicate CIds with different meanings
|
|
|
|
### JSON Structure Errors
|
|
- ⚠️ Don't omit required fields (`name.nominative`)
|
|
- ⚠️ Don't nest structures incorrectly (service templates)
|
|
- ⚠️ Don't mix CId numbers and strings inconsistently
|
|
- ⚠️ Don't leave trailing commas in JSON
|
|
|
|
### File Organization Mistakes
|
|
- ⚠️ Don't place month-prefixed CIds in misc.json
|
|
- ⚠️ Don't create inconsistent JSON indentation
|
|
- ⚠️ Don't mix languages in incorrect directories
|
|
|
|
## Examples
|
|
|
|
### Valid CId Examples
|
|
- `010101` → `01.json` (January saint)
|
|
- `1253` → `12.json` (December saint)
|
|
- `772426` → `misc.json` (non-prefixed saint)
|
|
|
|
### Invalid CId Examples
|
|
- `00501` → Should not exist (prefix `00` → misc)
|
|
- `13xxx` → Should not exist (prefix `13` → misc)
|
|
|
|
### File Routing Examples
|
|
- CId `1253` routes to `12.json`
|
|
- CId `772426` routes to `misc.json`
|
|
- CId `010101` routes to `01.json`
|
|
|
|
### Bundle Entry Examples
|
|
```json
|
|
{
|
|
"01-15": [
|
|
{ "id": "010201" },
|
|
{ "id": "772455" }
|
|
]
|
|
}
|
|
```
|
|
|
|
### Life Entry Examples
|
|
```json
|
|
{
|
|
"772426": {
|
|
"name": {
|
|
"nominative": "Прп. Сильвестра Печерского (XII)",
|
|
"short": "Прп. Сильвестра Печерского"
|
|
},
|
|
"life": {
|
|
"id": "minei-0101-772426",
|
|
"copyright": "Четьи-Минеи свт. Димитрия Ростовского",
|
|
"text": "<p>Complete life content...</p>"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Current Project State
|
|
|
|
### Coverage Statistics
|
|
- Total CIds: 3046
|
|
- Lives with text: 1190 (39% coverage)
|
|
- Empty lives: 1856 (61% remain)
|
|
|
|
### Data Files
|
|
- Total validated files: 274
|
|
- Main source files: 6 Lives bundle files (misc, 01-12)
|
|
- Service template files: Multiple per language
|
|
|
|
### Recent Changes
|
|
- Bundle fix: 868 Иаков Боровицký moved from 05-22 to 10-23
|
|
- Enrichment: 64 manual fixes added to enrich-lives.ts
|
|
- Coverage increase: 1009→1190 lives with text (191 new) |