sportdb-writers 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/Manifest.txt +4 -2
- data/bin/fbgen +1 -171
- data/bin/fbtxt +1 -36
- data/config/leagues_europe.csv +13 -4
- data/lib/sportdb/{writers → fbgen}/github.rb +2 -2
- data/lib/sportdb/{writers → fbgen}/github_config.rb +2 -2
- data/lib/sportdb/fbgen/main.rb +211 -0
- data/lib/sportdb/fbtxt/main.rb +37 -0
- data/lib/sportdb/writers/txt_writer.rb +108 -4
- data/lib/sportdb/writers/version.rb +2 -2
- data/lib/sportdb/writers.rb +13 -4
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3483a7e2f321970a2e970ba30e272127892013b61c63be66431a318d32b52c3f
|
4
|
+
data.tar.gz: 4d213ad75e6973aa6ef95bee7fb39a62bca69cd3261fc18e2bfcfc9a6b913b87
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7b00a033d247555ca57acc503c88de73111605738998a9e5b3ea4e53f0353b08df19cfa1f9d5c84a5ad22b5528ddb632ba927b4f0b53fb5493f5391732d3d13
|
7
|
+
data.tar.gz: 23cec6ae8fa9b9ca04cf2242c86f8310de76a191b5a66bc4f2cab09aff7ea5c3e0a0d312bfe582dd2150d344302bdabab592c9b1944385bd75ae86de2367d207
|
data/CHANGELOG.md
CHANGED
data/Manifest.txt
CHANGED
@@ -8,9 +8,11 @@ config/leagues_america.csv
|
|
8
8
|
config/leagues_europe.csv
|
9
9
|
config/leagues_world.csv
|
10
10
|
config/openfootball.csv
|
11
|
+
lib/sportdb/fbgen/github.rb
|
12
|
+
lib/sportdb/fbgen/github_config.rb
|
13
|
+
lib/sportdb/fbgen/main.rb
|
14
|
+
lib/sportdb/fbtxt/main.rb
|
11
15
|
lib/sportdb/writers.rb
|
12
|
-
lib/sportdb/writers/github.rb
|
13
|
-
lib/sportdb/writers/github_config.rb
|
14
16
|
lib/sportdb/writers/goals.rb
|
15
17
|
lib/sportdb/writers/league_config.rb
|
16
18
|
lib/sportdb/writers/txt_writer.rb
|
data/bin/fbgen
CHANGED
@@ -6,178 +6,8 @@
|
|
6
6
|
|
7
7
|
require 'sportdb/writers'
|
8
8
|
|
9
|
-
require 'optparse'
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
args=ARGV
|
14
|
-
|
15
|
-
|
16
|
-
opts = {
|
17
|
-
source_path: [],
|
18
|
-
push: false,
|
19
|
-
dry: false, ## dry run (no write)
|
20
|
-
debug: true,
|
21
|
-
}
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
parser = OptionParser.new do |parser|
|
26
|
-
parser.banner = "Usage: #{$PROGRAM_NAME} [options] [args]"
|
27
|
-
|
28
|
-
parser.on( "-p", "--push",
|
29
|
-
"fast forward sync and commit & push changes to git repo - default is (#{opts[:push]})" ) do |push|
|
30
|
-
opts[:push] = push
|
31
|
-
end
|
32
|
-
parser.on( "--dry",
|
33
|
-
"dry run; do NOT write - default is (#{opts[:dry]})" ) do |dry|
|
34
|
-
opts[:dry] = dry
|
35
|
-
end
|
36
|
-
parser.on( "-q", "--quiet",
|
37
|
-
"less debug output/messages - default is (#{!opts[:debug]})" ) do |debug|
|
38
|
-
opts[:debug] = !debug
|
39
|
-
end
|
40
|
-
end
|
41
|
-
parser.parse!( args )
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
if opts[:source_path].empty? &&
|
46
|
-
File.exist?( '/sports/cache.api.fbdat') &&
|
47
|
-
File.exist?( '/sports/cache.wfb' )
|
48
|
-
opts[:source_path] << '/sports/cache.api.fbdat'
|
49
|
-
opts[:source_path] << '/sports/cache.wfb'
|
50
|
-
end
|
51
|
-
|
52
|
-
|
53
|
-
puts "OPTS:"
|
54
|
-
p opts
|
55
|
-
puts "ARGV:"
|
56
|
-
p args
|
57
|
-
|
58
|
-
|
59
|
-
### split args in datasets with leagues and seasons
|
60
|
-
datasets = []
|
61
|
-
|
62
|
-
|
63
|
-
args.each do |arg|
|
64
|
-
if arg =~ %r{^[0-9/-]+$} ## season
|
65
|
-
if datasets.empty?
|
66
|
-
puts "!! ERROR - league required before season arg; sorry"
|
67
|
-
exit 1
|
68
|
-
end
|
69
|
-
|
70
|
-
season = Season.parse( arg ) ## check season
|
71
|
-
datasets[-1][1] << season
|
72
|
-
else ## assume league key
|
73
|
-
key = arg.downcase
|
74
|
-
league_info = Writer::LEAGUES[ key ]
|
75
|
-
|
76
|
-
if league_info.nil?
|
77
|
-
puts "!! ERROR - no league found for >#{key}<; sorry"
|
78
|
-
exit 1
|
79
|
-
end
|
80
|
-
|
81
|
-
datasets << [key, []]
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
pp datasets
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
def find_file( filename, path: )
|
90
|
-
path.each do |src_dir|
|
91
|
-
path = "#{src_dir}/#{filename}"
|
92
|
-
return path if File.exist?( path )
|
93
|
-
end
|
94
|
-
|
95
|
-
## fix - raise file not found error!!!
|
96
|
-
nil ## not found - raise filenot found error - why? why not?
|
97
|
-
end
|
98
|
-
|
99
|
-
|
100
|
-
source_path = opts[:source_path]
|
101
|
-
source_path = ['.'] if source_path.empty? ## use ./ as default
|
102
|
-
|
103
|
-
|
104
|
-
root_dir = if opts[:push]
|
105
|
-
SportDb::GitHubSync.root # e.g. "/sports"
|
106
|
-
else
|
107
|
-
'./o'
|
108
|
-
end
|
109
|
-
|
110
|
-
|
111
|
-
puts " (output) root_dir: >#{root_dir}<"
|
112
|
-
|
113
|
-
|
114
|
-
sync = if opts[:push]
|
115
|
-
repos = SportDb::GitHubSync.find_repos( datasets )
|
116
|
-
puts " #{repos.size} repo(s):"
|
117
|
-
pp repos
|
118
|
-
SportDb::GitHubSync.new( repos )
|
119
|
-
else
|
120
|
-
nil
|
121
|
-
end
|
122
|
-
puts " sync:"
|
123
|
-
pp sync
|
124
|
-
|
125
|
-
sync.git_fast_forward_if_clean if sync
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
datasets.each do |league_key, seasons|
|
130
|
-
seasons = [ Season('2024/25') ] if seasons.empty?
|
131
|
-
|
132
|
-
puts "==> gen #{league_key} - #{seasons.size} seasons(s)..."
|
133
|
-
|
134
|
-
league_info = Writer::LEAGUES[ league_key ]
|
135
|
-
pp league_info
|
136
|
-
|
137
|
-
seasons.each do |season|
|
138
|
-
### get matches
|
139
|
-
|
140
|
-
filename = "#{season.to_path}/#{league_key}.csv"
|
141
|
-
path = find_file( filename, path: source_path )
|
142
|
-
|
143
|
-
if path.nil?
|
144
|
-
puts "!! no source found for #{filename}; sorry"
|
145
|
-
exit 1
|
146
|
-
end
|
147
|
-
|
148
|
-
puts " ---> reading matches in #{path} ..."
|
149
|
-
matches = SportDb::CsvMatchParser.read( path )
|
150
|
-
puts " #{matches.size} matches"
|
151
|
-
|
152
|
-
## build
|
153
|
-
txt = SportDb::TxtMatchWriter.build( matches )
|
154
|
-
puts txt if opts[:debug]
|
155
|
-
|
156
|
-
league_name = league_info[ :name ] # e.g. Brasileiro Série A
|
157
|
-
basename = league_info[ :basename] #.e.g 1-seriea
|
158
|
-
|
159
|
-
league_name = league_name.call( season ) if league_name.is_a?( Proc ) ## is proc/func - name depends on season
|
160
|
-
basename = basename.call( season ) if basename.is_a?( Proc ) ## is proc/func - name depends on season
|
161
|
-
|
162
|
-
buf = String.new
|
163
|
-
buf << "= #{league_name} #{season}\n\n"
|
164
|
-
buf << txt
|
165
|
-
|
166
|
-
repo = SportDb::GitHubSync::REPOS[ league_key ]
|
167
|
-
repo_path = "#{repo['owner']}/#{repo['name']}"
|
168
|
-
repo_path << "/#{repo['path']}" if repo['path'] ## note: do NOT forget to add optional extra path!!!
|
169
|
-
|
170
|
-
outpath = "#{root_dir}/#{repo_path}/#{season.to_path}/#{basename}.txt"
|
171
|
-
if opts[:dry]
|
172
|
-
puts " (dry) writing to >#{outpath}<..."
|
173
|
-
else
|
174
|
-
write_text( outpath, buf )
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
|
180
|
-
sync.git_push_if_changes if sync
|
10
|
+
Fbgen.main( ARGV )
|
181
11
|
|
182
12
|
|
183
13
|
puts "bye"
|
data/bin/fbtxt
CHANGED
@@ -9,44 +9,9 @@
|
|
9
9
|
|
10
10
|
require 'sportdb/writers'
|
11
11
|
|
12
|
-
require 'optparse'
|
13
12
|
|
13
|
+
Fbtxt.main( ARGV )
|
14
14
|
|
15
15
|
|
16
|
-
args=ARGV
|
17
|
-
|
18
|
-
|
19
|
-
opts = {
|
20
|
-
}
|
21
|
-
|
22
|
-
parser = OptionParser.new do |parser|
|
23
|
-
parser.banner = "Usage: #{$PROGRAM_NAME} [options]"
|
24
|
-
end
|
25
|
-
parser.parse!( args )
|
26
|
-
|
27
|
-
puts "OPTS:"
|
28
|
-
p opts
|
29
|
-
puts "ARGV:"
|
30
|
-
p args
|
31
|
-
|
32
|
-
|
33
|
-
matches = []
|
34
|
-
|
35
|
-
## step 1 - get all matches via csv
|
36
|
-
args.each do |arg|
|
37
|
-
path = arg
|
38
|
-
puts "==> reading matches in #{path} ..."
|
39
|
-
more_matches = SportDb::CsvMatchParser.read( path )
|
40
|
-
matches += more_matches
|
41
|
-
end
|
42
|
-
|
43
|
-
puts "#{matches.size} matches"
|
44
|
-
puts
|
45
|
-
|
46
|
-
|
47
|
-
txt = SportDb::TxtMatchWriter.build( matches )
|
48
|
-
puts txt
|
49
|
-
puts
|
50
|
-
|
51
16
|
puts "bye"
|
52
17
|
|
data/config/leagues_europe.csv
CHANGED
@@ -7,10 +7,17 @@ at.3.o, Österr. Regionalliga Ost, 3-regionalliga-ost,,,
|
|
7
7
|
at.cup, ÖFB Cup, cup,,,
|
8
8
|
|
9
9
|
|
10
|
-
de.1,
|
11
|
-
de.2,
|
12
|
-
de.3,
|
13
|
-
de.
|
10
|
+
de.1, Deutsche Bundesliga, 1-bundesliga,,,
|
11
|
+
de.2, Deutsche 2. Bundesliga, 2-bundesliga2,,,
|
12
|
+
de.3, Deutsche 3. Liga, 3-liga3,,,
|
13
|
+
de.4.bayern, Deutsche Regionalliga Bayern, 4-regionalliga-bayern,,,
|
14
|
+
de.4.n, Deutsche Regionalliga Nord, 4-regionalliga-nord,,,
|
15
|
+
de.4.no, Deutsche Regionalliga Nordost, 4-regionalliga-nordost,,,
|
16
|
+
de.4.w, Deutsche Regionalliga West, 4-regionalliga-west,,,
|
17
|
+
de.4.sw, Deutsche Regionalliga Südwest, 4-regionalliga-suedwest,,,
|
18
|
+
de.cup, DFB Pokal, cup,,,
|
19
|
+
|
20
|
+
|
14
21
|
|
15
22
|
it.1, Italian Serie A, 1-seriea,,,
|
16
23
|
it.2, Italian Serie B, 2-serieb,,,
|
@@ -45,6 +52,8 @@ pt.2, Portuguese Segunda Liga, 2-segundaliga,,,
|
|
45
52
|
|
46
53
|
ch.1, Swiss Super League, 1-superleague,,,
|
47
54
|
ch.2, Swiss Challenge League, 2-challengeleague,,,
|
55
|
+
ch.cup, Swiss Cup, cup,,,
|
56
|
+
|
48
57
|
|
49
58
|
tr.1, Turkish Süper Lig, 1-superlig,,,
|
50
59
|
tr.2, Turkish 1. Lig, 2-lig1,,,
|
@@ -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
|
@@ -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
|
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
|
@@ -45,16 +48,21 @@ module Writer
|
|
45
48
|
end # module Writer
|
46
49
|
|
47
50
|
|
51
|
+
###
|
52
|
+
# fbtxt tool
|
53
|
+
require_relative 'fbtxt/main'
|
54
|
+
|
55
|
+
|
48
56
|
|
49
57
|
########################
|
50
58
|
# push & pull github scripts
|
51
59
|
require 'gitti' ## note - requires git machinery
|
52
60
|
|
53
|
-
require_relative '
|
54
|
-
require_relative '
|
61
|
+
require_relative 'fbgen/github_config'
|
62
|
+
require_relative 'fbgen/github' ## github helpers/update machinery
|
55
63
|
|
56
64
|
|
57
|
-
module
|
65
|
+
module Fbgen
|
58
66
|
class GitHubSync
|
59
67
|
REPOS = GitHubConfig.new
|
60
68
|
recs = read_csv( "#{SportDb::Module::Writers.root}/config/openfootball.csv" )
|
@@ -88,9 +96,10 @@ def self.find_repos( datasets )
|
|
88
96
|
repos.uniq ## note: remove duplicates (e.g. europe or world or such)
|
89
97
|
end
|
90
98
|
end # class GitHubSync
|
91
|
-
end # module
|
99
|
+
end # module Fbgen
|
92
100
|
|
93
101
|
|
102
|
+
require_relative 'fbgen/main'
|
94
103
|
|
95
104
|
|
96
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
|
@@ -94,9 +94,11 @@ files:
|
|
94
94
|
- config/leagues_europe.csv
|
95
95
|
- config/leagues_world.csv
|
96
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
|
97
101
|
- lib/sportdb/writers.rb
|
98
|
-
- lib/sportdb/writers/github.rb
|
99
|
-
- lib/sportdb/writers/github_config.rb
|
100
102
|
- lib/sportdb/writers/goals.rb
|
101
103
|
- lib/sportdb/writers/league_config.rb
|
102
104
|
- lib/sportdb/writers/txt_writer.rb
|