moneyball 0.0.1.alpha → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +2 -1
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +31 -4
- data/Rakefile +7 -1
- data/lib/moneyball.rb +4 -0
- data/lib/moneyball/batted_ball_location_extractor.rb +72 -0
- data/lib/moneyball/batted_ball_type_extractor.rb +48 -0
- data/lib/moneyball/parser.rb +214 -0
- data/lib/moneyball/version.rb +1 -1
- data/moneyball.gemspec +5 -13
- metadata +24 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f39378b88ae0c5a200beb76783c60706afd65ec
|
4
|
+
data.tar.gz: f114082afb54865c8b46754c2660317361c948fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c38fede0049073f02ded2636e7a70c86f1d52aa58b0c3e4e4780321c35309675f4321489b531d6308a4280567c455053a7a041f1eea1fe1ff69036d8989617f
|
7
|
+
data.tar.gz: 0227f09c11bd500e0b5d25cf70572145b9088b52f6adae422c9161e66a0ef5fe2c8eda50f3867fe8d56b380354bc55afdf7b6e499f0f5ecf797bf30f5e9601d6
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/{LICENSE.txt → LICENSE}
RENAMED
File without changes
|
data/README.md
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
[![Code Climate](https://codeclimate.com/github/geoffharcourt/moneyball/badges/gpa.svg)](https://codeclimate.com/github/geoffharcourt/moneyball)
|
1
2
|
# Moneyball
|
3
|
+
[![Build Status](https://travis-ci.org/geoffharcourt/moneyball.svg?branch=master)](https://travis-ci.org/geoffharcourt/moneyball)
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
Moneyball parses MLB Gameday's play-by-play information to pull useful
|
6
|
+
quantitative and qualitative information out of the data feed. Moneyball can
|
7
|
+
determine where a batted ball was hit, the general classification of the batted
|
8
|
+
ball, and stat line information from the plate appearance.
|
6
9
|
|
7
10
|
## Installation
|
8
11
|
|
@@ -22,7 +25,23 @@ Or install it yourself as:
|
|
22
25
|
|
23
26
|
## Usage
|
24
27
|
|
25
|
-
|
28
|
+
`Moneyball::Parser` takes a Nokogiri XML node.
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
raw_xml = '<atbat event="Strikeout" des="Ty Cobb strikes out swinging."></atbat>'
|
32
|
+
nokogiri_node = Nokogiri::XML(raw_xml).search("atbat").first
|
33
|
+
stats = Moneyball::Parser.new(nokogiri_node).stats
|
34
|
+
|
35
|
+
stats.slice(:pa, :ab, :h, :k) # => { pa: 1, ab: 1, h: 0, k: 1 }
|
36
|
+
```
|
37
|
+
|
38
|
+
`Moneyball::BattedBallLocationExtractor` and `Moneyball::BattedBallTypeExtractor` take a string from the play-by-play summary.
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
summary = "Billy Hamilton hits a fly ball home run (22) to deep center field."
|
42
|
+
Moneyball::BattedBallTypeExtractor.new(summary).categorize # => "Line drive"
|
43
|
+
Moneyball::BattedBallLocationExtractor.new(summary).categorize # => "CF"
|
44
|
+
```
|
26
45
|
|
27
46
|
## Development
|
28
47
|
|
@@ -32,8 +51,16 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
32
51
|
|
33
52
|
## Contributing
|
34
53
|
|
54
|
+
This is a work in progress! I have been using pieces of this code in private projects, but it's time for the saber community to get a crack at improving this code.
|
55
|
+
|
56
|
+
Any contributions should come with tests (we use RSpec) and a well documented PR. If you have a specific event from the Gameday feed that prompted your pull request, please reference it in your PR.
|
57
|
+
|
58
|
+
Here's how to contribute!
|
35
59
|
1. Fork it ( https://github.com/[my-github-username]/moneyball/fork )
|
36
60
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
37
61
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
38
62
|
4. Push to the branch (`git push origin my-new-feature`)
|
39
63
|
5. Create a new Pull Request
|
64
|
+
|
65
|
+
## License
|
66
|
+
Moneyball is © 2015 Geoff Harcourt. It is free software, and may be redistributed under the terms specified in the LICENSE file.
|
data/Rakefile
CHANGED
data/lib/moneyball.rb
CHANGED
@@ -0,0 +1,72 @@
|
|
1
|
+
module Moneyball
|
2
|
+
class BattedBallLocationExtractor
|
3
|
+
def initialize(event_description)
|
4
|
+
@event_description = event_description
|
5
|
+
end
|
6
|
+
|
7
|
+
def classification
|
8
|
+
case
|
9
|
+
when event_description.match(deflected_by_regex("first baseman")) then "1B"
|
10
|
+
when event_description.match(deflected_by_regex("second baseman")) then "2B"
|
11
|
+
when event_description.match(deflected_by_regex("third baseman")) then "3B"
|
12
|
+
when event_description.match(deflected_by_regex("shortstop")) then "SS"
|
13
|
+
when event_description.match(unassisted_regex("first baseman")) then "1B"
|
14
|
+
when event_description.match(unassisted_regex("second baseman")) then "2B"
|
15
|
+
when event_description.match(unassisted_regex("third baseman")) then "3B"
|
16
|
+
when event_description.match(unassisted_regex("shortstop")) then "SS"
|
17
|
+
when event_description.match(infielder_regex("catcher")) then "C"
|
18
|
+
when event_description.match(infielder_regex("first baseman")) then "1B"
|
19
|
+
when event_description.match(infielder_regex("second baseman")) then "2B"
|
20
|
+
when event_description.match(infielder_regex("third baseman")) then "3B"
|
21
|
+
when event_description.match(infielder_regex("shortstop")) then "SS"
|
22
|
+
when event_description.match(infielder_regex("pitcher")) then "P"
|
23
|
+
when event_description.match(outfielder_regex("left")) then "LF"
|
24
|
+
when event_description.match(outfielder_regex("center")) then "CF"
|
25
|
+
when event_description.match(outfielder_regex("right")) then "RF"
|
26
|
+
when event_description.match(flies_into_sacrifice_double_play_regex("left"))
|
27
|
+
"LF"
|
28
|
+
when event_description.match(flies_into_sacrifice_double_play_regex("center"))
|
29
|
+
"CF"
|
30
|
+
when event_description.match(flies_into_sacrifice_double_play_regex("right"))
|
31
|
+
"RF"
|
32
|
+
when event_description.match(/(caught stealing|fan interference|hit by pitch|reaches on catcher interference|strikes out|out on strikes|walks)/)
|
33
|
+
nil
|
34
|
+
when event_description.match(/(passed ball|wild pitch).+out at/) then nil
|
35
|
+
when event_description.match(/picks off/) then nil
|
36
|
+
when event_description.match(/\AThrowing error by/) then nil
|
37
|
+
when event_description.match(/\A(\w+ challenged([A-Za-z\s\(\)\-\,])+\:)?([A-Za-z]|\s)+(, Jr.)? out at /)
|
38
|
+
nil
|
39
|
+
when event_description.match(/ (doubles|hits a home run|singles|triples)\.\s+\Z/) then nil
|
40
|
+
else
|
41
|
+
raise "No match for batted ball location on '#{event_description}'"
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
attr_reader :event_description
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def deflected_by_regex(position)
|
53
|
+
/deflected by #{position}/
|
54
|
+
end
|
55
|
+
|
56
|
+
def infielder_regex(position)
|
57
|
+
/(ball to|bunt(,| to)|fielded by|(F|f)ielding error by|fly to|line drive to|reaches on a (force attempt, )?missed catch error by [A-Za-z\s\.]+, assist to|out( sharply| softly)? ?(,| to)|play,|pop up to|reaches on a(n)? (fielding |throwing )?error by|reaches on a force attempt, throwing error by|bunt\.\s+Throwing error by|pops into a double play in foul territory,) ?#{position}/
|
58
|
+
end
|
59
|
+
|
60
|
+
def outfielder_regex(position)
|
61
|
+
/((ground|fly) ball|drive|fielding error|flies into a double play|fly|grand slam( \(\d?\))|lines into a double play|out)( sharply| softly)?(,| by| down the| to) #{position}(-field line)?/
|
62
|
+
end
|
63
|
+
|
64
|
+
def flies_into_sacrifice_double_play_regex(position)
|
65
|
+
/flies into a sacrifice double play(,| to) #{position} fielder/
|
66
|
+
end
|
67
|
+
|
68
|
+
def unassisted_regex(position)
|
69
|
+
/#{position}[A-Za-z\s]+unassisted/
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Moneyball
|
2
|
+
class BattedBallTypeExtractor
|
3
|
+
def initialize(event_description)
|
4
|
+
@event_description = event_description
|
5
|
+
end
|
6
|
+
|
7
|
+
def classification
|
8
|
+
case
|
9
|
+
when event_description.match(/line(s)? (drive|into|out)/)
|
10
|
+
"Line drive"
|
11
|
+
when event_description.match(/fl(ies|y) (ball|out)/)
|
12
|
+
"Fly ball"
|
13
|
+
when event_description.match(/sacrifice fly/)
|
14
|
+
"Fly ball"
|
15
|
+
when event_description.match(/flies into a/)
|
16
|
+
"Fly ball"
|
17
|
+
when event_description.match(/ground(s)?( (ball|into|out)|, fielded)/)
|
18
|
+
"Ground ball"
|
19
|
+
when event_description.match(/fielder's choice/)
|
20
|
+
"Ground ball"
|
21
|
+
when event_description.match(/((hits|out on) a sacrifice|ground) bunt/)
|
22
|
+
"Ground ball"
|
23
|
+
when event_description.match(/reaches on a(n)? ((fielding |missed catch |throwing )?error|force attempt)/)
|
24
|
+
"Ground ball"
|
25
|
+
when event_description.match(/pop(s)? (into a(n)? (unassisted )?double play|(into a force )?out|up)/)
|
26
|
+
"Pop up"
|
27
|
+
when event_description.match(/(grand slam|home run)/)
|
28
|
+
"Fly ball"
|
29
|
+
when event_description.match(/(\AThrowing error|catcher interference|caught stealing|fan interference|hit by pitch|strikes out|out on strikes|walks)/)
|
30
|
+
nil
|
31
|
+
when event_description.match(/(passed ball|wild pitch).+out at/) then nil
|
32
|
+
when event_description.match(/picks off/) then nil
|
33
|
+
when event_description.match(/\A(\w+ challenged ([A-Za-z]|\s|\(|\)|\-|\,)+\:)?([A-Za-z]|\s)+(, Jr.)? out at /)
|
34
|
+
nil
|
35
|
+
when event_description.match(/ triples\.\s+\Z/) then nil
|
36
|
+
when event_description.match(/ doubles\.\s+\Z/) then nil
|
37
|
+
when event_description.match(/ singles\.\s+\Z/) then nil
|
38
|
+
else
|
39
|
+
raise "No match for batted ball type on '#{event_description}'"
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
attr_reader :event_description
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
module Moneyball
|
2
|
+
class Parser
|
3
|
+
def initialize(node)
|
4
|
+
@node = node
|
5
|
+
end
|
6
|
+
|
7
|
+
def stats
|
8
|
+
{
|
9
|
+
pa: pa,
|
10
|
+
ab: ab,
|
11
|
+
h: h,
|
12
|
+
h_1b: h_1b,
|
13
|
+
h_2b: h_2b,
|
14
|
+
h_3b: h_3b,
|
15
|
+
hr: hr,
|
16
|
+
bb: bb,
|
17
|
+
ibb: ibb,
|
18
|
+
k: k,
|
19
|
+
roe: roe,
|
20
|
+
gidp: gidp,
|
21
|
+
dp: dp,
|
22
|
+
tp: tp,
|
23
|
+
hbp: hbp,
|
24
|
+
sf: sf,
|
25
|
+
sh: sh,
|
26
|
+
fc: fc,
|
27
|
+
bi: bi,
|
28
|
+
ci: ci,
|
29
|
+
fi: fi,
|
30
|
+
r: r,
|
31
|
+
rbi: rbi
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
attr_reader :node
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def batter_id
|
42
|
+
@batter_id ||= node.attribute("batter").value
|
43
|
+
end
|
44
|
+
|
45
|
+
def r
|
46
|
+
@r = node.search("runner[id='#{batter_id}'][score='T']").any? ? 1 : 0
|
47
|
+
end
|
48
|
+
|
49
|
+
def rbi
|
50
|
+
@r = node.search("runner[rbi='T']").count
|
51
|
+
end
|
52
|
+
|
53
|
+
def event_value
|
54
|
+
@event_value ||= node.attribute("event").value
|
55
|
+
end
|
56
|
+
|
57
|
+
def event_matches(regex)
|
58
|
+
if event_value.match(regex)
|
59
|
+
1
|
60
|
+
else
|
61
|
+
0
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def any_outcomes_occurred(outcomes)
|
66
|
+
if outcomes.any? { |outcome| outcome == 1 }
|
67
|
+
1
|
68
|
+
else
|
69
|
+
0
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def ab
|
74
|
+
@ab ||= any_outcomes_occurred([
|
75
|
+
h,
|
76
|
+
k,
|
77
|
+
batted_out,
|
78
|
+
double_play,
|
79
|
+
tp,
|
80
|
+
roe,
|
81
|
+
force_out,
|
82
|
+
fc,
|
83
|
+
bi,
|
84
|
+
fi
|
85
|
+
])
|
86
|
+
end
|
87
|
+
|
88
|
+
def bi
|
89
|
+
@bi ||= event_matches(/Batter Interference/)
|
90
|
+
end
|
91
|
+
|
92
|
+
def bb
|
93
|
+
@bb ||= event_matches(/Walk/)
|
94
|
+
end
|
95
|
+
|
96
|
+
def ibb
|
97
|
+
@ibb ||= event_matches(/(I|i)ntent(ional)? (W|w)alk/)
|
98
|
+
end
|
99
|
+
|
100
|
+
def ci
|
101
|
+
@ci ||= event_matches(/Catcher Interference/)
|
102
|
+
end
|
103
|
+
|
104
|
+
def gidp
|
105
|
+
@gidp ||= event_matches(/((G|g)rounded (I|i)nto|Sacrifice Bunt) DP/)
|
106
|
+
end
|
107
|
+
|
108
|
+
def dp
|
109
|
+
@dp ||= any_outcomes_occurred([gidp, double_play, sacrifice_double_play])
|
110
|
+
end
|
111
|
+
|
112
|
+
def tp
|
113
|
+
@tp ||= event_matches(/(T|t)riple (P|p)lay/)
|
114
|
+
end
|
115
|
+
|
116
|
+
def sacrifice_double_play
|
117
|
+
@sacrifice_double_play ||= event_matches(/Sac (Bunt|Fly) DP/)
|
118
|
+
end
|
119
|
+
|
120
|
+
def double_play
|
121
|
+
@double_play ||= event_matches(/((D|d)ouble (P|p)lay| - DP)/)
|
122
|
+
end
|
123
|
+
|
124
|
+
def fc
|
125
|
+
@fc ||= event_matches(/Fielders Choice( Out)?/)
|
126
|
+
end
|
127
|
+
|
128
|
+
def fi
|
129
|
+
@fi ||= event_matches(/Fan (I|i)nterference/)
|
130
|
+
|
131
|
+
if @fi
|
132
|
+
parse_hit_from_description
|
133
|
+
end
|
134
|
+
|
135
|
+
@fi
|
136
|
+
end
|
137
|
+
|
138
|
+
def h
|
139
|
+
@h ||= any_outcomes_occurred([h_1b, h_2b, h_3b, hr])
|
140
|
+
end
|
141
|
+
|
142
|
+
def hbp
|
143
|
+
@hbp ||= event_matches(/Hit By Pitch/)
|
144
|
+
end
|
145
|
+
|
146
|
+
def h_1b
|
147
|
+
@h_1b ||= event_matches(/(S|s)ingle/)
|
148
|
+
end
|
149
|
+
|
150
|
+
def h_2b
|
151
|
+
@h_2b ||= event_matches(/(D|d)ouble\Z/)
|
152
|
+
end
|
153
|
+
|
154
|
+
def h_3b
|
155
|
+
@h_3b ||= event_matches(/(T|t)riple?\Z/)
|
156
|
+
end
|
157
|
+
|
158
|
+
def hr
|
159
|
+
@hr ||= event_matches(/(H|h)ome (R|r)un/)
|
160
|
+
end
|
161
|
+
|
162
|
+
def k
|
163
|
+
@k ||= event_matches(/(S|s)trikeout/)
|
164
|
+
end
|
165
|
+
|
166
|
+
def batted_out
|
167
|
+
@batter_out ||= event_matches(/(Fly|Ground|Line|Pop)( )?(O|o)ut|Grounded Into DP/)
|
168
|
+
end
|
169
|
+
|
170
|
+
def force_out
|
171
|
+
@force_out ||= event_matches(/Forceout/)
|
172
|
+
end
|
173
|
+
|
174
|
+
def pa
|
175
|
+
@pa ||= if !event_value.match(/Runner Out/)
|
176
|
+
1
|
177
|
+
else
|
178
|
+
0
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def roe
|
183
|
+
@reached_on_error ||= event_matches(/Field Error/)
|
184
|
+
end
|
185
|
+
|
186
|
+
def sf
|
187
|
+
@sf ||= event_matches(/Sac Fly/)
|
188
|
+
end
|
189
|
+
|
190
|
+
def sh
|
191
|
+
@sh ||= event_matches(/Sac(rifice)? Bunt/)
|
192
|
+
end
|
193
|
+
|
194
|
+
def parse_hit_from_description
|
195
|
+
description = node.attribute("des").value
|
196
|
+
|
197
|
+
if description.match(/singles/)
|
198
|
+
@h = 1
|
199
|
+
@h_1b = 1
|
200
|
+
elsif description.match(/doubles/)
|
201
|
+
@h = 1
|
202
|
+
@h_2b = 1
|
203
|
+
elsif description.match(/ground-rule double/)
|
204
|
+
@h = 1
|
205
|
+
@h_2b = 1
|
206
|
+
elsif description.match(/triples/)
|
207
|
+
@h = 1
|
208
|
+
@h_3b = 1
|
209
|
+
elsif description.match(/hits a sacrifice bunt/) && description.match(/error/)
|
210
|
+
@roe = 1
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
data/lib/moneyball/version.rb
CHANGED
data/moneyball.gemspec
CHANGED
@@ -9,26 +9,18 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Geoff Harcourt"]
|
10
10
|
spec.email = ["geoff.harcourt@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary = %q{
|
13
|
-
spec.description = %q{Moneyball parses
|
12
|
+
spec.summary = %q{A parser for Gameday XML play descriptions.}
|
13
|
+
spec.description = %q{Moneyball parses Gameday play-by-play descriptions and extracts usable data from plain English summaries of plays.}
|
14
14
|
spec.homepage = "https://github.com/geoffharcourt/moneyball"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
|
-
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
18
|
-
# delete this section to allow pushing this gem to any host.
|
19
|
-
# if spec.respond_to?(:metadata)
|
20
|
-
# spec.metadata['allowed_push_host'] = ": set to 'http://mygemserver.com'"
|
21
|
-
# else
|
22
|
-
# raise "rubygems 2.0 or newer is required to protect against public gem pushes."
|
23
|
-
# end
|
24
|
-
|
25
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
18
|
spec.bindir = "exe"
|
27
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
20
|
spec.require_paths = ["lib"]
|
29
21
|
|
30
|
-
spec.add_development_dependency "bundler", "~> 1.9"
|
31
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
32
|
-
|
33
22
|
spec.add_dependency "nokogiri"
|
23
|
+
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.2.0"
|
34
26
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: moneyball
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Geoff Harcourt
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: nokogiri
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
type: :
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,21 +39,21 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
48
|
-
type: :
|
47
|
+
version: 3.2.0
|
48
|
+
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
55
|
-
description: Moneyball parses
|
56
|
-
|
54
|
+
version: 3.2.0
|
55
|
+
description: Moneyball parses Gameday play-by-play descriptions and extracts usable
|
56
|
+
data from plain English summaries of plays.
|
57
57
|
email:
|
58
58
|
- geoff.harcourt@gmail.com
|
59
59
|
executables: []
|
@@ -65,12 +65,15 @@ files:
|
|
65
65
|
- ".travis.yml"
|
66
66
|
- CODE_OF_CONDUCT.md
|
67
67
|
- Gemfile
|
68
|
-
- LICENSE
|
68
|
+
- LICENSE
|
69
69
|
- README.md
|
70
70
|
- Rakefile
|
71
71
|
- bin/console
|
72
72
|
- bin/setup
|
73
73
|
- lib/moneyball.rb
|
74
|
+
- lib/moneyball/batted_ball_location_extractor.rb
|
75
|
+
- lib/moneyball/batted_ball_type_extractor.rb
|
76
|
+
- lib/moneyball/parser.rb
|
74
77
|
- lib/moneyball/version.rb
|
75
78
|
- moneyball.gemspec
|
76
79
|
homepage: https://github.com/geoffharcourt/moneyball
|
@@ -88,13 +91,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
88
91
|
version: '0'
|
89
92
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
93
|
requirements:
|
91
|
-
- - "
|
94
|
+
- - ">="
|
92
95
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
96
|
+
version: '0'
|
94
97
|
requirements: []
|
95
98
|
rubyforge_project:
|
96
|
-
rubygems_version: 2.4.
|
99
|
+
rubygems_version: 2.4.7
|
97
100
|
signing_key:
|
98
101
|
specification_version: 4
|
99
|
-
summary:
|
102
|
+
summary: A parser for Gameday XML play descriptions.
|
100
103
|
test_files: []
|