1use serde::{Deserialize, Serialize};
12use std::collections::BTreeMap;
13
14use crate::constants::versions::STATS_SCHEMA_VERSION;
15use crate::timeutil;
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct ProductivityStats {
20 pub version: u32,
22 pub first_task_completed_at: Option<String>,
24 pub last_updated_at: String,
26 pub daily: BTreeMap<String, DayStats>,
28 pub streak: StreakInfo,
30 pub total_completed: u64,
32 pub milestones: Vec<Milestone>,
34}
35
36impl Default for ProductivityStats {
37 fn default() -> Self {
38 let now = timeutil::now_utc_rfc3339_or_fallback();
39 Self {
40 version: STATS_SCHEMA_VERSION,
41 first_task_completed_at: None,
42 last_updated_at: now,
43 daily: BTreeMap::new(),
44 streak: StreakInfo::default(),
45 total_completed: 0,
46 milestones: Vec::new(),
47 }
48 }
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, Default)]
53pub struct DayStats {
54 pub date: String,
55 pub completed_count: u32,
56 pub tasks: Vec<CompletedTaskRef>,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct CompletedTaskRef {
62 pub id: String,
63 pub title: String,
64 pub completed_at: String,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize, Default)]
69pub struct StreakInfo {
70 pub current_streak: u32,
71 pub longest_streak: u32,
72 pub last_completed_date: Option<String>,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct Milestone {
78 pub threshold: u64,
79 pub achieved_at: String,
80 pub celebrated: bool,
81}
82
83#[derive(Debug, Clone)]
85pub struct CompletionResult {
86 pub milestone_achieved: Option<u64>,
88 pub streak_updated: bool,
90 pub new_streak: u32,
92 pub total_completed: u64,
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct VelocityMetrics {
99 pub days: u32,
100 pub total_completed: u32,
101 pub average_per_day: f64,
102 pub best_day: Option<(String, u32)>,
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct EstimationMetrics {
108 pub tasks_analyzed: u32,
110 pub average_accuracy_ratio: f64,
113 pub median_accuracy_ratio: f64,
115 pub within_25_percent: f64,
117 pub average_absolute_error_minutes: f64,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
123pub struct TaskEstimationPoint {
124 pub task_id: String,
125 pub task_title: String,
126 pub estimated_minutes: u32,
127 pub actual_minutes: u32,
128 pub accuracy_ratio: f64,
129}
130
131#[derive(Debug, Clone)]
133pub struct SessionSummary {
134 pub tasks_completed: Vec<String>,
135 pub session_start: String,
136 pub session_duration_seconds: i64,
137}
138
139#[derive(Debug, Clone, Serialize)]
141pub struct ProductivitySummaryReport {
142 pub total_completed: u64,
143 pub current_streak: u32,
144 pub longest_streak: u32,
145 pub last_completed_date: Option<String>,
146 pub next_milestone: Option<u64>,
147 pub milestones: Vec<Milestone>,
148 pub recent_completions: Vec<CompletedTaskRef>,
149}
150
151#[derive(Debug, Clone, Serialize)]
153pub struct ProductivityStreakReport {
154 pub current_streak: u32,
155 pub longest_streak: u32,
156 pub last_completed_date: Option<String>,
157}
158
159#[derive(Debug, Clone, Serialize)]
161pub struct ProductivityVelocityReport {
162 pub window_days: u32,
163 pub total_completed: u32,
164 pub average_per_day: f64,
165 pub best_day: Option<(String, u32)>,
166}
167
168#[derive(Debug, Clone, Serialize)]
170pub struct ProductivityEstimationReport {
171 pub tasks_analyzed: u32,
172 pub average_accuracy_ratio: f64,
173 pub median_accuracy_ratio: f64,
174 pub within_25_percent: f64,
175 pub average_absolute_error_minutes: f64,
176}