OmniAICreator/Qiita-1.07M huggingface dataset:
[MySQL] トランザクション vs ロック

SQLでは[ACID特性](https://ja.wikipedia.org/wiki/ACID_(%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E7%A7%91%E5%AD%A6))を担保するために、トランザクションとロックが用意されています。トランザクションとロックは区別されずに説明されることが多いですが、実際には違うものです。この区別がないことによって、トランザクションの動作に誤解が生じることがあります。

## よくある説明

銀行の預金管理システムを考えましょう。

ある口座をAさんとBさんの二人が共有している状況では、次にような状況が起こりえます。

```
12:00 Aさん : 口座を開設します。
12:01 Aさん : 通販の支払いのために1万円預け入れます。
12:03 Bさん : 昼ご飯代で5千円引き出します。
12:05 Aさん : 通販の支払いのために1万円振り込みます。
```

果たして、Aさんの振込は成功するでしょうか。Aさんの立場では、せっかく通販の支払いのために1万円預けたので、途中でBさんに引き出される事態は防ぎたいはずです。

このようなときに、トランザクションを使います。具体的には、Aさんの取引が終わるまでBさんの取引を待ってもらう(ロックする)ようにします。

```
12:00 Aさん : 口座を開設します。
12:01 Aさん : 通販の支払いのために1万円預け入れます。
12:03 Bさん : [locked] 昼ご飯代で5千円引き出します。
12:05 Aさん : 通販の支払いのために1万円振り込みます。
12:05 Bさん : [実行] 昼ご飯代で5千円引き出します。(fail)
```

## よくある誤解

誤解の内容を説明する前に、次の口座取引がどのような順番で行われるべきか考えてみてください。

```
17:00 Aさん : 夕飯代を引き出したいので残高を確認します。(5千円)
17:03 Bさん : 飲み代で5千円引き出します。
17:05 Aさん : 夕飯代で3千円引き出します。
```

もし、トランザクションとロックが渾然一体なら、

```
17:00 Aさん : 夕飯代を引き出したいので残高を確認します。(5千円)
17:03 Bさん : [locked] 飲み代で5千円引き出します。
17:05 Aさん : 夕飯代で3千円引き出します。
17:05 Bさん : [実行] 飲み代で5千円引き出します。(fail)
```

となるはずです。しかし、MySQLの実装では、Bさんの引き出しが先に行われて、Aさんの引き出しが失敗します。

## トランザクション分離レベル

二つのトランザクションが競合したときに、どのような動作になるかは、トランザクション分離レベルによって決定されます。分離レベルは、分離の度合いが小さい順に、

- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE

の四種類がANSI/ISO SQL標準で定められています。

MySQLではデフォルトでは`REPEATABLE READ`レベルでトランザクションが分離されています。具体的な動作としては、クエリがテーブルを参照すると、初めて参照した時のテーブル状態がスナップショットとして記録されて、以降のクエリ実行ではスナップショットがデータソースとして使われるようになります。

そのため、たとえばBさんが飲み代を引き出した後に、再度Aさんが残高を確認すると、Bさんの引き出しは反映されません。

```
17:00 Aさん : 夕飯代を引き出したいので残高を確認します。(5千円)
17:03 Bさん : 飲み代で5千円引き出します。
17:05 Aさん : 夕飯代を引き出したいので再度残高を確認します。(5千円)
```

## ロック

これでは困ることも多いので、ここでロックが登場します。

ロックには、

- 共有ロック
- 占有(排他)ロック

の二種類があります。ロックによって、他のトランザクションのロック取得が制限(ブロック)されます。

||共有ロック|占有ロック|
|:-:|:-:|:-:|
|共有ロック|o|x|
|占有ロック|x|x|

先ほどの例でBさんの飲み代の引き出しをロックしたい場合は、Aさんが初めに残高を確認した段階で共有ロックを取得しておく必要があります。

```sql
SELECT account.amount FROM account WHERE account.id = "xxx" LOCK IN SHARE MODE;
```

共有ロックを取得するには、SQLクエリの末尾に`LOCK IN SHARE MODE`を追加します。すると、口座テーブルがAさんのトランザクション用にロックされて、Bさんは口座テーブルの内容を変更できなくなります。

```
17:00 Aさん : 夕飯代を引き出したいので残高を確認します。(5千円)
17:03 Bさん : [locked] 飲み代で5千円引き出します。
17:05 Aさん : 夕飯代で3千円引き出します。
17:05 Bさん : [実行] 飲み代で5千円引き出します。(fail)
```

ちなみに、占有ロックを取得するには、SQLクエリの末尾に`FOR UPDATE`を追加します。また、SELECTでは明示しない限りロックは取得されませんが、UPDATEやINSERTでは自動的にロックが取得されます。

そのため、例えば`LOCK IN SHARE MODE`を指定したSELECTとUPDATEを別トランザクションで並列実行するとロック取得が制限されます。

## ネクストキーロック

先ほどは、あたかも口座テーブルの全行がロックの対象になるかのような書き方をしましたが、実際にはケースバイケースでテーブルの一部の行のみロックの対象になる場合があります。

ロック対象はWHERE句の指定内容をもとに決められます。WHERE句の指定でインデックスされていないカラムが使われている場合は全行がロック対象になります。一方でインデックスされているカラムが使われている場合は、ネクストキーロックという仕組みによって一部の行のみがロック対象になります。

例えば、次の口座テーブルとSQLクエリの組み合わせで、どの行がロックされるのか考えます。

|id (indexed)|amount|
|:-:|:-:|
|1|1万円|
|5|3万円|
|7|2万円|
|...|...|

```sql
SELECT * FROM account WHERE account.id = 3 FOR UPDATE;
```

すると、口座情報が存在しないインデックスの隙間（ギャップ）と隙間の次の口座情報(id = 5)がロックされます。id = 3の口座情報を他のトランザクションから保護することで、競合を防いでいます。

本来であれば、id = 3の場合のみロックすれば事済みますが、実際にはid = 1, 2, 3, 4, 5の行がロックされます。これは、おそらくロック機構を実装するときに、実レコードのインデックスを基準にしてロックをかけた方が都合が良いからだとされています(噂)。
Elseを使わないコード作成

# はじめに
今まで私は主にelseを使用してコードを書いてきましたが、より簡潔にコードを作成するための方法を探したところとある記事を発見し、役に立ったので紹介したいと思います。

# elseを使わない作成例
例えば以下のコードを見ると、何を意味しているのかすぐに分かります。

```typescript
if (x !== 0) {
    return 10 / x;
} else {
    return 0;
}
```

下のコードではどうでしょうか。
```typescript
else {
	return 0;
}
```

なぜ0をリターンするのか、一般的な返却形態なのか、 問題があるから返すのか、

すぐに理解しづらいです。

このような時は、さまざまな状況である変数の値を検証する必要がある場合が多いです。 

```typescript
const doSomething = (err, something) => {
	if (err) {
    	console.log(err);	
    } else {
    	if(something.OK) {
        	//Do Something
        } else {
        	console.log('Not Invalid');
        }
    }
}
```

`if`と`else`が入り混じっています。以下のように変更してみましょう。

```typescript
const doSomething = (err, something) => {
	if (err) {
    	return console.log(err);	
    } 
  
	if (!something.OK) {
		return console.log('Not Invalid');
	}
  
	//Do Something
}
```

このように重要なロジックが動作する前に検査を行い、
それに応じてリターンすることで、コードをより明確に記述できます。

###  非同期の処理の場合

非同期処理の場合、次のように書くことができます。

```typescript
const doSomething = async (err) => {
	if (err) {
    	throw err;	
    }

 	//Do something
}
```

`throw`を適切に活用して検証を迅速に行い、関数を中断させることができます。


###  Expressの場合

多くの人々が次のような問題を見落としています。
```typescript
app.get('/', (req, res, next) => {
	res.send({});
  
  	console.log('hi'); // hi
});
```

`res.send` メソッドは `return` や `throw` のようにコードを中止させません。

つまり、`console.log` 関数はそのまま実行されます。

以下のコードはexpressで推奨されるエラー処理`handler`です。

```typescript
app.use((err, req, res, next) => {
	// Error handler	
  	// エラー処理ロジック...
});
```

この`handler`は、`next`メソッドのパラメータが空でない場合に機能します。

つまり、以下のように`handler`内で`next`メソッドのエラーを取り込み、

`err`パラメータを介してエラーを受け取り処理できます。

```typescript
app.get('/', (req, res, next) => {
	next(new Error('Error'));
});
```


しかし、上記で言及した方法では、

`next`関数は`return`や`throw`と同様に関数を即座に中断させないため、

次のように使用する必要があります。

```typescript
app.get('/', (req, res, next) => {
	return next(new Error('Error'));
});
```

###  Expressの使用例

APIの利用者がデータを検証し、

エラーが発生した場合は即座にエラー処理`handler`に投げます。

```typescript
app.post('/auth', (req, res, next) => {
	// from FE
	const inputId = req.body.id;
  
  	if (!inputId) {
		return next({ status: 400, message: 'Bad Request' });
    }
  
  	// Do Something
});
```
このようにしてコードが簡潔になりました。


# まとめ

Else文を使うと、エラーハンドリングとハッピーパスのために同じインデントレベルを強制するので、
どんなコードでも可読性が損なわれます。またコードに影響を与えるロジックから分離してしまいます。

しかし早期リターンとロジックをヘルパー関数に分割するという2つのテクニックを使うことで解決できるので、Else文を使わない方が良いといえます。


# 参考

https://dev.to/dglsparsons/write-better-code-and-be-a-better-programmer-by-never-using-else-statements-4dbl
PostgreSQL Conference Japan 2023の小反省会とZennにbookを追加した話

# 初めてのQiitaのポストです

みなさんはじめまして。

かつてはQiitaに大変お世話になってましたが、全部 Zenn に移動させていっかいアカウントを消したので、新アカウントとしては初めてのポストです。

今回は、Zennの方でgithub連携をしていて、非公開前に実質公開されているので、こちらを借りようと思いました。必要に応じて使いたいと思います。

よろしくお願いします。

# PGcon Japan ではすみませんでした

日本PostgreSQLユーザ会主催の「PostgreSQL Conference Japan 2023 」( https://www.postgresql.jp/jpug-pgcon2023 ) というものがあって、これの T4 「PostGIS入門の入門」というタイトルでしゃべらせてもらいました。

しかし、同じ時間帯では A4 で「pgvectorを使ってChatGPTとPostgreSQLを連携してみよう！」－これは絶対観客持っていかれるわと感じてました。そもそも私自身が T4 の発表をほっぽり出して聞きたいと思いました。

15人ほどの方々の前でとりあえずしゃべったけれども、GISは恐くないよと言うのが目的でしたが、失敗。
とてもうなずいてる人たちがいらっしゃいましたが、MapLibreの人とかなんとかということで、「こっち側の人」やないの…。あと、別の方から「難しいのは分かった」というお声を頂きました。失敗やないか。

すみませんでした。

もうちょっと考えていきたいと思います。

# ひさびさにzennのbookを作りたくなった

さて本題。

PGCon用の資料を作っていたら、ひさびさに分析っぽいことをやったので、zenn で book にしようかと思って書いてみました。

https://zenn.dev/boiledorange73/books/pgis-cookbook

市街化区域内の農地の面積の総計を求めるというものです。本職で気づいたのでなく宅建のテキストで農地法を知ったとかなんとか。

他にもきっとネタができると思うので、何かイヤなことが合ったら拡充していきたいと思います。
連珠プログラムを作っています。

![スクリーンショット 2023-12-05 135002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519376/ac482979-c013-9cec-3e15-1125f7157afe.png)
他の方が作ったソフトと対戦させてみても、勝ちます。
Instana エージェントについて

こんにちは。今日はAIOps分野で圧倒的に注目を集めているAPMツール「Instana」のエージェントについて書こうと思います。

エージェントは、簡単に言えば、監視したいデータを収集するために必要な仕事をしてくれるものです。英語でAgentと言えば、代理人、仲介者といった訳になりますが、エージェントとは必要だけれど面倒なことを代わりにやってくれるような存在だとイメージすれば分かりやすいかもしれません。

さて、Instanaのエージェントはどんな働きをしてくれるのでしょうか。Instanaのエージェントを導入すると、エージェントが現在稼働しているテクノロジを自動的に見つけ出してくれます。さらに、見つけ出したテクノロジに対応するセンサーをほとんどの場合自動でロードして構成し、モニタリングを開始できる状態を作ります。このように、自動的に必要なものを見つけ出し、自動で必要な作業をしてくれるInstanaのエージェントは、Instanaがキー・コンセプトとして掲げている「自動化」という点で大きく寄与しています。
　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621347/7c7c6576-c844-cd4b-e3d7-5be80f92e060.png)
↑エージェントの一覧画面。バージョンや更新モード等を把握できる



以下、Instanaのエージェントの代表的なメリットについてまとめてみたいと思います。

■Instanaのエージェントの長所は何か？

（１）300を超えるテクノロジーに対し、継続的かつリアルタイムに対応
Instanaエージェントが対応しているテクノロジーには、Linux、Kubernetes等の基盤からJava、Node.js等ミドルウェアを含め様々なものがあります。 また、Instanaエージェントはつねにテクノロジーの状況変化も確認しているため、Kubernetes環境のようにアプリケーションが変化していくような環境であっても、手動の変更作業なしで自動的に変化に追随していくことが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621347/4ee15962-86ee-22b4-5379-09b73a3ddbbd.png)
↑レポートしているエージェントの状況も視覚的に確認できる
　
（２）分散トレースを100%収集する自動構成を備えた単一エージェント
Instanaのエージェントは、1秒単位のデータ粒度で、サンプリングなしの100%のトレースを行います。他のAPM製品のデータ粒度は1～10分間単位ですが、これでは問題となる数値のスパイクを見逃したり、迅速な問題対応が（Instanaと比較して）難しいため、動的な環境の把握のためには理想的なデータ粒度ではないと思われます。
　
（３）オーバーヘッド（処理的負荷）を抑えらえる
レガシーなAPMツールではコンテナ等の各テクノロジに対してそれぞれ別個のエージェントをインストールしなければならず、システムのオーバーヘッドが大きいのが課題でした。しかし、Instanaの場合、基本的に、1つのノードに対して1つのエージェントをインストールするだけでＯＫです。後はエージェントが各テクノロジ必要なセンサーを自動的にロードしてくれます。結果的に、Instanaの場合、「単一エージェント」＋「各テクノロジに対応した小さなセンサー」だけで良いので、レガシーなAPMツールと比較してオーバーヘッドを大幅に削減可能です。
　
以上３つのメリットがあり、非常に先進的なエージェントであることが分かります。
Instanaにはこのような便利なエージェントがあり、手動で複雑な導入作業をする必要がなく、簡単に使用を開始できるAPMツールですのでお勧めです。
技術書典15で「Go言語で構築するクリーンアーキテクチャ設計」を頒布した話

