OmniAICreator/Qiita-1.07M huggingface dataset:
Flutter:iOSのバージョンがxcodeアーカイブエラーで更新されないときに見直すべきポイント（Xcode & pubspec編）

### はじめに

Flutterで `pubspec.yaml` の version を更新しても、Xcodeで前のバージョンが残ってしまい、xcodeでarchive作成すると何度やってもバージョンとビルドがアップデートされない問題に直面した。 
chatgptに聞きながら格闘してやっと解決したので、そのままchatgptに書かせて記録を残す。

---

### 🎯 発生した問題

- `pubspec.yaml` に `version: 1.0.3+13` と書いたのに、App Store Connect で「1.0.2のビルドです」と言われる
- `Info.plist` は `$(FLUTTER_BUILD_NAME)` として指定済み
- `Xcode` 側でも `MARKETING_VERSION` は 1.0.3 に見える。軒並みbuild settingは何億回も確認した。
- **でもビルドには古い 1.0.2 が使われ続ける**

---

### 🕵️‍♂️ 原因

Flutterは `pubspec.yaml` を元に `ios/Flutter/Generated.xcconfig` を生成する。ここに：

```xcconfig
FLUTTER_BUILD_NAME=1.0.2
```

のように**古いバージョンが残っていると**、`Info.plist` に間接的に反映されてしまい、Xcodeでは最新に見えても**アーカイブ結果は旧バージョン**になってしまう。

さらに `project.pbxproj` に `FLUTTER_BUILD_NAME=1.0.2` が**直書きされているケース**もあり、`Generated.xcconfig` を上書きしても効かないことがある。

---

### 🔧 解決法（全部やる）

以下の手順を順番に実行：

---

#### ✅ 1. ビルドキャッシュを削除
```bash
flutter clean
```

---

#### ✅ 2. `pubspec.yaml` のバージョンを確認・更新
```yaml
version: 1.0.3+13
```

---

#### ✅ 3. `ios/Runner.xcodeproj/project.pbxproj` を手動で確認

`FLUTTER_BUILD_NAME=1.0.2` のようなハードコードされた値がある場合、**手動で削除 or `$(FLUTTER_BUILD_NAME)` に修正**。

```diff
- FLUTTER_BUILD_NAME = 1.0.2;
+ FLUTTER_BUILD_NAME = $(FLUTTER_BUILD_NAME);
```

---

#### ✅ 4. MacとXcodeを**再起動**

- `project.pbxproj` を書き換えたら、**Xcodeのキャッシュが残ることがあるため再起動は必須**。
- ターミナルも念のため再起動。

---

#### ✅ 5. 正しいビルドを実行

```bash
flutter pub get
flutter build ios --release --build-name=1.0.3 --build-number=13
```

---

#### ✅ 6. Xcodeでアーカイブ

```bash
open ios/Runner.xcworkspace
```

メニューから `Product > Archive`。Organizerでビルドバージョンが `1.0.3 (13)` になっていることを確認。

---

### 🧼 補足Tips

- `Info.plist` の記述はこのようになっている必要あり：

```xml
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
```

- `MARKETING_VERSION` は `FLUTTER_BUILD_NAME` と自動で連動しないため、**Xcode GUI側で変えても効かないことがある**。

---

### ✅ まとめ

| 見落としがちな箇所 | 要チェック事項 |
|--------------------|----------------|
| `project.pbxproj`  | `FLUTTER_BUILD_NAME` がハードコードされていないか？ |
| `Info.plist`       | バージョンは `$(FLUTTER_BUILD_NAME)` 指定か？ |
| ビルドキャッシュ   | `flutter clean` でクリアしたか？ |
| 再起動             | Mac・Xcode再起動でキャッシュ解除したか？ |
| `flutter build ios`| `--build-name` / `--build-number` を指定したか？ |

---
### 記事執筆
全てChatGPTであることをご承知おきください
文系新卒が免除制度を使って基本情報に合格した記録

## はじめに

この記事は、**文系新卒としてIT企業に入り、会社から午前免除試験の受講を案内された方**に向けて書いています。

IT企業では「1年目で基本情報を取ろう」という方針のところも多く、去年の私と同じような立場の方は多いと思います。実際Qiitaには合格体験記が沢山あがっていますが、午前免除制度について詳しく書かれていた記事はあまり見かけませんでした。

本記事では、未経験の私が科目A試験免除制度を使って合格するまでにやったことや、感じたことをまとめてみました✍️

## 自己紹介

- 2024年に中小SIerへ新卒入社  
- 文系出身で、学生時代にプログラミングの経験はなし  
- プログラミングは研修で初めて触るレベル（SQLも初耳）
- 1回目の試験は不合格、2回目の試験は37点でギリギリ合格 （36/60以上で合格）

## 科目A試験免除制度ってなに？

