OmniAICreator/Qiita-1.07M huggingface dataset:
PowerShellからサービスプリンシパルを使ってAzureにログインする

対話型

```powershell
PS /> $pscredential = Get-Credential

PowerShell credential request
Enter your credentials.
User: <IDを入力>
Password for user <ID>: <パスワードを入力>

PS /> Connect-AzAccount -ServicePrincipal -Credential $pscredential -Tenant <テナントID>
```

非対話型

```powershell
PS /> $passwd = ConvertTo-SecureString <パスワード> -AsPlainText -Force
PS /> $pscredential = New-Object System.Management.Automation.PSCredential('<ID>', $passwd)
PS /> Connect-AzAccount -ServicePrincipal -Credential $pscredential -Tenant <テナントID>
```

ref. https://docs.microsoft.com/ja-jp/powershell/azure/authenticate-azureps?view=azps-2.8.0
ブランチ【学習記録】

■ブランチとは
履歴の流れを分岐して記録していくためのもの
分岐したブランチは他のブランチの影響を受けないので、
同じリポジトリ内で複数の変更を同時に進めていくことができる

同じものだけど、別の世界線で作業するよ！的なことでしょうか、、

■masterブランチ
リポジトリに最初のコミットをするとmasterブランチが作られる
切り替えなければ、以後のコミットはこのブランチに追加される
統合ブランチとも呼ばれる

■トピックブランチ
機能追加やバグ修正など、ある課題に関する作業をする時に作成する
トピックブランチは統合ブランチから作成し、作業が終わったら統合ブランチに取り込む

■merge（マージ）
複数の履歴の流れを合流させること
分岐したブランチは他のブランチと合流（マージ）することで一つにまとめ直すことができる

■基本的なワークフロー
①最初はmasterブランチにいる
②機能Aを追加したいので、機能A用のブランチを切ります
③ブランチを切り替えます
④機能A追加okなので、masterブランチにマージします
⑤機能A実装完了
⑥機能A用のブランチはもういらないので削除

■ブランチ操作コマンド

ブランチを作成
`git branch ブランチ名`

ブランチの切り替え
`git checkout ブランチ名`

ブランチを作成後、切り替える
`git checkout -b <branch>`

ブランチをマージする
マージするブランチに切り替えてから`git merge 追加するブランチ名`

ブランチの削除
`git branch -d ブランチ名`

ブランチの一覧を表示
`git branch`

ブランチ名の変更
`git branch -m 旧ブランチ名　新ブランチ名`
DockerでPostgresSQLをビルドするとエラー

## 環境
macOS
Docker
PostgresSQL

### 経緯
下記サイトを参考に、Spring-boot+PostgresSQL環境で勉強したかったので、docker-composeで環境作成。
（下記サイト様は素晴らしく、独自で追加した内容が悪かったという流れです）

https://ameblo.jp/kazusa-g/entry-12535018096.html

コンテナdownしてもデータを残しておきたかったので、サイトを渡り歩いてdataをhostのフォルダと繋げてみました。

```yaml:docker-compose.yml
version: '3.2'
services:
    db:
        image: postgres:latest
        #省略
        volumes:
            - "$PWD/db_data/:/var/lib/postgresql/data"
            - "$PWD/init_db/:/docker-entrypoint-initdb.d/"
    java:
      #省略
```

### エラー内容
docker-compose up -dするものの、docker ps で確認すると、sb_dbのみExit(1)になる。
log見ると、

```
2021-03-13 05:24:51.750 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
2021-03-13 05:24:51.750 UTC [1] LOG:  listening on IPv6 address "::", port 5432
2021-03-13 05:24:51.765 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2021-03-13 05:24:51.908 UTC [27] LOG:  database system was shut down at 2021-02-28 11:28:55 UTC
2021-03-13 05:24:51.921 UTC [27] LOG:  invalid primary checkpoint record
2021-03-13 05:24:51.922 UTC [27] PANIC:  could not locate a valid checkpoint record
2021-03-13 05:24:51.924 UTC [1] LOG:  startup process (PID 27) was terminated by signal 6: Aborted
2021-03-13 05:24:51.924 UTC [1] LOG:  aborting startup due to startup process failure
2021-03-13 05:24:51.934 UTC [1] LOG:  database system is shut down
```

自分で追加した[- "$PWD/db_data/:/var/lib/postgresql/data"]をコメントアウトするとエラーが出ないのでここが諸悪の根源。

### うまくいった方法
https://gamingpc.one/dev/docker-volumes/#volumes-2

上記サイトを参考に、データのマウントする場所をhostでなく、dockerのvolumeに変更

```yaml:docker-compose.yml
      #省略
        volumes:
            - "dbdata:/var/lib/postgresql/data"
      #省略
volumes:
  dbdata:
```

postgresSQLのdockerはdata部がVOLUMEとのこと。
コンテナ内部に置いていないものをhostとつなげるってところが無理があったのだという理解です。
他のサイトでもvolume作ってそことつなげるが普通とみたいです。
コンテナdownしてもデータが消えなきゃいいのでこれで解決です。
ようやくメインのSpringのお勉強にうつれそう。
「初心者向け」ターミナルからmysqlでカラム一覧をみる方法。

記事を探すのに手間取ったので投稿します。

基本知識
database>table>colums
という階層となっていることに注意。


＜ターミナルでmysqlを起動＞

```
% mysql -u root -p;         
Enter password: 
```
パスワードを入力したら
以下のように表示が変わる

```
mysql>
```
<データベース一覧を表示>
＊注意　コマンドの最後に" ; "(セミコロン)を忘れないように！

```
mysql> show databases;
```
結果こうなる

```
+----------------------------+
| Database                   |
+----------------------------+
| blog_development           |
| information_schema         |
| mysql                      |
| performance_schema         |
| Recommend_spot_development |
| Recommend_spot_test        |
| recospo_development        |
| recospo_test               |
| sample_app_development     |
| sample_app_test            |
| sample_app_test-0          |
| sample_app_test-1          |
| sample_app_test-2          |
| sample_app_test-3          |
| sys                        |
+----------------------------+
15 rows in set (0.01 sec)
```

＜databaseを指定する＞
いきなりテーブルやカラムを取り出そうとするとdatabase選択されてないぞと怒られます。
以下のように指定する。

```
mysql> use recospo_development（データベース名）;
```
＜テーブルを確認＞

```
mysql> show tables from recospo_development（データベース名）;
```
結果がこちら

```
+-------------------------------+
| Tables_in_recospo_development |
+-------------------------------+
| active_storage_attachments    |
| active_storage_blobs          |
| ar_internal_metadata          |
| microposts                    |
| relationships                 |
| schema_migrations             |
| users                         |
+-------------------------------+
7 rows in set (0.00 sec)
```

＜カラム一覧表示＞

```
mysql> show columns from microposts（テーブル名）;
```
結果がこちら

```
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | bigint      | NO   | PRI | NULL    | auto_increment |
| content    | text        | YES  |     | NULL    |                |
| user_id    | bigint      | NO   | MUL | NULL    |                |
| created_at | datetime(6) | NO   |     | NULL    |                |
| updated_at | datetime(6) | NO   |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
5 rows in set (0.01 sec)
```

おわり！！

こんな基礎のことなのに、記事探してもあんまり見つからなかったので、備忘録にかきました。
[記録]コマンドライン引数について

#はじめに
<p>最近Djangoを触り始めたのだが、よく「python manage.py runserver」
(「python モジュール名 コマンド」)のようなコマンドを打つことがあり、モジュール名の後にコマンドを打つとなぜ特定の動きをするのか疑問に思った。

<p>参考はネットで見つけた以下の記事
>https://qiita.com/Tadahiro_Yamamura/items/cecbc27182b76257d18f
>https://techacademy.jp/magazine/20629

##コマンドライン引数
<p>「python モジュール名 コマンド」のコマンドの部分はコマンドライン引数というらしい。イメージとしては、関数における引数とほぼ同じだろう。
このコマンドライン引数はsysモジュールのargvという配列に格納されるらしい。

##sys.argvについて
<p>上記でも行ったがsys.argvはコマンドライン引数のリストである。ただし、先頭(srgv[0])はスクリプトの名前である。つまり、実行されるモジュール名が格納される。

##使い方
以下は入力したコマンドをすべて表示するプログラム。

```python:name.py
import sys

for comand_name in sys.arg:
　print(comand_name)
```
コマンドは「python モジュール名 コマンド コマンド(以下略)」のようにスペースを空けて何個でも入力できる。

##最後に
今回はコマンドライン引数について自分の復習のためにまとめてみました。プログラミング初学者なので言い回しや用語の使い方などに違和感や誤りがあるかもしれません。

<p>Djangoで使うようなコマンドの仕組みとあってるか違っているかもわからないが、何となく裏側で何が起こっているのかが把握できただけでも見通しが晴れて学びやすくなった。
Python 勉強メモ #2 リスト以外のデータ構造

