Compare commits
4 commits
d256235c1b
...
636f8c2feb
Author | SHA1 | Date | |
---|---|---|---|
636f8c2feb | |||
3eae584d6d | |||
aa5c24f06d | |||
62fbb1d356 |
4 changed files with 88 additions and 48 deletions
|
@ -1,3 +1,3 @@
|
||||||
package metadata
|
package metadata
|
||||||
|
|
||||||
const GoTomatoVersion = "v0.0.2" // The GoTomato Version
|
const GoTomatoVersion = "v0.0.3" // The GoTomato Version
|
||||||
|
|
|
@ -6,11 +6,21 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var pomodoroResetChannel = make(chan bool, 1)
|
|
||||||
var pomodoroPauseChannel = make(chan bool, 1)
|
|
||||||
var pomodoroResumeChannel = make(chan bool, 1)
|
|
||||||
|
|
||||||
var mu sync.Mutex // to synchronize access to shared state
|
var mu sync.Mutex // to synchronize access to shared state
|
||||||
|
var timer Timer
|
||||||
|
|
||||||
|
func waitForTimer(t Timer) bool {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-t.End:
|
||||||
|
return true
|
||||||
|
case <-t.Abort:
|
||||||
|
return false
|
||||||
|
case shared.Message.TimeLeft = <-t.TimeLeft:
|
||||||
|
// do nothing, just let the timer update the message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// RunPomodoro iterates the Pomodoro work/break sessions.
|
// RunPomodoro iterates the Pomodoro work/break sessions.
|
||||||
func RunPomodoro() {
|
func RunPomodoro() {
|
||||||
|
@ -22,26 +32,32 @@ func RunPomodoro() {
|
||||||
pomodoroConfig := shared.Message.PomodoroSettings
|
pomodoroConfig := shared.Message.PomodoroSettings
|
||||||
|
|
||||||
for session := 1; session <= pomodoroConfig.Sessions; session++ {
|
for session := 1; session <= pomodoroConfig.Sessions; session++ {
|
||||||
|
timer = timer.Init()
|
||||||
|
|
||||||
shared.Message.Session = session
|
shared.Message.Session = session
|
||||||
|
|
||||||
shared.Message.Mode = "Work"
|
shared.Message.Mode = "Work"
|
||||||
if !startTimer(pomodoroConfig.Work) {
|
go timer.Start(pomodoroConfig.Work)
|
||||||
|
if !waitForTimer(timer) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if session == pomodoroConfig.Sessions {
|
|
||||||
shared.Message.Mode = "LongBreak"
|
|
||||||
if !startTimer(pomodoroConfig.LongBreak) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
shared.Message.Mode = "ShortBreak"
|
|
||||||
if !startTimer(pomodoroConfig.ShortBreak) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
shared.Message.Mode = "End"
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
if session < pomodoroConfig.Sessions {
|
||||||
|
shared.Message.Mode = "ShortBreak"
|
||||||
|
go timer.Start(pomodoroConfig.ShortBreak)
|
||||||
|
if !waitForTimer(timer) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else { // last phase, prepare for finish
|
||||||
|
shared.Message.Mode = "LongBreak"
|
||||||
|
go timer.Start(pomodoroConfig.LongBreak)
|
||||||
|
if !waitForTimer(timer) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
shared.Message.Mode = "End"
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
shared.Message.Ongoing = false
|
shared.Message.Ongoing = false
|
||||||
|
@ -53,12 +69,8 @@ func RunPomodoro() {
|
||||||
shared.Message.TimeLeft = shared.Message.PomodoroSettings.Work
|
shared.Message.TimeLeft = shared.Message.PomodoroSettings.Work
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stops and resets the running Pomodoro
|
|
||||||
func ResetPomodoro() {
|
func ResetPomodoro() {
|
||||||
shared.Message.Mode = "Idle"
|
timer.Stop()
|
||||||
shared.Message.Session = 0
|
|
||||||
shared.Message.TimeLeft = shared.Message.PomodoroSettings.Work
|
|
||||||
pomodoroResetChannel <- true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func PausePomodoro() {
|
func PausePomodoro() {
|
||||||
|
@ -66,14 +78,14 @@ func PausePomodoro() {
|
||||||
shared.Message.Paused = true
|
shared.Message.Paused = true
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
|
|
||||||
pomodoroPauseChannel <- true
|
timer.Pause()
|
||||||
}
|
}
|
||||||
|
|
||||||
func ResumePomodoro() {
|
func ResumePomodoro() {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
shared.Message.Paused = false
|
shared.Message.Paused = false
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
pomodoroResumeChannel <- true
|
timer.Resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsPomodoroOngoing() bool {
|
func IsPomodoroOngoing() bool {
|
||||||
|
|
|
@ -1,32 +1,59 @@
|
||||||
package pomodoro
|
package pomodoro
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.smsvc.net/pomodoro/GoTomato/internal/shared"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// runs the countdown and updates shared.Message.TimeLeft every second.
|
type Timer struct {
|
||||||
func startTimer(remainingSeconds int) bool {
|
TimeLeft chan int // time left
|
||||||
for remainingSeconds > 0 {
|
End chan bool // signal on successful end
|
||||||
|
Abort chan bool // signal on premature end
|
||||||
|
stop chan bool
|
||||||
|
wait chan bool
|
||||||
|
resume chan bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Timer) Init() Timer {
|
||||||
|
return Timer{
|
||||||
|
TimeLeft: make(chan int),
|
||||||
|
End: make(chan bool, 1),
|
||||||
|
Abort: make(chan bool, 1),
|
||||||
|
stop: make(chan bool, 1),
|
||||||
|
wait: make(chan bool, 1),
|
||||||
|
resume: make(chan bool, 1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Timer) Start(duration int) {
|
||||||
|
tick := time.NewTicker(time.Second)
|
||||||
|
for timeLeft := duration; timeLeft > 0; {
|
||||||
select {
|
select {
|
||||||
case <-pomodoroResetChannel:
|
case <-t.stop:
|
||||||
return false
|
t.Abort <- true
|
||||||
case <-pomodoroPauseChannel:
|
return
|
||||||
// Nothing to set here, just waiting for the signal
|
case <-t.wait:
|
||||||
case <-pomodoroResumeChannel:
|
<-t.resume
|
||||||
// Nothing to set here, just waiting for the signal
|
continue
|
||||||
|
case <-tick.C:
|
||||||
|
timeLeft--
|
||||||
default:
|
default:
|
||||||
// Broadcast the current state to all clients
|
t.TimeLeft <- timeLeft
|
||||||
if !IsPomodoroPaused() {
|
|
||||||
shared.Message.TimeLeft = remainingSeconds
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
remainingSeconds--
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
t.TimeLeft <- 0
|
||||||
|
|
||||||
// Final shared.Message when time reaches zero
|
t.End <- true
|
||||||
shared.Message.TimeLeft = remainingSeconds
|
}
|
||||||
|
|
||||||
return true
|
func (t *Timer) Stop() {
|
||||||
|
t.resume <- true
|
||||||
|
t.stop <- true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Timer) Pause() {
|
||||||
|
t.wait <- true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Timer) Resume() {
|
||||||
|
t.resume <- true
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
// sends continous messages to all connected WebSocket clients.
|
// sends continous messages to all connected WebSocket clients.
|
||||||
func SendPermanentBroadCastMessage() {
|
func SendPermanentBroadCastMessage() {
|
||||||
|
tick := time.NewTicker(time.Second)
|
||||||
for {
|
for {
|
||||||
// Marshal the message into JSON format
|
// Marshal the message into JSON format
|
||||||
jsonMessage, err := json.Marshal(shared.Message)
|
jsonMessage, err := json.Marshal(shared.Message)
|
||||||
|
@ -25,6 +26,6 @@ func SendPermanentBroadCastMessage() {
|
||||||
// The client is responsible for closing itself on error
|
// The client is responsible for closing itself on error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second)
|
<-tick.C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue