OmniAICreator/Qiita-1.07M huggingface dataset:
[競プロ用]有向最小全域木まとめ

# (無向)最小全域木を求める方法

双方向に繋いでいる場合には以下の方法で最小全域木を構築できる。

* プリム法
* クラスカル法

https://qiita.com/Kept1994/items/051594a52dee5f8a4d3f

これらは辺に向きがあると使えない。

# 本題

最小全域木に向きがあったらどうするか？
つまりあるノードを根とした時にそこから全てのノードへ移動可能な木を構築した際に必要なコストはいくつか？という問に対してどう回答するか。

有向最小全域木を求めるには`Chu-Liu/Edmond`のアルゴリズムというのがある。
ここでは強連結成分分解を用いて有向最小全域木を構築する。

## 基本のアイデア

まず最も理想的でシンプルな有向最小全域木を考えてみる。
各ノードにおいて、そのノードへ流入する辺のうち最も小さいものが選択された場合に最小全域木になっていれば何も難しくない。

`Fig1-1`において、根である`ノード0`を除く全てのノードにおいて流入する辺の中で最小コストのものを選ぶ。

* `ノード1`に流入する辺は`0→1を結ぶコスト1の辺`のみなのでこれを選ぶ。
* `ノード2`に流入する辺は`1→2を結ぶコスト1の辺`もしくは`3→2を結ぶコスト10の辺`なので低コストな前者を選ぶ。
* `ノード3`に流入する辺は`0→3を結ぶコスト10の辺`もしくは`2→3を結ぶコスト1の辺`なので低コストな後者を選ぶ。

こうして構築されるのが`Fig1-2`のようなグラフになる。
見てみると赤字の辺が採用された辺であり確かに根から辿ることで全ての辺へ移ることが可能である。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406130/888830b2-62bc-2b03-a837-f083e3fbde2a.png)

ではまず、この方法で生成するグラフが必ず`有向最小全域"木"`なのか？というところを考える。

全N個のノードのうち根を除くN-1個のノードに対して1つの辺を採用したグラフなのでグラフが連結であれば必ず木になっているし、Fig1-2の通り有効最小全域木になる。
では、グラフが非連結になる場合。これは当然有効最小全域木とは言えない。
ではどういうケースで非連結になるのか？

→ どこかでサイクルが発生している状況である。例えば`Fig2-1`を見てみる。
同様に書くノードの最小コストの辺を選択する。

* `ノード1`に流入する辺は`0→1を結ぶコスト1の辺`のみなのでこれを選ぶ。
* `ノード2`に流入する辺は`1→2を結ぶコスト10000の辺`もしくは`3→2を結ぶコスト1の辺`なので低コストな後者を選ぶ。
* `ノード3`に流入する辺は`0→3を結ぶコスト10の辺`もしくは`2→3を結ぶコスト1の辺`なので低コストな後者を選ぶ。

すると構築される新たなグラフは`Fig2-2`のようになる。

## サイクルが発生したらどうするか

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406130/32476140-d76c-937d-68f1-30c38d6b5e79.png)

### 強連結成分をマージする

2と3を結ぶ辺はいずれのノードから見ても最小コストの辺を選択しているのでどちらかがその辺を諦めて別の辺から流入することにするしかない。
ここで重要なのは2と3の間の辺を両方とも切るケースは考える必要がないことである(`Fig2-3`少なくとも2か3はコスト最小の辺を選んだら？ってなる)。
→ つまり、ノード2と3は切り離す必要がないなら単一のノードと考えても差し支えない。(`Fig2-4`の赤いノード)

2と3のように違いに行き来可能な強連結成分を1つにまとめる時には`強連結成分分解(SCC)`というアルゴリズムが役に立つ。
ここでは説明を割愛。

また、ここで強連結成分を構成する2←→3の辺の合計値`2`は辺をどちらかの辺を譲ったとしても必ずかかる辺のコストなのであらかじめこの段階でカウントしておき、どちらかの辺に譲った場合に追加でかかるコストで辺のコストを上書きしておく。(`Fig2-4`の緑の辺)

(`Fig2-4`の緑の辺について念の為補足的な説明)
`元々のグラフでノード0→3のコスト10の辺`を選択するとなると`元のグラフのノード2→3のコスト1の辺`を辞めて変更することになるので差分は9。これが上書き後のノード0→強連結成分2へのコスト9に対応している。

### サイクルに属しておらずここで選択された辺は必ず採用してOK

サイクルが発生してしまっている部分でどちらかの辺を譲りましょうという話なのでサイクルに関係していない辺が選ばれないことで得することは起こり得ない。→ サイクルに関わらない辺なら有効最小全域木に使用されると言い切れるのでこの段階でカウントしてしまい、それ以上考慮不要なのでコストを0に上書きする。(`Fig2-5`)

### 次は何するの？

実はこの先は同じことを繰り返すだけでいい。
結局、強連結成分をまとめて新たなノードにし、コストを新たな値に直したことで、単に`Fig2-6`のようなグラフが出題されている状況と同値なのだ。(もちろんカウンタsumの値は初期値と異なるが)
つまりはサイクルがないかを探し→あるなら確定させた上で辺のコスト更新とノード縮約を実施。サイクルがなくなった(=木になったら)終了すればいい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406130/93ef8119-6595-bb9b-ac46-d2e6980f872f.png)

一応`Fig2-5`から先を実施すると、

* `ノード0`は根なので無視。
* `ノード1`に流入する辺は`0→1を結ぶコスト0の辺`のみなのでこれを選ぶ。
* `ノード2`に流入する辺は`1→2を結ぶコスト9999の辺`もしくは`0→2を結ぶコスト9の辺`なので低コストな後者を選ぶ。

よって、以下の木が構成され、これは有効最小全域木になる。コストは12と分かる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406130/16eb89b4-76d3-64bf-3645-8bb4409a7dfa.png)

## 早くコードを見せろ

verifyに使った問題は以下
https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_2_B&lang=ja

提出
https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=7990028#1

# もう少し発展

そもそも構築した木自体が欲しくなったらどうする？

サイクルでない辺を採用する際にはその辺はグラフに取り込んでOK。サイクルは保留しておき、後からあるノードへの別の流入経路(辺)を採用したらそっちで上書くようにしたらいいなじゃないかと思う。
kustomize buildしたときに`Error: invalid Kustomization: json: cannot unmarshal string into Go struct field Kustomization.patches of type types.Patch`で失敗

インターネットに情報があまりなさそうだったのでメモ程度に書いています。
## 結論
結論から先に書くと手元とリポジトリのkustomizeのバージョン差異だった
- 手元のMac kustomize 5.1.0
- リポジトリ kustomize 4.2.0

## 現状
overlays/production以下などでkustomize buildを行うとコケた。
少し調べてみると`patches:`の書き方が古いのでこのエラーが出ているっぽい。

``` shell
$ kustomize build .
Error: invalid Kustomization: json: cannot unmarshal string into Go struct field Kustomization.patches of type types.Patch
```

手元のMacにインストールされているkustomizeのバージョンは5.1.0だったが、リポジトリで使用されているバージョンは4.2.0だった。
``` shell
$ kustomize version
v5.1.0
```


## 修正
再インストールするよりもasdfでkustomizeのバージョン管理を行ったほうが良い気がしたので追記(2023/11/22)

### asdfでkustomizeをバージョン管理する
asdfのガイドを参考にasdfをインストールする。今回はbrew+zshの環境です。
https://asdf-vm.com/guide/getting-started.html

``` shell
# asdfをインストール
$ brew install asdf

# brewでインストールしてzshを使用している場合
$ echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ${ZDOTDIR:-~}/.zshrc
```

asdf pluginでkustomize pluginを入れてkustomizeをインストールします。
https://github.com/Banno/asdf-kustomize
``` shell
# kustomizeプラグインを追加
asdf plugin-add kustomize https://github.com/Banno/asdf-kustomize.git

# kustomize 4.2.0をasdf経由でインストール
$ asdf install kustomize 4.2.0
Downloading kustomize from https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv4.2.0/kustomize_v4.2.0_darwin_arm64.tar.gz

# kustomize v4.2.0を使うようにする
$ asdf global kustomize 4.2.0
``` 
kustomize v4.2.0が使えるようになりました
``` shell
$ kustomize version
{Version:kustomize/v4.2.0 GitCommit:d53a2ad45d04b0264bcee9e19879437d851cb778 BuildDate:2021-06-30T22:49:26Z GoOs:darwin GoArch:arm64}
```


### brewでインストールされているものをアンインストールしてからバイナリをバージョン指定してインストールする

