Class: SportDb::TxtMatchWriter
- Inherits:
-
Object
- Object
- SportDb::TxtMatchWriter
- Defined in:
- lib/sportdb/writers.rb,
lib/sportdb/writers/txt_writer.rb
Constant Summary collapse
- ROUND_TRANSLATIONS =
translate from lang x (german, etc) to english
{ # de/german '1. Runde' => 'Round 1', '2. Runde' => 'Round 2', 'Achtelfinale' => 'Round of 16', 'Viertelfinale' => 'Quarterfinals', 'Halbfinale' => 'Semifinals', 'Finale' => 'Final', }
Class Method Summary collapse
- ._build_batch(matches, rounds: true) ⇒ Object
-
.build(matches, rounds: true) ⇒ Object
note: build returns buf - an (in-memory) string buf(fer).
- .build_goals(goals) ⇒ Object
- .build_goals_for_team(team_goals) ⇒ Object
- .write(path, matches, name:, rounds: true) ⇒ Object
Class Method Details
._build_batch(matches, rounds: true) ⇒ Object
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 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/sportdb/writers/txt_writer.rb', line 126 def self._build_batch( matches, rounds: true ) ## note: make sure rounds is a bool, that is, true or false (do NOT pass in strings etc.) raise ArgumentError, "rounds flag - bool expected; got: #{rounds.inspect}" unless rounds.is_a?( TrueClass ) || rounds.is_a?( FalseClass ) buf = String.new last_round = nil last_date = nil last_time = nil matches.each_with_index do |match,i| ## note: make rounds optional (set rounds flag to false to turn off) if rounds if match.round != last_round buf << (i == 0 ? "\n" : "\n\n") ## start with single empty line if match.round.is_a?( Integer ) || match.round =~ /^[0-9]+$/ ## all numbers/digits ## default "class format ## e.g. Runde 1, Spieltag 1, Matchday 1, Week 1 buf << "Matchday #{match.round}" else ## use as is from match ## note: for now assume english names if match.round.nil? ## warn puts "!! ERROR - match with round nil?" pp match exit 1 end buf << (ROUND_TRANSLATIONS[match.round] || match.round) end ## note - reset last_date & last_time on every new round header last_date = nil last_time = nil buf << "\n" end end date = if match.date.is_a?( String ) Date.strptime( match.date, '%Y-%m-%d' ) else ## assume it's already a date (object) or nil!!!! match.date end time = if match.time.is_a?( String ) Time.strptime( match.time, '%H:%M') else ## assume it's already a time (object) or nil match.time end ## note - date might be NIL!!!!! date_yyyymmdd = date ? date.strftime( '%Y-%m-%d' ) : nil ## note: time is OPTIONAL for now ## note: use 17.00 and NOT 17:00 for now time_hhmm = time ? time.strftime( '%H.%M' ) : nil if date_yyyymmdd if date_yyyymmdd != last_date ## note: add an extra leading blank line (if no round headings printed) buf << "\n" unless rounds buf << "[#{date.strftime( '%a %b/%-d' )}]\n" last_time = nil end end ## allow strings and structs for team names team1 = match.team1.is_a?( String ) ? match.team1 : match.team1.name team2 = match.team2.is_a?( String ) ? match.team2 : match.team2.name line = String.new line << ' ' if time if last_time != time_hhmm line << "%5s" % time_hhmm else line << ' ' end line << ' ' else line << ' ' end line << "%-23s" % team1 ## note: use %-s for left-align ## note: separate by at least two spaces for now line << " #{match.score.to_s( lang: 'en' )} " line << "%-23s" % team2 if match.status line << ' ' case match.status when Status::CANCELLED line << '[cancelled]' when Status::AWARDED line << '[awarded]' when Status::ABANDONED line << '[abandoned]' when Status::REPLAY line << '[replay]' when Status::POSTPONED line << '[postponed]' ## was -- note: add NOTHING for postponed for now else puts "!! WARN - unknown match status >#{match.status}<:" pp match line << "[#{match.status.downcase}]" ## print "literal" downcased for now end end ## add match line buf << line.rstrip ## remove possible right trailing spaces before adding buf << "\n" if match.goals buf << ' ' # 4 space indent buf << ' ' if time # 7 (5+2) space indent (for hour e.g. 17.30) buf << "[#{build_goals(match.goals)}]" buf << "\n" end last_round = match.round last_date = date_yyyymmdd last_time = time_hhmm end buf end |
.build(matches, rounds: true) ⇒ Object
note: build returns buf - an (in-memory) string buf(fer)
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 |
# File 'lib/sportdb/writers/txt_writer.rb', line 18 def self.build( matches, rounds: true ) ## note: make sure rounds is a bool, that is, true or false (do NOT pass in strings etc.) raise ArgumentError, "rounds flag - bool expected; got: #{rounds.inspect}" unless rounds.is_a?( TrueClass ) || rounds.is_a?( FalseClass ) ### check for stages & stats stats = { 'stage' => Hash.new(0), 'date' => { 'start_date' => nil, 'end_date' => nil, }, 'teams' => Hash.new(0), } ## add matches played stats too?? matches.each do |match| stage = match.stage stage = 'Regular Season' if stage.nil? || stage.empty? stats['stage'][ stage ] += 1 if match.date ## todo/fix - norm date (parse as Date) ## check format etc. date = if match.date.is_a?( String ) Date.strptime( match.date, '%Y-%m-%d' ) else ## assume it's already a date (object) match.date end stats['date']['start_date'] ||= date stats['date']['end_date'] ||= date stats['date']['start_date'] = date if date < stats['date']['start_date'] stats['date']['end_date'] = date if date > stats['date']['end_date'] end [match.team1, match.team2].each do |team| stats['teams'][ team ] += 1 if team && !['N.N.'].include?( team ) end end use_stages = if stats['stage'].size >= 2 || (stats['stage'].size == 1 && stats['stage'].keys[0] != 'Regular Season') true else false end ### add comment header buf = String.new # e.g. 13 April – 25 September 2024 # or 16 August 2024 – 25 May 2025 ## note - date is optional!! if stats['date']['start_date'] buf << "# Date " start_date = stats['date']['start_date'] end_date = stats['date']['end_date'] if start_date.year != end_date.year buf << "#{start_date.strftime('%a %b/%-d %Y')} - #{end_date.strftime('%a %b/%-d %Y')}" else buf << "#{start_date.strftime('%a %b/%-d')} - #{end_date.strftime('%a %b/%-d %Y')}" end buf << " (#{end_date.jd-start_date.jd}d)" ## add days buf << "\n" end buf << "# Teams #{stats['teams'].size}\n" buf << "# Matches #{matches.size}\n" if use_stages buf << "# Stages " stages = stats['stage'].map { |name,count| "#{name} (#{count})" }.join( ' ' ) buf << stages buf << "\n" end buf << "\n\n" if use_stages ## split matches by stage matches_by_stage = {} matches.each do |match| stage = match.stage || '' matches_by_stage[stage] ||= [] matches_by_stage[stage] << match end ## todo/fix ## note - empty stage must go first!!!! matches_by_stage.each_with_index do |(name, matches),i| buf << "\n" if i != 0 # add extra new line (if not first stage) if name.empty? buf << "# Regular Season\n" ## empty stage else buf << "== #{name}\n" end buf += _build_batch( matches, rounds: rounds ) buf << "\n" if i+1 != matches_by_stage.size end buf else buf += _build_batch( matches, rounds: rounds ) buf end end |
.build_goals(goals) ⇒ Object
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
# File 'lib/sportdb/writers/txt_writer.rb', line 267 def self.build_goals( goals ) ## todo/fix: for now assumes always minutes (without offset) - add offset support ## note: "fold" multiple goals by players team1_goals = {} team2_goals = {} goals.each do |goal| team_goals = goal.team == 1 ? team1_goals : team2_goals player_goals = team_goals[ goal.player ] ||= [] player_goals << goal end buf = String.new if team1_goals.size > 0 buf << build_goals_for_team( team1_goals ) end ## note: only add a separator (;) if BOTH teams have goal scores if team1_goals.size > 0 && team2_goals.size > 0 buf << '; ' end if team2_goals.size > 0 buf << build_goals_for_team( team2_goals ) end buf end |
.build_goals_for_team(team_goals) ⇒ Object
296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
# File 'lib/sportdb/writers/txt_writer.rb', line 296 def self.build_goals_for_team( team_goals ) buf = String.new team_goals.each_with_index do |(player_name, goals),i| buf << ' ' if i > 0 buf << "#{player_name} " buf << goals.map do |goal| str = "#{goal.minute}'" str << " (o.g.)" if goal.owngoal? str << " (pen.)" if goal.penalty? str end.join( ', ' ) end buf end |
.write(path, matches, name:, rounds: true) ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/sportdb/writers.rb', line 36 def self.write( path, matches, name:, rounds: true) buf = build( matches, rounds: rounds ) ## for convenience - make sure parent folders/directories exist FileUtils.mkdir_p( File.dirname( path) ) unless Dir.exist?( File.dirname( path )) puts "==> writing to >#{path}<..." File.open( path, 'w:utf-8' ) do |f| f.write( "= #{name}\n" ) f.write( buf ) end end |