OmniAICreator/Qiita-1.07M huggingface dataset:
Google 翻訳の正規 URL から誘導されるフィッシングについて

フィッシング対策協議会から「Google 翻訳の正規 URL から誘導されるフィッシング」という注意喚起が出たが，●●●●で隠されたリダイレクトの仕組みがわからなかったので，いろいろ試してみた。

Google 翻訳の正規 URL から誘導されるフィッシング (2022/08/09)

https://www.antiphishing.jp/news/alert/googletranslate_20220809.html

フィッシング対策協議会のコレ見ると， `translate?` の後ろに，セカンドレベルドメインを入れれば，`https://prevent.●●●●.com/` にリダイレクトされるように書いている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/016d3e1f-144a-c3de-4119-98bac0aa5895.png)

`onamae.com` に飛ぶのか実験してみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/1acd055c-304e-d386-38bb-84f6dfc66dd0.png)

だめだ。失敗。
どういう仕組みなのか？さっぱりわからん。
`prevent` って意味あるのか？

Burp Suite でGoogle 翻訳（URL翻訳）のリダイレクトを追っていくアプローチから秘密が解明できた。

私が作った `Google翻訳の正規ドメイン` から，フィッシング対策協議会のトップページにリダイレクトするURLはコレ。
悪用防止でお見せできないが。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/27eec893-d8ca-d61c-31c4-45d99eec29b4.png)

証拠
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/f0c5b6a6-04dc-59e3-4d84-6ed4a3145413.png)
COCOAログを Python で読んでみた（リンク集あり）

## COCOA 接触確認アプリ
COCOA 接触確認アプリで出力されるログファイルを読み込んで、接触リスクは低いがニアミス（？）している可能性をチェックしてみようと思いました。

