sportdb 1.8.28 → 1.8.29
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +14 -0
- data/README.md +2 -2
- data/Rakefile +1 -1
- data/lib/sportdb.rb +7 -0
- data/lib/sportdb/deleter.rb +3 -0
- data/lib/sportdb/models/assoc.rb +106 -0
- data/lib/sportdb/models/assoc_assoc.rb +15 -0
- data/lib/sportdb/models/event.rb +6 -9
- data/lib/sportdb/models/event_comp.rb +21 -0
- data/lib/sportdb/models/forward.rb +2 -0
- data/lib/sportdb/models/game.rb +4 -151
- data/lib/sportdb/models/game_comp.rb +157 -0
- data/lib/sportdb/models/group.rb +4 -11
- data/lib/sportdb/models/group_comp.rb +23 -0
- data/lib/sportdb/models/team.rb +12 -52
- data/lib/sportdb/models/team_comp.rb +64 -0
- data/lib/sportdb/models/world/country.rb +2 -1
- data/lib/sportdb/reader.rb +3 -0
- data/lib/sportdb/readers/assoc.rb +34 -0
- data/lib/sportdb/schema.rb +38 -1
- data/lib/sportdb/stats.rb +2 -1
- data/lib/sportdb/version.rb +1 -1
- data/test/data/national-teams/assocs.txt +231 -0
- data/test/data/national-teams/europe/assocs.txt +13 -0
- data/test/data/national-teams/europe/teams.txt +13 -0
- data/test/data/national-teams/north-america/assocs.txt +10 -0
- data/test/data/national-teams/north-america/teams.txt +7 -0
- data/test/data/national-teams/teams.txt +19 -0
- data/test/helper.rb +8 -5
- data/test/test_assoc_reader.rb +199 -0
- metadata +42 -27
@@ -0,0 +1,157 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SportDb
|
4
|
+
module Model
|
5
|
+
|
6
|
+
#############################################################
|
7
|
+
# collect depreciated or methods for future removal here
|
8
|
+
# - keep for now for compatibility (for old code)
|
9
|
+
|
10
|
+
class Game
|
11
|
+
|
12
|
+
### getter/setters for deprecated attribs (score3,4,5,6) n national
|
13
|
+
def score3() score1et end
|
14
|
+
def score4() score2et end
|
15
|
+
def score5() score1p end
|
16
|
+
def score6() score2p end
|
17
|
+
|
18
|
+
def score3=(value) self.score1et = value end
|
19
|
+
def score4=(value) self.score2et = value end
|
20
|
+
def score5=(value) self.score1p = value end
|
21
|
+
def score6=(value) self.score2p = value end
|
22
|
+
|
23
|
+
def self.create_knockouts_from_ary!( games, round )
|
24
|
+
Game.create_from_ary!( games, round, true )
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.create_from_ary!( games, round, knockout=false )
|
28
|
+
|
29
|
+
### fix:
|
30
|
+
# replace knockout=false with more attribs
|
31
|
+
# see create teams and than merge attribs
|
32
|
+
|
33
|
+
games.each_with_index do |values,index|
|
34
|
+
|
35
|
+
value_pos = index+1
|
36
|
+
value_scores = []
|
37
|
+
value_teams = []
|
38
|
+
value_knockout = knockout
|
39
|
+
value_play_at = round.start_at # if no date present use it from round
|
40
|
+
value_group = nil
|
41
|
+
|
42
|
+
### lets you use arguments in any order
|
43
|
+
## makes pos optional (if not present counting from 1 to n)
|
44
|
+
|
45
|
+
values.each do |value|
|
46
|
+
if value.kind_of? Numeric
|
47
|
+
value_pos = value
|
48
|
+
elsif value.kind_of?( TrueClass ) || value.kind_of?( FalseClass )
|
49
|
+
value_knockout = value
|
50
|
+
elsif value.kind_of? Array
|
51
|
+
value_scores = value
|
52
|
+
elsif value.kind_of? Team
|
53
|
+
value_teams << value
|
54
|
+
elsif value.kind_of? Group
|
55
|
+
value_group = value
|
56
|
+
elsif value.kind_of?( Date ) || value.kind_of?( Time ) || value.kind_of?( DateTime )
|
57
|
+
value_play_at = value
|
58
|
+
else
|
59
|
+
# issue an error/warning here
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
Game.create!(
|
64
|
+
:round => round,
|
65
|
+
:pos => value_pos,
|
66
|
+
:team1 => value_teams[0],
|
67
|
+
:score1 => value_scores[0],
|
68
|
+
:score2 => value_scores[1],
|
69
|
+
:score1et => value_scores[2],
|
70
|
+
:score2et => value_scores[3],
|
71
|
+
:score1p => value_scores[4],
|
72
|
+
:score2p => value_scores[5],
|
73
|
+
:team2 => value_teams[1],
|
74
|
+
:play_at => value_play_at,
|
75
|
+
:group => value_group, # Note: group is optional (may be null/nil)
|
76
|
+
:knockout => value_knockout )
|
77
|
+
end # each games
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.create_pairs_from_ary_for_group!( pairs, group )
|
81
|
+
|
82
|
+
pairs.each do |pair|
|
83
|
+
game1_attribs = {
|
84
|
+
:round =>pair[0][5],
|
85
|
+
:pos =>pair[0][0],
|
86
|
+
:team1 =>pair[0][1],
|
87
|
+
:score1 =>pair[0][2][0],
|
88
|
+
:score2 =>pair[0][2][1],
|
89
|
+
:team2 =>pair[0][3],
|
90
|
+
:play_at =>pair[0][4],
|
91
|
+
:group =>group }
|
92
|
+
|
93
|
+
game2_attribs = {
|
94
|
+
:round =>pair[1][5],
|
95
|
+
:pos =>pair[1][0],
|
96
|
+
:team1 =>pair[1][1],
|
97
|
+
:score1 =>pair[1][2][0],
|
98
|
+
:score2 =>pair[1][2][1],
|
99
|
+
:team2 =>pair[1][3],
|
100
|
+
:play_at =>pair[1][4],
|
101
|
+
:group =>group }
|
102
|
+
|
103
|
+
game1 = Game.create!( game1_attribs )
|
104
|
+
game2 = Game.create!( game2_attribs )
|
105
|
+
|
106
|
+
# linkup games
|
107
|
+
game1.next_game_id = game2.id
|
108
|
+
game1.save!
|
109
|
+
|
110
|
+
game2.prev_game_id = game1.id
|
111
|
+
game2.save!
|
112
|
+
end # each pair
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.create_knockout_pairs_from_ary!( pairs, round1, round2 )
|
116
|
+
|
117
|
+
pairs.each do |pair|
|
118
|
+
game1_attribs = {
|
119
|
+
:round =>round1,
|
120
|
+
:pos =>pair[0][0],
|
121
|
+
:team1 =>pair[0][1],
|
122
|
+
:score1 =>pair[0][2][0],
|
123
|
+
:score2 =>pair[0][2][1],
|
124
|
+
:team2 =>pair[0][3],
|
125
|
+
:play_at =>pair[0][4] }
|
126
|
+
|
127
|
+
game2_attribs = {
|
128
|
+
:round =>round2,
|
129
|
+
:pos =>pair[1][0],
|
130
|
+
:team1 =>pair[1][1],
|
131
|
+
:score1 =>pair[1][2][0],
|
132
|
+
:score2 =>pair[1][2][1],
|
133
|
+
:score1et =>pair[1][2][2],
|
134
|
+
:score2et =>pair[1][2][3],
|
135
|
+
:score1p =>pair[1][2][4],
|
136
|
+
:score1p =>pair[1][2][5],
|
137
|
+
:team2 =>pair[1][3],
|
138
|
+
:play_at =>pair[1][4],
|
139
|
+
:knockout =>true }
|
140
|
+
|
141
|
+
game1 = Game.create!( game1_attribs )
|
142
|
+
game2 = Game.create!( game2_attribs )
|
143
|
+
|
144
|
+
# linkup games
|
145
|
+
game1.next_game_id = game2.id
|
146
|
+
game1.save!
|
147
|
+
|
148
|
+
game2.prev_game_id = game1.id
|
149
|
+
game2.save!
|
150
|
+
end # each pair
|
151
|
+
end
|
152
|
+
|
153
|
+
end # class Game
|
154
|
+
|
155
|
+
|
156
|
+
end # module Model
|
157
|
+
end # module SportDb
|
data/lib/sportdb/models/group.rb
CHANGED
@@ -6,23 +6,16 @@ module SportDb
|
|
6
6
|
class Group < ActiveRecord::Base
|
7
7
|
|
8
8
|
if ActiveRecord::VERSION::MAJOR == 3
|
9
|
-
has_many :games, :
|
9
|
+
has_many :games, order: 'pos'
|
10
10
|
else
|
11
11
|
has_many :games, -> { order('pos') }
|
12
12
|
end
|
13
13
|
|
14
14
|
belongs_to :event
|
15
|
-
|
16
|
-
has_many :group_teams, :
|
15
|
+
|
16
|
+
has_many :group_teams, class_name: 'GroupTeam'
|
17
17
|
has_many :teams, :through => :group_teams
|
18
|
-
|
19
|
-
def add_teams_from_ary!( team_keys )
|
20
|
-
team_keys.each do |team_key|
|
21
|
-
team = Team.find_by_key!( team_key )
|
22
|
-
self.teams << team
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
18
|
+
|
26
19
|
end # class Group
|
27
20
|
|
28
21
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SportDb
|
4
|
+
module Model
|
5
|
+
|
6
|
+
#############################################################
|
7
|
+
# collect depreciated or methods for future removal here
|
8
|
+
# - keep for now for compatibility (for old code)
|
9
|
+
|
10
|
+
class Group
|
11
|
+
|
12
|
+
def add_teams_from_ary!( team_keys )
|
13
|
+
team_keys.each do |team_key|
|
14
|
+
team = Team.find_by_key!( team_key )
|
15
|
+
self.teams << team
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end # class Group
|
20
|
+
|
21
|
+
|
22
|
+
end # module Model
|
23
|
+
end # module SportDb
|
data/lib/sportdb/models/team.rb
CHANGED
@@ -23,13 +23,16 @@ class Team < ActiveRecord::Base
|
|
23
23
|
has_many :event_teams, class_name: 'EventTeam' # join table (events+teams)
|
24
24
|
has_many :events, :through => :event_teams
|
25
25
|
|
26
|
+
# note: team belongs_to a single (optinal) assoc for now (national assoc may have many assocs)
|
27
|
+
belongs_to :assoc
|
26
28
|
|
27
29
|
### fix!!! - how to do it with has_many macro? use finder_sql?
|
28
30
|
## finder_sql is depreciated in Rails 4!!!
|
31
|
+
# use -> { where() } etc. -- try it if it works
|
29
32
|
## keep as is! best solution ??
|
30
33
|
## a discussion here -> https://github.com/rails/rails/issues/9726
|
31
34
|
## a discussion here (not really helpful) -> http://stackoverflow.com/questions/2125440/activerecord-has-many-where-two-columns-in-table-a-are-primary-keys-in-table-b
|
32
|
-
|
35
|
+
|
33
36
|
def games
|
34
37
|
Game.where( 'team1_id = ? or team2_id = ?', id, id ).order( 'play_at' )
|
35
38
|
end
|
@@ -53,7 +56,8 @@ class Team < ActiveRecord::Base
|
|
53
56
|
def self.create_or_update_from_values( new_attributes, values )
|
54
57
|
|
55
58
|
## fix: add/configure logger for ActiveRecord!!!
|
56
|
-
logger =
|
59
|
+
logger = LogUtils::Logger.root
|
60
|
+
|
57
61
|
|
58
62
|
## check optional values
|
59
63
|
values.each_with_index do |value, index|
|
@@ -81,6 +85,8 @@ class Team < ActiveRecord::Base
|
|
81
85
|
new_attributes[ :code ] = value
|
82
86
|
elsif value =~ /^[a-z]{2}$/ ## assume two-letter country key e.g. at,de,mx,etc.
|
83
87
|
## fix: allow country letter with three e.g. eng,sco,wal,nir, etc. !!!
|
88
|
+
## fix: if country does NOT match / NOT found - just coninue w/ next match!!!!
|
89
|
+
# - just issue an error/warn do NOT crash
|
84
90
|
value_country = Country.find_by_key!( value )
|
85
91
|
new_attributes[ :country_id ] = value_country.id
|
86
92
|
else
|
@@ -97,61 +103,15 @@ class Team < ActiveRecord::Base
|
|
97
103
|
logger.debug "create Team:"
|
98
104
|
rec = Team.new
|
99
105
|
end
|
100
|
-
|
106
|
+
|
101
107
|
logger.debug new_attributes.to_json
|
102
|
-
|
103
|
-
rec.update_attributes!( new_attributes )
|
104
|
-
end # create_or_update_from_values
|
105
108
|
|
109
|
+
rec.update_attributes!( new_attributes )
|
106
110
|
|
107
|
-
|
108
|
-
teams.each do |values|
|
109
|
-
|
110
|
-
## key & title required
|
111
|
-
attr = {
|
112
|
-
key: values[0]
|
113
|
-
}
|
114
|
-
|
115
|
-
## title (split of optional synonyms)
|
116
|
-
# e.g. FC Bayern Muenchen|Bayern Muenchen|Bayern
|
117
|
-
titles = values[1].split('|')
|
118
|
-
|
119
|
-
attr[ :title ] = titles[0]
|
120
|
-
## add optional synonyms
|
121
|
-
attr[ :synonyms ] = titles[1..-1].join('|') if titles.size > 1
|
122
|
-
|
123
|
-
|
124
|
-
attr = attr.merge( more_values )
|
125
|
-
|
126
|
-
## check for optional values
|
127
|
-
values[2..-1].each do |value|
|
128
|
-
if value.is_a? Country
|
129
|
-
attr[ :country_id ] = value.id
|
130
|
-
elsif value.is_a? City
|
131
|
-
attr[ :city_id ] = value.id
|
132
|
-
elsif value =~ /#{TEAM_CODE_PATTERN}/ ## assume its three letter code (e.g. ITA or S04 etc.)
|
133
|
-
attr[ :code ] = value
|
134
|
-
elsif value =~ /^city:/ ## city:
|
135
|
-
value_city_key = value[5..-1] ## cut off city: prefix
|
136
|
-
value_city = City.find_by_key!( value_city_key )
|
137
|
-
attr[ :city_id ] = value_city.id
|
138
|
-
else
|
139
|
-
attr[ :title2 ] = value
|
140
|
-
end
|
141
|
-
end
|
111
|
+
end # create_or_update_from_values
|
142
112
|
|
143
|
-
## check if exists
|
144
|
-
team = Team.find_by_key( values[0] )
|
145
|
-
if team.present?
|
146
|
-
puts "*** warning team with key '#{values[0]}' exists; skipping create"
|
147
|
-
else
|
148
|
-
Team.create!( attr )
|
149
|
-
end
|
150
|
-
end # each team
|
151
|
-
end
|
152
|
-
|
153
113
|
end # class Team
|
154
|
-
|
114
|
+
|
155
115
|
|
156
116
|
end # module Model
|
157
117
|
end # module SportDb
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SportDb
|
4
|
+
module Model
|
5
|
+
|
6
|
+
#############################################################
|
7
|
+
# collect depreciated or methods for future removal here
|
8
|
+
# - keep for now for compatibility (for old code)
|
9
|
+
|
10
|
+
class Team
|
11
|
+
|
12
|
+
|
13
|
+
def self.create_from_ary!( teams, more_values={} )
|
14
|
+
teams.each do |values|
|
15
|
+
|
16
|
+
## key & title required
|
17
|
+
attr = {
|
18
|
+
key: values[0]
|
19
|
+
}
|
20
|
+
|
21
|
+
## title (split of optional synonyms)
|
22
|
+
# e.g. FC Bayern Muenchen|Bayern Muenchen|Bayern
|
23
|
+
titles = values[1].split('|')
|
24
|
+
|
25
|
+
attr[ :title ] = titles[0]
|
26
|
+
## add optional synonyms
|
27
|
+
attr[ :synonyms ] = titles[1..-1].join('|') if titles.size > 1
|
28
|
+
|
29
|
+
|
30
|
+
attr = attr.merge( more_values )
|
31
|
+
|
32
|
+
## check for optional values
|
33
|
+
values[2..-1].each do |value|
|
34
|
+
if value.is_a? Country
|
35
|
+
attr[ :country_id ] = value.id
|
36
|
+
elsif value.is_a? City
|
37
|
+
attr[ :city_id ] = value.id
|
38
|
+
elsif value =~ /#{TEAM_CODE_PATTERN}/ ## assume its three letter code (e.g. ITA or S04 etc.)
|
39
|
+
attr[ :code ] = value
|
40
|
+
elsif value =~ /^city:/ ## city:
|
41
|
+
value_city_key = value[5..-1] ## cut off city: prefix
|
42
|
+
value_city = City.find_by_key!( value_city_key )
|
43
|
+
attr[ :city_id ] = value_city.id
|
44
|
+
else
|
45
|
+
attr[ :title2 ] = value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
## check if exists
|
50
|
+
team = Team.find_by_key( values[0] )
|
51
|
+
if team.present?
|
52
|
+
puts "*** warning team with key '#{values[0]}' exists; skipping create"
|
53
|
+
else
|
54
|
+
Team.create!( attr )
|
55
|
+
end
|
56
|
+
end # each team
|
57
|
+
end
|
58
|
+
|
59
|
+
end # class Team
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
end # module Model
|
64
|
+
end # module SportDb
|
@@ -4,7 +4,8 @@ module WorldDb
|
|
4
4
|
module Model
|
5
5
|
|
6
6
|
class Country
|
7
|
-
has_many :teams,
|
7
|
+
has_many :teams, class_name: 'SportDb::Model::Team', foreign_key: 'country_id'
|
8
|
+
has_one :assoc, class_name: 'SportDb::Model::Assoc', foreign_key: 'country_id'
|
8
9
|
|
9
10
|
# fix: require active record 4
|
10
11
|
# has_many :clubs, -> { where club: true }, class_name: 'SportDb::Model::Team', foreign_key: 'country_id'
|
data/lib/sportdb/reader.rb
CHANGED
@@ -117,6 +117,9 @@ class Reader
|
|
117
117
|
elsif name =~ /(?:^|\/)seasons/ # NB: ^seasons or also possible at-austria!/seasons
|
118
118
|
reader = SeasonReader.new( include_path )
|
119
119
|
reader.read( name )
|
120
|
+
elsif name =~ /(?:^|\/)assocs/ # NB: ^assocs or also possible national-teams!/assocs
|
121
|
+
reader = AssocReader.new( include_path )
|
122
|
+
reader.read( name )
|
120
123
|
elsif match_stadiums_for_country( name ) do |country_key|
|
121
124
|
country = Country.find_by_key!( country_key )
|
122
125
|
reader = GroundReader.new( include_path )
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module SportDb
|
4
|
+
|
5
|
+
|
6
|
+
class AssocReader
|
7
|
+
|
8
|
+
include LogUtils::Logging
|
9
|
+
|
10
|
+
## make models available by default with namespace
|
11
|
+
# e.g. lets you use Usage instead of Model::Usage
|
12
|
+
include Models
|
13
|
+
|
14
|
+
|
15
|
+
attr_reader :include_path
|
16
|
+
|
17
|
+
|
18
|
+
def initialize( include_path, opts = {} )
|
19
|
+
@include_path = include_path
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def read( name, more_attribs={} )
|
24
|
+
reader = ValuesReaderV2.new( name, include_path, more_attribs )
|
25
|
+
|
26
|
+
reader.each_line do |new_attributes, values|
|
27
|
+
Assoc.create_or_update_from_values( new_attributes, values )
|
28
|
+
end # each lines
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
end # class AssocReader
|
34
|
+
end # module SportDb
|
data/lib/sportdb/schema.rb
CHANGED
@@ -20,6 +20,8 @@ create_table :teams do |t|
|
|
20
20
|
t.string :address
|
21
21
|
t.string :web
|
22
22
|
|
23
|
+
t.references :assoc # optional: national football assoc(iation), for example - used for national teams
|
24
|
+
|
23
25
|
### fix: remove and add virtual attribute in model instead
|
24
26
|
t.boolean :national, null: false, default: false # is it a national selection team (not a club)?
|
25
27
|
t.timestamps
|
@@ -230,7 +232,8 @@ add_index :games, :round_id # fk round_id index
|
|
230
232
|
add_index :games, :group_id # fk group_id index
|
231
233
|
add_index :games, :next_game_id # fk next_game_id index
|
232
234
|
add_index :games, :prev_game_id # fk next_game_id index
|
233
|
-
|
235
|
+
add_index :games, :team1_id
|
236
|
+
add_index :games, :team2_id
|
234
237
|
|
235
238
|
|
236
239
|
# todo: remove id from join table (without extra fields)? why?? why not??
|
@@ -298,6 +301,40 @@ create_table :badges do |t|
|
|
298
301
|
end
|
299
302
|
|
300
303
|
|
304
|
+
create_table :assocs do |t|
|
305
|
+
t.string :key, null: false
|
306
|
+
t.string :title, null: false # e.g. Premier League, Deutsche Bundesliga, World Cup, Champions League, etc.
|
307
|
+
|
308
|
+
t.integer :since # founding year
|
309
|
+
t.string :web
|
310
|
+
|
311
|
+
### if national assoc - has (optional) country ref
|
312
|
+
t.references :country # note: optional - only used/set (required) for national assocs (or subnational too?)
|
313
|
+
t.boolean :national, null: false, default: false
|
314
|
+
|
315
|
+
## add :world flag for FIFA? - just check if parent is null? for root assoc(s)? why? why not?
|
316
|
+
## add :regional flag for continental subdivision?
|
317
|
+
t.boolean :continental, null: false, default: false
|
318
|
+
t.boolean :intercontinental, null: false, default: false # e.g. arab football league (africa+western asia/middle east)
|
319
|
+
t.timestamps
|
320
|
+
end
|
321
|
+
|
322
|
+
add_index :assocs, :key, unique: true
|
323
|
+
|
324
|
+
|
325
|
+
|
326
|
+
create_table :assocs_assocs do |t|
|
327
|
+
t.references :assoc1, null: false # parent assoc
|
328
|
+
t.references :assoc2, null: false # child assoc is_member_of parent assoc
|
329
|
+
t.timestamps
|
330
|
+
end
|
331
|
+
|
332
|
+
add_index :assocs_assocs, [:assoc1_id,:assoc2_id], unique: true
|
333
|
+
add_index :assocs_assocs, :assoc1_id
|
334
|
+
add_index :assocs_assocs, :assoc2_id
|
335
|
+
|
336
|
+
|
337
|
+
|
301
338
|
############################################
|
302
339
|
# stats tables
|
303
340
|
|