module BomRadarImage
BomRadarImage — decode BOM indexed radar PNGs and classify rain intensity. Public: decode, downsample, char_for_index, intensity_label, colorize_line Depends: chunky_png, bom_radar_config, irc_format Tests: test/lib/bom_radar_image_test.rb
Constants
- BACKGROUND_META
- CELL_STYLES
- INDEX_META
- IRC_RESET
- STYLE_BORDER
- STYLE_CENTER
- STYLE_CLEAR
- STYLE_COAST
- STYLE_HEAVY
- STYLE_INTENSE
- STYLE_LAND
- STYLE_LIGHT
- STYLE_MODERATE
- STYLE_SEA
Public Instance Methods
Source
# File lib/bom_radar_image.rb, line 108 def char_for_background(index) BACKGROUND_META.fetch(index) { BACKGROUND_META[2] }[:char] end
Source
# File lib/bom_radar_image.rb, line 112 def char_for_index(index, center: false) return BomRadarConfig::CENTER_CHAR if center meta_for(index)[:char] end
Source
# File lib/bom_radar_image.rb, line 118 def char_for_merged(index, center: false) return BomRadarConfig::CENTER_CHAR if center meta_for_merged(index)[:char] end
Source
# File lib/bom_radar_image.rb, line 160 def colorize_line(line, grid: nil, center: nil, row: nil, merged: false) return "" if line.empty? runs = [] line.each_char.with_index do |char, col_index| style_key = if char == BomRadarConfig::CENTER_CHAR :center elsif grid && row merged ? style_for_merged(grid[row][col_index]) : style_for(grid[row][col_index]) else style_for_char(char) end style = CELL_STYLES[style_key] if runs.empty? || runs.last[:style] != style runs << { style: style, chars: char } else runs.last[:chars] << char end end runs.map { |run| "#{run[:style]}#{run[:chars]}#{IRC_RESET}" }.join end
Source
# File lib/bom_radar_image.rb, line 198 def colorize_lines(lines, grid: nil, center: nil, merged: false) lines.each_with_index.map do |line, row| colorize_line(line, grid: grid, center: center, row: row, merged: merged) end end
Source
# File lib/bom_radar_image.rb, line 63 def decode(bytes) decoded = BomRadarPng.decode_indices(bytes) { width: decoded[:width], height: decoded[:height], grid: decoded[:grid] } end
Source
# File lib/bom_radar_image.rb, line 128 def display_intensity(index) return nil if index.to_i < BomRadarConfig::RAIN_MIN_INDEX label = intensity_label(index) return label if label nil end
Source
# File lib/bom_radar_image.rb, line 86 def dominant_index(source, rows, cols) counts = Hash.new(0) rows.each do |row| cols.each do |col| idx = source[row][col] counts[idx] += 1 end end counts.max_by { |index, count| [count, -index] }&.first || 0 end
Source
# File lib/bom_radar_image.rb, line 68 def downsample(grid_data, width: BomRadarConfig::MAP_WIDTH, height: BomRadarConfig::MAP_HEIGHT) source = grid_data[:grid] src_h = grid_data[:height] src_w = grid_data[:width] block_h = src_h.to_f / height block_w = src_w.to_f / width Array.new(height) do |row| Array.new(width) do |col| y0 = (row * block_h).floor y1 = [((row + 1) * block_h).ceil - 1, src_h - 1].min x0 = (col * block_w).floor x1 = [((col + 1) * block_w).ceil - 1, src_w - 1].min dominant_index(source, y0..y1, x0..x1) end end end
Source
# File lib/bom_radar_image.rb, line 149 def grid_to_chars(grid, center: nil) height = grid.length width = grid.first.length grid.map.with_index do |row, row_index| row.map.with_index do |index, col_index| is_center = center && center[0] == row_index && center[1] == col_index char_for_index(index, center: is_center) end.join end end
Source
# File lib/bom_radar_image.rb, line 124 def intensity_label(index) meta_for(index)[:label] end
Source
# File lib/bom_radar_image.rb, line 97 def meta_for(index) INDEX_META[index] || INDEX_META[0] end
Source
# File lib/bom_radar_image.rb, line 101 def meta_for_merged(index) value = index.to_i return BACKGROUND_META[value] if value < BomRadarConfig::RAIN_MIN_INDEX meta_for(value) end
Source
# File lib/bom_radar_image.rb, line 137 def style_for(index, center: false) return :center if center meta_for(index)[:style] end
Source
# File lib/bom_radar_image.rb, line 183 def style_for_char(char) case char when "#" then :border when "." then :land when "~" then :sea when "|" then :coast when ":" then :light when "o" then :moderate when "O" then :heavy when "@" then :intense when "+" then :center else :clear end end
Source
# File lib/bom_radar_image.rb, line 143 def style_for_merged(index, center: false) return :center if center meta_for_merged(index)[:style] end