OmniAICreator/Qiita-1.07M huggingface dataset:
yolo v8でもすみっコぐらしたちをリアルタイムに物体検出してみる

# はじめに

いつの間にやらYolo v8まで出てしまっているので、
Yolo v5で使ったすみっコぐらし学習データを使ってYolo v8のオリジナルデータ検出に挑戦したいと思います。
v5のときと基本やることは変わらないですね。むしろインストールがさらに楽になってます。

https://qiita.com/enya314/items/1bd053d6a81a156ff814

# 開発環境

windows 10 ノートPC（GPUなし）: 画像整理編集、物体検知実施
Google Colabo : モデル学習

# 学習データ

前回作成したyolo v5の学習に用いたすみっコぐらし学習データを利用します。
幸いにもデータ形式は依然と変わっていないようです。
今は学習データ作成にはRoboflowを使うのがよい?

# GoogleColabでの学習実施

## 学習前準備

以前同様GoogleのMyドライブ直下に「sumikko」フォルダを作成して学習データを丸ごと転送しておきます。

この時点ではこんなフォルダ構成

```
sumikko
 | - dataset.yaml
 | - train 学習用画像（100枚ほど）
 |      | - classes.txt クラスラベルの一覧
 |      | - IMG_・・・.jpg　画像ファイル
 |      | - IMG_・・・.txt　ラベリング情報
 |      | - IMG_・・・.jpg　
 |      | - IMG_・・・.txt　
 |　　　　・・・
 | - val 検証用画像（10枚ほど）
        | - classes.txt クラスラベルの一覧
        | - IMG_・・・.jpg　
        | - IMG_・・・.txt
  　　　・・・
```

GoogleColabに接続して新規でNotebookを作成する。
**学習するのでGPUをONにしておく。**

## MyDriveのマウント

データセットを読み込むためにMydriveをマウントします。

```
from google.colab import drive
drive.mount('/content/drive')
```

## GoogleColabでYOLOインストール

```
#pipからyolo v8をインストール
!pip install ultralytics
```

## wandbのインストール

学習結果をリアルタイムで確認するためのツールとなります。
yolo v8でも現在対応しているようです。

使用するには以下のサイトへの登録が必要です。
https://wandb.ai/site
個人で使う分には無料のようです。

    !pip install wandb

Yoloモデルのトレーニング時に、登録したアカウントに学習データをリアルタイムで連携しているようです。
上記サイトにログインすることで学習状況が見られます。

## 学習の実施

※wandbを利用する場合は実行時にアカウント情報を入力する必要があります。
すべてのセル実行等では途中で止まりますのでご注意ください。

```
!yolo detect train data='/content/drive/MyDrive/sumikko/dataset.yaml' model=yolov8s.pt epochs=300 imgsz=640
```

## wandbによる学習推移確認

以下は最終結果ですが、このようなグラフがwandbのダッシュボードでリアルタイムに更新されていきます。

metrics
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131606/ae48be8f-bb4c-fb6d-6593-f7217d0bf5bf.png)

train/val
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131606/f516eb3d-7ec7-8ffb-4219-6e6ebf80fc1c.png)

## 結果をドライブに移動

結果をドライブに移動しておく。
```
!cp -rf /content/runs/detect/train /content/drive/MyDrive/sumikko/result/
```

# ローカルPC側の準備

前回同様にpipで環境構築していく。

## Python環境の準備

64bit版のPythonをインストール
https://www.python.org/

```
# 先に仮想環境を作成(任意のフォルダに移動しておく)
PS C:\yolo_pj> python -m venv yolo_v8
PS C:\yolo_pj> .\yolo_v8\Scripts\activate
```

## yolov8のインストール

Pytorch等必要資材もまとめてインストールされるみたいでｓ。
```
(yolo_v8) PS C:\yolo_pj> pip install ultralytics
```

## モデルの移植

学習時に以下のパスに学習結果を保存していたので
/content/drive/MyDrive/sumikko/results
モデルの場所は以下となります。{name}は学習時に指定したnameとなります。
/content/drive/MyDrive/sumikko/results/{name}/weight/best.pt

モデルをダウンロードしてyolov5フォルダの直下に配置します。
今回は以下の場所
C:\yolo_pj\yolo_v8

# すみっコ検出確認

## 物体検出実行

source=0でカメラ番号を指定、show=Trueにすると画像も併せて表示されます
(show=TrueにしないとDetect結果だけプロンプトに流れます)
confで表示の閾値を指定できます

```
(yolo_v8) PS C:\yolo_pj> cd yolo_v8
(yolo_v8) PS C:\yolo_pj\yolo_v8> yolo detect predict model=best.pt  source=0 show=True conf=0.25
```

## 検出結果

yolo v5と同様にv8でも作成したデータで検知できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131606/1b6ae6ed-06e7-94ce-3eed-a0b4fc6f065f.png)

以上です。お疲れさまでした。
PhotoshopのCMでよく見かける風景画像の季節を変えるやつって何？？実際に調べてやってみました。

![スクリーンショット 2023-10-10 0.35.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/db7f3fae-c5ac-f05a-d4dd-e35aef28e0a4.png)


## はじめに
こんにちは。
Photoshopを模索中のエンジニアです。
最近AI昨日が増えてきて色々ついていけるようにしたいものです、、！！
そのためにもQiitaでアウトプットとして記事を書いていこうと思います。

## 概要
今回は最近AdobeのCMで流れてくる「風景の季節を一瞬で変える機能」が毎回気になって、実際に試してみました。

## 風景ミキサー
使われている機能は「風景ミキサー」というものでした。
Photoshop 2022 に追加されたらしいですね。(全然最近の機能じゃなかった、、)
2022年ではかなり注目の機能だったみたいですね！！

## 風景ミキサーの使い方
1\. 変更したい画像を開く
2\.「フィルター」→「ニューラルフィルター」→「風景ミキサー」
3\. 風景ミキサーのプリセットの中から好きなものを選択

以上です！！
実際に画像つきで説明していきます！

### 1\. 変更したい画像を開く
![スクリーンショット-2023-10-09-22.59.38.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/b5052c96-e22b-25be-6b33-84076083093b.jpeg)
今回は緑の山の風景画像を

### 2\.「フィルター」→「ニューラルフィルター」→「風景ミキサー」
![スクリーンショット 2023-10-10 0.11.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/345ebc0b-f7e1-b384-a452-7a49fe6e8929.png)
「フィルター」→「ニューラルフィルター」を選択します。
![スクリーンショット-2023-10-10-0.14.31.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/3bc97d9a-e807-0e3c-15bb-f237051a4291.jpeg)
「ニューラルフィルター」が開かれます。
そこから風景ミキサーを選択してください。

### 3\. 風景ミキサーのプリセットの中から好きなものを選択
![スクリーンショット 2023-10-10 0.51.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/9535a1ef-d752-5973-d96b-b9725f554ec5.png)
![スクリーンショット-2023-10-10-0.32.47.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/71d4b81b-fe61-55da-ec0a-f2583a311651.jpeg)
押下して画像の風景を変えることが出来ました！！

## 最後に
今回やってみて思ったのですが、反映されないプリセットもあったり、イメージしてたものと違うもの(上記だと岩になるのかなと思ったら茶色い風景になっただけ)だったりして思ったものと違う画像が出来ました。
もう少し時間ある時調べてみようと思います、、！！！！
AI Builder カスタム カテゴリ分類モデルの検証(Azureとの比較)

今回、AI Builderのカスタムモデルの一つカテゴリ分類の検証結果をまとめます。

# カテゴリ分類モデル検証
カテゴリ数３でカテゴリごとに100のデータセットを用意しました。
結果、パフォーマンスとして計算される、F1スコアは0.889となりました。
（与えるデータによってスコアはもちろん変わります。）

このデータには日本語を使っていますが、実はカテゴリ分類は日本語対応していません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/02e1b3fa-391c-35d2-9674-09386b1fad1b.png)

どうしているのかというと、、
Power Automateのフローの中で翻訳コネクタを使用して、一度英語に翻訳し、その内容をモデルに認識させて、その認識結果によってカテゴリに振り分けています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/3a16e21b-3654-9779-251c-1735b2cdb7ef.png)


# 日本語データをそのまま入れるとどうなるのか

英語しか対応していないカテゴリ分類モデルに日本語データをそのまま入力した時は0.43しかF1スコアが出ませんでした。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/ce4e9ae6-2834-c5c1-7a7f-1ca07f7db97a.png" width=60%>


# データ数によるパフォーマスの結果
カテゴリごとのデータ数は最低で10となっていますが、最低データ数でどれだけ精度が出るのか検証してみました。
結果は以下の画像のようになりました。
最低データ数（10）の時72、データ数100の時88です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/c2e3b07a-3196-ed15-1e96-55bc0272fc54.png)

# Azureとの比較

Azureにもカスタムテキスト分類モデルがありますが、AI Builderと比較してどうなるのか試してみました。
データ数はカテゴリごとに150で、分類数は同じ3つです。
Azureのカスタムテキスト分類モデルは日本語対応しているので、日本語のままデータを与えています。（ここの差分はあるかもです。）

結果は以下のようになりました。
F1スコア出ていますが、90%ということで、AI Builderの88%とあまり変わらないですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/bbb0be27-8c27-7aa2-58e9-04f6feb9e874.png)

