prb 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 97fa1172495612ccf5109e932970c74bdaf02690e9399f7da5a451f41598cfdf
4
- data.tar.gz: 1df513efca5f84ac516121e0f720c1522474eb97581a390777ad37786e6caf98
3
+ metadata.gz: d09ffeecc26a41b306564b20a9e9acc62d5cbbfd9b03a16684ae0204f289717e
4
+ data.tar.gz: 0d6615043f85ff16ab3f4da9c5e2c5fa17525d16c6425b32d210898084683680
5
5
  SHA512:
6
- metadata.gz: 4c3f24a6477fcca54805d9ed7a799a45f97e2afdf1007882131045f796b4ae9373b9af293fc0a8831bb2623e8398543150d6c7f32d9f03e837bd6787df19c96f
7
- data.tar.gz: a0995f9549574d236c49dfd5f99f0c927c61de46c0841d4e34dbd2c9b764dddc5311f18d391a50def038ebec010aefa596a0cbb312cd7b7883fb3ea1e29b5f2e
6
+ metadata.gz: d5c9433e04646ea3467add2f8915cdb2ccd6c2ecb8a1dfcd6118a46f42593b0db22ab0a210316b90de478a38939a401b9e80fabbe602c9dd20c49e2036fd58cd
7
+ data.tar.gz: 8836c99454be9f1cbaf3a1f63c1104c3437ed350b5db9abe656fc417ff2976be188052e1b4194f349851588b9e17e479f5396350a77da42c2f925d28d627a21b
@@ -1,14 +1,19 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- prb (0.1.0)
5
- optimist
4
+ prb (0.2.0)
5
+ optimist (~> 3.0)
6
+ sinatra (~> 2.0)
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
9
10
  specs:
10
11
  diff-lcs (1.3)
12
+ mustermann (1.0.3)
11
13
  optimist (3.0.0)
14
+ rack (2.0.7)
15
+ rack-protection (2.0.7)
16
+ rack
12
17
  rake (10.5.0)
13
18
  rspec (3.8.0)
14
19
  rspec-core (~> 3.8.0)
@@ -23,6 +28,12 @@ GEM
23
28
  diff-lcs (>= 1.2.0, < 2.0)
24
29
  rspec-support (~> 3.8.0)
25
30
  rspec-support (3.8.0)
31
+ sinatra (2.0.7)
32
+ mustermann (~> 1.0)
33
+ rack (~> 2.0)
34
+ rack-protection (= 2.0.7)
35
+ tilt (~> 2.0)
36
+ tilt (2.0.10)
26
37
 
27
38
  PLATFORMS
28
39
  ruby
@@ -34,4 +45,4 @@ DEPENDENCIES
34
45
  rspec (~> 3.0)
35
46
 
36
47
  BUNDLED WITH
37
- 2.0.1
48
+ 2.0.2
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Prb
2
2
 
3
- `prb` is a light-weight timer service written in Ruby for the pomodoro
4
- technique.
3
+ Prb is a light-weight HTTP service written in Ruby for controlling a pomodoro
4
+ timer.
5
5
 
6
6
  ## Installation
7
7
 
@@ -11,24 +11,40 @@ Install the gem
11
11
 
12
12
  ## Usage
13
13
 
14
+ The promodoro timer can be started using `prb start -d` where `-d` will
15
+ run the process in the background.
16
+
17
+ ```
18
+ prb start -d
19
+ ```
20
+
21
+ Options can be passed to configure the timer. By default, there are 4 pomodoro's
22
+ each taking 25 minutes to complete. You can override this behaviour using the
23
+ following command:
24
+
25
+ ```
26
+ prb start -d --pomodoros=4 --timer=25
14
27
  ```
15
- prb v0.1.0 - Pomodoro timer service
16
28
 
17
- Usage:
18
- prb [COMMAND] [SUB_COMMAND]
29
+ After starting the service you can query the timers status over HTTP using
30
+ `curl`:
19
31
 
20
- Options:
21
- -d, --daemonize Start the service in the background
32
+ ```
33
+ curl http://localhost:3838/status
34
+
35
+ {
36
+ "running" true,
37
+ "completed": 0, # completed pomodoros
38
+ "remaining": 4, # remaining pomodoros
39
+ "time_remaining": 440
40
+ }
41
+ ```
22
42
 
