tennis 0.1.7 → 0.2.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: 071d8da8d7b39b88163c917635cff96a913bafcd
4
- data.tar.gz: 63252be0e608ee1d0f597d36c0333d24b8256606
3
+ metadata.gz: ce621f74414d103564e2bcc239a788d487c912ee
4
+ data.tar.gz: 7fb8ec8e853cf6b05f775aed1ad42a95fe982d34
5
5
  SHA512:
6
- metadata.gz: e9a0401551a28c70dd2cd3106196c3ec3d8723ff603ed5ef7250c077e3d76c41f74747a698594fb58929c41c154cdfdb92c880b08814b639569732b4457e2d67
7
- data.tar.gz: 66c54ec51b6a0f6520d4caa602c3eacdd950eb43736c749da85a4f294cbca106b820cf8c35a4f9d0faa209be8cd24d2d5337f369b5ac61cc59186b4198986399
6
+ metadata.gz: e693fb0265a8e3934b631971f86a57320003ac1fe82863ad840478cc3ab57cf5107f98e9d314483ee8b6a5fe59338ea45e2723b7d7a06f2752e94d35f1974ec4
7
+ data.tar.gz: f69de2817fda3554545f98af969f1dbf6d2dbceafff7f43c3b6109d0adbb3fde5889bc4ad870ad8a893ca8b7966dd8698ff76e9fe8f1277d63ad77717796ee7d
data/Makefile CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- VERSION=0.1.6
2
+ VERSION=0.2.0
3
3
 
4
4
  all:
5
5
  rake spec
@@ -1,3 +1,3 @@
1
1
  class Tennis
2
- VERSION = "0.1.7"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/tennis.rb CHANGED
@@ -4,180 +4,78 @@ class Tennis
4
4
  # player 1 is the home player(0) , player 2 is the away player(1)
5
5
  # winner is either 0 or 1
6
6
  # points is an array: [points for 0 , points for 1]
7
- # sets_lost is an array: [sets lost by 0, sets lost by 1]
8
- # games_lost is an array: [games won by 0, games won by 1]
7
+ # sets_won/lost is an array: [sets won/lost by 0, sets won/lost by 1]
8
+ # games_won/lost is an array: [games won/lost by 0, games won/lost by 1]
9
9
 
10
- attr_reader :winner, :points, :sets_lost, :games_lost
10
+ attr_reader :winner, :sets_won, :sets_lost, :games_won, :games_lost
11
11
 
12
- def initialize(scores)
12
+ def initialize(score)
13
13
  # dfh -> default win for home player(0)
14
14
  # dfa -> default win for away player(1)
15
- @winner = :default
16
- @scores = validate_score(scores)
17
- @winner = match_winner if @winner == :default
18
- @points = match_points
19
- unless @scores.is_a? String
20
- @sets_lost = count_sets_lost
21
- @games_lost = count_games_lost
22
- end
15
+ process_score(score)
23
16
  end
24
17
 
25
18
  # to_s
26
19
  # return the score in string format
27
20
  def to_s
28
- (0...@scores.length).step(2).map{ |i| [@scores[i], @scores[i+1]].join('-') }.join(', ')
21
+ @score.map{|set| set.join('-') }.join(', ')
29
22
  end
30
23
 
31
24
  # flip score ( P1-P2 to P2-P1)
32
25
  # returns the flipped score as a string
33
26
  def flipped
34
- (0...@scores.length).step(2).map{ |i| [@scores[i+1], @scores[i]].join('-') }.join(', ')
27
+ @score.map{|set| set.reverse.join('-') }.join(', ')
35
28
  end
36
29
 
37
30
  private
38
31
 
