sportdb 1.7.6 → 1.7.7

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.
@@ -41,6 +41,7 @@ lib/sportdb/models/run.rb
41
41
  lib/sportdb/models/season.rb
42
42
  lib/sportdb/models/team.rb
43
43
  lib/sportdb/models/track.rb
44
+ lib/sportdb/models/utils.rb
44
45
  lib/sportdb/reader.rb
45
46
  lib/sportdb/schema.rb
46
47
  lib/sportdb/service.rb
@@ -80,6 +81,11 @@ lib/sportdb/utils.rb
80
81
  lib/sportdb/version.rb
81
82
  tasks/test.rb
82
83
  test/helper.rb
84
+ test/test_changes.rb
85
+ test/test_cursor.rb
86
+ test/test_date.rb
83
87
  test/test_lang.rb
84
88
  test/test_round.rb
89
+ test/test_scores.rb
85
90
  test/test_utils.rb
91
+ test/test_winner.rb
@@ -53,6 +53,7 @@ require 'sportdb/models/run'
53
53
  require 'sportdb/models/season'
54
54
  require 'sportdb/models/team'
55
55
  require 'sportdb/models/track'
56
+ require 'sportdb/models/utils' # e.g. GameCursor
56
57
  require 'sportdb/schema' # NB: requires sportdb/models (include SportDB::Models)
57
58
  require 'sportdb/utils'
58
59
  require 'sportdb/reader'
@@ -79,7 +80,7 @@ require 'sportdb/data/models' # add convenience finders for known fixtures
79
80
  module SportDb
80
81
 
81
82
  def self.banner
82
- "sportdb #{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
83
+ "sportdb/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
83
84
  end
84
85
 
85
86
  def self.root
@@ -96,6 +97,9 @@ module SportDb
96
97
 
97
98
  def self.lang
98
99
  # todo/fix: find a better way for single instance ??
100
+ # will get us ruby warning: instance variable @lang not initialized => find a better way!!!
101
+ # just use @lang w/o .nil? e.g.
102
+ # @lang =|| Lang.new why? why not?? or better use @@lang =|| Lang.new for class variable!!!
99
103
  if @lang.nil?
100
104
  @lang = Lang.new
101
105
  end
@@ -14,6 +14,9 @@ require 'yaml'
14
14
 
15
15
  ## shortcuts for models
16
16
 
17
+ ##
18
+ ## todo/fix: just use include SportDb::Models - why? why not? is it possible/working?
19
+
17
20
  Badge = SportDb::Models::Badge
18
21
  Event = SportDb::Models::Event
19
22
  Game = SportDb::Models::Game
@@ -11,7 +11,78 @@ class Game < ActiveRecord::Base
11
11
 
12
12
  has_many :goals
13
13
 
14
- before_save :calc_toto12x
14
+ before_save :calc_winner
15
+
16
+
17
+ def toto12x() toto1x2; end # alias for toto12x - todo/fix: use ruby alias helper
18
+ def toto1x2
19
+ ## note: will return string e.g. 1-X-2 (winner will return int e.g. 1-0-2)
20
+
21
+ ## fix: use switch/when expr/stmt instead of ifs
22
+ value = winner90 # 1 0 2 1 => team 1 0 => draw 2 => team
23
+ if value == 0
24
+ 'X'
25
+ elsif value == 1
26
+ '1'
27
+ elsif value == 2
28
+ '2'
29
+ elsif value == -1
30
+ nil # ??? - unknown -- include --??? why? why not??
31
+ else
32
+ nil
33
+ end
34
+ end
35
+
36
+
37
+ def winner1?() winner == 1; end
38
+ def winner2?() winner == 2; end
39
+ def draw? () winner == 0; end # use different name; use an alias (any better names more speaking???)
40
+
41
+
42
+ def calc_winner
43
+ if score1.nil? || score2.nil?
44
+ self.winner90 = nil
45
+ self.winner = nil
46
+ else
47
+ if score1 > score2
48
+ self.winner90 = 1
49
+ elsif score1 < score2
50
+ self.winner90 = 2
51
+ else # assume score1 == score2 - draw
52
+ self.winner90 = 0
53
+ end
54
+
55
+ ## todo/fix:
56
+ # check for next-game/pre-game !!!
57
+ # use 1st leg and 2nd leg - use for winner too
58
+ # or add new winner_total or winner_aggregated method ???
59
+
60
+ ## check for penalty - note: some games might only have penalty and no extra time (e.g. copa liberatadores)
61
+ if score1p.present? && score2p.present?
62
+ if score1p > score2p
63
+ self.winner = 1
64
+ elsif score1p < score2p
65
+ self.winner = 2
66
+ else
67
+ # issue warning! - should not happen; penalty goes on until winner found!
68
+ puts "*** warn: should not happen; penalty goes on until winner found"
69
+ end
70
+ ## check for extra time
71
+ elsif score1et.present? && score2et.present?
72
+ if score1et > score2et
73
+ self.winner = 1
74
+ elsif score1et < score2et
75
+ self.winner = 2
76
+ else # assume score1et == score2et - draw
77
+ self.winner = 0
78
+ end
79
+ else
80
+ # assume no penalty and no extra time; same as 90min result
81
+ self.winner = self.winner90
82
+ end
83
+ end
84
+ end
85
+
15
86
 
