クラゲ発生検知アルゴリズム

#はじめに
昨年、海でシュノーケリングをした際に、一緒に連れて行ったエンジニアが極度にクラゲを恐れていた。たまに毒を持ったクラゲも出てきたりして、目の前を通り過ぎた際は戦慄した。

海が好きな私にとっては、これは由々しき事態と感じ、
クラゲが発生しやすいタイミングを教えてくれる処理を考えてみた。

まずクラゲの性質を個人的に整理（wikiで参照)
※専門家ではないので、あしからず、、

#クラゲの性質
##まずは調べてみた
・水流を作ってやらないと、次第に水底に沈む
　→次第に弱って死に至る
・ペンギンに頻繁に捕食されている
・クラゲの毒の人体への作用は、クラゲの種類によって大きく異なる
・カツオノエボシやハブクラゲ、オーストラリアウンバチクラゲは危険
・日本ではお盆過ぎに海水浴場に泳ぎに行くとクラゲに刺される
　→クラゲが大人に成長するタイミング
・クラゲを飼育する場合の水温は25℃くらい
　→30度で死滅
・10月ぐらいまで水温が高いのでクラゲが発生しやすい
・風が強い時期（強風及び台風など）には発生しづらい
・潮の流れが激しい場所は発生しづらい
・活動期が8月中～10月まで→海の温度が高い時期
・水温が低いとクラゲは発生しづらい
・海水温度の一番高い時期でも、朝七時頃まではクラゲが
　活動し易い温度まで達してはいません。
・船のスクリュー音を聞くと、高音域の音が沢山あり、
　クラゲの動きを停止させると考えられている
・クラゲの体は95%以上が水分→真水が含まれると
　海の底に沈む


##更に性質を定量的に整理してみた
・クラゲは高温に弱い
　→水温27℃～30℃は出現率が低い

・降水確率
　→100%に近ければ近いほど表れにくい
　→梅雨の時期には表れにくいという仮説

・8/11～10/1にかけては出現率が高い
　→クラゲが成体になるタイミング

・海流が遅いほどクラゲの発生が低い
　→1ノット≒0.5m/s
　→1時間に1海里(1852m)進む速さ
　→水流がないと底に沈む

・海水の塩分濃度が低いと海の底に沈む
　→塩分濃度 34-35pptが生育に適切であるため、
　　36ppt以上が発生しない

#実装ベースで整理
##条件
・気温：27 ≦ 現在の気温 ≦ 30

・降水確率：50% ≦ 現在の気温 ≦ 100%
　※ただ、雨だと海を堪能できない、、。
　　クラゲ処じゃない。。

・危険期間：8/11 ≦ 現在日 ≦ 10/1

・海流：1.5 ≧　現在の海流
　※ノットが定量的にわからないので、一旦こんな感じです。
　　（クラゲが出ない日の海のノット数を計りたい。。）

・塩分濃度：36ppt ≦ 現在濃度

・各判定の良悪はBoolean判定

##判定方法
独自の基準ですが、以下で判定結果を出力

条件
①晴れ晴れとした気持ちでクラゲを気にせず海にいきましょう！
　(true,false,false,true,true)
　・気温：27 ≦ 現在の気温 ≦ 30
　・降水確率：0%～40%
  ・危険期間：8/11 ≦ 現在日 ≦ 10/1以外
　・海流：1.5 ≧　現在の海流
　・塩分濃度：36ppt ≦ 現在濃度

②どんよりして雨は降りますが、クラゲは確実に出現しません！
  (true,true,false,true,true)
　・気温：27 ≦ 現在の気温 ≦ 30
　・降水確率：50%～100%
　・危険期間：8/11 ≦ 現在日 ≦ 10/1以外
　・海流：1.5 ≧　現在の海流
　・塩分濃度：36ppt ≦ 現在濃度

③クラゲほぼ出ます。家でゴロゴロしましょう。
  (false,false,true,false,false)
　・27 ≧ 現在の気温
　・降水確率：0～40%
  ・危険期間：8/11 ≦ 現在日 ≦ 10/1
　・海流：1.5 <　現在の海流
  ・塩分濃度 < 36ppt

③基本やつらは出てきます！しかし、出現しない場合もあります。
   ※前提
  ・危険期間：8/11 ≦ 現在日 ≦ 10/1

★条件１ (true,false,true,true,true)
　・気温：27 ≦ 現在の気温 ≦ 30
　・降水確率：0%～40%
　・海流：1.5 ≧　現在の海流
　・塩分濃度：36ppt ≦ 現在濃度
　　　　or
★条件2 (true,false,true,true,true)
　・気温：27 ≧ 現在の気温
　・降水確率：0%～40%
　・海流：1.5 ≧　現在の海流
　・塩分濃度：36ppt ≦ 現在濃度
　　　　or
★条件3(true,false,true,true,true)
　・気温：27 ≦ 現在の気温 ≦ 30
　・降水確率：0%～40%
　・海流：現在の海流 ≧ 1.5
　・塩分濃度：36ppt ≦ 現在濃度
　　　or
★条件4(true,false,true,true,true)
　・気温：27 ≦ 現在の気温 ≦ 30
　・降水確率：0%～40%
　・海流：1.5 ≧　現在の海流
　・塩分濃度：現在濃度 < 36ppt

