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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 66b36b917ccd87f925171e33aadc3edd58db330f7f46af0a8c7ca7f36060ba2d
4
- data.tar.gz: 324a37bb90fdb2badf86e187c8e422eca9ecead101cbc057a638aac247b86e65
3
+ metadata.gz: 5ef1887740ca10a869bb772542efbd1c0f96bfdfd17368e425c104f6653c497c
4
+ data.tar.gz: 45d1fb3ec650e499c9c0f8318dc56c942d92806d76e4a534e0ee0d541da20f5b
5
5
  SHA512:
6
- metadata.gz: f4c5dcac2a7ba88ab44943536bbad963bc5897d641076ae4f9af078d87d49be40e7a0cd853547a6bd247ae39f69a83c08d12ef941cc7fb5b4a1f9d36820370dd
7
- data.tar.gz: 1336d12e9b6009b970ac4f7401146790a6dca5cd08098add1956fba224a5f6aef8ec82da36b0310c0c0296f35ee24041eb097d3178215ba27e6bcf1233e5aace
6
+ metadata.gz: af4f21b7f278fced209a80fac3c043868c64c82b5c1246da38bb56774ff34f4df06404a661ef0c449e0a62eca02dcd4e20f64826cab3011530761078f18db594
7
+ data.tar.gz: c1dc3ea735f2af33794c708be36bf9c6bb6ff37ae2d8cc218c61005fc923ed1775a7f7c2955c4755bc24b364020bf69924a53cacfafb6af6fa30c20b3951cd45
data/CHANGELOG.md CHANGED
@@ -1,4 +1,4 @@
1
- ### 0.2.2
1
+ ### 0.3.0
2
2
  ### 0.0.1 / 2024-09-28
3
3
 
4
4
  * Everything is new. First release.
data/Manifest.txt CHANGED
@@ -2,4 +2,5 @@ CHANGELOG.md
2
2
  Manifest.txt
3
3
  README.md
4
4
  Rakefile
5
+ bin/fbtxt2csv
5
6
  bin/fbtxt2json
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'hoe'
2
2
 
3
3
 
4
4
  Hoe.spec 'fbtxt2json' do
5
- self.version = '0.2.2'
5
+ self.version = '0.3.0'
6
6
 
7
7
  self.summary = "fbtxt2json - convert football.txt match schedules & more to json"
8
8
  self.description = summary
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.2.2
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-06 00:00:00.000000000 Z
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: