OmniAICreator/Qiita-1.07M huggingface dataset:
🔐 Laravelでログインが成功しない原因と解決方法（Sanctum使用時）

## 0.この記事の目的
LaravelでSanctumを使ってAPIログインを実装しているのに、ログインがうまくいかず `500 Internal Server Error` や `401 Unauthorized` が返ってきて困ったことはありませんか？
本記事では、実際に私がハマった原因とその解決方法を紹介します。

## 1.背景
バックエンド：Laravel
フロントエンド：React
インフラ：Docker / Mysql
上記構成でWebアプリを作成中、Laravel Sanctumを使用してAPIログインを確認していたところ、` ログイン処理のみ `エラーが発生。Postmanでリクエストを確認しながら解決まで至った手順をまとめました。
###### 該当コード抜粋

`api.php`
*ユーザ登録：正常
*ログイン処理：`エラー発生`
```
Route::prefix('/user')->group(function () {
    Route::post('/register', [AuthController::class, 'register']); //ユーザ登録処理
    Route::post('/login', [AuthController::class, 'login']); // ログイン処理
}
```
`controller`(ログイン処理)
```
    // ログイン処理
    public function login(LoginRequest $request)
    {
        $user = User::where('email', $request->email)->first();

        if (!$user || !Hash::check($request->password, $user->password)) {
            return response()->json(['message' => '認証失敗'], 401);
        }

        $token = $user->createToken('auth_token')->plainTextToken;

        return response()->json([
            'message' => 'ログイン成功',
            'token' => $token,
            'user' => [
                'id' => $user->id,
                'name' => $user->name,
                'email' => $user->email,
                'avatar_path' => $user->avatar_path,
            ],
        ]);
    }
```

## 2.エラー内容
###### /api/user/login に POST リクエストを送ると、以下のような現象が発生。
・レスポンス：`500 Internal Server Error`
・ログ：`Call to undefined method App\Models\User::createToken()`

## 3.結論
### Userモデルに HasApiTokens がないとログインできない！
・Laravel Sanctum を使ってトークン認証を行う際には、ログイン時に以下のようにトークンを発行します。
```
$token = $user->createToken('auth_token')->plainTextToken;
```
・この createToken() メソッドは、`HasApiTokens` というトレイトを使っている必要があります。

## 4.解決方法
User.php モデルに `HasApiTokens` を追加
```
※抜粋内容
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasFactory, Notifiable, SoftDeletes, HasApiTokens;

```
・これで createToken() が有効になり、トークンを発行できるようになります。

## 5.まとめ
###### Laravelでログインできない時は
・Userモデルに `HasApiTokens` があるか？
　*`createToken()` を使うにはこれが必要。
・パスワードがハッシュ化されているか？
　*プレーンな文字列のままだと Hash::check() が失敗する。
・ルーティングでSanctum関連のミドルウェアを使用しているか？
　＊Sanctumトークン認証を使用するには` auth:sanctum `を使う(1.背景 api.php 参照)
・エラーログは確認したか？
　*500エラーが出る場合、画面だけで原因が分からないためログファイルの以下のコマンドでログ確認が必要。
 ```
 ※対象のdockerコンテナ内で
tail -f storage/logs/laravel.log
 ```
【1ヶ月】AWS DVA-C02に合格した体験記

## 概要
約1ヶ月の勉強で、AWS DVA-C02に合格しました。
勉強法について振り返りたいと思います。
少しでも参考になれば幸いです。

## 筆者について
理系の大学院を修了し、現在社会人4年目です。
ユーザ企業のシステム部門にて、システム開発の企画やベンダーマネジメントをしています。
自身で開発をしたり、実務でAWSを使用する機会はあまりありません。
昨年、下記の通りSAA-C03, SOA-C02を取得しており、主要なサービスの概要は理解しているつもりです。 
表1. これまでのAWS試験結果
| 年月 | 試験名 | 結果 | 点数 | 
| ---- | ---- | ---- | ---- | 
| 2024年10月 | SAA-C03 | 合格 | 776|
| 2024年12月 | SOA-C02 | 合格 | 778|

## 学習期間
2025年3月中旬〜4月中旬(約1ヶ月)

## 使用した教材
CloudTech、BlackBelt

## 勉強方法
1. CloudTech DVA問題(約260問)を1周する (1~2週間目)
1日約20問ペースで解きました。
間違えた/勘で正解した問題は答えを覚えるのではなく、
間違えた理由や正解以外の選択肢が正しくない理由を理解しました。
この際、自分の解釈をChatGPTで壁打ちし、誤った理解をしていないか徹底的に確認しました。
※生成AIを使用される際は、ハルシネーションリスクにご注意ください。
この段階での正答率は、約50%でした。


2. BlackBeltでサービスの定義を理解する (1~2週間目)
1で弱点を把握し、理解しにくいサービス（個人的にはECSクラスター/サービス/タスクの定義や、X-Ray）について、BlackBeltの資料を参考にしました。
わかりやすく体系的にまとめられているため、サービスの定義を復習したいときにおすすめです。

3. CloudTech DVA問題を2~4周する (3~4週間目)
1で間違えた問題を中心に解きました。
以下のように、間違えた問題をスプレッドシートで管理しました。
CloudTechにもブックマーク機能はついているのですが、間違えた問題の番号や、間違えた回数を把握できた方が弱点克服しやすいため、おすすめです。
![スクリーンショット 2025-05-09 22.33.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452125/bbe2484c-83f3-4070-a417-c92e576dabc1.png)

## 試験本番
テストセンターにて、午前中に受験しました。
Cloudtechと類似した問題は約10問程度あり、全体の7割程度は自信を持って回答できました。

受験当日の20:16頃、合格メールを受信しました。

## 今後について
次はSCS-C02を受験してセキュリティの知識をつけつつ、ハンズオンを行うことで、AWS環境構築力を習得していきたいと考えています。
【初投稿】エンジニアを目指している大学生の自己紹介

## はじめに

こんにちは！
現在、大学2年生で**クラウドエンジニア**を目指して勉強を始めました。  
この記事では、自己紹介と現時点での今後の学習方針をまとめます。



## 👩‍🎓 自己紹介

- 学年：大学2年生（2025年5月時点）
- 目標：クラウドエンジニア
- 興味：AWS / Linux / セキュリティ / インフラ / Git 



## 🎯 今後の学習方針

以下の分野を重点的に学習していきます。

- **Linux基礎**
- **Git/GitHub**
- **基本情報技術者試験（FE）**
- **ネットワーク**
- **AWS（特にCloud Practitioner → SAA）**

学習記録やつまずき・メモなどをQiitaとX（旧Twitter）に定期的nアウトプット予定です。



## 🧠 Qiitaで発信していく予定の内容

- 学習記録
- LinuxやGitの基本コマンド
- AWSの学習ログ
- 試験対策メモ（基本情報技術者など）
- QiitaやGitHub、Xの活用記録



## 🔗 SNS・アカウント