https://kubectl.docs.kubernetes.io/installation/kustomize/binaries/
``` shell
# brewでインストールされていたものを削除
$ brew uninstall kustomize

# バイナリをバージョン指定してインストール
$ curl -s “https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh” | bash -s <version>

#今回の場合は4.2.0を入れた
$ kustomize version
{Version:kustomize/v4.2.0 GitCommit:d53a2ad45d04b0264bcee9e19879437d851cb778 BuildDate:2021-06-30T22:49:26Z GoOs:darwin GoArch:arm64}
```

本当はリポジトリのkustomizeのバージョン上げるのが良いですが、大変だったり難しかったり、今すぐ結果を見たい時は手元のバージョンを下げる手段を取るのが良いんだろうなと思いました。

### 参考

https://dev.classmethod.jp/articles/install-specified-version-kusotmize/
単一責任の原則 の説明をできるだけ簡潔にやってみたい

# はじめに
単一責任の原則というのをご存知でしょうか？
SOLID原則のうちの一つに含まれる原則で、CleanArchitecture にて、モジュールの関係性を「モジュールはたったひとつの変更を望む人に対して責任を負うべきである」と説明している原則です。

よくクラスAとかクラスBとか依存だとか関係だとか抽象的な言葉で説明されているため、私が全く飲み込めなかったため、具体的な例に落とし込んでみました。

## 変更とは？責任とは？

### 変更
そのままの意味。
クラスや、インターフェース、関数など、ソースコードに関わるすべてのものに対する変更

### 責任
こちらもそのままの意味
そのモジュールの役割＝責任

例えばTeacher とStudentというクラスを考えます。
Teacher クラスはteach メソッドの引数にもらったStudent に対して、subject をセットすることを責任として持っています。
Student.setTeachSubject を呼ぶことで、Student がなんの科目を教えられたのかを保存します。

```TypeScript
class Teacher {
	teach(student: Student, subject: string) {
		student.setTeachedSubject(subject)
		console.log(`${student.name} に${subject}を教えました`)
	}
}


class Student {
	private const teachedSubject: string
	
	setTeachedSubject(subject: string) {
		this.teachedSubject = subject
	}
}
```



## 変更を望む人とは？
Teacher クラスの例えをそのまま使うと、**Teacher クラスに依存している別のロジック**が、変更を望む人たちと言う事になります。

例えば Teacher クラスを使う、TeachingService というクラスを作成したとします。
```TypeScript
class TeachingService {
	teachingMath() {
		const student = new Student()
		const teacher = new Teacher()
		const subject = '数学'
		teacher.teach(student, subject)
	}
}
```

TeachingService は、teachingMath というメソッドを持っており、名前の通り数学を教える役割を持っています。
そのロジックの中でTeacher クラスに依存しています。

もしteachingMath メソッドで、subjectを複数保存したい。などの希望が出てきたとき
、初めて**TeachingService クラスはTeacher クラスの変更を望む人**になります。

今この瞬間、Teacherクラスに依存しているクラスは**単一**で、Teacher クラスを変更を望む人も単一な状態です。

つまり、Teacherクラスはたった一つの変更を望むクラスTeacherServiceに対して責任を負う。という意味で単一責任の原則を適用された状態になっています。


##  変更を望む人が複数いたらどんな不都合がある？
さて、単一責任の原則。という名前が付いているのは、変更を望む人が複数いると不都合が発生するからです。


では、変更を望む人が二人いるときのことを考えてみます。
TeachingService と同様に、Teacher クラスに依存しているClubService が新しく出来上がったとします。

```TypeScript
class ClubService {
	teachingSoccer() {
		const student = new Student()
		const teacher = new Teacher()
		const sports = 'サッカー'
		teacher.teach(student, sports)
	}
}
```

teachingSoccer メソッドは、生徒に対してサッカーを教える責任を持っています。
TeachingServiceと同様、teachingSoccer でteach メソッドに変更を加えたくなったとき、ClubService はTeacher クラスの変更を望む人になります。

これにより、Teacher は単一責任の原則に違反した状態になりました。

また、ClubService もTeachingService も、お互いのことは考慮せずにteach メソッドを使用しています。

元々、Teacher クラスはTeachingService に対して責任を負っていたため、TeachingService の要求に従ってteach メソッドのロジックを変更しましょう。

TeachingService はsubject が数学の時以外はエラーを返すようにしたとします
（そんな変更要求はなさそうですが。。。）

```TypeScript
class Teacher {
	teach(student: Student, subject: string) {
		if(subject !== '数学') {
			throw new Error()
		}
		
		student.setTeachedSubject(subject)
		console.log(`${student.name} に${subject}を教えました`)
	}
}
```

そうすると、ClubService は常にエラーを返却されてしまうことになります。

全く異なる文脈で使用されていることを知らないまま、TeachingService がteach メソッドを変更したことで、ClubService が期待する動作を行えなくしてしまいました。

これが単一責任の原則に違反したときの不都合です。

ClubServiceはTeacher クラスを使用せず、ClubService に対して責任を負う別のクラスを参照すべきなのです。

## まとめ
この記事では単一責任の原則に付いて、簡単なロジックを使って説明しました。
異なる文脈で使用されるロジックは、簡単に不具合を起こすことができるため、単一の文脈で使用されるようにクラス間の関係性を整理することが重要になります。
ブラウザの開発者ツールでJavaScriptをデバッグする

ブラウザの開発者ツールでJavaScriptのデバッグを行う方法を記載します。
これを知っておくと、手軽にJavaScriptの動作確認ができるので便利です。

本記事ではGoogle Chromeを使用しておりますが、FirefoxやMicrosoft Edgeでも同様にできます。

# JavaScriptのファイルを開く
デバッグしたいJSを使用している画面をブラウザで開きます。
画面上で「右クリック → 検証」をクリックすると開発者ツールが開きます。
windowsなら「F12キー」、Macなら「option + command + i」でも開けます。

開発者ツール上の「Sources」タブをクリックすると、左エリアに「Page」が表示されます。
「Page」には画面で使用されているファイルが表示されているので、今回デバッグしたいJSのファイルを選択すると、中央エリアに選択したファイルのコードが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/ba79d8b6-f032-f7e8-e0c4-0dbfb1dff216.png)

# ブレークポイントを設定する
コード上にブレークポイントを設定することで、設定した箇所で処理の実行を止めることができます。
コードの任意の行番号をクリックすると、行番号が青くなり、ブレークポイントが設定されます。
ブレークポイントは複数設定することもできます。
設定したブレークポイントの一覧は、右エリアの「Breakpoints」で確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/742cd8be-88fd-4094-054e-715ce95bbba5.png)

# JavaScriptを実行する
JSを実行し、ブレークポイントで処理を止めます。
定義されている変数の一覧が、右エリアの「Scope」に表示されます。
関数内で定義した変数は「Local」に表示されます。
画像では"params"、"msgType"、"msg"を定義しており、止めた時点でのそれぞれの値が表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/cb530e44-5409-d831-ca01-061a6dde7825.png)

# 処理を進める
ブレークポイントで止めた箇所から処理を進めることで、処理がコード上のどこを通っているか確認できます。
処理の進め方は以下の方法があります。
## Resume
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/476dde6f-6800-68f2-35c1-7219d9192601.png)
止まっていた箇所から次のブレークポイントまで進みます。
以下の画像では、6行目でResumeを実行すると、12行目に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/56d5b281-429f-6e9c-1342-276ca91b1ab2.png)

## Step over
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/c3d26d4a-33d3-64e3-5dde-ef5e8bcb91aa.png)
止まっていた箇所から1行ずつ進みます。
ただし、関数内部では止まりません。
以下の画像では、9行目でStep overを実行すると、12行目に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/a45654a2-48a7-a4c0-d04f-3ba4b40cc8e1.png)

## Step into
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/72f4185f-0ea6-67d1-1aa6-1a710a390ecb.png)
止まっていた箇所から1行ずつ進みます。
関数内部でも止まります。
以下の画像では、9行目でStep intoを実行すると、18行目に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/cf4b02d7-ee00-bb89-7091-fd399ac13dce.png)

## Step out
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/5a8fc29e-1afa-9a86-8c24-e964838d9c42.png)
止まっていた箇所から1行ずつ進みます。
ただし、関数内部では止まりません。
関数内部でStep outを実行した場合は、関数外部まで処理が進みます。
以下の画像では、18行目でStep outを実行すると、19行目ではなく、12行目に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/26414e01-ecb5-6ffb-3014-4afd333653eb.png)