23
- Commands:
24
- start Start pomodoro service
25
- stop Stop pomodoro service
26
- status Print status of pomodoro service
27
- skip Skip the current timer
28
- reset Reset the current timer
29
- pause Pause the current timer
30
- -v, --version Print version and exit
31
- -h, --help Show this message
43
+ After each pomodoro the timer will stop. The timer can be resumed
44
+ and the next pomodoro started by using `prb resume` or by `curl` request:
45
+
46
+ ```
47
+ curl http://localhost:3838/resume
32
48
  ```
33
49
 
34
50
  ## Development
data/exe/prb CHANGED
@@ -1,31 +1,42 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "optimist"
4
+ require "webrick"
4
5
  require "bundler/setup"
5
6
  require "prb"
6
7
 
7
8
  COMMAND_MAP = {
8
9
  'start' => 'Start pomodoro service',
9
- 'stop' => 'Stop pomodoro service',
10
- 'status' => 'Print status of pomodoro service',
11
- 'skip' => 'Skip the current timer',
12
- 'reset' => 'Reset the current timer',
13
- 'pause' => 'Pause the current timer'
10
+ 'resume' => 'Resume pomodoro timer',
11
+ 'stop' => 'Stop pomodoro service'
14
12
  }
15
13
 
16
- opts = Optimist::options do
14
+ global_opts = Optimist::options do
17
15
  version "prb v#{Prb::VERSION}"
18
16
  banner "prb v#{Prb::VERSION} - Pomodoro timer service\n \n"
19
17
  banner "Usage:"
20
- banner " prb [COMMAND] [SUB_COMMAND]\n \n"
21
- banner "Options:"
22
- opt :daemonize, 'Start the service in the background', short: '-d'
18
+ banner " prb [COMMAND] [SUB_COMMAND]\n"
23
19
  banner "\nCommands:"
24
20
  COMMAND_MAP.each { |cmd, desc| banner format(" %-10s %s", cmd, desc) }
21
+
22
+ stop_on COMMAND_MAP.keys
25
23
  end
26
24
 
27
25
  commands = COMMAND_MAP.keys & ARGV
28
26
  cmd = commands.first
27
+ opts = {}
28
+
29
+ case cmd
30
+ when "start"
31
+ opts = Optimist::options do
32
+ opt :pomodoros, "Number of pomodoros", default: 4
33
+ opt :timer, "The time in minutes for the timer", default: 25
34
+ opt :port, "The port to run the pomodoro HTTP server", default: 3838
35
+ opt :daemonize, 'Start the service in the background', short: '-d'
36
+ end
37
+ end
38
+
39
+ opts = opts.merge(global_opts)
29
40
 
30
41
  if COMMAND_MAP.keys.include?(cmd)
31
42
  Prb::CommandRunner.new(opts).send(cmd)
data/lib/prb.rb CHANGED
@@ -1,4 +1,10 @@
1
+ require 'json'
2
+ require 'net/http'
3
+ require 'rack'
4
+ require 'rack/server'
5
+
1
6
  require_relative "prb/version"
7
+ require_relative "prb/opts"
2
8
  require_relative "prb/timer"
3
9
  require_relative "prb/timer_control"
4
10
  require_relative "prb/server"
@@ -1,57 +1,51 @@
1
1
  module Prb
2
2
  class CommandRunner
3
3
  def initialize(opts)
4
- @opts = opts
4
+ @opts = Opts.new(opts)
5
5
  end
6
6
 
7
7
  def start
8
- if Prb::Server.running?
8
+ if running?(@opts.port)
9
9
  puts "A prb server is already running."
10
10
  exit(1)
11
11
  end
12
12
 
13
- Process.daemon() if @opts[:daemonize]
13
+ Process.daemon() if @opts.daemonize?
14
14
 
15
- Prb::Server.new.start
15
+ app = Prb::Server.new(@opts)
16
+ Rack::Server.start(
17
+ app: app,
18
+ Port: @opts.port
19
+ )
16
20
  end
17
21
 
18
- def status
19
- response = send_command('STATUS')
20
- puts response
21
- end
22
-
23
- def skip
24
- send_command('SKIP')
25
- end
26
-
27
- def pause
28
- send_command('PAUSE')
29
- end
30
-
31
- def reset
32
- send_command('RESET')
22
+ def resume
23
+ send_request('resume')
33
24
  end
34
25
 
35
26
  def stop
36
- send_command('QUIT')
27
+ send_request('stop')
37
28
  end
38
29
 
39
30
  private
40
31
 
