sportdb 1.8.7 → 1.8.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -47,6 +47,16 @@ lib/sportdb/models/world/continent.rb
47
47
  lib/sportdb/models/world/country.rb
48
48
  lib/sportdb/models/world/region.rb
49
49
  lib/sportdb/reader.rb
50
+ lib/sportdb/readers/event.rb
51
+ lib/sportdb/readers/game.rb
52
+ lib/sportdb/readers/ground.rb
53
+ lib/sportdb/readers/league.rb
54
+ lib/sportdb/readers/race.rb
55
+ lib/sportdb/readers/record.rb
56
+ lib/sportdb/readers/roster.rb
57
+ lib/sportdb/readers/season.rb
58
+ lib/sportdb/readers/team.rb
59
+ lib/sportdb/readers/track.rb
50
60
  lib/sportdb/schema.rb
51
61
  lib/sportdb/service.rb
52
62
  lib/sportdb/service/public/football/js/football/api.js
File without changes
@@ -72,7 +72,20 @@ require 'sportdb/utils_round'
72
72
  require 'sportdb/utils_scores'
73
73
  require 'sportdb/utils_teams'
74
74
  require 'sportdb/matcher'
75
+
76
+
77
+ require 'sportdb/readers/event'
78
+ require 'sportdb/readers/game'
79
+ require 'sportdb/readers/ground'
80
+ require 'sportdb/readers/league'
81
+ require 'sportdb/readers/race'
82
+ require 'sportdb/readers/record'
83
+ require 'sportdb/readers/roster'
84
+ require 'sportdb/readers/season'
85
+ require 'sportdb/readers/team'
86
+ require 'sportdb/readers/track'
75
87
  require 'sportdb/reader'
88
+
76
89
  require 'sportdb/lang'
77
90
 
78
91
  require 'sportdb/updater'
@@ -43,17 +43,20 @@ class Reader
43
43
  def load( name ) # convenience helper for all-in-one reader
44
44
 
45
45
  logger.debug "enter load( name=>>#{name}<<, include_path=>>#{include_path}<<)"
46
-
46
+
47
47
  if name =~ /^circuits/ # e.g. circuits.txt in formula1.db
48
- load_tracks( name )
48
+ reader = TrackReader.new( include_path )
49
+ reader.read( name )
49
50
  elsif match_tracks_for_country( name ) do |country_key| # name =~ /^([a-z]{2})\/tracks/
50
51
  # auto-add country code (from folder structure) for country-specific tracks
51
52
  # e.g. at/tracks or at-austria/tracks
52
53
  country = Country.find_by_key!( country_key )
53
- load_tracks( name, country_id: country.id )
54
+ reader = TrackReader.new( include_path )
55
+ reader.read( name, country_id: country.id )
54
56
  end
55
57
  elsif name =~ /^tracks/ # e.g. tracks.txt in ski.db
56
- load_tracks( name )
58
+ reader = TrackReader.new( include_path )
59
+ reader.read( name )
57
60
  elsif name =~ /^drivers/ # e.g. drivers.txt in formula1.db
58
61
  load_persons( name )
59
62
  elsif match_skiers_for_country( name ) do |country_key| # name =~ /^([a-z]{2})\/skiers/
@@ -65,101 +68,80 @@ class Reader
65
68
  elsif name =~ /^skiers/ # e.g. skiers.men.txt in ski.db
66
69
  load_persons( name )
67
70
  elsif name =~ /^teams/ # e.g. teams.txt in formula1.db
68
- load_teams( name )
71
+ reader = TeamReader.new( include_path )
72
+ reader.read( name )
69
73
  elsif name =~ /\/races/ # e.g. 2013/races.txt in formula1.db
70
- load_races( name )
74
+ reader = RaceReader.new( include_path )
75
+ reader.read( name )
71
76
  elsif name =~ /\/squads/ || name =~ /\/rosters/ # e.g. 2013/squads.txt in formula1.db
72
- load_rosters( name )
77
+ reader = RosterReader.new( include_path )
78
+ reader.read( name )
73
79
  elsif name =~ /\/([0-9]{2})-/
74
80
  race_pos = $1.to_i
75
81
  # NB: assume @event is set from previous load
76
82
  race = Race.find_by_event_id_and_pos( @event.id, race_pos )
