OmniAICreator/Qiita-1.07M huggingface dataset:
Goでテーブル駆動のベンチマークをとる方法

公式に記載ありますが、まとめてみます。

[公式サイトのブログ記事](https://go.dev/blog/subtests#table-driven-benchmarks)

# ベンチマークのシナリオ

- 数値を文字列に変換する関数を作った。
- 標準パッケージが提供する同種の関数と、パフォーマンスの比較をしたい。
- テーブルとして用意したテストケースそれぞれについて比較をしたい。

# 書き方(ベンチマークの部分のみ)

```go
type testcase struct {
	name  string
	input []int
}

var testcases = []testcase{
	{ // このテストケース単位で、標準パッケージ関数との比較をしたい。
		name:  "plus",
		input: []int{1, 2, 3},
	},
	{ // このテストケース単位で、標準パッケージ関数との比較をしたい。
		name:  "minus",
		input: []int{-1, -2, -3},
	},
}

func BenchmarkStringer(b *testing.B) {
	std := strconv.Itoa
	myitoa := MyItoa

	for _, c := range testcases { // テストケース
		b.Run(c.name+"(std)", func(b *testing.B) { // 比較対象(サブベンチマーク)
			for i := 0; i < b.N; i++ {
				for _, n := range c.input {
					std(n)
				}
			}
		})
		b.Run(c.name+"(my)", func(b *testing.B) { // 比較対象(サブベンチマーク)
			for i := 0; i < b.N; i++ {
				for _, n := range c.input {
					myitoa(n)
				}
			}
		})
	}

	// ちなみに、普通の(?)サブベンチマークとして書くとこんな感じになる。
	// こちらの方法だとテーブル全体で比較する形になっている。

	b.Run("std-all", func(b *testing.B) {
		for _, c := range testcases { // テストケース
			for i := 0; i < b.N; i++ {
				for _, n := range c.input {
					std(n)
				}
			}
		}
	})

	b.Run("my-all", func(b *testing.B) {
		for _, c := range testcases { // テストケース
			for i := 0; i < b.N; i++ {
				for _, n := range c.input {
					myitoa(n)
				}
			}
		}
	})
}
```

## 結果の出力例

```
go test -bench .
```

全部で6つあるテスト結果のうち、前半4つがテーブル駆動の出力例です。

```
BenchmarkStringer/plus(std)-8           144737995                8.125 ns/op
BenchmarkStringer/plus(my)-8            54076951                20.84 ns/op
BenchmarkStringer/minus(std)-8          17072347                61.68 ns/op
BenchmarkStringer/minus(my)-8           26117388                40.63 ns/op

BenchmarkStringer/std-all-8             16578752                70.74 ns/op
BenchmarkStringer/my-all-8              19311915                64.46 ns/op
```

# 対象を絞り込む

`-bench xxx` でベンチマーク対象となるテストケースを絞り込むこともできます。

```
go test -bench /minus
```

```
BenchmarkStringer/minus(std)-8          17571860                67.47 ns/op
BenchmarkStringer/minus(my)-8           27569918                43.05 ns/op
```


<!--  vim: set et ft=markdown sts=4 sw=4 ts=4 tw=0 :  -->
SchemaSpyでサクッとER図やテーブル定義書を生成

# はじめに

既にDDLファイルはざっくりできてるから自動的にリバースしてくれるツールとかないかな～と思っていたら良いのがありました。

いくつか使用方法があるみたいですが、今回はDockerを使用したやり方を紹介します。

# 概要

- SchemaSpy とは
- 使い方

# SchemaSpy とは

SchemaSpy はDBの接続情報さえ持っていればそこからテーブル定義やER図といった設計書を様々なフォーマットで出力してくれるツールです。（超便利）

# 使い方

まずはスパイ対象のDBを適当に起動します。（既にあればスキップしてください）

SQL
![スクリーンショット 2024-08-15 224949.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/dac754b8-ddb7-fad8-3b6a-465741da0f90.png)

docker-compose.yml
![スクリーンショット 2024-08-15 224930.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/56a34ea6-8095-7d52-9be5-4b76305a0c7d.png)

起動したら、SchemaSpy用の作業フォルダの中で以下を行います。

1. 公式Dockerイメージの取得

下記のコマンドでSchemaSpyのイメージをプルしてきます。

```
docker pull schemaspy/schemaspy
```

プルしたら以下のコマンドを実行します。（パスや認証情報は各々で置き換えてください）

```
docker run -v "$PWD/schema:/output（出力先のパス）" --net="host" schemaspy/schemaspy:snapshot -t <DBの種類(mysql postgresqlなど)> -host <ホスト:ポート [例localhost:3306]> -db <スキーマ名> -u <ユーザ名> -p <パスワード> -connprops useSSL\\=false -s <スキーマ名>
```

今回はdocker-compose.ymlで設定したDBの情報をもとに以下のようにします。

```
docker run -v "$PWD/schema:/output" --net="host" schemaspy/schemaspy:snapshot -t mysql -host localhost:3306 -db schema_spy -u schema_spy -p schema_spy -connprops useSSL\\=false -s schema_spy
```

※上記を実行した際に`「java.io.IOException: Unable to create directory /output/tables」`というエラーが発生した場合、出力先ディレクトリの権限を変更する必要があります。

```
sudo mkdir -p schema
sudo chmod 777 schema
```

無事に実行が完了すると、schemaディレクトリ（厳密には`docker run -v "$PWD/"` で指定したフォルダ）にファイル群が出力されると思います。

この中にHTMLやJSファイルもあるのでブラウザで確認すると、

![スクリーンショット 2024-08-15 230924.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/ab974b8c-73e5-598d-1f6d-16d5baf6e7d8.png)

![スクリーンショット 2024-08-15 230958.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/e365e29b-8dca-7b85-e8cd-a5036d7c9dba.png)

![スクリーンショット 2024-08-15 231025.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/03601dc8-cf31-debb-450c-4ddb0f68078f.png)

こんな感じでテーブル定義情報を確認することができるようになります。

また、右上のボタンからExcel、CSV、PDF形式で出力することも可能です。

![スクリーンショット 2024-08-15 231151.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/e6273f94-d5d5-bc50-588e-c7d7812082f6.png)

![スクリーンショット 2024-08-15 231159.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/f596e569-815d-2363-a85b-134af9a2f079.png)

![スクリーンショット 2024-08-15 231209.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/9f860343-fa1b-1b85-740c-c5f4e1feb72c.png)

# 最後に

先に動作環境を作っちゃったけど設計書に書き出すのつら～って時におすすめです。
foobar2000にレーティング（☆0～☆5で評価のような）機能と再生回数機能の追加

# 概要

foobar2000をインストールしただけだと

* レーティング（☆0～☆5で評価のような）機能
* 再生回数機能

が無いので追加します。

# やり方

下記サイトへ行って…

https://www.foobar2000.org/components/view/foo_playcount

コンポーネントをダウンロード。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/3f922759-5f38-eec5-069d-0fa1f7db97b4.png)

ダウンロードされたファイルをダブルクリックで起動すると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/c295cc60-304d-a778-0152-0bf8ddbc7caa.png)

下記ダイアログ出てくるので『Yes』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/d2040430-36ad-0903-5a3c-3ae9eb11ae67.png)

下記のようにコンポーネントに機能が追加されれるので『OK』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/ff4737c6-5d73-095c-5fcd-d504d157cb55.png)

下記ダイアログも『OK』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/9dc73322-bde2-13a1-d063-71be4666c2f5.png)

# 例えばこんなふうに使えます

右クリック ⇒ 表示カラムの選択肢に『Rating』が追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/6266c016-9b36-df0f-638c-f11cf40f392c.png)

カラムが追加されると1曲単位でマウスポチポチで評価付けられます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/2492115e-e81a-65f7-4676-358c6d0f0934.png)

再生回数表示したい時は『Play Count』。

# 参考サイトさん

https://aresei-note.com/17878

# バージョン

Microsoft Windows [Version 10.0.22631.4037]
foobar2000 v2.1.5 [×64]
pytorchをimportしようとしたらOSErrorが出た

## 環境
OS :  windows10
python :  3.11.15
pytorch : 2.4.0
仮想環境 : venv

## 問題
yoloを使う際にpytorchが必要になり`pip install torch torchvision torchaudio`でtorchをインストールした。
その後、`import torch`で下記エラーが出てきた。

```
OSError: [WinError 126] fbgemm.dll" or one of its dependencies
```

