OmniAICreator/Qiita-1.07M huggingface dataset:
androidデバイスのGPUを使ってTensorflow liteを高速にする

# AIを使うならGPUは使わないと
androidでAIモデルを使用する場合、デフォルトではCPUのみで実行することになります。
もしデバイスに**GPU**（Graphics Processing Unit）が入っている場合、GPUを使用することで**処理を大幅に高速化できます**。

たとえば、Google Pixel 7aでYolov8を実行した場合、
**CPUでは　0.9秒
GPUでは　0.2秒**
で実行されます。

# GPUDelegate

デバイスのGPUを使うためには、TensorFlowLiteの**GPUDelegate**を設定します。
TensorFlowLiteのInterpreterを初期化するときに、オプションにGPUDelegateを加えるだけです。

（ちなみに、NNAPIDelegate（NeuralNetworkAPI）というのもありますが、これは自分の環境（GooglePixel7a）ではCPUと変わりませんでした、）


# 方法

### 必要なライブラリのインストール

```gradle:build.gradle
implementation("org.tensorflow:tensorflow-lite:+")
implementation("org.tensorflow:tensorflow-lite-gpu:+")
implementation("org.tensorflow:tensorflow-lite-gpu-api:+")
implementation("org.tensorflow:tensorflow-lite-gpu-delegate-plugin:+")
implementation("org.tensorflow:tensorflow-lite-support:+")
```

上から４つのライブラリはバージョンを合わせないとクラッシュすることがあるみたいです。
:+ にしておけば全部最新バージョンがインストールされるのでOKです。

### GPUDelegateの設定

モジュールインポート

```kotlin
import org.tensorflow.lite.Interpreter
import org.tensorflow.lite.gpu.CompatibilityList
import org.tensorflow.lite.gpu.GpuDelegate
```

デリゲートの設定。

モデルのInterpreterのオプションにGPUDelegateを設定します。

```kotlin
val compatList = CompatibilityList()

val options = Interpreter.Options().apply{
    if(compatList.isDelegateSupportedOnThisDevice){
        // if the device has a supported GPU, add the GPU delegate
        val delegateOptions = compatList.bestOptionsForThisDevice
        this.addDelegate(GpuDelegate(delegateOptions))
    } else {
        // if the GPU is not supported, run on 4 threads
        this.setNumThreads(4)
    }
}

interpreter = Interpreter(model, options)
```

これで、デバイスに利用可能なGPUがある場合はGPUを使用してモデルが実行されます。

🐣
****
フリーランスエンジニアです。
AIについて色々記事を書いていますのでよかったらプロフィールを見てみてください。

もし以下のようなご要望をお持ちでしたらお気軽にご相談ください。
AIサービスを開発したい、ビジネスにAIを組み込んで効率化したい、AIを使ったスマホアプリを開発したい、
ARを使ったアプリケーションを作りたい、スマホアプリを作りたいけどどこに相談したらいいかわからない…

いずれも中間コストを省いたリーズナブルな価格でお請けできます。

お仕事のご相談はこちらまで
rockyshikoku@gmail.com

機械学習やAR技術を使ったアプリケーションを作っています。
機械学習／AR関連の情報を発信しています。