16
87
  ### getter/setters for deprecated attribs (score3,4,5,6) n national
17
88
 
@@ -196,20 +267,6 @@ class Game < ActiveRecord::Base
196
267
  end
197
268
 
198
269
 
199
-
200
- def calc_toto12x
201
- if score1.nil? || score2.nil?
202
- self.toto12x = nil
203
- elsif score1 == score2
204
- self.toto12x = 'X'
205
- elsif score1 > score2
206
- self.toto12x = '1'
207
- elsif score1 < score2
208
- self.toto12x = '2'
209
- end
210
- end
211
-
212
-
213
270
  def over? # game over?
214
271
  play_at <= Time.now
215
272
  end
@@ -218,33 +275,56 @@ class Game < ActiveRecord::Base
218
275
  def knockout?
219
276
  knockout == true
220
277
  end
221
-
278
+
222
279
  def complete?
223
280
  score1.present? && score2.present?
224
281
  end
225
282
 
283
+
226
284
  ############# convenience helpers for styling
227
285
  ##
228
286
 
229
287
  def team1_style_class
230
288
  buf = ''
231
289
  ## NB: remove if calc?
232
- buf << 'game-team-winner ' if complete? && (score1 > score2)
233
- buf << 'game-team-draw ' if complete? && (score1 == score2)
290
+
291
+ ### fix: loser
292
+ ## - add method for checking winner/loser on ko pairs using (1st leg/2nd leg totals) ??
293
+ ## use new winner_total method ??
294
+
295
+ if complete?
296
+ if winner1?
297
+ buf << 'game-team-winner '
298
+ elsif winner2?
299
+ buf << 'game-team-loser '
300
+ else # assume draw
301
+ buf << 'game-team-draw '
302
+ end
303
+ end
304
+
234
305
  buf << 'game-knockout ' if knockout?
235
- ### fix: loser - add method for checking winner/loser on ko pairs using (1st leg/2nd leg totals)
236
- buf << 'game-team-loser ' if complete? && (score1 < score2)
237
306
  buf
238
307
  end
239
-
308
+
240
309
  def team2_style_class
241
310
  buf = ''
242
311
  ## NB: remove if calc?
243
- buf << 'game-team-winner ' if complete? && (score2 > score1)
244
- buf << 'game-team-draw ' if complete? && (score2 == score1)
312
+
313
+ ### fix: loser
314
+ ## - add method for checking winner/loser on ko pairs using (1st leg/2nd leg totals) ??
315
+ ## use new winner_total method ??
316
+
317
+ if complete?
318
+ if winner1?
319
+ buf << 'game-team-loser '
320
+ elsif winner2?
321
+ buf << 'game-team-winner '
322
+ else # assume draw
323
+ buf << 'game-team-draw '
324
+ end
325
+ end
326
+
245
327
  buf << 'game-knockout ' if knockout?
246
- ### fix: loser - add method for checking winner/loser on ko pairs using (1st leg/2nd leg totals)
247
- buf << 'game-team-loser ' if complete? && (score2 < score1)
248
328
  buf
249
329
  end
250
330
 
@@ -262,25 +342,51 @@ class Game < ActiveRecord::Base
262
342
 
263
343
 
264
344
  def score_str
265
- return ' - ' if score1.blank? && score2.blank?
266
-
267
- if score1p.present? && score2p.present? # im Elfmeterschiessen i.E.?
268
- "#{score1_str} : #{score2_str} / #{score1et} : #{score2et} n.V. / #{score1p} : #{score2p} i.E."
269
- elsif score1et.present? && score2et.present? # nach Verlaengerung n.V.?
270
- "#{score1_str} : #{score2_str} / #{score1et} : #{score2et} n.V."
271
- else
272
- "#{score1_str} : #{score2_str}"
273
- end
274
- end
345
+ ## return ' - ' if score1.nil? && score2.nil?
275
346
 
276
- def score1_str
277
- if score1.blank? then '-' else score1.to_s end
278
- end
347
+ # note: make after extra time optional;
348
+ # e.g. copa liberatadores only has regular time plus penalty, for example
349
+
350
+ buf = ""
279
351
 
280
- def score2_str
281
- if score2.blank? then '-' else score2.to_s end
352
+ buf << "#{score1_str} : #{score2_str}"
353
+ buf << " / #{score1et_str} : #{score2et_str} n.V." if score1et.present? || score2et.present?
354
+ buf << " / #{score1p_str} : #{score2p_str} i.E." if score1p.present? || score2p.present?
355
+
356
+ buf
282
357
  end
283
358
 
