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