@gracefullight/saju 0.1.1 → 0.3.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.
Files changed (55) hide show
  1. package/README.en.md +314 -28
  2. package/README.md +314 -28
  3. package/dist/__tests__/four-pillars.test.js +52 -40
  4. package/dist/__tests__/luck.test.d.ts +2 -0
  5. package/dist/__tests__/luck.test.d.ts.map +1 -0
  6. package/dist/__tests__/luck.test.js +33 -0
  7. package/dist/__tests__/lunar.test.d.ts +2 -0
  8. package/dist/__tests__/lunar.test.d.ts.map +1 -0
  9. package/dist/__tests__/lunar.test.js +83 -0
  10. package/dist/__tests__/relations.test.d.ts +2 -0
  11. package/dist/__tests__/relations.test.d.ts.map +1 -0
  12. package/dist/__tests__/relations.test.js +90 -0
  13. package/dist/__tests__/saju.test.d.ts +2 -0
  14. package/dist/__tests__/saju.test.d.ts.map +1 -0
  15. package/dist/__tests__/saju.test.js +133 -0
  16. package/dist/__tests__/solar-terms.test.d.ts +2 -0
  17. package/dist/__tests__/solar-terms.test.d.ts.map +1 -0
  18. package/dist/__tests__/solar-terms.test.js +121 -0
  19. package/dist/__tests__/strength.test.d.ts +2 -0
  20. package/dist/__tests__/strength.test.d.ts.map +1 -0
  21. package/dist/__tests__/strength.test.js +44 -0
  22. package/dist/__tests__/ten-gods.test.d.ts +2 -0
  23. package/dist/__tests__/ten-gods.test.d.ts.map +1 -0
  24. package/dist/__tests__/ten-gods.test.js +119 -0
  25. package/dist/__tests__/yongshen.test.d.ts +2 -0
  26. package/dist/__tests__/yongshen.test.d.ts.map +1 -0
  27. package/dist/__tests__/yongshen.test.js +62 -0
  28. package/dist/core/four-pillars.d.ts +2 -0
  29. package/dist/core/four-pillars.d.ts.map +1 -1
  30. package/dist/core/four-pillars.js +7 -4
  31. package/dist/core/luck.d.ts +41 -0
  32. package/dist/core/luck.d.ts.map +1 -0
  33. package/dist/core/luck.js +96 -0
  34. package/dist/core/lunar.d.ts +13 -0
  35. package/dist/core/lunar.d.ts.map +1 -0
  36. package/dist/core/lunar.js +24 -0
  37. package/dist/core/relations.d.ts +94 -0
  38. package/dist/core/relations.d.ts.map +1 -0
  39. package/dist/core/relations.js +305 -0
  40. package/dist/core/solar-terms.d.ts +155 -0
  41. package/dist/core/solar-terms.d.ts.map +1 -0
  42. package/dist/core/solar-terms.js +266 -0
  43. package/dist/core/strength.d.ts +18 -0
  44. package/dist/core/strength.d.ts.map +1 -0
  45. package/dist/core/strength.js +255 -0
  46. package/dist/core/ten-gods.d.ts +130 -0
  47. package/dist/core/ten-gods.d.ts.map +1 -0
  48. package/dist/core/ten-gods.js +335 -0
  49. package/dist/core/yongshen.d.ts +20 -0
  50. package/dist/core/yongshen.d.ts.map +1 -0
  51. package/dist/core/yongshen.js +216 -0
  52. package/dist/index.d.ts +54 -0
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +48 -0
  55. package/package.json +15 -12