## 解決方法
[この記事](https://github.com/ultralytics/ultralytics/issues/14893)を参考にして、torchらのバージョンを2.4.0から2.3.1にダウングレードしたらうまくいった。

```
# 一度アンインストール
pip uninstall torch torchvision torchaudio

# バージョンを指定してインストール
pip install torch==2.3.1 torchvision==0.18.1 torchaudio==2.3.1
```

## 原因（pytorchのバージョン）
`pytorch 2.4.0` は `python 3.12` でも使えると書いてあったが、自分の環境ではできなかった。（仮想環境を作り直してもダメ）

### 別の要因
PyTorch は、いくつかの依存関係として Microsoft Visual C++ ランタイムを必要とする。これがインストールされていないか、バージョンが古い場合、DLL のロードに失敗することがある。
supabaseからデータを取得しようとするとPGRST116のエラーがでる

# はじめに
supabaseのDBからデータを取得しようとした際にエラーが出たのでその対処法を書いていきます。

# 問題
supabaseのDBからデータを取得しようとした際にコンソールで以下のエラーが表示され、正常にデータが表示されない。

![スクリーンショット 2024-08-15 22.01.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3279945/6354f460-329f-2272-010a-766b4f4cd290.png)

GPTによるとPGRST116というのはクエリの結果が0行だった場合に返されるエラーコードで、指定された条件に一致するレコードが存在しないことを示しているそうです。
また実装コードは以下のようになっており、URLパラメータで指定したidを引数に受け取りそのidを持つデータの情報を返すような処理になっています。
```js
/*---supabasefunctions.ts---*/
export const getUserData = async (id:string) => {
    const { data } = await supabase
        .from('users')
        .select('*')
        .eq('id', id)
        .single()
    return data;
};
```
# 原因と解決策
supabaseにデータを入れる際最後に改行を入れてしまっていたのが原因でした。今回の場合デモのidであるsample-idを入力した後に改行を入れてしまっていたためその改行を消すと正常にデータが取得されました。
![スクリーンショット 2024-08-15 22.21.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3279945/279eabc7-e785-5200-418f-9310a58862ea.png)

# おわりに
改行で動かなくなることもあるんですね...今後はプログラム以外の箇所でも原因があることを視野にデバッグしていきます。
オリジナルアプリの説明

こんにちは。看護師→プログラミング初学者の我那覇です。
今更になりますが現在どのようなアプリを作ろうとしているかを皆さんに共有しようと思います。


## Wantsの説明
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/7d15a7f4-0404-50bd-914e-f988abf83667.png)


### 1. (ざっくりと)何ができるのか

"Wants"は、ユーザーが希望する商品をリクエストし、それに応じて出品者が商品を出品できるウェブアプリケーションです。リクエストには詳細や希望条件を含めることができ、他のユーザーと情報を共有可能です。

### 2. 誰のどんな課題を解決するのか
このアプリは、特定の商品が見つからない、または市場に存在しないという課題を解決します。ユーザーは、ニーズを投稿することで他のユーザーやメーカーに伝えられ、転売対策にもなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/5fffa51e-7731-6010-bc51-3c653427deb6.png)


### 3. こだわろうと思っている点、苦労しそうな点はどこか
**こだわりたい点:**
- リクエスト投稿の簡単さを追求し、使いやすいUIを実現する。
- カテゴリーやタグ機能を実装し、リクエストが見つけやすいようにする。

**苦労しそうな点:**
- リクエストしたユーザーと出品希望者がやり取りできるコメント機能の追加が難点です。
![スクリーンショット 2024-08-15 22.36.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/14c7f53d-8d3e-7855-07ff-b8dd1d88457a.png)

### 4. 実装後にアップデートしていきたい機能は何か
- **通知機能:** 関心のあるリクエストや新しい投稿に対する通知を追加したい。
- **データ分析とレポート機能:** 投稿されたリクエストのトレンドや人気のある商品カテゴリーを分析し、ユーザーにフィードバックを提供する機能を検討しています。

"Wants"は、ニーズにマッチした商品を迅速に提供し、購入者が商品の条件を決定できるプラットフォームです。今後、さらに多くのユーザーに便利で魅力的なアプリケーションに進化させていきたいと考えています。
【Spring Security】認証トークンって何？

## はじめに
SpringSecurityの認証トークンについて、トークンってなに？何ができるの？みたいなところ解決していければと思い記事を書いていきます。
間違いなどございましたらご指摘いただけますと幸いです！

## （まずSpring Securityとは）
認証や認可、およびその他多くのセキュリティ対策を簡易に実装できるSpringのフレームワークです。
認証：ユーザーが誰であるかを確認する（ログインのこと）
認可：認証された（ログインした）ユーザーが特定のページにアクセスできるかを決定する方法（権限があるかないか）

## よく聞くトークンってなんなの？
トークンは、認証や認可のプロセスにおいてユーザーの認証情報を安全にやりとりするための文字列です。
このトークンはユーザーは見れないものになっています。
ちなみに、今回は認証トークンについての説明ですがトークンにはさまざまな種類があります。
下記にどんなトークンがあるのか書いておきます。
```
1. 認証トークン
- JWT(JSON Web Token)
ユーザー認証に使用されるトークンの一種で、セッションの代わりに使用されることが多いです
サーバーが署名したトークンで、ユーザーがログイン後受け取りそれを用いて認証されたリクエストを行います
2. セッショントークン
ユーザーがウェブサイトやサービスにログインした際に発行されるトークンでセッションを維持するために使用されます。クッキーとしてブラウザに保存されます
3. APIトークン
APIへのアクセスを制御するために使用されるトークンです
開発者がAPIを利用する際にリクエストに含めることで認証や権限の確認が行われます
4. CSRFトークン
CSRF攻撃を防ぐために使用されるトークンで、フォーム送信時に一緒に送信され、サーバー側で検証されます
```
他にもありますが、トークンにはこのように色々あるということを知っていただければOKです。
セッショントークンと認証トークンは同じように見えますが、違いがありますので簡単に説明しておきます。
違いとして、認証トークンはサーバーがトークンの状態を保持することはないのですが、セッショントークンはサーバーがセッションの状態を保持するなどの違いがあります。



## 認証トークンのイメージ図
下の図のような感じでトークンは発行されて保持されます。

![スクリーンショット 2024-08-07 214108.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3669426/ea8ebe1c-177c-41df-3f19-d80cee2fbf44.png)
**【流れ】**
クライアントが名前とパスワードを入力して送信
↓
受け取ったサーバーはトークンを発行
↓
クライアントにトークンを返す
↓
クライアントはcookieなどでトークンを保持

といった感じです。
セッションでもたせてもよいので、タブが開いている場合はトークンが有効になるような処理をかくことで、ユーザーがページにアクセスする権限があるのかを判断することができます。
つまり、トークンが有効である限り、クライアントからのリクエストは権限が付与されてあれば通るということです。

## まとめ
簡単によく聞くトークンって何？ということをまとめてみました。
まだどのように処理書くの？などは理解できていないためさらに学習を進めていければと思います。
The next big coding trends for 2024

![coding trends.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862306/d8f879d6-c65a-3102-9d7e-8fe76deed629.jpeg)


Alright, tech enthusiasts and aspiring coders, listen up! 2024 is shaping up to be a wild ride in the world of programming. Let's dive into the hottest coding trends that are about to take over and revolutionize the tech scene.

First up, artificial intelligence is still the name of the game, and it's not slowing down anytime soon. AI integration in coding is going to be huge in 2024. We're talking about AI assistants that can help debug your code, automate repetitive tasks, and even improve overall code quality [citation:8]. So if you're not already buddying up with AI tools like ChatGPT for coding help, it's time to get on board!

But hold up, it's not just about AI doing the heavy lifting. Low-code and no-code platforms are on the rise, making it easier for anyone to build apps and websites without deep programming knowledge [citation:8]. This trend is opening doors for more people to join the tech world, but it also means professional coders need to step up their game to stay ahead.

Speaking of staying ahead, cybersecurity is more crucial than ever. In 2024, the security-first approach is going to be a top priority throughout the entire development cycle [citation:8]. So if you're looking to specialize, focusing on secure coding practices could be your ticket to success.

Now, let's talk about where you'll be doing all this coding. Remote work is here to stay, fam. The pandemic changed the game, and now more companies are embracing the work-from-home life. This means you could be coding in your PJs while sipping on your favorite latte – just make sure your Wi-Fi is solid!

But it's not all about convenience. The coding world is getting eco-friendly too. Sustainable software development is gaining traction, with a focus on optimizing code to minimize carbon footprints and reduce resource consumption. It's like being a tech superhero for the planet!

And for all you crypto enthusiasts out there, blockchain applications are expanding beyond just finance. From supply chain management to identity verification, blockchain is making waves across various industries. So if you're looking to ride the next big wave, brushing up on your blockchain skills might be the move.

Lastly, let's not forget about the explosion of online learning. Thanks to the pandemic, online courses have become the go-to for skill development, especially among us Gen Z folks. Whether you're into coding bootcamps or self-paced tutorials, there's never been a better time to level up your programming skills from the comfort of your couch.

So there you have it – the coding trends that are about to shake things up in 2024. Whether you're a seasoned developer or just starting out, staying on top of these trends could be your key to crushing it in the tech world. Now go forth and code, my friends! The future is waiting, and it's looking pretty lit. 🚀💻
Python  `typing.Callable`を使って関数の型を定義する

## はじめに

Pythonは動的型付け言語ですが、型ヒントを使用することで、コードの可読性を向上させ、潜在的なバグを早期に発見することができます。特に関数を扱う際、`typing.Callable`を使用して関数の型を定義することは非常に有用です。この記事では、`typing.Callable`の基本的な使い方から、より複雑なケースまでを解説します。

## `typing.Callable`とは

`typing.Callable`は、関数の型を表現するためのジェネリック型です。これを使用することで、関数の引数の型と戻り値の型を指定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/5a3d3922-f931-6e02-372d-17c692e9c1c2.png)


## 基本的な使い方

最も単純な形式は以下のとおりです：

```python
from typing import Callable

def apply_function(func: Callable[[int], int], value: int) -> int:
    return func(value)

def double(x: int) -> int:
    return x * 2

result = apply_function(double, 5)
print(result)  # 出力: 10
```

出力:
```
10
```

この例では、`Callable[[int], int]`は「整数を1つ受け取り、整数を返す関数」を表しています。

## 複数の引数を持つ関数

