OmniAICreator/Qiita-1.07M huggingface dataset:
初心者向け　YAMLファイルの基礎を理解する

YAMLファイルについて、そもそもどんなものなのか理解できていなかったので調べてみました。今回はYAMLファイルの基礎的な部分（基本的な構文や特徴）が理解できることをゴールとしています。
IT未経験のため間違っている点がありましたらご指摘いただけますと幸いです。

# そもそもYAMLファイルとはなに？
YAMLファイルとは、アプリやサービスの設定ファイルを記述する際に使われるファイルです。他にもJSONやXMLといったデータ形式がありますが、YAMLはその中でも人間にとっての読みやすさNo1です。また、多くのプログラミング言語で読み書きができるという特徴があります。

# どんな用途で使われる？
- アプリやサービスの設定ファイル（`docker-compose.yml`など）
- CI/CD（GitHub Actionsの`workflow.yml`）
- Djangoなどのフレームワークの設定

上記のような場面で幅広く使われています。設定ファイルはWebアプリの細かなふるまいを決定する際に必要になります。Dockerなど、設定ファイルがないと動かないシステムもあります。

#  YAMLファイルの書き方は？
いくつかの基本的なルールがあります。
### 1. データの階層構造をインデントで表す。
JSONでは{ }や[ ]で階層構造を表現しますが、YAMLではこれをインデントで表現します。この際のインデントはタブではなくスペースです。
### 2. キーの後に":"、値との間にスペースを入れる。
```
name: hanako
```
※スペースは2つでもエラーにはなりませんが、可読性の観点で1つが推奨されます。

### 3. リストの記述はインデントを揃え、"-"を入れる。
```
list:
  - item1
  - item2
  - item3
```
※スペースが1つでも3つでもエラーにはなりませんが、一般的には2つが推奨されます。

### 4. リストの階層が深い場合はそれぞれにインデントを揃え、スペースをあける。
```
services:
  db:
    container_name: MySQL
```

### 5. 表現が曖昧な場合は文字列に`" "`や`' '`をつける。
```
date: "2024-12-15"
```
※プログラムによってはデータ型が意図しない型で判断され、エラーになることがあります。

### 6. コメントは`#`で記載する。
```
name: hanako
# これでコメントが記載できます
```

# プログラム毎にフォーマットのルールは決まっているの？
各プログラムやツール毎にフォーマットが決まっています。基本的な書き方を踏まえた上で、公式サイト等を参考に決められた形式に従います。


# コンピューターにとっても読みやすいファイルなの？
設計自体はコンピューターにとっても読みやすいように作られています。しかし、データ型の曖昧さやインデントのミスによってエラーが起こります。これを防ぐために、YAMLファイル専用のLintツール（yamllint）やVS Codeの拡張機能（YAML by Red Hat）を利用すると良い様です。今回はYAMLファイルの基礎を理解することが目的のため、この部分は今後理解を深めていきます。

# 結論
今回はYAMLファイルの基本的な構文や特徴を理解しました。今後、実際にツールで使用されるYAMLファイルを操作しながら具体的な使い方を学んでいきたいと思います。
A Tour of Go【Packages, variables, and functions.】まとめ

## はじめに

A Tour of Goについて勉強になった箇所をまとめる。

## パッケージ参照

最初の文字が大文字で始まる名前は、外部のパッケージから参照できるエクスポート（公開）された名前。

 パッケージをインポートすると、そのパッケージがエクスポートしている名前を参照することができる。
 エクスポートされていない名前(小文字ではじまる名前)は、外部のパッケージからアクセスすることはできない。

 ↓ Pi は math パッケージでエクスポートされている。

```go
package main

import (
	"fmt"
	"math"
)

func main() {
	fmt.Println(math.Pi)
}
```

## 引数の型定義の省略

関数の２つ以上の引数が同じ型である場合には、最後の型を残して省略して記述できる。


```x int, y int```　を　```x, y int```　へ省略している。

```go
package main

import "fmt"

func add(x, y int) int {
	return x + y
}

func main() {
	fmt.Println(add(42, 13))
}
```

## 複数の戻り値

関数は複数の戻り値を返すことができる。

```go
package main

import "fmt"

func swap(x, y string) (string, string) {
	return y, x
}

func main() {
	a, b := swap("hello", "world")
	fmt.Println(a, b)
}
```

## Named return values

名前をつけた戻り値の変数を使うと、 return ステートメントに何も書かずに戻すことができる。

```go
package main

import "fmt"

func split(sum int) (x, y int) {
	x = sum * 4 / 9
	y = sum - x
	return
}

func main() {
	fmt.Println(split(17))
}
```

## 変数

### 変数のリスト

```var```では複数の変数の最後に型を書くことで、変数のリストを宣言できる。

```go
package main

import "fmt"

var c, python, java bool

func main() {
	var i int
	fmt.Println(i, c, python, java)
}
```

### 初期化子

初期化子が与えられている場合は型を省略でき、その変数は初期化子が持つ型になる。

```go
package main

import "fmt"

var i, j int = 1, 2

func main() {
	var c, python, java = true, false, "no!"
	fmt.Println(i, j, c, python, java)
}
```

### 暗黙的な型宣言

関数の中では、 ```var``` 宣言の代わりに、短い := の代入文を使い、暗黙的な型宣言ができる。
※関数の外では、キーワードではじまる宣言( var, func, など)が必要で、 := での暗黙的な宣言は利用できない

```go
package main

import "fmt"

func main() {
	var i, j int = 1, 2
	k := 3
	c, python, java := true, false, "no!"

	fmt.Println(i, j, k, c, python, java)
}
```

### 基本型一覧

```
bool

string

int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr

byte // uint8 の別名

rune // int32 の別名
     // Unicode のコードポイントを表す

float32 float64

complex64 complex128
```

### ゼロ値

変数に初期値を与えずに宣言すると、ゼロ値( zero value )が与えられる。

ゼロ値は型によって以下のように与えられます:

```
数値型(int,floatなど): 0
bool型: false
string型: "" (空文字列( empty string ))
```

### 型変換

変数```v``` 、型```T``` があった場合、 ```T(v)```は、変数```v```を```T```型へ変換する。


```go
package main

import (
	"fmt"
	"math"
)

func main() {
	var x, y int = 3, 4
	var f float64 = math.Sqrt(float64(x*x + y*y))
	var z uint = uint(f)
	fmt.Println(x, y, z)
}
/// 3 4 5
```

### 型推論

明示的な型を指定せずに変数を宣言する場合( := や var = のいずれか)、変数の型は右側の変数から型推論される。

```go
package main

import "fmt"

func main() {
	v := 42 // change me!
	fmt.Printf("v is of type %T\n", v)
}
/// v is of type int
```

## 定数

定数( constant )は、 const キーワードを使って変数と同じように宣言する。
文字(character)、文字列(string)、boolean、数値(numeric)のみで使える
定数は```:=``` を使って宣言できない。

```go
package main

import "fmt"

const Pi = 3.14

func main() {
	const World = "世界"
	fmt.Println("Hello", World)
	fmt.Println("Happy", Pi, "Day")

	const Truth = true
	fmt.Println("Go rules?", Truth)
}
/// Hello 世界
/// Happy 3.14 Day
/// Go rules? true
```
#2 Claudeでコードを一切書かずにゲームを作成する話

https://qiita.com/Kazzynao/items/d94d69f60a272ffdaf3a

それでは、前回の続きのClaudeとのやりとりを掲載していきます。

## 設定がわからない部分もスクリーンショットで伝えるだけ！
初めてGodotを使うので、Inspectorにどんな項目があるか、それがどこにあるか分からなかったので、Inspectorのスクリーンショットを貼りつけ。
さらに、イメージを表示する際にTextureRectとSprite2Dという2種類のNodeがあったので、それについても、検索するよりもGodotに聞く方が理解が早かったです。

![CleanShot 2024-12-15 at 13.33.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3961653/8614ee52-9daf-d48a-bfe3-f8cd2f813d69.png)

## リングの動きが完成したので、次は発射する「弾」を実装。

スクリーンショットが長いですが、予約すると一度に多くの実装を伝えたため作業手順が多くなり、自分の理解不足で色々とエラーが発生して、その解決方法についてのやりとりです。

![CleanShot 2024-12-15 at 13.41.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3961653/41adec23-871e-2e1e-8ec3-57f707ca4e8b.png)

## シンプルな構造で一から構築
Claudeの指示を仰ぎながらも、どうしてもエラーが回避できず諦めかけていたのですが、こういう時はシンプルな構造から作っていく方がミスも減るんじゃないかと、まずはスコアとかゲームオーバーの実装は後回しにして、
・リングが回転する
・弾が発射される
を最低限の実装として作り直すことに。
これが上手くいき、基本の構造がほぼ想像通りに出来ました。
![CleanShot 2024-12-15 at 13.50.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3961653/2abc037c-5fb9-e169-1ae0-38d0e38c6547.png)


それでは、今日はここまでにしたいと思います。
次は、さらに細かい部分の調整をClaudeとともにやっていきます。

ここまで読んでいただきありがとうございました！
自作ブラウザを作ってみた話

この記事はKCS Advent Calender 2024の15日目の記事です。

