Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | // lib/evolution/timeline.align.ts import { readEvolutionHistory } from './history.collector'; import { appendHistory } from './history.collector'; /** * Timeline Alignment Layer * ------------------------ * 1. يوحّد timestamps إلى وحدة زمنية ثابتة (day أو hour) * 2. يحسب التغيّر النسبي بين القيم المتتابعة * 3. يضيف مؤشر الاتجاه trendDirection (+, -, stable) */ export type AlignedPoint = { t: string; deltaStability?: number; deltaAdaptation?: number; trend?: 'up' | 'down' | 'stable'; stability?: number; adaptationRate?: number; }; export function alignEvolutionTimeline(mode: 'daily' | 'hourly' = 'daily'): AlignedPoint[] { const history = readEvolutionHistory(); if (!Array.isArray(history) || history.length === 0) return []; // ✅ Group by day/hour const groupKey = (iso: string) => { const d = new Date(iso); return mode === 'hourly' ? d.toISOString().slice(0, 13) // YYYY-MM-DDTHH : d.toISOString().slice(0, 10); // YYYY-MM-DD }; const grouped: Record<string, any[]> = {}; history.forEach((s) => { const key = groupKey(s.ts); grouped[key] = grouped[key] || []; grouped[key].push(s); }); // ✅ Average metrics per group const aligned: AlignedPoint[] = Object.entries(grouped).map(([k, arr]) => { const mean = (key: string) => arr.reduce((a, b) => a + (b.metrics?.[key] ?? 0), 0) / arr.length; const stability = mean('stability') || 0; const adaptationRate = mean('adaptationRate') || 0; return { t: k, stability, adaptationRate }; }); // ✅ Compute deltas and trends for (let i = 1; i < aligned.length; i++) { const prev = aligned[i - 1]; const cur = aligned[i]; cur.deltaStability = cur.stability - (prev.stability ?? 0); cur.deltaAdaptation = cur.adaptationRate - (prev.adaptationRate ?? 0); const avgDelta = (cur.deltaStability + cur.deltaAdaptation) / 2; cur.trend = avgDelta > 0.001 ? 'up' : avgDelta < -0.001 ? 'down' : 'stable'; } return aligned; } |