# タプル
リストのようだが、イミュータブルであるデータ構造。要素を追加したり削除したりできない。
スライスによる操作や`count()`や、`index()`などのメソッドは使用できる。

```
t = (1, 2, 3, 4, 5)

# ()をつけなくてもカンマがついた時点でタプルと認識される
t = 1, 2, 3, 4, 5 → (1, 2, 3, 4, 5)

t[::-1] → (5, 4, 3, 2, 1)
t.count(1) → 1
t.index(1) → 0
```
## タプルのアンパッキング

```
tuple = (10, 20)
x, y = tuple → x = 10, y = 20

# これを使うと以下のような書き方もできる
min, max = 0, 100 → min = 0, max = 100

# 値の入れ替えを簡単にできる
a = 10
b = 20
a, b = b, a → a = 20, b = 10
```

# 辞書型(dict)
キーバリューでデータを管理できるデータ構造。Goで言うマップのようなもの。

```
d = {'x': 10, 'y': 20, 1: 300}
d['x'] → 10
d[1] → 300

# これでも生成できる
dd = dict(a=100, b=200) → {'a':100, 'b':200}
```

## dictの便利メソッド

```
d = dict(a=100, b=200)

# キーをリストで取得する
d.keys() → ['x', 'y']

# バリューをリストで取得する
d.values() → [100, 200]

# dictをアップデート。同じキーは上書きして、異なるキーは追加する。
d2 = dict(a=1000, c=300)
d.update(d2) → {'a':1000, 'b':200, 'c':300}
d.update(d2)

# 指定したキーに対応するバリューを取得する
d.get('a') → 1000

# 存在しないキーを指定すると、NoneTypeが返ってくる
d.get('d') → 

# 指定したキーの要素を取得して削除
d.pop('a') → {'b':200, 'c':300}

# 要素を全て削除
d.clear() → {}

# 要素が存在するかどうかを判定
'b' in d → True
'z' in d → False
```

# 集合型（set）
数学の集合と同じ。集合なのでインデックスはない。

```
# 集合なので重複は弾かれる
a = {1, 2, 2, 3, 3} → {1, 2, 3}
b = {1, 2, 3, 4, 5}

# 集合の計算ができる
a + b → {1, 2, 3, 4, 5}
b - a → {4, 5}
a & b → {1, 2, 3}

```

## set（集合）の便利メソッド

```
s = {1, 2, 3}
# 要素を追加する
s.add(4) → {1, 2, 3, 4}

# 要素を削除する
s.remove(4) → {1, 2, 3}

# 要素を全て削除する
s.clear()
```
Homebrew Install Mac M1

