OmniAICreator/Qiita-1.07M huggingface dataset:
[vscode]文字コードを変更する

vscodeにて、文字コードを変更したいときは、下ステータスバーをクリックして
変更できるが、反映されないときの対処法をまとめる。

![タイトルなし１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759593/330093f8-da58-87d8-23ed-98cc586dc18a.png)

ファイル⇒ユーザ定義設定⇒設定をクリックする。
![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759593/aa574fe5-673b-bc6f-34ab-03886b0bf81d.png)

![タイトルなし2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759593/16ba2bca-c0fa-1dfb-6cec-286b45721f8a.png)

設定ファイルが比較ので、検索バーに「encoding」と入力し、「file:encoding」のリンクをクリックする。
![タイトルなし３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759593/b81e1fd7-0c4e-0b14-b79f-c2b4c631eee0.png)

変更したい文字コードを入力する。
　※保存して、設定ファイルを閉じること。※
![タイトルなし４.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759593/f1eb21ae-ca9c-06d4-9bf1-35b4e025d023.png)


以上。
InteliJでgit-duetする方法

# InteliJでgit-duetする方法
※備忘録

[リポジトリ](https://github.com/git-duet/git-duet)を参照

ターミナルで下記を実行
```shell
brew install git-duet/tap/git-duet
mkdir ~/bin
curl -Ls -o ~/bin/jetbrains-git-wrapper https://raw.github.com/git-duet/git-duet/master/scripts/jetbrains-git-wrapper
chmod +x ~/bin/jetbrains-git-wrapper
```
サイバーエージェント様のAndroidブートキャンプに参加してみての感想

1. **イベント概要**
    - 株式会社サイバーエージェント様にAndroidアプリケーションについて教えてもらった
    - イベントの期間やスケジュール
        
        期間は7月から10月までの4ヶ月で1ヶ月に一度授業があり、次の授業までに課題を出せた人のみ次の授業を受けることができる。
        
2. **学んだこと**
    - プログラミングの具体的な内容
        - Navigation コンポーネントを使用した画面遷移
        - Column、Rowを用いたレイアウト構築
        - LazyColumn、LazyRowを使用した大量のデータ表示
        - Kotlin Coroutines
        - DataStore
        - Serialization
        - APKファイル
　
    - 企業の方からの指導内容で特に印象に残った点
        - データの永続化やSerializationは使用したことがなかったので、これからのアプリケーションで生かしていきたい。
3. **個人のプロジェクト**
    - 作成したアプリ
        - たくさんの人の自己紹介の項目を共有するアプリ
    - 作成した目的
        - 自己紹介をするときの項目を何にするかで悩む機会が度々あったため、他の人が自己紹介の時にどのような項目を使用するかを知りたいと思ったため
        - Kotlinの理解を深める
    - 機能
        - 他の人が書いた自己紹介の項目を表示する。
        - 自己紹介の項目を追加する
4. **課題と工夫**
    - 開発中に直面した課題やトラブル
        - 　データの永続化の仕組みやSerializationの導入の所で理解しきれず、時間がかかった
        - 　可読性の悪いコードだったため、データの流れがわかりづらく、どこがうまくいっていないのかがわかりづらかった。
    - それを解決するために工夫したこと
        - 　データの流れが分かりずらかったので、Logコマンドを使用して解決した。
5. **振り返りと今後の活かし方**
    - このイベントを通じて成長できた点
        - DataStoreやSerializationなど、自分が知らない新しい知識を得ることができた。
        - Kotlinでのアプリ開発の楽しさを知ることができた。
        - プログラミングでの可読性の重要性がわかった。
        - 期限を作成することが自分の成長に大きく関わると感じたので、普段の開発でも期限を作成して、開発を進めたいと思った。
    - 今後のキャリアやプロジェクトにどう活かしていきたいか
        - 今回の開発で公式のチュートリアルがあるということを教えてもらったので、それをまずは学習してみようと思った。
        - 期限を決めて開発する
        - APIをプログラムに組み込むイメージが少しできたので、もっと深めていく
　
1. 今回の成果物
https://github.com/tsuchida-y/AndroidBootcampIwatePref
ReservedInstance（RI）の割引率を最大にする条件

:::note info
気になった点
:::


「RIの最大割引額は72%です！安い！」みたいなお話をよく聞くと思いますが、どういった条件なのでしょうか、、？


:::note info
回答（東京リージョンの場合）
:::


①テナンシー：共有
②コミットメント期間：３年
③支払いオプション：全額前払い
④提供クラス：スタンダード
　　　　　　＋
⑤特定のインスタンスタイプ（下記参照）
* x2iedn.32xlarge
* x2iedn.8xlarge
* x2iedn.metal
* x2idn.32xlarge
* x2idn.16xlarge
* x2idn.metal
* x2iedn.24xlarge
* x2iedn.16xlarge
* x2idn.24xlarge
* x2iedn.2xlarge
* x2iedn.4xlarge
* x2iedn.xlarge
* u-3tb1.56xlarge
* u-6tb1.56xlarge
* u-6tb1.112xlarge
* x1.32xlarge
* x1e.16xlarge
* x1e.8xlarge
* x1e.32xlarge
* x1e.4xlarge
* x1e.2xlarge
* x1e.xlarge
* x1.16xlarge
* x2iezn.2xlarge
* x2iezn.6xlarge
* x2iezn.12xlarge
* 2iezn.8xlarge
* 2iezn.8xlarge
* x2iezn.metal
* u-9tb1.112xlarge
* u-12tb1.112xlarge


:::note info
参考
:::

https://aws.amazon.com/jp/ec2/pricing/reserved-instances/pricing/
Scanning folder for git repositories

たまにvsCodeがgitを認識しなくなる。

- 必要な拡張機能を再インストール
- vagrant halt
- vscodeを再起動する

# 参考
[Scanning folder for git repositories](https://github.com/microsoft/vscode/issues/173831)
[Windows の Visual Studio Code で Git が認識されない場合](https://obel.hatenablog.jp/entry/20180806/1533530699)
秘境駅ランキングAPI叩いてみた

## はじめに
こんばんは！今回はほぼ素人の私が、先輩に教わった通りAPIを使えるのか、一人で復習がてら実践記事にしたいと思います！

## 開発環境
OS：Windows11
言語：Python 3.12.4
ライブラリ：python-dotenv 1.0.1, requests 2.32.3
## APIとは？
そもそもAPIがどういうものなのか、あんまりしっくりきていなかったので、改めて調べてみました。

>APIとは「アプリケーション・プログラミング・インターフェース」の略で、簡単に言えば、異なるソフトウェアやサービス同士が会話をするための「共通言語」や「取り決め」のようなものです。


>日常生活の例で説明すると：
レストランのメニュー：
APIはレストランのメニューのようなものです。お客さん（アプリケーション）は、メニュー（API）を見て、どんな料理（機能やデータ）が提供されているかを知り、注文（リクエスト）することができます。
電気のコンセント：
世界中の電化製品は、決められた形状のプラグを使ってコンセントに接続します。APIは、このコンセントのような役割を果たし、異なるソフトウェア同士を「つなぐ」ための標準化された接続点となります。
通訳者：
異なる言語を話す人々の間で通訳者が意思疎通を助けるように、APIは異なるソフトウェア間でデータやコマンドを「翻訳」し、相互理解を可能にします。

>APIの実際の使用例：
スマートフォンアプリが天気予報を表示する際、気象サービスのAPIを使用してデータを取得しています。
ウェブサイトに地図を埋め込む際、Google MapsのAPIを利用しています。
SNSアプリで他のアプリと連携してログインする際、そのSNSのAPIを使用しています。

>つまり、APIは異なるソフトウェアやサービスが互いに情報をやり取りし、協力して機能するための「橋渡し」の役割を果たしているのです。

AI先生に聞いたらわかりやすいめに教えてくれました！
とにかく「つないでいるもの」なのですね。

## 準備
1. 旅旅APIにアクセスする。(https://tabi2api.docs.apiary.io/#introduction)
1. 左側のメニューから「認証」を選んでリンク先に飛ぶ。(トークンを発行するため)
1. 適当なところにフォルダを作って、中に「.env」というファイルを作る。
1. VScodeとかで作った.envファイルを開いて、中に次のコードを書き込む。
 `API_TOKEN = (さっき発行したAPIトークン)`

これで準備OK！あとはやるだけ！
## 手順
1. さっき作ったフォルダ内に「○○.py」というファイルを作る。(○○は好きな名前をつける。テキストドキュメントを作る、みたいなコマンドで.txtも消して新しい名前にしよう)
1. 旅旅APIのページから、秘境駅ランキングを選択して、一覧取得を押す。ページにこんな感じで表示されるはず↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906070/5a563f4e-6652-68f8-8782-685f0ac4bf71.png)
1. 右側の黒い部分の「秘境駅ランキング」から、コードの一番下までまるごとコピーする。
1. まるごとChatGPTなどの生成AIに投げて、「pythonでこのAPIを実行したいです。.envを使います。」とか指示する。
1. 出てきたコードをそれぞれコピペする。今回実行したコードはこちら。
```
 
import os
import requests
from dotenv import load_dotenv
# .envファイルから環境変数を読み込む
load_dotenv()
# APIのエンドポイントURL
url = "https://app.livlog.xyz/webapi/v2/hikyoeki/ranking?prefCd=23&population=100&trainCnt=20"
# 環境変数からトークンを取得
api_token = os.getenv("API_TOKEN")
headers = {
    "Accept": "application/json",
    "Authorization": f"Bearer {api_token}",
}
# GETリクエストを送信
response = requests.get(url, headers=headers)
# レスポンスのステータスコードを確認
if response.status_code == 200:
    # リクエストが成功した場合、JSONデータを取得
    data = response.json()
    # 結果を処理
    for station in data["results"]:
        print(f"駅名: {station['stationName']}")
        print(f"都道府県: {station['prefName']}")
        print(f"市区町村: {station['cityName']}")
        print(f"路線名: {station['lineName']}")
        print("---")
else:
    print(f"エラー: ステータスコード {response.status_code}")
    print(response.text) 
 
```
6. 以下のコマンドでコンソールからファイルを呼び出して、正しく動作するか確認する。
```
python ○○.py
```
○○は自分でつけた名前です。成功していれば以下のように表示されるはず。
![2024-10-10_14h26_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906070/462b102f-5387-cc21-4303-79cbaa0c601a.png)


以上です！自力でAPIを叩いてみられましたでしょうか。
作業していると多々エラーが出るかとは思いますが、そこも生成AIに投げて質問してみましょう。
私はVScodeで書いたファイルを上書き保存を忘れてエラーになっていました。
以後気を付けます！ありがとうございました。
【学習】Glitchを使用してREADMEに画像を載せる方法

# はじめに
今回はGlitchを使用してサービスを開発中にあたり、READMEに画像を載せる方法調べて実行してみました。以下流れを簡単にまとめました。

ついでに、調べる前は直接REDMEに画像をコピー＆ペーストで張り付けたり、URLをそのまま貼り付けていました。もちろん画像は表示されませんでした💦


## 画像を配置 

[![Image from Gyazo](https://i.gyazo.com/768f0c7b82fc70cfc6d0e3719c5619ac.png)](https://gyazo.com/768f0c7b82fc70cfc6d0e3719c5619ac)

現在上記ファイルがある状態です。

### Glitch上で
Assetsという所にREAMEで配置したい画像を追加します。
追加した画像をクリックするとURLが表示されるので、URLをコピーしておきます。

### Github上で
Githubの該当リポジトリのREADMEファイルで画像を配置したいか所に以下のようなコードを追加します。
**`![ファイル名](コピーしたURL)`**

「Preview」で確認すると画像が配置されているかと思います。
編集内容を保存します。

### 再びGithubでの操作
Glitchの該当プロジェクトに戻り「Tools」から「Import from Github」を選択し、インポートしてGithubで変更した内容をGlitch側に反映させます。


これでGithubとGlitchの両方のREADMEで画像を表示出来ている状態になるかと思います。


# さいごにまとめ
Glitchで先に画像を設定してからGithub側にエクスポートすると「Conflict」が発生しました。この場合対処が少し面倒になるので先にGithubで画像を設定してからGlitchにインポートの形で反映させることをおすすめします。
今回の記事が何か参考になれば幸いです。
[Python] FirebaseのTimeoutを設定 (Cloud Functions)

## 本記事の内容
Firebase Cloud FunctionsをPythonで実装する際に設定出来る**タイムアウト**の解説を行います。
Firebaseが公開している公式ドキュメントと、実際のソースコードを見ながら解説をしていきます。

## 背景
先日、生成AIのAPIを用いた関数をFirebseのCloud FunctionsにデプロイしてWebアプリを作っていました。

デプロイした関数には、実行時間がかかる処理を行っていたため、タイムアウトエラーになってしまいました。タイムアウトの時間を変更する方法が気になり、調べてみようと思いました。

## 目次

- [1. デコレータとは](#1-デコレータとは)
- [2. Timeoutの設定](#2-timeoutの設定)
- [3. 実装](#3-実装)
- [4. まとめ](#4-まとめ)


## 1. デコレータとは
デコレータとは**関数やクラスの前後に特定の処理を追加出来る機能**です。
Pythonでは、関数やクラスの定義する前に`@`をつけることで設定出来ます。

```Python sample.py
@https_fn.on_request()
def fetch_data(req: https_fn.Request) -> https_fn.Response:
    #省略
```

上記の関数のデコレータは`@https_fn.on_request()`です。

## 2. Timeoutの設定

ソースコードはこちらになります
```Python firebase-functions/options.py
@_dataclasses.dataclass(frozen=True, kw_only=True)
class RuntimeOptions:
    #other Options
    
    timeout_sec: int | Expression[int] | _util.Sentinel | None = None
    """
    Timeout for the function in sections. Possible values are 0 to 540.
    HTTP functions can specify a higher timeout.
    A value of ``RESET_VALUE`` restores the default of 60s
    The minimum timeout for a 2nd gen function is 1s. The maximum timeout for a
    function depends on the type of function: Event handling functions have a
    maximum timeout of 540s (9 minutes). HTTP and callable functions have a
    maximum timeout of 3,600s (1 hour). Task queue functions have a maximum
    timeout of 1,800s (30 minutes)
    """
```
ソースコードを参考にすると、timeoutのデフォルトの値は`60`秒になっていることが分かります。またタイムアウトの最小値は`1`秒で、最大`540`秒であることが分かります。

また、公式ドキュメントにも、最大値は`540`秒と記載されていました。

[公式ドキュメント]
![スクリーンショット 2024-10-02 17.31.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3767231/0a9e021b-eead-4dd5-5321-10cc7666b9d6.png)

https://firebase.google.com/docs/functions/manage-functions?hl=ja&gen=2nd#python-preview_3


## 3. 実装
Timeoutの値を60秒から240秒に変更してみます。
```Python sample.py
from firebase_functions import https_fn

@https_fn.on_request(timeout_sec=240)
def fetch_data(req: https_fn.Request) -> https_fn.Response:
    #省略
```

これでタイムアウト時間を240秒に設定することが出来ます。

## 4. まとめ
今回はFirebase Cloud FunctionsをPythonでデプロイする際に必要なデコレータの設定の中の1つである、Timeoutについての解説を行いました。実行時間で困ったときは参考にしてみて下さい。
また、他の設定についても投稿しているので、こちらも是非参考にしてください!


https://qiita.com/kikudesuyo/items/4b12becafc24df2c5457

https://qiita.com/kikudesuyo/items/ad991e2ab484cea446ae
[Flutter x Firebase] FlutterFire CLIインストール時に発生したエラー解決方法( cannot load such file -- xcodeproj (LoadError) )

# 実行コマンド

```zsh
flutterfire configure
```

上記コマンド実行時に以下のエラーが発生しました

# エラー全文
```zsh
❯ flutterfire configure --project=project-name
i Found 1 Firebase projects. Selecting project project-name.                                                                                                                                                                                                                             
✔ Which platforms should your configuration support (use arrow keys & space to select)? · android, ios                                                                                                                                                                                       
✔ Which Android application id (or package name) do you want to use for this configuration, e.g. 'com.example.app'? · com.example.project-name                                                                                                                                                              
i Firebase android app com.hoge is not registered on Firebase project project-name.                                                                                                                                                                                                     
i Registered a new Firebase android app on Firebase project project-name.                                                                                                                                                                                                                
i Firebase ios app com.example.hoge is not registered on Firebase project project-name.                                                                                                                                                                                                 
i Registered a new Firebase ios app on Firebase project project-name.                                                                                                                                                                                                                    
Exception: <internal:/Users/hoge/.rbenv/versions/3.0.3/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- xcodeproj (LoadError)
        from <internal:/Users/hoge/.rbenv/versions/3.0.3/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
        from -e:1:in `<main>'
```

解決すべきエラーメッセージは以下の箇所
```zsh
Exception: <internal:/Users/hoge/.rbenv/versions/3.0.3/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- xcodeproj (LoadError)
        from <internal:/Users/hoge/.rbenv/versions/3.0.3/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
        from -e:1:in `<main>'
```

# 解決方法

`xcodeproj` は Xcode プロジェクトの依存関係を管理する CocoaPods で利用されているが、エラーメッセージの通り `xcodeproj` が存在してないことが直接的な原因なのでインストールする
```zsh
$ gem install xcodeproj --user-install
```
OTセキュリティ　IEC61850通信方式

クライアント・サーバーサービス (Client-Server Services)
クライアント・サーバーサービスは、IEC 61850で定義されている通信方法の一つで、主に管理情報や制御指令の交換に使用されます。具体的な特徴としては以下の通りです：
MMS（Manufacturing Message Specification）:
MMSは、IEC 61850で使用されるアプリケーション層のプロトコルです。このプロトコルは、クライアントとサーバー間でデータやコマンドのやり取りを可能にします。
例えば、サブステーション内の監視装置や保護リレーが中央制御室と通信を行う際に使用されます。

TCP/IPを使用:
クライアント・サーバーサービスは、TCP/IPプロトコルスタックを使用します。TCP/IPは、信頼性の高いデータ転送を提供するため、通信中のデータ損失を防ぎ、再送機能などで通信の信頼性を確保します。
このため、クライアント・サーバーサービスは、7層のOSIモデルをフルに活用する、完全な通信スタックを使用します。具体的には、アプリケーション層から物理層までのすべての層を使用します。



パブリッシャー・サブスクライバーサービス (Publisher-Subscriber Services)
パブリッシャー・サブスクライバーサービスは、IEC 61850で使用されるもう一つの通信方式で、特に高速で広範なデータ配信が求められる場合に使用されます。具体的には以下のような特徴があります：

階層の簡略化:
この方式では、従来のTCP/IPのようなフルスタックを使用せず、通信階層を簡略化しています。
基本的にイーサネットのリンク層（Layer 2）に直接アクセスし、上位層のプロトコル（例えば、TCPやIP）を介さずに通信を行います。

特定の標準化されたEtherTypeの使用:
パブリッシャー・サブスクライバーサービスは、特定のEtherTypeを使用して、イーサネットフレームとしてデータを送信します。この方法により、非常に低レイテンシーで高速なデータ転送が可能です。
例えば、GOOSEメッセージやSV（Sampled Values）メッセージのような、リアルタイム性が要求されるアプリケーションで使用されます。これらのメッセージはイーサネットフレームとして直接送信され、通常のネットワークトラフィックとは異なる優先度で処理されます。


まとめ
IEC 61850では、用途に応じて2つの異なる通信方式を使い分けています。クライアント・サーバーサービスは、信頼性の高い通信を提供するためにTCP/IPスタックを使用し、フルスタックでのデータ管理や制御が可能です。一方、パブリッシャー・サブスクライバーサービスは、リアルタイム性が求められる場合に最適化されており、低レイテンシーで高速な通信が可能です。このように、IEC 61850はサブステーションの様々な通信ニーズに応じて適切な方法を提供しています。
ESP32: GATT の再接続のテスト

こちらと同じことを行いました。
[ESP32を使ったBLE実装時の再接続について](https://qiita.com/IRumA/items/00fc746892570f8d1c38)

ArduinoIDE 2.3.3 を使いました。

## プログラム

```text:gatt_advertise.ino
// ---------------------------------------------------------------------
//	gatt_advertise.ino
//
//						Oct/10/2024
// ---------------------------------------------------------------------

#define	PROGRAM	"gatt_advertise.ino"
#define VERSION	"Oct/06/2024 PM 13:25"

#include <BLEServer.h>
#include <BLEDevice.h>

#define DEVICE_NAME         "DEV-HAT"
#define SERVICE_UUID        "cf2a980a-f58a-49ba-bc44-8ef5e1cb2dd3"

int icount = 0;
// ---------------------------------------------------------------------
// Serverのコールバックで接続に対する処理を行う
class ServerCallbacks : public BLEServerCallbacks {
	// 接続時に呼び出される
	void onConnect(BLEServer* pServer) {
		Serial.println("*** onConnect ***");
		// 接続されたらAdvertisingを停止する
		BLEDevice::stopAdvertising();
	}

// ---------------------------------------------------------------------
	// 切断された時に呼び出される
	void onDisconnect(BLEServer* pServer) {
		Serial.println("*** onDisconnect ***");
		// 再接続のためにもう一度Advertisingする
		BLEDevice::startAdvertising();
	}
};

// ---------------------------------------------------------------------
void setup() {
	Serial.begin(115200);
	while (! Serial) { delay(1); }
	delay(300);
	Serial.println();
	Serial.println("*** setup *** start ***");
	Serial.println(PROGRAM);
	Serial.println(VERSION);

	// BLEの初期化
	BLEDevice::init(DEVICE_NAME);
	BLEServer* pServer = BLEDevice::createServer();
	pServer->setCallbacks(new ServerCallbacks());
	BLEService* pService = pServer->createService(SERVICE_UUID);
	
	pService->start();

	// Scanに引っかかるようにアドバタイジングする
	BLEAdvertising* pAdvertinsing = BLEDevice::getAdvertising();
	pAdvertinsing->addServiceUUID(SERVICE_UUID);
	pAdvertinsing->setScanResponse(true);
	// iPhoneの接続問題を解決するため
	pAdvertinsing->setMinPreferred(0x06); 
	pAdvertinsing->setMinPreferred(0x12);
	BLEDevice::startAdvertising();

	Serial.println("*** setup *** end ***");
}

// ---------------------------------------------------------------------
void loop() {
	icount++;

	if ((icount % 10) == 0)
		{
		Serial.print(VERSION);
		Serial.print(" -- ");
		Serial.println(icount);
		}

	delay(1000);
}

// ---------------------------------------------------------------------
```

## UUID
こちらのページで作成しました。
[Online UUID Generator](https://www.uuidgenerator.net/)

## 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/3d6fab81-c281-130d-99c5-2448b7b0e95b.png)

```text
*** setup *** start ***
gatt_advertise.ino
Oct/06/2024 PM 13:25
*** setup *** end ***
Oct/06/2024 PM 13:25 -- 10
Oct/06/2024 PM 13:25 -- 20
*** onConnect ***
Oct/06/2024 PM 13:25 -- 30
*** onDisconnect ***
Oct/06/2024 PM 13:25 -- 40
*** onConnect ***
Oct/06/2024 PM 13:25 -- 50
Oct/06/2024 PM 13:25 -- 60
Oct/06/2024 PM 13:25 -- 70
```
FlutterでERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'List<Object?>' is not a subtype of type 'PigeonUserDetails?' in type castが出た時の解決方法

# はじめに
firebase_auth導入後にIOSのエミュレータでSignUpまたはloginを利用しようとしたときに以下のエラーが出ていました。

:::note info
Firebaseのバージョン
* firebase_core: ^3.6.0
* firebase_auth: ^5.3.1
:::

```
ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'List<Object?>' is not a subtype of type 'PigeonUserDetails?' in type cast
#0      PigeonUserCredential.decode (package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart:432:23)
#1      _FirebaseAuthHostApiCodec.readValueOfType (package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart:830:37)
#2      StandardMessageCodec.readValue (package:flutter/src/services/message_codecs.dart:477:12)
#3      StandardMessageCodec.readValueOfType (package:flutter/src/services/message_codecs.dart:522:23)
#4      _FirebaseAuthHostApiCodec.readValueOfType (package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart:840:22)
#5      StandardMessageCodec.readValue (package:flutter/src/services/message_codecs.dart:477:12)
#6      StandardMessageCodec.decodeMessage (package:flutter/src/services/message_codecs.dart:341:28)
#7      BasicMessageChannel.send (package:flutter/src/services/platform_channel.dar<…>
```
# 解決方法
:::note info
### 実行環境
使用PC：MacBockAir M2
統合開発環境：Android Studio
:::

結論から言うと以下の方法で解決出来ました。
```
cd ios
pod update Firebase/Auth
pod install --repo-update
cd ..
flutter clean
flutter pub get
flutter run
```
この方法ではFirebaseとpod側とのバージョンの不一致が起きていたためエラーが出ていたらしいので、pod側で最新の互換性のあるバージョンを取得してエラーを解消しました。

次に**pod install --repo-update** でcocoaPodsのリポジトリを更新しました。

# 失敗例
### Firebaseのバージョンを落とす
```
firebase_core: ^3.6.0
->firebase_core: ^2.32.0

firebase_auth: ^4.15.3
->firebase_core: ^2.32.0
```
エラー文を調べてみるとFirebaseのバージョン関係でエラーが出ているのが分かったのでこちらを実行してみると、、、
普通に同様のエラーが出ました。
### Firebaseのバージョンを互換性のある最新バージョンにする
```
flutter pub upgrade firebase_auth
flutter clean
flutter pub get
```
これは逆に互換性のある最新バージョンにしてみました。
こちらも普通にエラーです。（そもそもの原因がIOSディレクトリのPodととのバージョン不一致だからPod側を最新にしないといけなかったですね）

:::note info
参考記事
https://github.com/firebase/flutterfire/issues/13077
:::

### podの再インストール
```
cd ios
pod update
pod install --repo-update
cd ..
flutter run
```
AIに聞いた時に **「多くのパッケージに新しいバージョンがありますが、現在の依存関係の制約と互換性がありません」** ということでしたので、podを入れ直しました。
うーん、エラー表記変わらず,,,,
# 終わりに
このエラーの解決方法がネットやサイトで見つけられなかったのでなかなか苦戦しました。
今回の解決方法はかなり時間がかかったので、Flutterのバージョン問題はなかなか骨が折れることを実感しました。
SingleEmailMessageについて

## SingleEmailMessage 制限の確認



【SingleEmailMessage 制限の確認】
https://help.salesforce.com/s/articleView?id=000386230&type=1
1. workbenchを利用して制限値を確認方法です。workbench 以外にもpostmanでも確認可能です。
2. 対象組織は Developer Edition の場合、SingleEmailMessage の上限は 1 日 15 件です。

【SingleEmailMessage の送信回数に関する検証】
https://help.salesforce.com/s/articleView?id=000385932&type=1
※この方法を利用すると制限がカウントされるかをテストした結果です。

【SingleEmailMessage のメソッド】
https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_email_outbound_single.htm
※Apex Devloperサイトです。




![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/5823a5c2-82d8-7479-637e-d9575cd54e15.png)
※送信実施後はRemainningの数が減ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/9e90d82b-ce6e-10e1-f15f-a481f8b28815.png)

開発コンソールから以下のコードでテストできます。
```apex
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(new String[] { 'aaabbb@gmail.com' });
mail.setSubject('Test Mail Subject');
mail.setPlainTextBody('This is a test Single Email.');

// where Address = 'doNotReply@<somedomain>.com'条件指定してもOK
// 設定｜メール｜組織のアドレスに登録している「ユーザー選択およびデフォルトの No-Reply 用途の組織のメールアドレス」
OrgWideEmailAddress[] owea = [select Id from OrgWideEmailAddress];
if ( owea.size() > 0 ) {
    mail.setOrgWideEmailAddressId(owea.get(0).Id);
    System.debug('***orgMail: ' + owea.get(0).Id);
}

Messaging.SingleEmailMessage[] messages = new List<Messaging.SingleEmailMessage> {mail};
Messaging.SendEmailResult[] results = Messaging.sendEmail(messages);
if (results[0].success) {
    System.debug('***The email was sent successfully.');
} else {
    System.debug('***The email failed to send: '
          + results[0].errors[0].message);
}
```
Snowflake 一括ロードに使用するステージまとめ

# はじめに
Snowflakeの一括ロード（バルクロードとも言う）に必要なステージについて調査した際のまとめです。
ステージを選ぶ際の検討材料に。

# 内部ステージ
　内部ステージは、ユーザーステージ、テーブルステージ、名前付きステージの3種類。ローカルにあるファイルにも対応（putコマンドでファイルを置く）。

### ユーザーステージ
・ユーザーにデフォルトで割り当てられるステージ（ユーザー1人に対して1つ）
・デフォルトのためDROPしたりCREATEできない
・ファイルが1人のユーザーのみによってアクセスされ、複数のテーブルにロードしたいとき
　→  **ユーザー1：テーブル多**
・`LIST @~` で参照する
・必要な権限：テーブルのINSERT権限
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635659/9f3ccc21-323c-c190-8ad9-602ee4926715.png)


　
### テーブルステージ
・テーブルにデフォルトで割り当てられるステージ(テーブル1つに対して1つ)
・デフォルトのためDROPしたりCREATEできない
・複数のユーザーがファイルにアクセスでき、一つのテーブルのみにロードしたいとき
　→ **ユーザー多：テーブル1**
・`LIST @%xxxxx` で参照する
・必要な権限：ステージのREAD権限とテーブルの所有権（OWNERSHIP権限）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635659/a4d83f7e-5d54-bbff-2b10-93bceedfc9b6.png)



### 名前付きステージ
・CREATE/DROP可能、最も柔軟
・適切な権限を持つユーザーは任意のテーブルにデータをロードする
　→ **ユーザー多：テーブル多**
・`LIST @xxxxx` で参照する
・必要な権限：ステージのREAD権限とテーブルのINSERT権限
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635659/5a3c6419-4b57-10bd-d36d-0e460c359b85.png)



# 外部ステージ
外部ステージの種類は1つ。クラウドストレージをステージとして利用する。外部ステージのデータはsnowflake上で保持しておらず、窓を通して見ているイメージ。
・クラウドストレージに対応（AWS, Azure, Google Cloud）
・適切な権限を持つユーザーは任意のテーブルにデータをロード可能
　→ **ユーザー多：テーブル多** （前述の名前付きステージが外部ストレージになったver.と個人的に思っている）
・`LIST @xxxxx` で参照する
・必要な権限：ステージのUSAGE権限&テーブルのINSERT権限 
・snowpipeによる自動取込が可能
　→snowpipeについては[こちら](https://qiita.com/Hikaru_O/items/141b4041bd87bd1595d0 "SnowflakeとAzureを使ってSnowpipeを実装してみた🔰")

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635659/b932d221-2274-0db3-5ca9-0f65f09c3bb2.png)


# まとめ

・内部ステージは3種類、外部ステージは1種類
・ファイルの置き場所がクラウドストレージorローカルか、
　ファイルを触るのは複数ユーザーor単一ユーザーか、
 　ロードするテーブルは1ファイルに対して複数テーブルor単一テーブルか、
  　で適切なステージが見えてくる





調べていて思ったのは、
テーブルステージにおいて、必要な権限に「テーブルの所有権」があるのは注意かなと感じました（私は見落としていました）。
他のステージはテーブルのINSERT権限でOKなのに対し、テーブルステージだけ所有権（あらゆる操作権限を包括してるので結構強め）が必要になるので、他の部分の設計にも影響がないか見直すことがおすすめです。


# 参考
内部ステージ
https://docs.snowflake.com/ja/user-guide/data-load-local-file-system-create-stage#user-stages
外部ステージ
https://docs.snowflake.com/ja/user-guide/data-load-s3-create-stage
シェルスクリプトをRubyで作る

## 環境

Ubuntu20.4
Ruby2.6

## はじめに

「Linux環境でシェルスクリプトを書くことになったのだが、bashの文法はあまり詳しくないし、普段書きなれたRubyを使ってサクッと作れないだろうか・・・。」

「Rubyなら色々なgemが用意されているし、複雑な処理でもシンプルに記述できるんだけどな
・・・。」

なんて思ったときは、Rubyを使ってシェルスクリプトを作ることができるのです。シェルスクリプトにしなくても、Rubyプログラムとして、ruby hoge.rbで実行してもいいのだが、シェルスクリプトにすると、.hoge.shで実行することができます。だけの話と言えば、だけの話ではありますが。

中身はRubyの文法のままで、あたかも、bashで動いているようなスクリプトを作ることができます。また、Rubyで作っても、systemやIO.popenを使うことで、Linuxのコマンドを埋め込むこともできます。

## 内容

Rubyで記述する場合は、シバンにはbashを指定するのではなくRubyを指定します。そして、スクリプトファイルの拡張子はshにします。rbでも動くようではありますが。

```hoge.sh
#! /usr/bin/env bash		# bash用
#! /usr/bin/env ruby		# Ruby用
```

このようにして実行します。実行権限はつけてください。

```hoge.sh
$./hoge.sh
```

bashで動くわけではないので、Rubyで書いたスクリプトファイルをこのようにして実行することはできません。

```hoge.sh
$. hoge.sh
$source hoge.sh
$bash hoge.sh
```

bashで動かす場合の書き方です。

```hoge.sh
#! /usr/bin/env bash
echo "OK"
```

同じことをRubyで書くとこのようになります。

```hoge.sh
#! /usr/bin/env ruby
puts "OK"
```

Rubyで記述しても、スクリプトファイルの実行が、bashと同じコマンドで実行できるようになります。
【Flask】アプリ全体で API Keyを安全に取り扱う方法

# app.config["API_key"] と current_app["API_Key"]を活用

## 1. アプリ全体で API Keyを使えるようにする

- Flaskの g に APIキー のようなアプリ全体で利用される情報を保存することは推奨されない。
- g はリクエストごとにスレッド固有のデータを一時的に格納するためのものであり、APIキーのようなグローバルな設定を格納する用途には適していない
- APIキーは、環境変数や設定ファイル (.env, config.py など) で管理し、アプリケーションが起動した際に一度ロードして使用するのが一般的
- .envを使う方がベストプラクティスとして標準的な手法なっている
- 環境変数にすることで、APIキーなどの機密情報をソースコードから分離することで、誤って公開してしまうリスクを大幅に減らすメリットがある
- クラウドプロバイダーが提供する シークレット管理サービス（例：AWS Secrets ManagerやGoogle Cloud Secret Manager）を使用するもある
- Flaskの app.config は、アプリケーション全体で設定値を管理するための辞書のような構造を持ったオブジェクト
- Flaskアプリケーションの設定に関わるパラメータ（デバッグモードのオン・オフ、データベース接続設定、APIキーなど）を保存し、アプリ全体から参照することができる

::: note information
### ファイル構成

```
flask_app
   |- .env
   |- app.py
   |- functions
      |- __init__.py
      |- function.py
```

- .env: 環境変数ファイル
- app.py: Flaskのメインアプリ
- function.py: アプリ内の分割されたファンクション（モジュール相当）
:::

### 設定例 １

- load_dotenv で.envを環境変数として読み込む
- os.getenv()でapi_keyを読み込み、変数API_keyとして定義
- app.config["API_key"]として

#### .env

``` text
api_key1="43785f92e7mshf1"
api_key2="AIzaSyD574tn5m7"
```

#### app.py

``` python
import os
from dotenv import load_dotenv
from flask import Flask

app = Flask(__name__)

load_dotenv()

app.config["API_key1"] = os.getenv("api_key1")
app.config["API_key2"] = os.getenv("api_key2")
```

#### function.py

``` python
from flask import current_app

API_Key1 = app.config["API_key1"]
API_Key2 = app.config["API_key2"]
```

### 設定例 ２ (Blueprintが採用されている場合)

- app が設定されないないため、function.pyに app.config["API_key"]を使えない
- load_dotenv で.envを環境変数として読み込む
- os.getenv()でapi_keyを読み込み、変数API_keyとして定義
- Blueprintが採用されている場合、app.config["API_key"]が使えないため、代わりにcurrent_app["API_key"]を使う

#### .env (BP)

``` text
api_key1="43785f92e7mshf1"
api_key2="AIzaSyD574tn5m7"
```

#### app.py (BP)

``` python
import os
from dotenv import load_dotenv
from flask import Flask, current_app

app = Flask(__name__)

load_dotenv()

app.config["API_key1"] = os.getenv("api_key1")
app.config["API_key2"] = os.getenv("api_key2")
```

#### function.py (BP)

``` python
from flask import Blueprint, current_app

API_Key1 = current_app["API_key1"]
API_Key2 = current_app["API_key2"]
```

## まとめ

- Blueprintを使っている場合でも、.env に保存された環境変数を load_dotenv を使ってFlaskの app.config に読み込み、Blueprint内では current_app を使って参照すれば、環境変数（APIキーなど）を安全かつ簡単に利用できる
新しいMicrosoft Copilotの回答精度を上げるための前提指示のテンプレートを作ってみた（らダメだったので、分解して指示するか･･･。）

**この記事は2024/10/15現在、既に古い内容です。最新のCopilot仕様を参照してください。**

https://blog.vemi.jp/entry/2024/10/09/212031

昨日は愚痴ブログを書いてしまいましたが･･･
前提指示のテンプレートを作成してみました。  

こいつを会話の最初に貼り付けて、新しいCopilotの回答精度を少しでも解消を･･･！と思ったら、だめだった。
「タメ口辞めて」（タメ口）は、受け入れてくれたのに･･･。

![IMG_6233.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215973/4f2cce57-0705-9240-4cf7-f0f2438a1e6f.jpeg)

サブリミナル的に指示・指摘していくしかないわね。。。

ということで、新しいCopilotの回答精度を上げられる（はず）の前提指示のテンプレート、このままは使えませんが、折角作ったので、置いておきます･･･。

```markdown
これから開始する会話では以下の内容を徹底してください。

1. **フォーマルな文体で回答すること**。
2. **文末の定型的な案内文は出力しないこと**。
3. **回答の厳密さを非常に重視する**。回答の速度は遅くても良い。
4. **常にインターネット上の最新情報を収集し、正しい情報を得ること**。
5. **信頼性の高い情報源から情報を収集すること**。信頼性が不明な場合はその旨を補足すること。
6. **回答は自身でレビューとテストを行い、精度の高い回答に努めること**。
7. **回答は文字崩れを起こさないよう、Copilotに出力するMarkdownの構文についても自己レビューすること**。
8. **エスケープ文字に十分注意すること**。
9. **ユーザーの意図や具体的なニーズを文脈から的確に推測し、簡潔に質問した意図を深く考えて気の利いた提案をすること**。
10. **コンテキストの理解**: 会話の前後関係を理解し、ユーザーの意図を的確に把握すること。
11. **多様な表現の使用**: 同じ内容を繰り返さないように、異なる表現や言い回しを使用すること。
12. **ユーザーの感情に配慮**: ユーザーの感情や状況に応じた適切な対応を心がけること。
13. **適切なフォローアップ**: ユーザーの質問に対して、関連する追加情報やフォローアップの質問を提供すること。
14. **ユーザーからのフィードバックを積極的に受け入れ、必要に応じて回答を修正すること**。ただし、ユーザーの見解が誤っている場合にはファクトチェックを行うこと。
15. **ユーザーのプライバシーとセキュリティを尊重し、個人情報を適切に扱うこと**。
16. **継続的な学習**: 新しい情報やフィードバックを基に、常に学習し改善を続けること**。
```

なお、こちら、2024/10/10現在のものでございます。  
来週には、最適な前提指示は変わっているカモ～
Arch LinuxにGUIで簡単に設定できるファイアウォール、フロントエンドの導入


Arch LinuxにGUIで簡単に設定できるファイアウォール・フロントエンドの導入をします。

アプリ名を　gufw　と言います。gufwはufwのフロントエンドです。

インストール

```
sudo pacman -S ufw gufw
```

実行

```
$ gufw
```

一番簡単に、gufwと実行したあと、
プロファイルを「自宅」に　#　ここは適当に
Statusをonに
IncomingをDenyに
OutgoingをAllowに
設定します。
これで、終了すると、iptablesとip6tablesを書き換えてくれます。
Arch Linuxを入れた直後は、ネットワークは素っ裸なので、注意してください。

sambaなどを使っている場合は、ルールの追加が必要です。
競馬予想AIを作りたい（AI学習編３）

# これまでの話とこれからの話
[前回](https://qiita.com/lefirea/items/f12a7625bc353196d68e)回収率100%超えて喜んでたけど、的中率を求めると酷いことが分かってしまった。
なんと単勝的中率1%！
つまり、手堅いのを外し続けて、まぐれ大当たりで結果的にプラスになってただけだった。
そこで、的中率も重視してより良いAIを作りたいのが今回の話。

# 要約
ランキング学習を取り入れることで、単勝的中率80%を達成した。
回収率は据え置きなので問題なし。
ただ、どうせなら三連単/複の的中率もせめて50%は超えたいので今後も調整していく。

# 今回のアプローチ
今までは分類問題として解いていた。（今回も分類問題ではある）
しかし分類問題の中にも色々あるようで、一般的に行われる分類問題は「ポイントワイズ法」と呼ばれる。
これはワンホットベクトルのように一つだけ立ってるものを当てるような話。
点を予測する。

対して、ランキング学習は順序を予測する。
ざっくり概要としては、1, 2, 3の並びを予測するために、考えられる並び順から一つ選ぶようなもの。
組み合わせは以下の６通りあり、この中から正解の一つを選ぶ。
- 1 2 3
- 1 3 2
- 2 1 3
- 2 3 1
- 3 1 2
- 3 2 1

仮に正解が`2 1 3`だとすると、ワンホット的に書くと`[0 0 1 0 0 0]`を与えるような話。

厳密には全然違うので専門家から怒られそうだが、イメージはそんな話。

本記事では、そういったランキング学習を取り入れて予測を行う。

# 実装と結果
lightGBMを使用して実装した。
使用するデータは前回の記事と同様で、中央レース2008～2022年を学習データ、2023年以降をテストデータとする。
説明変数は以下の25変数。
- 馬番
- 人気
- 単勝
- 馬場（札幌、函館、……、小倉）
- 距離
- 性別（牝、牡）
- 年齢
- 馬体重
- （馬体重の）増減
- 前走からの日数
- 前走順位～5走順位

また、着順を以下のようにラベルを振る。
- 1着→3
- 2,3着→2
- 4,5着→1
- 6着以降→0

学習プログラムは以下。
```python
model = lgb.LGBMRanker(n_estimators=1000,
                       random_state=0,
                       learning_rate=1 * 1e-1,
                       )
model.fit(
    train,
    target,
    group=groups,
    eval_set=[(test, ans)],
    eval_group=[tgroups],
    early_stopping_rounds=10,
    verbose=1,
    eval_at=[1, 3, 5],
    eval_names=["test"],
)
```

これで学習させた結果が以下になる。
単勝的中率は81%となり、良い感じ。
三連の的中率が35%というのが残念だが、今後の工夫次第では上昇が期待できるだろう。
```
[単勝]   回収率: 82609.19% (馬券: 2,785,500, 払戻: 2,301,079,000.0)
[三連単] 回収率: 2515949204.56% (馬券:33,426,000, 払戻: 70,081,765,093,000.0)
[三連複] 回収率: 20000845.02% (馬券: 5,571,000, 払戻: 1,114,247,076,000.0)
[単勝]   平均回収率: 14.83%
[三連単] 平均回収率: 451615.37%
[三連複] 平均回収率: 3590.17%
[単勝]   的中率: 81.65%
[三連]   的中率: 34.84%
[馬単]   的中率: 58.25%
```

# 今後の予定
実際に運用してみて、本当に8割も当たるのか確認する。
また、別の手法を試したり、説明変数を見直してより高い精度を目指す。
ReactでSelectタグにplaceholderのようなものを実装


## Reactでclassnameを条件分岐で付与する方法
※備忘録


Selectタグにはplaceholderがありません。
placeholderをCSSで作る方法はこちら
https://blog.logrocket.com/creating-custom-select-dropdown-css/

### ・三項演算子を使う方法
```tsx:Sample.tsx
import {useState} from "react";
import styles from './Sample.module.scss'

const options = [
    {optionLabel: "未選択", optionValue: ""},
    {optionLabel: "dog", optionValue: "dog"},
    {optionLabel: "cat", optionValue: "cat"},
    {optionLabel: "hamster", optionValue: "hamster"},
]

export const Sample = () => {
    const [selected, setSelected] = useState<string>("")
    return (
        <>
            <select
                value={selected}
                onChange={(e) => setSelected(e.target.value)}
                className={selected === "" ? styles.empty : styles.selected}
            >
                {options.map((option) => (
                    <option
                        key={option.optionValue}
                        value={option.optionValue}
                    >
                        {option.optionLabel}
                    </option>
                ))}
            </select>
        </>
    )
}
```

```scss:Sample.module.scss
.empty {
  color: gray;
}

.selected {
  color: black;
}
```

### ・classnamesを使う方法
classnamesをインストール([リンク](https://www.npmjs.com/package/classnames#usage-with-reactjs))
```shell
npm install classnames
```

```tsx:Sample.tsx
import {useState} from "react";
import styles from './Sample.module.scss'
import classNames from "classnames"

const options = [
    {optionLabel: "未選択", optionValue: ""},
    {optionLabel: "dog", optionValue: "dog"},
    {optionLabel: "cat", optionValue: "cat"},
    {optionLabel: "hamster", optionValue: "hamster"},
]

export const Sample = () => {
    const [selected, setSelected] = useState<string>("")
    return (
        <>
            <select
                value={selected}
                onChange={(e) => setSelected(e.target.value)}
                className={classNames(styles.selected, {
                    [styles.empty]: selected === ""
                })}
            >
                {options.map((option) => (
                    <option
                        key={option.optionValue}
                        value={option.optionValue}
                    >
                        {option.optionLabel}
                    </option>
                ))}
            </select>
        </>
    )
}

```

```scss:Sample.module.scss
.selected {
  color: black;
}

.empty {
  color: gray;
}
```
注 .selectedより.emptyが後で読み込まれるようにしている。
【ChatGPT Canvas】Canvasの内容をファイル（TEXT&PDF）にするPromptです。


　どうも、カーブミラーです。

　今回は、Canvasの内容をファイルにするPromptです。

:::note info
本記事は、ChatGPT（有料版）
で行なっております。画像は
ありません。　あしからず。
:::

　まずは、ニュース。

　ノーベル物理学賞に
　　米国プリンストン大学の
　　　ジョン・ホップフィールド教授
　　カナダ・トロント大学の
　　　ジェフリー・ヒントン教授
　のふたりが選ばれました。

　どちらもAIの第一人者。
　おめでとうございます。

[NEWS WEB](https://www3.nhk.or.jp/news/html/20241008/k10014603511000.html)
***
　次。

　Google Geminiに
　　画像生成が正式採用。

　その名も
　　“Imagen 3”。

　今まで、
　　英語での描画はできましたが、
　　　正式採用されたことで、
　　　　日本語Promptでも
　　　　　描けます。

　なお、
　　無料版では、人物は描けません。
　　　描きたければ、
　　　　Advancedにしてください。

　とはいえ、
　「まもなく Gemini Advanced で
　　人物の画像生成を
　　　利用できるようになります」と
　　　メッセージが出るので、
　　　　描けない可能性もあります。

　出てくるスピードは、
　　DALL-E3と比較して
　　　早い感じがしました。

[Google Gemini App公式ポスト]https://x.com/GeminiApp/status/1844061028742820059?t=bPGM63t0OdiomQhh9kHvfA&s=19()
***
　さて、本題に入ります。

　今回は、
　　Canvasの内容を
　　　ファイルにする
　　　　Promptです。

　Canvasの操作方法を
　　調べても、ファイルにすることは
　　　どこにも書かれていません。

　とすると、
　　結局、コピー・ペースト
　　　するしかありません。

　わざわざ
　　エディタなどのツールを
　　　新規で開き、
　　　　そこにペーストするなど、
　　　　　スマートじゃありません。

　しかし、
　　ファイルを作成することは
　　　ChatGPTでも可能です。

　Code Interpreterで、ですが。

　当然、Promptが必要です。

```Text:Canvas→TEXTファイルPrompt
Canvasの内容をCodeInterpreterで“✘✘✘.txt”としてファイル化してください。
```

　これで
　　ダウンロードできます。

　✘✘✘は、
　　自分で決めてください。
***
　ここでは、
　　テキストで
　　　ファイルを作成していますが、
　　　　PDFにすることも可能です。

　ただし、
　　上記Promptの“.txt”を
　　　“.pdf”にしても
　　　　PDFはできますが、
　　　　　内容が日本語だと
　　　　　　文字化けを起こします。

　これは、
　　日本語フォントが
　　　ChatGPTのCode Interpreterに
　　　　ないために起こります。

　そこで
　　日本語フォントを
　　　アップロードして
　　　　下記Promptを送信します。
```Text:Canvas→PDFファイルPrompt
NotoSansJP.ttfを使って、
CodeInterpreterで、Canvasの内容を“✘✘✘.PDF”という名前のファイルにしてください。
```
　ここでは、
　　日本語フォントに
　　　NotoSansJP.ttfを
　　　　使用していますが、
　　　　　ここはそれぞれで
　　　　　　変更してください。
***
　何度もPDF化する場合、
　　はじめから日本語フォントを
　　　読み込んでおくのも
　　　　手です。

　その場合は
　　日本語フォントを
　　　アップロードしたら
　　　　下記Promptを送信します。
```Text:CodeInterpreter
以降、CodeInterpreterで使うフォントはこのNotoSansJP.ttfを使用してください。
```

　“NotoSansJP.ttf”は
　　それぞれで変更してください。

　あとは最初のPromptを
　　PDFにして使えば
　　　それで日本語PDF化ができます。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
vscode-pets にブルーマール犬を追加する

## やること / やらないこと
- やること
  - 開発環境構築
  - vscode-pets にブルーマール犬を追加
  - ペットタイプ選択の先頭を犬に変更 (動作確認しやすくするためなので任意)
  - ペットカラー選択の先頭をブルーマールに変更 (動作確認しやすくするためなので任意)
- やらないこと
  - vscode-pets 公式にプルリク
  - VScode Marketplace で公開

## ブルーマール？
> ブルーマールとは、「マール因子」という遺伝子を持つ犬に見られる毛色のことです。  
> マール因子が作用すると、独特のまだら模様のような毛色を持つ子犬が生まれます。
>
> 引用元: https://magazine.cainz.com/wanqol/articles/blue_merle

## 開発環境構築

### 必要なもの
- Node.js
- VSCode
- VSCode拡張
  - ESLint
  - Prettier
- Aseprite (有料)
  - 公式 https://www.aseprite.org/
  - Steam版 https://store.steampowered.com/app/431730/Aseprite/?l=japanese
  - ※別のソフトでも大丈夫だと思います

### フォーク ～ 実行
- フォーク
  - https://github.com/tonybaloney/vscode-pets にアクセスして Fork をクリック
- クローン
  - フォークで作られた __自分の__ リポジトリを好きな方法でクローン
- ローカルリポジトリを VSCode で開く
- 依存パッケージのインストール
  - `$ npm i`
- 実行
  - ローカルリポジトリを VSCode で開いて F5

## ソースコード変更

```ts:src\common\types.ts
export const enum PetColor {
  bluemerle = 'bluemerle', // ペットカラーにブルーマールを追加
  brown = 'brown',
  // ...
}

// ...

export const ALL_PETS = [
  PetType.dog, // ペットタイプ選択の先頭を犬に変更
  PetType.cat,
  // ...
];
export const ALL_COLORS = [
  PetColor.bluemerle, // ペットカラー選択の先頭をブルーマールに変更
  PetColor.black,
  // ...
];
```

```ts:src/extension/extension.ts
// ...
const DEFAULT_COLOR = PetColor.bluemerle; // 拡張設定の規定値をブルーマールに変更
const DEFAULT_PET_TYPE = PetType.dog; // 拡張設定の規定値を犬に変更
// ...
```

```ts:src/panel/pets/dog.ts
export class Dog extends BasePetType {
  // ...
  static possibleColors = [
    PetColor.bluemale, // 犬で使用できるカラーにブルーマールを追加
    PetColor.black,
    // ...
  ];
  // ...
}
```

## gif の作成
vscode-pets の犬には 7種類 の動きが実装されているので、  
Aseprite などを使って 7つの gif を作成します。  

フォルダ構成は以下の通りです。

- `{ローカルリポジトリ}/media/dog`
  - `bluemerle_idle_8fps.gif` (立つ)
  - `bluemerle_lie_8fps.gif` (伏せる)
  - `bluemerle_run_8fps.gif` (走る)
  - `bluemerle_swipe_8fps.gif` (ひっかく or お座り) ※マウスカーソルを近づけたときの動き
  - `bluemerle_walk_8fps.gif` (歩く)
  - `bluemerle_walk_fast_8fps.gif` (速く歩く)
  - `bluemerle_with_ball_8fps.gif` (ボールを咥える)

## VSIX の作成

```bash
$ npx vsce package
```
appstoreで一般公開されていない非表示iOSアプリをMDMで配信する

# やりたいこと
 - [メッセナゴヤ2024](https://www.messenagoya.jp/)のアプリをダウンロードしたい
 - 弊社ではMDMで社用スマートフォンにインストールできるアプリを制限しているため、iphoneについてはapple business manager　から配信が必要

# 困ったこと
 - アプリがappstoreに公開されていない　いわゆる[非表示app](https://developer.apple.com/jp/support/unlisted-app-distribution/)
 ![画像 (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160366/ba5e4acc-6640-bf4c-5cd9-383f3e65223c.png)
- そもそもappstoreにつながるQRコードの読み取りを社用スマートフォンで許可していないので、appstoreの画面に飛べない

# 対応方法
- QRコードを読み取りURLを確認する
ブラウザからQRコード読み取るツールを使うと便利（例　[これ](https://qrcode.red/)　とか）
- URLに記載されているidを取得（具体的には、URLの末尾にある「id」+「数字10桁」）
- ABMにログインし、アプリとブック→検索欄に「数字10桁」を入力すると該当のアプリが出るので、ライセンス購入し割り当てる
![スクリーンショット 2024-10-09 14.36.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160366/c14f6db4-6093-fee1-cde1-e33a56b524b8.png)

- 後の手順は通常通り


# 注意
- この方法で対応できるのは非表示app（QRコードやURLを知っている人だけがDLできるアプリ）のみ
- カスタムappは別途ABMに申請が必要

# 参考記事
- [【2022最新版】法人がiOSアプリをApp Storeに非表示アプリとしてリリースする方法](https://qiita.com/YutaManaka/items/28106ba70716e0d4f488)
- [カスタムApp（CustomApp）とは何か（１） 〜非公開アプリをリリースする唯一の方法〜
](https://www.micss.biz/2021/03/08/3427/)
- [iOSのアプリURLを知る方法](https://qiita.com/macoril/items/48125b2a0a48339b3693)
Pydantic V2でのNone

Pydanticでモデル定義をしていたソースコードが、Pydantic V2でバリデーションエラーを出すようになり困った話。

None定義のルールが厳格化されたようで、定義の仕方がこちらの記事が大変参考になりました。

https://zenn.dev/ohke/articles/4a65d4b78637bc#%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%81%AF%E5%AD%98%E5%9C%A8%E3%81%99%E3%82%8B%E3%81%8B%3F-none%E3%82%92%E8%A8%B1%E3%81%99%E3%81%8B%3F
LangChain pydanticを触ってみた

### やってみたこと
昨日、ConpassのLang Chainのイベントで登壇者が話されていた「pydantic」が
気になったので触ってみた！
ゴールはとりあえず何かしらのプロンプトの返答が返ってきたらOK！


### 書いてみた（いやほぼ真似してみた）
pydanticは構造化してくれるよう。。
他がまだあまり詳しくないのでメリットがわかっていない。。

```python
from langchain_openai import ChatOpenAI
from pydantic import BaseModel

class Output(BaseModel):
    """Output Structure"""
    answer: str
    reason: str
    
model = ChatOpenAI(model="gpt-4o-mini", temperature=0).bind(seed=0)
model = model.with_structured_output(Output)

output = model.invoke('海外で住みやすい都市を理由をつけて教えて下さい。')
print(output.answer)

```
！回答
```
バンクーバー（カナダ）
   - 理由：美しい自然環境、温暖な気候、多文化共生が魅力。教育水準が高く、医療制度も充実しているため、生活の質が高い。
```
terraform state rm でリソースが見つからないエラー

## 問題
`for_each`でstring型をキーとするリソースを作成しました。`terraform state rm` でsteteファイルからリソースを削除しようとしたところ、エラーが出て削除ができませんでした。

```hcl:main.tf
resource "random_pet" "main" {
  for_each = toset(["a", "b", "c"])
}
```
```console
❯ terraform state list
random_pet.main["a"]
random_pet.main["b"]
random_pet.main["c"]

❯ terraform state rm random_pet.main["c"]
╷
│ Error: Index value required
│
│   on  line 1:
│   (source code not available)
│
│ Index brackets must contain either a literal number or a literal string.
```

## 原因
ダブルクォーテーションをエスケープしていないからです。
このエラーの原因は、コマンドライン引数の解釈にあります。Terraformは、リソース名に含まれるダブルクォーテーション（`"`）をコマンドの一部として誤って解釈してしまいます。これは、シェルの引数解析メカニズムとTerraformの期待する入力形式の不一致から生じる問題です。

## 解決方法
Linux, macOSの場合、リソース名をシングルクォーテーション(`'`)で囲ってください。
これにより、シェルがダブルクォーテーションを特別な文字として解釈することを防ぎ、Terraformに正しい形式でリソース名を渡すことができます。

正しいコマンド形式は以下の通りです：

```console
❯ terraform state rm 'random_pet.main["c"]'
Removed random_pet.main["c"]
Successfully removed 1 resource instance(s).
```

## まとめ
Terraformの `terraform state rm` コマンドを使用するときは、リソース名の正しい指定が重要です。特に、ダブルクォーテーションを含むリソース名を扱う場合は、シングルクォーテーションでコマンド全体を囲むことで、意図した通りの操作を実現できます。

## 確認をした環境
- Terraform v1.9.2

## 参考
https://developer.hashicorp.com/terraform/cli/commands/state/rm
【学習】自分で背景を作成してみる。Adobe Express

# はじめに

アプリ制作において、背景を無料画像サイトから選択して利用するのもいいのですが、今回は自分で背景を作成してみました。

## 利用したサイト
https://new.express.adobe.com/

👆こちらのサイトは無料枠と有料枠があります。無料枠内でも十分に作成できます。

https://321web.link/creative-cloud-express/

👆また、こちらの記事では無料と有料の違いを理解することができます。

## 作成手順はどんな感じ？
必要事項を入力して新規登録を行った後は次のようなページが表示されるかと思います
[![Image from Gyazo](https://i.gyazo.com/edcf78aeb400ba482b7ded80b901085f.png)](https://gyazo.com/edcf78aeb400ba482b7ded80b901085f)

「素早くかんたんに作成」から作成もできますが、サイドバーにある、「+」マークからも作成することができます。

#### AIで作成を選択した場合
[![Image from Gyazo](https://i.gyazo.com/358cfb886863a19845f6f4860345be19.png)](https://gyazo.com/358cfb886863a19845f6f4860345be19)

内容を記入：「大空をとぶペンギンたち」
コンテンツタイプ：「アート」
生成ボタンを押す

[![Image from Gyazo](https://i.gyazo.com/2ad7a837277038e223790839bc994006.png)](https://gyazo.com/2ad7a837277038e223790839bc994006)

生成画像はまず4つ生成されます。
「さらに生成」というボタンを押すことでさらに4つ生成することも可能です。

## さいごにまとめ
今回たまたま「背景画像作成」というような内容で検索したらこちらのサイトを利用して背景を作成するに至りました。
私自身は「新規ファイルを作成」からテンプレートなどは使用しない形で作成しましたが、利用したらもっと素敵な背景の作成も可能だという事を知ることができました。
皆さんのお勧めする背景・画像作成サイトがあれば教えていただきたいです。
今回の記事が何か参考になれば幸いです。

ついでに私が作成した背景はこんな感じです。
[![Image from Gyazo](https://i.gyazo.com/e5ca51511917644b1675b9d6607ef52f.png)](https://gyazo.com/e5ca51511917644b1675b9d6607ef52f)
私が低賃金でも今転職しない理由と、それでも将来の転職のためにやっている活動について

今回は給料が多いわけではない私が
転職する選択肢を視野に入れつつ
お金が尽きるまでは
現在の職場で働こうと決意した件について
話したいと思います。

***

現在の私の環境について

・就労継続支援 A 型で勤務
・勤務はとても楽しくストレスフリー
・最低賃金で 1 日 4 時間勤務
・月の休みは 8 日
・つまり給料は月 9万3000円 程度
・親の家に住んでいて食事代まで出して貰っている

という状況です。

親が亡くなったら転職しないと
生きていくのが難しい現状ですね。

***

何故今転職しないのか

今転職しない理由ですが

「仕事が楽しいから」

これにつきます。

親の支援を受けている現状ではありますが
かといってこれほど楽しく続けている職場を
辞めたくはないのです。

「転職しないとお金が無い」

という状況にならない限り
現在の職場を辞めたくないのです。

現在の職場に入社した時は
「5 年で一般就労したい」と希望していました。
しかしながら現在の職場を続けていると
楽しくて仕方ないのです。

なので親には申し訳ありませんが
この仕事を続けたいと考えているのです。

***

転職に向けてやっていること

転職に向けてやっている事として

「フリーソフトの公開」
「Qiita への投稿作業」

を続けています。

これらに効果があるか分かりませんが
Unity Asset Store の宣伝活動と銘打って
これらの作業を並走させて貰っています。

フリーソフトの公開は
このレベルのソフトなら作れるという
宣伝に繋がるかと思い作っています。

Qiita への投稿作業は
私のレベルが転職の時に伝わりやすいと思い
続けています。

転職の時にこれらの成果物があった方が
無いより絶対に就職活動しやすいと思うのです。

現在の職場で働きつつ
転職の時の手札増強を視野に入れる
これが現在の私の現状です。

***

以上、今転職しない理由と
将来転職せざる得ない場合のために
私がやっている作業を紹介しました。

ソフトを販売する取り組みを行っているならば
Qiita で知名度向上するのは間違っていないと思います。
そしてそれは将来の就職活動に繋がると思っています。

転職を考えているならば
会社でこれらの活動ができないとしても
これらの活動をしても良いと個人的に思います。

この活動を真似して
就職活動に繋がる人が現れたならば
大変嬉しいです。

皆さんが行動するきっかけになれますように。
閲覧ありがとうございました。

***

蛇足の追記

転職ドラフトについて調べてみました。
プロフィール欄が凄い充実しています。

〇〇がID:〇〇さんのQiitaを見ました！

という履歴が見れるの良いですね。
Qiita で記事を書いているので
将来的に使ってみたいなと思う
uni928 でした。

閲覧数 0 とかになると
メンタル豆腐な私としては
キツイですが...
AlmaLinuxにCockpitをインストールしてサーバをWebで管理する

# 0.はじめに
## 従来は・・・
サーバは大抵、ラックマウントしてたり、~~おうちの片隅に放置~~邪魔にならない適切な場所に設置して管理しますが、大抵ディスプレイやキーボードは接続せずに、ssh経由でアクセス、管理します。
しかし、ぶっちゃけsshコマンドでいろんなオプションつけて実行するのは面倒で、そもそも忘れるし、イントラネットやエアギャップ環境などの、ある程度ゆるいしよくね？な環境の場合はCUIオンリーだと面倒です。
そんな時はcockpitを利用するのも一つの手です。

## cockpitって？
cockpitとは、ざっくばらんに言うと、WebUIでサーバ管理できる環境とそれを提供するツールの事です。サーバの停止・再起動や、簡単なサーバスペック、統計情報などをWebブラウザで見る事ができるようになります。

cockpitを動かすリソースとしてもそれほど消費している訳でもなさそうで、1コア、メモリ512MB環境でももっさりせずに動作しています。

↓こんなのとか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599902/46580a14-76b7-04e8-d45b-cb68cd39570e.png)

↓こんなのとか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599902/1d71a8e1-bf8a-c23d-19cd-a14257f759aa.png)

↓こんなのとか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599902/27df6896-3ee7-02c6-cc5d-39bb7a9e0fdf.png)

が見れます。便利そうでしょ？

しかもこれはRHEL系だけのものではなく、他のディストロでも使用できます。

:::note 
- 本手順はAlmaLinux9.4を最小構成でインストールした状態での操作を想定しています。
- 本手順はsudo実行を省略しています。コマンドコピペで実行できないよと言う初学者さんは手前味噌なページを見てからご利用下さい。
:::

https://qiita.com/44dayo/items/81b50d2d757af35395f9

# 1.インストールと設定
- cockpitをインストールしたいAlmaLinuxのコンソールを開くか、ssh接続します。
- 以下のコマンドを実行します。
```bash
# dnf install cockpit
# systemctl enable --now cockpit.socket
# firewall-cmd --add-service=cockpit --permanent
# firewall-cmd --reload
```
たったこれだけでインストールは終了です。ね、簡単でしょ？

# 2.ログイン
- お使いのWebブラウザで以下のURLにアクセスします。

```
https://サーバのIPアドレス:9090
# 例えばhttps://192.168.1.10:9090など
```

:::note warn
- 大抵の場合は以下のような警告が出ますが、これについての説明は割愛します。これはchromeで開いた場合です。`詳細設定`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599902/f0793118-a9e1-dadb-8afc-c6732a981b5e.png)

- `"サーバIPアドレス"にアクセスする(安全ではありません)`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599902/9c8272f0-22ea-4a69-e6f1-aa83001b7351.png)
:::

- `ユーザー名`と`パスワード`を入力して`ログイン`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599902/903d36e8-7d5b-52c1-10d8-b33e1a09308f.png)

- こんな感じの画面が表示されたら成功です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599902/1c04e628-9486-6f07-be04-202a689790f3.png)

後は左ペインのアプリケーションから、色々有効にしたい機能をインストールすれば使えるようになります。

:::note info
画像は既に色々インストール済みの物です。初期状態だと表示されているものはもう少し少ないです。
:::


# 3.使ってみて
がっつり使い込んでいる訳ではないのですが、実際に使ってみて思ったのが・・・
- CUIに慣れてないメンバーや顧客にサーバ再起動やサーバ情報を参照させる時によかった
- ストレージの組込みとRAID設定が超楽になった
- CUIを使うにしてもopensshよりcockpitからの方がストレスが少なくなった

あたりです。


できる事、できない事、いくつかの制限などがありますが「簡易的なオペレーションしかしない」、「簡易的なオペレーションだけcockpitを使うようにする」などと分けて考えれば有用なツールです。

運用管理オペレーションの簡素化を検討している方は是非試してみて下さい。

# 参考リンク
https://cockpit-project.org/

https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/9/html/managing_systems_using_the_rhel_9_web_console/installing-the-web-console_getting-started-with-the-rhel-9-web-console
Dockerfile: install gcloud CLI

## 動機
Googleが公開しているimage `google/cloud-sdk`を最初にPULLすれば簡単なのだが、例えばPythonのバージョン依存などで`python:3.10-slim`をbaseにしたいとき自分でgcloud CLIをインストールする必要性があった。

https://hub.docker.com/r/google/cloud-sdk

## Dockerfile
できてしまえば簡単だが忘れると面倒なのでメモ。

```Dockerfile
FROM python:3.10-slim

RUN apt-get update && apt-get install -y \
  curl \
  apt-transport-https \
  ca-certificates \
  gnupg \
  sudo
RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list \
  && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg \
  && apt-get update -y \
  && apt-get install google-cloud-sdk -y

ENV CLOUDSDK_CORE_PROJECT=[your google cloud project]

# Allow statements and log messages to immediately appear in the Knative logs
ENV PYTHONUNBUFFERED True

# Copy local code to the container image.
ENV APP_HOME /app
WORKDIR $APP_HOME

# Install production dependencies.
RUN pip install --break-system-packages --no-cache-dir -r requirements.txt
RUN chmod +x main.py

ENTRYPOINT ["python3", "main.py"]
```

## Reference
インストールのcommandは以下のドキュメントを参照した:
>Docker Tip: If installing the gcloud CLI inside a Docker image, use a single RUN step instead: ...

https://cloud.google.com/sdk/docs/install#deb