-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplay.rb
253 lines (209 loc) · 6.46 KB
/
play.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
module PlayByPlay
module Model
# A Redux "action" or a finite-state machine transition.
class Play
TYPES = %i[
block
fg
fg_miss
ft
ft_miss
jump_ball
jump_ball_out_of_bounds
offensive_foul
period_end
personal_foul
rebound
shooting_foul
steal
team_rebound
technical_foul
turnover
].freeze
attr_accessor :opponent
attr_accessor :player
attr_accessor :seconds
attr_accessor :teammate
attr_reader :and_one
attr_reader :assisted
attr_reader :away_from_play
attr_reader :clear_path
attr_reader :flagrant
attr_reader :intentional
attr_reader :point_value
attr_reader :team
attr_reader :type
def self.block?(type)
type == :block
end
def self.foul?(type)
%i[ offensive_foul personal_foul shooting_foul technical_foul ].include?(type)
end
def self.jump_ball?(type)
type == :jump_ball
end
def self.rebound?(type)
type == :rebound
end
def self.shot?(type)
%i[ fg fg_miss ft ft_miss technical_ft technical_ft_miss ].include?(type)
end
def self.steal?(type)
type == :steal
end
def self.turnover?(type)
type == :turnover
end
def initialize(
type,
and_one: false,
assisted: false,
away_from_play: false,
clear_path: false,
flagrant: false,
intentional: false,
opponent: nil,
player: nil,
point_value: 2,
seconds: 7.7,
team: nil,
teammate: nil
)
@and_one = and_one
@assisted = assisted
@away_from_play = away_from_play
@clear_path = clear_path
@flagrant = flagrant
@intentional = intentional
@opponent = opponent
@point_value = point_value || 2
@player = player
@seconds = seconds
@team = team
@teammate = teammate
@type = type
validate!
end
def and_one?
and_one
end
def assisted?
assisted
end
def attributes
@attributes ||= create_attributes
end
def away_from_play?
away_from_play
end
def block?
Play.block? type
end
def clear_path?
clear_path
end
def create_attributes
attributes = {}
attributes[:and_one] = true if and_one?
attributes[:assisted] = true if assisted?
attributes[:away_from_play] = true if away_from_play?
attributes[:clear_path] = true if clear_path?
attributes[:flagrant] = true if flagrant?
attributes[:intentional] = true if intentional?
attributes[:point_value] = point_value if point_value == 3
attributes[:team] = team if set_team?
attributes
end
def flagrant?
flagrant
end
def foul?
Play.foul? type
end
def intentional?
intentional
end
def jump_ball?
Play.jump_ball? type
end
def key
if attributes.empty?
[ type ]
else
[ type, attributes ]
end
end
def period_end?
type == :period_end
end
def rebound?
Play.rebound? type
end
def set_team?
team && %i[
jump_ball
jump_ball_out_of_bounds
personal_foul
rebound
team_rebound
technical_foul
turnover
].include?(type)
end
def shot?
Play.shot? type
end
def steal?
Play.steal? type
end
def turnover?
Play.turnover? type
end
def technical_foul?
type == :technical_foul
end
def validate_player_attribute(attribute)
value = send(attribute)
if value && (value < 0 || value > 12)
raise(ArgumentError, "#{attribute}: must be player between 0-12, but is: #{value}")
end
end
def validate!
raise(ArgumentError, "Unknown Play type '#{type}'. Expected: #{TYPES.join(', ')}.") unless TYPES.include?(type)
raise(ArgumentError, "teammate required for #{type} in #{key}") if assisted? && teammate.nil?
raise(ArgumentError, "player required for #{type} in #{key}") if block? && player.nil?
raise(ArgumentError, "player required for #{type} in #{key}") if shot? && player.nil?
raise(ArgumentError, "player required for #{type} in #{key}") if steal? && player.nil?
raise(ArgumentError, "player required for #{type} in #{key}") if turnover? && player.nil?
raise(ArgumentError, "player required for #{type} in #{key}") if jump_ball? && player.nil?
raise(ArgumentError, "opponent required for #{type} in #{key}") if block? && opponent.nil?
raise(ArgumentError, "opponent required for #{type} in #{key}") if steal? && opponent.nil?
if foul? && !player
raise(ArgumentError, "player required for #{type} in #{key}")
end
if foul? && !technical_foul? && !player
raise(ArgumentError, "player required for #{type} in #{key}")
end
if jump_ball? && !teammate
raise(ArgumentError, "teammate required for #{type} in #{key}")
end
if jump_ball? && !opponent
raise(ArgumentError, "opponent required for #{type} in #{key}")
end
if seconds.nil?
raise(ArgumentError, "seconds cannot be nil")
end
raise(ArgumentError, "opponent not allowed for #{type} in #{key}") if shot? && opponent
raise(ArgumentError, "teammate not allowed for #{type} in #{key}") if steal? && teammate
raise(ArgumentError, "teammate not allowed for #{type} in #{key}") if turnover? && teammate
raise(ArgumentError, "opponent not allowed for #{type} in #{key}") if turnover? && opponent
raise(ArgumentError, "teammate not allowed for #{type} in #{key}") if foul? && teammate
raise(ArgumentError, "teammate not allowed for #{type} in #{key}") if block? && teammate
if player && player == teammate
raise(ArgumentError, "player and teammate must be different but are both #{player} for #{type} in #{key}")
end
%w[ opponent player teammate ].each { |attribute| validate_player_attribute(attribute) }
end
end
end
end