OmniAICreator/Qiita-1.07M huggingface dataset:
Google Playのデータセーフティに対応する

# はじめに
こんにちは。運動通信社プロダクト開発一部・Android担当の小林です。
本日は、来年の4月から情報の提供が必須になる、
Google Playのデータセーフティに対応する方法を記載していきます。

# データセーフティ (データセーフティセクション) とは
データセーフティセクションとは、アプリ開発者が、ユーザーデータをどのように収集・共有するか、データのセキュリティやプライバシーをどのように扱うかをユーザーに明示する方法です。
2022/2/22からユーザーに表示されるようになり、2022/4/22には情報の提供が必須になります。
更に詳細な情報は以下のブログ・ヘルプを参照ください。

https://android-developers-jp.googleblog.com/2021/05/new-safety-section-in-google-play-will-give-transparency-into-how-apps-use-data.html

https://android-developers.googleblog.com/2021/10/launching-data-safety-in-play-console.html

# アプリのデータ使用情報を提供する
データセーフティセクションへ情報を提供する手順を以下に記載していきます。

## Play Consoleで情報を提供するアプリを選択する
今回、データセーフティの情報を提供したいアプリを選択する。
![全てのアプリアプリを表示.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123957/252e84c5-0be1-e3ee-a9a7-16553d001a16.png)

## アプリのコンテンツ
左側の項目一覧の[ポリシー] -> [アプリのコンテンツ] を選択する。
以下の画像の赤枠内の[開始]をクリックする。
![スクリーンショット 2021-11-10 133609赤枠.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123957/ec7550e0-8ac2-e5c9-cef5-c647916dc1a6.png)

## データセーフティ

### 概要
概要が表示されるので、内容を確認したら右下の[次へ]。
![データセーフティ概要.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123957/b611cf95-f8d4-4a7e-5b40-d382cda97a1b.png)

### データの収集とセキュリティ
データの収集とセキュリティでは必須項目にチェックする。チェックが終わったら右下の[次へ]。
![データセーフティデータの収集とセキュリティfilled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123957/4d851b29-0c5c-8057-dea8-87a06d620e46.png)
なお対象になるユーザーデータの詳細は以下になります。

https://support.google.com/googleplay/android-developer/answer/10787469?hl=ja#types&zippy=%2C%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E7%A8%AE%E9%A1%9E

### データの種類
![データセーフティデータの種類.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123957/4d705002-dde8-f165-c57e-0077def3c5ac.png)
アプリで使用しているデータの項目にチェックを入れます。終わったら右下の[次へ]。
![データセーフティデータの種類checked.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123957/aae93b10-ca37-e0de-6f40-6243d2a5fb53.png)

### データの使用と処理
選択したデータが項目に出てくるので、[開始]をクリックする。
![データセーフティデータの使用と処理赤枠.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123957/6fdb23b0-d652-25f6-f63b-415caae8b350.png)
データの設定に関するシートが表示されるので、適切に項目を埋める。
完了したら右下の[保存]。
![データセーフティデータの使用と処理 - 各項目filled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123957/7b46cfa3-1891-384e-9e0b-8bf97ca417f2.png)
各データの設定が完了したら右下の[次へ]。

### プレビュー
![データセーフティプレビュー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123957/773aa435-436a-94ad-87cd-bb021f3a086b.png)

このときにプライバシーポリシーの設定をしていないとエラーが表示されるので、
設定していないときは以下のように設定を行う。
1. 右下の[未公開版の保存]を押して現在の進捗状況を保存
2. [アプリのコンテンツ] -> [プライバシーポリシー]を選択
3. プライバシーポリシー情報のURLを設定

全ての項目が問題無く設定されていることを確認したら右下の[保存]。

## 確認
各項目の設定が完了した後、[アプリコンテンツ] -> [データセーフティ]をチェックする。
緑のチェックマークがついていたら完了。
![アプリのコンテンツデータセーフティ完了赤枠.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123957/0e72df0e-b8c8-45bd-6a8a-c752ac818846.png)

## Firebaseを使用しているプロジェクトについて
Firebaseを使用してデータを収集しているアプリに関しては以下のページが参考になります。

https://firebase.google.com/docs/android/play-data-disclosure?hl=ja

# まとめ
申告する必要があるデータの種類が多岐にわたるため、意外と時間がかかります。
特にユーザーデータの収集を重視するアプリでは、項目のチェックに苦労するかと思います。
直前になって急いで設定できるようなものではないので、
早めに調査・設定をしておいたほうが良いでしょう。
今回は以上になります。ここまで読んでいただいてありがとうございます。
勉強してきたことの概要

勉強してきたことのアウトプットです

## Amazon EC2
Amazonが提供している仮想サーバーの構築サービス。EC2を使うことでOSを乗せた仮想環境が素早く構築できる。また、作成後のマシンスペック変更や削除が簡単にできる。例えばCPUメモリが不足した場合はインスタンスタイプを変更することで増強が可能で、データ容量が多くなってディスク容量が不足した場合は、拡張が可能。
EC2はインスタンスという単位でサーバー環境が構築できる。インスタンスは簡単に言えばOSを乗せた仮想サーバーのこと。

##nginx
Webアプリケーションと連携するために利用されるWebサーバ。
速くて高負荷に強く、機能の取り外しができるため柔軟にカスタマイズが可能。

##Capistrano
自動デプロイツール。Railsアプリをデプロイするときは、EC2インスタンスに接続したり、EC2インスタンスをpullしたり、Unicornを再起動したりするが、これをローカルでたったひとつのコマンドで実行してくれるのが自動デプロイツール。

##CircleCI
Saas型のCI/CDサービス。
CIとは継続的インティグレーションの略。テストや静的コード解析などの作業を自動化して、継続的に実行する方法。
CDとは継続的デリバリーの略。各環境へのデプロイ作業を自動化して継続的に実行する方法。
Saasとは、サーバー側で稼働するサービスをインターネットなどに経由させて、クライアント側は必要な機能を必要な分だけ利用できる提供形態のこと。

##Docker
開発環境や実行環境をチームで同じものを使うために使うアプリ。
例えばAさんとBさんがチームを組んでアプリを作っている場合、AさんとBさんの開発環境は全く同じである必要があり、更にテスト環境、本番環境も同じである必要がある。
環境を全て同じにするのは難しいがDockerがそれを簡単にしてくれるみたいです。
コンテナという技術を使って、コンテナの中で環境構築をしたり、コードを実行したり開発をしたりする。
AさんとBさんが同じコンテナを使っていれば同じ環境で開発をしていることになる。

##Amazon Route 53
AWSクラウド内で使用するドメインを一元管理するためのサービス。
新しいドメインの購入や所有ドメインの維持管理、DNSサーバーのレコード登録管理などができる。

# JavaとRubyの比較
####共通点
・共にオブジェクト指向言語であるためクラスの定義や継承などの概念は同じ

####相違点
・Rubyは動的型付け言語に対してJavaは静的型付け言語である
　変数や関数の引数などを設定する時、Rubyは型宣言が必要ないがJavaは必要

**静的型付け言語：**プログラマが予め変数や関数の引数などのデータをどう扱うか、つまり「型」を決めて使うこと。

**動的型付け言語：**プログラマが書いたコードをコンパイラやインタプリンタが実行して解釈し、型を想定して扱うこと。

## Vue.js
wubアプリケーションにおけるユーザーインターフェイスを構築するための、オープンソースのJavaScriptのフレームワーク。

# UI/UX
**UI**とはユーザーインターフェースの略で、ユーザーとサービスの接触面、簡単に言えば見た目を表すもの。
サービスのデザインなどユーザーの視覚に触れる情報がUIとみなされる。

**UX**とはユーザーエクスペリエンスの略で、ユーザーがサービスを利用した得られる体験のこと。
通販サービスで例えるなら、デザインが整っていて商品が見やすい、この商品を買ってみたいなどユーザーがサービスを利用して感じたことがUXとなる。

# MVCモデル
プログラムの処理を役割毎に分けて開発をするやり方。Webシステム開発で頻繁に用いられる。

###Model
MはModel(モデル)のこと。
システムとしての実際の処理(ビジネスロジック)を担当する部分。
データの作成・更新・削除をしたり、DBからデータを取得してコントローラーへ渡す。

###View
VはView(ビュー)のこと。ユーザーが実際に見る画面である。ユーザーからのリクエストをコントローラーに送ったり、コントローラーから受け取った処理を画面に表示させたりする。

