OmniAICreator/Qiita-1.07M huggingface dataset:
Javaのソースコードを実装する時の心得

上司にアドバイスをいただいた
Javaのソースコードを実装する際に
やった方がいい事
こうした方が効率が良くなるよ
とかを記録、メモ
(随時更新)

# Javadocは、メソッドとかクラスを作った（書いた）時点で書いてしまった方がいい

**経緯：**
時間があまり無い状況で、「まずは動くものを作ることを優先しよう！！」と考え、Javadocの記載を後回しにしていた。
しかし、上司から「後から書くと、二度手間になるし、記載漏れも出てくるでしょ。後回しにする理由も無いし、すぐに対応してしまった方がいいよ。」とご指摘をいただいた。
(上司の場合、Javadocは、メソッドとかクラスを作った（書いた）時点で書いてしまっているとのこと)

--
1. 実装し終わったクラスやメソッドにまた戻ってこなくてはいけない
1. 『これってなんのクラス、メソッドだっけ？引数、戻り値はなんだっけ？？』と、思い出す(考える)必要がある
1. 1.で戻る際に、記載漏れが発生するかも

→1、2の時点で二度手間
　3で記載漏れ(修正の場合は修正漏れ)が発生する

--

# Javadoc

公式サイト

https://www.oracle.com/jp/technical-resources/articles/java/javadoc-tool.html

