OmniAICreator/Qiita-1.07M huggingface dataset:
pyenvでPythonをインストールして、VSCodeで実行する方法

# ■はじめに

最近少しだけPythonを学んでいるため、VSCodeでPythonを実行するための方法や、Pythonインストール方法の備忘録を残します。

# ■Pythonのインストール

### ◆Homebrewのインストール

```
❯ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

https://brew.sh/ja/

公式ドキュメントに記載されているHomebrewのインストールコマンドを実行します。

```
❯ brew --version
```

`brew --version`でHomebrewがインストールされているかを確認します。

### ◆pyenvをインストール

```
❯ brew list
```

`❯ brew list`コマンドでHomebrewを使ってインストールしたパッケージを確認します。

この時点では、pyenvはないと思います。

```
❯ brew install pyenv
```

`brew install pyenv`を実行して、Homebrewを使って`pyenv`をインストールします。

```
❯ pyenv version
```

`pyenv version`コマンド実行して、pyenvがインストールされていることを確認します。

### ◆pyenvを使ってPythonをインストールする

```
❯ pyenv install -l
```
![スクリーンショット 2025-01-25 18.29.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307408/9d091b95-0266-a97f-de09-bf77dbccc6ad.png)

`pyenv install -l`でpyenvを使ってインストールできるPythonのバージョンを確認します。

```
❯ pyenv install <バージョン>
```

`❯ pyenv install <バージョン>`でインストールしたいバージョンのPythonをインストールします。

```
❯ pyenv global <バージョン>
```

`❯ pyenv global <バージョン>`コマンドでインストールしたPythonをデフォルトで利用するように設定します。

```
❯ python3 --version
```

`❯ python3 --version`で`❯ pyenv global <バージョン>`を実行した際に設定したバージョンが表示されたら完了です。

https://qiita.com/suisuina/items/02644576ab4d048ffa5e

https://qiita.com/fuqda/items/db8aff0ba4068aea2cc6

# ■PythonをVSCodeで実行する

### ◆Pythonの仮想環境を作成

```
❯ python -m venv pythonenv
```

`python -m venv pythonenv`を実行した仮想環境を作成します。

`pythonenv`は仮想環境名なので何でもいいです。

```
❯ . pythonenv/bin/activate
```

`. pythonenv/bin/activate`で、先程作成した仮想環境を有効化します。

### ◆VSCodeでPythonを実行する（デバッグなし）

![スクリーンショット 2025-01-23 8.45.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307408/ae40c3c4-38ef-3d42-85c7-d8f550a45af3.png)


VSCodeを開いて、「表示」→「コマンドパレット」を選択します。

![スクリーンショット 2025-01-23 8.46.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307408/046f0d5d-4c91-4164-bde9-8175ee4c884a.png)


「inter」と入力すると、「Python: インタープリターを選択」と表示されるので、選択します。

![スクリーンショット 2025-01-23 8.49.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307408/f9c0a9eb-7d93-79dc-57b4-ef680f0ca1fa.png)

先ほど作成した「Python仮想環境」を選択します。

表示されない場合は、「インタープリター　パスを入力」をクリックして、この図であれば「pythonenv」ディレクトリを選択します。

![スクリーンショット 2025-01-23 8.50.26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307408/9dcf7a4d-0c14-8437-2b61-50ea36158005.jpeg)

VSCodeの「実行」→「デバッグなしで実行」をクリックすると、デバッグなしで実行できます。

### ◆VSCodeでPythonを実行する（デバッグあり）

![スクリーンショット 2025-01-23 8.53.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307408/b1ffd421-e70d-2351-ae54-04a7f2d7f1e4.png)

デバッグモードで実行したい場合は、デバッグしたいコードの左端をクリックすると、赤丸が表示されます。

![スクリーンショット 2025-01-23 8.54.36.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307408/817ea4c0-a80a-caf7-4466-9595ca31dfbc.jpeg)

赤丸が表示されている状態で、「実行」→「デバッグの開始」をクリックすると、赤丸をつけたコードで実行が止まります。

左側の変数やコールスタックでコード実行時点での状態を確認できます。
東京大学大学院数理科学専攻の入試問題を解いてみた

|2024 東大院 数理科学研究科 数理科学専攻 修士課程 専門科目A 第4問|
|--|
|$t\in\mathbb{R}$に対して$[t]$を$t$以下最大の整数とし，$0<\alpha\le 1$とする$\displaystyle I\_\alpha:=\int_0^1\left(\frac{\alpha}{x}-\left[\frac{\alpha}{x}\right]\right)dx,~ J\_\alpha:=\int_0^1\left(\alpha\left[\frac{1}{x}\right]-\left[\frac{\alpha}{x}\right]\right)dx$とする．以下の問いに答えよ．|
|(1) $\alpha=1$のとき，$I\_\alpha$は$\displaystyle \sum\_{n=1}^{+\infty}\left\lbrace-\frac{1}{n+1}-\log\left(1-\frac{1}{n+1}\right)\right\rbrace$に収束することを示せ．|
|(2) $I\_\alpha=\alpha I\_1-\alpha\log \alpha$を示せ．|
|(3) $J\_\alpha$を求めよ．|

:::note info
全体として，少々面倒ではありますが難しいことはなく，高校数学でも行けそうな感じがしました．ただ，床函数や天井函数なんかがでてくる積分に慣れてないとちょっと難しいかも知れません．そんな印象です．
:::

:::note warn
もし間違いや論理の飛躍，もっと楽ちんにできる方法などがあれば指摘してくださるとありがたいです．
:::


(1)Proof.
$\alpha=1$のとき
```math
\begin{aligned}
I_1&=\int_0^1\left(\frac{1}{x}-\left[\frac{1}{x}\right]\right)dx\\
&=\sum_{n=1}^{+\infty}\int_{\frac{1}{n+1}}^{\frac{1}{n}}\left(\frac{1}{x}-\left[\frac{1}{x}\right]\right)dx\\
&=\sum_{n=1}^{+\infty}\int_{\frac{1}{n+1}}^{\frac{1}{n}}\left(\frac{1}{x}-n\right)dx\quad \left(\because \frac{1}{n+1}< x<\frac{1}{n}\iff n<\frac{1}{x}<n+1\right)\\
&=\sum_{n=1}^{+\infty}(\log x-nx)\Big|_{\frac{1}{n+1}}^{\frac{1}{n}}\\
&=\sum_{n=1}^{+\infty}\left\lbrace-\frac{1}{n+1}-\log\left(1-\frac{1}{n+1}\right)\right\rbrace
\end{aligned}
```
が成立する．収束性については，$\log$函数のMaclaurin展開から
```math
\begin{aligned}
\left|\sum_{n=1}^{+\infty}\left\lbrace-\frac{1}{n+1}-\log\left(1-\frac{1}{n+1}\right)\right\rbrace\right|&=\left|\sum_{n=1}^{+\infty}\left\lbrace-\frac{1}{n+1}+\sum_{k=1}^{+\infty}\frac{1}{k}\left(\frac{1}{n+1}\right)^k\right\rbrace\right|\\
&=\left|\sum_{n=1}^{+\infty}\sum_{k=2}^{+\infty}\frac{1}{k}\left(\frac{1}{n}\right)^k\right|\\
&\le \sum_{n=1}^{+\infty}\sum_{k=2}^{+\infty}\left(\frac{1}{n}\right)^k\\
&=\sum_{n=1}^{+\infty}\frac{1}{k(k+1)}=1
\end{aligned}
```
より成立する．$\square$

(2)Proof.
```math
\begin{aligned}
I_\alpha&=\alpha\int_0^{\frac{1}{\alpha}}\left(\frac{1}{x}-\left[\frac{1}{x}\right]\right)dx\\
&=\alpha\left\lbrace\int_0^1\left(\frac{1}{x}-\left[\frac{1}{x}\right]\right)dx-\int_{\frac{1}{\alpha}}^1\left(\frac{1}{x}-\left[\frac{1}{x}\right]\right)dx\right\rbrace\\
&=\alpha\left\lbrace I_1-\int_{\frac{1}{\alpha}}^1\left(\frac{1}{x}-\left[\frac{1}{x}\right]\right)dx\right\rbrace\\
&=\alpha\left\lbrace I_1-\int_{\frac{1}{\alpha}}^1\left(\frac{1}{x}-0\right)dx\right\rbrace\quad\left(\because~\alpha<\frac{1}{x}<1\right)\\
&=\alpha\bigg\{ I_1-(\log x)\Big|_{\frac{1}{\alpha}}^1\bigg\}\\
&=\alpha\left(I_1-\log\alpha\right)\quad\square
\end{aligned}
```

(3)
```math
\begin{aligned}
J_\alpha&=\int_0^1\left(\alpha\left[\frac{1}{x}\right]-\left[\frac{\alpha}{x}\right]\right)dx\\
&=\int_0^1\left(\frac{\alpha}{x}-\frac{\alpha}{x}+\alpha\left[\frac{1}{x}\right]-\left[\frac{\alpha}{x}\right]\right)dx\\
&=\int_0^1\left(\frac{\alpha}{x}-\left[\frac{\alpha}{x}\right]\right)dx-\alpha\int_0^1\left(\frac{1}{x}-\left[\frac{1}{x}\right]\right)dx\\
&=I_\alpha-\alpha I_1\\
&=\alpha(I_1-\alpha\log\alpha)-\alpha I_1\\
&=-\alpha\log\alpha\cdots(\text{答})
\end{aligned}
```
ウェブサーバーへのIP直アクセスを制限しつつ、ヘルスチェックを受容する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417736/4b609ebb-2a8f-a816-9927-0fa356f78671.png" alt="apache" width="80">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417736/9362fc28-852c-1965-b839-f63b00223139.png" alt="aws" width="80">


IPアドレス直のサーバーアクセスを403制限しつつ、ロードバランサのヘルスチェックを通すapacheconfの設定

## ポイント

* 一番初めにローディングされる`VirtualHost`ディレクティブがデフォルトサーバーとなるため、Include順を考慮したconfファイルを命名する
* ファイル命名規則のInclude順でデフォルトサーバーは自明だが、明示的に`ServerName any`ですべてのホスト名を捕まえている
* デフォルトサーバーは`:80`と`:443`ポートごとに設定が必要。 `<VirtualHost *:*>`だと、うまく動かない
* デフォルトサーバーは`httpd -S`で確認する

```sh:httpd -S
httpd -S
VirtualHost configuration:
*:80                   is a NameVirtualHost
         default server any (/usr/local/httpd-2.4/conf/extra/httpd-vhosts.conf:1)
         port 80 namevhost any (/usr/local/httpd-2.4/conf/extra/httpd-vhosts.conf:1)
         port 80 namevhost webapp.com (/usr/local/httpd-2.4/conf/extra/httpd-vhosts.conf:28)