39
- # helper method: to check score validation
40
- def validate_score(scores_string)
41
- set_scores = scores_string.split(/[-,,]/).map(&:to_i)
42
- if set_scores == [0]
43
- # checks bad default string value reported
44
- @winner = (0 if scores == 'dfh') || (1 if scores == 'dfa') || :error
45
- scores_string
46
- else
47
- # check blank input ''
48
- validation_1 = set_scores.any? { |score| score.nil? }
49
- # to check if score for only 1 set has been input
50
- validation_2 = set_scores.length == 2
51
- # to check if any input > 7
52
- validation_3 = set_scores.any? { |score| score > 7 }
53
- # to check if one of the input is 7 and the other is not 6
54
- # bad tie break input
55
- validation_4 = false
56
- set_scores.each_slice(2).each { |r| validation_4 = true if r.any? { |score| score == 7 } && !r.any? { |score| score == 6 || score == 5 } }
57
- @winner = :error if validation_1 || validation_2 || validation_3 || validation_4
58
- # if set score is not complete eg: 4-6,7-6,4-1
59
- set_scores.each_slice(2).each {|r| @winner = :incomplete_match if r[0] < 6 && r[1] < 6 } unless @winner == :error
60
- set_scores
61
- end
62
- end
63
-
64
- # returns who won the match
65
- # :incomplete_match (bad input/incomplete match)
66
- # :error (bad input for sure)
67
- # 0 (player-1 won)
68
- # 1 (player-2 won)
69
- def match_winner
70
- @scores.length == 4 ? two_sets : three_sets
71
- end
72
-
73
- # returns an array of points
74
- # returns (points_player_1 , points_player_2)
75
- # returns (0,0) for bad input
76
- def match_points
77
- return [0, 0] if @winner == :error
78
- return [@scores == 'dfh' ? 12 : 0, @scores == 'dfa' ? 12 : 0] if @scores.is_a? String
79
- @winner == 0 || @winner == 1 ? complete_match_points : incomplete_match_points
80
- end
81
-
82
- # returns the number of sets lost by each player
83
- def count_sets_lost
84
- sets = [0, 0]
85
- (0...@scores.length).step(2).each do |i|
86
- @scores[i] > @scores[i + 1] ? sets[1] += 1 : sets[0] += 1
87
- end
88
- sets
89
- end
90
-
91
- # returns the number of won by each player
92
- def count_games_lost
93
- games = [0, 0]
94
- (0...@scores.length).step(2).each do |i|
95
- games[0] += @scores[i + 1]
96
- games[1] += @scores[i]
32
+ def process_score(score, best_of=3)
33
+ begin
34
+ sets = score.split(/,/)
35
+ # only take 2 to 5 sets
36
+ raise "invalid number of sets" unless (2..best_of).cover? sets.length
37
+ score_plus_winner = map_scores_winners(sets)
38
+ @set_winners = score_plus_winner.map{ |sw| sw[1] }
39
+ home = @set_winners.count(0)
40
+ away = @set_winners.count(1)
41
+ raise "nobody won" if home + away == 0
42
+ @winner = home > away ? 0 : away > home ? 1 : raise("no winner")
43
+ # sets won and lost
44
+ @sets_won, @sets_lost = [[home, away], [away, home]]
45
+ # score array
46
+ @score = score_plus_winner.map{ |sw| sw[0] }
47
+ @games_won = @score.transpose.map{ |games| games.inject{ |sum,x| sum + x } }
48
+ @games_lost = @games_won.reverse
49
+ # FIXME this is the only thing that assumes 3 sets
50
+ raise "too many sets" if @set_winners[0] == @set_winners[1] and sets.size > 2
51
+ rescue => e
52
+ raise ArgumentError, "Invalid score '#{score}': #{e}"
97
53
  end
98
- games
99
54
  end
100
55
 
101
- # returns the number of sets won by each player
102
- def sets_won
103
- sets = [0, 0]
104
- (0...@scores.length).step(2).each do |i|
105
- @scores[0 + i] > @scores[1 + i] ? sets[0] += 1 : sets[1] += 1
56
+ # return an array of scores and winners for each set
57
+ def map_scores_winners(sets)
58
+ sets.map do |set|
59
+ set.strip!
60
+ games = set.split(/-/).map(&:to_i)
61
+ raise "uneven games in set '#{set}'" unless games.length == 2
62
+ h, a = games
63
+ sw = set_winner(h, a)
64
+ raise "no valid winner in set '#{set}'" unless sw
65
+ [games, sw]
106
66
  end
107
- sets
108
67
  end
109
68
 
110
- # returns the number of won by each player
111
- def games_won
112
- games = [0, 0]
113
- (0...@scores.length).step(2).each do |i|
114
- games[0] += @scores[0 + i]
115
- games[1] += @scores[1 + i]
116
- end
117
- games
69
+ # determine the set winner for home and away, or else return nil
70
+ def set_winner(h, a)
71
+ # basic range check
72
+ return nil if h > 7 or a > 7 or h < 0 or a < 0
73
+ # game went to 7
74
+ return 0 if h == 7 and [5,6].include?(a)
75
+ return 1 if a == 7 and [5,6].include?(h)
76
+ # there has to be one winner, to 6
77
+ return nil unless (h == 6 and h > a + 1) or (a == 6 and a > h + 1)
78
+ h > a ? 0 : 1
118
79
  end
