OmniAICreator/Qiita-1.07M huggingface dataset:
超現実数 第３章 証明 0,-1,1の大小関係

Knuth博士が書いた超現実数についての「[Surreal Numbers](https://amzn.to/42mSt57)」の本の第3章証明について書く。

[前回のブログ](https://qiita.com/Trubetzkoy/items/28eb54613afe61712643)で超現実数の$0,-1,1$を定義した。これらが現実数であることは証明できたが、お互いは同じものなのか、それとも違うものなのか、大小関係はどうなっているのだろうか？

$$0=(\phi,\phi),\quad -1=(\phi,\\{0\\}),\quad 1=(\\{0\\},\phi)$$

#### 1. 0≦0の証明

$$x\leq y　の意味は　X_L\ngeq y　かつ\ x\ngeq Y_R\qquad(2)$$

上記のルール$(2)$に$0=(\phi,\phi)$を当てはめると、右辺は、
$$\phi\ngeq0　かつ　0\ngeq\phi$$

空集合には要素がないので、どんな空集合の要素も$0$より大きく、あるいは等しくなることはない、しかも、$0$はどんな空集合の要素よりも大きかったり、等しくなることはない。つまり、$0\leq 0$が証明された。
とりあえずは$$0\leq 0\qquad\tt(i)$$

#### 2. 0≦1は自明そうには見えるが確認しよう
$0$も$1$も通常の自然数ではなく、超現実数として定義したものなので、改めてルール$(2)$に基づいて証明する必要があると思う。
$0\leq 1\Leftrightarrow(\phi,\phi)\leq(\\{0\\},\phi)
\Leftrightarrow\phi\ngeq1かつ0\ngeq\phi
\Leftrightarrow\tt TかつT
\Leftrightarrow\tt T$つまり、
$$0\leq 1\qquad\tt(ii)$$

同じく、$-1\leq 0$も示したい。
$-1\leq 0\Leftrightarrow(\phi,\\{0\\})\leq(\phi,\phi)
\Leftrightarrow\phi\ngeq 0かつ-1\ngeq\phi
\Leftrightarrow\tt TかつT
\Leftrightarrow\tt T$
つまり
$$-1\leq 0\qquad\tt(iii)$$

#### 3. 0≦-1が偽であることを示したい
$0\leq-1$は$(\phi,\phi)\leq(\phi,\\{0\\})$となるので、
$x=0 かつY_R=\\{0\\}$なので、ルール$(2)$右辺の$x\geq Y_R$は、$0\geq\\{0\\}\Rightarrow\tt T$。$x\ngeq Y_R\Rightarrow\tt F$
$0\leq-1\Rightarrow\tt F$従って、
$$0\nleq-1\qquad\tt (iv)$$が示された。
これは$0\neq -1$ということなので$\tt(iii)$は$$-1\lt 0\qquad\tt(iii/b)$$となる。

#### 4. 1≦0はどうなるのか
$0\nleq-1$が証明されたので、$-1と1$を入れ替えた形式の$1\leq 0$が気になる。
$1\leq 0\Rightarrow(\\{0\\},\phi)\leq(\phi,\phi)$となり、
ルール$(2)$で$y=0かつX_L=\\{0\\}$なので、$y\geq X_L$は$0\geq\\{0\\}=\tt T$。つまり、$y\ngeq X_L\Rightarrow\tt F$より、$1\leq 0\Rightarrow\tt F$従って、
$$1\nleq 0\qquad\tt(v)$$が示された。
これは$1\neq 0$ということなので$\tt(ii)$は$$0\lt 1\qquad\tt(ii/b)$$となる。

#### 5.1 -1≦1を示したい
$-1\leq 1\Leftrightarrow(\phi,\\{0\\})\leq(\\{0\\},\phi)$はルール$(2)$より
$\phi\ngeq-1かつ-1\ngeq\phi\Rightarrow\tt TかつT\Rightarrow\tt T$なので
$$-1\leq 1\qquad\tt(vi)$$が示された。

#### 5.2 逆の場合の1≦-1はどうなる？
$1\leq-1\Leftrightarrow(\\{0\\},\phi)\leq(\phi,\\{0\\})
\Leftrightarrow \\{0\\}\ngeq-1かつ1\ngeq\\{0\\}$
上記の結果から$0\leq -1$と$1\leq 0$が成り立っているので、全体が$\tt F$となるので、$$1\nleq -1\qquad\tt(vii)$$

これは、$1\neq -1$と意味するので、$$-1\lt 1\qquad\tt(vi/b)$$となる。

0,-1,1の大小関係は以下の通り：
![surreal_0_1_-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734194/fcbf3c05-3bb3-c0b1-3f2a-8d98263de2be.jpeg)
WEBエンジニアの基礎知識を本で学ぶ（前半）

## 背景
エンジニアとしてWEBの網羅的な情報が知りたいと思い、プロになるためのWEB技術入門を読んでみました。
（気になった点だけ列挙してます。）

## 目的
基礎知識を再確認し基礎固めをすること

## 内容

### Q1. wwwの由来はHTML？
HTML内のハイパーリンク。ハイパーリンクで文章の参照をするようになり、ハイパーリンク通しが蜘蛛の巣に繋がるようになっていることからWorldWideWeb（世界に広がる蜘蛛の巣）と命名された。

### Q2. そもそもなぜクライアント、サーバの仕組みが必要なの？
wwwで参照されるコンテンツは1箇所にまとまっているべき（点在していると情報がバラバラになる）であるが、コンテンツの利用者がそのWebサーバを直接操作してコンテンツを閲覧するのは非現実的。そこで、利用者はクライアント、コンテンツ配信元をサーバとして、やり取りできる現在のような不特定多数の人がコンテンツにアクセスできる仕組みが出来上がった。

### Q3. URLのスキーム（プロトコル）の後ろはなぜホスト名というか？
他のコンピュータから要求を受け取り、処理した結果を返すコンピュータのことを、ホストコンピュータというため。

### Q4.プライベートアドレスの192.168.0.0って？
事前に定められたある一定範囲のIPアドレスを、プライベートネットワークで自由に利用できることになっている。範囲としては3つあり、ネットワーク内の台数によってクラスA〜クラスCまであるが、クラスCで十分なことが多いため（65536個接続可能）クラスCの192.168.0.0 ~ がよく使われている。

### Q5.DNSサーバって具体的にどうなってるの？
ルートサーバー→トップレベルドメイン（.jpなど）のように、ルートサーバから順番に下位のサーバーに問い合わせることで参照している。

### Q6.ポート番号はなぜ必要？
TCP/IPでは、情報のやり取りの責任は負うが、その情報のプロトコルやアプリケーションはわからないから。ポート番号があれば、ポート番号をlistenしているアプリケーションに、情報を任せることができる。

### Q7.なぜURLだと日本語は表示できないか？
URLで利用できる文字には制限があるから。アルファベット数字記号のみ。
そのため、日本語はUTF8で16進数の英数字にしてパーセントを1文字ずつけてURLにしている。

### Q8.リダイレクトってレスポンス内ではどのように記載されているの？
レスポンスラインに 302 Found、Locationヘッダに移動先が書いてある。
クライアントは上記を受け取ったのち、Locationヘッダにリクエストするためリダイレクトできる。

## 学び
ぼんやりわかっていたことが、よりクリアにわかるようになった。
基礎知識は調査時、実装時、障害時、全てに活きるため、コツコツ続けなければ、、、と思った。

## 次のアクション
後半を読み進めてまとめたい。
Insertion Sort of Single LinkedList 

**挿入ソートアルゴリズムの手順:**

1. **初期状態:** リストの最初の要素のみを含む部分的にソートされたリストを用意します。
2. **反復処理:** 未ソートの入力データから1つの要素を取り出し、ソート済みリスト内の適切な位置に挿入します。
3. **終了条件:** 未ソートの入力要素がなくなるまでこのプロセスを繰り返します。

**単一リンクリストにおける挿入ソートの実装:**

単一リンクリストで挿入ソートを実装するには、以下の手順を踏みます:

1. **ダミーノードの作成:** ソート済みリストの開始を示すダミーノードを作成します。
2. **現在のノードの探索:** 元のリストの各ノードを順に処理します。
3. **挿入位置の探索:** ソート済みリスト内で現在のノードの値を挿入する適切な位置を見つけます。
4. **ノードの挿入:** 現在のノードをソート済みリストの適切な位置に挿入します。
5. **次のノードへの移動:** 元のリストの次のノードに移動し、プロセスを繰り返します。

**Example**

```java
class Solution {
    public ListNode insertionSortList(ListNode head) {
        ListNode curNode = head;
        if (curNode.next == null) return head;

        while (curNode != null) {
            ListNode nextNode = curNode.next;
            int curr = curNode.val;
            while (nextNode != null) {
                if (curr > nextNode.val) {
                    int tmp = curr;
                    curNode.val = nextNode.val;
                    curr = curNode.val;
                    nextNode.val = tmp;
                }
                nextNode = nextNode.next;
            }
            curNode = curNode.next;
        }

        return head;
    }
}
```

**コードの説明:**

- **初期設定:** `curNode`をリストの先頭ノード`head`に設定します。
- **リストの走査:** `curNode`が`null`でない限り、以下の処理を繰り返します:
  - **次のノードの設定:** `nextNode`を`curNode`の次のノードに設定します。
  - **現在の値の保存:** `curr`に`curNode`の値を保存します。
  - **内部ループ:** `nextNode`が`null`でない限り、以下の処理を繰り返します:
    - **値の比較と交換:** `curr`が`nextNode`の値より大きい場合、値を交換します。
    - **次のノードへの移動:** `nextNode`をその次のノードに更新します。
  - **`curNode`の更新:** `curNode`をその次のノードに更新します。
- **ソート済みリストの返却:** `head`を返します。
Graph PowerShellでSharePointリストの参照列に値を登録する

# やりたいこと
タイトル通りです。前回の記事ではPnP PowerShellでしたが、今回の記事はGraph PowerShell版の備忘録として記事に残します。

# 事前準備
ClientリストとProductリストを用意しておきます。Productリストの「RefClientName」列を参照列として、Clientリストの「ClientName」列でリレーションシップを設定しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/afd57a74-2528-bdc7-a6b7-c698a18374bd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/8aa4098a-84a3-7f54-0f10-71f68b487055.png)

# PowerShellの実行コマンド
結論、実行コマンドは以下です。
「LookupId」を参照列名に付与することが動作の鍵となります。
```powershell
Connect-MgGraph -Scopes "User.Read.All", "Group.ReadWrite.All", "Sites.ReadWrite.All"

$clientName = "テスト株式会社"
$productName = "テスト製品"
$clientListName = "Client"
$productListName = "Product"
$siteName = "{サイト名}"

$siteId = Get-MgSite -Search "$siteName"
$productListId = Get-MgSiteList -SiteId $siteId.Id -Filter "DisplayName eq '$clientListName'"
$clientListId = Get-MgSiteList -SiteId $siteId.Id -Filter "DisplayName eq '$productListName'"

$clientListItem = Get-MgSiteListItem -SiteId $siteId.Id -ListId $clientListId -Filter　"fields/ClientName eq '$clientName'"
$params = @{
    fields = @{
        ProductName          = $productName
        RefClientNameLookupId = $clientListItem.Id
    }
}

New-MgSiteListItem -SiteId $siteId.Id -ListId $productListId -BodyParameter $params
```
chatGPTテーマ入力から一発でフローチャートを作成する方法

## この記事のポイント
- chatGPT→フローチャートへの２ステップ手順（ただしchatGPT無料ユーザーはGPTsの利用制限があるので注意）

## フローチャート作成の２ステップ
### １・GPTsアプリストアで「mermaidchart.com」を選択する
![タイトルなし5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980972/9cf7e311-ac4f-5295-cdf4-840a22a65b13.png)


### ２・作成したいフロー図をチャット欄に入力し送信する
(例)１
```
交通系ICカードの仕組みをフローチャートにしてください。
```
(例)２・事前にChatGPTで文章からMermaidコードを作成した場合
```
以下のMermaidコードからフローチャートを作成してください
graph TD
    A[ユーザーがChatGPTに質問する] --> B[ChatGPTが回答を生成]
    B --> C[回答がユーザーに表示される]
    B --> D[GPTsを使用して追加タスクを実行]
    D --> E[タスクの結果をChatGPTに返す]
    E --> C
    C --> F[ユーザーが次の質問を送信]
```
## ３・ChatGPTでの作成結果がこちら
![タイトルなし3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980972/12c5b127-5c13-502a-8b76-8d4873c7e5e6.png)
##### MermaidChartエディターで編集をクリックしてみると。。。
![スクリーンショット 2025-01-24 220220.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980972/92245562-4543-49cf-f111-056d95a05366.png)




### ※Mermaid Chartについて

**Mermaid Chart**は、テキストベースでダイアグラムを簡単に作成できるツールです。Markdownスタイルを利用し、フローチャートやシーケンス図などをスムーズに作成可能です。リアルタイムでのコラボレーション機能も備えています。

#### 利用料金
- **無料プラン**  
  - 基本的なダイアグラム作成機能  
  - オープンソースのMermaid機能の利用可能  
  - 個人向けのシンプルな利用に最適  
  - 作成自体は何度でも可能ですが、保存できる数には最大5つのダイアグラムのみ保存可能（この制限を超えてダイアグラムを保存したい場合は、有料プランへのアップグレードが必要です）


- **有料プラン**（プロフェッショナル向け）  
  - チームでのコラボレーション機能  
  - ダイアグラムのセキュアな保存と管理  
  - 高度なカスタマイズと追加ツールの統合  
  - エンタープライズサポート  

**まとめ**  
無料プランでは基本機能が使えるため、個人利用や試しに最適です。有料プランを利用すると、チームでの共同作業やより充実した機能が利用可能になります。
[SwiftUI]ヒラギノ系のフォントを利用すると端末によって文字が見切れる不具合への対処法

## 1. 不具合内容
ヒラギノのフォントを利用した時、文字下部分が見切れてしまう。
この事象はiPhoneSEなどの比較的画面サイズが小さいものでやるとより顕著となります、、、

- 発生条件: iPhone 12　※実機
- 発生環境: iOS18(OSは関係ない)

![IMG_8942.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582590/0a32a5a3-9660-50d2-b57e-6c2f2983f097.jpeg)

## 2. 原因
フォントの問題。
(2025年でもまだ解決されないのか。。。ヒラギノでは英語表記するなってことなのかな、、、)

https://stackoverflow.com/questions/44374358/system-font-hiragino-sans-is-show-with-clipped-ascender-and-descenders

https://note.com/yotsukura/n/nbbcd7eb0a1dd


## 3. 解決策
この記事を参考にしました！
調べてみた感じ、SwiftUIではこの方しかこの件の解決策を書いてくれてなさそう、、、
足向けて寝れないですね🙃

[ヒラギノフォントが切れる問題 SwiftUI編](https://koze.hatenablog.jp/entry/2020/05/11/093000)


ちなみに、.system(font)を使えば、
文字サイズは少しちっちゃくなるけどこの問題は解決する。
(英語はSanFransisco、日本語はヒラギノになるっぽい。
今回は小さくしたくなかったので、こちらの方法は使ってません。)

https://spinners.work/posts/kudakurage-figma-ios-ja-system-font-size-plugin/
## 4. 無事解決！
![IMG_8941.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582590/d07e540b-e360-818c-5ccd-925240113053.jpeg)
本当にこの記事書いてくださってありがとうございます🥺という気持ちです。
備忘録として残しておきます。
[Swift]環境変数ENABLE_PREVIEWSがXcode16で機能しない

## 始めに
SwiftLintやSwiftFormatをビルドフェーズで実行している場合、Previewが更新されるたびにこれらが実行され、頻繁にクラッシュが発生してしまいました。そのため、以下の対応を試してみましたが、どうやら期待通りに機能していないようなので、解決策を調べてみました。環境変数の`ENABLE_PREVIEWS`はPreviewビルド時に`YES`が入るらしいです。

```swift
# Xcode Preview のビルド時はスクリプトを実行しない
if [ \"$ENABLE_PREVIEWS\" == \"YES\" ]; then
  exit 0
fi

# Formatter, Generator の実行
...
```

## 調査
Xcode16だとデバッグビルドとPreviewビルドの違いがなくなり、`ENABLE_PREVIEWS`は機能しなくなったみたいです。短期的な解決策として、以下が提示されていましたが、OpenAPIらへんでエラー出まくりだったのでLegacyPreviewsの使用はできなかったです。私の場合、ビルド時に生成して使用しているOpenAPIがPreviewで使えなくなっている感じでした。

```swift
Editor > Canvas > Use Legacy Previews Execution
```

Preview表示時の環境変数を見てみたましたが、期待した値は取ってこれないですね、、

```swift
ENABLE_PREVIEWS: NO
XCODE_RUNNING_FOR_PREVIEWS: // 空
```

面倒ですが、シミュレーターの場合、ビルド時は実行しないという方法で手を打つ、、？
実機ビルドをする必要があるので、解決策としてはよくない気がします。なので、Previewのクラッシュが目立つ場合、一時的に設定を消す、手動で行うなどの対応が必要かも？

```swift
if [ -z $CI ] || [ $CI = false ] && [ "$EFFECTIVE_PLATFORM_NAME" != "-iphonesimulator" ]; then
  xcrun --sdk macosx mint run swiftlint
else 
    echo 'warning: skip SwiftLint run script'
fi
```

## 終わりに
良い方法を知っている方がいらっしゃいましたら、ご教授願います🙇

## 参考

https://qiita.com/temoki/items/5fddc026b4817c6ce5ff

https://forums.developer.apple.com/forums/thread/761439

https://github.com/firebase/firebase-ios-sdk/issues/13603
Goのエラーハンドリング実践入門

こんにちは！フリーランスエンジニアのこたろうです。

サービス層の設計とデータベース操作について、実践で得た知見を共有します。

## カスタムエラー型の実装の必要性

Webアプリケーション開発では、DB接続エラーやバリデーションエラーなど様々なエラーに適切に対応する必要があります。Goでは`error`インターフェースを実装することで、独自のエラー型を定義できます。

```go
// エラーコードの定義
type ErrorCode string

const (
    ErrSystem   ErrorCode = "E001" // システムエラー
    ErrDB       ErrorCode = "E002" // DBエラー
    ErrInput    ErrorCode = "E100" // 入力エラー
    ErrNotFound ErrorCode = "E101" // 未検出エラー
)

// カスタムエラー型
type AppError struct {
    Code    ErrorCode
    Message string    // ユーザー向けメッセージ
    Detail  string    // 開発者向け詳細
    Err     error     // 元エラー
}

func (e *AppError) Error() string {
    return e.Message
}
```

## 実装例：ユーザー情報取得

```go
func (r *UserRepo) Find(id int) (*User, error) {
    var user User
    err := r.db.Get(&user, "SELECT * FROM users WHERE id = ?", id)
    
    if err != nil {
        if err == sql.ErrNoRows {
            return nil, &AppError{
                Code:    ErrNotFound,
                Message: "ユーザーが見つかりません",
                Detail:  fmt.Sprintf("ID %d not found", id),
                Err:     err,
            }
        }
        return nil, &AppError{
            Code:    ErrDB,
            Message: "データ取得に失敗しました",
            Detail:  fmt.Sprintf("Failed to get user: %d", id),
            Err:     err,
        }
    }
    return &user, nil
}
```

## エラーハンドリングの利点

1. エラーの種類を明確に区別
2. ユーザー/開発者向けの異なるメッセージ管理
3. 適切なHTTPステータスコード設定
4. ログ出力とモニタリングの容易化

参考文献:
-『Goで作るはじめてのWebアプリケーション改訂版』技術書典
- https://techbookfest.org/product/jXDAEU1dR53kbZkgtDm9zx
MySQLのタイムゾーン問題の話

# 概要
先日ちょっとした事件に出くわしたので備忘録として記載します。


お仕事でMySQLのライブラリバージョン「MySQL Connector/J 8.0」以上にした際、担当していたアプリが軒並み動かなくなる事象がありました。

その原因と修正の話

## 調査

調査を行っていたところログに「java.lang.IllegalArgumentException: HOUR_OF_DAY: 0 ->1」の見慣れない文字が・・・


調査の過程で下記ブログに行き当たりました。

https://getore.blogspot.com/2021/07/mysqljavalangillegalargumentexception.html

ブログにも記載がありますが、日本でも過去にサマータイムが導入されていた時期ある様子

|西暦|和暦|
|----|----|
|1948-05-02|昭和23-05-02|
|1949-04-03|昭和24-04-03|
|1950-05-07|昭和25-05-07|
|1951-05-06|昭和26-05-06|


つまり時刻を含まない形（年月日）だけ受け取れれば問題なしと思っていたのですが、使っていたJavaのライブラリがseasar2だったこともあり、さらに問題が・・・

https://github.com/seasarorg/seasar2/blob/db46d1f5891159eb5ef6aab3a40af7b0e0885377/seasar2/s2-extension/src/main/java/org/seasar/extension/jdbc/types/ValueTypes.java#L566


seasar2ではなぜかDATE型をTimestampに置き換えるようにしている様子・・・
```ValueTypes.java
        case Types.DATE:
            return Timestamp.class;
```

当然Timestampにしてたら上記のタイムゾーン問題に抵触する訳ですよ。


## 対応

上記のブログにあったようにタイムゾーンの設定やらなんやらしてみたけどうまくいかず。

困っていたのですが極力修正しないために（バグ生みたくないから・・・）
SQL側を文字列に、受け取り側をStringにする強行手段で解決することに成功


簡易的ではあるけど以下のように
```sql
--h.dateには2024-12-27が格納されている場合
select date_format(h.date, '%Y-%m-%d') from hoge h;
```
と実行するとレスポンスとして`2024-12-27`が文字列として返ってくる。

これをJava側でバインド(String型で)して受けとり、後続の処理で時間として使っているのであればcastするなりなんなりすればよいということ。


本来だったらタイムゾーンの設定とかで何とか出来たら影響は少なかったのかもしれないけど、その辺はうまくいかなかったので力業で解決しましたって話。

---

### あとがき

あとはseasar2の[BeanMap](https://github.com/seasarorg/seasar2/blob/master/s2-tiger/src/main/java/org/seasar/framework/beans/util/BeanMap.java)を使っていたのも問題の原因だったとも思う

https://github.com/seasarorg/seasar2/blob/master/s2-tiger/src/main/java/org/seasar/framework/beans/util/BeanMap.java


DBから受けっとったレスポンスを良しなに`Map<String,Object>`にしてくれる機能でseasar2側がTimestampに置き換えていなければDate型でうまくいったのかなとか・・・

思うことは沢山あるけど、この問題は力業でも対応できるって事を共有したかった感じでした。
ベストな方法ではないけど、最小にするならって感じ


とはいえSQL側でStringに変換するので結局BeanMapのままでもいいんだけど

今回は複合的な要因があってこの問題が一般的ではないとは思うけど、この先似たような事象に出くわした誰かのためになったらいいなと思います。

では！
nodebrewを用いてmacOSにnodeとnpmをインストールする

```
% brew install nodebrew
% nodebrew setup
% nodebrew -v
nodebrew 1.2.0
% echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.zshrc
% source ~/.zshrc
% nodebrew install stable
% nodebrew ls
v22.13.1

current: none
% nodebrew use v22.13.1
use v22.13.1
% node -v
v22.13.1
% npm -v
10.9.2
```

macOS Sonoma 14.6.1
#0024（2024/01/24）NATインスタンスとNATゲートウェイの違いは？

# NATインスタンスとNATゲートウェイの違い

AWS上でプライベートサブネット内のリソース（EC2など）がインターネットへ発信通信を行うためには、「NAT（Network Address Translation）」を使ってプライベートIPアドレスをパブリックIPアドレスに変換する仕組みが必要です。  
AWSでは大きく分けて「**NATインスタンス**」と「**NATゲートウェイ**」という2つの選択肢がありますが、それぞれ以下の点で異なります。

---

## 1. NATインスタンス

### 概要
- **EC2インスタンス**に対してカスタマイズしたAMI(例えばAmazon LinuxにNAT用の設定を加えたもの)などを使い、NAT機能を持たせる方法。
- インスタンスとして起動するため、**自分で管理**・運用が必要。

### 主な特徴
1. **管理・運用負荷が高い**  
   - OSのアップデートやセキュリティパッチ適用、可用性の確保(マルチAZ対応など)を自分で行う。  
   - インスタンスタイプやAuto Scalingの構成も手動で設定する必要がある。

2. **コスト**  
   - 通常のEC2料金(オンデマンド/RI/スポットなど)に加え、データ転送料がかかる。  
   - 小規模なら安く済む可能性もあるが、トラフィックが増えると単一インスタンスによるボトルネックが発生しやすくなる。

3. **柔軟性**  
   - OSレベルでパケットを制御できるため、NAT以外にもカスタムのプロキシや監視ツール等を組み込む余地がある。

---

## 2. NATゲートウェイ

### 概要
- AWSが提供する**フルマネージドなNATサービス**。  
- VPCのパブリックサブネット内に作成し、プライベートサブネットがインターネットにアクセスするときに使われる。

### 主な特徴
1. **管理の手間がほぼ不要**  
   - ソフトウェアやOSの更新、可用性確保はAWSが面倒を見てくれる。  
   - スケーリングも自動的に行われ、高負荷にも対応可能。

2. **高可用性**  
   - 同じAZ内では冗長化されており、障害が起きにくい。  
   - マルチAZ構成にするにはAZごとにNATゲートウェイを置き、ルーティングを設定する必要がある。

3. **コスト**  
   - **時間単位の料金**と**データ転送料金**が課金対象。  
   - NATインスタンスよりやや割高に感じることもあるが、運用コストや手間削減のメリットが大きい。

---

## 3. 選択の目安

1. **小規模で柔軟性を重視**  
   - NATインスタンスが向いている場合もある。  
   - インスタンスに細かい設定や独自のパケット操作をしたい場合。

2. **管理負荷を最小化し可用性を確保したい**  
   - NATゲートウェイがおすすめ。  
   - ほぼ運用不要で高可用性かつ自動スケーリングを備えている。

---

## まとめ

- **NATインスタンス**: EC2をNAT用にカスタマイズ。運用の柔軟性はあるが、管理と可用性確保は自分で行う必要がある。  
- **NATゲートウェイ**: フルマネージドサービス。初期設定が簡単で運用負荷が小さいが、インスタンスに比べるとややコストが高くなる可能性がある。  

運用規模や要件（コスト・可用性・運用リソース）を考慮して使い分けるのがベストです。
ローカル環境のみインストール不要！即使えるブラウザだけで動く2画面ファイラーをAI（CursorのComposer）で作成してみた

# ブラウザだけで動く2画面ファイラー「Browser Web Filer」の紹介

## はじめに

皆さんこんにちは。今回は、インストール不要でブラウザだけで動作する2画面ファイラー「Browser Web Filer」を紹介させていただきます。

## なぜこのツールを作ったのか

企業などで働いていると、以下のような制約に悩まされることがありませんか？

- セキュリティポリシーでアプリケーションのインストールが制限されている
- 作業用PCの環境を変更できない
- 管理者権限がない

そんな環境でも、効率的なファイル操作をしたい！という思いから、このツールを開発しました。

## 特徴

### 1. インストール不要、ブラウザだけで動作

- HTMLファイルを開くだけで即座に使用可能
- Chrome推奨（File System Access API対応ブラウザ）
- サーバー環境も不要

### 2. 2画面（左右ペイン）のファイル操作

- Norton Commanderライクな2画面インターフェース
- キーボード操作重視の設計
- ダークテーマ対応で目に優しい

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284824/2f3ba4c4-0e76-cf17-9fee-0535b84ee7a9.png)


### 3. 基本的なファイル操作機能

- ファイル/フォルダのコピー
- ファイル/フォルダの移動
- ファイル/フォルダの削除
- 新規ファイル/フォルダの作成

### 4. セキュリティ面での安心感

- ローカル環境でのみ動作
- 外部サーバーとの通信なし
- ブラウザのセキュリティサンドボックス内で動作

## 使い方

1. GitHubからプロジェクトのzipファイルを[ダウンロード](https://github.com/2f0833e717/browserwebfiler/archive/refs/heads/main.zip)
2. `C:\Users\Users\Downloads\browserwebfiler-main\browserwebfiler-main\main\src\app\html\index.html`をブラウザで開く
3. 「フォルダを選択」ボタンで作業フォルダを選択
4. キーボードショートカットでファイル操作

### 主なキーボードショートカット

```
[基本操作]
n         : フォルダを選択
←/→      : ペイン移動
↑/↓      : ファイル選択
Enter     : フォルダに移動

[コマンド]
Space     : コマンドモードON/OFF
m         : 移動
c         : コピー
d         : 削除
Shift + k : 新規フォルダ作成
Shift + e : 新規ファイル作成
```

## 制限事項

正直に申し上げると、以下のような制限があります：

- システムファイルエリア（C:/等）へのアクセス不可
- ファイル編集機能なし
- ドラッグ＆ドロップ非対応

## 類似ツールとの違い

既存のWEBベースのファイラーと比較した際の本ツールの特徴は：

1. **完全ローカル動作**
   - サーバー不要
   - インストール不要
   - 外部依存なし

2. **シンプルな構成**
   - HTML/CSS/JavaScriptのみで構築
   - フレームワーク未使用

3. **セキュリティ重視**
   - ローカルファイルのみアクセス
   - 通信機能なし
   - ブラウザの保護機能を活用

## まとめ

Browser Web Filerは、以下のようなシーンで特に活躍します：

- 社内の制約の厳しい環境での作業
- クライアントPCでの一時的なファイル操作
- アプリケーションのインストールが制限された環境

## 今後の展望

現在はベータ版ですが、以下の機能を検討中です：

- ファイル検索機能
- ファイル名編集機能
- ソート機能の拡充

## おわりに

本ツールがお役に立てば幸いです。GitHubでソースコードを公開していますので、ぜひフィードバックやプルリクエストをお待ちしています。
※この記事はAI(Cusrorチャット)で作成されました。画像の挿入、リンクの説明等一部を筆者が編集しています。

### 参考リンク

- [GitHub Repository](https://github.com/2f0833e717/browserwebfiler)
- [File System Access API](https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API)

### 以下、余談(作者コメントの追記)

投稿前にQiitaで検索したところ、先駆者がいたようです。
@takanopontaro (Shinji Takano)
二画面ファイラーを作った。
https://qiita.com/takanopontaro/items/58a4474e88f439330ab5

本WEBアプリはNode.jsなどインストールが必要ないので、
気軽にお試しできるところが強みかなとは思いますが、
機能は殆ど皆さんご存知「あふｗ」を元に作成しています。

ツールの作成理由は、先駆者の方も記事に書いていましたが、
Web版の2画面ファイラーがほとんど存在しないので、作りました。

本投稿記事もそうですが、このWEBアプリ自体はAI（CursorのCOMPOSER）で作成しました。
設計資料を途中で後から作ったりしていたので実装込みで2週間ほどの期間です。
途中でテストコードも出力させようとしていましたが、
node.jsを使わないといけなかったりしたので、アプリ仕様に合わないため一旦諦めました。
（オリジナルのテスト設計ライブラリを作らせたりもしましたが微妙だった）

CursorのCOMPOSERのagent modeでそこそこ動いてくれましたが、
設定等を調整したりするとうまく動いたりしなかったり。
https://github.com/2f0833e717/browserwebfiler/blob/main/main/docs/develop/auto-composer.ps1
主にこれを使い完全手放しでCOMPOSERの25回制限の自動実行テストをしていましたが、
COMPOSERS自体が反応したり、しなかったりと、とはいえ、「続けて Enter」の操作をしなくて済むので、
完全自動実行で今話題のCline系と使用感は変わらないかなと思います。
この辺だけでも記事にできそうですがまた別の機会で。

それではまた。
PineScriptリファレンスマニュアルを効果的に活用するTips



## 概要  
本記事では、TradingViewにおける[PineScript](https://www.tradingview.com/pine-script-reference/v6/?aff_id=112991&source=qtn-tradingview)のリファレンスマニュアルを効果的に活用するための具体的な方法を解説する。PineScriptはアルゴリズムトレードやシステムトレードを構築する際に重要な役割を果たすが、リファレンスマニュアルを上手に活用することで、スクリプト作成の効率性が格段に向上する。本記事では、リファレンスマニュアルの利用方法に加え、実践的な活用法や注意点も紹介する。

https://www.tradingview.com/pine-script-reference/v6/?aff_id=112991&source=qtn-tradingview

## 対象読者  
本記事は以下のような方々を対象としている。  
- PineScriptを使い始めたばかりの方  
- システムトレードやアルゴリズムトレードを学びたい方  
- PineScriptのリファレンスマニュアルを効果的に利用したい方  

---

## PineScriptリファレンスマニュアルの概要  
PineScriptのリファレンスマニュアルは、PineScriptの各種関数やライブラリの詳細な解説を提供しているオンラインリソースであり、公式ドキュメントとしてTradingViewのウェブサイト上に公開されている。リファレンスマニュアルには、以下のような情報が網羅されている。  
- 構文や関数の説明  
- 変数や型の定義  
- 描画やアラートなどの機能の使い方  
- サンプルコード  

PineScriptは非常に多機能であり、スクリプト作成時に多くの関数やライブラリを駆使することが求められるため、リファレンスマニュアルを効果的に活用することは、スクリプト作成の精度向上に不可欠である。

---

## リファレンスマニュアル活用のポイント  

### 1. 検索機能を駆使する  
PineScriptリファレンスマニュアルの最大の利点は、検索機能を利用して目的の関数やトピックを迅速に見つけることができる点である。特定の関数やキーワードを検索することで、必要な情報にすぐにアクセス可能である。特に、PineScriptでは新しい関数や機能が追加されることが多いため、常にリファレンスマニュアルを参照し最新情報を把握することが重要である。

#### 実践例  
例えば、「sma」という移動平均関数を使いたい場合、「sma」と検索することで、関数の使い方、引数、戻り値に関する詳細な説明がすぐに表示される。これにより、スクリプトを実装する際にどの引数を設定すべきかが簡単に理解できる。

### 2. サンプルコードを参照する  
リファレンスマニュアルには、各関数やメソッドの使い方に関するサンプルコードが掲載されている。これを利用することで、コードの動作イメージをつかみやすく、実際のプロジェクトに組み込みやすくなる。サンプルコードは、トレードシステムの基盤となる部分を組み立てる際に非常に有益である。

#### 実践例  
`plot()`関数を用いてデータをチャート上に描画する方法を学びたい場合、リファレンスマニュアルに記載されたサンプルコードを参考にすることで、すぐにグラフ表示の実装が可能となる。

### 3. ドキュメントを組み合わせて学習する  
PineScriptのリファレンスマニュアルだけでなく、公式のチュートリアルやブログ記事と合わせて学習することが効果的である。ドキュメントの解説は非常に詳細であるが、具体的な使用例や実際のトレードシナリオに基づいた応用力を高めるためには、他のリソースを参照することが有用である。

#### 実践例  
リファレンスマニュアルで関数の基本的な使い方を確認した後、実際のトレードシステムにどのように組み込むかについては、他のユーザーが投稿したコードや実践的なアプローチを参考にすることが重要である。

### 4. エラーメッセージを活用する  
スクリプトを書いている際にエラーが発生することが多いが、PineScriptはエラーメッセージを非常に明確に表示するため、エラーメッセージをリファレンスマニュアルで調べることで、迅速に問題を解決できる。エラーメッセージの中には、関数の誤用や引数の間違いなどが明記されており、それに基づいて正しい書き方を見つけることができる。

#### 実践例  
「undeclared identifier」というエラーが出た場合、このエラーメッセージをリファレンスマニュアルで調べることで、変数が未定義であることを認識でき、定義を見直すことができる。

---

## 注意点  

### 1. バージョンに留意する  
PineScriptは定期的にアップデートされ、新しいバージョンがリリースされる。リファレンスマニュアルの内容もバージョンに応じて異なるため、現在使用しているバージョンに適した情報を参照することが重要である。特に、古いバージョンの関数や仕様が新しいバージョンで非推奨となっている場合があるので注意が必要である。

### 2. 関数の依存関係を理解する  
PineScriptの関数やメソッドは、他の関数や変数に依存して動作することが多いため、リファレンスマニュアルで関数の詳細な仕様を確認した後、他の関数との組み合わせでどのように動作するかを理解する必要がある。特に、`plot()`や`alertcondition()`などは、適切に条件を設定しないと意図した通りに動作しないことがある。

---

## 結論  
PineScriptのリファレンスマニュアルは、スクリプト作成における貴重なリソースであり、効率的に活用することで開発の速度や精度を大幅に向上させることができる。検索機能やサンプルコード、エラーメッセージを上手に活用することにより、PineScriptの習得を加速し、効果的なシステムトレードを実現することが可能となる。適切にリファレンスマニュアルを活用し、より高度なトレーディング戦略の構築を目指していただきたい。

---

APIドキュメント：

https://www.tradingview.com/pine-script-reference/v6/?aff_id=112991&source=qtn-tradingview

---

## 免責事項  

本記事に記載されている内容は、筆者がTradingViewおよびPineScriptを用いて学び得た知識と経験を基に執筆したものである。内容の正確性および完全性については可能な限り配慮しているが、必ずしもその保証をするものではない。  

自動売買Botの構築や運用、またそれに関連する投資活動は読者自身の判断と責任に基づいて行われるべきであり、筆者および本記事を掲載するプラットフォーム（Qiita）は、それによって生じたいかなる損失や損害に対しても一切の責任を負わないものとする。  

特に、トレードに関する意思決定は市場リスクを伴うため、実運用前に十分な検証とリスク評価を行い、必要に応じて専門家への相談を推奨する。  

読者各位の責任において本記事をご活用いただければ幸いである。
PineScriptの無料版と有料版での違い・制限と収益化



## 概要  
TradingViewにおける[PineScript](https://www.tradingview.com/pine-script-reference/v6/?aff_id=112991&source=qto-tradingview)は、トレーダーが独自のインジケーターやストラテジーを作成するために非常に有用なツールである。PineScriptは、無料版および有料版（Pro、Pro+、Premium）に分かれており、それぞれに異なる機能や制限が存在する。本記事では、PineScriptの無料版と有料版における違いや制限、さらには収益化の観点からの活用方法について解説する。

https://www.tradingview.com/pine-script-reference/v6/?aff_id=112991&source=qto-tradingview

## 対象読者  
本記事は以下のような方を対象としている。  
- TradingViewのPineScriptを使っている、または使おうと考えている方  
- PineScriptの無料版と有料版の違いを理解したい方  
- システムトレードやアルゴリズムトレードを収益化したい方  

---

## PineScriptの無料版と有料版の基本的な違い  
TradingViewには、無料版といくつかの有料プラン（Pro、Pro+、Premium）が存在する。これらのプランには、PineScriptに関する機能や使用制限に差異がある。以下に、無料版と有料版の主な違いを示す。

### 1. スクリプトの制限  
- **無料版**: 無料版では、最大3つのカスタムインジケーター（PineScript）をチャートに追加できる。これは、個人の学習や簡単なトレード戦略のテストには十分であるが、複雑なシステムトレードや複数のインジケーターを並行して使用する場合には制約が生じる。
- **有料版（Pro, Pro+, Premium）**: 有料プランに加入すると、スクリプトの数に対する制限が緩和され、最大10個、20個、またはそれ以上のカスタムインジケーターを追加できる。複数のインジケーターや戦略を一度に使いたい場合には、有料プランが推奨される。

### 2. アラート機能  
- **無料版**: 無料プランでは、最大1つのアラートのみ設定できる。これにより、特定の条件を監視することは可能であるが、複数のシグナルを同時に監視するには制限がある。
- **有料版**: 有料プランでは、アラートの設定数が大幅に増加する。Proプランでは最大10個、Pro+では最大30個、Premiumでは無制限にアラートを設定できるため、複数の条件をリアルタイムで監視し、迅速に反応することが可能となる。

### 3. バックテスト機能  
- **無料版**: 無料版でも基本的なバックテストは可能だが、ストラテジーテストの精度や過去データに対するアクセスには制限がある。特に、バックテストの期間や頻度に関して制限がかかることが多い。
- **有料版**: 有料プランでは、バックテストにおけるデータのアクセス範囲が広がり、より長期間のデータを用いた詳細なテストが可能になる。また、過去のデータに対するリソースの制限も緩和されるため、精度の高い分析が行える。

### 4. チャートの更新頻度  
- **無料版**: 無料版では、チャートの更新頻度が遅く、1分足や短期的なデータに基づくトレードには不便を感じることがある。  
- **有料版**: 有料プランでは、より高頻度でのチャート更新が可能となる。これにより、リアルタイムで市場の動きに追従しやすく、精度の高いトレードが可能となる。

---

## PineScriptにおける収益化  
PineScriptを活用した収益化には、いくつかの方法が考えられる。特に、有料プランを活用することで、より効率的に収益化を目指すことができる。以下に収益化の手段を示す。

### 1. インジケーターの販売  
PineScriptで作成したインジケーターやトレード戦略を販売することができる。TradingViewの「Public Library」に公開することで、他のトレーダーと共有し、評価を受けることができる。これにより、特定のインジケーターを有料で販売することが可能となる。無料プランではインジケーター数に制限があるため、収益化を目指す場合は有料プランへの移行が推奨される。

### 2. 自動化されたシグナル提供サービス  
有料プランを利用して、複数のインジケーターを駆使したトレードシグナルを提供するサービスを作成することができる。サブスクリプションモデルを導入することで、安定した収益を得ることが可能である。  

### 3. システムトレードの運用  
PineScriptを用いてシステムトレードを構築し、アルゴリズムトレードを自動化することができる。特に、有料プランを利用してバックテストの精度を向上させ、リアルタイムでのトレード環境を整えることで、効率的な運用が可能となる。

---

## 結論  
PineScriptの無料版と有料版には、機能や制限に明確な違いが存在する。特に、システムトレードやアルゴリズムトレードを実践する上で、無料版では機能に制限が多いため、収益化を目指すのであれば有料プランへの移行が有効である。自分のトレードスタイルに合わせて適切なプランを選択し、効率的にトレードを行うことが、成功への鍵となるであろう。

---

APIドキュメント：

https://www.tradingview.com/pine-script-reference/v6/?aff_id=112991&source=qto-tradingview

---

## 免責事項  

本記事に記載されている内容は、筆者がTradingViewおよびPineScriptを用いて学び得た知識と経験を基に執筆したものである。内容の正確性および完全性については可能な限り配慮しているが、必ずしもその保証をするものではない。  

自動売買Botの構築や運用、またそれに関連する投資活動は読者自身の判断と責任に基づいて行われるべきであり、筆者および本記事を掲載するプラットフォーム（Qiita）は、それによって生じたいかなる損失や損害に対しても一切の責任を負わないものとする。  

特に、トレードに関する意思決定は市場リスクを伴うため、実運用前に十分な検証とリスク評価を行い、必要に応じて専門家への相談を推奨する。  

読者各位の責任において本記事をご活用いただければ幸いである。
【FastAPI】RequestValidationErrorのdetailsのtypeにはどんな種類があるのか？

# 概要
FastAPIで便利な`RequestValidationError`の`details`について、どんな形式になっているのか、デバッグして色々と調査してみました。

### 前提
- Python：3.12
- fastapi：0.112.1
- pydantic：2.8.2

## `RequestValidationError`とは
`RequestValidationError`とは、Pydanticの`ValidationError`のサブクラスで、FastAPIとPydanticが連携してリクエストデータのバリデーションを行う際に発生するエラーです。

リクエストデータが定義したPydanticモデルに一致しない場合に、内部的に（自動で）発生させてくれます。FastAPIがバリデーションに強い、と言われる所以の一つと思います。

公式ドキュメントには以下のように記載があります。

> リクエストに無効なデータが含まれている場合、FastAPI は内部的にRequestValidationErrorを発生させます。
また、そのためのデフォルトの例外ハンドラも含まれています。
これをオーバーライドするにはRequestValidationErrorをインポートして@app.exception_handler(RequestValidationError)と一緒に使用して例外ハンドラをデコレートします。
この例外ハンドラはRequsetと例外を受け取ります。
https://fastapi.tiangolo.com/ja/tutorial/handling-errors/#_5

しかし、いざレスポンスの詳細を見ようと思うと、`type`にどんな種類があるのだろう？とかドキュメントや記事を見てもよくわかりません（AWSドキュメントのCloudformationみたいに項目の全量があるとわかりやすいんですが）

ということで実際にぽちぽち検証してみました。

### 型エラー(STRING型に対してINT連携)
例えば、STRING型で定義された項目に対して整数値(例：`2`)で連携すると以下のエラーになります。

```json
 {
    "detail": [
        {
            "type": "string_type",
            "loc": [
                "body",
                "sample_name"
            ],
            "msg": "Input should be a valid string",
            "input": 2
        }
    ]
}
```

なるほど。`msg`のところで丁寧に理由まで返してくれます。

### 型エラー(INT型に対してSTRING連携)

次に、INTで定義した項目に対して、STRINGを連携します。
すると以下のエラーメッセージになります。

```json
{
    "detail": [
        {
            "type": "int_parsing",
            "loc": [
                "body",
                "sample_number"
            ],
            "msg": "Input should be a valid integer, unable to parse string as an integer",
            "input": "abcd"
        }
    ]
}
```

先ほどは`type`は`string_type`とありましたが、
今回は`int_parsing`になりました。

### 必須エラー
Pydantic側で必須項目にしたものを入力せずに連携すると以下のエラーになります。

```json
{
    "detail": [
        {
            "type": "missing",
            "loc": [
                "body",
                "sample_name"
            ],
            "msg": "Field required",
            "input": "...(省略)..."
        }
    ]
}
```

`type`が`missing`になっているので、「必要なものが欠けていますよ」という意味で直感的でわかりやすいですね。

### 文字数エラー（STRING型）

最小・最大文字数をPydantic側で定めている場合、それ以下だったりそれ以上だったりすると以下のエラーになります。以下は1文字以上4文字以下と定義されたSTRING型の項目に対して0文字で連携した場合のエラーメッセージです。

```json
{
    "detail": [
        {
            "type": "string_too_short",
            "loc": [
                "body",
                "sample_name"
            ],
            "msg": "String should have at least 1 character",
            "input": "",
            "ctx": {
                "min_length": 1
            }
        }
    ]
}
```

最小文字数まで教えてくれる。

### 数値範囲エラー（INT型）

INT型の項目に対して定められた数値範囲(`1`-`9999`)があり、それを超えた数値を連携した場合のレスポンスは以下の通り。

```json
{
    "detail": [
        {
            "type": "less_than_equal",
            "loc": [
                "body",
                "sample_number"
            ],
            "msg": "Input should be less than or equal to 9999",
            "input": "19999",
            "ctx": {
                "le": 9999
            }
        }
    ]
}
```

こちらも最大数値も一緒に教えてくれます。

## 以上！
こうしてみると丁寧に色々と返してくれるのがわかります。

他にも色々とPydantic側で用意してくれているみたいです。
バリデーションエラーを自動的にキャッチし、適切なエラーメッセージを返してくれるのはありがたいですね。かつ
[Tauri] VSCodeからのデバッグ


[公式の情報](https://v2.tauri.app/develop/debug/vscode/) に従い、
`.vscode/launch.json`,`.vscode/tasks.json` を作成する。

コメントに従って、`tasks.json` の `command` を、
`src-tauri\tauri.conf.json` の `beforeDevCommand`,`beforeBuildCommand` へ書き変える必要がある事に留意。

* e.g. npm の場合は、以下の様に変更をする。
```diff_json
- // change this to your `beforeDevCommand`:
- "command": "yarn",
- "args": ["dev"]
+  "command": "npm run dev",
```

デバッグ版/リリース版の選択を行い、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274593/137ebdad-af04-dc6e-f27c-99e73cd2c7ad.png)


F5 でデバッグを開始すると、アプリが起動する。


# note

---

この方法では、VSCode上では、バックエンド(Rust)側しかデバッグできない。
フロントエンド(React)側のデバッグは、アプリの右クリックから、開発者ツールを出して行う。
<!-- フロントエンド(React)側にブレークポイントを置いても止まらない。 -->

---

`println`,`dbg`などによるコンソール出力の結果は、
VSCode のターミナルへ、出力される。

```rs
println!("Test");
```
![image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274593/b02e234f-c4b8-30a5-cf00-77114838160c.png)


---


`npm run tauri dev` でのデバッグと異なり、
ソースを変更しても自動での再ビルドは走らない。
LaravelでTCPDFとFPDIを使用してPDFを作成する方法

皆さん、こんばんは。

今日は「LaravelでTCPDFとFPDIを使用してPDFを作成する方法」についてご紹介します。

TCPDFはPDF生成ライブラリで、FPDIは既存のPDFを読み込んで編集するためのライブラリです。これらを組み合わせることで、強力なPDF操作が可能になります。

# パッケージのインストール

まず、Composerを使用して必要なパッケージをインストールします。

```bash
composer require tecnickcom/tcpdf
composer require setasign/fpdi
```

setasign/fpdi はFPDIの公式パッケージです。TCPDFとの互換性を確保するため、追加で setasign/fpdi-tcpdf をインストールすることも推奨されます。

```bash
composer require setasign/fpdi-tcpdf
```

## ライブラリの設定

LaravelでTCPDFとFPDIを使用するために、サービスプロバイダやファサードを設定する必要はありません。直接クラスをインポートして使用できます。

# PDFの作成方法

TCPDFとFPDIを使用して新しいPDFを作成し、既存のPDFにページを追加する基本的な例です。

## コントローラにコードを追加

app/Http/Controllers/PdfController.php を以下のように編集します。

```php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use setasign\Fpdi\TcpdfFpdi;

class PdfController extends Controller
{
    public function createPdf()
    {
        // FPDIのインスタンスを作成（TCPDFをベースに）
        $pdf = new TcpdfFpdi();

        // ドキュメント情報を設定
        $pdf->SetCreator(PDF_CREATOR);
        $pdf->SetAuthor('あなたの名前');
        $pdf->SetTitle('サンプルPDF');
        $pdf->SetSubject('TCPDFとFPDIの統合');

        // デフォルトのヘッダーとフッターを設定
        $pdf->setPrintHeader(false);
        $pdf->setPrintFooter(false);

        // フォントの設定
        $pdf->SetFont('helvetica', '', 12);

        // 新しいページを追加
        $pdf->AddPage();

        // テキストを追加
        $pdf->Write(0, 'こんにちは、これはTCPDFとFPDIを使用したサンプルPDFです。');

        // 既存のPDFを読み込んでページを追加（オプション）
        // 例として、storage/app/public/sample.pdf を使用
        $existingPdfPath = storage_path('app/public/sample.pdf');
        if (file_exists($existingPdfPath)) {
            $pageCount = $pdf->setSourceFile($existingPdfPath);
            for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
                $tplId = $pdf->importPage($pageNo);
                $size = $pdf->getTemplateSize($tplId);

                // 新しいページを追加し、既存のページをテンプレートとして使用
                $pdf->AddPage($size['orientation'], [$size['width'], $size['height']]);
                $pdf->useTemplate($tplId);

                // 必要に応じて追加のコンテンツを挿入
                $pdf->SetFont('helvetica', '', 10);
                $pdf->SetXY(10, 10);
                $pdf->Write(0, "これはページ {$pageNo} の上に追加されたテキストです。");
            }
        }

        // PDFを出力（ブラウザで表示）
        return response($pdf->Output('sample.pdf', 'S'), 200)
                  ->header('Content-Type', 'application/pdf');
    }
}
```

既存のPDFを操作する場合は、storage/app/public/sample.pdf に対象のPDFファイルを配置してください。必要に応じて、ストレージへのアクセス権限を設定します。

### 画像の追加

Image関数で画像も追加できます。

```php
$pdf->Image('@'.$fileContent, $x, $y, '', '');
```

## ルートの設定

routes/web.php にルートを追加します。

```php
use App\Http\Controllers\PdfController;

Route::get('/create-pdf', [PdfController::class, 'createPdf']);
```

# 注意点

- フォントの設定: TCPDFは多くのフォントをサポートしていますが、日本語フォントを使用する場合は、フォントファイルを適切に設定する必要があります。例えば、mplus-1p-regular.ttf などの日本語フォントをTCPDFに読み込ませてください。
- エラーハンドリング: 実際のアプリケーションでは、ファイルの存在確認や読み込み時のエラーハンドリングを適切に行うことが重要です。
- パフォーマンス: 大きなPDFファイルや多くのページを扱う場合、メモリ使用量や処理時間に注意してください。必要に応じて、サーバーの設定を調整することを検討してください。

ぜひ参考にしてみてください。

今日は以上です。

ありがとうございました。
よろしくお願いいたします。
PowerShellでビープ音を鳴らして処理完了を通知するCLIツールを作った

# 作成背景

AWS SAMのデプロイやビルドって結構時間かかって、気が付いたら終わっていることが多々あった。常に気にするのもストレスなので終わったらなるようにしたかった。

# 作ったもの

PowerShellでビープ音を鳴らすシンプルなCLIツール「beep」：

- 周波数、長さ、回数、間隔を指定してビープ音を鳴らせる
- コマンドライン引数で簡単に設定を変更可能
- エラー発生時も適切にハンドリング
- ヘルプメッセージで使い方をすぐに確認できる

# 使い方

基本的な使い方は以下の通り：

```powershell
beep -f 1000 -n 3 -i 500  # 1000Hzの音を3回、500ms間隔で鳴らす
beep -Frequency 800 -Long  # 800Hzの音を長め（1秒）で鳴らす
beep -c 5 -f 2000         # 2000Hzの音を5回鳴らす
```

# SAMでの活用例

以下のように組み合わせることで、長時間のSAM処理が完了したことを音で知ることができる：

```powershell
sam build; beep -n 3  # ビルド完了時に3回ビープ音
sam deploy; beep -l   # デプロイ完了時に長めのビープ音
```

# コード

正直`[Console]::Beep(3000,1000)`を実行するだけでも、まあ十分ではあるんですが、ちょっとした遊び心です。

エイリアス設定等面倒くさい場合は、直接関数を実行してやってください。

# おわりに

完全なコードは[GitHub](https://github.com/koinunopochi/tools/tree/main/cli/beep)にあります。

前からちょっとストレスだったので、手軽に作れてよかｔ
WordからMermaidフローチャートを作成する方法

## この記事のポイント
- 複雑なプロセスを視覚的に理解するフローチャート作成方法
- Wordドキュメント→ChatGPT→draw.ioでフローチャートへの3ステップ変換手順

## フローチャート作成の３ステップ

### 1. Word文書の内容を整理する
ステップが構成されるよう以下を中心に文章を明確化する
- プロセスや手順を説明している部分を特定する
- 主要なステップと分岐点を抽出する
- 対象となる典型的なフローを整理する


### 2. ChatGPTでMermaidを作成する

ChatGPTでWord文書をMermaidコードに変換してもらう
```
以下内容をMermaidコードに変換してください
＜１で整理した文章を入力＞
```


### 3. draw.ioでフローチャートを作成
出力されたコードを、Mermaid対応のエディターに貼り付け、フローチャートを視覚化します

##### 1. draw.ioを開く
https://app.diagrams.net/
##### 2. リンクを開くとLoadingが始まる
![スクリーンショット 2025-01-24 .jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980972/ce656e1a-4e89-b34d-e400-5496c790c567.jpeg)
##### 3. 後で決める をクリック
![スクリーンショット 2025-01-24 211637.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980972/eb5a4b70-ed3c-f986-5fcb-d06843b25fcd.jpeg)
##### 4. draw.ioのMermaidエディターを開く
・配置タブ＞挿入＞テキスト＞Mermaid
![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980972/74e299ed-462d-0d3c-3751-9b133d8abf00.png)
##### 5. draw.ioのMermaidエディターに貼り付ける
![スクリーンショット 2025-01-24 205303.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980972/43e9b30d-8d3b-ba93-6b53-63f709badaff.jpeg)

### ４. フローチャート完成
![スクリーンショット 2025-01-24 205355.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980972/3aec16c3-b623-0c46-072d-64b13e874726.jpeg)

ただし量が多いと横長になってしまう。。。
ChatGPTを使い、ツールを使ってよりきれいなフロー図を作成する方法を
以下のページで別途解説します
https://qiita.com/ellyyyy/items/15d3c17208f27a3b5665
「Node.js（Express）とMongoDB」に決定！バックエンド技術選定の舞台裏✨

# 開発日記8日目：バックエンド技術選定完了！Node.js（Express）とMongoDBに決定！🌟

群馬県民がもっと地元イベントを楽しめるように！イベント発見アプリを個人開発している🐮です！

今日は開発8日目。バックエンド開発に必要な技術の選定を行い、ついに**Node.js（Express）**と**MongoDB**を選ぶことにしました！技術の海を泳ぎ回り、ようやくたどり着いたこの選択にワクワクしています！✨

---

🌟 **今日のハイライト**

- ✅ バックエンドフレームワークに**Node.js**を選定！
- ✅ データベースに**MongoDB**を採用決定！
- ✅ 各技術のメリット・デメリットを徹底比較！

---

🛠 **今日の作業内容**

### 1. バックエンド技術の候補を比較検討

まずは、以下の技術を候補に挙げ、それぞれの特徴をじっくりと分析しました。

#### 🔹 **Node.js（Express）**

- **メリット**
  - **JavaScriptで統一**：フロントエンドと同じ言語で開発可能
  - 非同期I/Oで高いパフォーマンス
  - 豊富なライブラリと巨大なコミュニティ
- **デメリット**
  - 単一スレッドのため、CPU負荷の高い処理には不向き
  - コールバック地獄の可能性（最近はasync/awaitで解決）

#### 🔸 **Django（Python）**

- **メリット**
  - **堅実なフレームワーク**：セキュリティや管理画面が充実
  - バッテリー同梱哲学で必要な機能が統合
  - オブジェクト指向でコードが整理しやすい
- **デメリット**
  - フロントエンドと異なる言語での開発
  - 学習コストと開発効率の懸念

#### 🔺 **Firebase（BaaS）**

- **メリット**
  - **サーバーレスで迅速な開発**が可能
  - 認証やリアルタイムデータベースなどの豊富な機能
  - スケーラビリティが高く、インフラ管理不要
- **デメリット**
  - **ベンダーロックイン**のリスク
  - カスタマイズ性や複雑なビジネスロジックの実装に制約

### 2. **Node.js（Express）**と**MongoDB**を選定！

数々の検討を経て、最終的に**Node.js（Express）**をバックエンドフレームワークに、データベースには**MongoDB**を採用することに決めました！🎉

**選定理由**

- **言語の統一感**：フロントエンドとバックエンドをJavaScript（TypeScript）で統一することで、開発効率が向上。
- **学習コストの低減**：新たな言語を学ぶ時間を削減し、開発に集中できる。
- **柔軟性と拡張性**：Expressのシンプルさから、必要な機能を自由に組み込める。
- **MongoDBのドキュメント指向**：イベント情報などの多様なデータ構造を柔軟に扱える。

### 3. 各技術のメリット・デメリット比較での学び

技術選定の過程で、それぞれの技術の強みと弱みを深く理解することができました。

- **Node.js（Express）＋MongoDB**
  - **メリット**：開発効率、スケーラビリティ、NoSQLの柔軟性
  - **デメリット**：データの整合性管理の難しさ
- **Django（Python）＋PostgreSQL**
  - **メリット**：堅牢な構造、豊富な機能、データ整合性
  - **デメリット**：開発効率、言語の違いからくる学習コスト
- **Firebase**
  - **メリット**：迅速な開発、インフラ管理不要
  - **デメリット**：カスタマイズ性の制限、ベンダーロックイン

---

📊 **プロジェクト進捗状況**

| フェーズ            | 進捗率 | 主要成果物                           |
| ------------------- | ------ | ------------------------------------ |
| 要件定義            | 100%   | ユーザーストーリーマップ              |
| UI/UX設計           | 90%    | デザインシステムガイドライン         |
| フロントエンド技術選定 | 100%   | 技術選定レポート                     |
| **バックエンド技術選定** | **100%**   | **技術選定レポート**                 |
| 開発環境構築        | 20%    | 開発ツールリスト、初期プロジェクト構成 |

---

💡 **今日の気づきと学び**

**成功した点**

- **言語統一による開発効率の向上**：JavaScriptで統一することで、頭の切り替えがスムーズに。
- **コミュニティの力を実感**：情報が豊富で、問題解決が迅速に行える安心感。

**改善が必要な点**

- **データベース設計の深掘り**：MongoDBの特性を活かしたデータ設計をさらに学ぶ必要がある。
- **セキュリティ面の強化**：Non-blocking I/Oのメリットを活かしつつ、セキュリティリスクを最小限に。

---

🚀 **次回予告：開発環境の構築と初期設定！**

次回は、選定した技術を基に開発環境の構築とプロジェクトの初期設定を行います！

- **Node.jsとExpressのセットアップ**
- **MongoDBのローカル環境構築**
- **TypeScriptの導入とlint設定**

これから本格的に開発が始まると思うと、胸が高鳴ります！🔥

---

✨ **今日のひとこと**

群馬の皆さんに役立つアプリを目指して、明日も全力で頑張ります！皆さんの応援が本当に励みになっています。コメントやいいね、お待ちしています！😊

---

最後までお読みいただきありがとうございます！

引き続き応援よろしくお願いします！では、また明日〜！👋
【解決済】node_modules を Lambda 関数 zip に含めるとgithub actionsに仕込んだ Terraform plan が走らない

## 発生した問題

* **Terraform plan の失敗**: Lambda 関数のソースコードを zip ファイルにまとめる際、`node_modules` ディレクトリを含めた状態で `terraform plan` を実行すると、処理が非常に遅くなる、またはタイムアウトやエラーが発生して plan が完了しない。
* **GitHub Actions CI/CD の停止**: 上記の状態の Terraform コードを GitHub Actions の CI/CD パイプラインで実行しても、パイプラインが正常に開始されず、ログも出力されないまま失敗する。

## 原因

* **zip ファイルサイズの肥大化**: `node_modules` ディレクトリは、多数のファイルと大きなサイズを持つため、zip ファイルに含めるとファイルサイズが非常に大きくなる。
* **Terraform の処理負荷増大**: `archive_file` データソースが、肥大化した zip ファイル (特に `node_modules` 内の大量のファイル) を処理しようとする際に、Terraform 自体の処理負荷が著しく増大し、リソース不足やタイムアウトが発生する。
* **GitHub Actions のリソース制限**: GitHub Actions の実行環境にはリソース制限があるため、Terraform plan の処理負荷が増大すると、リソース制限を超えてしまい、パイプラインが正常に動作しなくなる。ログが出力されなかったのは、Terraform plan の処理が開始される前に、リソース不足などで異常終了していたためと考えられる（詳細はログがないため推測）。

## 解決策

* **Lambda Layer の利用**: Lambda 関数の依存ライブラリ (`node_modules`) を Lambda Layer として分離し、Lambda 関数本体の zip ファイルには含めないように構成を変更する。
* **Terraform での Lambda Layer 実装**:
    * `archive_file` データソースを使用して、Lambda Layer 用の `node_modules` ディレクトリを zip ファイルとして作成。
    * `aws_s3_object` リソースで zip ファイルを S3 バケットにアップロード。
    * `aws_lambda_layer_version` リソースで Lambda Layer を定義 (S3 URI、互換ランタイムなどを指定)。
    * `aws_lambda_function` リソースの `layers` 引数に Lambda Layer の ARN を指定して、Lambda 関数に Layer を紐付け。

## ファインプレーだった点

* GitHub Actions で CI/CD パイプラインがエラーログも出力せずに停止した際、**`node_modules` ディレクトリを削除** してローカル環境で `terraform plan` を実行するという**切り分け**を試したことが、問題の原因特定と解決に繋がった。
    * 通常、CI/CD が動かない場合はログを確認することが first step となるが、今回はログが出力されなかったため、別の切り口で原因を探る必要があった。
    * `node_modules` を削除するという**大胆な仮説**と**検証**が功を奏した。

## 今後の対応

* **Lambda 関数の `node_modules` は Lambda Layer で管理**: 今後 Terraform で Lambda 関数を管理する際は、Lambda 関数の依存ライブラリ (`node_modules`) は zip ファイルに含めず、Lambda Layer を利用してデプロイすることを標準とする。
* **CI/CD 異常時はローカル環境での `terraform plan` 実行**: GitHub Actions で CI/CD パイプラインが正常に動作しない場合は、まずローカル環境で `terraform plan` を実行し、エラーメッセージや挙動を確認する。
* **zip ファイルサイズと Terraform 処理負荷の考慮**: Terraform で Lambda 関数を扱う際は、zip ファイルサイズが肥大化しないように注意し、Terraform の処理負荷を下げる対策 (Lambda Layer の利用、zip ファイルの最適化など) を検討する。
* **原因不明なエラーには大胆な仮説と検証**: エラーログが少ない場合や原因が特定できない場合は、固定観念にとらわれず、大胆な仮説を立てて検証することで、問題解決に繋がる場合があることを意識する。

## まとめ

今回の事象は、`node_modules` を Lambda 関数 zip に含めることによる zip ファイルの肥大化と、それに伴う Terraform の処理負荷増大が原因でした。Lambda Layer を利用することで、この問題を解決し、Terraform による Lambda 関数管理を効率化することができました。また、CI/CD パイプラインが異常停止した場合の切り分け方法として、ローカル環境での `terraform plan` 実行と、大胆な仮説検証が有効であることを学びました。
ChatGPT Teamの年間課金の更新に関する備忘録

# ChatGPT Team
　ChatGPTには、複数のメンバーが同じワークスペースで知見を共有できるChatGPT Teamというサービスが用意されています。

https://openai.com/ja-JP/chatgpt/team/

　今回は、そのChatGPT Teamの年間課金の更新時にシート数を減らして次の１年を契約する方法と、その金額の確認方法を、びぼうｒとして残しておきたいと思います。

## ChatGPT Teamの課金額
　ChatGPT Teamでは、最初にシート数を設定して金額が決まります。年間課金だと１シートで330ドル（税込み）になるので、nシートだと330nドルになります。
 　その後、nシートをメンバーに割り当てることになりますが、期間内であればflexibleにメンバーをassingし直すことが出来ます。

## ChatGPT Teamのシート数管理
　ここで問題になるのが、シート数の管理です。一度年間課金でシート数nを契約した場合、使わなくてもrefundされることはありません。逆に、シート数をk増やすことは出来て、その分は新たに課金されます。

## 更新タイミングでのシート数管理
　１年が経過したタイミングで、次の年にはpシート減らしたいということがあるかも知れません。その場合、nと表示されている"シート数"をn-pに減らすというものは、UI的には存在しません。契約の途中でシート数を減らすことが出来ないからです。このUIの仕様を見ると、更新時にもシート数が減らせないように見えます。

  一方で、**実は更新のタイミングで、シート数ではなく、メンバー数をn-pにしていれば、自動的に翌年のBillingがn-p人で請求されるようになるらしいのです。** 
　英語版のHELP文書を読んでいると、そのような記載があるのですが、間違ってもrefundも出来ず、Billingが送られてくるまで金額を確認出来ないので、万が一間違いがあっては損をしてしまいます。
　そこで、openAIのSupportにチャットで問い合わせて確認をしたところ、「その理解で正しいが、**ただし更新日の４８時間前のメンバー数で請求額が変わる**」とのことで、少し早めに対応するのが良いということがわかりました。
　実際、メンバーを減らしてみると、いつの間にか（たぶん４８時間サイクルなのだろう）、次回の請求額がそのメンバー数で計算された額に変更されていました。
 
　しかし、更新の４８時間前に変更しないければならないと、p人×２日分は実質使えなくなってしまうので、なんだか勿体ないですね。

　本当は、次回更新時のシート数をnからn-pに直接変更できる仕様にしてくれるとUI／UX的にも分かりやすいと思います。そうすると、契約更改の前に契約から外すp人のメンバーも指定しておかなければならないですが、そのくらいのフロントエンドは作って欲しいですね。
 
以上。
【Linux】ログローテートされたファイルを解凍展開せずに見る方法


　ログローテートされたファイルを解凍することなく、中身を見たいってなったときに便利。
というか、ログローテートされたファイルのログを見るときにこのコマンドしか使っていない。
　　**gunzip -dc ≪ファイル名≫ | less**
　　**gunzip -dc ≪ファイル名≫ | grep "≪検索文字≫"**

標準出力をfileAに書き込み、fileAを圧縮した後、それを解凍せずに中身が見れることを確認します。
まずは、標準出力をfileAに書き込みます。
```
[root@www test]# echo "happynewyear 2025" > fileA
[root@www test]# cat fileA
happynewyear 2025
```
⇒fileAに書き込まれたことをcatで確認できること

次に、fileAを圧縮します。
```
[root@www test]# gzip fileA
[root@www test]# ll
合計 8
4 -rw-r--r-- 1 root root 44 2024/12/29 09:29:17 fileA.gz
4 -rw-r--r-- 1 root root 22 2024/12/29 09:32:54 fileB
0 -rw-r--r-- 1 root root  0 2024/12/28 18:13:19 fileC
```
⇒<font color="Red">fileA.gz</font>が作られたこと

最後に、fileA.gzの中身を解凍なしに見ます。
今回はパイプでcatコマンドに標準出力を渡します。
```
[root@www test]# gunzip -dc fileA.gz | cat
happynewyear 2025
```
⇒<font color="Red">fileA.gz</font>の内容が表示されること
grepも試してみます。
```
[root@www test]# gunzip -dc fileA.gz | grep "2025"
happynewyear 2025
```
⇒<font color="Red">2025</font>が赤文字となっていること
GitHub Pages をローカルでテストする (2025)

GitHub Pages はいろいろカスタマイズできるのですが、出来上がるページを確認するのにいちいち git push しないといけないのが作業的にもコミット履歴としてもちょっとよろしくないです。
そこで push する前にローカルでテストする方法を調べました。

作業環境は Windows 10 です。

:::note info
情報は 2025 年 1 月現在のものです。
環境はどんどん変化していくため、あくまでこの時点の情報であることをご確認ください。
:::

## Docker で環境をつくる

環境を Docker で構築します。

Docker ってなんぞや？ってのは調べてください。
調べてもよくわからないかもしれませんが、今回ローカルでテストできるようになるころにはなんとなくその便利さがわかるかと思います。
自分がそうでした。


### 1. Docker Desktop をインストールする

参考：[Windows 11にDocker Desktopを入れる手順（令和5年最新版）](https://qiita.com/zembutsu/items/a98f6f25ef47c04893b3)


### 2. GitHub Pages をローカルで作る Docker イメージを取得する

今回は [mrseccubus/github-pages](https://hub.docker.com/r/mrseccubus/github-pages?uuid=AD604D36-E65C-4CB2-9CB2-6935B3A2FDBD) イメージを使います。Docker Desktop で取得してください。


### 3. テストする GitHub Pages のソースを準備する

GitHub Pages のソースとなるディレクトリを用意します。
git のリポジトリディレクトリ、もしくは設定によってはその docs ディレクトリのことです。

例として、以下のように index.md ファイル１つだけの最小構成で考えます。
ローカルでテストするには、さらに2つの設定ファイルが必要です。

```
C:\Sample
     +- index.md
     +- Gemfile
     +- _config.yml
```

:::note info
WSL2 の Ubuntu のファイルシステム上にソースを配置して Ubuntu で作業したほうが少し便利になります。
:::

### 3.1 Gemfile

このテキストファイルの内容は以下の通りです。

```
source 'https://rubygems.org'
gem "github-pages", "~> 232", group: :jekyll_plugins
```

「232」は github-pages のバージョンで、対応するものを指定する必要があります。
[Dependency versions](https://pages.github.com/versions/) から調べて適切な値に変更してください。

### 3.2 _config.yml

このテキストファイルの内容は以下の通りです。

```
repository: user/repo
title: Sample
description: This is sample.
```

すでに _config.yml がある場合はそこに記述してください。

このファイルで GitHub Pages が自動追加する情報をローカルでも動作するように設定しています。
「user/repo」には GitHub のユーザー名、リポジトリ名を指定してください。おそらく生成する URL に使用されます。


### 4. Docker コンテナを作成して GitHub Pages をローカルで確認する

準備はできました。これらをローカルで変換してブラウザで確認できるように Docker を動かします。

わかりやすいので、コマンドラインで作業します。Docker Desktop がインストールされていればコマンドラインで docker コマンドが使用できます。
作業ディレクトリ (C:\Sample) に移動して、以下のコマンドを実行します。

PowerShell の場合
```
docker run --volume="$(pwd):/root/project:delegated" --publish 4000:4000 -ti mrseccubus/github-pages 
```

Ubuntu シェルの場合
```
docker run --volume="$PWD:/root/project:delegated" --publish 4000:4000 -ti mrseccubus/github-pages
```

しばらくビルド処理のログが流れたあと、成功すれば以下のメッセージでローカルWebサーバが起動した状態で止まります。

```
:
Auto-regeneration: enabled for '/root/project'
Server address: http://0.0.0.0:4000
Server running... press ctrl-c to stop.
```

:::note info
何らかのエラーが発生した場合、延々とビルドが繰り返されることがあります。このときは Ctrl+C を素早く2回押すことで停止します。
:::

この状態で、Webブラウザで http://localhost:4000 にアクセスして GitHub Pages と同じページが確認できれば成功です。わーい！

このあと index.md を編集してそれを反映させたい場合は Ctrl+C を押してください。再ビルドされるので、その後ブラウザを更新すれば反映されます。

このローカルサーバー (Docker コンテナ) を停止させるには Ctrl+C を素早く2回押してください。

:::note info
Ubuntu で実行させていると、ファイルが更新されると自動で再ビルドされるようで、ちょっと便利です。
:::

## おわりに

以上で最低限の動作確認方法となります。

作業ファイルが作られる、とか、毎回 docker run するとコンテナが増え続ける、とかありますが、別途対処してください。
Pythonを使って指定したフォルダ内のJSONファイルを整形する

# はじめに
最近、JSONファイルの内容を確認する作業がありましたが、ファイルの内容が1行で記述されていました。
ファイルが少なかったらVSCodeの拡張機能などでファイルを整形しても良いと思いますが、今回はファイルが多かったので、Pythonを使ってフォルダ内のJSONファイルを整形しました。

# コードの例
```python
import argparse
import json
import os


def main():
    parser = argparse.ArgumentParser(description="対象フォルダ内のJSONファイルを整形する")

    parser.add_argument("input", help="入力フォルダパス")
    parser.add_argument("-o", "--output", help="出力フォルダパス", default="./output")

    args = parser.parse_args()

    formatting_json(args.input, args.output)


def formatting_json(in_dir, out_dir):
    # 出力フォルダがない場合、自動生成
    os.makedirs(out_dir, exist_ok=True)

    # 入力フォルダ内のJSONファイルのみのファイル名一覧を取得
    file_name_list = [f for f in os.listdir(in_dir) if f.endswith(".json")]

    # 各JSONファイルを読み込んで、整形して出力する
    for file_name in file_name_list:
        # 入力ファイル
        src_file = open(
            os.path.join(in_dir, file_name),
            "r",
            encoding="utf-8",
        )

        # 出力ファイル
        dest_file = open(
            os.path.join(out_dir, file_name),
            "w",
            encoding="utf-8",
        )

        # JSONデータを読み込む
        json_data = json.load(src_file)

        # JSONデータを整形して出力
        dest_file.write(json.dumps(json_data, indent=2, ensure_ascii=False))

        src_file.close()
        dest_file.close()


if __name__ == "__main__":
    main()
```

# 実行例と結果
・実行例
```shell
python formatting_json.py input_folder -o output_folder
```

・入力されたJSONファイル
```json:input_folder/test1.json
{"list":[{"str":"test1","int":111,"bool":true},{"str":"test2","int":222,"bool":false}]}
```

・出力されたJSONファイル
```json:output_folder/test1.json
{
  "list": [
    {
      "str": "test1",
      "int": 111,
      "bool": true
    },
    {
      "str": "test2",
      "int": 222,
      "bool": false
    }
  ]
}
```
VSCode + git bashのやらかしを未然に防ぐ(1敗)

# 経緯
VSCode上で開発をしていて  
> npm run dev  

の実行結果がターミナルに残っていたので十字キー上を押して再度起動しようとコマンドを見ずにエンターしたら、
> git clean -df

が実行されて未追跡のファイルが全部吹き飛んだ。

:sob:
# 原因
VSCodeのターミナルに指定したgit bashは終了時に.historyを保存しないため、ターミナルを再起動したときのhistoryはピュアなgit bashの終了時のものになる。  
今回はsource treeのGUI上で不要な未追跡ファイル(間違った場所に生成してしまったnode_modulesなどなど)をまとめて消すのが手間だったためCUI上で作業していたコマンドが残っていたせいでこんなことになった。
# 再発防止対策
VSCode側のhistoryが保存されないのが問題なら保存されるようにしてしまえばいい。以下がとても参考になりました。  
https://qiita.com/misohagi/items/3ab0abc3bce2c11719c8
# 残った救い
VSCodeはファイルシステムに存在しないファイルがタブに存在する場合にファイルが見つからないエラーを表示するが、ファイルが消える際にそのタブがアクティブになっていればメモリ上には残っているので、そのまま保存すれば復元できる。GET KOTONAKI。
Arduino, Raspberry Pi, Raspberry Pi Pico,  M5Stack, micro:bit スペック表

|ボード名|Arduino UNO Rev3|Raspberry Pi 4 Model B|Raspberry Pi Pico|M5Stack BASIC|micro:bit V2|
|-|-|-|-|-|-|
|Soc, マイコン|ATmega328P|BCM2711|RP2040|ESP32|nRF52833|
|CPU|AVR シングルコア16MHz|Cortex-A72 クアッドコア 1.5GHz|Cortex M+ デュアルコア 133MHz|Xtensa LX6 デュアルコア 240MHz|Cortex-M4F シングルコア 64MHz|
|メインメモリー|2KByte|1G/2G/4G/8GByte|264KByte|520KByte|125KByte|
|フラッシュメモリー|32KByte|-|2MByte|16MByte|512KByte|
|SDカードスロット|-|microSD|-|microSD(16MByte以下)|-|
|os|-|Raspberry Pi OS/Ubuntu/OSMCなど|-|-|-|
|GPIOデジタル入力|14端子|26端子|26端子|15端子|19端子|
|GPIOアナログ入力(分解能)|6端子(10ビット)|-|3端子(12ビット)|2端子(10ビット)|6端子(10ビット)|
|GPIOハードウエアPWM|6端子(6ch)|4端子(2ch)|26端子(16ch)|15端子(16ch)|19端子(3ch)|
|GPIOアナログ出力|-|-|-|2端子|-|
|GPIO以外のインターフェイス|USB(USBシリアル)/ICSP|Micro HDMI×2/USB2.0×2/USB3.0×2/MIPI/DSI/コンポジット|USB1.1|Grove(I2Cのみ)/USB(USBシリアル)|USB2.0|
|オーディオ|-|ステレオジャック|-|スピーカー|スピーカー/マイク|
|ネットワーク機能|-|ギガビットイーサネット, IEEE802.11 b/g/n/ac, Bluetooth 5.0|-|IEEE802.11 b/g/n, Bluetooth 4.2|Bluetooth 5.1|
|表示装置|単色LED×1|-|単色LED×1|2インチ液晶ディスプレイ(320×240)|単色LED×1|
|搭載スイッチ|-|-|-|3個|2個|
|搭載センサー|-|-|-|-|加速度/地磁気/タッチ|
|動作電圧|5V|3.3V|3.3V|3.3V|3.3V|
|電源|5V(USB)/7〜12V(DCジャック)|5V(USB)|5V(USB/1.8〜5.5(VSYS)|5V(USB)/バッテリー搭載(110mAh)|5V(USB)/1.8〜3.6V(バッテリーコネクタ)|
|サイズ|74.9×53.3mm|85×56mm|51×21mm|54×54mm|51.6×42mm|
はじめての256timesをやってみました。

一日目は、マークダウン記法、テキストと文章のスタイリングを習いました。
二日目は、ボックスを移動させる方法とボックスのスタイリングの仕方を習い、この二日間習ったことを活かして自由にスタイリングしていいボックスを作って楽しかったです。