aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2017-04-05 23:14:56 +0200
committerDimitri Sokolyuk <demon@dim13.org>2017-04-05 23:14:56 +0200
commitffbc5ac02e8e934ccfbcc4825c12ea618673688f (patch)
tree3b18cd812946f0c1fe8b08756e373a86dc74f8bc
Initial import
-rw-r--r--LICENSE13
-rw-r--r--README.md0
-rw-r--r--main.go101
3 files changed, 114 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..9863fd4
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2017 Dimitri Sokolyuk <demon@dim13.org>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README.md
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..b85198a
--- /dev/null
+++ b/main.go
@@ -0,0 +1,101 @@
+package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "log"
+ "time"
+)
+
+type Opt struct {
+ Work time.Duration
+ Short time.Duration
+ Long time.Duration
+ Day time.Duration
+ Runs int
+ run int
+}
+
+type stateFn func(context.Context, chan string) stateFn
+
+func (o *Opt) doWork(ctx context.Context, c chan string) stateFn {
+ t := time.NewTimer(o.Work)
+ defer t.Stop()
+ c <- fmt.Sprintf("Work %v run #%v", o.Work, o.run+1)
+ select {
+ case <-ctx.Done():
+ return nil
+ case <-t.C:
+ return o.doBreak
+ }
+}
+
+func (o *Opt) doBreak(_ context.Context, _ chan string) stateFn {
+ if o.run++; o.run%o.Runs == 0 {
+ return o.longBreak
+ }
+ return o.shortBreak
+}
+
+func (o *Opt) shortBreak(ctx context.Context, c chan string) stateFn {
+ t := time.NewTimer(o.Short)
+ defer t.Stop()
+ c <- fmt.Sprintf("Short %v", o.Short)
+ select {
+ case <-ctx.Done():
+ return nil
+ case <-t.C:
+ return o.doWork
+ }
+}
+
+func (o *Opt) longBreak(ctx context.Context, c chan string) stateFn {
+ t := time.NewTimer(o.Long)
+ defer t.Stop()
+ c <- fmt.Sprintf("Long %v", o.Long)
+ select {
+ case <-ctx.Done():
+ return nil
+ case <-t.C:
+ return o.doWork
+ }
+}
+
+func notifier(ctx context.Context) chan string {
+ c := make(chan string)
+ go func() {
+ defer close(c)
+ for v := range c {
+ select {
+ case <-ctx.Done():
+ return
+ default:
+ log.Println(v)
+ }
+ }
+ }()
+ return c
+}
+
+func (o *Opt) pomodoro() {
+ defer func(t time.Time) { log.Printf("total %v", time.Since(t)) }(time.Now())
+ ctx, cancel := context.WithTimeout(context.Background(), o.Day)
+ defer cancel()
+ c := notifier(ctx)
+ for s := o.doWork; s != nil; s = s(ctx, c) {
+ }
+}
+
+const timeBase = time.Second
+
+func main() {
+ var o Opt
+ flag.DurationVar(&o.Work, "work", 25*timeBase, "work time")
+ flag.DurationVar(&o.Short, "short", 5*timeBase, "short break")
+ flag.DurationVar(&o.Long, "long", 15*timeBase, "long break")
+ flag.DurationVar(&o.Day, "day", 600*timeBase, "work day")
+ flag.IntVar(&o.Runs, "runs", 4, "work runs")
+ flag.Parse()
+ o.pomodoro()
+}