sportdb-formats 1.0.2 → 1.1.0

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/Manifest.txt +5 -0
  3. data/Rakefile +2 -2
  4. data/lib/sportdb/formats.rb +17 -5
  5. data/lib/sportdb/formats/country/country_index.rb +7 -7
  6. data/lib/sportdb/formats/country/country_reader.rb +26 -6
  7. data/lib/sportdb/formats/datafile_package.rb +10 -7
  8. data/lib/sportdb/formats/league/league_outline_reader.rb +24 -7
  9. data/lib/sportdb/formats/league/league_reader.rb +3 -3
  10. data/lib/sportdb/formats/match/mapper.rb +63 -63
  11. data/lib/sportdb/formats/match/mapper_teams.rb +1 -1
  12. data/lib/sportdb/formats/match/match_parser.rb +99 -180
  13. data/lib/sportdb/formats/match/match_parser_csv.rb +321 -0
  14. data/lib/sportdb/formats/package.rb +165 -11
  15. data/lib/sportdb/formats/parser_helper.rb +11 -2
  16. data/lib/sportdb/formats/score/score_formats.rb +41 -1
  17. data/lib/sportdb/formats/score/score_parser.rb +6 -0
  18. data/lib/sportdb/formats/structs/country.rb +6 -3
  19. data/lib/sportdb/formats/structs/group.rb +5 -12
  20. data/lib/sportdb/formats/structs/round.rb +6 -13
  21. data/lib/sportdb/formats/structs/standings.rb +30 -9
  22. data/lib/sportdb/formats/structs/team.rb +1 -2
  23. data/lib/sportdb/formats/team/club_reader_props.rb +3 -3
  24. data/lib/sportdb/formats/version.rb +4 -2
  25. data/test/helper.rb +2 -1
  26. data/test/test_club_reader_props.rb +2 -2
  27. data/test/test_country_index.rb +4 -4
  28. data/test/test_country_reader.rb +34 -4
  29. data/test/test_csv_match_parser.rb +114 -0
  30. data/test/test_csv_match_parser_utils.rb +20 -0
  31. data/test/test_csv_reader.rb +5 -5
  32. data/test/test_datafile.rb +0 -32
  33. data/test/test_datafile_package.rb +46 -0
  34. data/test/test_match_auto_relegation.rb +41 -0
  35. data/test/test_package.rb +60 -28
  36. data/test/test_package_match.rb +27 -3
  37. data/test/test_regex.rb +25 -7
  38. data/test/test_scores.rb +58 -49
  39. 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\.txt$
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\.txt$
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\.wiki\.txt$
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\.props\.txt$
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{ /(?: \d{4}-\d{2} ## season folder e.g. /2019-20
32
- | \d{4}(--[^/]+)? ## season year-only folder e.g. /2019 or /2016--france
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}/**/{*,.*}.txt" )
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( &blk ) each( pattern: MATCH_RE, &blk ); end
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() ary=[]; each_match {|entry| ary << entry }; ary; end
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: =~ return nil if not match found, and 0,1, etc for match
22
- (line =~ SportDb.lang.regex_round) != nil
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. 2:2 (1:1, 1:0) n.V. 5:1 i.E.
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, :fifa, :tags
14
+ attr_reader :key, :name, :code, :tags
15
15
  attr_accessor :alt_names
16
16
 
17
- def initialize( key:, name:, fifa:, tags: [] )
18
- @key, @name, @fifa = key, name, fifa
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 :title, :pos, :teams
5
+ attr_reader :key, :name, :teams
6
6
 
7
- ##
8
- ## todo: change db schema
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
- @title = title
18
- @pos = pos
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 :title, :start_date, :end_date, :knockout
6
- attr_accessor :pos # note: make read & writable
5
+ attr_reader :name, :start_date, :end_date, :knockout
6
+ attr_accessor :num # note: make read & writable - why? why not?
7
7
 
8
- ##
9
- ## todo: change db schema
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
- @title = title
22
- @pos = pos
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
- matches = match_or_matches.is_a?(Array) ? match_or_matches : [match_or_matches]
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
- ## puts " #{m.team1} - #{m.team2} #{m.score_str}"
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 (play_at date in the future)"
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 #{m.team1} - #{m.team2} - scores incomplete #{m.score_str}"
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
- line1 = @lines[ m.team1 ] || StandingsLine.new( m.team1 )
186
- line2 = @lines[ m.team2 ] || StandingsLine.new( m.team2 )
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[ m.team1 ] = line1
240
- @lines[ m.team2 ] = line2
260
+ @lines[ team1 ] = line1
261
+ @lines[ team2 ] = line2
241
262
  end # method update_match
242
263
 
243
264
  end # class Standings