119
80
 
120
- # helper method: called by RESULT method for valid matches with 2 sets
121
- def two_sets
122
- set_results = []
123
- (0...@scores.length).step(2).each do |i|
124
- # tie breaker (assuming a 7 point tie breaker) or a 7-5 scores
125
- if @scores[i] == 7 || @scores[i + 1] == 7
126
- set_results << (@scores[i] == 7 ? 0 : 1)
127
- # regular set victory - 6 games with a margin of 2
128
- else
129
- return :incomplete_match if ( @scores[i] - @scores[i + 1] ).abs < 2
130
- set_results << (@scores[i] == 6 ? 0 : 1)
131
- end
132
- end
133
- # incomplete match e.g: 6-4,5-3
134
- (set_results[0] if set_results[0] == set_results[1]) || :incomplete_match
135
- end
136
-
137
- # helper method: called by RESULT method for valid matches with 3 sets
138
- def three_sets
139
- set_results = []
140
- (0...@scores.length).step(2).each do |i|
141
- # tie breaker (assuming a 7 point tie breaker) or a 7-5 score
142
- if @scores[i] == 7 || @scores[i + 1] == 7
143
- set_results << (@scores[i] == 7 ? 0 : 1)
144
- # regular set victory - 6 games with a margin of 2
145
- else
146
- return :incomplete_match if (@scores[i] - @scores[i + 1]).abs < 2
147
- set_results << (@scores[i] == 6 ? 0 : 1)
148
- end
149
- end
150
- # checks if the result has been decided in the first 2 sets
151
- # but the 3rd set is also present in the input
152
- return :error if set_results[0] == set_results[1]
153
- set_results.count(0) == 2 ? 0 : 1
154
- end
155
-
156
- # helper method: called by POINTS for complete matches
157
- def complete_match_points
158
- points = [0, 0]
159
- points[@winner] = (@scores.length == 6) ? 12 : 14
160
- runner_up = 1 - @winner
161
- runner_up_points = player_points(runner_up)
162
- points[runner_up] = runner_up_points < 8 ? runner_up_points : 8
163
- points
164
- end
165
-
166
- # helper method: called by POINTS for incomplete matches
167
- def incomplete_match_points
168
- points = [0, 0]
169
- player_1_points = player_points(0)
170
- player_2_points = player_points(1)
171
- points[0] = player_1_points < 10 ? player_1_points : 10
172
- points[1] = player_2_points < 10 ? player_2_points : 10
173
- points
174
- end
175
-
176
- # helper method: returns the POINTS of a player given the player number
177
- def player_points(player)
178
- player_scores = []
179
- @scores.each_with_index { |score, index| (player_scores << score; player += 2) if index == (player) }
180
- player_scores = player_scores.sort! { |x, y| y <=> x }
181
- player_scores[0] + player_scores[1]
182
- end
183
81
  end
data/spec/tennis_spec.rb CHANGED
@@ -28,90 +28,44 @@ describe Tennis, "#scores" do
28
28
  end
29
29
 
30
30
  it "reports incomplete match score (set 1-1)" do
31
- score = Tennis.new("6-4,4-6")
32
- expect(score.winner).to eq :incomplete_match
31
+ expect { Tennis.new("6-4,4-6") }.to raise_error
33
32
  end
34
33
 
35
34
  it "reports incomplete match score (set incomplete)" do
36
- score = Tennis.new("6-4,4-5")
37
- expect(score.winner).to eq :incomplete_match
35
+ expect { Tennis.new("6-4,4-5") }.to raise_error
38
36
  end
39
37
 
40
38
  it "checks invalid score: difference in games won < 2" do
41
- score = Tennis.new("6-5,4-6,7-6")
42
- expect(score.winner).to eq :incomplete_match
39
+ expect { Tennis.new("6-5,4-6,7-6") }.to raise_error
43
40
  end
44
41
 
45
42
  it "checks invalid score: only 1 set input" do
46
- score = Tennis.new("6-4")
47
- expect(score.winner).to eq :error
43
+ expect { Tennis.new("6-4") }.to raise_error
48
44
  end
49
45
 
50
46
  it "checks invalid score: winner decided in first 2 sets but 3rd set input" do
