OmniAICreator/Qiita-1.07M huggingface dataset:
Uncategorized (Xcode): Unable to find a destination matching the provided destination specifier

## はじめに

vscodeでflutterのdebugを行おうとするとタイトルのエラーが発生しました。
エラーメッセージ読んでもよくわから図、かなりはまってしまった為備忘録として残します。

## 問題

発生したエラー

```
Launching lib/main.dart on iPhone 15 Pro Max in debug mode...
Xcode build done.                                            2.3s
Failed to build iOS app
Uncategorized (Xcode): Unable to find a destination matching the provided destination specifier:
		{ id:DB36E98A-36F9-4D63-8AB4-071487E833BD }

	Available destinations for the "Runner" scheme:
		{ platform:macOS, arch:arm64, variant:Designed for [iPad,iPhone], id:00008103-000405893ABB001E, name:My Mac }
		{ platform:iOS, arch:arm64, id:00008020-001270E91A3A002E, name:iPhone }
		{ platform:iOS, arch:arm64, id:00008110-000624D92263A01E, name:iPhone }
		{ platform:iOS, id:dvtdevice-DVTiPhonePlaceholder-iphoneos:placeholder, name:Any iOS Device }

Could not build the application for the simulator.
Error launching application on iPhone 15 Pro Max.

Exited (1).
```

指定されたデバイスがないよ的なエラーに見える

## やったこと

### flutter devices

```shell
$ flutter devices
Found 5 connected devices:
  iPhone (mobile)           • 00008020-001270E91A3A002E            • ios            • iOS 17.5.1 21F90
  iPhone 15 Pro Max (mobile)      • DB36E98A-36F9-4D63-8AB4-071487E833BD • ios            •
  com.apple.CoreSimulator.SimRuntime.iOS-17-5 (simulator)
  macOS (desktop)                 • macos                                • darwin-arm64   • macOS 14.0 23A344
  darwin-arm64
  Mac Designed for iPad (desktop) • mac-designed-for-ipad                • darwin         • macOS 14.0 23A344
  darwin-arm64
  Chrome (web)                    • chrome                               • web-javascript • Google Chrome
  126.0.6478.127

Found 1 wirelessly connected device:
  iPhone (mobile) • 00008110-000624D92263A01E • ios • iOS 17.5.1 21F90

Run "flutter emulators" to list and start any available device emulators.

If you expected another device to be detected, please run "flutter doctor" to diagnose potential issues. You
may also try increasing the time to wait for connected devices with the "--device-timeout" flag. Visit
https://flutter.dev/setup/ for troubleshooting tips.

```

うーん、あるよね？？

```
iPhone 15 Pro Max (mobile)      • DB36E98A-36F9-4D63-8AB4-071487E833BD • ios  
```

```
Uncategorized (Xcode): Unable to find a destination matching the provided destination specifier:
		{ id:DB36E98A-36F9-4D63-8AB4-071487E833BD }
```

### xcodeから直接ビルド

build失敗して、ログには**3秒だけ**「Module 'cloud_firestore' not found」とエラーが出た
さらによくわからなくなり迷子に

## 原因

xcode(Version 15.4)のSchemeの設定が誤っていた。
Product -> Scheme -> EditScheme -> Build Configurationのところが
「debug」ではなく「release」になっていた。

### 理由

app store connectにアプリをアップロードする際releaseに変更したのですが、
その後debugに戻すのを忘れていた侍😭

## 解決

Schemeの設定をrelease から debug に戻し、vscodeでdebugすることができました。
コスパのいいサーバーレス構成

# はじめに
最近(というかここ数年)では、サーバーレスアーキテクチャが流行ってますよね。
アプリケーション本体の開発に注力できインフラ等の余計な部分を考えなくて済むのでいいですよね。~~(ちょっと寂しい気もしますが)~~


# 主要なベンダの簡単な比較
## AWS Lambda
AWSが提供するサーバーレスプラットフォームで、多機能で柔軟性が高いですが、複雑な価格体系と比較的コストが高いです。

## Google Cloud Functions
Googleのサーバーレスソリューションで、他のGCPサービスとの連携が強みです。
料金は普通くらい。

## Azure Functions
Microsoftの提供するサーバーレスプラットフォームで、.NET環境との親和性が高いです。
ただ、コールドスタートがめっちゃ遅いらしいです。(私は使ったことないんですけどね)

## Cloudflare Workers
Cloudflareが提供するエッジコンピューティングプラットフォームです。
グローバルなエッジネットワークを活用し、低コストで高パフォーマンスを実現します。


# Cloudflare Workersがいい理由
## 安い、安いぞ！
Cloudflare Workersは、他のプラットフォームと比較して圧倒的に低コストです。
1日10万リクエストまでは無料で利用でき、それ以上でも$5/1,000万リクエストという価格設定はとても魅力的です。

## ぐろーばる
Cloudflareの世界中に展開されたエッジロケーションを活用し、ユーザーに最も近い場所でコードを実行します。これにより、低レイテンシーと高速なレスポンスを実現します。

エッジで動くと何が嬉しいかというと、パフォーマンスが高いことです。
物理的な距離が離れているとレイテンシの問題が発生しがちですが、近くのエッジノードにて処理されるため最小限の遅延でレスポンスができます。

## かんたん！！うごく！！
Workersは標準的なJavaScriptやTypeScriptを使用でき、開発環境の構築も容易です。
また、デプロイも簡単で、CIツールとの連携も容易です。

## スケーラビリティ
自動的にスケールアップ・ダウンするため、トラフィックの変動に柔軟に対応でき、開発者はインフラの管理から解放され、アプリケーション本体の開発に注力することができるかもしれません。

## はやい！！やばい！！うごく！！
Lambda＠Edgeのような環境では、コンテナが使用されているため、リクエストが投げられる度にコンテナの起動処理が入ってしまい、遅延が起こってしまいます。
俗に言うコールドスタート問題ってやつです。

しかし、Cloudflare Workersではコンテナが使用されておらず、JSのV8エンジンが使用されています。
そのため、コールドスタートによる遅延は(ほぼ)ありません。

# さいごに
Cloudflare Workersは、その低コスト、高パフォーマンス、簡単な開発・展開プロセスにより、最もコストパフォーマンスの高いサーバーレス構成と言えます。

D1やKVなど関連するプロダクトも他社のものと比較してかなり安価であるため、総合的に見てもCloudflare Workersを中心としたアーキテクチャは非常に魅力的です。

是非使ってみてください。

それでは。
Chrome サイドバーのタブを管理する - ブラウザ拡張機能

カラフルなサイドパネルのタブマネージャー 🌈

サイドパネルでブラウザタブを管理するための魅力的で強力なツールです。

特徴：
- 🌞明暗モード切り替え：お好みに応じて表示モードを選択してください。

- 🔠 カスタマイズ可能なフォント サイズ: 快適な読書体験が得られるようにフォント サイズを調整します。

- 🖥️カスタマイズ可能なインターフェースのレイアウト: 使用習慣に応じてインターフェースのレイアウトを調整します。

- 🎨 パーソナライズオプション: カラフルな背景や背景画像などを追加して、サイドパネルをユニークにしましょう。

- 🗂️ タブ管理: 効率的なタブ管理のためのサムネイル プレビューの表示、豊富な並べ替えおよび表示オプション、豊富なアクション メニューへのアクセス。

- 🔍 検索: 最近閉じたタブや閲覧履歴を簡単に検索して、必要なものをすばやく見つけます。

- 🖼️ピクチャーインピクチャーモード: タブを切り替えたり、ページをスクロールしたりすると、自動的にピクチャーインピクチャーモードに切り替わり、スムーズなブラウジングエクスペリエンスが提供されます。

- 📂 自動グループ化: 同じドメインに基づいてグループを自動的に作成または参加します。

- 📖 読書進行状況バー: 読書の進行状況をリアルタイムで追跡します。

- 🎵 再生プログレスバー: 早送り、巻き戻し、音量の調整、再生速度の調整など、マルチメディアの再生を制御します。

その他の機能については、オプションのページをご覧ください。


[chromewebstore](https://chromewebstore.google.com/detail/chejfhdknideagddnddjpgamkchefjhoi) 


私たちの取り組みが気に入っていただけましたら、レビューを投稿して情報を広めてください。 [https://www.producthunt.com/products/rabbitpair-vertical-tabs-in-side-panel/reviews/new](https://www.producthunt.com/products/rabbitpair-vertical-tabs-in-side-panel/reviews/new)


いくつかのプレビュー写真


![main_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836968/43e97e98-7d4b-804d-cd3b-1bf337591b09.png)
![main_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836968/634b624b-5ecb-25ce-8217-187bf8f7bfeb.png)
![main_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836968/bf6ec9e0-50c1-ef9c-3c3d-c6e59d53d8f8.png)
Notionのデータベース機能でマッチング機能を作成

Notionのデータベース機能でマッチング機能を作成してみました。

## リストビューを登録
![スクリーンショット 2024-07-16 22.53.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133917/91382038-0aee-bd55-a638-d67dcb0acff1.png)

## データベースにユーザを登録
![スクリーンショット 2024-07-16 22.52.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133917/4346d218-2646-0a26-b1b2-ac2764fa57bc.png)


## ユーザのプロパティにマッチングしたい項目を追加
![スクリーンショット 2024-07-16 22.56.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133917/eeacab8a-ca9a-d4a4-e237-4af6e6d1f231.png)

![スクリーンショット 2024-07-16 22.58.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133917/20bc800c-ab2f-1aca-61dc-48d53d56d7a4.png)

## グループ化する

![スクリーンショット 2024-07-16 22.57.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133917/a8632ccb-fc31-db1e-d246-60138996161e.png)

![スクリーンショット 2024-07-16 22.58.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133917/5e81ef5b-5411-4cc1-631d-d3fb4ac89c8b.png)

![スクリーンショット 2024-07-16 22.59.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133917/c01e302b-6bcb-9fb6-c23e-412d6a0322b8.png)


## リストビューの名前を変更!
![スクリーンショット 2024-07-16 22.59.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133917/c9f3d10f-d05f-6d19-cb56-6af209d412c2.png)

![スクリーンショット 2024-07-16 22.59.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133917/290b0790-332e-913d-c8c3-667f3fe561a5.png)
Python　Flaskの環境構築

PythonのフレームワークFlaskの環境構築について書いていきます。

Flaskのドキュメント
https://flask.palletsprojects.com/en/3.0.x/

Virtual environmentsを選択

コマンドプロンプトで下記を実施していきます。

Create an environment
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3686008/0c5cfd1c-9fe6-6d13-98d9-95de1d406526.png)
```
mkdir myproject
```
myprojectというファイルができます。

```
cd myproject
```
```
py -3 -m venv .venv
```
仮想環境が出来上がりました。


続いて仮想環境の有効化します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3686008/04578384-4f05-a59d-cd2b-41dab03ed68d.png)
```
 .venv\Scripts\activate
```


続いてFlaskのインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3686008/72ca72ed-bdeb-4d16-f8ef-dada8d75408f.png)
```
pip install Flask
```

インストールの確認方法は
```
flask --version
```
にてインストールが確認できます。
【反省文】ROM専だった私がQiita投稿マラソンに初参加するも質の悪い記事を量産した話

# はじめに
これまで技術情報収集はQiitaにお世話になるばかりのROM専でしたが、
QiitaEngineerFesta2024を機にQiita投稿マラソンに参加してみました。
結果として、
開催期間中に20投稿できましたが、質の悪い記事ばかり投稿してしまいました。

# なぜ質が悪いと思ったのか
=>AIの力を借りて記事を量産するものの、**理解や気づきが欠如**していると感じたため
=>ネタも尽き、同じような内容を焼き直すだけで、**誰に向けて何の目的で発信**しているのかも曖昧で、ただただ**検索結果を汚染する**だけの記事になったため

私の投稿の目的は学習の振り返りと定着でしたが、、、
実際には、**コピペ**するだけでなんの学習にもならず、理想とする**アウトプット**とは程遠いものになってしまいました。
「些細なことでもアウトプット」という言葉を履き違え、質よりも量を優先してしまいました。質の高い記事を投稿するために、**優れた記事の構成や内容を参考にすべき**でした。🙇‍♂️

# 良かった点
=>投稿マラソンを通して、**些細な気づきでもメモを取る習慣**📝が身についた
=>誰かの役に立ちたいという気持ち、そして「いいね」や「ストック」をもらえた時の喜びを知れた
=>自信に繋がり、技術的な内容だけでなく、**自分の考えを発信することの楽しさ**👍を教えてくれた

間違いがあれば、指摘や助言をもらえるのもQiitaの魅力だと思いました。
また、自身の学習内容や心境を振り返る良い機会を得られたことも大きな収穫でした。

さらに、Qiitaを通して技術やプロダクト、マネジメントなど、新たな分野に興味を持つようになり、ネタ探しのためにアンテナ📡を張るようになりました。

# まとめ
今回の経験を糧に、今後は**読者の役に立つ**、**質の高い記事**を投稿できるよう、精進していきたいと思います。 💪

# 備考(投稿マラソンの記事一覧)

#### Canvasの絵をAsciiアートにするツール
=>一発芸的なツールでした

https://qiita.com/shisojuice/items/2413580f72244a4823c7

#### Fabric.jsのVersionが上がったためだった
=>特筆なし

https://qiita.com/shisojuice/items/c6b13ff6c17ef1705d75

#### FaviconGenerator
=>一発芸的なツールでした

https://qiita.com/shisojuice/items/2ce43d25ec48c2c36486

#### FaviconChecker
=>一発芸的なツールでした

https://qiita.com/shisojuice/items/b81df8fd81b6dc0e8c7c

#### ドット絵作るツール
=>一発芸的なツールでした

https://qiita.com/shisojuice/items/dd4c99bdab0c4cef2387

#### マークダウン系クレートの紹介
=>HelloWorldレベルの紹介になってしまった😑

https://qiita.com/shisojuice/items/c9391ea9bc719db0bd7d

#### web-sys使って写真ペイントツール
=>成果物が微妙すぎた

https://qiita.com/shisojuice/items/d4bf349a658944aa4456

#### web-sys使って写真ペイントツール_リベンジ版
=>結局web-sysあんまり使ってない😰

https://qiita.com/shisojuice/items/2259763b3352c9c6ff97

#### 電光掲示板みたいに文字が自動で横に流れるツール
=>一発芸的なツールでした

https://qiita.com/shisojuice/items/0bd4663aed0a3152d1f6

#### 拡大鏡ツール
=>一発芸的なツールでした & わざわざRust使わんでもCSSで良かった😧

https://qiita.com/shisojuice/items/7f640c13cc040e341ac0

#### Canvas要素を使わずお絵描きする
=>特筆なし

https://qiita.com/shisojuice/items/a6aa1d7df75fa70fb1a9

#### あるあるらしい
=>知識不足を実感😥

https://qiita.com/shisojuice/items/5813e07ce77422915862

#### 文字をGif画像みたいにパラパラさせる
=>電光掲示板で使用したコードを再利用しただけだった😞

https://qiita.com/shisojuice/items/90c70d8218236e0325b3

#### アナログ時計をRustで実装してみた
=>三角関数を利用した部分はほぼAIのコードになってしまった🤖

https://qiita.com/shisojuice/items/370769ecdfb48313ed24

#### Svgコンバーター
=>一発芸的なツールでした

https://qiita.com/shisojuice/items/ff3b453bddf64df1f89c

#### Rand使っていろんな円を描いてみた
=>自分で作っておいてそもそもRandomArtって何だろうとなった(ネタ切れ)🙇‍♂️

https://qiita.com/shisojuice/items/75611d854ffa65613a43

#### imageproc使って動かせる目玉を描いてみた
=>自分で作っておいてそもそも目玉Artって何だろうとなった(ネタ切れ)🙇‍♂️

https://qiita.com/shisojuice/items/84299b0f5ac4f38fa920

#### similar系クレートの紹介
=>HelloWorldレベルの紹介になってしまった😑

https://qiita.com/shisojuice/items/e782cfec512e73928e82

#### Javascriptで映像をCanvas要素に描画する
=>HelloWorldレベルの紹介になってしまった😑

https://qiita.com/shisojuice/items/d5906127e031354db800

#### WebCameraの映像にドット絵フィルターをかける
=>一発芸的なツールでした

https://qiita.com/shisojuice/items/7142c594afd6bdc79b13
GitHubにおけるOIDC(OpenID Connect)とは？

こちらのGtiHub Docsが英語しかないため、OIDCとはなにか？に関わる部分のみ短く抜粋していきます。

https://docs.github.com/ja/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect


## 概要
OIDCというのは、OpenID Connectの省略した呼び名になります。

GitHub ActionsのWorkflowではたびたびAWSやAzureといったクラウドサービスへとアクセスを行います。
workflowがクラウド上のリソースに対してアクセスするためには、事前にクレデンシャル(credential)が必要となります。

クレデンシャルのような永続的な認証を発行してGitHubに保存するのではなく、一時的なアクセストークンをAWSなどのクラウドサービスから発行することで認証とするのがOIDCです。


## OIDCがない場合はどうなる？
前述の通り、workflowがクラウド上のリソースに対してアクセスするためには、事前にクレデンシャル(credential)が必要となります。
通常、このクレデンシャルはGitHubのsecretに保存し、クラウドにアクセスする際は毎回このクレデンシャルをsecretから呼び出します。

つまり、ハードコードされたクレデンシャルをGitHubに保存するためにAWSなどのクレデンシャルをコピーする必要があるのです。
クレデンシャルはユーザネームとパスワードのようなものですから、可能な限り複製して複数の場所に保管したりはしたくないですよね...

これを防ぐために、OpenID Connect(OIDC)が存在しているのです。
ruff + pre-commit でフォーマッタを強制する

ruffにフォーマットされていないコードがコミットされるのを防ぎます。

## pre-commit とは
pre-commit は GitHook スクリプトをコミット前に実行します。

以下のようなイメージである。
ステージング -> pre-commit -(コーディング規約を遵守していれば)-> コミット


ruff, pre-commitを追加する。

```bash
$ rye add -d pre-commit ruff
$ rye sync
```

pre-commit用の設定ファイルを作成します。

`~\.pre-commit-config.yaml`の例
```yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    # Ruff version.
    rev: v0.1.4
    hooks:
      # Run the Ruff linter.
      - id: ruff
        exclude: "(__init__\\.py|migrations/)"
      # Run the Ruff formatter.
      - id: ruff-format
        exclude: "(__init__\\.py|migrations/)"
```

`__init__.py`と`migrations`系のファイル群を例外に設定しています。

設定ファイルを適用します。

```
pre-commit install
```

これでフォーマッタが実行されていないコードのコミットは防げます。
[Swift] フィボナッチ数列のイテレータの実装

# [ウィキペディアより](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%9C%E3%83%8A%E3%83%83%E3%83%81%E6%95%B0)、

フィボナッチ数列 (Fn) は、次の漸化式で定義される：

```math
\left\{
\begin{array}{ll}
F_0 = 0 \\
F_1 = 1 \\
F_n = F_{n-1} + F_{n-2} & (n \geq 2) 　　　　　　　　　　　　　　　　　　
\end{array}
\right.
```

<br>第0～22項の値は次の通りである：

`0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711`

# Swiftでフィボナッチ数列を求める

92項目まで求められたが、それ以降は、Int（64ビット整数）を超えるため終了。

