eletrotupi / tcc / api/src/lib/queue/processors/insights/dailySleep.ts master
2.7 KB Raw
import { prisma } from "@app/lib/prisma";
import { InsightType, InsightPeriod } from "@prisma/client";
import { InsightPeriodPayload } from "@app/lib/queue/types";
// XXX: date-fns?
import { formatHours, formatDiff } from "@app/utils/calc";
import { startOfDay, addDays, subDays } from "date-fns";

export async function processDailySleep({
  userId,
  periodStart,
}: InsightPeriodPayload): Promise<void> {
  const today = startOfDay(new Date(periodStart));
  const tomorrow = addDays(today, 1);
  const yesterday = subDays(today, 1);

  const [todayRecords, yesterdayRecords] = await Promise.all([
    prisma.sleepRecord.findMany({
      where: { userId, date: { gte: today, lt: tomorrow } },
      select: { average: true },
    }),
    prisma.sleepRecord.findMany({
      where: { userId, date: { gte: yesterday, lt: today } },
      select: { average: true },
    }),
  ]);

  console.log("todayRecords, yesterdayRecords", todayRecords, yesterdayRecords);

  if (todayRecords.length === 0) return;

  // average is stored in hours
  // sum across all records for the day
  const totalToday = todayRecords.reduce(
    (sum: number, r: { average: number }) => sum + r.average,
    0,
  );
  const totalYesterday =
    yesterdayRecords.length > 0
      ? yesterdayRecords.reduce(
          (sum: number, r: { average: number }) => sum + r.average,
          0,
        )
      : null;

  const diffMinutes =
    totalYesterday !== null
      ? Math.round((totalToday - totalYesterday) * 60)
      : null;

  const sessionCount = todayRecords.length; // 1 = normal night, 2+ = nap(s)

  const diffStr =
    diffMinutes !== null && Math.abs(diffMinutes) >= 5
      ? `${formatDiff(diffMinutes)} que ontem`
      : "";

  const napStr =
    sessionCount > 1
      ? `incluindo ${sessionCount - 1} cochilo${sessionCount > 2 ? "s" : ""}`
      : "";

  await prisma.insight.upsert({
    where: {
      userId_type_periodStart: {
        userId,
        type: InsightType.DAILY_SLEEP,
        periodStart: today,
      },
    },
    update: {
      body: buildBody(totalToday),
      metadata: {
        totalHours: totalToday,
        diffMinutes,
        diffStr,
        sessionCount,
        napStr,
        hadNaps: sessionCount > 1,
      },
      generatedAt: new Date(),
    },
    create: {
      userId,
      type: InsightType.DAILY_SLEEP,
      period: InsightPeriod.DAILY,
      title: "Sono",
      body: buildBody(totalToday),
      metadata: {
        totalHours: totalToday,
        diffMinutes,
        sessionCount,
        diffStr,
        napStr,
        hadNaps: sessionCount > 1,
      },
      periodStart: today,
      periodEnd: tomorrow,
    },
  });
}

function buildBody(total: number): string {
  const totalStr = formatHours(total);

  return `${totalStr} de sono hoje`;
}