repo-wrapped 0.0.6 → 0.0.9

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 (176) hide show
  1. package/.github/agents/complete.agent.md +257 -0
  2. package/.github/agents/feature-scaffold.agent.md +248 -0
  3. package/.github/agents/jsdoc.agent.md +243 -0
  4. package/.github/agents/plan.agent.md +202 -0
  5. package/.github/agents/spec-writer.agent.md +169 -0
  6. package/.github/agents/test-writer.agent.md +169 -0
  7. package/.stylelintrc.json +27 -0
  8. package/README.md +94 -94
  9. package/coverage/base.css +224 -0
  10. package/coverage/block-navigation.js +87 -0
  11. package/coverage/favicon.png +0 -0
  12. package/coverage/index.html +446 -0
  13. package/coverage/lcov-report/base.css +224 -0
  14. package/coverage/lcov-report/block-navigation.js +87 -0
  15. package/coverage/lcov-report/favicon.png +0 -0
  16. package/coverage/lcov-report/index.html +446 -0
  17. package/coverage/lcov-report/prettify.css +1 -0
  18. package/coverage/lcov-report/prettify.js +2 -0
  19. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  20. package/coverage/lcov-report/sorter.js +210 -0
  21. package/coverage/lcov.info +7039 -0
  22. package/coverage/prettify.css +1 -0
  23. package/coverage/prettify.js +2 -0
  24. package/coverage/sort-arrow-sprite.png +0 -0
  25. package/coverage/sorter.js +210 -0
  26. package/dist/commands/generate.js +262 -5
  27. package/dist/config/defaults.js +158 -0
  28. package/dist/config/index.js +10 -0
  29. package/dist/features/achievements/data/achievements.json +284 -0
  30. package/dist/features/achievements/engine.js +140 -0
  31. package/dist/features/achievements/evaluators.js +246 -0
  32. package/dist/features/achievements/helpers.js +58 -0
  33. package/dist/features/achievements/index.js +57 -0
  34. package/dist/features/achievements/loader.js +88 -0
  35. package/dist/features/achievements/template.js +155 -0
  36. package/dist/features/achievements/types.js +7 -0
  37. package/dist/features/commit-quality/analyzer.js +378 -0
  38. package/dist/features/commit-quality/analyzer.test.js +484 -0
  39. package/dist/features/commit-quality/index.js +28 -0
  40. package/dist/features/commit-quality/template.js +114 -0
  41. package/dist/features/commit-quality/types.js +2 -0
  42. package/dist/features/comparison/analyzer.js +222 -0
  43. package/dist/features/comparison/index.js +28 -0
  44. package/dist/features/comparison/template.js +119 -0
  45. package/dist/features/comparison/types.js +2 -0
  46. package/dist/features/contribution-graph/index.js +9 -0
  47. package/dist/features/contribution-graph/template.js +89 -0
  48. package/dist/features/events/index.js +31 -0
  49. package/dist/features/events/parser.js +253 -0
  50. package/dist/features/events/template.js +113 -0
  51. package/dist/features/events/types.js +2 -0
  52. package/dist/features/executive-summary/generator.js +275 -0
  53. package/dist/features/executive-summary/index.js +27 -0
  54. package/dist/features/executive-summary/template.js +80 -0
  55. package/dist/features/executive-summary/types.js +2 -0
  56. package/dist/features/gaps/analyzer.js +298 -0
  57. package/dist/features/gaps/analyzer.test.js +517 -0
  58. package/dist/features/gaps/index.js +27 -0
  59. package/dist/features/gaps/template.js +190 -0
  60. package/dist/features/gaps/types.js +2 -0
  61. package/dist/features/impact/analyzer.js +248 -0
  62. package/dist/features/impact/index.js +26 -0
  63. package/dist/features/impact/template.js +118 -0
  64. package/dist/features/impact/types.js +2 -0
  65. package/dist/features/index.js +40 -0
  66. package/dist/features/knowledge/analyzer.js +385 -0
  67. package/dist/features/knowledge/index.js +26 -0
  68. package/dist/features/knowledge/template.js +239 -0
  69. package/dist/features/knowledge/types.js +2 -0
  70. package/dist/features/streaks/calculator.js +184 -0
  71. package/dist/features/streaks/calculator.test.js +366 -0
  72. package/dist/features/streaks/index.js +36 -0
  73. package/dist/features/streaks/template.js +41 -0
  74. package/dist/features/streaks/types.js +9 -0
  75. package/dist/features/team/analyzer.js +316 -0
  76. package/dist/features/team/index.js +30 -0
  77. package/dist/features/team/template.js +146 -0
  78. package/dist/features/team/types.js +2 -0
  79. package/dist/features/time-patterns/analyzer.js +319 -0
  80. package/dist/features/time-patterns/analyzer.test.js +278 -0
  81. package/dist/features/time-patterns/index.js +37 -0
  82. package/dist/features/time-patterns/template.js +109 -0
  83. package/dist/features/time-patterns/types.js +9 -0
  84. package/dist/features/velocity/analyzer.js +257 -0
  85. package/dist/features/velocity/analyzer.test.js +383 -0
  86. package/dist/features/velocity/index.js +27 -0
  87. package/dist/features/velocity/template.js +189 -0
  88. package/dist/features/velocity/types.js +2 -0
  89. package/dist/generators/html/scripts/knowledge.js +17 -0
  90. package/dist/generators/html/styles/base.css +10 -6
  91. package/dist/generators/html/styles/components.css +121 -1
  92. package/dist/generators/html/styles/knowledge.css +21 -0
  93. package/dist/generators/html/styles/leaddev.css +1335 -0
  94. package/dist/generators/html/styles/strategic-insights.css +1337 -0
  95. package/dist/generators/html/templates/commitQualitySection.js +28 -2
  96. package/dist/generators/html/templates/comparisonSection.js +119 -0
  97. package/dist/generators/html/templates/eventsSection.js +113 -0
  98. package/dist/generators/html/templates/executiveSummarySection.js +80 -0
  99. package/dist/generators/html/templates/gapSection.js +190 -0
  100. package/dist/generators/html/templates/impactSection.js +8 -6
  101. package/dist/generators/html/templates/knowledgeSection.js +16 -2
  102. package/dist/generators/html/templates/teamSection.js +146 -0
  103. package/dist/generators/html/templates/velocitySection.js +189 -0
  104. package/dist/generators/html/types.js +7 -0
  105. package/dist/generators/html/utils/analysisRunner.js +93 -0
  106. package/dist/generators/html/utils/cardBuilder.js +47 -0
  107. package/dist/generators/html/utils/contextBuilder.js +54 -0
  108. package/dist/generators/html/utils/htmlDocumentBuilder.js +396 -0
  109. package/dist/generators/html/utils/kpiBuilder.js +76 -0
  110. package/dist/generators/html/utils/sectionWrapper.js +71 -0
  111. package/dist/generators/html/utils/styleLoader.js +2 -1
  112. package/dist/html/analysisRunner.js +93 -0
  113. package/dist/html/htmlDocumentBuilder.js +396 -0
  114. package/dist/html/index.js +29 -0
  115. package/dist/html/shared/colorUtils.js +61 -0
  116. package/dist/html/shared/commitMapBuilder.js +23 -0
  117. package/dist/html/shared/components/cardBuilder.js +47 -0
  118. package/dist/html/shared/components/index.js +18 -0
  119. package/dist/html/shared/components/kpiBuilder.js +76 -0
  120. package/dist/html/shared/components/sectionWrapper.js +71 -0
  121. package/dist/html/shared/contextBuilder.js +54 -0
  122. package/dist/html/shared/dateRangeCalculator.js +56 -0
  123. package/dist/html/shared/developerStatsCalculator.js +28 -0
  124. package/dist/html/shared/index.js +39 -0
  125. package/dist/html/shared/scriptLoader.js +15 -0
  126. package/dist/html/shared/scripts/export.js +125 -0
  127. package/dist/html/shared/scripts/knowledge.js +137 -0
  128. package/dist/html/shared/scripts/modal.js +68 -0
  129. package/dist/html/shared/scripts/navigation.js +156 -0
  130. package/dist/html/shared/scripts/tabs.js +18 -0
  131. package/dist/html/shared/scripts/tooltip.js +21 -0
  132. package/dist/html/shared/styleLoader.js +18 -0
  133. package/dist/html/shared/styles/achievements.css +387 -0
  134. package/dist/html/shared/styles/base.css +822 -0
  135. package/dist/html/shared/styles/components.css +1511 -0
  136. package/dist/html/shared/styles/knowledge.css +242 -0
  137. package/dist/html/shared/styles/strategic-insights.css +1337 -0
  138. package/dist/html/shared/weekGrouper.js +27 -0
  139. package/dist/html/types.js +7 -0
  140. package/dist/index.js +54 -21
  141. package/dist/test/helpers/commitFactory.js +166 -0
  142. package/dist/test/helpers/dateUtils.js +101 -0
  143. package/dist/test/helpers/index.js +29 -0
  144. package/dist/test/setup.js +17 -0
  145. package/dist/test/smoke.test.js +94 -0
  146. package/dist/types/achievements.js +7 -0
  147. package/dist/types/analysis.js +7 -0
  148. package/dist/types/core.js +7 -0
  149. package/dist/types/index.js +38 -0
  150. package/dist/types/options.js +7 -0
  151. package/dist/types/shared.js +7 -0
  152. package/dist/types/strategic.js +7 -0
  153. package/dist/types/summary.js +7 -0
  154. package/dist/utils/achievementDefinitions.js +22 -22
  155. package/dist/utils/analyzerContextBuilder.js +124 -0
  156. package/dist/utils/commitQualityAnalyzer.js +13 -2
  157. package/dist/utils/emptyResults.js +95 -0
  158. package/dist/utils/eventAnnotationParser.js +253 -0
  159. package/dist/utils/executiveSummaryGenerator.js +275 -0
  160. package/dist/utils/fileHotspotAnalyzer.js +4 -12
  161. package/dist/utils/gapAnalyzer.js +298 -0
  162. package/dist/utils/gitParser.test.js +363 -0
  163. package/dist/utils/htmlGenerator.js +126 -450
  164. package/dist/utils/impactAnalyzer.js +20 -19
  165. package/dist/utils/knowledgeDistributionAnalyzer.js +32 -27
  166. package/dist/utils/matrixGenerator.js +13 -13
  167. package/dist/utils/rangeComparisonAnalyzer.js +222 -0
  168. package/dist/utils/streakCalculator.js +77 -27
  169. package/dist/utils/teamAnalyzer.js +316 -0
  170. package/dist/utils/timePatternAnalyzer.js +18 -3
  171. package/dist/utils/velocityAnalyzer.js +257 -0
  172. package/dist/utils/wrappedGenerator.js +8 -8
  173. package/package.json +74 -55
  174. package/vitest.config.ts +46 -0
  175. package/dist/cli.js +0 -24
  176. package/dist/commands/index.js +0 -24
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+ /**
3
+ * Achievement Evaluators Module
4
+ *
5
+ * Pure functions that evaluate achievement criteria against analysis data.
6
+ * Each evaluator returns { earned: boolean, progress: number } where progress is 0-100.
7
+ *
8
+ * @module achievementEvaluators
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.evaluate = evaluate;
12
+ exports.evaluateMeta = evaluateMeta;
13
+ exports.isMetaCriteria = isMetaCriteria;
14
+ /**
15
+ * Calculate progress as percentage (capped at 100)
16
+ */
17
+ function progressPercent(current, target) {
18
+ if (target === 0)
19
+ return 100;
20
+ return Math.min(100, Math.round((current / target) * 100));
21
+ }
22
+ /**
23
+ * Evaluate commit count threshold
24
+ */
25
+ function evaluateCommitCount(data, criteria) {
26
+ const count = data.totalCommits ?? 0;
27
+ const threshold = criteria.threshold ?? 0;
28
+ return {
29
+ earned: count >= threshold,
30
+ progress: progressPercent(count, threshold),
31
+ };
32
+ }
33
+ /**
34
+ * Evaluate exact commit count (for special achievements)
35
+ */
36
+ function evaluateExactCommitCount(data, criteria) {
37
+ const count = data.totalCommits ?? 0;
38
+ const threshold = criteria.threshold ?? 0;
39
+ return {
40
+ earned: count === threshold,
41
+ progress: count === threshold ? 100 : progressPercent(count, threshold),
42
+ };
43
+ }
44
+ /**
45
+ * Evaluate streak length
46
+ */
47
+ function evaluateStreak(data, criteria) {
48
+ const streak = data.streakData?.longestStreak?.days ?? 0;
49
+ const threshold = criteria.threshold ?? 0;
50
+ return {
51
+ earned: streak >= threshold,
52
+ progress: progressPercent(streak, threshold),
53
+ };
54
+ }
55
+ /**
56
+ * Evaluate quality score threshold
57
+ */
58
+ function evaluateQualityScore(data, criteria) {
59
+ const score = data.commitQuality?.overallScore ?? 0;
60
+ const threshold = criteria.threshold ?? 0;
61
+ return {
62
+ earned: score >= threshold,
63
+ progress: progressPercent(score, threshold),
64
+ };
65
+ }
66
+ /**
67
+ * Evaluate conventional commit adherence percentage
68
+ */
69
+ function evaluateConventionalAdherence(data, criteria) {
70
+ const adherence = data.commitQuality?.conventionalCommits?.adherence ?? 0;
71
+ const threshold = criteria.threshold ?? 0;
72
+ return {
73
+ earned: adherence >= threshold,
74
+ progress: progressPercent(adherence, threshold),
75
+ };
76
+ }
77
+ /**
78
+ * Evaluate percentage of commits with body content
79
+ */
80
+ function evaluateBodyPercentage(data, criteria) {
81
+ const withBody = data.commitQuality?.bodyQuality?.withBody ?? 0;
82
+ const total = data.totalCommits ?? 1;
83
+ const percentage = (withBody / total) * 100;
84
+ const threshold = criteria.threshold ?? 0;
85
+ return {
86
+ earned: percentage >= threshold,
87
+ progress: progressPercent(percentage, threshold),
88
+ };
89
+ }
90
+ /**
91
+ * Evaluate commits within a time range (e.g., early morning)
92
+ */
93
+ function evaluateTimeRangeCommits(data, criteria) {
94
+ const hourlyData = data.timePattern?.hourly ?? [];
95
+ const startHour = criteria.startHour ?? 0;
96
+ const endHour = criteria.endHour ?? 24;
97
+ const threshold = criteria.threshold ?? 0;
98
+ let count = 0;
99
+ for (const hourEntry of hourlyData) {
100
+ if (hourEntry.hour >= startHour && hourEntry.hour < endHour) {
101
+ count += hourEntry.commitCount;
102
+ }
103
+ }
104
+ return {
105
+ earned: count >= threshold,
106
+ progress: progressPercent(count, threshold),
107
+ };
108
+ }
109
+ /**
110
+ * Evaluate night commits (after 9pm or before 5am)
111
+ */
112
+ function evaluateNightCommits(data, criteria) {
113
+ const hourlyData = data.timePattern?.hourly ?? [];
114
+ const threshold = criteria.threshold ?? 0;
115
+ let count = 0;
116
+ for (const hourEntry of hourlyData) {
117
+ // Night hours: 21, 22, 23, 0, 1, 2, 3, 4
118
+ if (hourEntry.hour >= 21 || hourEntry.hour < 5) {
119
+ count += hourEntry.commitCount;
120
+ }
121
+ }
122
+ return {
123
+ earned: count >= threshold,
124
+ progress: progressPercent(count, threshold),
125
+ };
126
+ }
127
+ /**
128
+ * Evaluate chronotype match
129
+ */
130
+ function evaluateChronotype(data, criteria) {
131
+ const chronotype = data.timePattern?.chronotype ?? '';
132
+ const targetValue = criteria.value ?? '';
133
+ const earned = chronotype.toLowerCase() === targetValue.toLowerCase();
134
+ return {
135
+ earned,
136
+ progress: earned ? 100 : 0,
137
+ };
138
+ }
139
+ /**
140
+ * Evaluate work-life balance score
141
+ */
142
+ function evaluateWorkLifeScore(data, criteria) {
143
+ const score = data.timePattern?.workLifeBalance?.score ?? 0;
144
+ const threshold = criteria.threshold ?? 0;
145
+ return {
146
+ earned: score >= threshold,
147
+ progress: progressPercent(score, threshold),
148
+ };
149
+ }
150
+ /**
151
+ * Evaluate if any commit was made at exactly midnight
152
+ */
153
+ function evaluateMidnightCommit(data) {
154
+ const commits = data.commits ?? [];
155
+ const hasMidnightCommit = commits.some((commit) => {
156
+ const date = new Date(commit.date);
157
+ return date.getHours() === 0 && date.getMinutes() === 0;
158
+ });
159
+ return {
160
+ earned: hasMidnightCommit,
161
+ progress: hasMidnightCommit ? 100 : 0,
162
+ };
163
+ }
164
+ /**
165
+ * Evaluate weekend commit percentage
166
+ */
167
+ function evaluateWeekendPercentage(data, criteria) {
168
+ const commits = data.commits ?? [];
169
+ const threshold = criteria.threshold ?? 0;
170
+ if (commits.length === 0) {
171
+ return { earned: false, progress: 0 };
172
+ }
173
+ const weekendCommits = commits.filter((commit) => {
174
+ const day = new Date(commit.date).getDay();
175
+ return day === 0 || day === 6;
176
+ }).length;
177
+ const percentage = (weekendCommits / commits.length) * 100;
178
+ return {
179
+ earned: percentage >= threshold,
180
+ progress: progressPercent(percentage, threshold),
181
+ };
182
+ }
183
+ /**
184
+ * Evaluate badge count for meta achievements
185
+ */
186
+ function evaluateBadgeCount(earnedCount, criteria) {
187
+ const threshold = criteria.threshold ?? 0;
188
+ return {
189
+ earned: earnedCount >= threshold,
190
+ progress: progressPercent(earnedCount, threshold),
191
+ };
192
+ }
193
+ /**
194
+ * Registry of all evaluator functions by criteria type
195
+ */
196
+ const evaluators = {
197
+ 'commit-count': evaluateCommitCount,
198
+ 'exact-commit-count': evaluateExactCommitCount,
199
+ streak: evaluateStreak,
200
+ 'quality-score': evaluateQualityScore,
201
+ 'conventional-adherence': evaluateConventionalAdherence,
202
+ 'body-percentage': evaluateBodyPercentage,
203
+ 'time-range-commits': evaluateTimeRangeCommits,
204
+ 'night-commits': evaluateNightCommits,
205
+ chronotype: evaluateChronotype,
206
+ 'work-life-score': evaluateWorkLifeScore,
207
+ 'midnight-commit': evaluateMidnightCommit,
208
+ 'weekend-percentage': evaluateWeekendPercentage,
209
+ };
210
+ /**
211
+ * Evaluate an achievement criteria against analysis data
212
+ * @param data Analysis data to evaluate against
213
+ * @param criteria The criteria to evaluate
214
+ * @returns Evaluation result with earned status and progress
215
+ */
216
+ function evaluate(data, criteria) {
217
+ const evaluator = evaluators[criteria.type];
218
+ if (!evaluator) {
219
+ console.warn(`Unknown criteria type: ${criteria.type}`);
220
+ return { earned: false, progress: 0 };
221
+ }
222
+ return evaluator(data, criteria);
223
+ }
224
+ /**
225
+ * Evaluate badge-count criteria (for meta achievements)
226
+ * This is separate because it depends on the count of earned achievements,
227
+ * not on the raw analysis data.
228
+ * @param earnedCount Number of achievements already earned
229
+ * @param criteria The criteria to evaluate
230
+ * @returns Evaluation result with earned status and progress
231
+ */
232
+ function evaluateMeta(earnedCount, criteria) {
233
+ if (criteria.type !== 'badge-count') {
234
+ console.warn(`evaluateMeta only supports badge-count criteria, got: ${criteria.type}`);
235
+ return { earned: false, progress: 0 };
236
+ }
237
+ return evaluateBadgeCount(earnedCount, criteria);
238
+ }
239
+ /**
240
+ * Check if a criteria type is a meta achievement type
241
+ * @param type The criteria type to check
242
+ * @returns True if this is a meta achievement type
243
+ */
244
+ function isMetaCriteria(type) {
245
+ return type === 'badge-count';
246
+ }
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * Achievement Helper Functions
4
+ *
5
+ * Utility functions for achievement display formatting.
6
+ * Achievement data is now loaded from src/data/achievements.json
7
+ * via the achievementLoader module.
8
+ *
9
+ * @module achievementDefinitions
10
+ * @deprecated Import from achievementLoader for achievement data
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.getTierColor = getTierColor;
14
+ exports.getCategoryLabel = getCategoryLabel;
15
+ /**
16
+ * Get the display color for an achievement tier
17
+ * @param tier Achievement tier level
18
+ * @returns CSS color value for the tier
19
+ */
20
+ function getTierColor(tier) {
21
+ switch (tier) {
22
+ case 'bronze':
23
+ return '#cd7f32';
24
+ case 'silver':
25
+ return '#c0c0c0';
26
+ case 'gold':
27
+ return '#ffd700';
28
+ case 'platinum':
29
+ return '#e5e4e2';
30
+ case 'legendary':
31
+ return '#ff6b6b';
32
+ default:
33
+ return '#8b949e';
34
+ }
35
+ }
36
+ /**
37
+ * Get the display label for an achievement category
38
+ * @param category Achievement category
39
+ * @returns Formatted label with emoji
40
+ */
41
+ function getCategoryLabel(category) {
42
+ switch (category) {
43
+ case 'milestone':
44
+ return '🎯 Milestone';
45
+ case 'quality':
46
+ return '🎨 Quality';
47
+ case 'collaboration':
48
+ return '🤝 Collaboration';
49
+ case 'time':
50
+ return '⏰ Time & Consistency';
51
+ case 'special':
52
+ return '🎮 Special';
53
+ case 'meta':
54
+ return '🏆 Meta';
55
+ default:
56
+ return category;
57
+ }
58
+ }
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ /**
3
+ * Achievements Feature
4
+ *
5
+ * Self-contained achievement system including:
6
+ * - Data: JSON achievement definitions
7
+ * - Types: Achievement interfaces
8
+ * - Engine: Processing and evaluation
9
+ * - Template: HTML rendering
10
+ *
11
+ * @module features/achievements
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
25
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
26
+ };
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.buildAchievementsSection = exports.getCategoryLabel = exports.getTierColor = exports.isMetaCriteria = exports.evaluateMeta = exports.evaluate = exports.getTotalAchievementCount = exports.getMetaAchievements = exports.getNonMetaAchievements = exports.getAchievementsByTier = exports.getDefinitionsByCategory = exports.getAchievementById = exports.loadAchievementDefinitions = exports.getNextMilestone = exports.getAchievementsByCategory = exports.getRecentAchievements = exports.checkAchievements = void 0;
29
+ // Types
30
+ __exportStar(require("./types"), exports);
31
+ // Engine & Processing
32
+ var engine_1 = require("./engine");
33
+ Object.defineProperty(exports, "checkAchievements", { enumerable: true, get: function () { return engine_1.checkAchievements; } });
34
+ Object.defineProperty(exports, "getRecentAchievements", { enumerable: true, get: function () { return engine_1.getRecentAchievements; } });
35
+ Object.defineProperty(exports, "getAchievementsByCategory", { enumerable: true, get: function () { return engine_1.getAchievementsByCategory; } });
36
+ Object.defineProperty(exports, "getNextMilestone", { enumerable: true, get: function () { return engine_1.getNextMilestone; } });
37
+ // Loader
38
+ var loader_1 = require("./loader");
39
+ Object.defineProperty(exports, "loadAchievementDefinitions", { enumerable: true, get: function () { return loader_1.loadAchievementDefinitions; } });
40
+ Object.defineProperty(exports, "getAchievementById", { enumerable: true, get: function () { return loader_1.getAchievementById; } });
41
+ Object.defineProperty(exports, "getDefinitionsByCategory", { enumerable: true, get: function () { return loader_1.getAchievementsByCategory; } });
42
+ Object.defineProperty(exports, "getAchievementsByTier", { enumerable: true, get: function () { return loader_1.getAchievementsByTier; } });
43
+ Object.defineProperty(exports, "getNonMetaAchievements", { enumerable: true, get: function () { return loader_1.getNonMetaAchievements; } });
44
+ Object.defineProperty(exports, "getMetaAchievements", { enumerable: true, get: function () { return loader_1.getMetaAchievements; } });
45
+ Object.defineProperty(exports, "getTotalAchievementCount", { enumerable: true, get: function () { return loader_1.getTotalAchievementCount; } });
46
+ // Evaluators
47
+ var evaluators_1 = require("./evaluators");
48
+ Object.defineProperty(exports, "evaluate", { enumerable: true, get: function () { return evaluators_1.evaluate; } });
49
+ Object.defineProperty(exports, "evaluateMeta", { enumerable: true, get: function () { return evaluators_1.evaluateMeta; } });
50
+ Object.defineProperty(exports, "isMetaCriteria", { enumerable: true, get: function () { return evaluators_1.isMetaCriteria; } });
51
+ // Helpers
52
+ var helpers_1 = require("./helpers");
53
+ Object.defineProperty(exports, "getTierColor", { enumerable: true, get: function () { return helpers_1.getTierColor; } });
54
+ Object.defineProperty(exports, "getCategoryLabel", { enumerable: true, get: function () { return helpers_1.getCategoryLabel; } });
55
+ // Template
56
+ var template_1 = require("./template");
57
+ Object.defineProperty(exports, "buildAchievementsSection", { enumerable: true, get: function () { return template_1.buildAchievementsSection; } });
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ /**
3
+ * Achievement Loader Module
4
+ *
5
+ * Loads achievement definitions from JSON and constructs Achievement objects.
6
+ * This separates data (JSON) from logic (evaluators).
7
+ *
8
+ * @module achievementLoader
9
+ */
10
+ var __importDefault = (this && this.__importDefault) || function (mod) {
11
+ return (mod && mod.__esModule) ? mod : { "default": mod };
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.loadAchievementDefinitions = loadAchievementDefinitions;
15
+ exports.getAchievementById = getAchievementById;
16
+ exports.getAchievementsByCategory = getAchievementsByCategory;
17
+ exports.getAchievementsByTier = getAchievementsByTier;
18
+ exports.getNonMetaAchievements = getNonMetaAchievements;
19
+ exports.getMetaAchievements = getMetaAchievements;
20
+ exports.createRuntimeAchievement = createRuntimeAchievement;
21
+ exports.getTotalAchievementCount = getTotalAchievementCount;
22
+ const achievements_json_1 = __importDefault(require("./data/achievements.json"));
23
+ /**
24
+ * Load all achievement definitions from JSON
25
+ * @returns Array of achievement definitions
26
+ */
27
+ function loadAchievementDefinitions() {
28
+ return achievements_json_1.default.achievements;
29
+ }
30
+ /**
31
+ * Get achievement definition by ID
32
+ * @param id Achievement ID to find
33
+ * @returns Achievement definition or undefined
34
+ */
35
+ function getAchievementById(id) {
36
+ return loadAchievementDefinitions().find((a) => a.id === id);
37
+ }
38
+ /**
39
+ * Get achievements by category
40
+ * @param category Category to filter by
41
+ * @returns Array of achievements in that category
42
+ */
43
+ function getAchievementsByCategory(category) {
44
+ return loadAchievementDefinitions().filter((a) => a.category === category);
45
+ }
46
+ /**
47
+ * Get achievements by tier
48
+ * @param tier Tier to filter by
49
+ * @returns Array of achievements at that tier
50
+ */
51
+ function getAchievementsByTier(tier) {
52
+ return loadAchievementDefinitions().filter((a) => a.tier === tier);
53
+ }
54
+ /**
55
+ * Get all non-meta achievements (for evaluating before meta achievements)
56
+ * @returns Array of non-meta achievements
57
+ */
58
+ function getNonMetaAchievements() {
59
+ return loadAchievementDefinitions().filter((a) => a.category !== 'meta');
60
+ }
61
+ /**
62
+ * Get all meta achievements (evaluated last, based on badge count)
63
+ * @returns Array of meta achievements
64
+ */
65
+ function getMetaAchievements() {
66
+ return loadAchievementDefinitions().filter((a) => a.category === 'meta');
67
+ }
68
+ /**
69
+ * Create a runtime achievement from a definition
70
+ * @param definition Achievement definition from JSON
71
+ * @returns LoadedAchievement with default runtime state
72
+ */
73
+ function createRuntimeAchievement(definition) {
74
+ return {
75
+ ...definition,
76
+ progress: 0,
77
+ isUnlocked: false,
78
+ earnedDate: undefined,
79
+ rarity: undefined,
80
+ };
81
+ }
82
+ /**
83
+ * Get total count of all achievements
84
+ * @returns Total number of achievements
85
+ */
86
+ function getTotalAchievementCount() {
87
+ return loadAchievementDefinitions().length;
88
+ }
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildAchievementsSection = buildAchievementsSection;
4
+ // Helper: Build SVG progress ring
5
+ function buildProgressRing(progress, size = 50) {
6
+ const radius = (size / 2) - 4;
7
+ const circumference = 2 * Math.PI * radius;
8
+ const offset = circumference * (1 - progress / 100);
9
+ return `
10
+ <svg class="progress-ring" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">
11
+ <circle class="progress-ring-bg" cx="${size / 2}" cy="${size / 2}" r="${radius}"
12
+ fill="none" stroke="var(--border-subtle)" stroke-width="3" />
13
+ <circle class="progress-ring-fill" cx="${size / 2}" cy="${size / 2}" r="${radius}"
14
+ fill="none" stroke="var(--accent-blue)" stroke-width="3"
15
+ stroke-dasharray="${circumference}"
16
+ stroke-dashoffset="${offset}"
17
+ stroke-linecap="round"
18
+ transform="rotate(-90 ${size / 2} ${size / 2})" />
19
+ </svg>
20
+ `;
21
+ }
22
+ // Helper: Build individual achievement card
23
+ function buildAchievementCard(achievement) {
24
+ const cardClass = achievement.isUnlocked ? 'unlocked' : 'locked';
25
+ const showProgress = !achievement.isUnlocked && achievement.progress > 0;
26
+ return `
27
+ <div class="achievement-card ${cardClass}">
28
+ ${showProgress ? `
29
+ <div class="achievement-ring-wrapper">
30
+ ${buildProgressRing(achievement.progress, 60)}
31
+ </div>
32
+ ` : ''}
33
+ <div class="achievement-emoji">${achievement.emoji}</div>
34
+ <div class="achievement-name">${achievement.name}</div>
35
+ ${!achievement.isSecret || achievement.isUnlocked ? `
36
+ <div class="achievement-description">${achievement.description}</div>
37
+ ` : `
38
+ <div class="achievement-description">???</div>
39
+ `}
40
+ <div class="badge-tier ${achievement.tier}">${achievement.tier}</div>
41
+ ${showProgress ? `
42
+ <div class="achievement-progress-text">${achievement.progress.toFixed(0)}%</div>
43
+ ` : ''}
44
+ </div>
45
+ `;
46
+ }
47
+ // Helper: Generate growth narrative
48
+ function buildGrowthNarrative(progress) {
49
+ const { unlockedCount, totalCount, completionPercentage, categories, nextMilestones } = progress;
50
+ // Find strongest category
51
+ let strongestCategory = '';
52
+ let strongestCount = 0;
53
+ if (categories && categories.length > 0) {
54
+ for (const cat of categories) {
55
+ if (cat.unlocked > strongestCount) {
56
+ strongestCount = cat.unlocked;
57
+ strongestCategory = cat.name;
58
+ }
59
+ }
60
+ }
61
+ // Get next milestone info
62
+ let nextMilestoneText = '';
63
+ if (nextMilestones && nextMilestones.length > 0) {
64
+ const next = nextMilestones[0];
65
+ const remaining = 100 - next.progress;
66
+ nextMilestoneText = `Next milestone: <strong>${next.name}</strong> — ${remaining.toFixed(0)}% to go.`;
67
+ }
68
+ return `
69
+ <div class="growth-narrative">
70
+ <h3>Your Developer Journey</h3>
71
+ <p class="narrative-text">
72
+ You've unlocked <strong>${unlockedCount} of ${totalCount}</strong> achievements (${completionPercentage.toFixed(0)}%).
73
+ ${strongestCategory ? `Your strongest area is <strong>${strongestCategory}</strong> with ${strongestCount} badges earned.` : ''}
74
+ ${nextMilestoneText}
75
+ </p>
76
+ </div>
77
+ `;
78
+ }
79
+ function buildAchievementsSection(achievementProgress) {
80
+ return `
81
+ <div class="achievements-section">
82
+ <h2>Achievements</h2>
83
+
84
+ ${buildGrowthNarrative(achievementProgress)}
85
+
86
+ <div class="achievement-stats">
87
+ <div class="stat-card">
88
+ <div class="stat-value">${achievementProgress.unlockedCount}</div>
89
+ <div class="stat-label">Badges Unlocked</div>
90
+ </div>
91
+ <div class="stat-card">
92
+ <div class="stat-value">${achievementProgress.completionPercentage.toFixed(0)}%</div>
93
+ <div class="stat-label">Completion</div>
94
+ </div>
95
+ <div class="stat-card">
96
+ <div class="stat-value">${achievementProgress.totalCount - achievementProgress.unlockedCount}</div>
97
+ <div class="stat-label">Remaining</div>
98
+ </div>
99
+ </div>
100
+
101
+ ${achievementProgress.nextMilestones && achievementProgress.nextMilestones.length > 0 ? `
102
+ <div class="next-milestones">
103
+ <h3>Next Milestones</h3>
104
+ ${achievementProgress.nextMilestones.slice(0, 3).map(milestone => `
105
+ <div class="milestone-item">
106
+ <div class="milestone-header">
107
+ <span class="milestone-emoji">${milestone.emoji}</span>
108
+ <span class="milestone-name">${milestone.name}</span>
109
+ </div>
110
+ <div class="milestone-description">${milestone.description}</div>
111
+ <div class="milestone-progress-bar">
112
+ <div class="milestone-progress-fill" style="width: ${milestone.progress}%"></div>
113
+ <div class="milestone-progress-text">${milestone.progress.toFixed(0)}%</div>
114
+ </div>
115
+ </div>
116
+ `).join('')}
117
+ </div>
118
+ ` : ''}
119
+
120
+ ${achievementProgress.newBadges && achievementProgress.newBadges.length > 0 ? `
121
+ <div class="new-badges">
122
+ <h3>Recently Unlocked</h3>
123
+ <div class="badge-list">
124
+ ${achievementProgress.newBadges.map(badge => `
125
+ <div class="badge-item-mini">${badge.emoji} ${badge.name}</div>
126
+ `).join('')}
127
+ </div>
128
+ </div>
129
+ ` : ''}
130
+
131
+ ${achievementProgress.categories ? `
132
+ <div class="achievement-categories">
133
+ ${achievementProgress.categories.map(category => `
134
+ <div class="category-section">
135
+ <h3>${category.emoji} ${category.name}</h3>
136
+ <div class="category-progress">
137
+ <div class="category-bar">
138
+ <div class="category-fill" style="width: ${category.progress}%"></div>
139
+ </div>
140
+ <span class="category-count">${category.unlocked}/${category.total}</span>
141
+ </div>
142
+ <div class="achievement-grid">
143
+ ${category.achievements.map(achievement => buildAchievementCard(achievement)).join('')}
144
+ </div>
145
+ </div>
146
+ `).join('')}
147
+ </div>
148
+ ` : achievementProgress.achievements && achievementProgress.achievements.length > 0 ? `
149
+ <div class="achievements-grid">
150
+ ${achievementProgress.achievements.map(achievement => buildAchievementCard(achievement)).join('')}
151
+ </div>
152
+ ` : ''}
153
+ </div>
154
+ `;
155
+ }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Achievement system types.
4
+ *
5
+ * @module types/achievements
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });