OmniAICreator/Qiita-1.07M huggingface dataset:
Proxmoxのマニュアルに管理GUIからアクセスする


## TL;DR

- 管理GUIから利用中バージョンのマニュアルにアクセスできる！
- 作業中の項目にも直アクセスできる！
- でもアクセスできないものもある…

## 概要
毎回、以下のオンラインマニュアルからブラウザの検索機能で該当箇所を探していたのですが、管理GUIからマニュアルにアクセスできるじゃん！
しかも今利用しているバージョンのマニュアルじゃん！ということに今更気が付いた！


https://pve.proxmox.com/pve-docs/index.html




## ヘッダのドキュメントは目次へアクセス

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/59ab83b4-d80c-1f63-cc1b-d8e2c4866bdd.png)



`ドキュメント`をクリックすると、目次へアクセスします。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/5d513bf3-6a90-befa-8d06-ad1ec41673eb.png)

ぱっと見オンラインマニュアルと同じかと思わせておいて、よく見るとローカルを参照しています。
オンかオフかわからなくなりそうですが、URLはもちろん、アイコンが違います。
黒背景がオン、白背景がオフです。


## ヘッダのヘルプからは該当項目に直アクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/eccfed95-2ea9-f492-5cb6-cdb56ef070ae.png)



`ヘルプ`をクリックすると今選択中の項目のマニュアルに直アクセスできます。
`クラスタ`を選択中であれば、`Cluster Manager`に直アクセスできます。



## ポップアップのヘルプからも直アクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/e2bb3e5f-e1f4-26a1-299c-4df9e933a8b8.png)

何か操作をしようとしたときのポップアップにもマニュアルへのリンクがあります。
`クラスタを作成`をクリックした後のポップアップの`ヘルプ`からもアクセス可能です。
この場合は`Create a Cluster`へアクセスします。






## でもヘルプがないものもある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/7a1abbaf-c4d6-d1ea-22e4-da1f43edd5dd.png)

例としては`ユーザ`の`追加`には`ヘルプ`へのリンクはありません。
マニュアル及び、設定要素がないからだとは思うのですが、`キーID`あたりの解説はほしいかも…
【ChatGPT有＋DALL-E3】はデカいのがお好き？人間はふつうサイズが好き？


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

　今回は、DALL-E3はデカいのがお好き？　それでも人間はふつうサイズが好き？　というお話。

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

　昨日一昨日くらいからでしょうか？

　cotomoという
　　iOSアプリが
　　　話題です。

　知らない方のために
　　説明しますと、
　　　会話できるBotアプリです。

　“そんなの、前からあるじゃん”
　　そう思われるかもしれませんね。

　ところがこちら、
　　こちらが話していると
　　　相槌をうつ。

　遅延なく
　　回答してくる、というのです。

　おそらく、
　　中身は、ChatGPT 3.5だろう、
　　　という話が上がっていますが
　　　　真偽のほどは
　　　　　わかりません。

　ChatGPTであれば、
　　Custom instructionsに
　　　ゴリゴリ書いているのでしょう。

　それとシステム側で
　　音声入力時に
　　　対話者の息継ぎなどを
　　　　チェックして
　　　　　相槌をうつようにしていて
　　　　　　話し終わりに
　　　　　　　ChatGPTに渡す、
　　　　　　　　みたいな仕組みかな。

　Android版がないので
　　私は試せませんよ　ﾄﾎﾎ
***
　さて
　　本題にいきましょう！

　DALL-E3さんに
　　物体の描画を
　　　依頼すると、
　　　　対比物があった場合、
　　　　　その物体の大きさが
　　　　　　デカい、ということが
　　　　　　　まま、あります。

　例えば、
　　“和室でお茶を点てる”みたいな
　　　依頼をすると、
　　　　器はふつうなのに
　　　　　茶せん（撹拌するヤツ）は
　　　　　　器の口と同じくらいの
　　　　　　　大きさだったり。

　逆に、
　　小さ過ぎる場合も
　　　ありましたねw

　それなのに
　　巨大な女性に
　　　街を歩かせると、
　　　　人よりは大きいけれど
　　　　　倍の身長にも
　　　　　　なりません。
***
　どうしてこうなるのか？

　考察してみました。

　人間は、
　　こういうものだ、と
　　　教え込まれています。

　おそらく、
　　一番、描画されますから
　　　多くの情報を教え込まれて
　　　　いるはずです。

　だから、
　　巨大にもちっこくにも
　　　ならない、とわかり、
　　　　許容範囲でのサイズ感に
　　　　　なるのでしょう。

　では、
　　ものについては、
　　　どうでしょう？

　これは
　　人間とは違い、
　　　情報がものによって
　　　　異なります。

　よく使われるものは
　　情報量が多く、
　　　使われないものは、少ない。

　人間でも
　　同じですよね。

　“黒いリンゴ”と聞いて、
　　どのようなリンゴかは
　　　想像はできます。

　ちなみに、実際にありますよw

　“ブラックダイヤモンドアップル”と
　　呼ばれており、
　　　正式品種名は
　　　　「レッドデリシャス」
　　　　　　と言います。

　では、
　　“チャウシー”は
　　　どうです？

　ふつうの人は
　　知らないですが、
　　　愛猫家ならば、
　　　　写真で見たことが
　　　　　あるかと思います。
　　　　　　そう、猫です。

　このように
　　名前から、
　　　そのものズバリを
　　　　言い当てるのは、
　　　　　知識が必要ですよね。

　DALL-E3さんも
　　知識をもとに
　　　描画しているわけです。

　その知識が
　　少なければ、
　　　“描画しろ”と言われても
　　　　難しい。

　細かく形状を
　　説明したとしても、です。
***
　ならば、
　　どうすればいいのか？

　ものによります、
　　としか言えません。

　それでも
　　ヒントは
　　　提供できるかと。

　さきほどの
　　“巨大な女性が街なかを歩く”
　　　のを考えてみましょう。

　ふつうならば
　　ありえません。
　　　DALL-E3さんは
　　　　そう判断します。

　では
　　逆に考えてみましょう。

　女性はふつう、
　　街が小さくなる。

　しかし、
　　それも
　　　ありえません。

　ですが、
　　街並みを
　　　ミニチュアにしたら
　　　　どうでしょうか？

　要するに
　　実写撮影の手法ですね。

　ゴジラが
　　街なかを
　　　歩きながら暴れる、のを
　　　　想像してみてください。

　想像できますよね。

　それと同じです。

　実際にやってみると
　　DALL-E3さんも
　　　描画してくれます。

　しかし、
　　どうしても
　　　ミニチュア感が
　　　　出てしまいます。

　ここで
　　“臨場感を増加してください”と
　　　プロンプトに加えます。
![Imagine_a_highly_detailed_and_realistic_scene_wher.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/d49cf3cb-773f-242c-e54b-f3bb60d9d35d.jpeg)

　こうしたヒントが
　　みなさんの
　　　作品制作の糧に
　　　　なれば、幸いです。

　今回は、ここまで。
Pythonで電卓を作る方法の解説（初心者向け）（サンプルコードあり）

# この記事の対象者
pythonの条件分岐や四則演算、繰り返しや変数、定義を学び、それらのまとめとして何か作ってみたいという方向けです。
# プログラム
早速ですがまずプログラムを貼っときます。
解説は後でします
```python:電卓.py
//各計算の定義
def add(x, y):
    return x + y

def subtract(x, y):
    return x - y

def multiply(x, y):
    return x * y

def divide(x, y):
    if y != 0:
        return x / y
    else:
        return "Error: Division by zero"

while True:
    print("選択してください:")
    print("1. 足し算")
    print("2. 引き算")
    print("3. 掛け算")
    print("4. 割り算")
    print("5. 終了")

    choice = input("選択 (1/2/3/4/5): ")

    if choice == '5':
        print("処理を終了します。")
        break

    if choice in ('1', '2', '3', '4'):
        num1 = float(input("最初の数: "))
        num2 = float(input("次の数: "))

        if choice == '1':
            print(num1, "+", num2, "=", add(num1, num2))
        elif choice == '2':
            print(num1, "-", num2, "=", subtract(num1, num2))
        elif choice == '3':
            print(num1, "*", num2, "=", multiply(num1, num2))
        elif choice == '4':
            print(num1, "/", num2, "=", divide(num1, num2))
    else:
        print("無効な選択です。正しい選択をしてください。")
```
# 解説
まず最初の
```java
def add(x, y):
    return x + y

def subtract(x, y):
    return x - y

def multiply(x, y):
    return x * y

def divide(x, y):
    if y != 0:
        return x / y
    else:
        return "Error: Division by zero"
```
というので掛け算、割り算、足し算、引き算の動作を定義します。
次の
```java
while True:
    print("選択してください:")
    print("1. 足し算")
    print("2. 引き算")
    print("3. 掛け算")
    print("4. 割り算")
    print("5. 終了")

    choice = input("選択 (1/2/3/4/5): ")
```
というので何算をするか選ばせています。
最後の
```java
    if choice == '5':
        print("処理を終了します。")
        break

    if choice in ('1', '2', '3', '4'):
        num1 = float(input("最初の数: "))
        num2 = float(input("次の数: "))

        if choice == '1':
            print(num1, "+", num2, "=", add(num1, num2))
        elif choice == '2':
            print(num1, "-", num2, "=", subtract(num1, num2))
        elif choice == '3':
            print(num1, "*", num2, "=", multiply(num1, num2))
        elif choice == '4':
            print(num1, "/", num2, "=", divide(num1, num2))
    else:
        print("無効な選択です。正しい選択をしてください。")
```
というので各処理をしています。（計算とか）
# 最後に
まぁこんな感じですね。
間違えているところがあったら優しく教えてください。（小学生なので）
ありがとうございました！
request テストで rpsec テスト用のパラメータを作成

# attributes_for
attributes_for を用いることで、モデルに紐づくパラメータを簡単に作れる


```rb
    let(:valid_params) { attributes_for(:agent_scout_company) }
    let(:valid_params) do
      {
        name: "株式会社ホゲ",
        name_kana: "カブシキガイシャホゲ",
        zipcode: "1057510",
        address: "東京都港区 東京",
        tel: "0312345670",
        url: "https://www.hoge.co.jp",
        license_number: "11-ユ-343453"
      }
    end

```
ジョークプログラム'pseudovirus'

このスクリプトに実行権を与え、DEのアプリケーションのランチャに
仕込んでおきましょう。firefoxのアイコンのアプリケーションランチャを、このスクリプトを起動するように指定すると、ジョークメッセージが表示された後、firefoxを起動します。
悪質なジョークですが、実害はありません。スクリプトを見せれば納得してもらえるはずです。
・zenityのインストールが必要です。
sudo pacman -S zenity
・実行権を与える
chmod +x pseudovirus


```pseudovirus
#!/usr/bin/bash
#
# joke program 'pseudovirus'
# このスクリプトに実行権を与え、DEのアプリケーションのランチャに
# 仕込んでおきましょう。firefoxのアイコンのアプリケーションランチャを、このスクリプトを起動するように
# 指定すると、ジョークメッセージが表示された後、firefoxを起動します。
# 悪質なジョークですが、実害はありません。スクリプトを見せれば納得してもらえるはずです。
# ・zenityのインストールが必要です。
# pacman -S zenity
# ・実行権を与える
# chmod +x pseudovirus
 

# JOKE MESSAGE
    sleep 1
    zenity --info --text="ウィルスが検出されました。\nシステムが致命的なダメージを受けています。\nOSを再インストールしてください。"
    zenity --info --text="嘘です。"

#   
# LAUNCH APPLIUCATION
# ここで、アプリケーションをラウンチします。
#
/usr/lib/firefox/firefox
```
クイックソート



今回はクイックソートについて。
よく分からなかったので考え方について検索

https://medium-company.com/%E3%82%AF%E3%82%A4%E3%83%83%E3%82%AF%E3%82%BD%E3%83%BC%E3%83%88/

上のがわかりやすかったです。
要するに、グループの中で、ある一つの値を決め、その値より大きいグループと小さいグループにわけ、それらの中でも同じようにわけ、ソートする感じ。


```py
# アルゴリズムが正しく実装されていることを確認するために導入するカウンタ変数、ソート処理には関係がないことに注意
count = 0


"""
    A[left] ~ A[right-1] をクイックソートする
    配列 A をクイックソートするには quick_sort(A, 0, n) を呼び出す
    left＝左端、right=右端
"""
def quick_sort(A, left, right):
    # ソートする範囲の長さが1以下の場合は何もしない
    if left+1 >= right:
        return

    # データ列の末尾 A[right-1] をピボットとする
    pivot = A[right-1]

    # ピボット未満のデータを挿入する位置を保持する変数を用意
    cur_index = left

    for i in range(left,right-1):
        if A[i] < pivot:
            #見つかったら交換する
            A[cur_index], A[i] = A[i], A[cur_index]
            cur_index += 1
            global count
            count += 1

    # ピボットを A[cur_index] へ移動し、データ列を分割する
    #　つまり、交換する
    A[cur_index], A[right-1] = A[right-1], A[cur_index]
    
    # 分割されたデータ列に対して再帰的にクイックソートを行う
    quick_sort(A, left, cur_index)
    quick_sort(A, cur_index+1, right)
    
    
n = int(input())
A = list(map(int,input().split()))
quick_sort(A, 0, n) 
print(*A)
print(count)

```
Pandasの列単位での演算、加工



## はじめに
Pandasの演算、加工の基本に関しての備忘録です。
コードを書き始めて1年以内の若輩者です😅
もし間違いがあれば、ご指摘いただけると助かります🙇
<br>
## 🦁<INS>**結論**</INS>🦁
Excelのように列ごとに演算、加工が可能。
シンプルに列を選択して演算を入れて計算、加工することが可能。

:::note info
押さえておくべき点
* 演算結果を元のDataFrameに直接反映させるか、新しいDataFrameを作成するかを選択できる。
* 日付や時刻のデータを加工して、曜日や月などの情報を抽出もできる。
:::  
***

:::note alert
注意点
*  データ型を確認する必要がある。（特に、数値演算を行う際に文字列型のデータが含まれているとエラーが発生するため、dtype属性やastype()メソッドを用いてデータ型を確認・変換することが重要）
* inplace=Trueの使用: 元のデータを上書きすると、元に戻せないため注意が必要。
:::  

***

## <INS>**コード例**</INS>

## <INS>**数値での演算**</INS>
新しい欄を作成してそこに演算した数値を反映させる。
既存部分に追加するなど可能。

```py
import pandas as pd

# データフレームの作成
df = pd.DataFrame({
    'A': [1, 2, 3, 4],
    'B': [10, 20, 30, 40]
})

# 列Aに2を足す
df['A'] = df['A'] + 2

# 列Bから列Aを引いた結果を新しい列Cに保存
df['C'] = df['B'] - df['A']

# 列Aの平均値を計算
average_of_A = df['A'].mean()

# 条件付きで新しい列Dを作成（列Aが3より大きい場合はTrue、そうでなければFalse）
df['D'] = df['A'] > 3

# 日付列の加工（ここではサンプルとして現在日付を追加）
df['Date'] = pd.to_datetime('2024-02-27')
df['Year'] = df['Date'].dt.year

print(df)
```

## <INS>**文字列の演算**</INS>
文字列になにかを追加したい場合にも使える。

```py
import pandas as pd

# データフレームの作成
df = pd.DataFrame({
    'First Name': ['John', 'Jane', 'Jim', 'Jill'],
    'Last Name': ['Doe', 'Doe', 'Smith', 'Johnson']
})

# 名前と姓を結合してフルネームを作成
df['Full Name'] = df['First Name'] + ' ' + df['Last Name']

# 文字列の置換（例えば、'John'を'Jonathan'に置換）
df['First Name'] = df['First Name'].replace('John', 'Jonathan')

# 文字列の大文字化
df['Last Name'] = df['Last Name'].str.upper()

# 特定の文字列を含む行をフィルタリング
contains_doe = df['Last Name'].str.contains('DOE')

# 文字列の長さを新しい列に追加
df['Name Length'] = df['Full Name'].str.len()

print(df)
print(contains_doe)
```
***  

## まとめ✍️
 Excelよりも全然早く、また自由も効く。
文字列も色々反映できる。

## 参考にした記事📕
[Pandasの基本～表
形式データ・データ分析～初心者向けのDataFrameの操作入門！]
(https://youtu.be/HYWQbAdsG6s?si=m4Tl3UlmXLlhTxhZ)
Laravel Sailが起動できない（自分用）

# Laravel プロジェクトの作成でのエラーについて

コマンドでLaravel Sailを起動したところ...
```
$ cd example-app
$ ./vendor/bin/sail up
```
```
Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:80 -> 0.0.0.0:0: listen tcp 0.0.0.0:80: bind: address already in use
```
http://localhost/ にアクセスしてもLaravel の起動画面が表示されない。

# 対処法
参考
https://01memo.com/docker/ports-error1/
```
// ターミナルに入力
sudo lsof -i:80
// 実行結果
COMMAND   PID   USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
httpd    7262   root   15u  IPv6 0x879c8e7bc96759a9      0t0  TCP *:http (LISTEN)
httpd    7266 daemon   15u  IPv6 0x879c8e7bc96759a9      0t0  TCP *:http (LISTEN)
..(省略)...
```

# 解決
```
// ターミナルに入力
sudo kill 7262
```


http://localhost/ にアクセスしてLaravel の起動画面が表示されるようになった！
アジャイル検定Lv1受けてきました

## はじめに
先日アジャイル検定Lv1に合格しましたので、
検定を受けるにあたっての勉強法や感想について書いていきたいと思います。
## アジャイル検定とは
正式名称は「アジャイルソフトウェア開発技術者検定試験」
アジャイル開発のスキルを客観的な尺度で分析・判定する試験になります。

https://agilecert.org/

二つのレベルがあり、
アジャイル開発の基礎的な知識について問われる、レベル1
アジャイルのチーム開発について問われる、レベル2
となります。
今回自分が受けてきたのはレベル1の方である
「アジャイルソフトウェア開発技術者検定試験 Lv.1」です。
### 試験概要
<dl>
  <dt>試験時間</dt>
  <dd>60分 (守秘義務契約およびアンケートは別)</dd>
  <dt>出題形式</dt>
  <dd>多肢選択式 (四肢択一)60問</dd>
  <dt>評価方法</dt>
  <dd>80％以上合格</dd>
  <dt>受験料</dt>
  <dd>10,000円(税別)</dd>
</dl>

## 勉強法
アジャイル検定約一か月前から検定に向けちまちま勉強を始めました。
![juken_sleep_inemuri_man.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632606/bfb49cb2-c031-7bf5-01b5-9c07de92dec3.png)
ですが、アジャイル検定過去問が一切出回っていません。
ITパスポートの時のように過去問を数年分解いて勉強する…という
ごり押し戦法が通じないので地道に勉強することになりました…。
初めにアジャイル検定公式テキストを、大事そうな単語などを
ノートにメモしながら一通り読みました。

https://www.amazon.co.jp/%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E6%A4%9C%E5%AE%9A%E5%85%AC%E5%BC%8F%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A8%E3%82%A2%E9%96%8B%E7%99%BA%E6%8A%80%E8%A1%93%E8%80%85%E6%A4%9C%E5%AE%9A%E8%A9%A6%E9%A8%93-%E3%83%AC%E3%83%99%E3%83%AB1%E5%AF%BE%E5%BF%9C-%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A8%E3%82%A2%E9%96%8B%E7%99%BA%E6%8A%80%E8%A1%93%E8%80%85%E6%A4%9C%E5%AE%9A%E8%A9%A6%E9%A8%93%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%82%B7%E3%82%A2%E3%83%A0/dp/4865940871/ref=as_li_ss_tl?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E6%A4%9C%E5%AE%9A&qid=1554945560&s=gateway&sr=8-1-fkmrnull&linkCode=sl1&tag=certification-22&linkId=8621556f970dd2f91f0c4b98b32ad003&language=ja_JP

前所属していた部署の先輩が「アジャイル宣言」を毎日読んでれば
アジャイル検定は余裕で受かる、なんてことを言っていたので、
「アジャイルソフトウェア開発宣言」と「アジャイルソフトウェア開発の原則」を
紙に書いて部屋の壁に貼って毎日目を通すようにしてみました。
![ポスター.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632606/68d8afa3-c865-aba9-7f16-362df4c079b0.png)
アジャイル検定の一週間後にAZ900の試験も控えていたので
朝はAZ900、夜はアジャイルという感じに同時進行でテキストを読み進め
結局読み終わったのは検定の前日でした。
テキストを読み終わった後は、前述のとおり過去問が一切ないので、
テキストの章末の演習問題を数回解き、実戦のイメージをつけました。
## 試験当日
試験は10:30からだったのでそれまで会場の近くのファミレスで
テキストを軽く流し読みしたり、メモで使っていたノートを見返すなどして
時間をつぶしました。

試験は公式テキストを一通り読んでいれば解ける、という問題と
こんなのテキストに出てきたっけ…という感じでしたが、一通り解くことができました。
見直しも終え、時間は余っていましたがその時点で試験の終了処理をしました。

続いての結果発表画面。
総合スコアは、80%で合格のところ83%でした。(割とギリギリでした…)
![pose_goukaku3_man.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632606/1c8b689e-7bf2-6485-6e8b-414a94b16a65.png)
分野別正答率では「基礎知識」「開発チームの運営」は10割行っていましたが、
「開発技能」は7割を切っていました。
思い返してみると「常時結合」、「テスト駆動開発」のあたりは
テキストを読んでてもあまりピンとこない範囲でした。
結果受かったからいいものの割とギリギリな戦いでした…。

## 検定を終えて
今回のアジャイル検定受験をから、
アジャイル開発に関する基礎的な知識をつけることができました。
また、日々の業務の中で毎朝行われるミーティングは実はアジャイル開発の手法の
一つだったのかも…などと思ったりもしました。
今まで受けてきた他の検定と違い、過去問が公開されておらず、
実際の試験のイメージが付かない状況での試験でした。
テキストを読んで地道に勉強することの大切さについても知ることができたと思います。
反省点としてはテキストを読み終えるのを試験前日ではなく
もう少し余裕をもって読み切りたかった、というのと、
開発技能等の分野中の理解しきれていない範囲を理解した状態で
検定に挑みたかった、というところだと思います。

今回の検定で学んだことや反省を日々の業務の中で活かしていければと思います。
Mac - Cursor Editor の 設定ファイルのJSONの場所 ( 直接編集したい )

# 問題

VsCodeではコマンドでユーザ設定ファイルが開けるが、Cursorにはそのコマンドがない

<img width="730" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/b1886550-c0f6-43a0-b83f-14809b5ee0a4">

# 解決

`~/Library/Application\ Support/Cursor/User/settings.json` から編集できる




# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
シリアライズをpickleで行って高速化



## はじめに
シリアライズをpickleで行って高速化に関しての備忘録です。
コードを書き始めて1年以内の若輩者です😅
もし間違いがあれば、ご指摘いただけると助かります🙇
<br>
## 🦁<INS>**結論**</INS>🦁
データの蓄積や膨大なデータの読込を早くするためにシリアライズすることで読込、書込を早くすることができる。
Pythonでは標準ライブラリで「pickle」がある。
データが大きくなった場合には非常に便利なライブラリ。
また文字列もそのまま保管できる。

:::note info
押さえておくべき点
* シリアライズとはデータ一つのバイト列（バイナリデータ）に変換するプロセスのことを指す（他の形式もある）
* pickleファイルはバイナリモードで読み書きする必要がある。
* バイナリデータでの読み書きは処理が早くなる。
* 数行のコードでデータを保存・読み込みできる。
* 大量のデータも素早く保存・読み込みができる。
* テキストだけでなく、リストや辞書なども扱える。
* 自動的にデータを圧縮して小さくできることがある。
:::  
***

:::note warn
利用シーン
* 大量のデータを一時保存したいとき
* データ分析の中間結果を保存したいとき
* 機械学習モデルを保存したいとき
* 設定情報の保存したいとき
* セッション情報の保存したいとき
:::  
***

:::note alert
注意点
* 異なるPythonバージョン間でpickleファイルを交換すると、問題が起こることがある。
* テキストよりもバイナリデータの方が大きくなることがある。
* 人間が直接読むことができないバイナリ形式で保存される。
* pickleで保存されたデータは、Python以外では読み込めない。
:::  

***

## <INS>**基本コード**</INS>
膨大な数値データリストも一次保存としておいて置くデータとしても非常に簡単に操作でき、様々なデータをそのままの型を維持して保管できる。リストはもちろん、辞書も可能。

.pickleというファイルに保存される（.pkl）

```py
import pickle

# 保存したいデータ
my_data = {'key': 'value', 'number’: 42}

# データをバイナリ形式でファイルに保存する
with open(‘data.pickle’, ‘wb’) as file:
pickle.dump(my_data, file)

#ファイルからデータを読み込む
with open(‘data.pickle’, ‘rb’) as file:
loaded_data = pickle.load(file)

print(loaded_data)  
# {‘key’: ‘value’, ‘number’: 42} と表示される

```

## <INS>**文字**</INS>

```py
import pickle

# 文字列データ
greeting = "こんにちは、世界！"

# 文字列をバイナリ形式でファイルに保存
with open('greeting.pickle', 'wb') as file:
    pickle.dump(greeting, file)

# ファイルから文字列を読み込む
with open('greeting.pickle', 'rb') as file:
    loaded_greeting = pickle.load(file)
    print(loaded_greeting)  # "こんにちは、世界！" と表示されます
```

## <INS>**辞書データ**</INS>
辞書データもそのまま保存可能。
```py
import pickle

# 辞書を作成
my_friends = {
    'Alice': '123-456-7890',
    'Bob': '987-654-3210',
    'Charlie': '555-555-5555'
}

# 辞書をファイルに保存
with open('friends.pickle', 'wb') as f:
    pickle.dump(my_friends, f)

# ファイルから辞書を読み込む
with open('friends.pickle', 'rb') as f:
    loaded_friends = pickle.load(f)
    print(loaded_friends)  # 保存した辞書が表示されます
```
***  

## <INS>**クラスのオブジェクト**</INS>

```py
import pickle

# ペットを表すクラスを定義
class Pet:
    def __init__(self, name, animal_type):
        self.name = name
        self.animal_type = animal_type

# ペットのインスタンスを作成
my_pet = Pet('Fido', 'dog')

# インスタンスをファイルに保存
with open('pet.pickle', 'wb') as f:
    pickle.dump(my_pet, f)

# ファイルからインスタンスを読み込む
with open('pet.pickle', 'rb') as f:
    loaded_pet = pickle.load(f)
    print(loaded_pet.name, loaded_pet.animal_type)  # 'Fido dog' と表示されます
```
***  

## まとめ✍️
機械語に直すだけで処理が早くなるとはすごいなと思った。速度も全然違うこともビックリした。
これからどんどん使っていきたい。

***  
## 参考にした記事📕
[pickleでデータ保存をもっと便利に！～Pythonプログラミング入門～初心者にも分かりやすく解説！](https://youtu.be/tiklK1zcKec?si=u5Ng6plKbh1i5UQT)
react-dndからdnd kitへ乗り換えたい

## はじめに
現状、react-dndでドラッグアンドドロップを実現しているReactのアプリケーションのドラッグアンドドロップライブラリを変えようとしています。
その乗り換え先としては、いまReactのドラッグアンドドロップライブラリで一番勢いのありそうなdnd-kitを検討しています。

ここでは、react-dndで書かれているコードをdnd kitに変更するにはどうするのかというのを調べてみました。

## react-dndの不満点
そもそもreact-dndをなぜ乗り換えたいのかということなのですが、react-dndだとスマートフォン対応が面倒というのがあります。
react-dndはHTML5のドラッグアンドドロップ APIを使用して実装しているため、スマートフォンでは別の専用のバックエンドを指定する必要があります。
https://react-dnd.github.io/react-dnd/about#touch-support

そのため、デバイスタイプを見て、スマートフォンなら`TouchBackend`を使用し、PCならば`HTML5Backend`を使用する必要があります。
できればこのようなデバイスタイプを見て処理を切り替えるようなコードは採用したくないです。

## 対象のコード
対象となるコードは以下のようなコードで、ドラッグアンドドロップによくありがちなリストをドラッグアンドドロップで並び替えるようなものとはちょっとだけ違います。
オレンジ色のタイルをドラッグアンドドロップで移動するようなコードです。

https://codesandbox.io/embed/react-dnd-sample-yjx6jf

## dnd-kit
乗り換えの候補として選んだのがdnd-kitです。
https://docs.dndkit.com/

後発のドラッグアンドドロップライブラリで、最近は日本語の記事も増えてきています。
参考:
https://zenn.dev/castingone_dev/articles/dndkit20231031
https://zenn.dev/hamo/articles/725e4189bfc54d
https://smootech.net/s8envpsfod/

## dnd-kitで書き換えたコード
react-dndと同じようなhooksを使ったAPIなので比較的簡単に書き換えることが可能でした。

* drag中、移動もとのタイルを半透過で残すため、DragOverlayを追加
* drop終了時のアクションをDndContextへ移動

https://codesandbox.io/embed/dnd-kit-sample-vnc499

スマートフォンだと問題なくドラッグアンドドロップが動作するのですが、使用しているChakra-UIの影響なのか、PCのタッチパネルだと正常に動作しないです。

## おわりに
react-dndのコードをdnd-kitを使って書き換えてみたのですが、使用感としてはほぼ同じでした。
dnd-kitはSortable interfaceが用意されており、これを利用できるならばそれなりに簡単に書けそうです。
これを使えない場合は、どうしても書かなくてはいけないコードが多くなってしまうようです。
そのため、リストをドラッグアンドドロップで並び替えるような用途にdnd-kitは向いていて、それ以外では採用するメリットはなさそうです。
GCPにDjangoアプリをデプロイ

GCPインスタンス上でDjangoアプリをデプロイするまでにやったことをメモとして残す。

### システムを最新の状態にする
```bash
sudo apt update
sudo apt upgrade -y
```

### nginxのインストールと起動設定
```bash
sudo apt install nginx -y

sudo systemctl start nginx

# インスタンス立ち上げ時に自動で起動
sudo systemctl enable nginx
```
ここまでの作業でIPにアクセスすればNginxのWelcomeページを見れる

### gitのインストール
```bash
sudo apt install git -y

git --version
```

### Python系
```bash
sudo apt install python3-pip

sudo apt install python3.11-venv

python3 -m venv venv

source venv/bin/activate
```

### mysql系
```bash
sudo apt-get install python3-dev libmariadb-dev gcc pkg-config

sudo apt-get install mariadb-server

sudo mysql_secure_installation

```

### mysql系のインストールを1からやり直したい場合
```bash
sudo apt-get remove --purge mysql-server mysql-client mysql-common mysql-community-server
sudo apt-get autoremove
sudo apt-get autoclean

sudo rm -rf /etc/mysql /var/lib/mysql
sudo rm -rf /var/log/mysql*

sudo rm /etc/apt/sources.list.d/mysql.list

sudo apt-get update

```
【React】useEffectが２回呼び出される場合の対応方法

#### はじめに
useEffectのコールバックが２回呼び出される場合の回避方法について書きました。

参考資料は以下です。
[【React18】StrictModeは開発時にはuseEffectが２回呼び出される｜MarsquaiBlog](https://marsquai.com/745ca65e-e38b-4a8e-8d59-55421be50f7e/f83dca4c-79db-4adf-b007-697c863b82a5/84dda80d-d8a0-4a1a-a042-66848dc6afe9/)

#### ＜事象＞
１回しか呼ばれないはずのuseEffectのコールバックが２回呼び出されてしまう。

#### ＜原因＞
StrictModeは開発時にコンポーネントが初めてマウントされる時に、一度アンマウントして再度マウントし直される。
つまり、`<StrictMode />`の内部のコンポーネントは開発時には常にマウントが２度行われる。

#### ＜回避策＞
index.jsにあるReact.StrictModeのタグをコメント化する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579718/7fe8cdbe-c7ed-99a6-223c-7f59ed2be499.png)
Chakra UIのButtonでdisabledが使えない

# はじめに
どうもこんにちは！僕は現在1ヵ月本気の技術力向上を目指している現役高校生1年生(@shunii )です！
現在以下のUdemy講座をもとにChakraUIでの開発を進めていたのですが、困ったことがあったのでまとめます。

https://www.udemy.com/course/react_stepup/?couponCode=ST22FS22724

# 問題
ChakraUIのButtonコンポーネントでdisabledが使えない。
以下のようなコードを書いたのですが、ボタンを非活性にできませんでした。
```jsx:PrimaryButton.tsx
import { Button } from "@chakra-ui/react";
import { FC, ReactNode } from "react";

type Props = {
    children: ReactNode;
    disabled?: boolean;
    onClick: () => void;
};

export const PrimaryButton: FC<Props> = (props) => {
    //propsとしてdisabledも受け取る
    const { children, onClick, disabled=false } = props;
    return (
        <Button
            onClick={onClick}
            disabled={disabled}
        >
            {children}
        </Button>
    );
};
```

# 解決策
結論
<font color="red">**disabledをisDisabledにした**</font>

原因はChakra UIのButtonコンポーネントではdisabledオプションが使えないことにありました。おそらくバージョンの変更によるものだと思います。

変更後
```jsx:PrimaryButton.tsx
import { Button } from "@chakra-ui/react";
import { FC, ReactNode } from "react";

type Props = {
    children: ReactNode;
    disabled?: boolean;
    onClick: () => void;
};

export const PrimaryButton: FC<Props> = (props) => {
    //propsとしてdisabledも受け取る
    const { children, onClick, disabled=false } = props;
    return (
        <Button
            onClick={onClick}
            isDisabled={disabled}
        >
            {children}
        </Button>
    );
};
```

# 終わりに
バージョン変更による問題発生はすごく多いので今後も記事にして行けたらなと思います。今回は公式のドキュメントにも記載されていなかったので、少し戸惑いました。

# About Me
- X(Twitter)

https://twitter.com/shunii_hack

# 参考
https://qiita.com/FumioNonaka/items/3f3be1fa53727d113562

https://www.udemy.com/course/react_stepup/?couponCode=ST22FS22724
aタグtarget="_blank"のセキュリティ的問題点

今回の記事は、新米エンジニアの僕がフロントエンドの保守を行って、普段通りプルリクを出したら、すごく有益なコードレビューを上司の方にしていただいたのでそれをまとめます。

## aタグのtarget="_blank"
まず、この`target="_blank"`をaタグに追加するとどうなるかを説明します。
このオプションを追加することでaタグをクリックしたときに別タブが開かれて表示されるようになります。
これは、ブラウザの設定なども影響するのですが、基本的にはこのオプジョンをつければ、別タブでの表示が確約されます。

## target="_blank"のセキュリティ的な問題点
本来、リンクをクリックした時に別タブが開かれるようにする理由としては、ユーザエクスペリエンスを向上させ、離脱率を下げるという目的があります。しかし、この`target="_blank"`には、リンク元の情報を保持して別のタブを開くという性質があります。これによって、悪意あるユーザがリンク元のページの情報を抜き取ったり、攻撃をしたりするという問題が起こりえます。

## 解決策
この解決策としては、`rel="noopener noreferrer"`をaタグに追加するということです。
これにより、新しいタブが開かれたときに、そのタブからリンク元への参照とリファラ情報が削除されます。これにより、攻撃者がリンク元を使用してアクセスできる攻撃ベクトルが制限され、セキュリティが向上します。
名前付き export と デフォルト export

理解しているつもりでしたが、いざ質問されるとスラスラと回答出来ませんでした。これはうろ覚えというやつです。

二度とこういうことが無いように、今まとめておいて「この記事見て」で説明終わりにしようと思います。

# デフォルト export

**export default** という記述が、モジュールファイルに1回だけ記述出来る。

## サンプルコード1 - 関数編

### helloWorld.js

```javascript
export default function HelloWorld() {
    return 'Hello World!';
}
```

### index.js

```javascript
// helloWorld.js に記述されているメソッド名は HelloWorld() だが、好きな名前を付けられる。
import TekitouFunctionName from "./helloWorld.js";

console.log(TekitouFunctionName);
// コンソール出力
// Hello World!
```

## サンプルコード2 - 定数編

### HelloWorld.js

```javascript
export default const helloWorld = 'Hello World!';
```

### index.js

```javascript
// 好きな名前を付けられる
import TekitouConstName from "./helloWorld.js";

console.log(TekitouConstName);
// コンソール出力
// Hello World!
```


## エラーの example

ちなみに複数あるとエラーが発生します。


```javascript
export default function HelloWorld() {
    return 'Hello World!';
}

// 2つ目の export default のためエラー！！！！！！
export default function OhayouWorld() {
    return 'Ohayou World!';
}

```

## デフォルト export の利点

- import の際に好きな名前を付けられる。名前付き export は出来ません。
- 該当モジュール内で一番重要な export を明確にできる。まさか一番重要という訳ではない export に default は付けませんよね？


# 名前付き export

名前付き export は複数指定可能です
モジュール名の関数名、定数名などをそのまま指定する必要があります。

## サンプルコード

### helloWorld.js

```javascript
export function HelloWorld() {
    return 'Hello World!';
}

export function OhayouWorld() {
    return 'Ohayou World!';
}

export const OyasumiWorld = 'Oyasumi World!';
```

### index.js

```javascript
// 指定されたメソッド名、定数を記述する。
import {
  HellowWorld, 
  OhayouWorld,
  OyasumiWorld
} from "./helloWorld.js";

console.log(HellowWorld);
// コンソール出力
// Hello World!
console.log(OhayouWorld);
// コンソール出力
// Ohayou World!
console.log(OyasumiWorld);
// コンソール出力
// Oyasumi World!
```

## 名前付き export のエイリアス

名前付き exportはインポートの際にエイリアスを付与することが可能です。
これがあるとデフォルト export の利点がないのでは？

```javascript
import {
  HellowWorld as ohiru, 
  OhayouWorld as asa,
  OyasumiWorld as yoru
} from "./helloWorld.js"
```

## 名前付き export を一括 import

該当するモジュール内の名前付き export を一括で import します。
これがあるとデフォルト export の（略

```javascript
import * as helloWorld from "./helloWorld.js"
```

## 名前付き export の利点

- 上で書いてきた通り、細かい import の指定が可能


## デフォルト export と名前付き export は混在できる

デフォルト export の利点に「一番重要な export を明確に出来る」とは書きましたが、フロントエンド弱者な僕は混在させる利点が全く分かっていません。なんでだろ。

### HelloWorld.js

```javascript
// デフォルト export
export default function HelloWorld() {
    return 'Hello World!';
}

// 名前付き export
export function OhayouWorld() {
    return 'Ohayou World!';
}
```

### index.js

```javascript
// デフォルト export を import。好きな名前付けられる。
import TekitouFunctionName from "./helloWorld.js";
// 名前付き export を import。名前は指定される。
import {
  OhayouWorld
} from "./helloWorld.js";

console.log(TekitouFunctionName);
// コンソール出力
// Hello World!
console.log(OhayouWorld);
// コンソール出力
// Ohayou World!
```

# まとめ

僕も **「JavaScript 何も分からん」** 状態のとき、「 import する際の中括弧有り無しは何が違うんだよ！？」と憤った記憶があるので何となく懐かしい気持ちになりました。
pipについて

## pipでインストールされているライブラリの情報を見たい時

#### 特定のライブラリのバージョン情報をみたい場合
```python
pip show <library_name>
```
#### pipでインストールされている全ライブラリのバージョンを表示
```python
pip list
```
#### "pip list"のオプションを表示
```python
pip list -h
```

#### "pip freeze"のオプションを表示
```python
pip freeze -h
```

## pipでインストールしたい時

#### インストール
```python
pip install <library_name>
```

#### ライブラリのバージョン指定インストール
```python
pip install <library_name>==<desired_version>
```
【注意】
『library_name』と『desired_version』の間の"=="がダイジ！！

#### requirements.txtを使った一括インストール
```python
pip install -r requirements.txt
```
requirements.txtとは
```python
<library_name>==<desired_version>
```
のように、インストールしたい『library_name』と『desired_version』が延々記述されているテキストデータ

#### ライブラリをアップデートしたい時
```python
pip install --upgrade <library_name>
```
#### ライブラリをバージョンを指定してアップデートしたい時
```python
pip install --upgrade <library_name>==<desired_version>
```
StreamlitをPyCharmでデバックする


PyCharm community 2023.3では、以下と画面が異なっていました。

https://chemesim.xsrv.jp/wp/streamlit%E3%82%92pycharm%E3%81%A7%E5%AE%9F%E8%A1%8C%EF%BC%88run-debug%EF%BC%89%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95-631.html

Interpreter optionsに、-m streamlit run　を追加してみると、Run実行はできたけれど、
デバックできませんでした。

以下の設定
module をstreamlitとして、スクリプトパラメータに、
run 実行したいコード.pyを入れると、Debugでも動きました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643531/d47a048f-85eb-2a1d-0877-e1ce21b4e709.png)
【レビューで指摘されがちシリーズ】ロジック部分が未実装のメソッドには NotImplementedException が使えます 

久々のレビューで指摘された内容をそのまま放流するシリーズ。[まとめページ](https://qiita.com/lx-sasabo/items/c2d2e5ccae10ff3ecabd) もあります。

実装をしていると「今回はロジック部分を実装しないけどメソッドだけは用意しておく」のような場面はないでしょうか？

例えば、テンプレートメソッドパターンで実装する必要があるが現時点でテンプレート側にあるメソッドをすぐに使うことがないケースなどが考えられます。

例（メソッド自体が微妙なのはご了承ください。良い例が思い浮かばず…）

```cs
// 抽象クラス
abstract class AbstractClass
{
    // コンソールに何らかの情報を表示するメソッド
    // 実装はサブクラスに任せる
    protected abstract void Print();

    // ログを記録するメソッド
    // 実装はサブクラスに任せる
    protected abstract void Log();
}

// サブクラス
class SubClass : AbstractClass
{
    protected override void Print()
    {
        Console.WriteLine("ここは実装したよ");
    }

    protected override void Log()
    {
        // 現状使っていません。後々実装予定です。
    }
}
```

上記のように、今まで私はロジック部分の実装がないときは、コメントで「現状使っていません。後々実装予定です。」のように書いていました。また、返り値を返すメソッドの場合は通常取りえないダミー値を返していました。

そんなコードを書いていたら、 NotImplementedException を教えてもらいました。

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

NotImplementedException をスローすれば未実装であることが明確に分かる例外が発生するので、万が一中身を実装していないメソッドが使われた場合に気づくことができます。

NotImplementedException を使った場合

```cs
// サブクラス
class SubClass : AbstractClass
{
    protected override void Print()
    {
        Console.WriteLine("ここは実装したよ");
    }

    protected override void Log()
    {
        // 現状使っていません。後々実装予定です。呼び出すとエラーが発生します。
        throw new NotImplementedException();
    }
}
```


余談

この記事を書くために NotImplementedException について調べていたら、VisualStudio の機能でメソッドを生成すると、デフォルトで NotImplementedException をスローするコードが作成されることを知りました。

https://learn.microsoft.com/ja-jp/visualstudio/ide/reference/generate-method?view=vs-2022

なので普段から VisualStudio を使っている人からすると、この記事の内容はすごく当たり前の内容なっているかもしれません。
私は VisualStudio から逃げた人間なので知りませんでした…。（neovim で実装しています。）さすがにC#を生業とするなら VisualStudio を使えないのはまずいだろうと感じている今日このごろです。
WSLでディストリビューションをインポート・エクスポート

## 概要

* WSL（Windows Subsystem for Linux）でディストリビューションをインポート・エクスポートする手順メモ
* 実施環境：Windows 11

## 背景

* Microsoft Storeからインストールしたディストリビューションをベースに、利用目的に応じた個別の環境を構築しようと考えた
    * 例えば、開発用環境とレビュー用環境を分けて、開発の途中でもレビューにすぐ対応できるようにするなど
* インストールしたディストリビューションをエクスポートしてファイル化し、それをインポートしてディストリビューション名を個別指定すれば可能
* 今回は[AlmaLinux8](https://apps.microsoft.com/detail/9nmd96xjj19f?hl=ja-jp&gl=JP)の環境を作成

## 手順

### 1. ディストリビューションの一覧を確認

```bat
> wsl --list
Linux 用 Windows サブシステム ディストリビューション:
Ubuntu-20.04 (既定)
AlmaLinux-8
```

### 2. エクスポート

```bat
> wsl --export ディストリビューション名 書き出したいファイル名
```

* 例

```bat
> cd %HOMEPATH%
> mkdir %HOMEPATH%\wsl_export
> wsl --export AlmaLinux-8 %HOMEPATH%\wsl_export\alma_8.tar.gz
> dir wsl_export
2024/02/27  08:36    <DIR>          .
2024/02/27  08:35    <DIR>          ..
2024/02/27  08:36       269,455,360 alma_8.tar.gz
               1 個のファイル         269,455,360 バイト
               2 個のディレクトリ  378,183,249,920 バイトの空き領域
```

### 3. インポート

```bat
> wsl --import ディストリビューション名 インストール先パス　書き出したファイル名
```

* 例

```bat
> cd %HOMEPATH%
> mkdir wsl\alma_8_test
> wsl --import alma-8-test %HOMEPATH%\wsl\alma_8_test %HOMEPATH%\wsl_export\alma_8.tar.gz
インポート中です。この処理には数分かかることがあります。
この操作を正しく終了しました。
> wsl --list
Linux 用 Windows サブシステム ディストリビューション:
Ubuntu-20.04 (既定)
AlmaLinux-8
alma-8-test
```

* インポートしたディストリビューションの開き方は下記記事を参考
    * [WSLにUbuntu Server 22.04 LTSをインポートする](https://level69.net/archives/30266)

## おわりに

* WSLの簡単に環境作れるスマートなところ好き！

## 参考記事

* [WSL上のLinuxのバックアップ](https://www.aise.ics.saitama-u.ac.jp/~gotoh/HowToBackupLinuxOnWSL.html)
* [WSLにUbuntu Server 22.04 LTSをインポートする](https://level69.net/archives/30266)
YOLOWorldを手軽に使う　iOS用に変換する

# 好きな物体を設定できる
テキストで物体検出するクラスを設定できるYOLOWorldですが、
pipパッケージを使うと数行のコードで簡単に使えます。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/12507fae-9d82-d090-d69d-e8d36d8a3944.jpeg width=400>

### インストール

```bash
pip install ultralytics
```

```python
from ultralytics import YOLOWorld
model = YOLOWorld('yolov8l-world.pt')
```

### クラスを設定

```python
model.set_classes(["donuts"])
```

これでドーナツを検出するようになりました。

### 実行

```python
results = model.predict('donuts.jpg',save=True)
```

### Core MLに変換

しかも、カスタムクラスを設定した検出モデルをiOSやmacOS用にCore MLに変換できます。

```python
import torch
from ultralytics import YOLO 

with torch.no_grad():
    model = YOLO('yolov8s-world.pt')

    custom_classes = ["donuts"]
    model.set_classes(custom_classes)

    model.save("donuts_yolov8s.pt")

    model = YOLO("donuts_yolov8s.pt")

    model.export(format="coreml", nms=True)
```

これで、ドーナツ検出用のyolov8sのCore MLモデルが取得できます。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/7a29a168-b6ea-9dac-a74e-a5b6618d53a5.png width=400>

がんばってるねultralytics。

🐣
****
フリーランスエンジニアです。
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)
Vimを覚える【vimtutor Lesson 5】

# はじめに

前回の記事はこちらです。

https://qiita.com/kohki_takatama/items/1fe6d693bfcd90abf2a3

# Lesson 5.1

<font color="Salmon">`:! + シェルコマンド`で、外部コマンドを使えるよ！</font>ですね。 

例として、`:!ls`で、VimではなくLinuxのコマンドである`ls`コマンドを使用できるようです。

`touch` / `cd` / `mkdir` などを使えるのは良いですね！

ちなみに、`:`で始まるコマンドはすべて、`Enter`で終了する必要があるようです。
# Lesson 5.2

<font color="Salmon">`:w filename`で新規ファイルに保存ができるよ！</font>ですね。

ファイル名が存在する場合は`File exits`という警告が出ます。

`:w!`で強制すると、上書きができるようです。

# Lesson 5.3

<font color="Salmon">`v`と組み合わせることで、一部分だけを新規ファイルに保存できるよ！</font>ですね。

1. `v`：ビジュアルモードで範囲選択をします。
2. `:`を押し、コマンドモードに入ります（`:'<.'>`と表示されます）。
3. `w filename`で、選択した範囲をfilenameの新規ファイルとして保存します。
# Lesson 5.4

<font color="Salmon">`:r filename`で他のファイル内容を挿入できるよ！</font>ですね。

他のファイルだけでなく、出力結果を挿入することもできるようです。

例：`:r !ls`で`ls`の出力を挿入
# Lesson 5 修了！

おつかれさまでした！

# おわりに

Linuxコマンド（外部コマンド）との組み合わせはアツいですね！
テンション爆上げです。実際に使うかは・・・まだわかりませんが。

レッスンは残り2つです！！

次回記事

https://qiita.com/kohki_takatama/items/db39de072e8ad908cf7d
【ReactNative】WebViewのAPIのメソッドを確認してみた

ReactNative WebViewのAPIドキュメントを読んで、どのようなメソッドがあるかを確認しました。

https://github.com/react-native-webview/react-native-webview/blob/master/docs/Reference.md

## goForward() / goBack()
```tsx
goForward() / goBack()
```
ユーザーがウェブページ内で履歴を戻ったり進んだりするための関数です。`goForward()`は一つ前のページに、`goBack()`は一つ前のページに戻ります.

## reload()
```tsx
reload()
```
現在のページを再読み込みするための関数です。

## stopLoading()
```tsx
stopLoading()
```
現在のページの読み込みを停止するための関数です。

## injectJavaScript(str)
```tsx
injectJavaScript(str)
```
WebView内でJavaScriptを実行するための関数です。
引数には実行したいJavaScriptのコードを文字列で渡します。

## requestFocus()
```tsx
requestFocus()
```
WebViewにフォーカスを要求するための関数です。
TVアプリに取り組んでいる人にとっては良いみたいです。

## postMessage(str)
```tsx
postMessage(str)
```
WebViewにメッセージを送信するための関数です。
ウェブページとアプリ間での連携時に使用されます。

## clearFormData()
```tsx
clearFormData()
```
WebView内のフォームの自動補完ポップアップを削除するための関数です。主にAndroidで使用されます。

AndroidのWebViewのドキュメントを詳しく見ていきます。

https://developer.android.com/reference/android/webkit/WebView

>Removes the autocomplete popup from the currently focused form field, if present. Note this only affects the display of the autocomplete popup, it does not remove any saved form data from this WebView's store

>日本語訳）現在フォーカスされているフォームフィールドからオートコンプリートポップアップを削除します。これはオートコンプリートポップアップの表示にのみ影響し、この WebView のストアから保存されたフォームデータを削除するわけではないことに注意してください。

### 自動補完ポップアップ
オートコンプリートポップアップという言葉は、画像の赤枠の部分のパスワード入力したりする際にでてくる自動入力のポップアップのことを指します。（筆者は知らなかったです）
![スクリーンショット 2024-02-27 6.55.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799713/079e5f1c-d620-889c-17fe-9c4bda308b1c.png)
https://entre-salon.com/manual/autofill-android/

上記のポップアップの表示を削除する関数であることが理解できました。

## clearCache(bool)
```tsx
clearCache(bool)
```
WebViewのキャッシュをクリアするための関数です。

## clearHistory()
```tsx
clearHistory()
```
Androidのみの機能です。WebViewの内部の戻る/進むリストをクリアするための関数です。
アプリ内の履歴を削除する必要がある場合に使用されます。


## 最後に
他にも良い方法があれば、コメントいただけると大変うれしいです。
良かったと思ったら、いいねやTwitterのフォローよろしくお願いいたします！

https://sites.google.com/view/muranakar

個人でアプリを作成しているので、良かったら覗いてみてください！
Stackプログラミング言語を実行できるJSライブラリを作った

## 概要

こんにちは！
私がコミュニティで開発しているスタック指向型の強力なスクリプト言語「Stack」を、PHPみたいにHTMLに組み込んで動かせたら便利だと考えて、Webアセンブリ版Stackプログラミング言語を実行するJSライブラリを開発しました。

https://qiita.com/KajizukaTaichi/items/1c3e3ee08d102bfd576c

# コード紹介

```javascript
import init, { run_stack } from './pkg/web_stack.js';

init().then(() => {
    window.run_stack = run_stack;
    
    // ページの読み込みが完了したら実行する処理
    // class が stack である要素を全て取得
    const stackElements = document.getElementsByClassName("stack");

    // 各要素に対して処理を行う
    for (let i = 0; i < stackElements.length; i++) {
        const stackElement = stackElements[i];
        const code = stackElement.innerText.trim(); // 要素内のテキストを取得し、両端の空白を除去する
        const result = run_stack(code).output(); // Stack 言語のコードを実行する
        stackElement.innerHTML = result; // 結果を要素内に表示する
    }

});

```

JavaScriptからWebアセンブリ版Stackプログラミング言語を実行しています。

```html
<html>
    <body>
        
        <div class="stack">
            (<) (table) (>) concat concat print

                1 10 1 range (i) (
                    (<) (tr) (>) concat concat print
                
                    1 10 1 range (j) (
                        (<) (td) (>) concat concat print

                        i j mul print

                        (<) (/td) (>) concat concat print
                    ) for

                    (<) (/tr) (>) concat concat print
                ) for

            (<) (/table) (>) concat concat print
        </div>

        <script src="https://stack-community.github.io/stack.js" type="module"></script>
    </body>
</html>
             
```
`stack`クラスの中のStackプログラミング言語の掛け算表を出力するコードを実行して動的にHTMLで掛け算表を生成しています。

## 実行結果の確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952107/66579721-3490-7e3b-bada-1fa441586bf6.png)


これで、Webページ上でStackプログラミング言語を実行して動的にHTMLを生成できます。

## まとめ

この記事では、Webページ上でStackプログラミング言語を実行する方法を紹介しました。柔軟な構文と高い表現力を持つStackプログラミング言語を活用して、さまざまなアプリケーションを開発してみてください。
2024/2/27主にITとかセキュリティの記事

セレクト地域短信 企業HPの脆弱性に警鐘 注意喚起セミナーも開催(2/25)
https://ab.jcci.or.jp/article/94604/

セキュリティ対策普及へ10大脅威2024を公表 IPA(2/25)
https://ab.jcci.or.jp/article/94667/

【詐欺】ドコモのdカードが不正利用された!? →個人情報を盗む偽メールです(2/25)
https://ascii.jp/elem/000/004/185/4185983/?rss

サイバー防御「事前の対策強化を」
松原実穂子氏、千葉「正論」懇話会で講演(2/25)
https://www.sankei.com/article/20240225-2I46A664NFMOVN46BITBGDUTAQ/

共同作戦で壊滅したマルウェア「Qakbot」復活、米国は犯行グループを逮捕できず(2/25)
https://news.mynavi.jp/techplus/article/20240225-2885670/

悪意あるPythonパッケージを2つ発見、DLLサイドローディング技術悪用(2/25)
https://news.mynavi.jp/techplus/article/20240225-2889952/

情報セキュリティー分野の注目資格「情報処理安全確保支援士」とは？効率的な勉強法と試験対策、キャリア展望を解説(2/25)
https://news.yahoo.co.jp/articles/dd305a5a59a11f17bb57c15393702d5a14e788dc?source=rss

サイバー攻撃への悪用を確認、ファイルレスSSHツール「SSH-Snake」に注意を(2/25)
https://news.mynavi.jp/techplus/article/20240225-2889088/

「経済安保法案」的外れな東京新聞　日本大教授・小谷賢 新聞に喝！(2/25)
https://www.sankei.com/article/20240225-KRO55L4BKZNGJN6LEZQMFUEG6Y/

生成AIを利用したSCMとは？メリットとデメリット、業界の導入状況を徹底解説(2/25)
https://weel.co.jp/media/scm

マイナカード利用「認証アプリ」、個人の利用状況を国が一元管理のプライバシーリスク(2/26)
https://xtech.nikkei.com/atcl/nxt/column/18/00989/022000140/

高速無線LAN(2/26)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/031500132/021600025/

伊丹市がノーウエアランサム被害　システム委託先が感染(2/26)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/031800050/021600060/

GIGAで伸ばす情報活用能力、1人1台端末で学校に「変わり続ける」を実装(2/26)
https://xtech.nikkei.com/atcl/nxt/column/18/02740/020900001/
GPT-4の新たなライバル？ Claudeより賢いとウワサのMistral AIとは

# Bedrockに新たな仲間が登場！

AWSは先日、生成AIサービスAmazon BedrockにMistal AIのLLMを追加する予定があることを発表しました。

https://aws.amazon.com/jp/bedrock/mistral/


# そもそもMistral AIとは？

2023年4月にフランスで立ち上げられたAIベンチャーです。元DeepMind（Google系）や元Metaのメンバーらが共同創業しています。

https://mistral.ai/


# GPT-4に迫る賢さ？ 最新のLargeモデルとは

そんな話題の中、日本時間2/27（火）未明ごろに同社の最新モデル「Mistral Large」が発表されたようです。MMLUというベンチマークによると、なんとClaude 2を押さえてGPT-4に迫る第2位のスコアを叩き出しています。

https://mistral.ai/news/mistral-large/

![mistral-large-bar-plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/ca41a395-bbe8-31a1-6e9b-9ce45ff9dc00.png)
（出典：上記ブログ記事より）


# 公言されていないが日本語も普通に使えそう！

このMistral Largeモデル、すでに同社の提供するWebチャット「Le Chat」で無料で試すことができます。

https://chat.mistral.ai

公にプッシュされているのは欧米系の5言語への対応でしたが、試してみたところ普通に日本語でもスムーズに回答してくれました。（出力を見るとWebブラウジングによるRAGも裏で動いているようです）

![スクリーン ショット 2024-02-27 に 02.22.55 午前.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/182f9046-12b5-3a49-ca09-39655f9cb067.png)


# そしてAzureでも本日から使える？

https://azure.microsoft.com/en-us/blog/microsoft-and-mistral-ai-announce-new-partnership-to-accelerate-ai-innovation-and-introduce-mistral-large-first-on-azure/

アナウンスの早かったAWSより先に、Microsoft Azure上で本日からこのMistral Mediumモデルが利用可能となったようです。さすが動きが早いですね！
Azureの従量課金型LLMサービスと言えばAOAIのイメージでしたが、このモデルはもちろんOpenAI製ではないので「Azure AI」サービス上での対応と謳われています。

今日は遅いのでAzureのハンズオンまではやめておきますが、GPTやClaudeと違ってAWSとAzureの両プラットフォーム上でここまで高性能が期待されるLLMが双方ともで利用可能になるのは面白い展開ですね。

AWSのBedrockでも最新のLargeモデル含め、早くローンチされることを心待ちにしています🤩


# 追記：LargeはAWSに来るか、まだ分からないかも…？

これまで開発したモデルをオープンソースで公開していたMistral AIですが、今回の新モデルMistral Largeはクローズドな形になってしまったようです。

https://x.com/bindureddy/status/1762194125422743692?s=20

Xでも海外のAI関係者が嘆いており、イーロン・マスク氏も加わって議論が盛り上がっています。

https://x.com/elonmusk/status/1762217391633952953?s=20
【生成AI】Flutterプロジェクトの作成

### プロンプト
```
flutter でToDoアプリのプロジェクト作成する方法を記述して
```
---
### AIの回答
FlutterでToDoアプリのプロジェクトを作成する手順は以下の通りです：

1. **Flutter SDKのインストール**: まず、Flutter SDKをインストールします。Flutter SDKのインストール手順については、先ほどの回答に記載されている手順に従ってください。

2. **新しいFlutterプロジェクトの作成**:

    ターミナル（Windowsの場合はコマンドプロンプト）を開き、次のコマンドを実行して新しいFlutterプロジェクトを作成します。

    ```
    flutter create todo_app
    ```

    これにより、`todo_app` という名前の新しいFlutterプロジェクトが作成されます。`todo_app` はあなたが選んだプロジェクトの名前です。適切な名前を選択してください。

3. **プロジェクトディレクトリに移動**:

    プロジェクトが作成されたら、そのディレクトリに移動します。

    ```
    cd todo_app
    ```

4. **プロジェクトの開始**:

    プロジェクトディレクトリに移動したら、エディタ（お好みのテキストエディタ、Visual Studio Code、Android Studioなど）を開いて、Flutterプロジェクトを開始します。

5. **コードの追加**:

    ToDoアプリの機能を追加するために、`lib/main.dart` ファイルを編集します。このファイルにアプリのレイアウトやロジックを追加してください。具体的なコードの追加方法については、先ほど提供したToDoアプリの実装例を参考にしてください。

6. **実行**:

    アプリの開発が完了したら、プロジェクトのディレクトリで次のコマンドを実行してアプリを起動します。

    ```
    flutter run
    ```

    これにより、Flutterアプリが起動し、ToDoアプリがデバイスまたはエミュレータに表示されます。
これでFlutterでToDoアプリのプロジェクトが作成され、開発が始まります。必要に応じてコードを編集し、アプリの機能を追加してください。
---
### 実際にやってみる
SDKのインストールは済んでいるので1はスキップ。

##### 新しいFlutterプロジェクトの作成:
```
>flutter create todo_app
Creating project todo_app...
Resolving dependencies in todo_app... (1.3s)
Got dependencies in todo_app.
Wrote 129 files.

All done!
You can find general documentation for Flutter at: https://docs.flutter.dev/
Detailed API documentation is available at: https://api.flutter.dev/
If you prefer video documentation, consider: https://www.youtube.com/c/flutterdev

In order to run your application, type:

  $ cd todo_app
  $ flutter run

Your application code is in todo_app\lib\main.dart.
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1710277/d9e4f09c-25c6-f26d-385f-e55abfe342c4.png)

###### 実行
```
flutter run
Connected devices:
Windows (desktop) • windows •
windows-x64    • Microsoft Windows
[Version 10.0.22621.3155]
Chrome (web)      • chrome  •
web-javascript • Google Chrome
121.0.6167.189
Edge (web)        • edge    •
web-javascript • Microsoft Edge
122.0.2365.52
[1]: Windows (windows)
[2]: Chrome (chrome)
[3]: Edge (edge)
Please choose one (or "q" to quit): 2
Launching lib\main.dart on Chrome in debug mode...
Waiting for connection from debug service on Chrome...             23.3s
This app is linked to the debug service:
ws://127.0.0.1:50957/pcA4ZiNOVXc=/ws
Debug service listening on
ws://127.0.0.1:50957/pcA4ZiNOVXc=/ws


  To hot restart changes while running, press "r" or
"R".
For a more detailed help message, press "h". To quit,
press "q".

A Dart VM Service on Chrome is available at:
http://127.0.0.1:50957/pcA4ZiNOVXc=
The Flutter DevTools debugger and profiler on Chrome is
available at:
http://127.0.0.1:9101?uri=http://127.0.0.1:50957/pcA4ZiNOV
Xc=
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1710277/6ad1f9ee-64c5-744a-9886-f6199f73c166.png)
venvとjupyterを使用時、仮想環境内のモジュールをインポートできるようにする（ModuleNotFoundErrorの解決）

## 経緯
https://qiita.com/lilacs/items/acff5baa9b49af0586d0#%EF%BC%93%E4%BB%AE%E6%83%B3%E7%92%B0%E5%A2%83%E3%81%AE%E6%A7%8B%E7%AF%89

を参考に、JupyterLabの仮想環境上での作業ページを作ったが、ModuleNotFoundErrorが発生した。

まあいつものことなので、どうせJupyterに仮想環境内のモジュールへのパスが通っていないのだろうなとsys.pathを見てみると当たり。

毎回sys.path.appendをするのは面倒くさすぎるので、ちょっと手を加えてなんとかする。

（初めてのQiitaの記事作成です）

## 使用OS
windows11

## 作業手順
参考

https://blog.amedama.jp/entry/jupyter-ipy-kernel-startup-script

IPython Kernelのスタートアップスクリプトを利用する。

```Powershell:Powershell
 $ ipython profile create
 $ ipython locate
 /Users/username/.ipython
```

.ipython/profile_default/startup に、名前が数字 2 ケタから始まる Python スクリプトを入れると、カーネルの起動時にそれが呼び出されるようになる。

例えば、00-first.py を作って、以下のようにする。
```python:00-first.py
import sys
sys.path.append('.\\venv\\Lib\\site-packages')
```
わざと相対パスにすることで、どの仮想環境（カーネル）を起動しても、パスが通るようにしている。
ちなみに仮想環境を作るとき、環境名を統一してないと、もちろんこの方法は通用しないので注意。

## 余談
自分はまだ使ってないが、多分仮想環境はPoetryを使ったほうがいい。

参考

https://qiita.com/yokohama4580/items/dc6ba7259e99cad0dd65
ハッカソン：実例から見るイノベーションと成長の可能性

## ハッカソンとは
「ハッカソン」とは、「ハック」（技術的な解析や改良）と「マラソン」（長期間にわたる活動）を組み合わせた造語です。

「ハック」とは、システムやソフトウェアを分析し改善することを指します。

このイベントでは、短期間でチームを組んで、特定のテーマに関連するプロトタイプを開発することが主な目的です。

## ハッカソンの進め方
1. 社内ハッカソンのテーマを決める
2. ハッカソン実施前のセミナーを行う
3. 参加者をチーム分けする
4. 社内ハッカソンを実施する
5. 成果の発表・評価を行う

## 実例
直近、ハッカソンのイベントに参加させていただきました。
定義だけが聞いたことがあるが、実感できたのが今回はじめてです。
課題とチームのメンバーは事前にお知らせがなく、当日に課題とチームのメンバー初めて知りました。
どうなるのか不安とワクワクがわいてきました。

**成果**
・リマインダーツールWebアプリケーション
・PCとスマホでも利用可能

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3663796/83533c56-f4fd-6266-73da-3310995c3d70.png)

**・結論から言うと、何を作ったか？**
制限された時間以内で5人のチームでリマインダーツールを作りました！

＜できた機能＞
➊リマインダー作成/編集/処理済み
➋リマインダー優先順位設定
➌リマインダー内容のカテゴリー
➍リマインダー通知（設定された時間の10分前に通知）

**・チームのメンバーはどうやって、どんな役割を分けたか？**
各メンバーが担当仕事に経験があるため、最初にリーダー役割を選んで次々にエンジニア担当、テスト担当とBA担当の役割をすぐに決めました。

**・制限された時間以内でどうやってスムーズに商品を作れたか？**
課題が与えられたときに、できるだけ基本機能を迅速に完成させることが理想だと考えました。ただ、制限された時間内でどこまで進められるか不安もありました。また、メンバー間の認識のずれがあれば、期限までに成果物を完成させることが難しいとも感じていました。

しかし、最初からメンバーと共通の目標や実装のイメージを共有し合い、それを確認することができたおかげで、最終的には素晴らしい成果物を作り上げることができました。結果として、皆が満足できる良い商品ができ、それが何よりも大きな喜びです。

もちろん、作っている途中で、小さな喧嘩や意見の相違があったことも事実です。しかし、そのような時こそ、喧嘩の目的が何かを明確にし、どのようにして良い結果を得るかを考えることが大切です。お互いが理解できない部分や、追加機能の要望など、様々な見解がありましたが、それらを解決するために協力し合いました。

課題が与えられると、それぞれが実装したい機能やイメージがあります。しかし、重要なのはユーザーがその機能をどのように使用するか、その使いやすさやUIの分かりやすさです。そのために、プロジェクトの目的や内容を分析し、お互いが納得できる解決策を見つけることが重要だと思われます。

**・はじめてのハッカソンで何を学べたか？**
#チームワーク
#リーダーシップ

上記の2つが今回のハッカソンで本当に勉強になりました。
簡単に見えるがそう簡単ではないです。
制限された時間以内でもっとも納得できる決断をしないといけないので、ここで「リーダーシップシップ」がとても重要だと実感できました。
今回自分のチームに良いリーダーがいて、その素晴らしい姿から知識とマインドセットをいただきました。

以上です。

## 一緒に働く仲間を募集しています！
株式会社コネクター・ジャパンでは一緒に働いてくれる仲間を募集しています！

事業拡大に伴い、エンジニアを大募集しています。
興味のある方は下記リンクから弊社のことをぜひ知っていただき応募してもらえると嬉しいです。
▼会社について
https://www.wantedly.com/companies/cnctor/about
▼代表メッセージ
https://cnctor.jp/10years-anniversary/
▼応募はこちら
https://www.wantedly.com/companies/cnctor/projects
OpenAI APIをTypeScriptから実行するための備忘録

# 概要
昨年の大晦日にOpenAIのChatAI APIを利用して検証したいことを以下の記事にまとめました。そこで、早速検証してみようと思い立ちました。年明けから色々と検証してみており、まだ終わってはいませんが、現状の備忘録をまとめておこうと思います。

https://qiita.com/y-vectorfield/items/02734f8f6860d976ba10

# 検証1: TypeScriptで動作させたい

## 検証結果
以下のコマンドを実行すると環境構築が出来る。

:warning: 筆者はNode.jsのパッケージマネージャーとしてnpmを利用しています。

```bash
npm install --save-dev typescript && npm install openai
```

https://the2g.com/post/difference-between-npm-install

参考資料として以下の公式チュートリアルの内容が非常に役に立ちました。以前勉強のために購入した書籍は情報が古く、書籍内のコードをそのまま実行してもエラー終了してしまい、困っていた時に発見し、大変救われました。

https://github.com/openai/openai-node

# 検証2: Azure上のAPIのバージョンと共用したい

## 検証結果
社内版のChatAI APIはAzure版のそれとも独立した独自仕様の物でした。よってaxiosを用いてREST APIを叩くという方法が必要でした。

https://axios-http.com/ja/docs/intro

https://zenn.dev/yuki_tu/scraps/7dd1a6d1fd220d

# 検証3: 検証3: 5$でどれぐらいの期間使えるか

## 検証結果
全然無料分が減りません。結構な行数のコードを渡しても全然消費されず。。。無料クレジットは有効期間が3ヶ月であるため、トークンの節約のためにコメントを除外する処理を回してからAPIに渡していた部分を止めて実行していますが、全く減りません。。。プロンプトエンジニアリングの勉強のために、ドシドシAPIにリクエストを送って頑張って消化します。
【Jotai 】atomWithStorageを使うときの注意点(getOnInit: true しておこう)

jotaiという便利な状態管理のライブラリがあります。

https://jotai.org/

色々機能がありますが、ローカルストレージに値を永続化できる atomWithStorage という関数があります。useStateと同じように値の取得・設定ができるので、ブラウザローカルで永続化したい時に便利です。

jotai使う前は react-use の useLocalStorage を使ったりしてたので、atomWithStorage も同じ感覚で使えると思ってました。

使い始めてからしばらく経って、レンダリングの動作に違和感を覚えました。初回レンダリングが何か違う。

atomWithStorage の初期値がおかしい?
ローカルストレージに保存された値が読み込まれてない?

react-use の useLocalStorage では、ローカルストレージに値が保存してあれば、そちらが読み込まれて初期値となるのですが、 atomWithStorage では関数で指定した初期値を使ってまずレンダリングされ、その後ローカルストレージからロードされた値でレンダリングされてました。

useLocalStorage の動作の方が望ましいので、これは困りました。

ドキュメントを参照してみると、getOnInitというフラグで制御できるとあります。

https://jotai.org/docs/utilities/storage

> options (optional): an object with the following properties:
> 
>getOnInit (optional, by default false): A boolean value indicating whether to get item from storage on initialization. Note that in an SPA with getOnInit either not set or false you will always get the initial value instead of the stored value on initialization. If the stored value is preferred set getOnInit to true.

翻訳
> オプション（オプショナル）：以下のプロパティを持つオブジェクト：
> 
> getOnInit（オプショナル、デフォルト値はfalse）：初期化時にストレージからアイテムを取得するかどうかを示す真偽値。getOnInitが設定されていないかfalseの場合、初期化時には常に初期値が取得され、ストレージに保存された値は取得されないことに注意してください。ストレージに保存された値を優先する場合は、getOnInitをtrueに設定してください。


なるほど。ということで、getOnInit: true にしておくと、useLocalStorageと同じく、初期値をローカルストレージからロードする挙動になります。getOnInit: true の動作の方がしっくりくるので、忘れないようにしたいです。

同様の話が GitHub issue でありました。

https://github.com/pmndrs/jotai/issues/2240