OmniAICreator/Qiita-1.07M huggingface dataset:
配列 vs ArrayList vs HashMapの拡張for文レース

# 訂正
比較演算子間違ってました（修正済み）

# つかったもの
・Java9
・eclipce

# 動機
何が最適かは置いといて拡張for文で回したらどれが一番早いのかなと。

# 結果
```ruby:ForEaerVs.java
public class ForEaerVs {
	public static void main(String[] argS) {

		Integer mm;
		
		// 配列
		Integer[] arry = new Integer[1000000000];

		for (Integer i = 0 ; i < 1000000000; i++) {
			Integer arryInt = i;
			arry[i] = arryInt;
		}
		long staetTimeArry = System.nanoTime();
			for(Integer iA : arry) {
				mm = iA;
			}
		long endTimeArry = System.nanoTime();
		System.out.println("配列速度：" + (endTimeArry -staetTimeArry));

		// List
		List<Integer> list = new ArrayList<Integer>();
		for (Integer j = 0 ; j < 1000000000; j++) {
			Integer arryInt = j;
			list.add(arryInt);
		}
		long staetTimeList = System.nanoTime();
			for (Integer iL: list) {
				mm = iL;
			}
		long endTimeList = System.nanoTime();
		System.out.println("List速度：" + (endTimeList -staetTimeList));

		
		// HushMap
		HashMap<Integer,Integer> hash = new HashMap<Integer,Integer>();
		for (Integer k = 0 ; k < 1000000000; k++) {
			Integer arryInt = k;
			hash.put(k, arryInt);
		}
		long staetTimeHash = System.nanoTime();
			for (Integer iH : hash.values()) {
				mm = iH;
			}
		long endTimeHash = System.nanoTime();
		System.out.println("Hash速度：" + (endTimeHash -staetTimeHash));

	}
}
```
```ruby:ForEaerVsResult.java
配列速度  ：4020600
List速度  ：11350400
Hash速度  ：18974400
```
作成時間もいれた結果は以下

```ruby:ForEaerVsPlusCreateResult.java
配列速度 ：35613700
List速度 ：98473300
Hash速度 ：121742700
```

# 感想

それぞれ使いどころは違うとはいえ、配列ってこんなに遅いのか。

配列先輩の凄さを崇めよ

# 追加
LinkedListでもやってみた

```ruby:ForEaerVsResult.java
Array速度 ：4001200
List速度  ：9521900
Hash速度  ：19611200
Linked速度：15211300
```
作成時間もいれた結果は以下

```ruby:ForEaerVsPlusCreateResult.java
Array速度 ：32542100
List速度  ：80343600
Hash速度  ：101256200
Linked速度：140576800
```
少人数チームでスクラムをやってみた気づき

### はじめに
* 自分の経験として、初めて開発チームにスクラムを導入し、運用してきたことの個人的な感想をまとめます。
* 題の通り、スタンダードなスクラムの運用とはちょっと違う部分もあったので、その状態でどう運用したかについて話せる範囲で残したいと思います。
    * ちょっと昔の経験を思い出しながら記述しているので、執筆不十分なところもあると思いますが、よろしければ最後までどうぞ

### スクラムとは？

* ざくざくっとまとめると以下のようなイメージ
    * アジャイル開発手法の一つ
    * 一定期間(スプリント/Sprintと呼ばれる)ごとにタスク消化/リリースを計画し、実行する
    * 基本的には5~6人以上のチームで行う

* 場面によってはこんなことを言われていたりします。

> 開発チームのメンバーが3人未満の場合は、相互作用が少なく、生産性の向上につながらない。また、開発チームの規模が小さいと、スキル不足が原因でリリース判断可能なインクリメントを届けられない可能性もある。

