OmniAICreator/Qiita-1.07M huggingface dataset:
背景と背景の隙間

iSaraの模写していまして、
background-imageとbackground-color（オレンジ）の
間になぜか隙間ができます…
なぜでしょうか。

一時期は
body{
margin: 0;
}
したら隙間なくなって喜んでいたのですがどこそこいじっていたら
いつの間にかまた隙間が…

教えてください。よろしくお願いします。

<img width="1660" alt="スクリーンショット 2020-02-14 22.40.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586251/06fdfb58-0335-0e32-2fa6-dc41356fcaaa.png">
<img width="1680" alt="スクリーンショット 2020-02-14 22.41.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586251/2b45d211-662d-0aa2-6d97-23a1ddeb733b.png">
<img width="1680" alt="スクリーンショット 2020-02-14 22.41.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586251/86772c9c-a9df-78fe-b2df-e7084bfccb2f.png">
<img width="1680" alt="スクリーンショット 2020-02-14 22.41.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586251/3d97f70a-1b67-6555-ee57-f19ea45582aa.png">
<img width="1680" alt="スクリーンショット 2020-02-14 22.41.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586251/35697b9a-eba3-4129-a48b-6a100f1e8cd0.png">
Codeforces Round #615 B. Collecting Packages

シンプルな問題

# 概要
- x,yの二次元平面があり、たかだかマスは1000程度である
- 0,0にロボットがおり、UかRのアクションを行える
- 100個のnx, nyが順番に与えられる
- ロボットは各nx,nyを通過できるか判定せよ。YESの場合、例を１つ表示せよ。

# アプローチ
- 今の座標をx,yに対して、x <= nx かつ y <= nyであるかを判定。NGなら、"NO"が確定
- 可能なら、x軸の差分だけRを、y軸の差分だけUを表示する

```Python
q = int(input())
for q in range(q):
    qq = int(input())
    dat = []
    s = ""
    for _ in range(qq):
        x, y = map(int, input().split())
        dat.append([x, y])
        dat.sort(key=lambda a: a[0] + a[1])
    cx, cy = 0, 0
    f = True
    for i in range(qq):
        x, y = dat[i][0], dat[i][1]
        if x < cx or y < cy:
            f = False
            break
        s += "R" * (x - cx)
        s += "U" * (y - cy)
        cx,cy = dat[i][0], dat[i][1]
    if f:
        print("YES")
        print(s)
    else:
        print("NO")

```
https://codeforces.com/contest/1294/submission/69314972
Git 間違ってmasterで作業してしまった時のコマンド

思わずdevelopmenntのつもりで作業してしまった！　または止むを得ずmasterで作業せざるを得なかった場合のコマンド備忘録

特にデプロイ確認の際には本番環境で作業せざるをえない。

#作業内容を退避させる

```
$ git stash save
```
これでmasterで作業した分を一時保存

#新ブランチに移動

```
$ git checkout -b development
```

#新ブランチで作業内容を復元
```
$ git stash pop
```
これにて　マスターの作業内容が無事に新ブランチに移ったとさ。　チャンチャン！
APK is signed with Signature Scheme V3, which is not yet supported.で躓いた時のメモ

OculusGoのアルファチェンネルにアップロードしたときのエラー

結論
Unityでproject exportした後
AndroidStudioでV1署名したものをαチェンネルにアップロードすると回避できる


Unityのgradleファイルを編集しなさい。などネットには書いてあるがV2で署名されたりして
V1で署名できないので困った挙句

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312137/adf11b1c-2e4f-5e2d-0059-438f8dc6970b.png)


エクスポートして後は素直にreleaseビルドしたらいけた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312137/524ad7e4-6373-cc35-d059-ecee31ea2e29.png)
exportしたときのgradleファイルがうまく置換されていないっぽい
多重に生成されている&設定が反映されていない


Unity2018.4.8f1

参考にしたフォーラム（アドバイスは悉く通用しなかった）
chrome-extension://aclmceilickagfkaddbiedcnccdkfafa/blank.html?%26url%3Dhttps%253A%252F%252Fforums.oculusvr.com%252Fdeveloper%252Fdiscussion%252F73099%252Fapk-is-signed-with-signature-scheme-v3%2523latest
基本情報技術者　マネジメント系　第2章 プロジェクトマネジメント①


# ①ITサービスマネジメントの基礎
ITIL (IT Infrastructure Library):体系的にまとめた物として有名

##  SLA (Servise Level Agreement)
顧客(受け手)とプロバイダ(提供側)で合意したサービスの内容とレベルについて
詳細を記した文書です。

## ITILの概要
PDCAサイクルの考え方を取り入れており
サービスライフサイクルという概念で実践することにしています。

下記の五つの冊子で構成されています。

* サービスストラテジ(サービス戦略)
* サービスデザイン(サービス設計)
* サービストランジション(サービス移行)
* サービスオペレーション(サービス運営)
* 継続サービス改善

### サービスストラテジ(サービス戦略)

* 財務管理
* 需要管理
* サービスポートフォリオ管理

### サービスデザイン(サービス設計)
* サービスレベル管理
* キャパシティ管理
* ITサービス継続性管理
* 可用性管理
* サプライヤ管理

### サービストランジション(サービス移行)
* サービス資産及び構成管理
* 変更管理
* リリース及び展開管理

### サービスオペレーション(サービス運営)
* サービスデスク
* インシデント管理
* 問題管理


### 継続サービス改善(SLAより)
* サービスレベル管理
* サービス測定
* サービス報告
Djangoでレンタリングするhtmlを共通化する

# 概要

`<header>`や`<footer>`、jsやcssの参照先を定義した`<link>`や`<script>`をhtmlファイル単位で書いていたら保守性が低下する。
thymeleafの様に`Layout Dialect`で他のhtmlファイルを引用することはできないのか。
調べてみたところdjangoにはテンプレートの継承の概念があるのでこれを使うこととする。

