import assert from "node:assert/strict"; import test from "node:test"; import { BIRTH_SKY_HEADLINES, birthSkyFactLine, birthSkyCaptionLine, birthSkyHeadline, octantName, } from "../src/lib/birth-sky/sentence.ts"; import type { BirthSkyOk } from "../src/lib/birth-sky/contract.ts"; import { birthSkyGolden, goldenSky } from "./birth-sky-test-support.ts"; test("the fictional sample (07:40) reads exactly as the brief", () => { const sky = goldenSky("day"); assert.equal(birthSkyGolden.times.day, "07:40"); assert.equal(birthSkyHeadline(sky), "星星都在,只是还看不见。"); assert.equal(birthSkyFactLine(sky), "太阳在东,月亮在脚下,火星正悬在东南"); }); test("each phase takes its one headline from the four-line table", () => { assert.deepEqual(Object.values(BIRTH_SKY_HEADLINES), [ "星星都在,只是还看不见。", "天快亮了,星星正一颗颗退场。", "天刚暗下来,星星正一颗颗出来。", "那一刻,头顶就是这片天。", ]); assert.equal(birthSkyHeadline(goldenSky("day")), BIRTH_SKY_HEADLINES.day); assert.equal(birthSkyHeadline(goldenSky("twilight_morning")), "天快亮了,星星正一颗颗退场。"); assert.equal(birthSkyHeadline(goldenSky("twilight_evening")), "天刚暗下来,星星正一颗颗出来。"); assert.equal(birthSkyHeadline(goldenSky("night")), "那一刻,头顶就是这片天。"); }); test("outside daytime the fact line never names the Sun", () => { for (const phase of ["twilight_morning", "twilight_evening", "night"] as const) { const line = birthSkyFactLine(goldenSky(phase)); assert.doesNotMatch(line, /太阳/); assert.match(line, /^月亮在(脚下|北|东北|东|东南|南|西南|西|西北)/); assert.ok(line.split(",").length <= 2, line); } }); test("fact line combinations: moon above, no visible planet, highest planet wins", () => { const base = goldenSky("night"); const planets = (overrides: Record): BirthSkyOk["planets"] => base.planets.map((planet) => { const next = overrides[planet.id]; return next ? { ...planet, altitude: next[0], azimuth: next[1] } : { ...planet, altitude: -10 }; }); assert.equal( birthSkyFactLine({ phase: "night", planets: planets({ moon: [40, 225], jupiter: [20, 10], venus: [35, 300] }) }), "月亮在西南,金星正悬在西北", ); assert.equal(birthSkyFactLine({ phase: "night", planets: planets({}) }), "月亮在脚下"); assert.equal( birthSkyFactLine({ phase: "day", planets: planets({ sun: [10, 225], saturn: [5, 170] }) }), "太阳在西南,月亮在脚下,土星正悬在南", ); }); test("eight-point compass rounds to the nearest 45 degrees, north at both ends", () => { assert.equal(octantName(0), "北"); assert.equal(octantName(22.4), "北"); assert.equal(octantName(22.6), "东北"); assert.equal(octantName(84.69), "东"); assert.equal(octantName(117.24), "东南"); assert.equal(octantName(191.14), "南"); assert.equal(octantName(350), "北"); }); // 原值: 「按你填写的时间」 footnote for a reported time, none for an adopted one. // 新值: the caption line; an adopted time appends 「 · 校正后」, a reported one adds nothing. // 原因: TASK-birth-sky-polish-20260928 P2 — the cover prints date, time and city in that line. test("the caption line appends 「· 校正后」 only for an adopted time", () => { const caption = "1994年5月18日 07:40 · 杭州"; assert.equal(birthSkyCaptionLine({ timeBasis: "reported", caption }), caption); assert.equal(birthSkyCaptionLine({ timeBasis: "adopted", caption }), "1994年5月18日 07:40 · 杭州 · 校正后"); });