## Step
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2300564/8dbfd053-98c7-5f19-1ee9-e9eaf958b284.png)
Step intoとほぼ同じ動きになりますが、非同期アクションを無視するといった違いがあるようです。
詳しくは以下の記事が分かりやすかったので参照してください。

https://penpen-dev.com/blog/steoin-stepout-stepover/

***
基本的なデバッグ操作は以上となります。
参考になれば幸いです。
【ExcelVBA】指定したワークブックの参照設定を配列で取得する（Basic > GetData > Config）

```
Option Explicit

Private basic As basic

Public Property Set setBasic(ByRef obj As basic)

    Set basic = obj

End Property
Public Function references(ByRef wb As Workbook) As String()

    Dim ref As Object
    
    Dim result() As String
    
    Dim refCount As Long
    Dim i As Long
    
    refCount = wb.VBProject.references.Count
    ReDim result(1 To refCount, 1 To 2)

    For i = LBound(result, 1) To UBound(result, 1) Step 1
    
        Set ref = ThisWorkbook.VBProject.references.Item(i)
        
        result(i, 1) = ref.Description
        result(i, 2) = ref.FullPath
        
    Next i
    
    references = result
    
End Function
```
～備忘録～　Zoweについて（概要）

Zoweについて学んだことをまとめて見返せるように備忘録を作成した。
参照したサイトはZoweの公式サイトである。

Zowe: https://www.zowe.org/learn

 ## [Zoweとは]
・Zoweはメインフレーム上で管理、制御、スクリプト、開発を安全に行えるようにするオープンソース・ソフトウェア・フレームワークである

・ISV、システムインテグレータ、z/OSコンシューマーを含む全てのZコミュニティーメンバーの為に作られた。

・ZoweにはMacとWindowsのようにAPIとOS機能セットが付属している。

・Zoweはz/OSと対話するためのモダンインターフェースを提供しており、今日のクラウドプラットフォームと同様の方法でz/OSを操作できる。

・Zoweのインターフェースはクライアントやサードパーティー・ベンダーが提供、作成したプラグインや拡張機能でも使用できる。


## [Zoweの構成]
Zoweは以下の7つのコンポーネントで構成される。

・Zowe Application Framework
・API Mediation Layer
・Zowe CLI
・Zowe Explorer
・Zowe Client Software Development Kits SDKs
・Zowe Launcher
・ZEBRA (Zowe Embedded Browser for RMF/SMF and APIs) - Incubator


それぞれについて簡潔に説明すると

- Zowe Application Framework
z/OS機能へのアクセスを可能にする多くのappを含む仮想デスクトップを提供してくれるWeb UI

- API Mediation Layer
z/OSのリバースプロキシとして動作するゲートウェイ、REST APIカタログ、動的ディスカバリ機能を提供してくれる。

- Zowe CLI
オフプラットホームな環境でメインフレームと対話できるCLI。
IDE、シェルコマンド、bashスクリプトなどの一般的なツールが使用可能。
z/OS appのサポートと構築を迅速に効率化したいユーザー向けに、実用性とサービスをセットで提供してくれる。

- Zowe Explorer
開発者とシステム管理者がz/OSメインフレームがモダンな方法で対話することができるようになるVScodeの拡張機能。
z/OS上に保存されたデータセット、USSファイル、ジョブを操作可能になる。
（こいつはよくよくお世話になってる。最近ようやく中身が分かってきた。）

- Zowe Client Software Development Kits SDKs
名前のまんまでZoweが提供するSDK
利用可能なのは、Zowe Node.js Client SDKとZowe Python Client SDK

- Zowe Launcher
これもほとんど名前の通りで、可用性の高いZowe z/OSサーバー・コンポーネント用のランチャー。

- ZEBRA (Zowe Embedded Browser for RMF/SMF and APIs) - Incubator
再利用可能で業界準拠のJSON形式のRMF/SMFレコードを提供してくれる。
それらを活用して多くのISV SWやユーザーがオープンソースSWを様々な方法で利用できる。
(ISVとは、システム開発業界などにおけるソフトウェアの開発・販売会社の分類の一つで、コンピュータメーカーなどのプラットフォーム事業者以外の、また、それらの傘下にない独立系企業のこと。特に、受託開発事業者ではなくパッケージソフトの開発・販売元のことを指すことが多い。)
https://e-words.jp/w/ISV.html


## [感想]
今までなんとなくVScodeの拡張機能使ってたけど今回調べてZoweについて前よりは理解が深まった。
Zoweは比較的最近できた様で(2018年くらい？）その前について理解ができれば、よりZoweの便利さというものが理解できるかも。
というかZoweってなんて読むの。。。。
配列のソート方法のアルゴリズムについてまとめ。バブル選択挿入。

# 初めに
配列のソートアルゴリズムについて基本的な3つの方法を知ったので自分用にまとめる。
サンプルコードはjavaで書く。
バブルだけは全体のコード、他はソート部分だけを。

## 基本交換法(バブルソート)
```java:bubble sort
public class TrySort{
    public static void main(String[] args) {
        // 適当な配列を作る
        int[] array = {3, 5, 4, 1, 2};

        // ++++++++++++++++++++++++++++++
        // バブルソート
        for(int i = array.length - 1; i > 0; i--){  // 内側ループ毎に終了回数を下げていく
            for(int j = 0; j < i; j++){ // 
                if(array[j] > array[j + 1]){  // 左側の方が大きければ入れ替える。
                    // 入れ替え
                    int temp = array[j + 1];
                    array[j + 1] = array[j];
                    array[j] = temp;
                }
            }
        }
        // ++++++++++++++++++++++++++++++

        // 表示
        for(int i = 0; i < array.length; i++){
            System.out.printf("array[%d]...%d\n", i, array[i]);
        }
    }
}
```
あるインデックスjと隣接するインデックスj+1を比較、終わったら一つ右隣のインデックスをj(基準)にして繰り返す。(内側のループ)
これを配列の長さ-1周行う。減っていく(i--;)内側ループの最大値を外側のループで制御(j < i; 内側ループの最大値(比較の回数)を外側のループ毎のiの値に設定)。
一周するごとに最大値が順に確定するため比較の回数が少なくなっていく。
探索はn(n-1)/2回かかるらしい知らんけど



## 選択ソート
```java:selection sort
        // 選択ソート
        for(int i = 0; i < array.length - 1; i++){
            for(int j = i + 1; j < array.length; j++){ // 外側ループのインデックスを基準としてその右~最後のインデックスまでをそれぞれ比較 
                if(array[i] > array[j]){  // 基準のほうが大きいなら入れ替える
                    // 入れ替え
                    int temp = array[j];
                    array[j] = array[i];
                    array[i] = temp;
                }
            }
        }

```
バブルソートの改良版。
あるインデックスにを基準として右のインデックス~最後のインデックスまでをそれぞれ比較
あるインデックスを外側のループで制御



## 挿入ソート
```java:insertion sort
        // 挿入ソート
        for(int i = 0; i < array.length - 1; i++){  // [0]~[最後から一つ前]まで繰り返す
            for(int j = i; j >= 0; j--){ // 外側ループのインデックスを基準として、その右と比べ(※)入れ替え処理ができたなら、基準インデックスを左にずらし今入れ替えれた値を基準に変え、同じ処理を適した位置になるまで繰り返す(内ループ)。 
                if(array[j] > array[j + 1]){  // その右と比べ(※)ただしい順番に入れ替える
                    // 入れ替え
                    int temp = array[j + 1];
                    array[j + 1] = array[j];
                    array[j] = temp;
                }else{
                    break;  // それ以上左にずらせない適した位置まで移動出来たら内ループを抜ける
                }
            }
        }

```
あるインデックスと右のインデックスを比べ正しい位置になるまで左と交換し続ける
あるインデックスを外側のループで制御

## おわり
ほかにもシェルソート、クイックソート、ヒープソートといったより高速なソートアルゴリズムもあるらしい。
今度まとめるかも。
Next.jsでStoryBookを使うもModuleNotFoundError


# 結論
.storybook/webpack.config.jsをを実装してください。 pathは各自の環境に合わせてください。

```JavaScript:webpack.config.js
const path = require('path');

module.exports = ({ config }) => {
  config.resolve.alias = {
    '@': path.resolve(__dirname, '../'),
  };

  return config;
};
```
以上です。

# 　エラー
以下に結論までの詳細をかきます。

storybookを導入し起動しようとした際に、次のエラーがでてしまった場合について説明します。
```bash:terminal
$ npm run storybook

// something

<i> [webpack-dev-middleware] wait until bundle finished
99% end closing watch compilationWARN Force closed preview build
ModuleNotFoundError: Module not found: Error: Can't resolve 
'@/app/components/StyledButton' in '/Users/apple/your-app/stories'
    at <anonymous> (/Users/apple/your-app/node_modules/webpack/lib/Compilation.js:2022:28)
```

# 原因
storybookが、`@`のalias-pathが解決できていないためエラーとなっています。
`@`のパスを定義してあげると解決します。

# 解決方法
結論の章と重複するが以下の方法で解決します。
1. .storybook/webpack.config.jsを作成する
1. @のaliasを定義する
1. storybookを再起動する

私の場合は、@がプロジェクトルートを指しており、またプロジェクトルート直下に.storybookがあるため `'@': path.resolve(__dirname, '../'),` と定義しています。
@のパスは各自の環境ごとに合わせて設定してください。

```JavaScript:webpack.config.js
const path = require('path');

module.exports = ({ config }) => {
  config.resolve.alias = {
    '@': path.resolve(__dirname, '../'),
  };

  return config;
};
```

ちなみに、ディレクトリ構成の一例です。この投稿ではつぎの構成を前提としています。
```bash:terminal
. // ← ここに @ aliasを通したい
├── README.md
├── .storybook
│   ├── main.js
│   ├── webpack.config.js // ← 追加
│   └── preview.js
├── app
│   ├── components
│   │   └── StyledButton
│   │       └── index.tsx
│   ...
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── pages/
├── public/
├── stories
│   ├── Button.stories.ts
│   ├── Button.tsx
│   ├── assets/
│   ...
├── styles/
├── tsconfig.json
└── yarn.lock
```

storybookの起動
```bash:terminal
npm run storybook
```

ブラウザからアクセス
```text:ブラウザ
http://localhost:6006/
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102978/8156aeca-022a-2838-08dd-a51a8153fd64.png)


# 補足
この投稿でのstorybookのバージョンは^7.0.24です。

```json:package.json
{
  ...
  "scripts": {
    ...
  },
  "dependencies": {
    ...
    "next": "13.4.6",
    "react": "18.2.0",
    "typescript": "5.1.3"
  },
  "devDependencies": {
    ...
    "@storybook/addon-essentials": "^7.0.24",
    "@storybook/addon-interactions": "^7.0.24",
    "@storybook/addon-links": "^7.0.24",
    "@storybook/blocks": "^7.0.24",
    "@storybook/nextjs": "^7.0.24",
    "@storybook/react": "^7.0.24",
    "@storybook/testing-library": "^0.0.14-next.2",
    "@types/styled-components": "^5.1.26",
    "storybook": "^7.0.24",
    "styled-components": "^6.0.0-rc.6"
  }
}
```

# まとめ
Qiitaに書いたらまとめを書かなければならない気がしたのでまとめると、
お弁当のつつみ風呂敷のそめ落ち具合で他人のお弁当歴を推測しようとするおばちゃんってなんなんでしょうね。
27歳総務職　WEBエンジニア目指すため勉強内容を記録していく③

【勉強内容】
HTML & CSS 学習レッスン 中級編
８～１３

【所感】
・各プロパティをググりながら確認
・インラインとブロック要素の違いなんとなく分かってきた気がする
git rebase

## git rebase
:::note
Gitのコマンド
**ブランチのヒストリーを再構築するために使用**

別のブランチの変更を現在のブランチに適用
コミットの順序を変更したりする
:::

## git rebaseコマンドの使い方

-リポジトリ内でgit rebaseコマンドを実行

- リベースしたいブランチを指定
Ex)
git rebase masterと入力
→現在のブランチを「master」ブランチにリベース

:::note


**リベース操作中にコンフリクトが発生した場合**

→ファイルを編集してコンフリクトを解決し、git addで変更をステージングエリアに追加する
:::


- git rebase --continueコマンドを実行
→リベースを再開

リベースが完了すると
新しいコミットが作成されて、ブランチのヒストリーが再構築されます。

## 詳細情報の確認方法

- git rebase --help を使用

詳細な情報とオプションを確認できる
【AWS】AWSアカウントのサインアップ時に電話がかかってこないときの対処法

# 1.はじめに
どうも、ARIの名古屋支社に勤務している愛知県民こと、
新藏（にいくら）と申します♪
(/・ω・)/

先日、諸事情でAWSアカウントを作成しました。
その際、電話番号を入力して電話から認証コードを聞いて認証をする手順があるのですが、
**以下のエラーが出て電話がかかってきませんでした・・・**

|![010_エラー文.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/4cda0ca7-aed6-31f8-61f8-82f7015bce38.png)|
|:--|

そこで今回は**サインアップの時に、電話がかかってこないときの対処法**
について記事にしたいと思います！

AWS初心者の方、同じエラーで困っている方の参考になれば幸いです。
(*^^)v

# 2.スマホの非通知を拒否する設定を解除する

**非通知を全て拒否する設定だと、先ほどのエラーが出る可能性があるみたいです。**
以上より、まずはスマホの非通知設定を解除してみてください。

それでもエラーが解消しない場合は3章の内容を実施してください。

# 3.サポートとのチャットで認証を実施する
非通知を拒否する設定を解除しても事象が改善しない場合、
**AWSサポートに連絡してもらい、電話をかけてもらうことで、認証を完了することができます。**
では、早速実施してみます。

3.1.AWSマネジメントコンソールにログインします。

3.2.画面上部の検索欄にて「サポート」と入力し、「サポート」を選択します。

|![015_サポートを選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/b85417e3-a8d0-aec1-ed13-305389f686f7.png)|
|:--|

3.3.「ケースを作成」を選択します。

|![016_ケースを作成を選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/cf3d5f95-2a7f-116b-7bb1-6265769af51f.png)|
|:--|

3.4.「アカウントと請求」、「アカウント」、「アカウントにアクセスできません」の順に選択します。

![020_ケースを作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/8f9f4e76-8e07-0910-978c-682c3e141a27.png)

3.5.ケースの詳細を入力し、「お問い合わせ」を選択します。

:::note info
私が実施した時は件名を「サインアップ時に電話がかかってこない」
説明を『「AWSにサインアップ」の画面にて、電話番号を入力しても電話がかかってきません』
としました。
:::

|![030_ケースの詳細を入力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/4acfc02e-d983-935f-6a72-d852403f0cac.png)|
|:--|

3.6.「チャット」を選択し、「送信」を選択します。

:::note info
以下の手順の画像は「チャット」を選択した場合の画像となりますが、
「ウェブ」を選択した場合も同じような流れになると思います。
:::

|![040_ケースの連絡方法を選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/18931e29-cf08-aad6-e093-f91abb840f82.png)|
|:--|

3.7.チャットが開始されます。

3.8.ケースIDを聞かれるので、ケースIDを確認し問題なければ返信します。

|![050_チャットでのやり取り_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/484c5f64-a81c-4533-ed83-31be14f77587.png)|
|:--|

:::note info
ケースIDはケースを作成したときに送信されるメールに記載されています。
また、アカウントIDも後ほど使うので、メモ帳等にコピーしておくと良いです。

|![045_メールでケースIDとアカウントIDを確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/c01125c7-fa88-a60d-97cd-88f4a5238410.png)|
|:--|
:::

3.9.続いて、電話番号を聞かれるため電話番号を返信します。

|![051_チャットでのやり取り_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/03e1405e-1cf9-ecee-4044-a44e32c68667.png)|
|:--|

3.10.電話がかかってきます。

3.11.電話にてアカウントIDを伝えます。

:::note info
アカウントIDは手順3.8のメール、もしくは
マネジメントコンソール右上のアカウント名を選択すると確認できます。

|![060_アカウントIDを確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/aebf06a6-f079-2d8b-c6a2-58cf41975cac.png)|
|:--|
:::

3.12.アカウントIDが合っていれば、AWSサポートにて認証の処理を実施していただけます。

3.13.認証が完了すると、以下のメールが届きます。

|![070_電話認証完了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/bad0d01f-584a-7d20-8421-938b634e65c2.png)|
|:--|

3.14.以下のURLに接続し、サポートプランを選択するとAWSアカウントの作成が完了します。

https://aws-portal.amazon.com/gp/aws/developer/registration/index.html

# 4.おわりに
ここまで読んで下さり、ありがとうございます！！！
(^^)

いやはや、意外と初歩的な部分ですがつまずいてしまったので、記事にしてみました。
とても丁寧に対応していただいたAWSサポートの方、ありがとうございます！

また次も何かしら記事にします。
(:3_ヽ)_
【Git】最初のコミットを変更する方法


## 修正方法
以下のコマンドを実行します。
```:ターミナル
$ git rebase -i --root
```

するとGitで設定しているエディタが開きます。
```
pick f2a0ijl 最初のコミット
pick 4d506gf 2回目のコミット
pick 23456a5 3回目のコミット
```

最初のコミットの`pick`の箇所を編集します。

```
r f2a0ijl 最初のコミット
pick 4d506gf 2回目のコミット
pick 23456a5 3回目のコミット
```
すると以下のようにエディタに表示されます。
```
最初のコミット

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.

```
コミットメッセージを変更して保存し、エディタを閉じます。
```
initial commit

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.

```

コミットメッセージが変更されたことを確認して`push`します。
```
$ git push -f origin main
```
AWS Dev Day にCFPを出す時に読むメモ

ジャーニーマン( @beajourneyman )です。

4年強寝かしていたQiitaを再始動して5日目です。5本目のエントリーになります。いつの日か AWS Dev Day にCFPを出す時に読みたい自分向けのメモを残します。

# ベースはRejectDay2023のAWS金森さんのパネルディスカッション

@yoshii0110 が配信してくれていたのでアーカイブを紹介します。正直、このエントリーはコレがあれば目的を達せられるくらい重要な情報です。運営のみなさん、ありがとうございます。

https://www.youtube.com/live/kMiijJdWi-s?feature=share&t=19480

# CFPを出す時に読むメモ

## CFPとは？

CFPとは Call for Proposals コールフォープロポーザルの略で、技術カンファレンスなどで行われる登壇公募のコトです。一緒にコミュニティ活動をしている戸倉彩さんが解説記事を書かれているので、ご紹介します。

https://note.com/ayatokura/n/n5fb7aebc781d

今回の AWS Dev Day のCFPについては以下のGithubで詳細が確認できます。

https://github.com/aws-events/aws-dev-day-tokyo-2023-cfp

## 当たり前だがCFPを出さないと始まらない

どんなに確率が低くても一歩を踏み出さないと始まりません。スタートラインに立つための最低条件が期日内のCFPエントリーです。

## 採択されるかとCFPで語られる内容の良し悪しは必ずしも一致しない

* セッションのバランスをとても重視する。仮に AWS Lambda を掘り下げるとても質の高いセッションが10エントリーされても、採択されるのは多くて数本である。サーバレス、コンテナ、データベース、開発手法などのカテゴリー毎のバランスを見る。
* Dev Day では単純にサービスの紹介のような内容は採択されない。ただ Summit には合う内容のケースもある。
* あくまで内容を見て決める。近しいテーマの場合にいいね数を参考にするコトはあるが重要ではない。
* AWS内の選定に関わるメンバーが「自分ならこうセッションを回る」を考えてエントリーに投票する。言い換えれば、参加者の体験を考慮した選考を行う。
* 多くのバックグラウンドを持った方が可能な限り丸1日どの時間枠でも楽しめるように組む。3日間くらいかけてじっくり取り組む。
* 言い換えれば、穴場・レアなテーマのCFPは競争率が低いため採択されやすいと言える。

## CFPの書き方、中身について(実際のCPFをその場で講評しながら)

講評サンプルはイベントの運営メンバーのひとり、HTB三浦さんのCFP

https://github.com/aws-events/aws-dev-day-tokyo-2023-cfp/issues/161

* タイトルはとても重要。タイトルから実際の内容が伝わるかどうか。
* アブストラクト(概要)がしっかり書かれていると選考する側も選びやすい。
* 誰のエントリーかは見えない。アブストラクト(概要)で選考する。
* 続く、補足情報で「何を話すか」がイメージできるととても良い。
* 落選の決定打はバランス、Sagaパターンのテーマがたまたま多かった。正直、お手本になるレベルのCFPだった。
* 「気がついたらなってしまった」という部分がアーキテクトに一家言ある選考メンバーにとって若干のネガティブな要素になったかも知れない。

現地でセッションに参加しながらまとめたツイートは以下のとおりです。

https://twitter.com/beajourneyman/status/1672535968585482241

## エントリー状況について

* 今回もギリギリにエントリーされたCFPがとても多かった。
* 前述のバランスを意識してテーマを選ぶのは現実的ではないと思われる。

https://twitter.com/knuna_t/status/1672536617448513537


## セッション時間について

 * 20分、50分、90分などがあっても90分でエントリーしてきた方はいなかった。
 
※イベント参加者がツイートしていた意見でも、20分と50分(もしくは45分)が圧倒的多数でした。90分は短い映画だとの意見も。

# 最後に…

保存版な内容だったのでQiitaにまとめました。金森さん、運営のみなさん、ありがとうございます！！
![スクリーンショット 2023-07-19 0.01.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155285/567d821f-14a4-beb7-d6e0-6997952f1db8.png)

以上です。
Slack ワークスペースにIncoming WebHooksのアプリを追加する方法

# 概要

- SlackのワークスペースにIncoming WebHooksのアプリを追加する方法をまとめる。

# 方法

- Slackのサイドバーにて「アプリを追加する」をクリックする。

    ![90_notice_github_test_-_miriwo-notice_-_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/b8f8af0e-bdab-7542-b36d-57f8f23b832d.png)

- 検索で「Incoming WebHooks」と検索する。ヒットした内容の「追加」をクリックする。

    ![App_-_miriwo-notice_-_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/8e7a1c33-0bfc-3b7b-ab64-6bc9db9d9c31.png)

- チャンネルが合っていることを確認し、「Slackに追加」をクリックする。

    ![Incoming_Webhook___Slack_App_ディレクトリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/082e7272-b604-34b3-b0f4-bfd1939bee7b.png)

- WebHook URLを使って通知したい任意のチャンネルを選択し、「Incoming WebHook インテグレーションの追加」をクリックする。

    ![Incoming_Webhook___miriwo-notice_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/deee9f2a-dd66-a6a4-fcb0-cf33bd3bb382.png)

- 遷移した画面の中に「例」という欄があるので記載されているコマンドをコピーする。

    ![Incoming_Webhook___Slack_App_ディレクトリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/6f1c27e8-883b-be98-105d-6f0068b117b8.png)

- ターミナルなどのコマンドラインツールを開いて、ペーストして実行する。
- 下記のような通知が行われれば追加完了

    ![test_-_miriwo-notice_-_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/e8a513fa-3bbe-d0f6-c41c-22ecfffcd49f.png)
WSL2, Laravel Sail 環境でXdebugを有効にする

# WSL2, Laravel Sail 環境でXdebugを有効にする
## Background
最近laravel sailをよく使うが、xdebug環境を整えたことがなかった。
`php artisan serve`を使わない方法を調べてもなかなか解決しなかったのでまとめ。

## Environment
- wsl2, ubuntu
- PHP 8.2.8, laravel 10.14.1
- Xdebug v3.2.1

## Solution
※sailでアプリケーションディレクトリ作成後からの内容になります。
編集対象のファイルは以下の4つ。
- php.ini
- docker-compose.yml
- .env
- launch.json

### php.ini
通常はvendor配下に存在しているので、以下コマンドでアプリフォルダ直下に持ってきます。
- wslで実行
	- `./vendor/bin/sail sail:publish`
- container内で実行
	- `php artisan sail:publish`
コマンド実行するとアプリディレクトリ直下に`docker`フォルダが作成されます。
中身はこんな感じ
```
-docker/
  -8.0/
  -8.1/
  -8.2/
    -Dockerfile
    -php.ini
    -start-container
    -supervisord.conf
```
php.iniに以下を追加
```ini
[xdebug]
zend_extension = xdebug.so
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.discover_client_host = true
xdebug.idekey = VSC
xdebug.client_host = host.docker.internal
xdebug.client_port = 9003
```

Dockerfileの以下の箇所で配置されています
```Dockerfile
COPY php.ini /etc/php/8.2/cli/conf.d/99-sail.ini
```

### docker-compose.yml
docker-compose.ymlのservecesのアプリコンテナ(デフォルトではlaravel.test)に以下の内容にする
(直接変更した箇所はportsに`9003:9003`を追加しただけ。depends_onはアプリ作成時に選択したサービスによって変わる。)
```yml
    laravel.test:
        build:
            context: ./docker/8.2
            dockerfile: Dockerfile
            args:
                WWWGROUP: '${WWWGROUP}'
        image: sail-8.2/app
        extra_hosts:
            - 'host.docker.internal:host-gateway'
        ports:
            - '${APP_PORT:-80}:80'
            - '${VITE_PORT:-5173}:${VITE_PORT:-5173}'
            - '9003:9003'
        environment:
            WWWUSER: '${WWWUSER}'
            LARAVEL_SAIL: 1
            XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}'
            XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}'
            IGNITION_LOCAL_SITES_PATH: '${PWD}'
        volumes:
            - '.:/var/www/html'
        networks:
            - sail
        depends_on:
            - mysql
            - redis
            - selenium
