OmniAICreator/Qiita-1.07M huggingface dataset:
インストール不要でキー配列を変更する(Windows)

# 結論：インストール不要でWindowsのキー配列を変更できるサイトを作ったよ
https://map-scan-code.soncho-works.com/

エンジニアもエンジニアじゃない人も、キー配列を最適化して生産性を上げよう！

# キーボードって無駄多くね？
こんにちは。そんちょーと申します。
突然ですが、キーボード、特に日本語キーボードには無駄があるなあと感じることはないでしょうか？私はずっと感じています。

大前提として、その人が一番使いやすいと感じるならその配列が正解です。それでバリバリコードを書いて最強のエンジニアになってください。

私としては、例えば「全角/半角」「左Ctrl」「矢印キー」「Enter」あたりが使用頻度が高い割に遠いなと思っています。
反対に、「CapsLock」「無変換」「変換」あたりは使わない人も結構いるのに押しやすい位置に陣取っているなと思います。
ま、私の好みの話です。

エンジニアなら、非効率なものは改善しましょう。
私はAutoHotKeyというWindows用のキーマッピングツールが好きで、プライベートではそれでキー配列を改造しています。
[私の愛用しているマッピング](https://soncho-works.com/2022/06/03/my-ahk/)
結構いろいろ弄れるので、是非使ってみてください。

# 社内規則「前例が無いのでインストールだめです」
新卒でSIerに入社してびっくりしました。
いやいや、AHKは結構有名なツールだし、エンジニアは~~楽する~~生産性を上げるのに全力でいるものでしょって思ってたので、頭の固さにビビりました。
どうやら社内規則として「安全だと認められた」ソフトしかインストールしちゃだめらしいです。
何を持って安全と証明するのかという議論を一通りしましたが、残念ながら私には「規則だから」の壁を壊すことはできませんでした。

# 俺「インストール不要なら問題ないんすね？」
規則を変えられないなら規則の抜け穴を探しましょう。
ということでインストール不要でキー配列を変更できるWebサイトを作りました。
https://map-scan-code.soncho-works.com/
変更前のキーと変更後のキーを指定して、「キー変更ファイルを作成」ボタンをクリックするとファイルがダウンロードされます。それを実行してWindowsを再起動すればキーが入れ替わってます。

## 簡単な仕組みの説明
仕組みとしては、Windowsのキーマッピングを管理しているレジストリを書き換えています。
「キー変更ファイルを作成」では、レジストリを書き換えるファイルを生成しています。

もう少し詳細な仕組みは作ったサイト内にも記載してあるので、ちゃんと知りたい方はそちらをご確認ください。
https://map-scan-code.soncho-works.com/mechanism

## 一応セキュリティの話
- ダウンロードした.regファイルを起動するまで、このサイトはPCに影響を与えません。
- サイト内に[キーマッピングの仕組み](https://map-scan-code.soncho-works.com/mechanism)と、[キーマッピングとバイナリの対応表](https://map-scan-code.soncho-works.com/scancode)を記載してあります。これを読めばダウンロードした.regファイルが安全かどうかはご自身で検証可能なはずです。
- インターネット上の全てに言えることですが、最後は自己責任です。私としては悪意のあるものは仕込んでないです。

この辺で許してもらえないでしょうか。

# みんな、効率化しようぜ！
非エンジニアでも問題なく使えるように設計したつもりです。
そもそもキーボードは英語圏の人のために設計されてるので、それを日本語用に使う時点でディスアドバンテージなんです。
日本の生産性を上げるためにも、「インストール不要で簡単に使えるキーマッピングツール」が必要だと思って作りました。

是非使って生産性アゲアゲでいきましょう。
https://map-scan-code.soncho-works.com/
SQLログの"?"を変換するツール

## SQLログの"?"を変換するツール
SQLログに出力される"?"を実際の値に置き換えるツール。

## やりたいことのイメージ
アプリログなどに出力されるSQLログ
```
select a, b, c from table where aa = ? and bb = ? and cc = ?
Param:arg1,arg2,arg3
```
"?"を以下のように実際の値に置き換えるツール
```
select a, b, c from table where aa = arg1 and bb = arg2 and cc = arg3
```

## 前提(注意点)
今回のツールはコマンドプロンプトで実行するよう作成しています。

## 使い方
 1. 任意のディレクトリにファイルを格納
    - file(ディレクトリ)
      - args.txt
      - input.txt
    - IoTest.java
    - go.bat
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527379/066aefa4-4946-ee15-a56a-3723b58f3472.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527379/1c20a9c4-4b62-ebf3-6e8e-50f8c8677772.png)

 2. input.txt
置換前の文言を記載
例）select a, b, c from table where aa = ? and bb = ? and cc = ?
 3. args.txt
置換文言を記載。
※カンマ区切り
例）arg1,arg2,arg3
 4. 実行
go.batを実行。
実行すると
"file/output.txt"が出力される

## ファイル内容
### go.bat
```
echo off
cd ./
javac IoTest.java
java IoTest
pause
```
### IoTest.java
```
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

class IoTest {
	public static void main(String[] args) {
		FileReader inputFile = null;
		String[] argsFile;
		FileWriter outputFile = null;
		try {
			// 置き換え前ファイル読み込み
			inputFile = new FileReader(new File("./file/input.txt"));
			// 置き換え文字列ファイル読み込み
			argsFile = getArgsFile();
			// 置き換え後ファイル作成
			outputFile = new FileWriter(new File("./file/output.txt"));
			
			int argsIndex = 0;
			int ch = inputFile.read();
			while (ch != -1) {
				// 書き込み文字取得
				char wch = (char) ch;
				
				// 変換確認
				if (isConvertChar(wch)) {
					// 変換書き込み
					outputFile.write(argsFile[argsIndex]);
					argsIndex++;
				} else {
					// そのまま書き込み
					outputFile.write(wch);
				}

				ch = inputFile.read();
			}
			
			// 処理完了後はクローズ
			inputFile.close();
			outputFile.close();
		} catch (Exception e) {
			System.out.println(e);
		}
	}

	private static String[] getArgsFile() throws Exception {
		String[] result;
		
		Path path = Paths.get("./file/args.txt");
		try {
			String str = Files.readString(path);
			result = convertArgsFile(str);
		} catch (Exception e) {
			System.out.println(e);
			throw e;
		}
		
		return result;
	}

	private static String[] convertArgsFile(String argsFile) throws Exception {
		String[] result = argsFile.split(",");
		return result;
	}

	private static boolean isConvertChar(char target) throws Exception {
		boolean result = false;

		if (target == '?') {
			return true;
		}

		return result;
	}
}
```
Android Studioのメモリーサイズを変更する方法

# はじめに
たまにAllroidStudioのメモリーサイズが足りなくなり、警告が出たりしますよね。
その場合の対応方法としてメモリーサイズの変更方法を残しておこうと思います。

# 変更方法
Android Studioのメモリーサイズを変更するためには、VMオプションから設定する必要があります。
VMオプションは、`help→Edit Custom VM Options`という項目から設定可能です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354522/a77e1f0b-f75d-87b0-b9cf-8134c813df16.png" width="320px">

上記からVMオプションを開くと、以下設定の記載があると思いますので、サイズを上下させることでメモリーサイズを変更可能です。

```
-Xmx3072m
```

上記を変更したら、Android Studioを再起動すれば反映されるはずです。
設定は以上になります。

# さいごに
こういった設定は設定を変更する頻度が少なく忘れがちなので、こまめに残しておこうと思います。
Gradleで使用できるヒープサイズを引き下げる方法もあったりするので、後日記事にしようと思います。
Always Freeでインスタンス作成できなかった

# きっかけ
Oracle CloudのAlways freeで遊ぼうと思ったのに管理コンソール画面から作成できなかった。
「使用可能なシェイプがありません」って表示されてるのでリソース不足なのかなーと思ったけど、どうやら違うみたい。。


# 考えられる原因
Always Freeテナンシでは「VM.Standard.E4.Flex」が選択できないから。
イメージに対していちばん最初に選択されるシェイプは「VM.Standard.E4.Flex」なので、有償契約していないテナンシの場合そのシェイプが選択できない。選択できないからエラーが発生して、その後の操作を受け付けないといった感じかなと解釈。

↓は有償契約しているテナンシ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610268/3886acdf-d600-b54b-fb9f-fdd043cb1598.png)

↓はAlways Freeテナンシ
イメージを変更しても他シェイプを選んでもエラーが先行して作成することができない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610268/54415e57-9c7d-22de-82be-aca779e3e4b8.png)

# 回避方法
現状は画面からの作成は不可能なのでOCI-CLIを使う。チュートリアルの延長だと思えば。。。">https://oracle-japan.github.io/ocitutorials/intermediates/using-cli/">チュートリアルの延長だと思えば。。。
　※「A1.Flex」で作るときは「--shape-config」が必要なので注意
```
$ oci compute instance launch --availability-domain $ADNAME --image-id $IMAGEID --shape $SHAPE --shape-config '{"ocpus":"1.0"}' --ssh-authorized-keys-file "<Public Key>" --subnet-id $SUBNETID --assign-public-ip true --query 'data.id' --display-name '<display name>' --raw-output --compartment-id $COMPARTMENTID
```
# 作成できた！
Oracle Cloudらしい仕様だなぁと感じました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610268/31be7b41-cecb-2bfc-e0c0-bfc9de265592.png)
プログラミング初心者の機械学習の勉強に役立った記事