## きっかけは元祖のサイト
COCOAログをチェックしてくれるサイト（公式？）があったので、試してみたら、結構ニアミスしているようでした。
[COCOAログチェッカー](https://cocoa-log-checker.com/#/)
さらに、気になって調べてみたら、ソースも公開されていました。
[https://github.com/ktansai/COVID-19-ExposeChecker](https://github.com/ktansai/COVID-19-ExposeChecker)

## Pythonプログラムの参考にしたサイト
「[COCOAデータを読む](https://okumuralab.org/~okumura/python/COCOA.html?fbclid=IwAR3V07TPOAANfqlywqS8wHXn_YLDGgtgtB2IPMu4qZ8zrua_Je0n5zSI1u0)」というサイトに、COCOAログファイルを読む Python プログラムがありましたので、早速使ってみました。

## 自分なりにプログラムを変更してみた
上記のプログラムでも結果は出ますが、全記録が出てくるので、
・割と近くで検出されたものだけ（MinAttenuationDb が 100未満のもの）を表示
するように変更しました。

## 変更後のソース
```python:cocoaLogChecker.py
import json
import pandas as pd

with open("exposure_data.json") as f:
	exposure = json.load(f)

print("Date Infectiousness  TypicalAttenuationDb MinAttenuationDb SecondsSinceLastScan")
ts = ""
for x in exposure["exposure_windows"]:
	t = pd.Timestamp(x['DateMillisSinceEpoch'], unit='ms')
	td = str(t)[:10] + " " + str(x["Infectiousness"])
	for y in x["ScanInstances"]:
		if y["MinAttenuationDb"] < 100 :
			if td != ts :
				print()
				print(td, end="")
				ts = td
			print(" ", y["TypicalAttenuationDb"], y["MinAttenuationDb"],
              y["SecondsSinceLastScan"], end="")
print()
```
このプログラム「cocoaLogChecker.py」と、COCOA接触確認アプリで出力された JSONファイル「exposure_data.json」を同じディレクトリに置いて、ターミナルからコマンドで
`$ python cocoaLogChecker.py`
と実行させると、ログの開始日から現在までの結果が表示されます。
```:出力サンプル
2022-07-24 2  97 97 60
2022-07-25 2  79 79 60  87 76 120  91 84 120  92 92 180  93 82 120  95 95 120
2022-07-31 2  97 97 60  95 95 60  97 97 60  98 98 60  90 90 60  96 96 120  90 81 60  77 68 60
2022-08-02 2  71 64 120  70 65 120  71 69 60  83 72 120
2022-08-03 2  90 78 60
2022-08-04 2  87 87 60  98 93 60
2022-08-05 2  80 80 60  94 94 60
2022-08-06 2  99 99 60
2022-08-07 2  96 96 60  97 97 60
```
結構ニアミスしていたようです。
日付以外の数値の意味については、上記の「COCOAデータを読む」のサイトをご覧ください。
（私も良くわかっていません...）

## 後書きなど...
このプログラムでは全期間を対象としていますが、本家のように２週間以前のものは処理しないようにしたいところですが、面倒で組み込んでいません。
M1 Mac mini で動かしましたが、Python をどのように入れたのか覚えていません。
で、M1 MacBook Air で動かそうとしたら、Pythonが入っていませんでした。

基本的には、このサイトが参考になりますしたが、最初の Home brew のインストールでつまづく
[https://www.python.jp/install/macos/install_python.html](https://www.python.jp/install/macos/install_python.html)

M1 macOSに Home brew をインストールするには、このサイトの情報を利用する
[https://docs.brew.sh/Installation](https://docs.brew.sh/Installation)

また pip もアップデートして、 pandas をインストールする
[https://www.geeksforgeeks.org/how-to-install-python-pandas-on-macos/](https://www.geeksforgeeks.org/how-to-install-python-pandas-on-macos/)

で、Airでは Python3 になっています。
NCMBのC#（Xamarin） SDKがスクリプト実行に対応しました

ニフクラ mobile backend（NCMB）では公式として各種フレームワーク、環境向けにSDKを提供しています。その1つにUnityがあります。Unity向けに開発を行う際にはC#を利用しますが、このUnity用SDKは.NET環境では利用できません。

そこでコミュニティSDKとしてXamarinや.NET 2.0でも動作するC# SDKを開発しています。今回のバージョンアップでスクリプト実行にも対応したので使い方を解説します。

[NuGet Gallery | NCMBClient 1.0.0](https://www.nuget.org/packages/NCMBClient/)

## NCMBをインストール

任意のプロジェクトをVisual Studioで開きます。

![スクリーンショット 2022-06-21 16.12.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/9c51cd20-c9f4-a00b-804a-ed7db410ccd0.png)

そしてプロジェクトを右クリックして、NuGetパッケージの管理を選択します。

![スクリーンショット 2022-06-21 14.55.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/61392119-a472-9d33-101d-970f016fc2cf.png)

出てきたウィンドウで、NCMBClientを検索します。執筆時点での最新版は1.0.0です。これを追加します。

![スクリーンショット 2022-06-21 14.43.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/f06df07c-f55d-1e0e-65b2-de79c779cc80.png)

## NCMBをインポートする

`MainPage.xaml.cs` を開きます。そして、namespaceの下でNCMBClientをインポートします。

```cs
namespace MyMauiApp;
using NCMBClient;
```

インスタンス変数としてNCMBを定義します。

```cs
public partial class MainPage : ContentPage
{
	int count = 0;
	// 追加
	NCMB ncmb;
```

クラスの初期化時にNCMBも初期化します。キーは[ニフクラ mobile backend](https://mbaas.nifcloud.com/)より取得してください。

```cs
public MainPage()
{
	InitializeComponent();
	ncmb = new NCMB("YOUR_APPLICATION_KEY", "YOUR_CLIENT_KEY");
}
```

## スクリプトオブジェクトの作成

まずスクリプトオブジェクトを作成します。引数はアップロードしたスクリプトのファイル名です。

```dart
var script = new NCMBScript("script_test_put.js");
```

## ヘッダー、ボディ、クエリーの指定

スクリプトはヘッダー、ボディ、クエリーを指定できます。

### ヘッダーの指定

```dart
script.Header('foo1', 'bar1');
script.Header('foo2', 'bar2');
```

### クエリーの指定

```dart
script.Query('hoge1', 'fuga1');
script.Query('hoge2', 'fuga2');
```

### ボディの指定

ボディはPOST/PUTメソッドの時しか使えません。

```dart
// Only POST or PUT method
script.Body('hoge2', 'fuga2');
script.Body('hoge3', 'fuga3');
```

## 実行

実行は各HTTPメソッドごとにメソッドを用意しています。バイナリのレスポンスを受け取る場合には 〜Byteを使ってください。

### GET

```dart
var result = await script.Get();
// バイナリの場合
var result = await script.GetByte();
```

### POST

```dart
var result = await script.Post();
// バイナリの場合
var result = await script.PostByte();
```

### PUT

```dart
var result = await script.Put();
// バイナリの場合
var result = await script.PutByte();
```

### DELETE

```dart
var result = await script.Delete();
// バイナリの場合
var result = await script.DeleteByte();
```

## レスポンス

通常は `JObject` 型でレスポンスを返します。〜Byteの場合は `Byte[]` で返却します。

## まとめ

C# SDKはXamarinで使えばiOSやAndroidはもちろん、Linux/macOS/Windowsアプリも開発できます。.NET環境であればWebやCLI開発でも利用できます。ぜひ皆さんのアプリ、Webアプリ開発に利用してください。

[NuGet Gallery | NCMBClient 1.0.0](https://www.nuget.org/packages/NCMBClient/)
renameコマンド使ってみた

renameコマンドで個人的に使った条件を備忘録的に置いておきます。（随時更新するかも）
# install
```
brew install rename
```
# 使ったケース
## ディレクトリ内のファイルの名前を特定の名前`blogpost.md`に一括でリネームしたい
```
.
├── A
│   └── aaa
│       └── aaa.md
├── B
│   └── bbb
│       └── bbb.md
```
を
```
.
├── A
│   └── aaa
│       └── blogpost.md
├── B
│   └── bbb
│       └── blogpost.md
```
にしたい

### 答え
```
rename 's/(.+)\/(.+)(\.md+$)/$1\/blogpost.md/' ./**/*.md
```

$1がディレクトリ名部分、$2が変える前のファイル名、$3が拡張子になる
Excelの「リアルタイムでの画面更新を無効または有効にする」

# はじめに
Automation 360の「Excel の高度な操作」に「リアルタイムでの画面更新を無効または有効にする（Disable or enable real-time screen update）」があります。
これを使っているときに少し気になった小ネタです。
なお、「Excelの高度な操作（6.8.0-20220409-020138）」での確認です。今後変わる可能性があります。

#  どんなときに使うか？
例えば100×100のセルを１つずつ、「Excel の高度な操作: セルを設定」で書き込む場合、標準では1セルずつのデータの書き込みとセルの移動が目に見えます。このオプションを使うと画面の書き換えがなくなり実行時間が半分以下になります。

AA社サイトでの説明は以下。

https://docs.automationanywhere.com/ja-JP/bundle/enterprise-v2019/page/enterprise-cloud/topics/aae-client/bot-creator/commands/cloud-excel-worksheet-operations.html

ただ、このページで「重要: 大きなデータセットを使用する アクション を実行したときにパフォーマンスの問題が発生した場合にのみ、このアクションを使用することをお勧めします。」と書かれているように、使うときに少し注意が必要です。

#  注意事項

## （１）リアルタイム画面更新以外への影響
（ａ）計算方法の設定(Application.Calculation)が「手動」に代わる
（ｂ）イベントの発生の制御(EnableEvents)が「無効」になる

(b)はそこまで影響ないと思いますが、(a)は「計算式が入っているセルの参照」は注意です。
また「計算方法の設定」は保存されるので、「リアルタイムでの画面更新を無効または有効にする」でDisableのまま「Excel の高度な操作: 閉じる」を実行するとExcelに「計算方法の設定」が「手動」で保存されます。
保存前に忘れずにEnableに戻しましょう。

## （２）複数Excel時の注意
「リアルタイムでの画面更新を無効または有効にする」には「セッション名」の指定がありますが、実際にはExcelプロセス全体に対して利いているようです。
そのため複数のExcelを使う場合、開いているExcel全部で「計算方法の設定」が「手動」になります。（Disableにセッション名を指定していないExcelでも）
使うときには、Excelの「開く」「閉じる」と「Disable」「Enable」の切り替えタイミングに注意しましょう。
レンタルサーバーを借りてオンラインゲームのWikiサイトを作ってみる #2.1

前の記事
https://qiita.com/Unirenkon/items/49191c9b06d3cf3e78d2

## 今回の作業
前回の記事で、「フロントを簡単にいじれるように環境を整える」ということで
gitの導入、共有レポジトリの作成などを行ってgit pushで簡単に本番反映をする、というところを目標にすると書きましたが、
なかなか自分の思うように動かせずに作業がストップしてしまっているので、一時的に別の方法で作業することにしました;-;

FTPクライアントを導入し、手動でローカルにファイルを落としてきて、更新後またFTPに戻して上書きするという方法です。

手順としては下記となります。

- FTPクライアントの導入
- xserverへ接続
- ローカルでファイルを編集してxserverにアップロード（上書き）

ではさっそく導入します！

## FTPクライアントの導入
FTPソフトというと有名な「[FFFTP](https://forest.watch.impress.co.jp/library/software/ffftp/)」など多数存在しますが、
今回はxserverで使うにあたって参考にさせていただいたサイト様で紹介されていた「[FileZilla](https://filezilla-project.org/)」を使用します。

### FileZillaをインストールする
[FileZillaダウンロードページ](https://filezilla-project.org/)からお使いの環境/OSに適したバージョンをダウンロードして、インストールを行います。

## xserverへの接続

### Xserver接続に必要な情報を確認
[Xserverのサーバーパネル](https://secure.xserver.ne.jp/xapanel/login/xserver/server/)にて、サーバー接続に必要な情報を確認します。

![スクリーンショット 2022-08-11 13.19.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296171/9a9b5fae-7058-53c9-3a80-76b879603bec.png)

![スクリーンショット 2022-08-11 13.10.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296171/0a26d8f5-5f88-9335-421a-b313a2741fd5.png)
![スクリーンショット 2022-08-11 13.11.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296171/0c406dff-f61e-a9e0-e61b-11b2e2959b23.png)
![スクリーンショット 2022-08-11 13.12.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296171/12ab1672-7654-cfa6-9115-298c519ad56d.png)

上記画像内の情報
- FTPサーバー（ホスト名）
- ユーザー名（アカウント名）

を確認します。
また、パスワードの部分は、サーバーパネルログイン時のパスワードを使用します。

**※サーバーパネルのパスワードとxserverアカウントのパスワードは異なります。**
私はサーバーパネルにxserverアカウントでログインしていたため、そのパスワードを使用しましたがうまくいきませんでした。
サーバーパネルのパスワードは、サーバーを申し込んだ際の「**■重要■サーバーアカウント設定完了**」という題名のメール内に記載されています。

### サーバーに接続
FileZillaに接続します。
ツールバーのファイル（F）→サイトマネージャーを開くと下記の画面になります。
![スクリーンショット 2022-08-11 14.48.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296171/0611848a-fab7-b2cd-aade-4f3f7b6f6230.png)

右下の新しいサイトをクリックし、右側に出てきたエリアに先ほど確認した情報を入力します。

- ホスト
  - FTPサーバー（ホスト名）
- ユーザー
  - ユーザー名（アカウント名）
- パスワード
  - メールで確認したサーバーパネルのパスワード

左下の接続を押すと接続が開始されます。


## 使い方
![スクリーンショット 2022-08-11 14.51.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296171/cd5c8c5d-6138-4a4e-0c5d-087e05a1c636.png)

左のスペースにローカル・右のスペースにサーバーのディレクトリが並んでいます。
左上の画面でディレクトリを選択すると、その中身が左下に表示されます。
ローカル・リモート間でファイルをやり取りするには、ローカルからサーバーに移動させたい場合はローカルで該当のファイルをドラッグしてサーバー内の該当のディレクトリ内にドロップすればOKです。
ruby の pack template 文字列の表

# これは何？

ruby の pack template 文字列を覚えられないので毎回調べるんだけど、マニュアルの記載は一覧性がないし使わないのも混ざっていて不便（私にとって不便ということで、マニュアルとして悪いわけではない）なので、まとめてみた。

私が使うやつしか書かないのであしからず。

# 整数

まあ 8bit はエンディアン関係ないけど。

|エンディアン|符号|8bit|16bit|32bit|64bit|
|:--|:--|:--|:--|:--|:--|
|LE (Intel)|signed|`c`|`s<`|`l<`|`q<`|
|LE (Intel)|unsigned|`C`|`v`|`V`|`Q<`|
|BE (Motorola)|signed|`c`|`s>`|`l>`|`q>`|
|BE (Motorola)|unsigned|`C`|`n`|`N`|`Q>`|


`v` や `N` などを使わなければ

* 8bit から順に `C`, `S`, `L`, `Q`。
* 小文字は signed、大文字は unsigned。
* エンディアンは `<` と `>` で表現

と、一貫性のある感じになる。

でもまあ `c`, `v`, `n` などでなんとかなる場合はそうする → やっぱり符号付きが必要 → あれどうするんだっけ ってなるよね。

# 浮動小数点数

|エンディアン|32bit|64bit|
|:--|:--|:--|
|LE (Intel)|`e`|`E`|
|BE (Motorola)|`g`|`G`|

x86 や ARM なら IEEE754 の普通の浮動小数点数になると思うけど、環境によってはその環境なりの浮動小数点数になる模様。

半精度はない模様。使う予定はないけどちょっと残念。
Docker備忘録

# コンテナと仮想マシン

`VMware`の仮想マシンとは使い方がかなり違うので、そちらに慣れていると初めたてのころは戸惑うかもしれない。

`VMware`の仮想マシンではインスタンスを生成した後、依存パッケージやプログラムをインストールした状態を保存して使うが、Dockerはインスタンスを生成するときに`dockerfile`に従って必要な依存パッケージやプログラムをインストールする。

生成したインスタンスは`イメージ`と呼ばれ、`イメージ`を元に`コンテナ`を生成する。生成したコンテナは、タグやダイジェストを指定して外部からアクセスできる。

`docker run`で生成したコンテナ内で作業した内容は、`docker commit`でイメージに保存することができるが、`-v`オプションを使ってホストとコンテナのディレクトリを共有することができるので`docker commit`はあまり使われない。

一般的にDocker単体で使うことは少なく、[Docker Compose](https://docs.docker.com/compose/)というツールを使って複数のコンテナを管理することが多い。ソースコードに加えて、`docker-compose.yml`を`git`で管理し、コンテナやイメージにソースコードが含まれることは少ない。

# サブコマンド
## ps
稼働中のコンテナの一覧を出す

```
$ docker ps
CONTAINER ID   IMAGE             COMMAND       CREATED         STATUS         PORTS     NAMES
923f3e2a1d15   centos:7.8.2003   "/bin/bash"   2 minutes ago   Up 2 minutes             nervous_cartwright
```

## images
```
$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE  
ubuntu       latest    ba6acccedd29   9 months ago   72.8MB
```
ローカルに保有しているコンテナ一覧


## pull
[Docker Hub](https://hub.docker.com/)からコンテナイメージをダウンロードしてくる。gitと違ってfetchはない。
Docker Hub以外にもローカルからダウンロードすることもできる。

```bash:$ docker pull [OPTIONS] NAME[:TAG|@DIGEST]
# :の後ろがタグ ubuntuの20.04をダウンロード
$ docker pull ubuntu:20.04
# ダイジェスト指定でダウンロード
$ docker pull ubuntu@sha256:82becede498899ec668628e7cb0ad87b6e1c371cb8a1e597d83a47fac21d6af3
```
- タグ指定
    - 対象のタグに最新があれば、最新のものが入れられる
- ダイジェスト指定
    - タグに更新があっても、固定のバージョンがインストールされるのでイメージの動作に再現性がある

## run
コンテナイメージを元にコンテナを生成して起動する
```
docker run -it ubuntu:20.04
```
Ctrl+Dで終了するとルートプロセスから終了していまうのでデタッチという操作で抜けます

## [cp](https://docs.docker.com/engine/reference/commandline/cp/)

コンテナからローカルにファイルをコピーすることができる

```bash:data.sqlをカレントディレクトリにコピーする
docker cp {{コンテナ名}}:/data.sql ./
```

# デタッチ
ctrl+Pとctrl+Q

# キーバインド削除
vscodeを使っている場合ショートカットキーが重複してるので変更します

基本設定のキーボードショートカットで[ctrl p と ctrl q]でそれぞれ検索してdeleteキーでキーバインドを消します

# rename
パラメーター指定なしで起動したコンテナには変な名前がついてます。気に食わないので変えたい人は
```
docker rename old_contena_name new_contena_name
```

# コマンドラインにアタッチ

起動しているコンテナで、コマンドラインで操作したい場合は、次のコマンドを実行する

```
docker exec -it contena_name /bin/bash
```

# alphine版のコンテナ
ubutuベースのコンテナはサイズが大きいので、軽量版のLinuxであるalphineがよく使われている

## bashは使えない
alphineは/bin/bashのバイナリを持っていないので、/bin/ashを使う

```diff_batchfile:/bin/bashを指定すると
$ docker run -it python:3.6.9-alpine /bin/bash
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown.

- docker run -it python:3.6.9-alpine /bin/bash
+ docker run -it python:3.6.9-alpine /bin/ash
```

# dockerfile
既存のコンテナをカスタマイズして、新たにイメージをビルドするための設定ファイル

```dockerfile:例
FROM python:3.6.9-alpine
WORKDIR /app
ENV FLASK_APP=app
COPY ./app /app
RUN pip install --upgrade pip
RUN pip install -r ./requirements.txt
```

# コンテナを停止して削除
```bash
docker rm -f {container_id}
```

# 便利な拡張機能
sshで開発するのは面倒なので、[Remote - Containers](https://code.visualstudio.com/docs/remote/remote-overview)を使うとremote sshと似たような開発環境が作れる
MariaDB 導入方法

# MariaDB導入

### インストール
Amazon Linux 2を利用している場合、MariaDBは 「yumコマンド」からインストールできます
```:EC2ターミナル
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install  mariadb-server mysql-devel
```

### データベースの起動
データベースを起動するには`systemctl`コマンドを利用します
```:EC2ターミナル
[ec2-user@ip-172-31-25-189 ~]$ sudo systemctl start mariadb
```
`systemctl`コマンド：
Amazon LinuxやCentOSに含まれているもので、インストールしたソフトウェアの起動を一括して行えるツールです。

データベースが起動したことを確認します
```:EC2ターミナル
[ec2-user@ip-172-31-25-189 ~]$ sudo systemctl status mariadb

● mariadb.service - MariaDB database server
   Loaded: loaded (/usr/lib/systemd/system/mariadb.service; disabled; vendor preset: disabled)
   Active: active (running) since 土 2020-02-29 07:00:11 UTC; 7s ago
  Process: 5993 ExecStartPost=/usr/libexec/mariadb-wait-ready $MAINPID (code=exited, status=0/SUCCESS)
  Process: 5957 ExecStartPre=/usr/libexec/mariadb-prepare-db-dir %n (code=exited, status=0/SUCCESS)
```
「active (running) 」と緑色の表示がされれば、データベースの起動は成功です。

### データベースのrootパスワードを設定する
yumでインストールしたMariaDBには、デフォルトで「root」というユーザーでアクセスできるようになっていますが、パスワードは設定されていません。なので、パスワードを設定する必要があります。
```:EC2ターミナル
[ec2-user@ip-172-31-25-189 ~]$ sudo /usr/bin/mysql_secure_installation
```
以下の手順で設定します
[1]`Enter current password for root (enter for none)`
現在のパスワードを入力（なければエンター）
[2]`Set root password? [Y/n]`
パスワードをセットしますか？`Y`でエンター
[3]`New password:`
新しいパスワードを入力してエンター
[4]`Re-enter new password:`
パスワードを再度入力
[5]`Remove anonymous users? [Y/n]`
匿名のユーザーを排除しますか？（誰でもログインできないようにしますか？）`Y`でエンター
[6]`Disallow root login remotely? [Y/n]`
RootでMySQLにリモートログインをできないようにしますか？という意味
セキュリティ上りモートでログインできるとまずいので`Y`でエンター
[7]`Remove test database and access to it? [Y/n]`
テストデータベースとそれのアクセスを排除しますか？`Y`でエンター
[8]`Reload privilege tables now? [Y/n]`
権限の変更を即時反映しますか？`Y`でエンター

### データベースへ接続する
```:EC2ターミナル
[ec2-user@ip-172-31-25-189 ~]$ mysql -u root -p

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 142
Server version: 5.5.64-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> 
```

## まとめ
パスワードはこれからも使うことになるのでメモしておきましょう
（一回パスワード忘れて酷い目に遭いました）
データベースの操作方法に関してまた記事を出そうと思います
DockerでRails環境を構築する(Compose V2対応)

## なんで書いたか

DockerでRails環境を構築する記事のほとんどが(更新日が新しかったとしても)Compose V2に対応していないものとなっており、見た人がそれを再生産しまくっているせいで誰もCompose V2に対応した書き方をしてくれないため。

一応今は動くけど、非推奨になってるものもあるので早めに新しい書き方に移行しようという話です。

## 既存のRailsアプリをDocker化する時

```dockerfile:Dockerfile
# Rubyは使っているバージョンに合わせる
FROM ruby:3.1.2
RUN apt-get update && apt-get install -y nodejs npm && npm i -g yarn # Rails6用(Rails7では不要)

WORKDIR /app

COPY Gemfile Gemfile.lock ./
RUN bundle
COPY . .

ENTRYPOINT ["bash", "/app/entrypoint.sh"]

CMD ["rails", "s", "-b", "0.0.0.0"]
```

```yaml:compose.yml
services:
  app:
    build: .
    volumes:
      - .:/app
    ports:
     - 3000:3000
```

```bash:entrypoint.sh
#!/bin/bash
set -e
rm -f /app/tmp/pids/server.pid
exec "$@"
```

これの3つをプロジェクトルートに置いて

```shell
docker compose up
```

で起動します。なんらかの理由で再ビルドしたい場合には`docker compose up --build`を実行します。

## 新規Railsアプリ作成時

`Dockerfile`を一部コメントアウトしておきます。`compose.yml`はそのままで。

```dockerfile:Dockerfile
# Rubyは使っているバージョンに合わせる
FROM ruby:3.1.2
RUN apt-get update && apt-get install -y nodejs npm && npm i -g yarn # Rails6用(Rails7では不要)

WORKDIR /app

# COPY Gemfile Gemfile.lock ./
# RUN bundle
# COPY . .

ENTRYPOINT ["bash", "/app/entrypoint.sh"]

CMD ["rails", "s", "-b", "0.0.0.0"]
```

以下のコマンドを実行します。`x.x.x`にはRailsのバージョンを指定してください。最新バージョンで良い場合は`-v`ごと消してください。

```shell
docker compose run app bash -c "gem install rails -v x.x.x && rails new ."
```

後はDockerfileを元に戻して`docker compose up --build`で起動します。

開発時に`rails g model`等のコマンドの入力が必要になった場合には、`docker compose run`コマンドを推している記事が多いですが、VSCodeの[Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)拡張機能を使って、ずっとコンテナの中に入った状態で開発を進めることをお勧めします（本記事ではこの辺りの詳細な解説は行いません）。

## Compose V2での変更点

V2からCompose Specに準拠しました。仕様は全部[ここ](https://github.com/compose-spec/compose-spec/blob/master/spec.md)に書いてあるので、それを読む英語力と時間がある人はそっちを読んでください。

以下は本記事に関係ありそうな部分だけまとめています。

- `docker-compose.y(a)ml`だけでなく`compose.y(a)ml`もデフォルトの設定ファイルとして認識されるようになった
    - `docker-compose.y(a)ml`は後方互換のためにしばらくサポートしているだけみたいなので、`compose.y(a)ml`の方を使った方が良いでしょう
- `docker-compose`コマンド(`docker-compose up`等で使用)が`docker compose`になった
    - `docker-compose`コマンドも一応`docker compose`コマンドのエイリアスとして今のところ使えますが、これも非推奨になる可能性があるので`docker compose`を使うようにしましょう
- `compose.yml`内で`version: '3'`のようにバージョンを記述する項目が非推奨になった
- ARMにネイティブ対応したので、特にM1Macで高速化された

## 他の記事でよく見る内容からのその他の変更点

誤解を招きがちなため、敢えて掲載しなった点がいくつかあります。

- 開発用にPostgreSQLやMySQLを用意する手順を完全に削除
    - 本記事での手順のように、他のDBを導入しなければSQLiteが使われるだけです
    - 初学者の方が練習用にRailsアプリを作成する際にはPostgreSQLやMySQLは難易度が高いと思い、スキップしています
- `docker compose build`は`docker compose up`時に自動で実行されるので記述していません
- `docker compose up -d`で起動する派が多かったですが、ログが直に見えた方が初学者にとって分かりやすいと思い、`-d`は省略しました

## 最後に

高速化などは本記事では行わなかったですが、その辺りはV2以前までと同様の手段が実行できるはずです。
【CytoscapeJS】The style value of label is deprecated for width

# 概略

[CytoscapeJS](https://js.cytoscape.org/)でノードの幅を文字の幅で取りたい時があります。
その時は以下のようにwidthを設定することで設定すれば可能です。

```ts
cytoscape({
  container: /** target dom */,
  elements: {/** 略 */},
  style: [
    {
      selector: 'node',
      css: {
        label: 'data(name)',
        width: 'label', // これ
        shape: 'round-rectangle',
        'text-valign': 'center',
        'text-halign': 'center'
      }
    },
  ],
});
```

![スクリーンショット 2022-08-11 13.56.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299962/3413148c-51d1-9c95-4c0e-365a6177fdf3.png)

しかしconsoleをみたとき、以下のようなワーニングが出てしまいます。

![スクリーンショット 2022-08-11 13.57.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299962/b1c061b5-723a-3603-13ea-892eb9252e47.png)

今回はワーニングを出さず同じ結果を出すことを目指します。

# install

```bash
npm i cytoscape @types/cytoscape
```

# やりかた

```ts
const getCharacterWidthInCanvas = (
  target: cytoscape.NodeCollection | cytoscape.EdgeCollection
): number => {
  const labelWidthPadding = 10;

  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d')!;
  const fontStyle = target.style('font-style');
  const fontSize = target.style('font-size');
  const fontFamily = target.style('font-family');
  const fontWeight = target.style('font-weight');
  ctx.font = fontStyle + ' ' + fontWeight + ' ' + fontSize + ' ' + fontFamily;

  return ctx.measureText(target.data('name')).width + labelWidthPadding;
}
```

```ts
cytoscape({
  container: /** target dom */,
  elements: {/** 略 */},
  style: [
    {
      selector: 'node',
      css: {
        label: 'data(name)',
        width: getCharacterWidthInCanvas,  // ここで使う
        shape: 'round-rectangle',
        'text-valign': 'center',
        'text-halign': 'center'
      }
    },
  ],
});
```

![スクリーンショット 2022-08-11 14.11.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299962/a5f58943-c3fc-6c60-08d9-ebef3049ee7c.png)

![スクリーンショット 2022-08-11 14.12.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299962/3e3b7716-3f91-789a-48a3-7e8b5b513b38.png)

にっこり。

表示領域はcanvasを用いているため、[measureText()](https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D/measureText)で文字幅を取得します。

しかし実際に表示しているcanvas DOMに値を突っ込むことはできないため、別途canvasを生成してそこで `measureText()` を走らせます。
[CanvasRenderingContext2D.font](https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D/font)の形式で設定するわけですが、そのために各ノードのstyleを取得します。
`fontStyle`, `fontWeight`, `fontSize`, `fontFamily`を見てみましょう。

```ts
console.log([fontStyle, fontSize, fontFamily, fontWeight]);
// ['normal', '16px', 'Helvetica Neue, Helvetica, sans-serif', 'normal']
```

できていますね。
少しパディングをつけて完成です。

# 参考

- [cytoscape/cytoscape.js#2713](https://github.com/cytoscape/cytoscape.js/issues/2713)
【MySQL学習】mysqldumpコマンド

# はじめに
MySQLの論理バックアップで使用するmysqldumpコマンドについて学習したことを簡単にまとめます。

# 検証に使用した環境
DB：MySQL8.0

# 論理バックアップについて
バックアップ手法には、論理バックアップと物理バックアップという観点があり、

論理バックアップは、
データベースのユーティリティー等を使用してバックアップする手法のこと

物理バックアップは、
ファイルシステムレベルでバックアップする手法のこと

となります。

# mysqldumpコマンド
MySQLではmysqldumpコマンドで論理バックアップを取得できます。
このコマンドではバックアップ対象を復元するためのSQLを出力します。
インスタンス全体やデータベース、テーブルごと、といった単位を指定することも可能です。

```shell
shell> mysqldump [オプション] > file_name
```
## ケース別の使い方
### 全てのデータベースをバックアップする場合

```shell
shell> mysqldump --all-databases > dump.sql
```

### データベースを指定してバックアップする場合

```shell
shell> mysqldump [オプション] --databases [オプション] データベース1 データベース2 ... > dump.sql
```

### データベースとテーブルを指定してバックアップする場合

```shell
shell> mysqldump [オプション] データベース名 テーブル名1 テーブル名2 ... > dump.sql
```

## 主なオプション
### --user (-u)
サーバーへの接続時に使用するユーザー

### --password (-p)
サーバーに接続する際に使用するパスワードです。
-pで指定した場合、オプションとパスワードの間にスペースを置けません。

### --host (-h)
ダンプするホスト名。
デフォルトはlocalhostになります。

### --port (-P)
使用するポート番号

### --all-databases (-A)
すべてのデータベース内のすべてのテーブルをダンプします。

### --flush-logs (-F)
ダンプを始める前にMySQLサーバーログファイルをフラッシュします。
※RELOAD権限が必要になります

--all-databasesオプションと組み合わせて使用した場合、ダンプされるデータベースごとにログをフラッシュします。
ただし、以下を使用した場合は例外となります。
--lock-all-tables、--master-data または --single-transaction を使用した場合。
詳細は[こちら](https://dev.mysql.com/doc/refman/8.0/ja/mysqldump.html)

### --master-data
ダンプに、ダンプされたサーバーのバイナリログ座標 (ファイル名と位置) を出力するようになります。
バイナリログ座標が出力されることで、別のMySQLサーバーをレプリケーションのレプリカとして設定するために使用できるようになります。

### --single-transaction
バックアップを1つのトランザクションで実行します。

InnoDBテーブルとして作成されている、トランザクションテーブルに効果があります。
データのダンプ前に、トランザクション分離モードをREPEATABLE READに設定し、START TRANSACTIONステートメントをサーバーに送信するため、
アプリケーションをブロックすることなく、START TRANSACTIONが発行された時点のデータベースの一貫したデータをダンプ出来ます。

### --no-data
データを出力対象外とし、データベースやテーブルの定義のみダンプするようになります。

## 注意点
### 静止点を作ってバックアップする
MySQL8.0以降でInnoDBのみを使用している場合、--single-transactionで静止点を作ることが出来ます。
しかし、他のストレージエンジンを使用している場合、トランザクションの機能がありません。
そのため、--lock-all-tablesで全テーブルをロックして静止点を作る必要があります。

# 参考文献
https://www.amazon.co.jp/gp/product/B07YNB6QLJ/ref=ppx_yo_dt_b_d_asin_title_o01?ie=UTF8&psc=1

https://dev.mysql.com/doc/refman/8.0/ja/backup-and-recovery.html

https://dev.mysql.com/doc/refman/8.0/ja/mysqldump-sql-format.html

https://dev.mysql.com/doc/refman/8.0/ja/mysqldump.html
WSL2+VS Code Neovim+ノーマルモードIME自動OFF

設定に難儀したのでメモを残します。

# 手順

[windowsでwsl2でvscode-neovimを早めにしたい](https://qiita.com/sijiaoh/items/4add320d684b7978a29f)に書いてあるとおりです。
手順としては以下のようになります。

- WSL+VS Code+VS Code Neovim環境構築
- WSL側にzenhanをインストール
    - コマンドは上記リンク先のものが秀逸なのでそのまま転記

> ```
> curl -fLO https://github.com/iuchim/zenhan/releases/download/v0.0.1/zenhan.zip
> unzip zenhan.zip
> chmod u+x zenhan/bin64/zenhan.exe
> sudo mv zenhan/bin64/zenhan.exe /usr/local/bin/zenhan
> ```

- init.vimにzenhanを利用した自動IME/ON OFFの設定を書く

```
if executable('zenhan')
  autocmd InsertLeave * :call system('zenhan 0')
  autocmd CmdlineLeave * :call system('zenhan 0')
endif
```

- VSCode再起動

# 難儀した部分

手順は上記のとおり、非常に簡単なのですが、以下らへんが分からず難儀しました

- [zenhanの作者様の紹介ページ](https://qiita.com/iuchi/items/9ddcfb48063fc5ab626c)の設定は必要なのか、どう設定するのか

  > ```
  >     "vim.autoSwitchInputMethod.enable": true,
  >     "vim.autoSwitchInputMethod.defaultIM": "0",
  >     "vim.autoSwitchInputMethod.obtainIMCmd": "C:\\users\\foo\\bin\\zenhan.exe",
  >     "vim.autoSwitchInputMethod.switchIMCmd": "C:\\users\\foo\\bin\\zenhan.exe {im}",
  > ```

  - setting.jsonに書いても読み込まれない
  - 結果、これはVSCodeVimというもっと以前からあるvscodeのvim拡張利用時に行う設定で、VSCode Neovimでは設定しない
  - ちなみにVSCode Neovimを使う場合、VSCodeVimがインストールされていれば、無効化(orアンインストール)が必要
- im-selectは必要なのか??
    - im-selectを同時に設定している紹介記事がちらほら
    - てかim-selectって何?
    - 結果、これもVSCodeVimでIMEを制御するためのやつで、今回は必要ない
- zenhanはWSLに置くのか、Windowsに置くのか
  - これはWSLでした(zenhan.exeなのでWindowsに置くと思い込んでいました)
- zenhan.exeが読み込まれない
  - Pathが通っていればどこでもOKと思っていましたが、init.vim読み込み時にログインプロファイルは読み込まれないようでハマっていました

# 余談

- 動作したときは気分があがり、よししばらくこれで日本語文章書いてくぞという感じだったのですが、書き始めてすぐ日本語入力がバグってることに気が付きます..
- 日本語入力して、ノーマルモードに戻るとき、ひとつの漢字が2回連続して入力されていたり、2文字の漢字が両方同じ漢字に置き換えられていたり(変換時は普通です)します。例えば、作業と変換してノーマルモードにすると、作作となったり..
- どういう条件かなど詳しく試していないのですが、なかなかストレスです。まだ解決策は調べていません(zenhanを使えるようにするところで力尽きた)
- それさえなければ、日本語入力してすぐノーマルモードでカーソル移動してまた入力、という操作はなかなか快適なのですが..
- ちなみに上記の設定だけだと、ノーマルモードから入力モードにするときは毎回IMEOFFになりますが、これはこれでマークダウンで箇条書きをしていて先頭にハイフンをつける場面で逆に楽だったり、入力モードにしたときのIME ON/OFFを気にしなくて良いのでいいかなと思いました。ノーマルモードにする直前のIMEの状態を復元してくれる方法もあるようなのでそれを試してみてもいいかもです
あるWebサービスの開発メモ

- この記事を書き始めたのは 2022年8月11日、山の日という祝日です
- だいぶ情報が古くなりましたので [こちらのページ]() に 2024年2月時点の手順を記載しました
- [弊社](https://unremoted.com)ではこの仕組みを使って [sirokuro.site] という、いろいろなことにシロクロをつけるサービスを開発中です
- まだまったく認知されておらず、小さくて貧しいサービスですが、その開発の道中で知り得た知見というか手順といったものをまとめています

## [技術スタック](https://qiita.com/ishi32/items/12f722004e914e9119aa)

## 開発環境
- [Intel chip の macOS PC に、Webフロントエンドの開発に必要なツールをインストールする手順](https://github.com/unrcom/devenv_mac_intelcpu)
- [Docker + Nextjs + TypeScript + mui + supabase-js + react-query + swiper の導入手順](https://qiita.com/ishi32/items/c7baded80262cd1fe429)
- [React v18 から v17 へのダウングレードについて](https://qiita.com/ishi32/items/72a4dd3763868672e2e4)
- [Safari で開発者ツールを使いたい](https://hep.eiz.jp/safari-developer-tool/)

## [本番環境](https://qiita.com/ishi32/items/de94267f52025383f61f)
- [Docker](https://qiita.com/ishi32/items/23810529e7c036739d01)
- [Supabase](https://qiita.com/ishi32/items/08e08b19b0cbdbf6c610)
- [PostgreSQL チート (随時加筆中)](https://qiita.com/ishi32/items/eaa4c1f3a4cf8f3d4170)
- [NEXT.jp](https://nextjs-ja-translation-docs.vercel.app)
  - [Hydration時にReact.hydrate()による警告が発生するケースとその解決方法](https://nishinatoshiharu.com/next-hydration-warning-resolution/)
  - [Next.jsでOGP・metaタグを設定する方法](https://qiita.com/TK-C/items/cd34d0f6d4b001053443)
  これだけではダメでして、次の SSR を実行しないと OGP を読んでもらえませんでした
  - [SSR を実行する](https://qiita.com/ishi32/items/8f2957b0de4d4c563350)
  - [image のオプション全部触ってみる](https://www.forcia.com/blog/001561.html)
  - [画面サイズを取得する方法](https://zenn.dev/developanda/articles/daf34873fe4ef4)
  - [WEBフォントを追加する](https://penpen-dev.com/blog/next-webfont/)

## 開発メモ
- [react-query (随時加筆中)](https://qiita.com/ishi32/items/fc0157922fd0c4fc73b6)
- [JavaScript チート (随時加筆中)](https://qiita.com/ishi32/items/aa1db70e2176652dc97f)
- [React, JSX チート (随時加筆中)](https://qiita.com/ishi32/items/ce86885045d69bbfb2c9)
- [css (随時加筆中)](https://qiita.com/ishi32/items/df1e47fbc8457e3be6be)
- [mui (随時加筆中)](https://qiita.com/ishi32/items/99d9df23f5c9e5e75687)
- Swiper
あまり書けることがないのですが、なかなか正解に辿りつけなかった問題をまとめておきたいと思っています。
  - [送りと戻しのボタンの色や大きさを変えたい (これから書く予定です)]()
  - [1つのスライドに複数のリンクやコントロールを埋め込みたい (これから書く予定です)]()
- [よく使う Linux コマンド (随時加筆中)](https://qiita.com/ishi32/items/e74a4345b4782ad73f21)
- [Git](https://qiita.com/ishi32/items/f569aa429f942840f135)
- [Next.js のサイトに Google Tag Manager 経由でGoogle Analytics(GA4)を導入する](https://egashira.dev/blog/nextjs-gtm)
- [【フォーム送信を実装】Getform.ioの使い方を解説](https://ralacode.com/blog/post/create-contact-form-with-getform-io-in-react/)

## その他
- [気分を上げる](https://www.youtube.com/watch?v=pzJM0EjuAMM)
Jenkins 構築（Mac・Docker）

# はじめに
Mac・Docker での Jenkins の構築・使い方を残す。

# 構築
以下を実施して、Jenkins を動作させる。
```
// Jenkins コンテナを取得
docker pull jenkins/jenkins
```
```
// 実行
docker run -p 8080:8080 -p 50000:50000 jenkins/jenkins
```
完了したら、http://localhost:8080 をブラウザで表示させる。
すると、こんな感じのページが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477044/9150ff04-201c-007f-0747-c75903e0c306.png)
ここでのパスワードは以下で取得可能。
```
// 動作しているコンテナを確認
$ docker ps

// 以下のように表示される
CONTAINER ID   IMAGE             COMMAND                  CREATED         STATUS         PORTS                                              NAMES
a711c1432e5f   jenkins/jenkins   "/usr/bin/tini -- /u…"   2 minutes ago   Up 2 minutes   0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp   condescending_boyd
```
```
// ログ出力
$ docker logs -f condescending_boyd

// 以下のように表示される
*************************************************************
*************************************************************
*************************************************************

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

[password]

This may also be found at: /var/jenkins_home/secrets/initialAdminPassword

*************************************************************
*************************************************************
*************************************************************
```
[password] に表示されている値を、先ほど起動したブラウザの Administrator password に貼り付けて continue。
すると、このような画面に遷移する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477044/c72469c0-602c-404c-4942-00c3290006a2.png)
よくわからなければ、install suggested plugins を選択すれば OK。
あとは、表示された通り、Username とか Password とか設定する。


# 参照
- [Install and setup Docker and Jenkins — Mac OS](https://blog.devgenius.io/install-and-setup-docker-and-jenkins-mac-os-machine-738b7c23bf91)
【ホームディレクトリ】「~（チルダ）」って何ですか？


# 「~（チルダ）」って何ですか？
先日Linux環境を操作している時に、こんなやり取りがあった。

後輩ちゃん「**黒い画面に表示されている"にょろ"ってなんですか？**」
後輩ちゃん「いつもはカレントディレクトリが表示されていると思うんですけど」

> `[kouhaichan@hostname ~]#`
> 上記「~」のこと

すずこ「にょろ？チルダのことだね」

後輩ちゃん「チルダ...？」

すずこ「波線のことをチルダって言うんだよ」
すずこ「チルダは、Linux環境における**ホームディレクトリ**を表現しているんだよ」

後輩ちゃん「ホームディレクトリ...？」

すずこ「ユーザーのお家のことだよ」

後輩ちゃん「...」

すずこ（カレントディレクトリは知ってて、ホームディレクトリは知らんのかい）

ということで、ホームディレクトリについての説明をすることになった。

## Linuxのホームディレクトリについて
すずこ「Linuxを使用するときにログインするユーザーがいるのは知っているかな？」

後輩ちゃん「はい。**kouhaichan**っていうユーザーを指定してログインしました」

すずこ「そう！Linuxに限らず、どんなOSでも何かしらのユーザーでログインして操作するよね」
すずこ「そのユーザーがファイルを作ったり、ディレクトリを作ったり...」
すずこ「自由に操作できる領域のことを**ホームディレクトリ**って言うんだよ」

後輩ちゃん「なるほど、自由に使えるお家みたいだからホームディレクトリっていうんですね」

すずこ「そして、そのホームディレクトリは基本的にはそのユーザーしか操作できないんだ」
すずこ「他のユーザーのホームディレクトリは干渉できないってこと」

## ~（チルダ）について
後輩ちゃん「ということは、黒い画面に"にょろ"が表示されていた場合は、カレントディレクトリがホームディレクトリってことなんですね！」

すずこ（急に饒舌だな）
すずこ（というより、黒い画面て...）

後輩ちゃん「ところで、ホームディレクトリって場所はどこにあるんですか」

すずこ「カレントディレクトリを確認するコマンド`pwd`って打ってごらん」

後輩ちゃん「`/home/kouhaichan`って表示されました」
後輩ちゃん「なるほど、/home 直下にユーザー毎のお家が作成されるんですね」
後輩ちゃん「まるでマンションですね！」

すずこ（マンション...？）

後輩ちゃん「だって、他のお家には干渉できないんですよね」
後輩ちゃん「私も隣のお部屋に勝手に入ったり、生活したりできないですもん！」

すずこ（なるほど...）
すずこ（権限の話はまた今度だな）

## rootについて
すずこ「ところで、Linuxには**root**と呼ばれる、最高権限を持ったユーザーがいるのはご存じ？」
すずこ「いわゆる、管理者権限と呼ばれるユーザーのこと」

後輩ちゃん「聞いたことはありますが、具体的にどんなことができるユーザーなんですか？」

すずこ「例えば、他ユーザーのパスワードを変更したり...」
後輩ちゃん「お部屋の鍵を勝手に交換したり！（食い気味）」

すずこ「パッケージをインストールしたり...」
後輩ちゃん「んー。マンションに駐輪場作ったり、床暖導入したり、オプションを導入したり...？」

後輩ちゃん「普通の住民（ユーザー）だとできないことができるユーザーですね！」
後輩ちゃん「まるで、マンションのオーナーだ」

すずこ（わ、分かりやすい）

後輩ちゃん「ってことは、rootユーザーは他ユーザーのホームディレクトリで操作出来たりするんですかね」

すずこ「うん、できちゃう」

後輩ちゃん「やっぱり！マンションのオーナーはマスターキー持ってるから、だれの部屋でも入れちゃいますもんね」

すずこ（この子、物事のエッセンスを取り込むの上手だな）

---

と、こんなやりとりがありましたとさ。
Gistに画像を添付する

ファイルの拡張子をMarkDown「~.md」をつけると、画像ファイルを貼り付けることができるようになります。
（別サイトに画像をアップロードしてそのURLを記載する必要はありません）


1. 画面のハードコピー(Windowsキー＋Shift＋S)を取得後、
貼り付けたい位置にペースト(Ctrl+V)をするだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/999eb24f-a51a-a2bc-330a-49c42d4b84f4.png)

2. 画像が自動的にアップロードされ、そのURLがペーストした位置に書き込まれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/15ecf054-6b53-b0fa-01de-b696b7278c5f.png)

3. プレビューすると画像が表示されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/41113f40-6238-f17c-28d8-73dcef27fe06.png)
PowerShellの二重引用符文字列のクセがすごい

先入観は怖い。

## 環境
* PowerShell 5.1

## 二重引用符文字列のクセ

```powershell
"""" # 文字列 '"'　　二重引用符の中で二重引用符を書くときは二つ並べます。
"$(1+1)" # 文字列 '2'　　二重引用符の中で$()としたら式を中に書けます。
"$("""")" # 文字列 '' 👈 いや '"' じゃないんかい！

"`"" # 文字列 '"'　　二重引用符の中で二重引用符を書くときはバッククォートでエスケープします。
"$("`"")" # 評価不可　👈 実行すらできひんのかい！
```

## 理由

式`$()`よりも先に`""`の処理が行われるから。

```powershell
"$("""")" => "$("")"
"$("`"")" => "$("`")"
```

公式ドキュメントには`コマンドに渡される前`に式が評価されると書いてある。
おそらく、文字列として処理してからコマンド（`Write-Host`？`Set-Variable`？）実行前に式が評価される。

https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-5.1

> 二重引用符で囲まれた文字列は 、展開可能な文字列です 。 ドル記号 ($) の前に付いた変数名は、処理のために文字列がコマンドに渡される前に、変数の値に置き換えられます。

> また、二重引用符で囲まれた文字列では、式が評価され、結果が文字列に挿入されます。

> 文字列に引用符文字を含める
> 二重引用符で囲まれた語句を二重引用符で囲みます。

## 対応方法
「二重引用符の中で二重引用符を使いたいときは重ねる。」が基本ルールなので、書きたい式の二重引用符を2倍すればよい。

```powershell
"""" # 書きたい式
"""""""" # 二重引用符2倍
"$("""""""")" # 文字列 '"'
```

式を入れ子（二重引用符文字列中の式に二重引用符文字列の式）にするとさらに2倍する必要がある。

```powershell
"$(""$("""""""""""""""")"")" # 文字列 '"'
```

ちなみにシンタックスハイライトはあてにならない。

## 回避策
一度変数に入れれば大丈夫。（先に式を実行する）

```powershell
$a = """"
"$a" # 文字列 '"'
"$($a)" # 文字列 '"'

"$(($a = """"))" # 文字列 '' 👈 これはダメ❌
```

いっそのこと原点回帰で結合するのもアリ。（式を二重引用符内に書かない）

```powershell
"" + """" + ""
```

## 検証データ

| 二重引用符数 | 入力 | 出力 | `""`処理後 |
|-:|-|-|-|
| 0 | `"$()"` | 空文字列 | `"$()"` |
| 1 | `"$(")"` | ❌評価不可 | `"$(")"` |
| 2 | `"$("")"` | ❌評価不可 | `"$(")"` |
| 3 | `"$(""")"` | 空文字列 | `"$("")"` |
| 4 | `"$("""")"` | 空文字列 | `"$("")"` |
| 5 | `"$(""""")"` | ❌評価不可 | `"$(""")"` |
| 6 | `"$("""""")"` | ❌評価不可 | `"$(""")"` |
| 7 | `"$(""""""")"` | `"` | `"$("""")"` |
| 8 | `"$("""""""")"` | `"` | `"$("""")"` |
| 9 | `"$(""""""""")"` | ❌評価不可 | `"$(""""")"` |
| 10 | `"$("""""""""")"` | ❌評価不可 | `"$(""""")"` |
| 11 | `"$(""""""""""")"` | `""` | `"$("""""")"` |
| 12 | `"$("""""""""""")"` | `""` | `"$("""""")"` |
| 13 | `"$(""""""""""""")"` | ❌評価不可 | `"$(""""""")"` |
| 14 | `"$("""""""""""""")"` | ❌評価不可 | `"$(""""""")"` |
| 15 | `"$(""""""""""""""")"` | `"""` | `"$("""""""")"` |
| 16 | `"$("""""""""""""""")"` | `"""` | `"$("""""""")"` |
| 17 | `"$(""""""""""""""""")"` | ❌評価不可 | `"$(""""""""")"` |
| 18 | `"$("""""""""""""""""")"` | ❌評価不可 | `"$(""""""""")"` |
| 19 | `"$(""""""""""""""""""")"` | `""""` | `"$("""""""""")"` |
| 20 | `"$("""""""""""""""""""")"` | `""""` | `"$("""""""""")"` |

## おわり
文字列リテラルに変数や式を埋め込むことを文字列補間(string interpolation)というのだが、上記のような仕様になっている言語はほかにあるのだろうか？

## 追記

よく考えると、これが実行できるのが不思議だ。
```powershell
"$("x")" # 文字列 'x'
```

文字列の始まり`"`から終わり`"`まで解析するとしたら、`"$("`と`x`と`")"`に分かれるように思える。
`"$("`のみでは評価不可なので、解析中に`$()`を認識していると思う。
文字列解析中に`$()`認識しているのに、式中の`""`を`"`にしているのは意味が分からない。

PowerShellよくわからない。どうしてこうなった。
[React]react-modalのparent要素を指定したい。

# 背景
nextjsでモーダルの実装にreact-modalを用いた。
https://github.com/reactjs/react-modal

このライブラリではモーダルはデフォルトでdomのルートに配置されてしまう。
相対的な位置に置く際には待ったのでまとめる。
```modal.tsx
<div>
  <ReactModal {...props} />
</div>
```
```tsx:domの表示
<div>
</div>
<ReactModal ... />
```

# やりかた
parentSelectorを指定すれば良い
https://reactcommunity.org/react-modal/#custom-parent
```tsx
const Modal = ({ id }) => (
  <div>
    <ReactModal {...props} parentSelector={() => document.getElementById('id')} />
  </div>
)
```

:::note warn
はまったとこ
1. 親要素からrefを渡し、react-modalにref.currentを渡すとエラーになる。
ref.currentが最初のレンダリングタイミングではnullになっており、appendChildができないため。
2. また、親要素でMath.random()で作ったidを渡した時もうまくいかなかった。

いずれにせよ、strictモードによるcomponentの描画が2度行われるため意図した挙動にはならなかった。
https://ja.reactjs.org/docs/strict-mode.html
:::
ADX for Unityで、物理挙動にランダム性のある効果音をつける

# はじめに

Unityには標準で物理演算エンジンが備わっているので、簡単に物理挙動を実装することが出来ます。しかし、その衝突に適切な音を発生させるのは、音量の調整や音のバリエーションの用意が必要になり、大変です。ましてや大量のオブジェクトがぶつかる場合はなおさらです。

本記事ではUnityとサウンドミドルウェア「ADX for Unity」を用い、ランダム性があり物理的な状態を考慮した効果音の実装例を紹介します。

この記事は「ADX2+UE4で、物理挙動にランダム性のある効果音をつける」のUnity版です。元記事作者の[Sig](https://qiita.com/SigRem )さんの許可を得て作成しています。

[https://qiita.com/SigRem/items/77644c292a1f3e1e16fd](https://qiita.com/SigRem/items/77644c292a1f3e1e16fd)

# 前提

### 動作確認環境

Windows 10 Home 20H2
Unity 2020.3.27f1  + ADX LE Unity SDK 3.06.03
CRI ADX LE Tools for Windows 3.46.09

### 前提記事

CRI ADXの導入方法や基本的な操作については、以下の記事を参照して下さい。

Unityのサウンド機能をADXで強化する
[https://qiita.com/Takaaki_Ichijo/items/16e6501fc07f5b3b3377](https://qiita.com/Takaaki_Ichijo/items/16e6501fc07f5b3b3377)

# やること

- AtomCraftでキューを作成
- パラメータを調整し、音に性質を追加する
- Unityにインポート
- テストシーンを作成、サウンド処理を実装する

# 実装

## AtomCraft側

まずは、再生する音データの作成を行います。ADXにおいては、再生用のデータはUnityとは別のツール「AtomCraft」を使います。その手順については、元の記事（UE4向け記事）の同名の項と同じになりますので省略しています。
本記事の手順を試す場合は、まず元の記事の[該当項目](https://qiita.com/SigRem/items/77644c292a1f3e1e16fd#atomcraft%E5%81%B4)を進めてから本記事を進めてください。UE4版との違いとして1点、「Atomキューシートバイナリのビルド」画面で、一番左下のオプション「UnityAssets出力」にチェックを入れるのを忘れないようにして下さい。

## Unity側の実装

### キューシートのインポート

AtomCraftからエクスポートしたファイルをインポートします。

### スクリプトの作成

以下のようなRandomHit.csを作成します。

```RandomHit.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RandomHit : MonoBehaviour
{
    public CriAtomSource criAtomSource;

    private void OnCollisionEnter(Collision collision)
    {
        criAtomSource.Play();
    }
}
```

動作は単純で、オブジェクトが何かにぶつかったら音を再生します。

### テストシーンの作成

以下のようなシーンを作成します。

![テストシーン](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576800/93179ab3-27ef-d453-29db-28110b03dc56.png)

- CriWareLibraryInitializer、CriWareErrorHandler
    - 基本コンポーネント、GameObject＞CRIWAREから作成
- CRIWARE
    - 自動生成
- Cue_Impact_Metal(CriAtomSource)
    - 前項でインポートした音源
- Plane
    - デフォルトでOK、色を変えると見分けやすい
- Cube
    - Rigidbodyをアタッチ
    - 先程作成したRandomHit.csをアタッチ
    - CriAtomSourceにCue_Impact_Metal(CriAtomSource)を設定

### テストシーンの実行

ここまで出来たら忘れずに保存し、実行しましょう。
Cubeを上から落としたり、Ctrl+Dで増やしたりして衝突させて音を鳴らします。AtomCraftで設定した通り、ランダム性のある衝突音が確認できます。

## 応用

場合によってはこのままでも問題ないですが、ほんの少しだけ当たった場合や勢いよく当たった場合でも同じように音が鳴ってしまいます。そんな状況をカバーするために改良を加えます。

### スクリプトの改良

RandomHit.csを以下のように修正します。

```
    private void OnCollisionEnter(Collision collision)
    {
        if (collision.impulse.magnitude < 1) return;

        criAtomSource.volume = Mathf.Clamp( collision.impulse.magnitude / 15, 0, 3);
        
        criAtomSource.Play();
    }
```

collision.impulse.magnitudeは衝突による運動量の大きさを取得することができます。
よって、if文では小さな衝突の場合音がならないようにし、次の文では勢いに応じてボリュームを変化させる、という処理をしています。

### 破壊音などのバリエーションを加えたい

さらに大きな衝突が起きた場合に破壊音を鳴らしたい、というケースがあるかもしれません。しかし、今回利用した「ランダムノーリピート」のキュータイプには、特定の音を選択して鳴らすという方法がありません。
そのため、別のキュータイプを利用する、もしくは別のキューシートとして破壊音を用意しコードの方で衝突音・破壊音を鳴らし分ける、といった工夫が必要になります。
PyTorch入門(part-1) - パーセプトロンの可視化

# この記事では.

今更Deepやり始めたのでメモ程度です。
基本的に他記事をなぞり、自分の理解のために可視化などの回り道をした部分のみをまとめる。

今回はMNISTで単純パーセプトロンで分類する。
そのときにどのように重みが更新されているのかを可視化している。

# モデル
単純パーセプトロンなので特段記載する必要なし。

```python
class NN(nn.Module):
    def __init__(self):
        super().__init__()
        self.layer = nn.Linear(28*28, 10) # 画像サイズ:28*28, 分類:0~9
        
    def forward(self, input_data):
        input_data = input_data.view(-1, 28*28)
        input_data = self.layer(input_data)
        return input_data
```

可視化しているだけなので lr, epoch, batch などの条件は省略する。

# 学習工程の可視化
重みは以下で layer.weight, layer.bias を確認できる。

```python
model.state_dict()
```

任意のタイミングで以下のコードを差し込めばOK。これで 0~9 の重みの更新が可視化される。
PyTorchはtensor型でデータを扱うがplot時はnumpyに変換する必要がある。（もしかしたらないかもしれんが・・）
```python
# 重み tensor > numpy
weights = [weight.numpy().reshape(28,28) for weight in model.state_dict()["layer.weight"]]

# subplotで 0 ~ 9の重みを可視化
plt.figure(figsize=(30,6))

for i, weight in enumerate(weights):
    plt.subplot(1, len(weights)+1, i+1)
    plt.imshow(weight)

# これがないとprintなどのタイミングが狂う
plt.show()
```

最初はランダムで初期値設定しているのでノイズにしか見えない。
![スクリーンショット 2022-08-11 13.02.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283053/a1cc8810-db35-b174-ae08-da173a5d9962.png)

最後は 0~9 が浮き上がっているように見える。
![スクリーンショット 2022-08-11 13.03.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283053/3c5c43a0-8493-0474-b5ab-b63d287f93dd.png)

# 予測の可視化
上記の重みと画像を掛け合わせる。

```python
# テストデータ
test = test_data[0].numpy().reshape(28,28)

# subplotで 0 ~ 9の重みを可視化
plt.figure(figsize=(30,6))

for i, weight in enumerate(weights):
    plt.subplot(1, len(weights)+1, i+1)
    plt.imshow(test*weight, vmin=-0.3, vmax=0.3) # 画像*重み, 最大値・最小値は適当
```

元の画像が5で重みをそのまま掛け合わせた結果（0~9)
3,5,6,8あたりが似ている。5が一番色付けされている気がする。
![スクリーンショット 2022-08-11 13.23.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283053/8f22a3c3-3f12-2ffa-e864-a3f3c51fe4ea.png)
【Rails】Guardの導入

## 導入方法
GemfileにGemfileの :test グループと :development グループguard-rspec を追加。

```php:Gemfile
group :development, :test do
  gem 'guard-rspec', require: false
end
```

`bundle install`を実行する 

```
$ bundle install
```

`Guardfile`を追加する。

```
$ bundle exec guard init rspec
```


```
$ bundle exec guard
```
pandasでダウンサンプリングをする


## やりたいこと

深層学習(lstm)で時系列データを扱うのだが、サンプリングレートが高く
シーケンスあたりの情報量が少なそうであったり、学習時にメモリを圧迫したりするので、
いい感じにダウンサンプリングしたい。


## サンプルデータ作成

20000フレームの三次元のデータを想定。
処理結果の整合性がとりやすいように単調増加なデータを作成。

~~~python
npy = np.array([np.arange(1,20000), np.arange(1,20000)*2, np.arange(1,20000)*3]).T
df = pd.DataFrame(npy, columns=["x", "y", "z"])
df
~~~

結果

![a.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/e28c89ea-7f73-c0cf-ea29-a99cb76f612e.png)

## くし型関数っぽくやる

シンプルな方法。データを10フレーム毎に取得する。

~~~python
t   = 10
_df = df.copy()
_df = _df[::t]
_df
~~~

結果

![b.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/105cbd92-0d5c-5f07-5856-d35fea603bd7.png)


## 任意の幅でデータを取得し平均をとる

任意の窓幅を定義するにはgroupbyを使うと処理が早かった。
以下の例はindexを10で割ったときの商をグループの基準とし、
10サンプルの平均をとることでリサンプリングしている。


~~~python
t   = 10
_df = df.copy()
_df = _df.groupby(_df.index//t).mean()
_df

~~~

結果

![c.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/4dd3798a-fd12-4d73-1716-ff9d58a024af.png)


## 任意の窓幅でデータを取得し自作関数を適用する

概念は上記の例と同じだが、自作関数を適用するver。
どうやらgroupが複数の列を持つ場合、列ごとに処理を適用する設定らしいので、
関数の入力はseriesとしている。

以下の例は、10サンプル毎の最大値か最小値をランダムに取得し、
リサンプリング結果としている。

~~~python
def random_choice(series):

    npy = series.values

    retval = np.random.choice([npy.min(), npy.max()], 1)

    return retval

t   = 10
_df = df.copy()
_df = _df.groupby(_df.index//t).agg(random_choice)
_df

~~~

結果

![d.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/2766ff41-956f-b051-f274-983027ebdc39.png)



## 参照

https://pandas.pydata.org/pandas-docs/stable/user_guide/groupby.html
PHP Docker環境でMysql DBに接続する際の注意点

## はじめに
Dockerについての解説はしない
DockerでPHP環境が構築できているのが前提

## PHPからDBに接続

適当なファイルを作成する
内容を記述

```php
<?php
// Docker環境下ではhostはコンテナ名
const DB_HOST = 'mysql:host=mysql;dbname=udemy_php;charset=utf8';

// userとpassword
const DB_USER = 'php_user';
const DB_PASSWORD = 'password123';

// 例外処理
try {
  $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD);
  echo '接続成功';
} catch(PDOException $e) {
  echo '接続失敗' . $e->getMessage() . "\n";
  exit();
}
```

## 注意点
*DB_HOSTの*`mysql:host=mysql`はコンテナ名を指定している
厳密にいうとコンテナのipアドレスを指定しているのだが、コンテナ名を書けば自動で割り出してくれるらしい
これによりコンテナを立ち上げるたびにipアドレスが変わっても対応せずに済む

XAMPやMAPM環境ではlocalhostと指定するためその方法でやろうとすると詰む

Dockerfileで使用しているImageによっては`PDO`がない可能性がある
Dockerfileの`RUN`に`docker-php-ext-install pdo_mysql pdo_pgsql`を加えてインストールする

`php:7.2-apache-stretch`には含まれていないようだが、`php:7.4-apache`には含まれている
`stretch`には含まれていないのかな？？ *確認はしていない*
エクストリームプログラミング入門のペアプログラミングのまとめ翻訳

ケントベック氏のこのツイートで、戦略的に最も重要な"変"なことってなんだろうと興味を惹かれて一連のツイートを読んだので、せっかくなので許可をいただき翻訳（意訳）しました。

https://twitter.com/KentBeck/status/1557385381963657217

ツイート主は[Andrew Edstrom](https://twitter.com/andrewedstrom)氏で、bioによるとフリーランスのエンジニアでアジャイルレトロスペクティブに関するアプリケーションを開発している方なのだそうです。

文中の “Extreme Programming Explained” は**XPエクストリーム・プログラミング入門―変化を受け入れる** という日本語訳にもなっているケントベック氏の書籍です。書き終わってからその書籍が手元にあることに気づきました。訳書とは少しノリが違う部分があります。ペアを交代することをペアチェンと訳しましたがローカル用語かもしれません。

---

https://twitter.com/andrewedstrom/status/1557173564872175616

ケントベックによる**XPエクストリーム・プログラミング入門**はペアプログラミングをしているチームのバイブルになっています。それは評判に値するものです。

ペアプログラミングのアイデアを世に広める助けになったにもかかわらず、ペアプログラミングの節はたった2ページしかありません！

何が述べられているか、恐らくあなたは驚くでしょう:

#### 1. すべてのプロダクションコードをペアプログラミングしましょう。

なぜなら

- 職務に集中できる
- チームのこと以外に気が逸れなくなる
- あなたがイライラしたりハマったとき、あなたのペアがドライバーに代わり、イライラを減少させる
- アイデアを思いついたり明確にする

#### 2. ”ペアプログラミングはプログラミングであると同時に二人の間の対話（かつ分析かつ設計かつテスト）であり、プログラムをよりよくすることの試みである”

その鍵は双方が能動的に改善を試みることです。

もし一方がペアプログラミング中に電話していたら…それは問題です！

#### 3. もしあなたがあるアイデアに取り組んだりプロトタイプを一人で作るとしても、それは全く問題ないです！

ソロで行ったことの（コードではなく）考えをチームに共有しましょう。

あなたがソロで書いたどんなコードであっても、後でペアで再実装されるべきです。

#### 4. ペアプロは疲れます。ほとんどのプログラマーは1日に5，6時間程度が限度です。

私がこれまで見てきたほとんどのXP組織はこのことを無視していて、プログラマーにミーティング以外の100％をペアでやることを期待してしまっています。

#### 5. ペアプロ中はたくさんの水を飲みましょう。体に良いですし、頻繁な小休憩を取ることになります。

#### 6. ペアをよく回しましょう。理想的には2時間毎に

そんなに頻繁なペアチェンを実践しているのは見たことがありませんでした。ほとんどのチームは1日か2日にペアチェンします。

いくつかのチームは1週間に一度しかペアチェンしません。ですがそれは普通はあまりうまくいきません。

#### 7. (ここから少し変になってきます) あなたのペアのパーソナルスペースを尊重しましょう。

あまり近くに座ってはいけません。「近すぎる」がどれくらいなのかは個々人の文化的背景から異なります。

#### 8.もしあなたがペアの人を異性として好きになってしまったら、気持ちのほとぼりが冷めるまでその人とはペアにならないようにしましょう。

もしその気持ちがお互いのものであってもその気持ちは抑えましょう。もしチームメンバーと付き合いたいと思ってしまったら、そのどちらか一方がチームを離れるべきでしょう。

#### 9.もしペアプロによってあなたが不快になるようなら、マネージャーや人事など安全に相談できる人に相談しましょう。

---

以上です！

個人的には「キモいことするな。そういうペアを放置するな、デートしたり口説いたりするな」ということに半分のセクションを費やしていることに驚きました。

でも、彼の言う通り。そういうことはペアセッションを台無しにし、多くのトラブルを引き起こすでしょう。

---

以上翻訳
メモ書き作成中　FAST API

FAST APIとは
--
-
webフレームワーク、高速であることが特徴

ここがいいよ！FAST API
-
*直感的でわかりやすい
*公式ドキュメントが豊富
    日本語も豊富
+自動ドキュメント生成機能がすばらしい
　pythonの型ヒントが肝になる
　Swagger UIと連携
+バリデーション機能の実装が簡単
　バリデーションとは、入力されたデータが規定や仕様に合っているかを確認する機能
　今回ではAPIにリクエストされるデータ
　例）入ってくる型がint型になっているかなど（もちろん型が違えばバグの温床になる）

初学者がAPIをpythonで学ぶならFAST API一択
中級者ならDjangoのAPIフレームワークを学んでもいい

型ヒントとは
-

型注釈をつけることを型アノテーションという
↑これがFASTAPIには重要になってくる！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602767/01a9cb37-7b78-f671-99e1-42520392c7c0.png)

FASTAPIの公式ドキュメント
-
https://fastapi.tiangolo.com/ja/