# はじめに
技術書典15にサークル名「コードカキタイ」で初参加し「Go言語で構築するクリーンアーキテクチャ設計」を頒布しました。

https://techbookfest.org/product/9a3U54LBdKDE30ewPS6Ugn?productVariantID=itEzQN5gKZX8gXMmLTEXAB

本記事では初めて出展するまでの話を書きます。

# 参加までの背景
社内の定期輪読会にて技術書を読み、意見交換をしていく中で、技術書を書く側も面白そうと感じていました。また技術書典に参加経験がなく、いつか経験してみたいと考えていました。

そんな時エンジニア仲間が技術書典参加メンバーを募集しており、参加を決意しました。結果として、別々の企業に所属する4人のGoエンジニアが集まり、約半年にわたるプロジェクトが始まりました。

# 頒布までに大事にした点
企画~出展までのストーリーは共著者の@hiroaki-u さんの記事にまとまっているため、自分は書籍を執筆する中で大事にした点を書きます。

https://qiita.com/hiroaki-u/items/b85c369ee2b6fe1a710c

## 何を達成したいか
過去、Goの実装パターンやアーキテクチャに関して悩み、苦労した経験がありました。なので過去の自分のように **「クリーンアーキテクチャの概念は何となく理解したが、実践が難しく困っている」** という悩みを持つ人に対して、1つの実装例を届けたいと思いで取り組みました。

そのため書籍では「クリーンアーキテクチャの説明」と「Go言語での実装」の2部構成に分け、GitHub上にサンプルコードを用意し、一連の処理を追いながら理解できるようにしています。

## どのように伝えるか
どのように伝えるかは1番難しく、大変でした。わかりやすく、論理的に、正しく伝えることの難しさを痛感しました。複数名で進める中で振り返ってみて良かった点をご紹介します。

### 共通認識をつくる
議論をするにあたり、前提が揃っていないと意見のすれ違いの原因となります。今回は執筆前にペルソナを用意し、想定読者を用意しました。

![スクリーンショット 2023-11-22 17.04.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184054/5e15dff4-c53d-ef2f-6e98-b2601fcf2182.png)
（ペルソナの一部を抜粋）

結果、記事を執筆・校閲する中でペルソナに合わせて内容の加筆・削除を進めることができました。

### 関係性をつくる
全員別会社なため一緒に何を行うことが初めてでした。そのためご飯やサウナなどを通じて交流を行いました。また、システムコーチングをメンバー全員で受けさせていただく機会があり、相互理解を深めることができました。

（もちろんサウナは黙浴です）

### コードを書き、議論する
クリーンアーキテクチャの概念や実装に関して気になる点があれば、メンバー同士で話し合いました。それぞれの持つ知識や経験が異なるので、より内容をブラッシュアップすることができました。

# 成果物
このように試行錯誤して、書籍を進めました。平日の夜や土日にコツコツ進めていたのですが、締め切り直前にはお昼から終電まで作業する日もあり、とても大変でした。笑

そのような苦労もあり、思い入れのある成果物を作成することができました。

https://twitter.com/sugamaan/status/1721691838778864057

目次は以下の通りで、二部構成にしました。

![目次1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184054/3ed0e8fd-f5a6-f6e9-43e8-3d49edb911c0.png)

![目次2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184054/836ddb78-ed1c-abfd-45d8-0597be546de0.png)

第一部ではクリーンアーキテクチャの基礎から理解を深めます。アーキテクチャの発展からその目的を明確にした上で、クリーンアーキテクチャとは何かを解説しました。

第二部ではサンプルアプリケーションを用いて、クリーンアーキテクチャをGo言語で実践していきます。各レイヤーの実装方法とその要点を詳しく掘り下げました。

# 結果
ありがたいことに600部以上販売することができました！

https://twitter.com/sugamaan/status/1729299015429451911

当日も様々な方と交流できて楽しかったです。

![IMG_3763.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184054/9a736a0d-e740-62b7-ecb8-452f83c0c01c.jpeg)

