File size: 2,036 Bytes
22aa376
 
 
 
 
 
c798beb
 
22aa376
eda28cd
22aa376
 
eda28cd
22aa376
 
 
 
 
 
 
 
 
 
 
 
eda28cd
22aa376
eda28cd
 
 
22aa376
c798beb
22aa376
 
 
 
 
 
eda28cd
 
 
c798beb
22aa376
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
eda28cd
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
61
62
63
64
65
66
67
68
69
70
71
import {
  ModelData,
  ProviderInfo,
  CalendarData,
  Activity,
} from "../types/heatmap";

export const generateCalendarData = (
  modelData: ModelData[],
  providers: ProviderInfo[]
): CalendarData => {
  const data: Record<string, Activity[]> = Object.fromEntries(
    providers.map((provider) => [provider.authors[0], []]),
  );

  const today = new Date();
  const startDate = new Date(today);
  startDate.setMonth(today.getMonth() - 11);
  startDate.setDate(1);

  // create a map to store counts for each provider and date
  const countMap: Record<string, Record<string, number>> = {};

  modelData.forEach((item) => {
    const dateString = item.createdAt.split("T")[0];
    providers.forEach(({ authors }) => {
      if (authors.some((author) => item.id.startsWith(author))) {
        countMap[authors[0]] = countMap[authors[0]] || {};
        countMap[authors[0]][dateString] =
          (countMap[authors[0]][dateString] || 0) + 1;
      }
    });
  });

  // fill in with 0s for days with no activity
  for (let d = new Date(startDate); d <= today; d.setDate(d.getDate() + 1)) {
    const dateString = d.toISOString().split("T")[0];

    providers.forEach(({ authors }) => {
      const count = countMap[authors[0]]?.[dateString] || 0;
      data[authors[0]].push({ date: dateString, count, level: 0 });
    });
  }

  // calculate average counts for each provider
  const avgCounts = Object.fromEntries(
    Object.entries(data).map(([provider, days]) => [
      provider,
      days.reduce((sum, day) => sum + day.count, 0) / days.length || 0,
    ]),
  );

  // assign levels based on count relative to average
  Object.entries(data).forEach(([provider, days]) => {
    const avgCount = avgCounts[provider];
    days.forEach((day) => {
      day.level =
        day.count === 0
          ? 0
          : day.count <= avgCount * 0.5
            ? 1
            : day.count <= avgCount
              ? 2
              : day.count <= avgCount * 1.5
                ? 3
                : 4;
    });
  });

  return data;
};