OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerでコンテナがどのネットワークに属しているのかを調べたい

# はじめに
この記事は、ほぼ自分のメモのための記事です。
ですが、自分と同じような悩みをお持ちの方はご参考にどうぞ。

# 本題
最近、システムで利用しているデータベースについて、

SchemaSpy

https://schemaspy.org/

を利用してDDLを作成しようと思ったのですが、「対象のコンテナがどのネットワークに属しているのかわからん。」

という事態になったので、調査のために以下のコマンドを作成しました。

```bash
docker network ls --format '{{.Name}}' | while read network; do
  echo "Network: $network"
  docker network inspect "$network" --format '{{range .Containers}}{{.Name}}{{"\n"}}{{end}}' | sed '/^$/d'
done
```


出力結果

```
Network: host
Network: hogehoge_default
Network: hogefuga_default
Network: fugafuga_default
fugafuga-web
fugafuga-redis
fugafuga-app
fugafuga-db
fugafuga-storage
```

これで、DDLを作成しようとしているDBコンテナが、「fugafuga_default」というネットワークに属していることがわかりました。

ネットワークに属しているコンテナが存在しないときは、何も表示されません。
例「hogehoge_default」

みなさんも、自分のDockerコンテナがどのネットワークに属しているのか知りたくなったときは利用してみてはいかがでしょうか。

以上です。
PNGからEPSへの変換方法

# はじめに

本記事ではpng画像をeps形式に手軽に変換するための手法について記します。このような変換が必要な理由として

- platex → dvips のワークフローでは PNG や JPEG は直接扱えず、「Cannot determine size of graphic in ～ (no BoundingBox)」というエラーが発生するが、epsファイルならコンパイルが通ること
- 論文を書くときに用いる図はepsファイルであることが多いこと

が挙げられます。

以下のtipsでは、pngを一つの要素としてしまうのでベクターのありがたみはなくなりますが、例えばレポートの体裁を整えるのに役立つでしょう。ただし論文に掲載する図としてpngを直接epsファイルにしたものを用いるのは好ましくない可能性があります。筆者はこの事情に詳しくありませんが、少なくとも直接ベクターファイルを作ってepsにするよう教育されました。分野ごとに文化が違う可能性もあるので専門家にルールを相談するべきです。

# 変換方法

PNG画像をEPS形式に変換する場合、ImageMagickの`convert`コマンドを実行することで変換が可能です。

~~~bash
convert hogehoge.png hogehoge.eps
~~~

もしコマンド実行時にエラーが発生する場合、ImageMagickのセキュリティポリシーが原因に挙げられます[^2]。特にImageMagick 6 系の場合、以下の設定ファイルを編集する必要があります。

`/etc/ImageMagick-6/policy.xml`

各々の環境でファイルの在処が違うかもしれないので、各自確認してください。ファイル内でEPSに対する権限を確認し、必要に応じて変更します。

## policy.xml の編集
### 1. ファイルの場所  
Debian/Ubuntu では `/etc/ImageMagick-6/policy.xml` などに配置されているはずですが、環境に応じて適切なパスを参照してください。
### 2. **該当行の確認**  
以下のような行があるはずです: 
~~~xml
<policy domain="coder" rights="read|write" pattern="PDF" />
<policy domain="coder" rights="read|write" pattern="PS" />
<policy domain="coder" rights="read|write" pattern="EPS" />
~~~
### 3. **コメントアウト:**  
nano などのエディタで管理者権限で開き[^3]、該当行を以下のようにコメントアウトします。
 ```xml
 <!-- <policy domain="coder" rights="none" pattern="EPS" /> -->
 ```
### 4. **保存後、変換を再試行:**  
`convert example1.png example1.eps` を実行し、問題なくepsが出力されることを確認してください。


# まとめ
本記事ではpng画像をeps形式に変換する方法について、
1. `convert hogehoge.png hogehoge.eps` コマンドでPNGからEPSへの変換が可能
2. 文句を言われたら`/etc/ImageMagick-6/policy.xml` を編集して必要な権限を付与する

という2つの手順にそって解説しました。

[^2]:筆者はここで躓いたので、この記事を書くことにしました。
[^3]:VSCodeを管理者権限で開こうとしてうまくいかず、この時はじめてnanoを使いました。
git rebase(既存のブランチをdevelopブランチから作成したようにする方法)

### ケース
昔branchAをdevelopから作成した
developブランチが他のブランチをマージまたはリベースで更新された。
branchAをdevelopにリベースしたい場合

---
いわゆる
```
* 639d8ax - (origin/develop, develop) authorA / commit message 
* 4e18fdx - authorA / commit message 
* a64267x - (origin/branchA, branchA) authorA / commit message 
```
を
```
* 4e18fdx - authorA / commit message 
* a64267x - (origin/branchA, branchA) authorA / commit message 
* 639d8ax - (origin/develop, develop) authorA / commit message 
```
にしたい(developブランチからbranchAが作成されているようにしたい)

---

```
git sw branchA
```

```
git rebase --onto origin/develop origin/develop branchA
```

```
git push origin branchA --force
```
---
### 補足
```
$ git log --no-merges --pretty=format:'%C(green)%h %C(reset)-%C(red bold)%d %C(blue)%an %C(reset)/ %C(reset)%s / %ad' --graph develop branchA
```
でgit treeを見られる
🎯 時間計算量と空間計算量について

# 🎯 概要

プログラムの処理効率を評価する際に重要なのが 時間計算量（Time Complexity） と 空間計算量（Space Complexity） です。

これらは、アルゴリズムが どれくらいの時間 や メモリ を消費するかを表します。

# 🎯 時間計算量（Time Complexity）

時間計算量は、入力のサイズ `n` が大きくなるにつれて、処理時間がどのように増加するかを示します。
一般的に Big-O 記法（O 記法） を使って表し、以下のようなパターンがあります。

| 計算量 | 計算時間の増え方 | 例 | 適用シーン |
|---|---|---|---|
| O(1) | 常に一定 | 配列のインデックスアクセス | どんな場合でも最速 |
| O(log n) | ゆっくり増える | 二分探索 | データ量が大きくても高速に処理可能 |
| O(n) | 線形に増える | 配列のループ | 要素をすべてチェックする場合 |
| O(n log n) | 線形より速く増える | クイックソート、マージソート | 効率の良いソート |
| O(n²) | 急激に増える | 二重ループ | 小規模なデータセットなら許容可能 |
| O(2ⁿ) | 爆発的に増える | 再帰的なフィボナッチ | `n` が大きくなると現実的に不可能 |

### 時間計算量の例とコード
#### O(1) - 定数時間
```python
# 配列の特定のインデックスにアクセスする（O(1)）
numbers = [10, 20, 30, 40, 50]
print(numbers[2])  # 30 を取得
```

#### O(log n) - 二分探索
```python
# 二分探索（O(log n)）
def binary_search(arr, target):
    left, right = 0, len(arr) - 1
    while left <= right:
        mid = (left + right) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    return -1
```

#### O(n) - 線形時間
```python
# 配列の全要素を走査する（O(n)）
numbers = [1, 2, 3, 4, 5]
for num in numbers:
    print(num)
```

#### O(n log n) - クイックソート
```python
# クイックソート（O(n log n)）
def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    return quick_sort(left) + middle + quick_sort(right)
```

#### O(n²) - 二重ループ（バブルソート）
```python
# バブルソート（O(n²)）
def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        for j in range(n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
```

#### O(2ⁿ) - 非効率なフィボナッチ
```python
# フィボナッチ数列（指数時間 O(2ⁿ)）
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)
```

# 🎯 空間計算量（Space Complexity）
空間計算量は、入力サイズ `n` に対して どれくらいメモリを使うか を示します。
これも Big-O 記法 で表現し、以下のようなパターンがあります。


| 計算量 | メモリ使用量の増え方 | 例 | 適用シーン |
|---|---|---|---|
| O(1) | 一定 | 単一の変数 | メモリを極力抑えたいとき |
| O(n) | 線形に増える | 新しいリストを作成 | 動的なデータ構造を扱う場合 |
| O(n²) | 急激に増える | 2次元配列 | 小規模なデータセットで使用 |

#### O(1) - 定数空間
```python
# 変数を1つしか使わない（O(1)）
def add(a, b):
    return a + b
```

#### O(n) - 線形空間
```python
# O(n) - 配列のコピー（入力サイズに比例してメモリを消費）
original_list = [1, 2, 3, 4, 5]
# 新しいリストを作成（元のリストと同じサイズのメモリを使用）
copied_list = original_list.copy()
print(copied_list)  # [1, 2, 3, 4, 5]
```

#### O(n²) - 2次元配列
```python
# O(n²) - 2次元配列（メモリ使用量が n × n に比例）
n = 3

# 3×3 の行列（すべて 0 で初期化）
matrix = [[0] * n for _ in range(n)]

# 出力して確認
for row in matrix:
    print(row)

# 出力結果:
# [0, 0, 0]
# [0, 0, 0]
# [0, 0, 0]
```
git switch/checkoutのタブ補完をローカルブランチだけにする方法

Git CLIで `checkout` や `switch` を利用する際に、ブランチ名をタブ補完で入力する方も多いと思います。

しかし、git の補完のデフォルトの挙動では、リモートリポジトリ上のブランチも含まれるため、タブを押すたびに大量の候補が表示されてしまうのが煩わしいと感じていました。