```

### .env
.evnファイル2以下を追加。docker-compose.ymlで環境変数を渡す。
```
SAIL_XDEBUG_MODE=debug
```

### launch.json
アプリフォルダ直下の.vscodeフォルダのlaunch.jsonを編集。
ファイルが存在しない場合はRun -> Add ConfigurationでPHPを選択してファイル作成。(サイドバーのデバッグから作成も可)
ファイル内容は以下
```json
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for Xdebug",
            "type": "php",
            "request": "launch",
            "port": 9003
        }
    ]
}
```

## Confirmation
1. F5キーを押してデバッグモードを起動
2. web.phpなどデバッグしたい場所にブレイクポイントを設置
3. http://localhost に接続
上記の手順で設定に問題なければ止まってくれると思います。
![](https://storage.googleapis.com/zenn-user-upload/3fef585b8283-20230718.png)

## Conclusion
laravel公式のやり方でやると、`php artisan serve`コマンド実行しないとできなかった。
ネットで探した情報で試してもなかなかうまく行かず。
同じように困っている人の参考になれば。
調べ方のコツ

# はじめに
　現在ソフトウェアエンジニアとして働いていますが、日々スキルを身につけながら感じているのは、
### 『ITスキルは生ものだから、新しい技術が出たときに  "いかに早くキャッチアップできるか" がエンジニアとしての成否を分ける』
ということです。これはエンジニアに限った話ではなく、世のビジネスマン全員に共通して大切な原理原則だと思います。
　今回は、記念すべき Qiita 初投稿 のテーマとして、「調べ方のコツ」を、備忘録も兼ねて記しておきます。

# 戦略を立てる
　私もよく陥りますが、右も左もよく知らない領域でわからないことに直面すると、"そもそも何がわかっていないのかわからない" "手あたり次第に検索するが解決せず、時間だけが過ぎていく" という事態に陥りがちです。
　そうならないためには、いま自分は「どんな問題に直面していて」「こんな情報があれば」「こういうふうに解決できるだろう」という状況整理をすることが大切だと思います。ただやみくもに調べる前に戦略を立てて、解決までの道筋が見えてから、調べるという行為に臨みましょう。
　頭の中でこれらを完結させるのには慣れが必要ですので、はじめは紙やテキストに書き起こして状況を整理するのがおすすめです。

　調べるという行為は一言でまとめると「何がわからないかを整理して言語化すること」です。つまりは、これを意識して極めればよいわけです。

# 仮説を立てる
　調べる前の戦略が立案出来たら、余裕がある方は仮説を立ててみましょう。「どこに原因がありそうか」事前に当てをつけておくことで、ある程度的を絞った検索ワードが浮かんできます。仮説を立てることで、正解にたどり着くまでにかかる時間が短くなりますし、それだけでなく、答えのない問題に対して解決策を導く力が鍛えられるでしょう。

# 調べたことを人に共有する(つもりで理解する)
　調べものが解決したら、アウトプットの機会を作りましょう。せっかく調べて得た知識を頭に定着させるには、一度頭に入れた内容を頭から取り出してあげる作業をすることが鍵になります。ドキュメント化する、人に共有する、定期的に振り返る。その場その場は時間がかかるかもしれませんが、長い目で見ると大きな時間の節約につながると考えます。

# おわりに
　冒頭でも述べましたが、「新しい技術に対していかに早くキャッチアップできるか」これがVUUCA時代に突入したビジネス世界において個人の市場価値をあげるために重要な力の一つだと考えます。ただなんとなく調べるのではなく、考え抜いてから調べる。そう自分にも言い聞かせます。

　初のQiita投稿はここまでとします。今後もアウトプットの場の一つとして活用します。
GASとUIFlowでGoogleスプレッドシートにM5stackの情報を取得する。

商業ディベロッパー勤務の非エンジニアが試行錯誤しながらいろいろなモノを作成をしています。非エンジニア、電子工作1年生のため、とりあえずアレやコレやとやってみようを繰り返しています。

## 1. デバイスデータを取得する方法を模索中

https://qiita.com/am003004/items/b4ca7db6f122e25568c4

前回の記事でもお話ししましたが、単身赴任中の夫とのコミュニケーションをもっと楽しくするために、色々思案中です。
前回は画面クリックでハートを飛ばすというとこまでやりましたが、
デバイス操作で画面にハートが飛ぶようになるといいなと思っています。

### 1-1. M5stackからHTTP POSTをしてみる

ｽﾀｯｸﾁｬﾝというスーパーカワイイロボットにハマっているため、手元にM5stackがあります。
これを使ってHTTP通信を出来るようになりたいです。

## 2. 実装
作ったものはこちら

https://twitter.com/am003004/status/1681273030566354946?s=20

初心者なのでまずはこちらの記事の再現から始めます。

https://elchika.com/article/37f89e20-5af7-4443-9cc4-0957c3f7be90/#h_google%20%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88%20%2B%20GAS

### 2-1. コード

M5stack側はUIFLOWのコードブロックで実装します。
M5stackのボタンを押すとランダムの数字が出るようにして、それをHTTP POSTのPOSTリクエストでGAS側に送信します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2668122/8129fc0f-3a98-51e7-ff7c-66c923cb7909.png)


GoogleAppsScript 側で、WEBアプリでデータの受信と受信日とデータをスプレッドシートに転記するコードを書きます。

```js
function doPost(e) {
  console.log('catch post');
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');
  const params = JSON.parse(e.postData.getDataAsString());
  const status = params.status;

  // データをシートに追加
  sheet.insertRows(2,1);
  sheet.getRange(2, 1).setValue(new Date());      // 受信日時を記録
  sheet.getRange(2, 2).setValue(params);          // 受信データを記録
  sheet.getRange(2, 3).setValue(status);          // 乱数値を抜き出してを記録
}


