sportdb-formats 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Manifest.txt +5 -0
- data/Rakefile +2 -2
- data/lib/sportdb/formats.rb +17 -5
- data/lib/sportdb/formats/country/country_index.rb +7 -7
- data/lib/sportdb/formats/country/country_reader.rb +26 -6
- data/lib/sportdb/formats/datafile_package.rb +10 -7
- data/lib/sportdb/formats/league/league_outline_reader.rb +24 -7
- data/lib/sportdb/formats/league/league_reader.rb +3 -3
- data/lib/sportdb/formats/match/mapper.rb +63 -63
- data/lib/sportdb/formats/match/mapper_teams.rb +1 -1
- data/lib/sportdb/formats/match/match_parser.rb +99 -180
- data/lib/sportdb/formats/match/match_parser_csv.rb +321 -0
- data/lib/sportdb/formats/package.rb +165 -11
- data/lib/sportdb/formats/parser_helper.rb +11 -2
- data/lib/sportdb/formats/score/score_formats.rb +41 -1
- data/lib/sportdb/formats/score/score_parser.rb +6 -0
- data/lib/sportdb/formats/structs/country.rb +6 -3
- data/lib/sportdb/formats/structs/group.rb +5 -12
- data/lib/sportdb/formats/structs/round.rb +6 -13
- data/lib/sportdb/formats/structs/standings.rb +30 -9
- data/lib/sportdb/formats/structs/team.rb +1 -2
- data/lib/sportdb/formats/team/club_reader_props.rb +3 -3
- data/lib/sportdb/formats/version.rb +4 -2
- data/test/helper.rb +2 -1
- data/test/test_club_reader_props.rb +2 -2
- data/test/test_country_index.rb +4 -4
- data/test/test_country_reader.rb +34 -4
- data/test/test_csv_match_parser.rb +114 -0
- data/test/test_csv_match_parser_utils.rb +20 -0
- data/test/test_csv_reader.rb +5 -5
- data/test/test_datafile.rb +0 -32
- data/test/test_datafile_package.rb +46 -0
- data/test/test_match_auto_relegation.rb +41 -0
- data/test/test_package.rb +60 -28
- data/test/test_package_match.rb +27 -3
- data/test/test_regex.rb +25 -7
- data/test/test_scores.rb +58 -49
- metadata +9 -4
@@ -2,38 +2,79 @@
|
|
2
2
|
module SportDb
|
3
3
|
class Package
|
4
4
|
|
5
|
+
## todo/fix: make all regexes case-insensitive with /i option - why? why not?
|
6
|
+
## e.g. .TXT and .txt
|
7
|
+
## yes!! use /i option!!!!!
|
8
|
+
|
5
9
|
CONF_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
|
6
10
|
\.conf\.txt$
|
7
11
|
}x
|
8
12
|
|
13
|
+
## leagues.txt or leagues_en.txt
|
14
|
+
## remove support for en.leagues.txt - why? why not?
|
9
15
|
LEAGUES_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
|
10
16
|
(?: [a-z]{1,4}\. )? # optional country code/key e.g. eng.clubs.wiki.txt
|
11
|
-
leagues
|
17
|
+
leagues
|
18
|
+
(?:_[a-z0-9_-]+)?
|
19
|
+
\.txt$
|
12
20
|
}x
|
13
21
|
|
22
|
+
## clubs.txt or clubs_en.txt
|
23
|
+
## remove support for en.clubs.txt - why? why not?
|
14
24
|
CLUBS_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
|
15
25
|
(?: [a-z]{1,4}\. )? # optional country code/key e.g. eng.clubs.txt
|
16
|
-
clubs
|
26
|
+
clubs
|
27
|
+
(?:_[a-z0-9_-]+)?
|
28
|
+
\.txt$
|
17
29
|
}x
|
18
30
|
|
19
31
|
CLUBS_WIKI_RE = %r{ (?:^|/) # beginning (^) or beginning of path (/)
|
20
32
|
(?:[a-z]{1,4}\.)? # optional country code/key e.g. eng.clubs.wiki.txt
|
21
|
-
clubs
|
33
|
+
clubs
|
34
|
+
(?:_[a-z0-9_-]+)?
|
35
|
+
\.wiki\.txt$
|
22
36
|
}x
|
23
37
|
|
24
38
|
CLUB_PROPS_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
|
25
39
|
(?: [a-z]{1,4}\. )? # optional country code/key e.g. eng.clubs.props.txt
|
26
|
-
clubs
|
40
|
+
clubs
|
41
|
+
(?:_[a-z0-9_-]+)?
|
42
|
+
\.props\.txt$
|
43
|
+
}x
|
44
|
+
|
45
|
+
## teams.txt or teams_history.txt
|
46
|
+
TEAMS_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
|
47
|
+
teams
|
48
|
+
(?:_[a-z0-9_-]+)?
|
49
|
+
\.txt$
|
27
50
|
}x
|
28
51
|
|
52
|
+
### season folder:
|
53
|
+
## e.g. /2019-20 or
|
54
|
+
## year-only e.g. /2019 or
|
55
|
+
## /2016--france
|
56
|
+
SEASON_RE = %r{ (?:
|
57
|
+
\d{4}-\d{2}
|
58
|
+
| \d{4}(--[a-z0-9_-]+)?
|
59
|
+
)
|
60
|
+
}x
|
61
|
+
SEASON = SEASON_RE.source ## "inline" helper for embedding in other regexes - keep? why? why not?
|
62
|
+
|
63
|
+
|
29
64
|
## note: if pattern includes directory add here
|
30
65
|
## (otherwise move to more "generic" datafile) - why? why not?
|
31
|
-
MATCH_RE = %r{
|
32
|
-
|
33
|
-
|
34
|
-
/[a-z0-9_-]+\.txt$ ## txt e.g /1-premierleague.txt
|
66
|
+
MATCH_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
|
67
|
+
#{SEASON}
|
68
|
+
/[a-z0-9_-]+\.txt$ ## txt e.g /1-premierleague.txt
|
35
69
|
}x
|
36
70
|
|
71
|
+
MATCH_CSV_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
|
72
|
+
#{SEASON}
|
73
|
+
/[a-z0-9_.-]+\.csv$ ## note: allow dot (.) too e.g /eng.1.csv
|
74
|
+
}x
|
75
|
+
|
76
|
+
|
77
|
+
|
37
78
|
## move class-level "static" finders to DirPackage (do NOT work for now for zip packages) - why? why not?
|
38
79
|
|
39
80
|
def self.find( path, pattern )
|
@@ -41,7 +82,7 @@ module SportDb
|
|
41
82
|
|
42
83
|
## check all txt files
|
43
84
|
## note: incl. files starting with dot (.)) as candidates (normally excluded with just *)
|
44
|
-
candidates = Dir.glob( "#{path}/**/{*,.*}
|
85
|
+
candidates = Dir.glob( "#{path}/**/{*,.*}.*" )
|
45
86
|
pp candidates
|
46
87
|
candidates.each do |candidate|
|
47
88
|
datafiles << candidate if pattern.match( candidate )
|
@@ -52,6 +93,8 @@ module SportDb
|
|
52
93
|
end
|
53
94
|
|
54
95
|
|
96
|
+
def self.find_teams( path, pattern: TEAMS_RE ) find( path, pattern ); end
|
97
|
+
def self.match_teams( path ) TEAMS_RE.match( path ); end
|
55
98
|
|
56
99
|
def self.find_clubs( path, pattern: CLUBS_RE ) find( path, pattern ); end
|
57
100
|
def self.find_clubs_wiki( path, pattern: CLUBS_WIKI_RE ) find( path, pattern ); end
|
@@ -66,7 +109,19 @@ module SportDb
|
|
66
109
|
def self.find_conf( path, pattern: CONF_RE ) find( path, pattern ); end
|
67
110
|
def self.match_conf( path ) CONF_RE.match( path ); end
|
68
111
|
|
112
|
+
def self.find_match( path, format: 'txt' )
|
113
|
+
if format == 'csv'
|
114
|
+
find( path, MATCH_CSV_RE )
|
115
|
+
else ## otherwise always assume txt for now
|
116
|
+
find( path, MATCH_RE )
|
117
|
+
end
|
118
|
+
end
|
119
|
+
## add match_match and match_match_csv - why? why not?
|
120
|
+
|
69
121
|
class << self
|
122
|
+
alias_method :match_teams?, :match_teams
|
123
|
+
alias_method :teams?, :match_teams
|
124
|
+
|
70
125
|
alias_method :match_clubs?, :match_clubs
|
71
126
|
alias_method :clubs?, :match_clubs
|
72
127
|
|
@@ -149,7 +204,14 @@ module SportDb
|
|
149
204
|
end
|
150
205
|
|
151
206
|
def each_conf( &blk ) each( pattern: CONF_RE, &blk ); end
|
152
|
-
def each_match(
|
207
|
+
def each_match( format: 'txt', &blk )
|
208
|
+
if format == 'csv'
|
209
|
+
each( pattern: MATCH_CSV_RE, &blk );
|
210
|
+
else
|
211
|
+
each( pattern: MATCH_RE, &blk );
|
212
|
+
end
|
213
|
+
end
|
214
|
+
def each_match_csv( &blk ) each( pattern: MATCH_CSV_RE, &blk ); end
|
153
215
|
def each_club_props( &blk ) each( pattern: CLUB_PROPS_RE, &blk ); end
|
154
216
|
|
155
217
|
def each_leagues( &blk ) each( pattern: LEAGUES_RE, &blk ); end
|
@@ -157,8 +219,100 @@ module SportDb
|
|
157
219
|
def each_clubs_wiki( &blk ) each( pattern: CLUBS_WIKI_RE, &blk ); end
|
158
220
|
|
159
221
|
## return all match datafile entries
|
160
|
-
def match(
|
222
|
+
def match( format: 'txt' )
|
223
|
+
ary=[]; each_match( format: format ) {|entry| ary << entry }; ary;
|
224
|
+
end
|
161
225
|
alias_method :matches, :match
|
226
|
+
|
227
|
+
|
228
|
+
## todo/check: rename/change to match_by_dir - why? why not?
|
229
|
+
## still in use somewhere? move to attic? use match_by_season and delete by_season_dir? - why? why not?
|
230
|
+
def match_by_season_dir( format: 'txt' )
|
231
|
+
##
|
232
|
+
## [["1950s/1956-57",
|
233
|
+
## ["1950s/1956-57/1-division1.csv",
|
234
|
+
## "1950s/1956-57/2-division2.csv",
|
235
|
+
## "1950s/1956-57/3a-division3n.csv",
|
236
|
+
## "1950s/1956-57/3b-division3s.csv"]],
|
237
|
+
## ...]
|
238
|
+
|
239
|
+
h = {}
|
240
|
+
match( format: format ).each do |entry|
|
241
|
+
season_path = File.dirname( entry.name )
|
242
|
+
|
243
|
+
h[ season_path ] ||= []
|
244
|
+
h[ season_path ] << entry
|
245
|
+
end
|
246
|
+
|
247
|
+
## todo/fix: - add sort entries by name - why? why not?
|
248
|
+
## note: assume 1-,2- etc. gets us back sorted leagues
|
249
|
+
## - use sort. (will not sort by default?)
|
250
|
+
|
251
|
+
h.to_a ## return as array (or keep hash) - why? why not?
|
252
|
+
end # method match_by_season_dir
|
253
|
+
|
254
|
+
def match_by_season( format: 'txt', start: nil ) ## change/rename to by_season_key - why? why not?
|
255
|
+
|
256
|
+
## todo/note: in the future - season might be anything (e.g. part of a filename and NOT a directory) - why? why not?
|
257
|
+
|
258
|
+
## note: fold all sames seasons (even if in different directories)
|
259
|
+
## into same datafile list e.g.
|
260
|
+
## ["1957/58",
|
261
|
+
## ["1950s/1957-58/1-division1.csv",
|
262
|
+
## "1950s/1957-58/2-division2.csv",
|
263
|
+
## "1950s/1957-58/3a-division3n.csv",
|
264
|
+
## "1950s/1957-58/3b-division3s.csv"]],
|
265
|
+
## and
|
266
|
+
## ["1957/58",
|
267
|
+
## ["archives/1950s/1957-58/1-division1.csv",
|
268
|
+
## "archives/1950s/1957-58/2-division2.csv",
|
269
|
+
## "archives/1950s/1957-58/3a-division3n.csv",
|
270
|
+
## "archives/1950s/1957-58/3b-division3s.csv"]],
|
271
|
+
## should be together - why? why not?
|
272
|
+
|
273
|
+
####
|
274
|
+
# Example package:
|
275
|
+
# [["2012/13", ["2012-13/1-proleague.csv"]],
|
276
|
+
# ["2013/14", ["2013-14/1-proleague.csv"]],
|
277
|
+
# ["2014/15", ["2014-15/1-proleague.csv"]],
|
278
|
+
# ["2015/16", ["2015-16/1-proleague.csv"]],
|
279
|
+
# ["2016/17", ["2016-17/1-proleague.csv"]],
|
280
|
+
# ["2017/18", ["2017-18/1-proleague.csv"]]]
|
281
|
+
|
282
|
+
## todo/fix: (re)use a more generic filter instead of start for start of season only
|
283
|
+
|
284
|
+
## todo/fix: use a "generic" filter_season helper for easy reuse
|
285
|
+
## filter_season( clause, season_key )
|
286
|
+
## or better filter = SeasonFilter.new( clause )
|
287
|
+
## filter.skip? filter.include? ( season_sason_key )?
|
288
|
+
## fiteer.before?( season_key ) etc.
|
289
|
+
## find some good method names!!!!
|
290
|
+
season_start = start ? Import::Season.new( start ) : nil
|
291
|
+
|
292
|
+
h = {}
|
293
|
+
match( format: format ).each do |entry|
|
294
|
+
## note: assume last directory in datafile path is the season part/key
|
295
|
+
season_q = File.basename( File.dirname( entry.name ))
|
296
|
+
season = Import::Season.new( season_q ) ## normalize season
|
297
|
+
|
298
|
+
## skip if start season before this season
|
299
|
+
next if season_start && season_start.start_year > season.start_year
|
300
|
+
|
301
|
+
h[ season.key ] ||= []
|
302
|
+
h[ season.key ] << entry
|
303
|
+
end
|
304
|
+
|
305
|
+
## todo/fix: - add sort entries by name - why? why not?
|
306
|
+
## note: assume 1-,2- etc. gets us back sorted leagues
|
307
|
+
## - use sort. (will not sort by default?)
|
308
|
+
|
309
|
+
## sort by season
|
310
|
+
## latest / newest first (and oldest last)
|
311
|
+
|
312
|
+
h.to_a.sort do |l,r| ## return as array (or keep hash) - why? why not?
|
313
|
+
r[0] <=> l[0]
|
314
|
+
end
|
315
|
+
end # method match_by_season
|
162
316
|
end # class Package
|
163
317
|
|
164
318
|
|
@@ -18,10 +18,19 @@ module SportDb
|
|
18
18
|
|
19
19
|
|
20
20
|
def is_round?( line )
|
21
|
-
## note: =~
|
22
|
-
|
21
|
+
## note: =~ returns nil if not match found, and 0,1, etc for match
|
22
|
+
|
23
|
+
## note: allow "free standing" leg 1 and leg 2 too
|
24
|
+
## (e.g. Hinspiel, Rückspiel etc. used for now in Relegation, for example)
|
25
|
+
## note ONLY allowed if "free standing", that is, full line with nothing else
|
26
|
+
## use "custom" regex for special case for now
|
27
|
+
## avoids match HIN in PascHINg, for example (hin in german for leg 1)
|
28
|
+
line =~ SportDb.lang.regex_round ||
|
29
|
+
line =~ /^(#{SportDb.lang.leg1})$/i ||
|
30
|
+
line =~ /^(#{SportDb.lang.leg2})$/i
|
23
31
|
end
|
24
32
|
|
33
|
+
|
25
34
|
def is_knockout_round?( line )
|
26
35
|
|
27
36
|
## todo: check for adding ignore case for regex (e.g. 1st leg/1st Leg)
|
@@ -93,12 +93,51 @@ module ScoreFormats
|
|
93
93
|
(?=[ \]]|$)/xi ## todo/check: remove loakahead assertion here - why require space?
|
94
94
|
## note: \b works only after non-alphanum e.g. )
|
95
95
|
|
96
|
+
|
96
97
|
#####
|
97
98
|
# deutsch / german helpers (penalty, extra time, ...)
|
98
99
|
## todo add more marker e.g. im Elf. or such!!!
|
99
100
|
P_DE = '(?: ie | i\.e\.? )' # e.g. iE, i.E., i.E etc.
|
100
101
|
ET_DE = '(?: nv | n\.v\.? )' # e.g. nV, n.V., n.V etc.
|
101
102
|
|
103
|
+
|
104
|
+
## support alternate all-in-one score e.g.
|
105
|
+
## i.E. 2:4, n.V. 3:3 (1:1, 1:1) or
|
106
|
+
## n.V. 3:2 (2:2, 1:2)
|
107
|
+
DE__P_ET_FT_HT__RE = /\b
|
108
|
+
(?:
|
109
|
+
#{P_DE}
|
110
|
+
[ ]*
|
111
|
+
(?<score1p>\d{1,2})
|
112
|
+
[ ]* : [ ]*
|
113
|
+
(?<score2p>\d{1,2})
|
114
|
+
[ ]* (?:, [ ]*)?
|
115
|
+
)? # note: make penalty (P) score optional for now
|
116
|
+
#{ET_DE}
|
117
|
+
[ ]*
|
118
|
+
(?<score1et>\d{1,2})
|
119
|
+
[ ]* : [ ]*
|
120
|
+
(?<score2et>\d{1,2})
|
121
|
+
[ ]*
|
122
|
+
\(
|
123
|
+
[ ]*
|
124
|
+
(?<score1>\d{1,2})
|
125
|
+
[ ]* : [ ]*
|
126
|
+
(?<score2>\d{1,2})
|
127
|
+
[ ]*
|
128
|
+
(?:
|
129
|
+
, [ ]*
|
130
|
+
(?:
|
131
|
+
(?<score1i>\d{1,2})
|
132
|
+
[ ]* : [ ]*
|
133
|
+
(?<score2i>\d{1,2})
|
134
|
+
[ ]*
|
135
|
+
)?
|
136
|
+
)? # note: make half time (HT) score optional for now
|
137
|
+
\)
|
138
|
+
(?=[ \]]|$)
|
139
|
+
/xi
|
140
|
+
|
102
141
|
## support all-in-one "literal form e.g.
|
103
142
|
# 2:2 (1:1, 1:0) n.V. 5:1 i.E. or
|
104
143
|
# 2-2 (1-1, 1-0) n.V. 5-1 i.E.
|
@@ -168,7 +207,8 @@ FORMATS_EN = [
|
|
168
207
|
]
|
169
208
|
|
170
209
|
FORMATS_DE = [
|
171
|
-
[ DE__ET_FT_HT_P__RE, '[SCORE.DE__ET_(FT_HT?)_P?]' ], # e.g.
|
210
|
+
[ 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.
|
211
|
+
[ 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)
|
172
212
|
[ DE__FT_HT__RE, '[SCORE.DE__FT_(HT)?]' ], # e.g. 1:1 (1:0)
|
173
213
|
]
|
174
214
|
|
@@ -90,6 +90,12 @@ class ScoreParser
|
|
90
90
|
|
91
91
|
|
92
92
|
def parse( line )
|
93
|
+
|
94
|
+
##########
|
95
|
+
## todo/fix/check: add unicode to regular dash conversion - why? why not?
|
96
|
+
## e.g. – becomes - (yes, the letters a different!!!)
|
97
|
+
#############
|
98
|
+
|
93
99
|
score = nil
|
94
100
|
@formats.each do |format|
|
95
101
|
re = format[0]
|
@@ -11,11 +11,14 @@ class Country
|
|
11
11
|
|
12
12
|
## note: is read-only/immutable for now - why? why not?
|
13
13
|
## add cities (array/list) - why? why not?
|
14
|
-
attr_reader :key, :name, :
|
14
|
+
attr_reader :key, :name, :code, :tags
|
15
15
|
attr_accessor :alt_names
|
16
16
|
|
17
|
-
def initialize( key
|
18
|
-
|
17
|
+
def initialize( key: nil, name:, code:, tags: [] )
|
18
|
+
## note: auto-generate key "on-the-fly" if missing for now - why? why not?
|
19
|
+
## note: quick hack - auto-generate key, that is, remove all non-ascii chars and downcase
|
20
|
+
@key = key || name.downcase.gsub( /[^a-z]/, '' )
|
21
|
+
@name, @code = name, code
|
19
22
|
@alt_names = []
|
20
23
|
@tags = tags
|
21
24
|
end
|
@@ -2,20 +2,13 @@ module SportDb
|
|
2
2
|
module Import
|
3
3
|
|
4
4
|
class Group
|
5
|
-
attr_reader
|
5
|
+
attr_reader :key, :name, :teams
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
## make start and end date optional
|
10
|
-
## change pos to num - why? why not?
|
11
|
-
## make pos/num optional too
|
12
|
-
##
|
13
|
-
## sort round by scheduled/planed start date
|
14
|
-
def initialize( title:,
|
15
|
-
pos:,
|
7
|
+
def initialize( key: nil,
|
8
|
+
name:,
|
16
9
|
teams: )
|
17
|
-
@
|
18
|
-
@
|
10
|
+
@key = key ## e.g. A,B,C or 1,2,3, - note: always a string or nil
|
11
|
+
@name = name
|
19
12
|
@teams = teams
|
20
13
|
end
|
21
14
|
end # class Group
|
@@ -2,24 +2,17 @@ module SportDb
|
|
2
2
|
module Import
|
3
3
|
|
4
4
|
class Round
|
5
|
-
attr_reader :
|
6
|
-
attr_accessor :
|
5
|
+
attr_reader :name, :start_date, :end_date, :knockout
|
6
|
+
attr_accessor :num # note: make read & writable - why? why not?
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
## make start and end date optional
|
11
|
-
## change pos to num - why? why not?
|
12
|
-
## make pos/num optional too
|
13
|
-
##
|
14
|
-
## sort round by scheduled/planed start date
|
15
|
-
def initialize( title:,
|
16
|
-
pos: nil,
|
8
|
+
def initialize( name:,
|
9
|
+
num: nil,
|
17
10
|
start_date: nil,
|
18
11
|
end_date: nil,
|
19
12
|
knockout: false,
|
20
13
|
auto: true )
|
21
|
-
@
|
22
|
-
@
|
14
|
+
@name = name
|
15
|
+
@num = num
|
23
16
|
@start_date = start_date
|
24
17
|
@end_date = end_date
|
25
18
|
@knockout = knockout
|
@@ -12,7 +12,7 @@ module SportDb
|
|
12
12
|
|
13
13
|
class Standings
|
14
14
|
|
15
|
-
class StandingsLine ## nested class StandinsLine
|
15
|
+
class StandingsLine ## nested class StandinsLine - todo/fix: change to Line - why? why not?
|
16
16
|
attr_accessor :rank, :team,
|
17
17
|
:played, :won, :lost, :drawn, ## -- total
|
18
18
|
:goals_for, :goals_against, :pts,
|
@@ -21,8 +21,13 @@ class Standings
|
|
21
21
|
:away_played, :away_won, :away_lost, :away_drawn, ## -- away
|
22
22
|
:away_goals_for, :away_goals_against, :away_pts
|
23
23
|
|
24
|
+
alias_method :team_name, :team ## note: team for now always a string
|
25
|
+
alias_method :pos, :rank ## rename back to use pos instead of rank - why? why not?
|
26
|
+
|
27
|
+
|
24
28
|
def initialize( team )
|
25
29
|
@rank = nil # use 0? why? why not?
|
30
|
+
## change rank back to pos - why? why not?
|
26
31
|
@team = team
|
27
32
|
@played = @home_played = @away_played = 0
|
28
33
|
@won = @home_won = @away_won = 0
|
@@ -49,7 +54,12 @@ class Standings
|
|
49
54
|
|
50
55
|
def update( match_or_matches )
|
51
56
|
## convenience - update all matches at once
|
52
|
-
|
57
|
+
## todo/check: check for ActiveRecord_Associations_CollectionProxy and than use to_a (to "force" array) - why? why not?
|
58
|
+
matches = if match_or_matches.is_a?(Array)
|
59
|
+
match_or_matches
|
60
|
+
else
|
61
|
+
[match_or_matches]
|
62
|
+
end
|
53
63
|
|
54
64
|
matches.each_with_index do |match,i| # note: index(i) starts w/ zero (0)
|
55
65
|
update_match( match )
|
@@ -171,19 +181,30 @@ class Standings
|
|
171
181
|
private
|
172
182
|
def update_match( m ) ## add a match
|
173
183
|
|
174
|
-
##
|
184
|
+
## note: always use team as string for now
|
185
|
+
## for now allow passing in of string OR struct - why? why not?
|
186
|
+
## todo/fix: change to m.team1_name and m.team2_name - why? why not?
|
187
|
+
team1 = m.team1.is_a?( String ) ? m.team1 : m.team1.name
|
188
|
+
team2 = m.team2.is_a?( String ) ? m.team2 : m.team2.name
|
189
|
+
|
190
|
+
score = m.score_str
|
191
|
+
|
192
|
+
## puts " #{team1} - #{team2} #{score}"
|
193
|
+
|
175
194
|
unless m.over?
|
176
|
-
puts " !!!! skipping match - not yet over (
|
195
|
+
puts " !!!! skipping match - not yet over (date in the future) => #{m.date}"
|
177
196
|
return
|
178
197
|
end
|
179
198
|
|
180
199
|
unless m.complete?
|
181
|
-
puts "!!! [calc_standings] skipping match #{
|
200
|
+
puts "!!! [calc_standings] skipping match #{team1} - #{team2} w/ past date #{m.date} - scores incomplete => #{score}"
|
182
201
|
return
|
183
202
|
end
|
184
203
|
|
185
|
-
|
186
|
-
|
204
|
+
|
205
|
+
|
206
|
+
line1 = @lines[ team1 ] || StandingsLine.new( team1 )
|
207
|
+
line2 = @lines[ team2 ] || StandingsLine.new( team2 )
|
187
208
|
|
188
209
|
line1.played += 1
|
189
210
|
line1.home_played += 1
|
@@ -236,8 +257,8 @@ private
|
|
236
257
|
puts "*** warn: [standings] skipping match with missing scores: #{m.inspect}"
|
237
258
|
end
|
238
259
|
|
239
|
-
@lines[
|
240
|
-
@lines[
|
260
|
+
@lines[ team1 ] = line1
|
261
|
+
@lines[ team2 ] = line2
|
241
262
|
end # method update_match
|
242
263
|
|
243
264
|
end # class Standings
|