sportdb-importers 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Manifest.txt +2 -1
- data/lib/sportdb/importers.rb +91 -32
- data/lib/sportdb/importers/{import.rb → event.rb} +0 -2
- data/lib/sportdb/importers/match.rb +96 -0
- data/lib/sportdb/importers/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a504f73f34a5e73bb311ee460402b068056d68d
|
4
|
+
data.tar.gz: b8680b47ec3c06958ac8f6718261873521314998
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c0ea550c7450f524d0314e55365b221841e95c6c5794681ec1b34c5d27cdb721bd0a4408b69ade5e751a76d88a0fddbcdc58bbe1644f5d644ae925311bdec3f
|
7
|
+
data.tar.gz: 358bdd2d3872ff3b80d9916293c9bf372f581ebaf2e0c14de370a80983bb74148acba97b6baa1b0072b59da796c1ba3849d5bc5279c519111a011a46f4fd007f
|
data/Manifest.txt
CHANGED
data/lib/sportdb/importers.rb
CHANGED
@@ -8,37 +8,20 @@ require 'sportdb/sync'
|
|
8
8
|
###
|
9
9
|
# our own code
|
10
10
|
require 'sportdb/importers/version' # let version always go first
|
11
|
-
require 'sportdb/importers/
|
11
|
+
require 'sportdb/importers/event'
|
12
|
+
require 'sportdb/importers/match'
|
12
13
|
|
13
14
|
|
14
15
|
module SportDb
|
15
16
|
class Package
|
16
17
|
## (re)open class - note: adds more machinery; see sportdb-text for first/original/base definition
|
17
18
|
|
18
|
-
def read_csv( start: nil )
|
19
|
+
def read_csv( start: nil )
|
19
20
|
## start - season e.g. 1993/94 to start (skip older seasons)
|
20
21
|
## note: assume package holds country/national (club) league
|
21
22
|
# use for importing german bundesliga, english premier league, etc.
|
22
23
|
|
23
|
-
|
24
|
-
puts "season [#{i+1}] >#{season_key}<:"
|
25
|
-
|
26
|
-
entries.each do |entry,j|
|
27
|
-
## note: assume datafile basename (without extension) is the league key
|
28
|
-
## e.g. eng.1, eng.3a, eng.3b, at.1, champs, world, etc.
|
29
|
-
league_key = File.basename( entry.name, File.extname( entry.name ) ) ## get basename WITHOUT extension
|
30
|
-
|
31
|
-
pp [entry.name, season_key, league_key]
|
32
|
-
|
33
|
-
event = CsvEventImporter.parse( entry.read, league: league_key,
|
34
|
-
season: season_key )
|
35
|
-
|
36
|
-
puts "added #{event.name} - from source >#{entry.name}<"
|
37
|
-
puts " #{event.teams.size} teams"
|
38
|
-
puts " #{event.matches.size} matches"
|
39
|
-
puts " #{event.rounds.size} rounds"
|
40
|
-
end # each datafile
|
41
|
-
end # each season
|
24
|
+
each_csv { |entry| SportDb.handle_csv( entry, start: start ) }
|
42
25
|
end # method import
|
43
26
|
|
44
27
|
end # class Package
|
@@ -50,25 +33,101 @@ end # class Package
|
|
50
33
|
def self.read_csv( path )
|
51
34
|
if File.directory?( path ) ## if directory assume "unzipped" package
|
52
35
|
DirPackage.new( path ).read_csv
|
53
|
-
elsif File.file?( path ) && File.extname( path ) == '.zip' ## check if file is a .zip (archive) file
|
36
|
+
elsif File.file?( path ) && File.extname( path ).downcase == '.zip' ## check if file is a .zip (archive) file
|
54
37
|
ZipPackage.new( path ).read_csv
|
55
38
|
else ## no package; assume single (standalone) datafile
|
56
39
|
## assume single (free-standing) file
|
40
|
+
handle_csv( path )
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
##################
|
45
|
+
### helper
|
46
|
+
## move handle_csv somewhere else - why? why not?
|
47
|
+
def self.handle_csv( source, start: nil )
|
48
|
+
## todo/fix: (re)use a more generic filter instead of start for start of season only
|
49
|
+
|
50
|
+
## todo/fix: use a "generic" filter_season helper for easy reuse
|
51
|
+
## filter_season( clause, season_key )
|
52
|
+
## or better filter = SeasonFilter.new( clause )
|
53
|
+
## filter.skip? filter.include? ( season_sason_key )?
|
54
|
+
## fiteer.before?( season_key ) etc.
|
55
|
+
## find some good method names!!!!
|
56
|
+
season_start = start ? Import::Season.new( start ) : nil
|
57
|
+
|
58
|
+
if source.is_a?( Datafile::DirPackage::Entry) ||
|
59
|
+
source.is_a?( Datafile::ZipPackage::Entry)
|
60
|
+
entry = source
|
61
|
+
|
62
|
+
basename = File.basename( entry.name, File.extname( entry.name ) ) ## get basename WITHOUT extension
|
63
|
+
|
64
|
+
## check if basename is all numbers (and _-) e.g. 2020.csv or 20.csv etc.
|
65
|
+
## if yes, assume "mixed" match datafiles (with many/mixed leagues)
|
66
|
+
if basename =~ /^[0-9_-]+$/
|
67
|
+
pp [entry.name, basename]
|
68
|
+
|
69
|
+
CsvMatchImporter.parse( entry.read )
|
70
|
+
else ## assume "classic" with season
|
71
|
+
league_key = basename
|
72
|
+
|
73
|
+
## todo/fix: check if season_key is proper season - e.g. matches pattern !!!!
|
74
|
+
season_q = File.basename( File.dirname( entry.name ))
|
75
|
+
season = Import::Season.new( season_q ) ## normalize season
|
76
|
+
season_key = season.key
|
77
|
+
|
78
|
+
if season_start && season_start.start_year > season.start_year
|
79
|
+
## skip if start season before this season
|
80
|
+
else
|
81
|
+
pp [entry.name, season_key, league_key]
|
82
|
+
|
83
|
+
event = CsvEventImporter.parse( entry.read, league: league_key,
|
84
|
+
season: season_key )
|
85
|
+
|
86
|
+
puts "added #{event.name} - from source >#{entry.name}<"
|
87
|
+
puts " #{event.teams.size} teams"
|
88
|
+
puts " #{event.matches.size} matches"
|
89
|
+
puts " #{event.rounds.size} rounds"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
else ## assume (string) filepath for now - add more options later on!!!!
|
93
|
+
## assume single (free-standing) file
|
94
|
+
path = source
|
57
95
|
full_path = File.expand_path( path ) ## resolve/make path absolute
|
58
96
|
## 1) assume basename is the league key
|
59
97
|
## 2) assume last directory is the season key
|
60
|
-
league_key = File.basename( full_path, File.extname( full_path ) ) ## get basename WITHOUT extension
|
61
|
-
season_key = File.basename( File.dirname( full_path ) )
|
62
|
-
|
63
|
-
event = CsvEventImporter.read( full_path, league: league_key,
|
64
|
-
season: season_key )
|
65
98
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
99
|
+
basename = File.basename( full_path, File.extname( full_path ) ) ## get basename WITHOUT extension
|
100
|
+
if basename =~ /^[0-9_-]+$/
|
101
|
+
pp [path, basename]
|
102
|
+
CsvMatchImporter.read( full_path )
|
103
|
+
else ## assume "classic" with season
|
104
|
+
## 1) assume basename is the league key
|
105
|
+
## 2) assume last directory is the season key
|
106
|
+
league_key = basename
|
107
|
+
|
108
|
+
season_q = File.basename( File.dirname( full_path ) )
|
109
|
+
season = Import::Season.new( season_q ) ## normalize season
|
110
|
+
season_key = season.key
|
111
|
+
|
112
|
+
if season_start && season_start.start_year > season.start_year
|
113
|
+
## skip if start season before this season
|
114
|
+
else
|
115
|
+
## todo/fix: check if season_key is proper season - e.g. matches pattern !!!!
|
116
|
+
pp [path, season_key, league_key]
|
117
|
+
|
118
|
+
event = CsvEventImporter.read( full_path, league: league_key,
|
119
|
+
season: season_key )
|
120
|
+
|
121
|
+
puts "added #{event.name} - from source >#{path}<"
|
122
|
+
puts " #{event.teams.size} teams"
|
123
|
+
puts " #{event.matches.size} matches"
|
124
|
+
puts " #{event.rounds.size} rounds"
|
125
|
+
end
|
126
|
+
end
|
70
127
|
end
|
71
|
-
end
|
128
|
+
end # method self.handle_csv
|
129
|
+
|
130
|
+
|
72
131
|
end # module SportDb
|
73
132
|
|
74
133
|
|
@@ -0,0 +1,96 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module SportDb
|
4
|
+
class CsvMatchImporter
|
5
|
+
|
6
|
+
def self.read( path, headers: nil )
|
7
|
+
txt = File.open( path, 'r:utf-8' ) {|f| f.read }
|
8
|
+
parse( txt, headers: headers )
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.parse( txt, headers: nil )
|
12
|
+
new( txt, headers: headers ).parse
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def initialize( txt, headers: nil )
|
17
|
+
@txt = txt
|
18
|
+
@headers = headers
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def parse
|
23
|
+
## todo/fix: add headers options (pass throughto CsvMatchReader)
|
24
|
+
## add filters too why? why not?
|
25
|
+
|
26
|
+
## todo/fix:
|
27
|
+
## add normalize: false/mapping: false flag for NOT mapping club/team names
|
28
|
+
## make normalize: false the default, anyways - why? why not?
|
29
|
+
opts = {}
|
30
|
+
opts[:headers] = @headers if @headers
|
31
|
+
|
32
|
+
matches = CsvMatchParser.parse( @txt, **opts )
|
33
|
+
|
34
|
+
matches.each do |match|
|
35
|
+
league = Import.catalog.leagues.find!( match.league )
|
36
|
+
# pp league
|
37
|
+
|
38
|
+
team1 = Import.catalog.teams.find_by!( name: match.team1, league: league )
|
39
|
+
team2 = Import.catalog.teams.find_by!( name: match.team2, league: league )
|
40
|
+
|
41
|
+
date = Date.strptime( match.date, '%Y-%m-%d' )
|
42
|
+
## quick hack - for now always use 2019/20 style season
|
43
|
+
## fix!!! - use league to find proper season e.g. 2019 or 2019/20 etc.
|
44
|
+
|
45
|
+
start_year = if date.month >= 7
|
46
|
+
date.year
|
47
|
+
else
|
48
|
+
date.year-1
|
49
|
+
end
|
50
|
+
|
51
|
+
## note: for now always assume 2019/20 season
|
52
|
+
season = Import::Season.new( '%d/%d' % [start_year, (start_year+1)%100] )
|
53
|
+
# pp season
|
54
|
+
|
55
|
+
|
56
|
+
event_rec = Sync::Event.find_or_create_by( league: league,
|
57
|
+
season: season )
|
58
|
+
|
59
|
+
team1_rec = Sync::Team.find_or_create( team1 )
|
60
|
+
team2_rec = Sync::Team.find_or_create( team2 )
|
61
|
+
|
62
|
+
## warn about duplicates?
|
63
|
+
## note: for now only allow one (unique) match pair per team
|
64
|
+
match_recs = Model::Match.where( event_id: event_rec.id,
|
65
|
+
team1_id: team1_rec.id,
|
66
|
+
team2_id: team2_rec.id ).to_a
|
67
|
+
if match_recs.size > 0
|
68
|
+
puts "!! #{match_recs.size} duplicate match record(s) found:"
|
69
|
+
pp match_recs
|
70
|
+
exit 1
|
71
|
+
end
|
72
|
+
|
73
|
+
## find last pos - check if it can be nil? yes, is nil if no records found
|
74
|
+
max_pos = Model::Match.where( event_id: event_rec.id ).maximum( 'pos' )
|
75
|
+
max_pos = max_pos ? max_pos+1 : 1
|
76
|
+
|
77
|
+
rec = Model::Match.create!(
|
78
|
+
event_id: event_rec.id,
|
79
|
+
team1_id: team1_rec.id,
|
80
|
+
team2_id: team2_rec.id,
|
81
|
+
## round_id: round_rec.id, -- note: now optional
|
82
|
+
pos: max_pos,
|
83
|
+
date: date.to_date,
|
84
|
+
score1: match.score1,
|
85
|
+
score2: match.score2,
|
86
|
+
score1i: match.score1i,
|
87
|
+
score2i: match.score2i )
|
88
|
+
|
89
|
+
## todo/fix:
|
90
|
+
## check if event includes teams?
|
91
|
+
## if not (auto-)add teams to event.teams !!!!!!!
|
92
|
+
end
|
93
|
+
end # method parse
|
94
|
+
|
95
|
+
end # class CsvEventImporter
|
96
|
+
end # module SportDb
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sportdb-importers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
@@ -67,7 +67,8 @@ files:
|
|
67
67
|
- README.md
|
68
68
|
- Rakefile
|
69
69
|
- lib/sportdb/importers.rb
|
70
|
-
- lib/sportdb/importers/
|
70
|
+
- lib/sportdb/importers/event.rb
|
71
|
+
- lib/sportdb/importers/match.rb
|
71
72
|
- lib/sportdb/importers/version.rb
|
72
73
|
- test/helper.rb
|
73
74
|
- test/test_club.rb
|