estimate 0.0.1

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