- X（旧Twitter）: [@maimi_28](https://twitter.com/maimi_28)
- GitHub: [https://github.com/maimi-28](https://github.com/maimi-28)
- Qiita：[@maimi_28](https://qiita.com/maimi_28)



## 📝 最後に

初心者ですが、コツコツ継続してアウトプットしていく予定です！  
同じく学習中の方、現場で働くエンジニアの方、アドバイスなど大歓迎です。  

ご覧いただきありがとうございました。
【Windows11】Shift＋右クリックメニューをキャプチャしたい

職場環境の画面キャプチャは掲載できないため文字が多くなります。ご容赦ください。

## 困ったこと
アプリの操作マニュアルをつくりたいときなどに、フォルダの右クリックメニューの画像を添付したくてもWindows11ではキャプチャできなくなりました。

SnippingToolの仕様で「Windows＋Shift＋S」押しと同時に右クリックメニューが消えてしまいます。

それでも自宅PCなら「Shift＋右クリック」メニュー画像を「Windows＋Shift＋S」でキャプチャできます。
しかし会社PCでは「Shift＋右クリック」メニュー画像もキャプチャできないため、困りました。

## 解決方法
SnippingToolの「遅延切り取り」機能を使います。

①遅延時間を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3903408/9b2f8e88-14bc-4d3d-b91d-2ad56bf873fb.png)

②「新規」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3903408/00fa0000-b1d6-4ffd-8044-a18b5dde5642.png)

③遅延時間内にキャプチャしたいメニューを表示します。

④範囲指定するとキャプチャできます。
　「Shift＋右クリック」メニュー画像がキャプチャできない環境でも。キャプチャできます。
Java学習記録 #パッケージ

## 🔍 パッケージとは？
パッケージは、関連するクラスやインターフェースをまとめるための名前空間のようなものです。
パッケージを使うことで、クラス名の衝突を避けたり、コードを整理整頓して保守性を高めたりできます。

例: java.util は、ユーティリティクラス（例えば ArrayList や HashMap）をまとめたパッケージです。

例: 自分で作成したプロジェクトにおいても、com.example.project など、パッケージを使うことでコードを管理しやすくなります。

## ✅ パッケージの作成
Javaでパッケージを作成するには、ソースコードの先頭に package キーワードを使ってパッケージ名を指定します。

```java
package com.example.util;  // パッケージの指定

public class MyUtility {
    public static void printMessage(String message) {
        System.out.println(message);
    }
}
```
:::note info
パッケージ名は通常、小文字で書きます。
:::

### ファイルのディレクトリ構造
package com.example.util; を使った場合、そのクラスファイル（MyUtility.java）は com/example/util/ というディレクトリに配置するのが規約です。

## ✅ パッケージの使い方
クラスやメソッドを他のパッケージから利用する場合、import 文を使って指定する必要があります。

1\. **自作クラスをインポートする**
例えば、先ほど作成した MyUtility クラスを使いたい場合、他のクラスから以下のようにインポートします。

```java
import com.example.util.MyUtility;  // MyUtilityクラスをインポート

public class Main {
    public static void main(String[] args) {
        MyUtility.printMessage("Hello, World!");  // メッセージを表示
    }
}
```

import 文によって、指定したパッケージ内のクラスを簡単に使えるようになります。

2\. **import の省略とワイルドカード**
もし同じパッケージ内の複数のクラスを使いたい場合、*（ワイルドカード）を使って一括でインポートすることができます。

```java
import com.example.util.*;  // utilパッケージ内の全クラスをインポート
```
ただし、無駄なインポートは避け、必要なクラスだけをインポートすることが推奨されます。

## ✅ Java標準ライブラリのパッケージ
Javaには多くの標準パッケージが存在し、これらを利用することでさまざまな機能を簡単に活用できます。

### java.lang
ほとんどのクラスはこのパッケージに含まれており、自動的にインポートされます（例: String, Math, System など）。

### java.util
ユーティリティクラス（例: ArrayList, HashMap, Date など）をまとめたパッケージ。

### java.io
入出力に関連するクラス（例: File, BufferedReader, PrintWriter など）。

### java.net
ネットワークに関連するクラス（例: Socket, URL など）。

これらのパッケージをインポートすることで、外部ライブラリを手軽に使うことができます。



## ✅ パッケージの利点
- 名前の衝突を避ける
異なるパッケージに同じクラス名を持つクラスを配置できるので、名前の衝突を避けることができます。

```java
// パッケージcom.example.util
package com.example.util;
public class MyClass { /* ... */ }

// パッケージcom.example.db
package com.example.db;
public class MyClass { /* ... */ }
```
- コードの整理
プロジェクトが大規模になった場合でも、関連するクラスをパッケージ単位で整理することができ、メンテナンス性が向上します。

- アクセス制御の向上
Javaでは、アクセス修飾子（public、protected、private、default）を使って、パッケージ内外のアクセス権限を制御できます。

## ⚠️ パッケージに関する注意点
- パッケージ名の重複
同じパッケージ名を複数の場所で使うと、コンパイル時にエラーが発生します。パッケージ名は一意にすることが重要です。

- パッケージを変更した場合
すでに利用されているクラスのパッケージを変更する場合、import 文を更新する必要があります。

- default パッケージの使用は避ける
default パッケージ（パッケージ名を指定しないクラス）は、プロジェクトが大きくなると管理が難しくなるため、使用しない方が良いです。

## 💡 まとめ
- パッケージはクラスやインターフェースを整理するための仕組みで、名前の衝突を避けるために使います。

- package キーワードでパッケージを指定し、import で他のパッケージからクラスを使います。

- Java標準ライブラリにも多くのパッケージがあり、それらを活用することで効率的に開発ができます。

パッケージ名は一意であることを意識し、規則的に整理しましょう。
Apacheではまったところ

## 概要
Amazon Linux2023移行に伴い、ドキュメントルートを変更することになりました。
その際の設定でハマった部分があるので、記録に残ります。

## 内容
旧サーバーのドキュメントルートをA
新サーバーのドキュメントルートをB

として記載していきます。

新サーバーににてAを設定し、アクセスしたところ正常に閲覧ができておりました。
その後、バーチャルホストの設定を行う事になり旧サーバーのバーチャルホストを設定通りにドキュメントルートを設定しました。

現状
・新サーバーのメインドキュメントルートはB
・バーチャルホストの設定はA

この状態で、サーバーIP+ファイルパスでアクセスしたところ404が表示されました。
ドキュメントルートの設定は行っていないのになぜということで調査をしました。

結果
バーチャルホストを設定した場合、メインドキュメントルートではなく一番最初のバーチャルホストに設定されているドキュメントルートを参照することがわかりました。
参考：https://httpd.apache.org/docs/2.2/ja/vhosts/examples.html

## まとめ
メインドキュメントルートを変えてないはずなのに、と首をかしげていたのですがまさかのバーチャルホスト設定で影響がでるとは思いませんでした。

linuxというかApacheは奥深いですね。
【特許出願中】HTML の view-sourceをロギングする方法、スクショの予兆を取る方法

2025年4月22日に特許出願したの（審査はまだ）

ChatGPTに聞いたら、特許出願したっばっかのでも公開して大丈夫ってことなのでその簡単な仕様を書いておくの

# view-sourceのロギング
## その１
- アクセスがあったよ！っていう通知を一時データベースに保存する
- JavaScriptでCookieを発行する、UNIXTIME÷60をした整数の時間でcookieを発行する、このcookieは9秒間のみ有効
- base64にエンコードした同じURLを発行し（直クリック防止）、それをatobでデコードしてURL転送する
- 9秒以内に上記cookieに認証したら、一時データベースから削除
- 9秒以内にアクセスがなければ、一時データベースからログデータベースに移動
## その２
- アクセスがあったよ！っていう通知を一時データベースに保存する
- footerとかすぐにHTMLを確認できない位置に1x1 gifをスクリプトから発行する
- 9秒以内に上記画像にアクセスがあれば、一時データベースから削除
- 9秒以内にアクセスがなければ、一時データベースからログデータベースに移動

## 特徴
- Webサーバーに何も特別な設定をせず、CMSのプラグインとして動作させることができる
- curlなどのbotもUA変更されても検知される（しかし403にはならない）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149448/fa44234e-af5b-4389-84a8-f9c341c7ab0a.png)

なんか変じゃないですか？いずれもbotとして認識しています

## ちょっぴり難点
- Geckoエンジンのブラウザではこの対処が効かない
- botもview-sourceしたって通知が来てしまう
- 素のHTMLだけだとこの検出ができない CMSとかでスクリプトベースになってないとダメ

## なぜ9秒？
- インターネットがある程度遅い環境に対応する
- JavaScriptでもコードが書かれるので10秒より9秒のほうのが1文字節約できる

## これ特許その１
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149448/bdb8d4b8-1563-4a9e-9cfb-e2d05ee59dd6.png)

はったりではなく、view-source がロギングされているのです
アスキーアートで警告したりしてるのとかは、特許範囲外

## これ特許その２
トラッキングコードはfooterの頭にあります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149448/62ead3c8-968e-4fce-9885-092ef4f2a5ab.png)


ここがトラッキングコード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149448/307d2023-e952-4f8a-ab41-bc40f16e5367.png)

# スクショの予兆をロギングする
- PrintScreenは無理かも、Linuxだと動くかも
- Ctrl+Shift+S Command+Option+3とかはイベント駆動できない
- しかし、Ctrl+Shift、Command+Option とかの中途半端な事前キーを押したことでロギングできる

## 特徴
- JavaScript+ajaxを受け取るスクリプトだけで実装可

## ちょっぴり難点
- アンケート調査によって1%の誤操作がある可能性がある
- 当然のことだが、専用のスクショツールには非対応

## これが特許出願中
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149448/85ffc77e-d811-4a47-b5ae-484208ea3a95.png)

## これは特許ではない
PrintScreenが普通に検出されました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149448/90587fe8-2c61-440e-81e1-055a0ad306ab.png)

:::note
これらのCSSもChatGPTに出力させています
:::
# 試作品コード

https://github.com/nanakochi123456/Neo-HTML-Protector-for-Wordpress

:::note
試作品の割にはChatGPTが99%ぐらい書いたWordpressプラグインです
ただ人間によるチェックは行われており、特にJavaScriptの最適化は人間が行ってます
:::

## デモサイト

https://demo1.773.moe/

https://demo2.773.moe/

https://demo3.773.moe/

デモサイトではCtrl+Uしてソース表示できるようにしてあるの

:::note alert
demo1サイトのみ公開しているIPログリーダがあります
view-sourceとかCtrl+SとかCtrl+PとかF12とか右クリックとかスマホでロングタップとかするとあなたのIPアドレスが全世界に？公開されます
具体的なキーについては、上記にある試作品コードにある src/js/neo-html-protector.js を確認して下さい
テストしたいがばれたくない場合は有償・無償のVPNを経由してアクセスしてください
:::

:::note
Ctrl+S とか押すと怖い画面とBGMがなるかもしれないのは仕様
:::

それぞれ少し違うので、試してみるといいわね

## おまけ
https://qiita.com/nanakochi123456/items/17f68576983034c8f05d

特許出願の翌日、勢いでこの記事をAIに書かせたってのがありました

# ここまで書いてるのは一部です
個人にとっては非常に高額な価格ですが、特許ライセンスを下記で販売中です

https://coconala.com/services/3724976
windowsでiverilog その159

# 概要　
windowsでiverilogやってみた。
cpu見つけたので、勝手にマシン語、作ってみた。

# 参考にしたページ

https://qiita.com/KajizukaTaichi/items/2da92161db1355466b5c

# cpu仕様
名前 : Ruka
レジスタマシン
64bit CPU（レジスタが全部　64bit）富豪仕様
ROMメモリーは、32語72bit
マシン語は72bit固定長
命令は、転送、足す、引く、代入、比較、メモリ操作、スタック操作、ジャンプなどの１７種類
命令に８bit、64bitを値に
値は、倍精度浮動小数点
７２:６８	６７:６５　６４：０
命令	レジスタ　値
レジスタは5コ、とプログラムカウンタ、デバッグ用に1個追加。
RAMメモリ領域 :	32バイト
スタック領域	: 関数などとのデータ受け渡し用 32バイト
関数スタック	: 呼び出し元アドレスが積まれる 32バイト
入力、出力は無し。
HLTで、プログラムカウンタが停止。

