#!/usr/bin/ruby -Ku require 'detac' class SelSurf def initialize # decode table - hash of array of hash @dcd = {:fixed => [], :mobile => []} @year = @mon = @yy = @gg = nil @bbox = [16..52, 116..180] @index = {} @mindex = {} end def convert ent, dcd raise "#{self.class.name}#convert unimplemented" end def report raise "#{self.class.name}#report unimplemented" end def load_stns fnam File.open(fnam, 'r') { |fp| for line in fp id, name, slalo, x = line.chomp.split(/\t/) ent = {:ID => id, :NAME => name, :miss => true} case slalo when /^([-+]\d\d)([-+]\d\d\d)\// lat = $1.to_i lon = $2.to_i ent[:flalo] = ent[:ilalo] = [lat, lon] when /^([-+]\d\d\.\d+)([-+]\d\d\d\.\d+)\// lat = $1.to_f lon = $2.to_f ent[:flalo] = [lat, lon] ent[:ilalo] = ent[:flalo].map{|f| (f + 0.5).floor} end @dcd[:fixed].push ent @index[id] = ent end } end def insert dcd lat = lon = nil if Numeric === dcd['La.3'] lat = dcd['La.3'] * 0.1 elsif Numeric === dcd['La.5'] lat = dcd['La.5'] * 0.001 else return end return unless @bbox.first === lat if Numeric === dcd['Lo.4'] lon = dcd['Lo.4'] * 0.1 elsif Numeric === dcd['Lo.6'] lon = dcd['Lo.6'] * 0.001 else return end return unless @bbox.last === lon key = format('%+.2d%+.3d/', lat + 0.5, lon + 0.5) if @mindex[key] then STDERR.puts "%dup #{key}" if $VERBOSE return else STDERR.puts "%pass #{key}" if $VERBOSE end ent = { :key => key, :flalo => [lat, lon], :miss => true, } ent[:ilalo] = ent[:flalo].map{|f| (f + 0.5).floor} convert(ent, dcd) @mindex[key] = ent end def compile prevmiss = nil @dcd[:fixed].each {|ent| if /^:/ === ent[:NAME] if prevmiss then ent[:NAME].sub!(/^:/, '') else ent[:miss] = :killed end end prevmiss = ent[:miss] next if ent[:miss] next unless ent[:ilalo] lat, lon = ent[:ilalo] for j in -2..2 for i in -2..2 next if j.abs + i.abs > 3 key = format('%+.2d%+.3d/', lat + j, lon + i) case @mindex[key] when Hash STDERR.puts "%kill #{key} by #{ent.inspect}" if $VERBOSE @mindex[key] = :killed end end end } mobile = @mindex.values.reject{|ent| :killed === ent} @dcd[:mobile] = mobile.sort{|a, b| a[:ilalo].reverse <=> b[:ilalo].reverse } end def run argv while /^-./ === argv.first case arg = argv.shift when /^-f/ then load_stns($' || argv.shift) when /^-m:(-?\d+)\.\.(-?\d+),(-?\d+)\.\.(-?\d+)/ then @bbox = [$1.to_i .. $2.to_i, $3.to_i .. $4.to_i] when /^-y\d{4}/ then @yy = arg[2, 2].to_i @gg = arg[4, 2].to_i when /^-ym\d{4}-\d\d/ then @year = arg[3, 4].to_i @mon = arg[8, 2].to_i when /^--$/ then break end end now = Time.at(Time.now.to_i % 3600 * 3600).utc @year = now.year unless @year @mon = now.mon unless @mon @yy = now.mday unless @yy @gg = now.hour unless @gg for file in argv DeTac.new(file).decode {|mimj, dcd| if @yy === dcd['YY'] and @gg === dcd['GG'] if 'AAXX' === mimj ent = @index[dcd['@ID']] convert(ent, dcd) if ent else insert(dcd) end end } end compile report end end SelSurf.new.run(ARGV) if $0 == __FILE__