*:443                  is a NameVirtualHost
         default server any (/usr/local/httpd-2.4/conf/extra/httpd-vhosts.conf:15)
         port 443 namevhost any (/usr/local/httpd-2.4/conf/extra/httpd-vhosts.conf:15)
         port 443 namevhost webapp.com (/usr/local/httpd-2.4/conf/extra/httpd-vhosts.conf:45)
```

## 設定

* `:80`と`:443`それぞれのポートでデフォルトのバーチャルホストを定義する
* ドキュメントルートを`/var/www/_default`に設定して、ロードバランサのヘルスチェックファイル`/hb.html`=>`/var/www/_default/hb.html`を作成
* ヘルスチェック=`hb.html`はELB=サブネットワークにだけ公開したいので、リモートアドレスをRemoteIPTrustedProxyでX-Forwarded-For偽装をはじく。
* リモートアドレスがtrustでなければ、X-Forwarded-Forを剥がしてクライアントの本来のリモートアドレスを採用する
* `:443`のデフォルトサーバーはアクセス不要なので全拒否

![](image.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417736/6fd97dd9-349d-60d8-6429-003399af3a16.png)

```httpd.conf:path/to/httpd//conf/_default.conf(デフォルトサーバー)
<VirtualHost *:80>
    DocumentRoot "/var/www/_default/" 
    ServerName any
    <Directory "/var/www/_default/">
        Require all granted
    </Directory>
    # リモートアドレスがプロキシーのRemoteIPTrustedProxyアドレス帯ならば、X-Forwarded-Forを採用する。X-Forwarded-Forがなければリモートアドレスを採用する=ロードバランサである
    # リモートアドレスがプロキシーのRemoteIPTrustedProxyアドレス帯でなれけば、X-Forwarded-Forを剥がして、リモートアドレスを採用する=プロキシーを経由しないインターネットアクセス
    RemoteIPHeader X-Forwarded-For
    RemoteIPTrustedProxy 172.21.0.0/16

    # リモートアドレスがプロキシーのRemoteIPTrustedProxyアドレス帯ならば、X-Forwarded-Forを採用する。X-Forwarded-Forがなければリモート
アドレスを採用する=ロードバランサである
    # リモートアドレスがプロキシーのRemoteIPTrustedProxyアドレス帯でなれけば、X-Forwarded-Forを剥がして、リモートアドレスを採用する=プ
ロキシーを経由しないインターネットアクセス
    RemoteIPHeader X-Forwarded-For
    RemoteIPTrustedProxy 172.21.0.0/16

    # サブネットワーク直の侵入のみ許可する
    <Location />
        <RequireAll>
            Require ip 172.21.0.0/16
        </RequireAll>
    </Location>

</VirtualHost>

<VirtualHost *:443>
    ServerName any
    <Location />
        Require all denied
    </Location> 
</VirtualHost>
```
Codejump を試す

## 前置き
デザインカンプからwebページを作ってみたいと考えていた。  
調べたところ、「Codejump 作って学ぶコーディング学習サイト」を見つけた。  
なんでも素材を含めてフリーで利用できるとのことなので、早速やってみた。  

https://code-jump.com/

なお、教材はいくつもあり、今回は以下の「【HTML/CSS コーディング練習】中級編：ブログサイト／2カラム」に取り組んだ。  

https://code-jump.com/blog-menu/

## 感想
とてもよかった。  
サクッと取り組めるし、作成後に振り返りもしやすい。  
ポイントとしては以下の通り。  
- Figma のデザインカンプが公開されている。  
- 素材が一括でダウンロードできる。  
- コーディング使用が記載されている  
- ソースコードが公開されている  
- デモサイトが公開されている  

## おまけ
自分の反省点のメモ  
- ページの構成をよく考えず、なんとなく上から作成してた。  
  - タイトルに対するタグが適当←SEO的にだめ  
  - レイアウトが適当←(今回は実装していないが)他ページを実装したときにぐちゃぐちゃになる  
- 繰り返し要素をべた書きしてた。  
- 画像やフォントの遅延ロードができていない。  
- そろそろバックエンドを作って画像とか管理したいな...  

今回の記事は以上です。  

前回記事はこちら  

https://qiita.com/magurouhiru/items/0252f0350387cf85bf93

詳細見たい人はこちら  

https://github.com/magurouhiru/mysite/pull/67

https://github.com/magurouhiru/mysite/pull/69

https://magurouhiru.github.io/mysite/#/portfolio/code-jump/blog-menu
VSCodeのLinux版がいつの間にかモダンなGUIに変わってた

# 筆者について

```
name → Koki Teramoto
age → 18
language → ja_JP, en_US
```

# 本編

僕の普段のメイン機はM1のMacBook AIrなのですが、このたびバッテリー交換のために完全に修理に出しまして、それをきっかけにAsahi Linuxの環境を完全に削除しました。その代わりにLinux環境を改めてUTM上に立てたArch LinuxのVMで揃えたのですが、その際にインストールしていたVSCodeが以前よりもとても変化していたので今回とインストールをしたいと思っています。

## そもそもGUIが全体的にめちゃめちゃ操作しやすくなっている

そうなんです、そもそもの話でGUIがめっちゃ整理されています。なんと言うのか、最近はWayland移行の動きが結構活発化している気もするのですが、その一つでしょうか。個人的にはかなりLinux版もWindows版やMac版みたいなモダンなGUIに寄せてきているなと思っています。

![Screenshot From 2025-01-25 18-17-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583428/c00fe533-a400-148c-1676-eacc0af5bf87.png)

## Arch LinuxにVSCOdeの最新版をインストールしていく方法

ここからはArch LinuxでのVSCodeのインストール方法について記しておきたいと思います。devパッケージやrpmパッケージは実はWebでも配信されているのですが、Archベースの人たちがインストールできるようなパッケージは用意されていません（というかそもそも僕あんまpacmanにパッケージが用意されているの知らないんですよね）。ここで、僕たちがVSCodeをArch Linuxにイントールする方法はどうしても限られてきます。

- pacmanにある古いパッケージをインストールする
- Flatpakからインストールする
- 手動でファイルを展開する

今回全て試したのですが、新しいGUIを試せたり、あるいはInsidersビルドを使いたいということもあってすべて手動で設定しましたので、その軌跡を記しておきたいと思います。

### `.tar.gz`をダウンロードする

VSCodeのダウンロードページから圧縮されたgzipをダウンロードしておきましょう。そのまま、回答もお忘れないように。

```bash
tar -zxvf code.tar.gz 
```

そのまま回答したフォルダを適当なフォルダに移動させます。僕は予め作っていた`/opt`下に持っていきました。


### シンボリックリンクを作成する

シンボリッククリックを使っていきましょう。これでコマンドからも起動できるようになります。

```bash
ln -sf /opt/code/bin/code-insiders /usr/bin/code-insiders
```

### Desktopファイルを作成する

便利なようにDesktopファイルを作成してそれをDockに固定したいと思います。Desktopファイルは以下のようになりました。

```:code-insiders.desktop
[Desktop Entry]
Name=Visual Studio Code Insiders
Comment=Code Editing. Redefined.
GenericName=Text Editor
Exec=/usr/bin/code-insiders %F
Icon=/opt/code/resources/app/resources/linux/code.png
Type=Application
StartupNotify=false
StartupWMClass=Code
Categories=TextEditor;Development;IDE;
MimeType=application/x-code-workspace;
Actions=new-empty-window;
Keywords=vscode;

[Desktop Action new-empty-window]
Name=New Empty Window
Name[de]=Neues leeres Fenster
Name[es]=Nueva ventana vacía
Name[fr]=Nouvelle fenêtre vide
Name[it]=Nuova finestra vuota
Name[ja]=新しい空のウィンドウ
Name[ko]=새 빈 창
Name[ru]=Новое пустое окно
Name[zh_CN]=新建空窗口
Name[zh_TW]=開新空視窗
Exec=/usr/bin/code-insiders --new-window %F
Icon=/opt/code/resources/app/resources/linux/code.png
```

もとのDesktopファイルはパッケージマネージャー経由でインストールしたものをコピーしています。肝となるのは、まずアイコンのところとExecのところです。アイコンのところはresourcesのとことろにあるものを、Execはそのまま`code-insiders`と書きましょう。それ咲いてできれば最低限のジョウン日は完了です。最後にデスクトップをアップデートです。

```bash
sudo update-desktop-database
```

これで全体のアプリケーション一覧にVSCodeが表示されるような状態にしておきたいと思います。これで、インストールは完了です！

# 最後に

いや〜、ここ最近は本当に自分の周りの進化の速度が早すぎて困る。頑張ってついていきたいと思います。
丁寧なzip/gzip

手抜きzip/gzip fileを作っている人必見、とてつもなく丁寧に圧縮して、互換性のあるfileをヒネリ出すprogramを紹介していくぞ…。
## 7zip
言わずと知れた[高圧縮書庫製造機](https://7-zip.opensource.jp/)。zip/gzipの圧縮率も本家を上回る。

## kzip
[Ken Silverman's Utility Page](https://advsys.net/ken/utils.htm)にて公開中。古代より高圧縮zip生成噐の頂点に君臨し続けていたかもしれない程の無名program。その地位はzopfliの出現により脅かされつつある。

## zopfli
もはや説明不要かもしれないが、[Google様が開発した](https://github.com/google/zopfli) deflate/gzip/zip 互換機。圧縮率を高める工夫を施しまくった逸品である。本家deflateより10%前後高い圧縮率を誇る事もあるっぽいかもしれないとされる。しかし最速設定でも実用に耐え難い程度にはうすのろである。

## pigz
[zlib.net](https://zlib.net/pigz)にて大絶賛配布中。実行fileは未公開という親切っぷり、さすがである。自前でcompileしましょうね([大元](http://zlib.net)からzlib v1.2.3以降のsourceをincludeする必要がある)。[ここに](http://nishi.dreamhosters.com/u/pigz_win_src_20220503.7z)実行file含む書庫(2022年版)が落ちている。

## zopfli KrzYmod
[Krzysztof Bochniak氏](https://github.com/MrKrzYch00/zopfli)が手掛けたzopfliの改良版。本家より多彩な設定が可能。速度なんて気にしてはいけない。

## Efficient Compression Tool
[Felix Hanau氏作](https://github.com/fhanau/Efficient-Compression-Tool)のdeflate系最適化装置。これもzopfliの技術を応用しまくっている。png画像の最適化も得意である。処理速度はzopfliより遥かに高速で、圧縮性能も概ね上回る。

## libdeflate
[Eric Biggers氏](https://github.com/ebiggers/libdeflate)がgithubで大公開中。その名の通りdeflate/zlib/gzip互換圧縮fileを作る機能満載である。圧倒的処理速度、zopfliに匹敵する圧縮性能を誇る名作。それだけに**使い心地はこの中で最高**

## ツンデレ Zipper
[vector](https://www.vector.co.jp/soft/winnt/util/se503579.html)で密かにうごめいている。面白い発想で楽しませてくれる…かも。性能度外視。別にあんたの為に紹介しているんじゃないんDa力ラNe!

## それはともかく
deflate法をいくら最適化した所で今時の巨大file相手ではイマイチ使えない…。バラモス相手にひのきの棒で挑んでいるような感覚である。いや素手か。
Tailwind v4 移行後に発生する『Error: Cannot apply unknown utility class』の解決方法

## 問題

tailwind v4 に移行する際、[公式ドキュメント](https://tailwindcss.com/blog/tailwindcss-v4)に従って以下のコマンドを実行すると、プロジェクト内のファイルが v4 に対応するよう自動的に修正されます。

```bash
npx @tailwindcss/upgrade@next
```

しかし、2025/1/25時点では、Next.jsなどで利用するCSS Module ファイル（`hoge.module.css`）等は修正してくれません。その結果、以下のようなエラーが発生することがあります。

```
Error: Cannot apply unknown utility class: text-lg
```

## 解決法

CSS Module ファイルの先頭に、以下のようにグローバル CSS ファイルを `@reference` で参照する設定を追加します。

```
@reference "./global.css";
```
:::note info
ファイルパス、ファイル名は適宜修正してください
:::


なお、この問題は以下の Github issue や discussion で議論中です。

https://github.com/tailwindlabs/tailwindcss/discussions/13336

https://github.com/tailwindlabs/tailwindcss/discussions/14491

https://github.com/tailwindlabs/tailwindcss/issues/15778

公式の解決策が発表された場合、本記事に追記します。
【初心者】Thymeleafについて

## Thymeleafってなに？ ～ホームページ作りを手伝ってくれるすごいヤツ！～

例えば、あなたが学校でクラスメイトの紹介ページを作りたいとします。
一人ずつ自己紹介を書いていくのは大変ですよね？

Thymeleafは、そんな時に役立つ**ホームページ作りを手伝ってくれるツール**です。
Javaというプログラミング言語と一緒に使います。

### Thymeleafでできること

Thymeleafを使うと、**少ない記述でたくさんの情報を表示**できます。

例えば、クラス全員の名前、誕生日、好きなものが書かれたリストがあるとします。
Thymeleafを使うと、このリストから一人一人の情報を自動で読み込んで、
**簡単に個別の紹介ページを作成**できます。

#### 例えばこんな感じ！

**Thymeleafを使う前**

```
田中太郎さんの紹介ページ
名前：田中太郎
誕生日：2008年4月1日
好きなもの：サッカー

佐藤花子さんの紹介ページ
名前：佐藤花子
誕生日：2008年5月2日
好きなもの：ピアノ
…
```

**Thymeleafを使った後**

```html
<div th:each="student : ${studentList}">
  <h1><span th:text="${student.name}"></span>さんの紹介ページ</h1>
  <p>名前：<span th:text="${student.name}"></span></p>
  <p>誕生日：<span th:text="${student.birthday}"></span></p>
  <p>好きなもの：<span th:text="${student.favorite}"></span></p>
</div>
```

Thymeleafを使うと、このように**繰り返し**の作業を減らすことができます。
クラスの人数が増えても、簡単にページを作ることができますね！

### まとめ

Thymeleafは、Javaと組み合わせて使うことで、**ホームページを効率的に作成**するためのツールです。
特に、**たくさんの情報を表示する**場合に役立ちます。

中学生のうちは、Thymeleafを使う機会は少ないかもしれませんが、
**ホームページの仕組み**を知る上で、Thymeleafは **分かりやすい例** となります。
特殊な三進数、「廃マンションの一室」をpython3で攻略

こんにちは。nasuoです。

皆さんはPaizaの新作ゲーム、電脳少女プログラミング2088で遊んでますでしょうか。

https://ppg.paiza.jp/dennou2088


僕はといえば、レイミとストーリーを進めていく最中に、
「廃マンションの一室」という問題に出会いました。


![スクリーンショット 2025-01-25 17.27.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3955329/dd0b8516-a7c9-2c4f-6516-c612faafd5cd.png)
https://ppg.paiza.jp/denno2088/challenges/denno2088_c_c_02

今までの常識を見つめ直させる良問だなと思いながら、

![スクリーンショット 2025-01-25 17.04.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3955329/c4619748-4e53-1168-5b4b-aee3b1af4c23.png)


攻略できた！よっしゃー！

十進数や三進数の仕組みを見直す、良い機会になりました。
（レイミが褒めてくれる親切な設計、すごくいいですね。）

では、早速コード解説に参りましょう。

廃マンションの一室   　解答：python3

    def san(n):
        q = (n + 1) // 3 
        r = (n + 1) % 3
        if q == 0:
            return ""
        else:
            return san(q) + "201"[r]

    n = int(input())
    if n == 0:
        print(0)
        exit()
    hugou = "1"
    if n < 0:
        hugou = "2"
        
    print(hugou + san(n))

コードの概要としては、
1,定義
2,符号決定
3,出力
の3つからなります。

1,定義
入力された値から1を足した数字に、三で割った商と余りをqとrとしておきます。このアルゴリズムについては、下記の動画の説明がわかりやすかったです。ぜひ参考にしてみてください。

https://www.try-it.jp/chapters-4962/sections-5093/lessons-5122/

入力された値から1を足しているのは、[2,0,1]の並びを-1,0,1と対応させたかったからです。2をどのように-1として実装するのかが、この問題を解く上で重要だったと思います。

2,符号決定
まず、0を除外します。都合の悪い数字を早めに退場させたい時に、exit()は本当に便利。
入力された値が自然数なら1を、そうでないなら2を一番左におきます。

3,出力
符号と定義に通した入力値を、結合させて完成です。

やっぱりプログラミングって、すごく楽しいし面白いですね！
初めてのGitHubActionsへのデプロイでつまずいた話 ~Gradleを添えて~

UdemyでDockerの講座をハンズオンで進めていたらつまずきました。
基本コピペで進めていけばつまずくことはないはずなのに...

# どこでつまずいたのか
簡単なwebアプリを作成し、GitHubActionsにデプロイしてAWS上で動かすということをしていました。
ですが、GitHubActionsにデプロイするとなぜか失敗します。
ログを見るとAPIコンテナのBuildがうまくいっていない模様。

`ERROR: failed to solve: process "/bin/sh -c ./gradlew build" did not complete successfully: exit code: 126` 

もう少し上の行をみたらこんな出力も...
`./gradlew: Permission denied`

ふ～ん、permission denied ね

# どう解決したのか
APIコンテナをBuildするDockerfileを修正しました。
具体的には、

`RUN ./gradlew build`

というBuildを行うコマンドの実行前に、

`RUN chmod +x ./gradlew`

というコマンドを走らせました。

gradleの実行権限を追加するコマンドのようですね～
gradleの実行には権限が必要らしいよ

# 最後に
この記事が誰かの役に立てば幸いです
【Rails】"::" を付与していなかったので"uninitialized constant ApplicationController"になった

# はじめに
Railsデビューして約一か月、わからないことがたくさんあるので初歩的なことも記事にしていきます。
今回の記事は**エラー解消方法よりかは「"::"とはなんぞや」が趣旨になる**かと思います。
# 原因
ブラウザ上でルートパスを開いてみると"**uninitialized constant ApplicationController**" のエラーが出ていました。

# 解決方法
載せるまでもないかもしれませんが。。修正前と後のコードになります。

**修正前**
```rb:application_controller.rb
class ApplicationController < ActionController
end 
```

**修正後**
```rb:application_controller.rb
class ApplicationController < ActionController::Base
end
```
`ActionController::Base`と定義する必要があったようです。
下記のガイドに説明がありました。

https://railsguides.jp/action_controller_overview.html

>ApplicationControllerを継承したすべてのコントローラは、最終的にActionController::Baseを継承します。ただし、API専用アプリケーションの場合のみ、ApplicationControllerはActionController::APIを継承します。
# そもそも::とは？

::という記号は、**Rubyで「名前空間」を表す記号**です。

とはいえ、いまいちピンとこないので、AIにやさしく解説してもらいました。

>例えば、「2年A組」という教室を探すとき、
**2年という階層の中にA組という教室がある**、というように場所を特定しますよね。
Rubyでも同じように、**この時 ::は「その中にある」という意味になります**。
つまり、Api::V1::ApiControllerは「**Apiの中のV1の中のApiController**」
という意味になります。
これは、**同じ名前のコントローラーでも、場所（名前空間）が違えば共存できるようにするための仕組み**なんです！

# おわりに
ずっとTypeScript×React・Next.jsを書いていたので、異言語を学んでいる感がすごいです。。

# 参考

https://qiita.com/saitok7/items/6ec166fdaf5b77a058d4
VirtualBox上のkali-linuxで共有フォルダーを設定する

「7日間でハッキングをはじめる本」の中でkali-linuxを使用することになり、説明に沿って導入していたが、  
設定途中にあるホストOSとの共有フォルダの設定をしてもkali-linux側から共有フォルダにアクセスできなかった。  
調べても対応方法が見つからなくてあきらめていたが、  
ChatGPTに聞いたところ解決したのでやり方を残しておく。

うまくいかない場合は
「共有フォルダー」で検索してkali-linuxの他の記事を参考にしてください。

## 事象
Oracle VirtualBox マネージャーで仮想マシンの設定に共有フォルダを設定
この時、フォルダの設定に自動マウントと永続化するのチェックを入れていたが
kali-linuxを起動しても/mnt配下に共有フォルダのディレクトリが存在せず、アクセスできない状態だった。

## 対応
ChatGPTに質問してみたところkali-linux側でも共有フォルダをマウントする必要があるらしいということで試したところ共有フォルダーへアクセスできるようになった。

```
VirtualBoxを使用している場合、
Kali LinuxとWindowsの間でファイル移動用ディレクトリがうまく作成できない主な原因は、
共有フォルダの設定やゲスト追加ツール（Guest Additions）の未設定に
関連している可能性が高いです！
以下に、具体的な手順を確認・解決方法を説明します。