# Latte's Simple Browser (LSB)

Latte's Simple Browser (LSB) は、ブラウザの基本機能を学びながら実装することを目的として設計されています。実用に足るブラウザを作ることは目的としていません。

:::note warn
この記事の内容はd0iasmさんの「作って学ぶブラウザの仕組み」とは一切関係ありません。ご注意ください。
:::

このプログラムではまずHTMLのコードを解析するためのパーサを作成し、SDL2 を利用してウィンドウに描画することで、シンプルなブラウザアプリケーションを作成します。

![lsb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448138/8e7d3d50-069a-e12d-6254-5b3f9e353a0e.png)
⇑LSBで筆者のポートフォリオを表示した様子⇑

:::note warn
あまり一般向けな内容でもなく、完成度も高くないためソースコードの解説は省略し、概要と感想のみに留めさせていただきます。質問があれば下にあるコメント欄か、Twitterなどで連絡してください。
:::

## 特徴
LSB は以下のような特徴を持っています。
- **シンプルな設計**: 必要最低限の機能に絞り込んで設計
- **軽量**: 小規模なプログラムサイズで動作
- **教育目的**: ブラウザの基本的な動作原理を学ぶための実装例

このプロジェクトは、C 言語と SDL2 を使用して開発されています。

## 一般的な WebBrowser との違い
一般的なWebBrowserには以下のような機能がついています。
- Webページのデータを取得
- HTMLの構文を解析してDOMを構築
- HTMLをパースした結果をGUIライブラリを使って描画
- CSSを解析し、フォント、色、レイアウトなどを反映
- JavaScriptを実行するには専用エンジンを組み込む

しかし今回作成したLSBではWebページのデータを取得したり、JavaScriptを使ってサイトを動的に変更することはできません。
一応、HTMLの構文を解析してDOMを構築し埋め込まれたCSSも解析していますが、対応は限定的です。

## 動作環境

LSB を実行するためには以下が必要です：
- **GCC** (GNU Compiler Collection)
- **SDL2 ライブラリ**

## SDL について
SDL は、C 言語で書かれたクロスプラットフォームのグラフィック描画ツールです。フォントやネットワーク、スプライト、画像処理などの多数の補助ライブラリが公開されています。詳しくは [SDL Wiki](https://wiki.libsdl.org/SDL2/FrontPage) をご覧ください。

日本語の資料はあまり多くないですが、低レベルなグラフィックス処理をシンプルに行うためのAPIを提供していて、レンダリングや画像の管理、描画処理が比較的簡単に実装できるので採用しました。

## SDL2 のインストール
### Ubuntu の場合
以下のコマンドを実行して SDL2 をインストールしてください：
```bash
sudo apt install libsdl2-dev libsdl2-ttf-dev
```

### その他の環境
他の OS で SDL2 をインストールする方法については、[SDL Wiki](https://wiki.libsdl.org/) を参照してください。

## プログラムのダウンロードと実行
### GitHub リポジトリ
ソースコードはこちらのリポジトリで公開しています：
[Latte's Simple Browser (LSB)](https://github.com/Latte72R/LSB/)

### プログラムの実行
完成版のプログラムは、以下の手順に従ってソースコードをダウンロードしコンパイルすることで実行できます。

1. **リポジトリをクローン**
   ```bash
   git clone https://github.com/Latte72R/LSB.git
   ```

2. **ディレクトリを移動**
   ```bash
   cd ./LSB
   ```

3. **プログラムをコンパイル**
   ```bash
   gcc ./main.c ./parser.c -o lsb -lSDL2 -lSDL2_ttf
   ```

4. **ブラウザを起動**
   ```bash
   ./lsb ./test.html
   ```

## 作成した感想
今回はHTMLやCSSをある程度手動でパースするプログラムになってしまった。できればもう少し一括出会い王するプログラムが作りたかった（というかもともとはタグの一覧とパースした際に付与する条件をまとめていた）のだが、`<title>`や`<script>`など様々な挙動をするタグがあったため次作る気になったときはもっと完成度の高いものを作りたい。

## まとめ

今回、LSBを実装することでブラウザやHTMLの仕様について考える良い機会となりました。自分でコードを読んだり、カスタマイズしたりすることで、ブラウザの仕組みや Web 技術への理解を深まると思います。興味を持たれた方は、ぜひリポジトリからコードをダウンロードし、体験してみてください。
Codeじゃない方のVisual Studio 2022で、GitHub Copilotのコード提案が動かない場合の対処法

![a1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568364/b98e0c61-c2b8-a9ff-af99-f2dce24d4779.png)

もはや日々の開発に欠かせなくなったCopilot。

![a2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568364/d297cd2c-3eb8-0a90-b44c-ced32fafe433.png)

以前はVisualStudio 2022の機能拡張でしたが、17.10以降は主なワークロードの一部として含まれるデフォルトの機能になったようです。
Visual Studio Installerから個別にインストールしたりアンインストールしたりできますが、デフォルトで指定されていますので、あえてアンインストールしない限りは勝手に入っているはずです。

# Copilotがコード提案をしなくなった

このVisualStudioのアップデートあたりを境に、私の環境ではCopilotがコード提案をしなくなりました。Copilot Chatとか、それ以外のCopilotの機能は動作します。

![a4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568364/eecf5b59-5ba5-bc46-a377-0b14befb0be4.png)

開発者コマンドプロンプトから`devenv /ResetSettings`を実行すると、再びコード提案をするようになります。これは設定を全部リセットしてしまいますので、色々とカスタマイズしている人は諦めて設定し直してください。

![a5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568364/d38bfcc9-5164-f80b-8dad-99bfa8d37797.png)

また`ResetSettings`で直らない場合、`Copilot.ToggleLanguage`コマンドを実行してみてください。キーボードマップで`Copilot.ToggleLanguage`を検索し、適当なキーにバインドして、エディタ上でコマンドを実行すると、復旧することがあります。
【Rails】in_order_ofがもっと便利になった

# 概要
in_order_ofというメソッドがある

https://railsdoc.com/page/in_order_of

> ```rb:使い方
> モデル.in_order_of(カラム, 値)
> ```

こんな感じで使う
```rb
User.in_order_of(:id, [2, 3, 1])
```
順序を指定して並び替えができる便利メソッド

上のコードを実行すると、このような配列を取得できる

```
[#<User:0x0000ffff84edde90 id: 2, created_at: "2024-12-15 04:19:33.799418000 +0000", updated_at: "2024-12-15 04:19:33.799418000 +0000">,
 #<User:0x0000ffff84eddd50 id: 3, created_at: "2024-12-15 04:19:33.803428000 +0000", updated_at: "2024-12-15 04:19:33.803428000 +0000">,
 #<User:0x0000ffff84eddc10 id: 1, created_at: "2024-12-15 04:19:33.791725000 +0000", updated_at: "2024-12-15 04:19:33.791725000 +0000">]
```
idが2, 3, 1の順に並び、それ以外のレコードはフィルタされている

# 8.0以降
filterという引数を渡せるようになった
これは、値としてわたした条件以外のレコードも取得するもの

```rb
User.in_order_of(:id, [2, 3, 1], filter: false)
```
実行してみる
```
app(dev)> User.in_order_of(:id, [2, 3, 1], filter: false)
  User Load (6.9ms)  SELECT `users`.* FROM `users` /* loading for pp */ ORDER BY CASE WHEN `users`.`id` = 2 THEN 1 WHEN `users`.`id` = 3 THEN 2 WHEN `users`.`id` = 1 THEN 3 ELSE 4 END ASC LIMIT 11
=>
[#<User:0x0000ffff84ee9c40 id: 2, created_at: "2024-12-15 04:19:33.799418000 +0000", updated_at: "2024-12-15 04:19:33.799418000 +0000">,
 #<User:0x0000ffff84ee9b00 id: 3, created_at: "2024-12-15 04:19:33.803428000 +0000", updated_at: "2024-12-15 04:19:33.803428000 +0000">,
 #<User:0x0000ffff84ee99c0 id: 1, created_at: "2024-12-15 04:19:33.791725000 +0000", updated_at: "2024-12-15 04:19:33.791725000 +0000">,
 #<User:0x0000ffff84ee9880 id: 4, created_at: "2024-12-15 04:19:33.818582000 +0000", updated_at: "2024-12-15 04:19:33.818582000 +0000">,
 #<User:0x0000ffff84ee9740 id: 5, created_at: "2024-12-15 04:19:33.820695000 +0000", updated_at: "2024-12-15 04:19:33.820695000 +0000">,
 #<User:0x0000ffff84ee9600 id: 6, created_at: "2024-12-15 04:19:33.825088000 +0000", updated_at: "2024-12-15 04:19:33.825088000 +0000">,
 #<User:0x0000ffff84ee94c0 id: 7, created_at: "2024-12-15 04:19:33.829939000 +0000", updated_at: "2024-12-15 04:19:33.829939000 +0000">,
 #<User:0x0000ffff84ee9380 id: 8, created_at: "2024-12-15 04:19:33.834391000 +0000", updated_at: "2024-12-15 04:19:33.834391000 +0000">,
 #<User:0x0000ffff84ee9240 id: 9, created_at: "2024-12-15 04:19:33.836578000 +0000", updated_at: "2024-12-15 04:19:33.836578000 +0000">,
 #<User:0x0000ffff84ee9100 id: 10, created_at: "2024-12-15 04:19:33.840795000 +0000", updated_at: "2024-12-15 04:19:33.840795000 +0000">]
```
2, 3, 1以外のレコードも取得されるようになった

```sql
// filter: true
SELECT `users`.* FROM `users` WHERE `users`.`id` IN (2, 3, 1) /* loading for pp */ ORDER BY CASE WHEN `users`.`id` = 2 THEN 1 WHEN `users`.`id` = 3 THEN 2 WHEN `users`.`id` = 1 THEN 3 END ASC LIMIT 11

// filter: false
SELECT `users`.* FROM `users` /* loading for pp */ ORDER BY CASE WHEN `users`.`id` = 2 THEN 1 WHEN `users`.`id` = 3 THEN 2 WHEN `users`.`id` = 1 THEN 3 ELSE 4 END ASC LIMIT 11
```

`filter: false`にすると`WHERE `users`.`id` IN (2, 3, 1)`が消えている

地味にありがたい変更なので覚えておきたい

### 実装されたPR

https://github.com/rails/rails/pull/51761
bb9の電池を付け替える

### 背景
sphero bb9をメルカリで入手したので、遊べるように電池を交換しました。

中身を傷つけないようにリューターでカプセルを割りました。

電池が見える状態

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/b0e01a0c-59b1-e0b1-d0ce-2ca8e5fe21d3.png)

:::note alert
警告
この記事について作者はいかなる責任も負いません。
バッテリー関連の改造は非常に危険な行為です。
:::

### 電池を探す
探し回った結果、次の電池は入るようなので購入しました。

https://www.amazon.co.jp/dp/B07GJS8W5M

### つなぐ
メイン基板との接続用にピンソケットは交換前の部品を流用しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/21c08085-7ae9-573d-ba2f-37d3f169ddbb.png)

### 充電器で起動する
boltと同様に充電器で起動しました。
前後のLEDがゆっくり点滅しました。

### 今日のまとめ
電池が膨らんで充電できなくなったsphero bb9の電池を代替えして動かすことができました。
ここでも大きさが合っている電池を探すのに1か月くらいかかりましたが、動かすことができてよかったです。

繰り返しになりますが、

:::note alert
警告
この記事について作者はいかなる責任も負いません。
バッテリー関連の改造は非常に危険な行為です。
:::
playwrightのscreenshot と video の自動保存機能について

# screenshot と video の自動保存機能について

playwright では screenshot と video の自動保存機能がある。

# screenshot の自動保存機能
以下の様に記述することで、テスト実行時に screenshot が自動保存される。

```tsx
  // ページ全体のスクリーンショットを保存
  await page.screenshot({ path: 'screenshots/datepicker.png' });

  const calendarInputField = page.getByPlaceholder('Form Picker');
  await calendarInputField.click();
  // calendarInputField のスクリーンショットを保存
  await calendarInputField.screenshot({ path: 'screenshots/calendarInputField.png' });

  // screenshot をバイナリデータとして取得
  const buffer = await page.screenshot();
  console.log(buffer.toString('base64'));
  /* 長い長い文字列が出力される。screenshot をバイナリデータとして取得することで、
   1. 画像データをテキストとして扱える
   2. データベースへの保存が容易
   3. APIでの送受信が可能
   4. HTMLのimg要素のsrc属性で直接表示可能
  */
```

# video の自動保存機能

playwright.config.ts の use の中で video: 'on' を設定することで、テスト実行時に video が自動保存される。
なお、test-results/UsePageObjects-parametrized-methods-chromium/video.webm のような形で保存される。
```tsx
  use: {
    trace: 'on-first-retry',
    // 以下を追記
    video: 'on',
  },
```
条件分岐の様々な書き方

## はじめに
チェリー本で学習中に`!!`を用いた真偽値の型変換について学習した
他にも色々書き方あると考え列挙してみた

```
def user_exists?
   # データベースなどからユーザを探す（なければnil）
   user = find_user
   if user
     # userが見つかったのでtrue
     true
   else
     # userが見つからないのでfalse
     false
   end
end

# 上と同義(否定系の否定 = 結果をbooleanでそのまま返す)
def user_exists?
   !!find_user
end
```


## 三項演算子
```
# find_userメソッドがtureであればtureを返し、falseであればfalseを返す
def user_exists?
  find_user ? true : false
end
```

## 早期リターン
```
def user_exists?
  return true if user_find
  false
end
```

## 最後に

個人的人は三項演算子が読みやすい気がする

## 参考文献
https://ruby-book.jnito.com/
VecをHashSetに変換する

VecからHashSetを作成したい場合、まず`collect`を利用する方法があります。メソッドチェーンで書ける、型推論が活用できるという点で個人的にはこちらが好みです。

```rust
let v = vec![1, 2, 2, 3, 3, 3];
let s = v.into_iter().collect::<HashSet<_>>();
```

もしくは、`HashSet::from_iter`を利用する方法もあります。ただし型推論がうまくいかずに、型の明示が必要になる場合があります。

```rust
let v: Vec<i32> = vec![1, 2, 2, 3, 3, 3];
let s: HashSet<i32> = HashSet::from_iter(v.iter().cloned());
```

**環境情報**

- rustc 1.76.0 (07dca489a 2024-02-04)
- cargo 1.76.0 (c84b36747 2024-01-18)
出力: サウンド

### 背景
Sphero IDEには音声再生のブロックが用意されています。
boltは本体ではなく、制御するPCやスマホから音が鳴るようです。

### Scratch
サウンドの欄にブロックがありました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/2d2d81f2-cc43-d717-2633-f3ceced01859.png)

四角いボタンを押すと音の種類を選べました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/730c1ba4-6988-7d02-6185-c382751051aa.png)

「ロボットの321の音を再生する」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/1e27c5cf-5cd1-20c9-ff6c-51df85d6a861.png)

サウンドのブロックの右にあるwaitを押すと、waitと「続ける」を選ぶことができました。
「続ける」は音声を再生しながら次に進むということでした。

### spheroV2
sphero_edu.pyには音声再生の関数が見つかりませんでした。
代わりにpygameモジュールを用いて再生するようにしました。

https://www.pygame.org/wiki/GettingStarted

```
import time

from spherov2 import scanner
from spherov2.sphero_edu import EventType, SpheroEduAPI
from spherov2.types import Color

from spherov2.utils import FrameRotationOptions

import os

import pygame

print("Testing Starting...")
print("Connecting to Bolt...")
toy = scanner.find_BOLT()

if toy is not None:
    print("Connected.")
    with SpheroEduAPI(toy) as api:
        pygame.mixer.init(frequency=44100)

        api.set_stabilization(False)

        api.set_main_led(Color(r=50, g=0, b=0)) #Sets whole Matrix
        time.sleep(1)

        file_path = os.path.abspath("jinglebells.mp3")
        
        pygame.mixer.music.load(file_path)
        pygame.mixer.music.play()
        while pygame.mixer.music.get_busy():
            continue

        api.set_main_led(Color(r=0, g=0, b=0)) #Sets whole Matrix
        time.sleep(1)

else:
    print("Failed to connect to Sphero.")
```

実行結果はこちらのようになりました。
```
git\spherov2.py\spherov2\test>python BoltTest_sound.py
pygame 2.6.1 (SDL 2.28.4, Python 3.12.7)
Hello from the pygame community. https://www.pygame.org/contribute.html
Testing Starting...
Connecting to Bolt...
Connected.
```

音楽が終了するまでは次に進まないですので、Scratchの「続く」のような機能は並列化などで対応できるのかもしれないです。

### まとめ
spheroV2とpygamesを用いて、サウンドをpythonで模擬的に動かすことができました。
bluetoothイヤホンを改造して、bolt側にスピーカーをつけると面白そうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/62ebabf6-3e39-c875-c7d5-8df8867528a6.png)
端末に保存する方法

データを端末内部に保存する方法のメモ。
端末にデータを保存、削除のするにはgetSharedPreferencesを使用する。
```kotlin
val sharedPref = context.getSharedPreferences("preference_file_key", Context.MODE_PRIVATE)
// getSharedPreferences(保存するファイル名, Context.MODE_PRIVATE)

sharedPref.edit().putString("key","value").apply()
// edit().putString(キー,値).apply()
println(sharedPref.getString("name","")) // value

```
```kotlin
sharedPref.edit().putString("key","apple").apply()
println(sharedPref.getString("key","")) // apple
// 別の値を入れると上書きされる。
```
全ての値を消したいときはclearを使用する。
```kotlin
val sharedPref = context.getSharedPreferences("preference_file_key", Context.MODE_PRIVATE)
sharedPref.edit().clear().apply()
println(sharedPref.getString("name","")) //   (値なし)
```

参考

https://android.keicode.com/basics/preferences-basic.php
MATLAB/Simulinkでモデルベース設計メモ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/2061e873-a91f-9bc5-0670-5bfa2b79d4cb.png)


