jma_feed 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []