OmniAICreator/Qiita-1.07M huggingface dataset:
ParrotOS isoファイルのダウンロード方法

## ParrotOS isoファイルのダウンロード方法

１：[Parrot Security](https://parrotsec.org/)にアクセスする。

２：Liveを押下する。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887376/04362334-b0b2-7cb6-c8b5-f2dee0630fba.png)

３：Securityを押下する。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887376/de6b7808-1f0e-5aa5-85d7-6b8cabaeeb29.png)

４：AMD64を押下する。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887376/00154f16-e872-3340-c0d2-2d21cbc1ffed.png)

５：Douwload -> ISO imageを押下する。

![スクリーンショット 2024-09-16 205224.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887376/3d8d1f3f-5f1b-e70a-e4a5-026685cd22f2.png)

Parrot-security-6.1_amd64.isoがダウロードされます。
Siv3D for Webで作ったゲームをGitHub Pagesを用いて無料で公開する方法

# 準備
- Siv3D for Webで作成したプロジェクトでビルドを成功させる
- GitHubリポジトリを作成する

# 1.GitHubリポジトリをPublicにする。
GitHubリポジトリのサイトから、SettingのGeneralのページの下の方にChange repository visibilityがあるのでPublicに変更してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620250/352658bc-119f-364d-682f-caed86d49d75.png)

# 2.プロジェクトフォルダにdocsフォルダを作る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620250/23382dd9-3e81-847d-6f46-8e85807f56aa.png)
`docs`以外の名前ではダメなので注意してください。

# 3.四種のファイルをdocsフォルダにコピペ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620250/c1ea72cc-0442-d898-cd09-70ca94e65c59.png)
プロジェクトフォルダ/Emscripten/Release(もしくはDebug)/の中にある`.data`,`.html`,`.js`,`.wasm`の四種のファイルを全て選択コピーし、先ほど作った`docs`フォルダの中に貼り付けてください。

# 4.プロジェクト名.htmlをindex.htmlにする
`docs`フォルダに張り付けたファイルのうち、`.html`ファイルだけは、`index.html`に名前を変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620250/49ff699e-b455-dd70-7fec-b72d26dde7af.png)

# 5.コミットとプッシュを忘れずに
ここまで出来たら一度変更をコミットし、プッシュしておきましょう。


# 6.Pagesの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620250/560f5fae-41ea-7dc5-5f6d-efcd2ee9dbc5.png)
- GitHubリポジトリのサイトから、SettingのPagesに行きます
- Branchの設定を`master` `/docs`とし、`Save`を押します

# 7.完了
ページの作成が開始されるので、1分ほど待ちます。
完了すると、Setting,Pagesの上部にある`Visit site`から作成されたWebページに飛ぶことが出来ます。

# 8.更新
ビルドした後に3~5の手順をもう一度行うと更新できます。
`docs`フォルダを更新してプッシュすると、Pagesが自動で更新されます。（更新の様子はActionsのタブから見ることができます。）

:::note warn
更新が終わった後でも、Webサイトのキャッシュが残っている場合は更新前のサイトに行ってしまうことがあるので注意してください。
:::
linuxシステムでリバース・エンジニアリング

この程、どうしても必要に駆られて、リバースエンジニアリングをすることになり、記録を残しておきます。

### コマンド

```
objdump -d a.out
```

-dは逆アセンブルのオプションです。unixシステムはobjdump -dでそれぞれのシステムのバイナリコードを逆アセンブルできると思います。

### objdumpのインストール

binutilsに入っていると思うので、archlinuxの人は特にインストールしなくてもいいでしょう。

### x86_64の例

```
a.out:     ファイル形式 elf64-x86-64


セクション .init の逆アセンブル:

0000000000004000 <_init>:
    4000:	f3 0f 1e fa          	endbr64
    4004:	48 83 ec 08          	sub    $0x8,%rsp
    4008:	48 8b 05 c1 2f 00 00 	mov    0x2fc1(%rip),%rax        # 6fd0 <__gmon_start__@Base>
    400f:	48 85 c0             	test   %rax,%rax
    4012:	74 02                	je     4016 <_init+0x16>
    4014:	ff d0                	call   *%rax
    4016:	48 83 c4 08          	add    $0x8,%rsp
    401a:	c3                   	ret

セクション .plt の逆アセンブル:

0000000000004020 <strncmp@plt-0x10>:
    4020:	ff 35 ca 2f 00 00    	push   0x2fca(%rip)        # 6ff0 <_GLOBAL_OFFSET_TABLE_+0x8>
```
CloudShell で cfn-lint と cfn-nag を使う

使ってみたかったけど環境を準備するのが面倒だったので `CloudShell` で使えるようにする方法を調べました。

`CloudFormation` のテンプレートは `template` に格納しているとします。

```bash:cfn-lint
pip install cfn-lint

# バージョン確認
cfn-lint --version

# 使い方
cfn-lint template/*
```

```bash:cfn-nag
sudo dnf install -y ruby ruby-devel gcc
sudo gem update --system
sudo gem install cfn-nag -N

# バージョン確認
cfn_nag --version

# 使い方
cfn_nag_scan --input-path template
```
Reactを用いての初めてのアプリ作成

## 学習記録アプリ作成
作成したアプリは学習内容と学習時間のフォームを用意してその二つの内容を登録する、登録後学習時間をカウントする。

## 感じたこと
一から自分で作るとファイル名や変数名など含めて考える部分が多く、特にReactについては慣れてないため色々考えさせられた。実際の案件などではルール付けなどがされているケースなどもあるかと思われるため、どういう名前付けなどをすると他の方がコードを読みやすいかなど想定して実装できるようになりたいと感じた。
propsについても受け渡しする変数の記載ミスなどで、エラーが出たりするケースがあったためもっと学習していきます。

## 学んだこと
propsを使って複数のonChangeイベントをまとめる方法について
最初はイベント名を分けて実装をしようとしたが、下記方法で実施
```jsx
  const handleChange = (event) => {
    const { name, value } = event.target;
    if (name === 'name属性') {
      set変数(value);
    } else if (name === 'name属性') {
      set変数(value);;
    }
  };

 <input
 handleChange={handleChange}
 />
```

```jsx
export const input = (props) => {
  const { handleChange } = props;

  return (
    <>
      <div className="p-5">
        <input type="text" name="name属性" value="value値" onChange={handleChange}  />
      </div>
      <div className="p-5">
        <label htmlFor="">学習時間</label>
        <input type="number"  name="name属性" value="value値" onChange={handleChange}/>
      </div>
    </>
  );
};

```


## 実際に作成したアプリ画像
![スクリーンショット 2024-09-16 20.33.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880277/dfb79504-b38b-0bd0-1e85-a55da6735745.png)
GIthubの操作をミスったときによく使うコマンドメモ

<h3>①直前のコミットを取り消し、変更はステージングエリアに残されたままにする（git addされたままにする）</h3>

```powershell
$ git reset --soft HEAD^
```
<h3>②直前のコミットも取り消し、ステージングエリアからも変更を取り消す</h3>

```powershell
$ git reset --hard HEAD^
```
**※過ってマージコミットしてしまった場合も、これを使うことでマージ前の状態に完全に戻せる**
____

<h3>③git addしたファイルを全て git addされていない状態に戻す</h3>

```powershell
$ git reset
```
<h3>④git addしたファイルのうち、特定のファイルを git addされていない状態に戻す</h3>

```powershell
$ git reset <git addを取り消したいファイル名>
```
____

<h3>⑤マージの途中で何らかの理由で取り消したい場合、進行中のマージを中止する</h3>

```powershell
$ git merge --abort
```

<h3>⑥履歴は保持するようにして、マージコミットは元に戻す</h3>

```powershell
$ git revert -m 1 <マージコミットのハッシュ>
```
※<マージコミットのハッシュ> は取り消したいマージコミットのID
※-m 1 は、最初の親ブランチを指定したもの（マージコミットには複数の親があるため、元のブランチがどちらであったかを明示する必要がある）

____

<h3>⑦githubに一度pushしてしまったファイルの名前を付け替える。（大文字小文字など）</h3>

※githubにpushしたファイル名は大文字・小文字は区別されるものと思って注意が必要
（下では、Laravel（PHPのフレームワークの１つ）のあるプロジェクト内のフォルダの Contactcontroller.php を ContactController.phpに直す場合）

```powershell
$ git mv app/Http/Controllers/Contactcontroller.php app/Http/Controllers/Contactcontroller2.php
#                      （github上）                          （一旦変換用の名前につけかえ）
$ git mv app/Http/Controllers/Contactcontroller2.php app/Http/Controllers/ContactController.php
#                                                                           ↑(直したい名前)
```

<h1>その他参考資料</h1>

@Sicut_study (渡邉 臣 | JISOU) in JISOU | 経験者専門プログラミングコーチング さん、Qiita

https://qiita.com/Sicut_study/items/0318cc136c189b179b7f
Unity でキャラクタを1マスごとスムーズに動かす

ローグライクゲームとかである、キャラが動き出したら必ず次のマス目まで移動して、升目の決まった位置にくるまでは次の方向キーを受け付けない、みたいな動作の実装方法の一つをメモしておきます。

下記スクリプトと CharactorController を動かしたいオブジェクトにアタッチしておきます。エディタで moveSpeed に適当な値を入れます。デフォルトは 0 なので、そのままでは動きません。

`transform.posotion` を直接いじっているので、衝突判定などで問題がおこるかもしれませんが、ターン制のローグライクゲームならアクション要素はないはずなのでたぶん大丈夫（多分）。

```.cs
using UnityEngine;

[RequireComponent(typeof(CharacterController))]
public class PlayerController : MonoBehaviour
{
    public float moveSpeed; //移動速度
    private CharacterController controller;
    private Vector3 moveVelocity;

    int x = 1; // player の論理的 X 座標
    int z = 1; // plyaer の論理的 z 座標

    int nextX = 1; // 移動先論理 X
    int nextZ = 1; // 移動先論理 Z

    bool waitingCommand; // キャラクタが移動のアニメーション中かどうか

    void Start()
    {
        controller = GetComponent<CharacterController>(); //CharacterControllerを取得
        waitingCommand = true;
        controller.transform.position = new Vector3(x, 1, z * SceneController.SCALE);
    }

    private void Update()
    {
        Vector3 pos = controller.transform.position;
        if (waitingCommand == true)
        {
            if (Input.GetKey(KeyCode.D)){
                nextX = x + 1;
            }
            if (Input.GetKey(KeyCode.A)){
                nextX = x - 1;
            }
            if (Input.GetKey(KeyCode.S)){
                nextZ = z - 1;
            }
            if (Input.GetKey(KeyCode.W)){
                nextZ = z + 1;
            }
            if (nextX != x || nextZ != z)
            {
                // 0-99 の範囲に移動を制限
                if ( nextX < 0 || !(nextX < 100) || nextZ < 0 || !(nextZ < 100) ){ 
                    waitingCommand = false;
                    moveVelocity = (new Vector3(nextX - x, 0, nextZ - z))
                         * moveSpeed;
                    //Debug.Log(moveVelocity);
                }
                else // 移動できない
                {
                    nextX = x;
                    nextZ = z;
                }
            }
        }
        else
        {
            Vector3 delta = moveVelocity * Time.deltaTime;
            //Debug.Log(delta);
            Vector3 nextPos = new Vector3(nextX, pos.y, nextZ);
            
            if (Vector3.Distance( pos, nextPos) <= Vector3.Distance(delta, new Vector3(0,0,0 )) )
            {
                pos = nextPos;
                waitingCommand = true;
                x = nextX;
                z = nextZ;
            }
            else
            {
                pos += delta;
            }
            controller.transform.position = pos;
        }
    }
}
```
【Hackathon Experience with RevenueCat and MeltingHack】15 Days of Learning, Innovation, and Teamwork #Buildin

# はじめに
この度、**MeltingHack** 主催、**RevenueCat** スポンサーによるハッカソンに参加しました。15日間のこのイベントは、技術的なスキルの向上、チームワーク、そして新しいツールとの出会いの場となりました。特に**RevenueCat**の提供するサポートが非常に魅力的で、アプリ開発に使える資金援助があるという点で大きなモチベーションとなりました。

# チーム結成とアイデア
初日、素晴らしい才能を持つ開発者やアイデアを持つ参加者たちと出会いました。何人かは既に具体的なプランを持っており、私はどのチームに参加するべきか迷いましたが、最終的に興味のあるプロジェクトに参加しました。チームにはマーケティング担当者と私（フロントエンドエンジニア）しかいなかったため、iOS開発者、Android/バックエンド開発者を一人ずつ見つけ、チームが完成しました。

# 開発のプロセス
翌日には、開発環境を決定し、アプリの設計と計画を立てました。私はUI/UXの担当として大きな挑戦を受けましたが、この機会を楽しみました。平日は各自の仕事がある中で、みんなで協力し合い、デザインやアプリプランを進めました。

週末には、東京イノベーションセンターで再集合し、プロジェクトをさらに進めました。ここは無料で使える素晴らしいワーキングスペースで、事前登録とQRコードの提示で簡単に利用可能です。

#チャレンジと解決策
プロジェクトを進める中で、Apple Developerアカウントの承認が何度も拒否されるという問題に直面しましたが、チームメンバーの努力のおかげで、この課題を克服することができました。

# 会場巡り
このハッカソンは15日間にわたり、さまざまな企業の素晴らしいオフィスを巡る体験でもありました。最初の日は**Artience**、次の日は**MoneyForward**、その次は**Mercari**、その後は**DeNA**での開発日があり、最終日には再び**Artience**での発表が行われました。どのオフィスも美しい景観と優れた設備を持っており、非常に刺激的でした。

# 最終結果とこれから
最終日には、他のチームの素晴らしい成果に感銘を受けつつ、我々のアプリも無事に発表することができました。そして、スコアリングの結果、私たちのチームは2位を獲得！信じられないほど嬉しい瞬間でした。これからは、11月20日までに最終プロダクトを完成させる必要があります。

この機会を提供してくれた**RevenueCat**、そしてハッカソンを主催した**MeltingHack**に心から感謝しています。
Oracle Database VaultとAudit Vaultの両方導入する必要はある？

Oracle Database VaultとOracle Audit Vaultは、それぞれ異なる目的のために設計されており、特定のセキュリティニーズに応じて両方を導入するかどうかを判断する必要があります。以下に両者の機能と違いを説明します。

**1. Oracle Database Vault**
- **目的:** データベース内の不正アクセスや内部の不正行為を防止し、データベース管理者 (DBA) や特権ユーザーのアクセスを制限することが目的です。
- **機能:**
  - セキュリティポリシーを作成し、特定のアクションを制限。
  - 機密データへのアクセスを制限し、DBAでさえもアクセスできないように制御可能。
  - 役割ベースのセキュリティを強化し、権限の分離を実施。

**2. Oracle Audit Vault**
- **目的:** データベースやその他のシステム（ファイルシステム、オペレーティングシステムなど）の監査情報を収集し、監査ログを一元的に管理することです。特に不正な操作や異常な動作を追跡するための監視に焦点を当てています。
- **機能:**
  - 監査ログの収集とレポート。
  - 不正アクセスや異常な操作の検出。
  - データベース以外のシステムからのログ収集にも対応。

**両方を導入する必要があるか？**
- Database Vault は主にアクセス制御に焦点を当てており、特権ユーザーや管理者からのデータ保護に優れています。
- Audit Vault は監査・追跡に特化しており、誰が何をいつ行ったかの証跡を提供します。

これらは補完的な機能を持っているため、セキュリティ要件が高い場合、両方を導入することが推奨されます。特に、アクセス制御の強化（Database Vault）と、監査・ログ管理（Audit Vault）の両方が求められる環境では、二重のセキュリティを実現できます。

そのため、アクセス制御だけでなく、監査ログの収集と分析が必要な場合は、両方の導入を検討する価値があります。
ParallelsでWin11をSysprepしてMac間で移動してみる

# やりたいこと
- ParallelsのWin11仮想マシンをSysprepしてみる。
- その状態の仮想ディスクを別のMac Miniにつけかえて起動するかテストする。

# 結論
:::note
- なんのエラーもなく移動が可能でした。
- 1つのpvmファイルにVMの構成・仮想ディスク・スナップショットがまとまっているのでコピーするだけでとてもラク。
:::

# Sysprepする
- 「一般化」と「シャットダウン」にチェックを入れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/e83bc219-4fec-0ba3-ff27-f6c8f8e88f82.png)

- 初回はだいたいエラーになるのですが、Bitlockerが進行してるのとストアアプリが原因なことがほとんどです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/7b20a31a-8105-10a6-9a59-a14811f1a619.png)

- 自分の場合はBitlockerを停止して、Widgetと言語パックのストアアプリを削除すればいけました。

```.ps1
Get-AppxPackage -AllUsers Microsoft.LanguageExperience* | Remove-AppxPackage -AllUsers
Get-AppxPackage -AllUsers Microsoft.Widget* | Remove-AppxPackage -AllUsers

# エラーログフォルダの確認
Invoke-Item "%WINDIR%\System32\Sysprep\Panther\"
```
- ワイルドカードで後方あいまい検索できるので思ってたよりラクでした。Sysprepへの心理的ハードルが下がった！


# pvmファイルのコピー
- Mac Mini No1.からNo.2にコピー。
- Parallelsコントロールセンターの「新規作成」から、右下の「開く」を押してpvmファイルを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/390d14da-32a2-23e6-fb8a-4b5c81c9d004.png)

- すると一瞬ですべての構成・スナップショットふくめて復元されます。あっけないほど簡単です。


# pvmファイルの中身
- 32GBのpvmファイルの中身は以下のようになっていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/dfab5b00-cf8d-52f5-5ea5-bde5fc27e1af.png)

- スナップショットのサイズも最低限に抑えられいてるような印象です。ほんと感心しかない。
- 逆にHyper-Vはなんであんな複雑なんだ・・・？（構成ファイルが別で、スナップショットは移動できない）
- Parallelsしか勝たん。。。スペルが打ち間違えやすいのだけ玉にキズ。

# ポエム
- 10月～11月くらいに[Mac Mini M4がメモリ16GBをベースに登場](https://www.gizmodo.jp/2024/08/m4-mac-has-16gb-ram.html)するようです。
- Parallels運用はメモリが命なので、本当ならありがたい。
- USBはAを廃止してCポートのみとのこと。こういうAppleの無駄を省く設計がとても魅力的。
- AppleTVくらいのサイズらしいので、リモートワーク用途にも活躍しそうです。ノート持ち運ぶよりセキュアですね。
Lambda関数でMySQLに接続する（パブリックレイヤー）

AWSが提供しているライブラリには直接MySQLデータベースと接続する機能は含まれていないため、LambdaでRDSのMySQLに接続する場合、PyMySQLなどの外部ライブラリを使う必要がある。

## レイヤー追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3412108/f41bd875-cf0d-41bb-6c7f-74fa61612888.png)

レイヤーソース：ARNを指定
パブリック公開されているレイヤーのARNを指定する

https://github.com/keithrozario/Klayers/tree/master/deployments

arn:aws:lambda:ap-northeast-1:770693421928:layer:Klayers-p311-pymysql:1

ランタイムとレイヤーのPythonバージョンは合わせる
※バージョンが異なると、ライブラリのバイナリや依存関係が異なるため、互換性の問題が生じる可能性がある

参考サイト：https://qiita.com/kyuu2197/items/46ef484db8e54bc74069

## lambdaコード
```python
import pymysql
import os

def lambda_handler(event, context):
    # RDSの接続情報を環境変数から取得する
    rds_host = os.environ['RDS_HOST']
    rds_user = os.environ['RDS_USER']
    rds_password = os.environ['RDS_PASSWORD']
    rds_db = os.environ['RDS_DB']
    
    # データベース接続
    connection = pymysql.connect(
        host=rds_host,
        user=rds_user,
        password=rds_password,
        database=rds_db
    )

    try:
        with connection.cursor() as cursor:
            # SQLクエリを実行
            cursor.execute("SELECT VERSION()")
            result = cursor.fetchone()
            print(f"Database version: {result[0]}")
    
    finally:
        connection.close()

    return {
        'statusCode': 200,
        'body': 'Success'
    }
```
react-hook-formのwatchでフォームの入力された値を表示する

# はじめに
react-hook-formを使っていて、watchというフォームの値を監視する便利なものを見つけたので使い方をまとめたいと思います。

# watchとは
react-hook-formのフォームの状態を監視できる機能です。
例えば、inputに入力した値の状態を監視して、入力された値を画面に表示することができます。
useStateで状態をsetして、そのつど処理を挟まなくてもwatchで変更を監視してくれます。

# 実際に使用してみる
入力された値を画面に表示する処理をuseState, watchでそれぞれ試してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1328154/8e67d67d-5b69-7638-c499-642ec65346ce.png)

## useStateの場合
useStateでinputValueを定義し、onChangeイベントにより、値が変更されるたびにsetInputValueを行い値の変更を反映する。
```react
import { useState } from "react";

export default function App() {
  const [inputValue, setInputValue] = useState("");
  // フォームが送信されたときの処理
  const handleSubmit = (event) => {
    event.preventDefault();
    // ここでフォームデータを処理する
    console.log('入力された値:', inputValue);
  };

  // フィールドの値が変更されたときの処理
  const handleChange = (event) => {
    setInputValue(event.target.value);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={inputValue}
        onChange={handleChange}
      />
      <input type="submit" value="送信" />
      <div>現在の値: {inputValue}</div>
    </form>
  );
}
```

## watchの場合
`register("inputValue")`のinputValueの値を監視したい場合は`const inputValue = watch("inputValue");`のようにwatchで("registerの値")で定義することにより値を監視。
```react
import { useForm } from "react-hook-form";

export default function App() {
  const { register, watch, handleSubmit } = useForm();

  // inputValueフィールドの値を監視
  const inputValue = watch("inputValue");

  const onSubmit = (data) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("inputValue")} />
      <input type="submit" value="送信" />
      <div>現在の値: {inputValue}</div>
    </form>
  );
}
```

## まとめ
useStateとwatchそれぞれで変更された値を表示してみましたが、watchの方がuseStateより簡単に変更された値を表示できました。
フォームに入力された値を使って画面に表示したり、なにかの処理を行いたい場合は、watchを使ったほうが簡単に実装できると思います。
【極秘】Citrix NetScaler 設計構築マニュアル

# 【極秘】本マニュアルについて

本マニュアルは、Citrix 社が提供する ADC (アプリケーション・デリバリーコントローラ) 製品である NetScaler の設計構築をするエンジニアのためのマニュアルです。
特に、初めて NetScaler を扱う人を対象に、基礎知識から詳しく丁寧に説明しています。

また NetScaler に詳しくない新人の教育をする際にも利用できるのではないかと思います。

なお、NetScaler という名称ですが、これまでに NetScaler → Citrix ADC のように変わってきていますが、現時点では NetScaler という名称に戻ってきたようです。

NetScaler については公式ドキュメントを除きネット上にほとんど情報が無く、設計構築に苦労している人も多いのではないでしょうか。そんな中当方では幸いにも検証環境を得ることができました。検証して得たナレッジをネット上に蓄積したいと思いますので参考にしていただければと思います。

# 基礎知識

https://kagechiku.com/citrix-netscaler-reset/

https://kagechiku.com/citrix-netscaler-license/

https://kagechiku.com/citrix-netscaler-upgrade/

https://kagechiku.com/citrix-netscaler-backup/

# 冗長構成 (HA構成)

https://note.com/shadowgarden_org/n/n01ad9a655d90

# ネットワーク系設定

https://kagechiku.com/citrix-netscaler-ipvlan/

https://kagechiku.com/citrix-netscaler-staticroute/

# 証明書関連

https://kagechiku.com/citrix-netscaler-certificate/

# Citrix Gateway 系設定

https://kagechiku.com/citrix-netscaler-icaproxy/

# 認証系設定

https://note.com/shadowgarden_org/n/nc351c48e4bd1
rex0220 計算式プラグイン テーブル初期設定(DIC関数版)

[計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)で、DIC関数を使ってテーブルを初期設定してみます。

# 概要

DIC関数を使って、テーブルの初期データを作成することが出来ます。
DIC関数は、フィールドコードと値の組合せで初期データを作成するため、フォーム上の項目やログインユーザーの値で設定値を変えることが出来ます。
※計算式プラグイン Ver.81以降でサポート

テーブルの初期設定例
![2024-09-16_19h10_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/6e476b94-ca94-d3df-db72-fc4962f471e4.png)

# 計算式プラグイン設定

- ARRAY_FOR 関数で 6行分のダミーデータを作成
    - 区分T1,文字列T1,数値T1 に、DIC 関数で値を設定
        - 区分T1: 交互に "A","B" を設定
        - 文字列T1: "TEST"&(idx+1) ※行番号
        - 数値T1: RANDBETWEEN(10,100)*10 ※乱数で数値を設定
- 作成したオブジェクトデータを JSON_S 関数で文字列に変換

![2024-09-16_19h13_52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/d7af219f-2838-4ad5-4ee0-68494560da30.png)

```.js
// テーブル SUBTABLE (editable)
JSON_S(ARRAY_FOR(6,idx,
  DIC(
    "区分T1",IF(idx%2,"B","A"),
    "文字列T1","TEST"&(idx+1),
    "数値T1",RANDBETWEEN(10,100)*10
  )
))
```

# 初期データの内容

計算式ツールで、テーブルの計算式を実行して、内容を確認することが出来ます。

![2024-09-16_19h15_39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5701f4d7-9d0e-6f7e-863d-9a753bf02173.png)

- 初期データ

19:15:22> exec: [{'区分T1':'A','文字列T1':'TEST1','数値T1':230},{'区分T1':'B','文字列T1':'TEST2','数値T1':220},{'区分T1':'A','文字列T1':'TEST3','数値T1':740},{'区分T1':'B','文字列T1':'TEST4','数値T1':170},{'区分T1':'A','文字列T1':'TEST5','数値T1':120},{'区分T1':'B','文字列T1':'TEST6','数値T1':210}]
【豆知識】コンテナに入ると似たような名前が2つあったけど違いを理解していなかった

# はじめに
`docker ps` コマンドで実行中のコンテナを確認しましたが、なぜ2つ存在するのか。初期で学習したであろう内容。教わっただけでなんとなくの理解で終わっていたので自分で調べて再確認していきたいと思います。

## 環境
- Windows, WSL
- Docker
- Ruby 3.2.3
- Rails 7.1.3


```
$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS                    PORTS                    NAMES
10decb16164c   AAA   "bash -c 'bundle ins…"   14 minutes ago   Up 14 minutes             0.0.0.0:3000->3000/tcp   AAA-1      
483375b2e402   postgres       "docker-entrypoint.s…"   14 minutes ago   Up 14 minutes (healthy)   0.0.0.0:5432->5432/tcp   AAA-db-1 
```
- 出力の`NAMES`列に表示されているのがコンテナ名です。


## 1：表示された2つのコンテナの役割
1. **`AAA`**:
    - **イメージ**: `AAA`
    - **役割**: これはアプリケーションのウェブサーバーを実行しているコンテナになります。Ruby on RailsやDjangoのようなウェブフレームワークが実行されている可能性が高く、このコンテナが、ウェブリクエストを処理し、ユーザーインターフェイスを提供する役割を果たしています。
2. **`AAA-db-1`**:
    - **イメージ**: `postgres`
    - **役割**: これはデータベースサーバーを実行しているコンテナになります。PostgreSQLが動作しており、アプリケーションがデータを保存・取得するために使用します。



## 2：どのコンテナを使うべきか？

たびたび、「コンテナ内で実装」という文言を見かける事があったのですが。どちらのコンテナを使えばいいのか改めて悩む機会がありました。

例として、新たに投稿一覧に関するポストモデルを作成する場合、アプリケーションのコードやデータベーススキーマを変更することになります。

- **アプリケーションのコードを編集**:
    - 新しいモデルを定義したり、マイグレーションファイルを作成したりする場合は、`AAA-1` コンテナ内で作業します。
    - コード編集、マイグレーションの実行、アプリケーションのビルドなどの操作はすべてこのコンテナで行います。
    - 
- **データベースに関する操作**:
    - マイグレーションを実行する際、実際にデータが保存されるのは `AAA-db-1` コンテナにあるデータベースですが、これを直接操作することは少なく、通常はウェブコンテナ (`AAA-1`) を通じて行うことになります。


### 具体的な操作例

- **モデル作成**:
    - `AAA-1` コンテナに入って、Railsの場合、以下のようにコマンドを実行することになります
        
        ```bash
        docker exec -it AAA-1 bash
        rails generate model Post title:string content:text
        ```
        
- **マイグレーション実行**:
    - マイグレーションも同様に、`AAA-1` コンテナで行うことになります。
        
        ```bash
        rails db:migrate
        ```
        
