OmniAICreator/Qiita-1.07M huggingface dataset:
Replitで開発したNode.js+PostgreSQLのウェブアプリをAWSのEC2で動かした話

こんにちは。サイドFIREを目指しながら開発を続けているプログラマー、田中です。

今回は、**Replitで開発したNode.js + PostgreSQL構成のWebアプリケーションを、AWS EC2上に本番環境として移行したプロセス**をまとめました。  
実際に移行したサイトはこちらです：  
👉 [https://yomiai.info/](https://yomiai.info/)

![スクリーンショット 2025-04-09 午前11.45.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282387/29a92cca-fe10-488c-a7ac-aff21357ca96.png)

---

## 想定読者

- Replitを活用してAIと一緒にアプリ開発をしている方  
- 開発したアプリを**できるだけ低コストで本番運用したい**方

---

## 背景：Replitとは何か

Replitは、AIと対話しながらアプリを構築できるクラウド開発プラットフォーム（SaaS）です。  
コードを一切書かずに、**チャット形式でAIに指示を出すだけでアプリが完成する**という、新しい開発体験を提供してくれます。

特に、プロトタイピングや学習用途では非常に優秀で、デプロイ機能まで内蔵されているため、**ワンクリックでアプリを公開することも可能**です（独自ドメインにも対応）。

Replitについて詳しく知りたい方は、Qiitaなどで解説記事を探してみてください。

---

## Replitを本番運用に使う際の課題

実際にReplitでアプリを構築し、公開してみたことで、以下のような課題が見えてきました。

### 課題1：継続的な課金が必要

Replitは、AI機能の利用、データベースの使用、Webサイトの公開に対して月額課金される仕組みです。  
私のケースでは、**公開しているだけで毎月およそ30ドル程度**の費用が発生していました。

AIによる開発支援は価値がありますが、「完成したアプリをただ置いておくだけ」で課金され続けるのは、コスト的に見合わないと感じました。

### 課題2：開発環境と本番環境の分離ができない

Replitでは、**開発環境と本番環境で同じデータベースを共有**する構成になっており、開発中の操作がそのまま本番に影響を及ぼすリスクがあります。

スキーマ分割によって論理的に分けることは可能ですが、設定ファイルの切り替えなどで運用する必要があり、**人的ミスによる事故リスクが常に伴います**。

---

## 解決策：AWS EC2への移行

上記の課題を踏まえ、以下の方針で本番環境をReplitからAWS EC2へ移行しました。

- 開発は引き続きReplitを利用（AIによる迅速な構築支援を活用）
- 本番環境はAWS EC2上に構築し、**開発・本番の完全分離**
- インフラコストは極力抑えつつ、**安全かつ安定した本番運用**を実現

---

## 実際に行った移行手順

### 前提条件

- GitHubアカウント保有
- AWSアカウント保有

### 移行フロー

1. ReplitとGitHubの連携
2. AWS EC2インスタンスの作成
3. インスタンスに以下をインストール：
   - NGINX
   - PostgreSQL
   - Node.js
   - Git
4. GitHubからReplitで作成したソースコードをクローン
5. Replitに依頼し、`.env`ファイルでDB接続設定を切り替えられるように調整
6. Replitに依頼し、本番用のDBスキーマを生成
7. EC2上のPostgreSQLで、Replit用のユーザとDBを作成
8. 作成されたDBスキーマをPostgreSQLに適用
9. お名前.comでドメイン取得
10. DNS設定で、ドメインからEC2インスタンスのIPを参照するように設定
11. NGINXでドメイン受け取り設定を実施
12. NGINXでNode.js（ポート5000）をHTTP（ポート80）で公開するように設定
13. Let’s Encryptを使ってHTTPS化

---

## 苦労したポイントと解決法

### 1. Node.jsアプリが起動しない

原因の特定には至りませんでしたが、ReplitがAWS上で動作させるためのバッチスクリプトを用意してくれたことで解決しました。

### 2. DB接続の切り替え対応

Replit上ではHTTPS経由でクラウドDBへ接続する構成ですが、EC2ではローカルにPostgreSQLをインストールする必要があります。  
この差異に対応するため、`.env`ファイルに**接続環境を識別するフラグ**を用意し、それに応じて接続設定を切り替えるようにしました。

---

## AI駆動開発で大事なマインドセット

AIを活用した開発では、**トラブルに直面したときに「どのような情報をAIに渡せば解決できるか」を考えることが重要**です。  
エラーが出たらその情報をAIに伝え、修正提案をもらう。その繰り返しが問題解決の鍵になります。

---

## まとめ

- ReplitはAI開発のスピードを最大限活かせる優秀な開発環境  
- ただし本番運用には課題があるため、EC2との併用がオススメ  
- 最小限のコストで安全な運用を実現したい方には、今回の方法が有効

---

## お知らせ

この記事が参考になった方は、ぜひ「いいね！」やX（旧Twitter）のフォローをお願いします！

📱 [https://x.com/40jobseeking](https://x.com/40jobseeking)

Replit関連でお仕事を依頼したいという方がいましたらTwitterでDMください！
削除した .blade copy.php ファイルに関するエラーを削除する方法

# 概要
削除した .blade copy.php ファイルに関するエラーが VSCode に残っている場合、キャッシュ（インデックス）が残っているだけの可能性が高い。

# ワークスペースキャッシュのクリア
## ①コマンドパレットを開く
```
command + Shift + P
```

## ②コマンドパレットを開く
```
Developer: Reload Window
```
を実行
👉 VSCode の内部状態をリロードして、不要な警告を消してくれる
【EKS】eksctlでサクッとAmazon EKSクラスタを作成してみよう！

## 概要
EKSを使用している人はご存知かもしれませんが、
eksctlを使用するとクラスタの立ち上げが容易なので
まとめます！

## 🔧eksctlとは？
Amazon EKS クラスタを簡単に作成・管理するためのCLI ツールです！
クラスタ作成に必要な 
- IAM ロール
- VPC
- ノードグループ
なども自動でセットアップしてくれる優れもの〜


Terraform や CloudFormation を使わずに、
```
eksctl create cluster
```
だけで環境構築できちゃいます！

## 🛠️ eksctlのインストール

Macの場合はHomebrewでサクッとインストールできます：
```
brew tap weaveworks/tap
brew install weaveworks/tap/eksctl
```
インストール確認：
```
eksctl version

# 結果
0.207.0
```

:::note info
### Mac OS以外を利用の方
LinuxやWindowsの方は公式ドキュメントを参照してください！
https://eksctl.io/installation/
:::

## 🚀 クラスタを作成してみる
まずはプロファイルが設定されていることを確認しておきましょう：

```
aws configure list
```

次に、以下のコマンドでクラスタを作成します（名前はお好みでOK!）

```bash
eksctl create cluster \
  --name my-eks-cluster \
  --region ap-northeast-1 \
  --nodes 2 \
  --node-type t3.medium \
  --managed
```

:::note info
※作成には10～15分ほどかかります。
:::

### クラスタ作成コマンドの解説

以下は `eksctl create cluster` コマンドで使用した主なオプションの説明です：

| オプション | 説明 |
|------------|------|
| `--name` | 作成するEKSクラスタの名前を指定 |
| `--version` | Kubernetesのバージョンを指定（例：`1.30`） |
| `--region` | クラスタを作成するAWSリージョンを指定（例: `ap-northeast-1` は東京リージョン）|
| `--nodegroup-name` | ノードグループの名前（例：`workers`） |
| `--node-type` | ノードとして使用するインスタンスタイプを指定（例: `t3.medium`） |
| `--nodes` | 作成するノード（EC2インスタンス）の数を指定 |
| `--nodes-min` | ノード数の最小値（オートスケーリング用） |
| `--nodes-max` | ノード数の最大値（オートスケーリング用） |
| `--ssh-access` | ノードへのSSHアクセスを有効化 |
| `--ssh-public-key` | SSH接続に使用する公開鍵ファイルのパス |
| `--managed` | マネージドノードグループとしてノードを作成するオプション |

### 🔍作成された内容を確認
作成後、以下のリソースが自動で作られています：

- EKSクラスタ
- マネージドノードグループ
- VPC（サブネット、ルートテーブル含む）
- セキュリティグループ
- IAMロール（クラスタ・ノード用）

kubectl を使って、ノードの状態も確認できます！

```bash
kubectl get nodes
```

### 参考
コンソールはこんな感じで作成が確認できます！

![スクリーンショット 2025-04-09 21.08.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/945342/f93780e4-b63c-458a-9ac8-860d0dd7ccc6.png)

## 作成物をもう少し見てみよう

作成されたクラスタとリージョンが見えます。
```bash
$ eksctl get cluster
NAME		REGION		EKSCTL CREATED
eks-from-eksctl	ap-northeast-1	True
```

kubectlの向き先が作成されたeksに変更されてます。
(私の環境では元々docker-desktopに向いてました)
```
$ kubectl config get-contexts
CURRENT   NAME                                                CLUSTER                                    AUTHINFO                                            NAMESPACE
          docker-desktop                                      docker-desktop                             docker-desktop
*         eks-demo@eks-from-eksctl.ap-northeast-1.eksctl.io   eks-from-eksctl.ap-northeast-1.eksctl.io   eks-demo@eks-from-eksctl.ap-northeast-1.eksctl.io
```

imageを動かすワーカーノード。
```
$ kubectl get nodes
NAME                                                 STATUS    ROLES     AGE       VERSION
ip-000-000-000-000.ap-northeast-1.compute.internal   Ready     <none>    14m       v1.10.11
ip-000-000-000-000.ap-northeast-1.compute.internal   Ready     <none>    14m       v1.10.11

```

## 🧹 クラスタの削除（片付け）
EKSクラスタを起動していると費用がかかります。
使い終わったら片付けも簡単なので、リソース削除しましょう。

```bash
eksctl delete cluster --name my-eks-cluster --region ap-northeast-1
```

:::note info
※削除にも数分かかります。
:::

## ✍️ まとめ
- eksctl を使うと EKSクラスタの作成が爆速！
- VPCやIAMも一括で作成してくれるので超便利
- 学習用や検証用にぴったりのツール

EKSのとっかかりとしては最高なので、ぜひ触ってみてください！
複素数の因数分解のパターン数

![image2x10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/aaf4141f-2524-4513-ba30-127a161d8475.png)
図１　約数の数

![image2x10高レベル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/58d96374-c3a7-492f-ba11-ee73b5e4d88f.png)
図２　約数の有無

![GaussianPrimeと吉原のOL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/9a101789-9ab4-4f99-932b-95ef2c56b778.png)
図３　ガウス素数（緑）の上に、約数の数（赤）をオーバーラップ


# はじめに
複素数の素数は？
複素数の約数は？
複素数の因数分解は？
という、考えのもと、複素数の約数のパターン数を数え上げ、数に応じて可視化しました。
吉原さんの考えをもとに考案しています。
複素数の積（因数分解）として表すことができればそれを複素数の約数と捉えよう、という方針です。

# 環境
Processing 4.2
Complex Numbersライブラリ利用

# プログラム
ダブりがあり、2重にカウントしてます。
力任せ、計算非効率なアルゴリズムです。
第一象限のみ計算。
Y軸反転。
軸上は計算なし。


```java:Processing
import complexnumbers.*;

void setup() {
  size(50, 50);
  background(0);
  for (int y=1; y<=width; y++) {
    for (int x=1; x<=width; x++) {
      int count=0;
      Complex target;
      if (x<=y)
        target = new Complex(x, y);  // 目標の複素数
      else
        break;

      println("整数範囲 [-"+width+", "+width+"] で、(a + bi)(c + di) = "+x+"+"+y+"i となる組み合わせ：");

      for (int a = -width; a <= width; a++) {
        if (a==0) a++;
        for (int b = -width; b <= width; b++) {
          if (b==0) b++;
          Complex z1 = new Complex(a, b);

          for (int c = -width; c <= width; c++) {
            if (c==0) c++;
            for (int d = -width; d <= width; d++) {
              if (d==0) d++;
              Complex z2 = new Complex(c, d);
              Complex product = z1.mul(z2);
              if (product.equals(target)) {
                //println("("+z1+")("+z2+")");
                count++;
              }
            }
          }
        }
      }
      set(x, y, color(count*3));
      set(y, x, color(count*3));
      println(count);
    }
  }

  println("探索完了！");
}
```

```math
x+yi=(a+bi)(c+di)
```
となるa,b,c,dの最大値はxまたはyを超えない、という前提で計算しています。

# 参考サイト

複素数の約数の総和（千葉県立船橋高等学校３年，吉原和志）

https://www.chiba-c.ed.jp/funako/fttp_kousin/ssh/reserch/2016/2016_30m.pdf

自分の

https://qiita.com/hextomino/items/f85fd6a9be6407803215
vue の template 上で 変数を宣言したい。そういう時のアプローチ

## まず

Vue3 では ジェネリクス が使えます。

https://ja.vuejs.org/api/sfc-script-setup.html#generics

vuejs では スコープ付きスロット を使うことで template 上で 変数を宣言することができます。

また、 default スロットであれば template 要素も省略できます。

https://ja.vuejs.org/guide/components/slots#scoped-slots


## アプローチ

具体的なアプローチとしては

まず、 型引数 `T` を使うこととします。

任意の型を Props に直接渡すことはできない為、一旦 `value` プロパティを `T` 型として公開します。

また、スコープ付き スロットとして default スロット の引数を `T` 型とします。

つまり、こういう実装になります。

```vue:PassThrough.vue
<script setup lang="ts" generic="T">
export interface PassThroughProps<T> {
  value: T;
}
export interface PassThroughSlots<T> {
  default(props: T): any
}
defineOptions({
  inheritAttrs: false,
});
const props = defineProps<PassThroughProps<T>>()
defineSlots<PassThroughSlots<T>>();
</script>
<template>
  <slot name="default" v-bind="props.value"></slot>
</template>
```

使う時はこんな感じです。

```vue:App.vue
<script setup lang="ts">
import PassThrough from "./PassThrough.vue";
</script>
<template>
  <PassThrough :value="{ hello: 'hello', world: 'world' }" v-slot="{ hello, world }">
    <div class="hello">{{ `${hello} ${world}` }}</div>
  </PassThrough>
</template>
```

これにより `PassThrough` の `value` プロパティに渡した値が `v-slot:default` の変数として取得できます。

[playground](https://play.vuejs.org/#eNp9U8Fu2zAM/RVCKJAEyJLDdvLcAN3Qw3bYgjVHHarZjKNOlgxJTjMY/vdSdNK4bZCTJPLx8ZEiO3HXNIt9iyITeSi8biIEjG0DRtnqVooYpFhJq+vG+QhrFcJm511b7WDrXQ1SLJYjY2KS4qu0+XIgo9A8Yt0YFZHuAPmYItsr0yJl6WCHxrgMJnxO5vDsvCnpzecEeilg/ykYF8/oIyj5mJrIS72HwlAGQjGGXF0Hjzcdv3q46Timf4S+z5cEH0SNa0iSlyPNYk5NKJzd6mrxFJylTnUpSIrC1Y026H83UTtLjcqAPcmnKN3zT7ZF3+L8ZC92WPy7YH8Kh2STYu0xoN9TG199UfkK4+C+f/iFB7q/OmtXtobQV5x/MDjTJo0D7FtrS5I9wrHaH/zH2labcH+IaMOpqCQ0IXvGS0Gf/P1K6We5nxdfOE7anrr4bk6uTRxUaNHrgp4b/l088PxpG9FvVYHjSVx714R8sxoU8EhlsKEhpLzX4h5oms5xJW5Va+K0SWwUP8tA2f9MQi5t8VjqlNHa7khfvIvRE3irTEhf2c8oK41KiMA0cJtoKXaQeEHzajo78Q9yLugjzNuN+rBTaS/Aqjqt0rEO3pe/2pZkYi0Lbgw1k4gI/mHK+xcSX2WH)

以上。
Amazon Nova Sonic のコードを Python で書いてみた

公式の Document はこちら

https://docs.aws.amazon.com/nova/latest/userguide/speech.html

これをもとに Python で 1 ファイルで全部書いた。処理を追うには便利かと思われる。たぶん。

ここにアップしておいた。

https://github.com/kazuhitogo/nova-sonic-sample

pyaudio に依存外野だったので soundfile に書き換えた。


```bash
python -m venv .venv
source /.venv/bin/activate
pip install -r requirements.txt
python run.py
```

で動くはず
AWSコスト監視くん - AWSのコストをSlackに通知するTerraformモジュール

# はじめに
このモジュールを作成するきっかけとなったのは、「AWS Step Functions(JSONata)でAWS料金をSlackへ通知【Lambda無し】」という記事でした。この記事を読んで、Lambdaを使用せずにAWSのコストを監視できる仕組みに感銘を受けたスタッフが「これを導入したい！」ということで、これをTerraformモジュールとして再利用可能な形にさせて頂きました。

https://dev.classmethod.jp/articles/aws-cost-watcher-with-sfn-jsonata/

# 背景

AWSの利用コストを監視することは、クラウド運用において重要な課題の一つです。特に、予期せぬコストの増加や、特定のサービスの利用状況を把握することは、コスト最適化の第一歩となります。しかし、AWSのコスト管理コンソールを毎日確認するのは手間がかかり、また、コストの急激な増加に気づくのが遅れる可能性があります。

# 概要

https://github.com/nix-tkobayashi/aws-cost-monitoring-slack-notification

「AWSコスト監視くん」は、以下の機能を提供します。

- AWSのコストを定期的に自動確認
- コストが設定した閾値を超えた場合、Slackに通知
- コストの内訳をサービスごとに表示
- カスタマイズ可能なスケジュール設定

このモジュールは、AWS Step Functions、SNS、Chatbot、EventBridge Schedulerを組み合わせて実装されています。Lambdaを使用せずに実装されているため、運用コストを抑えることができます。

# 使い方

1. モジュールを呼び出すTerraformコードを作成します。

    ```hcl
    module "cost_watcher" {
      source = "../../modules/cost-watcher"
    
      project            = "my-project"
      slack_channel_id   = "C0123456789"
      slack_workspace_id = "T0123456789"
      cost_lookback_days = 7
      angry_threshold    = 100
      batch_schedule     = "cron(0 9 ? * MON-FRI *)"
      batch_timezone     = "Asia/Tokyo"
    }
    ```

2. 必要な変数を設定します。

    | 変数名 | 説明 | デフォルト値 |
    |--------|------|------------|
    | project | プロジェクト名 | - |
    | slack_channel_id | SlackチャンネルID | - |
    | slack_workspace_id | SlackワークスペースID | - |
    | cost_lookback_days | コストを確認する日数 | 7 |
    | angry_threshold | コスト監視くんが怒る閾値（USD） | 100 |
    | batch_schedule | コスト確認のスケジュール（cron形式） | cron(0 9 ? * MON-FRI *) |
    | batch_timezone | スケジュールのタイムゾーン | Asia/Tokyo |

3. Terraformを実行してデプロイします。

    ※詳しくはリポジトリの README をご覧ください。

## 終わりに

「AWSコスト監視くん」は、AWSのコスト管理を自動化し、コストの急激な増加を早期に検知することを可能にします。このモジュールを使用することで、コスト管理の効率化と、予期せぬコストの増加を防ぐことができます。

# 一言

AWSのコスト管理は、クラウド運用において重要な要素です。「AWSコスト監視くん」を使用して、効率的なコスト管理を実現しましょう。

この記事良かったと少しでも思って頂けたら是非 [@\_\_\_nix___](https://twitter.com/___nix___) をフォローしてあげてください。或いは記事に対してリアクションをお願い致します。

# 謝辞

この記事は、以下を参考にインスパイアされました。
- [AWS Step Functions(JSONata)でAWS料金をSlackへ通知【Lambda無し】](https://dev.classmethod.jp/articles/aws-cost-watcher-with-sfn-jsonata/)

この記事の著者である川原＠Classmethod様に感謝申し上げます。
指定した時間にそれぞれ表示する

**指定した時間にメッセージを表示する**



```
@echo off
setlocal enabledelayedexpansion

:: 現在時刻を取得
set "NOW=%TIME%"

:: 時と分を取り出して数値化（先頭スペース対策付き）
set "HOUR=%NOW:~0,2%"
set "MIN=%NOW:~3,2%"
set /a HOUR=1%HOUR% - 100
set /a MIN=1%MIN% - 100

:: 現在時刻を分単位に変換（例：10:30 → 630）
set /a NOW_MINUTES=HOUR*60+MIN

:: 各時間帯を分単位で定義
set /a WORK_START=10*60
set /a LUNCH_START=12*60
set /a LUNCH_END=13*60
set /a WORK_END=18*60

:: メッセージ分岐
if !NOW_MINUTES! GEQ !LUNCH_START! if !NOW_MINUTES! LSS !LUNCH_END! (
    echo  Bです（12:00～13:00）
) else if !NOW_MINUTES! GEQ !WORK_START! if !NOW_MINUTES! LSS !WORK_END! (
    echo  Aです（10:00～18:00）
) else (
    echo  Cです
)

endlocal
pause
```
Arduino通過カウンタ

<font COLOR="BLUE">

### Arduino通過カウンタ</FONT>

::: note
- Arduinoマイコン + レーザ発信機 + 光度センサ + サーボモータ + 計算機
- 通過カウンタを作って欲しいと依頼を受けて作ったもの。
- incする手法は計算機のボタンをサーボで押すという簡単(手抜き)仕様。
- bool t=false はセンサ前で立ち止まっていると連続incされるのでその防止用。
- 隔たりなく通過すると複数でも一つ(一人)としてカウントされる。
- 適当なポートにブザーもしくはFET経由で付けて非受光部のelse文を直せば侵入警報器になる。アクション映画等で見かけるアレです。
- (https://qiita.com/inf102/items/9eec6471b1c587995a7b)

:::

<font COLOR="BLUE">

#### 1.試作動画</FONT>

<iframe width="560" height="315" src="https://www.youtube.com/embed/lsKk3Rp7aaA?si=VS2Jd3PyngunIr_Q" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


<font COLOR="BLUE">

#### 2.Arduino R3マイコン ATmega328チップ</FONT>

![P1580846.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/f982f699-f159-4e7e-a133-81c06afb9159.jpeg)
- 7PIN サーボデータ線
- 5PIN 光度センサデータ線

<font COLOR="BLUE">

#### 3.システム全景</FONT>

![P1580841.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/dd90de06-a5e7-471b-abb0-e425185e20f5.jpeg)



<font COLOR="blue" >

#### 4.c++ Sourcecode</FONT>
```cpp
////////////////////
// Arduino Counter.
// inf102 S.H 2025.
////////////////////

#include <Servo.h>

Servo myservo;
const int SV_PIN = 7;
const int PIN_ANALOG_INPUT = 5;
static bool t=false;

void setup() {
    myservo.attach(SV_PIN, 500, 2400);
    Serial.begin( 9600 );
}

void loop() {
    int i = analogRead( PIN_ANALOG_INPUT );
    
    float f = i * 5.0 / 1024.0;
    Serial.print (f); 
    
    if ( f>=4.0) {
        Serial.print ("レーザ受光中\r\n"); 
        t=false;
    }
    else{
        Serial.print ("レーザ非受光\r\n"); 
        if (t==false){
            myservo.attach(SV_PIN, 500, 2400);
            myservo.write(33);
            delay(300);
            myservo.write(0);
            delay(300);
            myservo.detach();
            t=true;
        }
    }
    delay (50);
}
```

- 参考 LR44等ボタン電池は意外と早くなくなるので不要な単三電池に無理やり換装
数年使ってます。
![P1440752.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/ad00bc80-aac4-43fc-aa08-f423b054641e.jpeg)
【初心者向けGit入門】Gitを学ぶときに必ずやってほしいこと

これは初心者向けのGit入門の記事です。ただし、具体的な手順を示したチュートリアルではなく、少し概念的な解説です。

今回は「Gitを学ぶときに必ずやってほしいこと」を解説します。

## Gitを学ぶときに必ずやってほしいこと

Gitを学ぶときに必ずやってほしいこと。それは　**「GUIツールでコミットグラフを確認する」** です。


GUIツールはなんでも構いません。Git公式の git-gui や gitk でもよいですし、コミットグラフの表示が可能なIDE付属のGitインターフェースでもよいです。

## コミットグラフとは？

コミットグラフとは次のようなコミット同士のつながりのことです。次の画像は gitk の画面の一部です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15320/187fb370-7fef-4745-98c6-7d19633a0fde.png)

丸がコミットを表しています。黄色い丸は現在作業スペースに展開中のコミットで、それ以外のコミットは青い丸です。

コミット同士をつなぐカラフルな線はコミットの親子関係のつながりを表しています。コミットは gitk においては上に行くほど子孫、下に行くほど祖先といった具合に並んでいます。

緑の四角はブランチ（ブランチヘッド）を表しています。Gitにおいてブランチとは永続的にコミットが所属する名前のついた枝が存在するわけではなく、実は図のようにコミットにつけられた単なるラベルです。ブランチをチェックアウトしてコミットするとそのラベルがついた場所に新しいコミットが作られていき、結果として枝が構成されます。このラベルは構成される枝の先頭を指し示すと考えることができるので「ブランチヘッド」と呼ばれます。

## GUIツールでコミットグラフを確認する理由

私の理解では、バージョン管理はGitに限らず本質的にコミットグラフを操作することと等しいです。コミットグラフを確認することで、管理しているバージョンの状態が想定通りであることを視覚的に確認することができます。

Gitは多数のサブコマンドやオプションがあり、習得には大変な困難が伴うツールと思われていますが、実はGitを「コミットグラフを操作するツール」と捉えると各コマンドをシンプルに理解することができるようになります。

例えば次のような感じです：

* `git branch <ブランチ名>`
    * ブランチヘッド（ラベル）を新しく作る
* `git commit`
    * チェックアウト中のブランチヘッドが指すコミットを親コミットとして子コミットを新しく作り、ブランチヘッドをその子コミットへ移す
* `git merge`
    * 基本的に `git commit` と同じだが、複数の親を持つ子コミットを作る
* `git checkout`
    * 指定したコミットを現在の作業スペースに展開する
* `git reset`
    * 現在のブランチヘッドを指定されたコミットに付け替える
* `git rebase`
    * 指定した分岐前の場所から現在のブランチヘッドまでの一連のコミットを別の場所へ移植する
* `git fetch`
    * リモート追跡ブランチ(`git branch -r` で確認できるやつです)の各ブランチヘッドを最新のリモートリポジトリ(originとか)の状況にあわせて付け替える

これらのサブコマンドはコミットグラフおよびそこにつけられたブランチヘッド(ラベル)を操作するサブコマンドです。これらの操作を行う前後でかならずコミットグラフを確認するようにしてください。それにより、操作とコミットグラフの関係性をより正確に理解することができ、結果として Git やバージョン管理の深い理解に繋がります。

## 例外

`git log` のようなリードオンリーの操作や、 `git add` のようなステージングエリアを操作するコマンドはコミットグラフに影響を与えないので、操作の都度コミットグラフを確認する必要はありません。

## まとめ

Git を学ぶときに各種操作の前後で **GUIツールでコミットグラフを確認する** ようにすると、Gitをより深く理解できるようになります。
Cloudflareでメンテナンス画面を作る

Cloudflareのみを利用して、メンテナンスページを作成してみます。

:::note warn
Cloudflareのプロプラン以上になります
:::

Cloudflareの以下の機能を利用します

- Pages
- Snippets

## HTMLを作る

```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>メンテナンス中</title>
  <style>
    body {
      margin: 0;
      padding: 0;
      background-color: #f7f7f7;
      font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100vh;
      text-align: center;
      color: #333;
    }

    .container {
      max-width: 500px;
      padding: 20px;
    }

    h1 {
      font-size: 2.5em;
      margin-bottom: 0.5em;
    }

    p {
      font-size: 1.2em;
      margin-bottom: 1em;
    }

    .logo {
      max-width: 150px;
      margin-bottom: 1.5em;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>ただいまメンテナンス中です</h1>
    <p>ご迷惑をおかけして申し訳ございません。<br>現在、サイトのメンテナンスを行っております。</p>
    <p>しばらくしてから再度アクセスをお試しください。</p>
  </div>
</body>
</html>

```

## CloudflareのPagesにHTMLファイルをアップロード

![スクリーンショット 2025-04-09 20.00.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113764/f777552e-5f0f-429f-ba93-df3e4c2febc9.png)


```
maintenance  
└── index.html
```

:::note warn
HTMLをアップロードする際はフォルダに入れる必要があります。
:::

アップロード完了後はサイトをデプロイします。

## Snippetsの作成

![スクリーンショット 2025-04-09 20.11.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113764/f773c384-0de8-49e3-abd0-97ed689fb553.png)

### スクリプトの追加

```js
// メンテナンスにしないIP
const allowedIPs = [
  "123.456.789.123"
];

export default {
  async fetch(request) {
    const clientIP = request.headers.get("cf-connecting-ip");
    console.log(clientIP)

    if (allowedIPs.includes(clientIP)) {
      // 管理者のIPなので通常処理へ
      return fetch(request);
    }

    // それ以外はメンテナンスページ（Cloudflare Pages）を503で返す
    const response = await fetch("https://xxx.pages.dev/"); // 作成したpagesのURL
    const html = await response.text();

    return new Response(html, {
      status: 503,
      headers: {
        "Content-Type": "text/html; charset=UTF-8",
        "Cache-Control": "no-store",
      },
    });
  },
};

```

![スクリーンショット 2025-04-09 20.12.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113764/0b498420-1e01-406e-b31e-051276919f66.png)


作成したSnippetsを有効にすると、メンテナンスページになります。
ただ、Snippetsのスクリプトで定義したIPはメンテナンスにならず、通常のページへと遷移ができます。

メンテナンスのHTMLはSnippets内のスクリプトに記述しても良かったのですが、
ソースが長くなるので今回はPagesに配置しました。

---

Snippetsの詳細は以下の記事をご参考ください！

https://qiita.com/Alfredo/items/98189eb1d8cd2294bbc3
曜日を取得して表示する

日付を取得して表示

```
@echo off
setlocal enabledelayedexpansion

:: ==== 現在の日付を取得 ====
set "TODAY=%DATE%"

:: ==== YYYY MM DD を抽出 ====
for /f "tokens=1-3 delims=/" %%A in ("%TODAY%") do (
    set "YYYY=%%A"
    set "MM=%%B"
    set "DD=%%C"
)

:: ==== DD に付いた (曜日) を除去 ====
for /f "tokens=1 delims=(" %%X in ("!DD!") do set "DD=%%X"

:: ==== 1月 or 2月なら前年として扱う ====
set /a MMINT=10%MM% %% 100
if !MMINT! LSS 3 (
    set /a MMINT+=12
    set /a YYYY-=1
)

:: ==== ツェラーの公式に必要な値 ====
set /a K=!YYYY! %% 100
set /a J=!YYYY! / 100
set /a q=10%DD% %% 100
set /a m=!MMINT!

:: ==== ツェラーの公式 ====
set /a h=(q + (13*(m+1))/5 + K + K/4 + J/4 + 5*J) %% 7

:: ==== 曜日配列（0=土, ..., 6=金） ====
set WEEKDAYS=土 日 月 火 水 木 金

:: ==== 対応する曜日を取得 ====
set i=0
for %%W in (%WEEKDAYS%) do (
    if !i! EQU !h! (
        set "WEEKDAY=%%W"
    )
    set /a i+=1
)

:: ==== 結果表示 ====
echo 今日の曜日は!WEEKDAY!曜日です

endlocal
pause

```
EXIN BCS SIAM認定がITSMキャリアを飛躍させる理由

今日の急速に進化するIT業界では、複数のサービスプロバイダーを効果的に管理することが、組織の成功にとって重要な要素となっています。多くの企業がマルチソーシングモデルを採用する中、サービスインテグレーションとマネジメント（SIAM）を扱えるプロフェッショナルの需要が高まっています。そこで注目されているのが、EXIN BCS SIAM認定です。この国際的に認められた資格は、複数のサービスプロバイダーにわたるサービス提供を管理するための知識とスキルをITプロフェッショナルに提供します。

すでにITサービスマネジメント（ITSM）の分野で働いている方も、これからキャリアを築こうとしている方も、EXIN BCS SIAM認定を取得することで、キャリアに大きなプラスとなるでしょう。以下に、その理由を詳しくご紹介します。

SIAMの基本とその重要性
**Service Integration and Management（SIAM）**とは、異なるベンダーから提供されるサービスを統合し、シームレスに管理するための方法論です。SIAMは、複数のサービスを一つのまとまりあるユニットとして統合しつつ、ガバナンスと責任体制を維持することに重点を置いています。

企業が複雑なアウトソーシング環境へと移行する中で、SIAMの原則を理解し実践できるプロフェッショナルが求められています。EXIN BCS SIAM認定は、こうした環境での業務能力を証明するものであり、SIAMコンサルタント、サービスインテグレーター、サービスデリバリーマネージャーといった職種に就くための大きな後押しになります。

競争の激しい市場で差をつける
IT業界では常に優れた人材が求められており、特に専門性の高い知識を持つ人材は重宝されます。SIAM認定を取得していることで、マルチベンダー環境に対する理解があることを示すことができ、他の候補者との差別化につながります。

この資格を取得することで、技術的なスキルだけでなく、ガバナンス、プロセス設計、文化統合、ツールの整合性など、現代のITSM職に不可欠な戦略的スキルもアピールできます。

ITILとのギャップを埋める
多くのITプロフェッショナルはすでにITIL認定を持っていますが、ITILは主に社内プロセスに焦点を当てています。複数のサービスプロバイダーが関与する環境における課題には、ITILだけでは対応しきれないことがあります。

EXIN BCS SIAMは、ITILの枠組みを拡張し、マルチベンダー環境でのサービスマネジメントを可能にする知識を提供します。これは、ITILと補完的な関係にあり、現場で直面する知識のギャップを埋めるのに非常に効果的です。

収入アップの可能性
資格取得は一般的に収入の向上と相関があり、SIAMも例外ではありません。ベンダー関係の管理やインテグレーションプロジェクトをリードできる人材の需要が高まる中、SIAM認定者の給与も上昇傾向にあります。

問題解決力とコラボレーションスキルの向上
SIAMは単なるプロセスやツールの話ではなく、「人」や「文化」、「協力体制」にも焦点を当てています。この認定を通じて、異なる組織間の関係をどう築くか、対立をどう解消するか、そして協力的な文化をどう促進するかといったスキルも身につきます。これはリーダーシップを発揮する上で非常に重要です。

認定取得のための準備
EXIN BCS SIAM Foundationはエントリーレベルの資格で、SIAMの原則、役割、実践、課題について学ぶことができます。学習には認定トレーニングコースや公式教材が役立ちます。さらに、試験準備にはpractice questionsを活用することで、理解度をチェックし、弱点を把握するのに非常に効果的です。
https://www.certboosters.com/exin/path/exin-bcs-siam


EXIN BCS SIAM認定は、単なる資格以上の価値を提供します。それは、キャリアを加速させるパスポートとも言えます。複数のサービスプロバイダーに依存する現代のIT環境において、サービスインテグレーションを成功に導ける人材は非常に貴重です。この認定を取得することで、組織にとっての戦略的な存在となり、ITSM分野での新たなチャンスを切り開くことができるでしょう。
【Rails】Integerの=~でエラーが出る

## はじめに
Ruby 3.2 では、`Integer` クラスにおける `=~` 演算子の使用ができなくなりました。これにより、以前のバージョンで動作していたコードがエラーを引き起こす可能性があります。

## `=~` 演算子とは？

`=~` は Ruby で主に正規表現マッチングに使用される演算子であり、通常は `String` や `Regexp` のマッチング処理に使用されます。

```ruby
puts 'hello' =~ /ell/  #=> 1 （マッチした位置を返す）
puts 'hello' =~ /xyz/  #=> nil （マッチしない場合は nil）
```

以前の Ruby では、`Integer` に `=~` を使用すると `nil` を返していました。

```ruby
puts 42 =~ /42/  #=> nil （Ruby 3.1 以前ではエラーにならない）
```

しかし、Ruby 3.2 ではこの動作が削除され、`Integer` に対して `=~` を使用するとエラーが発生します。

## Ruby 3.2 における変更点

Ruby 3.2 では、`Integer` クラスにおける `=~` のサポートが削除され、以下のようなコードは `NoMethodError` を引き起こします。

### Ruby 3.1 以前

```ruby
42 =~ /42/  #=> nil （特に意味はないがエラーにはならない）
```

### Ruby 3.2 以降

```ruby
42 =~ /42/  #=> NoMethodError: undefined method `=~' for 42:Integer
```

### 回避策
`Integer` と `Regexp` の比較を行う場合は、明示的に `to_s` を使用する。

```ruby
42.to_s =~ /42/  #=> 0
```

## 参考
https://zenn.dev/tmtms/articles/202212-ruby32-5#object%23%3D~
SharePointのリンクコピーが長すぎるので、少しだけ何とかする

そもそも標題を何とかしようとした理由ですが、Excelなら皆が抵抗なく触れるので、Excel⇒Htmlでリンク集を作っています。当然Hyperlink関数を使いますが、SharePointのリンクをコピーしてHyperlink関数に貼ると、リンクが長すぎて、以下事象が発生します。

    事象
    ・Hyperlink関数で読める文字数に制限があり、リンク先に飛べない。
    ・Hyperlinkの文字で、リンク先が、即座にわからない。

解決策は短縮URL使ったり色々ありそうですが、そもそも日本語がURLエンコーディングかかっているから文字数が長くなっているので、一旦日本語に戻せばよいのではないか？ということでシンプルに日本語に戻すことのみで解決しました。
日本語への戻し方も、幾つか並べておきます。

## 解決策１
　『すべてのドキュメント』⇒『エクスプローラで表示』で、
　 エクスプローラ上のアドレス欄からコピーし/{ファイル名}を追加
　　https://<foo>o365kddi.sharepoint.com</foo>/sites/xxxxx/Shared Documents/{ファイル名}

## 解決策２
　AIチャットにURLデコーディングを頼んでみる。（複数変換するのであればプログラム書いても良いかもしれませんが・・・数件なら・・）

## 
まだフォルダを作っていないのであれば、最初に全部英字でフォルダつくって改名する方法もあるはずです。
余りにもシンプル過ぎてか、誰も書いてないですが、困ってる人もいるかもしれないと思ったので記載してみました。
【Tera Term】2台以上のArduinoと同時にシリアル通信を開始する方法

# 1. はじめに
Tera Termを使って複数のArduinoとシリアル通信するとき，手動だと通信の確立とログ保存を台数分やらないといけないので煩雑です．
portとbaudrateを設定したTTLファイルを開けば通信の確立は容易ですが，ログ保存がやはり面倒です．
そのため，2台以上のArduinoに対して，
(1) シリアル通信確立
(2) ログ保存
が簡単にできるような方法をまとめました．

※厳密には開く順序があり数msのラグがあるかもしれませんが，今回はそこまでの精度を求めない人向けです．検証はまた後日．

# 2. 方法
## (1) TTLファイルを用意
接続するArduinoの台数分，以下の内容を記載したTTLファイル(.ttl)を用意します．
メモ帳を開いて.txtを.ttlに書き換えるだけでOKです．
$USERNAMEはPCのユーザネームに変更してください．
``` com4.ttl
; 日付取得 "2025-04-09"
getdate dateStr
;messageBox dateStr "今日の日付"
; 時刻取得 "15: 43: 21"
gettime timeStr
;messageBox timeStr "今の時刻"

; 年の取り出し（1〜4文字目）
strcopy dateStr 0 4 year
; 月の取り出し（6〜7文字目）
strcopy dateStr 6 2 month
; 日の取り出し（9〜10文字目）
strcopy dateStr 9 2 day
; 時 (:をファイル名に含めるとエラーが出るので注意)
strcopy timeStr 0 2 hour
; 分
strcopy timeStr 4 2 min
; 秒
strcopy timeStr 7 2 sec

; ファイル名構築
fileName = ""
strconcat fileName year
strconcat fileName month
strconcat fileName day
strconcat filename "-"
strconcat fileName hour
strconcat fileName min
strconcat fileName sec

; "_com4.log"を付ける（COMポート等に応じて適宜変更）
strconcat fileName "_com4.log"

; 保存するフルパス（"download" フォルダに保存）
strconcat logPath "C:\\Users\\$USERNAME\\Downloads\\"
strconcat logPath fileName

; シリアル通信開始 /C:ポート /BAUD:ボードレート
connect '/C=4 /BAUD=9600'

; 通信確立したかチェック
if result = 0 then
    messagebox 'COM4への接続に失敗しました' 'エラー'
    end
endif

; ログ保存
logopen logPath
```

## (2) バッチファイルを用意
以下の内容のバッチファイル(.bat)を用意します．
`start`はexeを実行するコマンドです．
第1引数: ウィンドウにタイトルを付けられるのですが，不要なので`""`にしています．
第2引数: ttermpro.exeが格納されているパス．
インストールされているteratermのバージョンやPC構成によってはttermpro.exeのパスが違うので，その場合は調整してください．
第3引数: `/M=`の後は(1)で作成したTTLファイルのパスを記載してください．
``` teraterm.bat
@echo off
start "" "C:\Program Files (x86)\teraterm5\ttermpro.exe" /M=C:\Users\$USERNAME\Downloads\com4.ttl
start "" "C:\Program Files (x86)\teraterm5\ttermpro.exe" /M=C:\Users\$USERNAME\Downloads\com5.ttl
```

作成したバッチファイルを開くとTera Termが起動しシリアル通信を開始します．
そして設定したファイル名でログファイルが作成されます．

# 3. おわりに
これでバッチファイルを実行するだけでログファイルへの書き出しまで自動化されました．
めでたしめでたし．
ログ書き出しのタイミングを同期したい場合は，すべてのArduinoｎ共通の外部トリガ用スイッチを設け，立ち上がった瞬間から`Serial.println()`を開始すればいいと思います．
ガウス素数

# はじめに
ガウス素数を表示するプログラムです。

（乱数で上下左右斜めに対象な画像を生成しても、似たような感じになってしまうので、絵的にはあんまり、面白くなかったです）

# ガウス素数
例えば、ある複素数zを考え、絶対値(norm)の二乗が素数であるかをチェックします。
```math
z = 2+3i　のとき　|z|^2=2^2+3^2=13
```
13は素数なので、zはガウス素数という考え方。

また、
```math
z = 2-3i　のとき　|z|^2=2^2+(-3)^2=13
```
```math
z = -2+3i　のとき　|z|^2=(-2)^2+3^2=13
```
```math
z = -2-3i　のとき　|z|^2=(-2)^2+(-3)^2=13
```
なので、可視化したときに、複素平面上で上下対象、左右対称になる。
さらに、実部と虚部を入れ替え、
```math
z = 3+2i　のとき　|z|^2=3^2+2^2=13
```
となるので、複素平面上で45度の軸でも対象になる。

下図の白点がガウス素数。
実軸、虚軸の上は４で割ってあまり３となる素数が対象。

```math
\begin{multline}
. \\
\sqrt{2}=\sqrt{1^2+1^2}=1.4142135 \\
\sqrt{5}=\sqrt{1^2+2^2}=2.236068 \\
3 \\
\sqrt13=\sqrt{2^2+3^2}=3.6055512 \\
\sqrt17=\sqrt{1^2+4^2}=4.1231055 \\
\sqrt29=\sqrt{2^2+5^2}=5.3851647 \\
\sqrt37=\sqrt{1^2+6^2}=6.0827627 \\
\sqrt41=\sqrt{4^2+5^2}=6.4031243 \\
7 \\
.
\end{multline}
```

同心円を重ねた。
緑は半径３と７。
赤は半径が上記の数値。


![GaussianPrime同心円.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/ee944b2a-7bb1-477b-b727-bae32cb17509.png)



# 環境
processing 4.2
Complex Numbersライブラリ利用

# プログラム
第一象限だけ計算しています。Y軸反転なので、左上が原点(0+0i)です。
サイズはwikiの画像サイズに合わせました。
![GaussianPrime.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/aab05cae-bdf2-40c8-9433-995c83d53f42.png)

```java:Processing
void setup() {
  size(384, 384);
  background(0);
  fill(0);

  for (int a = 0; a <= 384; a++) {
    for (int b = 0; b <= 384; b++) {
      if (a == 0 && b == 0) continue;
      if (isGaussianPrime(a, b)) {
        set(a, b, 0xFFFFFFFF);
      }
    }
  }
  //save("GaussianPrime.png");
}

boolean isGaussianPrime(int a, int b) {
  if (a == 0) {
    return isPrime(b) && b % 4 == 3;
  }
  if (b == 0) {
    return isPrime(a) && a % 4 == 3;
  }
  int norm = a * a + b * b;
  return isPrime(norm);
}

boolean isPrime(int n) {
  if (n < 2) return false;
  for (int i = 2; i <= sqrt(n); i++) {
    if (n % i == 0) return false;
  }
  return true;
}
```

# 参考サイト

https://en.wikipedia.org/wiki/Gaussian_integer

https://qiita.com/hextomino/items/47a5a4207df0522df770
大学生が母の誕生日に思い出を振り返るアプリを作ってプレゼントした話

# 母の誕生日に贈る、思い出を振り返る体験型ゲーム「Omoide」

今回は、母の誕生日にUnityで制作した体験型ゲーム「Omoide」をプレゼントした経験を共有します。

この記事では、ゲームの概要と具体的な内容を紹介し、次回の記事で技術的な詳細をお伝えする予定です。

## 1. どんなゲームを作ったのか

動画のようなゲームをUnityｄ作成しました。

<iframe width="560" height="315" src="https://www.youtube.com/embed/FnwKtiLX8MM?si=WNOfrYKPVpZuzUvO" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>




### 1.1 きっかけ

今年度から東京で一人暮らしを始めましたが、実家の母が何度も私の住む街へ来てくれて、一緒に様々な場所を訪れました。これまで当たり前のように一緒にいた母との時間が特別なものに感じられ、その温かい思い出を形に残る特別なプレゼントとして贈りたいと思いました。

そこで思いついたのが、「思い出を美術館に」というコンセプトのアプリです。

### 1.2 ゲーム概要

「Omoide」は、First Person視点で美術館内を自由に探索できるアドベンチャーゲームです。以下がゲームの主な特徴です。

* コンセプト: 記念日（誕生日、結婚記念日など）に贈る、思い出を振り返る体験型ゲーム
* ジャンル: アドベンチャー、体験型
* 視点: First Person
* プレイ時間: 10分未満（何度も繰り返し楽しめる）
* ターゲット層: 大切な人に特別なプレゼントを贈りたいユーザー

### 1.3 インスピレーション

自分自身、美術館、美術館巡りが好きで、「美術館に飾られているものは特別」というイメージがあります。インスピレーションを得たのは、最近実家に帰省した時に姉が大学のゼミの思い出の写真をLINEスタンプにしているのを見て、「思い出を残すことって価値があるなー」と思った時です。

↓参考にした美術館イメージ画像

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617200/05bd3336-2f72-4284-9542-46a32771f860.jpeg" width=50%>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617200/64c10acf-5f30-4775-bac4-8e094105776c.jpeg" width=42.3%>

## 2. ゲームの具体的な内容

### 2.1 ゲームプレイの流れ

「Omoide」のゲームプレイは、大きく分けて以下の2つのフェーズで構成されています。

---
* 写真・動画登録フェーズ:
    * スマートフォン内から思い出の写真や動画を選択
    * 登録完了後、美術館フェーズへ
<br/>
    <img width=15%>
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617200/9e9675fd-926f-4334-ba0b-5877a8db60c6.png" width="50%">


---
* 美術館探索フェーズ:
    * First Person視点で美術館内を自由に探索
    * 壁に飾られた写真や動画を鑑賞
<br/>
    <img width=15%>
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617200/6acf4e87-fe1e-458a-bc6e-0decfd715fad.png" width="50%">


### 2.2 美術館の探索

美術館は幻想的で美しい雰囲気のデザインにしました。具体的に以下のような特徴があります。

* 自由な探索: First Person視点で美術館内を自由に歩き回れる
* 特別な演出: 柔らかな照明と鮮やかなシェイダー設定で雰囲気を演出

### 2.3 技術的な特徴

「Omoide」の開発では、以下の技術的な要素が使われています。

* Unity: ゲームエンジンとしてUnity 2022.3.xを使用
* First Person視点: Unityの「Starter Assets - FirstPerson」パッケージを活用
* Native Gallery連携: スマートフォンのギャラリーから写真・動画を取得
* インタラクションシステム: レイキャストを用いた展示物との対話機能
* メディア表示システム: 写真や動画を適切にレンダリングする仕組み

### 2.4 プレゼントとしての効果

このゲームを母の誕生日にプレゼントした際の反応は、期待以上でした。実際の思い出の場所が美術館として再現され、そこに思い出の写真や動画が飾られている体験は、通常のアルバムやスライドショーよりもはるかに感動的な体験となったようです。

何より、「自分の子どもがプログラミングで作ってくれた」という点が、特別な価値をもたらしたと思います。

## おわりに

この記事では「Omoide」の概要と具体的な内容を紹介しました。次回の記事では、このゲームの制作過程や技術的な詳細、工夫した点などをより深く掘り下げていく予定です。

次回もお楽しみに！

次回予告：「大学生が母の誕生日に思い出を振り返るアプリを作ってプレゼントした話【技術編】」では、Unity開発の詳細や、First Person視点の実装方法、Native Galleryとの連携方法、美術館の演出テクニックなどを解説します。
【kintoneノーコード開発】「レコードの一覧」画面の編集仕様についてまとめてみた

# はじめに
こんにちは、現在kintoneノーコード開発で日々試行錯誤しているばんちゃん（[@Banchan_k12](https://x.com/Banchan_k12)）です。
今回は、kintoneの「レコードの一覧」画面からレコード編集する仕様について、通常使っているけど改めて確認してみようと思います。

### 対象
- 「レコードの一覧」画面の編集仕様について確認したい方
- 詳細画面への遷移編集が手間だな～と思っている方

# レコードの編集方法
レコードの編集方法には以下の方法があります。

:one:一覧画面に表示されているレコードのファイルマークをクリックして詳細画面へ移動して、編集ボタンから1レコードずつ編集する方法
![20250407_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/1ce4e9fc-d186-44ba-970d-5e9f79b518bf.jpeg)


:two:ExcelファイルやCSVファイルをアプリに読み込んで、複数レコードをまとめて上書き（一括更新）する方法
![20250407_6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/60321ffe-bbf3-4760-8703-9c40fbf24145.jpeg)



:three:右端の「編集する」（鉛筆マーク）を押して一覧画面のまま内容を編集する方法

:::note info
「レコードの一覧」画面で編集したいレコード行の上をダブルクリックしても編集が開きます。
:::

![20250407_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/af42a603-355c-4596-930a-20075945b6dd.jpeg)

内容を編集完了したら、「保存する」を押して更新
![20250407_7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/4a08486f-42ac-4614-b0b2-bb93489fedc2.jpeg)

# 「レコードの一覧」画面での編集仕様
:loudspeaker:【ルックアップフィールド】など「レコードの一覧」画面で編集できないフィールドがあります。こちらで編集できないフィールドは詳細画面からの編集となります。
![20250407_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/db92e754-278a-4288-bf94-2a407a3020ba.jpeg)

:::note info
kintone ヘルプ
[「レコードの一覧」画面で編集できるフィールド](https://jp.cybozu.help/k/ja/id/040718.html#using_app_edit_record_30 "「レコードの一覧」画面で編集できるフィールド")
:::

:loudspeaker:「レコードの一覧」画面で編集の設定をしたくない場合は、下記の通り無効にすることができます。

:::note info
kintone ヘルプ
[レコード一覧でのレコードの直接編集と削除を無効にする](https://jp.cybozu.help/k/ja/id/040833.html "レコード一覧でのレコードの直接編集と削除を無効にする")
:::

「高度な設定」から「レコード一覧でのインライン編集」の:white_check_mark:を外すと
![20250407_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/85ac3829-549c-4266-843c-fd26315e50e6.jpeg)

下記の通り、「編集」「削除」アイコンが表示されなくなります
![20250407_5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/254eb5a1-fcf8-4ef5-be68-392c150958d5.jpeg)


# まとめ
#### 「レコードの一覧」画面で編集について良いなと思う点
- 詳細画面に遷移する手間が省け、作業効率が向上し、ユーザーの負担が減少する
- 一覧上で変更可能なので、複数データを順次短時間で修正できる
- 変更、保存が即座にでき、すぐに確認できる

#### 「レコードの一覧」画面で編集について注意が必要だと思う点
- 編集がすぐにできる分、変更対象でないデータの誤削除やデータ変更をしてしまう可能性がある
- 容易に編集がかけられるため、適切なアクセス制御や管理が必要
- プラグインやカスタマイズ設定について注意が必要

「レコードの一覧」画面での編集作業は編集項目が多い場合など、一覧で確認しながら手早くできるのでいいですね。
Viteでマルチエントリーポイントを活用した開発

## はじめに
Viteは通常シングルページアプリ（SPA）に使われますが、マルチエントリーポイントを設定することで、複数の独立したページを持つアプリも効率的に開発できます。この記事では、マルチエントリーポイントを活用し、管理画面と公開ページを持つアプリを作ります。

## マルチエントリーポイントとは？
マルチエントリーポイントは、1つのプロジェクトで複数のHTMLファイルをエントリーとして管理する手法です。  
- **利点**: ページごとに異なるコードを分離、独立したデプロイが可能。  
- **活用例**: ダッシュボードとランディングページを1つのリポジトリで管理。

## プロジェクトの準備
ReactベースのViteプロジェクトを用意：
```bash
npm create vite@latest my-multi-entry -- --template react
cd my-multi-entry
npm install
```

### HTMLエントリーの追加
- `index.html`（デフォルト）をランディングページに。
- 新規に`dashboard.html`を作成：
```html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>ダッシュボード</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/dashboard.jsx"></script>
  </body>
</html>
```

## 設定のカスタマイズ
### 1. エントリーポイントの設定
`vite.config.ts`を更新：
```typescript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  build: {
    rollupOptions: {
      input: {
        main: './index.html',
        dashboard: './dashboard.html',
      },
    },
  },
});
```

### 2. 各エントリーのコード
- `src/main.jsx`（ランディングページ用）：
```jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <div>
      <h1>ランディングページ</h1>
      <p>ようこそ、こちらは公開ページです。</p>
    </div>
  </React.StrictMode>
);
```

- `src/dashboard.jsx`（管理画面用）：
```jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './dashboard.css';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <div>
      <h1>ダッシュボード</h1>
      <p>管理画面へようこそ。</p>
    </div>
  </React.StrictMode>
);
```

### 3. CSSの分離
- `src/index.css`：
```css
body {
  font-family: Arial, sans-serif;
  text-align: center;
  background-color: #f0f0f0;
}
h1 {
  color: #282c34;
}
```

- `src/dashboard.css`：
```css
body {
  font-family: Arial, sans-serif;
  text-align: center;
  background-color: #e0e0e0;
}
h1 {
  color: #61dafb;
}
```

## 開発とビルド
### 開発モード
```bash
npm run dev
```
- `http://localhost:5173/`でランディングページ。
- `http://localhost:5173/dashboard.html`で管理画面。

### ビルド
```bash
npm run build
```
`dist/`に`main`と`dashboard`の資産が生成。プレビュー：
```bash
npm run preview
```

## 活用例
- **MPAの構築**: 管理画面と公開ページを分離しつつ、共有コンポーネントを`src/components/`で管理。
- **パフォーマンス**: 各ページが独立しているため、不要なコードの読み込みを回避。

## 動作確認
ビルド後、両方のページが正しく表示され、スタイルが適用されているか確認してください。

---

この記事が役に立ったら、ぜひ「いいね」や「ストック」をお願いします！質問や感想はコメント欄で気軽にどうぞ。Viteの柔軟性を活かして開発を楽しんでください！
Arduinoで高速PWM:レジスタから設定

# 目的
Arduinoを使い始めて、そろそろ10年超えそうです。
10年経っても結局Arudinoが安いし、使い勝手がいいですね。
ESPという選択もありますが、ESPほどの性能は必要ないときの方が多いので結局Arudinoを使ってしまいます。

PWMを100kHz単位で出す場合、タイマー関数では精度が全く出ません。多重割り込みを起こしている可能性もあります。16MHz動作クロックなので、大丈夫な気もしますが

ということで、レジスタで設定する方法を備忘録として残します。

作成途中に見つけたおすすめサイト（このサイト見れば全部解決してる気がする）

https://elchika.com/article/1b95dfe9-efd3-4581-b9dd-3a932917d240/

# レジスタ設定 : Fast PWM : timer1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/363e96a7-ff48-4937-aea9-53482e86f30b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/5e5e74f0-7a5a-4bb7-867d-ca5bcedd9378.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/7bbf5599-71ef-47fd-95a5-1e1d7ee69c7b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/3572c731-3650-4880-9ddc-73af34625b64.png)


周波数可変Fast PWMモードを使うには、mode 15か14です。mode14の場合でやります。
```
WMG13 = 1
WMG12 = 1
WGM11 = 1
WGM10 = 0
```

コンペアマッチについて解説します。
```
OCR1A/OCR1Bとカウンターが同じ値になるとハードウェア的に下記の動作が発生します。

COM1*1/COM1*0 = 0/0 →不動作
COM1*1/COM1*0 = 0/1 →コンペアマッチでトグル
COM1*1/COM1*0 = 1/0 →下限で1、コンペアマッチで0
COM1*1/COM1*0 = 1/1 →下限で0、コンペアマッチで1

portは
OCR1A　： pin9
OCR1B  : pin10
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/f14f4fc2-d043-4540-95b0-b352b504d191.png)

プリスケーラの解説

```
CS12/11/10 = 0/0/0 →　不動作
CS12/11/10 = 0/0/1 →　16MHz:62.5ns
CS12/11/10 = 0/1/0 →　2MHz:500ns
CS12/11/10 = 0/1/1 →　250kHz:4us
CS12/11/10 = 1/0/0 →　62.5kHz:16us
CS12/11/10 = 1/0/1 →　15.625kHz:64us
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/27072d4c-9d3d-4773-b637-df288c56793e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/b092c37a-63fd-4760-bb1f-090578230374.png)