[X](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
ZEDSDK と Unityで出来ることまとめ

## 公式Unityサンプルを確認するまで

・ZEDを買う
[こちらから（公式サイト）](https://www.stereolabs.com/products/zed-2)
少々お高いので個人で買うならお財布と相談して下さい。

・ZEDSDKを入れる
[こちらから](https://www.stereolabs.com/developers/release/4.0/migration-guide)ダウンロード

:::note info
ZED SDKの入れ方は[こちらから](https://qiita.com/zz_suy/items/c5296d8c1fbf6d4cb23d)
:::

・Unityを入れる
[こちらから](https://unity.com/ja/download)ダウンロード

・GitHubから公式ソースを手に入れる
[こちらから](https://github.com/stereolabs/zed-unity)ダウンロード

## 説明書を見てみる
GitHub公式ソースのRead meに説明が書いてあります。
英語でもいいならぶっちゃけ公式を見るのが一番分かりやすいと思います。

### 出来ること一覧
#### ボディトラッキング
:::note info
※インストール後、ZEDSDK DiagnosticでAIModelを別途インストールする必要があります。だいたい40分ぐらいかかります
:::
AIモジュールを使用して、モデルトラッキングができます。最大70人同時にリアルタイムでトラッキングできるそうです。

[セットアップ方法](https://www.stereolabs.com/docs/unity/body-tracking)

#### AR/MR
ZED 2iをカメラと見立ててAR、MR空間にさせることができます。

[セットアップ方法](https://www.stereolabs.com/docs/unity/creating-mixed-reality-app)

#### 点群表示
:::note info
OqulusなどのVRヘッドセットの有無にかかわらず表示可。
VRコントローラーの併用も可能です。
:::
Unity内で検知された映像をそのままシーン上で点群表記させます。

#### 人体（オブジェクト）検知
オブジェクトを検知させてその位置にオブジェクト生成させることができます。

#### 平面検出
深度センサーが搭載されているので、静的な物体の検出が可能です。床とか読み込んでそこをUinty上の床にすることもできます。

※VR機材を併用する場合のキャリブレーションも想定されているので体感扱いやすめです

[サンプル](https://www.stereolabs.com/docs/unity/samples#point-cloud)

### 所感
センサーとしてはかなり精度が良いです。基本的にぶつ切りになることも無く人を読み込んでくれます。足も上がります。

## 苦悩したところ（余談）
新しく初期化したパソコン(Windows)にZEDSDKの入ったUnity projectを起動した瞬間に落ちる現象、ビルドでエラーを吐く現象が発生しました

### 原因(おそらく)
ZEDSDKのバージョンがUnityで使用するsdk (4.0)のバージョンより上だった為(4.1だった為)

### 解決策
ZEDSDKのバージョンとUnityのバージョンを同じにする

ZEDSDKの以前のバージョン(私の場合は4.0)をインストールして再開する
それでもできなかった場合、Unity packageを一旦消して入れ直す。これで開けました。

また、トラブルシューティングも公式で用意されているので、エラーが起きたらまずは確認すると良いと思います。
https://support.stereolabs.com/hc/en-us/categories/200856185-Troubleshooting

それでは。
STM32C011でソフトウェアI2Cで遊ぶ





参考


↓クリック↓

https://qiita.com/7of9/items/a1a42359cff9ed06778f


x オリジナルハードのへんなI2C液晶を使う。

目的
I2Cで遊ぶ。


結果

![o_coq073.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/316451ea-1c41-6f06-16e3-4358d3eb6f23.jpeg)



文字の「0」を出力する時のイメージ

![o_con368.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/6eaf5712-dd27-9cfc-6f03-f5b390f60a1a.jpeg)



プログラム


```c++


//soft_i2c_test_C011_1

#include <Arduino.h>


//A5
#define SCK_0_HIGH()  digitalWrite(PA8, HIGH)
#define SCK_0_LOW()   digitalWrite(PA8, LOW)

//A4
#define SDA_0_HIGH()  digitalWrite(PA12, HIGH)
#define SDA_0_LOW()   digitalWrite(PA12, LOW)
#define SDA_O         A4

// 1000us   1kh
//  100us  10kh
//   10us 100kh
#define myDelay()  delayMicroseconds(100);

int soft_i2c(char add_p, char data_p) {

  int ii;

  //待ち
  SDA_0_HIGH();
  SCK_0_HIGH();
  myDelay();
  myDelay();
  myDelay();

  //START
  SDA_0_LOW();
  myDelay();
  SCK_0_LOW();
  myDelay();

  for (ii = 0; ii < 8; ii++) {
    SCK_0_LOW();
    if ( ((add_p << ii) & 0x80) == 0 ) {
      SDA_0_LOW();
    } else {
      SDA_0_HIGH();
    }//endif
    myDelay();
    SCK_0_HIGH();
    myDelay();
  }//for

  //ack
  SCK_0_LOW();
  SDA_0_HIGH();
  myDelay();
  SCK_0_HIGH();
  myDelay();

  for (ii = 0; ii < 8; ii++) {
    SCK_0_LOW();

    if ( ((data_p << ii) & 0x80) == 0 ) {
      SDA_0_LOW();
    } else {
      SDA_0_HIGH();
    }//endif

    myDelay();
    SCK_0_HIGH();
    myDelay();
  }//for

  //ack
  SCK_0_LOW();
  SDA_0_HIGH();
  myDelay();
  SCK_0_HIGH();
  myDelay();

  //STOP
  SCK_0_LOW();
  SDA_0_LOW();
  myDelay();
  SCK_0_HIGH();
  myDelay();
  SDA_0_HIGH();
  myDelay();

  return (0);

}//soft_i2c


void setup() {

  pinMode(PA12, OUTPUT_OPEN_DRAIN);
  pinMode(PA8, OUTPUT_OPEN_DRAIN);
  digitalWrite(PA12, HIGH);
  digitalWrite(PA8, HIGH);

}//setup


void loop() {

  char *ss1 = "hello world ";
  int ii = 0;
  while (ss1[ii] != 0 ) {
    soft_i2c(0x80, ss1[ii]); ii++;
  }//while

  delay(1000); //1秒の待ち

}//loop


```
データモデリング  ネーミングとドメイン

前回までは、トップダウンで切り出したモデルに対して、主キー候補属性やエンティティについて説明してきた。
次に行うのは作成したモデルに対してボトムアプローチをすること。

::: note
ボトムアップアプローチは、画面や帳票、データベースから属性を見つけ出す
:::


<h3>なぜ、ネーミングが必要なのか?</h3>
モデルを見る人や扱う人が複数いることが多いからである。
また、モデラーが一人だったとしても、保守/開発者が複数いれば、なんらかのルールが必要になる
<h3></h3>
<h3>ネーミング表示の策定</h3>
データ標準化を進める上で、最低限なルールを紹介する。
Primer(主要語)、修飾語(Qualifier)、分類区分語(Class)の組み合わせによるネーミング標準を紹介。
データ項目は大きく3つの要素から成り立っているとの考え方に基づき、要素となる単語の用語集を整備し、
それら用語の組み合わせによって硬毛を決める。

<h3>ドメインとは</h3>
ドメインは、データの型やデータの取りうる値、データの範囲の規定でデータ項目の組成が決定される。次に、ドメインを決定するにあたり、「区分」がポイントとなる。例えば、口座種別によれば1:定期預金 2普通預金、3 当座預金などのように定義する。そうすることで、ドメイン上でバリデーション(有効値)を規定することで個別の設定が不要になる。
<h3>ドメインの分離</h3>
ドメインをどのレベルまで定義するかは悩ましいいところである。まず、ドメインを2分割に分ける.
共通ドメインと業務固有ドメインである。共通ドメインは基本コード、氏名、住所など「業務に関連することなく」使えるドメインを指す。一方で、業務ドメインは言葉通り、業務に関連するドメインを指す。例えば、ECであれば
仕入れや物流、購入などといった内容である。
共通ドメインは、組織、、商品に関係なくドメインを扱う リソース系ドメインを指す。

一方で、業務固有ドメインは


<h3>ドメインと用語集をもとに因数分解</h3>
ドメインにドメイン名をつけていく必要がある、そのために「因数分解」をしていく必要がある。
データ標準化でもいかにどんな要素の組み合わせかを知る必要があり、因数分解のように、あるデータ項目を
「因数分解」のように分解する必要がある。


<h3></h3>
ドメインの定義、つま理因数分解が終われば、次は要素の組み合わせを光量する必要がある。
主要後、修飾語、文理分区語に分解する。
例えば、顧客のメールアドレス、顧客の住所であれば、顧客が就職後にあたる。
メールアドレスと住所については、分類区分語にあたる。

::: note
ドメインを因数分解し、何を示しているかを明確化
→その上で、主要語、就職語、分類区分語にさらに分解する。

ここでは例を表示しないが、スプレなどで表を作成しエンティティ、データ項目ごとに表でまとめることがポイントである。
ここでの目的は**データ項目の標準化であり、データ項目を正式にドメインに区分させることがポイントである。**
なので、そのデータが何のデータであるのかを
**主要語や修飾語、区分単語句に分離することがポイントである**
:::

<h3>ネーミング項目を遵守するツール</h3>
いくら、ルールを設定してもモデラーが別々作業すると、同じ名前のデータ項目や同じ意味を持つ項目が定義されてしまう。これを防ぐために、自動検証&生成ツールを作成すると便利。
Ex エクセルなど


<h3>データ項目を構成する要素</h3>
ドメインを割り付けたり、構成単語に分解するのは、データ項目を真に理解するためである。理解したデータ項目について、知り得た情報をデータ項目の属性として定義する。

    - 名称
        属性名:モデル上の論理名称(日本語)
        カラム名: DBMS実装上の名前
        モデルとしての名前である日本語名をそのまま用いることも可能
    - 意味定義
    - ドメイン
    - データタイプ(文字型、数値型、日付型)
    - 桁数(長さ)
    - デフォルト
    - ルール制約: ドメインで定義する有効値
Solr9、UUIDがダブルクォートされないってバグだったのよ。

### はじめに

業務でつかっているSolr、先月バージョン8.7から9.5に移行した。solrconfig.xml の書式の一部が変更になった点、修正して使っていたのだけれど、表題にあるとおりのバグにぶち当たってしまったのよ。

### どんなときに困るのか

バグの内容は、クエリを投げて得られるデータがダブルクォートされず、その処理ソフトウェアを開発していたメンバーが発見した。AWS Cloutfront で動作するJSでの処理だったものだから、想定される型どおりのデータが返ってこないことでにっちもさっちもいかず・・・。

### 結論は、「ver.9.6 以降を使おうぜ」

対処法を探していくが、日本語では情報が得られなかった。Solr9、日本語の情報少なすぎ。とくに「利用ソフトウェアの開発」についての情報が少なすぎ。ReactとかVueJSとかで利用する方法についての情報が皆無。なんでSolr4tとか6でみんな情報止まってるの？

MySQLもそうだけど、データベース的に使われるソフトの最新版運用、ソフトウェア開発に関する情報、もっとみんな共有しようよ、と呼びかけたい。


・・・と、結局、Apache.orgのIssuesのSolrのコーナーで、開発メンバーが見つけた。今年１月にバグ報告されていて、4月27日リリースの最新版で修正されてる、とのこと。


https://issues.apache.org/jira/browse/SOLR-17110?jql=project%20%3D%20SOLR%20AND%20text%20~%20%22uuid%22

### 何を言いたいか。

Solr を利用したアプリケーション開発で困ったこと、解決策は、日本語でも情報共有したいです。私も気づいたことは書くけど、みなさんも何かあったらよろしくお願いします。
ストロングパラメーターについて

ストロングパラメーターの理解が難しいので一度整理します。

### 1.ストロングパラメーターとは
Web上で受け取ったパラメーター（変数）が安全かどうかを検証したうえで取得する仕組み。
安全ではない（意図しない）データの登録や更新を未然に防ぐことができる。

### 2.仕組み
メソッドにあらかじめ許可するカラムを指定しておく。

### 3.対象のデータ
ユーザーがフォームから入力した内容。
（viewから送られてきた情報）

### 4.対象の機能
登録・更新機能。
（コントローラー上で定義されたcreate.updateメソッド）


### 5.deviseを使った場合とそうでない場合を整理
#### deviseを使っていない場合
コントローラーにストロングパラメーターを記述。
permitメソッドを使って許可するキー（カラム名）を記述する。
```ruby:user_controller.rb
private
def user_params
  params.require(:user).permit(:email, :nickname)
end
```
上記の場合、**Userモデルに存在するemailカラムとnicknameカラムの情報を許可する**。他のカラムに関しては許可しない。

#### deviseを使った場合
```ruby:devise_create_users.rb
class DeviseCreateUsers < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""
      t.string :name                
      t.text   :profile                    
      t.text   :position            
      t.integer :user_id
    ## 略　
  end
end
```
Gem内に処理が記述されているのでコントローラーを編集できないためapplication_controllerに記述する。
**permit(:処理名, keys: [:許可するカラム名])**
処理名にはもとから設定されているsign_in, sign_up, account_updateがある。
before_actionで各アクションの事前に処理をする記述をする。
if: :devise_controller?でコントローラーに関するアクションが処理された時に実行する設定。
```ruby:application_controller
before_action :configure_permitted_parameters if: :devise_controller?

  private
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :profile])
  end
end
```
モデルではname,profile,positionカラムが追加されているが、今回許可されているのはnameとprofileのみとなる。
また、emailとpasswordはあらかじめ備わっているので追加する必要はない。
5年分の思いやりリリース

# はじめに

誰にでも使いやすい最新かつ安定したOSを目標に開発されているオープンソースのOS、Ubuntuの最新版がリリースされました。

# LTSのサポート期間は5年間
Linuxディストリビューションの中でもシェアの高いUbuntuは2年おきに長期サポート版(LTS:Long Term Support)をリリースしており、そのサポート期間は5年間です。

# 戴冠式
Ubuntuはバージョンごとに生き物にちなんだコードネームを持っていて今回リリースされた24.04 LTSはNoble Numbat。この高貴なナンバットをインストール(あるいはアップデート)して新しいLinuxを戴冠しましょう。

https://jp.ubuntu.com/blog/the-coronation-of-a-new-mascot-noble-numbat-jp

# Ubuntuは思いやりでできている
Ubuntuの名は南アフリカのズールー語で「他者への思いやり」を意味するウブントゥからきています。
5年分の思いやりを体感できるこの春を楽しんでください。

# さいごに
「ソフトウェアがもたらす利益を世界中に与え広げよう」というUbuntuの哲学はオープンソースムーブメントの礎となるものです。
LinuxのオープンコミュニティLinuC Open Networkも同様の思いで活動しています。
LinuC Open NetworkがLinuC 101向けの無料勉強会を開催します。
これから受験を考えている方、既に取得しているけど復習したい方も、この機会にぜひ。

参加申込はこちらから

https://linuc.org/study/seminar/5400/
【Python 型ヒントTips】for文で型ヒントを使う方法

# はじめに
Pythonのfor文で型ヒントを使う方法のメモ。

# 動作確認環境
* Python 3.8.10

# 方法

ループの前で変数を宣言する。

```python
i: int
for i in range(5):
    pass
```

# 参考

https://stackoverflow.com/questions/41641449/how-do-i-annotate-types-in-a-for-loop
VSCodeでpythonのdocstringの色を変更する

## settings.jsonでコメントの色を設定する

settings.jsonを開き、下記の設定を追加することでdocstringの色を変更できる。

```
  "editor.tokenColorCustomizations": {
    "comments": "#d8bfd8", // インラインのコメントの色
    "textMateRules": [
      {
          "scope": [
              "string.quoted.docstring.multi.python"
          ],
          "settings": {
              "foreground": "#d8bfd8",  // docstringのコメントの色
              "fontStyle": "italic"
          }
      }
  ]
```
「ことのはたんご」で連勝

## 概要

「[**ことのはたんご｜単語推理ゲーム**](https://plum-chloride.jp/kotonoha-tango/index.html)」はシンプルでとてもよくできたゲームです。正解にたどりつけないと悔しいので、JavaScript の勉強を兼ねて対策用のプログラム「[**ことのはレンズ**](https://sense-n-react.github.io/Kotonoha-Lens/kotonoha.html)」を作りました。

### 使い方

**ことのはたんご**の評価（緑、黄、灰）の通りに [**ことのはレンズ**](https://sense-n-react.github.io/Kotonoha-Lens/kotonoha.html) に文字を入れるだけです。

<img src="https://sense-n-react.github.io/Kotonoha-Lens/Screenshot.png" width="240px">

### 仕組み

約8000語のひらがな５文字の単語をデータベースとして保持しています。
これは人間の語彙力、記憶を助けるものです。
このデータベースは不定期に更新しています。

以下の手順で「候補の単語」を提示します。

1. **ことのはたんご**の評価に従い正規表現を生成
2. その正規表現に一致する単語をデータベースから抽出し、あいうえお順にそれを表示
3. 抽出した単語に含まれる文字の出現頻度を計算し、出現頻度順にそれを表示
4. データベースの単語に対して「出現頻度の高い文字」が含まれている度合いで評価
5. 4.の評価が高い順に「候補を絞り込む単語」として表示

### 注意

* 辞書の単語が入力可能とは限りません。
* 辞書にない単語が出題された場合には正解にたどり着けません。その場合には [語尾検索エンジン](https://bluesnap.net/gobisearch/)のようなサイトを利用して自力で正解してください。
* 入力の度に上記の処理が走るため画面更新がギクシャクします。
* HTML に不慣れなため画面のレイアウトがイマイチです。

### 辞書

[https://github.com/sense-n-react/Kotonoha-Lens/blob/main/kotonoha.txt](https://github.com/sense-n-react/Kotonoha-Lens/blob/main/kotonoha.txt)


# リンク

https://plum-chloride.jp/kotonoha-tango/index.html

https://bluesnap.net/gobisearch/

https://github.com/sense-n-react/Kotonoha-Lens/tree/main
React公式ページで学んでみた18（備忘録）

# はじめに
初めまして！
エンジニアになって数年、今まで本を読むだけでしたが、もっとプライベートで楽しみながら成長したい！自分が学んだ足跡を残していきたい！と思い記事を書きました！
最終的には自在に開発できるようになりたいと思っています。:triumph:
いろいろな記事を参考にさせてもらっています。:bow_tone2:
その中でもこれってどういう意味？とかつまづいたところを念入りに書いていこうかと思います。:fist:

# 今回の目的
前回の続きです。今回は「そのエフェクトは不要かも」。被る部分もあると思いますが、後で振りかえって深掘りするきっかけになるのが理想です。細かく書くと大変なのであっさりめ。

https://qiita.com/mr_noppo/items/86089370e89f7bfdcda5

# 使用したものや事前準備
・Macbook Pro

# 主に参考にさせていただいた記事
https://ja.react.dev/learn/you-might-not-need-an-effect

# エフェクトも避難ハッチ
refは、レンダリングに関与しない避難ハッチだったが、Effectも同様である。主に外部システムとの同期など、Reactの外の処理で使用される。stateの変更に合わせてstateを変更する等、React内で完結できるものをEffectで使用する必要はない。

# エフェクトの使用パターン
・データフェッチ
・イベントリスナーの登録解除
・タイマーの設定クリア
・リソースのクリーンアップ

# Effectとイベントハンドラの区分け
Effectは、値がリアクティブで常にキャッチアップが必要な時に使用する。イベントハンドラはユーザーに実施させる時、選択する。
リアクティブな値を依存配列に含めたくない場合は、useEffectから外に出す。
ロジックであればuseEffectEventを使用するとあるが試験的なもののため注意。

# エフェクトが不要・NGパターン
・state変数を更新するためのEffect。レンダー後に実施されるため再度レンダリングされることとなる。
・ユーザーイベントに使用すること。イベントハンドラで対応するのが基本。（バッチ処理としてまとめられる）
・上記の例に続いて、Effectを数珠つなぎにすることもNG。stateの更新用関数が含まれる場合、複数のレンダリングが発生してしまう。イベントハンドラでまとめることができるのであれば、そちらで対応する。

# Effectを使わない対応
下記２点が基本的な対応
・stateによるレンダリング中に計算する
・コンポーネントのkeyを変更することにより、新しいコンポーネントとして対応させstateを破棄させる

下記は滅多にないことと可読性が落ちるがこういう対応も可能
・前回のprops情報を保持し、変化があれば更新用関数を実施する。（レンダーが再実施される）

# 他
・Lintを使っている時にリアクティブな値（固定値ではない変数）を依存配列に含まないとエラーになる。

# 最後に
後半の内容は、実用的な考えに置き換えることは自分にはまだ難しかったです。一応一通り学べたことはとても良かったと思います！
Symbol ノードのブロック同期速度を比較してみる

とある検証のために作りました。
簡易的なノード間の同期速度を比較するツールです。

https://github.com/ccHarvestasya/sync-speed-checker

## インストール

github からクローン。
```bash
git clone https://github.com/ccHarvestasya/sync-speed-checker.git
```

中に入る。
```bash
cd sync-speed-checker
```

## パッケージのインストール
(開発はyarnを使用しています)

yarn の場合はこっち。
```bash
yarn install
```

npm の場合はこっち。
```bash
npm install
```

## 接続ノード一覧作成

`hostlist.txt` に比較したいノードリストを入力する。
入力数分 WebSocket で接続するので数はほどほどに…

```bash
vi hostlist.txt
```

## 実行

yarn の場合はこっち。
```bash
yarn start
```

npm の場合はこっち。
```bash
npm run start
```

## 実行結果

最初に来た、新ブロック通知を基準にどれだけ時間差があるか何となく計測します。
一カ所でも WebSocket の接続に失敗したり、切断すると終了します。

出力フォーマットは以下の通り。
```
時間差:ブロック高:ホスト名
```

実際動かすとこんな感じ。
```
harvestasya@sakia:/opt/sync-speed-checker$ yarn start
    0ms: 3278827: finnel.harvestasya.com
  583ms: 3278827: pasomi.net
    0ms: 3278828: finnel.harvestasya.com
   71ms: 3278828: pasomi.net
    0ms: 3278829: pasomi.net
  450ms: 3278829: finnel.harvestasya.com
    0ms: 3278830: finnel.harvestasya.com
 1020ms: 3278830: pasomi.net
```

毎ブロック1秒以上遅れてるとあまり良くない…かな？
streamlit app を初めて開発・公開した件

# 1. streamlitとは

StreamlitはPythonのウェブアプリケーションを構築するためのフレームワークの一つです。Pythonのコード内に直接書かれたコマンドでウェブアプリケーションを構築するため、HTMLやCSSなどのファイルを扱う必要がありません。さらに、作ったアプリをStreamlit Sharingと呼ばれるサービスを介して、無料でデプロイ・公開できるのが大きな魅力です。

# 2. 何を作ったか:

以前、kaggleのtarotカードのデータを用いてpythonで作成していた占いゲームを、Streamlit用に焼き直すこととしました。内容は、3枚のカードをランダムに選び、カードとカードの意味する内容を表示するという、単純なものです。

https://www.kaggle.com/code/stpeteishii/tarot-reading

# 3. 開発過程:

まずはlocalで開発して動作確認まで行いました。streamlitをinstallすると共に、Pythonの仮想環境を作成して有効化します。

```bash
pip install streamlit
python -m venv .venv
source .venv/bin/activate
```

フォルダ内は
- app.py
- requirements.txt
- dataホルダ
- .venvホルダ

ターミナルで以下を起動しlocalhostで動作確認。
（注意）ホスト環境で動いたとしても、デプロイされるのは仮想環境なので、仮想環境下で動作確認することが大切です。

```bash
streamlit run app.py
```

スクリプトを.venvと共にgithubにpushします。

Streamlit Community Cloud アカウントを作成後、Streamlit Sharingにgithubの該当リポジトリを登録して動作を確認します。

**しかし**、ここでエラーが発生します。ホスト環境では動いたのに。
```text
AttributeError: module 'cv2.dnn' has no attribute 'DictValue' 
```
なかなか解決方法が判らないので、app.py について、cv2でなくPILを使って書き直し、pushし直しました。PILを使ったコードでは問題は起きずデプロイに成功しました。

# 5. コード:

app.pyのコード内容を示します。st.xxx の部分でWebに表示する内容を設定しています。

```python
import streamlit as st
import pandas as pd
import os
import random
from PIL import Image

data_dir = './cards'
files = os.listdir(data_dir)
data = pd.read_json('./tarot-images.json', orient='records')
data = pd.json_normalize(data['cards'])
data1 = data[['name', 'img', 'fortune_telling']][data['arcana'] == 'Major Arcana']

def predict():
    rand3 = random.sample(range(22), k=3)
    fortune = []
    name = []
    file = []
    for i in rand3:
        fortune.append(data1.loc[i, 'fortune_telling'][0])
        name.append(data1.loc[i, 'name'])
        file.append(data1.loc[i, 'img'])
    times = ['Past', 'Present', 'Future']
    images = []
    for i in range(3):
        img = Image.open(os.path.join(data_dir, file[i]))
        images.append(img)
    return times, fortune, name, images

st.title("Tarot Reading!")

if st.button("Predict Your Fortune"):
    times, fortune, name, images = predict()
    col1, col2, col3 = st.columns(3)
    with col1:
        st.image(images[0], caption=name[0], use_column_width=True)
        st.write(f'Your {times[0]} is {name[0]}.')
        st.write(f'{fortune[0]}.')
    with col2:
        st.image(images[1], caption=name[1], use_column_width=True)
        st.write(f'Your {times[1]} is {name[1]}.')
        st.write(f'{fortune[1]}.')
    with col3:
        st.image(images[2], caption=name[2], use_column_width=True)
        st.write(f'Your {times[2]} is {name[2]}.')
        st.write(f'{fortune[2]}.')

```

# 6. アプリへのリンク:
![tarrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311614/65c4b7ca-6d09-fe4a-1f8d-d1e1b07b532d.png)

https://app-tarrot-reading-mlnessbppgllzg2dns5pfc.streamlit.app/

# 7. 今後の展望:
streamlitのおかげで、pythonコードのWebアプリ化のハードルが一気に下がったように思います。機械学習でトレーニング済みのモデルを使ったアプリなども作れそうな気がします。

# 8. 参考文献やリソース:
https://streamlit.io/
https://docs.streamlit.io/
https://share.streamlit.io/
分布(distribution)とは

# 分布(distribution)

・分布とはどの値にどれくらいデータが存在するか表したもの
・データの分布を図で表すことができる
・データを図で可視化することにより、データの大きさや偏りがわかる


```
# データ準備

import seaborn as sns

df = sns.load_dataset('tips')
df['tip_rate'] = df['tip'] / df['total_bill']
```

# ヒストグラム
#### データが連続変数の場合はヒストグラムを使う。
※連続変数とは連続した数値で表現できる変数です。身長や体重、テストの点数など

・一つの連続変数の分布を表すのに使う

:::note warn
複数の連続変数の分布を見たいとなると、違う図が必要。
:::

・各棒の区間に間隔がない
・横軸はデータの区間で区切られている
・ビン(bin)を使ってその区間の度数(frequency)を表す



```
sns.distplot(df['tip'], kde=False)
```



![histgram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780659/b0aa8798-d529-8dd6-b88e-cba04a3d776a.png)

:::note warn
seabornのバージョン(sns.__version__)が0.11.0以上ならsns.displot()を使う
:::



# 棒グラフ
#### データがカテゴリ変数の場合は棒グラフを使う。
※カテゴリ変数とは一般的に数や量で測れない変数。性別（0：男性、1：女性）、職業、地名や行政名、意識や実態に関する質問に対する回答（１．はい ２．いいえ）など

・一つのカテゴリ変数の分布を表すのに使うことができる
・各棒の区間には間隔がある
・横軸はカテゴリ変数のとりうる値
・棒を使ってその値の度数(frequency)を表す

```
sns.catplot(x='time', data=df, kind='count')
```
![catplot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780659/20079639-affd-4003-0002-fb60507ad677.png)
Nextjsでコンポーネントテストを書いていたら、renderで落ちた

# はじめに
現在Nextjsで開発をしていたのですが、コンポーネントテストがどうにも通らなかったので共有します

# 問題
npm run test(jest)を実行すると以下のエラーが出た
```
Error: Uncaught [Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.]
```

# 解決策
> テストする関数コンポーネントのasyncを削除する

コンポーネントの中で非同期な処理も行っていたので、それを外部に切り出して関数コンポーネントの
```tsx
export const コンポーネント名 async() => {}
```
のasyncを削除すればOK

# 終わりに
外部に処理を切り出すところまではできてたんですが、asyncを削除してなくてわりと解決に時間がかかっちゃいました

# About Me
- twitter

https://twitter.com/shunii_hack
vscodeからEC2接続時に出る「Permission denied (publickey,gssapi-keyex,gssapi-with-mic)」の解決法

# 概要
- vscodeからEC2インスタンスへリモートSSH接続する際にハマり、いろんな記事を調べて試してみたが、うまくいかなかった。色々試してみて、自分なりに納得したので数ある方法の一解決方法として記録しておく。

# 対象
- vscodeからEC2へのSSH接続で「Permission denied (publickey,gssapi-keyex,gssapi-with-mic)」が出て困っている人

# 書かないこと
- EC2周りの設定や説明
- EC2接続時に使用するsshコマンドの詳細

# 環境
- PC : Mac 
- OS : Ventura 13.3
- SSHクライアント : [Remote SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh)(vscode拡張機能)

# 注意すること
いろんな人の記事をみて、注意することが書いてあったので、わかる範囲で列挙する

- 「ssh -i {path}/{key-name}.pem ec2-user@xxx.xxx.xxx.xxx」の秘密鍵のPathは絶対パスである必要がある
- 秘密鍵ファイルは他のユーザーがアクセス出来ないフォルダに配置していなければならない
  - 秘密鍵ファイルは`.ssh`ディレクトリ配下に配置するのが良い
  - .sshディレクトリの権限を700で設定しておくのが良い
    ```
    // 所有者に対して読み取り、書き込み、実行の権限を設定し、グループメンバーや他のユーザーには一切の権限を与えない設定。
    chmod 700 ~/.ssh
    ```
- 適切なディレクトリに配置して、適切な権限を付与してもエラーとなる場合は.ssh配下のconfigファイルが正しく記述されているか確認する

# 設定手順

上記注意事項を踏まえた上で設定していく

上記前提でも記載の通り、[Remote SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh)(vscode拡張機能)を使用した手順（他のSSHクライアントを使用した際にもおそらく変わらないと思う）

1 .sshディレクトリに移動する
  ```
  cd ~/.ssh
  ```

2 configファイルがあるので開く

:::note info
インフォメーション
vscode->Remote SSHでの設定方法を説明しておりますが、vimや他のテキストエディタを用いてconfigファイルを開いていただくでも問題ないです
:::

1 vscode->Remote SSH画面からconfigファイル選択画面を表示する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531653/3f1d8591-54ce-3702-67c4-6655661a0586.png)

2 表示するconfigファイルを選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531653/342f6401-47dd-9a57-6546-b95428c2a96c.png)

3 configファイルを開いたら、設定を記述する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531653/498e2167-ec0e-af59-5415-830e8bd75313.png)

記述例

:::note warn
注意
IdentityFileの鍵ファイルのパスは絶対パス指定なので、.sshディレクトリにてpwdコマンドを叩き、取得したパスを指定するようにしてください
:::
    ```
    Host {EC2 public IP Address}
      HostName {EC2 public IP Address}
      IdentityFile /Users/{username}/.ssh/my-key.pem
      User ec2-user
    ```

4 接続する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531653/74bda396-af60-aa9e-c64b-2a90eb8fb325.png)


# まとめ

### 見る必要があるポイント
 - .sshディレクトリ配下に鍵ファイルを配置しているか？
 - .sshディレクトリと鍵ファイルの権限は適切か？
 - configファイルは正しく記述できているか？
 
上記手観点を踏まえた上で試行錯誤したところ私は解決することができたので、同じような悩みを持つ人の一助になれれば幸いです。
API Gateway経由でLambda呼び出すときのマッピングテンプレート

## はじめに
BedrockにAPIリクエスト投げるLambda書いたからフロントエンドも作りたいな…と言いつつ数か月経ってしまった。
API Gatewayにリクエスト投げるシンプルなhtml書いてS3+CloudFrontのベタな構成……と思ったらAPI Gatewayにリクエスト投げるところで詰まったので、とりあえずその部分を記事化。

Lambda書いたときの記事

https://qiita.com/Pretzelisa/items/61c4d3838bb6ac7ff561

https://qiita.com/Pretzelisa/items/e9f873806ed40d853e71

## 1. ハマリポイント

Lambdaに引数keywordを渡す必要がある。マネコンのLambdaのエディタからテストしたときは以下のようにJSONを手打ちして問題なく動いていた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3458266/b3f56c84-2487-1393-ce1d-eafc513348a3.png)

…が、API GatewayにLambdaを統合し、API GatewayにPOSTリクエストを送ったとき、どうも上手く引数が渡らない。

KeyErrorとか言われる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3458266/1413d9d9-b5fa-7cdb-cc0c-f35e42b82e08.png)


調べたところ、POSTリクエストの本文だとフォーマットが都合よくJSON形式にはなってくれないみたいなので、API Gateway側でマッピングテンプレートを設定し、渡す値を整形する必要がある。

おそらく以下のようなフォーマットで渡っちゃってるみたい

> キーと値は、 '&' で区切られ、キーと値の組が '=' で結ばれた形でエンコードされます。キーや値が英数字以外の文字であった場合は、パーセントエンコーディングされます。

https://developer.mozilla.org/ja/docs/Web/HTTP/Methods/POST

## 2. マッピングテンプレート設定方法

API Gateway リソース から「統合リクエストの設定」横の編集ボタンを押す。
![APIGateway.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3458266/7a371773-f228-8eaa-6d35-d4a880e3d545.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3458266/629f3d4e-6470-77e9-dbff-2cfaa8128909.png)

マッピングテンプレートのコンテンツタイプに`application/x-www-form-urlencoded`を入力する。
テンプレート本文はJSONフォーマットにPOSTの本文で渡された値をはめ込むイメージで書く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3458266/ef1e9f6b-0b3b-9e01-9084-441d33d91d85.png)

今回書いたLambdaは引数1つなので、マッピングテンプレートも以下のようにシンプルなものでいけた。
```
{
    "keyword" : $input.json('$')  
}
```
POSTリクエストの本文がもっと複雑な構造ならテンプレートももっと複雑になるはず。複数のキーと値の組があるなら&で分割してあげるとか。

`$input.json('$')`だと何もフィルタしないけど、`$input.json('$.hoge')`とかで指定してあげると特定のフィールドだけ抽出できそう。

マッピングテンプレートについて(サンプル多数)

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/models-mappings.html

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html

JSONPathの詳細

https://goessner.net/articles/JsonPath/

## 3. html

とりあえずAPI GatewayにPOSTリクエスト投げるだけのシンプルなやつ。
formのactionのURLは適宜書き換え。

```html
<html>
<head>
<meta charset="utf-8">
<title>CreateImages</title>
</head>
<body>
<form method="POST" action="https://restapi_id.execute-api.region.amazonaws.com/stage_name/">
    <div><label>生成したい画像のキーワード：<input type="text" name="keyword"></label></div>
    <input type="submit" value="Submit!">
</form>
</body>
</html>
```
REST API呼び出し

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-call-api.html

## おわりに
API GatewayのマッピングテンプレートでLambdaからの戻り値も整形できそう(統合レスポンス)なのでこちらも設定が必要そう。
Content-Typeのところから理解がぼんやりしてるのでコード改善しつつAPIまわりも勉強したい……

## 参考サイト

https://maitakeramen.hatenablog.com/entry/2019/02/22/105438
Laraverlのマイグレーションではまった話

## 概要
- マイグレーションを行ったところ、実行順でテーブル作成ができず解決に時間がかかってしまった

## 事象概要
```bash
$ php artisan migrate

Deprecated: PHP Startup: Use of mbstring.internal_encoding is deprecated in Unknown on line 0

   INFO  Running migrations.

  2024_04_17_135308_XXX_XXX_XXX ............................................................. 622ms FAIL

   Illuminate\Database\QueryException 

  SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table 'ZZZ' (Connection: mysql, SQL: alter table `YYY` add constraint `YYY_XXX_ZZ_foreign` foreign key (`XXX_ZZ`) references `ZZZ` (`hoge`))

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:829
    825▕                     $this->getName(), $query, $this->prepareBindings($bindings), $e
    826▕                 );
    827▕             }
    828▕
  ➜ 829▕             throw new QueryException(
    830▕                 $this->getName(), $query, $this->prepareBindings($bindings), $e
    831▕             );
    832▕         }
    833▕     }

      +9 vendor frames 

  10  database/migrations/2024_04_17_135308_XXX_XXX_XXX.php:11
      Illuminate\Support\Facades\Facade::__callStatic("create")
      +24 vendor frames 

  35  artisan:35
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
```

このような形で、エラーが発生していた

## 解決法
簡単にエラーの内容をまとめると、`外部キー制約`によりあるはずのテーブルが存在しないために発生している

そのため、生成順を気を付ける必要がある

参考サイト

https://xtimmune.com/blog/laravel_migration_procedure

参考サイトにもあるように、生成順をいじるにはマイグレーションファイルの先頭にあるYYYY_MM_DD_hhmmssが古い順で実行されるため、実行が速くあるべきものを前に行くように調整する必要がある

```bash
php artisan migrate
```

本来はこれを行うことで、古い順から再実行されるはずであるが、いろいろとやりすぎたせいか自分は以前の順番で実行されてしまった。

そこで今回残したいデータはなかったこともあり、データをすべて削除して再実行するように変更した

:::note alert
データをすべて消す処理を事前に挟むため、やむを得ない場合を除きほかの手段を利用することを推奨します。
また、もし本番環境で実行する場合は必ずバックアップを取るようにしましょう。
本当にすべてのテーブルを削除するので注意です
:::

```bash
php artisan migrate:fresh
```

これをすると、テーブルが初期化されるためすでにテーブルがある等のエラーがなく、単に順番による依存関係のみを考えればよくなります。

が、、最終手段なので本番環境を触っている人は注意してください


## まとめ
外部制約に苦しめられたが、必ず必要な部分であるため開発段階で調整できてよかった

しかし、今後開発が進む中で運用中のシステムを変える場合は、また違ったアプローチで常に気を使う必要があり、大変に難しい問題であるとも感じた。
二項ブランド選択モデル

# はじめに

最近、照井先生著「[ベイズモデリングによるマーケティング分析](https://www.amazon.co.jp/%E3%83%99%E3%82%A4%E3%82%BA%E3%83%A2%E3%83%87%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E3%82%88%E3%82%8B%E3%83%9E%E3%83%BC%E3%82%B1%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E5%88%86%E6%9E%90-%E7%85%A7%E4%BA%95-%E4%BC%B8%E5%BD%A6/dp/4501623500)」でブランド選択モデルや階層ベイズによる異質性モデリング等を勉強しているので、勉強記録として残しておく。

勉強しながらポストしていくので細切れになるが、[all-in-oneなもの](https://kyohashi.github.io/DS_study/brand_choice_model/ME_report.html)はGitHubにおいておく。今回は二項ブランド選択ロジットモデルだけだが、最終的には階層ベイズを用いた多項ブランド選択モデルのギブスサンプラー実装まで取り組みたい。

# ブランド選択モデル

消費者のブランド選択行動は、効用関数および効用最大化原理を用いてモデル化される。いま、消費者 $h$ ・ブランド $i$ ・時期 $t$ における効用関数 $U_{iht}$  が

$$
U_{iht} = V_{iht} + e_{iht}
$$

のように書けると仮定する。ただし、 $V_{iht}$は諸々のマーケティング活動等によって規定される確定項であり、 $e_{iht}$ はその他の確率的部分（例：心理的な揺れ）を表している。効用最大化原理とは、「消費者は自身の効用を最大にするような選択肢を取る」という仮定のことである。消費者は常に合理的なのか？と問われれば恐らくNOだが、効用関数には確率的揺れを仮定しているため、そのあたりの「場当たり性」のようなものも考慮されている。

## ２項ブランド選択モデル

いま、ブランドAとBの選択肢があるとする。またシンプルに確定項が $V_{iht} = p_{iht} \beta$ のように各ブランドの値段によってのみ規定されるとする。この場合ブランドAを選択する確率は 

$$
P(p_{Aht}\beta + e_{Aht} > p_{Bht}\beta + e_{Bht}) = P(e_{Aht} - e_{Bht} > -(p_{Aht}-p_{Bht})\beta)
$$

と書ける。確率変数 $e_{Aht}-e_{Bht}$に極値分布を仮定する場合をロジットモデル、正規分布の場合をプロビットモデルと呼ぶ。途中式は省略するが、ロジットモデルの場合のブランド選択確率は

```math
\begin{align}
P(\text{Choice A}) &= (1 + \exp\{-(p_{Aht}-p_{Bht})\beta\})^{-1} \\ 
P(\text{Choice B}) &= 1 - P(\text{Choice A})
\end{align}
```

と導出できる。簡単な実験により、最尤推定法でパラメータ $\beta$ を求めてみよう。

```r
# Define Choices
choices <- c(1,0,0,1,1) # 1:A, 0:B
price_A <- c(100, 120, 120, 100, 100)
price_B <- c(110, 110, 110, 110, 110)

# Log-Likelihood of Logit model
log_likelihood <- function(beta){
  prob_A <- 1 / (1 + exp(-(price_A - price_B) * beta))
  loglikelihood <- sum(choices * log(prob_A) + (1-choices) * log(1 - prob_A))
  return(-loglikelihood)
}

# Estimation using optim function
init_value <- 0
result <- optim(par = init_value, fn = log_likelihood, method = "BFGS")
```

```r
> print(result$par)
[1] -2.15183
```
$\beta$がマイナスということは、値段が低い方が相対的に選択されやすいことを意味しており、推定は上手く行っていそうだ。

本モデルは切片項(マーケティングサイエンスの文脈ではブランド固有の価値と解釈される重要な項)も無ければ説明変数も価格のみというシンプルなものだったが、ブランド選択モデルのチュートリアルとしては良かったと思う。

# 参考
- [ベイズモデリングによるマーケティング分析](https://www.amazon.co.jp/%E3%83%99%E3%82%A4%E3%82%BA%E3%83%A2%E3%83%87%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E3%82%88%E3%82%8B%E3%83%9E%E3%83%BC%E3%82%B1%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E5%88%86%E6%9E%90-%E7%85%A7%E4%BA%95-%E4%BC%B8%E5%BD%A6/dp/4501623500)
JavaScript ページをリロードしないと動かない(RubyonRails)

RubyonRailsにてフリマアプリ実装中、JavaScriptがうまく動かなかった件について。
初学者のアウトプット用記事なので、情報の信憑性の低さについてはご容赦ください。同じところで苦戦している初学者の方にも参考になれば幸いです。

当記事はRails７で実装した際の記録であり、具体的にはgemfileに以下のTurbolinksに関する記述がある場合を想定しています。該当しない場合は、当記事の内容が合わない場合がありますのでご注意ください。

```ruby:gemfile
# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
gem "turbo-rails"
```


# 不具合の具体的な内容
商品出品ページで販売価格を入力した時に、販売手数料と利益も同時に表示されるようにしたい。JavaScriptの実装後、ローカル環境で動作を確認したときに問題発生。JavaScriptのコードは問題なく書けているのに、商品出品ページに遷移しても動かない。なぜ？

商品出品ページを開いた状態でリロードすると、正常に動くようになる。でも、一度トップページに戻ってまた商品出品ページに遷移するとまた動かない、リロードすると動く、の繰り返し。

# ページ遷移だけで動かないのはTurbolinksが原因
原因を調べてみるとRailsにデフォルトで組み込まれているTurbolinksという機能が影響して、上記のような誤作動が起こっているようでした。Turbolinksを無効化することで、JavaScriptが正常に動くようになります。

ただし、Turbolinksはページ遷移を高速化するために組み込まれている機能なので、ユーザーが快適にアプリを使えるようするために必要な機能です。なので、無効化が必要な箇所にだけ以下の記述を行います。

# 解決方法（Tubolinksを無効化）
Tutbolinksを無効化する方法のひとつに、link_toにdata: {turbo: false}を追記する方法があります。

元の記述
```ruby:index.html.erb
<%= link_to('/items/new', class: 'purchase-btn') do %>
```
Turbolinksを無効化
```diff_ruby:index.html.erb
<%= link_to('/items/new', data: {turbo: false }, class: 'purchase-btn') do %>
```

トップページから商品購入ページに遷移する際のTurbolinksを無効化したいので、トップページのビュー（index.html.erb）に記述してあるlink_to（商品出品ページへのリンク）にdata:{turbo: failse}を追記しています。
# Turbolinksを削除すれば簡単？
Turbolinks自体を削除すればJavascriptが問題なく動くようになりますが、この方法はおすすめできません。理由は上記のとおり、Turbolinksはページ遷移の高速化をしているので、こちらの恩恵を受けられなくなるからです。
# まとめ
・Turbolinksの影響で、ページ遷移時にJavascriptが正常に動かないことがある。
・ページ遷移で動かなくても、リロードすると動くようになる。
・TurbolinksはRailsにデフォルトで入っているGem。
・Turbolinksを無効化するとJavaScriptが正常に動作するようになる。
・TurbolinksでRailsアプリのページ遷移を高速化している。
・link_toにdata: {turbo: false }を記述することで、無効化が必要な箇所だけ無効化することができる。
Git操作について

## Git操作について記載
※参考 兼 自身のメモ用
※随時追記

```bash:
# リモートリポジトリの複製
$ git clone <URL>
```

```bash:
# ブランチの作成（ブランチ名を指定しないと既存ブランチの確認ができる）
$ git branch ブランチ名
```

```bash:
# ブランチの切り替え
$ git checkout ブランチ名
```

```bash:
# ステージングエリアへの移行
$ git add
```

```bash:
# リポジトリへのコミット
$ git commit -m "コミットメッセージ"
# amendオプション（最新のコミット情報を変更できる）
$ git commit --amend -m "コミットメッセージ"
```

```bash:
# ブランチのマージ
$ git merge ブランチ名
```

```bash:
# リモートリポジトリへの反映
$ git push
```

```bash:
# ローカルリポジトリへの反映
# リモート→ローカルの追跡ブランチ
$ git fetch
# リモート→ローカルの作業ブランチ
$ git pull
```

```bash:
# 状態確認
$ git status
```

```bash:
# 変更履歴の確認
$ git log
```
C++でデバッグした時、表示されている行と実行されている行がずれる


# VSCode編(gdb)

## 原因1. lambdaの中にブレークポイントを張っている

最適化を無効にしているのにいろんなところにジャンプしまくる。
例: 170行目(ただの代入)でステップオーバーすると164行目に一度ジャンプして次のステップオーバーで171行目に戻ってくる 
![gdb_lambda_bouncing.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73072/c23e8fa9-b247-0914-cb04-6d579243695a.gif)

### 対策

普通の関数にする。。。


# Visual Studio編

## 原因1. エンコードの問題

以下のエラーが出ていたら該当。
`1>***.cpp(1,1): warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。`

### 対策

UTF-8 BOM付でファイルを保存する。
競プロで使用できるvscodeのスニペット（C++)

## はじめに
こちらは仮で上げているモノですので、清書したものをいずれ出す予定です。

## C++のスニペット
```cpp.json
	"C++ Template Class": {
		"prefix": "cpptemplate",
		"body": [
			"/**",
			"	* filename: ${TM_FILENAME}",
			"	* author: teniwoha",
			"	* X: @RyutaUrushi",
			"	* created: $CURRENT_MONTH/$CURRENT_DATE/$CURRENT_YEAR $CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND",
			"	* result: ",
			"	**/",
			"#include <bits/stdc++.h>",
			"using namespace std;",
			"",
			"/* alias */",
			"using ull = unsigned long long;",
			"using ll = long long;",
			"using vi = vector<int>;",
			"using vll = vector<ll>;",
			"using vvi = vector<vi>;",
			"using vvll = vector<vll>;",
			"using vs = vector<string>;",
			"using pii = pair<int, int>;",
			"",
			"/* define short */",
			"#define pb push_back",
			"#define mp make_pair",
			"#define SZ(x) ((int)(x).size())",
			"#define bit(n) (1LL<<(n))",
			"#define rep(i, a, b) for (int i = a; i < b; i++)",
			"#define rrep(i, a, b) for (int i = a; i >= b; i--)",
			"#define fore(i,a) for(auto &i:a)",
			"#define all(obj) (obj).begin(), (obj).end()",
			"#define rall(obj) (obj).rbegin(), (obj).rend()",
			"",
			"",
			"int main() {",
			"\t",
			"}",
			""
		],
		"description": "C++ Template Class"
	}
```
unity"パスワード入力でロック解除システム"作ってみた

# 完成イメージ
![スクリーンショット 2024-04-29 193842.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780171/872f347e-daa7-e4fd-a4e8-e10f35b5295b.png)
細かい仕様
・近づくと詳細を拡大し、離れると非表示
・ボタンを入力したらtetxの部分に現在入力している数字が表示される
・正しい数字を入力するとドアが破壊(動かすだけも可能)

## 実装手順
1.オブジェクトを用意(今回は画像にあるような無料のモデル)
2.1にコライダーを付け、isTriggerにチェックを付け、次のコードを実装
```
public GameObject Panel_1;
    public GameObject Key;
    void OnTriggerStay(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            //プレイヤーが圏内にいるときの処理
            //ボタン等を設置したPanelを表示させる。
            Panel_1.SetActive(true);
        }
    }
    void OnTriggerExit(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            //プレイヤーが圏内から出た時の処理
            //Panelを非表示にする。
            Panel_1.SetActive(false);
        }
    }

```

3.1で用意したオブジェクトと"同じ階層"にキャンバスを作成

EnptyObject
 --モデル
 --CAnvas
 のような形
 
4.キャンバスにPAnelを置き、画像のようにボタンを並べる。
これを上記のPanel_1に指定。
5.キャンバスに以下のコードを実装する
```
using UnityEngine;
using UnityEngine.UI;

public class PasswordEntry : MonoBehaviour
{
    public string correctPassword = "1234"; // 正しいパスワードを設定
    public Text displayText; // 入力された文字列を表示するText
    public GameObject door; // 扉のGameObject

    private string inputPassword = ""; // 入力中のパスワード

    public void AppendNumber(string number)
    {
        inputPassword += number;
        displayText.text = inputPassword;
    }

    public void CheckPassword()
    {
        if (inputPassword == correctPassword)
        {
            // 正しいパスワードが入力された時の処理
            door.SetActive(false); // 扉を非アクティブにする
        }
        else
        {
            // パスワードが間違っていた時の処理
        }

        inputPassword = ""; // 入力中のパスワードをリセット
        displayText.text = inputPassword;
    }
}
```
数字ボタンをクリックした時は AppendNumber 関数を呼び出し、Enterボタンをクリックした時は CheckPassword 関数を呼び出します。CheckPassword関数で入力された文字列と正しいパスワードを比較し、一致した場合は扉のGameObjectを非アクティブにしています。
### 完成
以上でplayerが近づくと入力パネルが出現し、正しい数字を入力するとドアが開くようなシステムが完成しました。
「Pythonで学ぶ衛星データ解析基礎」で衛星データを見てみよう（１）

# [Pythonで学ぶ衛星データ解析基礎](https://www.amazon.co.jp/Python%E3%81%A7%E5%AD%A6%E3%81%B6%E8%A1%9B%E6%98%9F%E3%83%87%E3%83%BC%E3%82%BF%E8%A7%A3%E6%9E%90%E5%9F%BA%E7%A4%8E%E2%80%95%E2%80%95%E7%92%B0%E5%A2%83%E5%A4%89%E5%8C%96%E3%82%92%E5%AE%9A%E9%87%8F%E7%9A%84%E3%81%AB%E6%8A%8A%E6%8F%A1%E3%81%97%E3%82%88%E3%81%86-%E7%94%B0%E4%B8%AD-%E5%BA%B7%E5%B9%B3/dp/429713232X/ref=sr_1_1?crid=3N1I2X4BV48E8&dib=eyJ2IjoiMSJ9.LbJ4hINPq3EU8wpXG7CqAOr45zhByJ5t2MypllKZ-vo33RORKjfpOTj3AVAgpEa0qps09OzZF4vTB7PBTb0ESwVrv94qLHznta4d2xNxl08rp0obnA8Q-n-9Od5FXZoEdiGXNeu9mwC8y7DT4-fdS2sn-fZ1HgoSQ2O5AkmPHnM.Nu3yk_AM14kAm6M6_j4E5mz0F7P3IQBxY33u4gVib8k&dib_tag=se&keywords=%E8%A1%9B%E6%98%9F+python&qid=1714371283&sprefix=%2Caps%2C472&sr=8-1)
この本は、２２年１２月に初版がでていますが、この本で使う衛星のAPIの仕様が変わってしまいました。
ノートブックなどが変更になっています。

## 衛星サイトのアカウントでの作り方
### Tellusアカウント
Tellusは、日本初のデータプラットフォームです。
https://www.tellusxdp.com/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/61ba08e7-6788-dea4-61d7-88c0c22e2aae.png)
会員登録から登録します。
Tellusは日本語ですので、比較的簡単に登録できるでしょう。Googleアカウントでも登録できます。
私はGoogleアカウントでサクッと登録しました。
### Landsatアカウント
https://earthexplorer.usgs.gov/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/d7113b9d-1aa5-2cd0-e07a-3b9eedf565a3.png)

右上のloginボタンを押すと、ログイン画面に移ります。ログイン画面の下にあるCreateNewAccountボタンを押してアカウントを作成します。

### Sentinel
このSentinelのアカウントが、サイトが変更になっていて注意が必要です。本に指定されているサイトにアクセスすると
https://scihub.copernicus.eu/dhus/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/adf810e6-e604-e0b5-656b-2890764e8a02.png)
https://dataspace.copernicus.eu
に遷移を求められます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/a5721c1c-d21a-75e3-9e8b-51add0dd2cab.png)
ここでLOGINを押して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/e4bd794e-a85c-87a0-9cac-2c3f67ebabe6.png)
このページで右下のRegisterを押して登録していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/641ceea1-ea77-fc09-7135-2d540e259b97.png)

登録はここまで。

いきなりSentinelのサイトが使えなくなっていて、焦りましたが、移動したサイトで登録ができます。
何を学べばいい？というときの指針になりそうな roadmap.sh

roadmap.sh というサイトがあるんですね。

https://roadmap.sh/

名前の通り、ロードマップをまとめたサイトで、ジャンルごとにどのような技術・製品を学んでいけばいいかが紹介されています。

自身のスキルアップに何が必要なのかが分からない人ももちろんですが、部下・後輩の指導方針に悩んでいる上司さんにも役立ちそうですね。

こういうものもあったのね、っていう気付きにもなるかもです。
作成したNext.jsアプリをAWS Amplifyで自動デプロイできるようにする

## 手順1
① VSCodeで新しいウィンドウを開く
② 新しいターミナルからターミナルを立ち上げ、　以下のコマンドを打ち込む。これによってreactアプリが作成されます
```
npx create-next-app amplifyapp
cd amplifyapp
npm run dev
```
③ AWSのアカウントを作成し、ルートユーザーとしてログインしておく
④ VSCodeの「フォルダを開く」からamplifyappフォルダを選択し、そこでもターミナルを開く
⑤ 確認のため、新しく開いたVSCodeのウィンドウでもターミナルに npm start と打ち込み、ブラウザが自動で立ち上がるか確認する。立ち上がればアプリ作成ができています。以下のようになるはずです

![スクリーンショット 2024-05-01 10.11.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3685116/e22bbf60-fcb1-2732-0a99-ad05a22b6f68.png)


⑥ AWSマネジメントコンソールを開き、検索欄にaws-amplifyと打ち込む。選択肢からaws-amplifyを選択し、開く。右にある「新しいアプリケーション」の「アプリケーションをホスト」を選択する。そしてgithubを選択し、「続行」ボタンを押せば「認証に成功しました。」と出てきます。（このタブは以降使用するので閉じないでください）
⑦ githubを開き、以下の写真のように新しいレポジトリを作成する。
![スクリーンショット 2024-02-06 12.03.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3685116/af8a209a-c010-8d58-ef61-87f08f85c6bf.png)
⑧以下の写真の「…or create a new repository on the command line」の部分をコピーし、ターミナルに貼り付け、実行する。
![スクリーンショット 2024-02-06 12.06.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3685116/40addd6d-7a89-358c-7bad-d52ff5b5314e.png)

⑨aws-amplifyコンソールに戻り一度リロードをして、「最近更新されたリポジトリ」で作成したレポジトリを選択し、ブランチを main　にして「次へ」ボタンを押す。その後のビルドの設定と確認は何も変更せずに「保存してデプロイ」ボタンを押す。
⑩プロビジョン、構築、デプロイという３つの段階がありますが、デプロイまで進んだ状態でそれらの表示の左隣にあるリンクを押すと以下のような画面が出てきます。これが表示されればデプロイは完了です。
![スクリーンショット 2024-05-01 10.13.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3685116/6ed32540-01c9-ffca-d69d-9903f100754c.png)

最後にコードの変更を自動的にデプロイできるようにします。どこかファイルの適当なところを変更した上でターミナルで以下のコードを打ち込むことで自動デプロイができるようになります。
```
git add .
git commit -m “auto-deploy”
git push origin main
```
amplifyコンソールを開き、デプロイまで進んでいることを確認し、以下のようにauto-deployと表示されていれば完了です。
![スクリーンショット 2024-05-01 10.16.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3685116/179e6949-56f5-6a07-6669-df3527522846.png)
javascriptで初期化した配列を作成する方法

## 方法その１：変数に配列を格納する
```javascript
const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
```

## 方法その２：for文で作成する
```javascript
const array = [];
for (let i = 0; i <= 9; i++) {
    array.push(i);
}
```

## 方法その３：Array.formを使う
```javascript
const array = Array.from({ length: 10 }, (v, k) => k);
```

## 方法その４：Array()を使う
```javascript
const array = [...Array(10)].map((v, i) => i);
```

:::note warn
Array(10)について補足
Array(10).map()と書きたくなるところだが、Array(10)で作成した配列は空配列ではなくemptyとなる。
※ここでの「空配列」とは[undefined, undefined,...] のような形のこと

emptyはnullでもundefinedでもない値のためmapが機能しない。
```javascript
Array(10).map((v, i) => console.log(i));
```
```:結果
[ <10 empty items> ]
```
:::
GPTsのWrite for meを使って競プロの入門記事を書いてみる

タイトルの通り、GPTsのWrite for meを使って記事を作成しましたという記事。
テーマを与えるとブログを自動生成してくれるツール。

入力したプロンプト

### User
１０００文字で競技プログラミングに関する紹介記事を書いてほしい
### GPT
競技プログラミングについての記事を書く前に、いくつか詳細を確認させてください。記事の対象読者は誰ですか？例えば、初心者や経験者など特定のグループを想定していますか？また、記事のトーンやスタイルに特別な希望はありますか？例えば、カジュアルな雰囲気やよりフォーマルな書き方を希望しますか？これらの情報をお知らせいただけると、より適切な内容を作成することができます。

### User
対象読者は同じ会社の社員で初心者向けを想定している。フォーマルな雰囲気で。
### GPT
ありがとうございます。対象読者とトーンについての情報が明確になりましたので、初心者向けでフォーマルな雰囲気の競技プログラミングに関する紹介記事を1000文字で作成します。以下に記事の概要を提示します。

概要
はじめに
競技プログラミングとは何か、その目的と魅力について簡潔に紹介。
約150文字
競技プログラミングの基本
競技プログラミングのルール、使用されるプログラミング言語、主要なプラットフォームについて説明。
約250文字
参加するメリット
論理的思考力の向上、問題解決スキルの発展、コーディング技術の向上など、競技プログラミングを通じて得られる利点。
約300文字
初心者が始める方法
具体的な学習方法、推薦される学習リソース、参加すべき初心者向けコンテスト。
約250文字
まとめ
競技プログラミングを始めることの価値についての総括。
約50文字
この概要に基づき、各セクションを詳しく書いていきます。それでは、まず「はじめに」のセクションから始めていきましょうか。

### User
お願いします
### GPT
はじめに
競技プログラミングとは、特定のアルゴリズムやデータ構造を用いて、与えられた問題を解決する技術と速度を競う知的スポーツです。この分野は、複雑な問題を効率的に解く能力を養うことに重点を置いています。競技プログラミングは、世界中の技術者や学生にとって、プログラミングスキルの向上だけでなく、論理的思考や創造性を養う場としても非常に価値があります。

競技プログラミングの基本
競技プログラミングでは、通常、短時間の中で複数のプログラミング問題を解くことが求められます。参加者は、C++、Java、Pythonなどの一般的なプログラミング言語を使用して、最も効率的なコードを書く必要があります。主要なプラットフォームには、Codeforces、AtCoder、TopCoderなどがあり、それぞれが異なる形式のコンテストを提供しています。

参加するメリット
競技プログラミングに参加することには多くのメリットがあります。特に、以下のようなスキルが向上します：

論理的思考力： 問題を分析し、複雑な問題を明確なステップに分解する能力が鍛えられます。
問題解決スキル： 効率的な解決策を迅速に考え、実装することが必要とされるため、プロジェクト管理や日常業務においても役立ちます。
プログラミング技術： 様々なプログラミング言語やアルゴリズム、データ構造に習熟することができます。
初心者が始める方法
競技プログラミングを始めるには、まず基本的なプログラミングスキルを身につけることが重要です。オンラインで利用できる教育リソース（例えば、「Codecademy」や「Khan Academy」）を活用すると良いでしょう。また、初心者向けコンテストに参加して、実際の問題解決を試みることも推奨されます。これにより、リアルタイムでのコーディングスキルと問題解析スキルが身につきます。

まとめ
競技プログラミングは、ただのプログラミング能力のテストではなく、論理的かつ創造的な思考を促進する有益な活動です。初心者であっても、適切なリソースと練習を通じて、この興味深い世界に足を踏み入れることができます。社内でのコミュニケーションと協力を深める一環として、是非挑戦してみてください。

この記事が競技プログラミングの基礎とその魅力を理解するのに役立つことを願っています。もしご質問やさらに詳しい情報を知りたい場合は、お気軽にお問い合わせください。

## 感想
教育リソースが海外のものになっているなど多少気になる点はあったが、微修正すればそれなりの記事になるように思えた。
Atcoder Beginner Contest 351 [Rust]

# A問題
チーム青木の得点が、チーム高橋の得点を上回るための最小値を求める問題。
よって、
$$チーム高橋の得点 - チーム青木の得点　+ 1$$
が答えとなる。
## 解答
```
use proconio::input;
use std::cmp;
use proconio::marker::Chars;
use std::collections::VecDeque;
use std::collections::HashSet;
use permutohedron::LexicalPermutation;
use std::num;

fn main() {

    input! {
        a: [usize; 9],
        b: [usize; 8],
    }
    
    let mut ans =0;
    let mut asum =0;
    let mut bsum =0;
    for i in 0..9 {
        asum += a[i];
    }
    for i in 0..8 {
        bsum += b[i];
    }
    ans = asum-bsum+1;
    println!("{}",ans);

}

```
# B問題
グリッドA、Bの入力を受け取り、文字が異なる箇所の座標(i,j)を出力する。

## 解答
```
use proconio::input;
use std::cmp;
use proconio::marker::Chars;
use std::collections::VecDeque;
use std::collections::HashSet;
use permutohedron::LexicalPermutation;
use std::num;

fn main() {

    input! {
        n: usize,
        a: [Chars; n],
        b: [Chars; n],
    }

    for i in 0..n {
        for j in 0..n {
            if a[i][j] != b[i][j] {
                println!("{} {}", i+1,j+1);
            }
        }
    }

}

```

# C問題

スタックにボールを一つ入れ、後ろ二つのボールが同じ大きさなら、+1した大きさのボールを入れる。
異なるなら二つのボールを入れ直す。
N個のボールにおいてこれを行うが、上記のスタックの計算量は0(1)なので、愚直に実装して良い。
## 解答
```
use proconio::input;
use std::cmp;
use proconio::marker::Chars;
use std::collections::VecDeque;
use std::collections::HashSet;
use permutohedron::LexicalPermutation;
use std::num;

fn main() {

    input! {
        n: usize,
        a: [usize; n],
    }
    let mut deque = VecDeque::new();
    deque.push_back(a[0]);

    for i in 1..n {
        deque.push_back(a[i]);
        while deque.len()>1{
            let mut back1 = deque.pop_back().unwrap();
            let mut back2 = deque.pop_back().unwrap();
            if back1 == back2 {
                deque.push_back(back1+1);
            } else {
                deque.push_back(back2);
                deque.push_back(back1);
                break;
            }
        }
    }

    println!("{}",deque.len());

}

```
C#で音声認識

# 環境
Windows 11 Pro (64bit)
Visual Studio Community 2022

# C# 5

```dev.bat
@echo off
path %path%;C:\Windows\Microsoft.NET\Framework64\v4.0.30319
prompt $e[33m$p$g$e[m
cmd
```

```recog.cs
using System;
using System.Speech.Recognition;

class Program {
	static void Main() {
		using (var rec = new SpeechRecognitionEngine()) {
			rec.LoadGrammar(new DictationGrammar());
			rec.SpeechRecognized += (sender, e) => {
				Console.WriteLine("> " + e.Result.Text);
			};
			rec.SetInputToDefaultAudioDevice();
			rec.RecognizeAsync(RecognizeMode.Multiple);

			Console.ReadLine();
		}
	}
}
```

https://learn.microsoft.com/ja-jp/dotnet/api/system.speech.recognition.speechrecognitionengine?view=net-8.0

```
csc /r:"C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Speech\v4.0_4.0.0.0__31bf3856ad364e35\System.Speech.dll" recog.cs
```

でコンパイル。

```
Add-Type -AssemblyName System.Speech
([AppDomain]::CurrentDomain).GetAssemblies()
```

`System.Speech.dll`のpathはPowerShellで確認できる。

# Visual Studio C#

適当なプロジェクト名のディレクトリを用意する。
例：`C:\Projects\.NET\Recog`

```
dotnet new console
```

というコマンドを実行すると`Recog.csproj` `Program.cs`が作られる。

```Program.cs
using System.Speech.Recognition;

using var rec = new SpeechRecognitionEngine();
rec.LoadGrammar(new DictationGrammar());
rec.SpeechRecognized += (sender, e) => {
	Console.WriteLine("> " + e.Result.Text);
};
rec.SetInputToDefaultAudioDevice();
rec.RecognizeAsync(RecognizeMode.Multiple);

Console.ReadLine();
```

```
dotnet add package System.Speech
```

で参照を追加する。

```
dotnet build
```

でビルド。

```Recog.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>
```

`warning CA1416: この呼び出しサイトはすべてのプラットフォームで到達可能です。`
という警告にはTargetFrameworkを`net8.0-windows`とする。

```
bin\Debug\net8.0-windows\Recog.exe
```

で実行。
import pickleって何

import pickleってなんだ。
なかなかクリティカルに説明してくれてるやつが（個人的に）なかったので自分で備忘録的にまとめます。

# pickleとは

chatGPTより下記回答
>pickle は Python の標準ライブラリの一部で、オブジェクトの直列化（serialization）と非直列化（deserialization）を行うためのモジュールです。直列化とは、Pythonオブジェクトをバイト列に変換することで、ファイルに保存したりネットワークを介して送信したりすることができるようにするプロセスです。非直列化はその逆のプロセスで、バイト列を元のPythonオブジェクトに戻すことです。

>pickle を使用すると、Pythonのほぼすべてのデータ型（リスト、辞書、クラスなど）を直列化することができます。以下に、pickle の基本的な使い方と、その利用例を示します。


# どういうときに使う
株価分析するときに使う。

>データの永続化:
Pythonオブジェクトをファイルに保存して、後で再度読み込むことができます。これはプログラムの実行中にデータを保存したり、プログラム間でデータをやり取りするために利用されます。

オブジェクトの複製:
pickle を使用してオブジェクトを直列化し、そのコピーを作成することができます。この方法は、オブジェクトのディープコピーを作成したり、複雑なオブジェクトを再利用したりするために役立ちます。

モデルの保存:
機械学習モデルや訓練済みのモデルを保存して、後で再利用する場合にも pickle が使用されます。

### 危険な点

https://docs.python.org/ja/3/library/pickle.html