こちらより引用させていただきました→ [The Scrum Guide](https://www.scrumguides.org/docs/scrumguide/v1/Scrum-Guide-JA.pdf)

### 導入した背景

* エンジニア個人のタスクを可視化したかった
* 導入した当時、ガントチャートを使った進捗管理をしていたが、流動的に変わる計画に対応できなかったのでやり方を変えたかった
* よそのチームが導入しているのを見て、自分がやってみたくなった


#### 参考にした書籍

* [SCRUM BOOT CAMP THE BOOK](https://www.amazon.co.jp/SCRUM-BOOT-CAMP-BOOK-%E8%A5%BF%E6%9D%91%E7%9B%B4%E4%BA%BA-ebook/dp/B00DIM6BMI)
* [アジャイルサムライ――達人開発者への道](https://www.amazon.co.jp/dp/B00J1XKB6K/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)

ちなみに、上記書籍は(スクラム初学者の方は特に)SCRUM BOOT CAMP→アジャイルサムライの順に読むのをオススメしたいです。
SCRUM BOOT CAMPで感覚ベースで掴み、アジャイルサムライでよりアジャイルの本質に踏み込んだ内容に触れていくという手順でインプットできました。

### チーム構成
* プロダクトオーナー(兼プランナー) ... 1名
* エンジニア ... 2~3名(自分含む)

### どのような運用だったか
* 本来、スクラムを遂行するチームには**スクラムマスター**という仙人のプロジェクトマネージャ的なロールの人がいるのですが、3〜4人しかいないのでそれがいません
* 各スプリントの計画はプロダクトオーナーの要望に沿ってエンジニア側がブレークダウン・ポイントをつけていました
* それ以外の点（デイリースクラムなど）は通常通りです。

#### 少人数で良かったこと

* 基本的には問題なく運用できていたこと
    * メンバー全員で履修含め導入前の準備ができていたという要因もありますが、私がチームを離れるまで基本的に大きな問題なく運用を継続できました。
* デベロッパーとしてスクラムに参加する以上に自分の業務範囲が広くなる
    * 自分でタスクプランニングをしたりするという機会が得られたのは良い経験だったかなと思います。

#### 同じくイマイチだったこと
* **タスク消化業務とタスクのプランニング業務の兼務が必然になる**
    * これに尽きます。業務の範囲が広くなった分、エンジニアの開発タスクの時間がプランニングにも割かれてしまう状態でした。
        * 実際、私がチームを離れることが決まったあと、一歩引いた立場でスクラムの遂行をオブザーブすることがありましたが、自分が前線にいた時に見えなかったメンバーの負荷度合いなどが見えるようになったので、スクラムマスターの必要性をそのタイミングで改めて実感しました。
    * また、私のいたチームの場合、ある程度成熟しきったプロダクトの開発だったので、余裕があったから遂行できたというのはあるかもしれません。

### さいごに
* 少人数でスクラムを回すのは不可能ではないですが、可能ならやはり専任のスクラムマスターがいるのがベストなのかなとは思います。
    * 私の場合決して大きくないプロジェクト&開発プロダクトも成熟した状態だったからこそ、小規模でも導入でき、なんとか運用できているところはありました。
* 総じて、少人数でスクラムを回す場合は自分の職務が増えることがどうメリットに働くか、どういったものを犠牲にするかを考えて導入することは大事かなと感じました。
    * 個人的に思うのは、マネジメントキャリアを目指すエンジニアは一度経験してみることはあえて少人数でスクラムをやってみるのは悪くないのではないかと思います。

### おまけに

実際に運用していた時に使っていたサービスについて簡単に触れたいと思います。
綿密に比較検討をした上で決定したわけではないので、より良いものがあればぜひ教えて欲しいです！(他力本願)

* Trello
    * 厳密に言うと、スクラム導入前に無計画にタスクを可視化するためだけに導入していました。無計画にというところがよくないですね。
    * シンプルかつ自由度が高いのでスクラム以前にTODOリストという軽い目的から手軽に使えるのがいいところかなと思いました。当時は後述するZubeに乗り換えましたが、今改めて考えたらTrelloでも全然運用できたな・・・
    * Chrome経由でプラグインを導入できるので、カスタマイズ性も○
* Zube.io
    * 使用経験のあるメンバーにオススメしてもらったものです。
    * Sprintごとにカンバンを区切ったり、タスク(カード)ごとにポイントを割り振ったりなど、スクラム運用向けに色々な機能が盛りだくさんです。
    * GitHub Issueと連携しているので、ソースコードをGitHubで管理していると色々と恩恵あります。
    * まともな人数で運用しようとすると有料プランになってしまう点がややハードル？
Vue Composition API を使ってリアクティブに値を更新する方法

## 書かないこと
- Vue Composition APIの導入方法
- TypeScriptではなく、Vueのみ
- refとreactiveの使い分けについて

Vue3.0より実装予定の Composition API を使ってstateの値を更新します。


## setup関数内で更新する。

```vue:index.vue
<template>
  <div>
    <p>{{ count }}</p>
    <button @click='increment'>+</button>
  </div>
</template>

<script>
  import { ref } from '@vue/composition-api'
  export default {
    setup(){
      const count = ref(0)

      function increment () {
        count.value++
      },
      return{
       increment,
       count
      }
    }
  }
</script>
```

公式にもある通りですが、シンプルですね。
Vueで値の更新を検知するにはrefを使う必要があります。  

## Composition Functionで切り出した時の更新

```vue:index.vue
<template>
  <div>
    <p>{{ count }}</p>
    <button @click='increment'>+</button>
  </div>
</template>

<script>
  import { ref } from '@vue/composition-api'
  const useIncrement = () => {
    const count = ref(0)

    const increment = () => {
      count.value++
    }
    return {
      increment,
      count
    }
  }
}

  export default {
    setup(){
      const {increment, count } = useIncrement()
      return{
       increment,
       count
      }
    }
  }
</script>
```

従来のVueではdataやmethodごとに記述箇所が決まっていましたが、
Composition APIを使うことで関数の切り出しが可能になりました。

## setup内のstateを更新する。

```vue:index.vue

<template>
  <div>
    <p>{{ state.count }}</p>
    <button @click='increment'>+</button>
  </div>
</template>

<script>
  import { ref } from '@vue/composition-api'
  const useIncrement = (state) => {
    const increment = () => {
      state.count++
    }
    return {
      increment
    }
  }
}

  export default {
    setup(){
    const state = reactive({
      count: 0
    })
      const {increment } = useIncrement(state)
      return{
       state,
       increment
      }
    }
  }
</script>
```

Composition Functionにstateを渡して更新すればOK

VueComposition APIはさわり始めたばかりですが、柔軟コードが書けそうな反面難しそうですね。

参考資料
[Vue Composition APIのコラムっぽいもの集](https://mya-ake.com/posts/vue-composition-api-columns/)
MySQLのデータが人質にとられた

#はじめに
[前回の記事](https://qiita.com/playTag55/items/1766c097502763888579)で紹介していたWebサービスの[shijimi](https://www.shijimi.work/)のデータがなくなりました（泣）
どうやら，データを人質に取られたみたい．
ランサムウェアだね．SCの勉強中だからね．

（実は，最初に公開したときから約2週間後にも同様の現象がありました．そのときは，原因不明でした．）

#調査
サービスはconohaのVPSを利用しています．
自分のサーバが何かのタイミングで感染したのでしょうか？
AVは未導入でした．あちゃちゃ．
<img width="476" alt="please_read_me_vvv.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343913/5d408eaf-a5ad-ecd8-79e7-75e2bf609c23.png">
mysql_dataフォルダに，謎のplease_read_me_vvvがありますね．
自分の環境では，文字化けして読めませんでしたが，[参考サイト](https://k-suzuki.hateblo.jp/entry/2019/11/18/030728)によると，
「おまえのデータ盗んでやったぜ！！返してほしければ10日以内に0.03bitcoin払いやがれ！！」
とのこと．
ちなみに，
<img width="510" alt="0.03bitcoin.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343913/49436f8b-a47c-82d2-2612-0aefa3341959.png">
です．最近上がってきてますからね．

原因をいくつか考えてみました．

###案1
外部からMySQLをいじれたっけ？
<img width="784" alt="conoha_setting.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343913/f61de1d9-11e9-2d30-b7f8-448e48d44fdc.png">
あ～，接続許可ポートにMySQL:3306おるやん．
これはまずい．
だれでもアクセスできそうですね．
あとは，ブルートフォース攻撃で突破されたんかなぁ．

####追記
上の設定で，特定のポートだけを許可すると，サーバーにアクセスが届く前に遮断されるようです．
他のポートを開放したいなっていうときに，どうしようも無くなる．

よって，「全て許可」のまま，firewall-cmdで設定するのが良さそうです．
でも，遮断したポートに外部から繋がってるぞ！？
[Dockerでマストドンやってたら、遮断したはずのポートが丸見えだった件](https://glorificatio.org/archives/2953)によると，dockerで開放したポートはファイアーウォールを無視するようです．
内部だけに開放するよう，127.0.0.1:3306:3306みたいにすると上手くいきました！！


###案2
dockerコンテナ構築用に，データベースのenvファイルを置いているのですが，外部から見られたら一発アウトですね．
イメージファイル作ったら，破棄すべき？
root権限さえ乗っ取られなければ，大丈夫だとふんでいる．

#不幸中の幸い
まだ，shijimiには新規登録者いませんでしたので，セーフです！
また，conohaの粋な計らいでSSD容量が50GB→100GBになったようです．
たぶん，サーバを再構築しないと適用されないのかな．
ちょうどいいので，一旦サーバを破壊しましょう．
当分shijimiにはアクセスできないかもです．

#おわりに
セキュリティやらないとなってことで，情報処理安全確保支援士(SC)の勉強真っ只中でおきた事件でした．
お金払っちゃだめっ！ぜったい！！
tmuxチートシート

# tmuxチートシート

コマンドだけ簡潔にまとまっているものを作成しました。
詳しい説明などが必要な場合は別の記事を

## セッションコマンド
|コマンド|機能|
|:----------|:----------|
|tmux|新規セッションの開始|
|tmux new-session -s name|新規セッションの開始（名前指定）|
|[Ctrl+b] + $|セッション名変更|
|[Ctrl+b] + ,|ウィンドウ名変更|
|[Ctrl+b] + d|セッションのデタッチ|
|tmux a -t name|指定したセッションにアタッチ|
|tmux a|直近のセッションにアタッチ|
|tmux ls|セッション一覧|
|tmux lsc|クライアント一覧|

## ウィンドウコマンド
|コマンド|機能|
|:----------|:----------|
|[Ctrl+b] + c|ウィンドウの作成|
|[Ctrl+b] + n|ウィンドウを移動(next)|
|[Ctrl+b] + p|ウィンドウを移動(pre)|
|[Ctrl+b] + num|指定した番号にウィンドウを移動|
|[Ctrl+b] + w|ウィンドウ一覧を表示|
|[Ctrl+b] + &|ウィンドウを強制終了|

## ペインコマンド
|コマンド|機能|
|:----------|:----------|
|[Ctrl+b] + "|ペイン横分割|
|[Ctrl+b] + %|ペイン縦分割|
|[Ctrl+b] + o|ペインの移動|
|[Ctrl+b] + q|インジケータ表示|
|[Ctrl+b] + x|現在のペインを終了|
|[Ctrl+b] + !|現在のペイン以外を終了|
|[Ctrl+b] + {|現在のペインを左と入れ替え|
|[Ctrl+b] + }|現在のペインを右と入れ替え|
|[Ctrl+b] + ;|以前のペインへ移動|
|[Ctrl+b] + o|ペイン順に移動|
敢えてRubyで学ぶ「ゼロから作るDeep Learning」第4章 数値微分/勾配

Rubyだとちょっと数値微分に一工夫必要。

Pythonだと

```python
def numerical_diff(f,x):
  h = 1e-4
  return (f(x+h) - f(x-h)) / (2*h)
```

と引数に関数を渡せてしまうが、Rubyで同じことはできない。
Proc(lambda)オブジェクトを定義し、ブロック化して関数を渡すことで実行可能。

## 数値微分

```ruby:numerical_diff.rb
def numerical_diff(f,x)
  h = 1e-4
  return (f.call(x+h) - f.call(x-h)) / (2*h)
end

def function_1(x)
  0.01*x**2 + 0.1*x
end

# 実行
f = lambda {|arg| function_1(arg)}
numerical_diff(f,5) # => 0.1999999999990898
numerical_diff(f,10) # => 0.2999999999986347
```

## 勾配

```ruby
require 'numo/narray'

def numerical_gradient(f, x)
  h = 1e-4
  grad = Numo::DFloat.zeros(x.shape)
  # 各xで偏微分
  x.length.times do |idx|
    tmp_val = x[idx]
    # 要素に差分を入れて、中心差分を取る
    x[idx] = tmp_val + h
    fxh1 = f.call(x)
    x[idx] = tmp_val - h
    fxh2 = f.call(x)
    grad[idx] = (fxh1 - fxh2) / (2*h)
    # 元のxに戻す
    x[idx] = tmp_val
  end

  grad
end

def function_2(x)
  return x[0]**2 + x[1]**2
end

x = Numo::DFloat[3.0, 4.0]
f = lambda{|arg| function_2(arg)}
numerical_gradient(f, x) # =>Numo::DFloat#shape=[2] [6, 8]
x = Numo::DFloat[0.0, 2.0] 
numerical_gradient(f, x) # => Numo::DFloat#shape=[2] [0, 4]
x = Numo::DFloat[3.0, 0.0] 
numerical_gradient(f, x) # => Numo::DFloat#shape=[2] [6, 0]
```

## 勾配法

```ruby
def gradient_descent(f, init_x, lr=0.01, step_num=10)
  x = init_x

  step_num.times do |i|
    grad = numerical_gradient(f, x)
    x -= lr * grad
  end
  return x
end

init_x = Numo::DFloat[-3.0, 4.0]
f = lambda{|arg| function_2(arg)}
# 良い例
gradient_descent(f, init_x, lr=0.1, step_num=100) => Numo::DFloat#shape=[2][-6.11111e-10, 8.14814e-10]
# 悪い例 : 学習率が大きすぎる例
gradient_descent(f, init_x, lr=10, step_num=100) => Numo::DFloat#shape=[2][-2.58984e+13, -1.29525e+12]
# 悪い例 : 学習率が小さすぎる例
gradient_descent(f, init_x, lr=-10, step_num=100) => Numo::DFloat#shape=[2][-2.4204e+12, 3.0874e+12]
```
Juliaのアプリケーションを実行形式にしてデプロイできてしまうんや．そう，(新しい) PackageCompiler ならね

# 本日は

- 最近やった事のまとめを書いておこうと思います．(そろそろ本職の方でPyTorchをお勉強したいため）
- お題は [HelloX.jl](https://github.com/terasakisatoshi/HelloX.jl) という自作のアプリケーションを別のPCにデプロイすることを考えます．
- `HelloX.jl` は添付の図のように UnicodePlots で書いたグラフをターミナル上で描画する Julia のアプリです．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/6c96e721-14ea-fd1e-4cda-756fd8047de0.png)

# これができると嬉しいこと

- プログラマーは Julia を Python のように高級言語として記述でき，計算においては Just in Time なコンパイルによる高いパフォーマンスを得ることができます. Julia で書いたコードをコンパイルする PackageCompiler の能力を用いれば Ahead of Time なコンパイルにより実行形式として使えるバイナリーになり，Julia に依存しない環境でも動作させるようにできます．
- これにより Python のプロトタイプとして書かれたコードを組込先に向けて C＋＋ などに変換・移植という工程が不要になり,Juliaを使うことで一つの言語で開発をすることができるようになります．

<blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/hashtag/JuliaLang?src=hash&amp;ref_src=twsrc%5Etfw">#JuliaLang</a> solves this two language problem, <a href="https://twitter.com/elonmusk?ref_src=twsrc%5Etfw">@elonmusk</a>. No need to convert Python to C++, deploy what you develop to production! <a href="https://t.co/U3pdeyYiP7">https://t.co/U3pdeyYiP7</a></p>&mdash; Viral B. Shah (@Viral_B_Shah) <a href="https://twitter.com/Viral_B_Shah/status/1224362465779163138?ref_src=twsrc%5Etfw">February 3, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 動かしましょう

- 以降の検証環境は Mac で行いましたが，gcc などが入っていればLinuxでもWindowsでも動くはずです．

# Julia がある環境で動かす

```
$ julia --project=. -e "using HelloX; HelloX.julia_main()"
```

上の図のようにグラフが出ればOKです．また動作した関数の定義は下記の通りです．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/00cd85b3-55d7-cabb-6a87-2945af7334d7.png)

# HelloX.jl をビルドする

上では動作確認ができましたのでビルドしてみましょう．

```console
$ git clone https://github.com/terasakisatoshi/HelloX.jl
$ cd HelloX.jl
$ make run
```

`make run` に相当する部分は次と等価です

```console
$ julia --project=. -e 'using Pkg; Pkg.add(PackageSpec(url="https://github.com/JuliaLang/PackageCompiler.jl",rev="master"))'
$ julia --project=. -e 'using Pkg; Pkg.instantiate()'
$ julia --project=. -e 'using PackageCompiler; create_app(".", "build", force=true)'
$ build/bin/HelloX
```

- ビルドには時間がかかりますのでコーヒを飲みながら待ちましょう．ノートパソコンだと大変かもしれないです．`build/bin/HelloX` でグラフが出現すればOKです. `build` 以下を見ると dylib などのオブジェクトがワンサカ出てると思います．できましたら，他の同じOSのPCに移動して試してみましょう．Juliaのない環境で動かしてみるなどしてみてください．


# ラズパイ, ジェットソンでも動くっぽい．

- これはもう趣味なんですが，Jetson とかラズパイで Julia で書いたアプリケーション動かしたいなーということで PackageCompiler.jl やPackageCompilerX.jl で ARM 対応のPRにレビューに参加して arm32bit でも動くようにしてくれました．元々は aarch64 対応のPRだったのですが，32bitの配慮をするロジックがあったのでついでにお願いした形になります．Jetsonでも動くっぽいよ！
- 基本的には実機の上で動かすか，Dockerのなかでクロスコンパイルした後でターゲットのデバイスに入れ込むという流れになります．HelloX.jl の直下にあるスクリプトがあるのでそれを実行するとPi3やPi4，そして PiZero といったニッチな環境でも動作をさせることができるのがわかります．

## パイゼロは茨の道

- ただし，パイゼロは公式に対応しているわけではないので自分で Julia をソースからビルドしたり，必要に応じて Julia コードにパッチを適用したり，依存ライブラリの解決を自分で行う必要があります．そういう意味ではハードルがありますが，勉強にはなると思います．
- arm32bit環境自体 Julia では２級市民扱いなのでPackage開発者自体あまりよくわかってなかったり設計が考慮されてないということもありますが，適宜フィードバックをすることでよくなってきてはいますのでニッチなことが好きな人はトライしてみてください．
gflagsをVisual Studioで使う（静的リンク）

# gflagsとは
Googleが作った引数解析用のライブラリ。
Visual Studioで使おうとすると、意外と苦労したのでメモ。

# gflagsのビルド
CMakeを使って、Visual Studioのプロジェクトを生成します。

```
git clone https://github.com/gflags/gflags.git
cd gflags && mkdir vs && cd vs
cmake -DCMAKE_BUILD_TYPE=Release -A x64 ..
```
`gflags.sln`を開けば、ビルドできるが、重要なのは、`gflags_static.vcxproj`だ。

# gflagsを参照するプロジェクトの作成
## サンプル
gflagsを用いた以下の`main.cpp`をビルドしたいとする。

```cpp
#include <iostream>
#include "gflags/gflags.h"

DEFINE_string(message, "Hello world!", "Message to print");

int main(int argc, char *argv[])
{
	gflags::SetUsageMessage("How To Use");
	gflags::SetVersionString("1.0.0");
	gflags::ParseCommandLineFlags(&argc, &argv, true);
	std::cout << FLAGS_message << std::endl;
	gflags::ShutDownCommandLineFlags();
	return 0;
}
```

## プロジェクトの設定
1. インクルードディレクトリの設定（`vs\include`）
2. 追加のライブラリディレクトリ(`vs\lib\Release`)
3. 追加の依存ファイル(`gflags_static.lib`, `shlwapi.lib`)
4. ランタイムライブラリの設定(`マルチスレッド(/MT)`)
5. 上記の`gflags`のプロジェクトを参照に追加する

3の`shlwapi.lib`が必要というところが難しかった。
これはWindowsのAPIで、`__imp_PathMatchSpecA`のリンクに必要らしい([参考ページ](https://mmiyano.blogspot.com/2016/06/visual-studio-2015-gflags-x64unicode.html))。
Swift：WKWebViewでローカルファイルを開く時のTips

```swift
import Cocoa
import WebKit

class ViewController: NSViewController {
    
    var webView: WKWebView? {
        return self.view as? WKWebView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        guard let url = Bundle.main.url(forResource: "LocalFile", withExtension: "html") else { return }
        self.webView?.loadFileURL(url, allowingReadAccessTo: url)
    }
       
}
```

こんな感じでBundle内のHTMLファイルをWebViewに表示するとき、`SandBox`の`Network: Outgoing Connections (client)`にチェックを入れないとコンテンツが読み込まれない。
archでdns-over-httpsを設定してみたお話

#archでdns-over-httpsを設定してみたお話

普段dnsmasqは動かしてるので
そろそろ使ってみようと思ってとりあえずやってみた



###必要なパッケージをインストール

今回はdns-over-httpsを使用

```
$ sudo pacman -S dns-over-https
resolving dependencies...
looking for conflicting packages...

Packages (1) dns-over-https-2.2.1-1
...
```

以下設定とか

設定としてはとりあえず最小限の変更として、listenだけ調整してやりました

何も使ってない環境は調整不要のはずなのでお好みで

```
$ /etc/dns-over-https/doh-client.conf
# DNS listen port
listen = [
　　　　　　#"127.0.0.1:53",
　　　　　　"127.0.0.1:5380",
```

systemdへ普通にスタート登録して起動

```
systemctl enable doh-client
systemctl start doh-client
```

dnsmasqを使っているので、設定に次の項目を入れてやりました。

```
# no reading resolv.conf
no-resolv

# to local doh-client
server=127.0.0.1#5380
```

あとはdoh-clientを参照するように設定で完了

```
$ /etc/resolve.conf
nameserver 127.0.0.1
```



###使用確認について

これで暗号化されてDNS参照ができるようになりました。

一応digってみてもなんの変化も有りませんが、少しはセキュアになってます。

```
$ dig @127.0.0.1 www.google.com

; <<>> DiG 9.14.7 <<>> @127.0.0.1 www.google.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53182
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1452
; PAD (65 bytes)
;; QUESTION SECTION:
;www.google.com.                        IN      A

;; ANSWER SECTION:
www.google.com.         140     IN      A       172.217.26.4

;; Query time: 10 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
```



気になる場合は doh-client.conf に verbose=true を追加
journald等でログを眺めてやるとニヤニヤできます。
RailsチュートリアルとRails6

##概要
Railsチュートリアルの指定バージョンが5.1.6なのだが、Rails6でチュートリアルを進めるとエラーが頻出するのでメモ。

＊以下「Railsチュートリアル」は「チュートリアル」と表記する。

##エラー①
パソコンのRailsのバージョンが6なのにチュートリアルのGemfile通りに

```ruby:Gemfile
gem 'rails',        '5.1.6'
```
に指定していると

```
`load_defaults’: Unknown version “6.0”
```
こんなメッセージで怒られる。

###対処
一度ファイルを削除して、バージョンを指定してrails newするかgemのバージョンを変更する。

##エラー②(Rails5も共通?)
[Railsチュートリアル1章](https://railstutorial.jp/chapters/beginning?version=5.1#sec-heroku_setup"Rilsチュートリアル")リスト1.13の通りに指定してbundleするとエラーが出る。

```console
An error occurred while installing sqlite3 (1.3.13), and Bundler cannot
continue.
Make sure that `gem install sqlite3 -v '1.3.13' --source 'https://rubygems.org/'`
succeeds before bundling.

In Gemfile:
  sqlite3
```

###対処
[こちらの回答](https://teratail.com/questions/220752)によると
>rails6ではsqlite3のgemは1.4以上が必要になる

ということなので

```ruby
 gem 'sqlite3', '1.3.13'
```
を下記の内容に書き換え。

```ruby

gem 'sqlite3', '~> 1.4'
```

***
このエラーについては、

```ruby:
gem 'sqlite3', '~> 1.3.13'
```

のようにすれば良いという記事もあったのだが、Rails5でチュートリアルを進めている時にも同様のエラーが発生した。
こちらも1.4に指定することで解決した。
さくらのVPSストレージ増量メンテで増加したパーティションを追加する（足踏み中。。）

#はじめに
さくらのVPSが2019年11月19日にストレージ増量メンテナンスを実施され、契約していたVPSが50GB SSD → 100GB SSDとなったので、パーティション追加を行った。
結構空き容量が無くなってきていたタイミングだったので渡りに船！
倍ですよ倍！
因みに[さくらのVPS ディスク拡張手順](https://vps-news.sakura.ad.jp/scaleup/disk-expansion_centos7/)を参考に実施した。
ありがとう！さくらインターネット！！

#環境
|||
|:-:|:--|
| VPSプラン | 2G |
| OS | CentOS Linux release 7.3.1611 |
| CPU | 仮想3Core |
| メモリ | 2GB |
| SSD | 50GB → 100GB 😁 |

#操作手順
##gdiskのインストール
```
# rpm -q gdisk
package gdisk is not installed
# yum -y install gdisk
```
##ディスクの状態確認（vdisk）
```
# gdisk -l /dev/vda
GPT fdisk (gdisk) version 0.8.10

Partition table scan:
  MBR: MBR only
  BSD: not present
  APM: not present
  GPT: not present


***************************************************************
Found invalid GPT and valid MBR; converting MBR to GPT format
in memory.
***************************************************************

Disk /dev/vda: 209715200 sectors, 100.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 712FB94B-6375-42FF-8C1B-7D3B8EC68C50
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 209715166
Partitions will be aligned on 2048-sector boundaries
Total free space is 104859581 sectors (50.0 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         1026047   500.0 MiB   8300  Linux filesystem
   2         1026048       104857599   49.5 GiB    8E00  Linux LVM
```
> Disk /dev/vda: 209715200 sectors, 100.0 GiB

/dev/vdaに100GBあるでって言ってる
嬉しい
でも無効なGPTもあるでって言ってる
そうか…
MBRからGPTへ変換かけろって言ってるけど大丈夫なのかしら…わからん。。

##パーティション確認（lsblk）
```
# lsblk
NAME                               MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0                                 11:0    1 1024M  0 rom
vda                                252:0    0  100G  0 disk
├vda1                              252:1    0  500M  0 part /boot
└vda2                              252:2    0 49.5G  0 part
  ├centos_tk2--xxx--xxxxx-swap     253:0    0    2G  0 lvm  [SWAP]
  └centos_tk2--xxx--xxxxx-root     253:1    0 47.5G  0 lvm  /
```
vda1, vda2の2つのパーティションがある模様
##課題
```
# sgdisk -g /dev/vda
```
ってやればその後はいい感じにいけそうだけど、環境壊れないか不安。。。
ってなって足踏み中です

もし似たような事された方いたらご意見ください

（2020/05/09追記）
作業完了しました！（色々躓きましたが。。）
後日まとめます！
【WireMock】Javaでスタブ・モックサーバを立ててE2Eテストを行いたい

# 連携先システムが検証系では使えないけどE2Eテストがしたい
世はマイクロサービス時代なので、HTTPリクエスト・レスポンスのモック・スタブの需要が高まっているみたいですね。
私の参加しているプロジェクトはマイクロサービスなんて関係ないのですが、
表題のとおりの目的で、Javaで動くAPIサーバを探していたところ教えていただきました。

# WireMock
HTTPベースのAPIのシミュレータ、mockサーバー。
http://wiremock.org/
https://github.com/tomakehurst/wiremock

ほかのAPIServerとの比較は下記サイトで確認できます
[Comparison of API simulation tools](https://en.wikipedia.org/wiki/Comparison_of_API_simulation_tools)

## ThoughtWorksのTECHNOLOGY RADARに2018年にTRIALで選ばれてました
https://www.thoughtworks.com/radar/tools/wiremock
ちなみにTRIALはちゃんと管理するのであればやる価値はあるという指標らしいです。

## 利用方法
ざっと見た感じ以下の2通りがあります
### ソースコード内で利用する
MavenやGradleで導入します。こちらはJUNITと組み合わせて利用している例が多そうです
[Download and Installation](http://wiremock.org/docs/download-and-installation/)
### StandAloneサーバとして導入する
公式サイトからJarファイルをダウンロードして起動します
[Running as a Standalone Process](http://wiremock.org/docs/running-standalone/)

今回はE2Eテストのシミュレータとして動いてほしいので、StandAloneサーバとして利用します。
こちらの形式だと、できることが減りそうですかね？
やりたいことが実現できるか調査していきます。

# 参考サイト
[WireMockサーバーの導入手順](https://qiita.com/Junichi_M_/items/7fe4c25ef4b82ecb0d16)
dockerが占有しているディスクを開放するコマンド

# docker system prune

自分の個人用Linux環境では現在root(`/`)に100Gのディスクをマウントしているのだけれど、最近ディスクスペースがないぞと警告がでてしまった。

調べるとdockerのimageやらなんやらで25GBもぶんどられていたので、ここを削減すべく調査。

# 調査結果
以下のコマンドでいい感じに使っていないものを削除してくれる。

```
$ docker system prune -af
```

14GBも削除できた。
とりあえず満足。

```
$ docker system prune -af
...                                                     
deleted: sha256:324e4d3a7dea2e55f7d62c69ed5c2c75e0498830d33f1bdf91ac3b53caaa3a4f
deleted: sha256:4500a5ee8f0d643c3f75655827ea893133976c034aaf02e2d362c2d74b3f2553
deleted: sha256:7f097c1fef1a1ccb97a17ae6e82f72096db3337655f3e4e3b192bdd61e9ed858
deleted: sha256:3feae1c6f465840e3ea3658175c7667ba6fc29dee110de2a690e751ac0d36962
deleted: sha256:7a73e56f893cf6284a6ad2be795dfe627da1b354e95befc61e49011a84e3f846
deleted: sha256:f38296c87e1266afe76efb0b909646b2898d50450a03679d505e9ee220ad3a61
deleted: sha256:a78b5195ddd832f217b5255707d9767efd74c43a3d373e7fcdff4176998d87a4
deleted: sha256:65e53d7a0ba16f3c4c6382176d26a23af5d669e0354910e7f3cb23c1ac2b35d1
deleted: sha256:7d54cb4e40b6e9f887c39adcc92656626fd8eb5bcd3472622bcdd03a7b63bbb7
deleted: sha256:db45b38d6bbd6cab848d4958e172201e041dfbc0abbacdfe55937081e809979b
deleted: sha256:05340d226ca3ff0041553d3d732257a8f3182e11612e47ac15cde17fa8a5e568
deleted: sha256:9cbb0103d6c58071dae6b3b5e5a471e954785875803067ab570008cd50e3db13
deleted: sha256:f7c732c81f969b4677ef4312ca2f70e5e3368e5e3a2244809d064a9533e0576d
deleted: sha256:ebb9ae013834b54e76c8d7dfde0ca9018f6bb3495740356a8f1dc655a8552130

Total reclaimed space: 14.1GB
```

volumeも削除したい場合には`--volumes` フラグをつける。

```
$ docker system prune -f --volumes
...
4290242096f39a7b48c1ed736b93395a917b682369717cbb020cacda4d3ded5a
4607556efe8c2d4450f5452f74260bd421acda8ded47f4e5b854881c08f318e5
579a2fe1ddd4dea14d8ad8320daa7c48c0fc4bc2c1c754dd7ab9f167f3ab2c4a
21bb1876436790dd3c1b1cf5696f925834f32b951d1a2aa6644d316b947722a3
50c9a60c8228b7d86a610f4a582cba2d344c9c3fc6a6f73c8ecb1e6b61f9be08
93ab608312285d3158c468ea6f8f143bb61ffc0fc813c6bc1a0179dee22565e9
a10442a600e0ef690ed8357ee82ca42c70254ace5a47ba899fb4ce81badab39c
164c8cc1a4e287ab0b5d55709e784c2cd0e73181dccefebbbb6be1f14cd8aabe
4200fd127cffb155c2c153257897755597498ce1a333f47cc3153827bc10c737
76c0c21bfdd76e2b9b8aebd77a37b0e4bbb09a5590671d7b2f327bc5fcc970f6

Total reclaimed space: 681.9MB
```
あなたの心を守るちょっとした心構え

#真面目な人程心が折れる
仕事は大変です。
人が足りない、時間が足りない、などなど、色々あってストレスがたまることもあると思います。
そんな中で、一番ストレスが溜まるのが対人関係。
人不足や時間不足は数値で論理的に改善策が出せますが、人と人だけは残念ながらそうもいかない。
そんな人間関係で困ってる人たちへのちょっとした指針になればと思います。

#色々言ってくるけど、その人は本当に仕事ができる人？
お前が悪い、仕事ができないね、この問題どうするの？　これは指導だから素直に聞け。
などと、色々言われることもあると思います。
問題点を指摘されて、改善策を考えなければいけない。指摘自体は理解できるが、悩むしストレスが溜まるところです。
さて、ここで一歩、思考を止めて立ち止まってみましょう。

#その人の言ってること、本当に正しいの？
問題点を指摘されたときに改善策を出さない人がいた場合、経験上３つのパターンがあります。
####1.自分で考えて答えを出すことを期待しているパターン
　良い人です。こういった方は、改善策を出したときに、論理的に問題点や改善策を伝えてくれる場合があります。
　但し、そうでない場合は下記のパターンに準じます。

####2.問題点を指摘するが、改善案を提案しないパターン
　このパターンは相手のフォローをする気持ちはなく、指摘をすることで相手を下にもっていこうとする傾向があります。
　改善案を出したときに良いところ、悪いところを提示せずに改善案も出さないパターンは大体この傾向があります。
　そういった人は、一見それっぽいことを言っていたとしても問題の分析ができないパターンが多いので、鵜呑みにすることはやめましょう。
　弁が立つだけなので、悩むよりはより影響力のある人を巻き込んで味方を作ることをお勧めします。

####3.経験や役職などの権力をかさに指摘をするタイプ
　今すぐ逃げてください。話を聞くだけ無駄です。
　逃げられない場合は、言質を取った上で指示を聞き、失敗した場合に「指示に従った」ことを強調してください。
　このタイプの人間は、話が二転三転する上に自己責任を取ろうとしない傾向があります。
　相手のほうがポジションが上であろうが、話を聞く必要はない、という考えを持ってください。
　そうしないと、あなたの良いところを全く生かせないまま、あなたの心が折れます。

#あなたの体が一番大事
仕事や職場は転職などで変えることができます。
今の部署で合わなかったり、評価が低かったりするからといって、あなたの価値が低いわけではありません。
ぜひ、本記事を見て心の在り方について楽になればと思います。

#最後に:上役の担務について
リーダーやマネージャーと呼ばれる人の担務が幾つかあると思いますが、蔑ろにされがちなのが
・チーム内の問題を解決する
・部署間の問題を解決する
です。
特に問題解決できない上役はその傾向が強いです。
リーダーやマネージャー職の人でこれが出来ない人がいたら、
仕事ができないと同義なので相手にしないことをお勧めします。
Gitの内部の動きを知ろう　～その３～

### [目次](https://qiita.com/as-chapa/items/246b03c671bd798d50a8)

# 今回の確認内容
前回のコミットに対してtagをつけてみます。

## git tag
以下のコマンドを実行します。

```
$ git tag -a v001 -m "first tag"
```
オブジェクトがどのように変わったかを見ていきます。
差分は以下の通りです。

```
├── .git
│   ├── objects
│   │   ├── 8b
│   │   │   └── e68ce70275726ea093eb5da6c1fe9c9566bd7e
│   └── refs
│       └── tags
│           └── v001
```
新しく追加されたオブジェクトの中身を見てみます。

```
$ git cat-file -t 8be68ce70275726ea093eb5da6c1fe9c9566bd7e
tag
$ git cat-file -p 8be68ce70275726ea093eb5da6c1fe9c9566bd7e
object 2deb1b0751cbfeffdc75683b2f61e476ef970640
type commit
tag v001
tagger Chapa <hoge@hoge.com> 1581461073 +0900

first tag
```
前回コミットした際にできたコミットオブジェクト（2deb1b0751cbfeffdc75683b2f61e476ef970640）とタグが紐づいていることがわかります。
試しに何もコミットしないでさらにタグを追加してみます。

```
$ git tag -a v002 -m "2nd tag, no changes"
```
差分は以下のようになりました。

```
├── .git
│   ├── objects
│   │   ├── ab
│   │   │   └── ca15c3e8b8f5db47539ad14551806eb2f57df4
│   └── refs
│       └── tags
│           └── v002
```
オブジェクトの中身を見てみます。

```
$ git cat-file -t abca15c3e8b8f5db47539ad14551806eb2f57df4
tag
$ git cat-file -p abca15c3e8b8f5db47539ad14551806eb2f57df4
object 2deb1b0751cbfeffdc75683b2f61e476ef970640
type commit
tag v002
tagger Chapa <hoge@hoge.com> 1581461574 +0900

2nd tag, no changes
```
新規にコミットをしていないので、v001と同じコミットオブジェクトが記載されています。
タグに関しては順序性がないので、「/refs/tags/」配下を見ても同列にv001とv002が存在し、タグオブジェクト以外に変更点はありません。

タグに対応するオブジェクトのハッシュ値は「/refs/tag/」配下のファイルを見るとわかります。

```
$ cat .git/refs/tags/v001
8be68ce70275726ea093eb5da6c1fe9c9566bd7e
$ cat .git/refs/tags/v002
abca15c3e8b8f5db47539ad14551806eb2f57df4
```
以下のgitのコマンドでも確認可能ですが、どこに何が作られるかを理解していると単純にcatでも情報が確認できます。

```
$ git rev-parse v001
8be68ce70275726ea093eb5da6c1fe9c9566bd7e
$ git rev-parse v002
abca15c3e8b8f5db47539ad14551806eb2f57df4
```

# 今回のおさらい
git tagを叩くと、どのコミットに対してどこにタグ情報やコミットとの関連が作られていくかがわかりました。意外とgitのコマンドがわからなくてもcatで必要な情報が見つかることもわかりました。
RaspberryPi4 外付けSSD編

# 買ったSSD
TCSunBow 外付けSSD120GB USB 3.0
https://www.amazon.co.jp/gp/product/B0784FBV62/

# 接続確認
おもむろにUSBコネクタに差し込む
`dmesg`で認識しているか確認

```bash
$ dmesg
...
[188855.959585] usb 2-2: new SuperSpeed Gen 1 USB device number 2 using xhci_hcd
[188855.991660] usb 2-2: New USB device found, idVendor=2109, idProduct=0715, bcdDevice=f0.40
[188855.991677] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[188855.991690] usb 2-2: Product: VLI Product String
[188855.991701] usb 2-2: Manufacturer: VLI manufacture String
[188855.991712] usb 2-2: SerialNumber: 0000000000006200
[188855.994517] usb-storage 2-2:1.0: USB Mass Storage device detected
[188855.997133] scsi host0: usb-storage 2-2:1.0
[188857.060516] scsi 0:0:0:0: Direct-Access     TCSUNBOW  P1 120GB        R052 PQ: 0 ANSI: 6
[188857.064345] sd 0:0:0:0: [sda] 234441648 512-byte logical blocks: (120 GB/112 GiB)
[188857.065327] sd 0:0:0:0: [sda] Write Protect is off
[188857.065346] sd 0:0:0:0: [sda] Mode Sense: 2f 00 00 00
[188857.066339] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[188857.072851]  sda: sda1
[188857.077995] sd 0:0:0:0: [sda] Attached SCSI disk
[188857.081997] sd 0:0:0:0: Attached scsi generic sg0 type 0
```

# フォーマットとマウント
```bash
sudo fdisk /dev/sda # メッセージに従って設定する
sudo mkfs.ext4 /dev/sda1
sudo mkdir /mnt/ex-ssd
sudo mount -t ext4 /dev/sda1 /mnt/ex-ssd
```

`df`してマウントされているか確認する

```bash
df -f | grep ex-ssd
  /dev/sda1        110G   83M  104G    1% /mnt/ex-ssd
```

# 起動時にマウントするように設定する
マウントしていたら`sudo umount /mnt/ex-ssd`で外す

```bash
sudo blkid /dev/sda1 # UUIDを調べる
sudo vim /etc/fstab
... # 先程調べたUUIDと設定を最後に追記する
 UUID=xxxxxxxxxxxx /mnt/ex-ssd ext4 discard,nofail 0 2
...
sudo mount -a
df -f | grep ex-ssd
  /dev/sda1        110G   83M  104G    1% /mnt/ex-ssd
``` 

`nofail`を指定しているのはマウント出来なかった場合でも起動をさせるためです

再び`df`してマウントされていればOK

以上
JOI春合宿2019-Day1-1 Examination 解説

JOI春合宿2019-Day1-1 Examination（問題は[こちら](https://www.ioi-jp.org/camp/2019/2019-sp-tasks/day1/examination.pdf),ジャッジは[こちら](https://atcoder.jp/contests/joisc2019/tasks/joisc2019_a),解説は[こちら](https://www.ioi-jp.org/camp/2019/2019-sp-tasks/day1/examination-review.pdf)）の解説です。
解法メモです。

# 問題概要
$N$ 人の学生がいて、それぞれ数学と情報で $S_i,T_i$ の点数を取った。
$Q$ 回のクエリが与えられるので、$S_i\geq X_j,T_i\geq Y_j,S_i+T_i\geq Z_j$ を満たす $i$ の個数を、それぞれの $j$ について求めよ。

# 考察

- 制約がでかい、やばそう
- とりあえず $X_j+Y_j\geq Z_j$ のときは、$Z_j$ の条件は実質気にしなくていいので、クエリとデータを $X_j,S_i$ 順にソートして自動的に $X_j$ の条件を満たすようにしておき、$Y_j$ 以上の $T_i$ をもつ $i$ の個数を求める $\rightarrow$ BITなりセグ木なりでできる
- 問題は $X_j+Y_j<Z_j$ のとき、この時は $X_j,Y_j,Z_j$ 全部気にしないといけない、一個ソートしておいて無視したにしても他の $2$ つに条件が絡まる
- これを処理できるデータ構造を知っていますか？僕は知りません（後から見たネット上の解説によるとうまく座圧するとできるらしいが、めんどくさそう、やりたくない、やめたい、やめてしまった）
- 知らないので、不等式処理でなんとかしようとするが、できない（それはそう、ここで3時間ほど溶かす、睡眠時間はドブへ）
- 音楽の授業中に頑張って考察をすると、後者のクエリをさらに二つに分割できないか？となる
- $X_j\leq S_i<Z_j-Y_j$ と、$Z_j-Y_j\leq S_i$ に分けてみると、前者では $Z_j\leq S_i+T_i$, 後者では $Y_j\leq T_i$ が題意と必要十分であることに気づく
- これなら、$X_j$ に関する条件は自動的に満たすようにしておき、あとは $Y_j$ と $Z_j$ をそれぞれ別々に気にするだけでいい $\rightarrow$ 完全勝利
- まとめると、次のようになる
    - 基本的にクエリとデータは $X_j,S_i$ の順にソートしておき、残りの条件だけ気にすればいい、という状態にする
    - $X_j+Y_j\geq Z_j$ のときは、$Y_j$ と $T_i$ の大小関係だけ見ればいいので、BITかセグ木で殴れる
    - そうでない時は、$X_j\leq S_i<Z_j-Y_j$ の範囲だけに対しては $Z_j\leq S_i+T_i$ を満たすか見る、$Z_j-Y_j\leq S_i$ については $Y_j\leq T_i$ を満たすか見る
    - これで気にすべきパラメータを絞れたので高々 $Y_j$ 用と $Z_j$ 用、2本のセグ木で処理できる（使いまわせば1本でも済む）
    - セグ木に対する取得のタイミングとかが一個一個のクエリからいい感じには定まらないし、そもそも異なるタイミングで複数の取得が必要な場合もある（たとえば $S_i$ を区間で挟むなら2回取得して引き算する必要がある）ので、セグ木に対して必要な取得操作をまとめておいてソートすると吉

以上でした。これで強そうなデータ構造を使わずに、セグ木1本でこの問題が解けました。
SegmentTree on SegmentTreeとかいらないでしょ？（威圧）
ところでガストのチーズinハンバーグって、名前的にハンバーグは脇役でチーズが主役ですよね。（どうでもいい）

# 実装
[これ](https://atcoder.jp/contests/joisc2019/submissions/10064684)を見てください。
結構コードが汚くてごめんなさい。

# おわりに
データ構造の知識がないとこういう変な考察で変な解き方をすることになります。
勉強はちゃんとしましょう。
ねむいですね。おやすみなさい。
postgresで任意のid順にorder by

# 任意のid順にorder by
例えば手元にこのようなidsがあり、このidsの順番でuserを取得したいとき

```ruby
ids = [2,3,1,10,9]
```

これでうまくいくかも


```ruby
users = User.order("COALESCE(array_position(ARRAY[#{ids.join(",")}], id), 0) asc")
```

たまにこういうこと並び順が必要になること
ありますよね
PHP クラスの定義とインスタンスの作成

# 目的

- クラスの定義方法とインスタンスの作成方法を記載する

# 用語

- クラス内で定義される変数: プロパティ
- クラス内で定義される関数: メソッド

# クラスの定義

- 下記にUserクラスを定義する。
- nameプロパティを定義する。
- Hi, i am プロパティとなるようなsayHiメソッドを定義する。

```php
class User 
{
    // プロパティの宣言
    public $name;

    //constructの宣言
    public function __construct($name) {
        $this->name = $name;
    }

    // メソッドの宣言
    public function sayHi() {
        echo "Hi, i am $this->name";
    }
}
```

# インスタンスの作成

- 先に定義したクラスの下で下記の行を記載する。

```php
$miriwo = new User("miriwo");
```

# インスタンスのメソッドを使用する

- 下記にUserクラスを元に作成したmiriwoインスタンスを使用してsayHiメソッドを実行する。(>の後ろは出力)

```php
$miriwo->sayHi();
>Hi, i am miriwo
```
React基本

## JSX
FaceBookが開発したjavascript拡張機能。HTMLタグをjavascriptの中に書ける。実際はBabelを使ってHTMLの部分をjavascriptのプログラムに置き換えている

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>

  <body>
    <div id="app"></div>
    <script src="app.js"></script>
  </body>
</html>
```

```jsx
// jsxを使用できるようにreactのモジュールをimport
import React from "react";
import ReactDOM from "react-dom";

// 描画関数のReactDom.renderにh1タグを渡して'app'に描画する
const app = document.getElementById('app');
ReactDOM.render(<h1> Hello </h1>, app);
```

### 注意点
1. コンポーネント名は大文字から始める
* class属性は「className」と書く
* returnで戻すタグは一つ。複数返したい場合はdivとかでくくる
* 閉じタグがない場合はエラー
* 属性値は""でくくる。テンプレート文字列(``)は指定できない
* {}でくくるとjavascriptが使用できる

```jsx
import React from "react";
import ReactDOM from "react-dom";

// 関数コンポーネント。大文字から始める
const App = () =>{
  // class属性はclassName
  // 属性値は””でくくる
  // 戻すタグはdivなどで一つにまとめる
  return (
    <div>
      <h1 className="greeting"> Hello </h1>
    </div>
  )
}

const app = document.getElementById('app');
ReactDOM.render(<App>, app);

```

## コンポーネント
独立した再利用可能な部品として分けられたもの

### 関数コンポーネント
```jsx
// JSXの項で描いたやつ
const App = () =>{
  return (
    <div>
      <h1 className="greeting"> Hello </h1>
    </div>
  )
}
```
### クラスコンポーネント
```jsx
// importしたReactモジュールのComponentを継承する
// renderメソッドに描画したい内容を定義する
class App extends React.Component {
  render(){
    return(
      <div>
        <h1 className="greeting"> Hello </h1>
      </div>
    )
  }
}
```
#### renderメソッドについて
renderは以下のタイミングでReactが自動的に呼び出す

* javascriptがブラウザにロードされた直後
* コンポーネントのpropsが変更された時
* コンポーネント内でsetState()メソッドを実行してstateが変更された時

※setState()を複数回呼んだからといって毎回render呼び出しされるわけではないみたい

[setStateを複数回実行してもrenderは1回しか呼ばれない](https://qiita.com/ichi944/items/75095a70e22d936d31e0)
[【翻訳記事】関数型setStateはReactの未来だ](https://career.levtech.jp/guide/knowhow/article/394/)

## State
コンポーネントが保持する状態、値のこと
### 注意点
* stateはthis.stateというインスタンス変数に格納される
* stateの更新は必ずthis.setState()メソッドを使用する
* this.setState()はrender()メソッドで呼び出してはいけない。this.setState()によってrender()が呼び出され再帰呼び出しエラーとなってしまうため

```jsx

class Human extends React.Component {
  constructor() {
    super();
    // stateの初期処理
    this.state = { name: '' }
  }

  setName(){
    const name = this.getName()

    this.setState({ 
      name: name
    });
  }
   ...

  render(){
    return(
      <div>
        <h1>{this.state.name}</h1>
      </div>
    )
  }
}
```

## Props
コンポーネントに渡されるパラメータのこと

```jsx
class Human extends React.Component {
   ...

  render(){
    return(
      // Greetingコンポーネントのnameにパラメータを渡す
      <Greeting name={this.state.name}>
    )
  }
}

const Greeting = (props) => {
  const greeting = this.currentTimeGreeting()

  return (
    <div>
      <h1>私は{props.name}です{greeting}!</h1>
    </div>
  )
}

```

## 参考
[公式ドキュメント](https://ja.reactjs.org/docs/getting-started.html)
[setStateを複数回実行してもrenderは1回しか呼ばれない](https://qiita.com/ichi944/items/75095a70e22d936d31e0)
[【翻訳記事】関数型setStateはReactの未来だ](https://career.levtech.jp/guide/knowhow/article/394/)
ESP8266とDHT11とAmbientを使って部屋の温度と湿度をグラフ化

#はじめに
wifiが使えるマイコン「ESP8266」と温度湿度センサー「DHT11」を使って「Ambient」という簡単にデータを可視化するサービスで部屋の温度と湿度を可視化していきます

###準備
ESP8266への書き込みはArduinoIDEを使用します。ArduinoIDEでESP8266を使う手順はこちらのサイトがわかりやすいです。「[ESP-WROOM-02開発ボードをArduino IDEで開発する方法 ](https://trac.switch-science.com/wiki/esp_dev_arduino_ide)」
グラフの生成にAmbientを使用するので、事前にユーザー登録とチャンネルの生成をしておきます
サービスの概要は「[Ambientを使ってみる](https://ambidata.io/docs/gettingstarted/)」を参照してください。
また、使用するためにAmbientライブラリをインポートする必要がありますのでこちらも併せて参照してください。「[Arduino ESP8266で温度・湿度を測定し、Ambientに送ってグラフ化する](https://ambidata.io/docs/esp8266/)」

ESP8266とDHT11の接続にはGPIOピン12番を指定してます
DHT11のライブラリは「DHT sensor library」を使用しています
![Screenshot from 2020-02-13 08-17-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584794/0337e784-7a2b-99a6-45df-2faba212ad32.png)

Linuxでのシリアルポートへのアクセスは「[https://www.arduino.cc/en/Guide/Linux](https://www.arduino.cc/en/Guide/Linux)」を参照してください

###コード
```c
#include <ESP8266WiFi.h>
#include <Ambient.h>
#include "DHT.h"

// DHT11の設定
#define DHTPIN 12        // 使用するGPIOピン
#define DHTTYPE DHT11   // DHT 11
#define channelId ****  // 生成したAmbientチャネルID
#define writeKey "****"  // Ambient のライトキーをセット

WiFiClient client;
DHT dht(DHTPIN, DHTTYPE);
Ambient ambient;

//WiFiのIDとPASS
const char *ssid = "****";  //wifiのssid
const char *password = "****";  //wifiのパスワード

void setup() {
  Serial.begin(115200);
  // WiFiに接続
  Serial.println(ssid);
  Serial.print("Waiting for Wi-Fi connection");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");


  ambient.begin(channelId, writeKey, &client);  //  チャネルIDとライトキーを指定してAmbientの初期化
  dht.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
    // DHT11から読み込み
    float t = dht.readTemperature();
    float h = dht.readHumidity();
    delay(200);
    if (isnan(t) || isnan(h)) {
      Serial.println("Failed to read from DHT sensor!");
      return;
    }
    //シリアルモニターに温度・湿度の表示
    Serial.println("Temperature: " + String(t) + "C   Humidity: " + String(h) + "%");

    //Ambientに温度と湿度を送る
    ambient.set(1, t);   //データセット          
    ambient.set(2, h); 
    ambient.send();   //  Ambientにデータを送信  
    //データ取得頻度
    delay(1000*60);  //1000ミリ秒＝1　*60秒なので1分
}
```
データ送信がうまく行っていたら自動的にグラフが作られます
こんな感じ　※この画像のグラフでは30分置きにデータ取得してます
![Screenshot from 2020-02-12 23-08-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584794/786f90ab-741b-2822-414c-a954e2d2ec80.png)
グラフ名は自分で変更してます

###最後に
今回はambientというサービスを使って温度と温度を可視化を解説してみました
グラフを簡単に作成してくれる便利なサービスなのでぜひ使ってみてください

次回はIFTTTを使ってLINEに温度と温度を通知してくれるプログラムを作ります！

####追記
elchikaにも記事を投稿しました。
(https://elchika.com/article/80b5bc1c-6b88-4aff-98ec-5fdfa4bd4695/)
Raspberry Pi上のDockerで動くイメージのCIでのビルド方法

## 発端
x86_64アーキテクチャ上でビルドしたDockerイメージが、Raspberry Pi上で動かない。
（Kubernetesクラスター on Raspberry Piでうまく動かなかった）

エラー内容

```
standard_init_linux.go:211: exec user process caused "exec format error"
```

## 理由
ビルドしたマシンと、Raspberry PiとでCPUアーキテクチャが異なるため。

```console
# 普段使ってるLinux
$ uname -m
x86_64

# Raspberry Pi
$ uname -m
armv7l
```

## 対策1
Raspberry Pi上でイメージをビルドする。
この時、`FROM node`ではなく、`FROM arm32v7/node`等、arm用のベースイメージに変更する必要がある（場合もある）。

## 対策2
対策1には実機が必要になる。
CIでイメージを作成したい場合等には利用できない。（ほとんどのCIはx86_64アーキテクチャなので）

そこで、[multiarch/qemu-user-static](https://github.com/multiarch/qemu-user-static)を利用することで、x86_64アーキテクチャ上でarm用イメージをビルドできるようになる。

### 例
```yaml
name: main

on: [push, pull_request]

jobs:
  main:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: setup docker for arm
        run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
      - name: build image
        run: docker build -f Dockerfile.arm -t owner/name:arm .
      - name: push image
        run: |
          docker login -u ${{ secrets.DOCKER_USER }} -p ${{ secrets.DOCKER_PASS }}
          docker push owner/name:arm
```
引数、スコープについて

変数はメソッドの中で定義するとそのメソッド内でしか基本使えません。
これをスコープといいます
ある変数を利用できる範囲のことです。スコープの範囲外の変数を使おうとすると、エラーが起こります。

その場合どうするかというと引数を使います。
引数はメソッドの外にある変数(スコープ外の変数)をメソッドの中で使うことができます。

postに入っているハッシュのデータを配列オブジェクトの中に入れたい場合

```ruby

def example
  post = {}
  post[:name] = "太郎"
  post[:age] = "25"
  post[:gender] = "男性"
　posts << post 
end

#配列オブジェクト
posts = []

```
こちらはエラーになってしまいます。
変数postsはexampleメソッドの外にあるためです。

そこで引数を使うと

```ruby

def example(a_posts)
  #ハッシュオブジェクト
  post = {}
  post[:name] = "太郎"
  post[:age] = "25"
  post[:gender] = "男性"
  a_posts << post 
  return a_posts
end

#配列オブジェクト
posts = []
posts = example(a_posts)
```
これで配列オブジェクトpostsにハッシュオブジェクトpostのデータが追加されるコードが書けました。
ssh先のvimへコピペできなくなった時は？

# 状況


- サーバー
 - Debian 10
- クライアント
 - Debian sid

ssh先でvimを開いた時、中ボタンでコピーしようとしてもコピーできず「@」などだけが出る。
ssh先へコンソールではコピーができる。

# 対策

### その1
env TERM=vt100 vim
などで起動する。

### その2
~/.vimrc に以下を追記し、vimでmouseを無効にする。

    set mouse-=a

以上
乃木坂メンバーブログのタイトル長さ選手権

こんばんは、乃木オタエンジニアです。先日、某メンバーのブログタイトルが長いこと人気メンバーのマネだと言われ、炎上のネタになっていて気になりました。そこで、私は以前、ブログ全記事スクレイピングし、そのデータがDBに全て残っているのでSQLでちょちょっとブログのタイトルの長さランキング取ってみました。
以前の記事　→　[乃木坂46公式ブログのスクレイピング～2011年からの全ての記事をDBに収めて画像も保存してやる！～](https://qiita.com/nirs_kd56/items/c03326a4f3c02cd6193f)

実際に流したSQLはこんなん。

```sql
select member_name ,AVG(CHAR_LENGTH(title)) as avarage_title_length from blog_articles
 group by member_name order by avarage_title_length desc
```

実行結果はこんな感じ

```
"member_name","avarage_title_length"
"齋藤飛鳥",187.0151
"掛橋沙耶香",36.0000
"金川紗耶",32.8148
"運営スタッフ",31.4010
"佐藤楓",26.5562
"和田まあや",25.1511
"向井葉月",20.5333
"早川聖来",20.1538
"筒井あやめ",20.1538
"高山一実",18.7571
"山下美月",18.6706
"研究生",18.4950
"清宮レイ",17.6538
"秋元真夏",17.3662
"柴田柚菜",17.1429
"樋口日奈",16.6295
"北川悠理",16.2963
"遠藤さくら",16.0000
"中村麗乃",15.9160
"中田花奈",15.3146
"伊藤純奈",15.1982
"与田祐希",15.0882
"松村沙友理",15.0815
"寺田蘭世",15.0077
"田村真佑",14.6923
"賀喜遥香",14.4615
"矢久保美緒",14.1538
"梅澤美波",14.0370
"伊藤理々杏",14.0282
"井上小百合",13.7735
"生田絵梨花",13.3581
"吉田綾乃クリスティー",13.2584
"岩本蓮加",13.1679
"阪口珠美",11.9316
"白石麻衣",11.5188
"久保史緒里",10.6154
"北野日奈子",10.3929
"星野みなみ",10.0398
"大園桃子",9.3818
"佐々木琴子",8.7203
"山崎怜奈",8.3864
"堀未央奈",7.3388
"新内眞衣",6.5158
"鈴木絢音",6.4566
"渡辺みり愛",6.0742
```
炎上していた某メンバーは確かに上位ですが、飛鳥ちゃんはダントツの長さなのです。こんなことでメンバーを叩くのは間違いですね。



ちなみにmaxを取ってみるとこんな感じ

```
"member_name","MAX_title_length"
"齋藤飛鳥",255
"北野日奈子",255
"中村麗乃",226
"掛橋沙耶香",140
"柴田柚菜",136
"山崎怜奈",122
"金川紗耶",119
"寺田蘭世",115
"中田花奈",112
"和田まあや",91
"梅澤美波",90
"松村沙友理",85
"佐々木琴子",83
"樋口日奈",83
"佐藤楓",76
"岩本蓮加",73
"研究生",70
"運営スタッフ",67
"向井葉月",65
"伊藤純奈",64
"高山一実",60
"渡辺みり愛",56
"井上小百合",53
"筒井あやめ",53
"与田祐希",48
"山下美月",44
"伊藤理々杏",43
"堀未央奈",42
"生田絵梨花",39
"早川聖来",39
"阪口珠美",36
"秋元真夏",35
"清宮レイ",35
"鈴木絢音",34
"北川悠理",33
"遠藤さくら",32
"新内眞衣",31
"賀喜遥香",31
"久保史緒里",28
"白石麻衣",27
"星野みなみ",27
"大園桃子",26
"吉田綾乃クリスティー",24
"矢久保美緒",22
"田村真佑",22
```

これは...もしかしてchar(255)の文字列がオーバーフローしている疑惑ですね。直さなきゃ。
そのうち乃木坂の音ゲーのランキングのスクレイピングをしたいなぁ。誰かサブ端末をください
若手の進捗管理

#始めに
進捗管理は皆さんは得意でしょうか？はっきり言って私は苦手です。
今の職場に配属されて1年以上が経ちますが、自分の作業の進捗管理が非常に難しいです。
ここでは自分の反省も兼ねて、これまでに行なってきた私の進捗管理の試行錯誤を書いていきたいと思います。

#どんな仕事か
とあるシステムの保守作業をしています。職場には正社員と派遣社員がおり、正社員が案件をリードして派遣社員が実作業を進めていく。という進め方です。
私は正社員ですが経験が浅いので、派遣社員の皆様と一緒にリードされながら仕事を覚えていっています。
そのうちにリードする側になるので、マネジメントの能力を付けたいと思うこの頃です。

#配属されてから3ヶ月まで
まずは言語や基本的な開発プロセスを覚えます。
その後、小さな案件の設計、製造とテストを実施しました。
製造はスムーズにいきましたがテストで遅れが発生！
テストは非常に時間がかかることを知りました。テストデータを作る必要があり、業務知識が圧倒的に足りず時間がかかり、残業で遅れをカバーしました。
初めての案件だったため、余裕のあるスケジュールを組んでいました。
ここで学んだことは、、
・知識不足を補う時間を予定に見積もる。

規模は大きくありませんでしたが、一通りの開発プロセスを体験することができました。

#配属されてから半年まで
初めて担当した案件より大きな案件を担当しました。この時もリードされる側の立場です。
ここでは製造とテストで遅れが発生しました。設計書に書ききれない製造のロジックと、膨大なテストケースに手間取りました。規模が大きくなると、さっき悩んだとこでまた悩む、というような非効率なことが起きて思うような進捗となりませんでした。
ここで学んだことは、、
・規模と時間は比例しないこと

#配属されてから1年
リードされながらの案件と、派遣社員の方をリードして案件を進める、の2つを行うようになりました。しかし自分の作業に夢中になって、作業を抱え込みすぎて遅れが発生しました。
ここで学んだことは
・割振れるものはどんどん割り振ること。、

誰かに作業依頼をすれば自分のタスクは半減します。依頼を面倒に感じるきらいがあると思うので、うまく派遣社員をマネジメントして、作業負荷を分散して進めていきたいです。
LeetCode - 56. Merge Intervals


# 問題
[56. Merge Intervals](https://leetcode.com/problems/merge-intervals/)

# Ver. 1

1. とりあえず `interval` を `merged_intervals` にほりこむ
2. `merged_intervals` の最後の要素 `[a, b]` を取り出して、次の `interval` の `[x, y]` と重なっているか判定
3. `interval` が重なってなかったら、`[a, b]`, `[x, y]` をそのまま`merged_intervals` にほりこむ
4. 重なってたら、`[a, b]`, `[x, y]` をマージしてほりこむ

- `intervals` は事前にソートされていないとうまくいかない
- `O(n^2)` を避けるため、ソートして、都度マージする

```ruby

# @param {Integer[][]} intervals
# @return {Integer[][]}
def merge(intervals)
  merged_intervals = []

  intervals.sort.each do |curr|
    last = merged_intervals.pop
    if last.nil?
      merged_intervals << curr
    elsif last[1] < curr[0] || curr[1] < last[0] # Last and curret are not overlapped
      merged_intervals << last << curr
    else # Last and curret are overlapped
      merged_intervals << [(last + curr).min, (last + curr).max]
    end
  end

  merged_intervals
end
```


# スコア

```yaml

Runtime: 88 ms, faster than 15.18% of Ruby online submissions for Merge Intervals.
Memory Usage: 9.8 MB, less than 100.00% of Ruby online submissions for Merge Intervals.
```

いまいち...

# Ver. 2

コメントいただいて、再度考えてみたバージョン

```ruby
# @param {Integer[][]} intervals
# @return {Integer[][]}
def merge(intervals)
  merged_intervals = []

  intervals.sort.each do |curr|
    last = merged_intervals.last
    if last.nil?
      merged_intervals << curr
    elsif last[1] < curr[0]  # Last and curret are NOT overlapped
      merged_intervals << curr
    else # Last and curret are overlapped
      last[1] = (last + curr).max
    end
  end

  merged_intervals
end
```

# スコア

```yaml

Runtime: 60 ms, faster than 44.64% of Ruby online submissions for Merge Intervals.
Memory Usage: 9.7 MB, less than 100.00% of Ruby online submissions for Merge Intervals.
```
だいぶよくなった
Swift TableVIew Realmを配列のように使いたいです。。。

Todoリストを作成したいのですが、よいデータの保存方法が見つからないので教えてください。

ネット記事を探しましたが、基本的な
BarButtonItemでUIAlertControllerを出して→　文字を入力　→　TableViewのcellに反映
という方法しか載っておらず困っています。

自分は
TableViewのcellにtextFieldを追加して、
cellのtextFieldに入力　→　エンターを押す　→　Realmで保存　→　下のtextFieldにカーソルが合う　→　cellのtextFieldに入力→　...
という処理を作成しました。

質問↓
Realmを配列のように保存したいです。
エンターを押したときにrealm.add(hogehoge)を行うと、
Realmの最後尾にデータが追加されてしまい、cellのtextFieldに対応してデータが保存・取得ができません。

記事で載っていたリスト？を使用したものも試しましたがうまくできませんでした。
サンプルになるコードなどあれば教えてください。よろしくお願いいたします。
【備忘録】Ruby : クラス変数の使い方

```ruby:sample.rb

class Num
	@@num = 1
	#クラス変数
	#インスタンスメソッドからでもクラスメソッドからでもアクセス可能
	#異なるオブジェクトでも同じクラスであれば値は共有可能
	#あまり使われることはないらしい
	def increment
		@@num += 1
	end

	def decrement
		@@num -= 1
	end

	def num
		puts @@num
	end

	def self.num
		puts @@num
	end
end

foo = Num.new
foo.num #=> 1
foo.increment #+1
foo.num #=> 2
foo.decrement #-1
foo.num #=>1
foo.decrement #-1

fuga = Num.new
fuga.num #=>0
#新しいオブジェクトを作ったのにも関わらず、fooオブジェクトでの処理を引き継いでいる。
#引き継がない場合は 1 からスタートするはず。


```
【NestJS】ヘルスチェック（v6版）

# やりたいこと

NestJS x TypeORM の環境で、DBまで一気通貫したヘルスチェック用URLを作りたい。
[terminus](https://github.com/godaddy/terminus)というNodeJS用のパッケージで、NestJS用のものがあるので、それを使います。

# NestJS 7 版

[こちらを参照してください。](https://qiita.com/piggydev/items/11a73d0c78b7f378ba61)

# 環境

- [NestJS 6.11.3](https://nestjs.com/)
- [TypeORM 0.2.25](https://github.com/typeorm/typeorm)
- [terminus 4.3.1](https://github.com/godaddy/terminus)
- [@nestjs/terminus 6.5.6](https://github.com/nestjs/terminus)

# インストール

```
yarn add @nestjs/terminus @godaddy/terminus --no-optional

// or

npm install --save @nestjs/terminus @godaddy/terminus --no-optional
```

参照: https://github.com/nestjs/terminus#installation

# 実装

- ほとんど、↓のページに書いている通りです。
  - https://github.com/nestjs/terminus#usage
  - ↑との違いは、 `async (): Promise<HealthIndicatorResult>` として、戻り値の型を定義しているぐらいです。 

- `src/health/health.module.ts` に置いていますが、場所は任意です。

```typescript:src/health/health.module.ts
import { TYPE_ORM_CONFIG } from '../config/app.config'

import { Module } from '@nestjs/common'
import {
  TerminusModule,
  TerminusModuleOptions,
  TypeOrmHealthIndicator,
  HealthIndicatorResult,
} from '@nestjs/terminus'
import { TypeOrmModule } from '@nestjs/typeorm'

const getTerminusOptions = (
  db: TypeOrmHealthIndicator
): TerminusModuleOptions => ({
  endpoints: [
    {
      url: '/health',
      healthIndicators: [
        // Set the timeout for a response to 300ms
        async (): Promise<HealthIndicatorResult> =>
          db.pingCheck('database', { timeout: 300 }),
      ],
    },
  ],
})

@Module({
  imports: [
    TypeOrmModule.forRoot(TYPE_ORM_CONFIG),
    TerminusModule.forRootAsync({
      inject: [TypeOrmHealthIndicator],
      useFactory: (db) => getTerminusOptions(db),
    }),
  ],
})
export class HealthModule {}
```

- `src/app.module.ts`で`imports`に追加します。

```typescript:src/app.module.ts
import { HealthModule } from './health/health.module'  // この行と、、、

   imports: [
     TypeOrmModule.forRoot(TYPE_ORM_CONFIG),
     HealthModule,                                     // この行を追加 
```

# 前提

↑の前提として、`TYPE_ORM_CONFIG`（`config/app.config`）に、DBの定義情報が設定されている必要があります。以下、例です。

```typescript:src/config/app.config.ts
import { TypeOrmModuleOptions } from '@nestjs/typeorm'

export const TYPE_ORM_CONFIG: TypeOrmModuleOptions = {
  type: 'mysql',
  charset: 'utf8mb4_bin',
  host: process.env.DB_HOST || 'localhost',
  port: +(process.env.DB_PORT || 3306),
  username: process.env.DB_USERNAME || 'root',
  password: process.env.DB_PASSWORD,
  database: process.env.DB_DATABASE || 'your_database_name_comes_here',
  entities: [__dirname + '/../**/*.entity.{js,ts}'],
}
```

# 動作確認ログ

```
$ curl -X GET "http://localhost:3000/health"
{"status":"ok","info":{"database":{"status":"up"}},"details":{"database":{"status":"up"}}}% 
```

```
// DBに対して SELECT 1 が実行されていることが確認できます。

$ yarn start:dev
:
{"level":30,"time":1581485016754,"pid":62278,"hostname":"xl.local","msg":"Server listening at http://0.0.0.0:3000","v":1}
query: SELECT 1
```