# 設定例100kHzPWM

```
WMG13 = 1
WMG12 = 1
WGM11 = 1
WGM10 = 0
COM1A1/COM1A0 = 1/0 →下限で1、コンペアマッチで0
OCR1A　： pin9
CS12/11/10 = 0/0/1 →　16MHz:62.5us

100kHz:10us → 10us/62.5ns = 160
ICR1 = 160-1
```

プログラム

```C++
void setup() {

  Serial.begin(9600);
  pinMode(9,OUTPUT);
  digitalWrite(9,LOW);
  
  /*タイマ1初期化*/
  TCCR1A = 0;
  TCCR1B = 0;
  
  /* OC1A,OC1B 40kHz出力
   * PWMモード:Fast PWM
   * 分周比:1
   * TOP:ICR1 = 160 - 1
   * OCR1A:コンペアマッチLOW
   * OCR1B:コンペアマッチLOW
   */
  TCCR1A |= (1 << WGM11) | (1 << COM1A1);
  TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1 << CS10);
  ICR1 = 160 - 1;
  OCR1A = 10;
}

void loop() {
  

}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/5ea522de-74cc-4fea-94f8-c09e10371a24.png)

問題なさそうです。
ViteとSSGで作る軽量サイト



## はじめに
Viteは高速な開発体験を提供するビルドツールですが、静的サイトジェネレーション（SSG）にも活用できます。SSGを使えば、SEOに強く軽量なサイトを簡単に作れます。この記事では、ViteでSSGを実践し、シンプルなサイトを構築します。

## SSGとは？
SSG（Static Site Generation）は、ビルド時にHTMLを事前生成する手法です。  
- **利点**: 高速な読み込み、SEO対策が容易、サーバー負荷の軽減。  
- **Viteの適性**: 高速ビルドとシンプルな設定でSSGに最適。

## プロジェクトのセットアップ
Reactベースのプロジェクトを用意します。ターミナルで以下を実行：
```bash
npm create vite@latest my-ssg-site -- --template react
cd my-ssg-site
npm install
```

SSG用にプラグインを追加：
```bash
npm install vite-plugin-ssg --save-dev
```

## 静的ページの生成
### 1. ルーティングの設定
`src/pages`フォルダを作成し、ページを追加：
- `src/pages/Index.jsx`:
```jsx
export default function Index() {
  return (
    <div>
      <h1>ホーム</h1>
      <p>ようこそ！</p>
    </div>
  );
}
```
- `src/pages/About.jsx`:
```jsx
export default function About() {
  return (
    <div>
      <h1>このサイトについて</h1>
      <p>Viteで作られた静的サイトです。</p>
    </div>
  );
}
```

### 2. vite.config.tsの設定
`vite.config.ts`を更新：
```typescript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { VitePluginSsg } from 'vite-plugin-ssg';

