OmniAICreator/Qiita-1.07M huggingface dataset:
windowsでポート開放のFirewallの設定について

# はじめに
この記事は、初めて書くものであり、内容などを詳しく言及するものではない
何かを変えてみたかったので適当に書いた記事である。

最近ゲームをしていて、自作サーバーを作るみたいなことが増えてきた気がする。
毎回作るたびにファイアウォールの設定に行き作るのが**めんどくさい**と感じた、それで
いい方法を探していたらコマンドで設定できることを知った。
最初は旧式の方でやっていた、また使おうとしたときに使えなくなっていた。
どうやら変わっていたらしい、なので自分用でまとめることにした。

> この記事は初心者によるの初心者のための基本的なことしか書いていないからそれでもいいよって方のみ閲読してください。
>

# ポート開放とは
まずこの記事に、来ている人が**何それ**はないと思うが一応語っておこう。
ポート開放とは、簡単に言ってしまえば**識別ID**みたいなものだ、
実際は、**ネットワーク**機器（主に**ルーター**）において特定のポート番号を通じて外部からの通信を許可することをいう
**ポート**とはその識別番号のことである
## 何故するのか
通常ルーターは外部からの通信に対して制限をしているそのためその制限を掻い潜る必要がある。そのため設定する必要がある。

# 本題
旧タイプの場合
netsh.exeを使用してfirewallコマンドを使用しセットする 方法
<dl>
<dt>ファイアウォール設定</dt>

<dd>ファイアウォールを有効にする 

    netsh firewall opmode mode =ENABLE

特定のポート(**任意のポート**)を許可する
    
    netsh firewall add portopening protocol= プロトコルタイプ port=任意のポート番号 name="任意の設定名" 
nameはダブルクォーテーション(**""**)で囲むがportは囲まなくて良い

特定のプログラム（例：任意のプログラム）を許可する
    
    netsh firewall add allowedprogram program = "任意のプログラム" name="任意のプログラム名"

ファイアウォール設定を表示する

    netsh firewall show all

現在のプロファイルの設定を表示する

    netsh firewall show state

全てのルールを表示する

    netsh firewall show config verbose=enable

ファイアウォール設定をリセットする

    netsh firewall reset

</dd>

以下の通りに書いてbatファイルで保存すれば使える

### ※ どちらも保存するときに **UTF-8**ではなく**ASIN**で保存しなければならない

```bat:port開放(旧).bat
@echo off
netsh firewall set opmode mode = ENABLE
netsh firewall add portopening protocol= プロトコルタイプ
port=任意のポート番号 name="任意の設定名" 
pouse
```
### こちらで今は成功している

netsh advfirewall を使用する例:ルールの追加。﻿

    netsh advfirewall firewall add rule name="任意の設定名" dir=in action=allow protocol=プロトコルタイプ localport=任意のポート

これは、任意の設定名 という名前のルールを削除します。ルールのエクスポート。﻿

    netsh advfirewall firewall delete rule name="任意の設定名"
    
これは、現在のファイアウォールルールを 任意のプログラム にエクスポートします。ルールのインポート

    netsh advfirewall export "任意のプログラム"
    
これは、任意のプログラム からルールをインポートします。
netsh advfirewall は、Windowsファイアウォールの詳細な設定をスクリプトで自動化したり、一元的に管理したりする場合に非常に便利です。

    netsh advfirewall import "任意のプログラム"

### プロトコルタイプは
<dt>TCP / IP</dt>
<dd>インターネット通信の基盤となるプロトコルです。TCPは信頼性の高い通信を保証し、IPはデータのルーティングを担当します。﻿</dd>
<dt>UDP</dt>
<dd>TCPよりも軽量で、リアルタイム性の高い通信に使用されます。﻿</dd>
それ以外のプロコトルタイプはゲームに使うことは殆どありません。
<dl>

### profileはprivate,public,domainの3つである

<dt>ドメインは</dt>
<dd>ドメインネットワーク環境にてしようする。ドメインネットワークは通常、企業や組織などの管理されたネットワークである、とても高いセキュリティレベルがいる</dd>
<dt>プライベートは</dt>
<dd>家庭や企業などのプライベートネットワーク環境にて使用する。プライベートネットワークは、信頼できるネットワークよりも緩やかなセキュリティ設定が適用されることもある。</dd>
<dt>パブリックは</dt>
<dd>公衆無線LANやインターネットなどの公共のネットワークに接続されている場合に適用されます。
公共のネットワークは、潜在的な脅威のリスクが高いため最も厳格なセキュリティ設定が適用されます。</dd>

</dl>


```bat:port開放.bat
@echo off
netsh advfirewall firewall add rule name="任意の設定名" 
dir=in action=allow protocol=プロトコルタイプ localport=任意のポート番号 
profile=プロファイル remoteip=any 
pouse
```
ちなみに@echo offはコマンドプロンプトに文字列を出力しないようにする命令で、pouseはコマンド実行後、即コマンドプロンプトが閉じるのを阻止するもの。
【高山慶】今日はどこまで「考える」仕事ができただろうか﻿



こんにちは、高山慶です。今日は「考えるエンジニアであること」について、振り返ってみたくなりました。

タスクの“なぜ”を常に問いかける
コードを書く前に、なぜそのロジックが必要なのか、どう使われるのか。
仕様書をなぞるのではなく、「なぜその要件が生まれたか」に思いを馳せることで、本質に近づく設計ができます。

「設計→仮実装→設計見直し」のループ
短くても一度仮実装してみることで、仕様の曖昧さが浮き彫りに。ここから再設計を入れることで、不要な技術選定や過剰設計を防げます。

データから仮説を検証
数字やログを参照して、仮説を自分で検証する時間は大切です。「遅い原因はDBのWHERE句？」「負荷はどこで増えている？」──この問いなしにエンジニアリングは進みません。

チームで「考える場」をつくる
コードレビューや設計会議は「人の考えを見る場」。質問を投げかけ、他者の思考パターンを知ることで、自分の引き出しも広がります。

 振り返り
今日は一日に「5回以上」は考える時間を持てたか。
雑に終えたタスクは振り返れば何か学びがあるはず。
明日も「考える」時間を大切に、自分とチームの成長を促していきたいと思います。

「考える」をもっと日常に。本当のエンジニア力は、ここから生まれるはずです。
Google、CompTIA認定資格でIT人材を強化（CompTIA米国本部ブログより）

# 企業組織におけるITトレーニングの重要性
今日の急速に変化するIT環境では、企業は競争力を維持するために継続的な学習とスキル開発を最優先にする必要があります。こうした認識のもと、GoogleではCompTIAのトレーニングと認定資格を企業の人材育成戦略に組み込んでいます。このブログでは、Googleのこれまでの歩みや直面した課題、そしてCompTIA認定資格がGoogle従業員に与えた変革的な影響についてご案内します。

![comptia-google_case-study-thumbnail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4110514/bb84793d-7e47-4bcf-8a24-16d430756e84.png)


# 従業員のニーズが企業のトレーニングとスキルアップを促進
GoogleのセキュリティプログラムマネージャーであるOlesya Menon氏は、体系的な学習機会を求める声は、従業員から寄せられていたと言います。多くの従業員は、自身の役割における強化やキャリア構築のためのスキルアップに努め、目標達成においてIT認定資格の重要性を認識しています。このような従業員主導の需要は、さまざまなスキルギャップに対応するための体系的なITトレーニングプログラムの必要性を浮き彫りにしました。

# ITとサイバーセキュリティにおける生成AIの影響
Menon氏は、IT、特にサイバーセキュリティにおけるテクニカルスキルとソフトスキルを重視しました。彼女は、自動のインシデント対応やコードの自動化を実現する生成AIツールのようなAI技術の重要性が高まっていることを強調しています。こうした進歩は、企業ITとサイバーセキュリティの将来を形作る重要なトレンドです。

# 企業がCompTIAのトレーニングと認定資格を選ぶ理由
Googleは、特にセキュリティアナリストの職務において、スキルギャップを埋めるソリューションとしてCompTIA認定資格を活用しています。体系化されたトレーニングは、従業員が資格を取得するための準備だけでなく、セキュリティイベントやインシデントの特定、分析、対応といった彼らの職務に必要な基本的知識を提供します。

企業組織にとって、CompTIAのトレーニングプログラムは人材育成のニーズに応えるスケーラブルかつクオリティの高いソリューションを提供します。

# Googleが実施したトレーニングプログラム
Googleは、セキュリティに特化したチームにCompTIA Security+などのサイバーセキュリティ認定資格を提供し、CertMasterや自学ツールといったツールを活用しました。任意でありながらも、自己負担なく質の高いトレーニングにアクセスできるという特権に、従業員は意欲的にプログラムに参加しました。

CompTIA認定資格を人材育成戦略に組み込むことで、Googleは体系的な企業ITトレーニングプログラムの価値を実証しました。

# 結果：ITトレーニングによる人材の変革
CompTIAのトレーニングと認定資格を活用することで、Googleは人材を強化し、進化し続けるIT環境における競争力を高めています。このプログラムの成功は、企業ITにおける学習と能力開発に対する従業員主導の需要によるものです。

スキルギャップのための取り組みや、従業員のスキルアップについてCompTIA認定資格が企業の人材育成にどう貢献できるか、ケーススタディにて詳細をご確認ください。

