File size: 2,201 Bytes
c798beb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { ModelData, ProviderInfo, CalendarData, Activity } from "../types/heatmap";

export const generateCalendarData = (
    modelData: ModelData[],
    providers: Record<string, ProviderInfo>,
  ): CalendarData => {
    const data: Record<string, Activity[]> = Object.fromEntries(
      Object.keys(providers).map((provider) => [provider, []]),
    );
  
    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];
      Object.entries(providers).forEach(([provider, { authors }]) => {
        if (authors.some((author) => item.id.startsWith(author))) {
          countMap[provider] = countMap[provider] || {};
          countMap[provider][dateString] =
            (countMap[provider][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];
  
      Object.entries(providers).forEach(([provider]) => {
        const count = countMap[provider]?.[dateString] || 0;
        data[provider].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;
  };