一次遅れ系伝達関数
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/8e474dc7-89ef-0daf-7aeb-fd8256920d7e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/3df23efc-bb65-3223-21ae-4ed72a279c84.png)

チャットGPTから引用　入力の種類
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/42c2d18d-550d-5a7a-3adb-eed45dc9d06f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/fcee2589-6471-9a49-a975-083d292c4fa8.png)

自由落下モデル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/9d404abe-103a-382b-1d32-f154c2b572fd.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/93d9ab42-0e3e-77b2-da8f-35a18f77c1ed.png)


アンプ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/6e20abe3-05b1-4193-3c74-432b02715ccc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/5fbcbf53-098c-e0b8-7ab0-78b11d2e7569.png)

NAND回路
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/3951d86e-efee-ed6b-660f-014f1b191ff0.png)
```
function Y = nand_gate(A, B)
% NANDゲートの実装（閾値2.5V, ハイ: 5V, ロー: 0V）
% 入力: A, B (入力電圧)
% 出力: Y (NANDゲートの出力)

% 閾値電圧
Vth = 2.5;

% NAND論理判定
if A > Vth && B > Vth
    Y = 0;  % 両方が閾値を超えた場合、出力はロー (0V)
else
    Y = 5;  % それ以外はハイ (5V)
end
end

```
PWM用のコンパレータ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/5262cd02-2085-ea5b-6f14-304d3c8e1107.png)
```

function Y = pwm_comparator(input1, input2)
% PWM用の2入力コンパレータ
% 入力: input1, input2
% 出力: Y (5V: ハイ, 0V: ロー)

% 出力電圧の定義
HIGH = 5;  % ハイの電圧
LOW = 0;   % ローの電圧

% 比較処理
if input1 > input2
    Y = HIGH;  % 入力1が入力2より大きいなら5V
else
    Y = LOW;   % 入力1が入力2以下なら0V
end
end

```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/4129ff12-3333-a074-58bf-91917612e654.png)


Pythonコード
```
import matplotlib.pyplot as plt
import numpy as np

# PWM信号生成関数
def generate_pwm(frequency, duty_cycle, duration):
    """
    PWM信号を生成してプロットする
    :param frequency: PWM信号の周波数 (Hz)
    :param duty_cycle: デューティ比 (0～100%)
    :param duration: シミュレーション時間 (秒)
    """
    # 基本パラメータ
    T = 1 / frequency  # PWM周期 (秒)
    t = np.linspace(0, duration, int(1000 * duration))  # 時間軸

    # PWM波形の生成
    pwm_wave = ((t % T) < (duty_cycle / 100) * T).astype(float)  # デューティ比に基づいて波形を生成

    # プロット
    plt.figure(figsize=(10, 4))
    plt.plot(t, pwm_wave * 5, color='blue')  # 5V信号として表示
    plt.title(f"PWM Signal (Frequency: {frequency} Hz, Duty Cycle: {duty_cycle}%)")
    plt.xlabel("Time (s)")
    plt.ylabel("Amplitude (V)")
    plt.grid(True)
    plt.ylim(-0.5, 5.5)
    plt.show()

# パラメータ設定
frequency = 10       # PWM周波数 (Hz)
duty_cycle = 30      # デューティ比 (%)
duration = 0.5       # シミュレーション時間 (秒)

# PWM信号生成関数を呼び出し
generate_pwm(frequency, duty_cycle, duration)
```

https://ir2110-test.hatenablog.jp/entry/2023/12/02/162200


https://note.com/hsn_fomalhaut/n/ne14d1d1d4fd6
RockyLinux 8.7 における ActiveDirectory ユーザのグループ表示不具合

# 問題

なるべく RockyLinux バージョンを 8.7 に固定したくてインストールメディア内の winbind パッケージを使用して ActiveDirectory 連携をした。

```
# yum --disablerepo=\* --enablerepo=InstallMedia-* --releasever=8.7 install samba-winbind samba-winbind-clients
# net ads join
```

AD参加はできたが、idコマンドでユーザ情報を表示しようとするとデフォルトグループしか表示されない。

```
# id xxxxx
uid=11306(xxxxx) gid=10513(domain users) groups=10513(domain users)
```

# 解析

```
# smbcontrol winbind debug 10
```
としてログレベルを上げて idコマンド実行時のログを見ると、 NT_STATUS_OBJECT_NAME_NOT_FOUND となっていてユーザ情報取得時に失敗している模様。

```
...

../../librpc/ndr/ndr.c:484(ndr_print_function_debug)
       wbint_LookupUserAliases: struct wbint_LookupUserAliases
          in: struct wbint_LookupUserAliases
              sids                     : *
                  sids: struct wbint_SidArray
                      num_sids                 : 0x00000010 (16)
                      sids: ARRAY(16)
                          sids                     : S-1-5-21-3973462380-3092671858-2928372798-513

 ...

../../librpc/ndr/ndr.c:484(ndr_print_function_debug)
       wbint_LookupUserAliases: struct wbint_LookupUserAliases
          out: struct wbint_LookupUserAliases
              rids                     : *
                  rids: struct wbint_RidArray
                      num_rids                 : 0x00000000 (0)
                      rids: ARRAY(0)
              result                   : NT_STATUS_OBJECT_NAME_NOT_FOUND

 ...
```

ログに出ている sids リストについて、`wbinfo --sid-to-name` で変換してみると、正しく得られる。

```
$ wbinfo --sid-to-name S-1-5-21-3973462380-3092671858-2928372798-513
Domain Users 2
```

NT_STATUS_OBJECT_NAME_NOT_FOUND をキーワードに検索してみると、winbind 4.16.4 にはどうやら[バグがある](https://access.redhat.com/solutions/6995660)らしい。

実際、winbindバージョンを見るとドンピシャ。

```
# yum info samba-winbind
Installed Packages
Name         : samba-winbind
Version      : 4.16.4
Release      : 2.el8
Architecture : x86_64
Size         : 1.2 M
Source       : samba-4.16.4-2.el8.src.rpm
Repository   : @System
From repo    : InstallMedia-BaseOS
Summary      : Samba winbind
URL          : https://www.samba.org
License      : GPLv3+ and LGPLv3+
Description  : The samba-winbind package provides the winbind NSS library, and some client
             : tools.  Winbind enables Linux to be a full member in Windows domains and to use
             : Windows user and group accounts on Linux.
```

# 対処

RockyLinux 8.7 に限定しないで yum search すると winbind 4.18.6 が提供されているので更新。

```
# yum install samba-winbind samba-winbind-clients
```

インストール後に id コマンドを実行してみると、ちゃんと表示された。

```
# id xxxxx
uid=11306(xxxxx) gid=10513(domain users) groups=10513(domain users),10572(denied rodc password replication group),11649(groupmanagers),11164(roaming user profiles users and computers), ...
```

下手にバージョンを上げないようにするとこんなこともある。
docker(201) install error(158)

LLM(Large Language Model) Calendar 2024
https://qiita.com/advent-calendar/2024/llm
9日目の記事です。

externally-managed-environment, python pip error
https://qiita.com/kaizen_nagoya/items/237922e479c5182686e6

error(159) externally-managed-environment docker(202) pip, python(47) install
https://qiita.com/kaizen_nagoya/items/4757f7ac9c47f6611a60

python3(48) docker(203) error(160)
https://qiita.com/kaizen_nagoya/items/7edf72ec7e7a1bfacbe3

```
# apt install docker
...
Selecting previously unselected package wmdocker.
Preparing to unpack .../5-wmdocker_1.5-2_amd64.deb ...
Unpacking wmdocker (1.5-2) ...
Selecting previously unselected package docker.
Preparing to unpack .../6-docker_1.5-2_all.deb ...
Unpacking docker (1.5-2) ...
Setting up libxau6:amd64 (1:1.0.9-1build5) ...
Setting up libxdmcp6:amd64 (1:1.1.3-0ubuntu5) ...
Setting up libxcb1:amd64 (1.14-3ubuntu3) ...
Setting up libx11-data (2:1.7.5-1ubuntu0.3) ...
Setting up libx11-6:amd64 (2:1.7.5-1ubuntu0.3) ...
Setting up wmdocker (1.5-2) ...
Setting up docker (1.5-2) ...
...
# docker run -v /ws:/tmp/ws -it ubuntu /bin/bash
bash: command docker not found
# find / -name docker
/usr/lib/google-cloud-sdk/lib/googlecloudsdk/core/docker
/usr/lib/google-cloud-sdk/lib/googlecloudsdk/command_lib/ai/docker
/usr/lib/google-cloud-sdk/lib/surface/artifacts/docker
/usr/lib/google-cloud-sdk/lib/third_party/docker
/usr/local/lib/python3.10/dist-packages/wandb/docker
/usr/local/lib/python3.10/dist-packages/docker
/usr/share/doc/docker
/opt/pytorch/torch_tensorrt/docker
/opt/pytorch/text/.circleci/smoke_test/docker
/opt/pytorch/pytorch/.ci/docker
/opt/pytorch/pytorch/third_party/kineto/libkineto/third_party/dynolog/third_party/DCGM/docker
/opt/pytorch/pytorch/third_party/cutlass/python/docker
/opt/pytorch/pytorch/third_party/flatbuffers/tests/docker
/opt/pytorch/apex/examples/docker
```
AndroidとMacでのファイル共有

# はじめに

この記事は、Qiita Advent Calendar 11日目の記事です。
以下の記事より、すべての記事をご覧になれます。

https://qiita.com/0_terarin_0/items/2b60d47a2d0e64a273c3

# 本編

以前よりXiaomiのAndroidを利用しているんですけど、この時に困るのがファイル共有。普段はiPhoneを使っているのでAirDropっていうなんでもかんでもまあまあなスピードで共有できる超神ツールがあるんですけど、AndroidのQuick Shareは使えませんよね。

と思っていました。

https://github.com/Martichou/rquickshare

こちらの方を使ってみることにしました。

## インストール

またこれインストールが大変なんかなと思ったけど、パッケージが公開されています。

https://github.com/Martichou/rquickshare/releases

それぞれ、あったものをインストールしてください。ただ、Armとかは自分でビルドをする必要があります。（Macを除く）

アプリの見た目はこんな感じです。AndroidとMacを同じネットワークに接続しましょう。さて、これ、Androidから認識されるのでしょうか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583428/3b62984e-f7bb-9484-6e33-33f7e3399cd8.png)

