This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

a MAFs and DAFs

+66 -3
+55 -2
app/src/app/api/bluesky/stats/route.ts
··· 130 130 flushesPerDay = parseFloat(((totalCount || 0) / activeDaysCount).toFixed(1)); 131 131 } 132 132 133 + // Calculate Monthly Active Flushers (MAFs) 134 + // This is the number of unique DIDs that have posted at least once in the past 30 days 135 + const thirtyDaysAgo = new Date(); 136 + thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30); 137 + 138 + // Filter records to get only those from the last 30 days 139 + const recentRecords = dailyData?.filter(entry => 140 + new Date(entry.created_at) >= thirtyDaysAgo 141 + ); 142 + 143 + // Get unique DIDs from recent records 144 + const recentUniqueDids = new Set<string>(); 145 + recentRecords?.forEach(entry => { 146 + if (entry.did) { 147 + recentUniqueDids.add(entry.did); 148 + } 149 + }); 150 + 151 + const monthlyActiveFlushers = recentUniqueDids.size; 152 + console.log(`Monthly Active Flushers (last 30 days): ${monthlyActiveFlushers}`); 153 + 154 + // Calculate Daily Active Flushers (DAFs) 155 + // This is the average number of unique users who post per day over the last 30 days 156 + const dailyActiveUserCounts = new Map<string, Set<string>>(); 157 + 158 + // Group users by day 159 + recentRecords?.forEach(entry => { 160 + const date = new Date(entry.created_at); 161 + const dateKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`; 162 + 163 + if (!dailyActiveUserCounts.has(dateKey)) { 164 + dailyActiveUserCounts.set(dateKey, new Set<string>()); 165 + } 166 + 167 + if (entry.did) { 168 + dailyActiveUserCounts.get(dateKey)!.add(entry.did); 169 + } 170 + }); 171 + 172 + // Calculate average daily active users 173 + let dailyActiveFlushers = 0; 174 + if (dailyActiveUserCounts.size > 0) { 175 + const totalDailyActiveUsers = Array.from(dailyActiveUserCounts.values()).reduce( 176 + (total, users) => total + users.size, 0 177 + ); 178 + dailyActiveFlushers = parseFloat((totalDailyActiveUsers / dailyActiveUserCounts.size).toFixed(1)); 179 + } 180 + console.log(`Daily Active Flushers (average over last 30 days): ${dailyActiveFlushers}`); 181 + 133 182 // 3. Get top flushers (leaderboard) - excluding test accounts 134 183 const { data: leaderboardData, error: leaderboardError } = await supabase 135 184 .from('flushing_records') ··· 194 243 chartData: chartData.slice(-30), // Last 30 days 195 244 leaderboard, 196 245 plumberFlushCount, 197 - totalFlushers 246 + totalFlushers, 247 + monthlyActiveFlushers, 248 + dailyActiveFlushers 198 249 }); 199 250 } else { 200 251 // If no Supabase credentials, return mock data ··· 204 255 chartData: generateMockChartData(), 205 256 leaderboard: generateMockLeaderboard(), 206 257 plumberFlushCount: 15, 207 - totalFlushers: 28 258 + totalFlushers: 28, 259 + monthlyActiveFlushers: 18, 260 + dailyActiveFlushers: 5.2 208 261 }); 209 262 } 210 263 } catch (error: any) {
+11 -1
app/src/app/stats/page.tsx
··· 13 13 leaderboard: { did: string; count: number; handle?: string }[]; 14 14 plumberFlushCount: number; 15 15 totalFlushers: number; 16 + monthlyActiveFlushers: number; 17 + dailyActiveFlushers: number; 16 18 } 17 19 18 20 export default function StatsPage() { ··· 185 187 <div className={styles.statValue}>{statsData.totalFlushers}</div> 186 188 <div className={styles.statLabel}>Total flushers</div> 187 189 </div> 190 + <div className={styles.statCard}> 191 + <div className={styles.statValue}>{statsData.monthlyActiveFlushers}</div> 192 + <div className={styles.statLabel}>Monthly active flushers</div> 193 + </div> 194 + <div className={styles.statCard}> 195 + <div className={styles.statValue}>{statsData.dailyActiveFlushers}</div> 196 + <div className={styles.statLabel}>Daily active flushers (avg)</div> 197 + </div> 188 198 </div> 189 199 </section> 190 200 ··· 262 272 className={styles.shareButton} 263 273 onClick={() => { 264 274 // Generate share text 265 - const statsText = `There have been ${statsData.totalCount} flushes by ${statsData.totalFlushers} unique users on @flushes.app! That's averaging ${statsData.flushesPerDay} flushes per active day. Check out the stats and leaderboard: https://flushes.app/stats`; 275 + const statsText = `There have been ${statsData.totalCount} flushes by ${statsData.totalFlushers} unique users on @flushes.app! We have ${statsData.monthlyActiveFlushers} monthly active flushers and ${statsData.dailyActiveFlushers} daily active flushers on average. Check out the stats: https://flushes.app/stats`; 266 276 window.open(`https://bsky.app/intent/compose?text=${encodeURIComponent(statsText)}`, '_blank'); 267 277 }} 268 278 >