[ケーススタディ（英語）をダウンロードする](https://comptiacdn.azureedge.net/webcontent/docs/default-source/blog-documents/comptia-google_case-study.pdf?sfvrsn=a66b8d7_2)
databricks summit 2025

https://www.databricks.com/blog/aibi-genie-now-generally-available

2025年6月9〜12日にサンフランシスコで開催された Databricks Data + AI Summit 2025 のハイライトまとめです。

1. Agent Bricks（ベータ版）
自然言語でタスクを指定するだけで、ドメイン特化型エージェントを自動生成・評価・最適化する新ツール。ガバナンスやコスト最適化機構も備え、⽣産環境で利用可能なエージェント構築を支援 


2. Lakebase（一般提供開始）
サーバーレスPostgreSQL互換OLTPデータベースが、Lakehouse上でACIDと低レイテンシーを実現。構造化かつリアルタイムなトランザクション処理をData Lakeと統合 。

3. MLflow 3.0
ジェネレーティブAI向けに再設計された最新版。プロンプトやエージェントのバージョン管理・モニタリング、エージェントの外部環境での稼働観測が可能に 。

4. Lakeflow Designer（プレビュー）
アナリストがドラッグ＆ドロップでETLパイプラインを構築できる、AIアシスト付きノーコードオーケストレーション環境 。

5. Unity Catalogの強化
Delta LakeとApache Icebergを統合し、フォーマットやクラウド間でのデータとガバナンスを一元管理可能に。

ビジネスメトリクスをカタログ化する「Unity Catalog Metrics」や、データ／AIアセットを発見しやすいマーケットプレイス機能が強化 


6. AI Functions in SQL
SQL内で大規模ジェネレーティブAIを呼び出せる関数群が高速・低コスト化し、マルチモーダル対応により文書や画像処理もSQLで完結 。

7. サーバーレスGPUコンピューティング（ベータ）
A10G、H100など選べるGPUマシンで、トレーニングや推論をインフラ管理なしで実行可能 

。

8. 無料版Databricks Free Editionと教育投資
学習者・学生向けに初の無料エディションを展開。さらに学習コンテンツに対して1億ドル規模の投資を表明し、認知拡大を狙う 。

CEOアリ・ゴドシ（Ali Ghodsi）発言ポイント
AIはまだ完全に自動化される段階にはなく、人間による監督が不可欠－パイロットが飛行機のオートパイロットを監視するように。今後も人間が「承認」する体制が必要 。

会議では、Databricksは2025年7月までに年商37億ドルへ成長する見込みを発表。AI関連製品だけで年間3億ドルのARR（年継続収益）を達成中 


全体の方向性と総評
統合されたデータ・AIプラットフォーム: LakebaseでのOLTP統合、Unity Catalogによるガバナンス、エージェント構築のAgent Bricksで、断片化されたデータ基盤を一本化。

民主化と信頼性の両立: ノーコード、Free Edition、教育投資により専門知識の壁を下げながら、MLflow 3.0でモデルやプロンプト運用の透明性・信頼性を確保。

ビジネス価値の高速化: Unity Catalog MetricsやAI関数によって、ビジネスと技術のギャップを縮め、ダッシュボードやAI活用を迅速化。

まとめ
DatabricksはData + AI Summit 2025で、従来の断片化された「OLTP vs OLAP」構造に代わる、統一されたデータ＋AI基盤の姿を示しました。その中心には「人間による監督付きAI」と「誰でも使えるプラットフォーム」があり、信頼性とアクセシビリティの両立という現代のニーズに応える布石となっています。
Nuxt 3 The useError composable

**The useError composable**

```
                 ┌────────────────────────────┐
                 │      User visits a URL     │
                 └────────────┬───────────────┘
                              │
                              ▼
        ┌────────────────────────────────────────┐
        │   An error occurs (404, 403, 400, etc) │
        └────────────────┬───────────────────────┘
                         │
                         ▼
       ┌───────────────────────────────────────────────┐
       │ Nuxt renders the custom error.vue file        │
       │ (e.g., /error.vue inside your pages/ folder)  │
       └────────────────┬──────────────────────────────┘
                        │
                        ▼
┌────────────────────────────────────────────────────────────────────┐
│ Old Approach (Bad)                                                 │
│ ───────────────────────────────────────────────────────────────── │
│  Static content:                                                 │
│    <h1>404</h1>                                                    │
│    <p>Page Not Found</p>                                           │
│ ─ Always shows this, even if error is 403, 500, etc.               │
└────────────────────────────────────────────────────────────────────┘
                        │
                        ▼
┌────────────────────────────────────────────────────────────────────┐
│ New Approach (Good)                                                │
│ ───────────────────────────────────────────────────────────────── │
│ Dynamic content using Nuxt's `useError()` composable:           │
│                                                                    │
│ <script setup>                                                     │
│   const error = useError()                                         │
│ </script>                                                          │
│                                                                    │
│ <template>                                                         │
│   <h1>{{ error.statusCode }}</h1>                                  │
│   <p>{{ error.message }}</p>                                       │
│ </template>                                                        │
│ ─ This will adapt based on the actual error type.                  │
└────────────────────────────────────────────────────────────────────┘
                        │
                        ▼
           ┌───────────────────────────────────┐
           │ Shows:                            │
           │ - 404 → Page Not Found            │
           │ - 403 → Forbidden                 │
           │ - 500 → Server Error              │
           └───────────────────────────────────┘

```

**Summary:**
Previously, the error page was static – it always showed a generic 404.

Using useError(), you can access the actual error.statusCode and error.message.

This makes the error page dynamic, reusable for any type of error (403, 404, 500, etc.).
如果有JOB执行时间不对的时候，是不是时区设错了

「代替タイムゾーン」可以看到代替的时间
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3795764/2a9607d7-c5a2-401d-b4da-7d5a4fdacf06.png)
初心者が書いたコードを“プロっぽくする”ために必要なたった1つの視点

## はじめに

「このコード、動くんだけどなんか初心者っぽい…」「先輩のコードとなんか違うな…」

あなたが書いたコードに、そんな違和感を感じたことはないですか？

実は、**動くかどうかじゃなく、“読み方”と“考え方”に差があるだけ**なんですよね。

この記事では、初心者のコードを“プロっぽくする”ために必要なたった1つの視点——つまり、 **「意図が読めるかどうか」** について徹底的に掘り下げていきます。

---

## コードの「意図」が読めるってどういうこと？

### 初心者のコードにありがち：

* 変数名が `data1`, `list`, `temp`, `result` など抽象的
* if文や処理の目的が一見してわからない
* どの値がどこで使われてるかが追いにくい

### プロっぽいコードは？

* `selectedUserIds`、`isLoginError`、`fetchPostData()` のように**何のためかが明確**
* コメントを使わなくても、コード自体が**目的を語っている**
* 「これ、なんの処理？」ってならない

→ つまり、**読み手が“なぜこの処理があるのか”を一瞬で把握できるかどうか**。

---

## たとえば、こういう差が出る

### 初心者の書く例：

```js
let a = [];
for (let i = 0; i < users.length; i++) {
  if (users[i].age >= 20) {
    a.push(users[i]);
  }
}
```

### プロっぽいコード：

```js
const adultUsers = users.filter(user => user.age >= 20);
```

✅ 違いは“短さ”じゃなくて、**「aって何？」って聞かれないこと**。

---

## どうやったら「意図が読める」ようになるの？

### ✅ 書くときに「3つの問い」を自分に投げてみて：

1. これ何の処理？（目的）
2. これは誰に対して？（データの構造）
3. 何を返す？何を変える？（結果）

この3つがコードににじみ出てたら、**もうそれは“プロっぽいコード”** だよ。

---

## コメントで補うんじゃなく、「コードで語る」

悪いコードってのは、“コメントがないと意味がわからないコード”。

良いコードは、“コメントがなくても読める”コード。

**関数名、変数名、処理の粒度、順番、構造——全部で意図を表現してる。**

---

## まとめ：プロっぽさとは、“読みやすさのデザイン”である

| 初心者コード       | プロっぽいコード        |
| ------------ | --------------- |
| 動くけど読みにくい    | 意図がすぐ読める        |
| 名前が抽象的       | 名前が具体的で文脈がある    |
| 処理が雑に詰め込まれてる | 処理の粒度と順番が考えられてる |
| コメントが必要      | コード自体が説明している    |

✅ 結論：

> **コードに“意図”を込めよう。**
> 「読み手が理解できるように書く」それだけで、あなたのコードはプロっぽくなる。

コードレビュアーさんに「これなに？」って書かれなくなれば一歩上達です。
私が1年目のころは、「これなに？」とか「ここいる？」とかいっぱい書かれてました。
ゲーム開発で使用したテクニック～画像読み込み～

個人でゲーム開発をしている中で、実装に苦労した部分が多かったので、テクニックとして紹介していこうと思います。