Javadocの主な記述箇所
|記述箇所|説明|例|
|---|---|---|
|クラス|クラスの役割を記述<br>(バージョンや、作成者の情報もここに記述)|/** ほげほげControllerクラス. */<br>public class  HogehogeController{|
|コンストラクタ|コンストラクタの説明を記述|public class  HogehogeController{<br><br>  /**<br>   * デフォルトコンストラクタ.<br>   */<br>  HogehogeController(){<br>    this.hugahuga = 0;<br>      }|
|フィールド|フィールドがどんな意味のデータを保持するのかを記述|/** 学生情報Dao. */<br>private StudentDao studentDao;|
|メソッド|メソッドの<br>　・説明<br>　・引数<br>　・戻り値<br>　・発生する例外<br>などの説明を記述|/** 学生情報を更新する. */<br>public void updateStudent(int id, String studentName) throws SQLException {|

公式サイト

https://docs.oracle.com/javase/jp/8/docs/technotes/tools/windows/javadoc.html

より
> 説明
javadocコマンドは、一連のJavaソース・ファイルにある宣言およびドキュメンテーション・コメントを解析し、デフォルトではpublicクラス、protectedクラス、ネストされたクラス(匿名の内部クラスは除く)、インタフェース、コンストラクタ、メソッド、およびフィールドについて説明した一連のHTMLページを生成します。javadocコマンドを使用すると、APIドキュメントや、一連のソース・ファイルの実装ドキュメントを生成できます。

Javadocで使用できるタグ
|タグ  |説明| [公式サイト](https://docs.oracle.com/javase/jp/8/docs/technotes/tools/windows/javadoc.html)より| 備考 |
|---|---|---|---|
|```@param``` 変数名 説明|メソッドの引数、ジェネリクスの型の説明を記述| > `@param` parameter-name description | - |
|```@return``` 説明|メソッドの戻り値の説明を記述| > `@return` description | - |
|```@throws``` 例外クラス 説明|メソッドでスローされる例外の説明を記述| > `@throws` class-name description | 公式の[How to Write Doc Comments for the Javadoc Tool](https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html#@exception)より<br>> Document the following exceptions with the `@throws` tag:<br>> All checked exceptions.<br>> (These must be declared in the throws clause.)<br>> Those unchecked exceptions that the caller might reasonably want to catch.<br>> (It is considered poor programming practice to include unchecked exceptions in the throws clause.)<br>> Documenting these in the `@throws` tag is up to the judgment of the API designer, as described below.[^1]|
[^1]:Javadocの`@throws`タグを記載しなくてはいけない時はどんな時なのかについては、[Javadocの@throwsタグを記載しなくてはいけない時](https://qiita.com/pe-pe-desu/items/fb15918de7ab5efcaeb8)を参照

- Javadocの記載は、`<br>`で改行できる




# ログの書き方

## 参考サイト
https://qiita.com/opengl-8080/items/49719f2d35171f017aa9

# HTTPステータスコード
Java8
HttpURLConnection

https://docs.oracle.com/javase/jp/8/docs/api/java/net/HttpURLConnection.html


# 実装

## 関数の「戻り値」以外で、関数の呼び出し元に値を返す方法
try-catchで捕まえて throwする

別なファイルとかに出力して、出力したものを別なヤツで読み込む
Ubuntuで自作コマンド?を作ろう

# Ubuntuで多機能自作コマンドを作ろう

自分でコマンドみたいなの作ってみたから参考までに。
このコマンドは、いくつかのオプションを持っていて、テキストファイルやPDFファイルの操作、Pythonファイルの実行や作成ができるようにしました。

## スクリプトファイルの作成

まずは、スクリプトファイルを作成。
altairって名前のコマンドにします。

```bash
nano ~/bin/altair
```

## スクリプトの内容を編集

以下の内容をスクリプトファイルに記述するんや。

```bash
#!/bin/bash
# altairコマンド

function show_help {
    echo "使用法: altair [オプション]"
    echo "オプション:"
    echo "  -h, --help      このヘルプメッセージを表示"
    echo "  txt             geditでサンプルのテキストファイルを開く"
    echo "  pdf [filename]  evinceでPDFファイルを開く"
    echo "  py [filename]   /home/user/Documents/python からPythonファイルを検索して実行する"
    echo "  mkpy [filename] /home/user/Documents/python にPythonファイルを作成してgeditで開く"
    echo "  oppy [filename] /home/user/Documents/python からPythonファイルを検索してgeditで開く"
}

function open_text {
    gedit ~/sample.txt
}

function open_pdf {
    if [ -z "$1" ]; then
        echo "ファイル名を指定してや"
    else
        evince "$1"
    fi
}

function run_python {
    if [ -z "$1" ]; then
        echo "ファイル名を指定してや"
    else
        python3 "/home/user/Documents/python/$1"
    fi
}

function make_python {
    if [ -z "$1" ]; then
        echo "ファイル名を指定してや"
    else
        touch "/home/user/Documents/python/$1"
        gedit "/home/user/Documents/python/$1"
    fi
}

function open_python {
    if [ -z "$1" ]; then
        echo "ファイル名を指定してや"
    else
        gedit "/home/user/Documents/python/$1"
    fi
}

case "$1" in
    -h|--help)
        show_help
        ;;
    txt)
        open_text
        ;;
    pdf)
        open_pdf "$2"
        ;;
    py)
        run_python "$2"
        ;;
    mkpy)
        make_python "$2"
        ;;
    oppy)
        open_python "$2"
        ;;
    *)
        echo "不正なオプションやで"
        show_help
        ;;
esac
```

## 実行権限を付与

作成したスクリプトに実行権限を付与

```bash
chmod +x ~/bin/altair
```

## PATHにディレクトリを追加

自作コマンドをどこからでも実行できるようにするために、スクリプトのディレクトリをPATHに追加。`~/.bashrc`に以下の行を追加。

```bash
echo 'export PATH=$PATH:~/bin' >> ~/.bashrc
source ~/.bashrc
```

## コマンドの実行

これで自作コマンド「altair」が完成。

### ヘルプを表示

```bash
altair -h
```

### テキストファイルを開く

```bash
altair txt
```

### PDFファイルを開く

```bash
altair pdf filename.pdf
```

### Pythonファイルを実行

```bash
altair py script.py
```

### Pythonファイルを作成して開く

```bash
altair mkpy new_script.py
```

### Pythonファイルを開く

```bash
altair oppy existing_script.py
```

## おわりに

Ubuntuで多機能な自作コマンド？を作成する方法を紹介しました。
自分だけの便利なコマンドが増えていくと、作業が楽になる。きがする。
Ubuntu 22.04 LTSでのROS2 Humble Hawksbillのインストール手順

Ubuntu 22.04 LTS（Jammy Jellyfish）にROS2 Humble 機会があったのでメモしてたのを記事にしました。
一応説明すると、ROS2（Robot Operating System 2）は、ロボット開発のためのオープンソースフレームワーク

## 前提条件

まず、以下の前提条件を確認しといてや：

- Ubuntu 22.04 LTSがインストールされていること
- 管理者権限（sudo）があること

## インストール手順

### 1. パッケージの更新

まずは、システムのパッケージを最新の状態に更新に。

```bash
sudo apt update
sudo apt upgrade
```

### 2. ソースリストの追加

ROS2のパッケージをダウンロードするために、ソースリストを追加する必要がある。

```bash
sudo apt install software-properties-common
sudo add-apt-repository universe
sudo apt update
```

### 3. ロケールの設定

ロケール（言語と地域設定）を適切に設定しとく。

```bash
sudo apt install locales
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8
```

### 4. aptリポジトリの追加

ROS2のaptリポジトリを追加する。

```bash
sudo apt install curl gnupg lsb-release
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -
sudo sh -c 'echo "deb [arch=amd64,arm64,armhf] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" > /etc/apt/sources.list.d/ros2-latest.list'
sudo apt update
```

### 5. ROS2 Humbleのインストール

ROS2 Humble Hawksbillをインストール。

```bash
sudo apt install ros-humble-desktop
```

### 6. 環境変数の設定

ROS2の環境変数を設定するために、`.bashrc`に追記。

```bash
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
source ~/.bashrc
```

### 7. colconのインストール

ビルドツールであるcolconをインストールする。

```bash
sudo apt install python3-colcon-common-extensions
```

### 8. 動作確認

最後に、ROS2が正しくインストールされているか確認するために、デモノードを実行

```bash
ros2 run demo_nodes_cpp talker
```

別のターミナルを開いて、リスナーを実行

```bash
ros2 run demo_nodes_cpp listener
```

### おわりに

これで、Ubuntu 22.04 LTSにROS2 Humble Hawksbillのインストールが完了したはず。
初めてUbuntu触ったときは色々戸惑ったけど慣れればいける。気がする…
Workato：サービスの稼働状況（障害・メンテナンス情報）を確認する

# はじめに

Workatoはサービスの稼働状況（ステータスページ）が公開されており、ユーザーである・なしにかかわらずその内容をリアルタイムに確認することができます。この機能を活用することで、Workatoの障害情報をいち早くキャッチすることが出来ます。

# ステータスページのリンク

Workatoの障害ならびにメンテナンス情報は以下より参照することが可能です。

リージョン（データセンター）ごとにリンクは分かれており、参照したいリージョンのリンクをクリックすることで、そのリージョンの障害・メンテナンス情報を確認することができます。

- [Workato US (United States Region)](https://status.workato.com/)
- [Workato EU (Europe Region)](https://status.eu.workato.com/)
- [Workato SG (Singapore Region)](https://status.sg.workato.com/)
- [Workato JP (Japan Region)](https://status.jp.workato.com/)
- [Workato AU (Australia Region)](https://status.au.workato.com/)

これらのページへアクセスすると、次のようなページが表示され、サービスの稼働状況を確認することができます。（Atlassianの[Statuspage](https://www.atlassian.com/ja/software/statuspage)というサービスを利用して公開されています）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/11965639-cdd3-ccb5-57a9-09fd0581663f.png)

# 障害・メンテナンスの詳細を確認する

ページをスクロールすると、次のように、何らか障害やメンテナンスが発生した際の内容を確認することが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/60ff85ad-2f10-f787-f528-9e51e5ea1357.png)

# 過去に遡って障害・メンテナンス情報を確認する

ページ下部の「Incident History」というリンクをクリックすると、過去に発生した障害ならびにメンテナンス情報を確認することが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/98eb5996-4e83-ab81-ea0e-6d8b3f9a5c25.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/ea064ae4-577e-dbb9-aef2-757a4619a374.png)

# 障害・メンテナンス情報の購読

「SUBSCRIBE TO UPDATES」ボタンをクリックすると、障害あるいはメンテナンスが発生した際に、希望のチャネルに対してその情報を通知する（障害・メンテナンス情報を購読する）ことができます。障害・メンテナンス情報をいち早くキャッチする方法として大変役立ちます。

チャネルとして、E-Mail, SMS, Slackによる通知（購読）に対応しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/b33d94cf-71a5-d143-c5a6-e9c19c8f9e83.png)
Roomが「DatabaseのVersionが違う」とクラッシュしてしまう原因パターン

# Roomが「DatabaseのVersionが違う」とクラッシュしてしまう原因パターン
[パターン1：新規開発もしくは、初めてDBに変更を加える](#パターン1新規開発もしくは初めてdbに変更を加える)
[パターン2：DB修正後とかに、再度DBに修正を加える](#パターン2db修正後とかに再度dbに修正を加える)

# パターン1：新規開発もしくは、初めてDBに変更を加える
**例**
①開発環境(Android Studio)で、初めてDBに修正を入れてDBバージョンを1→2に上げた
②実機(Android端末)から、アプリ(←DBバージョン1)を**アンインストールせず**に、アプリを再インストール(←DBバージョン2)
③マイグレーションが実行される
　(DBバージョンが上がっているアプリを再インストールされたため、マイグレーションが実行される)
**★ここで例外が出て(クラッシュして)しまうとダメ！！
　ここでクラッシュするのはヤバいので、要調査&要対応！！**

# パターン2：DB修正後とかに、再度DBに修正を加える
**例**
①開発環境(Android Studio)で修正したDB周りのコードが間違えてたから直したお！
　(DBバージョンは2から変更せず、 DBの定義(Entityクラスとか)修正)
②実機(Android端末)から、アプリ(←DBバージョン2)を**アンインストールせず**に、アプリを再インストール(←DBバージョン2)
③実機(Android端末)内で、`allowBackup`のバックアップ情報(コードを直す前のDB情報)を参照
④マイグレーションが実行されず、DB情報が噛み合わなくなって例外が発生(クラッシュする)！！
　(↑開発中はよくある(よくやってしまう)ため、あまり問題にはならない)

これの回避策は、
アプリをちゃんと**アンインストールしてから**再インストールしなおす。
もしくは、実機(Android端末)の設定から、**アプリのストレージ情報を手動で削除する**。
こうすることで、DBのバックアップ情報を削除できる！！

# 備考
Roomで「DatabaseのVersionが違う」とクラッシュしてしまうのは、もし問題が元々のソースコードであった場合、アプリアップデート時に検出されるような目立つクラッシュ。
開発環境では、DBを弄ることが多いため、この手のクラッシュは必然的に出やすくなるが、テスト観点としても気にしておく必要はある。

# 参考サイト
https://qiita.com/satohu20xx/items/071570f7b4766b3124b7

https://hilog07.blogspot.com/2019/03/android-studio-room-cannot-verify-data.html?m=1
OpenSSH の脆弱性について簡単に調べと対策

# 概要
2024/07/01、OpenSSH サーバー (sshd) に深刻な脆弱性が確認されたとして [CVE-2024-6387](https://nvd.nist.gov/vuln/detail/CVE-2024-6387) が公開された。この脆弱性では、クライアントが LoginGraceTime 秒以内に認証しない場合、sshd の SIGALRM ハンドラーが非同期的に呼び出されるため、リモートコードを実行される危険性があると説明している。

この脆弱性は [CVE-2006-5051](https://nvd.nist.gov/vuln/detail/CVE-2006-5051) のレグレッションと言われているらしい。また、[Qualys](https://blog.qualys.com/vulnerabilities-threat-research/2024/07/01/regresshion-remote-unauthenticated-code-execution-vulnerability-in-openssh-server) によると 1400 万以上の潜在的に脆弱なサーバーインスタンスを特定したとしている。

# 対策
既に修正版がリリースされているので、できる限り早く更新する必要がある。

Ubuntu では、以下のコマンドを使用し (再起動する) ことで更新の確認ができた。
(apt 使うものなら大体これでいけるはず。)
```bash
# オプションを指定して sshd だけアップグレードしても良い
apt update && apt upgrade
```

詳細は各ディストリビューションページを参照してください。

Ubuntu
> https://ubuntu.com/security/CVE-2024-6387

Debian
> https://security-tracker.debian.org/tracker/CVE-2024-6387

Red Hat Enterprise Linux
> https://access.redhat.com/security/cve/CVE-2024-6387




# 参考
https://rocket-boys.co.jp/openssh-vulnerability-cve2024-6387/

https://security.sios.jp/vulnerability/openssh-security-vulnerability-20240701/

https://qiita.com/mai_llj/items/e02383af984bd7f35ad0

https://piyolog.hatenadiary.jp/entry/2024/07/02/032122
Webページの更新見落としを防ぐDistill Web Monitorを使ってみた

# 概要
任意のページが更新されたか、注意深く確認しているつもりでも、監視対象が増えると、見落としが発生してしまいます。加えて、定期的にページにアクセスして確認するという手順は煩雑です。よって、自動確認してアラートが出来るソフトウェアはないかと探している時に見つけたのが、「Distill Web Monitor」です。これを使ってページの更新が有った時は自動的にアラートが飛ぶようにしたいと思います。

# Distill Web Monitorとは？
任意のWebページが更新されているか定期的に監視し、更新されている場合は通知を行うアプリケーションです。Googole Chromeをはじめとるする主要なWebブラウザ向けの拡張機能やデスクトップアプリ版などが提供されています。無料で利用が出来ます。より高度な監視やアラートを使いたい場合は、有料版も有りますが、まずは無料版で試してみようと思います。

https://forest.watch.impress.co.jp/docs/review/1051597.html

https://distill.io/

https://distill.io/pricing/

# Google Chrome拡張機能のインストール
Google Chrome向けの拡張機能でDistill Web Monitorを利用しようと思います。実際に利用してみて便利だったら、デスクトップアプリ版なども利用しようと思います。

https://chromewebstore.google.com/detail/distill-web-monitor/inlikjemeeknofckkjolnjbpehgadgge?hl=ja

# Distillアカウントの作成
アカウントを作成しなくても利用は可能です。しかし、アラートをメールで受け取りたい場合は、アカウントが必要になります。よって、アカウントを作成しました。サインインページから案内に従って入力し、メールアドレス確認のメールが送られてきたら、メール内のリンクをクリックしてアカウント作成を完了させます。

# 実際にアラートを作成
監視したいWebページを起動した上で、Distill Web Monitor拡張機能のアイコンをクリックすると以下のウィンドウが表示されます。「ページのパーツを選択」をクリックします。

![distill.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/bbcf649a-377f-05b9-c185-ba6290611798.png)

今回は以下のRaspberry PiのAI Kitの入荷を監視しようと思います。現在は下図の様に在庫切れとなっており、購入が出来ません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/47a63c39-e978-e0a6-dd6c-b2f844d6980d.png)

今回は以下の部分を監視することにします。在庫が入荷されれば、恐らく表示が変わるでしょう。
> この商品は在庫切れ中です

監視オプション設定を下図の様に設定し、保存をクリックします。

![option.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/36c41cb2-80d7-dd18-9cef-a8b09cbb6f8c.png)

監視リストに監視エントリが追加されました。

![list.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/6c9969ef-6f31-6c37-813c-2c4e1c5c399a.png)

資格の申込受付の開始がページに掲載されるタイミングでアラートが飛ぶと申し込み忘れを防止できて便利なので、幾つか監視リストに追加してみることにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/973a8496-9fa7-1665-4448-1459979e6b50.png)

# まとめ
Webページの更新を監視するためにDistill Web Monitorを導入してみました。監視の設定などはとても簡単に出来ます。まだアラートは受け取っていないため、何とも言えませんが、今回設定した幾つかのページで更新を観測した通知が届いてから今後積極的に利用するか考えようと思います。
高専ロボコン回路　モタドラ編

高専ロボコン用に作成したモータードライバーです。
HブリッチでFull-Nchのモタドラです。
これらを動かすための回路（MDD）は別の記事に乗せてます。
今の所1度も燃えていないので多分頑丈です。
排熱も良さげ

# [**AltairMD_V7**](https://github.com/Altairu/AltairMD_V7)

![MD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336552/21ffa2f6-7693-4556-db66-273c93aca587.png)

![MD_kairozu_all.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336552/f54935b0-5d27-b5ca-a8d8-9fcd7a98553a.png)

![MD_PCB_all.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336552/54347daf-1edf-e46c-db71-d0621acba8a6.png)


https://github.com/Altairu/AltairMD_V7
---
### **仕様**
* 30V~10V(フォトカプラを変更すると10V以下も可)
* 最大40A 

|SDs|Ps1|Ps2|出力|
|:----:|:----:|:----:|:----:|
|HIGH|LOW	|LOW	|停止|
|HIGH|LOW	|HIGH	|逆転|
|HIGH|HIGH	|LOW	|正転|
|HIGH|HIGH	|HIGH	|`ブレーキ`（非推奨）|
|LOW|X	|X	|0|
### **降圧**

![三端子.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336552/b6c5dcde-8be4-c37c-876f-5dae68fa2204.png)
![三端子PCB.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336552/aa338410-c174-0f3b-796b-e6eb96c48f8a.png)


### **三端子レギュレーター** 
### **[NJM7812SDL1]()**
* **12Vに降圧**
* **端子が3つ(入力・グラウンド・出力）**
* **三端子レギュレータは落とした分の電圧をすべて`熱`として消費**
* **ダイオード**
レギュレータに逆電流が流れるのを防止
* **コンデンサ**
コンデンサは入力側と出力側に0.1～10[uF]程度入れるのが一般的


## **フォトカプラ**
![フォトカプラ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336552/a38c2f57-7882-3982-d020-207697387efa.png)

### [TLP152](https://akizukidenshi.com/catalog/g/g110824/)
* 取り付け様式:	SMD/SMT	
* パッケージ/ケース:SOIC-6
* 電源電圧min.：10V
* 電源電圧max.：30V
* 出力電流：2A
* 入力電流max.：20mA
* 上昇応答時間：95ns
* 下降応答時間：110ns


---
## **MOSFET**
[**RSJ400N10**](https://www.rohm.co.jp/products/mosfets/small-signal/single-nch/rsj400n10-product)
Nch 100V 40A Power MOSFET

![fet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336552/95c65179-6a7f-cb4d-8691-cec3cebdff7d.png)

* 4V駆動タイプ
* Nチャンネル　パワーMOSFET
* 高速スイッチング
* 駆動回路が簡単
* 並列使用が容易

ゲート抵抗は10[Ω]で設定している

---
### **ハーフブリッジゲートドライバ**
### [**IR2302STRPBF**](https://akizukidenshi.com/catalog/g/g115656/)
![ir2302PCB.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336552/f2decc8e-0330-1f57-91aa-62905c601ed8.png)
![ir2302_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336552/b293b9b6-e11d-0266-b743-1214f445d9f1.png)

 
* IN端子
ハイサイドMOSFETをONにするか、ローサイドMOSFETをONにするかの切り替えを行う
Hが入力されるとハイサイド、Lが入力されるとローサイドがONとなる
**ハイサイドにNchMOSFETを使うためにブーストラップ回路を使用**
* ブートストラップコンデンサの容量は[10uF]
* ブートストラップダイオード
(ファストリカバリダイオード)
* `100％出力は不可`
ブートストラップ回路の制約で
コンデンサのチャージ時間が必要.

# hブリッジ回路
![HブリッジPCB.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336552/0fa9b702-9665-5267-900c-7d457076feac.png)


| Ps1 | Ps2 | Q1  | Q2  | Q3  | Q4  | 1    | 2    | 
| :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: | 
| L   | L   | H   | L   | H   | L   | open | open | 
| L   | H   | H   | H   | L   | L   | L    | H    | 
| H   | L   | L   | L   | H   | H   | H    | L    | 
| H   | H   | H   | H   | H   | H   | L    | L    |
デジタルフィルター



![IMG_6396.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/19960aae-e621-d701-0137-840f720a0723.jpeg)

![IMG_6397.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/7929688b-b414-de0b-46fe-108d5d5a22fe.jpeg)



```
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import freqz

# フィルタ係数
H = 1
b = 0.5  # 例として0.5を使用

# 周波数範囲の設定
w, _ = freqz([1], [1])

# 1次ローパスフィルタの周波数応答
b_lp = [H, H]
a_lp = [1, -b]
w, h_lp = freqz(b_lp, a_lp)

# 1次ハイパスフィルタの周波数応答
b_hp = [H, -H]
a_hp = [1, -b]
w, h_hp = freqz(b_hp, a_hp)

# 1次オールパスフィルタの周波数応答
b_ap = [b, -1]
a_ap = [1, -b]
w, h_ap = freqz(b_ap, a_ap)

# ボード線図のプロット
plt.figure(figsize=(12, 8))

# 振幅応答
plt.subplot(2, 1, 1)
plt.plot(w, 20 * np.log10(abs(h_lp)), label='Low-pass Filter')
plt.plot(w, 20 * np.log10(abs(h_hp)), label='High-pass Filter')
plt.plot(w, 20 * np.log10(abs(h_ap)), label='All-pass Filter')
plt.title('Bode Plot - Magnitude Response')
plt.xlabel('Frequency [radians / sample]')
plt.ylabel('Magnitude [dB]')
plt.legend()
plt.grid()

# 位相応答
plt.subplot(2, 1, 2)
plt.plot(w, np.angle(h_lp), label='Low-pass Filter')
plt.plot(w, np.angle(h_hp), label='High-pass Filter')
plt.plot(w, np.angle(h_ap), label='All-pass Filter')
plt.title('Bode Plot - Phase Response')
plt.xlabel('Frequency [radians / sample]')
plt.ylabel('Phase [radians]')
plt.legend()
plt.grid()

plt.tight_layout()
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/517d2135-daf4-eeab-7a18-5e045d74bcf3.png)





```



```




```



```



```



```



```



```



```



```
クローンアプリを作ってみたーNetflixクローン⑤

# はじめに
初めまして！
エンジニアになって数年、今まで本を読むだけでしたが、もっとプライベートで楽しみながら成長したい！自分が学んだ足跡を残していきたい！と思い記事を書きました！
最終的には自在に開発できるようになりたいと思っています。:triumph:
いろいろな記事を参考にさせてもらっています。:bow_tone2:
その中でもこれってどういう意味？とかつまづいたところを念入りに書いていこうかと思います。:fist:

# 今回の目的
nextjsはまだですが、実際のアプリ開発からどう作られていくかを学んでいくためにクローンアプリを開発します。
とは言っても自分で考えることは特になくYoutubeを見てやっていきます。
その中で覚えておきたい部分を分類ごとに記載していきます。なので、その時々に知ったことを小出しにしていく形になります。

前回

https://qiita.com/mr_noppo/items/4dd10edb45d0febd2d77

# 使用したものや事前準備
・Macbook Pro
・Visual Studio Code

# 使用にさせていただいた動画

https://www.youtube.com/watch?v=mqUN4N2q4qY&t=4201s

# Next.jsの知識
### next-auth
#### Github
取得できる情報は下記を参考

https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/github.ts

### ~Provider
#### clientId
OAuth アプリケーションを識別するために GitHub によって提供される一意の公開識別子。「ユーザーID」のようなもの。Github上で一意なためURLに付与しアプリケーション認証へ遷移する。
#### clientSecret
OAuth アプリケーションの認証を行うための秘密キー。「パスワード」のようなもの。
```ts
GithubProvider({
    clientId: ...
    clientSecret: ...
}),
```

### import { NextPageContext } from 'next';
Next.jsのコンテキストオブジェクトで、HTTPリクエストやルーティングの情報などが含まれる

### import { getSession, signOut } from 'next-auth/react'
#### getSession(context: NextPageContext)
ページコンテキストからセッション情報取得。
内部でfetchData<Session>を呼び出しており、cookieをparamにリクエストした結果、jsonが帰ってこなければnullとなる。
#### signOut
サインアウト実行

### getServerSideProps
Next.js で定義された特別な関数。ページがレンダリングされる前にサーバー側で自動的に実行され、その結果がページコンポーネントにpropsで渡される。

https://nextjs.org/docs/pages/building-your-application/data-fetching/get-server-side-props

#### リダイレクト構文
```tsx
  if(!session){
    return {
      redirect: {
        destination: '/auth',
        permanent: false,
      }
    }
  }
```

### import useSWR from "swr";
React アプリケーションでデータフェッチングを簡単に行うためのカスタムフック
```tsx
const { data, error, isLoading, mutate } = 
useSWR("/api/user", (url: string) => axios.get(url).then((res) => res.data));
```

#### /api/user
エンドポイントURL

#### (url: string) => axios.get(url).then((res) => res.data)
fetcher関数。urlはエンドポイントURL

#### data
リクエストが成功するとフェッチされたデータが格納される。

#### error
リクエスト中にエラーが発生した場合、エラー情報が格納される。

#### isLoading
ローディング状態を判断

#### mutate
ローカルキャッシュのデータを手動で再検証（更新）することができる関数

# 次
https://qiita.com/mr_noppo/items/5be0b586fa2f335170a6
Seleniumの激遅find_elementsから開放されよう、lxmlのすすめ

# はじめに
ブラウザ操作を自動化するライブラリのSelenium。
Seleniumのfind_elementメソッド遅くて正直しんどくないですか？
特に大量のデータを扱うときなんかだと、イライラしてキーボードを投げたくなっちゃうこともしばしば…。
そんな時は、`page_source`をもってきてlxmlに食わせてしまいましょう。


# 動作環境
- Python 3.12.3
- google-colab-selenium-1.0.13

# どのくらい違うの？
以下のコードで実行時間を比較してみました。
今回は、例として、[Yahoo Japan](https://www.yahoo.co.jp/)からリアルタイム検索で話題のキーワードを取得します。

```py
import google_colab_selenium as gs
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import datetime
import lxml.html
import lxml.cssselect

options = Options()
options.add_argument("--headless")
options.add_argument('--disable-dev-shm-usage')
options.add_argument("--no-sandbox")
options.add_argument("--lang=ja")
driver = gs.Chrome(options=options)

start_time = datetime.datetime.now()
# Yahoo Japanからリアルタイム検索で話題のキーワードを取得
driver.get("https://www.yahoo.co.jp/")
# find_elementsで要素を探索
results = driver.find_elements(By.CLASS_NAME, "_35gOEPVmLqF0YTra3WRwfD")

end_time = datetime.datetime.now()
for val in results:
  print(val.text)

find_elements_return_time = end_time - start_time
print(f"\nfind_elements実行時間: {find_elements_return_time}\n")


start_time = datetime.datetime.now()
# Yahoo Japanからリアルタイム検索で話題のキーワードを取得
driver.get("https://www.yahoo.co.jp/")
# lxmlによる探索
html = lxml.html.fromstring(driver.page_source)
results = html.cssselect("._35gOEPVmLqF0YTra3WRwfD")
end_time = datetime.datetime.now()

for val in results:
  print(val.text)

lxml_return_time = end_time - start_time
print(f"\nlxml実行時間: {lxml_return_time}")

driver.quit()
```

実行してみるとこんな感じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/7302065b-e2a8-2192-4d59-cc1144db3b04.png)

lxmlでの取得は約1秒で終わったのに対し、find_elementsでの取得では約2秒かかっていて、処理時間に大きな差がありました。

今回のように1つの要素のみを取得する場合はあまり差が出ませんでしたが、ページの内容が増えれば増えるほど、この差はさらに大きくなります。

# まとめ
Seleniumで`find_elements`が遅いと感じているなら、ぜひlxmlを試してみてください。
きっとしあわせになれるでしょう。

それではそれでは。
CGIってなんじゃ

# はじめに

CGI。前から存在だけは知っていて、でも少ーし調べたところで「？」「サーバーサイドで動作するプログラムと何が違うんや」という感想しか生まれず、ずっと目を背け続けていたそんな彼と今日、ようやく向き合ってみました。

<br>

長らく気になっていたことが頭の中で整理できた喜びのあまり 急いでまとめたので、誤った表現もあるかもしれませんがその際はご指摘いただけますと幸いです。

# 概要

- CGIとは
- FastCGIとは
- PHP-FPM？mod_php？
- Dockerイメージの例

# CGIとは

CGI（Common Gateway Interface）は、Webサーバーと外部プログラム（PHPなど）の間で情報をやりとりするための標準的なインターフェース（プロトコル）です。

（現在ではCGIに似た役割を担う別の方法もありますが、）基本的にこのような仕組みがないとサーバーサイドでプログラムを実行することはできません。←**知らなかった...**

:::note warn
※厳密には「実行できない」というよりWebサーバーから「呼び出すことができない」？（実行自体はランタイムがあれば可能なため）
:::


<br>
処理の流れとしては

1. Webサーバーがクライアントからリクエストを受ける
1. Webサーバーは**CGIプロトコルによってリクエストを転送し、外部プログラム（PHPスクリプト等）を実行**
1. その結果をWebサーバーが受け取り、クライアントへ返却

という感じです。

<br>

元々私はCGIがなんだかよくわからず、かつWebサーバー／APサーバーを一から構築した経験がなかったため、「**サーバーサイドでプログラムを実行させるなんて、LaravelやNode.jsだって（ローカルやDockerコンテナ上では）普通に動いてるし要るの？**」と考えていました。

また、「PHP:x.x-apache」や「PHP:x.x-fpm」のようなDockerイメージを使用して起動したコンテナで（当たり前ですが）「**普通にPHP動いとるがな？**」と、なんとも恥ずかしい勘違いをしていました。

※これらのDockerイメージについては後述します。

<br>

### 私なりにまとめると、

- 元々、Webサーバーで静的コンテンツを提供するだけなら問題なかった
- プログラムを実行して動的コンテンツを生成したい場合、**Webサーバーの機能だけではサーバーサイドでプログラムを実行することができない**ため、その基盤としてCGIが必要
- 「Webサーバー＋PHP＋CGIでまとめた1つのサーバー」でも「Webサーバー／PHP＋CGIのAPサーバー」でも可。いずれにせよ、**WebサーバーからCGIに対して指示を行い、PHPスクリプトを実行する**ような仕組みが必要

となります。

# FastCGIとは

簡単に言えばCGIの強化版です。

### CGI

- ユーザーからの**リクエストのたびにプロセスの生成と破棄**を行う

### FastCGI

- **初回リクエストのタイミングで起動したプロセスをメモリで保持**し、以降のリクエストに対してはそのプロセスを実行するため、サーバーの負荷の低減や処理速度の向上につながる

上記以外にも違いはありますが、大きな違いとしてはこんな感じです。

# PHP-FPM？mod_php？

現在、PHPをサーバーサイドで実行するための仕組みとして主流なものが2種類あります。

### PHP-FPM（FastCGI Process Manager）

- 前述したFastCGIの仕組みを取り入れたもの
- PHPをFastCGIとして動作させ、NginxやApacheのようなWebサーバーと通信する
- 処理の流れ（CGIと基本的に変わりませんが）
    - クライアントがサーバーへのリクエストを送信
    - WebサーバーがFastCGIプロトコルを使用してリクエストをPHP-FPMに転送
    - PHP-FPMがスクリプトを実行し、生成されたHTMLやデータをWebサーバーに返却
    - Webサーバーからクライアントに返却

### mod_php

- ApacheなどのWebサーバーにPHPをモジュールとして組み込む方法
    - ここでいう「モジュール」はWebサーバーが直接実行可能な機能のこと
- こうすることで、Webサーバーは直接PHPスクリプトを実行可能
- 処理の流れ
    - クライアントがWebサーバーへのリクエストを送信
    - Webサーバーが直接PHPモジュールを呼び出し、スクリプトを実行
    - 生成されたHTMLやデータをクライアントに返却

<br>

### イメージとしては、

- PHP-FPMがCGI（FastCGI）を介してプログラムを実行
- mod_phpはWebサーバーが直接プログラム（実際にはモジュール）を実行

という感じです。

# Dockerイメージの例

普段、何気なく使ってたDockerイメージも掘り下げてみるとこんな違いがありました。

### php:x.x-fpm

- Webサーバーから外部接続する、PHPプログラム専用のサーバーとなる（別でWebサーバーが必要）
- **PHP-FPM** の仕組み
- Nginx＋PHP-FPMの構成が一般的
- **フロントエンドサーバー（Nginx）とバックエンドサーバー（PHP-FPM）を分離できるため、スケーラブルなアーキテクチャが構築しやすい**
- 高パフォーマンス、スケーラビリティが高い、Nginxなどのウェブサーバーと連携が可能
- 高トラフィックのウェブサイト、大規模なアプリケーション、スケーラブルなインフラ構築

### php:x.x-apache
- PHPがApache Webサーバーのモジュールとして組み込まれている（Webサーバー上でそのままPHPプログラムを実行可能）
- **mod_php** の仕組み
- セットアップが簡単、単一のコンテナで完結
- 小規模なプロジェクト、開発やテスト環境、シンプルなデプロイメント

# 最後に

私自身 Angular＋NestJSでの開発経験が長かった（かつリリース経験が少ない）ため、Webサーバー、アプリケーションサーバー、Apache、Nginx...といったことに疎く、SPAから非同期でAPIを呼び出すため、サーバーにはAngularの実行ファイル＋APIサーバーを置いておく、といった雑な感覚のままでいました。

一般的にはWebサーバー（Apache、Nginx）で静的コンテンツの供給、アプリケーションサーバーで動的コンテンツを生成し、Webサーバーに返却、という流れが多いと思いますが、このあたりの感覚がなかったことで理解に時間がかかったというのもあると思います。

（Webサーバーでプログラムが実行できないとは？？？のような混乱を起こす原因に）

<br>

CGIがプロトコルであること、Webサーバーから外部（アプリケーションサーバー、あるいはWebサーバー内の）プログラムを呼び出すために必要であることは、Webアプリケーションを開発する上で非常に重要な仕組みだと思います。

<br>



苦手意識の強い部分でしたが、かなり勉強になりました。
Rubyで連分数展開のプログラムを書いてみた

# 連分数とは

**連分数**とは、以下のように分母に分数が含まれているような分数です。ただし、 $a_n$ と $b_n$ は整数です。また、 $b_n$ がすべて $1$ の場合、**正則連分数**と呼ばれます。（この記事では正則連分数のみを対象とするので、以降 「連分数」 と表記したものは正則連分数を指します。）

```math
x = a_0 + \frac{b_1}{a_1 + \frac{b_2}{a_2 + \frac{b_3}{a_3 + ...}}}
```

上記の $x$ が有理数の場合 $a_n$ は有限ですが、無理数の場合は無限に続きます。例として、黄金数 $\varphi = \frac{1 + \sqrt{5}}{2}$ は以下のように $a_n$ がすべて $1$ で、それが無限に続きます。

```math
x = 1 + \frac{1}{1 + \frac{1}{1 + \frac{1}{1 + ...}}}
```

# 連分数展開とは

ある数を連分数に変形することを、**連分数展開** と呼びます。小数は以下の手順で連分数展開できます。

1. 整数部分と小数部分に分ける
1. 分母と分子を分子で割る
1. 分母に対して 1 ~ 3 を繰り返す

例として、 $1.6$ を連分数展開してみます。

```math
\begin{align}
1.6 &= 1 + \frac{6}{10} & (1.6 を整数部分と小数部分に分ける) \\
    &= 1 + \frac{1}{\frac{10}{6}} & (分母と分子を分子で割る) \\
    &= 1 + \frac{1}{1 + \frac{4}{6}} & (10/6 を整数部分と小数部分に分ける) \\
    &= 1 + \frac{1}{1 + \frac{1}{\frac{6}{4}}} & (以下繰り返し) \\
    &= 1 + \frac{1}{1 + \frac{1}{1 + \frac{2}{4}}} \\
    &= 1 + \frac{1}{1 + \frac{1}{1 + \frac{1}{2}}} \\
\end{align}
```

できました。ちなみに、$1.6$ は黄金数 $1.618...$ に近い数なので、 $1.6$ の連分数展開も途中まで黄金数と同様に $a_n$ が $1$ になっています。このように、連分数は無理数を有理数で近似する際にも役立つらしいです。詳細は「ディオファントス近似」で調べてみてください。

https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%A3%E3%82%AA%E3%83%95%E3%82%A1%E3%83%B3%E3%83%88%E3%82%B9%E8%BF%91%E4%BC%BC

他にも、連分数に関連する様々な情報が Wikipedia にも書かれていて、面白いのでおすすめです。

https://ja.wikipedia.org/wiki/%E9%80%A3%E5%88%86%E6%95%B0

# 小数を連分数展開するプログラム

ここからが本題です。

手計算で連分数展開するのは面倒なので、プログラムで連分数展開しましょう。
先程紹介した手順を Rubyで書いてみます。

## 1. 整数部分と小数部分に分ける

Ruby には有理数の計算をするための `Rational` クラスがあるので、それを使います。
整数部分は `Rational#floor` を使い、小数部分は元の数から整数部分を引けば求まります。

```ruby 
x = Rational("1.6")

a = x.floor
b = x - a

p "a = #{a}, b = #{b}" #=> a = 1, b = 3/5
```

$1.6$ を $1 + \frac{3}{5}$ に変換できました。

## 2. 分母と分子を分子で割る

ステップ3では、 $1 + \frac{1}{t}$ の $t$ の部分が必要になります。

前のステップで `b` に小数部分が入っているので、 $b = \frac{1}{t}$ となり、これを変形すると $t = \frac{1}{b}$ になります。つまり、$\frac{1}{b}$ を求めればOKです。

Ruby では $\frac{1}{b}$ を `Rational(1, b)` と書けます。

```ruby
t = Rational(1, b)
p "t = #{t}" # => t = 5/3
```

これで $1 + \frac{3}{5}$ を $1 + \frac{1}{5/3}$ に変換できました。

## 3. 分母に対して 1 ~ 3 を繰り返す

あとは $t = 5/3$ に対して 1 ~ 3 を繰り返すだけです。
なのでループを回せば完成ですが、注意点として `b` が 0 になったら止める必要があります。

完成したプログラムはこちらです。

```ruby
def cf(x)
  tmp = x

  loop do
    a = tmp.floor # 整数部分
    b = tmp - a   # 小数部分

    if b == 0
      puts a
      break
    end

    print "#{a}, "
    tmp = Rational(1, b) # t = 1/b
  end
end
```

実行すると、$a_n$ が順番に出力されます。

```ruby
> cf(Rational("1.6"))
1, 1, 1, 2
```

1.6 は $1 + \frac{1}{1 + \frac{1}{1 + \frac{1}{2}}}$ なので、正しく動いていそうです。

（誤差などはあまり考慮していないので、入力によっては正しく計算されない可能性があります。）

# あとがき

連分数展開のプログラムを作ったきっかけは、とある謎解きの問題です。その問題の鍵の一つに連分数展開が必要だったので、作ってみました。

業務などでは連分数展開のプログラムが役に立つことは少ないと思いますが、競技プログラミングやCTFで活用できる場面もあるらしいので、その時はこの記事を思い出してみてください。
Sequence Makerで常に同じ設定でExcelを起動させる

## はじめに
Sequence MakerはExcelから測定器を制御可能にするアドインです。Sequence Maker用に作ったExcelのファイルは、複数人で共有して使用する場合もあると思います。しかし、それぞれのExcelのSequence Makerの設定が異なると、測定器と通信できなかったり、シーケンスを実行したときに思いもよらないような動作をしたり、最悪ワークシート上の変な場所にデータが書かれたりと大変なことが起こります。この記事ではSequence Makerを常に同じ設定でExcelを起動させる方法を解説します。Sequence Makerについての詳細は以下の記事を参照ください。

https://qiita.com/sequencemaker/items/8e6a370ab0a793a06a3b

:::note warn
***お断り***
本記事の内容はSequence Maker開発元の公式見解ではなく、あくまでも個人が趣味の範囲内で執筆しているものです。記事の内容について開発元へ問い合わせることはお控えください。ご質問・要望などは各記事のコメント欄へお願いいたします。
:::

## 同じ設定でExcelを起動させる方法
Sequence Makerでは設定をファイルに保存したり、読み込んだりする機能があります。その機能を使用して作成した設定ファイルを、Excelのブックと同じ場所に保存しておくと、Excel起動時に設定ファイルの内容が反映されます。
これは実は詳細設定オプション画面にも説明があります。
詳細設定画面はオプショングループの右下の矢印をクリックすると開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/59df7454-8368-6969-bd91-af4370cd6a62.png)

詳細設定の「設定の保存と読み込み」をご覧ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/106d3bee-4af1-a01d-58ad-5243faa0a090.png)

ここで「設定の保存」をクリックすると、現在のSequence Makerの設定が保存できます。
設定ファイルはデフォルトで「SequenceMakerDefault.xml」というXMLファイルで保存されます。
このXMLファイルをExcelのブックと同じ場所に置いておくだけです。これでExcel起動時に自動的に設定が反映されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/e5dc0f33-116e-324b-5b91-4911c586d1af.png)


## SequenceMakerDefault.xml
このファイルにはSequence Makerのいろいろな設定情報が保存されています。XMLなので、テキストエディタなどで書き換えることも可能です（自己責任ですが・・・）

```xml
<?xml version="1.0" encoding="utf-8"?>
<SequenceMakerParameter xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ControlParameter>
    <Timeout>5</Timeout>
    <Wait>0</Wait>
    <RepeatNum>1</RepeatNum>
  </ControlParameter>
  <OptionParameter>
    <SendCheck>false</SendCheck>
    <NotOverWriteMsg>true</NotOverWriteMsg>
    <NotEndMsg>true</NotEndMsg>
    <TimeLog>false</TimeLog>
    <CommTimeLog>false</CommTimeLog>
    <OverWrite>false</OverWrite>
    <SeparateComma>false</SeparateComma>
    <ExponentFormat>###.0#########E+00</ExponentFormat>
    <LineAccessToken />
    <ContecDigitalIoDeviceName />
  </OptionParameter>
………この後、インターフェイスの設定などが続く
```

## まとめ
この記事の方法を使えば、例えばファイルサーバー上の共有フォルダーにExcelのブックとXMLファイルを置いておいて、複数人で共有することも可能です。設定を固定したい！という場合に便利な機能かと思います。
Reactのkeyに配列のindexを使うのはやめた方がいいだろう

## はじめに
「**Reactのkeyに配列のindexを使うのは避けるべきだ**」
Reactを書いたことのある方なら、なんとなく耳にしたことがあるのではないでしょうか。React公式ドキュメントにも落とし穴として書かれている内容です。

https://ja.react.dev/learn/rendering-lists#why-does-react-need-keys

私もなんとなく使用を避けてはいたのですが、先日「indexを使って書いても問題なさそうだな」と思い、あえて使ったことがありました。
レビューで指摘されて修正することになったのですが…先輩に自分の考えを伝えて意見交換した上で、やはり「Reactのkeyに配列のindexを使うのはやめた方がいいだろう」と思ったので、記録しておこうと思います。

## 問題のコード
以下が、問題となるソースコードです。
ここで`errorMessages`はAPIリクエスト後に返されるstringの配列です。

```typescript
{errorMessages.map((message, index) => (
    <ValidationErrorText key={index} text={message} />
))}
```
レビューで先輩にコメントいただきました。

>配列をループしてリストのようにJSXをレンダーするとき、keyにはindexを使用しない方がいいですよ。
今回であれば、messageがユニークになっているはずなので、messageをkeyに入れるのがいいと思います。

私：「（先輩、わかっているんだけども…いやでも、今回は大丈夫じゃない？）」

先輩に自分の考えを伝えてみることにしました。

## 先輩とディスカッション
私：「仕様上、`errorMessages`はAPIリクエストによって描画されます。一度描画されると、配列の順番が変更されたり削除されることはないです。」

私：「重複することはないとしても、stringの`message`をkeyにするのはなんか気持ち悪い気がするから、`index`でも良さそう〜と考えて実装しました」

先輩：「確かに、今の仕様上なら問題は起こらないかもしれない。ただし、初めてこのソースコード読む人からすると、その背景はちょっと考えないとわからないよね。読み手に負荷がかかってしまう」

先輩：「それに、将来は仕様が変わって`message`を消せるようになったりするかもしれない。その場合、今回の実装ではバグが生まれてしまう可能性がある」

先輩：「それなら、やらない方がいいと思うんだけどどうかな？」

私：「た、確かに…」

## 修正
`key`に`message`を入れるよう修正しました。
```typescript
{errorMessages.map((message) => (
    <ValidationErrorText key={message} text={message} />
))}
```
- ①読み手に負荷がかかってしまうこと
- ②将来バグが発生するリスクがあること

ここまで考慮できていませんでした。仕様上は問題ないとしても、「Reactのkeyに配列のindexを使うのはやめた方がいいだろうと思いました。

## 終わりに
少し調べてみると、こちらの記事にkeyをindexに仕様しても問題ない場合が書かれていました。

https://robinpokorny.medium.com/index-as-a-key-is-an-anti-pattern-e0349aece318

:::note info
**keyをindexに仕様しても問題ない場合**
1. 配列と要素が静的である - 計算も変更もされない
2. 配列内の要素にIDがない
3. 配列が決して並べ替えられたりフィルタリングされたりしない

これらすべての条件が満たされている場合、indexをkeyとして使用しても問題ない
:::

今回に当てはめてみると、そもそも条件1を満たしていないですね😇
APIリクエストの結果で`errorMessages`が変わってしまうので、静的とは言えないです。


読み手に優しいコードを書く、将来バグを生むリスクを下げる。
2つの観点からも、たとえ今は問題がないとしてもReactのkeyに配列のindexを使うのはやめた方がいいだろうと思いました。
Python業務歴1年目から5年目でコードはこう変わった

# Before
``` Python
class DBClient:
    PATH = 'hoge/fuga'

    @classmethod
    def insert(cls, recs):
        for rec in recs:
            # ここでは仮でprintするだけとする
            print(f"PATH: {cls.PATH}, name: {rec['name']}, age: {rec['age']}")


records = [
    {"name": "Taro", "age": 20},
    {"name": "Jiro", "age": 18},
    {"name": "Saburo", "age": 12}
]

DBClient.insert(records)
```
# After
``` Python
import dataclasses
from typing import Final


@dataclasses.dataclass
class Record:
    name: str
    age: int


class DBClient:
    PATH: Final[str] = "hoge/fuga"

    # DBにレコードを挿入する
    def insert(self, records: list[Record]) -> None:
        for record in records:
            # ここでは仮でprintするだけとする
            print(f"PATH: {self.PATH}, name: {record.name}, age: {str(record.age)}")


raw_records = [
    {"name": "Taro", "age": 20},
    {"name": "Jiro", "age": 18},
    {"name": "Saburo", "age": 12},
]
# レコードをインスタンスの配列に変換
records = [Record(record["name"], record["age"]) for record in raw_records]

dbClient = DBClient()
# DBにレコードを挿入
dbClient.insert(records)
```
# 解説
### ポイント1. dictを乱用しない(今回一番伝えたいこと！)
- **「辞書(dict)型」の変数を関数の引数にしたり、長い行数(100行とか)の間ずっと使っていたりする**と、「このdictって何が入っているんだっけ？」となり、**可読性が下がったり、バグの原因になったりします**
    - 上記の例のBeforeの`insert`関数では本来、`rec`対し`name`と`age`があるかのキー存在チェックが必要となります
- **そこで、専用のクラスを用意して、辞書型の変数をインスタンスに変換することを強くお勧めします**
    - 上記の例ではAfterの`Record`クラス
- そうすることで、「何の項目があるか」「各項目の型は何か」を明示することができます
- その際、Pythonに元々備わっている 「**dataclass**」を使うと、__init__関数を省略できるためオススメです
    - 参考: https://qiita.com/ttyszk/items/01934dc42cbd4f6665d2
- dictは非常に便利ですが、自由過ぎるが故、中身が不透明になりやすいので、注意して使ってください
### ポイント2. 型定義を書く
- Pythonは型定義を書かなくても動く言語ですが、メリットが多いので書くことを推奨します
    - **特に関数の引数に対して**
- 可読性の向上に加え、(自分はVSCodeを使っていますが、)エディターでの補完が強力になりますので、ぜひ実感してみてください
    - 上記のポイント1とも相性バツグンです
- ちなみに、`path: str = 'hoge/fuga'`といった、型定義と初期値の設定を同時に行う書き方もできます
    - `records: list[Record] = []`のように初期値が空配列のときによく使います
### ポイント3. クォートを統一する
- ダブルクォートとシングルクォートのどちらを主に使うか、プロジェクトで統一するといいでしょう
    - 私のプロジェクトではダブルクォートを主に使うようにして、「f-string」の中など必要な部分だけシングルクォートを使うようにしていますが、プロジェクトで統一できればどちらでもいいと思います
### ポイント4. 安易に`classmethod`を使わない
- `@classmethod`や`@staticmethod`はきちんと用途を調べ、適切な箇所で使いましょう
- 少なくとも、過去の私のように「インスタンスを生成しなくていいから行数が一行減るやん！」といった理由で使わないようにしましょう
### ポイント5. 無闇に略称を使わない
- `rec`だと`record`なのか`reccomend`なのか`recipe`なのかわかりません
- 略さなくても支障がない場合は略さない方がいいと思います
- ただし、ユビキタス言語などで略称がプロジェクト全体で定義・浸透していれば使っても問題ありません
### ポイント6. コメントをきちんと書く
- コメントは少なすぎるよりは多すぎる方がいいと私は考えています
- 例では使っていませんが、「docstring」を使うとより良いでしょう
    - 参考: https://qiita.com/flcn-x/items/393c6f1f1e1e5abec906
### ポイント7. 配列の最後にカンマを置く
- 配列などを複数行で記述している場合、最後の要素の後にカンマを置くと、要素を追加したときgitの変更点が見やすくなる、などのメリットがあります
    - 上記の例だと`{"name": "Saburo", "age": 12}`の後ですね
- Python公式ドキュメントでも触れられています
    - https://docs.python.org/ja/3/faq/design.html#why-does-python-allow-commas-at-the-end-of-lists-and-tuples
# あとがき
- Pythonについて学んだことはまだまだ色々ありますが、要点を絞ってコンパクトにまとめることができたのではと思います
- BeforeとAfterを書いてみて、コード量がかなり増えていることに自分で驚きました。コードが短ければ可読性が高いってわけではないですね(当たり前か)
- 本記事とはあまり関係ないかもですが、オブジェクト指向について、「[現場で役立つシステム設計の原則 ~変更を楽で安全にするオブジェクト指向の実践技法](https://www.amazon.co.jp/dp/477419087X
)」という書籍が実践的でわかりやすく、ためになったので、宣伝(ダイマ)させていただきます
Apexで指定バイト数まで文字列を切り詰め

```apex
  // 指定バイト数まで文字列切り詰め
  private static String truncateToByteLength(String s, Integer byteLength) {
    if (s == null) {
      return null;
    }
    while (Blob.valueOf(s).size() > byteLength) {
      s = s.substring(0, s.length() - 1);
    }
    return s;
  }
```
javascript勉強　クラス

お疲れ様です。

昨日まで編集していた自己紹介ページは、背景画像をjsやjQueryを用いて動きをつけられるようになるまでは一旦置いておき、jsの復習をします。

![スクリーンショット 2024-07-03 000437.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/b97a7168-9615-668b-0f67-03e7027c2f80.png)
![スクリーンショット 2024-07-03 000528.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/272b8d49-9f17-58bf-f3ae-011684875dcb.png)

![スクリーンショット 2024-07-03 000552.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/dfb83272-e003-6560-e709-80b7aa161942.png)

今日はクラスについての復習です。
これを初めて勉強したのも半年近く前だったような気がしますが、やはりコードを書いたりしないと忘れるものですので、定期的に復習はしていきたいものです:slight_smile:

明日はDOM操作の基本から再開し、また課題に挑戦していきます。
Python初心者がWebスクレイピングをやってみた【初心者】

### 初心者がスクレイピングやってみた

### 記事概要
Webスクレイピングは、インターネット上のデータを自動的に収集する技術です。
Pythonはそのための強力なツールを提供していますが、初学者にとっては幾つかの難所があります。
この記事では、初心者の私が実際にWebスクレイピングを実装する過程で遭遇した問題点とその解決方法を紹介します。

### 前準備
必要なライブラリのインストール
まず、Webスクレイピングに必要なライブラリをインストールしましょう。一般的にはrequestsとBeautifulSoupを使用します。

~~~:bash
pip install requests beautifulsoup4
~~~

::: note warm
注意点
ライブラリをインストールする際にpipが認識されない場合は、Pythonが正しくインストールされているか確認してください。
:::

### 基本的なスクレイピングの流れ
基本的なスクレイピングの流れは以下の通りです。

1. Webページの内容を取得する
2. HTMLを解析する
3. 必要なデータを抽出する

以下は基本的な実装したコードです。
~~~:Python
import requests 
from bs4 import BeautifulSoup

# 取得したいウェブページのURL　今回はブルームバーグを利用しました
url = "https://www.bloomberg.co.jp/"

# ウェブページの内容を取得
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')

# ヘッドラインとURLを抽出
headlines = []
for item in soup.find_all('h2', class_='headline'):
    headline_text = item.get_text()
    headline_url = item.find('a')['href']
    headlines.append({'headline': headline_text, 'url': headline_url})

~~~

上記の処理で、headlinesの中に以下のようなデータが取得できました

~~~
[{'headline': '\nバイデン氏の正式候補、米民主党が認定前倒しを検討－大統領選挙\n', 'url': '/news/articles/2024-07-01/SFYLKIT1UM0W00?srnd=cojp-v2', 'time': '2024-07-02 23:49:26'}, {'headline': '\n円は161円台半ば、米長期金利上昇で38年ぶり安値更新－介入警戒強い\n', 'url': '/news/articles/2024-07-01/SFXND9DWRGG000?srnd=cojp-v2', 'time': '2024-07-02 23:49:26'}, {'headline': '\nトランプ氏返り咲きにらむウォール街、米債券市場の展開を予測\n', 'url': '/news/articles/2024-07-01/SFYKMKDWRGG000?srnd=cojp-v2', 'time': '2024-07-02 23:49:26'}, {'headline': '\nエヌビディア、反トラスト関連で仏当局が告発を準備－ロイター報道\n', 'url': '/news/articles/2024-07-01/SFYNM1T0G1KX00?srnd=cojp-v2', 'time': '2024-07-02 23:49:26'}, {'headline': '\nＥＣＢ総裁、「確信には時間がかかる」－インフレに不透明性残る\n', 'url': '/news/articles/2024-07-01/SFYBQNDWX2PS00?srnd=cojp-v2', 'time': '2024-07-02 23:49:26'}, {'headline': '\nマクロン氏と左派連合、ルペン氏の極右封じ込めに奔走\n', 'url': '/news/articles/2024-07-01/SFXOWXT0AFB400?srnd=cojp-v2', 'time': '2024-07-02 23:49:26'}, {'headline': '\n日本株は小反落へ、米製造業の景況感悪化が重し－輸出一角や素材安い\n', 'url': '/news/articles/2024-07-01/SFYR2ST1UM0W00?srnd=cojp-v2', 'time': '2024-07-02 23:49:26'}, {'headline': '\nＮＹ連銀総裁、ＦＲＢがインフレ率２％達成への道を進んでいると確信\n', 'url': '/news/articles/2024-07-01/SFY7UZT0G1KW00?srnd=cojp-v2', 'time': '2024-07-02 23:49:26'}, {'headline': '\n債券下落か、円安進行で日銀政策変更を警戒－10年入札無難観測は支え\n', 'url': '/news/articles/2024-07-01/SFQ8MOT0AFB400?srnd=cojp-v2', 'time': '2024-07-02 23:49:26'}, {'headline': '\nロビンフッド、プルートを買収－ＡＩ主導の投資アドバイスを提供へ\n', 'url': '/news/articles/2024-07-01/SFY495T1UM0W00?srnd=cojp-v2', 'time': '2024-07-02 23:49:26'}]
~~~

見出し、url、取得してきた日時が格納されています
pythonでopenCVを使おうとしたらimportエラーが起きた

# はじめに

WSL2+poetry+python環境で開発を行っています。
昨日までは問題なく実行できていたプログラムでしたが、今日は急にopenCVがエラーを起こしました。
なんで昨日までは動いていたんだよ...

最後の一文に原因が載っていました。
```
ImportError: libGL.so.1: cannot open shared object file: No such file or directory
```

libGLがないとのことです。

# やったこと

結構ありがちなエラーらしく、いろいろな記事で触れられていました。
人によってやり方が違うので、まとめて載せておきます。

私は以下のコマンドで解決できました。

```bash
sudo apt install libopencv-dev
```

libopencv-devを削除したうえで、以下のコマンドも試してみました。
こちらも解決できました。

```bash
sudo apt install libgl1-mesa-dev
```

以下は試していませんが、解決するらしいです。
```bash
sudo apt install libglib2.0-0 libsm6 libxrender1 libxext6
```

ほかにも異なる方法をとっている方を見つけました。
参考に載せておきます。

# 参考

https://github.com/ultralytics/ultralytics/issues/1270

https://stackoverflow.com/questions/55313610/importerror-libgl-so-1-cannot-open-shared-object-file-no-such-file-or-directo

https://predora005.hatenablog.com/entry/2021/08/05/190000
投稿 2 JavaScriptの変数

本日の勉強時間　2H

JavaScriptの変数は読んで理解できるもの、２文字とかよくない。
例
const textLength = (s.length);
const frameLengh = textLength + 2
const FRAME = “+”;　

固定値記号は大文字で表現するのもお作法。


エンジニアみたら、固定値。なにやっているかわかりやすいいよ！
[CentOS][Yum] Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=os&infra=vag error was 14: curl#6 - "Could not resolve host: mirrorlist.centos.org; Unknown error" solved 解決法


## 概要

使っていたCentOS にて
急に Yumが使えなくなった

```:bash
$ sudo yum update
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=os&infra=vag error was
14: curl#6 - "Could not resolve host: mirrorlist.centos.org; Unknown error"


 One of the configured repositories failed (Unknown),
 and yum doesn't have enough cached data to continue. At this point the only
 safe thing yum can do is fail. There are a few ways to work "fix" this:

     1. Contact the upstream for the repository and get them to fix the problem.

     2. Reconfigure the baseurl/etc. for the repository, to point to a working
        upstream. This is most often useful if you are using a newer
        distribution release than is supported by the repository (and the
        packages for the previous distribution release still work).

     3. Run the command with the repository temporarily disabled
            yum --disablerepo=<repoid> ...

     4. Disable the repository permanently, so yum won't use it by default. Yum
        will then just ignore the repository until you permanently enable it
        again or use --enablerepo for temporary usage:

            yum-config-manager --disable <repoid>
        or
            subscription-manager repos --disable=<repoid>

     5. Configure the failing repository to be skipped, if it is unavailable.
        Note that yum will try to contact the repo. when it runs most commands,
        so will have to try and fail each time (and thus. yum will be be much
        slower). If it is a very temporary problem though, this is often a nice
        compromise:

            yum-config-manager --save --setopt=<repoid>.skip_if_unavailable=true

Cannot find a valid baseurl for repo: base/7/x86_64

```

## 調査

原因を 普通に調べると

* インターネットにつながっていない
* `/etc/resolv.conf` が壊れている

が出るが、
どちらもそれ自体はよさそうだった

参考
https://serverfault.com/questions/904304/could-not-resolve-host-mirrorlist-centos-org-centos-7

## 原因

どうやら、
> Centos 7 は本日 2024 年 7 月 1 日に EOL に達したため、mirrorlist.centos.org は不要になりました。パッケージをインストールするには、リポジトリを「mirrorlist」から「baseurl」に調整する必要があります。ほとんどの場合、vault.centos.org は正常に機能します。

とのこと..


## 解決法

この問題を解決するには、すべての .repo ファイルを一括更新します。
```
$ sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo
$ sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo
$ sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo
```

->
```:bash
$ sudo yum update
..
Success.. OK

```


## 参考

https://serverfault.com/questions/1161816/mirrorlist-centos-org-no-longer-resolve
投稿 22 ラーニングゾーン 2024/07/21

本日の勉強時間　1H

コンフォートゾーンから抜け出し、ラーニングゾーンにいるのがおすすめ。

・ストレスレベル　中
・プレッシャー　適度
・挑戦と達成感のバランスをとる


1番成長できる具合なので意識する。
パニックゾーンにならないのも大事。
パニックゾーンは成長には至らないのも理解する。
【Next.js】Imageの最適化を無効化する


## 個別に無効化する

特定のImageコンポーネントのみ画像最適化を無効化するには`unoptimized`propsを`true`にします。

```jsx
import Image from 'next/image'
 
const UnoptimizedImage = (props) => {
  return <Image {...props} unoptimized />
}

```

## 全て無効化する

全てのImageコンポーネントで画像最適化を無効にするには`next.config.js`に以下のように記述します。

```js:next.config.js
module.exports = {
  images: {
    unoptimized: true,
  },
}

```

https://nextjs.org/docs/app/api-reference/components/image#unoptimized
【副業】LP制作で収入を得るまで_2日目

２日目は、Udemyの教材を購入して本格的に「STUDIO」の学習に取り掛かります。
購入した教材はこちらです
[①ノーコードで超速WEB制作　STUDIO学習完全パック（初級編・中級編・上級編）](https://www.udemy.com/course/studio-complete-pack)

## 用語解説
・ダッシュボード：様々な設定を行う場所
・エディタ：ページの編集画面
・アーカイブ：実質削除、STUDIOはプロジェクトを完全に削除できない

## エディタの理解
「バー」「パネル」「キャンバス」に分けて構成される

「バー」：最上部,レスポンシブバーなどが存在

「キャンバス」：画面中央

「パネル」：画面左
画像や動画の埋め込み
テンプレート素材の利用

画面右下の「？」
ショートカットやヘルプ記事など

## ボックスレイアウト手法について
ボックスレイアウト手法とは、
キャンバス内の全ての要素が「ボックス」として成立していること。
→上下で配置、左右で配置、親と子で配置など

メリットが「レスポンシブ」対応が簡単になる
→反面、デザインが少し難しく感じるので慣れるのに時間がかかる

要素の配列的考え方
親要素の中に、子要素を配置する
子要素の配置を変えたいときは「親要素」を選択して移動させる

## パディングとマージンの違い
パディング：ボックスの「中」にスペースを入れたいときに設定する値
マージン：ボックスの「外」にスペースを入れたいときに設定する値
→ボックスをドラッグするか、画面上のバーで値を変更できる

### マイナスマージン
2つの要素を重ねたいときに使用する
上のバーからしか設定できない

## ボックス幅の設定の違い(px,%,auto)
px(ピクセル)：横幅をピクセル値で設定
%：「親要素」の幅を基準として、そこから何パーセントの幅に決めたもの
auto：「子要素」の幅に合わせて親が調整される
→この３つはレスポンシブ対応したときに違いが生じる

親のボックスの幅を変えると
pxは全く変化しない
%は親要素に従って大きさが増減する

autoはボタンの文字を変えるときなどに便利

## ボックス幅の設定(flex)
2つの要素を並べると指定できる
要素A以外の幅を要素Bが埋めつくすような設定

応用として、
Aを3flex、Bを1flexで指定すると、
画面幅を3:1のように分けて使用できる
→ギャラリー画像などはflexが便利

## ボックス幅の設定(vh)
vh：view heightの訳
画面の高さに応じて要素の高さを変えたいときに使用する
※１番多い使用例は、画面幅いっぱいに画像を配置したいとき

## まとめ
画面の幅の設定はいろいろなパターンがあるので、
用途によって使い方を覚えていきたい。

記事作成時間：2h
Ruby 特異メソッドについて

# はじめに


#### <font color="red">※以下の内容には誤りが含まれる可能性があります</font>



# 特異メソッドとは何か



Rubyにおける特異メソッドは、特定のオブジェクトだけが持つ独自のメソッドです。

要するに、そのメソッドは定義したオブジェクトに対してのみ使用可能で、他のオブジェクトでは使用できないということです。

# 特異メソッドの書き方


```
str = "hello"
def str.greet
  puts"Hello,world!"
end

str.greet #=> Hello,world!
```
ここで"greet"メソッドは"str"オブジェクトに対してのみ定義されているので他の文字列オブジェクトではこのメソッドは使用できません。



# まとめ

Rubyの特異メソッドは強力なツール。

ですが使用には慎重になるべきです。

特異メソッドは定義したオブジェクトに対してのみ存在し、他の同じクラスのオブジェクトには影響を与えない。

つまり、同じクラスの異なるオブジェクトに対して同じ動作を
期待する場合、それぞれのオブジェクトに対して特異メソッドを定義する必要があります。

こうなると、コードの量が増え、保守性が下がる可能性があるため注意が必要です。
Django Rest Framework VS Code おすすめ拡張機能

# 概要
本記事では、Django Rest Frameworkで開発を行う上で、おすすめの拡張機能を紹介する

# 拡張機能一覧

| 拡張機能名 | 作成者 |
| ---- | ---- |
| [Git History](https://marketplace.visualstudio.com/items?itemName=donjayamanne.githistory) | Don Jayamanne |
| [Django](https://marketplace.visualstudio.com/items?itemName=batisteo.vscode-django) | Baptiste Darthenay |
| [Django Template](https://marketplace.visualstudio.com/items?itemName=bibhasdn.django-html) | bibhasdn |
| [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python) | Microsoft |
| [Python Debugger](https://marketplace.visualstudio.com/items?itemName=ms-python.debugpy) | Microsoft |
| [Python Environment Manager](https://marketplace.visualstudio.com/items?itemName=donjayamanne.python-environment-manager) | Don Jayamanne |
|[Python Extension Pack](https://marketplace.visualstudio.com/items?itemName=donjayamanne.python-extension-pack)|Don Jayamanne|
| [Python Indent](https://marketplace.visualstudio.com/items?itemName=KevinRose.vsc-python-indent) | Kevin Rose |
| [Pylance](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance) | Microsoft |
C# : itext7でpdfを作成するときのエラー

# unknown pdf exception

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/cea6c7f2-af3b-d6ee-b67a-7634309ce046.png)

itext7.bouncy-dastle-adapterをインストールする。

https://stackoverflow.com/questions/76260218/how-do-i-resolve-unknown-pdfexception-when-using-itext7-in-net-maui

# 余白なし・縦横自動判定

```C#
iText.Layout.Document document = new iText.Layout.Document(pdf);
document.SetMargins(0, 0, 0, 0); // 上、右、下、左のマージンを0に設定
```

# サイズ自動調整
機能なし、ページサイズ入力は可能

# I/O exception
以下実行時に発生したエラー

```C#
ImageData imageData = ImageDataFactory.Create(imagePath);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/7d6c6f8f-54d2-b825-32fd-6a33c77772bb.png)

発生原因：pathが間違っていた。普通にミス・・・


情報がなさすぎて、ChatGPTの出力を検証して並べるみたいになっちゃいました。
便利だけど、著作権大丈夫かな
macでのpyenvインストール

# 概要
本記事では、macでのPyenvインストールから、Pythonのインストールまで行う

## pyenvのインストール
```
~ % brew install pyenv
==> Downloading https://ghcr.io/v2/homebrew/core/pyenv/manifests/2.4.8
######################################################################### 100.0%
==> Fetching pyenv
==> Downloading https://ghcr.io/v2/homebrew/core/pyenv/blobs/sha256:45459a58894d
######################################################################### 100.0%
==> Pouring pyenv--2.4.8.arm64_sonoma.bottle.tar.gz
🍺  /opt/homebrew/Cellar/pyenv/2.4.8: 1,215 files, 3.5MB
==> Running `brew cleanup pyenv`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
```


## 使用しているシェルの確認
```
~ % echo $SHELL
/bin/zsh
```

## パスを通す

```.zshrc
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
```

## インストール可能なpythonのバージョン確認
```
~ % pyenv install -list
Available versions:
  2.1.3
  ...バージョン一覧...
  3.12.3
  3.12.4
  ...バージョン一覧...  
```

## pythonのインストール
```
~ % pyenv install 3.12.3
python-build: use openssl@3 from homebrew
python-build: use readline from homebrew
Downloading Python-3.12.3.tar.xz...
-> https://www.python.org/ftp/python/3.12.3/Python-3.12.3.tar.xz
Installing Python-3.12.3...
python-build: use readline from homebrew
python-build: use zlib from xcode sdk
Installed Python-3.12.3 to /path/to/.pyenv/versions/3.12.3
```

## pyenvバージョン確認
```
~ % pyenv --version
pyenv 2.4.8
```

## pyenvをリフレッシュする
```
pyenv rehash
```