estimate 0.0.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 @@
1
+ .rvmrc
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - ruby-head
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -0,0 +1,36 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ builder (3.0.0)
5
+ diff-lcs (1.1.3)
6
+ happymapper (0.4.0)
7
+ libxml-ruby (~> 2.0)
8
+ libxml-ruby (2.3.2)
9
+ mime-types (1.18)
10
+ nokogiri (1.5.2)
11
+ pivotal-tracker (0.5.1)
12
+ builder
13
+ builder
14
+ happymapper (>= 0.3.2)
15
+ happymapper (>= 0.3.2)
16
+ nokogiri (>= 1.4.3)
17
+ nokogiri (~> 1.4)
18
+ rest-client (~> 1.6.0)
19
+ rest-client (~> 1.6.0)
20
+ rest-client (1.6.7)
21
+ mime-types (>= 1.16)
22
+ rspec (2.9.0)
23
+ rspec-core (~> 2.9.0)
24
+ rspec-expectations (~> 2.9.0)
25
+ rspec-mocks (~> 2.9.0)
26
+ rspec-core (2.9.0)
27
+ rspec-expectations (2.9.0)
28
+ diff-lcs (~> 1.1.3)
29
+ rspec-mocks (2.9.0)
30
+
31
+ PLATFORMS
32
+ ruby
33
+
34
+ DEPENDENCIES
35
+ pivotal-tracker
36
+ rspec
@@ -0,0 +1,21 @@
1
+ # Estimate
2
+
3
+ Do you have a manager that's been nugging you about an end date or a project estimate?
4
+ **Estimate** can solve your problem.
5
+
6
+ ## Usage
7
+
8
+ ```ruby
9
+ gem install estimate # install
10
+
11
+ estimate <project_name> -u <username> -p <password> --ssl
12
+
13
+ Usage: estimate <project_name> [options]
14
+ -u, --user STRING Pivotal tracker username
15
+ -p, --pass STRING Pivotal tracker password
16
+ -s, --ssl Use secure connection
17
+ -d, --developers INT Number of developers (default: 2)
18
+ -x, --day_points INT Points allocated to a day (default: 1)
19
+ ```
20
+
21
+ [![Build Status](https://secure.travis-ci.org/despo/estimate.png)](http://travis-ci.org/despo/estimate)
@@ -0,0 +1,8 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new(:spec) do |t|
4
+ t.rspec_path = 'rspec'
5
+ t.rspec_opts = ["-cfd"]
6
+ end
7
+
8
+ task :default => :spec
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+
4
+ options = {}
5
+ parsed_options = OptionParser.new do |opts|
6
+ opts.banner = "Usage: estimate <project_name> [options]"
7
+
8
+ opts.on('-u', '--user STRING', 'Pivotal tracker username') { |user| options[:username] = user }
9
+ opts.on('-p', '--pass STRING', 'Pivotal tracker password') { |pass| options[:password] = pass }
10
+ opts.on('-s', '--ssl', 'Use secure connection') { options[:ssl] = true }
11
+
12
+ opts.on('-d', '--developers INT', 'Number of developers (default: 2)') do |developers|
13
+ options[:developers] = developers
14
+ end
15
+
16
+ opts.on('-x', '--day_points INT', 'Points allocated to a day (default: 1)') do |day_options|
17
+ options[:day_points] = day_points
18
+ end
19
+
20
+ begin
21
+ opts.parse!(ARGV)
22
+ rescue OptionParser::ParseError => e
23
+ warn e.message
24
+ puts opts
25
+ exit 1
26
+ end
27
+ end
28
+
29
+ project = ARGV.first or warn("Which project do you want to estimate?")
30
+
31
+ if !options[:username] or !options[:password]
32
+ warn "No authentication credentials specified"
33
+ exit
34
+ end
35
+
36
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
37
+ require 'estimate'
38
+ begin
39
+ Estimate::TrackingSystem.authenticate! options[:username], options[:password], options[:ssl]
40
+ puts Estimate::Project.new(project, options).process!
41
+ rescue Exception => e
42
+ puts "Something went wrong..."
43
+ puts e.message
44
+ end
@@ -0,0 +1,27 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "estimate/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "estimate"
6
+ s.version = Estimate::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.author = "Despo Pentara"
9
+ s.email = "despo@extractmethod.com"
10
+ s.homepage = "https://github.com/despo/estimate"
11
+ s.summary = "Estimate projects the easy way."
12
+ s.description = %{Have a manager that's been nugging you for a project estimate? Waste no time! Estimate your project now.}
13
+ s.required_ruby_version = '>= 1.9.2'
14
+
15
+ s.licenses = ["MIT"]
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {spec}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "pivotal-tracker", "~> 0.5.1"
23
+
24
+ s.add_development_dependency "rspec", "~> 2.8.0"
25
+ s.add_development_dependency "rake"
26
+ end
27
+
@@ -0,0 +1,7 @@
1
+ require 'pivotal-tracker'
2
+ require_relative 'estimate/tracking_system'
3
+ require_relative 'estimate/project'
4
+
5
+ module Estimate
6
+
7
+ end
@@ -0,0 +1,78 @@
1
+ require 'pivotal-tracker'
2
+
3
+ module Estimate
4
+ class Project
5
+
6
+ def initialize name, properties={}
7
+ @name = name
8
+ @properties = properties
9
+ end
10
+
11
+ def process!
12
+ """
13
+ Project: #{@name}
14
+ Incomplete stories: #{incomplete_stories.length}
15
+
16
+ And your project end date is.....
17
+ #{display_end_date}
18
+
19
+ You have #{remaining_days} days to complete this project.
20
+ """
21
+ end
22
+
23
+ private
24
+ WORK_WEEK_DAYS = 5
25
+
26
+ def incomplete_stories
27
+ @stories = @stories || project.stories.all(:story_type => story_points.keys, :current_state => incomplete_stati)
28
+ end
29
+
30
+ def project
31
+ @project = @project || PivotalTracker::Project.all.select { |x| x.name.eql? @name }.first
32
+ end
33
+
34
+ def story_points
35
+ { :feature => 5,
36
+ :bug => 1,
37
+ :chore => 1
38
+ }
39
+ end
40
+
41
+ def incomplete_stati
42
+ [ 'unscheduled', 'unstarted', 'started' ]
43
+ end
44
+
45
+ def display_end_date
46
+ end_date.strftime('%A, %b %d %Y')
47
+ end
48
+
49
+ def end_date
50
+ DateTime.now + remaining_weeks*7
51
+ end
52
+
53
+ def remaining_weeks
54
+ @remaining_weeks = @remaining_weeks || (points/day_points+holidays*developers)/WORK_WEEK_DAYS/developers
55
+ end
56
+
57
+ def points
58
+ incomplete_stories.inject(0) { |points, story| points + story_points[story.story_type.to_sym] }
59
+ end
60
+
61
+ def day_points
62
+ @properties[:day_points] || 1
63
+ end
64
+
65
+ def holidays
66
+ 5*developers
67
+ end
68
+
69
+ def developers
70
+ @properties[:developers] || 2
71
+ end
72
+
73
+ def remaining_days
74
+ (end_date-DateTime.now).to_i
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,9 @@
1
+ module Estimate
2
+
3
+ class TrackingSystem
4
+ def self.authenticate! username, password, ssl=nil
5
+ PivotalTracker::Client.token(username, password)
6
+ PivotalTracker::Client.use_ssl = true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ module Estimate
2
+ VERSION = "0.0.1"
3
+ end
4
+
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Estimate::Project do
4
+
5
+ context 'properties' do
6
+ it '#developers' do
7
+ project = Estimate::Project.new(:project_name, :developers => 5)
8
+ project.stub(:project => mock_pivotal_project)
9
+
10
+ 3.times { project.should_receive(:developers).and_return(5) }
11
+
12
+ project.process!
13
+ end
14
+
15
+ it '#day_points' do
16
+ project = Estimate::Project.new(:project_name, :day_points => 2)
17
+ project.stub(:project => mock_pivotal_project)
18
+
19
+ project.should_receive(:day_points).and_return(2)
20
+
21
+ project.process!
22
+ end
23
+ end
24
+
25
+ it "can estimate the project's end date" do
26
+ number_of_stories = 10
27
+
28
+ project = Estimate::Project.new(:project_name)
29
+ mock_incomplete_stories(project, number_of_stories)
30
+
31
+ end_date = (DateTime.now + 7*7).strftime('%A, %b %d %Y')
32
+
33
+ project.process!.should eq process_string(:project_name, number_of_stories, end_date)
34
+ end
35
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Estimate::TrackingSystem do
4
+
5
+ context 'can connect to the tracking system' do
6
+
7
+ it 'can authenticate a user' do
8
+ PivotalTracker::Client.should_receive(:token).with(:username, :password)
9
+ Estimate::TrackingSystem.authenticate! :username, :password
10
+ end
11
+
12
+ it 'can authenticate when ssl authentication is enabled' do
13
+ PivotalTracker::Client.should_receive(:token).with(:username, :password)
14
+ PivotalTracker::Client.should_receive(:use_ssl=).with(true)
15
+
16
+ Estimate::TrackingSystem.authenticate!(:username, :password, true)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,6 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ require 'rspec'
3
+ require 'support/mocks.rb'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ require 'estimate'
@@ -0,0 +1,25 @@
1
+ def mock_incomplete_stories project, number_of_stories
2
+ incomplete_stories = number_of_stories.times.map { mock_feature }
3
+
4
+ 2.times { project.should_receive(:incomplete_stories).and_return(incomplete_stories) }
5
+ end
6
+
7
+ def process_string name, incomplete_stories, end_date
8
+ """
9
+ Project: #{name}
10
+ Incomplete stories: #{incomplete_stories}
11
+
12
+ And your project end date is.....
13
+ #{end_date}
14
+
15
+ You have 48 days to complete this project.
16
+ """
17
+ end
18
+
19
+ def mock_feature
20
+ mock(:story_type => 'feature')
21
+ end
22
+
23
+ def mock_pivotal_project
24
+ mock(:pivotal_project, :stories => mock(:all => []))
25
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: estimate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Despo Pentara
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: pivotal-tracker
16
+ requirement: &70293662021420 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.5.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70293662021420
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &70293662020720 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 2.8.0
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70293662020720
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ requirement: &70293662020000 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70293662020000
47
+ description: Have a manager that's been nugging you for a project estimate? Waste
48
+ no time! Estimate your project now.
49
+ email: despo@extractmethod.com
50
+ executables:
51
+ - estimate
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - .gitignore
56
+ - .travis.yml
57
+ - Gemfile
58
+ - Gemfile.lock
59
+ - README.md
60
+ - Rakefile
61
+ - bin/estimate
62
+ - estimate.gemspec
63
+ - lib/estimate.rb
64
+ - lib/estimate/project.rb
65
+ - lib/estimate/tracking_system.rb
66
+ - lib/estimate/version.rb
67
+ - spec/estimate/project_spec.rb
68
+ - spec/estimate/tracking_system_spec.rb
69
+ - spec/spec_helper.rb
70
+ - spec/support/mocks.rb
71
+ homepage: https://github.com/despo/estimate
72
+ licenses:
73
+ - MIT
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: 1.9.2
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 1.8.10
93
+ signing_key:
94
+ specification_version: 3
95
+ summary: Estimate projects the easy way.
96
+ test_files: []