### 補足
- **すべてのコンテナを確認したい場合**は、`docker ps -a` コマンドを使用すると、実行中のものだけでなく停止したコンテナも含めたリストが表示されます


# さいごにまとめ
- `docker compose exec web bash`というコマンドをよく利用していますが`docker exec -it AAA-1 bash`単一で行えるコードもあることを今回知る、認識することができてよかったです。
- `docker compose exec web bash`は`docker-compose`コマンドを使っていて、複数のコンテナを一緒に管理する場合に便利です。（例えば、データベース、Webサーバー、バックエンドサービスなどを1つのセットとして扱うときに使います。）
- 今回の記事が何か参考になれば幸いです。
Typescript✖️Reactのプロジェクトを作成する

## はじめに
TypeScriptを学習しよう！と思い立ったものの、プロジェクトを１から作成するのは面倒・・・
そこで、開発環境を整えてくれる便利なツールを使って、効率的に学習を進める方法を備忘録としてまとめます。

## 作成 → 実行
以下のコマンドをローカル上の任意のディレクトリで実行することで、簡単にプロジェクトの作成から実行まで行えます。

```zsh: Terminal
# TypeScriptを使用したプロジェクト(tsx-app)を作成
npx create-react-app tsx-app --template typescript

# 依存関係をインストール
npm install

# 開発サーバーを起動
npm run start
```

コマンドの説明としてはこちらが分かりやすかったです。

（参考記事）

https://qiita.com/course_k/items/98f7b95446b51f0d2ff2

## メリット
`create-react-app`コマンドを利用することで、WebpackやBabelなどの面倒な設定を自動で行ってくれるため、簡単にReactプロジェクトを始めらます。

## 注意点
しかし、なんと、この`create-react-app`は非推奨らしい。
現在は`Vite`が主流。
とのことで、これからは`vite`を使用したプロジェクトを作成した方が良いとのこと。

githubディレクトリで実行。

```zsh: Terminal
# 以下を入力してEnter
npm create vite@latest tsx-vite-app

# 成功すると、viteの最新バージョンが表示される。
Need to install the following packages:
create-vite@6.0.1
# yを入力してEnter
Ok to proceed? (y) y

> npx
> create-vite tsx-vite-app

# Reactを選択してEnter
? Select a framework: › - Use arrow-keys. Return to submit.
    Vanilla
    Vue
❯   React
    Preact
    Lit
    Svelte
    Solid
    Qwik
    Angular
    Others

✔ Select a framework: › React
# TypeScriptを選択してEnter
? Select a variant: › - Use arrow-keys. Return to submit.
❯   TypeScript
    TypeScript + SWC
    JavaScript
    JavaScript + SWC
    React Router v7 ↗

# 下記内容が表示されていれば作成完了！
✔ Select a framework: › React
✔ Select a variant: › TypeScript

Scaffolding project in /Users/{ユーザ名}/github/tsx-vite-app...

Done. Now run:

  cd tsx-vite-app
  npm install
  npm run dev
```

（参考記事）

https://dev.to/ag2byte/create-react-app-is-officially-dead-h7o

https://qiita.com/dragon-develop/items/34996f8a8931f28ec8ce

## 最後に
１からTypeScriptとReactを使用したプロジェクトを作成しようとすると、package.jsonやtsconfig.jsonなどの設定ファイルを編集する必要があります。
しかし、学習目的であれば `create-react-app` や `Vite`を使うことで環境設定の手間を省くことができ、効率的に学習を進められると思います！

# JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？

気になる方はぜひHPからお願いします👇

https://projisou.jp
ARM Templateについて

ARM Templateとは
--
Azure リソースのインフラ構成をコードにて定義することで、インフラ構成を把握しやすく、信頼性と再現性を向上させることがメリットである
また、デプロイの自動化もできる

内容はIaCとほぼ類似している

https://www.redhat.com/ja/topics/automation/what-is-infrastructure-as-code-iac

https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/templates/overview

ARM Templateのベストプラクティスについてまとめる
--

テンプレートの制約
--
・テンプレートのサイズは4MBに制限し、各リソース定義は1MBに制限する
・制限の内訳は、反復的なリソース定義、変数及びパラメータの値でテンプレートが拡張された後の最終状態に適用される

パラメータも4MBに制限される

親テンプレート、子テンプレート、パラメータファイルの合計は、4MBである必要がある
超えてしまった場合、ARMのリクエストサイズが4MBで限界だから


リソースグループ
--
ARM Templateにて定義したリソースをリソースグループへデプロイする
その際に、リソースグループにはリソースに関するメタデータが保存される

リソースグループのリージョンが一時的に利用できなくなった場合、リソースグループ内のメタデータの更新ができなくなるため、リスクを最小限に抑えるためには、リソースグループとリソースを同じリージョンに配置することが推奨される

個人的には、可用性が低下することはサービスの定義において、反するのではないかと個人的に思いますが、こちら要件によりきりな気がします

具体的には以下のトレードオフがあります
同じリージョンに配置するメリット
・リソースとリソースグループが同一リージョンにあることで、更新が一貫性を持ちやすい
・ネットワーク遅延が少なく、高速な更新が可能

デメリット
・リージョン障害時にリソースとインフラ更新の影響を受ける
・可用性が低下する

異なるリージョンに配置するメリット
・可用性の向上

デメリット
・リソース更新が制限される
・ネットワーク遅延やデータ転送コストが増加


可能性の話なので、数字で出した方が判断しやすいと思いますが、こちらでは記載と調査は、割愛させていただきます
この辺がとても重要なのは重々承知ですが、リソースが限られているため、時間があるときに検証してみたいと思います

パラメータ
--
・パラメータの使用を最小限に控える。代わりに変数やリテラル値を使用する
・パラメータ名にはキャメルケースを使用する
・SKU,Size,Capacityなど、環境に応じて異なる設定にはパラメータを使用する
・簡単に識別できるようリソース名にパラメータを使用する
・メタデータ内のすべてのパラメータの説明を提供する

メタデータの件ですが、テンプレートの制約を認識つつ、可読性を上げる必要があります

defaultValue
・気密性のないパラメータの指定に必要

secureValue
・ユーザ名とパスワードなどの機密性があるパラメータの指定使用する
使用することで、デプロイ後に読み取れなくすることができる。また、型はsecureStringを使用する

変数
--
・変数名はキャメルケースを使用できる
・テンプレ―ト内で複数回使用する値がある場合は、変数を使用する。複数使用しない場合は、ハードコードの方を使用することで、可読性が上がる
・テンプレート関数の複雑な組み合わせから構築した値は、変数を使用する。こちらも同様に可読性が上がる
・テンプレートの セクションでは参照関数を使用できません。
・一意である必要があるリソース名には変数を含めて使用する。ただし、参照関数は使用できないため、注意する

リソースの依存関係
--
・depensonの過剰の使用は避ける。
処理の複雑性の回避とデプロイ時の効率性を上げるために

・子リソースを親リソースに依存するように設定します。
子リソースはデフォルトで親リソースに依存するため

・リソースは直接依存しているリソースのみを dependsOn で指定する
テンプレート可読性と保守性を上げることができ、依存関係の変更が容易になる

--
最後、雑になりましたが以上になります

実装の方は、またあとで記載したいと思います。
https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/azure-resource-manager/templates/best-practices.md
新しい技術に触れながら開発をした際の失敗と反省

現在参加しているプログラミングスクール「JISOU」で、課題としてReactやtypescript、chakraUIを用いた学習記録アプリを作成しました。
失敗や反省を踏まえ、今回の記事では初めての技術に触れながら自分でアプリを作成する上での失敗について共有します。

# 作成したもの

![スクリーンショット 2024-09-15 183011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815580/a0eefe89-13df-f8c4-13b1-3820438c6ad4.png)

学習記録のテーブルに対して、基本的なCRUD操作を行います。
今回は主にTypeScriptの学習として作成しました。

https://github.com/Y-miu-Y/jisou-ex3

## 使用した技術

使用した技術としては以下の通りです。
* React
* typescript ⭐︎新規学習
* vite
* jest
* React-testing-liblaly
* firebase
* chakraUI

# めちゃめちゃ失敗した話

今回の開発については８月中を目標にしていましたが、実際には間に合いませんでした。
失敗した事についてのお話をここに書いていきたいと思います。

## 1. 公式ドキュメントを読み込まなかった

これで２週間くらい無駄にしました。
まず今回詰まった内容としては、Jestというライブラリのモック機能が上手く動作しませんでした。

（参考までに、こういうところで詰まっていました。）

https://qiita.com/miu-Y/items/b73b02538b2132ce8a7c

https://qiita.com/miu-Y/items/efb904fc888083252c20

### 詰まっていた理由

Jestのモックについては以前も触っていたため特に問題ないと油断していましたが、記法やJestの仕組みについて理解できていませんでした。
書き方について理解できているわけではないのに、公式ドキュメントを見もせず色々と間違った書き方を試していました。
挙句の果てにAIへ丸投げしましたが、結局上手くいきませんでした。

### 解決方法

コーチの方に問題解決の方法についてお伺いしました。
その際に調査が足りていないというご指摘を頂き、解決手順についてご教示を頂きました。
具体的には「**問題を切り分ける**」事についての重要性を教わりました。
（ex. 環境構築が間違っているのか、テストコードが間違っているのかなど……）

調査の結果、コードの書き方に間違いがあること分かりました。（詳細は記事を参照）

## 2. AIを使わない

このタイトルを書くとこんな事を言われてしまうかもしれません。

「2024年にいまだにAI触ってないの？」

今までの私はあまりAIを信頼していなかったので、自分の手で書いた物が一番だと考えていました。
ですが、JISOUのメンバーがAIを活用しているのを見たのがきっかけで本格的に触りました。

### AIを触ってからの変化

