@boshu2/vibe-check 1.0.2 → 1.1.0
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.
- package/.agents/bundles/ml-learning-loop-complete-plan-2025-11-28.md +908 -0
- package/.agents/bundles/unified-vibe-system-plan-phase1-2025-11-28.md +962 -0
- package/.agents/bundles/unified-vibe-system-research-2025-11-28.md +1003 -0
- package/.agents/bundles/vibe-check-ecosystem-plan-2025-11-29.md +635 -0
- package/.agents/bundles/vibe-check-gamification-complete-2025-11-29.md +132 -0
- package/.agents/bundles/vibe-score-scientific-framework-2025-11-28.md +602 -0
- package/.vibe-check/calibration.json +38 -0
- package/.vibe-check/latest.json +114 -0
- package/CHANGELOG.md +38 -0
- package/CLAUDE.md +178 -0
- package/README.md +185 -7
- package/action.yml +270 -0
- package/dashboard/app.js +494 -0
- package/dashboard/index.html +235 -0
- package/dashboard/styles.css +647 -0
- package/dist/calibration/ece.d.ts +26 -0
- package/dist/calibration/ece.d.ts.map +1 -0
- package/dist/calibration/ece.js +93 -0
- package/dist/calibration/ece.js.map +1 -0
- package/dist/calibration/index.d.ts +3 -0
- package/dist/calibration/index.d.ts.map +1 -0
- package/dist/calibration/index.js +15 -0
- package/dist/calibration/index.js.map +1 -0
- package/dist/calibration/storage.d.ts +34 -0
- package/dist/calibration/storage.d.ts.map +1 -0
- package/dist/calibration/storage.js +188 -0
- package/dist/calibration/storage.js.map +1 -0
- package/dist/cli.js +30 -76
- package/dist/cli.js.map +1 -1
- package/dist/commands/analyze.d.ts +16 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +256 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/index.d.ts +4 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +11 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/level.d.ts +3 -0
- package/dist/commands/level.d.ts.map +1 -0
- package/dist/commands/level.js +277 -0
- package/dist/commands/level.js.map +1 -0
- package/dist/commands/profile.d.ts +4 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +143 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/gamification/achievements.d.ts +15 -0
- package/dist/gamification/achievements.d.ts.map +1 -0
- package/dist/gamification/achievements.js +273 -0
- package/dist/gamification/achievements.js.map +1 -0
- package/dist/gamification/index.d.ts +8 -0
- package/dist/gamification/index.d.ts.map +1 -0
- package/dist/gamification/index.js +30 -0
- package/dist/gamification/index.js.map +1 -0
- package/dist/gamification/profile.d.ts +46 -0
- package/dist/gamification/profile.d.ts.map +1 -0
- package/dist/gamification/profile.js +272 -0
- package/dist/gamification/profile.js.map +1 -0
- package/dist/gamification/streaks.d.ts +26 -0
- package/dist/gamification/streaks.d.ts.map +1 -0
- package/dist/gamification/streaks.js +132 -0
- package/dist/gamification/streaks.js.map +1 -0
- package/dist/gamification/types.d.ts +111 -0
- package/dist/gamification/types.d.ts.map +1 -0
- package/dist/gamification/types.js +26 -0
- package/dist/gamification/types.js.map +1 -0
- package/dist/gamification/xp.d.ts +37 -0
- package/dist/gamification/xp.d.ts.map +1 -0
- package/dist/gamification/xp.js +115 -0
- package/dist/gamification/xp.js.map +1 -0
- package/dist/git.d.ts +11 -0
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +52 -0
- package/dist/git.js.map +1 -1
- package/dist/metrics/code-stability.d.ts +13 -0
- package/dist/metrics/code-stability.d.ts.map +1 -0
- package/dist/metrics/code-stability.js +74 -0
- package/dist/metrics/code-stability.js.map +1 -0
- package/dist/metrics/file-churn.d.ts +8 -0
- package/dist/metrics/file-churn.d.ts.map +1 -0
- package/dist/metrics/file-churn.js +75 -0
- package/dist/metrics/file-churn.js.map +1 -0
- package/dist/metrics/time-spiral.d.ts +8 -0
- package/dist/metrics/time-spiral.d.ts.map +1 -0
- package/dist/metrics/time-spiral.js +69 -0
- package/dist/metrics/time-spiral.js.map +1 -0
- package/dist/metrics/velocity-anomaly.d.ts +13 -0
- package/dist/metrics/velocity-anomaly.d.ts.map +1 -0
- package/dist/metrics/velocity-anomaly.js +67 -0
- package/dist/metrics/velocity-anomaly.js.map +1 -0
- package/dist/output/index.d.ts +6 -3
- package/dist/output/index.d.ts.map +1 -1
- package/dist/output/index.js +4 -3
- package/dist/output/index.js.map +1 -1
- package/dist/output/json.d.ts +2 -2
- package/dist/output/json.d.ts.map +1 -1
- package/dist/output/json.js +54 -0
- package/dist/output/json.js.map +1 -1
- package/dist/output/markdown.d.ts +2 -2
- package/dist/output/markdown.d.ts.map +1 -1
- package/dist/output/markdown.js +34 -1
- package/dist/output/markdown.js.map +1 -1
- package/dist/output/terminal.d.ts +6 -2
- package/dist/output/terminal.d.ts.map +1 -1
- package/dist/output/terminal.js +131 -3
- package/dist/output/terminal.js.map +1 -1
- package/dist/recommend/index.d.ts +3 -0
- package/dist/recommend/index.d.ts.map +1 -0
- package/dist/recommend/index.js +14 -0
- package/dist/recommend/index.js.map +1 -0
- package/dist/recommend/ordered-logistic.d.ts +49 -0
- package/dist/recommend/ordered-logistic.d.ts.map +1 -0
- package/dist/recommend/ordered-logistic.js +153 -0
- package/dist/recommend/ordered-logistic.js.map +1 -0
- package/dist/recommend/questions.d.ts +19 -0
- package/dist/recommend/questions.d.ts.map +1 -0
- package/dist/recommend/questions.js +73 -0
- package/dist/recommend/questions.js.map +1 -0
- package/dist/score/index.d.ts +21 -0
- package/dist/score/index.d.ts.map +1 -0
- package/dist/score/index.js +48 -0
- package/dist/score/index.js.map +1 -0
- package/dist/score/weights.d.ts +16 -0
- package/dist/score/weights.d.ts.map +1 -0
- package/dist/score/weights.js +28 -0
- package/dist/score/weights.js.map +1 -0
- package/dist/types.d.ts +83 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +10 -9
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getProfileDir = getProfileDir;
|
|
37
|
+
exports.getProfilePath = getProfilePath;
|
|
38
|
+
exports.createInitialProfile = createInitialProfile;
|
|
39
|
+
exports.loadProfile = loadProfile;
|
|
40
|
+
exports.saveProfile = saveProfile;
|
|
41
|
+
exports.recordSession = recordSession;
|
|
42
|
+
exports.getAchievementCounts = getAchievementCounts;
|
|
43
|
+
exports.getRecentSessions = getRecentSessions;
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const os = __importStar(require("os"));
|
|
47
|
+
const streaks_1 = require("./streaks");
|
|
48
|
+
const xp_1 = require("./xp");
|
|
49
|
+
const achievements_1 = require("./achievements");
|
|
50
|
+
const PROFILE_DIR = '.vibe-check';
|
|
51
|
+
const PROFILE_FILE = 'profile.json';
|
|
52
|
+
/**
|
|
53
|
+
* Get profile directory path (in user's home directory)
|
|
54
|
+
*/
|
|
55
|
+
function getProfileDir() {
|
|
56
|
+
return path.join(os.homedir(), PROFILE_DIR);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get profile file path
|
|
60
|
+
*/
|
|
61
|
+
function getProfilePath() {
|
|
62
|
+
return path.join(getProfileDir(), PROFILE_FILE);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create initial profile
|
|
66
|
+
*/
|
|
67
|
+
function createInitialProfile() {
|
|
68
|
+
const now = new Date().toISOString();
|
|
69
|
+
return {
|
|
70
|
+
version: '1.0.0',
|
|
71
|
+
createdAt: now,
|
|
72
|
+
updatedAt: now,
|
|
73
|
+
streak: (0, streaks_1.createInitialStreak)(),
|
|
74
|
+
xp: (0, xp_1.createInitialXP)(),
|
|
75
|
+
achievements: [],
|
|
76
|
+
sessions: [],
|
|
77
|
+
preferences: {
|
|
78
|
+
weeklyGoal: 5,
|
|
79
|
+
showNotifications: true,
|
|
80
|
+
publicProfile: false,
|
|
81
|
+
},
|
|
82
|
+
stats: {
|
|
83
|
+
totalSessions: 0,
|
|
84
|
+
totalCommitsAnalyzed: 0,
|
|
85
|
+
avgVibeScore: 0,
|
|
86
|
+
bestVibeScore: 0,
|
|
87
|
+
totalSpiralsDetected: 0,
|
|
88
|
+
spiralsAvoided: 0,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Load profile from disk
|
|
94
|
+
*/
|
|
95
|
+
function loadProfile() {
|
|
96
|
+
const filePath = getProfilePath();
|
|
97
|
+
if (fs.existsSync(filePath)) {
|
|
98
|
+
try {
|
|
99
|
+
const data = fs.readFileSync(filePath, 'utf-8');
|
|
100
|
+
const profile = JSON.parse(data);
|
|
101
|
+
return migrateProfile(profile);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return createInitialProfile();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return createInitialProfile();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Save profile to disk
|
|
111
|
+
*/
|
|
112
|
+
function saveProfile(profile) {
|
|
113
|
+
const dirPath = getProfileDir();
|
|
114
|
+
const filePath = getProfilePath();
|
|
115
|
+
if (!fs.existsSync(dirPath)) {
|
|
116
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
117
|
+
}
|
|
118
|
+
profile.updatedAt = new Date().toISOString();
|
|
119
|
+
fs.writeFileSync(filePath, JSON.stringify(profile, null, 2));
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Check if a period was already analyzed (to prevent XP gaming)
|
|
123
|
+
*/
|
|
124
|
+
function isPeriodDuplicate(sessions, periodFrom, periodTo) {
|
|
125
|
+
const fromTime = periodFrom.getTime();
|
|
126
|
+
const toTime = periodTo.getTime();
|
|
127
|
+
// Check recent sessions (last 50) for matching periods
|
|
128
|
+
const recentSessions = sessions.slice(-50);
|
|
129
|
+
for (const session of recentSessions) {
|
|
130
|
+
if (session.periodFrom && session.periodTo) {
|
|
131
|
+
const sessionFrom = new Date(session.periodFrom).getTime();
|
|
132
|
+
const sessionTo = new Date(session.periodTo).getTime();
|
|
133
|
+
// Check for exact match or significant overlap (>80%)
|
|
134
|
+
if (sessionFrom === fromTime && sessionTo === toTime) {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
// Check for significant overlap
|
|
138
|
+
const overlapStart = Math.max(fromTime, sessionFrom);
|
|
139
|
+
const overlapEnd = Math.min(toTime, sessionTo);
|
|
140
|
+
const overlap = Math.max(0, overlapEnd - overlapStart);
|
|
141
|
+
const currentDuration = toTime - fromTime;
|
|
142
|
+
if (currentDuration > 0 && overlap / currentDuration > 0.8) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Record a new session and update all gamification state
|
|
151
|
+
*/
|
|
152
|
+
function recordSession(vibeScore, overall, commits, spirals, periodFrom, periodTo) {
|
|
153
|
+
const profile = loadProfile();
|
|
154
|
+
const now = new Date();
|
|
155
|
+
// Check for duplicate period (anti-gaming)
|
|
156
|
+
const isDuplicate = periodFrom && periodTo
|
|
157
|
+
? isPeriodDuplicate(profile.sessions, periodFrom, periodTo)
|
|
158
|
+
: false;
|
|
159
|
+
if (isDuplicate) {
|
|
160
|
+
// Return current profile without awarding XP
|
|
161
|
+
return {
|
|
162
|
+
profile,
|
|
163
|
+
xpEarned: 0,
|
|
164
|
+
leveledUp: false,
|
|
165
|
+
achievementsUnlocked: [],
|
|
166
|
+
streakExtended: false,
|
|
167
|
+
isPersonalBest: false,
|
|
168
|
+
isDuplicate: true,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
// Update streak
|
|
172
|
+
const oldStreak = profile.streak.current;
|
|
173
|
+
profile.streak = (0, streaks_1.updateStreak)(profile.streak, now);
|
|
174
|
+
const streakExtended = profile.streak.current > oldStreak;
|
|
175
|
+
// Check achievements (before recording session)
|
|
176
|
+
const sessionRecord = {
|
|
177
|
+
date: now.toISOString().split('T')[0],
|
|
178
|
+
timestamp: now.toISOString(),
|
|
179
|
+
vibeScore,
|
|
180
|
+
overall,
|
|
181
|
+
commits,
|
|
182
|
+
spirals,
|
|
183
|
+
xpEarned: 0, // Will be updated
|
|
184
|
+
achievementsUnlocked: [],
|
|
185
|
+
periodFrom: periodFrom?.toISOString(),
|
|
186
|
+
periodTo: periodTo?.toISOString(),
|
|
187
|
+
};
|
|
188
|
+
const newAchievements = (0, achievements_1.checkAchievements)(profile.sessions, profile.streak, profile.xp, sessionRecord, profile.achievements.map(a => a.id));
|
|
189
|
+
// Calculate and add XP
|
|
190
|
+
const xpEarned = (0, xp_1.calculateSessionXP)(sessionRecord, profile.streak, newAchievements.length);
|
|
191
|
+
sessionRecord.xpEarned = xpEarned;
|
|
192
|
+
sessionRecord.achievementsUnlocked = newAchievements.map(a => a.id);
|
|
193
|
+
const { xp: newXP, leveledUp, newLevel } = (0, xp_1.addXP)(profile.xp, xpEarned);
|
|
194
|
+
profile.xp = newXP;
|
|
195
|
+
// Add achievements to profile
|
|
196
|
+
profile.achievements.push(...newAchievements);
|
|
197
|
+
// Add session to history (keep last 100)
|
|
198
|
+
profile.sessions.push(sessionRecord);
|
|
199
|
+
if (profile.sessions.length > 100) {
|
|
200
|
+
profile.sessions = profile.sessions.slice(-100);
|
|
201
|
+
}
|
|
202
|
+
// Update stats
|
|
203
|
+
const isPersonalBest = vibeScore > profile.stats.bestVibeScore;
|
|
204
|
+
profile.stats.totalSessions += 1;
|
|
205
|
+
profile.stats.totalCommitsAnalyzed += commits;
|
|
206
|
+
profile.stats.bestVibeScore = Math.max(profile.stats.bestVibeScore, vibeScore);
|
|
207
|
+
profile.stats.totalSpiralsDetected += spirals;
|
|
208
|
+
if (spirals === 0 && commits >= 10) {
|
|
209
|
+
profile.stats.spiralsAvoided += 1;
|
|
210
|
+
}
|
|
211
|
+
// Recalculate average
|
|
212
|
+
const allScores = profile.sessions.map(s => s.vibeScore);
|
|
213
|
+
profile.stats.avgVibeScore = Math.round(allScores.reduce((a, b) => a + b, 0) / allScores.length);
|
|
214
|
+
// Save profile
|
|
215
|
+
saveProfile(profile);
|
|
216
|
+
return {
|
|
217
|
+
profile,
|
|
218
|
+
xpEarned,
|
|
219
|
+
leveledUp,
|
|
220
|
+
newLevel: newLevel?.name,
|
|
221
|
+
achievementsUnlocked: newAchievements,
|
|
222
|
+
streakExtended,
|
|
223
|
+
isPersonalBest,
|
|
224
|
+
isDuplicate: false,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Migrate old profile versions
|
|
229
|
+
*/
|
|
230
|
+
function migrateProfile(profile) {
|
|
231
|
+
// Add migrations here as schema evolves
|
|
232
|
+
if (!profile.version) {
|
|
233
|
+
profile.version = '1.0.0';
|
|
234
|
+
}
|
|
235
|
+
// Ensure all fields exist
|
|
236
|
+
if (!profile.preferences) {
|
|
237
|
+
profile.preferences = {
|
|
238
|
+
weeklyGoal: 5,
|
|
239
|
+
showNotifications: true,
|
|
240
|
+
publicProfile: false,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
if (!profile.stats) {
|
|
244
|
+
profile.stats = {
|
|
245
|
+
totalSessions: profile.sessions?.length || 0,
|
|
246
|
+
totalCommitsAnalyzed: 0,
|
|
247
|
+
avgVibeScore: 0,
|
|
248
|
+
bestVibeScore: 0,
|
|
249
|
+
totalSpiralsDetected: 0,
|
|
250
|
+
spiralsAvoided: 0,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
return profile;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Get achievement counts
|
|
257
|
+
*/
|
|
258
|
+
function getAchievementCounts(profile) {
|
|
259
|
+
return {
|
|
260
|
+
unlocked: profile.achievements.length,
|
|
261
|
+
total: achievements_1.ACHIEVEMENTS.length,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Get recent sessions (last N days)
|
|
266
|
+
*/
|
|
267
|
+
function getRecentSessions(profile, days) {
|
|
268
|
+
const cutoff = new Date();
|
|
269
|
+
cutoff.setDate(cutoff.getDate() - days);
|
|
270
|
+
return profile.sessions.filter(s => new Date(s.date) >= cutoff);
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/gamification/profile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { StreakState } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Create initial streak state
|
|
4
|
+
*/
|
|
5
|
+
export declare function createInitialStreak(): StreakState;
|
|
6
|
+
/**
|
|
7
|
+
* Update streak based on new session
|
|
8
|
+
*/
|
|
9
|
+
export declare function updateStreak(streak: StreakState, sessionDate: Date): StreakState;
|
|
10
|
+
/**
|
|
11
|
+
* Check if streak is at risk (not checked in today)
|
|
12
|
+
*/
|
|
13
|
+
export declare function isStreakAtRisk(streak: StreakState): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Get days until streak expires
|
|
16
|
+
*/
|
|
17
|
+
export declare function getDaysUntilExpiry(streak: StreakState): number;
|
|
18
|
+
/**
|
|
19
|
+
* Format streak for display
|
|
20
|
+
*/
|
|
21
|
+
export declare function formatStreak(streak: StreakState): string;
|
|
22
|
+
/**
|
|
23
|
+
* Format weekly progress for display
|
|
24
|
+
*/
|
|
25
|
+
export declare function formatWeeklyProgress(streak: StreakState): string;
|
|
26
|
+
//# sourceMappingURL=streaks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaks.d.ts","sourceRoot":"","sources":["../../src/gamification/streaks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,WAAW,CASjD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,GAAG,WAAW,CAiDhF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAK3D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAc9D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAexD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAKhE"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createInitialStreak = createInitialStreak;
|
|
4
|
+
exports.updateStreak = updateStreak;
|
|
5
|
+
exports.isStreakAtRisk = isStreakAtRisk;
|
|
6
|
+
exports.getDaysUntilExpiry = getDaysUntilExpiry;
|
|
7
|
+
exports.formatStreak = formatStreak;
|
|
8
|
+
exports.formatWeeklyProgress = formatWeeklyProgress;
|
|
9
|
+
/**
|
|
10
|
+
* Create initial streak state
|
|
11
|
+
*/
|
|
12
|
+
function createInitialStreak() {
|
|
13
|
+
return {
|
|
14
|
+
current: 0,
|
|
15
|
+
longest: 0,
|
|
16
|
+
lastActiveDate: '',
|
|
17
|
+
weeklyGoal: 5,
|
|
18
|
+
weeklyProgress: 0,
|
|
19
|
+
freezesRemaining: 1,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Update streak based on new session
|
|
24
|
+
*/
|
|
25
|
+
function updateStreak(streak, sessionDate) {
|
|
26
|
+
const today = formatDate(sessionDate);
|
|
27
|
+
const yesterday = formatDate(new Date(sessionDate.getTime() - 24 * 60 * 60 * 1000));
|
|
28
|
+
const twoDaysAgo = formatDate(new Date(sessionDate.getTime() - 2 * 24 * 60 * 60 * 1000));
|
|
29
|
+
// Already checked in today
|
|
30
|
+
if (streak.lastActiveDate === today) {
|
|
31
|
+
return streak;
|
|
32
|
+
}
|
|
33
|
+
let newCurrent = streak.current;
|
|
34
|
+
let freezesRemaining = streak.freezesRemaining;
|
|
35
|
+
let lastFreezeUsed = streak.lastFreezeUsed;
|
|
36
|
+
if (streak.lastActiveDate === yesterday) {
|
|
37
|
+
// Consecutive day - extend streak
|
|
38
|
+
newCurrent = streak.current + 1;
|
|
39
|
+
}
|
|
40
|
+
else if (streak.lastActiveDate === twoDaysAgo && freezesRemaining > 0) {
|
|
41
|
+
// Missed one day but have freeze
|
|
42
|
+
newCurrent = streak.current + 1;
|
|
43
|
+
freezesRemaining -= 1;
|
|
44
|
+
lastFreezeUsed = yesterday;
|
|
45
|
+
}
|
|
46
|
+
else if (streak.lastActiveDate === '') {
|
|
47
|
+
// First ever session
|
|
48
|
+
newCurrent = 1;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// Streak broken
|
|
52
|
+
newCurrent = 1;
|
|
53
|
+
}
|
|
54
|
+
// Update weekly progress
|
|
55
|
+
const weekStart = getWeekStart(sessionDate);
|
|
56
|
+
const lastActiveWeekStart = streak.lastActiveDate
|
|
57
|
+
? getWeekStart(new Date(streak.lastActiveDate))
|
|
58
|
+
: '';
|
|
59
|
+
const weeklyProgress = weekStart === lastActiveWeekStart
|
|
60
|
+
? streak.weeklyProgress + (streak.lastActiveDate === today ? 0 : 1)
|
|
61
|
+
: 1;
|
|
62
|
+
return {
|
|
63
|
+
current: newCurrent,
|
|
64
|
+
longest: Math.max(streak.longest, newCurrent),
|
|
65
|
+
lastActiveDate: today,
|
|
66
|
+
weeklyGoal: streak.weeklyGoal,
|
|
67
|
+
weeklyProgress,
|
|
68
|
+
freezesRemaining,
|
|
69
|
+
lastFreezeUsed,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Check if streak is at risk (not checked in today)
|
|
74
|
+
*/
|
|
75
|
+
function isStreakAtRisk(streak) {
|
|
76
|
+
if (streak.current === 0)
|
|
77
|
+
return false;
|
|
78
|
+
const today = formatDate(new Date());
|
|
79
|
+
return streak.lastActiveDate !== today;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get days until streak expires
|
|
83
|
+
*/
|
|
84
|
+
function getDaysUntilExpiry(streak) {
|
|
85
|
+
if (streak.current === 0)
|
|
86
|
+
return 0;
|
|
87
|
+
const today = new Date();
|
|
88
|
+
today.setHours(0, 0, 0, 0);
|
|
89
|
+
const lastActive = new Date(streak.lastActiveDate);
|
|
90
|
+
lastActive.setHours(0, 0, 0, 0);
|
|
91
|
+
const diffDays = Math.floor((today.getTime() - lastActive.getTime()) / (24 * 60 * 60 * 1000));
|
|
92
|
+
if (diffDays === 0)
|
|
93
|
+
return 2; // Checked in today, expires day after tomorrow
|
|
94
|
+
if (diffDays === 1)
|
|
95
|
+
return 1; // Checked in yesterday, expires tomorrow
|
|
96
|
+
return 0; // Already expired or will expire today
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Format streak for display
|
|
100
|
+
*/
|
|
101
|
+
function formatStreak(streak) {
|
|
102
|
+
if (streak.current === 0) {
|
|
103
|
+
return 'No active streak';
|
|
104
|
+
}
|
|
105
|
+
const isPersonalBest = streak.current === streak.longest && streak.current > 1;
|
|
106
|
+
const fire = '🔥'.repeat(Math.min(streak.current, 5));
|
|
107
|
+
let text = `${fire} ${streak.current}-day streak`;
|
|
108
|
+
if (isPersonalBest && streak.current > 7) {
|
|
109
|
+
text += ' (Personal best!)';
|
|
110
|
+
}
|
|
111
|
+
return text;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Format weekly progress for display
|
|
115
|
+
*/
|
|
116
|
+
function formatWeeklyProgress(streak) {
|
|
117
|
+
const filled = '█'.repeat(streak.weeklyProgress);
|
|
118
|
+
const empty = '░'.repeat(Math.max(0, streak.weeklyGoal - streak.weeklyProgress));
|
|
119
|
+
return `${streak.weeklyProgress}/${streak.weeklyGoal} days ${filled}${empty}`;
|
|
120
|
+
}
|
|
121
|
+
// Helper functions
|
|
122
|
+
function formatDate(date) {
|
|
123
|
+
return date.toISOString().split('T')[0];
|
|
124
|
+
}
|
|
125
|
+
function getWeekStart(date) {
|
|
126
|
+
const d = new Date(date);
|
|
127
|
+
const day = d.getDay();
|
|
128
|
+
const diff = d.getDate() - day + (day === 0 ? -6 : 1); // Monday start
|
|
129
|
+
d.setDate(diff);
|
|
130
|
+
return formatDate(d);
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=streaks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaks.js","sourceRoot":"","sources":["../../src/gamification/streaks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
export interface StreakState {
|
|
2
|
+
current: number;
|
|
3
|
+
longest: number;
|
|
4
|
+
lastActiveDate: string;
|
|
5
|
+
weeklyGoal: number;
|
|
6
|
+
weeklyProgress: number;
|
|
7
|
+
freezesRemaining: number;
|
|
8
|
+
lastFreezeUsed?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface XPState {
|
|
11
|
+
total: number;
|
|
12
|
+
level: number;
|
|
13
|
+
levelName: string;
|
|
14
|
+
currentLevelXP: number;
|
|
15
|
+
nextLevelXP: number;
|
|
16
|
+
lastSessionXP: number;
|
|
17
|
+
}
|
|
18
|
+
export interface Achievement {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
icon: string;
|
|
23
|
+
category: 'streak' | 'score' | 'sessions' | 'special';
|
|
24
|
+
condition: string;
|
|
25
|
+
unlockedAt?: string;
|
|
26
|
+
progress?: number;
|
|
27
|
+
hidden?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface SessionRecord {
|
|
30
|
+
date: string;
|
|
31
|
+
timestamp: string;
|
|
32
|
+
vibeScore: number;
|
|
33
|
+
overall: 'ELITE' | 'HIGH' | 'MEDIUM' | 'LOW';
|
|
34
|
+
commits: number;
|
|
35
|
+
spirals: number;
|
|
36
|
+
xpEarned: number;
|
|
37
|
+
achievementsUnlocked: string[];
|
|
38
|
+
periodFrom?: string;
|
|
39
|
+
periodTo?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface UserProfile {
|
|
42
|
+
version: string;
|
|
43
|
+
createdAt: string;
|
|
44
|
+
updatedAt: string;
|
|
45
|
+
streak: StreakState;
|
|
46
|
+
xp: XPState;
|
|
47
|
+
achievements: Achievement[];
|
|
48
|
+
sessions: SessionRecord[];
|
|
49
|
+
preferences: {
|
|
50
|
+
weeklyGoal: number;
|
|
51
|
+
showNotifications: boolean;
|
|
52
|
+
publicProfile: boolean;
|
|
53
|
+
};
|
|
54
|
+
stats: {
|
|
55
|
+
totalSessions: number;
|
|
56
|
+
totalCommitsAnalyzed: number;
|
|
57
|
+
avgVibeScore: number;
|
|
58
|
+
bestVibeScore: number;
|
|
59
|
+
totalSpiralsDetected: number;
|
|
60
|
+
spiralsAvoided: number;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export declare const LEVELS: readonly [{
|
|
64
|
+
readonly level: 1;
|
|
65
|
+
readonly name: "Novice";
|
|
66
|
+
readonly icon: "🌱";
|
|
67
|
+
readonly minXP: 0;
|
|
68
|
+
readonly maxXP: 100;
|
|
69
|
+
}, {
|
|
70
|
+
readonly level: 2;
|
|
71
|
+
readonly name: "Apprentice";
|
|
72
|
+
readonly icon: "🌿";
|
|
73
|
+
readonly minXP: 100;
|
|
74
|
+
readonly maxXP: 300;
|
|
75
|
+
}, {
|
|
76
|
+
readonly level: 3;
|
|
77
|
+
readonly name: "Practitioner";
|
|
78
|
+
readonly icon: "🌳";
|
|
79
|
+
readonly minXP: 300;
|
|
80
|
+
readonly maxXP: 600;
|
|
81
|
+
}, {
|
|
82
|
+
readonly level: 4;
|
|
83
|
+
readonly name: "Expert";
|
|
84
|
+
readonly icon: "🌲";
|
|
85
|
+
readonly minXP: 600;
|
|
86
|
+
readonly maxXP: 1000;
|
|
87
|
+
}, {
|
|
88
|
+
readonly level: 5;
|
|
89
|
+
readonly name: "Master";
|
|
90
|
+
readonly icon: "🎋";
|
|
91
|
+
readonly minXP: 1000;
|
|
92
|
+
readonly maxXP: 2000;
|
|
93
|
+
}, {
|
|
94
|
+
readonly level: 6;
|
|
95
|
+
readonly name: "Grandmaster";
|
|
96
|
+
readonly icon: "🏔️";
|
|
97
|
+
readonly minXP: 2000;
|
|
98
|
+
readonly maxXP: number;
|
|
99
|
+
}];
|
|
100
|
+
export declare const XP_REWARDS: {
|
|
101
|
+
readonly dailyCheckIn: 10;
|
|
102
|
+
readonly eliteSession: 50;
|
|
103
|
+
readonly highSession: 25;
|
|
104
|
+
readonly mediumSession: 10;
|
|
105
|
+
readonly lowSession: 5;
|
|
106
|
+
readonly streakBonus: 5;
|
|
107
|
+
readonly achievementBase: 25;
|
|
108
|
+
readonly noSpirals: 15;
|
|
109
|
+
readonly perfectTrust: 20;
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/gamification/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAElB,MAAM,EAAE,WAAW,CAAC;IACpB,EAAE,EAAE,OAAO,CAAC;IACZ,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAG1B,WAAW,EAAE;QACX,UAAU,EAAE,MAAM,CAAC;QACnB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,aAAa,EAAE,OAAO,CAAC;KACxB,CAAC;IAGF,KAAK,EAAE;QACL,aAAa,EAAE,MAAM,CAAC;QACtB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAGD,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOT,CAAC;AAGX,eAAO,MAAM,UAAU;;;;;;;;;;CAUb,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Gamification Types for Vibe-Check
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.XP_REWARDS = exports.LEVELS = void 0;
|
|
5
|
+
// Level progression
|
|
6
|
+
exports.LEVELS = [
|
|
7
|
+
{ level: 1, name: 'Novice', icon: '🌱', minXP: 0, maxXP: 100 },
|
|
8
|
+
{ level: 2, name: 'Apprentice', icon: '🌿', minXP: 100, maxXP: 300 },
|
|
9
|
+
{ level: 3, name: 'Practitioner', icon: '🌳', minXP: 300, maxXP: 600 },
|
|
10
|
+
{ level: 4, name: 'Expert', icon: '🌲', minXP: 600, maxXP: 1000 },
|
|
11
|
+
{ level: 5, name: 'Master', icon: '🎋', minXP: 1000, maxXP: 2000 },
|
|
12
|
+
{ level: 6, name: 'Grandmaster', icon: '🏔️', minXP: 2000, maxXP: Infinity },
|
|
13
|
+
];
|
|
14
|
+
// XP rewards
|
|
15
|
+
exports.XP_REWARDS = {
|
|
16
|
+
dailyCheckIn: 10,
|
|
17
|
+
eliteSession: 50,
|
|
18
|
+
highSession: 25,
|
|
19
|
+
mediumSession: 10,
|
|
20
|
+
lowSession: 5,
|
|
21
|
+
streakBonus: 5, // Per day of streak
|
|
22
|
+
achievementBase: 25, // Base for achievements
|
|
23
|
+
noSpirals: 15, // Bonus for 0 spirals
|
|
24
|
+
perfectTrust: 20, // 100% trust pass rate
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/gamification/types.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;AA0EpC,oBAAoB;AACP,QAAA,MAAM,GAAG;IACpB,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;IAC9D,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE;IACpE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE;IACtE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE;IACjE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IAClE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE;CACpE,CAAC;AAEX,aAAa;AACA,QAAA,UAAU,GAAG;IACxB,YAAY,EAAE,EAAE;IAChB,YAAY,EAAE,EAAE;IAChB,WAAW,EAAE,EAAE;IACf,aAAa,EAAE,EAAE;IACjB,UAAU,EAAE,CAAC;IACb,WAAW,EAAE,CAAC,EAAY,oBAAoB;IAC9C,eAAe,EAAE,EAAE,EAAO,wBAAwB;IAClD,SAAS,EAAE,EAAE,EAAa,sBAAsB;IAChD,YAAY,EAAE,EAAE,EAAU,uBAAuB;CACzC,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { XPState, LEVELS, SessionRecord, StreakState } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Create initial XP state
|
|
4
|
+
*/
|
|
5
|
+
export declare function createInitialXP(): XPState;
|
|
6
|
+
/**
|
|
7
|
+
* Calculate XP earned from a session
|
|
8
|
+
*/
|
|
9
|
+
export declare function calculateSessionXP(session: SessionRecord, streak: StreakState, achievementsUnlocked: number): number;
|
|
10
|
+
/**
|
|
11
|
+
* Add XP and handle level ups
|
|
12
|
+
*/
|
|
13
|
+
export declare function addXP(currentXP: XPState, earnedXP: number): {
|
|
14
|
+
xp: XPState;
|
|
15
|
+
leveledUp: boolean;
|
|
16
|
+
newLevel?: typeof LEVELS[number];
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Get level for given XP amount
|
|
20
|
+
*/
|
|
21
|
+
export declare function getLevelForXP(xp: number): {
|
|
22
|
+
level: number;
|
|
23
|
+
levelInfo: typeof LEVELS[number];
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Format XP progress for display
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatXPProgress(xp: XPState): string;
|
|
29
|
+
/**
|
|
30
|
+
* Format level for compact display
|
|
31
|
+
*/
|
|
32
|
+
export declare function formatLevel(xp: XPState): string;
|
|
33
|
+
/**
|
|
34
|
+
* Get progress percentage to next level
|
|
35
|
+
*/
|
|
36
|
+
export declare function getLevelProgress(xp: XPState): number;
|
|
37
|
+
//# sourceMappingURL=xp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xp.d.ts","sourceRoot":"","sources":["../../src/gamification/xp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAc,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAElF;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CASzC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,WAAW,EACnB,oBAAoB,EAAE,MAAM,GAC3B,MAAM,CAkCR;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAA;CAAE,CAoBjI;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAA;CAAE,CAO7F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CAUpD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CAG/C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CAGpD"}
|