import { dbMain } from "@core/drizzle"; import { eta as etaTable } from "@core/drizzle/main/schema"; import { eq } from "drizzle-orm"; import { MINUTE, HOUR, getClosetMilestone } from "@core/lib"; import { getLatestSnapshot, getClosestSnapshot } from "@core/db"; export const getGroundTruthMilestoneETA = async ( aid: number, targetViews?: number ): Promise => { const DELTA = 1e-5; let minETAHours = Infinity; const timeIntervals = [3 * MINUTE, 20 * MINUTE, HOUR, 3 * HOUR, 6 * HOUR, 72 * HOUR]; const currentTimestamp = new Date().getTime(); const latestSnapshot = await getLatestSnapshot(aid); const latestSnapshotTime = new Date(latestSnapshot.time).getTime(); for (const timeInterval of timeIntervals) { const date = new Date(currentTimestamp - timeInterval); const snapshot = await getClosestSnapshot(aid, date); if (!snapshot) continue; const currentSnapshotTime = new Date(snapshot.created_at).getTime(); const hoursDiff = (latestSnapshotTime - currentSnapshotTime) / HOUR; const viewsDiff = latestSnapshot.views - snapshot.views; if (viewsDiff <= 0) continue; const speed = viewsDiff / (hoursDiff + DELTA); const target = targetViews || getClosetMilestone(latestSnapshot.views); const viewsToIncrease = target - latestSnapshot.views; const eta = viewsToIncrease / (speed + DELTA); if (eta < minETAHours) { minETAHours = eta; } } return minETAHours; }; export const getMilestoneETA = async (aid: number) => { const data = await dbMain.select().from(etaTable).where(eq(etaTable.aid, aid)).limit(1); if (data.length > 0) { return data[0].eta; } return getGroundTruthMilestoneETA(aid); };