こんにちは。初めまして！
本当にど文系で大学まできて営業職として就職した社会人1年目の私がPythonの勉強を始めて試行錯誤していく過程を綴ります。
私は現在機械学習の授業を受講しているため、ゼロから勉強するにあたり助けられた、役立った記事やサイトをシェアできればと思います。

まだ学習途中なので、一旦箇条書きで掲載。
①基本のき
機械学習に必要な基礎のみならずそこで使われる数学について、そもそもPythonの基礎についての記載も細かく書いてあったので、順番にフォローすることで理解が深まりました。

https://tutorials.chainer.org/ja/01_Welcome_to_Chainer_Tutorial.html


②y = wTxすらわからなかったのですが、すごくわかりやすい説明が書いてありました。

https://qiita.com/mucunwuxian/items/a23305d54ffcd8dc0a06
Docker Engine SDK でホストポートを範囲指定する

Docker Engine SDK でホストポートを範囲指定する
コードは Go 言語ですが、他の SDK でも困っていたら、試してみるとうまくいくかもしれません。

検索しても、いまいち解決していなさそう
https://stackoverflow.com/questions/63236679/unable-to-port-forward-with-the-port-range-syntax-in-docker-sdk

### `"80-85:80"`（ホストポートを範囲指定する場合）
Dockerfile で `EXPOSE` していても `ExposedPorts` が必要な模様
https://qiita.com/ryskiwt/items/27cb74f621c9e9ee18be#%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E4%BD%9C%E6%88%90

起動途中や停止中に Docker Desktop 等で確認すると `localhost:80-85` と表記されるが、起動が完了すると正しく `0.0.0.0:80` や `0.0.0.0:81` と表示される。
```go
resp, err := cli.ContainerCreate(ctx, &container.Config{
    Image: imageName,
    ExposedPorts: nat.PortSet{nat.Port("80"): struct{}{}},
}, &container.HostConfig{
    PortBindings: nat.PortMap{
        nat.Port("80"): []nat.PortBinding{{HostPort: "80-85"}},
    },
}, nil, nil, "")
if err != nil {
    panic(err)
}
```

### `"80"` （ホストポートを指定しない場合、使用可能なポート番号を Docker が選択）
探すのにだいぶ時間を溶かした…
`HostPort` に `0` を入れると Docker が使用可能なポート番号を選択するようになった。
```go
resp, err := cli.ContainerCreate(ctx, &container.Config{
    Image: imageName,
    ExposedPorts: nat.PortSet{nat.Port("80"): struct{}{}},
}, &container.HostConfig{
    PortBindings: nat.PortMap{
        nat.Port("80"): []nat.PortBinding{{HostPort: "0"}},
    },
}, nil, nil, "")
if err != nil {
    panic(err)
}
```
または、書いてる途中で見つけた下記のように書いてもうまく行った。
こっちのほうが自然かも？
```go
resp, err := cli.ContainerCreate(ctx, &container.Config{
    Image: imageName,
    ExposedPorts: nat.PortSet{nat.Port("80"): struct{}{}},
}, &container.HostConfig{
    PortBindings: nat.PortMap{
        nat.Port("80/tcp"): []nat.PortBinding{{HostPort: ""}},
    },
}, nil, nil, "")
if err != nil {
    panic(err)
}
```
https://stackoverflow.com/questions/38385077/docker-give-a-random-port-mapping-only-to-certain-ports