今回は「画像読み込み」について書きます。
## 問題点
gifアニメーションを実行しようと思ったのですが、標準では無理でした。
そこでgifを複数の画像に分割し、それを順番に表示しようと思いました。
しかし実装してみると激重で、改善が必要でした。
## 改善
```py
# 高速化
self.IMG = self.IMG.convert()
for i in range(0, 120, 1):
    self.IMG_LIST[i] = self.IMG_LIST[i].convert_alpha()

clock = pg3.time.Clock()

# GIF画像をアニメーションさせる
for i in range(len(self.IMG_LIST)):
    self.screen.blit(self.IMG, self.INIT_POS)
    self.screen.blit(self.IMG_LIST[i], (400, 350))
    pg3.display.update()
    clock.tick(90)
```
「self.IMG」には背景画像が入っています。
「self.IMG_LIST」が分割したGIF画像です。
最初は画像をロードしてfor文の処理を実行していました。
しかしながら、画像をロードしただけでは内部的に未変換という状態らしく、描画時に変換処理が走るということがわかりました。
なので、変換処理を予め実行するように、「convert」「convert_alpha」を利用しました。
「convert_alpha」は透過画像を利用する際に使うようです。
これだけで劇的にアニメーションが速くなりました。

「画像読み込み」に関しては以上となります。

## リリース済みのゲームはこちら
・PC向け無料ゲーム
『LAbyrinth』（2Dの迷路探索ゲーム）
●Freem!
https://www.freem.ne.jp/win/game/33791
●Unityroom
https://unityroom.com/games/2025-labyrinth-isukaka
ゲーム開発で使用したテクニック～ワープ～

個人でゲーム開発をしている中で、実装に苦労した部分が多かったので、テクニックとして紹介していこうと思います。

今回はプレイヤーの「ワープ」について書きます。
## プレイヤーを変形させて消す方法
```py
def animation_jump(self, Player):
    """
    スキルのアニメーションを実行する処理
    """
    rate_x = -2.5
    rate_y = 5
    margin_x = 5
    margin_y = -10
    x,y = self.IMG_SCALE

    icon_x,icon_y = Player.ICON_POS

    for i in range(0, 20, 1):
        self.redraw()
        P_TRANS_IMG_1 = pg3.transform.scale(Player.P_IMG_FRONT, (x, y))
        self.screen.blit(P_TRANS_IMG_1, (icon_x+margin_x+i, icon_y+margin_y-i))
        pg3.display.update()
        pg3.time.delay(20)
        x += rate_x
        y += rate_y
    self.redraw()
    pg3.display.update()

    for m_x in range(0, 11):
        for m_y in range(0, 11):
            flag = self.MAZE[m_y][m_x]
            if flag == 9:
                margin_y = 5
                for i in range(20, -1, -1):
                    self.redraw()
                    P_TRANS_IMG_1 = pg3.transform.scale(Player.P_IMG_FRONT, (x, y))
                    self.screen.blit(P_TRANS_IMG_1, (m_x+margin_x+i, m_y+margin_y-i))
                    pg3.display.update()
                    pg3.time.delay(20)
                    x -= rate_x
                    y -= rate_y
                self.redraw()
                self.screen.blit(Player.P_IMG, (m_x, m_y), Player.P_IMG_D_1)
                Player.ICON_POS = (m_x, m_y)
                pg3.display.update()
                break
```
最初のfor文で、一定の割合でプレイヤーの縦横比を変形させていき、最後は消します。
横幅は「rate_x」の分だけ小さくなり、縦幅は「rate_y」の分だけ大きくなります。
プレイヤーの画像は徐々に縦長になっていき、最後は横幅が0になって消えたように見えるという流れです。
ただし、そのままだとプレイヤーの表示位置もずれていってしまうため、「margin_x」「margin_y」で位置調整をしています。
次のfor文で、さっきとは逆のことをしています。
横幅は「rate_x」の分だけ大きくなり、縦幅は「rate_y」の分だけ小さくなります。
縦長だったプレイヤーの画像は徐々に元の形に戻っていきます。
「self.MAZE[m_y][m_x]」は画面にあるオブジェクトの座標と種類が入っているので、「flag == 9」でプレイヤーを表示したい座標（m_x,m_y）を取得しています。
## プレイヤーを画面外に飛ばす方法
```py
def animation_jump(self, Player):
    """
    スキルのアニメーションを実行する処理
    """
    # プレイヤーの位置を取得する
    icon_x,icon_y = Player.ICON_POS

    # プレイヤーを画面外へ飛ばす
    for i in range(icon_y, -121, -30):
        self.redraw()
        self.screen.blit(Player.P_IMG, (icon_x, i), Player.P_IMG_D_1)
        pg3.display.update()
        pg3.time.delay(1)

    # ゴール地点の座標を取得する
    m_x,m_y = self.MAZE.get_coordinate(9)
    
    # プレイヤーを画面外からゴール地点に戻す
    for i in range(-121, m_y+1, 30):
        self.redraw()
        self.screen.blit(Player.P_IMG, (m_x, i), Player.P_IMG_D_1)
        pg3.display.update()
        pg3.time.delay(1)
    
    self.redraw()
    self.screen.blit(Player.P_IMG, (m_x, m_y), Player.P_IMG_D_1)
    Player.ICON_POS = (m_x, m_y)
    pg3.display.update()
```
プレイヤーは現在地から上昇していき、画面外に出ます。その後、画面外から指定の座標まで下りてきます。
最初のfor文ではプレイヤーを上昇させたいので、Y軸を「30」ずつ減算しています。
次のfor文ではプレイヤーを下降させたいので、Y軸を「30」ずつ加算しています。
上昇の到達点と下降の開始地点は一致させたいので、今回は「-121」としています。
負の数にすることで、画面の外を表現することができます。
「self.MAZE.get_coordinate(9)」はプレイヤーを変形させる方法で述べた、プレイヤーを表示したい座標（m_x,m_y）を取得する関数です。
関数はあとから作成したので、こちらだけそうなっています。

「ワープ」に関しては以上となります。

## リリース済みのゲームはこちら
・PC向け無料ゲーム
『LAbyrinth』（2Dの迷路探索ゲーム）
●Freem!
https://www.freem.ne.jp/win/game/33791
●Unityroom
https://unityroom.com/games/2025-labyrinth-isukaka
ゲーム開発で使用したテクニック～スキルエフェクト～

個人でゲーム開発をしている中で、実装に苦労した部分が多かったので、テクニックとして紹介していこうと思います。

今回は「スキルエフェクト」について書きます。

## 概要
スキルを使用したときに円形（輪）のエフェクトを表示させます。
通常スキルは円を1回表示させます。
必殺技は円を3回表示させます。
## 円1回
```python
def skill_effect(self, rgb, Player):
    """
    スキル使用時のエフェクトを描画する
    """
    x,y = Player.ICON_POS
    r,g,b = rgb
    width = 10
    for radius in range(0, 128, 1):
        self.screen.fill(self.BG_COLOR)
        self.screen.blit(Player.P_IMG, (x, y), Player.get_direction())
        pg3.draw.circle(self.screen,(r,g,b),(x+30,y+30),radius*8,width)
        pg3.time.delay(4)
        pg3.display.update()
    # 元に戻す
    self.redraw()
    # プレイヤーを表示する
    self.screen.blit(Player.P_IMG, (x, y), Player.get_direction())
    pg3.display.update()
```
radiusを更新することで、円はプレイヤーを中心に広がっていき、画面外に消えていきます。
描画がかなり重く、円を表示している間は背景とプレイヤー以外は表示しないようにしました。
円の描画が終わったら「self.redraw()」で画面全体を再描画しています。
「Player.get_direction()」はプレイヤーの現在の向きに応じた切り取り位置を返す関数です。
## 円3回
```python
def skill_effect_sp(self, rgb, Player):
    """
    SPスキル使用時のエフェクトを描画する
    """
    x,y = Player.ICON_POS
    r,g,b = rgb
    width = 10
    temp_surface = pg3.Surface(self.DISP_SIZE, pg3.SRCALPHA)
    for radius in range(0, 128, 1):
        self.screen.fill(self.BG_COLOR)
        self.screen.blit(Player.P_IMG, (x, y), Player.get_direction())
        pg3.draw.circle(self.screen,(r,g,b),(x+30,y+30),radius*8,width)
        if radius > 25:
            pg3.draw.circle(self.screen,(r,g,b),(x+30,y+30),(radius-25)*8,width)
        if radius > 50:
            pg3.draw.circle(self.screen,(r,g,b),(x+30,y+30),(radius-50)*8,width)
        temp_surface.fill((r, g, b, radius))
        self.screen.blit(temp_surface, (0, 0))
        pg3.time.delay(3)
        pg3.display.update()
    # 元に戻す
    self.redraw()
    # プレイヤーを表示する
    self.screen.blit(Player.P_IMG, (x, y), Player.get_direction())
    pg3.display.update()
```
処理は円1回と大体同じです。
radiusが一定値を超えたら次の円を表示します。
最後の円が画面外に消えるように調整しています。
こちらは描画時に半透明のサーフェイスも描画しています。
透明度はradiusに一致させているので、円が広がると同時に透明度も変更されます。

「スキルエフェクト」に関しては以上となります。

## リリース済みのゲームはこちら
・PC向け無料ゲーム
『LAbyrinth』（2Dの迷路探索ゲーム）
●Freem!
https://www.freem.ne.jp/win/game/33791
●Unityroom
https://unityroom.com/games/2025-labyrinth-isukaka
ゲーム開発で使用したテクニック～ボタン連打抑止～