## ニーモニックとマシン語

|5bit |3bit |ニーモニック	|意味|
|:-|:-|:-|:-|
|01|レジスタ|MOV レジスタ, 値	|データ転送
|02|レジスタ|ADD レジスタ, 値	|足し算
|03|レジスタ|MUL レジスタ, 値	|掛け算
|04|レジスタ|NEG レジスタ	|符号反転
|05|レジスタ|INV レジスタ	|逆数
|06|レジスタ|EQL レジスタ, 値	|等価比較
|07|レジスタ|LES レジスタ, 値	|大小比較
|08|レジスタ|NOR レジスタ, レジスタ	|論理ORして否定
|09|レジスタ|MOV レジスタ, レジスタ	|データ転送
|10|w|JMP 条件, アドレス	|条件つきジャンプ
|11|0|CAL アドレス	|関数呼び出し
|12|0|RET	|呼び出し元に戻る
|13|x|LDA レジスタ, アドレス	|データ読み込み
|14|x|STA アドレス, レジスタ	|データ書き込み
|15|x|PSH レジスタ	|スタックに追加
|16|x|POP レジスタ	|スタックから取り出し
|17|x|PSH 値	|スタックに追加
|00|0|NOP	|何もしない
|1f|0|HLT	|プログラム終了


## レジスタ
|3bit|名前	|意味	|役割|
|:-|:-|:-|:-|
|0|PC	|Program Counter	|次の命令のアドレス
|1|AR	|Accumulator Register	|演算結果の格納
|2|DR	|Data Register	|データの格納
|3|CR	|Conditional Register	|条件の格納
|4|BA	|Base Address	|メモリの基底アドレス
|5|SP	|Stack Pointer	|スタックに長さ

## 条件
１－常に
３－CR

以上。
DockerなしでGitHub MCPを環境構築する【Cursor】

# やること

- Dockerが使えないという~~かわいそうな~~Windows環境でGitHub MCPを使う

# （前提）GitHub MCPとは

https://github.com/github/github-mcp-server

GitHub MCP（MCP Server）とは、GitHubが公式に提供しているMCPサーバーです。

たとえば、以下のような機能が利用できます。

- プルリクエストやイシューの作成・更新・マージ
- ファイルの取得・更新・コミット
- ブランチやタグの管理
- ユーザーやリポジトリの検索

MCP Server自体はGo言語で実装されており、MITライセンスで公開されています。

# Dockerなしでなんとかする

https://github.com/github/github-mcp-server?tab=readme-ov-file#build-from-source

公式にもやり方が載っていますが、ここは1つずつ丁寧にやってみましょうか。特に、筆者はGoを触ったことが無かったのでそもそも`go build`しようがなく、Goの環境構築からやりました。

## 1. Goの環境を作る