#### 試行錯誤した記録
```go
// NG (127.0.0.1:49179 になってしまう)
nat.Port("80"): []nat.PortBinding{{HostPort: ""}},

// NG (ポートバインドされない)
nat.Port("80"): []nat.PortBinding{{HostIP: "0.0.0.0"}},

// NG (ポートバインドされない)
nat.Port("80"): []nat.PortBinding{{}},
```
[Docker Engine Go SDK リファレンス](https://godoc.org/github.com/docker/docker/client)や[API リファレンス](https://matsuand.github.io/engine/api/latest/)で見つからなかったため、[SDKリファレンスでリンクされていたリポジトリ](https://github.com/docker/go-connections/blob/v0.4.0/nat/nat.go#L176)も探したが力不足で見つからなかった。

ふと、お手本でコマンドで起動させていたポート範囲指定コンテナを停止すると、`localhost:80-85`と表示されている…（起動時は `0.0.0.0:81` だった）
ホストポート指定なしのお手本コンテナも停止させて、ポートを確認すると `0.0.0.0:0` の表示

もしやと思い、
```go
nat.Port("80"): []nat.PortBinding{{HostPort: "0"}},
```
としたところ、Docker が使用可能なポート番号を探して使用するようになった！

### 最後に
Docker Engine SDK のドキュメントもう少し情報が欲しい…
2022/08/10 頃に買ったM1 MacBookAirにgitをhomebrewでインストールするまで。

# homebrewのインストール
https://brew.sh/index_ja
のサイトにあるコマンドをターミナルに貼る。
パスワードを聞かれてエンターを押したらインストールが開始される。
インストールが終わったら↓を実行する。
```:ターミナル
brew --version
```
バージョンが表示されればOK。
表示されなければ続きます。

実はインストールのときにhomebrewから次のコマンドを入力してね　と言われている。
下記がその一部。
```:ターミナル
==> Next steps:
- Run these two commands in your terminal to add Homebrew to your PATH:
    echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/あなたの名前/.zprofile
    eval "$(/opt/homebrew/bin/brew shellenv)"
- Run brew help to get started
- Further documentation:
    https://docs.brew.sh
```
なので言われてるコマンドを入力する。
```:ターミナル
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/あなたの名前/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
```
もう一度下記を実行する。
```:ターミナル
brew --version
```
バージョンが表示されればOK。
されなければ.zshenv、.zprofile、.zshrc、.zlogin等のファイルに余計なパスを設定しているのかと思われます。
自分はこれでパスが通ったのでわからないです。

# Gitのインストール
Macは初めからGitが入っているらしい。
初めから入っているGitを使っても大丈夫だと思いますが、homebrewからGitをインストールするという記事が多かったのでhomebrewでインストールしてみる。
下記を実行する。
```:ターミナル
brew install git
```
インストールが完了したら下記を実行する。
```:ターミナル
git --version
```

```:実行結果
git version 2.32.1 (Apple Git-133)
```
実行結果に(Apple Git-133)と表示された場合は、初めから入っているGitになっているらしい。
表示されなければOK。
表示されていれば続きます。

これを先ほどhomebrewでインストールしたGitに設定する。

下記を実行。
```:ターミナル
cd ~
ls -a
```
実行結果に.zshrcファイルがなければさらに下記を実行。あれば実行しなくて大丈夫です。
```:ターミナル
touch .zshrc
```
これで.zshrcファイルがある状態になったので、Finderでcmd+shift+hを入力。
そこに.zshrcがなければcmd+shift+.を入力。
これで.zshrcが見えるようになったと思うのでこのファイルを開く。
開いたファイルに下記を貼り付けて保存。

```:.zshrc
export PATH=/usr/local/bin/git:$PATH
```
ターミナルに戻って下記を実行。
```:ターミナル
source ~/.zshrc
git --version
```

```:実行結果
git version 2.37.2
```
(Apple Git-133)が表示されなくなったのでOK。
それでも表示される場合はやはり.zshenv、.zprofile、.zshrc、.zlogin等のファイルに余計なパスを設定しているのかと思われます。
Kubernetesネイティブの開発ツールを、体系的に理解する方法

# 要旨

クラウドネイティブの時代になり、APレイヤだけでなく、インフラレイヤのコードも含めて広く考慮する必要がある。

開発者の環境で実施すべきものもあれば、ビルド環境でCI/CDをまわすものもある。

複雑化した構造の中で、開発ツールをどうとらえれば良いか。体系化の方針として、開発成果物をレイヤとフェーズの2軸で整理し、対応するツール・機能を紐づける。

## 要素は何か

レイヤとフェーズ分けした成果物ごとに、どういう機能が求められるかを明確にする。

* 成果物
  * レイヤ: AP、コンテナ、k8s（オーケストレーション）
  * フェーズ: ソースの状態から、Build/Ship/Runのそれぞれの成果の状態
* 機能
  * 成果物のレイヤとフェーズごとに必要な機能は異なる
  * ソース
    * エディタ
      * フォーマッタ/シンタックスハイライト/ソースの自動再生や補完
    * 静的チェック
      * スタイル、バグ検出、セキュリティチェック
  * Build
    * テスト実行
    * パッケージング
      * AP: Jarファイル
      * コンテナ: コンテナイメージ
    * セキュリティチェック
      * ※AP、コンテナ共に
  * Ship
    * リポジトリへの登録
      * AP: NEXUSへアーティファクトの登録
      * コンテナ: コンテナレジストリへの登録
      * k8s: etcdへの登録
    * セキュリティチェック
      * ※AP、コンテナ、k8s共に
  * Run
    * 実行環境へのデプロイ
      * コンテナ: コンテナの実行
      * k8s: Podの起動

## 要素に対応するツールは何か

組み合わせがかなり多いので、組み合わせを減らせる順にざっくり代表例を書く。

* セキュリティ全般
  * Trivyなどを用いてシフトレフトが基本。つまりなるべく早いフェーズでリスクを排除する
* コンテナ全般
  * とりあえずDocker。
  * コンテナ × Build: Buildpackなどのツールで効率化
* ソース全般: VSCodeなどのIDEを使うことでエディタなどの機能が使える
  * AP × ソース:言わずもがなMaven
  * k8s × ソース:SkaffoldやKustomizeで効率的に開発
* Run全般: 
  * IaC化: kubectl芸に頼らない。
    * コマンドで頑張るのではなく、TerraformなどのIaCツールのソースに寄せる
  * パイプライン化: GitOpsなどの考え方をベースにする
    * Circle CIやArgoCDなどのCI/CDツールとの組み合わせてビルドパイプラインを構築する
    * APとインフラのGitリポジトリは分ける
  * 効率化: k9sなどのツールの活用

## どのツールの組み合わせがお薦めか

好みに合わせてで良いが、例えば、
Trivy, Kustomize, Rancher Desktop, VSCode, Circle CI, ArgoCD, k9sなど。

### 世の中の事例をどう捉えれば良いか

前節までの整理を頭に入れた上で、クラウドネイティブ系のコミュニティで先進企業の事例セッションなどを聞いてツールの位置付けを理解すると良い。

## まとめ

ここまで書いておいて逆のことを言うが、ツールの比較表などは、破綻することが多いのであまりこだわらない方が良い。

なぜならば、ツール間で機能が重複するし、具備する機能のレベルもAppleToAppleで語れないケースも多い。

あくまで、ツールは手段でもあるので、ざっくりとした概観の理解に留め、やりたい事・目的に応じてプロジェクトで検証すると良いと思う。
MacでSeeed XIAO RP2040 C++,C開発

# 環境
* Intel Mac monterey Version.12.5
* arm-none-eabi-gcc Version.10.3.1
* cmake

# 参考文献 
XIAOのBボタンを押しながら、USBケーブルを接続した後、USBドライブのindex.htmをオープンする。 
The C/C++ SDKとExampleのリポジトリなどPICOに関するドキュメントへジャンプする。

# 手順
* SDKクローン

```
git clone -b master https://github.com/raspberrypi/pico-sdk.git
cd pico-sdk
git submodule update --init
```

* Exampleのクローン
```
git clone -b master https://github.com/raspberrypi/pico-examples.git
```

* 環境変数設定
    * export PICO_SDK_PATH=[pico-sdkへのパス]
    * export  PICO_TOOLCHAIN_PATH=[arm-none-eabi-gccへのパス]
* サンプルコンパイル
    * buildディレクトリ作成
    * cd build
    * cmake Exampleへのパス
    * cd blink
    * make
* uf2ファイルをXIAOへ書き込む
    * Bボタンを押しながら、USBケーブルを繋ぐ。
    * 現れたUSBドライブにuf2ファイルをドロップ


# pico-exampleのコンパイル 
```
cd pico-example
mkdir build
cd build
```
cmakeの実行とターゲットのリスト表示
  
```
cmake -D"PICO_BOARD=seeed_xiao_rp2040" -GNinja ..
ninja -t targets
```
コンパイル
ninja target名

# pio_ws2812
PICO_DEFAULT_WS2812_POWER_PINを出力に設定し、1を出力する.
```
	#ifdef PICO_DEFAULT_WS2812_POWER_PIN
	gpio_init(PICO_DEFAULT_WS2812_POWER_PIN);
	gpio_set_dir(PICO_DEFAULT_WS2812_POWER_PIN, GPIO_OUT);
	gpio_put(PICO_DEFAULT_WS2812_POWER_PIN, 1);
   	#endif
```
USBにデバック出力する場合、CMakefileに追加 
```
   # Debug output - Enable for USB CDC and disable for on-board UART
   # You can change these around (or even have both active) by changing the 1s and 0s
   pico_enable_stdio_usb(pio_ws2812 1)
   pico_enable_stdio_uart(pio_ws2812 0)
```
usbに出力する場合、MACがポートを利用できるまでにリセットから２秒以上かかるので、　
exampleのhello_timerを参照してwaitをかける。
RaspberryPi3 B+で監視カメラを作ってみた

right(engineer)です。

今回はRaspberryPi(以降ラズパイ)で監視カメラを作成してみました。

# １.環境

- Raspberry Pi3 Model B+
- カメラモジュール(感光チップOV5647センサー)[ブランド：LOTW]
- Python3 (Ver.3.9.2)
- pip3 (Ver.22.2.2)
- OpenCV2 (Ver.4.6.0)
- NumPy (Ver.1.23.1)
```
$ git --version
Python 3.9.2
$ pip3 --version
pip 22.2.2 from /usr/local/lib/python3.9/dist-packages/pip (python 3.9)
$ python3
>>> import cv2
>>> cv2.__version__
'4.6.0'
>>> import numpy
>>> numpy.__version__
'1.23.1'
>>> exit()
```

# ２.事前準備
今回はプログラミング言語としてPython3を使用した。

### ２.１.pip更新
pipを最新版に更新する。
```
$ sudo python -m pip install --upgrade pip
```

### ２.２.OpenCV インストール
OpenCVをインストールする。
OpneCV：画像解析ライブラリ
今回はPythonでOpenCV2をインストールする。
```
$ sudo pip3 install opencv-python==4.6.0
```

### ２.３.NumPy更新 
NumPyを最新版に更新する。
NumPy：数値計算ライブラリ
```
$ sudo pip3 install -U numpy
```

# ３.仕様
ラズパイに接続したカメラモジュールの映像をモニタする。
プログラム実行後、ウィンドウ上にモニタ映像が表示される。
ESCキーを押すとウィンドウを閉じて、プログラムを終了する。

# ４.実装
以下ソースコードをラズパイ上で作成した。
```
import cv2

camera_no = 0 #Camera No.
window_title = "Window" #Window name

camera = cv2.VideoCapture(camera_no)

while True:
    ret, frame = camera.read()
    if not ret:
        break
    
    cv2.imshow(window_title, frame)
    key = cv2.waitKey(1)
    
    if key == 27: #Push Esc kye if you want to close the window.
        break
    
camera.release()
cv2.destroyAllWindows()
```

### GitHub URL
https://github.com/righteng/pi.git

# ５.ソースコード解説
OpenCV2のライブラリを呼び出す。
```
import cv2
```

使用するカメラを選択する。
カメラが1台しか接続されていない場合はcamera_noを0に設定する。
```
camera = cv2.VideoCapture(camera_no)
```

カメラが複数台ある場合はターミナルに以下コマンドを入力して、カメラのNo.を確認する。
```
$ v4l2-ctl --list-devices
UVC Camera:/dev/video0
```

カメラから1フレーム分の画像を保存する。
ret：カメラ画像取得結果が入る。True、falseが入る。
img_src：1フレーム分の画像データが入る。
```
ret, frame = camera.read()
```

上記で取得したカメラ画像を表示する。
第一引数：表示ウィンドウ名。
第二引数：表示するカメラ画像(1フレーム分)
```
cv2.imshow(window_title, frame)
```

1m秒間キーが押下されるのを待つ。
keyには押下されたキー入力の10進アスキーコードが入る。
例）ESCキーが押下された場合、key=27となる。
```
key = cv2.waitKey(1)
```

カメラのキャプチャを終了し、
表示ウィンドウを閉じる。
```
camera.release()
cv2.destroyAllWindows()
```

# ６.動作確認
RaspberryPi上でカメラモジュールの映像をモニタすることができました。
![RasPi-camera_Operation-check.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613720/37ea258a-fcbd-d91e-672d-78c6a79e6a30.png)
【Git】ブランチを保護する方法【GitHub】

## 設定方法
対象のリモートリポジトリにアクセスし､`Settings`の`Branches`を選択します。
![スクリーンショット 2022-08-14 午後5.22.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/a83925f9-3aee-d5ba-2310-ee6a5c179602.png)

`Add rule`をクリックします。
![スクリーンショット 2022-08-14 午後5.25.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/bbbb0205-1ac5-4f7a-7dc8-16c051fc0ce8.png)

`Branch name pattern`に対象ブランチの名前を入力し`Protect matching branches`および`Rules applied to everyone including administrators`から適用するルールを選択します。
選択後`Create`をクリックします。
![スクリーンショット 2022-08-14 午後5.29.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/7326481f-8284-951e-cf19-77adfaf7fe68.png)

## 設定例
以下のように設定することで`main`ブランチへの直`push`を禁止できます。
![スクリーンショット 2022-08-26 14.43.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/e8b848cf-8d78-5c07-7bd4-61cc27915e83.png)

`main`ブランチに直接`push`しようとすると以下のようなエラーが出ます。

```zsh:ターミナル
$ git push origin main
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 8 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 659 bytes | 659.00 KiB/s, done.
Total 5 (delta 4), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (4/4), completed with 4 local objects.
remote: error: GH006: Protected branch update failed for refs/heads/main.
remote: error: At least 1 approving review is required by reviewers with write access.
To github.com:GitHubUser/sample-app.git
 ! [remote rejected] main -> main (protected branch hook declined)
error: failed to push some refs to 'github.com:GitHubUser/sample-app.git'
```
【いまさらシリーズ】AWS Redshiftまとめ

# Redshiftとは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782361/e2ee13f3-07eb-4187-7bc3-002a0b311053.png)

[公式ページ](https://aws.amazon.com/jp/redshift/)の説明によると、以下の通り。
> SQLを使用して、データウェアハウス、運用データベース、データレイクにわたる構造化および半構造化データを分析し、AWSが設計したハードウェアと機械学習を使用して、あらゆる規模で最高の料金パフォーマンスを実現します。

つまり、あらゆるデータを構造化して蓄積し、高速に**分析処理**ができる特徴がある。

# スナップショット
スナップショットには自動と手動の２種類がある。Amazaon Redshiftはスナップショットを**Amazon S3に内部的に保存する。**

## ストレージの管理
スナップショットを溜め込みすぎて容量の上限を超過すると課金が発生する。そのため、不要になったら削除する必要がある。スナップショットの保持期間は指定ができる。
ただし、自動スナップショットを削除できるのはAmazon Redshiftのみで、手動で削除することはできない。自動スナップショットを長期間保持する場合は、そのコピーを手動スナップショットとして作成ができるため、好きなタイミングで手動で削除が可能となる。

## スナップショットを別のリージョンにコピーするには
スナップショットのコピー先のAWSリージョンを指定する必要がある。

# 参照
https://aws.amazon.com/jp/redshift/

https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-snapshots.html

今後追記予定。
ブロークングリッドレイアウトっぽいグリッドレイアウト

## この記事の概要

プロモーション用のサイトからコーポレートサイトまで、ブロークングリッドレイアウトを採用しているWebサイトをよく見かけます。
イケてる見た目にはなりますが、`position`で頑張って配置するのは大変過ぎますよね。（レスポンシブでの挙動まで考えると尚更）

というわけで、比較的手抜きでブロークングリッドレイアウトっぽく見える方法を考えてみました。

## 方向性

`display: grid;`を使います。
ブロークングリッドという名前のレイアウトを実現するのにCSS gridを使うのもいささか気が引けますが、使います。

そもそも、ブロークングリッドと呼ばれているようなサイトは大半が`完全に不揃い`なわけではなく`まあまあグリッドがあるけど、一部が崩れている`に過ぎません。

以下のようなギャラリーを見てみるとよく分かると思います。

https://webdesignclip.com/tag/broken-grid-layout/

基本的には`display: grid;`に沿わせつつ、一部の要素だけを外すように作ると省エネで作れます。

## 見本 & 解説

見本というほど大それたものではありませんが、今回の記事のために簡単に作ってみました。

https://xrxoxcxox.github.io/qiita-broken-grid-like-grid-layout/

リポジトリはこちらです。

https://github.com/xrxoxcxox/qiita-broken-grid-like-grid-layout

具体的なテクニックとして、以下を紹介します。

- 奇数グリッドを用いる
- 要素が重なるように配置する
- 中央揃えやpaddingで少々位置をずらす
- writing-modeがverticalな要素を入れておく

### 奇数グリッドを用いる

よくあるグリッドレイアウトでは偶数、とりわけ12カラムのレイアウトがよく使われています。
しかしここであえて奇数を選びました。

好みの問題もあるかもしれませんが、偶数だと画面中央での分割が増える・目立ちがちな気がします。
するとブロークングリッドというよりはスプリットスクリーンっぽさが強く見えるかもしれません。

というわけで奇数にしてみるのをお勧めします。

今回でいうと、以下のようなコードで全体のグリッドを定義しています。

```css
.container {
  display: grid;
  grid-template-columns: repeat(13, minmax(80px, 1fr));
  grid-template-rows: auto;
  width: 100%;
}
```

maxを`1fr`にしていますが、今のままだと際限なく伸びてしまうので適当な上限を決めても良いかもしれませんね。

### 要素が重なるように配置する

`ブロークングリッドっぽさ`を出すのに一番重要なポイントかもしれません。
`grid`を使うと要素の重ね合わせが`position`より楽（というか、管理がしやすい）と思います。

例えば、以下のように書けば少しずつ重なった要素を再現できます。
グリッドコンテナ側の記述を変えればアイテムも追従して位置やサイズが変わってくれるので、メディアクエリによる気合いの入った分岐も少なくて済むのではないでしょうか。

<p class="codepen" data-height="300" data-default-tab="css,result" data-slug-hash="XWExgzX" data-user="xrxoxcxox" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/xrxoxcxox/pen/XWExgzX">
  Untitled</a> by Keisuke Watanuki (<a href="https://codepen.io/xrxoxcxox">@xrxoxcxox</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

### 中央揃えやpaddingで少々位置をずらす

そうは言ってもすべての要素がグリッドの線に沿っていると若干単調になってしまいます。
というわけでスパイス的に変化を加えておきましょう。

例えば中央揃えを施すと、始点や終点が既存のグリッドから外れます。

```css
.text {
  grid-column: 1 / -1;
  text-align: center;
}
```

見本でいうと、タイトルっぽい部分に中央揃えを施しています。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/fd3d86e2-a4db-abbd-0ee3-f5f2f72824cc.png)

また、微妙に`padding`をつけて位置をずらすのも良いでしょう。

注意点として、こういった微妙なずらしは多用しないでください。
ある程度グリッドを感じられる中で1つや2つのズレがあるからこそ良い緩急がつくのであって、すべてがずれていたらただの混沌です。

### writing-modeがverticalな要素を入れておく

最後のはテクニックというか、ブロークングリッドレイアウトでは大抵使われているのでついでに紹介するだけです。

`writing-mode: vertical-lr;`などと指定すると、テキストの書かれる向きが変わります。
見本では右下の`Scroll`という文字に使っています。

これも、単調になりすぎるのを防ぐためのスパイスのようなものなので、ページの中に1~2個存在している程度で十分だと思います。

---

最後まで読んでくださってありがとうございます！
Twitterでも情報を発信しているので、良かったらフォローお願いします！

https://twitter.com/xrxoxcxox
latin1のようでlatin1でない（TextDecoder）

`TextDecoder`でバイト列を文字列に変換しようとしたら、意外な形で引っかかってしまいました。

## TL; DR

* `TextDecoder`に`latin1`や`ascii`と指定しても、実際にはWindows-1252として処理される
* latin1とWindows-1252では、0x80 - 0x9Fのマッピングが違う
* バイナリ文字列を配列に起こすなど、0x80 - 0x9FをU+0080 - U+009Fにそのまま対応させたい用途には使えない

## `TextDecoder`とは

`TextDecoder`は、配列に入った数値の組を、文字コードとして解釈して文字列に変換するためのクラスです。[対応するエンコード](https://developer.mozilla.org/en-US/docs/Web/API/Encoding_API/Encodings)はUnicode系だけでなく豊富に用意されていて、たとえば日本語用のSJIS、EUC-JP、ISO-2022-JPも存在します（JavaScriptコードとしてテーブルを持たずに、これらのエンコードを解釈できる、ということになります）。

## `latin1`を使ってみたら

その中に`latin1`があったので、`atob`の結果を投げ込んでバイト配列にしてみたのですが…おかしな値を出していることに気づいてしまいました。

### 調べてみた結果

先ほど挙げた [エンコードリスト](https://developer.mozilla.org/en-US/docs/Web/API/Encoding_API/Encodings)のページを見たところ、`latin1`、`ascii`、`us-ascii`などのように指定した場合、実際にはWindows-1252（[Wikipedia](https://ja.wikipedia.org/wiki/Windows-1252)）というエンコーディングが使われることが判明しました。この2つの違いは、

* latin1…0x80 - 0x9Fには制御コードが入っている（UnicodeでもU+0080 - U+009Fに同じ形で入っている）
* Windows-1252…0x80 - 0x9Fには一部を除いて文字が入っている（Unicodeと単純なマッピングにはならない）

というもので、latin1で書かれた普通の文書であれば0x80 - 0x9Fの文字がないので問題にはならないのですが、`atob`の結果など256通りのバイトパターンが全て使われている場合には大問題となってしまいます。

### 結論

`TextDecoder`で得られた結果のうち、マッピングが違う文字だけあとから置換する、というようなことを試してみたりもしたのですが、結局は素直に`for`で`String.fromCharCode`を動かして文字列を継ぎ足す、という原始的な方法が最速だったのでそれでいいかなとなっています。
【Java】複数の配列(List)をStreamを利用して一つのListにまとめる

# はじめに

業務でJavaを使うことになったが、少しブランクがあるため、記事としてまとめる。

# 環境

Java：11

# 準備

実際の業務では、DBから取得した半角スペース区切りの文字列（2カラム分）を配列化し、一つのListに格納する処理が必要であったため、配列の部分から記述する。

```java
String column1 = "あああ いいい ううう";
String column2 = "えええ おおお";

// NULLか空の場合は長さ0の配列を代入
String[] column1Array = column1.isEmpty()
    ? new String[0]
    : column1.split(" ");

// NULLか空以外の場合は半角スペース区切りの文字列を
String[] column2Array = column2.isEmpty()
    ? new String[0]
    : column2.split(" ");
```

# 複数（2つ）の配列を一つのListにまとめる

```java
// 上記で準備した配列をListにまとめる
List<String> tests = Stream.concat(
        Arrays.stream(column1),
        Arrays.stream(column2))
    .collect(Collectors.toList());
```

これで上記二つの配列を一つのListにまとめることが出来た。
また、例では配列を扱ったが、複数のListを一つのListにまとめる場合は以下のようにすれば可能。

```Java
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();

List<String> tests = Stream.concat(
        list1.stream(),
        list2.stream())
    .collect(Collectors.toList());
```

# 備考：複数（3つ以上）の配列を一つのListにまとめる

```java
String[] column1Array = "あああ いいい ううう".split(" ");
String[] column2Array = "えええ おおお".split(" ");
String[] column3Array = "かかか ききき".split(" ");
List<String> list = Stream.of(
        column1Array,
        column2Array,
        column3Array)
    .flatMap(array -> Arrays.stream(array))
    .collect(Collectors.toList());
```


以上。
【ポートフォリオ作成3日目】アイデア出し、READMEの作成

# 概要
[エンジニア転職に成功するポートフォリオ戦略!!](https://www.youtube.com/watch?v=nkdz-lLwDZI)を参考に、以下の流れで進めていく。今回は1〜2まで。
1. アイデア出し
2. READMEの作成
3. 画面遷移図の作成
4. ER図の作成
5. issue化して開発開始

# 1. アイデア出し
以下を参考にアイデアを出す。
- [ポートフォリオ作成のネタ収集シート](https://docs.google.com/document/d/1Hovs1P8rGKvZAx6oqL0TqLtv-cWkMxICEvf2fPPM5A8/edit)
- [【アイディア出しシート】](https://onyx-tuba-8de.notion.site/6d8f9abb42d0448aae5d91ce9bf6215f)

# 2. READMEの作成
以下を参考にREADMEを作成。
- [READMEフォーマット](https://onyx-tuba-8de.notion.site/README-3afe5fc40f1e4a38b2caece311efbe91)
【Blender】装飾小物をテクスチャにベイクして軽量化(VRChat想定)

# 前書き
VRChatにて、こうめちゃんをフォールバックアバター化するために装飾小物をテクスチャで表現したかった。しかし、画像編集ソフトで衣装テクスチャに小物をつぎはぎしようとすると、UVの歪みからどうしても歪む。UVはあんまり動かしたくないのでベイクで対応。
その覚え書き。

# 先に結果から
左がアフター、右がビフォー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738995/d5062de4-7681-791e-3f05-811ec0f4b536.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738995/7c1e0554-db81-787d-af0f-1e18231c7b78.png)

# 環境
+ Blender 3.2.1

# ベイクの考え方
Blenderのベイク機能の"選択物 → アクティブ(Selected to Active)"を使う。

https://docs.blender.org/manual/en/latest/render/cycles/baking.html

マニュアルによると、本来はハイポリをローポリに転写する用途で、以下の図のような感じらしい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738995/8fc458eb-2f18-dfdb-76c0-265c248181b8.png)
今回はボタンやリボンなどの小物をコスチュームやヘアーテクスチャにベイクしたい。
そこで、"押し出し"と"レイの最大距離"で調整して以下のように転写する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738995/ff6b75d0-35d0-dd0e-0ba7-711bfe340377.png)
# ベイクの手順
服へボタンを転写する(厳密にはボタンのみ転写されたテクスチャが生成されるので、それを画像編集ソフトで服テクスチャに重ねる)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738995/f555173f-58d2-7d9c-a6a4-41ec3f078f09.png)

## 1. 転写用のテクスチャを作成
+ 名前はtex_costume_bakedとか
+ 後々、画像編集しやすいように転写先のテクスチャと同じ解像度にしたほうが良いかも
+ カラーはアルファチャンネルを0に設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738995/777a6310-fad1-415b-9ad0-2b2adcf6022e.png)

## 2. 転写先のマテリアルにテクスチャノードを設定
+ シェーダーエディターを開き、転写先オブジェクトに設定しているマテリアルを開く。テクスチャノードに転写先テクスチャtex_costume_bakedを設定。そして、テクスチャノードを選択し、アクティブな状態にしておく。
+ 一応テクスチャノードと繋がってるノードを外す。(調べてたらテクスチャノードのノードは外しておくって記事を見かけたんだけど、外さなくてもメッセージが出るだけでベイクはうまくいったりした)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738995/56e6e04a-fd34-7316-401a-43eb81d1d6c3.png)

## 3. レンダリング設定
+ 標準のレンダリング設定では時間がかかりすぎるので変更
+ レンダープロパティタブにて。サンプル数を落として、一応デノイズのチェックも外す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738995/e5620b2a-c9c6-0c7a-bb23-927de7d6e8b7.png)
+ 効いてるのかわかんないけど、念の為ライトパスの最大バウンス数の合計を1に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738995/db0e9eec-5034-5d7c-9687-3ae6026bd4f5.png)

