import { ADAPT as A } from './rules' const DAY = 86_400_000 export type Adapt = { value: number; day: number; firsts: string[] } /** 本地日序號(時區換算後的第幾天) */ export const dayNumber = (ms: number, tzOffsetMin: number) => Math.floor((ms + tzOffsetMin * 60_000) / DAY) export const initialAdapt = (now: number, tzOffsetMin: number): Adapt => ({ value: 0, day: dayNumber(now, tzOffsetMin), firsts: [] }) /** k = 1.5 + 1.5 × (主動度 + 想像力)/2,參數 0–100 */ export const growthRate = (initiative = 50, imagine = 50) => A.kBase + A.kSpan * ((initiative + imagine) / 200) /** 逐日成長 ΔA = k(1 − A/100),跨多日用閉式:A' = 100 − (100 − A)(1 − k/100)^n;只往前算、不寫回 */ export function grow(a: Adapt, now: number, tzOffsetMin: number, k: number): Adapt { const n = dayNumber(now, tzOffsetMin) - a.day if (n <= 0) return a return { ...a, day: a.day + n, value: 100 - (100 - a.value) * Math.pow(1 - k / 100, n) } } /** 本地「第一次」事件(例如第一次讀到天氣、新聞)另加 2;每種事件只算一次 */ export function markFirst(a: Adapt, kind: string): Adapt { if (a.firsts.includes(kind)) return a return { ...a, value: Math.min(100, a.value + A.first), firsts: [...a.firsts, kind] } } /** 想家基準:越不熟悉越想家 */ export const homesickBase = (value: number) => A.homesickMax * (1 - value / 100) /** 今天最多聊幾則本地新聞:適應度不夠不聊 */ export function newsQuota(value: number, cap: number): number { if (value < A.newsMin) return 0 return Math.min(cap, value >= A.newsTwo ? 2 : 1) } export function describeAdapt(value: number): string { if (value < 20) return '初來乍到' if (value < 40) return '慢慢熟悉' if (value < 60) return '逐漸適應' return value < 80 ? '相當熟悉' : '像本地人' }