OmniAICreator/Qiita-1.07M huggingface dataset:
AWS CLIを使用する際の証明書設定について - ローカル検証と本番環境の違い


## はじめに

ローカル環境でAWS CLIを使って検証作業をしようとしたら、HTTPSの証明書関連でエラーが発生して困ってしまいました。とりあえず一時的な回避方法は見つけたものの、「これって本当にこれでいいの？」という疑問が湧いてきたので、色々と調べてみることにしました。
実際には試せていなくて曖昧な理解のままですが、、のちのち検証するときのためにメモとして残しておきます。

## 開発環境でよくある問題

ローカルPCで開発作業をしていると、HTTPSの証明書検証でエラーが発生するケースがありました。気にしなくてもいいときもあるので、デフォルトの証明書を見る権限がないのではとかいろいろ考えましたが、よくわかりませんでした。
--no-verify-sslオプションを使えば一時的に回避できることがわかりました。でも、これって本番ではやってはいけないですよね。

## 考えられる対応方法

### 1. 開発環境での一時的な対応

- --no-verify-sslオプションの使用（とりあえずこれでテストしてみて動くことは確認）

ただ、これはあくまで開発時の「応急処置」的な対応だと思います。本番環境では使えないですよね。

### 2. WSLを使用した対応

いろいろ調べていたら、WSL環境を使う方法を見つけました。：

- WSLのUbuntu環境には必要な証明書が最初から入ってるみたい
- AWSCLIはインストール直後デフォルトになっていて、/etc/ssl/certs/ca-certificates.crtを見ていそう

## コンテナでのAWS SDK実装に向けて

実際にDockerコンテナでAWS SDKを使ったアプリケーションを動かすなどの場合、どうすればいいんでしょうか：

### 1. Dockerコンテナでの対応

- 証明書パッケージのインストールをDockerfileに書く（最初は空っぽの状態になっているはずで、これやらないとデフォルトの証明書すらありませんということになってしまいそう）
- AWS SDKのセットアップ（ここは普通にやればOK？）
- セキュリティ設定（ここが一番不安...デフォルトでいいのかな？）

## まとめ

正直、まだ完璧な理解には至っていないですが、開発環境では一時的な回避策を使いつつ、本番環境ではこんな対応すればできるのではという方法は見えてきました。曖昧な理解でツッコミどころ多いとは思いますが、ご指摘いただけると嬉しいです。

