atris 1.9.6 → 2.0.2

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.
@@ -0,0 +1,150 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ function analyticsAtris() {
5
+ const targetDir = path.join(process.cwd(), 'atris');
6
+
7
+ if (!fs.existsSync(targetDir)) {
8
+ console.log('✗ atris/ folder not found. Run "atris init" first.');
9
+ process.exit(1);
10
+ }
11
+
12
+ // Get date range (today + last 7 days)
13
+ const today = new Date();
14
+ const dates = [];
15
+ for (let i = 0; i < 7; i++) {
16
+ const date = new Date(today);
17
+ date.setDate(date.getDate() - i);
18
+ dates.push(date);
19
+ }
20
+
21
+ // Parse journals and collect data
22
+ let totalCompletions = 0;
23
+ let todayCompletions = 0;
24
+ let todayInbox = 0;
25
+ let oldestInbox = 0;
26
+ const completionsByDay = {};
27
+ const hourCounts = {};
28
+
29
+ dates.forEach((date, index) => {
30
+ const year = date.getFullYear();
31
+ // Use local timezone, not UTC (fixes timezone bug)
32
+ const month = String(date.getMonth() + 1).padStart(2, '0');
33
+ const day = String(date.getDate()).padStart(2, '0');
34
+ const dateFormatted = `${year}-${month}-${day}`;
35
+ const logPath = path.join(targetDir, 'logs', year.toString(), `${dateFormatted}.md`);
36
+
37
+ if (!fs.existsSync(logPath)) {
38
+ completionsByDay[dateFormatted] = 0;
39
+ return;
40
+ }
41
+
42
+ const content = fs.readFileSync(logPath, 'utf8');
43
+
44
+ // Count completions (C# pattern)
45
+ const completionMatches = content.match(/- \*\*C\d+:/g);
46
+ const completionCount = completionMatches ? completionMatches.length : 0;
47
+ completionsByDay[dateFormatted] = completionCount;
48
+ totalCompletions += completionCount;
49
+
50
+ if (index === 0) {
51
+ todayCompletions = completionCount;
52
+
53
+ // Count today's inbox
54
+ const inboxMatch = content.match(/## Inbox\n([\s\S]*?)(?=\n##|---)/);
55
+ if (inboxMatch && inboxMatch[1].trim()) {
56
+ const inboxMatches = inboxMatch[1].match(/- \*\*I\d+:/g);
57
+ todayInbox = inboxMatches ? inboxMatches.length : 0;
58
+ }
59
+ }
60
+
61
+ if (index === 6) {
62
+ // Count oldest day's inbox for trend
63
+ const inboxMatch = content.match(/## Inbox\n([\s\S]*?)(?=\n##|---)/);
64
+ if (inboxMatch && inboxMatch[1].trim()) {
65
+ const inboxMatches = inboxMatch[1].match(/- \*\*I\d+:/g);
66
+ oldestInbox = inboxMatches ? inboxMatches.length : 0;
67
+ }
68
+ }
69
+
70
+ // Parse timestamps for productivity hours
71
+ const timestampMatches = content.match(/\*\*(\d{2}):(\d{2}):(\d{2})\*\*/g);
72
+ if (timestampMatches) {
73
+ timestampMatches.forEach(ts => {
74
+ const hour = parseInt(ts.match(/\d{2}/)[0]);
75
+ hourCounts[hour] = (hourCounts[hour] || 0) + 1;
76
+ });
77
+ }
78
+ });
79
+
80
+ // Calculate metrics
81
+ const velocity = (totalCompletions / 7).toFixed(1);
82
+ const inboxTrend = todayInbox > oldestInbox ? 'Growing ⬆' :
83
+ todayInbox < oldestInbox ? 'Shrinking ⬇' :
84
+ 'Stable →';
85
+
86
+ // Find most productive hour
87
+ let mostProductiveHour = null;
88
+ let maxCount = 0;
89
+ Object.keys(hourCounts).forEach(hour => {
90
+ if (hourCounts[hour] > maxCount) {
91
+ maxCount = hourCounts[hour];
92
+ mostProductiveHour = hour;
93
+ }
94
+ });
95
+
96
+ const productiveHours = mostProductiveHour !== null ?
97
+ `${mostProductiveHour}:00 - ${(parseInt(mostProductiveHour) + 1) % 24}:00` :
98
+ 'No data';
99
+
100
+ // Display analytics
101
+ // Use local timezone, not UTC (fixes timezone bug)
102
+ const year = today.getFullYear();
103
+ const month = String(today.getMonth() + 1).padStart(2, '0');
104
+ const day = String(today.getDate()).padStart(2, '0');
105
+ const dateFormatted = `${year}-${month}-${day}`;
106
+ console.log('');
107
+ console.log('┌─────────────────────────────────────────────────────────────┐');
108
+ console.log(`│ ATRIS Analytics — ${dateFormatted}${' '.repeat(33 - dateFormatted.length)}│`);
109
+ console.log('└─────────────────────────────────────────────────────────────┘');
110
+ console.log('');
111
+
112
+ // Today's performance
113
+ console.log(`📊 Today's Performance`);
114
+ console.log(` Completions: ${todayCompletions}`);
115
+ console.log(` Inbox items: ${todayInbox}`);
116
+ console.log('');
117
+
118
+ // Weekly trends
119
+ console.log(`📈 Weekly Trends (Last 7 Days)`);
120
+ console.log(` Total completions: ${totalCompletions}`);
121
+ console.log(` Average velocity: ${velocity} completions/day`);
122
+ console.log(` Inbox trend: ${inboxTrend}`);
123
+ console.log('');
124
+
125
+ // Productivity patterns
126
+ console.log(`⏰ Productivity Patterns`);
127
+ console.log(` Most active hour: ${productiveHours}`);
128
+ console.log(` Activity count: ${maxCount} timestamps`);
129
+ console.log('');
130
+
131
+ // Daily breakdown
132
+ console.log(`📅 Daily Breakdown`);
133
+ const sortedDates = Object.keys(completionsByDay).sort().reverse();
134
+ sortedDates.forEach((date, index) => {
135
+ const count = completionsByDay[date];
136
+ const bar = '█'.repeat(count);
137
+ const label = index === 0 ? ' (today)' : '';
138
+ console.log(` ${date}: ${bar} ${count}${label}`);
139
+ });
140
+ console.log('');
141
+
142
+ console.log('─────────────────────────────────────────────────────────────');
143
+ console.log('💡 Insight: This data syncs to backend via "atris log sync"');
144
+ console.log('');
145
+ }
146
+
147
+
148
+ module.exports = {
149
+ analyticsAtris
150
+ };