Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
async function fetchContributionData() {
try {
const response = await fetch('https://ejfox-allvals.web.val.run');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return processContributionData(data.vals);
} catch (error) {
console.error('Error fetching contribution data:', error);
throw error;
}
}
function processContributionData(vals) {
try {
const today = new Date();
const oneYearAgo = new Date(today.getFullYear() - 1, today.getMonth(), today.getDate());
const data = {};
// Initialize all days in the past year with 0 contributions
for (let d = new Date(oneYearAgo); d <= today; d.setDate(d.getDate() + 1)) {
data[d.toISOString().split('T')[0]] = 0;
}
// Count contributions for each day
vals.forEach(val => {
const date = new Date(val.createdAt).toISOString().split('T')[0];
if (date in data) {
data[date]++;
}
});
return data;
} catch (error) {
console.error('Error processing contribution data:', error);
throw error;
}
}
function getColorIntensity(count) {
if (count === 0) return '#ebedf0';
if (count < 5) return '#9be9a8';
if (count < 10) return '#40c463';
if (count < 15) return '#30a14e';
return '#216e39';
}
function drawContributionChart(ctx, contributionData, width, height) {
try {
const cellSize = 10;
const cellGap = 2;
const weekGap = 4;
const days = Object.keys(contributionData).sort();
const weeks = Math.ceil(days.length / 7);
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, width, height);
for (let week = 0; week < weeks; week++) {
for (let day = 0; day < 7; day++) {
const index = week * 7 + day;
if (index >= days.length) break;
const date = days[index];
const count = contributionData[date];
const x = week * (cellSize + weekGap);
const y = day * (cellSize + cellGap);
ctx.fillStyle = getColorIntensity(count);
ctx.fillRect(x, y, cellSize, cellSize);
}
}
} catch (error) {
console.error('Error drawing contribution chart:', error);
throw error;
}
}
async function server(request: Request): Promise<Response> {
try {
console.log('Fetching contribution data...');
const contributionData = await fetchContributionData();
console.log('Contribution data fetched successfully');
const width = 53 * (10 + 4) - 4; // 53 weeks * (10px cell + 4px gap) - 4px (no gap after last week)
const height = 7 * (10 + 2) - 2; // 7 days * (10px cell + 2px gap) - 2px (no gap after last day)
console.log('Creating canvas...');
const { createCanvas } = await import("https://deno.land/x/canvas/mod.ts");
const canvas = createCanvas(width, height);
if (!canvas) {
throw new Error('Failed to create canvas');
}
const ctx = canvas.getContext("2d");
if (!ctx) {
throw new Error('Failed to get 2D context from canvas');
}
ejfox-canvasvalcontributionchart.web.val.run
September 1, 2024