forked from MrLesk/Backlog.md
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstatistics.ts
More file actions
162 lines (141 loc) · 4.57 KB
/
Copy pathstatistics.ts
File metadata and controls
162 lines (141 loc) · 4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import type { Task } from "../types/index.ts";
export interface TaskStatistics {
statusCounts: Map<string, number>;
priorityCounts: Map<string, number>;
totalTasks: number;
completedTasks: number;
completionPercentage: number;
draftCount: number;
recentActivity: {
created: Task[];
updated: Task[];
};
projectHealth: {
averageTaskAge: number;
staleTasks: Task[];
blockedTasks: Task[];
};
}
/**
* Calculate comprehensive task statistics for the overview
*/
export function getTaskStatistics(tasks: Task[], drafts: Task[], statuses: string[]): TaskStatistics {
const statusCounts = new Map<string, number>();
const priorityCounts = new Map<string, number>();
// Initialize status counts
for (const status of statuses) {
statusCounts.set(status, 0);
}
// Initialize priority counts
priorityCounts.set("high", 0);
priorityCounts.set("medium", 0);
priorityCounts.set("low", 0);
priorityCounts.set("none", 0);
let completedTasks = 0;
const now = new Date();
const oneWeekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
const oneMonthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
const recentlyCreated: Task[] = [];
const recentlyUpdated: Task[] = [];
const staleTasks: Task[] = [];
const blockedTasks: Task[] = [];
let totalAge = 0;
let taskCount = 0;
// Process each task
for (const task of tasks) {
// Skip tasks with empty or undefined status
if (!task.status || task.status === "") {
continue;
}
// Count by status
const currentCount = statusCounts.get(task.status) || 0;
statusCounts.set(task.status, currentCount + 1);
// Count completed tasks
if (task.status === "Done") {
completedTasks++;
}
// Count by priority
const priority = task.priority || "none";
const priorityCount = priorityCounts.get(priority) || 0;
priorityCounts.set(priority, priorityCount + 1);
// Track recent activity
if (task.createdDate) {
const createdDate = new Date(task.createdDate);
if (createdDate >= oneWeekAgo) {
recentlyCreated.push(task);
}
// Calculate task age
// For completed tasks, use the time from creation to completion
// For active tasks, use the time from creation to now
let ageInDays: number;
if (task.status === "Done" && task.updatedDate) {
const updatedDate = new Date(task.updatedDate);
ageInDays = Math.floor((updatedDate.getTime() - createdDate.getTime()) / (24 * 60 * 60 * 1000));
} else {
ageInDays = Math.floor((now.getTime() - createdDate.getTime()) / (24 * 60 * 60 * 1000));
}
totalAge += ageInDays;
taskCount++;
}
if (task.updatedDate) {
const updatedDate = new Date(task.updatedDate);
if (updatedDate >= oneWeekAgo) {
recentlyUpdated.push(task);
}
}
// Identify stale tasks (not updated in 30 days and not done)
if (task.status !== "Done") {
const lastDate = task.updatedDate || task.createdDate;
if (lastDate) {
const date = new Date(lastDate);
if (date < oneMonthAgo) {
staleTasks.push(task);
}
}
}
// Identify blocked tasks (has dependencies that are not done)
if (task.dependencies && task.dependencies.length > 0 && task.status !== "Done") {
// Check if any dependency is not done
const hasBlockingDependency = task.dependencies.some((depId) => {
const dep = tasks.find((t) => t.id === depId);
return dep && dep.status !== "Done";
});
if (hasBlockingDependency) {
blockedTasks.push(task);
}
}
}
// Sort recent activity by date
recentlyCreated.sort((a, b) => {
const dateA = new Date(a.createdDate || 0);
const dateB = new Date(b.createdDate || 0);
return dateB.getTime() - dateA.getTime();
});
recentlyUpdated.sort((a, b) => {
const dateA = new Date(a.updatedDate || 0);
const dateB = new Date(b.updatedDate || 0);
return dateB.getTime() - dateA.getTime();
});
// Calculate average task age
const averageTaskAge = taskCount > 0 ? Math.round(totalAge / taskCount) : 0;
// Calculate completion percentage (only count tasks with valid status)
const totalTasks = Array.from(statusCounts.values()).reduce((sum, count) => sum + count, 0);
const completionPercentage = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0;
return {
statusCounts,
priorityCounts,
totalTasks,
completedTasks,
completionPercentage,
draftCount: drafts.length,
recentActivity: {
created: recentlyCreated.slice(0, 5), // Top 5 most recent
updated: recentlyUpdated.slice(0, 5), // Top 5 most recent
},
projectHealth: {
averageTaskAge,
staleTasks: staleTasks.slice(0, 5), // Top 5 stale tasks
blockedTasks: blockedTasks.slice(0, 5), // Top 5 blocked tasks
},
};
}