複数の引数を持つ関数の型も簡単に定義できます：

```python
from typing import Callable

def operate(func: Callable[[int, int], int], a: int, b: int) -> int:
    return func(a, b)

def add(x: int, y: int) -> int:
    return x + y

result = operate(add, 3, 4)
print(result)  # 出力: 7
```

出力:
```
7
```

ここでは、`Callable[[int, int], int]`が「2つの整数を受け取り、整数を返す関数」を表しています。

## 任意の数の引数を持つ関数

`*args`や`**kwargs`を使用する関数の型も定義できます：

```python
from typing import Callable, Any

def execute(func: Callable[..., int], *args: Any) -> int:
    return func(*args)

def sum_all(*numbers: int) -> int:
    return sum(numbers)

result = execute(sum_all, 1, 2, 3, 4, 5)
print(result)  # 出力: 15
```

出力:
```
15
```

`Callable[..., int]`は「任意の引数を受け取り、整数を返す関数」を表します。

## ジェネリック型との組み合わせ

`TypeVar`を使用して、より柔軟な型定義も可能です：

```python
from typing import Callable, TypeVar, List

T = TypeVar('T')

def map_list(func: Callable[[T], T], items: List[T]) -> List[T]:
    return [func(item) for item in items]

def square(x: int) -> int:
    return x ** 2

numbers = [1, 2, 3, 4, 5]
result = map_list(square, numbers)
print(result)  # 出力: [1, 4, 9, 16, 25]
```

出力:
```
[1, 4, 9, 16, 25]
```

この例では、`Callable[[T], T]`が「任意の型Tを受け取り、同じ型Tを返す関数」を表しています。

## まとめ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/a96489ae-7e36-b673-bbb8-bc6f9d90834c.png)

`typing.Callable`を使用することで、関数の型を明確に定義し、コードの品質と可読性を向上させることができます。これは特に大規模なプロジェクトや、複数の開発者が関わるプロジェクトで非常に有用です。

Pythonの型ヒントは、コードの実行時には無視されますが、静的型チェッカー（例：mypy）を使用することで、潜在的なバグを早期に発見することができます。

`typing.Callable`を適切に使用することで、より堅牢で保守性の高いPythonコードを書くことができるでしょう。

## 公式ドキュメント参照

より詳細な情報や高度な使用方法については、Pythonの公式ドキュメントを参照することをお勧めします：

- [typing — 型ヒントのサポート](https://docs.python.org/ja/3/library/typing.html)
- [PEP 484 -- Type Hints](https://www.python.org/dev/peps/pep-0484/)
- [typing.Callable](https://docs.python.org/ja/3/library/typing.html#typing.Callable)

これらの公式ドキュメントでは、`typing`モジュールの詳細な使用方法や、型ヒントシステムの背景にある設計思想について説明されています。特に、`Callable`に関する高度な使用方法や、他の型ヒント機能との組み合わせ方などについて、より深く理解することができます。
AWS SAA合格体験記(+AWS summit Japan参加レポ)

# はじめに
AWS SAAに合格した合格体験記
+
AWS summit Japan参加レポ（おまけ）
***
# AWS SAA合格体験記
***
# 学習前の状況
AWSの知識
→2年前にAWS CLPを勉強したきり
クラウド環境（AWSではない）の構築は業務で少し触った
***
# 使った教材
- ping-t
- udemyのハンズオン講座
- AWS summit Japanに行った
***
# 受けた理由
- 2年前に取ったCLPの有効期限が切れそうだった
- Linuxの勉強ばっかで飽きたので気分転換
- ~~会社からの報奨金目当て~~
***
# やったこと
1. ping-tの【試験レベル】以外の問題を1周
1. udemy模擬試験が全く解けず撃沈
1. ping-tの【試験レベル】を重点的に学習

***
# 結果
受験日：2024/07/06
スコア：777 ~~縁起がいい~~
***
# 感想
- 業務都合で一時中断を挟みつつ1.5か月ほどで合格できた
- udemy模擬試験は難しすぎる
- ping-tの試験レベルが解ければ受かる
    - DDoS？AWS Shield！　並列実行？SQS！　リアルタイム？Global Accelerator！みたいな感覚が身に着けばOK
***
# [AWS summit Japan](https://aws.amazon.com/jp/summits/japan/)参加レポ
***
# 参加動機
QuizKnock登壇！？行かなきゃ…
***
# 見たもの
- AWS DeepRacer Japan Championship Cup
- QuizKnockの講演
- 初級者向けセッション

***
# 感想
- 初心者向けセッションはSAA勉強中レベルでも全然理解できる内容だった
    - 全然当日飛び入りで空席に潜り込めた
    - 実際AWSってこういう使われ方するんだ～がわかるので勉強に大いに役立った
- 生QuizKnock初めて見られて嬉しかった
- 名前と社名入りネームプレート渡されてびびった
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616564/3e3c3174-6356-0e52-64f5-f119c4b679ee.png)

***
# おわりに
とっくに書いて投稿したものだと思っていた記事が下書きから発掘されたのでそっと投稿…気を付けよう…
【丸め誤差】なぜ0.1 + 0.2 ≠ 0.3となるのか？を解説する

# はじめに

前々から「`0.1+0.2=0.3000.....0004`と0.3にならないのは何でだろう？？」といった疑問を持っていましたものの、当時は深掘りをしていませんでした。下記が問題のソースコードです。

```js
console.log(0.1+0.2); // 0.30000000000000004
```

最近、Javascriptで勉強を始める中で、その理由について解説しており腑に落ちたので、本記事にて共有します。

# 0.1 + 0.2 ≠ 0.3となる理由

### 実は0.1や0.2は...

実は0.1や0.2もコンピュータの世界では、**「0.1」や「0.2」と表現されないのです**。
その理由として、コンピュータ上では2進数で表記されることより、0.1や0.2を正確に表すことができなくなっています。実際に計算される2進数表記(`toString(進数)`)、正確な数値(`toFixed(桁数)`)をそれぞれ表現をすると、下記のようになります。

```js
/* 0.1 */
// 2進数表記：0.0001100110011001100110011001100110011001100110011001101
console.log((0.1).toString(2));
// 正確な数値：0.1000000000000000055511151231257827021181583404541015625
console.log((0.1).toFixed(100));

/* 0.2 */
// 2進数表記：0.001100110011001100110011001100110011001100110011001101
console.log((0.2).toString(2));
// 正確な数値：0.200000000000000011102230246251565404236316680908203125
console.log((0.2).toFixed(100));
```

**注)** 上記の記述の場合、正確な数値にて本来は100桁分表示するので0が続くのですが、今回は説明の都合上割愛しています。

ソースコードより、2進数表記はいずれも`00110011...`と循環しており、最後の桁で`...1101`と切り上げていることが確認できます。この切り上げの影響により、0.1や0.2を正確に割り出すと微小な丸め誤差が発生するのです。

### 0.1 + 0.2 ≠ 0.3となる正体は何なのか？

こちらについても、上記で説明したような **「切り上げ」** の影響を受けた結果として、`0.1 + 0.2 ≠ 0.3`となります。実際に、`0.1+0.2`と`0.3`について2進数表記で比較すると下記のようになります(分かりやすいように、出力結果の項目で比較します)。

```js
// 入力
console.log((0.1+0.2).toString(2));
console.log((0.3).toString(2));

// 出力結果
// 0.010011001100110011001100110011001100110011001100110100 (0.1+0.2)
// 0.010011001100110011001100110011001100110011001100110011 (0.3)
```

上記のように、2進数で比較した場合に誤差が発生することについて確認できます。
この切り上げられた数値同士が加算されることによって、最初に掲げた問題となる下記のような出力結果が生まれます。

```js
console.log(0.1+0.2); // 0.30000000000000004
```

# 最後に

`0.1 + 0.2 ≠ 0.3`になる理由として、

* 2進数表記で表すと切り上げが発生すること
* 切り上げた数値同士を加算することで、目に見える誤差が発生すること

がありました。

皆さんのお役に立てれば幸いです！
プログラミング言語・ライブラリ・フレームワークのバージョンアップ手法

## はじめに

プログラミング言語とフレームワークをバージョンアップする機会があったため、バージョンアップの方法やその注意点などを解説していきます。
今回はPHPとLaravelを例に挙げて解説していきます。

## セマンティックバージョニングとは

各プログラミング言語やライブラリ、フレームワークにはそれぞれバージョンが定められており、コードを更新するごとにそのバージョンが変わっていきます。

プログラミング言語やライブラリで利用されるバージョニング手法はセマンティックバージョニングと呼ばれ、3つのセクションに区切られて表示されます。左にある数字ほど大規模な変更が含まれ、それぞれ以下のような意味があります。

![versions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1087368/3df60b87-b2dc-678b-efdf-b94b31bf08c2.png)

- メジャーバージョン：互換性のない変更の場合にバージョンを上げる
- マイナーバージョン：後方互換性がある機能を含む変更の場合にバージョンを上げる
- パッチバージョン：後方互換性があるバグ修正などの場合にバージョンを上げる

https://semver.org/lang/ja/

## セキュリティアップデート

PHPの場合、`composer audit`を利用することで、現在利用しているバージョンに脆弱性が含まれるかチェックすることができます。
ライブラリ等依存しているものに脆弱性が混入していると、自分がどれだけセキュリティを意識してコードを書いたとしても、その脆弱性が原因で障害が起こってしまう可能性があるため、セキュリティアップデートは放置せずにアップデートを行うのが望ましいです。

https://getcomposer.org/doc/03-cli.md#audit

## バージョンの指定方法

以下の方法でバージョンの指定を行うことができます。

```sql
8.3.1: : 指定したバージョンがインストールされる
~8.3.1: メジャーバージョン(8)は固定で、マイナーバージョン(3)とパッチバージョン(1)が最新のバージョンがインストールされる
~8.3: メジャーバージョン(8)は固定で、マイナーバージョン(3)とパッチバージョン(1)が最新のバージョンがインストールされる
^8.3.1: メジャーバージョン(8)とマイナーバージョン(3)は固定で、パッチバージョン(1)が最新のバージョンがインストールされる
^8.3: メジャーバージョン(8)は固定で、マイナーバージョン(3)とパッチバージョン(1)が最新のバージョンがインストールされる
```

https://getcomposer.org/doc/articles/versions.md#next-significant-release-operators

## バージョンアップ方法

基本的にメジャーな言語であれば、アップグレードガイド（言語によって呼び方は違うと思いますが、本記事ではアップグレードガイドで統一）があると思うので、そちらを参照してバージョンアップを行っていきます。

その言語やライブラリのバージョンに対応している移行ツールがあれば、それを利用するのもひとつの手です。ちなみにPHP, Laravelには[Rector](https://github.com/rectorphp/rector)という移行ツールがあります。

基本的には以下の手順でバージョンアップを行なっていきます。
1. どのバージョンまでバージョンを上げるか決める
2. アップグレードガイドを確認する
3. バージョンアップにあたって変更する必要がある箇所を修正する
    - この時にテストコードも一緒に修正するのを忘れないように
4. 依存ライブラリをバージョンアップ、修正する
5. 正常にサービスが動作するか確認

### 例1 PHPのバージョンアップ
PHP8.2.xから8.3.xにバージョンアップをしていきます。
1. PHPを8.3.xにアップデート
2. PHPでは[こちら](https://www.php.net/manual/ja/migration83.php)に変更内容が記載されているため、そこから変更内容を確認する
    - 新たに追加される機能は変更しなくてもひとまずは問題ないため、[下位互換性のない変更点](https://www.php.net/manual/ja/migration83.incompatible.php)と[PHP8.3.xで推奨されなくなる機能](https://www.php.net/manual/ja/migration83.deprecated.php)を確認する
3. この2ページに含まれているコードが作成しているプロダクトに含まれる場合、該当箇所を修正する
4. 実際に動作させ、問題ないかを確認する

### 例2 Laravelのバージョンアップ

Laravel10から11にバージョンアップをしていきます。
1. Laravelを11.x.xにアップデート
2. Laravel では[こちら](https://laravel.com/docs/11.x/upgrade)に変更内容が記載されているため、そこから変更内容を確認する（日本語は[こちら](https://readouble.com/laravel/11.x/ja/upgrade.html)）
    - Laravelのアップグレードガイドはとてもわかりやすく書かれているため、一通り読み進めればどれをどのように変更すれば良いかがすぐにわかります
3. 変更が必要な箇所を修正する
4. 実際に動作させ、問題ないかを確認する

今回はプログラムの動作に影響がある箇所のみを確認していますが、アップグレードガイドの他の箇所もパフォーマンスが向上したり、コードが簡潔に書けるなど読んでおいて損はないため、一通り読んでみることをお勧めします。

## 注意事項

- 破壊的変更がある箇所はバージョンアップによって、アプリケーションが動かなくなる可能性があるので要チェック
- まとめてバージョンを上げる際は、その範囲のガイドを全て見る必要がある
- ライブラリを利用している場合、バージョンアップによって別のライブラリが動作しなくなる可能性がある

## おわりに

初めてバージョンアップ作業を行ったのですが、バージョンアップ作業を行うことにより追加された新機能やコードの内部などを知ることができたため非常に勉強になりました。
ツール等は利用せず手作業で行ったのですが、次行う際はツールを利用したバージョンアップも試してみたいと思います。

## 参考

https://dev.classmethod.jp/articles/versoning-with-pictures/

https://speakerdeck.com/blue_goheimochi/phpcon2022
ダブリング【競技プログラミング】

ニバイ、ニバ～イ

# はじめに
- 先日、累乗計算(a^n)を効率的に計算できる[繰り返し二乗法](https://qiita.com/kei_tnk/items/a622eec4e7a9d0c47aca)を紹介した。
- この手法では、計算量を大きく削減できる。具体的には、シンプルな計算方法での計算量O(n) ⇒ 繰り返し二乗法での計算量O(log n) となる。
- 今回は、同じような考え方で計算量を削減するダブリングを紹介したいと思う。
- なお、コードはswiftで書きます。

# ダブリングとは
- まず、要素数nの配列を考え、配列には0...(n-1)の範囲の数値が入っているものとします。n=5なら、[3,4,3,1,0]が例となります。
- このような配列[3,4,3,1,0]に対して、例えば、スタート地点をi=2とし、その要素3を次の地点、さらにi=3の要素1を次の地点、i=1の要素4を次の地点、.....と繰り返していくとき、スタート地点からk番目の地点を求める計算量はO(k)となります。
- 上記のような、シンプルな解法に対して、あらかじめ、地点iから、$2^0,2^1,2^2,2^3,..$番目の地点を記憶しておけば、ショートカットできるため、計算量を削減できます。この考え方により、計算量を削減する手法をダブリングと呼びます。
- よって、まず、事前準備として全ての地点iについて、$2^0,2^1,2^2,2^3,..$番目の地点を記憶する必要があります。

# ダブリングのコード化
- 上記で説明したダブリングをコードにしようと思うけど、例題として、[AtCoderのABC167のd問題](https://atcoder.jp/contests/abc167/tasks/abc167_d)を利用しようと思う。
- 入力例は以下の通り
```
6 727202214173249351 // n=6、k=727202214173249351
6 5 2 5 3 2 // 最小値を1とする前提だから、取り込むときは-1として配列のindexにあわせ、あとで出力するとき+1する。
```
- これを解くコードは、以下の感じ。なお、地点iから、$2^j$先の地点を配列mem[j][i]に記憶することとする。
```swift
import Foundation

let (n,k) = [readLine()!.split(separator:" ").map{Int($0)!}].map{($0[0],$0[1])}[0]
let vs = readLine()!.split(separator:" ").map{Int($0)! - 1} //配列のindexに合わせるため-1している。

let lgk = Int(log(Float(k)) / log(Float(2))) + 1 //kの対数は2を底としたときlg(k)で表記されるため

var mem = [[Int]](repeating:[Int](repeating:-1,count:n),count:lgk) // 初期化。どうせ全部塗り替えられるので、0でも1でも何でも良いけど、答えに絶対ならない数字にした方が気持ちよい。オプショナル値にしてnilにするのも良いけど、コードが複雑になるのでやめた。

// 一周目
for i in 0..<n {
    mem[0][i] = vs[i]
}

// 二周目以降
for j in 1..<lgk {
    for i in 0..<n {
        mem[j][i] = mem[ j-1 ][ mem[j-1][i] ] // -- ※この式の意味は下記の解説を参照
    }
}

var ans = 0 // 開始位置は0
var j = 0
var temp = k
while temp > 0 {
    if temp & 1 == 1 {ans = mem[j][ans]}
    temp >>= 1
    j += 1
}

print(ans + 1) // 出力用に+1とした。
```
- 上記コードのキモは、※マークの式となる。※以外の部分は、前回解説した[繰り返し二乗法](https://qiita.com/kei_tnk/items/a622eec4e7a9d0c47aca)を見てほしい。
    - ※式の左辺は、地点iから$2^j$先地点を意味する
    - ※式の右辺は、地点iから$2^{(j-1)}$先地点のさらに$2^{(j-1)}$先という意味だが、$2^{(j-1)}$先の$2^{(j-1)}$先とはつまり、$2×2^{(j-1)} = 2^j$先と言うこと。
    - よって、左辺と右辺は等しいことが分かる。このとき、左辺の「j」に対して、右辺は「j-1」のため、配列memのjについての漸化式となっている。
- 上記コードを実行すると、出力は2となり、ABC167のd問題での回答例と一致した。
- 上記コードをABC167のd問題に提出すると、200ms程度でACとなった。

# 終わりに
- うーむ。ABC167のd問題以外に、どんな場面で役立つのかいまいち分かってないけど、ダブリングはアルゴリズム的には基礎知識っぽいので、そのうち、利用場面も出てくるでしょう。
- そのときは、また、ここにリンクを張って、お知らせするね。
Go言語（golang）でGoogle Cloud Storageを操作する際の共通部分をメソッド化する

### 概要
Go言語でGCS（Google Cloud Storage ）のデータを操作する際に、ファイルのアップロード、取得、削除といった処理で共通部分があります。
共通部分をメソッド化して使いまわしたかったのですが、公式のドキュメントだとdeferを使っており、どのようにメソッドにしたらよいかわからなかったので、自分なりに調べて考えた結果を残しておきます。

---

### やりたいこと
GCPに対する操作について公式のドキュメントをみてみると、以下の部分は共通化できそうです...

https://cloud.google.com/storage/docs/uploading-objects?hl=ja

https://cloud.google.com/storage/docs/deleting-objects?hl=ja
``` go
// bucket := "bucket-name"
// object := "object-name"
ctx := context.Background()
client, err := storage.NewClient(ctx)
if err != nil {
        return fmt.Errorf("storage.NewClient: %w", err)
}
defer client.Close()

ctx, cancel := context.WithTimeout(ctx, time.Second*50)
defer cancel()

o := client.Bucket(bucket).Object(object)
```
今回作成しているアプリでは同じバケットを使っているので、バケットの取得まで共通化して、各々の関数でオブジェクトの取得からやってもらうようにしたいです！

---

### 問題点
そのままメソッド化しても、`defer`はメソッドが`GetCloudStorageBucket`が終わるタイミングで実行されてしまうので、呼び出し元では戻り値のバケットは使えません...
※contextは呼び出し元のものをポインターで渡して使うように変更しています。
``` go
func GetCloudStorageBucket(ctx *context.Context) (*storage.BucketHandle, error) {
    // bucket := "bucket-name"
    // object := "object-name"
    client, err := storage.NewClient(*ctx)
    if err != nil {
            return nil, fmt.Errorf("storage.NewClient: %w", err)
    }
    defer client.Close()
    
	var cancel context.CancelFunc
	*ctx, cancel = context.WithTimeout(*ctx, time.Second*50)
    defer cancel()

    bucket := client.Bucket(bucketName)
    if err != nil {
        return nil, fmt.Errorf("client.Bucket: %w", err)
    }
    return bucket, nil
}
```

なんとかしてこのdeferを上手い具合に呼び出し元で実行させるようにしたい...

---

### 結論 ： 戻り値にdeferで実行したい関数を渡してあげる
いくつか調べていると、自分と似たような質問をされている方がいらっしゃいました。

https://stackoverflow.com/questions/21634192/golang-defer-to-act-on-caller-outer-function

回答者の方はdeferで実行したい関数を変数に詰めていて、これならできそうだったのでやってみました！

``` go
func GetCloudStorageBucket(ctx *context.Context) (*storage.BucketHandle, func(), error) {
    // bucket := "bucket-name"
    // object := "object-name"
    client, err := storage.NewClient(*ctx)
    if err != nil {
            return nil, func(){}, fmt.Errorf("storage.NewClient: %w", err)
    }
    defer client.Close()
    
	var cancel context.CancelFunc
	*ctx, cancel = context.WithTimeout(*ctx, time.Second*50)
    defer cancel()

    deferFunc := func() {
		client.Close()
		cancel()
	}

    bucket := client.Bucket(bucketName)
    if err != nil {
        return nil, func(){}, fmt.Errorf("client.Bucket: %w", err)
    }
    return bucket, deferFunc, nil
```

呼び出しもと
``` go
ctx := context.Background()
bucket, clientDeferFunc, err := GetCloudStorageBucket(&ctx)
if err != nil {
    return err
}
defer clientDeferFunc()

objectName := "object-name"
obj := bucket.Object(objectName)
```

問題なくGCSに対して操作することができました！🙌

---

### まとめ
Go言語に触れたばかりで全然慣れていないので、初歩的な部分で悩んでしまいました🥲
ですがこれを機にGoについて少し理解できた気がします！

もしもっとよい方法などあれば教えていただけますと大変嬉しいです！🥳


---
### 参考
https://zenn.dev/rescuenow/articles/bc95e45e466083
CDP経由でChromeのタブを切り替える

以下ソース

```signage.rb
require 'chrome_remote'

# Chromeリモートデバッグプロトコルに接続
client = ChromeRemote.client

# 開かれているタブを取得し、ページタイプのタブのみをフィルタリング
targets = client.send_cmd('Target.getTargets')['targetInfos']
page_targets = targets.select { |target| target['type'] == 'page' }

# タブを順に切り替える
index = page_targets.size - 1
loop do
  if index < 0
    index = page_targets.size - 1 # 最初のタブに戻る
  end

  # タブをアクティブにする
  target_id = page_targets[index]['targetId']
  client.send_cmd('Target.activateTarget', targetId: target_id)

  # 現在のタブのURLを出力
  url = page_targets[index]['url']
  puts "Switched to tab: #{url}"

  index -= 1
  sleep 1 # 1秒ごとに切り替え
end
```

### 用途

デジタルサイネージ的にChromeを使いたいときに一定時間で切り替える。
chrome_remote経由なので自由に操作はできる。リロードしてみたり、スクロールしてみたり。
プログラミングノートの書き方と目的

私は新しい言語や技術に出会ったときはプログラミングノートを書くことを決めています。今回はその書き方や目的、コツなどを自分なりにまとめてみました。

# きっかけ
牛尾剛さんの著書「世界一流エンジニアの思考法」や雑食系エンジニアの勝又健太さんのyoutubeなどで新しい言語などを学ぶ際に簡単なプログラミングノートを書くようにしていると言われていたので真似をすることにしました。まだ始めたばかりなので効果はわかりませんが、今は一流の人の習慣をとにかく真似をすると自分の中で決めているので実践してみました。

# 書き方
・文書量としてはWord２−３ページほどでいいのでqiitaに記入する
・言語の文法や簡単な説明、簡単なサンプルコードなどを記入する
・メンタルモデルを構築するために大まかな概念についてなども記入する
・なるべく思い出しながら記入する。また人に説明をすることを目的とした文章にする
・サンプルコードなどは積極的にコピペする。そのコードの一部を理解のために変更できるとなおよし
**・労力を極力かけない**

# 目的
・アウトプットをすることで理解を早める
・メンタルモデルを構築する
・実際に開発する際にリファレンスとして使用したり、コピペできるようにする
・しばらく使っていなかった技術を思い出しやすくする
・同じ間違いやエラーを繰り返さないようにする
### 重要
***満足感を得るためにこだわって作りすぎないこと。あくまで理解を助けるために作成する。またなるべく早くその技術を使ってアプリなどを作ることが一番理解につながる。***

# まとめ
しばらくやってみて効果を測りたいと思います
全方位木DPメモ

# 全方位木DPの流れ

一般的に深さ優先探索 (DFS) を2回実行するだけ．
ここで木の頂点が$N$個であるとする．
木であるため，辺は$N - 1$本ある．
従って，各辺の端点が $(u_n, v_n) \in \\{1,...,N\\} \times \\{1,...,N\\}$ であるとする．
すると，求めたいのは$n$番目の辺で木を二分した際に得られる部分木でのある量 $q_{n,0}, q_{n,1}$ (例: その木の中の頂点の個数やその木の中の各頂点同士の距離の和) である．
ここで$q_{n,0}$は葉側の部分木における量，$q_{n,1}$は根 (頂点1) 側の部分木における量だとする．

全方位木DPでは1回目のDFSで全ての$q_{n,0}$を求める．
これだけなら単純なDFSである．

2回目のDFSで全ての$q_{n,1}$を求める．
この部分が普段のDFSとは若干異なる．
1回目のDFSと同様に始点は頂点1として，DFSを実行する．
各頂点から生える部分木は根方向に生えている辺を除けば，全て葉方向に伸びるため，1回目のDFSで得られた$q_{n,0}$の再利用が可能である．
根方向に伸びる辺に対する量 $q_{n,1}$に関しては，2回目のDFSで上から順番に更新をかけるため，ある辺に到達した時点でもう既に必要な量が計算されている状態になる．

さて，頂点$n$についた段階で，頂点$n$の子供全てに対して，頂点$n$と子供を結ぶ辺で木を切断した際の頂点 $n$ 側の量を求めたい．
これを愚直に行うと子供の数 $M$ に対して，$O(M^2)$必要になる．
愚直な計算は星型の木だとTLEしてしまう．
従って，累積処理 (累積和等) を行って，各処理を $O(M)$ で行えるようにする．

[解答例](https://atcoder.jp/contests/abc220/submissions/56716912)
AWS ECSの基本概念

# AWS ECSの基本概念

ECSには以下のような項目があります。

- ECS Service
- ECS Cluster
- ECS タスク定義
- ECS タスク
- ECR リポジトリ

実際にはECSを使うために、AWSの他サービスと併用することがほとんどですが、本記事では***ECSを構成する要素とはなんなのか***に焦点を当ててなるべく簡潔に説明していきます。

::: note info
ECRは厳密にはECSのサービスではないかもしれませんが、ECSと密接に関係しているため含めています
:::

## ECS全体の関係図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492874/bacbdd2f-9554-d214-f062-b6c724dafbfb.png)



大まかな理解として、
- クラスターの中にはサービス、タスクが含まれる
- サービスの中にはタスクが含まれる
上記のような関係性になっています。次の項目で各リソースの役割について解説します。

## ECS Cluster

ECSを構成する要素の最大単位であり、タスク（コンテナ）やサービスを複数含める事ができます。
このクラスターがないとそもそもタスクを起動させる事ができないので、まず初めに作成する事になるかと思います。
タスクやサービスをグルーピングしたまとまりです。

::: note info
RDSにもクラスターの概念がありますが、RDSの場合はクラスターを作成せずにインスタンス単体で作成することもできます。
ECSの場合はタスクを起動する際にクラスターが必ず必要になるのでそういったリソース毎の違いには注意が必要です。
:::

## ECS タスク

ECSを構成する要素の最小単位であり、***タスク=コンテナ***です。
後述しますが、タスク定義に記載された内容で起動します。

## タスク定義

どのような設定でタスクを起動するかをjson形式で記述した設計書です。
開放するポート番号、環境変数の指定等、様々な設定ができます。

## ECS Service

タスクをいくつ起動するか、どのELBを指定するか、どのタスク定義を使用してタスクを起動させるか等の設定ができます。

## 筆者がECSを理解するためにイメージした事
これは完全に筆者のイメージでしかないですが、ECSの各種サービスがアマゾン等で荷物を注文する流れに似ているなと思いました。


1. まず購入者が、商品をカートに入れて注文します。
この時どんな商品を、いくつ注文するかを指定しますが、これが***サービス***に当たります。サービスでもいくつタスクを起動させるか、どのタスク定義からタスクを起動させるか等を選択できます。

2. 商品が注文されたら、商品を入れる箱を用意します。これは***クラスター***です。

3. 用意した箱に商品と、組み立てに必要な設計書を入れます。これは***タスク、タスク定義***です。

上記の流れは、実際にECSを作成する際の流れを考えるとおかしい点もあるので一例としてこんな考え方あるんだくらいに思っていただけますと幸いです。

## ECS タスク起動までの流れ

サービスからタスクを起動する流れについては以下のとおりです。

1. クラスターを作成する
1. ECRリポジトリを作成し、コンテナの起動に使用するイメージを入れておく
1. タスク定義を作成（ここでどのECRリポジトリのイメージを使用するかも記載します。）
1. クラスター内にサービスを作成し、タスクの数や、どのタスク定義からタスクを起動させるか等を指定する

上記まで実行すれば、サービスで指定したタスクの数分タスクが起動します。

::: note info 
ここではあくまでECSに絞って記載していますが、実際にはサービスからタスクを起動させるにはELBを作成したり、SecurityGroup周りも設定する必要があります。
:::

## 終わりに

正直、ECSにはじめて触れた際には用語の意味だったり概念的な理解がとてもしんどかったです。
実際に触れてみると、案外理解しやすかったりすると思いますのでぜひこの￥記事を読んだあとに手を動かしてみるのをおすすめします！筆者は以下のUdemyの講座でハンズオンしてみましたが解説も丁寧でわかりやすかったのでおすすめです。

[AWSコンテナサービス入門―AWSの基本からECS・Copilot CLI・CI/CD・App Runnerまで](https://www.udemy.com/course/aws-container/?couponCode=KEEPLEARNING)
自作キーボード：Keyball44のファームウェア更新がタイムアウトするのでQMK Toolkitを使って解決した話

## おことわり
以下をご了承願います。
- 初投稿です。よろしくお願いします。
- 生業は製造業の製品評価につき門外漢です。内容の正確性は保障できかねます。
- ~~あなたもKeyballいかがですか(布教ノルマ達成)~~ [keyball44紹介](https://shirogane-lab.net/items/64b7a006eb6dbe00346cd0c5)

## 経緯
キーマップ検討にて、自動マウスレイヤ切り替え機能(AML)が必須だと感じたので、[こちらの記事](https://note.com/yinouet1001/n/n54e6d3dc243a)を参考にファームウェアの開発環境を構築したものの、
「AML使うならLEDも必須じゃね？ でも工房で組んだから工具ないし...その後のマッピングもつらい…」と約半年グダグダしていた。
（お前に布教の資格はないという諸兄のお叱りの声が聞こえてきますね！）

流石に色々もったいないので情報収集からやりなおしたところ、公式ファームウェアがAML対応していたことを知る。蛇足だがリリース時期は挫折の約1～2週間後である…

とりあえずAMLだけでも有効化したくて、Remapで公式ファームウェアv.1.3.2のFLASHボタンをポチった。←今ココ

## 現象
で、遭遇した現象が下図。「ブートローダーは検知されませんでした」の文言が見えるが直後に「ファームウェアの書き込みに成功しました」とも言っている。

ブートローダーってファームウェアの読み書きのためのソフトじゃないんだっけ？
そいつが見つからないのに書き込みに成功してるの？？ （その程度の理解です）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759711/804457a3-7c88-e19a-9256-295d5a18169e.png)


スクロールバーで見切れている１行も含めたログの全文は下記。最終的にタイムアウトエラーを吐いている。

> Reading the firmware binary from the server.
Reading the firmware binary done.
Initialize a bootloader.
Fetching the Software Identifier.
Caterina bootloader is not detected.
Writing the firmware finished successfully.
Error: Reading bytes was timeout.

成功ならkeyballのOLEDの表示がAML対応のものに変わるはずだが、変化ないためまず更新はできていない。
なお、Remapでの通常のキーコンフィグの上書きはできるし、上書きしたキーで入力できることも確認している。

## githubの関連ディスカッション
下記の関連ディスカッションが見つかった。

https://github.com/Yowkees/keyball/discussions/375

エラーログは本件と同じ。下記の点は異なるがあまり関係なさそう。
- 記事はMac, こちらはWin
- 記事は初回ビルド時, こちらはアップデート時
- 記事はProMicroを5つ試している, こちらは実機搭載の2つしか試していない
- 記事はKeyball39, こちらはKeyball44

最終的に**QMK Toolbox**というデスクトップアプリからの書き込みで解決したようだ。環境とRemapの兼ね合いで起こる不具合っぽい？

なお、記事に記載あった下記についてはこちらでも試してみたが解決しなかった。
- PC変更
- ブートローダ変更(Caterina ⇒ dfu)
- USBケーブル変更
- USBポート変更
- KeyballのResetボタンを押してからの書き込み

## QMK Toolbox でファームウェアを上書きする

手順は下記を参照した。

https://github.com/foostan/crkbd/blob/fbb146fe372ce8b2b1543ced67367bf19e910945/doc/firmware_jp.md#qmk-toolbox-%E3%81%AE%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89

一応、ざっくり手順を示す。
1. QMK Toolboxをインストール
1. 書き込みたいhexファイルをRemapからダウンロード
1. QMK Toolboxで2を読み込んでFLASH

これだけ。下図の表示になったらOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759711/43266109-8931-6a32-fd10-c6664cc6d432.png)

OLEDも目的のAML機能対応の表示になったことを確認できた。
次項のAMLの有効化と動作の確認もできました。

## (おまけ) AMLの有効化
v1.3.2ではデフォでオフになっているので有効化する必要がある。専用のトグルキーが割り当てられているのでRemapで適当に設定すること。
詳細は下記の記事を参照。デフォで有効化する方法についても記述がある。

https://note.com/metoro/n/na129911a9252

## おわりに
自作キーボードは金銭コストもさることながら、時間も吸い取られますよね…。
引き続き気長にマッピングをやっていきます。
顔検出のパフォーマンス

## はじめに
Raspberry Piは熱暴走を発生させてしまう可能性があるので今後の目安としたいため、前回の記事（[OpenCVで顔検出してみる](https://qiita.com/cnysntry/items/6f7973a1f307c7c4a663)）で使用した顔検出処理のパフォーマンスを測ってみました。

## 動作環境
**デバイス**
　Raspberry Pi 4 Model B

**Raspberry Pi のOS情報**
```
lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 12 (bookworm)
Release:        12
Codename:       bookworm
```
**使用画像**
46人の集合写真

## 結果
温度検出に使用したコマンドは以下の通り。
```
$ vcgencmd measure_temp
```
46人中28人、顔検出することができた。
前の人と重なっている人もいるし、解像度も低いのでこんなものかな。。

**起動時のSoCの温度**
| 回数 | 温度 |
|:-:|:-:|
| 1 | 34.5 |
| 2 | 35.5 |
| 3 | 35.5 |
| 4 | 36.0 |
| 5 | 36.5 |
| 平均 | 35.6 |

**顔検出実行時のSoCの温度と実行時間**
| 回数 | 温度 | 時間 |
|:-:|:-:|:-:|
| 1 | 39.9 | 3.490s |
| 2 | 38.9 | 3.271s |
| 3 | 40.4 | 3.216s |
| 4 | 39.4 | 3.273s |
| 5 | 39.9 | 3.042s |
| 平均 | 39.7 | 3.258s |

## 補足
同じ顔検出スクリプトを使って、Raspberry Pi 4のファンを回さないようにしてSoCの温度検出を試してみました。

**起動時のSoCの温度**
| 回数 | 温度 |
|:-:|:-:|
| 1 | 39.9 |
| 2 | 43.3 |
| 3 | 41.8 |
| 4 | 41.3 |
| 5 | 40.9 |
| 平均 | 41.4 |

ファンを取り付けている時と比べると5～6℃も差がありますね。

**顔検出実行時のSoCの温度と実行時間**
| 回数 | 温度 | 時間 |
|:-:|:-:|:-:|
| 1 | 51.1 | 3.109s |
| 2 | 51.6 | 3.103s |
| 3 | 50.6 | 2.762s |
| 4 | 52.1 | 2.828s |
| 5 | 53.5 | 2.682s |
| 平均 | 51.8 | 2.897s |

ファンを取り付けるのは大事ですね。
nRFConnectSDKを基盤としたSesameの暗号通信 #8 使い慣れた開発環境-Clion

![sesame](https://scontent-nrt1-2.xx.fbcdn.net/v/t39.30808-6/455673256_10221188971154136_5683654793213838811_n.jpg?_nc_cat=106&ccb=1-7&_nc_sid=127cfc&_nc_ohc=SsQ53z7aDvIQ7kNvgFeoycZ&_nc_ht=scontent-nrt1-2.xx&oh=00_AYBpJGVqJJKvGGzCrOOw0_2EOLk64kStdP-ef178ObISIw&oe=66C3AC4C)


# 目的

量産を前提とした開発には注意すべき点が多く、開発環境は最低限以下の基準を満たす必要があります。

# 基準

- C言語では、すべてのハイパーリンクが適切にジャンプできる
- ショートカットキーで同時にコンパイルと書き込みができる
- 画面上で同時に出力、コンパイルの過程、そしてコードの編集ができ
- ターミナルでコマンドを入力してコンパイルおよび書き込みができる



# 雑談
JetBrainsのブログがあまりにも複雑なので、私が簡単な使い方をまとめて書くことにしました。

# 用語
[JetBrainsのブログ](https://blog.jetbrains.com/clion/2021/04/using-nrf52-with-cmake-connect-sdk/)



# 関連記事

- [nrf52840を基盤としたSesameの暗号通信](https://qiita.com/tse123321/items/c0fa105cd5b9f14c2a0c)
Javascriptプログラミングノート

# 変数の挙動

プログラムで使われる値は全てメモリ上に保管されている。

変数とは、番地への参照をするようなものである

変数に別の値が代入されると変数が保持されているアドレスが代入された値のアドレスに切り替わる

constは参照がロックされるイメージ

再代入できない

# データ型

プログラムで扱うデータにはいくつかの種類があり、そのデータの種類のことをデータ型または型と呼ぶ

データ型は大きく、次の2つに分類される

Primitive型　stringなど

非Primitive型　オブジェクト

プリミティブとは、原始的なという意味である

# Javascriptのオブジェクトについて

オブジェクトとはプロパティと呼ばれる値を格納する

オブジェクトとは、変数を管理する入れ物のようなものである

オブジェクトは複数の値を1つのまとまりとして管理できる

オブジェクトから値を取得変更する場合には、次の方法を使用できる

## ドット記法

ドット記法では、オブジェクトとプロパティーを.でつなぐことで、オブジェクトの値の取得変更ができる

## ブラケット記法

ブラケット記法ではオブジェクトの後ろに[]を続けてその中に文字列でプロパティ名を記述する

##  Reflect.get() またはReflect.set() 
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Reflect/get
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Reflect/set


# メソッド

プロジェクトでは特定の処理を行う機能を追加したい場合、関数を登録できます

また、オブジェクトに保持される関数は** メソッド **という

# コールバック関数

関数はオブジェクトの1種なので、オブジェクトのように他の関数の引数として渡すことができます

この引数で渡される関数のことをコールバック関数と呼ぶ

→引数で関数を渡すとは？

具体例:

```
function greet() {

　console.log("Good morning!");

}

// 2秒後に `greet` 関数を実行する
setTimeout(greet, 2000);
```

# 無名関数を使ったコールバック関数
コールバック関数を定義する時は無名関数と呼ばれる関数をたびたび使う
無名関数とは名前がない関数のことである
無名関数は複数回呼ばれることを想定していない
無名関数を使ってコールバック関数を定義してみよう

```
setTimeout(function(){
 console.log("こんにちは");
 },3000);

```

# アロー関数
アロー関数とは無名関数の省略記号
コールバック関数に使う無名関数をアロー関数に書き換える場合次のように記述できる
```
///無名関数
setTimeout(function(){
    console.log("こんにちは");
}, 1000 );

// アロー関数
setTimeout(() => console.log("こんにちは"), 1000);
```
いい省略だ


# 非同期処理

作業の完了を待たずに別の作業をすることを非同期処理と呼ぶ
githubのリポジトリの命名変更

なんか既存のリポジトリと似たような名称で作成してしまっていた。
**github上のリポジトリの命名を変更したい**

初心者ながら下記の内容でいいかなと思っていた

1. github上で名称変更
1. ローカルに新ディレクトリ作成,そこでgit clone

先輩エンジニアからの一言
『これでもできるけど、こんな回りくどいことしなくとも変更できるよ』

調べてみたところ確かに簡単に実行できそうでした
ローカル環境(ターミナル)から変更すればいいみたいです。

まずはドキュメントを読むように学んだので
読んだ上で今後同じことが起きた時用にまとめます。

## やり方

現在のリモートリポジトリの名称確認
```
$ git remote -v

origin  git@github.com:<ユーザー名>/<現在のリポジトリ名> (fetch)
origin  git@github.com:<ユーザー名>/<現在のリポジトリ名> (push)
```

新しいリモートURLに変更する
```
$ git remote set-url origin https://github.com/<ユーザー名>/<最新のリポジトリ名>.git
```

再度最新の名称になっているか確認
```
git remote -v

origin  git@github.com:<ユーザー名>/<最新のリポジトリ名> (fetch)
origin  git@github.com:<ユーザー名>/<最新のリポジトリ名> (push)
```

覚えたての知識だけで太刀打ちするのではなく
まずはググって効率のいい方法を調べることが重要と再認識しました。


参考資料
-
https://docs.github.com/ja/repositories/creating-and-managing-repositories/renaming-a-repository
win10(22H2)のタスクバーの検索機能で「話題の検索ワード」を無効にする

# 記事のまとめ
レジストリエディターでレジストリを編集し、「ニュースと関心事項」を無効にしても右下に出てくる「話題の検索ワード」を消します

### 1:レジストリエディターを起動する
1. スタートメニュー＞windows管理ツールから起動する
もしくは
2. win + r で `regedit.exe`と入力する

### 2:キーを新規作成する

1.`HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows`　を開く
2.Windowsフォルダ内にキーを作成(右クリック＞新規＞キー)
キー名は `Explorer` に設定


### 3:DWORDを新規作成する
1.作成したExplorerキー内に"DWOED(32ビット)値"を新規作成
![レジストリエディターの画面。作成したExplorerキーを選択すると、ウィンドウ右側にバイナリデータの一覧が表示されるので右クリック＞DWOED(32ビット)値を選択](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3824049/90267445-5349-362f-93ff-8d20dad666f0.png)
2.値の名前を編集
値の名前を`DisableSearchBoxSuggestions`に設定します

::: note info
うっかり"新しい値#1"で確定してしまったら、右クリック＞名前の変更で編集できます。他の項目(修正など)では編集できないようです。
:::

3.値のデータを編集
作成したDWORDをダブルクリック
値のデータは`1`で、表記は16進数を選択
![DWORD編集画面。値のデータを1に、表記は16進数を選択。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3824049/dc904f5b-4e66-df4a-da74-d88f11f7f549.png)

### 4:再起動する
再起動すると(任意の悪口)の「話題の検索ワード」が消えます
**************************

###### 5:参考
[1] https://superuser.com/questions/1751366/how-to-remove-trending-searches-in-windows-10-search
【重回帰分析】正規方程式の導出

## はじめに
機械学習・深層学習がもてはやされる昨今ではあるが、重回帰分析は今でも実業務で使われているのを目にする。
説明変数に主効果だけでなく、高次項や交互作用項などの非線形因子を加えることで機械学習と同レベルの予測精度を期待できる。
また、説明性が高いため、実業務での顧客への説明が比較的容易というメリットがある。

正規方程式は、偏回帰係数を求めるための数学的な方程式である。

## 定義
説明変数：$ x \$($ p \$個と仮定)
目的変数：$ y \$
目的変数推定値：$ \hat{y} \$
偏回帰係数：$ β \$($ β_0 \$は切片)
```math
\begin{align}
\hat{y} &= β_0 + β_1 x_1 + β_2 x_2 + ・・・ + β_p x_p
\end{align}
```
また、次のようにベクトルと行列を定義する（$ n \$はデータ数）。
```math
\boldsymbol{\hat{y}}=
\begin{bmatrix}
\hat{y_1} \\
\hat{y_2} \\
\vdots \\
\hat{y_n}
\end{bmatrix}
,
\boldsymbol{X}=
\begin{bmatrix}
1 & x_{11} & x_{12} & \ldots & x_{1p} \\
1 & x_{21} & x_{22} & \ldots & x_{2p} \\
\vdots & \vdots & \vdots & \ddots & \vdots\\
1 & x_{n1} & x_{n2} & \ldots & x_{np} \\
\end{bmatrix} \\
,
\boldsymbol{β}=
\begin{bmatrix}
β_0 \\
β_1 \\
β_2 \\
\vdots \\
β_p
\end{bmatrix}
```
以上より重回帰モデルは以下の数式で表される。
```math
\boldsymbol{\hat{y}} = \boldsymbol{X}\boldsymbol{β}
```
## 正規方程式導出
目的関数を$ L(β) \$とし、最小二乗法を用いる。
※最小二乗法：誤差の二乗が最小となるようにパラメータ$β\$を求める方法
```math
\begin{align}
L(\boldsymbol{β}) = \displaystyle \sum_{ i = 1 }^{ n } (y_i - \hat{y_i})^2
&= (\boldsymbol{y}-\boldsymbol{X}\boldsymbol{β})^T(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{β}) \\
&= (\boldsymbol{y}^T-\boldsymbol{β}^T\boldsymbol{X}^T)(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{β}) \\
&= \boldsymbol{y}^T\boldsymbol{y} - 2\boldsymbol{β}^T\boldsymbol{X}^T\boldsymbol{y} + \boldsymbol{β}^T\boldsymbol{X}^T\boldsymbol{X}\boldsymbol{β}
\end{align} \\
```
ここで、$ \boldsymbol{β} \$で偏微分した結果が0になる場合を考える。
```math
-2\boldsymbol{X}^T\boldsymbol{y} + 2\boldsymbol{X}^T\boldsymbol{X}\boldsymbol{β}=0
```
あとは式を整理して
```math
\begin{align}
-\boldsymbol{X}^T\boldsymbol{y} + \boldsymbol{X}^T\boldsymbol{X}\boldsymbol{β} &= 0 \\
\boldsymbol{X}^T\boldsymbol{X}\boldsymbol{β}  &= \boldsymbol{X}^T\boldsymbol{y} \\
\boldsymbol{β}  &= (\boldsymbol{X}^T\boldsymbol{X})^{-1}\boldsymbol{X}^T\boldsymbol{y}
\end{align}
```
これが正規方程式であり、各偏回帰係数を求めることができる。
エンジニアの育児で整備したもの・役立ったもの

育児が一旦落ち着いたので、これから子育てを始める方・絶賛子育て中の方向けに
事前に整備したこと・個人的に役立ったガジェットやWEBサービス等をまとめておきます。


## 妻と家族写真の共有
撮影した写真や動画の画質などを考慮し、私と妻のそれぞれで、
新し目のiPhone（例：iPhone13 mini）を使うようにしました。

iPhone同士であれば、「共有写真ライブラリ」の機能が使えます。
撮影した写真や動画が、妻のiPhoneと自動的に同期されるようになったので
「あの写真、どっちののスマホで撮ったっけ？」がなくなり、とても便利になりました。

https://support.apple.com/ja-jp/guide/iphone/iph28ac9ea81/ios



## 写真のバックアップ先の決定
以下で迷いましたが、最終的にiCloudに決めました。
途中での移行は面倒なので、はじめから1つに決めておけば良いと思います。

|種類 | メリット|デメリット |
|---|---|---| 
[iCloud](https://support.apple.com/ja-jp/108782)|iOSと統合されておりバックアップが簡単。Macでも使いやすい | 月額が高い・Windowsで使いにくい
[Googleフォト](https://photos.google.com/)|顔認識の精度が良い、◯年前の今日、など気の利いたまとめも作成してくれる | 簡単ではあるものの、バックアップには専用アプリを起動させる必要がある。
[Amazon Photos](https://www.amazon.co.jp/b?node=5262648051)|prime会員なら写真の容量は無制限。動画は5GBまで（課金で増やせる）|Amazon Prime会員であり続ける必要がある
自宅NAS|維持費が無料（電気代はかかるが…） | 初期投資が必要。端末からのバックアップが手間。




## スマートスピーカー
Google製のスマートスピーカー Google Home mini が便利でした。
（今は後継のNest Mini が販売されています）
手が離せない時にさっとタイマーをかけたり、寝かしつけのときの曲を再生したり、
後述する育児記録をつけるのに利用しました。

Amazon製のAmazon echo も所持しておりますが、
個人的にはGoogle製の方が音声認識の点などでGoogleのほうが良かったです。


## スマートテレビ
スマートテレビに買い替える金は無いので Fire TV Stick を使っています。
YouTubeを再生したり、
Kodi というメディアプレーヤーのアプリをインストールし
NASのメディアを再生するなどの用途で利用しています。

https://cheapna.com/amazon/fire-tv-stick_kodi/


## 育児の記録

ミルクやおむつ交換、睡眠などの記録をスマホでさっとつけることができるアプリです。
複数端末でデータが共有できるうえ、Apple Watch にも対応しており、
私が仕事中のときも「あ、今ミルク飲んだんだな」と、子どもの様子がわかりました。

https://www.piyolog.com/

が、それより便利な点。スマートスピーカーと組み合わせることで、
「OK Google、ミルク飲んだよ」
「OK Google、うんちしたよ」
のように、__声での育児記録が可能です。__ 設定方法は以下を参考に。

https://ayajima.com/piyolog/12835/

姉妹アプリで予防接種の管理もできたので

https://www.piyolog.com/service.html

## 予定の管理

Googleアカウントをまとめるファミリーグループを作成しました。

https://families.google/intl/ja/families/

その後、家族間で共有できるGoogleカレンダーを作成し、家族の予定はGoogleカレンダーに入力していくこととしました。

妻はiPhoneの純正カレンダーアプリを利用していたため、Googleアカウントを設定することで、アプリの操作性はそのままに、裏側だけGoogleカレンダーで同期するようにしました。



## 英語のCD

YouTube Music は、配信されている曲だけではなく、任意の曲を自身のプライベート空間にアップロードし、聴くことが可能です。

https://support.google.com/youtubemusic/answer/9716522?hl=ja

YouTube Music は スマートスピーカー（Google Nest Mini）でも利用可能だったので
「OK Google、○○のアルバム再生して」と言うだけで、英語の曲が再生されるように設定しました。
気軽に再生できる環境を作ることで、英語に耳を慣らさせることが目的です。


## まとめ

さっと思いついたのはこれぐらいです。
これから子育てを始める方・子育て中の方は参考にしてみてください。



---

https://naokichigyoza.com/
RailsプロジェクトにおけるBunを使用したJS/CSSビルドのメリットと実装方法

## 背景
今回、個人開発の小規模アプリにおいて、軽量かつシンプルなビルドツールを求めていました。これまでWebpackerやesbuildを使ってきましたが、設定が複雑でビルド時間が長いことが課題でした。Bunを選んだ理由は、非常に高速で、設定が簡単な点に加え、JSとCSSのビルドが一貫してシンプルに管理できるからです。Bunを使ったビルドプロセスの実装手順について詳しく説明します。

## Bunの速度比較
中規模のプロジェクト（約1000行のJSと500行のSassコード）をビルドする場合、Webpackerは約8〜10秒、esbuildは1〜2秒でビルドを完了します。一方、Bunはその中でも最速で、同じビルドタスクをわずか0.5〜1秒未満で処理できます。Bunの高いパフォーマンスは、ランタイムとビルド機能の統合による効率の高さにあります。

※詳細は調べると検証した記事があるため、それを参照してください！

## 実装手順

### 手順 1
まず、Homebrewを使ってBunをインストールします。
```
brew install bun
#bun -v でバージョン確認
```

### 手順 2
プロジェクトディレクトリ内でBunを初期化するため、以下のコマンドを実行します。これにより、package.jsonが自動的に生成されます。
```
bun init
```
「bun init」コマンドを打ち込むと名前とエントリーポイントの入力を要求されます。

エントリーポイントについては、今回はオリジナルで設定をするために「index.ts」をとりあえず設定をしておけばいいです。このファイルは後ほど使わないので削除するか無視してください。

### 手順 3
次に Procfile.dev と package.json の設定をします。
Procfile.devでは下記のようにbin/devを行った際に「bun run」コマンドをjsとcssごとに行うよう設定をします。
```
web: bin/rails server -p 3000
js: bun run build --watch
css: bun run css:build --watch
```

「bun run build --watch」を実行した場合、Bunは package.json 内の "scripts" セクションに定義された "build" コマンドを実行します。そのため、このコマンドは package.json に定義されている特定のスクリプトをもとにビルド を行います。
※「js: bun run build --watch」はpackage.json 内のjsに関する設定のみビルドを行います。

```
{
  "name": "shuffle-lunch-app",
  "scripts": {
    "build": "bun build app/javascript/base.js",
    "css:build": "sass app/assets/stylesheets/application.scss:app/assets/builds/application.css --no-source-map"
  },
  "devDependencies": {
    "@types/bun": "latest"
  },
  "peerDependencies": {
    "typescript": "^5.0.0"
  },
  "module": "index.ts",
  "type": "module"
}

```
「css: bun run css:build --watch」を実行する際には、「gem 'sass-rails'」をインストールして、sassコマンドを実行できるようにしてください。

```
gem 'sass-rails'
#=> bundle install
```

## まとめ
今回の個人開発では、軽量かつシンプルなビルドツールを求め、Bunを採用しました。Webpackerやesbuildに比べて、Bunは高速で、設定が簡単であり、JSとCSSのビルドを統一して管理できるため、小規模アプリの開発には最適な選択でした。Bunのインストールから初期設定、そしてProcfile.devによる自動ビルドの設定まで、シンプルで効率的なプロセスを実装することができました。Bunは、個人開発においてフロントエンドビルドを簡素化し、開発速度を向上させる優れたツールです。
Azureの無料アカウントを開設する


以下のサイトにアクセス。

https://azure.microsoft.com/ja-jp/free/

`無料で始める`をクリック。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862159/498f1aff-8439-e788-0b38-9a4e90d56a66.png">

Microsoftアカウントを持っていればそのままサインイン。なければ作成。
<img width="300" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862159/133778af-fe45-10a9-5303-78c6116e8268.png>

必要事項を記入。
<img width="400" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862159/1b5c4420-728f-33f5-261f-891ade4a2a50.png>

クレジットカード情報を入力。
<img width="400" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862159/380063a6-4a4f-07db-67d4-ef4d636e2ade.png>

以下注意事項。
<img width="400" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862159/8eda05e6-c4c2-a325-da9b-758fadd4c065.png>

多要素認証の設定。
<img width="300" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862159/95e2a4a0-111c-7cfd-4997-cdd607d5063b.png>

無料アカウントの作成が完了。`Azure Portalに移動する`をクリック。
<img width="500" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862159/3d16fd3c-0e20-193a-0591-1fd0d056015a.png>

Azure Portalにアクセスできた。
<img width="400" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862159/23e7db38-7c1f-67d8-2469-7ddff2c286dc.png>

色々見てみたら、サブスクリプションが既定で出来ていた。
<img width="500" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862159/be717167-8202-9a0b-014e-0c36293f514f.png>

以上。