export default defineConfig({
  plugins: [
    react(),
    VitePluginSsg({
      routes: ['/', '/about'],
    }),
  ],
});
```

### 3. メインエントリーの調整
`src/main.jsx`を更新：
```jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import Index from './pages/Index';
import About from './pages/About';

const routes = {
  '/': Index,
  '/about': About,
};

const App = () => {
  const path = window.location.pathname;
  const Component = routes[path] || Index;
  return <Component />;
};

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
```

## ビルドとプレビュー
ビルドを実行：
```bash
npm run build
```
`dist/`に静的ファイルが生成されます。プレビューで確認：
```bash
npm run preview
```
`http://localhost:4173/`と`/about`にアクセスし、ページが表示されるかテスト。

### SEO対策の追加
`src/pages/Index.jsx`にmetaタグを追加：
```jsx
import { Helmet } from 'react-helmet';

export default function Index() {
  return (
    <div>
      <Helmet>
        <title>ホーム | Vite SSG</title>
        <meta name="description" content="Viteで作った軽量な静的サイト" />
      </Helmet>
      <h1>ホーム</h1>
      <p>ようこそ！</p>
    </div>
  );
}
```
`react-helmet`をインストール：
```bash
npm install react-helmet
```

## デプロイ
Netlifyにデプロイします：
1. `dist/`フォルダをドラッグ＆ドロップでアップロード。
2. または、GitHubリポジトリと連携し、ビルドコマンドを`npm run build`、出力ディレクトリを`dist`に設定。