359
+ def score1_str() score1.nil? ? '-' : score1.to_s; end
360
+ def score2_str() score2.nil? ? '-' : score2.to_s; end
361
+
362
+ def score1et_str() score1et.nil? ? '-' : score1et.to_s; end
363
+ def score2et_str() score2et.nil? ? '-' : score2et.to_s; end
364
+
365
+ def score1p_str() score1p.nil? ? '-' : score1p.to_s; end
366
+ def score2p_str() score2p.nil? ? '-' : score2p.to_s; end
367
+
368
+
369
+
370
+ ## todo/fix: find a better name?
371
+ ## todo: move to utils for reuse?
372
+
373
+ def check_for_changes( new_attributes )
374
+ changes_counter = 0
375
+ new_attributes.each do |key,new_value|
376
+ old_value = attributes[ key.to_s ]
377
+ ## todo/fix: also check for class/type matching ????
378
+ if new_value == old_value
379
+ # do nothing
380
+ else
381
+ changes_counter +=1
382
+ puts "change #{changes_counter} for #{key} old:>#{old_value}< : #{old_value.class.name} new:>#{new_value}< : #{new_value.class.name}"
383
+ end
384
+ end
385
+
386
+ # no changes found for counter==0;
387
+ # -- otherwise x changes found; return true
388
+ changes_counter == 0 ? false : true
389
+ end
284
390
 
285
391
  end # class Game
286
392
 
@@ -16,11 +16,20 @@ class Team < ActiveRecord::Base
16
16
  has_many :event_teams, :class_name => 'EventTeam' # join table (events+teams)
17
17
  has_many :events, :through => :event_teams
18
18
 
19
- ### fix - how to do it with has_many macro? use finder_sql?
19
+ ### fix!!! - how to do it with has_many macro? use finder_sql?
20
20
  def games
21
- Game.where( 'team1_id = ? or team2_id = ?', id, id ).order( 'play_at' ).all
21
+ Game.where( 'team1_id = ? or team2_id = ?', id, id ).order( 'play_at' )
22
22
  end
23
-
23
+
24
+ def upcoming_games
25
+ Game.where( 'team1_id = ? or team2_id = ?', id, id ).where( 'play_at > ?', Time.now ).order( 'play_at' )
26
+ end
27
+
28
+ def past_games
29
+ Game.where( 'team1_id = ? or team2_id = ?', id, id ).where( 'play_at < ?', Time.now ).order( 'play_at desc' )
30
+ end
31
+
32
+
24
33
  has_many :badges # Winner, 2nd, Cupsieger, Aufsteiger, Absteiger, etc.
25
34
 
26
35
  belongs_to :country, :class_name => 'WorldDb::Models::Country', :foreign_key => 'country_id'
@@ -0,0 +1,78 @@
1
+ module SportDb
2
+ module Models
3
+
4
+
5
+ class GameCursor
6
+
7
+ def initialize( games )
8
+ @games = games
9
+ end
10
+
11
+ def each
12
+ state = GameCursorState.new
13
+
14
+ @games.each do |game|
15
+ state.next( game )
16
+ yield( game, state ) # e.g. lets you use state.new_date? or state.new_week? or state.new_year? etc.
17
+ end
18
+ end # method each
19
+ end # class GameCursor
20
+
21
+
22
+ class GameCursorState
23
+
24
+ def initialize
25
+ @last_play_at = DateTime.new( 1971, 1, 1 )
26
+ @new_date = true
27
+ @new_year = true
28
+ @new_week = true
29
+ @index = -1 # zero-based index; thus start off with -1 (e.g. -1+=1 => 0)
30
+ end
31
+
32
+ attr_reader :index
33
+
34
+ def new_date?() @new_date; end
35
+ def new_year?() @new_year; end
36
+ def new_week?() @new_week; end
37
+
38
+
39
+ ## add new league ?
40
+ ## add new round ?
41
+ ## add new time ?
42
+
43
+ def next( game )
44
+ @index += 1 # zero-based index; start off with -1 (undefined/uninitialized)
45
+ game_play_at = game.play_at # cache play_at value ref
46
+
47
+ if @last_play_at.year == game_play_at.year &&
48
+ @last_play_at.month == game_play_at.month &&
49
+ @last_play_at.day == game_play_at.day
50
+ @new_date = false
51
+ else
52
+ @new_date = true
53
+
54
+ # check for new_year
55
+ if @last_play_at.year == game_play_at.year
56
+ @new_year = false
57
+ else
58
+ @new_year = true
59
+ end
60
+
61
+ # check for new_week
62
+ # -- todo: find a method for week number; do NOT use strftime; there must be something easier
63
+ # -- check if activesupport adds .week or similar ??? use it if it exists
64
+ if @last_play_at.strftime('%V') == game_play_at.strftime('%V')
65
+ @new_week = false
66
+ else
67
+ @new_week = true
68
+ end
69
+ end
70
+
71
+ @last_play_at = game.play_at
72
+ end # method next
73
+
74
+ end # class GameCursorState
75
+
76
+
77
+ end # module Models
78
+ end # module SportDb
@@ -816,31 +816,38 @@ private
816
816
  group_id: @group.present? ? @group.id : nil
817
817
  }
818
818
 
819
- game_attribs[ :pos ] = pos if pos.present?
819
+ game_attribs[ :pos ] = pos if pos.present?
820
820
 
821
- if game.present?
822
- logger.debug "update game #{game.id}:"
821
+ ####
822
+ # note: only update if any changes (or create if new record)
823
+ if game.present? &&
824
+ game.check_for_changes( game_attribs ) == false
825
+ logger.debug " skip update game #{game.id}; no changes found"
823
826
  else
824
- logger.debug "create game:"
825
- game = Game.new
826
-
827
- more_game_attribs = {
828
- round_id: @round.id,
829
- team1_id: team1.id,
830
- team2_id: team2.id
831
- }
827
+ if game.present?
828
+ logger.debug "update game #{game.id}:"
829
+ else
830
+ logger.debug "create game:"
831
+ game = Game.new
832
+
833
+ more_game_attribs = {
834
+ round_id: @round.id,
835
+ team1_id: team1.id,
836
+ team2_id: team2.id
837
+ }
832
838
 
833
- ## NB: use round.games.count for pos
834
- ## lets us add games out of order if later needed
835
- more_game_attribs[ :pos ] = @round.games.count+1 if pos.nil?
839
+ ## NB: use round.games.count for pos
840
+ ## lets us add games out of order if later needed
841
+ more_game_attribs[ :pos ] = @round.games.count+1 if pos.nil?
836
842
 
837
- game_attribs = game_attribs.merge( more_game_attribs )
838
- end
843
+ game_attribs = game_attribs.merge( more_game_attribs )
844
+ end
839
845
 
840
- logger.debug game_attribs.to_json
846
+ logger.debug game_attribs.to_json
847
+ game.update_attributes!( game_attribs )
848
+ end
841
849
 
842
- game.update_attributes!( game_attribs )
843
- end
850
+ end # method parse_game
844
851
 
845
852
 
846
853
  def parse_fixtures( reader )
@@ -194,12 +194,9 @@ create_table :games do |t|
194
194
  t.integer :score2ii # second third - team2 (opt)
195
195
  t.references :next_game # for hinspiel bei rueckspiel in knockout game
196
196
  t.references :prev_game
197
-
198
-
199
-
200
- ### todo> find a better name (toto is not international/english?)
201
- ## rename to score12x or pt12x or result12x
202
- t.string :toto12x # 1,2,X,nil calculate on save
197
+
198
+ t.integer :winner # 1,2,0,nil calculate on save - "real" winner (after 90 or extra time or penalty, aggregated first+second leg?)
199
+ t.integer :winner90 # 1,2,0,nil calculate on save - winner after 90 mins (or regugular play time depending on sport - add alias or find a better name!)
203
200
 
204
201
  t.timestamps
205
202
  end
@@ -387,8 +387,13 @@ module SportDb::FixtureHelpers
387
387
  find_leading_pos!( line )
388
388
  end
389
389
 
390
+
390
391
  def find_scores!( line )
391
392
 
393
+ # note: always call after find_dates !!!
394
+ # scores match date-like patterns!! e.g. 10-11 or 10:00 etc.
395
+ # -- note: score might have two digits too
396
+
392
397
  ### fix: depending on language allow 1:1 or 1-1
393
398
  ## do NOT allow mix and match
394
399
  ## e.g. default to en is 1-1
@@ -399,17 +404,31 @@ module SportDb::FixtureHelpers
399
404
  # and return it
400
405
  # NB: side effect - removes date from line string
401
406
 
407
+ # note: regex should NOT match regex extra time or penalty
408
+ # thus, we do NOT any longer allow spaces for now between
409
+ # score and marker (e.g. nV,iE, etc.)
410
+
402
411
  # e.g. 1:2 or 0:2 or 3:3 // 1-1 or 0-2 or 3-3
403
- regex = /\b(\d)[:\-](\d)\b/
404
-
405
- # e.g. 1:2nV => overtime
406
- regex_ot = /\b(\d)[:\-](\d)[ \t]?[nN][vV]\b/
407
-
408
- # e.g. 5:4iE => penalty
409
- regex_p = /\b(\d)[:\-](\d)[ \t]?[iI][eE]\b/
410
-
412
+ regex = /\b(\d{1,2})[:\-](\d{1,2})\b/
413
+
414
+ ## todo: add/allow english markers e.g. aet ??
415
+
416
+ ## fix: use case insansitive flag instead e.g. /i
417
+ # instead of [nN] etc.
418
+
419
+ # e.g. 1:2nV => after extra time a.e.t
420
+ regex_et = /\b(\d{1,2})[:\-](\d{1,2})[nN][vV]\b/
421
+
422
+ # e.g. 5:4iE => penalty / after penalty a.p
423
+ regex_p = /\b(\d{1,2})[:\-](\d{1,2})[iI][eE]\b/
424
+
411
425
  scores = []
412
-
426
+
427
+ ## todo: how to handle game w/o extra time
428
+ # but w/ optional penalty ??? e.g. used in copa liberatores, for example
429
+ # retrun 0,0 or nil,nil for extra time score ?? or -1, -1 ??
430
+ # for now use nil,nil
431
+
413
432
  if line =~ regex
414
433
  logger.debug " score: >#{$1}-#{$2}<"
415
434
 
@@ -417,24 +436,35 @@ module SportDb::FixtureHelpers
417
436
 
418
437
  scores << $1.to_i
419
438
  scores << $2.to_i
420
-
421
- if line =~ regex_ot
422
- logger.debug " score.ot: >#{$1}-#{$2}<"
423
-
424
- line.sub!( regex_ot, '[SCORE.OT]' )
439
+ end
440
+
441
+ ## todo:
442
+ ## reverse matching order ??? allows us to support spaces for nV and iE
443
+ ## why? why not??
425
444
 
426
- scores << $1.to_i
427
- scores << $2.to_i
445
+ if line =~ regex_et
446
+ logger.debug " score.et: >#{$1}-#{$2}<"
428
447
 
429
- if line =~ regex_p
430
- logger.debug " score.p: >#{$1}-#{$2}<"
448
+ line.sub!( regex_et, '[SCORE.ET]' )
449
+
450
+ ## check scores empty? - fill with nil,nil
451
+ scores += [nil,nil] if scores.size == 0
452
+
453
+ scores << $1.to_i
454
+ scores << $2.to_i
455
+ end
456
+
457
+ if line =~ regex_p
458
+ logger.debug " score.p: >#{$1}-#{$2}<"
431
459
 
432
- line.sub!( regex_p, '[SCORE.P]' )
460
+ line.sub!( regex_p, '[SCORE.P]' )
433
461
 
434
- scores << $1.to_i
435
- scores << $2.to_i
436
- end
437
- end
462
+ ## check scores empty? - fill with nil,nil
463
+ scores += [nil,nil] if scores.size == 0
464
+ scores += [nil,nil] if scores.size == 2
465
+
466
+ scores << $1.to_i
467
+ scores << $2.to_i
438
468
  end
439
469
  scores
440
470
  end # methdod find_scores!
@@ -1,6 +1,6 @@
1
1
 
2
2
  module SportDb
3
- VERSION = '1.7.6'
3
+ VERSION = '1.7.7'
4
4
  end
5
5
 
6
6
 
@@ -9,8 +9,45 @@ require 'minitest/autorun'
9
9
  # include MiniTest::Unit # lets us use TestCase instead of MiniTest::Unit::TestCase
10
10
 
11
11
 
12
- ## our own code
12
+ require 'pp'
13
+
14
+
15
+ # ruby gems
13
16
 
17
+ require 'active_record'
18
+
19
+ require 'worlddb'
14
20
  require 'logutils'
21
+ require 'logutils/db' # NB: explict require required for LogDb (not automatic)
22
+
23
+ ## our own code
24
+
15
25
  require 'sportdb'
16
26
 