> **IPAに認定された講座を受講し、修了試験に合格する（修了認定の基準を満たす）ことによって、基本情報技術者試験の科目A試験が免除される制度です。**  
> [IPA公式サイト：科目A試験免除制度について](https://www.ipa.go.jp/shiken/about/menjo-fe.html)

出題数は60問で、試験当日は**指定された会場にてマークシート方式で受験**します。  
通常のCBT方式とは異なり、日時や場所があらかじめ決まっている点に注意が必要です。

また、免除試験を受けるには**受験資格が必要**です。  
私は独習ゼミの講座を利用しましたが、**オンライン教材内にある修了試験に合格することなどが受験条件**となっていました。
[独習ゼミ：基本情報技術者試験の科目A試験免除制度（旧・午前免除制度）とは](https://www.seplus.jp/dokushuzemi/ec/fe/exemption/)


免除試験に合格すると、その後1年間は科目A試験が免除され、本試験では科目B試験だけを受験することになります。

私の場合は、新人研修中に会社から「希望者は免除制度で受験できる」と案内され、5月上旬から勉強を始めました。
免除試験は2回受験でき、私は6月と7月に試験を受け、2回目の試験で合格しました。

## 勉強法  
### 過去問道場をメインに使用

免除試験は、基本情報技術者試験・応用情報技術者試験などの **過去問から100%出題されていて、新しい問題は出題されません**。  

なので私は、「質より量」を意識して、過去問道場で最新から7回分を繰り返し解いていました。
下記画像は解いた問題数です。
![スクリーンショット 2025-04-13 19.06.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4059056/7d5f7491-673a-4fef-ae2e-fb2e6181f18b.png)

ただ、実際に出題された問題を振り返ってみると、**平成の試験からの出題が多かったな**という印象があります。

 [SEプラス：試験講評](https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/tag/試験講評/#!)  
この講評、私は試験を受けたあとに存在を知りました。もっと早く知っていれば、平成の過去問を重点的に勉強していました…

これから受験される方は、**少し前の問題（特に平成の問題）をしっかり解くのがおすすめ**です。



### 初学者向けの分野から着手

情報処理技術者試験の科目A問題は、「テクノロジ」「マネジメント」「ストラテジ」の3つの分野に分かれています。

その中でも私は、未経験の自分でも取り組みやすそうだと感じた「マネジメント」と「ストラテジ」から学習を始めました。
どちらも実務経験がなくてもイメージしやすい内容が多く、選択肢の文章を丁寧に読めば答えにたどり着ける問題が多かった印象です。


### 毎日の生活の中に少しずつ組み込む

「長時間集中して勉強する」のは自分に合っていなかったので、勉強のハードルを下げることを意識していました。

具体的には、**5分だけ問題を解く → 25分休憩や好きなことをする**という形で、 
いわゆるポモドーロ法の逆パターンですが、私にとってはこのくらいがちょうどよかったです。
「勉強してない日を作らない」ことを意識していました。

また、その日に新しく解く問題だけでなく、**前日にやった範囲を復習してから進める**ようにして、知識を少しずつ重ねるようにしていました。


## 科目A試験免除制度を使ってよかったこと
### 免除試験は2回チャンスがある

私が受けたコースでは、免除試験を2回まで受けることができました。  
（スケジュール的には、1回目が6月、2回目が7月に実施されました）

1回目で不合格になったあとも、「まだ1回残っている」という安心感があったので、過去問道場に集中して取り組みました。  
その結果、2回目で合格することができました。


### 勉強の負担を分散できる

科目Aと科目Bを同時に対策するのではなく、**まず科目A集中できた**ことは大きなメリットでした。  
「基本情報に合格する」ではなく、「免除試験を合格する」という目標があることで、精神的にも楽でした。



## 注意点
### 有効期限を意識する

科目A試験免除試験に合格したら **1年間有効**ですが、「まだ時間があるから大丈夫」と油断して後回しにしてしまうと、  それまで続けていた学習習慣が途切れてしまうことがあります。

私自身も、7月に試験を終え、8月は勉強をお休み → 9月に科目B試験対策を開始・受験しました。  
無事に合格できましたが、**たった1ヶ月空いただけでも再スタートがかなり大変でした。**

学生時代と違って、仕事のあとに勉強するのは体力的にも簡単ではありません…
だからこそ、「勉強する習慣」があるうちに、その流れで科目B試験まで一気に進めてしまうのがいちばん楽だと思います。

## 科目B試験について

科目B試験の勉強法については本記事では割愛させていただきます。
使用した書籍は下記になります。  
[情報処理教科書 出るとこだけ！基本情報技術者［科目B］第4版](https://amzn.to/42u1iJ0)

## おわりに

働き始めてからの勉強は慣れないことも多く大変かもしれません。  
ですが、コツコツと学習を続ければ必ず合格に近づきます！

この記事が同じような状況にいる方の参考になれば嬉しいです✨
CH224KによるPDトリガー

## 目的
USB type-C充電器から5~20Vの電圧を取り出すものを作ります。
使用するICはCH224Kです。

https://akizukidenshi.com/catalog/g/g118023/

秋月電子通商で100円でした。

## 原理
### PD
PD(Power Delivery)はUSB IFによって定められた給電規格です。
type-Cではcc1とcc2で要求電圧などをやり取りします。

5/9/12/15/20/28/36/48V、3/5Aで調整可能です。
※CH224Kは5/9/12/15/20V、3/5Aのみのサポートです。

### CH224K
データシートを読みます。
DETA線はおそらくBCなどで使うものだと思うので接続しなくても大丈夫だと思います。
駆動電圧は3V~3.6Vなのでレギュレーター等で電源を作らなくてはいけません。
type-Cから送られてくる電源は5V以上なので、降圧だけで済むのはありがたいです。

要求電圧を制御する方法は２つあり、
・CFG1~CFG2に信号を印加し、要求電圧を制御する方法
・CFG1にプルダウン抵抗を設置し、その抵抗値で制御する方法です。
今回は前者を使います。
| CFG1 | CFG2 | CFG3 | 要求電圧 |
|:-:|:-:|:-:|:-:|
|1| / | / | 5V  |
|0| 0 | 0 | 9V  |
|0| 0 | 1 | 12V |
|0| 1 | 1 | 25V |
|0| 1 | 0 | 20V |

ロータリースイッチで電圧を切り替える仕様にしたいので上記の表に変換して使います。

## 回路
以上のことを踏まえ回路を設計します。
![スクリーンショット 2025-04-08 170152.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922522/ac95976b-99f8-4969-9da2-b15a30f28bcc.png)
ダイオードでロータリースイッチ→２進数に変換し、74HC04のインバーター直列でバッファしてCH224Kに接続します。
また、どの電圧を出力しているか分かるようにLEDを点灯させます。
３端子レギュレータで20V→3Vに下げるのは絶対によくないですが、icとLED一個しか使わないので見なかったことにします。

## 実装

本格的に使う予定はないので雑に実装します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922522/c9fa12d7-b9d0-4526-a106-1737265ce838.jpeg" width="300">


3端子レギュレータの放熱板としてワニグチクリップ(!?)を設置しました。
電源取り出し用にターミナルを設置しました。
上からVDD(3V),GND,VBUS(5~20V)です。

## テスト
20Vまで出力できるtype-C充電器を接続して、通電チェックします。

負荷用に、LED10個程度を点灯させます。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922522/51520be6-bb48-472c-8956-2d9aef302609.jpeg"width="300">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922522/73dbea5f-8a97-49f0-b071-0b383afab82d.jpeg"width="300">

5V,9Vともに安定して出力されています。
9Vの際には充電ケーブルのPDマークが点灯しています。

テストする際、D+,D-を接続していませんでしたが、操作が確認できたのでおそらくいらないのでしょう。

同様に12V,15V,20Vも出力できました。
ですが、電圧をあげるにつれCH224Kの発熱が大きくなり、長時間の出力は難しいと思います。


## まとめ

CH224KによるPDトリガーを設計、作成しました。
動作は確認できましたが、放熱に問題を抱えており、長期使用には耐えられないものができてしまいました。
次制作する場合は、横着せずヒートシンクを載せようと思います。

また、CH224Kをには使い方が2種類あるようで、PD,BCコントローラーと、E-markerエミュレータが使えるらしいです。
E-markerエミュレータを使えばtype-Cケーブルを作成できるのでいつか作りたいです。


<details><summary>部品表</summary>

#### IC
[CH224KUSB PD+BC シンクコントローラー ](https://akizukidenshi.com/catalog/g/g118023/)
[74HC04 インバーター ]()
[NJM78L03SU3 3端子レギュレータ ](https://akizukidenshi.com/catalog/g/g111318/)

#### 素子
[1kΩ*6](https://akizukidenshi.com/catalog/g/g116102/)
[22kΩ*3](https://akizukidenshi.com/catalog/g/g116223/)
[1.5μF*2](https://akizukidenshi.com/catalog/g/g102803/)
LED*5
[ダイオード*5](https://akizukidenshi.com/catalog/g/g100941/)

#### その他
[ロータリースイッチ](https://akizukidenshi.com/catalog/g/g116036/)
[type-Cレセプタクル](https://akizukidenshi.com/catalog/g/g115426/)
ユニバーサル基板

</details>
gtkをsudoで実行すると"can not open display"エラーで実行できない

gtkをsudo 実行時に "can not open display" が出る場合、root 権限で起動しようとして、Xサーバへのアクセス権限がないことが原因です。

## 解決方法（sudo でも DISPLAY を使えるようにする）
1. 現在のユーザーに xhost でアクセス許可を与える
 まず、通常ユーザー（root ではない）で以下を実行
```
xhost +SI:localuser:root
```
これで root ユーザーが GUI（X）にアクセスできるようになります。
VSCode上でのPrettierの保存時自動整形設定でのチェックポイント

## なぜこの記事を書こうと思ったのか
VSCode上でPrettierを使った保存時の自動整形をネット上での記事を参考にしたが、なかなか上手く行かなかったので自分のための記録と自分と同じようなパターンで困ってる人のために書こうと思いました。

## 躓いたポイント
いろんな記事に書いてある方法は、
1. Prettierをインストール
2. 設定 > saveと検索  > Format On Save Modeにチェックを入れる
![Screenshot 2025-04-13 at 20.33.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4053972/967e7c80-a1d8-45bb-a47b-18b54833ac4b.png)
3. 同じく 設定 > default formatterと検索 > Editor:Default FormatterをPrettier - Code formatterに設定(他の記事だと少し名前が異なるかもしれないが、内容は同じでした。)
![Screenshot 2025-04-13 at 20.34.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4053972/78a2bb9e-190f-4429-9e10-24a1a47ee64e.png)
上記が、いろんな記事に記載してある方法で問題なくできると思いましたが、自分の場合はできませんでした。

## 追加で必要だったこと
躓いたポイントの手順にプラスアルファで、確認して欲しい設定は
Format On Save Modeの設定がmodificationsになっていないか、
ここがmodificationsになっていたため自分はうまくいきませんでした。
ここをmodificationsではなく、fileにしてください。
![Screenshot 2025-04-13 at 20.44.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4053972/784b575e-19c1-4d0a-a86e-3d7e72ce4362.png)
もし、Prettierの自動整形がうまく行かなない方は、上記画像の設定も一度見てみてください！
JWTを超わかりやすく言うとサ〜♪✨

## JWTってなによ？💅
ねぇねぇ、JWTのことマジ気になってんでしょ？今日はそんなJWT（ジェイダブリューティー）のこと、超分かりやすく説明しちゃうよ〜！🌟

**JWT（JSON Web Token）** ってサ、めっちゃ簡単に言うと「デジタルIDカード」みたいなもの！マジぱねぇ〜便利なやつなの！ログインしたユーザーに「あなたは本物だよ認定証」みたいなトークンを渡して、それを見せるだけでアクセスできるようにしちゃうシステム！

```mermaid
graph TD
    A[ユーザー] -->|①ログイン| B[サーバー]
    B -->|②JWT発行| A
    A -->|③JWTを持ってアクセス| C[保護されたページ]
    C -->|④OK！入っていいよ| A
```

## JWTの構造がマジやばい！✨

JWTは3つのパーツに分かれてて、それぞれドットで区切られてんの！こんな感じ↓

```
xxxxx.yyyyy.zzzzz
```

1. **ヘッダー（Header）**：最初のパート！「このトークンの種類とか、どうやって署名したかとか」のアタマの情報が入ってるの
2. **ペイロード（Payload）**：真ん中のパート！「誰のトークンか」とか「いつまで有効か」みたいな大事な情報が入ってる部分！
3. **署名（Signature）**：最後のパート！「改ざんされてないよね？」ってチェックするためのサインが入ってる！

こんな感じで見るとめっちゃシンプルじゃない？✨

```mermaid
graph LR
    A[ヘッダー] --- B[ペイロード] --- C[署名]
    A -->|"アルゴリズム情報<br>(どうやって暗号化するか)"| D["例：<br>alg: 'HS256'<br>typ: 'JWT'"]
    B -->|"クレーム情報<br>(ユーザー情報など)"| E["例：<br>sub: 'ユーザーID'<br>name: 'タナカ'<br>exp: '有効期限'"]
    C -->|"改ざんチェック用<br>デジタルサイン"| F["秘密鍵で<br>署名された<br>ハッシュ値"]
```

## 使い方まじ超簡単！🔥

1. **ログイン**：ユーザーが「あたし！」って自己紹介する（ID・パスワード入力）
2. **JWT発行**：サーバーが「あなたは確かにあなたね！」って認定証（JWT）を作る
3. **保存**：ブラウザがその認定証を持っとく（LocalStorageとかCookieとか）
4. **リクエスト**：「この情報見せて〜」ってサーバーにお願いするとき、JWTも一緒に見せる
5. **検証**：サーバーが「このJWT、本物だね！」って確認して情報をくれる

```mermaid
sequenceDiagram
    participant ユーザー
    participant ブラウザ
    participant サーバー
    ユーザー->>ブラウザ: ログイン情報入力
    ブラウザ->>サーバー: ID・パスワード送信
    サーバー->>サーバー: 認証成功！
    サーバー->>ブラウザ: JWTを発行！
    Note over ブラウザ: JWTを保存
    ブラウザ->>サーバー: 保護されたページにアクセス<br>(JWTを一緒に送信)
    サーバー->>サーバー: JWTを検証
    サーバー->>ブラウザ: アクセス許可！
    ブラウザ->>ユーザー: ページ表示
```

## JWTのイマドキ用語解説💗

- **クレーム（Claims）**：トークンの中に入れた「この人はこんな人だよ情報」のこと！例えば名前とかメールとか権限とか！

- **署名アルゴリズム（Signing Algorithm）**：トークンにサインする方法！「HMAC」とか「RSA」とかいろいろあるの！複雑な数学使ってるけど、要は「このサインは本物」って証明するためのもの！

- **有効期限（Expiration Time）**：「このIDカードいつまで使える？」ってやつ！セキュリティのために、永遠に使えるわけじゃないの〜

- **JWS（JSON Web Signature）**：署名付きのJWT！「このトークン、マジで正規のサーバーが作ったやつ！」って証明する仕組み

- **JWE（JSON Web Encryption）**：暗号化されたJWT！超秘密情報も安心して入れられちゃう特別仕様💅

## まとめ：JWTのメリットがヤバい！⭐

- **ステートレス（Stateless）**：サーバーが「この人誰だっけ？」って記憶しなくていいから超ラク〜！
- **スケーラブル（Scalable）**：サーバーがいくつあっても大丈夫！だからめっちゃ大きいサービスでも使えちゃう！
- **セキュア（Secure）**：ちゃんと署名されてるから、偽物作ろうとしても無理〜！

JWTっていうクソ便利な認証システムで、みんなのアプリがもっとセキュアで使いやすくなっちゃうよ〜！💕 

マジでいろんなところで使われてるから、覚えといて損なし！これであなたもJWTマスターね✨💯
ABC401回答メモ

# 0.はじめに
　最近調子を落としているうえに先週は旅行に行っていたため
　少しお疲れ気味で参戦したABC401。
　そういえば最近コードテストや提出後の判定に時間がかかることがあり
　また攻撃受けているのかなと不安になりますね。
　というのは、言い訳でもないですがCすら解けずに
　あえなく終了。
　レートも-42の734と大きく後退し茶色もしっかり根付いてきました。


# 1. 	A - Status Code
　Sを読み込んで範囲比較して範囲内ならSuccess、外ならFailureを
　出力して終了。
　コードを書くよりFailureのつづりの方が難しかったです。

　https://atcoder.jp/contests/abc401/submissions/64731834


# 2.B - Unauthorized
　いろいろややこしい感じではありますが、
　ログイン状態のフラグとエラー回数カウントの変数ansを持ち
　loginしたらフラグを１に、logoutしたらフラグを0に
　ログインしている状態でprivateしたらansに1加算
　として、最後にansを出力して終了としました。

　https://atcoder.jp/contests/abc401/submissions/64741275


# 3.C - K-bonacci
　コンテスト中は、要素の値の対象となる範囲をデキューで管理したり
　リストの値を辞書で管理したり、modintを使ったりと
　いろいろ工夫してもダメでした。
　
　解説を見たところ、考え方はあっていたようですが
　普通にリストでの管理で行けると知り
　時間がかかるポイントの洗い出しが出来ていないことを学びました。

　https://atcoder.jp/contests/abc401/submissions/64797503

# 4.D - Logical Filling
　コンテスト終了間近にCはだめだけどDならいけるのでは？
　と、取り組みましたがWAとなりました。
　場合分けの種類が足りなかったようで、Cを早々に諦めれば
　ワンチャン行けたかなとも思いました。

　解説を見ながら解き方を把握し復習しました。

　【考え方】
　　１）先に.となることが確定している？を.に置き換えつつoの数を数え変数oにセット
　　　→先頭から文字列を見ていき左隣か右隣りがoである?を.に変換
　　２）１）で数えたoの数がKと一致していたら１）で変換し後の文字列の
　　　?を.に変換して出力して終了
　　３）残った?を出来るだけoにした場合、何個oにできるかを数えてｑにセット
　　　→文字列を先頭から見ていき、
　　　　フラグが立っておらずかつ?だったらｑを１加算しフラグを立てる
　　　　フラグが立っていて？だったらフラグを倒す
　　　　フラグが立っていて？以外だったらフラグを倒す
　　　→上記に合わせ、連続する？の先頭位置と、？の連続する個数を辞書に保持しておく
　　４）o+qがKより少ない場合？のoの位置はどこでも取りうるので
　　　　１）で変換した文字列のまま出力して終了
　　５）o+qがKと同じ場合、?の固まりの位置と？の数毎に以下変換をして出力して終了
　　　　→？の固まりの個数が偶数の時？はそのまま
　　　　→？の固まりの個数が奇数の時？を１ならo、3ならo.o以下.oを増やしてつなげた形に変換

　場合分けを思った以上に細かくする必要がありました。

　https://atcoder.jp/contests/abc401/submissions/64807820


以上
アナリティクスエンジニアリング：自律分散型データ管理イベントに参加してきた

# モノタロウデータ活用

## データ活用概要
BtoBがメインのフルスタックEC企業

2010年ごろから基盤づくりスタートした
2016年に全社的基盤

ビッククエリに集めてデータ管理

サービスアカウント除いて900人/月　かなり幅広くヘヴィに活用している

局所最適なデータ活用が起きていた。
→見てる指標の定義が微妙に違ってしまいコミュニケーション齟齬

分析したいけどどのテーブル使ったらいいか不明とか
SQLがそもそも正しいのかわからないとか


## 取り組み
2020にLooker導入
データに詳しい利害関係者にヒアリングしてデータの定義

2021年DWH構築　データをほかの用途でも使えるように構築

導入の結果：徐々に使われるように　持ち帰ってデータ集計していたのが、その場で素早く商談できるようになった
（匠によるデータモデリングが有効と思われる）

DHW普及に伴い指標管理をしたいというニーズが出てきた


## 現状の課題
これまで中央集計型でやってきたが、最近これだけでは難しい。
要求が特定ドメインに依存してしまう。

管理はしたいけど、ドメイン独自で見てる指標を管理するところがないから中央で集めてる、
データの粒度感が指標によって異なる。
その指標がどういう意味があってとか、それを満たすためにシステム側にどんなデータ　(←☆ここ質問したい：メトリクスを構成する分析系のデータって意味？or 業務データ？)が入ってればいいか？の理解が十分に必要で大変
回答：後者の意味合い
業務と分析で多少のギャップがある


### 上記の理由
中央集計が困難な理由　ドメインが広範囲にわたる

ドメインが異なると同じ用語でも意味が異なる　ユビキタス
商品情報といっても、ドメインによって粒度も意味合いも変わる。


## どう取り組むか
データメッシュ　アナリティクスエンジニアリング

自律的にデータ活用　←ティール組織との関連性がなにかあるのでは？

SQLを変更したことでオペレーションにどんな影響があるのか？

dbt導入でデータ品質も一定の担保ができるようになった。



# パネルディスカッション

## 営業領域やSCM領域でデータ管理やろうとなったきっかけ
もらっているデータの中でどうにかするしかない状況だった。

分析するに伴う必要なデータが全然そろっていない状況である中で、
モデルをどうにかやるうよりも手でアナログに必要なデータを追加した方が費用対効果上がった。
　
クエリ見たところスプレっとシートに1000行以上のSQLによって、
営業が本来のバリュー発揮する、お客さんの意思決定支援以外に時間を割かれていた。


## アナリティクスエンジニアリングはドメイン内でどんな働き方をしているのか
データ周りの煩雑さを入社当初はやっていた。
最近は人によってクエリがバラバラなので、とりまとめてKPI定義して整備など、SQLレビューなど。
　

長いSQLが無数にあったので、全社で指標を揃えることはできなくても、営業内のスコープで整備した。
中間テーブルなどを定義するなどの環境づくりをしてた。

　
連携の仕方は、本当に暗黙的にチートポ的連携をしている。

:::note info
アナリティクスエンジニアは、イネイブリングとして各データプロダクトを管理するストリームアラインドを支援する印象。
:::


・アナリティクスエンジニアリングとして参画して変化したこと
　みんな自身で自立してデータ活用できるようになってきた。
　使う方からこういった指標を今見たいから入れてもらえないか？などの質のいいデータ活用サイクルと対話が資産としてたまる環境を作ることができた。


　KPI揃えるときに、週１mtgやってクエリ何にする？という対話を重ねられた。イネイブラーとしてファシリ的に問いかけていたようだ。
　横に何かを共有する場が最初なかったが、強制的に横連携の文化を構築。

　データを使って業務の改善BPRにもつながる。宿題：GQMストラクチャーとの関係性を落とし込む　　（☆質問したい！！業務効率化にデータ活用って具体的には？　各業務プロセスの指標では？　アジャイルメトリクスにつながる？）
　回答：どういう業務プロセスがあるか明らかにしないといかん　リード数これくらいで～とか
めずらしめのビジネスモデルなので、なかなか既存のBPMツールがフィットしない。けどもフィットする部分も一定数以上あるはずだから、汎用的業務部分には適材適所BPMツールを導入検討されているとのこと。



・ドメイン内におけるデータ活用、管理面における課題
　商談を何回こなせているのか？　とか売上という漠然としたものではなく、データ活用サイクルを設計することが課題点

　SQLかけるけど複雑なのかけないとかスキルセットがバラバラ。そこにどんなツール使うとか、業務フローどう作るのかが課題点。

　データ管理や活用のリテラシーが必要：データマネジメントピラミッドの知恵の部分？


・アナリティクスエンジニアリングのやりがいと感じる点
　組織がフラットなのでボトムアップにできることに限界あるときには、トップダウンでもいろんな方法でできる。
　基幹システムの刷新を今やっている中で、基幹システムとしてデータをどう持つべき？という考察は機会があまりないのでやりがい。


　組織としてデータ活用したいという声が多い。
　せっかくダッシュボード作ったのに参照されないみたいなことがある。
　つくったものをデータ活用サイクルを設計していくことに携われるのが楽しいそう。

　同じ用語でも言葉の定義が変わる部分は、データの境界場所。(メッシュの切り分け部分の目安)


(☆質問)データに対する制度が足をひっぱったことは？　またそこからどう復帰した？


③アナリティクスエンジニアリングとして取り組んでいきたいところ


大きく分けて３つの取り組みを行っている。

・使われないダッシュボード(ECRSのEで対応)
・似た指標が別々ロジックで管理されてる(DRY違反)
・バッチ障害対応に時間かかる(ボトルネックの特定)

最初はストリーマーとして入りつつ、解像度上がったらイネイブラーとして俯瞰して関わっていく。
プラットフォームとして支えることも。

GQMによる指標の企画　と　情報品質　データストーリーテリングかな？→DFDにつなぐ？

データに対する価値駆動モデリングと、脅威モデリング、GQMで、データの品質の考察をする感じかな？

バリューストリームマップ使って業務プロセス可視化するあたりが素晴らしいと感じた。
データストーリーテリングによるデータの価値記述が必要かもしれないと感じた。
【【AWSでブログ運用】XServerからWordPressを完全移行した手順とトラブル対応まとめ（全文リンクあり）

---

## ✅ はじめに：なぜAWSに移行しようと思ったのか？

「そろそろ自分でサーバー環境を構築できるようになりたい」「AWSやクラウド環境のスキルを、実戦で学びたい」

そんな思いから、これまでXServerで運用していたWordPressブログを、**ゼロからAWS上で構築・移行すること**に挑戦しました。

結果的にこの作業は、単なる“引っ越し”ではなく、  
- **サーバー構築スキル**  
- **WordPressの構造理解**  
- **セキュリティやトラブル対応の実践知**  

など、フリーランス・副業・インフラ運用にも活かせるスキルを多く学べる機会となりました。

---

## 🛠 使用した構成（クラウドインフラ）

| 項目        | 内容                                           |
|-------------|------------------------------------------------|
| EC2         | Ubuntu 22.04（Apache + PHP8）                 |
| RDS         | Amazon Aurora（MySQL互換）                    |
| Route 53    | DNS管理（独自ドメイン：raku-study.com）       |
| Let's Encrypt | 無料SSL証明書（Certbot導入）             |
| WordPress   | 既存のコンテンツを完全移行（テーマ・DB含む）  |

特に EC2 + RDS の連携設定や、Let’s Encrypt の導入、`.htaccess` 調整などは実務で使える重要な構成要素でした。

---

## 🧭 実際に行った移行ステップ（要約）

### ① XServerからの完全バックアップ

- FTPツール（FileZilla）で `public_html` 配下を全取得  
- phpMyAdminで WordPress用の `.sql` ファイルをエクスポート

### ② AWSでWordPress環境を構築

- EC2（Ubuntu）にApache + PHPをインストール  
- RDSでデータベース作成 → EC2と接続  
- `wp-config.php` に接続情報を記載 → 動作確認

### ③ ドメイン・SSL・リダイレクト設定

- Route 53で新ドメインを設定し、ネームサーバーを切替  
- CertbotでHTTPS対応  
- `301リダイレクト`により旧ドメインから新ドメインへSEO引き継ぎ

### ④ セキュリティ・パフォーマンス調整

- XO Security, Wordfence導入でログイン試行検知  
- EWWW Image Optimizer や UpdraftPlus で最適化・バックアップ体制構築  
- 投稿エラーなどにはDB構造・PHP設定調整で対応

---

## 🚨 実際に遭遇したトラブルと解決策

「手順通りにやったのに、なぜか動かない」「投稿が保存できない」など、実際には多くのハマりポイントがありました。

以下はその一部です：

### ❌ `.htaccess`が効かず記事が404エラーに  
→ Apacheの設定を `AllowOverride All` に修正して反映

### ❌ CertbotがAmazon Linuxで正常動作せず  
→ UbuntuへOSを切り替え、仮想環境でCertbot導入＆SSL化成功

### ❌ WordPress投稿が保存できない（HTTP 500 or 更新失敗）  
→ DBのテーブル定義修正・PHP設定（post_max_sizeなど）で解決

### ❌ reCAPTCHAエラー：「サイトキーのドメインが無効です」  
→ Google側で新ドメインを再登録 → WordPressに新キーを設定

---

## ✨ 今回の移行を通して得られた知見

- AWSの主要サービス（EC2, RDS, Route 53）の実践的な使い方  
- WordPressの構造（DB設計・設定ファイル・権限管理）  
- 自動SSL化、301リダイレクト設定、バックアップ管理の仕組み  
- 不具合に直面しても調査 → 修正 → 動作確認という力

これらは今後、**インフラ構築・Web制作・副業・サーバー引っ越し案件**で確実に活かせる知識になったと実感しています。

---

## 🔗 もっと詳しく知りたい方へ（移行の全手順＋コード公開中）

👉 全スクショ・設定ファイル付きで詳細に解説した本編はこちら！

👉 🔗 [raku-study.com：XServer → AWS WordPress完全移行ガイド](https://raku-study.com)

> トラブル対応、Certbot構築、.htaccess例、セキュリティ設定などを網羅。これから移行する人向けの保存版です！

---

## ✉️ おわりに

「AWSでWordPressを運用してみたいけど難しそう…」  
そんな方にとって、本記事が一歩目の道しるべになれば幸いです。

記事の内容について質問や「ここがうまくいかなかった」なども、ぜひコメントください！  
一緒に試行錯誤していきましょう💪
（自分用メモ）Hiltで依存関係を追加する


## 1. 依存関係を追加する
[ドキュメント](https://developer.android.com/training/dependency-injection/hilt-android?hl=ja#setup)

まずルートの gradle にプラグインを追加
```build.gradle.kts
plugins {
  ...
  id 'com.google.dagger.hilt.android' version '2.51.1' apply false
}
```
<details><summary> トップレベルの gradle の記述について</summary>
全てのモジュールで同じ plugin バージョンを使用するため、トップレベルのGradle でバージョン付きの plugin を宣言している。<br>
こうすることで、モジュール側ではバージョンを書かずに plugin を宣言することができる。<br>
トップレベルでは宣言のみを行なって plugin の使用はしないので、 apply false を設定している。<br>
https://developer.android.com/build/migrate-to-kotlin-dsl?hl=ja&utm_source=chatgpt.com#perform-refactoring

</details>


それからappモジュールの gradle に依存関係を追加

```app/build.gradle.kts
plugins {
  id("kotlin-kapt")
  id("com.google.dagger.hilt.android")
}

android {
  ...
}

dependencies {
  implementation("com.google.dagger:hilt-android:2.51.1")
  kapt("com.google.dagger:hilt-android-compiler:2.51.1")
}

// Allow references to generated code
kapt {
  correctErrorTypes = true
}
```

## 2. Application クラスにアノテーションを付与する
```MainApplication.kt
@HiltAndroidApp
class MainApplication : Application() { ... }
```

## 3. Activity / Fragment にアノテーションを付与する
依存関係を受け取る側に `@AndroidAnnotation` のアノテーションを付与する
https://developer.android.com/training/dependency-injection/hilt-android?hl=ja#android-classes
```MainActivity
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {

  @Inject lateinit var analytics: AnalyticsAdapter
  ...
}
```

## 4. ViewModel にアノテーションを付与する

```ExampleViewModel.kt
@HiltViewModel
class ExampleViewModel @Inject constructor(
  private val savedStateHandle: SavedStateHandle,
  private val repository: ExampleRepository
) : ViewModel() {
  ...
}
```

## 5. 依存関係を受け取る側に依存関係を注入する

```ExampleActivity.kt
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {
  private val exampleViewModel: ExampleViewModel by viewModels()
  ...
}
```

## 5'. Composable 関数に viewModel の依存関係を注入する

まず以下の依存関係を追加する。
```build.gradle.kts
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5")
```

すると `viewModel()` 関数を使用して Composable 関数に viewModel を追加できる

```MyScreen.kt

// import androidx.lifecycle.viewmodel.compose.viewModel
@Composable
fun MyScreen(
    viewModel: MyViewModel = viewModel()
) {
    // use viewModel here
}
```
https://developer.android.com/develop/ui/compose/libraries?hl=ja#viewmodel
HTTP通信を使うゲームの設計

# HTTP通信を使ったゲーム

古よりブラウザゲームでHTTP通信を使ったゲームはたくさん作られてきたはずである。
ちなみに私はその歴史も、ブラウザゲームについてもあまり詳しくない。

だがどういうわけかブラウザゲームは作っているので、思う所を書いていく。

## 状態レス

HTTPは状態を持たない。
クライアントがサーバーにリクエストを送ったらサーバーがレスポンスを返す。
それで通信は終わりである。

いっぽうゲームは状態を持つ。
ゲーム側からすると状態をサーバーに保存してもらいたいという欲求がある。

## 掲示板なんだよな

結局、HTTP通信縛りがある以上、その形態は掲示板に似ることになる。
つまりゲーム側がSPAに似た設計にして、サーバーと通信しても、それは結局掲示板の発展形にしかならない。
制約として掲示板があるわけである。

この縛りプレイを念頭に置かないといけない。

## でも他の人と通信したいんだけど

しかしWebゲームなわけだから、一人で出来るゲームを作ってもしょうがないわけである。
やはりWebで他の人とつながれるなら、他の人と繋がれるゲームを作りたいものである。

ということはゲームのデータをHTTPでサーバーに保存して、それをみんなで共有する、という設計になる。
掲示板である。

## この制約でできることはあまり多くない

WebSocketなどであればベースが掲示板ではなくチャットになるので、掲示板よりはリアルタイム性が上がる。
しかしHTTPはベースが掲示板である。
よって出来ることは掲示板の範囲に収まる。
強引にリクエストをリアルタイムで出してもいいが、それだとサーバーの負荷が上がるため、PVが伸びたら現実的な設計にはならないことが懸念される。

## どうやってリアルタイム性を演出するか？

面白いのはゲームを通じて他のプレイヤーと繋がっている実感を演出することである。
そうするとたとえばゲーム中に掲示板を作って、その掲示板を通して他のユーザーと交流するなどがある。
だが、それならゲームはおまけで掲示板が主役になってしまう。
どうやってゲーム主役で演出したらいいか？

## クリエイト系ゲーム

たとえばゲームステージをユーザーに作らせて、それを投稿させる。
そしてそのゲームステージをみんなで共有してプレイする。
これならゲーム主役のコミュニケーションだろう。
だが、ゲーム中にほかのユーザーとコミュニケーションを取るにはやはり掲示板じゃないとだめである。

## ステージデータの更新

クリエイト系でゲームステージを投稿するゲームで、そのステージを他のユーザーが改変できるようにする。
たとえば岩を叩いたら岩が壊れ、その状態をHTTPでサーバーに送ってステージデータを更新する。
これはリアルタイム性がありそうである。
だが、HTTPなので同時に二人にデータが配信されて、一方がデータを更新してももう一方はその更新を受け取れない。ブラウザを更新しないといけない。チャットならブロードキャストでデータが入ってくるが、掲示板だとこういうことができない。

## うーん

何か面白いアイデアがあればいいのだが。
HTTPという縛りの中で面白いアイデアが。
なかなか思いつかないのであった。
おわり。
【Go】関数変数化で簡単にテスト可能なコードを書く

## はじめに

こんにちは！フリーランスエンジニアのこたろうです。
今回は、Goで直接関数呼び出しを含むコードをテスト可能にする最もシンプルな方法を紹介します。

## テスト難しい直接関数呼び出し

次のようなコードがあるとします：

```go
func ProcessUser(userID string) (*ProcessedData, error) {
    // 直接関数を呼び出している - テスト時に置き換えられない
    user, err := GetUserFromDB(userID)
    if err != nil {
        return nil, err
    }
    
    // 結果の作成
    return &ProcessedData{
        UserName: user.Name,
        ProcessedAt: time.Now(),
    }, nil
}

// 実際のデータベースアクセスを行う関数
func GetUserFromDB(id string) (*User, error) {
    // 実際のDB処理（テスト時には実行したくない）
    db, err := sql.Open("mysql", "user:password@/dbname")
    if err != nil {
        return nil, err
    }
    defer db.Close()
    
    // データベース処理...
    return &User{ID: id, Name: "John"}, nil
}
```

## シンプルな解決策：関数変数化

わずか2行の変更で、テスト可能なコードに変えられます：

```go
// 通常の関数定義をそのまま残す
func GetUserFromDB(id string) (*User, error) {
    // 実際のDB処理
    db, err := sql.Open("mysql", "user:password@/dbname")
    if err != nil {
        return nil, err
    }
    defer db.Close()
    
    // データベース処理...
    return &User{ID: id, Name: "John"}, nil
}

// 変数に関数を代入
var GetUserFromDBFunc = GetUserFromDB

// ProcessUser関数も少し修正
func ProcessUser(userID string) (*ProcessedData, error) {
    // 直接呼び出す代わりに変数経由で呼び出す
    user, err := GetUserFromDBFunc(userID)  // ここだけ変更
    if err != nil {
        return nil, err
    }
    
    return &ProcessedData{
        UserName: user.Name,
        ProcessedAt: time.Now(),
    }, nil
}
```

## モックを使ったテスト

この変更により、テスト時に関数をモックに置き換えることが可能になります：

```go
func TestProcessUser(t *testing.T) {
    // 元の関数を保存
    originalFunc := GetUserFromDBFunc
    
    // テスト終了時に元に戻す
    defer func() {
        GetUserFromDBFunc = originalFunc
    }()
    
    // モック関数を設定
    GetUserFromDBFunc = func(id string) (*User, error) {
        // テスト用のモック実装
        return &User{ID: id, Name: "Test User"}, nil
    }
    
    // テスト実行
    result, err := ProcessUser("123")
    
    // 検証
    assert.NoError(t, err)
    assert.Equal(t, "Test User", result.UserName)
}
```

## エラーケースのテスト

エラーパターンも同様に簡単にテストできます：

```go
func TestProcessUser_Error(t *testing.T) {
    // 元の関数を保存して後で復元
    originalFunc := GetUserFromDBFunc
    defer func() { GetUserFromDBFunc = originalFunc }()
    
    // エラーを返すモック関数
    GetUserFromDBFunc = func(id string) (*User, error) {
        return nil, errors.New("database error")
    }
    
    // テスト実行
    result, err := ProcessUser("123")
    
    // 検証
    assert.Error(t, err)
    assert.Nil(t, result)
}
```

## この方法のメリット

- コード変更が最小限（たった2行）
- シンプルで理解しやすい
- 既存コードへの影響が少ない
- 特別なライブラリやフレームワークが不要

## まとめ

Goで関数を変数化する方法は、テスタビリティを向上させる最もシンプルな手法の一つです。既存のコードに対しても最小限の変更で導入できるため、レガシーコードのリファクタリングや、急いでテストを書く必要がある場合に非常に有効です。
開発する前に知っておきたかったDynamoDB


DynamoDBはNoSQLDBとして人気のあるサービスですが、RDBとは考え方が大きく異なるため、初めて使う方は戸惑うことが多いサービスです。

実際にDynamoDBを触って半年経ったので、「最初に知っておけばよかった」と感じたポイントを共有しておきます。

# 各データの一覧ができるように設計する
DynamoDBでは、RDBのように自由な検索ができるわけではないため、「どういう条件で一覧を取得するのか？」をあらかじめ明確にしておく必要があります。

特に、各データの一覧の取得はシステムの要件になくても開発する上で頻繁に必要になるので最初から設計しておくといいです。

事前に設計するのを忘れても後から追加で取得できるようにはできます。

ただ、緊急でなくても開発しているとどこかで必要になるので、早めに対応しておいた方がいいです。


# よく使う〇〇一覧はブックマークしておく

多くの他のAWSサービスでもそうなのですが、DynamoDBもクエリの検索条件はURLに反映されるので、ブックマークしておくと同じ条件で再度開くことができます。

よく確認するデータやクエリ結果の画面は、ブックマークしてすぐ開けるようにしておくと便利です。

DynamoDBはPKとSKで検索を行うのですが、PKとSKを覚えてなくてDB設計書を開いて確認、といった手間がなくなります。

チームでも共有しておくといいです。

# 最初はオンデマンドで様子を見る
DynamoDBの料金体系には「オンデマンド」と「プロビジョンド」がありますが、最初からプロビジョンドにするのはおすすめしません。

プロビジョンドはWCU/RCUというキャパシティの設計が必要ですが、最適な値は実際に運用してみないと分かりません。

CUの制限に合わせた実装が難しく、たとえば大量のUpdateを行いたいとき、WCUの上限に引っかかる可能性があり、リトライ処理を実装する必要がありますがオンデマンドなら気にする必要がありません。

GSIもそれぞれでCUを設定する必要もあるため、どれくらい必要かわかっていない実運用前に調整するのは難しいです。

また、オンデマンドにすると料金が高いと聞いていたのですが、実際に試しにオンデマンドで運用してみたら、プロビジョンドを使用していたときも安かったので、最初からオンデマンドで開発しておけばよかったです。

# クエリで全部取れない問題とlastEvaluatedKeyの罠
DynamoDBでは、QueryやScanで一度に取得できるデータの件数に上限があります（デフォルトで1MB分まで）。

lastEvaluatedKeyを使って、ページングやループ処理でデータを全件取得するような実装が必要です。

本番で動かしたら「一部しかデータが取れてない！」という状態になりかねません。

大抵は全部取得必要があると思うので、lastEvaluatedKeyを考慮した全て取得する関数を作って、それを使うようにしておくといいです。

```js
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { QueryCommand, DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({});
const ddbDocClient = DynamoDBDocumentClient.from(client);

/**
 * DynamoDBのQueryでページネーションを考慮しつつ全件取得する
 * @param {object} params - QueryCommandで使うパラメータ（TableName, KeyConditionExpressionなど）
 * @returns {Promise<Array>} - 全てのアイテムを含む配列
 */
async function fetchAllItems(params) {
  const allItems = [];
  let lastEvaluatedKey = undefined;

  do {
    const command = new QueryCommand({
      ...params,
      ExclusiveStartKey: lastEvaluatedKey,
    });

    const result = await ddbDocClient.send(command);

    if (result.Items) {
      allItems.push(...result.Items);
    }

    lastEvaluatedKey = result.LastEvaluatedKey;
  } while (lastEvaluatedKey);

  return allItems;
}

```

# バックアップはポイントインタイムリカバリ（PITR）が楽
当初はAWS Backupを利用していましたが、現在はポイントインタイムリカバリ（PITR）を使っています。

テーブル設定で有効化するだけで、秒単位で過去35日間の任意の時点に復元できます。

AWS Backupに比べても料金に大きな差はありません。

バックアップ取得のスケジュール設定やライフサイクル設定をする必要がないので、PITRのほうが運用がシンプルです。

# SQLとのデータ取得方法の違い
SQLが使えないので、JOINもできません。

そのため、RDBのような複数テーブルの結合ができないため、複雑なデータの取得はローカルでJavaScriptなどでプログラムを書いてCSVで出力しています。

これは見方によってはメリットでもあるのですが、SQLと違ってプログラムで取得するため自由にデータを取得ができます。

SQLが苦手な人にとってむしろ使いやすいかもしれません。
私も今はこちらの方が使いやすく感じてます。

# おわりに
最初から知っておいてたらよかったな〜、と思ったことをまとめました。
これからDynamoDBを使う方に、少しでも役に立てば幸いです。
【備忘録】"Ports are not available: exposing port TCP 0.0.0.0:3306 -> 0.0.0.0:0: listen tcp 0.0.0.0:3306..."の対処法

dockerのコンテナを起動させるために、いつも通り`docker compose up -d`したところ、以下のようなエラーが出た。
```
[+] Running 2/3
 ✔ Container app_laravel      Started                                                                  0.3s
 ✔ Container test_phpmyadmin  Started                                                                  0.3s
 ⠸ Container db               Starting                                                                 0.3s
Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:3306 -> 0.0.0.0:0: listen tcp 0.0.0.0:3306: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.
```

### 原因と解決策

他のアプリにポート番号3306番が使われているのでは...？
と思い、データベース関連のアプリが裏で動いているのではと考え、Windowsのタスクマネージャーを調査。

mysqldが動いてた。

なので、タスクマネージャーから「タスクの終了」でアプリを強制終了（これはdockerだけど）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2646702/ab21d7aa-f708-4229-80b7-c9861caf1d13.png)

そして再度`docker compose up -d`を実行。
```
[+] Running 4/4
 ✔ Container app_laravel      Running                                                                  0.0s
 ✔ Container test_phpmyadmin  Running                                                                  0.0s
 ✔ Container nginx            Started                                                                  0.4s
 ✔ Container db               Started                                                                  0.4s
```
動いた！！！

Ports are not availableと言われたら、ポートの競合を疑ってみると◎ということを学べた。

### 参考記事
https://sneakyblog.com/how_to_solve_port_conflict_error/
SadServers part2

本記事は(SadServers)[https://sadservers.com/]というlinuxサーバに関するトラブルシューティングを無料で練習可能なサイトを実施した記録です。
正解だけでなく、自分の回答過程やチップスを記録するためのものです

# TL;DR
\#1 - "Saint John": what is writing to this log file?
学べること
1. テキストファイルの抽出と加工
1. 行の並び替え
1. 行の重複排除

利用コマンド
- awk：テキストを「フィールド単位」で処理して、抽出・加工
- sort：テキスト行を並び替える
- uniq：連続した重複行を1つにまとめる

# 取り組み
## 問題の理解
>説明:ウェブサーバーのアクセスログファイルが にあります/home/admin/access.log。ファイルはHTTPリクエストごとに1行で構成され、各行の先頭にはリクエスト元のIPアドレスが記されています。
このファイルで最もリクエスト数が多いIPアドレスを調べてください（同点はありません。IPアドレスは一意です）。結果をファイルに書き込んでください/home/admin/highestip.txt。例えば、リクエストが「1.2.3.4」の場合、次のように記述します。echo "1.2.3.4" > /home/admin/highestip.txt

考え方
1. 該当ファイルの中身を確認
1. 各行から該当のフィールドを抽出
1. IPアドレスを昇順で表示
1. IPアドレスの重複排除と重複カウント
1. 重複カウントの数が大きいものから順にIPアドレスを表示

## 該当ファイルの中身確認
（下記はイメージ）
```terminal
admin@i-0b71e631086adadb0:~$ cat /home/admin/access.log
192.168.0.1 - - [13/Apr/2025] "GET /index.html"
10.0.0.2 - - [13/Apr/2025] "POST /login"
192.168.0.1 - - [13/Apr/2025] "GET /home"

(省略)

```
## 各行から該当のフィールドを抽出
各行の先頭にIPアドレスが記載されているので、一番目の要素を抽出
```terminal
awk '{print $1}' /home/admin/access.log
```
## IPアドレスを昇順で表示
```terminal
awk '{print $1}' /home/admin/access.log | sort 
```
## IPアドレスの重複排除と重複カウント
同一IPアドレスを重複排除。また、同一IPの個数を表示
```terminal
awk '{print $1}' access.log | sort | uniq -c
```
## 重複カウントの数が大きいものから順にIPアドレスを表示
```terminal
admin@i-0b71e631086adadb0:~$awk '{print $1}' access.log | sort | uniq -c | sort -nr
2 192.168.0.1　（出力例）
1 10.0.0.2　　（出力例）
```
あとは出力結果の最初のIPアドレスを該当ファイルに記載するのみ
```head -n 5```等を使って上位５つの最頻IPが降順に並んでいることを確認してみたもよい

# 公式のヒントと解答
上記の考え方と同様のため、公式のヒントは省略
補足
- ```cat, cut```コマンドを用いたフィールド抽出

# Tips
```
awk [パターン] {アクション} ファイル名
```
{print $1} → 1列目（フィールド）を表示（例: awk '{print $1}' access.log）
-F'区切り文字' → 区切り文字を指定（例: awk -F':' '{print $1}' /etc/passwd）
{if ($3 > 1000) print $1} → 条件を指定して出力

```
sort [オプション] ファイル名 または パイプ入力
```
-n → 数値順にソート（例: sort -n numbers.txt）
-r → 降順にソート（例: sort -r names.txt）
-nr → 数値＋降順（例: sort -nr）
-k 番号 → 指定フィールドでソート（例: sort -k 2）

```
uniq [オプション] ファイル名 または パイプ入力
```
-c → 重複の回数を表示（例: uniq -c）
-d → 重複した行のみ表示（例: uniq -d）
-u → 一度だけ出現した行を表示（例: uniq -u）

```
cut [オプション] ファイル名
```
-d'区切り文字' → 区切り文字を指定（例: cut -d',' -f1）
-f 番号 → フィールド番号を指定（例: cut -d' ' -f1）
ITサービスマネージャー試験　試験1週間前に確認すること

ITサービスマネージャー試験を受験するにあたり、要点を取りまとめました。

# 午後試験対策の要点
要点は下記の通り。 
* インシデントの発生原因と回復方法や回避策をデータベースで管理する理由は、同種のインシデントを早期に回復させるため
* 不審なメールを受信したことが判明した場合には、速やかに削除指示を行う
* 日程や日数については、要点を抽出し、それをスケジュールに書き出す

### ■ システム名や各企業との関係性の整理  
システムや関係企業が複雑に絡む問題については、以下のように構造化して記録・管理することが重要です。

- **システム名**：各システムの正式名称、略称、用途
- **関係企業**：
  - **開発元**：どの企業がシステムを開発したか
  - **運用保守担当**：保守・運用を担っている企業名と担当部署
  - **ユーザー企業**：システムを実際に利用している企業や部門
- **関係図**：相互関係を示す図解（例：ER図や業務フロー図など）

このように体系的に記載することで、インシデント発生時や調整が必要な場合に、スムーズな情報把握と対応が可能になります。

### ■ インシデント情報のデータベース管理の目的  
- **目的**：同種のインシデントに迅速かつ的確に対応するため
- **内容に含める情報**：
  - 発生日時・影響範囲
  - 発生原因
  - 一時対応と恒久対応の手順
  - 回避策や注意点
  - 対応した担当者・連絡先

**→ 定型的なフォーマットで蓄積することで、検索性・再利用性が高まる。**
### ■ 不審なメールの対応手順  
- **確認**：不審なメールが届いたという報告を受けた場合
- **初動対応**：
  - 速やかに削除を指示
  - 関係者へ注意喚起（メール転送や開封をしないように）
- **その後の対応**：
  - セキュリティ部門へ報告
  - メールヘッダ等の情報を元に調査
  - 必要に応じてPC隔離、パスワード変更などを実施

---

### ■ スケジュール管理における日程・日数の記載方法  
- **ポイント**：
  - 日程や期間を把握する際は、**要点を抜き出して箇条書き**
  - **タスク・イベント単位**でスケジュール表に記載（カレンダー形式が有効）
- **例**：

| タスク内容 | 開始日 | 終了日 | 日数 | 備考 |
|------------|--------|--------|------|------|
| サーバ点検 | 4/15   | 4/16   | 2日  | 深夜作業 |
| システム移行準備 | 4/17 | 4/22 | 6日 | 外部ベンダー調整含む |
React Testing LibraryのqueryByTextとgetByTextの違い

React Testing LibraryのqueryByTextとgetByTextの違いがわかっていなかったのでメモ。

queryByTextの場合は対象の文字列がなくてもエラーにはなりませんが、getByTextの場合は対象の文字列がなかった場合はエラーになります。

```react
const Sample = () => {
  return <div>Sample</div>;
};

export default Sample;
```

```react
import "@testing-library/jest-dom";
import Sample from "@/components/Sample";
import { render, screen } from "@testing-library/react";

describe("Sample", () => {
  it("queryByText", () => {
    render(<Sample />);

    expect(screen.queryByText("test")).not.toBeInTheDocument();
  });
  it("getByText", () => {
    render(<Sample />);

    expect(screen.getByText("test")).not.toBeInTheDocument();
  });
});
```

上記の2つのテストケースはどちらも文字列`Sample`が見つからないためpassしそうですが、1つ目のケースはテストが通りましたが2つ目は下記エラーが発生しました。

```shell
TestingLibraryElementError: Unable to find an element with the text: test.
This could be because the text is broken up by multiple elements.
In this case, you can provide a function for your text matcher to make your matcher more flexible.
```
Weekday Coffee Morning #1 - Jazz, Bossa, Piano, Brass【Suno AIで作曲】【動画 3分44秒】【YouTubeチャンネルからの転記です】

この記事は、わたしの[YouTubeチャンネル](https://bit.ly/Yamanaka-YouTube "Living without things. 持たない生き方 手放す生き方")にある公開動画を転記しております。
( どこかのタイミングで、プログラミング-Google Apps Script or iPaaS-Zapier をつかって自動転記させる予定です )

転記のための時間コストを少なくしたいので、文字装飾( Markdown記法 )を極力つかわずに書いております。

こちらが動画内容です👇

***

![01 YouTubeサムネイル & 再生中の画像 Suno AI _ Weekday Coffee Morning #1 2nd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386308/2c86a36a-82db-4374-993c-7c34e2d711f5.png)




* # 動画URL
    * https://youtu.be/3lUDCHayI1g

<br>

* # 動画タイトル
    * Weekday Coffee Morning #1 - Jazz, Bossa, Piano, Brass【Suno AIで作曲】【動画 3分44秒】

<br>

* # 動画の説明欄(一部を抜粋)

撮影日 = 2025-04-12(土)

Suno AIとは、文章から音楽を生成することができるAI( Text-to-Music-AI )です。
わたしは、2024-04-02(火)に初めてSuno AIで有償プランを契約してから、時々楽曲をつくって遊んでいます。

🎦【Suno AI】文章から音楽を生成するAI( Text-to-Music-AI )で、3分間で2曲、6分間で4曲作りました【試聴可能】1)伴侶の曲 2)税理士の曲【動画 16分11秒】
https://youtu.be/QKfhk4HgQ_g

🎦“Suno AIでつくった楽曲”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghMLdiSVqwvSs_Z5y0H4VGOe

🎦“効果的にSuno AIを活用するヒント”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghPuaNOVZn-N53wVvsBkeHdI


今回は、Suno AIで作曲し、 WAV 出力した楽曲を動画に仕上げました。

2025年3月～4月、毎朝のように訪れていた『WEEKDAY COFFEE ROASTERS』( https://bit.ly/Whatis-WEEKDAY-COFFEE-ROASTERS )さん。
この楽曲の舞台は、こちらのお店です。
美味しいエスプレッソやマキアートのおかげで、気が重かったプロジェクトの様々なタスクもはかどり、いつの間にか楽しみながら乗り切ることができました。
歌詞には、わたしが実際に口にした飲み物のメニューや、印象的だった会話、お店の空気感を織り込みました。
そんな素敵な時間を思い出しながら、感謝を込めて制作したファンメイドテーマソングです。

「毎朝美味しいコーヒーと、穏やかな時間をありがとうございました。ごちそうさまでした！」

この楽曲をぜひ聴いてみてください。
ぜひ、温かいコーヒーを飲みながら楽しんでください。
そしてぜひみなさんも、大好きなお店やブランドや企業への感謝を込めて、オリジナル曲をつくってみてください！

作曲日:
2025-04-04(金)

Suno AI 契約の種類:
Pro Plan

Suno AI Version:
v4

楽曲の正式名称:
Weekday Coffee Morning #1

Suno AI Library URL:
https://bit.ly/Weekday-Coffee-Morning-01

Custom Mode: On

Audio Inputs: Not Used

With Vocals:


---


Lyrics/歌詞:

[vers1]  
Weekdayの Espresso  
Weekdayの Macchiato  
Weekdayの Caffè Latte  
Weekdayの Cappuccino  

[vers2]  
Weekdayの Vanilla Latte  
Weekdayの Caffè Mocha  
Weekdayの Americano  
Tu lu lu lu… Weekdayの  

[Chorus]  
Weekdayの ありがとう  
Weekdayの 美味しいね  
Weekdayの おめでとう  
Weekdayの また明日


---


Suno AIへの指示文章( プロンプト/Prompt ): Custom Modeの場合は”Style of Music”を指定します。


🇬🇧English

[Jazz][Bossa][Piano][220 Seconds][Break][Outro]


🇯🇵日本語訳

[ジャズ][ボサノバ][ピアノ][220秒][ブレイク][アウトロ]


---


Suno AI 公式URL
https://accounts.suno.ai


---


🎥この動画と関連が強いわたしの動画
・“Weekday Coffee Morning”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghNWYsHCCd7SDJ2ED3KXCX3s


・“Weekday Coffee Morning 日付降順(新しい動画を上に追加)”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghMKm724o2RNIrdEVvL9CWQh


・“Suno AIでつくった楽曲”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghMLdiSVqwvSs_Z5y0H4VGOe


・“効果的にSuno AIを活用するヒント”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghPuaNOVZn-N53wVvsBkeHdI


🎥Shortened URL for this video | この動画の短縮URL
https://bit.ly/42xHfJz
SSIT1のWriteUp

# WriteUp
問題のインスタンスを立ち上げてアクセスすると下記の画面が表示される

![Pasted image 20250412100444.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754817/c8c24237-157c-443f-8088-5704ac6e4f6c.png)

適当な文字をテキストボックスに入力してOKを押下すると
画面遷移し入力したテキストがh1タグで囲まれて表示される

![Pasted image 20250412100507.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754817/4345a965-3162-4431-9db4-0aaeecd861d2.png)

![Pasted image 20250412100513.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754817/c8e56090-403b-46cb-a5c7-790ff0dde116.png)

SSTIはServer Side Templete Injectionの略でテンプレート構文の脆弱性をついてコードをインジェクションする攻撃手法。


問題のWebサイトが一体どんなWebフレームワークを使っているのかがわかれば
対象に応じたコードをテキストボックスからインジェクションすることでフラグを取得できるはず。

開発者ツールからNetworkタブをみると
ResponseヘッダーのServerにPythonの文字があるのでおそらくテンプレートエンジンはJinja2あたりと検討をつける

![Pasted image 20250412101828.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754817/40872aea-5c8c-43f9-8edd-6b79db696b3f.png)


PythonフレームワークへのSSTI手法をググってみると下記のサイトが見つかった
https://behradtaher.dev/2021/12/02/SSTI-In-Python-Frameworks/#Abusing-Jinja2-to-call-built-in-Python-methods

Pythonの継承階層をたどって、"subprocess.Popen"までたどり着ければ
外部コマンド等を実行することでサーバの情報を取得することができるはず

![Pasted image 20250413183744.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754817/d5bb4947-2710-4588-aae6-0e513f25b8c0.png)

`"".__class__.__base__.__subclasses__()`
でstrのベースクラス（object）のサブクラスを取得するとPopenが見つかる


![Pasted image 20250413183854.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754817/33e6e79a-fffe-493b-b9f3-55d37c8126be.png)


`{{"".__class__.__base__.__subclasses__()[356](["ls"],stdout=-1).stdout.read()}}`

subprocess.Popenは357個目の要素なので配列のインデックスに356を指定してlsコマンドを発行する。
Popenの標準出力をとるためにstdout=-1（subprocess.PIPE）を指定してreadする。

![Pasted image 20250413185728.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754817/1a33c77f-e302-4cac-b122-bc5552f54457.png)

"flag"というファイルがみつかるので同様にcatコマンドでファイルの中身をみるとフラグが手に入る

----

下記のサイトにはテンプレートエンジンを判別するチャートが載っていた

https://portswigger.net/web-security/server-side-template-injection

また、Flaskアプリケーションの場合、requestなどのオブジェクトを経由することでビルトインオブジェクトにアクセスしosモジュールからpopenを実行する方法もあるらしい

https://kleiber.me/blog/2021/10/31/python-flask-jinja2-ssti-example/
devise_for, devise_scopeの使い方


Railsアプリにdeviseを導入すると、routes.rbにこのように書いたりする。

```ruby:routes.rb
  devise_for :users, controllers: {
    sessions: 'users/sessions',
    registrations: 'users/registrations',
  }

  devise_scope :user do
    get 'signup', to: 'users/registrations#new', as: :signup
    get 'login', to: 'users/sessions#new', as: :login
    delete 'logout', to: 'users/sessions#destroy', as: :logout
  end
```

`devise_for`と`devise_scope`とは？その使い分けは？ を整理した。


## `devise_for`, `devise_scope` = devise独自のルート定義メソッド

`devise_for`, `devise_scope` = ActionDispatch::Routing::Mapperクラスのメソッド。

Routing::Mapperクラスには、`Rails.application.routes.draw do ... end`ブロック内で使える、ルート定義を行うメソッドたちが含まれる。

`get`, `delete`, `resources`などのRails標準搭載のRouting::Mapperクラスのメソッドに追加して、devise独自のメソッドとして`devise_for`, `devise_scope` などが定義されている。

## `devise_for` と `devise_scope`の使い分け

:::note info
結論
`devise_for`で標準ルーティングを一括生成して、さらに必要なカスタムルーティングを`devise_scope`で生成する。
:::

### devise_for 詳細

`devise_for`:  deviseを使うモデル (`User`など) で定義したmodule (e.g. `registerable`, `validatable`) をもとに、deviseの標準的なルーティングを一括生成。モデル, パス, コントロール etc.の指定ができる。
(`devise_for`の内部では`devise_scope`を呼んでいる)

```rb
devise_for :resources

# example
devise_for :users do
	class_name: 'Account', # モデルの指定 User -> Account
	# --- or --- 
	path: 'accounts', # パスの指定 /users -> /accounts
	# --- or --- 
	controllers: { sessions: 'users/sessions' } # コントローラの指定 devise/sessions -> users/sessions
end
```

参考：[devise rubydoc > devise_for](https://www.rubydoc.info/github/plataformatec/devise/ActionDispatch%2FRouting%2FMapper:devise_for)


### devise_scope 詳細
`devise_scope`: 新たにdevise関連のルーティングを追加する時に使う。パスとcontroller#actionを対応付ける。
(`scope` = deviseを使っているモデルに対応した識別子)

```rb
devise_scope :scope do 
	get '/some/route', to: 'some_devise_controller#action', as: :some_path_name
end

# `as`がエイリアスメソッドなので下記のようにも書ける
as :user do
	get 'login', to: 'devise/sessions#new', as: :login
end
```

参考：[devise rubydoc > devise_for](https://www.rubydoc.info/github/plataformatec/devise/ActionDispatch%2FRouting%2FMapper:devise_scope)
個人的備忘録：Clipyの履歴項目（1〜10）をフォルダにまとめて表示する方法を整理してみました

## はじめに

ClipyはMac向けの高機能クリップボードマネージャーです。コピーした履歴をすばやく呼び出せる便利なツールですが、初期設定では最新の10件がインライン（直列）で表示され、11件目以降がフォルダに分類されるようになっています。

:::note info
**個人の備忘録程度の走り書きとなっておりますが、温かい目で見守っていただければ幸いです。**
:::

本記事では、**履歴1〜10の項目も含めてすべての履歴をフォルダにまとめて表示する方法**を紹介します。

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

実際にClipyを使っている中で、1〜10件目だけがインラインで表示されることに違和感がありました。

![Screenshot 2025-04-13 at 12.33.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/25d7201f-e609-45ba-8980-32be3edb6222.png)

**履歴をすべてフォルダで整理して表示したいというニーズから、この設定方法をまとめることにしました。**

## 設定手順

1. Clipyメニューの「Preferences（設定）」を開く
2. 上部タブから「Menu」を選択
3. 以下の項目を変更
   - **Number of items place inline:** `0`
   - **Number of items place inside a folder:** `10`（そのままでOK）

## 設定の意味
- 「Number of items place inline」を `0` にすることで、インライン表示（メニュー直下のリスト）を無効化できます。
- 「Number of items place inside a folder」が `10` の場合、フォルダごとに10件ずつ履歴が表示されます。

![Screenshot 2025-04-13 at 12.35.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/e7f7d20a-5539-47f2-b656-a421a0b39c29.png)

## 補足
設定変更後は、Clipyを一度終了して再起動することで、確実に反映されます。

## まとめ
履歴項目を整理して表示したい場合には、すべての履歴をフォルダ表示にまとめることで、視認性が向上し、より快適に利用できます。**Clipyの柔軟な設定を活用して、自分好みにカスタマイズしてみましょう！**
CastContext.getSharedInstance()についてのメモ

# はじめに
CastContext.getSharedInstance()について自分なりの解釈をメモとして残しておきます。
```
CastContext.getSharedInstance(context)
```
と
```
CastContext.getSharedInstance()
```
の違いはなんなのかと言う話です。

# 引数あり
```
CastContext.getSharedInstance(context)
```
>CastContext には、非同期初期化のために Context または Context と Executor のいずれかを使用して `getSharedInstance()` を使用して共有インスタンスとしてアクセスできます。

引数ありのものはCastを使用する前に呼び出す必要があり、呼び出すことで初期化されるといった感じです。


# 引数なし
```
CastContext.getSharedInstance()
```
は　引数ありのものを一度呼び出して初期化した後に使用でき、返却物としては引数ありと同じなので引数にしようするContextが取得できない時などにCastContextを定義したい時などに使用します。




# 参考

https://developers.google.com/android/reference/com/google/android/gms/cast/framework/CastContext#getSharedInstance(android.content.Context)
Cellpose 3.1.1.1のWindows 11へのインストール

# Cellpose インストール手順（経験談）

## 環境

- OS: Windows 11
- Anaconda prompt: インストール済み
- GPU: Quadro RTX 4000
- Cellpose: 未インストール

## 手順

以下は、私が実際に試した際に成功した方法です。

1. NVIDIAドライバを最新にする
   - [NVIDIA公式サイト](https://www.nvidia.com/en-us/drivers/)から最新のドライバをダウンロードしてインストールする。

2. Anacondaのbase環境から新しい環境を作成

   ```shell
   conda create --name cellpose python=3.11
   ```

3. 作成した環境にCellposeをインストール

   ```shell
   python -m pip install cellpose[gui]
   ```

4. torchをアンインストール

   ```shell
   pip uninstall torch
   ```

5. PyTorchのGPU対応バージョンをインストール
   - [PyTorch公式サイト](https://pytorch.org/)からCUDA 11.8対応のバージョンを選択。今回は以下のコマンドを実行。

   ```shell
   pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
   ```

6. Cellposeを起動する

   ```shell
   python -m cellpose
   ```

## 詰まったところと解決した内容

### 1. ドライバ更新前の問題（CUDA 11.0の場合）

ドライバが古い（CUDA 11.0）状態では、torchはGPUを認識するものの以下のエラーが発生した。

```python
try:
    device = torch.device("cuda:0")
    x = torch.zeros((1,1)).to(device)
    print("CUDA is working on device:", torch.cuda.get_device_name(0))
except Exception as e:
    print("Error using CUDA:", e)
```

**エラー内容：**

```
Error using CUDA: CUDA error: out of memory
```

→ ドライバを最新のものに更新することで解決。

### 2. Cellpose公式推奨インストール方法でGPU対応版が入らない

Cellposeの公式GitHubのReadmeにある以下の方法では、GPU対応版がインストールされなかった。

```shell
conda install pytorch pytorch-cuda=11.6 -c pytorch -c nvidia
```

→ PyTorchの公式サイトから直接対応するCUDAバージョンを選択してインストールすることで解決。

---

以上が私の環境での成功事例です。
開発環境構築

# 開発環境構築

Pleiades All in One (JDK, STS, Lombok 付属)
https://willbrains.jp/

7-zip
https://7-zip.opensource.jp/

A5M2
https://a5m2.mmatsubara.com/

WSL2 のインストール
Windows PowerShellにて以下コマンド
wsl --install

DockerDesktop(4.40.0)
https://docs.docker.com/desktop/setup/install/windows-install/
Dockerアカウント作成

## Spring実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4050450/a241b308-9918-471b-b53b-f8b97eee4b33.png)

## ブラウザにて実行確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4050450/efd0e4c0-0026-4570-8736-60c18a292182.png)

## ホームページを追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4050450/c704c91b-7a2c-49bd-8628-91a5f80f1353.png)
【React】学習記録アプリを作った話

## はじめに
日々の学習内容と学習時間を記録する学習記録アプリをReactで作成しました
（前提として、UdemyのReact講座を受講済み）

## 主な機能
1.登録ボタン押下→学習内容と学習時間を記録
2.学習内容と学習時間を一覧で表示
3.学習内容と学習時間が入力されていない状態で登録ボタン押下→エラー
4.記録した学習時間の累計表示

## 動き

![プレゼンテーション1 (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048214/1533a3b9-49f4-43e8-9312-58e55ea6b70b.gif)

## 気づき
・いざ作成となると、意外と手が動かない。ToDOアプリをかなり見返してやっと作成できた。
・アウトプットすることで、よくわかっていないところが分かった。例えばフォームに入力した値を表示させるところでは、onChange関数とeventについて理解が深まった。また累計表示ではそこでレンダリングの仕組みを改めて理解できた。

・今回は要件には含まれていなかったけど、CSSが難しい。（今後勉強）

# JISOUのメンバー募集中！
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
興味のある方は、ぜひホームページをのぞいてみてください！
▼▼▼

https://projisou.jp
Laravel11とFilamentでサブディレクトリにインストールした時に撃破された話

ロリポップサーバーにWEBアプリを作成する案件をGETした♪  
当初は、管理画面の指示が無かったので管理画面無しで開発は進めていた。  
たぶん必要だろうな・・・と思いつつも進めていたところ、  
納品チェックでやはりデータの編集・削除できるようにしてほしいと言われたｗ  
やっぱりねｗ

こんな事もあろうかと、Laravelで作成してたので管理画面は1時間もあれば出来るだろうと思い承諾。

※詳しいLaravelのインストールとFilamentのインストールは、私より詳しく書いている人がいるのでそれを参考にしてください。

## Filamentを導入してみる

早速、`composer`でFilamentをインストールして`panel`を`admin`に設定してユーザーを作成。  
ログイン画面も無事表示された。

メールアドレスとパスワードを入力して・・・と  
ん？ 何かおかしい。  
パスワードが通常はマスクされて表示されるところが、なぜかマスクされずに平文で表示されている！？

まさかね・・・と思いつつログインボタンを押してみると、  
**「The POST method is not supported for route admin/login. Supported methods: GET, HEAD.」**  
というエラーが発生！

AIにエラーコードをそのままぶち込んで聞いてみたら、`web.php`にrouteを書けと出てくるが、  
それを入れても全然違うエラーが勃発して絶望。


## 別環境で検証してみた

とりあえず、CohonaでLaravel環境を立ち上げて別環境で検証してみると……  
あれ？ 普通に動くしｗ

まさかと思い、検証環境でサブディレクトリにコピーして動作させてみると、  
見事、同じ現象が再現！


## 原因が判明！

そう、ロリポップサーバーにインストールした場所は、  
**`https://デフォルトドメイン/app/public`** だったのです。

今回は先方からドメインの提供が無く、デフォルトドメインで構築することになっていました。  
※ここまでで、他の案件も同時進行だったこともあり、なんと5日を要した……

## 解決方法

ここからは解決が早かったです。

`.env` に以下を追加：

```env
APP_SUBDIR=app/public
```

そして、`web.php` に以下を追加：

```php
// サブディレクトリにインストールした場合
// ルートの場合は消す
Livewire::setScriptRoute(function($handle) {
    return Route::get(env('APP_SUBDIR') . '/livewire/livewire.js', $handle);
});

Livewire::setUpdateRoute(function($handle) {
    return Route::get(env('APP_SUBDIR') . '/livewire/update', $handle);
});
```

上記を追加することで、サブディレクトリでもFilamentがエラーを起こさずに使えるようになります！


## 反省点

最近、AIに聞くことがデフォルトになっており、**自分で調べることを怠っていた**。  
実は、「The POST method is not supported for route admin/login. Supported methods: GET, HEAD.」で  
ググったら、一番下の方にちゃんと解決策が載っていたｗ

そして、ログインでパスワードがマスクされない時点でDeveloper Toolでエラーを確認していれば、  
`example.com/livewire/livewire.js` と表示されており、PATHがおかしいことに気づけたはず……。


## 最後に

Filament自体は素晴らしいライブラリで、慣れれば爆速で管理画面が作れます。  
ただ、ローカルと本番環境の差異には要注意。特に**サブディレクトリ環境**は罠が多いです。

同じような環境でハマっている方の助けになれば幸いです！

## 参考サイト
https://note.com/yamashita3910/n/n6cbf41a1fada
https://github.com/filamentphp/filament/discussions/11481