## MacからAndroidに送信

ファイルをドラッグしてデバイスを選択します。普通に送信できました。

![Screenshot 2024-12-15 at 12.48.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583428/79ad222d-3559-081d-e51b-861c4a31a9a5.png)

## AndroidからMacに送信

通常通り送信しようとしたらコンピューターに現れるのでそれで送信します。こちらも普通に送信できます。

![Screenshot_2024-12-15-12-49-33-503_com.google.android.gms.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583428/94cff4d0-ae59-2f2c-0158-23b913218b8f.jpeg)

## 注意点

この機能、Captive認証が必要なWi-Fi下、Enterpriseネットワーク下では利用できません。ネットワーク経由なので仕方がないですね。今後はBluetooth経由でできるようにしようと頑張っていますね。

https://github.com/Martichou/rquickshare/blob/master/TODO.md

# 最後に

今回は軽めの記事でしたけどこれ結構革命じゃないでしょうか。今後に乞うご期待です。
【完全なるおまけ】SESから中堅SIerに転職した話

## 自分のスペック
新卒は全然エンジニアと関係ない仕事をしていた。
次に第二新卒としてSES企業に異業種転職をし、大体3年弱のエンジニア歴。
そこから今年の秋にSIer企業に転職し、今は業務に少しずつ慣れてきている状態。
これまでは詳細設計～単体テストといういわゆる下流行程がメインであり、典型的なSESの働き方をしていた。
スキル感的にはそこまで高くないかなというのが正直なところ。開発はできるけど、そこまでレベルは高くないし、設計も詳細止まり。

## 何で転職しようと思ったのか
### SESという働き方が嫌になった
未経験で拾ってくれたことには感謝だが、正直SESという働き方は開発以外で気をつかうことが多く、ちょっとしんどかった。同じ現場にはいるけど社員・パートナーという風に区別をつけられ、やっと慣れてきたと思ったら全く違う現場になり…。
すごくストレスという訳では無かったけど、現場もコロコロ変わるから、常に人間関係も頑張らなきゃいけないことがちょっといしんどくなった。しかも1人常駐なので心寂しい。

またSESあるあるだと思うが、帰属意識がほぼ無く、同じ会社なのに名前も顔も知らないという状況もちょっとしんどかった。特に忘年会に呼ばれたりすると初めまして状態だから、しゃべるのきっつい…

### 将来への不安
前の会社は上場もしていない、社員も100人程度の小さい会社だった。だからか、整備されていないところも多々あったし、将来もこの会社は存続しているのだろうかという不安は常にあった。またほぼSES事業しかしておらず、成長性が見込めなかった。

年収も正直低いし、福利厚生も整っていない。自分のライフプランと照らし合わせた時に、転職するなら今しかないと思った。

### 下流行程しか経験できない
これもSESならではと思うが、おおよそ開発から単体テストまでしか担当させてくれない。自分が将来もエンジニアとして働くならば、設計の工程もちゃんと経験すべきだと考えた。
もちろん設計もとても大変だと思うが、まだ若いうちに経験(失敗も含め)を積んでおくことで、将来のやれることの幅が広がるうと考えた。

### 会社への不信感がちょっとあった
これは個人的な話だが、上層部の人数が少なく、色々なことがおざなりになっていると感じた。例えば面談をしますと言っても、結局なされなかったり…。勉強会もコロナ時期はあったが最近は一切無くなったりと。
また転職前に研修があると言われていたにも関わらず、前職に就いている時に現場面接させされ、転職1日目から現場に派遣になった。おかげ様でかなり苦労した…。

## もちろん悪いことばかりではない
未経験でエンジニアになったけど、色々な技術に触ることができたし、資格もちらほら取ることができた。新卒の時から年収も上がったし、たまにリモートワークもできてワークライフバランスはかなり改善された。

SESに入ることは悪いことばかりではない。ただある程度経験を積んだら次のステップに行っても良いと個人的に思った。
自分は将来もエンジニアとして働きたいし、できることなら20代(自分は今20代半ば)のうちに上流工程の経験も積んでおきたいと考えている。それを叶えるためにはSESの環境から次へ行かないといけないと考えた。

## 転職の軸
今年の夏頃にゆるっと転職活動を開始。最初は自分で進めようとしたが全然スケジュールが立てられず、レバテックさんに申し込んだ。

ざくっと転職の軸は以下
* フル出社でない(半分くらいリモートが理想)
* SESでない(SIerはOK)
* 年収アップ
* 上流工程できる
* 後は自分と雰囲気があいそうか(かなり感覚的だが)

## 結果
書類選考　20社
書類通過　7社
1次面接通過 6社
2次面接辞退　3社
2次面接通過(内定) 3社

2次面接辞退は内定承諾後に辞退したものもあれば、雰囲気や軸と合わなさそうということで辞退したものもあり。最終的に2次面接を通過した中で第一希望の会社に入社した。

## 転職活動で大変だったこと
### やはり面接とその対策
面接のスケジュール調整がとにかく大変だった。当時はリモートワークもできたので、業務中に離席すると言って抜け出したり、業務時間外に面接することもあった。とにかく物理的に時間も無いし、対策もしなければでヒィヒィしてた思い出。ただ面接スケジュールも面接対策もエージェントさんの方でしてくれるので、そこはとても助かった。

### 本当にこれでいいのかぶれまくる
転職の軸もこれで良いのかぶれてくるし、そもそも今転職して良いのかもぶれてくる(現場がちょうど忙しい時だった)。しかもSES以外を希望していたのにエージェントさんからSESの求人が送られて、今のあなたのスキル感だとSESも見た方が良いと言われる。そして面接でも、それうちじゃなくても良くない？と本当に言われる。

ただちゃんと自分の希望は折らずに持っておいた方が良い。多少妥協も必要だが、最低限の条件を達成しているものを受ける方が時間も無駄にしなくて済む。

### リモート面接のトラブル
企業から送られてきたURLに入れなかったり、途中でWifiが切れたりなど…。前者は事前にURLから入ってみるとかちゃんと確認した方が良い。マジで焦るので…。

## 結局転職して良かった？
まだ転職して数か月しか経っていないが、結論転職して良かったと感じている。理由は以下。

* ある程度大きい会社なので、コンプラや規律が整備されている
* 教育の制度が整っている(キャリアプランや資格報奨金など)。放置されてる感が無い
* オフィスが綺麗
* ロールモデルが多い
* 基本設計やらせてもらえる
* 年収も上がった。後資格報奨金もあるので、資格取得のモチベが上がる
* 勉強会が多く開催されており、最新の情報をキャッチアップしやすい

などなど…。ちょっとまだ不安なところもあるし、転職するとアウェイ感きちぃなーと思う場面もあるが、総合的には良さげ。

## これからどうしていきたいか
ということで新しい会社での生活も始まり、これからどうしていきたいか考えてみた。

* まずは目の前の仕事を頑張る
せっかく設計の仕事ができるので、書き方などをしっかり吸収していきたい。また、プロジェクト運営のやり方なども意識して、コミュニケーションも大事にしていく。
* 資格を沢山取る
技術力を上げると同時に報奨金を沢山GETしたい…
* 会社の人と仲良くなる
SESでは全然自社の人と会う機会が無かったので、今の会社では沢山の人と仲良くなりたい。その方が仕事も捗ると思う。
* 次の転職は特に考えていない
今回で2度目の転職をしたが、特に次も転職しようとは考えていない。もちろん上を見ればより良い会社は沢山あるが、まずは今の会社で全力を出し切りたい。自分がどこまでできるか試してみたい。
データ分析におけるベースライン作成【初心者】

## なぜベースラインを作成するのか
ベースラインを作成する主な理由はベースラインがないと評価の判断がしづらいからです。
データの可視化やデータの前処理を行う際にも基準となるものがないと精度の良し悪しを判断することが難しくなります。


## ベースライン作成で意識すること
1. 目的変数の設定
2. どのモデルを使って評価を行うか
3. モデルを何の評価指標で評価するか