```swift
for (n, f) in Fibonacci().enumerated() {
    print(n, f)
}
```

```terminal:出力結果
0 0
1 1
2 1
3 2
4 3
5 5
6 8
7 13
8 21
9 34
10 55
11 89
12 144
13 233
14 377
15 610
16 987
17 1597
18 2584
19 4181
20 6765
21 10946
22 17711
23 28657
24 46368
25 75025
26 121393
27 196418
28 317811
29 514229
30 832040
31 1346269
32 2178309
33 3524578
34 5702887
35 9227465
36 14930352
37 24157817
38 39088169
39 63245986
40 102334155
41 165580141
42 267914296
43 433494437
44 701408733
45 1134903170
46 1836311903
47 2971215073
48 4807526976
49 7778742049
50 12586269025
51 20365011074
52 32951280099
53 53316291173
54 86267571272
55 139583862445
56 225851433717
57 365435296162
58 591286729879
59 956722026041
60 1548008755920
61 2504730781961
62 4052739537881
63 6557470319842
64 10610209857723
65 17167680177565
66 27777890035288
67 44945570212853
68 72723460248141
69 117669030460994
70 190392490709135
71 308061521170129
72 498454011879264
73 806515533049393
74 1304969544928657
75 2111485077978050
76 3416454622906707
77 5527939700884757
78 8944394323791464
79 14472334024676221
80 23416728348467685
81 37889062373143906
82 61305790721611591
83 99194853094755497
84 160500643816367088
85 259695496911122585
86 420196140727489673
87 679891637638612258
88 1100087778366101931
89 1779979416004714189
90 2880067194370816120
91 4660046610375530309
92 7540113804746346429
```



# イテレータの実装

```swift
@inlinable
public func Fibonacci(upperLimit: Int = .max) -> FibonacciSequence {
    return FibonacciSequence(upperLimit)
}
@frozen
public struct FibonacciSequence: Sequence, IteratorProtocol, Sendable {
    @usableFromInline
    internal let upperLimit: Int
    @usableFromInline
    internal var prev2: Int? = nil
    @usableFromInline
    internal var prev1: Int? = nil
    @inlinable
    internal init(_ _upperLimit: Int) { upperLimit = _upperLimit }
    @inlinable
    public mutating func next() -> Int? {
        if prev2 == nil {
            prev2 = 0
            return prev2! <= upperLimit ? prev2 : nil
        }
        if prev1 == nil {
            prev1 = 1
        } else {
            let (sum, overflow) = prev2!.addingReportingOverflow(prev1!)
            if overflow { return nil }
            (prev2, prev1) = (prev1, sum)
        }
        return prev1! <= upperLimit ? prev1 : nil
    }
}
```

---



↓ たまたま この記事を見て、急に実装してみたくなりました。

https://qiita.com/yoooz/items/cd5ff9c00198ca123afa


なんの参考にもなりませんね。
失礼しました。


---

（2024.7.17追加）↓ 任意精度版を作りました。

https://qiita.com/nak435/items/777a5bc0dcc1f1c5e3dd
th:ifを使った時のaddEventListener

# 結論
```javascript:qiita.js
const 目的のボタン等;
if(目的のボタン等){
    目的のボタン等.addEventListener…
}
```

# 経緯
th:ifを使って表示の切り替えを行うボタンにクリックイベントを追加しようとしたら
```html:sample.html
<div th:if="${boolean}">
    <button id="sample-btn">OK<button>
</div>
```

```
Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
```
と表示されてボタンが想定通りに作動しない。

# 解決方法
どうやらth:ifで非表示にしているオブジェクトは、ないものとしてふるまってしまいjavascriptを読み込む際にイベントを追加しようとしているオブジェクトが見つからなくなってしまうようだ。

そのため、そのオブジェクトが存在するかどうかをif()で判断し、それが存在するときのみイベントを追加するようにすればよいらしい。
```javascript:sample.js
const samplebtn = document.getElementById(sample-btn);
if(samplebtn){
    samplebtn.addEventListener
}
```
#### th:ifの説明
th:if="boolean"
thymeleafで追加されるHTMLの拡張
booleanに入る変数によってオブジェクトを存在させるかどうかを判断できる。

https://qiita.com/sinoofgan/items/d81063b5eda6664a3d1a
SPA・SSR・SSG・CSR・ISRについてまとめてみた

# SPA・SSR・SSG・CSR・ISRについてまとめてみた

## はじめに
この記事では、Web開発におけるレンダリング方式について解説します。具体的にはSPA、SSR、SSG、CSR、ISRの5つのレンダリング戦略について、それぞれの特徴、メリット、デメリット、そしてどのようなアプリケーションに向いているのかを紹介します。これにより、あなたのプロジェクトに最適なレンダリング方式を選択する手助けとなるでしょう。

## SPA（Single Page Application）
### 概要
SPAは、単一のHTMLページを基盤にし、JavaScriptを使って動的にコンテンツを更新するアプローチです。初回アクセス時に必要なリソースを全てダウンロードし、以降は必要なデータだけをサーバーから取得して動的にページを更新します。

### メリット
- **高速なユーザー体験**：ページ遷移が不要で、画面の更新が迅速。
- **通信量の削減**：静的ファイルの再取得が不要。
- **シンプルな開発**：アプリケーションの構造を簡単に把握できる。

### デメリット
- **SEOに弱い**：初期ロード時にコンテンツが無いため、検索エンジンに認識されにくい。
- **初期ロードが遅い**：全てのリソースを初回にダウンロードするため、初期ロードが重い。

### 向いているアプリケーション
- **ダッシュボードや管理画面**：頻繁にデータが更新されるが、SEOが重要でない場合。
- **シングルページのWebアプリケーション**：ユーザーがページ内で多くの操作を行うアプリケーション。

### 使用例
- **Trello**：タスク管理ツールとして、リアルタイムでタスクの更新が必要。
- **Facebook**：ユーザーがページ遷移なく、フィードの更新や友人の投稿に反応することが求められる。

## SSR（Server-Side Rendering）
### 概要
SSRは、サーバーサイドでHTMLを動的に生成し、それをクライアントに返す方式です。これにより、ユーザーがページにアクセスした際、サーバーがデータを取得してHTMLを生成し、ブラウザに送信します。

### メリット
- **SEOに強い**：初期ロード時に完全なHTMLを提供。
- **迅速な初期表示**：サーバーで重たい処理を行うため、ブラウザの負担が少ない。

### デメリット
- **サーバー負荷が高い**：サーバーでの処理が多いため、サーバーのリソース消費が激しい。
- **複雑なセットアップ**：クライアントサイドとサーバーサイドの両方でレンダリングの管理が必要。

### 向いているアプリケーション
- **コンテンツ管理システム（CMS）**：SEOが重要で、コンテンツが頻繁に更新される場合。
- **Eコマースサイト**：初期表示が早く、商品ページがSEOの影響を受けやすい。

### 使用例
- **Next.jsを使用したNetflix**：大量の動画コンテンツを持ち、SEO対策が重要。
- **Nuxt.jsを使用したRecruit**：求人情報サイトでSEOが重要な要素。

## SSG（Static Site Generation）
### 概要
SSGは、ビルド時に全てのページを静的なHTMLとして生成する方式です。これにより、ユーザーがページをリクエストした際には、事前に生成されたHTMLを即座に返します。

### メリット
- **SEOに強い**：静的なHTMLを提供。
- **高速なページ表示**：事前に生成されたHTMLを提供するため、表示が非常に速い。

### デメリット
- **動的なコンテンツに不向き**：コンテンツが頻繁に更新されるサイトには向かない。
- **ビルド時間が長い**：ページ数が多いとビルドに時間がかかる。

### 向いているアプリケーション
- **ブログやドキュメントサイト**：コンテンツの更新頻度が低く、SEOが重要な場合。
- **ランディングページ**：特定のキャンペーン用の静的なコンテンツが多いサイト。

### 使用例
- **Next.jsを使用したHuluのブログ**：静的なコンテンツでSEOが重要。
- **Gatsbyを使用したJAMstackのサイト**：静的なサイトでパフォーマンスを重視。

## CSR（Client-Side Rendering）
### 概要
CSRは、クライアントサイドでJavaScriptを使用して動的にHTMLを生成する方式です。ユーザーがページにアクセスすると、サーバーからJavaScriptファイルがダウンロードされ、その後にJavaScriptが実行されてHTMLが生成されます。

### メリット
- **ユーザビリティが高い**：動的にページを更新できる。
- **SPAに適している**：単一ページでの動的な更新が可能。

### デメリット
- **SEOに弱い**：初期ロード時にコンテンツが無いため、検索エンジンに認識されにくい。
- **初期ロードが遅い**：全てのリソースを初回にダウンロードするため、初期ロードが重い。

### 向いているアプリケーション
- **インタラクティブなWebアプリケーション**：ユーザーが多くの操作を行うアプリケーション。
- **リアルタイムアプリケーション**：チャットアプリやリアルタイムフィードが必要な場合。

### 使用例
- **React.jsを使用したTrello**：タスク管理ツールでリアルタイムの更新が必要。
- **Vue.jsを使用したTwitter**：ユーザーが多くの操作を行うソーシャルメディアアプリケーション。

## ISR（Incremental Static Regeneration）
### 概要
ISRは、SSGとCSRの中間的な手法です。ビルド時に静的なHTMLを生成し、古いHTMLをキャッシュしつつ、必要なページのみ動的に更新します。

### メリット
- **高速なページ表示**：事前に生成されたHTMLを提供するため、表示が非常に速い。
- **リアルタイムな更新が可能**：必要なページのみ動的に更新できる。

### デメリット
- **複雑なセットアップ**：キャッシュ管理と動的更新の管理が必要。
- **サーバー負荷**：動的な更新が頻繁に行われる場合、サーバー負荷が高くなる。

### 向いているアプリケーション
- **更新頻度が高いコンテンツサイト**：ニュースサイトやイベント情報サイト。
- **ミックスコンテンツサイト**：静的と動的コンテンツが混在するサイト。

### 使用例
- **Next.jsを使用したHacker News**：リアルタイムでニュースが更新されるサイト。
- **Next.jsを使用した日経電子版**：更新頻度が高いニュースサイト。

## まとめ
レンダリング戦略を選択するには、ユーザー体験（UX）、SEO、アプリケーションの複雑さ、パフォーマンスなどを考慮する必要があります。それぞれの方法にはメリットとデメリットがあるため、プロジェクトの要件に最適な戦略を選びましょう。また技術選定の機会がある際には実際に検証をして、選定できるといいなと思いました。
AWSをローカル環境で試せるLocalStackの環境構築

# はじめに
こんにちは、H×Hのセンリツ大好きエンジニアです。（同担OKです😉）

AWSを用いた開発、どうしてますか？
Lambdaでバッチ処理を行いS3バケットに保存する、みたいな動作をローカルで試してみたいですよね。

今回は、そんなあなたにピッタリのLocalStackの紹介と環境構築をしていきます！😁

# LocalStackとは

https://www.localstack.cloud/

AWSをローカル環境で開発・テストすることができるサービスです。
正確には、**AWSをローカル環境にエミュレートしてくれるサービス**です。

### ローカルでAWSが試せるので、AWSの利用料は掛かりません！

ただ、サービスによってはLocalStack自体が有料プランになりますのでそこだけ注意🤯

# LocalStackの環境構築
方法はいくつかありますが、今回はDockerを使っていきます！

``` docker-compose.yml
version: "3.8"

services:
  localstack:
    image: localstack/localstack
    ports:
      - "127.0.0.1:4566:4566" # LocalStack Gateway
      - "127.0.0.1:4510-4559:4510-4559" # external services port range
    environment:
      DEBUG: 1
      DOCKER_HOST: unix:///var/run/docker.sock
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
```

これだけでOKです！
`DEBUG: 1`はデバッグモードを有効にしていますが、こちらは無くても動作します！

ポイントだけ説明すると、
``` docker-compose.yml
    ports:
      - "127.0.0.1:4566:4566" # LocalStack Gateway
      - "127.0.0.1:4510-4559:4510-4559" # external services port range
```
`4556`番ポートは、LocalStackのゲートウェイポートになります。
ホストの`4556`番ポートにマッピングしています。


``` docker-compose.yml
    environment:
      DOCKER_HOST: unix:///var/run/docker.sock
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
```
`DOCKER_HOST`は、LocalStackが内部でDockerコンテナを管理するために必要になります。

`volumes`はLocalStackがホストのDockerデーモンと通信するために定義しています。

また、LocalStackではAWS CLIを使用しますのでインストールします。

``` zsh
$ brew install awscli
```

その後、LocalStackが提供している`awscli-local`をインストールします。
これはAWS CLIのラッパーとなります。
``` zsh
$ brew install awscli-local
```

後はDockerコンテナをビルドして起動するだけで使えるようになります！🤩

# S3バケットをLocalStackコンテナ起動時に作成されるようにする
おまけ的な感じです。
S3バケットを作成し、JSONファイルを格納します。

``` docker-compose.yml
version: "3.8"

services:
  localstack:
    image: localstack/localstack
    ports:
      - "127.0.0.1:4566:4566"
      - "127.0.0.1:4510-4559:4510-4559"
    environment:
      DEBUG: 1
      DOCKER_HOST: unix:///var/run/docker.sock
      SERVICES: s3 # 使用するサービスを指定
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "./init-scripts:/docker-entrypoint-initaws.d" # 初期化スクリプトをマウント
      - "./data:/data" # JSONファイルをマウント
```

`SERVICES: s3`で使うサービスを指定します。
今回はS3を使用します。

``` docker-compose.yml
    volumes:
      - "./init-scripts:/docker-entrypoint-initaws.d" # 初期化スクリプトをマウント
      - "./data:/data" # JSONファイルをマウント
```

`init-scripts`ディレクトリをコンテナ内の`/docker-entrypoint-initaws.d`にマウントします。

**LocalStackはこのディレクトリ内のスクリプトを起動時に実行します。**

``` init-scripts/init.sh
#!/bin/bash
# S3バケットの作成
awslocal s3 mb s3://my-bucket

# JSONファイルのアップロード
awslocal s3 cp /data/sample.json s3://my-bucket/sample.json
```

初期化スクリプトで、S3バケットの作成とJSONファイルのアップロードを行います。

``` data/sample.json
{
  "name": "John Doe",
  "age": 30,
  "city": "New York"
}
```

使用するJSONファイルです。

これで再ビルドして、コンテナを起動します。

http://localhost:4566/my-bucket/sample.json にアクセスすると、JSONが出力されていることが確認できます！

# おわりに
ローカル環境でAWSを試せるLocalStackは如何でしたでしょうか？
気になった方は是非触ってみてください！

ここまでご覧いただき、ありがとうございました！
PC付近にはフタ付きの飲み物だけを置こう

**事象**
PCにコーヒーをこぼして破損
緊急作業があったため作業ができなくなり問題

事象を分析した。
リスクにはハザードとペリルという要素があります。
ハザードは、望ましくない事象がおきる可能性を高める状況です。
ペリルは、望ましくない事象を引き起こす直接的な原因です。

引用元:
https://www.arm.or.jp/pdf/resource/ronbun/2004/2004-3-13.pdf

これを元に今回の事故を分析しました。
(という振り…)


**ハザード**
･片道2.5時間かけての客先オフィスへの通勤による疲労
･同僚からハラスメント
･仕事のミスも発覚し謝罪
･リカバリーのため残業決定
･リカバリーに対してまたも先輩からの真綿で首を絞めるようなプッシュ
･この時点で意識レベルが65%くらい

**ペリル**
･しんどいのでコーヒーを用意
･数分仮眠
･頭がぼーっとしたままPCやディスプレイをセッティング
･その時、不注意に置いたペンポーチがコップにぶつかる
･コップはフタなし
･コーヒーがこぼれてPC壊れた
作業できなくなる

**教訓**
･ミスしても落ち着く方法を持つべし
･周囲からプレッシャーかけられても落ち着く方法を持つべし
･PCの周りに置く飲み物はフタ付きの飲み物のみとするべし
Django のダミーデータを雑に作成する

Django で Faker と Factory Boy で雑に作成する。

Factory部分
```python
class ProductFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Product

    name = factory.LazyFunction(fake.sentence)
    description = factory.LazyFunction(fake.paragraph)
    price = factory.LazyFunction(
        lambda: fake.pydecimal(left_digits=10, positive=True)
    )
```


Django コマンドでダミーデータを作成する。以下の実装で10レコード分をDBへ登録する。
```python
class Command(BaseCommand):
    help = "Your custom command description"

    def handle(self, *args, **options):
        authors = ProductFactory.create_batch(10)
```
EntiyFrameworkでCannot determine the frame size or a corrupted frame was received

.NET8.0でEntity Frameworkを使用してMySQLを参照した時、タイトルのエラーが発生

どうやらSSL通信まわりの問題らしく、MySQLの接続文字列に***SSL MODE=Disabled***を追加したら解消した

```
optionsBuilder.UseMySQL("server=db_host;SSL Mode=Disabled;database=test_database;user=user_name;password=your_password
```

ローカルで普通に立ち上げたときは発生しなかったが、Dockerで立ち上げたときに発生

もし有識者の方がいらっしゃいましたらご教示いただけますと幸いですm(__)m
サイバー攻撃や対策について調べてみた

# サイバー攻撃の種類と対策について

## はじめに
サイバー攻撃は日々進化しており、その被害は個人から企業、政府機関に至るまで多岐にわたります。最近ではKADOKAWAが大規模なランサムウェア攻撃を受け、多くのデータが暗号化され、サービス停止や情報漏洩などの被害が発生しました。この記事では、代表的なサイバー攻撃の種類とその対策について調べてみました。

## サイバー攻撃の種類

### 1. フィッシング攻撃
フィッシング攻撃は、偽のWebサイトやメールを使ってユーザーの個人情報（パスワード、クレジットカード情報など）を盗む手法です。

**対策:**
- メールのリンクをクリックする前に、URLを確認する。
- 信頼できるセキュリティソフトを使用する。
- 二要素認証を有効にする。

### 2. マルウェア攻撃
マルウェア（ウイルス、ワーム、トロイの木馬など）は、システムに侵入し、データを盗んだり破壊したりする悪意のあるソフトウェアです。

**対策:**
- 最新のセキュリティソフトをインストールし、定期的にスキャンする。
- 不明なファイルやリンクを開かない。
- OSやソフトウェアを最新の状態に保つ。

### 3. ランサムウェア攻撃
ランサムウェアは、データを暗号化して人質に取り、復号のために身代金を要求する攻撃です。

**対策:**
- 定期的にデータのバックアップを行う。
- セキュリティソフトでリアルタイム保護を有効にする。
- 怪しいメールや添付ファイルを開かない。

### 4. DDoS攻撃
DDoS（Distributed Denial of Service）攻撃は、複数のシステムから大量のリクエストを送信してサーバーを過負荷にし、サービスを停止させる攻撃です。

**対策:**
- CDN（Content Delivery Network）やDDoS対策サービスを利用する。
- ネットワークトラフィックを監視し、異常な活動を検知する。
- フィルタリングを強化して不要なトラフィックをブロックする。

### 5. ゼロデイ攻撃
ゼロデイ攻撃は、公開されていないセキュリティの脆弱性を利用して行われる攻撃です。脆弱性が公になる前に攻撃されるため、非常に危険です。

**対策:**
- 常にソフトウェアを最新の状態に保ち、パッチを即座に適用する。
- 不審な活動を監視し、異常があれば迅速に対応する。

## 具体例：KADOKAWAのサイバー攻撃

2024年6月、KADOKAWAグループの複数のサーバにアクセスできない障害が発生しました。調査の結果、ランサムウェアを含む大規模なサイバー攻撃であると発表しました。

> ### 事業および業務への主な影響
> - **出版事業:** 国内における紙書籍の受注システム、デジタル製造工場・物流システムの機能を停止。受注停止、生産量の減少、物流の遅延が発生。
> - **Webサービス事業:** 「ニコニコ動画」「ニコニコ生放送」「ニコニコチャンネル」などのサービスが停止。ニコニコアカウントによる外部サービスへのログインが不可能に。
> - **MD事業:** 複数のオンラインショップで商品の受注不能や出荷の一部遅延が発生。
> - **経理業務:** 経理システムが一時的に機能停止状態となり、一部の取引先への支払いに遅延が生じる可能性がある。


## 企業の対策

### 1. 攻撃される前の対策実施
- **マルウェア対策:** 従業員への教育、セキュリティソフトの導入。
- **ランサムウェア対策:** 定期的なデータバックアップ、バックアップ先は通常業務領域と切り離す。

### 2. サイバー攻撃を検知するための仕組みづくり
- **システム導入:** IDS/IPSやEDRなどを導入し、不審な動作を検知。

### 3. サイバー攻撃検知後の対応手順の策定
- **対策本部メンバーの選定と意思決定フロー:** 役割を明確にし、意思決定の手順を取り決める。
- **対応手順の明確化:** 被害ごとの対応策を事前に策定。

### 4. 定期的な見直し
- **セキュリティ対策の更新:** 最新情報を入手し、対策をアップデート。
- **リハーサルの実施:** 数年に一度のリハーサルを行い、対策の有効性を確認。

### その他の対策
- **C1WS:** インターネットの脅威からネットワークを保護するクラウドセキュリティサービス。
- **脆弱性診断:** アプリケーションの定期的な脆弱性診断を実施。
- **災害対策環境の準備:** 攻撃を受けた後も別環境でサービス提供ができるようにする。
- **定期的なバージョンアップ:** ソフトウェアや言語の定期的なバージョンアップを行い、サポート期限を意識する。
- **定期的なバックアップ:** 定期的にバックアップを実施し、ランサムウェア対策としてバックアップの状態を確認。
- **本番サーバーのアクセス管理:** 本番サーバーにアクセスする人は名簿に記載し、アクセス管理を徹底する。


## まとめ
サイバー攻撃の種類と対策を理解し、事前に適切な対策を講じることが重要です。
また、システム全体におけるセキュリティリスクみたいな所を一通り分析した上で、優先順位をつけた上で何年間で大体こういう所っていうのを順々に潰していくと、セキュリティに関するリスクっていうのが今の時点と2年後でこれぐらい下げられるんじゃないか。のような全体像を把握して提案できるといいのかなと思いました。
Webセキュリティの基本まとめ

# Webセキュリティの基本まとめ

## はじめに
この記事では、Webセキュリティの基本的な概念と、一般的な攻撃手法とその対策についてまとめます。