## 4. ベイク設定
+ レンダープロパティタブにて。
+ ベイクタイプ：ディフューズ
+ 寄与：カラーのみ
+ 選択物 → アクティブ：チェック
+ 押し出し：5cm(今回は、衣服表面の5cm以内のボタンを転写)
+ レイの最大距離：5cm(多分設定しておかないと、衣服のあっちこっちのメッシュから飛んできたレイがボタンに当たって想定外のとこに転写される)
+ ※上記の距離はアクティブオブジェクトのスケールの影響を受ける模様。スケールの逆数を距離にかけて設定するか、アクティブオブジェクトのスケールを適用して1にする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738995/4efb284e-e5fb-a86e-289f-de7dd5cf5ca7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738995/f882ee38-d6f8-658c-fcf3-015a57da7959.png)

## 5. ベイク
+ Shiftを押しながら装飾小物(ボタン)をクリックし、その後転写先オブジェクト(服)をクリックする。ボタンオブジェクトが朱色のアウトライン、服オブジェクトがオレンジ色になってるはず。
+ ベイクボタンを押す。CPU環境4267x4267で20秒くらい。
+ テクスチャノードを外している場合は、シェーダーエディターでテクスチャノードを接続
+ UVエディタ開くと転写されていることが確認できる。
+ この画像を保存して画像編集ソフトとかで元テクスチャに乗っければ完了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738995/42ec5b4f-5b33-c1d7-212a-4a6e53abbc91.png)