[Djangoのテンプレート(html)の共通化と継承について](https://www.nblog09.com/w/2019/02/09/django-common-template/)

## htmlファイルの継承関係

参照元には共通化したhtmlタグを記載し、参照元によって切り替わる部分にはテンプレートタグ```{% block <ブロック名> %}～{% endblock %}```を挿入する

```html:parent.html
<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
{% block mainblock %}
(1)
{% endblock %}
    </body>
</html>
```

参照先にはテンプレートタグ```{% extends "htmlファイル名" %}```を記述し、切り替える内容にテンプレートタグ```{% block <ブロック名> %}～{% endblock %}```を挿入する
extendsに指定するhtmlファイル名にはdjangoで作成されたtempleteディレクトリ配下からのフルパスを指定する。

```html:child.html
<!DOCTYPE html>
{% extends "pull/parent.html" %} (2)

{% block mainblock %}
(3)
<div>
    <span>hello python!!</span>
</div>
{% endblock %}

```

(1).参照先によって切り替えるエリア。blockは複数指定できる。
(2).参照するhtmlファイルを指定する。
(3).参照元に挿入したいエリアを書く。

## レンタリング後

```html
<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <div>
            <span>hello python!!</span>
        </div>
    </body>
</html>
```

## 感想

* thymeleafだと参照元のhtmlタグにて宣言が必要だが、djangoではその必要がない。参照先htmlで使用するテンプレートを指定するだけで、理解が浅い私にもわかりやすかった。
* 切り替えたい部分をテンプレートタグで囲むだけでよいのがとても分かりやすい。thymeleafでは切り替えたいhtmlタグに```layout:fragment```を書いて切り替えるので、埋め込み用のタグが必要。
* java育ちのため継承と聞くと拡張したくなる。継承テンプレートを継承したテンプレートを参照することができるのか、できるけどそんなことしてよいのか･･･。暇があるときにでも試してみる。
【Sendgridからメールが送られない際の解決法】rails チュートリアル11章

rails チュートリアル11章を進めていて、Sendgridの実装に手間がかかりました。

他に書いてる人がいなかったので、記録として残します。


##したいこと
rails チュートリアルでSendgirdを実装したい。

##結論
動画のrails チュートリアル通りに作業するとうまくいきます。
文字のrails チュートリアル通りに作業するとうまく行きません。



文字のrails チュートリアル通りに進めるとメールが送られないようになっているようでした。

動画のrails チュートリアルだと別のコマンドを入力しておりまして、その通りに進めるとうまく行きました。


##【解決法】
railsチュートリアルのconfig/environments/production.rbに紹介されているコードを入力して保存したら、

```
$ git add -A
```

```
$ git commit -m "メッセージ"
```


```
$ git push 
```

```
 $ git push heroku
```

activated_trueに変更しているので、

```
$ heroku pg : reset DATABASE
```

（このコマンドが必要みたいです）

```
$ 削除するデータベースのアプリ名
```

```
$ heroku run rails db : migrate
```

```
$ heroku run rails db : seed
```



本番環境をリロードして再びログイン、またはサインアップ
→メールが送られてくる、完了です。


まとめ

幸運なことに私は動画のチュートリアル教材も視聴できる環境にあったので判明しましたが、文字だけのチュートリアル教材で進めている方にとっては気が付きにくいことだと思います。

railsチュートリアル特有の説明吹っ飛ばす系の問題でした。

かなりの初心者泣かせかなとwww

自分も早く初心者を卒業して初心者に優しい教材を作れるようになりたいです。
fish3.1.0でpyenvの初期化失敗の対処方法

## tl;dr
`~/.config/fish/config.fish` のpyenv(rbenv)の行を以下の用に変更すると問題が起きなくなります。

before

```
. (pyenv init - | psub)
. (rbenv init - | psub)
```

after

```
source (pyenv init - | psub)
source (rbenv init - | psub)
```

## 発生する問題
fish3.0.2までは `.` コマンドを使うことができたのですが、どうやら fish3.1.0から使うことができなくなったようです。
これは<a href="https://fishshell.com/docs/current/cmds/source.html">元から予告されていたこと</a> ではありますが、

```
. (a single period) is an alias for the source command. The use of . is deprecated in favour of source, and . will be removed in a future version of fish.
```

ついになくなってしまったんですね(泣)

bash系のコマンドを使っていたり、 `.` コマンドをなんとなく使っていたという方はこれを機に設定ファイルを見直す必要があります。

pyenv(rbenv)の初期化の構文でも `.` コマンドを使うことが一般的ですが、fish3.1.0で動かすと以下のようにエラーメッセージが発生してしまいます。

```
source: Error encountered while sourcing file '/var/folders/yv/0npp741974sgp79671hf_48c0000gn/T//.psub.pxGqFIeIaF':
source: No such file or directory
source: Error encountered while sourcing file '/var/folders/yv/0npp741974sgp79671hf_48c0000gn/T//.psub.VyHOD74WrY':
source: No such file or directory
```

## 終わりに
このようなエラーが出たら冒頭で紹介した通り、 `source` コマンドを使うようにすれば問題なく動くようになります。
僕も今朝この問題に悩まされたので、他に困っている方がいたら参考にしてください〜〜
EXCELがあまりに遅いので、ゲームPCを買いに走った話

工場で使っているノートPCがあまりにも遅いので、一般向けではなく、ゲームPCに買い替えました。
NC旋盤の、在庫管理、生産管理、カルテ管理、出荷管理、部材発注管理、部品使用回数管理等などを
１つのExcelファイルに詰め込んでいますので、関数の数が半端ありません。

- [シートに定義されている関数を集める関数](https://qiita.com/matumoto_onga/items/d5ec309850cc378c7a8f)を参照。

関数の数を減らすため、EXCEL Insiderになり、動的変数を返す関数使いまくりです。

- [365日EXCELの強制終了に苦しむエンジニア（旋盤工）が、テクニックを詰め込んでみる。](https://qiita.com/matumoto_onga/items/83131c58c107f90d5220)を参照。

特に、パイプの[カッティングストック問題を解く](https://qiita.com/matumoto_onga/items/855b7e72c8646678c18d)場合や、Windows 10 Updateの処理時間は、
仕事が止まり地獄でした。



以前は、起動時間を考えて、終業時はスリープにしてからコンセントからの電源を落としていました。
以後は、OSの立ち上げも一瞬で、帰りは即Shutdownです。
買ったPCのスペックは以下の通りです。EXCEL専用なのでGPUにこだわる必要がなくて費用が抑えられました。

MSI GF63-9SC-082JP

CPU インテル® Core™ i7-9750H（2.6GHz / Turbo 4.5GHz / 6コア12スレッド）
GPU NVIDIA® GeForce® GTX 1650 Max-Q デザイン 4GB GDDR5
MEM 16GB（8GB ×2）DDR4 
SSD 256GB（M.2 NVMe） 
HDD 1TB
[TypeScript] TypeGuard とは

# TypeGuardってなに
条件ブロック内でオブジェクトの型を制限すること。

例えば、ある関数の中で `if (typeof hoge === "undefined") return` と
書いたとします。
するとその関数内では以後、`hoge`が `undefined`である事はないですよね。
こうやってオブジェクトが複数の型を持つ場合に型を制限することを指します。



## どういう時に使うのか？ 

どんな型のデータでも引数に受け取りたい時（例えばJSONデータやオブジェクト）。




関数の引数で`any`を使ってしまっているよ...lintが怒っている:thinking:（anyは使わないのがベスト）

そんなときはTypeGuardをして余計なものを排除しましょう。


## 実例

今回はURLに乗っているクエリパラメータの一部分の数字を取得して変数に格納したいケースですが、
背景は気にしないで結構です。雰囲気作りが大事だと思っているので背景をつけました:angel:（なるほだない）

```sample.ts

const hogeRound = null;

// まずURLの?で始まる検索クエリ部分を参照する
const { search } = location;

// 取得したクエリパラメータから1文字目を除いてオブジェクトにパースする
// この時点でqueriesはany型
const queries.roundId = qs.parse(search.substr(1));

function typeGuard (queries.roundId) {
  //求めてるid以外のクエリが入ってくる可能性を考慮してる
  if (queries.roundId) {
    // queries.roundIdという文字列をNumber型かつ数字に変換してroundIdに格納
    const roundId = Number.parseInt(queries.roundId, 10);
    // クエリvalueに数字以外が渡ってくることを防ぐ（型絞り込みその1）
    if (!Number.isNaN(roundId)) {
      // オブジェクトにパースする
      const queryId = JSON.parse(String(roundId));
 
      // number型でさらに絞り込む（型絞り込みその２）
      if (typeof queryId === "number") {
        // hogeRound.idはほぼnumber型
        hogeRound.id = queryId;
      
        hogeRound.id.type === "number"
      }
    }
  }
}

```

location.searchについては[こちら](http://www.htmq.com/js/location_search.shtml?aaa)へ
qs.parseについては[こちら](https://github.com/ljharb/qs)へ
substr()については[こちら](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/substr)へ
Number.parseInt()については[こちら](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/parseInt)へ
JSON.parse()については[こちら](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse)へ
typeofについては[こちら](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/typeof)へ


こうして入ってくるデータの型を制限することで`hogeRound.id`はほぼ間違いなくnumber型しか入らない形になりました（厳密には違いますが）。

このようにデータの型が確定された時に `true` を返す関数の事

おしまい。
引用したい部分をスクショしてOCRもしてTrelloにかっ飛ばす方法

論文読みながら「あ、この辺参照したいな」と思ったときに、即座にスクショで切り取ってTrelloで集積しておくシェルスクリプトです。既にevernoteとか何やらでそういう便利クリップ機能はたくさんあると思いますが、PDF閲覧ソフトとか電子書籍リーダーとか、ブラウザ以外でもとにかく切り取りまくりたい＆Trelloに入れたいという願望から、簡易的なシェルスクリプトを書いてみました。


- 手順
    1. スクショ取る（gnome-screenshot）
    2. ページ数とかキーワードとかのメモを書く（yad）
    3. OCR化する（tesseract）
    4. メールで送信（mutt）

以上です。要はTrelloのメールでカード追加する機能を使って画像を添付してメールしているだけ。OCRはおまけです。

ちなみにTrelloのメール機能は右上のShow MenuからMoreをクリックするとEmail-to-board Settingsというのが出てくるのでそれを使います。muttの設定は省略します。


```sh

#!/bin/sh

CITATION=$HOME/{スクショの保存先}
FILE=$CITATION/$(date "+%Y%m%d-%H%M%S").jpg
CONTENT=$CITATION/ocr.txt


#スクショる
gnome-screenshot --area --file=$FILE
if [ ! -f "$FILE" ]; then exit 1; fi
#メモる（yayのオプションはお好みで）
SUBJECT=$(yad --width=1500 --posy=50 --posx=250 --entry --entry-label="Reference" --no-buttons --enable-spell --spell-lang=fr)
#メモが空白だと自動的にキャンセルされ、取ったスクショも消える
if [ -z "$SUBJECT" ]
	then
        notify-send "Abort"
        rm -rf $FILE
	exit 1
else
#OCRる（今回はフランス語に設定）
tesseract $FILE stdout -l fra > $CONTENT
#メーる
mutt -s "$SUBJECT" {Trelloで設定されたカード追加用のメールアドレス} -a $FILE < $CONTENT
notify-send "Success"
fi

```

あとは適当にスクリプトを走らせるショートカットを割り当てます。自分はi3wmを使っているので``bindsym control+Shift+4 exec "~/.bin/trello-screenshot"``みたく設定しています。

スクショを指定ディレクトリに保管するようにしていますが、よくよく考えたらTrelloに送られているんだから、送信後に削除した方が良いのかもしれません。



---

例：

![Peek 2020-02-19 09-44.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38964/2da5866e-62b0-c656-cd3f-11f27f00dde6.gif)


OCRかけると若干反映が遅くなりますので不要な場合は外しておきましょう。

集めた引用を一つのリストに入れていきます。各章ごとのリストをあらかじめ作っておいて、必要なところにぽんぽん放り込んでいきながら、実際に引用する部分をOCRから抜き取ったり、考察を加えていったりすると良い感じの論文アウトラインが出来上がります。

Trelloは短い間隔で更新するとよく接続が切れるので（Trelloではなくplanyway側の問題？）、集中的な執筆には向いていないですが、カンバン形式でぼんやりとしたアウトラインを考えるのには向いていると思います。一人でやるならほぼ無料というのも有り難いです。

---

### おまけ

一応、日本語も試してみました。以下をif文中に追記して、名前が[jp]から始まるものを日本語で認識させてみます。

```sh

elif [[ "$SUBJECT" =~ ^[jp]* ]]
then
tesseract $FILE stdout -l jpn > $MCONTENT
mutt -s "$SUBJECT" {Trelloで設定されたカード追加用のメールアドレス} -a $FILE < $CONTENT

```

結果：

![Peek 2020-02-19 10-10.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38964/d5df3a52-dac4-e4dc-d7f8-130a35725d7c.gif)

元画像：
![Screenshot from 2020-02-19 10-21-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38964/27ef3f82-7cd7-bcbe-a112-fefb4fb871bb.png)

OCR：
![Screenshot from 2020-02-19 10-21-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38964/9f2934df-0575-bfa6-d91d-196c74887b26.png)



謎の空白と謎の漢字が発生しました。元画像が粗いせいもあるかもしれません。縦書きのファイルも同様にダメでした。

日本語OCR精度は今後に期待です。
Codeforces Round #617 D. Fight with Monsters

とてもシンプルな問題。

# 概要
- $n, a, b, k$が与えられる。
- n体のそれぞれ$h1, h2, \cdots ,hn$の体力を持つ
- 攻撃力aのあなたと、攻撃力bのライバルがいる。
- あなたは攻撃する敵を任意に選び、あなた->ライバルの順番に敵が倒れる(hp <= 0になる)まで攻撃を続ける
- あなたは全部でk回だけ、ライバルの行動をスキップできる(これをスキップと呼ぶ)
- あなたは最大で何体の敵にとどめを刺せるか？

# 例と考え方
- パラメータ: 6 2 3 3
- 敵: 7, 10 50 12 1 8
まず、1ターン(自分と相手の攻撃1回ずつ)で変動する敵のhpはa + bであるため、相手が倒れる直前のターンまでのダメージを引く、つまり、各hpをmod (a + b) = mod 5する。
- modした敵のhp: 2, 0, 0, 2, 3
12について例をとると、1ターン目、12 - 2 - 3 = 7 ⇒ 2ターン目、7 - 2 - 3 = 2になっているといった次第である。ところで、hp=0の値を5に変える。なぜなら、各ターンは相手のターンで終わるため、modをとって、hp = 0 となるケースは相手が倒してしまっているからである。
- modした敵のhp: 2, 5, 5 2, 3
この中で、hp <= a = 2の値を削り、得点とする。これらの敵は次のターンで必然的に倒せるからである。残りをソートすると
- 残りの敵: 3, 5, 5
となり、通常であればこれらの敵は、相手に倒される。しかし、各敵は、a + (a*k) >= 残りhpとなる最小のkのスキップを行えば倒すことができる。
残りの敵は倒すことができない。

# 実装
```Python
n, a, b, k = map(int,input().split())
odat = list(map(int, input().split()))
point = 0
dat = []
x = a + b # 1ターンで減る体力
for i in range(n):
    if 0 < (odat[i] % x) <= a: # 確実に倒せる敵
        point += 1
        continue
    # 倒せなかった敵はその数をリストに追加(0はa+bに変換)
    sonota = odat[i] % x
    dat.append(x if sonota == 0 else sonota)
# ソートする
dat.sort()
import math
for i in range(len(dat)):
    # 必要となるkを計算する
    needk = math.ceil(dat[i] / a) - 1
    # まだスキップ回数が余っているなら使う
    if needk <= k:
        k -= needk
        point += 1
    else:
        # スキップ回数が足りないなら終了
        # ソートしているのでこれより後の敵を倒せるわけがないから
        break
print(point)
```
https://codeforces.com/contest/1296/submission/70290227
[Firebase] Functionsを並列実行する

### 前置き

Firebase Functionsで、日次のバッチ処理をする場合に、処理を並列に実行して、すべての処理が完了する時間がを短くしたい場合がありました。具体的には、Firestoreのコレクション内の複数のドキュメントの一つ一つに、時間がかかる処理をしたい場合です。

なお、ここでの並列とは、Functions自体を複数に分けて、それぞれ別のインスタンス上で処理を実行させることを意味しています。Promiseを使った非同期処理による並列ではありません。

### Functionsを並列に実行する方法

Stack OverFlowに参考になる質問があります。
[How to invoke other Cloud Firebase Functions from a Cloud Function](https://stackoverflow.com/questions/45713690/how-to-invoke-other-cloud-firebase-functions-from-a-cloud-function)

* [Cloud Pub/Sub トリガー](https://firebase.google.com/docs/functions/pubsub-events?hl=ja)を使って、特定のトピックのFunctionsを複数実行させる
  * Pub/Subを利用するには有料プランにする必要がある
* [Firestore トリガー](https://firebase.google.com/docs/functions/firestore-events?hl=ja)を使って、Firestoreに複数ドキュメント作成して、onCreateイベントを複数実行させる
  * Firestoreトリガーが重複発火する問題がある（詳しくは「[Cloud FunctionsのCloud Firestoreトリガーの重複発火を防ぐ、より良いアプローチ
](https://tech-blog.sgr-ksmt.org/2019/12/16/104935/)」を参照）

※ どちらのケースでもFunctionsの呼び出し回数は増えるので課金に影響があります。

今回は、問題の少ない、Pub/Subを使ったアプローチを試してみました。

### Cloud Pub/Sub トリガーを使って、Functionsを並列実行する

FunctionsからPub/Subにメッセージを発行するには[@google-cloud/pubsub](https://github.com/googleapis/nodejs-pubsub)を利用します

```
npm install @google-cloud/pubsub
```

Functionsのサンプルコードは以下の通りです。

```
import * as functions from "firebase-functions";
import { PubSub } from "@google-cloud/pubsub";

// スケジュール実行される
export const scheduleFunctions = functions
  .region("asia-northeast1")
  .pubsub.schedule("*/5 * * * *") // 検証のため5分毎にしている
  .timeZone("Asia/Tokyo")
  .onRun(async context => {
    const pubsub = new PubSub();
    for (var message of ["hello", "world"]) {
      const data = JSON.stringify({ message: message });
      const dataBuffer = Buffer.from(data);
      // Pub/Sub 特定のトピックにメッセージ送信
      const eventId = await pubsub.topic("topic-functions").publish(dataBuffer);
      console.log(eventId);
    }
  });

// Pub/Sub 特定のトピックにメッセージ受信で実行される
export const topicFunctions = functions
  .region("asia-northeast1")
  .pubsub.topic("topic-functions")
  .onPublish(async (message, context) => {
    await new Promise(resolve => setTimeout(resolve, 5000)); // 検証のため5秒待つ
    console.log(Buffer.from(message.data, "base64").toString());
    console.log(context);
    return true;
  });
```

#### 実行結果

![スクリーンショット 2020-02-14 22.03.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30719/86934129-5b9f-bcfa-ed02-f5d7e37394b1.png)

### 制限

Functionsのスケーラビリティには[制限](https://firebase.google.com/docs/functions/quotas?hl=ja)があります。未検証ですが、最大同時呼び出し数 `1,000` に該当すると思います。
※上記のコードを使って、同時実行数100までは検証しました。

### まとめ

Pub/Subを使って、１つのFunctinosから複数のFunctionsを発行できました。業務への組み込みはこれからなので、まだ見えていない課題はあるかもしれません。

別の並列化の方法や間違っている部分があったらご指摘ください。
Flutter Dart VMの動作モード

# はじめに

FlutterのDartコードはDart VM (バーチャルマシーン) 上で動作していますが、デバッグモードとリリースモードの違いや仕組みについて簡単に解説します。

# 動作モード

動作モードにはデバッグモード (JIT) とリリースモード (AOT) の2種類が存在します。

## デバッグモード (JIT)

Flutterにおける通常のデバッグ時に利用するモードです。このモードでは、便利なホットリロード機能が利用できます。

JITとは`Just In Time`の略称で、実行時コンパイラと呼ばれるものです。クラスやメソッドなどの単位でコードが実行される時にコンパイルして実行するインタプリタな方式です。OSやCPUなどのプラットフォームに依存せずにコードを実行できるメリットがある一方で、速度的には遅くなってしまいます。

この速度が遅い欠点を改善するために、適応的コンパイル (Adaptive Compilation) という仕組みが導入されるのが一般的です。最初はインタプリタで実行時にコンパイルをするものの、頻繁にコールされるようなコードを最適化しながらコンパイルすることで、実行プログラムや環境に最適化する仕組みです。これにより初期はスピードが遅いものの、実行する時間が長くなるにつれ、パフォーマンスが上がっていく傾向があります。

このモード時においてFlutterは、Dartコード (バイトコード) を一つのバイナリデータ (flutter_assets/kernel_blob.bin) として固めて、Flutter Engine初期化時にDart VMにロードします。

## リリースモード (AOT)

Flutterにおけるリリース時のモードです。このモードでは、ホットリロード機能が使えません。

AOTとは`Ahead-Of-Time`の略称で、事前コンパイラと呼ばれるものです。C++のように実行前にコンパイラでビルドしてターゲットのOS/CPU向けの実行バイナリを作っておく方式です。

実行時にコンパイルの必要がないため、一般的にはJITよりも数倍のパフォーマンスが出せますが、プログラムの内容次第では以下のように実行につれて最適化が進み、逆にJITの方がパフォーマンスが高くことがあります。

<img width="480" alt="スクリーンショット 2020-02-14 22.12.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259963/464f3cbd-1b35-ebf8-1129-5ecbe2ee3d8a.png">

### スナップショット

AOT時、Dart VM自体が高速起動できる仕組みを保有しています。それがスナップショット機能で、Dart VMおよびRoot Isolateの起動高速化を実現しています。

ノリとしては同じ処理を毎回行うのは無駄なので、起動処理完了後の状態やコアライブラリをバイナリファイルとして保有しておき、Dart VM起動時にロードしちゃおう！そうしたら高速起動実現出来るじゃん！というパターンです。LinuxなどのOSでも良くあるスナップショットブートと同じようなイメージです。

# 参考文献
 * [Flutter engine operation in AOT Mode](https://github.com/flutter/flutter/wiki/Flutter-engine-operation-in-AOT-Mode)
 * [Dart VMソースコード](https://dart.googlesource.com/sdk)
【Laravel】foreachで配列回して送信したcheckboxのoldを取得する

# 環境
- PHP 7.4.1
- Composer 1.9.3
- Laravel Framework 6.14.0
- laravelcollective/html v6.0.3

# 結論
laravelcollective/html入れてFormファサード使ったら、勝手に直前の入力値をcheckedにしてくれました。
便利すぎて震えた。oldなんて書く必要なかったんや･･･

**Composer**

```shell

composer require laravelcollective/html
```

**View**

```php

{{ Form::open(['method' => 'POST', 'action' => 'HogeController@fuga']) }}
    {{ Form::submit() }}
    <ul>
    @foreach($items as $item)
        <li>
          {{ Form::checkbox('item_ids[]', $item->id) }}
        </li>
    @endforeach
    </ul>

    {{-- バリデーションエラー確認用 --}}
    @if ($errors->any())
        <div class="alert alert-danger">
            <ul>
                @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                @endforeach
            </ul>
        </div>
    @endif
{{ Form::close() }}
```

**Controller**

```php

public function fuga(Request $request) {
    $this->validate($request, [
        'item_ids' => 'required|array',
        'item_ids.*' => 'email' // わざとバリデーションをエラーにして確認
    ]);
    dd($request->item_ids);
}
```


# 余談
もちろん、Formファサードを使用しない以下のコードはcheckedされません。

```php

<input type="checkbox" name="item_ids[]" value="{{ $item->id }}">
```
【CroWish勉強会】 Docker基礎

#はじめに
勉強会を開催したのでまとめです。
https://crowish.connpass.com/event/166807/


#Dockerとnginxを使ってWebサーバーを構築する


``` 
// docker hubからnginxイメージを取得
$ docker pull nginx

// imageからコンテナを作成(80番から80番にポートフォワーディング)
$ docker run --name test_nginx -d -p 80:80 nginx

// コンテナが起動しているのかどうか確認
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
43305a573df9        nginx               "nginx -g 'daemon of…"   3 seconds ago       Up 2 seconds        0.0.0.0:80->80/tcp   test_nginx
```
http://localhost:80 にアクセスすると以下の画面がhyoujisareru
<img width="666" alt="スクリーンショット 2020-02-14 21.54.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328210/d934c867-fa43-4bae-d6a2-e3b910bc4a80.png">

##表示されるページを編集したい！

```
// コンテナを停止して削除
$ docker container rm `docker stop [container_id]`

/**
* コンテナを作成
* ホストのhtmlファイルをマウント
**/
$ docker container run --name test_nginx -v [表示したいhtmlがある絶対パス]:/usr/share/nginx/html -p 80:80 -d nginx

//nginxコンテナの中に入る
$ docker exec -it test_nginx /bin/bash 

// index.htmlの確認
root@43305a573df9:/# cat /usr/share/nginx/html/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Sample</h1>    
</body>
</html>
```

hennkousareteru
<img width="729" alt="スクリーンショット 2020-02-14 22.06.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328210/5a204fcd-e6f2-a273-b0b9-bbbdb6d3c39f.png">
RubyでS3内の5GB以上のファイルをコピーする 

S3で5GB以上のファイルをコピーするには、普通のコピーでは出来ずMultipart Copyを使う必要があります。
RailsサーバからS3内の5GB以上のファイルを同じS3内にコピーする記事が無かったのでやり方を書きます。

# gemのインストール
```
gem 'aws-sdk'
```

# コピー処理
Aws::S3::Resourceのcopy_toを使用します。
Aws::S3::Clientのcopy_objectだと恐らくMultipart Copyが出来ません。

```ruby
s3 = Aws::S3::Resource.new(
      region: 'reagion_name',
      access_key_id: 'access_key',
      secret_access_key: 'secret_key',
    )
bucket = s3.bucket('bucket_name')
object = bucket.object("src/file") # コピー元のobject key
object.copy_to(bucket: 'bucket_name', key: "target/file", multipart_copy: true) # コピー先のobject key
```

# 参考
https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html
SwiftUIのおすすめ参考サイトまとめ

##無料

####Hacking with swift
https://www.hackingwithswift.com/quick-start/swiftui

####Medium（一部有料）
https://medium.com/tag/swiftui

####Liquidcoder
https://liquidcoder.com/

####Kavsoft
https://kavsoft.tech/index.html

####reddit
https://www.reddit.com/r/SwiftUI/

##有料
####DesignCode
https://designcode.io/swiftui?promo=learnswiftui


##動画
####Hacking with swift
https://www.youtube.com/channel/UCmJi5RdDLgzvkl3Ly0DRMlQ

####Kavsoft
https://www.youtube.com/channel/UCsuV4MRk_aB291SrchUVb4w/playlists

####DesignCode
https://www.youtube.com/playlist?list=PLDaHCLWmCcQLL-3YDxnPgG8VENNUiJ0Nv
ESP8266でNTPサーバから時刻を取得する

#はじめに
電子工作をやってると、特定の時間や一定時間ごとに動かしたいという動作が出てくる。
そういう時にNTPサーバから時刻を取得したら便利かなと思ったので、このやり方で正しいのかわからないけど書き記しておきます。

###準備
ArduinoIDEのスケッチ＞ライブラリをインクルード＞ライブラリを管理から「ライブラリマネージャ」を開き「NTPClient」をインストールする。
![Screenshot from 2020-02-14 20-57-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584794/b19b7bec-0bfe-ab97-4581-7cd547519445.png)

###とりあえず時刻を表示してみる
exapmleファイルから引用

```c
#include <NTPClient.h>
// change next line to use with another board/shield
#include <ESP8266WiFi.h>
//#include <WiFi.h> // for WiFi shield
//#include <WiFi101.h> // for WiFi 101 shield or MKR1000
#include <WiFiUdp.h>

const char *ssid     = "WiFiのSSID";
const char *password = "WiFiのパスワード";

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

void setup(){
  Serial.begin(115200);

  WiFi.begin(ssid, password);

  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( "." );
  }

  timeClient.begin();
}

void loop() {
  timeClient.update();

  Serial.println(timeClient.getFormattedTime());

  delay(1000);
}
```

![Screenshot from 2020-02-14 21-15-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584794/37c04ca9-0609-3e58-8198-32925b68c0de.png)
UTC時刻だけど表示出来た。
日本標準時にするには

```
//NTPClient timeClient(ntpUDP);を以下に書き換える
NTPClient timeClient(ntpUDP,32400);
```

###時/分/秒(HOUR, MINUTE, SECOND)を別々に表示する
時/分/秒を別々に取得出来たほうがより便利かなと思ったので一応…
timeClient.getMinutes()で分を取得できる。時や秒も同様に

```
 Serial.println(timeClient.getHours());
 Serial.println(timeClient.getMinutes());
 Serial.println(timeClient.getSeconds());
```
![Screenshot from 2020-02-14 21-48-27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584794/8c81bf3a-a9ea-9abe-15d9-d9b41e6d5988.png)
出来た。
ただ、1秒毎の取得だとNTPサーバに負荷がかかりそうだけどどうなんだろうか…

###追記
elchikaに記事を投稿しました。
(https://elchika.com/article/fe06afea-ee55-43ab-8952-8acc96f56778/)
【Laravel】Homestead環境でログを確認する

# 環境
- Laravel Homestead 9.2.0
- Nginx 1.15.8
- Laravel Framework 6.14.0

# アクセスログを出力する
デフォルトだとNginxのアクセスログが出力されないため、出力するように設定を変更します。

```nginx:/etc/nginx/sites-available/homestead.test（更新前）

access_log off;
error_log /var/log/nginx/homestead.test-error.log error;
```

↓

```nginx:/etc/nginx/sites-available/homestead.test（更新後）

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/homestead.test-error.log error;
```

設定ファイルを更新したら、Nginxを再起動して設定を適用します。

```shell

sudo service nginx restart
```

# ログを確認する
3つ目に指定しているアプリログは、アプリケーションのルート（Homestead.yamlのfolders-to）から見て storage/logs/laravel.log にあります。

```shell

tail -f /var/log/nginx/access.log /var/log/nginx/homestead.test-error.log ~/code/Laravel/storage/logs/laravel.log
```

# アプリケーションでログを吐いてみる

```php

use Illuminate\Support\Facades\Log;

Log::Debug('test'); // [YYYY-MM-DD HH:MM:SS] local.DEBUG: test
```

ちなみに、開発中のデバッグ用にログを仕込むのはオススメしません。
Laravel Debugbarという高機能なデバッグツールがあるため、それを使うのが一般的です。
もしくは、Laravelにはdd(), dump()といったデバッグ用のメソッドが標準で用意されています。
これらを使うと配列などを見やすく整形して表示してくれるため便利です。
EXCELで５ミリ方眼旋盤CAD（図形情報)

[前回](https://qiita.com/matumoto_onga/items/f587ea214b12b80da43a)の作図した図形情報を一覧にするプログラムを定義します。
QL_INITは、図形情報を収納する領域を確保し、"NAME"というタイトルを付けます。


[RANGE関数をさらに拡張し組込む](https://qiita.com/matumoto_onga/items/b150c14c7c58b9c88839)に伴って、QL_INIT()を書き換えて、関数M_()を廃止しました。

```vb
Function QL_SHAPES(Optional S = "")
    On Error Resume Next

    S = QL_INIT(ActiveSheet.Shapes.Count, "NAME")
    
    For I = 1 To UBound(S)
         S(I, 1) = ActiveSheet.Shapes(I).Name
    Next I
    QL_SHAPES = S
End Function

Function QL_INIT(M, N, Optional L1 = 1, Optional L2 = 1, Optional S = "")
    On Error Resume Next
    If TR_(M) Then
        S = M
        S = QL_INIT(S, N, L1, L2)
             
    ElseIf TV_(M) Then
        S = QL_INIT(UBound(M, 1), N, L1, L2)
        
        For I = 1 To UBound(M, 1)
            For J = 1 To UBound(M, 2)
                S(I, J) = M(I, J)
            Next J
        Next I
        
    ElseIf TS_(M) Then
        S = QL_INIT(M_(M), N, L1, 1)
        
    ElseIf TS_(N) Then
        T = A_(N, ","): N = UBound(T) - LBound(T) + 1
        S = QL_INIT(M, N, 0, 1)
        For J = 1 To N: S(0, J) = T(J - 1): Next J

    Else
        ReDim S(L1 To M, L2 To N)
        For J = L2 To N: For I = L1 To M: S(I, J) = "": Next I: Next J
    End If

    QL_INIT = S
End Function
```
# QL_INITの説明

QL_INITは、関数M_(),A_()と自分自身を呼んでいます。
M_()は、文字列を２次元配列に、A_()は一次元配列に変換します。
引数の型を別の型に変換して、自分自身を呼びます。
そのさいに、引数に型宣言がされているとエラーに引っ掛かります。
VBAの引数型宣言は、有害無益のものだと思います。
VBAにかぎっては、型宣言不要のプログラミング作法で良いと思います。

```vb
Function M_(V, Optional S = "")
    On Error Resume Next
    
    T = SPLIT_(V, ",")
    N = UBound(T) + 1
    U = SPLIT_(T(0), " ")
    M = UBound(U) + 1
    
    S = QL_INIT(M, N)
    
    For J = 0 To N
        U = SPLIT_(T(J), " ")
        For I = 0 To M
            S(I + 1, J + 1) = U(I)
        Next I
    Next J
    M_ = S
End Function

Function A_(V, Optional D = "")
    A_ = SPLIT_(V, D)
End Function

Function SPLIT_(V, D)
    SPLIT_ = Split(Trim_(V), D)
End Function

Function Trim_(V)
    Trim_ = WorksheetFunction.Trim(V)
End Function
```

# 恒投射について

関数QL_SHAPES()は引数を持ちませんので、自動計算されません。
そこで関数I_()を挟みます。

```vb
Function I_(A, V) ' 恒投射
    I_ = V
End Function
```
引数Aに適当なセルのアドレスを指定すると、指定したセルの内容の変化で、関数Vが呼ばれる仕組みです。

(AA1)  =I_(A1,QL_SHAPES())

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184069/c187fd8f-3bf7-b5f5-8693-94187483af0e.png)
Serverless Frameworkを使ったLambda+Pythonのローカル開発環境を構築

Windows上にServerless Frameworkを使ったLambda+Pythonのローカル開発環境を構築した時のメモ。実際にAWSにデプロイせずにローカルで単体テストまでできる環境を構築します。

# Pythonのインストール
[本家のWindows用ダウンロードサイト](https://www.python.org/downloads/windows/)から最新版(執筆時点では[3.8.1](https://www.python.org/ftp/python/3.8.1/python-3.8.1-amd64.exe))をダウンロードし、実行する。

最初の画面で「Add Python 3.8 to PATH」にチェックを入れて「Install Now」で標準インストールする。最後の画面で「Disable path length limit」をクリックして、パス文字列長の制限を解除しておく。

```
>python --version
Python 3.8.1
```
バージョンが正しく表示されればOK。

# pipenvのインストール
Pythonのパッケージ管理システムpipを使ってインストールする。

```
>pip install pipenv
(略)
Successfully installed appdirs-1.4.3 certifi-2019.11.28 distlib-0.3.0 filelock-3.0.12 pipenv-2018.11.26 six-1.14.0 virtualenv-20.0.1 virtualenv-clone-0.5.3

>pipenv --version
pipenv, version 2018.11.26
```

# Node.jsのインストール
Serverless FrameworkはNode.jsで作られているため、Node.jsのインストールをする。

[本家のダウンロードサイト](https://nodejs.org/en/download/)から最新版のWindows用インストーラー(執筆時点では[12.15.0](https://nodejs.org/dist/v12.15.0/node-v12.15.0-x64.msi))をダウンロードし、実行する。
オプションは特に変更しないでデフォルトのままインストールする。

```
>node --version
v12.15.0
```

# Serverless Frameworkのインストール
Node.jsのパッケージ管理システムnpmを使ってインストールする。

```
>npm install -g serverless
(略)
+ serverless@1.63.0
added 527 packages from 335 contributors in 21.542s

>sls --version
Framework Core: 1.63.0
Plugin: 3.3.0
SDK: 2.3.0
Components Core: 1.1.2
Components CLI: 1.4.0
```

# プロジェクトの作成
Serverless Frameworkのプロジェクトを作成。テンプレートはAWSのPython3用。

```
>sls create -t aws-python3 -p helloworld
(略)
Serverless: Successfully generated boilerplate for template: "aws-python3"
```

`-t`は使用するテンプレートの指定。AWS上のLambdaでPython3を使って開発するので`aws-python3`を指定する。
`-p`はプロジェクトディレクトリのパス(-nを指定しなければ、そのままプロジェクト名にもなる)

カレントパスの下にhelloworldというプロジェクトディレクトリが作成され、Serverless Frameworkの設定ファイルserverless.ymlとLambda関数の実装が書かれているhandler.pyと.gitignoreが作成される。

# Python仮想環境の作成
プロジェクトごとにPythonライブラリを管理するため、プロジェクトディレクトリの中に入り、このプロジェクト用の仮想環境を作る。

```
>cd helloworld
>pipenv install
Creating a virtualenv for this project…
(略)
Successfully created virtual environment!
(略)
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
```

# サンプル関数の実行
テンプレートに最初から定義されているhelloという名前のLambda関数をローカル実行してみる。

```
>sls invoke local -f hello
{
    "statusCode": 200,
    "body": "{\"message\": \"Go Serverless v1.0! Your function executed successfully!\", \"input\": {}}"
}
```

handler.pyに記述されたhello関数が実行され、レスポンスが返った。
`invoke local`で実行しているため、ローカル実行となる。

これでひとまずLambda + Pythonでローカル開発する環境が完成。
Get absolute path of running process


```shell

$ ps -ef | grep containerd

root      8723  8715  0 12:26 ?        00:00:01 containerd

```

If there have many commands with name containerd, the result may let some annoyance.

If you want to know the full path of the process, can do this:

```shell
$ ls -al /proc/8723/exe 
lrwxrwxrwx 1 root root 0 Feb 14 12:26 /proc/8723/exe -> /usr/local/bin/containerd
```
Ubuntu 18 で MySQL を使うのにやったこと

`Ubuntu 18.04.3 (LTS) x64` に `mysql` をインストールしてユーザーを設定するまでの手順。

## MySQL のインストール

```bash
# パッケージ目録の更新
$ apt-get update
# インストール
$ sudo apt install mysql-server
# インストールされていることを確認
$ mysql --version
$ sudo service mysql status
```

## MySQLのセキュリティ設定

```bash
$ sudo mysql_secure_installation
# パスワードがセットされたことを確認
$ sudo mysqladmin -p -u root version
```

匿名のユーザー、テストデータベースの削除。リモートでのrootログインを禁止するなどの設定をします。すべての回答にYにしました。
python3でAPIをコールする。

pythonの`urllib.request`モジュールを用いてAPIをコールするメモ。

# 下準備

* 適当なlambdaとAPI Gatewayを用意。

lambdaは受け取った`event`を返却するようにする。

```python
import json

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'body': event
    }
```

API Gatewayでは各種メソッド(GET、POST、PUT)を用意。

* メソッドリクエスト → APIキーの必要性`true`に指定。
* 統合リクエスト → lambda関数を指定。

[APIのデプロイ]を実行し、URIを取得。（API Gatewayで何かの更新をしたのなら都度デプロイすること！でないと反映されない。←めっちゃこれハマる。）

[使用量プラン]から[作成]を選び、APIステージを選択、レート・バースト・クォータを設定、APIキーを作成する。

# 本題のAPIを叩くlambda

```python
import json
import urllib.request, urllib.error

request_url = "https://xxxx.execute-api.ap-northeast-1.amazonaws.com/stage"

api_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxx"

def lambda_handler(event, context):
    headers = {'x-api-key': api_key, "Content-Type":"application/json"}

    request_json = {
        "key":"val"
    }
    
    req = urllib.request.Request(url=request_url, method="GET", headers=headers, data=json.dumps(request_json).encode())
    
    with urllib.request.urlopen(req) as res:
        body = res.read().decode()
    
    return json.loads(body)
```

# 参考
以下を加筆修正
https://qiita.com/j_tamura/items/5a22b102a58d1fa93a78
swiperをyarnで導入して、画像をスライダー形式にする！

## yarnとは？

JavaScript(node.js)のパッケージマネージャで、2016年にFaceBookが公開したものです。
他にもパッケージマネージャーとしては**「npm」**とう言うものものありますが、今回は、yarnを使います。

yarnの仕組みは簡単で、

１、使いたいパッケージをインストールする

```
$ yarn add 〇〇
```

２、```package.json```と言うファイルに、追加したパッケージに関する情報が記載される

３、開発環境下にパッケージ（関係するファイル一式）をインストール

```
$ yarn install
```

もしくは

```
$ yarn
```

コマンドを打つと、実行時に、``yarn.lock``と言うファイルの有無を確認し、なければ、先ほど追加された、``package.json``を見て、記載されているパッケージを開発環境下にインストールします。``yarn.lock``がすでに存在している場合は、``yarn.lock``を見て、インストールします。

似た挙動をするコマンドで、
```
$ yarn upgrade
```
と言うものもあるのですが、こちらは、yarn.lockがあっても無視して、もう一度、package.jsonを見て、インストールします！バージョンなどをあげた場合に、yarn installだと、yarn.lockを見てインストールするので、package.jsonに書いた新しいバージョンが適用されません。なので、こちらのコマンドを実行して、新たに、package.jsonを見て、yarn.lockを更新することが必要です。

以上のような流れです！

実は、gemの管理とよく似ていて、gemの場合は、Gemfileに記載されたgemは、どの環境でも```$ bundle install```すればgem同士の互換性など考慮して良しなに調整してインストールしてくれて使えるようになりますが、**yarn**も似たような管理方法で、``yarn.lock``か``package.json``確認して、そのアプリに導入されているパッケージを```$ yarn install```すれば、どの環境でも使えるようになります。

例えば、開発現場などで、ローカルにリモートリポジトリを``$ git clone``して、手元で開発する場合も、``$ yarn install``すれば、`yarn.lock``の有無を確認して、記載されているnodeのパッケージをローカルにインストールして環境構築できます。


それでは、yarnを使って画像をスライダー形式にできる「swiper」と言うパッケージを導入していきます。

swiperの公式サイトに行くと、以下のようなデモが見れて、ソースコードも見れますので、かなり便利です！
[![Image from Gyazo](https://i.gyazo.com/0fd93b74c068042830500a6f70f14be7.gif)](https://gyazo.com/0fd93b74c068042830500a6f70f14be7)

[![Image from Gyazo](https://i.gyazo.com/408599a6583cf89317164aea1c0f8726.gif)](https://gyazo.com/408599a6583cf89317164aea1c0f8726)

## yarnのinstall
まず、homebrewでyarnをPCにインストールします。

$ brew lsでyarnが既に入っているか確認できます。
[![Image from Gyazo](https://i.gyazo.com/7629b39ad05ccd05b32d19fceaac1c89.png)](https://gyazo.com/7629b39ad05ccd05b32d19fceaac1c89)

画面では一番最後のところに「yarn」の記載があるので、この場合はインストールされていますね。
記載がない場合はインストールされていないので、以下コマンでインストールします。

```
$ brew install yarn
```

## yarnでパッケージを導入

package.jsonを作成するために以下のコマンドを打ちます。（gemで言う所の$ bundle initに似てますね。）もともとファイルがあればやる必要はないです。

```
$ yarn init
```

次に、swiperを導入します。

```
$ yarn add swiper
```
こうすると、package.jsonにswiperの記載がなされるはずです！

インストールします。

```
$ yarn install
```

必要なファイルがnodeディレクトリ配下に作成されます！

[![Image from Gyazo](https://i.gyazo.com/96b21aa60063294843dd2028f6864d38.png)](https://gyazo.com/96b21aa60063294843dd2028f6864d38)

## 導入したファイルの読み込み設定

マニフェストファイルに導入したファイルのpathを記載して、読み込みの設定を書きます。

例）

```js:assets/javascript/application.js
//= require swiper/js/swiper.js
//= require swiper.js
```
ディレクトリのpathはnode部分は省略できるので、swiperから書きます。```//= require swiper.js```は、後ほど、viewと連動させるためのファイルの読み込みを書いていますが、ここは各自でやり方は色々あると思います。

scssにもスタイルの読み込みを書きます。

```scss:assets/stylesheets/application.scss
@import 'swiper/css/swiper';
```
この後の部分の記載を失念してしまうのが、ハマりポイントで、私もハマりました。

導入したnode以下のファイルを読み込むようにするための設定を書く必要があります

```ruby:config/initializers/assets.rb
Rails.application.config.assets.paths << Rails.root.join('node_modules')
```
これで準備は完了です。

あとはview側の実装や、jsファイルの作成などは、swiperの公式ドキュメントを見れば、コピペで実装できます！

https://swiperjs.com/demos/

yarnでswiperを導入するところまでの解説でした！
【Rails】中級者になるためのリファクタリング

Railsのリファクタリングの記事は、良記事がたくさんあります。

でも「初心者向け」を謳っているにしては項目が多くて、**いきなり全部を意識するのは無理だな**ってなりました。初心者向けって謳い文句の記事に、自分のできていないことがたくさん書かれていると「お前は初心者以下だ」って言われているみたいでちょっと嫌な気持ちになりますね。

他の方が書いた記事の中から、私がまず意識しようと思ったことをピックアップしてまとめようと思います。

##controllerを薄く、modelを厚く
可能な限り処理をメソッドとして切り出して、controllerを薄くします。
modelがFatになることは、最初は目をつぶります。

##viewの中の処理をhelperに移す
viewの中に処理がゴチャゴチャと書かれていると、コードが混沌としてしまうので。

##パーシャルを使う
パーシャルを使って、可読性と再利用性を上げます。
※使いすぎるとパフォーマンスが下がるので注意

##繰り返し使う文字列をlocaleに定義する
コードをDRYに。時刻のフォーマット等もlocaleを使い、`strftime`は基本使わない。

##コードの行数を減らす
基本的に以下の記事からのピックアップです。超良記事なのでまだ読んでいない人はぜひ。
[[初心者向け] RubyやRailsでリファクタリングに使えそうなイディオムとか便利メソッドとか](https://qiita.com/jnchito/items/dedb3b889ab226933ccf)

最初はとっつきにくくても、短く書ける記法はどんどん使って慣れていくべき。慣れたら難しくないものも多そうだし、他の人が書いたコードを理解する能力も上がる。
とはいえ全部いきなりは大変なので、まずは以下を意識する。

###なるべくネストしない
早めにreturnで返すなど、出来るだけネストを減らすことを意識します。

###後置if
```rb
send_mail_to(user) if user.active?
```
###三項演算子
```rb
user.admin? ? "I appreciate for that." : "Thanks"
```
###ぼっち演算子
```rb
#if parent.children && parent.children.singleton?
if parent.children&.singleton?
```
### ||=でnilだった場合のみ代入
```rb
@twitter_client ||= Twitter::REST::Client.new 
```

##その他書き方
###if + notではなく、unless
```rb
user.destroy unless user.active?
```
条件にorとかandが含まれる時は複雑になるので`if`を使う

###戻り値を返すときにreturnを使わない
```rb
def build_message(user)
  message = 'hello'
  message += '!!' if user.admin?
  #return message
  message
end
```
###+ではなく#{ }
```rb
#"Hello, " + user.name + "!"
"Hello, #{user.name}!"
```
##%w( )、%i( )
```rb
#actions = ['index', 'new', 'create']
actions = %w(index new create)
#actions = [:index, :new, :create]
actions = %i(index new create)
```

##いつかやる
・他の便利な文法いろいろ
・RESTなcontrollerを意識する
・Concern(controllerで共通で使う処理をまとめるやつ)を使う
・デコーダー?ViewModel?
・サービスクラス?

##参考
[[初心者向け] RubyやRailsでリファクタリングに使えそうなイディオムとか便利メソッドとか](https://qiita.com/jnchito/items/dedb3b889ab226933ccf)
[脱Rails初心者のためのリファクタリングガイド](https://qiita.com/ysi/items/fba39c5c5992d686b7a5)
[実務で学んだRailsの設計・リファクタリング](https://qiita.com/wawoon/items/08ee0e4230893a770cce)
VBA 結合されたセルの解除と解除した全セルに値を設定


## 全カラムのマージを解除

```
'全カラムのマージを解除
Private Sub UnMargeAllCell(ByRef wsWorkSheet As Worksheet)
    
    Dim rngRange                As Range
    Dim strMargeAreaAddress     As String
    
    For Each rngRange In wsWorkSheet.UsedRange
        If rngRange.MergeCells = True Then
            strMargeAreaAddress = rngRange.MergeArea.Address
            rngRange.MergeArea.UnMerge
            wsWorkSheet.Range(strMargeAreaAddress).Value = rngRange.MergeArea.Resize(1, 1).Value
        End If
    Next
    
End Sub
```

```
'範囲を指定して、セルの結合を解除（こっちの方がスピード的に現実的かな）
Private Sub UnMargeAllCell(ByRef wsWorkSheet As Worksheet)
    
    Dim strMargeAreaAddress     As String
    Dim lngLoopRow              As Long
    Dim lngLoopCol              As Long
    
    For lngLoopRow = 1 To 3
        For lngLoopCol = 1 To 200
            DoEvents
            Call dispInformationAtStatusBar("UnMerge " & lngLoopRow & "-" & lngLoopCol)
            If wsWorkSheet.Cells(lngLoopRow, lngLoopCol).MergeCells = True Then
                '解除前のアドレスを保持
                strMargeAreaAddress = wsWorkSheet.Cells(lngLoopRow, lngLoopCol).MergeArea.Address
                DoEvents
                'マージを解除
                wsWorkSheet.Cells(lngLoopRow, lngLoopCol).MergeArea.UnMerge
                DoEvents
                '解除したセルに値をコピー
                wsWorkSheet.Range(strMargeAreaAddress).Value = wsWorkSheet.Cells(lngLoopRow, lngLoopCol).MergeArea.Resize(1, 1).Value
            End If
        Next lngLoopCol
    Next lngLoopRow
    
End Sub
```

## 最終行と最終列

```
.Cells(.Rows.Count, 1).End(xlUp).Row
.Cells(1, .Columns.Count).End(xlToLeft).Column
```
flexboxはじめてみた

CSS3から新しく追加されたflexboxを初めて使ってみたので、自分の備忘録としてまとめてみる。

#そもそもflexboxとは
要素を中央寄せしたり、横並びにしたり、横並びの要素の高さを揃えたりできるもの。
要は、flexboxを使えば、これまでfloatやJavaScriptを使っていたものをより簡単に実装できる！

#書き方

使い方はとてもシンプル。まずはHTMLから。

```html:index.html
<body>
    <div class="container">
      <div class="item1">Item1</div>
      <div class="item2">Item2</div>
      <div class="item3">Item3</div>
      <div class="item4">Item4</div>
    </div>
  </body>
```

このHTMLに対してflexboxを適用させたい場合は、

```css:app.css
.container {
  display: flex;
}
```
これだけ。
これだけで横並びになる。


あとは、親要素に指定できるプロパティと子要素に指定できるプロパティがそれぞれあるので、
適用させたいスタイルに応じて利用する。

例えば・・・
・子要素（上で言えばitem1~item4）の並ぶ向きを揃えたい。
→flex-directionを使う。

```css:app.css

.container {
  display: flex;
  flex-direction: row;
}

```

これは子要素を左から右に並べる方法。
逆にこ要素を右から左に並べたい場合は、

```css:app.css

.container{
  display: flex;
  flex-direction: row-reverse;

```

にする。

などなど適用させたいスタイルによって様々なプロパティがある。


より多くのパターンを自分のものにしたい。
ファイルを読み込んで書き込む

test.txtというテキストファイルの中身が、
AAA
BBB
CCC
DDD
である場合に

```py:
s = """\
AAA
BBB
DDD
DDD
"""
with open ('test.txt', 'r+') as f:
    print(f.read())
    f.seek(0)
    f.write(s)
```

```:実行結果
AAA
BBB
CCC
DDD
```

でtest.txtというテキストファイルの中身は、
AAA
BBB
DDD
DDD
になる。

r+は読み込み+書き込み。
なので、
もしも、test.txtがないと、
読み込みができず、
エラーとなる。
お困りのあなたにgit stash！！

まず、はじめにgitは、１つの作業テーマに１つのブランチを作成して作業します。
だいたい機能追加とかバグ修正とかの単位でブランチを作って作業します。（ちゃんとやってますよね？）
そんな中で、こんな時ありませんか？

- ブランチを間違えて作業してしまっていた！！！やべ！！
- あるブランチで作業中だけど、いますぐ他のブランチでやりたいことができた。ブランチを切り替えるためにコミットしないといけないけど、作業すごく中途半端だからコミットはしたくない、、、
- 作業の途中で別の修正を優先してお願いされる、、、、そんな時は、別のブランチに切り替えないといけない。何も考えずブランチを切り替えるとエラー。。。

上記の場合、ブランチを切り替えたい、、、
でもコミットしていない変更点があってブランチを切り替えられず、「変更をコミットしてください」と怒られる
その時の解決策としては大きく2つあります。

- １つ目は、コミットしてしまうことです。<br>
　　ある程度編集が落ち着いているのであれば、アドしてコミットしてしまっていいと思います。
- 2つ目がgit stashを使うことです。 <br>
　　**こちらが今回の本題です。**

では、git stashについて説明します。

#git stashとは一時的に変更を保存すること
まず、git stashとは変更を一時的に保存しておくことです。
git stashをするとローカルの作業ファイルが綺麗な（変更点のない）状態になります
そうすると、自由にブランチを切り替えることができます。

#git stashの流れ
git stashの大まかな流れを説明します
##変更を一時退避させる
下記のコマンドでコミットをまだしていない変更点を一時退避します
コミットしていない変更点なので、addしているかどうかは関係ありません

```:ターミナル
git stash -u
```

###オプション-uについて
上記のコマンドについている-uは--include-untrackedの略です
Gitがまだ追跡を開始いていない新規作成のファイルも一時退避させるためのオプションです
このオプションをつけないと新規作成したファイルなどは一時退避されません

##コミットメッセージをつける
作業ファイルを確認してみましょう
変更した箇所が最新のコミット状態に戻っていると思います。
では、変更はどのように保存されているかを確認しましょう
下記のようなコマンドでコミットメッセージを残すことも可能です
コミットメッセージ`message`を残しています

```
git stash push ”message”
```

`git stash save`は非推奨となったようです

##一時退避を確認
確認は以下のコマンドでできます。
実行結果が一時退避させた変更点になります

```:ターミナル
git stash list

// 実行結果
stash@{0}: WIP on hoge_branch: 7ea2020 Update hoge.rb
```

実行結果について説明します。
スタッシュ名`stash@{0}`はブランチ名`hoge_branch`の作業でコミットハッシュ`7ea2020`のコミットメッセージ` Update hoge.rb`の変更です
以上が実行結果の内容です
###スタッシュした内容の詳細を確認する
下記のコマンドで一時退避した内容の詳細を見ることができます

```:ターミナル
git stash show　-p ハッシュ名
```
##別ブランチで作業スタート
一時退避ができていれば、`git status`などで作業ファイルが綺麗な状態か確認し、
ブランチを切り替えて作業をしましょう。

##一時退避を戻す
作業が完了したら元の状態に戻したいと思うので、戻していきましょう
下記のコマンドで一時退避を現在いるブランチに反映させることができます
下記のコマンドはスタッシュ名`stash@{0}`を反映させる時のコマンドです
スタッシュ名を指定しない時は直前のスタッシュが反映されます

```:ターミナル
git stash apply stash@{0}
```

##使い終わった一時退避を削除する
使い終わったスタッシュは削除しましょう
ためていくと履歴がカオスなことになるので、こまめに消すことをオススメします！！

```:ターミナル
git stash drop stash@{0}
```

以上がgit stashを使って行う作業の大きな流れです。

ここからは、もっと便利なgit stashの機能について説明します。
#その他の便利機能
##一時退避した内容を反映と削除を一緒にする
`apply`と`drop`をいっぺんにやってくれるコマンドです

```:ターミナル
git stash pop stash@{0}
```

##インデックスの内容もそのまま一緒に一時退避する
下記のコマンドでインデックスの内容(addしたファイル)をそのままに一時退避することもできます

```:ターミナル
git stash -k
```
オプション：`-k`　もしくは　`--keep-index`

##スタッシュを全て消す
下記のコマンドで一時退避したスタッシュを全部消すことができます
全て消えてしまうので注意してください

```:ターミナル
$git stash clear
```

以上です！！！
**ここまで読んでいただきありがとうございました！！
疑問、気になるところがございましたら、質問、コメントよろしくお願いします！！！**
初心者によるプログラミング学習ログ 239日目

#100日チャレンジの239日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

239日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>239日目<br>・youtubeで、javascriptのfizzbuzz問題模写<br>・udemyで、javascript講座<br>・photoshopで、バナー作成模写<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1228045245650128897?ref_src=twsrc%5Etfw">February 13, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【Poetry】Poetry script で Django の runserver を起動


## poetry script は関数の実行を行う

poetry には Pipenv のような scripts 機能があるが、npm scripts のように入力したものがそのままシェルで実行されるわけではない。
引数なしの関数の実行のみが可能である。

詳細については以前書いた記事があるので次のリンクを参考に。[【Python】Poetry始めてみた & Pipenv から poetry へ移行した所感](https://qiita.com/ragnar1904/items/0e5b8382757ccad9a56c#scripts)


今回は 1 コマンドで Django 開発サーバーを立ち上げられるように、簡単な script を書く。

## 環境

- python 3.7.4
- poetry 1.0.2

## 構成

`$ poetry install`した後、`$ django-admin startproject config .`を行った後のディレクトリ。  
`./scripts`に poetry scripts 用のファイルを書いていく。今回はサーバ立ち上げ用なので`server.py`とした。

```bash
.
├── config
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
├── poetry.lock
├── pyproject.toml
└── scripts
    └── server.py
```

## 作成

### script

以下の内容で作成。  
最初は`manage.py`を絶対パスで指定していたのだが、絶対でなくても動いた。

```python:scripts/server.py
import subprocess


def main():
    cmd = ["python", "manage.py", "runserver", "0.0.0.0:8000"]
    subprocess.run(cmd)
```

### pyproject.toml

以下を追加する。

```toml:pyproject.toml
[tool.poetry.scripts]
start = 'scripts.server:main'
```

これだけでは、`[ModuleOrPackageNotFound] No file/folder found for package <projectname>`となってしまう。

```bash
$ poetry run start

[ModuleOrPackageNotFound]
No file/folder found for package project
```

scripts のファイルがルートディレクトリ(pyproject.toml のあるディレクトリ)以下にある場合、  
パッケージディレクトリを指定してやる必要がある。

```toml:pyproject.toml
[tool.poetry]
name = "project"
version = "0.1.0"
description = ""
authors = [""]
packages = [
    { include="scripts", from="." },
]
```

これで起動出来る。仮想環境に入っていないシェルから実行しても、仮想環境内で実行してくれる。

```bash
$ poetry run start
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

February 14, 2020 - 10:41:57
Django version 3.0.3, using settings 'config.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
...
```

### ちなみに

この書き方で実行する poetry script は pyproject.toml のあるディレクトリで実行する必要がある。  
`from="."`としているので、poetry が`scripts`ディレクトリを見つけられない。

```toml:pyproject.toml
packages = [
    { include="scripts", from="." },
]
```
Raspberry PiにSuricataをインストール

# 目的
Raspberry Piを簡易Gatewayとして使いたい。
SuricataでIPS/IDSを作るというよりは、セキュリティの解析用環境からイケナイ通信が出ていくのを止めたり、特定の通信の発生をキャッチしたい。
でも、今回は、インストールと起動の確認まで。

# 前提
Raspberry PiのOSは、Raspbianで、WiFiルータ(WAN)に接続、eth0にDHCPサーバを設定している。
今回は、eth0のLAN側の通信を監視してみる。

# 手順
## Raspberry PiのUpdate　
以下の手順を参照して、Raspberry PiをUpdateする
https://qiita.com/tanuwo/items/04df160281153c0e24bc

## Suricataのインストール
結構みんな、公式サイトのinstallation見れば良いよと教えてくれている。
~~どれを見ろとは教えてくれていない。。。~~

Debianのインストール手順参照しました。
Suricata公式サイトのDoc>Suricata installation>Debian install

https://redmine.openinfosecfoundation.org/projects/suricata/wiki/Debian_Installation

手順の最後の部分だけメモ

```
./configure --enable-nfqueue --prefix=/usr --sysconfdir=/etc --localstatedir=/var
make
make install-full
ldconfig
```
make install-fullでルールのインストールも出来ているはず。

## Suricataの起動
公式サイトのBasic setupを参照してみる
https://redmine.openinfosecfoundation.org/projects/suricata/wiki/Basic_Setup

make install-fullしているので、ほとんどの手順は不要。

```
sudo suricata -c /etc/suricata/suricata.yaml -i wlan0 --init-errors-fatal
```
でサクッと起動して完了！！
と思いきや

```
Warning> - [ERRCODE: SC_ERR_NO_RULES(42)] - No rule files match the pattern /etc/suricata/rules/tls-events.rules
```
だって。

確かに`/etc/suricata/rules/`に`tls-events.rules`がいない。
そこで、downloadしたソースパッケージ内のrulesフォルダにtls-events.rulesがいたのでrulesフォルダ内のrulesファイルを全コピーしたところ解決。

再度、起動を試すと

```
<Warning> - [ERRCODE: SC_ERR_AFP_CREATE(190)] - Using AF_PACKET with GRO or LRO activated can lead to capture problems
```

GROやLROが有効だと出るエラーらしい。
※GRO/LROは、オフロード方法らしい(<=ちゃんと勉強しなさい)

## 
エラーを絶対に回避する必要があるか分からないけど、気持ち悪いので解決します。
以下のURLを参考にします。
https://ac-as.net/how-to-setting-nic-offload/

ethtoolがねぇので。

```
apt-get install ethtool
ethtool -k eth0
```
で見てみると、確かに`generic-receive-offload: on`となっている。

```
ethtool -K eth0  gro off
```
でGROをコロスと上手くいった。
今日はここまで、後は、自動起動と目的に合わせたルールの設定。


## 追記
### GRO無効化の恒久化

コマンドラインで`ethtool`を叩いただけだと恒久的な設定にはならないので、`rc.local`に以下の通り追記

```
/sbin/ethtool -K eth0 gro off
```
【iOS】アプリが閉じた状態でUniversal Linksでの起動をデバッグする

アプリが**閉じた状態**でのUniversal Links経由の起動を繰り返しデバッグしたい時のメモ

## 手順
1. `EditScheme` → `Wait for executable to be launched` をチェック
![Screen Shot 2020-02-14 at 19.51.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116582/401f34c7-f56b-f7bd-3888-6f7646757614.png)
これによって、Runした時にアプリが自動で起動しなくなります

2. アプリをRun(`Wait for executable to be launched`)
3. Terminalで以下のコマンドを実行

```
$ xcrun simctl terminate booted <bundle_identifier> && xcrun simctl openurl booted <url>
```
これによって常にアプリが閉じた状態で、Universal Links経由でアプリが起動するようになります。
繰り替えし確認したい場合は2と3を繰り返すことで可能となります。

## 解説
細かいコマンドの仕様はhelpやdocumentを参照してください。
- `xcrun simctl terminate booted <bundle_identifier>` は対象のアプリをタスクキルするのと同様です
- `xcrun simctl openurl booted url` はUniversal Links経由でアプリを起動します