fbtxt-pp 0.0.2

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.
@@ -0,0 +1,92 @@
1
+
2
+
3
+
4
+ ##
5
+ ## opt_country: true|false -- add country code for clubs
6
+ ## opt_stadium: false|true -- print only city (NOT long stadium+city)
7
+
8
+
9
+ ## use OptsFormat or OptsPP or such - why? why not?
10
+
11
+ ## change format to opts for entities (time/team/etc.) - why? why not?
12
+ ## use - time: timezone
13
+ ## - venue/ground/stadium: city|stadium
14
+ ## - team: country
15
+
16
+ class FormatOpts
17
+
18
+ def self.build_min( **kwargs )
19
+ new( **{ city: false,
20
+ stadium: false,
21
+ timezone: false,
22
+ country: false,
23
+ }.merge( kwargs ))
24
+ end
25
+
26
+ def self.build( **kwargs )
27
+ new( **{ city: true,
28
+ stadium: true,
29
+ timezone: true,
30
+ country: false,
31
+ }.merge( kwargs ))
32
+ end
33
+
34
+ def self.build_full( **kwargs )
35
+ new( **{ city: true,
36
+ stadium: true,
37
+ timezone: true,
38
+ country: false,
39
+ }.merge( kwargs))
40
+ end
41
+
42
+
43
+ def initialize( city:,
44
+ stadium:,
45
+ timezone:,
46
+ country:,
47
+ clubs: true, ## true|false (allow use nati(onal) as reverse?)
48
+ ####
49
+ inline_cards: false,
50
+ ## fix- change to short_names - why? why not?
51
+ short: false, ## use short (player/referee/etc.) names true|false
52
+ ####
53
+ ## (stats) headers
54
+ ## use list_stadiums or such - why? why not?
55
+ show_stadiums: false,
56
+ show_teams: false,
57
+ show_stages: false
58
+ )
59
+ @city = city
60
+ @stadium = stadium
61
+ ## incl. timezone to time
62
+ @timezone = timezone
63
+ ## incl. country code in team name?
64
+ @country = country
65
+
66
+
67
+ @inline_cards = inline_cards
68
+ @short = short
69
+ @clubs = clubs
70
+
71
+ ## stats header
72
+ ## print/list teams
73
+ @show_teams = show_teams
74
+ @show_stadiums = show_stadiums
75
+ @show_stages = show_stages
76
+ end
77
+
78
+ def city?() @city; end
79
+ def stadium?() @stadium; end
80
+ def timezone?() @timezone; end
81
+ def country?() @country; end
82
+
83
+ def inline_cards?() @inline_cards; end
84
+
85
+ def short?() @short; end
86
+
87
+ def clubs?() @clubs; end
88
+
89
+ def show_teams?() @show_teams; end
90
+ def show_stadiums?() @show_stadiums; end
91
+ def show_stages?() @show_stages; end
92
+ end # class FormatOpts
@@ -0,0 +1,32 @@
1
+
2
+
3
+ def _pp_pen( pen )
4
+ if pen.scored?
5
+ "#{pen.score[0]}-#{pen.score[1]} #{pen.name}"
6
+ else
7
+ ### fix - check for saved or crossbar or ????
8
+ " #{pen.name} (missed)"
9
+ end
10
+ end
11
+
12
+ def _pp_pens( pen1, pen2 )
13
+ buf = String.new
14
+ buf << _pp_pen( pen1 )
15
+ if pen2
16
+ buf << ", "
17
+ buf << _pp_pen( pen2 )
18
+ end
19
+ buf
20
+ end
21
+
22
+
23
+ def pp_penalties( pens, indent: )
24
+ lines = []
25
+ line = String.new
26
+
27
+ pens.each_slice(2) do |pen1, pen2|
28
+ lines << _pp_pens( pen1, pen2 )
29
+ end
30
+
31
+ lines.join( ",\n#{' '*indent}" )
32
+ end
@@ -0,0 +1,224 @@
1
+
2
+ ##
3
+ ## check - maybe add Heights (e.g. 195.0)
4
+
5
+
6
+
7
+ POS = {
8
+ 0 => 'GK', # goalkeeper
9
+ 1 => 'DF', # defender
10
+ 2 => 'MF', # midfielder
11
+ 3 => 'FW', # forward
12
+ 4 => '?', # unknown !!!
13
+ }
14
+
15
+ def pp_squads( slug:,
16
+ season:,
17
+ opt_jerseys: true,
18
+ opt_country: false )
19
+
20
+ data = read_json( "./#{slug}/misc/#{season}_squads.json" )
21
+ data = data['Results']
22
+
23
+ puts " #{data.size} result(s)"
24
+
25
+
26
+ buf = String.new
27
+ buf << "# #{data.size} Teams\n\n"
28
+
29
+
30
+ puts "#{slug} #{season} # #{data.size} Teams"
31
+
32
+
33
+
34
+ data.each_with_index do |h,i|
35
+
36
+ team = desc( h['TeamName'])
37
+ country = h['IdCountry']
38
+
39
+ ## e.g. Germany FR => West Germany, etc.
40
+ team = norm_team( team )
41
+
42
+
43
+
44
+ players = h['Players']
45
+
46
+ if opt_country
47
+ buf << "== #{team} (#{country})"
48
+ else
49
+ buf << "== #{team}"
50
+ end
51
+
52
+ buf << " # #{players.size} Players\n\n"
53
+
54
+
55
+
56
+
57
+ puts "== [#{i+1}/#{data.size}] #{team} - #{players.size} player(s)"
58
+
59
+ players = players.sort do |l,r|
60
+ res = l['Position'] <=> r['Position']
61
+ if res == 0 && opt_jerseys
62
+ res = (l['JerseyNum']||999) <=> (r['JerseyNum']||999)
63
+ end
64
+ res
65
+ end
66
+
67
+ ## use max country - why? why not?
68
+ ## 1934 Austria first is not AUT - check??
69
+
70
+ firstIdCountry = players[2]['IdCountry']
71
+ last_pos = nil
72
+
73
+ players.each do |player|
74
+
75
+ name = desc( player['PlayerName'])
76
+
77
+ name = norm_player( name )
78
+
79
+ ##
80
+ ## check player name if include parentheses or such
81
+ ## GILMAR (Gilmar Dos Santos Neves) - 1958 Brazil
82
+ ## PELÉ (Edson Arantes do Nascimento)
83
+
84
+ ## ROMÁRIO (Romário de Souza Faria)
85
+ ## only allow alpha and space
86
+ if !is_alpha?( name )
87
+ puts "!! invalid player name:"
88
+ pp player
89
+ pp name
90
+ exit 1
91
+ end
92
+
93
+
94
+ pos = player['Position']
95
+ jersey = player['JerseyNum']
96
+
97
+ assert( [0,1,2,3,4].include?(pos),
98
+ "pos 0/1/2/3/4 expected; got #{player.pretty_inspect}" )
99
+
100
+ ## note - birth_date is OPTIONAL (not available for all)
101
+ bday = player['BirthDate'] ? parse_date( player['BirthDate']) : nil
102
+
103
+
104
+ idCountry = player['IdCountry']
105
+
106
+ # if lastIdCountry
107
+ # assert( idCountry == lastIdCountry,
108
+ # "country code do NOT match #{idCountry} != #{lastIdCountry}" )
109
+ # end
110
+
111
+
112
+ ## add a blank line between GK/DF/MF/FW/? (unknown)
113
+ buf << "\n" if last_pos && last_pos != pos
114
+
115
+
116
+ name_col = if opt_country
117
+ ## check if player country is different from team country
118
+ if country != idCountry
119
+ "#{name} (#{idCountry}),"
120
+ else
121
+ "#{name},"
122
+ end
123
+ else
124
+ if firstIdCountry != idCountry
125
+ ## ignore country code - why? why not?
126
+ puts "!! country code do NOT match #{idCountry}; #{firstIdCountry} expected"
127
+ pp player
128
+
129
+ ## "#{name} (#{idCountry}),"
130
+ "#{name},"
131
+ else
132
+ "#{name},"
133
+ end
134
+ end
135
+
136
+ cols = [name_col,
137
+ "#{POS[pos]},",
138
+ bday ? "b. #{bday.strftime('%Y/%m/%d')}" :
139
+ ""
140
+ ]
141
+
142
+ if opt_jerseys
143
+ cols = ["#{jersey},"] + cols
144
+ buf << " %6s %-30s %-4s %-10s" % cols
145
+ else
146
+ buf << " %-30s %-4s %-10s" % cols
147
+ end
148
+
149
+ buf << "\n"
150
+
151
+ last_pos = pos
152
+ end
153
+
154
+
155
+ officials = h['Officials'] ## coaches
156
+
157
+ if officials.size > 0
158
+
159
+ buf << "\n"
160
+
161
+ officials.each do |official|
162
+
163
+ name = desc( official['Name'])
164
+ name = norm_official( name ) ## replace non-breaking spaces
165
+
166
+ if !is_alpha?( name )
167
+ puts "!! invalid official name:"
168
+ pp official
169
+ pp name
170
+ exit 1
171
+ end
172
+
173
+
174
+ role = official['Role']
175
+ idCountry = official['IdCountry']
176
+
177
+ assert( [0,1].include?(role),
178
+ "role 0/1 expected; got #{official.pretty_inspect}" )
179
+
180
+ ## skip co-coaches - why? why not?
181
+ next if role == 1
182
+ # " skip co-coach: #{official.pretty_inspect}"
183
+
184
+
185
+
186
+ ## note - birth_date is OPTIONAL (not available for all)
187
+ bday = official['BirthDate'] ? parse_date( official['BirthDate']) : nil
188
+
189
+
190
+ ## 0 -> mg = manager
191
+ ## 1 -> am = assistant manager
192
+ ## or use co (coach), ac (assistiant coach) ??
193
+
194
+
195
+ ##
196
+ ## for now add country code (cc) to all managers/coaches
197
+
198
+ ## firstIdCountry != idCountry ? "#{name} (#{idCountry})," : "#{name},"
199
+
200
+ cols = [ "#{name} (#{idCountry}),",
201
+ role == 0 ? "MG," : "AM,",
202
+ bday ? "b. #{bday.strftime('%Y/%m/%d')}" :
203
+ ""
204
+ ]
205
+
206
+ if opt_jerseys
207
+ cols = ["-,"] + cols
208
+ buf << " %6s %-30s %-4s %-10s" % cols
209
+ else
210
+ buf << " %-30s %-4s %-10s" % cols
211
+ end
212
+ buf << "\n"
213
+
214
+ end
215
+ buf << "\n\n"
216
+ end
217
+
218
+
219
+
220
+ end
221
+ buf
222
+ end
223
+
224
+
@@ -0,0 +1,60 @@
1
+
2
+ def pp_stats( doc, opts: )
3
+
4
+
5
+ buf = String.new
6
+
7
+ ####
8
+ # dates
9
+ # - start/end dates and duration in days
10
+
11
+ start_date, end_date = doc.calc_start_end_dates
12
+
13
+ diff_in_days = end_date.jd - start_date.jd
14
+ diff_in_years = end_date.year - start_date.year
15
+
16
+ buf << "# Dates "
17
+ if diff_in_years > 0
18
+ buf << "#{start_date.strftime('%a %b %-e %Y')} - #{end_date.strftime('%a %b %-e %Y')}"
19
+ else
20
+ buf << "#{start_date.strftime('%a %b %-e')} - #{end_date.strftime('%a %b %-e %Y')}"
21
+ end
22
+ buf << " (#{diff_in_days}d)\n"
23
+
24
+ ########
25
+ # teams
26
+ # - number of matches
27
+ buf << "# Teams #{doc.teams.size}\n"
28
+
29
+ if opts.show_teams?
30
+ ##
31
+ ## sort teams by country - why? why not?
32
+ doc.teams.each do |team|
33
+ buf << "# #{team.name} (#{team.country})\n"
34
+ end
35
+ end
36
+
37
+ ######
38
+ # matches
39
+ # - number of teams
40
+ buf << "# Matches #{doc.matches.size}\n"
41
+
42
+
43
+ #####
44
+ # venues
45
+ # - all stadiums
46
+
47
+ if opts.show_stadiums?
48
+ buf << "# Venues #{doc.stadiums.size}"
49
+ cities = doc.stadiums.cities
50
+ buf << (cities.size == 1 ? " (in 1 city)" : " (in #{cities.size} cities)")
51
+ buf << "\n"
52
+
53
+ doc.stadiums.each do |stadium|
54
+ buf << "# #{stadium.name}, #{stadium.city} (#{stadium.country})\n"
55
+ end
56
+ end
57
+
58
+
59
+ buf
60
+ end
@@ -0,0 +1,204 @@
1
+
2
+ ##
3
+ ## kind of a new version of fbup !!!
4
+ ## works with json datasources (not csv)
5
+ ## maybe merge later into one
6
+
7
+
8
+ module Fbhub
9
+
10
+
11
+ LEAGUE_CODES = {
12
+ 'de' => 'de.1',
13
+ 'eng' => 'eng.1',
14
+ 'es' => 'es.1',
15
+ 'it' => 'it.1',
16
+ 'fr' => 'fr.1',
17
+ 'at' => 'at.1',
18
+ 'mx' => 'mx.1',
19
+ }
20
+
21
+
22
+
23
+ def self.main( args=ARGV )
24
+
25
+ opts = {
26
+ push: false,
27
+ ffwd: false,
28
+
29
+ full: true, ## add full details page - true|false
30
+ test: true, ## true, ## sets push & ffwd to false
31
+ test_dir: './o',
32
+ convert_dir: '/sports/cache.api.fifa',
33
+ file: nil,
34
+ }
35
+
36
+
37
+ parser = OptionParser.new do |parser|
38
+ parser.banner = "Usage: #{$PROGRAM_NAME} [options] [args]"
39
+
40
+ parser.on( "-p", "--[no-]push",
41
+ "fast forward sync and commit & push changes to git repo - default is (#{opts[:push]})" ) do |push|
42
+ opts[:push] = push
43
+ if opts[:push] ## note: autoset ffwd too if push == true
44
+ opts[:ffwd] = true
45
+ opts[:test] = false
46
+ end
47
+ end
48
+ ## todo/check - add a --ffwd flag too - why? why not?
49
+
50
+ parser.on( "-t", "--test",
51
+ "test run; writing output to #{opts[:test_dir]} - default is #{opts[:test]}" ) do |test|
52
+ opts[:test] = true
53
+ opts[:push] = false
54
+ opts[:ffwd] = false
55
+ end
56
+
57
+ parser.on( "-f FILE", "--file FILE",
58
+ "read leagues (and seasons) via .csv file") do |file|
59
+ opts[:file] = file
60
+ end
61
+ end
62
+ parser.parse!( args )
63
+
64
+
65
+
66
+ puts "OPTS:"
67
+ pp opts
68
+
69
+
70
+ datasets = if opts[:file]
71
+ recs = read_csv( opts[:file] )
72
+
73
+ datasets = recs.map do |rec|
74
+ ## auto-convert season to season obj - why? why not?
75
+ ## use Season.parse_line
76
+ [ rec['league'],
77
+ Season.parse_line( rec['seasons'])]
78
+ end
79
+ else
80
+ puts "!! error: --file FILE option for now required; sorry"
81
+ exit 1
82
+ end
83
+
84
+
85
+ pp datasets
86
+
87
+
88
+ ####
89
+ # get github repos for (league) slugs/codes
90
+
91
+ root_dir = if opts[:test]
92
+ opts[:test_dir]
93
+ else
94
+ Fbup::GitHubSync.root # e.g. "/sports"
95
+ end
96
+
97
+ puts " (output) root_dir: >#{root_dir}<"
98
+
99
+
100
+ repos = Fbup::GitHubSync.find_repos( datasets )
101
+ puts " #{repos.size} repo(s):"
102
+ pp repos
103
+
104
+ sync = Fbup::GitHubSync.new( repos )
105
+ puts " sync:"
106
+ pp sync
107
+
108
+ sync.git_fast_forward_if_clean if opts[:ffwd]
109
+
110
+
111
+
112
+ datasets.each do |slug, seasons|
113
+ puts "==> gen #{slug} - #{seasons.size} seasons(s)..."
114
+
115
+ config = CONFIGS[ slug ]
116
+ if config.nil?
117
+ puts "!! no pp config found for slug >#{slug}<; keys/codes include:"
118
+ pp CONFIGS.keys
119
+ exit 1
120
+ end
121
+
122
+ seasons.each do |season|
123
+ ## get repo config for flags and more
124
+ repo = Fbup::GitHubSync::REPOS[ slug ]
125
+ flags = repo['flags'] || {}
126
+ classic_flag = flags['classic'] || false
127
+
128
+ pp repo
129
+
130
+
131
+ basename = nil
132
+ if classic_flag
133
+ league_config = Fbup::LeagueConfig.find_by( code: LEAGUE_CODES[slug]||slug,
134
+ season: season )
135
+ if league_config.nil?
136
+ puts "!! ERROR - basename league config required for classic format; no config found for #{league_query} #{season}; sorry"
137
+ exit 1
138
+ end
139
+ basename = league_config['basename']
140
+ else
141
+ ## change base name to league key
142
+ ## todo - fix - make gsub smarter
143
+ ## change at.cup to at_cup - why? why not?
144
+ basename = (LEAGUE_CODES[slug]||slug).gsub( '.', '' )
145
+ end
146
+
147
+
148
+ repo_path = "#{repo['owner']}/#{repo['name']}"
149
+ repo_path << "/#{repo['path']}" if repo['path'] ## note: do NOT forget to add optional extra path!!!
150
+
151
+
152
+ outpath = "#{root_dir}/#{repo_path}"
153
+ outpath += if classic_flag
154
+ "/#{season.to_path}/#{basename}.txt"
155
+ else
156
+ ## note - add season "inline" (to basename) or use dir
157
+ "/#{season.to_path}_#{basename}.txt"
158
+ end
159
+
160
+ outpath_full = "#{root_dir}/#{repo_path}"
161
+ outpath_full += if classic_flag
162
+ "/#{season.to_path}/#{basename}-full.txt"
163
+ else
164
+ ## note - add season "inline" (to basename) or use dir
165
+ "/#{season.to_path}_#{basename}-full.txt"
166
+ end
167
+
168
+ puts " writing to >#{outpath}<..."
169
+ puts " writing (full) to >#{outpath_full}<..."
170
+
171
+ league_name = config[:name]
172
+ format_opts = config[:opts]
173
+ format_opts_full = config[:opts_full]
174
+
175
+ header = String.new
176
+ header << "= #{league_name} #{season}\n\n"
177
+
178
+ buf = pp_matches( slug: slug, season: season,
179
+ indir: opts[:convert_dir],
180
+ opts: FormatOpts.build( **format_opts ))
181
+
182
+ puts buf[0..300]
183
+ write_text( outpath, header+buf )
184
+
185
+ if opts[:full]
186
+ buf = pp_matches_full( slug: slug, season: season,
187
+ indir: opts[:convert_dir],
188
+ opts: FormatOpts.build_full( **format_opts_full ))
189
+
190
+
191
+ puts buf[0..300]
192
+ write_text( outpath_full, header+buf )
193
+ end
194
+ end
195
+ end
196
+
197
+
198
+ sync.git_push_if_changes if opts[:push]
199
+
200
+
201
+ puts "bye"
202
+ end
203
+
204
+ end ## module Fbhub