### 1. 課題の理解
  Kaggleであればコンペの内容、業務であれば課題を理解することが非常に重要です。何を目的変数にするか、どの評価指標を使うかを理解することが分析設計につながります。
　私はこの課題の理解を疎かにしてとりあえず手に動かす癖があるのですが、結局のいつか課題の理解をしなければならず、それまでやっていたことが無駄になった経験があります。最初は面白くないと感じることもあると思いますが、焦らずに時間をかけて課題の理解を行いましょう！
  
### 2. データの確認
　簡単にデータの確認を行います。確認することは以下の3点です。
 ・レコード数、カラム数
 ・データの型
 ・欠損値
 仮に欠損値があったとしても、ここで欠損値の補間を行うことは避けましょう！
 欠損に意味がある場合もあるので、ここでは確認に留めておきましょう。

### 3. 目的変数と説明変数
　次に目的変数と説明変数の作成を行います。
 説明変数は全ての項目を入れると、問題点の洗い出しがしにくくなるため最初は2,3個程度を使って行いましょう。あくまでベースライン作成を行っていることを忘れないことが大切だと思います。

### 4. バリデーション設計
　手元のデータを使って作成するモデルを評価するためにバリデーション設計を行います。
 詳しくは述べませんが、学習データと検証データを分割する手法としてホールドアウト検証と交差検証が挙げられます。重要なことは本来手元にないはずの未来のデータを使って学習をすることがないようにバリデーション設計を行うことです。

### 5. モデル学習
　どのモデルを使うかは悩むと思いますが、最初のうちはLightGBMを使うことが良いと思います。
特にLightGBMではカテゴリ変数を数値に変換したり、欠損値を処理する必要がないため初心者にはおすすめです。

### 6. モデル推論
　いよいよ最後の工程です。学習したモデルと推論用データセットを使って予測を行いましょう。

## 最後に
最後まで読んでいただいた方はありがとうございます！
私もデータ分析を始めたばかりでわからないことしかないのですが、大切なのは1つ1つ学んでいくことだと思ってます。私と同じようにデータ分析始めたばかりの方がいれば一緒に頑張りましょう！
内容に不備があれば、ご指摘いただけると嬉しいです！

