beans 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []