fbtxt2json 0.2.2 → 0.3.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 +1 -0
- data/Rakefile +1 -1
- data/bin/fbtxt2csv +244 -0
- data/bin/fbtxt2json +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ef1887740ca10a869bb772542efbd1c0f96bfdfd17368e425c104f6653c497c
|
4
|
+
data.tar.gz: 45d1fb3ec650e499c9c0f8318dc56c942d92806d76e4a534e0ee0d541da20f5b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af4f21b7f278fced209a80fac3c043868c64c82b5c1246da38bb56774ff34f4df06404a661ef0c449e0a62eca02dcd4e20f64826cab3011530761078f18db594
|
7
|
+
data.tar.gz: c1dc3ea735f2af33794c708be36bf9c6bb6ff37ae2d8cc218c61005fc923ed1775a7f7c2955c4755bc24b364020bf69924a53cacfafb6af6fa30c20b3951cd45
|
data/CHANGELOG.md
CHANGED
data/Manifest.txt
CHANGED
data/Rakefile
CHANGED
data/bin/fbtxt2csv
ADDED
@@ -0,0 +1,244 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
###
|
4
|
+
# todo/check - move fbtxt2csv to its own top-level gem
|
5
|
+
## or add to ___ - why? why not?
|
6
|
+
|
7
|
+
|
8
|
+
## tip: to test run:
|
9
|
+
## ruby -I ./lib bin/fbtxt2csv
|
10
|
+
|
11
|
+
|
12
|
+
## our own code
|
13
|
+
require 'sportdb/quick'
|
14
|
+
|
15
|
+
require 'fbtok' ### check if requires sportdb/quick (no need to duplicate)
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
require 'optparse'
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
args = ARGV
|
24
|
+
opts = { debug: false,
|
25
|
+
output: nil,
|
26
|
+
seasons: [],
|
27
|
+
}
|
28
|
+
|
29
|
+
parser = OptionParser.new do |parser|
|
30
|
+
parser.banner = "Usage: #{$PROGRAM_NAME} [options] PATH"
|
31
|
+
|
32
|
+
##
|
33
|
+
## check if git has a offline option?? (use same)
|
34
|
+
## check for other tools - why? why not?
|
35
|
+
# parser.on( "-q", "--quiet",
|
36
|
+
# "less debug output/messages - default is (#{!opts[:debug]})" ) do |debug|
|
37
|
+
# opts[:debug] = false
|
38
|
+
# end
|
39
|
+
|
40
|
+
parser.on( "--verbose", "--debug",
|
41
|
+
"turn on verbose / debug output (default: #{opts[:debug]})" ) do |debug|
|
42
|
+
opts[:debug] = true
|
43
|
+
end
|
44
|
+
|
45
|
+
parser.on( "-o PATH", "--output PATH",
|
46
|
+
"output to file" ) do |output|
|
47
|
+
opts[:output] = output
|
48
|
+
end
|
49
|
+
|
50
|
+
parser.on( "--seasons SEASONS",
|
51
|
+
"turn on processing only seasons (default: #{!opts[:seasons].empty?})" ) do |seasons|
|
52
|
+
pp seasons
|
53
|
+
seasons = seasons.split( /[, ]/ )
|
54
|
+
seasons = seasons.map {|season| Season.parse(season) }
|
55
|
+
opts[:seasons] = seasons
|
56
|
+
end
|
57
|
+
end
|
58
|
+
parser.parse!( args )
|
59
|
+
|
60
|
+
|
61
|
+
puts "OPTS:"
|
62
|
+
p opts
|
63
|
+
puts "ARGV:"
|
64
|
+
p args
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
paths = if args.empty?
|
69
|
+
['/sports/openfootball/euro/2021--europe/euro.txt']
|
70
|
+
else
|
71
|
+
args
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
if opts[:debug]
|
76
|
+
SportDb::QuickMatchReader.debug = true
|
77
|
+
SportDb::MatchParser.debug = true
|
78
|
+
else
|
79
|
+
SportDb::QuickMatchReader.debug = false
|
80
|
+
SportDb::MatchParser.debug = false
|
81
|
+
LogUtils::Logger.root.level = :info
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
MAX_HEADERS = [
|
88
|
+
'League',
|
89
|
+
'Date',
|
90
|
+
'Time',
|
91
|
+
'Team 1',
|
92
|
+
'Team 2',
|
93
|
+
'HT',
|
94
|
+
'FT',
|
95
|
+
'ET',
|
96
|
+
'P',
|
97
|
+
'Round',
|
98
|
+
'Status',
|
99
|
+
]
|
100
|
+
|
101
|
+
MIN_HEADERS = [ ## always keep even if all empty
|
102
|
+
'League',
|
103
|
+
'Date',
|
104
|
+
'Team 1',
|
105
|
+
'FT',
|
106
|
+
'Team 2'
|
107
|
+
]
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
def vacuum( rows, headers: MAX_HEADERS, fixed_headers: MIN_HEADERS )
|
112
|
+
## check for unused columns and strip/remove
|
113
|
+
counter = Array.new( MAX_HEADERS.size, 0 )
|
114
|
+
rows.each do |row|
|
115
|
+
row.each_with_index do |col, idx|
|
116
|
+
counter[idx] += 1 unless col.nil? || col.empty?
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
## pp counter
|
121
|
+
|
122
|
+
## check empty columns
|
123
|
+
headers = []
|
124
|
+
indices = []
|
125
|
+
empty_headers = []
|
126
|
+
empty_indices = []
|
127
|
+
|
128
|
+
counter.each_with_index do |num, idx|
|
129
|
+
header = MAX_HEADERS[ idx ]
|
130
|
+
if num > 0 || (num == 0 && fixed_headers.include?( header ))
|
131
|
+
headers << header
|
132
|
+
indices << idx
|
133
|
+
else
|
134
|
+
empty_headers << header
|
135
|
+
empty_indices << idx
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
if empty_indices.size > 0
|
140
|
+
rows = rows.map do |row|
|
141
|
+
row_vacuumed = []
|
142
|
+
row.each_with_index do |col, idx|
|
143
|
+
## todo/fix: use values or such??
|
144
|
+
row_vacuumed << col unless empty_indices.include?( idx )
|
145
|
+
end
|
146
|
+
row_vacuumed
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
[rows, headers]
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
def parse( txt ) ### check - name parse_txt or txt_to_csv or such - why? why not?
|
156
|
+
quick = SportDb::QuickMatchReader.new( txt )
|
157
|
+
matches = quick.parse
|
158
|
+
name = quick.league_name ## quick hack - get league+season via league_name
|
159
|
+
|
160
|
+
recs = []
|
161
|
+
|
162
|
+
matches.each do |match|
|
163
|
+
|
164
|
+
## for separator use comma (,) or pipe (|) or ???
|
165
|
+
round = String.new
|
166
|
+
## round << "#{match.stage} | " if match.stage
|
167
|
+
## round << "#{match.group} | " if match.group
|
168
|
+
round << "#{match.stage}, " if match.stage
|
169
|
+
round << "#{match.group}, " if match.group
|
170
|
+
round << match.round
|
171
|
+
|
172
|
+
rec = [
|
173
|
+
#############################
|
174
|
+
## todo/fix - split league into league_name and season!!!!
|
175
|
+
###############################
|
176
|
+
name, ## league name
|
177
|
+
match.date ? match.date : '',
|
178
|
+
match.time ? match.time : '',
|
179
|
+
match.team1,
|
180
|
+
match.team2,
|
181
|
+
(match.score1i && match.score2i) ? "#{match.score1i}-#{match.score2i}" : '',
|
182
|
+
(match.score1 && match.score2) ? "#{match.score1}-#{match.score2}" : '',
|
183
|
+
(match.score1et && match.score2et) ? "#{match.score1et}-#{match.score2et}" : '',
|
184
|
+
(match.score1p && match.score2p) ? "#{match.score1p}-#{match.score2p}" : '',
|
185
|
+
round,
|
186
|
+
match.status ? match.status : '',
|
187
|
+
]
|
188
|
+
|
189
|
+
## add more attributes e.g. ground, etc.
|
190
|
+
|
191
|
+
recs << rec
|
192
|
+
end
|
193
|
+
|
194
|
+
puts " #{recs.size} record(s)"
|
195
|
+
|
196
|
+
if quick.errors?
|
197
|
+
puts "!! #{quick.errors.size} parse error(s):"
|
198
|
+
pp quick.errors
|
199
|
+
exit 1
|
200
|
+
end
|
201
|
+
|
202
|
+
recs
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
recs = []
|
207
|
+
|
208
|
+
paths.each do |path|
|
209
|
+
if Dir.exist?( path )
|
210
|
+
puts "==> reading dir >#{path}<..."
|
211
|
+
|
212
|
+
datafiles = SportDb::Parser::Opts._find( path, seasons: opts[:seasons] )
|
213
|
+
pp datafiles
|
214
|
+
puts " #{datafiles.size} datafile(s)"
|
215
|
+
datafiles.each_with_index do |datafile,j|
|
216
|
+
puts " reading file [#{j+1}/#{datafiles.size}] >#{datafile}<..."
|
217
|
+
txt = read_text( datafile )
|
218
|
+
recs += parse( txt )
|
219
|
+
end
|
220
|
+
elsif File.exist?( path )
|
221
|
+
puts "==> reading file >#{path}<..."
|
222
|
+
txt = read_text( path )
|
223
|
+
recs += parse( txt )
|
224
|
+
else ## not a file or dir repprt errr
|
225
|
+
raise ArgumentError, "file/dir does NOT exist - #{path}"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
recs, headers = vacuum( recs )
|
231
|
+
pp recs[0,10] ## dump first 10 records
|
232
|
+
pp headers
|
233
|
+
puts " #{recs.size} record(s)"
|
234
|
+
|
235
|
+
|
236
|
+
if opts[:output]
|
237
|
+
puts "==> writing matches to #{opts[:output]}"
|
238
|
+
write_csv( opts[:output], recs,
|
239
|
+
headers: headers )
|
240
|
+
end
|
241
|
+
|
242
|
+
|
243
|
+
puts "bye"
|
244
|
+
|
data/bin/fbtxt2json
CHANGED
@@ -56,7 +56,7 @@ parser.banner = "Usage: #{$PROGRAM_NAME} [options] PATH"
|
|
56
56
|
end
|
57
57
|
|
58
58
|
parser.on( "--seasons SEASONS",
|
59
|
-
"turn on processing only seasons (default: #{!opts[:seasons].empty?}" ) do |seasons|
|
59
|
+
"turn on processing only seasons (default: #{!opts[:seasons].empty?})" ) do |seasons|
|
60
60
|
pp seasons
|
61
61
|
seasons = seasons.split( /[, ]/ )
|
62
62
|
seasons = seasons.map {|season| Season.parse(season) }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fbtxt2json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.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: 2025-04-
|
11
|
+
date: 2025-04-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sportdb-quick
|
@@ -75,6 +75,7 @@ dependencies:
|
|
75
75
|
description: fbtxt2json - convert football.txt match schedules & more to json
|
76
76
|
email: gerald.bauer@gmail.com
|
77
77
|
executables:
|
78
|
+
- fbtxt2csv
|
78
79
|
- fbtxt2json
|
79
80
|
extensions: []
|
80
81
|
extra_rdoc_files:
|
@@ -86,6 +87,7 @@ files:
|
|
86
87
|
- Manifest.txt
|
87
88
|
- README.md
|
88
89
|
- Rakefile
|
90
|
+
- bin/fbtxt2csv
|
89
91
|
- bin/fbtxt2json
|
90
92
|
homepage: https://github.com/sportdb/footty
|
91
93
|
licenses:
|