###Controller
CはController(コントローラー)のこと。ViewとModelを操作する部分であり、ViewとModelの間にあるイメージである。Viewからリクエストを受け取り、Modelへ処理の命令を出す。Modelから処理の結果を受け取り、Viewへレスポンスを返す。

###gem
Rubyで使うことのできる汎用性の高い機能をひとまとまりにしたライブラリを管理するシステムのこと。
または、それぞれのライブラリのことをgemという。

###ActiveRecord
RubyでDBの操作を一部でき流ようにするもの。
基本的にSQLを用いないとDBを操作できない。
しかしモデルに適用されているActiveRecordを用いれば、Rubyを用いてデータを探したり、取得できたりする。
Couchbase Lite 機能解説：インデックス作成

Couchbase Liteの機能全般について、以下の記事も合わせてご参照ください。

https://qiita.com/yoshiyuki_kono/items/6a5bbad1b02196a25417


## 概要

インデックスを作成すると、クエリのパフォーマンスを高速化できます。クエリは、インデックスを利用して、ドキュメントのセットを絞り込むことができれば、より迅速に結果を返すことができます。



## 新しいインデックスの作成

次のデータモデルに含まれる`type`、`name`プロパティを指定して新しいインデックスを作成します。

データモデル

```JSON
{
    "_id": "hotel123",
    "type": "hotel", 
    "name": "Apple Droid"
}
```

インデックスを作成するコードは次のようになります。

##### Android

```JAVA
database.createIndex(
    "TypeNameIndex",
    IndexBuilder.valueIndex(
        ValueIndexItem.property("type"),
        ValueIndexItem.property("name")));
```

##### Swift

```swift
let index = IndexBuilder.valueIndex(items:
    ValueIndexItem.expression(Expression.property("type")),
    ValueIndexItem.expression(Expression.property("name")))
try database.createIndex(index, withName: "TypeNameIndex")
```

## その他のメソッド

com.couchbase.lite.Databaseクラスには、下記の様なインデックス関連のメソッドがあります。

- void createIndex(String name, Index index)
- void deleteIndex(String name)
- List<String> getIndexes()

## 留意点

インデックスを計画するときは、インデックスによってクエリが高速化される一方で、次のことも行われる可能性があることに注意する必要があります。

- ドキュメントが更新されるたびに各インデックスを更新する必要があるため、書き込みを少し遅くします

- Couchbase Liteデータベースを少し大きくします。

- インデックスが多すぎると、パフォーマンスが低下する可能性があります。最適なパフォーマンスは、クエリに合わせて適切なインデックスを設計および作成するかどうかに依存します。



## 関連情報

https://docs.couchbase.com/couchbase-lite/3.0/android/indexing.html
Let's EncryptでSSL証明書をインストール

## 環境
CentOS7
Nginx
対象ドメイン xxx.com

## certbotのインストール
```
# yum -y install certbot python2-certbot-nginx
```


## 証明書の作成
```
# certbot certonly --webroot -w /var/www/html/xxx.com -d xxx.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel):      intra@xxx.com
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N
Account registered.
Requesting a certificate for xxx.com
Performing the following challenges:
http-01 challenge for xxx.com
Using the webroot path /var/www/html/xxx.com for all unmatched domains.
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/xxx.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/xxx.com/privkey.pem
   Your certificate will expire on 2022-02-08. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again. To non-interactively renew *all* of your
   certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
```

## 証明書が作られているのを確認
```
# ls -la /etc/letsencrypt/live/xxx.com/
```

あとはNginxのconfに
ssl_certificate         /etc/letsencrypt/live/xxx.com/fullchain.pem;
ssl_certificate_key     /etc/letsencrypt/live/xxx.com/privkey.pem;
を埋め込んで再起動
Windows11の右クリックメニューを以前の仕様に戻す設定



レジストリ値
コンピューター\HKEY_CURRENT_USER\SOFTWARE\CLASSES\CLSID\
へ
{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}"という名称のキーを作成する。
さらに、上記キーの中に
InprocServer32"という名称のキーを作成する。

InprocServer32"キーにある（規定）という名称の値のデータを空白に設定する。

パソコンを再起動する。
PythonでGCSオブジェクトを制御する権限

#はじめに
PythonでGCSバケット内のオブジェクトを操作したい場合の権限について、**単純にIAMで指定するGCSオブジェクトオーナー権限だけ**ではPermissionエラーでしたのでメモしておきます。

#エラー内容
対象のサービスアカウントに"Storage オブジェクト管理者"や"Storage オブジェクト作成者"、"Storage オブジェクト閲覧者"の権限を付けてPythonを実行しても以下のエラーが出ます。

```shell
google.api_core.exceptions.Forbidden: 403 GET https://storage.googleapis.com/storage/v1/b/[バケット名]?projection=noAcl&prettyPrint=false: [サービスアカウント] does not have storage.buckets.get access to the Google Cloud Storage bucket.
```

