rotation 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,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rotation.gemspec
4
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright 2011 Marcelo Silveira. http://www.mhfs.com.br
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,56 @@
1
+ Rotation
2
+ ========
3
+
4
+ Rotation is a simple command line utility to help you rotate any kind of
5
+ stuff over time. It was originally created to help control code review
6
+ rotation among the members of a team.
7
+
8
+ Currently it only rotates by any given number of weeks. More units
9
+ planned for the future.
10
+
11
+ Installation
12
+ ------------
13
+
14
+ Install the gem:
15
+
16
+ gem install rotation
17
+
18
+ Usage
19
+ -----
20
+
21
+ Create your first rotation topic:
22
+
23
+ rotation init topic_name
24
+
25
+ This will create a `~/.rotation` file. It's a yaml file that will look
26
+ like:
27
+
28
+ topic_name:
29
+ start_date: 2011-09-12
30
+ duration: 1
31
+ first: Huey
32
+ candidates:
33
+ - Huey
34
+ - Dewey
35
+ - Louie
36
+
37
+ Tweak the file for your needs. Notice that you can create as many topics
38
+ as you want.
39
+
40
+ See who's in charge by typing:
41
+
42
+ rotation responsible topic_name
43
+
44
+ If you want to check the responsible of each of your topics type:
45
+
46
+ rotation responsibles
47
+
48
+ Author and License
49
+ ------------------
50
+
51
+ Marcelo Silveira :: marcelo@mhfs.com.br :: @mhfsilveira
52
+
53
+ Released under the MIT License. See the [LICENSE][license] file for further
54
+ details.
55
+
56
+ [license]: https://github.com/mhfs/rotation/blob/master/MIT-LICENSE
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ t.pattern = 'test/**/*_test.rb'
7
+ end
8
+
9
+ desc "Run tests"
10
+ task :default => :test
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require "rotation"
3
+
4
+ Rotation::CLI.start
@@ -0,0 +1,9 @@
1
+ require "date"
2
+ require "yaml"
3
+
4
+ module Rotation
5
+ autoload :Version, "rotation/version"
6
+ autoload :Configuration, "rotation/configuration"
7
+ autoload :Topic, "rotation/topic"
8
+ autoload :CLI, "rotation/cli"
9
+ end
@@ -0,0 +1,37 @@
1
+ require "thor"
2
+
3
+ module Rotation
4
+ class CLI < Thor
5
+ CONFIG_PATH = File.expand_path("~/.rotation")
6
+
7
+ desc "init TOPIC", "Init a new dummy topic config in your ~/.rotation file."
8
+ def init(topic_name)
9
+ config = File.exists?(CONFIG_PATH) ? YAML.load_file(CONFIG_PATH) : {}
10
+ config[topic_name] = { "duration" => 1, "start_date" => Date.today, "first" => "Huey", "candidates" => ["Huey", "Dewey", "Louie"] }
11
+ File.open(CONFIG_PATH, "w") do |out|
12
+ YAML.dump(config, out)
13
+ end
14
+ end
15
+
16
+ desc "responsibles", "Gives the responsibles for all your configured topics"
17
+ def responsibles
18
+ load_settings
19
+ Configuration.config_store.each do |name, topic|
20
+ say_status(name, topic.responsible)
21
+ end
22
+ end
23
+
24
+ desc "responsible TOPIC", "Tells you who is in charge for a given topic."
25
+ def responsible(topic_name)
26
+ load_settings
27
+ topic = Configuration.fetch(topic_name)
28
+ say_status(topic_name, topic.responsible)
29
+ end
30
+
31
+ protected
32
+
33
+ def load_settings
34
+ Configuration.load(CONFIG_PATH)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,18 @@
1
+ module Rotation
2
+ module Configuration
3
+ extend self
4
+
5
+ def load(config_path = "~/.rotation")
6
+ configs = YAML.load_file(config_path)
7
+ configs.each { |topic_name, params| config_store[topic_name] = Topic.new(topic_name, params) }
8
+ end
9
+
10
+ def config_store
11
+ @config ||= {}
12
+ end
13
+
14
+ def fetch(topic_name)
15
+ config_store[topic_name]
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ module Rotation
2
+ class Topic
3
+ attr_accessor :name, :duration, :start_date, :first, :candidates
4
+
5
+ def initialize(topic_name, params)
6
+ @name = topic_name
7
+ @duration = params["duration"]
8
+ @start_date = params["start_date"]
9
+ @first = params["first"]
10
+ @candidates = params["candidates"]
11
+ end
12
+
13
+ def responsible(date = Date.today)
14
+ candidates[responsible_index(date)]
15
+ end
16
+
17
+ def responsible_index(date)
18
+ unit_delta = week_delta(start_date, date)
19
+ (cycle(unit_delta) + candidates.index(first)) % candidates.size
20
+ end
21
+
22
+ def cycle(unit_delta)
23
+ (unit_delta / duration.to_f).floor
24
+ end
25
+
26
+ def week_delta(d1, d2)
27
+ year_difference = (d2.year - d1.year) * 52
28
+ year_difference + (d2 - d2.wday).yday / 7 - (d1 -d1.wday).yday / 7
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Rotation
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rotation/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rotation"
7
+ s.version = Rotation::VERSION
8
+ s.authors = ["Marcelo Silveira"]
9
+ s.email = ["marcelo@mhfs.com.br"]
10
+ s.homepage = "https://github.com/mhfs/rotation/"
11
+ s.summary = %q{Command line utility to help you control rotation of stuff over time}
12
+ s.description = %q{Rotation is a quick utility to help you rotate any kind of stuff over time. I created it to control code review rotation among the team members.}
13
+
14
+ s.rubyforge_project = "rotation"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "rake"
22
+ s.add_development_dependency "contest"
23
+ s.add_development_dependency "redgreen"
24
+
25
+ s.add_runtime_dependency "thor"
26
+ end
@@ -0,0 +1,20 @@
1
+ require "test_helper"
2
+
3
+ class ConfigurationTest < Test::Unit::TestCase
4
+ setup do
5
+ Rotation::Configuration.load("./test/fixtures/sample_config.yml")
6
+ end
7
+
8
+ test "load settings from file" do
9
+ assert Rotation::Configuration.fetch("cool_topic").is_a?(Rotation::Topic)
10
+ end
11
+
12
+ test "correctly feed topics" do
13
+ topic = Rotation::Configuration.fetch("cool_topic")
14
+ assert_equal "cool_topic", topic.name
15
+ assert_equal 2, topic.duration
16
+ assert_equal Date.new(2011, 9, 13), topic.start_date
17
+ assert_equal "one", topic.first
18
+ assert_equal ["one", "two", "three"], topic.candidates
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ cool_topic:
2
+ duration: 2
3
+ start_date: 2011-09-13
4
+ first: one
5
+ candidates: [one, two, three]
@@ -0,0 +1,4 @@
1
+ require "test_helper"
2
+
3
+ class RotationTest < Test::Unit::TestCase
4
+ end
@@ -0,0 +1,5 @@
1
+ require "test/unit"
2
+ require "contest"
3
+ require "redgreen"
4
+
5
+ require "rotation"
@@ -0,0 +1,84 @@
1
+ require "test_helper"
2
+
3
+ class TopicTest < Test::Unit::TestCase
4
+ setup do
5
+ @topic = Rotation::Topic.new("test_topic", {
6
+ "duration" => 2,
7
+ "start_date" => Date.new(2011, 9, 5),
8
+ "first" => "one",
9
+ "candidates" => ["one", "two", "three"]
10
+ })
11
+ end
12
+
13
+ context "#week_delta" do
14
+ test "is 0 for same week" do
15
+ assert_equal 0, @topic.week_delta(@topic.start_date, Date.new(2011, 9, 10))
16
+ end
17
+
18
+ test "is 1 for next week" do
19
+ assert_equal 1, @topic.week_delta(@topic.start_date, Date.new(2011, 9, 11))
20
+ end
21
+
22
+ test "is -1 for previous week" do
23
+ assert_equal -1, @topic.week_delta(@topic.start_date, Date.new(2011, 9, 3))
24
+ end
25
+
26
+ test "is not negative for lower dates in following years" do
27
+ assert_equal 17, @topic.week_delta(@topic.start_date, Date.new(2012, 1, 3))
28
+ end
29
+
30
+ test "is negative for higher dates in previous years" do
31
+ assert_equal -36, @topic.week_delta(@topic.start_date, Date.new(2010, 12, 31))
32
+ end
33
+ end
34
+
35
+ context "#cycle" do
36
+ test "is 0 for up to duration value" do
37
+ assert_equal 0, @topic.cycle(0)
38
+ assert_equal 0, @topic.cycle(1)
39
+ end
40
+
41
+ test "is 1 for up to twice the duration value" do
42
+ assert_equal 1, @topic.cycle(2)
43
+ assert_equal 1, @topic.cycle(3)
44
+ end
45
+
46
+ test "is 2 for up to three time the duration value" do
47
+ assert_equal 2, @topic.cycle(4)
48
+ assert_equal 2, @topic.cycle(5)
49
+ end
50
+ end
51
+
52
+ context "#responsible_index and #responsible" do
53
+ test "is 0 in the first cycle" do
54
+ date = Date.new(2011, 9, 10)
55
+ assert_equal 0, @topic.responsible_index(date)
56
+ assert_equal "one", @topic.responsible(date)
57
+ end
58
+
59
+ test "is 1 for second cycle" do
60
+ date = Date.new(2011, 9, 18)
61
+ assert_equal 1, @topic.responsible_index(date)
62
+ assert_equal "two", @topic.responsible(date)
63
+ end
64
+
65
+ test "is 2 for third cycle" do
66
+ date = Date.new(2011, 10, 8)
67
+ assert_equal 2, @topic.responsible_index(date)
68
+ assert_equal "three", @topic.responsible(date)
69
+ end
70
+
71
+ test "is 0 again for fourth cycle" do
72
+ date = Date.new(2011, 10, 22)
73
+ assert_equal 0, @topic.responsible_index(date)
74
+ assert_equal "one", @topic.responsible(date)
75
+ end
76
+
77
+ test "is 2 for first cycle if first candidate says so" do
78
+ @topic.first = "three"
79
+ date = Date.new(2011, 9, 10)
80
+ assert_equal 2, @topic.responsible_index(date)
81
+ assert_equal "three", @topic.responsible(date)
82
+ end
83
+ end
84
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rotation
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Marcelo Silveira
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-09-12 00:00:00 -03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rake
23
+ prerelease: false
24
+ version_requirements: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ requirement: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: contest
37
+ prerelease: false
38
+ version_requirements: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ requirement: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: redgreen
51
+ prerelease: false
52
+ version_requirements: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ requirement: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: thor
65
+ prerelease: false
66
+ version_requirements: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ type: :runtime
76
+ requirement: *id004
77
+ description: Rotation is a quick utility to help you rotate any kind of stuff over time. I created it to control code review rotation among the team members.
78
+ email:
79
+ - marcelo@mhfs.com.br
80
+ executables:
81
+ - rotation
82
+ extensions: []
83
+
84
+ extra_rdoc_files: []
85
+
86
+ files:
87
+ - .gitignore
88
+ - Gemfile
89
+ - MIT-LICENSE
90
+ - README.md
91
+ - Rakefile
92
+ - bin/rotation
93
+ - lib/rotation.rb
94
+ - lib/rotation/cli.rb
95
+ - lib/rotation/configuration.rb
96
+ - lib/rotation/topic.rb
97
+ - lib/rotation/version.rb
98
+ - rotation.gemspec
99
+ - test/configuration_test.rb
100
+ - test/fixtures/sample_config.yml
101
+ - test/rotation_test.rb
102
+ - test/test_helper.rb
103
+ - test/topic_test.rb
104
+ has_rdoc: true
105
+ homepage: https://github.com/mhfs/rotation/
106
+ licenses: []
107
+
108
+ post_install_message:
109
+ rdoc_options: []
110
+
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ hash: 3
119
+ segments:
120
+ - 0
121
+ version: "0"
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ hash: 3
128
+ segments:
129
+ - 0
130
+ version: "0"
131
+ requirements: []
132
+
133
+ rubyforge_project: rotation
134
+ rubygems_version: 1.6.2
135
+ signing_key:
136
+ specification_version: 3
137
+ summary: Command line utility to help you control rotation of stuff over time
138
+ test_files:
139
+ - test/configuration_test.rb
140
+ - test/fixtures/sample_config.yml
141
+ - test/rotation_test.rb
142
+ - test/test_helper.rb
143
+ - test/topic_test.rb