完成したサイトは、例えば`https://my-ssg-site.netlify.app/`で公開されます。

## 動作確認
デプロイ後、ホームとAboutページが正しく表示され、SEOタグが反映されているか確認してください。

---

この記事が役に立ったら、ぜひ「いいね」や「ストック」をお願いします！質問や感想はコメント欄で気軽にどうぞ。Viteで軽量なサイト作りを楽しんでください！
UnityでSpineに2DLightで光るフレネルシェーダーを実装してみた

# 概要
UnityでSpineを使用する際、シェーダーは正しく描画するためSpine公式が提供するシェーダーを使用する必要があります。しかし、このシェーダーはバラバラのパーツを描画するためのコードベースなシェーダーでさらに追加の機能を持たせるのは難易度が高く、非効率的です。
そこでSpine公式が提供している**SkeletonRenderTexture**を使用しShaderGraphで簡単に追加の描画をする方法の解説です。

### SkeletonRenderTextureとは
Spineは通常、他のオブジェクト同様１つRenderTexture（仮にCameraTargetTextureとします）に描き加えられていきます。
しかしSkeletonRenderTextureを使用すると、そのSpine専用のRenderTextureを用意し、一旦そのRenderTextureにCommandBufferで前もって描画します。その後通常と同じ描画タイミングでCameraTargetTextureに描き戻します。

この描き戻す際のTextureを描画するだけの単純なシェーダーでいいので、このシェーダーにフレネルなど追加したい機能を追加するのが簡単だよねという仕組みです。

負荷についてはSpineごとに描画する範囲のRenderTexture1枚分のメモリ負荷と描き戻しの描画負荷だけなのでほとんど大したことない認識です。

Spineが1枚のTextureになるので半透明にした際パーツが透けないようにできたりもします。（むしろそっちがメインの用途だと思います）

# 環境
- Unity 6000.0.23f1 (2DRenderPipeline)
- Spine 4.2.40
- spine-unityランタイム 4.2（SkeletonRenderTextureはSpineExamplesにあります）

導入方法はSpine[公式ドキュメント](https://ja.esotericsoftware.com/spine-unity#Unity)を確認してください。

# 実装
:::note warn
※
SpineAssetのインポートなどのやり方は省略します。
:::

### SkeletonRenderTexture

1. SpineのGameObject[^1]にAddComponentでSkeletonRenderTextureを追加します
1. SkeletonRenderTextureのプロパティのQuad Materialにフレネルシェーダーを使用するマテリアルをアタッチします

### 2DLightで光るフレネルシェーダーグラフ
2Dなので本来のフレネルとは違いテクスチャの境界の数ピクセルに2DLightのライトテクスチャを加算させる処理をしています。

1. 2DLightTextureというノードでライトテクスチャを取得できるのでサンプルするUVをScreenPositionのノードでスクリーン座標にすることで2DLightのカラーを取得できます
1. SkeletonRenderTextureで描画したRenderTextureのAlphaを使用し微妙にずらしたUVでテクスチャの境界部分を抽出します
1. 2DLightのカラーと抽出した境界部分を乗算し、さらに通常のサンプルしたカラーに加算してあげれば完成です

フレネル以外にも機能追加してますが1~3の部分です。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054619/9ca094c3-8b2b-413d-a9ad-5fe37c50c962.png)

