repo-wrapped 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/commands/generate.js +104 -95
  2. package/dist/constants/chronotypes.js +23 -23
  3. package/dist/constants/colors.js +18 -18
  4. package/dist/constants/index.js +18 -18
  5. package/dist/formatters/index.js +17 -17
  6. package/dist/formatters/timeFormatter.js +28 -29
  7. package/dist/generators/html/templates/achievementsSection.js +42 -43
  8. package/dist/generators/html/templates/commitQualitySection.js +25 -26
  9. package/dist/generators/html/templates/contributionGraph.js +64 -48
  10. package/dist/generators/html/templates/impactSection.js +19 -20
  11. package/dist/generators/html/templates/knowledgeSection.js +86 -87
  12. package/dist/generators/html/templates/streakSection.js +8 -9
  13. package/dist/generators/html/templates/timePatternsSection.js +45 -46
  14. package/dist/generators/html/utils/colorUtils.js +61 -21
  15. package/dist/generators/html/utils/commitMapBuilder.js +23 -24
  16. package/dist/generators/html/utils/dateRangeCalculator.js +56 -57
  17. package/dist/generators/html/utils/developerStatsCalculator.js +28 -29
  18. package/dist/generators/html/utils/scriptLoader.js +15 -16
  19. package/dist/generators/html/utils/styleLoader.js +17 -18
  20. package/dist/generators/html/utils/weekGrouper.js +27 -28
  21. package/dist/index.js +78 -78
  22. package/dist/types/index.js +2 -2
  23. package/dist/utils/achievementDefinitions.js +433 -433
  24. package/dist/utils/achievementEngine.js +169 -170
  25. package/dist/utils/commitQualityAnalyzer.js +367 -368
  26. package/dist/utils/fileHotspotAnalyzer.js +269 -270
  27. package/dist/utils/gitParser.js +136 -126
  28. package/dist/utils/htmlGenerator.js +245 -233
  29. package/dist/utils/impactAnalyzer.js +247 -248
  30. package/dist/utils/knowledgeDistributionAnalyzer.js +380 -374
  31. package/dist/utils/matrixGenerator.js +369 -350
  32. package/dist/utils/slideGenerator.js +170 -171
  33. package/dist/utils/streakCalculator.js +134 -135
  34. package/dist/utils/timePatternAnalyzer.js +304 -305
  35. package/dist/utils/wrappedDisplay.js +124 -115
  36. package/dist/utils/wrappedGenerator.js +376 -377
  37. package/dist/utils/wrappedHtmlGenerator.js +105 -106
  38. package/package.json +10 -10
