sportdb-writers 0.1.1 → 0.2.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/Manifest.txt +9 -10
- data/bin/fbgen +1 -87
- data/bin/fbtxt +1 -36
- data/config/leagues_america.csv +6 -0
- data/config/leagues_europe.csv +94 -0
- data/config/leagues_world.csv +4 -0
- data/config/openfootball.csv +52 -0
- data/lib/sportdb/fbgen/github.rb +83 -0
- data/lib/sportdb/fbgen/github_config.rb +97 -0
- data/lib/sportdb/fbgen/main.rb +211 -0
- data/lib/sportdb/fbtxt/main.rb +37 -0
- data/lib/sportdb/writers/league_config.rb +83 -0
- data/lib/sportdb/writers/txt_writer.rb +108 -4
- data/lib/sportdb/writers/version.rb +2 -2
- data/lib/sportdb/writers/write.rb +11 -8
- data/lib/sportdb/writers.rb +60 -13
- metadata +11 -12
- data/lib/sportdb/leagues/leagues_at.rb +0 -35
- data/lib/sportdb/leagues/leagues_de.rb +0 -21
- data/lib/sportdb/leagues/leagues_eng.rb +0 -58
- data/lib/sportdb/leagues/leagues_es.rb +0 -15
- data/lib/sportdb/leagues/leagues_europe.rb +0 -185
- data/lib/sportdb/leagues/leagues_it.rb +0 -16
- data/lib/sportdb/leagues/leagues_mx.rb +0 -23
- data/lib/sportdb/leagues/leagues_south_america.rb +0 -17
- data/lib/sportdb/leagues/leagues_world.rb +0 -14
- data/lib/sportdb/writers/github.rb +0 -195
@@ -0,0 +1,211 @@
|
|
1
|
+
|
2
|
+
module Fbgen
|
3
|
+
def self.main( args=ARGV )
|
4
|
+
|
5
|
+
opts = {
|
6
|
+
source_path: [],
|
7
|
+
push: false,
|
8
|
+
dry: false, ## dry run (no write)
|
9
|
+
debug: true,
|
10
|
+
file: nil,
|
11
|
+
}
|
12
|
+
|
13
|
+
parser = OptionParser.new do |parser|
|
14
|
+
parser.banner = "Usage: #{$PROGRAM_NAME} [options] [args]"
|
15
|
+
|
16
|
+
parser.on( "-p", "--push",
|
17
|
+
"fast forward sync and commit & push changes to git repo - default is (#{opts[:push]})" ) do |push|
|
18
|
+
opts[:push] = push
|
19
|
+
end
|
20
|
+
parser.on( "--dry",
|
21
|
+
"dry run; do NOT write - default is (#{opts[:dry]})" ) do |dry|
|
22
|
+
opts[:dry] = dry
|
23
|
+
end
|
24
|
+
parser.on( "-q", "--quiet",
|
25
|
+
"less debug output/messages - default is (#{!opts[:debug]})" ) do |debug|
|
26
|
+
opts[:debug] = !debug
|
27
|
+
end
|
28
|
+
|
29
|
+
parser.on( "-f FILE", "--file FILE",
|
30
|
+
"read leagues via .csv file") do |file|
|
31
|
+
opts[:file] = file
|
32
|
+
end
|
33
|
+
end
|
34
|
+
parser.parse!( args )
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
if opts[:source_path].empty? &&
|
39
|
+
File.exist?( '/sports/cache.api.fbdat') &&
|
40
|
+
File.exist?( '/sports/cache.wfb' )
|
41
|
+
opts[:source_path] << '/sports/cache.api.fbdat'
|
42
|
+
opts[:source_path] << '/sports/cache.wfb'
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
puts "OPTS:"
|
47
|
+
p opts
|
48
|
+
puts "ARGV:"
|
49
|
+
p args
|
50
|
+
|
51
|
+
datasets = if opts[:file]
|
52
|
+
read_datasets( opts[:file] )
|
53
|
+
else
|
54
|
+
parse_datasets( args )
|
55
|
+
end
|
56
|
+
|
57
|
+
puts "datasets:"
|
58
|
+
pp datasets
|
59
|
+
|
60
|
+
|
61
|
+
source_path = opts[:source_path]
|
62
|
+
source_path = ['.'] if source_path.empty? ## use ./ as default
|
63
|
+
|
64
|
+
root_dir = if opts[:push]
|
65
|
+
GitHubSync.root # e.g. "/sports"
|
66
|
+
else
|
67
|
+
'./o'
|
68
|
+
end
|
69
|
+
|
70
|
+
puts " (output) root_dir: >#{root_dir}<"
|
71
|
+
|
72
|
+
sync = if opts[:push]
|
73
|
+
repos = GitHubSync.find_repos( datasets )
|
74
|
+
puts " #{repos.size} repo(s):"
|
75
|
+
pp repos
|
76
|
+
GitHubSync.new( repos )
|
77
|
+
else
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
puts " sync:"
|
81
|
+
pp sync
|
82
|
+
|
83
|
+
sync.git_fast_forward_if_clean if sync
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
datasets.each do |league_key, seasons|
|
88
|
+
seasons = [ Season('2024/25') ] if seasons.empty?
|
89
|
+
|
90
|
+
puts "==> gen #{league_key} - #{seasons.size} seasons(s)..."
|
91
|
+
|
92
|
+
league_info = Writer::LEAGUES[ league_key ]
|
93
|
+
pp league_info
|
94
|
+
|
95
|
+
seasons.each do |season|
|
96
|
+
### get matches
|
97
|
+
|
98
|
+
filename = "#{season.to_path}/#{league_key}.csv"
|
99
|
+
path = find_file( filename, path: source_path )
|
100
|
+
|
101
|
+
if path.nil?
|
102
|
+
puts "!! no source found for #{filename}; sorry"
|
103
|
+
exit 1
|
104
|
+
end
|
105
|
+
|
106
|
+
puts " ---> reading matches in #{path} ..."
|
107
|
+
matches = SportDb::CsvMatchParser.read( path )
|
108
|
+
puts " #{matches.size} matches"
|
109
|
+
|
110
|
+
## build
|
111
|
+
txt = SportDb::TxtMatchWriter.build( matches )
|
112
|
+
puts txt if opts[:debug]
|
113
|
+
|
114
|
+
league_name = league_info[ :name ] # e.g. Brasileiro Série A
|
115
|
+
basename = league_info[ :basename] #.e.g 1-seriea
|
116
|
+
|
117
|
+
league_name = league_name.call( season ) if league_name.is_a?( Proc ) ## is proc/func - name depends on season
|
118
|
+
basename = basename.call( season ) if basename.is_a?( Proc ) ## is proc/func - name depends on season
|
119
|
+
|
120
|
+
buf = String.new
|
121
|
+
buf << "= #{league_name} #{season}\n\n"
|
122
|
+
buf << txt
|
123
|
+
|
124
|
+
repo = GitHubSync::REPOS[ league_key ]
|
125
|
+
repo_path = "#{repo['owner']}/#{repo['name']}"
|
126
|
+
repo_path << "/#{repo['path']}" if repo['path'] ## note: do NOT forget to add optional extra path!!!
|
127
|
+
|
128
|
+
outpath = "#{root_dir}/#{repo_path}/#{season.to_path}/#{basename}.txt"
|
129
|
+
if opts[:dry]
|
130
|
+
puts " (dry) writing to >#{outpath}<..."
|
131
|
+
else
|
132
|
+
write_text( outpath, buf )
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
sync.git_push_if_changes if sync
|
138
|
+
|
139
|
+
end # method self.main
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
def self.parse_datasets( args )
|
144
|
+
### split args in datasets with leagues and seasons
|
145
|
+
datasets = []
|
146
|
+
args.each do |arg|
|
147
|
+
if arg =~ %r{^[0-9/-]+$} ## season
|
148
|
+
if datasets.empty?
|
149
|
+
puts "!! ERROR - league required before season arg; sorry"
|
150
|
+
exit 1
|
151
|
+
end
|
152
|
+
|
153
|
+
season = Season.parse( arg ) ## check season
|
154
|
+
datasets[-1][1] << season
|
155
|
+
else ## assume league key
|
156
|
+
key = arg.downcase
|
157
|
+
league_info = Writer::LEAGUES[ key ]
|
158
|
+
|
159
|
+
if league_info.nil?
|
160
|
+
puts "!! ERROR - no league found for >#{key}<; sorry"
|
161
|
+
exit 1
|
162
|
+
end
|
163
|
+
|
164
|
+
datasets << [key, []]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
datasets
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
def self.read_datasets( path )
|
172
|
+
### split args in datasets with leagues and seasons
|
173
|
+
datasets = []
|
174
|
+
recs = read_csv( path )
|
175
|
+
recs.each do |rec|
|
176
|
+
league_code = rec['league']
|
177
|
+
key = league_code.downcase
|
178
|
+
league_info = Writer::LEAGUES[ key ]
|
179
|
+
|
180
|
+
if league_info.nil?
|
181
|
+
puts "!! ERROR - no league found for >#{key}<; sorry"
|
182
|
+
exit 1
|
183
|
+
end
|
184
|
+
|
185
|
+
datasets << [key, []]
|
186
|
+
|
187
|
+
seasons_str = rec['seasons']
|
188
|
+
seasons = seasons_str.split( /[ ]+/ )
|
189
|
+
|
190
|
+
seasons.each do |season_str|
|
191
|
+
season = Season.parse( season_str ) ## check season
|
192
|
+
datasets[-1][1] << season
|
193
|
+
end
|
194
|
+
end
|
195
|
+
datasets
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
def self.find_file( filename, path: )
|
200
|
+
path.each do |src_dir|
|
201
|
+
path = "#{src_dir}/#{filename}"
|
202
|
+
return path if File.exist?( path )
|
203
|
+
end
|
204
|
+
|
205
|
+
## fix - raise file not found error!!!
|
206
|
+
nil ## not found - raise filenot found error - why? why not?
|
207
|
+
end
|
208
|
+
|
209
|
+
|
210
|
+
|
211
|
+
end # module Fbgen
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
module Fbtxt
|
3
|
+
def self.main( args=ARGV )
|
4
|
+
|
5
|
+
|
6
|
+
opts = {
|
7
|
+
}
|
8
|
+
|
9
|
+
parser = OptionParser.new do |parser|
|
10
|
+
parser.banner = "Usage: #{$PROGRAM_NAME} [options]"
|
11
|
+
end
|
12
|
+
parser.parse!( args )
|
13
|
+
|
14
|
+
puts "OPTS:"
|
15
|
+
p opts
|
16
|
+
puts "ARGV:"
|
17
|
+
p args
|
18
|
+
|
19
|
+
|
20
|
+
matches = []
|
21
|
+
|
22
|
+
## step 1 - get all matches via csv
|
23
|
+
args.each do |arg|
|
24
|
+
path = arg
|
25
|
+
puts "==> reading matches in #{path} ..."
|
26
|
+
more_matches = SportDb::CsvMatchParser.read( path )
|
27
|
+
matches += more_matches
|
28
|
+
end
|
29
|
+
|
30
|
+
puts "#{matches.size} matches"
|
31
|
+
puts
|
32
|
+
|
33
|
+
txt = SportDb::TxtMatchWriter.build( matches )
|
34
|
+
puts txt
|
35
|
+
puts
|
36
|
+
end
|
37
|
+
end # module Fbtxt
|
@@ -0,0 +1,83 @@
|
|
1
|
+
|
2
|
+
module SportDb
|
3
|
+
class LeagueConfig
|
4
|
+
|
5
|
+
def self.read( path )
|
6
|
+
recs = read_csv( path )
|
7
|
+
new( recs )
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize( recs=nil )
|
11
|
+
@table = {}
|
12
|
+
add( recs ) if recs
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
class LeagueItem
|
17
|
+
def initialize
|
18
|
+
@recs = []
|
19
|
+
end
|
20
|
+
def add( rec ) @recs << rec; end
|
21
|
+
alias_method :<<, :add
|
22
|
+
|
23
|
+
def find_by_season( season )
|
24
|
+
@recs.each do |rec|
|
25
|
+
start_season = rec['start_season']
|
26
|
+
end_season = rec['end_season']
|
27
|
+
return rec if (start_season.nil? || start_season <= season) &&
|
28
|
+
(end_season.nil? || end_season >= season)
|
29
|
+
end
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def name_by_season( season )
|
35
|
+
rec = find_by_season( season )
|
36
|
+
rec ? rec['name'] : nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def basename_by_season( season )
|
40
|
+
rec = find_by_season( season )
|
41
|
+
rec ? rec['basename'] : nil
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def [](key)
|
46
|
+
## short cut - if only one or zero rec
|
47
|
+
## return directly
|
48
|
+
if @recs.empty?
|
49
|
+
nil
|
50
|
+
elsif @recs.size == 1 &&
|
51
|
+
@recs[0]['start_season'].nil? &&
|
52
|
+
@recs[0]['end_season'].nil?
|
53
|
+
@recs[0][key.to_s]
|
54
|
+
else ### return proc that requires season arg
|
55
|
+
case key.to_sym
|
56
|
+
when :name then method(:name_by_season).to_proc
|
57
|
+
when :basename then method(:basename_by_season).to_proc
|
58
|
+
else
|
59
|
+
nil ## return nil - why? why not?
|
60
|
+
## raise ArgumentError, "invalid key #{key}; use :name or :basename"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def add( recs )
|
67
|
+
recs.each do |rec|
|
68
|
+
@table[ rec['key'] ] ||= LeagueItem.new
|
69
|
+
|
70
|
+
## note: auto-change seasons to season object or nil
|
71
|
+
@table[ rec['key'] ] << { 'name' => rec['name'],
|
72
|
+
'basename' => rec['basename'],
|
73
|
+
'start_season' => rec['start_season'].empty? ? nil : Season.parse( rec['start_season'] ),
|
74
|
+
'end_season' => rec['end_season'].empty? ? nil : Season.parse( rec['end_season'] ),
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def [](key) @table[ key.to_s.downcase ]; end
|
81
|
+
|
82
|
+
end # class LeagueConfig
|
83
|
+
end # module SportDb
|
@@ -19,12 +19,116 @@ def self.build( matches, rounds: true )
|
|
19
19
|
## note: make sure rounds is a bool, that is, true or false (do NOT pass in strings etc.)
|
20
20
|
raise ArgumentError, "rounds flag - bool expected; got: #{rounds.inspect}" unless rounds.is_a?( TrueClass ) || rounds.is_a?( FalseClass )
|
21
21
|
|
22
|
-
|
22
|
+
|
23
|
+
### check for stages & stats
|
24
|
+
stats = { 'stage' => Hash.new(0),
|
25
|
+
'date' => { 'start_date' => nil,
|
26
|
+
'end_date' => nil, },
|
27
|
+
'teams' => Hash.new(0),
|
28
|
+
}
|
29
|
+
|
30
|
+
## add matches played stats too??
|
31
|
+
|
32
|
+
matches.each do |match|
|
33
|
+
stage = match.stage
|
34
|
+
stage = 'Regular Season' if stage.nil? || stage.empty?
|
35
|
+
stats['stage'][ stage ] += 1
|
36
|
+
|
37
|
+
if match.date
|
38
|
+
|
39
|
+
## todo/fix - norm date (parse as Date)
|
40
|
+
## check format etc.
|
41
|
+
date = if match.date.is_a?( String )
|
42
|
+
Date.strptime( match.date, '%Y-%m-%d' )
|
43
|
+
else ## assume it's already a date (object)
|
44
|
+
match.date
|
45
|
+
end
|
46
|
+
stats['date']['start_date'] ||= date
|
47
|
+
stats['date']['end_date'] ||= date
|
48
|
+
|
49
|
+
stats['date']['start_date'] = date if date < stats['date']['start_date']
|
50
|
+
stats['date']['end_date'] = date if date > stats['date']['end_date']
|
51
|
+
end
|
52
|
+
|
53
|
+
[match.team1, match.team2].each do |team|
|
54
|
+
stats['teams'][ team ] += 1 if team && !['N.N.'].include?( team )
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
use_stages = if stats['stage'].size >= 2 ||
|
59
|
+
(stats['stage'].size == 1 &&
|
60
|
+
stats['stage'].keys[0] != 'Regular Season')
|
61
|
+
true
|
62
|
+
else
|
63
|
+
false
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
### add comment header
|
68
|
+
buf = String.new
|
69
|
+
# e.g. 13 April – 25 September 2024
|
70
|
+
# or 16 August 2024 – 25 May 2025
|
71
|
+
buf << "# Date "
|
72
|
+
start_date = stats['date']['start_date']
|
73
|
+
end_date = stats['date']['end_date']
|
74
|
+
if start_date.year != end_date.year
|
75
|
+
buf << "#{start_date.strftime('%a %b/%-d %Y')} - #{end_date.strftime('%a %b/%-d %Y')}"
|
76
|
+
else
|
77
|
+
buf << "#{start_date.strftime('%a %b/%-d')} - #{end_date.strftime('%a %b/%-d %Y')}"
|
78
|
+
end
|
79
|
+
buf << " (#{end_date.jd-start_date.jd}d)" ## add days
|
80
|
+
buf << "\n"
|
81
|
+
|
82
|
+
buf << "# Teams #{stats['teams'].size}\n"
|
83
|
+
buf << "# Matches #{matches.size}\n"
|
84
|
+
|
85
|
+
if use_stages
|
86
|
+
buf << "# Stages "
|
87
|
+
stages = stats['stage'].map { |name,count| "#{name} (#{count})" }.join( ' ' )
|
88
|
+
buf << stages
|
89
|
+
buf << "\n"
|
90
|
+
end
|
91
|
+
buf << "\n\n"
|
92
|
+
|
93
|
+
|
94
|
+
if use_stages
|
95
|
+
## split matches by stage
|
96
|
+
matches_by_stage = {}
|
97
|
+
matches.each do |match|
|
98
|
+
stage = match.stage || ''
|
99
|
+
matches_by_stage[stage] ||= []
|
100
|
+
matches_by_stage[stage] << match
|
101
|
+
end
|
102
|
+
|
103
|
+
## todo/fix
|
104
|
+
## note - empty stage must go first!!!!
|
105
|
+
matches_by_stage.each_with_index do |(name, matches),i|
|
106
|
+
buf << "\n" if i != 0 # add extra new line (if not first stage)
|
107
|
+
if name.empty?
|
108
|
+
buf << "# Regular Season\n" ## empty stage
|
109
|
+
else
|
110
|
+
buf << "== #{name}\n"
|
111
|
+
end
|
112
|
+
buf += _build_batch( matches, rounds: rounds )
|
113
|
+
buf << "\n" if i+1 != matches_by_stage.size
|
114
|
+
end
|
115
|
+
buf
|
116
|
+
else
|
117
|
+
buf += _build_batch( matches, rounds: rounds )
|
118
|
+
buf
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def self._build_batch( matches, rounds: true )
|
124
|
+
## note: make sure rounds is a bool, that is, true or false (do NOT pass in strings etc.)
|
125
|
+
raise ArgumentError, "rounds flag - bool expected; got: #{rounds.inspect}" unless rounds.is_a?( TrueClass ) || rounds.is_a?( FalseClass )
|
126
|
+
|
127
|
+
## note: for now always english
|
23
128
|
round = 'Matchday'
|
24
129
|
format_date = ->(date) { date.strftime( '%a %b/%-d' ) }
|
25
130
|
format_score = ->(match) { match.score.to_s( lang: 'en' ) }
|
26
131
|
round_translations = ROUND_TRANSLATIONS
|
27
|
-
|
28
132
|
|
29
133
|
buf = String.new
|
30
134
|
|
@@ -33,12 +137,12 @@ def self.build( matches, rounds: true )
|
|
33
137
|
last_time = nil
|
34
138
|
|
35
139
|
|
36
|
-
matches.
|
140
|
+
matches.each_with_index do |match,i|
|
37
141
|
|
38
142
|
## note: make rounds optional (set rounds flag to false to turn off)
|
39
143
|
if rounds
|
40
144
|
if match.round != last_round
|
41
|
-
buf << "\n\n"
|
145
|
+
buf << (i == 0 ? "\n" : "\n\n") ## start with single empty line
|
42
146
|
if match.round.is_a?( Integer ) ||
|
43
147
|
match.round =~ /^[0-9]+$/ ## all numbers/digits
|
44
148
|
## default "class format
|
@@ -53,7 +53,7 @@ def self.write( league:, season:,
|
|
53
53
|
source:,
|
54
54
|
extra: nil,
|
55
55
|
split: false,
|
56
|
-
normalize: false,
|
56
|
+
normalize: false,
|
57
57
|
rounds: true )
|
58
58
|
season = Season( season ) ## normalize season
|
59
59
|
|
@@ -71,7 +71,7 @@ def self.write( league:, season:,
|
|
71
71
|
exit 1
|
72
72
|
end
|
73
73
|
source_info = { path: source } ## wrap in "plain" source dir in source info
|
74
|
-
|
74
|
+
|
75
75
|
source_path = source_info[:path]
|
76
76
|
|
77
77
|
## format lets you specify directory layout
|
@@ -106,14 +106,14 @@ def self.write( league:, season:,
|
|
106
106
|
if normalize.is_a?(Proc)
|
107
107
|
matches = normalize.call( matches, league: league,
|
108
108
|
season: season )
|
109
|
-
else
|
109
|
+
else
|
110
110
|
puts "!! ERROR - normalize; expected proc got #{normalize.inspect}"
|
111
111
|
exit 1
|
112
|
-
end
|
112
|
+
end
|
113
113
|
end
|
114
|
-
|
115
114
|
|
116
|
-
|
115
|
+
|
116
|
+
|
117
117
|
league_name = league_info[ :name ] # e.g. Brasileiro Série A
|
118
118
|
basename = league_info[ :basename] #.e.g 1-seriea
|
119
119
|
|
@@ -122,7 +122,10 @@ def self.write( league:, season:,
|
|
122
122
|
|
123
123
|
## note - repo_path moved!!!
|
124
124
|
## repo_path = league_info[ :path ] # e.g. brazil or world/europe/portugal etc.
|
125
|
-
|
125
|
+
repo = SportDb::GitHubSync::REPOS[ league ]
|
126
|
+
repo_path = "#{repo['owner']}/#{repo['name']}"
|
127
|
+
repo_path << "/#{repo['path']}" if repo['path'] ## note: do NOT forget to add optional extra path!!!
|
128
|
+
|
126
129
|
|
127
130
|
|
128
131
|
season_path = String.new ## note: allow extra path for output!!!! e.g. archive/2000s etc.
|
@@ -175,7 +178,7 @@ def self.write( league:, season:,
|
|
175
178
|
)
|
176
179
|
|
177
180
|
## note: might be empty!!! if no matches skip (do NOT write)
|
178
|
-
write_text( "#{config.out_dir}/#{repo_path}/#{season_path}/#{stage_basename}.txt",
|
181
|
+
write_text( "#{config.out_dir}/#{repo_path}/#{season_path}/#{stage_basename}.txt",
|
179
182
|
buf ) unless buf.empty?
|
180
183
|
end
|
181
184
|
else ## no stages - assume "regular" plain vanilla season
|
data/lib/sportdb/writers.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
require 'sportdb/quick'
|
3
3
|
|
4
4
|
|
5
|
+
require 'optparse' ## command-line processing; check if included updstream?
|
6
|
+
|
7
|
+
|
5
8
|
|
6
9
|
module Writer
|
7
10
|
class Configuration
|
@@ -29,30 +32,74 @@ require_relative 'writers/goals'
|
|
29
32
|
require_relative 'writers/write'
|
30
33
|
|
31
34
|
|
35
|
+
## setup leagues (info) table
|
36
|
+
require_relative 'writers/league_config'
|
37
|
+
|
38
|
+
module Writer
|
39
|
+
LEAGUES = SportDb::LeagueConfig.new
|
40
|
+
|
41
|
+
['leagues_europe',
|
42
|
+
'leagues_america',
|
43
|
+
'leagues_world'
|
44
|
+
].each do |name|
|
45
|
+
recs = read_csv( "#{SportDb::Module::Writers.root}/config/#{name}.csv" )
|
46
|
+
LEAGUES.add( recs )
|
47
|
+
end
|
48
|
+
end # module Writer
|
49
|
+
|
50
|
+
|
51
|
+
###
|
52
|
+
# fbtxt tool
|
53
|
+
require_relative 'fbtxt/main'
|
54
|
+
|
55
|
+
|
32
56
|
|
33
57
|
########################
|
34
58
|
# push & pull github scripts
|
35
59
|
require 'gitti' ## note - requires git machinery
|
36
60
|
|
37
|
-
require_relative '
|
61
|
+
require_relative 'fbgen/github_config'
|
62
|
+
require_relative 'fbgen/github' ## github helpers/update machinery
|
38
63
|
|
39
64
|
|
65
|
+
module Fbgen
|
66
|
+
class GitHubSync
|
67
|
+
REPOS = GitHubConfig.new
|
68
|
+
recs = read_csv( "#{SportDb::Module::Writers.root}/config/openfootball.csv" )
|
69
|
+
REPOS.add( recs )
|
40
70
|
|
41
|
-
##
|
42
|
-
|
43
|
-
|
71
|
+
## todo/check: find a better name for helper?
|
72
|
+
## note: datasets of format
|
73
|
+
##
|
74
|
+
## DATASETS = [
|
75
|
+
## ['it.1', %w[2020/21 2019/20]],
|
76
|
+
## ['it.2', %w[2019/20]],
|
77
|
+
## ['es.1', %w[2019/20]],
|
78
|
+
## ['es.2', %w[2019/20]],
|
79
|
+
## ]
|
80
|
+
|
81
|
+
def self.find_repos( datasets )
|
82
|
+
repos = []
|
83
|
+
datasets.each do |dataset|
|
84
|
+
league_key = dataset[0]
|
85
|
+
repo = REPOS[ league_key ]
|
86
|
+
## pp repo
|
87
|
+
if repo.nil?
|
88
|
+
puts "!! ERROR - no repo config/path found for league >#{league_key}<; sorry"
|
89
|
+
exit 1
|
90
|
+
end
|
91
|
+
|
92
|
+
repos << "#{repo['owner']}/#{repo['name']}"
|
93
|
+
end
|
94
|
+
|
95
|
+
pp repos
|
96
|
+
repos.uniq ## note: remove duplicates (e.g. europe or world or such)
|
44
97
|
end
|
98
|
+
end # class GitHubSync
|
99
|
+
end # module Fbgen
|
45
100
|
|
46
|
-
require_relative 'leagues/leagues_at'
|
47
|
-
require_relative 'leagues/leagues_de'
|
48
|
-
require_relative 'leagues/leagues_eng'
|
49
|
-
require_relative 'leagues/leagues_es'
|
50
|
-
require_relative 'leagues/leagues_europe'
|
51
|
-
require_relative 'leagues/leagues_it'
|
52
|
-
require_relative 'leagues/leagues_mx'
|
53
|
-
require_relative 'leagues/leagues_south_america'
|
54
|
-
require_relative 'leagues/leagues_world'
|
55
101
|
|
102
|
+
require_relative 'fbgen/main'
|
56
103
|
|
57
104
|
|
58
105
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sportdb-writers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.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: 2024-09-
|
11
|
+
date: 2024-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sportdb-quick
|
@@ -90,18 +90,17 @@ files:
|
|
90
90
|
- Rakefile
|
91
91
|
- bin/fbgen
|
92
92
|
- bin/fbtxt
|
93
|
-
-
|
94
|
-
-
|
95
|
-
-
|
96
|
-
-
|
97
|
-
- lib/sportdb/
|
98
|
-
- lib/sportdb/
|
99
|
-
- lib/sportdb/
|
100
|
-
- lib/sportdb/
|
101
|
-
- lib/sportdb/leagues/leagues_world.rb
|
93
|
+
- config/leagues_america.csv
|
94
|
+
- config/leagues_europe.csv
|
95
|
+
- config/leagues_world.csv
|
96
|
+
- config/openfootball.csv
|
97
|
+
- lib/sportdb/fbgen/github.rb
|
98
|
+
- lib/sportdb/fbgen/github_config.rb
|
99
|
+
- lib/sportdb/fbgen/main.rb
|
100
|
+
- lib/sportdb/fbtxt/main.rb
|
102
101
|
- lib/sportdb/writers.rb
|
103
|
-
- lib/sportdb/writers/github.rb
|
104
102
|
- lib/sportdb/writers/goals.rb
|
103
|
+
- lib/sportdb/writers/league_config.rb
|
105
104
|
- lib/sportdb/writers/txt_writer.rb
|
106
105
|
- lib/sportdb/writers/version.rb
|
107
106
|
- lib/sportdb/writers/write.rb
|