最初はAzureで実装しようとしたのですが、翻訳するだけでAI Builderでも変わらないレベルのモデルができ
そうでしたので、今回はAI Builderを使ってアプリを作成しています。

### AI Builderを使うメリット・デメリット
Azureと比較したときのAI Builderを使うメリット・デメリットをまとめてみます。
メリット
・知識が必要な箇所は省いた直観的な操作
・データ少なくても対応
・トレーニング時間少ない

デメリット
・ブラックボックス化しやすい
・カスタマイズできないので言語対応などの制限がつく

# まとめ
AI BuilderだとAIの知識がなくても構築できるというところで初心者でもAIをアプリやフローに取り込みやすいです。
AI機能を入れ込んでアプリ・フローを作りたいというときはAI Builderを思い出してみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/5f3ad928-a7f1-6740-ba23-c46d4e43af01.png)
プロジェクトでの工数やスケジュールを決める際に考えること

# スケジュールを決める時にどうするか

スケジュールを決める際に、ウォーターフォール開発とアジャイル開発の側面からの決め方があると思う。
どちらがいいかはその時々によるが、納期、工数、メンバーのレベル、実現可能性、目標等を元に考えるのがいいのだと思う。

## 不確実性を扱いたくないウォーターフォール
ウォーターフォールについて軽く触れておく、

>ウォーターフォール開発の骨子は、プロジェクトの立ち上げからソフトウェアの開発までの「ソフトウェア開発ライフサイクル（SDLC: Software Development Life Cycle）」を複数の工程に区分し、上流工程から下流工程へと順番に進めていく点にあります。

ウォーターフォールの考え方は下記のような感じ。よくV字モデルで語られることが多い。

実装工程：要件定義　ー＞　　外部設計　ー＞　内部設計　ー＞　実装
テスト工程：単体テスト　ー＞　結合テスト　ー＞　システム/受け入れテスト

左側の開発フェーズは、それぞれのテストに対応している。

要件定義　ー＞　システム/受け入れテスト
外部設計　ー＞　結合テスト
内部設計　ー＞　単体テスト


実際には大規模なWEB開発において複雑性が増しているので、各レイヤで求められるスキルももちろん増大しているし、不確実性ももちろん高くなる。だいたいそうなるとスケジュール通りには行かずに炎上して同じことを繰り返すようになる。昨今の開発において運用するにはかなり求められるレベルは高くなる

## なぜうまくいかないのか

**実行したタスクに対してのスケジュールやタスク自体に関して検証をしないから**
**お互いの合意形成が圧倒的に足りていないから**

だと思う。

## 本当のウォータフォールが成立する組織ってなんだろう
この考え方は各レイヤにおいて、本当のプロフェッショナルな組織でないと実現が不可能に思える。（もちろん簡単なアプリケーションなどでは可能かもしれない。）
そうでなければ実装の漏れや不確実性に対しての対処が後手に回り、技術的負債、納期に苦しめられる。

ウォーターフォール開発においては以下が重要だと思う。
 - 各レイヤにおける明確な定義、合意
 - できる限りの不確実性が排除された工数管理
 - 各レイヤにおける数字の見える化（上流であれば流入バグ数、下流であれば流出バグ数など）
 - 起きた問題に対してのトレーサビリティの管理

様々な方法で工数を算出する方法はあると思うが、その組織においての工数を測るには仮説検証しかない。
これがそもそもできない組織の大規模開発は破綻、収束するまで地獄のような時間をかけるしかない。

つまり大規模開発というのは安易にできるものではない。

## アジャイルをどのように活用するか
アジャイル開発宣言で語られている事項として下記がある。

>私たちは、ソフトウェア開発の実践
あるいは実践を手助けをする活動を通じて、
よりよい開発方法を見つけだそうとしている。
この活動を通して、私たちは以下の価値に至った。
>プロセスやツールよりも個人と対話を、
包括的なドキュメントよりも動くソフトウェアを、
契約交渉よりも顧客との協調を、
計画に従うことよりも変化への対応を、
価値とする。すなわち、左記のことがらに価値があることを
認めながらも、私たちは右記のことがらにより価値をおく。

なるべく「価値」のあるものに関して、きちんと開発者、顧客に合意できる形の成果物にして合意することこそ大事だと書いてあるように解釈している。アジャイルにも仮説と検証が必要であり、スクラム開発の考え方と一致している。

たとえば以下のような開発のスケジュールだとどうだろうか。（かなり簡略にしている。あくまで考え方の話）

| タスク | 10/1 | 10/2 |　10/3 | 10/4|
|:-----------|------------:|:------------:|:------------:|:------------:|
| 要件定義    　| ○        　|          |      |        |
| 外部設計     |    |○   |      |      |
| 内部設計      |     |       |○       |        |
| 実装         |    |    | | ○     |

この場合に確認したいことがいくつかある。
 - なぜ各タスク1日で終わると思ったのか？（根拠）
 - 1日で終わるとして、各レイヤでどこまでやることをゴールとするのか？（目標）
 - もっとタスクを分解してフィジビリを高められないか？（実現可能性）

これで根拠がそもそもない、ミスリードな根拠を提示すると、そもそもスケジュールを引く意味はない。
（それやるぐらいなら手を動かせ、となってしまう。）

>「自分が思う観点と、他人が思う観点の議論と認識合わせ」
「実現可能性に対しての仮説と検証」

これらが工数やスケジュールを引く時に大事なポイントだと思いました。

・自分や相手にとって、どこまでできたら価値があるのか？
・相手や他の人にとって、できたものに関して合意ができるのか？
・その価値を届けることができると思った根拠は？

これらを確認するタスクをフローとして乗せていきたいですね。
Poetryで追加したライブラリを削除する

ちょっと困ったことがあったのでメモとして残しておく。

Poetryで追加したライブラリを削除したくなったことがあると、ライブラリ名を指定して
```
> poetry remove パッケージ名
```
で削除することができる。

しかし、Poetryで作成した仮想環境が必要なくなることもある。そんな時ライブラリ全てを削除したい場合はどうしたらいいか？というと次のコマンドを叩くと解決してくれる。
```
> poetry env remove --all
```

一括削除する方法がわからなくて30分も時間を費やしてしまった。

参考: [poetry env remove --all?](https://github.com/python-poetry/poetry/issues/3208)
中心極限定理の証明の文献

中心極限定理は統計学の定理の中で最重要定理と言っても過言ではないほど重要な定理で、いわゆる教養レベルの本でもだいたい以下のような書き方で必ず出てきます。


```math:
確率変数X_1, X_2, ..., X_nが互いに独立で、平均\mu, 分散\sigma^2であるような同一の確率分布に従うものとする。
```
```math:
nが十分に大きいとき、平均\overline{X}は近似的に正規分布N(\mu, \sigma^2/n)に従う。
```
しかし、その証明は教養レベルの統計学の範囲を大きく超えます。


ここでは、証明が気になった場合の参考文献を記載しておきます。


## だいたいこれを読んでおけば大丈夫
完全な証明ではないですが、以下の2冊にはかなり詳しい説明があります。また、これらの本では「近似的に従う」ではなく「分布収束する」という言葉を使うようになります。

・竹村 彰通：新装改訂版 現代数理統計学, 学術図書出版社, 2020.

・久保川 達也：現代数理統計学の基礎,  共立講座 数学の魅力, 2017.

後者の本には中心極限定理の一般化についても解説があります。


## さらに詳しい説明

証明についてさらに詳しい説明が以下の本にあります。

・駒木文保, 清　智也：確率・統計Ⅲ　東京大学工学教程, 丸善出版, 2020.

余談ですが、この本では中心極限定理(という単語)が索引に載っていません。


## 完全な証明

完全な証明が載っているのは、例えば以下の本です。

・小谷眞一：測度と確率（岩波講座, 現代数学の基礎5), 岩波書店, 2005.
C++ 競プロ　学習記録#3

# 集合
* 重複無しの配列の問題
重複する要素のない、「集合」を用いた。
重複のない配列、string型の順序付き配列、計算量を考えるときに用いる。
#include \<set>
set\<型> s;

* for文で全要素の参照
for(auto it = s.begin(); it != s.end(); it++) {
    cout << *it;
}
または
for(auto x : s) {
    cout << x << endl;
}
* 要素追加
s.insert(要素);

* 要素削除
s.erase(要素);

## 参考
[C++のstd::setの使い方について詳しく解説](https://af-e.net/cpp-stl-set/)
せんせー、リキッドクリスタルディスプレイってなに？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/2c47de5a-d81a-78f9-53c1-4d31d8398c36.png)

キーンコーンカーンコーン...
授業が始まります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/be1492ca-910f-2708-d0fa-8fcfcf14af73.png)

せんせー、リキッドクリスタルディスプレイってなに？

# リキッドクリスタルディスプレイとは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/da229491-9c49-fb7a-a542-417180e256a7.png)

## リキッドクリスタルディスプレイって何？

みんな、テレビやタブレット、スマートフォンの画面を見たことがあるよね？その画面を作っている技術の一つが「リキッドクリスタルディスプレイ」だよ。名前はちょっと難しいけど、「液体の結晶」を使って色んな色や形を表示する魔法の画面と思えばいいよ。

## どういうこと？