# 終わりに
また一歩Blender君に歩み寄れた気がする。こうめちゃんありがとう。
IntelliJでタイポを無視する方法

# 概要
IntelliJでタイポを無視したい場合の手順をまとめました。

# 手順

① 緑の波線(タイポの警告)が付いていることを確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680827/7b54bfed-e26f-be9c-17df-b942070dcf32.png)


② 「Alt + Enter」を押下する。
メニューが表示されるので、「'XXX'を辞書に保存」を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680827/992f64d1-2924-ce8a-0a5c-7826b37e6454.png)


②を実施したソースコード以外でも辞書に登録した用語についてはタイポの警告が消える。


<辞書から用語を削除したい場合>
設定からスペルのメニューを開き、削除したい用語を選択して「－」ボタン⇒「適用」を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680827/f4a91b93-559f-58d4-cc27-db43b545c5f5.png)
リージョンとアベイラビリティゾーン

# リージョンとアベイラビリティゾーン
AWSはサーバーとデータセンターを世界中の21の地域に置いている。
この地理的分類が**リージョン**。
ユーザーがサービスを受けるときは地域を選択する。
日本には東京リージョンと大阪リージョン（ローカル）がある。
大阪はローカルリージョンという特殊なリージョンなので限られた顧客しか使えない
リージョンとは簡単に言えば**データセンター**。
各リージョンでは複数の**アベイラビリティーゾーン**（AZ）にそれぞれ物理的に独立した設備を置いてある。
イメージ）データセンターの設備をさらに分散している
# リージョンとサービス
**リージョンによって提供されているサービスと提供されていないサービスがある**
ex)まだ東京リージョンで提供されていないサービスを使用したい時は、**そのサービスのみを米国東部などの別リージョンを選んで使用する**。
※サービスによっては海外リージョンの方が安いときがある
※どのリージョンを選んでも、コントロールパネルのダッシュボードから管理するため、日本語で操作できる。
## リージョン一覧
|コード|名前|
|-|-|
|us-east-1|米国東部（バージニア北部）|
|us-east-2|米国東部（オハイオ）|
|us-west-1|米国西部（北カリフォルニア）|
|us-west-2|米国西部（オレゴン）|
|ca-central-1|カナダ（中部）|
|eu-central-1|欧州（フランクフルト）|
|eu-west-1|欧州（アイルランド）|
|eu-west-2|欧州（ロンドン）|
|eu-west-3|欧州（パリ）|
|eu-north-1|欧州（ストックホルム）|
|ap-east-1|アジアパシフィック（香港）|
|ap-northeast-1|アジアパシフィック（東京）|
|ap-norhteast-2|アジアパシフィック（ソウル）|
|ap-northeast-3|アジアパシフィック（大阪：ローカル）|
|ap-southeast-1|アジアパシフィック（シンガポール）|
|ap-southeast-2|アジアパシフィック（シドニー）|
|ap-south-1|アジアパシフィック（ムンバイ）|
|sa-east-1|南米（サンパウロ）|
AtCoderの成績を動的にMarkdownに埋め込む方法