## 目次
1. [Webセキュリティの基本概念](#webセキュリティの基本概念)
2. [一般的な攻撃手法](#一般的な攻撃手法)
    1. [SQLインジェクション](#sqlインジェクション)
    2. [クロスサイトスクリプティング (XSS)](#クロスサイトスクリプティング-xss)
    3. [クロスサイトリクエストフォージェリ (CSRF)](#クロスサイトリクエストフォージェリ-csrf)
    4. [ディレクトリトラバーサル](#ディレクトリトラバーサル)
    5. [セッションハイジャック](#セッションハイジャック)
    6. [DDoS攻撃](#ddos攻撃)
    7. [フィッシング](#フィッシング)
    8. [ランサムウェア](#ランサムウェア)
3. [セキュリティ対策](#セキュリティ対策)
4. [まとめ](#まとめ)

## Webセキュリティの基本概念
Webセキュリティは、Webアプリケーションやサービスが外部の攻撃や不正アクセスから保護されることを目的としています。以下の3つの基本概念が重要です。

- **機密性**: データが不正にアクセスされないようにすること。
- **完全性**: データが正確であり、改ざんされていないことを保証すること。
- **可用性**: 必要なときにシステムやデータにアクセスできることを保証すること。

## 一般的な攻撃手法

### SQLインジェクション
**SQLインジェクション**は、攻撃者がデータベースに対して不正なSQLクエリを実行する攻撃です。これにより、データの漏洩や改ざんが行われる可能性があります。

#### 対策
- プレースホルダーを使用する
- 入力データの検証とサニタイズ

### クロスサイトスクリプティング (XSS)
**クロスサイトスクリプティング (XSS)** は、悪意のあるスクリプトをWebページに挿入し、ユーザーがそのページを表示したときにスクリプトが実行される攻撃です。

#### 対策
- 入力データのエスケープ処理
- セキュアなHTTPヘッダーの設定

### クロスサイトリクエストフォージェリ (CSRF)
**クロスサイトリクエストフォージェリ (CSRF)** は、ユーザーが認証された状態で意図しない操作を実行させる攻撃です。

#### 対策
- CSRFトークンの利用
- Refererヘッダーのチェック

### ディレクトリトラバーサル
**ディレクトリトラバーサル**は、攻撃者がファイルシステムの任意のファイルにアクセスするためにディレクトリの階層を移動する攻撃です。

#### 対策
- 入力データのサニタイズ
- ファイルアクセスの制限

### セッションハイジャック
**セッションハイジャック**は、攻撃者がユーザーのセッションIDを盗み、なりすます攻撃です。

#### 対策
- HTTPSの使用
- セッションIDの再生成

### DDoS攻撃
**DDoS攻撃** (分散型サービス拒否攻撃) は、多数のコンピュータを利用してターゲットサーバーに過剰なトラフィックを送り、サービスを停止させる攻撃です。

#### 対策
- トラフィックモニタリング
- フィルタリングルールの設定
- CDNの利用

### フィッシング
**フィッシング**は、信頼できる企業や個人を装ったメールやメッセージでユーザーから個人情報を騙し取る攻撃です。

#### 対策
- メールフィルタリング
- ユーザー教育
- 2段階認証の導入

### ランサムウェア
**ランサムウェア**は、感染したシステムのデータを暗号化し、解除のために身代金を要求するマルウェアです。

#### 対策
- 定期的なバックアップ
- アンチウイルスソフトの導入
- ソフトウェアの定期更新

## セキュリティ対策
Webアプリケーションのセキュリティを強化するための基本的な対策は以下の通りです。

1. **セキュアコーディング**: 脆弱性を回避するためのコーディング手法を採用する。
2. **定期的なセキュリティテスト**: ペネトレーションテストや脆弱性スキャンを定期的に実施する。
3. **アップデートとパッチ管理**: 使用しているソフトウェアやライブラリを最新の状態に保つ。
4. **ログ監視と分析**: システムログを監視し、異常な活動を検知する。

## まとめ
Webセキュリティの基本を理解し、適切な対策を講じることで、外部からの攻撃や不正アクセスを防ぐことができます。また、フレームワークを利用した開発により、基本的なセキュリティ対策が施された状態で開発を進めることが可能です。これにより、セキュアなWebアプリケーションを効率的に構築し、ユーザーの安全を確保することができます。
フレームワークによる開発でどのように対策されているのか、またどのような箇所が漏れるのかなども調べてみたいと思います。
短縮URLサービスの仕組み

# 短縮URLサービスの仕組みについて

## はじめに
短縮URLサービスは、長いURLを短く変換することで、共有や記載を簡単にするツールです。本記事では、短縮URLサービスの基本的な仕組みや、自作する方法、実際の短縮URLの例、そしてセキュリティリスクについて解説します。

## 短縮URLとは？
短縮URLとは、元の長いURLを短く変換したURLです。短縮URLをクリックすると、自動的に元のURLにリダイレクトされ、目的のWebページにアクセスできます。これにより、ソーシャルメディアやメール、メッセージアプリなどでのURLの共有が簡単になります。

## 短縮URLサービスの仕組み

### 1. ユーザーからのリクエスト
ユーザーが短縮URLサービスを利用するとき、まず元のURLをサービスに提供します。このURLは、データベースに保存され、固有の識別子（短縮URL）が生成されます。

### 2. URLの変換
短縮URLサービスは、元のURLを短縮URLに変換する際に以下のようなプロセスを経ます。

- **ハッシュ関数の利用**: 元のURLをハッシュ関数を用いて固定長の文字列に変換します。この文字列が短縮URLの一部となります。
- **ランダムな文字列の生成**: 固定長のランダムな文字列を生成し、それを短縮URLとして使用する方法もあります。
- **データベースに保存**: 短縮URLと元のURLの対応をデータベースに保存します。これにより、短縮URLがアクセスされたときに元のURLにリダイレクトできます。

### 3. 短縮URLの提供
変換された短縮URLがユーザーに提供されます。ユーザーはこの短縮URLを共有したり、利用したりすることができます。

### 4. リダイレクトの処理
ユーザーが短縮URLをクリックすると、以下のプロセスで元のURLにリダイレクトされます。

- **短縮URLの受信**: サーバーが短縮URLを受信します。
- **データベースの照会**: 短縮URLを元にデータベースを照会し、対応する元のURLを取得します。
- **リダイレクト**: サーバーがHTTPリダイレクトを返し、ユーザーのブラウザが元のURLにアクセスします。


<!--
## 短縮URLサービスの自作
短縮URLサービスは比較的簡単に自作できます。以下に、基本的な手順を示します。

### 1. 必要なツール
- Webサーバー（例: Apache、Nginx）
- データベース（例: MySQL、SQLite）
- サーバーサイドプログラミング言語（例: PHP、Python）

### 2. 基本的な流れ
1. **URLの入力フォーム**: ユーザーが元のURLを入力するためのフォームを作成します。
2. **URLの保存**: 入力されたURLをデータベースに保存し、短縮URLを生成します。
3. **リダイレクト処理**: 短縮URLがアクセスされたときに、データベースから元のURLを取得し、リダイレクトを行います。

### 3. サンプルコード（Python Flaskの場合）
```python
from flask import Flask, request, redirect
import sqlite3
import string
import random

app = Flask(__name__)
db = sqlite3.connect('urls.db', check_same_thread=False)
cursor = db.cursor()
cursor.execute('CREATE TABLE IF NOT EXISTS urls (id INTEGER PRIMARY KEY, original TEXT, short TEXT)')

def generate_short_url(length=6):
    characters = string.ascii_letters + string.digits
    return ''.join(random.choice(characters) for _ in range(length))

@app.route('/shorten', methods=['POST'])
def shorten_url():
    original_url = request.form['url']
    short_url = generate_short_url()
    cursor.execute('INSERT INTO urls (original, short) VALUES (?, ?)', (original_url, short_url))
    db.commit()
    return f'Shortened URL: http://localhost:5000/{short_url}'

@app.route('/<short_url>')
def redirect_url(short_url):
    cursor.execute('SELECT original FROM urls WHERE short=?', (short_url,))
    original_url = cursor.fetchone()[0]
    return redirect(original_url)

if __name__ == '__main__':
    app.run(debug=True)

-->


## セキュリティリスク
短縮URLサービスにはいくつかのセキュリティリスクがあります。

### 1. フィッシング攻撃
短縮URLを利用して、ユーザーをフィッシングサイトに誘導する攻撃があります。短縮URLでは元のURLが見えないため、悪意のあるサイトへのリンクを偽装しやすくなります。

### 2. マルウェアの配布
短縮URLを通じてマルウェアを配布することも可能です。ユーザーが短縮URLをクリックすると、マルウェアがダウンロードされるリスクがあります。

### 3. トラッキングとプライバシーの侵害
短縮URLサービスは、ユーザーのクリックデータを収集することがあります。これにより、ユーザーの行動を追跡し、プライバシーが侵害される可能性があります。

### 4. URLの期限切れ
一部の短縮URLサービスでは、URLに有効期限を設定することがあり、期限が切れるとリンクが無効になります。これにより、必要な情報にアクセスできなくなるリスクがあります。

## まとめ
今回短縮URLサービスについてまとめてみました。短縮URLサービスは、長いURLを短くし、共有を簡単にするための便利なツールです。利用する際にはセキュリティリスクにも注意を払いましょう。
NotebookLMのススメ

最近、プログラム以外の調べものが多いのですが、
GoogleのNotebookLMを重宝しています。

https://notebooklm.google.com/

NotebookLMは、あらかじめ入力したテキストやPDF、ウェブページに基づいた回答を行う生成AI, LLMです。

ハルシネーションをほとんど発生しないように調整されているので、
公式や正確な情報を調査したいときに向いています。

---

# (1) 法律について聞く

これが本当に便利。
e-GovのWebページURLを入力して、法的解釈を聞く。

* 個人のWebサイトの解釈よりも信頼性がある
* 弁護士のWebサイトの解釈よりも、一般人にわかりやすい記述になっている。

というところで、法的判断を調べるときに非常に役立ちます。

例として、個人情報保護法のURLを読ませてみました。

https://elaws.e-gov.go.jp/document?lawid=415AC0000000057

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/43a2fd36-5919-0954-f955-3c098b317992.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/90bee070-33cc-9354-0f27-d5a582b767cb.png)

私は個人情報保護法については多少知っているほうですが、
私の回答の肌感覚と完全に合致しています。

# (2) 英語の論文について、日本語で聞く

論文を読むときも便利です。
英語で読ませて、日本語で聞けて、日本語で返って来るのが本当に素晴らしい。

Transformerの論文を試しに入力します。

https://arxiv.org/pdf/1706.03762

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/bded62c1-c378-8330-63ed-dd5bc8c8b64a.png)

回答が本当に正しいか確認するために、
回答の根拠になっている部分の表示をしてくれるのも助かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/adb72f23-da09-4c09-c502-de53c9b57d56.png)


# (3) API仕様書について聞く

ちょっとむずかしめのAPIリファレンスを参照させて
マニュアルとして使う方法もあります。

今回はお試しでAWS boto3 のS3のページを読ませました。

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/37a468d6-7d22-f905-d9a0-f3b9746bbe89.png)

ちゃんとオブジェクトロックするためのメソッドを教えてくれました
厳格に返すあまり、
「これはAPIではない」
との注釈もつけてくれます。

確かにboto3はAPIではなかったですね...（あ、はい、すみません...みたいな気持ちになりました）

これくらいちゃんと厳格なんで、ハルシネーションに対してはかなり安心して使えます

---

# まとめ

自分専用の、簡単に構築できるRAGとして、
NotebookLMは大変素晴らしいサービスです。

法律や、論文など難しめの文章を、
ハルシネーションすくなく解釈してくれるので、
本当に理解力の少ない私のような人間が仕事をするのに向いてます。
フロントエンドチームでコメントアノテーションの利用方針を決めました

# コメント、書いていますか？

僕はコメントを適度に書いています。

ここでいうコメントは、
```
// 定数
```

のように、「ここは〇〇を書くブロックですよ〜」と指し示すものではなくて、
```
// 現状仕方なくこうしています
```
という、補足説明をするためのコメントです。


## コメントを書く基準

基本的には、コードを読んでわかるよう記載、設計にする。
という方針でコードを書いてるつもりですので、必要以上にコメントを書き込むことは無いですが、仕方なく特殊な実装をせざるを得ない場合など、コメントを書くようにしています。

<br>

そのように方針を決めていますので、レビューでも「ここはコメントを書いては？」と提案します。
すると、メンバーから「コメントを残すルールを決めたい」という意見が出てきました。
確かに、個人的な基準をきちんと整理して、チーム内でルール化できれば、最適な開発ができるかもなと思い、ルール化することにしました。
現状、うまく活用できているため、紹介いたします。


## コメントルール

| コメントアノテーション | ルール |
|:-:|:-:|
| TODO  | リリースまでの開発で利用可能|
| FIXME  | 既知の不具合がある　<br> ※不具合のチケット番号を記載  |
| REFACTOR | リファクタリング　<br> ※リファクタリングチケット番号を記載 |
| NOTE  |  任意のコメント |

FIXMEとREFACTORのルールにて、チケット起票漏れを防ぎます。

TODOは、開発中のみ利用を許可しました。リリースするタイミングで残っていることは禁止です。

Github actionsでmainブランチに向けてPR作成時、TODOが残ってるとコメントされるようにするつもりです。（実装を忘れていた。やらねば。。。）

:::note info
vs codeの拡張機能で、todo treeというものを教えてもらいました。便利！

https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree
:::

NOTEは、任意コメントのため、コメントとして残すべきかどうかをしっかりとレビューし、必要がなければ削除するようにしました。


## 参考

個人的に、以下記事のアノテーションを利用していましたので、ルール設定の際に参考にさせてもらいました。

https://qiita.com/taka-kawa/items/673716d77795c937d422


<br >

以上です、みなさま、よきコメントライフをお過ごしください。
TestRailとエクセル・スプレッドシートの比較

## TestRailとは

* テストにかかわる情報を一元管理
* Webブラウザー上でテストケースを簡単に入力や編集可能
* テストケースの管理項目をカスタマイズ可能
* テストケースのバージョンを管理
* CSVやXMLで既存のテストケースをインポート

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133917/16346fa8-a00a-54db-88d2-f271a0f7b5a8.png)

## デモサイト
デモサイトで簡単に試せます。

https://www.techmatrix.co.jp/product/testrail/demo_site.html

## TestRailの機能

|機能|内容
|-|-|
インポート|エクセル可
エビデンス|コピペ可
集計|可
レポート|可|

<br>

## TestRailと表計算の比較
TestTailとスプレッドシート、エクセルなどの表計算と比較してみました。

|項目|TestRail|エクセル
|-|-|-|
わかりやすさ|わかりやすい|表による
手間|少ない|多い
同時編集|できる|
管理|しやすい|しにくい
柔軟性|低い|高い
レポート|標準|個別作成
[MySQL]DATETIME型とTIMESTAMP型の違い

# はじめに
個人開発でDB設計を行っていた際、MySQLのDATETIME型とTIMESTAMP型の違いが曖昧だったため、ここで整理してみました。

# 基本情報
### DATETIME
- 日付と時間の両方を扱うことができる
- サポートしている範囲は `1000-01-01 00:00:00` から `9999-12-31 23:59:59`
- 日時の情報を`YYYY-MM-DD hh:mm:ss`の形式で保存する

### TIMESTAMP
- 日付と時間の両方を扱うことができる
- サポートしている範囲は`1970-01-01 00:00:01` UTC から `2038-01-19 03:14:07` UTC の範囲
- 内部的には1970年1月1日00:00:01 UTC（Unixエポック）からの経過秒数として保存する

# 保存方法の違いについて
結論としては、「タイムゾーンの影響を受けるか」です。
DATETIMEの場合、日本時間（UTC+9）で「2024-07-14 12:00:00」として保存された日時が、アメリカ東部時間（UTC-5）のユーザーから見ても同じ「2024-07-14 12:00:00」として表示されます。この場合、実際の時間のずれ（14時間）が考慮されません。
TIMESTAMP型はUTC（協定世界時）で保存され、サーバーやクライアントのタイムゾーンに基づいて表示(クライアントのタイムゾーンを元に変換)される。

### 実際に検証(※mysql8.2のdocker imageを使用)
テーブル準備

```sql
-- DATETIME用
CREATE TABLE events (
    id INT AUTO_INCREMENT PRIMARY KEY,
    event_name VARCHAR(100) NOT NULL,
    event_date DATETIME NOT NULL
);

INSERT INTO events (event_name, event_date) VALUES ('Meeting', '2024-07-14 12:00:00');

-- TIMESTAMP用
CREATE TABLE logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    message VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO logs (message) VALUES ('System started');
```
タイムゾーンを変えて値を比較
```sql
mysql> SELECT @@system_time_zone;
+--------------------+
| @@system_time_zone |
+--------------------+
| UTC                |
+--------------------+

mysql> select * from events;
+----+------------+---------------------+
| id | event_name | event_date          |
+----+------------+---------------------+
|  1 | Meeting    | 2024-07-14 12:00:00 |
+----+------------+---------------------+


mysql> select * from logs;
+----+----------------+---------------------+
| id | message        | created_at          |
+----+----------------+---------------------+
|  1 | System started | 2024-07-16 12:51:26 |
+----+----------------+---------------------+

-- タイムゾーンを変更
mysql> SET time_zone = 'America/New_York';
Query OK, 0 rows affected (0.00 sec)

-- DATETIMEは変わらない
mysql> select * from events;
+----+------------+---------------------+
| id | event_name | event_date          |
+----+------------+---------------------+
|  1 | Meeting    | 2024-07-14 12:00:00 |
+----+------------+---------------------+

-- TIMESTAMPはタイムゾーンを考慮してくれる
mysql> select * from logs;
+----+----------------+---------------------+
| id | message        | created_at          |
+----+----------------+---------------------+
|  1 | System started | 2024-07-16 08:51:26 |
+----+----------------+---------------------+

```

# summary
### datetimeのメリット
- タイムゾーンの影響を受けず、保存した日時はそのまま保持される
- 幅広い日時範囲をサポートできる
### timestampのメリット
- 異なるタイムゾーンのユーザーに対しても一貫した時間の取り扱いが可能
-> 異なるタイムゾーンのユーザーが存在するシステムでは、TIMESTAMP型を使用する方が適している

## 余談
今までTIMESTAMPとDATETIMEなんて自動更新できるかの違い(updated_atはTIMESTAMPとか🥹)かと思っていたけど、違った。
しかもMySQL8からどちらも自動更新できるようになってました💦

### 参考URL
[11.2.2 DATE、DATETIME、および TIMESTAMP 型(MySQL公式)
](https://dev.mysql.com/doc/refman/8.0/ja/datetime.html)
[11.2.5 TIMESTAMP および DATETIME の自動初期化および更新機能(MySQL公式)](https://dev.mysql.com/doc/refman/8.0/ja/timestamp-initialization.html)
オフラインでのtiktokenの使用方法：キャッシュ設定でSSLエラーを回避する方法

## はじめに

LangChainやChromaDBなどを会社のプロキシ環境下やオフライン環境でなどで使おうとすると、以下のようなSSLエラーが発生することがあります。

```
requests.exceptions.SSLError: HTTPSConnectionPool(host='openaipublic.blob.core.windows.net', port=443): Max retries exceeded with url: /encodings/cl100k_base.tiktoken (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1112)'))
```

これは、内部的にtiktokenを使用する際の通信が原因です。オフライン環境やプロキシ環境下で許可されていない場合、エラーが発生します。

このような場合、必要なファイルを事前にダウンロードし、ローカルキャッシュとして設定することでエラーを回避することができます。

本記事はStackOverflowの[こちらの内容](https://stackoverflow.com/questions/76106366/how-to-use-tiktoken-in-offline-mode-computer)を参考に記載しています。

## エンコーダーのBlob URLからファイルのダウンロード

エンコーディング(テキストをトークンに変更するときのルールのようなもの)に使用されるファイルをダウンロードします。
主な種類は以下です。

| モデル | エンコーディング |
| ----- | --------------|
| gpt-3.5-turbo ~ gpt-4-turbo with vision | cl100k_base |
| gpt-4o | o200k_base |


[こちらのファイル](https://github.com/openai/tiktoken/blob/main/tiktoken_ext/openai_public.py)から該当するエンコーディングのファイルのダウンロード先を確認します。
ここでは`cl100k_base`のファイルをダウンロードします。

```
https://openaipublic.blob.core.windows.net/encodings/cl100k_base.tiktoken
```

上記のURLにアクセスすると`cl100k_base.tiktoken`ファイルがダウンロードされます。

## ファイル名の変更

ダウンロードしたファイル名をリンクのパスのハッシュ値に変更する必要があります。
以下のコードを実行すると`9b5ad71b2ce5302211f9c61530b329a4922fc6a4`が得られるため、この文字列にファイル名を変更します。

```python
import hashlib

blobpath = "https://openaipublic.blob.core.windows.net/encodings/cl100k_base.tiktoken"
cache_key = hashlib.sha1(blobpath.encode()).hexdigest()
print(cache_key)
```

## tiktokenキャッシュの設定

`TIKTOKEN_CACHE_DIR`の環境変数に上記のファイルを置いたディレクトリを指定します。

```python
import os

os.environ["TIKTOKEN_CACHE_DIR"] = <上記ファイルを置いたディレクトリ>
```

## tiktokenの使用

```python
import tiktoken

encoding = tiktoken.get_encoding("cl100k_base")
tokens = encoding.encode("Hello, world")
print(len(tokens))
```

これで、tiktokenをオフラインで使用できるようになります。

また、`TIKTOKEN_CACHE_DIR`を設定しておくことでtiktokenを内部的に使用するChromaDB等であっても冒頭のエラーを回避して使用することができます。
報告のイロハ

# はじめに
報告で意識すべき点や注意点、受け手にとってに分かりやすく書くための方法について記載していく。

ただし、以下記載内容はあくまで記載方法の一例にすぎず、結果的に簡潔で分かり易く書くことが出来れば良いとは思う。
一つの方法として参考にしてもらえれば。

# まずは期日確認
1. いつまでに報告する必要があるか、期日をまずは確認する 
2. 報告は素早く行うこと 
3. 期日前ギリギリに報告しない 

報告内容に誤りがあり、再度対応が必要な場合もあるし、観点が間違っている場合もありえる。そのため、報告が早く出来るのであれば前倒しで報告していくスタイルをとる。

:::note info
対応が完了しても報告することを忘れる、といったことをしない 
もしくは"どうなっているのか状況を聞かれてから報告する"、といったことはすべきではない
:::


# 基本的な書き方 
### 見やすくする 
箇条書き、段落を分けて記載するなど、短く端的に記載する。 
また、報告相手は得てして忙しい人向けの場合が多い。 
（PM/PLなどの役職者向けに報告することが多いと思われる） 

そのため、箇条書きや段落分け、必要に応じて強調したい箇所を色を変えたり太字にすり。"分かり易さ"と共に、”何を伝えたいか”も意識して記載する。

必要に応じて図や表、ScreenShotなどで表現することも検討する。 

### 明確に記載する 
抽象的に記載し、論点がボヤけるような記載の仕方は極力しない（例えば曖昧な言葉を選んでしまったら数字に置き換えて記載するなど可能な限り明確化する）。 
 
### 情報に正確性を持たせる 
不正確な情報を報告しない。 
１つでも誤情報があれば、報告自体の信頼性を失う可能性もあるためだ。
 
また、事実と自分の意見を明確にさせる 。
調査して明確に分からないことも勿論ある。その場合は判明した"事実"と、調査が難しい領域で推測になる自分の"意見"とを明確になるように記載する。 
 
### 目的や宛先 
いきなり書き始めるのではなく、
「何のために書くのか」
「誰に向けて書くのか」
つまり、目的と誰宛てに記載するのかを明確にする。 

:::note info
これは報告相手によって記載内容や書き方が変わってくるため、明確にすべき。 
・PM向け？　それともPL向け？ 
・アプリ側やサーバ側などエンジニア単位のリーダー向け？ 
・テックリード向け？ 
・テスター向け？それともデザイナー向け？ 
:::

### 目的や背景説明 
"結論から記載しろ"とよく言われるが、目的や宛先を加味した上で何の内容について報告するのか一番最初に記載する。 

また、調査事項や問題に関する報告であれば必要に応じて、問題点の背景説明も必要。冒頭に結論だけ書いても、読んだ人はいったい何が書いてあるのか分からないためである。 
　※チャットなどを使用していて、話題となるスレッドですでに背景説明が不要な場合は不要 
 
### 要約する 
報告で何を伝えたいのか要約する（要約した内容が"結果"を記載することが多いことになるかも？）。 
要約の仕方のポイントとして、記載する順番も重要。報告する側が最も伝えたいこと、または報告される側が最も知りたいと思われることから記載した方が分かり易い。 
 
### 詳細化する 
ここまで記載できたら、次にさらに伝えるべきことを一つ一つ詳細にかつ明確に記載する。
内容が長くなりそうであれば、添付ファイルにまとめたり図式化することを検討する。
管理ツールのチケットに詳細を書いて、詳細はこちらとしても良いだろう。
 
### 報告量 
つい長文になりがちだが、重複するが報告相手は得てして忙しい人向けであることが多いと思われる。そのため、可能な限り短く端的にまとめる 
 
### 報告前の見直し 
誤って記載することで意図した記載内容と真逆になることもあるため、報告する前に最低１度の見直しは絶対に必要。 

また、自分が読んだときに分かり易いのか？見にくくないのか？の観点で確認する。

ただし、時間が無かったり緊急性の高い場合も往々にしてあるため、その場合は一旦報告を上げつつ口頭で説明をする、といった２つのアプローチで報告するのもあり。 

# 最後に
報告の基本的な仕方について記載した。
状況によってはスピード重視で対応する必要がある場合や、時間をかけても良いから精度の高い報告をする必要がある場合など、状況によって異なると思う。

その場合は、この記事で記載した記載方法の全てに対応するのではなく、一部だけに特化して記載していければ良いと思う。
機械学習テクニックをマスターしよう

# はじめに
こんにちは！この記事では、色々な種類の機械学習について紹介していきたいと思います。
機械学習は今やテクノロジーの核心部分となっており、その応用は数知れません。日常のアプリケーションから業務効率化まで、私たちの生活に使われている技術なのでぜひ知っていただけると嬉しいです！

# 対象読者
- 機械学習の基礎を理解している方
- 最新の機械学習トレンドに興味がある方
- 実践的な機械学習テクニックを学びたい方

# 目次
1. 機械学習とは
2. 機械学習の紹介
3. 効率的なデータ前処理テクニック
4. モデルの最適化と評価指標
5. 実際にプロジェクトに適用する際のベストプラクティス

# 1. 機械学習とは
まずは基本に戻りましょう。機械学習（Machine Learning、ML）は、コンピュータがデータを使って学習し、アルゴリズムを改善していく技術です。これは大量のデータを用いて訓練され、重要なパターンや洞察を自動的に見つけ出すことができます。
- **教師あり学習**: ラベル付きデータを使ってモデルを訓練し、未知のデータに対する予測を行います。
- **教師なし学習**: ラベルのないデータをクラスター化や次元削減のために使用します。
- **強化学習**: エージェントが環境との相互作用を通じて行動を改善していく方法です。

## 機械学習の基本について
機械学習は、データとアルゴリズムの2つの要素に大きく依存しています。データはモデルの訓練と評価のために使用され、アルゴリズムはこれらのデータをどのように解析し、予測するかを決定します。最もポピュラーなアルゴリズムには、線形回帰、ロジスティック回帰、決定木、サポートベクターマシン、ニューラルネットワークなどがあります。

# 2. 機械学習の紹介
機械学習の分野は日進月歩しており、次々と新しいトレンドが現れています。

## 深層学習（ディープラーニング）
近年、ディープラーニングがますます注目を集めています。大規模なデータセットと強力なコンピュータリソースを使用して、多層のニューラルネットワークを訓練することで、高度な予測や識別が可能になります。

:::note info
ディープラーニングの代表的なフレームワークには、TensorFlow、Keras、PyTorchなどがあります。
:::

## 生成モデルとGANs
生成モデルは新しいデータサンプルを生成するためのモデルです。特に、生成敵対ネットワーク（GANs）は2つのモデルが競い合うことでリアリスティックなデータ生成が可能です。これにより、画像生成やスタイル転送などの応用が進んでいます。

## Federated Learning（フェデレーテッドラーニング）
データプライバシーを保護しつつ分散型学習を行うための技術です。中央サーバーではなく、データ所有者の端末で直接モデルを訓練し、その結果のみを共有することで、プライバシー保護を実現します。

# 3. 効率的なデータ前処理テクニック
データ前処理は機械学習プロジェクトの最も重要なステップの一つです。正しいデータ前処理を行うことで、モデルのパフォーマンスを大幅に向上させることができます。

## 欠損値の処理
データセットにはしばしば欠損値が含まれます。欠損値の処理方法としては、削除、補完、または代替値の使用などがあります。
- **削除**: 行全体または列を削除します。ただし、情報損失のリスクがあります。
- **補完**: 平均値、中央値、または最頻値を使用して欠損値を補完します。
- **代替値**: 特定のアルゴリズムを使用して欠損値を予測し、補完します。

## カテゴリカルデータの処理
カテゴリカルデータは数値データに変換する必要があります。これには、ワンホットエンコーディング、ラベルエンコーディング、ターゲットエンコーディングなどの手法があります。

# 4. モデルの最適化と評価指標
機械学習モデルのパフォーマンスを最大化するためには、モデルの最適化と評価が不可欠です。適切な評価指標を使用することで、モデルの性能を定量的に評価し、改善することができます。

## 評価指標
- **正確度（Accuracy）**: 正しく予測したデータポイントの割合。
- **F1スコア**: PrecisionとRecallの調和平均。
- **AUC-ROC**: 真陽性率と偽陽性率のトレードオフを示す曲線の下の面積。

## クロスバリデーション
モデルの汎化性能を評価する方法として、クロスバリデーションが広く利用されています。データセットを複数の分割に分けて、複数回訓練と評価を行うことで、モデルの過学習を防ぎます。

# 5. 実際にプロジェクトに適用する際のベストプラクティス
理論を学ぶだけでなく、実際にプロジェクトに適用する際のベストプラクティスについても触れておきましょう。

## データ収集と特徴エンジニアリング
高品質なデータを収集し、適切な特徴量を選択することで、モデルの性能を大幅に向上させることができます。特徴エンジニアリングは、ドメイン知識を活かしてモデルの性能を引き出す重要なプロセスです。

## モデルのデプロイメント
モデルを訓練した後は、実際の環境にデプロイメントすることが必要です。これは、Webアプリケーションやモバイルアプリケーションへの統合など、エンドユーザーに対する実用化のためのステップです。

# まとめ
今回は機械学習の基本や少し応用編まで紹介しました。
このブログを機会に機械学習に関心を持っていただけると嬉しいです！
音声ファイルをラウドネスノーマライズして、Whisper文字起こし精度を微増する

Whisperモデルに入力する音声ファイルを色々加工して、文字起こし精度を上げる実験をしていて
ラウドネスノーマライズがまあまあうまく行きました。

---

# pylnでラウドネスノーマライズ

```python
import pyloudnorm as pyln
import soundfile as sf

# ファイル読み込み
y, sr = sf.read("path_to_your_audio_file.wav")

# ラウドネスノーマライズ
meter = pyln.Meter(sr)
loudness = meter.integrated_loudness(y)
target_loudness = -26.0  # （LUFS単位）デフォルトの-23よりもうちょっと小さくしてみました。
normalized_audio = pyln.normalize.loudness(data, loudness, target_loudness)

# 出力
sf.write("normalized_audio.wav", normalized_audio, rate)
```

# 結果確認

Audacityで波形を見てみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/cedcbdb0-827d-0271-1c08-29445e12085e.png)

上がオリジン波形、
下がラウドネスノーマライズ後の波形です。

通常の振幅ノーマライズをしてしまうと、
なんかぶつかったときとかの大きな衝撃音（ほぼ振幅１）を基準値にしてしまうので、
ほとんど波形が増幅されません。

実際の音声部をそこそこ大きくしたいので、ラウドネス知覚レベルのノーマライズを行いました。

---

# 精度上昇の確認

２時間の音声ファイルに対して、
オリジン波形をWhisperモデルで文字起こししたものと、ラウドネスノーマライズしたもので比較しました。

## (1) wordのprobで比較。

文字起こしの精度、ここでは誤変換なく正しく文字起こしできているかの精度を見るために、word内のprob値を参照します。

```python
# 結果のJSONから収集
word_porb_list = []
for seg in result_json["segments"]:
    for w in seg["words"]:
        word_porb_list.append(w["probability"])

# グラフ化
pd.options.display.float_format = '{:.6f}'.format
plt.hist(np.array(word_porb_list), bins=100)
plt.xlim(0.0, 1.0)
plt.show()

# 統計量も表示
pd.DataFrame(word_porb_list).describe()
```

| 項目 | オリジン | ラウドネスノーマライズ |
|:-:|:-:|:-:|
|図|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/ab806a76-25a5-d9c1-92dd-a8aa90f693d7.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/e05c462e-ed1d-574b-4842-e587ad110838.png)|
|count |17506.000000|17516.000000|
|mean 	|0.811445|0.808790|
|std 	|0.280351|0.288111|
|min 	|0.000000|0.000000|
|25% 	|0.711286|0.714275|
|50% 	|0.970335|0.972944|
|75% 	|0.998044|0.998234|
|max 	|1.000000|1.000000|

正直、図からは改善の様子がわかりません。

describe()結果を見ると、
meanが落ちているので、全てのwordの文字起こし精度が良くなっているわけではないですが、
25%と中央値(50%)の精度が上がっているので、（0.30ポイントと、0.26ポイント)
全体的に精度が微増しているような傾向が見られます。
もうすこし詳しく確認します。


## 変換精度 0.7超えについて確認

ただしく変換できてそうな、推定確率0.7を超えた要素のみを取得してみます。

```python
tmp = np.array(word_porb_list)
tmp = tmp[tmp >= 0.7]
plt.hist(tmp, bins=100)
plt.xlim(0.7, 1.0)
plt.show()

pd.DataFrame(tmp).describe()
```

| 項目 | オリジン | ラウドネスノーマライズ |
|:-:|:-:|:-:|
|図|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/86a44e33-1c96-a39b-ef0b-ab839bbb7d6e.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/653e9804-6ef5-18a7-970e-8d2885d0adc5.png)|
|count |13224.000000|13259.000000|
|mean 	|0.954670|0.955299|
|std 	|0.071901|0.072084|
|min 	|0.700109|0.700216|
|25% 	|0.942927|0.945302|
|50% 	|0.991646|0.992563|
|75% 	|0.999112|0.999248|
|max 	|1.000000|1.000000|

やっぱり図からは見えてこないほどの微増ですが、
count数が、全体で10サンプル差だったのが、
0.7以上のそれは、35サンプル差に増えています

雑に25サンプルの誤り変換を修正できたと考えられます。


実際に、下記のようなちょっとした誤変換を修正できていました
```
誤：トランプロジェクトに合うような、
正：そのプロジェクトに合うような
```

ちょっとおまじないライクにラウドネスノーマライズして振幅増幅してWhisperにかけるとよいかもしれません