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,55 @@
1
+
2
+ ##
3
+ ## check - use ppcards.rb - why? why not?
4
+
5
+
6
+ ## use _pp_cards - why? why not?
7
+ def _pp_bookings( bookings )
8
+
9
+ ##
10
+ ## sort
11
+ ##
12
+ bookings = bookings.sort do |l,r|
13
+ l_min,l_offset = _parse_minute( l['minute'])
14
+ r_min,r_offset = _parse_minute( r['minute'])
15
+
16
+ res = l_min <=> r_min
17
+ res = (l_offset||0) <=> (r_offset||0) if res == 0
18
+ res
19
+ end
20
+
21
+ bookings.map do |b|
22
+ ## todo - fix-fix-fix - build player struct/obj
23
+ name = b['name']
24
+ minute = b['minute']
25
+ "#{name} #{minute}'"
26
+ end.join( ', ')
27
+ end
28
+
29
+
30
+ ## use pp_cards - why? why not?
31
+ def pp_bookings( yellow, yellowred, red,
32
+ players:, opts: )
33
+
34
+ buf = String.new
35
+
36
+ unless yellow.empty?
37
+ buf << " Yellow: "
38
+ buf << _pp_bookings( yellow )
39
+ buf << "\n"
40
+ end
41
+
42
+ unless yellowred.empty?
43
+ buf << " Yellow-Red: "
44
+ buf << _pp_bookings( yellowred )
45
+ buf << "\n"
46
+ end
47
+
48
+ unless red.empty?
49
+ buf << " Red: "
50
+ buf << _pp_bookings( red )
51
+ buf << "\n"
52
+ end
53
+
54
+ buf
55
+ end
@@ -0,0 +1,71 @@
1
+
2
+
3
+
4
+ def _pp_goals( recs )
5
+ players = {}
6
+
7
+ ## "fold" multiple goals of player
8
+ recs.each do |rec|
9
+ player_name = rec.name
10
+
11
+ goal = String.new
12
+ ## goal << _fmt_minute( rec[:minute], rec[:offset] )
13
+ goal << rec.minute
14
+ goal << "'" unless ['?','??'].include?(rec.minute) ## add minute marker
15
+
16
+ ## check for goal type (og) or (p)
17
+ goal << "(p)" if rec.pen?
18
+ goal << "(og)" if rec.og?
19
+
20
+ player_rec = players[ player_name ] ||= []
21
+ player_rec << goal
22
+ end
23
+
24
+
25
+ buf = players.map do |name,goals|
26
+ "#{name} #{goals.join(', ')}"
27
+ end.join( ', ' )
28
+ buf
29
+ end
30
+
31
+
32
+
33
+ def pp_goals( m, indent: 4 )
34
+
35
+ return '' if m.goals1.nil? && m.goals2.nil?
36
+
37
+
38
+ goals1 = m.goals1
39
+ goals2 = m.goals2
40
+
41
+ puts
42
+ puts " #{goals1.size}-#{goals2.size} "
43
+ pp goals1
44
+ pp goals2
45
+
46
+
47
+ buf_goals1 = _pp_goals( goals1 )
48
+ puts buf_goals1
49
+ buf_goals2 = _pp_goals( goals2 )
50
+ puts buf_goals2
51
+
52
+
53
+ buf = String.new
54
+
55
+ goal_indent = ' ' * indent
56
+
57
+ if goals1.size == 0 && goals2.size == 0
58
+ ## do nothing
59
+ elsif goals1.size > 0 && goals2.size == 0
60
+ buf << "#{goal_indent} (#{buf_goals1})\n"
61
+ elsif goals1.size == 0 && goals2.size > 0
62
+ buf << "#{goal_indent} (#{buf_goals2})\n"
63
+ elsif (goals1.size == 1 && goals2.size == 1)
64
+ buf << "#{goal_indent} (#{buf_goals1}; #{buf_goals2})\n"
65
+ else ## both sides with goals
66
+ buf << "#{goal_indent} (#{buf_goals1};\n"
67
+ buf << "#{goal_indent} #{buf_goals2})\n"
68
+ end
69
+
70
+ buf
71
+ end
@@ -0,0 +1,98 @@
1
+
2
+ def _pp_player( player, opts: )
3
+ buf = String.new
4
+
5
+ if opts.short? ## use/prefer short name - why? why not?
6
+ buf << "#{player.short_name || player.name}"
7
+ else
8
+ buf << "#{player.name}"
9
+ end
10
+
11
+ buf << " [c]" if player.captain?
12
+
13
+
14
+ ## check for y/yr/r cards
15
+ ## todo/check - change Y/R to YR - why? why ynot?
16
+ buf << " [Y #{player.y.minute}']" if player.yellow?
17
+ buf << " [Y/R #{player.yr.minute}']" if player.yellowred?
18
+ buf << " [R #{player.r.minute}']" if player.red?
19
+
20
+ ## check for sub (recursive)
21
+ if player.sub
22
+ buf << " (#{player.sub.minute}' #{_pp_player( player.sub.player, opts: opts )})"
23
+ end
24
+
25
+ buf
26
+ end
27
+
28
+
29
+ ## note - allow (optional formation e.g. 5-3-2 etc.
30
+ ##
31
+
32
+ def pp_lineup( players, indent: 6, formation: nil,
33
+ opts: )
34
+
35
+
36
+ if formation
37
+ ## split into integers
38
+ parts = formation.split( /[ ]*-[ ]*/ )
39
+ ## add 1 upfront for (implied) goalie
40
+ formation = ['1']+parts
41
+ ## e.g.
42
+ ## 1-4-3-3
43
+ ## 1-5-8-11
44
+ sum = 0 ## make cumulate sum (index)
45
+ formation = formation.map { |part| sum += part.to_i(10) }
46
+ end
47
+
48
+
49
+ lines = []
50
+ line = String.new
51
+
52
+ players.each_with_index do |player,i|
53
+ text = String.new
54
+ text << _pp_player( player, opts: opts )
55
+
56
+
57
+ next_player = players[i+1]
58
+ if next_player
59
+ if formation ### use formation for separators
60
+ if formation.include?( i+1 )
61
+ text << " - "
62
+ else
63
+ text << ", "
64
+ end
65
+ elsif next_player.pos != player.pos
66
+ text << " - " ## separate gk/def/mid/forw
67
+ else
68
+ text << ", "
69
+ end
70
+ end
71
+
72
+ if (line.length+text.length) > 88 ## start a new line
73
+ lines << line.rstrip
74
+ line = String.new
75
+ end
76
+ line << text
77
+ end
78
+
79
+ lines << line.rstrip
80
+ lines
81
+
82
+ lines.join( "\n#{' '*indent}" )
83
+ end
84
+
85
+
86
+
87
+ ###########
88
+ # officials (that is, referees)
89
+
90
+ def pp_officials( recs, opts: )
91
+ recs.map do |official|
92
+ if opts.country?
93
+ "#{official.name} (#{official.country})"
94
+ else
95
+ "#{official.name}"
96
+ end
97
+ end.join( ', ' )
98
+ end
@@ -0,0 +1,127 @@
1
+
2
+ ## pretty print matches ("summary" - not full w/ line-up, penalties etc.)
3
+
4
+
5
+ def pp_matches( season:,
6
+ slug:,
7
+ opts:,
8
+ indir: '.' )
9
+
10
+
11
+ season = Season( season )
12
+
13
+
14
+ doc = Document.read( "#{indir}/#{season.to_path}/#{slug}.json" )
15
+
16
+
17
+
18
+
19
+ buf = String.new
20
+
21
+
22
+ ## add stats block (dates, teams, matches, venues, etc.)
23
+ buf << pp_stats( doc, opts: opts )
24
+ buf << "\n"
25
+
26
+
27
+ last_round = nil
28
+ last_date = nil
29
+ last_year = nil ## track running year
30
+
31
+
32
+ doc.each_match do |m|
33
+
34
+
35
+ # stageName, groupName = norm_stage( stageName, groupName,
36
+ # team1: team1,
37
+ # team2: team2,
38
+ # date: localDateTime.strftime( '%Y-%m-%d') )
39
+
40
+
41
+ ####
42
+ ## note - make round
43
+ ## = stage + group (optional) + matchday (optional)
44
+ round = m.stage
45
+ round += ", #{m.group}" if m.group
46
+ round += " - #{m.matchday}" if m.matchday
47
+
48
+
49
+
50
+ if last_round.nil? || last_round != round
51
+
52
+ buf << "\n"
53
+
54
+ buf << "▪ #{round}\n"
55
+
56
+ last_round = round
57
+ last_date = nil
58
+ end
59
+
60
+
61
+
62
+ if last_date && (last_date.year == m.date_local.year &&
63
+ last_date.month == m.date_local.month &&
64
+ last_date.day == m.date_local.day)
65
+ ## skip date header if same (local) date
66
+ else
67
+ ## e.g. Fri Jun 7 -or- Fri Jun 7 2026
68
+ if last_year.nil? || last_year != m.date_local.year
69
+ buf << "#{m.date_local.strftime('%a %b %-e %Y')}\n"
70
+ else
71
+ buf << "#{m.date_local.strftime('%a %b %-e')}\n"
72
+ end
73
+ end
74
+
75
+
76
+ ## always print time for now
77
+ if opts.timezone?
78
+ ## use 20:30 UTC+1 or 20:30 UTC-3
79
+ buf << " #{m.date_local.strftime( '%H:%M' )} UTC%+d" % m.diff_in_hours
80
+ else
81
+ buf << " #{m.date_local.strftime( '%H:%M' )}"
82
+ end
83
+
84
+
85
+ ##
86
+ ##
87
+ ## note - if score empty (e.g. '') use A v B
88
+ score = if m.score
89
+ m.score.to_s
90
+ else
91
+ ' v '
92
+ end
93
+
94
+ if opts.clubs? && opts.country?
95
+ buf << " #{m.team1.name} (#{m.team1.country})"
96
+ buf << " #{score} "
97
+ buf << "#{m.team2.name} (#{m.team2.country}) "
98
+ else
99
+ buf << " #{m.team1.name} #{score} #{m.team2.name} "
100
+ end
101
+
102
+
103
+ if opts.stadium? ## stadium PLUS city
104
+ buf << "@ #{m.stadium.name}, #{m.stadium.city}"
105
+ elsif opts.city? ## city only
106
+ buf << "@ #{m.stadium.city}"
107
+ else
108
+ ## add nothing
109
+ end
110
+
111
+ buf << "\n"
112
+
113
+
114
+ last_date = m.date_local
115
+ last_year = m.date_local.year
116
+
117
+
118
+ ## skip adding goals if teams not yet known!!
119
+ ## fix-fix-fix -- add more checks (e.g. ResultType = ??, MatchStatus = ??) !!!
120
+ next if m.team1.dummy? || m.team2.dummy?
121
+
122
+
123
+ buf << pp_goals( m, indent: 17 )
124
+ end
125
+
126
+ buf
127
+ end
@@ -0,0 +1,222 @@
1
+
2
+
3
+
4
+ def pp_matches_full( season:,
5
+ slug:,
6
+ opts:,
7
+ indir: '.' )
8
+
9
+ season = Season( season )
10
+
11
+ doc = Document.read( "#{indir}/#{season.to_path}/#{slug}.json" )
12
+
13
+
14
+
15
+
16
+ buf = String.new
17
+
18
+ ## add stats block (dates, teams, matches, venues, etc.)
19
+ buf << pp_stats( doc, opts: opts )
20
+ buf << "\n"
21
+
22
+
23
+
24
+ last_round = nil
25
+
26
+
27
+ doc.each_match do |m|
28
+
29
+ ####
30
+ ## note - make round
31
+ ## = stage + group (optional) + matchday (optional)
32
+ round = m.stage
33
+ round += ", #{m.group}" if m.group
34
+ round += " - #{m.matchday}" if m.matchday
35
+
36
+
37
+ score = if m.score
38
+ m.score.to_s
39
+ else
40
+ ''
41
+ end
42
+
43
+ ##
44
+ ## for debugging output match line (before goals, line-up, penalties, etc)
45
+ puts " #{m.team1.name} v #{m.team2.name} #{score} - #{m.date_local}"
46
+
47
+
48
+
49
+ if last_round.nil? || last_round != round
50
+
51
+ buf << "▪ #{round}\n"
52
+
53
+ last_round = round
54
+ end
55
+
56
+
57
+
58
+ ## use Fir Jan 7 20:30 UTC+1 or 20:30 UTC-3
59
+ buf << m.date_local.strftime( '%a %b %-e %H:%M' )
60
+ buf << " UTC%+d" % m.diff_in_hours
61
+
62
+
63
+ buf << " @ #{m.stadium.name}, #{m.stadium.city}"
64
+ buf << ", Att: #{m.attendance}" if m.attendance
65
+ buf << "\n"
66
+
67
+
68
+
69
+ if opts.clubs? && opts.country?
70
+ buf << " #{m.team1.name} (#{m.team1.country}) v #{m.team2.name} (#{m.team2.country})"
71
+ else
72
+ buf << " #{m.team1.name} v #{m.team2.name}"
73
+ end
74
+ buf << " #{score}"
75
+
76
+ buf << "\n"
77
+
78
+
79
+
80
+ ## skip adding goals if teams not yet known!!
81
+ ## fix-fix-fix -- add more checks (e.g. ResultType = ??, MatchStatus = ??) !!!
82
+ next if m.team1.dummy? || m.team2.dummy?
83
+
84
+
85
+ buf << pp_goals( m, indent: 4 )
86
+
87
+
88
+ ## fix-fix-fix
89
+ ## hack - code is missing in teams!!!
90
+ pp m.team1
91
+ pp m.team2
92
+ team1_code = m.team1.code || m.team1.country
93
+ team2_code = m.team2.code || m.team2.country
94
+
95
+ ### get match (live) details
96
+ live = read_json( "#{indir}/#{season.to_path}/#{slug}/#{m.date_local.strftime('%Y-%m-%d')}_#{team1_code}-#{team2_code}.json" )
97
+
98
+
99
+
100
+ ##########
101
+ ## add penalty kicks / penalties
102
+
103
+ penalties = (live['penalties']||[]).map { |rec| Penalty.build(rec) }
104
+
105
+ unless penalties.empty?
106
+ buf << "\n"
107
+ buf << "Penalties: #{pp_penalties( penalties, indent: 11 )}\n"
108
+ end
109
+
110
+
111
+
112
+
113
+ players1 = Players.new
114
+ players1.add_starter( live['lineup1'] )
115
+ players1.add_bench( live['bench1']||[])
116
+ players1.add_subs( live['subs1']||[])
117
+
118
+ if opts.inline_cards?
119
+ players1.add_yellow( live['yellow1']||[])
120
+ players1.add_yellowred( live['yellowred1']||[]) ## second yellow (resulting in red)
121
+ players1.add_red( live['red1']||[])
122
+ ### check for bookings too (change to bookings/cards - why? why not?)
123
+ ## players1.add_bookings( live['HomeTeam']['Bookings'])
124
+ end
125
+
126
+ players2 = Players.new
127
+ players2.add_starter( live['lineup2'] )
128
+ players2.add_bench( live['bench2']||[])
129
+ players2.add_subs( live['subs2']||[])
130
+
131
+ if opts.inline_cards?
132
+ players2.add_yellow( live['yellow2']||[])
133
+ players2.add_yellowred( live['yellowred2']||[]) ## second yellow (resulting in red)
134
+ players2.add_red( live['red2']||[])
135
+ ### check for bookings too (change to bookings/cards - why? why not?)
136
+ ## players2.add_bookings( live['AwayTeam']['Bookings'])
137
+ end
138
+
139
+
140
+
141
+ lineup1 = players1.lineup
142
+ lineup2 = players2.lineup
143
+
144
+ ## pp lineup1
145
+ ## pp lineup2
146
+
147
+ buf << "\n"
148
+
149
+
150
+ buf << "#{m.team1.name}: "+ pp_lineup( lineup1, formation: live['formation1'], opts: opts ) + "\n"
151
+ unless opts.inline_cards?
152
+ buf << pp_bookings( live['yellow1']||[],
153
+ live['yellowred1']||[],
154
+ live['red1']||[],
155
+ players: players1, opts: opts )
156
+ buf << "\n"
157
+ end
158
+
159
+ buf << "#{m.team2.name}: "+ pp_lineup( lineup2, formation: live['formation2'], opts: opts ) + "\n"
160
+ unless opts.inline_cards?
161
+ buf << pp_bookings( live['yellow2']||[],
162
+ live['yellowred2']||[],
163
+ live['red2']||[],
164
+ players: players2, opts: opts )
165
+ end
166
+
167
+
168
+ buf << "\n"
169
+
170
+
171
+ =begin
172
+
173
+ if players1.size == 0 &&
174
+ players2.size == 0
175
+ puts "!! WARN - no players available - skipping line-ups for teams!!!!!"
176
+ else
177
+ ## 1954-06-20 - only 10 player in south koera team listed!!
178
+ ## 2021-02-07T21:00:00+00:00 expected 11 players, got 10
179
+ ## 2021-02-11T18:00:00+00:00 expected 11 players, got 10
180
+ if !((team1[:name] == 'Turkey' && team2[:name] == 'South Korea') ||
181
+ (team1[:name] == 'Palmeiras' && team2[:name] == 'Tigres UANL') ||
182
+ (team1[:name] == 'Al Ahly FC' && team2[:name] == 'Palmeiras')
183
+ )
184
+
185
+
186
+ [lineup1,lineup2].each do |lineup|
187
+ if lineup.size != 11
188
+
189
+ players1.dump
190
+ puts "---"
191
+ players2.dump
192
+ puts "---"
193
+
194
+ pp lineup
195
+
196
+ puts " in match #{team1[:name]} v #{team2[:name]} #{score}"
197
+ puts " #{localDateTime}"
198
+ end
199
+
200
+ assert( lineup.size == 11, "expected 11 players, got #{lineup.size}" )
201
+ end
202
+ end
203
+ =end
204
+
205
+ ###
206
+ ## add referees
207
+ officials = live['referees'].map { |rec| Official.build(rec) }
208
+
209
+ if officials.size == 0
210
+ ## puts "!! WARN no refs / officials found"
211
+ else
212
+ buf << "Refs: " + pp_officials( officials, opts: opts )
213
+ buf << "\n"
214
+ end
215
+
216
+
217
+ buf << "\n\n"
218
+ end
219
+
220
+
221
+ buf
222
+ end
@@ -0,0 +1,68 @@
1
+
2
+ ## pretty print matches ("summary" - not full w/ line-up, penalties etc.)
3
+
4
+
5
+ def pp_matches_min( season:,
6
+ slug:,
7
+ opts:,
8
+ indir: '.' )
9
+
10
+ season = Season( season )
11
+
12
+ doc = Document.read( "#{indir}/#{season.to_path}/#{slug}.json" )
13
+
14
+
15
+
16
+
17
+
18
+ buf = String.new
19
+
20
+ ## add stats block (dates, teams, matches, venues, etc.)
21
+ buf << pp_stats( doc, opts: opts )
22
+ buf << "\n"
23
+
24
+
25
+ last_round = nil
26
+
27
+ doc.each_match do |m|
28
+
29
+
30
+ round = m.stage
31
+ round += ", #{m.group}" if m.group
32
+ round += " - #{m.matchday}" if m.matchday
33
+
34
+
35
+ if last_round.nil? || last_round != round
36
+ buf << "\n"
37
+ buf << "▪ #{round}\n"
38
+
39
+ last_round = round
40
+ end
41
+
42
+
43
+
44
+ score = if m.score
45
+ m.score.to_s
46
+ else
47
+ ''
48
+ end
49
+
50
+
51
+ if opts.clubs? && opts.country?
52
+ line = "#{m.team1.name} (#{m.team1.country})"
53
+ line << " v "
54
+ line << "#{m.team2.name} (#{m.team2.country})"
55
+
56
+ buf << " %-40s " % line
57
+ else
58
+ line = "#{m.team1.name} v #{m.team2.name}"
59
+
60
+ buf << " %-30s " % line
61
+ end
62
+ buf << "#{score}"
63
+
64
+ buf << "\n"
65
+ end
66
+
67
+ buf
68
+ end