このLCDは、特別な液体（リキッドクリスタル）を使って、光の通り方を変えることで、いろんな色や画像を作り出すんだ。電気の力で、この液体の向きを変えて、画面に色を表示させることができるのよ。

## どうしてそれがすごいの？

昔のテレビは大きくて重かったけど、LCDのおかげで、薄くて軽いテレビやスマートフォンが作れるようになったんだ。そして、はっきりとしたきれいな画像を見ることができるよ。

## だから、リキッドクリスタルディスプレイってなに？

リキッドクリスタルディスプレイは、特別な液体を使って、色んな色や画像を表示する魔法の画面のことなんだ。

# まとめ

このように、リキッドクリスタルディスプレイは、私たちが日常でよく見るテレビやスマートフォンの画面を作る技術。それがあるおかげで、私たちはきれいな画像や動画を楽しむことができるんだよ。
【Zod】パスワードのバリデーション


以下のようにすることでパスワードと確認用パスワードが一致していることを確認できます。

```js
export const changePasswordSchema = z.object({
    password: signUpSchema.shape.password,
    passwordConfirmation: z.string()
  })
  .refine((data) => data.password === data.passwordConfirmation, {
    message: 'パスワードが一致しません',
    path: ['passwordConfirmation'],
  })
```
私は小さいLinuxのサイバー セキュリティのゲームを書きました！

私は小さいLinuxのサイバー セキュリティのゲームを書きました！

それは端末のゲームです

実行ファイルは[ここに](https://git.sr.ht/~alienagain/Broken-spaceship/tree/master/item/src/EXECUTABLES_RELEASE)です
 ソースファイルは[ここに](https://git.sr.ht/~alienagain/Broken-spaceship/tree/master/item/src/CODE)です

![](https://s3.bskstorage.com/sakura/backspacekey/4325d1e3-28ad-4945-8a3e-4c8773dd50fb.webp)
![](https://s3.bskstorage.com/sakura/backspacekey/4777576b-be1b-44a5-82ca-6cb998fa75a2.webp)
![](https://s3.bskstorage.com/sakura/backspacekey/5b5466f6-d752-4f11-957e-f390ceabd06e.webp)


[Misskey](https://misskey.backspace.fm/)もみてください
FlaskとOpenAI APIで構築：効率的なメール作成アシスタント


# プロジェクト名: 日本語メール作成AI

## はじめに

本プロジェクト「日本語メール作成AI」は、ユーザーが日本語でメールを簡単かつ効率的に作成できるWebアプリケーションです。OpenAI APIを利用したメール生成機能、絵文字追加機能が含まれています。このプロジェクトは現在、[mailsakusei.com](https://www.mailsakusei.com) で無料で公開されています。

## 使用技術

- **バックエンド**: Python Flask
- **フロントエンド**: HTML5, JavaScript (jQuery), Bootstrap
- **API**: OpenAI API

## セットアップ方法

1. **リポジトリのクローン**

    ```
    git clone [https://github.com/ryoshumei/mailsakusei.git]
    ```

2. **依存関係のインストール**

    ```
    pip install -r requirements.txt
    ```

3. **環境変数の設定**

   OpenAI APIを使用するため、APIキーを環境変数として設定してください。
   
    ```
   openai.api_key = os.getenv('OPENAI_KEY')
    ```

4. **アプリケーションの実行**

    ```
    python app.py
    ```

## 機能

1. **文字数カウンター**: テキストエリアに入力された文字数をカウントし、上限を500文字と制限します。
2. **自動メール生成**: 入力されたテキストを元に、OpenAI APIを使用して自動でメール文を生成します。
3. **絵文字を入れる、もっと丁寧に調整**: 生成されたコンテンツをOpenAI APIを使用して調整します。 

## 使用方法

1. Webページにアクセスし、提供されたテキストエリアにメッセージを入力します。
2. 「作成」ボタンをクリックすると、自動生成されたメール文が表示されます。

## スクリーンショット

![Weixin Image_20231009233600.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533761/c9b1a00b-35d6-3913-0042-7e4a5f239771.jpeg)


## 公開

このプロジェクトは[mailsakusei.com](https://www.mailsakusei.com)で無料で公開されています。ぜひアクセスしご利用ください。

## おわりに

「日本語メール作成AI」は、日本語でのメール作成をサポートするシンプルなツールです。今後、機能を拡張して、ユーザーがさまざまなシチュエーションで便利に使えるツールにしていきたいと考えています。
【Python】OpenCVで出力したMP4Vの動画が再生されない場合の解決策

# はじめに
PythonでOpenCVを使って画像をMP4形式の動画に変換したところ、フォト（Windowsアプリ）では表示されるが、Telegram上では表示されないという挙動が怪しいファイルになってしまった。
結論から述べるとコーデックの形式が悪かったのだけど、少し面倒だったので解決策を残しておく。

## 実行環境
- Windows 10
- Python 3.10.6
  - opencv-python 4.8.1.78

## コード
実行したコードは以下の通り。

```python

# 省略

_MP4V = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')

def create_mp4_from_images(root_dir: str, out_path: str, exts: list[str]=['.png'], codec=_H264, fps: float=30.0, recursive: bool=False) -> None:
  # フォルダから画像ファイルを抽出
  image_path_list = sorted(glob_with_exts(root_dir, exts, recursive))
  # 見つからない場合はエラー
  if len(image_path_list) == 0:
    print('no such image files')
    return
  # 一つ取り出して動画の縦横サイズを取得
  height, width, _ = cv2.imread(image_path_list[0]).shape
  writer = cv2.VideoWriter(out_path, codec, fps, (width, height))
  for image_path in image_path_list:
    image = cv2.imread(image_path)
    writer.write(image)
  writer.release()
  print(f'{out_path} created')

# 省略

if __name__ == '__main__':
  create_mp4_from_images('C:/Users/xxx/downloads', 'C:/Users/xxx/downloads/xxx.mp4', codec=_MP4V)
```

## エラー内容

これで動画を出力するとフォトでは普通に表示されるが、ブラウザ版のTelegramでは以下のエラーメッセージが出て表示されない。

```
Unfortunately, this video can't be played on Telegram Web.
Try opening it with our desktop app instead.
```

# 原因と解決策
**MP4V形式**は大方のブラウザで対応していないため、**H264形式**で出力する必要がある。
H264形式で出力するには`cv2.VideoWriter_fourcc('m', 'p', '4', 'v')`を`cv2.VideoWriter_fourcc('h', '2', '6', '4')`に変更すればOK…という訳にはいかない。変更して実行すると下記のエラーメッセージが出力されて動作しない。

```console
Failed to load OpenH264 library: openh264-1.8.0-win64.dll
        Please check environment and/or download library: https://github.com/cisco/openh264/releases

[libopenh264 @ 000001f0b4d19880] Incorrect library version loaded
[ERROR:0@0.011] global cap_ffmpeg_impl.hpp:3076 open Could not open codec libopenh264, error: Unspecified error (-22)
[ERROR:0@0.012] global cap_ffmpeg_impl.hpp:3093 open VIDEOIO/FFMPEG: Failed to initialize VideoWriter
```

これを解決するため、エラーメッセージに従ってopenh264ライブラリを下記の手順で配置してやる必要がある。

## openh264ライブラリ配置手順

1. [github cisco/openh264](https://github.com/cisco/openh264/releases)にアクセス
1. エラーメッセージに表示されているライブラリ名を確認（上記例だと`openh264-1.8.0-win64.dll`）
1. releases内を確認して同名の**ライブラリ名.bz2**をダウンロード（Releaseバージョン一番下のAssetsの矢印をクリックすれば展開されてダウンロードリストが表示される）
1. ダウンロードしたファイルを`7zip`等で解凍
1. 解凍した*.dllファイルをPythonをインストールしたフォルダに配置（Pythonのインストール先はコマンドプロンプトで`python -c "import sys; print(sys.base_prefix)"`で確認可能）

上記手順を踏むとCisco製のOpenH264ライブラリを使っていますというメッセージ共にH264形式の動画が出力される。

```console
OpenCV: FFMPEG: tag 0x34363268/'h264' is not supported with codec id 27 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x31637661/'avc1'

        OpenH264 Video Codec provided by Cisco Systems, Inc.
```

# 参考
- [Shikoan's ML Blog「OpenCVで作成した動画がブラウザで正常に表示できない場合の解決法」](https://blog.shikoan.com/opencv-h264/)
[Unity]Quaternionで角度を変更する

# 概要
QuaternionでY軸を中心に回転させるサンプルコードです。
# 本文
```cs
using UnityEngine;

public class Spawner : MonoBehaviour
{
    [SerializeField] private GameObject prefab;

    private void Start()
    {
        // 基本位置で生成
        Instantiate(prefab, transform.position, transform.rotation);
        // Y軸を中心に90度回転させて生成
        Instantiate(prefab, transform.position, transform.rotation * Quaternion.AngleAxis(90, Vector3.up));
    }
}
```
Quaternion.AngleAxisの部分に注目します。
```cs
Quaternion.AngleAxis(90, Vector3.up)
```
Quaternionで回転する時はプラスじゃなくて掛け算をするのがポイントです。Vector3.upはVector3(0, 1, 0)と同等です。この部分を変更すればX軸やZ軸を中心に回転させることもできます。


小判オブジェクトを90度回転させて生成する事ができました。
![スクリーンショット 2023-10-09 23.23.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/2a679ccc-c2fc-9d45-d19c-1a33abcb7543.png)
Power AutomateでForms→承認→SharePoint Onlineに登録

![スクリーンショット 2023-10-09 232527.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119709/83159138-a91b-b9b9-e426-490e30c3fa25.png)
When a new response is submitted
Get response details
開始して承認を待機
condition＝Approve
回答数　承認者
若手エンジニアに聞きたい、同期/非同期処理って説明できますか？？

# はじめに

1年間モバイルアプリ開発をしてきて、非同期処理ではないと期待値を取れないシーンにいくつか立ち会ってきました。

ただ、非同期処理にしたことでシステムがどういう流れで実行されているのか、完全に理解ができていないっていうのが本音です。

後輩に説明を求められて答えられないなんて格好悪いことしたくないので、この機会に完全に理解してみようと思います！！

# 概要

この記事は、ChatGPTとネット検索で、同期/非同期処理の概念と、後半に実際にコードを動かした動作結果をまとめています。

初心者向けの記事になりますので、ベテランエンジニアの方は、説明が甘い箇所がありましたらコメントにてご教授いただけると幸いです！！

# 一旦ChatGPTに聞いてみた

※記事全体が長くなるので、回答をトグルにします。

### 同期処理を200字以内で説明してください。

<details><summary>同期処理とは</summary>

```「同期処理は、複数のプロセスやスレッドが共有リソースにアクセスする際に、競合状態を避けるための仕組みです。これにより、リソースへのアクセスが順序よく管理され、予測不可能な結果やデッドロックを防ぎます。一般的な同期手法には、ミューテックス、セマフォ、条件変数などがあります。同期処理は、並行プログラムの安定性と正確性を確保し、競合や混乱を回避するために不可欠な要素です。」```

</details>

### 非同期処理を200字以内で説明してください。

<details><summary>非同期処理とは</summary>

```「非同期処理は、コンピュータープログラム内で、待機しながら他のタスクを実行できる方法です。これにより、長時間かかる操作（例：データベースアクセス、ネットワークリクエスト）を実行中に他の処理を進められ、アプリケーションの効率と応答性を向上させます。非同期処理では、非同期タスクが完了したときにコールバック関数を呼び出し、その結果を処理します。非同期プログラミングはウェブアプリケーション、GUIアプリケーション、ネットワーク通信、ファイル操作など多くの場面で使用され、ユーザーエクスペリエンスの向上とアプリケーションのスケーラビリティを支えています。」```

</details>

### 同期処理と非同期処理の違いを300字以内で説明してください。

<details><summary>同期処理と非同期処理の違い</summary>

```「同期処理と非同期処理は、プログラム内のタスクや操作を管理する方法において異なります。以下はその違いを要約した説明です。```

```同期処理:同期処理は、タスクが順番に逐次実行され、一つのタスクが終了するのを待ってから次のタスクが実行される仕組みです。つまり、タスクAが実行中の間、他のタスクBは待機状態にあり、Bが開始するのはAが完了してからです。同期処理は処理の順序が明確で安定しており、競合状態やデッドロックが発生しにくい利点がありますが、一つのタスクの完了を待つため、効率が低下する可能性があります。```

```非同期処理:非同期処理は、複数のタスクや操作が同時に進行し、一つのタスクが完了するのを待つ必要がありません。タスクは非同期に実行され、待機せずに他のタスクを進行できます。非同期処理は非常に効率的で、リアルタイム性が高い反面、タスク間の相互作用や競合状態を適切に管理する必要があります。コールバック関数やPromiseなどが使用され、タスクの完了を通知し、結果を処理します。```

```要するに、同期処理はタスクを順序立てて実行し、非同期処理は複数のタスクを同時に進行させます。選択はタスクの性質と目的に依存し、効率性とコントロール性のバランスを考慮する必要があります。」```

</details>

## 結局どういうことなの？？
ChatGPTの回答を読んでくださった方はわかると思いますが、初心者からして分かりずらいですよね(苦笑)

じゃあ結局どういうことかっていうと、以下です。

### 同期処理

同期処理は、**同時に2つ以上の処理を実行せず、先頭から順番に一つずつ処理が実行していきます！**


### 非同期処理
非同期処理は、先頭から順番に処理が実行されるが、**1つの処理の完了を待たずに、並列して複数の処理を実行することができます！**

## 試してみた！！

以下の動作確認は、すべてFlutterでの実行結果となります。

### 準備

以下の2つのメソッドを用意します。
func1が非同期処理のメソッド、func2が同期処理のメソッドです。

```dart
Future<void> func1() async {
    return Future.delayed(const Duration(seconds: 2), () => print('func1が終了'));
}

void func2() {
    return print('func2が終了');
}
```

上記2つを実行してみます。

### 非同期処理のメソッドを実行
```dart
TextButton(
    onPressed: () {
      print('=処理開始===');
      func1();
      print('=処理終了===');
    },
    child: const Text('実行'),
),
```
func1の処理が、2秒間待って実行される処理になっていますが、非同期処理となっているので、待機時間に次の処理(今回で言うと処理終了のログ)が実行されるので、実行結果はこうなります！

```
I/flutter ( 4840): =処理開始===
I/flutter ( 4840): =処理終了===
I/flutter ( 4840): func1が終了
```
### 同期処理のメソッドを実行

```dart
TextButton(
    onPressed: () {
      print('=処理開始===');
      func2();
      print('=処理終了===');
    },
    child: const Text('実行'),
),
```
こちらは単純に、同期処理なので、func2の実行が完了後、処理終了のログ表示が実行されます。実行結果はこうなります！

```
I/flutter ( 4840): =処理開始===
I/flutter ( 4840): func2が終了
I/flutter ( 4840): =処理終了===
```

## 最後に

以上となります！
気が向いたら更新していきます
【React】条件付きレンダー３つのパターン

:::note
Reactではアプリケーションの状態に応じて、その一部だけを描画することが可能。
Reactにおける条件付きレンダーはJavaScriptにおける条件分岐と同じように動作する。
:::

https://ja.legacy.reactjs.org/docs/conditional-rendering.html

## 要素変数
:::note
要素を保持しておくために変数を使うことができる。
これは、出力の他の部分を変えずにコンポーネントの一部を条件付きでレンダーしたい時に役立つ。
:::

ログアウトとログインボタンを表す以下のような2つの新しいコンポーネントを考える。
```react
function LoginButton(props) {
  return (
    <button onClick={props.onClick}>
      Login
    </button>
  );
}

function LogoutButton(props) {
  return (
    <button onClick={props.onClick}>
      Logout
    </button>
  );
}
```

そして以下のLoginControlは現在のstateによって` <LoginButton /> `もしくは `<LogoutButton />` の一方をレンダーする。
```react
class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;
    let button;
    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }

    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );
  }
}
```



## 論理&&演算子によるインラインIf
:::note
中括弧で囲むことで、JSXに式を埋め込むことができる。これにはJavaScriptの論理`&&`演算子も含まれる。
これは条件に応じて要素を含めたい時に便利。
:::

```react
function Mailbox(props) {
  const unreadMessages = props.unreadMessages;
  return (
    <div>
      <h1>Hello!</h1>
      {unreadMessages.length > 0 &&
        <h2>
          You have {unreadMessages.length} unread messages.
        </h2>
      }
    </div>
  );
}
```



## 条件演算子によるインラインIf-Else
:::note
条件的に要素をレンダーするもう一つの方法はJavaScriptの`condition ? true : false`条件演算子を利用すること。
:::

```react
render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
    </div>
  );
}
```

:::note warn
より大きな式になると、可読性が下がる。条件が複雑になりすぎている場合は、コンポーネントの抽出のタイミングかもしれない。
:::

## コンポーネントのレンダーを防ぐ
:::note
時にコンポーネントを隠したいケースもある。その場合はレンダー出力の代わりに、`null`を返すようにする。
コンポーネントの render メソッドから null を返してもコンポーネントのライフサイクルメソッドの発火には影響しない。
:::

```react
function WarningBanner(props) {
  if (!props.warn) {
    return null;
  }

  return (
    <div className="warning">
      Warning!
    </div>
  );
}
```
[小ネタ]EBSがgp2のEC2から作ったAMIからEBSがgp3のEC2を起動できるか？

こんにちは。Kaneyasuです。
ここ数週間は情報処理技術者試験の準備に集中していて、昨日やっと終わりました。
結果はまだわかりませんが、とりあえず全力は尽くしたの今の気分は晴れやかです。

今日は、EBSのタイプがgp2のEC2から作ったAMIから、EBSのタイプがgp3のEC2を起動できるか？
というのを質問されたので、試してみました。
結論から言うと、できます。

エビデンスと手順がないと不安かなと思うので本記事はそれを書いておきます。

まず、EBSのタイプがgp2のEC2インスタンスを用意します。
インスタンスタイプはt4g.microです。

![EC2インスタンス一覧](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/339ff8a6-31e6-0289-f258-6aacf891f494.png)

ベースのAMIはAmazon Linux　2023です。
![EC2の詳細](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/f6fa9436-fec2-f83e-0741-9d65c38b6fef.png)

ストレージの情報を追っていくと、EBSのタイプがgp2であることがわかります。

![EC2のストレージ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/182cac5c-0db1-f192-b704-fdb9662a4639.png)

![EBSのタイプ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/14dbf336-602b-ae1e-3fff-15c9e6a2347c.png)

このインスタンスからAMIを作ります。
![AMIの作成メニュー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/c927d76c-669c-f18f-c55e-c1edf74d0606.png)

AMIを作成する時、特に変わった指定はしていません。
AMIの元のインスタンスで、EBSのタイプがgp2であることがここでも確認できます。

![AMIの作成画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/530691af-227e-49fa-d083-21c1f9ab6a78.png)

作成したAMIからEC2を起動します。

![AMIからEC2を起動](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/19dd11a7-f54c-020b-a5c7-34ef237463ac.png)

AMIからEC2を起動する画面で、EBSのタイプが選択できます。
元がgp2なので、デフォルト選択値がgp2になっていますが、これをgp3に変更すればOKです。

![AMIからEC2を起動する画面でEBSのタイプを選択](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/cf571e88-eb37-cecb-807e-834a3b587754.png)

これが成立する理由ですが、まず、AMIはEBSをスナップショットで保存します。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/AMIs.html

>1 つまたは複数の Amazon Elastic Block Store (Amazon EBS) スナップショット、または、instance-store-backed AMI、インスタンスのルートボリュームのテンプレート (オペレーティングシステム、アプリケーションサーバー、アプリケーションなど)

EBSのスナップショットは、結局はデータなので、gp2だろうがgp3だろうが展開できるということだと思います。
Railsのローカル環境にHTTPSとカスタムドメインを導入！10分でOK!

## はじめに
ローカル認証局(CA)の機能を提供する**mkcert**を使用して、MacOSのローカル環境でHTTPSとカスタムドメインを導入してみましょう！

## mkcertの設置
**brew**を利用してパソコンに**mkcert**を設置します。
```shell
brew install mkcert
```

## 認証局(CA)の設置
**mkcert**のコマンドを利用してMacOSにローカル認証局(CA)のルート証明書を設置します。
```shell
mkcert -install
```

## SSL証明書
**`config/ssl`** ディレクトリにSSL証明書とプライベートキーを生成します。
```shell
# Railsプロジェクトのルートディレクトリで実行
mkdir -p config/ssl && cd $_ && mkcert "*.custom_domain.localhost"
```

## Rails環境構成の変更
**`config/environments/development.rb`** ファイルにカスタムドメインを追加します。
```shell
# config/environments/development.rb
config.force_ssl = true
config.hosts << '.custom_domain.localhost'
```
## Railsアプリの実行
ローカルでSSL証明書とプライベートキーを利用してRailsアプリを実行します。
```shell
rails server -b 'ssl://0.0.0.0:3443?key=config/ssl/_wildcard.custom_domain.localhost-key.pem&cert=config/ssl/_wildcard.custom_domain.localhost.pem'
```

## 参考文献
https://web.dev/i18n/en/how-to-use-local-https/
VSCode サーバーの止め方 Mac版

# はじめに
VSCodeにおいて、Windowsでのサーバー停止方法とMacでのサーバー停止方法が違い、少し困ったため記録に残しておきます。

# サーバーの起動方法
```
npm start
```
または
```
npm run start
```


# サーバーの停止方法
control + C で停止させることができます。

# おわりに
windowsではctrl + C でサーバー停止させることができます。
Macでは基本的にWindowsのctrlは基本的にcommandに置き換えて操作するため、ずっとcommand + Cでサーバーを停止させようとしていました。
入力するコマンドを間違えているので、それは止まらないですよね。。
Macにまだ慣れていないので少しずつ使いこなせるように頑張ります。
30分毎にドロップダウンに時間を設定をする方法(SequenceとForAllで)


今日はPower Appsのお話です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/13bd208c-d5b4-ca13-01f3-8a662ff1340b.png)

ドロップダウンに時間を設定することは、アプリ作成者にとっては多いことだと思いますが、
Itemsに入力すると下記画像のように長々とした悩ましいローコードになってしまいがちではないでしょうか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/4342cf0a-c7e1-047e-22d5-139b3c2df047.png)

:::note info
ローコードアプリなんだから最初から設定されている見本のようなものがあってもいいんじゃないか、と思うくらいです。
:::

## SequenceとForAllの関数を利用し30分毎のテーブルを作る


そこでSequenceとForAllを利用し、短いコードで解決してみようと思います。
これが結構便利で、よく使います。

## Sequence関数とは
下記のようにSequence(数字)と入力すると自動で連番を生成しテーブルを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/fd5383e2-1df6-6165-63d9-5d273f17eca4.png)

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-sequence
## ForAll関数とは
名前の通り、全てのテーブルのデータにアクションを与えます
今回は、Sequence関数で作成した連番を00：00など時間に表示を変更したいのでこれを利用します

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-forall

今回、24時間のうち30分毎にデータを表示させたいので、まずテーブルには全部で48個のデータが必要になります
とりあえず48データを作成します

```IETF BCP-47:下地
Sequence(48)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/60f06063-5067-ba83-5a4b-d10f203b64f9.png)

Sequence関数は、0は開始する数字、0.5は増加分量を指定することもできます。
```IETF BCP-47:下地
Sequence(48,0,0.5)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/6caa9780-6e62-e40c-fdc0-9330368a20d7.png)
こんな感じで0.5ずつ増えていくテーブルが作成されます
とっても便利ですよね。

さあ、最初に時間を設定していきましょう
```IETF BCP-47:書き方
ForAll(Sequence(48,0,0.5),Text(RoundDown(Value,0),"00"))
```
全ての値にText(RoundDown(Value,0),"00"))を反映させたいのでForAllを使用します

30分置きのコードは&以下のコードで、下記のようになりました
```IETF BCP-47:書き方
ForAll(Sequence(48,0,0.5),Text(RoundDown(Value,0),"00")&":"&Text(Mod(Value*60,60),"00"))
```
ただくっつけてるだけ(笑)ですが、これだけで入力が終わります。
15分置きに設定したい時はSequence関数の中身を下記のように
倍に変更してあげるとよいでしょう。

```IETF BCP-47:書き方
Sequence(96,0,0.25)
```

これを利用しコレクションにいれて、現在時間の30分後に開始時間を初期値として入れてあげたりしたらユーザーの時間を減らすこともできるかもしれませんね。

## 最後に

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/6de20c98-0386-6fb3-1ac9-475464828b7a.png)
読んでくださってありがとうございました。
地味に時間がかかる入力作業はこのように
できるだけ簡単な関数を使って減らしていくと、
保守性もあがりますし
家族と過ごす時間も増えてWinWinだと思います。
ぜひ利用してみてくださいね！
FCSW構築とライセンスが適用できなかった話

### FC（SAN）スイッチとは
 ファイバーチャネル（FC : Fibre Channel）に位置するスイッチとして、FCスイッチ（下記、FCスイッチと呼ぶ）は複数のサーバとストレージを束ね、コンピュータとストレージの通信を中継し、SANを形成するネットワーク機器である。 
https://www.dell.com/ja-jp/dt/storage/connectrix/connectrix-switches.htm

FCスイッチのメリット
 日々拡大しているネットワーク需要に伴い、高速、低遅延、長距離伝送などといった課題の深刻さも浮き上がった。ファイバーチャネルが選ばれた理由はまさにそこに存在する。

 ◉光ファイバーによる高速・長距離伝送

 1Gbps、8Gbps、導入する機器によっては16Gbpsも実現できる。さらに、ファイバーチャネルのケーブルは最大で10kmに対応可能で、社内や建物間の長距離通信を確保する。

 ◉プロトコルによるシステムの高い信頼性・安定性

 ファイバーチャネルはより少ない伝送エラーと高い信頼性を確保できる。複数の上位プロトコルをサポートするため、伝送の効率向上を実現した。

### FCスイッチの構成


 下記の図のように、パスの二重化を構成した場合、ディスクを両方のFCスイッチに接続したことで、チャンネル障害に備えてアクセスの切り替えを自動的に行うことが可能である。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573738/1633ef78-3291-71ad-67fe-9ac030460245.png)





 ラインAが障害に遭った場合、ホストAはラインBを経由してディスクAもしくはディスクBにアクセスできる。ホストBも同じく正常動作が可能である。




### FCSWライセンス適用されていなかった話

本題に入りますが、FCSW構築を行っている際になぜか2port以降がライセンス適用されていないことがありました。
流れとしてはFCSW初期構築 → FCSWファブリック拡張
ライセンスも購入していることは確認しており、納品時に48portまでライセンス適用されていることを確認しました。
初期構築が完了したのでファブリック拡張を行ったのですが、下記コマンドをたたくと24port以降にライセンスが適用されていないとエラーが表示されました。
#show license　

結果、スイッチが24port用のスイッチが間違えてメーカーから発送されていました。

※納品の際に気づけなかったの？
→ライセンスportの確認が現場の手順の中に入っておらず、他案件でもなかなか確認することはないかも・・・
と言われてしまい、メーカーの責任もあるので、なんとか収まりました。

改善策としは単純ですが、①メーカーへの確認　②手順の更新
上記２つになるかと思います。
オブジェクト指向とは(初心者向け)

転職活動中にオブジェクト指向について聞かれ、
うまく答えることができなかったので、理解を深めるための記録です！

オブジェクト指向とは
=
「属性（構成するデータ）」と「メソッド（指示に対する振る舞い）」を1つにまとめた「オブジェクト」の定義ごとに「クラス」を分類し、そのクラス同士を組み合わせてシステムを組み立てる考え方のこと。

、、、？？？
という感じだと思います笑(何を隠そう私がそうです)

この考え方を車に例えて説明をすると、

属性とは、モノ(オブジェクト)が持っているデータのことで、「色」、「メーカー」、「車種」など
メソッドとは、モノ（オブジェクト）が持っている処理のことで、「前進する」「止まる」「バックする」などのこと

次に「クラス」について説明していきます。

クラスとは
=

データと処理をひとつにまとめたもの。
オブジェクトのもつ性質ごとに分類したものとも言い換えることができます。
モノ(オブジェクト)の設計書のようなモノです。

今回の車で例えると、下記のようになります。
「」に入っているものは全てオブジェクトです。
ーーーーーーーーーーーーーーーーーーーーーーーーーー
「乗り物」

↓

「車」　　、「バイク」、「電車」、「飛行機」

↓

「トヨタ」　、「日産」、「ホンダ」、「BMW」

↓インスタンス化

「プリウス」、「クラウン」、「ハイエース」
ーーーーーーーーーーーーーーーーーーーーーーーーーー
このようにクラス分けをすると、全体におけるオブジェクト位置付けが明確になり、
どのような共通点があり、どのような異なっている点があるのかがはっきりします。


インスタンスとは
=
クラスというモデルをもとに作られら実体のことを表します。
言い換えると、クラスが設計書で、そのモデルから生まれた実体がインスタンスです。

オブジェクト指向のメリット
=
オブジェクト指向を活用するメリットとしては、次のようなものが挙げられます。

・効率よくプログラムを設計・開発できる
先ほどの例の中で、全ての車に「自動運転を機能を搭載する」という事象が発生したとします。
「プリウス」などの車種が1000種類ある場合に、それぞれを変更すると1000回の変更が必要ですが、
「車」というクラスを変更すると1回の変更で済みます。

・不具合の原因を特定しやすくなる
不具合が起きた際に、
「ブレーキが効かない」→「車」のクラスを確認する
「トヨタのエンブレムがズレている」→「トヨタ」を確認する
「着陸時の揺れが激しい」→「飛行機」を確認する
など、不具合の特定がしやすくなります。

・分業できる
上位クラスを元として、1000車種あるものを分業して作成していくことができます。

などがあります。

オブジェクト指向のデメリット
=
完全無欠で便利に見えるオブジェクト指向にも下記のようなデメリットはあります。

・設計の工程に時間がかかる。
オブジェクト指向プログラミングはしっかりと設計されてはじめて実力を発揮します。
逆に設計がしっかりできていないと、オブジェクト指向のメリットを享受できなかったり、
別の問題が生じたりします。

・知識やスキルが求められる
オブジェクト指向のプログラミングを行うには相応のスキルや知識が必要となります。

オブジェクト指向の代表的な言語
=
・Java
・Ruby
・PHP
・Python
など様々な言語で使われています

以上、理解の整理も兼ねた初心者向けのオブジェクト指向とはでした！
Raspberry Pi 4 Model B 【TypeScript開発環境構築】

# はじめに

基本的な環境構築はできてきたので、TypeScriptの開発環境の構築を行っていきます。

# 実現したいこと

* TypeScript & Express でサーバーを立てて、作業PCからAPIをたたく

# 環境

* 作業PC
  * OS：Windows 11 Home
  * Version：22H2
  * プロセッサ：11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz 3.00 GHz
  * RAM：16GB
* Raspberry Pi 4 Model B

# 概要

0. node.jsのLTS版(18.x)をインストール
0. サンプルプログラムの作成
0. 作業PCからAPIをたたく

## node.jsのLTS版(18.x)をインストール

`https://deb.nodesource.com/setup_lts.x`を使用する方法が検索すると多くヒットしますが、ワーニングが出るので、[公式](https://github.com/nodesource/distributions)の手順でインストールしました。
全て LXTerminal 上での作業です。
※以下、公式の手順を転記します。

### 1. Download and import the Nodesource GPG key

```bash
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
```

### 2. Create dev repository

```bash
NODE_MAJOR=18
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
```

### 3. Run Update and Install

```bash
sudo apt-get update
sudo apt-get install nodejs -y
```

### インストール確認

```bash
$ npm -v
9.8.1
$ node -v
v18.18.0
```

## Express サーバーの作成 & 起動

※あくまで最低限の構成なので、好みに合わせてカスタマイズしてください。

0. 任意の作業ディレクトリを作成し、その中に移動する
0. `npm init -y`と入力し、nodeプロジェクトの設定ファイルを作成する
0. `npm i express`と入力し、expressをインストールする
0. `npm i typescript @types/node @types/express --save-dev`と入力し、TypeScript に必要なライブラリをインストールする
0. `npx tsc --init`と入力し、TypeScript の設定ファイルを作成する
0. `touch index.ts`と入力しファイルを作成した後、以下の内容を転記する
   ```index.ts
   import express from 'express';

   const app: express.Express = express();
   const port: number = 3500; // ここは任意のポート番号

   app.get('/', (req: express.Request, res: express.Response) => {
       console.log('Get API is invoked.');
       res.send('Hello from Raspberry Pi!!');
   });

   app.listen(port, () => {
       console.log(`Hello World app listening on port ${port}`);
   });
   ```
0. `npx tsc`と入力し、javascript にコンパイルする
0. `node index.js`と入力し、サーバーを起動する
0. 別の LXTerminal から`curl localhost:3500`と入力し、「Hello from Raspberry Pi!!」と表示されるか確認する

## 作業PCからAPIをたたく

0. LXTerminal で`sudo ufw allow 3500`と入力し、サーバーとして使用するポートを開放する
0. 作業PC側で`curl http://192.168.2.50:3500`と入力し、「Hello from Raspberry Pi!!」と表示されるか確認する

# 備考

## node.js のアンインストール方法

※試していませんが、備忘録も兼ねて転記しておきます。

```bash
apt-get purge nodejs &&\
rm -r /etc/apt/sources.list.d/nodesource.list &&\
rm -r /etc/apt/keyrings/nodesource.gpg
```

# まとめ

これで Raspberry Pi をサーバーとして使用する準備が整ったので、一通りの環境構築は終わったかなと。
APIサーバーとして使用したり、センサー繋げたり、色々と使っていきたい。

# 参考

* [【2023年】Raspberry Piに最新版や LTSの Node.jsを超簡単にインストールする方法](http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_install_newest_node_js/)
* [NodeSource/distributions](https://github.com/nodesource/distributions)
[Unity]デバイスごとで使用されるURP設定を確認する

# 概要
UnityはAndroidやiOS、PCなど色々なデバイス用のビルドを作成する事ができます。グラフィックにはURPを使用する事が多いと思いますが、デバイスごとに最適な設定が適用されるように切り替えられる仕組みが用意されています。それの確認方法を共有します。
# 本文
メニューからEdit > ProjectSettings
表示されるポップアップからQualityを選びます。
緑色のチェックがついているのがそのデバイスで適用される設定を表しています（PCはHigh Fidelity、AndroidとiOSはBalanced）
表のDefaultにある下向きの三角を押すと表示されるプルダウンから設定変更することもできます。
![スクリーンショット 2023-10-09 22.00.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/7501c19d-8159-ac2d-d523-861939dd2ca2.png)

ちなみにその下にあるRender Pipline Assetの項目をクリックするとそのファイルのある場所がProjectのウィンドウで表示されます。
![スクリーンショット 2023-10-09 22.04.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/5a4d1d5d-fd51-d6c7-fa51-9dede7b49289.png)

# 補足
Universal Renderer Dataで変更した画像設定がUnity Editor上では反映されたのを確認出来てもスマフォ実機では上手くいかなかった。そんな場合はこれらの項目を確認すると原因が特定できることもあるかもしれないです！
Go言語で作ったPubSub起動のCloud Functionsの関数をローカル環境(Mac)で動かす

# 概要

PubSubのイベントを受け取って起動するGo言語で作った Cloud Functions の関数をローカル環境で実行する方法

## 参考

- [Functions Framework  |  Google Cloud Functions に関するドキュメント](https://cloud.google.com/functions/docs/functions-framework?hl=ja)
- [Function Frameworks を使用した関数を実行する  |  Google Cloud Functions に関するドキュメント](https://cloud.google.com/functions/docs/running/function-frameworks?hl=ja)
- [ローカル関数を呼び出す  |  Google Cloud Functions に関するドキュメント](https://cloud.google.com/functions/docs/running/calling?hl=ja)

# 事前準備

- goのversionを1.18に上げておく（ここでハマったので）
- `gcloud auth application-default login` でログインしておく

# 方法

## ディレクトリ構成

```
.
├── cmd
│   └── main.go
├── go.mod
├── go.sum
└── hoge_functions.go
```

## 起動関数(main.go)

```go
package main

import (
	"fmt"
	"github.com/GoogleCloudPlatform/functions-framework-go/funcframework"
	"github.com/hogehoge/fugafuga/sample/hoge"
	"log"
)

func main() {
	funcframework.RegisterEventFunction("/", hoge.HogeFunction) // ここで自作したCloud Functionsの関数を呼ぶ
	port := "8080"
	if err := funcframework.Start(fmt.Sprintf("%s", port)); err != nil {
		log.Fatalf("funcframework.Start: %v\n", err)
	}
}
```

## 実行

```
GOOGLE_CLOUD_PROJECT="your-project-id" go run ./cmd/main.go
```

## 確認方法

[ローカル関数を呼び出す  |  Google Cloud Functions に関するドキュメント](https://cloud.google.com/functions/docs/running/calling?hl=ja) にあるとおり、curlで確認する

`d29ybGQ=`がデータの中身(base64)になるらしいです。topic名は特に変更することなく動きました。パスが合ってればいいんでしょうね。おそらく。

```
# 'world' base64-encoded is 'd29ybGQ='
curl localhost:8080 \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
        "context": {
          "eventId":"1144231683168617",
          "timestamp":"2020-05-06T07:33:34.556Z",
          "eventType":"google.pubsub.topic.publish",
          "resource":{
            "service":"pubsub.googleapis.com",
            "name":"projects/sample-project/topics/gcf-test",
            "type":"type.googleapis.com/google.pubsub.v1.PubsubMessage"
          }
        },
        "data": {
          "@type": "type.googleapis.com/google.pubsub.v1.PubsubMessage",
          "attributes": {
             "attr1":"attr1-value"
          },
          "data": "d29ybGQ="
        }
      }'
```
Springのヒストリー

##### < 前 >
- CGI使用
- マルチスレッドができなくて要請が来る度に毎回新しいプロセスを生成しなければならなかった。

##### < Servlet, 1997>
- 長所:**マルチスレッド支援**→要請が来る度に新しいスレッドを生成すれば良い。
- 短所:画面の機能や構成が複雑になるにつれ、ユーザーを考慮する画面要求事項もますます増える

しかし、Javaコードで画面を作らなければならず、HTML生成が難しかった。

##### < JSP, 1999 >
- 長所:HTML、CSS、JavaScriptを基盤にJSP要素を使用して画面を具現する
- 短所:HTML生成は便利だが、ビジネスロジックまであまりにも多くの役割を担う

##### <Servlet、JSPを組み合わせたMVCパターンを使用>
- モデル、ビュー、コントローラに役割を分けて開発
- 画面に関連する部分は**JSP**のようなビュー側のコードをコピーして、ビジネスロジックと関連した部分であれば、**JavaコードやServlet**の方を直す方法で関心事を分かち合う


##### <数多くのMVCフレームワークが登場.. >
- ウェブが爆発的に成長した時期でしたが、メンテナンスに関する問題も多く、標準化が必要となり、様々なFrameworkが登場した。
- ex.EJB, Struts

##### < Spring Framework, アノテーションベースのスプリングMVC登場, 2004 >

- メンテナンスが楽になり、生産性も高めるようになった。
- ジャワ言語の最大の特徴である**オブジェクト指向**をうまくできるように助けるフレームワークだ。

##### < Springboot, 2017 >
- Springの設定をさらに簡便にできるようにした。
- サーバーを内蔵しており、別にトムキャット設置をしなくてもよい。
- ビルド結果（Jar）にWASサーバを含め、ビルド配布が単純となった。
    - (過去にはサーバにWASを直接インストールし、ソースはWarファイルを作成してインストールしたWASに配布していた)
    - ただし、JSPを推奨していないが、あえて書く必要がある場合は、パッキングをwarに設定する必要がある。


##### <スプリングウェブ技術の分化>
1. Web Servlet - Spring MVC
    - サーブレットの上で動作してHttpServletRequest、HttpServletResponseを使用することができる。
    - マルチスレッドが使用できる。
2. Web Reactive - Spring WebFlux
    - 完全な非同期ノンブロッキング処理を行う。
    - 最小スレッドで最大性能を出す。
        - cpuコアが4つあれば、スレッド数を4つ、5つ程度とする。
        - そうするとスレッドは戻り続けることができるようになり、Context Switchingの費用がほとんどかからない。
    - 関数型スタイルで開発するため、同時処理のコードが非常に効率化される。
        - 複数のサーバーからデータを持ってきて組み合わせなければならない場合、コードが非常にきれいになる。
    - サーブレット技術を使わない。
    - Netty というウェブフレームワークで実現する。
    - まだRDB支援不足、実務で多く使う方ではない
    - 性能がとても重要で、複雑な時に効果があり、その他はほとんどMVCモデルで解決すれば良い。
競プロ典型 90 問 004 - Cross Sum（★2）

## 競プロ典型 90 問 004 - Cross Sum（★2）

競プロの初めて向けの10問を解いたので、90問をチャレンジ！

★2でもめちゃくちゃ難しいんよな。。。
## 問題

H 行 
W 列のマス目があります。
その縦横の合計を出してほしい。


## 説明
縦横の合計を足すのですが、
重複しているところを引くことが必要になります。これを包除原理というらしい。
H行とW列を足しても、重複があるため、(H+W)-1 が成り立つ。

Aは[[1,2,3],[1,2,3],[4,5,6]]みたいなリスト。

前処理として、縦のみ。横のみのリストを作成する。


### zip(*A)
zipは*演算子を使えば展開してくれる。
リストを展開して、各リストの要素を対応するものとして組み合わせる。
各リストの同じインデックス同士が組み合わさるみたい。
→各リストの同じインデックスインデックス同士という事は縦軸で合わさる。
縦の合計ができる。

参考：
https://qiita.com/kubochiro/items/5daedd51654a8155bc06

## ソースコード
```python

# 入力
H, W = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(H)]

# 前処理
yoko = list(map(sum, A))
tate = list(map(sum, zip(*A)))
      
yoko = list(map(sum,A))
tate = list(map(sum,zip(*A)))

for i in range(H):
  print(
    ' '.join(
      map(lambda j: str(yoko[i]+ tate[j] - A[i][j]) ,range(W))
      )
  )

##########
range(H)で縦を回す。range(W)で横を回す。

mapだけでは、for i in range(H)を回すだけ。
mapのrange(W)で横も回す。mapの中でfor文書いてもう一回回しているイメージでいます。

range(H)だけでは、行しか回れない。
mapは行数分しか回せないが、mapの中でrange(W)することで、縦x横になる。

あとは、提出用のデータを作るために、strに変換してjoinで文字結合する。

```



参考：
https://drken1215.hatenablog.com/entry/2021/07/25/215000
AIチャレンジ3（経済成長率の予測その2）

　前回は、二値分類モデルで経済成長しているかどうかでディープラーニングしました。
こちらの記事を参照。
AIチャレンジ2（経済成長率の予測）
https://qiita.com/horiivalue/items/97563e4a647d071419cc

　今回は、同じデータで多クラス分類モデルで学習させてみたいと思います。

# 前回との違い

　二値分類モデルと異なり、成長率を0.5%づつ８クラスに分けて分類。

```Python
for i in range(117):
    s = dataset.iloc[i,0]
    if s >= 2:
        dataset.iloc[i,0] = 2
    elif s>= 1.5:
        dataset.iloc[i,0] = 1.5
    elif s>= 1:
        dataset.iloc[i,0] = 1
    elif s>= 0.5:
        dataset.iloc[i,0] = 0.5
    elif s>= 0:
        dataset.iloc[i,0] = 0
    elif s>= -0.5:
        dataset.iloc[i,0] = -0.5
    elif s>= -1:
        dataset.iloc[i,0] = -1
    elif s>= -1.5:
        dataset.iloc[i,0] = -1.5
    else:
        dataset.iloc[i,0] = -2
dataset.head()

dataset2 = pd.get_dummies(data=dataset, columns=['keizai'])
dataset2.head()

Y = np.array(dataset2[['keizai_-2.0', 'keizai_-1.5', 'keizai_-0.5','keizai_0.0','keizai_0.5','keizai_1.0','keizai_1.5','keizai_2.0']])
X = np.array(dataset2[['kakei','export','minkan','import']])
```

# 学習と効果

　学習も以下のように変更。

```Python
# モデルの初期化
model = keras.Sequential()

# 入力層
model.add(Dense(24, activation='relu', input_shape=(4,)))
# 隠れ層
model.add(Dense(24, activation='relu'))
# 出力層
model.add(Dense(8, activation='softmax'))

# モデルの構築
model.compile(optimizer = "rmsprop", loss='binary_crossentropy', metrics=['accuracy'])

%%time
# 学習の実施
log = model.fit(X_train, Y_train, epochs=5000, batch_size=32, verbose=True,
                callbacks=[keras.callbacks.EarlyStopping(monitor='val_loss',
                                                         min_delta=0, patience=100,
                                                         verbose=1)],
         validation_data=(X_valid, Y_valid))

# predictで予測を行う
Y_pred_0 = model.predict(X_test)

# 多クラス分類は予測結果の各リストにおける
# 最大値のインデックスを取得するようにする
Y_pred = np.argmax(Y_pred_0, axis=1)

# モデルの評価
from sklearn.metrics import classification_report

print(classification_report(Y_test_, Y_pred))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533364/c237569d-dea5-ddd5-32a3-2478778fce2c.png)

 結果、前回よりかなり悪い値が出てきました。もう少しデータが必要のようです。
AppConfig

- AppConfig という別の設定クラスを作り、実装オブジェクトを生成して接続する責任を持つようにした。

    ```jsx
    public static void main(String[] args) {
        // 前
        // MemberService memberService = new MemberServiceImpl();
        // OrderService orderService = new OrderServiceImpl();
        // クライアント オブジェクトが実装オブジェクトの生成、接続、実行のすべての責任を負っている。
        // インターフェースだけでなく、実装クラスにも依存している。
        // 後
        AppConfig appConfig = new AppConfig();
        MemberService memberService = appConfig.memberService();
        OrderService orderService = appConfig.orderService();
        // クライアント オブジェクトは実行する責任のみを担うことになった。
        // => 1.SRP:単一責任原則解決
        // どの実装オブジェクトを生成して接続するかをAppConfigで決定し、
        // クライアント オブジェクトでは修正することがない。
        // =>2. OCP:開放-閉鎖の原則を解決
        // インターフェース（抽象化）のみに依存し、実装クラス（球体科）に依存しない。
        // =>5.DIP:依存関係逆転の原則解決
    
        Long memberId = 1L;
        Member member = new Member(memberId, "memberA", Grade.VIP);
        memberService.join(member);
        
        Order order = orderService.createOrder(memberId, "itemA", 10000);
        System.out.println(order);
        System.out.println(order.calculatePrice());
    }
    ```

    ```jsx
    public class AppConfig {
    
        public MemberService memberService() {
            return new MemberServiceImpl(memberRepository());
        }
    
        public OrderService orderService() {
            return new OrderServiceImpl(memberRepository(), discountPolicy());
        }
    
        public MemberRepository memberRepository(){
            return new MemoryMemberRepository();
        }
    		
        // どの実装オブジェクトを生成して接続するかをAppConfigで決定する。
        public DiscountPolicy discountPolicy(){
        // 前
        // return new FixDiscountPolicy();
        // 後
        return new RateDiscountPolicy();
        }
    
    }
    ```
    ```jsx
    package hello.hellospring.member;
    
    public class MemberServiceImpl implements MemberService{
    
        // 前
        // private final MemberRepository memberRepository = new MemoryMemberRepository();
        // 後
        private final MemberRepository memberRepository;
        public MemberServiceImpl(MemberRepository memberRepository){
            this.memberRepository = memberRepository;
        }
    
        @Override
        public void join(Member member) {
            memberRepository.save(member);
        }
    
        @Override
        public Member findMember(Long memberId) {
            return memberRepository.findById(memberId);
        }
    }
    ```
初学者向け）form_withの使い方とオプション(model,local:true)について

# **はじめに**
私自身が`form_with`が何であるか、local:trueとは何なのか理解せずに躓いてしまったので、初学者の方々に`form_with`についての理解の一助になればと思い投稿しました。
    （記事の内容について不備等あれば、ご意見等いただけると幸いです）

# 目次
| 章 |    タイトル    |    備考    　|
|---:|-------------|------------|
| 1  |[form_withの紹介](#form_withの紹介)|       どんなことができるのか、`form_tag`や`form_for`との違い     |
| 2  |[form_withの構文](#form_withの紹介)|       使い方と引数、オプションについて     |
| 3  |[最後に](#最後に)　|             |
| 4  |[参考文献](#参考文献)　|        今回参考にした文献     |

# form_withの紹介
**（１）どんなことができるのか**
ヘルパーメソッドの一つで、入力フォーム（テキスト、検索、パスワードなど）を作成することができます。

**（２）`form_tag`や`form_for`とはどう違うのか**
>Rails 5.1でform_withが導入されるまでは、form_withの機能はform_tagとform_forに分かれていました。form_tagおよびform_forは、禁止ではないものの、利用は推奨されていません。
「参考文献：Railsガイドより」

以前までは、検索フォームのようにmodelが無い場合は`form_tag`を使用し、反対にmodelが有る場合は`form_for`を使用していたようですが、これらが統合されて現在は、`form_with`を推奨されているようです。

# form_withの構文
### 使い方
```rails:viewに記載
form_with(model or url,[scope:],[オプション]) do |f(form)|
```
例）ユーザーの登録(簡易)
```rails:app/view/hoge.erb
<%= form_with model: @user, local: true do |f| %>
    <%= f.text_field :name %>
    <%= f.email_field :email %>
    <%= f.password_field :password %>
    <%= f.submit '登録' %>
<% end %>
```
この場合、下記のようなフォームを作成できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556982/8e762cab-34ae-e5f8-090d-287ec3f2871c.png)

### 引数について
**（１）model**
>:model引数を使うと、フォームビルダーオブジェクトをモデルオブジェクトに紐付けできるようになります。つまり、フォームはそのモデルオブジェクトを対象とし、そのモデルオブジェクトの値がフォームのフィールドに自動入力されるようになります。
「参考文献：Railsガイドより」
>
つまり、Railsが自動的にフォームに入れたもの（上記だと、名前、email、パスワード）とオブジェクト（@user)を紐付てくれます。
また、Railsが自動で適切なURLを判別してくれる機能もあり、例えば、ユーザーが登録されてなければ新規登録へ、すでに登録済みなら更新へという形で判別してくれます。

**（２）url**
`url:new_user`のように、特定のURLを指定してフォームデータを送信できる

**（３）scope**
フォームフィールドのname属性にプレフィックス（接頭辞）を指定してグループ化できるもの。
以下の方が詳しく解説してくれてますので、参考にされてください。
https://endoakak.hatenablog.com/entry/2020/08/29/200000

**（４）オプション**
`local:true`：同期通信を使う場合に使います。
（Rails 5.1〜6.0 = 非同期通信（Ajax）がデフォルト、Rails 6.1 = 同期通信がデフォルトのようです）

::: note warn
【同期通信ではない場合どうなるか（体験談）】
フォーム送信後にリダイレクトした際に、バリデーションが表示されない・投稿を新規作成したのに一覧に表示されないなど、ページ全体を更新したい時に更新がされません
:::
なお、ほかにも、GETとPOST以外のHTTPメソッドを使う時に使用する`:method`などのオプションもあります。


# 最後に
備忘録のような形になりましたが、引数でmodelを使うことのメリットやlocal:trueの使い方について理解が少しでも深まればと思います。

# 参考文献
- [フォームヘルパーform_withについて | Railsガイド](https://railsguides.jp/form_helpers.html#%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)
- [form_withに関するAPIドキュメント](https://api.rubyonrails.org/v6.0/classes/ActionView/Helpers/FormHelper.html#method-i-form_with)
- [form_withの使い方 | Pikawaka](https://pikawaka.com/rails/form_with)
【Flutter】iOSの生体認証の処理が失敗した時に表示される『パスコードを入力する』を消す方法

# はじめに
業務で生体認証系のパッケージで[local_auth](https://pub.dev/packages/local_auth)を触る機会があり、セキュリティの観点からiOSの生体認証の処理が失敗したらパスコードを入力できないようにしたかったので実装しました。
ドキュメントに方法が記述されておらず、私が少しハマったため他の人が困らないように、と私のために備忘録として残しておこうと思います。
# 結論
生体認証の処理を実行時、連続で失敗すると『パスコードを入力する』ボタンが表示されますが、`IOSAuthMessages`クラスの`localizedFallbackTitle`プロパティを空文字にすることで『パスコードを入力する』を表示しないようにすることができます。

:::note warn
あくまで2023年10月時点での情報のため、パッケージのアップデートによる破壊的変更や、Flutterのバージョンによって実装方法が変わる可能性がありますので参考程度にしていただけたらと思います🙇‍♂️
:::
# 執筆時の環境
- Flutter3.13.2
- local_auth2.1.7
# 実装方法
## 今回作るもの
![生体認証GIF.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501157/34efcfbe-75e4-c770-52ef-426435d74677.gif)


## 実装方法
:::note warn
『パスコードを入力する』ボタンを消すための記事のため、local_authの詳しい実装についてはここでは触れないです。
詳しく知りたい方は[local_authのドキュメント](https://pub.dev/packages/local_auth)をご覧下さい。
:::

結論でも書きましたが、`IOSAuthMessages`クラスの`localizedFallbackTitle`プロパティを空文字にすることで『パスコードを入力する』を表示しないようにすることができます。

```:dart
Future<void> authenticate() async {
      final auth = LocalAuthentication();
      await auth.authenticate(
        //localizedReasonはrequiredになっているので仮で空文字を入れています。
        localizedReason: '',
        authMessages: [
          const IOSAuthMessages(
        // localizedFallbackTitleを空文字にすることでパスコードを入力するを消すことができます。
            localizedFallbackTitle: '',
          ),
        ],
        options: const AuthenticationOptions(
        //生体認証機能を提供するにはbiometricOnlyをtrueにしてください
          biometricOnly: true,
        ),
      );
    }
```
# 参考にしたサイト
 
https://tech.nri-net.com/entry/swift_local_authentication

https://zenn.dev/nakaken/articles/0589fe47d647a0

https://developer.apple.com/documentation/localauthentication/lacontext/1514183-localizedfallbacktitle

https://qiita.com/yokirin/items/32597ab0cc53f6ad8c74

https://pub.dev/packages/local_auth