goal 0.0.3 → 0.1.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
  SHA1:
3
- metadata.gz: 2a84abf9125ab94f0ab2cf6eebf7efdf4490198d
4
- data.tar.gz: 5561546fb4f5db03c667c5131b4ce0e9340bf377
3
+ metadata.gz: 3a273a57258b55e11c3d0f61514950efb5026ffa
4
+ data.tar.gz: 9e98c87c2cee48f8617f609acdf7388d6f9ede4f
5
5
  SHA512:
6
- metadata.gz: 7594268927070c99251e58107215c3e552f1f3ef136d994f32ac741e3213031317fc21a9dd1ef3c16eaa05c6b817f502f4f4449fd4761eacf036da27519a2845
7
- data.tar.gz: 553291d1fdab8f007e69368a7eee93aec75f1f6dbab323c0d5f42441d51f0de63cb69918c80d655e4cc5b94514fca8209b8f0d8f292fb020a6a18f6852118c88
6
+ metadata.gz: 2674f99af748b9e286bf9b04316816e6561c7f3b5599ccf466d8ecfcf7723901f4abb7ed9bd3d2634ea69991827f74523463f78f75d1e90b2e8ac0807fe26bb0
7
+ data.tar.gz: 964867d39e49b6d1a4a31ed4aa87fd62f9eaeedc34becd4e6ae54cc36d5110f822ed9ed86417f8f77d1409f33ed575701468b063e14a01555539ff81e0d44e1a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ### 0.1.0
2
+
3
+ * bug fix
4
+ * Fix typo "Left days" => "Days left" on report
5
+ * Now -h or -u and -t are required options for the binary file
6
+
7
+ * new
8
+ * Removes the Base class, now there is a Calculator class reponsible to make
9
+ the main calculations and generate data to the report
10
+ * Add a report class to print the report
11
+ * Add a new option -h(--hours)
12
+
13
+
1
14
  ### 0.0.3
2
15
 
3
16
  * bug fix
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- goal (0.0.3)
4
+ goal (0.1.0)
5
5
  colorize (~> 0.6.0)
6
6
  ruby-freshbooks (~> 0.4.1)
7
7
 
data/README.md CHANGED
@@ -8,28 +8,44 @@ Goal
8
8
  the month that have 23 business days.
9
9
 
10
10
  ```ruby
11
- g = Goal.new
11
+ calculator = Goal::HourCalculator.new
12
12
 
13
- g.calculate_goal(160) # => 97.39130434782608
13
+ calculator.estimated_for(160) # => 97.39130434782608
14
14
  ```
15
15
 
16
16
  So I need to have 97.39 hours to be within my goal.
17
17
 
18
18
 
19
- ## Using the bin
19
+ ## Using the binary file
20
20
 
21
21
  ```bash
22
22
  $ goal -u freshbooks_user -t freshbooks_token
23
23
 
24
- | Goals | Estimate | Avg. to Goal |
25
- | 160 | 97 | 4.93 |
26
- | 200 | 121 | 9.37 |
27
- | 250 | 152 | 14.93 |
28
- | 300 | 182 | 20.48 |
29
- |_________________________________|
24
+ | Goals | Expected | Average |
25
+ | 160 | 97 | 4.93 |
26
+ | 200 | 121 | 9.37 |
27
+ | 250 | 152 | 14.93 |
28
+ | 300 | 182 | 20.48 |
29
+ |____________________________|
30
30
  | Current: 115.66h
31
31
  | Average: 8.26h
32
- | Left days: 9
32
+ | Days left: 9
33
+ ```
34
+
35
+ or
36
+
37
+ ```bash
38
+ $ goal -h 115.66
39
+
40
+ | Goals | Expected | Average |
41
+ | 160 | 97 | 4.93 |
42
+ | 200 | 121 | 9.37 |
43
+ | 250 | 152 | 14.93 |
44
+ | 300 | 182 | 20.48 |
45
+ |____________________________|
46
+ | Current: 115.66h
47
+ | Average: 8.26h
48
+ | Days left: 9
33
49
  ```
34
50
 
35
51
  ### Available options
@@ -39,9 +55,10 @@ Usage: goal [options]
39
55
  -u, --username=USERNAME Freshbooks username
40
56
  -t, --token=TOKEN Freshbooks token
41
57
  -g, --goals=[GOALS] Your goal list. Ex 160:200:300
