OmniAICreator/Qiita-1.07M huggingface dataset:
日付でソートするとき

# はじめに
文字列型でソートするよりDateTime型でソートする方が良いというお話。

# なぜなのか
①正確なソート
文字列型でソートすると、アルファベット順でソートされる
2024-10-01と2024-2-01を文字列型でソートすると、2024-10-01が先に来てしまい、想定通りの結果にならない。

②一貫性
文字列型の日付はフォーマットが統一されていないと正しくソートできない。
例えば、"2024/10/01"と"2024-10-01"は異なる形式のため、正しくソートされない。
DateTime型は内部的に一貫した形式で保持されるため、フォーマットの違いによる問題は発生しない。


# 終わりに
APIなどで、日付が入っているものについては、DateTime型に変換するなどをして対応する。
もしかしたら、APIで日付ソートが入っている場合は、アプリ側で気にしなくて良いが、もしAPI側で考慮が漏れていたら気をつけよう。
[Rails / Rspec] instance_doubleの使い分け：第二引数の有無による違い

## 概要
表題の違いについて、まとめました。

## 結論
- **第二引数なしの場合**  
  - `instance_double`で`Mock`のみ作成される
  - `allow`によるスタブ設定が必要

<br>

- **第二引数ありの場合**  
  - `Mock`の作成と、スタブの定義を同時に実施される

## コード

ここでは `XmlGenerator` クラスの `call`インスタンスメソッドをスタブします。

### 第二引数なしの場合

1. `instance_double` で モックを作成
1. `allow` で スタブの定義

```ruby
let(:xml_generator) { instance_double(XmlGenerator) }

before do
  allow(xml_generator).to receive(:call).and_return('<xml>Test</xml>')
end
```

### 第二引数ありの場合

1. `instance_double` で モックとスタブを作成

```ruby
let(:xml_generator) { instance_double(XmlGenerator, call: '<xml>Test</xml>') }
```

## メリット / デメリット

### 第二引数なしの場合
- **メリット**
  - 柔軟性が高く、複雑なスタブ設定や複数のメソッドのスタブを後から個別に定義できる  
- **デメリット**
  - コード量が増え、記述が冗長になる可能性がある  

### 第二引数ありの場合
- **メリット**
  - モック作成と同時にスタブの定義ができるため、コードが簡潔で読みやすい  
- **デメリット**
  - 複雑なスタブ設定には向かず、シンプルな戻り値の定義に限定される場合が多い  

## まとめ
以上です。
メリデメを理解した上で使い分けると、可読性の高いテストコードが記載できそうですね！
PS2Linux Beta版 kernel-2.4.17 rebuild

今までの"VECTOR様のPS2Linuxをいじる"がwebで見れなくなりました。
PS2Linux kernel再構築 Version 2.4.17_mvl21

Linux-2.4.17_mvl21 (起動時、今までのタックスが組み込みに強いMontaVistaLinuxに変わる)

"linux-2.4.17_ps2.tar.bz2"のカーネルを検索すれば見つかります。

cd /tmp
sudo wget  https://sourceforge.net/projects/kernelloader/files/Linux%202.4/Linux%202.4.17%20Kernel%20Source/

sudo tar zxvf linux-2.4.17_ps2.tar.bz2
　何故か tarコマンドのoption -jxvf では解凍出来ませんでした。

sudo mv linux-2.4.17_ps2 /usr/src
cd /usr/src
sudo ln -s linux-2.4.17_ps2 linux　シンボリックリンクを貼る

　PS2のメモリーカードをマウントする
sudo mount -t ps2mcfs /dev/ps2mc00 /mnt/mc00

　rootしか/mnt/mc00に移動出来ないので
sudo -s
password:XXXXXXXX
　自分のUserパスワードを入れてroot(管理者)になる
cd /mnt/mc00

cp -p bblinux4.diff.gz /usr/src/linux　Beta版はこのパッチが無いと再構築出来ません。
注意
[正式版]Linux (for PlayStation2)では patchは不要です

cd /usr/src/linux
rm -r /usr/src/linux/scripts/mkdep split-include
　2.4.17のカーネルではこの2つのファイル(mkdep split-include)を削除する必要有り(削除しないとkernelをビルドできないよ)
gzip -d bblinux4.diff.gz
patch -p0 < bblinux4.diff　ここでパッチをあてています

cp /usr/src/linux/arch/mips/configs/defconfig-ps2   .config

[Kernel Rebuild編]
make menuconfig
ext2 (M) ---> ext2(＊)　モジュールを組み込みにする
optionは好きにいじるけどext2のmodule(M)を(＊)にする必要有り！

make dep; make clean; make
make modules; make modules_install

exit
[kernel Rebuildは終了(約1時間)]

sudo cp -p vmlinux /boot/vmlinux-2.4.17 　　出来たカーネルを/bootにcopyする
sudo gzip -c9 vmlinux > /mnt/mc00/vmlinux-2.4.17.gz 　　MemoryCardに圧縮したカーネルを入れる(圧縮せずコピーでも可能ですが圧縮した方が小さくなるよ)

sudo vi /mnt/mc00/p2lboot.cnf　の編集例(NTSCのテレビに合わせているので)
"Linux-2.4.17" vmlinux-2.4.17.gz "" 203 /dev/hda1 "crtmode=ntsc1" MontaVistaLinux-2.4.17_mvl21
　末尾は同じでなくて構いません

[PS2Linux再起動の設定]
sudo cp -p /mnt/mc00/akmem_ps2.tar.gz /usr/src

sudo tar zxvf akmem_ps2.tar.gz
cd akmem_ps2
sudo make; make mknod; make install
sudo cp -p akload /sbin/akload　コピーする

sudo umount /mnt/mc00

これがPS2Linuxの再起動のコマンド
sudo /sbin/akload -r /boot/vmlinux-2.4.17
　reboot~が始まり2.4.17のカーネルでのlogin画面が立ち上がります
このカーネルが再起動には、適しているのか、ほぼ成功しますが2.2.21とか2.2.26だと固まり動かないことが多いです。
再起動ができないで今のカーネルのシャットダウンのみで画面は動かなくなりました。

vmlinux-2.4.17でakmem_ps2(意味はAnotherKernelMemory_ps2かな??)を使って
再起動したら

PS2Linux release1.0beta
Linux-2.4.17_mvl21 on a mips

login:hoge
password:XXXXXXXX

2.4.17のカーネル構築用のpatch(bblinux4.diff.gz)
2.2.2X以降のPS2Linuxでの再起動コマンドの
(akmem_ps2.tar.gz)
はもう見つからないと思いますが必要であればuploadをします。

PLAYSTATION2関連やPS2Linuxの検索で見つからない情報や紙の媒体にPS2Linuxの記事があるよとか！
詳しい方がいれば情報をくださいませ。
私も間違えているのも自分でわからないで運用していたらみっともないので！！
作ったものの配布（Minecraft）

Minecraft（Java版）のデータパック、プラグイン、Mod などの配布物まとめ
※統合版では動きません

# はじめに
Minecraft（Java版）の開発物を配布します。配信で利用する場合はクレジットの記載をして下さい。使用許可の確認などのご連絡は不要です。

バグ報告があればコメント欄に書いてもらえれば不定期に確認するかもしれないし、しないかもしれません。辛辣な感想などは心が折れるかもしれませんが、感謝のコメントは泣いて喜びます。

```
クレジット表記の例
・Ⓒジョニキ
・Twitter: @jojohniki
・製作者「ジョニキ」さん
など
```

# 作品一覧
## HP＆空腹ゲージ共有（プラグイン）
あなたには本当の友達がいますか？
友達との絆を確かめ合うために使ってください。
仲が悪くなっても私のせいにはしないでください。

- サバイバルモード、アドベンチャーモードのプレイヤーのHP＆空腹ゲージが共有される
- 受けるダメージや回復量も共有される

※対応バージョン：Spigot 1.16.1 ～ 1.21.4（及び互換性のあるサーバー）
　Paper 1.18.2、1.19.2、1.20.4、1.21.4 で動作確認しています。

https://drive.google.com/file/d/1Dz83ij0wvR0CN_CpgGUGd19rAZAoNEsr/view?usp=drive_link

遊んでくれた方々
<iframe width="560" height="315" src="https://www.youtube.com/embed/cBgvaWOSFUk?si=2UvtpFaForQejtw-" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## インベントリ共有（プラグイン）
友達が増えれば増えるほど操作性が悪くなる鬼畜マインクラフトを体験できます。
友達との絆を確かめ合うために使ってください。
仲が悪くなっても私のせいにはしないでください。

- サバイバルモード、アドベンチャーモードのプレイヤーのインベントリが共有される
- インベントリ内のマウス操作やホットキーを使ったアイテムの持ち替え等も共有される

※アイテムの無限増殖バグがあるかもしれません。見つけたら教えてください

※対応バージョン：Spigot 1.16.1 ～ 1.21.4（及び互換性のあるサーバー）
　Paper 1.18.2、1.19.2、1.20.4、1.21.4 で動作確認しています。

https://drive.google.com/file/d/1yiM21YMHVP4QcIGxsETwWjVaI9-ENJo5/view?usp=drive_link

参考動画
<blockquote class="twitter-tweet" data-media-max-width="560"><p lang="ja" dir="ltr">1年くらい前に海外で600万回の再生回数を叩き出した企画をまるぱｋ・・・インスパイアすることに成功しました。<br>インベントリを共有できます。<br>本家の事は動画の一部分でしか見たことないので分からないですが他に共有した方が良さそうなところもついでに共有してみました。 <a href="https://t.co/LB5mZc00I9">pic.twitter.com/LB5mZc00I9</a></p>&mdash; ジョニキ🙄 (@jojohniki) <a href="https://twitter.com/jojohniki/status/1356481880116264960?ref_src=twsrc%5Etfw">February 2, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

