#!/usr/bin/ruby -Ku require 'rubygems' require 'sqlite3' class App def initialize dbf = 'bufrtable.sq3' @db = SQLite3::Database.new(dbf) end =begin CREATE TABLE bufrd( dom INTEGER NOT NULL, ver INTEGER NOT NULL, cls INTEGER NOT NULL, cod INTEGER NOT NULL, pos INTEGER NOT NULL, f INTEGER NOT NULL, x INTEGER NOT NULL, y INTEGER NOT NULL, dsc TEXT NOT NULL, sta TEXT NOT NULL, PRIMARY KEY (dom, ver, cls, cod, pos) ); =end =begin CREATE TABLE bufrb( dom INTEGER NOT NULL, ver INTEGER NOT NULL, cls INTEGER NOT NULL, cod INTEGER NOT NULL, uni TEXT NOT NULL, wid INTEGER NOT NULL, scl INTEGER NOT NULL, rfv INTEGER NOT NULL, dsc TEXT NOT NULL, sta TEXT NOT NULL, PRIMARY KEY (dom, ver, cls, cod) ); =end UTAB = { 'Text' => 'CCITT IA5', 'Character' => 'CCITT IA5', 'CodeTable' => 'Code table', 'Code Table' => 'Code table', 'FlagTable' => 'Flag table', 'Degree true' => 'deg', 'Degree' => 'deg', 'm/s' => 'm s-1', 'Common Code table C-1' => 'Code table', 'Common Code Table C-1' => 'Code table', 'Common Code table C-11' => 'Code table', 'Common Code Table C-11' => 'Code table', 'Common Code table C-12' => 'Code table', 'Common Code Table C-12' => 'Code table', 'CodeTable defined by originating/generating centre (Notes 3, 4 and 5)' => 'Code table', 'Code table defined by originating/generating centre' => 'Code table', 'Code table defined by originating/ generating centre (Notes (3), (4) and (5))' => 'Code table', 'Degree/s' => 'deg/s', 'Degree s-1' => 'deg/s', "m\xC2\xB2" => 'm2', 'Degree2' => 'deg2', 'Year' => 'a', 'Month' => 'mon', 'Day' => 'd', 'Hour' => 'h', 'Minute' => 'min', 'Second' => 's', "m\xC2\xB2/s\xC2\xB2" => 'm2 s-2', 'ms-1' => 'm s-1', 'Degree^2' => 'deg2', 'Pa/s' => 'Pa s-1', '/s' => 's-1', '1/s' => 's-1', 'm2/s' => 'm2 s-1', "m\xC2\xB2/s" => 'm2 s-1', "m/s\xC2\xB2" => 'm s-2', 'Km/s' => 'K m s-1', 'rad/m' => 'rad m-1', 'm^(2/3)/s' => 'm2/3 s-1', 'knot' => 'kt', 'km/h' => 'km h-1', " \xC3\x82\xC2\xB0C" => 'C', "\xC3\x82\xC2\xB0C" => 'C', "W/m\xC2\xB2 s/r" => 'W m-2 sr-1', 'kg/kg' => 'kg kg-1', "kg/m\xC2\xB3" => 'kg m-3', 'M' => 'm', "kg/m\xC2\xB2" => 'kg m-2', "kg/(m\xC2\xB2s)" => 'kg m-2 s-1', 'Kg m-2 s-1' => 'kg m-2 s-1', 'Siemens m-1' => 'S m-1', 'S/m' => 'S m-1', 'Kg m-3' => 'kg m-3', 'Lumen' => 'lm', 'kgm-2' => 'kg m-2', "J/m\xC2\xB2" => 'J m-2', "W/m\xC2\xB2" => 'W m-2', 'Wm-2 sr-1 cm-1' => 'W m-2 sr-1 cm-1', "W/(m\xC2\xB2 sr cm)" => 'W m-2 sr-1 cm-1', 'Wm-2sr-1m-1' => 'W m-2 sr-1 m-1', 'Dobson' => 'DU', 'Pascal' => 'Pa', "log(1/m\xC2\xB2)" => 'log(m-2)', "log(1/m2)" => 'log(m-2)', '1/m2' => 'm-2', 'molmol-1' => 'mol mol-1', 'mol/mol' => 'mol mol-1', 'N-units' => 'N units', 'Radians' => 'rad', 'CCITTIA5' => 'CCITT IA5', 'Foot' => 'ft', 'Decibels' => 'dB', 'Rad m-1' => 'rad m-1', 'rad/m' => 'rad m-1', 'dB/deg' => 'dB deg-1', 'dB Deg-1' => 'dB deg-1', 'dB/m' => 'dB m-1', 'db/m' => 'dB m-1', 'Part per thousand' => '0/00', 'm2Hz-1' => 'm2 Hz-1', '1/m' => 'm-1', "m\xC2\xB2 s" => 'm2 s', "m\xC2\xB3" => 'm3', "(m\xC2\xB2/rad)s" => 'm2 rad-1 s', "m\xE2\x81\xB4" => 'm4', "m\xC2\xB3/s" => 'm3 s-1', 'm3/s' => 'm3 s-1', 'Bq*' => 'Bq', 'mSv*/**' => 'mSv', 'MSv' => 'mSv', 'log (m-2)' => 'log(m-2)', 'log (1/m2)' => 'log(m-2)', 's m-1' => 'S m-1', "m\xC2\xB2s" => 'm2 s', 'm^4' => 'm4', "Bq/m\xC2\xB3" => 'Bq m-3', 'Bq/l' => 'Bq L-1', 'Bq l-1' => 'Bq L-1', 'Bq 1-1' => 'Bq L-1', 'log (m-1)' => 'log(m-1)', 'Log m-1' => 'log(m-1)', 'Log/m' => 'log(m-1)', } DELS = %r{( \(SEE NOTE \d+\)| \(SEE NOTES \d+(, \d+)* AND \d+\)| \(DEGREE TRUE\)|\*+|\(+| \(OBSOLETE: SEE NOTE 6\)| \(SEE NOTE\)| \(MOL MOL 1\))$} SUBS = [ [ /POLARISATION/, 'POLARIZATION' ], [ /NUMBER\/ IDENTIFICATION/, 'NUMBER/IDENTIFICATION' ], [ /SPECTRO PHOTOMETER/, 'SPECTROPHOTOMETER' ], [ /WAVE LENGTH/, 'WAVELENGTH' ], [ /WAVE NUMBER/, 'WAVENUMBER' ], [ /NOISE RATION$/, 'NOISE RATIO' ], [ /PROCESSING\(6\)$/, 'PROCESSING' ], [ /WIND \(6\)$/, 'WIND' ], [ /FACTOR \(CF\)$/, 'FACTOR' ], [ /ANGLE \(7\)$/, 'ANGLE' ], [ /\(TEMPERATURE DATA\)$/, '(FOR TEMPERATURE DATA)' ], [ /EARTH'S/, "EARTHS" ], [ /EARTH\xC2\x92S/, "EARTHS" ], [ /EARTH RADIUS/, "EARTHS RADIUS" ], [ /WIND SPEED \(GUSTS\)$/, 'WIND GUST SPEED' ], [ /\(10 MIN MEAN WIND\)/, '(10 MINUTE MEAN WIND)' ], [ /INSTRUMENT$/, 'INSTRUMENTS' ], [ / \(SOLUTION (\d)\)$/, 'SOLUTION \1' ], [ /DRY BULB TEMPERATURE/, 'AIR TEMPERATURE' ], [ /AT 2M/, 'AT 2 M' ], [ /GLOBAL RADIATION/, 'GLOBAL SOLAR RADIATION' ], [ /BI DIRECTIONAL/, 'BIDIRECTIONAL' ], [ /, /, ' ' ], [ / [0O]3 /, ' OZONE ' ], [ /COLOR/, 'COLOUR' ], [ /SATELLLITE/, 'SATELLITE' ], [ /COEFFICENT/, 'COEFFICIENT' ], [ / NOF\* /, ' NOF ' ], [ / CORRECTION OF SIGMA /, ' CORRECTION ON SIGMA ' ], [ /CO LOCATION/, 'COLLOCATION' ], [ /CO ORDINATE/, 'COORDINATE' ], [ /AT 40 DEG\. /, 'AT 40 DEGREES ' ], [ /NUMBERS\(WAVELENGTH/, 'NUMBERS (WAVELENGTH' ], [ /STD 18HZ /, 'STD OF 18 HZ ' ], [ / 20HZ /, ' 20 HZ ' ], [ /FM REGIONAL/, 'FM AND REGIONAL' ], [ /RADIOMETRIC\)$/, 'RADIOMETRIC CALIBRATION)' ], [ /^ALTERNATE LONGITUDE$/, 'ALTERNATE LONGITUDE (COARSE ACCURACY)' ], [ /^ALTERNATE LATITUDE$/, 'ALTERNATE LATITUDE (COARSE ACCURACY)' ], [ /^OZONE$/, 'TOTAL OZONE' ], [ /KP ESTIMATE QUALITY/, 'KP QUALITY ESTIMATE' ], [ /NEMBER/, 'NUMBER' ], [ /MIXING RATIO QUALITY/, 'MOISTURE QUALITY' ], [ /HEIGHTSOLUTION/, 'HEIGHT SOLUTION' ], ] def checkB sql = <<-SQL SELECT dom, cls, cod FROM bufrb GROUP BY dom, cls, cod SQL @db.execute(sql) do |row| dom, cls, cod = row h = {} sql = <<-SQL SELECT ver, uni, wid, scl, rfv, dsc, sta FROM bufrb WHERE dom = ? AND cls = ? AND cod = ? SQL @db.execute(sql, [dom, cls, cod]) do |row| ver, uni, wid, scl, rfv, dsc, sta = row next if /Validation/ === sta uni = uni.strip uni = UTAB[uni] if UTAB.include?(uni) d = dsc.strip.upcase.gsub(/[-\s]+/, ' ') d.sub!(DELS, '') for r, s in SUBS d.sub!(r, s) end m = [wid, scl, rfv, uni, d].join("\t") h[m] = [] unless h.include?(m) h[m].push ver.to_i end next if h.size < 2 fxy = format('%03u:0-%02u-%03u', dom.to_i, cls.to_i, cod.to_i) syms = %w(W S R U D) chgs = {} syms.size.times do |i| vals = h.keys.map{|m| m.split(/\t/)[i] }.uniq chgs[syms[i]] = true if vals.size > 1 end chg = chgs.keys.sort.join for m, vers in h puts [chg, fxy, m, vers.sort.join(',')].join("\t") end end end def run checkB $stderr.puts "done" end end App.new.run