77
- load_records( name, race_id: race.id ) # e.g. 2013/04-gp-monaco.txt in formula1.db
83
+ reader = RecordReader.new( include_path )
84
+ reader.read( name, race_id: race.id ) # e.g. 2013/04-gp-monaco.txt in formula1.db
78
85
  elsif name =~ /(?:^|\/)seasons/ # NB: ^seasons or also possible at-austria!/seasons
79
- load_seasons( name )
86
+ reader = SeasonReader.new( include_path )
87
+ reader.read( name )
80
88
  elsif match_stadiums_for_country( name ) do |country_key|
81
89
  country = Country.find_by_key!( country_key )
82
- load_stadiums( name, country_id: country.id )
90
+ reader = GroundReader.new( include_path )
91
+ reader.read( name, country_id: country.id )
83
92
  end
84
93
  elsif match_leagues_for_country( name ) do |country_key| # name =~ /^([a-z]{2})\/leagues/
85
94
  # auto-add country code (from folder structure) for country-specific leagues
86
95
  # e.g. at/leagues
87
96
  country = Country.find_by_key!( country_key )
88
- load_leagues( name, club: true, country_id: country.id )
97
+ reader = LeagueReader.new( include_path )
98
+ reader.read( name, club: true, country_id: country.id )
89
99
  end
90
100
  elsif name =~ /(?:^|\/)leagues/ # NB: ^leagues or also possible world!/leagues - NB: make sure goes after leagues_for_country!!
91
101
  if name =~ /-cup!?\// || # NB: -cup/ or -cup!/
92
102
  name =~ /copa-america!?\// # NB: copa-america/ or copa-america!/
93
103
  # e.g. national team tournaments/leagues (e.g. world-cup/ or euro-cup/)
94
- load_leagues( name, club: false )
104
+ reader = LeagueReader.new( include_path )
105
+ reader.read( name, club: false )
95
106
  else
96
107
  # e.g. leagues_club
97
- load_leagues( name, club: true )
108
+ reader = LeagueReader.new( include_path )
109
+ reader.read( name, club: true )
98
110
  end
99
111
  elsif match_teams_for_country( name ) do |country_key| # name =~ /^([a-z]{2})\/teams/
100
112
  # auto-add country code (from folder structure) for country-specific teams
101
113
  # e.g. at/teams at/teams.2 de/teams etc.
102
114
  country = Country.find_by_key!( country_key )
103
- load_teams( name, club: true, country_id: country.id )
115
+ reader = TeamReader.new( include_path )
116
+ reader.read( name, club: true, country_id: country.id )
104
117
  end
105
118
  elsif name =~ /(?:^|\/)teams/
106
119
  if name =~ /-cup!?\// || # NB: -cup/ or -cup!/
107
120
  name =~ /copa-america!?\// # NB: copa-america/ or copa-america!/
108
121
  # assume national teams
109
122
  # e.g. world-cup/teams amercia-cup/teams_northern
110
- load_teams( name, club: false )
123
+ reader = TeamReader.new( include_path )
124
+ reader.read( name, club: false )
111
125
  else
112
126
  # club teams (many countries)
113
127
  # e.g. club/europe/teams
114
- load_teams( name, club: true )
128
+ reader = TeamReader.new( include_path )
129
+ reader.read( name, club: true )
115
130
  end
116
131
  elsif name =~ /\/(\d{4}|\d{4}_\d{2})\// || name =~ /\/(\d{4}|\d{4}_\d{2})$/
117
132
  # e.g. must match /2012/ or /2012_13/
118
133
  # or /2012 or /2012_13 e.g. brazil/2012 or brazil/2012_13
119
- load_event( name )
120
- event = fetch_event( name )
121
- fixtures = fetch_event_fixtures( name )
122
- fixtures.each do |fx|
123
- load_fixtures( event.key, fx )
124
- end
134
+ reader = GameReader.new( include_path )
135
+ reader.read( name )
125
136
  else
126
137
  logger.error "unknown sportdb fixture type >#{name}<"
127
138
  # todo/fix: exit w/ error
128
139
  end
129
140
  end # method load
130
141
 
