lib/eew_parser.rb in eew_parser-0.1.6 vs lib/eew_parser.rb in eew_parser-0.1.7
- old
+ new
@@ -2,12 +2,11 @@
require_relative "epicenter_code"
require_relative "area_code"
# 緊急地震速報パーサ
-# Author:: Glass_saga
-# License:: NYSL Version 0.9982
+# Author:: mmasaki
#
# 高度利用者向け緊急地震速報コード電文フォーマットを扱う為のライブラリです。
# http://eew.mizar.jp/excodeformat を元に作成しました。
#
# str = <<EOS
@@ -28,20 +27,25 @@
# 引数には緊急地震速報の電文を与えます。
def initialize(str)
raise ArgumentError unless str.is_a?(String)
@fastcast = str.dup
@fastcast.freeze
- raise Error, "電文の形式が不正です" if @fastcast.size < 135
+ raise Error, "電文の形式が不正です" if @fastcast.bytesize < 135
end
attr_reader :fastcast
# initializeに与えられた電文を返します。
def to_s
- @fastcast
+ @fastcast.dup
end
+ # 電文のサイズを返します。
+ def size
+ @fastcast.bytesize
+ end
+
# 緊急地震速報の内容をテキストで出力します。
def print
str = <<-EOS
電文種別: #{self.type}
発信官署: #{self.from}
@@ -92,20 +96,28 @@
hash[attribute] = __send__(attribute)
end
return hash
end
+ # 正しい電文であるかを返します
+ def verify
+ Attributes.each do |attribute|
+ __send__(attribute)
+ end
+ return true
+ end
+
def inspect
- "#<EEWParser:#{id}>"
+ "#<EEWParser:#{id} (第#{number}報) #{epicenter} #{seismic_intensity}>"
end
def ==(other)
fastcast == other.fastcast
end
def <=>(other)
- Integer(id) <=> Integer(id)
+ __id__ <=> other.__id__
end
# 電文種別コード
def type
case @fastcast[0, 2]
@@ -160,20 +172,33 @@
else
raise Error, "電文の形式が不正です(識別符)"
end
end
+ # 訓練かどうか
+ def drill?
+ case @fastcast[6, 2]
+ when "00", "10", "20"
+ return false
+ when "01", "11", "30"
+ return true
+ else
+ raise Error, "電文の形式が不正です(識別符)"
+ end
+ end
+
# 電文の発表時刻のTimeオブジェクトを返します。
def report_time
Time.local("20" + @fastcast[9, 2], @fastcast[11, 2], @fastcast[13, 2], @fastcast[15, 2], @fastcast[17, 2], @fastcast[19, 2])
end
# 電文がこの電文を含め何通あるか(Integer)
def number_of_telegram
number_of_telegram = @fastcast[23]
- raise Error, "電文の形式が不正です" if number_of_telegram =~ /[^\d]/
- number_of_telegram.to_i
+ return Integer(number_of_telegram, 10)
+ rescue ArgumentError
+ raise Error, "電文の形式が不正です"
end
# コードが続くかどうか
def continue?
case @fastcast[24]
@@ -192,14 +217,20 @@
end
# 地震識別番号(String)
def id
id = @fastcast[41, 14]
- raise Error, "電文の形式が不正です(地震識別番号)" if id =~ /[^\d]/
- id
+ Integer(id, 10) # verify
+ return id
+ rescue ArgumentError
+ raise Error, "電文の形式が不正です(地震識別番号: #{id})"
end
+ def __id__
+ id + number.to_s
+ end
+
# 発表状況(訂正等)の指示
def status
case @fastcast[59]
when "0"
"通常発表"
@@ -216,10 +247,16 @@
else
raise Error, "電文の形式が不正です"
end
end
+ # 第1報であればtrueを、そうでなければfalseを返します。
+ def first?
+ return true if self.number == 1
+ return false
+ end
+
# 最終報であればtrueを、そうでなければfalseを返します。
def final?
case @fastcast[59]
when "9"
true
@@ -231,56 +268,63 @@
end
# 発表する高度利用者向け緊急地震速報の番号(地震単位での通番)(Integer)
def number
number = @fastcast[60, 2]
- raise Error, "電文の形式が不正です(高度利用者向け緊急地震速報の番号)" if number =~ /[^\d]/
- number.to_i
+ return Integer(number, 10)
+ rescue ArgumentError
+ raise Error, "電文の形式が不正です(高度利用者向け緊急地震速報の番号)"
end
alias :revision :number
# 震央の名称
def epicenter
- key = @fastcast[86, 3]
- raise Error, "電文の形式が不正です(震央の名称)" if key =~ /[^\d]/
- EpicenterCode[key.to_i]
+ code = @fastcast[86, 3]
+ code = Integer(code, 10)
+ EpicenterCode.fetch(code)
+ rescue KeyError
+ raise Error, "電文の形式が不正です(震央地名コード: #{code})"
+ rescue ArgumentError
+ raise Error, "電文の形式が不正です(震央の名称)"
end
# 震央の位置
def position
position = @fastcast[90, 10]
if position == "//// /////"
"不明又は未設定"
else
- raise Error, "電文の形式が不正です(震央の位置)" if position =~ /[^\d|\s|N|E]/
+ raise Error, "電文の形式が不正です(震央の位置)" unless position.match(/N\d{3} E\d{4}/)
position.insert(3, ".").insert(10, ".")
end
end
# 震源の深さ(単位 km)
def depth
depth = @fastcast[101, 3]
if depth == "///"
- "不明又は未設定"
+ return "不明又は未設定"
else
- raise Error, "電文の形式が不正です(震源の深さ)" if depth =~ /[^\d]/
- depth.to_i
+ return Integer(depth, 10)
end
+ rescue ArgumentError
+ raise Error, "電文の形式が不正です(震源の深さ)"
end
# マグニチュード
# マグニチュードが不明又は未設定である場合は"不明又は未設定"を返します。
# そうでなければ、マグニチュードをFloatで返します。
def magnitude
magnitude = @fastcast[105, 2]
if magnitude == "//"
- "不明又は未設定"
+ return "不明又は未設定"
else
- raise Error, "電文の形式が不正です(マグニチュード)" if magnitude =~ /[^\d]/
- (magnitude[0] + "." + magnitude[1]).to_f
+ return Float(magnitude[0] + "." + magnitude[1])
end
+ rescue ArgumentError
+ raise Error, "電文の形式が不正です(マグニチュード)"
end
# 電文フォーマットの震度を文字列に変換
def to_seismic_intensity(str)
case str
@@ -310,12 +354,10 @@
end
# 最大予測震度
def seismic_intensity
to_seismic_intensity(@fastcast[108, 2])
- rescue Error
- raise Error, "電文の形式が不正です(最大予測震度)"
end
# 震央の確からしさ
def probability_of_position
case @fastcast[113]
@@ -484,10 +526,20 @@
else
raise Error, "電文の形式が不正です(最大予測震度の変化)"
end
end
+ # 最大予測震度に変化があったかどうか
+ def changed?
+ case @fastcast[129]
+ when "0", "3".."9", "/"
+ return false
+ when "1", "2"
+ return true
+ end
+ end
+
# 最大予測震度の変化の理由
def reason_of_change
case @fastcast[130]
when "0"
"変化無し"
@@ -506,10 +558,19 @@
else
raise Error, "電文の形式が不正です(最大予測震度の変化の理由)"
end
end
+ # EBIを含むかどうか
+ def has_ebi?
+ if @fastcast[135, 3] == "EBI"
+ return true
+ else
+ return false
+ end
+ end
+
# 地域毎の警報の判別、最大予測震度及び主要動到達予測時刻
# EBIがあればHashを格納したArrayを、なければ空のArrayを返します。Hashに格納されるkeyとvalueはそれぞれ次のようになっています。
# :area_name 地域名称
# :intensity 最大予測震度
# :arrival_time 予想到達時刻のTimeオブジェクト。既に到達している場合はnil
@@ -517,10 +578,10 @@
# :arrival 既に到達していればtrue、そうでなければfalse、電文にこの項目が設定されていなければnil
def ebi
data = []
return data unless @fastcast[135, 3] == "EBI"
i = 139
- while i + 20 < @fastcast.size
+ while i + 20 < @fastcast.bytesize
local = {}
local[:area_code] = @fastcast[i, 3].to_i
local[:area_name] = AreaCode[local[:area_code]] # 地域名称
raise Error, "電文の形式が不正でです(地域名称[EBI])" unless local[:area_name]
if @fastcast[i+7, 2] == "//"