# 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": "
Complete life text in HTML...
" } } } ``` ### 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": "Content paragraphs...
" } ] } ``` ### 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": "Complete life content...
" } } } ``` ## 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)