OmniAICreator/Qiita-1.07M huggingface dataset:
[Python] SQS拡張クライアントライブラリ


SQS拡張クライアントライブラリ
--
SQSのペイロード256KB制限を超えたいときに利用できる拡張ライブラリ、最近Pythonでもライブラリが公開された。

S3を経由してメッセージを伝えているが、それらを隠蔽しているだけなので自作したほうがいいかもしれない



公式のチュートリアル
```python
import boto3
import sqs_extended_client

sqs_extended_client = boto3.client("sqs", region_name="us-east-1")
sqs_extended_client.large_payload_support = "S3_BUCKET_NAME" 
sqs_extended_client.use_legacy_attribute = False


```
これでもいいが、分かりにくいのとLinterに引っかかるためboto3.Sessionクラスを継承したSQSExtendedClientSessionを使うほうが好き。

```python
from sqs_extended_client.client import SQSExtendedClientSession

client = SQSExtendedClientSession().client("sqs")

client.large_payload_support = "<BUCKET_NAME>"
client.use_legacy_attribute = False

#送信
send_message_response = client.send_message(
    QueueUrl="<QUEUE_URL>",
    MessageBody=large_message
)
assert send_message_response['ResponseMetadata']['HTTPStatusCode'] == 200
#受信
receive_message_response = client.receive_message(
    QueueUrl="<QUEUE_URL>",
    MessageAttributeNames=['All']
)

```

Lambdaでポーリングしている場合は以下のようにしてメッセージを取得している
```python
from aws_lambda_powertools.utilities.batch import (
    BatchProcessor,
    EventType,
    process_partial_response,
)
from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord
from aws_lambda_powertools.utilities.typing import LambdaContext
from sqs_extended_client import SQSExtendedClientSession

processor = BatchProcessor(event_type=EventType.SQS)

client = SQSExtendedClientSession().client("sqs", region_name="ap-northeast-1")
client.large_payload_support = "<BUCKET_NAME>"
client.use_legacy_attribute = False
client.delete_payload_from_s3 = True 

def record_handler(record: SQSRecord) -> str:
    body = sqs_extend_client.retrieve_message_from_s3(record.body)
    
    #
    
def lambda_handler(event, context: LambdaContext):
    return process_partial_response(
        event=event,
        record_handler=record_handler,
        processor=processor,
        context=context,
    )

```

---

インストールするときの名前は`amazon-sqs-extended-client`です

`pip install sqs-extended-client`とすると開発が止まってしまった、よく似たライブラリがインストールされるので注意
困ったときのdiffコマンド！同一ファイル内でdiffをとる方法

同一ファイル内でdiffをとるコマンドについてまとめました。

## 結論
### コマンド
```
diff -u <(sed -n [開始行番号],[終了行番号]p [ファイル名]) <(sed -n [開始行番号],[終了行番号]p [ファイル名])
```

### 使用例
ファイル(test.txt)の中身
```
aaaaa
bbbbb

aacaa
bbbeb
```

コマンド
```
diff -u <(sed -n 1,2p ./test.txt) <(sed -n 4,5p ./test.txt)
```

実行結果
```
$ diff -u <(sed -n 1,2p ./test.txt) <(sed -n 4,5p ./test.txt)
--- /dev/fd/63  2023-05-31 08:18:30.290596341 +0900
+++ /dev/fd/62  2023-05-31 08:18:30.290596341 +0900
@@ -1,2 +1,2 @@
-aaaaa
-bbbbb
+aacaa
+bbbeb
```

## 同一ファイル内でのdiffをとるとは
先日とてつもなく長いファイルに出会いました。
このファイルには、同じような記述だけど、微妙に値が異なるケースがあり、
レビューするのに困っていました。
（微妙な差異を目視で判断するのは大変かつ事故の元になりかねない）

どうにかコマンドで実現できないかと本コマンドを作成しました。
もしほかにも同一ファイル内のdiffをとりたい方がいれば、ご参考いただければと思います。

## コマンドの解説
### diff
```
diff -u
```
diffは言わずもがな、ファイルの差分を取得するコマンドです。
`-u`オプションは、「Unified Format（統一形式）」と呼ばれるもので、差分行が先頭に「-」または「+」の記号とともに表示され、先頭に2つのファイル名が表示されます。
差分がみやすくなるので、普段のdiffからつけることをおすすめします。

### sed
```
sed -n 1,2p ./test.txt
```
sedコマンドは、指定したファイルを標準出力に出力するコマンドです。
`-n`オプションは、出力コマンド以外の出力を行わないという意味です。
`-n 1,2p`とすることで、1行目と2行目だけを標準出力に出力できます。

### プロセス置換
```
<(sed -n 1,2p ./test.txt)
```
プロセス置換とは標準出力をファイルのように扱うことができる機能で`<()`とすることで使用できます。
比較対象が両方とも標準出力に対してdiffをする場合、プロセス置換を使うことで比較できます。

## まとめ
いかがでしたでしょうか？
同じように長いファイルのdiffに困っている方の助けになれば幸いです
ラズベリーパイからラズベリーパイへバックアップの定期自動実行をやる。

## 概要
ラズベリーパイの常時稼働しているファイルサーバーに、アプリケーション兼DBサーバーの、アプリとDBのバックアップを自動で取得する。
↓ファイルサーバー

https://qiita.com/SHIJIMI_EN/items/f57c7a3d705805a6662c

↓アプリ兼DBサーバ

https://qiita.com/SHIJIMI_EN/items/e9bb7a9968739a3b6f61

## なぜラズパイでやるのか。
省電力が少ないため自宅でやる分には最適だと思っている。

どちらのラズパイにもsamba設定をしてください。

https://qiita.com/SHIJIMI_EN/items/9904ae0f17b5d329f192


## バックアップ元ラズベリーパイでの準備(アプリ兼DB)
SSHの有効化
```
sudo systemctl enable ssh
sudo systemctl start ssh

```



## バックアップ先の設定(ファイルサーバ)
```
sudo apt update
sudo apt install cifs-utils
```
バックアップ元マウント
username とpasswordはそのディレクトリにアクセスできる権限をもったアカウントを記述する。
versはsambaのバージョン。エラー出たら合わせる。
```
sudo mount -t cifs -o username=arisa,password=arisa,vers=2.0 //100.64.16.103/shared/Videos
```
バックアップ先マウント
```
sudo mkdir -p /mnt/backup_destination
```
```
sudo mount -t cifs -o username=arisa4,password=admin,uid=arisa4,gid=arisa4
```

### luckybackup のインストール
```
sudo apt install luckybackup
```
起動
```
luckybackup
```
こっからGUI操作。
プロファイルの追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882753/7e0fa470-9b2f-a09b-fa34-78cbc93e1d72.png)

プロファイル名を書く 自分がわかるように適当に。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882753/9d39f1dd-12b4-2ee7-8d01-ddf2b45a0575.png)

タスクを書く。ソースはバックアップ元。destinationは先。先程マウントしたディレクトリを入れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882753/8000c350-64ac-4ec6-c10f-e1f1d36ca968.png)


OKEY押す。
バックアップスータトされる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882753/f19d90aa-fdff-8e89-f347-9e818ef00883.png)

完了
フロッピーマークを押せば設定がセーブされる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882753/16ebf37f-fbce-75d3-4a53-6342b62ee11c.png)

## スケジュール実行
バックアップ先ラズパイでターミナルうちます。
```
crontab -e
```
毎週月曜日の午前3時に実行する場合は、
```
0 2 * * * luckybackup --silent --profile kaji-app
```
[Autohotkey]一つのキーに対して、単独で押した時と他のキーと組み合わせて押した時の挙動を変える

こんにちは。
泡アハです。

私は別の記事でも書いた通り、キー配列をがちがちにカスタマイズしています。
windows,mac,linuxでキー配列を変更していますが、
唯一Autohotkeyだけは少し癖があります。

karabiner(mac用), xremap(linux用)では、設定ファイルに単体押しとキーコンビネーション時に押し続けた場合の役割を定義することができます。

例:xremapの場合(Space単体押し=Space, 押し続けたとき=CapsLock)
```
modmap:
  - name: Global
    remap:
      Space:
        held: CapsLock
        alone: Space
```
※xremapは、設定ファイルを簡潔に書くことができ、なおかつ後から見返した場合にわかりやすくて個人的に好きです。

そんな中でAutohotkeyでも、一つのキーに対して、単独で押した時と他のキーと組み合わせて長押しした時で、それぞれ異なる機能を割り当てたかったのですが、解決策をみつけたので、共有します。

同じようにAutohotkeyで単体押しとキーコンビネーション時の場合分けをしたい方がいれば、ご参考いただければと思います。

なお、本スクリプトは、Autohotkey ver2で実装しています。
おそらくver1.0でも書き方を工夫すれば同じことはできると思いますが、この点ご注意ください。

## 結論

例:
```
Spaceキー単体押し = Space
Space + i = up
```
としたい場合、以下のようなスクリプトで実現できます。

```ahk
SinglePress(lastkey, sendkey) {
    KeyWait lastkey
    If (A_PriorKey = lastkey)
    {
        Send sendkey
    }
    return
}

Space:: SinglePress("Space", "{Space}")
~Space & i::up
```

## 解説
### SinglePress
#### 概要
```
SinglePress(lastkey, sendkey) {
    KeyWait lastkey
    If (A_PriorKey = lastkey)
    {
        Send sendkey
    }
    return
}

Space:: SinglePress("Space", "{Space}")
```

このスクリプトでは、スペースキーが押されてすぐには何も実行せず、スペースキーが離されるまで待つ動作を行います。
その後、最後に押されたキーがスペースキーだった場合（つまり、他のキーとのコンビネーションではない場合）、スペースキーが押されたことをシミュレート（再送）します。

#### 引数
SinglePressには、lastkeyとsendkeyを引数に受け取りますが、それぞれ以下のような意味となっています。