遊んでくれた方々
<iframe width="560" height="315" src="https://www.youtube.com/embed/_ip1kQABDko?si=pOSu5Z3pFL3ilTko" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## ブロックが見えない世界（Mod）
ブロックのテクスチャが黒（白）一色になります。特定条件を満たすとブロックが見えるようになります。
エンダードラゴンを倒して世界に色を取り戻してください🙄
とりあえずテストプレイでは２，３時間でやっとネザー入れました🙄

- 光源の周りがちょっと見える（黒一色モードの場合のみ）
- ブロックを１スタック持つとそのブロックが見えるようになる
- 以下のコマンドで黒一色モード、白一色モードの切り替えができる

```
/colorless black
/colorless white
```

※もし条件を満たしているのにブロックが見えない場合は再ログインまたは F3+T を押してリソースパックを更新してください。

※対応バージョン：Forge 1.20.1
https://www.curseforge.com/minecraft/mc-mods/colorless

<blockquote class="twitter-tweet" data-media-max-width="560"><p lang="en" dir="ltr">Ignorance is bliss. <a href="https://t.co/7dIsLd7Ah9">https://t.co/7dIsLd7Ah9</a> <a href="https://t.co/JCaplXA95R">pic.twitter.com/JCaplXA95R</a></p>&mdash; ジョニキ🙄 (@jojohniki) <a href="https://twitter.com/jojohniki/status/1892576136879640846?ref_src=twsrc%5Etfw">February 20, 2025</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# さいごに
随時更新
Snowflakeのワークシート共有について、消えるのか消えないのかどっちなんだい

Snowflakeのユーザーを作り直す必要に駆られまして、元々使っていたユーザーのワークシートを新ユーザー側に共有しておくことになりました。
そこで気になるのは、元々のユーザーが削除になったらワークシートは見れなくなるのかどうか？

https://docs.snowflake.com/ja/sql-reference/sql/drop-user

公式ドキュメントを見ると共有していれば、ユーザー削除後もワークシートは見れるようです。

試してみます。
まずはユーザー削除の前に、共有したワークシートを削除したら？というシチュエーションをやってみました。
ワークシートには一応一文は書いて実行しておきます。（current_xxxxx()系をいろいろ試しつつ。）

共有の方法でビュー/表示と実行/編集の3つがあるので全部試します。

# 共有したワークシートを削除するとどうなる？

## 実験1
共有する側⇒ワークシート作成：ワークシート削除テスト1
```
select current_role();
```
共有する側⇒「ビュー」権限で共有する
共有される側⇒見えた
共有する側⇒ワークシート削除
共有される側⇒消えた

## 実験2
共有する側⇒ワークシート作成：ワークシート削除テスト2
```
select current_ip_address();
```
共有する側⇒「表示と実行」権限で共有する
共有される側⇒見えた
共有する側⇒ワークシート削除
共有される側⇒消えた

## 実験3
共有する側⇒ワークシート作成：ワークシート削除テスト3
```
select current_version();
```
共有する側⇒「編集」権限で共有する
共有される側⇒見えた
共有する側⇒ワークシート削除
共有される側⇒消えた

## 結果
全て同じ挙動でした。
ワークシートを削除したら、共有された側からも消えるという結果でした。

# 共有した側のユーザーを削除するとどうなる？

では次にワークシートを削除でななくて、ワークシートを共有した側のユーザーを削除を。
## 実験4
TESTUSER1を作成。
TESTUSER1でログイン。

共有する側（TESTUSER1）⇒ワークシート作成：ワークシート削除テスト4
```
select current_session();
```
共有する側⇒「ビュー」権限で共有する
共有される側⇒見えた
共有される側⇒TESTUSER1を削除
共有される側⇒「共有されたデータ」タブに残っている

## 実験5
TESTUSER2を作成。
TESTUSER2でログイン。

共有する側（TESTUSER2）⇒ワークシート作成：ワークシート削除テスト5
```
select current_client();
```
共有する側⇒「表示と実行」権限で共有する
共有される側⇒見えた
共有される側⇒TESTUSER2を削除
共有される側⇒「共有されたデータ」タブに残っている

## 実験6
TESTUSER3を作成。
TESTUSER3でログイン。

共有する側（TESTUSER3）⇒ワークシート作成：ワークシート削除テスト5
```
select current_available_roles();
```
共有する側⇒「編集」権限で共有する
共有される側⇒見えた
共有される側⇒TESTUSER3を削除
共有される側⇒「共有されたデータ」タブに残っている

## 結果
全て同じ挙動でした。
ワークシートを共有したユーザーを削除しても、共有された側はずっと見えるという結果でした。

これで安心してユーザー削除できます。
PS2Linux DiskLess Client (Memory-Based Linux)

PS2LinuxのHDDへのインストールなしで起動させるプロジェクトです。
起動にはPS2LinuxのDVDが必要だとおもっていましたがなくても大丈夫です。
FreeMcBootが必要なのとKernelLoader3.0.ELF(Kloader3.0.elf)を使いDisklessClientを起動させます。
8GBくらいのUSBメモリーにPS2NSというdirectoryを作り中に
1.vmlinux_v11.gzをvmlinux.gzにリネーム
2.initrd(usb2).gzをinitrd.gzにリネーム
3.適当なファイル(ISOイメージ)
4.Config.txt

と、USBのTOPにConfig.txtを作ります。以下はConfig.txtの内容です

KernelFileName=mass0:PS2NS/vmlinux.gz
InitrdFileName=mass0:PS2NS/initrd.gz
KernelParameter=ramdisk_size=16384 cdrom=/dev/sda1 newroot=/cdrom/PS2NS/DISC.IMG
Auto Boot=10(適当)

このUSBをPS2(PlayStation2)につけてメモリーカードのKLoader3.0.ELFを起動させると
PS2Linux(DiskLessClient)の起動が可能です。
起動させると

/>

このような画面になります
Kernelは2.2.21-pre1-xr7です。Kernelは2.6.35.4かも分かりませんがPS2LinuxCommunityのDisklessClient(MemoryBasedLinux)とほぼ同じです。
PS2のメモリだけでLinuxが機能しています(最大32MB)

適当なDiskImageのマウントですが
/ext0というのがdefaultであるのでそこに

mount -o loop /dev/sda1/PS2NS/DISC.IMG /ext0
cd /ext0

ここからPS2LinuxをインストールしたHDDをマウントして内容をリカバリしたりネットワークも使えるのでなにかしらに使えそうです。

HDDのマウントは
mkdir /mnt
mount -t ext2 /dev/hda1 /mnt
cd /mnt

B.B.Navigatorのパーティションをマウントするならreiserfsでhda11になります
mount -t reiserfs /dev/hda11 /mnt
cd /mnt とかです

ネットワークの使用はコマンドが必要！
ifconfig eth0 192.168.1.9 netmask 255.255.255.0　IPアドレス、GATEWAYは任意(使用環境)で構いません。
route add default gw 192.168.1.1

上の設定をしたら
telnet 192.168.1.2 23 とかでリモートサーバのマシンにtelnetでLoginする。

USBのマウントは
mkdir /usb0

一度目にこうして
mount -t usb-storage /dev/sda1 /usb0
マウントする時には
mount -t vfat /dev/sda1 /usb0
とか
mount -t vfat /dev/sdb1 /usb0　です。

MemoryCardのマウントは
mount -t ps2mcfs /dev/ps2mc00 /mc0
mount -t ps2mcfs /dev/ps2mc10 /mc1

MemoryCardの中にアクセスするには
cd /mc0/BWLINUX　です。

PS2Linuxファイルはこの
BWLINUX(仮想ルート)の中に入れなくては使えません。
実行は
cd /mc0/BWLINUX　移動して
./ps2fdisk_0.9-3　でps2fdisk_0.9-3の実行 で(B.B.navigatorのパーティションが見えます)
と、いう風に使います。
next/navigationのuseParamsを使ってURLのパラメータを取得する

# はじめに
**next/navigationの`useParams`を使って**`http://localhost:3000/posts/edit/[id]`の`id`を取得しました。
その知見を備忘録として残しておきます。

# 手順

`http://localhost:3000/posts/edit/1`というURLに対して、`id=1`を取得する処理が下記です。
※`useRouter`・`useParams`はクライアントサイドのみ使用可。
```
  const { id } = useParams(); 

  console.log(id);
```
ログ出力では想定通りの結果になっています。
```
1
```
# おまけ・UsePathnameとの違い
`UsePathname`を使って格闘したこともありましたが、改めて調べてみたら用途が全然違いますね。

・`useParams`：**動的ルーティングのパラメータを取得**
例）`posts/edit/[id]/page.ts`の	`/edit/1`で`{ id: '1' }`を取得

https://nextjs.org/docs/app/api-reference/functions/use-params

※Next.jsにおける動的ルーティングは、フォルダー名を角括弧で囲むことで作成できます。

https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes

・`UsePathname`：**URLのパス名を文字列として取得**
例）	`/edit/1`で`"/edit/1"`を取得

https://nextjs.org/docs/app/api-reference/functions/use-pathname

# おわりに
どちらもv13で登場した方々らしいですが、意外と知らなかったです。
現時点で早くもv15になっていますが、どんどんアップデートされていくのでついていけるように頑張ります
IBM i Services Directory : QSYS2.NETSTAT_Interface_Info ビュー