個人でゲーム開発をしている中で、実装に苦労した部分が多かったので、テクニックとして紹介していこうと思います。

今回は「ボタン連打抑止」について書きます。

## 問題点
キーボードのEnterキーや方向キー、マウスクリックなどゲーム中ではボタン押下をトリガーにしていました。
すると、ある画面でEnterキーを連打すると、次の画面が表示されていないのに、すでにEnterキーが押された判定になってしまい、Enterキーを押していないのに勝手に処理が進むという事象に遭遇しました。
## 対策
ボタン押下というイベントがキューに溜まっていく仕様は理解しました。
とりあえず次の画面が表示されるまである程度Enterキーを連打しても大丈夫にしたいと考え、最終的には以下のコードになりました。
```python
def is_wait(self):
    """
    指定時間の間イベントを受け付けない
    """
    if self.WAIT != 0 and self.START_TIME is not None:
        if pg3.time.get_ticks() - self.START_TIME > self.WAIT:
            # ウェイト終了
            self.WAIT = 0
            self.START_TIME = None
            return False
        else:
            return True
    return False
```
まずはウェイト判定をする関数です。
「self.WAIT」には待ちたい時間を入れておきます。
「self.START_TIME」にはウェイトを開始する時間を入れておきます。
あとは現在時間から開始時間を引いた値が待ち時間を超えるかどうかを判定しています。
ウェイトが終わった時点で、待ち時間と開始時間はリセットします。
```python
def set_wait(self, wait):
    """
    ウェイト関連の情報をセットする
    """
    self.START_TIME = pg3.time.get_ticks()
    self.WAIT = wait
```
次にウェイトしたいところで呼ぶ関数です。
待ち時間と開始時間をセットしています。
```python
for event in pg3.event.get():

    # ウェイト中はボタン無効化
    if state.is_wait():
        continue

    if event.type == pg3.KEYDOWN and event.key == pg3.K_RETURN:
        state.set_wait(1000)
```
使い方としてはこんな感じです。
ゲーム状態を管理するクラスを作っていたので、先ほどの関数はそのクラスで定義してあります。
Enterキーが押されたときに「set_wait(1000)」で1秒セットします。
「is_wait()」が1秒間Trueを返し続けるので、キー判定の処理に来る前にcontinueされて、次のボタン押下が無視されるという流れです。
待ち時間の「1000」の部分は実際にプレイして調整していました。

「ボタン連打抑止」に関しては以上となります。

## リリース済みのゲームはこちら
・PC向け無料ゲーム
『LAbyrinth』（2Dの迷路探索ゲーム）
●Freem!
https://www.freem.ne.jp/win/game/33791
●Unityroom
https://unityroom.com/games/2025-labyrinth-isukaka
ゲーム開発で使用したテクニック～画像データの取得～

個人でゲーム開発をしている中で、実装に苦労した部分が多かったので、テクニックとして紹介していこうと思います。

今回は「画像データの取得」について書きます。

## 画像データの配置場所
「game.py」が起動ファイルだったとして、同階層に「img」フォルダを作ります。
必要な画像データは「img」フォルダに入れます。
## 画像データの取得
ただロードするだけなら1行です。
「img_path」には「img\XXXXX.png」という感じでPATHが入ります。
```python
self.IMG = pg3.image.load(img_path)
```
## 問題点
pyinstallerを使用してexeファイルを作成しました。
すると、画像参照ができないというエラーに遭遇しました。
exeを起動すると必要なファイルが一時領域に展開されるのですが、それがフォルダ構成を維持してくれませんでした。
ということで、コードは以下のようになりました。
```python
img_path = self.get_image_path(self.IMG_NAME)
self.IMG = pg3.image.load(img_path)

def get_image_path(self, filename):
    """
    画像ファイルのパスを返す
    """
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, filename)
    return os.path.join(os.path.abspath("."), "img\\" + filename)
```
exeファイルを実行しｔ時に一時領域が追加されている場合は、一時領域の直下にあるファイルをpathに追加しています。
普通にpyファイルを実行する場合は、一時領域がありませんので、imgフォルダ直下にあるファイルをpathに追加しています。

「画像データの取得」に関しては以上となります。

## リリース済みのゲームはこちら
・PC向け無料ゲーム
『LAbyrinth』（2Dの迷路探索ゲーム）
●Freem!
https://www.freem.ne.jp/win/game/33791
●Unityroom
https://unityroom.com/games/2025-labyrinth-isukaka
ゲーム開発で使用したテクニック～フェード演出～

個人でゲーム開発をしている中で、実装に苦労した部分が多かったので、テクニックとして紹介していこうと思います。

今回は「フェード演出」について書きます。

## フェードイン
画面が徐々に表示されていく演出です。
以下は実装したコードです。
```python
def fade_in(self):
    """
    フェードインさせる
    """
    temp_surface = self.IMG.copy()
    for alpha in range(0, 131, 10):
        if alpha == 130:
            alpha = 125
        temp_surface.set_alpha(alpha)
        self.screen.blit(temp_surface, self.INIT_POS)
        pg3.display.update()
        pg3.time.delay(30)
```
「self.IMG」に表示したい画像が読み込まれています。
その画像オブジェクトのアルファ値を「0～125」まで「10ずつ」加算していきます。
「self.INIT_POS」は表示したい位置です。
「pg3.time.delay」またはステップ数（今回だと10）でフェードのスピードを調整できると思います。
## フェードアウト
画面が徐々に暗転していく演出です。
以下は実装したコードです。
```python
def fade_out(self):
    """
    フェードアウトさせる
    """
    temp_surface = pg3.Surface(self.DISP_SIZE, pg3.SRCALPHA)
    for change in range(0, 261, 10):
        if change == 260:
            change = 255
        self.screen.blit(self.IMG, self.INIT_POS)
        self.screen.blit(self.IMG_LIST[0], (250, 200))
        pg3.time.delay(1)
        temp_surface.fill((0, 0, 0, change))
        self.screen.blit(temp_surface, self.INIT_POS)
        pg3.display.update()
```
こちらは別途サーフェイスを作成しています。
「self.IMG」だけでなく「self.IMG_LIST[0]」もフェードアウトの対象にしたかったからです。
サーフェイスのアルファ値を「change」で更新しています。
こちらも「pg3.time.delay」またはステップ数（今回だと10）でフェードのスピードを調整できると思います。
## 注意点
フェード演出に共通していることですが、アルファ値の上限が決まっているので、ステップ数次第では上限を超えてしまい、エラーになることがありました。
それを回避する為、IF文で一定数値を超えたら上限を設定するようにしてあります。
ただし無限ループにならないように、rangeの上限には注意が必要です。

また、画面にオブジェクトがたくさんある場合、フェード中にすべて再描画する必要がありました。
```python
def fade_out(self):
    """
    フェードアウトさせる
    """
    temp_surface = pg3.Surface(self.DISP_SIZE, pg3.SRCALPHA)
    for change in range(0, 261, 10):
        if change == 260:
            change = 255
        self.redraw()
        pg3.time.delay(1)
        temp_surface.fill((0, 0, 0, change))
        self.screen.blit(temp_surface, self.INIT_POS)
        pg3.display.update()
```
「self.redraw()」のように、再描画処理は別関数へまとめるようにしました。
redrawの中で「pg3.display.update」をコールする必要はありません。

「フェード演出」に関しては以上となります。

## リリース済みのゲームはこちら
・PC向け無料ゲーム
『LAbyrinth』（2Dの迷路探索ゲーム）
●Freem!
https://www.freem.ne.jp/win/game/33791
●Unityroom
https://unityroom.com/games/2025-labyrinth-isukaka
スペースコロニーXRで音楽を聴く

# はじめに

経緯はこちら。

https://qiita.com/kitazaki/items/5609b1382def6584f6d4

きっかけはこちら。

https://x.com/hirax/status/1932945127309517001

成果物はこちら。

https://x.com/Zakkiea/status/1935116153061523560

# A-Frameで音楽を聴く

公式のドキュメントを確認します。

https://aframe.io/docs/1.7.0/components/sound.html

画像ファイル(再生・停止ボタン)と任意の音楽ファイル(mp3)を用意します。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/241aed2b-12d3-4cf4-93b1-c634427923a1.png" width="10%">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/10ffee11-1330-40a2-947c-ad8422ba5381.png" width="10%">



## ソースコード

追加するA-Frame(a-scene)のパーツです。

```html:index.htm
<a-camera position="0 -320 0" cursor="rayOrigin: mouse;"></a-camera>
<a-assets><img id="img_play" src="img_play.png"/></a-assets>
<a-assets><img id="img_pause" src="img_pause.png"/></a-assets>
<a-assets><audio id="audio01" preload="auto" src="音楽.mp3"/></a-assets>
<a-entity sound="src: #audio01; autoplay: false; positional: false; loop: true"></a-entity>
<a-image id="button01" src="#img_pause" position="0 -300 -200" scale="20 20 20"/>
```

イベント(クリック)をトリガーとして音楽を再生(停止)、ボタンを表示(変更)します。

