moneyball 0.0.1.alpha → 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 +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
|
+
[](https://codeclimate.com/github/geoffharcourt/moneyball)
|
1
2
|
# Moneyball
|
3
|
+
[](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: []
|