51
- score = Tennis.new("6-4,6-4,4-6")
52
- expect(score.winner).to eq :error
47
+ expect { Tennis.new("6-4,6-4,4-6") }.to raise_error
53
48
  end
54
49
 
55
50
  it "checks invalid score: bad input for tie break" do
56
- score = Tennis.new("7-0,4-6,6-2")
57
- expect(score.winner).to eq :error
51
+ expect { Tennis.new("7-0,4-6,6-2") }.to raise_error
58
52
  end
59
53
 
60
54
  it "checks invalid score: no score > 7" do
61
- score = Tennis.new("8-4,2-6,6-1")
62
- expect(score.winner).to eq :error
55
+ expect { Tennis.new("8-4,2-6,6-1") }.to raise_error
63
56
  end
64
57
 
65
- it "checks invalid score: blank score '' " do
66
- score = Tennis.new("")
67
- expect(score.winner).to eq :error
58
+ it "checks invalid score: blank score ''" do
59
+ expect { Tennis.new("") }.to raise_error
68
60
  end
69
61
 
70
62
  it "finds the winner properly in scores with 7-5" do
71
63
  score = Tennis.new("3-6,5-7")
72
64
  expect(score.winner).to eq 1
73
65
  end
74
- end
75
-
76
- describe Tennis, "#points" do
77
- it "returns 12 points in a three set win in a complete match" do
78
- score = Tennis.new("6-4, 4-6, 6-4")
79
- expect(score.points).to eq [12,8]
80
- end
81
-
82
- it "returns 14 points in two set win in a complete match" do
83
- score = Tennis.new("4-6, 4-6")
84
- expect(score.points).to eq [8,14]
85
- end
86
66
 
87
- it "returns a max of 8 points for the runners up in a complete match" do
88
- score = Tennis.new("4-6, 6-2, 3-6")
89
- expect(score.points).to eq [8,12]
90
- end
91
-
92
- it "return a max of 10 points for each player in an incomplete match" do
93
- score = Tennis.new("7-6,6-7")
94
- expect(score.points).to eq [10,10]
95
- end
96
-
97
- it "return a max of 10 points for each player in an incomplete match" do
98
- score = Tennis.new("7-6,4-6,4-1")
99
- expect(score.points).to eq [10,10]
100
- end
101
-
102
- it "return [0,0] for bad input" do
103
- score = Tennis.new("8-1")
104
- expect(score.points).to eq [0,0]
105
- end
106
-
107
- it "checks invalid score: blank score '' " do
108
- score = Tennis.new("")
109
- expect(score.points).to eq [0,0]
110
- end
111
-
112
- it "finds the points properly in scores with 7-5" do
113
- score = Tennis.new("3-6,5-7")
114
- expect(score.points).to eq [8,14]
67
+ it "raises exception for bad input" do
68
+ expect { Tennis.new("8-1") }.to raise_error
115
69
  end
116
70
  end
117
71
 
@@ -138,7 +92,7 @@ end
138
92
 
139
93
  describe Tennis, "#sets_lost" do
140
94
  it "returns the sets lost by each player" do
141
- scores = [["6-4, 4-6, 6-4", [1,2]],["6-2,6-1", [0, 2]], ["7-6,4-6,6-4", [1, 2]], ["6-4", [0,1]]]
95
+ scores = [["6-4, 4-6, 6-4", [1,2]],["6-2,6-1", [0, 2]], ["7-6,4-6,6-4", [1, 2]], ["6-4, 6-1", [0, 2]]]
142
96
  scores.each do |s|
143
97
  ts = Tennis.new(s[0])
144
98
  expect(ts.sets_lost).to eq s[1]
@@ -148,7 +102,7 @@ end
148
102
 
149
103
  describe Tennis, "#games_lost" do
150
104
  it "returns the games won by each player" do
151
- scores = [["6-4, 4-6, 6-4", [14,16]],["6-2,6-1", [3, 12]], ["7-6,4-6,6-4", [16, 17]], ["6-4", [4,6]]]
105
+ scores = [["6-4, 4-6, 6-4", [14,16]],["6-2,6-1", [3, 12]], ["7-6,4-6,6-4", [16, 17]], ["6-4, 7-5", [9, 13]]]
152
106
  scores.each do |s|
153
107
  ts = Tennis.new(s[0])
154
108
  expect(ts.games_lost).to eq s[1]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tennis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rohan Katyal
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-02-13 00:00:00.000000000 Z
12
+ date: 2015-02-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler