sportdb-models 1.19.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Manifest.txt +27 -38
  3. data/Rakefile +1 -1
  4. data/lib/sportdb/models.rb +55 -49
  5. data/lib/sportdb/{deleter.rb → models/deleter.rb} +3 -9
  6. data/lib/sportdb/models/formats.rb +23 -0
  7. data/lib/sportdb/models/models/assoc.rb +38 -0
  8. data/lib/sportdb/models/{badge.rb → models/badge.rb} +1 -1
  9. data/lib/sportdb/models/models/event.rb +55 -0
  10. data/lib/sportdb/models/{forward.rb → models/forward.rb} +3 -3
  11. data/lib/sportdb/models/{goal.rb → models/goal.rb} +1 -1
  12. data/lib/sportdb/models/models/ground.rb +16 -0
  13. data/lib/sportdb/models/{group.rb → models/group.rb} +10 -7
  14. data/lib/sportdb/models/models/league.rb +20 -0
  15. data/lib/sportdb/models/{roster.rb → models/lineup.rb} +3 -4
  16. data/lib/sportdb/models/{game.rb → models/match.rb} +16 -60
  17. data/lib/sportdb/models/{person.rb → models/person.rb} +0 -0
  18. data/lib/sportdb/models/{round.rb → models/round.rb} +1 -6
  19. data/lib/sportdb/models/{season.rb → models/season.rb} +0 -0
  20. data/lib/sportdb/models/{stage.rb → models/stage.rb} +9 -5
  21. data/lib/sportdb/models/{stats/alltime_standing_entry.rb → models/stats/alltime_standing.rb} +9 -1
  22. data/lib/sportdb/models/{stats/event_standing_entry.rb → models/stats/event_standing.rb} +11 -1
  23. data/lib/sportdb/models/{stats/group_standing_entry.rb → models/stats/group_standing.rb} +10 -1
  24. data/lib/sportdb/models/models/team.rb +56 -0
  25. data/lib/sportdb/models/{world → models/world}/city.rb +2 -2
  26. data/lib/sportdb/models/{world → models/world}/continent.rb +0 -0
  27. data/lib/sportdb/models/{world → models/world}/country.rb +0 -0
  28. data/lib/sportdb/models/{world → models/world}/state.rb +0 -0
  29. data/lib/sportdb/{schema.rb → models/schema.rb} +98 -74
  30. data/lib/sportdb/{stats.rb → models/stats.rb} +4 -4
  31. data/lib/sportdb/models/utils.rb +24 -24
  32. data/lib/sportdb/{version.rb → models/version.rb} +4 -4
  33. data/test/helper.rb +10 -6
  34. data/test/test_changes.rb +38 -38
  35. data/test/test_cursor.rb +15 -15
  36. data/test/test_winner.rb +75 -70
  37. metadata +29 -40
  38. data/lib/sportdb/calc.rb +0 -279
  39. data/lib/sportdb/models/assoc.rb +0 -106
  40. data/lib/sportdb/models/assoc_assoc.rb +0 -15
  41. data/lib/sportdb/models/event.rb +0 -66
  42. data/lib/sportdb/models/event_ground.rb +0 -15
  43. data/lib/sportdb/models/event_team.rb +0 -16
  44. data/lib/sportdb/models/ground.rb +0 -100
  45. data/lib/sportdb/models/group_team.rb +0 -14
  46. data/lib/sportdb/models/league.rb +0 -83
  47. data/lib/sportdb/models/stage_team.rb +0 -14
  48. data/lib/sportdb/models/stats/alltime_standing.rb +0 -44
  49. data/lib/sportdb/models/stats/event_standing.rb +0 -55
  50. data/lib/sportdb/models/stats/group_standing.rb +0 -50
  51. data/lib/sportdb/models/team.rb +0 -119
  52. data/lib/sportdb/models/team_compat.rb +0 -64
  53. data/lib/sportdb/patterns.rb +0 -37
  54. data/lib/sportdb/standings.rb +0 -178
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sportdb-models
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.19.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-23 00:00:00.000000000 Z
11
+ date: 2020-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: worlddb-models
@@ -79,46 +79,35 @@ files:
79
79
  - Manifest.txt
80
80
  - README.md
81
81
  - Rakefile
82
- - lib/sportdb/calc.rb
83
- - lib/sportdb/deleter.rb
84
82
  - lib/sportdb/models.rb
85
- - lib/sportdb/models/assoc.rb
86
- - lib/sportdb/models/assoc_assoc.rb
87
- - lib/sportdb/models/badge.rb
88
- - lib/sportdb/models/event.rb
89
- - lib/sportdb/models/event_ground.rb
90
- - lib/sportdb/models/event_team.rb
91
- - lib/sportdb/models/forward.rb
92
- - lib/sportdb/models/game.rb
93
- - lib/sportdb/models/goal.rb
94
- - lib/sportdb/models/ground.rb
95
- - lib/sportdb/models/group.rb
96
- - lib/sportdb/models/group_team.rb
97
- - lib/sportdb/models/league.rb
98
- - lib/sportdb/models/person.rb
99
- - lib/sportdb/models/roster.rb
100
- - lib/sportdb/models/round.rb
101
- - lib/sportdb/models/season.rb
102
- - lib/sportdb/models/stage.rb
103
- - lib/sportdb/models/stage_team.rb
104
- - lib/sportdb/models/stats/alltime_standing.rb
105
- - lib/sportdb/models/stats/alltime_standing_entry.rb
106
- - lib/sportdb/models/stats/event_standing.rb
107
- - lib/sportdb/models/stats/event_standing_entry.rb
108
- - lib/sportdb/models/stats/group_standing.rb
109
- - lib/sportdb/models/stats/group_standing_entry.rb
110
- - lib/sportdb/models/team.rb
111
- - lib/sportdb/models/team_compat.rb
83
+ - lib/sportdb/models/deleter.rb
84
+ - lib/sportdb/models/formats.rb
85
+ - lib/sportdb/models/models/assoc.rb
86
+ - lib/sportdb/models/models/badge.rb
87
+ - lib/sportdb/models/models/event.rb
88
+ - lib/sportdb/models/models/forward.rb
89
+ - lib/sportdb/models/models/goal.rb
90
+ - lib/sportdb/models/models/ground.rb
91
+ - lib/sportdb/models/models/group.rb
92
+ - lib/sportdb/models/models/league.rb
93
+ - lib/sportdb/models/models/lineup.rb
94
+ - lib/sportdb/models/models/match.rb
95
+ - lib/sportdb/models/models/person.rb
96
+ - lib/sportdb/models/models/round.rb
97
+ - lib/sportdb/models/models/season.rb
98
+ - lib/sportdb/models/models/stage.rb
99
+ - lib/sportdb/models/models/stats/alltime_standing.rb
100
+ - lib/sportdb/models/models/stats/event_standing.rb
101
+ - lib/sportdb/models/models/stats/group_standing.rb
102
+ - lib/sportdb/models/models/team.rb
103
+ - lib/sportdb/models/models/world/city.rb
104
+ - lib/sportdb/models/models/world/continent.rb
105
+ - lib/sportdb/models/models/world/country.rb
106
+ - lib/sportdb/models/models/world/state.rb
107
+ - lib/sportdb/models/schema.rb
108
+ - lib/sportdb/models/stats.rb
112
109
  - lib/sportdb/models/utils.rb
113
- - lib/sportdb/models/world/city.rb
114
- - lib/sportdb/models/world/continent.rb
115
- - lib/sportdb/models/world/country.rb
116
- - lib/sportdb/models/world/state.rb
117
- - lib/sportdb/patterns.rb
118
- - lib/sportdb/schema.rb
119
- - lib/sportdb/standings.rb
120
- - lib/sportdb/stats.rb
121
- - lib/sportdb/version.rb
110
+ - lib/sportdb/models/version.rb
122
111
  - test/helper.rb
123
112
  - test/test_changes.rb
124
113
  - test/test_cursor.rb
data/lib/sportdb/calc.rb DELETED
@@ -1,279 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module SportDb
4
-
5
- ############
6
- ##
7
- ## fix/todo: obsolete
8
- ## - use new Standings class
9
-
10
-
11
- ##############################################
12
- # helper/ builds standings table in memory
13
- # - find a better module name for StandingsHelper ?? why? why not?
14
-
15
-
16
- module StandingsHelper
17
-
18
- ## todo:
19
- ## add team_id to struct - why? why not? - saves a db lookup?
20
- class Stats
21
- ### fix/todo: change/rename :pos to :rank
22
- attr_accessor :pos, :played, :won, :lost, :drawn,
23
- :goals_for, :goals_against, :pts,
24
- :recs
25
-
26
- def initialize
27
- @pos = nil # use 0? why? why not?
28
- @played = 0
29
- @won = 0
30
- @lost = 0
31
- @drawn = 0
32
- @goals_for = 0
33
- @goals_against = 0
34
- @pts = 0
35
- @recs = 0
36
- # note: appearances (event) count or similar
37
- # is recs counter (number of (stats) records)
38
- end
39
-
40
- def add( rec )
41
- ### fix: add plus + operator too!
42
-
43
- # note: will NOT update/add pos (ranking)
44
- self.played += rec.played
45
- self.won += rec.won
46
- self.lost += rec.lost
47
- self.drawn += rec.drawn
48
- self.goals_for += rec.goals_for
49
- self.goals_against += rec.goals_against
50
- self.pts += rec.pts
51
- self.recs += rec.recs
52
-
53
- self # return self stats rec
54
- end # method add
55
- end # class Stats
56
-
57
-
58
- def self.calc( games, opts={} )
59
-
60
- ##
61
- # possible opts include:
62
- # pts_won: 3 or 2 or n (default 3)
63
- # pts_exclude_scorep false or true (default false) -- exclude penalty shotout scores (e.g. count a draw/tie - no winner)
64
- #
65
- recs = calc_stats( games, opts )
66
-
67
- ## update pos (that is, ranking e.g. 1.,2., 3. etc.)
68
- recs= update_ranking( recs )
69
-
70
- pp recs
71
- recs
72
- end
73
-
74
-
75
-
76
- def self.calc_for_events( events, opts={} )
77
-
78
- ## todo:
79
- ## - add tracker for appeareances (stats records counter)
80
-
81
- alltime_recs = {} # stats recs indexed by team_key
82
-
83
- events.each do |event|
84
- puts " update standings for #{event.title}"
85
- recs = calc_stats( event.games, opts )
86
-
87
- recs.each do |team_key, rec|
88
- alltime_rec = alltime_recs[ team_key ] || Stats.new
89
-
90
- ## add stats values
91
- alltime_rec.add( rec )
92
-
93
- alltime_recs[ team_key ] = alltime_rec
94
- end
95
- end
96
-
97
-
98
- ### fix:
99
- # - make merge team into a helper method (for reuse)
100
-
101
- ## check for merging teams
102
- # e.g. all time world cup
103
- # Germany incl. West Germany
104
- # Russia incl. Soviet Union etc.
105
-
106
- # todo: change opts para to :includes instead of :merge ? why? why not??
107
-
108
- merge = opts[:merge]
109
- if merge
110
- puts " merging teams (stats records):"
111
- pp merge
112
-
113
- merge.each do |k,v|
114
- # note: assume key is destition team key and
115
- # value is source team key e.g. 'GER' => 'FRG'
116
- # or array (for mulitple teamss e.g. 'GER' => ['FRG','GDR']
117
- team_key_dest = k.to_s
118
-
119
- if v.kind_of? Array
120
- team_keys_src = v
121
- else
122
- team_keys_src = [v] # turn single value arg into array w/ single item
123
- end
124
- team_keys_src = team_keys_src.map { |src| src.to_s } # turn all to string (might be symbol)
125
-
126
- alltime_rec_dest = alltime_recs[ team_key_dest ] || Stats.new
127
-
128
- team_keys_src.each do |team_key_src|
129
- alltime_rec_src = alltime_recs[ team_key_src]
130
-
131
- if alltime_rec_src # stats record found?
132
- alltime_rec_dest.add( alltime_rec_src ) # add stats values
133
- alltime_recs.delete( team_key_src ) # remove old src entry
134
- end
135
- end
136
-
137
- alltime_recs[ team_key_dest ] = alltime_rec_dest
138
- end
139
- end
140
-
141
- ## update pos (that is, ranking e.g. 1.,2., 3. etc.)
142
- alltime_recs= update_ranking( alltime_recs )
143
-
144
- ## pp alltime_recs
145
- alltime_recs
146
- end
147
-
148
-
149
-
150
- def self.calc_stats( games, opts={} )
151
-
152
- ## fix:
153
- # passing in e.g. pts for win (3? 2? etc.)
154
- # default to 3 for now
155
-
156
- # note:
157
- # returns stats records w/ stats records counter always set to one (recs==1)
158
-
159
- ## todo/fix: find a better way to include logger (do NOT hardcode usage of root logger)!!!
160
- logger = LogUtils::Logger.root
161
-
162
-
163
- ## lets you pass in 2 as an alterantive, for example
164
- pts_won = opts[:pts_won] || 3
165
-
166
- ## lets you exclude penalty shootout (e.g. match gets scored as draw/tie 1 pt each)
167
- # e.g. why? used for alltime standings formula in world cup, for example
168
- # todo: check other standings - exclude penalty shootout too - e.g. championsleague ?? if yes - make it true as default??
169
- pts_exclude_scorep = opts[:pts_exclude_scorep].present? ? opts[:pts_exclude_scorep] : false
170
-
171
-
172
- recs = {}
173
-
174
- games.each_with_index do |g,i| # note: index(i) starts w/ zero (0)
175
- puts " [#{i+1}] #{g.team1.title} - #{g.team2.title} #{g.score_str}"
176
- unless g.over?
177
- puts " !!!! skipping match - not yet over (play_at date in the future)"
178
- next
179
- end
180
- unless g.complete?
181
- logger.error "[StandingsHelper.calc_stats] skipping match #{g.team1.title} - #{g.team2.title} - scores incomplete #{g.score_str}"
182
- next
183
- end
184
-
185
- rec1 = recs[ g.team1.key ] || Stats.new
186
- rec2 = recs[ g.team2.key ] || Stats.new
187
-
188
- ## set stats records counter to one if new (first) record update
189
- rec1.recs = 1 if rec1.recs == 0
190
- rec2.recs = 1 if rec2.recs == 0
191
-
192
- rec1.played += 1
193
- rec2.played += 1
194
-
195
- ## check - if winner (excludes penalty shootout scores in calc? start w/ extra time e.g winneret)
196
- if pts_exclude_scorep
197
- winner = g.winneret || g.winner90 ## if no extra time (et) score; try 90min (regular time score)
198
- else
199
- winner = g.winner ## note: might include penalty shoot scores
200
- end
201
-
202
- if winner == 1
203
- rec1.won += 1
204
- rec2.lost += 1
205
- rec1.pts += pts_won
206
- elsif winner == 2
207
- rec1.lost += 1
208
- rec2.won += 1
209
- rec2.pts += pts_won
210
- else ## assume drawn/tie (that is, 0)
211
- rec1.drawn += 1
212
- rec2.drawn += 1
213
- rec1.pts += 1
214
- rec2.pts += 1
215
- end
216
-
217
- rec1.goals_for += g.score1
218
- rec1.goals_against += g.score2
219
-
220
- rec2.goals_for += g.score2
221
- rec2.goals_against += g.score1
222
-
223
- ## add overtime and penalty??
224
- ## - for now add only overtime if present
225
-
226
- rec1.goals_for += (g.score1et-g.score1) if g.score1et.present?
227
- rec1.goals_against += (g.score2et-g.score2) if g.score2et.present?
228
-
229
- rec2.goals_for += (g.score2et-g.score2) if g.score2et.present?
230
- rec2.goals_against += (g.score1et-g.score1) if g.score1et.present?
231
-
232
- recs[ g.team1.key ] = rec1
233
- recs[ g.team2.key ] = rec2
234
- end # each game
235
-
236
- recs # return records; hash indexed by team key
237
- end # method calc
238
-
239
-
240
- def self.update_ranking( recs )
241
- #############################
242
- ### calc ranking / pos
243
- ##
244
- ## fix/allow sampe pos e.g. all 1 or more than one team 3rd etc.
245
- ## see sportbook for an example
246
-
247
- # build array from hash
248
- ary = []
249
- recs.each do |k,v|
250
- ary << [k,v]
251
- end
252
-
253
- ary.sort! do |l,r|
254
- ## note: reverse order (thus, change l,r to r,l)
255
- value = r[1].pts <=> l[1].pts
256
- if value == 0 # same pts try goal diff
257
- value = (r[1].goals_for-r[1].goals_against) <=> (l[1].goals_for-l[1].goals_against)
258
- if value == 0 # same goal diff too; try assume more goals better for now
259
- value = r[1].goals_for <=> l[1].goals_for
260
- end
261
- end
262
- value
263
- end
264
-
265
- ## update pos using ordered array
266
- ary.each_with_index do |rec,i|
267
- k = rec[0]
268
- v = rec[1]
269
- v.pos = i+1 ## add ranking (e.g. 1,2,3 etc.) - note: i starts w/ zero (0)
270
- recs[ k ] = v ## update recs
271
- end
272
-
273
- recs
274
- end # method update_ranking
275
-
276
-
277
- end # module StandingsHelper
278
-
279
- end # module SportDb
@@ -1,106 +0,0 @@
1
- module SportDb
2
- module Model
3
-
4
- class Assoc < ActiveRecord::Base
5
-
6
- has_many :parent_assoc_assocs, class_name: 'AssocAssoc', foreign_key: 'assoc2_id'
7
- ## child_assocs - use child_assocs? - (direct) member/child assocs instead of member?
8
- has_many :member_assoc_assocs, class_name: 'AssocAssoc', foreign_key: 'assoc1_id'
9
-
10
-
11
- ## note: split member_assocs into two sets (into national=true and national=false)
12
- # e.g. fifa has six member confederations (non-national) and 216 national assocs
13
- if ActiveRecord::VERSION::MAJOR == 3
14
- has_many :all_assocs, class_name: 'Assoc', :source => :assoc2, :through => :member_assoc_assocs
15
- has_many :sub_assocs, class_name: 'Assoc', :source => :assoc2, :through => :member_assoc_assocs, conditions: { national: false }
16
- has_many :national_assocs, class_name: 'Assoc', :source => :assoc2, :through => :member_assoc_assocs, conditions: { national: true }
17
- else
18
- ## note: includes all member (sub assocs + national assocs) - rename to member_assocs?
19
- has_many :all_assocs, class_name: 'Assoc', :source => :assoc2, :through => :member_assoc_assocs
20
- ## use zone/region as name instead of sub ( for confederatons,zones,etc.)
21
- has_many :sub_assocs, -> { where( national: false ) }, class_name: 'Assoc', :source => :assoc2, :through => :member_assoc_assocs
22
- has_many :national_assocs, -> { where( national: true ) }, class_name: 'Assoc', :source => :assoc2, :through => :member_assoc_assocs
23
- end
24
-
25
- ## for now can have more than one (direct) parent assoc
26
- ## e.g. Africa Fed and Arab League Fed
27
- has_many :parent_assocs, class_name: 'Assoc', :source => :assoc1, :through => :parent_assoc_assocs
28
-
29
- # assoc only can have one direct team for now (uses belongs_to on other side)
30
- # has_one :team
31
-
32
-
33
- def self.create_or_update_from_values( new_attributes, values )
34
-
35
- ## fix: add/configure logger for ActiveRecord!!!
36
- logger = LogUtils::Logger.root
37
-
38
- assoc_keys = [] # by default no association (e.g. fifa,uefa,etc.)
39
-
40
- ## check optional values
41
- values.each_with_index do |value, index|
42
- if value =~ /^(18|19|20)[0-9]{2}$/ ## assume founding year -- allow 18|19|20
43
- ## logger.info " founding/opening year #{value}"
44
- new_attributes[ :since ] = value.to_i
45
- elsif value =~ /\/{2}/ # assume it's an address line e.g. xx // xx
46
- logger.info " found address line #{value}"
47
- ## new_attributes[ :address ] = value
48
- elsif value =~ /^(?:[a-z]{2}\.)?wikipedia:/ # assume it's wikipedia e.g. [es.]wikipedia:
49
- logger.info " found wikipedia line #{value}; skipping for now"
50
- elsif value =~ /(^www\.)|(\.com$)/ # FIX: !!!! use a better matcher not just www. and .com
51
- new_attributes[ :web ] = value
52
- ## elsif value =~ /^[a-z]{2}$/ ## assume two-letter country key e.g. at,de,mx,etc.
53
- ## ## fix: allow country letter with three e.g. eng,sco,wal,nir, etc. !!!
54
- ## value_country = Country.find_by_key!( value )
55
- ## new_attributes[ :country_id ] = value_country.id
56
- elsif value =~ /^[a-z]{2}$/ ## assume two-letter country key e.g. at,de,mx,etc.
57
- ## fix: allow country letter with three e.g. eng,sco,wal,nir, etc. !!!
58
- ## fix: if country does NOT match / NOT found - just coninue w/ next match!!!!
59
- # - just issue an error/warn do NOT crash
60
- value_country = Country.find_by_key!( value )
61
- new_attributes[ :country_id ] = value_country.id
62
- ## note: if country present - assume it's a national assoc, thus, set flag to true
63
- new_attributes[ :national ] = true
64
- elsif value =~ /^[a-z|]+$/ ## looks like a tag list e.g. fifa|uefa or fifa|caf or ocf?
65
- logger.info " trying adding assocs using keys >#{value}<"
66
- assoc_keys = value.split('|')
67
- else
68
- ## todo: assume title2 ??
69
- # issue warning: unknown type for value
70
- logger.warn "unknown type for value >#{value}< - key #{new_attributes[:key]}"
71
- end
72
- end
73
-
74
- rec = Assoc.find_by_key( new_attributes[ :key ] )
75
- if rec.present?
76
- logger.debug "update Assoc #{rec.id}-#{rec.key}:"
77
- else
78
- logger.debug "create Assoc:"
79
- rec = Assoc.new
80
- end
81
-
82
- logger.debug new_attributes.to_json
83
-
84
- rec.update_attributes!( new_attributes )
85
-
86
- unless assoc_keys.empty?
87
- ## add team to assocs
88
- assoc_keys.each do |assoc_key|
89
- assoc = Assoc.find_by_key!( assoc_key )
90
- logger.debug " adding assoc to assoc >#{assoc.title}<"
91
-
92
- ### todo/fix: how can we delete assoc_assocs? for now only update n create
93
- assoc_assoc = AssocAssoc.where( assoc1_id: assoc.id, assoc2_id: rec.id ).first
94
- if assoc_assoc.nil? ## create if does NOT exist yet
95
- AssocAssoc.create!( assoc1_id: assoc.id, assoc2_id: rec.id )
96
- end
97
- end
98
- end
99
-
100
- end # create_or_update_from_values
101
-
102
- end # class Assoc
103
-
104
-
105
- end # module Model
106
- end # module SportDb