brackets 0.0.0 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ef9e0f90d5ce9ae4ebd3193d0db4218463333415
4
- data.tar.gz: 563f99e283542007f9b6b7528ef3ab20a4a5fbd9
3
+ metadata.gz: 6c83d7fafb937ee94ed9ae54cefa98cb2ed830c4
4
+ data.tar.gz: 990b94f69f4e57cb5ecb43804fefbe7cb1565e1c
5
5
  SHA512:
6
- metadata.gz: 832d2402b34fe714a948d3aa71f79638617000d67d008fe9169b99606fb4b63b98e8d966f7f9891b112914dba4faf298edd8fe17cf6df75eb276946bbccfdb01
7
- data.tar.gz: d6834ca5434be898119361a5f29ed32fe65239bfff393926a5dc2488d68af400b6f328dd5eb9453910d8262a23f500da989c6273d4d15edfe6584035b651581c
6
+ metadata.gz: 8187f943dbc8be7e3c96501966e2f506637fa5f1814308224018ea864409758454589cd98d14621a766d2eba4bbca7970c6cc58bb40b5a84873d4a49703b8146
7
+ data.tar.gz: 53213ef11e8cc68488f95be647d9bd373b6b74e9c1985cbbc93e4b544966a5ebed66ac2a104cd965a99d98afdc41da5e53247adc36a07a3bf894750fbb0063f7
@@ -0,0 +1,2 @@
1
+ tmp/
2
+ *.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem "rspec"
7
+ gem "guard-rspec"
8
+ gem "pry"
9
+ end
@@ -0,0 +1,67 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ brackets (0.0.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ coderay (1.1.0)
10
+ diff-lcs (1.2.5)
11
+ ffi (1.9.10)
12
+ formatador (0.2.5)
13
+ guard (2.13.0)
14
+ formatador (>= 0.2.4)
15
+ listen (>= 2.7, <= 4.0)
16
+ lumberjack (~> 1.0)
17
+ nenv (~> 0.1)
18
+ notiffany (~> 0.0)
19
+ pry (>= 0.9.12)
20
+ shellany (~> 0.0)
21
+ thor (>= 0.18.1)
22
+ guard-compat (1.2.1)
23
+ guard-rspec (4.5.0)
24
+ guard (~> 2.1)
25
+ guard-compat (~> 1.1)
26
+ rspec (>= 2.99.0, < 4.0)
27
+ listen (3.0.4)
28
+ rb-fsevent (>= 0.9.3)
29
+ rb-inotify (>= 0.9)
30
+ lumberjack (1.0.9)
31
+ method_source (0.8.2)
32
+ nenv (0.2.0)
33
+ notiffany (0.0.8)
34
+ nenv (~> 0.1)
35
+ shellany (~> 0.0)
36
+ pry (0.10.3)
37
+ coderay (~> 1.1.0)
38
+ method_source (~> 0.8.1)
39
+ slop (~> 3.4)
40
+ rb-fsevent (0.9.6)
41
+ rb-inotify (0.9.5)
42
+ ffi (>= 0.5.0)
43
+ rspec (3.3.0)
44
+ rspec-core (~> 3.3.0)
45
+ rspec-expectations (~> 3.3.0)
46
+ rspec-mocks (~> 3.3.0)
47
+ rspec-core (3.3.2)
48
+ rspec-support (~> 3.3.0)
49
+ rspec-expectations (3.3.1)
50
+ diff-lcs (>= 1.2.0, < 2.0)
51
+ rspec-support (~> 3.3.0)
52
+ rspec-mocks (3.3.2)
53
+ diff-lcs (>= 1.2.0, < 2.0)
54
+ rspec-support (~> 3.3.0)
55
+ rspec-support (3.3.0)
56
+ shellany (0.0.1)
57
+ slop (3.6.0)
58
+ thor (0.19.1)
59
+
60
+ PLATFORMS
61
+ ruby
62
+
63
+ DEPENDENCIES
64
+ brackets!
65
+ guard-rspec
66
+ pry
67
+ rspec
@@ -0,0 +1,47 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features)
6
+
7
+ ## Uncomment to clear the screen before every task
8
+ # clearing :on
9
+
10
+ ## Guard internally checks for changes in the Guardfile and exits.
11
+ ## If you want Guard to automatically start up again, run guard in a
12
+ ## shell loop, e.g.:
13
+ ##
14
+ ## $ while bundle exec guard; do echo "Restarting Guard..."; done
15
+ ##
16
+ ## Note: if you are using the `directories` clause above and you are not
17
+ ## watching the project directory ('.'), then you will want to move
18
+ ## the Guardfile to a watched dir and symlink it back, e.g.
19
+ #
20
+ # $ mkdir config
21
+ # $ mv Guardfile config/
22
+ # $ ln -s config/Guardfile .
23
+ #
24
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
25
+
26
+ # Note: The cmd option is now required due to the increasing number of ways
27
+ # rspec may be run, below are examples of the most common uses.
28
+ # * bundler: 'bundle exec rspec'
29
+ # * bundler binstubs: 'bin/rspec'
30
+ # * spring: 'bin/rspec' (This will use spring if running and you have
31
+ # installed the spring binstubs per the docs)
32
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
33
+ # * 'just' rspec: 'rspec'
34
+
35
+ guard :rspec, cmd: "bundle exec rspec" do
36
+ require "guard/rspec/dsl"
37
+ dsl = Guard::RSpec::Dsl.new(self)
38
+
39
+ # RSpec files
40
+ rspec = dsl.rspec
41
+ watch(rspec.spec_helper) { rspec.spec_dir }
42
+ watch(rspec.spec_support) { rspec.spec_dir }
43
+ watch(rspec.spec_files)
44
+
45
+ # Ruby files
46
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
47
+ end
@@ -0,0 +1,17 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'brackets'
5
+ s.version = '0.0.1'
6
+ s.date = '2015-11-08'
7
+ s.summary = "A gem to generate tournament brackets"
8
+ s.description = "A gem to generate tournament brackets"
9
+ s.authors = ["Vitor HP Bittencourt"]
10
+ s.email = 'vitorhp2@gmail.com'
11
+
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files -- test/*`.split("\n")
14
+ s.require_paths = ["lib"]
15
+ s.homepage = 'http://rubygems.org/gems/brackets'
16
+ s.license = 'MIT'
17
+ end
@@ -0,0 +1,8 @@
1
+ module Brackets
2
+ autoload :Tournament, 'brackets/tournament'
3
+ autoload :Match, 'brackets/match'
4
+
5
+ module Util
6
+ autoload :BooleanCounter, 'brackets/util/boolean_counter'
7
+ end
8
+ end
@@ -0,0 +1,19 @@
1
+ module Brackets
2
+ class Match
3
+ attr_reader :winner, :deph, :number, :red, :blue
4
+
5
+ def initialize(deph = 0, number, red, blue)
6
+ @red, @blue, @deph, @number = red, blue, deph, number
7
+
8
+ @winner = blue.nil? ? red : nil
9
+ end
10
+
11
+ def placeholder?
12
+ @red.nil? && @blue.nil?
13
+ end
14
+
15
+ def to_s
16
+ "-"
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,76 @@
1
+ module Brackets
2
+ class Tournament
3
+ def initialize(counter = Brackets::Util::BooleanCounter.new)
4
+ @counter = counter
5
+ end
6
+
7
+ def generate(competitors)
8
+ generate_rounds(generate_first_round(competitors))
9
+ end
10
+
11
+ private
12
+
13
+ def generate_first_round(competitors)
14
+ c = competitors.dup
15
+
16
+ if c.size == 1
17
+ [build_match(1, [c.first, nil])]
18
+ else
19
+ placeholder_matches = generate_placeholder_matches(c)
20
+ exceeding_matches = generate_exceeding_matches(c)
21
+ normal_matches = c.each_slice(2).map do |slice|
22
+ build_match(1, slice)
23
+ end
24
+
25
+ placeholder_matches.concat(exceeding_matches).concat(normal_matches)
26
+ end
27
+ end
28
+
29
+ def generate_rounds(round, deph = 2)
30
+ if round.size == 1
31
+ round
32
+ else
33
+ matches = round.select{|m| m.deph == deph - 1 }.each_slice(2).map do |slice|
34
+ build_match(deph, slice)
35
+ end
36
+
37
+ round.concat(generate_rounds(matches, deph + 1))
38
+ end
39
+ end
40
+
41
+ def build_match(deph = 0, competitors)
42
+ red, blue = competitors
43
+
44
+ Match.new(deph, @counter.next_if(deph > 0, nil), red, blue)
45
+ end
46
+
47
+ def generate_exceeding_matches(competitors)
48
+ matches = exceeding_number_of_players_for(competitors.size).times.map do
49
+ build_match(0, competitors.slice!(0, 2))
50
+ end
51
+
52
+ exceeding_player_matches = matches.map do
53
+ build_match(1, [competitors.slice!(0)])
54
+ end
55
+
56
+ matches.concat(exceeding_player_matches)
57
+ end
58
+
59
+ def generate_placeholder_matches(competitors)
60
+ placeholder_matches_count = power_of_two_after(competitors.size) - competitors.size
61
+
62
+ placeholder_matches_count.times.map do
63
+ build_match(0, [nil, nil])
64
+ end
65
+ end
66
+
67
+ def power_of_two_after(x, pow = 1)
68
+ 2 ** pow >= x ? 2 ** pow : power_of_two_after(x, pow + 1)
69
+ end
70
+
71
+ def exceeding_number_of_players_for(size, pow = 1)
72
+ 2 ** pow > size ? size - (2 ** (pow - 1)) : exceeding_number_of_players_for(size, pow + 1)
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,13 @@
1
+ module Brackets
2
+ module Util
3
+ class BooleanCounter
4
+ def initialize
5
+ @counter = 0
6
+ end
7
+
8
+ def next_if(boolean, falsey_value = nil)
9
+ boolean ? @counter += 1 : falsey_value || @counter
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,113 @@
1
+ module Brackets
2
+ describe Tournament do
3
+ let(:anakin) { double("anakin") }
4
+ let(:obiwan) { double("obiwan") }
5
+ let(:maul) { double("maul") }
6
+ let(:mace) { double("mace") }
7
+ let(:yoda) { double("yoda") }
8
+ let(:shaak) { double("shaak") }
9
+ let(:kit) { double("kit") }
10
+ let(:plo) { double("plo") }
11
+
12
+ describe "#generate_round" do
13
+
14
+ subject { Tournament.new.generate(competitors) }
15
+
16
+ let(:competitors) { [anakin, obiwan, maul, mace] }
17
+
18
+ it "numbers the matches sequentially" do
19
+ expect(subject.map(&:number)).to eq([1, 2, 3])
20
+ end
21
+
22
+ context "with one participant" do
23
+ let(:competitors) { [anakin] }
24
+
25
+ it "generates one match with the only participant being the winner" do
26
+ expect(subject.length).to eq(1)
27
+ expect(subject.first).to be_a(Match)
28
+ expect(subject.first.winner).to eq(anakin)
29
+ end
30
+ end
31
+
32
+ context "with two competitors" do
33
+ let(:competitors) { [anakin, obiwan] }
34
+
35
+ it "generates one match with no winner" do
36
+ expect(subject.length).to eq(1)
37
+ expect(subject.first).to be_a(Match)
38
+ expect(subject.first.winner).to be(nil)
39
+ expect(subject.first.red).to be(anakin)
40
+ expect(subject.first.blue).to be(obiwan)
41
+ end
42
+ end
43
+
44
+ context "when number of competitors is a power of two" do
45
+ let(:competitors) { [yoda, mace, anakin, obiwan] }
46
+
47
+ it "generates matches from subsequent rounds" do
48
+ expect(subject.size).to eq(3)
49
+ expect(subject.last.red).to be_a(Match)
50
+ expect(subject.last.blue).to be_a(Match)
51
+ expect(subject.last.red.red).to be(yoda)
52
+ expect(subject.last.red.blue).to be(mace)
53
+ expect(subject.last.blue.red).to be(anakin)
54
+ expect(subject.last.blue.blue).to be(obiwan)
55
+ end
56
+ end
57
+
58
+ context "when number of competitors is not a power of two" do
59
+ let(:competitors) { [yoda, mace, anakin, obiwan, maul] }
60
+
61
+ it "puts the exceeding competitors against winners of the first round" do
62
+ expect(subject.select{ |m| m.deph == 0 }.size).to eq(4)
63
+ expect(subject.select{ |m| m.deph == 1 }.size).to eq(2)
64
+ expect(subject.select{ |m| m.deph == 2 }.size).to eq(1)
65
+ end
66
+
67
+ end
68
+
69
+
70
+ # context "with three competitors" do
71
+ # # TODO: Special case of three competitors
72
+ # subject { Tournament.new.generate_round([anakin, obiwan, maul], 0, 1) }
73
+
74
+ # it "generates three matches" do
75
+ # expect(subject.length).to eq(3)
76
+ # end
77
+
78
+ # it "has no winners on the first match" do
79
+ # expect(subject.first.winner).to eq(nil)
80
+ # end
81
+
82
+ # it "has a winner on the second match because there's only one guy" do
83
+ # expect(subject[1].winner).not_to eq(nil)
84
+ # end
85
+
86
+ # it "generates a final match with one participant from the second match", focus: true do
87
+ # expect(subject.last.red).to eq(nil)
88
+ # expect(subject.last.blue).not_to eq(nil)
89
+ # end
90
+
91
+ # it "sets deph of match accordingly" do
92
+ # expect(subject.first.deph).to eq(0)
93
+ # expect(subject[1].deph).to eq(0)
94
+ # expect(subject.last.deph).to eq(1)
95
+ # end
96
+
97
+ # it "numbers the matches sequentially" do
98
+ # expect(subject.first.number).to eq(1)
99
+ # expect(subject[1].number).to eq(2)
100
+ # expect(subject.last.number).to eq(3)
101
+ # end
102
+ # end
103
+
104
+ # context "when number of competitors is not a power of two" do
105
+ # subject { Tournament.new.generate_round([yoda, mace, anakin, obiwan, maul], 1, 1) }
106
+
107
+ # it "moves the remaining competitors to the second round" do
108
+ # expect(subject.size).to eq(4)
109
+ # end
110
+ # end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,22 @@
1
+ module Brackets::Util
2
+ describe BooleanCounter do
3
+ describe "#next_if" do
4
+ it "advances the counter when the param is true" do
5
+ expect(subject.next_if(true)).to eq(1)
6
+ end
7
+
8
+ it "keeps advancing if called multiple times" do
9
+ subject.next_if(true)
10
+ expect(subject.next_if(true)).to eq(2)
11
+ end
12
+
13
+ it "noes not advance the value when the param evals to false" do
14
+ expect(subject.next_if(false)).to eq(0)
15
+ end
16
+
17
+ it "returns the given value when param evals to false" do
18
+ expect(subject.next_if(false, "Nothing")).to eq("Nothing")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,7 @@
1
+ require 'pry'
2
+ require_relative "../lib/brackets.rb"
3
+
4
+ RSpec.configure do |config|
5
+ config.filter_run :focus
6
+ config.run_all_when_everything_filtered = true
7
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brackets
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vitor HP Bittencourt
@@ -15,7 +15,20 @@ email: vitorhp2@gmail.com
15
15
  executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
18
- files: []
18
+ files:
19
+ - ".gitignore"
20
+ - ".rspec"
21
+ - Gemfile
22
+ - Gemfile.lock
23
+ - Guardfile
24
+ - brackets.gemspec
25
+ - lib/brackets.rb
26
+ - lib/brackets/match.rb
27
+ - lib/brackets/tournament.rb
28
+ - lib/brackets/util/boolean_counter.rb
29
+ - spec/brackets/tournament_spec.rb
30
+ - spec/brackets/util/boolean_counter_spec.rb
31
+ - spec/spec_helper.rb
19
32
  homepage: http://rubygems.org/gems/brackets
20
33
  licenses:
21
34
  - MIT