58
+ -h, --hours=HOURS Worked time in hours.
42
59
  ```
43
60
 
44
61
  Options `-u` and `-t` are required and specify the user and token to access the
45
- Freshbooks hours.
62
+ Freshbooks hours. But you can use the -h option to specify manually the hours.
46
63
 
47
64
  The `-g` is optional, by default it has the following value `160:200:250:300`
data/bin/goal CHANGED
@@ -1,85 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'goal'
4
- require 'colorize'
5
4
  require 'optparse'
6
5
 
7
- class MyGoals
8
- def initialize(options = {})
9
- @base = Goal::Base.new
10
- @calculator = Goal::HourCalculator.new
11
- @goal_list = options.fetch(:goal_list, [160, 200, 250, 300])
12
- @username = options[:username]
13
- @token = options[:token]
14
- end
15
-
16
- def print
17
- puts
18
- print_header
19
- print_data
20
- print_footer
21
- puts
22
- end
23
-
24
- private
25
-
26
- attr_reader :base, :calculator, :goal_list, :username, :token
27
-
28
- def print_header
29
- puts '| Goals | Estimate | Avg. to Goal |'
30
- end
31
-
32
- def print_data
33
- goals.each do |goal|
34
- avg = calculator.rate_to_goal(goal[:goal], current_time).round(2)
35
-
36
- puts '| ' + goal[:goal].to_s.ljust(5) + ' | ' + goal[:expected].to_i.to_s.ljust(8) + ' | ' + avg.to_s.ljust(12).colorize(average_color(avg)) + ' |'
37
- end
38
- end
39
-
40
- def print_footer
41
- puts '|_________________________________|'
42
- puts "| Current: " + "#{current_time}h".colorize(current_color)
43
- puts "| Average: " + "#{rate}h".colorize(current_color)
44
- puts "| Left days: #{calculator.days_left}"
45
- end
46
-
47
- def current_time
48
- @current_time ||= base.worked_time(username, token).round(2)
49
- end
50
-
51
- def rate
52
- @rate ||= calculator.hour_rate(current_time).round(2)
53
- end
54
-
55
- def goals
56
- base.calculate_goals goal_list
57
- end
58
-
59
- def current_color
60
- if rate < 8
61
- :red
62
- elsif rate >= 8 && rate < 9
63
- :yellow
64
- else
65
- :green
66
- end
67
- end
68
-
69
- def average_color(avg)
70
- if avg < 8
71
- :green
72
- elsif avg >= 8 && avg < 9
73
- :yellow
74
- else
75
- :red
76
- end
77
- end
78
- end
79
-
80
6
  options = {}
81
7
 
82
- OptionParser.new do |opts|
8
+ optparse = OptionParser.new do |opts|
83
9
  opts.banner = "Usage: goal [options]"
84
10
 
85
11
  opts.on("-u", "--username=USERNAME", "Freshbooks username") do |u|
@@ -93,6 +19,20 @@ OptionParser.new do |opts|
93
19
  opts.on("-g", "--goals=[GOALS]", "Your goal list. Ex 160:200:300") do |g|
94
20
  options[:goal_list] = g.split(':').map(&:to_i)
95
21
  end
96
- end.parse!
97
22
 
98
- MyGoals.new(options).print
23
+ opts.on("-h", "--hours=HOURS", "Worked time in hours.") do |h|
24
+ options[:hours] = h.to_f
25
+ end
26
+ end
27
+
28
+ optparse.parse!
29
+
30
+ unless options[:hours] || (options[:username] && options[:token])
31
+ puts 'Arguments -h or -u and -t are required.'
32
+ puts optparse
33
+ exit
34
+ end
35
+
36
+ calculator = Goal::Calculator.new(options)
37
+ puts Goal::Report.new(calculator.generate_data)
38
+
@@ -0,0 +1,47 @@
1
+ module Goal
2
+ class Report
3
+ def initialize(data, options = {})
4
+ @data = data
5
+ @column_width = options.fetch(:column_width, 8)
6
+ end
7
+
8
+ def to_s
9
+ output = row(header) + "\n"
10
+
11
+ data[:rows].each do |r|
12
+ output += row([r[:goal], r[:expected], r[:average]]) + "\n"
13
+ end
14
+
15
+ output += footer
16
+
17
+ output
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :data, :column_width
23
+
24
+ def header
25
+ %w(Goals Expected Average)
26
+ end
27
+
28
+ def footer
29
+ "|" + ('-' * ((column_width * 3) + 8)) + "|\n" +
30
+ "| Current time: #{data[:summary][:total_time]}\n" +
31
+ "| Current rate: #{data[:summary][:rate]}\n" +
32
+ "| Days left: #{data[:summary][:days_left]}"
33
+ end
34
+
35
+ def row(columns)
36
+ prepared_columns = prepare_columns(columns)
37
+
38
+ "| #{prepared_columns.join(' | ')} |"
39
+ end
40
+
41
+ def prepare_columns(columns)
42
+ columns.map do |c|
43
+ c.to_s.ljust(column_width)
44
+ end
45
+ end
46
+ end
47
+ end
data/lib/goal/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Goal
2
- VERSION = '0.0.3'.freeze
2
+ VERSION = '0.1.0'.freeze
3
3
  end
data/lib/goal.rb CHANGED
@@ -1,6 +1,69 @@
1
1
  require 'goal/hour_calculator'
2
2
  require 'goal/freshbooks_calculator'
3
- require 'goal/base'
3
+ require 'goal/report'
4
4
 
5
5
  module Goal
6
+ class Calculator
7
+ def initialize(options = {})
8
+ @calculator = Goal::HourCalculator.new
9
+ @goal_list = options.fetch(:goal_list, [160, 200, 250, 300])
10
+ @username = options[:username]
11
+ @token = options[:token]
12
+ @hours = options[:hours]
13
+ end
14
+
15
+ def worked_time
16
+ if hours
17
+ hours
18
+ elsif username && token
19
+ freshbooks.hours
20
+ else
21
+ 0
22
+ end.round(2)
23
+ end
24
+
25
+ # It calculates the current hour rate
26
+ def rate
27
+ calculator.hour_rate(worked_time).round(2)
28
+ end
29
+
30
+ def generate_data
31
+ data = {}
32
+
33
+ data[:rows] = goals
34
+ data[:summary] = summary
35
+
36
+ data
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :base, :calculator, :goal_list, :username, :token, :hours
42
+
43
+ def freshbooks
44
+ Goal::FreshbooksCalculator.new(username, token)
45
+ end
46
+
47
+ def goals
48
+ calculated_goals = []
49
+
50
+ goal_list.each do |goal|
51
+ calculated_goals.push({
52
+ goal: goal,
53
+ expected: calculator.estimated_for(goal).round(2),
54
+ average: calculator.rate_to_goal(goal, worked_time).round(2)
55
+ })
56
+ end
57
+
58
+ calculated_goals
59
+ end
60
+
61
+ def summary
62
+ {
63
+ total_time: worked_time,
64
+ rate: rate,
65
+ days_left: calculator.days_left
66
+ }
67
+ end
68
+ end
6
69
  end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe Goal::Calculator do
4
+ describe '#worked_time' do
5
+ context 'with hours' do
6
+ subject do
7
+ described_class.new(hours: 90)
8
+ end
9
+
10
+ it 'should return hours' do
11
+ expect(subject.worked_time).to eq 90
12
+ end
13
+ end
14
+
15
+ context 'with hours' do
16
+ subject do
17
+ described_class.new(username: 'username', token: 'token')
18
+ end
19
+
20
+ it 'should return the freshbooks hours' do
21
+ instance = double(:instance)
22
+
23
+ Goal::FreshbooksCalculator.should_receive(:new).with('username', 'token').and_return(instance)
24
+ instance.should_receive(:hours).and_return 55.55
25
+
26
+ expect(subject.worked_time).to eq 55.55
27
+ end
28
+ end
29
+ end
30
+
31
+ describe '#rate' do
32
+ subject do
33
+ described_class.new(hours: 90)
34
+ end
35
+
36
+ it 'should return calculate the rate' do
37
+ Date.stub(today: Date.new(2013, 10, 20))
38
+
39
+ expect(subject.rate).to eq 6.43
40
+ end
41
+ end
42
+
43
+ describe '#generate_data' do
44
+ subject do
45
+ described_class.new(hours: 90, goal_list: [160, 200])
46
+ end
47
+
48
+ it 'should return the generated data' do
49
+ Date.stub(today: Date.new(2013, 10, 20))
50
+
51
+ expect(subject.generate_data).to eq({
52
+ rows: [
53
+ {
54
+ goal: 160,
55
+ expected: 97.39,
56
+ average: 7.78
57
+ },
58
+ {
59
+ goal: 200,
60
+ expected: 121.74,
61
+ average: 12.22
62
+ }
63
+ ],
64
+ summary: {
65
+ total_time: 90.0,
66
+ rate: 6.43,
67
+ days_left: 9
68
+ }
69
+ })
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Goal::Report do
4
+ let(:data) do
5
+ {
6
+ rows: [
7
+ {
8
+ goal: 160,
9
+ expected: 97.39,
10
+ average: 7.78
11
+ },
12
+ {
13
+ goal: 200,
14
+ expected: 121.74,
15
+ average: 12.22
16
+ }
17
+ ],
18
+ summary: {
19
+ total_time: 90.0,
20
+ rate: 6.43,
21
+ days_left: 9
22
+ }
23
+ }
24
+ end
25
+
26
+ subject do
27
+ described_class.new(data)
28
+ end
29
+
30
+ describe '#to_s' do
31
+ it 'should build the report' do
32
+ report = "| Goals | Expected | Average |\n"
33
+ report += "| 160 | 97.39 | 7.78 |\n"
34
+ report += "| 200 | 121.74 | 12.22 |\n"
35
+ report += "|--------------------------------|\n"
36
+ report += "| Current time: 90.0\n"
37
+ report += "| Current rate: 6.43\n"
38
+ report += "| Days left: 9"
39
+
40
+ expect(subject.to_s).to eq report
41
+ end
42
+ end
43
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: goal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mateus Lorandi dos Santos
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-21 00:00:00.000000000 Z
11
+ date: 2013-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-freshbooks
@@ -83,13 +83,14 @@ files:
83
83
  - bin/goal
84
84
  - goal.gemspec
85
85
  - lib/goal.rb
86
- - lib/goal/base.rb
87
86
  - lib/goal/freshbooks_calculator.rb
88
87
  - lib/goal/hour_calculator.rb
88
+ - lib/goal/report.rb
89
89
  - lib/goal/version.rb
90
- - spec/base_spec.rb
90
+ - spec/calculator_spec.rb
91
91
  - spec/freshbooks_calculator_spec.rb
92
92
  - spec/hour_calculator_spec.rb
93
+ - spec/report_spec.rb
93
94
  - spec/spec_helper.rb
94
95
  homepage: http://github.com/comogo/goal
95
96
  licenses:
@@ -111,9 +112,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
112
  version: '0'
112
113
  requirements: []
113
114
  rubyforge_project:
114
- rubygems_version: 2.1.5
115
+ rubygems_version: 2.1.9
115
116
  signing_key:
116
117
  specification_version: 4
117
118
  summary: Keep track of your hour goals
118
119
  test_files: []
119
- has_rdoc:
data/lib/goal/base.rb DELETED
@@ -1,32 +0,0 @@
1
- module Goal
2
- class Base
3
- def initialize
4
- @calculator = HourCalculator.new
5
- end
6
-
7
- def worked_time(username, token)
8
- FreshbooksCalculator.new(username, token).hours
9
- end
10
-
11
- def calculate_goal(goal)
12
- calculator.estimated_for(goal)
13
- end
14
-
15
- def calculate_goals(goals)
16
- calculated_goals = []
17
-
18
- goals.each do |goal|
19
- calculated_goals.push({
20
- goal: goal,
21
- expected: calculate_goal(goal)
22
- })
23
- end
24
-
25
- calculated_goals
26
- end
27
-
28
- private
29
-
30
- attr_reader :calculator
31
- end
32
- end
data/spec/base_spec.rb DELETED
@@ -1,40 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Goal::Base do
4
- describe '#worked_time' do
5
- it 'should get the worked_time from freshbooks' do
6
- freshbooks_instance = double(:freshbooks_instance)
7
-
8
- Goal::FreshbooksCalculator.should_receive(:new).with('username', 'token').and_return(freshbooks_instance)
9
- freshbooks_instance.should_receive(:hours).and_return(30)
10
-
11
- expect(subject.worked_time('username', 'token')).to eq 30
12
- end
13
- end
14
-
15
- describe '#calculate_goal' do
16
- it 'should calculate goal using the hour calculator' do
17
- Goal::HourCalculator.any_instance.should_receive(:estimated_for).with(200).and_return 10
18
-
19
- expect(subject.calculate_goal(200)).to eq 10
20
- end
21
- end
22
-
23
- describe '#calculate_goals' do
24
- it 'should calculate goals using the hour calculator' do
25
- Goal::HourCalculator.any_instance.should_receive(:estimated_for).with(160).and_return 10
26
- Goal::HourCalculator.any_instance.should_receive(:estimated_for).with(200).and_return 20
27
-
28
- expect(subject.calculate_goals([160, 200])).to eq([
29
- {
30
- goal: 160,
31
- expected: 10
32
- },
33
- {
34
- goal: 200,
35
- expected: 20
36
- }
37
- ])
38
- end
39
- end
40
- end