| 引数名  | 意味 |
| ------------ | ------------ |
| lastkey | 最後に押されたキー |
| sendkey | 単押しだった場合に送信するキー |

なぜlastkeyとsendkeyをわけているかというと、Alt+Spaceのようにキーコンビネーションを制限したいケースを考慮したからです。
Alt + Spaceは、コマンドランチャーを起動したいけど、Alt + Space + iの場合、Alt + upとして動いてほしいというときに有効です。
```
!Space:: SinglePress("Space", "!{Space}")
```

私の場合、VSCodeでAlt + Space + iでAlt + up(行の移動)を実現したかったのですが、
```
~Space & i::up
```
とだけ設定しても先にAlt + Spaceが先に動いてしまうため、SinglePressを使うとやりたかったことができるようになります。

#### 要点
このスクリプトの肝は、
```
    KeyWait lastkey
    If (A_PriorKey = lastkey)
```
の部分です。
単押しかどうかを判断するために
```
KeyWait "Space"
```
で、スペースキーが離されたかどうかを検知し、
```
If (A_PriorKey = "Space")
```
最後に押されたキーがスペースキーだった場合（つまり、スペースキーが単体で押された場合）に条件を満たして、Send sendkeyするという仕組みになっています。

## まとめ
いかがでしたでしょうか？

Autohotkeyは、ほかのキーバインドツールにくらべ、スクリプトで記述する分、自由度は高いですが、その分難易度も高いと思っています。

とはいえ、マスターすれば、強力なツールになることは間違いないと思いますので、
ぜひこの記事を参考に素晴らしいキーボードライフを楽しんでください。
Dockerでbitcoindをたてる

こんにちは。
泡アハです。

皆様の中には、新たな技術トレンドであるブロックチェーンに魅力を感じている方もいらっしゃるのではないでしょうか？
この革新的な技術のルーツとも言える存在、それがビットコインです。

ビットコインは、暗号資産としてその名を広く知られていますが、エンジニアの視点から見ると、その背後の技術と理論は圧倒的な魅力があります。

ブロックチェーンに興味をお持ちの方々、まずはこのビットコインから始めてみてはいかがでしょうか？
そんな皆さんのために、今回は手軽に使えるdockerを使ってビットコインノード（bitcoind）を立ち上げる方法をご紹介します。
これを通して、ブロックチェーンの深淵に一歩踏み込むきっかけを提供できればと思います。

## 結論
とにかく立ち上げたいんだ！という方もいらっしゃると思いますので、先に記載しておきます。
各コマンドの詳しいところは、記事後半をご覧ください。
また、Githubでも公開していますので、そちらもご確認いただければと思います。

なお、今回は、regtestモードたてるようにしています。
regtestモードは、ローカルでブロックチェーンネットワークを構築できるモードのことです。
もしmainnet(本番のブロックチェーンネットワーク)、testnet(テスト用のブロックチェーンネットワーク)を立てたい場合は、bitcoin.confで調整してみてください。
https://github.com/nogu3/bitcoincorefordocker
### フォルダ構成
```
├── conf
│  └── bitcoin.conf
├── docker-compose.yml
├── Dockerfile
└── README.md
```

### Dockerfile
```Dockerfile
FROM ubuntu:22.04

ARG BITCOIN_CORE_VERSION=25.0

RUN apt update -y && apt upgrade -y

RUN apt install -y wget

# install bitcoin
RUN wget -q https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_CORE_VERSION}/bitcoin-${BITCOIN_CORE_VERSION}-x86_64-linux-gnu.tar.gz

RUN tar -zxvf bitcoin-${BITCOIN_CORE_VERSION}-x86_64-linux-gnu.tar.gz

RUN install -m 0755 -o root -g root -t /usr/local/bin bitcoin-${BITCOIN_CORE_VERSION}/bin/*

RUN rm -r bitcoin-${BITCOIN_CORE_VERSION}*

# copy conf
ADD ./conf/bitcoin.conf /root/.bitcoin/bitcoin.conf

CMD bitcoind
```
### docker-compose.yml
```
services:
  bitcoind:
    build: .
    volumes:
      - bitcoin_data:/root/.bitcoin/blocks
    tty: true

volumes:
  bitcoin_data:
```

### bitcoin.conf
```
regtest=1
```

## 解説
それぞれ重要な部分のみを抜粋していきたいと思います。

### bitcoin coreのインストール
bitcoin coreとは、bitcoinネットワークに接続するノードをたてることができるクライアントソフトのことです。
このbitcoin coreをインストールすることで、bitcoind(※1)をたてることができ、bitcoin-cli(※2)を使うことができるようになります。
※1…bitcoinネットワークに接続するノードのプロセスのこと
※2…ブロックチェーンの情報やトランザクション(アドレス間の取引のこと)の情報など取得するコマンドのこと

Dockerfile内で実際にbitcoin coreをインストールしているのは、以下の箇所です。
各コマンドの意味は、コメントで記載しています。
```
# wgetを利用し、bitcoin coreのバイナリを取得する
RUN wget -q https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_CORE_VERSION}/bitcoin-${BITCOIN_CORE_VERSION}-x86_64-linux-gnu.tar.gz

# バイナリ(tar.za)を解凍する
RUN tar -zxvf bitcoin-${BITCOIN_CORE_VERSION}-x86_64-linux-gnu.tar.gz

# installコマンドを利用し、/usr/local/binにコピーする
RUN install -m 0755 -o root -g root -t /usr/local/bin bitcoin-${BITCOIN_CORE_VERSION}/bin/*

# インストールに使用した媒体を削除する
RUN rm -r bitcoin-${BITCOIN_CORE_VERSION}*
```

### bitcoindの起動
bitcoindを起動するためには、bitcoin-cliのインストール後、`bitcoind`を実行するだけで良いです。
bitcoindにはオプションで`-regtest`などあり、それでもregtestモードで起動することは可能ですが、
今回は設定内容をbitcoin.confにまとめたいため、bitcoin.confに記載し、bitcoind起動前にbitcoin.confをコピーしています。
```
# copy conf
ADD ./conf/bitcoin.conf /root/.bitcoin/bitcoin.conf

CMD bitcoind
```

## まとめ
いかがでしたでしょうか？

自分もつい先日までbitcoin初心者だったのですが、
これからbitcoinを始めてみたいという方のご参考になればと思い、書いてみました。

まだまたbitcoinビギナーなので、これからも精進していきたいと思います。

次は、コンテナを2つたててそれぞれのアドレスに送金するデモの記事でも書こうかな。
重回帰分析計算ツール

重回帰分析をさくっとできるツールがググっても出てこなかったのでChatGPTに作らせました（とりあえず開いてみてください）[^1][^2] 

https://markn.shinyapps.io/Regression_App

<br>

