台風接近時、電車が止まるレベルの時に出社しなくて良いように警報や注意報を自動でSlack通知したい

最近台風が来ても、出社しなくて良いよ！無理しないでね！といった、アラートが会社からでなくなってしまいました。

チームごとに方針を決めろとも、特に連絡もないのですが、チームのメンバーが無理に出社したら元も子もないので、

`台風が接近しているときに、数時間かけて出社しなくて良い！安全第一！`

ということをメインにSlackで通知したいと思います。
ただ、何を基準として通知するべきか。

# 電車が止まる基準は何？

https://trafficnews.jp/post/109311

## 風の場合
> JR在来線の場合、瞬間風速20m/s以上で列車の速度制限を行います。そして25m/s以上で運転を見合わせます。新幹線についても20m/s以上で段階的に速度制限、運転見合わせが行われます。
> 私鉄などの場合は、瞬間風速25～30m/s以上で運転見合わせとする会社が多く見られます。

ということなので、

- 瞬間風速20m/s ~ 25m/s 以上

というのがキーワードとしてまずあるようです。

## 雨の場合

> 降雨による速度制限、運転見合わせの基準は風速のようにシンプルではなく、線路の環境やそれまでの経験によって対応が決められます。
> なお降雨量で判断する場合は、1時間あたり40mm以上、継続300mm以上の雨で運転見合わせになるケースが多いようです。もちろん沿線の環境に応じた対応となり、例えば山間部を通る西武秩父線の一部区間では、30mm/hで速度制限、50mm/hまたは継続250mmで運転見合わせとなります。

ケースにはよるようですが、

- 40mm/h 以上
- 継続は300mm以上

# 気象庁のデータでは何を見るか

- 大雨
- 暴風
- 波浪

あたりがメインと思います。沿岸に会社はないので、大雨と暴風だけ注視してみましょう。

## 注意報の種類

https://www.jma.go.jp/jma/kishou/know/bosai/warning_kind.html

これによると、特別警報は数十年に一度規模の特に発表されるようです。

https://www.jma.go.jp/jma/kishou/know/bosai/alertlevel.html

コレを見るに、赤色帯は、自治体が高齢者避難発令レベルとなります。ということは、赤の時点で出社はありえません。
注意報は`避難行動の確認が必要とするレベル`だそうです。
一旦どの程度なのでしょうか？

ページによると、自身の住んでる地域のハザードマップや避難先などは把握しておくように、準備をするレベル、だそうです。少しわかりにくいですね。

## 注意報・警報の基準

https://www.jma.go.jp/jma/kishou/know/kijun/index.html

これによると、都道府県ごとに基準が違うようです。東京を見てみます。
見てみたら、区とか市によって違うらしくて、細分化されてます。なんてこった・・ｗ


世田谷区をとりあえず抜粋してみましょう。pdfだわ・・。

### 注意報
|種類|基準値|
|--|--|
|大雨|表面12mm/h|
|暴風|平均13m/s|

### 警報
|種類|基準値|
|--|--|
|大雨|表面22mm/h|
|暴風|平均25m/s|

この基準を見ると、おそらく`警報が出たら、電車が止まるだろう`、ということがわかります。
また、この数値をみると、`注意報レベルで出社がむちゃくちゃ大変`、ということもわかります。

雨1mm/h で、傘をささずに歩けるかな？自転車には乗れない（危ない）というレベルです。
10~20mm/hを超えると出社がだるい。
20mm/hを超えたら、土砂降り。出社やだな〜、と感じるレベルです。

https://mainichi.jp/articles/20210926/ddm/005/070/088000c

とすると、注意報と警報の間ぐらいだったら、RW推奨としたいところですが、
住んでる場所によっては、千葉やら、東京の端っこやら、神奈川やら・・・。注意報のばらつきがあることだと思います。

`注意報以上だったら、RW推奨`、とするのが妥当に思えます。


# 気象庁の警報と注意報の取得

https://qiita.com/conqueror/items/f72cfdedd01149c35313

良い記事がありました。
Pythonで書かれたコードのようです。
これを、GASxSlack通知するために、GASで書き直して！とchatGPTにお願いしてみました。