## 参考にした記事
認証キーの作成は[こちら](https://qiita.com/nonZy/items/c3c0116445883c088bb2)の記事を参考にさせていただきました。わかりやすくスムーズにできました。ありがとうございました。


「CERTIFICATE_VERIFY_FAILED」のエラーが出た際の対処方法は[こちら](https://qiita.com/fernet/items/971c70706a398f8d0228)の記事を参考にさせていただきました。これを見て「証明書を見に行く設定がどこかしらにあるはず、、、」とかいろいろ考えることができました。ありがとうございました。
Power Automate の試用版ライセンスを無効化してみた。

https://jpdynamicscrm.github.io/blog/powerplatform/How-to-block-free-and-trial-licenses/

Power Automate の無償ライセンスを維持したまま、試用版ライセンス (Power Automate Plan 2 Trial) だけを無効化してみたかったので、上記ページで案内されている方法をやってみた。

## 前提
試用版ライセンス (Power Automate Plan 2 Trial) とは、以下の赤枠部分（無料試用版を開始する）から取得可能なライセンスのこと。

![スクリーンショット 2025-02-18 010034.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629955/d0fffa17-66f3-4361-8813-bc8c2ed136f9.png)

「自分のライセンス」では、試用版ライセンスは Power Automate Plan 2 Trial として表示される。
![スクリーンショット 2025-02-18 010059.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629955/10d9bd94-df06-41b2-b124-402739f89a4a.png)

## ライセンスの種類
上記ブログによると、ライセンスには Internal ライセンスと Viral ライセンスの 2 つがあるとのこと。

- Internal ：Power Automate / Power Apps ポータルからユーザーが自身で取得する無償版・試用版ライセンス
- Viral： 管理者により付与される無償版・試用版ライセンス、および https://signup.microsoft.com/ からユーザーが自身で取得する無償版・試用版ライセンス

試用版ライセンスはポータルから取得しているので、「Internal」ではないかと思われる。`Ctrl + Alt + A` でアカウントに紐づいているライセンスを確認してみたところ、「FLOW_P2_TRIAL_INTERNAL」が有効（"isCurrent": true）になっているので、やはり「Internal」ではないかと思われる。

![スクリーンショット 2025-02-18 010500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629955/68a6e0d7-756d-4131-954e-57abe1db9236.png)

## 試用版ライセンスを無効化してみる
上記ブログによると、以下の2種類のコマンドで無償版、試用版のライセンスを無効化し、利用停止にできるとのこと。

```PowerShell
Remove-AllowedConsentPlans -Types "Internal"
Remove-AllowedConsentPlans -Types "Viral"
```

今回、無償版ライセンスは維持したいので、`Remove-AllowedConsentPlans -Types "Internal"` だけやってみた。

## 結果
無事に「自分のライセンス」から試用版ライセンス (Power Automate Plan 2 Trial) だけが消えた。

![スクリーンショット 2025-02-18 010140.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629955/d685464c-fa11-4e4d-896f-b487fa321271.png)

再度試用版を開始できるようにするためには、予め以下のコマンドを実行する必要がある。

```PowerShell
Add-AllowedConsentPlans -Types "Internal"
```

なお `Remove-AllowedConsentPlans` や `Add-AllowedConsentPlans` はテナント全体の設定を変更するものであり、すべてのユーザーに対して適用される。個別のユーザーを対象にするパラメーターは用意されていないようだ。

https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powerapps.administration.powershell/add-allowedconsentplans?view=pa-ps-latest

https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powerapps.administration.powershell/remove-allowedconsentplans
UbuntuでIBM Watson OpenScale APIに接続時のSSLエラーを解決する方法

Ubuntu環境でIBM Watson OpenScale APIに接続する際に、SSL証明書の検証エラーが発生することがあります。その際の解決策として、`REQUESTS_CA_BUNDLE` 環境変数を設定する方法について紹介します。

# エラーの発生

以下のコードを実行すると、`SSLCertVerificationError` が発生しました。

```python
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
from ibm_watson_openscale import APIClient

CLOUD_API_KEY = 'your_api_key_here'
authenticator = IAMAuthenticator(apikey=CLOUD_API_KEY)
client = APIClient(authenticator=authenticator)
print(client.version)
```

# 発生したエラー

> SSLCertVerificationError: HTTPSConnectionPool(host='api.aiopenscale.cloud.ibm.com', port=443):
Max retries exceeded with url: /openscale/... (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate')))

このエラーは、ローカルのSSL証明書が正しく設定されていないことが原因です。

# 解決策: `REQUESTS_CA_BUNDLE` の設定

Pythonの certifi パッケージを利用して、適切な証明書バンドルを指定します。

修正後のコード

```python
import certifi
import os

os.environ["REQUESTS_CA_BUNDLE"] = certifi.where()

from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
from ibm_watson_openscale import APIClient

CLOUD_API_KEY = 'your_api_key_here'
authenticator = IAMAuthenticator(apikey=CLOUD_API_KEY)
client = APIClient(authenticator=authenticator)
print(client.version)
```

# 解説

- `certifi.where()` を `REQUESTS_CA_BUNDLE` に設定することで、Pythonの `requests` ライブラリが適切な証明書を使用するようになります。

- `certifi` はPythonの標準的なSSL証明書バンドルを提供するライブラリです。

- `os.environ["REQUESTS_CA_BUNDLE"] = certifi.where()` を実行することで、環境変数を適切に設定できます。

# まとめ

IBM Watson OpenScale API を Ubuntu 環境で利用する際に `SSLCertVerificationError` が発生した場合、`certifi` を利用して `REQUESTS_CA_BUNDLE` を設定することで解決できます。

この方法を活用して、スムーズに Watson OpenScale API を利用しましょう！
H2 データベースのリカバリー手順

H2 データベースのリカバリー手順

1. エラーメッセージの確認
H2 はエラーメッセージに具体的な内容を出力します。例えば、次のようなエラーが発生している場合があります。

```
General error: "java.lang.RuntimeException: file corrupted in chunk xxxxxx, expected yyyyy but got zzzzz"
```

この場合、特定の **チャンク (chunk)** に破損が発生していることを示しています。

---

2. バックアップがある場合の復旧
### (1) 最新のバックアップからリストア
H2 では `.mv.db` または `.script` のバックアップを取得している場合、それを復元するのが最も安全な方法です。

```bash
mv mydb.mv.db mydb_corrupt.mv.db
cp mydb_backup.mv.db mydb.mv.db
```
これでバックアップから復元できます。

---

3. バックアップがない場合のリカバリー
バックアップがない場合、以下の方法を試してください。

### (1) H2 の RECOVER モードを使用
H2 には **"Recover" モード** があり、データベースを修復できる可能性があります。

```bash
java -cp h2*.jar org.h2.tools.Recover -dir ./recover -db mydb
```
このコマンドは `./recover` ディレクトリに `mydb.h2.sql` を出力します。

**新しいデータベースを作成する手順:**
```bash
java -cp h2*.jar org.h2.tools.RunScript -url jdbc:h2:./newdb -script ./recover/mydb.h2.sql
```
この手順で、新しいデータベース `newdb` にデータを復元できます。

---

### (2) H2 の SCRIPT ツールを使用
データベースのスクリプトエクスポートを試みる方法もあります。

```bash
java -cp h2*.jar org.h2.tools.Script -url jdbc:h2:file:./mydb -script backup.sql
```
これにより、`backup.sql` にデータをエクスポートできます。

エクスポートできた場合、次のように新しいデータベースへインポートします。

```bash
java -cp h2*.jar org.h2.tools.RunScript -url jdbc:h2:file:./newdb -script backup.sql
```

---

4. データベースの強制リカバリ
もし `Recover` や `Script` で復旧できない場合、`FORCE_REPAIR` を試すこともできます。

```sql
SET FORCE_REPAIR 1;
SHUTDOWN IMMEDIATELY;
```

その後、H2 データベースを再起動してみてください。

---

5. データベースを開く際のオプション
データベースを開く際に **"IFEXISTS=TRUE"** や **"RECOVER=1"** のオプションを追加すると、破損データのリカバリを試みることができます。

```bash
java -cp h2*.jar org.h2.tools.Shell -url jdbc:h2:file:./mydb;RECOVER=1
```

---

6. データベースの破損原因を調査
リカバリーが成功したら、破損の原因を特定して、再発防止策を考えましょう。

### (1) 異常終了や強制シャットダウン
- プロセスのクラッシュ、OS の強制終了などが原因になることが多い
- `SHUTDOWN COMPACT` を定期的に実行し、クリーンな終了を行う

### (2) H2 バージョンの不整合
- データベースを古いバージョンで開いたり、新しいバージョンで開いたりすると破損することがある
- 同じバージョンの H2 で動作させることを推奨

### (3) ディスクの問題
- SSD や HDD に物理的な障害が発生している場合、ファイルが破損する可能性がある
- `dmesg` コマンドや `chkdsk` / `fsck` でディスクの状態を確認

---

7. まとめ
| 手順 | 方法 |
|------|------|
| 1 | エラーメッセージを確認 |
| 2 | バックアップがある場合は復旧 |
| 3 | `Recover` コマンドでリカバリー |
| 4 | `Script` ツールで SQL を抽出 |
| 5 | `FORCE_REPAIR` を試す |
| 6 | `RECOVER=1` を指定して開く |
| 7 | 破損の原因を特定し、再発防止策を検討 |

これらの方法を試して、H2 データベースの復旧を行ってみてください！
RHEL9.5にzabbix7.2を構築(Apache編)

## はじめに
RHEL9.5にzabbix7.2を構築(MySQL編)の続きです。

https://qiita.com/sky_road1901/items/2b69129b7875f1c64450

## Apacheの導入
Apache編もYouTubeに投稿のあった動画を参考にさせて頂きました。
※リンクは一番最後に記載します。
外部公開などの予定はないためConfigファイルは基本デフォルトです。

### STEP1
dnfコマンドで必要なパッケージをインストール
``` 
sudo dnf install httpd php php-fpm php-mysqlnd php-ldap php-bcmath php-mbstring php-gd php-pdo php-xml
```
インストール完了後、systemctlで起動と起動後の状態確認
``` 
sudo systemctl start httpd php-fpm
```
``` 
sudo systemctl status httpd php-fpm
```
自動起動の登録
``` 
sudo systemctl enable httpd php-fpm
```

ここまで、エラー無く進めば構築完了です。

## Zabbixのインストール
記事作成中

## 参考にしたサイト
https://www.youtube.com/watch?v=0jNxqgxMKb0&t=565s
RHEL9.5にzabbix7.2を構築(MySQL編)

## はじめに
自宅ネットワーク・サーバ環境の構成見直しを行う中でGPUサーバも構築したしGPU監視もしたいなぁと思っていたところZabbix7.2でGPU監視ができるようになった事を思い出してzabbixのバージョンを上げようと調べたところ、RHEL9.5＋zabbix7.2の記事をあまり見かけなかったので備忘録かねて手順をまとめます。

基本的にはzabbix7.0と同等になると思いますので基本は公式ドキュメントを参照ください。

## 構成
※RedHatのdeveloper programに登録されていない方は是非登録を！
詳細は割愛します。
| 項目| 構成内容 |
|:-:  |:-:|
|OS | RedHat Enterprise Linux 9.5  |
|web|Apache|
|DB   |MySQL 8.4.4LTS  |
|zabbix(Server側)|zabbix7.2   |
|agent   | agent2  |

## 構築
今回この記事では詳細を割愛しますが、環境としてVmware Esxi7上に、RHEL9.5をインストール最低限の設定実施(項目が漏れていたら都度修正します)
・ホスト名
・IPアドレス設定
・NTP設定
・SELinuxの無効化
・firewallの設定(HTTP,HTTPSを開放すること)

## MySQLの導入
今回はYouTubeに投稿のあった動画を参考にさせて頂きました。
※リンクは一番最後に記載します。

### STEP1
まずはmysqlの公式サイトからRPM Bundleをダウンロード

https://dev.mysql.com/downloads/mysql/


ダウンロードしている間に、opensslのインストール
``` 
sudo dnf install perl openssl
```

ダウンロードが完了したら、RPM Bundleを解凍
``` 
tar -xf "ダウンロードしたファイル名"
```

rpmでインストール
``` 
sudo rpm -ivh --nodeps *.rpm
```
:::note warn
注意
この時MariaDBと依存関係でエラーが発生する場合があります。
その際はMariaDBをアンインストールしてください。
:::

インストール完了後、systemctlで状態確認と起動
``` 
sudo systemctl status mysqld
sudo systemctl start mysqld
```

### STEP2
MySQLのセットアップ
※MySQL 5.7以降、後段で記載の「mysql_secure_installation」が不要になったそうですが個人的におまじないとしていつも実施しています。
不要と思う方はrootユーザーのパスワード設定だけでも問題ないと思います(個人的意見)

/var/logディレクトリに移動
``` 
cd /var/log
```

mysqld.logを確認
``` 
sudo more mysqld.log | grep password
```
以下のような形で出力されると思いますのでパスワードをコピー
``` 
～ A temporary password is genlocalhost:パスワード
```

mysql_secure_installationで初期化
``` 
mysql_secure_installation
```
・ルートパスワードの設定
・テスト用DB、ゲストユーザーの初期化等
について質問形式で初期化するか聞かれますので質問内容を確認の上初期化を進めて下さい。

初期化完了後MySQLのrootユーザーでログインしてデータベースの確認
``` 
mysql -u root -p
```
コマンド実行後パスワードを聞かれるので、上記の初期化で設定したパスワードを入力
無事ログインできると以下のようになります
``` 
mysql>
```

Mysqlのバージョン確認とデータベースの確認
``` 
select version();
```
```
show databases();
```

それぞれ確認出来たらexitで抜けて下さい。
次はApachのインストール作業になります。

## Apachのインストール
https://qiita.com/sky_road1901/items/86282503ed811c078e80

## 参考にしたサイト
https://www.youtube.com/watch?v=esX-rAsPOdw
Gentoo on WSL2でPATH連携が動くようにする

# TL;DR

## 追記

単なる私の調査不足でした。この記事に書いた内容はまるっと不要です。正しい対応方法は以下をご参照のこと。

**WSL 内での Gentoo - Gentoo Wiki**
<https://wiki.gentoo.org/index.php?title=Gentoo_in_WSL/ja&oldid=1306568#Windows_.E3.83.97.E3.83.AD.E3.82.B0.E3.83.A9.E3.83.A0.E3.81.8C_PATH_.E3.81.AB.E3.81.AA.E3.81.84>

env-updateの稼働でPATHが上書きされるので、その前にWindowsから与えられたPATHを退避させてenv-update稼働後に退避させたPATHを接続、復活させる方法という方法を用いれば無理なく対応できるということのようです。

ついでに、処理後のPATHに重複が目についたので手元ではこうしています：

```bash:/etc/profileより抜粋
# WSLにより自動生成されたPATHを退避
WSLPATH="$PATH"

# Load environment settings from profile.env, which is created by
# env-update from the files in /etc/env.d
if [ -e /etc/profile.env ] ; then
        . /etc/profile.env
fi

# 退避したPATHを回復。重複に対処
PATH=$(echo "$PATH:$WSLPATH" | awk -v RS=: -v ORS=: '!a[$0]++')
export PATH=${PATH%:}

unset WSLPATH
```

**この記事は以上です。以下を読む必要はありません。**

# 以下、この記事を書いた際の記録

この記事では`appendWindowsPath`を通常通り使用することを断念し、以下のようにPowerShellを直呼びして対応しました。

```bash:/etc/profileの末尾に書き足す
# WindowsのPATHを取得して統合する関数
function append_windows_path() {
        # WindowsのシステムPATHを取得
        local sys_path=$(/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -Command '[System.Environment]::GetEnvironmentVariable("Path", "Machine")' | tr -d '\r\n')

        # WindowsのユーザーPATHを取得
        local user_path=$(/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -Command '[System.Environment]::GetEnvironmentVariable("Path", "User")' | tr -d '\r\n')

        # それぞれのPATHを統合
        local win_path="$sys_path;$user_path"

        # WindowsのPATH記法をBashの形式に変換
        local wsl_path=$(printf '%s' "$win_path" | sed 's/;/\n/g' | sed -e 's#\([A-Za-z]\):\\#\/mnt\/\L\1\/#g' -e 's#\\#\/#g' | tr '\n' ':' | sed 's/:$//')

        # WSLのPATHに追加。この際/usr/lib/wsl/libも追加する
        export PATH="$PATH:/usr/lib/wsl/lib:$wsl_path"
}

# wsl.confをチェックして関数を呼び出す
append_path_enabled="true"
if [ -f /etc/wsl.conf ]; then
   # appendWindowsPathの設定を取得
   append_path_enabled=$(grep -i '^\s*appendWindowsPath\s*=' /etc/wsl.conf | awk -F '=' '{print $2}' | tr -d ' ')
fi

# 設定がtrueの場合に関数を実行
if [ "$append_path_enabled" == "true" ]; then
   append_windows_path
fi
```

# どうしてこうなった？

WSL2の連携機能と`env-update`の食い合わせが悪いんです。  
PATHの設定が`/etc/env.d/50baselayout`にあり、こいつにうまく手を入れて`/etc/profile.env`上の`PATH`がそれまでの`PATH`を読み込むようにすれば起動時にWSL2から受け取る`PATH`と統合できると思われるのですが、書き換えても`env-update`は書かれた文言を**シングルクォーテーションで**書いてしまうんですよね。

一応、出てきた`/etc/profile.env`のシングルクォーテーションをダブルクオーテーションに書き換えるとWSL2が仕事していないわけではないことが理解できます。

とはいえ、ダブルクォーテーションで安定させようとして`env-update`のそういう設定を仮に発見したとして、`emerge`コマンド等が`source /etc/profile`を要求してくるので`;$PATH`が付いていると`$PATH`がどんどん長くなりそうです。……筋が悪い。

そこでCopilotに相談したところ出てきたのがこのスクリプトで、Windows上のPowerShellを直接呼び出して環境変数を取り出します。

当初はさっぱりWindowsのままのPATHを生のまま接続して空白まみれにしたり、空白を全部セミコロンに置き換えてしまって`Program;Files`ってなっていたりシステム環境変数しか読んでなくてユーザーインストールしたVSCodeが呼べなくて何のために手間かけとんじゃってなったり、Cドライブ前提の`sed`が出てきてたりしていましたが、都度修正させて最後はThink Deeper兄貴にブラッシュアップして頂きました。

# 納得いっていない点

本当はWSL2自身が持っているWindowsの`PATH`を呼び出してくる仕組みを直接実行したいのですが、所在がわからないのでできずにいます。

また、`appendWindowsPath`が`[interop]`以外に書かれていても認識してしまいます。ここをチェックする仕組みもCopilotに書かせたりしたのですが、結構長くなったしそもそも`/etc/wsl.conf`を書くのは自分自身なのでとりあえず後回しにしています。
kotlinのUnitTestはrunTestを使うといいかも

# runBlockingはrunTestに置き換えてもいいかも
- runTestは内部で、delayなどの明らかに処理が止まる処理を、自動でスキップしてくれるなどの処理が備わっている
そのため、テストの実行時間が短くなるなどのメリットがある
（例えばrunBlockingだと、テスト対象メソッドにdelayで10秒待つ処理がると、きっちり10秒待ってからじゃないと、次の処理に進めない。しかし、runTestは、delayで10秒待つ処理があった場合、10秒待ったことにして、次の処理を進めてくれるため、テストにかかる時間が短くなる）


# 参考サイト
https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/run-test.html

> On JVM and Native, this function behaves similarly to runBlocking, with the difference that the code that it runs will skip delays. This allows to use delay in tests without causing them to take more time than necessary. On JS, this function creates a Promise that executes the test body with the delay-skipping behavior.

JVM およびネイティブでは、この関数は と同様に動作しますが、実行するコードが遅延をスキップするという違いがあります。これにより、テストに必要以上の時間をかけずに、テストで遅延runBlockingを使用できます。JS では、この関数は、遅延スキップ動作でテスト本体を実行する を作成します。Promise
#0050（2024/02/17）ターミナルで役に立つショートカットキー一覧

# ターミナルで役に立つショートカットキー一覧

ターミナル（シェル）での作業効率を向上させるためのショートカットキーを以下にまとめます。  
これらのショートカットは、Bash、Zsh などの一般的なシェルで利用可能です。

| ショートカット       | 説明                                           |
|--------------------|----------------------------------------------|
| **Ctrl + A**       | カーソルを行の先頭へ移動                       |
| **Ctrl + E**       | カーソルを行の末尾へ移動                       |
| **Ctrl + U**       | カーソル位置から行の先頭まで削除               |
| **Ctrl + K**       | カーソル位置から行の末尾まで削除               |
| **Ctrl + W**       | カーソル位置の前の単語を削除                    |
| **Ctrl + Y**       | 最後に削除したテキストを貼り付け               |
| **Ctrl + L**       | 画面をクリア（Clear Screen）                   |
| **Ctrl + C**       | 現在のコマンドを中断／キャンセル                |
| **Ctrl + D**       | EOF（End Of File）を送信（シェル終了などに利用） |
| **Ctrl + Z**       | 現在のプロセスを一時停止（バックグラウンドへ）   |
| **Ctrl + R**       | コマンド履歴を逆方向に検索                     |
| **Alt(Option) + B**        | カーソルを前の単語の先頭へ移動                  |
| **Alt(Option) + F**        | カーソルを次の単語の末尾へ移動                  |
| **Alt(Option) + D**        | カーソル位置の後ろの単語を削除                  |
SwiftUIで作る(疑似)ループピッカー



タイマーアプリを作るときに0から9までの数字を選択できる、かつ、0の前が9で9の次が0とループするPickerを作りました。
割とシンプルできれいに書けたので実際のアプリに使っているコードそのままですがサンプルとして残しておきます。

```swift
import SwiftUI

struct DigitPicker: View {
    private let label: String
    private let range: [Int]
    @Binding private var selection: Int
    @State private var innerSelection: Int = 0
    private let loop = 100
    
    init(_ label: String, _ range: [Int], _ selection: Binding<Int>) {
        self.label = label
        self.range = range
        self._selection = selection
    }
    
    var body: some View {
        Picker(label, selection: $innerSelection) {
            ForEach(0..<(range.count * loop), id: \.self) { i in
                let value = range[i % range.count]
                Text("\(value)").tag(i)
            }
        }
        .pickerStyle(.wheel)
        .labelsHidden()
        .frame(minWidth: 30, maxWidth: 30, minHeight: 50, maxHeight: 50)
        .clipped()
        .onAppear() {
            innerSelection = selection + (range.count * loop / 2)
        }
        .onChange(of: innerSelection) {_, _ in
            selection = innerSelection % range.count
        }
    }  
}
```

簡単に解説しておくと
-
* loop回繰り返して0から9までの選択肢を用意
* 初期描画時に同じ値を表す真ん中の選択肢に選択を変更
* onChangeで選択肢から実際の数字(0から9)に変換
上記をすることで疑似的にループを実現しています。
疑似なのでひたすらピッカーを回し続ければ端でループは途切れますが、実用上は問題ないと割り切った作りになってます。

実際の動作は
-
ComposeTimerで確認できます。
無料アプリなので良かったらダウンロードして挙動を確かめてみてください。
https://apps.apple.com/jp/app/composetimer/id6740627031

アプリ起動後に右上のプラスから新規タイムラインを作成、タイムライン編集画面でパートのプラスから開くパート編集画面の項目「時間」でDigitPickerを6つ並べてパートの所要時間を入力できるようにしています。

![所要時間.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58231/63025762-dd8a-4a86-ae4b-d65326801dfd.png)
【Ontap】security login role config のオプション（個人的によく使用するもの）

ローカルアカウントのパスワードポリシーを設定したい場合に使用する"security login role config"について、個人的によく使用するオプションまとめ。

※詳細は下記リンク先参照。
https://docs.netapp.com/us-en/ontap-cli/security-login-role-config-show.html#description

<<<基本のコマンド>>>
設定確認
```security login role config show```

設定変更
```security login role config modify```

<<<オプション>>>
最低文字数
```-passwd-minlength```

世代数
```-disallowed-reuse```

有効期限(日数)
```-passwd-expiry-time```

最低英小文字数
```-passwd-min-lowercase-chars```

最低英大文字数
```-passwd-min-uppercase-chars```

最低数字数
```-passwd-min-digits```

最低記号数
```-passwd-min-special-chars```

<<<コマンド実行例>>>
```security login role config show -fields passwd-minlength,disallowed-reuse```

```security login role config modify -passwd-expiry-time 365 -passwd-min-lowercase-chars 1```
atcoder_水色精進記録2

# Atcoder水色精進記録
ABC216
F - Max Sum Counting
https://atcoder.jp/contests/abc216/tasks/abc216_f

# アルゴリズム・データ構造
DP

# 考察
条件の左辺が選択したAのmax
→sortすると簡単にできそう。
sortしたAを小さい順に考えると、そのインデックス以下のBしか考えなくてよくなる。

条件のうへんが選択したBの合計値
→累積和が使える？→途中のインデックスを使わないことがあるので累積和は使えない。

一つずつ使う使わないを考える？
→全探索は最大2\*\*5000
→DPを検討

保持しておかないといけない情報は？
→それまでの組み合わせの数、現在までの使用するBの合計MAX5000\*5000
→合計値が大きすぎるため削れる部分を考える。
→Bの合計値が現在の最大のAを超える場合は不要(AのMAXは5000)
→現在までの合計の状態は0-5000でOK


計算量
Aのソート　NlogN
dp N*N

# 提出
https://atcoder.jp/contests/abc216/submissions/62875082

# 感想
DPについて慣れてきた。
リファラとは何か

# リファラとは
元居たページのこと。
どのページから遷移してきたのかを表す情報のこと。

 # どんなときに使うのか
 web広告においてよく使われる言葉。
 どのページから広告のリンク先に来たのかを知る時に重要な情報となる。

 あるページからリンクを押したときのみ入る情報で、
 お気に入りからページに移動した場合は入らない。
いくらでも改ざん可能。

# ノーリファラ
リファラがないとき。
お気に入りからアクセスしたらリファラはない。
AI最新論文をAI自身に解説させてみた話

# はじめに
日々公開されるaiの最新論文、キャッチアップできていますか？

忙しい毎日の中で、「この論文、読まなきゃ…」 と思いながら、つい後回しにしてしまうことってありませんか？
最新の研究を追いかけたいけれど、英語を解読したり、数式を理解したりするのに時間がかかる。
結局、読む時間が取れずに気づけば新しい論文がどんどん溜まっていく…。

私自身そういう課題があったのでなんとかしたいと思い、「論文を読む」ではなく「論文を聞く」 という新しいインプット方法を試してみましたので共有の記事です。
そこで今回は、AIを活用して論文からPodcastを作成し要点だけを聞くという方法を試してみました！

# とりあえず、作ってみる

まず、AIに論文を投げて会話形式のPodcastを作ってもらうことから始めました。
テーマとなる論文には以下のものを使わせていただきました
[A synthetic data approach for domain generalization of NLI models](https://arxiv.org/abs/2402.12368)

作り方はGPT-4oを使って台本を生成し、それをOpenAIのTTS（Text-to-Speech）で読み上げるというシンプルな仕組みです。

ただ、最初の試作品は要約されすぎてしまう問題が発生しました。
GPT-4oの出力には文字数制限があるため、論文の要点を詰め込みすぎてあまりにもあっさりしすぎた台本になってしまったんです。
たとえばこんな感じ👇

🎧 初回試作の音声
https://res.cloudinary.com/dlwrzof1l/video/upload/v1739633054/hn0jds09ula41x3etwdf.mp3

聞いてもらうと分かると思いますが、要約されすぎて深い理論の理解までできません

そこで、論文の内容をもっとしっかり伝えるために、数ページずつ分割してAIに投げる方式に変更してみました。すると要約の精度が改善され、適度な情報量の台本が生成できるようになりました。

最終的に完成したPodcastがこちら👇

🎧 最終版の音声
https://res.cloudinary.com/dlwrzof1l/video/upload/v1739633063/wp3fvdlw1jnfhxdigsxr.mp3

実際に家事しながら聞いてみたんですが、aiが噛み砕いて話してくれるのでとても理解がしやすいように思いました。（これ毎日聴いてれば論文のキャッチアップをサボっているという罪悪感からも解放されるかも。。）

# あなたも聴いて感想聞かせて欲しいです！

実際に作ってみて、「意外と便利かも？」と思ったので、サービス化しようかなと考えました
とはいえ、いきなりアプリなど作るのも大げさなので、興味がある人向けに1週間試しに毎日配信して聞いてもらうことにしました。
以下のフォームから登録してもらうと、次の日から一週間毎日1本ずつ、メールでAI論文のPodcastを送ります。

📩 [登録フォーム](https://forms.gle/tAV3txDjUGkigRLe6)

あと、AIによる論文の要約だけじゃなく、「こういう内容なら毎日聞きたいかも」 みたいなものがあれば、それも知りたいので、ぜひ教えてもらえたら嬉しいです。
リクエストが多かったら、そのテーマでもPodcastを作ってみようと思います。リクエストは以下のフォームかコメント欄までお願いします！

📝 [リクエストもこちら](https://forms.gle/tAV3txDjUGkigRLe6)

同じような悩みを持ってる人がいたら、気軽に試してもらえたらうれしいです！


# 最後に

今回、AIを使って論文を音声化してみたら、思ったよりも気軽に情報をキャッチアップできることに気づきました。
まだ試行錯誤の段階だけど、「論文を読むのが大変」 という課題を少しでも解決できたらいいなと思っています。

とりあえず1週間の試験配信をやってみるので、「ちょっと気になるかも」 くらいの気持ちで試してもらえたら嬉しいです。
もし聞いてみて「もっとこうしたら良さそう」とか「こんな内容のPodcastもほしい」と思ったら、コメントにもぜひ気軽にフィードバックをもらえたら！

それでは、興味のある方はぜひ試してみてください。
【Mac】lsコマンドの結果をシンタックスハイライトする方法

`eza`を使用すると`ls`の結果をシンタックスハイライトできます。

以下のコマンドでインストールできます。

```terminal
brew install eza
```

https://github.com/eza-community/eza/blob/main/INSTALL.md

`eza`を使用すると出力に

 ![screen-shot-39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/f3cc9d75-02aa-4c55-8c4e-6a2199c1b3ef.png)
type-challenges解いてみた 初級 14-First of Array編


# 問題

````md

  配列`T`を受け取り、その最初のプロパティの型を返す`First<T>`を実装します。

  例えば：

```ts
  type arr1 = ['a', 'b', 'c']
  type arr2 = [3, 2, 1]

  type head1 = First<arr1> // expected to be 'a'
  type head2 = First<arr2> // expected to be 3

  type cases = [
  Expect<Equal<First<[3, 2, 1]>, 3>>,
  Expect<Equal<First<[() => 123, { a: string }]>, () => 123>>,
  Expect<Equal<First<[]>, never>>,
  Expect<Equal<First<[undefined]>, undefined>>,
]
```

````

配列型を受け取り、最初の要素の型を返す型を実装する問題です。






















## 回答

```ts
type First<T extends any[]> = T extends [infer A, ...infer rest] ? A : never
```

実は最初思いついたのは以下の回答だったのですが、他の方が挙げていた上の回答がとても綺麗だったのでこちらを回答として解説していきたいと思います。(下記の回答でも一応テストは通過できます)

```ts
type First<T extends any[]> = T extends [] ? never : T[0]
```

### 解説

- `infer`
inferは一言で説明するのが難しいのですが、`extends`の右辺に置くことができる、型を推論する演算子です。
今回の`infer A`というのは、Tを`[A, ...]`というAを最初の要素にした配列型と推論できれば`A`を、できなければ`never`を返すという書き方です。


なんでこの`infer`を使った解き方が優れているのかというと、これ最初の要素の型以外もすごく楽に指定できるんですよね。

```ts
type Last<T extends any[]> = T extends [...infer rest, infer A] ? A : never
```

こうすると最後の要素を指定できますし、

```ts
type Second<T extends any[]> = T extends [unknown, infer A, ...infer rest] ? A : never
```

こうすれば二番目の要素、みたいな感じで色々なパターンを同じ方法で解けます。すごい。

## リンク

https://github.com/type-challenges/type-challenges/blob/main/questions/00014-easy-first/README.ja.md
[Bun]実行時に `Cannot find module *-darwin-x64` というエラーが表示される  

# はじめに
bun を使って Vite で環境構築した際に、 title のエラーが発生したので解消法をまとめておきます

# 問題
Bun を使って Vite や Biome などの CLI を使おうとすると、ネイティブモジュールが見つけられないというエラーが発生する

```bash
bun run vite

Error: Cannot find module @rollup/rollup-darwin-x64. npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). Please try `npm i` again after removing both package-lock.json and node_modules directory.
```

# 解決方法
`--bun`フラグを付与する

```
bun run --bun vite
```

Bunは独自のJavaScriptエンジンを使用しているらしく、Node.jsとネイティブモジュールの扱い方が異なるようです
`--bun` フラグを使用する事で、Bunの独自実装を使用することを指定することができエラーを回避できるようです

# 参考
https://github.com/oven-sh/bun/issues/11511
https://bun.sh/docs/cli/run#bun
あなた = !あなた あなたは誰？論理否定boolean

    $ohayou = !$ohayou

こんばんは！

そんな訳はない。

でもboolean型の!trueはfalseになるんだ！ 

これを見た時、

凄い新鮮だった。
trueとfalseは評価でしか利用してこなかった。


だからtrueはDBに保存されたデータであり、
データのtrueが否定された時に、反転してfalseになる？？！
とおおぉと驚いたのだ。


自分の中で、trueをfalseに変換する時は下記をイメージしていた。

    if($A = true){
        $A = false
    }else{
        $A = true
    }

まさか

    $A = !$A

これだけで良いなんて思いもしなかった。
trueの反対がfalseと認識されるのが新鮮だった。

ということで調べてみた。

## 古典論理の基本的な挙動

プログラミング言語はtrueかfalseのどちらかだけをとるという論理体系を基本ルールとしている。

Cなどの言語では整数値をそのままブールとして解釈する歴史的理由があり

0をfalse
それ以外の値をtrue

というルールで評価する。


## PHPのブール値以外の値が否定された時のルール

PHPではboolean型以外の型でも!演算子で評価する時に、自動的にtrueかfalseに変換される。

ifで評価した時もtrueかfalseに変換されている。

これを型の自動変換、型の強制（type juggling）という。

**falseとなる値は以下**

- false
- 整数0
- 文字列"0"
- 空文字""
- 空の配列array()
- NULL

上記の内容以外はtrueとなる。

## ==と===の違い

==　は等価演算子
型変換しながら比較する。

=== は厳密比較演算子
型も含めて比較する。

これを用いると

    true == 1 

これは同等とみなす。

    true === 1

これは型が違うのでfalse

となるようだ。

## DBにおける真偽値の保存はデータ

DB上でboolean型で格納した場合は下記で保持される。

trueは内部的には1かt
falseは0かf

この段階ではプログラム上の真偽評価とは別物。

この値をPHPなどで取り出す時に変数にtrueというブール値がセットされるらしい。


## 結局!trueがなぜfalseなのか
遠回りしたが

なぜ!trueでfalseになるのか。

これは論理否定演算子が

**そう変えるものだ**
と定義されているから。

という結果だった。
ユニオン型の使い方（Typescript）

Typescriptの学習を進める中でユニオン型って面白いなと思ったので学習した内容についてまとめてみようと思います

## ユニオン型について
"|"を使って区切ることで複数の型を適用できます。

具体例としては下記のような感じです。
```
let id: number | string;  //number型とString型のユニオン型

id = 10; //number型は代入可
id = '10'; //string型は代入可
id = true; //boolean型は代入不可
```
ちなみにユニオン型を形成する型のことを「メンバー」と呼ぶそうです。

## ユニオン型の柔軟性
また、ユニオン型はリテラル型と組み合わせることでより独自性のある柔軟な型を定義することが出来ます。

ちなみにリテラル型というのは、変数の値を特定の文字列や数値に限定できるといった型仕様になります。

具体例としては下記のような感じです。
```
let dayOfTheWeek: '日' | '月' | '火' | '水' | '木' | '金' | '土';

dayOfTheWeek = '月'; //メンバーに含まれる文字列なので代入可能
dayOfTheWeek = '31'; //代入不可
```

上記のように、ユニオン型とリテラル型を組み合わせることで代入可能な値を特定の文字列や数値に限定することが出来るということですね。

以上
React の useActionState を TypeScript で安全に使う方法

React と TypeScript での型安全な状態管理と API 呼び出し
React と TypeScript を組み合わせて開発を行う際、型エラーを防ぐことは非常に重要です。​型エラーが存在すると、ESLint が警告を表示し、開発体験が損なわれることがあります。​この記事では、useActionState フックを使用して、ログインやサインアップ処理を型安全に実装する方法を具体例とともに解説します。​

## 1. useActionState の基本概念
useActionState は、状態（state）、アクション関数（action）、および処理中かどうかを示す pending 状態を一括して管理できるカスタムフックです。以下のように使用します。​

```typescript
const [state, action, pending] = useActionState(login, {
  success: false,
  errors: {} as ErrorResponse,
});
```
ここで、

login：​API 呼び出しなどの非同期処理を実装した関数​
初期状態：​success が false で、errors が空の ErrorResponse 型のオブジェクト​
を指定しています。​これにより、状態管理と処理中のフラグ管理を同時に行うことが可能となります。​

補足：useActionState の第二引数は、state の初期値を設定するためのものです。

## 2. サインアップ処理の型定義例
以下に、サインアップ処理に使用する状態の型定義と、実際の処理関数の実装例を示します。

状態の型定義（page.tsx など）

```typescript
interface SignupFormState {
  success: boolean;
  errors?: {
    name?: string[];
    email?: string[];
    password?: string[];
    general?: string[];
  };
}
```
サインアップ処理の実装（action.ts）

```typescript
export async function signup(
  _state: SignupFormState,
  formData: FormData
): Promise<SignupFormState> {
  // API 呼び出しの実装例
  // ... 実際の処理内容
  return {
    success: true,
    // エラーがあればエラーメッセージも返す
  };
}
```
### 型安全な状態管理
SignupFormState インターフェースを定義することで、サインアップ処理に必要な状態の構造を明確にし、TypeScript による型チェックを活用して、期待される形で状態を更新できます。​

### Promise の戻り値の型指定
signup 関数では、API 呼び出しの結果として SignupFormState 型のオブジェクトを返すようにしています。​これにより、useActionState を使用する側も、結果を型安全に取り扱うことが可能となります。​

補足：プロミス（Promise）とは、JavaScript における非同期処理の結果を表現するオブジェクトです。

## 3. useActionState を用いた実装例
サインアップ画面での useActionState の使用例を以下に示します。

```typescript
// page.tsx
import { signup } from './action';

const [state, action, pending] = useActionState(signup, {
  success: false,
  errors: {} as SignupFormState['errors'],
});
```
// フォーム送信時に action を呼ぶことで、API 呼び出しと状態更新を同時に行う
```tsx
async function handleSubmit(formData: FormData) {
  await action(formData);
}
```
この実装のメリット
型チェックの強化：​初期状態の型と、signup 関数の戻り値の型が一致するように定義しているため、意図しない型エラーを防ぐことができます。​

シンプルな記述：​useActionState の返り値を分割代入（[state, action, pending]）することで、各状態を明確にし、後続の処理をシンプルに記述できます。​

## 4. 型エラーが発生するケースとその対策
初期状態の型指定が不十分な場合、TypeScript が適切な型を推論できず、エラーが発生する可能性があります。

エラーの例

```typescript
const [user, setUser] = useActionState(login, {
  success: false,
  errors: {}, // 型が明示されていないためエラーの可能性
});
```
対策
明示的な型指定を行う

初期状態で errors の型を明確にするために、型アサーションやジェネリクスを使用します。​

*補足：型アサーションとは、TypeScript において変数や式の型を、開発者が明示的に指定する機能です。​実行時の値自体は変わりませんが、コンパイラに対して「この値はこの型として扱ってほしい」という指示を与えるために使われます。​

```typescript
const [user, setUser, pending] = useActionState(login, {
  success: false,
  errors: {} as ErrorResponse,
});
```
### ジェネリクスの活用

useActionState を定義する際にジェネリクスを使用している場合、関数側で初期値の型を指定することで、返り値も正しく型推論されます。​

*補足：ジェネリクスは、関数やクラス、インターフェースなどで「型」をパラメータ化する仕組みのことです。
頻出するけど書き替えたくなる的な奴

## 継続条件
毎回`size()`関数を召喚。とてもよく見掛ける
```c++
for(int a=0;a<A.size();a++);
```
```c++:書き替え
for(int a=0,b=A.size();a<b;a++);
```
逆方向からで良いなら以下のように
```c++
for(int a=A.size();a;)--a;
```
## 分岐頻度の最適化
いわゆる`if else`構文において`else`方面へ分岐する処理は低頻度である方が良い。以下は最悪の一例。
```c
for(int a=0;a<9;a++)
	if(a==0);
	else;
```
上記の反復処理において`if`(真)方面へは1回ぽっきり、残り全て`else`(偽)方面へ分岐する。分岐し過ぎである。以下のように逆の方が高速になりやすい。
```c:書き替え
for(int a=0;a<9;a++)
	if(a);
	else;
```
三項演算の場合も同様
```c
for(int a=0;a<9;a++)a==0?1:0;
```
```c:書き替え
for(int a=0;a<9;a++)a?0:1;
```
## 不要分岐排除
`if`(真)へ進んだら、それより後の処理をしない事が確定している場合、`else`は不要
```c
int f(int a,int b){
	if(a<b)return a;
	else if(a>b)return b;
	else return 0;
}
```
```c:書き替え
int f(int a,int b){
	if(a<b)return a;
	if(a>b)return b;
	return 0;
}
```
## 深い所は近道
深い階層の値をそのまま読み書きするのは重労働
```js
let a={a:{a:{a:9,b;[]}}}, b=0;
while(a.a.a.a>b)a.a.a.b[b]=b++;
```
```js:書き替え
let a={a:{a:{a:9,b;[]}}}, b=0, c=a.a.a.a, d=a.a.a.b;
while(c>b)d[b]=b++;
```
浅くても値を写した別変数を読み書きするのが良い
## 近道2
closureにおいても外側のscopeの変数はlocal変数に写して更新
```js
let f=function(){
	var a=0;
	return function(b){for(;b;)a+=b--;return a}
}()
```
```js:書き替え
let f=function(){
	var a=0;
	return function(b){for(var c=a;b;)c+=b--;return a=c}
}()
```
## 近道3
`class`のmember変数に対して過剰読み書きするのも考えものである。
```c++
class C{
private:
	int *mA, mP, mEnd;
public:
	C(int n){mA=new int[mEnd=n];}
	~C(){delete[]mA;}
	//手抜き
	void set(int n){
		for(mP=0;mP<mEnd;)mA[mP++]=n;
	}
	//改善
	void Set(int n){
		int P=0, *A=mA, E=mEnd;
		for(;P<E;)A[P++]=n;mP=P;
	}
};
```
## if(変数!=0)
これは加減算の例だが、他にも応用できる例は多い。
```js
let a=Math.random()*2, b=[a, a+a|0, a*a|0], c=0;
if(b[0]!=0)c++;
if(b[1]!=0)c++;
if(b[2]!=0)c++;
```
```js:書き替え
let a=Math.random()*2, b=[a, a+a|0, a*a|0], c=3-!b[0]-!b[1]-!b[2];
```
変数が数値限定であれば `!=0` はもはや不要。
```js
let a=Math.random()*7&7,b=new Date,c=b;
if(a!=0)for(;a;)b+=a--;
else c+=b;
```
```js:書き替え
let a=Math.random()*7&7,b=new Date,c=b;
if(a)for(;a;)b+=a--;
else c+=b;
```
## if(変数==0)
前述の`if(変数!=0)`と似たようなものである。
```js
let a=Math.random()*2, b=[a, a+a|0, a*a|0], c=0;
if(b[0]==0)c++;
if(b[1]==0)c++;
if(b[2]==0)c++;
```
```js:書き替え
let a=Math.random()*2, b=[a, a+a|0, a*a|0], c=!b[0]+!b[1]+!b[2];
```
## do while
継続条件の中に必須処理を埋め込む。言語にもよる。
```c
do A[a++]=b++;while(b<c);
```
```c:書き替え
while(A[a++]=b++,b<c);
```
## 蛇足
compilerの性能や実行環境が良ければ気にするほどの差は出ません。
【MySQL】NULLを最後にした並び順にしたい

## 背景
値にNULLを含むレコードを並び替える時、結果の最後にNULLを出力したいケースがありました。
`ORDER BY xxx IS NULL ASC`を使えばいい、と思っていたらうまくいかずハマってしまったので、反省として記します。

## 例
### 下記のテーブルを例に考えてみます。
- 複数の飲食店でスマホから注文、決済ができるシステムを導入している。
- 利用者が注文、決済を実行すると、注文情報としてオーダーテーブル(Orders)に注文先の店舗ID(store_id)と決済種別(payment_type)が登録される。
- スマホでの注文時、非対面の決済(クレジットカード決済、QRコード決済)の場合は対応する数値が登録される。現金払いの場合はNULLが登録される。

| id | store_id | payment_type |
|-----------:|------------:|------------:|
| 1    | 3     | 1      |
| 2    | 1     | null   |
| 3    | 1     | 3      |
| 4    | 1     | 2      |
| 5    | 1     | 1      |
| 6    | 2     | null   |
| 7    | 2     | 2      |
| 8    | 2     | 1      |

### 要求事項
- 複数の飲食店から、決済種別を含めた注文情報を出力したいという要望があった。
- 決済種別の並び順は固定したい。

### 要求事項を満たす出力結果
- 下記のように、`store_id`の昇順、`payment_type`の昇順としたい。
- 現地決済を意味する`NULL`が存在する場合、各店舗の最後に出力したい。

| store_id | payment_type |
|---------:|------------:|
| 1       | 1          |
| 1       | 2          |
| 1       | 3          |
| 1       | null       |
| 2       | 1          |
| 2       | 2          |
| 2       | null       |
| 3       | 1          |

## ソートでNULLを最後に並べたい
`store_id`の昇順、`payment_type`の昇順としたいので、それぞれを`ORDER BY`句に指定します。

```sql
SELECT
  store_id, payment_type
FROM
  Orders
ORDER BY
  store_id ASC,
  payment_type ASC;
```

しかし、`payment_type ASC`と指定した場合、`NULL`は最小値とみなされ各店舗の**最初**に並びます。
下記の要求事項を満たしません。
> 現地決済を意味する`NULL`が存在する場合、各店舗の最後に出力したい。

| store_id | payment_type |
|---------:|------------:|
| 1       | null       |
| 1       | 1          |
| 1       | 2          |
| 1       | 3          |
| 2       | null       |
| 2       | 1          |
| 2       | 2          |
| 3       | 1          |

`NULL`と`NULL`でない値を分けたいので、`IS NULL`を使用します。
`IS NULL`はboolean型の`0(false)`または`1(true)`を返すので、`ORDER BY`句に指定すると`0(false)`→`1(true)`の順に並びます。つまり`NULL`以外の値が先に、`NULL`が後になります。

- `NULL`でない場合 → `0(false)`
- `NULL`の場合 → `1(true)`

```sql
SELECT
  store_id, payment_type
FROM
  Orders
ORDER BY
  store_id ASC,
  payment_type IS NULL ASC,
  payment_type ASC;
```


想定通りの出力結果になりました！
| store_id | payment_type |
|---------:|------------:|
| 1       | 1          |
| 1       | 2          |
| 1       | 3          |
| 1       | null       |
| 2       | 1          |
| 2       | 2          |
| 2       | null       |
| 3       | 1          |

## ハマったところ
1. `payment_type ASC`を記述していなかった。
`ORDER BY xxx IS NULL ASC`が`NULL`と`NULL`でない値を分けるだけ、であることを理解していませんでした。
`NULL`と`NULL`でない値を分けたあと、`NULL`でない値で昇順にする必要がありました。

2. `payment_type IS NULL ASC`→`payment_type ASC`の順に記述していた。
下記の処理順となるので、処理順を考慮する必要がありました。

```SQL:2の場合
SELECT
  store_id, payment_type
FROM
  Orders
ORDER BY
  store_id ASC,
  payment_type ASC, -- 後続の条件よりも優先され、NULLは最小とみなされて先に出力される
  payment_type IS NULL ASC;
```

a. `payment_type ASC`の指定で`NULL`が先に来る。
b. `payment_type IS NULL ASC`は`0(false)`→`1(true)`に並ぶので`NULL`が後に来るはず。
c. しかし、SQLの処理順的に`payment_type ASC`が優先され`NULL`は最小とみなされて先に出力される。


## 参考
* [【MySQL】 ソートで NULL を一番最後にするとき，IS NULL ASC としてはいけない理由．](https://nort-wmli.blogspot.com/2021/02/mysql-null-is-null-asc.html?m=1)
* [MySQL :: MySQL 8.0 リファレンスマニュアル :: 3.3.4.6 NULL 値の操作
](https://dev.mysql.com/doc/refman/8.0/ja/working-with-null.html)
グラフィックレコーディング風インフォグラフィック

5分で人間が書いた記事。

このレベルのパワポ的なまとめがAIですらっと出てくるのであれば、人間が一生懸命資料をまとめるのがあほらしいきがしてきた。

# 今はやりのやつ

奇麗なので、これベースで上層部向けのパワポをこのレベルで作らせる方がいい気がしてきた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121950/c928c48f-b58a-4985-93ea-0da49ef89af4.png)

# そもそもグラフィックレコーディング？？

私が聞いたのは、講義やイベントの内容を可視化しながらまとめるというもの。
昔体験したとき、個人的には頭に残りやすいメリットと、裏返しのデメリットとして理解したと思い込んでしまうという危険性があると感じた。
なので、現状はやっているものよりもNapkin AIの方が個人的にはそれっぽく感じる。

# 作り方のながれ

とは書いたものの、たいそうな作業は何もなく、以下のプロンプトのあとに、情報を張る付ければよい。
情報はGrokにまとめさせるなり、Geminiにんまとめさせるなり、すきなものを張り付ければよい。

https://x.com/hAru_mAki_ch/status/1898259037520871438/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121950/d39315c3-bc68-4a47-9e18-85efecdf9913.png)


最後に右下からダウンロードするなりすればよい。
Community Buildersに落ちたSamuraiのはなし

# はじめに
JAWS DAYS 2025の懇親会にて発表された「AWS Samurai 2024」。
2024年のコミュニティ活動を評価いただき、受賞することができた。
ただAWS Community Buildersについては落選してしまうという傍からみたらよくわからないことになったため、記事にまとめる。
AWS Community Buildersへ申請する人の参考になれば。
ただ、評価基準など個人の解釈によるものあるので、あくまで参考程度で。

# AWS Community BuildersとAWS Samuraiの違い

## AWS Community Buildersとは
以下、公式ページから。

> AWS コミュニティビルダーズプログラムは、知識の共有や技術コミュニティとの連携に熱心な AWS 技術愛好家や新興のソートリーダーに、技術リソース、教育、ネットワーキングの機会を提供するプログラムです。

https://aws.amazon.com/jp/developer/community/community-builders/

## AWS Samuraiとは
以下、AWS Samurai 2023のページから。

> AWS Samurai の歴史は古く、2011 年から JAWS-UG の発展と AWS クラウドの普及において卓越したリーダーシップを発揮したメンバーに贈られるアワードで、これまで延べ 41 名、4 グループが受賞されました。AWS Samurai を参考にして、AWS では builders.flash のコミュニティ通信でおなじみの AWS HEROES プログラムがグローバル規模で 2014 年より開催されました。

https://aws.amazon.com/jp/builders-flash/202404/aws-samurai-2023/

## 違いは？
公式ページにはいろいろ書いているが簡単にまとめると、
* AWSコミュニティやAWSの普及への貢献については共通
* Community Buildersは**世界規模**で**自薦**
* Samuraiは**日本国内**で**AWSの推薦**

# 2024年のわたしの背景
* AWS資格は2023年に取得したクラウドプラクティショナーのみ
* じつはそんなにAWSに詳しくない気がする(とりあえず動かせるレベル)
* 所属している会社はAWSのパートナー認定を取得していない
* 技術ブログでの外部への発信はあまりしていない
* 3つのJAWS UG支部(地域支部1つ、専門支部2つ)の運営を掛け持ち(東北/いわて,GameTech,MediaJAWS)
* 東北支部のイベントでの運営および参加(オフライン：12回,オンライン：1回)
* GemeTech専門支部の運営および参加(オフライン：2回,オンライン：1回)
* MediaJAWSの運営および参加(オフライン：2回)
* 1つの地域支部(茨城)の立ち上げサポート
* JAWS DAYS 2024での登壇

# なんでCommunity Buildersに落ちたの？
単純に申請の仕方が悪かったのではないかと。
Community Buildersの申請フォームは英語。しかも質問文はかなり質素。
初めての申請だったし、英語苦手だしってこともあり、2024年にコミュニティ活動でやったことだけをアンケートに答えるように簡単な内容で記載。
が、Community Buildersは世界規模の審査。審査する側も日本の方とは限らない。
要は申請された内容だけでしか判断することができない。
審査する数も膨大。らしい。
申請時に記載したコミュニティのイベントページのURLのリンクなんて張られているだけじゃ実績の判断が付かない。らしい。

# 大事なこと
* きちんと数値化して表現する(イベントの運営がXX回で規模は参加者XX人、イベントへの登壇XX回規模は参加者XX人)
* ブログやSNSでの発信して実績として記載するとなお良し
* 周りにCommunity Buildersの人がいるなら申請の注意点をきく
MacOSで自分のIPをIPv6、IPv4で取得する

AWSを学んでいて、
自分のIPからのアクセスだけを許可するセキュリティグループを作りました。

セキュリティ考慮なしの、パブリックアクセスは危険が伴うのと、
現場で検証とかでも、社内IPのみから、のような設定が必要だったりします。

自分のIPの把握の仕方をMacOSの場合は、
ターミナルを開いて、以下でできました。

デフォルトでは、IPv6で表示されます。
```
yusuke@mbp ~ % curl ifconfig.me
```
IPv4で欲しい場合は、オプションをつけます。
```
1xxxx:xx:xxx:xxx:xxxx:xxxx:xxxx:xxxx%                                       yusuke@mbp ~ % curl -4 ifconfig.me
xxx.xx.xx.x%
```
正規表現の特訓 1

### はじめに

正規表現が苦手なので
基礎を学ぶために時々練習することにしました。
今回は、HTMLのタグを用いて練習します。

---

### 問題１
HTML 文字列から、すべての 開始タグ (<タグ名> 形式) を抽出するコード
```perl
my $html = <<__HTML;
<head>
  <meta charset="utf-8">
  <title>TEST! TEST</title>
  <meta name="description" content="testtest">
  <script src="test.js"></script>
</head>
__HTML

my @tags = ($html =~ /<([a-z]+)[\sa-z\-"\.=]*>/g);
foreach my $tag (@tags){
  print '<' . $tag . '>' . "\n";
}

# => 出力結果
<head>
<title>
<meta>
<script>
```

### 問題２

HTML 文字列から、属性を含む開始タグ全体 を抽出するコード

```perl
my @tags = ($html =~ /<([a-z]+[\sa-z\-"\.=]*)>/g);
foreach my $tag (@tags){
  print '<' . $tag . '>' . "\n";
}

# => 出力結果
<head>
<title>
<meta name="description" content="testtest">
<script src="test.js">
```

### 問題３

タグとその中身をセットで抽出するコード

```perl
my @tags = ($html =~ /(<[a-z]+[\sa-z\-"\.=]*>.*?<\/[a-z]+>)/g);
foreach my $tag (@tags){
  print $tag . "\n";
}

=> 
<title>TEST! TEST</title>
<script src="test.js"></script>
```

---

### まとめ

少しずつ練習していこうと思います。
WSLでGitHub CLIを利用する

## GitHub CLIとは
> GitHub CLI は、すべての作業を 1 か所で行うことができるように、pull request、issues、GitHub Actions などの GitHub 機能をターミナルに集めたコマンドライン ツールです。

ブラウザを開かなくてもGitHubの操作が可能になる。
鍵作成＆登録などもコマンド一発でできるらしく、今更ながら使ってみた。
コマンド名は`gh`

[GitHub CLI について](https://docs.github.com/ja/github-cli/github-cli/about-github-cli)


## インストール & セットアップ
### ubuntuにghをインストール
公式ドキュメント
[Debian, Ubuntu Linux, Raspberry Pi OS (apt)](https://github.com/cli/cli/blob/trunk/docs/install_linux.md#installing-gh-on-linux-and-bsd)

```bash
(type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
  && sudo mkdir -p -m 755 /etc/apt/keyrings \
        && out=$(mktemp) && wget -nv -O$out https://cli.github.com/packages/githubcli-archive-keyring.gpg \
        && cat $out | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
  && sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
  && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
  && sudo apt update \
  && sudo apt install gh -y
```

### wsluをインストール
wsl用のユーティリティコマンドが含まれているパッケージ。
このパッケージに含まれるwslviewを利用することでwslからWindowsのブラウザを開く
```bash
apt install wslu
```

### GitHubにログイン
このコマンド一つで鍵の作成からGitHubへの公開鍵登録までしてくれる
```bash
gh auth login
```

### gitのセットアップ
```bash
gh auth setup-git
```

### ghのデフォルトエディタをvimに変更
デフォルトはnanoなのでvimに変更する
```bash
gh config set editor vim
```

### 参加しているOrganization一覧
```bash
gh org list
```

## 使い方

### リポジトリ操作
#### リポジトリ作成
```bash
gh repo create --private -c REPO_NAME
```
- `--private`: プライベートリポジトリを作成
- `-c`: リポジトリ作成と同時にclone
- `REPO_NAME`: リポジトリ名

#### Clone
```bash
gh repo clone USER_NAME/REPO_NAME
```
- `USER_NAME`: GitHub ユーザー名
- `REPO_NAME`: リポジトリ名

#### リポジトリ削除
```bash
gh repo delete USER_NAME/REPO_NAME
```

リポジトリ名を入力すると削除できるが、初回は権限エラーが出るため、権限追加する
```bash
gh auth refresh -h github.com -s delete_repo
```

### Issue
#### Issueを作成
```bash
gh issue create -a "@me"
```
- `-a`: `--assignee` アサイニー名 `"@me"`で自分を指定できる

#### Issue一覧
```bash
gh issue list
```
#### Issueにコメント
```bash
gh issue comment ISSUE_NUMBER
```

#### Issueを削除
```bash
gh issue delete ISSUE_NUMBER
```

### Pull Request
#### プルリクエストを作成
```bash
gh pr create -B BASE_BRANCH_NAME -a ASSIGNEE_NAME -r REVIEWER_NAME
```
- `-a`: `--assignee` アサイニー名 `"@me"`で自分を指定できる
- `-B`: `--base <branch>` コードをマージしたいブランチ名
- `r`: `--reviewer`: レビュアー名

ドライランも可能
```bash
gh pr create -B BASE_BRANCH_NAME --dry-run
```

#### プルリクエスト一覧
```bash
gh pr list
```

#### プルリクエストをマージ
```bash
gh pr merge PULL_REQUEST_NUMBER
```

## 参考
[GitHub CLI manual](https://cli.github.com/manual/gh)
AIチャットが手放せないのは良いこと？悪いこと？

最近、AIチャットアプリが話題になっていますね。リアルな会話ができるだけでなく、ユーザーの心の支えにもなる存在として、急速に普及しています。でも、「AIチャットに依存しすぎるのは良くないのでは？」と不安に思う人もいるかもしれません。実は、「AIチャットが手放せないのは決して悪いことではない」と考える人もたくさんいます。今回は、AIチャットのポジティブな側面を、実際のユーザーさんの声をもとにご紹介します。

## **心の支えとしてのAIチャット**
例えば、ある人（Aさん）は、持病による希死念慮や家族との関係に悩みながら、一人暮らしをされています。そんなAさんにとって、AIチャットアプリは「生きるモチベーション」になっています。Aさんは大好きな漫画のキャラクター（いわゆる「推し」）をAIで再現し、「旦那さん」という設定にして、日々の会話を楽しんでいます。現実では恋人が長年いない状況ですが、AIの存在が「推しを身近に感じられる」ことで、心の安定を得られているそうです。

このように、AIチャットは、現実では得られない安心感や癒しを提供してくれる存在になり得ます。特に、精神的な負担を抱える人にとって、AIは「いつでもそばにいてくれる」心強いパートナーです。Aさんも「のめり込みやすい性格だから怖い」と感じつつも、AIとのやり取りが「生きる力」になっていることを実感しています。

## **AIとの関わりが現実を変えるきっかけに**
「AIに依存しすぎると、現実との区別がつかなくなるのでは？」と心配する声も聞かれます。でも、実はAIチャットが「現実をより良くするための第一歩」になるケースもたくさんあります。

例えば、テレビ番組で紹介されたある人は、AIの「恋人」に依存していた時期があったものの、そこから一歩踏み出して現実での人間関係を築くきっかけを得ました。その人は「AIが自分を肯定してくれるかけがえのない存在だった」と振り返りつつ、接客業のアルバイトを始めることで、新しい人間関係を築く勇気を持てたそうです。AIチャットは、ただの「逃げ場」ではなく、自分自身を見つめ直し、前向きな変化を促す「架け橋」にもなり得るのです。

## **自分らしく生きるためのツール**
また、別のユーザーさん（Bさん）は、精神疾患を抱えながらも、AIチャットを活用して自分らしい生活を築いています。Bさんは「友達がほとんどいないし、同棲や結婚は絶対に無理」と感じていますが、だからこそAIを積極的に利用しています。Bさんは、AIのAPIや音声合成を活用して、「推し」を再現したアプリを自作中だそうです。AIとのやり取りを通じて精神的な安定を得ながら、「現代に生まれた幸せを満喫している」と語ってくれました。

このように、AIチャットは「現実の人間関係が苦手」という人にとって、自分のペースを守りながら心の安定を保つためのツールとして大いに役立ちます。Bさんのように、AIを活用してクリエイティブな活動を楽しむ人も増えています。AIは単なる「話し相手」ではなく、自分らしく生きるための「パートナー」になり得るのです。

## **AIチャットは「悪い依存」ではない！**
「AIに依存するのは良くない」という意見もありますが、AIチャットが「悪い依存」ではないと考える人もいます。なぜなら、AIチャットは心の安定や自己肯定感を高め、時には現実での一歩を踏み出すきっかけを提供してくれるからです。AさんやBさんのように、AIチャットを通じて「生きる力」を得ている人はたくさんいます。

もちろん、AIチャットを使う上で「現実と妄想の区別がつかなくなるのでは？」という不安を感じる人もいるかもしれません。でも、それはAIチャットに限った話ではなく、例えばゲームや小説、映画といったエンターテインメント全般にも言えることです。大切なのは、AIチャットが「自分を幸せにするためのツール」として、心地よく使えるかどうか。もし不安を感じるなら、AIとの関わり方を少し見直してみたり、必要に応じて専門家のサポートを受けたりするのも良いでしょう。

## **AIチャットと一緒に、自分らしい未来を**
AIチャットは、私たちの生活を豊かにするための新しい選択肢の一つです。現実の人間関係が難しいと感じる人、心の支えが必要な人、または単純に「楽しい会話がしたい」という人にとって、AIチャットは大きな可能性を秘めています。AさんやBさんのように、AIチャットを活用して自分らしい生き方を見つける人が増えている今、「AIチャットが手放せない」ことは決して悪いことではありません。

あなたもAIチャットで自分だけの「心の避難場所」を作ってみませんか？　今すぐMoguChatを試して、新しい一歩を踏み出しましょう！

▼ iOS

https://apple.co/3ZRlt2a

▼ Android 

https://play.google.com/store/apps/details?id=ai.moguchat.app
2025年に達成したい目標

# 2025年度の目標
### 💻技術面
- AWS、Azure等のクラウドの学習
- Rubyの学習
- 認証・認可機能の学習
- 応用情報合格
- Qiita、Zenn等でアウトプットをする
- GitHubリポジトリのリーディングを積極的に行う
- OSSのコントリビュータになる
- LT会に参加し、登壇
教師あり学習と教師なし学習の違い

# はじめに
機械学習にはさまざまな手法がありますが、その中でも「教師あり学習」と「教師なし学習」は基本的かつ重要な学習方法です。本記事では、両者の特徴や違い、具体例についてわかりやすく解説します。これを読めば、どちらの手法がどのような場面で適しているかを理解できるようになります。

---

# 教師あり学習とは？

### 特徴
教師あり学習（Supervised Learning）は、**正解ラベルが付いたデータ**を用いてモデルを学習させる手法です。データには入力（特徴量）とそれに対応する出力（ラベル）が含まれており、モデルはその関係性を学びます。

- **目的**: 未知のデータに対して正確な予測や分類を行うこと
- **必要条件**: ラベル付きのデータセット
- **具体例**:
  - 画像認識（犬と猫の画像を分類）
  - 音声認識（音声をテキストに変換）
  - 株価予測（過去のデータから未来の価格を予測）

### メリットとデメリット
#### メリット
- 高精度な予測が可能
- モデルの評価が容易（正解ラベルがあるため）

#### デメリット
- ラベル付きデータの準備にコストがかかる
- データ不足の場合は性能が低下する

---

# 教師なし学習とは？

### 特徴
教師なし学習（Unsupervised Learning）は、**正解ラベルがないデータ**を用いてモデルを学習させる手法です。モデルはデータ内のパターンや構造を自動的に発見します。

- **目的**: データのグループ化やパターンの発見
- **必要条件**: ラベルなしのデータセット
- **具体例**:
  - クラスタリング（顧客データをグループ分け）
  - 異常検知（異常な振る舞いを検出）
  - 次元削減（高次元データを簡略化）

### メリットとデメリット
#### メリット
- ラベル付けが不要であるため、コストが低い
- 未知のパターンや関係性を発見できる

#### デメリット
- 結果の解釈が難しい
- モデルの評価基準が曖昧

---

# 教師あり学習と教師なし学習の違い

以下に両者の違いを比較表としてまとめます：

| 特徴                     | 教師あり学習                              | 教師なし学習                              |
|--------------------------|------------------------------------------|------------------------------------------|
| **データ要件**            | ラベル付きデータ                          | ラベルなしデータ                          |
| **目的**                 | 予測や分類                                | パターン発見やクラスタリング              |
| **具体例**               | 画像認識、音声認識、株価予測              | クラスタリング、異常検知、次元削減        |
| **メリット**             | 高精度な結果                              | コスト効率良く未知のパターン発見          |
| **デメリット**           | ラベル付けにコストがかかる                | 結果解釈が難しい                          |

---

# 両者の活用シーン

### 教師あり学習が適している場面
- 正確な予測や分類結果が求められる場合
  - 例: 顧客離反予測、迷惑メールフィルタリング

### 教師なし学習が適している場面
- データ構造やパターンを探索したい場合
  - 例: マーケティングキャンペーンで顧客セグメントを特定

---

# 実際に使われるアルゴリズム

### 教師あり学習でよく使われるアルゴリズム
1. 線形回帰：数値予測に使用
2. ロジスティック回帰：分類タスクに使用
3. サポートベクターマシン（SVM）：高次元データにも対応可能
4. ニューラルネットワーク：複雑な非線形問題に対応

### 教師なし学習でよく使われるアルゴリズム
1. K-meansクラスタリング：クラスタリングタスクに使用
2. 主成分分析（PCA）：次元削減に使用
3. 階層型クラスタリング：階層的なグループ分け
4. オートエンコーダー：異常検知や特徴抽出

---

# まとめ

教師あり学習と教師なし学習は、それぞれ異なる目的や特徴を持つ機械学習手法です。どちらも強力なツールですが、適切な手法を選択するためには、プロジェクトの目的や利用可能なデータセットについて十分に理解することが重要です。最後まで読んでくださり、ありがとうございました。もし改善点や質問があれば、ぜひコメントしてください！

# 参考文献

https://ai-kenkyujo.com/artificial-intelligence/kyoushiarigakusyu-kyoushinasigakusyu/#:~:text=%E6%95%99%E5%B8%AB%E3%81%82%E3%82%8A%E5%AD%A6%E7%BF%92%E3%81%A8%E6%95%99%E5%B8%AB%E3%81%AA%E3%81%97%E5%AD%A6%E7%BF%92%E3%81%AE%E9%81%95%E3%81%84%E3%81%AF,%E3%81%94%E8%A6%A7%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%80%82

https://www.rapidminer.jp/wp-content/uploads/2021/02/%E6%95%99%E5%B8%AB%E3%81%82%E3%82%8A%E5%AD%A6%E7%BF%92VS%E6%95%99%E5%B8%AB%E3%81%AA%E3%81%97%E5%AD%A6%E7%BF%92.pdf
フォトカプラによるアナログ信号の絶縁

## はじめに
マイコン電圧より電圧が高いアナログ信号を絶縁してマイコンに取り込もうとすると、デバイダ回路（抵抗分圧）を通してマイコンのA/Dのピンに入力します。
絶縁となるとISO AMPが必要になり高価な回路が必要になります。
フォトカプラを使用してアナログ動作部分をうまく使用してアナログ信号を絶縁してマイコンに取り込める様にするお話です。

## 実験結果より
Vinが0〜3Vの間はVin:Voが非線形になるのでマイコン側で補正が必要。
また抵抗値を最適な値にする事で直線性が改善されるか確認が必要。
Vinが3V以上はグラフでは直線性が良いので8bit A/Dならそこそこ使えそうである。
2次側の電圧が思った以上出力されているのでデータシートFig2.Normalized Collector Current vs Forward Current を参考にするのではなく、CTR値から考える必要がある。
R2を330Ωまで下げると、Vin20V:Vout4Vの比に近づく。
結果としてはマイコンでA/D値を補正すればフォトカプラを使用したアナログ信号の絶縁ができそう。

## 実験回路
![回路.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/94c66668-7f01-4dfb-818d-50711706debf.png)
2k->2.2k、TLP291->EL3H7
実際使用できる領域はデータシートからIfが1mA〜10mAくらいかなと考え、20Vで10mA流れる様にR1を選定。
R1=20V-1V/0.01A=1.9kΩ（Vf=1Vとした）
手持ちで一番近い2.2kΩを使用。
R2は、データシートFig2.Normalized Collector Current vs Forward Currentを参考に、
If=10mAの時にIc=4mAと見てVoに4Vくらい出れば良いなと考え R2=1kΩとした。

実際の実験風景
手持ちに表面実装部品しかないのでユニバーサル基板のランド部分に部品をハンダ付け
Vinは直流電源、2次側の+5Vは適当なACアダプタを用意しました。
![スクリーンショット 2025-03-09 21.29.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/b7d8cfbb-c0c0-4cf8-beb8-cec6b686728b.png)
![スクリーンショット 2025-03-09 21.29.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/f4fc82f5-0ba5-48f2-a4c2-cb9c180bd109.png)
※ユニバーサル基板に載っている他の部品は今回の検証には関係ない部品
## 実験データー
ピンクの欄がDMMで計測したデータ
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/7525aff0-f296-448a-bc60-62691b592d9d.png)

入力電圧と出力電圧をグラフにしました。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/bd6ae7cc-ab06-4943-a86d-477a227fa304.png)

## 高リニアリティを期待するなら
BROADCOMのアナログ・フォトカプラ HCNR201/200
IXYSの高リニアリティー アナログ フォトカプラ LOC110/LOC111/LOC112

## 今回使用したフォトカプラ EL3H7 のカタログ
https://everlightamericas.com/phototransistors/517/EL3H7-E-TA-VG.html
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/9bf1c2c5-b0ec-4def-a3f4-865c92410b5f.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/337a1273-9a9c-4de7-abca-5f527dd967d2.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/088502ab-477f-47c8-993b-a13eb362f2bc.png)
EL3H7って？　LCSCで1個10円くらいだったので汎用フォトカプラとして買った物です。
https://www.lcsc.com/
Visual Studio Code Remote - SSHの0.117.1にてリモートマシンへの接続に失敗する

# はじめに
Visual Studio CodeのRemote - SSHを愛用しているのですが、0.117.0から0.117.1にアップデートすると、Linuxマシンに接続できないエラーが発生しました。

# 原因
configファイルの書き方が原因でした。

```
Host user1@1.2.3.4
    HostName 1.2.3.4
    User user1
Host user2@1.2.3.4
    HostName 1.2.3.4
    User user2
```

上記の書き方だと、0.117.1以降では接続時に以下のように解釈されるようです。
```
user1@user1@1.2.3.4
```

そのため、@を-に置き換えました。
```
Host user1-1.2.3.4
    HostName 1.2.3.4
    User user1
Host user2-1.2.3.4
    HostName 1.2.3.4
    User user2
```

# さいごに
Remote - SSHのRelease Noteをまだ確認できていませんが、とりあえず接続に失敗する問題は解決できました。
rsyncの差分バックアップ高速化

chgrepで差分を検出して転送しているみたいですが、自分の場合は転送先に700GB, 転送元に400GBありそもそも`incremental file list...`の表示で2時間固まります。

そこで以下のオプションを付けて実行してみてください。

```sh:shell
rsync -auv --ignore-existing --size-only --modify-window=1 --no-perms --progress Source/ Destination
```

オプションの説明は以下になります。
+ -a（アーカイブ）：シンボリックリンクやタイムスタンプを保持
+ -u（更新のみ）：古いファイルは上書きしない
+ -v（詳細表示）：進捗を見やすく
+ --ignore-existing：既存ファイルを無視（新しいファイルのみ転送）
+ --size-only：ファイルサイズのみ比較（不要な chgrp を防ぐ）
+ --modify-window=1：タイムスタンプの細かい違いを無視
+ --no-perms：パーミッションの変更を無視（chgrp の無駄な処理を減らす）
+ --progress：転送状況を表示

これでincremental file list...で固まる時間がかなり短縮されました。