27
+
28
+ def setup_in_memory_db
29
+ # Database Setup & Config
30
+
31
+ db_config = {
32
+ adapter: 'sqlite3',
33
+ database: ':memory:'
34
+ }
35
+
36
+ pp db_config
37
+
38
+ ActiveRecord::Base.logger = Logger.new( STDOUT )
39
+ ## ActiveRecord::Base.colorize_logging = false - no longer exists - check new api/config setting?
40
+
41
+ ## NB: every connect will create a new empty in memory db
42
+ ActiveRecord::Base.establish_connection( db_config )
43
+
44
+
45
+ ## build schema
46
+
47
+ LogDb.create
48
+ WorldDb.create
49
+ SportDb.create
50
+ end
51
+
52
+
53
+ setup_in_memory_db()
@@ -0,0 +1,74 @@
1
+ # encoding: utf-8
2
+
3
+ require 'helper'
4
+
5
+ class TestChanges < MiniTest::Unit::TestCase
6
+
7
+ def test_scores
8
+ game1 = SportDb::Models::Game.new
9
+ game1.score1 = 1
10
+ game1.score2 = 2
11
+
12
+ game2 = SportDb::Models::Game.new
13
+ game2.score1 = 1
14
+ game2.score2 = 1
15
+ game2.score1p = 5
16
+ game2.score2p = 3
17
+
18
+ game_attribs = {
19
+ score1: 1,
20
+ score2: 2,
21
+ score1et: nil,
22
+ score2et: nil,
23
+ score1p: nil,
24
+ score2p: nil
25
+ }
26
+
27
+ assert_equal false, game1.check_for_changes( game_attribs )
28
+ assert_equal true, game2.check_for_changes( game_attribs )
29
+ end
30
+
31
+ def test_play_at
32
+ game1 = SportDb::Models::Game.new
33
+ game1.score1 = 1
34
+ game1.score2 = 2
35
+ game1.play_at = DateTime.new( 2012, 11, 5 )
36
+
37
+ game2 = SportDb::Models::Game.new
38
+ game2.score1 = 1
39
+ game2.score2 = 2
40
+ game2.play_at = DateTime.new( 2012, 12, 24 )
41
+
42
+ game_attribs = {
43
+ score1: 1,
44
+ score2: 2,
45
+ play_at: DateTime.new( 2012, 11, 5 )
46
+ }
47
+
48
+ assert_equal false, game1.check_for_changes( game_attribs )
49
+ assert_equal true, game2.check_for_changes( game_attribs )
50
+ end
51
+
52
+ def test_group_id
53
+ game1 = SportDb::Models::Game.new
54
+ game1.score1 = 1
55
+ game1.score2 = 2
56
+ game1.group_id = 1
57
+
58
+ game2 = SportDb::Models::Game.new
59
+ game2.score1 = 1
60
+ game2.score2 = 2
61
+ game2.group_id = 2
62
+
63
+ game_attribs = {
64
+ score1: 1,
65
+ score2: 2,
66
+ group_id: 1
67
+ }
68
+
69
+ assert_equal false, game1.check_for_changes( game_attribs )
70
+ assert_equal true, game2.check_for_changes( game_attribs )
71
+ end
72
+
73
+
74
+ end # class TestChanges
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ require 'helper'
4
+
5
+ class TestCursor < MiniTest::Unit::TestCase
6
+
7
+ def test_games
8
+ games = []
9
+
10
+ games << SportDb::Models::Game.new( score1: 3, score2: 1, play_at: DateTime.new(2013, 8, 9) )
11
+ games << SportDb::Models::Game.new( score1: 1, score2: 3, play_at: DateTime.new(2013, 8, 10) )
12
+ games << SportDb::Models::Game.new( score1: 2, score2: 0, play_at: DateTime.new(2013, 8, 10) )
13
+ games << SportDb::Models::Game.new( score1: 3, score2: 2, play_at: DateTime.new(2013, 8, 12) ) # new_week
14
+
15
+ SportDb::Models::GameCursor.new( games ).each do |game,state|
16
+ if state.index == 0
17
+ assert_equal 3, game.score1
18
+ assert_equal 1, game.score2
19
+ assert_equal true, state.new_date?
20
+ assert_equal true, state.new_year?
21
+ assert_equal true, state.new_week?
22
+ end
23
+
24
+ if state.index == 1
25
+ assert_equal 1, game.score1
26
+ assert_equal 3, game.score2
27
+ assert_equal true, state.new_date?
28
+ assert_equal false, state.new_year?
29
+ assert_equal false, state.new_week?
30
+ end
31
+
32
+ if state.index == 2
33
+ assert_equal 2, game.score1
34
+ assert_equal 0, game.score2
35
+ assert_equal false, state.new_date?
36
+ assert_equal false, state.new_year?
37
+ assert_equal false, state.new_week?
38
+ end
39
+
40
+ if state.index == 3
41
+ assert_equal 3, game.score1
42
+ assert_equal 2, game.score2
43
+ assert_equal true, state.new_date?
44
+ assert_equal true, state.new_week?
45
+ assert_equal false, state.new_year?
46
+ end
47
+ end
48
+ end
49
+
50
+ end # class TestCursor
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+
3
+ require 'helper'
4
+
5
+ class TestDate < MiniTest::Unit::TestCase
6
+
7
+ def test_date
8
+ assert_datetime DateTime.new( 2013, 1, 19, 22 ), parse_date( '19.01.2013 22.00' )
9
+ assert_datetime DateTime.new( 2013, 1, 21, 21, 30 ), parse_date( '21.01.2013 21.30' )
10
+
11
+ assert_date DateTime.new( 2013, 1, 26 ), parse_date( '26.01.2013' )
12
+ end
13
+
14
+ private
15
+
16
+ ## todo: check if assert_datetime or assert_date exist already? what is the best practice to check dates ???
17
+ def assert_date( exp, act )
18
+ assert_equal exp.year, act.year
19
+ assert_equal exp.month, act.month
20
+ assert_equal exp.day, act.day
21
+ end
22
+
23
+ def assert_time( exp, act )
24
+ assert_equal exp.hour, act.hour
25
+ assert_equal exp.min, act.min
26
+ end
27
+
28
+ def assert_datetime( exp, act )
29
+ assert_date( exp, act )
30
+ assert_time( exp, act )
31
+ end
32
+
33
+ class Reader
34
+ include LogUtils::Logging # add logger
35
+ include SportDb::FixtureHelpers
36
+ end
37
+
38
+ def parse_date( line, opts={} )
39
+ # e.g. lets you pass in opts[:start_at] ???
40
+ reader = Reader.new
41
+ reader.find_date!( line, opts )
42
+ end
43
+
44
+ end # class TestScores
@@ -18,28 +18,29 @@ class TestRound < MiniTest::Unit::TestCase
18
18
 
19
19
  pos, title, title2, group_pos, group_title, ko = parse_round( line )
20
20
 
21
- assert( pos == 2 )
22
- assert( title == "2. Round" )
23
- assert( title2 == nil )
24
- assert( ko == false )
21
+ assert_equal 2, pos
22
+ assert_equal '2. Round', title
23
+ assert_equal nil, title2
24
+ assert_equal false, ko
25
25
 
26
26
  line = "(1) Matchday P.1 / 1st Leg // January 22-24"
27
27
 
28
28
  pos, title, title2, group_pos, group_title, ko = parse_round( line )
29
29
 
30
- assert( pos == 1 )
31
- assert( title == "Matchday P.1 / 1st Leg" )
32
- assert( title2 == "January 22-24" )
33
- assert( ko == false )
30
+ assert_equal 1, pos
31
+ assert_equal 'Matchday P.1 / 1st Leg', title
32
+ assert_equal 'January 22-24', title2
33
+ assert_equal false, ko
34
34
 
35
35
  line = "(4) Matchday 2 / Group 1 // February 19-21"
36
36
 
37
37
  pos, title, title2, group_pos, group_title, ko = parse_round( line )
38
38
 
39
- assert( pos == 4 )
40
- assert( title == "Matchday 2" )
41
- assert( title2 == "February 19-21" )
42
- assert( ko == false )
39
+ assert_equal 4, pos
40
+ assert_equal 'Matchday 2', title
41
+ assert_equal 'February 19-21', title2
42
+ assert_equal false, ko
43
+
43
44
 
