OmniAICreator/Qiita-1.07M huggingface dataset:
DockerがESETの影響でファイルマウントできない場合の対処法


DockerがESET Endpoint Protectionのファイアウォールの影響で「Firewall Detected」エラーが発生し、ファイル共有が一切できなくなる問題の対処方法を掲載しています。

:::note warn

※ これは2019-07-15に[個人ブログ](https://bicstone.me)で公開した記事を移植し、[CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/deed.ja)で提供しています。情報は古い可能性があります。

:::

## Docker でファイルマウントができない

Dockerでファイルのマウントが一切できない状態になりました。

Dockerを右クリック →「Settings」

![Dockerを右クリック→「Settings」](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/bfdb947a-9097-9f9e-311e-88d20f9bf492.png)

「Shared Drives」→「Shared」にチェック →「Apply」

![「Shared Drives」→「Shared」にチェック→「Apply」](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/cfc45a70-6ba1-9d57-6ba6-4128936a85d3.png)

「Docker needs to access your computer's filesystem」にファイルシステムへアクセスができるユーザー情報を入力。

![「Docker needs to access your computer's filesystem」にファイルシステムへアクセスができるユーザー情報を入力](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/ba76d1f2-1df4-8fe3-3eb6-587eb7a10fc3.png)

「Firewall detected」エラーが発生。

![「Firewall detected」エラーが発生](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/e2fa131d-f1f9-ec63-777c-f1c68b60f968.png)

## ファイアウォールの解除方法

PCに入っていた「ESET Endpoint Protection」のファイアウォール機能が原因でした。

「ESET Endpoint Protection」を起動し、「設定」→「ネットワーク」をクリックします。

![ESET Endpoint Protection のメイン画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/ded8bae3-f1e7-41e4-cb3f-e07d148413b1.png)

再度Dockerを操作して「Firewall detected」エラーを発生させた後、「トラブルシューティングウィザード」をクリックします。

![トラブルシューティングウィザード　を選択する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/a4b20cae-e662-cb67-1554-1fdf47115d1a.png)

「ネットワーク保護トラブルシューティング」のIPアドレス「10.0.75.2」を探し出し、「ブロック解除」をクリックします。あまりにも数が多く見つからない場合は「最後の5分」をします。

![ネットワーク保護トラブルシューティング を開き、フィルターを「最後の5分」と選択し、10.0.75.2をブロック解除する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/59ca6aed-b4c4-3a0c-1f05-ecac7c0d6aeb.png)

「以前にブロックされた通信と類似した通信は許可されます」と表示されるので「完了」をクリックします。

![以前にブロックされた通信と類似した通信は許可されます　ダイアログが表示されるので「完了」をクリックする](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/919f5f7f-3c30-79e0-4f0a-360097972e4b.png)

再度「Shared」にチェックして、「Apply」をクリックするとマウントが可能になります。できない場合は「Reset Credentials」をクリックするか、再起動してみてください。

![Docker の Shared Drives でオフ→オンする](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/7b0afa3f-8ca6-59b9-70f4-bf8e362cb337.png)
Vagrant で Apache が自動起動しない場合の対処法


Vagrant + VirtualBoxでApacheを動かすと、 `DocumentRoot is not a directory, or is not readable` で自動起動せずに強制終了してしまい、手動でのサービス再起動が必要になってしまいます。Apacheを強制終了しないようにする方法を紹介します。

:::note warn

※ これは2020-02-11に[個人ブログ](https://bicstone.me)で公開した記事を移植し、[CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/deed.ja)で提供しています。情報は古い可能性があります。

:::

## 強制終了してしまう

仕事でLaravelを使ったWebサイトをVirtualBoxで構築(指定されたので...)していたところ、 `vagrant up` してもApacheが自動起動せずに強制終了してしまう現象に遭遇しました。

ログには次のように残っています。

```sh
Main PID: 1021 (code=exited, status=1/FAILURE)
systemd[1]: Starting The Apache HTTP Server...
httpd[1021]: AH00526: Syntax error on line 5 of /etc/httpd/conf/httpd.conf:
httpd[1021]: DocumentRoot '/var/www/public' is not a directory, or is not readable
systemd[1]: httpd.service: main process exited, code=exited, status=1/FAILURE
kill[1455]: kill: cannot find process ""
systemd[1]: httpd.service: control process exited, code=exited status=1
systemd[1]: Failed to start The Apache HTTP Server.
systemd[1]: Unit httpd.service entered failed state.
systemd[1]: httpd.service failed.
```

Apacheから、DocumentRootが読めないというエラーになっています。

`DocumentRoot '/var/www/public' is not a directory, or is not readable`

しかし、この後にサービスの再起動をすると強制終了せずに動作します。

## 原因

原因は、Vagrantによるマウントが完了する前にApacheが起動してしまい、DocumentRootのシンボリックリンクが読めないため発生しています。

## 対処方法

かなり対処療法ですが、VagrantFileによるマウントの記述の後にApacheを再起動することで対処します。

CentOS 7系の場合はマウントの記述の後に下記を追加します。

```rb
config.vm.provision :shell, run: "always", :inline => <<-EOT
  sudo systemctl restart httpd.service
EOT
```

その他は下記を追加します。

```rb
config.vm.provision :shell, run: "always", :inline => <<-EOT
  sudo service httpd restart
EOT
```

以上で、マウント後にApacheが自動再起動されます。

ちなみに、`vagrant up` 時にApacheの再起動をした際のログが次のように残ります。

```sh
==> default: Running provisioner: shell...
    default: Running: inline script
```
Vagrant(VirtualBox)でディスクアクセスが遅い問題の対処法


Windows + Vagrant + VirtualBoxでLaravelを動かすと、ローディングにかなりの時間がかかって仕事が進まなかったという問題の対処方法を紹介します。NFSを使用する方法です。

:::note warn

※ これは2020-02-01に[個人ブログ](https://bicstone.me)で公開した記事を移植し、[CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/deed.ja)で提供しています。情報は古い可能性があります。

:::

## Virtual Box の共有フォルダ機能は遅い

ホスト側とゲスト側でプログラムファイルなどを共有するためにVirtualBoxには共有フォルダ機能が存在しますが、デフォルトの共有方法を用いるとかなり遅くなります。

仕事でLaravelを使ったWebサイトをVirtualBoxで構築していたところ、Windows環境やMac環境でも1ページ読み込むのに5秒ほどかかり、まともに仕事ができない状態になってしまいました。

![Laravelのデバッグツールのスクリーンショット、Bootingに1.15s、Appに1.03sかかっている](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/ac106095-9e40-a975-fd51-e0da5d775443.png)

デフォルトのファイル共有機能は、比較的安定性は高く、多くのOSで使用できるのですが、メモリキャッシュなどの機能を使用していないため、ディスクアクセスは遅い欠点があります。

一方、Laravelは大量の依存ファイルを読み込むのでディスクアクセスが大量に発生します。そのため表示が遅くなります。

## 対処方法

Dockerなどの仮想化技術が使用できるツールに切り替えができるのであれば、切り替えるのをおすすめします(ちなみにDocker ToolBoxはVirtualBoxを使用するので意味ありません...)。それができない場合は、NFSでマウントする機能を使用します。

仕組みは公式ドキュメントをご確認ください。

https://www.vagrantup.com/docs/synced-folders/nfs

## Windows の場合はプラグインが必要

公式ドキュメントには次の記載があり、Windowsホストでは使えないと書いてあります。

> Windows users: NFS folders do not work on Windows hosts. Vagrant will ignore your request for NFS synced folders on Windows.

ところが、なんとWindowsでNFS機能を使用できるプラグイン(`vagrant-winnfsd`)がコミュニティに存在します！素晴らしすぎて感謝してもしきれません。

https://github.com/winnfsd/vagrant-winnfsd

ホスト側がWindowsの場合は下記コマンドでプラグインを先にインストールしておいてください。

```bash
vagrant plugin install vagrant-winnfsd
```

## NFS に変更する方法

NFSに変更するにはVagrantFileの共有ディレクトリの設定にあたる部分を変更する必要があります。

先ほどの公式ドキュメントに記載されていた通り、`type: "nfs"` を追加するだけで使用できます。

例えば次のように設定します。

```rb
config.vm.synced_folder ".", "/var/www/src", type: "nfs"
```

尚、private_networkが必要です。IPは例ですが、静的IPアドレスだとトラブルがすくないです(.1はホスト側で予約されていますので.2以上にする必要があります)。

```rb
config.vm.network :private_network, ip: "192.168.2.2"
```

(とくにMac)ファイアウォールに引っかかりやすいので、うまく動作しない場合はファイアウォールの設定をご確認ください。

## CSS や JavaScript が壊れてしまう場合

環境の組み合わせによっては、sendfileの影響でCSSやJavaScriptが壊れてしまう場合があります。その場合の対処方法はこちらをご確認ください。

https://bicstone.me/enablesendfile-js-broken/

## シンボリックリンクが動作しない場合

Laravelでは、シンボリックリンクを貼らないといけない機能(ファイルストレージ)があります。

https://readouble.com/laravel/6.x/ja/filesystem.html

ホストがWindowsの環境では、なぜかシンボリックリンクが壊れてしまい利用できませんでした。

```bash
$ ls -l storage
lrwxrwxrwx 1 root root 0 Dec 24 02:12 storage -> ../../storage/app/public
```

```bash
$ cd storage
cd: no such file or directory: storage
```

vagrant-winnfsdプラグインの影響なのか、Windowsの影響なのかわかってはいません。

私は、Publicディレクトリのみ、標準の共有ファイルに設定しました。次のようなイメージです。

```rb
config.vm.synced\_folder ".", "/var/www/src", type: "nfs", rsync\_\_exclude: "./public"
config.vm.synced\_folder "./public", "/var/www/src/public"
```

これで、高速化しつつ、ファイルストレージも使用できる環境になりました。それでもLaravelは遅いですけどね…。

![Larabelのデバッグツールスクリーンショット　Bootingが304ms、Appが195ms](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684999/f8b436be-bb5d-cbce-abf6-d180c29942d0.png)
Djangoで削除時に外部キー制約によって例外が発生する問題の対処法


Djangoで汎用View `django.views.generic.DeleteView` を用いた削除時に外部キー制約によってProtectedErrorの例外が発生するのをキャッチする方法を紹介します。

:::note warn

※ これは2020/02/05に[個人ブログ](https://bicstone.me)で公開した記事を移植し、[CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/deed.ja)で提供しています。情報は古い可能性があります。

:::

## PROTECT されている場合に削除しようとする場合の挙動

Djangoでは、モデルに外部キーを設定できます。モデルの第二引数では、参照先が削除等された場合の挙動が設定できます。

```py
class Comment(models.Model):
 user = models.ForeignKey(User, models.PROTECT)
```

ここで、参照先を削除できなくする `models.PROTECT` という設定ができます。この設定をした場合、参照先は削除できなくなります。

そして、公式ドキュメントにはこのような記述があります。

> Prevent deletion of the referenced object by raising ProtectedError, a subclass of django.db.IntegrityError.

https://docs.djangoproject.com/ja/3.0/ref/models/fields/#arguments

削除を試みると、 ProtectedError例外が発生するという仕様です。例外ということは、誤って削除が試みられると500エラーとなってしまいます。

## 汎用 View でシンプルに実装したい

一方で、せっかくDjangoで実装するのですから、汎用Viewでリレーション確認などの記述無しでシンプルに削除したいですよね。そこで次のように構築したとします。

```py
class UserDeleteView(DeleteView):
  model = User
  success_url = reverse_lazy('user-list')
```

ここで先程示したように他のモデルからPROTECTされていた場合、UserDeleteViewはProtectedError例外エラー(500エラー)を返してしまいます。

## 例外をキャッチする

Viewでは例外をキャッチするのみの実装とします。

https://docs.djangoproject.com/ja/3.0/misc/design-philosophies/

ほとんど汎用View使う理由がないような感じはしますが、post関数を上書きします。

```py
class UserDeleteView(DeleteView):
  model = User
  success_url = reverse_lazy('user-list')

  def post(self, request, *args, **kwargs):
    try:
      obj = self.get_object()
      obj.delete()
    except models.ProtectedError as e:
      messages.error(request, f'「{obj}」は紐付けられているため削除できません。')
      return redirect('user-list')
```

これで、ProtectedErrorが発生したら削除されず、フラッシュメッセージが表示されます。
【ChatGPT有＋DALL-E3】で思い付く限りの画風を試してみた。


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

　今回は、思い付く限りの画風を試してみました。画像は多いので付けません。

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

　二度寝して
　　しまいましたw

　さて、
　　今回は、
　　　思い付く限りの画風を
　　　　試してみました。

　数が多いので
　　どんなことを
　　　やったのか、だけを
　　　　書き出しました。
　　　　　ChatGPTさんがw
***
***user***
このセッションでの私の発言を集めてください。余計な加工はしないように。

***ChatGPT***
以下は、このセッションでのあなたの発言です。

1. 女性 猫 お互いに寝転がる 女性が猫につんつんする 描画
2. 英語プロンプト出力。和訳。
3. 男性と女性 背中合わせ 服装、男性が黒、女性が赤 描画
4. リトライ。ふたりがこちらを見る
5. リトライ。荒い油絵で
6. リトライ。リアルアニメで
7. リトライ。アニメで
8. リトライ。マンガに
9. リトライ。アメコミ風に
10. リトライ。写真で
11. リトライ。ゴッホ風に
12. リトライ。レオナルド・ダ・ヴィンチ風に
13. リトライ。フェルメール風に
14. リトライ。ゴヤ風に
15. リトライ。マネ風に
16. リトライ。ルノワール風に
17. リトライ。ダリ風に
18. リトライ。白黒写真で
19. リトライ。デフォルメ
20. リトライ。フィギュアで
21. リトライ。スーパードルフィーで
22. リトライ。編みぐるみで
23. リトライ。ねんどろいどで
***
　１番２番は、
　　関係ありません。
　　　ちょっと記事を書くための
　　　　アイディアを
　　　　　試しただけなので。
　　　　　　“ならば、消せよ”
　　　　　　　というのは
　　　　　　　　途中で気付きました。
　　　　　　　　　遅かったw

　男女が背中合わせで、
　　こちらを見ている画像をベースに、
　　　あれこれ画風を
　　　　指定したわけです。

　気になる画風があるならば、
　　やってみてください。

　もちろん、
　　画風は、これだけではありません。

　ほかにも
　　たくさんあります。

　今回のは、
　　思い付いたものだけですので
　　　みなさんも試してみてください。

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

　今回は、ここまで。
Win11のPCでdockerを利用して、aws のlambdaのレイヤーを作成した

四苦八苦したので備忘録代わりに。
そもそもなぜdockerを使おうとしたのか？
→lambdaのレイヤーに、moduleをインポートしたかったけど、
windows環境でpip installしたものを圧縮して、lambdaにアップロードしてもうまくいかなかったため。

環境がwindowsで作成したものだとよくないとのことがあり、
aws のcloud9を使って

win11でdocker
→起動できない

HyperVプラットフォーム
の機能をONに
→できない

BIOSのセットアップ画面から以下二つを有効化
・CPU
・virtualizaion

再起動して、タスクマネージャ起動→パフォーマンス→右下に「仮想化：有効」となっていることを確認
→あらためてHyperVプラットフォーム
の機能をONに


```docker-file
# syntax=docker/dockerfile:1
# Install necessary dependencies
FROM amazonlinux:2 as builder
RUN yum update -y && yum install -y tar gzip make gcc openssl-devel bzip2-devel libffi-devel zip

# Install Python
ARG PYTHON_VERSION=3.9.13
RUN curl https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz | tar xz \
    && cd Python-${PYTHON_VERSION} && ./configure && make && make install

# Build runtime image
FROM amazonlinux:2
COPY --from=builder /usr/local /usr/local

# Install line-bot-sdk
RUN /usr/local/bin/python3.9 -m venv venv && \
    source venv/bin/activate && \
    pip3 install line-bot-sdk && \
    deactivate

# Install zip command
RUN yum install -y zip

# Create a ZIP file with the installed libraries
RUN mkdir -p /python/lib/python3.9/site-packages && \
    cp -r /venv/lib/python3.9/site-packages/* /python/lib/python3.9/site-packages/ && \
    cd /python && zip -r /aws-layers.zip .
```

注意１
https://www.python.org/ftp/python/
のFTPにあるバージョンがあるものしかDLできない

注意２
aws-layers.zip
└── python
    └── lib
        └── python3.9
            └── site-packages
                └── linebot_sdk

この構造にする必要があるらしく、最後にフォルダを作っている

・docker コンテナから該当ファイルを取り出す
Dockerfileのあるフォルダにいき、
docker runで起動
別のコマンドプロンプトを開き、
docker ps
でコンテナが作成されていることを確認。

docker cp コンテナID:該当フォルダ名 ローカルに保存する先の絶対パス

追記・・うまくいきませんで。
cloud9でつくってうまくいきました。
参考URL
https://qiita.com/ndj/items/bbc96b8aa910b49cce1e

うまくいかなった理由は
・ファイル名がPythonじゃなかった
・line-bot-sdkでインストールしたファイルを、ぜんぶ圧縮できていなかった
（line-bot-sdkという名前のファイルだけを圧縮してアップロードしていた）
を考えてますが、検証できてないです。
停止したコンテナを起動しシェルコマンドで操作する方法について

停止したコンテナを起動しシェルコマンドで操作する方法をまとめました。

- 起動対象のコンテナ
    - ubuntu-dev

![スクリーンショット 2024-03-02 14.43.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449065/1c9fc98c-fc90-91c8-e040-de108eb58d9a.png)

Actionから起動するか`docker start`コマンドを実行します。

```bash
% docker start ubuntu-dev
ubuntu-dev
% docker container ls
CONTAINER ID   IMAGE           COMMAND       CREATED          STATUS         PORTS     NAMES
2dc9c9e78660   ubuntu:latest   "/bin/bash"   20 minutes ago   Up 8 seconds             ubuntu-dev
```

インタラクティブモードで対話的にコンテナを操作します。

```bash
% docker exec -it ubuntu-dev /bin/bash
root@2dc9c9e78660:/# 
```

以上で停止したコンテナを起動しコマンド操作できるようになりました。

## まとめ
`docker exec`コマンドを実行する前には必ずコンテナを起動しよう！
「現代数理統計学の基礎」演習問題解法メモ　第6章問11～13

デルタ法がなかなかわからないです。
問13はN(0,ϴ)です。勘違いしてϴの2乗で進めがちです。基本的な積分も青字で記載しました。
![第6章問11 P1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/5ca944ab-b087-fe39-ca4b-c600df034e71.jpeg)
![第6章問11 P2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/9adfb7ea-2eb4-7302-91d4-48599a6c4f00.jpeg)
![第6章問12 P1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/5d68fc65-79fd-fe26-b699-cfd98ba03f04.jpeg)
![第6章問12 P2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/c87b59da-cb8f-1310-f9e7-ca5aec80eb98.jpeg)
![第6章問12 P3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/31706fa1-5070-94cc-44c3-2c11299c9a84.jpeg)
![第6章問13 P1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/d8058386-69f7-ce5d-0815-c3451eddac5f.jpeg)
![第6章問13 P2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/4ef727e3-f734-76cf-d5d9-2e4f661ca2bb.jpeg)
![第6章問13 P3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/146453f1-89b7-1c56-eb3e-8cd1b5956ada.jpeg)
![第6章問13 P4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/5ab93508-1fd5-edc9-04a5-786d71fb72a2.jpeg)
dockerイメージからインタラクティブモードでコンテナを実行する

コンテナを作成しコンテナ内で対話的にシェルコマンドを実行する方法をまとめました。

```bash
docker run -it --name container_name ubuntu:latest /bin/bash
```

コマンド詳細
- runコマンド
    - コンテナを起動する
- itオプション
    - インタラクティブモードでコンテナを実行する
    - i(=interactive コンテナの標準入力を開いた状態に保ち、ユーザーの入力をコンテナに送る)
    - t（=tty　仮想端末（TTY）を割り当てることで、ユーザーに対話的なシェルセッションを提供する）
- nameオプション
    - コンテナに名前を付ける
- ubuntu:latest
    - dockerイメージ:タグ
- /bin/bash
    - 使用するシェル


実行結果

```bash
% docker run -it --name ubuntu-dev ubuntu:latest /bin/bash
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
01007420e9b0: Pull complete 
Digest: sha256:f9d633ff6640178c2d0525017174a688e2c1aef28f0a0130b26bd5554491f0da
Status: Downloaded newer image for ubuntu:latest
root@2dc9c9e78660:/#
```

ubuntu-devコンテナを作成できました。

![スクリーンショット 2024-03-02 14.27.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449065/6d035f00-e4f5-4fc1-9d4c-5f6e21b4c25d.png)

シェルコマンドで操作できていますね。

```bash
root@2dc9c9e78660:/# echo $SHELL
/bin/bash
root@2dc9c9e78660:/# ls
bin   dev  home  lib32  libx32  mnt  proc  run   srv  tmp  var
boot  etc  lib   lib64  media   opt  root  sbin  sys  usr
```

## まとめ
コンテナをシェルで操作するには-itオプションを使う
さくらのレンタルサーバーでFastAPI

## はじめに

さくらのレンタルサーバーでFlaskを動かす記事を見たので、同様の方法でFastAPIが動かせるかを試してみた。

とりあえず動く様だが…
- 各種環境が古いので運用には問題があるかも
- また、Hello worldでの動作確認なので実際にはどうなるか不明

## さくらの制限

これを書いている現在の自分のレンタルサーバー環境だと

- FreeBSD 11.2-RELEASE-p15 
- OpenSSL 1.0.2o-freebsd  27 Mar 2018

となっていた。

これにより、

#### Pythonを最新のものにできない

さくらのレンタルサーバーのFreeBSDのOpenSSLが古いのでPython 3.9までになる。Python 3.10以降はOpenSSL1.1.1以降が必須。

#### Pydanticを最新のものにできない
FastAPIが利用しているPydanticはV2からRustで実装されているとのことだが、さくらのレンタルサーバにはRustをインストールすることができずPydantic V1を使い続ける必要がある。本当にさくら環境でRustが動かせないかは不明だがとりあえず諦めた。

## 参考になる文書を読む

まず、次の記事を参考にFlaskの場合を試してみる

https://qiita.com/ninoko1995/items/8b01fd02bada3a2fa794

https://qiita.com/peace098beat/items/de9fdadfc4128e99bca6

https://zenn.dev/cti1650/articles/5e6c7bd15d7fbe

自分の場合、サーバー上のパスは `~/www/api/v1/*`、WebAPIのパスとして`/api/v1/*`に読み換えてFlaskの動作確認をしてみた。

これは`~/www/*`,`/*`にフロントエンドを置くこと、FastAPIをv2パスに置くことを想定。

## pyenv+virtualenv環境

上記の参考文書を見てpyenv+virtualenvの環境を用意する。pyenv+virtualenvの使い方に関しては省略。

### Python
最初に書いたようにOpenSSLのバージョンが古いのでPython 3.10以上はインストールできないので3.9.xまでで指定する。

### FastAPI

Pydantic V1が使われるようにFastAPIをインストールする。これを書いている現在FastAPI 0.110.0との組み合わせでインストールできたがPydantic V1がいつまでサポートされるかは不明。

```sh
pip install fastapi 'pydantic<2'
```

FastAPIはASGIなのでWSGIにコンバートするためにa2wsgiをインストール。

```sh
pip install a2wsgi
```

### 環境まとめ

これを書いている時点でのバージョンは次の様になった。さくらやFreeBSDのアップデートで状況が変わってくると良いですが…

- FreeBSD 11.2-RELEASE-p15 
- OpenSSL 1.0.2o-freebsd  27 Mar 2018
- Python		3.9.18
- fastapi           0.110.0
- pydantic          1.10.14

## 実際のアプリケーション

### CGI関連ファイル

`.htaccess`と`index.cgi`でFastAPIアプリを動作できるように設定。パーミッションやRewriteRuleのパスやshbangのパスなどは参考文書を見て適宜設定・読み換え。

```text:.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /api/v2/index.cgi/$1 [QSA,L]
<Files ~ "\.py$">
  deny from all
</Files>
```

```python:index.cgi
#!/home/username/.pyenv/versions/3.9.18-fastapi/bin/python

import a2wsgi
from wsgiref.handlers import CGIHandler

from main import app

wsgi_app = a2wsgi.ASGIMiddleware(app)
CGIHandler().run(wsgi_app)
```

### FastAPIアプリケーション

[公式ページのサンプル](https://fastapi.tiangolo.com/)の`main.py`をそのまま利用し、

```python:main.py
from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
    return {"Hello": "World"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
    return {"item_id": item_id, "q": q}
```

## 動作

上記で用意した2個のAPIも動作し、OpenAPI/Swaggerのページ(`/docs`)やReDoc(`/redoc`)も動作する様です。

![スクリーンショット 2024-03-02 12.12.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132537/31b685dc-bf5a-66a7-ddec-7e902f4a2496.png)

## まとめ

- 各種環境が古いので運用には問題があるかも
- Hello worldでの動作確認なので実際にはどうなるか不明
- OpenSSLやRustをセルフビルドし最新環境にできるかに関しては未検証
- さくらやFreeBSDのアップデート次第では状況が変わってくる
Laraveファイルライブラリをアップデートしました！！

## はじめに

こんにちは，ご覧いただきありがとうございます。
前回，Laravel用のファイルライブラリを作成しました。

https://qiita.com/ikepu-tp/items/69c445a4de47f52ce6d7

前回提示していた目標は以下のとおりでした。

1. 機能感はWordPressのメディアライブラリに近い
2. 特に設定をしなくても使える
   1. アップロードしたファイルの一覧等をデフォルトで表示できる
   2. ファイルのアップロードフォームをデフォルトで使用できる
3. ファイルのアップロードや情報の取得，編集をAPIを通じて行うことができる
4. ファイルのアップロードや情報の取得，編集をインスタンスで行うことができる

これらのうち，1，2の目標を達成しています。
そこで今回は残りの2つの目標を達成するためにアップデートを行いました。

## アップデート内容

- API対応
- ファイルのアップロード処理のインスタンス化
- ダウンロードリンクの追加

の3点です。

### API対応

API対応について，以下のリソースでAPIを利用することができます。

```json:API Resource
{
  "fileId": "string",
  "name": "string",
  "url": "string",
  "mime_type": "string",
  "created_at": "string",
  "updated_at": "string"
}
```

### ファイルのアップロード処理のインスタンス化

ファイルのアップロード処理のインスタンス化については，以下のように使用できます。

```php:UploadFileController
class FileController extends Controller
{
    public function store(Request $request)
    {
        $guard = config("file-library.guard");
        $files = \ikepu_tp\FileLibrary\app\Services\FileLibraryService::upload(
            $guard, 
            $request->file("files", []), 
            $request->input("names", [])
        );

        return back()->with("status", "File uploaded.");
    }
}
```

### ダウンロードリンクの追加

ダウンロードリンクは`http://your-project.com/file/lib/{fileId}/download`となっています。

## 最後に

これで当初の目標を達成することができました。
加えて，リスト表示やまとめて処理の機能を付与することもいいかもしれないと考えております。
ぜひ皆様のご意見をお聞かせいただければと思います。
エンジニアになって5年経ったのでこれまでしてきた勉強を振り返ってみる（あと今後の展望）

# はじめに
新卒でエンジニアになって5年経ったので、これまで私がやってきた勉強と取った資格を振り返ります。
また、今後行うべき・行いたい勉強を整理します（私はすぐに気が変わって違うことやり始めるので……）

# 前提
新卒でSIer企業に入社（Java/Web系）→3年後、インフラエンジニアに転職

# これまで取った資格
| 取得時期 | 資格名 | 備考 |個別記事|
|:-:|:-:|:-:|:-:|
|2018/11/14   |ITパスポート   |入社前に事前勉強として取った記憶   |
|~~2021/12/08~~   |~~色彩検定2級~~   |完全に趣味   |
|2021/12/26   |AWS CCP   |前職がAWSを押していた時期があったので取った   |
|2021/12/27   |基本情報技術者試験   |無資格で転職するのもなと思って取った   |
|2022/12/22   |応用情報技術者試験   ||[応用情報技術者合格記](https://qiita.com/aiz4ryhe/items/bccd9bdc451cc28941cd)   |
|2023/01/28   |OSSDB-Silver   |   |[OSSDB-Silver合格体験記](https://qiita.com/aiz4ryhe/items/63327dbb17aeb607c0d4)|
|2023/03/26   |LinuC Level1   |   |[LinuC Level1合格体験記](https://qiita.com/aiz4ryhe/items/6db8d9d28a2674cc0058)|
|2023/12/11   |LinuC Level2   |   |[LinuC Level2合格体験記](https://qiita.com/aiz4ryhe/items/03daf058ff4f528a2d6b)|
|2024/02/12   |LinuC Level3 (304)   |   |[LinuC 304合格体験記](https://qiita.com/aiz4ryhe/items/d54507e9396340ccc6a9)|

# これから勉強したい分野、資格
- クラウド分野・仮想化技術
    - LiniC304の範囲が高可用性・仮想化であり、そこの勉強を進めるうちに仮想化へ興味を持ちました。業務でほんの少し仮想環境に触れていたこともあり、このあたりは勉強したいと思っています。
    - 市場価値的な面でも、この分野の知識の価値が高いのはまだしばらく続くと思われるので、そういう意味でも勉強しておきたいです。
- linuC 303
    - 上司オーダー
        - と言いつつ、資格めっちゃ取ってる先輩にもおすすめされたのでちょっと興味ある。セキュリティ系は腐らない知識だし。
- 安全情報確保支援士
    - 完全に個人的な事情ですが、職場の同期が取得したので。
    - 資格頑張ってます！というのが、私流の同期との差別化ポイントの1つだったので結構衝撃が大きかった。
- CCNA
    - インフラエンジニア名乗るならネットワーク系技術の基礎くらい知っておきたいと思い続け、参考書が本棚から睨みつけています。

# スケジュール
※ 予定は未定
※ 厳しめに引かないとやらないので
| 取得予定 | 資格名 |
|:-:|:-:|
| AWS SAA  | 2024/04  |
| LinuC303  | 2024/06  |
| 安全情報確保支援士  | 2024/10  |
|  CCNA | 2024/12  |

# まとめ
転職当時のチームリーダーに焚き付けられて始めた資格勉強ですが、気が付けば2年継続し、5つの試験に受かることが出来ました。
資格勉強で学んだ知識のうち、仕事で使うのはよくて2割程度です。しかし、自己研鑽する習慣であったり、ふとした時に理解できることの幅が広がったので、続けてきてよかったと思います。
会社から取得を求められていた資格は取り切ったので、ここからは自分の興味と需要を勘案して引き続き知っていることを増やしていきたいと思います。
AsyncStreamを触ってみた。

# AsyncStreamとは？
非同期のSequence, 要素が非同期的に流れてくる小川。　[公式資料](https://developer.apple.com/documentation/swift/asyncstream)

従来はクロージャで実装していたものを`Swift Concurrency`の記法、`async await`で書けるように変換できるのが嬉しい。（のだと思う…）


```swift
// 以下のように定義すると
var asyncStream: AsyncStream<String> {
    AsyncStream { continuation in
        Task {
            try? await Task.sleep(until: .now + .seconds(1))
            continuation.yield("🍑") // 川に桃を流す
            
            try? await Task.sleep(until: .now + .seconds(1))
            continuation.yield("🪑") // 川に椅子を流す
            
            try? await Task.sleep(until: .now + .seconds(1))
            continuation.yield("👢") // 川に長靴を流す
        }
    }
}

// 以下のように使用できる。
func startStreaming() {
    Task {
        for await sth in asyncStream {
            if sth == "🍑" {
                print("桃が流れてきました。")
            } else {
                print("ゴミが流れてきました。")
            }
        }
    }
}
```

# 実装例A

カメラのプレビュー用画像データを逐次流す

https://developer.apple.com/tutorials/sample-apps/capturingphotos-camerapreview

# 実装例B

タップされたらすぐに数字が増加する動機カウンターと、一カウントごとに1秒表示して数字が増加する非同期カウンターを実装する。

![Simulator Screen Recording - iPhone 15 - 2024-03-02 at 13.33.23.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/05df5a43-7db4-18df-86ad-4149236f51e8.gif)



```ContentView.swift
struct ContentView: View {
    @State private var model = Model()

    var body: some View {
        VStack {
            Text("Async: \(model.asyncCounter)")
            Text("Sync: \(model.syncCounter)")
            Button("Count Up") { model.countUp() }
        }
        .task { await model.startStreaming() }
    }
}
```
```Model.swift
@Observable
final class Model {
    private(set) var syncCounter = 0
    private(set) var asyncCounter = 0
    private let delay: UInt64 = 1_000_000_000

    func countUp() {
        syncCounter += 1
        throwIntoStream?(syncCounter)
    }

    func startStreaming() async {
        for await value in counterValueStream {
            try? await Task.sleep(nanoseconds: delay)
            asyncCounter = value
        }
    }

    private var throwIntoStream:((Int)->Void)?
    private var counterValueStream: AsyncStream<Int> {
        AsyncStream { continuation in
            self.throwIntoStream = { value in
                continuation.yield(value)
            }
        }
    }
}
```

# その他

[WWDC](https://developer.apple.com/videos/play/wwdc2021/10058/)の動画もあるらしい。（まだ見てない…。動画見るの面倒くさい…。）
Pythonで「関数で可変個数の引数を受け取る」の動作を確認してみた

# 概要

Pythonで「関数で可変個数の引数を受け取る」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/python/userfunc/index7.html

# 実装

以下のファイルを作成しました。
```sample.py
def myfunc(num1, *tupple1):
    print(tupple1)

myfunc(10)
myfunc(10, "Hello")
myfunc(10, "Hello", 25)
myfunc(10, "Hello", 25, "Orange")
myfunc(10, "Hello", 25, "Orange", True)

def myfunc(category, *ranktuple):
    count = 1
    print(category)
    for val in ranktuple:
        print("No." + str(count) + ":" + val)
        count += 1
    print("\n", end='')

myfunc("Fruits", "Orange", "Melon", "Banana", "Apple")
myfunc("Mobile", "Android", "iPhone")
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
()
('Hello',)
('Hello', 25)
('Hello', 25, 'Orange')
('Hello', 25, 'Orange', True)
Fruits
No.1:Orange
No.2:Melon
No.3:Banana
No.4:Apple

Mobile
No.1:Android
No.2:iPhone
```

# まとめ

何かの役に立てばと。
lsofコマンドのTCP/UDPの状態一覧

lsofのコマンドの結果として出てくるTCP/UDPの状態名の解説です。

## TCP/UDPの状態

### **TCP**

| 状態名 | 意味 | 詳細解説 |
|---|---|---|
| CLOSED | 接続が閉じており、アクティブではありません。 | 何かしらの通信が終了し、リソースが解放されています。 |
| IDLE | 特定のアクティビティを待っています。 | 接続の確立やデータの送受信など、次のアクションを待っています。 |
| BOUND | ソケットが特定のポートに結びつけられています。 | 特定のサービスを提供するために、ポート番号を占有しています。 |
| LISTEN | サーバーが新しい接続を待っている状態。 | クライアントからの接続要求を待ち受けています。 |
| ESTABLISHED | 接続が成功し、データの送受信が可能な状態。 | 双方向でデータ通信を行うことができます。 |
| SYN_SENT | クライアントが接続開始のためSYNを送信した状態。 | サーバーとの接続を確立しようとしています。 |
| SYN_RCDV | サーバーがクライアントからSYNを受信し、SYN+ACKを返信した状態。 | クライアントとの接続確立手続きの途中です。 |
| CLOSE_WAIT | リモート側が接続を終了した後、ローカル側が接続を閉じるのを待っている状態。 | リモート側から接続終了の指示を受け、ローカル側も接続を閉じる準備をしています。 |
| FIN_WAIT1 | ローカル側が接続終了を開始し、FINを送信した後の状態。 | リモート側からの応答を待っています。 |
| CLOSING | ローカル側とリモート側の両方が同時に接続を終了しようとしている状態。 | 接続が正常に終了するかどうかは、状況によって異なります。 |
| LAST_ACK | ローカル側がリモート側からの最終的なACKを待っている状態。 | 接続が完全に終了する前に、最後の確認が必要です。 |
| FIN_WAIT_2 | ローカル側がリモート側からのFINを待っている状態。 | リモート側からの接続終了の指示を待っています。 |
| TIME_WAIT | ローカル側が、遅れてくる可能性のある最終的なパケットがすべてネットワークを通過するのを待っている状態。 | ネットワーク上の遅延により、パケットがまだ届いていない可能性があるため、安全のために一定時間待機します。 |

### **UDP**

| 状態名 | 意味 | 詳細解説 |
|---|---|---|
| Unbound | ソケットがどのポートにも結びつけられていない状態。 | まだ通信相手やポート番号が決まっていない状態です。 |
| Idle | アクティビティがない待機状態。 | 何かしらの通信が行われるのを待っています。 |
[Google Sheets API] セルにHTML、CSVデータを貼り付ける

Google Sheets API v4（Java）を使用して、
スプレットシートのセルにHTMLデータ、CSVデータを貼り付ける方法
についてご紹介します。

:::note info
APIを利用する環境の準備から始める場合や、コードを実行する際は、
[⧉[Google Sheets API] Google Sheets API v4をJavaで操作する](https://qiita.com/doran/items/3d43f776188b2281044c)
を参照ください。
```
例：requests.add(moveDimension(sheetId)); //実行したいリクエストのMethodを指定
```
:::

:::note info
その他のGoogle Sheets APIは、下記の記事を参照ください。
[⧉[Google Sheets API] JavaでスプレットシートのメニューとAPIを関連づけてみた](https://qiita.com/doran/items/2f6f8932b994fbd1a170)
:::

|No|目次|
|---|---|
|1|[HTMLを貼り付ける](#1-htmlを貼り付ける)|
|2|[CSVを貼り付ける](#2-csvを貼り付ける)|

## 1. HTMLを貼り付ける
セルにHTMLデータを貼り付けることができます。

**サンプル コード**
HTMLのテーブルを貼り付けてみます。
```
public Request pasteData(Integer sheetId) {
    Request request = new Request();

    GridCoordinate range = new GridCoordinate();
    range.setSheetId(sheetId);    //シートID
    range.setRowIndex(0);         //開始行(0スタート)
    range.setColumnIndex(0);      //開始列(0スタート))
    
    PasteDataRequest r = new PasteDataRequest();
    r.setCoordinate(range);      //データの挿入を開始する座標。
    r.setData(                   //HTMLデータ
      "<table>"
      + "<thead>"
        + "<tr>"
         + "<th colspan=\"2\" style=\"background-color:red;\">タイトル1</th>"
         + "<th style=\"background-color:blue;\">タイトル2</th>"
        + "</tr>"
      + "</thead>"
      + "<tbody>"
        + "<tr>"
         + "<td>データ1</td>"
         + "<td>データ2</td>"
         + "<td>データ3</td>"
        + "</tr>"
     + "</tbody>"
    + "</table>");
    r.setHtml(true);              //データが HTMLの場合は true

    request.setPasteData(r);
    return request;
}
```
**実行結果**
HTMLデータが貼り付けられました。styleや行の結合も反映されています。
<img width="320" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/60f7f931-2c58-39f4-2ffe-53d86c1ce052.png">


## 2. CSVを貼り付ける
CSVデータをセルに貼り付けます。
区切り文字(CSVの場合は「,」)を指定するとセルを分けて貼り付けてくれます。

**サンプル コード**
```
public static Request pasteData(Integer sheetId) {
    Request request = new Request();

    GridCoordinate range = new GridCoordinate();
    range.setSheetId(sheetId);      //シートID
    range.setRowIndex(0);           //開始行(0スタート)
    range.setColumnIndex(0);        //開始列(0スタート))
    
    PasteDataRequest r = new PasteDataRequest();
    r.setCoordinate(range);         //データの挿入を開始する座標。
    r.setData("A,B,C,D\n1,2,3,4");  //挿入するデータ。
    r.setDelimiter(",");            //データ内の区切り文字。
    
    request.setPasteData(r);
    return request;
}
```
**実行結果**
カンマ区切りのデータが貼り付けられました。
ちゃんと、カンマの位置で区切られてセルに貼り付けられています。
<img width="320" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/4f0170fe-3f48-1a9e-25bd-f340cee69cef.png">

<br>
おしまい。。
Rubyの基本（ハッシュ）

# ハッシュの定義
キーと値（バリュー）の組み合わせが重要なデータはハッシュで管理する。
```ruby:sample_01.rb
# ハッシュの定義
scores = {english: 80, math: 70}
p scores
# {:english=>80, :math=>70}

# 特定のキーの値の更新
scores[:english] = 90
p scores[:english]
# 90

# データの追加
scores[:physics] = 50
scores.delete(:math)
p scores
# {:english=>90, :physics=>50}
```

# ハッシュについて調べる
ハッシュについて調べる方法には以下のようなものがある。
```ruby:sample_02.rb
scores = {english: 80, math: 70}

# 文字数
p scores.length
# 2
p scores.size
# 2

# キーや値の存在確認
p scores.has_key?(:physics)
# false
p scores.has_value?(70)
# true

# キーや値の一覧を出力
p scores.keys
# [:english, :math]
p scores.values
# [80, 70]
```

# ハッシュを`each`で処理する
`each`メソッドを使ってハッシュのデータを取り出すことができる。
```ruby:sample_03.rb
scores = {english: 80, math: 70}

scores.each do |subject, score|
  puts "Subject: #{subject}, Score #{score}"
end
# Subject: english, Score 80
# Subject: math, Score 70
```
【初心者向け】公開鍵認証について学んだことをまとめる【備忘録】

任意の環境にSSH接続すれば色々と捗ります。

## 学ぶメリット

- 本番環境にGithubからpull
- Githubからの自動デプロイ
- SCPやRSYNCコマンドなどでサーバーのデータを高速にDL/UP
- Dockerとの親和性
- セキュリティ意識の向上
- APIを安全に使用できる

## 基本的な概念
- まず2種類の鍵を作る
- 公開鍵を**接続する先**に持たせる
- ~~公開鍵（key.pub）はオープンにしてOK（とはいえ節度は守るべき）~~
- 秘密鍵を**ユーザー**に持たせる
- 秘密鍵は完全に非公開の状態にする

指摘あり修正。
公開鍵はプラットフォーム側に持たせるので、closedではない（秘密鍵はユーザーだけが持つのでclosed）。
ただ公開鍵をSNSで公開するようなものではないよねっていうニュアンスです。

~~具体的には、公開鍵は南京錠のこと。~~
~~秘密鍵は南京錠を開くための鍵のこと。~~

鍵としての側面だけなら、鍵穴と鍵のセットで開く南京錠の例えはわかりやすい。
しかし本来、公開鍵認証は秘密鍵を持つユーザーを特定するためのもの。
文字通り『鍵＋認証』の機能を持つため、南京錠は不適切でした（南京錠の鍵にユーザーを特定する機能はない）。

なので正確には、銀行印の方が的を射ている（[参考：公開鍵認証のイメージ](https://qiita.com/angel_p_57/items/19eda15576b3dceb7608#%E5%85%AC%E9%96%8B%E9%8D%B5%E8%AA%8D%E8%A8%BC%E3%81%AE%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8)）。

## 実行手順
主に2パターンあると思う。

### 自分で鍵を作成するケース

ユーザーの端末で
```ssh-keygen```
を実行。
.sshフォルダ内に、公開鍵・秘密鍵が作成されます。

作った公開鍵をサーバーやGithubなどログインしたいプラットフォームに登録する。
その後は秘密鍵を使ってSSH接続が可能になります。

### プラットフォーム側で鍵を生成するケース

プラットフォーム内の鍵を作成するページから作る。
秘密鍵がローカル（＝接続するユーザーが持つ）にDLされます。
DLした秘密鍵を使ってSSH接続します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530037/6b026308-4270-0c94-6a52-0c0359e1de5a.png)

※たぶん裏側でssh-keygenか同等の機能を動かしている

## 接続するためのコマンド例

よく使うコマンドまとめておく。

### ssh接続を行う

例えば-p は、Xserverの場合10022。
githubなんかは不要。

```
ssh -i ~/.ssh/privateKey loginUser@IPaddress -p portNum
```

### アップロード

```
rsync -avzP -e "ssh -i ~/.ssh/privateKey -p 10022" --exclude 'AAA' --exclude 'BBB' ~/filePath loginUser@IPaddress:~/uploadPath/
```
- -a：コピー元ファイルの状態を保持する
- -v：転送情報を表示する
- -z：圧縮して送信
- -P：転送中の情報を表示＋転送に失敗したファイルを削除
- -e：シェルコマンドを実行
- --exclude：UP/DL対象から外すファイルやフォルダを指定（個別に指定する必要がある）

### ダウンロード

アップロードのコマンドから、fileの前後を逆にしただけ。

```
rsync -avz -e "ssh -i ~/.ssh/xs980405.key -p 10022" --exclude 'AAA' --exclude 'BBB' loginUser@IPaddress:~/filePath/ ~/downloadPath
```

### Githubへの接続確認

まずはGitを実際に使用する環境下のターミナル上で下記を実行。
```
git init
git remote add origin git@github.com:user/repository
eval $(ssh-agent -s)
ssh-add ~/.ssh/privateKey
ssh-add -l　←確認用なのでやらなくても問題ない
```

次はGithubへの接続テスト。
エラーが出なければ、とりあえずサーバーからGithubへの接続はできるものと考えてOK。
git cloneやpullなどが使えるようになる。

```
ssh -T git@github.com
```

## 参考文献

ぜひ、より正確に学ぶことをオススメします。

https://qiita.com/angel_p_57/items/897bf94160be8d637585

https://qiita.com/angel_p_57/items/2e3f3f8661de32a0d432

https://qiita.com/angel_p_57/items/19eda15576b3dceb7608
Linux環境をWSLで構築

Linux環境をWSLで構築するまでにやったこと

# 参考ページ
https://learn.microsoft.com/ja-jp/windows/wsl/install

# 手順
1.PowerShellを管理者権限で開く

2.WSLをインストール
```
wsl --install
```

3.Linuxディストリビューションをインストール
　Ubuntuをインストールするため、下記コマンドを実行。
```
wsl --install -d Ubuntu-22.04
```

インストールが完了するとubuntuのusername、password設定を求められ、
設定完了すると、Powershell上でUbuntu環境が起動された。
node.js で VRT – PlayWright で Webページにアクセスしてスクリーンショットを撮影し、reg-cli で差分レポートを出力する例

# 事前準備

## npm インストール

`package.json` の例

```json
{
  "devDependencies": {
    "playwright": "^1.42.0",
    "@playwright/test": "^1.42.1",
    "http-server": "^14.1.1",
    "reg-cli": "^0.18.1"
  }
}
```

`npm install`

## Playwright セットアップ

`npm init playwright@latest`

質問にはてきとうに Yes と答えておく
<img width="789" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/830f0dcd-69ee-4df0-99e6-ca86f7e3fb58">


# localでWebサーバーを起動しておく

## HTML

見た目の違うページを2個用意しておく

例:

`example1.html`

```
<h1>Hello WoRLD!</h1>
```

`example2.html`

```
<h1>Hello WoRLD!</h1>
```

## Web サーバーを起動する

以下ページにアクセスできるようにしておく

- http://localhost:8080/example1.html
- http://localhost:8080/example2.html

```
npx http-server --port=8080
```

# Playwright でスクリーンショットを撮影する

## Playwright とは


Webブラウザを自動操作できるテストツールである

## 何をするか

- Playwright に localhost にアクセスさせて、そのスクリーンショットを撮影しておく
- ここでは簡単に差分を比較するために、2個の別々のページのスクリーンショットを撮影している
- VRT(ビジュアルリグレッション・テスト)として運用する場合、実際には「ページAを撮影する」ということをデプロイの前後などで複数回おこなって、差分を検知すると良い

## テストファイルの例

`tests/example.spec.ts` 

```js
import { test } from "@playwright/test";

test("Screen Shots", async ({ page }) => {
  await page.goto("http://localhost:8080/example1.html", { waitUntil: "networkidle" });

  await page.screenshot({ path: "expected_images/example.png" });

  await page.goto("http://localhost:8080/example2.html", { waitUntil: "networkidle" });

  await page.screenshot({ path: "actual_images/example.png" });
})
```

## テスト実行

`npx playwright test`

これでページ2個分のスクリーンショット画像が保存される

## 備考

- ここではlocalhostのWebページを利用したが、実際には `http://example.com` などグローバルなページに対しても実行できる

# reg-cli 

画像ファイルのあるディレクトリ2個を指定して、差分レポートを出力する

```
npx reg-cli ./expected_images ./actual_images ./diff --report ./report.html
```

## 差分検知

今回は差分があるパターンなので、差分検知されてコマンドはエラーで終わるが、これが正常動作

<img width="642" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/07eae29c-c51d-42b0-8890-c77866093061">

## レポートを開く

`report.html` を開く

差分レポートを開くと、差分が検知されているのが分かる

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/6eaefb0b-b618-4754-8cbb-82c1c6275598)

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/18cb3746-ceb8-447c-8f0a-4cb7901dc6f1)

## 備考

- CI に組み込む場合は reg-cli ではなく reg-suit を使うと良い


# チャットメンバー募集


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

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


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
Docker+IRuby（rubydata/datascience-notebook）にgemを追加して使う

Docker イメージ [rubydata/datascience-notebook](https://hub.docker.com/r/rubydata/datascience-notebook) にはデータサイエンス関連の gem があらかじめインストール済みになっていますが、それ以外の gem を使いたい場合の手順です。

単に Dockerfile に追記すればいいだけなんですが、「Docker + IRuby 使ってみたいけどまだ Docker についてよく知らない」みたいな人もいるかなと思ってメモしてみます。

---

使いたい gem が追加されていない状態だとこうなりますね（素の `rubydata/datascience-notebook` を使った場合）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/812a515b-6122-85ea-886f-0824cf75b8ae.png)

今回は例として [svg-graph](https://rubygems.org/gems/svg-graph) という gem で試しています。

---

やり方はいろいろありそうですが、今回は `rubydata/datascience-notebook` をベースにしたイメージを作る方法にしました。

まずは適当な作業ディレクトリに `Dockerfile` というファイルを置き、以下の内容で保存します。

```dockerfile
# Dockerfile

# ベースイメージの指定
FROM rubydata/datascience-notebook

# 使いたい gem をインストールする
RUN gem install svg-graph
```

今書いた Dockerfile の内容にしたがってイメージをビルド。

```sh
docker build -t my-datascience-notebook:test .
```

実行。

```sh
  # 最低限ならこう
docker run --rm -p 8888:8888 \
  my-datascience-notebook:test

  # 実際使う場合はこんな感じ
docker run --rm -p 8888:8888 \
  -v $(pwd):/home/jovyan/work \
  --name my_datascience_notebook \
  my-datascience-notebook:test

```

実行するとターミナルに以下のように表示されるので、URL（`http://127.0.0.1:〜`）をコピーしてブラウザで開く。

```
[C 2024-02-18 23:27:59.564 ServerApp] 
    
    To access the server, open this file in a browser:
        file:///home/jovyan/.local/share/jupyter/runtime/jpserver-6-open.html
    Or copy and paste one of these URLs:
        http://bbfe0f483910:8888/lab?token=09e596ae99c4f53d1349b7ba074d71f6782619f70ddbc75b
     or http://127.0.0.1:8888/lab?token=09e596ae99c4f53d1349b7ba074d71f6782619f70ddbc75b
```

---

ブラウザで開いたときの最初の画面。
Notebook＞Ruby〜 をクリックして新規ノートブックを開く。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/33aaa241-51aa-2e92-7e3a-4ce28d7182e7.png)

---

こんどは require できました。
（セルにコードを書いて Ctrl+Enter で実行）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/5be38ac5-19b8-b46f-e1fc-86272fe91555.png)

---

せっかくなのでもうちょっとやってみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/aff98626-d19f-5301-567e-11f9a3da0e18.png)

使えますね。



# この記事を読んだ人は（ひょっとしたら）こちらも読んでいます

<!-- Ruby + PyCall でデータサイエンス100本ノック（構造化データ加工編）をやってみた #Ruby - Qiita -->
https://qiita.com/sonota88/items/52d0e35dc5e6e112c02f

<!-- SVG::Graph（svg-graph gem）で散布図を描く #Ruby - Qiita -->
https://qiita.com/sonota88/items/86afece3b2595648a656

<!-- Galaaz を触ってみた（TruffleRuby + ggplot2 で散布図を描いてみた） #Ruby - Qiita -->
https://qiita.com/sonota88/items/b586e96f7805a5695a34
Javascript Registry (JSR) とは

### 概要

JSRとはjavascriptのパッケージのためのレジストリです。npmやNodeとも互換性がありますが、npmを進化させたようなレジストリです。


### レジストリとは
パッケージ等を管理するストレージのようなものです。例えば `npm install lodash` をすると、通常はnpmに設定されているデフォルトのレジストリである `https://registry. npmjs.org/ ` からパッケージをインストールしようとします。

ここで注意すべきはパッケージ管理ツールとレジストリは別の概念であることです。`npm`コマンドはあくまでもパッケージ管理ツールであり、`npm`コマンドを使っていても実際にパッケージをインストールしてくるストレージは自由に設定可能です。この記事で紹介しているJSRは**レジストリ**であり、したがってnpmコマンドを使ってJSRからパッケージを取得することが可能です。

例えば企業などでは独自のレジストリを管理しており、npmコマンドなどでもデフォルトのレジストリが会社の管理するものになっているケースも多いと思います。


### npmに対する優位性
- typescriptフレンドリー
    - パッケージのpublish時に、自動でAPIドキュメントの生成・型定義ファイルの生成・トランスパイル等を行ってくれます。
- あらゆるJS Runtimeとの相性
    - npmレジストリはあくまでもNode中心に開発されたレジストリですが、近年Bun・Deno等の新たなランタイムが登場してきております。例えばDenoではパッケージのインポートは基本的に直接パッケージのURLをソースコードで上で指定しますが、JSRを使う際は以下のように指定することでインポートが可能になります。
        ```typescript
        // 普通のインポート
        import { add } from "https://x.nest.land/ramda@0.27.0/source/index.js";

        // JSR
        import { printProgress } from "jsr:@luca/flag";
        ```
- ES Moduleのみサポート
    - これは優位性かどうかはわかりませんが、JSRはESMのみをサポートします。基本的に今の時代ブラウザやNodeなどほぼ全てがESMを解釈することができ、レジストリ上での統計的な解析等でもESMのみのほうがしやすいということらしいです。


### JSRをnpmと使う方法
基本的には `jsr` コマンドを用いることで、npmパッケージとしてインストールでき、普通のパッケージと同様にソースコード内でインポートできます。
```
npx jsr add @luca/flag
```


最初のレジストリの章でも述べた通り、パッケージ管理ツールとしてのnpmを用いてJSR上のパッケージをインストールすることは可能です。これは普通のレジストリを設定するようにプロジェクト内に以下のような `.npmrc` ファイルを設定することで可能です。
```
@jsr:registry=https://npm.jsr.io
```
これは `@jsr` スコープのパッケージは`https://npm.jsr.io`のレジストリを使うという設定です。したがって普通のnpmコマンドを用いてインストールを行いたい場合は以下のようなコマンドを使うことになります。
```
npm install @jsr/luca__flag@1
```
実際、`@jsr` は本当のスコープではなく単にJSRレジストリを使いたいことを示すためにあり、これにより実際のパッケージ名を少し変更しなければなりません。

と、色々面倒なので`npx jsr add`コマンドを使えば十分なのですが、どう動いているかを知りたい方は[ドキュメント](https://jsr.io/docs/npm-compatibility#advanced-setup)を参照ください。


### 参照
https://jsr.io/
https://syntax.fm/show/737/jsr-the-new-typescript-package-registry-npm-killer/transcript
GitHub上にコードを載せたい

何かしらコードを書いた際、GitHubにどうやって載せるか忘れてしまうので、備忘録的にまとめる。

## やりたいこと
手元のコードをGitHubに載せて見てもらいたい！

# 手順
① ``` git init ```
② ``` git add .  ```
③ ``` git commit -m "コミットメッセージ" ```
④ ``` git remote add origin git@github.com:{アカウント名}/{リポジトリ名}.git ```
⑤ ``` git push origin main ```
<br>




これだけです。masterブランチがデフォルトだった場合、後々めんどくさいのでmainに変更するコマンドもありますが、最近はmainがデフォルトになっている?ようです。  
<br>

本当に最小限のことしか書いていない、青二才学生の日記なので間違いがあるかもしれません。指摘事項などあれば教えてください…
MAMPのダウンロード時のエラー解除

# 初めに
MAMPをダウンロードし直そうと思っていたら、

```
MAMP (PRO) can not be installed yet! First, you have to • stop all servers, • deactivate the Dynamic DNS service, • turn off server starts at system startup, • and quit MAMP & MAMP PRO. If you keep seeing this message please restart your Mac.
```
と表示されたのでその解決策を書きます。

# 解決策
起動中のアプリケーションにMAMPがあったので、それを終了することでダウンロードすることができました。

# 終わりに
MAMPをダウンロードできない方へ参考にしていただきたいです。
Node.js - npx  なら package.json で管理している node モジュールのコマンドを直接実行できる

# 概要

npxをインストールしておけば、 package.json で管理している node モジュールを直接コマンド指定で実行できる

## インストール

```
npm install -g npx
```

## 利用例

たとえば次のような package.json がある場合

```json
{
  "dependencies": {
    "prettier": "^3.2.5"
  }
}
```

次のように自由にサブコマンド、フラグなどを指定して実行できる

```sh
npx prettier some_dir
```

```sh
npx prettier --cache  other_dir
```

# 問題の前提 – npm run 

package.json の script にコマンドを書いておけば、パッケージ管理しているバージョンでコマンド実行が出来るが、

- scripts に書かずに単発のコマンド実行がしたい
- 様々なバリエーションでコマンド実行したい

という時に不便だった


# チャットメンバー募集


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

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


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
ChatGPT、これはいいな！

# 久しぶりのプログラミング。

Googleで調べながらプログラミングをしていて、そうだChatGPTに聞いてみようと思いました。

そしたらすごく便利で驚きました。ググるとものすごい数の記事がヒットして、うっとうしい広告をだらけのページから使えそうなコードを探してコピーしてプログラムを組み立てていくという作業が、

ChatGPTだと必要な情報だけがパッとでるからすごく楽。その上動くコードがでてきて、これはいいかな？ ここは使えるかな？と試行錯誤しながら完成にもっていくという作業になりました。

めちゃくちゃ楽でした。確かにこれは後戻りできませんわー


やったこと。


## Pythonでローカルに保存したHTMLファイルのスクレイピングをしたい

![スクリーンショット 2024-03-02 11.46.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356263/68452d6a-f59f-41b0-05a8-c8310ded5410.png)

画面がシンプル！
広告がない！
すっごく快適・・・

##次に、お目当てのタグの中だけに絞る方法を聞く。

rslt_snipsタグで囲まれた範囲のリンクを抽出したい

![スクリーンショット 2024-03-02 11.48.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356263/b32269db-35bb-2438-6542-0f0eac3fc395.png)

わー！
コピーして保存して実行するだけ！

あれこれ注文していきます。

- 同じフォルダのHTMLファイル全てに実行したい
- この中のindex、テキスト、リンクを抽出したい
- タグ囲まれたすべてのリンクを取得したい
- このエラーはどうしたらいいですか
- textに含まれる改行を削除したい
- ”       ”をスペース一個にしたい
- もしインデックスがなかったら省きたい
- textの出力結果を"でくくりたい
- スプレッドシートの列を分割するには
- pythonでprint(index,text,link)の区切り文字を@にしたい

## できました！

本で探してなければググって、何度も何度も実行してはエラーコードを検索して対策して、かなりの時間がかかっていた作業が、２時間ちょっとでできました。すごいですね！
(２時間)
インターフェース

インターフェース全てのメソッドが抽象メソッドで一般的にフィールドを持たないクラスです。
※public static finalのフィールド（定数）のみ宣言が可能です。
フィールドを持たないインターフェースを用いると、通常のクラスでは利用できない多重継承を行う事が出来ます。

~~~:宣言方法
アクセス修飾子　interface インターフェース名{
}
~~~

インターフェースで宣言されたメソッドはpublicでabstructになります。

# 参考文献

https://docs.oracle.com/javase/tutorial/java/IandI/multipleinheritance.html
標本調査に必要なサンプル数・得られたサンプルの信頼性について

いいこと調べたけど、メモしないと一瞬で忘れそうなので書きます。

# 必要なサンプルサイズ

全数調査ができないときにどのくらいのサンプルを集めると信頼性のある判断が得られるかという問題について。

- `n` 必要なサンプル
- `N` 母集団数
- `z` 信頼度(zスコア)
- `p` 回答率(Yes/Noの割合とか)
- `e` 許容誤差

としたとき必要なサンプルサイズは、

```math
n=\frac{Nz^{2}p\left(1-p\right)}{e^{2}\left(N-1\right)+z^{2}p\left(1-p\right)}
```

となるそうです。

## パラメータ

`z`(zスコア)は信頼区間が標準偏差何個分になるかの値で、95%信頼区間なら`1.96`というあれです。

`p`はアンケートの回答が得られた割り合いではなく、タレント好感度(好きと答えた人の割合)のような感じです。

`e`は、サンプルから得られた`p`が前後何%までブレるのを認めるかという許容誤差です。

## サンプルサイズの例

例えばあるタレントの好感度を調査するとします。`p`は当然わからないので50%としておきます。

`p`が50%のとき、必要なサンプル`n`が最大化するので、50%からズレる分には精度が増すので問題ありません。

許容誤差は5%とします。

母集団は日本人でざっくり1億2000万人とします。これらを当てはめ上記を計算すると、

```math
n=384.1587734
```

となりました。本当に無作為に385人の人にタレントの好感度を尋ねると、日本全体における好感度を±5%の精度でわかり、その推測が外れる可能性は5%未満ということです。

# 得られたサンプルの信頼度

次に逆の問題を考えてみます。無作為で行われたアンケートの結果がどのくらい信頼できるものかを評価するものです。

ちょっと極端ですが、子供が「学校のみんな持ってるよ！」と言ってきたとき、証言の数で本当にみんなが持っていると言えるのかを検証するような感じです。

## 逆関数

先ほどの`n`についての関数を`z`について変形します。するとこのようになりました。

```math
z=\sqrt{\frac{ne^{2}\left(N-1\right)}{\left(N-n\right)p\left(1-p\right)}}
```

これを先ほどのタレント好感度の数値で検算してみます。すると、

```math
z=1.962144826
```

という結果が得られるので、どうやら正しいと言えそうです。

## zスコアから信頼区間

zスコアから信頼区間を求めるには、標準正規分布の累積度数分布関数が使えます。例えばGoogleスプレッドシートでは`NORMSDIST`が使えます。

```
=NORMSDIST(1.962144826) * 2 - 1
```

信頼区間は両側なので、`=NORMSDIST(z)-(1-NORMSDIST(z))`としなければなりません。これを変形すると上記になります。

その結果、

```math
信頼区間=0.9502543747
```

となり、ほぼ95%に逆算できました。

# 偏った回答は少ないサンプルでよい

偏った回答の場合、サンプルは少なくて済みます。

結果が半々の場合は慎重に吟味しないといけないけど、偏りがある場合はもっと早い段階で傾向がわかり、覆る可能性は低いという感じでしょうか。

例えば、タレント好感度の結果が99%とわかっている場合、

```math
n=15.2127342
```

となります。

日本人から無作為に16人を抽出し、全員がそのタレントを好きだと言ったら日本人の99%がそのタレントを好きである可能性が高いということです。

いわゆる出口調査的な話ですが、たった16人の意見で1億2000万人の大勢がわかるなんて面白いですね。

初歩的な統計学ですが、自分でハンズオンしてみて使える実感が湧きました！

間違いがあるかもなので、見つけたら優しく教えてください^^;
manコマンドと日本語化する方法

## manコマンド

manはコマンドのマニュアルを表示するコマンドです。
```bash
$ man コマンド名
```

マニュアルが表示された際の操作は以下の表の通りです。

| キー | 説明 |
|:----:|:----:|
| f | 1画面下に移動 |
| b | 1画面上に移動 |
| q | 終了する |
| d | 画面半分下に移動 |
| u | 画面半分上に移動 |
| g | 行頭まで移動 |
| G | 行末まで移動 |
| nG| n行目に移動 |

### 実行例

```bash
$ man ls
```
実行するとマニュアル画面が開きます。

```bash
LS(1)                          User Commands                          LS(1)

NAME
       ls - list directory contents

SYNOPSIS
       ls [OPTION]... [FILE]...

DESCRIPTION
       List information about the FILEs (the current directory by default).
       Sort entries alphabetically if none of -cftuvSUX nor --sort is spec‐
       ified.

       Mandatory  arguments to long options are mandatory for short options
       too.

       -a, --all
              do not ignore entries starting with .

       -A, --almost-all
              do not list implied . and ..

       --author
              with -l, print the author of each file

       -b, --escape
              print C-style escapes for nongraphic characters
 Manual page ls(1) line 1 (press h for help or q to quit)


```

## 日本語化する方法

実行例の通り、デフォルトではマニュアルが英語になっています。
日本語化するには以下のコマンドを実行します。

```bash
$ sudo apt install manpages-ja
```
上記コマンド実行後は以下のように日本語化されるようになります。

```bash
LS(1)                     ユーザーコマンド                    LS(1)

名前
       ls - ディレクトリの内容をリスト表示する

書式
       ls [オプション]... [ファイル]...

説明
       FILE (デフォルトは現在のディレクトリ) に関する情報を一覧表示
       します。 -cftuvSUX のいずれも指定されず、 --sort  も指定され
       ていない場合、 要素はアルファベット順でソートされます。

       長いオプションで必須となっている引数は短いオプションでも必須
       です。

       -a, --all
              . で始まる要素を無視しない

       -A, --almost-all
              . および .. を一覧表示しない

 Manual page ls(1) line 1 (press h for help or q to quit)
```
float32のrgbaデータをuint8に変換する


## 前提
ZED SDK で点群(PointCloud) データを取得する。
そのときに、XYZRGBAのデータを取得することができる。

# xyz_rgba はnumpy のdtype=np.float32 のデータ形式になる。
```
xyz_rgba = point_cloud.get_data()
```
xyz_rgba[:, :, 3]　は(r, g, b, a) の各uint8 をfloat32のデータ形式として解釈した値が格納されている。

## こまったこと
- float32のデータ形式 から(r, g, b, a) の各uint8 に変換する方法の記載がなかった。

### [IEEE 754 での単精度浮動小数点数の形式: binary32](https://ja.wikipedia.org/wiki/%E5%8D%98%E7%B2%BE%E5%BA%A6%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%95%B0)

![Screenshot from 2024-03-02 09-58-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83761/e6c3367e-70c7-8b2d-df67-cf91127a20bd.png)
wikiからのスクリーンショット

## 解決手法：
### [numpy.frombuffer()](https://numpy.org/doc/stable/reference/generated/numpy.frombuffer.html) を使う


```.py:
import numpy as np

colorarray = np.random.randint(0, 255, (12), dtype=np.uint8)
byte_data = colorarray.tobytes()
retrieved_color_array = np.frombuffer(byte_data, dtype=np.uint8)

# 変換・逆変換後の値が一致することを確認
assert np.array_equal(retrieved_color_array, colorarray)

print(f"{colorarray=}")
print(f"{byte_data=}")
print(f"{retrieved_color_array=}")

# float32にとして解釈
float32_array = np.frombuffer(byte_data, dtype=np.float32)
print(f"{float32_array=}")

# float32の配列を再度バイト列に変換
byte_data2 = float32_array.tobytes()
# そのバイト列をuint8で再解釈
retrieved_color_array2 = np.frombuffer(byte_data2, dtype=np.uint8)
print(f"{retrieved_color_array2=}")
# 元のuint8と一致することの確認
assert np.array_equal(retrieved_color_array2, colorarray)


```

## 実行結果
```.py:
colorarray=array([ 83,  15, 209, 142,  29, 242,  41, 229,  34, 209, 185, 172],
      dtype=uint8)
byte_data=b'S\x0f\xd1\x8e\x1d\xf2)\xe5"\xd1\xb9\xac'
retrieved_color_array=array([ 83,  15, 209, 142,  29, 242,  41, 229,  34, 209, 185, 172],
      dtype=uint8)
float32_array=array([-5.1537235e-30, -5.0159134e+22, -5.2812347e-12], dtype=float32)
retrieved_color_array2=array([ 83,  15, 209, 142,  29, 242,  41, 229,  34, 209, 185, 172],
      dtype=uint8)
```

# 追記：成功しなかった方法
- 以下の関数を利用してfloat32をTuple[int, int, int, int]　に変換しようとする試み。
- 失敗した理由：
− pythonの言語仕様自体には（つまりnumpyなしでは）、float32という型は存在しない。
- numpy配列の一部を単独のスカラー値として扱った時点で、float32からfloat64に暗黙の変換がされる。
- そのため、struct.pack('f', float_value)をした時点で、packされる値は、元のfloat32とは違ってしまっている。
- 結論:　numpyを使いましょう。


```.py:
# 成功しなかった方法
def float32_to_bytes(float_value: float) -> bytes:
    bytes_data = struct.pack('f', float_value)  # 'f'はfloat32を表すフォーマットです
    return bytes_data


def fourbytes2arraychar(fourbytes: bytes) -> Tuple[int, int, int, int]:
    int32_val = int.from_bytes(fourbytes, byteorder="little")
    return (int32_val & MASK0,
            (int32_val & MASK1) >> 8,
            (int32_val & MASK2) >> 16,
            (int32_val & MASK3) >> 24)
```