@@ -0,0 +1,62 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { analyzeYongShen, getElementRecommendations } from "@/core/yongshen";
3
+ describe("yongshen", () => {
4
+ describe("analyzeYongShen", () => {
5
+ it("returns yongshen analysis result", () => {
6
+ const result = analyzeYongShen("甲子", "丙寅", "甲辰", "乙亥");
7
+ expect(result.primary).toBeDefined();
8
+ expect(result.method).toBeDefined();
9
+ expect(result.reasoning).toBeDefined();
10
+ expect(result.allElements).toBeDefined();
11
+ });
12
+ it("identifies yongshen elements correctly", () => {
13
+ const result = analyzeYongShen("甲子", "丙寅", "甲辰", "乙亥");
14
+ expect(result.allElements[result.primary].isYongShen).toBe(true);
15
+ });
16
+ it("identifies kishen elements correctly", () => {
17
+ const result = analyzeYongShen("甲子", "丙寅", "甲辰", "乙亥");
18
+ const hasKiShen = Object.values(result.allElements).some((e) => e.isKiShen);
19
+ expect(hasKiShen).toBe(true);
20
+ });
21
+ it("uses 억부 method for 중화 strength (조후 is adjustment, not primary)", () => {
22
+ const result = analyzeYongShen("甲子", "丙寅", "庚申", "丁亥");
23
+ expect(["억부", "격국"]).toContain(result.method);
24
+ });
25
+ it("uses 억부 method for extreme strength", () => {
26
+ const result = analyzeYongShen("甲寅", "甲寅", "甲寅", "甲寅");
27
+ expect(result.method).toBe("억부");
28
+ });
29
+ it("includes johuAdjustment field in result", () => {
30
+ const result = analyzeYongShen("甲子", "丙寅", "甲辰", "乙亥");
31
+ expect("johuAdjustment" in result).toBe(true);
32
+ });
33
+ it("includes reasoning in result", () => {
34
+ const result = analyzeYongShen("甲子", "丙寅", "甲辰", "乙亥");
35
+ expect(result.reasoning.length).toBeGreaterThan(0);
36
+ });
37
+ });
38
+ describe("getElementRecommendations", () => {
39
+ it("returns colors for yongshen element", () => {
40
+ const yongShen = analyzeYongShen("甲子", "丙寅", "甲辰", "乙亥");
41
+ const recommendations = getElementRecommendations(yongShen);
42
+ expect(recommendations.colors.length).toBeGreaterThan(0);
43
+ });
44
+ it("returns directions for yongshen element", () => {
45
+ const yongShen = analyzeYongShen("甲子", "丙寅", "甲辰", "乙亥");
46
+ const recommendations = getElementRecommendations(yongShen);
47
+ expect(recommendations.directions.length).toBeGreaterThan(0);
48
+ });
49
+ it("returns numbers for yongshen element", () => {
50
+ const yongShen = analyzeYongShen("甲子", "丙寅", "甲辰", "乙亥");
51
+ const recommendations = getElementRecommendations(yongShen);
52
+ expect(recommendations.numbers.length).toBeGreaterThan(0);
53
+ });
54
+ it("includes secondary element recommendations when present", () => {
55
+ const yongShen = analyzeYongShen("甲子", "丙寅", "甲辰", "乙亥");
56
+ if (yongShen.secondary) {
57
+ const recommendations = getElementRecommendations(yongShen);
58
+ expect(recommendations.colors.length).toBeGreaterThan(2);
59
+ }
60
+ });
61
+ });
62
+ });
@@ -1,4 +1,5 @@
1
1
  import type { DateAdapter } from "@/adapters/date-adapter";
2
+ import { type LunarDate } from "@/core/lunar";
2
3
  export declare const STEMS: string[];
3
4
  export declare const BRANCHES: string[];