```js
var AREA_URL = "https://www.jma.go.jp/bosai/common/const/area.json";
var OFFICES_AREA_CODE = "130000"; // tokyo
var warning_info_url = `https://www.jma.go.jp/bosai/warning/data/warning/${OFFICES_AREA_CODE}.json`;
var CLASS_AREA_CODE = "XXXXXXX" // 計測したい地域のコードを入れる
var WEATHER_TRANS = {
 "warninginfo":{
                "02":"暴風雪警報",
                "03":"大雨警報",
                "04":"洪水警報",
                "05":"暴風警報",
                "06":"大雪警報",
                "07":"波浪警報",
                "08":"高潮警報",
                "10":"大雨注意報",
                "12":"大雪注意報",
                "13":"風雪注意報",
                "14":"雷注意報",
                "15":"強風注意報",
                "16":"波浪注意報",
                "17":"融雪注意報",
                "18":"洪水注意報",
                "19":"高潮注意報",
                "20":"濃霧注意報",
                "21":"乾燥注意報",
                "22":"なだれ注意報",
                "23":"低温注意報",
                "24":"霜注意報",
                "25":"着氷注意報",
                "26":"着雪注意報",
                "32":"暴風雪特別警報",
                "33":"大雨特別警報",
                "35":"暴風特別警報",
                "36":"大雪特別警報",
                "37":"波浪特別警報"
        }
};

// 警報チェック
function warnings() {
  var area_data = UrlFetchApp.fetch(AREA_URL);
  area_data = JSON.parse(area_data.getContentText());
  var area = area_data["class20s"][CLASS_AREA_CODE]["name"];
  var warning_info = UrlFetchApp.fetch(warning_info_url);
  warning_info = JSON.parse(warning_info.getContentText());
  var warning_codes = [];
  for (var i = 0; i < warning_info["areaTypes"][1]["areas"].length; i++) {
    if (warning_info["areaTypes"][1]["areas"][i]["code"] == CLASS_AREA_CODE) {
      for (var j = 0; j < warning_info["areaTypes"][1]["areas"][i]["warnings"].length; j++) {
        if (warning_info["areaTypes"][1]["areas"][i]["warnings"][j]["status"] != "解除" && warning_info["areaTypes"][1]["areas"][i]["warnings"][j]["status"] != "発表警報・注意報はなし") {
          warning_codes.push(warning_info["areaTypes"][1]["areas"][i]["warnings"][j]["code"]);
        }
      }
    }
  }
  var warning_texts = [];
  for (var i = 0; i < warning_codes.length; i++) {
    // undefinedが値で返ってくることがあるa
    if (WEATHER_TRANS["warninginfo"][warning_codes[i]] != undefined) {
      warning_texts.push(WEATHER_TRANS["warninginfo"][warning_codes[i]]);
    }
  }
  return [warning_texts, area];
}

function alertTyphoon() {
  // 営業日じゃなきゃキャンセル
  if (isWorkday(new Date()) != true) {
    return;
  }

  var result = warnings();
  Logger.log(`${result[1]}の気象警報・注意報`);
  if (result[0].length == 0 || result[0] == "") {
    Logger.log("現在発表警報・注意報はありません。");
  } else {
    Logger.log(result[0].join("/"));
    var message = result[0].join("/");
    message = `:alert: XXX区の気象警報情報 :rain_cloud: ${message} :alert:`;
    sendSlackMessage(message, 'SlackCHの名前');
  }
}
```
30秒か1分で出力、少し手直しして、よいしょと。
あとは、注意報と警報が出るテストまちですね。
元ネタのjsonデータはgas上にはおけないので、gsにぶっこんでいます。


余談ですが、区のコードは、

https://www.jma.go.jp/bosai/warning/#area_type=offices&area_code=130000&lang=ja

こちらのサイトを見て、見たい区などをクリックすると、
`area_code`に入ってくる数値のことを指します。

# 台風が来たので実際に使ってみた
台風だ！！ということで、早起きしてテストを試みた。

![スクリーンショット 2023-09-09 11.13.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1026740/7d74d7be-627a-ccc5-5457-0ffb4197bdb8.png)

良い感じに取れている。どうやら目黒区は大雨警報だったようだ。
これを使って悪天候時にどうするべきか？というあたり、可視化していきたいなあと思います。