beans 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Yjg4NWM1NmM0OGIzNDRiMjc1NWNlNzg0YjY3NWMwOGM3MGYxMDBmNw==
5
+ data.tar.gz: !binary |-
6
+ NmY4OTIzNzJjZDIwNTU3MTM1MDU0YzcxZDRiM2U2Y2IxYjIyYzM0Yg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZjI0NjUwODEwMTdlYjQ2ZDBhMmU4NTY5ZGUwZDZiMmY5OTdiYzM1MWQxOTRh
10
+ YTRjNDVmOWM2ZDA0ODhmNmE3ZmNhYWRkZWVhY2Y1NDQ2MWQwMWIxMzE1Nzdi
11
+ YTVmODFkYWQzNTQyM2RhMzgyMDlmMjQ2YzM1ZDE2ODliYzA1NDc=
12
+ data.tar.gz: !binary |-
13
+ NTQzNzQ1MDg4YzZjYWRhOTBiZTM5M2RhOGJjZWFiNzY1ZWE2NTQzNTJiZDk3
14
+ OTU3N2RiMDJhNDNiYTNjZTEyN2NjYWFhZjUyYjc2OTllYTBjOWZjZTRhNDFm
15
+ YzlhNDYwNjE5ZDgzZmZmZDFmOTYyYTVlNTg5MGNiMDQ1ZDAzNTA=
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'beans'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ require 'rake/testtask'
29
+
30
+ Rake::TestTask.new(:test) do |t|
31
+ t.libs << 'lib'
32
+ t.libs << 'test'
33
+ t.pattern = 'test/**/*_test.rb'
34
+ t.verbose = false
35
+ end
36
+
37
+
38
+ task :default => :test
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'beans'
4
+
5
+ if ARGV.include? '-n'
6
+ multiplier = ARGV[ARGV.index('-n')+1].to_f
7
+ end
8
+ multiplier ||= 1.0
9
+
10
+ if ARGV.include? '-i'
11
+ interval = ARGV[ARGV.index('-i')+1].to_f
12
+ end
13
+ interval ||= 0.25
14
+
15
+
16
+ if ARGV.include? '-t'
17
+
18
+ begin
19
+
20
+ s = Beans::BeanCounter.new
21
+
22
+ while true do
23
+ $stdout.printf "\r$%.02f", s.query.to_f*multiplier
24
+ sleep(interval)
25
+ end
26
+
27
+ rescue Interrupt
28
+ $stdout.printf "\n"
29
+
30
+ rescue Errno::ECONNREFUSED
31
+ $stderr.puts "Unable to connect to beans server! Are you sure it's running on port #{Beans::Config.port}?"
32
+
33
+ rescue Errno::EPIPE
34
+ $stderr.printf "\nLost connection with beans server!\n"
35
+
36
+ end
37
+
38
+ elsif ARGV.include? 'start' or ARGV.include? 'stop' or ARGV.include? 'reset'
39
+
40
+ s = Beans::BeanCounter.new
41
+ case ARGV[0].strip.downcase
42
+ when 'start'
43
+ s.query('start')
44
+ when 'stop'
45
+ s.query('stop')
46
+ when 'reset'
47
+ s.query('reset')
48
+ end
49
+
50
+ else
51
+
52
+ begin
53
+ s = Beans::BeanCounter.new
54
+ $stdout.printf "$%.02f\n", s.query.to_f
55
+
56
+ rescue Errno::ECONNREFUSED
57
+ begin
58
+ # Presumably there's no server running, so let's just count some beans.
59
+ s = Beans::Stopwatch.new
60
+ s.start
61
+
62
+ while true do
63
+ $stdout.printf "\r$%.02f", s.query('dollars')*multiplier
64
+ sleep(interval)
65
+ end
66
+ rescue Interrupt
67
+ $stdout.printf "\n"
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'beans'
4
+
5
+ bs = Beans::BeanServer.new
6
+
7
+ bs.respond do |query|
8
+ "Query was: #{query}"
9
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env/ruby
2
+ #
3
+ BINDIR=File.dirname(__FILE__)
4
+
5
+ require 'daemons'
6
+
7
+ Daemons.run(File.join(BINDIR,'beans-server'))
@@ -0,0 +1,9 @@
1
+ require 'beans/config'
2
+ require 'beans/stopwatch'
3
+ require 'beans/bean_server'
4
+ require 'beans/bean_counter'
5
+ require 'beans/notification'
6
+
7
+ module Beans
8
+
9
+ end
@@ -0,0 +1,26 @@
1
+ module Beans
2
+ class BeanCounter
3
+
4
+ def initialize(opts={})
5
+ opts[:port] ||= Config.port
6
+ @port = opts[:port]
7
+ end
8
+
9
+ def open
10
+ @socket = TCPSocket.new('127.0.0.1', @port)
11
+ end
12
+
13
+ def query( query='dollars' )
14
+ self.open
15
+ @socket.puts query
16
+ response = @socket.gets
17
+ self.close
18
+ response
19
+ end
20
+
21
+ def close
22
+ @socket.close
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,47 @@
1
+ require 'socket'
2
+
3
+ module Beans
4
+ class BeanServer
5
+
6
+ def initialize(opts={})
7
+ opts[:port] ||= Config.port
8
+ @server = TCPServer.new(opts[:port])
9
+ end
10
+
11
+ =begin
12
+ def in_background_loop &block
13
+ Thread.start do
14
+ loop do
15
+ begin
16
+ block.call
17
+ rescue StandardError => e
18
+ $stderr.puts "#{e.exception}: #{e.message}"
19
+ $stderr.puts e.backtrace
20
+ end
21
+ end
22
+ end
23
+ end
24
+ =end
25
+
26
+ def respond &block
27
+
28
+ #puts "Listening for bean counters on port #{opts[:port]}..."
29
+
30
+ loop do
31
+ Thread.start(@server.accept) do |client|
32
+ begin
33
+ response = block.call( client.gets )
34
+ client.puts response
35
+ client.close
36
+ rescue StandardError => e
37
+ $stderr.puts "#{e.exception}: #{e.message}"
38
+ $stderr.puts e.backtrace
39
+ end
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+
46
+ end
47
+ end
@@ -0,0 +1,51 @@
1
+ require 'yaml'
2
+
3
+ module Beans
4
+ class Config
5
+
6
+ class <<self
7
+ def config
8
+ @config ||= YAML.load(open(ENV['HOME']+'/.beans.yml'))
9
+ end
10
+
11
+ def salary
12
+ config['salary']
13
+ end
14
+
15
+ def per
16
+ config['per']
17
+ end
18
+
19
+ def salary_per_year
20
+ case per.downcase
21
+ when 'year'
22
+ salary
23
+ when 'month'
24
+ salary*12
25
+ when 'hour'
26
+ salary*hours_per_week*52
27
+ end
28
+ end
29
+
30
+ def hours_per_week
31
+ config['hours_per_week']
32
+ end
33
+
34
+ def port
35
+ config['port']
36
+ end
37
+
38
+ def dollars_per_second
39
+ seconds_per_week = hours_per_week*3600.0
40
+ weeks_per_year = 52.0
41
+ salary_per_year / weeks_per_year / seconds_per_week
42
+ end
43
+
44
+ def seconds_between_notifications
45
+ config['notify_every'] || 1800
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,13 @@
1
+ module Beans
2
+ class Dispatcher
3
+
4
+ class << self
5
+
6
+
7
+ def handle( query )
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+
@@ -0,0 +1,17 @@
1
+ require 'ruby-growl'
2
+
3
+ LIBDIR=File.dirname(__FILE__)
4
+
5
+ module Beans
6
+ class Notification
7
+
8
+ def initialize( m1, m2 )
9
+
10
+ @growl = Growl.new('localhost', 'beans')
11
+
12
+ @growl.add_notification 'beans', 'beans', File.read(File.join(LIBDIR,'/images/bean-icon.png'))
13
+ @growl.notify 'beans', m1, m2
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,113 @@
1
+ module Beans
2
+ class Stopwatch
3
+
4
+ def initialize
5
+ self.reset
6
+ end
7
+
8
+ def reset
9
+ t = Time.now
10
+ @first_started_at = nil
11
+ @last_notification_at = t
12
+ @previously_elapsed_time = 0.0
13
+ @last_stopped_at = t
14
+ @last_started_at = nil
15
+ @running = false
16
+ end
17
+
18
+ def start
19
+ if stopped?
20
+ t = Time.now
21
+
22
+ @first_started_at ||= t
23
+
24
+ @last_started_at = t
25
+ @running = true
26
+
27
+ end
28
+ end
29
+
30
+ def stop
31
+ if running?
32
+ t = Time.now
33
+
34
+ @previously_elapsed_time ||= 0
35
+ @previously_elapsed_time += (t-@last_started_at).to_f
36
+
37
+ @last_stopped_at = t
38
+ @running = false
39
+
40
+ end
41
+ end
42
+
43
+
44
+ def stopped?
45
+ !@running
46
+ end
47
+
48
+ def running?
49
+ @running
50
+ end
51
+
52
+ def seconds_elapsed
53
+ if @last_started_at.nil?
54
+ 0.0
55
+ else
56
+ s = @previously_elapsed_time
57
+ s += (Time.now-@last_started_at).to_f unless stopped?
58
+ s
59
+ end
60
+ end
61
+
62
+ def minutes_elapsed
63
+ seconds_elapsed / 60.0
64
+ end
65
+
66
+ def hours_elapsed
67
+ minutes_elapsed / 60.0
68
+ end
69
+
70
+ def days_elapsed
71
+ hours_elapsed/24.0
72
+ end
73
+
74
+ def dollars_elapsed
75
+ seconds_elapsed * Config.dollars_per_second
76
+ end
77
+
78
+ def query(unit)
79
+ self.send( "#{unit.strip}_elapsed" )
80
+ end
81
+
82
+ def next_notification_at
83
+ @last_notification_at + Config.seconds_between_notifications
84
+ end
85
+
86
+ def seconds_to_next_notification
87
+ next_notification_at - Time.now
88
+ end
89
+
90
+ def nice_elapsed_time
91
+ if (s=seconds_elapsed) < 60
92
+ "#{sprintf("%i",s)} seconds"
93
+ elsif (m=minutes_elapsed) < 60
94
+ "#{sprintf("%i",m)} minutes"
95
+ elsif (h=hours_elapsed) < 24
96
+ "#{sprintf("%.1f",h)} hours"
97
+ else
98
+ "#{sprintf("%.1f",days_elapsed)} days"
99
+ end
100
+ end
101
+
102
+
103
+ def notify
104
+ @last_notification_at = Time.now
105
+ return false if @first_started_at.nil?
106
+ Beans::Notification.new(
107
+ sprintf( "$%.02f", dollars_elapsed),
108
+ "over #{nice_elapsed_time} since #{@first_started_at.strftime( "%-I:%M %p")}."
109
+ )
110
+ end
111
+
112
+ end
113
+ end
@@ -0,0 +1,10 @@
1
+ module Beans
2
+ VERSION = "0.2.1"
3
+
4
+ class << self
5
+ def version
6
+ Beans::VERSION.dup
7
+ end
8
+ end
9
+
10
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: beans
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Ricky Reusser
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: daemons
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ruby-growl
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: A daemonized stopwatch with growl notifications so you don't forget.
56
+ email:
57
+ - rsreusser@gmail.com
58
+ executables:
59
+ - beans
60
+ - beans-server
61
+ - beansd
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - lib/beans/bean_counter.rb
66
+ - lib/beans/bean_server.rb
67
+ - lib/beans/config.rb
68
+ - lib/beans/dispatcher.rb
69
+ - lib/beans/images/bean-icon.png
70
+ - lib/beans/notification.rb
71
+ - lib/beans/stopwatch.rb
72
+ - lib/beans/version.rb
73
+ - lib/beans.rb
74
+ - Rakefile
75
+ - bin/beans
76
+ - bin/beans-server
77
+ - bin/beansd
78
+ homepage: https://github.com/rreusser/beans
79
+ licenses: []
80
+ metadata: {}
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 2.1.10
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: A small utility to convert time (yours) to money (theirs)
101
+ test_files: []