sportdb 1.9.1 → 1.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +5 -0
- data/lib/sportdb.rb +2 -0
- data/lib/sportdb/finders/goals.rb +260 -0
- data/lib/sportdb/models/game.rb +1 -1
- data/lib/sportdb/readers/game.rb +124 -1
- data/lib/sportdb/schema.rb +4 -1
- data/lib/sportdb/utils_goals.rb +20 -0
- data/lib/sportdb/version.rb +1 -1
- data/test/data/world-cup/1930/cup_goals.txt +47 -0
- data/test/data/world-cup/1930/cup_goals.yml +23 -0
- data/test/test_goals.rb +109 -0
- metadata +32 -26
data/Manifest.txt
CHANGED
@@ -21,6 +21,7 @@ lib/sportdb/data/keys.rb
|
|
21
21
|
lib/sportdb/data/models.rb
|
22
22
|
lib/sportdb/deleter.rb
|
23
23
|
lib/sportdb/finders/date.rb
|
24
|
+
lib/sportdb/finders/goals.rb
|
24
25
|
lib/sportdb/finders/scores.rb
|
25
26
|
lib/sportdb/lang.rb
|
26
27
|
lib/sportdb/matcher.rb
|
@@ -89,6 +90,7 @@ lib/sportdb/stats.rb
|
|
89
90
|
lib/sportdb/updater.rb
|
90
91
|
lib/sportdb/utils.rb
|
91
92
|
lib/sportdb/utils_date.rb
|
93
|
+
lib/sportdb/utils_goals.rb
|
92
94
|
lib/sportdb/utils_group.rb
|
93
95
|
lib/sportdb/utils_map.rb
|
94
96
|
lib/sportdb/utils_record.rb
|
@@ -114,6 +116,8 @@ test/data/players/europe/de-deutschland/players.txt
|
|
114
116
|
test/data/players/south-america/br-brazil/players.txt
|
115
117
|
test/data/world-cup/1930/cup.txt
|
116
118
|
test/data/world-cup/1930/cup.yml
|
119
|
+
test/data/world-cup/1930/cup_goals.txt
|
120
|
+
test/data/world-cup/1930/cup_goals.yml
|
117
121
|
test/data/world-cup/1954/cup.txt
|
118
122
|
test/data/world-cup/1954/cup.yml
|
119
123
|
test/data/world-cup/1962/cup.txt
|
@@ -140,6 +144,7 @@ test/test_assoc_reader.rb
|
|
140
144
|
test/test_changes.rb
|
141
145
|
test/test_cursor.rb
|
142
146
|
test/test_date.rb
|
147
|
+
test/test_goals.rb
|
143
148
|
test/test_lang.rb
|
144
149
|
test/test_load.rb
|
145
150
|
test/test_national_team_reader.rb
|
data/lib/sportdb.rb
CHANGED
@@ -88,9 +88,11 @@ require 'sportdb/utils_record'
|
|
88
88
|
require 'sportdb/utils_round'
|
89
89
|
require 'sportdb/utils_scores'
|
90
90
|
require 'sportdb/utils_teams'
|
91
|
+
require 'sportdb/utils_goals'
|
91
92
|
require 'sportdb/matcher'
|
92
93
|
require 'sportdb/calc'
|
93
94
|
|
95
|
+
require 'sportdb/finders/goals' # no: requires FixturesHelpers
|
94
96
|
|
95
97
|
require 'sportdb/readers/assoc'
|
96
98
|
require 'sportdb/readers/event'
|
@@ -0,0 +1,260 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SportDb
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
class GoalsPlayerStruct
|
8
|
+
##
|
9
|
+
# note: player with own goal (o.g) gets listed on other team
|
10
|
+
# (thus, player might have two entries if also scored for its own team)
|
11
|
+
#
|
12
|
+
attr_accessor :name
|
13
|
+
attr_accessor :minutes # ary of minutes e.g. 30', 45+2', 72'
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@minutes = []
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
class GoalsMinuteStruct
|
22
|
+
attr_accessor :minute, :offset
|
23
|
+
attr_accessor :penalty, :owngoal # flags
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
@offset = 0
|
27
|
+
@penalty = false
|
28
|
+
@owngoal = false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
class GoalStruct
|
34
|
+
######
|
35
|
+
# flat struct for goals - one entry per goals
|
36
|
+
attr_accessor :name
|
37
|
+
attr_accessor :team # 1 or 2 ? check/todo: add team1 or team2 flag?
|
38
|
+
attr_accessor :minute, :offset
|
39
|
+
attr_accessor :penalty, :owngoal
|
40
|
+
attr_accessor :score1, :score2 # gets calculated
|
41
|
+
|
42
|
+
## add pos for sequence number? e.g. 1,2,3,4 (1st goald, 2nd goal, etc.) ???
|
43
|
+
|
44
|
+
def initialize
|
45
|
+
# do nothing
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
# todo: find a better name? to avoid confusing w/ GoalsParser? use MatchGoalsParser or similar?
|
52
|
+
class GoalsFinder
|
53
|
+
include LogUtils::Logging
|
54
|
+
include FixtureHelpers # e.g. cut_off_end_of_line_comment!
|
55
|
+
|
56
|
+
def initialize
|
57
|
+
# nothing here for now
|
58
|
+
end
|
59
|
+
|
60
|
+
def find!( line, opts={} )
|
61
|
+
# remove end-of-line comments
|
62
|
+
# - move to textutils ?? why? why not??
|
63
|
+
cut_off_end_of_line_comment!( line ) ## note: func defined in utils.rb (FixtureHelpers)
|
64
|
+
|
65
|
+
# remove [] if presents e.g. [Neymar 12']
|
66
|
+
line = line.gsub( /[\[\]]/, '' )
|
67
|
+
# remove (single match) if line starts w/ - (allow spaces) e.g. [-;Neymar 12'] or [ - ;Neymar 12']
|
68
|
+
line = line.sub( /^[ ]*-[ ]*/, '' )
|
69
|
+
|
70
|
+
# split into left hand side (lhs) for team1 and
|
71
|
+
# right hand side (rhs) for team2
|
72
|
+
|
73
|
+
values = line.split( ';' )
|
74
|
+
|
75
|
+
# note: allow empty right hand side (e.g. team2 did NOT score any goals e.g. 3-0 etc.)
|
76
|
+
lhs = values[0]
|
77
|
+
rhs = values[1]
|
78
|
+
|
79
|
+
lhs = lhs.strip unless lhs.nil?
|
80
|
+
rhs = rhs.strip unless rhs.nil?
|
81
|
+
|
82
|
+
parser = GoalsParser.new
|
83
|
+
## todo/check: only call if not nil?
|
84
|
+
|
85
|
+
logger.debug " lhs (team1): >#{lhs}<"
|
86
|
+
lhs_data = parser.parse!( lhs )
|
87
|
+
pp lhs_data
|
88
|
+
|
89
|
+
logger.debug " rhs (team2): >#{rhs}<"
|
90
|
+
rhs_data = parser.parse!( rhs )
|
91
|
+
pp rhs_data
|
92
|
+
|
93
|
+
### merge into flat goal structs
|
94
|
+
goals = []
|
95
|
+
lhs_data.each do |player|
|
96
|
+
player.minutes.each do |minute|
|
97
|
+
goal = GoalStruct.new
|
98
|
+
goal.name = player.name
|
99
|
+
goal.team = 1
|
100
|
+
goal.minute = minute.minute
|
101
|
+
goal.offset = minute.offset
|
102
|
+
goal.penalty = minute.penalty
|
103
|
+
goal.owngoal = minute.owngoal
|
104
|
+
goals << goal
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
rhs_data.each do |player|
|
109
|
+
player.minutes.each do |minute|
|
110
|
+
goal = GoalStruct.new
|
111
|
+
goal.name = player.name
|
112
|
+
goal.team = 2
|
113
|
+
goal.minute = minute.minute
|
114
|
+
goal.offset = minute.offset
|
115
|
+
goal.penalty = minute.penalty
|
116
|
+
goal.owngoal = minute.owngoal
|
117
|
+
goals << goal
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
# sort by minute + offset
|
123
|
+
goals = goals.sort do |l,r|
|
124
|
+
res = l.minute <=> r.minute
|
125
|
+
if res == 0
|
126
|
+
res = l.offset <=> r.offset # pass 2: sort by offset
|
127
|
+
end
|
128
|
+
res
|
129
|
+
end
|
130
|
+
|
131
|
+
## calc score1,score2
|
132
|
+
score1 = 0
|
133
|
+
score2 = 0
|
134
|
+
goals.each do |goal|
|
135
|
+
if goal.team == 1
|
136
|
+
score1 += 1
|
137
|
+
elsif goal.team == 2
|
138
|
+
score2 += 1
|
139
|
+
else
|
140
|
+
# todo: should not happen: issue warning
|
141
|
+
end
|
142
|
+
goal.score1 = score1
|
143
|
+
goal.score2 = score2
|
144
|
+
end
|
145
|
+
|
146
|
+
logger.debug " #{goals.size} goals:"
|
147
|
+
pp goals
|
148
|
+
|
149
|
+
goals
|
150
|
+
end
|
151
|
+
|
152
|
+
end # class GoalsFinder
|
153
|
+
|
154
|
+
|
155
|
+
class GoalsParser
|
156
|
+
include LogUtils::Logging
|
157
|
+
|
158
|
+
|
159
|
+
# note: use ^ for start of string only!!!
|
160
|
+
# - for now slurp everything up to digits (inlc. spaces - use strip to remove)
|
161
|
+
# todo/check: use/rename to NAME_UNTIL_REGEX ??? ( add lookahead for spaces?)
|
162
|
+
NAME_REGEX = /^
|
163
|
+
[^0-9]+
|
164
|
+
/x
|
165
|
+
|
166
|
+
|
167
|
+
# todo/check: change to MINUTE_REGEX ??
|
168
|
+
# add MINUTE_SKIP_REGEX or MINUTE_SEP_REGEX /^[ ,]+/
|
169
|
+
# todo/fix: split out penalty and owngoal flag in PATTERN constant for reuse
|
170
|
+
MINUTES_REGEX = /^ # note: use ^ for start of string only!!!
|
171
|
+
(?<minute>[0-9]{1,3})
|
172
|
+
(?:\+
|
173
|
+
(?<offset>[1-9]{1})
|
174
|
+
)?
|
175
|
+
'
|
176
|
+
(?:[ ]*
|
177
|
+
\(
|
178
|
+
(?<type>P|pen\.|o\.g\.)
|
179
|
+
\)
|
180
|
+
)?
|
181
|
+
/x
|
182
|
+
|
183
|
+
|
184
|
+
|
185
|
+
def initialize
|
186
|
+
# nothing here for now
|
187
|
+
end
|
188
|
+
|
189
|
+
def parse!( line, opts={} )
|
190
|
+
|
191
|
+
## for now assume
|
192
|
+
## everything up-to 0-9 and , and () is part of player name
|
193
|
+
|
194
|
+
## try parsing lhs
|
195
|
+
## todo: check for empty - remove (make it same as empty string)
|
196
|
+
|
197
|
+
players = []
|
198
|
+
|
199
|
+
name = get_player_name!( line )
|
200
|
+
while name
|
201
|
+
logger.debug " found player name >#{name}< - remaining >#{line}<"
|
202
|
+
|
203
|
+
player = GoalsPlayerStruct.new
|
204
|
+
player.name = name
|
205
|
+
|
206
|
+
minute_hash = get_minute_hash!( line )
|
207
|
+
while minute_hash
|
208
|
+
logger.debug " found minutes >#{minute_hash.inspect}< - remaining >#{line}<"
|
209
|
+
|
210
|
+
minute = GoalsMinuteStruct.new
|
211
|
+
minute.minute = minute_hash[:minute].to_i
|
212
|
+
minute.offset = minute_hash[:offset].to_i if minute_hash[:offset]
|
213
|
+
if minute_hash[:type]
|
214
|
+
minute.owngoal = true if minute_hash[:type] =~ /o\.g\./
|
215
|
+
minute.penalty = true if minute_hash[:type] =~ /P|pen\./
|
216
|
+
end
|
217
|
+
player.minutes << minute
|
218
|
+
|
219
|
+
# remove commas and spaces (note: use ^ for start of string only!!!)
|
220
|
+
line.sub!( /^[ ,]+/, '' )
|
221
|
+
minute_hash = get_minute_hash!( line )
|
222
|
+
end
|
223
|
+
|
224
|
+
players << player
|
225
|
+
name = get_player_name!( line )
|
226
|
+
end
|
227
|
+
|
228
|
+
players
|
229
|
+
end # method parse!
|
230
|
+
|
231
|
+
private
|
232
|
+
def get_player_name!( line )
|
233
|
+
m = NAME_REGEX.match( line )
|
234
|
+
if m
|
235
|
+
## remove from line
|
236
|
+
line.slice!( 0...m[0].length )
|
237
|
+
m[0].strip # remove leading and trailing spaces
|
238
|
+
else
|
239
|
+
nil
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def get_minute_hash!( line )
|
244
|
+
m = MINUTES_REGEX.match( line ) # note: use ^ for start of string only!!!
|
245
|
+
if m
|
246
|
+
h = {}
|
247
|
+
# - note: do NOT forget to turn name into symbol for lookup in new hash (name.to_sym)
|
248
|
+
m.names.each { |n| h[n.to_sym] = m[n] } # or use match_data.names.zip( match_data.captures ) - more cryptic but "elegant"??
|
249
|
+
|
250
|
+
## remove matched string from line
|
251
|
+
line.slice!( 0...m[0].length )
|
252
|
+
h
|
253
|
+
else
|
254
|
+
nil
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
end # class GoalsParser
|
259
|
+
|
260
|
+
end # module SportDb
|
data/lib/sportdb/models/game.rb
CHANGED
@@ -14,7 +14,7 @@ class Game < ActiveRecord::Base
|
|
14
14
|
belongs_to :ground # ground is optional
|
15
15
|
belongs_to :city, class_name: 'WorldDb::Model::City', foreign_key: 'city_id' # city is optioanl (remove?? redundant?? use ground ??)
|
16
16
|
|
17
|
-
has_many :goals
|
17
|
+
has_many :goals, :dependent => :delete_all
|
18
18
|
|
19
19
|
|
20
20
|
before_save :calc_winner
|
data/lib/sportdb/readers/game.rb
CHANGED
@@ -109,6 +109,10 @@ class GameReader
|
|
109
109
|
@group = nil ## fix: change/rename to @last_group !!!
|
110
110
|
@last_date = nil
|
111
111
|
|
112
|
+
@last_team1 = nil # used for goals (to match players via squads)
|
113
|
+
@last_team2 = nil
|
114
|
+
@last_game = nil
|
115
|
+
|
112
116
|
|
113
117
|
#####
|
114
118
|
# fix: move to read and share event/known_teams
|
@@ -429,6 +433,9 @@ class GameReader
|
|
429
433
|
team1 = Team.find_by_key!( team1_key )
|
430
434
|
team2 = Team.find_by_key!( team2_key )
|
431
435
|
|
436
|
+
@last_team1 = team1 # store for later use for goals etc.
|
437
|
+
@last_team2 = team2
|
438
|
+
|
432
439
|
|
433
440
|
if @round.nil?
|
434
441
|
## no round header found; calculate round from date
|
@@ -556,6 +563,8 @@ class GameReader
|
|
556
563
|
logger.debug game_attribs.to_json
|
557
564
|
game.update_attributes!( game_attribs )
|
558
565
|
end
|
566
|
+
|
567
|
+
@last_game = game # store for later reference (e.g. used for goals etc.)
|
559
568
|
|
560
569
|
return true # game match found
|
561
570
|
end # method parse_game
|
@@ -594,12 +603,126 @@ class GameReader
|
|
594
603
|
end
|
595
604
|
|
596
605
|
|
606
|
+
def parse_goals( line )
|
607
|
+
logger.debug "parsing goals (fixture) line: >#{line}<"
|
608
|
+
|
609
|
+
goals = GoalsFinder.new.find!( line )
|
610
|
+
|
611
|
+
## check if squads/rosters present for player mappings
|
612
|
+
#
|
613
|
+
squad1_count = Roster.where( event_id: @event.id, team_id: @last_team1 ).count
|
614
|
+
if squad1_count > 0
|
615
|
+
squad1 = Roster.where( event_id: @event.id, team_id: @last_team1 )
|
616
|
+
else
|
617
|
+
squad1 = []
|
618
|
+
end
|
619
|
+
|
620
|
+
squad2_count = Roster.where( event_id: @event.id, team_id: @last_team2 ).count
|
621
|
+
if squad2_count > 0
|
622
|
+
squad2 = Roster.where( event_id: @event.id, team_id: @last_team2 )
|
623
|
+
else
|
624
|
+
squad2 = []
|
625
|
+
end
|
626
|
+
|
627
|
+
#####
|
628
|
+
# todo/fix: try lookup by squads first!!!
|
629
|
+
# issue warning if player not included in squad!!
|
630
|
+
|
631
|
+
##########
|
632
|
+
# try mapping player names to player
|
633
|
+
|
634
|
+
## note: first delete all goals for match (and recreate new ones
|
635
|
+
# no need to figure out update/merge strategy)
|
636
|
+
@last_game.goals.delete_all
|
637
|
+
|
638
|
+
|
639
|
+
goals.each do |goal|
|
640
|
+
player_name = goal.name
|
641
|
+
|
642
|
+
player = Person.where( name: player_name ).first
|
643
|
+
if player
|
644
|
+
logger.info " player match (name eq) - using player key #{player.key}"
|
645
|
+
else
|
646
|
+
# try like match (player name might only include part of name e.g. Messi)
|
647
|
+
# try three variants
|
648
|
+
# try %Messi
|
649
|
+
# try Messi%
|
650
|
+
# try %Messi% -- check if there's an easier way w/ "one" where clause?
|
651
|
+
player = Person.where( 'name LIKE ? OR name LIKE ? OR name LIKE ?',
|
652
|
+
"%#{player_name}",
|
653
|
+
"#{player_name}%",
|
654
|
+
"%#{player_name}%"
|
655
|
+
).first
|
656
|
+
|
657
|
+
if player
|
658
|
+
logger.info " player match (name like) - using player key #{player.key}"
|
659
|
+
else
|
660
|
+
# try synonyms
|
661
|
+
player = Person.where( 'synonyms LIKE ? OR synonyms LIKE ? OR synonyms LIKE ?',
|
662
|
+
"%#{player_name}",
|
663
|
+
"#{player_name}%",
|
664
|
+
"%#{player_name}%"
|
665
|
+
).first
|
666
|
+
if player
|
667
|
+
logger.info " player match (synonyms like) - using player key #{player.key}"
|
668
|
+
else
|
669
|
+
# auto-create player (player not found)
|
670
|
+
logger.info " player NOT found >#{player_name}< - auto-create"
|
671
|
+
|
672
|
+
## fix: add auto flag (for auto-created persons/players)
|
673
|
+
## fix: move title_to_key logic to person model etc.
|
674
|
+
player_key = TextUtils.title_to_key( player_name )
|
675
|
+
player_attribs = {
|
676
|
+
key: player_key,
|
677
|
+
title: player_name
|
678
|
+
}
|
679
|
+
logger.info " using attribs: #{player_attribs.inspect}"
|
680
|
+
|
681
|
+
player = Person.create!( player_attribs )
|
682
|
+
end
|
683
|
+
end
|
684
|
+
end
|
685
|
+
|
686
|
+
goal_attribs = {
|
687
|
+
game_id: @last_game.id,
|
688
|
+
team_id: goal.team == 1 ? @last_team1.id : @last_team2.id,
|
689
|
+
person_id: player.id,
|
690
|
+
minute: goal.minute,
|
691
|
+
offset: goal.offset,
|
692
|
+
penalty: goal.penalty,
|
693
|
+
owngoal: goal.owngoal,
|
694
|
+
score1: goal.score1,
|
695
|
+
score2: goal.score2
|
696
|
+
}
|
697
|
+
|
698
|
+
logger.info " adding goal using attribs: #{goal_attribs.inspect}"
|
699
|
+
Goal.create!( goal_attribs )
|
700
|
+
end # each goals
|
701
|
+
|
702
|
+
end # method parse_goals
|
703
|
+
|
704
|
+
|
705
|
+
=begin
|
706
|
+
###### add to person and use!!!
|
707
|
+
def self.create_or_update_from_values( values, more_attribs={} )
|
708
|
+
## key & title required
|
709
|
+
|
710
|
+
attribs, more_values = find_key_n_title( values )
|
711
|
+
attribs = attribs.merge( more_attribs )
|
712
|
+
|
713
|
+
## check for optional values
|
714
|
+
Person.create_or_update_from_attribs( attribs, more_values )
|
715
|
+
end
|
716
|
+
=end
|
717
|
+
|
597
718
|
|
598
719
|
def parse_fixtures( reader )
|
599
720
|
|
600
721
|
reader.each_line do |line|
|
601
722
|
|
602
|
-
if
|
723
|
+
if is_goals?( line )
|
724
|
+
parse_goals( line )
|
725
|
+
elsif is_round_def?( line )
|
603
726
|
## todo/fix: add round definition (w begin n end date)
|
604
727
|
## todo: do not patch rounds with definition (already assume begin/end date is good)
|
605
728
|
## -- how to deal with matches that get rescheduled/postponed?
|
data/lib/sportdb/schema.rb
CHANGED
@@ -60,8 +60,11 @@ add_index :grounds, :key, unique: true
|
|
60
60
|
create_table :goals do |t|
|
61
61
|
t.references :person, null: false
|
62
62
|
t.references :game, null: false
|
63
|
+
t.references :team, null: false ## use integer instead w/ values 1 or 2 for team1 or team2 ?? why? why not?
|
64
|
+
|
63
65
|
t.integer :minute
|
64
|
-
t.integer :offset # e.g. 45' +3 or 90' +2
|
66
|
+
t.integer :offset, null: false, default: 0 # e.g. 45' +3 or 90' +2
|
67
|
+
|
65
68
|
t.integer :score1
|
66
69
|
t.integer :score2
|
67
70
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SportDb
|
4
|
+
module FixtureHelpers
|
5
|
+
|
6
|
+
def is_goals?( line )
|
7
|
+
# check if is goals line
|
8
|
+
# e.g. looks like
|
9
|
+
# Neymar 29', 71' (pen.) Oscar 90+1'; Marcelo 11' (o.g.)
|
10
|
+
# check for
|
11
|
+
# <space>90' or
|
12
|
+
# <space>90+1'
|
13
|
+
|
14
|
+
line =~ /[ ](\d{1,3}\+)?\d{1,3}'/
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
end # module FixtureHelpers
|
19
|
+
end # module SportDb
|
20
|
+
|
data/lib/sportdb/version.rb
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
##############################################
|
2
|
+
# World Cup 1930 Uruguay, 13 July - 30 July
|
3
|
+
|
4
|
+
|
5
|
+
Group 1 | Argentina Chile France Mexico
|
6
|
+
Group 2 | Yugoslavia Brazil Bolivia
|
7
|
+
Group 3 | Uruguay Romania Peru
|
8
|
+
Group 4 | United States Paraguay Belgium
|
9
|
+
|
10
|
+
|
11
|
+
Matchday 1 | 13 July
|
12
|
+
Matchday 2 | 14 July
|
13
|
+
Matchday 3 | 15 July
|
14
|
+
Matchday 4 | 16 July
|
15
|
+
Matchday 5 | 17 July
|
16
|
+
Matchday 6 | 18 July
|
17
|
+
Matchday 7 | 19 July
|
18
|
+
Matchday 8 | 20 July
|
19
|
+
Matchday 9 | 21 July
|
20
|
+
Matchday 10 | 22 July
|
21
|
+
|
22
|
+
### - test auto-numbering (do NOTE predefine)
|
23
|
+
## (11) Semi-finals | 26 July - 27 July
|
24
|
+
## (12) Final | 30 July
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
Group 1:
|
29
|
+
|
30
|
+
(1) 13 July France 4-1 Mexico @ Estadio Pocitos, Montevideo
|
31
|
+
[L. Laurent 19' Langiller 40' Maschinot 43', 87'; Carreño 70']
|
32
|
+
|
33
|
+
(5) 15 July Argentina 1-0 France @ Estadio Parque Central, Montevideo
|
34
|
+
[Monti 81']
|
35
|
+
|
36
|
+
(6) 16 July Chile 3-0 Mexico @ Estadio Parque Central, Montevideo
|
37
|
+
[Vidal 3', 65' M. Rosas 51' (o.g.)]
|
38
|
+
|
39
|
+
(10) 19 July Chile 1-0 France @ Estadio Centenario, Montevideo
|
40
|
+
[Subiabre 65']
|
41
|
+
|
42
|
+
(11) 19 July Argentina 6-3 Mexico @ Estadio Centenario, Montevideo
|
43
|
+
[Stábile 8', 17', 80' Zumelzú 12', 55' Varallo 53'; M. Rosas 42' (pen.), 65' Gayón 75']
|
44
|
+
|
45
|
+
(15) 22 July Argentina 3-1 Chile @ Estadio Centenario, Montevideo
|
46
|
+
[Stábile 12', 13' M. Evaristo 81'; Subiabre 15']
|
47
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
##############################################
|
2
|
+
# World Cup 1930 Uruguay, 13 July - 30 July
|
3
|
+
|
4
|
+
league: world
|
5
|
+
season: 1930
|
6
|
+
start_at: 1930-07-13
|
7
|
+
|
8
|
+
# 13 Teams
|
9
|
+
|
10
|
+
teams:
|
11
|
+
- arg # Argentina
|
12
|
+
- bra # Brazil
|
13
|
+
- bol # Bolivia
|
14
|
+
- chi # Chile
|
15
|
+
- uru # Uruguay
|
16
|
+
- per # Peru
|
17
|
+
- par # Paraguay
|
18
|
+
- mex # Mexico
|
19
|
+
- usa # United States
|
20
|
+
- fra # France
|
21
|
+
- yug # Yugoslavia (-2003)
|
22
|
+
- bel # Belgium
|
23
|
+
- rou # Romania
|
data/test/test_goals.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
###
|
4
|
+
# to run use
|
5
|
+
# ruby -I ./lib -I ./test test/test_goals.rb
|
6
|
+
# or better
|
7
|
+
# rake -I ./lib test
|
8
|
+
|
9
|
+
|
10
|
+
require 'helper'
|
11
|
+
|
12
|
+
class TestGoals < MiniTest::Unit::TestCase
|
13
|
+
|
14
|
+
def setup
|
15
|
+
WorldDb.delete!
|
16
|
+
SportDb.delete!
|
17
|
+
## SportDb.read_builtin
|
18
|
+
|
19
|
+
add_countries
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_countries
|
23
|
+
countries = [
|
24
|
+
['cd', 'Congo DR', 'COD' ],
|
25
|
+
['kr', 'South Korea', 'KOR' ],
|
26
|
+
['au', 'Australia', 'AUS' ],
|
27
|
+
|
28
|
+
['ar', 'Argentina', 'ARG' ],
|
29
|
+
['br', 'Brazil', 'BRA' ],
|
30
|
+
['bo', 'Bolivia', 'BOL' ],
|
31
|
+
['cl', 'Chile', 'CHI' ],
|
32
|
+
['co', 'Colombia', 'COL' ],
|
33
|
+
['uy', 'Uruguay', 'URU' ],
|
34
|
+
['pe', 'Peru', 'PER' ],
|
35
|
+
['py', 'Paraguay', 'PAR' ],
|
36
|
+
|
37
|
+
['mx', 'Mexico', 'MEX' ],
|
38
|
+
['us', 'United States', 'USA' ],
|
39
|
+
['ht', 'Haiti', 'HAI' ],
|
40
|
+
|
41
|
+
['at', 'Austria', 'AUT' ],
|
42
|
+
['be', 'Belgium', 'BEL' ],
|
43
|
+
['fr', 'France', 'FRA' ],
|
44
|
+
['rs', 'Serbia', 'SRB' ],
|
45
|
+
['ro', 'Romania', 'ROU' ],
|
46
|
+
['bg', 'Bulgaria', 'BUL' ],
|
47
|
+
['cz', 'Czech Republic', 'CZE' ],
|
48
|
+
['en', 'England', 'ENG' ],
|
49
|
+
['de', 'Germany', 'GER' ],
|
50
|
+
['hu', 'Hungary', 'HUN' ],
|
51
|
+
['it', 'Italy', 'ITA' ],
|
52
|
+
['ru', 'Russia', 'RUS' ],
|
53
|
+
['es', 'Spain', 'ESP' ],
|
54
|
+
['ch', 'Switzerland', 'SUI' ],
|
55
|
+
['sc', 'Scotland', 'SCO' ],
|
56
|
+
['tr', 'Turkey', 'TUR' ],
|
57
|
+
['nl', 'Netherlands', 'NED' ],
|
58
|
+
['pl', 'Poland', 'POL' ],
|
59
|
+
['se', 'Sweden', 'SWE' ],
|
60
|
+
]
|
61
|
+
|
62
|
+
countries.each do |country|
|
63
|
+
key = country[0]
|
64
|
+
name = country[1]
|
65
|
+
code = country[2]
|
66
|
+
Country.create!( key: key, name: name, code: code, pop: 1, area: 1)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def test_world_cup_1930
|
72
|
+
teamreader = TeamReader.new( SportDb.test_data_path )
|
73
|
+
teamreader.read( 'world-cup/teams_1930' )
|
74
|
+
|
75
|
+
assert_equal 13, Team.count
|
76
|
+
|
77
|
+
seasonreader = SeasonReader.new( SportDb.test_data_path )
|
78
|
+
seasonreader.read( 'world-cup/seasons_1930')
|
79
|
+
|
80
|
+
assert_equal 1, Season.count
|
81
|
+
|
82
|
+
y = Season.find_by_key!( '1930' )
|
83
|
+
assert_equal '1930', y.title
|
84
|
+
|
85
|
+
|
86
|
+
leaguereader = LeagueReader.new( SportDb.test_data_path )
|
87
|
+
leaguereader.read( 'world-cup/leagues' )
|
88
|
+
|
89
|
+
assert_equal 1, League.count
|
90
|
+
|
91
|
+
l = League.find_by_key!( 'world' )
|
92
|
+
assert_equal 'World Cup', l.title
|
93
|
+
|
94
|
+
|
95
|
+
gamereader = GameReader.new( SportDb.test_data_path )
|
96
|
+
gamereader.read( 'world-cup/1930/cup_goals' )
|
97
|
+
|
98
|
+
assert_equal 1, Event.count
|
99
|
+
|
100
|
+
w = Event.find_by_key!( 'world.1930' )
|
101
|
+
|
102
|
+
assert_equal 13, w.teams.count
|
103
|
+
## assert_equal 18, w.games.count
|
104
|
+
## assert_equal 12, w.rounds.count
|
105
|
+
|
106
|
+
end # method test_world_cup_1930
|
107
|
+
|
108
|
+
|
109
|
+
end # class TestGoals
|
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.9.
|
4
|
+
version: 1.9.2
|
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: 2014-06-
|
12
|
+
date: 2014-06-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: props
|
16
|
-
requirement: &
|
16
|
+
requirement: &72505740 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *72505740
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: logutils
|
27
|
-
requirement: &
|
27
|
+
requirement: &72505490 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *72505490
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: textutils
|
38
|
-
requirement: &
|
38
|
+
requirement: &72505260 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *72505260
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: worlddb
|
49
|
-
requirement: &
|
49
|
+
requirement: &72521250 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 2.0.2
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *72521250
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: tagutils
|
60
|
-
requirement: &
|
60
|
+
requirement: &72520820 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *72520820
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: persondb
|
71
|
-
requirement: &
|
71
|
+
requirement: &72520360 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *72520360
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: activerecord-utils
|
82
|
-
requirement: &
|
82
|
+
requirement: &72519880 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *72519880
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: fetcher
|
93
|
-
requirement: &
|
93
|
+
requirement: &72518680 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0.3'
|
99
99
|
type: :runtime
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *72518680
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: gli
|
104
|
-
requirement: &
|
104
|
+
requirement: &72517660 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: 2.5.6
|
110
110
|
type: :runtime
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *72517660
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: activerecord
|
115
|
-
requirement: &
|
115
|
+
requirement: &72516940 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ! '>='
|
@@ -120,10 +120,10 @@ dependencies:
|
|
120
120
|
version: '0'
|
121
121
|
type: :runtime
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *72516940
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: rdoc
|
126
|
-
requirement: &
|
126
|
+
requirement: &72516180 !ruby/object:Gem::Requirement
|
127
127
|
none: false
|
128
128
|
requirements:
|
129
129
|
- - ~>
|
@@ -131,10 +131,10 @@ dependencies:
|
|
131
131
|
version: '4.0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
|
-
version_requirements: *
|
134
|
+
version_requirements: *72516180
|
135
135
|
- !ruby/object:Gem::Dependency
|
136
136
|
name: hoe
|
137
|
-
requirement: &
|
137
|
+
requirement: &72514980 !ruby/object:Gem::Requirement
|
138
138
|
none: false
|
139
139
|
requirements:
|
140
140
|
- - ~>
|
@@ -142,7 +142,7 @@ dependencies:
|
|
142
142
|
version: '3.11'
|
143
143
|
type: :development
|
144
144
|
prerelease: false
|
145
|
-
version_requirements: *
|
145
|
+
version_requirements: *72514980
|
146
146
|
description: sportdb - sport.db command line tool
|
147
147
|
email: opensport@googlegroups.com
|
148
148
|
executables:
|
@@ -176,6 +176,7 @@ files:
|
|
176
176
|
- lib/sportdb/data/models.rb
|
177
177
|
- lib/sportdb/deleter.rb
|
178
178
|
- lib/sportdb/finders/date.rb
|
179
|
+
- lib/sportdb/finders/goals.rb
|
179
180
|
- lib/sportdb/finders/scores.rb
|
180
181
|
- lib/sportdb/lang.rb
|
181
182
|
- lib/sportdb/matcher.rb
|
@@ -244,6 +245,7 @@ files:
|
|
244
245
|
- lib/sportdb/updater.rb
|
245
246
|
- lib/sportdb/utils.rb
|
246
247
|
- lib/sportdb/utils_date.rb
|
248
|
+
- lib/sportdb/utils_goals.rb
|
247
249
|
- lib/sportdb/utils_group.rb
|
248
250
|
- lib/sportdb/utils_map.rb
|
249
251
|
- lib/sportdb/utils_record.rb
|
@@ -269,6 +271,8 @@ files:
|
|
269
271
|
- test/data/players/south-america/br-brazil/players.txt
|
270
272
|
- test/data/world-cup/1930/cup.txt
|
271
273
|
- test/data/world-cup/1930/cup.yml
|
274
|
+
- test/data/world-cup/1930/cup_goals.txt
|
275
|
+
- test/data/world-cup/1930/cup_goals.yml
|
272
276
|
- test/data/world-cup/1954/cup.txt
|
273
277
|
- test/data/world-cup/1954/cup.yml
|
274
278
|
- test/data/world-cup/1962/cup.txt
|
@@ -295,6 +299,7 @@ files:
|
|
295
299
|
- test/test_changes.rb
|
296
300
|
- test/test_cursor.rb
|
297
301
|
- test/test_date.rb
|
302
|
+
- test/test_goals.rb
|
298
303
|
- test/test_lang.rb
|
299
304
|
- test/test_load.rb
|
300
305
|
- test/test_national_team_reader.rb
|
@@ -359,6 +364,7 @@ test_files:
|
|
359
364
|
- test/test_round_header.rb
|
360
365
|
- test/test_round_auto.rb
|
361
366
|
- test/test_national_team_reader.rb
|
367
|
+
- test/test_goals.rb
|
362
368
|
- test/test_reader.rb
|
363
369
|
- test/test_assoc_reader.rb
|
364
370
|
- test/test_changes.rb
|