AIを使ってのコーディングは、どうしても初心者が理解していないコードをコピペするだけのイメージがあり倦厭していました。
実際にプロンプトを活用してみると、実際に知識不足で理解できないコードを吐き出されて難儀しました。
ですが、「なぜそのコードで動くのか？本当に正しいのか？」と疑って検索したりやドキュメントを読み込んだりで裏を取る事で、自分の知識が増えていきました。

また、最近のAIは性能が良いので吐き出されるコードの質が良いです。
すっかり魅力に取りつかれてClaudeの有料プランを契約しました、めっちゃ性能いいです。

# 良かったこと

悪かった事ばかり書くのも微妙なので、良かった事も書きます。

## フックがちょっとわかった

Reactの概念が少しだけわかってきました。
特に関数型プログラミングという概念を今まで理解していなかったので、関数コンポーネントやフック等が何となくレベルで分かってきました。

## 習慣的に勉強出来た

勉強する習慣は大事です。
特に、詰まって投げてしまうと（私の場合は）やらなくなってしまいますが、JISOUのメンバーやコーチのおかけで勉強を継続できました。

# 最後に

個人で開発を行い新しい技術を触るというのは、どうしても躓く事が多かったです。
特に「問題を切り分けて調査する」という経験は、フロント開発だけでなく、エンジニアやそれ以外で仕事を行う上でも大切な観点でした。
20代前半をSESで働いていると、どうしても「上司から降りてきた仕事をする」だけの仕事が多いですが、そこでは積めない貴重な経験を積めました。
これからも個人開発でこういった学びを得たいです。

# JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？

気になる方はぜひHPからライン登録お願いします👇

https://projisou.jp
投稿 78 Docker環境構築　エラー文「no configuration file not found」 2024/09/16

本日の勉強時間　3H

```
no configuration file not found
```


Dockerコンテナを作りたいけど、ファイルが無いよっていうメッセージ。

この場合の「configuration（設定・構成）」は
Dockerがコンテナを正しく作成・管理するために必要な情報や指示を意味しています。


具体的には、docker-compose.ymlなどのファイルに記載されている内容がこれに該当します。
このファイルには、コンテナに関する設定情報
（使用するイメージ、サービス、ネットワーク設定、環境変数など）が含まれており、Dockerはこれをもとにコンテナを構築して動かします。エラーが出た場合、Dockerがこれらの設定情報を正しく読み取れていないということです。

ディレクトリを変更することで、改善する場合あり。

参考記事

https://qiita.com/TK_WebSE/items/355dbee55bf7fd9dff95
交通事故オープンデータを色々分析してみる２（データ可視化編）

## はじめに
警察庁から交通事故の詳細なデータがオープンデータとして公開されています。

https://www.npa.go.jp/publications/statistics/koutsuu/opendata/index_opendata.html

このデータを色々こねてみて、最終的には交通事故発生予想みたいなことをしたい。

前回は交通事故データを読み込んでヒートマップで表示するところまでをやりました。

https://qiita.com/bb258/items/5f0c22d106de6030e79b

今回は、個別の事故位置を地図上に表示し、各データを表示してみようと思います。

## 時系列ヒートマップの作製
本題に移る前に、前回実施したヒートマップを時系列変化で表示する方法があったのでやってみます。

まず前回のデータの緯度経度を1時間ごとに区切ってlist化します。
```python
honhyo2023_all_latlon_24 = [[] for _ in range(24)]

for ind, row in honhyo2023.iterrows():
    h = row["datetime"].hour
    honhyo2023_all_latlon_24[h].append([row["lat"], row["lon"]])
```
次にfoliumのHeatMapWithTime機能を使って1時間ごとの時系列表示をできるようにします。
```python
from folium.plugins import HeatMapWithTime

map = folium.Map(location=[35, 139], zoom_start=9, tiles='cartodbdark_matter')
HeatMapWithTime(data=honhyo2023_all_latlon_24).add_to(map)
map
```

当然ですが深夜は事故が少なくて日中は多いですね。描画も重くなってます。
朝９時くらいがピークに見えます。
![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605106/fe0eeec9-a62e-f918-735b-5ae7dfd4ae0f.gif)


## 個別の事故位置を地図上で表示する
ヒートマップでは事故発生場所の分布がわかりますが個別の発生地点は分かりません。
なので個別の位置がわかるように地図表示します。

ただし、2023年だけで30万件以上の事故情報があるため、すべて表示してしまうと固まってしまいます。
そこで、foliumのMarkerClusterを使用してまとまって表示できるようにします。

```python
map = folium.Map(location=[35, 139], zoom_start=9, tiles='cartodbdark_matter')
marker_cluster = MarkerCluster().add_to(map)
for i in range(0, len(honhyo2023)):
    folium.Marker(
        location=[honhyo2023["lat"][i], honhyo2023["lon"][i]],
    ).add_to(marker_cluster)
map
```

結果がこちら
縮小するとまとめて表示され、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605106/f07df5be-045d-82fb-100b-e39cb6433e82.png)

拡大すると分かれて表示されていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605106/55f64fd4-e6e6-cee5-3584-9ef4a31264c7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605106/745ea2b8-ce94-98e5-a780-b1954aae3304.png)

## 終わりに
この記事では警察庁の交通事故オープンデータをヒートマップとマーカーを使って可視化しました。
事故地点まで可視化したので次は事故情報も同時に可視化できるようにしたいと思います。
ドメイン駆動設計を簡単に整理する

最近ドメイン駆動設計について改めて学んでみたので、
仕事で使う時があればすぐに思い出せるようアウトプットしていきます。