131
-
132
- def load_stadiums( name, more_attribs={} )
133
- reader = ValuesReaderV2.new( name, include_path, more_attribs )
134
-
135
- reader.each_line do |new_attributes, values|
136
- Ground.create_or_update_from_values( new_attributes, values )
137
- end # each lines
138
- end
139
-
140
-
141
- def load_leagues( name, more_attribs={} )
142
-
143
- reader = ValuesReaderV2.new( name, include_path, more_attribs )
144
-
145
- reader.each_line do |new_attributes, values|
146
- League.create_or_update_from_values( new_attributes, values )
147
- end # each lines
148
-
149
- end # load_leagues
150
-
151
-
152
- def load_tracks( name, more_attribs={} )
153
-
154
- reader = ValuesReaderV2.new( name, include_path, more_attribs )
155
-
156
- reader.each_line do |new_attributes, values|
157
- Track.create_or_update_from_values( new_attributes, values )
158
- end # each lines
159
-
160
- end # load_tracks
161
-
162
142
 
143
+ ####
144
+ ## fix: move to persondb for (re)use
163
145
 
164
146
  def load_persons( name, more_attribs={} )
165
147
 
@@ -171,775 +153,6 @@ class Reader
171
153
 
172
154
  end # load_persons
173
155
 
174
-
175
- def load_seasons( name )
176
-
177
- reader = LineReaderV2.new( name, include_path )
178
-
179
- ####
180
- ## fix!!!!!
181
- ## use Season.create_or_update_from_hash or similar
182
- ## use Season.create_or_update_from_hash_reader?? or similar
183
- # move parsing code to model
184
-
185
- reader.each_line do |line|
186
-
187
- # for now assume single value
188
- logger.debug ">#{line}<"
189
-
190
- key = line
191
-
192
- logger.debug " find season key: #{key}"
193
- season = Season.find_by_key( key )
194
-
195
- season_attribs = {}
196
-
197
- ## check if it exists
198
- if season.present?
199
- logger.debug "update season #{season.id}-#{season.key}:"
200
- else
201
- logger.debug "create season:"
202
- season = Season.new
203
- season_attribs[ :key ] = key
204
- end
205
-
206
- season_attribs[ :title ] = key # for now key n title are the same
207
-
208
- logger.debug season_attribs.to_json
209
-
210
- season.update_attributes!( season_attribs )
211
- end # each line
212
-
213
- end # load_seasons
214
-
215
-
216
- def fetch_event_fixtures( name )
217
- # todo: merge with fetch_event to make it single read op - why? why not??
218
- reader = HashReaderV2.new( name, include_path )
219
-
220
- fixtures = []
221
-
222
- reader.each_typed do |key, value|
223
- if key == 'fixtures' && value.kind_of?( Array )
224
- logger.debug "fixtures:"
225
- logger.debug value.to_json
226
- ## todo: make sure we get an array!!!!!
227
- fixtures = value
228
- else
229
- # skip; do nothing
230
- end
231
- end # each key,value
232
-
233
- if fixtures.empty?
234
- ## logger.warn "no fixtures found for event - >#{name}<; assume fixture name is the same as event"
235
- fixtures = [name]
236
- else
237
- ## add path to fixtures (use path from event e.g)
238
- # - bl + at-austria!/2012_13/bl -> at-austria!/2012_13/bl
239
- # - bl_ii + at-austria!/2012_13/bl -> at-austria!/2012_13/bl_ii
240
-
241
- dir = File.dirname( name ) # use dir for fixtures
242
-
243
- fixtures = fixtures.map do |fx|
244
- fx_new = "#{dir}/#{fx}" # add path upfront
245
- logger.debug "fx: #{fx_new} | >#{fx}< + >#{dir}<"
246
- fx_new
247
- end
248
- end
249
-
250
- fixtures
251
- end
252
-
253
-
254
- def fetch_event( name )
255
- # get/fetch/find event from yml file
256
-
257
- ## todo/fix: use h = HashFile.load( path ) or similar instead of HashReader!!
258
-
259
- ## todo/fix: add option for not adding prop automatically?? w/ HashReaderV2
260
-
261
- reader = HashReaderV2.new( name, include_path )
262
-
263
- event_attribs = {}
264
-
265
- reader.each_typed do |key, value|
266
-
267
- ## puts "processing event attrib >>#{key}<< >>#{value}<<..."
268
-
269
- if key == 'league'
270
- league = League.find_by_key!( value.to_s.strip )
271
- event_attribs[ 'league_id' ] = league.id
272
- elsif key == 'season'
273
- season = Season.find_by_key!( value.to_s.strip )
274
- event_attribs[ 'season_id' ] = season.id
275
- else
276
- # skip; do nothing
277
- end
278
- end # each key,value
279
-
280
- league_id = event_attribs['league_id']
281
- season_id = event_attribs['season_id']
282
-
283
- event = Event.find_by_league_id_and_season_id!( league_id, season_id )
284
- event
285
- end
286
-
287
-
288
- def load_event( name )
289
-
290
- ####
291
- ## fix!!!!!
292
- ## use Event.create_or_update_from_hash or similar
293
- ## use Event.create_or_update_from_hash_reader?? or similar
294
- # move parsing code to model
295
-
296
- reader = HashReaderV2.new( name, include_path )
297
-
298
- event_attribs = {}
299
-
300
- ## set default sources to basename by convention
301
- # e.g 2013_14/bl => bl
302
- # etc.
303
- # use fixtures/sources: to override default
304
-
305
- event_attribs[ 'sources' ] = File.basename( name )
306
- event_attribs[ 'config' ] = File.basename( name ) # name a of .yml file
307
-
308
- reader.each_typed do |key, value|
309
-
310
- ## puts "processing event attrib >>#{key}<< >>#{value}<<..."
311
-
312
- if key == 'league'
313
- league = League.find_by_key( value.to_s.strip )
314
-
315
- ## check if it exists
316
- if league.present?
317
- event_attribs['league_id'] = league.id
318
- else
319
- logger.error "league with key >>#{value.to_s.strip}<< missing"
320
- exit 1
321
- end
322
-
323
- elsif key == 'season'
324
- season = Season.find_by_key( value.to_s.strip )
325
-
326
- ## check if it exists
327
- if season.present?
328
- event_attribs['season_id'] = season.id
329
- else
330
- logger.error "season with key >>#{value.to_s.strip}<< missing"
331
- exit 1
332
- end
333
-
334
- elsif key == 'start_at' || key == 'begin_at'
335
-
336
- if value.is_a?(DateTime) || value.is_a?(Date)
337
- start_at = value
338
- else # assume it's a string
339
- start_at = DateTime.strptime( value.to_s.strip, '%Y-%m-%d' )
340
- end
341
-
342
- event_attribs['start_at'] = start_at
343
-
344
- elsif key == 'end_at' || key == 'stop_at'
345
-
346
- if value.is_a?(DateTime) || value.is_a?(Date)
347
- end_at = value
348
- else # assume it's a string
349
- end_at = DateTime.strptime( value.to_s.strip, '%Y-%m-%d' )
350
- end
351
-
352
- event_attribs['end_at'] = end_at
353
-
354
- elsif key == 'grounds' || key == 'stadiums' || key == 'venues'
355
- ## assume grounds value is an array
356
-
357
- ##
358
- ## note: for now we allow invalid ground keys
359
- ## will skip keys not found
360
-
361
- ground_ids = []
362
- value.each do |item|
363
- ground_key = item.to_s.strip
364
- ground = Ground.find_by_key( ground_key )
365
- if ground.nil?
366
- puts "[warn] ground/stadium w/ key >#{ground_key}< not found; skipping ground"
367
- else
368
- ground_ids << ground.id
369
- end
370
- end
371
-
372
- event_attribs['ground_ids'] = ground_ids
373
- elsif key == 'teams'
374
- ## assume teams value is an array
375
-
376
- team_ids = []
377
- value.each do |item|
378
- team_key = item.to_s.strip
379
- team = Team.find_by_key!( team_key )
380
- team_ids << team.id
381
- end
382
-
383
- event_attribs['team_ids'] = team_ids
384
-
385
- elsif key == 'team3'
386
- ## for now always assume false # todo: fix - use value and convert to boolean if not boolean
387
- event_attribs['team3'] = false
388
- elsif key == 'fixtures' || key == 'sources'
389
- if value.kind_of?(Array)
390
- event_attribs['sources'] = value.join(',')
391
- else # assume plain (single fixture) string
392
- event_attribs['sources'] = value.to_s
393
- end
394
- else
395
- ## todo: add a source location struct to_s or similar (file, line, col)
396
- logger.error "unknown event attrib #{key}; skipping attrib"
397
- end
398
-
399
- end # each key,value
400
-
401
- league_id = event_attribs['league_id']
402
- season_id = event_attribs['season_id']
403
-
404
- logger.debug "find event - league_id: #{league_id}, season_id: #{season_id}"
405
-
406
- event = Event.find_by_league_id_and_season_id( league_id, season_id )
407
-
408
- ## check if it exists
409
- if event.present?
410
- logger.debug "*** update event #{event.id}-#{event.key}:"
411
- else
412
- logger.debug "*** create event:"
413
- event = Event.new
414
- end
415
-
416
- logger.debug event_attribs.to_json
417
-
418
- event.update_attributes!( event_attribs )
419
-
420
- end # load_event
421
-
422
-
423
-
424
- def load_fixtures_from_string( event_key, text ) # load from string (e.g. passed in via web form)
425
-
426
- SportDb.lang.lang = SportDb.lang.classify( text )
427
-
428
- ## todo/fix: move code into LineReader e.g. use LineReader.fromString() - why? why not?
429
- reader = StringLineReader.new( text )
430
-
431
- load_fixtures_worker( event_key, reader )
432
-
433
- ## fix add prop
434
- ### Prop.create!( key: "db.#{fixture_name_to_prop_key(name)}.version", value: "file.txt.#{File.mtime(path).strftime('%Y.%m.%d')}" )
435
- end
436
-
437
- def load_fixtures( event_key, name ) # load from file system
438
-
439
- ## todo: move name_real_path code to LineReaderV2 ????
440
- pos = name.index( '!/')
441
- if pos.nil?
442
- name_real_path = name # not found; real path is the same as name
443
- else
444
- # cut off everything until !/ e.g.
445
- # at-austria!/w-wien/beers becomes
446
- # w-wien/beers
447
- name_real_path = name[ (pos+2)..-1 ]
448
- end
449
-
450
-
451
- path = "#{include_path}/#{name_real_path}.txt"
452
-
453
- logger.info "parsing data '#{name}' (#{path})..."
454
-
455
- SportDb.lang.lang = SportDb.lang.classify_file( path )
456
-
457
- reader = LineReader.new( path )
458
-
459
- load_fixtures_worker( event_key, reader )
460
-
461
- Prop.create_from_fixture!( name, path )
462
- end
463
-
464
-
465
-
466
- def load_records( name, more_attribs={} )
467
- path = "#{include_path}/#{name}.txt"
468
-
469
- logger.info "parsing data '#{name}' (#{path})..."
470
-
471
- ### SportDb.lang.lang = LangChecker.new.analyze( name, include_path )
472
-
473
- reader = LineReader.new( path )
474
-
475
- ## for now: use all tracks (later filter/scope by event)
476
- # @known_tracks = Track.known_tracks_table
477
-
478
- ## fix: add @known_teams - for now; use teams (not scoped by event)
479
- @known_teams = TextUtils.build_title_table_for( Team.all )
480
- ## and for now use all persons
481
- @known_persons = TextUtils.build_title_table_for( Person.all )
482
-
483
- load_records_worker( reader, more_attribs )
484
-
485
- Prop.create_from_fixture!( name, path )
486
- end
487
-
488
- def load_records_worker( reader, more_attribs )
489
-
490
- reader.each_line do |line|
491
- logger.debug " line: >#{line}<"
492
-
493
- cut_off_end_of_line_comment!( line )
494
-
495
- state = find_record_leading_state!( line )
496
-
497
- map_team!( line )
498
- team_key = find_team!( line )
499
- team = Team.find_by_key!( team_key )
500
-
501
- map_person!( line )
502
- person_key = find_person!( line )
503
- person = Person.find_by_key!( person_key )
504
-
505
- timeline = find_record_timeline!( line )
506
-
507
- laps = find_record_laps!( line )
508
-
509
- comment = find_record_comment!( line )
510
-
511
- logger.debug " line2: >#{line}<"
512
-
513
- record_attribs = {
514
- state: state,
515
- ## team_id: team.id, ## NB: not needed for db
516
- person_id: person.id,
517
- timeline: timeline,
518
- comment: comment,
519
- laps: laps
520
- }
521
-
522
- record_attribs = record_attribs.merge( more_attribs )
523
-
524
- ### check if record exists
525
- record = Record.find_by_race_id_and_person_id( record_attribs[ :race_id ],
526
- record_attribs[ :person_id ])
527
-
528
- if record.present?
529
- logger.debug "update Record #{record.id}:"
530
- else
531
- logger.debug "create Record:"
532
- record = Record.new
533
- end
534
-
535
- logger.debug record_attribs.to_json
536
-
537
- record.update_attributes!( record_attribs )
538
-
539
- end # lines.each
540
-
541
- end # method load_record_worker
542
-
543
-
544
-
545
- def load_rosters( name )
546
- path = "#{include_path}/#{name}.txt"
547
-
548
- logger.info "parsing data '#{name}' (#{path})..."
549
-
550
- ### SportDb.lang.lang = LangChecker.new.analyze( name, include_path )
551
-
552
- reader = LineReader.new( path )
553
-
554
- ## for now: use all tracks (later filter/scope by event)
555
- # @known_tracks = Track.known_tracks_table
556
-
557
- ## fix: add @known_teams - for now; use teams (not scoped by event)
558
- ## for now use all teams
559
- @known_teams = TextUtils.build_title_table_for( Team.all )
560
- ## and for now use all persons
561
- @known_persons = TextUtils.build_title_table_for( Person.all )
562
-
563
-
564
- load_rosters_worker( reader )
565
-
566
- Prop.create_from_fixture!( name, path )
567
- end
568
-
569
- def load_rosters_worker( reader )
570
-
571
- reader.each_line do |line|
572
- logger.debug " line: >#{line}<"
573
-
574
- cut_off_end_of_line_comment!( line )
575
-
576
- pos = find_leading_pos!( line )
577
-
578
- map_team!( line )
579
- team_key = find_team!( line )
580
- team = Team.find_by_key!( team_key )
581
-
582
- map_person!( line )
583
- person_key = find_person!( line )
584
- person = Person.find_by_key!( person_key )
585
-
586
- logger.debug " line2: >#{line}<"
587
-
588
- ### check if roster record exists
589
- roster = Roster.find_by_event_id_and_team_id_and_person_id( @event.id, team.id, person.id )
590
-
591
- if roster.present?
592
- logger.debug "update Roster #{roster.id}:"
593
- else
594
- logger.debug "create Roster:"
595
- roster = Roster.new
596
- end
597
-
598
- roster_attribs = {
599
- pos: pos,
600
- team_id: team.id,
601
- person_id: person.id,
602
- event_id: @event.id # NB: reuse/fallthrough from races - make sure load_races goes first (to setup event)
603
- }
604
-
605
- logger.debug roster_attribs.to_json
606
-
607
- roster.update_attributes!( roster_attribs )
608
- end # lines.each
609
-
610
- end # method load_rosters_worker
611
-
612
-
613
-
614
- def load_races( name )
615
- load_event( name ) # must have .yml file with same name for event definition
616
- @event = fetch_event( name )
617
-
618
- logger.info " event: #{@event.key} >>#{@event.full_title}<<"
619
-
620
- path = "#{include_path}/#{name}.txt"
621
-
622
- logger.info "parsing data '#{name}' (#{path})..."
623
-
624
- ### SportDb.lang.lang = LangChecker.new.analyze( name, include_path )
625
-
626
- reader = LineReader.new( path )
627
-
628
- ## for now: use all tracks (later filter/scope by event)
629
- @known_tracks = Track.known_tracks_table
630
-
631
- load_races_worker( reader )
632
-
633
- Prop.create_from_fixture!( name, path )
634
- end
635
-
636
-
637
- def load_races_worker( reader )
638
-
639
- reader.each_line do |line|
640
- logger.debug " line: >#{line}<"
641
-
642
- cut_off_end_of_line_comment!( line )
643
-
644
- pos = find_leading_pos!( line )
645
-
646
- map_track!( line )
647
- track_key = find_track!( line )
648
- track = Track.find_by_key!( track_key )
649
-
650
- date = find_date!( line )
651
-
652
- logger.debug " line2: >#{line}<"
653
-
654
- ### check if games exists
655
- race = Race.find_by_event_id_and_track_id( @event.id, track.id )
656
-
657
- if race.present?
658
- logger.debug "update race #{race.id}:"
659
- else
660
- logger.debug "create race:"
661
- race = Race.new
662
- end
663
-
664
- race_attribs = {
665
- pos: pos,
666
- track_id: track.id,
667
- start_at: date,
668
- event_id: @event.id
669
- }
670
-
671
- logger.debug race_attribs.to_json
672
-
673
- race.update_attributes!( race_attribs )
674
- end # lines.each
675
-
676
- end # method load_races_worker
677
-
678
-
679
- def load_teams( name, more_attribs={} )
680
- reader = ValuesReaderV2.new( name, include_path, more_attribs )
681
-
682
- reader.each_line do |new_attributes, values|
683
- Team.create_or_update_from_values( new_attributes, values )
684
- end # each lines
685
- end # load_teams
686
-
687
- private
688
-
689
- include SportDb::FixtureHelpers
690
-
691
- def load_fixtures_worker( event_key, reader )
692
-
693
- ## assume active activerecord connection
694
- ##
695
-
696
- ## reset cached values
697
- @patch_rounds = {}
698
- @knockout_flag = false
699
- @round = nil
700
-
701
-
702
- @event = Event.find_by_key!( event_key )
703
-
704
- logger.debug "Event #{@event.key} >#{@event.title}<"
705
-
706
- ### fix: use build_title_table_for ??? why? why not??
707
- @known_teams = @event.known_teams_table
708
-
709
- @known_grounds = TextUtils.build_title_table_for( @event.grounds )
710
-
711
-
712
- parse_fixtures( reader )
713
-
714
- end # method load_fixtures
715
-
716
-
717
- def parse_group( line )
718
- logger.debug "parsing group line: >#{line}<"
719
-
720
- match_teams!( line )
721
- team_keys = find_teams!( line )
722
-
723
- title, pos = find_group_title_and_pos!( line )
724
-
725
- logger.debug " line: >#{line}<"
726
-
727
- group_attribs = {
728
- title: title
729
- }
730
-
731
- @group = Group.find_by_event_id_and_pos( @event.id, pos )
732
- if @group.present?
733
- logger.debug "update group #{@group.id}:"
734
- else
735
- logger.debug "create group:"
736
- @group = Group.new
737
- group_attribs = group_attribs.merge( {
738
- event_id: @event.id,
739
- pos: pos
740
- })
741
- end
742
-
743
- logger.debug group_attribs.to_json
744
-
745
- @group.update_attributes!( group_attribs )
746
-
747
- @group.teams.clear # remove old teams
748
- ## add new teams
749
- team_keys.each do |team_key|
750
- team = Team.find_by_key!( team_key )
751
- logger.debug " adding team #{team.title} (#{team.code})"
752
- @group.teams << team
753
- end
754
- end
755
-
756
- def parse_round( line )
757
- logger.debug "parsing round line: >#{line}<"
758
-
759
- ### todo/fix/check: move cut off optional comment in reader for all lines? why? why not?
760
- cut_off_end_of_line_comment!( line ) # cut off optional comment starting w/ #
761
-
762
- # NB: cut off optional title2 starting w/ // first
763
- title2 = find_round_title2!( line )
764
-
765
- group_title, group_pos = find_group_title_and_pos!( line )
766
-
767
- pos = find_round_pos!( line )
768
-
769
- title = find_round_title!( line )
770
-
771
- ## NB: use extracted round title for knockout check
772
- @knockout_flag = is_knockout_round?( title )
773
-
774
-
775
- if group_pos.present?
776
- @group = Group.find_by_event_id_and_pos!( @event.id, group_pos )
777
- else
778
- @group = nil # reset group to no group
779
- end
780
-
781
- logger.debug " line: >#{line}<"
782
-
783
- ## NB: dummy/placeholder start_at, end_at date
784
- ## replace/patch after adding all games for round
785
-
786
- round_attribs = {
787
- title: title,
788
- title2: title2,
789
- knockout: @knockout_flag
790
- }
791
-
792
-
793
- @round = Round.find_by_event_id_and_pos( @event.id, pos )
794
- if @round.present?
795
- logger.debug "update round #{@round.id}:"
796
- else
797
- logger.debug "create round:"
798
- @round = Round.new
799
-
800
- round_attribs = round_attribs.merge( {
801
- event_id: @event.id,
802
- pos: pos,
803
- start_at: Time.utc('1912-12-12'),
804
- end_at: Time.utc('1912-12-12')
805
- })
806
- end
807
-
808
- logger.debug round_attribs.to_json
809
-
810
- @round.update_attributes!( round_attribs )
811
-
812
- ### store list of round is for patching start_at/end_at at the end
813
- @patch_rounds[ @round.id ] = @round.id
814
- end
815
-
816
- def parse_game( line )
817
- logger.debug "parsing game (fixture) line: >#{line}<"
818
-
819
- pos = find_game_pos!( line )
820
-
821
- match_teams!( line )
822
- team1_key = find_team1!( line )
823
- team2_key = find_team2!( line )
824
-
825
- if is_postponed?( line )
826
- postponed = true
827
- date_v2 = find_date!( line, start_at: @event.start_at )
828
- date = find_date!( line, start_at: @event.start_at )
829
- else
830
- postponed = false
831
- date_v2 = nil
832
- date = find_date!( line, start_at: @event.start_at )
833
- end
834
-
835
- scores = find_scores!( line )
836
-
837
-
838
- map_ground!( line )
839
- ground_key = find_ground!( line )
840
- ground = ground_key.nil? ? nil : Ground.find_by_key!( ground_key )
841
-
842
-
843
- logger.debug " line: >#{line}<"
844
-
845
-
846
- ### todo: cache team lookups in hash?
847
-
848
- team1 = Team.find_by_key!( team1_key )
849
- team2 = Team.find_by_key!( team2_key )
850
-
851
-
852
- ### check if games exists
853
- ## with this teams in this round if yes only update
854
- game = Game.find_by_round_id_and_team1_id_and_team2_id(
855
- @round.id, team1.id, team2.id
856
- )
857
-
858
- game_attribs = {
859
- score1: scores[0],
860
- score2: scores[1],
861
- score1et: scores[2],
862
- score2et: scores[3],
863
- score1p: scores[4],
864
- score2p: scores[5],
865
- play_at: date,
866
- play_at_v2: date_v2,
867
- postponed: postponed,
868
- knockout: @knockout_flag,
869
- ground_id: ground.present? ? ground.id : nil,
870
- group_id: @group.present? ? @group.id : nil
871
- }
872
-
873
- game_attribs[ :pos ] = pos if pos.present?
874
-
875
- ####
876
- # note: only update if any changes (or create if new record)
877
- if game.present? &&
878
- game.check_for_changes( game_attribs ) == false
879
- logger.debug " skip update game #{game.id}; no changes found"
880
- else
881
- if game.present?
882
- logger.debug "update game #{game.id}:"
883
- else
884
- logger.debug "create game:"
885
- game = Game.new
886
-
887
- more_game_attribs = {
888
- round_id: @round.id,
889
- team1_id: team1.id,
890
- team2_id: team2.id
891
- }
892
-
893
- ## NB: use round.games.count for pos
894
- ## lets us add games out of order if later needed
895
- more_game_attribs[ :pos ] = @round.games.count+1 if pos.nil?
896
-
897
- game_attribs = game_attribs.merge( more_game_attribs )
898
- end
899
-
900
- logger.debug game_attribs.to_json
901
- game.update_attributes!( game_attribs )
902
- end
903
-
904
- end # method parse_game
905
-
906
-
907
- def parse_fixtures( reader )
908
-
909
- reader.each_line do |line|
910
- if is_round?( line )
911
- parse_round( line )
912
- elsif is_group?( line ) ## NB: group goes after round (round may contain group marker too)
913
- parse_group( line )
914
- else
915
- parse_game( line )
916
- end
917
- end # lines.each
918
-
919
- @patch_rounds.each do |k,v|
920
- logger.debug "patch start_at/end_at date for round #{k}:"
921
- round = Round.find( k )
922
- games = round.games.order( 'play_at asc' ).all
923
-
924
- ## skip rounds w/ no games
925
-
926
- ## todo/fix: what's the best way for checking assoc w/ 0 recs?
927
- next if games.size == 0
928
-
929
- round_attribs = {}
930
-
931
- ## todo: check for no records
932
- ## e.g. if game[0].present? or just if game[0] ??
933
-
934
- round_attribs[:start_at] = games[0].play_at
935
- round_attribs[:end_at ] = games[-1].play_at
936
-
937
- logger.debug round_attribs.to_json
938
- round.update_attributes!( round_attribs )
939
- end
940
-
941
- end # method parse_fixtures
942
-
943
156
 
944
157
  end # class Reader
945
158
  end # module SportDb