#!/usr/bin/ruby =begin * reads libECBufr's bufr_decoder -dump * writes synoplike text =end class DCD Inf = 1.0 / 0.0 def initialize hdr @h = {} @v = {} @s = nil @c = {} @hdr = hdr end attr_accessor :hdr def push k, v @h[k] = [] unless @h.include?(k) @h[k].push Hash[:val, v, :coord, @c.dup] @c[k] = v if /\A00/ === k self end def val d, pos = 0, quiet = false v = @h[d] unless v STDERR.puts "#{d}: missing" unless quiet return nil end v[pos][:val] end def sval d, pos = 0, quiet = false v = val(d, pos, quiet) case v when /"([^" ][^"]*)"/ then $1.strip when /" *"/ then '/EMPTY/' else nil end end def nval d, pos = 0, quiet = false v = val(d, pos, quiet) case v when 'MSNG' then nil when /\A-?\d+\z/ then v.to_i when /\A-?[.\d]+\z/ then v.to_f else nil end end def ncoord d, axis, pos = 0 v = @h[d] unless v STDERR.puts "#{d}: missing" return nil end v = v[pos][:coord] unless v STDERR.puts "#{pos}: missing for #{d}" return nil end v = v[axis] case v when 'MSNG' then nil when /\A-?\d+\z/ then v.to_i when /\A-?[.\d]+\z/ then v.to_f else nil end end def compile return if @s # extract values @v['2Y'] = nval('004003') @v['2G'] = nval('004004') @v['2g'] = nval('004005') @v['iw'] = 0 @v['2I'] = nval('001001', 0, :quiet) if @v['2I'] @v['3i'] = nval('001002') else @v['DD'] = sval('001011') @v['3La'] = nval('005002') @v['4Lo'] = nval('006002') end @v['ix'] = nval('002001') @v['h'] = nval('020013') @v['VV'] = nval('002001') @v['N'] = nval('020010') @v['2d'] = nval('011001') @v['2f'] = nval('011002') @v['3T'] = nval('012101') @v['3Td'] = nval('012103') @v['3U'] = nval('013003') @v['4P'] = nval('010004') @v['4P0'] = nval('010051') if @v['2I'] @v['a3'] = nval('007004') @v['3h'] = nval('010009') end @v['3R'] = nval('013011') @v['tR'] = ncoord('013011', '004024') @v['a'] = nval('010063') @v['3p'] = nval('010061') @v['2w'] = nval('020003') @v['w1'] = nval('020004') @v['w2'] = nval('020005') @v['Nh'] = nval('020011') @v['CL'] = nval('020012', 0) @v['CM'] = nval('020012', 1) @v['CH'] = nval('020012', 2) # adjust representation # iR @s = @v.dup @s['iR'] = case @v['3R'] when 0 then 3 when Float then 1 else 4 end # ww, ix case @v['2w'] when 0..99 @s['ix'] = 1 when 100..199 @s['ix'] = 7 @s['2w'] = @v['2w'] - 100 when 508 @s['ix'] = 2 @s['2w'] = nil else @s['ix'] = 3 @s['2w'] = nil end @s['ix'] += 3 if @v['ix'] == 0 and @s['ix'] != 7 if @v['w1'] and @v['w1'] >= 10 @s['w1'] = (@v['w1'] % 10) if [1, 4].include?(@s['ix']) if @v['w1'] == 10 then @s['w1'] = nil else STDERR.puts "Override ix(#{@s['ix']}) = 7 as w1 = #{@v['w1']}" @s['ix'] = 7 end else @s['ix'] = 7 end end if @v['w2'] and @v['w2'] >= 10 @s['w2'] = (@v['w2'] % 10) if [1, 4].include?(@s['ix']) if @v['w2'] == 10 then @s['w2'] = nil else STDERR.puts "Override ix(#{@s['ix']}) = 7 as w2 = #{@v['w2']}" @s['ix'] = 7 end else @s['ix'] = 7 end end # h @s['h'] = case @v['h'] when 0...50 then 0 when 50...100 then 1 when 100...200 then 2 when 200...300 then 3 when 300...600 then 4 when 600...1000 then 5 when 1000...1500 then 6 when 1500...2000 then 7 when 2000...2500 then 8 when 2500...Inf then 9 else nil end # VV @s['2V'] = case @v['2V'] when 0..5000 then ((@v['2V'] + 50) / 100).to_i when 5000..30_000 then ((@v['2V'] + 50500) / 1000).to_i when 30_000..70_000 then ((@v['2V'] - 30_000) / 5000).to_i + 80 when 70_000..Inf then 89 else nil end # N @s['N'] = ((@v['N'] + 6) / 12.5).to_i if @v['N'] # 2d @s['2d'] /= 10 if @s['2d'] # 2f, 3f case @v['2f'] when 0...100 @s['2f'] = @v['2f'].to_i when Numeric @s['3f'] = @v['2f'].to_i @s['2f'] = 99 end # 3T case @v['3T'] when 0...273.15 @s['s'] = 1 @s['3T'] = ((273.2 - @v['3T']) * 10).to_i when Numeric @s['s'] = 0 @s['3T'] = ((@v['3T'] - 273.1) * 10).to_i else @s['s'] = @s['3T'] = nil end # 3Td case @v['3Td'] when 0...273.15 @s['sd'] = 1 @s['3Td'] = ((273.2 - @v['3Td']) * 10).to_i when Numeric @s['sd'] = 0 @s['3Td'] = ((@v['3Td'] - 273.1) * 10).to_i else @s['sd'] = @s['3Td'] = nil end # 4P @s['4P'] = ((@v['4P'] + 5) / 10) % 10000 if @v['4P'] @s['4P0'] = ((@v['4P0'] + 5) / 10) % 10000 if @v['4P0'] if @v['2I'] @s['a3'] = case @v['a3'] when 1000_0 then 1 when 925_0 then 2 when 850_0 then 8 when 700_0 then 7 when 500_0 then 5 else nil end @s['3h'] = (@v['3h'] % 1000) if @v['3h'] else la = @v['3La'].to_f lo = @v['4Lo'].to_f @s['Qc'] = if lo >= 0 and la >= 0 then 1 elsif lo >= 0 then 3 elsif la >= 0 then 7 else 5 end @s['3La'] = (la.abs * 10).to_i @s['4Lo'] = (lo.abs * 10).to_i end @s['3p'] = @v['3p'].abs if @v['3p'] # 3R @s['tR'] = case @v['tR'] when -6 then 1 when -12 then 2 when -18 then 3 when -24 then 4 when -1 then 5 when -2 then 6 when -3 then 7 when -9 then 8 when -15 then 9 else nil end @s['3R'] = (@s['3R'] * 10 + 0.5).to_i if @s['3R'] @s['3R'] = case @s['3R'] when -1 then 990 when 0..9 then 990 + @s['3R'].to_i when 10..9884 then (@v['3R'] + 5) / 10 when 9885..Inf then 989 else nil end # group 8 @s['CL'] = case @v['CL'] when 30..39 then @v['CL'] - 30 when 59, 62, nil then nil else STDERR.puts("suspicious CL #{@v['CL']}"); nil end @s['CM'] = case @v['CM'] when 20..29 then @v['CM'] - 20 when 59, 61, nil then nil else STDERR.puts("suspicious CM #{@v['CM']}"); nil end @s['CH'] = case @v['CH'] when 10..19 then @v['CH'] - 10 when 59, 60, nil then nil else STDERR.puts("suspicious CH #{@v['CH']}"); nil end end def e *keys r = [] for key in keys v = @s[key] n = ((/\A[1-9]/ === key) ? $&.to_i : 1) s = (v ? sprintf(sprintf('%%0%uu', n), v) : ('/' * n)) s = "[#{s}]" if s.length > n r.push s end r.join end @@nnn = 0 def fm12 m = [] if @s['2I'] m.push e('2I', '3i') else m.push(@s['DD'] || 'SHIP') m.push e('2Y', '2G', 'iw') m.push ['99', e('3La')].join m.push e('Qc', '4Lo') end m.push e('iR', 'ix', 'h', '2V') m.push e('N', '2d', '2f') m.push ['00', e('3f')].join if @s['3f'] m.push ['1', e('s', '3T')].join m.push ['2', e('sd', '3Td')].join m.push ['3', e('4P')].join if @s['4P'] if @s['a3'] m.push ['4', e('a3', '3h')].join else m.push ['4', e('4P0')].join end m.push ['5', e('a', '3p')].join if @s['a'] m.push ['6', e('3R', 'tR')].join if @s['tR'] m.push ['7', e('2w', 'w1', 'w2')].join if [1, 4, 7].include?(@s['ix']) m.push ['8', e('Nh', 'CL', 'CM', 'CH')].join if @s['Nh'] and @s['CL'] m.push ['9', e('GG', 'gg')].join if not @s['gg'].to_i.zero? m.last.sub!(/\z/, '=') f = [] while not m.empty? f.push m[0,11].join(' ') m[0,11] = [] end f.join("\r\r\n") end def report0 nnn compile f = [] f.push "# this is not an official GTS report" f.push "# just converted from (#{@hdr.downcase})" f.push sprintf("ZCZC %03u ", nnn % 1000) f.push ["SXXX99 XXXX ", e('2Y', '2G', '2g')].join if @s['2I'] then f.push ['AAXX ', e('2Y', '2G', 'iw')].join else f.push 'BBXX' end f.join("\r\r\n") end def report1 compile if $VERBOSE for k, v in @v puts [k, v].inspect end end fm12 end def report2 "\nNNNN\r\r\n" end end # class DCD class Buffer def initialize @dcd = [] @nnn = 0 end def push dcd if @dcd.first and @dcd.first.hdr != dcd.hdr flush end @dcd.push dcd end def flush puts @dcd.first.report0(@nnn) @nnn += 1 for dcd in @dcd puts dcd.report1 end puts @dcd.last.report2 @dcd = [] end end hdr = nil dcd = DCD.new(hdr) buf = Buffer.new for line in ARGF line.chomp! case line when /\A\z/ then buf.push dcd dcd = DCD.new(hdr) when /\A(0\d{5})( \{R=\d+\})? / then dcd.push($1, $') when /\AHEADER_STRING="(.*)"/ then hdr = $1.gsub(/\\040/, ' ').gsub(/\\01[25]/, '') dcd.hdr = hdr end end buf.flush