```



M5stackのボタンを押すと数秒遅れでスプレッドシートに転記されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2668122/8f15284d-f0f1-5f28-5b3a-14d34b5b4bc0.png)



## 3. 簡単に作れた

ここまではお手本記事を参考に作ることが出来ました。
UIFLOWもGASも初心者に優しい。

ここからデータの作り方と取得方法を変更してみようと思いますが、まずはここまで。
Github 自分の特定のリポジトリのコミット状況等をSlackに通知する

# 概要

- Githubのリポジトリをサブスクリプション（購読）してアクティビティをSlackに通知する方法をまとめる。

# 前提

- 下記、またはそれに近い方法でSlackにGithubアプリケーションがインストールされていること。

https://qiita.com/miriwo/items/a783282e208e5b09e910

# 方法

- 通知チャンネルを作る
- 通知チャンネルで下記コマンドを実行し、Githubのアプリケーションをチャンネルに追加する。

    ```
    /invite @GitHub
    ```

- 追加が完了すると下記のように表示される。

    ![n_01_たかちゃん様_kintore_github_-_ドクサポ_-_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/2688b1ee-46de-9108-a940-75dc02836a01.png)


- 通知チャンネルで下記コマンドを実行してリポジトリを購読する。（「リポジトリオーナー名/リポジトリ名」は当該のリポジトリのホームにブラウザでアクセスしたときのURLのパスから抜き出すことができる。）

    ```
    /github subscribe リポジトリオーナー名/リポジトリ名
    ```

- 当該のリポジトリの可能な範囲の全てのアクティビティを通知したい場合、下記コマンドを実行して購読する。（このコマンドは何度も実行することが可能、設定は上書きされる）

    ```
    /github subscribe リポジトリオーナー名/リポジトリ名 issues,pulls,releases,deployments,reviews,comments,branches,commits:*,discussions
    ```

- 下記のように表示されるので「Connect GitHub account」をクリックする。

    ![n_01_たかちゃん様_kintore_github_-_ドクサポ_-_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/cedced0f-9424-520f-d9e5-10b4c6e5fc5c.png)

- ブラウザが開くはずなので「Connect GitHub account」をクリックする。

    ![Confirm_GitHub_Sign_in.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/7552a55b-99c8-d37c-4e69-f5fc3ecdb0d9.png)

- 認証コードが表示されるのでコピーする。

    ![Slack___GitHub.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/0bfde531-dd10-ca59-3341-156dfef839a2.png)

- Slackの方の「Enter code」をクリックする。

    ![n_01_たかちゃん様_kintore_github_-_ドクサポ_-_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/80780ada-44e9-9b7e-81b7-fc69a53f1c79.png)

- ウインドウが開くので、コピーしたコードをペーストし、「送信」をクリックする。

    ![n_01_たかちゃん様_kintore_github_-_ドクサポ_-_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/9e3d1cd4-92c0-c593-6369-d564079deb99.png)

- 無事に購読が完了すると下記のように表示される。

    ![n_01_たかちゃん様_kintore_github_-_ドクサポ_-_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/5323f889-1c7d-cb35-6cb8-8f8349920bb0.png)


# 参考文献

https://zenn.dev/kino_puehddby/articles/d6172cb5503166
SlackにGithubのアプリケーションを入れる方法

# 概要

- SlackにGithubのアプリケーションを入れる方法を簡単にまとめる。

# 方法

- Slackのサイドバーにて「アプリを追加する」をクリックする。

    ![90_notice_github_test_-_miriwo-notice_-_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/b8f8af0e-bdab-7542-b36d-57f8f23b832d.png)

- 検索で「Github」と検索する。ヒットした内容の「追加」をクリックする。

    ![App_-_miriwo-notice_-_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/62f30e12-1311-6661-f8c1-d6aa76599696.png)

- ブラウザが立ち上がるはずなので、開いたページの「Slackに追加」をクリックする。
- 問題なければ「許可する」をクリックする。※下記スクショはイメージです。Githubではないアプリケーションを追加したときのものになります。ただし、大幅に違いは無いはずです。

    ![Google_Drive_が_miriwo-notice_Slack_ワークスペースにアクセスする権限をリクエストしています___miriwo-notice_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/9d2f61e5-cf58-657b-545e-0aed61807edf.png)
【Python】select_related（とvaluesメソッド）を使用してクエリの数を最適化する

# 概要
`select_related`（と`values()`メソッド）を使用することで、クエリの数を減らせることがわかったので、備忘録も兼ねて記載します。

# サンプルコード解説
以下は、`select_related`と`values()`メソッドを使用して、Djangoモデル間の関連データを効率的に取得する方法のサンプルコード。

```models.py
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
```

```py
# select_relatedとvaluesを使用して、Bookモデルのタイトルと関連するAuthorモデルの名前を取得する例
books = Book.objects.select_related('author').values('title', 'author__name')