##実装したプログラム（やっと。。）
```JellyFishAlert.java
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Calendar;
import java.util.function.Function;

public class JellyFishAlert {

	public static void main(String[] args) {
		
		//コマンドライン引数(気温,降水確率,海流判定,塩分濃度判定)
		if(args.length == 4) {
			System.out.println("計算に必要な値はOK!");
		}else {
			System.out.println("コマンドライン引数を正しく指定してください");
			System.exit(0);
		}

		//判定マップを生成(a～gの表記がうんこ。。）
		boolean a[] = {true,false,false,true,true};
		boolean b[] = {true,true,false,true,true};
		boolean c[] = {false,false,true,false,false};
		boolean d[] = {true,false,true,true,true};
		boolean e[] = {true,false,true,true,true};
		boolean f[] = {true,false,true,true,true};
		boolean g[] = {true,false,true,true,true};

		//気温判定
		Function<Integer, Boolean> is_temperature = (tmperature) -> {
  			return tmperature >= 27 && tmperature <= 30 ? true : false;
		};
		
		//降水確率判定
		Function<Integer, Boolean> is_rainy_percent = (rainy_percent) -> {
  			return rainy_percent >= 50 && rainy_percent <= 100 ? true : false;
		};
		
		//危険期間判定
		Function<LocalDateTime, Boolean> is_jellyfish_danger_date = (now) -> {
			Calendar cTime = Calendar.getInstance();
  			return now.isBefore(LocalDateTime.of(cTime.get(Calendar.YEAR), 8, 11, 0, 0)) 
  					&& now.isAfter(LocalDateTime.of(cTime.get(Calendar.YEAR), 10, 1, 23, 59)) ? true : false;
		};
		
		//海流判定
		Function<Integer, Boolean> is_ocean_current = (current_knot) -> {
  			return  current_knot <= 1.5 ? true : false;
		};

		//塩分濃度判定
		Function<Integer, Boolean> is_salinity = (current_salinity) -> {
  			return  current_salinity >= 36 ? true : false;
		};
		
		//現在の海の状況（気温/降水確率/危険日/海流/塩分濃度）
		boolean state_of_sea[] = {is_temperature.apply(Integer.valueOf(args[0])),
				is_rainy_percent.apply(Integer.valueOf(args[1])),
				is_jellyfish_danger_date.apply(LocalDateTime.now()),
				is_ocean_current.apply(Integer.valueOf(args[2])),
				is_salinity.apply(Integer.valueOf(args[3]))
		};		
		
		//クラゲへの対応判定
		if(Arrays.equals(a,state_of_sea)) {
			System.out.println(JellyFishDangerStatus.NODANGER.status);
		}else if (Arrays.equals(b,state_of_sea)){
			System.out.println(JellyFishDangerStatus.LOWDANGER.status);
		}else if (Arrays.equals(c,state_of_sea)) {
			System.out.println(JellyFishDangerStatus.HIGHTDANGER.status);
		}else if(Arrays.equals(d,state_of_sea) 
				|| Arrays.equals(e,state_of_sea) 
				|| Arrays.equals(f,state_of_sea)
				|| Arrays.equals(g,state_of_sea)) {
			System.out.println(JellyFishDangerStatus.MIDDLEDANGER.status);
		}else {
			System.out.println(JellyFishDangerStatus.UNKNOWNDANGER.status);
		}
	}
	
	public enum JellyFishDangerStatus {
        NODANGER("晴れ晴れとした気持ちでクラゲを気にせず海にいきましょう！"),
        LOWDANGER("どんよりして雨は降りますが、クラゲは確実に出現しません！"),
        HIGHTDANGER("クラゲほぼ出ます。家でゴロゴロしましょう。"),
        MIDDLEDANGER("基本やつらは出てきます！しかし、出現しない場合もあります。"),
		UNKNOWNDANGER("予測不能。速やかに海から立ち去りなさい。");

        private final String status;

        private JellyFishDangerStatus(String status) {
        this.status = status;
        }

        public String getStatus() {
            return this.status;
        }
    }
}

```

#終わりに
殆どクラゲの情報を調べるのに時間を使ってしまいました。。

こんなもんでクラゲを打倒できるものではありませんが、一般の人がクラゲを恐れない状況を生み出すのに一役買えたら嬉しいですね。今後更に研究していきたいと思います。水中ドローンとかに組み込めたら最高ですね。