41
- def send_command(cmd)
32
+ def send_request(endpoint)
33
+ uri = URI.parse("http://0.0.0.0:#{@opts.port}/#{endpoint}")
34
+ Net::HTTP.get_response(uri)
35
+ rescue
36
+ nil
37
+ end
38
+
39
+ def running?(port)
42
40
  Timeout::timeout(1) do
43
41
  begin
44
- s = TCPSocket.new('127.0.0.1', PRB_PORT)
45
- s.puts(cmd)
46
- response = s.gets.chomp
42
+ s = TCPSocket.new('0.0.0.0', port)
47
43
  s.close
48
- return response
44
+ return true
49
45
  rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
50
- puts "A prb server is not running"
51
- exit(1)
46
+ return false
52
47
  end
53
48
  end
54
49
  end
55
50
  end
56
-
57
51
  end
@@ -0,0 +1,16 @@
1
+ module Prb
2
+ class Opts
3
+ attr_reader :pomodoros, :timer, :port
4
+
5
+ def initialize(opts)
6
+ @pomodoros = opts[:pomodoros].to_i
7
+ @timer = opts[:timer].to_i
8
+ @daemonize = opts[:daemonize]
9
+ @port = (opts[:port] || 3838).to_i
10
+ end
11
+
12
+ def daemonize?
13
+ !!@daemonize
14
+ end
15
+ end
16
+ end
@@ -1,76 +1,40 @@
1
- require 'socket'
2
1
  require 'timeout'
2
+ require 'sinatra/base'
3
3
 
4
4
  module Prb
5
- PRB_PORT = 3838
5
+ class Server < Sinatra::Base
6
+ def initialize(opts)
7
+ puts <<~MSG
8
+ Starting pomodoro service...
6
9
 
7
- class Server
8
- def initialize
9
- @controller = TimerControl.new
10
- end
11
-
12
- def start
13
- @controller.start
14
-
15
- server = TCPServer.open('127.0.0.1', PRB_PORT)
16
- puts "Server listening on #{PRB_PORT}"
10
+ Number of pomodoros: #{opts.pomodoros} pomodoro(s)
11
+ Pomodoro timer: #{opts.timer} minute(s)
17
12
 
18
- while true
19
- Thread.start(server.accept) do |socket|
20
- while cmd = socket.gets.chomp
21
- puts "RECV: #{cmd}"
13
+ MSG
22
14
 
23
- output = "OK"
24
- case cmd
25
- when 'STATUS'
26
- output = status_line
27
- when 'SKIP'
28
- @controller.toggle
29
- when 'RESET'
30
- @controller.reset
31
- when 'PAUSE'
32
- @controller.pause
33
- when 'QUIT'
34
- socket.puts "OK"
35
- exit(0)
36
- else
37
- puts "ERR: #{cmd} not a command"
38
- output = "ERR: #{cmd} not a command"
39
- end
40
-
41
- socket.puts output
42
- end
15
+ @controller = TimerControl.new(opts)
16
+ @controller.start
43
17
 
44
- socket.close
45
- end
46
- end
18
+ super
19
+ end
47
20
 
48
- server.close
21
+ get '/status' do
22
+ content_type :json
23
+ @controller.render_status
49
24
  end
50
25
 
51
- def self.running?
52
- Timeout::timeout(1) do
53
- begin
54
- s = TCPSocket.new('127.0.0.1', PRB_PORT)
55
- s.close
56
- return true
57
- rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
58
- return false
59
- end
60
- end
26
+ get '/reset' do
27
+ @controller.reset
28
+ status 200
61
29
  end
62
30
 
63
- private
31
+ get '/resume' do
32
+ @controller.resume
33
+ status 200
34
+ end
64
35
 
65
- def status_line
66
- status = ""
67
- status << @controller.timer.render
68
- status << ","
69
- status << "WORKING" if @controller.is_working?
70
- status << "BREAK" if !@controller.is_working?
71
- status << ",PAUSED" if @controller.paused?
72
- status << ",RUNNING" if !@controller.paused?
73
- status
36
+ get '/stop' do
37
+ Process.kill("INT", Process.pid)
74
38
  end
75
39
  end
76
40
  end
@@ -1,41 +1,57 @@
1
1
  module Prb
2
2
  class Timer
3
- def initialize(minutes)
3
+ attr_reader :pomodoros, :seconds, :paused, :completed
4
+
5
+ WORKING = 1
6
+ PAUSED = 2
7
+
8
+ def initialize(opts)
9
+ @opts = opts
10
+
4
11
  @paused = false
5
- set_timer(minutes)
6
- end
12
+ @pomodoros = opts.pomodoros
7
13
 
8
- def set_timer(minutes)
9
- @_seconds = minutes * 60
10
- @seconds = @_seconds
14
+ # set pomodoro timer
15
+ set_timer(@opts.timer)
11
16
  end
12
17
 
13
18
  def tick
14
- sleep 1
15
- @seconds -= 1 unless @paused or finished?
16
- end
19
+ return if completed? or paused?
17
20
 
18
- def finished?
19
- @seconds == 0
21
+ if @seconds == 0
22
+ if @paused == false
23
+ @pomodoros -= 1
24
+ @paused = true
25
+ end
26
+ else
27
+ @seconds -= 1
28
+ end
20
29
  end
21
30
 
22
- def reset
23
- @seconds = @_seconds
31
+ def resume
32
+ @paused = false
33
+ set_timer(@opts.timer)
24
34
  end
25
35
 
26
- def pause
27
- @paused = !@paused
36
+ def reset
37
+ @paused = false
38
+ @pomodoros = @opts.pomodoros
39
+ set_timer(@opts.timer)
28
40
  end
29
41
 
30
42
  def paused?
31
43
  @paused
32
44
  end
33
45
 
34
- def render
35
- min = (@seconds / 60) % 60
36
- sec = (@seconds % 60)
46
+ private
47
+
48
+ def set_timer(minutes)
49
+ @_seconds = minutes * 60
50
+ @seconds = @_seconds
51
+ end
37
52
 
38
- format("%02d:%02d", min, sec)
53
+ def completed?
54
+ @pomodoros == 0
39
55
  end
40
56
  end
41
57
  end
@@ -1,45 +1,36 @@
1
1
  module Prb
2
2
  class TimerControl
3
- WORK_MINUTES = 25
4
- BREAK_MINUTES = 5
5
-
6
3
  attr_reader :timer
7
4
 
8
- def initialize
9
- @timer = Timer.new(WORK_MINUTES)
10
- @is_working = true
5
+ def initialize(opts)
6
+ @opts = opts
7
+ @timer = Timer.new(@opts)
11
8
  end
12
9
 
13
10
  def start
14
11
  Thread.new do
15
12
  loop do
13
+ sleep 1
16
14
  @timer.tick
17
- toggle if @timer.finished?
18
15
  end
19
16
  end
20
17
  end
21
18
 
22
- def reset
23
- @timer.reset
24
- end
25
-
26
- def pause
27
- @timer.pause
19
+ def render_status
20
+ {
21
+ running: !@timer.paused?,
22
+ completed: @opts.pomodoros - @timer.pomodoros,
23
+ remaining: @timer.pomodoros,
24
+ time_remaining: @timer.seconds,
25
+ }.to_json
28
26
  end
29
27
 
30
- def paused?
31
- @timer.paused?
32
- end
33
-
34
- def is_working?
35
- @is_working
28
+ def reset
29
+ @timer.reset
36
30
  end
37
31
 
38
- def toggle
39
- @is_working = !@is_working
40
- @timer.set_timer(@is_working ?
41
- WORK_MINUTES : BREAK_MINUTES)
42
- @timer.pause unless @timer.paused?
32
+ def resume
33
+ @timer.resume
43
34
  end
44
35
  end
45
36
  end
@@ -1,3 +1,3 @@
1
1
  module Prb
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -36,7 +36,8 @@ Gem::Specification.new do |spec|
36
36
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
37
37
  spec.require_paths = ["lib"]
38
38
 
39
- spec.add_dependency "optimist"
39
+ spec.add_dependency "optimist", "~> 3.0"
40
+ spec.add_dependency "sinatra", "~> 2.0"
40
41
 
41
42
  spec.add_development_dependency "bundler", "~> 2.0"
42
43
  spec.add_development_dependency "rake", "~> 10.0"
metadata CHANGED
@@ -1,29 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Ramsden
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-21 00:00:00.000000000 Z
11
+ date: 2019-11-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: optimist
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '3.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sinatra
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
25
32
  - !ruby/object:Gem::Version
26
- version: '0'
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -86,6 +100,7 @@ files:
86
100
  - exe/prb
87
101
  - lib/prb.rb
88
102
  - lib/prb/command_runner.rb
103
+ - lib/prb/opts.rb
89
104
  - lib/prb/server.rb
90
105
  - lib/prb/timer.rb
91
106
  - lib/prb/timer_control.rb