jma_feed 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6e548f6f36c66d5fbf33b4827e9dc92ebb5a3db3e7afe5d65ab6e3438e7c2636
4
+ data.tar.gz: 8624233d9b3ad4e95b31ee409103aed698df7be193f32a3dd1b092cb049bfd52
5
+ SHA512:
6
+ metadata.gz: 3e0ce670bfdeb22f6ff8a1bfeae084643acbe03706c73dce37eb5851720852bcd79c04da42fc2dcfebb7c04afa9af679e75b1fcecebe7a1c722fd576d6b0cbf9
7
+ data.tar.gz: 48de3a2546694270418a5b4175e97187aedb65c876863b66bb58f90f899b0d034100cc11d4c04a7181d44a58347b49ad534961930a3c0e29701bc07e178b069f
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # README
2
+
3
+ # DEVELOPMENT GUIDE
4
+
5
+ ## REPL
6
+
7
+ Since `Gemfile` has the line below, you just run `require "jma_feed"` in `bundle exec irb` to start `JMAFeed`.
8
+
9
+ ```
10
+ gem "jma_feed", path: './'
11
+ ```
12
+
13
+ ```
14
+ bundle install
15
+ ```
16
+
17
+ ```
18
+ bundle exec irb
19
+
20
+ # (irb):> require "jma_feed"
21
+ ```
22
+
23
+ ## Local Build
24
+
25
+ Since it has `Rakefile`, you just run the following command to make build and install it on your local.
26
+
27
+ ```
28
+ bundle exec rake build
29
+ bundle exec rake install
30
+ ```
31
+
32
+ Then you just run `require "jma_feed"` in `irb` to start `JMAFeed`.
33
+
34
+ ```
35
+ irb
36
+
37
+ (irb):> require "jma_feed"
38
+ ```
39
+
40
+ ## Publish Gem
41
+
42
+ If you have the right to publish it to rubygems, run it.
43
+
44
+ ```
45
+ bundle exec rake build
46
+ gem push ./pkg/jma_feed-${VERSION}.gem
47
+ ```
@@ -0,0 +1,91 @@
1
+ 通番,分野,種別,資料(情報)名,"管理部:情報名称
2
+ (Control部のTitle)","<参考>
3
+ データ種類コード(オンライン配信時の電文識別用)",圧縮形式,サイズ(kbyte),,備考,(参考)旧形式(かな漢字形式等)電文のデータ種類コード
4
+ ,,,,,,,平均,最大,,
5
+ 1,気象,観測・解析,特殊気象報,季節観測,VGSK50,(非圧縮),3,5,,キセツ
6
+ 2,気象,観測・解析,生物季節観測報告気象報,生物季節観測,VGSK55,(非圧縮),3,5,,セイブツ,ブナイセイブツ
7
+ 3,気象,観測・解析,特殊気象報(トクシユ),特殊気象報,VGSK60,(非圧縮),3,5,※①,トクシユ
8
+ 6,気象,観測・解析/予報・予測,全般台風情報(総合情報、上陸等情報),発達する熱帯低気圧に関する情報,全般台風情報,VPTI50,GZIP,5,6,※②,ゼンコクタイフウ11
9
+ 7,気象,観測・解析/予報・予測,全般台風情報(位置、発生情報),発達する熱帯低気圧に関する情報,全般台風情報(定型),VPTI51,GZIP,5,6,※②,ゼンコクタイフウ21
10
+ 8,気象,観測・解析/予報・予測,全般台風情報(位置詳細),全般台風情報(詳細),VPTI52,GZIP,5,6,※②,ゼンコクタイフウ22
11
+ 9,気象,観測・解析/予報・予測,台風解析・予報情報電文(新形式),台風解析・予報情報(3日予報),VPTWii(ii=40-45),GZIP,20,100,※②令和3年度に廃止,KFXCii (ii=80-85)
12
+ 10,気象,観測・解析/予報・予測,台風解析・予報情報(延長予報)電文(新形式),台風解析・予報情報(5日予報),VPTWii(ii=50-55),GZIP,25,120,※②令和3年度に廃止,KFXCii (ii=90-95)
13
+ 10,気象,観測・解析/予報・予測,台風解析・予報情報(延長予報)電文(新形式),台風解析・予報情報(5日予報)(H30),VPTWii(ii=60-65),GZIP,30,150,"※②
14
+ 「1.3.5 地理空間情報(位置・領域)表記」に記載の例外となる情報",
15
+ 11,気象,観測・解析/予報・予測,全般海上警報(定時),全般海上警報(定時),VPZU50,GZIP,25,110,※②令和3年度に廃止,ウミケイホウ1
16
+ 11,気象,観測・解析/予報・予測,全般海上警報(定時),全般海上警報(定時)(H29),VPZU52,GZIP,25,110,"※②
17
+ 「1.3.5 地理空間情報(位置・領域)表記」に記載の例外となる情報",
18
+ 12,気象,観測・解析/予報・予測,全般海上警報(臨時),全般海上警報(臨時),VPZU51,GZIP,25,110,※②令和3年度に廃止,ウミケイホウ2
19
+ 12,気象,観測・解析/予報・予測,全般海上警報(臨時),全般海上警報(臨時)(H29),VPZU53,GZIP,25,110,"※②
20
+ 「1.3.5 地理空間情報(位置・領域)表記」に記載の例外となる情報",
21
+ 13,気象,観測・解析/予報・予測,地方海上警報,地方海上警報,VPCU50,GZIP,15,100,※① 令和2年度に廃止,チホウウミケイホウ1
22
+ 13,気象,観測・解析/予報・予測,地方海上警報,地方海上警報(H28),VPCU51,GZIP,20,100,※①,
23
+ 14,気象,予報・予測,地方海上予報,地方海上予報,VPCY50,GZIP,50,200,※① 令和2年度に廃止,チホウウミヨホウ1
24
+ 14,気象,予報・予測,地方海上予報,地方海上予報(H28),VPCY51,GZIP,60,200,※①,
25
+ 15,気象,予報・予測,気象特別警報・警報・注意報,気象警報・注意報,VPWW50,GZIP,100,300,※①(VPWW50を令和元年度末に廃止),ケイホウ1,ケイホウトク1,チユウイホウ1,ケイホウ11,ケイホウトク11,チユウイホウ11, ケイホウ13,ケイホウ21,ケイホウトク21,チユウイホウ21,VPWW40
26
+ 15,気象,予報・予測,気象特別警報・警報・注意報,気象特別警報・警報・注意報,VPWW53,,100,300,,
27
+ 15,気象,予報・予測,気象特別警報・警報・注意報,気象警報・注意報(H27),VPWW54,,600,"1,500",,
28
+ 16,気象,予報・予測,指定河川洪水予報,指定河川洪水予報,VXKO(ii=50-89),GZIP,15,300,※①,カセンコウズイ1、フケンコウズイii (ii=01-20)
29
+ 17,気象,予報・予測,土砂災害警戒情報,土砂災害警戒情報,VXWW50,GZIP,15,30,※①,ドシヤケイカイ1、VXWW40
30
+ 18,気象,予報・予測,記録的短時間大雨情報,記録的短時間大雨情報,VPOA50,GZIP,5,15,※①,キロクアメ1
31
+ 19,気象,予報・予測,竜巻注意情報,竜巻注意情報,VPHW50,GZIP,5,10,※①,タツマキジヨウホウ1
32
+ 19,気象,予報・予測,竜巻注意情報,竜巻注意情報(目撃情報付き),VPHW51,,5,10,,
33
+ 20,気象,予報・予測,全般気象情報,全般気象情報,VPZJ50,GZIP,3,6,※②,ゼンコクジヨウホウ1
34
+ 21,気象,予報・予測,地方気象情報,地方気象情報,VPCJ50,GZIP,3,6,※①,チホウジヨウホウ1
35
+ 22,気象,予報・予測,府県気象情報,府県気象情報,VPFJ50,GZIP,3,6,※①,フケンジヨウホウ1
36
+ 23,気象,予報・予測,天気概況,府県天気概況,VPFG50,GZIP,3,6,※①,フケンガイキヨウ1
37
+ 24,気象,予報・予測,府県天気予報,地域時系列予報,府県天気予報,VPFD50,GZIP,40,100,※①令和3年度末までに廃止予定,ヨホウ1、VPFD40/KYYY50
38
+ 24,気象,予報・予測,府県天気予報,地域時系列予報,府県天気予報(R1),VPFD51,GZIP,40,100,※①,
39
+ 27,気象,予報・予測,府県週間天気予報,府県週間天気予報,VPFW50,GZIP,20,60,※①,シユウカンヨホウ1,フケンシユウカン1,シユウカンシンライド1,VPFW40,VPFW41,VPFW42
40
+ 28,気象,予報・予測,スモッグ気象情報,スモッグ気象情報,VPSG50,GZIP,3,6,※①,オセンジヨウホウ1
41
+ 29,気象/地球環境・気候,予報・予測,全般気象情報(社会的に影響の大きい天候に関する情報),全般天候情報,VPZI50,GZIP,15,20,※②,ゼンパンテンコウ1
42
+ 30,気象/地球環境・気候,予報・予測,地方気象情報(社会的に影響の大きい天候に関する情報),地方天候情報,VPCI50,GZIP,15,30,※①,チホウテンコウ1
43
+ 32,地震・津波,観測・解析,震度速報,震度速報,VXSE51,GZIP,4,50,※②,シンドソクホウ3
44
+ 33,地震・津波,観測・解析,地震情報(震源に関する情報),震源に関する情報,VXSE52,GZIP,3,4,※②,シンゲンソクホウ1,11
45
+ 34,地震・津波,観測・解析,地震情報(顕著な地震の震源要素更新のお知らせ),顕著な地震の震源要素更新のお知らせ,VXSE61,GZIP,10,"1,000",※②,ゼンコクサイスモ1
46
+ 34,地震・津波,観測・解析,地震情報(地震回数に関する情報),地震回数に関する情報,VXSE60,GZIP,10,"1,000",※②,ゼンコクサイスモ1
47
+ 34,地震・津波,観測・解析,地震情報(地震の活動状況等に関する情報),地震の活動状況等に関する情報,VXSE56,GZIP,10,"1,000",※②,ゼンコクサイスモ1
48
+ 35,地震・津波,観測・解析,地震情報(震源・震度に関する情報),震源・震度に関する情報,VXSE53,GZIP,10,"1,000",※②,ゼンコクサイスモ11,エンチサイスモ1,ゼンコクサイスモ13,チイキチテンシンド13,エンチサイスモ3
49
+ 36,地震・津波,予報・予測,緊急地震速報(予報),緊急地震速報(予報),VXSE44,GZIP,15,100,※②,ナウキヤスト3,ナウキヤスト4
50
+ 37,地震・津波,予報・予測,緊急地震速報(警報),緊急地震速報(警報),VXSE43,GZIP,15,100,※②,キンキユウジシン3,キンキユウジシン4
51
+ 38,地震・津波,観測・解析,津波情報,津波情報a,VTSE51,GZIP,25,200,※②,ツナミジヨウホウ11,ツナミジヨウホウ13
52
+ 39,地震・津波,予報・予測,津波警報・注意報・予報,津波警報・注意報・予報a,VTSE41,GZIP,15,50,※②,ツナミヨホウ11,ツナミヨホウ16,ツナミジヨウホウ11,ツナミヨホウ13
53
+ 42,地震・津波,調査・解説・その他,地震・津波に関するお知らせ,地震・津波に関するお知らせ,VZSE40,GZIP,4,15,※②,サイスモオシラセ1
54
+ 42,火山,調査・解説・その他,火山に関するお知らせ,火山に関するお知らせ,VZVO40,GZIP,4,15,※②,サイスモオシラセ1
55
+ 43,火山,観測・解析,噴火に関する火山観測報,噴火に関する火山観測報,VFVO52,GZIP,4,10,※②,カザンゲンシヨウ1
56
+ 44,火山,観測・解析/調査・解説・その他,火山の状況に関する解説情報,火山の状況に関する解説情報,VFVO51,GZIP,20,80,※②,カザンカイセツ1
57
+ 45,火山,予報・予測,噴火警報・予報,噴火警報・予報,VFVO50,GZIP,8,300,※②,カザンジヨウホウ1
58
+ 46,火山,予報・予測,火山現象に関する海上警報・海上予報,火山現象に関する海上警報・海上予報,VFSVii(ii=50-61),GZIP,5,10,※②,チホウウミカザンii (ii=01-12)
59
+ 48,海洋,観測・解析,全般潮位情報,全般潮位情報,VMCJ50,GZIP,4,6,※②,ゼンパンチヨウイ1
60
+ 49,海洋,観測・解析,地方潮位情報,地方潮位情報,VMCJ51,GZIP,4,6,※①,チホウチヨウイ1
61
+ 50,海洋,観測・解析,府県潮位情報,府県潮位情報,VMCJ52,GZIP,4,6,※①,フケンチヨウイ1
62
+ 51,地球環境・気候,予報・予測,全般季節予報,全般1か月予報,全般3か月予報,全般暖・寒候期予報,VPZK50,GZIP,20,50,※②,キセツヨホウ1
63
+ 52,地球環境・気候,予報・予測,地方季節予報,地方1か月予報,地方3か月予報,地方暖・寒候期予報,VPCK50,GZIP,15,25,※①,チホウキセツヨホウ1
64
+ 54,地震・津波,調査・解説・その他,緊急地震速報の配信テスト電文,緊急地震速報配信テスト,VXSE42,GZIP,1,3,※②,ナウキヤストテスト1,ナウキヤストテスト91
65
+ 55,気象,予報・予測,全般スモッグ気象情報,全般スモッグ気象情報,VPZS50,GZIP,3,6,※②,ゼンパンスモツグ1
66
+ 57,気象,予報・予測,熱中症警戒アラート,熱中症警戒アラート,VPFT50,GZIP,2,5,※①,新設(コウオンジヨウホウ1)
67
+ 58,気象,予報・予測/観測・解析,地上実況図,地上実況図,VZSA50,GZIP,150,300,※②,なし
68
+ 59,気象,予報・予測/観測・解析,地上24時間予想図,地上24時間予想図,VZSF50,GZIP,150,300,※②,なし
69
+ 60,気象,予報・予測/観測・解析,地上48時間予想図,地上48時間予想図,VZSF51,GZIP,150,300,※②,なし
70
+ 61,地震・津波,観測・解析,沖合の津波観測に関する情報,沖合の津波観測に関する情報,VTSE52,GZIP,25,200,※②,新設(オキアイツナミ11)、新設(オキアイツナミ13)
71
+ 62,気象,予報・予測,気象特別警報報知,気象特別警報報知,VPNO50,GZIP,20,100,※①,新設(トクケイホウチ1,トクケイトクホウチ1)
72
+ 63,気象,予報・予測/観測・解析,アジア太平洋地上実況図,アジア太平洋地上実況図,VZSA60,GZIP,350,550,※②,なし
73
+ 64,気象,予報・予測/観測・解析,アジア太平洋海上悪天24時間予想図,アジア太平洋海上悪天24時間予想図,VZSF60,GZIP,350,550,※②,なし
74
+ 65,気象,予報・予測/観測・解析,アジア太平洋海上悪天48時間予想図,アジア太平洋海上悪天48時間予想図,VZSF61,GZIP,350,550,※②,なし
75
+ 66,火山,予報・予測,降灰予報,降灰予報(定時),VFVO53,GZIP,300,"3,000",※②,なし(ファイルで提供中)
76
+ 66,火山,予報・予測,降灰予報,降灰予報(速報),VFVO54,GZIP,300,"3,000",※②,なし(ファイルで提供中)
77
+ 66,火山,予報・予測,降灰予報,降灰予報(詳細),VFVO55,GZIP,300,"3,000",※②,なし(ファイルで提供中)
78
+ 67,火山,観測・解析,噴火速報,噴火速報,VFVO56,GZIP,3,15,※②,なし
79
+ 68,気象,予報・予測,警報級の可能性(明日まで),警報級の可能性(明日まで),VPFD60,GZIP,30,60,※①,なし
80
+ 69,気象,予報・予測,警報級の可能性(明後日以降),警報級の可能性(明後日以降),VPFW60,GZIP,5,15,※①,なし
81
+ 70,地球環境・気候,予報・予測,全般季節予報(2週間気温予報),全般季節予報(2週間気温予報),VPZK70,GZIP,3,6,※②,なし
82
+ 71,地球環境・気候,予報・予測,地方季節予報(2週間気温予報),地方季節予報(2週間気温予報),VPCK70,GZIP,700,"1,000",※②,なし
83
+ 72,地球環境・気候,予報・予測,早期天候情報,早期天候情報,VPAW51,GZIP,10,20,※①,なし
84
+ 73,気象,予報・予測,大雨危険度通知,大雨危険度通知,VPRN50,GZIP,"4,000","4,000",※①,なし
85
+ 74,地震・津波,観測・解析/調査・解説・その他,南海トラフ地震臨時情報,南海トラフ地震臨時情報,VYSE50,GZIP,3,10,※②,なし
86
+ 75,地震・津波,観測・解析/調査・解説・その他,南海トラフ地震関連解説情報,南海トラフ地震関連解説情報,VYSE51,GZIP,3,10,※②,なし
87
+ 75,地震・津波,観測・解析/調査・解説・その他,南海トラフ地震関連解説情報,南海トラフ地震関連解説情報,VYSE52,GZIP,3,10,※②,なし
88
+ 76,気象,観測・解析/予報・予測,台風の暴風域に入る確率,台風の暴風域に入る確率,VPTAii(ii=50-55),GZIP,"2,600","2,600",,FXJPii(ii=61-72)
89
+ 77,地震・津波,予報・予測,緊急地震速報(地震動予報)(新形式),緊急地震速報(地震動予報),VXSE45,GZIP,15,100,※②,なし
90
+ 78,地震・津波,観測・解析,長周期地震動に関する観測情報,長周期地震動に関する観測情報,VXSE62,GZIP,20,"2,000",※②,なし
91
+ 79,火山,観測・解析/予報・予測,推定噴煙流向報,推定噴煙流向報,VFVO60,GZIP,30,60,※②,なし
@@ -0,0 +1,48 @@
1
+ require "net/http"
2
+
3
+ class JMAFeed::Api
4
+ def initialize
5
+ end
6
+
7
+ def get_feed_regular(if_modified_since: nil, &block)
8
+ res = execute(:get, "https://www.data.jma.go.jp/developer/xml/feed/regular.xml", headers: {
9
+ "If-Modified-Since" => if_modified_since ?
10
+ if_modified_since.httpdate :
11
+ nil
12
+ }, &block)
13
+ JMAFeed::Result.new(res)
14
+ end
15
+
16
+ def get_feed_extra(if_modified_since: nil, &block)
17
+ res = execute(:get, "https://www.data.jma.go.jp/developer/xml/feed/extra.xml", headers: {
18
+ "If-Modified-Since" => if_modified_since ?
19
+ if_modified_since.httpdate :
20
+ nil
21
+ }, &block)
22
+ JMAFeed::Result.new(res)
23
+ end
24
+
25
+ def execute(verb, uri, query: nil, body: nil, headers: {})
26
+ uri = uri.is_a?(URI::HTTP) ? uri : URI.parse(uri)
27
+ request = build_request(verb, uri, query: query, body: body)
28
+ headers.each {|k,v| request[k] = v}
29
+ res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
30
+ yield(request, http) if block_given?
31
+ # http.read_timeout = 30 # sec
32
+ http.request(request)
33
+ end
34
+ end
35
+
36
+ def build_request(verb, uri, query: nil, body: nil, headers: {})
37
+ if query
38
+ uri.query = URI.encode_www_form(query)
39
+ end
40
+ request = "Net::HTTP::#{verb.to_s.camelize}".constantize.new(uri)
41
+
42
+ if body
43
+ request.body = body
44
+ end
45
+
46
+ request
47
+ end
48
+ end
@@ -0,0 +1,176 @@
1
+ class JMAFeed::Alert < Struct.new(:code, :name, :risk_level, :cluster, keyword_init: true)
2
+ # 気象警報・注意(H27)_解説資料.pdf > 別表1
3
+ # https://www.jma.go.jp/jma/kishou/know/bosai/warning_kind.html
4
+ LIST = {
5
+ "00" => {
6
+ name: "解除",
7
+ risk_level: :level5,
8
+ cluster: :clear,
9
+ },
10
+ "02" => {
11
+ name: "暴風雪警報",
12
+ risk_level: :level3,
13
+ cluster: :snowstorm,
14
+ },
15
+ "03" => {
16
+ name: "大雨警報",
17
+ risk_level: :level3,
18
+ cluster: :heavy_rain,
19
+ },
20
+ "04" => {
21
+ name: "洪水警報",
22
+ risk_level: :level3,
23
+ cluster: :flood,
24
+ },
25
+ "05" => {
26
+ name: "暴風警報",
27
+ risk_level: :level3,
28
+ cluster: :storm,
29
+ },
30
+ "06" => {
31
+ name: "大雪警報",
32
+ risk_level: :level3,
33
+ cluster: :heavy_snow,
34
+ },
35
+ "07" => {
36
+ name: "波浪警報",
37
+ risk_level: :level3,
38
+ cluster: :high_wave,
39
+ },
40
+ "08" => {
41
+ name: "高潮警報",
42
+ risk_level: :level3,
43
+ cluster: :storm_surge,
44
+ },
45
+ "10" => {
46
+ name: "大雨注意報",
47
+ risk_level: :level2,
48
+ cluster: :heavy_rain,
49
+ },
50
+ "12" => {
51
+ name: "大雪注意報",
52
+ risk_level: :level2,
53
+ cluster: :heavy_snow,
54
+ },
55
+ "13" => {
56
+ name: "風雪注意報",
57
+ risk_level: :level2,
58
+ cluster: :snowstorm,
59
+ },
60
+ "14" => {
61
+ name: "雷注意報",
62
+ risk_level: :level2,
63
+ cluster: :thunderstorm,
64
+ },
65
+ "15" => {
66
+ name: "強風注意報",
67
+ risk_level: :level2,
68
+ cluster: :storm,
69
+ },
70
+ "16" => {
71
+ name: "波浪注意報",
72
+ risk_level: :level2,
73
+ cluster: :high_wave,
74
+ },
75
+ "17" => {
76
+ name: "融雪注意報",
77
+ risk_level: :level2,
78
+ cluster: :snow_melting,
79
+ },
80
+ "18" => {
81
+ name: "洪水注意報",
82
+ risk_level: :level2,
83
+ cluster: :flood,
84
+ },
85
+ "19" => {
86
+ name: "高潮注意報",
87
+ risk_level: :level2,
88
+ cluster: :storm_surge,
89
+ },
90
+ "20" => {
91
+ name: "濃霧注意報",
92
+ risk_level: :level2,
93
+ cluster: :dense_fog,
94
+ },
95
+ "21" => {
96
+ name: "乾燥注意報",
97
+ risk_level: :level2,
98
+ cluster: :dry_air,
99
+ },
100
+
101
+ "22" => {
102
+ name: "なだれ注意報",
103
+ risk_level: :level2,
104
+ cluster: :avalanche,
105
+ },
106
+ "23" => {
107
+ name: "低温注意報",
108
+ risk_level: :level2,
109
+ cluster: :low_temperature,
110
+ },
111
+ "24" => {
112
+ name: "霜注意報",
113
+ risk_level: :level2,
114
+ cluster: :frost,
115
+ },
116
+ "25" => {
117
+ name: "着氷注意報",
118
+ risk_level: :level2,
119
+ cluster: :ice_accretion,
120
+ },
121
+ "26" => {
122
+ name: "着雪注意報",
123
+ risk_level: :level2,
124
+ cluster: :snow_accretion,
125
+ },
126
+ "27" => {
127
+ name: "その他の注意",
128
+ risk_level: :level2,
129
+ cluster: :other,
130
+ },
131
+
132
+ "32" => {
133
+ name: "暴風雪特別警報",
134
+ risk_level: :level5,
135
+ cluster: :snowstorm,
136
+ },
137
+ "33" => {
138
+ name: "大雨特別警報",
139
+ risk_level: :level5,
140
+ cluster: :heavy_rain,
141
+ },
142
+ "35" => {
143
+ name: "暴風特別警報",
144
+ risk_level: :level5,
145
+ cluster: :storm,
146
+ },
147
+ "36" => {
148
+ name: "大雪特別警報",
149
+ risk_level: :level5,
150
+ cluster: :heavy_snow,
151
+ },
152
+ "37" => {
153
+ name: "波浪特別警報",
154
+ risk_level: :level5,
155
+ cluster: :high_wave,
156
+ },
157
+ "38" => {
158
+ name: "高潮特別警報",
159
+ risk_level: :level5,
160
+ cluster: :storm_surge,
161
+ },
162
+ }
163
+
164
+ # def self.clusters
165
+ # LIST.map{|k,v| v[:cluster]}.uniq
166
+ # end
167
+
168
+ def self.clusters
169
+ # LIST.map{|k,v| v[:cluster]}.uniq
170
+ all.group_by(&:cluster)
171
+ end
172
+
173
+ def self.all
174
+ @all ||= LIST.map{|k,v| new(v.merge(code: k.to_s))}
175
+ end
176
+ end
@@ -0,0 +1,44 @@
1
+ class JMAFeed::RiskLevel
2
+ # Ex: id=:level0
3
+ # Ex: code='00'
4
+
5
+ # 大雨危険度通知_解説資料.pdf > 別表3 「危険度分布の危険度」コード表
6
+ LIST = {
7
+ level0: ['00'], # 今後の情報等に留意
8
+ level1: ['11', '13'], # 警戒レベル1(心構えを高める), 早期注意情報
9
+ level2: ['21', '22', '23', '24'], # 警戒レベル2(避難行動の確認)相当, 注意報
10
+ level3: ['31', '32', '33', '34'], # 警戒レベル3(高齢者等避難)相当, 警報
11
+ level4: ['41', '42', '43', '44'], # 警戒レベル4(避難)相当, 危険
12
+ level5: ['51', '52', '53', '54'], # 警戒レベル5(災害切迫)相当, 災害発生のおそれ
13
+ }
14
+
15
+ def self.all
16
+ @all ||= LIST.map{|k,v| new(k, v)}
17
+ end
18
+
19
+ def self.find(id)
20
+ all.find{|l| l.id == id.to_sym}
21
+ end
22
+
23
+ def self.greater_than(level)
24
+ level = (level.is_a?(Symbol) or level.is_a?(String)) ?
25
+ find(level) :
26
+ level
27
+ all.select{|l| l.intensity >= level.intensity}
28
+ end
29
+
30
+ attr_reader :id, :codes
31
+ def initialize(id, codes)
32
+ @id = id.to_sym
33
+ @codes = codes
34
+ end
35
+
36
+ def intensity
37
+ @intensity ||= id.to_s.sub('level', '').to_i
38
+ end
39
+
40
+ def risk_include?(code)
41
+ risk_codes = self.class.greater_than(self).map(&:codes).flatten
42
+ risk_codes.include?(code)
43
+ end
44
+ end
@@ -0,0 +1,92 @@
1
+ class JMAFeed::Report < Struct.new(
2
+ :name, :title, :kind, :category, :code_represented, :codes, keyword_init: true
3
+ )
4
+ CSV_ROW_SEP = "\r\n"
5
+ NUM_HEADER_ROWS = 3
6
+ HEADERS = %i(
7
+ number
8
+ category
9
+ kind
10
+ name
11
+ title
12
+ code
13
+ compression_format
14
+ size_average
15
+ size_max
16
+ memo
17
+ code_old
18
+ )
19
+
20
+ class << self
21
+ def load_csv(version: "20240216")
22
+ path = File.join(File.dirname(__FILE__), "../../data/jmaxml_#{version}_format_v1_3_hyo1.csv")
23
+ File.open(path) do |f|
24
+ csv = CSV.new(f, headers: HEADERS, row_sep: CSV_ROW_SEP)
25
+ yield(csv)
26
+ end
27
+ end
28
+
29
+ def load(**args)
30
+ load_csv(**args) do |csv|
31
+ csv.drop(NUM_HEADER_ROWS).map do |row|
32
+ build_by_csv_row(row)
33
+ end
34
+ end
35
+ end
36
+
37
+ def build_by_csv_row(row)
38
+ codes = build_codes(row[:code])
39
+ code_represented = build_code_represented(row[:code])
40
+ new(
41
+ name: row[:name],
42
+ title: row[:title],
43
+ kind: row[:kind].split('/'),
44
+ category: row[:category],
45
+ code_represented: code_represented,
46
+ code: codes,
47
+ )
48
+ end
49
+
50
+ def parse_raw_code(raw_code)
51
+ raw_code.match(/(.+)\(([^\)]+)\)/)
52
+ end
53
+
54
+ def build_code_represented(raw_code)
55
+ if m = parse_raw_code(raw_code)
56
+ _, main, cond = m.to_a
57
+ main
58
+ else
59
+ raw_code
60
+ end
61
+ end
62
+
63
+ # build_code('VGSK50')
64
+ # => 'VGSK50'
65
+ # build_code('VPTWii(ii=40-45)')
66
+ # => ["VPTW40", "VPTW41", "VPTW42", "VPTW43", "VPTW44", "VPTW45"]
67
+ # build_code('VXKO(ii=50-89)')
68
+ # => ["VXKO50", "VXKO51", "VXKO52", "VXKO53", "VXKO54", "VXKO55", ...]
69
+ def build_codes(raw_code)
70
+ if m = parse_raw_code(raw_code)
71
+ _, main, cond = m.to_a
72
+ cursor, range = cond.split('=')
73
+ range_first, range_last = range.split('-').map(&:to_i)
74
+ (range_first..range_last).map do |i|
75
+ main.match?(cursor) ?
76
+ main.sub(cursor, i.to_s) :
77
+ main + i.to_s
78
+ end
79
+ else
80
+ [raw_code]
81
+ end
82
+ end
83
+ end
84
+
85
+ def has_code?(c)
86
+ codes.include?(c)
87
+ end
88
+
89
+ def has_kind?(k)
90
+ Array(kind).include?(k)
91
+ end
92
+ end
@@ -0,0 +1,7 @@
1
+ # jmx_ib
2
+ class JMAFeed::JMX::Area < Giri::BaseNode
3
+ xml_attribute :code_type, with_name: :lower_camelcase
4
+
5
+ text_node :name
6
+ text_node :code
7
+ end
@@ -0,0 +1,7 @@
1
+ class JMAFeed::JMX::Discharge < Giri::TextNodeBigDecimal
2
+ xml_attribute :type
3
+ xml_attribute :unit
4
+ xml_attribute :ref_id, with_name: "refID"
5
+ xml_attribute :condition
6
+ xml_attribute :description
7
+ end
@@ -0,0 +1,7 @@
1
+ class JMAFeed::JMX::Precipitation < Giri::TextNodeInteger
2
+ xml_attribute :type
3
+ xml_attribute :unit
4
+ xml_attribute :ref_id, with_name: "refID"
5
+ xml_attribute :condition
6
+ xml_attribute :description
7
+ end
@@ -0,0 +1,7 @@
1
+ # jmx_mete
2
+ class JMAFeed::JMX::Significancy < Giri::BaseNode
3
+ xml_attribute :type
4
+ text_node :name
5
+ text_node :code
6
+ text_node :condition
7
+ end
@@ -0,0 +1,7 @@
1
+ class JMAFeed::JMX::WaterLevel < Giri::TextNodeBigDecimal
2
+ xml_attribute :type
3
+ xml_attribute :unit
4
+ xml_attribute :ref_id, with_name: "refID"
5
+ xml_attribute :condition
6
+ xml_attribute :description
7
+ end
@@ -0,0 +1,41 @@
1
+ # 竜巻注意情報
2
+ # https://xml.kishou.go.jp/tec_material.html
3
+ # 電文毎の解説資料 > 解説資料セットzip > 竜巻注意情報_解説資料.pdf
4
+ #
5
+ # STRUCTURE:
6
+ # <Warning type="竜巻注意情報(発表細分)">...</Warning>
7
+ # <Warning type="竜巻注意情報(一次細分区域等)">...</Warning>
8
+ # <Warning type="竜巻注意情報(市町村等をまとめた地域等)">...</Warning>
9
+ # <Warning type="竜巻注意情報(市町村等)">...</Warning>
10
+ #
11
+ class JMAFeed::VPHW50 < JMAFeed::ReportEntry
12
+ xml_node :body do
13
+ xml_node_collection :warning do
14
+ xml_attribute :type
15
+ xml_node_collection :item do
16
+ xml_node_collection :kind do
17
+ text_node :name
18
+ text_node :code
19
+ text_node :status
20
+ end
21
+ xml_node :area, type: "JMAFeed::JMX::Area"
22
+ end
23
+ end
24
+
25
+ def warning_district_report
26
+ warning.find{|w| w.type == "竜巻注意情報(発表細分)"}
27
+ end
28
+
29
+ def warning_district_1st
30
+ warning.find{|w| w.type == "竜巻注意情報(一次細分区域等)"}
31
+ end
32
+
33
+ def warning_district_aggregated
34
+ warning.find{|w| w.type == "竜巻注意情報(市町村等をまとめた地域等)"}
35
+ end
36
+
37
+ def warning_district_2nd
38
+ warning.find{|w| w.type == "竜巻注意情報(市町村等)"}
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,101 @@
1
+ # 大雨危険度通知
2
+ # https://xml.kishou.go.jp/tec_material.html
3
+ # 電文毎の解説資料 > 解説資料セットzip > 大雨危険度通知_解説資料.pdf
4
+ #
5
+ # STRUCTURE:
6
+ # <MeteorologicalInfos type="区域予報"> # 府県予報区
7
+ # <MeteorologicalInfo>...</MeteorologicalInfo> # 危険度
8
+ # <MeteorologicalInfo>...</MeteorologicalInfo> # 危険度分布
9
+ # </MeteorologicalInfos>
10
+ # <MeteorologicalInfos type="区域予報"> # 一次細分区域
11
+ # <MeteorologicalInfo>...</MeteorologicalInfo> # 危険度
12
+ # <MeteorologicalInfo>...</MeteorologicalInfo> # 危険度分布
13
+ # </MeteorologicalInfos>
14
+ # <MeteorologicalInfos type="区域予報"> # 市町村などをまとめた地域
15
+ # <MeteorologicalInfo>...</MeteorologicalInfo> # 危険度
16
+ # <MeteorologicalInfo>...</MeteorologicalInfo> # 危険度分布
17
+ # </MeteorologicalInfos>
18
+ # <MeteorologicalInfos type="区域予報"> # 二時細分区域およびさらに詳細な区域
19
+ # <MeteorologicalInfo>...</MeteorologicalInfo> # 危険度
20
+ # <MeteorologicalInfo>...</MeteorologicalInfo> # 危険度分布
21
+ # </MeteorologicalInfos>
22
+ #
23
+ # 危険度: 注意報・警報、土砂災害警戒情報、指定河川洪水予報、早期注意情報、危険度分布の発表状況を考慮した対象地域内の危険度
24
+ # 危険度分布: 危険度分布を指標とした危険度 https://www.jma.go.jp/jma/kishou/know/bosai/riskmap.html
25
+ class JMAFeed::VPRN50 < JMAFeed::ReportEntry
26
+
27
+ # AREA_TYPES = {
28
+ # district_forecast: "府県予報区",
29
+ # district_1st: "一次細分区域",
30
+ # district_aggregated: "市町村等をまとめた地域",
31
+ # district_2nd: "二次細分区域及びさらに詳細な区域",
32
+ # }
33
+
34
+ # RISK_TYPES = {
35
+ # heavy_rain: "大雨危険度",
36
+ # landslide: "土砂災害危険度",
37
+ # submerge: "浸水害危険度",
38
+ # flood: "洪水害危険度",
39
+ # }
40
+
41
+ xml_node :body do
42
+ xml_node_collection :meteorological_infos do
43
+ xml_node_collection :meteorological_info do
44
+ date_time_node :date_time
45
+ xml_node_collection :item do
46
+ xml_node :kind do
47
+ xml_node :property do
48
+ text_node :type
49
+ xml_node :significancy_part do
50
+ xml_node :base do
51
+ xml_node_collection :significancy, type: "JMAFeed::JMX::Significancy"
52
+ end
53
+ end
54
+ end
55
+ end
56
+ xml_node :area, type: "JMAFeed::JMX::Area"
57
+
58
+ def type
59
+ kind&.property&.type
60
+ end
61
+
62
+ def significancies
63
+ kind&.property&.significancy_part&.base&.significancy || []
64
+ end
65
+
66
+ def heavy_rain
67
+ significancies.find{|s| s.type == "大雨危険度"}
68
+ end
69
+
70
+ def landslide
71
+ significancies.find{|s| s.type == "土砂災害危険度"}
72
+ end
73
+
74
+ def submerge
75
+ significancies.find{|s| s.type == "浸水害危険度"}
76
+ end
77
+
78
+ def flood
79
+ significancies.find{|s| s.type == "洪水害危険度"}
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ def info_district_forecast
86
+ meteorological_infos[0].meteorological_info[0]
87
+ end
88
+
89
+ def info_district_1st
90
+ meteorological_infos[1].meteorological_info[0]
91
+ end
92
+
93
+ def info_district_aggregated
94
+ meteorological_infos[2].meteorological_info[0]
95
+ end
96
+
97
+ def info_district_2nd
98
+ meteorological_infos[3].meteorological_info[0]
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,109 @@
1
+ # 台風の暴風域に入る確率
2
+ # https://xml.kishou.go.jp/tec_material.html
3
+ # 電文毎の解説資料 > 解説資料セットzip > 台風の暴風域に入る確率_解説資料.pdf
4
+ #
5
+ # STRUCTURE:
6
+ # <MeteorologicalInfo type="台風呼称">...</MeteorologicalInfo>
7
+ # <MeteorologicalInfo type="台風の暴風域に入る確率(1日積算)">...</MeteorologicalInfo>
8
+ # <MeteorologicalInfo type="台風の暴風域に入る確率(2日積算)">...</MeteorologicalInfo>
9
+ # <MeteorologicalInfo type="台風の暴風域に入る確率(3日積算)">...</MeteorologicalInfo>
10
+ # <MeteorologicalInfo type="台風の暴風域に入る確率(4日積算)">...</MeteorologicalInfo>
11
+ # <MeteorologicalInfo type="台風の暴風域に入る確率(5日積算)">...</MeteorologicalInfo>
12
+ # <TimeSeriesInfo>...</TimeSeriesInfo>
13
+ #
14
+ class JMAFeed::VPTAii < JMAFeed::ReportEntry
15
+ xml_node :body do
16
+ xml_node :meteorological_infos do
17
+ xml_attribute :type
18
+ xml_node_collection :meteorological_info do
19
+ xml_attribute :type
20
+ date_time_node :date_time
21
+ duration_node :duration
22
+ text_node :name
23
+ xml_node_collection :item do
24
+ xml_node :kind do
25
+ xml_node :property do
26
+ text_node :type
27
+ xml_node :typhoon_name_part do
28
+ text_node :name
29
+ text_node :name_kana
30
+ text_node :number
31
+ end
32
+ xml_node :fifty_kt_wind_probability_part do
33
+ integer_node :fifty_kt_wind_probability do
34
+ xml_attribute :unit
35
+ end
36
+ end
37
+ end
38
+ end
39
+ xml_node :area, type: "JMAFeed::JMX::Area"
40
+ end
41
+ end
42
+
43
+ xml_node :time_series_info do
44
+ xml_node :time_defines do
45
+ xml_node_collection :time_define do
46
+ xml_attribute :time_id, with_name: :lower_camelcase
47
+ date_time_node :date_time
48
+ duration_node :duration
49
+ # text_node :name
50
+ end
51
+ end
52
+ xml_node_collection :item do
53
+ xml_node :kind do
54
+ xml_node :property do
55
+ text_node :type
56
+ xml_node :fifty_kt_wind_probability_part do
57
+ integer_node :fifty_kt_wind_probability, collection: true do
58
+ xml_attribute :unit
59
+ xml_attribute :ref_id, with_name: "refID"
60
+
61
+ def time_define
62
+ @time_define ||= parent.parent.parent.parent.parent.time_defines.time_define.find{|d| d.time_id == ref_id}
63
+ end
64
+
65
+ def date_time
66
+ time_define&.date_time
67
+ end
68
+
69
+ def duration
70
+ time_define&.duration
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ xml_node :area, type: "JMAFeed::JMX::Area"
77
+
78
+ def data
79
+ kind.property.fifty_kt_wind_probability_part.fifty_kt_wind_probability
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ def info_typhoon
86
+ meteorological_infos.meteorological_info.find{|i| i.type == "台風呼称"}
87
+ end
88
+
89
+ def info_probability_within_1day
90
+ meteorological_infos.meteorological_info.find{|i| i.type == "台風の暴風域に入る確率(1日積算)"}
91
+ end
92
+
93
+ def info_probability_within_2days
94
+ meteorological_infos.meteorological_info.find{|i| i.type == "台風の暴風域に入る確率(2日積算)"}
95
+ end
96
+
97
+ def info_probability_within_3days
98
+ meteorological_infos.meteorological_info.find{|i| i.type == "台風の暴風域に入る確率(3日積算)"}
99
+ end
100
+
101
+ def info_probability_within_4days
102
+ meteorological_infos.meteorological_info.find{|i| i.type == "台風の暴風域に入る確率(4日積算)"}
103
+ end
104
+
105
+ def info_probability_within_5days
106
+ meteorological_infos.meteorological_info.find{|i| i.type == "台風の暴風域に入る確率(5日積算)"}
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,77 @@
1
+ # 気象警報・注意報(H27)
2
+ # https://xml.kishou.go.jp/tec_material.html
3
+ # 電文毎の解説資料 > 解説資料セットzip > 気象警報・注意報(H27)_解説資料.pdf
4
+ #
5
+ # STRUCTURE:
6
+ # <Warning type="気象警報・注意報(府県予報区等)">...</Warning>
7
+ # <Warning type="気象警報・注意報(一次細分区域等)">...</Warning>
8
+ # <Warning type="気象警報・注意報(市町村等をまとめた地域等)">...</Warning>
9
+ # <Warning type="気象警報・注意報(市町村等)">...</Warning>
10
+ # <MeteorologicalInfos type="量的予想時系列(市町村等)">
11
+ # </MeteorologicalInfos>
12
+ #
13
+ class JMAFeed::VPWW54 < JMAFeed::ReportEntry
14
+ xml_node :body do
15
+ xml_node_collection :warning do
16
+ xml_attribute :type
17
+ xml_node_collection :item do
18
+ xml_node_collection :kind do
19
+ text_node :name
20
+ text_node :code
21
+ text_node :status
22
+ text_node :condition
23
+ xml_node :attention do
24
+ text_node :note, collection: true
25
+ end
26
+ xml_node :addition do
27
+ text_node :note, collection: true
28
+ end
29
+
30
+ def alert
31
+ @alert ||= JMAFeed::Alert.all.find{|a| a.code == code}
32
+ end
33
+ end
34
+ text_node :change_status
35
+ xml_node :area, type: "JMAFeed::JMX::Area"
36
+
37
+ JMAFeed::Alert.clusters.each do |cluster,alerts|
38
+ define_method cluster do
39
+ kind.find{|k| alerts.map(&:code).include?(k.code)}
40
+ end
41
+ end
42
+ end
43
+ end
44
+ xml_node :meteorological_infos do
45
+ xml_attribute :type
46
+ xml_node :time_series_info do
47
+ xml_node :time_defines do
48
+ xml_node_collection :time_define do
49
+ xml_attribute :time_id, with_name: :lower_camelcase
50
+ date_time_node :date_time
51
+ duration_node :duration
52
+ text_node :name
53
+ end
54
+ end
55
+ xml_node_collection :item do
56
+ # TODO
57
+ end
58
+ end
59
+ end
60
+
61
+ def warning_district_forecast
62
+ warning[0]
63
+ end
64
+
65
+ def warning_district_1st
66
+ warning[1]
67
+ end
68
+
69
+ def warning_district_aggregated
70
+ warning[2]
71
+ end
72
+
73
+ def warning_district_2nd
74
+ warning[3]
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,176 @@
1
+ # 指定河川洪水予報
2
+ # https://xml.kishou.go.jp/tec_material.html
3
+ # 電文毎の解説資料 > 解説資料セットzip > 指定河川洪水予報_解説資料.pdf
4
+ #
5
+ class JMAFeed::VXKO < JMAFeed::ReportEntry
6
+
7
+ xml_node :head do
8
+ xml_node :headline do
9
+ text_node :text
10
+ xml_node_collection :information do
11
+ xml_attribute :type
12
+ xml_node :item do
13
+ xml_node :kind do
14
+ text_node :name
15
+ text_node :code
16
+ text_node :condition
17
+ end
18
+ xml_node :areas do
19
+ xml_attribute :code_type
20
+ xml_node_collection :area do
21
+ text_node :name
22
+ text_node :code
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def info_river_district
29
+ information.find{|i| i.type == "指定河川洪水予報(予報区域)"}&.item
30
+ end
31
+
32
+ def info_river
33
+ information.find{|i| i.type == "指定河川洪水予報(河川)"}&.item
34
+ end
35
+
36
+ def info_district_forecast
37
+ information.find{|i| i.type == "指定河川洪水予報(府県予報区等)"}&.item
38
+ end
39
+ end
40
+ end
41
+
42
+ xml_node :body do
43
+ text_node :notice
44
+ xml_node :warning do
45
+ xml_attribute :type
46
+ xml_node_collection :item do
47
+ xml_node :kind do
48
+ text_node :name
49
+ text_node :code
50
+ text_node :status
51
+ xml_node :property do
52
+ text_node :type
53
+ text_node :text
54
+ end
55
+ end
56
+ xml_node :areas do
57
+ end
58
+ xml_node :stations do
59
+ end
60
+
61
+ def type
62
+ kind&.property&.type
63
+ end
64
+ end
65
+ end
66
+
67
+ def warning_sentence
68
+ warning.item.select{|i| i.type == "主文"}
69
+ end
70
+
71
+ def warning_inundation_expected
72
+ warning.item.select{|i| i.type == "浸水想定地区"}
73
+ end
74
+
75
+ def warning_inundation_happening
76
+ warning.item.select{|i| i.type == "浸水想定地区(氾濫発生情報)"}
77
+ end
78
+
79
+ xml_node_collection :meteorological_infos do
80
+ xml_attribute :type
81
+ xml_node :meteorological_info do
82
+ date_time_node :date_time
83
+ xml_node :item do
84
+ xml_node :kind do
85
+ text_node :name
86
+ xml_node :property do
87
+ text_node :type
88
+ text_node :text
89
+ end
90
+ end
91
+ xml_node :area, type: "JMAFeed::JMX::Area"
92
+
93
+ def type
94
+ kind&.property&.type
95
+ end
96
+ end
97
+ end
98
+ xml_node :time_series_info do
99
+ xml_node :time_defines do
100
+ xml_node_collection :time_define do
101
+ xml_attribute :time_id
102
+ date_time_node :date_time
103
+ duration_node :duration
104
+ text_node :name
105
+ end
106
+ end
107
+
108
+ xml_node_collection :item do
109
+ xml_node :kind do
110
+ text_node :name
111
+ xml_node :property do
112
+ text_node :type
113
+ xml_node :precipitation_part do
114
+ xml_node_collection :precipitation, type: "JMAFeed::JMX::Precipitation" do
115
+ def time_define_list
116
+ parent.parent.parent.parent.parent.time_defines.time_define
117
+ end
118
+
119
+ def time_define
120
+ time_define_list.find{|d| d.time_id == ref_id}
121
+ end
122
+ end
123
+ end
124
+ xml_node :water_level_part do
125
+ xml_node_collection :water_level, type: "JMAFeed::JMX::WaterLevel"
126
+ end
127
+ xml_node :discharge_part do
128
+ xml_node_collection :discharge, type: "JMAFeed::JMX::Discharge"
129
+ end
130
+ end
131
+ end
132
+ xml_node :area do
133
+ text_node :name
134
+ end
135
+ xml_node :station do
136
+ text_node :name
137
+ text_node :code
138
+ text_node :location
139
+ end
140
+
141
+ def precipitation
142
+ kind&.property&.precipitation_part&.precipitation
143
+ end
144
+
145
+ def water_level
146
+ kind&.property&.water_level_part&.water_level
147
+ end
148
+ end
149
+ end
150
+ end
151
+
152
+ def info_precipitation
153
+ meteorological_infos.find{|i| i.type == "雨量情報"}
154
+ end
155
+
156
+ def info_water_level
157
+ meteorological_infos.find{|i| i.type == "水位・流量情報"}
158
+ end
159
+
160
+ def info_flood
161
+ meteorological_infos.find{|i| i.type == "氾濫水の予報"}
162
+ end
163
+
164
+ def time_series_precipitation
165
+ info_precipitation.time_series_info.item.first
166
+ end
167
+
168
+ def time_series_water_level
169
+ info_water_level.time_series_info.item.first
170
+ end
171
+
172
+ def time_series_flood
173
+ info_flood.time_series_info.item.first
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,40 @@
1
+ require "nokogiri"
2
+ require "giri"
3
+
4
+ class JMAFeed::ReportEntry < Giri::BaseNode
5
+ class << self
6
+ def get(url)
7
+ xml = Net::HTTP.get(URI.parse(url))
8
+ doc = Nokogiri::XML(xml)
9
+ new(doc.root)
10
+ end
11
+ end
12
+
13
+ xml_node :control do
14
+ text_node :title
15
+ date_time_node :date_time
16
+ text_node :status
17
+ text_node :editorial_office
18
+ text_node :publishing_office
19
+ end
20
+ xml_node :head do
21
+ text_node :title
22
+ date_time_node :report_date_time
23
+ date_time_node :target_date_time
24
+ text_node :target_duration
25
+ text_node :info_type
26
+ text_node :info_kind
27
+ text_node :info_kind_version
28
+ end
29
+ end
30
+
31
+ require "jma_feed/report_entry/jmx/area"
32
+ require "jma_feed/report_entry/jmx/significancy"
33
+ require "jma_feed/report_entry/jmx/precipitation"
34
+ require "jma_feed/report_entry/jmx/water_level"
35
+ require "jma_feed/report_entry/jmx/discharge"
36
+ require "jma_feed/report_entry/vprn50"
37
+ require "jma_feed/report_entry/vpww54"
38
+ require "jma_feed/report_entry/vxko"
39
+ require "jma_feed/report_entry/vphw50"
40
+ require "jma_feed/report_entry/vptaii"
@@ -0,0 +1,64 @@
1
+ class JMAFeed::Result
2
+ attr_reader :http_result
3
+
4
+ def initialize(http_result)
5
+ @http_result = http_result
6
+ end
7
+
8
+ def code
9
+ http_result.code
10
+ end
11
+
12
+ def body
13
+ http_result.body
14
+ end
15
+
16
+ def last_modified
17
+ DateTime.parse(http_result["Last-Modified"])
18
+ end
19
+
20
+ def doc
21
+ @doc ||= Nokogiri::XML(body)
22
+ end
23
+
24
+ def namespace
25
+ {atom: doc.root.namespace.href}
26
+ end
27
+
28
+ def text(name)
29
+ doc.xpath("/atom:feed/atom:#{name}", namespace).text
30
+ end
31
+
32
+ def title
33
+ text('title')
34
+ end
35
+
36
+ def subtitle
37
+ text('subtitle')
38
+ end
39
+
40
+ def id
41
+ text('id')
42
+ end
43
+
44
+ def updated
45
+ DateTime.parse(text('updated'))
46
+ end
47
+
48
+ def related
49
+ text('link[@rel="related"]/@href')
50
+ end
51
+
52
+ def entries
53
+ @entries ||= doc.xpath('/atom:feed/atom:entry', namespace).map do |entry|
54
+ JMAFeed::ResultEntry.new(
55
+ title: entry.xpath('atom:title', namespace).text,
56
+ link: entry.xpath('atom:link/@href', namespace).text,
57
+ id: entry.xpath('atom:id', namespace).text,
58
+ updated: entry.xpath('atom:updated', namespace).text,
59
+ author: entry.xpath('atom:author/atom:name', namespace).text,
60
+ content: entry.xpath('atom:content', namespace).text,
61
+ )
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,24 @@
1
+ class JMAFeed::ResultEntry < Struct.new(
2
+ :title, :id, :updated, :author, :link, :content, keyword_init: true
3
+ )
4
+ def identifier
5
+ @identifier ||= id.split('/').last.sub(/\.\w+\z/, '')
6
+ end
7
+
8
+ def identifier_components
9
+ time, number, report_code, report_area_code = identifier.split('_')
10
+ end
11
+
12
+ def report_code
13
+ @report_code ||= identifier_components[2]
14
+ end
15
+
16
+ def report
17
+ return nil if report_code.nil?
18
+ @report ||= JMAFeed::Report.latest.detect{_1.has_code?(report_code)}
19
+ end
20
+
21
+ def report_area_code
22
+ @report_area_code ||= identifier_components[3]
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module JMAFeed
2
+ VERSION = "0.0.2"
3
+ end
data/lib/jma_feed.rb ADDED
@@ -0,0 +1,18 @@
1
+ require "giri"
2
+ # require "active_support/inflector"
3
+
4
+ module JMAFeed
5
+ module JMX
6
+ end
7
+ end
8
+
9
+ require "jma_feed/version"
10
+ require "jma_feed/report"
11
+ require "jma_feed/result_entry"
12
+ require "jma_feed/result"
13
+ require "jma_feed/api"
14
+ require "jma_feed/entity/alert"
15
+ require "jma_feed/entity/risk_level"
16
+
17
+ require "jma_feed/report_entry"
18
+
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jma_feed
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - metheglin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-08-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '13.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '13.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: jma_code
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.0.3
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.0.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: giri
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.0.3
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.0.3
69
+ description: JMA Feed
70
+ email: pigmybank@gmail.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - README.md
76
+ - data/jmaxml_20240216_format_v1_3_hyo1.csv
77
+ - lib/jma_feed.rb
78
+ - lib/jma_feed/api.rb
79
+ - lib/jma_feed/entity/alert.rb
80
+ - lib/jma_feed/entity/risk_level.rb
81
+ - lib/jma_feed/report.rb
82
+ - lib/jma_feed/report_entry.rb
83
+ - lib/jma_feed/report_entry/jmx/area.rb
84
+ - lib/jma_feed/report_entry/jmx/discharge.rb
85
+ - lib/jma_feed/report_entry/jmx/precipitation.rb
86
+ - lib/jma_feed/report_entry/jmx/significancy.rb
87
+ - lib/jma_feed/report_entry/jmx/water_level.rb
88
+ - lib/jma_feed/report_entry/vphw50.rb
89
+ - lib/jma_feed/report_entry/vprn50.rb
90
+ - lib/jma_feed/report_entry/vptaii.rb
91
+ - lib/jma_feed/report_entry/vpww54.rb
92
+ - lib/jma_feed/report_entry/vxko.rb
93
+ - lib/jma_feed/result.rb
94
+ - lib/jma_feed/result_entry.rb
95
+ - lib/jma_feed/version.rb
96
+ homepage: https://rubygems.org/gems/jma_feed
97
+ licenses:
98
+ - MIT
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '2.7'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubygems_version: 3.1.4
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: JMA Feed
119
+ test_files: []