そこで補完候補をローカルブランチのみにする方法を探したところ、意外と簡単にできたため記事に残します。

（タブ補完の設定自体は他に様々な記事で説明されているため割愛します）

## 結論

環境変数に以下を追加する

```sh
GIT_COMPLETION_CHECKOUT_NO_GUESS=1
```

この設定はGit の補完スクリプトである `git-completion.bash` の[ソースコード](https://github.com/git/git/blob/master/contrib/completion/git-completion.bash)にコメントとして記載がありました。

結構重要な情報だと思うのですが、公式ドキュメントなど目立つところのでの記載は発見できませんでした。

`git-completion.bash`を利用している限り多くの環境で動作するのではないかと思います。\
（筆者の環境はmac×zshですが、内部的には`git-completion.bash`が利用されているようで、問題なく動作しました。）

## その他の補完関連オプション

ソースコードのコメントには他にもいくつかのオプションが記載されていたので、ついでにそちらも紹介します。

### 1. `GIT_COMPLETION_SHOW_ALL_COMMANDS=1`

通常は隠されているコマンドも候補に含まれるようになります。

例えば、ソースコードのコメントでは `cat-file` などのコマンドが表示される例として挙げられています。

### 2. `GIT_COMPLETION_SHOW_ALL=1`

通常は表示されないオプションも補完候補になります。

例えば、`git commit`の際の`--allow-empty` などのオプションが表示されるようになるとのことです。

### 3. `GIT_COMPLETION_IGNORE_CASE=1`

補完時に大文字小文字が区別されないようになります。

例えば `FOO` ブランチに切り替えたい時に、`git switch f<TAB>` と打つと `FOO`を補完してくれます。

## まとめ

筆者の開発チームでは命名規則上、ブランチ名が大文字から始まることが多く、特に`GIT_COMPLETION_IGNORE_CASE` が便利に感じました。シフトキーを押す必要がなくなるだけで、ちょっとしたストレスから解放されます。

良い Git ライフを！
GitLab CIで複数のバイナリをリリースする

GitLabでは、CIでビルドしたバイナリをReleaseとして管理することができます。
久しぶりにリリースを作ってみたら色々忘れていたので、備忘録を兼ねて書いてみることにしました。

環境は、GitLab CEを使っています。言うまでもないですが、以下に出てくるYAMLの設定は、`.gitlab-ci.yml`の設定になります。

## buildを行う

特に変わったことをすることはないのですが、artifactsを設定する必要があります。

```yaml
compile:
  stage: build
  script:
    - make build
  artifacts:
    paths:
      - bin/*.exe
    expire_in: 5 minute
```
`make build` すると、`bin/`以下に、Windows用のバイナリが作られるようにしています。

`artifacts`に以下の設定があります。
```yaml
  artifacts:
    paths:
      - bin/*.exe
    expire_in: 5 minute
```
`paths`には、artifactsに含みたいものがどこにあるのかを指定します。`expire_in`は、消していい時間ですが、今回、CIが動いている間だけの話(buildしてからの後述の作業が完了するまで)なので、5分もあれば十分です。

## Package Registoryに登録する

GitLabには、Registryの機能があり、コンテナレジストリなどと同列にパッケージレジストリがあります。
artifactsをパッケージレジストリに登録します。

```yaml
put_package_registry:
  stage: publish
  image: alpine:latest
  needs:
    - job: compile
      artifacts: true
  rules:
    - if: $CI_COMMIT_TAG # Run this job when a tag is created manually
  script:
    - echo "publish binary"
    - apk update && apk add curl
    - |
      find bin/ -name '*.exe' -printf "%P" | xargs -i curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file bin/{} ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/${CI_COMMIT_TAG}/{};
```

これで、`bin/`以下にある`*.exe`ファイルを、パッケージレジストリに登録できました。
実際に登録している処理は、以下ですね。
```sh
find bin/ -name '*.exe' -printf "%P" | \
xargs -i curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" \
              --upload-file bin/{} \
              ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/${CI_COMMIT_TAG}/{};
```

これが動くのは、`compile`が動いているのと、artifactsがあり、タグがついているのも条件です。
```yaml
  needs:
    - job: compile
      artifacts: true
  rules:
    - if: $CI_COMMIT_TAG # Run this job when a tag is
```

## リリースを作る

リリースを作るためのCIです。

```yaml
release_job:
  stage: release
  image: registry.gitlab.com/gitlab-org/release-cli:latest
  rules:
    - if: $CI_COMMIT_TAG # Run this job when a tag is created manually
  script:
    - echo "running release_job"
  release:
    name: "Release $CI_COMMIT_TAG"
    description: "Created using the release-cli $EXTRA_DESCRIPTION" # $EXTRA_DESCRIPTION must be defined
    tag_name: "$CI_COMMIT_TAG" # elsewhere in the pipeline.
    assets:
      links:
        - name: "For xxxxx"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/${CI_COMMIT_TAG}/xxxxx.exe"
        - name: "For yyyyy"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/${CI_COMMIT_TAG}/yyyyy.exe"
```

最後の`assets`で複数のバイナリを1つのリリースに含めています。単に、先程パッケージレジストリへのlinksをartifactsごとに複数書いているだけです。

```yaml
    assets:
      links:
        - name: "For xxxxx"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/${CI_COMMIT_TAG}/xxxxx.exe"
        - name: "For yyyyy"
          url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/${CI_COMMIT_TAG}/yyyyyy.exe"
```

ここだけは、手動で追加する必要がありますが、まぁ、やむなしかなと。もしくは、複数にするのではなくて、zipにして、一つにしてしまうとかもありでしょうが、今回はバラバラのほうが良かったので、こうなりました。
Gaussian で GPU を利用する方法

<h1>概要</h1>

Gaussian16 rev C.02 では GPU を用いることで計算速度の高速化が可能。<a href="https://gaussian.com/g16/gpus.pdf">公式のベンチマーク</a>によると、最大で 4 倍まで計算速度が向上する。

Gaussian16 rev C.02 がサポートしている GPU は、<strong>Ampere 世代</strong>まで。公式には<strong>データセンターシリーズ</strong>の GPU（例: A100、H100）しかサポートしておらず、<strong>GeForceシリーズ</strong>（例: RTX 4090）はサポートしてない。これは、Gaussian16 が <strong><span style="color:green">fp64</span></strong> という倍精度計算を実行するために<span style="color:red"> ECC メモリ</span>の VRAM が必要となることが理由。

<strong>プロフェッショナルシリーズ</strong>（例: RTX A6000）のサポートは、公式には明言されてないが、ECC メモリを搭載しているため Gaussian で利用することが可能。

「NVIDIA Ada Lovelace アーキテクチャ」（例: RTX 6000 Ada）も Gaussian16 rev C.02 で利用可能。

<h2>検証環境</h2>

CPU: Ryzen 9 9950X
CPU: RTX A4000
OS: Fedora 40 server Edition
Nvidia Driver: 550.120 （NVIDIA Ada Lovelace アーキテクチャでは、550.144.03）

nvidia driver のインストールは以下の通り。

```shell
sudo dnf update
sudo dnf install gcc g++
sudo dnf install kernel-devel kernel-headers dkms
sudo dnf install xorg-x11-server-devel libglvnd-devel pkgconf-pkg-config
sudo wget https://us.download.nvidia.com/XFree86/Linux-x86_64/550.120/NVIDIA-Linux-x86_64-550.120.run
sudo chmod 755 NVIDIA-Linux-x86_64-550.120.run
sudo ./NVIDIA-Linux-x86_64-550.120.run
```

kernel に関するエラーが出た場合は、再起動してからもう一度 nvida-driver のインストールを試す（バージョンが一致していないことが原因）。
NVIDIA driver をインストールしてから RTX A4000 を挿す。
UEFI(BIOS) の secure boot は OFF にする。

secure boot が ON だと以下のメッセージが出る場合がある。

```
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. 
Make sure that the latest NVIDIA driver is installed and running.
```

AsRock だと secure boot は boot オプションの項目内にある。
MSI の場合は、Setting > Advanced > Windows OS Configuration の中にある。

<h2>設定方法</h2>
<a span style:color="red">プロフェッショナルシリーズの GPU では、デフォルトでは VRAM の ECC が OFF になっている</a>ので、これを ON にする必要がある。

一般的には、以下のコマンドで ECC がどのような状態かを確かめるが、プロフェッショナルシリーズではうまく機能しない。

```shell
nvidia-smi -q | grep -i ecc
```

以下のコマンドで ECC を ON にし、再起動する。
（\<GPU_ID> の部分を nvidia-smi で確認した gpu の id 番号に変える。）

```shell
sudo nvidia-smi -i <GPU_ID> -e 1
sudo reboot
```

再起動後にもう一度 ECC を ON にするコマンドを実行すると、以下のメッセージが表示される。これで GPU の準備は完了。

```
ECC support is already Enabled for GPU 00000000:01:00.0.
All done.
```

<h2>インプットファイルの書き方</h2>

GPU を使用する際は、Gaussian のインプットファイルは以下のように書く。ここでのメモリ指定は、マザーボード上のメモリではなく、GPU の VRAM を指定する。VRAM の容量は、nvidia-smi コマンドで確認する。

```fortran
%CPU=0-15
%GPUCPU=0=0
%mem=14gb
%nosave
#p rb3lyp/6-31+G(d,p) force test scf=novaracc
```

<strong><注意点></strong>
%nproc と %GPUCPU は共存できない。
%GPUCPU を使う際は、必ず %CPU コマンドで CPU のコア数を指定する。

GPU 2 枚挿しの場合は、以下のように書く。

```fortran
%CPU=0-15
%GPUCPU=0,1=0,1
```

<h2>Gaussian16 rev C.02 の GPU ベンチマーク</h2>

test0397.com の計算レベルを rb3lyp/6-31+G(d,p) に変更したベンチマークテストの結果を以下に示す。

```fortran
Ryzen 9 9950x 16core + RTX A4000 0 枚：36 minutes 17.4 seconds.
Ryzen 9 9950x 16core + RTX A4000 1 枚：31 minutes 13.7 seconds.（約 1.16 倍）
Ryzen 9 9950x 16core + RTX A4000 2 枚：28 minutes 9.5 seconds.（約 1.29 倍）
```
alert実行時に背景が真っ黒になった問題について

## はじめに

PHPでフォームのバリデーションを実装している際、JavaScriptのalertでバリデーションメッセージを表示しようとしました。しかし、alertがページの読み込み完了前に実行されてしまい、背景が真っ黒になる問題に直面しました。この記事では、この問題の原因と、`window.onload`を用いて解決した方法について解説します。

## 問題の背景

フォーム送信後、PHP側でエラーが検出された場合、エラーメッセージをJavaScriptのalertで表示するために以下のようなコードを用意していました。

```php
<head>
   <!--（省略）-->
</head>

<?php
  // （省略）
  
  // jsにエラーメッセージを渡すようにエンコード
  $errorsJson = json_encode($errors, JSON_UNESCAPED_UNICODE);
?>
<script>
  let errors = <?php echo $errorsJson; ?>;
  if (Object.keys(errors).length > 0) {
    let errorMessages = "";
    
    for (let key in errors) {
      errorMessages += errors[key] + "\n";
    }
    alert(errorMessages);
  }
</script>

<body>
   <!--（省略）-->
</body>
```

## なぜページ読み込み前にalertが実行されるのか

基本的にプログラムは上から順番に実行されるため、このプログラムでは、php → javascript → htmlの順番で実行されています。そのため、bodyタグ内の要素などがまだ読み込まれていない状況でalertが発動するため、不自然な挙動となってしまいます。

## window.onloadでの解決方法

今回はこの問題の解決策として、**window.onload** を使用しました。`window.onload` はページ内の全てのリソース（画像、CSS、スクリプト等）が完全に読み込まれた後に実行されるため、alertの実行タイミングを適切に調整することができます。

修正後のコードは以下のようになります。

```php
<head>
   <!--（省略）-->
</head>

<?php
  // 
  $errorsJson = json_encode($errors, JSON_UNESCAPED_UNICODE);
?>
<script>
  // ページの読み込み完了後にalertを実行する
  window.onload = function() {
    let errors = <?php echo $errorsJson; ?>;
    if (Object.keys(errors).length > 0) {
      let errorMessages = "";
      for (let key in errors) {
        errorMessages += errors[key] + "\n";
      }
      alert(errorMessages);
    }
  }
</script>

<body>
   <!--（省略）-->
</body>
```

## まとめ

今回のケースでは、ページ読み込み前にalertが実行されるというタイミングの問題が発生しました。しかし、`window.onload`を使用することでリソースの読み込み完了を待ってからalertを表示することで、問題を解決することができました。
Linuxコマンド入門：`which` コマンド徹底解説：コマンドの場所を特定する方法についてまとめてみた

## はじめに

LinuxやmacOS、Windows（WSL）などのUnix系環境でコマンドを実行するとき、どのディレクトリにある実行ファイルが使用されるのかを確認したい場面があります。

:::note info
**その際に便利なのが **`which` コマンド** です。**
:::

`which` コマンドを使うと、コマンドの実体となる実行ファイルのフルパスを表示できます。

***本記事では、`which` コマンドの使い方や関連する環境変数について詳しく解説します。***

---

## 1. `which` コマンドとは？

`which` コマンドは、指定したコマンドがシステム内のどこに存在するかを確認するためのコマンドです。

具体的には、`PATH` 環境変数に登録されているディレクトリ内を検索し、一番最初に見つかった実行ファイルのパスを表示します。

### 基本構文
```bash
which [オプション] コマンド名
```

### 例
```bash
$ which python
/usr/bin/python
```
この場合、システムは `/usr/bin/python` にある `python` コマンドを実行していることがわかります。

**Macbookの実際のターミナル画面**

![Screenshot 2025-03-14 at 8.52.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/a792b8be-c8cb-4306-8ee8-8e2ef2c4c354.png)

---

## 2. `which` コマンドのオプション

### 1. `-a` オプション（すべてのパスを表示）

通常、`which` は最初に見つかったパスのみを表示しますが、`-a` オプションを付けると、PATH 内のすべての一致するパスを表示できます。

#### 例
```bash
$ which -a python
/usr/bin/python
/usr/local/bin/python
```
このように、複数のバージョンの `python` がインストールされている場合、それぞれのパスを確認できます。

### 2. `--help` オプション（ヘルプ表示）

`which` コマンドの使い方を確認したい場合は、`--help` を使用できます。

```bash
$ which --help
```

---

## 3. `which` を活用したトラブルシューティング

### 1. コマンドが見つからない場合

```bash
$ which mycommand
```
結果が何も表示されない場合、
- コマンドがインストールされていない
- `PATH` に正しく追加されていない
可能性があります。

### 2. 意図しないバージョンが実行される場合

複数のバージョンのプログラムが存在する場合、`which -a` で確認し、実行したいバージョンのパスを優先するように `PATH` を調整できます。

```bash
$ which -a python
/usr/bin/python
/usr/local/bin/python
```

この場合、
```bash
export PATH=/usr/local/bin:$PATH
```
のように優先順位を変更できます。

---

## まとめ

- `which` コマンドは、指定したコマンドがどこにあるかを確認するのに役立つ。
- `which -a` を使うと、すべての該当するパスを表示できる。
- `which` で見つからない場合は、`PATH` の設定を確認する。

`which` コマンドを活用して、コマンドの実行環境を正しく使ってみてください
【Windows】WSLのインストール

# 記事概要
WindowsでWSLを有効化する方法をまとめる。

# 前提
- PCはWindowsを使用している

# WSLとは
- 正式名称は、Windows Subsystem for Linux
- Windows上でLinux環境を実行できる機能

# 手順
1. 管理者権限で、コマンドプロンプトを起動する
     - sudoコマンドで権限昇格することも可能
1. 下記コマンドを実行する
    ```
    > wsl --install
    ```
1. PCを再起動する
1. コマンドプロンプトを起動する
1. 下記コマンドでWSLのステータスを確認する
    ```
    > wsl --status
    ```
1. Ubuntuをインストールする
    ```
    > wsl --install Ubuntu
    ```
1. Ubuntuを起動する
    - 初回のみ、ユーザー名とパスワードを決める必要あり
「円周率（π）の日」からチャレンジ！アカデミックユーザー無料のJMP Proでデータの世界を探求しよう

![Pi-in-the-Sky-II.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417820/7be888be-f7d5-4e28-8597-96f5c8d8b34e.jpeg)
（「Pi in the Sky II」by Micajah Bienvenu）

今日は「ホワイトデー」ですね。と同時に3月14日は世界で「円周率の日（Pi Day）」としても祝われているのをご存じでしょうか？

## 円周率の日（Pi Day）とは？
円周率の日は、1988年にアメリカの物理学者ラリー・ショー氏がサンフランシスコの科学博物館「エクスプロラトリアム」で初めて祝ったのが始まりとされています。以来、世界中の教育機関や数学愛好家たちが、この日を特別なイベントや活動で祝うようになりました。

世界の多くの国で、円周率（π）は、3.14159...であることから、3/14の1:59や15:09にお菓子のパイを食べたり（π [Pi] とパイ [Pie] は同音異義語ですしね）、ダーレン・アロノフスキー監督の「π」を鑑賞したりして（2022年の「ザ・ホエール」も個人的に大好きです！）、思い思いにこの日を過ごすようです。

また、この日は、アルベルト・アインシュタインの誕生日や、日本では「数学の日」（日本数学検定協会による）でもあります。

## JMP（ジャンプ）と「円周率（π）の日」
そして、私たちJMPにとっても「円周率の日」は大切な日なのです。円周率は小学生から大人まで多くの人に知られていますが、数学定数であるこの**円周率はソフトウェア開発においても重要な役割を果たしています**（米国ノースカロライナ州ケーリーのSAS本社には、冒頭画像にあるような巨大なπ [Pi]のオブジェが屋外に展示されているほどです）。

そのため、この日に3.14kmのランニングにチャレンジしたり、地元の教室で数学を教えたりして、ささやかながら「円周率の日」を祝うのは私たちJMPやSASの文化の重要な一部となっています。

## 統計ソフトJMPとは？
ところで、この記事を読んでいる方の中には「**JMPってなに？**」という人もいるかもしれません。そこで簡単に私たちの製品を紹介させてください。

[JMP](https://www.jmp.com/ja/home?utm_campaign=bl&utm_source=JMPblog&utm_medium=social)は、30年以上にわたってさまざまな業界で利用され続けている**統計解析ソフトウェア**です。プログラミング不要で、データの探索的分析や可視化を容易に行えるツールとして、多くの分野で活用されています。
![スクリーンショット 2025-03-11 141659.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417820/e295b904-492d-4046-b7e1-e8989067b9e9.png)

* 2025年1月時点の収益による上場企業

## JMPの教育分野での活用
また、JMPは教育分野においても広く利用されています。特に、今年から提供開始したアカデミックユーザー（学位を授与する高等教育機関に在籍している学生、教職員、研究者）向けの「[JMP Student Edition](https://www.jmp.com/ja/academic/jmp-student-edition?utm_campaign=bl&utm_source=JMPblog&utm_medium=social)」は、より高度な分析を実施できる[JMP Pro](https://www.jmp.com/ja/software/predictive-analytics-software?utm_campaign=bl&utm_source=JMPblog&utm_medium=social)を<font color="red">**無料で利用できます（12ヶ月ごとの更新が必要です）**</font>。

![スクリーンショット 2025-03-11 142531.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417820/5ecd1c65-1c55-4de9-bb1a-199e5be0c59d.png)

## 無料オンライン統計コース「STIPS」
さらに、統計的手法や思考プロセスを演習や小テストで理解度をチェックしながら学べる無料のオンライン統計コース「[STIPS（Statistical Thinking for Industrial Problem Solving）](https://www.jmp.com/ja/online-statistics-course?utm_campaign=bl&utm_source=JMPblog&utm_medium=social)」も提供しています。

これは、製造業のみならずさまざまな業界での問題解決における統計的思考の重要性を理解し、実践的なスキルを身につけるためのオンラインコースで、無料で利用可能です。

![スクリーンショット 2025-03-11 143243.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417820/68d44337-c8a2-4989-9af8-66d1c896c423.png)

このようにJMPは、製造、製薬、化学等さまざまな業界や教育機関での先端的な研究を長年にわたってサポートし続けています。

## まとめ
3月14日の「円周率の日」は、数学や統計に触れる絶好の機会です。この日をきっかけに、データ分析や可視化のスキルを高めてみてはいかがでしょうか。

JMPは、その直感的な操作性と強力な分析機能で、皆様のデータ分析の旅をサポートします！


:::note info
JMPの体験版はサンプルデータが豊富。30日間、すべての機能を無料で利用できます。

**<font color="orange">30日間全機能無料のトライアル版はこちら**</font>
https://www.jmp.com/ja_jp/download-jmp-free-trial.html?utm_campaign=bl&utm_source=JMPblog&utm_medium=social
:::
設定ファイルってなんだろな

## はじめに

こんにちは！みなさんは開発で設定ファイルを書くとき、どのフォーマットを使っていますか？🤔

JSON？YAML？それとも最近話題のTOML？

実は設定ファイルにはいろんなフォーマットがあって、それぞれ得意な分野があります！

今日は **JSON / YAML / TOML / ENV** の4つを中心に、それぞれの特徴を楽しく比較してみましょう！✨


## 🎯 まずはざっくり比較！

| フォーマット | 用途 | メリット | デメリット | 普及率 |
|-------------|-----|---------|-----------|------|
| **JSON** | API, Web設定, 構成管理ツール | 多くのツール・言語で標準対応 / 構造が明確 | コメント不可 / 可読性が低め | ★★★★★ (API, Web開発で広く使用) |
| **YAML** | CI/CD, コンテナ管理, DevOps | 可読性が高い / コメントが書ける | インデントミスがエラーに直結 / パースが遅め | ★★★★★ (CI/CDやDevOpsで定番) |
| **TOML** | シンプルな設定管理 (Rust, Python) | 可読性が高い / 型情報を持てる / シンプル | 対応ツールが少なめ / YAMLほど普及していない | ★★★☆☆ (Rust, Pythonで採用増) |
| **ENV** | 環境変数の管理 (.envファイル) | シンプルで直感的 / 環境変数に適している | ネスト構造が持てない / 型情報なし | ★★★★☆ (環境変数管理で広く利用) |


## 📝 それぞれの記述サンプル

### **🟢 JSON (JavaScript Object Notation)**
```json
{
  "database": {
    "host": "localhost",
    "port": 5432
  }
}
```
✅ **メリット**: 多くのツール・言語が標準対応！
❌ **デメリット**: コメントが書けない…

### **🔵 YAML (YAML Ain’t Markup Language)**
```yaml
database:
  host: localhost
  port: 5432
```
✅ **メリット**: 可読性が高く、コメントもOK！
❌ **デメリット**: インデントのミスでエラーに…

### **🟠 TOML (Tom’s Obvious, Minimal Language)**
```toml
[database]
host = "localhost"
port = 5432
```
✅ **メリット**: 可読性バツグン＆型サポートあり！
❌ **デメリット**: YAMLほど普及していない…

### **🟡 ENV (環境変数ファイル)**
```env
DB_HOST=localhost
DB_PORT=5432
```
✅ **メリット**: 超シンプルで環境変数管理に最適！
❌ **デメリット**: ネスト不可＆型情報なし…


## 🚀 どれを選ぶべき？

**用途別おすすめフォーマットはこちら！**👇

| 用途 | 推奨フォーマット |
|------|--------------|
| API / Web開発 | JSON |
| CI/CD, DevOps | YAML |
| シンプルな設定管理 | TOML |
| 環境変数管理 | ENV |

迷ったら、 **「YAML or JSON」** を選べば大体うまくいきます！

RustやPythonのプロジェクトなら TOML を試してみるのもアリ！


## 🎉 まとめ

✔ **JSON** → 標準的だけどコメント不可

✔ **YAML** → 読みやすいけどインデントに注意

✔ **TOML** → シンプル＆型サポートあり

✔ **ENV** → 環境変数の管理に最適！

みんなはどのフォーマットをよく使ってる？

**コメントで教えてね！** ✨💬

---

### 🙌 最後に…
「これ知らなかった！」「試してみる！」と思ったら、ぜひ **LGTM 👍 & ストック📌** よろしくお願いします！

ではまた！👋🚀
Linuxコマンド入門：Linux・macOS・WindowsでのPATHの確認方法と「command not found」の対処法をまとめてみた

## はじめに

この辺りの仕組みがまったく理解できずに苦しい思いをしたが、わかると楽しくなってきたので書きました。

:::note info
*****PATH**（パス）は、Unix系OS（LinuxやmacOS）やWindowsにおいて、コマンドを実行する際に参照される環境変数の一つです。***
:::

PATHに設定されているディレクトリの中にあるプログラムやスクリプトは、フルパスを指定しなくても直接実行できます。

## 1. PATHの仕組み

PATH変数には、実行可能なファイルが格納されているディレクトリのリストが**コロン（:）**（Windowsではセミコロン（;））で区切られて登録されています。

コマンドを実行すると、シェルはPATHに登録されたディレクトリを順番に検索し、最初に見つかった実行ファイルを実行します。

### 例（Linux/macOS）
```bash
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
```

**Macbookの実際のターミナル画面**

```sh
/usr/local/opt/bind/sbin:/Applications/Visual Studio Code.app/Contents/Resources/app/bin:/Users/hondaakiratarou/.nvm/versions/node/vxx.x.x/bin:/Library/Frameworks/Python.framework/Versions/x.xx/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/private/var/folders/wm/xx_xxxxxxx/xxxxxxxxxxxxxxxxxxxxxx/T/AppTranslocation/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/d/iTerm.app/Contents/Resources/utilities:/usr/local/go/bin
```

この場合、コマンドが実行される際には以下のディレクトリ順に検索されます。
1. `/usr/local/bin`
2. `/usr/bin`
3. `/bin`
4. `/usr/sbin`
5. `/sbin`

## 2. PATHの確認方法

### Linux/macOS
```bash
$ echo $PATH
```

### Windows（PowerShell）
```powershell
PS C:\> echo $env:PATH
```

## 3. PATHの変更方法

### 一時的な変更（カレントシェルのみ適用）
PATH変数にディレクトリを追加することで、新しいコマンドをフルパスなしで実行できるようになります。

#### Linux/macOS
```bash
$ export PATH=/home/user/mybin:$PATH
```

#### Windows（PowerShell）
```powershell
PS C:\> $env:PATH = "C:\\mybin;" + $env:PATH
```

この変更は**現在のターミナルセッション**でのみ有効です。

### 永続的な変更（再起動後も適用）
システムの設定ファイルに記述することで、ログイン時に自動適用されます。

#### Linux/macOS
ホームディレクトリの`~/.bashrc`や`~/.zshrc`に以下を追加：
```bash
export PATH=/home/user/mybin:$PATH
```
変更を適用するには：
```bash
$ source ~/.bashrc  # または ~/.zshrc
```

#### Windows
環境変数を恒久的に変更するには、**システム環境変数**を編集します。
1. 「システムのプロパティ」を開く
2. 「詳細設定」タブの「環境変数」を選択
3. 「システム環境変数」または「ユーザー環境変数」の`Path`を編集

## 4. PATHのトラブルシューティング

### 1. コマンドが見つからない（`command not found` エラー）
- コマンドがインストールされていない
- PATHにコマンドのディレクトリが登録されていない

### 2. コマンドのバージョンが意図しないものになる
- PATHに複数の同名コマンドが存在し、異なるバージョンが先に見つかる
- `which` コマンドで確認可能
```bash
$ which python
/usr/bin/python
```

### 3. PATHの順番を調整する
最優先にしたいディレクトリを前に追加すると、優先度を変更できます。
```bash
$ export PATH=/opt/custom/bin:$PATH
```

## まとめ
- **PATHはコマンドを検索するディレクトリのリスト**
- `echo $PATH` で確認できる
- `export PATH=/new/path:$PATH` で一時的に変更可能
- `.bashrc` などに追加すると永続化できる
- `which コマンド名` で優先される実行ファイルを確認できる

PATHを理解し適切に設定することで、開発環境を快適にカスタマイズできますので、確認してみてくださ！
JavaScriptの基礎（4）

※この記事は初学者の毎日のアウトプット用に作成している記事です

## 演算子

### 算術演算子
| 演算子 | 使用例 | 働き |
|:-:|:-:|:-:|
| + |  a + b |  a足すb　文字列結合も可能 |
| - |  a - b |  a引くb |
| * |  a * b |  a掛けるb |
| / |  a / b |  a割るb |
| % |  a % b |  a割るbの余り |
| ** |  a ** b | aのb乗  |

### インクリメント・デクリメント
`++`や`--`を変数前後につけると変数の値に1を足したり引いたりする
```javascript
let a = 5;
let b = a++; // bに5が代入された後にaが6になる

console.log(a); // 6
console.log(b); // 5


let c = 5;
let d = c--; // dに5が代入された後にcが4になる

console.log(c); // 4
console.log(d); // 5
```

### 比較演算子
| 演算子 | 使用例 | 働き |
|:-:|:-:|:-:|
| ==     | a == b   | a と b が等しいと見なせるなら true（型が異なっても値が等しければ true）。そうでなければ false を返す。 |
| ===    | a === b  | a と b が厳密に等しいなら true。そうでなければ false を返す。 |
| !=     | a != b   | a と b が異なると見なせるなら true（型が異なっても値が異なれば true）。そうでなければ false を返す。 |
| !==    | a !== b  | a と b が厳密に異なるなら true。そうでなければ false を返す。 |
| >      | a > b    | a が b より大きければ true。そうでなければ false を返す。 |
| <      | a < b    | a が b より小さければ true。そうでなければ false を返す。 |
| >=     | a >= b   | a が b 以上なら true。そうでなければ false を返す。 |
| <=     | a <= b   | a が b 以下なら true。そうでなければ false を返す。 |

### 論理演算子
| 演算子 | 使用例 | 働き |
|:-:|:-:|:-:|
| &&     | a && b   | a が true で、かつ b も true なら true。そうでなければ false を返す。 |
| \|\|   | a \|\| b  | a が true または b が true なら true。そうでなければ false を返す。 |
| ??     | a ?? b    | a が null または undefined の場合に b を返す。それ以外の場合は a を返す。 |
| !      | !a        | a が true なら false を、a が false なら true を返す。 |

## 代入
・複数の変数を一行で宣言・代入
```javascript
let a = 1, b = 2, c = 3;

console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
```
<br>

・配列の各項目を別々の変数に代入
```javascript
let arr = [10, 20, 30];

// 配列の項目を個別の変数に代入
let [x, y, z] = arr;

console.log(x); // 10
console.log(y); // 20
console.log(z); // 30
```
<br>

・オブジェクトのプロパティを別々の変数に代入
```javascript
let person = {
  name: "John",
  age: 30,
  city: "New York"
};

// オブジェクトのプロパティを個別の変数に代入
let { name, age, city } = person;

console.log(name); // John
console.log(age);  // 30
console.log(city); // New York
```
<br>

・変数の値を入れ替える
```javascript
let a = 5;
let b = 10;

// 値を入れ替える
[a, b] = [b, a];

console.log(a); // 10
console.log(b); // 5
```
<br>

### スプレット構文を使った代入
スプレッド構文 (...) は、配列やオブジェクトの要素を別の配列やオブジェクトに展開（コピー）するための構文
```javascript
const arr = [1, 2, 3, 4, 5];

// 配列の最初の2つの要素を個別の変数に代入し、残りの要素を rest 配列にまとめる
const [first, second, ...rest] = arr;

console.log(first);  // 1
console.log(second); // 2
console.log(rest);   // [3, 4, 5]
```
<br>
参考書籍：

https://www.amazon.co.jp/%E3%81%93%E3%82%8C%E3%81%8B%E3%82%89%E3%81%AEJavaScript%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E7%8B%A9%E9%87%8E-%E7%A5%90%E6%9D%B1/dp/481561802X
wslでelixir その160

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
練習問題やってみた。


# 練習問題
Livebookの、kino.jsで、じゃんけんを書け。

# setup
```
Mix.install([
  {:kino, "~> 0.15.0"}
])
```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/4bec5858-c55c-4ae2-9b52-416813c7eaf5.png)


# サンプルコード

```
defmodule Janken do
	def hand(c) do
		cond do
		c == 0 ->
			"グー"
		c == 1 ->
			"チョキ"
		c == 2 ->
			"パー"
		:else ->
			"うそ"
		end
	end
	def judge(a, b) do
		cond do
		a == b ->
			"あいこ"
		a == 0 && b == 1 ->
			"あなたの勝ち"
		a == 1 && b == 2 ->
			"あなたの勝ち"
		a == 2 && b == 0 ->
			"あなたの勝ち"
		a == 0 && b == 2 ->
			"あなたの負け"
		a == 1 && b == 0 ->
			"あなたの負け"
		a == 2 && b == 1 ->
			"あなたの負け"
		end
	end
	def pon(a) do
		res = ""
		{a, _} = a
			|> Integer.parse()
		res = res <> hand(a) <> "と"
		b = 0..2
			|> Enum.random()
		res = res <> hand(b) <> "で、"
		res = res <> judge(a, b)
		res
	end
end


defmodule KinoHTML.Janken do
	use Kino.JS
	use Kino.JS.Live
	def new(ans) do
		Kino.JS.Live.new(__MODULE__, ans)
	end
	def init(ans, ctx) do
		{:ok, assign(ctx, ans: ans)}
	end
	def handle_connect(ctx) do
		{:ok, ctx.assigns.ans, ctx}
	end
	def handle_event("gu", _, ctx) do
    ans = Janken.pon("0")
		{:noreply, res(ctx, ans)}
	end
	def handle_event("choki", _, ctx) do
    ans = Janken.pon("1")
		{:noreply, res(ctx, ans)}
	end
	def handle_event("pa", _, ctx) do
    ans = Janken.pon("2")
		{:noreply, res(ctx, ans)}
	end
	defp res(ctx, ans) do
		broadcast_event(ctx, "update", ans)
		ctx
  end
	asset "main.js" do
		"""
		export function init(ctx, ans) {
			ctx.root.innerHTML = `
				<div id="ans"></div>
				<button id="bt0">グー</button>
				<button id="bt1">チョキ</button>
				<button id="bt2">パー</button>
			`;
			const ansEl = document.getElementById("ans");
			const bt0 = document.getElementById("bt0");
			const bt1 = document.getElementById("bt1");
			const bt2 = document.getElementById("bt2");
			ansEl.innerHTML = ans;
			ctx.handleEvent("update", (ans) => {
				ansEl.innerHTML = ans;
			});
			bt0.addEventListener("click", (event) => {
				ctx.pushEvent("gu");
			});
			bt1.addEventListener("click", (event) => {
				ctx.pushEvent("choki");
			});
			bt2.addEventListener("click", (event) => {
				ctx.pushEvent("pa");
			});
		}
		"""
	end
end

KinoHTML.Janken.new("じゃんけん、しよ")

```

以上。
MediaWikiベースのWikiページをダンプする

# MediaWikiとは？
MediaWikiとは、WikipediaのようなWikiページを書くために作られた
PHP製のソフトウェアです。このソフトウェアは無料で公開されており、
誰でもMediaWikiを使ってWikiを作れます。

# ダンプする
今回、MediaWikiベースのページをダンプする方法を見つけたので、
それをメモも兼ねて紹介します。

ダンプとは、MediaWikiでは記事などのデータをまとめて保存する
操作のことを指します。
(ダンプは、サーバーの管理者しかできない操作です。)
ダンプされたデータを公開しているWikiもあります。

https://dumps.wikimedia.org/jawiki/latest/

(これは、Wikipediaの日本語記事がダンプされたものです。)

しかし、ダンプをしていない、あるいはダンプしたファイルを
公開していないWikiも数多くあります。(多分)
そこで使うのがこれです！

https://github.com/mediawiki-client-tools/mediawiki-dump-generator/tree/python3

これを使用すると、MediaWikiページをダンプすることができます。

# 使ってみよう
どうやら、Pythonが新しすぎる(3.12など)と、動かないようで、
投稿主はAnaconda上にPython3.8を構築して動かしました。
(3.9も動くか怪しい)

基本的には、Installationを読み進めればいけると思いますが、
一応ここにも書きます。

### 1.作業フォルダにクローンする
```sh
git clone https://github.com/mediawiki-client-tools/mediawiki-dump-generator
```

### 2.ビルドする
```sh
pip install poetry
cd mediawiki-dump-generator # さっきクローンしたところに移動
poetry update && poetry install && poetry build
pip install --force-reinstall dist/*.whl
```

## 使用方法
```
dumpgenerator http://<保存したいWikiのURL> --xml
```

### オプション
```--xml```: xml形式で保存する時に指定

```--curonly```: 記事の最新版のみ保存する

```--api http://<<保存したいWikiのURL>>/path/to/api.php```:
記事をダンプするのにMediaWiki APIというものを使っていて、
APIが見つからないエラーの時は手動でAPIのパスを指定する必要がある。
デフォルトでは、```http://<<保存したいWikiのURL>>/w/api.php```

```--path /<保存先のパス>```: ダンプ結果の保存先フォルダ

```--namespaces 0```: ダンプする記事の名前空間を指定
通常の記事は0番なので、記事だけを保存したければ0を指定

```--exnamespaces 1,2,3,4,5,6```: 除外する名前空間を指定

```--force```: 前回の実行結果を再開せず、強制的にダンプする

```--images```: 画像を保存する場合に指定

# 終わり
最後まで読んでいただきありがとうございました。
GPT-4.5のいいところを探してみた


## はじめに

GPT-4.5がリリースされてしばらく経ちました。
今回はGPT-4.5を実際に使ってみて感じたポイント3点のみに絞って、短めに紹介します。

## 1. 感情的知性（EQ）の向上

先日、ジブリの「ゲド戦記」をはじめて鑑賞しました。

その挿入歌「テルーの唄」に感動したので、GPT-4.5 と o1 pro に共感を求めるため同じ質問をしてみました。

■質問

> （テルーの唄について）私の主観ですが、鷹は本来強い鳥の象徴のように感じていました。

■GPT-4.5 回答

> 「**あなたの感覚は鋭いと思います。**...あなたの「鷹＝強い鳥」という主観はまさに的を射ていて、この詩が持つ奥深さの本質をより引き立てる視点です。強さと孤独、自由と悲しさが共存するところに、この詩の本質的な魅力がありますね。」

■o1 pro 回答

> 確かに一般的に「鷹」というと、鋭い目や力強い翼といった「強さ」を象徴する鳥というイメージがありますよね。ところが、この歌詞では「鷹」であるにもかかわらず“孤独や休まることのない悲しみ”が強調されているのが印象的です。以下、その背景と意味合いについて考えられるポイントを挙げてみます。

o1 proの回答は、まとめ記事っぽくて感情移入しづらい。
GPT-4.5の回答は、丁寧な話し言葉。

回答の意味合いには大きな差は感じないものの、o1 proの回答よりもGPT-4.5の回答の方が、**話のトーンに合わせて物腰柔らかい感じで筆者の発言に自然に共感**してくれて、**読んでいて気持ちよくなってしまいます**。

このように、GPT-4.5は感情やニュアンスを繊細に捉え、ユーザーに共感を伝える能力が向上していることがわかりました。

全文については、ぜひ以下の会話を確認してみてください。

「テルーの唄」についての会話
- GPT-4.5: https://chatgpt.com/share/67d19bba-d0b0-8011-b972-21267eb02e0d
- o1 pro: https://chatgpt.com/share/67d19bc7-597c-8011-8c8c-45095a5c554e

## 2. システムアーキテクチャ

> GDPRに対応したWebアプリケーションのシステムアーキテクチャを出力してください。
> これを実現するAWSの構成図を作成してください。

```mermaid
graph TD
  %% ユーザーとインターネット層
  User[ユーザー] -->|HTTPS| Route53[Route 53 DNS]
  Route53 --> CloudFront[CloudFront CDN]

  %% ALBとアプリケーション層
  CloudFront --> ALB[Application Load Balancer]
  ALB --> ECS[ECS Fargate or EKS Cluster]

  %% ECSからデータベース、ストレージへ
  ECS --> RDS[Amazon RDS Aurora 暗号化DB]
  ECS --> S3[Amazon S3 暗号化ストレージ]

  %% セキュリティと監査
  ECS --> CloudWatch[CloudWatch 監視]
  ECS --> CloudTrail[CloudTrail 監査ログ]
  ECS --> KMS[AWS KMS 鍵管理]
  CloudFront --> WAF[AWS WAF 攻撃防御]

  %% GDPR関連
  Artifact[AWS Artifact GDPR コンプライアンス文書]

  %% 配置リージョン
  subgraph EU Region
    ALB
    ECS
    RDS
    S3
    KMS
    CloudWatch
    CloudTrail
  end

  %% AWS 外部サービス
  subgraph Global
    Route53
    CloudFront
    WAF
    Artifact
  end
```

最低限の要件を満たしていそうな図が出力されました。

https://chatgpt.com/canvas/shared/67d267771744819180d62cd1930f58cc

## 3. SVG

■システムアーキテクチャ

まずは先ほど検証したシステムアーキテクチャについてsvgにしてみる

> このシステムアーキテクチャをsvgにしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308256/b2088f6d-ea9a-486b-969a-386d0b7e2e4e.png)

mermaidをsvgにするのはすぐにできそう。


■幾何的な図形

まずはうまくいきそうな幾何的な図形から検証。

> 70m2、3LDKの新築マンションの間取りをsvgで出力してください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308256/f9203544-70db-42b6-a40c-3377d7d9a6c5.png" width="350" alt="test_2_svg">

廊下のことまで考えれていないので、World Model はそこまでしっかりしていなさそうだが、畳に合わせて広さが変わっているので、そこそこいい感じでは？

■犬

> ボストンテリアをsvgで出力してください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308256/f5a02ec8-3203-400e-9099-90fdf4d0eb40.png" width="150" alt="test_2_svg">

■キャラクター

> 鬼滅●刃の炭●郎をsvgで出力してください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308256/db18dc84-9ad9-4f96-8412-eb5465ea3824.png" width="150" alt="test_2_svg">



## まとめ

GPT-4.5 はエンジニア視点では大きく進歩したと感じづらいモデルになっているかと思いますが、使ってみて特に感情的なコミュニケーション能力が優れていると感じました。

このモデルを使ったAIエージェントが開発されるとどうなるのだろうと、今後が楽しみです。

---
### 会社紹介

**株式会社 Mosaica**  
最先端テクノロジーで社会課題を解決し、持続可能な未来を創造する IT カンパニー。
AI ソリューション、クラウド統合、DX 推進、経営コンサルティングなど包括的なサービスでビジネス変革を支援しています。  

詳しくは [公式サイト](https://mosaica.co.jp/) までお気軽にご相談ください。
公式サイト： https://mosaica.co.jp/
家計簿アプリを作る＃１６

![スクリーンショット 2025-03-14 064736.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/57feaed0-7484-4994-a0cf-98365d03c9a2.png)
サイドバーの中には、モバイル用とPC用のDrawerがあります。

![スクリーンショット 2025-03-14 064846.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/3b720d95-2357-4680-a58f-750f29fdf8ab.png)
Drawerは、👆を押したときに現れるものです↓
![スクリーンショット 2025-03-14 065018.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/db78c455-1948-4943-954d-7f21a63af9b3.png)
ネットワーク入門：なぜ「localhost」が必要なのか？ 仕組みとメリットを解説してみた

## はじめに

Localhost（ローカルホスト）は、コンピューターが自身を指す特別なホスト名です。通常、「127.0.0.1」というIPv4アドレス、または「::1」というIPv6アドレスに解決されます。

これは、ネットワークインターフェースを経由せず、ローカルマシン内で直接通信を行うために使用されます。

---

## 書こうと思ったきっかけ

多くの開発者やエンジニアが日常的に`localhost`を使用していますが、その動作原理や活用方法について詳しく理解していないケースも少なくありません。

特に、Web開発やサーバー設定を行う際に`localhost`が正しく動作しない場合、問題の切り分けや解決に時間がかかることがあります。

:::note alert
***また、最近ローカル環境でアプリケーションを動作させる機会が増え、改めて`localhost`の重要性を感じるようになりました。***
:::

この機会に、`localhost`の基本から活用方法、トラブルシューティングまでを整理し、多くの人が活用できるようにまとめようと思いました。

---

## Localhostの主な用途

1. **開発環境のテスト**
   - Web開発者やアプリケーション開発者は、サーバーアプリケーションをローカル環境で動作確認する際にlocalhostを使用します。
   - 例えば、FlaskやDjangoなどのWebフレームワークでは、`http://127.0.0.1:5000/` のようなローカルサーバーを立ち上げることができます。

2. **ネットワーク設定の検証**
   - `ping 127.0.0.1` を実行すると、コンピューターのネットワークスタックが正常に動作しているか確認できます。
   - ファイアウォールやネットワークフィルタの設定確認にも利用されます。

3. **データベースやAPIのローカル接続**
   - MySQLやPostgreSQLなどのデータベースをローカルで動作させる際に`localhost`を指定することで、外部接続を避けることができます。
   - `mysql -u root -p -h localhost` のようなコマンドがよく使用されます。

4. **セキュリティ上の隔離環境**
   - `localhost`を利用することで、外部からのアクセスを防ぎつつ、ローカルでのみ動作する環境を作れます。
   - 例えば、開発中のアプリケーションを外部に公開せずにテストできます。

---

## Localhostの動作原理

Localhostの仕組みは、ホスト名解決の一環として「hosts」ファイルに定義されています。
通常、LinuxやmacOSでは`/etc/hosts`、Windowsでは`C:\Windows\System32\drivers\etc\hosts`に次のような記述があります。

```
127.0.0.1   localhost
::1         localhost
```

この設定により、`localhost`というホスト名を使うと、自動的に「127.0.0.1」または「::1」に変換され、ループバック通信が行われます。

**実際に確認してみた**

![Screenshot 2025-03-14 at 6.36.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/0224eaf1-3cbd-474d-a9ea-10e80942ed37.png)

---

## Localhostを利用するメリット

- **外部ネットワークに依存しない** → インターネットやLAN接続なしでもテストや開発が可能。
- **高速な通信** → 外部ネットワークを経由しないため、遅延がほとんどない。
- **セキュリティリスクの低減** → 外部に公開しないため、攻撃のリスクが低い。
- **簡単な設定** → 特別な設定なしで利用可能。

---

## Localhostのトラブルシューティング

1. **Localhostにアクセスできない**
   - `hosts` ファイルの設定を確認（特に`127.0.0.1 localhost` の記述をチェック）。
   - サーバープロセスが起動しているか確認（例：`netstat -tulnp` でポートのリスニング状態を確認）。

2. **特定のポートが動作しない**
   - ファイアウォールの設定を確認（例：`sudo ufw allow 8000` でポート8000を許可）。
   - 別のプロセスがポートを占有していないか確認（例：`lsof -i:8000`）。

3. **ブラウザでlocalhostが開けない**
   - サーバーが正しいポートでリスニングしているか確認（例：`flask run --host=127.0.0.1 --port=5000`）。
   - キャッシュやブラウザの設定を見直す。

---

## まとめ

Localhostは開発やネットワークテストに欠かせない便利な仕組みです。

:::note warn
**特にWeb開発やデータベース管理の分野では、ローカル環境での動作確認に広く活用されています。**
:::

適切に理解し、活用することで、より効率的な開発やトラブルシューティングが可能になります。
現場で役立つシステム設計の原則 Chapter 4 ドメインモデルの考え方で設計する

## ドメインモデルの考え方を理解する

### ドメインモデルとデータモデルにおけるクラスの責務の違い

ドメインモデル

- データをそのまま入出力するのみではない
- データを求められる情報へと計算・判定・加工を行った上で出力する
- そのためのメソッドを持つ

データモデル

- データの保持と入出力のみ行う
- そのためのセッターとゲッターを持つ

### ドメインモデルではコードの重複が減る

- ドメインモデルではデータの計算・判定・加工をデータを保持するオブジェクトに任せられるため、そのためのロジックもそこに集約される
- しかし、データモデルでは、計算・判定・加工を他オブジェクトが行うため、ロジックが分散し、その結果重複も発生する。

## ドメインモデルをどうやって作っていくか

### 業務フロー図

- 業務プロセスや処理の流れの表現
- 実際の業務プロセスが正しいかどうか、業務の抜け漏れがないか、システム化範囲を検討するために使われる
- 業務活動を表現するため、「注文する」「出荷を指示する」「支払う」など、具体的な業務活動や処理を示す
- ここでは活動そのものが焦点となり、パッケージ図のようにオブジェクト構造やシステム内部の要素の名前が出てこない場合がある

### パッケージ図

- システム内部構造・依存関係の表現
- システム構造や依存関係を整理して理解するために使われる
- システム内の具体的なクラスやオブジェクトのまとまりを示す

### 業務フロー図からパッケージ図へ

- ドメインモデルを忠実にオブジェクト指向で設計すると、**業務フロー図（業務プロセスの流れ）とパッケージ図（プログラムの構造）**は、最終的に非常によく似た形になってくるのが自然
  - ドメインモデルとは、実際の業務をそのままプログラム構造に落とし込んだものである
  - オブジェクト指向設計の本質は「現実世界のモデルをプログラムに反映させる」ことであるため、業務の流れが忠実に再現されていれば、プログラムの設計は必然的に業務の流れと似たものになる

1. まずは業務フロー図を作成して、大きな流れを整理する
2. それを元に徐々に粒度を細かくしていき、見落としていた業務やオブジェクトを発見する
3. こうして明確化した詳細な業務を元にパッケージ図を作成し、プログラム設計を行う

## ドメインオブジェクトの見つけ方

### 業務の関心ごとはヒト・モノ・コト

- 業務の関心ごとはヒト・モノ・コトの３つに分類される。
- これらがどのように関連しているかを明らかにすることで適切にドメインモデルを設計することができる。
- コトに注目する
  - コトはイベント、事象、段階、フェーズなどに相当するものである。
  - コトの上にヒトやモノが存在するので、コトがどのように関係し合っているのかを整理することが全体像を把握する上で重要である。
- モノの差異の重要性
  - モノには、予定と実績の間に差異が発生する場合がある。
  - 差異は重要なものである
    - 差異が問題となり、その時点で特別な対応が必要になる場合がある
    - 後々問題が発覚し、その原因を探るために過去の差異が必要になる場合がある
- ドメインモデルにおける判定ロジック
  - 手続き型のトランザクションスクリプトでは、判定ロジックが入れ子構造になりがちで、複雑になりやすい
  - オブジェクト指向ドメインモデルでは、判定ロジックをドメインオブジェクトとして独立させるため、常にシンプルな構造になる
  - 判定ロジックを担うドメインオブジェクトはコトに相当する

## 業務の関心ごとの基本パターンを覚えておく

### ドメインオブジェクトの基本の設計パターン

ドメインオブジェクトは、大まかに４種類に分類することができる

- 値オブジェクト
- コレクションオブジェクト
- 区分オブジェクト
- 列挙型の集合操作

### 業務の関心ごとのパターン

業務の関心ごとは、主に次の４つのパターンに分類される

- 口座(Account)パターン
- 期日(Date)パターン
- 方針(Policy)パターン
- 状態(State)パターン

## 業務の理解がドメインモデルを洗練させる

### 業務知識の暗黙値

ドメインモデルを正確に設計するためには、その業界の暗黙値をも把握する必要がある。
暗黙値とは、専門家がそれまでの経験から感覚的に体得してきた言語化されていない知識のことである。
暗黙値を把握するには、専門家と会話するしかない。
会話の中で登場する違和感や聞き慣れない言葉が暗黙値の発見につながる。

### 相手の反応を見る

業務の関心ごとを適切にキャッチし、会話の中で適切に扱うことができるようになると、専門家の反応はよくなる。
逆に、反応が悪かったり、怪訝な雰囲気を感じたら、それは業務の関心ごとを適切にキャッチできていないということであ。
もし、そんな雰囲気を感じたら、言葉の使い方や言い回しを変えてみよう。
相手の反応が良くなってきたら、業務の関心ごとの理解が進んでいる証拠だ。

### まとめ

開発者が特定の業界向けシステムのドメインモデルを適切に設計するためには、その業界の基礎知識はもちろん、暗黙知をも適切に把握する必要がある。
暗黙知とは、専門家がそれまでの経験から感覚的に体得してきた言語化されていない知識のことである。
これらの把握の具合は、会話をする上での専門家の反応や表情から測ることができる。
相手の反応が悪かったり、怪訝な表情が見えたら、それは業務の関心ごとを適切にキャッチできていないことを示している。
そういった場合は、言葉の使い方や言い回しを変えたり、あやふやな箇所を深掘りしたりすることで理解を深めていくようにする。
classvalidatorが正常に働くために

とりまバリデーションパイプをグローバルにかけるのを忘れずに
```typescript:main.ts
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe({
    whitelist: true,
    forbidNonWhitelisted: true,
    transform: true,
  }));
  await app.listen(3001);
```
<dl>
    <dt>whitelist<dt>
    <dd>trueなら、デコレータのついてないプロパティ削除。デコレータの必要ないプロパティが消されないよう、いらなくても@Allowをつけよう。<dd>
    <dt>forbidNonWhitelisted<dt>
    <dd>tureで上記の設定で消されるプロパティを、削除せずエラーを吐くようにする<dd>
    <dt>transform<dt>
    <dd>trueで受け取ったDTOを型注釈にかかれてる型にへんかんする。ただし、仮にプロパティが食い違っていても、無理くり変換してしまうので注意。<dd>
<dl>

**whitelist**と**forbidNonWhitelisted**がtrueじゃないと、余計なプロパティをはじけない。
これらがなくても、プロパティの型が間違っている場合は指摘してくれるが、例外に対処できない。サーバーが固まってしまうかもしれないので、例外にも対処できるようにしておこう
PHPで「continue」の動作を確認してみた。

# 概要

PHPで「continue」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/php/for/index4.html

# 実装

以下のファイルを作成しました。

```sample.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHPテスト</title>
</head>
<body>

<p>PHPのテストです。</p>

<p>
<?php
$count1 = 0;
$sum = 0;

while ($count1 < 10){    // continueが実行された時に処理が移る位置
  $count1 += 1;

  $count2 = 0;
  while ($count2 < 10){
    $count2 += 1;
    if ($count1 * $count2 > 30){
      continue 2;
    }

    $sum += $count1 * $count2;
  }
}
print 'sum = '.$sum;
?>
</p>

</body>
</html>
```

以下のコマンドを実行しました。

```
$ php sample.php 
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHPテスト</title>
</head>
<body>

<p>PHPのテストです。</p>

<p>
sum = 869</p>

</body>
</html>
```

# まとめ

何かの役に立てばと。
【メモ】bashでよく見る出力されるログを同じ行に上書きするためのやつ

`tput`でカーソル位置を移動すると良いみたい。
だけどほんとは、`ANSIエスケプシーケンス`でやりたい。

```bash
tput cup $$ 0
```

~~だけの内容のせいか、なんか`本文に投稿禁止の内容が含まれています。利用規約、コミュニティガイドラインをご確認ください。`ってなって投稿できないんだけどなんでだろう~~
投稿できた・・・
競プロ日記#25/03/13

# AtCoder
## パナソニックプログラミングコンテスト2020-[B - Bishop](https://atcoder.jp/contests/panasonic2020/tasks/panasonic2020_b)
- 2次元配列から探索していくような形を考えたが、アルゴリズム設計などは不要だった。
単純に角の開始位置が固定されているので市松模様で移動可能マスがあることに気づけば一瞬。
（(H + W + 1) / 2）になるのはH,Wがどちらも奇数だった場合は市松模様がちょうど半分にならない。（どちらか一方が偶数ならちょうど半分になる）→切り上げを表現するために+1。
また、HかWが1になる時は角が全く動けないのでそのパターンも考慮する。
Xのポストから学ぶ！アプリ開発の重要性とオープンソースプロジェクトへの挑戦

## はじめに

こんにちは！2年目SEPGのタカタカです。

日々、技術を磨きながらアプリ開発に挑戦しています。今回は、X（旧Twitter）で見かけたポストをきっかけに、オープンソースプロジェクトに取り組むことにしました。その過程で得た学びや、開発の進め方について共有したいと思います。

🔗 [Xのポスト](https://x.com/Sicut_study/status/1889446818435703213)

また、「オープンソース開発レベル別プロジェクト」という記事に紹介されていたプロジェクトリストを活用し、実際にアプリ開発を進めることにしました。

🔗 [オープンソース開発レベル別プロジェクト](https://qiita.com/K3n_to_n17/items/cb7e02005e371665d4fb)

本記事では、プロジェクト選定の理由、管理方法、実践内容について紹介します。

## 取り組むプロジェクト

Xで紹介されていたアプリを順番に開発することにしました。（1～24）

![アプリ開発.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3860846/c054a89e-df10-4816-a3eb-f40e68d3ec97.jpeg)

これらのプロジェクトは、基本的なデータ管理からネットワーク通信まで幅広い技術を学ぶのに適しています。

## プロジェクト管理方法

### 1. GitHub を活用

- 各プロジェクトのリポジトリを作成。
- Issues や Projects 機能を使ってタスク管理。
- 定期的にコミットし、進捗を可視化。

### 2.Qiitaでの情報収集 & 発信

- Qiitaでの学習記録を投稿し、開発者コミュニティと交流。
- 他の開発者の意見を取り入れながら改善。

## まとめ

Xのポストをきっかけに、オープンソース開発レベル別プロジェクトに取り組むことを決めました。開発の進捗はGitHubで管理し、SNSでのアウトプットを活用しながらスキルアップを目指します。

皆さんも興味があれば、一緒にチャレンジしてみませんか？

---

📌 GitHub リポジトリ（随時更新）


フィードバックやアドバイスがあれば、ぜひコメントしてください！
コードの差分表示の仕方



```diff_java
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
```

```diff_java
public class HelloWorld {
    public static void main(String[] args) {
-       System.out.println("Hello, World!");
+       System.out.println("こんにちは, 世界!");
+       System.out.println("diff_java表示");
    }
}
```

下記のように、行の先頭に`+`または`-`を記述することにより、差分表示になる。
```
public class HelloWorld {
    public static void main(String[] args) {
-       System.out.println("Hello, World!");
+       System.out.println("こんにちは, 世界!");
+       System.out.println("diff_java表示");
    }
}
```
 
言語名は、言語の先頭に`diff_`とつける 
`java` → `diff_java`
`javascript` → `diff_javascript`
monorepoでtailwindのスタイルが当たらなかったことに対応したメモ

# 概要
tailwindcssを使ったコンポーネントが、読み込んだらスタイルが当たっていなかった。
スタイルを当てられるよう修正した。

[この時点のソース](https://github.com/hibohiboo/odyssage/blob/e388e5df4bbd38d124a85bd2c0f93376d478aec4/apps/frontend/src/styles/tailwind.css)

[UI - Storybook](https://hibohiboo.github.io/odyssage/odyssage-components/index.html?path=/)
[UIを使ったページ](https://develop.odyssage.pages.dev/)

# 対応

`@source`を利用する。[*](https://tailwindcss.com/blog/tailwindcss-v4#automatic-content-detection)


```css/apps/frontend/src/styles/tailwnd.css
@import '@odyssage/ui/tailwind.css';
@source "../../../../packages/ui/**/*.{js,ts,jsx,tsx,mdx}";
```
AWS ECS の コンテナ $HOME を EFS に保存する（code-server用）

## はじめに
仕事で，AWS上に全く同じ設定の code-server を複数建てたい，という要件がありました。
* それぞれの code-server はクライアントが利用し，事前配布のファイルを編集したりファイルを新規作成したりする
* 利用期間は数日から一週間で，期間終了後はシステムごと破棄する
* 費用節約のため業務時間外にはシャットダウンしたい

EC2で作ってもいいのですが，費用がかかること，code-server 構築コードがAWS依存になることがデメリットです。
そこで，ECS on EC2でコンテナ化し，ユーザが作成するファイルをEFSに保存する構成を考えました。
ホームディレクトリのサブディレクトリにEFSをマウントするだけなら簡単ですが，これだと以下の不都合があります。
* 業務時間終了にシャットダウンするとコンテナの中身が元に戻り，ユーザ設定が保存されない
* マウントしたEFSにファイルを事前配布するのが難しい（Dockerfileと比べて）
* 事前配布のファイルがEFS上に複数配布され，無駄が多い

この記事は，Linux の overlayfs で何とかできないか... と思って試行錯誤した記録です。

## 方針
privilaged コンテナ前提で，以下のようにしてみます。
* コンテナにEFSをマウントする
* EFS上にディスクイメージを作り，コンテナ内でループバックデバイスにlosetup。mkfs.ext4などしておく
* コンテナ内でループバックデバイスをマウント
* fuse-overlayfs によりコンテナのファイルシステムをlower，ループバック上のファイルシステムを upper とする

## 落とし穴いろいろ

コンテナ内からは overlay タイプのマウントができなかったので，fuse-overlayfs を使います。

当初は EFSを upper として利用するように fuse-overlayfs を設定していたのですが， code-server のログインページ以外が見えない... という現象になります。
恐らくこれは inotify を NFS がサポートしていないことに起因する問題で，@parcel/watcher かその使い方（多分 vscode）がよくない... です。
https://github.com/coder/code-server/issues/6953
これに気が付くまでとても時間が必要でした...

今回のユースケースではEFSを共有する必要はないので，ディスクイメージのストレージとしてだけ使います。
EFSにディスクイメージを作るとき，sparse file として作成できるように配慮が必要です。
そうしないと，ディスクイメージ * コンテナ数 分のストレージ容量に課金され，IOPSと帯域を無駄に消費してしまいます。

また，ループバックデバイスは namespace 対応ではないので，全コンテナ間で共通です。
コンテナが空きループバックデバイスを使うようにスクリプトを作る必要があります。

## 結果
コンテナ5個に，wxWidgets のソースコード（zipで23MB）を展開してみました。各コンテナにマウントしたEFSには16GBのスパースファイルを作り，そこにext4ファイルシステムを作って fuse-overlayfs でマウントしています。EFS のディスク容量をどの程度消費するか確認してみます。

zip を展開したのち，find してみたり， code-server を日本語にしたりと操作してみています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738861/94bf60a2-7dd3-466a-9c0f-325254fbcf1e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738861/b3f8f8a8-00a7-49cb-9ca8-fc65446b4518.png)

クライアント数が途中で0になっているのは，コンテナホストを落としたためです。
ストレージバイト数が出てこないのはなぜでしょう(CloudWatchでもとても小さい)...
ちゃんと sparse file になっているようです。

## おわりに
こんなに苦労するなら EBS にすればよかったんじゃ... と思ってみてみると，EBSはタスク終了時に削除されてしまったり，色々制約があるようです。
また，EBS だとプロビジョニングした容量分の請求になり，少し値段が上がりそうです。

このような使い方は一般的でないと思いますが，動くことが分かってすっきりしました。
samba4 の DCコンテナを作るときなど，色々応用できそうです。
【Python】alembicで、レコードの値を変更せずにカラム名を変更する方法

# 概要
Alembicにて、レコードの値を変更せずに、カラム名を変更する方法を紹介します。

# マイグレーションファイル

例えば、以下は`created_at`から`create_date`に変更する場合のマイグレーションファイル。SQLを直接実行するパターンですね。

```py
def upgrade() -> None:
    # カラム名を直接変更
    op.execute('ALTER TABLE sample_table CHANGE COLUMN created_at create_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP')

def downgrade() -> None:
    # カラム名を元に戻す
    op.execute('ALTER TABLE sample_table CHANGE COLUMN create_date created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP')
```

もしくは以下のように「追加」「更新」「削除」を行なって変更していく方法でも実現できました。

```py
def upgrade() -> None:
    op.add_column('sample_table', sa.Column('create_date', sa.DateTime(), nullable=True))
    op.execute('UPDATE sample_table SET create_date = created_at')
    op.alter_column('sample_table', 'create_date', existing_type=mysql.DATETIME(), server_default=sa.text('now()'), nullable=False)
    op.drop_column('sample_table', 'created_at')

def downgrade() -> None:
    op.add_column('sample_table', sa.Column('created_at', sa.DateTime(), nullable=True))
    op.execute('UPDATE sample_table SET created_at = create_date')
    op.alter_column('sample_table', 'created_at', existing_type=mysql.DATETIME(), server_default=sa.text('now()'), nullable=False)
    op.drop_column('sample_table', 'create_date')
```

以上！