pythonコードについては、こちらがよく書かれていますのでご参考下さい。
[pythonによるGCSへのバケット・ファイルの操作（転送・取得・削除・読み込み等）まとめ](https://qiita.com/kenkanayama/items/1050e8a10f23d5efbbd8)
サービスアカウントのjson　keyをダウンロードしてご利用ください。


#対策方法
"**Storage レガシー オブジェクト オーナー**"が必要です。
"Storage レガシー オブジェクト オーナー"に対象のサービスアカウントを追加してください。
**こちらはIAM画面では設定できず、GCSバケット詳細のロールで設定が可能**です。
![bucket_role.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668866/ea556429-d130-bc24-493b-94488265dc0d.png)

#さいごに
よく調べてないのですが、公式ドキュメントあるのでしょうか。
まぁ、動いたから良しとします。
(コンソール画面で操作してしまいました。これからTerraformに落とします:stuck_out_tongue_closed_eyes:)
2021.11.10現在 → nRF9160 で SPI 通信する(Ethernet Sheild を利用する, W5500 & SDCard )

# はじめに

ncs v1.6.1環境にて nRF9160DKやnRF9160 feather等で Ethernet Sheild（W5500＆SDカードの SPI モジュール）を利用する方法についての覚書。

Zephyrのライブラリはとっつきにくいのでかなりハマる。

今回の記事での実装方法は、動作はするが正解ではないと思われる。

正解を知りたいが情報が少ない。


# 配線について

できれば直結、もしくはできるだけシンプルに短い配線を心がけないと、
まともな波形は出なかった。

# ライブラリなど
W5500は、Zephyrのドライバを使用せず、wiznet提供のライブラリを無理やり移植。
https://github.com/Wiznet/ioLibrary_Driver

SDカードは、Zephyrのライブラリを利用することで、
とりあえず動作するようになった。

一番の問題は SPI の操作。

普通（？）のやり方で実装しても全く動作しなかった。
NRFX_SPIMライブラリを利用するやり方を試したらなぜか動作した。

``` prj.conf（抜粋）
CONFIG_SPI=n
CONFIG_NRFX_SPIM=y
CONFIG_NRFX_SPIM2=y
CONFIG_NRFX_SPIM3=y

CONFIG_DISK_ACCESS=y
CONFIG_DISK_DRIVER_SDMMC=y
CONFIG_SDMMC_OVER_SPI=y
CONFIG_FILE_SYSTEM=y
CONFIG_FAT_FILESYSTEM_ELM=y

```

SPI2 を SD カード用、 SPI3 を W5500 用に利用。

割り込みがUARTやI2Cとコンフリクトするので、無効化する必要がある。


追記：overlay ファイルにて、 spim3 の
``` compatible = "nordic,nrf-spim";```
を
``` compatible = "wiznet,w5500";```
に変更したら、下記の症状はなくなり、
irq_connect_dynamicを利用したり、nrfx_spimライブラリの修正する必要はなくなった。

<del>
CONFIG_DYNAMIC_INTERRUPTSを利用しているのは、
SDカードのライブラリが、SPI2とSPI3の両方を初期化してしまうから。
（SPI3用にIRQ_CONNECTを定義するとコンパイルに失敗する）
実行時に明確にirq_connect_dynamicにて初期化するようにしたら動作した。
</del>

<del>
↓↓↓↓↓追記：こちらの修正も必要
</del>

https://qiita.com/KiKUiCHi_R1R/items/c131c1bc17239dbb3a48

<del>
↑↑↑↑↑追記：こちらの修正も必要
</del>






```circuitdojo_feather_nrf9160ns.overlay
// SEGGER Embedded Studio auto generated
&uart1 {
        status = "disabled";
 };
&gpio0 {
	status = "okay";
};
&gpiote {
	status = "okay";
};
&i2c2 {
	status = "disabled";
};
&spi1 {
	status = "disabled";
};
&spi2 {
	compatible = "nordic,nrf-spim";
	status = "okay";
	mosi-pin = <21>;
	miso-pin = <22>;
	sck-pin = <19>;
	cs-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; /* SDHC */
	sdhc0: sdhc@0 {
		compatible = "zephyr,mmc-spi-slot";
		reg = <0>;
		status = "okay";
		label = "SDHC0";
		//spi-max-frequency = <24000000>;
		spi-max-frequency = <8000000>;
	};
};
&spi3 {
//	compatible = "nordic,nrf-spim";
	compatible = "wiznet,w5500";
	interrupts = < 0xb 0x1 >;
	status = "okay";
	mosi-pin = <21>;
	miso-pin = <22>;
	sck-pin = <19>;
	cs-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; /* W5500 */
};
```

featherのピン配置は、以下のように設定
　COPI(MOSI)ピンは 21 ピン
　CIPO(MISO)ピンは 22 ピン 
　SCKピンは、19ピン
　W5500 の CSピン は 4ピン（基板上の 8ピン）
　SDCard の CSピン は 3ピン（基板上の 7ピン）
         
Ethernet Sheild の W5500 と SDCard の MOSI,MISO,SCK は共通なので、こんな感じにしてみた。

# その他の注意点

W5500（SPI3）と SD（SPI2）の切り替え時には

　NRF_SPIM3->ENABLE = 0; //もしくは NRF_SPIM2->ENABLE = 0;

のように利用しない方のSPIを無効化する必要があった。
有効化は 0 の代わりに 7 を代入すればよい。

これも正しい方法がわからないので、とりあえず動作したレベルの話。


# NORDIC nRF9160DK

nRF9160DKは、Ethernet Sheild の直挿しで動作した。

事前に、nRF9160DK 上の nRF52840 に、ピンの配線を切り替えるプログラムを書き込んでおかないと、ちゃんと動作しないので注意。

nRF9160DK のボード配線のコントロールは nRF52840 側で設定する必要がある。
デフォルトだとLEDやスイッチにつながっている。
UARTもVCOM(USB上の仮想ポート)に接続しているので、ピンに配線しても何も出力されないし入力もされない。


# さいごに

nRF9160 は LTE 通信を手軽に利用できるメリットが大変素晴らしい。
しかし開発環境が難解かつライブラリの仕様がコロコロ変わるのが惜しいところ。

ただし、当面は付き合わないといけないチップなので、頑張るしかない。

* * *
以上、ご参考まで。

P.S. ソースを公開できなくて申し訳ないです
* * *
GNOME41.1 (AlterLinux based on ArchLinux from Japan)

今日のパッケージのアップデートで、GNOME41.1に更新されました。

https://foundation.gnome.org/2021/09/22/gnome-41-release/

Archベースのインストールが簡単なディストリビューションで、Manjaroも良かったですが、日本発のディストリビューションで日本語入力もデフォルトで設定されているし、32ビット（LXDE,xfce）にも対応しているので、Alterlinuxは、古いPCにも良いかもしれません。
GNOME41.1が思ったよりも早く導入できたので、ちょっと嬉しいです。

Alterで個人的に設定を変えたのは、
カーネルを独自にビルドしなおしたこと。
mkinitcpioでcompressをlz4にしたこと。
makepkgでccacheを有効にすること。くらいでした。
それ以外は、インストールされた環境で、そのまま利用しています。

https://alter.fascode.net

GNOMEの最新版を使いたいなら、ぜひ試してみてください。

- カーネルビルド時の留意点（make localmodconfig）

カーネルビルドで必要なモジュールのみビルドしてサイズを減らす場合、make localmodconfigを用いますが、その場合にはUSBディスクなどの外部ストレージも装着しておいて、動的に読み込まれるモジュールも読み込んだ上でビルドしましょう。
単純にlsmodでリストを作ると、外部ストレージなど動的に読み込まれるものが含まれない可能性もあります。localmodconfigを使う場合にはその点に留意しましょう。特にファイルシステムのモジュールに留意するほうがいいです。CDROMやDVDも読み込ませてからのほうがいいかもしれません。

例
usbディスクにchromeosをインストールしていて、ext4が必要だとします。
Linuxではbtrfsを利用している。
この場合、カーネルでファイルシステムのext4がモジュールとして読み込まれる設定になっている場合、USBディスクを繋がないで、lsmodすると、ext4モジュールが読み込まれていない場合もありえます。
デュアルブート構成でWindowsパーティションを読み込みたい場合などにも、当てはまります。
カーネルのサイズや、モジュールが減って、ファイルサイズや起動時間短縮に貢献するかもしれませんし、カーネルのビルド時間短縮にもなるかと思いますが、ハードウェア構成が固定化していて、はっきりしている場合のみでいい気もします。
特に自分にとって必須なファイルシステムについては、カーネルビルド時にモジュールではなく、カーネルに埋め込んだ形でオプションを設定するのもありかと思います。
make localmodconfig を使うときには、少し留意が必要そうです。

```diff
diff --git a/repos/core-x86_64/PKGBUILD b/repos/core-x86_64/PKGBUILD
index 16ff3af..1aa6dfe 100644
--- a/repos/core-x86_64/PKGBUILD
+++ b/repos/core-x86_64/PKGBUILD
@@ -1,6 +1,6 @@
 # Maintainer: Jan Alexander Steffens (heftig) <heftig@archlinux.org>
 
-pkgbase=linux
+pkgbase=linux-custom
 pkgver=5.14.16.arch1
 pkgrel=1
 pkgdesc='Linux'
@@ -16,7 +16,7 @@ makedepends=(
 options=('!strip')
 _srcname=archlinux-linux
 source=(
-  "$_srcname::git+https://github.com/archlinux/linux?signed#tag=$_srctag"
+  "$_srcname.tar.gz::https://github.com/archlinux/linux/archive/refs/tags/$_srctag.tar.gz"
   config         # the main kernel config file
 )
 validpgpkeys=(
@@ -33,6 +33,7 @@ export KBUILD_BUILD_USER=$pkgbase
 export KBUILD_BUILD_TIMESTAMP="$(date -Ru${SOURCE_DATE_EPOCH:+d @$SOURCE_DATE_EPOCH})"
 
 prepare() {
+  mv linux-${pkgver%.*}-${pkgver##*.} $_srcname
   cd $_srcname
 
   echo "Setting version..."
@@ -54,6 +55,9 @@ prepare() {
   make olddefconfig
   diff -u ../config .config || :
 
+  #lsmod > `pwd`/lsmod.txt && make LSMOD=`pwd`/lsmod.txt localmodconfig
+
+  make menuconfig
   make -s kernelrelease > version
   echo "Prepared $pkgbase version $(<version)"
 }
@@ -192,7 +196,7 @@ _package-docs() {
   ln -sr "$builddir/Documentation" "$pkgdir/usr/share/doc/$pkgbase"
 }
 
-pkgname=("$pkgbase" "$pkgbase-headers" "$pkgbase-docs")
+pkgname=("$pkgbase" "$pkgbase-headers")
 for _p in "${pkgname[@]}"; do
   eval "package_$_p() {
     $(declare -f "_package${_p#$pkgbase}")
```
[React] ResizeObserver APIを使ってリサイズする

##とりあえず便利
便利なので是非とも使用してみてください。
使用方法は以下にコードを入れましたのでこのまま使ってもらっても良いですし、独自に実装されても良いかと思います。ご自由にどうぞ。

###高さを調節するのに僕は使用しました。
以前まではresizeを使用しておりました。
もうそろそろ、やり方を変えてスマートな方法を採用したいと考えており調査しているとResizeObserverに出会いました。以前から知ってはいたのですがその時はまだ使用できる状況になかったのですが、今は整っている状況でもあったので採用しました。

コード自体のスッキリしているようですし、今度からResizeObserverを採用していこうと思います。

```react
  import React, { useRef } from 'react'

  const useRef = useRef(null) // 変数名はユニークな名前に変えましょー

  useEffect(() => {
      const H = Headerの高さ
      useRef.current.style.height = window.innerHeight - H + 'px' // 念の為初めに付与させる

      const resizeObserver = new ResizeObserver(() => {
        if (useRef.current) {
          useRef.current.style.height = // リサイズされた時に付与し直す
            window.innerHeight - H + 'px'
        }
      })

      useRef.current && resizeObserver.observe(document.body)

      return (): void => {
        resizeObserver.disconnect()
      }
  }, [])

```

型を利用される場合、以下を実行ください。

```shell

% npm install --save-dev @types/resize-observer-browser

```

よかったら、ぜひ使ってみてください。
PHPでMySQL(データベース)の情報をWebページに表示させたい

# 前提条件
MySQLのデータベース、テーブルをあらかじめ用意しておく
PHPMyadminが開ける

参考：[PHP maniual 接続、および接続の管理 ](https://www.php.net/manual/ja/pdo.connections.php)

# 出力させたいWebページに書く内容
## データベースに接続する
接続するためにPDOというクラスがPHPに用意されているので、インスタンス化して接続に必要な情報を引数に渡す。

```php
<?php
  $pdo = new PDO("mysql:host=接続先のサーバのアドレス;dbname=データベース名;charset=utf8", "ユーザ名", "パスワード");
?>
```

デフォだとユーザ名は`root`, パスワードは`""`と空でも繋がる。

## データベースからデータを取得する
データを取得するためのSQL文を変数sqlにセット。
さっき作ったインスタンスが入っているpdoに、SQL文を渡す。
最後にexecute()で、変数stmtを実行。

```php
<?php
    $sql = "SELECT * FROM テーブル名 ORDER BY update_at";
    $stmt = $pdo->prepare($sql);
    $stmt -> execute();
?>
```

## print_rで取得したデータを表示してみる

変数rowにfetchで1行ずつデータを取り出して入れておく。
PDO::FETCH_ASSOCをfetchの引数にすると、カラム名を添字にした配列にすることができる。
print_rで配列を出力して改行している。
…というのを、while文であるだけぐるぐる出力している。

```php
<?php
     while ($row = $stmt -> fetch(PDO::FETCH_ASSOC )) {
        print_r($row);
        echo("<br/>");
    }
?>
```

## 連想配列を使って、欲しいとこにデータを埋め込んでいく
さっきはprint_rで一気にキーと値が表示されていたので、これを連想配列の書き方を使って必要なとこに必要な情報を埋め込んでいく。
例えばこんな感じ。

```php
<table>
 <tr>
  <th>id:<?php $row[id]; ?></th>
  <th>投稿内容: <?php $row[content]; ?></th>
 </tr>
</table>
```
UIAlertControllerがcrashしたときの対応

## crash report
```
thunk for @escaping @callee_guaranteed (@guaranteed UIAlertAction) -> () + 4344281276
```

## 対応方法
### UIAlertControllerをmain threadに行う
```
DispatchQueue.main.async { [weak self] in
  guard let strongSelf = self else { return }
  strongSelf.present(alertController, animated: true, completion: nil)
}
```
CodeBuild上のDockerイメージにメタデータから取得したAWS認証情報を渡す方法

CodeBuild上でビルドしたDockerコンテナからAWSの認証情報が上手く使えないみたいなので調べてみました。


そもそも `http://169.254.169.254` が使えなくて、参考URLにあるように `http://169.254.170.2` から取得します。更に `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` の環境変数を組み合わせると認証情報が取得できます。

```sh
$ curl http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
{
    "AccessKeyId": "ACCESS_KEY_ID",
    "Expiration": "EXPIRATION_DATE",
    "RoleArn": "TASK_ROLE_ARN",
    "SecretAccessKey": "SECRET_ACCESS_KEY",
    "Token": "SECURITY_TOKEN_STRING"
}
```

ちなみに `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` の変数には以下のような値が入っています。

```sh
$ echo $AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
/v2/credentials/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx
```

上記踏まえた上で認証情報をDockerコンテナにAWSの認証情報渡す `buildspec.yml` の例です。


```yaml
version: 0.2

phases:
  build:
    commands:
# 省略----------------------------
      - export NO_PROXY=169.254.170.2 # Proxyがある場合
      - AWS_CRED=`curl http://169.254.170.2${AWS_CONTAINER_CREDENTIALS_RELATIVE_URI}`
      - AWS_ACCESS_KEY_ID=`echo ${AWS_CRED} | jq -r .AccessKeyId`
      - AWS_SECRET_ACCESS_KEY=`echo ${AWS_CRED} | jq -r .SecretAccessKey`
      - AWS_SESSION_TOKEN=`echo ${AWS_CRED} | jq -r .Token`
      - |
        docker run \
        -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
        -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
        -e AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN} \
        ${IMAGE_NAME} ${COMMAND}
```

# 参考URL

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task-metadata-endpoint-v2.html

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task-iam-roles.html
Vonage Voice APIで Speech Recognition - 3つの改善ポイント

[自動音声認識（ASR）](https://developer.nexmo.com/voice/voice-api/guides/asr)の利用により、アプリはIVRを含め様々な音声ボット/アシスタントのユースケースにおける音声入力サポートを可能にしました。この機能により今までのDTMFによるレガシーの数字入力アクションに留まらず、ユーザーからの音声を文字に起こし、その音声インプットに対して設定したビジネスロジックに従いコールフローを実行する事が可能になります。コールフローについては、以下を参照下さい。

![スクリーンショット 0003-11-09 12.18.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1880931/0a096ec0-f996-adb6-fa15-ce64a6b74d1f.png)

今回の記事では、VonageのVoice APIにおいて開発者の方々から多くの要望が上がっていた音声認識（ASR＝Automated speech recognition）が一般提供＝GAされるにあたり、ベータ段階で開発者の方々から頂いた貴重なフィードバックを反映した3つの改善ポイントをご紹介します。

Call IDを新しい仕様ではオプション化
---------------------------------------
DTMF入力とは異なり、コール（レッグとも呼ばれます）IDについては、ASRでは必須パラメーターでした。 [NCCO](https://qiita.com/Noboru_Goto/items/718b9fae1201f1ca325d)をその場で動的に構築する必要性について、開発者の方からのご指摘が上がり以下のように改善しました。

現在の仕様ではuuidパラメータはオプションであり、コールの最初のレッグがデフォルトとして使用されます。これは、エンドユーザーが問い合わせを行い、IVRや音声ボットなどのASRの機能を活用する一般的なユースケースになります。これら一般的なユースケースでは通常PSTNからアプリケーションへのインバウンド、またはアプリケーションからPSTN電話番号へのアウトバウンドのいずれかを前提としており、これらのユースケースでは単一のレッグとなりデフォルトになります。

単一のレッグではないユースケースでは、レッグを明示的に指定する事でより複雑なシナリオの実現も可能です。これは複数の人が会話をしている様なユースケースで、特定のコール＝レッグを指定してASRで処理する等が考えられます。

パラメータとしての入力タイプ
---------------------------------------
以前の仕様では:
* DTMFトーンのみ
* 音声のみ
* その両方を受け入れる
入力アクションを構成するケースではカスタム設定を設定したくない場合でも、それぞれDTMFおよび/または音声オブジェクトを定義する必要がありました。したがって、デフォルトのケースでは、入力アクションを次のように設定する必要がありました。

```
[
  {
      "action": "input",
      "dtmf": { 
      },
      "speech": {
          "uuid": "0a41d330-853b-4294-8cbb-69e8e65dc9d4"
      }
  }
]
```

今回の改善では、typeと呼ばれる新しいパラメーターを導入しました。これにより、必要な入力アクションのタイプを明示的に設定可能です。両方の場合は、`["dtmf"]、["speech"]`または`["dtmf"、 "speech"]`で設定可能になりました。音声のuuidがオプションになったことを踏まえ、アクティブ化されたDTMFとASRの両方をNCCOオブジェクトでは以下のように簡潔にする改善を行いました。

```
[
  {
      "action": "input",
      "type": [ "dtmf", "speech" ]
  }
]
```

以前と同様に、dtmf / speechオブジェクトを使用してカスタムDTMF / ASRパラメータを設定できます。下位互換性を維持する為に、デフォルトのDTMF入力シナリオは引き続きサポートします。


In-APP SDKでのフルサポート
---------------------------------------
利用可能なすべての[サーバーSDK](https://developer.nexmo.com/tools)がASRをサポートするよう改善しました。

これらの改善により、DTMF IVRを自然な音声音声アシスタントに変換したり、最初から作成したりする事が非常に簡単になりました。


VonageのAPIプラットフォームは開発者の方からの声を重要視しており、ベータ版からGA＝General availabilityになっても改善は継続します。多くの開発者の方からのフィードバックをお待ちしております！

今回の記事について不明な点や導入にサポートが必要でしたら、是非弊社まで遠慮なくご連絡下さい！

関連記事
---------------------------------------
* [ASR guide](https://developer.nexmo.com/voice/voice-api/guides/asr)
* [NCCO reference](https://developer.nexmo.com/voice/voice-api/ncco-reference#input)
* [Voice bot tutorial](https://developer.nexmo.com/use-cases/asr-use-case-voice-bot)

参照記事
---------------------------------------
https://learn.vonage.com/blog/2020/11/20/voice-api-speech-recognition-now-in-general-availability/

連絡先
---------------------------------------
Vonage Japan合同会社
Mail: sales-japan@vonage.com
URL: https://www.vonagebusiness.jp/communications-apis/
M1MacでHasuraを使おう

# Hasura公式のイメージはAppleSilliconに非対応(2021/11/10現在)

こちらのイメージを使ってM1で動くHasuraのdocker-composeを作成しました

https://hub.docker.com/r/fedormelexin/graphql-engine-arm64

```yaml:docker-compose
version: '3.6'
services:
  postgres:
    image: postgres:12
    restart: always
    volumes:
    - db_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: postgrespassword
  graphql-engine:
    image: fedormelexin/graphql-engine-arm64:v1.3.3.cli-migrations-v2
    ports:
    - "8080:8080"
    depends_on:
    - "postgres"
    restart: always
    environment:
      HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/postgres
      HASURA_GRAPHQL_ENABLE_CONSOLE: "true" 
      HASURA_GRAPHQL_ADMIN_SECRET: myadminsecretkey
volumes:
  db_data:
【Ruby】Ruby 3.1.0 Preview版が確認できる環境を構築してみた(ソースからのビルド)

## はじめに

11/9にRuby 3.1.0 Preview版がリリースされました！

https://www.ruby-lang.org/en/news/2021/11/09/ruby-3-1-0-preview1-released/

早速使ってみたかったので、ruby-3-1-0-preview1が動作できる環境を作ってみました。
(10分くらいでできます。)
rbenvに対象のバージョンがなさそうだったので、ソースからビルドする方法で行いました。

```sh
rbenv install --list-all | grep 3.1.0
# 3.1.0-dev
# ruby-3-1-0-preview1がない
```

## 動作環境

Mac OS Big Sur 11.2.1（20D74）
gcc version 4.9.4 (Homebrew GCC 4.9.4)

## 環境構築

※こちらのコードをcloneすればスムーズにできますので、参考にしてください

https://github.com/adebadayo/ruby-3.1.0-preview1


まず、ビルド後のファイルを格納するディレクトリを作ります。

```sh
mkdir installed_files
```

Ruby 3.1.0 Preview版のソースコードをダウンロードして解凍します。
解凍後、`ruby-3.1.0-preview1`ディレクトリが作成されます。

```sh
wget https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.0-preview1.tar.gz
tar -zxvf ruby-3.1.0-preview1.tar.gz # untar
```

現状のディレクトリ構造は以下のようになります。

```sh
.
├── installed_files
├── ruby-3.1.0-preview1
└── ruby-3.1.0-preview1.tar.gz
```


次にソースからビルドをします。(参照　[Rubyのインストール](https://www.ruby-lang.org/ja/documentation/installation/))
解凍後の作成される`ruby-3.1.0-preview1`ディレクトリに移動して以下を実行します。


```sh
# 解凍後のディレクトリに移動
cd ruby-3.1.0-preview1 

# ビルド後に生成されるファイルをinstalled_filesディレクトリに保存する設定
./configure --prefix="`pwd | xargs dirname`/installed_files" 

# ビルド
make
sudo make install
```

`installed_files`ディレクトリにファイルが生成されていれば、ビルド完了です。
以下のディレクトリ構成になります。

```sh
.
├── installed_files
│   ├── bin
│   ├── include
│   ├── lib
│   └── share
├── ruby-3.1.0-preview1
└── ruby-3.1.0-preview1.tar.gz
```

## Rubyの実行


実行用のスクリプト`main.rb`を作ります。

```sh
cd ../ #　解凍後の`ruby-3.1.0-preview1`フォルダから一つ上に戻る
touch main.rb
```

以下のコードをmain.rbに書きます。
ちなみに内容は新しく機能追加されたHashのシンタックスシュガー`{ a: } `の実行例です。


```ruby:main.rb
puts "hello ruby 3.1.0 !"

puts ""

puts <<'TEXT'
・Values in Hash literals and keyword arguments can be omitted. [Feature #14579]
TEXT

a = 'hoge'

h = { a: a }
puts <<"TEXT"
      normal syntax : { a : a } => #{h}
TEXT

h = { a: }
puts <<"TEXT"
      syntax sugar : { a: } => #{h}
TEXT
```

ビルド後の生成されたrubyのbinを指定して、3.1.0 Preview版を実行します

```sh
installed_files/bin/ruby main.rb 
```


以下の出力がされればOKです。


```sh
hello ruby 3.1.0 !

・Values in Hash literals and keyword arguments can be omitted. [Feature #14579]
      normal syntax : { a : a } => {:a=>"hoge"}
      syntax sugar : { a: } => {:a=>"hoge"}

```


main.rbを変更すれば、他の機能を試せると思います。


## 最後に

何か不足な情報があればご教示いただければ幸いです。
Codespacesで他のリポジトリにpushする

[Codespacesの設定ページ](https://github.com/settings/codespaces) の、 "Access and security" セクションで、 "All repositories" や "Selected repositories" を選択すれば、Codespaceを作成したリポジトリ以外へも書き込みできます。

以下の記述は古いですが、Codespaces内でtokenがどう利用されているのかを解説しているので消さずに残しています。

---

Codespacesは、デフォルトではCodespaceを作成したリポジトリにしか書き込みできません。なので、次のようなシナリオで push が失敗してしまいます。

* GitHubで他人のリポジトリにプルリクエストを作ろうとして、forkを作らずに直接Codespacesを作ってしまい、後から fork を作って `git remote add` した
* submoduleを使っているプロジェクトで、Codespacesは親プロジェクトで作成したけどsubmodule側にpushしたい

これは、Codespacesが、作成したリポジトリに対するアクセス権だけを持ったPersonal Access Tokenを払い出しているからです。次の箇所で設定されています。

```ini:/usr/local/etc/gitconfig
[credential]
        helper = /.codespaces/bin/gitcredential_github.sh
```

```sh:/.codespaces/bin/gitcredential_github.sh 
#!/bin/sh
echo protocol=https
echo host=github.com
echo path=
echo username=PersonalAccessToken
echo password=$GITHUB_TOKEN
```

なので、他のリポジトリに対しても書き込み権をもった Personal Access Token を払い出して、 `GITHUB_TOKEN` という環境変数を上書きしてやると、他のリポジトリにも書き込みができます。

新たなPersonal Access Tokenを払い出す方法は [ドキュメント](https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) を参照してください。
また、例えば `gh` という GitHub 公式CLIを使っているのであれば、 ` ~/.config/gh/hosts.yml` から token をコピペできます。（使い回しは推奨しませんが）

注意点として、このtokenはhttpsでしか使えません。forkなどを `git remote add` や `git remote set-url` するときは、 ssh ではなくて https の方の URL を指定する必要があります。
SwiftPlaygroundでXCTestCaseのユニットテストを試す


# やりたいこと
Playgroundでテストを試してみたい

# 事前準備

以下の関数をテストします

0 -> "Taylor"
1 -> "Swift"
other -> "Unknown"

になる関数

```swift
struct TestableStruct {
    static func getName(id: Int) -> String {
        switch id {
        case 0:
            return "Taylor"
        case 1:
            return "Swift"
        default:
            return "Unknown"
        }
    }
}
```

# テストする方法

テストクラスを書いて、`NameTestCase.defaultTestSuite.run()`を書くと、テストが実行されます。


## テストクラス

```swift 
class NameTestCase: XCTestCase {
    func test_0_Taylor() {
        print("Test1")
        XCTAssertEqual("Taylor", TestableStruct.getName(id: 0))
    }
    
    func test_1_Swift() {
        print("Test2")
        XCTAssertEqual("Swift", TestableStruct.getName(id: 1))
    }
    
    func test_Unknown() {
        print("Test3")
        XCTAssertEqual("Unknown", TestableStruct.getName(id: 10000))
    }
    
    func test_Fail() {
        print("Test3")
        XCTAssertEqual("Unknown", TestableStruct.getName(id: 0))
    }
}
```

## テストの実行方法

```swift
NameTestCase.defaultTestSuite.run()
```

## テストの実行結果

logに表示されるだけで、みやすいわけではない。
失敗したかは最後の行で確認


```
Test Suite 'NameTestCase' started at 2021-11-10 12:23:19.976
Test Case '-[__lldb_expr_12.NameTestCase test_0_Taylor]' started.
Test1
Test Case '-[__lldb_expr_12.NameTestCase test_0_Taylor]' passed (0.003 seconds).
Test Case '-[__lldb_expr_12.NameTestCase test_1_Swift]' started.
Test2
Test Case '-[__lldb_expr_12.NameTestCase test_1_Swift]' passed (0.000 seconds).
Test Case '-[__lldb_expr_12.NameTestCase test_Fail]' started.
Test3
/TestPlayground.playground:36: error: -[__lldb_expr_12.NameTestCase test_Fail] : XCTAssertEqual failed: ("Unknown") is not equal to ("Taylor")
Test Case '-[__lldb_expr_12.NameTestCase test_Fail]' failed (0.000 seconds).
Test Case '-[__lldb_expr_12.NameTestCase test_Unknown]' started.
Test3
Test Case '-[__lldb_expr_12.NameTestCase test_Unknown]' passed (0.000 seconds).
Test Suite 'NameTestCase' failed at 2021-11-10 12:23:19.980.
	 Executed 4 tests, with 1 failure (0 unexpected) in 0.003 (0.004) seconds
```

# 終わり

Playgroundで簡単にTestableなコードが書けているか確かめられます！
html.erbで条件によりマルチクラス(class)を利用する方法

## 概要
erbでのマルチクラスの書き方。
modifierなどを利用したコーディングをしている際によく利用される。

## erb
```erb
<div class="toggle<%= ' toggle--open' if flag %>">
```

半角スペースは、modifier側につけることでコードが汚れなくなる。

## HTML

```html
<div class="toggle toggle--open">
```
Progate Ruby on Rails5 VIII 個人的ざっくりまとめ

# getとpostで同じ名前のルーティングでもOK

以下のように、「/login」で2つのルーティングが同じ名前になっているが、getとpostでは異なるルーティングとして扱われるので問題ない。

```rb:routes.rb
:
get "login" => "users#login_form"
post "login" => "users#login"
:
```

```erb:application.html.erb
<!-- link_toメソッドはデフォルトでgetのルーティングを探す -->
<%= link_to("ログイン", "/login") %>
```

```erb:login_form.html.erb
<!-- form_tagメソッドはデフォルトでpostのルーティングを探す -->
<%= form_tag("/login") do %>
:
<% end %>
```


# 変数session

ページを移動してもユーザーの情報を保持し続けるために使われる。
sessionに代入された値は、ブラウザに保存される。
`session[:キー名] = 値`で値がブラウザに保存される。

```rb:users_controller.rb
def login
  @user = User.find_by(...)
  if @user 
    # 特定したユーザーのidを代入し、ログインユーザーの情報を保持
    session[:user_id] = @user.id
    :
  end
  :
end

def logout
  # nilを代入することで、値を空の状態にできる（ログイン状態ではなくすることができる）
  session[:user_id] = nil
end
```

※sessionの値を変更する場合は、ルーティングはpostになることに注意

```rb:routes.rb
:
post "logout" => "users#logout"
:
```


# before_action

**○before_actionが必要になる場面**
top.html.erbやabout.html.erbなどの各アクションに対応したビューファイルは、applecation.html.erbの`<%= yield %>`部分に代入される。
これによって、application.html.erbは全アクションから呼び出される。

つまり、**application.html.erbでアクション側の変数を使おうとすると、以下のように全アクションで＠変数を定義しなければいけなくなる。**

```rb:posts_controller.rb
def index
  @current_user = User.find_by(id: session[:user_id]) 
end

def show
  @current_user = User.find_by(id: session[:user_id])
end

def new
  @current_user = User.find_by(id: session[:user_id])
end
:
```

このように、各コントローラーの全アクションで共通する部分は`before_action`を使う。
`before_action`を用いることで、アクションが呼び出される際に必ず`before_action`の処理が先に実行される。

```rb:posts_controller.rb
# before_action 全アクションで共通する処理
before_action :set_current_user

def set_current_user
  @current_user = User.find_by(id: session[:user_id])
end

def index
  # @current_user = User.find_by(id: session[:user_id]) 
end

def show
  # @current_user = User.find_by(id: session[:user_id])
end

def new
  # @current_user = User.find_by(id: session[:user_id])
end
:
```


# applicationコントローラー

全てのコントローラーで共通する処理はapplicationコントローラーにまとめる。

```rb:application_controller.rb
before_action :set_current_user

def set_current_user
  @current_user = User.find_by(id: session[:user_id])
end
```


# before_actionを特定のアクションのみで実行

before_actionに`only`を用いることで、before_actionで指定したメソッドを`only`で指定したアクションでのみ実行させることができる。

```rb:users_controller.rb
before_action :authenticate_user, {only: [:edit, :update]}
```

```rb:application_controller.rb
def authenticate_user
 :
end
```

```rb:users_controller.rb
class UsersController < ApplicationController
  # applicationコントローラーを継承しているので、継承元のメソッドを使うことができる
  before_action :authenticate_user 
  :
end
```


# to_iメソッド

`to_iメソッド`は文字列を数値に変換することができる。

```rb:users_controller.rb
before_action :ensure_correct_user, {only: [:edit, :update]}

def endure_correct_user
  # params[:id]で取得できるのは数字であっても文字列なのでto_iメソッドで数値に変換する
  if @current_user.id != params[:id].to_i
    flash[:notice] = "権限がありません"
    redirect_to("/posts/index")
  end
end
```
macOS docker log削除(laradock)


## macOS環境
　DockerはmacOS上のHyperKitという仮想化環境でLinuxKitという軽量Linuxを動かすので、Linux環境のような docker inspectでによりLogPathを見つかる削除はできない。下記CMD検証で削除できる
※ CONTAINER_NAMEを自分のコンテナ名を替えてください。

~~~
 docker run -it --rm --privileged --pid=host CONTAINER_NAME nsenter -t 1 -m -u -n -i -- sh -c 'truncate -s0 /var/lib/docker/containers/*/*-json.log'
~~~

## linux環境

~~~
docker inspect 【コンテナ名】 | grep -i log
~~~
xxxx-json.logのログを消去(ゼロにする)すれば問題は解決
Androidアプリ起動、遷移後に落ちる理由


Androidアプリを触ってて落ちる原因になりそうなことをちょっこちょこ書いていく忘備録として使います。

##onCreateの前にViewの呼び出し

```kotlin
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_list)
    }
```

Activityを作成するときにこれ最初からあると思うんですが、これの前にViewの呼び出しをすると落ちます。

OKな例

```kotlin
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_list)

        val listView = findViewById<ListView>(R.id.list_view)
    }
```

NGの例

```kotlin
    override fun onCreate(savedInstanceState: Bundle?) {

        val listView = findViewById<ListView>(R.id.list_view)

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_list)
    }
```

なぜか落ちると思ってデバックしていろいろやった結果これでした

リファクタリングして綺麗にしようと思った時に結構起きると思うので注意が必要です。

##AndroidManifestでエラーが起きてる

クラス名微妙だなと思って変更したタイミングで結構起こりやすいです。


あれ、、、ビルドできるしソース間違えてないのにこの画面の時だけ落ちる、、、みたいな時はAndroid Manifestをチェックしてみましょう。

僕はこのパターンで3時間ほど考え込んでしまいました。

ついでにソースのリファクタリングもしてたので、それもとに戻したりとすごい時間を浪費しました。


その他は都度都度書いていきます。
【Laradock】npm run devでエラー

#出たエラー
Error: error:0308010C:digital envelope routines::unsupported
・
・
・
opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
  library: 'digital envelope routines',
  reason: 'unsupported',
  code: 'ERR_OSSL_EVP_UNSUPPORTED'
}

Node.js v17.0.1

#原因
Node.js　v17.0.1では「digital envelope routines」がサポートされていないとのこと。

#対処法
Node.jsのバージョンをダウングレードする。

#引っかかった点
```
# npm install -g n
# n　v16.13.0
```
とバージョンを指定してインストールを行なったが、認識されるバージョンはv17.0.1のまま変わらなかった。
→Node.jsのバージョン管理をしているnvmを参照していた。
　（activeのところで「.nvm」を見ているようなら同じ状況と思われます）

#解決策
nvmの方でNode.jsのバージョンをダウングレードする。

```
# nvm install v16.13.0
```
Node.jsのバージョンを確認

```
# node -v
// v16.13.0　に変わっていればOK！
```

その後、

```
# npm run dev
```
を実行したところ、問題なく実行できた！

#参考記事
https://qiita.com/guai3/items/4d38dcb8a877951b718a
[追記式]Discord.js v13のメモ

## 自分がDiscord.jsを用いた際のメモをただただ残していく
元々は`Discord.py`([discord.pyへようこそ](https://discordpy.readthedocs.io/ja/stable/))を用いてBOTを組んでいましたが，開発が終了していたり，自分が欲しい機能(ex. Slash Commands)かなかったりと色々あるので`Discord.js`に移行することを決めました．

### 余談
今まで`Python`ばかり触れており`node.js`?を触れるのは初めてなのでわからないことばかりです．なので，備忘録的な感じでここに追記しながら書き収めていきたいと思います．記述していくものはコード中心なのでBOTの設定等は省略します．

### 注意
あくまでも僕自身のやり方なので必ずしも正しい書き方とは限りません．有識者の方いらっしゃいましたらアドバイス等よろしくお願いします！

## 備忘録
2021/11/10: この記事の始まり

### 基本的なファイル構成
```
├── main
    ├── config.json
    ├── deploy-commands.js
    └── index.js
```

> config.json: `TOKEN`など外部に見せたくないファイルを書いていくファイル
> deploy-commands.js
> index.js: メインに書いていくファイル

> ※ Githubを用いる際などは`config.json`は`.gitignore`に記述する．

#### config.json
```config.json
{
    "clientId": "BOTのクライアントID",
    "guildId": "DiscordサーバーのID",
    "token": "トークン"
}
```

#### deploy-commands.js
このファイルでは`/`(Slash Commands)を登録しています．

```deploy-commands.js
const { SlashCommandBuilder } = require('@discordjs/builders');
const { REST } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v9');
const { clientId, guildId, token } = require('./config.json');

const commands = [
	new SlashCommandBuilder().setName('good').setDescription('Replies with morning!'),
]
	.map(command => command.toJSON());

const rest = new REST({ version: '9' }).setToken(token);

rest.put(Routes.applicationGuildCommands(clientId, guildId), { body: commands })
    .then(() => console.log('Successfully registered application commands.'))
	.catch(console.error);

```

#### index.js
このファイルでは`deploy-commands.js`で登録したSlash Commandsを実行した時の挙動を記述したり，その他の挙動を記述していきます．

```index.js
const { Client, Intents, Message, VoiceChannel } = require('discord.js');
const { token } = require('./config.json');

const client = new Client({ intents: [Intents.FLAGS.GUILDS] });

client.once('ready', () => {
	console.log('Ready!');
});

client.on('interactionCreate', async interaction => {
	if (!interaction.isCommand()) return;

	const { commandName } = interaction;

	if (commandName === 'good') {
		await interaction.reply('> morning!');
	}
});

client.login(token);
```

### メッセージが送信された`channel id`を取得して変数定義する
```index.js
const ch_id =interaction.channelId;
```

### 最後に
タイトルにある通りこの記事は追記式で書いています．
UnityのDropDownメニューの色を変えたり、半透明にしたい

## UnityのDropDownメニューの色を変えたり、半透明にしたい
ドロップダウンの背景色を半透明にしたいと言われましたので。

デフォルトはこんな感じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221026/5097de50-0bab-ad6e-467d-ca06d4c37044.png)

### Option Aの背景色を変更する
Option Aの背景色は、DropDownを選び、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221026/f76c1275-cc5a-e6c6-b1e3-97f9fa525e67.png)
InspectorのImageを変更する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221026/85c1d6bd-5ca7-95c1-7ea1-e180a13fa2ca.png)

### プルダウン時に出てくる選択肢の背景
プルダウンで表示される選択肢の背景色は、TemplateとItem Backgroundの2つの色が影響しています。（不透明の場合、Item Backgroundが有線される様子）

##### TemplateをImageを透明にする
- わかりやすくするために、TemplateのImageを透明にする
Templateを選択し、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221026/a3dad98e-2055-5697-a4a4-33d437ec928c.png)

InspectorのImageのColorを透明に（A（アルファ）をゼロに）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221026/b831adca-d7b8-b21e-32ee-4dfb29de004f.png)

