eletrotupi / tcc/ api/src/lib/queue/processors/insights/dailySleep.ts7fee969bd7c3a184aabf448e27667c76b4e49617
2.8 KB | 110 lines Raw
1
import { prisma } from "@app/lib/prisma";
2
import { InsightType, InsightPeriod } from "@prisma/client";
3
import { InsightPeriodPayload } from "@app/lib/queue/types";
4
import { logger } from "@app/lib/logger";
5
// XXX: date-fns?
6
import { formatHours, formatDiff } from "@app/utils/calc";
7
import { startOfDay, addDays, subDays } from "date-fns";
8

9
export async function processDailySleep({
10
  userId,
11
  periodStart,
12
}: InsightPeriodPayload): Promise<void> {
13
  const today = startOfDay(new Date(periodStart));
14
  const tomorrow = addDays(today, 1);
15
  const yesterday = subDays(today, 1);
16

17
  const [todayRecords, yesterdayRecords] = await Promise.all([
18
    prisma.sleepRecord.findMany({
19
      where: { userId, date: { gte: today, lt: tomorrow } },
20
      select: { average: true },
21
    }),
22
    prisma.sleepRecord.findMany({
23
      where: { userId, date: { gte: yesterday, lt: today } },
24
      select: { average: true },
25
    }),
26
  ]);
27

28
  logger.debug(
29
    { todayRecords, yesterdayRecords },
30
    "[insights] daily sleep records",
31
  );
32

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

35
  // average is stored in hours
36
  // sum across all records for the day
37
  const totalToday = todayRecords.reduce(
38
    (sum: number, r: { average: number }) => sum + r.average,
39
    0,
40
  );
41
  const totalYesterday =
42
    yesterdayRecords.length > 0
43
      ? yesterdayRecords.reduce(
44
          (sum: number, r: { average: number }) => sum + r.average,
45
          0,
46
        )
47
      : null;
48

49
  const diffMinutes =
50
    totalYesterday !== null
51
      ? Math.round((totalToday - totalYesterday) * 60)
52
      : null;
53

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

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

61
  const napStr =
62
    sessionCount > 1
63
      ? `incluindo ${sessionCount - 1} cochilo${sessionCount > 2 ? "s" : ""}`
64
      : "";
65

66
  await prisma.insight.upsert({
67
    where: {
68
      userId_type_periodStart: {
69
        userId,
70
        type: InsightType.DAILY_SLEEP,
71
        periodStart: today,
72
      },
73
    },
74
    update: {
75
      body: buildBody(totalToday),
76
      metadata: {
77
        totalHours: totalToday,
78
        diffMinutes,
79
        diffStr,
80
        sessionCount,
81
        napStr,
82
        hadNaps: sessionCount > 1,
83
      },
84
      generatedAt: new Date(),
85
    },
86
    create: {
87
      userId,
88
      type: InsightType.DAILY_SLEEP,
89
      period: InsightPeriod.DAILY,
90
      title: "Sono",
91
      body: buildBody(totalToday),
92
      metadata: {
93
        totalHours: totalToday,
94
        diffMinutes,
95
        sessionCount,
96
        diffStr,
97
        napStr,
98
        hadNaps: sessionCount > 1,
99
      },
100
      periodStart: today,
101
      periodEnd: tomorrow,
102
    },
103
  });
104
}
105

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

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