for book in books:
    title = book['title']
    author_name = book['author__name']
    print(f"Title: {title}, Author: {author_name}")
```

この例では、`Book`モデルのタイトルと関連する`Author`モデルの名前を取得しています。

### `select_related`
・`select_related`メソッド：関連するモデル（`Author`）のデータを事前に取得
・クエリの数を減らすことができます。以下も同じ意味ですが、この場合、それぞれのループで個別のクエリが発行されます。

```py
books = Book.objects.all()

for book in books:
    title = book.title
    author_name = book.author.name
    print(f"Title: {title}, Author: {author_name}")
```

### `values`
・`values`メソッド：指定したフィールドの値を辞書の形式で取得
・今回は、`'title'`と`'author__name'`という2つのフィールドを取得
・`'author__name'`は、関連する`Author`モデルの`name`フィールドにアクセスする方法。`values`メソッドを使用するとクエリセットのオブジェクトではなく辞書が返されるため、フィールド名には`__`を使用して関連フィールドにアクセスする必要があります。
・値にアクセスするとき、モデルのインスタンスから取得しているわけではないので`book.author.name`みたいにならないところもポイントですね。辞書のキー(`book['author__name']`)を使ってフィールドの値にアクセスします。

### `prefetch_related`
ちなみに、上記の`select_related`は外部キーや一対一の関係にあるモデルの間で使用されますが、多対多および一対多のオブジェクトを読み込む場合は`prefetch_related`を使います。
テキストコピー機能の配置

ブラウザ上のテキストを範囲選択してコピーするという手間を省く、テキストコピー機能を配置してみましたので紹介します。

まずは、Forgeで「copy clip」と検索し、下記のCopy String to Clipboardをインストールしてください。

https://www.outsystems.com/forge/component-overview/12110/copy-string-to-clipboard

Developmentのアイコンの中に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/a0550472-fc89-c46d-a341-6601ce6bed16.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/7fcf57bd-1ce5-1dcd-242d-82a42cd546a2.png)
このアイコンがあればインストール成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/12c99f7b-5bbf-1a50-2840-ca368b294e0a.png)
適当なアプリケーションを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/0e162bb1-4777-859a-1614-76eb024581ea.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/291cf30e-242e-6c3b-a70a-769bac74c2c4.png)
メニュー中のコンセントのアイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/82fcc946-b1d3-6be1-387d-9c47fd7283cf.png)
「clip」で検索し、CopyStringtoClipboard_Libを選択、チェックを入れ、Applyを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/b447f5bf-0deb-5321-710f-8b2f161d5909.png)
LogicタブのClient Actionsに追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/0e9f0ae0-5d3c-0388-9046-e60f72605f35.png)
EmptyでScreenを作成し、Inputを配置、New Local Variableしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/1d39ce1d-9cf6-fe56-83d9-343a0feacb2d.png)
Inputの右端を１カラム短くして、Iconを配置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/abd2eab5-4e0b-865c-6ddb-b2c15dd668c2.png)
copyで検索し、clipboradのアイコンにしておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/423dccd0-e067-00d2-03e2-cc33d89c03a3.png)
Iconを右クリックし、Link Toから(New Client Action)を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/d3c880ad-541f-c70c-c52c-6f0028bb925f.png)
LinkOnClickが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/10811732-bb6c-73a5-0ab8-ad008251c386.png)
LinkOnClickを開いて、LogicタブのClient ActionsからCopyStringToClipboardをドラッグ、
Input ParameterのTextはTextVarとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/d64991d3-719f-ab68-3019-2ae45f58ac9a.png)
Messageを配置し、”コピーしました”と表示するのもよいでしょう。

PublishしてOpen in browserします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/bb5c24cc-927f-9934-ae4d-1d96ffa8815e.png)
Inputに値を入力して、Iconをクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/00331f04-7004-649c-6bd3-b47a04d6d010.png)
メモ帳に張り付けると値が入っています。
Pythonの二次元配列初期化時にはまったり、リスト内包表記を覚える

## はじめに
二次元配列を初期化後、値を入れているはずの行に値が入っていることがあり、調べた末に納得できたので覚書

### 初めに書いたコード
```python
matrix = [[0] * 3] * 3
matrix[1][1] = False
print(matrix)
# [[0, False, 0], [0, False, 0], [0, False, 0]]
```
二行目の二番目変えたつもりなのに、一行目と三行目も変わっていて、しばらく悩む。そのうち、`[[0] * 3]`が同じオブジェクトのままで３掛けてmatrixに代入しているからと気付き、下に修正する。

### 修正したコード
```python
matrix = [[0] * 3 for i in range(3)]
matrix[1][1] = False
print(matrix)
# [[0, 0, 0], [0, False, 0], [0, 0, 0]]
```
リスト内包表記（List comprehensions）で書くと、新しいオブジェクトとして生成されるので想定の挙動にすることができた

## おわりに
共有渡しはこういうところでつまづく。引っかかるのはいいとして、すぐ気づけるようになろう

## 参考
https://aiacademy.jp/media/?p=1252
【SwiftUI】ウィンドウを複数開けなくしたらリジェクトされた👀

# はじめに
SwiftUIでmacアプリを作成すると、デフォルトではウィンドウを複数開けるようになっています。
ウィンドウを複数開けないようにするには、`@main`がついた`App`構造体に`.commands`をつけて、`CommandGroup(replacing: .newItem) {}`を追加します。

```swift
.commands {
    // ウィンドウグループにこれをつけるとウィンドウを複数開けなくなる
    CommandGroup(replacing: .newItem) {}
}
```

これでウィンドウを複数開けなくなります。
しかし、このままApp Storeの審査に出すとリジェクトされてしまいます。

# リジェクト内容
リジェクトされた内容は以下の通りです。

## 原文
:::note warn
Guideline 4.0 - Design


We noticed an issue with your app's user interface that contributes to a lower-quality user experience than App Store users expect.

Specifically, we found that when the user closes the main application window there is no menu item to re-open it.

Next Steps

It would be appropriate for the app to implement a Window menu that lists the main window so it can be reopened, or provide similar functionality in another menu item. 

Alternatively, if the application is a single-window app, it might be appropriate to save data and quit the app when the main window is closed.
:::

## 和訳（DeepL翻訳）
:::note warn
ガイドライン4.0 - デザイン


あなたのアプリのユーザーインターフェイスに、App Storeのユーザーが期待するよりも質の低いユーザーエクスペリエンスにつながる問題があることに気づきました。

具体的には、ユーザーがアプリケーションのメインウィンドウを閉じたときに、それを再び開くためのメニュー項目がないことがわかりました。

次のステップ

このアプリは、メイン・ウィンドウを一覧表示し、再度開くことができるウィンドウ・メニューを実装するか、別のメニュー項目で同様の機能を提供するのが適切でしょう。

あるいは、アプリケーションがシングルウィンドウアプリの場合、メインウィンドウが閉じられたときにデータを保存してアプリを終了するのが適切かもしれません。
:::

# 対応方法
リジェクトを回避するために、ウィンドウを閉じたときにアプリを終了するようにします。

```swift
@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onDisappear {
                    // ウィンドウが閉じられたらアプリを終了する
                    NSApplication.shared.terminate(self)
                }
        }
        .commands {
            CommandGroup(replacing: .newItem) {}
        }
    }
}
```

こうすることで、ウィンドウを閉じたときにアプリが終了できます。
これでリジェクトを回避できます。

# まとめ
macアプリのリジェクト事例と対応方法を紹介しました。この記事が参考になったという方は、いいねとフォローしていただけると嬉しいです😊
SSL証明書について

# はじめに
毎週1本様々な技術に関する記事を投稿しています。
もし興味のある方は下のリンクから他の記事も見ていただければ幸いです。
 [@7_inai_](https://qiita.com/7_inai_)

# SSL証明書とは
SSL証明書は、ウェブサイトとクライアント（ブラウザ）間のセキュアな通信を確立するために使用されるデジタル証明書です。証明書には公開鍵と認証局による署名が含まれており、`ウェブサイトの正当性とセキュリティを保証`します。

# SSL証明書の役割
SSL証明書には以下の2つの役割があります。
1. __通信データの暗号化__
クライアントとサーバー間の通信内容が第三者に盗聴、改ざんされるのを防ぎます。
2. __運営者の実在性確認__
通信先のサーバーが本物であることを証明できます。

# サーバー証明書とクライアント証明書
SSL証明書は、「サーバー証明書」と「クライアント証明書」の2種類があります。
1. サーバー証明書
ウェブサイトがクライアントに対して身元を証明するために使用されます。
2. クライアント証明書
クライアント自体が身元を証明するために使用されます。

# 終わりに
SSLサーバー証明書は、ウェブサイトのセキュリティを確保し、ユーザーの信頼を獲得するために重要な役割を果たしています。この記事では、SSLサーバー証明書の基本的な理解や役割について説明しました。セキュリティを向上させ、ユーザーの安心感を高めるために、適切なSSLサーバー証明書の取得と管理を行いましょう。


最後までお付き合いくださりありがとうございました。
WindowsでMAMPを使うとlaravelインストールでエラーが出ます

# 概要
laravelをインストールしてるんだけどできない！
ちょっと理由がありMAMPを使っていたら、問題発生！解決策を見つけるぞ！
と思って沢山対策を調べましたが全然なかったので、記事にしました。

# バージョン
- laravel 9.x
- composer 2.5.8
- php 8.1



# エラー内容
```
 laravel/framework[v9.36.4, ..., 9.x-dev] require league/flysystem ^3.8.0 -> satisfiable by league/flysystem[3.8.0, ..., 3.x-dev].
    - laravel/framework[v9.18.0, ..., v9.36.3] require league/flysystem ^3.0.16 -> satisfiable by league/flysystem[3.0.16, ..., 3.x-dev].
    - laravel/framework[v9.0.0-beta.2, ..., v9.17.0] require league/flysystem ^3.0 -> satisfiable by league/flysystem[3.0.0, ..., 3.x-dev].
    - league/flysystem[2.3.1, ..., 2.x-dev, 3.0.0, ..., 3.14.0] require league/mime-type-detection ^1.0.0 -> satisfiable by league/mime-type-detection[1.0.0, ..., 1.11.0].
    - league/flysystem[3.15.0, ..., 3.x-dev] require league/flysystem-local ^3.0.0 -> satisfiable by league/flysystem-local[3.15.0, 3.x-dev].
    - league/mime-type-detection[1.0.0, ..., 1.3.0] require php ^7.2 -> your php version (8.1.0) does not satisfy that requirement.
    - league/mime-type-detection[1.4.0, ..., 1.11.0] require ext-fileinfo * -> it is missing from your system. Install or enable PHP's fileinfo extension.
    - league/flysystem-local[3.15.0, ..., 3.x-dev] require ext-fileinfo * -> it is missing from your system. Install or enable PHP's fileinfo extension.
    - Root composer.json requires laravel/framework ^9.0 -> satisfiable by laravel/framework[v9.0.0-beta.1, ..., 9.x-dev].