4
5
  export declare const STANDARD_PRESET: {
@@ -73,6 +74,7 @@ export declare function getFourPillars<T>(adapter: DateAdapter<T>, dtLocal: T, {
73
74
  month: string;
74
75
  day: string;
75
76
  hour: string;
77
+ lunar: LunarDate;
76
78
  meta: {
77
79
  solarYearUsed: number;
78
80
  sunLonDeg: number;
@@ -1 +1 @@
1
- {"version":3,"file":"four-pillars.d.ts","sourceRoot":"","sources":["../../src/core/four-pillars.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,eAAO,MAAM,KAAK,UAAqD,CAAC;AACxE,eAAO,MAAM,QAAQ,UAA+D,CAAC;AAErF,eAAO,MAAM,eAAe;;;;CAI3B,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;;CAI9B,CAAC;AAEF,eAAO,MAAM,OAAO;;;;CAAkB,CAAC;AACvC,eAAO,MAAM,OAAO;;;;CAAqB,CAAC;AA0B1C,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,KAAK,EACL,GAAG,GACJ,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,GAAG;IACF,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAIA;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,OAAO,EAAE,CAAC,EACV,YAAY,EAAE,MAAM,EACpB,aAAa,SAAI,GAChB,CAAC,CAGH;AAiFD,wBAAgB,UAAU,CAAC,CAAC,EAC1B,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,OAAO,EAAE,CAAC,GACT;IACD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAOA;AAsBD,wBAAgB,WAAW,CAAC,CAAC,EAC3B,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,OAAO,EAAE,CAAC,GACT;IACD,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAWA;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,OAAO,EAAE,CAAC,EACV,EACE,WAAwB,EACxB,YAAY,EACZ,aAAiB,EACjB,2BAAmC,GACpC,GAAE;IACD,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2BAA2B,CAAC,EAAE,OAAO,CAAC;CAClC,GACL;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAgB9C;AAWD,wBAAgB,UAAU,CAAC,CAAC,EAC1B,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,OAAO,EAAE,CAAC,EACV,EACE,YAAY,EACZ,aAAiB,EACjB,uBAA+B,EAC/B,WAAwB,EACxB,2BAAmC,GACpC,GAAE;IACD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAClC,2BAA2B,CAAC,EAAE,OAAO,CAAC;CAClC,GACL;IACD,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,CAAC,CAAC;IACd,aAAa,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D,CAsBA;AAED,wBAAgB,cAAc,CAAC,CAAC,EAC9B,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,OAAO,EAAE,CAAC,EACV,EACE,YAAY,EACZ,aAAiB,EACjB,MAAgB,GACjB,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,OAAO,GAAG,OAAO,OAAO,CAAC;CAC1C,GACA;IACD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE;QACJ,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,gBAAgB,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/D,iBAAiB,EAAE,MAAM,CAAC;QAC1B,MAAM,EAAE,OAAO,MAAM,CAAC;KACvB,CAAC;CACH,CAuCA"}
1
+ {"version":3,"file":"four-pillars.d.ts","sourceRoot":"","sources":["../../src/core/four-pillars.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { getLunarDate } from "@/core/lunar";
1
2
  export const STEMS = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"];
2
3
  export const BRANCHES = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"];
3
4
  export const STANDARD_PRESET = {
@@ -33,7 +34,7 @@ function jdnFromDate(y, m, d) {
33
34
  }
34
35
  export function dayPillarFromDate({ year, month, day, }) {
35
36
  const jdn = jdnFromDate(year, month, day);
36
- const idx60 = (jdn + 12) % 60;
37
+ const idx60 = (((jdn - 11) % 60) + 60) % 60;
37
38
  return { idx60, pillar: pillarFrom60(idx60) };
38
39
  }
39
40
  export function applyMeanSolarTime(adapter, dtLocal, longitudeDeg, tzOffsetHours = 9) {
@@ -160,9 +161,9 @@ function hourBranchIndexFromHour(h) {
160
161
  // Traditional Chinese hours (時辰) mapping:
161
162
  // Each branch represents a 2-hour period, starting from 子時 at 23:00
162
163
  // 子時 (0): 23:00-01:00, 丑時 (1): 01:00-03:00, ..., 亥時 (11): 21:00-23:00
163
- // Formula: (hour + 1) / 2 gives the branch index, but we need +1 offset
164
- // because 23:00 (hour 23) should map to index 0 (子), wrapping around
165
- return Math.floor((h + 1) / 2 + 1) % 12;
164
+ // Formula: floor((hour + 1) / 2) % 12
165
+ // Examples: 0->0(子), 1->1(丑), 3->2(寅), 23->0(子)
166
+ return Math.floor((h + 1) / 2) % 12;
166
167
  }
167
168
  export function hourPillar(adapter, dtLocal, { longitudeDeg, tzOffsetHours = 9, useMeanSolarTimeForHour = false, dayBoundary = "midnight", useMeanSolarTimeForBoundary = false, } = {}) {
168
169
  let dtUsed = dtLocal;
@@ -205,11 +206,13 @@ export function getFourPillars(adapter, dtLocal, { longitudeDeg, tzOffsetHours =
205
206
  dayBoundary,
206
207
  useMeanSolarTimeForBoundary,
207
208
  });
209
+ const lunar = getLunarDate(effDate.year, effDate.month, effDate.day);
208
210
  return {
209
211
  year: y.pillar,
210
212
  month: m.pillar,
211
213
  day: d.pillar,
212
214
  hour: h.pillar,
215
+ lunar,
213
216
  meta: {
214
217
  solarYearUsed: y.solarYear,
215
218
  sunLonDeg: m.sunLonDeg,
@@ -0,0 +1,41 @@
1
+ import type { DateAdapter } from "@/adapters/date-adapter";
2
+ import { type Polarity } from "./ten-gods";
3
+ export type Gender = "male" | "female";
4
+ export interface LuckPillar {
5
+ index: number;
6
+ startAge: number;
7
+ endAge: number;
8
+ stem: string;
9
+ branch: string;
10
+ pillar: string;
11
+ }
12
+ export interface StartAgeDetail {
13
+ years: number;
14
+ months: number;
15
+ days: number;
16
+ }
17
+ export interface MajorLuckResult {
18
+ gender: Gender;
19
+ yearStemPolarity: Polarity;
20
+ isForward: boolean;
21
+ startAge: number;
22
+ startAgeDetail: StartAgeDetail;
23
+ daysToTerm: number;
24
+ pillars: LuckPillar[];
25
+ }
26
+ export declare function calculateMajorLuck<T>(adapter: DateAdapter<T>, birthDateTime: T, gender: Gender, yearPillar: string, monthPillar: string, options?: {
27
+ count?: number;
28
+ nextJieMillis?: number;
29
+ prevJieMillis?: number;
30
+ }): MajorLuckResult;
31
+ export interface YearlyLuckResult {
32
+ year: number;
33
+ stem: string;
34
+ branch: string;
35
+ pillar: string;
36
+ age: number;
37
+ }
38
+ export declare function calculateYearlyLuck(birthYear: number, fromYear: number, toYear: number): YearlyLuckResult[];
39
+ export declare function getYearPillar(year: number): string;
40
+ export declare function getCurrentMajorLuck(majorLuck: MajorLuckResult, age: number): LuckPillar | null;
41
+ //# sourceMappingURL=luck.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"luck.d.ts","sourceRoot":"","sources":["../../src/core/luck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEvC,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,QAAQ,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAqBD,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,aAAa,EAAE,CAAC,EAChB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;IACP,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACnB,GACL,eAAe,CA2DjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,gBAAgB,EAAE,CAkBpB;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAO9F"}
@@ -0,0 +1,96 @@
1
+ import { STEMS, BRANCHES } from "./four-pillars";
2
+ import { getStemPolarity } from "./ten-gods";
3
+ function getMonthPillarIndex(monthPillar) {
4
+ const stem = monthPillar[0];
5
+ const branch = monthPillar[1];
6
+ const stemIdx = STEMS.indexOf(stem);
7
+ const branchIdx = BRANCHES.indexOf(branch);
8
+ for (let i = 0; i < 60; i++) {
9
+ if (i % 10 === stemIdx && i % 12 === branchIdx) {
10
+ return i;
11
+ }
12
+ }
13
+ return 0;
14
+ }
15
+ function pillarFromIndex(idx60) {
16
+ const normalized = ((idx60 % 60) + 60) % 60;
17
+ return STEMS[normalized % 10] + BRANCHES[normalized % 12];
18
+ }
19
+ export function calculateMajorLuck(adapter, birthDateTime, gender, yearPillar, monthPillar, options = {}) {
20
+ const { count = 8 } = options;
21
+ const yearStem = yearPillar[0];
22
+ const yearStemPolarity = getStemPolarity(yearStem);
23
+ const isForward = (yearStemPolarity === "yang" && gender === "male") ||
24
+ (yearStemPolarity === "yin" && gender === "female");
25
+ const birthMillis = adapter.toMillis(birthDateTime);
26
+ const msPerDay = 1000 * 60 * 60 * 24;
27
+ let daysToTerm;
28
+ if (options.nextJieMillis !== undefined && options.prevJieMillis !== undefined) {
29
+ if (isForward) {
30
+ daysToTerm = Math.abs(options.nextJieMillis - birthMillis) / msPerDay;
31
+ }
32
+ else {
33
+ daysToTerm = Math.abs(birthMillis - options.prevJieMillis) / msPerDay;
34
+ }
35
+ }
36
+ else {
37
+ daysToTerm = 30;
38
+ }
39
+ const totalMonths = Math.round((daysToTerm / 3) * 12);
40
+ const years = Math.floor(totalMonths / 12);
41
+ const months = totalMonths % 12;
42
+ const days = Math.round(((daysToTerm / 3) * 12 - totalMonths) * 30);
43
+ const startAge = years;
44
+ const startAgeDetail = { years, months, days: Math.abs(days) };
45
+ const monthIdx60 = getMonthPillarIndex(monthPillar);
46
+ const pillars = [];
47
+ for (let i = 1; i <= count; i++) {
48
+ const pillarIdx = isForward ? monthIdx60 + i : monthIdx60 - i;
49
+ const pillar = pillarFromIndex(pillarIdx);
50
+ pillars.push({
51
+ index: i,
52
+ startAge: startAge + (i - 1) * 10,
53
+ endAge: startAge + i * 10 - 1,
54
+ stem: pillar[0],
55
+ branch: pillar[1],
56
+ pillar,
57
+ });
58
+ }
59
+ return {
60
+ gender,
61
+ yearStemPolarity,
62
+ isForward,
63
+ startAge,
64
+ startAgeDetail,
65
+ daysToTerm: Math.round(daysToTerm * 10) / 10,
66
+ pillars,
67
+ };
68
+ }
69
+ export function calculateYearlyLuck(birthYear, fromYear, toYear) {
70
+ const results = [];
71
+ for (let year = fromYear; year <= toYear; year++) {
72
+ const idx60 = (((year - 1984) % 60) + 60) % 60;
73
+ const pillar = pillarFromIndex(idx60);
74
+ const age = year - birthYear + 1;
75
+ results.push({
76
+ year,
77
+ stem: pillar[0],
78
+ branch: pillar[1],
79
+ pillar,
80
+ age,
81
+ });
82
+ }
83
+ return results;
84
+ }
85
+ export function getYearPillar(year) {
86
+ const idx60 = (((year - 1984) % 60) + 60) % 60;
87
+ return pillarFromIndex(idx60);
88
+ }
89
+ export function getCurrentMajorLuck(majorLuck, age) {
90
+ for (const pillar of majorLuck.pillars) {
91
+ if (age >= pillar.startAge && age <= pillar.endAge) {
92
+ return pillar;
93
+ }
94
+ }
95
+ return null;
96
+ }
@@ -0,0 +1,13 @@
1
+ export interface LunarDate {
2
+ lunarYear: number;
3
+ lunarMonth: number;
4
+ lunarDay: number;
5
+ isLeapMonth: boolean;
6
+ }
7
+ export declare function getLunarDate(year: number, month: number, day: number): LunarDate;
8
+ export declare function getSolarDate(lunarYear: number, lunarMonth: number, lunarDay: number, isLeapMonth?: boolean): {
9
+ year: number;
10
+ month: number;
11
+ day: number;
12
+ };
13
+ //# sourceMappingURL=lunar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lunar.d.ts","sourceRoot":"","sources":["../../src/core/lunar.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAYhF;AAED,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,WAAW,UAAQ,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAW9C"}
@@ -0,0 +1,24 @@
1
+ import { Lunar, Solar } from "lunar-javascript";
2
+ export function getLunarDate(year, month, day) {
3
+ const solar = Solar.fromYmd(year, month, day);
4
+ const lunar = solar.getLunar();
5
+ const rawMonth = lunar.getMonth();
6
+ const isLeapMonth = rawMonth < 0;
7
+ return {
8
+ lunarYear: lunar.getYear(),
9
+ lunarMonth: isLeapMonth ? Math.abs(rawMonth) : rawMonth,
10
+ lunarDay: lunar.getDay(),
11
+ isLeapMonth,
12
+ };
13
+ }
14
+ export function getSolarDate(lunarYear, lunarMonth, lunarDay, isLeapMonth = false) {
15
+ // lunar-javascript uses negative month for leap months
16
+ const month = isLeapMonth ? -lunarMonth : lunarMonth;
17
+ const lunar = Lunar.fromYmd(lunarYear, month, lunarDay);
18
+ const solar = lunar.getSolar();
19
+ return {
20
+ year: solar.getYear(),
21
+ month: solar.getMonth(),
22
+ day: solar.getDay(),
23
+ };
24
+ }
@@ -0,0 +1,94 @@
1
+ import type { Element } from "./ten-gods";
2
+ export type TransformationStatus = "합" | "반합" | "화" | "불화";
3
+ export type StemCombinationResult = {
4
+ stems: [string, string];
5
+ resultElement: Element;
6
+ };
7
+ export declare const STEM_COMBINATIONS: StemCombinationResult[];
8
+ export type BranchCombinationResult = {
9
+ branches: [string, string];
10
+ resultElement: Element;
11
+ };
12
+ export declare const BRANCH_SIX_COMBINATIONS: BranchCombinationResult[];
13
+ export type TripleCombinationResult = {
14
+ branches: [string, string, string];
15
+ resultElement: Element;
16
+ };
17
+ export declare const BRANCH_TRIPLE_COMBINATIONS: TripleCombinationResult[];
18
+ export declare const BRANCH_DIRECTIONAL_COMBINATIONS: TripleCombinationResult[];
19
+ export declare const BRANCH_CLASHES: [string, string][];
20
+ export declare const BRANCH_HARMS: [string, string][];
21
+ export declare const BRANCH_PUNISHMENTS: {
22
+ branches: string[];
23
+ type: string;
24
+ }[];
25
+ export declare const BRANCH_DESTRUCTIONS: [string, string][];
26
+ export interface StemCombination {
27
+ type: "천간합";
28
+ pair: [string, string];
29
+ positions: [string, string];
30
+ resultElement: Element;
31
+ transformStatus: TransformationStatus;
32
+ transformReason: string;
33
+ }
34
+ export interface BranchSixCombination {
35
+ type: "육합";
36
+ pair: [string, string];
37
+ positions: [string, string];
38
+ resultElement: Element;
39
+ transformStatus: TransformationStatus;
40
+ transformReason: string;
41
+ }
42
+ export interface BranchTripleCombination {
43
+ type: "삼합";
44
+ branches: string[];
45
+ positions: string[];
46
+ resultElement: Element;
47
+ isComplete: boolean;
48
+ transformStatus: TransformationStatus;
49
+ transformReason: string;
50
+ }
51
+ export interface BranchDirectionalCombination {
52
+ type: "방합";
53
+ branches: string[];
54
+ positions: string[];
55
+ resultElement: Element;
56
+ isComplete: boolean;
57
+ transformStatus: TransformationStatus;
58
+ transformReason: string;
59
+ }
60
+ export interface BranchClash {
61
+ type: "충";
62
+ pair: [string, string];
63
+ positions: [string, string];
64
+ }
65
+ export interface BranchHarm {
66
+ type: "해";
67
+ pair: [string, string];
68
+ positions: [string, string];
69
+ }
70
+ export interface BranchPunishment {
71
+ type: "형";
72
+ branches: string[];
73
+ positions: string[];
74
+ punishmentType: string;
75
+ }
76
+ export interface BranchDestruction {
77
+ type: "파";
78
+ pair: [string, string];
79
+ positions: [string, string];
80
+ }
81
+ export type Relation = StemCombination | BranchSixCombination | BranchTripleCombination | BranchDirectionalCombination | BranchClash | BranchHarm | BranchPunishment | BranchDestruction;
82
+ export interface RelationsResult {
83
+ combinations: (StemCombination | BranchSixCombination | BranchTripleCombination | BranchDirectionalCombination)[];
84
+ clashes: BranchClash[];
85
+ harms: BranchHarm[];
86
+ punishments: BranchPunishment[];
87
+ destructions: BranchDestruction[];
88
+ all: Relation[];
89
+ }
90
+ export declare function analyzeRelations(yearPillar: string, monthPillar: string, dayPillar: string, hourPillar: string): RelationsResult;
91
+ export declare function findStemCombination(stem1: string, stem2: string): StemCombinationResult | null;
92
+ export declare function findBranchClash(branch1: string, branch2: string): boolean;
93
+ export declare function findBranchSixCombination(branch1: string, branch2: string): BranchCombinationResult | null;
94
+ //# sourceMappingURL=relations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relations.d.ts","sourceRoot":"","sources":["../../src/core/relations.ts"],"names":[],"mappings":"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"}