score-formats 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 +7 -0
- data/CHANGELOG.md +3 -0
- data/Manifest.txt +13 -0
- data/README.md +29 -0
- data/Rakefile +27 -0
- data/lib/score-formats.rb +72 -0
- data/lib/score-formats/formats.rb +239 -0
- data/lib/score-formats/parser.rb +129 -0
- data/lib/score-formats/score.rb +165 -0
- data/lib/score-formats/version.rb +19 -0
- data/lib/score/formats.rb +5 -0
- data/test/helper.rb +12 -0
- data/test/test_formats.rb +129 -0
- data/test/test_score.rb +76 -0
- metadata +91 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0ce70736d26500e8d3866ae96a2f75e6ce8c1725
|
4
|
+
data.tar.gz: 16e29461a44bb4c232039b82f38d805596b47acf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 28ed77625082a2f1b29713b03cf92354df0799c8b0189f5e40e4ccddbad34cb6e14b286b580adee97304cb3b84e8c14064dd26c33efcfea80e94e4caa7354d6e
|
7
|
+
data.tar.gz: bf023b724232b5ca987615d223c8d8aef928a3afcf7b9807e1f1b9167fbabfc2a80d78404220cb5de6633585be885ea5e9f05c0770d28da59a1cb89d827b63b7
|
data/CHANGELOG.md
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
CHANGELOG.md
|
2
|
+
Manifest.txt
|
3
|
+
README.md
|
4
|
+
Rakefile
|
5
|
+
lib/score-formats.rb
|
6
|
+
lib/score-formats/formats.rb
|
7
|
+
lib/score-formats/parser.rb
|
8
|
+
lib/score-formats/score.rb
|
9
|
+
lib/score-formats/version.rb
|
10
|
+
lib/score/formats.rb
|
11
|
+
test/helper.rb
|
12
|
+
test/test_formats.rb
|
13
|
+
test/test_score.rb
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# score-formats - read / parse and print sports match scores (incl. half time, full time, extra time, penalties and more)
|
2
|
+
|
3
|
+
|
4
|
+
* home :: [github.com/sportdb/sport.db](https://github.com/sportdb/sport.db)
|
5
|
+
* bugs :: [github.com/sportdb/sport.db/issues](https://github.com/sportdb/sport.db/issues)
|
6
|
+
* gem :: [rubygems.org/gems/score-formats](https://rubygems.org/gems/score-formats)
|
7
|
+
* rdoc :: [rubydoc.info/gems/score-formats](http://rubydoc.info/gems/score-formats)
|
8
|
+
* forum :: [opensport](http://groups.google.com/group/opensport)
|
9
|
+
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
|
14
|
+
to be done
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
## License
|
20
|
+
|
21
|
+
The `score-formats` scripts are dedicated to the public domain.
|
22
|
+
Use it as you please with no restrictions whatsoever.
|
23
|
+
|
24
|
+
|
25
|
+
## Questions? Comments?
|
26
|
+
|
27
|
+
Send them along to the
|
28
|
+
[Open Sports & Friends Forum/Mailing List](http://groups.google.com/group/opensport).
|
29
|
+
Thanks!
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'hoe'
|
2
|
+
require './lib/score-formats/version.rb'
|
3
|
+
|
4
|
+
Hoe.spec 'score-formats' do
|
5
|
+
|
6
|
+
self.version = ScoreFormats::VERSION
|
7
|
+
|
8
|
+
self.summary = "score-formats - read / parse and print sports match scores (incl. half time, full time, extra time, penalties and more)"
|
9
|
+
self.description = summary
|
10
|
+
|
11
|
+
self.urls = ['https://github.com/sportdb/sport.db']
|
12
|
+
|
13
|
+
self.author = 'Gerald Bauer'
|
14
|
+
self.email = 'opensport@googlegroups.com'
|
15
|
+
|
16
|
+
# switch extension to .markdown for gihub formatting
|
17
|
+
self.readme_file = 'README.md'
|
18
|
+
self.history_file = 'CHANGELOG.md'
|
19
|
+
|
20
|
+
self.licenses = ['Public Domain']
|
21
|
+
|
22
|
+
self.extra_deps = []
|
23
|
+
|
24
|
+
self.spec_extras = {
|
25
|
+
required_ruby_version: '>= 2.2.2'
|
26
|
+
}
|
27
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'date'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
|
6
|
+
###
|
7
|
+
# our own code
|
8
|
+
require 'score-formats/version' # let version always go first
|
9
|
+
|
10
|
+
## todo/fix: make logging class configurable - lets you use logutils etc.
|
11
|
+
module ScoreFormats
|
12
|
+
module Logging
|
13
|
+
def logger() @logger ||= Logger.new; end
|
14
|
+
|
15
|
+
class Logger ## for now use quick "dummy" logger to
|
16
|
+
def debug( msg ) puts "[debug] #{msg}"; end
|
17
|
+
end # class Logger
|
18
|
+
end # module Logging
|
19
|
+
end # module ScoreFormats
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
require 'score-formats/score'
|
24
|
+
require 'score-formats/formats'
|
25
|
+
require 'score-formats/parser'
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
module ScoreFormats
|
30
|
+
def self.lang
|
31
|
+
@@lang ||= :en ## defaults to english (:en)
|
32
|
+
end
|
33
|
+
def self.lang=( value )
|
34
|
+
@@lang = value.to_sym ## note: make sure lang is always a symbol for now (NOT a string)
|
35
|
+
@@lang ## todo/check: remove =() method always returns passed in value? double check
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.parser( lang: ) ## find parser
|
39
|
+
lang = lang.to_sym ## note: make sure lang is always a symbol for now (NOT a string)
|
40
|
+
|
41
|
+
## note: cache all "built-in" lang versions (e.g. formats == nil)
|
42
|
+
@@parser ||= {}
|
43
|
+
parser = @@parser[ lang ] ||= ScoreParser.new( lang: lang )
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.parse( line, lang: ScoreFormats.lang )
|
47
|
+
parser( lang: lang ).parse( line )
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.find!( line, lang: ScoreFormats.lang )
|
51
|
+
parser( lang: lang ).find!( line )
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
##
|
58
|
+
# add more convenience / shortcut helpers / named ctors to score class itself
|
59
|
+
|
60
|
+
class Score
|
61
|
+
def self.parse( line, lang: ScoreFormats.lang )
|
62
|
+
ScoreFormats.parse( line, lang: lang )
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.find!( line, lang: ScoreFormats.lang )
|
66
|
+
ScoreFormats.find!( line, lang: lang )
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
puts ScoreFormats.banner # say hello
|
@@ -0,0 +1,239 @@
|
|
1
|
+
|
2
|
+
module ScoreFormats
|
3
|
+
|
4
|
+
## todo/check: use ‹› (unicode chars) to mark optional parts in regex constant name - why? why not?
|
5
|
+
|
6
|
+
#####
|
7
|
+
# english helpers (penalty, extra time, ...)
|
8
|
+
P_EN = '(?: p | pen\.? | pso )' # e.g. p, pen, pen., PSO, etc.
|
9
|
+
ET_EN = '(?: aet | a\.e\.t\.? )' # note: make last . optional (e.g a.e.t) allowed too
|
10
|
+
|
11
|
+
|
12
|
+
## note: allow SPECIAL cases WITHOUT full time scores (just a.e.t or pen. + a.e.t.)
|
13
|
+
## 3-4 pen. 2-2 a.e.t.
|
14
|
+
## 2-2 a.e.t.
|
15
|
+
EN__P_ET__RE = /\b
|
16
|
+
(?:
|
17
|
+
(?<score1p>\d{1,2})
|
18
|
+
[ ]* - [ ]* # note: sep in optional block; CANNOT use a reference
|
19
|
+
(?<score2p>\d{1,2})
|
20
|
+
[ ]* #{P_EN} [ ]*
|
21
|
+
)? # note: make penalty (P) score optional for now
|
22
|
+
(?<score1et>\d{1,2})
|
23
|
+
[ ]* - [ ]*
|
24
|
+
(?<score2et>\d{1,2})
|
25
|
+
[ ]* #{ET_EN}
|
26
|
+
(?=[ \]]|$)/xi ## todo/check: remove loakahead assertion here - why require space?
|
27
|
+
## note: \b works only after non-alphanum e.g. )
|
28
|
+
|
29
|
+
|
30
|
+
## e.g. 3-4 pen. 2-2 a.e.t. (1-1, 1-1) or
|
31
|
+
## 3-4 pen. 2-2 a.e.t. (1-1, ) or
|
32
|
+
## 3-4 pen. 2-2 a.e.t. (1-1) or
|
33
|
+
## 2-2 a.e.t. (1-1, 1-1) or
|
34
|
+
## 2-2 a.e.t. (1-1, ) or
|
35
|
+
## 2-2 a.e.t. (1-1)
|
36
|
+
|
37
|
+
EN__P_ET_FT_HT__RE = /\b
|
38
|
+
(?:
|
39
|
+
(?<score1p>\d{1,2})
|
40
|
+
[ ]* - [ ]* # note: sep in optional block; CANNOT use a reference
|
41
|
+
(?<score2p>\d{1,2})
|
42
|
+
[ ]* #{P_EN} [ ]*
|
43
|
+
)? # note: make penalty (P) score optional for now
|
44
|
+
(?<score1et>\d{1,2})
|
45
|
+
[ ]* - [ ]*
|
46
|
+
(?<score2et>\d{1,2})
|
47
|
+
[ ]* #{ET_EN} [ ]*
|
48
|
+
\(
|
49
|
+
[ ]*
|
50
|
+
(?<score1>\d{1,2})
|
51
|
+
[ ]* - [ ]*
|
52
|
+
(?<score2>\d{1,2})
|
53
|
+
[ ]*
|
54
|
+
(?:
|
55
|
+
, [ ]*
|
56
|
+
(?: (?<score1i>\d{1,2})
|
57
|
+
[ ]* - [ ]*
|
58
|
+
(?<score2i>\d{1,2})
|
59
|
+
[ ]*
|
60
|
+
)?
|
61
|
+
)? # note: make half time (HT) score optional for now
|
62
|
+
\)
|
63
|
+
(?=[ \]]|$)/xi ## todo/check: remove loakahead assertion here - why require space?
|
64
|
+
## note: \b works only after non-alphanum e.g. )
|
65
|
+
|
66
|
+
###
|
67
|
+
## special case for case WITHOUT extra time!!
|
68
|
+
## same as above (but WITHOUT extra time and pen required)
|
69
|
+
EN__P_FT_HT__RE = /\b
|
70
|
+
(?<score1p>\d{1,2})
|
71
|
+
[ ]* - [ ]* # note: sep in optional block; CANNOT use a reference
|
72
|
+
(?<score2p>\d{1,2})
|
73
|
+
[ ]* #{P_EN} [ ]*
|
74
|
+
\(
|
75
|
+
[ ]*
|
76
|
+
(?<score1>\d{1,2})
|
77
|
+
[ ]* - [ ]*
|
78
|
+
(?<score2>\d{1,2})
|
79
|
+
[ ]*
|
80
|
+
(?:
|
81
|
+
, [ ]*
|
82
|
+
(?: (?<score1i>\d{1,2})
|
83
|
+
[ ]* - [ ]*
|
84
|
+
(?<score2i>\d{1,2})
|
85
|
+
[ ]*
|
86
|
+
)?
|
87
|
+
)? # note: make half time (HT) score optional for now
|
88
|
+
\)
|
89
|
+
(?=[ \]]|$)/xi ## todo/check: remove loakahead assertion here - why require space?
|
90
|
+
## note: \b works only after non-alphanum e.g. )
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
## e.g. 2-1 (1-1) or
|
95
|
+
## 2-1
|
96
|
+
## note: for now add here used in Brazil / Portugal
|
97
|
+
## e.g 1x1 or 1X1 or 0x2 or 3x3 too
|
98
|
+
## todo/check/fix: move to its own use PT__FT_HT etc!!!!
|
99
|
+
|
100
|
+
EN__FT_HT__RE = /\b
|
101
|
+
(?<score1>\d{1,2})
|
102
|
+
[ ]* (?<sep>[x-]) [ ]*
|
103
|
+
(?<score2>\d{1,2})
|
104
|
+
(?:
|
105
|
+
[ ]* \( [ ]*
|
106
|
+
(?<score1i>\d{1,2})
|
107
|
+
[ ]* \k<sep> [ ]*
|
108
|
+
(?<score2i>\d{1,2})
|
109
|
+
[ ]* \)
|
110
|
+
)? # note: make half time (HT) score optional for now
|
111
|
+
(?=[ \]]|$)/xi ## todo/check: remove loakahead assertion here - why require space?
|
112
|
+
## note: \b works only after non-alphanum e.g. )
|
113
|
+
|
114
|
+
|
115
|
+
#####
|
116
|
+
# deutsch / german helpers (penalty, extra time, ...)
|
117
|
+
## todo add more marker e.g. im Elf. or such!!!
|
118
|
+
P_DE = '(?: ie | i\.e\.? )' # e.g. iE, i.E., i.E etc.
|
119
|
+
ET_DE = '(?: nv | n\.v\.? )' # e.g. nV, n.V., n.V etc.
|
120
|
+
|
121
|
+
|
122
|
+
## support alternate all-in-one score e.g.
|
123
|
+
## i.E. 2:4, n.V. 3:3 (1:1, 1:1) or
|
124
|
+
## n.V. 3:2 (2:2, 1:2)
|
125
|
+
DE__P_ET_FT_HT__RE = /\b
|
126
|
+
(?:
|
127
|
+
#{P_DE}
|
128
|
+
[ ]*
|
129
|
+
(?<score1p>\d{1,2})
|
130
|
+
[ ]* : [ ]*
|
131
|
+
(?<score2p>\d{1,2})
|
132
|
+
[ ]* (?:, [ ]*)?
|
133
|
+
)? # note: make penalty (P) score optional for now
|
134
|
+
#{ET_DE}
|
135
|
+
[ ]*
|
136
|
+
(?<score1et>\d{1,2})
|
137
|
+
[ ]* : [ ]*
|
138
|
+
(?<score2et>\d{1,2})
|
139
|
+
[ ]*
|
140
|
+
\(
|
141
|
+
[ ]*
|
142
|
+
(?<score1>\d{1,2})
|
143
|
+
[ ]* : [ ]*
|
144
|
+
(?<score2>\d{1,2})
|
145
|
+
[ ]*
|
146
|
+
(?:
|
147
|
+
, [ ]*
|
148
|
+
(?:
|
149
|
+
(?<score1i>\d{1,2})
|
150
|
+
[ ]* : [ ]*
|
151
|
+
(?<score2i>\d{1,2})
|
152
|
+
[ ]*
|
153
|
+
)?
|
154
|
+
)? # note: make half time (HT) score optional for now
|
155
|
+
\)
|
156
|
+
(?=[ \]]|$)
|
157
|
+
/xi
|
158
|
+
|
159
|
+
## support all-in-one "literal form e.g.
|
160
|
+
# 2:2 (1:1, 1:0) n.V. 5:1 i.E. or
|
161
|
+
# 2-2 (1-1, 1-0) n.V. 5-1 i.E.
|
162
|
+
DE__ET_FT_HT_P__RE = /\b
|
163
|
+
(?<score1et>\d{1,2})
|
164
|
+
[ ]* (?<sep>[:-]) [ ]* ## note: for now allow : or - as separator!!
|
165
|
+
(?<score2et>\d{1,2})
|
166
|
+
[ ]*
|
167
|
+
\(
|
168
|
+
[ ]*
|
169
|
+
(?<score1>\d{1,2})
|
170
|
+
[ ]* \k<sep> [ ]*
|
171
|
+
(?<score2>\d{1,2})
|
172
|
+
[ ]*
|
173
|
+
(?:
|
174
|
+
, [ ]*
|
175
|
+
(?:
|
176
|
+
(?<score1i>\d{1,2})
|
177
|
+
[ ]* \k<sep> [ ]*
|
178
|
+
(?<score2i>\d{1,2})
|
179
|
+
[ ]*
|
180
|
+
)?
|
181
|
+
)? # note: make half time (HT) score optional for now
|
182
|
+
\)
|
183
|
+
[ ]*
|
184
|
+
#{ET_DE}
|
185
|
+
(?:
|
186
|
+
[ ]*
|
187
|
+
(?<score1p>\d{1,2})
|
188
|
+
[ ]* \k<sep> [ ]*
|
189
|
+
(?<score2p>\d{1,2})
|
190
|
+
[ ]*
|
191
|
+
#{P_DE}
|
192
|
+
)? # note: make penalty (P) score optional for now
|
193
|
+
(?=[ \]]|$)
|
194
|
+
/xi ## todo/check: remove loakahead assertion here - why require space?
|
195
|
+
## note: \b works only after non-alphanum e.g. )
|
196
|
+
|
197
|
+
|
198
|
+
## e.g. 2:1 (1:1) or
|
199
|
+
## 2-1 (1-1) or
|
200
|
+
## 2:1 or
|
201
|
+
## 2-1
|
202
|
+
DE__FT_HT__RE = /\b
|
203
|
+
(?<score1>\d{1,2})
|
204
|
+
[ ]* (?<sep>[:-]) [ ]*
|
205
|
+
(?<score2>\d{1,2})
|
206
|
+
(?:
|
207
|
+
[ ]* \( [ ]*
|
208
|
+
(?<score1i>\d{1,2})
|
209
|
+
[ ]* \k<sep> [ ]*
|
210
|
+
(?<score2i>\d{1,2})
|
211
|
+
[ ]* \)
|
212
|
+
)? # note: make half time (HT) score optional for now
|
213
|
+
(?=[ \]]|$)/x ## todo/check: remove loakahead assertion here - why require space?
|
214
|
+
## note: \b works only after non-alphanum e.g. )
|
215
|
+
|
216
|
+
|
217
|
+
#############################################
|
218
|
+
# map tables - 1) regex, 2) tag - note: order matters; first come-first matched/served
|
219
|
+
|
220
|
+
|
221
|
+
FORMATS_EN = [
|
222
|
+
[ EN__P_ET_FT_HT__RE, '[SCORE.EN__P?_ET_(FT_HT?)]' ], # e.g. 5-1 pen. 2-2 a.e.t. (1-1, 1-0)
|
223
|
+
[ EN__P_FT_HT__RE, '[SCORE.EN__P_(FT_HT?)]' ], # e.g. 5-1 pen. (1-1)
|
224
|
+
[ EN__P_ET__RE, '[SCORE.EN__P?_ET]' ], # e.g. 2-2 a.e.t. or 5-1 pen. 2-2 a.e.t.
|
225
|
+
[ EN__FT_HT__RE, '[SCORE.EN__FT_(HT)?]' ], # e.g. 1-1 (1-0)
|
226
|
+
]
|
227
|
+
|
228
|
+
FORMATS_DE = [
|
229
|
+
[ DE__ET_FT_HT_P__RE, '[SCORE.DE__ET_(FT_HT?)_P?]' ], # e.g. 2:2 (1:1, 1:0) n.V. 5:1 i.E.
|
230
|
+
[ DE__P_ET_FT_HT__RE, '[SCORE.DE__P?_ET_(FT_HT?)]' ], # e.g. i.E. 2:4, n.V. 3:3 (1:1, 1:1)
|
231
|
+
[ DE__FT_HT__RE, '[SCORE.DE__FT_(HT)?]' ], # e.g. 1:1 (1:0)
|
232
|
+
]
|
233
|
+
|
234
|
+
FORMATS = {
|
235
|
+
en: FORMATS_EN,
|
236
|
+
de: FORMATS_DE,
|
237
|
+
}
|
238
|
+
|
239
|
+
end # module ScoreFormats
|
@@ -0,0 +1,129 @@
|
|
1
|
+
|
2
|
+
module ScoreFormats
|
3
|
+
|
4
|
+
class ScoreParser
|
5
|
+
|
6
|
+
include Logging
|
7
|
+
|
8
|
+
def initialize( lang: )
|
9
|
+
@lang = lang.to_sym ## note: make sure lang is always a symbol for now (NOT a string)
|
10
|
+
|
11
|
+
## fallback to english if lang not available
|
12
|
+
## todo/fix: add/issue warning - why? why not?
|
13
|
+
@formats = FORMATS[ @lang ] || FORMATS[ :en ]
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def parse( line )
|
18
|
+
|
19
|
+
##########
|
20
|
+
## todo/fix/check: add unicode to regular dash conversion - why? why not?
|
21
|
+
## e.g. – becomes - (yes, the letters a different!!!)
|
22
|
+
#############
|
23
|
+
|
24
|
+
score = nil
|
25
|
+
@formats.each do |format|
|
26
|
+
re = format[0]
|
27
|
+
m = re.match( line )
|
28
|
+
if m
|
29
|
+
score = parse_matchdata( m )
|
30
|
+
break
|
31
|
+
end
|
32
|
+
# no match; continue; try next regex pattern
|
33
|
+
end
|
34
|
+
|
35
|
+
## todo/fix - raise ArgumentError - invalid score; no format match found
|
36
|
+
score # note: nil if no match found
|
37
|
+
end # method parse
|
38
|
+
|
39
|
+
|
40
|
+
def find!( line )
|
41
|
+
### fix: add and match all-in-one literal first, followed by
|
42
|
+
|
43
|
+
# note: always call after find_dates !!!
|
44
|
+
# scores match date-like patterns!! e.g. 10-11 or 10:00 etc.
|
45
|
+
# -- note: score might have two digits too
|
46
|
+
|
47
|
+
### fix: depending on language allow 1:1 or 1-1
|
48
|
+
## do NOT allow mix and match
|
49
|
+
## e.g. default to en is 1-1
|
50
|
+
## de is 1:1 etc.
|
51
|
+
|
52
|
+
|
53
|
+
# extract score from line
|
54
|
+
# and return it
|
55
|
+
# note: side effect - removes date from line string
|
56
|
+
|
57
|
+
score = nil
|
58
|
+
@formats.each do |format|
|
59
|
+
re = format[0]
|
60
|
+
tag = format[1]
|
61
|
+
m = re.match( line )
|
62
|
+
if m
|
63
|
+
score = parse_matchdata( m )
|
64
|
+
line.sub!( m[0], tag )
|
65
|
+
break
|
66
|
+
end
|
67
|
+
# no match; continue; try next regex pattern
|
68
|
+
end
|
69
|
+
|
70
|
+
score # note: nil if no match found
|
71
|
+
end # method find!
|
72
|
+
|
73
|
+
private
|
74
|
+
def parse_matchdata( m )
|
75
|
+
# convert regex match_data captures to hash
|
76
|
+
# - note: cannont use match_data like a hash (e.g. raises exception if key/name not present/found)
|
77
|
+
h = {}
|
78
|
+
# - note: do NOT forget to turn name into symbol for lookup in new hash (name.to_sym)
|
79
|
+
m.names.each { |name| h[name.to_sym] = m[name] } # or use match_data.names.zip( match_data.captures ) - more cryptic but "elegant"??
|
80
|
+
|
81
|
+
## puts "[parse_date_time] match_data:"
|
82
|
+
## pp h
|
83
|
+
logger.debug " [parse_matchdata] hash: >#{h.inspect}<"
|
84
|
+
|
85
|
+
score1i = nil # half time (ht) scores
|
86
|
+
score2i = nil
|
87
|
+
|
88
|
+
score1 = nil # full time (ft) scores
|
89
|
+
score2 = nil
|
90
|
+
|
91
|
+
score1et = nil # extra time (et) scores
|
92
|
+
score2et = nil
|
93
|
+
|
94
|
+
score1p = nil # penalty (p) scores
|
95
|
+
score2p = nil
|
96
|
+
|
97
|
+
|
98
|
+
if h[:score1i] && h[:score2i] ## note: half time (HT) score is optional now
|
99
|
+
score1i = h[:score1i].to_i
|
100
|
+
score2i = h[:score2i].to_i
|
101
|
+
end
|
102
|
+
|
103
|
+
if h[:score1] && h[:score2] ## note: full time (FT) score can be optional too!!!
|
104
|
+
score1 = h[:score1].to_i
|
105
|
+
score2 = h[:score2].to_i
|
106
|
+
end
|
107
|
+
|
108
|
+
if h[:score1et] && h[:score2et]
|
109
|
+
score1et = h[:score1et].to_i
|
110
|
+
score2et = h[:score2et].to_i
|
111
|
+
end
|
112
|
+
|
113
|
+
if h[:score1p] && h[:score2p]
|
114
|
+
score1p = h[:score1p].to_i
|
115
|
+
score2p = h[:score2p].to_i
|
116
|
+
end
|
117
|
+
|
118
|
+
score = Score.new( score1i, score2i,
|
119
|
+
score1, score2,
|
120
|
+
score1et, score2et,
|
121
|
+
score1p, score2p )
|
122
|
+
score
|
123
|
+
end # method parse_matchdata
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
end # class ScoreParser
|
128
|
+
end # module ScoreFormats
|
129
|
+
|
@@ -0,0 +1,165 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
## note: make Score top-level and use like Date - yes, yes, yes - why? why not?
|
4
|
+
class Score
|
5
|
+
|
6
|
+
SCORE_SPLIT_RE = %r{^ [ ]*
|
7
|
+
([0-9]+)
|
8
|
+
[ ]*
|
9
|
+
[:x–-] ## note: allow some unicode dashes too
|
10
|
+
[ ]*
|
11
|
+
([0-9]+)
|
12
|
+
[ ]* $}xi
|
13
|
+
|
14
|
+
def self.split( str ) ## note: return array of two integers or empty array
|
15
|
+
## e.g. allow/support
|
16
|
+
## 1-1 or 1 - 1 - "english" style
|
17
|
+
## 1:1 - "german / deutsch" style
|
18
|
+
## 1x1 1X1 - "brazil/portugese" style
|
19
|
+
|
20
|
+
## note: add unicode "fancy" dash too (e.g. –)
|
21
|
+
## add some more - why? why not?
|
22
|
+
|
23
|
+
if m=SCORE_SPLIT_RE.match(str)
|
24
|
+
[m[1].to_i, m[2].to_i]
|
25
|
+
else
|
26
|
+
# no match - warn if str is not empty? why? why not?
|
27
|
+
##
|
28
|
+
## todo/fix:
|
29
|
+
## do NOT warn on
|
30
|
+
## assert_equal [], Score.split( '-' )
|
31
|
+
## assert_equal [], Score.split( '-:-' )
|
32
|
+
## assert_equal [], Score.split( '?' )
|
33
|
+
## for now - add more?
|
34
|
+
|
35
|
+
puts "!! WARN - cannot match (split) score format >#{str}<" unless str.empty?
|
36
|
+
[]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
attr_reader :score1i, :score2i, # half time (ht) score
|
44
|
+
:score1, :score2, # full time (ft) score
|
45
|
+
:score1et, :score2et, # extra time (et) score
|
46
|
+
:score1p, :score2p # penalty (p) score
|
47
|
+
## todo/fix: add :score1agg, score2agg too - why? why not?!!!
|
48
|
+
## add state too e.g. canceled or abadoned etc - why? why not?
|
49
|
+
|
50
|
+
## alternate accessor via array e.g. ft[0] and ft[1]
|
51
|
+
def ft() [@score1, @score2]; end ## e.g. 90 mins (in football)
|
52
|
+
def ht() [@score1i, @score2i]; end ## e.g. 45 mins
|
53
|
+
def et() [@score1et, @score2et]; end ## e.g. 90+15mins
|
54
|
+
def p() [@score1p, @score2p]; end ## e.g. note - starts "fresh" score from 0-0
|
55
|
+
alias_method :pen, :p ## add alias - why? why not?
|
56
|
+
|
57
|
+
## todo/check: allow one part missing why? why not?
|
58
|
+
## e.g. 1-nil or nil-1 - why? why not?
|
59
|
+
def ft?() @score1 && @score2; end
|
60
|
+
def ht?() @score1i && @score2i; end
|
61
|
+
def et?() @score1et && @score2et; end
|
62
|
+
def p?() @score1p && @score2p; end
|
63
|
+
alias_method :pen?, :p?
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
def initialize( *values )
|
68
|
+
## note: for now always assumes integers
|
69
|
+
## todo/check - check/require integer args - why? why not?
|
70
|
+
|
71
|
+
### todo/fix: add more init options
|
72
|
+
## allow kwargs (keyword args) via hash - why? why not?
|
73
|
+
## use kwargs for "perfect" init where you can only set the half time (ht) score
|
74
|
+
## or only the penalty or other "edge" cases
|
75
|
+
## allow int pairs e.g. [1,2], [2,2]
|
76
|
+
## allow values array MUST be of size 8 (or 4 or 6) - why? why not?
|
77
|
+
|
78
|
+
raise ArgumentError, "expected even integer number (pairs), but got #{values.size}" if values.size % 2 == 1
|
79
|
+
|
80
|
+
if values.size == 2
|
81
|
+
@score1 = values[0] # full time (ft) score
|
82
|
+
@score2 = values[1]
|
83
|
+
|
84
|
+
@score1i = @score2i = nil
|
85
|
+
@score1et = @score2et = nil
|
86
|
+
@score1p = @score2p = nil
|
87
|
+
else
|
88
|
+
@score1i = values[0] # half time (ht) score
|
89
|
+
@score2i = values[1]
|
90
|
+
|
91
|
+
@score1 = values[2] # full time (ft) score
|
92
|
+
@score2 = values[3]
|
93
|
+
|
94
|
+
@score1et = values[4] # extra time (et) score
|
95
|
+
@score2et = values[5]
|
96
|
+
|
97
|
+
@score1p = values[6] # penalty (p) score
|
98
|
+
@score2p = values[7]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
def to_h( format = :default )
|
105
|
+
case format.to_sym
|
106
|
+
when :default, :std
|
107
|
+
## check/todo: only add entries if ft, ht, etc. have values (non-null) or always - why? why not?
|
108
|
+
h = {}
|
109
|
+
h[:ht] = [@score1i, @score2i] if @score1i || @score2i
|
110
|
+
h[:ft] = [@score1, @score2] if @score1 || @score2
|
111
|
+
h[:et] = [@score1et, @score2et] if @score1et || @score2et
|
112
|
+
h[:p] = [@score1p, @score2p] if @score1p || @score2p
|
113
|
+
h
|
114
|
+
when :db
|
115
|
+
## use a "flat" structure with "internal" std names
|
116
|
+
{ score1i: @score1i, score2i: @score2i,
|
117
|
+
score1: @score1, score2: @score2,
|
118
|
+
score1et: @score1et, score2et: @score2et,
|
119
|
+
score1p: @score1p, score2p: @score2p
|
120
|
+
}
|
121
|
+
else
|
122
|
+
puts "!! ERROR: unknown score to_h format >#{format}<"
|
123
|
+
exit 1
|
124
|
+
end
|
125
|
+
end
|
126
|
+
alias_method :to_hash, :to_h ## add alias - why? why not?
|
127
|
+
|
128
|
+
|
129
|
+
def values
|
130
|
+
## todo/ fix: always return complete array
|
131
|
+
## e.g. [score1i, score2i, score1, score2, score1et, score2et, score1p, score2p]
|
132
|
+
|
133
|
+
## todo: how to handle game w/o extra time
|
134
|
+
# but w/ optional penalty ??? e.g. used in copa liberatores, for example
|
135
|
+
# retrun 0,0 or nil,nil for extra time score ?? or -1, -1 ??
|
136
|
+
# for now use nil,nil
|
137
|
+
score = []
|
138
|
+
score += [@score1i, @score2i] if @score1p || @score2p || @score1et || @score2et || @score1 || score2 || score1i || score2i
|
139
|
+
score += [@score1, @score2] if @score1p || @score2p || @score1et || @score2et || @score1 || score2
|
140
|
+
score += [@score1et, @score2et] if @score1p || @score2p || @score1et || @score2et
|
141
|
+
score += [@score1p, @score2p] if @score1p || @score2p
|
142
|
+
score
|
143
|
+
end
|
144
|
+
|
145
|
+
def to_a
|
146
|
+
## pairs with values
|
147
|
+
pairs = []
|
148
|
+
## note: allow 1-nil, nil-1 for now in pairs (or use && and NOT ||) - why? why not?
|
149
|
+
pairs << [@score1i, @score2i] if @score1i || @score2i
|
150
|
+
pairs << [@score1, @score2] if @score1 || @score2
|
151
|
+
pairs << [@score1et, @score2et] if @score1et || @score2et
|
152
|
+
pairs << [@score1p, @score2p] if @score1p || @score2p
|
153
|
+
|
154
|
+
if pairs.empty?
|
155
|
+
pairs # e.g. return []
|
156
|
+
elsif pairs.size == 1
|
157
|
+
pairs[0] # return single pair "unwrapped" e.g. [0,1] instead of [[0,1]] - why? why not?
|
158
|
+
else
|
159
|
+
pairs
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
end # class Score
|
164
|
+
|
165
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
module ScoreFormats
|
3
|
+
MAJOR = 0 ## todo: namespace inside version or something - why? why not??
|
4
|
+
MINOR = 0
|
5
|
+
PATCH = 1
|
6
|
+
VERSION = [MAJOR,MINOR,PATCH].join('.')
|
7
|
+
|
8
|
+
def self.version
|
9
|
+
VERSION
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.banner
|
13
|
+
"score-formats/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.root
|
17
|
+
File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
|
18
|
+
end
|
19
|
+
end # module ScoreFormats
|
data/test/helper.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
###
|
2
|
+
# to run use
|
3
|
+
# ruby -I ./lib -I ./test test/test_formats.rb
|
4
|
+
|
5
|
+
|
6
|
+
require 'helper'
|
7
|
+
|
8
|
+
class TestFormats < MiniTest::Test
|
9
|
+
|
10
|
+
def test_de
|
11
|
+
ScoreFormats.lang = :de
|
12
|
+
data = [
|
13
|
+
[ '10:0', [nil,nil, 10,0]],
|
14
|
+
[ '1:22', [nil,nil, 1,22]],
|
15
|
+
[ '1-22', [nil,nil, 1,22]],
|
16
|
+
|
17
|
+
## do not support three digits for now - why? why not?
|
18
|
+
[ '1:222', nil],
|
19
|
+
[ '111:0', nil],
|
20
|
+
[ '1-222', nil],
|
21
|
+
[ '111-0', nil],
|
22
|
+
|
23
|
+
[ '2:2 (1:1, 1:0) n.V. 5:1 i.E.', [1,0, 1,1, 2,2, 5,1]],
|
24
|
+
[ '2:2 (1:1, 1:0) n.V.', [1,0, 1,1, 2,2]],
|
25
|
+
[ '2:2 (1:1, ) n.V. 5:1 i.E.', [nil,nil, 1,1, 2,2, 5,1]],
|
26
|
+
[ '2:2 (1:1, ) n.V.', [nil,nil, 1,1, 2,2]],
|
27
|
+
|
28
|
+
[ '2:2 (1:1) n.V. 5:1 i.E.', [nil,nil, 1,1, 2,2, 5,1]],
|
29
|
+
[ '2:2 (1:1) n.V.', [nil,nil, 1,1, 2,2]],
|
30
|
+
|
31
|
+
[ '2-2 (1-1, 1-0) n.V. 5-1 i.E.', [1,0, 1,1, 2,2, 5,1]],
|
32
|
+
[ '2-2 (1-1, 1-0) n.V.', [1,0, 1,1, 2,2]],
|
33
|
+
[ '2-2 (1-1, ) n.V. 5-1 i.E.', [nil,nil, 1,1, 2,2, 5,1]],
|
34
|
+
[ '2-2 (1-1, ) n.V.', [nil,nil, 1,1, 2,2]],
|
35
|
+
|
36
|
+
[ '2 : 2 ( 1 : 1 , 1 : 0 ) n.V. 5 : 1 i.E.', [1,0, 1,1, 2,2, 5,1]],
|
37
|
+
[ '2 : 2 ( 1 : 1 , 1 : 0 ) n.V.', [1,0, 1,1, 2,2]],
|
38
|
+
[ '2 : 2 ( 1 : 1 , ) n.V. 5 : 1 i.E.', [nil,nil, 1,1, 2,2, 5,1]],
|
39
|
+
[ '2 : 2 ( 1 : 1 , ) n.V.', [nil,nil, 1,1, 2,2]],
|
40
|
+
|
41
|
+
## alternate format
|
42
|
+
['i.E. 2:4, n.V. 3:3 (1:1, 1:0)', [1,0, 1,1, 3,3, 2,4]],
|
43
|
+
['iE 2:4 nV 3:3 (1:1, 1:0)', [1,0, 1,1, 3,3, 2,4]],
|
44
|
+
['i.E. 2:4 n.V. 3:3 (1:1, 1:0)', [1,0, 1,1, 3,3, 2,4]],
|
45
|
+
['i.E. 2:4, n.V. 3:3 (1:1)', [nil, nil, 1,1, 3,3, 2,4]],
|
46
|
+
['i.E. 2:4 n.V. 3:3 (1:1)', [nil, nil, 1,1, 3,3, 2,4]],
|
47
|
+
['n.V. 3:2 (2:2, 1:2)', [1,2, 2,2, 3,2]],
|
48
|
+
['n.V. 3:2 (2:2)', [nil, nil, 2,2, 3,2]],
|
49
|
+
]
|
50
|
+
|
51
|
+
assert_score( data )
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_en
|
55
|
+
ScoreFormats.lang = :en
|
56
|
+
|
57
|
+
data = [
|
58
|
+
[ '1-22', [nil,nil, 1, 22]],
|
59
|
+
[ '1x22', [nil,nil, 1, 22]],
|
60
|
+
[ '1X22', [nil,nil, 1,22]],
|
61
|
+
|
62
|
+
## do not support three digits for now - why? why not?
|
63
|
+
[ '1-222', nil],
|
64
|
+
[ '111-0', nil],
|
65
|
+
[ '111x0', nil],
|
66
|
+
[ '111X0', nil],
|
67
|
+
|
68
|
+
## do not support colon sep for now in en locale - why? why not?
|
69
|
+
[ '2:1', nil],
|
70
|
+
[ '2:1 (1:1)', nil],
|
71
|
+
|
72
|
+
|
73
|
+
[ '2-1 (1-1)', [1,1, 2,1]],
|
74
|
+
[ '2x1 (1x1)', [1,1, 2,1]],
|
75
|
+
[ '2X1 (1X1)', [1,1, 2,1]],
|
76
|
+
|
77
|
+
[ '2-1 a.e.t. (1-1, 0-0)', [0,0, 1,1, 2,1]],
|
78
|
+
[ '2-1aet (1-1, 0-0)', [0,0, 1,1, 2,1]],
|
79
|
+
[ '2-1 A.E.T. (1-1, 0-0)', [0,0, 1,1, 2,1]],
|
80
|
+
[ '2-1AET (1-1, 0-0)', [0,0, 1,1, 2,1]],
|
81
|
+
[ '2-1 a.e.t.', [nil,nil,nil,nil, 2,1]],
|
82
|
+
|
83
|
+
[ '3-4 pen. 2-2 a.e.t. (1-1, 1-1)', [1,1, 1,1, 2,2, 3,4]],
|
84
|
+
[ '3-4 pen 2-2 a.e.t. (1-1, 1-1)', [1,1, 1,1, 2,2, 3,4]],
|
85
|
+
[ '3-4 pen 2-2 a.e.t. (1-1, 1-1)', [1,1, 1,1, 2,2, 3,4]],
|
86
|
+
[ '3-4p 2-2aet (1-1, 1-1)', [1,1, 1,1, 2,2, 3,4]],
|
87
|
+
[ '3-4PSO 2-2AET (1-1, 1-1)', [1,1, 1,1, 2,2, 3,4]],
|
88
|
+
[ '3-4 pen. 2-2 a.e.t.', [nil,nil,nil,nil, 2,2, 3,4]],
|
89
|
+
|
90
|
+
[ '4-3 pen. 1-0 a.e.t. (1-0, )', [nil,nil, 1,0, 1,0, 4,3]],
|
91
|
+
[ '3-4 pen. 2-1 a.e.t. (2-1, )', [nil,nil, 2,1, 2,1, 3,4]],
|
92
|
+
[ '4-1 a.e.t. (3-1, )', [nil,nil, 3,1, 4,1]],
|
93
|
+
[ '3-4aet (1-1,)', [nil,nil, 1,1, 3,4]],
|
94
|
+
[ '3-4 a.e.t. (1-1,)', [nil,nil, 1,1, 3,4]],
|
95
|
+
|
96
|
+
[ '4-3 pen. 1-0 a.e.t. (1-0)', [nil,nil, 1,0, 1,0, 4,3]],
|
97
|
+
[ '3-4 pen. 2-1 a.e.t. (2-1)', [nil,nil, 2,1, 2,1, 3,4]],
|
98
|
+
[ '4-1 a.e.t. (3-1)', [nil,nil, 3,1, 4,1]],
|
99
|
+
[ '3-4aet (1-1)', [nil,nil, 1,1, 3,4]],
|
100
|
+
[ '3-4 a.e.t. (1-1)', [nil,nil, 1,1, 3,4]],
|
101
|
+
|
102
|
+
[ '3-1 pen (1-1)', [nil,nil, 1,1, nil, nil, 3,1]],
|
103
|
+
|
104
|
+
## try with more "liberal" spaces
|
105
|
+
[ '2 - 1 ( 1 - 1 )', [1,1, 2,1]],
|
106
|
+
[ '2 - 1 a.e.t. ( 1 - 1 , 0 - 0 )', [0,0, 1,1, 2,1]],
|
107
|
+
[ '4 - 1 a.e.t. ( 3 - 1, )', [nil,nil, 3,1, 4,1]],
|
108
|
+
]
|
109
|
+
|
110
|
+
assert_score( data )
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
def assert_score( data )
|
115
|
+
data.each do |rec|
|
116
|
+
line = rec[0].dup
|
117
|
+
exp = rec[1]
|
118
|
+
|
119
|
+
score = ScoreFormats.find!( line )
|
120
|
+
## pp score
|
121
|
+
|
122
|
+
if exp.nil?
|
123
|
+
assert_nil score, "failed >#{rec[0]}< - >#{line}<"
|
124
|
+
else
|
125
|
+
assert_equal exp, score.values, "failed >#{rec[0]}< - >#{line}<"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end # class TestScores
|
data/test/test_score.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
###
|
2
|
+
# to run use
|
3
|
+
# ruby -I ./lib -I ./test test/test_score.rb
|
4
|
+
|
5
|
+
|
6
|
+
require 'helper'
|
7
|
+
|
8
|
+
class TestScore < MiniTest::Test
|
9
|
+
|
10
|
+
def test_split
|
11
|
+
assert_equal [], Score.split( '' )
|
12
|
+
assert_equal [], Score.split( '-' )
|
13
|
+
assert_equal [], Score.split( '-:-' )
|
14
|
+
assert_equal [], Score.split( '?' )
|
15
|
+
|
16
|
+
assert_equal [0,1], Score.split( '0-1' )
|
17
|
+
assert_equal [0,1], Score.split( ' 0 - 1 ' )
|
18
|
+
assert_equal [0,1], Score.split( '0:1' )
|
19
|
+
assert_equal [0,1], Score.split( ' 0 : 1 ' )
|
20
|
+
assert_equal [0,1], Score.split( '0x1' )
|
21
|
+
assert_equal [0,1], Score.split( '0X1' )
|
22
|
+
|
23
|
+
assert_equal [10,11], Score.split( '10 - 11' )
|
24
|
+
assert_equal [10,11], Score.split( '10 : 11' )
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_to_h
|
28
|
+
assert_equal Hash( ft: [1,0] ), Score.parse( '1-0' ).to_h
|
29
|
+
assert_equal Hash( ht: [1,0],
|
30
|
+
ft: [3,2] ), Score.parse( '3-2 (1-0)' ).to_h
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def test_new_et_al
|
35
|
+
score = Score.new
|
36
|
+
assert_equal [], score.to_a
|
37
|
+
assert_equal [], score.values
|
38
|
+
assert_equal [nil,nil], score.ft
|
39
|
+
assert_equal [nil,nil], score.ht
|
40
|
+
assert_equal Hash({}), score.to_h ## e.g. {} - empty hash
|
41
|
+
assert_equal Hash( score1i: nil, score2i: nil,
|
42
|
+
score1: nil, score2: nil,
|
43
|
+
score1et: nil, score2et: nil,
|
44
|
+
score1p: nil, score2p: nil ), score.to_h( :db )
|
45
|
+
|
46
|
+
|
47
|
+
[
|
48
|
+
Score.new( 0, 1 ),
|
49
|
+
Score.new( nil, nil, 0, 1 ),
|
50
|
+
].each do |score|
|
51
|
+
assert_equal [0,1], score.to_a
|
52
|
+
assert_equal [nil,nil,0,1], score.values
|
53
|
+
assert_equal [nil,nil], score.ht
|
54
|
+
assert_equal [0,1], score.ft
|
55
|
+
assert_equal Hash(ft: [0,1]), score.to_h
|
56
|
+
assert_equal Hash( score1i: nil, score2i: nil,
|
57
|
+
score1: 0, score2: 1,
|
58
|
+
score1et: nil, score2et: nil,
|
59
|
+
score1p: nil, score2p: nil ), score.to_h( :db )
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
score = Score.new( 0, 1, 2, 3 )
|
64
|
+
assert_equal [[0,1],[2,3]], score.to_a
|
65
|
+
assert_equal [0,1,2,3], score.values
|
66
|
+
assert_equal [0,1], score.ht
|
67
|
+
assert_equal [2,3], score.ft
|
68
|
+
assert_equal Hash(ht: [0,1],
|
69
|
+
ft: [2,3]), score.to_h
|
70
|
+
assert_equal Hash( score1i: 0, score2i: 1,
|
71
|
+
score1: 2, score2: 3,
|
72
|
+
score1et: nil, score2et: nil,
|
73
|
+
score1p: nil, score2p: nil ), score.to_h( :db )
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: score-formats
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gerald Bauer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-08-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rdoc
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: hoe
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.16'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.16'
|
41
|
+
description: score-formats - read / parse and print sports match scores (incl. half
|
42
|
+
time, full time, extra time, penalties and more)
|
43
|
+
email: opensport@googlegroups.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files:
|
47
|
+
- CHANGELOG.md
|
48
|
+
- Manifest.txt
|
49
|
+
- README.md
|
50
|
+
files:
|
51
|
+
- CHANGELOG.md
|
52
|
+
- Manifest.txt
|
53
|
+
- README.md
|
54
|
+
- Rakefile
|
55
|
+
- lib/score-formats.rb
|
56
|
+
- lib/score-formats/formats.rb
|
57
|
+
- lib/score-formats/parser.rb
|
58
|
+
- lib/score-formats/score.rb
|
59
|
+
- lib/score-formats/version.rb
|
60
|
+
- lib/score/formats.rb
|
61
|
+
- test/helper.rb
|
62
|
+
- test/test_formats.rb
|
63
|
+
- test/test_score.rb
|
64
|
+
homepage: https://github.com/sportdb/sport.db
|
65
|
+
licenses:
|
66
|
+
- Public Domain
|
67
|
+
metadata: {}
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options:
|
70
|
+
- "--main"
|
71
|
+
- README.md
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 2.2.2
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
requirements: []
|
85
|
+
rubyforge_project:
|
86
|
+
rubygems_version: 2.5.2
|
87
|
+
signing_key:
|
88
|
+
specification_version: 4
|
89
|
+
summary: score-formats - read / parse and print sports match scores (incl. half time,
|
90
|
+
full time, extra time, penalties and more)
|
91
|
+
test_files: []
|