OmniAICreator/Qiita-1.07M huggingface dataset:
SORACOM GPSマルチユニットで位置を可視化してみる


SORACOMさんのGPSマルチユニットを入手したので、試してみた。
https://soracom.jp/products/kit/gps_multiunit/
![2020-12-27_13h04_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106639/80bb46f8-d766-b95c-5337-f2491642aae9.png)

SORACOMさんのユニットといいつつも、製品そのものは京セラのもの。
この辺がSORACOMさんのサービスを理解していない人に説明するときがややこしい。

## 設定
いくつかほかのデバイスもやっていたので、なんとなくでわかるだろーと
SIMを有効化し、グループ設定をしてみたのだが、上手くいかず。
そもそも測位/通信の間隔とかをどうやって変更したらいいのかなと。

で、よくよく取説を読んでみると、「ガジェット管理」からSIMを紐づけていく様子。
ということで、グループ設定を一度削除して再設定。

![2020-12-27_12h38_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106639/cf4a1156-de6c-702e-c6e4-f59d1f56fd96.png)


ちなみに測位/通信の間隔についてもこの「ガジェット管理」内の「デバイス設定」で設定が可能。
つまり、デバイス側にコードを指してキッティングするのではなくSOACOMのコンソール上から設定することができる。
すごい。
悩んだのはこれぐらい。お手軽に設定できる。

## 送信確認
これで対象グループに対して送信されていることを確認。
※確認はHarvest Dataを有効にして貯めてみてみるのが一番簡単。

![2020-12-27_12h42_45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106639/801d54b4-899d-1501-b64b-6c79a78bc5fa.png)


一台ずつ設定しなくていいのでかなり便利な反面、
それぞれの端末にちゃんと設定が反映されているのかどうかが今一つわからないのが難点。
設定としては問題なさそうなのだが、UDPでやり取りしている都合上、端末⇔クラウドで届いているのかわからなく、ちゃんと反映できていないことが数回あった。
外みたいにこれは確実につながるだろうみたいな環境で設定反映はやるといいのかもしれない


同じ設定なのに3分に一回の送信になってしまっていた例。
外で何回かON/OFFしてたら、上記のように1分間隔になってた。
![2020-12-27_12h45_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106639/03139805-dd7a-0008-e852-1e6428a9e2d5.png)

## バッテリーについて
IoTやるうえでよくネックになるバッテリーのもち具合。
1分間隔で測位/通信させてみたところ、1日以上は余裕で受信されていたので、結構長持ちするんだなという印象。
最近のデバイスであれば、これぐらいが一般的なのかもしれないですが、逆に言えばこれで十分賄えるかと。



## 可視化
可視化先としてはLagoonではなく、Funnel経由でArcGIS Onlineにしてみる