このIBM iの通信インターフェース（LANアダプター）のステータスを返します。（ただし、アクティブなインターフェースに対してのみ。非活動状態（IPアドレスをオンにしていない）のインターフェース情報は返しません。）CLコマンドのNETSTATコマンドからオプション1(IPV4) and/or オプション4(IPV6）と同様なカラム情報を返しますが、1つのIBM i 側のIPアドレスに対して1行を返す点がNETSTATコマンドと異なります。
※NETSTATコマンドと同様にポート毎の情報を返すのは、[QSYS2.NETSTAT_Info ビュー](https://qiita.com/gomAnomalocaris/items/446fdfe7380c4c291f33)になります。

## 概要
■ビュー名：QSYS2.NETSTAT_INTERFACE_INFO
■カテゴリ：通信サービス
■サポート：IBM i 7.2 SF99702 Level 9, SF99702 Level 11以降 で拡張
■参照URL（IBM i 7.5）：https://www.ibm.com/docs/ja/i/7.5?topic=services-netstat-interface-info-view

## 実行例①

```
  SELECT * FROM QSYS2.NETSTAT_INTERFACE_INFO ;
```

WHERE句に何もしていないと、こんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/d3e91924-1832-4c4f-80f7-75c32c718fd7.png)

VLAN ID等もみえますね。5250のNETSTATコマンドより詳細な情報が一発で取れるのはIBM i サービスならではです。

※IPアドレスは意図的に外しています(^^;

### 実行例②

マニュアル記載のサンプルはこちらWHERE句にVETHを指定しています。
```
  SELECT * FROM QSYS2.NETSTAT_INTERFACE_INFO 
  WHERE INTERFACE_LINE_TYPE = 'VETH' ;
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/996335d0-15ac-4f9f-9476-e1079e64a1b1.png)

このインターフェースタイプという属性には、、

| LINEタイプ（プロトコルタイプ） | 説明 | コメント |
|:-:|:-:|:-:|
| ASYNC | 非同期通信プロトコル | 昔懐かしBSC通信とか無手順通信用のLINE定義など |
| ELAN | イーサネットプロトコル | VETHも別にあるのでこちらは物理イーサネットカードの方？ |
| L2TP | レイヤー２トンネリングプロトコル | |
| PPP | PPP通信用 | |
| PPPOE | PPP over イーサネット通信用 | |
| VETH | 仮想イーサネットプロトコル |仮想イーサアダプター用 |
|:-:|:-:|:-:|
| ERROR | 現在サポートされていない回線タイプなど？ | |
|NONE|回線記述が作成されていないケース|*LOOPBACK, *VIRTUALIP, *OPCの場合|
|NOT FOUND|このインターフェース用のLINDが見つからない場合||

## 参考：5250 NETSTATコマンドの実行結果例

5250 NETSTAT コマンドでは画面サイズ制約がありますので、こんな感じにサマリー表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/bd26a5fc-6dbb-4761-bd63-721a985b86df.png)

更に上記画面から詳細を確認したい接続について オプション5 詳細の表示　を選択すると詳細情報が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/b7a2536d-ac05-4f11-9f7c-1f3ebce76e83.png)

この際表示される詳細情報もポート接続に直接関連する詳細情報（リモート側のIP,ホスト名他、TCP/IPパケット送受信情報など）が主で、NETSTAT_INTERFACE_INFOビューで取得できる付帯情報（たとえばVLAN ID やDHCP関連情報など）は取得できないようです。
LiNGAMとは？

LiNGAM (Linear Non-Gaussian Acyclic Model) は、因果推論における手法の一つで、特に**観測データから因果関係を特定するためのモデル**として知られています。これは、従来の統計的手法や構造方程式モデリング（SEM）とは異なり、特定の仮定のもとで**因果関係を一意に決定できる**点が特徴です。
※この記事は、ChatGPTの出力を基に作成しています。

---

## 1. **LiNGAMの基本概念**
LiNGAMは、次のような線形モデルを前提としています。

$\ X = B X + e \$

ここで、
- **$X\$**: 観測変数のベクトル
- **$B$**: 因果構造を表す係数行列（**非巡回行列（DAG）**）
- **$e$**: 外生変数（**独立な非ガウス分布のノイズ**）

LiNGAMの核心となる仮定は以下の3つです：

1. **因果構造はDAG（有向非巡回グラフ）である**  
   → 変数間の関係に循環がない（ループなし）。
   
2. **線形モデルである**  
   → 変数間の関係は線形で記述される。
   
3. **ノイズ（誤差項）は非ガウス分布であり、相互に独立である**  
   → これはLiNGAMの大きな特徴であり、因果方向を一意に特定できる根拠となる。

この非ガウス性の仮定により、従来の**独立成分分析**（ICA: Independent Component Analysis）の手法を応用して因果関係を特定できる。

---

## 2. **LiNGAMの特徴**
### ◉ 従来の手法（回帰分析やGranger因果など）との違い
- 従来の回帰分析では、単なる相関関係しか捉えられず、因果関係の方向は決定できない。
- Granger因果は時系列データ向けであり、データの順序を利用しないと因果関係を特定できない。
- LiNGAMは「ノイズの非ガウス性」を利用することで、**相関ではなく因果方向を識別できる**。

### ◉ DAGベースの因果推論との違い
- Bayesian Network（ベイジアンネットワーク）などのDAGベースの因果推論手法では、事前情報や介入実験を用いない限り因果方向を特定するのは難しい。
- 一方、LiNGAMはデータのみに基づいて**因果関係の方向を一意に推定できる**という強みがある。

---

## 3. **LiNGAMの種類**
LiNGAMにはいくつかのバリエーションが存在します。

### ① **ICA-LiNGAM**
- **独立成分分析（ICA）** を用いて因果方向を推定する基本的なLiNGAMの手法。
- ただし、変数の数が多い場合やサンプル数が少ない場合には、推定精度が下がる可能性がある。

### ② **DirectLiNGAM**
- 逐次的に因果関係を推定する手法で、ICAを使わずに直接推定する。
- ICA-LiNGAMよりも計算量が少なく、精度も向上するケースが多い。

### ③ **Time-series LiNGAM（時系列LiNGAM）**
- 時系列データに適用可能な拡張版。
- 動的な因果関係を捉えられる。

---

## 4. **LiNGAMの応用例**
LiNGAMは、次のような分野で応用されています。

- **経済・金融**: 金利、株価、GDPなどの変数間の因果関係の解析。
- **医療・バイオ**: 遺伝子発現データや疾患の原因分析。
- **社会科学**: 教育、政策評価、消費者行動分析。
- **マーケティング**: 広告投資が売上に与える因果関係の特定。

---

## 5. **LiNGAMの実装**
LiNGAMはPythonの`lingam`ライブラリを使って簡単に実装できます。

### ◉ インストール
```python
pip install lingam
```

### ◉ 実装例
```python
import numpy as np
import lingam

# ダミーデータの生成
np.random.seed(42)
X1 = np.random.uniform(size=100)
X2 = 2 * X1 + np.random.uniform(size=100)  # X1 → X2 の因果関係
X3 = 3 * X1 + np.random.uniform(size=100)  # X1 → X3 の因果関係
X = np.column_stack([X1, X2, X3])

# LiNGAMの適用
model = lingam.DirectLiNGAM()
model.fit(X)

# 因果関係の推定結果（因果構造行列）
print(model.causal_order_)  # 推定された因果順序
print(model.adjacency_matrix_)  # 因果係数行列
```
このように、`DirectLiNGAM()` を適用することで、**データから因果順序を特定** できます。

---

## 6. **LiNGAMの限界**
LiNGAMは強力な手法ですが、いくつかの前提条件や制約があります。

1. **線形性の仮定**
   - LiNGAMは線形関係を前提としているため、非線形な因果関係をうまく表現できない。
   - 非線形関係に対応するための拡張版（例えばNonlinear LiNGAM）も研究されている。

2. **ノイズの非ガウス性の前提**
   - データのノイズがガウス分布に近い場合、因果方向の特定が難しくなる。

3. **データのスケール**
   - 変数のスケールが適切に調整されていないと、推定精度が低下することがある。

---

## 7. **まとめ**
- **LiNGAMは、非ガウス性を利用して因果関係の方向を特定できる手法。**
- **ICAや直接推定を用いたバリエーションがあり、特にDirectLiNGAMが実用的。**
- **経済、医療、マーケティングなど多くの分野で応用可能。**
- **線形性の仮定やデータの前処理に注意が必要。**

LiNGAMは「単なる相関分析ではなく、因果推論をデータから学習する」画期的な手法の一つです。興味があれば実データで試してみると面白いでしょう！
UiPathのホバーアクティビティで解決する方法_クリックしたふりをするのを解消したい

# こんなことに困っていませんか？？

- **とあるボタンをクリックし、タブを開いた後に別のボタンを押したいが、タブが閉じてしまう。**  
- **情報や画像がカーソルを外すと消えてしまう。**  
- **クリックしたはずなのに、エラーになった。**  
- **画像が押せず、エラーになる！**

---

## 始めに

上記のような現象に1日ほど悩まされ、解決したので共有します。  
本記事は筆者個人の見解に基づいて作成しており、最新情報でない可能性があります。ご了承ください。

---

## 問題の概要

あるサイトで、ログアウトができたりできなかったりする謎の挙動が発生しました。  
ログアウトに失敗するとエラーとなり、作業が止まってしまいます…これは困りますね！

そこで、解決策として **"ホバー"アクティビティ** を使用しました。

---

## "ホバー"アクティビティとは？

- 指定した UI 要素の上にカーソルを置く（UI 要素の上でホバーする）アクティビティです。  
（引用元：[UiPath公式ドキュメント](https://docs.uipath.com/ja/activities/other/latest/ui-automation/hover)）

### "ホバー"の役割

「ホバー」とは何か？
私も最初はピンときませんでしたが、要するにこういうことです。

- 次のアクションに移った際、**画像や情報が消えないようにする**。

---

## 問題の詳細と解決策

### フローの設計

今回のフローでは以下のような手順でログアウトを実現しようとしていました
1. **人の画像をクリック**
2. **ログアウトボタンが表示される**
3. **ログアウトボタンをクリック**

### 発生したエラー

- ログを見ると「人の画像はクリックできている」と表示されていました。  
- しかし、**ログアウトボタンのセレクターエラー**が発生。  
  → ログアウトボタンが押せない原因として、
  「人の画像クリック後に画面が閉じている」と考えました。

### 解決策

**人の画像をクリック → "ホバーアクティビティ" → ログアウトをクリック**  
このフローを組み直した結果、問題が解消され、正常にログアウトできるようになりました！

---

## "ホバー"アクティビティの活用場面

私の中で、"ホバー"アクティビティはこう定義しました。

- 予期せぬタイミングで画像や画面が変わってしまうのを防ぐ優秀なアクティビティ！

特に「特定の箇所をクリックした後、別のボタンを確実に押したい」場合に便利だと感じました。

### 活用例

例えば、Webサイトで、リソース＞RPAとはをクリックしたい時。
この画面が閉じてしまったら困りますよね、、、
そういう時に、 **検索ボックスにカーソルを合わせて情報を保持しつつ次の操作を行う**  
などが挙げられます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3934651/01eb0df7-adf6-b3f1-0656-50955bc87249.png)

引用元：https://www.uipath.com/ja/rpa/academy/faq

---

## 終わりに

再度お伝えしますが、本記事は個人の見解に基づいています。  

"ホバー"アクティビティは、UiPathの中でもあまり知られていないマイナーな機能かもしれませんが、非常に有用です！
クリックのプロパティを変更することも有効な手段なため、クリックのプロパティも確認してみてください。


ここまでお付き合いいただき、ありがとうございました！

＜参考文献＞
https://qiita.com/UmegayaRollcake/items/bf15d6463cbcb50d0886
https://blog-tips.sekenkodqx.jp/2020/10/12/uipath-activity-hover/
Swift学習：Optional型

## Optional型とは？
・「nil」を代入できるデータ型
・「nil」とは「値が無い値」という特別なもの
・「nil」になる可能性もある値であるとも解釈できる？

#### 記述例
```Swift
// Optional型の宣言
let int: Int = nil // コンパイルエラーが発生する
let optionalInt: Int? = nil // データ型の後ろに「?」を付ける

// nil以外の値も代入できる
let optionalString: String? = "Demogorgon"
```

## Optional型を使う時の注意点
・Optional型の変数や定数を参照する時は「nil」以外の値を取り出して使う！
・swiftは値が「nil」だとプログラムがクラッシュするので安全に取り出す方法がある！

　【取り出す方法】
 　１．フォースアンラップ
 　２．オプショナルバインディング
 　３．デフォルト値

#### 記述例
```Swift
// Optiona型を宣言
let optionalString: String? = "Demogorgon"

// フォースアンラップ
let nonOptionalString: String = optionalString! // 後ろに「!」を付ける
print(nonOptionalString) // "Demogorgon"を取り出せる

// オプショナルバインディング
// optionalStringが「nil」で無ければアンラップされてnonOptionaStringに代入される
if let nonOptionalString = optionalString {
    print(nonOptionalString)
}

// デフォルト値
// optionalStringが「nil」の場合は「Centaur」がgreekMonsterに代入される
let greekMonster: String = optionalString ?? "Centaur"
```
## メモ
フォースアンラップは有無を言わさず値を取り出すの「nil」が代入されていたらプログラムがクラッシュする。
オプショナルバインディングは値が「nil」の場合にはアンラップされないのでより安全です。

## 独り言
どのような場合にプログラム内の使うのかは正直まだ全く分からない！
Setting Up ViTPose for 2D Pose Estimation on Windows 11

# Summary
This guide outlines the setup process for **ViTPose**, a state-of-the-art 2D/3D pose estimation model, on a Windows 11 system with an RTX 4080 GPU. While the official documentation primarily supports Linux, this setup demonstrates a successful installation on Windows.

# Device Configuration
- Operating System: Windows 11 (Official support: Linux)
- GPU: NVIDIA RTX 4080
- NVIDIA Driver: 566.07
- CUDA Version: 11.1 ([Download CUDA 11.1.1](https://developer.nvidia.com/cuda-11.1.1-download-archive))
- cuDNN Version: 8.0.5 ([Download cuDNN 8.0.5](https://developer.nvidia.com/rdp/cudnn-archive))
- Development Tools:
     - MSYS2 + MinGW-w64
     - Python: 3.7.16
     - Visual Studio: 2019
     - GCC: 14.2.0 (Rev2, Built by MSYS2 project). 
     - System PATH: MinGW-w64 is added to Windows' system PATH


| Library | Version |
|---------|---------|
| **PyTorch** | 1.9.0 + cu111 |
| **TorchVision** | 0.10.0 + cu111 |
| **MMCV (mmcv-full)** | 1.3.9 |
| **MMPose** | 0.24.0 |
| **OpenCV** | 4.11.0 |
| **xtcocotools** | 1.14.3 |
| **timm** | 0.4.9 |
| **scipy** | 1.7.3 |
| **openmim** | 0.3.9 |
| **opencv-python** | 4.11.0.86 |
| **opencv-contrib-python** | 4.11.0.86 |
| **numpy** | 1.21.6 |
| **matplotlib** | 3.5.3 |
| **json-tricks** | 3.17.3 |

# Installation Steps

```
conda create -n vitpose_official python=3.7.6 -y
conda activate vitpose_test
conda install pytorch==1.9.0 torchvision torchaudio cudatoolkit=11.1 -c pytorch -c nvidia
pip install timm==0.4.9 einops
pip install matplotlib==3.5.3
pip install scipy==1.7.3
pip install json-tricks==3.17.3
pip install numpy==1.21.6

% clone ViTPose 
git clone https://github.com/ViTAE-Transformer/ViTPose.git
cd ViTPose
git clone https://github.com/open-mmlab/mmcv.git
cd mmcv
git checkout v1.3.9
set MMCV_WITH_OPS=1 
pip install -e .
======
(maybe below code also okay)
pip install -U openmim
mim install mmcv-full==1.3.9
=====
cd ..
git clone https://github.com/open-mmlab/mmpose.git
cd mmpose
pip install -r requirements.txt
pip install -v -e .
cd ..
pip install -v -e .
WebSocket connection to 'ws://localhost:8080/app/***?protocol=7&client=js&version=8.4.0&flash=false' failed:

## 概要
Laravel Reverbを使おうと思い、開発環境を立ち上げたのですが、ブラウザのコンソールに上記タイトルのエラーが出るので、その時の対応をメモしておきます。

## 前提
・開発環境での話です。Docker+Sail(Ubuntu)
・Laravelバージョン：11

## 解決策
・docker-compose.ymlのports設定のところでReverbのポートを追加しました。

```shell:config/livewire.php（抜粋）
services:
    laravel.test:
        build:
            context: './vendor/laravel/sail/runtimes/8.4'
            dockerfile: Dockerfile
            args:
                WWWGROUP: '${WWWGROUP}'
        image: 'sail-8.4/app'
        extra_hosts:
            - 'host.docker.internal:host-gateway'
        ports:
            - '${APP_PORT:-80}:80'
            - '${VITE_PORT:-5173}:${VITE_PORT:-5173}'
            - 8080:8080      # << ここを追加
        environment:
        　・
        　・
        　・
```
## 余談
REVERBをインストールしたときに設定されたREVERB_APP_KEY変数の値をデタラメな値に変えて試したんですけど、なぜか問題なく動いている。何か設定を間違えているのかな？と思いましたが、.envに設定した値とは違う値を使ってws://***にアクセスされた場合、アクセスを拒否するという感じですね。

コンソールから、以下のコマンドを使って、.envで設定された値と違う値でアクセスしたところ、ちゃんと拒否されました。
```shell:コンソールでの実行コマンド
wscat -c 'ws://IPアドレス/app/REVERB_APP＿KEYの値?protocol=7&client=js&version=8.4.0&flash=false'
```
OLVM4.5のリリース

みなさん、こんにちは！
今回もOracle Linux KVM/OLVMについての投稿となりますが、検証系の記事ではなくOLVM新バージョンとなるOLVM4.5についての記事になります。
■基本シリーズ
第1回：[Oracle Linux KVMとOLVMについて](https://qiita.com/ReQ_HY/items/bc6cb0d909bfa0fcdae6)
第2回：[Oracle Linux KVM 要件と構築について](https://qiita.com/ReQ_HY/items/b7f8ea4fde65f4dc7a34)
第3回：[OLVM構築 - セルフホステッドエンジン方式](https://qiita.com/ReQ_HY/items/82ad79dc48c7253c53fa)
第4回：[OLVM構築 - スタンドアロン方式](https://qiita.com/ReQ_HY/items/ebba85d163a5dba62790)
第5回：[OLVM - Oracle Linux KVM追加・設定](https://qiita.com/ReQ_HY/items/94158cca701e0cae28be)
第6回：[OLVM - 仮想マシン作成](https://qiita.com/ReQ_HY/items/5a0c4d554c5e3b7d6514)

■番外シリーズ
第1回：[OLVMとen_US.UTF-8](https://qiita.com/ReQ_HY/items/651f208c6c4478bfba2b)
第2回：[NFSを使用したOLVMデプロイ検証記](https://qiita.com/ReQ_HY/items/6f778a7b1d779d8f4c53)

※まだご覧になられていない場合、ぜひご覧ください！

## OLVM4.5リリース
現在OLVMの主流は4.4だと思いますが、新バージョンとなるOLVM4.5も2023年12月12日にリリースされています。
■Oracle Virtualization Blog
[Oracle Linux Virtualization Manager delivers enhanced monitoring and reporting](https://blogs.oracle.com/virtualization/post/oracle-linux-virtualization-manager-delivers-enhanced-monitoring-and-reporting)

## OLVM4.5新機能
詳細はOracle公式ブログをご確認ください。公式ブログより引用した内容を以下に記載いたします。

1.スナップショットの強化

2.ユーザーインターフェースと利便性のアップデート
2-1.vNIC プロファイルの新しい検索ボックス追加
2-2.仮想マシンを一時停止する時に確認ポップアップが表示
2-3.MACアドレスプールの空きと利用可能なアドレスが設定した閾値を下回った場合に新しい警告イベントが発生
2-4.ホストエンジンのホスト数が推奨最大数を超えたときに新しい警告が発生
2-5.クラスターアップグレードの進行状況トラッキングステータスが追加

3.新しいクラスターバージョン4.7利用可能へ

4.分散スケジューリングポリシーアップデート

5.ストレージドメインの改善

6.コンソール切断の新しい遅延パラメータ追加

7.ovirt-engine-renameのサポート

## OLVM4.5 ドキュメント
英語：[OLVM4.5、OLVM4.4](https://docs.oracle.com/en/virtualization/oracle-linux-virtualization-manager/index.html)
日本語：[OLVM4.5、OLVM4.4](https://docs.oracle.com/cd/F30061_01/)

## OLVM4.4と4.5の比較
OLVM4.4と4.5で比較した際に、異なる箇所をピックアップしてみました。
※詳細は公式ドキュメントをご確認ください。
**OLVM - OS**
| 項番 | バージョン | OS |
|:-|:-|:-|
|  1 | 4.4  |  Oracle Linux 8.5またはそれ以降 |
|  2 |  4.5 | Oracle Linux 8.8またはそれ以降  |

**KVM Host - OS**
| 項番 | バージョン | OS |
|:-|:-|:-|
|  1 | 4.4  |  Oracle Linux 8.5またはそれ以降 |
|  2 |  4.5 | Oracle Linux 8.8またはそれ以降  |

**KVM Host - 環境**
| 項番 | バージョン | 環境 |
|:-|:-|:-|
|  1 | 4.4  | 指定なし |
|  2 |  4.5 | オンプレミス環境のみ  |

**OLVMリリースパッケージ**
| 項番 | バージョン | パッケージ |
|:-|:-|:-|
|  1 | 4.4  | oracle-ovirt-release-el8 |
|  2 |  4.5 | oracle-ovirt-release-45-el8  |

**リポジトリ**
| 項番 | バージョン | リポジトリ |
|:-|:-|:-|
|  1 | 4.4  | ol8_ovirt44　ol8_ovirt44_extras |
|  2 |  4.5 |ovirt-4.5　ovirt-4.5-extra  |

**KVM HostがUEK R7の場合**
| 項番 | バージョン | 実行コマンド |
|:-|:-|:-|
|  1 | 4.4  | 特になし |
|  2 |  4.5 |dnf install kernel-uek-modules-extra  |

**OLVM - セルフホステッドエンジン方式のデプロイコマンド**
OLVM4.5-セルフホステッドエンジン方式のデプロイではOLVM4.4と異なり
デフォルトでIPv6が使用されるため、IPv4を使用する場合はオプション "--4"が必要となります。
| 項番 | バージョン | 実行コマンド |
|:-|:-|:-|
|  1 | 4.4  | hosted-engine --deploy |
|  2 |  4.5 |hosted-engine --deploy --4|

## 最後に
日本語のドキュメントがOLVM4.4までしかないため最新は4.4だと勘違いしてしまいそうですが、実はOLVM4.5もリリースされているんです！というのをOLVMを導入されているユーザーの皆様に知って頂きたく今回技術ブログの方へ掲載させて頂きました。

OLVMのバージョンアップやOracle Linuxのメジャー・マイナーバージョンのアップグレードに関しても弊社で対応可能ですので、是非お問い合わせください！
Swift学習：Array型

## Arrayとは？
・複数の値を格納できる箱
・個々の値を「エレメント」と呼ぶ。
・各エレメントにはインデックスとよばれる番号が付いている。

#### 記述例
```Swift
// Array型の作成
let stringArray: Array<String> = ["A", "B", "C"]
let intArray: Array<Int> = [10, 100, 1000]
```

## Arrayのメソッド
・メソッドを使用して各エレメントを操作できる。

```Swift
// Arrayを作成
let stringArray: Array<String> = ["A", "B", "C"]
let intArray: Array<Int> = [10, 100, 1000]

// 値を参照
let getA: String = stringArray[0] // インデックスは左端からゼロで始まる
let get1000: Int = intArray[2]

// 新しい値を追加する
stringArray.append = "D" // ["A", "B", "C", "D"]になる
intArray.append = 10000 // [10, 100, 1000, 1000]になる

// 最後の値を削除する
stringArray.remove(at: 0) // "D"が消える
intArray.remove(at: 2) // 10000が消える

// 値を操作する
let mappedStringArray: Array<String> = stringArray.map({ $0 + "!"}) // ["A!", "B!", "C!"]になる
let mappedIntArray: Array<String> = intArray.map({ $0 + 10}) // [20, 110, 1010, 10010]になる
```

## 独り言
Array型で使用できるメソッドは沢山有るので調べないと....！
PHP の 定数 では end を使えない

# 結論

定数として定義している配列から最後の要素のキーや値を取得したい場合は、array_key_last を使いましょう。

# 再現

```php:定数の配列に end は使えない
class Test {
  const NUMBERS = [10,20,30];
  function __construct()
  {
    // 期待値は 30
    echo end(self::NUMBERS);
  }
}
```

## はい、無理です

```xquery
Error - end(): Argument #1 ($array) cannot be passed
by reference in Test.php on line xxx
```

## なぜ？

end関数の引数は参照渡しで受け取る仕組みのため。
https://www.php.net/manual/ja/function.end.php

### Stack Overflow の質問コーナー

https://stackoverflow.com/a/49225170
end($s = Self::NUMBERS) のように1回変数に入れればいけるよ、と。

## PHP 8.0 では end($s = Self::NUMBERS) でもダメでした

Stack Overflow の参考ページは 6年前のものですし、今は使えないのかも。
全バージョンは試していませんが、
少なくとも PHP 8.0 では前述のトリックは使えませんでした。

```php:正解はコレ
class Test {
  const NUMBERS = [10,20,30];
  function __construct()
  {
    $last_key = array_key_last(self::NUMBERS);
    echo self::NUMBERS[$last_key];
  }
}
```
これで無事に「30」が返ってきます。

array_key_last は内部ポインタにも影響しないし、
配列の最後の要素を end で取得した場合は reset した方が良く、

どの道 2行にはなるので、array_key_last を使う方が無難ですね。
Angular のアナリティクスをグローバルで設定する方法


Angular では最初にコマンドを使用したときに `Would you like to share anonymous usage data with the Angular Team at ...` などと聞かれ、その結果に応じて `angular.json` に `cli.analytics` が追加される。
この設定はプロジェクトごとの設定だが、グローバルに設定したかった。

[ドキュメント](https://angular.dev/cli/analytics/disable)を辿れば書いてあるが、ググってもそのものは出てこなかったのでメモ。

有効にしたい場合:
`ng analytics enable --global=true`  
無効にしたい場合:
`ng analytics disable --global=true`

また、現在のグローバル、プロジェクトの設定は `ng analytics info` で両方確認できる。
LinuC学習

LinuCの勉強のし直しのため間違った箇所を記事化して理解を促す


## psコマンドについての問題
ps eを選択した
答えはps -fの実行結果が誤っている
ps -fは
UIDやPID,PPID等プロセスの詳細なリストをフルフォーマットで表示する
が正しい

ちなみにps fだと	実行されているプロセスの階層表示するとなる

ps eはコマンド名と環境変数を表示するとなり正しい

https://linuc.org/study/samples/5483/


## yumコマンドについての問題
パッケージの削除コマンド
yum remove httpdが正解

yum purge httpdは存在しない
purgeというコマンドはaptには存在するがyumには存在しないことに注意

https://linuc.org/study/samples/5580/

## ハードリンクとシンボリックリンク
ハードリンクとは？
Linux OSにおいて、1つの物理データを参照する複数のファイルを作る機能

inodeとは？
ファイルやディレクトリに関するメタデータを格納する情報のことです。具体的には、ファイルサイズ、所有者、アクセス権限、タイムスタンプなどの情報が含まれており、ファイルシステムはinodeによって物理的なデータの位置を特定します。

l:シンボリックリンク
ハードリンクに対してソフトリンクと呼ばれることもある
特徴として
・パスでファイルやディレクトリを参照(リンク元のポインタとして動作する)
・別のファイルシステムでも問題なく動作する
・ディレクトリに対しても有効
・元ファイルを移動するとデットリンクになる
・元ファイルを削除するとデットリンクになる

https://eng-entrance.com/linux-permission-link#i-4

https://www.freecodecamp.org/japanese/news/symlink-tutorial-in-linux-how-to-create-and-remove-a-symbolic-link/

## ファイルの配置と検索
wheresis　コマンドで出力される情報は
プログラムのソース、バイナリー、またはマニュアルの場所を出力する
設定ファイルは出力しない

https://www.ibm.com/docs/ja/aix/7.2?topic=w-whereis-command

## apt コマンドによるパッケージ管理

apt-cache
APTのパッケージキャッシュに対して、さまざまな操作を行うコマンド

depends:パッケージが持っている依存関係と、その依存関係を満たす他のパッケージの一覧を表示します。

showpkg:有効なバージョンと被依存関係を列挙し、さらに各バージョンについて依存関係を表示します。

rdepends:パッケージが持つ被依存関係を一覧表示します。 

policy:特定のパッケージに関連するインストール済みおよび利用可能なバージョンの情報、パッケージソースの優先度や、それぞれのパッケージの優先度を表示します。

https://linuc.org/study/samples/4932/

## 正規表現を使用したテキストファイルの検索

egrep '^[a-z]{2}[0-9]{4}$' test.txt
と
egrep '^[a-z]{2}[0-9]{4}' test.txt

$は正規表現の文末に対して機能する
12testAAAに対して
'^[a-z]{2}[0-9]{4}$'であれば12testが
'^[a-z]{2}[0-9]{4}'であれば12testAAAがヒットする

https://linuc.org/study/samples/4855/

## ハードディスクのレイアウトとパーティション

fdiskコマンドを用いたデバイスの削除
オプションを付けず、デバイス名だけを指定すると、対話形式でパーティションの作成・削除・変更等ができます


https://linuc.org/study/samples/4548/

## コマンドラインの操作

> setコマンドを使用すると、シェル変数の設定の確認や変更を行うことができます。
setコマンドでは、シェル変数と環境変数、両方の一覧を表示することが可能です。

> envコマンドは、引数を一切付けずに実行すると、現在指定されている環境変数を一覧表示します。シェル変数の一覧を表示することはできないため、不正解です。

https://linuc.org/study/samples/4494/

## RPMパッケージ管理

rpm
> Red Hat系のLinuxディストリビューションで使われている“RPM（Red Hat Package Manager）パッケージ”を扱うことができるパッケージ管理コマンド

https://atmarkit.itmedia.co.jp/ait/articles/1609/20/news019.html

コマンドオプション
-e
--erase パッケージ	
パッケージをアンインストール（削除）する

-V
--verify	
パッケージを検査する

-q	
--query	
問い合わせ（パッケージ情報の表示と検索）

-U	
--upgrade パッケージファイル名
パッケージをアップグレードする（「--install」と同じオプションが使用可能

-F
--freshen パッケージファイル名
以前のバージョンがインストールされているときのみパッケージをアップグレードする

https://linuc.org/study/samples/4407/
【Swift Concurrency】 `@preconcurrency` と `MainActor.assumeIsolated` の使い分け

Swift 6 への移行や、古いコードとの併用では「並行性チェック」をどう緩和・保証するかが大きな課題ですよね。そこで登場するのが **`@preconcurrency`** と **`MainActor.assumeIsolated`**。一見、どちらも「コンパイラやランタイムのチェックを回避する仕組み」に見えますが、**目的や動作タイミングがまったく異なります**。本記事では、それぞれの使い分けを解説します。

---

## 1. シチュエーション：古いコードとメインアクター

たとえば、あなたがゲームを作っているとします。

- ゲームエンジン (GameEngine): 昔からあるライブラリで作られている  
- 新しい Swift Concurrency: メインアクター（`@MainActor`）を使って画面更新を安全にしたい

このとき、古いゲームエンジンは「どのスレッド（アクター）で呼ばれるか分からない」状態のデリゲートを持っているかもしれません。すると、Swift 6 などの**厳しい並行性チェック**でエラーや警告が出ることがあります。

---

## 2. `@preconcurrency`：古いコードのコンパイルエラーを緩和する

### 2.1 どんなときに使う？

- 古いライブラリをインポートしたいけど、Swift 6 だとコンパイルエラーがいっぱい出て困るとき  
- ライブラリが「メインスレッドで呼ぶかどうか、昔の書き方であいまい」

ここで `@preconcurrency` を使うと、**コンパイラがエラーを警告にしてくれる** など、ビルドが通りやすくなります。

### 2.2 具体例

```swift
@preconcurrency import OldGameEngine
```

こう書くと、「このライブラリはコンカレンシーの新しいルールを完全には適用しないでね」とコンパイラに伝えることになります。

### 2.3 でも安全なの？

- 実行時にチェックはありません  
- メインアクターじゃないところでUIをいじっても、`@preconcurrency` は止めてくれません  
- 「コンパイルエラーを減らすだけ」で、根本的に安全になるわけではない

---

## 3. `MainActor.assumeIsolated`：実行時にメインアクター以外ならクラッシュ

### 3.1 どんなときに使う？

- 本当はメインアクターで呼ばれていると確信しているけど、コンパイラには証明できない場合  
- メインアクター以外から呼ばれると困るので、間違いならクラッシュさせたい

### 3.2 具体例

```swift
nonisolated func oldEngineCallback() {
    MainActor.assumeIsolated {
        // 実際にメインアクターじゃなかったら、ここでクラッシュ
        updateUI()
    }
}
```

nonisolated メソッド内で `MainActor.assumeIsolated` を呼ぶと、実行時に「メインアクターかどうか」をチェックし、違えば止まります。

### 3.3 クラッシュすることでユーザーデータ破損を防ぐ

- Swift Concurrency は「競合して壊すより、クラッシュで気づかせる」考え方  
- 実際にメインアクター以外で呼ばれたら即止まるので、データ破損を避けられる  
- ただし本当にメインアクター以外で呼ばれないと確信できるときだけ使う

---

## 4. 使い分けまとめ

### `@preconcurrency`

- **コンパイル時** の並行性チェックを緩和  
- 古いコードやライブラリでエラーを減らしたいとき  
- 実行時にメインアクターかどうかは確認しない

### `MainActor.assumeIsolated`

- **実行時** にメインアクターかどうかを強制チェック  
- 違えば即クラッシュしてデータ破損を防ぐ  
- 最終手段的な方法

---

## 5. どちらも正しい並行性に移行したほうがいい

- `@preconcurrency` は「とりあえず古いコードをビルド通す」だけで、実際の安全性を保証するわけではありません  
- `MainActor.assumeIsolated` は「ランタイムで強制的にチェック」する最終手段  
- いずれも「本来は `@MainActor`、`async`、`Sendable` などできちんと静的に証明できる形」が理想

---

## まとめ

- `@preconcurrency` はコンパイラに「古い仕組みだから厳密チェックしないで」と頼むための属性  
- `MainActor.assumeIsolated` は実行時に「ここはメインアクター」と強制し、違えば即クラッシュ  
- どちらも暫定措置としては便利だが、最終的には正しい並行性モデルにリファクタリングするのが望ましい
MQTT: 異なるプロトコルで、同一のブローカーとトピックに接続

次を確認してみました。

```text
同一のブローカーとトピックに対して、異なるプロトコルでサブスクライブしても、
受け取るメッセージの内容は同じです。
```

ブローカー　wss://broker.hivemq.com:8884/mqtt

トピック　testaa/topic

## Publish

こちらの方法で、Web で行いました。
[WebブラウザでパブリックMQTTサーバーに接続](https://qiita.com/ekzemplaro/items/f2e8d260826d4712b575)

## Subscribe

MQTT

```bash
BROKER="broker.hivemq.com"
#
mosquitto_sub -d -t orz -h $BROKER \
    --topic testaa/topic
```

MQTT over WebSocket Secure

```js:subscribe.js
const mqtt = require('mqtt');


const brokerUrl = 'wss://broker.hivemq.com:8884/mqtt'
const topic_sub = 'testaa/topic'

// MQTT クライアントの作成
const client = mqtt.connect(brokerUrl)

client.on('connect', () => {
  console.log('Connected to MQTT broker')

  // トピックをサブスクライブ
  client.subscribe(topic_sub, (err) => {
    if (!err) {
      console.log('Subscribed to ' + topic_sub)
    }
  })
})

client.on('message', (topic, message) => {
  console.log(`Received message on ${topic}: ${message.toString()}`)
})

client.on('error', (err) => {
  console.error('Connection error:', err)
})
```

実行コマンド

```bash
export NODE_PATH=/usr/local/lib/node_modules
#
node subscribe.js
```
gitで間違えてコミットしてしまったときに試したいこと

（プログラム修正）
カタカタバチーんEnterキーで決めたった
```
git commit -m "これで仕事終わり"
```

やったと思ったが束の間、よく見ると変更が間違っている…

ここで思いつくこと
１。もう一度ファイル修正するか
２。コミットを打ち消すか　(git revert 間違ってコミットしたときのコミットID)

２の方法を使うとコミットを打ち消すコミットを作ってくれている。
ファイルはこのコミットで行った変更前の状態に戻ります。
WebアプリケーションのUIテストの自動化実現

1.Selenium WebDriverの簡単な紹介
みなさん、Seleniumという技術をご存知ですか？
Seleniumとは、Webアプリケーションのテストを自動化するためのフレームワークやライブラリです。Seleniumは、Selenium IDE、Selenium WebDriver、Selenium Grid等、様々な種類がありますが、今回は、Selenium WebDriverについて紹介していきます。このライブラリを使用してプログラミングをすることで、テストしたいWebアプリケーションへのアクセスから、Webブラウザ上のテキスト入力やボタン、リンクのクリック等のような動作を自動で行うことができます。また、元々は、テストを自動化するために作られましたが、Webスクレイピングを行って、Webサイト上のデータの収集をしたり、RPAツールとして利用し、データ入力や定期的なレポート作成を自動化したりできます。

2.Seleniumを使用するメリット・デメリット
2-1.Seleniumを使用するメリット
2-1-1回帰テストの効率化
頻繁に機能改修があるWebアプリケーションでは、機能改修した箇所以外への影響確認（回帰テスト）をする必要があります。開発中でも、テストは全て合格して終わっているが、一部機能を変更したため、その影響確認のため再テストをしなければいけなくなってしまったなんてことはよくある話です。そこで、Seleniumを使用することによって、一度プログラムを書いてしまえば、ワンクリックで、短時間で動作確認できてしまいます。

2-1-2大量データを使用した負荷テスト
私が一番魅力的に感じているメリットかもしれません。最大桁数やデータを大量件登録する等の試験項目の際は、データを作るのがなおのこと大変ですよね？そんなときでも、最大桁数の場合は、プログラム内で、ループ処理を活用して最大桁数データを作成したり、大量件数のデータ登録のテストでも、登録する動作をループで実行すれば、手動で確認するまでもなくテストできます。

2-2.Seleniumを使用するデメリット
2-2-1.自動テストを作るために、学習コストと時間が大幅にかかる
Selenium WebDriverで、自動テストを作るためには、C#などのプログラミング言語の知識はもちろん、CSSセレクタの仕組みや、WebDriverというライブラリの使い方について学習する必要があったり、テストしたい項目の要素を局所的に指定することが難しかったりします。自動テスト自体は早いのですが、自動テストを作るために、十分な学習とプログラム作成時の工夫が必要になります。

2-2-2.UIの頻繁な変更に対して対応が不向き
画面項目が増減したり、画面項目の要素の種類が変わったりした場合、もちろん自動テストのプログラムを修正しなければいけません。この変更が開発中頻繁に依頼されると、メインのプログラムとドキュメントの修正にまた一つ、自動テストのプログラムの修正が加わってしまいます。頻繁に変更される場合、変更対象が一つ増えるだけで、工数超過の原因になりかねません。

3.応用技で、エビデンス管理も楽になる!?
Xunitという単体テストのためのフレームワークがあります。こちらは、バックエンドのロジックが正しく書かれているかどうかをメソッド単位で確認するためのものですが、テスト対象のメソッドにUIテストを行うメソッドを指定することで、検索系画面で出力されている値や登録処理後のDBの値を確認するときに画面の値をスクレイピングして、画面とDBの値をテストメソッド内で突き合わせて確認する自動テストが出来上がります。これにより、テストエクスプローラの実行結果自体がエビデンスとなるので、画面キャプチャのエビデンスを目で細かくみて品質管理をする必要がなくなり、お客様に納品する際も、テストエクスプローラのテストケースが全て合格している様子だけ見せることができれば、画面キャプチャよりも分かりやすいエビデンスとなります。

まとめ
Seleniumを使用するのに適している試験項目は、大量データを使用した負荷テストや複数回テストする可能性の高い画面に対してのテスト等が挙げられます。レイアウトの見た目の確認や1回しか行わないテストには不向きなので、そこは手動で確認する必要があるでしょう。企業によって開発工程の認識は異なると思いますが、開発工程でいえば仕様がある程度固まっていて、負荷テストの試験項目が多い総合テストあたりで使用すると効果的かと思います。
Vite と .env と mode と NODE_ENV

# はじめに

Vite での .env の扱いについてイマイチわからなかった点を調べて整理します。

# Vite での .env の扱いについて

通常の .env の管理とは違うようです。  
公式ドキュメントとしてはコチラ。  
https://ja.vite.dev/guide/env-and-mode

`.env` ファイルの項目に以下の説明があります。
```
.env                # 全ての場合に読み込まれる
.env.local          # 全ての場合に読み込まれ、gitには無視される
.env.[mode]         # 指定されたモードでのみ読み込まれる
.env.[mode].local   # 指定されたモードでのみ読み込まれ、gitには無視される
```

また、以下の説明があります。

> .env.*.local ファイルはローカル限定で、センシティブな変数を含めることができます。git にチェックインされるのを防ぐために、.gitignore に *.local を追加すべきです。

つまり、 .env や .env.[mode] はコミットされるのでセンシティブな変数 (パスワードやシークレットキーなど) は書かない。  
センシティブな変数は .env.local や .env.[mode].local に書く。

.env.local や .env.[mode].local のテンプレートファイルとして .env.local.template や .env.[mode].local.template ファイルをコミットすると良さそうです。  
(これは公式では言及されていない)

# [mode] とはなにか

これも同じドキュメント内で言及されていますがわかりにくい。
https://ja.vite.dev/guide/env-and-mode#modes

同じような概念で NODE_ENV があります。
どちらも development と production が定義されています。  
しかし、モードは NODE_ENV とは別の概念です。

### NODE_ENV

NODE_ENV はビルドの挙動を変更します。  
NODE_ENV=development を指定すると開発ビルドになり、コードが minify されないためデバッグしやすくなります。
ただし、ファイルサイズが大きくなるためパフォーマンスが悪くなり、コメントなどがソースコードから読み取れるため公開したくない情報が公開されてしまう懸念があります。
一方で NODE_ENV=production を指定すると本番ビルドになり、コードが minify されます。

Vite ではデフォルトでは `vite` (`vite dev`, `vite serve` と同様) コマンドを実行すると development に、 `vite build` を実行すると production になります。
`NODE_ENV=production vite dev` のように環境変数で変更することもできます。

コード上では以下のビルトイン定数で参照することができます。

- `import.meta.env.PROD`: {boolean} アプリがプロダクションで動作しているかどうか（`NODE_ENV='production'` で開発サーバーを起動するか `NODE_ENV='production'` でビルドしたアプリを実行する）。
- `import.meta.env.DEV`: {boolean} アプリが開発で動作しているかどうか（常に `import.meta.env.PROD` の逆）

### モード

Vite におけるモードは環境を指すものです。  
development と prodcution が想定されていますが、 staging など任意のモードを指定する事ができるようです。  
モードによって参照する環境変数を変えることが可能です。

Vite では NODE_ENV と同様に、デフォルトでは `vite` コマンドを実行すると development に、 `vite build` コマンドを実行すると production になります。
`vite dev --mode=production` のように `--mode` パラメータで変更することもできます。

コード上では以下のビルトイン定数で参照することができます。

- `import.meta.env.MODE`: {string} アプリが動作しているモード。

# 結論

- 開発環境向けの開発サーバー実行
  - `vite`
  - `vite --mode=development`
  - `NODE_ENV=development vite`
  - `NODE_ENV=development vite --mode=development`
- 本番環境向けの開発サーバー実行
  - `vite --mode=development`
  - `NODE_ENV=production vite`
  - `NODE_ENV=production vite --mode=development`
- 開発環境向けの開発ビルド
  - `NODE_ENV=development vite build --mode=development`
- 本番環境向けの開発ビルド
  - `vite build --mode=development`
  - `NODE_ENV=production vite build --mode=development`
- 開発環境向けの本番ビルド
  - `NODE_ENV=development vite build`
  - `NODE_ENV=development vite build --mode=production`
- 本番環境向けの本番ビルド
  - `vite build`
  - `vite build --mode=production`
  - `NODE_ENV=production vite build`
  - `NODE_ENV=production vite build --mode=production`

ややこしいなと思いました。
特定のユーザーだけOIDCに失敗してしまうのはなぜ？(答:言語設定)

# 発生事象
- 特定のユーザーだけOIDCで`redirect_uri`が一致してないエラーが出る
- ドメインは一致しているし、特に変なクエリが追加されているわけでもなさそう
- キャッシュクリアやシークレットモードを利用しても変化がない

# 原因
- アプリ側で言語をパスで分けていた
- ユーザーは想定した言語以外を利用していた
-> 結果、`redirect_uri`に言語idが含まれており、それが一致しない原因だった

# 対応
- `redirect_uri`の言語の箇所をワイルドカードにする

or
- 特定の言語の`redirect_uri`を追加する

# 敗因
- 正常に認証できるURIと失敗したURIを比較しなかった
    - すぐに見比べていれば気づいたはず…

# 対策
- スクリーンショットだけで判断せず、利用者からHARなどを入手し、実際のリクエストと比較して検証する
【React×Typescript】react-hook-formのdefaultValuesにハマった話

# はじめに
今回、TODOアプリを作っています。
そこで起きた問題と解決した内容について
備忘録として書いておきます。

# 今回ハマった事象について
TODOの中身を編集するために、モーダルを出し、
それぞれの`input`に値を持たせたいのに、
値が全然入ってこなかった。

`defaultValues`に値をちゃんと渡しているのになぜだろうと思い、
色々試行錯誤すると、ドキュメントに書いてありました。

`Important: defaultValues is cached at the first render within the custom hook. If you want to reset the defaultValues, you should use the reset api.`

どうやら最初にしかキャッシュされないらしく、動的にしたいならresetとか使ったほうがいいよと言われていた。


# 解決方法
```typescript
useForm<FormDataValidate>({
    defaultValues: defaultValues ?? {
      text: "",
      time: 0,
    },
  });
  useEffect(() => {
    reset(defaultValues);
  }, [defaultValues, reset]);
```
一部抜粋してみました。
useEffectを使ってこんな感じでやればOK

# おわりに

とにかくハマっていたので解決できてよかったです。
WordpressのCocoonにFont Awesome6のアイコンを使いたい

こんにちは
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

これはWordpressのCocoonテーマにFont Awesome6のアイコンを適用するためのメモです。
CocoonはFont Awesome5までは公式で対応しているのですが6は対応していないので、プラグインを導入しないと使用出来ないっぽいです

# Font Awesomeとは？
Wikipediaには以下の記載あり。
LESSとは"Leaner Style Sheets"の略で、CSSの拡張のために使われる言語らしいですね。
知りませんでした。

>Font Awesomeとは、CSSとLESSをベースとしたフォントとアイコンのツールキットである。

https://ja.wikipedia.org/wiki/Font_Awesome

公式サイトは以下

https://fontawesome.com/



Font Awesomeのバージョン5までであれば、Cocoon設定>全体タブのサイトアイコンフォントの以下の部分を変更することで適用することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/4a26e1f5-974d-4177-b7a0-376211e8a83b.png)

ただし「Font Awesomeの6にしかアイコンがないんだが。。。」ということが時たまあるかもしれません。
私の場合「X（旧Twitter）のアイコンを使いたいんだけど、Font Awesome5は無い！6だとあるんだけど・・・」といった状態に陥りました。
以下がそれを示しているものです。
右側のバージョンが5.15.4だとTwitterの旧アイコンはありますが、新しいアイコンはありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/3ffdd326-58a8-4074-8ece-9b2113d56c9e.png)
一方でバージョンを6.7.2にすると新アイコンも使えそうだということがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/df013bf1-ad41-49a9-afaf-fd35f27c77a5.png)


解決策としてはWordpressのプラグインであるFont Awesomeを導入するといいっぽいです。
これをインストールして有効化します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/9346e306-8f7e-4c44-bc18-c18083e959a0.png)
設定はデフォルトのままです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/03287dd7-c132-4473-a962-762d7554fdf6.png)
このように設定を入れておくとFont Awesome6のものもWordpressに表示されるようになりました。
![test02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/c48df9c3-256d-46ac-9e7e-012b9a73b1ef.png)
ちなみに、プラグイン有効化前は以下のような表示になってしまっておりました。
Xのアイコンが表示されておりませんね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/a4dcd2ec-e6b0-4517-b8a1-dfaf68f0d0a9.png)
コードを生成しないコレクション。今度こそ完成です。

うーん、まあ、特に必要ない機能です。組み込みとかのマイコンでは一応使えるかもしれません。
mapでは旨味がないです。ハッシュキーの生成に静的な型が必要なため。
listはかなりコードの生成を抑えられます。マイコンでは重要だ思います。
mapも一応各オブジェクトにget_hash_keyの関数ポインタを渡すようにすれば、mapも
コードの生成量が抑えられますが、その分全体的に遅くなるはずです。
version 14.0.0で使えます。一応サンプル

```C 
#include <comelang.h>

struct sData
{
    int a;
    int b;
    string c;
};

struct sData2
{
     string a;
};

int main(int argc, char** argv)
{
    list<sData~>*% li = new list<sData~>();

    li.add(new sData~ { a:1, b:2, c:s"WIN" });

    list<sData2~>*% li2 = new list<sData2~>();

    li2.add(new sData2~ { a:s"WIN2" });

    puts(li[0].c);

    puts(li2[0].a);

    return 0;
}
```

このコードではlist<sData~>とlist<sData2~>のメソッドは同一コードが生成されます。
内部的にはvoid*として生成しています。その代わり要素の生成の時にnew sData~などとして
clonerとfinalizerを動的にオブジェクトに持たせてます。
new sDataとするとメモリリークが起こると思います。
一応セルフホストでも使っていて、2000行程度、生成コードが減ってました。
まあ、また気が向けばmapの方もコードを生成しないようにして、生成コードの量を減らすかもしれません。
ただ、全体的にシステムの速度は遅くなると思います。
Rustよりかなり簡単にコードを生成しないようにできるので、ちょっと自慢の機能です。
まあ、個人的には頑張りました。マイコンでcomelangが使い物になるようにしたいため。
マイコンはプログラムのサイズがデカくなりすぎるとダメですしね。
といってもマイコンでは僕もC言語使ってりゃいいと思いますけどね。ぶっちゃけると。
comelangを動かすというロマンでやってます。
XIAO ESP32C6のLチカ

# はじめに
XIAOの ESP32C3 の評判が良いので試してみようかと思ったのだが、新商品のESP32C6が出ていたので C6 を購入。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203949/2b83d265-cc83-459a-9b4f-4418ec174626.png" width=50%>

# 購入
スイッチサイエンスにて ￥1,148 （税込）で購入。
[Seeed Studio XIAO ESP32C6](https://ssci.to/9688)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203949/2cc502fd-3cb1-43d5-b78b-6693e4880c20.png" width=50%>

# セットアップ
PC(Windows10) に USB type-C で接続すれば認識した。

## Arduino IDE

ArduinoIDE(2.3.4)で、ファイル ＞ 基本設定 ＞ 追加のボードマネージャのURL： に
```https://espressif.github.io/arduino-esp32/package_esp32_index.json```
を追加する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203949/f55b904a-ad5d-4174-aa69-3a1d4d917c32.png" width=50%>

ツールバー上のプルダウンから「他のボードとポートを選択」をクリックし
「XIAO_ESP32C6」と「（接続したtype-cのCOMポート）(USB)」を選択してOK。
（XIAO_ESP32C6が表示されないようなら、ArduinoIDEを再起動してみる）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203949/7d0425b5-73f3-415e-8bcc-b4187438277c.png" width=50%>

# Lチカ
ファイル ＞ スケッチ例 ＞ 01.Basics ＞ Blink を選択。
そのままでも動くけど、delayを100 ぐらいにした方がいい。初期で接続するとすでにオレンジLEDが点滅をしており、本当に書き込めたが分かりづらい。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203949/d9a36a83-80af-41e1-a783-09ce99cdb549.png" width=50%>

書き込みボタンをクリックするだけで、書き込める！ボード上のBOOTボタンやRESETボタンを押す必要はなかった。とても簡単！初回書き込みは1分ぐらい掛かる。2回目以降は20秒程度。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203949/02278c55-401b-48bd-a106-700b3a1e5e10.png" width=30%>

# おわりに
いやーホントに小さい。今までESP-WROOM-32-Devkitを使っていたので雲泥の差。WROOM32の方がピン数も多いし開発はしやすいけど実用的ではなかった。もうこれ一択になりそう。おそらくESP32C3よりC6の方が性能も良いし、C6が主流になると思う。値段は20円高いだけ。C3はピンヘッダなしのアンテナあり。C6はピンヘッダありのアンテナなし。どうやらC6の方はアンテナ性能が上がり、アンテナ無くても十分らしい。おそらくC3は問題があって添付せざるを得なかったのではないだろうか。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203949/1e1526d1-6d22-4961-8a56-b4c1f0983e57.png" width=50%>

次回は、WiFi／バッテリー駆動／DeepSleepなど。
【Swift Concurrency】安全に画面更新！メインアクターへのジャンプとは？

Swift で UI を操作するコードは、同時にいろいろな処理が動いていても **メインスレッド** だけで動かしたいですよね。そんなときに使われるのが `@MainActor` です。ですが、バックグラウンド処理から画面を更新したいとき、いったいどうやって「メインアクター」に移動すればいいのでしょう？　それを実現するのが **「メインアクターへのジャンプ」** です。

本記事では、中学生にもわかるように、できるだけやさしく解説してみます。

---

## メインアクターとは？

- **アクター** とは、Swift Concurrency でデータ競合（データが同時に書き換えられてしまうバグ）を防ぐための仕組みです。  
- **メインアクター（@MainActor）** は、UI を扱う処理を「メインスレッド」でだけ動かすためのアクターです。

iOS のアプリ開発では、UIKit や SwiftUI で画面を更新する処理は、**必ずメインスレッド** で行う必要があります。Swift Concurrency では、`@MainActor` を使うことで、そのメソッドやプロパティを **メインアクターに属する** と宣言できます。

```swift
@MainActor
func updateUI() {
    // メインスレッドで安全に画面を更新するコード
}
```

こう書くと、Swift は「この関数はメインアクター（メインスレッド）でしか呼んじゃダメ！」とチェックしてくれます。

---

## メインアクターへのジャンプとは？

### バックグラウンドからメインへ切り替える

たとえば、ネットワーク通信や重い計算をしている「バックグラウンド処理」から画面を更新したいとき、直接メインアクターの関数を呼ぼうとすると Swift Concurrency が怒ってきます。

> 「いまバックグラウンドにいるのに、メインアクターの関数を同期的に呼んじゃダメ！」

そうならないように、**`await` を使ってアクターを切り替える** のが「メインアクターへのジャンプ」です。

```swift
@MainActor
func updateUI() {
    // 画面を更新するコード
}

func doSomethingInBackground() async {
    // バックグラウンドで処理
    // ...

    // 画面を更新したい！ → メインアクターにジャンプ
    await updateUI()
}
```

`await updateUI()` と書くことで、呼び出し前に メインアクターへ切り替わって、安全に画面更新ができるようになります。

---

## 具体的なジャンプ方法

### 1. `await` 付きで呼び出す

単純にメインアクターな関数を `await` で呼び出す方法です。

```swift
@MainActor
func updateUI() {
    print("画面を更新します！")
}

func backgroundTask() async {
    // バックグラウンド処理
    // ...

    await updateUI() // メインアクターへジャンプして画面更新
}
```

### 2. `await MainActor.run { ... }`

複数の処理をまとめてメインアクターで実行したいときは、`MainActor.run` が便利です。  
ブロックの中はすべてメインアクター上になるので、UI 更新コードをまとめられます。

```swift
func backgroundTask() async {
    // 重い処理...

    await MainActor.run {
        // ここはメインアクター上になる
        // UI関連のコードをまとめて書ける
        updateLabel()
        showMessage()
    }
}
```

### 3. `Task { @MainActor in ... }`

新しくタスクを作って、そのタスクがメインアクターで動くようにする方法です。  

```swift
func doSomething() {
    Task { @MainActor in
        // ここはメインアクター上で動く
        updateUI()
    }
}
```

「いまこの瞬間にメインアクターで実行したいコード」を書く場合に使えます。

---

## なんで安全なの？

- **メインアクター** は、画面を変える処理を順番に実行してくれます。複数の処理が同時に走って画面がごちゃごちゃになるのを防ぐ仕組みです。  
- **`await`** は、「ここでいったん処理を止めて、メインアクターに切り替わるのを待つ」印です。スレッドをブロックするのではなく、非同期的に順番待ちします。

もしメインアクターじゃないところから直接 UI をいじると、データ競合やクラッシュの原因になります。Swift Concurrency はこうしたミスを**コンパイルエラー**にしてくれるため、安全性が高いわけです。

---

## 気をつけたいポイント

1. **同期的に呼び出せない**  
   メインアクターな関数は、メインアクター外から「同期的」に呼び出すことはできません。必ず `await` を付けて呼び出すか、同じメインアクター内で呼ぶ必要があります。

2. **ジャンプを多用しすぎない**  
   いろんなところで頻繁に `await` 付き呼び出しをすると、コードが行ったり来たりでわかりにくくなる場合も。なるべく `MainActor.run { ... }` でまとめて書くなど、設計を工夫しましょう。

3. **`MainActor.assumeIsolated` は最終手段**  
   「ここは絶対メインアクター上だよ！」と無理やり教える方法もありますが（`assumeIsolated`）、もし実際はメインアクターじゃなかったらクラッシュします。なるべく `@MainActor` や `await` を使った正式な方法をおすすめします。

---

## まとめ

- Swift で UI を更新するコードは、**メインアクター** に隔離する（`@MainActor`）。
- バックグラウンド処理から画面を更新したい場合は、**「メインアクターへのジャンプ」** が必要。
- ジャンプの方法はいろいろあり、`await` 付き呼び出し、`MainActor.run { ... }`、`Task { @MainActor in ... }` などがある。
- こうすることで、UI がごちゃごちゃになる競合を防ぎ、安全に画面を更新できる。

**「メインアクターへジャンプ」** を正しく使って、非同期処理と画面更新を上手に両立させていきましょう！