##### Item BackgroundのImageの色を彩色したり、半透明にする
Item Backgroundを選択し、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221026/84c90062-644b-b679-2378-acd184bba68b.png)

色を変え、半透明にしてみます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221026/3fc40149-5b56-5cea-7520-aa446c34f0ed.png)

半透明のドロップダウンができました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221026/f425564c-0888-b477-2685-2fe04c27789d.png)

以上です
【Nukkit】Java17とかがインストールされてるけどJava8で動かしたい人必見！！

# 安〇先生...!!
JAVA_HOMEはJava17だけどNukkitはJava8で動かしたいです...

てかNukkitはJava8で開発されてるので多分Java8で動かした方がいい（多分）

# 環境
Windows10

# Java8 jdkをインストール
Java8のjdkをインストールして下さい。
インストーラーは以下よりダウンロード出来ます。
[Java Downloads | Oracle](https://www.oracle.com/java/technologies/downloads/#java8-windows)

# パスを確認
普通の人なら```C:\Program Files\Java```にインストールされてるはずです。
2021/11/10現在はjdk1.8.0_311がインストールされました。

# Nukkitを起動
以下の通りにコマンドを実行します。
jdk1.8.0_311の部分はバージョンを確認して適宜変えてください。

```
> cd nukkit-1.0-SNAPSHOT.jarがあるパス
> "C:\Program Files\Java\jdk1.8.0_311\bin\java.exe" -jar nukkit-1.0-SNAPSHOT.jar
```

# おまけ
毎回さっきのアレ打つのも面倒なんでPocketMine-MPのstart.cmdっぽいものを作ります。

```bat:start.cmd
@echo off
"C:\Program Files\Java\jdk1.8.0_311\bin\java.exe" -jar nukkit-1.0-SNAPSHOT.jar
pause
```

おわり
超爆速でNode.js開発環境構築する

# やりたいこと
複数のNode.jsバージョンが混在可能な開発環境を構築したい。

# 解決策

[Volta](https://docs.volta.sh/guide/getting-started)をインストールしましょう。

# Linuxの場合

```shell:ターミナル
curl https://get.volta.sh | bash
volta setup
volta install node@16
```
上手く行かない場合はターミナルを再起動しましょう。


```shell:ターミナル
# バージョン表示されればOKです。
volta -v
node -v
npm -v
```


以上。
[VirtualBox] 仮想マシンにOSインストール

## はじめに
前回「[【初心者向け】仮想マシンの作成](https://qiita.com/HITOSUKE/items/5cc5c6a75e88317796f3)」よりVirtualBoxに仮想マシンとネットワーク設定まで行いました。
仮想マシンが準備できたので、本章では仮想マシンにOS（以下、ゲストOS）をインストールする手順を紹介していきます。

## OSインストール
実際に進めてみましょう。
### [Step1] CentOS 7 isoファイルをダウンロード
CentOS 7のインストール用メディアは公式サイトからダウンロードしたisoファイルを利用します。
CentOSのインストール用isoファイルはCentOSの公式サイトからダウンロードできます。
[CentOS公式サイト ダウンロードページ](https://www.centos.org/download/)

CentOS Linux の「7(2009)」のタブを選択します。
![01.キャプチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109986/1af215eb-d796-192c-c7b4-9efbdaf117dd.png)
今回は「x86_64」を選択します。

![02.キャプチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109986/97d68285-08b7-16c6-2d23-d8b39f77cfdf.png)
どのisoファイルでもよいですが、今回は ftp.riken.jp ドメインのを選択します。

最小限のインストールでよいので CentOS-7-x86_64-Minimal-2009.iso をダウンロードします。
ローカルPCの任意の場所に保存します。

### [Step2] 仮想マシンに設定
前回作成した仮想マシンの「設定」を開きます。
①ストレージにデバイスを追加
![03.キャプチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109986/9f776eac-31eb-f757-faad-e074c12fd228.png)
　ストレージデバイスの右下の「ディスクアイコンと＋」のアイコンより 光学ドライブ を選択します。

②光学ディスクを追加
![05.キャプチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109986/1d4b1b88-591e-a1e2-6cfb-762522eb75c1.png)
　左上の「追加」より、ダウンロードした「CentOS-7-x86_64-Minimal-2009.iso」を追加して選択します。
　ストレージデバイスに追加されたことを確認し「OK」で進みます。

### [Step3] OSインストール
①イメージを起動

②起動後ウィンドウが立ち上がる
![06.キャプチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109986/a9197341-5c9b-054d-9e6f-5164ebe7dc02.png)
　「起動」で進むとインストールが始まります。

③言語選択
![08.キャプチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109986/f8d910c5-4e5c-120d-f841-591e68f1fdf4.png)
　日本語を選択し「続行」で進みます。

④システムのインストール先を確認
![09-1.キャプチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109986/5d31f7a6-4e4d-54f4-20a1-444825d06e80.png)
　システム インストール先(D)よりシステムのインストール先を確認します。

![09-2.キャプチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109986/a0a2595e-2efb-da04-b5e6-bbfee075f80a.png)
　ローカルの標準ディスクが選択されていることを確認して「完了」で戻ります。

⑤ネットワークとホスト名の設定
![10.キャプチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109986/be9d725a-584a-b359-2725-c5421e6ff7cb.png)
　左側で「Ethernet(enp0s3)」「Ethernet(enp0s8)」それぞれを選択し右側のスイッチを「オン」に変更し「完了」で戻ります。

⑥インストールを開始
![11.キャプチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109986/31f1b145-683f-102f-4151-c496e4ef9c35.png)
　「インストールの開始」よりインストールをします。

　途中「root」アカウントの設定が可能です。
![11-1.キャプチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109986/8a179856-9af7-a336-5cd1-67235b5a426f.png)
　インストールを待つ間にパスワードを設定してしまいましょう。
![11-2.キャプチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109986/3f70d900-02ef-8935-ba83-46459841de3a.png)
　「ROOTパスワード(R)」よりパスワードを入力画面へ遷移します。
　パスワードを入力し「完了」で戻ります。

⑦インストール完了
　インストールが完了するまで少し待ちます。
![12.キャプチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109986/514880d2-9604-c87d-5d2e-632634a33e43.png)
　この画面が出てきたらインストールは完了です。

##　おわりに
前回より続いた仮想マシンの作成とOSインストールは以上です。
作成した仮想環境にミドルウェアをインストールして自由に活用していきましょう。
Pega　備忘録


#Activity例
 1.Page-New
 2.Obj-Open/Obj-Open-By-Handle
 3.Property-Set
 4.Obj-Save
 5.Commit
 
###Page-New
 clipboardに新しいPageを作成する

###Obj-Open/Obj-Open-By-Handle
　検索条件に一致するインスタンスを開く。
　複数のレコードを開く場合、Obj-Openを使用し、pzInsKeyも把握していて1レコードのみを処理対象としたい場合、Obj-Open-By-Handleを使用する

###Property-Set
　変更したい値を書き換える。

###Obj-Save
　変更した情報を保存。SQL実行のイメージ。
　WriteNowオプションを使用することで、DBへ即時反映される。

###Commit
　Obj-Saveした情報をDBへ反映される。

###サンプル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130008/c524fa40-f597-04a8-f33b-d1c322ddc79b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130008/8bc0e9f3-4e97-0f23-7010-8ce22eb25003.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130008/bfbefa74-3e80-6f8c-32e5-b1813afc924d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130008/fb8e82ce-7ac0-9a71-dcac-a43758715ea5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130008/a442c031-3a63-0f27-88dd-5e8279e11d01.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130008/b9db0d21-57fd-4d76-b808-91bb00afddca.png)


------------------------------------
###Debug
 Log-Message
　LoggingLevel:InfoForced

###Obj-Browse
　PageName:結果が格納されるList(Code-Pega-List)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130008/4f82bd3b-2d3f-90de-09a0-51d239553bef.png)

###Obj-Open

###Obj-Open-By-Handle

------------------------------------

###Link
 1.https://myknowpega.com/
 2.https://www.pegahelp.com/
 3.https://welearnpega.blogspot.com/2019/10/page-new-method.html
 3. google で　-site:pega.com
【Flutter】プロジェクト作成のコマンドをいつも忘れるので

# プロジェクト作成コマンド
```
flutter create -i swift -a kotlin hogehoge
```

コマンドをいつも忘れるので忘備録です。

# 詳細はこちら
https://qiita.com/kurun_pan/items/f9251b1827ce9dca9e14
インポートエラー　from PyQt5 import QtCore,QtGui,QtWidgets 

かなり何年前から使っているwinPython3.6.6.2が急にインポートエラーが発生している。なにも触っていないのに、急にエラーが発生しました。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263439/e62e9032-aa78-a8d4-a0ff-138c1035c5eb.png)
※import PyQt5は問題ないです。

対策したことをメモします。
１、Lib\site-packages\PyQt5\Qt\bin　下の
　　・QtCore.dll
　　・QtGui.dll
　　・Qt5Widgets.dll
　　をpython-3.6.6.amd64のフォルダーにコピー。
　\PyQt5\Qt\plugins下のplatformsフォルダーもpython-3.6.6.amd64のフォルダーにコピー。
　　→エラーが消えない。
２、新たなwinpython 3.6.6.2をダウロードし、python3.dllをコピーし、
　　上書き保存した。
　　→エラーが消えない。
もう駄目だと思って、PCを再起動すると、エラーが消えた。
結局エラーの原因は不明ですが、エラーが消えたので、一応メモします。
yahoo!広告排除Bookmarklet [個人的メモ]

```javascript
javascript:((list=[],f=s=>document.querySelectorAll(s).forEach(e=>e.remove()))=>list.forEach(f))(["[class*=yads]","iframe:not([class*=comment])","[data-rma-viewable]","[class^='yjad']","[class^='yad']","[class^='yjdad']"])
```
2021.11.10現在 → M5Stack + ArduinoIDE 環境での AquesTalk ESP32 利用時におけるリンカーエラー対策（とりあえず動作させたい人向け）

# はじめに

初投稿の覚書。
推奨されている方法は二の次で、とりあえず動作させたい人向けの記事。


現状、２種類の問題を確認。

１）リンク時、AquesTalk のコンパイル済みバイナリとリンクできないエラー（undefined reference to `CAqTkPicoF_SetKoe' 等）

　対策：下記のURLの通り。

http://blog-yama.a-quest.com/?eid=970195

　異なるところは、

　・環境設定
　・ボードマネージャ追加設定
　・platform.txt のパス


２）リンカーが動作しない（cannot open linker script file esp32.rom.redefined.ld: そのようなファイルやディレクトリはありません）

　対策： ボードマネージャでインストールするバージョンを古めのバージョンにする。


## 環境設定

追加のボードマネージャURLに M5Stack のURLを追加。
```
https://www.adafruit.com/package_adafruit_index.json,https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
```



## ボードマネージャ

M5Stackを追加。
注意点は2.0.0等の最新版は使わないこと（理由は不明……）。
1.0.9を使ってみたら成功した（1.0.6でも動作確認済み）。

![Screenshot from 2021-11-10 10-16-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190537/9495d74c-c3be-365b-351f-749193d57f30.png)



## platform.txt


編集対象の platform.txt の path は、Linux版では、

```
~/.arduino15/packages/m5stack/hardware/esp32/1.0.9/platform.txt 
```

となる。


編集内容は、以下の２点。

１）compiler.libraries.ldflags を空白に設定(なければ追加)

```
compiler.libraries.ldflags=
```


２）recipe.c.combine.pattern を以下に修正

```
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} {compiler.libraries.ldflags} -Wl,--end-group -Wl,-EL -o "{build.path}/{build.project_name}.elf"
```




なお、platform.txt を直接編集せずに、上記内容を platform.local.txt に記述して、platform.txt と同じディレクトリに保存するのが推奨らしい。


``` platform.local.txt
compiler.libraries.ldflags=
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} {compiler.libraries.ldflags} -Wl,--end-group -Wl,-EL -o "{build.path}/{build.project_name}.elf"
```

これも、動作確認済み。


* * *

以上、取り急ぎご報告まで。

* * *
isfloatable()　floatに変換できそうかどうか判定する関数

isfloat()が文字列に優しくなかったり
ちょっと不便な感じだったので・・。


```python
def isfloatable(value):
    if type(value) == float :
        return True
    elif type(value) == str or type(value) == int:
        try:
            float(value)
            return True
        except ValueError:
            return False
    else:
        return False
```

```text
>>> print( isfloatable(10) )
True
>>> print( isfloatable("10") )
True
>>> print( isfloatable(10.1) )
True
>>> print( isfloatable("10.1") )
True
>>> print( isfloatable("10.1a") )
False
>>> print( isfloatable("a") )
False
>>> print( isfloatable("") )
False
```

#参考
[【Python】文字列が数値型(int・float)へ変換可能か判定する方法](https://neko-py.com/python-type-judge)