[1.ドメイン駆動設計とは](#1-ドメイン駆動設計とは)
[2.具体的にどうなるのか](#2-具体的にどうなるのか)
[3.作り方（設計編）](#3-作り方（設計編）)
[4.作り方（実装編）](#4-作り方（実装編）)
[5.感想](#5-感想)

# 1. ドメイン駆動設計とは
> ドメイン駆動設計（ドメインくどうせっけい、英語: domain-driven design、DDD）は主要なソフトウェア設計手法の一つであり[1]、ドメインエキスパートの言葉に基づき、ドメインにおけるプロセスやルールをよく表現したドメインモデルを構築し、それに基づいてソフトウェア開発を行うことに主眼を置くものである[2][3][4]。※Wikipedia参照

画面本位でもデータ本位でもなく、業務（ドメイン）ロジックを重点として設計を行う手法。


# 2. 具体的にどうなるのか
ドメイン駆動設計（以下"DDD"）を使用していない一般的な開発？としては３層アーキテクチャ辺りがメジャーかなと思います。
そこに業務オブジェクトを追加したものがDDDとなります。

# 3. 作り方（設計編）
DDDをどのように設計に落とし込めばよいのか、手順としては下記。
①. 業務（要件）理解
②. 業務理解から業務ロジックへの落とし込み・分担（マイクロサービス）
　※個人情報でいうと「名前」「住所」「電話番号」などの機能
③. ②で分担した機能毎に必要となる処理（値オブジェクト）をまとめる
　※「住所」でいうと郵便番号、都道府県、市区町村など…
④. ②と③の共通処理を考える


# 4. 作り方（実装編）
設計が終わったら実装に反映していきます。
DDD実装としては下記になります。
①. 設計編②のドメインクラスを作成する
``` 
--例（住所ドメイン）

class 住所ドメイン {

  ゲッター
  セッター
}
```
②. 設計編③の値オブジェクト（郵便番号や都道府県）を住所ドメインに追加する
``` 
--例（住所ドメイン）

class 住所ドメイン {
 郵便番号クラス 郵便番号;
 都道府県クラス 都道府県;
 市区町村クラス 市区町村;

  ゲッター
  セッター
}
```

③. 設計編④の処理を各ドメイン・値オブジェクトへ実装
``` 
--例（住所ドメイン）

class 住所ドメイン {
 郵便番号クラス 郵便番号;
 都道府県クラス 都道府県;
 市区町村クラス 市区町村;

  ゲッター
  セッター

  住所ドメイン加工処理 {
   return hoge;
  }
}

class 郵便番号クラス {
  郵便番号加工処理 {
   return hoge;
  }
}
```

④. ③層アーキテクチャ（主にサービス層）でドメイン・値オブジェクトクラスを呼び出して使用

# 5. 感想
上記からメリットとしては、処理の重複回避や機能毎で何をしたいのかが分かりやすくなると思いました。

しかし画面本位の設計とは異なり「DDDとは何か」がPJ全体が知らないと、
返って複雑なシステムが出来上がってしまう可能性は十分に高いと感じます。

また、本記事ではかなり要約した形で記載をしており、実際にDDDを使用する際には
その他種類のオブジェクトや、そこからの実装パターンの作成を洗い出す必要があり、
設計も関心事で分けて考えたり業務フローを作成したりと考慮する点は多々あるため
一筋縄ではいかないようにも思います。

実装のサンプルにゲッター・セッターを書きましたが、
本来はこちらもあまり好ましくないらしく、まだまだ奥が深いようです…。
(else文回避したりと色々…）

あくまでDDDとしての理想形で、実際にはそうではない混合したものが
現実かなとも思います。郷に入っては郷に従えですね。
学習データ増加における過去の深層学習モデルとの評価指標の比較(notデータ拡張)

## 概要

 　学習データを増やした際に過去の深層学習モデルとどのようにして比較するか。もしくは比較できるようにデータセットをどのように増やすかについてついて独自の考えを記載する。なお本稿における学習データを増やすとはデータ拡張のことではない。


## 結論

　データ間でマクロ平均を取って深層学習モデルを比較する。
 　つまり元のデータのテストデータと新しいデータのテストデータそれぞれでAIモデルに推論をさせて、その推論結果の平均を取って比較するのである。
　
## 動機

　学習データを増やした際の過去の深層学習モデルとの評価指標の比較方法のドキュメントが全く無いので、ココに記載しようと思う。
 　何故か調べてヒットするのがデータ拡張（Data Augmentation）ばかりヒットする。

## シナリオ

　Aさんは単一物体検出AIを作成することになりました。ある日に画像データを収集してアノテーションを行い、ホールドアウト法を用いて以下のようにデータを学習データとテストデータに分割してデータセットを作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3474151/fd52680c-1060-cd61-9651-50393f5215d5.png)

　このデータセットを用いて深層学習モデルを学習してテストデータで評価を行いました。この評価値に対して上司から評価値が低いからなんとかならないかと指摘を受けました。
　この時用いてたAIモデルは最新のモデルであったため、学習データを増やすしかありません。AIには学習データを増やせば増やすほど性能がよくなるというスケーリング則というものがあるからです。
 
　この時正しいデータセットの増やし方および、正しい過去の深層学習モデルの評価指標の比較方法をどうすればよいでしょうか？

 ## データセットの増やし方

　以下のようにデータを増やした時にどのように配分すればよいか。
　なお、TrainAで学習された過去の深層学習モデルの名称はモデルAとする。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3474151/f6b769d9-b3eb-b3ea-0fe8-4f1403406dcd.png)


### A)新しいデータ全てを学習データにする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3474151/825eaaff-5586-66db-62d0-4b8635fe165f.png)

　新しいデータを全て学習データとしてモデルBを学習させて、テストデータAを用いてモデルAとモデルBを比較させる。
　この方法は（×）
　同一のテストデータを用いているため一見よく見えるが、これはテストデータが多様である場合はよいが現実ではそうではないから良くない。（自分の考えではそうだが根拠の引用がない）
　テストデータが多様でなく、新しく追加した学習データが多様であった場合は確実に性能が下がるという直感的な結果が思い浮かぶ。

### B)合成してホールドアウト法で作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3474151/60ac776c-4926-9b52-5def-cc6a190f7a51.png)

　新しいデータをデータセット全てに合成させて新しくホールドアウト法を用いてデータセットを作成する。
　この方法は（×）
　この方法は、テストデータZに学習データAが混ざっている可能性がモデルAの評価の際に正しい評価ができない。

### C)それぞれのデータセットでホールドアウト法を用いて分割してから合成させる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3474151/873ce626-1eb4-011f-5259-a6458cf2409d.png)

　この方法は新しいデータをホールドアウト法で分割して合成させる。学習データA＋学習データBで深層学習モデル（モデルB）を学習させる。そしてテストデータA+テストデータBを用いてモデルAとモデルBで評価して比較を行う。
　どうやらコレだと、テストデータの多様性が増え、またテストデータが学習データに混ざることもなくなるので良さそうである。
　この方法は（○）

 ## 本当にコレでいいか？

　実際に（C)の方法でデータを増やしてモデルの評価を比較していたが、再びデータを追加したが評価指標が下がってしまう現象が発生した。
　理由として挙げられるのは**追加データが少ないためテストデータに不均衡性が発生している**ことだ。
　コレにより、**追加データのテストデータの評価指標が低くても元データのテストデータの評価指標が高い方が全体としてはよい**という結果が発生してしまう。
　このような現象は一回や二回の追加では発生しないかもしれないが、元データが蓄積していくほど巨大になっていくため、いつかは発生する現象である。

 ## 解決策

　解決策として考えられるのは**マクロ平均**を用いて計算をすることである。
　マクロ平均とは、多クラス分類における不均衡データを用いたモデルを評価する際に用いられることが多い。
　この計算は、通常の平均が全体数で割るのに対して、各クラスの評価指標を各クラスの数で割った後にそれぞれのクラスの評価指標を足し合わせてクラスの数で割る計算方法である。

　今回はマクロ平均をクラスではなくデータに対して行う。
　これにより、
 モデルAの評価指標＝(テストデータAの評価指標＋テストデータBの評価指標)/2
 モデルBの評価指標＝(テストデータAの評価指標＋テストデータBの評価指標)/2
　となりデータの不均衡に関係なく深層学習モデルの学習データ増加による過去の深層学習モデルとの評価指標の比較ができるようになる。


 ## 問題点
 - 今回は単一物体検出の例だったからうまくいったが多クラス物体検出だと、どうすればよいだろうか？それぞれのクラスごとにやるべきか？
 - モデル学習時のバリデーションのデータセットに対してマクロ平均を計算するのはOSSが対応していないので、導入できない
 - データ増加によってモデルの性能が向上したことは証明できるが、最初に上司に提示した評価指標結果より下がるため（汎用性は向上するが特定のデータに関しては下がることが予想されるので）、「お前下がってんじゃねえか」と言われる点
GPGキーとは？AWSサーバーでのMySQLインストール事例に基づく備忘録

### 概要

開発中にAWSのサーバーにMySQLをインストールする際、GPGキーの使用が必要になる場面がありました。GPGキーは、データの署名や暗号化に使われるもので、ソフトウェアのパッケージの信頼性を検証するためにも重要な役割を果たします。この記事では、その具体的な事例をもとに、GPGキーの使い方とその意義を簡潔に解説します。

### 1. なぜGPGキーが必要だったのか？

AWSのサーバーにMySQLをインストールする際、公式のMySQLリポジトリからパッケージをダウンロードしましたが、そのパッケージの信頼性を確認するために、GPGキーが必要になりました。多くの公式リポジトリは、パッケージが改ざんされていないことを証明するために、GPG署名を使います。

- **GPGキーの役割**:
パッケージが配布元の正当なものであるかを確認し、改ざんや不正なアクセスを防ぐために使われます。GPGキーを使用することで、セキュリティの高いインストールを保証できます。

### 2. AWSサーバーでのMySQLインストール時の手順

### (1) GPGキーのインポート

MySQLをインストールする際、最初のステップは、公式MySQLリポジトリから提供されているGPGキーをサーバーにインポートすることです。これにより、ダウンロードしたパッケージが公式のものであるかどうかを確認できます。

- **GPGキーのインポートコマンド:**

```bash
sudo rpm --import <https://repo.mysql.com/RPM-GPG-KEY-mysql-2023>
```

このコマンドを実行すると、MySQLの公式リポジトリから最新のGPGキーがインポートされ、リポジトリの信頼性が保証されます。

### (2) MySQLリポジトリの設定

次に、MySQLリポジトリをサーバーに追加します。

```bash
sudo wget <https://dev.mysql.com/get/mysql80-community-release-el7-5.noarch.rpm>
sudo rpm -ivh mysql80-community-release-el7-5.noarch.rpm
```

これにより、サーバーがMySQLリポジトリを認識し、そこからパッケージをインストールできるようになります。

### (3) MySQLのインストール

リポジトリとGPGキーが設定された後、MySQLをインストールします。

```bash
sudo yum install mysql-server
```

このインストール中、GPGキーによってパッケージの信頼性が検証されます。

### 3. GPGキーとは？（簡潔な説明）

GPG（GNU Privacy Guard）は、データの暗号化と署名を行うためのツールです。主に以下の目的で使われます：

- **データの署名**: パッケージやファイルが正当なものであることを証明するため。
- **データの暗号化**: データの内容が第三者に見られないように保護するため。

AWSのような環境でソフトウェアをインストールする際には、パッケージが改ざんされていないことを確認するために、GPGキーが重要な役割を果たします。

### 4. 初心者が注意すべきポイント

- **GPGキーの信頼性**
    
    インポートするGPGキーが公式なものであることを確認する必要があります。公式サイトや信頼できるソースから入手しましょう。
    
- **秘密鍵の管理**
    
    GPGキーを使用してデータを署名する際は、秘密鍵を適切に管理し、第三者に漏れないようにすることが重要です。
    

### 結論

AWSサーバーでMySQLをインストールする際、GPGキーの重要性を学びました。GPGキーを使用することで、パッケージの信頼性を検証し、安全にソフトウェアをインストールすることができます。参考にした記事：[Serverworks Blog - Amazon Linux2にMySQLをインストールし、GPGキーを2023年版に設定する方法](https://blog.serverworks.co.jp/install-MySQL-on-Amazon-Linux2-and-pgp2023)。今後もこの知識を活用し、安全で信頼性の高い開発を目指していきたいと思います。
Oracle Database Vaultの監査とAudit Vaultの違いは？

Oracle Database Vaultの監査機能とOracle Audit Vaultの違いは、それぞれが提供する監査の目的や機能に関して異なる点があります。以下に両者の違いを整理します。

**1. Oracle Database Vaultの監査機能**
Oracle Database Vaultは、データベース内部での不正アクセスや不適切な操作を防ぐために、ポリシーベースでアクセス制御を行いますが、それに付随して監査機能も提供しています。

- **目的:** 主にデータベース内での特権ユーザーや管理者による不正アクセスを防止し、操作に対する監査を行います。
- **機能:**
  - **ポリシー違反の監査:** Database Vaultのセキュリティポリシーに違反する操作（例: 管理者が特定のデータにアクセスしようとした場合）の監査が行われます。
  - **細かい制御:** 特定のユーザーやロール、データに対して設定されたアクセス制御ポリシーに基づいた監査を行います。
  - **レポート生成:** 監査ログを元に、ポリシー違反や異常な操作を検出し、レポートを生成します。

Database Vaultは主に内部からの不正アクセスや特権ユーザーによる操作を制限・監視することが目的で、リアルタイムな監査が行われます。これにより、特定のデータに対してアクセスできないようにするだけでなく、そのアクセスを試みた記録も残ります。

**2. Oracle Audit Vault**
Oracle Audit Vaultは、より広範な監査を実現するための専用の監査管理システムです。Oracle Databaseだけでなく、他のデータベースやシステムの監査ログも一元的に収集・管理するためのプラットフォームです。

- **目的:** 企業全体での監査ログを統合的に管理し、セキュリティ監査やコンプライアンス要件に対応するためのシステムです。Database Vaultを含む、複数のソースからの監査ログを収集・分析します。
- **機能:**
  - **監査ログの統合管理:** Oracleデータベースに加えて、MySQL、SQL Server、Sybase、Oracle NoSQLなど、他のデータベースやアプリケーション、オペレーティングシステムからも監査データを収集できます。
  - **監査レポートの生成と分析:** 収集した監査データを基に、包括的な監査レポートを生成し、異常な動作やセキュリティインシデントを分析します。
  - **アラート機能:** 特定の条件に基づいて、異常な監査データが収集された場合にアラートを発行することができます。
  - **データの長期保存:** 監査データを長期間にわたって保存し、コンプライアンスの要件に対応できるようにしています。

Audit Vaultは、**全社的な監査ログの一元管理**を目的としており、異なるデータベースやシステムからの監査データを収集し、**総合的な監査と異常検知、コンプライアンス対応**に強みを持っています。

**まとめ**
-  **Oracle Database Vaultの監査機能**は、主に特権ユーザーや管理者のアクセスを制限し、そのアクセスや操作を監査する機能で、リアルタイムかつデータベース内部にフォーカスした監査を提供します。
-  **Oracle Audit Vault**は、複数のデータベースやシステムから監査データを収集し、包括的な監査管理を行うための専用プラットフォームです。より広範囲での監査と長期的な監査ログの保存、コンプライアンスの対応が主な目的です。

それぞれの製品は連携して使用することも可能で、Database Vaultでの監査データをAudit Vaultで一元管理することもできます。
サーバーのOSと開発環境でのフレームワーク等のバージョニングに関する備忘録

### 概要

サーバーのOSや開発環境で使用するフレームワークやライブラリのバージョン管理は、プロジェクトの安定性と互換性を保つために非常に重要です。今回の開発では、AWSのAmazon Linux 2を使用しており、PHP 8.2をインストールできない問題や、使用するライブラリのバージョン制限に直面しました。この記事では、こうしたバージョニングに関する注意点について備忘録としてまとめます。

### 1. 開発環境とサーバー環境のバージョン管理の重要性

開発環境とサーバー環境で異なるバージョンのOSやフレームワークを使用すると、依存関係の問題や互換性の問題が発生する可能性があります。特に、以下の点に注意が必要です：

- **PHPやNode.jsのバージョンの互換性**
- **使用するライブラリやフレームワークのサポート状況**
- **OSバージョンに依存するパッケージのインストール可否**

### 2. Amazon Linux 2とPHPのバージョン互換性問題

今回のプロジェクトでは、AWSのAmazon Linux 2を使用していましたが、PHP 8.2のインストールができない問題に直面しました。この問題の背景には、Amazon Linux 2が最新のPHPバージョンに対応していないことが原因でした。

- **問題点**:
    
    Amazon Linux 2のリポジトリには、PHP 8.2が含まれていないため、公式な方法でインストールできませんでした。
    
- **解決策**:
Amazon Corretto（Javaのディストリビューション）のように、AWSが独自に管理するバージョンを使用することもできますが、PHPの場合はRemiリポジトリを追加することで新しいバージョンを取得できます。ただし、安定性を重視する場合、サーバーOSの標準リポジトリに含まれるバージョンを使用することが推奨されます。

### 3. フレームワークやライブラリのバージョンの選定

PHPのバージョンに制約がある場合、使用するフレームワークやライブラリのバージョンにも制約が生じます。今回の開発では、画像処理ライブラリ `Intervention/Image` のバージョンも最新の3.xではなく、2.7を使用せざるを得ませんでした。

- **問題点**:
    
    `Intervention/Image` のバージョン3.xは、PHP 8.0以降を必要とするため、Amazon Linux 2でPHP 7.xを使用している環境ではインストールできませんでした。
    
- **解決策**:
    
    バージョン2.7を使用することで互換性を保ちながら、必要な機能を実装しました。このように、プロジェクトの環境に合ったライブラリバージョンを選択することが重要です。
    

### 4. バージョン管理のためのツールと方法

バージョン管理を適切に行うためには、いくつかのツールと方法が役立ちます。

- **Composerやnpmによる依存関係の管理**
    
    Laravelプロジェクトでは、`composer.json` を使用してPHPのライブラリのバージョンを管理します。開発環境と本番環境で同じバージョンを使用することで、互換性の問題を防ぎます。
    
    ```json
    {
        "require": {
            "php": "^8.1",
            "intervention/image": "^2.7"
        }
    }
    ```
    
- **Dockerによる開発環境の統一**
    
    Dockerを使用することで、開発環境と本番環境のOS、PHPのバージョン、使用するライブラリのバージョンを統一できます。これにより、環境の違いによる問題を減らすことができます。
    

### 5. 初学者向けの注意点

バージョン管理は、プロジェクト全体の安定性と保守性に直結します。以下の点に注意してバージョンを管理してください：

- **プロジェクト開始時に使用するバージョンを決定する**
    
    使用するOS、PHPのバージョン、フレームワークやライブラリのバージョンを事前に決めておくことが重要です。
    
- **互換性のチェックを怠らない**
    
    各バージョン間の互換性を常にチェックし、必要に応じてバージョンを調整します。
    
- **公式ドキュメントを確認する**
    
    ライブラリやフレームワークの公式ドキュメントには、サポートするバージョンや推奨される設定が記載されていますので、必ず確認するようにします。
    

### 結論

サーバーのOSや開発環境で使用するフレームワークやライブラリのバージョニングは、プロジェクトの成功に不可欠です。互換性を常に意識し、最新のバージョンを使用するだけでなく、プロジェクトに最適なバージョンを選択することが重要です。今後も、バージョニングに関する注意点を意識しながら開発を進めていきたいと思います。
AWSロードバランサー設定で詰まったところ - ヘルスチェック設定に関する備忘録

### 概要

AWSのロードバランサー（ELB）を使用している際に、ヘルスチェックの設定で詰まった経験があります。ヘルスチェックは、ロードバランサーが正常なインスタンスを識別し、リクエストを効率的に振り分けるために必要不可欠な機能です。この記事では、ヘルスチェックの設定で直面した問題と解決方法について備忘録としてまとめます。

### 1. ヘルスチェックの役割

ヘルスチェックとは、ロードバランサーがバックエンドのインスタンス（EC2インスタンスやコンテナ）が正常に動作しているかを確認するための仕組みです。AWS ELBでは、ターゲットグループに属するインスタンスに対して定期的にリクエストを送り、その応答を基にインスタンスが正常かどうかを判断します。

- **正常なインスタンス**はリクエストを受け続け、不正なインスタンスはロードバランサーの対象から外されます。

### 2. 直面した問題

ヘルスチェックの設定で以下のような問題が発生しました：

1. **ヘルスチェックが頻繁に失敗する**
    - 正常に稼働しているインスタンスにもかかわらず、ヘルスチェックが失敗し続けました。このため、ロードバランサーがインスタンスを「不健康」と判断し、トラフィックを振り分けなくなりました。
2. **不適切なヘルスチェック設定**
    - デフォルトのヘルスチェック設定のままでは、特定のシナリオで誤ってインスタンスが「不健康」と判断されることがありました。

### 3. 解決方法

### (1) ヘルスチェックのパスを適切に設定する

ヘルスチェックのパスは、ロードバランサーが健康状態を確認するために使用するURLパスです。デフォルトではルート（`/`）が指定されていましたが、これが問題を引き起こしていました。特定のアプリケーションやサービスのエンドポイントが必要な場合、それに合わせてパスを設定する必要があります。

```
/health-check
```

- **備忘ポイント**
ヘルスチェックのパスは、アプリケーションの稼働状況を正しく反映するエンドポイントを選択することが重要です。たとえば、`/health-check`のようなエンドポイントをアプリケーションに実装し、そのレスポンスが200ステータスコードを返すようにします。

### (2) ヘルスチェックの間隔とタイムアウトを調整する

デフォルトのヘルスチェック設定では、チェックの間隔（インターバル）やタイムアウト時間が短すぎるため、ネットワークの遅延やサーバーの応答時間がわずかに遅れるだけで失敗と判断されることがありました。これを調整することで、意図しない失敗を防ぎました。

- **設定例**:
    - **ヘルスチェックの間隔**: 30秒
    - **タイムアウト**: 5秒
    - **成功のしきい値**: 5回連続成功
    - **失敗のしきい値**: 2回連続失敗
- **備忘ポイント**
    
    ヘルスチェックの間隔とタイムアウトを適切に設定することで、ネットワーク遅延や一時的なサーバー応答の遅延に対する柔軟性を持たせることができます。
    

### (3) 正常なHTTPステータスコードを設定する

ヘルスチェックの成功基準として、どのHTTPステータスコードを「正常」とみなすかを設定します。デフォルトでは200のみが成功と見なされますが、場合によってはその他のステータスコード（たとえば、301リダイレクトや302リダイレクト）を許容する必要がある場合もあります。

- **設定例**:
    
    ```
    200-299
    ```
    
- **備忘ポイント**
    
    アプリケーションの構成やヘルスチェックの目的に応じて、許容するHTTPステータスコードの範囲を柔軟に設定することで、誤検出を防止できます。
    

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

上記の設定を見直すことで、ヘルスチェックが安定し、ロードバランサーが正常にインスタンスを健康と判断できるようになりました。結果として、ユーザーからのトラフィックが正しく分散されるようになり、サービスの安定性も向上しました。

### 5. 今後の改善点

- **定期的な設定の見直し**
    - サービスのスケールや負荷に応じて、ヘルスチェックの設定を定期的に見直す必要があります。
- **モニタリングの強化**
    - ヘルスチェックの失敗率を継続的に監視し、異常が発生した際には迅速に対応できる体制を整えることが重要です。

### 結論

AWSのロードバランサーでヘルスチェックを適切に設定することは、サービスの安定運用において非常に重要です。ヘルスチェックのパス、間隔、タイムアウト、およびHTTPステータスコードの設定を正確に行うことで、意図しないエラーを防ぎ、サービスの信頼性を高めることができます。
uk

```
Sub ReplaceFontInSlides()
    Dim slide As slide
    Dim shape As shape
    Dim textRange As TextRange
    Dim paragraph As TextRange
    Dim run As TextRange
    
    Dim oldFont As String
    Dim newFont As String
    
    ' 置き換えるフォント名を指定
    oldFont = "Noto Sans Symbols"
    newFont = "MS Pゴシック"
    
    ' すべてのスライドをループ
    For Each slide In ActivePresentation.Slides
        ' スライド内のすべてのシェイプをループ
        For Each shape In slide.Shapes
            ' テキストを含むシェイプのみ処理
            If shape.HasTextFrame Then
                If shape.TextFrame.HasText Then
                    Set textRange = shape.TextFrame.TextRange
                    
                    ' テキスト内のすべての段落をループ
                    For Each paragraph In textRange.Paragraphs
                        ' 段落内の各テキストラン（文字の連続）をループ
                        For Each run In paragraph.Runs
                            ' 指定したフォントが適用されているか確認
                            If run.Font.Name = oldFont Then
                                ' フォントを新しいフォントに変更
                                run.Font.Name = newFont
                            End If
                        Next run
                    Next paragraph
                End If
            End If
        Next shape
    Next slide
    
    MsgBox "フォントの置換が完了しました！", vbInformation
End Sub

```
GitHub ActionsでReactアプリをCloudFront + S3にデプロイして静的サイトをホスティングする

# GitHub ActionsでReactアプリをCloudFront + S3にデプロイして静的サイトをホスティングする

最近、ReactアプリケーションをS3とCloudFrontを使って静的にホスティングするプロジェクトに取り組みました。このブログでは、そのアーキテクチャやCICDパイプラインの構築について解説します。

タイトル内容のソースコードを先に把握したい方は[GitHubリポジトリ](https://github.com/kkkensuke/staticsite-s3-cloudfront-githubactions-public)を参照してください。

## アーキテクチャ概要

今回構築したアーキテクチャは、以下の要素で成り立っています。

- **S3バケット**: Reactアプリの静的ファイルをホスティングします。S3はサーバーレスで静的サイトのホスティングに最適です。
- **CloudFront**: S3上のコンテンツを高速に配信するためのCDN（Content Delivery Network）。世界中にあるエッジロケーションを利用し、ユーザーに近い場所からコンテンツを配信することで、パフォーマンスを向上させます。
- **GitHub Actions**: CICDパイプラインを構築し、Reactアプリのビルドからデプロイまでを自動化しています。

## CICDパイプラインの構築

CICDパイプラインはGitHub Actionsを使用して構築しました。リポジトリにコードがプッシュされるたびに、以下のプロセスが実行されます。

1. **Reactアプリのビルド**: `npm run build` コマンドでビルドを行い、最終的な静的ファイルを生成します。
2. **S3へのデプロイ**: ビルドされたファイルをS3にアップロードします。
3. **CloudFrontキャッシュの無効化**: 新しいバージョンのコンテンツが配信されるように、CloudFrontのキャッシュを無効化します。

### GitHub Actionsのワークフローファイル

以下は、実際に使用しているGitHub Actionsのワークフローファイルです。

```yaml
name: Upload files to S3

on:
  push:
    branches:
    - main

env:
  MY_AWS_REGION: '<YOUR AWS REGION>'
  AWS_ROLENAME: '<YOUR AWS ROLE>'
  AWS_S3_BUCKET: '<YOUR S3 BUCKET>'
  SOURCE_DIR: './build'

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
    - name: Checkout
      uses: actions/checkout@master

    - name: Set up Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '16' # 使用するNode.jsのバージョン

    - name: Install dependencies
      run: npm install

    - name: Build project
      run: npm run build

    - name: Configure AWS credentials with IAM Role
      uses: aws-actions/configure-aws-credentials@v4
      with:
        role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ env.AWS_ROLENAME }}
        aws-region: ${{ env.MY_AWS_REGION }}
    - name: Sync files to S3
      run: |
          aws s3 sync ${{ env.SOURCE_DIR }} s3://${{ env.AWS_S3_BUCKET }}/ --delete --exclude '.*git*'
    - name: Invalidate CloudFront Cache
      run: |
          aws cloudfront create-invalidation \
            --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} \
            --paths "/*"

```
## AWSリソースの構築
- **S3バケットの作成**: バケットを作成し、静的ウェブサイトホスティングを有効にします。パブリックアクセスはCloudFront経由で制御されるため、S3自体には直接アクセスできないように設定します。
- **CloudFrontの設定**: S3バケットをオリジンとして指定し、カスタムドメインやSSL証明書を設定します。

## 最後に
この構成により、ReactアプリをS3とCloudFrontを使用して高速かつセキュアにホスティングできるようになりました。また、GitHub Actionsを使ったCICDパイプラインで、簡単にデプロイを自動化することが可能です。

詳しいコードや設定については、GitHubリポジトリで公開していますので、ぜひ参考にしてください。 [GitHubリポジトリはこちら](https://github.com/kkkensuke/staticsite-s3-cloudfront-githubactions-public)
Laravelプロジェクトでの写真圧縮 — Intervention Imageライブラリの使い方に関する備忘録

### 概要

Laravelでの写真アップロード機能において、画像の圧縮はストレージの節約とパフォーマンス向上に重要です。この記事では、PHP用の画像操作ライブラリ「Intervention Image」の使い方について、私が開発中に経験した内容を備忘録としてまとめます。今回は、PHPのバージョンの関係で最新バージョン3ではなく、2.7を使った具体的な実装例を紹介します。

### 1. Intervention Imageライブラリとは？

Intervention Imageは、PHPで画像操作を簡単に行えるライブラリです。このライブラリを使用することで、画像のリサイズやトリミング、フィルターの適用など、様々な画像操作が可能になります。今回のプロジェクトでは、特に画像の圧縮とリサイズに焦点を当てて使用しました。

- **使用したバージョン**: `intervention/image` バージョン `2.7`
    - 最新バージョンではなく、PHPの互換性（PHP 8.2がサポートされていない）と他の依存関係のため、バージョン `2.7` を選択しました。

### 2. インストールと設定

まず、LaravelプロジェクトにIntervention Imageをインストールする必要があります。今回使用したバージョン `2.7` を指定してインストールします。

```bash
composer require intervention/image "^2.7"
```

次に、`config/app.php` ファイルにService ProviderとFacadeを追加します。

```php
'providers' => [
    Intervention\Image\ImageServiceProvider::class,
],

'aliases' => [
    'Image' => Intervention\Image\Facades\Image::class,
],
```

これで、Laravel内でIntervention Imageを使えるようになります。

### 3. 画像のリサイズと圧縮の実装例

以下のコードは、写真アップロード機能で使用した画像のリサイズと圧縮処理の実装例です。

```php
use Intervention\Image\ImageManager;

// GDドライバーを使用するImageManagerのインスタンスを作成
$manager = new ImageManager(['driver' => 'gd']);

// アップロードされた画像の一時パスを取得
$temporaryPath = $this->photo->store('livewire-tmp', 'local');
$absolutePath = storage_path('app/' . $temporaryPath);

// 画像をリサイズし、アスペクト比を保持したまま最大幅800ピクセルに設定
$image = $manager->make($absolutePath)->resize(800, null, function ($constraint) {
    $constraint->aspectRatio(); // アスペクト比を維持
    $constraint->upsize(); // サイズの引き伸ばしを防止
});

// 圧縮した画像を保存（品質75%）
$compressedPath = 'photos/' . uniqid() . '.jpg';
$image->save(storage_path('app/public/' . $compressedPath), 75); // 75%の品質で保存
```

- **備忘ポイント**`ImageManager`クラスを使用して、GDドライバーを指定しています。GDはPHPのデフォルトで組み込まれている画像処理ライブラリで、外部ライブラリを必要としないため、特に簡単な操作には便利です。

### 4. PHPのバージョンと依存関係の制約について

今回の開発では、PHPのバージョンや他のフレームワークとの依存関係の都合で、Intervention Imageの最新バージョン（3.x）を使用することができませんでした。

- **使用した環境**:
    - **OS**: AWSのAmazon Linux 2
    - **PHPバージョン**: PHP 7.x（8.2はサポート外）

最新のPHPバージョンを使用することで、Intervention Imageの最新機能が使える場合もありますが、互換性の問題からプロジェクトで使用できないこともあるため、バージョン選定には注意が必要です。

### 5. 他の圧縮方法と比較

Intervention Imageを使うことの利点と、他の圧縮方法（例えば、外部のCLIツールを使ったバッチ処理など）との比較も考慮しました。

- **利点**:
    - LaravelとPHP内で完結するため、追加の外部ツールを導入する必要がない。
    - コードの統一性を保ち、開発者がPHPの文法に統一して作業できる。
- **制約**:
    - 高度な圧縮やフォーマット変換が必要な場合、Intervention Imageだけでは機能が不足することがある。

### 結論

Intervention Imageは、Laravelプロジェクトでの簡単な画像処理に非常に便利なライブラリです。PHPのバージョンや他の依存関係を考慮しながら、適切なバージョンを選択することが重要です。今後も、PHP内で画像処理を行う場合はこのライブラリを活用しつつ、必要に応じて他のツールや方法も検討していきます。