描画結果
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054619/cea37568-b89a-4556-9b4e-5a39de8f36b7.png)

# まとめ

SkeletonRenderTextureはあくまでサンプルなので色々応用が利くと思います。用途に合わせてカスタマイズしたりして便利に使えると思います。個人的にはRendererFeatureで動くようにしてみたいです。

また、2DRenderPipelineや2DLightに関しても説明しなかったのｄそのうち記事書こうと思います。

[^1]: MeshFilterやMeshRenderer、SkeletonRendererを継承してるSkeletonAnimationが追加されてるGameObject
Viteで始める高速Web開発 | 第8章: 総括と次のステップ

## はじめに
第7章までで、Viteを使ったReactアプリを構築し、TypeScriptとテストを追加しました。今回はシリーズを振り返り、学んだことをまとめ、次の学習ステップを提案します。

## 目標
- Viteシリーズの成果を総括する  
- 学んだ教訓を共有する  
- さらなる学習リソースとプロジェクト案を提供する  

## シリーズの振り返り
1. [**第1章**: Viteの紹介と初期設定。](https://qiita.com/BNR-Long/items/2d4eb24f3e8b79724100)
2. [**第2章**: プロジェクト構造と仕組み。](https://qiita.com/BNR-Long/items/5f471f5703cc8b8529e5)
3. [**第3章**: Reactを使ったToDoリスト作成。](https://qiita.com/BNR-Long/items/e98aa1733499e404e6a0)
4. [**第4章**: HMR、プラグイン、環境変数の活用。](https://qiita.com/BNR-Long/items/de53d48cd269366c7b40)
5. [**第5章**: 本番ビルドとVercelデプロイ。](https://qiita.com/BNR-Long/items/33a0ed7e71dc1ab2fae0)
6. [**第6章**: バックエンドとのAPI連携。](https://qiita.com/BNR-Long/items/a443a6309a4ad825e630)
7. [**第7章**: TypeScriptとVitestで強化。](https://qiita.com/BNR-Long/items/dd4fb0871b31c6a73fcc)

これで、Viteを使った高速なWeb開発の基礎を習得しました！

## 学んだ教訓
- **スピードの重要性**: Viteの高速な開発サーバーで作業効率が向上。
- **柔軟性**: プラグインや設定でカスタマイズが容易。
- **型安全**: TypeScriptでバグを早期発見。
- **テスト**: Vitestで品質を保証。

## よくある課題と解決策
- **依存関係のエラー**: `npm install`で最新バージョンを確認。
- **プロキシ設定ミス**: `vite.config.ts`の`proxy`を正確に設定。
- **テストのカバレッジ不足**: モックやスナップショットを追加。

## 次のステップ
### 学習リソース
1. **Vite公式ドキュメント**: プラグインや設定の詳細を学ぶ。
2. **React + TypeScriptガイド**: 型付けのベストプラクティスを習得。
3. **Vitestドキュメント**: テストのカスタマイズを深掘り。
4. **オンラインコース**: Udemyの「Vite入門」や「フルスタック開発」。

### プロジェクト案
- **ブログアプリ**: Markdownサポートとコメント機能を追加。
- **チャットアプリ**: WebSocketでリアルタイム通信を実装。
- **ECサイト**: カートと決済機能をViteで構築。

## 最後に
Viteは高速で柔軟な開発体験を提供し、Reactとの相性も抜群です。このシリーズで学んだスキルを基に、あなただけのアプリを作ってみてください。可能性は無限です！

---

この記事が役に立ったら、ぜひ「いいね」や「ストック」をお願いします！質問や感想はコメント欄で気軽にどうぞ。これからも一緒に成長しましょう！
Dockerfile内でRUN mkdirしても何故かディレクトリが作成されない

# 結論

* ボリュームマウントしているディレクトリ配下のDockerfileによる変更は全て消えるので、ディレクトリをホスト側で作成しておくか、ボリュームマウントに含まれないディレクトリに変更する。

# 現象

```dockerfile:./docker/Dockerfile
FROM python:latest
RUN mkdir -p /app/data/hoge && echo "hello" > /app/data/hoge/sample.txt
```
```docker:./docker-compose.yaml
services:
  web:
    build:
      context: ./
      dockerfile: docker/Dockerfile
    volumes:
      - ./local_data:/app/data # hogeディレクトリの上位ディレクトリをマウント
```

* docker compose up -dで起動してexecでコンテナ内にログインすると/app/data内にhogeディレクトリがある想定だが見てみるとファイルどころかディレクトリも存在しない

# 原因

* ボリュームマウントされているディレクトリの中身はマウント元の内容に上書きされてしまうのが原因
* 処理の順番がdockerfileの処理→ボリュームマウントなのでdockerfile内で処理した内容が全て消える
    * ボリュームマウントした後ならdocker内でmkdirした内容がマウントによってホスト側に反映されるが残念ながら順番が逆
* ファイルコピーなどの場合も同様の挙動になるので注意。
    * Dockerfile内でマウントしているディレクトリ下にディレクトリを生成してその配下にファイルコピーすると直感的に考えてファイルが残りそうだが実際はマウント前なのでファイルが消えてしまい混乱しがち。
        * マウント元に元々あるディレクトリにDockerfile内でファイルをコピーするとこちらはちゃんとコピーされるので余計混乱する

# 対応策

* Dockerfile内でmkdirせずにホスト側でディレクトリをあらかじめ作成しておく
* マウントボリューム外にディレクトリを作成する
* Dockerfile内にENTRYPOINT ["/entrypoint.sh"]の記述を追加し、entrypoint.sh内でディレクトリを生成する（未検証）
    * entrypoint.shの実行タイミングはボリュームマウントの後らしい
🎮ゲームプログラミングの成果を目で見よう！無料で学べる2Dマッチゲーム作成🎉

こんにちは、韓国在住のsanaです！

今日は、プログラミングやIT勉強をしているみなさんにぴったりな無料の学習リソースを紹介します！🎓 今回の講座「高性能エンジンで作る2Dマッチゲーム」では、実際に目に見える成果を作りながら学べるので、今までの勉強の成果を実感できること間違いなし！🌟

📌プログラミングの勉強って、どうしても結果が目に見えにくいことがありますよね。でも、実際にゲームを作ることで、進んでいる実感が持てるんです！こんな風に、成果を実感しながら学ぶことができるからこそ、もっと頑張りたくなる気持ちが湧いてきますよ😊

この講座は無料なので、ぜひみなさんも気軽に挑戦してみてくださいね！💻💡 
ゲームを作りながら学ぶことで、楽しくスキルアップできますよ✨　ファイティン！

https://u.inf.run/4csjpU3
【Excel VBAベーシック】個人用マクロブック

## 個人用マクロブック
### 定義
Excel起動時に自動で読み込まれるブック

### 補足
・ファイル名は「**PERSONAL.XLSB**」
・拡張子は「**xlsb**」
・「**XLSTART**」フォルダに格納される

個人用マクロブックは、任意のブックを開いたときに自動的に起動するブックである。個人用マクロブックにマクロを保存しておけば、他のブックから呼び出すことが出来る。頻繁に行う処理をマクロとして保存しておくと便利である。ブックのファイル名は「**PERSONAL.XLSB**」で、拡張子は「**xlsb**」という見慣れないものである。また、個人用マクロブックの保存先フォルダ名は「**XLSTART**」という名前である。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387980/b7638995-fb01-4a80-9e76-d0514b2330ea.png)

個人用マクロブックを作成するには、マクロの記録を行うときに、[マクロの保存先]で「個人用マクロブック」を選択する。


 ## おわりに
ここまで読んでいただきありがとうございます！

## 参考文献
この1冊で合格! 永井雅明のExcel VBA ベーシック テキスト&問題集 単行本 – 2025/2/26
永井 雅明 (著)
p.31
044 AI屋さんの　RAG　巨匠召喚　LLMにトークン全文入力　マルチモーダル出力


044 AI屋さんの　RAG　巨匠召喚　LLMにトークン全文入力　マルチモーダル出力


巨匠召喚も実質　RAGと全文入力LLM　と同等です。
欲しい画像の指示をしながら、英語プロンプトを作てもらいまます。
日本語のままでも行けますが、

巨匠召喚は、細かな指示には従いません。
だって、
巨匠は、そうゆうものです。
そして、
巨匠は、完全新作をあなたの為だけに書き下ろししてくれます。
個人でお楽しみください。

もちろん、
公式公認の巨匠召喚が最も安全かと思います。


---

![スクリーンショット 2025-04-09 094936.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237930/e04acc48-059a-4488-8fe7-f9a004855fa9.png)

---

![ENTER_FILE_NAME005-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237930/38652455-a0fe-46aa-bbf0-1012168514dc.png)


---

たとえば、
プロンプトはこんな感じ


"Create a horizontal image. The scene should depict a horizontal white pedestrian crossing. Several umbrellas are lined up horizontally on the crossing. Below the pedestrian crossing, arrange multiple hydrangeas in soft shades of purple, red, and blue. Above the crossing and the umbrellas, along the top of the frame, place a series of blue traffic lights. Show rays of sunlight shining through gaps in the clouds in the sky, creating a divine atmosphere."

---


目次

https://qiita.com/bono0/items/dc1d000c98af7e07c9a7


巨匠召喚は完成度が高すぎて、
似ていない画像を作るのに苦労します。
ここではお見せできない、数々の書き下ろし画像、
本当の巨匠召喚は、もっとすごいです。
あらゆる巨匠を召喚可能です。
個人でお楽しみください。

今回も無事に
　044 AI屋さんの　RAG　巨匠召喚　LLMにトークン全文入力　マルチモーダル出力
巨匠召喚成功です。おめでとうございます。




ー以上ー
日記に関するプロンプト

日記を書く習慣はあったけど、これまでは書きっぱなしで振り返ることはほとんどなかった。文章量が多すぎて読み返すのが大変すぎた。
でも、AIで要約できるようになって気軽に見直せるようになった。

・以下の日記とメモの内容から、要点を階層箇条書きで500字を目安にまとめて。個人名が含まれても問題ありません。

(日記テキストデータをコピペ)


・日記の内容からわかる傾向や私の特性を教えて