To enable extensions, verify that they are enabled in your .ini files:
    - C:\MAMP\bin\php\php8.1.0\php.ini
You can also run `php --ini` in a terminal to see which files are used by PHP in CLI mode.
Alternatively, you can run Composer with `--ignore-platform-req=ext-fileinfo` to temporarily ignore these required extensions.
```

ざっと訳しますと、
インストールをするための必要なバージョンが足りません。とplatform-req=ext-fileinfo`を使えるようにして下さい。とあります。

# 1週間以上格闘
laravel再インストールをしたり、composerを入れ直したりと、試行錯誤を重ねましたが無理ですね。とplatform-req=ext-fileinfoを使えるようにしましたが、下記のエラーが出てきました、

# このエラーでxamppに変更

```
ドライバが見つかりませんでした（SQL: select * from information_schema.tables where table_schema = laravel_task and table_name = migrations and table_type = 'BASE TABLE')
```

ドライバーがインストールされていません。とエラーが出てようやくxamppに乗り換えました。おそらくですが、WindowsのMAMPには必要なドライバが足りていなかった可能性がありますね。

MacはMAMP、WindowsはXAMPPと言われている理由が納得できました。

# 結論
MacはMAMP、WindowsはXAMPPを使いましょう。
初記事なので読みにくかったらごめんなさい！

参考になれば幸いです！
【初心者向け】UnityでTimelineのAnimated Valuesの値が見れないときの対応方法

UnityでTimelineのAnimated Valuesの値が見れないときの対応方法です。

# ここの値が見たいのに見れない！
![2023-07-18_22h43_30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/06c2e2b3-0ec2-aa32-fbe3-8d6e921ee00f.png)

# 選択して、fキー押すとこうなります
全体がうまく縦幅に収まるように表示されます、めでたしめでたし。
![2023-07-18_22h43_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/10a24a3b-9292-5e86-f2c6-71160b110a60.png)

以上！
【Java,SpringBoot】顧客情報登録webアプリを作る

使用ツール
SpringBoot

codeダウンロード
https://drive.google.com/drive/folders/1h4nyNx4SeFfiDmiSB5xPv1Y1aTSYycML?usp=sharing

Page1
登録情報入力
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2220659/ce6c0291-ca65-ade2-f139-e2c3c35bcfa0.png)

Page2
登録情報の登録
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2220659/a033d3b9-cb5e-7887-c6e2-dd0deac72ac5.png)

Page3
データベースに出力
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2220659/559644cd-9a3c-a03b-87f1-283742eae070.png)

```
package com.example.demo;


import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class Register {

    @Autowired
    private UserRepository userRepository;

    @RequestMapping("/")
    public String start() {
        return "input.html";
    }

    @RequestMapping("/register")
    public ModelAndView register(@ModelAttribute RegisterBean rb, ModelAndView m) {
        User user = new User();
        user.setName(rb.getName());
        user.setAge(rb.getAge());
        userRepository.save(user); // データベースへの保存

        m.addObject("rb", rb);
        m.setViewName("register.html");
        return m;
    }
    
    @RequestMapping("/data")
    public ModelAndView showData(ModelAndView m) {
        List<User> users = userRepository.findAll();
        m.addObject("users", users);
        m.setViewName("data.html");
        return m;
    }
}

```
```
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>入力画面</title>
</head>
<body>
  <h1>登録情報を入力してください</h1>
  <form action="/register" method="post">
  名前：<input type="text" name="name" size="10" /><br/>
  年齢：<input type="radio" name="age" value="18歳未満"/>18歳未満　
        <input type="radio" name="age" value="18歳以上"/>18歳以上<br/><br/>
  <input type="submit" value="送信" />
  </form>
</body>
</html>

```