44
45
  line = "(13) Round of 16 / 1st Leg // April 25, May 1-3"
45
46
 
@@ -101,7 +102,7 @@ class TestRound < MiniTest::Unit::TestCase
101
102
 
102
103
  pos, title, title2, group_pos, group_title, ko = parse_round( line )
103
104
 
104
- assert( pos = 2 )
105
+ assert( pos == 2 )
105
106
  assert( title == 'Jornada 2' )
106
107
  assert( title2 == '27, 28 y 29 de julio' )
107
108
  assert( ko == false )
@@ -110,7 +111,7 @@ class TestRound < MiniTest::Unit::TestCase
110
111
 
111
112
  pos, title, title2, group_pos, group_title, ko = parse_round( line )
112
113
 
113
- assert( pos = 18 )
114
+ assert( pos == 18 )
114
115
  assert( title == 'Cuartos de Final / Ida' )
115
116
  assert( title2 == '14/15 de noviembre' )
116
117
  assert( ko == false )
@@ -119,7 +120,7 @@ class TestRound < MiniTest::Unit::TestCase
119
120
 
120
121
  pos, title, title2, group_pos, group_title, ko = parse_round( line )
121
122
 
122
- assert( pos = 19 )
123
+ assert( pos == 19 )
123
124
  assert( title == 'Cuartos de Final / Vuelta' )
124
125
  assert( title2 == '17/18 de noviembre' )
125
126
  assert( ko == true )
@@ -133,7 +134,7 @@ class TestRound < MiniTest::Unit::TestCase
133
134
 
134
135
  pos, title, title2, group_pos, group_title, ko = parse_round( line )
135
136
 
136
- assert( pos = 5 )
137
+ assert( pos == 5 )
137
138
  assert( title == 'Spieltag 5' )
138
139
  assert( title2 == 'Di./Mi., 20.+21. Nov 2012' )
139
140
  assert( ko == false )
@@ -142,7 +143,7 @@ class TestRound < MiniTest::Unit::TestCase
142
143
 
143
144
  pos, title, title2, group_pos, group_title, ko = parse_round( line )
144
145
 
145
- assert( pos = 8 )
146
+ assert( pos == 8 )
146
147
  assert( title == 'Achtelfinale Rückspiele' )
147
148
  assert( title2 == 'Di./Mi., 5.+6./12.+13. Mär 2013' )