## はじめに
都内でバックエンド開発を行なっている[@hamaguchi](https://twitter.com/Buffalo_G_7777)です。
最近趣味として競技プログラミングをはじめました。解けた喜びはもちろんのこと、解けなかった時の悔しさを毎週味わえるのが素晴らしいです。仕事では味わえない「THE・敗北」という感じがたまらないですよね。

**『悔しいっ…！悔しいっ…！だがこれでいいっ…！これでこそ競プロだっ…！』**


[![](https://atcoder-stats-git-main-akmhmgc.vercel.app/api?username=crazyhama)](https://github.com/akmhmgc/atcoder-stats)
さて前置きはここら辺にして、今回はAtCoderの成績をMarkdownファイル上に動的に埋め込むことができる **AtCoder Stats**を作成しました🎉

## リポジトリ
https://github.com/akmhmgc/atcoder-stats

よろしければスターを付けていただけると幸いです〜🤲

## 使い方
以下をコピーしてMarkdownファイルに貼り付けるだけで成績チャートを表示することができます🎉
`username=`は適宜AtCoderのユーザー名に変更して下さい。

```markdown
[![](https://atcoder-stats-git-main-akmhmgc.vercel.app/api?username={AtCoderのユーザー名})]
```

※ なおエンドポイントはVercelの無料プランを利用してデプロイしているので、API制限が気になる方はご自身でデプロイすることをお勧めします:pray:
（参考：[デプロイ方法](https://github.com/akmhmgc/atcoder-stats#deploy-on-your-own-on-vercel)）


## 仕組み
### AtCoderの過去の成績を取得する
AtCoderは公式APIはないのですが、特定のURLの末尾に/jsonをつけるとJSON形式でデータが返ってきます。なので過去の成績は簡単に取得できます。

https://twitter.com/chokudai/status/1001332212648701952?s=20&t=kTNs4SUa-8cmkmrDmGx7lw

```markdown
https://atcoder.jp/users/username/history/json
```


### SVGを返すエンドポイントを作る
<img src="https://upload.wikimedia.org/wikipedia/commons/6/68/Octopus_clipart.svg" width="420px">

[こちらのタコの画像](https://upload.wikimedia.org/wikipedia/commons/6/68/Octopus_clipart.svg)のような、SVG要素を返すURLは、以下のような形でMarkdownに埋め込んで画像として展開することができます。

```markdown
![タコの画像](https://upload.wikimedia.org/wikipedia/commons/6/68/Octopus_clipart.svg)

<img src="https://upload.wikimedia.org/wikipedia/commons/6/68/Octopus_clipart.svg" width="420px">
```

なので動的にSVGで成績のグラフを返すエンドポイントを作ってあげればOKです。
グラフ作成にはD3.jsをサーバーサイドで使用するためのライブラリを使用しています。

https://github.com/d3-node/d3-node

https://d3js.org/


## 最後に
お好きなMarkdownにAtCoderのグラフを埋め込んじゃいましょう🎉
また、改善点やご要望などがあればお気軽にコメントいただけると幸いです:pray:
深層学習の推論フレームワークのメモ

* Onnxruntime 

https://onnxruntime.ai/ 

   使用しやすい。有効なONNXモデルをほとんど全部実行できる。ONNXはほとんど全部深層学習のフレームワークをサポートしている。Githubで[事前コンパイルしたライブラリ](https://github.com/microsoft/onnxruntime/releases)もある。でも、INT8量子化モデルの実行速さが遅い。


* TensorRT

https://developer.nvidia.com/tensorrt-getting-started

　NVIDIAのGPUで一番速い。でも、NVIDIAのGPUに限り使用できる。ONNXなどモデルからTensorRTのエンジに変換する必要がある。変換の時、新しい演算子をサポートしない可能性がある。

* openvino

https://docs.openvino.ai/latest/openvino_docs_install_guides_overview.html

INTELのチップセットでよく速い。INT8のモデルも速い。変換することもある。UBUNTUで使用する時、UBUNTUのバージョンの要求がある。

* Tengine

https://github.com/OAID/Tengine/blob/tengine-lite/README_EN.md

例のコードがたくさんある。CとC++だけのAPIがある。

* libtorch

https://pytorch.org/cppdocs/installing.html

　Pytorchの演算子がほとんどサポートしている。訓練のフレームワークはPytorchに限りだ。

などなど
JavaScriptにセミコロンは入れるのか？入れないのか？

## 結論
- どちらでもいい
- セミコロン付けても付けなくても落とし穴はある
- ESLintを利用することで落とし穴を検知できる
- 私はセミコロンつけない派

## 自動セミコロン挿入とは
[自動セミコロン挿入(automatic semicolon insertion)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#automatic_semicolon_insertion)

- この仕組みのおかげでセミコロンを使わなくてもコードを書くことができ、コンパイラが行末を察してセミコロンを挿入してくれる
- 自動セミコロン挿入のしくみはECMAScriptで規定されており、自動セミコロン挿入はJavaScriptエンジン間で可搬性がある
- 自動セミコロン挿入には落とし穴があり、ルールを理解しておく必要がある

### 第１のルール：セミコロンが挿入されるのは、"}"トークンの前か、改行の後か、プログラムの末尾だけ
```JavaScript
{ 1
2 } 3

// 上記の文は、 ASI によって次のように変換される

{ 1
;2 ;} 3;
```

### 第２のルール：セミコロンが挿入されるのは、次の入力トークンを字句解析できないときだけ

セミコロン挿入されないケース
```JavaScript
a = b
(f());

// これは１個の文として正しく解析できるので、次のよう変換される

a = b(f());
```

セミコロン挿入されるケース
```JavaScript
a = b
f();

// これは2つの別々の文として解析される
// なぜなら次のように解釈したら解析エラーとなるから
// a = b f();

a = b;
f();
```
このルールには落とし穴があり、セミコロンを省略できるかできないかを判断するために、次の文の始まりに注意する必要がある

問題になる記号は`(`,`[`,`+`,`-`,`/`の5つ。
もし次の文が問題となる5つの記号のどれかであれば、セミコロンは挿入されない。

`[`の落とし穴
```JavaScript
a = b
['🍎', '🍌', '🍈'].forEach((key) => {
  console.log(fluits[key]['price']);
);

// 後続の文が [ で始まるので、1つの文として解析される

a = b['🍎', '🍌', '🍈'].forEach((key) => {
  console.log(fluits[key]['price']);
);
```

`/`の落とし穴
```JavaScript
a = b
/Error/i.test(str) && fail();

// 以下のように変換される

a = b / Error / i.test(str) && fail();
```

#### 必ずセミコロンを記述すれば無問題？
実はそうでもない。
構文解析でエラーにならない部分もコンパイラが強制的にセミコロンを挿入するケースがある。

```JavaScript
return
{ };

// これは次の3つの文として解析されてしまう

return;
{ }
;
```

セミコロンが挿入される場所(<;>)は次の通り
- `expr <;> ++`、`expr <;> --`
- `continue <;> lbl`
- `break <;> lbl`
- `return <;> expr`
- `throw <;> expr`
- `yield <;> expr`
- `yield <;> * expr`
- `(param) <;> => {}`
- `async <;> function`、`async <;> prop()`、`async <;> function*`、`async <;> *prop()`
- `async <;> (param) <;> => {}`

### 第３のルール：セミコロンがforループ頭部の区切りとして挿入されることはない
forループではセミコロンを明示的に書く必要がある
```JavaScript
for (let i = 0 // parse error
    i < n
    i++) {
    // 何かしらの処理
}

// 明示的にセミコロンを書く必要がある
for (let i = 0 ; i < n ; i++) {
    total *= i
    // 何かしらの処理
}
```

## どっちがいいの？

|| メリット | デメリット |
|:-----------|:------------|:------------|
| セミコロンあり| 落とし穴は少ない|最近のセミコロンを書かない言語から見ると古臭く見える|
| セミコロンなし| コードがすっきりする|セミコロン挿入のルールを知っていないと危険が多い|

## TC39ではどうなっているの？
TC39では入れるか入れないかを定義していない。
世間にはセミコロンを使っていないJavaScriptコードは山ほどあるので、セミコロンを使うのが正しくて、セミコロンが無くても動くのはたまたま動いているだけですと言うのは厳しいと思われる。

## どうすれば良い？
EsLintを使用し、意図しない動作になる箇所があれば警告を出す。

セミコロンを常に書く場合は`no-unreachable`ルール
[no-unreachable](https://eslint.org/docs/latest/rules/no-unreachable)

セミコロンを省略する場合は`no-unexpected-multiline`ルール
[no-unexpected-multiline](https://eslint.org/docs/latest/rules/no-unexpected-multiline)


## まとめ
ESLintを利用することで意図しない動作は検出できます。
セミコロン入れる派　or　セミコロン入れない派、どちらも楽しくコーディングしていきましょう！
AWSのコスト管理

AWSはクラウドなので、初期費用が抑えられる代わりに、従量制での課金となる。
そのため**日々の料金管理が重要な課題**となる。また、管理する対象も複数のサービスが多く煩雑になる。
# AWS Billing and Cost Management(AWSコスト管理)
* 請求書の支払い
* 使用料の監視
* コスト・使用状況レポート
* サービスの解約
などができる。
## AWS Billing and Cost Managementの主なサービス
|項目|内容|料金|
|-|-|-|
|請求書|毎月の請求書や、使っているAWSサービスの詳細内訳が確認できる|無料|
|請求ダッシュボード|支出ステータスやコスト傾向などが確認できる|無料|
|AWS Cost Explorer|コストと使用量を掲示的に可視化、把握、管理できる|付属のユーザーインターフェイス使用時は無料、APIを使用したプログラムアクセスは有料|
|AWS Budgets|コストと使用料のカスタム予算を設定して、特定の条件でアラートを発信する|使用自体は無料だが、３つめのカスタム予算から料金がかかる|
|コストと使用状況レポート|コストの使用料に関する最も詳細なデータを参照できる|無料|
# AWS Cost Explorer
月にどのくらいコストがかかっているのか、サービス単位で調べられる。
コストは月次だけでなく日次でも出せ、グラフで表示されるため、金額の増減を直感的に把握できる。
# AWS Budgets
特定の閾値を超えたときに、アラートを発行できる
# コストの使用状況を確認する
コストの使用状況レポートでは、コストや使用状況に関する細かいデータが、1日に一回、CSV形式でAmazon S3のS 3バケットに保存される。
これらの情報はAmazon Athena、AmazonRedshift、Amazon QuickSightなどの任意の集計。統計ツールに送れる
# コスト管理のコツ
## 選択は適切か
AWSは多くのサービスを提供していて、中には同じような機能もある。ただし、それぞれ自由度とコストが違うので、どのサービスが望ましいか分析する必要がある。
## 運用は適切か
使ってないのに、サービスをキープし続けてコストがかかっていたり、実は不要なシステムがないか、実情を調査が重要である。
【ポエム】コピペプログラミングから脱却してﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾁｮｯﾄﾜｶﾙになるための記事

# TL;DR
プログラミングを勉強したいけど

- プログラミングに苦手意識を持っている
- どこから勉強したら良いかわからない

そんな人向けに、自分の経験を掘り返した上で、
自分なら今までどうやってきたかを噛み砕いて説明した記事です。

この記事の内容は筆者の主観によって、
こうしたら個人的に理解が進んだという経験をもとに書いています。
ですので、人によっては別の方法の方がよい可能性もあります。
あくまで参考として読んでいただけると幸いです。

## メモ程度の筆者の経歴
- CS系学科出身（卒研でドロップアウト）
- 27歳の時に独学コーダー
- 先輩社員いない中ひたすら独習→転職
- Web制作会社でフロントエンドとバックエンドやってる

# そもそもプログラミングとは
> コンピューター（英語: Computer Programming）とは、ある特定のコンピューティングの結果を得ることを目的として、実行可能なコンピュータープログラムを設計・構築するプロセスのことである。

https://ja.m.wikipedia.org/wiki/プログラミング

例えばフロントエンドならAPIにリクエストを発信して受け取った値をブラウザに表示する「処理を実装する」こと、
バックエンドなら、APIからPOSTを受け取ってデータベースの値を更新する「処理を実装する」ことが当てはまります。

# プログラミングに必要な知識
個人的にプログラミングに必要な知識は**重要な順**に

- 実装したい処理に対して、処理フローを設計する知識
- 言語を問わないプログラミング知識
- 言語に関する知識
    - 言語仕様に関する知識
    - フレームワーク・ライブラリに関する知識

だと思っています。
主として設計知識やプログラミング基礎の知識があり、
そこに言語ごとの仕様やフレームワーク・ライブラリの知識が積み上がっていくイメージとなります。
土台ができているか否かで、新規学習の難易度はグッと下がります。
また、言語共通の仕様を理解しているのならば、
別の言語を理解するのも容易になります。

## 言語に関する知識
実務で一番重要になってくるのは言語そのものや
ライブラリに関する知識になるかと思います。

おそらく、ここについては通常業務をこなしていれば自然と身についてくる、
自主的に学習する際真っ先に学習対象になってくる部分ではないかと思います。

こちらについては特筆することもないかと思うので省きます（書くのめんどくさい）

言語に関する知識について、
なんとなくで学習すると言語仕様についての知識は割と抜けがちなので
しっかりやっておくと後が楽です。

## 言語を問わないプログラミング知識
言語を問わないプログラミング知識には、
例えば上記のプログラミング三大要素に加えて

- 変数
- 関数
- クラス

などの処理のまとまりや、
各変数・定数の型、例えば

- 文字列型(String)
- 整数型(Int)
- 浮動小数点数型(Float)
- 真偽値型(Boolean)
- 配列型・オブジェクト型

などがあります。

上記を組み合わせた設計理論なども
言語を問わない知識に入るかと思います。

上記は大まかな言語の方向性さえ揃っていれば
新しい言語やフレームワークにも応用できるので、
言語を問わない知識を身につけていると新規学習をする際のハードルが
グッと下がるようになります。

## 実装したい処理に対して、処理フローを設計する知識

プログラミングの基礎の基礎はこの部分であり、
おそらくなんとなくコピペから入った最初に突き当たる壁がこちらになります。
そして、所謂CS（情報科学）系学科でまず最初に勉強する部分がここになります。

この知識を伸ばすには、まずフローチャート描く練習をします。
いきなりソースコードを書くのではなくフローチャートを利用した上で、
プログラミングの三大要素である

- 順次
- 分岐
- 繰り返し

という概念を身につけます。

また、分岐を構築するためには

- 論理演算

の基礎が大事になってきます。

また、繰り返しの拡張である

- 再帰処理

も重要ですが、こちらは実際にプログラムを動かしながら
勉強するほうが理解度は高まるかと思います。

### フローチャートを描く能力の身につけ方について
例えば[FizzBuzz](https://mosipro.com/fizz-buzz/)や、[自販機](http://beyondbb.jp/Materials/%E7%94%9F%E5%BE%92%E7%94%A813_VendingMachine_140428.pdf)などの例題を探して、
フローチャートを書いてみます。

フローチャートじゃ味気ない、なんかイマイチ乗り気にならないという場合は、
Scratch

https://scratch.mit.edu/studios/1168062

や、ゲームを利用した

https://www.nintendo.co.jp/switch/awuxa/

ビジュアルプログラミングから入ると、
フローチャート・アルゴリズム部分を重点的に訓練することができるかと思います。

# というわけで
基礎は大事( ｰ`дｰ´)ｷﾘｯ
【MySQL学習】InnoDBの自動構成

# はじめに
InnoDB関連のシステム変数の自動構成について学習したことを簡単にまとめます。

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

# InnoDBの自動構成（innodb_dedicated_server）
サーバーのスペックをもとにシステム変数を推奨値に自動設定してくれる機能です。
※MySQL8.0.3から追加されました。

自動設定されるシステム変数は以下の4つです。
・innodb_buffer_pool_size
・innodb_log_files_in_group
・innodb_log_file_size
・innodb_flush_method

## 【注意】
こちらの機能は、使用しているサーバがMySQLのみを運用していることが前提とされています。
そのため、サーバにMySQLの他にアプリサーバ等を稼働させている場合は推奨されません。

他に稼働しているサービスがない、またはDockerやVMなどを使って、サーバがMySQLのみに注力できる環境の場合に効果を発揮します。

## 利用する
innodb_dedicated_serverシステム変数をONにして再起動することで利用できます。

my.cnfにinnodb_dedicated_serverの設定を追記します。

```shell
sh-4.2#  sudo vi /etc/my.cnf
[mysqld]
・・・
innodb_dedicated_server=ON
```

my.cnfを修正し、MySQLを再起動するとON担ってることが確認できます。

```shell
mysql> show variables like 'innodb_dedicated_server';
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| innodb_dedicated_server | ON    |
+-------------------------+-------+
1 row in set (0.02 sec)
```

## InnoDBバッファプールサイズ（innodb_buffer_pool_size）
グローバルバッファの中で一番重要なバッファで、テーブルのデータそのものと、インデックスのデータを持っています。
※デフォルトは128MB

### 自動構成を利用している場合
以下の通りにサイズが自動設定されます。

サーバのメモリが1GB未満の場合
　→ 128MiB (デフォルト値)

サーバのメモリが1GB〜4GBの場合
　→ サーバのメモリの50%

サーバのメモリが4GBを超える場合
　→ サーバのメモリの75%

近年のシステムの本番環境などでメモリが1GBのマシンをDBサーバに使うケースは少ないと思います。
なので、デフォルト値である128MiBは圧倒的に足りないと感じられます。

## InnoDBのログファイルの数（innodb_log_files_in_group）
ロググループ内のログファイルの数を指定します。
デフォルト (推奨) 値は2です。
対象となるログファイルの出力先は、innodb_log_group_home_dirで指定できます。

### 自動構成を利用した場合
InnoDBバッファプールサイズの自動設定値より、以下のように構成されます。

InnoDBバッファプールサイズが2Gバイト未満の場合
　→　2
InnoDBバッファプールサイズが8GB未満の場合
　→　丸められたバッファプールサイズ　ROUND(バッファプールサイズ(GB))
InnoDBバッファプールサイズが8GB〜128GBの場合
　→　丸められたバッファプールサイズの75%　ROUND(バッファプールサイズ(GB) * 0.75)
InnoDBバッファプールサイズが128GBを超える
　→　64

### InnoDBのログファイルの出力先（innodb_log_group_home_dir）
InnoDBのRedoログファイルへのディレクトリパスです。
この数は、innodb_log_files_in_groupで指定されます。
innodb_log_files_in_groupがデフォルト(2)の場合、データディレクトリ内にib_logfile0、ib_logfile1という2つのファイルが作成されます。

## ログファイルのサイズ（innodb_log_file_size）
InnoDBの各ログファイルのサイズ(バイト単位)です。
デフォルト値は48MBです。

増やすことでページのフラッシュを遅らせることができ、更新処理性能が期待できます。

設定値は、1MBから「1/グループ内のログファイルの数」のサイズまでが適切な設定値の範囲となります。
値を大きくするほど、バッファープール内で必要となるチェックポイントフラッシュアクティビティーの数が少なくなります。
これは、ページのフラッシュを遅らせることになり、ディスクI/Oを節約され、更新処理の性能向上が期待できます。

ただし、ログファイルを大きくすると、クラッシュリカバリの速度が遅くなります。
※MySQL5.5以上では、リカバリのパフォーマンスが改善され、ログファイルのサイズへの考慮事項も少なくなっているとのこと。
詳しくは[こちら](https://dev.mysql.com/doc/refman/8.0/ja/optimizing-innodb-diskio.html)

### 自動構成を利用した場合
InnoDBバッファプールサイズの自動設定値より、以下のように構成されます。

InnoDBバッファプールサイズが8GB未満の場合
　→　512MiB
サーバのメモリが8GB〜128GBの場合
　→　1024MiB
InnoDBバッファプールサイズが128GBを超える
　→　2048MiB

## innodb_flush_method
InnoDBのデータファイル、ログファイルをフラッシュする方法を指定します。
これにより、I/Oスループットが影響を受ける可能性があります。
Unix、Linuxでのみ変更が可能で、Windowsはasync_unbufferedで固定となります。

### 自動構成を利用した場合
O_DIRECT_NO_FSYNCが設定されます。
もしO_DIRECT_NO_FSYNCを設定できない場合、デフォルトのfsyncが設定されます。
各設定値の詳細は[こちら](https://dev.mysql.com/doc/refman/8.0/ja/innodb-parameters.html)

# 参考文献
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/innodb-dedicated-server.html

https://dev.mysql.com/doc/refman/8.0/ja/innodb-parameters.html
GoLand でdocker composeするときに、volumesについてのキャッシュを利用させないための設定

:::note warn

訂正
こちら、データヴォリュームの更新を反映するには`--force-recreate`も合わせて行う必要がありました。初版では、`--force-recreate`は設定せず、`--renew-anon-volume`だけすればよいような書き方をしてしまっていた（私自身そう思っていた）ので、訂正しております。

https://docs.docker.jp/engine/userguide/dockervolumes.html

> **ボリュームはコンテナ作成時に初期化されます。** コンテナのベース・イメージ上で、特定のマウント・ポイント上のデータが指定されている場合、初期化されたボリューム上に既存のデータをコピーします。
:::

GoLand 2022.1.1
Intellij, PyCharmなど、他のJetBrainsのIDEにもおそらく共通するとはおもいます。

クリーンアーキテクチャとGoの勉強用に、良さそうなプロジェクトをクローンして手元で起動したりソースコード読んだりと遊んでいました。
https://github.com/bxcodec/go-clean-arch

docker composeをあまり触ったことがなかったのですが、開発用のDBをこんなに簡単に準備できるのか、と感動しました。

こちらのプロジェクトでは、プロジェクト直下のP`docker-compose.yaml`ファイルにて、アプリケーションとMySQLのコンテナ起動を定義しています。

MySQL部分はこんな感じで、`mysql:5.7`のimageをそのまま使い、volumesにて、初期化時に走らせるsql文を渡したり、ユーザーパスワードを設定しています。
* mysqlのDockerイメージ公式 → https://hub.docker.com/_/mysql/  （`Initializing a fresh instance`の項目）
* https://qiita.com/NagaokaKenichi/items/ae037963b33a85df33f5 「Docker MySQLコンテナ起動時に初期データを投入する」こちらの記事も分かりやすかったです。

```docker
mysql:
    image: mysql:5.7 
    container_name: go_clean_arch_mysql
    command: mysqld --user=root
    volumes:
      - ./article.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
      - 3306:3306
    environment:
      - MYSQL_DATABASE=article
      - MYSQL_USER=user
      - MYSQL_PASSWORD=password
      - MYSQL_ROOT_PASSWORD=root
    healthcheck:
      test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
      timeout: 5s
      retries: 10

```

さて、初期データ入れたり、機能追加のためにテーブル増やしたりしたいなと思い、マウント元である`article.sql`に変更を加えてdocker compose upを実行しましたが、起動したコンテナを見ると、`article.sql`の変更が反映されていないようです。

当初、以下の画像のように
docker compose up 時のオプションとして、
--force-recreate` ＝ 「設定やイメージに変更がなくても、コンテナを再作成する」 
をいじってみましたが、やはりデータベースは更新されない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317324/97b16df3-8d9b-ef16-89bc-17311894e4de.png)


公式を確認すると、以下のようにありました。https://docs.docker.jp/engine/userguide/dockervolumes.html


>データ・ボリュームは、データ保持のために設計されており、コンテナのライフサイクルとは独立しています。そのため、コンテナの削除時、Docker は 決して 自動的にボリュームを消さないだけでなく、コンテナから参照されなくなっても”後片付け”をせず、ボリュームはそのままです。


コンテナのライフサイクルと、データボリュームは別なので、article.sqlの変更をdocker compose upのたびに反映させる場合は、

`--renew-anon-volume` 
> 以前のコンテナからデータを再利用せず、匿名ボリュームの再作成

`--force-recreate`と合わせて、こちらの指定も必要でした。

GoLandの画面でいうとこれですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317324/fea84e3a-e913-9a7f-107e-afb243232d7f.png)


ただし、この設定をすると、`article.sql`に変更を加えていないときにも毎回マウントしなおすことになり無駄です。
なので、この設定をしたRun Configurationに「docker compose up  mysql renew-anon-volume」のように名前をつけて、必要なときにだけこちらを使うようにしています。
Spring BootにThymeleaf Layout Dialectを使う

一つのウェブ画面にはヘッダー、フッターなど共通で使っているところがあります。
それらが画面ごとに書かれていて、ヘッダーを修正する場合、全ての画面を触らなあかんですね。
そんな面倒くさい作業を避けるために、Thymeleaf Layout Dialectを使って画面レイアウトの共通化をやってみます！
## イメージ図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727545/6b58cb71-8243-b9e0-f9b6-b5dbf6238cef.png)
## build.gradleにThymeleaf Layout Dialectの依存関係を追加
```
dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:2.6.2'
	implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:2.5.3'
}
```
Thymeleaf Layout Dialectの他のバージョンは[ここで確認](https://mvnrepository.com/artifact/nz.net.ultraq.thymeleaf/thymeleaf-layout-dialect)
## レイアウト設定
### beanの登録
``` 
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
import nz.net.ultraq.thymeleaf.LayoutDialect;

@Configuration
public class LayOutConfig {
	
	// thymeleaf layout
	@Bean
	public LayoutDialect layoutDialect() {
	    return new LayoutDialect();
	}
}
``` 
layout-dialectを使うためにはbeanの登録が必要です。
### ディレクトリ構成
``` 
templates
	ㄴfragments
	|	ㄴconfig.html
	|	ㄴfooter.html
    |	ㄴheader.html
    ㄴlayout
	|	ㄴlayout.html
	ㄴindex.html
```
*フォルダ名やファイル名はご自由につけてください。その場合、`layout.html`で各fragmentのパスを書くときに注意してください。
#### config.html
```
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
    <th:block th:fragment="config">
        <head>
            <!-- メタデータ、共通で使用するcssやjsファイルなどを宣言 -->
        </head>
    </th:block>
</html>
```
・`th:fragment=""`にfragment名を書きます。
#### header.html
```
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
  <th:block th:fragment="header">
    <!-- ヘッダーの内容を記入 -->
  </th:block>
</html>
```
#### footer.html
```
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
  <th:block th:fragment="footer">
    <!-- フッターの内容を記入 -->
  </th:block>
</html>
```
#### index.html
```
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="~{layout/layout}">
  <th:block layout:fragment="content">
    <!-- メイン内容を記入 -->
  </th:block>  
</html>
```
→`layout:decorator="~{layout/layout}"`：layout.htmlのパス(.htmlは省略)
#### layout.html
```
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
  <th:block th:replace="fragments/config :: config"></th:block>
  <body>
    <div>
      <th:block th:replace="fragments/header :: header"></th:block>
      <th:block layout:fragment="content"></th:block>
      <th:block th:replace="fragments/footer :: footer"></th:block>
    </div>
  </body>
</html>
```
→`<th:block th:replace="fragmentのパス(.htmlは省略) :: fragment名"></th:block>`
→`<th:block layout:fragment="メイン内容のfragment名"></th:block>`
## 結果画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727545/ea5d4de6-4ef7-e5f2-ae9c-9905a6692bbb.png)
## おわり
詳細のコードは[ここをクリック](https://github.com/crane93/qiita-article/tree/main/thymeleaf-layout-dialect/demo)