DEV Community

HYUN SOO LEE
HYUN SOO LEE

Posted on • Originally published at runartree.com

Building a Saju Engine: Case Study with Karina's Birth Chart Algorithm

The Data Problem K-pop Poses to Backend Engineers

Here's a fun engineering challenge that landed on my desk last year: how do you build a production-grade Korean Saju (Four Pillars of Destiny) calculation engine that can handle celebrity birth data at scale?

The problem sounds niche until you realize the scope. We're talking about parsing UTC timestamps down to the minute, converting them through multiple calendar systems (Gregorian → Lunar → Sexagenary), applying 1,500+ year-old algorithms, and outputting structured fortune analysis. All while handling timezone edge cases that would make any backend dev weep.

Enter Runartree — our deterministic Myeongri engine built in PHP/MySQL. No LLMs, no machine learning black boxes. Just classical Saju algorithms (十神, 五行, 大運, 세운) implemented as pure functions.

Today I'll walk you through our engine using a real case study: Karina from aespa. We ran her birth data through our "Overall Fortune" analysis pipeline, and I'll show you exactly how the algorithms work under the hood.

Why Karina? Her birth chart presents interesting edge cases — multiple 괴강살 (Kuei-kang) configurations, zero Wood element (木 0%), and a Day Pillar sitting in 胎 (embryo) position. Perfect stress test for our parsing logic.

The technical challenge isn't just calendar math — it's handling the combinatorial explosion of element interactions, 60-year cycles, and 10-year luck periods. Think of it as a deterministic state machine with 60^4 possible input combinations and culturally-encoded business logic dating back to the Tang Dynasty.

Deep Dive: Myeongri Engine Pipeline

Our Saju engine follows a classic ETL pattern: Extract birth timestamp → Transform through calendar systems → Load into element analysis algorithms.

Step 1: Day Pillar (日柱) Calculation

The core challenge is converting any UTC timestamp into the correct Sexagenary Cycle position. Here's our Day Pillar calculator:

php
class SexagenaryCycleCalculator {
private const STEMS = ['甲','乙','丙','丁','戊','己','庚','辛','壬','癸'];
private const BRANCHES = ['子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥'];
private const EPOCH_OFFSET = 8; // 甲子 = day 0 offset

public function getDayPillar($utcTimestamp, $timezone) {
    $localTime = $this->convertToLocalSolarTime($utcTimestamp, $timezone);
    $julianDay = $this->gregorianToJulian($localTime);

    // Sexagenary cycle: 60-day repeating pattern
    $cyclePosition = ($julianDay + self::EPOCH_OFFSET) % 60;

    $stemIndex = $cyclePosition % 10;
    $branchIndex = $cyclePosition % 12;

    return [
        'stem' => self::STEMS[$stemIndex],
        'branch' => self::BRANCHES[$branchIndex],
        'combined' => self::STEMS[$stemIndex] . self::BRANCHES[$branchIndex],
        'position' => $cyclePosition
    ];
}

private function convertToLocalSolarTime($utc, $tz) {
    // Handle leap seconds, DST transitions, solar-term boundaries
    // This gets gnarly with historical timezone data...
    return $this->solarTimeAdjustment($utc, $tz);
}
Enter fullscreen mode Exit fullscreen mode

}

For Karina's case, her Day Pillar came out as 己亥 (Ji-Hai) — Earth Pig. The 己 (Ji) represents soft, fertile earth. The 亥 (Hai) carries Water element and sits in "embryo" position within the 12-branch life cycle.

Step 2: Ten Gods (十神) Classification Algorithm

Once we have all four pillars, we need to classify each element relationship using the Ten Gods system. This is where it gets algorithmically interesting:

php
class TenGodsAnalyzer {
// Five Elements interaction matrix (생극관계)
private const ELEMENT_RELATIONS = [
'木' => ['generates' => '火', 'destroys' => '土'],
'火' => ['generates' => '土', 'destroys' => '金'],
'土' => ['generates' => '金', 'destroys' => '水'],
'金' => ['generates' => '水', 'destroys' => '木'],
'水' => ['generates' => '木', 'destroys' => '火']
];

public function classifyTenGods($dayMaster, $otherElement, $polarity) {
    $relationship = $this->getElementRelation($dayMaster, $otherElement);

    switch($relationship) {
        case 'same_element':
            return $polarity === 'same' ? '比肩' : '劫財'; // Shoulder/Rob Wealth

        case 'day_generates':
            return $polarity === 'same' ? '食神' : '傷官'; // Food God/Hurting Officer

        case 'day_destroys':
            return $polarity === 'same' ? '偏財' : '正財'; // Indirect/Direct Wealth

        case 'destroys_day':
            return $polarity === 'same' ? '偏官' : '正官'; // 7-Killings/Officer

        case 'generates_day':
            return $polarity === 'same' ? '偏印' : '正印'; // Indirect/Direct Resource
    }
}

public function scoreElementDistribution($fourPillars) {
    $distribution = ['木' => 0, '火' => 0, '土' => 0, '金' => 0, '水' => 0];
    $total = 0;

    foreach($fourPillars as $pillar) {
        $stemWeight = $this->getStemElementWeight($pillar['stem']);
        $branchWeight = $this->getBranchElementWeight($pillar['branch']);

        $distribution[$stemWeight['element']] += $stemWeight['points'];
        $distribution[$branchWeight['element']] += $branchWeight['points'];
        $total += $stemWeight['points'] + $branchWeight['points'];
    }

    // Convert to percentages
    return array_map(fn($count) => round($count/$total * 100), $distribution);
}
Enter fullscreen mode Exit fullscreen mode

}

Karina's Results:

  • 土 (Earth): 38% — Her Day Master element, providing stability but potentially rigid
  • 金 (Metal): 38% — Dominant 傷官 (Hurting Officer) energy = creative expression
  • 水 (Water): 13% — Limited 正印 (Resource) support
  • 火 (Fire): 11% — Minimal warmth/enthusiasm
  • 木 (Wood): 0% — Complete absence of 官星 (Authority) = rule-breaking tendency

The algorithmic insight here: three 傷官 (Hurting Officer) gods in Heaven Stems. In classical Saju theory, this creates an "expression overflow" pattern — intense creativity coupled with authority resistance.

Engineering Trade-offs We Faced

Timezone Hell: Converting celebrity birth data means handling historical timezone changes. Seoul's UTC offset shifted multiple times in the 20th century. We maintain a custom timezone database with transition dates.

Solar Term Boundaries: Traditional Chinese calendar divides the year into 24 solar terms, each ~15 days. Month boundaries don't align with Gregorian calendar. We pre-calculate all solar term timestamps and store them as lookup tables.

Performance vs Accuracy: Full Saju analysis involves calculating 10-year 大運 (Great Luck) periods spanning 80+ years forward from birth. We cache intermediate calculations but still hit ~200ms compute time per full chart.

The Five Elements DAG: Think rock-paper-scissors but with 5 players and generative relationships. Each element simultaneously generates one element and destroys another. We model this as a directed graph for cycle detection in complex element interactions.

Karina's Full Analysis Output

Here's what our engine generated for her Overall Fortune analysis:

Current 大運 Period: 丑 (Ugly-Earth) — reinforcing her already earth-heavy constitution. This creates "element stagnation" where growth requires external catalyst.

Key Strengths: Triple 傷官 configuration suggests exceptional creative output and independent thinking. The 己亥 Day Pillar combines practical earth with intuitive water — perfect for artistic endeavors requiring both vision and execution.

Structural Weaknesses: Zero Wood element means difficulty with hierarchical relationships and rule-following. The analysis flagged potential conflicts with authority figures and structured environments.

2026-2029 Forecast: 丙午 (Fire-Horse) year brings 印星 (Resource) energy — intellectual growth and learning opportunities. 2028-2029 shows strengthening Metal element, potentially indicating career advancement in creative fields.

The 괴강살 (Kuei-kang) double configuration particularly caught our algorithm's attention — this represents "exceptional intelligence with stubborn streaks." Classical texts describe it as "brilliant but uncompromising."

Try the Engine Yourself

Want to see how your own birth data runs through our algorithms? We've built this as a production API that handles the full complexity — timezone conversions, solar term calculations, element scoring, and 대운 period analysis.

Head to runartree.com/promo/karina-aespa?utm_source=devto&utm_medium=article&utm_campaign=tech_overall and plug in any birthdate. You'll get back structured JSON with element distributions, Ten Gods classifications, and algorithmic fortune analysis.

The engineering challenge here fascinates me: we're essentially running 1,500-year-old algorithms on modern cloud infrastructure. It's like implementing Byzantine fault tolerance using Tang Dynasty consensus mechanisms.

What other pre-modern algorithms deserve a modern PHP port? I'm thinking Islamic astronomical calculations, Mayan calendar math, maybe Roman numeral arithmetic optimizations. Drop a comment with your wildest ideas.

Coming in Season 2 (늦여름 2026): Full open-source SDK with REST API endpoints. We're also working on GraphQL support for complex multi-person relationship analysis.

The deterministic nature of these classical algorithms makes them surprisingly well-suited for modern backend architecture. No training data, no model drift, just pure mathematical relationships encoded in cultural wisdom.

That's the beauty of building production systems around ancient knowledge — the algorithms have already been battle-tested across centuries of human experience.

Top comments (0)