@@ -1,433 +1,433 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getCategoryLabel = exports.getTierColor = exports.ACHIEVEMENTS = void 0;
4
- exports.ACHIEVEMENTS = [
5
- // ========================================
6
- // 🎯 MILESTONE BADGES
7
- // ========================================
8
- {
9
- id: 'first-steps',
10
- name: 'First Steps',
11
- emoji: '🌱',
12
- description: 'Made your first commit',
13
- category: 'milestone',
14
- tier: 'bronze',
15
- criteria: { type: 'commit-count', threshold: 1, comparator: '>=' },
16
- progress: 0,
17
- isUnlocked: false,
18
- isSecret: false
19
- },
20
- {
21
- id: 'getting-started',
22
- name: 'Getting Started',
23
- emoji: '',
24
- description: 'Reached 10 commits',
25
- category: 'milestone',
26
- tier: 'bronze',
27
- criteria: { type: 'commit-count', threshold: 10, comparator: '>=' },
28
- progress: 0,
29
- isUnlocked: false,
30
- isSecret: false
31
- },
32
- {
33
- id: 'on-fire',
34
- name: 'On Fire',
35
- emoji: '🔥',
36
- description: 'Reached 50 commits',
37
- category: 'milestone',
38
- tier: 'silver',
39
- criteria: { type: 'commit-count', threshold: 50, comparator: '>=' },
40
- progress: 0,
41
- isUnlocked: false,
42
- isSecret: false
43
- },
44
- {
45
- id: 'century-club',
46
- name: 'Century Club',
47
- emoji: '👑',
48
- description: 'Reached 100 commits',
49
- category: 'milestone',
50
- tier: 'gold',
51
- criteria: { type: 'commit-count', threshold: 100, comparator: '>=' },
52
- progress: 0,
53
- isUnlocked: false,
54
- isSecret: false
55
- },
56
- {
57
- id: 'champion',
58
- name: 'Champion',
59
- emoji: '🏆',
60
- description: 'Reached 500 commits',
61
- category: 'milestone',
62
- tier: 'platinum',
63
- criteria: { type: 'commit-count', threshold: 500, comparator: '>=' },
64
- progress: 0,
65
- isUnlocked: false,
66
- isSecret: false
67
- },
68
- {
69
- id: 'master',
70
- name: 'Master',
71
- emoji: '💫',
72
- description: 'Reached 1000 commits',
73
- category: 'milestone',
74
- tier: 'platinum',
75
- criteria: { type: 'commit-count', threshold: 1000, comparator: '>=' },
76
- progress: 0,
77
- isUnlocked: false,
78
- isSecret: false
79
- },
80
- {
81
- id: 'legend',
82
- name: 'Legend',
83
- emoji: '🌟',
84
- description: 'Reached 5000 commits',
85
- category: 'milestone',
86
- tier: 'legendary',
87
- criteria: { type: 'commit-count', threshold: 5000, comparator: '>=' },
88
- progress: 0,
89
- isUnlocked: false,
90
- isSecret: false
91
- },
92
- // ========================================
93
- // 📅 STREAK ACHIEVEMENTS
94
- // ========================================
95
- {
96
- id: 'consistency',
97
- name: 'Consistency',
98
- emoji: '📅',
99
- description: 'Maintained a 3-day commit streak',
100
- category: 'time',
101
- tier: 'bronze',
102
- criteria: { type: 'streak', threshold: 3, comparator: '>=' },
103
- progress: 0,
104
- isUnlocked: false,
105
- isSecret: false
106
- },
107
- {
108
- id: 'week-warrior',
109
- name: 'Week Warrior',
110
- emoji: '',
111
- description: 'Maintained a 7-day commit streak',
112
- category: 'time',
113
- tier: 'silver',
114
- criteria: { type: 'streak', threshold: 7, comparator: '>=' },
115
- progress: 0,
116
- isUnlocked: false,
117
- isSecret: false
118
- },
119
- {
120
- id: 'streak-on-fire',
121
- name: 'Streak On Fire',
122
- emoji: '🔥',
123
- description: 'Maintained a 14-day commit streak',
124
- category: 'time',
125
- tier: 'gold',
126
- criteria: { type: 'streak', threshold: 14, comparator: '>=' },
127
- progress: 0,
128
- isUnlocked: false,
129
- isSecret: false
130
- },
131
- {
132
- id: 'unstoppable',
133
- name: 'Unstoppable',
134
- emoji: '💪',
135
- description: 'Maintained a 30-day commit streak',
136
- category: 'time',
137
- tier: 'platinum',
138
- criteria: { type: 'streak', threshold: 30, comparator: '>=' },
139
- progress: 0,
140
- isUnlocked: false,
141
- isSecret: false
142
- },
143
- {
144
- id: 'iron-will',
145
- name: 'Iron Will',
146
- emoji: '🦾',
147
- description: 'Maintained a 60-day commit streak',
148
- category: 'time',
149
- tier: 'platinum',
150
- criteria: { type: 'streak', threshold: 60, comparator: '>=' },
151
- progress: 0,
152
- isUnlocked: false,
153
- isSecret: false
154
- },
155
- {
156
- id: 'code-machine',
157
- name: 'Code Machine',
158
- emoji: '👾',
159
- description: 'Maintained a 100-day commit streak',
160
- category: 'time',
161
- tier: 'legendary',
162
- criteria: { type: 'streak', threshold: 100, comparator: '>=' },
163
- progress: 0,
164
- isUnlocked: false,
165
- isSecret: false
166
- },
167
- // ========================================
168
- // 🎨 QUALITY BADGES
169
- // ========================================
170
- {
171
- id: 'clean-coder',
172
- name: 'Clean Coder',
173
- emoji: '',
174
- description: '90%+ commits follow conventions',
175
- category: 'quality',
176
- tier: 'gold',
177
- criteria: {
178
- type: 'custom',
179
- customCheck: (data) => data.commitQuality.conventionalCommits.adherence >= 90
180
- },
181
- progress: 0,
182
- isUnlocked: false,
183
- isSecret: false
184
- },
185
- {
186
- id: 'documentarian',
187
- name: 'Documentarian',
188
- emoji: '📝',
189
- description: '50%+ commits include detailed bodies',
190
- category: 'quality',
191
- tier: 'silver',
192
- criteria: {
193
- type: 'custom',
194
- customCheck: (data) => (data.commitQuality.bodyQuality.withBody / data.totalCommits) >= 0.5
195
- },
196
- progress: 0,
197
- isUnlocked: false,
198
- isSecret: false
199
- },
200
- {
201
- id: 'quality-champion',
202
- name: 'Quality Champion',
203
- emoji: '🏅',
204
- description: 'Achieved 9.0+ overall quality score',
205
- category: 'quality',
206
- tier: 'platinum',
207
- criteria: { type: 'quality-score', threshold: 9.0, comparator: '>=' },
208
- progress: 0,
209
- isUnlocked: false,
210
- isSecret: false
211
- },
212
- {
213
- id: 'rising-star',
214
- name: 'Rising Star',
215
- emoji: '📈',
216
- description: 'Quality score above 7.0',
217
- category: 'quality',
218
- tier: 'gold',
219
- criteria: { type: 'quality-score', threshold: 7.0, comparator: '>=' },
220
- progress: 0,
221
- isUnlocked: false,
222
- isSecret: false
223
- },
224
- // ========================================
225
- // ⏰ TIME PATTERN BADGES
226
- // ========================================
227
- {
228
- id: 'early-bird',
229
- name: 'Early Bird',
230
- emoji: '🌅',
231
- description: '50+ commits before 9am',
232
- category: 'time',
233
- tier: 'silver',
234
- criteria: {
235
- type: 'time-pattern',
236
- customCheck: (data) => {
237
- const earlyCommits = data.commits.filter(c => {
238
- const hour = new Date(c.date).getHours();
239
- return hour >= 5 && hour < 9;
240
- }).length;
241
- return earlyCommits >= 50;
242
- }
243
- },
244
- progress: 0,
245
- isUnlocked: false,
246
- isSecret: false
247
- },
248
- {
249
- id: 'night-owl',
250
- name: 'Night Owl',
251
- emoji: '🦉',
252
- description: '50+ commits after 9pm',
253
- category: 'time',
254
- tier: 'silver',
255
- criteria: {
256
- type: 'time-pattern',
257
- customCheck: (data) => {
258
- const lateCommits = data.commits.filter(c => {
259
- const hour = new Date(c.date).getHours();
260
- return hour >= 21 || hour < 5;
261
- }).length;
262
- return lateCommits >= 50;
263
- }
264
- },
265
- progress: 0,
266
- isUnlocked: false,
267
- isSecret: false
268
- },
269
- {
270
- id: 'balanced-soul',
271
- name: 'Balanced Soul',
272
- emoji: '⚖️',
273
- description: 'Even distribution across all time periods',
274
- category: 'time',
275
- tier: 'gold',
276
- criteria: {
277
- type: 'custom',
278
- customCheck: (data) => data.timePattern.chronotype === 'balanced'
279
- },
280
- progress: 0,
281
- isUnlocked: false,
282
- isSecret: false
283
- },
284
- {
285
- id: 'work-life-balance',
286
- name: 'Balanced Life',
287
- emoji: '🌴',
288
- description: 'Excellent work-life balance score',
289
- category: 'time',
290
- tier: 'gold',
291
- criteria: {
292
- type: 'custom',
293
- customCheck: (data) => data.timePattern.workLifeBalance.score >= 4
294
- },
295
- progress: 0,
296
- isUnlocked: false,
297
- isSecret: false
298
- },
299
- // ========================================
300
- // 🎮 SPECIAL ACHIEVEMENTS
301
- // ========================================
302
- {
303
- id: 'midnight-coder',
304
- name: 'Midnight Coder',
305
- emoji: '🎆',
306
- description: 'Committed at exactly midnight',
307
- category: 'special',
308
- tier: 'silver',
309
- criteria: {
310
- type: 'custom',
311
- customCheck: (data) => data.commits.some(c => {
312
- const date = new Date(c.date);
313
- return date.getHours() === 0 && date.getMinutes() === 0;
314
- })
315
- },
316
- progress: 0,
317
- isUnlocked: false,
318
- isSecret: true
319
- },
320
- {
321
- id: 'lucky-seven',
322
- name: 'Lucky Seven',
323
- emoji: '🎰',
324
- description: 'Reached exactly 777 commits',
325
- category: 'special',
326
- tier: 'gold',
327
- criteria: { type: 'commit-count', threshold: 777, comparator: '==' },
328
- progress: 0,
329
- isUnlocked: false,
330
- isSecret: true
331
- },
332
- {
333
- id: 'binary-master',
334
- name: 'Binary Master',
335
- emoji: '🔢',
336
- description: 'Reached exactly 1024 commits',
337
- category: 'special',
338
- tier: 'platinum',
339
- criteria: { type: 'commit-count', threshold: 1024, comparator: '==' },
340
- progress: 0,
341
- isUnlocked: false,
342
- isSecret: true
343
- },
344
- {
345
- id: 'weekend-warrior',
346
- name: 'Weekend Warrior',
347
- emoji: '🎪',
348
- description: '20%+ commits on weekends',
349
- category: 'special',
350
- tier: 'silver',
351
- criteria: {
352
- type: 'custom',
353
- customCheck: (data) => {
354
- const weekendRatio = data.timePattern.workLifeBalance.weekendCommits / data.totalCommits;
355
- return weekendRatio >= 0.2;
356
- }
357
- },
358
- progress: 0,
359
- isUnlocked: false,
360
- isSecret: false
361
- },
362
- // ========================================
363
- // 🏆 META ACHIEVEMENTS
364
- // ========================================
365
- {
366
- id: 'collector',
367
- name: 'Collector',
368
- emoji: '🎖️',
369
- description: 'Earned 10 badges',
370
- category: 'meta',
371
- tier: 'silver',
372
- criteria: {
373
- type: 'custom',
374
- customCheck: (data) => false // Will be checked separately
375
- },
376
- progress: 0,
377
- isUnlocked: false,
378
- isSecret: false
379
- },
380
- {
381
- id: 'completionist',
382
- name: 'Completionist',
383
- emoji: '🏅',
384
- description: 'Earned 25 badges',
385
- category: 'meta',
386
- tier: 'gold',
387
- criteria: {
388
- type: 'custom',
389
- customCheck: (data) => false // Will be checked separately
390
- },
391
- progress: 0,
392
- isUnlocked: false,
393
- isSecret: false
394
- },
395
- {
396
- id: 'badge-king',
397
- name: 'Badge King',
398
- emoji: '👑',
399
- description: 'Earned 50 badges',
400
- category: 'meta',
401
- tier: 'legendary',
402
- criteria: {
403
- type: 'custom',
404
- customCheck: (data) => false // Will be checked separately
405
- },
406
- progress: 0,
407
- isUnlocked: false,
408
- isSecret: false
409
- }
410
- ];
411
- function getTierColor(tier) {
412
- switch (tier) {
413
- case 'bronze': return '#cd7f32';
414
- case 'silver': return '#c0c0c0';
415
- case 'gold': return '#ffd700';
416
- case 'platinum': return '#e5e4e2';
417
- case 'legendary': return '#ff6b6b';
418
- default: return '#8b949e';
419
- }
420
- }
421
- exports.getTierColor = getTierColor;
422
- function getCategoryLabel(category) {
423
- switch (category) {
424
- case 'milestone': return '🎯 Milestone';
425
- case 'quality': return '🎨 Quality';
426
- case 'collaboration': return '🤝 Collaboration';
427
- case 'time': return ' Time & Consistency';
428
- case 'special': return '🎮 Special';
429
- case 'meta': return '🏆 Meta';
430
- default: return category;
431
- }
432
- }
433
- exports.getCategoryLabel = getCategoryLabel;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ACHIEVEMENTS = void 0;
4
+ exports.getTierColor = getTierColor;
5
+ exports.getCategoryLabel = getCategoryLabel;
6
+ exports.ACHIEVEMENTS = [
7
+ // ========================================
8
+ // 🎯 MILESTONE BADGES
9
+ // ========================================
10
+ {
11
+ id: 'first-steps',
12
+ name: 'First Steps',
13
+ emoji: '🌱',
14
+ description: 'Made your first commit',
15
+ category: 'milestone',
16
+ tier: 'bronze',
17
+ criteria: { type: 'commit-count', threshold: 1, comparator: '>=' },
18
+ progress: 0,
19
+ isUnlocked: false,
20
+ isSecret: false
21
+ },
22
+ {
23
+ id: 'getting-started',
24
+ name: 'Getting Started',
25
+ emoji: '',
26
+ description: 'Reached 10 commits',
27
+ category: 'milestone',
28
+ tier: 'bronze',
29
+ criteria: { type: 'commit-count', threshold: 10, comparator: '>=' },
30
+ progress: 0,
31
+ isUnlocked: false,
32
+ isSecret: false
33
+ },
34
+ {
35
+ id: 'on-fire',
36
+ name: 'On Fire',
37
+ emoji: '🔥',
38
+ description: 'Reached 50 commits',
39
+ category: 'milestone',
40
+ tier: 'silver',
41
+ criteria: { type: 'commit-count', threshold: 50, comparator: '>=' },
42
+ progress: 0,
43
+ isUnlocked: false,
44
+ isSecret: false
45
+ },
46
+ {
47
+ id: 'century-club',
48
+ name: 'Century Club',
49
+ emoji: '👑',
50
+ description: 'Reached 100 commits',
51
+ category: 'milestone',
52
+ tier: 'gold',
53
+ criteria: { type: 'commit-count', threshold: 100, comparator: '>=' },
54
+ progress: 0,
55
+ isUnlocked: false,
56
+ isSecret: false
57
+ },
58
+ {
59
+ id: 'champion',
60
+ name: 'Champion',
61
+ emoji: '🏆',
62
+ description: 'Reached 500 commits',
63
+ category: 'milestone',
64
+ tier: 'platinum',
65
+ criteria: { type: 'commit-count', threshold: 500, comparator: '>=' },
66
+ progress: 0,
67
+ isUnlocked: false,
68
+ isSecret: false
69
+ },
70
+ {
71
+ id: 'master',
72
+ name: 'Master',
73
+ emoji: '💫',
74
+ description: 'Reached 1000 commits',
75
+ category: 'milestone',
76
+ tier: 'platinum',
77
+ criteria: { type: 'commit-count', threshold: 1000, comparator: '>=' },
78
+ progress: 0,
79
+ isUnlocked: false,
80
+ isSecret: false
81
+ },
82
+ {
83
+ id: 'legend',
84
+ name: 'Legend',
85
+ emoji: '🌟',
86
+ description: 'Reached 5000 commits',
87
+ category: 'milestone',
88
+ tier: 'legendary',
89
+ criteria: { type: 'commit-count', threshold: 5000, comparator: '>=' },
90
+ progress: 0,
91
+ isUnlocked: false,
92
+ isSecret: false
93
+ },
94
+ // ========================================
95
+ // 📅 STREAK ACHIEVEMENTS
96
+ // ========================================
97
+ {
98
+ id: 'consistency',
99
+ name: 'Consistency',
100
+ emoji: '📅',
101
+ description: 'Maintained a 3-day commit streak',
102
+ category: 'time',
103
+ tier: 'bronze',
104
+ criteria: { type: 'streak', threshold: 3, comparator: '>=' },
105
+ progress: 0,
106
+ isUnlocked: false,
107
+ isSecret: false
108
+ },
109
+ {
110
+ id: 'week-warrior',
111
+ name: 'Week Warrior',
112
+ emoji: '',
113
+ description: 'Maintained a 7-day commit streak',
114
+ category: 'time',
115
+ tier: 'silver',
116
+ criteria: { type: 'streak', threshold: 7, comparator: '>=' },
117
+ progress: 0,
118
+ isUnlocked: false,
119
+ isSecret: false
120
+ },
121
+ {
122
+ id: 'streak-on-fire',
123
+ name: 'Streak On Fire',
124
+ emoji: '🔥',
125
+ description: 'Maintained a 14-day commit streak',
126
+ category: 'time',
127
+ tier: 'gold',
128
+ criteria: { type: 'streak', threshold: 14, comparator: '>=' },
129
+ progress: 0,
130
+ isUnlocked: false,
131
+ isSecret: false
132
+ },
133
+ {
134
+ id: 'unstoppable',
135
+ name: 'Unstoppable',
136
+ emoji: '💪',
137
+ description: 'Maintained a 30-day commit streak',
138
+ category: 'time',
139
+ tier: 'platinum',
140
+ criteria: { type: 'streak', threshold: 30, comparator: '>=' },
141
+ progress: 0,
142
+ isUnlocked: false,
143
+ isSecret: false
144
+ },
145
+ {
146
+ id: 'iron-will',
147
+ name: 'Iron Will',
148
+ emoji: '🦾',
149
+ description: 'Maintained a 60-day commit streak',
150
+ category: 'time',
151
+ tier: 'platinum',
152
+ criteria: { type: 'streak', threshold: 60, comparator: '>=' },
153
+ progress: 0,
154
+ isUnlocked: false,
155
+ isSecret: false
156
+ },
157
+ {
158
+ id: 'code-machine',
159
+ name: 'Code Machine',
160
+ emoji: '👾',
161
+ description: 'Maintained a 100-day commit streak',
162
+ category: 'time',
163
+ tier: 'legendary',
164
+ criteria: { type: 'streak', threshold: 100, comparator: '>=' },
165
+ progress: 0,
166
+ isUnlocked: false,
167
+ isSecret: false
168
+ },
169
+ // ========================================
170
+ // 🎨 QUALITY BADGES
171
+ // ========================================
172
+ {
173
+ id: 'clean-coder',
174
+ name: 'Clean Coder',
175
+ emoji: '',
176
+ description: '90%+ commits follow conventions',
177
+ category: 'quality',
178
+ tier: 'gold',
179
+ criteria: {
180
+ type: 'custom',
181
+ customCheck: (data) => data.commitQuality.conventionalCommits.adherence >= 90
182
+ },
183
+ progress: 0,
184
+ isUnlocked: false,
185
+ isSecret: false
186
+ },
187
+ {
188
+ id: 'documentarian',
189
+ name: 'Documentarian',
190
+ emoji: '📝',
191
+ description: '50%+ commits include detailed bodies',
192
+ category: 'quality',
193
+ tier: 'silver',
194
+ criteria: {
195
+ type: 'custom',
196
+ customCheck: (data) => (data.commitQuality.bodyQuality.withBody / data.totalCommits) >= 0.5
197
+ },
198
+ progress: 0,
199
+ isUnlocked: false,
200
+ isSecret: false
201
+ },
202
+ {
203
+ id: 'quality-champion',
204
+ name: 'Quality Champion',
205
+ emoji: '🏅',
206
+ description: 'Achieved 9.0+ overall quality score',
207
+ category: 'quality',
208
+ tier: 'platinum',
209
+ criteria: { type: 'quality-score', threshold: 9.0, comparator: '>=' },
210
+ progress: 0,
211
+ isUnlocked: false,
212
+ isSecret: false
213
+ },
214
+ {
215
+ id: 'rising-star',
216
+ name: 'Rising Star',
217
+ emoji: '📈',
218
+ description: 'Quality score above 7.0',
219
+ category: 'quality',
220
+ tier: 'gold',
221
+ criteria: { type: 'quality-score', threshold: 7.0, comparator: '>=' },
222
+ progress: 0,
223
+ isUnlocked: false,
224
+ isSecret: false
225
+ },
226
+ // ========================================
227
+ // ⏰ TIME PATTERN BADGES
228
+ // ========================================
229
+ {
230
+ id: 'early-bird',
231
+ name: 'Early Bird',
232
+ emoji: '🌅',
233
+ description: '50+ commits before 9am',
234
+ category: 'time',
235
+ tier: 'silver',
236
+ criteria: {
237
+ type: 'time-pattern',
238
+ customCheck: (data) => {
239
+ const earlyCommits = data.commits.filter(c => {
240
+ const hour = new Date(c.date).getHours();
241
+ return hour >= 5 && hour < 9;
242
+ }).length;
243
+ return earlyCommits >= 50;
244
+ }
245
+ },
246
+ progress: 0,
247
+ isUnlocked: false,
248
+ isSecret: false
249
+ },
250
+ {
251
+ id: 'night-owl',
252
+ name: 'Night Owl',
253
+ emoji: '🦉',
254
+ description: '50+ commits after 9pm',
255
+ category: 'time',
256
+ tier: 'silver',
257
+ criteria: {
258
+ type: 'time-pattern',
259
+ customCheck: (data) => {
260
+ const lateCommits = data.commits.filter(c => {
261
+ const hour = new Date(c.date).getHours();
262
+ return hour >= 21 || hour < 5;
263
+ }).length;
264
+ return lateCommits >= 50;
265
+ }
266
+ },
267
+ progress: 0,
268
+ isUnlocked: false,
269
+ isSecret: false
270
+ },
271
+ {
272
+ id: 'balanced-soul',
273
+ name: 'Balanced Soul',
274
+ emoji: '⚖️',
275
+ description: 'Even distribution across all time periods',
276
+ category: 'time',
277
+ tier: 'gold',
278
+ criteria: {
279
+ type: 'custom',
280
+ customCheck: (data) => data.timePattern.chronotype === 'balanced'
281
+ },
282
+ progress: 0,
283
+ isUnlocked: false,
284
+ isSecret: false
285
+ },
286
+ {
287
+ id: 'work-life-balance',
288
+ name: 'Balanced Life',
289
+ emoji: '🌴',
290
+ description: 'Excellent work-life balance score',
291
+ category: 'time',
292
+ tier: 'gold',
293
+ criteria: {
294
+ type: 'custom',
295
+ customCheck: (data) => data.timePattern.workLifeBalance.score >= 4
296
+ },
297
+ progress: 0,
298
+ isUnlocked: false,
299
+ isSecret: false
300
+ },
301
+ // ========================================
302
+ // 🎮 SPECIAL ACHIEVEMENTS
303
+ // ========================================
304
+ {
305
+ id: 'midnight-coder',
306
+ name: 'Midnight Coder',
307
+ emoji: '🎆',
308
+ description: 'Committed at exactly midnight',
309
+ category: 'special',
310
+ tier: 'silver',
311
+ criteria: {
312
+ type: 'custom',
313
+ customCheck: (data) => data.commits.some(c => {
314
+ const date = new Date(c.date);
315
+ return date.getHours() === 0 && date.getMinutes() === 0;
316
+ })
317
+ },
318
+ progress: 0,
319
+ isUnlocked: false,
320
+ isSecret: true
321
+ },
322
+ {
323
+ id: 'lucky-seven',
324
+ name: 'Lucky Seven',
325
+ emoji: '🎰',
326
+ description: 'Reached exactly 777 commits',
327
+ category: 'special',
328
+ tier: 'gold',
329
+ criteria: { type: 'commit-count', threshold: 777, comparator: '==' },
330
+ progress: 0,
331
+ isUnlocked: false,
332
+ isSecret: true
333
+ },
334
+ {
335
+ id: 'binary-master',
336
+ name: 'Binary Master',
337
+ emoji: '🔢',
338
+ description: 'Reached exactly 1024 commits',
339
+ category: 'special',
340
+ tier: 'platinum',
341
+ criteria: { type: 'commit-count', threshold: 1024, comparator: '==' },
342
+ progress: 0,
343
+ isUnlocked: false,
344
+ isSecret: true
345
+ },
346
+ {
347
+ id: 'weekend-warrior',
348
+ name: 'Weekend Warrior',
349
+ emoji: '🎪',
350
+ description: '20%+ commits on weekends',
351
+ category: 'special',
352
+ tier: 'silver',
353
+ criteria: {
354
+ type: 'custom',
355
+ customCheck: (data) => {
356
+ const weekendRatio = data.timePattern.workLifeBalance.weekendCommits / data.totalCommits;
357
+ return weekendRatio >= 0.2;
358
+ }
359
+ },
360
+ progress: 0,
361
+ isUnlocked: false,
362
+ isSecret: false
363
+ },
364
+ // ========================================
365
+ // 🏆 META ACHIEVEMENTS
366
+ // ========================================
367
+ {
368
+ id: 'collector',
369
+ name: 'Collector',
370
+ emoji: '🎖️',
371
+ description: 'Earned 10 badges',
372
+ category: 'meta',
373
+ tier: 'silver',
374
+ criteria: {
375
+ type: 'custom',
376
+ customCheck: (data) => false // Will be checked separately
377
+ },
378
+ progress: 0,
379
+ isUnlocked: false,
380
+ isSecret: false
381
+ },
382
+ {
383
+ id: 'completionist',
384
+ name: 'Completionist',
385
+ emoji: '🏅',
386
+ description: 'Earned 25 badges',
387
+ category: 'meta',
388
+ tier: 'gold',
389
+ criteria: {
390
+ type: 'custom',
391
+ customCheck: (data) => false // Will be checked separately
392
+ },
393
+ progress: 0,
394
+ isUnlocked: false,
395
+ isSecret: false
396
+ },
397
+ {
398
+ id: 'badge-king',
399
+ name: 'Badge King',
400
+ emoji: '👑',
401
+ description: 'Earned 50 badges',
402
+ category: 'meta',
403
+ tier: 'legendary',
404
+ criteria: {
405
+ type: 'custom',
406
+ customCheck: (data) => false // Will be checked separately
407
+ },
408
+ progress: 0,
409
+ isUnlocked: false,
410
+ isSecret: false
411
+ }
412
+ ];
413
+ function getTierColor(tier) {
414
+ switch (tier) {
415
+ case 'bronze': return '#cd7f32';
416
+ case 'silver': return '#c0c0c0';
417
+ case 'gold': return '#ffd700';
418
+ case 'platinum': return '#e5e4e2';
419
+ case 'legendary': return '#ff6b6b';
420
+ default: return '#8b949e';
421
+ }
422
+ }
423
+ function getCategoryLabel(category) {
424
+ switch (category) {
425
+ case 'milestone': return '🎯 Milestone';
426
+ case 'quality': return '🎨 Quality';
427
+ case 'collaboration': return '🤝 Collaboration';
428
+ case 'time': return ' Time & Consistency';
429
+ case 'special': return '🎮 Special';
430
+ case 'meta': return '🏆 Meta';
431
+ default: return category;
432
+ }
433
+ }