refactor: code refactoring to improve stability.
This commit removes the need to calculate the time remaining in a session and instead introduces a countdown counter which decrements at each one second 'tick'. This stabilizes the interface where it appeared that he timer was randomly pausing or skipping time. A summary of changes made in this commit includes: - Updated the command line flags so that they are easier to remember. - The work, short break and long break session times are now parsed and converted to type float64. These times represent the total amount of seconds. - Removal of timer and finish from Pominal. - The method that calculates the time remaining is removed. - A countdown counter is added to the Pominal type. - Updated alert message for the desktop notification. - Simplified the Run method by moving the logic to chosse the next session in a separate method.
This commit is contained in:
parent
1ccf3b6302
commit
f0b46ed8b7
4 changed files with 101 additions and 101 deletions
6
Makefile
6
Makefile
|
@ -7,10 +7,10 @@ BIN_FILE := $(BIN_DIR)/$(NAME)
|
||||||
all: test_unit build
|
all: test_unit build
|
||||||
|
|
||||||
test_unit:
|
test_unit:
|
||||||
go test -v -cover ./...
|
@go test -v -cover ./...
|
||||||
|
|
||||||
build:
|
build:
|
||||||
go build -a -v -o $(BIN_FILE)
|
@go build -a -v -o $(BIN_FILE)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
go clean
|
@go clean
|
||||||
|
|
8
alert.go
8
alert.go
|
@ -54,9 +54,9 @@ func getIconPath() string {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// alert pushes a desktop notification
|
// alert creates a new desktop notification.
|
||||||
func alert(oldLabel, newLabel string) {
|
func alert(l string) {
|
||||||
title := oldLabel + " timer has stopped"
|
title := "Pominal notification."
|
||||||
text := newLabel + " timer has started"
|
text := l + " session has started."
|
||||||
notifier.Push(title, text, "", notificator.UR_NORMAL)
|
notifier.Push(title, text, "", notificator.UR_NORMAL)
|
||||||
}
|
}
|
||||||
|
|
41
main.go
41
main.go
|
@ -21,7 +21,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"time"
|
"time"
|
||||||
|
@ -34,18 +33,18 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
workTimer string
|
workTime string
|
||||||
shortBreakTimer string
|
shortBreakTime string
|
||||||
longBreakTimer string
|
longBreakTime string
|
||||||
maxWorkCycles int
|
maxWorkSessions int
|
||||||
printVersion bool
|
printVersion bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
flag.StringVar(&workTimer, "work-timer", "25m", "sets the timer for your work session.")
|
flag.StringVar(&workTime, "work", "25m", "sets the timer for your work session.")
|
||||||
flag.StringVar(&shortBreakTimer, "short-break-timer", "5m", "sets the timer for your short break.")
|
flag.StringVar(&shortBreakTime, "short-break", "5m", "sets the timer for your short break.")
|
||||||
flag.StringVar(&longBreakTimer, "long-break-timer", "20m", "sets the timer for your long break.")
|
flag.StringVar(&longBreakTime, "long-break", "20m", "sets the timer for your long break.")
|
||||||
flag.IntVar(&maxWorkCycles, "max-work-cycles", 4, "sets the maximum number of work cycles to complete before taking a long break.")
|
flag.IntVar(&maxWorkSessions, "max-work-sessions", 4, "sets the maximum number of work cycles to complete before taking a long break.")
|
||||||
flag.BoolVar(&printVersion, "version", false, "print version and exit.")
|
flag.BoolVar(&printVersion, "version", false, "print version and exit.")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
}
|
}
|
||||||
|
@ -59,43 +58,41 @@ func main() {
|
||||||
|
|
||||||
initNotifier()
|
initNotifier()
|
||||||
|
|
||||||
workTimeDuration, err := time.ParseDuration(workTimer)
|
w, err := time.ParseDuration(workTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("ERROR: Unable to set the work timer. %s", err.Error())
|
fmt.Printf("ERROR: Unable to set the work timer. %s", err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
shortBreakTimeDuration, err := time.ParseDuration(shortBreakTimer)
|
s, err := time.ParseDuration(shortBreakTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("ERROR: Unable to set the work timer. %s", err.Error())
|
fmt.Printf("ERROR: Unable to set the work timer. %s", err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
longBreakTimeDuration, err := time.ParseDuration(longBreakTimer)
|
l, err := time.ParseDuration(longBreakTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("ERROR: Unable to set the work timer. %s", err.Error())
|
fmt.Printf("ERROR: Unable to set the work timer. %s", err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pominal := NewPominal(
|
pominal := NewPominal(
|
||||||
workTimeDuration,
|
w.Seconds(),
|
||||||
shortBreakTimeDuration,
|
s.Seconds(),
|
||||||
longBreakTimeDuration,
|
l.Seconds(),
|
||||||
maxWorkCycles,
|
maxWorkSessions,
|
||||||
)
|
)
|
||||||
|
|
||||||
pominal.Run()
|
pominal.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// printScreen prints the details of the Pominal session on screen including
|
// printScreen prints the details of the Pominal session on screen including
|
||||||
// the current work cycle number, the timer's current label and the time remaining
|
// the current work session number, the timer's current label and the current countdoen.
|
||||||
// on the timer.
|
|
||||||
// TODO: To be removed when TUI is implemented.
|
// TODO: To be removed when TUI is implemented.
|
||||||
func printScreen(remaining float64, pominalCount, workCycle, maxWorkCycle int, label string) {
|
func printScreen(countdown float64, pominalCount, workSessionCount, maxWorkSession int, label string) {
|
||||||
clearScreen()
|
clearScreen()
|
||||||
remainingSecs := int(math.Ceil(remaining))
|
fmt.Printf("Pominal cycle: %d\nWork session: %d of %d\n\n", pominalCount, workSessionCount, maxWorkSession)
|
||||||
fmt.Printf("Pominal session: %d\nWork cycle: %d of %d\n\n", pominalCount, workCycle, maxWorkCycle)
|
fmt.Printf("Session: %s\nTime remaining: %02d:%02d", label, int(countdown)/60, int(countdown)%60)
|
||||||
fmt.Printf("Timer: %s\nTime remaining: %02d:%02d", label, (remainingSecs/60)%60, remainingSecs%60)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// clearScreen clears the terminal screen
|
// clearScreen clears the terminal screen
|
||||||
|
|
139
pominal.go
139
pominal.go
|
@ -27,106 +27,109 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Pominal struct {
|
type Pominal struct {
|
||||||
timer *time.Timer
|
// workSession is a counter for work sessions.
|
||||||
finish time.Time
|
workSession int
|
||||||
work time.Duration
|
|
||||||
shortBreak time.Duration
|
// maxWorkSessions sets the number of work sessions to complete
|
||||||
longBreak time.Duration
|
// before running the countdown timer for each long break.
|
||||||
maxWorkCycles int
|
maxWorkSessions int
|
||||||
session int
|
|
||||||
|
// cycle represents a Pominal cycle. A Pominal cycle increments after
|
||||||
|
// every long break.
|
||||||
|
cycle int
|
||||||
|
|
||||||
|
// countdown is the decrementing counter for Pominal.
|
||||||
|
countdown float64
|
||||||
|
|
||||||
|
// work is the time (represented in seconds) for the work sessions.
|
||||||
|
work float64
|
||||||
|
|
||||||
|
// shortBreak is the time (represented in seconds) for the short break sessions.
|
||||||
|
shortBreak float64
|
||||||
|
|
||||||
|
// longBreak is the time (represented in seconds) for the long break sessions.
|
||||||
|
longBreak float64
|
||||||
|
|
||||||
|
// label labels Pominal based on the session.
|
||||||
label string
|
label string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPominal creates a new pominal instance
|
// NewPominal creates a new pominal instance
|
||||||
func NewPominal(w, s, l time.Duration, m int) Pominal {
|
func NewPominal(w, s, l float64, m int) Pominal {
|
||||||
|
|
||||||
return Pominal{
|
return Pominal{
|
||||||
|
workSession: 1,
|
||||||
|
maxWorkSessions: m,
|
||||||
|
cycle: 1,
|
||||||
work: w,
|
work: w,
|
||||||
shortBreak: s,
|
shortBreak: s,
|
||||||
longBreak: l,
|
longBreak: l,
|
||||||
maxWorkCycles: m,
|
|
||||||
session: 1,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run Pominal
|
// Run Pominal
|
||||||
func (p *Pominal) Run() {
|
func (p *Pominal) Run() {
|
||||||
workCycleCount := 1
|
|
||||||
t := time.NewTicker(1 * time.Second)
|
|
||||||
s := make(chan os.Signal, 1)
|
s := make(chan os.Signal, 1)
|
||||||
|
|
||||||
signal.Notify(s, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(s, syscall.SIGINT, syscall.SIGTERM)
|
||||||
p.Start(workTimerLabel, workCycleCount)
|
|
||||||
|
p.UpdateSession()
|
||||||
|
t := time.NewTicker(1 * time.Second)
|
||||||
|
|
||||||
infinite:
|
infinite:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case sig := <-s:
|
case sig := <-s:
|
||||||
fmt.Printf("\n\nReceived signal '%s'. Closing Pominal.\n", sig)
|
fmt.Printf("\n\nReceived signal '%s'. Closing Pominal.\n", sig)
|
||||||
p.timer.Stop()
|
|
||||||
t.Stop()
|
t.Stop()
|
||||||
break infinite
|
break infinite
|
||||||
case <-t.C:
|
case <-t.C:
|
||||||
printScreen(p.TimeRemaining(), p.session, workCycleCount, p.maxWorkCycles, p.label)
|
p.countdown--
|
||||||
case <-p.timer.C:
|
if p.countdown < 0 {
|
||||||
fmt.Printf("\n%s timer has finished\n", p.label)
|
fmt.Printf("\n%s session has finished.\n", p.label)
|
||||||
p.timer.Stop()
|
|
||||||
t.Stop()
|
t.Stop()
|
||||||
|
p.UpdateSession()
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
oldLabel := p.label
|
t = time.NewTicker(1 * time.Second)
|
||||||
|
} else {
|
||||||
|
printScreen(p.countdown,
|
||||||
|
p.cycle,
|
||||||
|
p.workSession,
|
||||||
|
p.maxWorkSessions,
|
||||||
|
p.label,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSession resets Pominal's countdown
|
||||||
|
// based on the next session. If a 'short break'
|
||||||
|
// session is over the work session counter is incremented.
|
||||||
|
// If a 'long break' session is over then the Pominal cycle
|
||||||
|
// is incremented and the work session counter is reset
|
||||||
|
// to 1.
|
||||||
|
func (p *Pominal) UpdateSession() {
|
||||||
switch p.label {
|
switch p.label {
|
||||||
case workTimerLabel:
|
case workTimerLabel:
|
||||||
if workCycleCount >= p.maxWorkCycles {
|
if p.workSession >= p.maxWorkSessions {
|
||||||
p.Start(longBreakTimerLabel, workCycleCount)
|
p.countdown = p.longBreak
|
||||||
|
p.label = longBreakTimerLabel
|
||||||
} else {
|
} else {
|
||||||
p.Start(shortBreakTimerLabel, workCycleCount)
|
p.countdown = p.shortBreak
|
||||||
|
p.label = shortBreakTimerLabel
|
||||||
}
|
}
|
||||||
case shortBreakTimerLabel:
|
case shortBreakTimerLabel:
|
||||||
workCycleCount++
|
p.workSession++
|
||||||
p.Start(workTimerLabel, workCycleCount)
|
p.countdown = p.work
|
||||||
|
p.label = workTimerLabel
|
||||||
case longBreakTimerLabel:
|
case longBreakTimerLabel:
|
||||||
workCycleCount = 1
|
p.cycle++
|
||||||
p.IncrementCount()
|
p.workSession = 1
|
||||||
p.Start(workTimerLabel, workCycleCount)
|
p.countdown = p.work
|
||||||
|
p.label = workTimerLabel
|
||||||
|
default:
|
||||||
|
p.countdown = p.work
|
||||||
|
p.label = workTimerLabel
|
||||||
}
|
}
|
||||||
t = time.NewTicker(1 * time.Second)
|
alert(p.label)
|
||||||
newLabel := p.label
|
|
||||||
alert(oldLabel, newLabel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start begins the timer specified by the
|
|
||||||
// label argument.
|
|
||||||
func (p *Pominal) Start(label string, workCycleCount int) {
|
|
||||||
var d time.Duration
|
|
||||||
|
|
||||||
switch label {
|
|
||||||
case workTimerLabel:
|
|
||||||
d = p.work
|
|
||||||
case shortBreakTimerLabel:
|
|
||||||
d = p.shortBreak
|
|
||||||
case longBreakTimerLabel:
|
|
||||||
d = p.longBreak
|
|
||||||
}
|
|
||||||
|
|
||||||
p.label = label
|
|
||||||
if p.timer == nil {
|
|
||||||
p.timer = time.NewTimer(d)
|
|
||||||
} else {
|
|
||||||
p.timer.Reset(d)
|
|
||||||
}
|
|
||||||
|
|
||||||
p.finish = time.Now().Add(d)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TimeRemaining returns the remaining time left
|
|
||||||
// on the timer
|
|
||||||
func (p *Pominal) TimeRemaining() float64 {
|
|
||||||
return p.finish.Sub(time.Now()).Seconds()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IncrementCount increments the pominal session count
|
|
||||||
func (p *Pominal) IncrementCount() {
|
|
||||||
p.session++
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue