@orrery/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,698 @@
1
+ import {
2
+ BAEKHO_PILLARS,
3
+ BRANCH_BREAKS,
4
+ BRANCH_CLASHES,
5
+ BRANCH_COMBINES_6,
6
+ BRANCH_HARMS,
7
+ BRANCH_PUNISHMENTS,
8
+ BRANCH_SELF_PUNISHMENTS,
9
+ DIRECTIONAL_COMPOSES,
10
+ DIRECTIONAL_COMPOSE_ELEMENTS,
11
+ EARTH,
12
+ EARTH_KR,
13
+ GOEGANG_PILLARS,
14
+ HALF_COMPOSES,
15
+ HGANJI,
16
+ JIJANGGAN,
17
+ METEORS_12,
18
+ METEOR_LOOKUP,
19
+ PILLAR_NAMES,
20
+ RELATIONS,
21
+ SKY,
22
+ SKY_KR,
23
+ SPIRITS_12,
24
+ STEM_CLASHES,
25
+ STEM_COMBINES,
26
+ STEM_INFO,
27
+ TRIPLE_COMPOSES,
28
+ TRIPLE_COMPOSE_ELEMENTS,
29
+ YANGGAN,
30
+ YANGIN_MAP
31
+ } from "./chunk-VJDUZB5T.js";
32
+
33
+ // src/pillars.ts
34
+ function div(a, b) {
35
+ return Math.trunc(a / b);
36
+ }
37
+ var MONTH = [
38
+ 0,
39
+ 21355,
40
+ 42843,
41
+ 64498,
42
+ 86335,
43
+ 108366,
44
+ 130578,
45
+ 152958,
46
+ 175471,
47
+ 198077,
48
+ 220728,
49
+ 243370,
50
+ 265955,
51
+ 288432,
52
+ 310767,
53
+ 332928,
54
+ 354903,
55
+ 376685,
56
+ 398290,
57
+ 419736,
58
+ 441060,
59
+ 462295,
60
+ 483493,
61
+ 504693,
62
+ 525949
63
+ ];
64
+ var UNIT = {
65
+ year: 1996,
66
+ month: 2,
67
+ day: 4,
68
+ hour: 22,
69
+ min: 8,
70
+ // 세차
71
+ ygan: 2,
72
+ yji: 0,
73
+ // 월건
74
+ mgan: 6,
75
+ mji: 2,
76
+ msu: 26,
77
+ // 일진
78
+ dgan: 7,
79
+ dji: 7,
80
+ dsu: 7,
81
+ // 시주
82
+ hgan: 5,
83
+ hji: 11,
84
+ hsu: 35
85
+ };
86
+ function dayOfYear(year, month, day) {
87
+ let e = 0;
88
+ for (let i = 1; i < month; i++) {
89
+ e += 31;
90
+ if (i === 2 || i === 4 || i === 6 || i === 9 || i === 11) {
91
+ e -= 1;
92
+ }
93
+ if (i === 2) {
94
+ e -= 2;
95
+ if (year % 4 === 0) e += 1;
96
+ if (year % 100 === 0) e -= 1;
97
+ if (year % 400 === 0) e += 1;
98
+ if (year % 4e3 === 0) e -= 1;
99
+ }
100
+ }
101
+ e += day;
102
+ return e;
103
+ }
104
+ function daysBetween(y1, m1, d1, y2, m2, d2) {
105
+ let p1, p1n, p2;
106
+ let pp1, pp2, pr;
107
+ if (y2 > y1) {
108
+ p1 = dayOfYear(y1, m1, d1);
109
+ p1n = dayOfYear(y1, 12, 31);
110
+ p2 = dayOfYear(y2, m2, d2);
111
+ pp1 = y1;
112
+ pp2 = y2;
113
+ pr = -1;
114
+ } else {
115
+ p1 = dayOfYear(y2, m2, d2);
116
+ p1n = dayOfYear(y2, 12, 31);
117
+ p2 = dayOfYear(y1, m1, d1);
118
+ pp1 = y2;
119
+ pp2 = y1;
120
+ pr = 1;
121
+ }
122
+ let dis;
123
+ if (y2 === y1) {
124
+ dis = p2 - p1;
125
+ } else {
126
+ dis = p1n - p1;
127
+ let k = pp1 + 1;
128
+ const ppp2 = pp2 - 1;
129
+ while (k <= ppp2) {
130
+ if (k === -2e3 && ppp2 > 1990) {
131
+ dis += 1457682;
132
+ k = 1991;
133
+ } else if (k === -1750 && ppp2 > 1990) {
134
+ dis += 1366371;
135
+ k = 1991;
136
+ } else if (k === -1500 && ppp2 > 1990) {
137
+ dis += 1275060;
138
+ k = 1991;
139
+ } else if (k === -1250 && ppp2 > 1990) {
140
+ dis += 1183750;
141
+ k = 1991;
142
+ } else if (k === -1e3 && ppp2 > 1990) {
143
+ dis += 1092439;
144
+ k = 1991;
145
+ } else if (k === -750 && ppp2 > 1990) {
146
+ dis += 1001128;
147
+ k = 1991;
148
+ } else if (k === -500 && ppp2 > 1990) {
149
+ dis += 909818;
150
+ k = 1991;
151
+ } else if (k === -250 && ppp2 > 1990) {
152
+ dis += 818507;
153
+ k = 1991;
154
+ } else if (k === 0 && ppp2 > 1990) {
155
+ dis += 727197;
156
+ k = 1991;
157
+ } else if (k === 250 && ppp2 > 1990) {
158
+ dis += 635887;
159
+ k = 1991;
160
+ } else if (k === 500 && ppp2 > 1990) {
161
+ dis += 544576;
162
+ k = 1991;
163
+ } else if (k === 750 && ppp2 > 1990) {
164
+ dis += 453266;
165
+ k = 1991;
166
+ } else if (k === 1e3 && ppp2 > 1990) {
167
+ dis += 361955;
168
+ k = 1991;
169
+ } else if (k === 1250 && ppp2 > 1990) {
170
+ dis += 270644;
171
+ k = 1991;
172
+ } else if (k === 1500 && ppp2 > 1990) {
173
+ dis += 179334;
174
+ k = 1991;
175
+ } else if (k === 1750 && ppp2 > 1990) {
176
+ dis += 88023;
177
+ k = 1991;
178
+ }
179
+ dis += dayOfYear(k, 12, 31);
180
+ k += 1;
181
+ }
182
+ dis += p2;
183
+ dis *= pr;
184
+ }
185
+ return dis;
186
+ }
187
+ function minutesBetween(uy, umm, ud, uh, umin, y1, mo1, d1, h1, mm1) {
188
+ const dispday = daysBetween(uy, umm, ud, y1, mo1, d1);
189
+ return dispday * 24 * 60 + (uh - h1) * 60 + (umin - mm1);
190
+ }
191
+ function dateFromMinutes(tmin, uyear, umonth, uday, uhour, umin) {
192
+ let y1, mo1, d1, h1, mi1;
193
+ let t;
194
+ y1 = uyear - div(tmin, 525949);
195
+ if (tmin > 0) {
196
+ y1 += 2;
197
+ while (true) {
198
+ y1 -= 1;
199
+ t = minutesBetween(uyear, umonth, uday, uhour, umin, y1, 1, 1, 0, 0);
200
+ if (t >= tmin) break;
201
+ }
202
+ mo1 = 13;
203
+ while (true) {
204
+ mo1 -= 1;
205
+ t = minutesBetween(uyear, umonth, uday, uhour, umin, y1, mo1, 1, 0, 0);
206
+ if (t >= tmin) break;
207
+ }
208
+ d1 = 32;
209
+ while (true) {
210
+ d1 -= 1;
211
+ t = minutesBetween(uyear, umonth, uday, uhour, umin, y1, mo1, d1, 0, 0);
212
+ if (t >= tmin) break;
213
+ }
214
+ h1 = 24;
215
+ while (true) {
216
+ h1 -= 1;
217
+ t = minutesBetween(uyear, umonth, uday, uhour, umin, y1, mo1, d1, h1, 0);
218
+ if (t >= tmin) break;
219
+ }
220
+ t = minutesBetween(uyear, umonth, uday, uhour, umin, y1, mo1, d1, h1, 0);
221
+ mi1 = t - tmin;
222
+ } else {
223
+ y1 -= 2;
224
+ while (true) {
225
+ y1 += 1;
226
+ t = minutesBetween(uyear, umonth, uday, uhour, umin, y1, 1, 1, 0, 0);
227
+ if (t < tmin) break;
228
+ }
229
+ y1 -= 1;
230
+ mo1 = 0;
231
+ while (true) {
232
+ mo1 += 1;
233
+ t = minutesBetween(uyear, umonth, uday, uhour, umin, y1, mo1, 1, 0, 0);
234
+ if (t < tmin) break;
235
+ }
236
+ mo1 -= 1;
237
+ d1 = 0;
238
+ while (true) {
239
+ d1 += 1;
240
+ t = minutesBetween(uyear, umonth, uday, uhour, umin, y1, mo1, d1, 0, 0);
241
+ if (t < tmin) break;
242
+ }
243
+ d1 -= 1;
244
+ h1 = -1;
245
+ while (true) {
246
+ h1 += 1;
247
+ t = minutesBetween(uyear, umonth, uday, uhour, umin, y1, mo1, d1, h1, 0);
248
+ if (t < tmin) break;
249
+ }
250
+ h1 -= 1;
251
+ t = minutesBetween(uyear, umonth, uday, uhour, umin, y1, mo1, d1, h1, 0);
252
+ mi1 = t - tmin;
253
+ }
254
+ return [y1, mo1, d1, h1, mi1];
255
+ }
256
+ function calcPillarIndices(year, month, day, hour, min) {
257
+ const displ2min = minutesBetween(
258
+ UNIT.year,
259
+ UNIT.month,
260
+ UNIT.day,
261
+ UNIT.hour,
262
+ UNIT.min,
263
+ year,
264
+ month,
265
+ day,
266
+ hour,
267
+ min
268
+ );
269
+ const displ2day = daysBetween(
270
+ UNIT.year,
271
+ UNIT.month,
272
+ UNIT.day,
273
+ year,
274
+ month,
275
+ day
276
+ );
277
+ let so24 = div(displ2min, 525949);
278
+ if (displ2min >= 0) so24 += 1;
279
+ let so24year = so24 % 60 * -1 + 12;
280
+ if (so24year < 0) so24year += 60;
281
+ else if (so24year > 59) so24year -= 60;
282
+ let monthmin100 = displ2min % 525949;
283
+ monthmin100 = 525949 - monthmin100;
284
+ if (monthmin100 < 0) monthmin100 += 525949;
285
+ else if (monthmin100 >= 525949) monthmin100 -= 525949;
286
+ let so24monthIdx = 0;
287
+ for (let i2 = 0; i2 < 12; i2++) {
288
+ const j = i2 * 2;
289
+ if (MONTH[j] <= monthmin100 && monthmin100 < MONTH[j + 2]) {
290
+ so24monthIdx = i2;
291
+ }
292
+ }
293
+ let t = so24year % 10;
294
+ t = t % 5;
295
+ t = t * 12 + 2 + so24monthIdx;
296
+ let so24month = t;
297
+ if (so24month > 59) so24month -= 60;
298
+ let so24day = displ2day % 60;
299
+ so24day = so24day * -1 + 7;
300
+ if (so24day < 0) so24day += 60;
301
+ else if (so24day > 59) so24day -= 60;
302
+ let i;
303
+ if (hour === 0 || hour === 1 && min < 30) {
304
+ i = 0;
305
+ } else if (hour === 1 && min >= 30 || hour === 2 || hour === 3 && min < 30) {
306
+ i = 1;
307
+ } else if (hour === 3 && min >= 30 || hour === 4 || hour === 5 && min < 30) {
308
+ i = 2;
309
+ } else if (hour === 5 && min >= 30 || hour === 6 || hour === 7 && min < 30) {
310
+ i = 3;
311
+ } else if (hour === 7 && min >= 30 || hour === 8 || hour === 9 && min < 30) {
312
+ i = 4;
313
+ } else if (hour === 9 && min >= 30 || hour === 10 || hour === 11 && min < 30) {
314
+ i = 5;
315
+ } else if (hour === 11 && min >= 30 || hour === 12 || hour === 13 && min < 30) {
316
+ i = 6;
317
+ } else if (hour === 13 && min >= 30 || hour === 14 || hour === 15 && min < 30) {
318
+ i = 7;
319
+ } else if (hour === 15 && min >= 30 || hour === 16 || hour === 17 && min < 30) {
320
+ i = 8;
321
+ } else if (hour === 17 && min >= 30 || hour === 18 || hour === 19 && min < 30) {
322
+ i = 9;
323
+ } else if (hour === 19 && min >= 30 || hour === 20 || hour === 21 && min < 30) {
324
+ i = 10;
325
+ } else if (hour === 21 && min >= 30 || hour === 22 || hour === 23 && min < 30) {
326
+ i = 11;
327
+ } else {
328
+ so24day += 1;
329
+ if (so24day === 60) so24day = 0;
330
+ i = 0;
331
+ }
332
+ t = so24day % 10;
333
+ t = t % 5;
334
+ t = t * 12 + i;
335
+ const so24hour = t;
336
+ return [so24, so24year, so24month, so24day, so24hour];
337
+ }
338
+ function calcSolarTerms(year, month, day, hour, min) {
339
+ const [, , so24month] = calcPillarIndices(year, month, day, hour, min);
340
+ const displ2min = minutesBetween(
341
+ UNIT.year,
342
+ UNIT.month,
343
+ UNIT.day,
344
+ UNIT.hour,
345
+ UNIT.min,
346
+ year,
347
+ month,
348
+ day,
349
+ hour,
350
+ min
351
+ );
352
+ let monthmin100 = displ2min % 525949 * -1;
353
+ if (monthmin100 < 0) monthmin100 += 525949;
354
+ else if (monthmin100 >= 525949) monthmin100 -= 525949;
355
+ let ii = so24month % 12 - 2;
356
+ if (ii === -2) ii = 10;
357
+ else if (ii === -1) ii = 11;
358
+ const ingiName = ii * 2;
359
+ const midName = ii * 2 + 1;
360
+ const outgiName = ii * 2 + 2;
361
+ const j = ii * 2;
362
+ let tmin = displ2min + (monthmin100 - MONTH[j]);
363
+ const [ingiYear, ingiMonth, ingiDay, ingiHour, ingiMin] = dateFromMinutes(
364
+ tmin,
365
+ UNIT.year,
366
+ UNIT.month,
367
+ UNIT.day,
368
+ UNIT.hour,
369
+ UNIT.min
370
+ );
371
+ tmin = displ2min + (monthmin100 - MONTH[j + 1]);
372
+ const [midYear, midMonth, midDay, midHour, midMin] = dateFromMinutes(
373
+ tmin,
374
+ UNIT.year,
375
+ UNIT.month,
376
+ UNIT.day,
377
+ UNIT.hour,
378
+ UNIT.min
379
+ );
380
+ tmin = displ2min + (monthmin100 - MONTH[j + 2]);
381
+ const [outgiYear, outgiMonth, outgiDay, outgiHour, outgiMin] = dateFromMinutes(
382
+ tmin,
383
+ UNIT.year,
384
+ UNIT.month,
385
+ UNIT.day,
386
+ UNIT.hour,
387
+ UNIT.min
388
+ );
389
+ return {
390
+ ingiName,
391
+ ingiYear,
392
+ ingiMonth,
393
+ ingiDay,
394
+ ingiHour,
395
+ ingiMin,
396
+ midName,
397
+ midYear,
398
+ midMonth,
399
+ midDay,
400
+ midHour,
401
+ midMin,
402
+ outgiName,
403
+ outgiYear,
404
+ outgiMonth,
405
+ outgiDay,
406
+ outgiHour,
407
+ outgiMin
408
+ };
409
+ }
410
+ function getFourPillars(year, month, day, hour, minute) {
411
+ const [, y, m, d, h] = calcPillarIndices(year, month, day, hour, minute);
412
+ return [HGANJI[y], HGANJI[m], HGANJI[d], HGANJI[h]];
413
+ }
414
+ function getDaewoon(isMale, year, month, day, hour, minute) {
415
+ const [, sy, sm] = calcPillarIndices(year, month, day, hour, minute);
416
+ const yearStem = HGANJI[sy][0];
417
+ const isYangGan = YANGGAN.includes(yearStem);
418
+ const order = isMale && isYangGan || !isMale && !isYangGan;
419
+ const terms = calcSolarTerms(year, month, day, hour, minute);
420
+ const d0 = order ? new Date(terms.outgiYear, terms.outgiMonth - 1, terms.outgiDay, terms.outgiHour, terms.outgiMin) : new Date(terms.ingiYear, terms.ingiMonth - 1, terms.ingiDay, terms.ingiHour, terms.ingiMin);
421
+ const birth = new Date(year, month - 1, day, hour, minute);
422
+ const diff = birth.getTime() - d0.getTime();
423
+ const secondsToFirst = Math.abs(diff / 1e3 * 365.242196 / 3);
424
+ let nextDate = new Date(birth.getTime() + secondsToFirst * 1e3);
425
+ nextDate.setMilliseconds(0);
426
+ const flow = order ? 1 : -1;
427
+ let mIdx = sm;
428
+ const ret = [];
429
+ for (let i = 0; i < 10; i++) {
430
+ mIdx = mIdx + flow;
431
+ if (mIdx >= HGANJI.length) mIdx = 0;
432
+ if (mIdx < 0) mIdx = HGANJI.length - 1;
433
+ ret.push({ ganzi: HGANJI[mIdx], startDate: new Date(nextDate) });
434
+ nextDate = new Date(nextDate);
435
+ nextDate.setFullYear(nextDate.getFullYear() + 10);
436
+ }
437
+ return ret;
438
+ }
439
+ function getInteraction(e0, e1) {
440
+ if (e0 === e1) return "same";
441
+ if (e0 === "water" && e1 === "tree" || e0 === "tree" && e1 === "fire" || e0 === "fire" && e1 === "earth" || e0 === "earth" && e1 === "metal" || e0 === "metal" && e1 === "water") return "output";
442
+ if (e0 === "water" && e1 === "metal" || e0 === "tree" && e1 === "water" || e0 === "fire" && e1 === "tree" || e0 === "earth" && e1 === "fire" || e0 === "metal" && e1 === "earth") return "input";
443
+ if (e0 === "water" && e1 === "earth" || e0 === "tree" && e1 === "metal" || e0 === "fire" && e1 === "water" || e0 === "earth" && e1 === "tree" || e0 === "metal" && e1 === "fire") return "shield";
444
+ if (e0 === "water" && e1 === "fire" || e0 === "tree" && e1 === "earth" || e0 === "fire" && e1 === "metal" || e0 === "earth" && e1 === "water" || e0 === "metal" && e1 === "tree") return "sword";
445
+ return null;
446
+ }
447
+ function getRelation(dayStem, targetStem) {
448
+ const day = STEM_INFO[dayStem];
449
+ const target = STEM_INFO[targetStem];
450
+ if (!day || !target) return null;
451
+ const interaction = getInteraction(day.element, target.element);
452
+ if (!interaction) return null;
453
+ const sameYY = day.yinyang === target.yinyang;
454
+ switch (interaction) {
455
+ case "same":
456
+ return sameYY ? RELATIONS[0] : RELATIONS[1];
457
+ case "output":
458
+ return sameYY ? RELATIONS[2] : RELATIONS[3];
459
+ case "sword":
460
+ return sameYY ? RELATIONS[4] : RELATIONS[5];
461
+ case "shield":
462
+ return sameYY ? RELATIONS[6] : RELATIONS[7];
463
+ case "input":
464
+ return sameYY ? RELATIONS[8] : RELATIONS[9];
465
+ }
466
+ }
467
+ function getHiddenStems(branch) {
468
+ return JIJANGGAN[branch] || "";
469
+ }
470
+ function getJeonggi(branch) {
471
+ const jijang = getHiddenStems(branch);
472
+ return jijang.replace(/ /g, "").slice(-1);
473
+ }
474
+ function toHangul(hanja) {
475
+ const skyIdx = SKY.indexOf(hanja);
476
+ if (skyIdx >= 0) return SKY_KR[skyIdx];
477
+ const earthIdx = EARTH.indexOf(hanja);
478
+ if (earthIdx >= 0) return EARTH_KR[earthIdx];
479
+ return hanja;
480
+ }
481
+ function getTwelveMeteor(stem, branch) {
482
+ const stemKr = toHangul(stem);
483
+ const branchKr = toHangul(branch);
484
+ const key = stemKr + branchKr;
485
+ const idx = METEOR_LOOKUP[key];
486
+ if (idx !== void 0) return METEORS_12[idx].hanja;
487
+ return "?";
488
+ }
489
+ var SPIRIT_START = {
490
+ "\u5BC5": 11,
491
+ "\u5348": 11,
492
+ "\u620C": 11,
493
+ // 亥
494
+ "\u5DF3": 2,
495
+ "\u9149": 2,
496
+ "\u4E11": 2,
497
+ // 寅
498
+ "\u7533": 5,
499
+ "\u5B50": 5,
500
+ "\u8FB0": 5,
501
+ // 巳
502
+ "\u4EA5": 8,
503
+ "\u536F": 8,
504
+ "\u672A": 8
505
+ // 申
506
+ };
507
+ function getTwelveSpirit(yearBranch, targetBranch) {
508
+ const start = SPIRIT_START[yearBranch];
509
+ if (start === void 0) return "?";
510
+ const targetIdx = EARTH.indexOf(targetBranch);
511
+ if (targetIdx < 0) return "?";
512
+ const offset = ((targetIdx - start) % 12 + 12) % 12;
513
+ return SPIRITS_12[offset].hanja;
514
+ }
515
+ function lookupPair(table, a, b) {
516
+ return table[`${a},${b}`] ?? table[`${b},${a}`];
517
+ }
518
+ function getStemRelation(stem1, stem2) {
519
+ const results = [];
520
+ const combine = lookupPair(STEM_COMBINES, stem1, stem2);
521
+ if (combine) results.push({ type: combine[0], detail: combine[1] });
522
+ const clash = lookupPair(STEM_CLASHES, stem1, stem2);
523
+ if (clash) results.push({ type: clash, detail: null });
524
+ return results;
525
+ }
526
+ function getBranchRelation(branch1, branch2) {
527
+ const results = [];
528
+ const combine = lookupPair(BRANCH_COMBINES_6, branch1, branch2);
529
+ if (combine) results.push({ type: combine[0], detail: combine[1] });
530
+ const half = lookupPair(HALF_COMPOSES, branch1, branch2);
531
+ if (half) results.push({ type: half[0], detail: half[1] });
532
+ const clash = lookupPair(BRANCH_CLASHES, branch1, branch2);
533
+ if (clash) results.push({ type: clash, detail: null });
534
+ const brk = lookupPair(BRANCH_BREAKS, branch1, branch2);
535
+ if (brk) results.push({ type: brk, detail: null });
536
+ const harm = lookupPair(BRANCH_HARMS, branch1, branch2);
537
+ if (harm) results.push({ type: harm, detail: null });
538
+ const pKey1 = `${branch1},${branch2}`;
539
+ const pKey2 = `${branch2},${branch1}`;
540
+ if (BRANCH_PUNISHMENTS[pKey1]) {
541
+ const [t, d] = BRANCH_PUNISHMENTS[pKey1];
542
+ results.push({ type: t, detail: d });
543
+ } else if (BRANCH_PUNISHMENTS[pKey2]) {
544
+ const [t, d] = BRANCH_PUNISHMENTS[pKey2];
545
+ results.push({ type: t, detail: d });
546
+ }
547
+ if (branch1 === branch2 && BRANCH_SELF_PUNISHMENTS.has(branch1)) {
548
+ results.push({ type: "\u5211", detail: "\u81EA\u5211" });
549
+ }
550
+ return results;
551
+ }
552
+ function analyzePillarRelations(pillar1, pillar2) {
553
+ return {
554
+ stem: getStemRelation(pillar1[0], pillar2[0]),
555
+ branch: getBranchRelation(pillar1[1], pillar2[1])
556
+ };
557
+ }
558
+ function checkTripleCompose(branches) {
559
+ const results = [];
560
+ const branchSet = new Set(branches);
561
+ for (const triple of TRIPLE_COMPOSES) {
562
+ if (triple.every((b) => branchSet.has(b))) {
563
+ const key = triple.join(",");
564
+ results.push({ type: "\u4E09\u5408", detail: TRIPLE_COMPOSE_ELEMENTS[key] });
565
+ }
566
+ }
567
+ return results;
568
+ }
569
+ function checkDirectionalCompose(branches) {
570
+ const results = [];
571
+ const branchSet = new Set(branches);
572
+ for (const dir of DIRECTIONAL_COMPOSES) {
573
+ if (dir.every((b) => branchSet.has(b))) {
574
+ const key = dir.join(",");
575
+ results.push({ type: "\u65B9\u5408", detail: DIRECTIONAL_COMPOSE_ELEMENTS[key] });
576
+ }
577
+ }
578
+ return results;
579
+ }
580
+ function analyzeAllRelations(pillars) {
581
+ const pairs = /* @__PURE__ */ new Map();
582
+ for (let i = 0; i < pillars.length; i++) {
583
+ for (let j = i + 1; j < pillars.length; j++) {
584
+ const rel = analyzePillarRelations(pillars[i], pillars[j]);
585
+ if (rel.stem.length > 0 || rel.branch.length > 0) {
586
+ pairs.set(`${i},${j}`, rel);
587
+ }
588
+ }
589
+ }
590
+ const branches = pillars.map((p) => p[1]);
591
+ return {
592
+ pairs,
593
+ triple: checkTripleCompose(branches),
594
+ directional: checkDirectionalCompose(branches)
595
+ };
596
+ }
597
+ function getSpecialSals(dayStem, dayPillar, branches) {
598
+ const yanginBranch = YANGIN_MAP[dayStem];
599
+ const yangin = yanginBranch ? branches.reduce((acc, b, i) => {
600
+ if (b === yanginBranch) acc.push(i);
601
+ return acc;
602
+ }, []) : [];
603
+ return {
604
+ yangin,
605
+ baekho: BAEKHO_PILLARS.has(dayPillar),
606
+ goegang: GOEGANG_PILLARS.has(dayPillar)
607
+ };
608
+ }
609
+ var IMPORTANT_RELATIONS = /* @__PURE__ */ new Set(["\u5408", "\u6C96", "\u5211"]);
610
+ function findTransits(natalPillars, months = 1, backward = false) {
611
+ const results = [];
612
+ const today = /* @__PURE__ */ new Date();
613
+ const msPerDay = 864e5;
614
+ const endDate = new Date(today.getTime() + (backward ? -1 : 1) * months * 30 * msPerDay);
615
+ let prevMonthPillar = null;
616
+ const current = new Date(today);
617
+ const step = backward ? -msPerDay : msPerDay;
618
+ while (backward ? current >= endDate : current <= endDate) {
619
+ const [yearP, monthP, dayP] = getFourPillars(
620
+ current.getFullYear(),
621
+ current.getMonth() + 1,
622
+ current.getDate(),
623
+ 12,
624
+ 0
625
+ );
626
+ if (monthP !== prevMonthPillar) {
627
+ if (prevMonthPillar !== null) {
628
+ for (let i = 0; i < natalPillars.length; i++) {
629
+ const rel = analyzePillarRelations(monthP, natalPillars[i]);
630
+ const allRels = [];
631
+ for (const r of rel.stem) {
632
+ if (IMPORTANT_RELATIONS.has(r.type)) allRels.push({ prefix: "\uCC9C\uAC04", relation: r });
633
+ }
634
+ for (const r of rel.branch) {
635
+ if (IMPORTANT_RELATIONS.has(r.type)) allRels.push({ prefix: "\uC9C0\uC9C0", relation: r });
636
+ }
637
+ if (allRels.length > 0) {
638
+ results.push({
639
+ date: new Date(current),
640
+ type: "\u6708\u904B",
641
+ transit: monthP,
642
+ natalName: PILLAR_NAMES[i],
643
+ relations: allRels
644
+ });
645
+ }
646
+ }
647
+ }
648
+ prevMonthPillar = monthP;
649
+ }
650
+ for (let i = 0; i < natalPillars.length; i++) {
651
+ const rel = analyzePillarRelations(dayP, natalPillars[i]);
652
+ const allRels = [];
653
+ for (const r of rel.stem) {
654
+ if (IMPORTANT_RELATIONS.has(r.type)) allRels.push({ prefix: "\uCC9C\uAC04", relation: r });
655
+ }
656
+ for (const r of rel.branch) {
657
+ if (IMPORTANT_RELATIONS.has(r.type)) allRels.push({ prefix: "\uC9C0\uC9C0", relation: r });
658
+ }
659
+ if (allRels.length > 0) {
660
+ results.push({
661
+ date: new Date(current),
662
+ type: "\u65E5\u904B",
663
+ transit: dayP,
664
+ natalName: PILLAR_NAMES[i],
665
+ relations: allRels
666
+ });
667
+ }
668
+ }
669
+ current.setTime(current.getTime() + step);
670
+ }
671
+ results.sort((a, b) => {
672
+ const timeDiff = a.date.getTime() - b.date.getTime();
673
+ if (timeDiff !== 0) return timeDiff;
674
+ return (a.type === "\u65E5\u904B" ? 1 : 0) - (b.type === "\u65E5\u904B" ? 1 : 0);
675
+ });
676
+ return results;
677
+ }
678
+
679
+ export {
680
+ calcPillarIndices,
681
+ calcSolarTerms,
682
+ getFourPillars,
683
+ getDaewoon,
684
+ getRelation,
685
+ getHiddenStems,
686
+ getJeonggi,
687
+ toHangul,
688
+ getTwelveMeteor,
689
+ getTwelveSpirit,
690
+ getStemRelation,
691
+ getBranchRelation,
692
+ analyzePillarRelations,
693
+ checkTripleCompose,
694
+ checkDirectionalCompose,
695
+ analyzeAllRelations,
696
+ getSpecialSals,
697
+ findTransits
698
+ };