[あのボタンを設定した時](https://qiita.com/ryo_naka/items/f1e66c381582b4014da5)と同じようにFunnelを使えば、ArcGIS Onlineへも簡単に登録できる

以前やった「あのボタン」とはデバイスから送られてくる属性がちと違うので、こんな感じに設定

```
{
  "sendType": "json",
  "delimiter": "",
  "encode": "base64",
  "d_id": "#IMSI",
  "lat": "lat",
  "lng": "lon",
  "D_TIME": "",
  "v_dbl_1": "",
  "v_dbl_2": "",
  "v_dbl_3": "lat",
  "v_dbl_4": "lon",
  "v_int_1": "",
  "v_int_2": "bat",
  "v_str_1": "type",
  "v_str_2": "rs"
}
```
```
送信データ形式：バイナリ
```

マルチユニットはもう少しいろいろな項目を持っているので、紐づけ次第では気温などを設定することも可能。
やり方としてはHarvestを参照しつつ、設定したい項目名を上記の右側に設定してあげればOK。

これでデバイスの位置がこんな感じで可視化可能。
デバイスの都合上、加速度は取得できるけど速度が取れないのがちと残念。
![2020-12-27_13h22_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106639/941c0bf4-aaac-c3df-3885-ffc931b15558.png)




ちなみにHarvest上で見るとこんな感じ。
当たり前だけど、位置は一緒。
![2020-12-27_12h55_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106639/ecd90132-836e-ce56-5e72-c305e18bfcf3.png)



# 個人の意見です

数台であれば、これでも全然問題ないとは思うけど、複数台がそれぞれどこらへんにあるか/いるか？とかを可視化するんだったら、何かしらのGISを使った方が見やすいんだろうなとは思う。

なので、個人的にはSORACOMのHarvestでPoCとしてデバイスの選定をしたあとに、BeamやFunnel,FunkでGISへ流して可視化や解析をするのが手間がかからずにエコシステムを活用できる楽ちんなパターンなんじゃないかなと思う。
最近だとAWSのLocation Serviceもなんかリリースされましたし。

といっても、みんな言うことを聞いてくれずにGPSで可視化する一式が欲しいんですけどーって言ってくるのが非常に悩ましい。

10万円を三回ずつ出してくれればいろいろなことを試しつつ、ベストな方法を考えられるのに、
50万出すからまとめてやってくれとなって、えいやでデバイス選定してなんだかなーという結果になるとすごくモニョモニョする。
PackageInfoでbuildnumberが取得できない問題

[package:package_info](https://pub.dev/packages/package_info)でなぜかAndroidでだけ build number が取得できなかったのですが、解決策がわかったので載せておきます。

## 取得できないコード

```dart
final packageInfo = PackageInfo();
if (packageInfo.buildNumber == null) {
    // something
}
final buildNumber = int.parse(packageInfo.buildNumber);
```

## 取得できるコード

```dart
final packageInfo = await PackageInfo.fromPlatform();
if (packageInfo.buildNumber == null) {
    // something
}
final buildNumber = int.parse(packageInfo.buildNumber);
```
GitHub の personal access token の使い方

1) トークンの取得

こちらに方法が示されています。
[Creating a token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token#creating-a-token)

ブラウザーで　GitHub にサインインします。

Settings -> Developer settings -> Personal access tokens
![tokens_mar11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/f48df81c-9394-5128-37b6-d27bfdea08b6.png)


トークンを作成すると、画面に表示されるので、それをコピーペーストで保存します。40　文字の数字とアルファペットです。

2) トークンの使用
git push をかけた時、パスワードとして入力します。

```text
$ git push -u origin master
Username for 'https://github.com': ekzemplaro
Password for 'https://ekzemplaro@github.com': 
```

次のバージョンで確認しました。

```text
$ git --version
git version 2.32.0
```
Spring Data RESTでHal-Browserが使えない

# dependencyManagementで`org.springframework.data:spring-data-rest-hal-browser`が使えない

## dependencyManagementタスクを実行すると、、、
* `org.springframework.data:spring-data-rest-hal-browser`は無い
* 代わりに`org.springframework.data:spring-data-rest-hal-explorer` がある

どうやら、`org.springframework.data:spring-data-rest-hal-explorer`に差し替わっている模様。
マニュアルでは、`org.springframework.data:spring-data-rest-hal-browser` 使えるようなのだが・・・。よくわからない。

特にこだわりもないので、`org.springframework.data:spring-data-rest-hal-explorer`をdepenceiesに追加すれば使える。


以下、解決後のbuild.gradle。

```gradle
plugins {
    id 'java'
    id 'application'
    id 'maven'
    id "io.freefair.lombok" version "5.3.0"
    id "org.flywaydb.flyway" version "7.3.2"
    id "org.springframework.boot" version "2.4.1"
    id "io.spring.dependency-management" version "1.0.10.RELEASE"
}
dependencyManagement {
    imports {
        mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
    }
}
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'

    implementation "org.springframework.boot:spring-boot-starter-data-jpa"
    implementation "org.springframework.boot:spring-boot-starter-data-rest"
    implementation "org.springframework.data:spring-data-rest-webmvc"
    implementation "org.springframework.data:spring-data-rest-hal-explorer"
//    implementation "org.springframework.data:spring-data-rest-hal-browser"
    annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"

    implementation "org.flywaydb:flyway-core"

    implementation "com.zaxxer:HikariCP:3.4.0"
    implementation group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '2.2.2'
    implementation "com.influxdb:influxdb-client-java:1.0.0"

    implementation group: 'commons-collections', name: 'commons-collections', version: '3.2.1'
    implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
    implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3'
    implementation group: 'ch.qos.logback', name: 'logback-core', version: '1.2.3'

    // ------------ test -------------
    testImplementation ('org.springframework.boot:spring-boot-starter-test:2.2.1.RELEASE') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }

    testImplementation 'com.h2database:h2'

}
```

## 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/55074148-e051-07b4-a1de-10744e60bb6a.png)
signup後の画面で、profile,logoutを表示されない問題を解決した。

##発生した問題
ブログの完成に向けて、ログインシステムを構築する過程でエラーが発生した。
http://localhost:3000/users/new
において、Signupを実行後、UserのProfile画面にリダイレクトはできただが、ページ上部にProfileとLogoutが表示されず、代わりにSignUpとLoginが表示されてしまう。
![signup_error.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698990/81aed168-6861-d2fd-e697-1934ef576f30.gif)

##当初考えられた原因
　（１）app/helpers/sessions_helper.rbで定義し、layouts/application.html.erbに記述した”logged_in?”が有効でない。
　・・・しかし、コードの記述自体に誤りは見られず、条件分岐もlogged_in?メソッド（※）も発火している。

```rb:logged_in?メソッドを格納しているapp/helpers/sessions_helper.rb
module SessionsHelper
  def current_user
    @current_user ||= User.find_by(id: session[:user_id])
  end
  def logged_in?
    current_user.present?
  end
end
```
　（２）そもそも、”rails g controller sessions new”実行時に、sessions_helper.rbが生成されなかった。
　・・・これは「- CSS、JavaScript、Helperのファイルをrails g コマンドで自動生成しない設定を記述して、これらの余分なファイルができない」ようにするため、”config/application.rb”に下記の記述をしたことで、意図的に自動生成せず、代わりに自分でsessions_helper.rbファイルを作成した。

```rb:config/application.rb
require_relative 'boot'
require 'rails/all'
Bundler.require(*Rails.groups)
module HogehogeAppli
  class Application < Rails::Application
  #省略
    config.generators do |g|
      g.assets false
      g.helper false
    end
  end
end
```
　おそらく、上記（２）が原因で上手くlogged_in?が発火していないと予想していた。しかし、
http://localhost:3000/sessions/new
（Loginページ）でログインした場合は、正常にProfileとLogoutが表示されるため、なぜlogged_in?が発火しないのかが分からない。
　SignUp後に、ProfileとLogoutを表示させるためにはどうしたらよいのか、悩んでしまった。

##解決法
　logged_in?メソッドは何の問題も発火しているため、問題点は違うところにあった。

　そもそもログイン状態とは、**ユーザーのブラウザ内のcookiesに暗号化されたユーザーIDを付与することをログインといい、それが保持され続けていることをログイン状態という。（ブラウザとサーバ間で同一のユーザIDが突合し合えている状態）**をいい、その仕組みは**create時にsessionメソッドを使ってcookiesにユーザIDを持たせることでログイン状態が実現できる。**
　
　Login（＝ドメイン名/sessions/new）後には正常にProfileとLogoutを表示させられて、Signup（＝ドメイン名/users/new）では表示されず代わりにSignupとLoginが表示されてしまう…。

　この違いについて焦点を当てることが解決につながると考え、users_controller.rb内のcreateアクションでログイン状態を作れていないことが判った。

```rb:app/controllers/users_controller.rb
def create
    @user = User.new(user_params)
    if @user.save
      #下記１行を追記し、ユーザーのブラウザ内のcookiesに暗号化されたユーザーIDが自動で生成されるようにした。
      session[:user_id] = @user.id
      redirect_to user_path(@user.id)
    else
      render :new
    end
  end
```
　結果として、別添画像のとおりSignup後の画面でProfileとLogoutを表示させることに成功した。
![signup_correct.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698990/80f7093c-4b51-20fe-cb9f-230879502d57.gif)
macでTimeMachineを使わずに増分バックアップする

# ターゲット
・macOS Catalina 10.15.7

# cronの準備
cronをフルディスクアクセスにする。
1.**システム環境設定 > セキュリティとプライバシー > フルディスクアクセス** を開く。
![スクリーンショット 2020-12-27 12.18.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567239/f910c5f7-7c82-bf90-f00b-eb091d7ab171.png)

2.ロックを解除し、「＋」ボタンをクリックする。
3.**[⌘ command] + [shift] + [G]**を押下し、**「/usr/sbin/cron」**へ移動する。
![スクリーンショット 2020-12-27 12.24.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567239/f2871dd2-ee86-bdbc-932f-1670790908ca.png)

4.**「cron」**が選択されていることを確認し、「開く」をクリックする。
![スクリーンショット 2020-12-27 12.27.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567239/ec88054c-403f-3583-f434-b7cd2c60297f.png)

5.cronが追加されるので、チェックを入れる。
![スクリーンショット 2020-12-27 12.28.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567239/f29f913b-7049-e5ae-0d5a-54ec4ca68930.png)

# コピー用のスクリプトを作成
手元の環境では、「/Volumes/Cam1」を「/Volumes/Cam1_Backup」にコピーする。
スクリプトはこんな感じ（ファイル名は任意）。

```zsh:cam1_backup.sh
#!/bin/zsh

echo `date`" Executed Cam1 backup."
/usr/bin/osascript -e 'display notification "Running Cam1 backup." with title "Start Cam1 Backup."'
cp -r -n /Volumes/Cam1/* /Volumes/Cam1_Backup
echo "Finished Cam1 backup."
/usr/bin/osascript -e 'display notification "Finished Cam1 backup." with title "Finished Cam1 Backup."'
echo "========================================================"
```

### コードの説明 その1
以下のコードは、デスクトップに通知を出すコード。

```sh
/usr/bin/osascript -e 'display notification "Running Cam1 backup." with title "Start Cam1 Backup."'
```

こんなの
![スクリーンショット 2020-12-27 12.36.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567239/e4761842-6bfb-a030-f183-a55633e78bb4.png)

### コード説明 その2
コピーコマンドについて。

```sh
cp -r -n /Volumes/Cam1/* /Volumes/Cam1_Backup
#cp -r（再帰的に実行） -n（新しい項目のみコピー） /Volumes/Cam1/*(コピー元ディレクトリ) /Volumes/Cam1_Backup(コピー先ディレクトリ）
```

# cronの設定
前項で作ったスクリプトを適当なディレクトリに保存。
今回は以下の場所に保存した。

```sh
/Users/masato/cam_backup1.sh
```

**ターミナル**を開いて**「crontab -e」**を入力しreturn
開いたエディタに以下を入力する。今回は毎日23時に実行する。

```sh
0 23 * * * /bin/zsh /Users/masato/cam1_backup.sh>>/Users/masato/cam1_backup.log
```

実行時にスクリプトのechoコマンドで出力した文字列を、/Users/masato/cam1_backup.logファイルに追加していく。
cam1_backup.logはこんな感じ。

```sh:cam1_backup.log
Tue Dec 22 23:00:00 JST 2020 Executed Cam1 backup.
Finished Cam1 backup.
========================================================
Wed Dec 23 23:00:00 JST 2020 Executed Cam1 backup.
Finished Cam1 backup.
========================================================
Thu Dec 24 23:00:00 JST 2020 Executed Cam1 backup.
Finished Cam1 backup.
========================================================
Fri Dec 25 23:00:00 JST 2020 Executed Cam1 backup.
Finished Cam1 backup.
========================================================
Sat Dec 26 23:00:00 JST 2020 Executed Cam1 backup.
Finished Cam1 backup.
========================================================
```

# 完成
これで定期実行されるバックアップの設定ができた。

# 引用元
[macOS 10.15 catalina で crontab を使用する](https://mac-ra.com/catalina-crontab/)
[コマンドでMacの画面に通知ダイアログを出す](https://qiita.com/uqichi/items/180d9a5ad661268e0007)
[Vue.js]Storeの値がcommit以外で変わっちゃった時の話

# 前書き

業務でNuxt.jsアプリの改修をしていて、

なんかバグ出てるやん
→　どうやらStoreの値中の**配列**の値がおかしいぞ
→　変な値がcommitされているんだな
→　commit値は正常だな・・
→　あ、変なところでまたcommitが呼ばれちゃってるんだな！
→　commitは（正常時の）１回しかされていないぞ・・
→　**詰**

なことがあったので、これを解決した時の話を書いてみます。

# 体験談

今回のポイントは、異常値を示した値の型が`配列`と言う点。

最初はVue初級者が故に、
`storeの値はcommitから以外で変わり得ない`、と言う前提はあったため、
VueXの仕様的に誤った使い方しているんじゃ、、と的外れなあたりをつけてVue周りを調べてました。

そんな時、ふと配列で思い出したのが、
`配列は参照型やん`、です。

なので、`storeから取り出した配列を直接いじってる部分がないか`と言う方針で調査を進めました。

そして見つけました。

lodash（JSライブラリ）の`_.remove()`メソッド

※removeメソッドについては[こちら](https://matsukaz.hatenablog.com/entry/2014/04/09/082410)の記事がとても参考になります。

この処理の前後のstoreの値を確認し、確信しました。

この処理周りを改善し、無事バグ解決。

## 参照型とは

超ざっくり言うと、値が置いてある場所、のこと。
Java習いたてでよく注意点として出て来ます。

ありがちな事象は以下
↓
ある変数を別の変数にコピーして、値２個できたやん、とか思って片方を変更する。
でも参照型の場合は実際には場所を指しているので、コピーされたのは場所情報だけ、変更されたのはその場所にある値である。
つまり同じ場所を指しているもう一方の変数も、一緒に値が変わってしまう。

文面で起こすの辛いので実例↓

```JavaScript

// JSの場合

var a = [1,2,3,4,5]; // 配列定義。

var b = a; // 変数をコピー。実際は配列のある場所だけコピーされる。

b.pop(); // bの末尾削除

console.log(a); // [1,2,3,4]
console.log(b); // [1,2,3,4]

// aも削除されちゃった

```


# まとめ

配列が参照型、と言うのは実際にその類のバグに遭遇しないと意識しないと思うので、
体験談を書き記してみました。

これがあってから改めて意識するようになったのが、

* Vuexのstoreの中身がcommit以外から変更されるパターンもある（ReactのReduxなどでも同様だと思う）
* storeなど固定値として保持されている配列を直接いじらない
* 配列の中身に関するバグがあったら、直接操作を行っていないかを疑う

です。

ちなみにどうしてもいじる必要がある場合は、
例えばlodashの`_.cloneDeep()`と言うメソッドを使うことで、
配列を完全複製し、それを使用する方法などが回避策になるかなと思います。

この記事を見て、
うわ、こんなバグもありえるのか！、と感心していただけたり、
自分もあったわw、と共感していただける人がいたら幸いです。


# 参考

* lodashの紹介記事：https://matsukaz.hatenablog.com/entry/2014/04/09/082410
Dockerチュートリアルをやってみた！

# ナニコレ
この記事は Ubiregi Advent Calendar 2020 23日目のエントリです。
この投稿(12/27)からもう4日も過ぎているんですが、どうしても備忘録として残しておきたいという自分勝手な気持ちが強かったので、しれっと書きましたw

おそらく何万人という方がやられているDocker tutorialをやって、Dockerというのは
なんなのかというのを知りたい & 自分のポートフォリオにも使ってみたいという気持ちで臨みました。

## 参考文献
Docker tutorialは英文だったので、本当は原文読んで理解したかったのですが、途中で挫折しそうな気がしたので、@Michinosukeさんの和訳記事を元に進めました。圧倒的感謝:bow:
https://qiita.com/Michinosuke/items/5778e0d9e9c04038903c#docker%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97

チュートリアルを進めていく中でどうしてもわからない単語などは都度ググって調べました。

## チュートリアルメモ
ここからはちょっと雑ですが、自分が理解したことやチュートリアルに記載されていて大事だなと思うところを抜き取ったメモになります。理解がおかしいところもあると思うので、ご指摘ください！

### Dockerとは？
PCの上で別のOSを起動することができる。コンテナが別のOSを起動する為の容器。
自分の中ではそんなイメージです。
tutorialではnode.jsを起動したりしていました。

### Dockerを使うと何が嬉しいんだろうか？
・様々なコンテナを起動し、本番環境と同じように開発環境を作れば、「開発環境ではできるのに本番環境だとできないのはなぜ・・・」みたいなシーンが無くなりそう？
・ひとり開発だと恩恵があまり無いかもだが、チーム開発であれば一つのDocker composeを利用すれば同じ環境があら不思議！すぐに環境構築ができちゃう！みたいな恩恵がある？

### tutorialで苦労したポイント
・実体験はできるんだけど、コマンドの意味がわからなさ過ぎて途中で細かく調べることはやめました。
きちんと意味を理解しながら進めろよ！と言われそうな気もしますが、チュートリアルの目的はあくまでもDockerとはこういうものだ！と理解することだと思うので。
・コマンドはこのディレクトリで叩いてね！みたいに親切設計では無いので、チュートリアル通りに実行してもエラーが出たことがありました。ググったら解決しましたが。
・ボリュームがすごい。頑張って休日を1日使えば終わらせることも可能だと思います。7~8時間ぐらいかな。
・話が抽象的なので、内容を理解するのが本当に大変。Dockerは奥が深い・・・
・ネームドボリュームって実際使うんですかね？バインドマウントはすごく使いそうなのはなんとなくわかりましたけど。

### 今後どうしていくか
・チュートリアルは概要を知るもの。実戦向きではないと思うので、入門書やudemyなどで講座を受けたりするのがいいのかなあと思いました。
・一番手取り早いのは、ポートフォリオにさっさと導入してしまうことかなと。
・コンテナデプロイ？をやってみたい。めちゃ難しそうだけど！
RTXルーターで、一方向からアクセスできるDMZを構築する

# 概要
RTXルータを用いて、2つのセグメントを用意する。セグメント1は、内部用（一般利用用）セグメントで、セグメント2を、サーバー公開などを想定したセグメントとする。

セグメント1と2を疎通不可にするには、単純なIPフィルタを用いればよいが、メンテナンス性などを考えると、セグメント1→2への通信は許可し、セグメント2→1への通信はブロックしたいのが人情。この要件を満たすには、動的フィルタの理解が必要になる。

なんか過去にもやったな....とおもったら、過去にもやっていた。
https://qiita.com/buttyo_kuny/items/b3fe5e47d2954b91ddb6

# 参考
このサイトの解説が詳しいし、そのまんま書いてある。しかし理解に時間がかかったので自分でもまとめることにした。（追記：まずはこのURLを読んでみるといいというか、この記事いらないんじゃないかというか）
https://karasuma-kitaoji.hatenablog.com/entry/2017/05/31/014000
http://www.rtpro.yamaha.co.jp/RT/docs/firewall/index.html
http://www.rtpro.yamaha.co.jp/RT/manual/rt-common/ip/ip_filter_dynamic.html

# 動的フィルタ？
動的フィルタとは、静的フィルタを組み合わせるものである。とある通信条件にマッチするパケットが出現したとき、自動的に現れるフィルタのことである。

ちょっと難しいけど、特定の条件下の時だけ、静的フィルタを緩めてパケットを通す例外設定みたいなイメージ。

# 想定環境
NVR510とRTX1200を用いて、NVR510にセグメント1、RTX1200にセグメント2が割り当ててある場合を考える。
NVR510のlan1とRTX1200のlan3が互いに接続されており、ripでルーティング情報を交換している。RTX1200のlan1をサーバー公開セグメント（セグメント2)とする。このとき、NVR510配下のクライアントから、RTX1200のセグメント2へ通信できるが、逆はできないように設定したい。Pingは許可する。

### NVR510
- lan1 192.168.50.1/24 (セグメント1)

### RTX1200
- lan1 192.168.50.2/24 (セグメント1)
- lan3 192.168.51.1/24 (セグメント2)

### 接続許可リスト(tcp/udp)
|  元  |  先  |  許/不許可 |
| ----              | ----             | ----      |
|  192.168.50.0/24  |  192.168.51.1/0  |  許可       |
|  192.168.51.0/24  |  192.168.50.0/24 |  不許可      |
※icmpは許可とする

# 設定
フィルタ設定は、NVR510のlan1にセットする。
まず、単純に許可・不許可のフィルタをセットする。


```
ip filter 600000 pass * * icmp
ip filter 600002 reject 192.168.51.0/24 192.168.50.0/24
ip filter 600003 pass 192.168.50.0/24 192.168.51.0/24
ip filter 600004 pass * * * * *
```
※下記で定義する動的フィルタはtcp/udpにしか働かないので、icmpの許可は明示的に書いていく必要がある。

このままでは、192.168.50.0/24→50.1/24宛ての戻りパケットがフィルタによって破棄されてしまう。そこで、戻りパケットを許可する動的フィルタをセットする。

```
ip filter dynamic 300000 192.168.50.0/24 192.168.51.0/24 tcp
ip filter dynamic 300001 192.168.50.0/24 192.168.51.0/24 udp
```

最後に、lan1に適用する。

```
ip lan1 secure filter in 600000 600002 600003 600004
ip lan1 secure filter out 600000 600004 dynamic 300000 300001
```

# まとめ
- 動的フィルタを用いると、静的フィルタで設定しきれないフィルタを定義することができる。
- 動的フィルタでは、一方向の通信と、その戻りパケットを許可するフィルタを定義することができる。
- 例えば、公開サーバーセグメントや、サポート対象外OSを稼働させるセグメントとの通信に応用することが考えられる。
- 今回の想定例では、2台のルータを用いたが、1台のルータ内にVlanを切って、同様のフィルタを定義することもできる。参考URLでは、vlanに対してフィルタを定義している。
Docker Quickstart Terminalでクジラが出なかったときの原因の1つとその解決方法

#はじめに
Windows10 Homeを使われている方で、Dockerを開発環境に使われる方はDocker Toolboxを利用されていると思います。この記事では、今日(2020年12月27日)僕が遭遇したエラーと解決方法を紹介します。

#エラーの内容
一昨日まで普通に立ち上がっていたDocker Quickstart Terminalが、今日はいきなりクジラを見せてくれなくなりました。コマンドプロンプトで`docker-machine start default`を叩いたエラー内容はこんな感じです。

`(default) Windows might ask for the permission to configure a dhcp server. Sometimes, such confirmation window is minimized in the taskbar.
listen tcp4 127.0.0.1:55712: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.`

たぶん、Quickstart Terminalにもこんな感じのエラーが出ていたと思います。(その時は記事にするつもりは無かったのでしっかりと確認してませんでしたが)

使いたいポートが既に何者かに使われているっぽい。

#解決方法
エラー内容の中でポート番号を教えてくれているので、
`netstat -ano | find "55712"`をコマンドプロンプトで実行してプロセスIDを調べます。
その後、念のためにタスクマネージャーでそのプロセスの詳細を調べてからプロセスを終了し、Quickstart Terminalを再度立ち上げることで無事クジラを見ることができました。

#おわりに
ここに書くほどの内容でも無かったですが、将来慌てないためにも自分の備忘録として書き残しておきます。
M1 MacでDockerを使おう

#12月16日よりM1マック用パブリックプレビュー提供開始

以下の記事に記載あり。Public preview7だそうです。

https://www.docker.com/blog/download-and-try-the-tech-preview-of-docker-desktop-for-m1/

##ダウンロードはこちらから。
https://desktop.docker.com/mac/m1preview/Docker-AppleSilicon-Preview7.dmg
インストールは普通にdmgからアプリケーションにD&Dです。上書きはもはや動いていないからやってOKだと思います（笑）
ヘルパーのインストールで認証を求められたり、インストール後のGUIでログインをもう一度しなければいけなかったりします。あと、自動起動はしないので、自分で起動してください。そうしないと、ターミナルで

```docker-compose build```

や

```docker-compose up```

しても起動しません。当たり前ですが。

##使った感想
特に問題なく動いていますが、赤いメッセージが出まくったりして、まだまだですが、うちのnuxt環境は動いています。

##PHPなどは今後調査
バックエンドサーバで使っている```PHP+Laravel```がちゃんと動くのかは未検証。

##なので、M1マックを買ってもいいよ。
私は```M1 MacBookAir(Core8+メモリ16GB）```で動かしました。特に発熱もなく動いています。

##UIが少し変わった。
最近のUIがこうなっているんでしょうけれども、ずっと削っていたので新鮮でした。

##さらばインテル
インテルマックとか買っちゃダメです。バッテリーの持ちが違いすぎます。docker動かしているのに、バッテリーがめちゃくちゃ持ちます。信じられません。

##Macbook Proとどっちがいいの？
どっちでもいいですけど、MBAに16GBのメモリ積んでほとんどの人は十分かと。iMovieぐらいだったらサクサクでした。Premierはまだ動かしていませんけど。Zoomがちゃんと動いているのでこれで問題ないと思います。UnityもUnrealもサクサク動きました。まだ本気出していないx86版なのに。

##M1 macの唯一の問題点
Homebrewが完全対応しておらず、たぶんBluetoothマウスの通信を裏で邪魔している可能性があります。Appleと色々やっていますがまだ原因を追求できておらずです。OSが対応するのが早いかHomeｂrewが改善する方が早いか、時間の問題っぽいです。
webpack watchオプション試す

webpackのwatch(-w)オプションを付けることでファイル更新のたびにバンドルし直してくれる。
差分ビルドなので2回目以降のビルドが早くなる。


1回目は1343ms

```
$ npx webpack -w
asset main.js 299 bytes [compared for emit] [minimized] (name: main)
./src/index.ts 162 bytes [built] [code generated]
./src/hoge.ts 123 bytes [built] [code generated]

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

webpack 5.11.0 compiled with 1 warning in 1343 ms
asset main.js 318 bytes [emitted] [minimized] (name: main)
./src/index.ts 182 bytes [built] [code generated]
./src/hoge.ts 123 bytes [built] [code generated]
```

ファイルを変更し保存するとビルドが走り341msかかった。

```
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

webpack 5.11.0 compiled with 1 warning in 341 ms
```


watchから除外するオプションもある。watchOptionsのignoredにpathを指定すると除外される。

```webpack.config.js
module.exports = {
    watchOptions: {
        ignored: /node_modules/
    }
}
```

他にもコンパイルをまとめて行えるようにするaggregateTimeoutオプションや

```
module.exports = {
  //...
  watchOptions: {
    aggregateTimeout: 600
  }
};

```

ポーリングさせて指定間隔ごとにコンパイルさせるpollオプションがある。
(これは試してみたけど動作していない？？？)

```
module.exports = {
  //...
  watchOptions: {
    poll: 1000 // Check for changes every second
  }
};
```


公式
https://webpack.js.org/configuration/watch/
amazon-dashで、スキャンするNICを指定する方法

## amazon-dashでNICを明示的に指定
AmazonDashボタンをIoTボタン化するOSS, [amazon-dash](https://github.com/Nekmo/amazon-dash)のTIPSである。

amazon-dashにて、discoveryもしくはrunする際、複数のNICが存在すると、意図しないNICのパケットを監視してしまう場合がある。
たとえば、eth0, eth1が存在する場合、AmazonDashボタンが接続されているNICがeth1である場合でも、eth0をスキャンしてしまう場合がある。
その場合、以下のTIPSにてスキャンするNICを明示的に指定する必要がある。

### 実行環境
以下の環境で実行した際の結果を使用した。

```
# cat /etc/debian_version 
10.7

# python --version
Python 2.7.16

# pip --version
pip 18.1 from /usr/lib/python2.7/dist-packages/pip (python 2.7)

# amazon-dash 
Welcome to Amazon-dash v1.4.0 using Python 2.7.16
```


## discoveryでのNICの指定
discoveryを実行する場合、オプションでNICを指定可能である。

### example
```
# amazon-dash discovery --interface eth1
```

### Document
ヘルプに書いてあった

```
# amazon-dash discovery --help
Welcome to Amazon-dash v1.4.0 using Python 2.7.16
December 31 is the last day to block requests from your Amazon-dash buttons to Amazon servers. In 2020 your buttons can be bricked in an update from Amazon servers.
Usage: amazon-dash discovery [OPTIONS]

  Discover Amazon Dash device on network.

Options:
  --interface TEXT  Network interface.
  --help            Show this message and exit.
```

## runでのNICの指定
run、もしくはサービス化(systemctlから起動)の場合、`/etc/amazon-dash.yml`にて指定を行う。

### example

```
settings:
  interface: eth1
```

### Document
`/etc/amazon-dash.yml`そのものに記載は無いが、ソースコード内で確認が出来る。
該当のファイルは、`config.py`で、JSONのスキーマで存在を確認出来る。

```python

18:#: Json-schema validation
19:SCHEMA = {
20:    "title": "Config",
21:    "type": "object",
22:    "properties": {
23:        "settings": {
24:            "type": "object",
25:            "properties": {
26:                "delay": {
27:                    "type": "integer"
28:                },
29:                "interface": {
30:                    "type": "string"
31:                },
```

## NICの名前について
NICの名前そのものはamazon-dash内では特にバリデーションをしておらず、そのまま`scan.py`の`scan_devices`に渡しているだけのようである。
要には、OSが認識できていれば、なんでも良いらしい。
物理NICの他、VLAN Interface（例:`eth1.100`）でも正常に動作をしている。

試しに、無効なインターフェース名を渡したところ、こんな感じのエラーを吐いて止まった。
NIC周りを変更した後にトラブルになった際は、参考にして欲しい。

```
# amazon-dash discovery --interface foo                             
Welcome to Amazon-dash v1.4.0 using Python 2.7.16

(snip)

OSError: foo: No such device exists (SIOCGIFHWADDR: No such device)
Exception IOError: IOError(19, 'No such device') in <bound method L2ListenSocket.__del__ of <scapy.arch.linux.L2ListenSocket object at 0xb6744f0c>> ignored

# echo $?
1
```
【Cluster用アイテム】プレイヤーが近づくと表示される詳細アイテム＆スライドショーっぽい説明パネル

[【Cluster用アイテム】プレイヤーが近づくと表示される詳細アイテム＆スライドショーっぽい説明パネル \- tsukinon\*\*\* \- BOOTH](https://natsu-san.booth.pm/items/2633216)
の取説です。

![説明パネル (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570991/aaf84441-2540-3167-9fc0-10f80f975823.gif)


##これは何？

Cluster用アイテム
「プレイヤーが近づくと表示される詳細アイテム」

アイテムの解説パネル、NPCのセリフ、セーブポイントなど、
必要なんだけど、常時表示されると景観的にイマイチ（邪魔）なんだよな～
といったものに使うことを想定しています。
ダミーアイテムとメインアイテムは自由に入れ替えられます。
表示エリア自体はItemではないので、Itemも入れられます。

「スライドショーっぽい説明パネル」
も同様に、説明を1枚に詰め込むと
説明パネルがやたらとデカくなるのを
いい感じにしたくて作りました。

一緒にも別々にも使えるようにしてあります。
組み合わせると、目の前にくると詳しい説明が読める、といった動線ができます。

## 簡単な使い方解説（プレイヤーが近づくと表示される詳細アイテム）
- EreaSphere
プレイヤーの接近を検知するエリア（本体）です。
スケールを適当に変えたり、位置調整したり、BoxColliderに変えたりしていい感じにしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570991/14e986e0-dd06-2309-0785-138fb113789f.png)

- ダミー
展示オブジェクトの縮小版とかアイコンとかをこれの下に入れてください。
プレイヤーが近づくと消えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570991/0654ae93-d00e-6a68-b6b8-8103b164ebd1.png)

- メイン
プレイヤーが近づいたら見せたいものを入れてください。
プレイヤーが離れると消えます。
音がついてるのは自分の好みなので、無くてもいいです。
（個人的には、インタラクションには音をつける派です）
にゅっと出るアニメーションとか追加するとかっこいいと思います。
デフォルトでは説明パネルを入れていますが、お好きな3Dモデルなど入れてください。
ただのGameObjectなので、Itemも入れられます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570991/692f1203-7500-0e8e-cfe3-523412c89cc4.png)


## 簡単な使い方解説（スライドショーっぽい説明パネル）
各Planeのマテリアルに、表示したい画像（のマテリアル）を入れてください。
表示時にはPlane1から順に表示されます
4まで行くと、1に戻ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570991/2106224f-8eb6-5352-a9de-77e8674c18f7.png)

4枚も要らぬ！というときは、
ロジックの赤丸のところの数字を適宜減らしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570991/96ea1186-c6ea-3ccb-9ccd-bb5d0b6e67dc.png)


増やしたいときは、Animaterと和解して（ページ遷移のアニメーションを追加して）
赤丸の数字を増やしてください。

## 着想
[バーチャル特別展「アノニマス ー逸名の名画ー」｜バーチャルSNS cluster（クラスター）](https://cluster.mu/e/615dfed3-1511-4f82-9b22-5ab095bd22d4)
↑の展示で、ショーケースに近づくと展示物が目の前に飛び出してくるのが、バーチャルならではでありながら、展示会体験としてすごくいいな！と思ったので、こんな感じかな～と実装しました。
結果的にだいぶ汎用性は高いと思います。
特別展は、トーハクの再現度も、展示空間の作りも、作品自体も、とにかく最高なのでおすすめです！！！

モノ自体はGameGAM 2020 Winter前にできてたので、
もっと早く公開しとけばよかったと思いました！
軽量で爆速にコンテナを使える Azure Container Instances !

この記事は、[求ム！Cloud Nativeアプリケーション開発のTips！【PR】日本マイクロソフト Advent Calendar 2020](https://qiita.com/advent-calendar/2020/azure-cloudnative) の 9 日目です（後から追っかけで書いています）。

----
本記事では [Azure Container Instances](https://azure.microsoft.com/ja-jp/services/container-instances/?WT.mc_id=AZ-MVP-5001601) についてと Docker を Azure Container Instances 上で使う方法について、ご紹介したいと思います。

## What is Azure Container Instances?

[Azure Container Instances](https://azure.microsoft.com/ja-jp/services/container-instances/?WT.mc_id=AZ-MVP-5001601) は、シンプルなアプリケーション、タスク自動化、ビルドジョブなど、分離されたコンテナーのシナリオに向いたサービスです。

## Why Azure Container Instances?

似たサービスに [Azure Kubernetes Service](https://azure.microsoft.com/ja-jp/services/kubernetes-service/?WT.mc_id=AZ-MVP-5001601) があります。

[Azure Kubernetes Service](https://azure.microsoft.com/ja-jp/services/kubernetes-service/?WT.mc_id=AZ-MVP-5001601) は複数コンテナーを使うサービスやオートスケーリングなどコンテナーのオーケストレーションが必要なシナリオに向いたサービスです。

使い分けとしては、シンプルな構成であれば、[Azure Container Instances](https://azure.microsoft.com/ja-jp/services/container-instances/?WT.mc_id=AZ-MVP-5001601) が適しています（＝[Azure Kubernetes Service](https://azure.microsoft.com/ja-jp/services/kubernetes-service/?WT.mc_id=AZ-MVP-5001601) をシンプルな構成に使うのはあまり適切ではありません）。

一方で、複雑なサービス（オートスケーリングや複数コンテナーを使うサービス）に [Azure Container Instances](https://azure.microsoft.com/ja-jp/services/container-instances/?WT.mc_id=AZ-MVP-5001601) を使うのはあまり適切ではありません。

## Docker との連携強化

以前までは、Docker Desktop から [Azure Container Instances](https://azure.microsoft.com/ja-jp/services/container-instances/?WT.mc_id=AZ-MVP-5001601) を操作できず、Azure CLI や Azure Portal から操作が必要でした。

しかし、今年（2020 年）の Docker Desktop の更新バージョンでは、Azure Container Instances の Docker コンテキストを作成するためのコマンド `docker context` が追加されました。

詳細は以下のドキュメントに書いてあります。

* [公式ドキュメント: クイックスタート - コンテナー インスタンスに Docker コンテナーをデプロイする](https://docs.microsoft.com/ja-jp/azure/container-instances/quickstart-docker-cli/?WT.mc_id=AZ-MVP-5001601)
* [公式ドキュメント: Deploying Docker containers on Azure | Docker Documentation](https://docs.docker.com/engine/context/aci-integration/)
BertをFinetuningしてStoryPointを読む


# 概要
- NLPで使えるものを作りたかった
 (動くものを作るのが最優先）  
- PreTrainedモデルを使ったチュートリアルを色々試して最後まで辿り着くことができた
  (バージョン管理はかなり重要だと思った）    
- 積み残しあり
- それはそれとして

# 作ったもの
![Storyを入れるとStoryPointを返す](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328600/c712622d-f2ca-da02-2a47-d8a34b1f23e1.png "実行画面")

# 使ったもの
[データ」
- trelloから落としてきたカード一覧  

[学習]
- fugashi                      1.0.5
- ipadic                       1.0.0
- mecab-python3                1.0.3
- tensorflow                   2.3.1
- tensorflow-estimator         2.3.0
- tensorflow-gpu               2.3.1
- transformers                 3.4.0

[アプリ]
- django(3.1)

[環境]
- Ubuntu20.4
- docker 19.03
- docker-compose 1.27
- image tensorflow/tensorflow:latest-gpu-py3-jupyter(学習用)
- image python:3.8(アプリ用)

[参考にしたサイト」
- https://qiita.com/takubb/items/fd972f0ac3dba909c293

# 手順
参考にしたサイトを順番に実行してゆく
本件のために追加・修正した処理は以下

## 1. BertのFinetuning
transformerのソースを修正してタスクを足すタイプのチュートリアルは最後まで行きつかなかった、、参考サイトの方法で何とかアプリ作る所まで行きついた

### 1-1. trelloからデータの取得
* trelloのAPIを使ってカードを取得
* 取得したデータの名から学習用に使用できるデータを抽出  
（完了している、ストーリーポイント(SP)がついている、ストーリーが記載されている）  

### 1-2. ラベルの設定、対応表の保存
* SPは[0.5,1.0,2.0,3.0,,,]のようになっているが、マルチクラスの分類で使用できるラベルは[1,2,3,4,,,]なのでデータを修正してマッピング表{"0.5":0,"1.0":1,"2.0":2,,,}を作成しておく
* token化する際のmax_lengthを調整(長すぎるとなぜか学習できない）

## 2. Djangoで呼び出す
### 2-1. 学習で作成したモデルを配置  
- staticに配置して読み込む  

### 2-2. 学習時に作成した対応表を使用して結果をSPに変換
- staticに変換表を配置して変換処理に使用

# 結果
* 出来上がりは[使ったもの](使ったもの)にある通り
* データが少ないので精度は不安定、結果は以下
 ![mlflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328600/0c5fe300-ae52-3069-f939-822e0b03461d.png "mlflow画面")

# 今後やりたいこと
アプリまでいったので満足感は得た、、ジョークアプリとしては面白いと思う  

* 精度を上げたい（CVやってないし、GPUはmax_lenght=128以上はメモリのらないといわれたし、、）
* Importanceを出したい、可視化したい   

# それはそれとして
諸々思いました

1. プロジェクト単位でのデータ蓄積は厳しいかも
1. 本当に使う場合は「上位3位以内を参考値としてみる」など運用の工夫が必要（精度を上げても100%にはならない。人がSPをつけても100%は無理だと思うし、、）
1. 似たようなProbabilityが上位に並ぶ場合はストーリが不完全？ストーリー詳細化が必要となる指標になる？
2. 最小単位のカードは「スプリントの中で一人がこなせる」大きさのSPに収束する？とするとSPを推測するよりも一定のSPに収まらないストーリーとその原因を出すほうが使える？
1. チームに新しいメンバーが入った時も同じモデルでSPを出してよいのか？全体平均は上がるはず？そんなことが実際の案件で顧客に受け入れられるか？
1. 同一タスクのSP平均増減が許容されない場合、メンバーはアプリやサービスが終わるまで固定せざるを得ない？ 

* ご指摘、アドバイスなど是非お願いします！
サーファーが組織をブランディングする

# どういうこと？

結論からお話すると、私が以前在籍していた会社の人があまりにもサーフィンが好きで、海沿いに家を購入しそこからリモートで働き支社を立てようとした話です。
彼は、一緒にサーフィンをしながらエンジニアとして一緒に仕事をする人を求めていたのです。
そのため、サーファーがよく利用するサイトにエンジニアの求人を載せて募集をかけていました。

で・・・実際集まったのか？

というところが気になると思いますが・・・

結局集まりませんでした・・・。

世の中そんなにうまくいはいかないですね（笑）

しかし、今思うとこの戦略は非常に面白く可能性を感じるものだったと思います。

# 採用の現状

私がよく耳にする話だと、IT業界で採用活動をしている企業でなかなか人が集まらないといった会社が多く見受けられます。
これは単純に、人が足りないから。というものではなく企業が求める人材像と、それに見合った人材がなかなか見つからないということが原因の１つにあるのかなと思います。

昔は、人をとりあえず採って育てるという流れが一般的だったかもしれませんが今は経験、技術があって即働ける人が求められている感じがします。

当然そうなると、なかなか募集をかけても人は集まりません。

# ブランディングするということ

ではどうするのか？

これまでの経験をもとに分かっていることは他の会社と同じように人材業界の会社に登録して応募をまっていてもダメだということです。

やはり組織自体、もっといえば会社自体になにか面白みであったり、特徴がないと他社とは差別化ができないのが現状だと思います。

初めて会う方に「あなたの会社」はどういった会社ですか？どういった部署なんですか？
と聞かれても答えられない・・・

そんなことにならならいように組織をブランディングしていきましょう。

・実践する技術レイヤが広く多くのことを学べる
・ユニークな制度を取り入れて、働きやすい

または前述の例のように

サーフィンや猫好き、音楽好きなど同じ趣味を持った人で組織やチームを編成して、ただ一緒に働く仲間で終わるのではなく「このひとたちと一緒に働きたい！」と思わせることも大事だと思います。

そうやって組織をブランディングしていくことも１つの手段ではないでしょうか。
Lernaで全てのプロジェクトへのnpm installを実行する方法

## 概要
サーバー + フロントといった別々のプロジェクトを一つのリポジトリで管理するような運用をモノレポ(モノリポ？)と呼びます。
今回はモノレポを最適化するツールの`Lerna`を使って、運用している全てのプロジェクトのプロジェクトへの`npm install`を一括で実行する時の話です。
私の場合はCIで回す時に必要になりました。

## 結論
`lerna exec`コマンドを使いましょう。

以下のようなディレクトリ構成の場合、ルートディレクトリで`lerna exec npm install`を実行すると、frontとserver両方の`npm install`が実行されます。

```
├──packages
│    ├── front
│    │   ├── package-lock.json
│    │   ├── package.json
│    │   ...
│    └── server
│        ├── package-lock.json
│        ├── package.json
│        ...
├── package-lock.json
├── package.json
├── lerna.json
...
```

## もう少し詳しく...
lernaが用意している各パッケージでコマンドを実行するためのコマンドには以下の二つがあります。

- `lerna exec`
  - 全てのパッケージで任意のコマンドを実行する
  - `npm run`コマンドを実行することも出来るので、`lerna run`をこちらに置き換えることも可能(意味はないけど)
  - npm installの他にrmなどで使用
- `lerna run`
  - 全てのパッケージでnpm script を実行する
  - testやbuildなどで使用

また、どちらのコマンドもオプションがかなり共通しています。

- `--scope`
  - 指定されたパッケージの処理だけを実行する
- `--stream`
  - 出力をストリーミングしてログを出力する
- `--parallel`
  - `--stream`と同じくログを出力するが、`--stream`と違って順番に実行するのではなく、 一気に全パッケージの処理を実行する
  - 危険なので、watch系のコマンドでしか使わないか、`--scope`である程度の制限をする
- `--no-bail`
  - 途中でエラー終了コードが出た場合でも、無視して最後までコマンドを実行する
- `--no-prefix`
  - `--stream`や`--parallel`と一緒に使用
  - パッケージ名のプレフィックスを無効化して、ログを出力する
- `--profile`
  - コマンドの実行をプロファイルする
- `--profile-location <location>`
  - プロファイル出力の場所を指定する


## 最後に
記事を調べているとあまり見つからなかったが、公式のREADMEを見たら簡単に解決したというオチ。
基本的にnpm scriptに書くので途中から気にしなくなるが、こんなことが出来るのかというだけでも、コマンドやオプションの種類を知っておくのはとても大事。
『Gmailのアーカイブって何ぞ？』を無くして受信トレイ整理の第一歩

#1万7千件の受信メール
あたいの受信トレイは今こんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/e1acf8ec-20e3-c726-930a-c889f0340e33.png)
つまり…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/7ab6b50f-02d6-6a76-08bb-1bed40b2b0b5.png)
はい、ということで少しくらい整理するかと思いまして、まずは **自動振り分け** したり **読んだ** やつを受信トレイから消そうと思ったわけです。

でも物理消去だと後で読めなくて困るので、 **処理ったよフォルダー** に移動したいんです。

そこでアーカイブを使います。

#アーカイブって何をすること？
まず前提として、届いたメールは **受信トレイ** と **すべてのメール** の2か所から参照できる状態になりまする！

んでもって、
**アーカイブ = 受信トレイから消す**
です。
すべてのメールには残ります。

最初、『受信トレイ = すべてのメールが置いてある場所』 って頭だったから『アーカイブって何ぞ？メールはどこ行っちゃうの？消されるの？』ってちょっと混乱してもうた…。

受信トレイ ≒ 一時置き場 って捉えた方が分かりやすいかなと思います。

#すべてのメールが無いんですけど！
遥か古の時代に『すべてのメールってなんぞ？いらんわい！』で非表示にしていた時は、下記で蘇生。

右上の **すべての設定を表示**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/dc7c11f7-7c41-9bab-fdc4-7997c5f512e1.png)

**ラベル** タブにあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/b43f08c2-c6d1-4672-0418-993c89374d87.png)

#やっぱ受信トレイに戻したいんだけど
メール開いて **受信トレイに移動** ボタン。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/0ac2ef87-0679-e858-693a-d591dd6925a4.png)

#自動振り分けにアーカイブ設定あり
特定条件のメールは届いたら即アーカイブもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/bf657000-6c1d-f37e-69cb-7f39613a2974.png)

自動振り分けが分からんって時は下記。
[Gmailの自動振り分け設定（受信済のメールに対する適用や設定の確認・削除についても）](https://qiita.com/waokitsune/items/fd0a6e1af13eea4ba90a)

#蛇足
受信トレイには『新規』や『処理フローが明確になっていないやつ』だけが残る状態にすると使いやすくなるかなーって考えてます。

次は『既読で一定期間過ぎたメールは自動削除。（ただしスターが付いてるものは除外）』っていうスクリプトを組もうと思います。
自動振り分けじゃあどうもできなさそう。

#参考サイトさん
https://www.nojima.co.jp/support/koneta/54804/

#バージョン
Windows10 Pro バージョン20H2 OSビルド19042.685
Google Chrome 87.0.4280.88
WordPressでOGPの自動出力をしてみた

# はじめに
最近流行りのJamstack、いいですよね。

Gatsby.jsを調べているうちに、Gatsby.jsでOGPの自動出力をしたという記事を拝見しました。
[GatsbyJSでOGP画像の動的生成にチャレンジしてみた | Learn Something New](https://blog.kentarom.com/create-gatsbyjs-plugin-to-dynamically-generate-og-images/)

で、OGP自動出力したすぎる、と。目的がGatsby.jsからOPG自動出力に変わりまして。
じゃあ、個人でやってるブログで試したろ！と思ったのですが、私のブログ、ヘッドレスCMS化？SSR？なにそれ？みたいなWordpressを使ったフツーのブログなんですよね。(しかも１年以上放置)

**え、サイト作り直すのだる……PHPでどうにかできるならしよ。**

というのが、今回の趣旨です。

# PHPで画像作成
そもそもできるのか、というところから調べたのですが、できるらしいです。
imgタグには普通画像を指定しますが、.phpファイルを指定できるらしい。
PHPってサーバー関係！みたいなザックリした理解の仕方をしていたのでなんか画像と結びついてなかった。
そして驚きのあまりこの記事を書いているんですが、そんなの知ってるよって方はもう話すことはないです。

参考：[PHPで画像を動的に生成する【GD編】 | バシャログ。](http://bashalog.c-brains.jp/17/09/15-150000.php)

# ディレクトリ構成
ファイルを置く場所は極端にいえばドキュメントルートでもテーマ内でもどこでもいいのですが、こんな感じで。

```
/og
├─img.php
├─og_base.png
└─xxx.ttf
```

.phpファイル、画像、フォントが必要です。

画像はなくても作れますが、今回はこちらを用意しました。こちらの上にテキストを重ねるだけの簡単なOGPを作ります。
![ogp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825219/35cbdfa2-7832-2531-92e4-808145198564.png)

# PHPを書く

```img.php
<?php
  $fontSize = 40; // 文字サイズ
  $fontFamily = 'xxx.ttf'; // 字体
  $txtX = $fontSize; // 文字の横位置(文字の左が基準)
  $txtY = $fontSize * 2; // 文字の縦位置(文字のベースラインが基準)
  $txt = $_GET['text']; // テキスト
  
  $img = imagecreatefrompng('ogp_base.png'); // テキストを載せる画像
  // $img = imagecreatefromjpg('ogp_base.jpg'); // 元画像がjpgの場合はこうなります
  $color = imagecolorallocate($img, 0, 0, 0); // テキストの色指定(RGB)

  imagettftext($img, $fontSize, 0, $txtX, $txtY, $color, $fontFamily, $txt);
  header('Content-Type: image/png');
  imagepng($img);
  imagedestroy($img);
```

上はいろいろ指定なので、下４行が重要です。
一つだけ注意が必要なのが縦位置。文字のベースラインが基準となっているため、縦位置に0を指定するとテキストが画像の外に行ってしまいます。
***いい感じの改行などはできないので実際はもう少しいじる必要があります。***

`imagettftext($img, $fontSize, 0, $txtX, $txtY, $color, $fontFamily, $txt);`
重ねるテキストに関する指定です。左から順番に下記を指定します。

- 重ねる画像
- 文字サイズ
- テキストの角度
- 横位置
- 縦位置
- 色
- フォント
- テキスト

`header('Content-Type: image/png');`
画像として情報を送信します。

`imagepng($img);`
PNG画像を表示。

`imagedestroy($img);`
メモリを解放。

# og:imageを指定

```header.phpなど
<meta property="og:image" content="img.php?text=<?php the_title(); ?>">
```

PHPファイル内で取得するテキストデータに合わせてパラメータを付けます。

# できた
たとえば、同じ内容をアップしている下記記事だと、こんな感じです。ｱｯ、ブログはメモとして使っていてもっと~~雑に~~簡略化して書いてます。よろしくお願いします。
[WordPressでOGPの自動出力をする方法 | I log.](https://mymed.work/wordpress-auto-ogp/)
![createimg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825219/3a51b3f1-d71b-6bb9-0f77-1f2e2afcf7f1.png)
JKゴシックかわいい。

# まとめ

- PHPで画像生成ができる
- imgタグやmetaタグなど、画像を指定するときに.phpファイルを指定できる
【Memo】Emacs key-bind

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.6.3p62](<https://img.shields.io/badge/ruby-2.6.3p62-brightgreen>) 


# はじめに

マルチスケールシミュレーション特論の講義メモです．講義メモのインデックスは[コチラ](<https://qiita.com/e79a93e5b7b1/items/d48ad7b8df544d737a78>)


# emacs の key-bind

テキストエディタの emacs には独自のkey-bind があるので備忘録として簡単にまとめておく．


## 前提

    M-: meta key
    C-: ctrl key

自分の mac は meta key として option key を設定している．


### 個人的によく使う key-bind

    C-z        # suspend, fg で emacs に戻れる
    C-x C-c    # kill emacs
    C-x u      # undo
    C-space    # mark set


### 編集用 key-bind

**カット・コピペ**

    C-w    # kill-region (cut)
    M-w    # copy-region (copy)
    C-y    # yank (paste))

**削除**

    C-d    # delete
    C-k    # kill-line


### 移動用 key-bind

    C-f    # forward  (右に1文字)
    C-b    # backward (左に1文字)
    C-n    # next     (下に1行) 
    C-p    # previous (上に1行)
    C-a    # ahead    (左端)
    C-e    # end      (右端)



------
 - **source** ~/grad_members_20f/members/e79a93e5b7b1/posts/memo/memo_emacs-keybind.org
text-alignとdisplay inline-blockでレスポンシブをいい感じにする

Webのテキストのレスポンシブ対応で、
PC表示で改行されないときはセンター寄せ、
SP表示で改行されてしまうときは、改行されたテキストのみ左寄せにしたいときがあります。（センター寄せだと気持ち悪い表示になる。）

そんなときはtext-aliginとdisplay inline-blockを使うと簡単に実装できることを知ったので、備忘録として書いています。

例となる画面はそのうち更新します。

レスポンシブはPC用とSP用でCSSを書き分けるのではなく、共通のソースで対応するというのが基本的な考え方みたいです。

``` index.js
import React from 'react';
import styles from './styles.css';

const App = () => {
  return (
    <div className={styles.accessory_container}>
      <div className={styles.accessory_text}>
        ながいてきすとーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
      </div>
    </div>
  );
};

export default App;

```

``` styles.css
.container {
  text-align: center;
}
.text{
  display: inline-block;
  text-align: left;
}
```
【Memo】Emacs Org-Mode



# はじめに

マルチスケールシミュレーション特論の講義メモです．講義メモのインデックスは[コチラ](<https://qiita.com/e79a93e5b7b1/items/d48ad7b8df544d737a78>)


# Org-Mode について

Org-Mode とやらを授業で初めて耳にしたので

-   Org-Mode とはどういうものなのか
-   Org-Mode はどうやって使うのか

の2点についてまとめていく．


## Org-Mode とは


## Org-Mode の使い方

普段マークダウンでメモを取っているので，Org の記法とMarkDownの記法を比較してみた．

| 内容           | Org の記法         | MarkDown の記法    |
|:---------------|:-------------------|:-------------------|
| 見出し         | \* 見出し          | # 見出し           |
| コメント       | # コメント         | <!- コメント ->    |
| 強調           | `**強調**`         | `**強調**`         |
| 斜体           | `/斜体/`           | `*斜体*`           |
| 下線           | `_下線_`           | `<u>下線</u>`      |
| 打ち消し       | `+打ち消し+`       | `~~打ち消し~~`     |
| インラインコード| `~インラインコード~`| `` `インラインコード` ``|


# まとめ

ということで今回は，

-   Org-Mode とは

-   Org-Mode の使い方

Org-Mode を使って Qiita の記事を書くには，Qiita\_org でテンプレートを作成し，それを編集していくのが望ましい．

この方法については[【Memo】github & Qiita](<https://qiita.com/e79a93e5b7b1/items/db0f19a038c99135f5b3>)にまとめる．



------
 - **source** ~/grad_members_20f/members/e79a93e5b7b1/posts/memo/memo_org-mode.org
【Memo】github & Qiita



# はじめに

マルチスケールシミュレーション特論の講義メモです．講義メモのインデックスは[コチラ](<https://qiita.com/e79a93e5b7b1/items/d48ad7b8df544d737a78>)


# github と Qiita の投稿について


## githubの更新(？)

なんとなーくやっていることは理解したけど説明はできないので備忘録程度に載せておく．

授業時間中にやると失敗しがち．

    git add -A
    
    git commit -m 'first commit'
    
    git pull origin main
    
    git push origin main


## qiita\_org


### インストール

terminal 上で Qiita の記事が投稿できる qiita\_org について載せておく．

はじめに qiita\_org は以下のコマンドでインストールできる．

    > gem install qiita_org

インストール後，設定ファイルを作成する．

    # 名前の登録
    > qiita config global name 'your name'
    
    # メールアドレスの登録
    > qiita config global email 'your email'

**コマンド一覧**

-   qiita all
-   qiita config [global/local] [option] [input]
-   qiita get [qiita/teams] [記事のID]
-   qiita list [qiita/teams]
-   qiita post [FILE] [private/public/teams]
-   qiita template

（参考）[QiitaOrgのREADME.md](<https://github.com/yamatoken/qiita_org>)


### Qiita の投稿

    # テンプレートの.orgファイルをとってくる．
    $ qiita template
    
    # とってきたファイル名を変更する．（今回はhoge.orgに変更）
    $ mv templete.org hoge.org
    
    # .org ファイルを編集する．
    $ emacs hoge.org
    
    # 編集した .org ファイルを投稿する．
    $ qiita post hoge.org


### テンプレートを変更したい場合

テンプレートの.orgファイルをとってくる時に

    $ qiita template
    ProductName:	Mac OS X
    ProductVersion:	10.15.7
    BuildVersion:	19H15
    cp /***/Ruby/Gems/2.6.0/gems/qiita_org-0.1.16/lib/qiita_org/template.org

のようなログが出てくる．

この最終行の cp 元の template.org を編集することで変更可能．

    $ sudo emacs /***/Ruby/Gems/2.6.0/gems/qiita_org-0.1.16/lib/qiita_org/template.org

編集時に誤って中身を消してしまった場合は以下を参考に．

    #+OPTIONS: ^:{}
    #+STARTUP: indent nolineimages
    #+TITLE: title                                                                                      
    #+AUTHOR: Hoge Fuga                                                                               
    #+name_list: 47020999 hogefuga
    #+qiita_id: foo_bar_
    #+github_id: foo_bar_
    #+EMAIL:     (concat "hoge@kwansei.ac.jp")                                                          
    #+LANGUAGE:  jp
    # +OPTIONS:   H:4 toc:t num:2
    #+OPTIONS:   toc:nil
    #+TAG: tag1, tag2
    # +SETUPFILE: ~/.emacs.d/org-mode/theme-readtheorg.setup


# まとめ

Qiita の記事を書くには，Org-Mode と呼ばれる独自の記述法で編集する必要がある．

この方法については[【Memo】Emacs Org-Mode](<https://qiita.com/e79a93e5b7b1/items/d04df89cbdfada25cbab>)にまとめる．



------
 - **source** ~/grad_members_20f/members/e79a93e5b7b1/posts/memo/memo_github-qiita.org
Laravel すべてのviewで共通する変数の設定

## はじめに
Laravelを勉強中です。備忘録として残しておきます。

## 手順
#### サービスプロバイダーの作成
```app/Provider/ComposerServiceProvider.php

<?php
namespace App\Providers;
 
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Auth;
 
class ComposerServiceProvider extends ServiceProvider
{
    public function boot()
    {
        View::composer('*', function($view) {
            $view->with('user'(使いたい変数名), Auth::user()(使いたいデータ));
        });
    }
}
```
View::composerの第一引数「*」はすべてのviewという意味。
#### 作成したComposerServiceProviderの登録
```config/app.php
    'providers' => [
        .
        .
        .
     App\Providers\ComposerServiceProvider::class,
    ],

```
これですべてのviewで使用できるようになります。

## 参考にさせて頂いたサイト
https://www.webopixel.net/php/1287.html
データをインタラクティブに可視化する方法

## データをインタラクティブに可視化できるソフト
　調べたので、メモ代わりのQiita投稿です。

### Dash(Plotly)
　DashというのはPlotlyというライブラリを使ったWebのプラットフォームです。Plotlyに関しては[[Python] Plotlyでぐりぐり動かせるグラフを作る](https://qiita.com/inoory/items/12028af62018bf367722)を参照ください。

　Dash(Plotly)に関する記事は以下参照ください。

https://qiita.com/OgawaHideyuki/items/725f4ffd93ffb0d30b6c

https://qiita.com/OgawaHideyuki/items/db936fb9be25bfcbb856

https://www.mazarimono.net/entry/2020/10/31/dx

https://www.mazarimono.net/entry/2020/12/10/python-interactive-data-visialization

https://zenn.dev/kurusugawa/articles/intaractive_plotly_graph_in_zenn

　Google Colabでも動かせるチュートリアルです。

@OgawaHideyuki さん作成のノートブック
[qiita_jupyterdash_example.ipynb](https://colab.research.google.com/drive/1eUlcEKeHLzN7zBYPutFeU9yRPOwnWqKi?usp=sharing) 

漫画のデータを題材にデータ可視化を学ぶ教材

https://kakeami.github.io/viz-madb/index.html

### PandasGUI
　PandasをGUIでぐりぐりいじれるソフト。

<a href="https://github.com/adamerose/pandasgui"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/adamerose/pandasgui.png" width="460px"></a>

　まだ試せていませんが、リポジトリのREADMEの動画とかみるとかなりよさそうな感じです。

### 他の方からのフィードバック
　試したらまたちゃんと追記します。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">PandasGUI良さそうですよね! 合うかですが、Altair, Pandas profilingについてコメントしました。</p>&mdash; tomo-makes (@tomo_makes) <a href="https://twitter.com/tomo_makes/status/1343027522611474432?ref_src=twsrc%5Etfw">December 27, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">いままでqgrid使ってきたけど、PandasGUI凄く良さそう！<a href="https://t.co/aA1Q575hmH">https://t.co/aA1Q575hmH</a><a href="https://t.co/bKkjH1v8Uw">https://t.co/bKkjH1v8Uw</a> <a href="https://t.co/RjzDKyg553">https://t.co/RjzDKyg553</a></p>&mdash; 〒みやらん🐶❄ (@Miyaran99) <a href="https://twitter.com/Miyaran99/status/1343039135007686656?ref_src=twsrc%5Etfw">December 27, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

https://twitter.com/tomo_makes/status/1411629012091170819

### 気になるライブラリ
　とりあえず列挙

- pandas-profiling
- ipyplot
- PixieDust

## まとめ
　簡単な自分のためのメモです。他にも良さそうなもの知っている人あれば、コメントや編集リクエストいただけるとうれしいです。

## 参考リンク
https://www.tsjshg.info/slides.html

https://github.com/hannari-python/tutorial

https://note.com/ryosuzuki/n/nf6fa54a0bf52

https://github.com/karolzak/ipyplot

https://signate.jp/competitions/261/discussions/20200401171320-59

https://pygraph.helve-blog.com/

## 関連記事
https://note.com/karaage0703/n/n93b970528f22

## 変更履歴
- 2023/08/15 リンク追記
- 2022/02/14 リンク追記
【Ruby】日付のデータを取得する方法

##Dateクラスに対しクラスメソッドを使用

Rubyでは日付を扱うクラスとしてDateクラスが用意されており、これを使用することにより`うるう年やひと月ごとの日数、曜日などの管理`といった単なる数字のみでは正確に算出することが困難なデータを簡単に取得することが可能となる。
日付以外にも時間を管理するクラスや、日付と時間の両方を扱うクラスが存在する。

####日付や時間に関する主なクラス

|クラス名|管理可能なデータ　　　   |
|-------|---------------------|
|Dateクラス　　| 日付　　　　　   |
|Timeクラス   |時間            |
|DateTimeクラス| 日付と時刻の双方|

##Dateクラスを使う前準備（require）
Dateクラスを使用する際には、Rubyのコード上に`"Date"ライブラリーを呼び込む`必要がある。
その役割を果たすのが`requireメソッド`であり、これにより外部ファイルを参照して、そこで定義されているクラスを取得することが可能となる。
~~※Railsのアプリケーションの場合はクラスはどのファイルにおいても参照できる為、`require "~"`の記述は不要~~（下記に訂正）
**※Railsアプリの場合は、Railsフレームワークの仕様によって参照ファイルの自動読み込み機能が備わっている為、require "~"の記述は不要**

####・具体的な使用方法

```rb
require "date"
#日付に関わるライブラリ"date"を取り込む
:
:
```

##Dateクラスのインスタンス（オブジェクト）を取得する主な方法

* todayメソッド（今日の日付を自動で算出してDateオブジェクトを作成）

```rb

require "date"
today = Date.today
#今日の日付を自動で算出してDateオブジェクトを作成
```

* parseメソッド（引数で渡した文字列をDateオブジェクトに変換して作成）

```rb

require "date"
today_str = "2020-12-30"
Date.parse(today_str)
#2020年12月30日のDateオブジェクトが作成される
```

* newメソッドによる作成(引数で渡した整数を元にDateオブジェクトを作成）

```rb

require "date"
today = Date.new(2020, 12, 30) 
#2020年12月30日のDateオブジェクトが作成される
```

##作成したDateオブジェクトから年や月などを取得する

上記の方法で作成したDateオブジェクトから特定の情報を取得する場合は、以下のようなコードを使用する。

```rb

require "date"
today = Date.today
today.year # 作成したDateオブジェクトから年を取得
today.mon # 作成したDateオブジェクトから月を取得
today.mday # 作成したDateオブジェクトから日を取得
today.wday # 作成したDateオブジェクトから曜日を数字として取得
```


記載内容に間違い等ございましたらご指摘頂けると嬉しいです。
ご連絡お待ちしております。
ブロック要素を横並び&縦位置中央ぞろえ(display: flexとalign-items: center)

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="momonoki1990" data-slug-hash="QWKOJRz" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="display:flex と  align-items: center">
  <span>See the Pen <a href="https://codepen.io/momonoki1990/pen/QWKOJRz">
  display:flex と  align-items: center</a> by 熊瀬川直也 (<a href="https://codepen.io/momonoki1990">@momonoki1990</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

・そもそも ```div``` を横並びにするためには、親要素に```display: flex``` を指定すればよく、子要素に ```display: inline-block``` を指定する必要はなかった。 ```display: flex``` よくわかってない。理解したい。

### 参考
[ブロック内でブロック要素を上下左右中央揃えにする技](https://qiita.com/HiromuMasuda0228/items/6a51c2ce24c69c937092)
[上下中央揃えのCSSまとめ
Flexboxがたった3行で最も手軽](https://ics.media/entry/17522/)