1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5package lunatask
6
7import (
8 "errors"
9 "fmt"
10 "strings"
11)
12
13// Eisenhower represents a quadrant in the Eisenhower priority matrix, which
14// categorizes tasks by whether they are urgent (time-sensitive) and/or
15// important (valuable toward your goals).
16//
17// The four quadrants guide what action to take:
18//
19// | Urgent | Not Urgent
20// ------------------|---------------|-------------
21// Important | Do Now (1) | Do Later (3)
22// Not Important | Delegate (2) | Eliminate (4)
23//
24// Use [NewEisenhower] to compute the quadrant from boolean flags, or the
25// builder methods [TaskBuilder.Important] and [TaskBuilder.Urgent] for a
26// fluent API.
27type Eisenhower int
28
29// Eisenhower matrix quadrants. See [Eisenhower] for the full matrix.
30const (
31 EisenhowerUncategorized Eisenhower = 0 // not yet categorized
32 EisenhowerDoNow Eisenhower = 1 // urgent + important
33 EisenhowerDelegate Eisenhower = 2 // urgent, not important
34 EisenhowerDoLater Eisenhower = 3 // important, not urgent
35 EisenhowerEliminate Eisenhower = 4 // neither urgent nor important
36)
37
38// NewEisenhower returns the quadrant for the given flags:
39//
40// NewEisenhower(true, true) // DoNow
41// NewEisenhower(true, false) // DoLater
42// NewEisenhower(false, true) // Delegate
43// NewEisenhower(false, false) // Eliminate
44func NewEisenhower(important, urgent bool) Eisenhower {
45 switch {
46 case important && urgent:
47 return EisenhowerDoNow
48 case urgent:
49 return EisenhowerDelegate
50 case important:
51 return EisenhowerDoLater
52 default:
53 return EisenhowerEliminate
54 }
55}
56
57// String returns a human-readable description of the Eisenhower quadrant.
58func (e Eisenhower) String() string {
59 switch e {
60 case EisenhowerUncategorized:
61 return "uncategorized"
62 case EisenhowerDoNow:
63 return "do now (important + urgent)"
64 case EisenhowerDelegate:
65 return "delegate (urgent)"
66 case EisenhowerDoLater:
67 return "do later (important)"
68 case EisenhowerEliminate:
69 return "eliminate"
70 default:
71 return fmt.Sprintf("Eisenhower(%d)", e)
72 }
73}
74
75// IsUrgent reports whether e is in an urgent quadrant ([EisenhowerDoNow] or [EisenhowerDelegate]).
76func (e Eisenhower) IsUrgent() bool {
77 return e == EisenhowerDoNow || e == EisenhowerDelegate
78}
79
80// IsImportant reports whether e is in an important quadrant ([EisenhowerDoNow] or [EisenhowerDoLater]).
81func (e Eisenhower) IsImportant() bool {
82 return e == EisenhowerDoNow || e == EisenhowerDoLater
83}
84
85// Errors returned by Eisenhower operations.
86var (
87 // ErrInvalidEisenhower is returned when parsing an unknown Eisenhower quadrant string.
88 ErrInvalidEisenhower = errors.New("invalid eisenhower quadrant")
89)
90
91// ParseEisenhower parses a string to an Eisenhower quadrant value (case-insensitive).
92// Valid values: "uncategorized", "do-now", "delegate", "do-later", "eliminate",
93// as well as numeric strings "0" through "4".
94func ParseEisenhower(str string) (Eisenhower, error) {
95 switch strings.ToLower(str) {
96 case "uncategorized", "0":
97 return EisenhowerUncategorized, nil
98 case "do-now", "donow", "1":
99 return EisenhowerDoNow, nil
100 case "delegate", "2":
101 return EisenhowerDelegate, nil
102 case "do-later", "dolater", "3":
103 return EisenhowerDoLater, nil
104 case "eliminate", "4":
105 return EisenhowerEliminate, nil
106 default:
107 return 0, fmt.Errorf("%w: %q", ErrInvalidEisenhower, str)
108 }
109}