基本はExcelで作成したデータを使うことを想定しているため、データの直打ちをしたいよって人はみんな大好き「[高精度計算サイト - Keisan](https://keisan.casio.jp/exec/system/1402032384)」をお使いいただくのが良いかと思います。


[^1]:※RのShinyってやつで作っています。
[^2]:※shiny.ioの無料のプランを使っているので月に25hしか使えないらしいです。アクセスが多いようだったら考えます（どうせあんまアクセスされないと思うのでとりあえずこれで）

# 使い方
直感的に使えるようにしたつもりなので説明は不要かと思いますが一応...
データの入力方法は2通りです。

データを入力したら「分析実行」を押せばOKです。

### ①「Browse」を押して分析に使いたいcsvファイルを選ぶ。

<img width="300" alt=image.png src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296113/7be15d34-18b9-1f9a-bc69-f2d398f9053a.png>

- 1行目は変数名
- csvをExcelで開いた時の見た目はこんな感じ↓↓
    - <img width="200" alt=image.png src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296113/5461c078-0ff6-3e8c-be6b-ca4e8ee106fd.png>

<br>

### ② Excelからデータをコピペ


<img width="500" alt=image.png src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296113/a85ccd4d-3c94-3663-8fd6-465705a63abd.png>

- 1行目は変数名






# 最後に
日本語しか書いていないのにこんなのが作れちゃうの未来だなって思いましたまる。
[大人の自由研究]Rubyのmapとmap!の違いとパフォーマンス比較

こんにちは。
泡アハです。

仕事では主にRubyを使って開発しているのですが、
まだ始めて7ヶ月ほどなので、わからないことも多いです。

日々勉強の毎日ですが、
```
mapを使うとき、mapを使うのとmap!を使うのどちらがよい？
```
とふと疑問に思いました。

色々調べた結果、基本的には、
```
参照先を直接いじりたい -> map!
元の変数には変更を加えたくない -> map
```
という使い分けで問題ないようです。

ただ、これ動作速度的にはどういう違いがあるのだろうと疑問に思ったので、
大人の自由研究と題して、調査してみました。

## そもそもmapとmap!の違い
### 公式サイト
公式サイトを見てみます。

map
> 各要素に対してブロックを評価した結果を全て含む配列を返します。 
> 出典: https://docs.ruby-lang.org/ja/latest/class/Array.html#I_COLLECT

map!
> 各要素を順番にブロックに渡して評価し、その結果で要素を置き換えます。 
> 出典: https://docs.ruby-lang.org/ja/latest/class/Array.html#I_COLLECT

つまり、
```
map = 各要素に対して与えたブロックを評価した結果をすべて含む配列を新規で作って返す
map! = 各要素に対して与えたブロックを評価し、要素を直接置き換える
```
ということになります。

### Rubyのコード

Rubyにおいて、Arrayは、RArrayとよばれるオブジェクトでできています。
https://qiita.com/ksss/items/aaa222bb2f70ad10a0b6

RArrayでは、要素数に変更がある場合、reallocやmemmoveを使用して、メモリ領域を確保するようです。
> 要素数が大きく変わればrealloc()がかかるし、末尾以外に要素を挿入 すればmemmove()
> 出典: https://i.loveruby.net/ja/rhg/book/object.html

実際のコードも読んでみましょう。
map
https://github.com/ruby/ruby/blob/3874381c4483ba7794ac2abf157e265546f9bfa7/array.c#L3743
map!
https://github.com/ruby/ruby/blob/3874381c4483ba7794ac2abf157e265546f9bfa7/array.c#L3771

mapは、rb_ary_new2を利用して、新しい配列を用意しているのに対し、
map!は、rb_ary_modifyを利用して、引数に渡された配列をそのまま変更しています。

## 実験
ここからが本題です。
mapのように配列全体の要素数は変わらず、各要素の大きさが変わった場合どうなるのか。
検証してみることにします。

今回やってみるのは、以下の4つです。

|検証方法|検証コード|
|---|---|
|メモリ領域を広げない編集| &:upcase! |
|メモリ領域を固定長、狭める編集| value[0, 3] |
|メモリ領域を固定長、広げる編集| "#{value}A" |
|メモリ領域を可変長、広げる編集| "#{value}#{'A' * rand(10)}" |

実際の検証コードは、githubにて公開しているので、
興味がある方はご確認ください。
https://github.com/nogu3/mapcompareforruby

## 実行結果
実行結果は以下のとおりです。
```ruby
# ruby ./main.rb
メモリ領域を広げない編集
              user     system      total        real
map:      0.159628   0.009931   0.169559 (  0.169567)
              user     system      total        real
map!:     0.154216   0.000000   0.154216 (  0.154218)
メモリ領域を固定長、狭める編集
              user     system      total        real
map:      0.093633   0.009111   0.102744 (  0.102748)
              user     system      total        real
map!:     0.109660   0.000000   0.109660 (  0.109661)
メモリ領域を固定長、広げる編集
              user     system      total        real
map:      0.329067   0.009544   0.338611 (  0.338617)
              user     system      total        real
map!:     0.180752   0.000072   0.180824 (  0.180825)
メモリ領域を可変長、広げる編集
              user     system      total        real
map:      0.395469   0.020609   0.416078 (  0.416080)
              user     system      total        real
map!:     0.503577   0.000000   0.503577 (  0.503578)
```

## 考察
### メモリ領域を広げない編集
メモリの領域を広げない編集に関しては、想定どおりです。
mapの場合、新しく配列をメモリ領域に展開するため、その分遅くなっているようですね。

### メモリ領域を固定長、狭める編集
これは、少し想定と違いました。
想定では、map!の方が早いと思っていました。
メモリ領域を固定長狭める場合、メモリの再展開が不要だからです。
ですが、結果としては、ほぼ同等、若干mapの方が有利となっています。

### メモリ領域を固定長 or 可変長、広げる編集
元々の想定では、固定長や可変長広げる編集は、mapの方が早いと想定していました。
なぜなら、map!の場合、各要素の文字列長を広げると確保したメモリを再確保する必要があるため、最初から配列の領域を新しく確保するmapの方が早くなると考えたからです。

しかし、結果を見てみると、
```
固定長広げる編集 => map! < map
可変長広げる編集 => map < map!
```
となっていました。

う〜む。
mapの場合、可変長の文字列を追加するとき、新しい配列のメモリを確保するのに時間がかかるのかな。。

## まとめ
実行結果は、いくつか想定と異なることがあって、面白かったです。

なぜ追加する文字列長が固定長と可変長で逆転するのか。。。
こればっかりは、Rubyの実行ソースみるしかないかな〜。
繰り返し二乗法と逆元をKotlinで実装

# はじめに
KotlinでAtCoderに取り組んでいます。

Kotlin標準の[Math.pow](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.math/pow.html)はdouble or float型にて計算するため扱いにくいのでLong型対応のものを実装しました。([参考](https://qiita.com/drken/items/3b4fdf0a78e7a138cd9a))


## modを考慮しないpow
繰り返し二乗法により実装します。
```kotlin
fun pow(xx: Long, nn: Long): Long {
    var res = 1L
    var x = xx
    var n = nn
    while (n > 0) {
        if (n % 2 == 1L) res *= x
        x *= x
        n = n.shr(1)
    }
    return res
}
```


## modを考慮したpow
掛け算のたびにmodをとります。
```kotlin
fun modPow(xx: Long, nn: Long, mod: Long): Long {
    var res = 1L
    var x = xx % mod
    var n = nn
    while (n > 0) {
        if (n % 2 == 1L) res = res * x % mod
        x = x * x % mod
        n = n.shr(1)
    }
    return res
}
```


## フェルマーの小定理による逆元の算出
modPowを使用します。
```kotlin
fun modInv(x: Long, mod: Long): Long {
    return modPow(x, mod - 2, mod)
}
```

## 拡張Euclidの互除法による逆元の算出
```kotlin
fun modInv(xx: Long, mod: Long): Long {
    var x = xx
    var b = mod
    var u = 1L
    var v = 0L
    while (b > 0) {
        val t = x / b
        x -= t * b
        x = b.also {b = x}
        u -= t * v
        u = v.also {v = u}
    }
    u %= mod
    if (u < 0) u += mod
    return u
}
```
セブンイレブンとローソンの印刷処理速度の比較：大量印刷かつ2in1ならローソンがおすすめ

先日、USBメモリに入れたPDF17ページ分の印刷(2in1設定)をセブンイレブンとローソンでやったのだが、印刷が終わるまでの時間にだいぶ差があった。

結論からいえば、
**大量印刷かつ2in1なら、ローソン一択**
ということになるが、
**1. なぜそのような結論にいたったか**
**2. システム的な違いをエンジニア目線で考察**
についてまとめていきたいと思う。

## 結論
10枚以上の印刷を2in1でやるならローソンがおすすめ。

おそらく以下のような流れで印刷するため、ローソンの方が処理速度が早い
```
セブン: PDFを都度USBから読み込み、処理して印刷
ローソン: 選択したPDFをすべてメモリ内に格納し、メモリ上で結合して印刷
```

## 経緯
先日、PDF17ページ分を2度印刷する機会があった。

この17ページは、
```
片面印刷
2ページを1ページにする
```
で印刷したい。

最寄りのコンビニは、セブンイレブンとローソンなのだが、
当日は電車に乗る予定だったので、駅に近いセブンイレブンでUSBプリントを行った。

セブンイレブンに到着すると50代くらいの男性と女性がそれぞれ一人でプリンターにならんでいた。
少し待っているとそれぞれプリンターの使い方がわからなかったようで、先にプリンターを使わせてもらうことになった。

しかし、セブンイレブンは、17ページの印刷がまあ遅い。
とにかく遅い。
(多分、5分ぐらいかかった。後ろに二人待ちがいたので、なおのこと遅く感じた。)

これ以上先に使わせてくれた二人を待たせるわけにはいかないので、諦めてローソンに移動した。

ところがローソンでは、同じ分量のPDFを印刷したところ、1分もかからず終了した。
セブンイレブンで5分以上またされていたので、これにはとても感動した。

プリンターひとつとってもユーザ体験がこれほどまでに異なるのかと思ったので、
なぜここまで処理速度が異なるのか考察したいと思う。

## 各コンビニの印刷までの手順
まずは、印刷までの手順をまとめてみる。

### セブン
1. USBプリントを選択する
2. USBを指す
3. USBメモリ内のファイルを選択する(選択できるのは1ファイルのみ)
4. 印刷設定を選ぶ(片面印刷、2in1)
5. 印刷開始
印刷開始後、プリンターの画面にはn/17(1ページ目ならnは1)が表示され、nが進んで行くたびにページ処理中10%のような表示が出ていた。ページ処理中が100%になって表示が消えたあと、1枚印刷された。
6. 印刷終了
7. USBを取り出す

### ローソン
1. USBプリントを選択する
2. USBを指す
3. USBメモリ内のファイルを選択する(選択できるのは20ファイル)
4. USBを取り外す
5. 選択したファイルから印刷したいファイルを選ぶ
6. 印刷設定を選ぶ(片面印刷、2in1)
7. **印刷開始**
印刷開始後はほぼタイムリーに1枚ずつ印刷された。
8. 印刷終了

## 考察
注意:あくまで推測です。根拠はまるでないので、その点ご注意ください。

手順を改めて確認してみるとおそらくセブンは、USBメモリ内のPDFを読み込み、2in1するのに都度USBに接続しているように思える。

プログラムで実装するときのイメージとしては、
1. USBに接続
1. USB内のPDFの対象ページを読み込み、メモリに保存する
1. メモリ上にあるページを2in1にする
1. メモリ上に生成した2in1を印刷する

のような感じ。

一方、ローソンは、
1. USBに接続
1. 1つのPDFを全ページ読み込む
1. USB接続を切断
1. メモリに読み込んだい全ページを2in1する
1. メモリ上に生成した2in1を印刷する

のようになっていると推測できる。

違いとしては、USBメモリへの接続回数。
セブンのUSBへの接続は、n/2回(n=PDFの総枚数)
一方、ローソンは、最初の接続1回のみ。

一般的にメモリ上のデータにアクセスするより、物理デバイス上のデータにアクセスするのは時間がかかる。

仮にメモリ(RAM)を2020年に主流のDDR4、USBメモリの接続規格をUSB2.0だとすると、
そのデータ転送速度は、およそ290倍近く差が出る。

そりゃ290倍のデータ転送速度に時間がかかるとすると実際に印刷するのに時間がかかるのは納得できる。
またFileI/Oの回数もきっと異なるので、よりローソンの方が高速に処理できるはず。

※・・・メモリ(RAM)とUSBメモリの詳細な違いの説明は以下の通り。
```
DDR4は、17GB/s（ギガバイト毎秒）という転送速度を持つとされている。
これをメガバイト単位に換算すると（1ギガバイト = 1024メガバイトなので）以下のようになる：

17 GB/s x 1024 (MB/GB) = 17408 MB/s （メガバイト毎秒）

一方、USB 2.0の最大伝送速度は480Mbps（メガビット毎秒）。これをメガバイト毎秒に換算すると：

480 Mbps ÷ 8 (bit/byte) = 60 MB/s （メガバイト毎秒）

以上から、DDR4メモリとUSB 2.0のデータ転送速度を比較すると、DDR4は理論上１秒あたり最大17408 MBを転送できるのに対し、USB 2.0は理論上1秒あたり最大60 MBを転送できることになる。
これは、DDR4メモリの方がUSB 2.0よりも約290倍高速であることを意味する。

実際には、メモリアクセスやUSBデータ転送にはプロトコルのオーバーヘッドやシステム環境による遅延があるため、これらの理論値が現実のパフォーマンスを完全に反映するわけではないが、MHz速度オーダーのメモリとMbps速度オーダーのUSBとの間には、大きなスピードの差があることは明らかである。
```

## まとめ
ここまでセブンとローソンのプリンターの処理速度の違いについて考察してみた。
正直、10枚以上の印刷はそうそうやるもんではないので、そこまできにしなくてもいいかもしれないが、
大容量印刷をやるかたはぜひローソンがおすすめ。

エンジニア的観点で一つ気づきをあげるとすれば、
```
PDFファイルが印刷中に書き換わらないのだから、都度USBからデータを取得するのではなく、
最初にUSBからデータを読み込んで、処理するアーキテクチャの方が適している
(もし処理中にデータがかわるのであれば、都度読み込む方がいい)
```
があげられる。
もっと汎用的な気づきに昇華させるのであれば、以下としたい。
```
ユーザ体験としてあるべき形を考えて、実装を検討する
都度読み込むのか、一度にすべて読み込むのかは、そのデータに変更があるかどうかを基準に検討する
```

プリンター一つとっても実装次第でかなりユーザ体験が異なるので、
常によりよいものを作る精神でモノ作りをしていきたい。
getとfetchの違い：データの取得距離に着目した使い分け方法

突然ですが、getとfetchの違いを意識したことはあるでしょうか？

先日、職場でgetとfetchってどう使い分けるのですか？という話題になったのですが、
自分は本当になんとなくで使っていました。
(なんとなくgetが多め。。w)

改めて調べてみるとデータを取ってくる先との距離が重要になるみたいなので、まとめてみたいと思います。

## 結論
fetch：nw経由など遠い距離にあるデータを取得する
get：比較的に近い距離にあるデータを取得する

## そもそもの単語の意味を調べてみる

まずは単語の意味を調べてみます。
英語ではそれぞれどのような意味なのでしょう。

weblioで調べてみましょう。

```
get: 得る
出典: https://ejje.weblio.jp/content/get

fetch: 取ってくる
出典: https://ejje.weblio.jp/content/fetch
```

なるほど。

“取ってくる”の場合、少し歩いて取りに行く、どこかにあるものを自分で取りに行くというようなイメージですかね。
つまり、能動的に取りに行く。

一方、“得る”というのは、何かを手に入れるとかそういうイメージですかね。
受動的に取りに行く？

使い分け的には、自分から取りに行くか、データからくるかの違いになるのか？
あまりピンとこない。。。。

## プログラミングの観点から見てみる

次にプログラミングの観点から、考えてみましょう。

```
get: すでに持っている内部データから取得する。
fetch: ここにはないものを外部から取ってくる。
出典: https://study-z.net/100245422/2
```

英語の意味の時に比べ、使い分けがわかってきたように思います。

確かにDBのデータを取得するときやnw経由でデータを取得するときは、fetchを使うイメージですね。
一方、設定ファイルから値を取得するときは、getを使うイメージです。

他の使用例でいうと、CPUの操作にfetchというものがあります。
このfetchは、"メモリ(RAM)からレジスタ(CPU内の高速メモリ)に命令を取ってくること"を指します。

おそらくCPUから見てメモリは遠い位置にあるため、
"外部から取ってくる"という意味でfetchを使うみたいですね。

他にfetchが使われるもので思い浮かぶのは、gitのfetchです。
このfetchは、リモートリポジトリにあるソースの情報を取得する時に使います。

つまりこのfetchも、ここにはないもの(ソース情報)を外部(リモートリポジトリ)に取りに行くので、fetchを使っていそうです。

ある程度見えてきましたね。

```
ある地点から見て内部もしくは近くにあるものを取得するときは、get
外部にあるものを取得するときは、fetch
```
という整理になりそうです。

![](https://lifelongboy.com/wp-content/uploads/2024/01/diff-get-fetch-ver2.jpg)

ただし、何を近くとするのかは、文脈によって異なりそうなので、
プロジェクトなどで悩んだ場合は、チームメンバーに相談するのか良さそうです。

## まとめ

近くのものはget、遠くのものはfetch。

どちらも取得するという意味では同じですが、データを取ってくる先が遠いか近いかで使い分けが変わってくるようです。

こういう今までなんとなく理解していたものを言語化しておくのは、理解をより深めるという意味で大切ですね。

それでは。
Bitwardenから1Passwordに変えてみた理由とメリット

パスワードマネージャーはみなさん何を使っていますか？

今までiCloud keychainなど様々なパスワードマネージャを使っていましたが、ここ数年はBitwardenに落ち着いていました。

しかし、とある理由から1Passwordに乗り換えたので、その理由と経緯について書いておこうと思います。

## 結論

なぜ変えたのか、一言でいうと"脳のリソースをあけたかった"です。
Bitwardenはよさげだけど、ずっと以下の点に悩んでいました。
- パスワードマネージャ何がいいか問題に疲れた
- セキュリティリスクの懸念

これを解決するために、1Passwordにしました。

## プロローグ パスワードマネージャ最高！

数年前から、パスワードマネージャの必要性が騒がれてきました。
私はiPhoneユーザーなので、初めはiCloud keychainを利用していました。

パスワードマネージャを使い始めたことで、
- 複数サイトのパスワードを覚えておかなくてよくなった
- 自分でパスワードを考えなくてよくなった
→結果、パスワードのセキュリティ強度が上がった
- 自動入力により、パスワード入力の手間がなくなった
のような利点を得ることができるようになりました。

しかし、iCloud keychainを使っているとマルチプラットフォームに悩まされました。

Linux、Windows、iPhone、iPadでパスワードマネージャを使いたかったのですが、どうもApple製品以外とは相性が悪い。

一応、WindowsにもiCloud keychainのアプリはありますが、
同期が遅かったり、そもそも同期が全くされなかったり、うまく動かないとことが多かったです。

そこでパスワードマネージャを探す旅に出ました。

## パスワードマネージャは何がいいのか

自分がパスワードマネージャに求める条件は、以下の通りです。

- マルチプラットフォーム
- パスワード生成の仕様をある程度自分で選べる
- そこそこ有名
- できれば無料

iCloud keychainでは
- マルチプラットフォームに弱い
が弱点でしたが、
それに加えて地味に面倒くさかったのが、パスワードの仕様を自分で決められない点でした。

サイトによっては、パスワードの仕様に関して、
- 20文字が限界
- 記号はだめ
だったりしますが、iCloud keychainではその点を柔軟に変更することができないため、別途パスワード生成サイトでパスワードを生成してから、登録していました。

それらの弱点を解消し、必要条件を満たしていたのが、Bitwardenです。

導入したのは2022年あたりだったと思いますが、その頃はそこまで有名ではなく、一部レビュー記事があるかなといった状況でした。

とはいえ、以下の観点が決め手となって、Bitwardenを利用することにしました。
- オープンソースでセキュリティもそこそこしっかりしていそう。
- やりたいことは最低限できる
- 自分が使うどのOS上でも動く


## なぜBitwardenから1Passwordに変えたのか？
単刀直入にいいますが、パスワードマネージャ何にするか問題に疲れたのが理由です。

正直、Bitwardenでも必要十分な条件を満たしています。

しかし、以下の点がずっと気になり、
他にもいいパスワードマネージャはないかなと時折探していました。
- 無料なので、いつ何が起こるかわからない
(例えば、急にサービス終了したり、重要なところがプレミアムになったり、バグが修正されなかったりという点です)
- セキュリティ面で何があった場合、補償などの面で不安
(実際、この記事のような脆弱性が報告されています。https://gigazine.net/news/20230309-bitwarden-flaw-steal-passwords-using-iframes/)

割り切って使うのも一つの手かと思いますが、パスワードマネージャ界の雄である1Passwordにしたけばとりあえず間違いんないんじゃね？と思い、乗り換えました。

## 1Passwordに変えてみてどう？
正直、使い勝手としては、大きく変わらないです。

とはいえ、ざっと思いつく限り以下の点は優れているなと感じました。
- 少なくともiPhoneではパスワード入力時の1Passwordアプリの立ち上がりが早くなった
- emergency kitで、初期ログインする。
また、2週間に一度、マスターパスワードを入力する必要がある
→初期ログインのセキュリティは高そう
- UIが綺麗
- 専用のテンプレートでAPIキーや暗号資産ウォレットも登録できる
- ファミリープランなので、夫婦間のパスワード共有がスムーズ
- カスタムフィールドでパスワードのように***表示にできる(ワンタップでコピー可能)
→秘密の質問など見られたくないやつもセキュアに管理できる
- 2段階認証コードの管理も一元化できる

書き出してみると思ったより良かった点がありますね。

上記に加えてパスワードマネージャ何にしよう問題から解放されたことも大きな利点です。

Bitwardenになんかあったらどうしよう。
とはいえ、みんな使ってるし大丈夫では？
と自問自答を繰り返している時間から解放されました。

1Passwordは太古から利用されていますし、
有名企業でも採用されているため、安心感は強いと考えてます。

## まとめ

いかがでしたでしょうか？

パスワードマネージャは、かなりの選択肢があるので何を使うか悩んでしまいますよね。

1Passwordにすることにより、パスワードマネージャ何にするか問題から解放されたので、
可処分時間を増やすことができそうです。

それでは。
NeovimのDockerコンテナ上のclipboard共有がかんたんになった

1. こんにちは
泡アハです。

昨日neovim 0.10.0がリリースされました。

リリースノートはこちら
https://neovim.io/doc/user/news-0.10.html

そのリリースの中にOSC52を用いたclipboard共有が含まれていたので、
これはDockerコンテナ上でnvimを開いたときのclipboard共有がかんたんになるのでは？と思い、さっそく試してみました

## Dockerコンテナでためす
### Dockerコンテナを起動
```
docker run -it alpine:linux sh
```

### nevim0.10.0およびLazyvimのインストール
自分はLazyvimを使っているので、インストールしていますが、試すだけならneovimだけでもいいと思います。
```
# nvim のインストール
apk update
apk add build-base cmake coreutils curl unzip gettext-tiny-dev git
git clone https://github.com/neovim/neovim
cd neovim
git checkout stable
make CMAKE_BUILD_TYPE=Release
make install
nvim --version

# Lazyvimのインストール
apk add git lazygit ripgrep alpine-sdk --update
git clone https://github.com/LazyVim/starter ~/.config/nvim
cd ~/.config/nvim
nvim
```

### options.luaに追記
このドキュメントを参考にclipboardを追記
https://neovim.io/doc/user/provider.html#clipboard-osc52
```
vim.g.clipboard = {
  name = 'OSC 52',
  copy = {
    ['+'] = require('vim.ui.clipboard.osc52').copy('+'),
    ['*'] = require('vim.ui.clipboard.osc52').copy('*'),
  },
  paste = {
    ['+'] = require('vim.ui.clipboard.osc52').paste('+'),
    ['*'] = require('vim.ui.clipboard.osc52').paste('*'),
  },
}
```
nvimを開きなおして、checkhealthしてみたところ、OSC52となっていました。
```
==============================================================================
provider.clipboard: require("provider.clipboard.health").check()

Clipboard (optional) ~
- OK Clipboard tool found: OSC 52

==============================================================================
```

### yyしてみる
できた！！！
しかも自分の環境は、
`alactirry on ubuntu - ssh -> docker on wsl`
で試してみたのですが、ちゃんとubuntu側でコピペができるようになりました！

## まとめ
今までは、Docker上でコピペをするためにはtmuxと連携するなどの方法を取る必要がありました。
しかし、この方法だとdockerの外にtmuxがある場合、$TMUXやsockerファイルなどをDockerコンテナにマウントする必要がありました。

しかし、今回のアップデートによってnvimだけで完結するにようになったのは、とても嬉しいです。
neovimを初めてまだ3ヶ月ほどですが、neovimほどカスタマイズ性が高く、面白いエディタはそうそうないですね。
どんどんなれて快適な開発生活を送れるようになりたいところです。
それでは。
ブロックチェーンの理解に必要なことをざっくりまとめてみる

こんにちは。
泡アハです。

暗号資産ベンチャー企業に転職したことで、
ブロックチェーンへの興味がふつふつとわいています。

ブロックチェーンについては、全くのド素人だったため、
いろいろ調べたり、業務をしていくなかで少しずつ覚えていきました。

最低限ここだけ抑えておけば、
ブロックチェーンがふんわり理解できるというところまで、
説明できればと思います。

## ブロックチェーンとは？
ブロックチェーンとは、**情報を「ブロック」と呼ばれる単位に分け、それらを鎖のように連なる形で管理する技術**のこと。
ブロックには、トランザクション(後述)、や前のブロックのハッシュが含まれており、
自身のブロック情報をハッシュ化したブロックハッシュも持っている。
自身のブロック情報には、前のブロックのハッシュを含んでおり、そのブロック情報を元にブロックハッシュを算出しているため、
前のブロックが改ざんされ、前のブロックのハッシュが変更された場合、後続のブロックすべてのハッシュの計算が必要になる。
この性質より、ブロックチェーンと呼ばれる。

## explorer
bitcoinなどパブリックなブロックチェーンの情報は、すべて公開されている。
そのため、explorerと呼ばれるブロックの情報を確認するサイトを見れば、どのブロックにどんな情報が入っているかわかる。

bitcoin
https://www.blockchain.com/explorer/blocks/btc/801415
ethereum
https://etherscan.io/

## トランザクション
トランザクションとは、アドレス間の取引のこと。
どのアドレスからどのアドレスに向けて、いくつ送金したかを表している。
例によって、explorerを確認すれば、トランザクションの中身がわかる。
https://www.blockchain.com/explorer/transactions/btc/650f174d8594abe4cd4ce9ce3ef02b762e61c2f5722caec71423f2c75402dc28

## アドレス
ブロックチェーン上の口座番号のようなもの。
アドレスは、秘密鍵→公開鍵から導出される。
アドレスもexplorerで確認することができる。
https://www.blockchain.com/explorer/addresses/btc/bc1qamun47x67apk7ecquenmzalfu57w0neeedc3z0

## UTXO型
UTXOとは、"Unspent Transaction Output"の略で、
まだ使用されていないTransaction Outputのことを表す。

UTXO型は、以下の図がわかりやすい。
https://developer.bitcoin.org/devguide/block_chain.html#id2
Transactionには、inputとoutputを含んでいる。
inputとoutputは、それぞれ
```
input=どのtransaction outputを利用するか
output=どのアドレス宛にいくら送られたか
```
となっており、transactionは、各outputを次のtransactionのinputとして使うことで金銭の取引を表している。
この仕組みは、現金に近い動きとされる。

soffyが1000円を持っていて、harryに200円おくりたい場合、transactionでは、以下のように表される。
(送金手数料は、10円とする。)
```
{
    "txid": "2",
    "input": [
        {
            "txid": "1",
            "output": 1,
            "address": "soffyのアドレス",
            "value": 1000
        }
    ],
    "output": [
        {
            "address": "harryのアドレス",
            "value": 200
        },
        {
            "address": "soffyのアドレス",
            "value": 790
        }
    ]
}
```
inputの部分は、txidとoutputが指定されている。
これは、どのtxidのoutputを元に送金するかを表している。

outputの部分は、2つになっている。
1つ目のvalue: 200の部分は、harryのアドレスへの送金を表している。
2つ目のvalue: 790の部分は、soffyのアドレスへのおつりを表している。
もしこのおつりを使いたければ、次のtransactionでは、txid:2、output:1を指定すれば使うことができる。
送金手数料は、inputのvalueの総和-outputのvalueの総和で算出される。
その送金手数料は、ブロックをマイニングした人(miner)の報酬になる。

## アカウント型
Ethereum等で採用されている方式で、1つのアドレスに残高を蓄えておき、
その残高を送金することで実現される。

UTXO型が現金であれば、アカウント型は、電子マネーのイメージに近い。
https://etherscan.io/address/0xc76592655397bbb781509b92ee8f09eca361c397

## まとめ
ざっくりまとめてみましたが、
まだまだ全容は説明しきれないですね。。。

それだけ多くの知識が必要ということでもありますが、
学ぶべきことがたくさんあることは、エンジニア冥利につきるような気がします。

これからも引き続きブロックチェーンについての理解を深めていきたいと思います。
x.inferをGoogle Colabで試してみた！（Googleノートブック付）

## はじめに
最近、新しい画像認識モデルが次々とリリースされていますよね。例えば**GPT-4V**や**Claude 3**など、画像認識の性能は日々進化しています。でも、こんな悩みはありませんか？

- 🤔 新しいモデルを試したいけど、セットアップが面倒
- 😅 異なるフレームワークの学習が大変
- 💦 環境構築でつまずいてしまう

そんな悩みを解決してくれるのが「**x.infer**」です！このライブラリを使えば、1000以上の画像認識モデルを**たった4行**のコードで使えるようになります。

今回は、Google Colabを使って実際に動かしてみましょう。

<blockquote class="twitter-tweet" data-media-max-width="800"><p lang="ja" dir="ltr">x.infer を早速Google Colabで実装してGradioアプリで遊んでみた！！<br>まじで簡単にできてエグイ！！！<br>今後はこれがベースになりそうな気がする！ <a href="https://t.co/8SN4UyScgN">https://t.co/8SN4UyScgN</a> <a href="https://t.co/tamPeB2ocq">pic.twitter.com/tamPeB2ocq</a></p>&mdash; Maki@Sunwood AI Labs. (@hAru_mAki_ch) <a href="https://twitter.com/hAru_mAki_ch/status/1850079029443035549?ref_src=twsrc%5Etfw">October 26, 2024</a></blockquote> 

## 🌟 x.inferの特徴

- **シンプルな統一インターフェース**：異なるフレームワークのモデルも同じ方法で使える
- **豊富なモデル対応**：Transformers, TIMM, Ultralytics, vLLM, Ollamaなど
- **タスクの多様性**：画像分類、物体検出、画像からテキスト生成など

## 💻 Google Colabでの実装手順

### 1. 環境セットアップ
まずは必要なライブラリをインストールします。

```python
!pip install "xinfer[all]"  # すべての依存関係をインストール
```

### 2. 基本的なインポートと動作確認
```python
import xinfer

# 利用可能なモデルの一覧を表示
xinfer.list_models()
```

### 3. 画像キャプション生成を試してみる
実際に画像の説明を生成してみましょう。

```python
# モデルの初期化
model = xinfer.create_model("vikhyatk/moondream2")

# テスト用の画像URL
image = "https://raw.githubusercontent.com/vikhyat/moondream/main/assets/demo-1.jpg"
prompt = "Describe this image."

# 推論の実行
result = model.infer(image, prompt)
print(result)
```

### 4. インタラクティブなデモの起動
Gradioを使って、ブラウザ上で操作できるデモを起動できます。

```python
# モデルのGradioインターフェースを起動
model.launch_gradio()

# または、すべての利用可能なモデルを含むデモを起動
xinfer.launch_gradio_demo()
```

## 🔍 使用時の注意点
1. **GPUの有効化**
   - Google Colabで実行する場合は、「ランタイム」→「ランタイムのタイプを変更」からGPUを選択することをおすすめします
   - GPUを使用することで処理速度が大幅に向上します

2. **初回実行時の注意**
   - ライブラリのインストールには数分かかることがあります
   - モデルの初回ダウンロードも時間がかかる場合があります
   - 安定した通信環境で実行することをおすすめします

3. **メモリ使用量**
   - 大きなモデルを使用する場合は、他のセルの実行を停止してメモリを確保することをおすすめします

## 📚 発展的な使い方
- 異なるモデルの比較
- バッチ処理による複数画像の同時処理
- カスタムモデルの追加

## 🎯 まとめ
x.inferを使うことで、最新の画像認識モデルを簡単に試すことができます。特に：

- ✅ セットアップが簡単
- ✅ 統一的なインターフェース
- ✅ 豊富なモデル選択
- ✅ 直感的なAPI


ぜひGoogle Colabで試してみてください！新しいモデルの実験が、今までよりもずっと簡単になるはずです。


## ノートブック

https://colab.research.google.com/drive/12ri7-Llf8UgwGhj77NPCZ2PgiGw4LDpV?usp=sharing

## 🔗 参考リンク

https://github.com/dnth/x.infer?tab=readme-ov-file#quickstart


<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Excel VBA オートフィルターで特定の列の複数項目を除外する

## はじめに
VBAのオートフィルターで、特定の列の複数項目を含む条件には、配列を使えばよい。
では、逆に特定の列の複数項目を除く条件の場合には、どうすればよいか考えたい。

## マクロ作成の経緯
CSVデータのうち、A列の複数項目を含むデータのみを残し、他のデータは削除したい。
この他のデータをまとめて削除する方法はないかと考えたのがきっかけだった。
 
複数項目を含むという条件でオートフィルターを使い、結果を別シートにコピーすればよいのだが、他のデータだけをまとめて削除できたら、もっとシンプルになるのではと考えた。

結果、別シートにコピーする方がシンプルだったが、複数項目を除く条件を設定したい場合には使えるのではと思う。

## 作成したマクロの概要
オートフィルターに複数項目を除く条件を直接設定することはできない。
作業セルを使う方法をヒントに、除外したい項目に印をつける方法で作成することにした。

### 動作手順
1. 別シートにある指定した項目と、項目ラベルからデータ一覧の列番号を取得する
1. 指定した項目・列番号のオートフィルターを実行する
1. 指定した項目のデータのA列セルを塗りつぶす
1. A列の塗りつぶされていないセルをオートフィルターで抽出する
（結果、指定した項目を除くデータが表示される）

#### 注意点
- A列に始めからセルの塗りつぶしデータがある場合は使えない
(塗りつぶしを初期化してしまうため、元々の塗りつぶしが消えてしまう)


## 完成したマクロ
前提として、データ一覧とは別の「除外条件」シートに条件を記載。
データ一覧のあるシートをアクティブにして、マクロを実行する。
### 「除外条件」シートのイメージ
![スクリーンショット 2024-10-25 164627.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917113/f6fcf980-ce28-5f87-83cf-60453d1424d1.jpeg)


### データ一覧のあるシートのイメージ

サンプルとして、総務省の統計に用いる標準地域コードのCSV形式の全国版を使用した。

https://www.soumu.go.jp/toukei_toukatsu/index/seido/9-5.htm

![スクリーンショット 2024-10-25 165006.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917113/2570c0d5-3e86-0c4d-cf3f-d140c46a6c6b.jpeg)


### 作成したコード
```VB:AutofilterExcludeMultiple
Public Sub AutofilterExcludeMultiple()
Dim TargetColumnNo As Long
Dim ItemCount As Long
Dim TargetItemArray() As String
Dim i As Long

    '項目列番号・除外対象項目を取得
    With ThisWorkbook.Sheets("除外条件")
    
        TargetColumnNo = WorksheetFunction.Match(.Range("A2").Value, ActiveSheet.Rows(1), 0)       
        
        ItemCount = .Range(.Range("C2"), .Range("C2").End(xlDown)).Count
        ReDim TargetItemArray(ItemCount - 1) 
        
        For i = 0 To ItemCount - 1    
            TargetItemArray(i) = .Cells(i + 2, "C").Value       
        Next i 
        
    End With

    With ActiveSheet
        'オートフィルターが設定されている場合には解除
        If Not .AutoFilter Is Nothing Then .Range("A1").AutoFilter 
        .Columns(1).Interior.Color = xlNone
        
        .Range("A1").AutoFilter Field:=TargetColumnNo, Criteria1:=TargetItemArray, Operator:=xlFilterValues
        .Range(.Range("A2"), .Range("A2").End(xlDown)).Interior.Color = vbYellow
        
        .ShowAllData
        .Range("A1").AutoFilter Field:=1, Operator:=xlFilterNoFill
            
    End With

End Sub
```

サンプルファイル保存先：

https://github.com/rie1234k/ExcelVBA_Tips/tree/master/AutofilterExcludeMultiple

## 参考
- [複雑な条件（複数除外等）のオートフィルター（AutoFilter）｜VBA技術解説](https://excel-ubara.com/excelvba4/EXCEL259.html "タイトル")
Dual USB DAC

JazzSakuraをmpg123で鳴らしているRT3883なモジュールはUSBポートが二つあるので、両方にDACを接続してみました。

```
uaudio0 on uhub0
uaudio0: <Ten X Technology, Inc. USB  AUDIO, class 0/0, rev 1.10/1.40, addr 3> on usbus1
uaudio0: Play[0]: 48000 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio0: No recording.
uaudio0: No MIDI sequencer.
pcm0: <USB audio> on uaudio0
uaudio0: HID volume keys found.
uaudio1 on uhub0
uaudio1: <Burr-Brown from TI USB Audio DAC, class 0/0, rev 1.10/1.00, addr 2> on usbus1
uaudio1: Play[0]: 48000 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio1: Play[0]: 44100 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio1: Play[0]: 32000 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio1: No recording.
uaudio1: No MIDI sequencer.
pcm1: <USB audio> on uaudio1
uaudio1: HID volume keys found.
```

0がTP6902でキッチンのスピーカーに接続されていて、1がPCM2704でリビングのパソコンの付属のパワードスピーカーに接続されています。音は追求せずセルフパワーでお手軽なので、この二つにしました。

kldは起動してから以下のスクリプトでロードしています。

```
#!/bin/sh

# USB Power On
#gpioctl -f /dev/gpioc1 11 1

kldload snd_uaudio
kldload umass
kldload msdosfs

mixer -f /dev/mixer0 pcm 75 vol 6
mixer -f /dev/mixer1 pcm 90 vol 90

sysctl hw.snd.default_unit=1
```

TP6902をデフォルトのボリュームで鳴らすと大きすぎるので、小さくしています。

切り替えのスクリプトも用意してみました。

```
#!/bin/sh

CUR=`sysctl -n hw.snd.default_unit`

if [ ${CUR} -eq 0 ]; then
sysctl hw.snd.default_unit=1
fi
if [ ${CUR} -eq 1 ]; then
sysctl hw.snd.default_unit=0
fi
```

当たり前ですが、再生中に切り替えても代わりません。

いろいろ決め打ちでお行儀が悪いのですが、そもそもFreeBSDのサウンド機能がへっぽこなので、こんなところで良しとします。
教科「情報」でChromebookとPythonとVSCodeとJupyter Notebook

## 0. はじめに
高校でChromebookを使って、プログラミング教育を行うための環境構築手順をシミュレーションしてみました。

## 1. Linuxを有効化
1. 設定アプリで、次の手順で有効化する。
   「ChromeOSについて」→「Linux 開発環境」→[設定]→「Linux 開発環境をセットアップする」→[次へ]→ユーザー名を設定→[インストール]→ターミナルが開く
1. 日本語入力のための設定は必要ない

## 2. フォントとモジュールのインストール
1. 開いたターミナルで、まずは
   ```bash
   sudo apt update && sudo apt upgrade -y
   ```
1. VSCodeを日本語化したとき、メニューがぼやけるので、きれいな日本語フォントをインストールする
   ```bash
   sudo apt install fonts-noto-cjk -y
   ```
1. 仮想環境を作りパッケージをインストールしたいので、venvをインストールする
   ```bash
   sudo apt install python3-venv -y
   ```
1. matplotlibのグラフを表示するためにtkinterをインストールする
   ```bash
   sudo apt install python3-tk -y
   ```
   VSCodeでJupyter Notebookを利用する場合は不要。

## 3. VSCodeのインストール
1. [公式サイト](https://code.visualstudio.com/download)からDebian用の.debファイルをダウンロードする
1. .debファイルをダブルクリックしてLinuxにインストールする

## 4. VSCodeにPython開発環境を設定
1. ランチャーからVSCodeを起動する
1. 日本語化のための拡張機能をインストールする
1. Pythonの拡張機能をインストールする
1. Jupyterの拡張機能をインストールする（以前はPythoの拡張機能とともにインストールされていたが、別になった。）
1. 「MyProjects」というフォルダを作成し開く
1. [Ctrl]+[Shift]+[@]キーを押し、ターミナルを開く
1. 仮想環境を作成する
   ```bash
   python3 -m venv venv
   ```
1. 仮想環境をアクティブ化する
   ```bash
   source venv/bin/activate
   ```
   アクティブ化すると、ターミナルの先頭に (venv) と表示される。       
1. 仮想環境のpipをアップデートする
   ```bash
   python3 -m pip install --upgrade pip
   ```
1. 仮想環境にjupyterをインストールする
   ```bash
   python3 -m pip install jupyter
   ```
1. 必要なパッケージがわかっていればインストールしておく（今回は、次の起動確認のために matplotlib をインストールする）
   ```bash
   python3 -m pip install matplotlib
   ```

## 5. 起動確認
1. VSCodeのメニューの「ファイル」→「新しいファイル」→「Jupyter Notebook」から新しいnotebookを作成する
1. 4-7で作成した仮想環境のカーネルを選択する
1. 次のコードを入力して実行する
   ```python:parabolic_motion.ipynb
   import math as math
   import matplotlib.pyplot as plt
   plt.rcParams['font.family'] = 'Noto Sans CJK JP'  # matplotlibで日本語を表示するための設定
   
   dt = 0.01
   v0 = 30
   g = 9.8
   x = [0]
   y = [0]
   angle = 45.0 * math.pi / 180.0
   vx = [v0 * math.cos(angle)]
   vy = [v0 * math.sin(angle)]
   for i in range(1000):
       vx.append(vx[i])
       vy.append(vy[i] - g * dt)
       x.append(x[i] + vx[i] * dt)
       y.append(y[i] + (vy[i] + vy[i + 1]) / 2.0 * dt)
       if y[i] < 0:
           break
   plt.plot(x, y)
   plt.title("物体の放物運動")
   plt.xlabel("水平距離")
   plt.ylabel("高さ")
   plt.show()
   ```
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1849635/4c46f276-f9d4-26c2-ff75-c83effe426a3.png)
1. 成功！
実際はネットワークの通信速度の問題から、こんなにうまくいかないと思いますが。
【Apex】Salesforce ApexにおけるListの要素検索: ２重ループを回避するベストプラクティス

# はじめに 

Salesforce Apexを使用して開発を行う際、Listから特定の要素を検索することは頻繁にあります。しかし、初心者の方は二重ループを使ってしまうことが多く、パフォーマンスが低下しがちです。

本記事はコーディング経験がほとんど無い方から、少しコーディングに慣れてきた方あたりを対象としています。

たとえば、以下のようなコードです。

```apex
Id targetUserId = '0001';
for(Account acc : accList){
    Id ownerId;
    for(Contact cnt : cntList){
        if(cnt.AccountId == targetUserId){
            ownerId = cnt.OwnerId;
        }
    }
}
```
このコードは、accList と cntList の2重ループで検索を行っていますが、データ量が多い場合、パフォーマンスが悪化する原因となります。

# Setを活用してパフォーマンスを向上させる
Setを使うことで、パフォーマンスを向上させながら同じ処理を実現できます。以下が、Setを活用した修正版コードです。

```apex
コードをコピーする
Id targetUserId = '0001';
Set<Id> accountIdSet = new Set<Id>();
for(Contact cnt : cntList){
    accountIdSet.add(cnt.AccountId);
}

if(accountIdSet.contains(targetUserId)){
    for(Contact cnt : cntList){
        if(cnt.AccountId == targetUserId){
            Id ownerId = cnt.OwnerId;
            // 必要な処理をここに記述
            break;
        }
    }
}
```

# まとめ
このように、事前に Set を作成して該当する Id を格納しておくことで、特定の要素が存在するかの確認を効率的に行うことができます。また、二重ループが不要となり、コードの見通しも良くなります。
week コマンドの --dodgers と --yankees オプション

[week]: https://github.com/kaz-utashiro/App-week
[optex]: https://github.com/kaz-utashiro/optex
[Getopt::EX]: https://github.com/kaz-utashiro/Getopt-EX
[Getopt::EX::i18n]: https://github.com/kaz-utashiro/Getopt-EX-i18n
[termcolor]: https://github.com/kaz-utashiro/Getopt-EX-termcolor
[Getopt::EX::Colormap]: https://metacpan.org/pod/Getopt::EX::Colormap

## week コマンドの続き

- [ターミナルで使える色っぽいカレンダー - Qiita](https://qiita.com/kaz-utashiro/items/603f4bca39e397afc91c)
- [ライオンズカラーのカレンダーと termcolor モジュール - Qiita](https://qiita.com/kaz-utashiro/items/38cb50a4d0cd34b6cce6)
- [Tokyo2020 カレンダーと i18n モジュール - Qiita](https://qiita.com/kaz-utashiro/items/be37a4d703f9d2208ed1)
- [week コマンドの金メダル仕様と和暦表示](https://qiita.com/kaz-utashiro/items/d894932819b83a0be611)

## --dogders と --yankees オプション

先日 `--dodgers` オプションは実装してあったのだけど、ワールドシリーズを見ながら `--yankees` オプションも作ってみました。ただ、この2つのチーム、色調が似ていてつまんないのでピンストライプも入るようにしてみた。

配色がよくないと思う方はプルリクください。

![スクリーンショット 2024-10-26 15.21.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36551/2aa062de-0775-8697-7d17-0733dc5b0b93.png)

![スクリーンショット 2024-10-26 15.21.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36551/c35fb008-f414-2df7-f833-8c38922fdda8.png)

## --tigers

ではということで `--tigers` も縞模様になりました。

![スクリーンショット 2024-10-26 15.35.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36551/564e8cf8-70fa-2e5f-7d32-e04f9e50b1e0.png)

## インストール

cpanminus でどうぞ。

    cpanm App::week

## SEE ALSO

https://github.com/kaz-utashiro/App-week

https://metacpan.org/dist/App-week
SPF, DKIM, DMACのフィルタ情報の整理

# はじめに
可視化した件について、以下に記載しました。

https://qiita.com/matsuhira/items/e1c5e5b068561e4c6bdb

見易くなったことから、解析とは言わないものの、いろいろ調べてみたくなりました。となると、フィルタする情報を整理した上で、なるべく見落としが無い環境にしたくなりました。このフィルタ情報を記載します。

# SPF
* spf=pass
* spf=none
* spf=softfail
* spf=permerror
* spf=neutral
* spf=fail
* spf=temperror

 # DKIM
* dkim=pass
* dkim=none
* dkim=fail
* dkim=neutral
* dkim=temperror
* dkim=permerror
* dkim=policy
* dkim-adsp=none
* dkim-adsp=pass

dkim-adspは廃止らしいのですが、実際のメールのヘッダで見たので、入れることにしました。
# DMARC
* dmarc=pass
* dmarc=none
* dmarc=fail

# sender-id
* sender-id=pass
* sender-id=none
* sender-id=fail
* sender-id=softfail
sender-idについても、ついでですので、入れることにしました。

# 参考情報
https://eng-blog.iij.ad.jp/archives/20946
concurrent.futuresでLockの使い方

# concurrent.futuresでLockの使い方

---

### **Lockとは？**

- **Lock** は、複数のスレッドやプロセスが同時に共有変数やリソースにアクセスする際に、そのアクセスを制御するための仕組みです。
- Lockを使うことで、**データの整合性** を守ることができます。これにより、複数のスレッドが同時に変数を変更してしまう「競合状態（race condition）」を防ぐことができます。

### **例題 1: `import threading` を使った Lock の利用**

まず、`import threading` を使って Lock を導入する例を見てみましょう。

#### **コード: import threading を使う例**

```python
from threading import Thread, Lock
import time

database_value = 0

def increase(lock):
    global database_value

    with lock :
        local_copy = database_value
        # processing
        local_copy += 1
        time.sleep(0.1)
        database_value = local_copy



# スクリプトを直接実行する場合のみメイン関数を呼び出す
if __name__ == "__main__":

    lock = Lock()
    print("start value", database_value)
    thread_1 = Thread(target=increase, args=(lock,))
    thread_2 = Thread(target=increase, args=(lock,))

    thread_1.start()
    thread_2.start()

    thread_1.join()
    thread_2.join()

    print("end value", database_value)

```

#### **解説**

- **Lockの目的**: 上記のコードでは、複数のスレッドが `counter` という共有変数を同時に更新します。Lockを使うことで、1つのスレッドが変数の変更を完了するまで、他のスレッドのアクセスを一時的に停止します。これにより、データの不整合が防止されます。

- **使い方**: `with lock` という構文で、Lockを使ったブロックを定義し、そのブロック内での処理が終わるまで他のスレッドが変数にアクセスできないようにしています。

### **例題 2: `concurrent.futures` を使った Lock の利用**

次に、`from concurrent.futures` を使って、同じように Lock を導入する例を見てみましょう。

#### **コード: concurrent.futures を使う例**

```python
from concurrent.futures import ThreadPoolExecutor
import threading
import time

database_value = 0
lock = threading.Lock()


def increase():
    global database_value

    with lock:
        local_copy = database_value
        # processing
        local_copy += 1
        time.sleep(0.1)
        database_value = local_copy


if __name__ == "__main__":
    print("start value", database_value)

    # ThreadPoolExecutorを使用して2つのスレッドを実行
    with ThreadPoolExecutor(max_workers=2) as executor:
        # 2つのタスクを同時に実行
        futures = [
            executor.submit(increase)
            for _ in range(2)
        ]

        # すべての結果を待つ
        for future in futures:
            future.result()

    print("end value", database_value)
```

#### **解説**

- このコードでは、`ThreadPoolExecutor` を使って、最大4つのスレッドで `increment()` 関数を並行に実行します。
- Lockの使い方は、`import threading` を使った場合と同様です。`with lock` を使うことで、スレッドごとの変数更新が保護されます。
- **`concurrent.futures` を使う理由**: これを使うと、スレッドの管理がよりシンプルになり、`submit()` メソッドで関数を並行に実行できます。これにより、スレッドの作成と管理が統一された構造で行えます。

### **Lockが必要な理由**

- **データ競合の防止**: Lockを使うことで、複数のスレッドが同時に同じ変数にアクセスし、データを不整合にすることを防げます。これにより、プログラムの動作が正確になります。
- **例外的な状況の回避**: Lockを使わない場合、変数の更新中に他のスレッドがアクセスする可能性があり、最終的な計算結果が正しくない場合があります。

### **まとめ**

- Lockは、並行処理においてデータの整合性を守るために必要です。
- `concurrent.futures` でもLockを使うことができ、よりシンプルに並行処理を実装できます。
- Lockを適切に使うことで、データの競合を防ぎ、プログラムが意図した通りに動作するようにできます。

## 参考資料

Threading in Python - Advanced Python 16 - Programming Tutorial
https://youtu.be/usyg5vbni34?si=3skpeFP_TZ_L1Yp1


https://qiita.com/kotai2003/items/f0de0fb372f69ab6d3f4

https://qiita.com/kotai2003/items/2ac0b31245bb0d59a7ec
WindowsとFedoraのデュアルブート環境でrEFIndを使ってみた

# 筆者について

現在高校3年生
（元）水泳部マネージャー
（元）生徒会長
（元）とある団体の代表

# 本題

先日、一つのデスクトップPCをいただける手筈となったのですが、その時にふとFedoraを入れてみようと思ったのが一番最初のきっかけでした。その時に、GrubもWindows Boot Managerも好きじゃないので以前学校にあったIntelのMacで利用していたrEFIndを使ってみることにしました

https://www.rodsbooks.com/refind/

これね、僕からしたら起動の時点でBootするOSを選べるのはなかなか初心者には優しいと思うので、とりあえずチャレンジしてみましょう

# Dual-Boot環境の構築

まず最初にSSDの初期化を行なった上で、Windows 11 Proをインストールし、その後パーティションを分割した上でFedoraをインストールしました。これに関しては他の方が書いている記事がたくさんあると思うのでそちらの方を参考にしてください

https://qiita.com/kiwsdiv/items/1fa6cf451225492b33d8

こちらの記事はUbuntuですが要領はおなじです。需要あれば追記するかも（多分ない）

# rEFIndのインストール

まずはお決まりの。

```zsh
sudo dnf update && sudo dnf upgrade

sudo dnf install rEFInd
```

ここまできたらあとはもう少しです！

```zsh
sudo refind-install
```

終わりました！って、早すぎんだろ！！

あと最後に一つ、この状態でBIOSを開くとSSDのブート優先順位でおそらくrEFIndを使える状態になっていますので、こちらを選択すると、これからは一番最初にBootするOSを選択できるようになります。

# Boot Menuの変更

ここから先は完全に好みの設定となります。今回は取り扱いませんが、テーマの設定とかも変えれますのでやりたい方はぜひ！

僕の場合は基本的にFedoraのGrubだけ起動してくれたらそれでよかったので、他のメニューを全部削除したかったんです。ただ、検出されているものを削除するよりもマニュアルエントリーを作る方が簡単でしたので
僕の場合はマニュアルエントリーを作りました。

```diff_config:refind.conf
# 以下のところをコメントアウト
- scanfor internal,external,optical,manual,firmware
+ scanfor external,manual,

# 最下層に追加

menuentry Fedora {
    loader /EFI/fedora/grubx64.efi
    icon /EFI/refind/icons/os_fedora.png
    disabled
}

menuentry "Windows 11" {
    loader /EFI/Microsoft/Boot/bootmgfw.efi
    disabled
}

```

僕の環境ではこれで動きましたが、もしここで起動設定の記述を間違えているとOSを起動するのに結構手間がかかるようになるので、マニュアルエントリーの設定が正しいことを確認してから起動構成検出をしないようにする方が良いと思います。

# 最後に

まあそもそもの話でデュアルブートとかは危ないので、全て自己責任でお願いします。
SerializeField の Null チェックをできるだけ簡単に行う

# やりたいこと
SerializeField で null になってたらダメなフィールドが null だったら起動時に警告されるようにしたい。


# 実装

Null を許さないフィールドにつける用のアトリビュートを作成

```csharp
using System;

[AttributeUsage(AttributeTargets.Field)]
public class NonNullable : Attribute
{
}
```

`MonoBehaviour` を拡張して、 `NonNullable` がついているフィールドが null ならエラーログを出す `NullCheck` メソッドを生やす。

```csharp
using System;
using System.Reflection;
using UnityEngine;

namespace MyExtension
{
    public static class ExtenstionNullCheck
    {
        [RuntimeInitializeOnLoadMethod()]
        public static void NullCheck(this MonoBehaviour obj)
        {
            var fields = obj.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);

            foreach (var field in fields)
            {
                // クラスの名前
                var className = obj.GetType().ToString();
                // 値
                var val = field.GetValue(obj);
                // NonNullable属性があるかどうかを確認
                var isNonNullable = Attribute.GetCustomAttribute(field, typeof(NonNullable)) != null;

                // チェック処理
                if (isNonNullable && (val.Equals(null) || val == null))
                {
                    Debug.LogError(string.Format("{0} クラスの {1} フィールドは NonNullable ですが、値が null です", className, field.Name));
                }
            }
        }
    }
}
```

あとは以下のよう null チェックをしたいフィールドに `NonNullable` をつけて、`NullCheck` を呼び出すだけで `Start()` 時に null だったら警告が出るようになる。

```csharp
using UnityEngine;
using MyExtension;

public class Hoge : MonoBehaviour
{
    [NonNullable, SerializeField] private string _name;
    [NonNullable, SerializeField] private GameObject _panel;

    public void Start()
    {
        this.NullCheck();
	}
}
```
WSLにて新規ディストリビューションを作成する 

個人的備忘録として。

【目的】
VScodeにてUbuntu 24.04 LTSの新規ディストリビューションを作成し、開発環境としたい

【環境】
Windows11
WSL2
Ubuntu 24.04 LTS

### 目次
[1. Ubuntuの取得](#1-ubuntu-2404-ltsのルートファイルシステムを取得する)
[2. WSLにインポート](#2-wslに新規ディストリビューションとしてインポートする)
[3. 初期設定](#3-初期設定を行う)

---

### 1. Ubuntu 24.04 LTSのルートファイルシステムを取得する
以下のリンクから使用したいバージョンのものを取得する。
https://cloud-images.ubuntu.com/releases/

今回は24.04 LTSを使用したいので以下のリンクから`ubuntu-24.04-server-cloudimg-amd64-root.tar.xz`をダウンロードした。
どのバージョンであっても`root.tar`をダウンロードすれば問題はないはず。
https://cloud-images.ubuntu.com/releases/24.04/release/

### 2. WSLに新規ディストリビューションとしてインポートする
コマンドプロンプトにて以下のコマンドを叩き、新しいディストリビューションをインポートする。
```
$ wsl --import <ディストリビューション名> <インストール先パス>　<インストール元パス> --version 2
```
1で取得したファイルを使用するならこんな感じ
```terminal:コマンドプロンプト
$ wsl --import Ubuntu2404 C:\WSL\Ubuntu2404 C:\Users\User\Downloads\ubuntu-24.04-server-cloudimg-amd64-root.tar.xz --version 2
```
`$ wsl -l -v`を叩いてディストリビューション名が表示されていたらインストール成功。

### 3. 初期設定を行う
新規ディストリビューションの作成なら2.までで終了で問題ないが、
いつも以下の初期設定まで行う。
1. 必要なパッケージのアップデート
1. ユーザの追加
1. ユーザ権限の付与
1. デフォルトユーザの設定


以下のコマンドでWSL内に入る
```terminal:コマンドプロンプト
$ wsl -d Ubuntu2404
```

#### アップデート & アップグレード
```terminal:wsl
$ apt update
$ apt upgrade
```

#### WSLユーザの作成 & ユーザにsudo権限を付与
```terminal:wsl
$ adduser testUser
$ usermod -aG sudo testUser
```

#### WSLのデフォルトユーザの設定
```terminal:wsl
$ sudo vi /etc/wsl.conf
```
以下を記入して保存
```vim:/etc/wsl.conf
[user]
default=testUser
```

WSLから抜ける
```terminal:wsl
$ exit
```
WSLをシャットダウン
```terminal:コマンドプロンプト
$ wsl --shutdown
```


### 4. 初期設定の確認
```terminal:コマンドプロンプト
$ wsl -d Ubuntu2404
```
WSLに入ってユーザを確認する。
`$ whoami`を叩いて、設定したデフォルトユーザが返ってきたらOK
```terminal:wsl
$ whoami
> testUser
```


以上。
CISA/CISMの維持に必要なCPEの話

# はじめに
受験記録を書いてから半年ほど経ったので、資格維持のための学習要件（CPE）について記載しておきます。

# CPEについて
CISA、CISMの維持には1年あたり20CPE以上、3年間で120CPEの取得を行う必要があります。
つまり、年40CPEを継続取得していけば良いことになります。
CISAとCISMは同じ内容で申請できるので、複数保有でも労力は単体保有と同じです。

# CPEの取得項目
殆どの人は他の人への教育や講演をすることは無いと思うので、以下から取得になります。

|項目|取得できるCPE|
|---|--|
| ISACA以外のセキュリティ関連の資格を取得 | 試験時間1Hあたり1CPE |
| ISACA以外のセキュリティ関連のEラーニング受講 | 1Hあたり1CPE |
| ISACA以外のセキュリティ関連のセミナー受講 | 1Hあたり1CPE |
| セキュリティ関連のブログ執筆 | 執筆時間1Hあたり1CPE |
| ISACAの組合イベント参加 | 1Hあたり1CPE |
| ISACAサイトのジャーナルクイズ合格(年6CPEまで) | 1問あたり1CPE |
| 年に何回かISACAからメールでアンケート依頼が来るのでWEBから回答するとCPEが貰える| 1回1CPE |

# 実際の取得内容
エビデンスは自身で保存し、結果だけISACAのポータルサイトで登録して申請します。
ポータルサイトは英語ですがGoogle翻訳も出来るのでそれほど難しい作業ではありません。
|項目|説明|取得できるCPE|
|---|---|---|
| ジャーナルクイズ | ISACAのサイトでクイズに答える<br>1問10分くらいです<br>6問 x 1.0CPE | 6.0 CPE |
| 組合の月例会議参加 | 参加支部の月次のオンライン会議に参加<br>10回 x 2.5H | 25.0 CPE |
| アンケート | ISACAのWEBアンケートに回答<br>2回 x 1.0CPE | 2.0 CPE |
| Eラーニング | Udemyのセキュリティ講座を受けました<br>5H x 1回 | 5.0 CPE |
| セミナー参加  | ISACA外のセキュリティセミナーに参加<br>2回 x ２H  | 4.0 CPE  |
| 合計 |  | 42 CPE |

見てわかる通り、クイズと月例会議の参加だけで殆どのCPEが溜まります。
それほど労力は掛からないので、皆さんも是非取得を目指してください。