（中略）

3. Kali Linuxで共有フォルダをマウント

3-1.共有フォルダのマウントポイントを作成:
sudo mkdir -p /mnt/shared

3-2.共有フォルダをマウント: VirtualBoxで設定したフォルダ名（例: Shared）を使って以下を実行します:
sudo mount -t vboxsf Shared /mnt/shared

3-3.アクセス確認: マウントが成功したら、以下を実行してファイルが見えるか確認します:
ls /mnt/shared
```

3-1だけだとまだ共有されておらず、3-2までやったところ共有フォルダーが見られるようになった。
vboxsfが共有フォルダ用のファイルシステムらしく、フォルダを作成して紐づける必要があったらしい。
※「shared」ディレクトリは例示なので各々つけたい名前を設定

今回はゲスト追加ツール（Guest Additions）の未設定ではなく、共有フォルダの設定が原因のようだった。
本来は自動でやってくれる部分がどこかの設定方法のミスで作成されていなかったのかもしれない？
[React]リストのレンダーとkeyについて

:::note
データの集まりから、似たようなコンポーネントを複数表示させたい時に、`filter()`や`map()`といったJavaScriptの配列メソッドが使用できる。
この時に、配列の各アイテムには`key`を渡す必要がある。
:::

配列の各アイテムに`key`を渡さないと、以下のようなエラーがコンソールに表示される

![スクリーンショット 2025-01-25 17.28.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3191928/a7a2f144-cc59-1d23-a098-4e4b5b714854.png)

### keyが必要な理由
- 配列のどの要素がどのコンポーネントに対応するのかをReactが判断し、正しく更新するために必要
- 適切に`key`を選ぶことで、Reactは何が起こったか推測し、DOMツリーに正しい更新を反映させることができる
  - 配列の要素の移動
  - 要素の挿入
  - 要素の削除
### `key`の種類
  - DBからのデータの場合、DBのキーやIDは必然的に一意になるので、それを利用する
  - ローカルで生成された場合、アイテムを作成する際に、インクリメンタルなカウンタはuuidなどのパッケージを使用する   
### `key`のルール
  - キーは兄弟間で一意である必要がある
  - キーは変更してはいけない  

### keyとして指定してはいけないもの
- アイテムのインデックス
  - アイテムが挿入されたり削除されたりすると、レンダーするアイテムの順序が変わる。そのためインデックスをキーとして利用すると、バグの原因になる  
- その場で生成したキー
  - `key={Math.random()}`のようにその場で生成してはいけない。こうすると、レンダーごとにキーが合致しなくなり、コンポーネントとDOMが毎回再作成されるようになってしまう
  - 表示が遅くなったり、リストアイテム内の入力値も失われてしまう
- `key`はReact自体がヒントとして使用するだけで、コンポーネントのpropsとして受け取らない。コンポーネントがIDを必要とする場合は、別のpropsとして渡す必要がある

https://ja.react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key
TCP 3ウェイハンドシェイクの詳細

以下では、TCP 3ウェイハンドシェイクの各パケットにおける**フラグ(SYN/ACK)とシーケンス番号(Sequence Number)、確認応答番号(Acknowledgment Number)**がどのような値になるのかの典型例を示します。実際の値はOSによってランダムに初期化されますが（セキュリティ上、初期シーケンス番号は固定でなくランダムにする）、ここではわかりやすく「x」「y」という変数で表しています。

### 1. クライアント → サーバ: SYN パケット
- **フラグ:**
  - SYN = 1
  - ACK = 0  (初回なのでACKフラグは立てない)
- **Sequence Number:**
  - Seq = x (クライアントが選んだ初期シーケンス番号。実際にはランダム)
- **Acknowledgment Number:**
  - Ack = 0 (初回なので意味を持たない)

この最初のパケットが「SYNフラグのみセットされている」状態です。

### 2. サーバ → クライアント: SYN+ACK パケット
- **フラグ:**
  - SYN = 1
  - ACK = 1  (クライアントのSYNに対してACKする)
- **Sequence Number:**
  - Seq = y (サーバが選んだ初期シーケンス番号。実際にはランダム)
- **Acknowledgment Number:**
  - Ack = x + 1
  - クライアントのSYNを受け取ったことを示すため、「相手のSeqに+1した値」をACK番号に入れる

このパケットでは、サーバも自分のSYNフラグをセット（SYN=1）し、同時に「クライアントのSYNを受け取りましたよ（ACK=1）」という情報を返します。

### 3. クライアント → サーバ: ACK パケット
- **フラグ:**
  - SYN = 0  (すでにSYNは完了しているので立てない)
  - ACK = 1  (サーバのSYNを受け取ったことに対するACK)
- **Sequence Number:**
  - Seq = x + 1
  - クライアント自身のシーケンスは、最初に使ったxに+1した位置（2番目の送信）から始まる
- **Acknowledgment Number:**
  - Ack = y + 1
  - サーバのSYNに対して「受信したよ」と応答するため、サーバのSeqに+1した値

これでお互いのSYNを確認し合い、TCP接続（セッション）が確立します。

### 4. 全体のイメージ

1. Client -> Server
   - [ SYN=1, ACK=0, Seq=x,   Ack=0     ]
2. Server -> Client
   - [ SYN=1, ACK=1, Seq=y,   Ack=x+1   ]
3. Client -> Server
   - [ SYN=0, ACK=1, Seq=x+1, Ack=y+1   ]

- 1つめのパケット: クライアントがサーバへ「SYN=1, Seq=x」で送信
- 2つめのパケット: サーバが「SYN=1, ACK=1, Seq=y, Ack=x+1」で応答
- 3つめのパケット: クライアントが「ACK=1, Seq=x+1, Ack=y+1」で返す

これを「3ウェイハンドシェイク（3-way handshake）」と呼びます。ハンドシェイク後は、双方が x+1 と y+1 を基点にデータ（HTTPリクエストやレスポンス）を送受信していきます。

### 参考メモ
1. **Initial Sequence Number (ISN)**
   - x や y は OS が適当な乱数を使うことが多い。古い実装では固定値や単純カウンタだったが、セキュリティ強化のため現在はランダム化されている。
2. **SYN/ACK フラグは1ビット**
   - SYN=1 であれば「SYNフラグが立っている」、0 であれば「フラグなし」を意味する。
   - ACK=1 であれば「ACKフラグが立っている」。
3. **Ack = 相手のSeq + 1**
   - TCPでは「相手から送られてきたシーケンス番号に+1」を応答することで、相手のSYN（バイト数で1個分）を正しく受信したと知らせる仕組みをとっている。
4. **3ウェイハンドシェイク完了後**
   - この接続上で実際のデータ通信（HTTPリクエスト/レスポンス）が始まる。
   - HTTPS（TLS）の場合、TCP接続確立後にTLSハンドシェイクがさらに行われる。

### まとめ
- SYNフラグは、接続開始を示す1ビットフラグ（SYN=1 → SYNパケット）。
- ACKフラグは、受信確認応答を示す1ビットフラグ（ACK=1 → ACKパケット）。
- 最初のパケットでは SYN=1, ACK=0、2番目では SYN=1, ACK=1、3番目では SYN=0, ACK=1 という値になるのが一般的な流れ。
- シーケンス番号 (Seq) は x や y のように乱数で初期化されるが、ACK番号 (Ack) は相手のSeqに+1をした値を設定する。

これが典型的な3ウェイハンドシェイク時の「SYN/ACKフラグ」と「シーケンス番号/ACK番号」のイメージです。
Raspberry Piでcgpsの緯度経度が更新されない問題

## 背景
以下のRaspberry Piフォーラムと全く同じ問題が起きていた。

https://forums.raspberrypi.com/viewtopic.php?t=331525

u-bloxのGPSモジュールを付けて、`cgps -s`で緯度経度を取得しようとしても値を更新してくれない。一方、`gpsmon`コマンドで表示する場合は、LTP Pos（曲率を無視した座標系）が継続的に更新されていた。

Pythonコード経由でGPS緯度経度を取得しようとしても、`cgps -s`と同じ値のまま更新されず使えなかった。NMEAストリームは正しく流れていた。


## 解決した方法
何らかの理由で、単純にソケットがdisableになっていたことが原因だった。
```
sudo systemctl status gpsd.socket
```

上記のコマンドで `inactive (dead)` と表示された場合、以下を実行することで解決できる。
```
sudo systemctl enable gpsd.socket
sudo systemctl start gpsd.socket
```

### 備考
今回の問題とは関係ないが、屋内でGPS信号が十分に取得できず、屋外に移動しても緯度経度が0.0のまま変わらない場合は、以下の再起動で治ることがある。（今思えばこの過程の中で気付かずdisableにしてしまった可能性がある）

```
sudo systemctl stop gpsd.socket
sudo gpsd /dev/ttyACM0 -F /var/run/gpsd.sock
```
[^1]

[^1]: `ttyACM0`の部分は、GPSモジュールのポートによって`ttyUSB0`などに変更する
localStorage でサイズ制限エラーを出したい

# はじめに
localStorage を使うことになり、サイズ制限エラーを試してみたい！と思って色々調べた結果を残します。

# 実現したいこと
サイズ制限の状態を準備して、localStorage の setItem 呼び出し時に QuotaExceededError を発生させたい。

# やりかた
1.chrome の devtool の consoleで JavaScript を使いサイズ制限エラーが出るまで localStorage を利用
```javascript
for (let i = 0; i < 1000000000000; i++) {
  try {
    localStorage.setItem(`key_${i}`, 1);
  } catch (error) {
    console.error(i);
    console.error(error);
    break;
  }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206526/8f16db92-b86f-9404-0ecc-bd6d88dc6366.png)

