-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathcalendar.cpp
More file actions
243 lines (203 loc) · 9.9 KB
/
Copy pathcalendar.cpp
File metadata and controls
243 lines (203 loc) · 9.9 KB
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#include "calendar.h"
#include <raylib.h>
#include <iostream>
#include <iomanip>
#include <ctime>
#include <string>
#include <cstdio>
using namespace std;
// GitHub Dark-Mode Contribution Color Palette Definitions
#define COLOR_EMPTY (Color){ 22, 27, 34, 255 } // Dark Gray Empty Node
#define COLOR_ACTIVE_BASE (Color){ 57, 211, 83, 255 } // Base green — alpha scales with completion count
#define CELL_SIZE 26 // Box dimension width and height (enlarged)
#define CELL_PADDING 6 // Spacing between the heatmap boxes (enlarged)
// Intensity scaling for the heatmap: how many completions = fully opaque,
// and the alpha range used to represent "a little" vs "a lot" of activity.
#define MAX_INTENSITY_CAP 5
#define ALPHA_MIN 60
#define ALPHA_MAX 255
// LEAP YEAR CHECK
bool isLeapYear(int year) {
return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
}
// DAYS IN MONTH CALCULATOR
int getDaysInMonth(int month, int year) {
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month == 2 && isLeapYear(year)) return 29;
return days[month - 1];
}
// MONTH STRING UTILITY
string getMonthName(int month) {
string m[] = {"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"};
return m[month - 1];
}
// START DAY DAY-OF-WEEK CALCULATOR
int getStartDay(int month, int year) {
tm time_in = {0};
time_in.tm_year = year - 1900;
time_in.tm_mon = month - 1;
time_in.tm_mday = 1;
mktime(&time_in);
return time_in.tm_wday; // 0 = Sunday, 1 = Monday ...
}
// LEGACY BOOLEAN CHECKER
bool hasTaskOnDate(int day, int month, int year) {
for (const auto &t : allTasks) {
if (t.dueDay == day && t.dueMonth == month && t.dueYear == year) {
return true;
}
}
return false;
}
// UTILITY TO FETCH TOTAL COMPLETED TASKS FOR A GIVEN DATE
// Keys off dateCompleted (the day the task was actually finished), not the
// due date — a task completed today should light up today, not on whatever
// day it happened to be due.
int getCompletedTaskCount(int day, int month, int year) {
int count = 0;
for (const auto &t : allTasks) {
if (!t.isCompleted || t.dateCompleted.empty()) continue;
int cy = 0, cm = 0, cd = 0;
sscanf(t.dateCompleted.c_str(), "%d-%d-%d", &cy, &cm, &cd);
if (cd == day && cm == month && cy == year) count++;
}
return count;
}
// GITHUB HEATMAP RAYLIB RENDERER BLOCK
void DrawGitHubHeatmap(int startX, int startY, int currentMonth, int currentYear) {
int totalDays = getDaysInMonth(currentMonth, currentYear);
int startOffsetWeekday = getStartDay(currentMonth, currentYear);
// Title text
DrawText("Task Completion Activity Matrix", startX, startY - 28, 18, WHITE);
// Days of the week row-labels helper (S M T W T F S)
const char* daysOfWeek[] = {"S", "M", "T", "W", "T", "F", "S"};
for (int i = 0; i < 7; i++) {
int labelY = startY + (i * (CELL_SIZE + CELL_PADDING)) + 2;
DrawText(daysOfWeek[i], startX - 25, labelY, 12, GRAY);
}
// Process every single valid day of the calendar month inside the contribution array grid
for (int d = 1; d <= totalDays; d++) {
int targetCellIndex = startOffsetWeekday + (d - 1);
int row = targetCellIndex % 7; // Map into vertical Day of Week row position
int col = targetCellIndex / 7; // Map into horizontal Week Number column position
// Determine activity metrics count
int completedAmount = getCompletedTaskCount(d, currentMonth, currentYear);
// No completions -> empty dark cell. Otherwise, keep the same green
// hue for every day but scale its transparency (alpha) with how many
// tasks were completed — a light wash for 1 task, fully solid once
// completions reach MAX_INTENSITY_CAP. No yellow/amber is ever used
// for pending tasks; this heatmap only reflects completions.
Color cellColor = COLOR_EMPTY;
if (completedAmount > 0) {
int capped = completedAmount > MAX_INTENSITY_CAP ? MAX_INTENSITY_CAP : completedAmount;
unsigned char alpha = (unsigned char)(ALPHA_MIN +
((ALPHA_MAX - ALPHA_MIN) * (capped - 1)) / (MAX_INTENSITY_CAP - 1));
cellColor = COLOR_ACTIVE_BASE;
cellColor.a = alpha;
}
// Calculate layout screen space metrics
float posX = startX + (col * (CELL_SIZE + CELL_PADDING));
float posY = startY + (row * (CELL_SIZE + CELL_PADDING));
Rectangle cellRect = { posX, posY, (float)CELL_SIZE, (float)CELL_SIZE };
// Draw node item using roundness vector parameters to duplicate Github visual engine style
DrawRectangleRounded(cellRect, 0.25f, 4, cellColor);
// Draw inner tracking indicator digits inside active boxes
char dayStr[4];
snprintf(dayStr, sizeof(dayStr), "%d", d);
int textWidth = MeasureText(dayStr, 10);
DrawText(dayStr, posX + (CELL_SIZE - textWidth)/2, posY + 7, 10, (completedAmount >= 3) ? BLACK : LIGHTGRAY);
}
// Base UI Palette Indicator Legend Container — same green hue throughout,
// increasing opacity from left (empty / low activity) to right (high activity).
int legendX = startX;
int legendY = startY + (7 * (CELL_SIZE + CELL_PADDING)) + 20;
DrawText("Less", legendX, legendY, 13, GRAY);
for (int i = 0; i < 5; i++) {
Color legColor;
if (i == 0) {
legColor = COLOR_EMPTY;
} else {
unsigned char a = (unsigned char)(ALPHA_MIN + ((ALPHA_MAX - ALPHA_MIN) * i) / 4);
legColor = COLOR_ACTIVE_BASE;
legColor.a = a;
}
Rectangle legRect = { (float)(legendX + 45 + (i * 24)), (float)legendY - 2, 16, 16 };
DrawRectangleRounded(legRect, 0.25f, 4, legColor);
}
DrawText("More", legendX + 175, legendY, 13, GRAY);
}
// MAIN GRAPHICAL CALENDAR RUNTIME ENVIRONMENT
void displayCalendar() {
// Acquire current date from local hardware system clock configurations
time_t now = time(0);
tm *ltm = localtime(&now);
int currentYear = ltm->tm_year + 1900;
int currentMonth = ltm->tm_mon + 1;
int today = ltm->tm_mday;
// Window Setup configuration routines
const int winWidth = 900;
const int winHeight = 650;
// Mute annoying Raylib debug initialization terminal traces
SetTraceLogLevel(LOG_NONE);
// Avoid double-initializing if window structure is already alive in main login modules
if (!IsWindowReady()) {
InitWindow(winWidth, winHeight, "Task Workspace & Contribution Heatmap Dashboard");
SetTargetFPS(60);
}
while (!WindowShouldClose()) {
// Handle Month navigation buttons via arrow keys
if (IsKeyPressed(KEY_RIGHT)) {
currentMonth++;
if (currentMonth > 12) { currentMonth = 1; currentYear++; }
}
if (IsKeyPressed(KEY_LEFT)) {
currentMonth--;
if (currentMonth < 1) { currentMonth = 12; currentYear--; }
}
BeginDrawing();
ClearBackground((Color){ 11, 17, 26, 255 }); // GitHub dark background palette match
// Workspace headers
DrawText("CALENDAR CONTROL DASHBOARD", 40, 30, 26, WHITE);
string fullMonthHeading = getMonthName(currentMonth) + " " + to_string(currentYear);
DrawText(fullMonthHeading.c_str(), 40, 80, 22, (Color){ 255, 128, 0, 255 });
DrawText("Use Left/Right Arrow Keys to navigate between months", 40, 115, 14, GRAY);
// Render the main calendar grids layout system using text
int startDayOfWeek = getStartDay(currentMonth, currentYear);
int totalDaysInMonth = getDaysInMonth(currentMonth, currentYear);
const char* horizontalHeaders[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
for (int i = 0; i < 7; i++) {
// Changed from CYAN to pre-defined native SKYBLUE constant
DrawText(horizontalHeaders[i], 50 + (i * 65), 170, 15, SKYBLUE);
}
int currRow = 0;
for (int d = 1; d <= totalDaysInMonth; d++) {
int gridColumn = (startDayOfWeek + d - 1) % 7;
int renderX = 50 + (gridColumn * 65);
int renderY = 205 + (currRow * 40);
char dayBuf[8];
snprintf(dayBuf, sizeof(dayBuf), "%d", d);
if (d == today && currentMonth == (ltm->tm_mon + 1) && currentYear == (ltm->tm_year + 1900)) {
DrawCircle(renderX + 12, renderY + 8, 16, (Color){ 230, 80, 80, 255 });
DrawText(dayBuf, renderX, renderY, 15, WHITE);
} else if (hasTaskOnDate(d, currentMonth, currentYear)) {
DrawText(dayBuf, renderX, renderY, 15, (Color){ 0, 255, 150, 255 }); // Pending deadline check
} else {
DrawText(dayBuf, renderX, renderY, 15, LIGHTGRAY);
}
if (gridColumn == 6) currRow++;
}
// Render our Contribution Heatmap Dashboard Matrix Panel
int heatmapPanelX = 520;
int heatmapPanelY = 205;
DrawGitHubHeatmap(heatmapPanelX, heatmapPanelY, currentMonth, currentYear);
// Frame instructions box overlay
DrawRectangleLines(40, 520, 820, 80, DARKGRAY);
DrawText("LEGEND INDICATOR PROFILE:", 60, 535, 13, WHITE);
DrawText("* Green Matrix Shading indicates task volumes successfully COMPLETED on that specific calendar day.", 60, 555, 12, GRAY);
DrawText("* Highlighted skyblue columns track weekdays. Red circles specify today.", 60, 575, 12, GRAY);
EndDrawing();
}
// Graceful cleanup back to CLI terminal workspace loop
CloseWindow();
}