# 初参加で得たもの
想像の何倍も大変でしたが、素敵なメンバーのおかげでとても良い経験となりました。本活動を通じて自分の知見が深まったことも嬉しかったです。最後に技術書典という貴重な機会を用意くださった運営、スポンサー、参加者の方、購入くださった方、ありがとうございました！

個人としては、引き続きWebアプリケーションの知見を増やしていき、日々の業務へと活かしていきたいと思います！
Whitetooth No Energy 歯磨きを大切に

**こんなスイッチをつくりました。**

<img height="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986141/f31c7d82-096f-760b-2f7e-9acd79ffbf28.png">

**webページは[こちら](https://deft-elf-c83841.netlify.app/)です。**

## Bluetoothに接続するか、歯磨きしてWhitetoothにするか
自室で使っているワイヤレスヘッドフォンがあるのですが、家の照明のように、物理スイッチでスマートフォンと接続できたら、そっちの方が楽かも！と思いました。
今回はそんな物理スイッチを試しにつくってみようと、まずはコンセプトをWeb版でつくってみました。

あれ、物理スイッチは...？

さておき、Bluetoothな口元じゃイケてないので、接続を切った後は歯磨きを命令してくれます。
**夜歯磨きするタイミングでBluetoothデバイスを充電することで、充電し忘れがなくなる！** という作戦です。

## 動かしてみる
webアプリの挙動はこんな感じです。

1. **待機状態**
1. **BlueToothスイッチを押す → Bluetoothデバイスを探しリストを表示**
1. **WhiteToothスイッチを押す → 歯磨きしなさいのアラートが飛んでくる + Bluetoothデバイスとの接続を切る**
1. **1に戻る**

### BlueTooth On!
BlueToothスイッチを押すと、Bluetooth接続候補のデバイスが一気に表示されます。
<img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986141/2df521a5-85ad-e04a-7ed0-0775db1f2a84.png">

Web Bluetooth APIを利用していて、`bluetooth.requestDevice()`メソッドで候補を見つけています。
デバイスをつなぐとデバイス名をスイッチの下に表示します。

<img width="40%" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986141/81707fe2-837e-69bb-8427-fbab7b8d432e.png">

### WhiteTooth On!
WhiteToothスイッチを押すと接続が切れ、「Brush Your Teeth」の文字をアラートで表示します。
<img width="80%" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986141/0db1b606-4446-ecad-1cb3-1b33aa218a2e.png">

## 開発環境
- CodePen
- GitHub
- Netlify
- Google Chrome(119.0.6045.200)

また、Web Bluetooth APIのAPI仕様は[こちら](https://developer.mozilla.org/ja/docs/Web/API/Web_Bluetooth_API)を参考にしました。

実は、**スイッチ部分以外はChatGPTにつくってもらった背景画像**です。あくまで物理スイッチをつくりたいのでwebページの構造体はサクッと作りました。スイッチの動きはCSSで制御しています。
```
# 歯の形状をしたonとoffのスイッチの画像を16:9でつくって
```

Codepenはこちらです。(0.25×が見やすいです)

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="xxMmVgJ" data-user="yutowac" 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/yutowac/pen/xxMmVgJ">
  Untitled</a> by yuto (<a href="https://codepen.io/yutowac">@yutowac</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## 補足：スマートフォンの動作確認
androidのスマートフォン(Android11)でもChromeで動作しました。
ただし、スマートフォンでは、Bluetoothデバイスの候補が画面を半分くらい埋め尽くしてしまってやや扱いにくいです。モバイルのレイアウトにもう少しこだわっても良かったです。
<img width="40%" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986141/802b2687-5346-f148-9dc5-d6d0858502a3.png">

またせっかくのwebアプリなので、iOSユーザーの方 (30代・女性) にも感想を聞いてみました！
Safariではうまく動作しなかったので、私のスマホを使ってもらいました。
スイッチについては、、、

**「音楽聞きながら歯磨きしたい」** 

ということでした...。歯磨きが終わったら押すスイッチでも良かったかもしれないです。
wslでnerves その39

# 概要
wsl(wsl2じゃない)でnervesやってみる。
qemu(x86_64エミュレータ、ラズパイじゃない)でやってみた。
生成したnerves_livebook.imgを、QEMUで起動してテストしてみた。
GPIOが無いので、マウスを認識できる様にする。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/c3b7c006-4633-080f-4fc9-312a68a23f0c.png)

# 起動ログ

```
$ Toolshed.cmd("dmesg | grep usb")

usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
pci 0000:00:01.2: quirk_usb_early_handoff+0x0/0x690 took 422502 usecs
usbcore: registered new interface driver usb-storage
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver

```

# 魔法をかけた、起動スクリプト。

```

"C:\Program Files\qemu\qemu-system-x86_64.exe" -drive file="nerves_livebook.img",if=virtio,format=raw -m 1024 -net nic,model=virtio -net user,hostfwd=tcp::10022-:22,hostfwd=tcp::80-:80 -serial stdio -usb -device usb-ehci,id=ehci -device usb-mouse

```

# 起動ログ
マウスを認識した。

```
$ Toolshed.cmd("dmesg | grep usb")

usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
pci 0000:00:01.2: quirk_usb_early_handoff+0x0/0x690 took 416039 usecs
pci 0000:00:04.0: quirk_usb_early_handoff+0x0/0x690 took 411748 usecs
usbcore: registered new interface driver usb-storage
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
usb 1-1: new high-speed USB device number 2 using ehci-pci
input: QEMU QEMU USB Mouse as /devices/pci0000:00/0000:00:04.0/usb1/1-1/1-1:1.0/0003:0627:0001.0001/input/input4
hid-generic 0003:0627:0001.0001: input,hidraw0: USB HID v0.01 Mouse [QEMU QEMU USB Mouse] on usb-0000:00:04.0-1/input0

```

# 検出したデバイスの使用法を取得する。

```
$ Toolshed.cmd("cat /proc/bus/input/devices")

I: Bus=0019 Vendor=0000 Product=0001 Version=0000
N: Name="Power Button"
P: Phys=LNXPWRBN/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXPWRBN:00/input/input0
U: Uniq=
H: Handlers=kbd event0
B: PROP=0
B: EV=3
B: KEY=10000000000000 0

I: Bus=0011 Vendor=0001 Product=0001 Version=ab41
N: Name="AT Translated Set 2 keyboard"
P: Phys=isa0060/serio0/input0
S: Sysfs=/devices/platform/i8042/serio0/input/input1
U: Uniq=
H: Handlers=kbd event1
B: PROP=0
B: EV=120013
B: KEY=402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=7

I: Bus=0003 Vendor=0627 Product=0001 Version=0001
N: Name="QEMU QEMU USB Mouse"
P: Phys=usb-0000:00:04.0-1/input0
S: Sysfs=/devices/pci0000:00/0000:00:04.0/usb1/1-1/1-1:1.0/0003:0627:0001.0001/input/input4
U: Uniq=89126-0000:00:04.0-1
H: Handlers=event2
B: PROP=0
B: EV=17
B: KEY=1f0000 0 0 0 0
B: REL=903
B: MSC=10

I: Bus=0011 Vendor=0002 Product=0006 Version=0000
N: Name="ImExPS/2 Generic Explorer Mouse"
P: Phys=isa0060/serio1/input0
S: Sysfs=/devices/platform/i8042/serio1/input/input3
U: Uniq=
H: Handlers=event3
B: PROP=1
B: EV=7
B: KEY=1f0000 0 0 0 0
B: REL=143

```

以上。
setOnInputMethodTextChanged() メソッド内の処理が走らない。

あるフィールドに対して、入力内容の制御を行おうとしていた。
制御内容を記述したメソッドを作成し、`setOnInputMethodTextChanged()`を使ってメソッドが実行されるようにしたかったが上手く動かない。
全く同じコードを他の人に試してもらうと正常に動作した。どうしてか。

調べた内容だと、このようなことが原因に当たることがらしい。

* テキスト入力メソッドがプラットフォームで使用可能であるか
    参考元:https://stackoverflow.com/questions/12956061/javafx-oninputmethodtextchanged-not-called-after-focus-is-lost

```
Platform.isSupported(ConditionalFeature.INPUT_METHOD) //true ならOK
```

+ IMEがオンではない場合は、メソッドが動かない
 参考元:https://teratail.com/questions/23236

今のところ原因はわかっていないが、個人で使う範囲でない場合はsetOnInputMethodTextChanged() を使用した開発はやめておいたほうがよさそう。

他に入力イベントを拾うメソッドとして、
```
onKeyPressed //キーが押されるタイミング
onKeyReleased //キーが放されるタイミング
onKeyTyped //キーがタイプされるタイミング
```
こんなものもあった。
Eventクラスから、EventTypeを判定して処理を行うものも。
参考元:https://docs.oracle.com/javase/jp/8/javafx/api/javafx/event/Event.html

他何か情報があれば、随時追記していく。
Pythonで「while文を使った繰り返し」の動作を確認してみた

# 概要

Pythonで「while文を使った繰り返し」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/python/for/index1.html

# 実装

以下のファイルを作成しました。
```sample.py
#num = 0
#while num < 2:
#    print("num = " + str(num))
#
#print("End")

num = 0
while num < 2:
    print("num = " + str(num))
    num += 1

print("End")

num = 1
print("Start")
while num < 6:
    print("num = " + str(num))
    num += 1

print("End")

num = 1
total = 0
print("Start")
while num < 6:
    print("num = " + str(num))
    total += num
    num += 1
else:
    print("Total = " + str(total))

print("End")
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
num = 0
num = 1
End
Start
num = 1
num = 2
num = 3
num = 4
num = 5
End
Start
num = 1
num = 2
num = 3
num = 4
num = 5
Total = 15
End
```

# まとめ

何かの役に立てばと。
え!! 未経験で一人情シスを!? (2)

### 前回のあらすじ
新卒大手フリーランスでPM業務というめちゃくちゃなキャリアスタートから気づいたらベンチャーの一人情シスに!?しかもいきなり150時間分の作業の自動化なんて出来るの???

### 第四話　月150時間の行程を自動化？！
上からバックコストの削減について相談されたある日、「自動入力RPA作ってよ笑」との~~無茶ぶり~~打診を受けるも内心冷や汗タラタラ。「いや俺のかけるPythonなんて素人に産毛か生えた程度だし...」ってもう戦々恐々生まれたての小鹿くらい震えてChatGPT握りしめて書いてみたらまさかの、、、

##### 出来た。出来たけどお盆はなくなった。差し入れのアイスは美味しかった。

～作業する前に知っておきたかったこと（初めてのコーディング with ChatGPT編)～
・ChatGPTよりもGithubのコメント欄の方が信用できる
・エラーメッセージを用いてネット検索の上でコード修正するようプロンプトエンジニアリング
・結構GPT上でのライブラリだったり変数エラーするので雛形はあらかじめ作っておく

～作業する前に知っておきたかったこと（Selenium編)～
・構築されたのが昔(今回のケースだと最終メンテ2007年のWebフォーム)だとFull Xpath推奨
・実行ファイルとdriver.exeは同じレポジトリにあると楽
・ブラウザ表示モードにしておくと処理してるのが分かってモチベが上がる
###### 参考にさせていただいた記事→https://qiita.com/mochio/items/dc9935ee607895420186
先人の知識の大切さと「もしかしてコーディングちょっとだけ分かればChatGPTで開発できる？」と可能性を感じた夏のとある日でした。

### 第五話　要件定義ってめちゃくちゃ大事だよねって話
例の自動入力RPAで150時間分の人力業務を自動化したら、今までバックコストの高さからシステムよりも人力ムードだった社内にも「アレって出来る？」「こういうの出来たらめっちゃいいよね！」みたいな理解したいんだけどね～みたいなムードが出てきた。正直凄く嬉しかったし、自分が貢献できている気がして誇らしかった。

でも、それに乗っかって自分のふわっとした無茶ぶりを具現化してくれみたいなお願いも増えてきた。すり合わせの打合せをしたり作っては手戻しが発生する未来が見えたので前職の見よう見まねで要件定義書、英語で言うとRequest for Proposal, RFPなんて呼ばれたりするやつを雑に作った。

##### ドキュメントベースじゃないと要望聞けないし責任取れません！！
この世の全ての理不尽に苦しむ中小企業の一人情シスの皆さん、要件定義書を作ってドキュメントにしてもらいましょう。。。僕は場合はいわゆる、As-is, To-be, ユースケース、納期の4つに絞って記載してもらいましたが大分作業自体に集中できるようになり、依頼側も自分のもやっとしたものをエイヤでも言語化することで整理できたケースが多くてラッキーでした。
(開発V字モデルの存在は後に知りました)
開発V字モデルの分かりやすい先人の記事はこちら→https://qiita.com/mars0925y/items/9d03b89b2ce6af53ade1

### 第六話　クラウドって結局どれが正解なの？？弊社編
弊社の機関DBシステム、実は創業時５年間、メジャーアップデートなしで運用されています。確かにノーコードで改修や機能つけられるし、お手軽で現場スタッフでも作業できます。しかし、そもそものDB設計が現在の事業スケーリングに合わない、取り急ぎミラーリングでもいいからクラウドにお引越しだ！と一人情シス的には地獄のような大号令が聞こえてきたわけです。そこからは毎日狂ったようにUdemyで動画を見ながらQiitaで記事を読み漁り、無料クレジットで使える分は全部使う！！くらいの気概で調査に明け暮れていました。

弊社のように営業がずっと使ってるから高可用性は絶対譲れない、でもCognitive SearchもいいしDuet AIも良さそう。そもそもGoogle Spreadsheet使うケース多いしGASもやりたいなーなど迷った結果、、、

##### 決まりませんでした。全部のいいところをちょこちょこ使う事になりました。

サーバーはAZだったりBCPが強いAWSに、AIがらみの部分は元々Open AIの課金ユーザーだったのでAzureに、GASだけはGCPしかないのでお願いしたりと。今はまだなんちゃって導入なので良いのですが、ここからのスケーリングや冗長性、取り回しやすさなどなど考えるといつか一つに絞る必要があるのかなとは思いますが怖いです。引き続き勉強します。
Notionでスペルチェックを無効にする方法

Notionデスクトップアプリ(Windows版)でスペルチェックを無効にする方法
---

左上のサイドバーの**設定→言語と地域→スペルチェッカーの言語→選択されている言語を外す**(選択必須のドロップダウンリストに見えて実はチェックボックス！)

ちなみに赤い波線を右クリックして「スペルチェックを無効にする」をクリックしても無効にできますが、設定→言語と地域を開いただけでスペルチェックが勝手に復活するので、スペルチェックが一生いらない人は上記の方法がオススメです。

