Implement urgency system with TaskWarrior-inspired calculation
- Add urgency calculation based on multiple factors: * Due date (linear scale: overdue=12.0, today=10.0, week=6.0, 2weeks=2.0) * Priority (H=6.0, M=3.9, D=1.8, L=0.0) * Age (0-2.0 over 365 days) * Active status (+4.0 boost) * Waiting status (-3.0 penalty) * Tags (+1.0 with count modifier) * Project assignment (+1.0) * Configurable urgent tag (default 'next', +15.0) - Replace priority column with urgency in all reports * Display as decimal with 1 decimal place * 4-tier color coding: ≥10 (bright red), ≥5 (red), ≥2 (yellow), <2 (cyan) * Minimal format color-coded by urgency - Add default urgency sorting to all reports * list, minimal, active, ready, overdue reports sort by urgency * newest/oldest keep date-based sorting - Implement 'next' report * Shows most urgent ready tasks * Configurable limit (default 5) * Only includes tasks ready to work on (no future wait/scheduled) - Add urgency display to info command * Shows urgency score alongside priority - All urgency coefficients configurable via config * Adjusted defaults for Opal's simpler model (no blocking/annotations) * Configurable urgent tag name (not hardcoded to 'next') Priority order maintained: High > Medium > Default > Low
This commit is contained in:
@@ -31,6 +31,7 @@ func AllReports() map[string]*Report {
|
||||
"list": ListReport(),
|
||||
"minimal": MinimalReport(),
|
||||
"newest": NewestReport(),
|
||||
"next": NextReport(),
|
||||
"oldest": OldestReport(),
|
||||
"overdue": OverdueReport(),
|
||||
"ready": ReadyReport(),
|
||||
@@ -61,6 +62,7 @@ func ActiveReport() *Report {
|
||||
Description: "Started tasks",
|
||||
BaseFilter: filter,
|
||||
DisplayFormat: DisplayFormatTable,
|
||||
SortFunc: sortByUrgency,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +102,7 @@ func ListReport() *Report {
|
||||
Description: "Pending tasks",
|
||||
BaseFilter: filter,
|
||||
DisplayFormat: DisplayFormatTable,
|
||||
SortFunc: sortByUrgency,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +116,7 @@ func MinimalReport() *Report {
|
||||
Description: "Pending tasks (minimal format)",
|
||||
BaseFilter: filter,
|
||||
DisplayFormat: DisplayFormatMinimal,
|
||||
SortFunc: sortByUrgency,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,6 +152,51 @@ func NewestReport() *Report {
|
||||
}
|
||||
}
|
||||
|
||||
// NextReport shows most urgent tasks ready to work on
|
||||
func NextReport() *Report {
|
||||
filter := NewFilter()
|
||||
filter.Attributes["status"] = "pending"
|
||||
filter.Attributes["_ready"] = "true"
|
||||
|
||||
return &Report{
|
||||
Name: "next",
|
||||
Description: "Most urgent tasks ready to work on",
|
||||
BaseFilter: filter,
|
||||
DisplayFormat: DisplayFormatTable,
|
||||
SortFunc: func(tasks []*Task) []*Task {
|
||||
// Sort by urgency descending
|
||||
cfg, _ := GetConfig()
|
||||
coeffs := BuildUrgencyCoefficients(cfg)
|
||||
|
||||
sorted := make([]*Task, len(tasks))
|
||||
copy(sorted, tasks)
|
||||
|
||||
for i := 0; i < len(sorted)-1; i++ {
|
||||
for j := i + 1; j < len(sorted); j++ {
|
||||
urgI := sorted[i].CalculateUrgency(coeffs)
|
||||
urgJ := sorted[j].CalculateUrgency(coeffs)
|
||||
if urgI < urgJ {
|
||||
sorted[i], sorted[j] = sorted[j], sorted[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sorted
|
||||
},
|
||||
LimitFunc: func(tasks []*Task) []*Task {
|
||||
cfg, _ := GetConfig()
|
||||
limit := cfg.NextLimit
|
||||
if limit <= 0 {
|
||||
limit = 5
|
||||
}
|
||||
if len(tasks) > limit {
|
||||
return tasks[:limit]
|
||||
}
|
||||
return tasks
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// OldestReport shows oldest pending tasks
|
||||
func OldestReport() *Report {
|
||||
filter := NewFilter()
|
||||
@@ -185,6 +234,7 @@ func OverdueReport() *Report {
|
||||
Description: "Overdue tasks",
|
||||
BaseFilter: filter,
|
||||
DisplayFormat: DisplayFormatTable,
|
||||
SortFunc: sortByUrgency,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,6 +249,7 @@ func ReadyReport() *Report {
|
||||
Description: "Tasks ready to work on",
|
||||
BaseFilter: filter,
|
||||
DisplayFormat: DisplayFormatTable,
|
||||
SortFunc: sortByUrgency,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,3 +419,24 @@ func mergeFilters(base, user *Filter) *Filter {
|
||||
|
||||
return merged
|
||||
}
|
||||
|
||||
// sortByUrgency is a helper function to sort tasks by urgency (descending)
|
||||
func sortByUrgency(tasks []*Task) []*Task {
|
||||
cfg, _ := GetConfig()
|
||||
coeffs := BuildUrgencyCoefficients(cfg)
|
||||
|
||||
sorted := make([]*Task, len(tasks))
|
||||
copy(sorted, tasks)
|
||||
|
||||
for i := 0; i < len(sorted)-1; i++ {
|
||||
for j := i + 1; j < len(sorted); j++ {
|
||||
urgI := sorted[i].CalculateUrgency(coeffs)
|
||||
urgJ := sorted[j].CalculateUrgency(coeffs)
|
||||
if urgI < urgJ {
|
||||
sorted[i], sorted[j] = sorted[j], sorted[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sorted
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user