Gorunner.go -rw-r--r-- 2.7 KiB
1package main
2
3import (
4 "database/sql"
5 "time"
6)
7
8type TaskRunner struct {
9 count int
10 taskID int
11 taskMessage string
12 nPomodoros int
13 origDuration time.Duration
14 state State
15 store *Store
16 started time.Time
17 pause chan bool
18 toggle chan bool
19 notifier Notifier
20 duration time.Duration
21}
22
23func NewTaskRunner(task *Task, store *Store, notifier Notifier) (*TaskRunner, error) {
24 tr := &TaskRunner{
25 taskID: task.ID,
26 taskMessage: task.Message,
27 nPomodoros: task.NPomodoros,
28 origDuration: task.Duration,
29 store: store,
30 state: State(0),
31 pause: make(chan bool),
32 toggle: make(chan bool),
33 notifier: notifier,
34 duration: task.Duration,
35 }
36 return tr, nil
37}
38
39func (t *TaskRunner) Start() {
40 go t.run()
41}
42
43func (t *TaskRunner) TimeRemaining() time.Duration {
44 return (t.duration - time.Since(t.started)).Truncate(time.Second)
45}
46
47func (t *TaskRunner) run() error {
48 for t.count < t.nPomodoros {
49 // Create a new pomodoro where we
50 // track the start / end time of
51 // of this session.
52 pomodoro := &Pomodoro{}
53 // Start this pomodoro
54 pomodoro.Start = time.Now()
55 // Set state to RUNNING
56 t.state = RUNNING
57 // Create a new timer
58 timer := time.NewTimer(t.duration)
59 // Record our started time
60 t.started = pomodoro.Start
61 loop:
62 select {
63 case <-timer.C:
64 t.state = BREAKING
65 t.count++
66 case <-t.toggle:
67 // Catch any toggles when we
68 // are not expecting them
69 goto loop
70 case <-t.pause:
71 timer.Stop()
72 // Record the remaining time of the current pomodoro
73 remaining := t.TimeRemaining()
74 // Change state to PAUSED
75 t.state = PAUSED
76 // Wait for the user to press [p]
77 <-t.pause
78 // Resume the timer with previous
79 // remaining time
80 timer.Reset(remaining)
81 // Change duration
82 t.started = time.Now()
83 t.duration = remaining
84 // Restore state to RUNNING
85 t.state = RUNNING
86 goto loop
87 }
88 pomodoro.End = time.Now()
89 err := t.store.With(func(tx *sql.Tx) error {
90 return t.store.CreatePomodoro(tx, t.taskID, *pomodoro)
91 })
92 if err != nil {
93 return err
94 }
95 // All pomodoros completed
96 if t.count == t.nPomodoros {
97 break
98 }
99
100 t.notifier.Notify("Pomo", "It is time to take a break!")
101 // Reset the duration incase it
102 // was paused.
103 t.duration = t.origDuration
104 // User concludes the break
105 <-t.toggle
106
107 }
108 t.notifier.Notify("Pomo", "Pomo session has completed!")
109 t.state = COMPLETE
110 return nil
111}
112
113func (t *TaskRunner) Toggle() {
114 t.toggle <- true
115}
116
117func (t *TaskRunner) Pause() {
118 t.pause <- true
119}
120
121func (t *TaskRunner) Status() *Status {
122 return &Status{
123 State: t.state,
124 Count: t.count,
125 NPomodoros: t.nPomodoros,
126 Remaining: t.TimeRemaining(),
127 }
128}