以下蛇足
---
[例のEvernoteノート数50制限](https://www.itmedia.co.jp/news/articles/2311/30/news155.html "Evernote、無料プランを大幅制限　ノートの上限数が10万→50に")にさっそく引っかかったので前から気になっていたNotionに乗り換えたのですが、スペルチェックを無効にする方法をググっても、ChatGPTに聞いても、perplexityに聞いても答えを得られなかったので自己解決した方法を記事にしてみました。乗り換え初日の知識が薄い状態でこの手の記事を書きたくはなかったのですが、今私と同様の状況でNotionへの乗り換えが急増していそうな気がしたので取り急ぎそれだけ書きました。
Snapshot Isolation と Serializable の違い


## トランザクション分離レベル

まず、四つのトランザクション分離レベルから整理していきます。
これは、この記事に辿り着いた方は、すでに知っている方も多いと思うので、読みとばしていただいて大丈夫です。

今回は、トランザクションT1の直後にトランザクションT2が起ったとします。
この時に、トランザクションT1はデータ集合V1に対して処理(読み取り or 変更)をし、トランザクションT2は重複した部分集合を持つデータ集合V2に対して処理(読み取り or 変更)を及ぼすとします。


- Read Uncommitted
  - 一番緩やかな分離レベルです。トランザクション中の変更はコミットする前に他のトランザクションから参照できます。 dirty readという問題が発生する可能性があります。
  - dirty read とは、T1でコミットしていない変更をT2で読み取ってしまう問題です。
- Read Committed
    - トランザクション中の変更はコミットするまで他のトランザクションから参照できません。しかし、同じデータに対して複数のトランザクションが並行して実行されると、non-repeatable readという問題が発生する可能性があります。
    - non-repeatable readとは、T1の一つのトランザクション内で複数回データ集合V1を読み取る時に、トランザクションT2のコミットによってV2内のレコードの**更新**が先に完了すると、T1の同一トランザクション内でV1が更新されてしまうという問題です。
    - つまり、トランザクション内でのレコードの一貫性に問題が生じることがありますよ。というものです。
- Repeatable Read
    - トランザクション開始時に読み取ったデータは、そのトランザクション内で一貫性が保証されます。しかし、phantom readという問題が発生する可能性があります。
    - phantom readとは、T1の一つのトランザクション内で複数回データ集合V1を読み取る時に、トランザクションT2のコミットによってV2内のレコードの**追加や削除**が先に完了すると、T1の同一トランザクション内でV1が更新されてしまうという問題です。
    - つまり、トランザクション内でのテーブルの一貫性に問題が生じることがありますよ。というものです。(READ COMMITEDで起きる可能性のある、レコードの一貫性については保証される)
- Serializable
    - 最もstrictな分離レベルです。トランザクションは完全に直列に実行されるかのように動作します。コンカレンシーが著しく低下しますが、あらゆる問題が回避できます。


## Snapshot Isolation とは何か

Snapshot Isolationとは、そのトランザクションの開始時のスナップショットの上で一連のコミットが実現するように見えるものだ。
トランザクション分離レベルで言うならば、REPEATABLE READとSERIALIZABLEの間に相当する。
というのも、あるトランザクションに含まれる読み取り操作はそれがトランザクション内の最初の方で実行されようが最後の方で実行されようが常に同じ結果を得ることになるので、REPEATABLE READで起きえる、phantom read の問題は起きない。ですので、REPEATABLE READとは異なる。

ただし、以下のような問題が起きる。
- T1 と T2 はそれぞれ独自のスナップショットの上で動作するので、T1とT2が競合する変更を行なってしまった場合に、整合性が取れなくなってしまうという問題
- MVCCを用いて実装されている場合、コミット時に他のトランザクションにおける変更がなかったかどうかを確認し、競合があれば、コミット自体をAbortすることで対処することが多い。
- ただし、T1とT2のそのままの順序でコミットするとは限らず、先にコミットが完了したトランザクションが成功してしまうことが起こり得る。

つまり、完全にトランザクションが`SERIALIZABLE`であるということは保証されないのが、Snapshot Isolationである。

一般に、Snapshot Isolationは、MVCCを用いて実装される

## MVCC

MVCCといっても、実装の具体的なものはいろいろある。
MVTO,MV2PL,2V2PLなど、MVCCの実装はさまざまであるが、多くが、Snapshot Isolationの分離レベル実現を行うためのアルゴリズムだ。

SERIALIZABLEを実現するには、最も悲観的なアプローチを取る必要があり、現実的なところでは、Snapshot Isolationが最も一般的に使われる選択肢だ。
【将棋】局面フォーマットの新提案

とある将棋盤アプリのために考案した「プレーンテキストベースの簡素かつ高可読性の局面フォーマット」を軽く紹介します。


![とある将棋盤アプリ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564662/9031a52c-abf0-3b1c-3ee6-663308955bbd.png)


## 先行事例

将棋の棋譜や局面を表すデータフォーマットは既に多く存在します。

https://qiita.com/sunfish-shogi/items/964e139ef3bfd8f738d4


### 「BOD」フォーマット

```
後手の持駒：なし
  ９ ８ ７ ６ ５ ４ ３ ２ １
+---------------------------+
|v香v桂v銀v金v玉v金v銀v桂v香|一
| ・v飛 ・ ・ ・ ・ ・v角 ・|二
|v歩v歩v歩v歩v歩v歩v歩v歩v歩|三
| ・ ・ ・ ・ ・ ・ ・ ・ ・|四
| ・ ・ ・ ・ ・ ・ ・ ・ ・|五
| ・ ・ ・ ・ ・ ・ ・ ・ ・|六
| 歩 歩 歩 歩 歩 歩 歩 歩 歩|七
| ・ 角 ・ ・ ・ ・ ・ 飛 ・|八
| 香 桂 銀 金 玉 金 銀 桂 香|九
+---------------------------+
先手の持駒：なし
手数＝0    まで
```

私自身は将棋関連のデータフォーマットについて詳しくありません。
いくつかのWeb上の記事を読む限り、BODというフォーマットが可読性が高くて良い感じですね。
しかし、対面側の駒を「v」を含む2文字で表現したり、空白マスを「・」等で表現していたりと、私がイメージする「プレーンテキストベースの簡素かつ高可読性の局面フォーマット」としては伸び代がありそうです。


## 理想
対面の駒を上下反転させる事が出来れば「プレーンテキストベースの簡素かつ高可読性の局面フォーマット」としては理想です。
英字に限ればプレーンテキストでの上下反転(させたように見せる)表現の有名なテクニックがあります。

```
I have a pen.
↓
.uǝd ɐ ǝʌɐɥ I
```

しかし残念ながら将棋の「歩」や「金」といった駒の字をプレーンテキストで上下反転させる事(や上下反転させたように見せる事)は難しそうです。


## 提案
というわけで妥協案として「結合文字」を活用して対面の駒に目印を付けました。

```
☗
－－－－－－－－－
香͙桂͙銀͙金͙玉͙金͙銀͙桂͙香͙
　飛͙　　　　　角͙　
歩͙歩͙歩͙歩͙歩͙歩͙歩͙歩͙歩͙
　　　　　　　　　
　　　　　　　　　
　　　　　　　　　
歩歩歩歩歩歩歩歩歩
　角　　　　　飛　
香桂銀金王金銀桂香
－－－－－－－－－
☖
```

```
☗
－－－－－－－－－
香͙桂͙銀͙金͙玉͙金͙銀͙桂͙香͙
　飛͙　　　　　馬　
歩͙歩͙歩͙歩͙歩͙歩͙　歩͙歩͙
　　　　　　歩͙　　
　　　　　　　　　
　　歩　　　　　　
歩歩　歩歩歩歩歩歩
　　　　　　　飛　
香桂銀金王金銀桂香
－－－－－－－－－
☖角
```

```
☗歩͙4銀͙
－－－－－－－－－
香͙　　　　　　桂͙香͙
　飛͙金͙　　　　　　
歩͙玉͙　歩͙馬　金͙　歩͙
　銀͙歩͙　全歩歩͙歩͙　
　　　歩角　　　　
　　歩　桂͙歩͙杏͙　歩
歩金　王銀　　　　
　　　　金　　飛͙　
香桂桂　　　　　　
－－－－－－－－－
☖歩2
```

> 結合文字（けつごうもじ、英語: combining character）とは、文字コードにおいて先行する文字と組み合わせるための図形文字をいう

https://ja.wikipedia.org/wiki/結合文字

結合文字を活用することで1字の横幅が変化しない形で「手前の駒」と「対面の駒」を見分けられるようになります。

このフォーマットのポイントは主に5つあります。

- 全ての駒やマスを全角文字の横幅で表す
- 横幅が変化しないタイプの結合文字を対面の駒に組み合わせる(今回は「COMBINING ASTERISK BELOW(U+0359)」)
- 盤面上の空白マスには全角スペースを配置する
- 盤と手駒の間には全角の区切り文字を配置する(今回は「－」)
- 手駒を載せる行には先頭に目立つ文字を配置する(今回は「☗」と「☖」)


<!--![COMBINING ASTERISK BELOW]()-->
![COMBINING ASTERISK BELOW.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564662/91513a69-4de2-8b04-e91b-be628aab9779.png)


このフォーマットを拙作の将棋盤アプリに採用しました。アプリ上の盤面をテキストとしてこのフォーマットで書き出したり、以前書き出したテキストを読み込んでアプリの盤面として復元したり出来ます。


<!--![アプリと「テキストエディット」]()-->
![AppAndTextEdit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564662/7bbf8408-d706-ab79-c4e9-bfe973101b0c.png)


Apple「メモ」アプリやLINE、X等でも概ね綺麗に表示されます。


<!--![Appleメモ]()-->
<!--![LINE]()-->
<!--![X]()-->
![Appleメモ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564662/e2fcdb6e-4d4d-300c-54bb-e6f88c44d1d5.png)
![LINE](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564662/dfb5b685-5dba-2bc6-550e-5ab03c0dc5cc.png)
![X](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564662/4731556c-9a10-143f-1f9d-293e864e387f.png)


プレーンテキストなのでテキストファイルとして保存したり、テキストエディタ上で局面を簡単に編集したり出来ます。

「簡素な構成」で「可読性が高い」「プレーンテキスト」の局面フォーマット。

いかかでしょうか。


![Plain将棋盤](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564662/0d0dc365-46e4-9a70-11c7-f67418254b8b.png)

https://apps.apple.com/app/id1620268476

https://github.com/FlipByBlink/PlainShogi
crystal tool expand でCrystalのマクロを展開する

## はじめに

完全にネタが尽きましたが、なにか書きます。

たとえば、次のようなCrystalのコードがあったとして、

```cr:piyo.cr
{% for i in 1..10 %}
  puts {{ i }}
{% end %}
```

実行すると、以下のように出力されます。


```
1
2
3
4
5
6
7
8
9
10
```

このマクロが実際にはどのように展開されているか知りたい場合はどうすればいいでしょうか？

## crystal tool expand でマクロを展開する

こんなときには `crystal tool expand` コマンドを使います。

```
crystal tool expand -c piyo.cr:2:8 piyo.cr
```

ここで、 `-c` オプションで、`ファイル名:行:列` を指定するのですが、マクロの範囲を指定しておけばだいたい動く印象です。

```
1 expansion found
expansion 1:
   {% for i in 1..10 %}
     puts {{ i }}
   {% end %}

~> puts(1)
   puts(2)
   puts(3)
   puts(4)
   puts(5)
   puts(6)
   puts(7)
   puts(8)
   puts(9)
   puts(10)
```

こんな感じでマクロが展開されました。

この記事は以上です。
SpringBootで『Project '※' has no explicit encoding set』警告の解消

# この記事はこれの続きです

https://qiita.com/waokitsune/items/d7fa0ab0c538f8e86729

# 概要

下記のような警告が出ているので、警告が出ないようにします。

> Project '※' has no explicit encoding set

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/b1e70689-e942-4cd2-277e-60dec683d13c.png)

『常に警告が出ている状態』だと『本当に対応しなくてはいけない警告』が出てきた時に見過ごす可能性があるためです。
狼少年のようなことが起きないように。

# やり方

プロジェクト上で右クリック → 『Properties』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/00b2215b-3bc7-2786-f8b4-a6b3d5641d18.png)

『Resource』 → 『Text file encoding』設定がこうなっているので…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/e2a9369e-b63c-e50c-0b25-e9bd8de7792a.png)

こう設定して適用。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/6a1d031e-747a-8dec-9591-744cd5e9993a.png)

警告消えました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/3d8c18f9-63e8-8652-58ef-20c824c013aa.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/c81c28ff-6f3f-223d-ae7d-05333f35a081.png)

# この記事の続き

https://qiita.com/waokitsune/items/18932a8b259191ad69c8

# 参考サイトさん

https://stackoverflow.com/questions/72692978/eclipse-project-project-name-has-no-explicit-encoding-set

# バージョン

Microsoft Windows [Version 10.0.19045.3693]
Spring Boot v3.1.6
Instruct GPTの仕組みについて

# はじめに

ChatGPTが普及し、世間も落ち着いてきました。ChatGPTを使ってみて凄いなと思いましたが、どんな仕組みなんだろう？と不思議に思いました。ChatGPTの元ネタとウワサされているInstruct GPTの仕組みに興味が湧いたので、調査してみました。

この記事は、@omiita(オミータ)さんの記事を参考にしました。

https://qiita.com/omiita/items/c355bc4c26eca2817324