## はじめに
MacBookAir M1 で[homebrew](https://brew.sh/index_ja)をinstall設定した時のメモ


## install するが下記のログが出て brewが上手く使えない

```bash
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# ...
==> Installation successful!

==> Homebrew has enabled anonymous aggregate formulae and cask analytics.
Read the analytics documentation (and how to opt-out) here:
  https://docs.brew.sh/Analytics
No analytics data has been sent yet (or will be during this `install` run).

==> Homebrew is run entirely by unpaid volunteers. Please consider donating:
  https://github.com/Homebrew/brew#donations

==> Next steps:
- Add Homebrew to your PATH in /Users/<name>/.profile:
    echo 'eval $(/opt/homebrew/bin/brew shellenv)' >> /Users/<name>/.profile
    eval $(/opt/homebrew/bin/brew shellenv)
- Run `brew help` to get started
- Further documentation:
    https://docs.brew.sh
```

### Next steps を参考

- Pathを確認し、`.profile` がなかったので指定の配下にファイルを作成。

```bash
$ pwd
/Users/<name>

$ touch .profile
```

#### 作成したファイル `.profile` に以下を追記

```tex:.profile
# file/Users/<name>/.profile
eval $(/opt/homebrew/bin/brew shellenv)
```

#### brewが使えるか確認

```bash
$ brew --version
Homebrew 2.7.7
Homebrew/homebrew-core (git revision 5ae50e; last commit 2021-01-30)
```

## まとめ
こういった設定関係は、いつもスムーズにできなくて躓くのでメモとして✍️
SEGGER Embedded Studio で softdevice.hex が見つからない

Nordic の nRF52840 の開発中、コンパイルしようとしたら softdevice が無いというエラーが出た。

![Screenshot from 2021-03-13 10-50-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/20155f9d-4287-7b05-203e-7e2e8b5b45f1.png)



# 環境

- Ubuntu Linux 20.04
- SEGGER Embedded Studio for ARM Release 5.20  Build 2020102001.44035 Linux x64
SES (SEGGER Embedded Studio ) の Nordic の Free licenses を使用。

# 原因

プロジェクトツリーのプロジェクトを右クリック→「Options」→「Debug」→「Loader」→「Additional Load File[0]」

の内容が、


C:/SDK/components/softdevice/s140/hex/s140_nrf52_6.1.1_softdevice.hex 

になっていた。

# 修正

参照して、

SDKディレクトリの/components/softdevice/s140/hex/s140_nrf52_6.1.0_softdevice.hex

を指定し直してOK.
【Xcode】Swift Package Managerを使ってライブラリを追加してみる

SwiftPackageManagerを使ってライブラリを追加する方法を記します。

###使い方

Xcodeを起動し、File→SwiftPackages→Add Package Dependencyを選択します。

![スクリーンショット 2021-03-12 18.00.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840715/a754bdfc-ac1d-ccb5-2ff8-7182a780e3cc.png)

Choose Package Repositoryのウィンドウが出てくるので赤枠の箇所に追加したいライブラリのgithubURLをコピーしてきて貼り付けます。
※対象のライブラリがSwiftPackageManagerに対応しているかはgithubのリポジトリに記載があります。
対応しているライブラリを選んで貼り付けてください。
![スクリーンショット 2021-03-12 18.06.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840715/53d48648-117b-aa7e-8870-69db6f1de70a.png)

![スクリーンショット 2021-03-12 18.01.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840715/39a29b13-81f0-dbc5-2a7c-6aef6982f468.png)
![スクリーンショット 2021-03-12 18.04.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840715/eb0b576b-37a8-29a2-2608-60045a5b40b0.png)

貼り付けができたらNextを選択します。
![スクリーンショット 2021-03-12 18.04.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840715/4208a724-9a0f-4eb8-f19f-9f8f3dc966c0.png)

追加するライブラリのバージョンを指定する画面です。
デフォルトはVersionのUp to Next Majorが指定されており、これは「指定バージョン以上かつ次のメジャーバージョンより小さい」Versionを追加する設定です。
今回はこちらの設定で次へ進みます。

![スクリーンショット 2021-03-12 18.05.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840715/77a1c4d7-c9f9-3a18-652e-a574615a1ae9.png)
該当のライブラリが表示され、チェックマークがついてることを確認しFinishを選択します。
![スクリーンショット 2021-03-12 18.08.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840715/87711b4d-50dd-1343-6272-823dc62b5a66.png)
Projectにライブラリが追加されていることを確認して完了です！
![スクリーンショット 2021-03-12 18.08.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840715/d8c1988a-5fe5-1b76-88da-6050209e2f26.png)

###使ってみた感想
今まではcocoapodsしか使用したことがなかったのですが、管理のしやすさや導入のしやすさを考えるとSwiftPackageManagerの方が使いやすいように感じました！
デメリットとしては対応しているライブラリが他のパッケージ管理ツールほど多くないので、使うライブラリ次第では導入が難しいことです。

###最後に
最後までご覧頂きありがとうございました！
ご指摘などありましたらお気軽にコメントください！
BeautifulSoupによるXMLのパースについて


https://www.reddit.com/r/learnpython/comments/m3vj0a/urgent_help_me_convert_this_xml_to_csv/

で一旦は[Element Tree](https://docs.python.org/ja/3/library/xml.etree.elementtree.html)でやってみたんけど、別の人のやっている[BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/)が綺麗だったので、やってみた。

#data

[Generator Output by Fuel Type Hourly Report@Independent Electricity System Operator, Canada](http://reports.ieso.ca/public/GenOutputbyFuelHourly/PUB_GenOutputbyFuelHourly)のデータ

前日分までの発電種類で毎時集計したデータ

#code


```python:xml_read.py

from bs4 import BeautifulSoup as bs4
import requests 

url ='http://reports.ieso.ca/public/GenOutputbyFuelHourly/PUB_GenOutputbyFuelHourly'

r=requests.get(url)
 
soup = bs4(r.text,'lxml-xml')
result=[]
for i in soup("DailyData"):
    l=[[i.Day.text,v.Hour.text,]+[int(k.text) for k in v("Output")] for v in i('HourlyData')]
    for idx,lst in enumerate(l):
        tmp=lst[2:]
        l[idx].append(sum(tmp))
    result += l

df=pd.DataFrame(result, columns=['Date','Hour','NUCLEAR','GAS','HYDRO','WIND','SOLAR','BIOFUEL','Total'])

filename=soup.CreatedAt.text.replace("T","").replace(":","")

# to csv
# df.to_csv(filename+".csv", index=False)
```

#気づいたこと
BeautifulSoup(以下「BS」）のタグにアクセスするには
1. `soup.DailyData` : _bs4.element.Tag_
2. `soup("DailyData")` : _bs4.element.ResultSet_
の二つがあるけど、ループとかに使うには２番のほうじゃないと行けなかった。

#まとめ

`xml.etree.ElementTree`だと`re`を利用して余計なものを消さないとアクセスしづらかったけど、_BS_だと簡単だった。
Railsでメール送信機能を実装する

## これは何？
Railsの課題を実施しています。メール送信機能を作りましょうとの課題がありました。作りながら調べたことを勉強も兼ねてまとめています。

なお、実行環境は以下の通りです。

- Rails 5.2.3
- Ruby 2.6.0

そして、本記事は課題の内容を参考にしつつも[RailsガイドのAction Mailer の基礎](https://railsguides.jp/action_mailer_basics.html)から多くを引用して作成しています。

## メール送信機能の実装
### 必要ファイルの生成

それでは、早速メール送信機能を実装していきます。まずは以下のコマンドを打ちます。

```
$ rails g mailer UserMailer
```
このコマンドで、以下のファイルとディレクトリが追加されました。

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

また、Railsにはデフォルトで以下のレイアウトファイルが含まれています。

```
views      # 関係のないファイルは省略
└── layouts
     ├── mailer.html.slim
     └── mailer.text.slim
```
それぞれのファイルには、レイアウトに必要な設定が全て書かれています。**メール本文**に当たる部分は、先程生成した`app/views/user_mailer`ディレクトリ内に作成していきます。（下記は、デフォルトで生成されているレイアウトファイルのサンプル）

```slim:app/views/layouts/mailer.html.slim
doctype html
html
  head
    meta[http-equiv="Content-Type" content="text/html; charset=utf-8"]
    style
      |  /* Email styles need to be inline */
  body
    main
      = yield
```

### mailerの書き方（メール送信メソッドの実装）
mailerの書き方は、controllerに似ています。まず、デフォルトで生成されている`ApplicationMailer`には、以下のように記載されています。

```ruby:app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
  default from: 'from@example.com'
  layout 'mailer'
end
```
ここでの`default`は引数にハッシュを取り、全てのメーラーに共通の設定を記載できるそう。`from:`以外にも`to:`, `reply_to:`などの設定が[Railsガイド](https://railsguides.jp/action_mailer_basics.html#action-mailer%E3%81%AE%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF)では扱われていました。

先程生成した`UserMailer`には、`ApplicationMailer`を継承した、さまざまなメソッドを記載します。

```ruby:
class UserMailer < ApplicationMailer
  def welcome_email
    @user = params[:user]
    mail(to: @user.email, subject: 'メールのタイトルがここに入ります')
  end
end
```
`mail`の部分は、実際のメール・メッセージです。

### ビューの生成
`mailer`で定義した変数はビューで使えます。`app/views/user_mailer`に例えば以下のようなメッセージを作成することができます。

```slim:app/views/user_mailer/sample_mail.html.slim
h2= #{@user.name}さん
p= "アプリへようこそ！楽しんでいってくださいね！" 
p= link_to "ログインはこちら", login_url
```

mailの場合、`*_path`のように**相対パス**になる表示は使えないので、`*_url`のような**絶対パス**でパスを指定します。

### 送信のトリガー
最後に、送信のトリガーとなるメソッドを実装します。
userを作成した直後に、先の`welcome_mail`メソッドが発動するようにした場合、`users_controller`に以下のように記載します。

```ruby:app/controllers/users_controller.rb
class UsersController < ApplicationController
  def create
    @user = params[:user]
    if @user.save
      UserMailer.with(user: @user).welcome_mail.deliver_later
      # その他の処理は略
    end
  end
end
```
`.with`の部分で**key: value**を渡すと、その部分は`params`になって`UserMailer`に渡ります。

`deliver_later`の部分で、直前の処理（ここでは`create`が完了した場合、その直後にメールを送ることができます。

そのほかにも[deliver_nowなどのメソッド](https://railsguides.jp/action_mailer_basics.html#%E3%83%A1%E3%82%A4%E3%83%A9%E3%83%BC%E3%82%92%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%99)もあるようです。

### 完成！
以上で、メール送信メソッドを完成することができました!
実際には、[先の記事で紹介したletter_opener_web](https://qiita.com/tanutanu/items/c6193c4c2c352ac152ec)のgemを使っているので、メールを送信するとすぐに擬似的なメーラーが開いて確認できます＾＾

Railsの機能のおかげで、簡単に実装できるんですね。引き続き、頑張ろうと思います。
AWS CDKのフォルダ階層の変更をしたメモ

## 概要

[前回](https://qiita.com/hibohiboo/items/947c6627d07af439e541)までにApiGatewayが使えるまでになった。
ここで、「形で考えるサーバーレス設計」のCDKテンプレートとフォルダ構造がずれていたので、揃えてみる。

[ソースコード](https://github.com/hibohiboo/develop/tree/5bafa5d766c03df0526faacb3fd571e193c4a37a/tutorial/lesson/aws/typescript/projects/cdk_sample)

## 修正

* cdk以下にaws cdk関係のファイルを移動
* フォルダ階層を反映する必要があるものは修正


### setup

```diff:cdk/lib/process/setup.ts
#!/usr/bin/env node
import * as childProcess from 'child_process';
import * as fs from 'fs-extra';
import * as path from 'path'

const bundlePath = './bundle';
export const NODE_LAMBDA_LAYER_DIR = path.resolve(process.cwd(), bundlePath);
const NODE_LAMBDA_LAYER_RUNTIME_DIR_NAME = `nodejs`;
const runtimeDirName = path.resolve(process.cwd(), `${bundlePath}/${NODE_LAMBDA_LAYER_RUNTIME_DIR_NAME}`);
const distFilePath = (file: string) => path.resolve(process.cwd(), `${bundlePath}/${NODE_LAMBDA_LAYER_RUNTIME_DIR_NAME}/${file}`)
- const srcFilePath = (file: string) => path.resolve(`${process.cwd()}/${file}`)
+ const srcFilePath = (file: string) => path.resolve(`${process.cwd()}/../${file}`)

export const bundleNpm = () => {
  // create bundle directory
  copyPackageJson();
```

### stack

```diff:cdk/lib/sample-stack.ts
import * as cdk from '@aws-cdk/core';
import * as lambda from '@aws-cdk/aws-lambda';
import { NodejsFunction } from '@aws-cdk/aws-lambda-nodejs';
import * as apigateway from '@aws-cdk/aws-apigateway'
import { NODE_LAMBDA_LAYER_DIR } from './process/setup';

export class SampleStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
+    const entryHandlerDir = '../src/lambda/handlers/';
    const helloFunction = new NodejsFunction(this, 'hello', {
      runtime: lambda.Runtime.NODEJS_14_X,
-      entry: `src/lambda/handlers/hello.ts`,
+      entry: `${entryHandlerDir}/hello.ts`,
      functionName: 'kotahello',
      handler: 'lambdaHandler'
    });

```



## 参考

[Website & Mobile starter project - github][*1]
[サーバーレスをこれから始める方へ！「形で考えるサーバーレス設計」のCDKテンプレート(web/mBaaS編)を試して解説してみた][*2]
[【AWS】 CDKの始め方](https://qiita.com/maripoyo/items/f30ac4e8d2047c4edbe4)

[*1]:https://github.com/aws-samples/aws-lambda-sample-applications/tree/master/nodejs10.x/serverless-api-backend/cdk
[*2]:https://dev.classmethod.jp/articles/introduction-to-serverless-design-on-cdk/
統計的因果探索のLiNGAMを実装してみた

* 製造業出身のデータサイエンティストがお送りする記事
* 今回は、統計的因果探索手法の一つであるLiNGAMを実装してみました。

##はじめに
製造現場でデータサイエンスを行っている際、相関関係と因果関係をきちっと切り分けて分析することが重要だと思います。今回、データから因果関係を推測するための機械学習技術である[統計的因果探索](https://www.amazon.co.jp/exec/obidos/ASIN/4061529250/)を勉強しましたので、その中の1つ「LiNGAM」について整理しました。
細かい理論的な部分は書籍を参照して頂ければと思います。

##LiNGAMの流れ
今回、実装するLiNGAMモデルは、独立成分分析の手法を用いた方法になります。
具体的な因果関係は下記構造方程式の$\boldsymbol{B}$を推定することで実現します。

$$\boldsymbol{x} = \boldsymbol{B}\boldsymbol{x} + \boldsymbol{e}$$

$\boldsymbol{B}$はICA（独立成分分析）による混合行列を上記仮定を用いて一意に特定します。
$\boldsymbol{B}$は下記仮定より、正しい因果関係で置換すれば上三角部分が0となります。

- 未観測共通原因が存在しない　
- 有向非巡回モデルである
- 各変数が連続変数である
- 各変数の誤差項は非ガウス分布に従う
- 各変数の関係は線形である　

しかし、実際に得られる推定行列は、要素に0に近い値を持った$\boldsymbol{\hat{B}}$です。
ここから$\boldsymbol{B}$を推定するには、$\boldsymbol{P}$$\boldsymbol{\hat{B}}$$\boldsymbol{P}^T$の上三角部分が最小となるような置換行列$\boldsymbol{P}$を求めるという手法を取っているそうです。


今回もUCI Machine Learning Repositoryで公開されているボストン住宅の価格データを用いてLiNGAMを構築します。

pythonのコードは下記の通りです。

```php
# 必要なライブラリーのインポート
import pandas as pd
import numpy as np
from sklearn.datasets import load_boston

import graphviz
import lingam
from lingam.utils import make_dot

print([np.__version__, pd.__version__, graphviz.__version__, lingam.__version__])

np.set_printoptions(precision=3, suppress=True)
np.random.seed(100)
```

次にデータを読み込みます。

```php
# データセットの読込み
boston = load_boston()

# データフレームの作成
# 説明変数の格納
df = pd.DataFrame(boston.data, columns = boston.feature_names)

# 目的変数の追加
df['MEDV'] = boston.target

# データの中身を確認
df.head()
```

![スクリーンショット 2020-11-09 20.33.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/2ffa1a41-98dd-2798-1f6d-8f3385bf5f75.png)

次にグラフ構造を可視化するための関数を作成します。

```php
def make_graph(adjacency_matrix, labels=None):
    idx = np.abs(adjacency_matrix) > 0.5
    dirs = np.where(idx)
    d = graphviz.Digraph(format='png', engine='dot')
    # フォント設定
    d.attr('node', fontname="MS Gothic", fontsize="10")
    names = labels if labels else [f'x{i}' for i in range(len(adjacency_matrix))]
    for to, from_, coef in zip(dirs[0], dirs[1], adjacency_matrix[idx]):
        d.edge(names[from_], names[to], label=f'{coef:.2f}', fontsize="10")
    return d
```

ここから、LiNGAMを用いてモデルを学習し、可視化します。

```php
model = lingam.DirectLiNGAM()
model.fit(df)

labels = [f'{i}. {col}' for i, col in enumerate(df.columns)]
make_graph(model.adjacency_matrix_, labels)
```

![スクリーンショット 2021-03-13 15.29.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/1ee9da05-b75a-fa9f-735d-38d68edae6f3.png)

##さいごに
最後まで読んで頂き、ありがとうございました。
結構簡単に利用できることが分かりました。ノードはパラメータの設定次第で結果が変わってくるため、調整は必要ですが、これで因果関係を可視化できそうです。

訂正要望がありましたら、ご連絡頂けますと幸いです。
多変数暗号アルゴリズム開発者の略歴

普段多変数暗号アルゴリズム(量子耐性)について書いておきながら、肝心の渡辺さん(開発者)の経歴について書いてなかったので、遅ればせながら書きます。


**渡邊栄治（Eiji Watanabe）**


![渡邊英治](https://firebasestorage.googleapis.com/v0/b/hideaki-97c59.appspot.com/o/images%2FRFBAr1g92gNmXX7ETW6vA3XoYoB3%2FusQ7feWJa.jpeg?alt=media)


ちなみに僕はいつも「渡辺」さんと表記してますが、正確にはこちらの難しい方の漢字が正確です。メールのやりとりではご本人も「渡辺」の表記なので僕もそれに倣ってます。


**1964年東京電気大学・電子工学科を卒業**


不思議なもので、渡辺さんが大学をご卒業されたのは前回の「東京オリンピックの年」です。その渡辺さんの発明に、世代がかわって再びの東京オリンピックの年に僕が関与できていることに、なんとも言えないご縁を感じています。


**日本電子株式会社に入社後1972年まで株式会社フジミックに在籍**


日本電子株式会社は僕が今更説明するまでもなく、東証1部に上場する理化学機器メーカーです。知らなかったんですが、電子顕微鏡では世界シェア首位なんですね。株式会社フジミックは放送関連技術を扱うフジテレビ系列の企業です。


**1979年にメテオーラ・システム株式会社を設立**


現在渡辺さんが活動主体としているメインの法人です。技術開発の委託を受けることもありますが渡辺さんご自身の技術開発や開発した技術のライセンス管理などが主な目的の法人ですので、積極的な営業活動などは一切していません。


**1982年07月に株式会社アマダと資本提携(2005年03月に資本提携を解消)**


株式会社アマダは神奈川県に本社を置く板金加工機器の総合メーカーです。これまでの渡辺さんのキャリアとは業界が異なるので今度機会があれば資本提携の経緯について聞いてみます。


**2018年にポスト量子ビット株式会社を特許の現物出資で設立**


現在2021年ですので、3年ほど前から量子コンピューターによる未知の脅威に対して、その対策技術の研究に力を入れはじめました。暗号技術、セキュリティ分野での造詣を活かし、発明家として現在まで以下の技術を確立しています。


**未知のバックドアが活動を開始したとき、バックドア接続をサブネットTCP/IP層で自動切断する技術**


5G、6G通信にはバックドアがありその存在は一般にあまり知られていませんが、渡辺さんは普段からその脅威に対し警鐘を鳴らしています。


**非可換アルゴリズムを応用する技術**


「多変数暗号アルゴリズム(量子耐性)」の基礎技術です。NISTは可換アルゴリズムによるポスト量子技術の標準化を目指しファイナリストを選出していますが、可換アルゴリズムでは対処できない課題に渡辺さんは非可換アルゴリズムで解を導きました。
VS Codeでphpcsが動かない問題

何だかんだで1時間弱くらいハマってイラッとしたので、インターン生とかにも共有できるようにメモを残しておく

# エラー内容
phpcsのエラーでググるとよく出てくるこのエラーが発生。
既存プロジェクトでも上手く動くもの、動かないものがあったり、新規プロジェクトだとやっぱり動かなかったりして謎

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29195/94ed0cd2-55c0-0c78-0a73-0752eda9d78a.png)

# 解決方法
シンプルにStack Overflowのベストアンサーをそのまま試したら直った

cf.) https://stackoverflow.com/questions/47174009/visual-studio-code-unable-to-locate-phpcs/52477116

> 1. Install the phpcs by using composer with composer global require squizlabs/php_codesniffer
2. Press Command + , (Click Code -> Preferences -> Settings)
3. Select User Settings and locate 'PHP CodeSniffer'
4. Scroll to 'Executatble Path' and put `/Users/your-username/.composer/vendor/bin/phpcs`
awscli で help したときにサブコマンドの頭についている約物は何なのか

AWS で Cloud Shell が使えるようになったことで、awscli の活用シーンが増えていく気がしています。

awscli 初心者なので help を眺めることが多いのですが、ふとサブコマンドの一覧を一画面に収めたい気持ちになりました。

```console:とりあえずIAMのヘルプ
$ aws iam help 
...(略)...
NAME
       iam -

DESCRIPTION
       AWS  Identity and Access Management (IAM) is a web service for securely

...(略)...

       o update-user

       o upload-server-certificate

       o upload-signing-certificate

       o upload-ssh-public-key

       o wait

       o wizard



                                                                         IAM()
```

サブコマンド毎に空白が入るので必要以上に長いですね。

約物（頭の 'o'）が付いているので、とりあえず `grep` します。

```console
$ aws iam help | grep 'o '
       controlling access to AWS services. With IAM, you can centrally  manage
       o add-client-id-to-open-id-connect-provider
       o add-role-to-instance-profile
       o add-user-to-group
       o attach-group-policy
       o attach-role-policy
       o attach-user-policy
...(略)...
```

1行目にゴミが入りました。解る人には解ると思いますが、ピンポイントで約物を狙いたくなりましたので、以下のようにしました。

```console
$ aws iam help | grep ' o '
```

出力が無くなりました。約物の前方は唯の空白ではないようです。`cat` で制御文字を表示してみます。

```console
$ aws iam help | grep 'o ' | cat -A
...(略)...
       +^Ho update-service-specific-credential$
       +^Ho update-signing-certificate$
       +^Ho update-ssh-public-key$
       +^Ho update-user$
       +^Ho upload-server-certificate$
       +^Ho upload-signing-certificate$
       +^Ho upload-ssh-public-key$
       +^Ho wait$
       +^Ho wizard$
```

何か出ました。これは「+」と「[バックスペース](https://ja.wikipedia.org/wiki/ASCII#ASCII%E5%88%B6%E5%BE%A1%E6%96%87%E5%AD%97)」が隠れているようです。`grep` は制御文字を引っ掛けることもできるので、以下のようにするとサブコマンドだけの一覧を得ることができます。

```console
$ aws iam help | grep '+\bo'
       o add-client-id-to-open-id-connect-provider
       o add-role-to-instance-profile
       o add-user-to-group
...(中略)...
       o upload-server-certificate
       o upload-signing-certificate
       o upload-ssh-public-key
       o wait
       o wizard
```

一覧きれい
error: failed to push some refs to 'git リポジトリ名' 　git pushしたら怒られた

# git pushをやりうとしたら同じエラーに躓いてしまったのでまとめてみた！

<img width="812" alt="スクリーンショット 2021-03-07 7 02 01" src="https://user-images.githubusercontent.com/56257230/110222064-07638180-7f13-11eb-9252-644ced6178a6.png">

## 原因

この commit を行う前に、私がリモートで github の README の変更を行っていたことが
今回のエラーの原因でした。

- 「リモートのファイルがローカルのファイルも最新版だから、そのファイルに push できないですよ」ということみたいです yo らしい

## 対応

```
 git pull
  ⏬
 git stash で 1 つ前に戻し
 再度 add. commit し push したら動いた！

```
### 二回目は↑では動かず💦調べてみた結果⬇️の手順でうまく解決できました
## 対応 2

```ruby
 git fetch    （リモートの変更を取ってきて）

 git merge origin/master    （マージする）
```

- これで動いた
mindstroms nxt2.0でタッチセンサーを動かしてみた

## mindstroms nxt2.0でタッチセンサーを動かしてみた

<iframe width="100%" height="500" src="https://www.youtube.com/embed/qmcp35RcLJE" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


**ソースコードはこちらからコピーして遊んでみてください。**

```
SourceFile002.c
--------------

#pragma config(Sensor, S1,     touch,          sensorTouch)
#pragma config(Sensor, S2,     touch,          sensorTouch)

task main()
{
	while(true)
	{
		while(SensorValue (S1) ==0)
		{
			motor[motorC] = -100;
		}
		while(SensorValue (S2) ==0)
		{
			motor[motorC] = 100;
		}
	}
}
```
Python 勉強メモ #1 リスト操作

# 初めに
Python勉強のメモを気が向いたらQiitaにまとめようと思います。新しいことを覚えたら更新していきます！

# リスト操作

## メソッドによる操作
```
s = [1, 2, 3, 4, 5]

# 末尾に要素を追加
s.append(10)

# n番目に要素を追加
s.insert(n, 100) 

# n番目要素を取り出して削除する
s.pop(n) 

# 指定した値と同じ要素を削除、複数ある場合は最初の要素が削除される
s.remove(n)

# 全ての要素を削除
s.clear()

```

## スライスによる操作
```
s = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# ０番目から最後まで
s[:]  → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

# 1番目から最後まで
s[1:] → [2, 3, 4, 5, 6, 7, 8, 9, 10]

# 0番目から3番目まで
s[:4]  → [1, 2, 3, 4]

# １個飛ばしで０番目から最後まで
s[::2] → [1, 3, 5, 7, 9]

# 2個飛ばしで0番目から最後まで
s[::3] → [1, 4, 7, 10]

# 1個飛ばしで２番目から最後まで
s[2::2] → [3, 5, 7, 9]

# 1個飛ばしで2番目から7番目まで
s[2:8:2] → [3, 5, 7]

# 末尾の要素を指定する
s[-1] → 10

# 順番を反転させて０番目から最後まで （めっちゃ便利！！）
s[::-1] → [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

# 順番を反転させて１個飛ばしで0番目から最後まで
s[::-2] → [10, 8, 6, 4, 2]
```

## リストの結合
```
a = [1, 2, 3, 4, 5]
b = [6, 7, 8, 9, 10]

# 以下の三つどれでもできる
x = a + b 
a += b         →　[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a.extend(b)
```


# リストの便利メソッド
```
r = [1, 2, 3, 4, 5, 1, 2, 3]

# 指定した要素を探して、最初に見つかった要素のインデックスを返す。
r.index(3)　→　2

# 指定した要素を3番目から探して、最初に見つかった要素のインデックスを返す。
r.index(3, 3) → 7

# 指定した要素の数を数える
r.count(3) → 2

# リストを逆転させる
r.reverse() → [3, 2, 1, 5, 4, 3, 2, 1]

# リストをソートする
r.sort → [1, 1, 2, 2, 3, 3, 4, 5]

# リストを逆順にソートする
r.sort(reverse=True) →　[5, 4, 3, 3, 2, 2, 1, 1]

# 特定の値が含まれているかどうか判定
1 in r → True
10 in r → False
```
デートの時の話題について（ライフハック）

イーロン・マスクがデートの時に電気自動車の話をしたとYouTubeで見ました。
彼女にはじめて会って、「電気自動車のことを考えたことある？」と質問したとのこと。

ってな話をカミさんにしたら、じーっとこっちを見ていたので、
「もしかして俺もそうだった？」と聞いたら。
「うん。何を話しているか、全くわからなかった。」と言われた。
技術者あるあるかな。:relaxed:
Debian 10 BusterでNvidia RTXシリーズを使うと、gdmが起動しない

# 環境
ASRock X570 SteelLegend
AMD Ryzen 9 3950X
GALAX GeForce RTX 2070 Super

Debian 10 Buster
Linux 4.19.0-14-amd64

## 問題点
インストール後、[OK] Started Gnome Displayでスタックする
X11のログを見ると、no screen foundエラーで停止していた。

## 対処
最新版Nvidiaドライバのインストールとカーネル、ファームウェアの更新で解決した

スタック後、ttyを切り替えてログインする
Debianのバックポートを有効化する(contribとnon-freeも必要)

```
# echo deb http://deb.debian.org/debian buster-backports main contrib non-free >> /etc/apt/sources.list
# apt update  
```


ファームウェア、Nvidiaドライバのインストールとカーネルの更新

```
# apt install -t buster-backports nvidia-driver firmware-misc-nonfree firmware-linux firmware-linux-nonfree linux-headers-5.10.0-0.bpo.3-amd64 linux-image-5.10.0-0.bpo.3-amd64
```

Nvidiaドライバ460.39以降が導入できれば成功

X11の設定を削除する

```
# mv /etc/X11/xorg.conf /etc/X11/xorg.conf.bak
# mv /usr/share/X11/xorg.conf.d /usr/share/X11/xorg.conf.d.bak
```

ここまでの手順でgdmは起動したものの、マウスとキーボードが動作しなかった
ログを見るとno input driver specified ignoring this deviceエラーを繰り返し吐いていた
evdevのインストールで解決した

```
# apt install xserver-xorg-input-evdev
```
Windows10 で SSHサーバー を起動する

下記の記事で SSHサーバー が使えるようになったとの情報を見て軽く試してみました。

> Windows10 1803からOpenSSHサーバーが正式につかえるようになった
https://qiita.com/kenji0x02/items/3f4e7262e6de0d8c8702

## 試した環境

・Windows 10 Pro (64bit) 20H2

今回試した環境OSは、 Professional Edition ですが Home Edition でもできそうです。

・Git

git bash 使いたいので、Gitもインストールしておきます。

・TeraTerm

接続確認用

## SSH サーバーのセットアップ

まずは、SSH サーバーのセットアップですが・・・
セットアップ方法は、だいたい先ほど紹介した記事に書いてあります。

> スタートメニューの[アプリと機能]-[オプション機能の管理]-[機能の追加]でOpenSSH サーバーを選択して[インストール]をクリック
https://qiita.com/kenji0x02/items/3f4e7262e6de0d8c8702

![xxxxx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238600/d7454244-13a1-1e62-8291-f9a95918f794.png)

チェックしてインストール押して待つだけ。
うーん。簡単。

インストール完了したら下のリストに並びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238600/5daf083c-e1f7-eeea-9d4b-324744dff3f3.png)

入れただけではサーバーは立ち上がってないので、
コマンドなどから起動してあげる必要があります。

接続時のterminal デフォルト設定が コマンドプロンプト になっているようなので、
Git bash に変更しておきます。

```powershell
PS C:\WINDOWS\system32> New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Program Files\Git\bin\bash.exe" -PropertyType String -Force


DefaultShell : C:\Program Files\Git\bin\bash.exe
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\OpenSSH
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE
PSChildName  : OpenSSH
PSDrive      : HKLM
PSProvider   : Microsoft.PowerShell.Core\Registry

```

※管理者権限でPower Shellを立ち上げてコマンドを実行

他のPCから接続する使い方をする場合は、ファイアーウォールの設定も必要なようです。
接続時の認証がパスワードになっているので、鍵認証な接続したい場合も設定が必要です。
下記の記事を参考にやってみてください。今回はローカルのみ＋パスワード接続で使わないのでスキップします。

https://qiita.com/TukamotoRyuzo/items/7bd4ff6810421bdc9924#5-%E9%8D%B5%E8%AA%8D%E8%A8%BC%E6%96%B9%E5%BC%8F

デフォルトは、手動でSSHサーバーを立ち上げないと起動しませんが、
パソコン立ち上げたら自動で起動するようにも設定できます。

今回は設定せずコマンドで立ち上げます。

```powershell
PS C:\WINDOWS\system32> Start-Service sshd
```

これで立ち上がりました。

## 接続確認

TeraTerm で接続確認してみます。

ログイン時に使っているMicrosoftアカウントでもできるようなのですが
うまくいかなかったので、 (たぶんマルチバイトを含むIDだから？
ローカルにユーザー作ってやってみます。

> 端末を Microsoft アカウントで利用している場合でも、実ユーザー名（C:¥Users¥???? の ???? の部分）とそのパスワードでログインできます。
https://qiita.com/iShinkai/items/a12c9d26f8f4264897f9

コンピューターの管理 > ローカル ユーザーとグループ > ユーザー に接続確認用のアカウントを追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238600/dd377706-6162-19bb-cbf3-e775863bf473.png)

ホストに `localhost` いれて OK 押す。（使っているPCに接続する）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238600/7be29808-b3cf-ee33-3ce1-69f5e6cecd73.png)

先ほど ユーザー作ったときの ID と PASS を入れる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238600/6abdc471-64cf-8e73-e207-75a39379569b.png)

接続できた！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238600/82b3526f-d6bb-91f3-7a6c-e4b82d084bbc.png)

接続後は、ユーザーディレクトリがカレントディレクトリになっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238600/a00f82a4-2410-c072-89c1-f3725dbb5567.png)

`ls` でローカルにあるフォルダが表示されましたね。

## まとめ

簡単にSSHサーバーの導入・起動・接続ができました。

今回は使っているPC内だけで完結していますが、他のPCからコマンドを実行できるといろいろ活用できそうですね。

みなさんも触ってみてくださいね～！
Visual studio codeでhadolintを使うためのTips

## What is hadolint?
[hadolint](https://github.com/hadolint/hadolint) は Dockerfileのlinterです。
Dockerfile内でベストプラクティスに沿っていない書き方を見つけて警告を出してくれます。

## hadolint for Visual studio code
[hadolint \- Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=exiasr.hadolint)
`Dockerfile`を編集・保存していちいちlinterにかけるのも面倒くさいのでVS codeの拡張が存在します。
しかし、そこの`README.md`にはhadolintをhomebrew経由でインストールしたものを利用する方法しか紹介されていません。
自分はdocker container内のhadolintを使いたかったので今回その方法について調べたのでTipsとして残しておきます。

## How to use hadolint installed in a container
[Add support for running hadolint from docker image · Issue \#37 · ExiaSR/vscode\-hadolint](https://github.com/ExiaSR/vscode-hadolint/issues/37)

幸いなことに、過去にissueが立っていて同じくコンテナの中のhadolintを使う方法について紹介してくれている人がいました。

利用の手順としては次のとおりです。

1. PATHが通っている適当なディレクトリに下のようなshell scriptを作成します。
   最新のhadolintではエラーや警告に自動的に色付けがされましたが、エディタ内の警告メッセージでは色付けのためのコードがそのまま文字として出力されてしまうため見づらくなってしまいます。 そのため、`--no-color`を指定して色付けを無効化します。
 
    ```shell
    #!/bin/bash

    docker run --rm -i hadolint/hadolint:latest hadolint - --no-color < "$@"
    ```

1. 上で作ったコマンドをVS codeのhadolintの設定項目から指定する。

拡張が機能すると下のように警告があれば下線が引かれてエラーのレベルと内容が出るようになります。
![ScreenShot 2021-03-13 14.42.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4981/854d892a-85e6-ff41-9f85-1f695191f095.png)

たった2つの手順で簡単にVS codeでhadolintを使うことが出来るようになりました。
以上、簡単なtipsでしたが日々のDockerfile編集が楽になれば幸いです。

Enjoy your docker life!
【monaco-editor】カーソル位置を設定


## 概要
`monaco-editor` でカーソル位置を設定する

- ex. 3行目の5文字目に設定する場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320365/dae10a80-8dfd-346d-75e2-c59e5acb2787.png)

## 実装

`setPosition` で、 `lineNumber (行数)` と `column (文字数)` を設定する

```ts
editor.setPosition({
    lineNumber: 3,
    column: 5,
});
```

## 参考文献

- [Monaco Editor API](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.icodeeditor.html#setposition)

## 関連記事

- [【monaco-editor】閉じタグの補完](https://qiita.com/Naoto9282/items/deb735440b45853950b3)
BIO


#BIO
```
同步阻塞IO。B代表blocking
服务器实现模式为一个连接一个线程，即客户端有连接请求时服务器端就需要启动一个线程进行处理，如果这个连
接不做任何事情会造成不必要的线程开销，当然可以通过线程池机制改善。
适用场景：Java1.4之前唯一的选择，简单易用但资源开销太高
```


## 1.Server側
```IOServer.java
package com.lagou.bio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class IOServer {
    public static void main(String[] args) throws IOException {
        // 首先创建一个serverSocket
        ServerSocket serverSocket = new ServerSocket();
        serverSocket.bind(new InetSocketAddress("127.0.0.1",8081));
        while (true){
            final Socket socket = serverSocket.accept();// 同步阻塞
            new Thread(()->{
                byte[] bytes = new byte[1024];
                try {
                    int len = socket.getInputStream().read(bytes);
                    System.out.println(new String(bytes,0, len));
                    socket.getOutputStream().write(bytes,0,len);
                    socket.getOutputStream().flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

```

## 2.Client側
```IOClient.java
package com.lagou.bio;

import java.io.IOException;
import java.net.Socket;

public class IOClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 8081);
        socket.getOutputStream().write("hello".getBytes());
        socket.getOutputStream().flush();
        System.out.println("server send back data =====");
        byte [] bytes = new byte[1024];
        int len = socket.getInputStream().read(bytes);
        System.out.println(new String(bytes, 0, len));
        socket.close();
    }
}
```
interface インターフェース　PHP　オブジェクト指向

#interfaceとは
すでに親クラスが存在するが、すべての子クラスではなく特定のクラスにのみ継承したい場合に使用する

**以下の場合、Postクラスにのみメソッドの指定を強要したい場合を考える**
**しかし、使用上、子クラスは一つの親クラスしか持ってはいけない**

```PHP
abstract class BasePost
{
  protected $text;

  public function __construct($text)
  {
    $this->text = $text;
  }

  abstract public function show();
}

class Post extends BasePost
{
  public function show()
  {
    echo $this->text . PHP_EOL;
  }
}

class StaredPost extends BasePost
{
  private $star;

  public function __construct($text, $sponsor)
  {
    parent::__construct($text);
    $this->star = $star;
  }

  public function show()
  {
    echo $this->text . PHP_EOL;
    echo $this->star . PHP_EOL;
  }
}
```
##使い方
①interfaceとその中に強要したいメソッドを一番上に表記する
②指定したいクラスに[implements interface名]を追記する
③指定したクラスに処理を追加する

```PHP
//①
interface plusInterface
{
  public function plus();
}

abstract class BasePost
{
  protected $text;

  public function __construct($text)
  {
    $this->text = $text;
  }

  abstract public function show();
}
//②
class Post extends BasePost implements plusInterface
{
　//③
  private $pluses = 0;

  public function pluses()
  {
    $this->pluses++;
  }

  public function show()
  {
    echo $this->text . PHP_EOL;
    echo $this->pluses . PHP_EOL;
  }
}

class StaredPost extends BasePost
{
  private $star;

  public function __construct($text, $star)
  {
    parent::__construct($text);
    $this->star = $star;
  }

  public function show()
  {
    echo $this->text . PHP_EOL;
    echo $this->star . PHP_EOL;
  }
}

```
[SwiftUI] lineLimitで複数行表示されなかったのでその対処法

文字数によって行数を自動で変えたいときは``lineLimit(nil)``を使えば自動で変わってくれます。
しかし、それが適用されない場合があったので共有しておこうと思います。

``` swift

VStack(alignment: .leading) {
    Text("ここに長文を記入 ここに長文を記入 ここに長文を記入 ここに長文を記入")
        .lineLimit(nil)
    Text("ここは短文")
}
.frame(height: 60)

```

`frame`で高さを指定すると強制的にその高さに設定されるので、`lineLimit`が働きませんでした。

##解決策
* 高さを動的に変更する
* `frame`を指定しない
* `frame`の幅を大きめに設定する
似たようなFlutterアプリを作るために、共通リポジトリを作成した話

## やりたかったこと

2つの似たようなアプリを作りたい。

1つのデータソースに対して、利用者側と運営者側のアプリがあるイメージです。

全体的な機能・画面構成は異なるため、1つのコードベースで2つのアプリを出力する（内部に条件分岐などを入れる）では辛いと考えました。
ただし、API通信基盤やUIパーツ、一部の画面は共通化できそうだったので、それをどのように管理・更新していくかが課題となりました。

## 先に結論

common用のリポジトリを作成し、共通化できる箇所はその中に実装しました。
各アプリリポジトリでは、 Git submodule で `packages` ディレクトリにそれを読み込むこととしました。
それを、 `pubspec.yaml` にて相対パスで読み込みました。

（A, Bという2つのアプリと、commonリポジトリがあるイメージ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8708/eacb9161-3e98-e70b-bb20-6f61d6788e75.png)

### 良かった点

- 共通化することで、不具合が発生した場合に、1箇所の修正で済んだ。
    - ただし、各アプリリポジトリ側で common のコミットハッシュを更新する必要がある。（これは、「取り込みタイミングを任意にできる」という利点でもある）
- GitHubのPR上で、「どのコミットハッシュに書き換えられたか」が可視化されていた。
- それぞれのアプリ、共通部分の履歴（コミット・PR・tagなど）を分離できるため、それぞれのアプリライフサイクルを個別に管理できる。
- CIを分離しやすかった。（共通部分の修正の場合には、共通部分のCIのみ実行するなど）

### 悪かった点

- 修正に手間が増えた。それにより、「commonリポジトリを修正せずに問題を解決する方法」を探す力学が働きやすくなった。
    - commonリポジトリの修正 -> 各リポジトリでsubmoduleのcommit hashの更新 -> 利用箇所の修正の手順が必要。
    - また、各リポジトリで修正をマージする前にレビューも行ったため、さらに手間が大きかった。（commonのfeatureブランチを指している状態 -> commonのmainブランチに取り込まれたコミットを指している状態 -> マージ可能な状態という手順が必要。）
- １つの横断的な修正に対して、PRが最大3リポジトリに分離されるため、人の手でリンクさせてやる必要がある。（PRのdescriptionにURLを記載するなど）
- pull したあとに `git submodule update --init` する必要がある。
- 今回は、1つのアプリ実装後に慌ててcommonリポジトリを作成したため、共通化部分の精査が甘かった。「何を共通化するべきか」は未来を考える必要もあるので難易度が高かった。
    - また、あとになって「これも入れておけば」とか発生しても、3リポジトリを修正する必要があり、腰が重くなってしまった。
- 最新を指しているのかを差分から判断しづらい（PR上で見えるのはコミットハッシュなので）。
    - 初学者などがチームに混ざっていると、気をつけてレビューしないと巻き戻ってしまったりする。

## 他に考えた案

### 案1: Flutter packageとして定義する

共通部分を1つのgitリポジトリとして作成しておき、 `pubspec.yaml` にて `git` を利用して指定する。
参考: https://dart.dev/tools/pub/dependencies#git-packages

**メリット**

- `ref` を使って"バージョン番号"で管理できるため、最新かどうかを判断しやすい。
- 他のライブラリなどと同様に扱うことができる。

**デメリット**

- バージョン番号の管理が面倒。
    - 複数人で更新する場合には、バージョン番号の衝突を避けるようなフローが必要。
- パッケージをプライベートにするのは少し大変（CI上でトークンの管理したり？未確認。）

### 案2: 1つのリポジトリにまとめる

リポジトリルートに、それぞれのアプリディレクトリとcommon部分のディレクトリの計3つを作成する。
それぞれのアプリでは、 `pubspec.yaml` に相対パスでcommonパッケージを指定する。
参考: https://dart.dev/tools/pub/dependencies#path-packages

**メリット**

- 比較的わかりやすい。
- 1つのリポジトリをcloneするのみで、特別な操作なく開発を始めることができる。
- 1つのPRに、すべての変更を含めることができる。

**デメリット**

- コミット履歴・PR・タグなどが2アプリ分混在してしまい、単一アプリに対する変更が追いづらくなる。
- CIの設定が複雑化する（やり方を工夫したり、CIの設定を複雑化させると対応は可能だと思われる）
    - アプリ毎のルートが1つ下のディレクトリになるため、 `working_directory` などを指定する必要がある。
    - どちらのリポジトリに対する変更可を判断してビルドを開始するなど、ビルド時間短縮のための設定が追加で必要になる。（もしくは、富豪的に解決するか）
- アプリ単位でのアクセスコントロールが不可能。
    - リポジトリが別れていれば、「Aリポジトリは書き込みできるが、Bは読み込みのみ」などがGitHubの機能で実現可能。

### 案3: 共通化を諦めてファイルコピー

リポジトリを2つ作成し、それぞれの物理的な依存関係をなくす。
共通にできそうな部分であっても、それぞれのリポジトリのコードとして管理する。

**メリット**

- 一番わかりやすい
- それぞれのアプリで、個別の要件が発生した場合にも、柔軟に対応できる。

**デメリット**

- 重複コードが大量に発生し、メンテナンスが大変になる。
- 2アプリ間で同じように見えるコードであっても、差が無いかをしっかり確認して修正する必要がある。

## まとめ

先にも書いたように、今回は git submodule + `pubspec.yaml` による相対パス指定を選択しました。
ただし、共通化を考えきれなかった部分では、案3のような状態になってしまいました。

仕様やデザインレベルで、「何が共通的で、何が個別のものか」を、プロダクトオーナー・デザイナー・エンジニアが同じ認識を持ち、それをコードに反映されているのが、あるべき姿のように感じました。（時間かかるし、難しいですが）
【monaco-editor】閉じタグの補完

## 概要
`monaco-editor` で `html` のタグを閉じた際に、閉じタグの補完する。
`monaco` の標準の機能では実現できなかったので(2021年3月13日時点)、独自に実装する。

![f0a1d036d04bdff363f63b0b2eac75dc.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320365/b6d7f500-0fef-f244-44b4-189b6f4385aa.gif)

## 手順
1. `keyUp` のイベントを講読
2. `>` か否か
3. 補完前のコードを取得
4. 補完するタグを取得
5. 閉じタグを補完
6. 補完後にタグの中央へ位置を戻す

```ts
editor.onKeyUp((event) => {
    // 1. `>` か否か
    const keyCode = event.keyCode as number;
    if (keyCode !== 84) return;

    const model = editor.getModel();
    if (!model) return;
    const position = editor.getPosition();
    if (!position) return;

    // 2. 補完前のコードを取得
    const codePre = model.getValueInRange({
        startLineNumber: position.lineNumber,
        startColumn: 1,
        endLineNumber: position.lineNumber,
        endColumn: position.column,
    });

    // 3. 補完するタグを取得
    const tag = codePre.match(/.*<(\w+)>$/)?.[1];
    if (!tag) return;

    // 4. 閉じタグを補完
    editor.trigger('bra', 'type', {
        text: `</${tag}>`,
    });

    // 5. 補完後にタグの中央へ位置を戻す
    editor.setPosition(position);
});
```

## 参考文献

- [Auto complete for HTML -- add the close tag #221](https://github.com/microsoft/monaco-editor/issues/221)

## 関連記事

- [【monaco-editor】カーソル位置を設定](https://qiita.com/Naoto9282/items/650dc46bd2856f24d398)
Tinder（ティンダー）のスワイプ自動化


##TinderPC版にログイン
ブラウザ（Google Chrome）で、https://tinder.com/ にアクセス。

Tinderにログインをします。（※アプリではなくブラウザ版のTinder）


##デベロッパーツールのコンソールをいじる
デベロッパーツールを開いて、Consoleを選択。
以下のソースコードを入力します。

```
var autoswipe = function(){
document.getElementsByClassName(“button Lts($ls-s) Z(0) CenterAlign Mx(a) Cur(p) Tt(u) Bdrs(50%) P(0) Fw($semibold) focus-button-style Bxsh($bxsh-btn) Expand D(b) Bgc(#fff) Trstf(e) Trsdu($normal) Wc($transform) Pe(a) Scale(1.1):h Scale(.9):a”)[2].click();
}
setInterval(autoswipe, 1000);
```

##あとは待つだけ

自動化されたらあとは待つだけという簡単な操作を行いました。

https://youtu.be/DXm8StDOrB0

今回参考にした記事
https://matching-theory.com/tinder-automation/
Spring BootでControllerとURLが重複するstatic resourceを扱えるようにする→無理だった

この記事一旦中断です。
Spring Framework 4.0で実績がある方法だったのですが、Spring Boot 2.0 で試すと動作しませんね。
調査します。

URLとControllerやstatic resourceなどをマッピングする際、何種類かのMappingオブジェクトが使用されます。
Mappingオブジェクト内でURLとControllerなどのパターンマッチングが行われるわけです。
デフォルトでは最後に使用されるのが `SimpleUrlHandlerMapping` なんですが、このMappingオブジェクトはURLとマッチするパターンとして `/**` が定義されています。
そのため他のMappingオブジェクトでマッチしなかったURLを、 `SimpleUrlHandlerMapping` が全部拾う仕様となっています。
また、Mappingオブジェクトの順番を入れ替え `SimpleUrlHandlerMapping` を最初にすると、すべてのURLがマッチしてしまい、Controllerへマッピングされなくなります。

Spring Framework 4.0（Bootではない）では、static resourceへのマッピングは他のMappingオブジェクトが使用されていたので、下記のような方法が使用できたのです。


~~`Application` に以下のメソッドを追加すればOK。~~
詳しい説明はそのうち。
もっと簡単な方法を模索中。

```java
@Autowired
public void setApplicationContext(final ApplicationContext context) {
    final Object mapping = context.getBean("resourceHandlerMapping");
    if (mapping instanceof SimpleUrlHandlerMapping) {
        ((SimpleUrlHandlerMapping) mapping).setOrder(-1);
    }
}
```
UiPathStudioXって本当にフルレコーダーで作れるぞ

RPA業界にはこれ以上発展しそうにないという閉塞感が広がっている。
世間では、RPAを導入したが自動化が進まないし、プロセス制作にはシステム開発工数のような大規模な設計工程、開発工程が必要になっており、これでは費用対効果的にも新システムを開発するのと同じぐらいかかってしまうという声をたくさん聴くようになった。
当たり前である。RPAを推進してきた私から見ても難しすぎる。自動化できても安定しない。思ったように動かない。これではお勧めできない。
私も、もうRPAは無理だなと思っていた。そこに2020年12月になってStudioXが彗星のごとく現れた感じだ。

1、StudioXはフルレコーダー（アプリ/Webレコーダー、表抽出）で開始でき、覚えるべきアクティビティはExcelの操作だけで制作可能で、癖はあるが安定して動作する
2、Assistant機能を使うと、StudioXを起動しなくてもプロセスを実行できる。
3、StudioXでのフルレコーダーを使ったデモをライブでやっても失敗せず安定する。
4、こんなRPAは今まで出会ったことはない。覚えるべきTipsも少なくて済む。
5、しかもCommunity版は機能無制限で無料とか凄すぎる。※以下参考資料
https://www.uipath.com/ja/product/automation-cloud
・Studio、StudioXを2つまではEnterprise版でなくとも無料で個人、チーム、企業で利用が可能とされている。

StudioXPinPイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608295/8224b885-b63e-2e11-0681-450c72b66081.png)


ということでベンダーにとっては商売にはならないが、単純な大量業務を自動化するという本来のRPAの目的を達成するにはこれが最も理想のRPAと私は強く思う。５～６個の自動化ツールを使ったがどれもライブデモを用意しているうちにツール商品が廃止になったり、不安定になったり「RPAの理想」は全く達成されていなかった。
絶望感がRPA業界に漂いつつある中での唯一の希望的なリリースだったと思う。。。。UiPath社は今まで通りのスタイルだが。。。広告が下手な気がする。
この感動は文字では伝えられないので、gif動画で近日中に公開する。

RPAのロードマップでは、RPA化出来そうな業務を見つけてきて、自動化プロセスを自動で作り、自動で運用時間を設定して動くというようなのが出てくることになっているが、このうち、「RPA化出来そうな業務を見つけてきて、自動化プロセスを自動で作り」は近日中に出す準備ができているらしく、TaskCaptureという製品はさらに注目だ。こいつがあれば、まるで普通のシステム開発になっていたUiPathStudioでの開発が嘘みたいに簡単になる。ちょっと偏り過ぎてて、2021年時点では、まだスケルトンが出来るレベル。TaskCaptureが理想通りに開発されれば、自動でRPAプロセスが生成される仕組みになるようだ。

今後に期待したいが、その前にRPA市場がなくなってしまわないか心配なので、このStudioXは一度使ってみることをお勧めする。個人的には草の根活動的にでも、Studioでの開発に行き詰っている方々の救世主となることは間違いない。

これが無理なら業界内には簡単で安定するRPAは今のところ見当たらないので、RPAの次のロードマップが達成されるのを待つしかなくなる。なんとかこの感動を広く啓蒙したいものだ。

-------2021.10の更新情報---2021/10/26--------------------------------
更新された後のパワーアップされた機能などは、UiPath社からもたくさん出ているので是非ご確認頂くとして、かなり使いやすくなっている。

このレコーダーは以前から、例えばアプリケーションをレコーディングする場合、アプリケーションを起動してログイン画面で待機させ、StudioXを起動して、レコーディングを開始ボタンで、ログイン画面をキャプチャさせると、「アプリケーションを起動してログイン画面を表示する」部分を記録するので、他のRPAのレコーダー機能のように、ダブルクリックをするからレコーディングさせる必要がない。※特にNotesなど起動するアプリケーション名を間違える事があるので後から修正は必要。

しかも更新バージョンのレコーダー機能は、必ずアンカーを設定する方法に変わっており、完全なオブジェクト認識に近いので、都度アンカーを指定してチェックボタンを押す形となる。前のバージョンよりも一手間増えたが、より確実なレコーディングを行えるので作り直しの手間は減ると考えられる。※前のバージョンではアンカーがないとレコーダーが判断すると画像認識になっているようだった。

デフォルトで用意されていないアクティビティも「パッケージを管理」機能を使うことでほとんど補える。
TerminalやSOAP、REST APIを扱うアクティビティは「パッケージを管理」でダウンロード、インストールする事で利用可能である。※Terminalも最新バージョンはレコーディング機能ボタンが付いている。

ここを誤解されているのか、StudioXは出来る事が少ないと思っている方が多いのだと思うが、かなり完成度は高いシチズンデベロッパーツールと思う。

どうしてもStudioでしか使えない機能はStudioXで作ったプロセスは、Studioでも編集が可能であるから、難しい機能は、Studioで実装し、StudioXで動作させるのがお勧めである。※現在は上位互換はあるが下位互換はない。

-------2022.06の更新情報---2022/06/13--------------------------------
この件についても今年になって、Studioに最終的に統合し、UiはStudioXに近くなると窺える発表があった。
Excelの書き込みループ処理とWeb画面からの一覧抽出については、それぞれ、アクティビティを自作する必要があるが、Excelとの親和性が良いので、タイトル行や行認識を一瞬で行い、一覧作成は5分掛からない。
こうなるとレコーダーと合わせると無敵である。恐ろしいツールだStudioX！

私の今の導入すべきお勧めのRPAツールは個人でも法人でも、StudioXである。このツールは劇的に皆様の生産性を上げ、単純労働から解放してくれることであろう。

-------2022.08の更新情報---2022/08/11--------------------------------
難しかったCommunityEditionライセンスのアクティベーション手順をStudioX起動まで手順にまとめました。

https://qiita.com/jg1mnv/items/760ecb179b25a9d19265

RPAのPC占有問題を解決する方法を検証しました。この環境を使うとRPAと自分の業務両方出来ます。

https://qiita.com/jg1mnv/items/5b046c6cd1a90b5374ff
とりあえずDockerを動かすために必要なコマンド(初心者向き)

## この記事の目的
Dockerをターミナル上で動かすためだけに使ったコマンドについて記載。
## 環境
M1 Macを使用。
Dockerは[プレビュー版](https://www.docker.com/community/get-involved/developer-preview)を使用しました。

## 準備
[DockerHub](https://hub.docker.com/)のアカウント作成しておくこと。

## Dockerコマンド
- Docker login  
[DockerHub](https://hub.docker.com/)にログインするためのコマンド。  
事前にDockerHubにアカウント作成する必要あり。
- Docker pull  \<image>  
Docker Hubから指定したイメージのダウンロード
- Docker run \<image>  
指定した\<image>のDocker実行
- Docker images  
ダウンロードしたイメージの確認
- Docker ps  
アクティブなコンテナを表示。 "-a"オプションですべてのコンテナを表示。
Vue CLIプロジェクトをGitHub Pagesで公開する方法

GitHub Pagesは、[gh-pages](https://github.com/tschaub/gh-pages)を使うと自動で楽ですが、使わなくてもできます。

# GitHub Pagesを設定する

Githubで設定します。

``https://github.com/[アカウント名]/[リポジトリ名]/settings`` のGitHub Pagesにある設定を変えます。
``Danger Zone``の上辺りにあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11545/15e9aa62-a6c3-47dd-1191-bd064ec9721c.png)
``main``ブランチの``docs``を選択して、「Save」ボタンを押します。

# Vueプロジェクトのbuild先をdocsディレクトリにする

Vue CLIで作成したプロジェクトのルートに``vue.config.js``を作成して、以下のようにします。

```
module.exports = {
  outputDir: 'docs',
  publicPath: './'
}
```

# Vueプロジェクトをbuildしてリモートへpush

``vue.config.js``を保存したら、ローカルでbuildします。

```
$ npm run build
```

``build``ディレクトリにファイルが書き出されるので、ファイルをコミット＆mainブランチへpushします。

リモートリポジトリに反映されると、``https://[アカウント名].github.io/[リポジトリ名]/``で開けるようになります。
iOSのパーミッションテキストが日本語化されないとき

iOSアプリでLocalizeを使用して多言語化対応しており、iPhoneの使用言語を日本語にしているにもかかわらず、パーミッションのテキストが`Info.plist(English)`に設定しているものが使用されてしまう。

![スクリーンショット 2021-03-13 13.50.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658122/f1393c8f-89fc-540b-0925-5d98f52b8b52.png)

XcodeのLocalizationsで`Japanese(ja)`ではなく`Japanese(Japan)(ja-JP)`を使用するとパーミッションテキストが日本語になった。