2.実際に格納する値でもエラーが出る事を確認する（1でエラーが出るようになっても、実際格納する値ではエラーが出ない事もあるので。）

```javascript
localStorage.setItem('aaaaaaaaaa', 1);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206526/7036dd4e-0e6d-ac2a-398c-b91a1c4a739e.png)

3.お試しが終わったらクリア
```javascript
localStorage.clear();
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206526/33c74bd6-5153-e52f-7089-ac5a33c0b7f9.png)

# 参考資料
https://developer.mozilla.org/ja/docs/Web/API/Window/localStorage
https://developer.mozilla.org/ja/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria

# やりかたに辿りついた流れ
devtoolで一時的に格納できる最大サイズを小さくできないかな？と思い、devtoolをあさっていたら、Application に Simulate custom storage quota のチェックを発見！ 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206526/69962a2d-478a-f772-feff-43b56ffae30c.png)

こちらでサイズを極小にして、localStorageに大量データを格納してもエラーが出ず。

色々調べたけど分からず、GeminiにループするJavaScriptを作ってもらい、少し加工して今の方法に至る。
図解で、Datadog APMにサーバー［Infrastructure］を表示する

# Datadog APM の Infrastructure が表示されないの何故
まずはDatadog APMダッシュボード（下図）を見て、APMダッシュボードのインフラ欄に［N/A］が表示されてサーバー・メトリックスを可視化できないのはちょっと寂しい。これは、DatadogエージェントとAPMのDatadogトレーサーのタグが一致していないことが原因。タグが一致していれば六角形のアイコンが表示される。インフラ側のタグ命名ルールとアプリ側のタグ命名ルールを決めておかないと、あとで困ることになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/782aa47f-c386-231c-4ee8-bb4bd44a4a37.png)

## 悩んだこと
Datadog APM の Infrastructure は３つの予約済みタグで関連付けすることができる。［service］［env］［version］の３つ。サーバー１台にアプリ１個の場合は３つのタグを全て一致させればサーバーのメトリックスが表示される。しかし、サーバー１台に２個以上のアプリを実行する場合はどうやってタグを一致させればよいのかわからなかった。いくつかのパターンを検証したので以下にコンフィグ例を記載する。

## コンフィグ設定（1:1）
サーバー１台にアプリ１個のシンプルな構成の場合は図の通り。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/d6aafcb8-279f-cf26-ab1d-b48370cffe86.png)

▼ Datadogエージェントのコンフィグ例

``` /etc/datadog-agent/datadog.yaml
tags:
  - service:diary
  - env:prod
  - version:3.0
```

▼ Datadogトレーサーのコマンド例（node.js）

``` start.sh
#!/bin/bash
export DD_SERVICE=diary
export DD_ENV=prod
export DD_VERSION=3.0
node -r dd-trace/init app.js
```

## コンフィグ設定（1:N）
サーバー１台に複数アプリＮ個の場合は図の通り。Datadogエージェントのコンフィグに、複数のタグ名を追加してもいいんだという知見ノウハウ。タグ名は１回しか使えないのかと思ってた。けれど公式ドキュメントが見つかりません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/fea92093-6f6b-a55b-5727-715bd5e87df1.png)

▼ Datadogエージェントのコンフィグ例

``` /etc/datadog-agent/datadog.yaml
tags:
  - service:diary
  - service:requests
  - service:minecraft
  - env:prod
  - version:3.0
```

▼ Datadogトレーサー１のコマンド例（node.js）

``` start.sh
#!/bin/bash
export DD_SERVICE=diary
export DD_ENV=prod
export DD_VERSION=3.0
node -r dd-trace/init app.js
```

▼ Datadogトレーサー２のコマンド例（python）

``` start.sh
export DD_SERVICE=requests
export DD_ENV=prod
export DD_VERSION=3.0
ddtrace-run python3 heatrun.py
```

▼ Datadogトレーサー３のコマンド例（java）

``` start.sh
sudo java \
  -Ddd.service=minecraft \
  -Ddd.env=prod \
  -Ddd.version=3.0 \
  -javaagent:/home/kano/dd-java-agent.jar \
  -Xmx2G -Xms1G -jar /opt/minecraft-server/server.jar nogui &
```

## アプリのバージョンを変更する時
アプリをアップデートするとき、アプリを起動するDatadogトレーサーのタグを変更するだろうけど、このときDatadogエージェントのコンフィグを変更しないとどうなるのか検証した。それぞれの組み合わせの図とタグだけ記載し、説明やコンフィグ例は割愛する。

### diaryアプリ ver.3をメジャーバージョンアップして、diary2 ver.4をリリースするシナリオを想定

▼ まずは失敗例から。service, versionタグが一致しない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/012284e8-48f6-a57c-4769-341f8c8ca7e7.png)

▼ これも失敗例。serviceタグを追加したが、versionタグが一致しない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/7b27c4aa-d6dc-21a6-34d3-d83d00c34492.png)

▼ 成功例。公式ドキュメントに見つからないけれど、タグ名が重複しても機能しているようだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189936/ba677afe-cb25-f183-06d8-870e21785c03.png)

以上
【VirtualBox】CentOSインストール時にマウスポインタの可動域が小さくてインストールが進まない時の対処法

■環境
　・VirtualBox-7.0.20

　CentOSインストール時に、マウスポインタの稼働域が小さく、言語のインストール画面の[実行]ボタンを押せない場合、以下を実施する。

 ■手順
1．対象の仮想マシンを右クリックし、[設定]をクリックする。
⇒「設定」画面が開くこと

2．「設定」画面の左ペインから[システム]をクリックする。
⇒「システム」画面が開くこと

3．「システム」画面の[ポインティングデバイス]欄から[USBタブレット]を選択する。
⇒USBタブレットが選択されていること

4．[OK]をクリックする。
⇒「設定」画面が閉じること

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3761139/ff183a4b-9143-4509-e77b-f15974f654ea.png)


■参考URL
https://www.bnote.net/blog/virtualbox6_mouse.html
doctrineのここがイケてない

