OmniAICreator/Qiita-1.07M huggingface dataset:
2020年10月版ActivityResultAPIを使ってみた。

kotlinやandroidxの勉強も兼ねて、以前作った自作androidアプリケーションを一から作り直しているんですが、`Activity#startActivityForResult`は代わりにActivityResultAPIを使う事を薦められているとの事。

* [アクティビティからの結果の取得](https://developer.android.com/training/basics/intents/result)

いきなり使うのはためらうので、まずはテストプロジェクトで試してみましたが、まぁ、何ていうかその…。

**トラブル解決に自信があるなら別にいいけど、そうでないならあと1年は様子見でいいよ。**

## テストしてみる。

とりあえずテストした結果を書いておきます。

まず、「`build.gradle`」に依存関係を書きます。

```
dependencies {
	implementation "androidx.activity:activity:1.2.0-alpha08"
	implementation "androidx.activity:activity-ktx:1.2.0-alpha08"
	implementation "androidx.fragment:fragment:1.3.0-alpha06"
}
```

ここに注目。
というのも、結構新しいAPIなので、仕様が変わっていて、ネットの情報が間違っている事も多い。
ぶっちゃけ、**これから書く内容も、将来的には間違いかもしれないですよ。**

そして、Activityのコード。

```MainActivity.kt
package com.example.test1012a

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.TextView
import android.content.Intent
import android.app.Activity
import android.util.Log
import androidx.activity.result.contract.ActivityResultContracts
import android.widget.Toast

//private const val REQUEST_CODE = 1

class MainActivity(): AppCompatActivity(), View.OnClickListener {

	private val launcher = registerForActivityResult(ActivityResultContracts.CreateDocument()) { uri ->
		Log.d("test1012a", String.format("uri = %s.", uri.toString()))
		this@MainActivity.getContentResolver().openOutputStream(uri)?.writer()?.use {
			it.write("Hello, world!\n")
		}
	}

	protected override fun onCreate(savedInstanceState: Bundle?)
	{
		super.onCreate(savedInstanceState)
		this.setContentView(R.layout.main)

		this.findViewById<View>(R.id.button1).setOnClickListener(this)
	}

	override fun onClick(view: View)
	{
		when (view.getId()) {
			R.id.button1 -> {
//				val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
//					this.addCategory(Intent.CATEGORY_OPENABLE)
//					this.type = "*/*"
//				}
//				this.startActivityForResult(intent, REQUEST_CODE)
				this.launcher.launch("hoge")
			}
		}
	}

//	override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?)
//	{
//		if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
//			resultData?.data?.also {
//				this.findViewById<TextView>(R.id.result).setText(it.toString())
//			}
//		}
//	}
}

```

以下、ハマった点です。

## `prepareCall`ではなく、`registerForActivityResult`

先の公式サイトのとおりに記述したら、「`prepareCall`」でビルドエラー。
「なんでじゃー」と叫びつついろいろと探してみると、[バージョン1.2.0-alpha04の変更点](https://developer.android.com/jetpack/androidx/releases/activity#1.2.0-alpha04)に以下の記述が。

> prepareCall() メソッドの名前が、ここの ComponentActivity と Fragment 1.3.0-alpha04 の両方で、registerForActivityResult() に変更されました。

ドキュメント直しておけよーー。
(これに限らず、最近のandroidのドキュメントはおざなりになっていない?量が膨大になってきたのはわかりますけど、わかりますけどね)

## 「Can only use lower 16 bits for requestCode」

めでたくビルドが通って、実行してみると、ボタンを押した時点でアプリが落ちてしまいます。
ログを見てみると、「Can only use lower 16 bits for requestCode」とのエラーが出力。

実は、当初依存関係に「fragment:1.3.0-alpha06」は含んでいなかったのです。いやだって、fragment使ってないし。
でも、試しに加えてみたら、エラーが発生しなくなりました。もしかすると、`FragmentActivity`辺りが古いせいなのかもしれません。
E資格取得に向けた学習まとめ

#１．概要
本記事は、E資格取得に向けて学習の記録として記事をまとめる。
基本は、E資格を受けるにあたり必須となる日本ディープラーニング協会認定講座プログラム(いくつかあるが本記事では『ラビットチャレンジ』)での学習内容のレポート記事を記載する。
また、『ラビットチャレンジ』修了後はE資格取得に向けた試験対策などを記載したい。
(プログラムはPythonを使用する。)

#２．目次
・ラビットチャレンジレポートまとめ
・E資格試験対策
・各種リンク

#３．ラビットチャレンジレポートまとめ
『ラビットチャレンジ』で定められたプログラムでレポートのリンクをまとめる。

　◎応用数学
　　・<a href="https://qiita.com/gen1127/items/c38d4c4ab3a0a8887f85" target="_blank">線形代数</a>　演習問題以外更新済み。　2020/10/27
　　・確率・統計　(作成中)
　　・情報理論　(作成中)
　◎機械学習
　　・線形回帰モデル　(作成中)
　　・非線形回帰モデル　(作成中)
　　・ロジスティック回帰モデル　(作成中)
　　・主成分分析　(作成中)
　　・アルゴリズム　(作成中)
　　・サポートベクターマシーン　(作成中)
　◎深層学習
　　(day1)
　　・入力層～中間層　(作成中)
　　・活性化関数　(作成中)
　　・出力層　(作成中)
　　・勾配降下法　(作成中)
　　・誤差逆伝播法　(作成中)
　　(day2)
　　・勾配消失問題　(作成中)
　　・学習率最適化手　(作成中)
　　・過学習　(作成中)
　　・畳み込みニューラルネットワークの概念　(作成中)
　　・最新のCNN　(作成中)
　　(day3)
　　・再帰型ニューラルネットワークの概念　(作成中)
　　・LSTM　(作成中)
　　・GRU　(作成中)
　　・双方向RNN　(作成中)
　　・Seq2Seq　(作成中)
　　・Word2vec　(作成中)
　　・Attention Mechanism　(作成中)
　　(day4)
　　・Tensorflowの実装演習　(作成中)
　　・強化学習　(作成中)

#４．E資格試験対策
＊＊＊『ラビットチャレンジ』修了後更新予定＊＊＊

#５．各種リンク
**・ラビットチャレンジ**
<a href="https://ai999.careers/rabbit/" target="_blank">https://ai999.careers/rabbit/</a>


**・3カ月で現場で潰しが効くディープラーニング講座**
<a href="http://study-ai.com/jdla/" target="_blank">http://study-ai.com/jdla/</a>
[<img src = "http://ai999.careers/bnr_jdla.png">](http://study-ai.com/jdla/)
Pythonで日時フォーマットを判定してUnixtimeに変換する

ソースコードは以下になります。
日時の変換の可否によって判定しています。

```python 
import datetime


def validate_datetime(date_str):
    try:
        date_obj = datetime.datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S')
    except:
        print('Invalid Datetime Format')
        return False
    return date_obj


def main():
    date_str = '2020-10-13 22:47:57'
    result = validate_datetime(date_str)

    if result:
        print(int(result.timestamp()))


if __name__ == '__main__':
    main()
```

実行結果は以下になります。

```console
1602596877
```

最後まで読んでいただきありがとうございました。
またお会いしましょう。
【Java】OpenCSVでファイルの値を変換して取り込む

## 概要
JavaにはCSVファイルをBeanに取り込むためのライブラリで、OpenCSVというものがあります。[JavaのCSVライブラリ「opencsv」](https://qiita.com/sunnycloudy764/items/c117e769863dc96edc59)の記事にある通り、列名とBeanのプロパティ名を紐付けて取り込むことができます。
今回の記事は、ファイルの値を変換してBeanに取り込むときの対応を紹介します。

## 対応
[こちら](https://stackoverflow.com/questions/51155224/opencsv-wrong-date-format)のStackOverflowに書いてあるのが日付の変換例です。アノテーションの`converter`に変換用のクラスを設定して、変換します。

## 実装サンプル
文字列から日付の変換例を、実装サンプルとしてのせます。

ファイル中の`created_at`列を`LocalDateTime`型に変換します。

```SampleCsvBean.java
public class SampleCsvBean {
    @CsvBindByName(column = "id")
    private Long id;
    @CsvBindByName(column = "name")
    private String name;
    @CsvCustomBindByName(column = "created_at", converter = SampleConverter.class)
    private LocalDateTime createdAt;
}
```

ファイルには`20140101 00:00:00`の形式で、日付の値が設定されているとします。
これをconverterのクラス内で、LocalDateTimeにフォーマットします。

```SampleConverter.java
public class SampleConverter extends AbstractBeanField {
    @Override
    protected Object convert(String s) throws CsvDataTypeMismatchException, CsvConstraintViolationException {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");
        return LocalDateTime.parse(s, dtf);
  }
}
```
Elmでマンカラ（カラハ）を作って遊ぶ

## はじめ
突然ですが私はマンカラというボードゲームが好きです。アフリカを起源とする（諸説ある）種まきのようなゲームで、より多くの石を取ったほうが勝ちという最古級のアブストラクトゲームです。最近では任天堂の「世界のアソビ大全」で収録されているのでご存知の方も多いと思います。
このゲームはいわゆる二人零和有限確定完全情報ゲームで、ランダム要素がなく完全に相手の手を読むゲームです。さらに、盤面の情報はそれぞれの穴の中にある石の数だけで、ルールも（比較的）簡単です。新しい言語で遊ぶときの練習台としてちょうどいいと考え、Elmで実装してみることにしました。

## まとめ
マンカラにも色々あるのですが、今回は、マンカラの中でも日本で有名なカラハを作ってみました。
（「アソビ大全」で遊べるルールです。）
成果物は[このEllie](https://ellie-app.com/bf6gjXYMqNTa1)で遊ぶことができます。

## カラハのルールおさらい
1. 6個 * 2列の穴に石が4つずつあり、両端にゴールとなる空の穴があります（向かって右手側の穴が自分のゴールです）。
2. 自分側の穴の1つから石をとり、隣の穴に1個ずつ反時計回りに播きます。
3. 播いた石の最後の1つが自分のゴールに入ると、もう一回手番を行えます。
4. 播いた石の最後の1つが自陣の空の穴に入り、かつ向かいの（相手側の）穴に石があれば、それと自陣側の石（最後に播いたもの）を自分のゴールに移します。
5. これを繰り返して、播けるものがなくなったら、その時点で自陣にある石の数が多いほうが勝ちです。

## やったこと
### マンカラ盤のModelをつくる
ざっくりとやりたいこととしては、

* マンカラをあそびたい
* ターン表示
* 終わったらどちらが勝ったか表示

を考えていたので、下のようなModelにしてみました。

```elm
type Player --プレイヤーを示す
    = Myself
    | Opposite


type PlayStatus --ゲームの進行状況を示す
    = End Player
    | Draw
    | Playing

type alias Stage =
    { turn : Player --現在の手番
    , field : List Int --各穴に入っている石の数
    , lastSown : Maybe Int --最後に石を播いた穴のIndex
    , remainStone : Int --これから播く石の残数
    , status : PlayStatus --ゲームの進行状況
    }

type alias Model =
    Stage
```

fieldは下のように、0番目と7番目のindexがゴールの穴であるようなList Intを用意します。

```elm
[0, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4]
```

マンカラのゴールの穴は本来いろいろな機能があり、本当は別にしてやるべきだと思うのですが、カラハはゴールにも石を播くというルール上、こうすると楽でした。
lastSownとremainStoneは、ルール3. 4. を処理するために準備しました。

### 石を播く
石を播く処理は

```elm
prepareSowing : Int -> Stage -> Stage
progressSowing : Stage -> Stage
```
の2つの関数を用意しました。prepareSowingで指定した穴にある石を取り出してremainStoneに格納し、progressSowingで1つずつ播いていきます。石を取り出す穴の位置が確定すれば、播いた後の盤面も決まるので、こんなまだるっこしいことはしなくていいのですが、テストプレイしていると盤面が一気に変わって見にくかったのでこういう処理にしています。updateで画面更新をする際に、

```elm
progressSowing model, Task.perform (always (Spread position)) (Process.sleep 100)
```

として播いているときにちょっと時間を置いたりして1つずつ播いているように見せています。

### 画面を作る
elm-uiに興味があったので、せっかくだし使ってみました。パズルのようにcolumnやrowを組み合わせて作れるので、慣れれば面白い感じです。
めちゃ長くなったので詳細は割愛しますが、ゴールの要素はviewPointCell、それぞれの穴の要素はviewCell、といったかんじで部品ごとにつくっていって、だんだんまとめていくと書いていてわかりやすい感じでした。
ただ、センタリングのやり方（centerX, centerYなど）は意図通りに設定するのはかなり難儀しました。たぶん設定の重複とかいろいろあるはず……。

## 本当はやりたかったこと
* 石の情報を数字じゃなくて石を画像でわかりやすく表示したかった(svgとか)
* 全体的に極めてダサいのでなんとかしたかった
* 他のルールにも対応できる汎用性のある設計にしたかった

この辺は今後どうにかしたいですが、一区切りとするためにQiitaに供養することにしました。

## 参考にした記事
* [elm-uiハンズオン](https://qiita.com/nikueaters/items/5ad7f1ea541c64e7c035)
* [もう上下左右中央揃えでググらない！elm-uiで簡単レイアウト！](https://qiita.com/miyamo_madoka/items/c423af7b8c4b0f9dc200)
EC2上のmysqlにSequelProから接続してデータを挿入する

# SequelProを使ってデータベースにデータを挿入する方法を備忘録として残します。


まずSequelProを開きましょう！するとこんな画面ですよね
![84d6295b0f55a2bbac8fec55f2ef5166.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743908/23fabee2-a8f8-6c14-4514-1c54bee3553c.png)

### 左下の＋ボタンを押す
お気に入りのところに新しく追加されます
![あああ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743908/1a55107e-a60c-d6f8-36b8-625f71cf4264.png)
名前はわかりやすいように自分で変えましょう

### 標準にカーソルがあっているものをSSHに合わせる
![いいいい.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743908/1c353c7a-bcb1-aa0a-69b7-43cfac8f27f0.png)
ここのフォームに必要な情報を入力していくとデータベースにアクセスできます

・MySQLホスト:　127.0.0.1　←デフォルト

・ユーザー名: root

・パスワード: EC2上のMySQLのrootユーザのパスワード

・データベース:  空欄

・ポート: 3306

・SSHホスト: EC2のElastic IP

・SSHユーザー: ec2-user

・SSHパスワード:　 左の鍵のアイコンをクリックしましょう。finderに繋がります。EC2のキーペアをダウンロードしたときのファイルを選択する。(Finderにあるが隠れてい普段は見ることができない)

・ポート:　 空欄で良い

・SSLを使用して接続: 　チェックなし

### SSH鍵を表示するには、まずキーが.sshディレクトリにあるのを確認.sshディレクトリでlsコマンドで確認

```
hoge@hogenoMacBook-Air .ssh % ls
キーペア名.pem	known_hosts
```


### .sshディレクトリに〜.pemがあるのを確認したらfinderでこのファイルを探す。ただ、sshディレクトリは隠しディレクトリなのでそれを表示するためにはfinder上で［コマンド］＋［シフト］＋［ドット］を打つと隠しディレクトリが現れる。
![スクリーンショット 2020-10-13 22.16.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743908/f275f816-0472-ed80-5d08-fcd107c1bac3.png)

このなかにpemキーのファイルがあるので選択

この手順で本番環境のデータベース にアクセスできました。
コンテナ同士の通信について

# 概要
docker-compose.ymlで定義したコンテナは同じネットワーク下に置かれる。コンテナは互いにその名前でアクセスできる。

```shell
/var/www/container1# ping container2
64 bytes from ...省略
```

# docker-compose.yml
こんなときコンテナ1から2にアクセスしたい。

```docker-compose.yml
version: "3"

services:
  container1:
    build:
      context: ./docker/container1
    ports:
      - "3000:3000"

  container2:
    build:
      context: ./docker/container2
    ports:
      - "8080:80"
```
# なぜか
ネットワーク内のDNSサーバーが立っていて名前解決をしている。
通常コンテナからホストマシンのローカルipにはアクセスできないが、DNSサーバーがコンテナごとに割り当てられたポートで名前解決してくれる✨
(digコマンドで動いているDNSサーバーがわかる)

# おまけ
直接コンテナ内のhostsにipとドメインを書いて名前解決する方法。
ホストマシンのipアドレスはwifiの設定でip4・ip6で動的に変わったりするので意図せず開発環境が動かなくなる可能性あり。

```docker-compose.yml
# ports:
#    - "8080:80"
extra_hosts:
      - "localhost-dev:${ホストマシンのipアドレス}"
```
JavaScript htmlのプルダウンメニューの読み取り方法

・htmlで記述した、プルダウンメニューの作り方

```
<form id="form>
   <select name="select">
      <option value="index.html>日本語</option>
      <option value="index-en.html>英語</option>
      <option value="index-zh.html>中文</option>
   </select>
</form>
```
・フォームに必要不可欠なname属性（入力項目をサーバーで扱うときに使う名前）はselectタグに記述する。optionタグには書かない。
・各optionタグにそのデータを表すvalue属性を記述する。
・プルダウンメニュー(select要素）の場合、selectタグのname属性と選択されたoptionタグのvalue属性がセットになって、サーバーに送信される。

ここから、javascriptを記述していきます。

```
'use strict';
document.getElementById('form').select.onchange=function(){
location.href=document.getElementById('form').select.value;
}
```
このコードは、onchangeイベントプロパティが発生したら呼び出される関数を作っている。
onchangeイベントは、「フォームに入力された内容が変わったとき」に発生する。
その関数の処理は、locationオブジェクトのhrefプロパティ（表示しているURL）に、フォームで選択されたoptionのvalue(URL)が代入される。
ここで、疑問なのが、なぜ「.select.value;」となっているのか？
言い換えると、selectタグ内にはvalue属性を書いてないで、optionタグ内にvalue属性を書いたのに、なぜselectの中でvalueプロパティを読み取っているのか？
その理由は、『プルダウンメニューの場合は選択されているoptionのvalue属性を調べるために、その親要素であるselectのvalueプロパティを読み取る。』

そして、script.js全体のコードを以下で記述します。

```
'use strict';

const lang=document.querySelector('html').lang;

if(lang==='ja'){
    document.querySelector('option[value="index.html"]').selected=true;

}else if(lang==='en'){
    document.querySelector('option[value="index-en.html"]').selected=true;

}else if(lang==='zh'){
    document.querySelector('option[value="index-zh.html"]').selected=true;
}

document.getElementById('form').select.onchange=function(){
    location.href=document.getElementById('form').select.value;
}
```
documentオブジェクトのquerySelectorメソッドは、()内に書かれた「セレクタ」にマッチする要素を取得する。セレクタとはCSSで使うやつです。例えば、
2行目のセレクタはタイプセレクタで指定している。
4行目のif文ないの処理では、('option[value="index-en.html"]');となっていて、これは属性セレクタです。
属性セレクタとは、　要素名[属性名＝"属性値"]　で指定する方法です。
ここでまた注意点があります。
（複数の要素がマッチしたらどうなるの？という点)
この場合、htmlではマッチした全てが対象になるが、
javascriptでは『最初にマッチした要素』一つだけ対象になる。

参考：javascript超入門　P198~
【Udemy Python3入門+応用】　 66. 独自例外の作成

**※この記事はUdemyの
「[現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル](https://www.udemy.com/course/python-beginner/ "現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル")」
の講座を受講した上での、自分用の授業ノートです。
講師の[酒井潤](https://twitter.com/sakaijun "酒井潤")さんから許可をいただいた上で公開しています。**


##■独自例外の作成
####◆raise
```python
raise IndexError('test error')
```
```:result
Traceback (most recent call last):
  File "/~~~", line 1, in <module>
    raise IndexError('test error')
IndexError: test error
```
`raise` を使うことで、指定したエラーを引き起こすことができる。
<br>

####◆独自のエラーを作る
```python
class UppercaseError(Exception):
    pass

def check():
    words = ['APPLE', 'orange', 'banana']
    for word in words:
        if word.isupper():
            raise UppercaseError(word)

check()
```
```:result
Traceback (most recent call last):
  File "/~~~", line 10, in <module>
    check()
  File "/~~~", line 8, in check
    raise UppercaseError(word)
__main__.UppercaseError: APPLE
```
このように、プログラム内で自分で作ったエラーを発生させることができるようになる。
<br>

```python
class UppercaseError(Exception):
    pass

def check():
    words = ['APPLE', 'orange', 'banana']
    for word in words:
        if word.isupper():
            raise UppercaseError(word)

try:
    check()
except:
    print('This is my fault. Go next.')
```
```:result
This is my fault. Go next.
```
このようにしておくと、処理内でエラーが発生したときに、
「これはPythonのデフォルトのエラーではなくて、自分で作ったエラーが発生しているんだな」
と認識できるようになるため、開発で便利。
【Android】WebViewで、mailto:とかtel:を開けずに詰まった話

# 【Android】WebViewで、mailtoとかtelを開けずに詰まった話
AndroidのWebViewで、WebView内のリンクをタップした時に、mailto:やtel:だと、schemeに対応していないというメッセージが表示されて、電話アプリやメーラーが起動できないで詰まってました。

## 参考
* [公式ドキュメント](https://developer.android.com/guide/webapps/webview?hl=ja#HandlingNavigation)
  * こちらを読めば、理解が深まるかと思います。 

## 原因と対策
* 原因
  * WebViewに対して、setWebViewClientをだけをしていたので、mailto:などのURLをWebViewでロードされるようになっていた。
  * そもそもWebViewは、httpリソースを表示するようなので、mailto:やtel:などのURLスキームに対応していないみたい…(ドキュメントで明記されていたわけではないです。)

* 対策
  * WebViewClientに、shouldOverrideUrlLoadingメソッドを実装してあげて、処理を記述する。
  * 記事を調べると、メールアプリの起動や電話アプリの起動を、スキーマで判別して、暗黙的Intentで起動するとしているものが多かったけど、ただアプリを起動して値を渡すだけなら、ブラウザを起動させてurlを渡すだけで動きました。
  * [Intent.ACTION_VIEWのドキュメント](https://developer.android.com/reference/android/content/Intent#ACTION_VIEW)に、mailto:、tel:に対応してアプリ起動すると記載がありました。

``` SampleWebViewActivity.kt
public class SampleWebViewActivity extends FragmentActivity {    
    private WebView mWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample_web_view);

        // 仮にwebViewというidがあるとして
        mWebView = (WebView) findViewById(R.id.webview);
        mWebView.setWebViewClient(new WebViewClient(){

            // 大事なのはここです！
            // ここで、WebView内でのurlのロード(リンクがタップされた時)を制御している
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                // ブラウザを起動しているだけ
                // ブラウザの方で、mailto:やtel:を制御してくれる。
                val intent = new Intent(Intent.ACTION_VIEW, request.url);
　　　　　　　　　 startActivity(intent);

                // trueを返さないと、webViewで、このurlをロードしてしまいます。
                return true;
            }
        });
    }
``` 

## 最後に
今回の対策では、とりあえずmailto: とかtel:も対応できるようになっただけです。
そのため、電話アプリを起動する前にダイアログで知らせるとかになると、スキームで判定とかが必要かなと思います。
またdeep linkとかになると、また面倒な対応がさらに必要になります。
CloudWatchのダッシュボードをSlackに通知する

CloudWatch のダッシュボードって超イケてるですけど、見に行くの面倒くさいですよね。
というわけでSlackに定期的に通知するようにしました。

（公式でもっとイケてる手順があるなら知りたい）

## 全体像

Githubにあげてるので詳しくはそこ参照ください
https://github.com/takyam-git/cloudwatch-dashboard-notify-slack

## できること

こんな感じのをLambda経由でSlack通知できるようになります。

![Slack | develop | タノム 2020-10-13 21-48-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3865/28ef9a78-6f8d-97cf-f30f-f3b00e184793.png)

## 内容

Lambda5千年ぶりくらいに書いたから、最近のプラクティスに添えてない可能性がすごいでかいですが、ポイントは以下

- CloudWatchの画面からsourceをコピペってくる
- 画像をAWS SDK経由で取得する
- 結合する
- Slackになげる

## CloudWatchの画面からsourceをコピペってくる

通知したいCloudWatchダッシュボードの「アクション」を押すと「ソースを表示/編集」ってのがあって、
そこに現在設定されてる内容がJSONで取得できますです。

このJSONの `widgets[].properties` をSDKに投げると画像を返してくれる感じです。

![CloudWatch Management Console 2020-10-13 22-05-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3865/40497bf2-b17e-1230-c8cf-1c8c1d325964.png)

![CloudWatch Management Console 2020-10-13 22-07-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3865/177bf2c6-0f6a-a580-cae6-fd9fb2edd29f.png)


## 画像をAWS SDK経由で取得する

```js
const AWS = require('aws-sdk')
const source = require('./source.json')
const cloudwatch = new AWS.CloudWatch()

// 同じディレクトリにある source.json をもとにWidgetを取得する（後述）
const promises = source.widgets.map(async props =>
  cloudwatch
   .getMetricWidgetImage({
      OutputFormat: 'png',
      MetricWidget: JSON.stringify({
        ...props.properties,
        start: '-P14D', // 2週間レンジで取得
        timezone: '+0900' // JSTに変更
      })
    })
    .promise()
)
const imageBuffers = (await Promise.all(promises)).map(result => result.MetricWidgetImage)
```

さっきコピペしたJSONを `cloudwatch.getMetricWidgetImage()` にぶん投げると、いい感じにとれます。
APIの詳しい情報は https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_GetMetricWidgetImage.html この辺参照してください。

ここまでがCloudWatch周り。

## 結合する / Slackになげる

- 1ポストで全画像投げたかったので、 [merge-img](https://www.npmjs.com/package/merge-img) ってのを使って結合しました（なんでもいいと思います）
- SlackSDK経由でfile.upload API叩いてSlack通知します

（詳しくはgithubの方みてください）

## おわり

ローカルで実行できたら、適当にLambdaのセットアップして、EventBridge設定しておしまいです。
特に数叩かれるわけでもないので、タイムアウト1分、メモリ512MBみたいなリッチな感じで設定してます。
停まれ標識検知　可視化部分の開発part3 物体を検知した時にソケット通信を使って音声で知らせる

## 前回まで
前回は,socket通信を使って記録する部分までを書いていきました.今回はsocket通信をした後に音声を使ってお知らせする部分まで作っていきたいと思います.
※今回は正直あんまり中身がありません.ちなみに今回はスマホを検知した時に限定して書いています
## 今回実装した機能
Yolov5上で物体を検知した時➡ソケット通信をする.➡ソケット通信を受けたときに音声を再生する.
※ただこれだけをやっています.本当は場合分けでこれが来たらこれっていうプログラムが書きたいなぁと思っているので次回以降書いていきたいと思っています.


クライアント側

```detect.py
                    if label1=="chair":
                     print("椅子を検知しました.")
                     with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s2:
                         s2.connect(('127.0.0.1', 50007))
                         s2.sendall(b'isukenti')
                         data = s2.recv(1024)
```
※クライアント部分は前回同様です.
サーバ側

```server.py
from playsound import playsound
import socket

# AF = IPv4 という意味
# TCP/IP の場合は、SOCK_STREAM を使う
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # IPアドレスとポートを指定
    s.bind(('127.0.0.1', 50007))
    # 1 接続
    s.listen(1)
    # connection するまで待つ
    while True:
        # 誰かがアクセスしてきたら、コネクションとアドレスを入れる
        conn, addr = s.accept()
        with conn:
            while True:
                # データを受け取る
                data = conn.recv(1024)
                if not data:
                    break
                #print('data : {}, addr: {}'.format(data, addr))
                conn.sendall(b'Received: ' + data)
            playsound('2.wav')
                
                # クライアントにデータを返す(b -> byte でないといけない)
                
```
※これらのコードは全部もしくは一部を載せています.
###音声部分
基本的には,playsound()を使って音声を再生しているだけです.
```pip install playsound
```
音声作成はこちらを使っています.
https://w.atwiki.jp/softalk/
## 次回へ
次回はもう少し中身のある話を書いていけたらいいなと思っていますが,実装したことはそのまま載せたいので中身がない記事になってしまうときもあります.ごめんなさい.
次回は,物体ごとに音声を場合分けするプログラムを書いていきたいなと考えていますのでよろしくお願いします.
## 実際に動いている動画
https://youtu.be/ua45mDZaiJM
SElinuxってよく無効にされてるけど何？

## 勉強前イメージ

一旦何も考えず構築するサーバはoffにするって感じ。
セキュリティのなにか？
よく簡単にwebサーバ立ててアクセスしたらselinuxに弾かれてることある

## 調査

### Selinux とは？

Secure-Enhanced Linux の略
強制アクセス制御(MAC:Mandatory Access Control)と呼ばれるセキュリティを強化する機能である。
アメリカ国家安全保障局(NSA)が提供しているセキュリティ用のモジュールになります。
基本的には、Linuxをインストールすると最初からONになっている

元々Linuxではすべての権限がrootでは許可されており、root権限が何者かによって変更されると致命的な被害が及びことがあった。
SElinuxで`Type Enforcement(TE)` と `ロールベースアクセス制御(RBAC)` で制御を行うことによってrootにも制限をかけることができ、被害を少なくなるように設計されている

### Type Enforcement(TE) と ロールベースアクセス制御(RBAC)

- Type Enforcement(TE) 
	- プロセスがアクセスできる場所を制限できる機能
	- `プロセス : ドメイン` , `リソース : タイプ`　を割り当てて読み書きに対して制限をかける仕組み。
	- アクセス権の設定は`アクセスベクタ`と呼ばれる

- ロールベースアクセス制御(RBAC)
	- ユーザがアクセスできる場所を制限できる機能
	- ユーザごとにアクセスできるロールが決まっており、ロールごとにアクセス可能なドメイン(プロセス)が決まっている
	- TEによってドメイン(プロセス)ごとにアクセス可能なタイプ(リソース)が決まっているので、ユーザのアクセス制限が行える



### 動作モード(enforcing/permissive/disabled)

- enforcing
	- SElinux有効になっている。
	- ルール以外の動作があれば止める
- permissive
	- SElinux有効になっている。
	- ルール以外の動作があっても、止めずにログに記録のみ行う。
- disabled
	- SElinux無効になっている。
	- ルール以外の動作があっても、止めないしログに記録も行わない。

### 動作モードの確認

- 確認方法

```
# getenforce
```

### 動作モードの変更方法

#### 一時的に変更(再起動すると設定は元に戻る)

- 確認

```
# getenforce 
Enforcing
```

- 変更

```
# setenforce Permissive
```

- 確認

```
# getenforce 
Permissive
```

#### 永久に変更(再起動しても元に戻らない)

- 確認

```
# getenforce 
Enforcing
```

- 変更

```
vi /etc/selinux/config
==========
SELINUX=enforcing
==========

もしくは

cat /etc/selinux/config | sed -e s/^SELINUX=enforcing/SELINUX=disabled/
```

- 確認

```
# getenforce 
Disabled
```

## 勉強後イメージ

そもそもrootもあまり権限持たないようにしようねって思考ってことかな？
プロセスについてもアクセスができないようにしようねってことか。
今回は簡単にしか調べられなかったけど、結構面白そう。

## 参考

- [【ざっくりと理解する】SELinuxとは？](https://eng-entrance.com/linux-selinux)
- [【図解/初心者向け】SELinuxとは？〜仕組みやメリット・効果の基礎入門解説〜](https://milestone-of-se.nesuke.com/sv-advanced/selinux/selinux-summary/)
- [強制アクセス制御（SELinux）の基礎](https://thinkit.co.jp/article/13296)
- [理由がわかれば怖くない！SELinux とのつきあい方](https://blog.fenrir-inc.com/jp/2016/09/selinux.html)
- [SELinux を使おう．使ってくれ．](https://qiita.com/chi9rin/items/af532d0dd9237cc65741)
- [SELinuxとは](https://www.designet.co.jp/faq/term/?id=U0VMaW51eA)
オカンが応用情報のストラテジの単語を思い出せないそうです

A：オカンが最近応用情報の勉強してるらしいのよ。

B：おう、それはいいね。応用情報技術者試験といえば、ITエンジニアとして応用的な知識・技能を有することを国が合格者に対して証明する試験や。IT庁の設立が叫ばれる昨今役に立ちそうな資格やないの。

A：IPAのサイトから持ってきたような説明ありがとう。でストラテジの勉強をしてるんやけど、そのある単語を忘れたらしくてね

B：そうかー。試験もうすぐやのに忘れてたらあかんやん。

A：で答え出したろうと色々聞くんやけど、全然分からへんねん。

B：分からへんの？いや、ほな俺がね、その忘れた単語ちょっと一緒に考えてあげるから、どんな特徴ゆうてたかってのを教えてみてよ

A：経営戦略とITを絡めた全体最適化によって、顧客ニーズをはじめとする社会環境や情報技術自体の変化に素早く対応するための構造のことや言うねんな。

B：おー、そりゃ「エンタープライズアーキテクチャ」やないかい。

A：「エンタープライズアーキテクチャ」やなあ。でもこれちょっと分からへんのよ。

B：何が分からへんのよー

A：おれも「エンタープライズアーキテクチャ」やと思うてんけどな、強み、弱み、機会、脅威の4つのカテゴリーで要因分析する言うねんな。

B：じゃあ「エンタープライズアーキテクチャ」違うか。「エンタープライズアーキテクチャ」は4つは4つでもビジネス、データ、アプリケーション、テクノロジー、という4つの体系で分けられるんや。

A：そやねん

B：強み、弱み、機会、脅威の4つのカテゴリーで要因分析するなら「SWOT分析」ちゃうか？事業環境変化に対応した経営資源の最適活用を図る経営戦略策定方法の一つやで。

A：おれもそんなら「SWOT分析」」やと思うてんけどな。

B：違うんかいな。

A：オカンがいうには「市場成長率」と「市場占有率」の2軸からなる座標に事業や製品・サービスを分類し、経営資源の投資配分を判断するための手法言うねん。

B：じゃあ分析は分析でも「PPM分析」やないか。市場成長率を縦軸、相対的市場シェアを横軸に花形、金のなる木、問題児、負け犬の4つのフェーズに対応させる分析やろ。
　4つは4つでも全然違うやないか。四国と四十九日くらい違うやないか。

A：「PPM分析」やないかという話もしたんや。

B：まだ違うんかい！

A:オカンがいうには、思い出されへん単語はアルファベット3文字で、ソフトウェアの機能とサービスをネットワーク上で連携させて大規模なコンピューターシステムを構築する手法らしいねん。

B：じゃあSOA、サービス指向アーキテクチャやないか。

A：製品（商品）・サービスを市場に投入してから、市場から消えるまでの需要の寿命を指すプロセスでもあると

B：それはPLC（プロダクトライフサイクル）！

A：企業の目標を達成するために、企業活動や組織構造、業務フローを再構築することだったり、

B：それはBPR（ビジネス・プロセス・リエンジニアリング）！

A：BPRには継続的な改善が無いから違うと、

B：じゃあBPM（ビジネス・プロセス・マネジメント）！
　企業戦略と業務プロセスとの整合を取りながら、業務プロセスを分析、かつ最適化し、継続的改善サイクルを確立・運営する包括的な手法や！

A：供給側から最終消費者へのプロセスを統合的に見直し、効率化を実現するための経営管理手法だとも

B：それはSCM（サプライチェーン・マネジメント ）！

A：企業経営のベースとなるヒト・モノ・カネ・情報という資源要素を的確に仕分けし、有効に活用する考え方かも

B：ERP、エンタープライズリソースプランニング！ERPとSCMは混同しがちだから気を付けや！
　SCMは生産、調達、販売といった製品供給の物流部分に対する管理が中心、ERPは企業内のすべての部門のデータを管理するで！
　もう、なんやねん。何が来たって正解なんてないやろ！

A：んでオトンが言うにはな

B：オトン？

A：ブルートフォース攻撃ちゃうか？って言うねん

B：いや絶対ちゃうやろ、そりゃセキュリティ関連の用語や。もうええわー

A＆B：ありがとうございましたー

※あくまでネタなので各用語に対して正しく説明できているかは保証できません！

こちらのサイトで資格試験やゲーム開発関連の話を書いています
■ゲームプロマネのブログ
https://game-pm.com/
【Udemy Python3入門+応用】　 65. 例外処理

**※この記事はUdemyの
「[現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル](https://www.udemy.com/course/python-beginner/ "現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル")」
の講座を受講した上での、自分用の授業ノートです。
講師の[酒井潤](https://twitter.com/sakaijun "酒井潤")さんから許可をいただいた上で公開しています。**

##■例外処理
####◆基本
```python
l = [0, 1, 2]
i = 5

try:
    print(l[i])
except:
    print('Error!')
```
```:result
Error!
```
`try:` の中に書いたものを実行しようとし、それが何らかのエラーにより実行できなかった場合、
`except:` 内の処理が実行される。
<br>

####◆エラーの種類の指定
```python
l = [0, 1, 2]
del l

try:
    print(l)
except IndexError as ex:
    print('Error massage: {}'.format(ex))
except NameError as ex:
    print('Error massage: {}'.format(ex))
```
```:result
Error massage: name 'l' is not defined
```
`IndexError` だったらこの処理、
`NameError` だったらこの処理、といったようにエラーの種類の指定もできる。
<br>

####◆finally:
```python
l = [0, 1, 2]
i = 5

try:
    print(l[i])
except:
    print('Error!')
finally:
    print('clean up')
```
```:result
Error!
clean up
```
`finally:` 内に書いた処理は、tryが成功しようが、exceptとなろうが、必ず実行される。
<br>

```python
l = [0, 1, 2]
i = 5

try:
    print(l[i])
finally:
    print('clean up')
```
```:result
clean up
Traceback (most recent call last):
  File "/~~~", line 5, in <module>
    print(l[i])
IndexError: list index out of range
```
したがって、実際エラーが起きてしまった場合でも、`finally` 内の処理が先に実行され、その後エラーでプログラムが停止することになる。
<br>

####◆else:
```python
l = [0, 1, 2]

try:
    print(l[0])
except:
    print('Error!')
else:
    print('done')
```
```:result
0
done
```
`else:` を使うと、 `try:` 内の処理が成功した場合のみ、 `else:` 内の処理が実行される。
ちゃんと動いているのになぜ？React・Redux編

ちゃんとユーザーのアクションは取れているのにStoreが更新されない、Storeからデータが取れないなんてことになったことはないですか？

自分はあります、2日間くらい悩んでReact・Reduxの勉強やめたくなりましたが、なんとか解決することができ、React・Reduxの世界へ戻ってくることができたのでその時のお話をしたいと思います。

# mapStateToPropsでちゃんと設定しているのに...
mapStateToPropsを利用してコンポーネントにStoreのデータを反映させようとしていた時のことです。
**stateがundefinedになってんじゃん！**

ずっとこれでした、2日間。。。

なんでかという原因と解決策はこちらです。

<dl>
  <dt>原因：</dt>
  <dd>AppState（store本体のinterface）のプロパティ名と、mapStateToPropsで渡すときのプロパティ名が異なっていたため。</dd>
  <dt>解決法：</dt>
  <dd>AppStateのプロパティ名とmapStateToPropsで渡すときのプロパティ名を確認し、合わせるようにする。</dd>
</dl>

これだけです。
要は、受け取る側（mapStateToProps）と保存(Store)している側で、異なる名前をつけていたのでundefinedになっていました。
しかも自分がやっていたのはプロパティ名が単数形か複数形かの違いでこれにハマってました。

そのほかにも**Reactはファイルやコンポーネント、プロパティの命名でエラーになることがあるので、コード本体の間違いはもちろん、正しい名前をつけることができているかを確認する**ことを意識して開発したいと思わされた出来事でした。
VS code ショートカットキーのまとめ

- Alt + ↑ ↓　でカーソル位置の行ごと移動できる。
- Fn + ← →　で行頭や行末にカーソルを移動できる。
- Ctrl + Shift + L　で同じ単語をまとめて編集可能になる。
- Alt + Shift　行ごとコピーできる
blade構文

【概要】
----------------------------------------
<b>1.値</b>

<b>2.条件分岐ディレクティブ</b>

<b>3.繰り返しディレクティブ</b>

<b>補足(i)</b>

<b>補足(ii)</b>




1.値
----------------------------------------

```php
{{***}}
```
{{}}の中身は値だけでなく、変数・関数なども使用できます。HTML文でエスケープ処理されたくない時は、下記のように使用します。

```php
{{!! !!}}
```

<br>
2.条件分岐ディレクティブ
----------------------------------------

```php
@if (条件式)
//内容
@elseif (条件式)
//内容
@else
//内容
@endif
```
また@ifの逆の@unless-@endunlessもあります。

<br>
3.繰り返しディレクティブ
----------------------------------------
**for**

```php
@for(初期値 ; 条件 ; 処理) #例:@for($i=0 ; $i<=10 ; $i++)
//内容 #例:echo $i;
@endfor
```
また@breakは繰り返し処理の中断、@continueはcontinue以降は表示せず@forの繰り返し処理を引き続き行います。


**foreach**

```php
@foreach ($配列 as $変数)
//内容
@empty　#--❶
//変数が空の時の内容
@endforeach
```
❶については記載しなくてもOKです。@ifでいう@elseにあたります。

**while**

```php
@while (条件)
//内容
@endwhile
```

<br>
補足(i)
----------------------------------------
3.の繰り返しディレクティブには、$loopというループ変数があり、繰り返し処理のプロパティとして使用することが可能です。

```php
@foreach($category as $item)
 @if ($loop->first) #---❶
  <h1>アイテム一覧</h1>
  <ul>
 @endif
  <li>No.{{$loop->iteration}}.{{$item}}</li> #---❷
 @if ($loop->last)  #---❸
  </ul>
 @endif
@endforeach
 
```
❶：loop->firstは、最初の繰り返しならtrueを返します。
❷：loop->iterationは、1から順番に繰り返し、その回数を返します。
❸：loop->lastは、最後の繰り返しならtrueを返します。

<br>
補足(ii)
----------------------------------------
index.phpファイルとindex.blade.phpファイルが同じviewフォルダの中の指定のフォルダに入っていたとします。その時に、controllerにある”return view('＠@@@.index' , $@@@@)'はLaravelでは'index'としてした場合はindex.blade.phpファイルが優先して読み込まれます。
<br>
なぜAndroidエンジニアは少ないのか

# はじめに

まずはこちらのツイートをご覧ください
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">(駆け出しエンジニアのみなさん、モバイル開発は結構穴場ですよ…<br>今のところはかなり需要ありますし、供給が足りてないのでかなり狙い目ですよ…<br>とくにAndroidエンジニアは人足りてないので、狙い目ですよ…<br>Kotlin楽しいですよ…<br>みなさん、Android始めませんか？)</p>&mdash; どすこい@Android Engineer (@dosukoi_android) <a href="https://twitter.com/dosukoi_android/status/1315506547829559296?ref_src=twsrc%5Etfw">October 12, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

普段通り思ったことを呟いた結果、なぜか見事にプチバズりしました。
これにはかなり賛否両論あって、自分的にもかなり学びになったので自分の意見とみなさんの意見をまとめていきたいと思います。

# Androidユーザーが少ない
個人的にはこれが一番大きいと思います。
しかし調べてみると、iOSとAndroidの割合は6:4くらいなのです。(このAndroidにFireOS, HUAWEI OSを含むかは不明)

あれあまり大差ないじゃん！とか思ったんですが、恐らく若者、特に10代〜20代のシェアだけ見ると7:3、もしくは8:2くらいにはなるんでしょうね

僕の周りにはAndroidはダサい、古いみたいな考えを持っている人も少なくなく、こう言ったことがAndroidユーザーが増えない理由なんだと思います

# Javaを学ぶかKotlinを学ぶか迷う
僕がAndroidを学び始めたのは2018年
KotlinがAndroidの公式言語になったのは2017年のGoogle I/Oなので、情弱だった僕がAndroidを学び始めた頃はKotlinの存在すら知りませんでした。

ですが現在はKotlinの日本語のリファレンスも増えたり、推奨されることも多いのでKotlinから学び始めることも多いかと思います。
しかしKotlinはAltJavaなので、Javaから学ぼうかそれとも流行っているのでKotlinから学ぼうか悩んでしまう方も少なくないのかもしれませんね。

# ライブラリがたくさん
こんな意見もありましたね。

これに関しては半分納得、半分疑問という感じです。
というのもJava自体ライブラリがたくさんありますし、Androidの標準APIもかなり豊富です。
去年出たJetpackだけでも数えられないくらいのライブラリがたくさんあります。

しかしこれはiOSにも言えることです。しかもiOSは標準のライブラリではなくサードパーティのライブラリがめちゃくちゃあります。
Androidはほぼ公式のライブラリだけで完結するので個人的には楽なんですけどね、、


# 育つ環境がない
この意見が一番多かったです。

確かにその通りだと思います。
実際、弊社のAndroidエンジニアは誰かに教わった経験やスクールに入った経験がありません。

しかし育つ環境がないのはiOSも同じなのでは、、？という疑問を抱きました。

ですが後述する意見を見ると納得するかもしれません

# コミュニティが少ない、活発じゃない
僕自身、あまりコミュニティや勉強会などに参加したことがないので、あまり感覚的にわかりませんがこういった意見もありました。

iOSでいうとiOSDCみたいなイベントはないのかなぁと思いましたが、AndroidではDroidkaigiがありますし、個人的にはあまりしっくり来ませんでした。

# リファレンスが少ない
恐らく育つ環境が少ないに直結する理由がこれだと思います。

というのもAndroidは海外ではiOSよりもシェアが高いのでリファレンスがあるので、Androidエンジニアは多いのですが、如何せん僕らは日本人。
英語のリファレンスを嫌う人は山ほどいます。

Androidの日本語のリファレンスが少ないからAndroidエンジニアが増えない、Androidエンジニアが増えないから日本語のリファレンスも増えない


### あれ？？これって卵が先か鶏が先かみたいな話になってきませんか、、、？


# 結論
### わかりません！！

Kotlinはイケてますし、GoogleとJetBrainsはたくさんお金かけてくれてますし、かなり需要も高いと思います。
弊社の場合ですが、アプリの案件があれば必ず両OSのアプリも作ります。恐らくどの会社もそうだと思います。
なので同じ数のアプリエンジニアが必要な中、Androidエンジニアが足りていないというのは駆け出しエンジニアさんたちにとってもかなりお勧め出来るんですけどね、、、笑

意見を下さったみなさん、ありがとうございました！！


# 余談

バズらせるつもりのなかったツイートがバズるのは結構びっくりしますね笑
僕はツイートがバズるのが初めてだったのでちょっと焦りました
React + TypeScriptで Firestoreを使ったアプリケーションを開発する

Reactを勉強するにあたり、どうしてもTypeScriptを使用したかった筆者が勉強するのに結構苦労したところです。参考記事が少なく、結構苦労しました。firebaseとReactの連携に関してはこのやり方が絶対正しいというわけではないと思いますので、手段の１つだと思って読んでいただきたいです。

**本記事はReactがなんとなくわかっていて、Reduxなどもだいたいわかるよって人向けだと思います。さらに本記事で触れるのはFirestoreとReactアプリケーションの接続部分になりますので細かい設定の説明は吹っ飛ばしてます**

# Reactのセットアップ
以下のコマンドでアプリを作ります。
（この辺りの仕組みを筆者はあまりよく理解していないですが、このコマンド打てばReactのTypeScriptベースのアプリケーションの雛形が作れるんだなーって思ってます。）

```
npx create-react-app {作成するアプリケーション名} --typescript
```


# Firebaseのセットアップ

FirebaseのFirestoreというRDB（リレーショナルデータベース）のサービスを利用します。大量に使わない限りは基本無料なので良いです。
firebaseに関しての設定は以下の記事を参考に進めてみてください。
[React + TypeScript + Firebase環境を超高速で作る](https://qiita.com/magaming/items/6ee5318c581d34c4c932)
※ この記事は```yarn```でインストールしてますが、```npm```でも問題なくできます。


# React と Firebase どうやってデータやり取りするの問題
かなり悩んだところです。この記事に出会っていなければわからずじまいだったでしょう。
[React/Redux/redux-saga/TypeScript/Cloud Firestore/Cloud Functionあたりを使ってブログを作った！](https://qiita.com/katsuomi/items/f3e92aecc45b37ab08bb)

なんとこの記事、GitHubリポジトリを公開しています。（ありがたすぎました）
GitHubのコードを苦労しながら時間をかけて読み解いていくと、こんな感じの流れになっているんだなーというのがつかめてきました。

1. APIと名の付いたファイルでfirebaseとの通信を実行するプログラムを書いておく
2. redux-sagaを利用してユーザーの特定のアクションを待ち構える
3. アクションを検知したredux-sagaがAPIを呼び出してFirebaseとStoreデータを更新する
4. ReactのStoreデータが更新されるのでビューも更新される

ざっくりこのような流れです。
なので、
```APIファイル群``` → ```sagaファイル群``` の順でみてもらうと大体の流れが掴めると思います。

# お前この記事で何もやってねーじゃん
すみませんやってません。とりあえず、投稿したかったので。
ただこの辺りに関しては参考記事が少ないので、近いうちにしっかりパートを分けて記事化しようと思います。
```TypeScript + React + Redux + Firebase```の記事が少ないので勉強するのに困った経験があるので。

```TypeScript + React + Redux + Firebase```を勉強したい方におすすめの記事を最後に貼って終わりにします。

1. [React + Redux + TypescriptでサンプルWebアプリ](https://qiita.com/makishy/items/857bb838a2910eb34da3)
これでTypeScriptベースのReactアプリケーション作成の基礎を学びます

2. [たぶんこれが一番分かりやすいと思います React + Redux のフロー図解](https://qiita.com/mpyw/items/a816c6380219b1d5a3bf)
Reduxというものを学びます（Reactというフレームワークが提供しているデータフロー）

3. [TypeScript で Redux DevTools extension を使う](https://qiita.com/AshSuzuki/items/111d5a7c5d30fd1123c3)
Reduxも使えるようになってきたらデバッグできるようにしておきましょう。開発が捗ります。

4. [React+Redux+typescript+firebaseで認証機能作るのが辛い①](https://qiita.com/teshima/items/8ccf41cf7e297a6489e0)
Fireabseを利用して、アプリケーションに必須なログイン機能をつけてみましょう。
同時期にFirestoreとかもさわれたら尚良いです。

5. [redux-sagaで非同期処理と戦う](https://qiita.com/kuy/items/716affc808ebb3e1e8ac)
firebaseを利用できるようになったらログインだけでなく、CRUDな処理をFirestoreを利用して実装するために必要です。redux-sagaとはアプリケーション上の処理（タスク）の概念をReduxに持ち込むためのもの（MiddleWare)です。
ここを理解するのに少し時間がかかるかもしれませんが、わかってしまえばパターンなので頑張りましょう。

6. [Material-UI と styled-components を組み合わせて、React のサイトを怠惰にスタイリングする。](https://qiita.com/Ouvill/items/c6761c32d31ffb11e114)
なるべく簡単にレイアウトを作成する方法ですmaterial-uiを利用してスタイリングの手間を省きながら、綺麗なUI、レイアウトを目指しましょう
【Unity】NRSDK1.3.0のInput-VirtualControllerシーンを読んでみる（Inputシーン編3/3）【Nreal】

##はじめに

##Input-VirtualControllerシーンについて

![スクリーンショット 2020-10-08 19.57.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/301a01de-d012-035b-98a2-401dfeb6fd46.png)


##シーン構成
|シーン構成|
|:-----------|
|NRCameraRig|
|NRInput|
|Directional Light|
|TargetModelDisplayCtrl|
|[Tip:----------------------------]|
|[Drag " NRVirtualDisplayer" Prefab Here]|
|[Then Breake Prefab Instance And Make]|
|[Your Custom Virtual Controller. ]|
|CustomVirtualDisplayer|

##NRCameraRig、NRInput
Nrealに対応したカメラ、入力システム
別のサンプルシーンで読んでます。
[NrealSDK1.3.0のHelloMRシーンを読んでみる](https://qiita.com/y-mic/items/508c5a3e6cbdc9a20f86)

##Directional Light
Unity製のライト。

##TargetModelDisplayCtrl
##[Tip:----------------------------]
このオブジェクト以下はTipを記載しているらしい。
読んでみよう。

>Drag " NRVirtualDisplayer" Prefab Here
Then Breake Prefab Instance And Make
Your Custom Virtual Controller. 

NRVirtualDisplayerのプレハブをHierarchyにドラッグして
カスタムの仮装コントローラーを作れるらしい
(既存のNRVirtualDisplayerに同期されてしまうので、プレハブ化を無効にするってことですね)

###え、便利！！

もう少し理解するため、公式ページを覗いてみた。
以下Nreal公式リファレンス引用

>Nreal電話コントローラーの優れた点の1つは、UIインターレースを簡単にカスタマイズできることです。Nreal電話コントローラーを使用する2つの方法は次のとおりです。

>・デフォルトの方法 「NRInput」プレハブをシーンにドラッグするだけです。次に、デバイスでアプリを実行すると、デフォルトの仮想コントローラー（ "NRVirtualDisplayer"プレハブ）が自動的にロードされます。3つの一般的なコントローラーボタン（トリガー、ホーム、アプリ）があります。この仮想コントローラーは、NrealLightコントローラーと非常によく似ています。

>・カスタム方法 「NRInput」プレハブをシーンにドラッグします。次に、「NRVirtualDisplayer」プレハブをシーンにドラッグし、必要に応じて変更します。たとえば、アプリケーションに合わせて、いくつかの新しいボタンを追加したり、コントローラーUIのスタイルを変更したりします。

引用：https://developer.nreal.ai/develop/unity/customize-phone-controller

Nreal Lightでは、グラスにスマートフォンをコントローラーとして接続するので、それに使うようです。
デフォルトだと、2つのボタンとタッチ、ドラッグを検出する場所のみなので、
その他必要なUI等をカスタムできると、、、そういう話か。

##CustomVirtualDisplayer
カスタムされたコントローラーを子に持つオブジェクト

|スクリプト名|役割|
|:-----------|:-----------|
|NRVirtualDisplayer|NRInputクラスのEmulateVirtualDisplayInEditorの結果によって、仮装コントローラーの表示を行なっていたり、タッチした座標の更新を行なっている。各ボタンの状態はMultiScreenControllerで管理して流している。プレハブ内にあるBaseControllerPanelがデフォルトのコントローラー|
|CustomVirtualControlerUI|これがカスタムした仮装コントローラー。VirtualDisplayerの子にUIを配置することで、コントローラーを作ることができる。|

サンプルシーンにあるカスタムコントローラーの例
![スクリーンショット 2020-10-13 21.46.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/1f2be1f9-f330-0a5e-8bc1-973f7c99412e.png)

各色でNrealのロゴの色を変更
スライダーで大きさの変更
Resetボタンはそのままリセットって感じで。

簡易的ながら、UIを複数配置できるのはいいですね。

#Nreal Developer Kit で実行してみた

ロゴが一つ浮かんでた。
![S__647174.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/e0825708-1752-031b-5c28-b018b42dfebb.jpeg)

コントローラーを指でタッチしながら、黄色矢印方向に動かすとロゴが回転する仕組み
![S__647173.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/9947475f-59cd-1361-e654-2aa66402576b.jpeg)

![S__647176.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/e3f8a004-d8c3-0c80-b76a-ae8f8c0c9288.jpeg)

Developer Kitでは何も変化がないですね（NrealLight買うか、、

##まとめ
UIの処理のみで仮装コントローラーが作れるのは大変ありがたいです！
とすると、Developer KitよりNreal Lightを買ったほうがより良いショートカットなどを作れて大変便利なのでは！？
NRVirtualDisplayerはUnityEditor上で確認できるのでDeveloper Kitでもよく使うことになると思います。

##さいごに
NrealのInputが一通り理解できました。
最近(2020/09末)NRSDKが更新され、Inputで取得できる情報が追加されたようですね
（今後も増えていくのだろうか）
今後も更新を追いかけつつ、Nrealに関する記事を投稿していきたいと思います。
Rubyで三角形を出力

本日授業で初めてRubyとやらを触ったので記念に記録。
○の出力のみで以下のような三角形をつくるという問題。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;○
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;○○○
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;○○○○○
&nbsp;&nbsp;&nbsp;○○○○○○○

```
n = gets.to_i #入力

for x in 1..n
    (n-x).times{print(" ")} # 空白の数はn-1した数から1段につき1つずつ減っていく
    for y in 1..2*(x-1)+1 # ○の数は2*(x-1)+1
        print("○")
    end
    puts
end
```
はじめに、丸の左側にできている空白を出力し、それに続いて丸を出力する処理をします。そして、丸の出力が終わったらputsで改行をするという流れでプログラムを書きました。
左側にできる空白の数は一段目はn-1であり、それ以降-1されていきます。
○の数は、2(x-1)+1で求められます。
以上をプログラムに落とし込むと、無事、出力ができました。

やはり言語が違えば仕様も違うので戸惑いますが早く慣れていきたいです
pandasで欠損値nanじゃないデータを抽出する方法

- 環境
    - macOS Catalina バージョン10.15.7
    - Python 3.8.5
    - pandas 1.1.3

# 抽出元のデータはこんなかんじ

```py
df = pandas.read_csv('CSV.csv')
print(df)
```

```bash:出力
     名前  回数     開始     終了
0  ぽんすけ   1   9:00  18:00
1  ぽんすけ   2  18:00    NaN
2  ぽんすけ   3   9:00  13:00
3  ぽんすけ   4    NaN    NaN
4  ぽんすけ   5   9:00    NaN
5  ぽんすけ   6  18:00    NaN
6  ぽんすけ   7  12:00    NaN
7  ぽんすけ   8  12:00    NaN
8  ぽんすけ   9    NaN  18:00
9  ぽんすけ  10    NaN    NaN
```

# 1つのカラムがNaNじゃないデータを抽出する
|抽出したい<br/>データ|開始|終了|
|:-:|:-:|:-:|
|x|NaN|NaN|
|o|NaNじゃない|NaN|
|x|NaN|NaNじゃない|
|o|NaNじゃない|NaNじゃない|

```py:方法
# [開始]カラムがNaNのデータを削除する方法
print(df.dropna(subset=['開始']))
# [開始]カラムがNaNではないデータを抽出する方法
print(df[df['開始'].notna()])
# [開始]カラムがNaNではないデータを抽出する方法
print(df.query('開始.notna()', engine='python'))
```

```bash:出力
     名前  回数     開始     終了
0  ぽんすけ   1   9:00  18:00
1  ぽんすけ   2  18:00    NaN
2  ぽんすけ   3   9:00  13:00
4  ぽんすけ   5   9:00    NaN
5  ぽんすけ   6  18:00    NaN
6  ぽんすけ   7  12:00    NaN
7  ぽんすけ   8  12:00    NaN
```

# 2つのカラム両方NaNじゃないデータを抽出する
|抽出したい<br/>データ|開始|終了|
|:-:|:-:|:-:|
|x|NaN|NaN|
|x|NaNじゃない|NaN|
|x|NaN|NaNじゃない|
|o|NaNじゃない|NaNじゃない|

```py:方法
# [開始]または[終了]カラムのどちらかがNaNのデータを削除する方法
print(df.dropna(subset=['開始', '終了']))
# [開始][終了]カラム両方がNaNではないデータを抽出する方法
print(df.query('開始.notna() & 終了.notna()', engine='python'))
```

```bash:出力
     名前  回数    開始     終了
0  ぽんすけ   1  9:00  18:00
2  ぽんすけ   3  9:00  13:00
```

# 2つのカラムどっちかがNaNじゃないければデータを抽出する
|抽出したい<br/>データ|開始|終了|
|:-:|:-:|:-:|
|x|NaN|NaN|
|o|NaNじゃない|NaN|
|o|NaN|NaNじゃない|
|o|NaNじゃない|NaNじゃない|

```py:方法
# NaNを空文字にして[開始][終了]カラムをくっつけて空文字ではないデータを抽出する方法
print(df[df['開始'].str.cat(df['終了'], na_rep='') != ''])
# [開始][終了]カラムどちらかがNaNではないデータを抽出する方法
print(df.query('開始.notna() | 終了.notna()', engine='python'))
```

```bash:出力
     名前  回数     開始     終了
0  ぽんすけ   1   9:00  18:00
1  ぽんすけ   2  18:00    NaN
2  ぽんすけ   3   9:00  13:00
4  ぽんすけ   5   9:00    NaN
5  ぽんすけ   6  18:00    NaN
6  ぽんすけ   7  12:00    NaN
7  ぽんすけ   8  12:00    NaN
8  ぽんすけ   9    NaN  18:00
```

# 「1つのカラムがNaNじゃない」&「1つのカラムがNaN」のデータを抽出する
|抽出したい<br/>データ|開始|終了|
|:-:|:-:|:-:|
|x|NaN|NaN|
|x|NaNじゃない|NaN|
|o|NaN|NaNじゃない|
|x|NaNじゃない|NaNじゃない|

```py:方法
# [開始]カラムがNaNを抽出した後に[終了]カラムがNaNのデータを削除する方法
print(df[df['開始'].isna()].dropna(subset=['終了']))
# [開始]カラムがNaNではない かつ [終了]カラムがNaNのデータを抽出する方法
print(df.query('開始.isna() & 終了.notna()', engine='python'))
```

```bash:出力
     名前  回数   開始     終了
8  ぽんすけ   9  NaN  18:00
```
【Mac用】テキストエディタ用ショートカットキーまとめ（備忘録）

##記事制作背景

Atomコードを書いているときにいつも「あのショートカットってどんなっけ？」と
毎回調べ直していて非常に非効率なことをしていたので、
備忘録としてまとめることにしました。

###使用頻度の高い一般的なショートカットキーは敢えて載せません。

私の思う基準で「たまにしか使わないから忘れてしまいがちだけど、
使うとすごく便利な影の薄いショートカットキーたち」だけをまとめていきます。

command+Cでコピーとか王道のショートカットキーは多分載せていないので悪しからず。

###使用環境
・macbook pro
・Atom(テキストエディタ)

※別のOS・テキストエディタでは違う挙動をするかもしれないので
参考にならない可能性があります。ご了承ください

##テキスト用ショートカットキー一覧
command + D
　　ファイル内の同じ行の同じ単語を同時に選択できます。
　　繰り返し実行することで別の行にある同じ単語も選択可能です。
　　このショートカットキーを実行するとカーソルが
　　複数個になってしまいますが、escを押すと解除できます。

##順次更新していきます。
働き者だけど影の薄いショートカットキーを見つける度に更新していきます。

環境が同じなのに挙動が違ったり間違ってる箇所があれば
教えていただけると幸いです。
【経験談】エンジニアライフで苦労した経験

# 苦労した経験
システムアラートの受け取り方法をEメールから社内SNSで受け取れるようにシステムを変更したこと

**ASIS**
![スクリーンショット 2023-10-24 12.23.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377231/bee2342d-b92f-f64c-aaa3-f9539c0a7d33.png)
**TOBE**
![スクリーンショット 2023-10-24 12.29.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377231/d260149b-6693-65dc-866b-d9c4136f8f5a.png)

# なぜ苦労したのか

- 全ての工程（設計、環境構築、開発、テスト）を一人で行ったから。
- ポート番号やプロキシ、ネットワークのことでインフラチームの協力が必要であり、そのコミュニケーションに苦労したから。
- ネットワークに制約が多かったから。
- 作ったflaskアプリ自体が動いているかどうかのヘルスチェックのために、ジョブを定期実行させるためのパイプラインをJenkinsで作ったことがなかったから（初めてだったから）。

元々のアラートシステムは直接Eメールアドレスを指定するだけで通知できたが、そのシステムには他のSNSがアラートレシーバとしてサポートされていなかった。なのでWebhookを利用して既存システムからPOSTリクエストを飛ばし、それを別のウェブアプリで処理して最終的にSNSに通知するためのAPIを叩く設計にした。既存システム（社内）から直接SNS通知のためのAPI（社外）への接続はネットワークの制約で不可能なため、別に立てたウェブアプリ（社内サーバ）を経由させる必要があった。途中多くの壁にぶつかり、それを解決するために、理想と自分達が今置かれている状況を正確にインフラチームに理解してもらうためのコミュニケーションに一番苦労した。

# 学んだこと
これからどの仕事をしていてもインフラチームや外部チームの協力は必要なので、自分達が今どの状態であり、どうしたいかを正確に分かりやすく伝えることが円滑に仕事を進める上で重要だと思いました。
「Pythonで数字の桁数を取得する方法」を参考にして、WolframAlphaでやってみた。

(オリジナルポスト)Pythonで数字の桁数を取得する方法
https://qiita.com/RShirakawa/items/23f8f1d907dc40ebbdd2
(参考)常用対数を用いることで，大きな数の桁数を計算できます。<常用対数を用いた桁数と最高位の数の計算
https://mathtrain.jp/ketasu
#整数の場合：何かあやしい？
```
floor(log_10(abs(-12345)))+1
```
https://ja.wolframalpha.com/input/?i=floor%28log_10%28abs%28-12345%29%29%29%2B1


#小数の場合
だれか教えて下さい。
link_toメソッドのpathの引数、要る・要らない

#はじめに
アプリケーションを作るときに、いつもlink_toメソッドでエラーが出ていた。しかも、そのリンク先に飛ぶときではなく、link_toメソッドがあるページを表示させたときに、
`ActionController::UrlGenerationError`
このエラーが出ていて、悩まされた。いつも`○○_path`と、ルーティングを確認して記述するところまでは問題がなく、躓かない。ここに（　）で引数を渡すとなると、何を渡したらいいのか分からなくなっていた。

##引数がなくてもOKなパターン
　アプリケーションを利用する誰もが同じページに飛ぶ場合は引数がなくてもよい。ログインページやroot_pathのページがこれにあたる。

##やっぱりrails routesは便利だった

ターミナルでカレントディレクトリが作成中のアプリケーションのディレクトリで

```bash
% rails routes
```
を入力すると、ルーティングを教えてくれる。
pathの記述はもちろん、Prefixの部分を見る。しかし、
ここで着目すべきは、URI Patternの部分。ここで<font color=red>/:id</font>など、idがURIに含まれている場合は、引数を渡す必要がある。
:idとidがURIに含まれている場合は、引数に（user.id）などとすればよい。
また、引数によっては、.idを省略できる場合もある。
docker を用いてlaravel6+nuxt.js+mysql+nginx構築

#laravel6+nuxt.js+mysqlの構築 
laravel,mysql,nginxの構築は@simotarooさんの記事が優秀なのでこちらを参考にしてください
https://qiita.com/shimotaroo/items/29f7878b01ee4b99b951

本題に関係ないんですけどngixってエンジンエックスって読むんですね,,,(笑

#nuxt.jsの構築
@simotarooさんの記事で作成したdocker-compose.ymlに PORT:3000, HOST: 0.0.0.0を追加
理由としてコンテナで設定されているポート番号とnode.jsのポート番号が違うままだと繋がらないためです

```docker-compose.yml
#docker-compose.ymlのバージョン
version: '3.8'
#docker volumeの設定
volumes:
  docker-volume:

#services以下に各コンテナの設定を書く
services:
  #Webサーバーのコンテナ
  web:
    image: nginx:1.18
    ports:
      - '8000:80'
    depends_on:
      - app
    volumes:
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - .:/var/www/html
  #アプリケーションのコンテナ
  app:
    build: ./docker/php
    volumes:
      - .:/var/www/html
    environment:
      PORT: 3000 #追加
      HOST: 0.0.0.0　#追加
    ports:
      - 3000:3000
  #データベースのコンテナ
  db:
    image: mysql:5.7
    ports:
      - '3306:3306'
    environment:
      MYSQL_DATABASE: ######
      MYSQL_USER: #####
      MYSQL_PASSWORD: #######
      MYSQL_ROOT_PASSWORD: ##########
      TZ: 'Asia/Tokyo'
    volumes:
      - docker-volume:/var/lib/mysql
  
```

dockerfileに　RUN npm install -g create-nuxt-app を追加

```dockerfile:dockerfile
FROM php:7.2-fpm

#composerのインストール
COPY --from=composer:1.10 /usr/bin/composer /usr/bin/composer

#npmのインストール
COPY --from=node:10.22 /usr/local/bin /usr/local/bin
COPY --from=node:10.22 /usr/local/lib /usr/local/lib

#パッケージ管理ツールapt-getの更新と必要パッケージのインストール
RUN apt-get update \
&& apt-get install -y \
git \
zip \
unzip \
&& docker-php-ext-install pdo_mysql bcmath

RUN npm install -g create-nuxt-app #追加
#コンテナ内に入った時のディレクトリを指定
WORKDIR /var/www/html

```
追加後はdocker-compose buildし変更を反映

反映できたらdocker内で

```tarminal:tarminal
root@########:/var/www/html npx create-nuxt-app ディレクトリ名
```
で実行

```tarminal:tarminal
🎉  Successfully created project ディレクトリ名

  To get started:

	cd ディレクトリ名
	npm run dev

  To build & start for production:

	cd ディレクトリ名
	npm run build
	npm run start
```

成功したらこんな画面になります。
作成したディレクトリ内に入り,npm run devを実行後動作確認で以下のURLに入ってnode.jsの画面が出れば成功です
http://localhost:3000/ 
お疲れ様でした👏
サーブレットとは？

#サーブレットが理解できないのでまとめ
サーブレットって聞くけど理解できていないのでまとめる。
jboss,tomcatコンテナの違いもよく理解できていないのでまとめる。

#サーブレットとは
WEBサーバ（バックグラウンド上）で動作する。
javaプログラム。
javaプログラムなので実行環境が必要。
それが、サーブレットコンテナ。
また、サーブレットコンテ内でhttpを受け取り、サーブレットを動作させる。
　⚠️これが、get, post などの通信
　⚠️HTTPは、 「Hyper Text Transfer Protocol」の略のため
　　 javaによらずhttp通信が行われている。(phpとか)
　　 javaの場合httpRequestクラスを継承しhttpサーブレットを取得し使用している。
　　　

#サーブレットコンテナとは
javaサーブレットを動作させるための実行環境

例として

Apache Tomcat、JBoss Application Server、Apache Geronimo、Webspehere、Jetty

+ Apache tomcat (⚠️apacheとは異なる⚠️）（tomcatと省略される）
+ jboss(有償版をjoss,無償版をwildflyと呼んでいる。ともに、レッドハット社の製品）

#Aapacheとは
正式名称が(apache http server )
これはhttpサーバ。
つまり、javaのサーブレットコンテナではない。


#参考
https://qiita.com/yuji38kwmt/items/267d4ce618e80785f03d
https://qiita.com/7968/items/4bf4d6f28284146c288f
https://spring.pleiades.io/specifications/platform/8/apidocs/javax/servlet/http/HttpServletRequest.html
Herokuでスリープ防止のためにスケジューラを作成する

# 概要
Herokuのサイトは一定時間が経過すると、スリープ状態に入ってしまうため、次にアクセスする際にサイトが表示されるまで時間がかかるという問題が発生してしまいます。今回はそれを防止する方法について紹介します。

# herokuにスケジューラを追加
まずはアプリケーションフォルダ配下で下記コマンドを実行し、スケジューラのアドオンを追加していきます。

```
$ heroku addons:create scheduler:standard
```

下記のように表示されれば成功です。

```
Creating scheduler:standard on ⬢ <アプリ名>... free
 To manage scheduled jobs run:
 heroku addons:open scheduler

Created <スケジューラの名前>
Use heroku addons:docs scheduler to view documentation
```

# ジョブを作成する
続いて下記コマンドを実行して、ジョブの作成画面を表示します。

```
$ heroku addons:open scheduler
```

すると下記のような画面が表示されるはずです。

![WS000013.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469694/611dcba8-0e18-fa3c-c059-2a22b410577f.jpeg)

「Create Job」を押下します。

![WS000018.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469694/c9f3f04a-a2b0-7bed-ecf1-34f58d97f162.jpeg)

すると下記のようなウィンドウが表示されますので、

Schedule : Every 10 minutes
Run Command : curl <HerokuサイトのURL>

を入力し、「Save Job」を押下します。
これでジョブの作成は完了です。後は時間をおいてもう一度サイトにアクセスしてみると、表示が遅い問題が解消されているはずです。

参考：[herokuを24時間稼働させる設定](https://yukitoku-sw.hatenablog.com/entry/2020/02/04/225151)
VSCodeでHandlerbarsファイルをPrettierプラグインでフォーマットする

https://github.com/prettier/prettier/issues/5340#issuecomment-442576237

ここに書いてある通り、PrettierをGlimmerパーサー指定して起動することでフォーマットできます。

あとはVSCodeで設定するだけです。

```json:.vscode/settings.json
{
  ....
  "editor.formatOnSave": true,
  "prettier.documentSelectors": ["**/*.hbs"]
}
```

```json:.prettierrc.json
{
  ...
  "overrides": [
    {
      "files": "*.hbs",
      "options": {
        "parser": "glimmer"
      }
    }
  ]
}
```

これでVSCodeでファイル保存時にhbsファイルをフォーマットすることができます。