# Instruct GPTの学習

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/413cf461-e5fa-e164-192d-e1ef90f46adb.png)
[Instruct GPTの論文](https://arxiv.org/abs/2203.02155)

Instruct GPTの論文では3ステップでモデルを学習させています。

- Step1では、１プロンプトに対して、labelerが望ましい出力を与え、SFT(GPT-3)をファインチューニングする。

- Step2では、１プロンプトに対して、様々なモデルが出力し、labelerがアウトプットに対して選好を決める。そのデータを用いて、報酬関数reward modelを学習する。

- step3では、新しい１プロンプトをサンプリングし、強化学習PPOの方策policyが出力を生成する。出力に対して、報酬関数reward modelが報酬を計算する。報酬関数reward modelを用いて、方策policyを学習する。

SFTはGPT-3みたいなものと考えればとりあえずよさそうです。
しかし、これだけでは、報酬関数reward modelと方策policyをどのように学習させているか不透明です。
詳しくみていきましょう。

# reward modelの学習

コマンド$x$を与えたとき、出力$y\in\lbrace y_0,y_1\rbrace$のどちらがいいかlabelerが判断します。仮に、ラベル$i$が望ましい場合のreward modelの損失lossは以下の通りです。

```math
\mathrm{loss}(\theta)=-\mathbb{E}_{(x,y_0,y_1,i)\sim D}[\log(\sigma(r_{\theta}(x,y_i)-r_{\theta}(x,y_{1-i})))]
```

ここで、$\sigma$はシグモイド関数です。


イメージをつけるために、例えを出します。
ラベル$i$のほうが望ましいと報酬$r_\theta$が算出すれば、$r_{\theta}(x,y_i)-r_{\theta}(x,y_{1-i})>0$となり、損失lossが小さくなります。一方で、ラベル$i$のほうが望ましくないと報酬$r_\theta$が算出すれば、$r_{\theta}(x,y_i)-r_{\theta}(x,y_{1-i})<0$となり、損失lossが大きくなります。

この損失lossが最小となるように、reward modelを学習させます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/d49f6dc8-274a-9de8-2824-90ecf7ba8fce.png)

上記の損失lossは2個ずつサンプリングしたときの結果ですが、Instruct GPTでは$K$個のデータをセットでサンプリングしたときの損失lossを計算します。$y_w$の方が$y_l$より好ましいものとします。

```math
\mathrm{loss}(\theta)=-\dfrac{1}{_KC_2}\mathbb{E}_{(x,y_w,y_l)\sim D}[\log(\sigma(r_{\theta}(x,y_w)-r_{\theta}(x,y_{l})))]
```

この損失lossが最小となるように、reward modelを学習させます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/7da3dacf-f0fc-6029-4ae3-b39d9557d6b2.png)

