import { parseAscendantSignature, type SegmentMinute, type AscendantSignature } from "../core/segment-summary.ts"; import { asRecord as record } from "@/lib/guards"; export function segmentCandidateFields(row: Record | null): { signature?: AscendantSignature; rawScore?: number } { const signature = parseAscendantSignature(row?.signature); const rawScore = row?.raw_score; return { ...(signature ? { signature } : {}), ...(typeof rawScore === "number" && Number.isFinite(rawScore) ? { rawScore } : {}), }; } /** The frozen engine returns scores/features separately from public decisions. */ export function candidateSegmentMetadata(data: Record): { byTime: ReadonlyMap; minutes: readonly SegmentMinute[]; } { const scores = new Map(); for (const item of Array.isArray(data.candidate_scores) ? data.candidate_scores : []) { const row = record(item); if (typeof row?.time === "string" && typeof row.score === "number" && Number.isFinite(row.score)) scores.set(row.time, row.score); } const snapshot = record(data.candidate_feature_snapshot); const byTime = new Map(); const minutes: SegmentMinute[] = []; for (const item of Array.isArray(snapshot?.features) ? snapshot.features : []) { const row = record(item); if (!row || typeof row.time !== "string") continue; const vargas = record(row.varga_ascendants); const signature = parseAscendantSignature({ D1: row.ascendant_sign_index, D9: vargas?.D9, D10: vargas?.D10 }); const rawScore = scores.get(row.time); byTime.set(row.time, { ...(signature ? { signature } : {}), ...(rawScore !== undefined ? { rawScore } : {}) }); if (signature) minutes.push({ offset: minutes.length * 2, time: row.time, signs: signature }); } return { byTime, minutes }; } export function parseSegmentMinutes(value: unknown): readonly SegmentMinute[] | null { if (!Array.isArray(value) || !value.length) return null; const minutes: SegmentMinute[] = []; for (const item of value) { const row = record(item); const signs = parseAscendantSignature(row?.signs); if (!row || typeof row.offset !== "number" || !Number.isInteger(row.offset) || typeof row.time !== "string" || !/^(?:[01]\d|2[0-3]):[0-5]\d$/.test(row.time) || !signs) return null; minutes.push({ offset: row.offset, time: row.time, signs, ...(typeof row.date === "string" && /^\d{4}-\d{2}-\d{2}$/.test(row.date) ? { date: row.date } : {}), }); } return minutes; }