```javascript:main.js
"use strict";

// Window
window.onload = (e)=>{
	console.log("onload!!");
	const scene = document.querySelector("a-scene");
	const entity = document.querySelector('[sound]');
	const button01 = document.getElementById("button01");
	button01.addEventListener("click", (e)=>{
		console.log("clicked!!");
		console.log(entity);
		if(entity.components.sound.isPlaying){
			console.log("paused!");
			entity.components.sound.pauseSound();
			e.target.setAttribute("src", "#img_pause");
		}else{
			console.log("played!");
			entity.components.sound.playSound();
			e.target.setAttribute("src", "#img_play");
		}
	});
}
```


# NT金沢2025で体験(出展)

今週末(6/21(土)〜22(日))のNT金沢2025(うH)でお待ちしております！

https://wiki.nicotech.jp/nico_tech/?NT%E9%87%91%E6%B2%A22025

https://x.com/Zakkiea/status/1932943663359033538
Nuxt 3 study memo

**my-nuxt-app/**
├── app.vue
├── package.json
├── node_modules/
└── html/　　　　　 <-- Contains: your static HTML/CSS files)


**Enable Routing with the pages/ Directory**
Create a folder:
pages/
└── index.vue　　　　　 <-- homepage route "/"


**Use `<NuxtPage />` to Activate Routing**
```
<template>
  <nav>Navigation Bar</nav>
  <NuxtPage />       <!-- THIS loads the correct page -->
  <footer>Footer</footer>
</template>
```

This renders the correct component depending on the route:
/  　　　　　--> loads pages/index.vue
/cars　　　　--> 404 (until you create pages/cars.vue)


**Resulting Structure**

**my-nuxt-app/**
├── app.vue          　　　　<-- Global layout (Nav + <NuxtPage /> + Footer)
├── pages/
│   └── index.vue     　　　　<-- Home page
├── html/             　　　　　　<-- Old static HTML files (for reference)
├── package.json
└── node_modules/

**Problem with `<a href="/">`**
`<a href="/">Home</a>`
・Triggers a full page reload
・Breaks the SPA behavior
・Slower and less smooth

`<NuxtLink>`
`<NuxtLink to="/">Home</NuxtLink>`
・Client-side navigation
・No full page reload
・Auto-imported by Nuxt (no need to import NuxtLink)

**Component Example**
```
<template>
  <nav>
    <NuxtLink to="/">Home</NuxtLink>
  </nav>
</template>
```

**Flat Route Structure**
pages/
└── city/
　　　└── [city]/
　　　　　　└── car/
　　　　　　　　　└── [[make]].vue   <-- This handles everything

**Nested Route Structure Example**

pages/
└── city/
　　└── [city]/
　　　　　　└── car/
　　　　　　　　├── index.vue       <-- `/city/:city/car`
　　　　　　　　└── [[make]].vue    <-- `/city/:city/car/:make?` (optional)
Gitって「バカ」って意味らしい。他にも変なネーミング集めてみた

Gitは「バカ」って意味らしい。おもろい。

https://ejje.weblio.jp/content/git
>ばか者、ろくでなし
---
https://en.wikipedia.org/wiki/Git
>トーバルズは「git」という名前について皮肉交じりにこう冗談を言った（「git」はイギリス英語のスラングで「嫌な奴」という意味がある）：「僕は自己中心的な嫌な奴だから、自分のプロジェクトには全部自分の名前をつけるんだ。最初は『Linux』、次は『git』さ。」
マニュアルページでは、Gitを「間抜けなコンテンツトラッカー」と表現している。
---
[Linus Torvaldsのコミットログ](https://github.com/git/git/commit/e83c5163316f89bfbde7d9ab23ca2e25604af290?)

>GIT - おバカなコンテンツトラッカー
>
>「git」は、あなたの気分次第で何を意味してもいい。
>
>* 発音可能な3文字のランダムな組み合わせで、一般的なUNIXコマンドでは実際に使われていないもの。
  「get」の発音間違いであることは関係あるかもしれないし、ないかもしれない。
>* バカな、軽蔑すべき、最低な、単純な——スラング辞典から好きなのを選んでください。
>* 「global information tracker（グローバル情報トラッカー）」：機嫌が良いときは、実際にうまく動作します。天使が歌い、部屋に突然光が差し込みます。
>* 「goddamn idiotic truckload of sh\*t（クソバカで大量のクソ）」：壊れたときはこう思うでしょう。
>
>これはバカだけど（非常に高速な）ディレクトリコンテンツ管理ツールです。
>多くのことはしませんが、ディレクトリの内容を効率よく追跡することに特化しています。

### バグは本当に虫が由来！

電気回路に蛾が挟まっててコンピュータが止まって、それが由来っぽい。おもろい。

https://gigazine.net/news/20120910-first-computer-bug/

### 他にもいろいろ (Claude先生に) 集め (てもらっ) た

🐍 **Python**: 作者がイギリスのコメディ番組「モンティ・パイソン」のファンだったから

🐘 **PHP**: 元々は「Personal Home Page」の略だったが、今は「PHP: Hypertext Preprocessor」という再帰的な略語

☕ **Java**: 開発チームがよく行くコーヒーショップで飲んでいたジャワコーヒーから

🍃 **MongoDB**: 「humongous（巨大な）」から来ている

🐳 **Docker**: 港湾労働者（docker）が貨物コンテナを扱うように、アプリケーションをコンテナで管理するから

🔥 **Apache**: 「A Patchy server」（継ぎはぎだらけのサーバー）の駄洒落から

🍰 **CakePHP**: 「ケーキを焼くように簡単にWebアプリを作れる」という意味

🎭 **Puppet**: システムを「操り人形のように操作する」から

🍴 **Git Fork**: プロジェクトを「フォークで刺して分岐させる」イメージ

🥾 **Bootstrap**: 「自分の靴紐を引っ張って自分を持ち上げる」という慣用句から

🐰 **RabbitMQ**: メッセージを「うさぎのように素早く」配信するから

🔍 **Elasticsearch**: 「弾性的に検索できる」という意味

🌪️ **Apache Storm**: データストリームを「嵐のように」リアルタイム処理

🐙 **Kraken**: 巨大な海の怪物のように「巨大なデータを処理する」暗号通貨取引所

🍯 **Honeypot**: ハッカーを「蜂蜜で蜂を誘うように」おびき寄せるセキュリティ技術

🧙‍♂️ **Wizard**: 設定を「魔法使いのように」簡単にしてくれるインストーラー

🍪 **Cookie**: 小さな情報の「おやつ」をブラウザに保存

🐛 **Bug**: 実際にコンピューターに虫が挟まって動かなくなったのが語源

🔨 **Hammer**: 「金槌で叩くように」問題を解決するツール

🐧 **Linux**: 作者のLinus Torvaldsの名前＋UNIX

🦆 **DuckDuckGo**: 子供の遊び「だるまさんが転んだ」の英語版から

🐿️ **Squirrel**: データを「リスのように」せっせと集めて保存するSQL拡張
Salesforce資格更新の方法

今回は資格試験の更新方法について紹介します

　更新期限が赤字の場合は資格の更新が必要です

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/1649703b-48ff-478d-8441-47723434a269.png)

「更新を完了する」をクリックすれば更新モジュールのリンクが表示されます

更新モジュールをクリアしましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/198a76ee-6fff-400d-8a25-02aaced37aac.png)
がっちゃんこ　结合，整合，混合


3-1. 資料の合体
プレゼンテーションのために作成した複数の資料をがっちゃんこして統合することで、一つの完全な資料にすることができます。
会議で使用するために、チームメンバーが個別に作成した資料をがっちゃんこして組み合わせることがあります。

3-2. データの統合
異なるデータベースから得られたデータをがっちゃんこして統合することで、全体のデータを一元管理することができます。
インターネット関連の業務では、複数のデータをがっちゃんこして分析することがあります。

3-3. アイデアの組み合わせ
複数のアイデアをがっちゃんこして新しいアイデアを生み出すことがあります。
問題解決のために、異なる視点やアイデアをがっちゃんこして総合的な解決策を見つけることができます。
これらの事例からもわかるように、がっちゃんこは様々な場面で活用されるビジネス用語です。柔軟な発想と創造力を持って、異なる要素をがっちゃんこして新たな価値を生み出すことが重要です。
keyの仕組み



## Reactの描画のしくみ

Reactは、コンポーネントの表示を更新するときにこうします：

1. **前回の仮想DOM**（画面の状態）と、
2. **今回の仮想DOM**（更新後の状態）を
3. 比較して「**どこを変えればいいか**」を判断

そのとき、リストのように**同じ構造が何個も並んでいる部分**では、

> 「この<li>は、前回のどの<li>と同じものなの？」

が分からないと、**正しい比較ができません**。

---

## そこで使われるのが `key`

Reactは、`key` を使って「この要素はこれだよ！\*\*」と判別します。
つまり：

* `key` が同じ → 同じ要素と見なす
* `key` が違う → 新しい要素と見なして入れ替える

---

## `key`がない or indexを使うと起きるバグの例

### 例：フォームがリストにあるとき

```jsx
const items = ['A', 'B', 'C'];
const [list, setList] = useStat(items);
```

```jsx
return (
  <ul>
    {list.map((item, index) => (
      <li key={index}>
        {item}
        <input />
      </li>
    ))}
  </ul>
);
```

* それぞれの項目に `<input>` を入れている
* しかし、`index` を key に使っていると…

### 要素の順番を変更 or 削除したとき：

* 入力していたテキストが**別の項目に移動してしまう**
* なぜかというと、**Reactが間違った要素を同じ認識する**から

---

## `key`には「一意で変わらないID」を使うべき

```jsx
const tasks = [
  { id: 't1', text: '掃除' },
  { id: 't2', text: '洗濯' }
];

return (
  <ul>
    {tasks.map(task => (
      <li key={task.id}>{task.text}</li>
    ))}
  </ul>
);
```

このように、\*\*ユニークで安定したID（例：DBのID）\*\*を使うと完璧です。

---

## 要素を追加・削除・並び替えしたときの比較例

### keyがない（またはindex）

```diff
Before: <li key=0>🍎</li> <li key=1>🍌</li>
After:  <li key=0>🍌</li> <li key=1>🍇</li>

React「え？index 0は🍎のまま？じゃあ🍌の中身に🍎を使い回そう」
→ UIがズレる💦
```

### keyがある

```diff
Before: <li key="apple">🍎</li> <li key="banana">🍌</li>
After:  <li key="banana">🍌</li> <li key="grape">🍇</li>

React「keyが違うね。bananaは残すけど、apple→grapeに変えよう」
→ UIが正しく更新✨
```

---

## まとめ：keyとは？

| ポイント | 説明                  |
| ---- | ------------------- |
| 目的   | 要素の識別と効率的な再描画のため    |
| 理由   | 仮想DOMで差分を比べるために必要   |
| 良い例  | ユーザーID、タスクIDなど一意なID |
| 悪い例  | `index`（順番が変わるとバグる） |

---
useRefの使い方

##  `useRef` とは？

Reactのフックの一つで：

> 「\*\*ある値を記憶するための箱（オブジェクト）\*\*を作る」

ようなものです。

---

## 書き方（基本構文）

```jsx
import { useRef } from "react";

const ref = useRef(initialValue);
```

* `initialValue` は初期値（省略可）
* `ref.current` に値が入る（変更しても再レンダリングされない）

---

## ✳️ 主な使い道 2パターン

---

### ① DOMを直接触る（主用途）

#### 例：入力欄にボタンでフォーカスを当てたい

```jsx
import { useRef } from "react";

const Example = () => {
  const inputRef = useRef();

  const handleClick = () => {
    inputRef.current.focus(); // DOMのfocus()を呼ぶ！
  };

  return (
    <div>
      <input ref={inputRef} type="text" placeholder="ここにフォーカス" />
      <button onClick={handleClick}>フォーカスする</button>
    </div>
  );
};
```

#### 解説：

* `useRef()` で作った `inputRef` を `<input ref={inputRef}>` に渡すと、DOMが取得できる
* `inputRef.current` にその DOM 要素（inputタグ）が入ってる
* `inputRef.current.focus()` でフォーカスできる！

---

### ② 値を保持する（再レンダリングさせたくないとき）

#### 例：前回のカウント値を保持する

```jsx
import { useRef, useState, useEffect } from "react";

const Example = () => {
  const [count, setCount] = useState(0);
  const prevCount = useRef(0);

  useEffect(() => {
    prevCount.current = count;
  }, [count]);

  return (
    <div>
      <p>今のカウント: {count}</p>
      <p>前のカウント: {prevCount.current}</p>
      <button onClick={() => setCount(count + 1)}>＋1</button>
    </div>
  );
};
```

#### 解説：

* `prevCount.current` に前回の `count` を記録
* 値を更新しても **再レンダリングされない**
* `useRef` は「永続的なメモ帳」のような使い方もできる

---

## `useRef` vs `useState` の違い

| 比較項目          | `useRef`        | `useState`           |
| ------------- | --------------- | -------------------- |
| 値の更新で再レンダリング？ | ❌ されない          | ✅ 再レンダリングされる         |
| DOM参照に使える？    | ✅ できる           | ❌ できない（HTMLには渡せない）   |
| 値の保持目的        | ✅ 一時的・永続的どちらもOK | ✅ UIに影響を与える状態を管理するため |

---

## よくある使い道まとめ

| 用途                  | 例                                      |
| ------------------- | -------------------------------------- |
| DOM参照               | `inputRef.current.focus()`             |
| setTimeout の ID を保持 | `timeoutRef.current = setTimeout(...)` |
| 前回の値を覚えておく          | `prevCount.current = count`            |
| スクロール位置・ビデオ制御など     | `videoRef.current.play()`              |

---

##  まとめ

* `useRef()` は、DOM要素 or 値を保持するために使う
* `.current` にアクセスする
* 値が変わっても再レンダリングはされない
* フォーカス、スクロール、前回の値保持などに便利
学習14日目

# 今日学んだこと
createアクションの処理の成功と失敗で条件分岐させる

# 内容
初期のcreateアクションは、下記だった。
```
def create
  Hoge.create(hoge_params)
  redirect_to root_path
end
```

この記述の場合、保存処理の成功、失敗に関係無くroot_pathへリダイレクトされる。
これでは保存に成功したかわからない。

そこで、下記のように記述した。
```
def create
  @hoge = Hoge.new(hoge_params)
  if @hoge.save
    redirect_to roop_path
  else
    render :new
  end
end
```

これで、バリデーションに引っかかった場合、newアクションのviewが読まれるようになった。
しかし、これにも問題が発生。

newアクションのviewの上部に下記の記述をし、バリデーションに引っかかった場合のメッセージを表示させるようにしたところ、何も表示されなかった。
```
<% if model.errors.any? %>
  <% model.errors.full_messages each do |message|%>
    <%= message %><br>
  <% end %>
<% end %>
```

debuggerでmodel.errorsの結果を確認すると、空欄で保存しようとしているにも拘らず、エラー文の配列が空になっていた。

原因は、コントローラのrender部分に「status: :unprocessable_entity」を記述していないことだった。

(該当箇所のみ抜粋)
```
render :new, status: :unprocessable_entity
```

どうやら「status: :unprocessable_entity」の記述が無い場合、ステータスコードが正常終了のものとして進んでしまうらしく、errorsメソッドを用いても何も取得できないとのこと。

# 感想
ユーザ体験の向上のため、今後はエラーメッセージの日本語化も実装する必要があると感じた。
Google Stitch を使って、簡単なMCPクライアントを作った話

# あらすじ
学習かたがた MCP（Model Context Protocol）本家サイトの[Model Context Protocol: User Guide](https://modelcontextprotocol.io/quickstart/client "Quick Start - For Client Developers")をもとに、簡単なMCPクライアントを作ってみたけど、CLIだとちょっと見た目が寂しいので[Google Stitch](https://stitch.withgoogle.com/)を使ってUIを作ってみたのでメモ（まだ作業途中なので、参考程度に）

::: note
ここでは、開発環境は以下を使っている
- Node.js
- Typescript
- Windows
:::

## StitchでUIを作ってみる
Google Stitchは、自然言語のプロンプトで必要な画面を指定することでデザイン案を生成してくれる。今回のようにデモ用に簡単なUIをサクッと作るには充分な使い勝手になっていると思う

### Stitch
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125655/b3ef6611-6489-48d1-a90a-cf8989d894e3.png)
デザインもモバイルかWebかを選択でき、プロンプト入力してGenerate designsをクリックするだけでそれっぽいデザインを制作してくれる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125655/0bf592b9-2ff2-4d2a-9967-fee116c9a9c5.png)
特に細かい指定をしていない場合も、必要そうなメニューは項目などはあらかじめセットしてくれる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125655/4eebbff5-e1f1-4752-a048-89be3b03c01f.png)
見た目や色などもトンマナを指定できるので、ここでもお好みに調整できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125655/c1c46097-042f-4e52-9f4e-a8482a84ad18.png)

### デザインの修正をプロンプトで行える
もちろん出来上がったデザインにたいして、自然言語で改変も可能だ。左下のチャット欄にプロンプトを書くだけ。

> add a description field under conditions.

例えばこのように指定した場合、Conditions欄の下に、期待通りにDescription欄が追加され、ご丁寧に表示サンプルまでセットされている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125655/3faad8ed-df63-4a10-851c-98f9c2bc06ee.png)

 ### 出来上がったデザインをFigmaで編集したり、コードをコピペしたり
今回は、出来上がったコードをプロジェクトに新規作成したindex.htmlファイルにコピペして、これをテンプレにMCPクライアントの制作を開始した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125655/15071830-2647-4a5c-b7a0-1f2206777de6.png)

## MCPクライアントを作ってみる
MCPクライアントの実装自体は[User Guide](https://modelcontextprotocol.io/quickstart/client "Quick Start - For Client Developers")を参考に、ほぼそのままCLIベースで一度組み立てて動作確認をした

::: note warn
MCPのユーザーガイドに従ってWindows Powershellでechoして.envファイルを作成したら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125655/a003d71c-8f53-400b-8172-06aa59fc8a5c.png)
BOM付きUTFでファイル生成されたせいか期待通りAPI Keyが読み込めず思いのほかはまってしまった。。
.envファイルをテキストエディタでBOM無しに変換したら対処できたけど、慣れないPowershellでの作業には気を付けよう…
:::

そのうえで、先ほどStitchで制作したindex.htmlをベースに以前コーディングした mcp-weatherと連携して、指定した都市の天気を表示するようにClineに指示している

コードの中身は細かく見れていないが、いろいろとまだ課題はありつつも一応MCP Serverと連携して天気APIからデータをとってくるところまではできていそうだ

過去には、API叩かずにそれっぽいテストデータを自分で作ったスタブから取得して表示していたこともあったので、細かなコードレビューやテストをするまでは油断はできないので留意

https://github.com/katsuya-ide/mcp-weather-cl


## まとめ

以上、ここまでで、初見で調べながらで小一時間くらいでMCPクライアントからデザイン、実装までが一気に完了できた。慣れたらこれくらいなら10分前後でできてしまうかもしれない。

とはいえいまのところ一番面倒な突合せ作業や修正作業をClineがやってくれている。そういう意味で成果物や環境設定のレビューなどClineも含めた全体作業をしっかりと見る必要はあるが、Clineの使い方を最適化していくことである程度の規模の開発業務であれば、かなり劇的に作業圧縮もできそうだ。

個人的には、ツールや環境の向き不向きを念頭に技術選択するなどまだいろいろ考えないといけない煩わしさはあるが、企画者が自分でプロトタイプしつつ要件定義するくらいのところまでは使い勝手含めて技術的にはもう届いていると思う。

## 参考文献

[実用的なMCP Clientを実装してMCPを理解する](https://zenn.dev/nasubikun/articles/1bce68db0763fd)
数学的変換のパターン形成

# ある数学的変換

$$
\psi(\partial \phi/\partial x_1,x_2) = \phi(x_1,x_2)-x_1 \partial \phi/\partial x_1
$$

変換を考えます。たとえば、

$$
E = 2S^2 - V^2 +4
$$

$S=x_1$, $V=x_2$とすると、

$$
\psi(x_1,x_2) = 2S^2 - V^2 +4 - S \times 4S
$$

$\partial E/\partial S=T=4S$なので、

$S＝T/4$を代入すると

$$
2\left(\frac{T}{4}\right)^2 - V^2 + 4 - \frac{T}{4} \times 4\left(\frac{T}{4}\right)
$$

$$
\frac{T^2}{8} - V^2 + 4 - \frac{T^2}{4}
$$

分母をそろえると：

$$\frac{T^2}{8} - \frac{2T^2}{8} - V^2 + 4
$$

最終的に：

$$
-\frac{T^2}{8} - V^2 + 4
$$

この形になります。$\psi = A(\partial \phi/\partial x_1=T,x_2=S)$なので

$$
A(T,V)=-\frac{T^2}{8} - V^2 + 4
$$

# 数式の意味について

ある関数 $\phi(x_1, x_2)$ に対して、変数 $x_1$ の偏導関数を用いた変換を表しています。これを解釈すると、次のような意味を持つ可能性があります。

$$
\psi\left(\frac{\partial \phi}{\partial x_1}, x_2\right) = \phi(x_1, x_2) - x_1 \frac{\partial \phi}{\partial x_1}
$$

これは、関数 $\phi$ から $x_1$ に関する項を調整した形を取っています。一般に、解釈が考えられます.

この形式は物理・数学のさまざまな分野で見られます。例えば、座標変換や力学系の解析に似た形が現れることがあります。
備忘録

```ruby:title.rb

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: DragInAreaExample());
  }
}

class DragInAreaExample extends StatefulWidget {
  @override
  _DragInAreaExampleState createState() => _DragInAreaExampleState();
}

class _DragInAreaExampleState extends State<DragInAreaExample> {
  final GlobalKey _targetKey = GlobalKey();
  bool _dragStarted = false;

  void _checkIfInsideTarget(Offset globalPosition) {
    final RenderBox box = _targetKey.currentContext?.findRenderObject() as RenderBox;
    final Offset position = box.localToGlobal(Offset.zero);
    final Size size = box.size;

    final rect = Rect.fromLTWH(position.dx, position.dy, size.width, size.height);

    if (rect.contains(globalPosition) && !_dragStarted) {
      setState(() {
        _dragStarted = true;
      });
      print('ドラッグ開始（範囲内に入った）');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Listener(
        onPointerMove: (event) {
          _checkIfInsideTarget(event.position);
        },
        onPointerUp: (_) {
          setState(() => _dragStarted = false);
        },
        child: Stack(
          children: [
            Center(
              child: Container(
                key: _targetKey,
                width: 200,
                height: 200,
                color: _dragStarted ? Colors.green : Colors.blue,
                child: Center(child: Text("この範囲にドラッグで入ってみて")),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

```

```ruby:title.rb

void _checkIfInsideTarget(Offset globalPosition) {
  final RenderBox box = _targetKey.currentContext?.findRenderObject() as RenderBox;
  final Offset position = box.localToGlobal(Offset.zero);
  final Size size = box.size;

  final rect = Rect.fromLTWH(position.dx, position.dy, size.width, size.height);

  final isNowInside = rect.contains(globalPosition);

  if (isNowInside && !_dragStarted) {
    setState(() {
      _dragStarted = true;
    });
    print('枠内に入りました（ドラッグ開始）');
  } else if (!isNowInside && _dragStarted) {
    setState(() {
      _dragStarted = false;
    });
    print('枠から出ました（キャンセル）');
  }
}


```
ADHD傾向のある人のための仕事のミス対策・記憶術まとめ（チェックリスト付き）

# ✅ ADHD傾向のある人のための仕事のミス対策・記憶術まとめ（チェックリスト付き）

ADHD傾向のある方が仕事で抱えやすい悩みと、それに対する**実用的な対処法・チェックリスト・記憶術**をまとめました。  
自分自身の備忘録としても、同じ悩みを抱える方の参考になればと思います。

---

## 🔻 よくある仕事上のミスとその対処法

| ミスの種類 | よくあるパターン | 主な対策 |
|-------------|------------------|-----------|
| 記憶ミス | 頼まれたことを忘れる／記憶があいまい | ・ToDoリスト・リマインド活用<br>・声に出して復唱<br>・その場でメモ |
| 段取りミス | 手順を飛ばす／順番を間違える | ・チェックリスト化<br>・手順をフローで図示<br>・マニュアルを自作 |
| 衝動ミス | 思いつきで行動／確認せずに送信 | ・一時停止ルール（10秒確認）<br>・「送信前に読み直し」の習慣化 |
| 早とちり | 「多分こうだろう」で動いて間違える | ・早とちり防止チェックリスト<br>・相手に再確認する習慣 |
| 情報整理が苦手 | 要点が分からず混乱する | ・3W（誰が・何を・なぜ）で分解<br>・視覚化（図解・マインドマップ） |

---

## ✅ 早とちり防止チェックリスト

仕事で「多分こうだろう」と先走ってしまいミスをすることが多い場合に効果的なチェックリストです。

□ これは確認済みの情報？それとも想像？
□ 指示・目的は正確に理解している？
□ チャット・資料・過去のメモを確認した？
□ 一度、誰かに確認・復唱できる？
□ 焦って確認を省略していない？
□ 自分の思い込み・解釈が入っていない？
□ 同じようなミスを前にもしていない？

※壁に貼る、付箋でモニタに貼る、スマホメモにしておくのがおすすめです。

---

## ✅ 業務内容がなかなか覚えられないときの工夫

### 🔸 工夫①：「自分専用マニュアル」を作る

自分の言葉で手順を簡単にメモ。実例：

📌 請求書処理の手順
① Excelファイルを開く（Z:\xxx\）
② 宛名と日付を確認（要チェック：過去データと照合）
③ 金額に誤差がないかチェック
④ 完了したら「済」フォルダへ移動
🟥 注意点：②の確認をよく忘れる！

### 🔸 工夫②：「見る・動く・話す」の3つを使って記憶する

- 手で書く
- 実際に操作する
- 声に出して確認する

### 🔸 工夫③：フロー図・図解で理解する

- 複雑な手順はフローチャート化
- 視覚情報で記憶に残りやすくする

---

## ✅ 要約・噛み砕きが苦手なときの考え方

| 方法 | 解説 |
|------|------|
| 「つまり一文で言うと？」を口に出す | 要点の整理に役立つ |
| 「だれが・なにを・なぜ」で分解 | メモが取りやすくなる |
| 図で整理／3つに分けて考える | 情報を視覚で把握 |
| 声に出して説明してみる | アウトプットすることで理解が定着 |

---

## 📌 最後に：工夫次第でミスは「激減」できる

ADHD傾向のある人が抱えるミスは、「工夫すれば防げるミス」がほとんどです。

- ✅ ミスを責めない、自分を責めない
- ✅ 忘れる前提で「仕組み」を用意する
- ✅ 自分なりのやり方（メモ／音読／図／チェックリスト）を持つ

---

## ✍ 参考・おすすめ

- 『ハーバード式 大人のADHDパーフェクトガイド』
- 『のび太・ジャイアン症候群』などADHD向け書籍
- 自作マニュアル例・タスク管理アプリ（Notion, Trello, Google Keep等）

---
【初心者向け】Linuxのパーミッションについて

## はじめに
Linuxを触りだすとディレクトリやファイルの所有権を確認したい、変更したいということがでてきます。本記事では初心者向けにLinuxの所有権について書きたいと思います。

ディレクトリの情報をみると以下のように表示されます。

`$ ls -l`
`-rwxr--r--  1 root root 114 Jun  6 2022 hello.py`
`drw-r--r--  1 root root  76 Jul 12 2022 hello.d`
`drwxrwxrwx  2 root root  37 Mar  9 2023 log`
`-rwxrwxr--  1 root root  26 Mar  1 2023 read.txt`

今回取り上げるのは、各行の左側の部分です。この部分が各ディレクトリやファイルのパーミッション（アクセス権）を表しています。
`-rwxr--r--`
`drw-r--r--`
`drwxrwxrwx`
`-rwxrwxr--`

## パーミッションの表記

パーミッションの表記は、以下のように４つに分解できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4074924/9355862b-facd-4e6e-973a-1821cc54b354.png)

左端の１文字はファイルの種類です。
上図にある通り、ファイル、ディレクトリ、シンボリックリンクであることを表しています。他にも種類はありますが、この３つを覚えておけば十分でしょう。

所有者は、そのファイルを作成した人です。
所有グループは、所有者が所属しているグループです。
その他ユーザーは、所有者以外のユーザー（ルートユーザーは除く）です。

アルファベットの意味は以下の通りです。
r　読み取り可能
w　書き込み可能
x　実行可能
‐　権限無し

上図のパーミッションを説明すると、「所有者は読み取り書き込み実行可能、所有グループは読み取りのみ可能、その他ユーザーも読み取りのみ可能なファイル」ということになります。

## パーミッションの設定

hello.pyというファイルのパーミッションの設定をする場合、コマンドは以下のように２種類使えます。
:one:数値モード　`$ chmod 744 hello.py`
:left_right_arrow:記号モード　`$ chmod u=rwx,g=r,o=r hello.py`

どちらを使うかは好みですが、数値モードを使った方が設定が楽なため、今回は数値モードの設定を紹介します。

今回の「744」という数値は、上図にもある「rwxr--r--」という意味の権限です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4074924/8c64a25a-b0bd-44a7-8486-8fd2ddbe8556.png)

数値は上図のように対応しています。
なぜこのような対応になるのかを説明します。
今回出てくる数値（７、４）を２進数にすると、
７＝１１１　　４＝１００
になります。つまり、下図のようになります。
![スクリーンショット 2025-06-18 032410.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4074924/625f45ce-bacb-46e0-86a8-fbdb29dd6380.png)

２進数の１のところがアルファベットになっていて、０のところが「ー (権限なし)」になっています。これが数値モードの本質です。

つまり所有者、グループ、その他ユーザーの付けたい権限のところに１がくるように２進数を設定し、それを10進数に変換してコマンドを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4074924/5c875418-0199-4273-83c0-159efd4fa4b0.png)

## もっと簡単に
数値モードでのパーミッションの設定は以上ですが、パーミッションの設定のたびに２進数考えて…っていうのは面倒くさいです。そこでもっと簡単にパーミッションの設定ができる考え方があります。

２進数と10進数の対応は下図のようになっていることを念頭に置いて…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4074924/bd29d88d-18e8-45e5-ba48-c47e21a30a73.png)
rwx　３つとも権限を付けたければ４+２+１=７
rw-　読み取り、書き込み権限だけ付けたければ４+２+０=６
r--　読み取り権限だけ付けたければ４+０+０=４
というようにパーミッションで設定する数値を計算できます。
:point_up:rwx は***４２１***と覚えれば簡単です！

以上、Linuxのパーミッションの設定でした。ここに書いてあることさえ覚えればパーミッションの設定は十分できるでしょう:muscle::muscle:

## 余談
コンピュータの世界では:zero:と:one:は非常に大事です。コンピュータは:zero:と:one:ですべての物事を理解します。（もっと本質的にいえば電圧が高い状態を:one:、低い状態を:zero:として認識します。）

だから２進数が大事になってくるわけですね。
:zero:＝OFF、無い、無効
:one:＝ON、ある、有効
みたいなイメージを持っておくといいでしょう。

実際にプリンターなどのパラメータ設定でも、特定のビットを:zero:から:one:にすると特定の機能が有効化されたりします。

これからコンピュータの世界で数字に出会ったら、それは本当は２進数なんじゃないかといった観点も持てるといいかもしれませんね。

それではみなさん、001000111101001111110011110001110000 :wave:
【Rails初学者】不要になったカラム(memo_id)を削除したのにエラーが出続けた話とその解決法

# 【Rails初学者】不要になったカラム（memo_id）を削除したのにエラーが出続けた話とその解決法

## はじめに
Railsで開発中、テーブル設計の変更により、`memo_id` カラムを `visits` テーブルから削除しました。  
しかし、その後もなぜか `memo_id` を参照しようとして `PG::UndefinedColumn` エラーが出続けてしまいました。

こちらの記事は、自分の備忘録として、実際にハマった原因と、その解決方法をまとめます。

---

## 起きたこと

1. 初期設計で、`visits` テーブルには `memo_id`（外部キー）カラムが存在していた
2. 設計見直しにより、`memo` は単なる `text` カラムとして `visits.memo` に直接保存するように変更
3. 以下のマイグレーションで `memo_id` を削除

```ruby
class RemoveMemoIdFromVisits < ActiveRecord::Migration[8.0]
  def change
    remove_column :visits, :memo_id, :integer
  end
end
```
4. `schema.rb`からも`memo_id`は削除されたことを確認

## それでも出続けたエラー
```bash
PG::UndefinedColumn: ERROR:  column "memo_id" of relation "visits" does not exist
LINE 1: ... "has_document", "memo_id", ...
```
`memo_id`は、もう削除したはずなのに

## 原因①：フォームやStrong Parametersの残骸
真っ先に疑ったのは、フォームやコントローラ。
- `visit_params`に`memo_id`はなし
- ビューにも`f.hidden_field :memo_id`のような記述なし
- モデルに`belongs_to :memo`もなし

## 原因②：`test/fixtures/visits.yml`に`memo_id:`が残っていた
確認したところ、これが原因でした
```yaml
# test/fixtures/visits.yml
one:
  user_id: 1
  visit_date: 2025-06-20
  memo_id: 1  # ← これが残っていた
```
### サーバーを再起動
```bash
bin/dev
# または
bin/rails server
```

## まとめ
- カラムを削除したのにエラーが出る場合、`fixtures/*.yml`を見落としがち
- Railsは`fixture`を元にカラム情報を推論することがある
- `grep memo_id`で一括検索すると見逃しを防げる

## 最後に
開発中もう消したはずのカラムがなぜか参照されるという場合は、
`test/fixtures`も忘れずにチェックする。

------
初学者のため、間違えていたらすいません。
Terraform + Vault + Ansibleで作る！特権アクセス管理の自動構築フロー完全解説【連載第2回】

☑ゴール

前回の連載第1回では、特権ID管理の全体像を整理しながら、Vaultを使った特権アクセス管理の構成方針を紹介しました。

本記事（第2回）では、 Terraform + Vault + Ansible を用いた、 完全自動構築フローの中核ステップを、 **「実装コード付き」かつ「1クリック展開可能な構成」**で徹底解説します。


---

⚡ Step 1 : TerraformでVaultの認証方式とポリシーを定義

resource "vault_auth_backend" "userpass" {
  type = "userpass"
}

resource "vault_policy" "pam_policy" {
  name   = "pam-admin"
  policy = <<EOT
path "secret/data/pam/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}
EOT
}

この構成により、Vaultにおける userpass認証 と PAM専用のアクセス制御ポリシーを定義できます。
すべてコード化されているため、再現性・監査性・自動展開性が大幅に向上します。


---

🔐 Step 2 : AnsibleでVaultのSecretを取得・反映

- name: Get PAM credentials from Vault
  uri:
    url: "https://vault.example.com/v1/secret/data/pam/credential"
    method: GET
    headers:
      X-Vault-Token: "{{ vault_token }}"
    return_content: yes
    status_code: 200
  register: pam_secret

- name: Set PAM credentials
  set_fact:
    pam_user: "{{ pam_secret.json.data.data.username }}"
    pam_pass: "{{ pam_secret.json.data.data.password }}"

Vaultに保存された認証情報を取得し、Ansible変数へ格納します。
以降のタスク内で pam_user / pam_passを呼び出して、SSHやDB設定へ安全に反映可能です。


---

🔄 Step 3 : GitHub ActionsでCI/CD構築 (任意)

jobs:
  pam_pipeline:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run Ansible Playbook
        run: ansible-playbook -i inventory setup-pam.yml

TerraformとAnsibleの処理をGitHub Actionsに組み込むことで、CI/CD化することで、 インフラ構成 + PAMの自動管理 が実現できます。


---

🔹 まとめ

TerraformでVaultのポリシーを定義

AnsibleでSecretを取得して変数化

GitHub ActionsでCI/CDに組み込み


この三問のフローにより、特権アクセスの安全性 + DevOps性を高深度で両立させる自動化構築が成立します。


---

⬆️ 次回予告

次回は、この構成を 本番システムに実践適用する際のテスト解析・CI/CD向けパイプライン組み込みテクニック を詳細解説します。

> → 「GitHub Actions + Ansibleで実現する、現場で使えるPAMステートパイプライン」




---

ご感想や質問は、どんどん歓迎です。 読んで頂き最後まで本当にありがとうございました。