### 参考文献
1. 諸橋政幸 『[Kaggleで磨く機械学習の実践力](https://www.ric.co.jp/book/new-publication/detail/2168)』 リックテレコム, 2022
Paraphrase の開発状況 2024

　年末恒例となりました今年の進捗です。今年は 2 月に ver.0.97 をリリースした後はデバッグや仕様の軽微な変更を行いつつ、ドキュメントシステム Paradocs（パラドックス）の機能拡張と、それを用いた文書整備を行っていました。いや、正確に記すなら、Paradocs を使って文書整備を行っていたら、不具合や不都合が発生したので、それらにひとつひとつ対応していった、という状況となります。

　なお、Paradocs とは Paraphrase で記述されているドキュメントシステムであり、特徴としては索引の自動作成に対応している点が挙げられます。シングルソース・マルチユースなドキュメントシステムであり、HTML 版と TeX 経由の PDF 版を最終成果物として生成します。

Paraphrase は Forth 系の言語であるため、ワードに関する索引が重要となります。しかし、索引生成に対応しているシングルソース・マルチユースなシステムであり、HTML 版と PDF 版の出力をサポートしているドキュメントシステムが見つけられなかったため、しょうがなく自作している…といった状況です。

…と、このような状況なので、この記事を言語実装アドベントカレンダーに載せて良いものかどうかと一瞬悩みましたが、自作言語の場合、文書整備も重要な作業であるという思いから掲載してしまっています（論理的には少々無理がある説明ですが、まあ、それはそれとして…）。

# 進捗その１
　冒頭にも書いたように、ver.0.97 のリリースができました。ver.0.96 では Windows 版のビルドに少し苦労しましたが、ver.0.97 では特に問題もなく割とあっさりと Windows 版、Linux 版、MacOS 版を用意できた印象があります。今年度末にリリースする ver.0.97.1 でも同様にトラブル無くリリースできたら良いな、と願っています。

# 進捗その２
　言語処理系自体に変更はありませんが、いくつかのワードについてはデバッグや仕様変更を行いました。

## デバッグしたもの
### AOP 関連
　docol で呼び出し先のローカル変数用スタックの後始末ができていない問題を解決しました。

## 仕様変更したもの
### リスト関連
　ワード (< と >) を用いると Python のリスト内包表記のように、動的にリストを作成できます。これまではインタプリタモードの時のみこれらのワードを利用できましたが、今回、コンパイル
モードならびにリスト構築時などのシンボルモードにおいても機能するように機能拡張を行いました。

# 進捗その３（ドキュメント関連）
## Paradocs に関するもの
### 機能拡張
#### 文書内リンク
　Paradocs 文書内でリンクを張れるタグ <[href …]> を追加しました。
#### url タグ
　HTML 版においては、ハイパーリンクを生成する url タグを新設しました。
#### 表現能力
　鍵括弧 ( ) および中括弧 { } ならびにバックスラッシュに対応しました。


### デバッグ
　Paradocs で生成される HTML 版のドキュメントの索引部分において、正しくリンクを張れていないバグがありました。それを修正いたしました。

　HTML 出力における索引生成部において、正しくエンティティ参照を処理できない場合がありましたので、それを修正しました。

## 従来のワードリファレンスに関するもの
　cdr の説明部分に誤りがありましたので訂正を行いました。

　slice の説明部分のサンプルコードに誤りがありましたので修正を行いました。

　リストの構築終了処理を行うワード ')' のスタックの変化に関わる部分について誤りがありま
したので修正しました。

# まとめに代えて
　この文書は毎月 1 回発行している「Paraphrase の開発現場より」というメルマガ原稿を参考に書いています。こちらのメルマガの発行も今月で 60 回を迎え、来年は 6 年目に入っていきます。

 　Paraphrase の開発は 2018 年の 2 月か 3 月に開始したと記憶しています（が、このあたりの記憶は曖昧です）。となると来年は開発 7 年目となります。Paraphrase の開発者である私自身は、リファレンス文書の作成が苦手というか、あまり積極的になれないようです。そのため、遅々として進まず、関連して Paraphrase の開発自体も滞っている状況です。

　Paraphrase を Paraphrase として成立させるワードは一体何であるのか ー この事に興味を持っています。そのためには、現在実装されているワードを、他のワードを用いて実装できるか否かを調べなければなりません。他のワードの組み合わせでは実装できないワード、それこそが Paraphrase を構成する元素のようなワードであると考えられます。

　このような作業に着手していきたいのですが、そのためには一区切りをつけなければならないと感じています。その一区切りを付けるための作業がワードリファレンスのコンパクト化であり、そのためにリファレンス文書を作成しなければ…という状況です（そして、これがなかなか進まないので、Paraphrase 自体の開発も停滞してしまっています）。

　来年はなんとかリファレンス文章の作成を終了させ、ワードの整理はもちろんのこと、Paraphrase 自体の開発の方も進めていければ、と思っています。

　と、それはさておき、今年も残すところあと僅かとなりました。それでは皆さん、よいお年を！

Twitter： https://x.com/paraphrase_lang
GitHub ： https://github.com/iigura/Paraphrase
〜データ取得ロジックが肥大化するの厳しいって〜Railsで複雑なロジックを整理するためのQueryオブジェクトパターンを実例付きで解説❗️

この記事は [ex-crowdworks Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ex-cw)の17日目の記事です。

# はじめに
今年、株式会社クラウドワークスを退職した@nisyuuです。プロテインは[savas](https://www.meiji.co.jp/sports/savas/)を飲むことが多いです。
エンジニアとしてクラウドワークステック（旧クラウドテック）というフリーランスと企業をマッチングするエージェントサービスを開発していました。

Webアプリケーションを開発する中でデータの取得ロジックが複雑化しメソッドが冗長になってしまうケースがよくあります。
このような問題を解決するために役立つのが「Queryオブジェクトパターン」です。

本記事では初心者向けにQueryオブジェクトパターンの概要とRailsにおける実装方法を解説します。

# Queryオブジェクトパターンとは

Queryオブジェクトパターンは、アプリケーション内で特定のデータを取得するロジックをオブジェクトに切り出すデザインパターンです。
データベースクエリの責務を分離し、コードの可読性や再利用性を高めることを目的としています。このパターンは、特に複雑なクエリや複数の条件が必要な場合に有用です。

## 基本的な考え方
- クエリを専用のクラスに分離する
- 名前付きメソッドでクエリを定義する
- コントローラやモデル内のロジックを簡潔に保つ

# Queryオブジェクトパターンのメリット

- **再利用性の向上**
  - 同じクエリを複数の場所で簡単に利用可能
- **テストが容易**
  - クエリロジックを単体テストできる
- **責務の分離**
  - コントローラやモデルからクエリロジックを切り離すことで、コードがシンプルに
- **可読性の向上**
  - クエリがオブジェクトにカプセル化され、意図が明確になる

# Queryオブジェクトパターンのデメリット

- **クラスの増加**
  - 小規模なアプリケーションではクラスが増えすぎる可能性
- **初期学習コスト**
  - パターンを理解するための時間が必要
- **過剰設計のリスク**
  - シンプルなクエリに適用すると、かえって複雑になることも

# RailsでのQueryオブジェクトパターン実装例

## 例: 投稿の検索機能
以下は、投稿を特定の条件でフィルタリングするQueryオブジェクトの例です。

### ステップ1: Queryオブジェクトの作成

`app/queries/posts_query.rb`:
```ruby
class PostsQuery
  def initialize(relation = Post.all)
    @relation = relation
  end

  def with_title(title)
    @relation = @relation.where("title LIKE ?", "%#{title}%") if title.present?
    self
  end

  def by_author(author_id)
    @relation = @relation.where(author_id: author_id) if author_id.present?
    self
  end

  def recent
    @relation = @relation.order(created_at: :desc)
    self
  end

  def result
    @relation
  end
end
```

### ステップ2: コントローラでの利用

`app/controllers/posts_controller.rb`:
```ruby
class PostsController < ApplicationController
  def index
    query = PostsQuery.new
                  .with_title(params[:title])
                  .by_author(params[:author_id])
                  .recent

    @posts = query.result
  end
end
```

### ステップ3: テスト

`spec/queries/posts_query_spec.rb`:
```ruby
require "rails_helper"

RSpec.describe PostsQuery, type: :model do
  let!(:post1) { create(:post, title: "First Post", author_id: 1, created_at: 1.day.ago) }
  let!(:post2) { create(:post, title: "Second Post", author_id: 2, created_at: 2.days.ago) }

  it "filters posts by title" do
    result = PostsQuery.new.with_title("First").result
    expect(result).to eq([post1])
  end

  it "filters posts by author" do
    result = PostsQuery.new.by_author(2).result
    expect(result).to eq([post2])
  end

  it "orders posts by recent" do
    result = PostsQuery.new.recent.result
    expect(result).to eq([post1, post2])
  end
end
```

# おわりに

Queryオブジェクトパターンは、複雑なクエリロジックを整理し、コードの再利用性やテストの容易性を高める強力な手法です。
ビジネス要件によっては、データの取得方法が複雑化することもありますが、Queryオブジェクトパターンを活用することでロジックを整理しながら実装が進められます。
【Java】見た目が一桁数字の String, char, int の型変換まとめ

```Java
    String s = "1";
    char c = '1';
    int i = 1;

    // String
    String s_c = Character.toString(c);
    String s_i = Integer.toString(i);

    // char
    char c_s = s.charAt(0);
    char c_i = (char)('0' + i); // '0'のユニコードに i を足す

    // int
    int i_s = Integer.parseInt(s);
    int i_c = (int)(c - '0'); // c から'0'のユニコードを引く

    System.out.println("String: " + s + s_c + s_i);
    System.out.println("char: " + c + c_s + c_i);
    System.out.println("int: " + i + i_s + i_c);
```

```
String: 111
char: 111
int: 111
```

## 解説

#### String への変換
ラッパークラス.toString(元変数);

#### int への変換
String → int
`Integer.parseInt( 元のString変数 );`

char → int
`(int)( 元のchar変数 - '0' );`
ユニコードの差を取ることで、数字の **char** を **int** に変換

#### char への変換
String → char
`元のString変数.charAt( 変換する桁をintで指定 );`
Stringクラスの **charAt()** メソッド で **char** に変換

int → char
`(char)( '0' + 元のint変数 )`
0 のユニコードを加算することで、元のint変数が表す数値のユニコードを算出
QA学園の話

今日は、遊びで書いている小説、「QA学園」の話です。
こんな学校、あったらどうでしょう？

（画像はイメージです）

## 設定
場所は未来の埼玉。
QAを専攻できる、新設から数年しかたっていない高校「ＱＡ学園」で
日々研鑽をしている生徒たちの物語。

広大な敷地を利用して、いろいろな施設があるこの学園で繰り広げられる
熱いQAバトルが・・・って、これ戦闘物なの？


## 人物紹介
### ユウタ
本作主人公。QA学園１年。
![_5a6f8bc4-97f0-41a8-b159-fae8cbc8bfc3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156898/169d2d35-b8d3-8a56-8fcb-69fd3dd92107.jpeg)
QA学園には、なりゆきで入学することになった。
性格は、流行りにのった冗談を言うことが多いが、意外と傷つきやすい。
斜めに構えたような、あきらめたような振る舞いが多かったが、
周りの熱意にほだされて、次第にQAに目覚めていく。
好きなテスト技法は、「いま、勉強中です！」とかいいながら、
モデリングが面白いと思い始めたところ。

### 美桜　（Mio）
QA学園１年。厳密には美桜は、QA学園の生徒ではない。
![_be4ffc6a-24fa-4776-9480-b26faed8c23f.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156898/704611d6-a25a-85f7-d634-857c93ec24f6.jpeg)
本作ヒロインながら、途中から登場する。
あまり近づきたくないタイプの天然。なにか近くにいると、
巻き込まれそうな感じのキケンがありそうなそんな・・・元気娘。
好きな食べ物は、アイス。だが甘辛でいうと、辛い物派。
好きなテスト技法は、プロパティベースドテスティング

### テラ

QA学園１年。
![_7635913c-0074-489f-b603-41fe3479ef0c.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156898/e2f0dc51-eb3e-d910-694a-c06ed142a987.jpeg)
両親がQA関係の教授。英才教育ともいえる環境にいたため、
メンバーの中ではバランスの良い知識体系を持っており、
とりあえず、わからないことがあったらテラに聞け、という雰囲気がある。

それが故の、本人にしかわからないような悩みを抱えている。

全国にQAクラスタの知人・友人がいる。
好きな食べ物を聞くと、はぐらかされる。
好きなテスト技法は、「まあ、一通り・・・。」

### アヤ

QA学園１年。
![_c164c2a8-c51f-452c-bab9-72a169f5b256.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156898/aa9a33b0-cf14-347d-3d24-df9079ef35ee.jpeg)

芸術的な感性を持つマニュアルテスター。
テスト感、ひらめきに関しては、右に出るものはいない。
美桜とはスキルゾーンが被らないため、お互いにリスペクトしている。
好きな食べ物は、スイーツ全般。
好きなテスト技法は、探索的テストとモデリング。

### キョウスケ
QA学園２年。
天才的な才能を崇められている、ユウタたちの１学年上の先輩。
生徒たちの、あこがれの存在。
とある理由から、卒業はユウタたちと同時になる。
たまに人には理解されないマニアぶりを発揮する。
（密かに）好きな食べ物は、そば。
好きなテスト技法は、「え、だってテストはテストでしょ」

![_65eb62ba-ce65-4fef-b771-925bc5f749b0.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156898/5d985a7c-e1bc-3f6a-98b1-510549e7c6a8.jpeg)


## 教授陣
個性豊かな教授陣が、生徒たちを温かい目で見守っています。


## 各学園

### 静岡　ディープラーニングアカデミー
#### 穴見光
AIテスト のエース
限界集落における、Quality of Life の研究をしている。
テラとは、何やらいわくがあるらしい。
好きな飲み物は、もちろんお茶。


![_9751e31c-e4fe-4b6e-b272-8bfff584fcc9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156898/8907e938-baac-6efb-19f2-f0f280ea92d5.jpeg)

### 大阪　グローバルネットワーク学院
謎のテラにそっくりな人物がいる。
大阪は手ごわい。ほんとにQA甲子園（仮）にこの髪飾りつけてきたらどうしよう。

![_c85b242c-d1ba-4117-ade5-cdc3b826e318.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156898/17788f3d-a509-e05f-1924-a46221257f00.jpeg)



#### その他の各学園
QA甲子園（仮）で戦うことになる、全国のQAクラスタ学園たち。


## ストーリー紹介
ストーリーは、今のところあらすじはこちらでつくって、ChatGPTにかいてもらってます。
いずれリファインしたいと思っていますが。

たまに、登場させられない人物などをつくって、内々にストーリーを楽しんでいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156898/24e40f39-df47-07e9-170d-39f2665397a7.png)


(こうみると、テラが主人公じゃないのが不思議なくらいエピソードがあるなぁ。
 でも主人公はユウタ。
 テラだと、はぐらかしながら、なんでも解決しちゃうから、お話にならないんだもん・・・。)

 少しずつ書いていくので、気長によろしくお願いします。
2025年にEmacsに入門したい(人|Vimユーザ)におすすめの基本設定

## 前置き

VimやNeoVimをお使いの皆さんの中には、Emacsに興味を持たれている方もいるでしょう。以下の図は、Emacsに興味を持った人がどうなるかという状態変化（？）を表したものです。この図を描いたのは私ですが、@takeokunnが[twitterで広めて](https://x.com/takeokunn/status/1724744190259835091)一部界隈で反響を呼びました。

![F--FH5OakAApQRq.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151145/a4188d59-9ef2-bde7-39fd-30e4aa4743e9.png)


https://x.com/okita_kamegoro/status/1724953163823018467

ユーザ数においては(Neo)Vimに負けているEmacsですが、クローンではない本物のorg-modeなど、他のエディタにはない魅力があるのも事実です。

https://x.com/goyangi_web/status/1811462840538268036

衆知の通り、Emacsは敷居が高いと言われています。この問題に対する解決策として、使いやすいEmacs設定のリポジトリを共有するEmacs distributionという方法がコミュニティでは取られてきました。また、Emacsについての解説としては[Mastering Emacs](https://www.masteringemacs.org/)が有名で、Ayanokoji Takesiさん、およびUSAMI Kenta（@tadsan）さんによる日本語訳もされています。

https://qiita.com/mhangyo/items/e5fe6f4761f2a845d216

どんなEmacs distributionがこれまで人気だったかは、たとえば[Perplexity](https://www.perplexity.ai/)に"what are some popular Emacs distributions?"と聞けば、以下のようなものが挙がってきます。どれも数年以上続いている、有名なプロジェクトです。


https://www.spacemacs.org/

https://github.com/doomemacs/doomemacs

https://github.com/bbatsov/prelude

Emacs distributionには、大きく分けて以下の二種類のものがあります。

- (1) IDE相当のパッケージ・設定が入っている高機能なもの。例: SpacemacsやDoom Emacs。
- (2) デフォルトEmacsの不自然さを解消する程度にとどめたminimalistic（better defaultsあるいはsane defaultsともいう）なもの。

後者(2)の場合、ユーザはEmacsの基本的な概念を習得しながら、各自に必要な設定をさらに追加していくことが求められます。使えるようになるまで少し期間を要しますが、フレームワーク（distribution）独自の体系に振り回されないので、長期的にはpay offすると言われています。

## 本題

最小のEmacs configurationとして最近話題になっているのが、Protesilaos Stavrou氏の[Emacs: a basic and capable configuration](https://protesilaos.com/codelog/2024-11-28-basic-emacs-configuration/)です。今年末または2025年にEmacsに入門したい人には、これがおすすめです。

https://protesilaos.com/codelog/2024-11-28-basic-emacs-configuration/

その他の選択肢も検討したい人は、以下のRedditを見るといいでしょう。

https://www.reddit.com/r/emacs/comments/1he7ghg/recommendations_of_emacs_config/

（追記）Vimユーザ向けのEmacs初期設定として[emacs-kick](https://github.com/LionyxML/emacs-kick)というのも出たようです。こちらも見てみるといいかもしれません。

https://github.com/LionyxML/emacs-kick
Rを学びたい Step18 不偏分散

## はじめに
Rを学びたいのStep18です。今回は不偏分散について学びます。

## 不偏分散とは何か？
**サンプルデータのばらつきを表す指標**である。全体のばらつきがわからない場合、サンプルデータの分散を流用して利用します。

```math:
\begin{align}
s^2 &= \frac{1}{n-1} \sum_{i=1}^n (x_i - \bar{x})^2 \\
& s^2 \text{ :不偏分散}, \\
& n \text{ : データの個数}, \\
& x_i \text{:各データの値}, \\
& \bar{x} \text{:サンプル平均}.

\end{align}

```

## 不偏分散を求める問題
あるクラスの5人のテストの点数は次の通りです。

| 生徒 | 点数 \( x \) |
|------|-------------|
| A    | 60          |
| B    | 70          |
| C    | 80          |
| D    | 90          |
| E    | 100         |

## 解答

1.	サンプル平均  \bar{x}  を計算する
平均は次の公式で計算します：

```math
\bar{x} = \frac{1}{n} \sum_{i=1}^n x_i
```
```math
\bar{x} = \frac{60 + 70 + 80 + 90 + 100}{5} = 80
```

2. 偏差の２乗を算出

| 生徒 | 点数 \( x \) | 偏差 \( x_i - \bar{x} \) | 偏差の二乗 \( (x_i - \bar{x})^2 \) |
|------|-------------|-------------------------|--------------------------------|
| A    | 60          | \( 60 - 80 = -20 \)     | \( (-20)^2 = 400 \)           |
| B    | 70          | \( 70 - 80 = -10 \)     | \( (-10)^2 = 100 \)           |
| C    | 80          | \( 80 - 80 = 0 \)       | \( 0^2 = 0 \)                 |
| D    | 90          | \( 90 - 80 = 10 \)      | \( 10^2 = 100 \)              |
| E    | 100         | \( 100 - 80 = 20 \)     | \( 20^2 = 400 \)              |

3. 偏差の２乗の総和を算出

```math
\sum_{i=1}^n (x_i - \bar{x})^2 = 400 + 100 + 0 + 100 + 400 = 1000
```

4. 不偏分散の公式に代入

```math:
s^2 = \frac{1}{n-1} \sum_{i=1}^n (x_i - \bar{x})^2
```

```math
s^2 = \frac{1}{5-1} \cdot 1000 = \frac{1}{4} \cdot 1000 = 250
```

よって、不偏分散は**250**である。

## Rで実装する

```R:
# 点数データをベクトルとして定義
scores <- c(60, 70, 80, 90, 100)

# サンプル平均を計算
mean_score <- mean(scores)

# 偏差を計算
deviations <- scores - mean_score

# 偏差の二乗を計算
squared_deviations <- deviations^2

# 偏差の二乗の合計
sum_squared_deviations <- sum(squared_deviations)

# 不偏分散を計算
n <- length(scores)  # サンプルサイズ
unbiased_variance <- sum_squared_deviations / (n - 1)

# 結果を表示
cat("サンプル平均:", mean_score, "\n")
cat("偏差の二乗の合計:", sum_squared_deviations, "\n")
cat("不偏分散:", unbiased_variance, "\n")
```

```shell:実行結果
~/develop/R/r_study/unbiased_deviations  (main)$ Rscript test.R               (base) 
サンプル平均: 80 
偏差の二乗の合計: 1000 
不偏分散: 250 
```
AWS CDK workshopでAWS Code commitの代わりにGitHubを使用する方法

## これは何？
AWS CDKワークショップの `高度なトピック (オプション)` にて、AWS CodeCommitを使用して、Pipelineを作成する項目がある。しかし、AWS CodeCommitはサービスの新規提供が終了し、新規の利用ができない状態。(2024年12月現在)
そのため、代わりにGitHubを使用して、Pipelineを構築する方法。


## TL;DR
- CodeCommit自体はコードRepositoryのため、GitHubにて代用が可能。GitHubのRepositoryを作成し、コードをpushする
- AWS developer toolsの[Connections](https://ap-northeast-1.console.aws.amazon.com/codesuite/settings/connections?region=ap-northeast-1) にて、GitHubとの接続を設定する
- 発行されるARNを利用して、Pipeline設定を行う

AWS CDK workshop自体は[こちら](https://catalog.us-east-1.prod.workshops.aws/workshops/10141411-0192-4021-afa8-2436f3c66bd8/ja-JP)

## 前提
workshopを進めていくと、 `高度なトピック (オプション) > CDK Pipelines > リポジトリの作成` にてエラーとなる。
原因として、AWS CodeCommitの新規利用が停止されているため。[公式Blog](https://aws.amazon.com/jp/blogs/devops/how-to-migrate-your-aws-codecommit-repository-to-another-git-provider/)

## 手順

#### GitHubとの接続設定
GitHubのRepositoryを作成し、コードをコミット、プッシュする。

AWSコンソールにLoginし、Developer Toolsの[Settings>Connections](https://ap-northeast-1.console.aws.amazon.com/codesuite/settings/connections?region=ap-northeast-1)に移動。
![スクリーンショット 2024-12-15 12.12.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386347/c9a9856f-4155-71d9-6276-9554501f5cee.png)

`Create Connections`から接続先: GitHub、任意の名前を入力し、接続を選択。
初めて利用する場合は、GitHubにリダイレクトされ、必要なAppをInstallすることになる。

次に接続設定を行う。`Install new App` を選択する。GitHubにリダイレクトし、接続するRepositoryを選択することになる。
![スクリーンショット 2024-12-15 12.15.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386347/9d58760f-2703-cad3-dd56-254afe064595.png)

接続が終わると、Connectionsが新規作成されている。

#### GitHubとの接続を利用した、Pipeline設定

workshopのコードにて、CodeCommitを作成するコードを削除し、Pipelineの

```diff_python
from aws_cdk import Stack
from aws_cdk import pipelines as pipelines
from constructs import Construct


class WorkshopPipelineStack(Stack):

    def __init__(self, scope: Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

-        # Creates a CodeCommit repository called 'WorkshopRepo'
-        repo = codecommit.Repository(
-            self, "WorkshopRepo", repository_name="WorkshopRepo"
-        )

        pipeline = pipelines.CodePipeline(
            self,
            "Pipeline",
            synth=pipelines.ShellStep(
                "Synth",
-               input=pipelines.CodePipelineSource.code_commit(repo, "main"),
+                input=pipelines.CodePipelineSource.connection(
+                    "{GitHub user名}/{GitHub Repository名}",
+                    "{branch名}",
+                    connection_arn="arn:aws:codeconnections:...(connectionsで作成されたARN)",
                ),
                commands=[
                    "npm install -g aws-cdk",
                    "pip install -r requirements.txt",
                    "cdk synth",
                ],
            ),
        )
```

チュートリアルどうりに以下のコマンドを実行。
```
git commit -am "MESSAGE" && git push
cdk deploy
```

CodePipelineを確認し、作成されていることを確認する。