Windowsなら[Scoop](https://scoop.sh/)というパッケージ管理ツールを使うとできるだけ環境を汚さずにGoを入れられます。（ほかの言語もすぐに入れられちゃうので愛用してます。）

```powershell
scoop install go
```

Macならみんな大好き[HomeBrew](https://brew.sh/)というパッケージ管理ツールを使えばすぐ入れられますね。

```bash
brew install go
```

パッケージ管理ツールも入れられない系PCであれば仕方がないので、以下の公式サイトからインストールしましょう。

https://go.dev/doc/install

インストール後、Goが入っているかを確認するなら`go version`などしてみるといいと思います。

## 2. GitHub MCPのビルド

https://github.com/github/github-mcp-server

あ、**そのパソコン、gitは入れられますよね？さすがに。**

`git clone`して、GitHub MCPのレポジトリをローカルに持ってきます。

cloneできたら、`cd github-mcp-server`して、以下のコマンドをうってください。

```powershell
# 依存関係の整理
go mod tidy

# ビルド
go build -o cmd/github-mcp-server/github-mcp-server.exe cmd/github-mcp-server

# 動作確認
cmd/github-mcp-server/github-mcp-server.exe --help
```

ここまでエラーなしで来られたらOKです。これで生成された`github-mcp-server.exe`については絶対パスを控えておきましょう。

## 3. GitHub PATの作成

GitHubにアクセスし、

- 右上アイコンから[**Setting**]を開く
- 左サイドメニューから[**Developer settings**]を開く
- [**Personal access tokens**]から[**Tokens(classic)**]を選択
- [**Generate new token**]より、[**Generate new token(classic)**]を選択

deleteとか暴走すると困るものはチェックを外しつつ、「GitHub MCP Token」とかそんな名前でトークンを作って、PATを生成したらそれを控えておきます（この後の手順で使うので必ず控えてくださいね）。

## 4. Cursorの設定を変える

Cursorを開き、[**ファイル**]→[**ユーザ設定**]→[**Cursor Settings**]でMCPの設定を変えられます。

```json
{
  "mcpServers": {
    "github": {
      "command": "<##2で控えたgithub-mcp-server.exeの絶対パス>",
      "args": [
        "stdio"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "<##3で控えたPAT>"
      }
    }
  }
}
```

# できた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518330/6252ca35-8c3f-47d8-9026-da3406e88a20.png)

# まとめ

Dockerを使っている人はいいよね。
いやちがうな、Dockerを使えるPCを持っている人はいいよね。（プライベート・仕事問わず）

それはともかく、今度はPRの作成をやってみます。
MacのRでRcmdrを使う方法&R日本語化 2025/05

# はじめに
大学の講義内でRcmdrを使う機会があり、せっかくなのでMacでRcmdrを使う方法と日本語化までまとめてみました。
当方の実行環境は以下の通りです。
・Apple M1 
・OS ver.15.3.2
・R ver.4.5.0
・XQuartz ver.2.8.0 

# Rcmdrのインストール前に
Mac上でRcmdrを動かすためには、「XQuartz」というソフトウェアが必要になります。
MacでRcmdrを動かす上で、Xquartzはバージョンが2.8.0でないとうまく動かせないようなので注意をして下さい。以下のリンクからインストールできます。

https://www.xquartz.org/releases/XQuartz-2.8.0.html

# Rcmdrのインストール
```
install.packages("Rcmdr")
```
まずはRのコンソール上に上記のコードを実行してRcmdrのパッケージを入れましょう。
大体10秒程度でインストールが終わります。(環境差あり)

# Rの日本語化
```
system("defaults write org.R-project.R force.LANG ja_JP.UTF-8")
```
上記のコードをRのコンソール上で実行し、Rを再起動することで、Rを日本語化することが可能になります。
元の英語に戻したい場合には
```
system("defaults write org.R-project.R force.LANG en_US.UTF-8")
```
と実行してあげれば戻ります。

# Rcmdrの実行
```
library("Rcmdr")
```
これでRcmdrが立ち上がるはずです。
![Rcmdrの画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3797408/aa5a95f1-6dc6-454b-a6d5-623871c1b542.png)

# 参考文献
https://www.jichi.ac.jp/saitama-sct/SaitamaHP.files/statmedFAQ.html
"成長"と"幸せ"と"価値"──2冊の本から見えたチームの在り方

## はじめに

本記事は、日々チームを率いているエンジニアやリーダー、あるいはこれからマネジメントや組織運営に関わろうとしている方に向けてお勧めしたい2冊をご紹介します。
特に、「早く成長しなきゃ」「成果を上げないと」という焦燥感に苛まれ、辛い今を生きている方やそうした人達をマネジメントしている方には、この2冊から得られる示唆は多いのではないかと思います。

---

## 読んだきっかけと目的

今回紹介する2冊はいずれもKindle Unlimitedで読み、その後に紙の書籍として購入したほど強く印象に残ったものです。  
一見すると自己啓発書に見えますが、実際にはチームマネジメントやリーダーシップに直結する内容が多く、自分自身の仕事の仕方を大きく見直すきっかけになりました。  
個人の振り返りだけでなく、チームや組織としての在り方にも活かせると感じたために記事にしたためました。

---

## 『パッション・パラドックス』を読んで見えてきた「情熱」のリスクと光

#### 情熱の負の側面を見つめ直す

私はこれまで「情熱さえあれば頑張れる」、「その対象を早く見つけなければ」と信じてきました。  
しかしこの本は、情熱にも負の側面があることを突きつけてきます。  
この本とは別なところで、私の師匠に「モチベーションはもともと工場の生産性を高めるために使っていたにすぎない」という言葉を思い出し、私はその“善”とされてきた情熱を他者に押し付けていなかったか、自問することになりました。

#### 炎ではなく灯火としての情熱

歴史を振り返っても、情熱に飲まれて破滅した人は数多く存在します。  
「完璧」「好成績」といった瞬間的な報酬に引き寄せられ過ぎると、ヒトはその急激なドーパミンの誘惑にかられ不正や過剰な恐れを生みやすくなります。
だからこそ、情熱は自分を焦がす炎ではなく、未来を照らす灯火であってほしい。
そのためには過集中を避け、俯瞰した自己認識を持つことが重要であると説かれていました。

#### アクセルとブレーキの両立

情熱とバランスは相反するトレードオフの関係性があります。
多くの自己啓発本では情熱を煽るか、バランスこそが大切だ…と両極端な論調が多い印象です。
しかしこの本ではどちらにも言及しており、「今だ」と思った時にはバランスの天秤を傾け情熱に向かってひた走ること。そのために日ごろはバランスを整えておく準備が必要だという視点は焦燥感を持っていた私には非常に刺さる内容でした。

---

## 『世界一流エンジニアの思考法』が示す「理解」に基づく生産性と文化

#### 理解に立脚した思考法

この本は、「生産性を上げるためのノウハウ集」ではなく、「組織にとっての思考の質」を深く掘り下げた一冊でした。  
表面的な効率化ではなく、まず“理解”に時間をかけ、仮説を立てたうえで検証に進む。  
個人の成果ではなく、組織的に再現可能なナレッジの蓄積へとつなげる思考法が描かれています。

#### 初歩の徹底と聞く力

「初歩の学習を応用できるレベルにまで引き上げること」や、「エキスパートに早く積極的に聞くことは必須であり最短ルートである」といった考え方の最たるものとして、「試行錯誤は悪である」とまで言い切っていました。
こうした姿勢が長期的に生産性を高めていくことに繋がるのであろうと実感しました。

#### やらないことを決める力

「いかにやることを減らすか？」に頭を使う。マルチタスクを避け、最も重要なことだけに集中する。  
そのための判断軸として、「リスクや間違いを早く受け入れて学ぶ」Fail Fastの文化や、「他人の意見を違う視点から自分の理解を助けてもらうためのものとして受け入れる」相互理解のためのコミュニケーションが、組織全体のスキル底上げを支える鍵になると感じました。

#### 成果よりも共有される価値

定例会議で「スケジュールの計画状況」ではなく「やってみて実際どうだったか？改善ポイントやベストプラクティスは？」を問うというエピソードには自分自身の振り返りや1on1でも聞いていきたいと思いました。

#### 一人一人が責任を持って仕事をする
チームをコントロールするのではなく「自己組織チーム」として、目指すゴールを共有した後その道程は各チームに任せるという「サーバントリーダーシップ」が非常に印象的でした。
更に、インターンでも学生でも「できるもの」として大人扱いすることで周囲の助けを得ながら進んでいくという「育てる」のではなく「育つ」環境を作るマネージメントはまさに私の理想です。

---

## まとめ ～目指すは幸せに成長しながら価値を創出するチームビルディング～

"成長するためにプライベートを犠牲にしないと…"、"幸せのために出世を諦める…"、"お客様の価値提供のために一同身を粉にして…"
仕方ない。そういうものだ。そんな弱音がぶっ飛ばされた(少々乱暴なのはご容赦ください)。そんな気持ちになりました。自己啓発というよりも、チームや組織をより良くするための“灯火”を見たような感覚があります。

どちらの本も、単に「個人が強くなるため」ではなく、「組織と個人との関係性でいかに**大きな**価値を生むか」を問うものだと感じました。
記載の内容は理想論かもしれません。全てやり切ることは難しいかもしれない。でも、**目指すことはできる。**

2つの書籍を読み、本記事の題名にもある"成長"と"幸せ"と"価値"これらはトレードオフではなく両立できるものであると信じることができました。
そんな組織を、私は育てていきたい。
…もっとも、私自身まだまだ未熟で出来ることなんて少ないですし、ここに記載の内容もほとんど自戒を込めているようなものです。この記事が、同じように悩んでいる誰かの背中を、そっと支えられるヒントになれば幸いです。

### 補足-紹介した2冊-
[パッション・パラドックス eBook : ブラッド・スタルバーグ, スティーブ・マグネス, 池村千秋: 本](https://www.amazon.co.jp/dp/B08D5ZVZ48)

[世界一流エンジニアの思考法 (文春e-book) 電子書籍: 牛尾 剛: Kindleストア](https://www.amazon.co.jp/dp/B0CKSZV5DQ)
レコード型のパターンマッチングはwhileでも利用できる

最近ふと思ったのですが、知ってみると当たり前のことでも、実際に気づくと感動することがあります。今回は、Javaのパターンマッチングについて、改めて「なるほど」と思ったことを共有します。

Javaにおけるパターンマッチングは、JDK 14で初めてプレビュー機能として導入されて以来、段階的に拡張されてきました。そして、JDK 21ではついにレコード型に対するパターンマッチングもサポートされています。

レコード型のパターンマッチングの例として、`if` 文と組み合わせたコードはよく見かけます。

```java
if (obj instanceof Point(int x, int y)) {
  // Do Something
}
```

ここで見落としがちなポイントとして、`instanceof` が使える場所であればどこでもパターンマッチが使えるという点があります。つまり、`if` だけでなく、`while` などのループ文でも利用可能です。


たとえば、レコード型のオブジェクトが格納されたキューから、すべての要素を取り出して処理するコードを考えてみましょう。

従来の（JDK 21以前の）書き方：

```java
Deque<Point> queue = ...;
while (!queue.isEmpty()) {
  Point point = queue.pollFirst();
  int x = point.x();
  int y = point.y();
  // Do Something
}
```

これをパターンマッチングを用いて書き直すと、次のようにより簡潔になります：

```java
Deque<Point> queue = ...;
while (queue.pollFirst() instanceof Point(int x, int y)) {
  // Do Something
}
```

**参考**

- [公式JEP 440](https://openjdk.org/jeps/440)

**環境**

- javac 21.0.6
- openjdk 21.0.6 2025-01-21 LTS
新卒が「テスタブルなコード」について本気出して考えてみた

## はじめに

こんにちは！
新卒2年目（そろそろ言い訳できなくなってくる時期）のエンジニアです。
<br>
コードレビューでいろんなご指摘を頂くのですが、
その中でも特に指摘されたのが、、

**• 「DIに従って」**

**• 「これだと単体テスト書けないよ！」**

でした。
いわゆるテスタブルなコードにしようって話ですね。

**DI…？？単体テスト…？？？**
っていう混乱状態から始まった自分が、ちょっとだけわかるようになってきたのでまとめてみました。
お手柔らかに....:sweat:


## テスタブルなコードってなんだ？

**テストが書きやすいコード！**　です。

なるほど....（？？？？）

自分は調べてこうなりました(笑)

実際の例を見てみましょうー！


#### テストしにくいコード（やりがち）

```php
class UserService {
    public function register(string $email) {
        $user_dao = new UserDao(); // ← ここでnewしてる
        $user_dao->save($email);
    }
}
```

学生の時はひたすらこれでした笑
一見だいじょぶそう。でも問題が！！

1. 依存
→UserServiceがUserDaoの実装に依存してしまっているので、単体テストができない
2. DB接続してしまう
→実際にDB接続してしまうため、単体テストができない

ノットテスタブルですね。

<br>
じゃあ、テスタブルなコードにするには？

キーワードは  **DI（Dependency Injection）** です。

なんか必殺技みたいで強そう（）

簡単に説明すると、
**「newは外でやって、それを渡す」**
それだけ！それだけ！

DIを考慮して書き直してみると、、
```php5
class UserService {
    private $user_dao;
    
    public function __construct(UserDao $user_dao) {
        $this->user_dao = $user_dao;
    }

    public function register(string $email) {
        $this->user_dao->save($email);
    }
}
```

これでテスタブルなコード、単体テストが書けるようになりました！！！！

(.......)
なんでこれだと単体テストが書けるようになるんだ？？
当時の自分はここでもピンと来ませんでした。

<br>
もう少し詳しく話します。

上記のようなコードにすることで、UserService は UserDao を直接インスタンス化する必要がなくなり、代わりに UserDao 型のもの（**モック**）を外部から渡すことができるようになりました！
なので単体テストが書けるように！！

いや待て、**モック**ってなんだよ...

簡単に言うと、
単体テストで使う、**指定したクラスを抽象化した偽物**のこと！

実際にモックを使って単体テストを書いてみると...
```php5
    //Mockery使用
    // モックを作成
    $mock_user_dao = Mockery::mock('UserDao');
    // 期待する呼び出し内容を指定
    $mock_user_dao->shouldReceive('save')
        ->once()
        ->with('test@example.com');
    // テスト対象のサービスを生成
    $service = new UserService($mock_user_dao);
    // メソッドを実行
    $service->register('test@example.com');
```
処理の説明は割愛しますが、
上記のようにUserDaoの偽物を実際に単体テストをしたいUserServiceに渡してあげることで、他に依存しない、UserServiceだけの単体テストができるというわけです。


#### 単体テストをするメリット
1.コードを個別にテストすることで、バグの早期発見ができる！
2.リファクタリングした際、既存の処理が壊れていないことを担保できる！
3.手動テストでの確認漏れを防げる！

すごい、これがテスタブルってやつか...

## まとめ

「テスタブルなコード」って、最初はふわっとしててよく分からない言葉でしたが、
実はとてもシンプルでした！

• newは外でやって渡す（＝DI）
• モックを使えば、依存先を偽物に置き換えてテストできる
→ だから単体テストが書ける！

単体テストが書けるコードにすると、
バグを早く見つけられるし、リファクタも安心してできるし、何より怖くなくなる！
これが少しずつ実感できてきたなと思います。

コードレビューの指摘も少しずつ減ってきた……気がします！
これからもがんばります！
iPhoneでパララックスが崩れる？背景画像拡大問題を解決する方法まとめ

今回は、パララックス効果を実装した際に、PCは問題ないのにiPhoneで見ると何故か背景画像が拡大されて崩れる？問題 に遭遇したので、その原因と今回私が対応した解決方法を記載します。

同じことで悩んでいる方の参考になれば嬉しいです！

## 問題の概要
Webサイトでパララックス効果を作るとき、以下のように CSS を書くことが多いと思います。

```ruby:scss

.parallax_content {
    background-image: url(../img/main_img.jpg);
    background-attachment: fixed;
    background-position: center;
    background-size: cover;
    background-repeat: no-repeat;
}
```
PCでは問題なく動作し、デバックモードでスマホサイズを確認しても問題ないのに、iPhoneの実機で見ると背景がズーム（拡大）されてしまうことがあります。

### iOSで起こる原因
iOS Safari では現状 background-attachment: fixed が仕様上サポートされておらず、
その代わりに背景が勝手にズームされる表示になってしまいます。

これはiOS側の仕様なので、CSSの指定を調整しても直りません。

## 解決方法
スマホでは次の方法で対応します。

1. スマホ用のメディアクエリを切り分ける

1. background-attachment: fixed を外す

1. 擬似要素 ::before を使って背景画像を表示する

擬似要素を使うことで、スマホでもパララックス風の表現が可能になります。

### 実装の流れ
**PC向けのパララックス設定（通常）**
```ruby:scss

.parallax_content {
    background-image: url(../img/main_img.jpg);
    background-attachment: fixed;
    background-position: center;
    background-size: cover;
    background-repeat: no-repeat;
}
```
**スマホ向けの対応**
以下は、SCSSのメディアクエリ例（mq(sm) は @media (max-width: 768px) などに置き換えてください）。

```ruby:scss

@include mq(sm) {
    .parallax_content {
        position: relative; // 擬似要素の基準を作る
        background-image: none; // 元の背景画像を消す
        background-attachment: scroll; // fixedを無効化する
    }

    .parallax_content::before {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-image: url(../img/sp_main_img.jpg);
        background-position: center;
        background-size: cover;
        background-repeat: no-repeat;
        z-index: -1; // 背景を後ろに配置
    }
}
```
## ポイント
✅ 擬似要素の ::before を活用することで、
iOSでも背景画像をパララックス風に見せることができる。

✅ .parallax_content に position: relative を忘れずに。
擬似要素は親要素を基準に配置されます。

✅ メディアクエリは環境に合わせて調整。
例：@media (max-width: 768px) や mq(sm) など。

## まとめ
iOSでは background-attachment: fixed が使えない仕様なので、
スマホ用には擬似要素を活用した別のアプローチを取ることが重要です。

今回紹介した方法を使えば、
PCとスマホそれぞれに最適なパララックス表現を作ることができると思います。
JavaでSQLiteデータベースの内容をExcelにエクスポートする方法

業務システムでは、データのエクスポート機能がよく求められます。Excelファイルとして出力することで、報告書の作成やデータの共有が容易になります。

この記事では、**Javaを使ってSQLiteのデータをExcelファイルに書き出す方法**を解説します。

### 使用技術

* SQLite：データ取得元となる軽量データベース
* JDBC：SQLクエリを実行しデータを取得するためのAPI
* [Free Spire.XLS for Java](https://jp.e-iceblue.com/introduce/free-spire-xls-for-java.html)：Excelファイルの作成と保存に使用

### 処理の手順

1. JDBCでSQLiteデータベースに接続し、テーブルを取得
2. 各テーブルの全データをSQLで取得
3. Excelワークブックを作成し、カラム名とデータをシートに書き込み
4. 最終的にExcelファイルとして保存

### Javaコード例：SQLite → Excel

```java
import com.spire.xls.*;
import java.sql.*;

public class SQLiteToExcel {
    public static void main(String[] args) {
        String dbPath = "jdbc:sqlite:BusinessData.db";
        String outputExcel = "output/exported_data.xlsx";

        // Excel ワークブックを作成し、デフォルトのワークシートを削除する
        Workbook workbook = new Workbook();
        workbook.getWorksheets().clear();

        try (Connection conn = DriverManager.getConnection(dbPath)) {
            DatabaseMetaData meta = conn.getMetaData();
            ResultSet tables = meta.getTables(null, null, "%", new String[]{"TABLE"});

            while (tables.next()) {
                String tableName = tables.getString("TABLE_NAME");
                Worksheet sheet = workbook.getWorksheets().add(tableName);

                // テーブル全体をクエリで取得
                String query = "SELECT * FROM `" + tableName + "`";
                try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(query)) {
                    ResultSetMetaData rsmd = rs.getMetaData();
                    int columnCount = rsmd.getColumnCount();

                    // 列名（ヘッダー）を書き込む
                    for (int i = 1; i <= columnCount; i++) {
                        sheet.getCellRange(1, i).setText(rsmd.getColumnName(i));
                    }

                    // データを書き込む
                    int rowIndex = 2;
                    while (rs.next()) {
                        for (int i = 1; i <= columnCount; i++) {
                            String value = rs.getString(i);
                            sheet.getCellRange(rowIndex, i).setText(value != null ? value : "");
                        }
                        rowIndex++;
                    }
                }
            }

            // デフォルトの空ワークシートを削除（未使用の場合）
            if (workbook.getWorksheets().get(0).getName().equalsIgnoreCase("Sheet1") &&
                    workbook.getWorksheets().getCount() > 1) {
                workbook.getWorksheets().removeAt(0);
            }

            // Excel ファイルを保存
            workbook.saveToFile(outputExcel, ExcelVersion.Version2016);
            System.out.println("Success!");

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}
```

**データベースの例**
![JavaでSQLiteからExcelにデータをエクスポートする例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/c56261a5-7bb0-4d9b-9542-9dd36ac5ca3e.png)

**出力された Excel ファイル**
![JavaでSQLiteからExcelにデータをエクスポートした結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/5fd24475-d2c8-444a-9647-ccf74c8697b5.png)


### まとめ

本記事では、SQLiteのデータをJavaでExcelファイルにエクスポートする方法を紹介しました。報告書の作成、データのバックアップや分析用途で非常に有用です。
五月雨のユーザ定義関数（WHERE文のリテラルを変数置換）

```
Function ReplaceWhereLiterals(sqlText As String) As String
    Dim reg As Object
    Set reg = CreateObject("VBScript.RegExp")
    
    reg.IgnoreCase = True
    reg.Global = True
    ' 1: WHERE/AND/OR
    ' 2: 空白
    ' 3: カラム名
    ' 4: 演算子 (=, <>, <=, >=, <, >)
    ' 5: リテラル値（シングルクォート付き文字列／数値／英数字／その他）
    reg.Pattern = "(WHERE|AND|OR)(\s+)([A-Za-z_][A-Za-z0-9_]*?)\s*(=|<>|<=|>=|<|>)\s*('[^']*'|\d+|[A-Za-z0-9]+|[^\s\)\(]+)"
    
    ' 置換: 「WHERE カラム 演算子 リテラル」→「WHERE カラム 演算子 [カラム]」
    ReplaceWhereLiterals = reg.Replace(sqlText, "$1$2$3$4[$3]")
End Function
```
unity　エンドレスに敵を沸かせるスクリプト　オブジェクトプール使用

・変数定義
敵が出現する時間間隔
-------------
```
public float spawnInterval = 2.0f;
```
敵の出現位置をplayerから何Mかに設定
------
```
public float spawnDistance = 30f;
```
objectpoolの参照　
---
```
public ObjectPool enemyPool;
```
現在アクティブな敵の一覧を管理するキュー
---
```
private Queue<GameObject> active = new Queue<GameObject>();
```
同時に表示できる敵の最大数
---
```
public int maxOnScreen = 6;
```
---
・start()メソッド
タグが "Player" のオブジェクトを見つけて、Transform を取得
InvokeRepeating() で SpawnEnemy() を1秒後から spawnInterval ごとに呼び出す
---
```
player = GameObject.FindWithTag("Player").transform;
InvokeRepeating(nameof(SpawnEnemy), 1f, spawnInterval);

```
SpawnEnemy() メソッドの流れ
敵の数が上限に達しているか確認
古い敵はキューから取り出し、プールに戻す
---
```
if (active.Count >= maxOnScreen)
{
    GameObject oldEnemy = active.Dequeue();
    enemyPool.ReturnToPool(oldEnemy);
}

```
新しい敵を取得
オブジェクトプールから敵をもってくる
---
```
GameObject enemy = enemyPool.GetFromPool();

```
出現位置の計算
playerから位置を計算して配置
---
```
Vector3 spawnPos = player.position + Vector3.right * spawnDistance;
spawnPos.y = player.position.y;

```
敵の位置をせっとしてアクティブに
---
```
enemy.transform.position = spawnPos;
enemy.SetActive(true);

```
敵を管理キューに追加
---
```
active.Enqueue(enemy);
```
毎日write up 4日目 caas

## 問題

Description
Now presenting cowsay as a service

コンテナではなく牛だそうです
![スクリーンショット 2025-05-09 18.33.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853234/e5adf707-da6d-443a-91dd-7e792c6d27aa.png)

![スクリーンショット 2025-05-09 18.33.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853234/9d0265bb-2e48-406c-b8e7-3bf3301b049a.png)


## 解答
パスに指定したものが直接表示されているので、そこの制御不備を突くのだろうなと思いながら、添付されているindex.jsを見ます。
```js
const express = require('express');
const app = express();
const { exec } = require('child_process');

app.use(express.static('public'));

app.get('/cowsay/:message', (req, res) => {
  exec(`/usr/games/cowsay ${req.params.message}`, {timeout: 5000}, (error, stdout) => {
    if (error) return res.status(500).end();
    res.type('txt').send(stdout).end();
  });
});

app.listen(3000, () => {
  console.log('listening');
});
```
expressで書かれたサーバサイドのコードのようです。
app.getで/cowsay/リクエストパラメータの制御を行っています。
どうやらなんのサニタイズもされず、直接execに使われていることがわかります。
execはnode.jsの組み込みのシェルコマンドを実行する関数です。もう明らかにヤバいですね
現在では、/usr/games/cowsay にparamsのmessageを引数として実行しています。
message引数を与えた後にパイプ | でつないで任意のコマンドを実行できます。
試しに/cowsay/a | lsとurlに入れて見ます。
するとフォルダ一覧が見えました。
![スクリーンショット 2025-05-09 18.52.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853234/3c226a74-ce15-4b73-a9e8-66bebeaf6ebd.png)
なぜかflagではなくfalg.txtとなっているのに気を付けて、cat等で出力します
/cowsay/a | cat falg.txt
するとflagが出力されます
【購買担当者向け】資材のサイズ集約でコストを下げる仮説検証

## 1. はじめに：製造業の「資材多すぎ問題」とどう向き合うか

製造部門から「資材の種類を減らして、コストを抑えたい」という相談を受けました。  
発注点の管理や在庫スペースの圧縮、調達単価の交渉強化などを目的とした現場の声でした。

ただ、調達コストの削減といっても単純に品目数を減らせば良いという話ではありません。  
資材の強度や見た目、加工精度といった製品仕様に深く関わるため、無理に集約してしまうと製造工程に支障が出てしまいます。

そこで今回は、「どこまで集約できれば効果がありそうか？」をデータで検証してみました。  
目標は調達コストの10%削減（KGI）です。

---

## 2. 課題の整理と仮説の立て方（KGI → KSF → 仮説）

### ■ KGI：調達コストを10%削減する

### ■ KSF（成功のカギ）

- 資材の品目数を可能な限り減らすこと
- 1品目あたりの発注量を増やして、ボリュームディスカウントを得ること
- 可能であれば取引先数の集約も目指すこと

### ■ 仮説として考えたこと

| 仮説 | 想定される課題 | 結果 |
|------|----------------|------|
| 樹種ごとに集約する | 木目や強度などの違いにより、製品側での調整が難しい | 不採用 |
| 最も使用頻度の高いサイズに集約する | 他サイズとの差が大きく、板取効率が著しく悪化 | 非現実的 |
| **厚みを揃えた上で、一番集約しやすいサイズを選定する** | 板取のシミュレーションで効率検証が可能 | 採用 |

最終的には、「厚みを揃えた上で、集約しやすいサイズを探す」という仮説を立てて検証を進めることにしました。

---

## 3. 分析条件とシミュレーション設計

### ■ 分析の前提条件

（Excelシート「前提条件」より）

- 集約の単位は「厚み（t）」ごとに設定しました
- 同一厚みグループ内で、もっとも多くの既存サイズに対応できるものを代表サイズとします
- 歩留まり（＝切り出し効率）を考慮し、現実的な必要枚数を算出します
- 集約後の代表サイズを使ったコスト試算が、削減目標内に収まるかを検証します

### ■ 板取の条件について

- 本来であれば、製品部品からの板取パターンをもとに検証したかったのですが、SKU数が数万点にのぼる上、データ整備も未完了のため断念しました
- そこで今回は、原版（板）から原版（別サイズの板）を採るという、あえて非効率な前提でのシミュレーションを行っています
- 板の90度回転も許容したうえで、何枚切り出せるか（切り出し数）をベースに歩留まり率を計算しました

---

## 4. シミュレーションの実施と結果概要

代表サイズを仮定し、各厚みグループごとに以下のような指標で評価を行いました：

- 歩留まり率（＝理論必要枚数 ÷ 現実必要枚数）
- 現実に必要となる調達枚数（歩留まり考慮後）
- 割引率（目標単価 vs 現状単価）
- 削減目標との乖離

以下は一例として、2.5mm厚の分析結果をぼかしてまとめたものです。

| 厚み | 最大サイズ候補 | 歩留まり率 | 現実必要枚数 | 想定単価差 | 集約評価 |
|------|----------------|-------------|----------------|----------------|------------|
| 2.5mm | 920×2440 | 約80% | ○○○○枚 | ▲3% | 集約効果あり（交渉余地あり） |
| 2.5mm | 960×2440 | 取れない | – | – | 非採用 |

- 歩留まりが80%を下回ると、必要枚数が増加し、単価優位性が消えてしまう傾向がありました
- サイズによっては、そもそも切り出しができない（＝歩留まり0%）ケースも存在します

---

## 5. 難しさと今後の展望

本来目指したかったのは、「製品部品（SKU）」から板を切り出す実運用ベースでの分析でした。  
しかし、SKUデータが未整備な状況では、現実的にそこまで踏み込めませんでした。

ただ、今回のような「板から板を切り出す」形の簡易シミュレーションでも、一定の示唆を得ることができました。


## 6. まとめ

- 板材の集約は「単価」だけではなく、「歩留まり」や「対応可能サイズ」の観点を含めた総合判断が必要です
- 特に「厚みごとの代表サイズを設ける」という考え方は、現場負荷を最小限にしつつ集約を進める上で現実的なアプローチと感じました
- 今後はデータ基盤を整えつつ、より精緻な最適化や、発注単位の自動設計にも挑戦していければと思っています
【初日】導入：PMBOKとは何か？【PMBOKを1日10分、半年で！】

# ✅【初日】導入：PMBOKとは何か？

このドキュメントでは、プロジェクトマネジメント初心者の方が、PMBOK（プロジェクトマネジメント知識体系）を基礎から学び、国際資格であるPMP取得を目指すための学習記録をまとめていきます。まずはPMBOKとは何か、そしてPMPがどういった資格なのかを理解することから始めましょう。

## 1. PMBOKとは？

PMBOK（ピンボック）とは、  
**「Project Management Body of Knowledge」＝プロジェクトマネジメント知識体系**のこと。

PMBOKは、プロジェクトを「うまく進めるための共通言語・ルール・やり方（ベストプラクティス）」をまとめたもの。  
世界中のプロジェクトマネージャーがPMBOKを基準に仕事をしており、PMP資格もこのPMBOKをベースに出題される。

## 2. プロジェクトとは？

PMBOKでは、プロジェクトを以下のように定義している。

> **「一時的な努力であり、独自の成果物（製品・サービス・結果）を生み出すもの」**

つまり、「はじまりと終わりがある仕事」で、「いつもと違う成果」を生み出すのがプロジェクト。

### ✅ 例：
- 新しいWebサイトの制作
- 社内システムの入れ替え
- 商品の新発売に向けた準備

## 3. PMP資格とは？

| 項目         | 内容                                                       |
|--------------|------------------------------------------------------------|
| 正式名称     | Project Management Professional（PMP）                   |
| 認定団体     | PMI（アメリカのプロジェクトマネジメント協会）           |
| 試験形式     | 180問／230分（選択式）                                     |
| 主な出題内容 | PMBOK第6・7版＋アジャイル知識＋状況判断力               |
| 日本語対応   | 試験・教材ともに日本語対応あり                             |

---

## ✅ 今日のまとめ

- PMBOKは「世界共通のプロジェクトの教科書」
- PMPはその知識を証明する**国際資格**
- プロジェクトとは「期間限定＋成果がある仕事」
- 初心者からでも習得は可能！


## 🔜 次回予定

「プロジェクトマネジメントの全体像（5つのプロセス群）」を学びます。
Jenkinsの認証情報を用いてbatでNASにアクセスする

```bat
stage('Copy to NAS with Login') {
    steps {
        withCredentials([usernamePassword(credentialsId: 'nas-credentials', usernameVariable: 'NAS_USER', passwordVariable: 'NAS_PASS')]) {
            bat '''
            chcp 65001
            set "NAS_PATH=\\\\NAS01\\coverage-reports"
            net use %NAS_PATH% /user:%NAS_USER% %NAS_PASS%
            set "src=%WORKSPACE%\\build\\reports\\jacoco"
            set "dst=%NAS_PATH%\\%DATE:~0,4%%DATE:~5,2%%DATE:~8,2%"
            mkdir "%dst%"
            robocopy "%src%" "%dst%" /E
            '''
        }
    }
}

```

自分用
```
stage('Zip and Upload Coverage to NAS') {
    steps {
        withCredentials([usernamePassword(credentialsId: 'nas-credentials', usernameVariable: 'NAS_USER', passwordVariable: 'NAS_PASS')]) {
            bat '''
            chcp 65001

            rem ====== 日付フォルダ名を作成 ======
            for /f %%i in ('powershell -Command "Get-Date -Format yyyyMMdd"') do set DATE_DIR=%%i

            rem ====== ZIPファイル作成 ======
            powershell -Command "Compress-Archive -Path build\\reports\\jacoco\\* -DestinationPath build\\reports\\jacoco\\jacoco_%DATE_DIR%.zip -Force"

            rem ====== NASへ接続 ======
            set "NAS_PATH=\\\\NAS01\\coverage-reports"
            net use %NAS_PATH% /user:%NAS_USER% %NAS_PASS%

            rem ====== アップロード ======
            copy build\\reports\\jacoco\\jacoco_%DATE_DIR%.zip %NAS_PATH%\\jacoco_%DATE_DIR%.zip

            rem ====== 接続解除（必要に応じて） ======
            net use %NAS_PATH% /delete /yes
            '''
        }
    }
}

```
ターミナルからのVScode起動時に警告が出る問題

# code .すると起動するが下記のような警告が出た
```
$ code .
[0509/182154.821020:ERROR:codesign_util.cc(109)] SecCodeCheckValidity: Error Domain=NSOSStatusErrorDomain Code=-67062 "(null)" (-67062)```
```

# 意味のなかった対応
VSCodeの設定を含む全て削除し、再度公式サイトからインストール
→何も変わらなかt

# 解決方法
下記コマンドを実行し、ウィザードに従ってパスワードを入れたりすればOK
```
codesign --force --deep --sign - /Applications/Visual\ Studio\ Code.app
```

# コマンドの中身
| オプション                                    | 説明                                                                              |
| ---------------------------------------- | ------------------------------------------------------------------------------- |
| `--force`                                | すでにある署名を強制的に上書き                     |
| `--deep`                                 | アプリ内部（バンドル内）のすべてのバイナリにも署名（ネストされた実行ファイル含む）                                    |
| `--sign -`                               | 自己署名（ad-hoc署名）する。Apple ID や認証済みの開発者証明書を使わず、署名だけして Gatekeeper を通すようにする |
| `/Applications/Visual\ Studio\ Code.app` | 対象アプリケーション                                                                      |

# なぜ治るのか？
macOS はアプリの実行時に「コード署名」がApple 開発者署名 or 信頼できる署名であることを Gatekeeper が検証しています。

何らかの理由で VS Code の署名が壊れていた、あるいは一部のバイナリ（例えば code コマンドや拡張）が署名から外れていた場合、SecCodeCheckValidity エラーで実行がブロックされます。

codesign --deep --sign - は、
「署名は適当（ad-hoc）でもいいから、署名の一貫性だけ保って再構築してくれ」
という命令で、Gatekeeper を黙らせます。

ただし、この方法は「とりあえず使えるようにする」ための応急処置的な手段です。

# 参考
こちらを参考にさせていただきました。
ありがとうございます🙏
http://nalab.mind.meiji.ac.jp/~mk/knowhow-2024/node17.html
🌿 第２回：[ラズパイ管理がぐっとラクになる！DockerとZoraxyで作るリバースプロキシ②【ローカルテスト編】]

## 🐣 はじめに

前回、リバースプロキシの概要を簡単に紹介しました。今回は、実際にローカル環境でDockerを使ってリバースプロキシツール『Zoraxy』をセットアップし、具体的な設定を試してみます。

まずは手元のPCで安全にテストしてみましょう！

## 📋 概要

今回の記事では、以下の内容を順番に実施します。

- Docker Desktopのインストール
- Zoraxyのセットアップ
- Zoraxy設定ファイルのローカル保存方法
- リバースプロキシの設定と動作確認

## 🐳 Docker Desktopをインストール

Dockerを利用するにはDocker Desktopが必要です。以下のページからインストールできます。

- [Docker Desktopのインストールページ](https://docs.docker.com/desktop/)

:::note warn
警告
各種ソフトウェアのダウンロードやインストールについては、自己責任でお願いします。
:::

インストール後、以下のコマンドを実行してDockerが正常に動作しているか確認します。

```bash
docker --version
```

バージョン番号が表示されればOKです！

## 🚀 Zoraxyをローカルでセットアップ

Docker Desktopが正常に動作していることを確認後、以下のコマンドでZoraxyをセットアップします。

```bash
git clone https://github.com/tobychui/zoraxy
cd ./zoraxy/docker/
docker compose up -d
```

## 📂 Zoraxyの設定ファイルをローカルに永続的に保存

Dockerの再起動後も設定が消えないように、`docker-compose.yml`を以下の内容で修正します。

```yaml
version: '3'

services:
  zoraxy:
    image: zoraxydocker/zoraxy:latest
    container_name: zoraxy
    restart: unless-stopped
    ports:
      - 80:80
      - 443:443
      - 8000:8000
    volumes:
      - ./zoraxy-config:/opt/zoraxy/config   # 設定ファイルをローカル保存
      - ./zoraxy-data:/app/data              # データベース、ログ等をローカル保存
      - /var/run/docker.sock:/var/run/docker.sock
      - /etc/localtime:/etc/localtime
    extra_hosts:
      - "host.docker.internal:host-gateway"
    environment:
      FASTGEOIP: "true"
```

変更後、Dockerを再起動します。

```bash
docker compose down
docker compose up -d
```

これで設定がローカルPCの`zoraxy-config`フォルダ内に保存されます。

## 🔑 Zoraxyの管理画面にアクセス

Dockerコンテナが起動したら、ブラウザでZoraxyの管理画面にアクセスします。

- 管理画面URL: `http://localhost:8000`

初回ログイン時にユーザーアカウントの作成が求められます。任意のユーザー名とパスワードを設定しましょう。

## 🌐 Zoraxyでリバースプロキシ設定をする

Zoraxyにログイン後、『HTTP Proxy』または『Create Proxy Rules』をクリックして以下のように設定します。

| 項目 | 設定例 |
|------|-------|
| Matching Keyword / Domain | `test.local` |
| Target IP Address or Domain Name with port |  `192.168.1.50:8080`（例：同じLAN内にある別のラズパイやWebサーバーのIP:Port） |
| Proxy Target require TLS Connection | チェックなし |

設定後、『Create Endpoint』をクリックして保存します。

## 🖥️ ローカル環境でドメイン名を設定する

ローカル環境のテスト用にドメイン名「test.local」を使います。hostsファイルを編集して設定します。

- Windowsの場合、管理者権限で以下のファイルを編集します。

```
C:\Windows\System32\drivers\etc\hosts
```

hostsファイルの末尾に以下を追加します。

```
127.0.0.1   test.local
```

これでブラウザから`http://test.local`でアクセスすると、Zoraxyを通じて設定した内容に接続できます。

## ✅ 動作確認

設定が完了したら、ブラウザで`http://test.local`にアクセスし、リバースプロキシが正しく動作することを確認しましょう。

## 📖 今回保存したZoraxyの設定ファイルの構成

保存された設定ファイルは以下の構成になっています。

- `config.json`：基本的なサーバー設定（管理画面のログイン情報など）
- `rules.json`：リバースプロキシの設定（設定したドメインや転送先）
- `tls.json`：SSL設定（本番環境で使用する場合に重要）

これらのファイルを使えば、本番環境への設定移行も簡単です。

## ⚠️ 注意

> **注意:** 本記事はローカル環境でのテスト用です。本番環境への設定方法については次回以降の記事で詳しく説明します。

## 🚩 次回予告

次回は、本番環境（Linux）でZoraxyを利用したリバースプロキシの構築方法を詳しく解説します。

お楽しみに！

## 🔗 シリーズリンク

- 第１回：[ラズパイ管理がぐっとラクになる！DockerとZoraxyで作るリバースプロキシ①【企画編】](https://qiita.com/Piyovate/items/e275e011a52aab8245fa)
- 次回：Coming soon
『ゲームプログラマのためのコーディング技術』が良かった話

# 本書の情報

- https://gihyo.jp/book/2015/978-4-7741-7413-6  
  第1刷は2015年と古いが、第4刷は2025年4月と比較的最近

# 本書との出会い

- 秋葉原の本屋で『[ゲームプログラミングC++](https://www.shoeisha.co.jp/book/detail/9784798157610)』を買おうとした際、たまたま隣に並んでいた
- 気になってその場でパラパラと立ち読みしてみたところ、良さそうだったのでついでに購入。  
  ~~Switch2落選の鬱憤を晴らすために、ちょっと高めの買い物をしたかった~~  

# 本書の構成

- 構成は非常にシンプル

    - **第1章：わかりやすいコードを書くためのテクニック（関数の章）**  
      初心者向けの章。関数を単位とした細かなテクニックを紹介しており、クラスの話も少し先取りしている

    - **第2章：シンプルな設計のための原則とパターン（クラスの章）**  
      中級者向け。主にクラス設計の話で、GoFのデザインパターンもいくつか紹介されている

    - **第3章：ソースコードの品質計測（パフォーマンス測定の章）**  
      前2章とは内容が変わり、QA的な内容にシフト。初心者から上級者まで広く対応している。付録的な位置づけで、ボリュームは少なめ

# 本書の優れている点・感想

- **初心者へのアプローチが非常に優れている**

    - 「綺麗にコードを書きたい」という気持ちはあるが、設計原則や理論のイメージが掴めない初学者（＝自分）にとってはドンピシャだった
    - 複雑なコードを書いた経験があまりないため、設計原則やクラス設計の理論は理屈としては理解できても実感が伴わない
    - クラス設計の理論に沿ってコードを書くとわざとらしさが出てしまう上に、コードが読みやすくなる実感も持てず、どうすればよいか分からない
    - そんな状態の自分に、本書冒頭から展開されているアドバイスはまさに必要としていたものだった

- **第1章での「関数を基本単位とせよ」というメッセージが特に良かった**

    - オブジェクト指向を学び始めると、クラスや継承を使いこなしたくなるが、個人開発レベルではクラスが不要なことも多い
    - 小さな単位である関数に焦点を当てることで、初心者でも実践しやすく、自分のコードにもすぐに適用できそうなテクニックが多かった
    - 読んですぐ実践し、疑問に思ったらまた読み直すというサイクルを回すことが上達に必要だと再認識した

- **1章後半～2章にかけて、中級者への導線が丁寧だった点も評価したい**

    - まずは小さな関数をたくさん書き、共通点のあるものをクラスにまとめるという、シンプルで実践的なアプローチが紹介されていた
    - 同じ名前を持つ関数同士を1つのクラスにまとめる、という分かりやすく納得感のある基準も提示されていた

- **第3章では、「結合度」「凝集度」といった概念に対し、定性的な説明に留まらず、定量的な指標を提示している点が良かった**

    - 定量的な基準があることで、自分のコードにどう適用すべきかの判断がしやすくなる。初心者にとっては「なんとなく減らす／増やす」ではなく、妥当な範囲が提示されているのがありがたかった

# 印象に残ったメッセージ

- 「職業でコードを書く人はある程度アウトプットの機会が担保されているため、インプットを重視すべき」という指摘
    - 技術書や他人のコードを読まないと成長しない
    - 「アウトプットが大事！」という言葉を真に受けて、ひたすらアウトプットしていた自分には刺さる内容だった

# 向いている読者層

- C++の基本文法やオブジェクト指向の基礎を一通り勉強した人  
  （if, for 等の制御構文、四則演算、論理記号などを理解しており、クラスや継承のイメージがついている）  
    - 目安として『独習C++』を一読していれば十分
- GoFのデザインパターンに興味があるが、理解が浅く、ちゃんと学びたいと思っている人  
- ゲーム制作に興味がある人  
- C++で簡単なコードは書けるが、複雑なコードの設計に悩んでいる人  
- 初心者から中級者にステップアップしたい人

# 余談

本書や『[オブジェクト指向のこころ](https://www.maruzen-publishing.co.jp/book/b10111856.html)』に出てくる「変更が多い部分とそうでない部分を分離して管理する」という考え方にどこか既視感があると以前から思っていたが、この既視感の正体が「抗体に多様性が生じる仕組み(抗体の可変領域の組換え)」であることに最近気づいた

※筆者は生物系の出身で、抗体の可変領域の組換えについては高校や大学の頃に学んでいる

- 「変更が多い部分とそうでない部分を分離して管理する」というのは、『オブジェクト指向のこころ』では「共通性・可変性分析による流動的要素の切り出し」として表現されている内容に相当する
    - 大雑把に言うと、ソフトウェアの設計において「どの部分が共通で、どの部分が変化しやすいか」を明確にして保守しやすい設計にしましょうという考え方
- 一方の「抗体の可変領域の組換え」は、生物の免疫システムにおいて多様な抗原(病原体など外部からやってきて悪さするやつ)に対応して排除するための仕組み
    - 抗体の基本構造（定常領域＝Constant region）は共通で、抗原に特異的に結合する可変領域だけが多様化するというげんr
    - [参考](https://www.kyowakirin.co.jp/antibody/basics/diversity.html)
- このイメージが頭にあったおかげで、本書や『オブジェクト指向のこころ』で説明されている共通性・可変性分析の考え方もすんなり理解できた
- 生物系の自分にとって、思わぬところで役立つ知識が知らず知らずのうちに身についていたことに驚いた。思考のフレームワークはおもしろい
巨大な数の足し算（文字列処理）　BigInt禁止でどうする!?

「`BigInt` 使えば一発でしょ」と思ったけど、今回は文字列処理の分野なので文字列処理で解いていく！

<br><Br>

## 📌 問題概要

1000桁までの2つの数字（文字列SとT）を足して、その結果を文字列で出力します。注意点は以下のとおり：

- SとTは文字列（数字のみ）
- 桁の長さは同じ
- 数値がめちゃくちゃ大きい


入力例：

    1029384756
    1029384756

出力例：

    2058769512


設計のカギは「下の桁から順に計算＋繰り上がり」

<Br>

https://paiza.jp/works/mondai/string_primer/advance_step11

<br><br>

## 💥これでも解けるけど　今回は文字列処理でやりたい
```js
const rl = require('readline').createInterface({ input: process.stdin });

const lines = [];

rl.on('line', (input) => {
    lines.push(input);
});

rl.on('close', () => {
    const [A, B] = lines.map(BigInt); // ここで変換！

    // BigInt同士で加算し、文字列として出力
    console.log((A + B).toString()); 

});
```

<br><br>

## 📌文字列処理バージョン

「繰り上がりあり」「非常に大きな桁の数字でも対応可」「BigInt非使用」

```js
const rl = require('readline').createInterface({ input: process.stdin });
const lines = [];

rl.on('line', (line) => lines.push(line));
rl.on('close', () => {
    let [s, t] = lines;

    // 桁数が同じであることが前提
    let ans = "";
    let carry = 0;

    // 下位の桁から計算する（末尾の文字からループ）
    for (let i = s.length - 1; i >= 0; i--) {

        const digitSum = Number(s[i]) + Number(t[i]) + carry; // 同じ桁の文字を数値に変換し、繰り上がりも加算

        carry = Math.floor(digitSum / 10); // 10以上なら繰り上がりが発生 → 次のループに持ち越す

        ans = String(digitSum % 10) + ans; // 現在の桁の値（1桁）を取り出し、先頭に追加（上の桁へつなげる）
    }


    // 最後に繰り上がりが残っていたら追加
    if (carry > 0) {
        ans = String(carry) + ans;
    }

    console.log(ans);
});
```
🔍 ポイント

- `for (let i = s.length – 1; i >= 0; i–)` で 末尾からループ。
- `digitSum % 10`  がその桁の数、 `Math.floor(digitSum / 10)`  が繰り上がり。
- 最後に `carry > 0` を忘れず確認。

### <Br>⚠️ 注意

このコードは `S` と `T` が同じ桁数 である前提。

違う長さの場合は短い方を `padStart` で補完すればOK！　

例：
```js
if (s.length < t.length) s = s.padStart(t.length, '0');
if (t.length < s.length) t = t.padStart(s.length, '0');
```

## <br>📝 気づきメモ

- 最後の繰り上がり処理、忘れやすいから注意。

- 足し算は下の桁から繰り上がりを考えて進めるから、左からじゃなく「右（下の桁）」から処理するのが大事！

- `padStart()`で桁をそろえれば応用も効く！

## <br>✨ まとめ

今回は「数値に変換しないで、文字列のまま足し算する」方法を学んだ。下の桁から繰り上がりを意識して処理することで、JavaScriptでも正確に大きな数を扱えるようになる！

<br><br><br>
[🐻僕の失敗談(´;ω;｀)と解決法🐈](https://paizabeginner.wordpress.com/about/)
配列の処理を途中で止めたい場合

## 前提

　配列と、

```js
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
```

　重い処理の関数があって、

```js
const slowFunction = x => {
    console.log(`slowFunction called with ${x}`);
    return x;
}
```

　これを配列の先頭から適用して、その結果を判定するという繰り返し処理があったとして、

```js
const isOK = x => {
    return x > 5;
}
```

　判定関数で有効なものをひとつでも取得できればそれでいい場合、途中で処理を打ち切りたい時、どう書くか、という話です。
　`Array.prototype.reduce`とかを使ってしまうと最後まで走査してしまいますし、`Array.prototype.some`は途中で停止できますが処理後の値を取得することができないです。

## 結論

　Iterator Helper が素敵。

## 今までのコード

　おそらく、ループを使ってこんな感じで書くか、

```js
let result = null;
for (let i = 0; !isOK(result) && i < arr.length; i++, result = slowFunction(arr[i])) { } // breakでもよい
console.log(result);
```

　`Array.prototype.some`などの関数の副作用を使って書くか、

```js
let result = null;
arr.some(x => { // findでもよい
    result = slowFunction(x);
    return isOK(result);
});
console.log(result);
```

　という感じだったかと思います。
　いずれにせよ、テンポラリ変数を`let`で準備しなくてはいけない、というのはちょっとダサい感じがします。

## まさかの時の Iterator Helper

　これからはこう書けます。

```js
arr.values().map(slowFunction).filter(isOK).take(1).toArray()[0]
```

　遅延評価（？）してくれるので、必要のない関数呼び出しはしないのが素敵。

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

　他の言語ではわりと当たり前だと思うのですが、JavaScriptは2025年になってようやく実装がそろってきました。

https://caniuse.com/mdn-javascript_builtins_iterator_map
useParams()でidがundefinedになるテストエラーの解決法【React Router】

## はじめに

React Router を使ったコンポーネントでよく出るエラーのひとつが、
`useParams()` で URL パラメータが取得できずにテストが落ちることでした。

ここでは、そのエラーの原因と解決方法を整理します。


## useParams()とは

React Router のフックのひとつです。

```ts
const { id } = useParams();
```

このように書くと、`/user/abc123` のようなURLから `id: "abc123"` を取得できる。
ただしRouterコンテキストの中でしか使えないです。


https://api.reactrouter.com/v7/functions/react_router.useParams.html

今回は useParams を使って、URLの id に応じたユーザーの個人ページ（例：/taro → 太郎さんのページ）を表示するために使いました。



## エラーの例

```txt
TypeError: Cannot read properties of undefined (reading 'id')
```

このエラーは `useParams()` で `id` を読み込もうとしているのに、
テスト中は `id` を持つ URL パラメータが渡っていない状態で起こりました。


## エラーの原因n

```tsx
const { id } = useParams();
```

上記のようなコードがあるコンポーネント（例：`Card`）を
テストでこう書いて失敗しました。

```tsx
render(<Card />); // ← URL が無い
```

`useParams()` は React Router のコンテキストが無いと動きません。

## MemoryRouter で仮URLを与えて解決

テストでは `MemoryRouter` を使って、仮の URL を与えます。

### MemoryRouterとは

React Router の `Router` の一種で、
**テスト中に「仮のURL履歴」を作るためのラッパーです**

https://v5.reactrouter.com/web/api/MemoryRouter

#### initialEntries

MemoryRouter に渡す initialEntries は、仮のURL履歴を表す配列です。

このように書くと、最初にアクセスしているURLを「/taro」と仮定してくれます。
これにより、useParams() が正しく id: "taro" を返すようになります。

```tsx
render(
  <MemoryRouter initialEntries={["/taro"]}>
    <Routes>
      <Route path="/:id" element={<Card />} />
    </Routes>
  </MemoryRouter>
);
```

これで `useParams()` が `{ id: "taro" }` を返せるようになります。


## つまずいたポイント

* `useParams()` はRouterコンテキストの中でしか使えない
* 単体で `<Card />` を `render()` するだけではパラメータが入らない
* `MemoryRouter` + `initialEntries` を知らないとテストが通らなかった


## まとめ

* `useParams()` が必要なコンポーネントは `MemoryRouter` で包む
* `initialEntries` で仮のURLを渡す
* `Route path="/:id"` と `element={<対象コンポーネント />}` を組み合わせる