148
149
  assert( ko == true )
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ require 'helper'
4
+
5
+ class TestScores < MiniTest::Unit::TestCase
6
+
7
+
8
+ def test_scores
9
+ assert_equal [10,0], parse_scores( '10:0' )
10
+ assert_equal [1,22], parse_scores( '1:22' )
11
+ assert_equal [1,22], parse_scores( '1-22' )
12
+
13
+ assert_equal [], parse_scores( '1-222' ) # do not support three digits
14
+ assert_equal [], parse_scores( '111-0' ) # do not support three digits
15
+ assert_equal [], parse_scores( '1:222' ) # do not support three digits
16
+ assert_equal [], parse_scores( '111:0' ) # do not support three digits
17
+
18
+ ## penality only
19
+ assert_equal [nil,nil,nil,nil,3,4], parse_scores( '3-4iE' )
20
+ assert_equal [nil,nil,nil,nil,3,4], parse_scores( '3:4iE' )
21
+
22
+ ## extra time only - allow ?? why not ?? only allow penalty w/ missing extra time?
23
+ ## todo/fix: issue warning or error in parser!!!
24
+ assert_equal [nil,nil,3,4], parse_scores( '3-4nV' )
25
+ assert_equal [nil,nil,3,4], parse_scores( '3:4nV' )
26
+
27
+ assert_equal [1,1,3,4], parse_scores( '3:4nV 1:1' )
28
+ assert_equal [1,1,3,4], parse_scores( '1:1 3:4nV' )
29
+
30
+ assert_equal [1,1,nil,nil,3,4], parse_scores( '3:4iE 1:1' )
31
+ assert_equal [1,1,nil,nil,3,4], parse_scores( '1:1 3:4iE' )
32
+ end
33
+
34
+ private
35
+ class Reader
36
+ include LogUtils::Logging # add logger
37
+ include SportDb::FixtureHelpers
38
+ end
39
+
40
+ def parse_scores( line )
41
+ reader = Reader.new
42
+ reader.find_scores!( line )
43
+ end
44
+
45
+ end # class TestScores
@@ -0,0 +1,95 @@
1
+ # encoding: utf-8
2
+
3
+ require 'helper'
4
+
5
+ class TestWinner < MiniTest::Unit::TestCase
6
+
7
+ def test_1_2
8
+ game = SportDb::Models::Game.new
9
+ game.score1 = 1
10
+ game.score2 = 2
11
+ game.calc_winner
12
+
13
+ assert_equal 2, game.winner90
14
+ assert_equal 2, game.winner
15
+ assert_equal true, game.winner2?
16
+ assert_equal false, game.winner1?
17
+ assert_equal false, game.draw?
18
+ end
19
+
20
+ def test_1_1
21
+ game = SportDb::Models::Game.new
22
+ game.score1 = 1
23
+ game.score2 = 1
24
+ game.calc_winner
25
+
26
+ assert_equal 0, game.winner90
27
+ assert_equal 0, game.winner
28
+ assert_equal true, game.draw?
29
+ assert_equal false, game.winner1?
30
+ assert_equal false, game.winner2?
31
+ end
32
+
33
+ def test_2_1
34
+ game = SportDb::Models::Game.new
35
+ game.score1 = 2
36
+ game.score2 = 1
37
+ game.calc_winner
38
+
39
+ assert_equal 1, game.winner90
40
+ assert_equal 1, game.winner
41
+ assert_equal true, game.winner1?
42
+ assert_equal false, game.winner2?
43
+ assert_equal false, game.draw?
44
+ end
45
+
46
+ def test_1_1__2_1
47
+ game = SportDb::Models::Game.new
48
+ game.score1 = 1
49
+ game.score2 = 1
50
+ game.score1et = 2
51
+ game.score2et = 1
52
+ game.calc_winner
53
+
54
+ assert_equal 0, game.winner90
55
+ assert_equal 1, game.winner
56
+ assert_equal true, game.winner1?
57
+ assert_equal false, game.winner2?
58
+ assert_equal false, game.draw?
59
+ end
60
+
61
+ def test_1_1__2_2__3_5
62
+ game = SportDb::Models::Game.new
63
+ game.score1 = 1
64
+ game.score2 = 1
65
+ game.score1et = 2
66
+ game.score2et = 2
67
+ game.score1p = 3
68
+ game.score2p = 5
69
+ game.calc_winner
70
+
71
+ assert_equal 0, game.winner90
72
+ assert_equal 2, game.winner
73
+ assert_equal true, game.winner2?
74
+ assert_equal false, game.winner1?
75
+ assert_equal false, game.draw?
76
+ end
77
+
78
+ def test_1_1_x_3_5
79
+ game = SportDb::Models::Game.new
80
+ game.score1 = 1
81
+ game.score2 = 1
82
+ game.score1et = nil
83
+ game.score2et = nil
84
+ game.score1p = 3
85
+ game.score2p = 5
86
+ game.calc_winner
87
+
88
+ assert_equal 0, game.winner90
89
+ assert_equal 2, game.winner
90
+ assert_equal true, game.winner2?
91
+ assert_equal false, game.winner1?
92
+ assert_equal false, game.draw?
93
+ end
94
+
95
+ end # class TestWinner
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sportdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.6
4
+ version: 1.7.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-10-20 00:00:00.000000000 Z
12
+ date: 2013-10-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: worlddb
16
- requirement: &81394750 !ruby/object:Gem::Requirement
16
+ requirement: &70825440 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '1.7'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *81394750
24
+ version_requirements: *70825440
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: fetcher
27
- requirement: &81394520 !ruby/object:Gem::Requirement
27
+ requirement: &70825170 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0.3'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *81394520
35
+ version_requirements: *70825170
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: gli
38
- requirement: &81394270 !ruby/object:Gem::Requirement
38
+ requirement: &70824860 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 2.5.6
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *81394270
46
+ version_requirements: *70824860
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rdoc
49
- requirement: &81394020 !ruby/object:Gem::Requirement
49
+ requirement: &70824550 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '3.10'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *81394020
57
+ version_requirements: *70824550
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: hoe
60
- requirement: &81393780 !ruby/object:Gem::Requirement
60
+ requirement: &70824310 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '3.3'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *81393780
68
+ version_requirements: *70824310
69
69
  description: sportdb - sport.db command line tool
70
70
  email: opensport@googlegroups.com
71
71
  executables:
@@ -117,6 +117,7 @@ files:
117
117
  - lib/sportdb/models/season.rb
118
118
  - lib/sportdb/models/team.rb
119
119
  - lib/sportdb/models/track.rb
120
+ - lib/sportdb/models/utils.rb
120
121
  - lib/sportdb/reader.rb
121
122
  - lib/sportdb/schema.rb
122
123
  - lib/sportdb/service.rb
@@ -156,9 +157,14 @@ files:
156
157
  - lib/sportdb/version.rb
157
158
  - tasks/test.rb
158
159
  - test/helper.rb
160
+ - test/test_changes.rb
161
+ - test/test_cursor.rb
162
+ - test/test_date.rb
159
163
  - test/test_lang.rb
160
164
  - test/test_round.rb
165
+ - test/test_scores.rb
161
166
  - test/test_utils.rb
167
+ - test/test_winner.rb
162
168
  - .gemtest
163
169
  homepage: https://github.com/geraldb/sport.db.ruby
164
170
  licenses:
@@ -198,6 +204,11 @@ signing_key:
198
204
  specification_version: 3
199
205
  summary: sportdb - sport.db command line tool
200
206
  test_files:
207
+ - test/test_date.rb
201
208
  - test/test_lang.rb
209
+ - test/test_cursor.rb
202
210
  - test/test_round.rb
211
+ - test/test_scores.rb
212
+ - test/test_winner.rb
203
213
  - test/test_utils.rb
214
+ - test/test_changes.rb