Class: EEW::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/eew_parser.rb

Defined Under Namespace

Classes: Error

Constant Summary collapse

Attributes =
[
  :type, :from, :drill_type, :report_time, :number_of_telegram, :continue?, :earthquake_time, :id, :status, :final?, :number, :epicenter, :position, :depth,
  :magnitude, :seismic_intensity, :observation_points_of_magnitude, :probability_of_depth, :probability_of_magnitude, :probability_of_position, :probability_of_depth_jma,
  :land_or_sea, :warning?, :prediction_method, :change, :reason_of_change, :ebi
].freeze
SeismicIntensity =
{
  "//" => "不明又は未設定",
  "01" => "1",
  "02" => "2",
  "03" => "3",
  "04" => "4",
  "5-" => "5弱",
  "5+" => "5強",
  "6-" => "6弱",
  "6+" => "6強",
  "07" => "7"
}.freeze
OriginProbability =
{
  "1" => "P波/S波レベル越え、またはIPF法(1点) または仮定震源要素の場合",
  "2" => "IPF法(2点)",
  "3" => "IPF法(3点/4点)",
  "4" => "IPF法(5点)",
  "5" => "防災科研システム(4点以下、または精度情報なし)[防災科研Hi-netデータ]",
  "6" => "防災科研システム(5点以上)[防災科研Hi-netデータ]",
  "7" => "EPOS(海域[観測網外])",
  "8" => "EPOS(内陸[観測網内])",
  "9" => "予備",
  "/" =>"不明又は未設定"
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(str) ⇒ Parser

引数には緊急地震速報の電文を与えます。

Raises:

  • (ArgumentError)


28
29
30
31
32
33
34
# File 'lib/eew_parser.rb', line 28

def initialize(str)
  raise ArgumentError unless str.is_a?(String)
  @fastcast = str.dup
  @fastcast.force_encoding(Encoding::ASCII)
  @fastcast.freeze
  raise Error, "電文の形式が不正です" if @fastcast.bytesize < 135
end

Instance Attribute Details

#fastcastObject (readonly)

Returns the value of attribute fastcast.



36
37
38
# File 'lib/eew_parser.rb', line 36

def fastcast
  @fastcast
end

Instance Method Details

#<=>(other) ⇒ Object



135
136
137
# File 'lib/eew_parser.rb', line 135

def <=>(other)
  __id__ <=> other.__id__
end

#==(other) ⇒ Object



131
132
133
# File 'lib/eew_parser.rb', line 131

def ==(other)
  fastcast == other.fastcast
end

#__id__Object

地震識別番号 + 通番



257
258
259
# File 'lib/eew_parser.rb', line 257

def __id__
  (id * 10) + number
end

#canceled?Boolean

キャンセル報かどうか

Returns:

  • (Boolean)


156
157
158
159
# File 'lib/eew_parser.rb', line 156

def canceled?
  return true if @fastcast[0, 2] == "39"
  return false
end

#changeObject

最大予測震度の変化



524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
# File 'lib/eew_parser.rb', line 524

def change
  case @fastcast[129]
  when "0"
    "ほとんど変化無し"
  when "1"
    "最大予測震度が1.0以上大きくなった"
  when "2"
    "最大予測震度が1.0以上小さくなった"
  when "3".."9"
    "未定義"
  when "/"
    "不明又は未設定"  
  else
    raise Error, "電文の形式が不正です(最大予測震度の変化)"
  end
end

#changed?Boolean

最大予測震度に変化があったかどうか

Returns:

  • (Boolean)


542
543
544
545
546
547
548
549
# File 'lib/eew_parser.rb', line 542

def changed?
  case @fastcast[129]
  when "0", "3".."9", "/"
    return false
  when "1", "2"
    return true
  end
end

#continue?Boolean

コードが続くかどうか

Returns:

  • (Boolean)


229
230
231
232
233
234
235
236
237
238
# File 'lib/eew_parser.rb', line 229

def continue?
  case @fastcast[24]
  when "1"
    true
  when "0"
    false
  else
    raise Error, "電文の形式が不正です"
  end
end

#depthObject

震源の深さ(単位 km)



336
337
338
339
340
341
342
343
344
345
# File 'lib/eew_parser.rb', line 336

def depth
  depth = @fastcast[101, 3]
  if depth == "///"
    return "不明又は未設定"
  else
    return Integer(depth, 10)
  end
rescue ArgumentError
  raise Error, "電文の形式が不正です(震源の深さ)"
end

#drill?Boolean

訓練かどうか

Returns:

  • (Boolean)


202
203
204
205
206
207
208
209
210
211
# File 'lib/eew_parser.rb', line 202

def drill?
  case @fastcast[6, 2]
  when "00", "10", "20"
    return false
  when "01", "11", "30"
    return true
  else
    raise Error, "電文の形式が不正です(識別符)"
  end
end

#drill_typeObject

訓練等の識別符



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/eew_parser.rb', line 182

def drill_type
  case @fastcast[6, 2]
  when "00"
    "通常"
  when "01"
    "訓練"
  when "10"
    "取り消し"
  when "11"
    "訓練取り消し"
  when "20"
    "参考情報またはテキスト"
  when "30"
    "コード部のみの配信試験"
  else
    raise Error, "電文の形式が不正です(識別符)"
  end
end

#earthquake_timeObject

地震発生時刻もしくは地震検知時刻のTimeオブジェクトを返します。



241
242
243
244
245
# File 'lib/eew_parser.rb', line 241

def earthquake_time
  Time.local("20" + @fastcast[26, 2], @fastcast[28, 2], @fastcast[30, 2], @fastcast[32, 2], @fastcast[34, 2], @fastcast[36, 2])
rescue ArgumentError
  raise Error, "電文の形式が不正です (地震発生時刻: #{@fastcast[26, 12]})"
end

#ebiObject

地域毎の警報の判別、最大予測震度及び主要動到達予測時刻

EBIがあればHashを格納したArrayを、なければ空のArrayを返します。Hashに格納されるkeyとvalueはそれぞれ次のようになっています。
:area_name 地域名称
:intensity 最大予測震度
:arrival_time 予想到達時刻のTimeオブジェクト。既に到達している場合はnil
:warning 警報を含んでいればtrue、含んでいなければfalse、電文にこの項目が設定されていなければnil
:arrival 既に到達していればtrue、そうでなければfalse、電文にこの項目が設定されていなければnil


588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
# File 'lib/eew_parser.rb', line 588

def ebi
  return [] unless has_ebi?
  return @ebi.dup if @ebi

  @ebi = []
  i = 139
  while i + 20 < @fastcast.bytesize
    local_str = @fastcast[i, 20]
    area_code = ebi_area_code(local_str)
    local = {
      area_code: area_code,
      area_name: ebi_area_name(area_code),
      intensity: ebi_intensity(local_str),
      arrival_time: ebi_arrival_time(local_str),
      warning: ebi_warning(local_str),
      arrival: ebi_arrival(local_str)
    }
    local.freeze
    @ebi.push(local)
    i += 20
  end
  @ebi.freeze
  return @ebi.dup
end

#epicenterObject

震央の名称



316
317
318
319
320
321
322
# File 'lib/eew_parser.rb', line 316

def epicenter
  code = @fastcast[86, 3]
  code = Integer(code, 10)
  EpicenterCode.fetch(code)
rescue ArgumentError, KeyError
  raise Error, "電文の形式が不正です(震央地名コード: #{code})"
end

#final?Boolean

最終報であればtrueを、そうでなければfalseを返します。

Returns:

  • (Boolean)


294
295
296
297
298
299
300
301
302
303
# File 'lib/eew_parser.rb', line 294

def final?
  case @fastcast[59]
  when "9"
    true
  when "0", "6", "7", "8", "/"
    false
  else
    raise Error, "電文の形式が不正です"
  end
end

#first?Boolean

第1報であればtrueを、そうでなければfalseを返します。

Returns:

  • (Boolean)


288
289
290
291
# File 'lib/eew_parser.rb', line 288

def first? 
  return true if self.number == 1
  return false
end

#fromObject

発信官署



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/eew_parser.rb', line 162

def from
  case @fastcast[3, 2]
  when "01"
    "札幌"
  when "02"
    "仙台"
  when "03"
    "東京"
  when "04"
    "大阪"
  when "05"
    "福岡"
  when "06"
    "沖縄"
  else
    raise Error, "電文の形式が不正です(発信官署)"
  end
end

#has_ebi?Boolean

EBIを含むかどうか

Returns:

  • (Boolean)


576
577
578
579
# File 'lib/eew_parser.rb', line 576

def has_ebi?
  return true if @fastcast[135, 3] == "EBI"
  return false
end

#idObject

地震識別番号(String)



248
249
250
251
252
253
254
# File 'lib/eew_parser.rb', line 248

def id
  id = @fastcast[41, 14]
  Integer(id, 10) # verify
  return id
rescue ArgumentError
  raise Error, "電文の形式が不正です(地震識別番号: #{id})"
end

#inspectObject



127
128
129
# File 'lib/eew_parser.rb', line 127

def inspect
  "#<EEWParser:#{id} (第#{number}報) #{epicenter} 震度#{seismic_intensity}>"
end

#land_or_seaObject

震央位置の海陸判定



482
483
484
485
486
487
488
489
490
491
492
493
494
495
# File 'lib/eew_parser.rb', line 482

def land_or_sea
  case @fastcast[121]
  when "0"
    "陸域"
  when "1"
    "海域"
  when "/"
    "不明又は未設定"
  when "2".."9"
    "未定義"
  else
    raise Error, "電文の形式が不正です(震央位置の海陸判定)"
  end
end

#magnitudeObject

マグニチュード

マグニチュードが不明又は未設定である場合は"不明又は未設定"を返します。
そうでなければ、マグニチュードをFloatで返します。


350
351
352
353
354
355
356
357
358
359
# File 'lib/eew_parser.rb', line 350

def magnitude
  magnitude = @fastcast[105, 2]
  if magnitude == "//"
    return "不明又は未設定"
  else
    return Float(magnitude[0] + "." + magnitude[1])
  end
rescue ArgumentError
  raise Error, "電文の形式が不正です(マグニチュード)"
end

#normal?Boolean

発表状況と訓練識別が通常かどうか

Returns:

  • (Boolean)


282
283
284
285
# File 'lib/eew_parser.rb', line 282

def normal?
  return true if (@fastcast[59] == "0" || @fastcast[59] == 9) && @fastcast[6, 2] == "00"
  return false
end

#numberObject Also known as: revision

発表する高度利用者向け緊急地震速報の番号(地震単位での通番)(Integer)



306
307
308
309
310
311
# File 'lib/eew_parser.rb', line 306

def number
  number = @fastcast[60, 2]
  return Integer(number, 10)
rescue ArgumentError
  raise Error, "電文の形式が不正です(高度利用者向け緊急地震速報の番号: #{number})"
end

#number_of_telegramObject

電文がこの電文を含め何通あるか(Integer)



221
222
223
224
225
226
# File 'lib/eew_parser.rb', line 221

def number_of_telegram
  number_of_telegram = @fastcast[23]
  return Integer(number_of_telegram, 10)
rescue ArgumentError
  raise Error, "電文の形式が不正です"
end

#observation_points_of_magnitudeObject Also known as: probability_of_position_jma

マグニチュード使用観測点(※気象庁の部内システムでの利用)



435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
# File 'lib/eew_parser.rb', line 435

def observation_points_of_magnitude
  case @fastcast[116]
  when "1"
    "1点、P波/S波レベル超え、または仮定震源要素"
  when "2"
    "2点"
  when "3"
    "3点"
  when "4"
    "4点"
  when "5"
    "5点以上"
  when "/"
    "不明又は未設定"
  when "6".."9", "0"
    "未定義"
  else
    raise Error, "電文の形式が不正です(マグニチュード使用観測点[気象庁の部内システムでの利用])"
  end
end

#positionObject

震央の位置



325
326
327
328
329
330
331
332
333
# File 'lib/eew_parser.rb', line 325

def position
  position = @fastcast[90, 10]
  if position == "//// /////"
    "不明又は未設定"
  else
    raise Error, "電文の形式が不正です(震央の位置)" unless position.match(/(?:N|S)\d{3} (?:E|W)\d{4}/)
    position.insert(3, ".").insert(10, ".")
  end
end

#prediction_methodObject

予測手法



510
511
512
513
514
515
516
517
518
519
520
521
# File 'lib/eew_parser.rb', line 510

def prediction_method 
  case @fastcast[123]
  when "9"
    "震源とマグニチュードによる震度推定手法において震源要素が推定できず、PLUM 法による震度予測のみが有効である場合"
  when "0".."8"
    "未定義"
  when "/"
    "不明又は未設定"
  else
    raise Error, "電文の形式が不正です(警報の判別)"
  end
end

緊急地震速報の内容をテキストで出力します。



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/eew_parser.rb', line 49

def print
  return @print.dup if @print

  @print = <<-EOS
緊急地震速報 (第#{number}報)
電文種別: #{type}
発信官署: #{from}
訓練等の識別符: #{drill_type}
電文の発表時刻: #{report_time.strftime("%F %T")}
電文がこの電文を含め何通あるか: #{number_of_telegram}
コードが続くかどうか: #{continue?}
地震発生時刻もしくは地震検知時刻: #{earthquake_time.strftime("%F %T")}
地震識別番号: #{id}
発表状況(訂正等)の指示: #{status}
発表する高度利用者向け緊急地震速報の番号(地震単位での通番): #{number}
震央地名: #{epicenter}
震央の位置: #{position}
震源の深さ(単位 km)(不明・未設定時,キャンセル時:///): #{depth}
マグニチュード(不明・未設定時、キャンセル時:///): #{magnitude}
最大予測震度(不明・未設定時、キャンセル時://): #{seismic_intensity}
震央の確からしさ: #{probability_of_position}
震源の深さの確からしさ: #{probability_of_depth}
マグニチュードの確からしさ: #{probability_of_magnitude}
震央の確からしさ(気象庁の部内システムでの利用): #{probability_of_position_jma}
震源の深さの確からしさ(気象庁の部内システムでの利用): #{probability_of_depth_jma}
震央位置の海陸判定: #{land_or_sea}
警報を含む内容かどうか: #{warning?}
予測手法: #{prediction_method}
最大予測震度の変化: #{change}
最大予測震度の変化の理由: #{reason_of_change}
  EOS

  if has_ebi?
    @print << "\n地域毎の警報の判別、最大予測震度及び主要動到達予測時刻(EBI):\n"
    ebi.each do |local|
      arrival_time = local[:arrival] ? "すでに到達" : local[:arrival_time]&.strftime("%T")
      @print << "#{local[:area_name]} 最大予測震度: #{local[:intensity]} 予想到達時刻: #{arrival_time} 警報: #{local[:warning]}\n" 
    end
  end

  @print.freeze
  return @print.dup
end

#probability_of_depthObject

震源の深さの確からしさ



400
401
402
403
404
# File 'lib/eew_parser.rb', line 400

def probability_of_depth
  OriginProbability.fetch(@fastcast[114])
rescue KeyError
  raise Error, "電文の形式が不正です(震央の確からしさ)"
end

#probability_of_depth_jmaObject

震源の深さの確からしさ(※気象庁の部内システムでの利用)



460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
# File 'lib/eew_parser.rb', line 460

def probability_of_depth_jma
  case @fastcast[117]
  when "1"
    "P波/S波レベル越え、IPF法(1点)、または仮定震源要素"
  when "2"
    "IPF法(2点)"
  when "3"
    "IPF法(3点/4点)"
  when "4"
    "IPF法(5点以上)"
  when "9"
    "震源とマグニチュードに基づく震度予測手法の精度が最終報相当"
  when "/"
    "不明又は未設定"
  when "5".."8", "0"
    "未定義"
  else
    raise Error, "電文の形式が不正です(震源の深さの確からしさ[気象庁の部内システムでの利用])"
  end
end

#probability_of_magnitudeObject

マグニチュードの確からしさ



407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
# File 'lib/eew_parser.rb', line 407

def probability_of_magnitude
  case @fastcast[115]
  when "1"
    "未定義"
  when "2"
    "防災科研システム[防災科研Hi-netデータ]"
  when "3"
    "全点P相"
  when "4"
    "P相/全相混在"
  when "5"
    "全点全相"
  when "6"
    "EPOS"
  when "7"
    "未定義"
  when "8"
    "P波/S波レベル越え または仮定震源要素の場合"
  when "9"
    "予備"
  when "/", "0"
    "不明又は未設定"
  else
    raise Error, "電文の形式が不正です(マグニチュードの確からしさ)"
  end
end

#probability_of_positionObject

震央の確からしさ



393
394
395
396
397
# File 'lib/eew_parser.rb', line 393

def probability_of_position
  OriginProbability.fetch(@fastcast[113])
rescue KeyError
  raise Error, "電文の形式が不正です(震央の確からしさ)"
end

#reason_of_changeObject

最大予測震度の変化の理由



552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
# File 'lib/eew_parser.rb', line 552

def reason_of_change
  case @fastcast[130]
  when "0"
    "変化無し"
  when "1"
    "主としてMが変化したため(1.0以上)"
  when "2"
    "主として震源位置が変化したため(10.0km以上)"
  when "3"
    "M及び震源位置が変化したため"
  when "4"
    "震源の深さが変化したため"
  when "9"
    "PLUM 法による予測により変化したため"
  when "/"
    "不明又は未設定"
  when "5".."8"
    "未定義"
  else
    raise Error, "電文の形式が不正です(最大予測震度の変化の理由)"
  end
end

#report_timeObject

電文の発表時刻のTimeオブジェクトを返します。



214
215
216
217
218
# File 'lib/eew_parser.rb', line 214

def report_time
  Time.local("20" + @fastcast[9, 2], @fastcast[11, 2], @fastcast[13, 2], @fastcast[15, 2], @fastcast[17, 2], @fastcast[19, 2])
rescue ArgumentError
  raise Error, "電文の形式が不正です (発表時刻: #{@fastcast[9, 12]})"
end

#seismic_intensityObject

最大予測震度



375
376
377
# File 'lib/eew_parser.rb', line 375

def seismic_intensity
  to_seismic_intensity(@fastcast[108, 2]) 
end

#sizeObject

電文のサイズを返します。



44
45
46
# File 'lib/eew_parser.rb', line 44

def size
  @fastcast.bytesize
end

#statusObject

発表状況(訂正等)の指示



262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/eew_parser.rb', line 262

def status
  case @fastcast[59]
  when "0"
    "通常発表"
  when "6"
    "情報内容の訂正"
  when "7"
    "キャンセルを誤って発表した場合の訂正"
  when "8"
    "訂正事項を盛り込んだ最終の高度利用者向け緊急地震速報"
  when "9"
    "最終の高度利用者向け緊急地震速報"
  when "/"
    "未設定"
  else
    raise Error, "電文の形式が不正です"     
  end
end

#to_hashObject

電文を解析した結果をHashで返します。



100
101
102
103
104
105
106
107
108
109
# File 'lib/eew_parser.rb', line 100

def to_hash
  unless @hash
    @hash = {}
    Attributes.each do |attribute|
      @hash[attribute] = __send__(attribute)
    end
    @hash.freeze
  end
  return @hash.dup
end

#to_sObject

initializeに与えられた電文を返します。



39
40
41
# File 'lib/eew_parser.rb', line 39

def to_s
  @fastcast.dup
end

#typeObject

電文種別コード



140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/eew_parser.rb', line 140

def type
  case @fastcast[0, 2]
  when "35"
    "最大予測震度のみの高度利用者向け緊急地震速報"
  when "36"
    "マグニチュード、最大予測震度及び主要動到達予測時刻の高度利用者向け緊急地震速報(B-Δ法、テリトリ法)"
  when "37"
    "マグニチュード、最大予測震度及び主要動到達予測時刻の高度利用者向け緊急地震速報(グリッドサーチ法、EPOS自動処理手法)"
  when "39"
    "キャンセル報"
  else
    raise Error, "電文の形式が不正です(電文種別コード)"
  end
end

#valid?Boolean

正しい電文であるかを返します

Returns:

  • (Boolean)


112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/eew_parser.rb', line 112

def valid?
  unless @valid
    begin
      Attributes.each do |attribute|
        __send__(attribute)
      end
    rescue Error
      @valid = false
    else
      @valid = true
    end
  end
  return @valid
end

#warning?Boolean

警報を含む内容であればtrue、そうでなければfalse

Returns:

  • (Boolean)


498
499
500
501
502
503
504
505
506
507
# File 'lib/eew_parser.rb', line 498

def warning?
  case @fastcast[122]
  when "0", "/", "2".."9"
    false
  when "1"
    true
  else
    raise Error, "電文の形式が不正です(警報の判別)"
  end
end