Top Level Namespace
Defined Under Namespace
Modules: Fbhub, Fbpp, Fbtxt Classes: Document, FormatOpts, Goal, Match, Official, Penalty, Player, Players, Score, Stadium, Stadiums, Team, Teams
Constant Summary collapse
- FORMAT_OPTS_DEFAULTS =
defaults
{ country: false, city: false, stadium: false, timezone: false, }
- FORMAT_OPTS_FULL_DEFAULTS =
{ country: false, city: true, stadium: true, timezone: true, show_teams: false, show_stadiums: false, }
- CONFIGS =
{}
- MINUTE_RE =
%r{ \A (?<minute>\d{1,3}) '? ( \+ (?<offset>\d{1,2}) '? )? \z }x- POS =
{ 0 => 'GK', # goalkeeper 1 => 'DF', # defender 2 => 'MF', # midfielder 3 => 'FW', # forward 4 => '?', # unknown !!! }
- TEAM_MODS =
{ ## nati(onal) teams (e.g. world cup) ## map "offical" country names to common country names 'Germany FR' => 'West Germany', 'German DR' => 'East Germany', 'Korea Republic' => 'South Korea', 'Korea DPR' => 'North Korea', 'China PR' => 'China', 'Republic of Ireland' => 'Ireland', 'IR Iran' => 'Iran', 'United States' => 'USA', 'Czechia' => 'Czech Republic', 'Türkiye' => 'Turkey', ## Côte d'Ivoire [fr] => Ivory Coast ??? ## austria (at) ## remove cut-out (commerical) sponsor names 'RZ Pellets WAC' => 'Wolfsberger AC', ## WAC 'CASHPOINT SCR Altach' => 'SCR Altach', 'SV Guntamatic Ried' => 'SV Ried', }
Instance Method Summary collapse
- #_fmt_minute(minute, offset) ⇒ Object
- #_parse_format_opts(str) ⇒ Object
- #_parse_minute(str) ⇒ Object
-
#_pp_bookings(bookings) ⇒ Object
use _pp_cards - why? why not?.
- #_pp_goals(recs) ⇒ Object
- #_pp_pen(pen) ⇒ Object
- #_pp_pens(pen1, pen2) ⇒ Object
- #_pp_player(player, opts:) ⇒ Object
- #assert(test, msg) ⇒ Object
-
#banner ⇒ Object
say hello.
- #norm_name(str) ⇒ Object
- #parse_date_local(date_str) ⇒ Object
- #parse_date_utc(date_str) ⇒ Object
-
#pp_bookings(yellow, yellowred, red, players:, opts:) ⇒ Object
use pp_cards - why? why not?.
- #pp_goals(m, indent: 4) ⇒ Object
-
#pp_lineup(players, indent: 6, formation: nil, opts:) ⇒ Object
note - allow (optional formation e.g. 5-3-2 etc..
- #pp_matches(season:, slug:, opts:, indir: '.') ⇒ Object
- #pp_matches_full(season:, slug:, opts:, indir: '.') ⇒ Object
- #pp_matches_min(season:, slug:, opts:, indir: '.') ⇒ Object
-
#pp_officials(recs, opts:) ⇒ Object
officials (that is, referees).
- #pp_penalties(pens, indent:) ⇒ Object
- #pp_squads(slug:, season:, opt_jerseys: true, opt_country: false) ⇒ Object
- #pp_stats(doc, opts:) ⇒ Object
- #read_config_pp(*paths) ⇒ Object
- #slugify(str) ⇒ Object
Instance Method Details
#_fmt_minute(minute, offset) ⇒ Object
61 62 63 64 65 66 67 68 69 |
# File 'lib/fbtxt-pp/helper.rb', line 61 def _fmt_minute( minute, offset ) ## pp [minute,offset] buf = String.new buf << "#{minute}" buf << "+#{offset}" if offset buf << "'" buf end |
#_parse_format_opts(str) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/fbtxt-pp/config.rb', line 22 def _parse_format_opts( str ) h = {} keys = str.split( /[ ]*\|[ ]*/ ) keys.each do |key| case key.to_sym when :country then h[:country] = true when :city then h[:city] = true else raise ArgumentError, "unknown key #{key} in format opts" end end h end |
#_parse_minute(str) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/fbtxt-pp/helper.rb', line 47 def _parse_minute( str ) ## support weirdo 120'+-30' -- remove minuts str = str.gsub( '-', '' ) m = MINUTE_RE.match( str ) raise ArgumentError, "unknown goal minute format in #{str.inspect}" if m.nil? minute = m[:minute].to_i(10) offset = m[:offset] ? m[:offset].to_i(10) : nil [minute,offset] end |
#_pp_bookings(bookings) ⇒ Object
use _pp_cards - why? why not?
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/fbtxt-pp/pp/ppbookings.rb', line 7 def _pp_bookings( bookings ) ## ## sort ## bookings = bookings.sort do |l,r| l_min,l_offset = _parse_minute( l['minute']) r_min,r_offset = _parse_minute( r['minute']) res = l_min <=> r_min res = (l_offset||0) <=> (r_offset||0) if res == 0 res end bookings.map do |b| ## todo - fix-fix-fix - build player struct/obj name = b['name'] minute = b['minute'] "#{name} #{minute}'" end.join( ', ') end |
#_pp_goals(recs) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/fbtxt-pp/pp/ppgoals.rb', line 4 def _pp_goals( recs ) players = {} ## "fold" multiple goals of player recs.each do |rec| player_name = rec.name goal = String.new ## goal << _fmt_minute( rec[:minute], rec[:offset] ) goal << rec.minute goal << "'" unless ['?','??'].include?(rec.minute) ## add minute marker ## check for goal type (og) or (p) goal << "(p)" if rec.pen? goal << "(og)" if rec.og? player_rec = players[ player_name ] ||= [] player_rec << goal end buf = players.map do |name,goals| "#{name} #{goals.join(', ')}" end.join( ', ' ) buf end |
#_pp_pen(pen) ⇒ Object
3 4 5 6 7 8 9 10 |
# File 'lib/fbtxt-pp/pp/pppenalties.rb', line 3 def _pp_pen( pen ) if pen.scored? "#{pen.score[0]}-#{pen.score[1]} #{pen.name}" else ### fix - check for saved or crossbar or ???? " #{pen.name} (missed)" end end |
#_pp_pens(pen1, pen2) ⇒ Object
12 13 14 15 16 17 18 19 20 |
# File 'lib/fbtxt-pp/pp/pppenalties.rb', line 12 def _pp_pens( pen1, pen2 ) buf = String.new buf << _pp_pen( pen1 ) if pen2 buf << ", " buf << _pp_pen( pen2 ) end buf end |
#_pp_player(player, opts:) ⇒ Object
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/fbtxt-pp/pp/pplineup.rb', line 2 def _pp_player( player, opts: ) buf = String.new if opts.short? ## use/prefer short name - why? why not? buf << "#{player.short_name || player.name}" else buf << "#{player.name}" end buf << " [c]" if player.captain? ## check for y/yr/r cards ## todo/check - change Y/R to YR - why? why ynot? buf << " [Y #{player.y.minute}']" if player.yellow? buf << " [Y/R #{player.yr.minute}']" if player.yellowred? buf << " [R #{player.r.minute}']" if player.red? ## check for sub (recursive) if player.sub buf << " (#{player.sub.minute}' #{_pp_player( player.sub.player, opts: opts )})" end buf end |
#assert(test, msg) ⇒ Object
3 4 5 6 7 8 9 |
# File 'lib/fbtxt-pp/helper.rb', line 3 def assert( test, msg ) if test else puts "!! ASSERT FAILED - #{msg}" exit 1 end end |
#norm_name(str) ⇒ Object
11 12 13 14 15 16 17 18 19 20 |
# File 'lib/fbtxt-pp.rb', line 11 def norm_name( str ) ## todo/fix - add/report to console if space collaped or dash trimmed etc. ## collapse spaces into one ## e.g. str = str.gsub( /[ ]+/, ' ' ) ## remove leading & trailing space around dash (-) ## e.g. Callum HUDSON - ODOI => Callum HUDSON-ODOI str = str.gsub( / - /, '-' ) str end |
#parse_date_local(date_str) ⇒ Object
26 27 28 29 30 31 32 33 34 |
# File 'lib/fbtxt-pp/helper.rb', line 26 def parse_date_local( date_str ) ## fix - parse UTC+-offset !!!! ## e.g. 2025-08-01 20:30 UTC+2 date = DateTime.strptime( date_str, '%Y-%m-%d %H:%M UTC%z' ) ## assert( date_str == date.strftime('%Y-%m-%dT%H:%MZ'), ## "date parse expected #{date_str} - got #{date.inspect}" ) date end |
#parse_date_utc(date_str) ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/fbtxt-pp/helper.rb', line 12 def parse_date_utc( date_str ) ## note - DateTime has NOT daylight saving time (e.g. dst?) ## or named timezones!! ## only works with offsets ## ## use Time for built-in timezones (and check on daylight saving time etc.) date = DateTime.strptime( date_str, '%Y-%m-%dT%H:%M%z' ) assert( date_str == date.strftime('%Y-%m-%dT%H:%MZ'), "date parse expected #{date_str} - got #{date.inspect}" ) date end |
#pp_bookings(yellow, yellowred, red, players:, opts:) ⇒ Object
use pp_cards - why? why not?
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/fbtxt-pp/pp/ppbookings.rb', line 31 def pp_bookings( yellow, yellowred, red, players:, opts: ) buf = String.new unless yellow.empty? buf << " Yellow: " buf << _pp_bookings( yellow ) buf << "\n" end unless yellowred.empty? buf << " Yellow-Red: " buf << _pp_bookings( yellowred ) buf << "\n" end unless red.empty? buf << " Red: " buf << _pp_bookings( red ) buf << "\n" end buf end |
#pp_goals(m, indent: 4) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/fbtxt-pp/pp/ppgoals.rb', line 33 def pp_goals( m, indent: 4 ) return '' if m.goals1.nil? && m.goals2.nil? goals1 = m.goals1 goals2 = m.goals2 puts puts " #{goals1.size}-#{goals2.size} " pp goals1 pp goals2 buf_goals1 = _pp_goals( goals1 ) puts buf_goals1 buf_goals2 = _pp_goals( goals2 ) puts buf_goals2 buf = String.new goal_indent = ' ' * indent if goals1.size == 0 && goals2.size == 0 ## do nothing elsif goals1.size > 0 && goals2.size == 0 buf << "#{goal_indent} (#{buf_goals1})\n" elsif goals1.size == 0 && goals2.size > 0 buf << "#{goal_indent} (#{buf_goals2})\n" elsif (goals1.size == 1 && goals2.size == 1) buf << "#{goal_indent} (#{buf_goals1}; #{buf_goals2})\n" else ## both sides with goals buf << "#{goal_indent} (#{buf_goals1};\n" buf << "#{goal_indent} #{buf_goals2})\n" end buf end |
#pp_lineup(players, indent: 6, formation: nil, opts:) ⇒ Object
note - allow (optional formation e.g. 5-3-2 etc.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/fbtxt-pp/pp/pplineup.rb', line 32 def pp_lineup( players, indent: 6, formation: nil, opts: ) if formation ## split into integers parts = formation.split( /[ ]*-[ ]*/ ) ## add 1 upfront for (implied) goalie formation = ['1']+parts ## e.g. ## 1-4-3-3 ## 1-5-8-11 sum = 0 ## make cumulate sum (index) formation = formation.map { |part| sum += part.to_i(10) } end lines = [] line = String.new players.each_with_index do |player,i| text = String.new text << _pp_player( player, opts: opts ) next_player = players[i+1] if next_player if formation ### use formation for separators if formation.include?( i+1 ) text << " - " else text << ", " end elsif next_player.pos != player.pos text << " - " ## separate gk/def/mid/forw else text << ", " end end if (line.length+text.length) > 88 ## start a new line lines << line.rstrip line = String.new end line << text end lines << line.rstrip lines lines.join( "\n#{' '*indent}" ) end |
#pp_matches(season:, slug:, opts:, indir: '.') ⇒ Object
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/fbtxt-pp/pp/ppmatch.rb', line 5 def pp_matches( season:, slug:, opts:, indir: '.' ) season = Season( season ) doc = Document.read( "#{indir}/#{season.to_path}/#{slug}.json" ) buf = String.new ## add stats block (dates, teams, matches, venues, etc.) buf << pp_stats( doc, opts: opts ) buf << "\n" last_round = nil last_date = nil last_year = nil ## track running year doc.each_match do |m| # stageName, groupName = norm_stage( stageName, groupName, # team1: team1, # team2: team2, # date: localDateTime.strftime( '%Y-%m-%d') ) #### ## note - make round ## = stage + group (optional) + matchday (optional) round = m.stage round += ", #{m.group}" if m.group round += " - #{m.matchday}" if m.matchday if last_round.nil? || last_round != round buf << "\n" buf << "▪ #{round}\n" last_round = round last_date = nil end if last_date && (last_date.year == m.date_local.year && last_date.month == m.date_local.month && last_date.day == m.date_local.day) ## skip date header if same (local) date else ## e.g. Fri Jun 7 -or- Fri Jun 7 2026 if last_year.nil? || last_year != m.date_local.year buf << "#{m.date_local.strftime('%a %b %-e %Y')}\n" else buf << "#{m.date_local.strftime('%a %b %-e')}\n" end end ## always print time for now if opts.timezone? ## use 20:30 UTC+1 or 20:30 UTC-3 buf << " #{m.date_local.strftime( '%H:%M' )} UTC%+d" % m.diff_in_hours else buf << " #{m.date_local.strftime( '%H:%M' )}" end ## ## ## note - if score empty (e.g. '') use A v B score = if m.score m.score.to_s else ' v ' end if opts.clubs? && opts.country? buf << " #{m.team1.name} (#{m.team1.country})" buf << " #{score} " buf << "#{m.team2.name} (#{m.team2.country}) " else buf << " #{m.team1.name} #{score} #{m.team2.name} " end if opts.stadium? ## stadium PLUS city buf << "@ #{m.stadium.name}, #{m.stadium.city}" elsif opts.city? ## city only buf << "@ #{m.stadium.city}" else ## add nothing end buf << "\n" last_date = m.date_local last_year = m.date_local.year ## skip adding goals if teams not yet known!! ## fix-fix-fix -- add more checks (e.g. ResultType = ??, MatchStatus = ??) !!! next if m.team1.dummy? || m.team2.dummy? buf << pp_goals( m, indent: 17 ) end buf end |
#pp_matches_full(season:, slug:, opts:, indir: '.') ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/fbtxt-pp/pp/ppmatch_full.rb', line 4 def pp_matches_full( season:, slug:, opts:, indir: '.' ) season = Season( season ) doc = Document.read( "#{indir}/#{season.to_path}/#{slug}.json" ) buf = String.new ## add stats block (dates, teams, matches, venues, etc.) buf << pp_stats( doc, opts: opts ) buf << "\n" last_round = nil doc.each_match do |m| #### ## note - make round ## = stage + group (optional) + matchday (optional) round = m.stage round += ", #{m.group}" if m.group round += " - #{m.matchday}" if m.matchday score = if m.score m.score.to_s else '' end ## ## for debugging output match line (before goals, line-up, penalties, etc) puts " #{m.team1.name} v #{m.team2.name} #{score} - #{m.date_local}" if last_round.nil? || last_round != round buf << "▪ #{round}\n" last_round = round end ## use Fir Jan 7 20:30 UTC+1 or 20:30 UTC-3 buf << m.date_local.strftime( '%a %b %-e %H:%M' ) buf << " UTC%+d" % m.diff_in_hours buf << " @ #{m.stadium.name}, #{m.stadium.city}" buf << ", Att: #{m.attendance}" if m.attendance buf << "\n" if opts.clubs? && opts.country? buf << " #{m.team1.name} (#{m.team1.country}) v #{m.team2.name} (#{m.team2.country})" else buf << " #{m.team1.name} v #{m.team2.name}" end buf << " #{score}" buf << "\n" ## skip adding goals if teams not yet known!! ## fix-fix-fix -- add more checks (e.g. ResultType = ??, MatchStatus = ??) !!! next if m.team1.dummy? || m.team2.dummy? buf << pp_goals( m, indent: 4 ) ## fix-fix-fix ## hack - code is missing in teams!!! pp m.team1 pp m.team2 team1_code = m.team1.code || m.team1.country team2_code = m.team2.code || m.team2.country ### get match (live) details live = read_json( "#{indir}/#{season.to_path}/#{slug}/#{m.date_local.strftime('%Y-%m-%d')}_#{team1_code}-#{team2_code}.json" ) ########## ## add penalty kicks / penalties penalties = (live['penalties']||[]).map { |rec| Penalty.build(rec) } unless penalties.empty? buf << "\n" buf << "Penalties: #{pp_penalties( penalties, indent: 11 )}\n" end players1 = Players.new players1.add_starter( live['lineup1'] ) players1.add_bench( live['bench1']||[]) players1.add_subs( live['subs1']||[]) if opts.inline_cards? players1.add_yellow( live['yellow1']||[]) players1.add_yellowred( live['yellowred1']||[]) ## second yellow (resulting in red) players1.add_red( live['red1']||[]) ### check for bookings too (change to bookings/cards - why? why not?) ## players1.add_bookings( live['HomeTeam']['Bookings']) end players2 = Players.new players2.add_starter( live['lineup2'] ) players2.add_bench( live['bench2']||[]) players2.add_subs( live['subs2']||[]) if opts.inline_cards? players2.add_yellow( live['yellow2']||[]) players2.add_yellowred( live['yellowred2']||[]) ## second yellow (resulting in red) players2.add_red( live['red2']||[]) ### check for bookings too (change to bookings/cards - why? why not?) ## players2.add_bookings( live['AwayTeam']['Bookings']) end lineup1 = players1.lineup lineup2 = players2.lineup ## pp lineup1 ## pp lineup2 buf << "\n" buf << "#{m.team1.name}: "+ pp_lineup( lineup1, formation: live['formation1'], opts: opts ) + "\n" unless opts.inline_cards? buf << pp_bookings( live['yellow1']||[], live['yellowred1']||[], live['red1']||[], players: players1, opts: opts ) buf << "\n" end buf << "#{m.team2.name}: "+ pp_lineup( lineup2, formation: live['formation2'], opts: opts ) + "\n" unless opts.inline_cards? buf << pp_bookings( live['yellow2']||[], live['yellowred2']||[], live['red2']||[], players: players2, opts: opts ) end buf << "\n" =begin if players1.size == 0 && players2.size == 0 puts "!! WARN - no players available - skipping line-ups for teams!!!!!" else ## 1954-06-20 - only 10 player in south koera team listed!! ## 2021-02-07T21:00:00+00:00 expected 11 players, got 10 ## 2021-02-11T18:00:00+00:00 expected 11 players, got 10 if !((team1[:name] == 'Turkey' && team2[:name] == 'South Korea') || (team1[:name] == 'Palmeiras' && team2[:name] == 'Tigres UANL') || (team1[:name] == 'Al Ahly FC' && team2[:name] == 'Palmeiras') ) [lineup1,lineup2].each do |lineup| if lineup.size != 11 players1.dump puts "---" players2.dump puts "---" pp lineup puts " in match #{team1[:name]} v #{team2[:name]} #{score}" puts " #{localDateTime}" end assert( lineup.size == 11, "expected 11 players, got #{lineup.size}" ) end end =end ### ## add referees officials = live['referees'].map { |rec| Official.build(rec) } if officials.size == 0 ## puts "!! WARN no refs / officials found" else buf << "Refs: " + pp_officials( officials, opts: opts ) buf << "\n" end buf << "\n\n" end buf end |
#pp_matches_min(season:, slug:, opts:, indir: '.') ⇒ Object
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/fbtxt-pp/pp/ppmatch_min.rb', line 5 def pp_matches_min( season:, slug:, opts:, indir: '.' ) season = Season( season ) doc = Document.read( "#{indir}/#{season.to_path}/#{slug}.json" ) buf = String.new ## add stats block (dates, teams, matches, venues, etc.) buf << pp_stats( doc, opts: opts ) buf << "\n" last_round = nil doc.each_match do |m| round = m.stage round += ", #{m.group}" if m.group round += " - #{m.matchday}" if m.matchday if last_round.nil? || last_round != round buf << "\n" buf << "▪ #{round}\n" last_round = round end score = if m.score m.score.to_s else '' end if opts.clubs? && opts.country? line = "#{m.team1.name} (#{m.team1.country})" line << " v " line << "#{m.team2.name} (#{m.team2.country})" buf << " %-40s " % line else line = "#{m.team1.name} v #{m.team2.name}" buf << " %-30s " % line end buf << "#{score}" buf << "\n" end buf end |
#pp_officials(recs, opts:) ⇒ Object
officials (that is, referees)
90 91 92 93 94 95 96 97 98 |
# File 'lib/fbtxt-pp/pp/pplineup.rb', line 90 def pp_officials( recs, opts: ) recs.map do |official| if opts.country? "#{official.name} (#{official.country})" else "#{official.name}" end end.join( ', ' ) end |
#pp_penalties(pens, indent:) ⇒ Object
23 24 25 26 27 28 29 30 31 32 |
# File 'lib/fbtxt-pp/pp/pppenalties.rb', line 23 def pp_penalties( pens, indent: ) lines = [] line = String.new pens.each_slice(2) do |pen1, pen2| lines << _pp_pens( pen1, pen2 ) end lines.join( ",\n#{' '*indent}" ) end |
#pp_squads(slug:, season:, opt_jerseys: true, opt_country: false) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/fbtxt-pp/pp/ppsquads.rb', line 15 def pp_squads( slug:, season:, opt_jerseys: true, opt_country: false ) data = read_json( "./#{slug}/misc/#{season}_squads.json" ) data = data['Results'] puts " #{data.size} result(s)" buf = String.new buf << "# #{data.size} Teams\n\n" puts "#{slug} #{season} # #{data.size} Teams" data.each_with_index do |h,i| team = desc( h['TeamName']) country = h['IdCountry'] ## e.g. Germany FR => West Germany, etc. team = norm_team( team ) players = h['Players'] if opt_country buf << "== #{team} (#{country})" else buf << "== #{team}" end buf << " # #{players.size} Players\n\n" puts "== [#{i+1}/#{data.size}] #{team} - #{players.size} player(s)" players = players.sort do |l,r| res = l['Position'] <=> r['Position'] if res == 0 && opt_jerseys res = (l['JerseyNum']||999) <=> (r['JerseyNum']||999) end res end ## use max country - why? why not? ## 1934 Austria first is not AUT - check?? firstIdCountry = players[2]['IdCountry'] last_pos = nil players.each do |player| name = desc( player['PlayerName']) name = norm_player( name ) ## ## check player name if include parentheses or such ## GILMAR (Gilmar Dos Santos Neves) - 1958 Brazil ## PELÉ (Edson Arantes do Nascimento) ## ROMÁRIO (Romário de Souza Faria) ## only allow alpha and space if !is_alpha?( name ) puts "!! invalid player name:" pp player pp name exit 1 end pos = player['Position'] jersey = player['JerseyNum'] assert( [0,1,2,3,4].include?(pos), "pos 0/1/2/3/4 expected; got #{player.pretty_inspect}" ) ## note - birth_date is OPTIONAL (not available for all) bday = player['BirthDate'] ? parse_date( player['BirthDate']) : nil idCountry = player['IdCountry'] # if lastIdCountry # assert( idCountry == lastIdCountry, # "country code do NOT match #{idCountry} != #{lastIdCountry}" ) # end ## add a blank line between GK/DF/MF/FW/? (unknown) buf << "\n" if last_pos && last_pos != pos name_col = if opt_country ## check if player country is different from team country if country != idCountry "#{name} (#{idCountry})," else "#{name}," end else if firstIdCountry != idCountry ## ignore country code - why? why not? puts "!! country code do NOT match #{idCountry}; #{firstIdCountry} expected" pp player ## "#{name} (#{idCountry})," "#{name}," else "#{name}," end end cols = [name_col, "#{POS[pos]},", bday ? "b. #{bday.strftime('%Y/%m/%d')}" : "" ] if opt_jerseys cols = ["#{jersey},"] + cols buf << " %6s %-30s %-4s %-10s" % cols else buf << " %-30s %-4s %-10s" % cols end buf << "\n" last_pos = pos end officials = h['Officials'] ## coaches if officials.size > 0 buf << "\n" officials.each do |official| name = desc( official['Name']) name = norm_official( name ) ## replace non-breaking spaces if !is_alpha?( name ) puts "!! invalid official name:" pp official pp name exit 1 end role = official['Role'] idCountry = official['IdCountry'] assert( [0,1].include?(role), "role 0/1 expected; got #{official.pretty_inspect}" ) ## skip co-coaches - why? why not? next if role == 1 # " skip co-coach: #{official.pretty_inspect}" ## note - birth_date is OPTIONAL (not available for all) bday = official['BirthDate'] ? parse_date( official['BirthDate']) : nil ## 0 -> mg = manager ## 1 -> am = assistant manager ## or use co (coach), ac (assistiant coach) ?? ## ## for now add country code (cc) to all managers/coaches ## firstIdCountry != idCountry ? "#{name} (#{idCountry})," : "#{name}," cols = [ "#{name} (#{idCountry}),", role == 0 ? "MG," : "AM,", bday ? "b. #{bday.strftime('%Y/%m/%d')}" : "" ] if opt_jerseys cols = ["-,"] + cols buf << " %6s %-30s %-4s %-10s" % cols else buf << " %-30s %-4s %-10s" % cols end buf << "\n" end buf << "\n\n" end end buf end |
#pp_stats(doc, opts:) ⇒ Object
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/fbtxt-pp/pp/ppstats.rb', line 2 def pp_stats( doc, opts: ) buf = String.new #### # dates # - start/end dates and duration in days start_date, end_date = doc.calc_start_end_dates diff_in_days = end_date.jd - start_date.jd diff_in_years = end_date.year - start_date.year buf << "# Dates " if diff_in_years > 0 buf << "#{start_date.strftime('%a %b %-e %Y')} - #{end_date.strftime('%a %b %-e %Y')}" else buf << "#{start_date.strftime('%a %b %-e')} - #{end_date.strftime('%a %b %-e %Y')}" end buf << " (#{diff_in_days}d)\n" ######## # teams # - number of matches buf << "# Teams #{doc.teams.size}\n" if opts.show_teams? ## ## sort teams by country - why? why not? doc.teams.each do |team| buf << "# #{team.name} (#{team.country})\n" end end ###### # matches # - number of teams buf << "# Matches #{doc.matches.size}\n" ##### # venues # - all stadiums if opts.show_stadiums? buf << "# Venues #{doc.stadiums.size}" cities = doc.stadiums.cities buf << (cities.size == 1 ? " (in 1 city)" : " (in #{cities.size} cities)") buf << "\n" doc.stadiums.each do |stadium| buf << "# #{stadium.name}, #{stadium.city} (#{stadium.country})\n" end end buf end |
#read_config_pp(*paths) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/fbtxt-pp/config.rb', line 37 def read_config_pp( *paths ) config = {} paths.each do |path| recs = read_csv( path ) recs.each do |rec| key = rec['code'] h = { slug: key, name: rec['name'], seasons: rec['seasons'], opts: {}.merge( FORMAT_OPTS_DEFAULTS, _parse_format_opts( rec['opts'] )), opts_full: {}.merge( FORMAT_OPTS_FULL_DEFAULTS, _parse_format_opts( rec['opts_full'] )), } config[ key ] = h end end config end |
#slugify(str) ⇒ Object
23 24 25 |
# File 'lib/fbtxt-pp.rb', line 23 def slugify( str ) str.downcase.gsub( /[^a-z0-9]/, '' ) end |