[doctrine](https://www.doctrine-project.org/)を利用していて、イケてないと思えるポイントを書き出してみた。
なおdoctrineをそこまで熟知しているわけではないので、もしかしたら解決策がある可能性はある。

## 設計に関する課題

### エンティティクラスが何も継承していない

何も継承していないすっぴんのPHPクラスで定義しているので、共通の処理が一切ない。
必要であれば、自前のベースクラスを定義して継承させる設計が求められる。
例えば[この記事のように](https://norbertschvoy.medium.com/base-entities-and-behaviors-for-doctrine-how-i-do-it-06f700763324)。

```php
abstract class BaseEntity {
    protected ?int $id = null;

    public function getId(): ?int {
        return $this->id;
    }
}

class User extends BaseEntity {
    private string $name;

    public function getName(): string {
        return $this->name;
    }

    public function setName(string $name): static {
        $this->name = $name;

        return $this;
    }
}
```

### テーブルの個々の列に対してGetter/Setterが必要

getter/setterだけで数百行になることは珍しくない。
列の名前や型はdoctrine向けのテーブル定義から取得できるはずなので、そもそもこれらは要らないもののはずだ。
getterだけ、setterだけを外から見えないようにしたいニーズは、無くはないが稀だ。

### 保存時に別のテーブルに影響を与えようとした場合の処理が煩雑

`prePersist` や `preUpdate` といった仕組みはあるが、ほぼ自身のデータの更新に限られる。
別のテーブルに影響を与えようとした場合、そのテーブルだけでなく、DBへの保存全体に対するフックを用意し、全テーブルの中からそのテーブルに対して変更が来た場合に、別のテーブルのデータを呼び出して変更する処理が必要になる。

### クエリの書き方が冗長

バックエンドエンジニアは「データベース読み書きエンジニア」と揶揄されている程度にはデータベースとのやり取りが多い。
にも関わらず、doctrineはとにかく記述量が多い。
getter/setterの件もそうだが、基本的にデータを問い合わせる際の記述は冗長だ。
例えば名前が一致するユーザーがいるかどうかを取得しようとした場合、以下のようなクエリを書く必要がある。

```php
$result = $entityManager->getRepository(Order::class)
    ->createQueryBuilder('o')
    ->select('1')
    ->andWhere('o.name = :name')
    ->setParameter('name', $name)
    ->getQuery()->setMaxResults(1)->getOneOrNullResult();

$exists = !is_null($result);
```

特に `where` に関わる部分が冗長で、 AはA'、A'にはA''が入るのような書き方が煩雑だ。
`where`と`andWhere`があるのもトラップに近い。
以下のような構文でできるようになっていて欲しいものだ。

```php
$exists = $entityManager->getRepository(Order::class)
    ->where('name', $name)
    ->exists();
```

## パフォーマンスや動作の課題

### メモリーにくわえ込んで管理する

エンティティをpersistするが、その時点では記録しないし、何ならpersistした後でもflushするまで変更が可能だ。
課題はいくつかある。

- 1つ目は「persistとflushを分ける意味があまり無い」ということ
    - persistとflushをわざわざ分けることで余計な関心事が増えてしまっている。これはtransactionで囲むことで全体が対象であることが分かるし、flushを適宜挟むのは分かりづらさを助長している側面がある
- 2つ目は「PHP側で余計なメモリを食ってしまう」ということ
    - transactionしておけばDB側でより良くメモリ管理をしてくれるところを、PHP側でも余計なメモリ管理コストがかかる
    - 二重管理になるだけで意味があるとは考えづらい
- 3つ目はエンティティがロードされていないなどの場合に「あれが無い」「これが無い」とエラーを吐く点
    - 頼んでもいないのに勝手にエンティティを管理して、不必要にエラーを出して止めてしまう
    - この問題に対処するためには、余計なエンティティをDBからロードするなどの対処が必要になる

### N+1問題に対応する方法がほぼ無い

エンティティで別のテーブルにリレーションを書くと、勝手にロードされてしまうことがある。ここまではよくあることだが、問題は複数エンティティ分をまとめてロードする方法がほぼ無いことだ。
それに対処するためには、自前で必要なエンティティのIDを集めて別途エンティティを取得し、そのエンティティを関連元のエンティティに関連付けなければならない。
そのため、N+1対応をしようとした場合、通常の数倍のコードを書くことになる。

## 雑感

おそらく古めの設計だとこういうこともあるだろう、と感じられる。
doctrineは、私が触ってきたORMの中では、不必要に学習コストが高く感じられた。
記述量や考慮事項が多い当該パッケージを今から採用するメリットはあまり感じられなかった。
AWS S3をJP1/AJS3で監視する

# 背景

近年、AWSサービスとJP1/AJS3を利用するシステムの立案、設計のみならず、運用・保守に携わると必ず聞かれる質問。

__「JP1でAWS S3のファイル監視ってできないの？」__

`JP1/AJS3には「ファイル監視ジョブ」というものがあり、
特定のエージェントホスト上の、特定のファイルに対する、特定のアクション（作成・更新・削除など）を監視できる。
検知したら、後続の業務バッチを実行するなど利用頻度が高いジョブ。
これをAWS S3に置き換えて実現できないかというわけだ。`
	
結論、「できる」。
ただし、標準機能では利用できないため、後述の「AWSサービス連携ツール」の導入が必要となる。

# 前提条件

JP1/AJS3 12-00以降
JP1/AJS3 - View（ジョブを定義する側）環境：Microsoft .NET Framework 4.5 以降

# やること

**日立サポートから「AWSサービス連携ツール」をもらう**

オンラインサポートなどで依頼すればもらえる。導入マニュアル同梱。
基本的に受領したマニュアルに記載されていることを実施するだけでOK。割と簡単。
やることを大まかに上げると、

* エージェントホストに、AWS CLI バージョン2 を導入
* エージェントホストから、AWS S3 へアクセスできるようにする（IAMロールの割り当てなど）
* AWSサービス連携ツールの導入（ファイルの配置とアクセス許可）
* JP1/AJS3 - Viewのセットアップ（カスタムジョブ登録）
:::note info
JP1/AJS3サービスの再起動が必要
:::



上記を実施すると、「Amazon S3連携ジョブ」を定義できるようになる。

# さいごに
「Amazon S3連携ジョブ」は、通常のファイル監視ジョブのようにS3上の特定のファイルを監視できる他、ファイル操作（作成、削除、ダウンロードなど）も可能。
早く、標準機能で実装してほしい…
位置パラーメータ

## 位置パラーメータとは
シェルスクリプト内からコマンドライン引数を扱うためのシェル変数。
```
# test.shの中身
#!/bin/bash
echo $1 $2 $3

test.sh hello world !

# $1 に hello
# $2 に world
# $3 に !
# が渡される

=> hello world !
```

### $0
$0は位置パラメータではなく特殊パラメータの一つ。シェルスクリプトを実行したときのシェルスクリプト名が渡される。
```
# test.shの中身
#!/bin/bash

echo "Execute $0 !"
/
./tesh.sh

=> Execute ./test.sh !
```
### ワイルドカード
コマンドライン引数に 「*」 を渡した場合、現在のディレクトリのファイル、ディレクトリが展開され引数として渡される。
```
# カレントディレクトリにfile_1とfile_2がある場合
ls

=> file_1 file_2

# test.shの中身
#!/bin/bash

echo $1
echo $2

# 「*」に対してカレントディレクトリの内容がそれぞれ位置パラメータに設定される
./test.sh *

=> file_1
=> file_2
```

### 引数の数を参照する
「$#」を利用すると渡されたコマンドライン引数がわかる。
```
# test.shの中身
#!/bin/bash

echo $#

./test.sh a b c d e f g

=> 7
```

### コマンドライン引数をまとめて参照する
「#@」「#*」を使うと、シェルスクリプトに渡されたコマンドライン引数をまとめて扱うことができる。
```
# test.shの中身
#!/bin/bash

echo $@
echo $*

./test.sh a b c d e f g

=> a b c d e f g
=> a b c d e f g
```

「#@」「$*」の違うところは「echo "#@"(あるいは「#＊」)」とダブルクォートで囲った場合
- 「"#@"」を利用した場合
各位置パラメータに渡された引数が、ダブルクォートで分割される。そのためシェルスクリプト内でコマンドにコマンドライン引数をまとめて渡すことができる。
- 「"#*"」を利用した場合
全ての位置パラメータに渡されたコマンドライン引数が一つのダブルクォートに囲まれ一つの文字列となる。
AWS Certified AI Practitioner合格の記録

年始にAWS Certified AI Practitionerを受けて、ギリギリ合格してきました。
合格ラインが700点のところ711点で本当にギリギリでした・・・。 

どんな勉強をしたかについて記録として残そうと思います。

### 前提となる知識レベル
試験前の私のAIに関する知識レベルはこんな感じです。

- AIに関する知識
  - 用語はなんとなく知っているが、詳細に説明するのは難しいレベル
  - AI関連の業務経験はなし
- AWSに関する知識
  - AWS SAAを持っており、AWSサービス全般の知識はある程度あり

試験範囲はAWSだけではなくAIやMLに関わる問題の分量が多いので、AIに関する知識に自信がない人はG検定を受けた方がいいといった記事も見かけました。しかし私は時間が取れずいきなり試験に臨むことになりました・・・。

### 勉強方法
- 参考書

以下の２冊を活用しました。一問一答なので移動時間やちょっとした隙間時間で読み進めることができました。
Kindle Unlimitedで読めるのがありがたいです:pray:

https://www.amazon.co.jp/-/dp/B0DP3MQXF7/

https://www.amazon.co.jp/-/dp/B0DP85MT8D/

- 問題集

全4回分＋補足問題で構成されており、これをひたすら解きました。
解説がとても親切なのですが、自分の知識が及ばない部分もありネットで調べながら知識を補完しました。

https://www.udemy.com/share/10bP133@_jG-pCmXOojqrX4sc5wPYW2hEOdtrdvb77KiUWftMH1iPbC3h5vTaRNK9B3YICT9Sg==/

- AWS Skill Builder
試験直前の理解度の確認でAWS公式の試験問題を解きました。
全20問、無料で何度でも受けることができます。

https://explore.skillbuilder.aws/learn/courses/19791/exam-prep-official-practice-question-set-aws-certified-ai-practitioner-aif-c01-japanese

- 勉強にかけた時間
1ヶ月くらいです。
平日隙間時間はKindleで参考書を読みつつ、週末は練習問題を解きつつ足りない知識を補いような勉強をしました。

### 所感
AWSに限らずAI全般の知識を問われる問題が多く、なんとなく知っていた用語や知識が整理できてよかったです。
2行2列を固定してスクロールできる、ヘッダーが階層化されたテーブル

# 概要

下記のようなヘッダーが階層化(グルーピング)されているテーブルがあります。(下記図のようなテーブル)
そんなテーブルのヘッダーを固定してスクロールできるようにします。

![スクリーンショット 2025-01-25 16.22.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299962/8eea25f2-166b-42d5-416b-2e370cc37bcc.png)

試行錯誤しながらHTML・CSSで実装したので記録として残します。

# 実装方法

`position: sticky` と `z-index` で固定と重なったときを制御します。
私のクラスの振り方が悪いのかもしれませんが、何を対象にするか・しないかに注意しないと固定化されなかったり重なったときの振る舞いが効かなかったりします

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="RNbqQEV" data-pen-title="fool-table" data-user="masayasviel" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/masayasviel/pen/RNbqQEV">
  fool-table</a> by masayasviel (<a href="https://codepen.io/masayasviel">@masayasviel</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>

# おわりに

topとleftの固定位置で幅と高さが若干縮むので、ボーダーを消して背景色のみにして誤魔化すとかtopとleftを調整するとかしてください。
YOLO v8 の環境を Windows で構築する際の注意点

# Python に YOLO を導入する際は
Windows 環境に YOLO の環境を構築する際は、
1. [git for wndows](https://gitforwindows.org/) をインストール
1. `git clone https://github.com/ultralytics/ultralytics`で YOLO (ultralytics) のクローン作製
1. Python の仮想環境作成・アクティベート
1. `python -m pip install --upgrade pip setuptools`
1. `pip install -r requirements.txt` (requirements.txt は、クローンした ultralytics のどこかにある)

という手順で行うと思うのですが、Python のバージョンが高すぎると、5番目の`install`でエラーが出る事があります。
今は解消されているかもしれませんが、昨年 2024/12/26 の段階で、3.13 では上手くインストールできませんでした。
情報を集めた所、別のパッケージですが、同じ様なエラーメッセージでインストールできない方の Web ページを参考に、Python のバージョンを下げてインストールした所、上手くインストールできました。
ただし、この事が後に別の問題を生みます・・・
# YOLO を CUDA (GPU) を使用して動作させるには
YOLO に CUDA の環境を構築するには
1. GPU のドライバを最新にする
1. C++ のコンパイラを入れる
1. [PyTorch のサイト](https://pytorch.org/get-started/locally/#start-locally) で、インストールする CUDA のバージョンを確認
1. [CUDA toolkit](https://developer.nvidia.com/cuda-11-8-0-download-archive?target_os=Windows&target_arch=x86_64&target_version=11&target_type=exe_local) をインストール
1. [cuDNN](https://developer.nvidia.com/rdp/cudnn-download) をインストール
1. [PyTorch のサイト](https://pytorch.org/get-started/locally/#start-locally) で、pip コマンドを生成し、実行

という手順になると思われます。
なお、YOLO をインストールした段階で、CPU 版の PyTorch がインストールされており、GPU 版の PyTorch が上手くインストールできない場合は
`pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 --upgrade --force-reinstall`
の様に、`--upgrade --force-reinstall`オプションを付ける事で強制的にインストール出来るらしいです。

さて、この [PyTorch のサイト](https://pytorch.org/get-started/locally/#start-locally) に、うっすらと灰色で「Latest PyTorch requires Python 3.9 or later.」と書いてあります。
そう、YOLO をインストールする際に、Python のバージョンが高すぎるとインストールできないからと、3.6 や 3.7 を入れると、PyTorch がインストールできません・・・
# 結論
**この記事を書いている時点**では、YOLO で GPU を使う際は、Python のバージョンは 3.9 ベストと思われます。
【DB】クローンとスナップショットの違いをざっくり解説



データベースを運用していると、「**スナップショット**」や「**クローン**」という言葉を耳にすることがあると思います。  
どちらも「DBのコピー的なもの」みたいですが、違いがよくわかっていないかったです。
というこｔ今回は **“クローン” と “スナップショット”** の違いをまとめてみました！

---

## スナップショット (Snapshot) とは？

**スナップショット** は、**ある時点のデータベース状態を読み取り専用で保存**する仕組みのことが多いです。

- **ポイントインタイムの状態を保存**  
  - 「2023/10/05 15:00 の時点でのDBの状態」をぱっと切り出し、そのまま保存しておけるイメージ。
- **通常は読み取り専用**  
  - 作ったスナップショットを直接書き換えることはできない場合が多い。  
  - 後から復旧するときなどに参照する用として使うケースがメジャー。
- **復元が目的**  
  - 不測の事態やデータ破損があったとき、スナップショットから **DBを“巻き戻す”** のに使う。  
  - よくある例：Amazon RDS のスナップショット → 後で RDS インスタンスを新しく作成して復元。

### メリット
- データの**保護**や**バックアップ**用途でわかりやすい。  
- 特定時点の状態を簡単に再現できるので、障害時のリカバリが素早くなる。

### デメリット / 注意点
- **基本的に読み取り専用**で、そのまま別環境に書き込みたいときは別途手順が必要。  
- スナップショットの保存にはストレージ容量がかかる（増分保存の仕組みがある場合もあるが、コスト管理に注意）。

---

## クローン (Clone) とは？

**クローン** は、**既存のデータベースをベースにして、書き込み可能な“複製”を素早く作る**仕組みを指すことが多いです。

- **元のDBの物理データを使いまわしつつ、新規変更だけ差分で管理**  
  - 例：Snowflake の “Zero-Copy Clone” などでは、元データを参照しながら、クローンで行った変更だけ別途保持するので、素早く複製できる＆コストが低い。
- **生成されたクローンは書き込み可能**  
  - 実際にアプリケーション開発・テスト環境で使ったり、新しい機能の実験に使えたりする。
- **スナップショットと違い、編集が前提**  
  - 切り出した複製元とは独立して操作できるので、自由に書き込み可能。

### メリット
- 開発やテストで「本番DBのリアルなコピー」を手軽に用意できる。  
- 差分ベースのクローンを提供する仕組みなら、フルコピーしなくてもいいので高速＆コスト削減。

### デメリット / 注意点
- 差分管理の仕組みによっては元DBのストレージ消費とクローン分を合わせて管理する必要がある。  
- クローン先で勝手に変更して本番データと混同しないように運用ルールが大事。

---

## 違いのまとめ

| 項目               | スナップショット (Snapshot)                   | クローン (Clone)                                     |
|--------------------|-----------------------------------------------|------------------------------------------------------|
| **用途**          | バックアップ / 復元                           | 複製DBを作って開発・テスト・検証などに利用           |
| **読み書き**       | 通常は**読み取り専用**                        | **書き込み可能**（複製DBとして機能）                |
| **作り方**         | 指定時点の状態を記録                          | 元DBを参照しつつ差分を管理して高速に複製            |
| **主な利用シーン** | 災害復旧、データ破損時のリカバリ、監査など     | 開発環境・テスト環境の構築、新機能検証、本番の影響回避|
| **コスト**         | 増分管理の場合もあるが、フルバックアップに近い | 差分管理の仕組みがあればフルコピー不要でコスト削減可|

---

## 使い分けのイメージ

- **障害対策やバックアップ用途**  
  - **「スナップショット」** で定期的に保存しておけば、いざというときに巻き戻し可能。  
- **開発・テスト環境を本番同様に作りたい**  
  - **「クローン」** 機能を使えば、本番の状態をコピーして実験できる。書き込みもOK。

実際には各データベースやサービスで用語が微妙に違うケースがありますが、多くの場合はこのように **“スナップショット = 読み取り専用のバックアップ”、 “クローン = 書き込み可能な複製”** というイメージです。

---

## まとめ

- **スナップショット** は**バックアップ**や**リカバリ**が目的：  
  - ある時点で「どうだったか」を記録し、読み取り用に保管。
- **クローン** は**開発やテストなど実際に書き込み可能な“複製”**：  
  - 本番データと同じ状態を別環境で動かしたいときに便利。

どちらも DB のコピーっぽい動きをしますが、目的や読み書き可否が違うので、ユースケースに合わせて選びましょう！

> もし何か追加の質問や実際のサービス事例などがあれば、コメントで教えてください！  
> この記事が参考になればうれしいです。
記号「⊂ ⊃ の、読み方を、英語と日本語で教えて下さい。」をAI先生に聞きました。


#### 以下、質問事項
⊂　⊃
・上の記号の、読み方を、英語と日本語で教えて下さい。
・違いも教えて下さい。
・何年生で勉強しますか。


# ChatGPT先生へ
>読み方
日本語
「⊂」→ 「部分集合」または「真部分集合」（読み：ぶぶんしゅうごう、しんぶぶんしゅうごう）
「⊃」→ 「包含する」または「真包含」（読み：ほうがんする、しんほうがん）
英語
「⊂」→ "**Subset**"（サブセット）または "Proper Subset"（プロパー・サブセット）
「⊃」→ "**Superset**"（スーパーセット）または "Proper Superset"（プロパー・スーパーセット）

>違い...
(省略)

>何年生で勉強するか...
日本：中学校（**おおよそ中学3年生**）の数学で学びます。特に「集合」の基本概念が出てくる単元で使用されます。高校の集合論（場合の数や論理）でも再度扱われます。

chromebokの文字変換だと、記号　⊃　真上位集合 でます。真上位集合で変換できません。

>...
**「真上位集合」は学術用語**としては適切ですが、日常的なIME（日本語入力システム）ではあまり採用されていない場合があるようです。


# Gemini先生へ
未

# copilot先生へ
未

# いつもの? sympyの実行環境と 参考のおすすめです。
[(テンプレート)](https://qiita.com/mrrclb48z/items/00dd08b0317069be9342)

# いつもと違うおすすめです。
#### Qiita
WorkManagerの情報取得エラー

WorkManagerの情報を取得する時に下記のようなメソッドを呼び出しますが、ある時から`Cannot access class`エラーになりビルドが通らなくなりました。
``` kotlin
WorkManager.getInstance(this).getWorkInfoById()
WorkManager.getInstance(this).getWorkInfosByTag()
```

エラー内容です。原因は同じクラス名が競合してるみたい。
```
Cannot access class 'com.google.common.util.concurrent.ListenableFuture'. Check your module classpath for missing or conflicting dependencies
```

gradleから直接指定することで解決しました。バージョンや指定法方によってはエラーになるようなので、参考のリンクからビルドが通るものを選びます。
```gradle
implementation "com.google.guava:guava:33.4.0-android"
```


#### 参考
https://github.com/google/guava?tab=readme-ov-file#adding-guava-to-your-build

https://stackoverflow.com/questions/74216853/cannot-access-class-com-google-common-util-concurrent-listenablefuture-in-flut
Cognitoを使ったユーザー認証の基本と実践

AWS Cognitoを使ってユーザー認証を実装する機会があったので、備忘録も兼ねて記事を書いてみます。Cognitoは便利ですが、最初はフローに少し戸惑うこともありました。この記事では、基本的な仕組みと使い方をシンプルにまとめています。

## Cognitoとは？
AWS Cognitoは、ユーザー認証と管理を手軽に実現できるサービスです。主に以下の2つの役割があります：
### 1. ユーザープール (User Pool)
ユーザーの登録やログイン、トークンの管理を行うものです。例えば、Webアプリやモバイルアプリにログイン機能を実装したいときに使います。

### 2. IDプール (Identity Pool)
認証済みユーザーに対してAWSリソース（S3やDynamoDBなど）へのアクセスを制御するためのものです。例えば、「ログインしたユーザーだけが特定のファイルをダウンロードできる」ようなケースに使えます。

## 実際の使用例
Cognitoのユーザープールを使ってログイン認証を実装した例を紹介します。例えば、以下のようなリクエストをCognitoに送信することで、トークンを取得できます。

```
POST https://cognito-idp.<region>.amazonaws.com/

{
   "AuthFlow": "USER_PASSWORD_AUTH",
   "AuthParameters": { 
      "USERNAME": "example@example.com",
      "PASSWORD": "password123"
   },
   "ClientId": "xxxxxxxxxxxxxxxxxxxx",
   "ClientMetadata": { 
      "tenant": "my-app"
   }
}
```

これに対するレスポンスとして、以下のようなJSONが返ってきます。

```
{
    "AuthenticationResult": {
        "AccessToken": "eyJraWQiOi...",
        "IdToken": "eyJraWQiOi...",
        "RefreshToken": "eyJjdHkiOi..."
    }
}
```

このレスポンスに含まれるAccessTokenやIdTokenを利用することで、APIの認証が可能になります。

## 使ってみて感じたこと
USER_PASSWORD_AUTH フローを使うと、簡単にトークンを取得できます。そのトークンを使えばバックエンドやフロントエンドでスムーズに認証処理が進みます。特に、CognitoのトークンはJWT形式なので、デコードするだけでユーザー情報がすぐに使えるのが便利だと感じました。
Web Audio API を図に描きながら触れる

## Web Audio API とは

(詳しいことは全て MDN に載っていますが) Web 上 (JavaScript) でオーディオを扱うのに便利な機能が提供されています。

https://developer.mozilla.org/ja/docs/Web/API/Web_Audio_API

この API は、オーディオの入力、加工 (エフェクト)、出力を、モジュールをつなぎ合わせる形で制御できるもので、自由な構成を組み立てることができます。

先の MDN で、下の図が示されています。

![audio-context_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540894/783dda29-275e-6dd7-27c5-7bd4121b3bf0.png)

> ©1998–2025 by individual mozilla.org contributors
> CC-BY-SA-2.5

この記事では、上の図を描きながら Web Audio API を触ってみます。

## Audio context を作る

まずは外枠を作ります。Audio Context と呼ばれます。

```js
const audio_context = new AudioContext();
```

![web-audio-api-graph-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540894/86b924d1-d430-757c-87b3-54e5e3dcb9f9.png)

## Audio node を作る

次に、生成したコンテキストの中に入力、エフェクト、出力のモジュール (Audio node) を生成していきます。

### 入力

オシレータ (発振器) のノードを作ってみます。設定は 1000Hz のサイン波、いわゆるピー音です。

```js
const oscillator_node = audio_context.createOscillator();
oscillator_node.type = "sine";
oscillator_node.frequency.value = 1000;

// .start() を呼ばないと鳴り始めないので注意
oscillator_node.start();
```

![web-audio-api-graph-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540894/50512fb0-9b10-37f2-df19-05078316cfff.png)

### エフェクト

ゲインのノードを作ってみます。音量変更ができます。0 で音無し、1で入力と同じ (増幅も減衰もなし) です。設定は 0.5 (たぶん半分？) です。

```js
const gain_node = audio_context.createGain();
gain_node.gain.value = 0.5;
```

![web-audio-api-graph-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540894/e4da2054-16b7-c0ef-ff98-0e13e5cd666f.png)

### 出力

出力先の node は、何もしなくとも Audio Context に備わっています。

```js
const destination_node = audio_context.destination;
```

![web-audio-api-graph-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540894/2c601f03-cb54-82d2-6611-c06e70ab3b89.png)

## Audio node を接続する

最後に、用意した Audio node を、必要な形に接続します。

```js
oscillator_node.connect(gain_node);
gain_node.connect(destination_node);

// 以下のように書くことも可
oscillator_node.connect(gain_node).connect(destination_node);
```

![web-audio-api-graph-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540894/d78bd524-51dc-6e15-4970-f82adbb56e2d.png)

これで、最初の図のように仕上がりました。

## 完全版デモ

以上を一通り実装するとこんな感じ。

https://codesandbox.io/embed/dj28sg?view=split&module=%2Faudio.js

ちなみに、最近のブラウザでは、ユーザの操作無しできなり音を鳴らすことができません。Click イベントで鳴らすなどしてやる必要があります。

以上、おしまい。
【AWS】CloudTrail と CloudWatch の違いをざっくり解説



AWS を使っていると必ず耳にする **CloudTrail** と **CloudWatch**。両方とも AWS のモニタリング系サービスですが、何が違うの？と思う方もいるのではないでしょうか。  
この記事では、それぞれの基本と違い、使い分けのポイントをざっくりまとめてみます！

---

## そもそも CloudTrail って何？

**CloudTrail** は、**AWS での API 呼び出し履歴を記録・監査するためのサービス** です。

- **対象**  
  - AWS アカウントで行われた**管理イベント**（例えば EC2 の起動や IAM ポリシーの変更など）や一部の**データイベント**（S3 オブジェクト操作など）をログとして保存。  
  - 誰がいつどんな操作をしたかを追跡できる。

- **保存先**  
  - 標準的には S3 にログを出力する。オプションで CloudWatch Logs にも流し込んで可視化やアラートをかけたりできる。

- **用途**  
  - 監査やセキュリティ対策（不審なアクションがないかチェック）。  
  - 障害調査（「いつ誰が何をやった？」を追う）。  
  - リソース操作の履歴が必要なコンプライアンス要件など。

### メリット
- すべての操作ログが蓄積されるので、後から何が起きたかを詳細にたどれる。  
- 標準で多くのサービスに対応していて、連携も簡単。

### 注意点
- **リアルタイム性はあまり期待できない**（少し遅延してログが書き込まれるイメージ）。  
- 保管するログの容量によってはストレージコストがかかる場合もある。

---

## CloudWatch って何？

**CloudWatch** は、**AWS リソースとアプリケーションをモニタリングするためのサービス** です。CPU 使用率やディスク I/O、メモリ使用率（※カスタムメトリクスが必要）などを可視化したりアラート設定できたりします。

- **メトリクス**  
  - EC2、RDS、DynamoDB、ALB など、各種 AWS サービスがデフォルトでメトリクスを CloudWatch に送信。  
  - 自分でカスタムメトリクスを送ってアプリ固有の情報を記録することも可能。

- **ログ管理 (CloudWatch Logs)**  
  - アプリケーションログや Lambda のログ出力をリアルタイムで収集し、監視や可視化ができる。  
  - Metrics Filter などを使ってログの中の特定文字列を検知 → アラートを発火、といった使い方も。

- **アラーム**  
  - しきい値を超えたら SNS 通知を送る、Auto Scaling を発火させる、などの柔軟な設定が可能。

### メリット
- リソースの稼働状況やアプリケーションのログを一元管理＆可視化できる。  
- アラーム機能で素早く問題を検知、通知ができる。

### 注意点
- 監視対象やログの量が多いと、メトリクスやログの取り扱いコストがかさむ。  
- 詳細なメトリクスを取得したい場合や期間を長く保存したい場合などには別途追加料金が発生する（高解像度メトリクスなど）。

---

## CloudTrail と CloudWatch の違い

| 項目                       | CloudTrail                                      | CloudWatch                                             |
|---------------------------|-------------------------------------------------|--------------------------------------------------------|
| **主な目的**              | API 呼び出しの監査・ログ記録                     | リソースやアプリのメトリクス＆ログ監視                  |
| **ログ/データの内容**     | “誰が何をしたか” という操作履歴                   | 稼働状況(CPU,メモリ)やログ情報(エラー数など)             |
| **出力先**                | S3 (標準)、CloudWatch Logs(オプション)          | CloudWatch メトリクス・CloudWatch Logs                 |
| **主なユースケース**      | セキュリティ監査、障害調査、コンプライアンス       | リソースの稼働監視、パフォーマンス可視化、アラート設定  |
| **リアルタイム性**        | やや遅延して記録 (数分)                           | ほぼリアルタイム (数十秒〜数分)                         |
| **料金イメージ**          | 無料枠あり。大量保存時は S3 コストなどに注意       | メトリクス数や保存期間、Logs の GB 数などで変動         |

---

## 使い分けのイメージ

- **操作履歴の監査が必要 → CloudTrail**  
  - 不審な操作がないかチェックしたり、障害時に「どの操作が原因だった？」と調べるなら CloudTrail。

- **システム稼働状況やログを監視 → CloudWatch**  
  - サーバーの CPU 使用率やメモリ、アプリログをリアルタイムにモニタしてアラートを飛ばしたいなら CloudWatch。

- **両方を組み合わせる事例が多い**  
  - CloudTrail のログを CloudWatch Logs に送って、特定の管理イベントをトリガーに通知を受け取ったりすることもできる。  
  - 「操作ログの保管」は CloudTrail、「メトリクス・ログ監視」は CloudWatch と役割分担している感じ。

---

## まとめ

- **CloudTrail** は **「誰がいつ何をしたか」** を追跡する監査ログサービス。  
- **CloudWatch** は **「今どうなってるか、どんなログが出てるか」** をモニタ・可視化・アラートするサービス。

どちらも AWS 運用には欠かせない定番サービスですが、役割が異なるので混同しないようにしましょう。  
大抵は両方設定しておいて、**セキュリティ監査**と**システム監視**をセットで固めるのがオススメです！

--- 

> もし何か不明点や追加情報があれば、コメントで教えてください！  
> この記事が少しでも参考になればうれしいです。