* Convert ProcessedStats to ClaudeCodeStats. * Used for filtered date ranges that bypass the cache.
( stats: ProcessedStats, )
| 747 | * Used for filtered date ranges that bypass the cache. |
| 748 | */ |
| 749 | function processedStatsToClaudeCodeStats( |
| 750 | stats: ProcessedStats, |
| 751 | ): ClaudeCodeStats { |
| 752 | const dailyActivitySorted = stats.dailyActivity |
| 753 | .slice() |
| 754 | .sort((a, b) => a.date.localeCompare(b.date)) |
| 755 | const dailyModelTokensSorted = stats.dailyModelTokens |
| 756 | .slice() |
| 757 | .sort((a, b) => a.date.localeCompare(b.date)) |
| 758 | |
| 759 | // Calculate streaks from daily activity |
| 760 | const streaks = calculateStreaks(dailyActivitySorted) |
| 761 | |
| 762 | // Find longest session |
| 763 | let longestSession: SessionStats | null = null |
| 764 | for (const session of stats.sessionStats) { |
| 765 | if (!longestSession || session.duration > longestSession.duration) { |
| 766 | longestSession = session |
| 767 | } |
| 768 | } |
| 769 | |
| 770 | // Find first/last session dates |
| 771 | let firstSessionDate: string | null = null |
| 772 | let lastSessionDate: string | null = null |
| 773 | for (const session of stats.sessionStats) { |
| 774 | if (!firstSessionDate || session.timestamp < firstSessionDate) { |
| 775 | firstSessionDate = session.timestamp |
| 776 | } |
| 777 | if (!lastSessionDate || session.timestamp > lastSessionDate) { |
| 778 | lastSessionDate = session.timestamp |
| 779 | } |
| 780 | } |
| 781 | |
| 782 | // Peak activity day |
| 783 | const peakActivityDay = |
| 784 | dailyActivitySorted.length > 0 |
| 785 | ? dailyActivitySorted.reduce((max, d) => |
| 786 | d.messageCount > max.messageCount ? d : max, |
| 787 | ).date |
| 788 | : null |
| 789 | |
| 790 | // Peak activity hour |
| 791 | const hourEntries = Object.entries(stats.hourCounts) |
| 792 | const peakActivityHour = |
| 793 | hourEntries.length > 0 |
| 794 | ? parseInt( |
| 795 | hourEntries.reduce((max, [hour, count]) => |
| 796 | count > parseInt(max[1].toString(), 10) ? [hour, count] : max, |
| 797 | )[0], |
| 798 | 10, |
| 799 | ) |
| 800 | : null |
| 801 | |
| 802 | // Total days in range |
| 803 | const totalDays = |
| 804 | firstSessionDate && lastSessionDate |
| 805 | ? Math.ceil( |
| 806 | (new Date(lastSessionDate).getTime() - |
no test coverage detected