[reward modelの論文](https://arxiv.org/abs/2009.01325)
[RLHF](https://arxiv.org/abs/1909.08593)

# policyの学習
報酬$R$は、強化学習PPOのpolicy $\pi_{\phi}^{RL}$が、SFTの方策$\pi^{SFT}$から大きく離れないように、KLダイバージェンスの項を追加したものとします。

```math
R(x,y) = r_{\theta}(x,y)-\beta \log\left[\dfrac{\pi_{\phi}^{RL}(y|x)}{\pi^{SFT}(y|x)}\right]
```

目的関数objectiveである報酬の期待値が最大となるように、policy $\pi_{\phi}^{RL}$を学習させます。
ただし、pretrain datasetはモデルを事前に学習させるのに用意していたデータセットで、ここから大きく変わった結果がでないようにする項をいれています。

```math
\mathrm{objective(\phi)}=
\mathbb{E}_{(x,y)\sim D_{\pi_{\phi}^{RL}}} 
\left[
r_{\theta}(x,y)-\beta \log\left(\dfrac{\pi_{\phi}^{RL}(y|x)}{\pi^{SFT}(y|x)}\right)\right]

+\gamma \mathbb{E}_{x\sim D_{\mathrm{pretrain}} }\left[\log \left(\pi_{\phi}^{RL}(x)\right)\right]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/b3b48bf4-cc98-97c5-4635-b543a0e8ca15.png)


[reward modelの論文](https://arxiv.org/abs/2009.01325)
[RLHF](https://arxiv.org/abs/1909.08593)

# おわりに

ソースコードを公開した方がいるので、リバースエンジニアリングをしてみようと思います。

https://github.com/lucidrains/PaLM-rlhf-pytorch/tree/a159310cf411308ba6120096e53e7a4bb02e51a1
AWS SAMで最速CORS対応

# はじめに
丁寧なインターネット生活を。[にわのわ](https://twitter.com/niwa_nowa)です。

前回、Chrome拡張でPOSTリクエストを送信するものを作りましたが、
fetchで送信するとCORSエラーが発生してしまいました。

API Gatewayの設定を変更してこれを解消していきます。
個人で開発しているものかつ、URLを公開していないのでとにかくCORS対応して動作確認をしたい。
という視点での設定となっています。

# 作ったもの
CORS対応を行ったコミットはこちらです

https://github.com/niwanowa/niwanowa-RSSFeed/commit/79c841b360baeebccc5b0f161561e027f2bac00c

```template.yaml

Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Cors: 
        AllowOrigin: "'*'"
        AllowHeaders: "'*'"
        AllowMethods: "'*'"
...

```
 のように設定を記載します。

```Cors: "'*'"``` という記載では動作しませんでした。

# おわりに
AWS SAMはかなり使い勝手が良いですが、少しニッチでドキュメントが少なく感じます。
ですのでどんなひとくちナレッジでも記事にしようと思います。

# 参考
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-property-api-corsconfiguration.html
【Flutter】Git packageを依存関係に追加する際エラーとなる場合の対処法

Flutterにおいて、内製パッケージなど、pub.devに無いパッケージを依存関係に追加する場合、gitのURLでソースを指定する [Git packages](https://dart.dev/tools/pub/dependencies#git-packages) や、ローカルのパスでソースを指定する [Path packages](https://dart.dev/tools/pub/dependencies#path-packages) などの方法があります。

 今回、社内で内製したパッケージをGit packagesとして依存関係に追加しようとしたとき、以下のようなエラーが発生しました。
 ```
 Because every version of package1 from git depends on package2 from hosted
  and project1 depends on package2 from git, package1 from git is forbidden.
So, because project1 depends on package1 from git, version solving failed.
 ```

当該エラーは、同一のgitリポジトリ内に複数のパッケージがあり、その中のあるパッケージがもう一方のパッケージに依存している場合に発生します。
今回の例では、同一gitリポジトリ内のpackage1とpackage2が依存関係にあります。

```yaml:pubspec.yaml
dependencies:
  package1:
    git:
      url: ssh://hoge@hoge.com/my_packages.git
      path: packages/package1
  package2:
    git:
      url: ssh://hoge@hoge.com/my_packages.git
      path: packages/package2
```

この場合、dependency_overrides内にも指定するよう修正することでエラーが解消されます。
```yaml:pubspec.yaml
dependencies:
  package1:
    git:
      url: ssh://hoge@hoge.com/my_packages.git
      path: packages/package1
  package2:
    git:
      url: ssh://hoge@hoge.com/my_packages.git
      path: packages/package2
      
dependency_overrides:
  package1:
    git:
      url: ssh://hoge@hoge.com/my_packages.git
      path: packages/package1
  package2:
    git:
      url: ssh://hoge@hoge.com/my_packages.git
      path: packages/package2
```
CloudFormationの静的コード解析してますか？

## はじめに
本記事は[Japan AWS Ambassadors Advent Calendar 2023](https://qiita.com/advent-calendar/2023/japan-aws-ambassador)の5日目の記事になります。
先週はre:Inventに行っていてAWS漬けの毎日を送っていました。
帰国して膨大なメールを前に途方にくれているところです。。
さてアドカレ5日目は私の好きなサービスであるCloudFormationのネタを記載したいと思います。

## 質問
この記事を読んでいる皆さんは普段CloudFormationを利用する際に静的解析を実施していますか？
そんなの当たり前っしょ！って方はこの記事のコメント欄にお勧めのツールやこんなやり方あるよ～をドシドシ記載してもらえればと思います。
エっ何それ？今までやった事ないんだけど・・や静的解析ってそもそも何すんねんって方はこのブログを読んでCloudFormationの静的解析に一歩足を踏み入れてもらえればと思います。

## 静的解析をやる目的
一言で言えば**コードの品質を上げる為**です。
私はSier（システムインテグレータ）という仕事上、お客様の本番ワークロードを触る機会が多いです。
AWSのベストプラクティスに準拠するのであれば本番・開発・ステージングといわゆる本番環境と同等の環境を用意して、本番環境への変更の前にその同一環境でテストする事が求められますが、全てのAWSユーザがそうしているかと言うと、コストの面であったり、管理・運用といった様々な要因があり、本番環境相当の環境が準備できていないユーザもいます。そういったユーザに対しては本番ワークロードに直接変更を加える事になる為、当たり前ですが失敗する事が許容されません。ではどうしたらいいのかというとコードをデプロイする直前まで、可能な限りリスクを潰す事が求められます。そのリスクを潰す手段として静的解析が存在します。今回はそのリスクを潰すツールの1つとして私が利用した事のある静的解析ツールを紹介したいと思います。

## AWS CloudFormation Linter
私が紹介するツールはcfn-lintになります。
https://github.com/aws-cloudformation/cfn-lint

### 利用方法
Python3.7以上が入っていること
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198480/7d180824-a6de-a4af-0a2f-1cfcc5b3f908.png)

### cfn-lintでできること
- [リソースプロパティ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html)の有効性チェック
- [ベストプラクティス](https://docs.aws.amazon.com/wellarchitected/latest/framework/perf-bp.html)への準拠をチェック

VSCodeの場合作成したテンプレートを選択して View->Problems （Ctrl+Shift+M）でチェックできます。

:::note alert
重要なエラー
修正必須
:::
:::note warn
警告
注意が必要、修正が要らない場合もある
:::
:::note info
インフォメーション
知って損はない情報
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198480/727e9de3-e8b0-4bdf-bbcb-89644ae15880.png)

### cfn-lint対応エディタ
以下のエディタをサポートしてます。
ちなみに私はVSCodeのプラグインを入れて使ってます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198480/d1e69afd-7887-3f1f-6154-832efc2d5a60.png)



## まとめ
ツールを使う意義というところでは人間は完璧ではないので、最後は機械的にチェックする事で人間の見落としも含めてレビューの質を高めるところが目的であると考えます。人がチェックする場合はチェックシートを作成してレビュー観点一つ一つをチェックするといったやり方を私自身した事がありましたが、ツールを利用する事でそういった**手間**をいい意味で省いて開発者もレビュアーも双方で幸せになれますね。この記事をきっかけに静的解析やってみよっかな？って思った人がいたら幸いです。

## P.S.
re:InventにてVSCodeからApplication Composerが利用できるようになったと発表がありました。
聴くところによるとVSCodeからダイレクトに利用可能でD＆Dでアイコンを置いていくだけでCFnテンプレートが自動生成されていくそうです。
これはいままでゼロベースまたはサンプルテンプレートベースにCFnを書いていた自分にとっては凄く便利な統合がされたな！といった感想です。
まだ試してみていないので確かな事は言えないですが、以前Application Composerがリリースされた当初は利用可能なサービスに制限があったので、今回の機能アップデートによって可能であれば全てのサービスが利用できるようになっているとよりgoodだと思いました。
利用してみた感想は追ってブログ書こうと思います。
さて明日のアドカレ6日目はGEEKFEEDのAmazon Connect大好き西山さんです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198480/1b9a0f95-d21f-925b-407e-9c20a6524072.png)

https://aws.amazon.com/jp/about-aws/whats-new/2023/11/ide-extension-aws-application-composer/?nc1=h_ls

https://aws.amazon.com/jp/blogs/aws/ide-extension-for-aws-application-composer-enhances-visual-modern-applications-development-with-ai-generated-iac/
テスト工程とは（初心者向けの基本解説記事）

# はじめに

単体テスト,結合テスト,結合テストについての学習をまとめて備忘録として投稿させていただきました。内容は初心者向けの基本的な手順や違いの説明になります

## 単体テスト,結合テスト,総合テストの違い

単体テスト:機能単体のテストを実施すること
結合テスト:機能同士を組み合わせたテストを実施すること
総合テスト:システム全体のテストを実施すること

## 単体テストとは

 プログラムの最小単位である、メソッド単位で行われるテストです。場合によってはクラス全体を対象とすることもあります。

 ### 単体テストの目的

 単体テストでは単体のメソッド（関数）が期待通りの結果を返すかどうかを確認します。これにより、そのメソッドが正しく機能することを確認します。しかし、そのメソッドが複数の他のメソッドやクラスと連携して機能する場合は、それらの相互作用もテストする必要があります。

 単体テストとは、基本的にメソッド単位から始まりますが、そのメソッドが属するクラスや他の関連するメソ度との連携も考慮されます

 ### 単体テストの例

 以下の計算するメソッドがあります
 ```java
public class Calculator {

    public int add(int a, int b) {
        return a + b;
    }

}
 ```
 Javaの場合、テスティン部フレームワークのJunitでメソッドの結果が期待通りに機能するかを検証することができます。

以下のassertEqualsメソッドは期待される値と実際の値が等しいかどうか検証できます
 ```java
assertEquals(期待される値, 実際の結果);
 ```

 ```java
@Test
public void testAddition(){

        // Calculatorクラスのインスタンスを生成する
        Calculator calculator = new Calculator(); 
        // addメソッドに引数として3と4を与えて計算を行う
        int result = calculator.add(3, 4); 
        // 計算結果が7と等しいか検証する
        assertEquals(7, result); 
    }




 ```

 ## 結合テストとは

ソフトウェアのクラスやメソッドなどを組み合わせて、うまく動作するかを確かめるテストです。単体テストで個別にメソッドやクラスが動作することが確認できたとしても、組み合わせた場合にエラーが発生しないかを確認するために実施します。

具体的にはそれぞれのメソッドやクラスからによるデータの受け渡しが正常に行われるか、データの受け渡しタイミングは適切かどうかなどを検証します

### 結合テストの例

例としてオンラインストアのシステムをテストを想定した場合、以下のようなテストが実施されます

- 商品検索機能のテスト
ユーザーが特定のキーワードで商品を検索し、正しい商品を返されることを確認します

- カートへの追加機能のテスト
選択した商品をカートに追加すると、カート内に正しく商品が追加されることを確認します

- 支払いページへの遷移テスト
カートに商品が追加されている状態から、支払いページに正しく遷移することを確認します

- 支払い情報の入力テスト
支払い情報を入力し、正しいフォーマットで受け入れられることを確認します

- 支払いの完了テスト
支払いを完了させ、注文が正常に確定されているかを確認します


このように結合テストでは**テストシナリオ**を作成することが一般的です。

#### テストシナリオとは
システムのさまざまな部分を連携させて、システム全体の動作をテストするための計画や手順を示したものです

##　総合テストとは

ソフトウェア全体を完成させてから行われるテストです。それぞれの部品や機能（メソッドやクラスなど）が単体テストと結合テストで個別にテストされた後、最後にそれらを組み合わせて、全体として正しく動作するかを確認するテストです。

つまり、総合テストは、単体テストや結合テストの後に行われ、ソフトウェア全体が要求通りに機能するかを最終的に確認する重要なテストになります。
SpringBootのバージョンを3.1.5から3.1.6へアップ

# この記事はこれの続きです

https://qiita.com/waokitsune/items/c8dfe4a0a90020bdb556

# 概要

現行は3.1.5。
下記警告が出ていたのでバージョンアップをしてみます。

> Newer patch version of Spring Boot available: 3.1.6

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/67e3230b-2c77-e4b7-9311-6a25509280f6.png)

デモ環境なので、バージョンアップによるデグレは考えなくてよいという判断です。

# build.gradle変更

警告文をダブルクリックすると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/ae91a9c7-5e56-f3b7-eb89-2c077757169f.png)

build.gradleが開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/5d5ba88e-1260-a226-8b3f-99edd4ed9d8b.png)

3.1.6へ変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/e2b5f18f-fda5-df31-48b8-77b0673ca4c6.png)

プロジェクト上で右クリックして…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/57c07b72-9fa0-bfc3-4b3b-185eb356c022.png)

『Gradle』 → 『Refresh Gradle Project』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/b525e72b-a280-8fda-aa68-0381326ac666.png)

1～2分ほどGradleの処理を待つと、バージョンに関する警告は消えました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/4f61b694-12f1-1888-585d-c7e9fc8dad97.png)

Spring Boot Appを起動すると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f5309001-debb-62a0-da2e-f2de667cc5ba.png)

ちゃんとバージョンアップされていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/67bc8daa-f7fb-2960-48b0-6c58f0fd0466.png)

# Gradleとは何ぞや

下記を参考にさせてもらいました。

https://camp.trainocate.co.jp/magazine/about-gradle/

すっごくざっくり言うとgradleは　~~グラビアアイドル~~　『必要なライブラリのインストール』などをやってくれます。
build.gradleは『どんなバージョンをインストールせよ』という設定ファイルです。

設定ファイルをちょろっと書き換えるだけで、あとはGradleが勝手にやってくれます。
便利です。

# この記事の続き

https://qiita.com/waokitsune/items/83febc4a0518d7d346aa

# 参考サイトさん

https://camp.trainocate.co.jp/magazine/about-gradle/

# バージョン

Microsoft Windows [Version 10.0.19045.3693]
Spring Boot v3.1.5
Spring Boot v3.1.6
二次元配列の入力 2 Python3編


https://paiza.jp/works/mondai/array_primer/array_primer__2dmatrix_input_step2

入力したとおりに出力する問題。
今までやった復習で、アンパックの方法を使って。

```py
M = int(input())
for _ in range(5):
    A = map(int,input().split())
    print(*A)

```

アンパックを使わない方法だと

```py
M = int(input())
#配列作成
A = [[0] * M for _ in range(5)]
#配列に入力データを入れる
for i in range(5):
    #別に単次元の配列を作成してそれに1行のデータを入れる
    values = input().split()
    #用意した配列に単次元の配列の要素ごとに格納していく
    for j in range(M):
        A[i][j] = int(values[j])

#配列から出力
for i in range(5):
    for j in range(M):
        print(A[i][j], end="")

        if j < M - 1:
            print(end=" ")
        else:
            print()

```

多次元配列への要素の入れ方として前半のコードは
覚えておきたいところ。

たとえばN行M列の配列を出力させるとすると
こういう風に公式みたいにできる。

```py
N,M = map(int,input().split())
A = [[0] * M for _ in range(N)]

for i in range(N):
    values = input().split()
    for j in range(len(values)):
        A[i][j] = int(values[j])
        
for i in range(N):
    for j in range(M):
        print(A[i][j], end="")
        if j < M-1:
            print(end=" ")
        else:
            print()

```
ただ、このときに、i行目、j列目の数を出力となると
```py
if i == K - 1 and j == L - 1:
    print(A[i][j]
```
というふうに−１しないといけない点に注意。
grid()を使用してウィジェットを配置すると親フレームがリサイズされる

## はじめに
tkinterを使用して簡易的なアプリケーションを作成しており，FrameやWidgetを配置する```pack()``` や ```grid()```で詰まった点を紹介します．備忘録です．

## 問題点
<ins>表題の通り，フレーム内に```grid()```でウィジェットを配置しようとすると，親フレームがリサイズされてしまう現象が発生した．</ins>

下図（サンプル）のように配置したかった...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617469/978ba381-8885-c1a6-63f1-1458c6f52358.png)

## 動作環境
- Python 3.12.0
- tkinter 8.6.12

## やったこと
tkinterの配置メソッドは```pack()```，```grid()```，```place()```があり，
- ```pack()``` ... 縦・横並びに配置
- ```grid()``` ... 格子状に配置
- ```place()``` ... 指定座標にピンポイントで配置

という特徴があります．
今回のケースでは格子状に配置するので```grid()```を採用しました．以下ソースコードです．
### ソースコード
```python
import tkinter as tk

root = tk.Tk()
root.title("tkinter")

frame = tk.Frame(root, width=1200, height=500, relief=tk.SOLID, bd=1)
frame.propagate(False)
frame.pack(side="left", fill=tk.Y, padx=2, pady=(0, 2))

inner_frame1 = tk.Frame(frame, width=200, height=100, relief=tk.SOLID, bd=1)
inner_frame1.grid(row=0, column=0, padx=5, pady=5, sticky=tk.NSEW)

inner_frame2 = tk.Frame(frame, width=200, height=100, relief=tk.SOLID, bd=1)
inner_frame2.grid(row=1, column=0, padx=5, pady=5, sticky=tk.NSEW)

inner_frame3 = tk.Frame(frame, width=200, height=100, relief=tk.SOLID, bd=1)
inner_frame3.grid(row=0, column=1, padx=5, pady=5, sticky=tk.NSEW)

inner_frame4 = tk.Frame(frame, width=200, height=100, relief=tk.SOLID, bd=1)
inner_frame4.grid(row=1, column=1, padx=5, pady=5, sticky=tk.NSEW)

root.mainloop()
```

L7の```frame.propagate(False)```で，フレーム内のウィジェットによらずフレームサイズが変更されないようになります．
上述のコードを実行すると下図のようにinner_frameのサイズに合わせて親フレームの横幅が変更されてしまいました．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617469/c6a77552-2dd3-105d-fcd2-ea319b605a2d.png)
（狭すぎるッ...!!）

## 解決策
解決方法としては，L7のコードを以下のように変更しました．
```python
# 変更前
frame.propagate(False)

# 変更後
frame.grid_propagate(False)
```
```.grid_propagate(False)```ですが，基本的に前述の```.propagate(False)```のgrid版だと思ってください．pack版の```.pack_propagate(False)```もあります．

inner_frameをpackで配置すると```.propagate(False)```でも親フレームはリサイズされないみたいです．
<br></br>
（そもそも子のフレームサイズをピッタリ合わせてサイズ不変にしたら，こんなこと起きないんですけどね．）

## おわりに
```grid()```を使用する際は親オブジェクトの```propagate()```に注意する必要がありそうなことがわかった．
【11日目】OSS連携してみたい！(8)Autowareのpure pursuitを調査する

この記事は筆者オンリーの[Advent Calendar 2023](https://qiita.com/advent-calendar/2023/aichallenge_racing_for_mas)11日目の記事です。  

# 前回までのあらすじ
C++/PythonでAutowareのmsgをサブスクライブしmsgをそのままAutowareにパブリッシュする処理を追加しました。

# 今回やること
OSS連携について、pursuitの処理をPythonRoboticsのソースコードに置き換えて実行してみたいと思います。
そこで、現在のAutowareの入出力、内部処理について調査してみたいと思います。

# pursuitの各処理について
[Autoware](https://github.com/AutomotiveAIChallenge/aichallenge2023-racing/blob/main/docker/aichallenge/aichallenge_ws/src/aichallenge_submit/autoware_micro/simple_pure_pursuit/src/simple_pure_pursuit.cpp)、[PythonRobotics](https://github.com/AtsushiSakai/PythonRobotics/blob/master/PathTracking/pure_pursuit/pure_pursuit.py)の処理はリンクの通りになります。

# Autowareのpursuitの構成
pursuitの構成を見てみます。
# 引数/サブスクリプション/パブリッシャー
引数
・wheel_base
・lookahead_gain
・lookahead_min_distance
・speed_proportional_gain
・use_external_target_vel
・external_target_vel
のfloatがあります。
サブスクリプション
・[Odometry](https://docs.ros.org/en/noetic/api/nav_msgs/html/msg/Odometry.html)
・[Trajectory](https://github.com/tier4/autoware_auto_msgs/blob/tier4/main/autoware_auto_planning_msgs/msg/Trajectory.idl)
の2つのmsgをサブスクライブしているようです。
Trajectory内には最大100000のベクターの[TrajectoryPoiont](https://github.com/tier4/autoware_auto_msgs/blob/tier4/main/autoware_auto_planning_msgs/msg/TrajectoryPoint.idl)を持つことができるようです。

パブリッシャー
・[AckermannControlCommand](https://github.com/tier4/autoware_auto_msgs/blob/tier4/main/autoware_auto_control_msgs/msg/AckermannControlCommand.idl)
のmsgをパブリッシュしているようです。
AckermannControlCommandは
・Time型のstamp
・[AckermannLateralCommand](https://github.com/tier4/autoware_auto_msgs/blob/tier4/main/autoware_auto_control_msgs/msg/AckermannLateralCommand.idl)型のlateral
（メンバーはsteering_tire_angle/steering_tire_rotation_rateで構成されている）
・[LongitudinalCommand](https://github.com/tier4/autoware_auto_msgs/blob/tier4/main/autoware_auto_control_msgs/msg/LongitudinalCommand.idl)型のlongitudinal
(メンバーはspeed、acceleration、jerkで構成されている)
で構成されているようです。
# メッセージをパブリッシュ/サブスクライブする契機
30ms毎にOdometry/Trajectoryのデータを受領してmsgを作成しているようです。

# パブリッシャーの作成
上記のAckermannControlCommandにパラメータを入力しているようです。
・AckermannControlCommand.stamp
・AckermannControlCommand.longitudinal.stamp
・AckermannControlCommand.lateral.stamp
には現在のタイムスタンプが入っているようです。

・AckermannControlCommand.longitudinal.speed
・AckermannControlCommand.longitudinal.acceleration
・AckermannControlCommand.lateral.steering_tire_angle
にpure pursuitで計算したパラメータを入れているようです
  
のパラメータを作り込んでいるようです。
処理としては
Trajectroryの複数点とOdometoryの点を比較し、Trajectory内の最も近い点(インデックス)を取得する。
上記で取得したTrajectoryの縦方向のスピードをlongitudinal.speedに代入する。
proportinal gainと縦方向の速度差分をlongitudinal.accelerationに代入する。
先読み点を検索し、計算を行い
ateral.steering_tire_angleに代入する。
ということをを行っているようです。

# まとめ
いろいろOSS連携してみたかったけど面倒くさい予感がしてきた。。。
BashとZshの違い

## BashとZshの概要
- Bash
BashはUNIX系オペレーティングシステムで使用されるコマンドラインシェルの一つで、GNUプロジェクトによって開発されました。Bashは、Bourne Shellのフリーソフトウェア版として機能を継承しつつ、C ShellやKornShellの機能を取り入れた高機能なシェルです。

- Zsh
ZshはUNIX系オペレーティングシステムで使用される強力なコマンドラインシェルの一つで、Bourne Shellやbash、ksh、tcshの便利な機能を取り込んでいます。Zshは特に強力な入力補完機能やカスタマイズ性の高さで知られており、macOS Catalina以降ではデフォルトのシェルとして採用されています。

## Zshの設定ファイル
Zshの動作をカスタマイズするために以下の設定ファイルが使用されます。
- .zshenv
Zshが起動した際に必ず読み込まれます。ここでは主に環境変数などの、操作に関係のない設定を記述します。
- .zprofile
ログインシェルの場合に１度だけ読み込まれます。つまりインタラクティブシェルやシェルスクリプトでは不要だけどログインシェルの時だけ必要な設定をする場合にはここに記述します。
- .zshrc
Zshのインタラクティブシェル(ユーザーがコマンドを入力する画面)が起動した際に読み込まれます。このファイルには主にZshの操作に関する設定を記述します。
- .zlogin
ログインシェルの場合だけ読み込まれます。zprofileと一緒なのだが、重要なのはzshrcの後に読み込まれるということです。
- .zlogout
シェルからexitする前に読み込まれます。最後に定型的な処理をさせたい場合にはここに記述します。

## BashとZshの違い
BashとZshは、Unix系のコマンドラインインターフェースで、ユーザーがコンピューターと対話するためのシェルです。Bashはシェルの基本的な機能を網羅しており、多くの場合、標準仕様で利用されます。一方、ZshはBashよりも高度な機能を持つシェルでBashの上位互換という位置付けです。Zshはより進んだタブ補完機能や、コマンドのスペルチェック、テーマやプラグインによるカスタマイズが可能です。

## エイリアスでショートカットコマンドを作成する
コマンドのショートカットを作成するには、.zshrcや.bashrcなどの設定ファイルなどにエイリアスを設定します。
```.zshrc
alias 新しいコマンド='元のコマンド'
```
これにより、新しいコマンドと入力するだけで元のコマンドが実行されるようになります。
また、エイリアスは単に新しい名前を提供するだけなので、元のコマンドはそのまま使えます。