今日・今月・今年の残り時間を表示する

# 何をするか？

[IchigoJam](https://ichigojam.net/)から[MixJuice](http://mixjuice.shizentai.jp/)経由で現在時刻を取得し、今日・今月・今年の残り時間をそれぞれバーで表示します。

※IchigoJamはjig.jpの登録商標です。

# 実装

タイトルを置きます。

```
10 ' ﾉｺﾘｼﾞｶﾝ ﾋｮｳｼﾞ
```

[昨日の記事](https://qiita.com/mikecat_mixc/items/2504f4575d995e8c564c)を応用し、現在時刻を取得します。

* `?" "`で改行を出力し、MixJuiceにコマンドを送信できるようにします。  
  `?""`としてしまうと、1.0.0で1個目ではなく2個目の`"`の後のコードが文字列と認識されてしまい、うまくいきません。
* 初期化など一部の処理を削ったり、演算子を調整したりすることで、コードを短くしました。
* 曜日(`"day_of_week"`)のかわりに、今年の中で何日目か(`"day_of_year"`)を取得するようにしました。

```
20 LOCATE0,-1:?" ":?"MJ GETS worldtimeapi.org/api/timezone/Asia/Tokyo":N=1:S=0:P=0:V=0:E=0
30 C=INKEY():IFPANDTICK()>29GOTO110ELSEIF!CGOTO30
40 N=N*(C<>58)|(C=44):H=H+C*S*N:IFC=34S=!S:IFS*NH=0
50 IF47<CANDC<58V=V*10+C-48:E=1ELSEIFEGOTO70
60 IFC=#7DGOTO110ELSECLT:GOTO30
70 IFH=879[P]=V:P=P+1
80 IFH=1188[9]=V
90 V=0:E=0:GOTO60
```

`T`でバーの黒い部分の長さ(経過した時間)を、`Y`で描画する位置を指定し、バーを描画します。
`T`の定義域は0～60 (両端を含む) です。

```
100 T=61-T:FORX=1TO30:C=#80+5*(T>=X*2)+#A*(T>X*2):LOCATEX,Y:?CHR$(C);:LOCATEX,Y+1:?CHR$(C);:NEXT:RETURN
```

現在時刻を出力し、今年の日数と今月の日数を計算します。
今年の日数(`D`)は、うるう年(`R`)なら366日、そうでなければ365日です。
今月の日数(`M`)は、

* 2月は、うるう年なら29日、そうでなければ28日
* 1月と3月～7月は、奇数月なら31日、偶数月なら30日
* 8月～12月は、偶数月なら31日、奇数月なら30日

となります。

```
110 CLS:LOCATE0,0:?[0];"/";[1];"/";[2];" ";[3];":";[4]:R=[0]%400=0OR([0]%4=0AND[0]%100):D=365+R:M=(30+[1]%2)^([1]>7):IF[1]=2M=28+R
```

バーのタイトルと枠を描画します。
左端は自動で改行が入ることを利用して描画することで、文字数を節約しています。

```
120 LOCATE0,3:?"ｷｮｳ":LOCATE0,10:?"ｺﾝｹﾞﾂ":LOCATE0,17:?"ｺﾄｼ":FORY=4TO18STEP7:LOCATE0,Y:?CHR$(#88);:FORX=1TO30:?CHR$(#8C);:NEXT:?CHR$(#84)
130 LOCATE0,Y+1:?CHR$(#8A):?CHR$(#8A):?CHR$(#82);:FORX=1TO30:?CHR$(#83);:NEXT:?CHR$(#81):LOCATE31,Y+1:?CHR$(#85):LOCATE31,Y+2:?CHR$(#85):NEXT
```

経過時間を0～60で表した値を求め、バーを描画します。
経過時間は、以下の式を約分したり展開したりしたものです。
割る数の半分を足してから割ることで、四捨五入をしています。
計算に使うパラメータは、61段階に丸められることを考え、細かすぎないように選びました。

* 今日の経過時間：((時×60+分)×60+60×12)÷(60×24)
* 今月の経過時間：(((経過日数-1)×24+時)×60+全日数×12)÷(全日数×24)
* 今年の経過時間：((経過日数-1)×60+全日数÷2)÷全日数

今月の経過時間の計算において、`U`の値を直接`T`の値を求める式内で計算しようとすると、
1.3.1でComprex expressionになってしまったので、分割しました。

```
140 T=([3]*60+[4]+12)/24:Y=5:GOSUB100:U=[2]*24-24+[3]:T=(U*5+M)/(M*2):Y=12:GOSUB100:T=([9]*60-60+D/2)/D:Y=19:GOSUB100:LOCATE0,22
```

約1分待機し、自動更新します。
現在時刻の取得中に`CLT`が実行されていることを利用します。

```
150 IFTICK()>3599GOTO20ELSEGOTO150
```

# コード全体

```
10 ' ﾉｺﾘｼﾞｶﾝ ﾋｮｳｼﾞ
20 LOCATE0,-1:?" ":?"MJ GETS worldtimeapi.org/api/timezone/Asia/Tokyo":N=1:S=0:P=0:V=0:E=0
30 C=INKEY():IFPANDTICK()>29GOTO110ELSEIF!CGOTO30
40 N=N*(C<>58)|(C=44):H=H+C*S*N:IFC=34S=!S:IFS*NH=0
50 IF47<CANDC<58V=V*10+C-48:E=1ELSEIFEGOTO70
60 IFC=#7DGOTO110ELSECLT:GOTO30
70 IFH=879[P]=V:P=P+1
80 IFH=1188[9]=V
90 V=0:E=0:GOTO60
100 T=61-T:FORX=1TO30:C=#80+5*(T>=X*2)+#A*(T>X*2):LOCATEX,Y:?CHR$(C);:LOCATEX,Y+1:?CHR$(C);:NEXT:RETURN
110 CLS:LOCATE0,0:?[0];"/";[1];"/";[2];" ";[3];":";[4]:R=[0]%400=0OR([0]%4=0AND[0]%100):D=365+R:M=(30+[1]%2)^([1]>7):IF[1]=2M=28+R
120 LOCATE0,3:?"ｷｮｳ":LOCATE0,10:?"ｺﾝｹﾞﾂ":LOCATE0,17:?"ｺﾄｼ":FORY=4TO18STEP7:LOCATE0,Y:?CHR$(#88);:FORX=1TO30:?CHR$(#8C);:NEXT:?CHR$(#84)
130 LOCATE0,Y+1:?CHR$(#8A):?CHR$(#8A):?CHR$(#82);:FORX=1TO30:?CHR$(#83);:NEXT:?CHR$(#81):LOCATE31,Y+1:?CHR$(#85):LOCATE31,Y+2:?CHR$(#85):NEXT
140 T=([3]*60+[4]+12)/24:Y=5:GOSUB100:U=[2]*24-24+[3]:T=(U*5+M)/(M*2):Y=12:GOSUB100:T=([9]*60-60+D/2)/D:Y=19:GOSUB100:LOCATE0,22
150 IFTICK()>3599GOTO20ELSEGOTO150
```

# 実行結果

現在時刻を取得し、それをもとに今日・今月・今年の残り時間をバーで表示することができました。

![実行結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/28866013-f9f1-e026-cc6e-81df4d48c397.png)