OmniAICreator/Qiita-1.07M huggingface dataset:
Amazon Q CLI + pygame でゲーム制作【実装＆プレイ編／後編】

## はじめに

この記事は、前回公開した
「Amazon Q CLI + pygame でゲーム制作【環境構築編／前編】」
の続編となる、「実装＆プレイ編／後編」です。

まだ前編を読んでいない方は、先にこちらをご確認ください！
👉 [前編はこちら](https://qiita.com/tyumugiko/items/df2eacabf89170a5907b)

後編となる本記事では、いよいよ Amazon Q Developer CLI を活用して PyGame のゲーム実装を進めていきます。

## 作成するゲームに関して

今回作成するのは、**うさぎを撫でる** というテーマのゲームです。
現に私は、うさぎを飼っており「撫でさせてくれる日」と「警戒して逃げてしまう日」があります。
その体験をもとに、「うさぎに見つからないように近づき、タイミングを見計らって撫でる」というルールのゲームを考えました！
イメージとしては**だるまさんがころんだ**です。

プレイヤーはうさぎに近づき、見つからずに撫でることができれば成功となります。

この設定をもとに、Q CLI にゲームコードの生成を依頼していきます。

## Q CLI にゲーム作成の指示を出す

Amazon Q CLI（Q Developer）に対してゲーム作成の指示を出す際には、なるべく詳細かつ明確な要件を提示することで、意図したコードを生成してもらいやすくなります。

今回は、そのために Markdown形式の要件定義書 を用意し、それを読んで開発するように、Q CLIに指示を出しました。

以下が実際に使用した要件定義書です。

<details><summary>要件定義書</summary>

```markdown
# うさぎを撫でろ！

これから開発するゲームの概要を記載する。
ゲームのタイトルは「うさぎを撫でろ！」である。

## ゲーム概要

「うさぎを撫でろ！」は、PyGameで開発されるPC向けゲームです。プレイヤーはうさぎに気づかれないように近づき、撫でることを目指します。だるまさんがころんだの要素を取り入れつつ、うさぎの機嫌度に注意しながら、クリアを目指すゲームです。

## ターゲットプラットフォーム

PC（Windows/Mac/Linux）
開発環境：PyGame

## グラフィック・サウンド

グラフィック: PyGameで表現可能な範囲でのグラフィックを使用します。テイストについては今後の議論で決定します。
サウンド: PyGameで表現可能な範囲でのサウンド（BGM、効果音）を使用します。

## ゲームサイクル

タイトル画面：ゲーム開始、オプション、終了などの選択肢を表示。
ゲーム開始：メインゲームプレイ開始。
プレイ画面：プレイヤーがうさぎに近づく操作を行う。うさぎの挙動を監視し、機嫌度を管理。
クリア/ゲームオーバー：
クリア: うさぎを撫でることに成功した場合。
ゲームオーバー: うさぎに気づかれ、機嫌度が0になった場合。
結果表示：クリアまたはゲームオーバーの結果を表示。
タイトル画面に戻る：次のプレイのためにタイトル画面へ遷移。

## プレイヤー操作

入力デバイス: マウス
操作内容:
左クリック: うさぎへ向かって移動する操作。
右クリック: 移動を停止する操作。
うさぎが振り返っている間は、プレイヤーは左クリックでの移動を停止する必要があります。停止しない場合、うさぎの機嫌度が減少します。

## うさぎの挙動

発見条件:
視覚: うさぎの視界（視野角や範囲）にプレイヤーが入ると、プレイヤーを発見します。
聴覚: プレイヤーの移動操作に伴う音（例: 一定距離以上近づいた場合の足音など）をうさぎが感知すると、プレイヤーを発見します。
機嫌度: うさぎには「機嫌度」が設定されており、プレイヤーが発見されるたびに減少します。機嫌度が0になるとゲームオーバーとなります。
振り返り: うさぎはランダムまたは一定のパターンで振り返り、プレイヤーの動きを確認します。振り返っている間は、プレイヤーは停止しなければなりません。

## 勝利・敗北条件

勝利条件:
うさぎに一定の距離まで近づき、かつ特定の条件（例: うさぎが前を向いている状態）を満たした上で、所定の操作（例: マウス左クリック）を行うことで、うさぎを撫でることができたと判定し、ゲームクリアとなります。
敗北条件:
うさぎに発見され、機嫌度が0になった場合、ゲームオーバーとなります。

## ステージ構成・レベルデザイン

初期段階では、1つのシンプルなステージのみを実装します。
このステージで基本的なゲームメカニクスとプレイヤーの体験を検証します。

## その他

まずは最低限の機能（MVP: Minimum Viable Product）の実装を目指します。
具体的なグラフィックやサウンドのアセット、うさぎの機嫌度や移動速度などの詳細な数値設定は、開発を進めながら調整します。
```
</details>

## 完成したゲーム（初期バージョン）

最初に出来上がった初期バージョンのゲームがこちらです。

![image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112040/0b7d4278-0291-46a7-8821-747f19614bbc.png)

……ご覧のとおり、文字は文字化けし、登場キャラクターも「人」や「うさぎ」には見えない謎の存在になってしまいました。
ゲームとしての基本的な構造はできているものの、視覚的にもプレイ感としてもまだまだ改善が必要です。

文字化けの修正をはじめ、改善点をいくつかあげ、修正などを行ってもらいました！

## 最終完成版

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112040/94d2a535-0d20-41d5-85ad-20208528f338.gif">

ソースコードは以下のリポジトリにアップしています。

https://github.com/tyumugi1113/nade-usagi


## まとめ

以上、Amazon Q CLI を使ってゲームを作ってみました！

無料枠でも思った以上にちゃんと遊べるものができて驚きました。最初の出力はちょっとアレでしたが、こちらの指示次第でかなり修正・改善できます。

とはいえ、察し力にはそこまで期待できないので、「なんとなくこうしてほしい」みたいなふんわりした指示ではうまくいきません。要件をちゃんと書いて伝えることが大事だと感じました！

要件定義書は、人が開発するのでもAIでも大事さは変わらないな～と思いますね！

正直、普通のエンジニアより素直で手早いので、いろいろ考えさせられました。
これからはこういうツールをうまく活かせるスキルも求められそうですね。。。

以上、ありがとうございました！！！

## 参考

https://github.com/tyumugi1113/nade-usagi
MacFUSE導入時のセキュリティ設定変更

自分用まとめ

目次
- [導入](#導入)
- [手順](#手順)
    - [リカバリーモードのユーティリティでやること](#リカバリーモードのユーティリティでやること)
    - [リカバリーモードのターミナルでやること](#リカバリーモードのターミナルでやること)
    - [再起動後のターミナルでやること](#再起動後のターミナルでやること)
    - [システム設定のプライバシーとセキュリティでやること](#システム設定のプライバシーとセキュリティでやること)

# 導入

macfuse導入後にmacbookのセキュリティ設定を変更しないと、マウントしてきたローカルのファイルにlsコマンドやmvコマンドが打てなかった。

# 手順

### リカバリーモードのユーティリティでやること

1. Macの電源を一度切り、長押ししてオプションを開く
2. ユーティリティ > 起動セキュリティユーティリティを開く
3. 「セキュアブートのレベル」を「完全なセキュアブート」以外に設定
4. 「許可されたカーネル拡張」を「管理者による承認が必要」から「許可する」に設定
5. Macを通常のモードで再起動

### リカバリーモードのターミナルでやること
以下のコマンドを入力：
```
$ csrutil disable
```

### 再起動後のターミナルでやること
以下のコマンドを入力：
```
$ csrutil status

# disabledと出てきたらOK
```

### システム設定のプライバシーとセキュリティでやること

開発者"Benjamin Fleischer"を許可
#0168（2025/06/13）DHCPの解説

# はじめに

IPv4/IPv6 ネットワークの自動設定を支える Dynamic Host Configuration Protocol（DHCP）は、家庭の Wi‑Fi ルータからデータセンタ、クラウド VPC に至るまで不可欠なインフラです。本記事では、DHCP の概要と使い方を復習しつつ、

* 個人向け小規模ネットワーク（住宅・SOHO の Wi‑Fi）
* 企業やキャンパスなど中大規模ネットワーク
  の設計・運用差異を 3,500 文字程度で整理します。

---

## 1. DHCP とは

* **役割**: IP アドレス、サブネットマスク、デフォルトゲートウェイ、DNS サーバなどをクライアントへ自動配布し、手動設定ミスと運用コストを削減。
* **プロトコル種別**: UDP 67/68 番ポート、ブロードキャスト/ユニキャスト併用。
* **基本フロー (DORA)**

  * **Discover**: クライアントが 0.0.0.0 からブロードキャストで「誰か IP くれませんか?」
  * **Offer**: サーバが利用可能な IP と各種オプションを提示
  * **Request**: クライアントが希望 IP を宣言し取得要求
  * **Ack**: サーバが確定通知しリーススタート

## 2. DHCP の構成要素

* **サーバ**: isc‑dhcpd、dnsmasq、Windows DHCP、Cisco IOS 等が代表例。
* **クライアント**: OS 内蔵の dhclient、systemd‑networkd、NetworkManager、モバイル OS のスタックなど。
* **リレーエージェント**: ルータや L3 スイッチが Option 82 を付加し、異なるサブネットへユニキャスト転送。
* **主要オプション**:

  * Option 1: Subnet Mask
  * Option 3: Router
  * Option 6: DNS
  * Option 15: Domain‑Name
  * Option 43/60: ベンダ固有情報（VoIP 電話の自動プロビジョニングなど）

## 3. 小規模 Wi‑Fi ネットワークでの DHCP

### 3.1 一体型ホームルータ

* 多くは AP・NAT・DHCP が統合された SoC。GUI でメインプールを 192.168.x.0/24 に設定し、範囲は .2–.254 がデフォルト。
* リース時間は 24h–7d 程度。短くすると再認証が増え接続切れ要因になる。

### 3.2 典型的設定手順

1. 管理画面で DHCP サーバ機能を有効化。
2. IP プール範囲を決定（例 192.168.10.100–150）。
3. 予約アドレス (Static DHCP) で NAS・プリンタを固定。

### 3.3 運用のポイント

* **IP 衝突防止**: LAN 内で手動固定 IP を併用する場合、プール外レンジへ配置。
* **UPnP 自動ポート開放**: 安易に有効化すると脆弱性露呈。必要最低限で。
* **ファーム更新**: DHCP Daemon の脆弱性修正は FW 更新でしか対処できない。定期確認必須。

### 3.4 典型的トラブルと対策

* **APIPA 169.254.x.x**: サーバ不達 ⇒ ルータ再起動 or LAN ケーブル断線確認。
* **リース枯渇**: IoT 機器の増加で `/24` 上限 253 台に到達。サブネット拡張または不要機器削除。

## 4. 中大規模ネットワークでの DHCP

### 4.1 サブネット分割とリレー

* フロア / VLAN ごとに `/24` 以上を割当。DHCP サーバはデータセンタに集約し、各 L3 デバイスで ip helper‑address を設定。
* Option 82 (Circuit‑ID, Remote‑ID) でどのスイッチ/ポート配下か特定し、きめ細かいアドレス配布と監査を実施。

### 4.2 可用性とプール設計

* **冗長構成**: DHCP フェイルオーバープロトコル (isc‑dhcpd)、Windows DHCP failover、Infoblox Grid など。
* **プール分割 (Split‑Scope)**: 80/20 ルールで 2 台にアドレス分散し障害時も枯渇を防止。

### 4.3 IPAM 連携と動的 DNS

* 多拠点でのアドレス一元管理は IPAM (BlueCat, Men\&Mice) が事実上必須。
* 更新時に DDNS (RFC2136) 連携しホスト名 → IP がリアルタイム同期。

### 4.4 セキュリティ

* **DHCP Snooping**: 信頼ポートのみ Offer/ACK を許可、Rogue サーバ対策。
* **802.1X + MAB**: 認証後に VLAN 割当、DHCP リース開始を連携。
* **ACL/ファイアウォール**: DHCP レイヤではなく L4/7 で業務アプリを制御。

### 4.5 大規模 Wi‑Fi

* コントローラベース WLAN では VLAN プールと DHCP リレーで数万端末に対応。
* Fast‑Secure Roaming（機器移動時の再アドレス不要）には同一 L3 ドメイン設計が鍵。

## 5. 小規模と中大規模の違い総括

### 5.1 スコープとアドレス管理

* 小規模: `/24` 1 つ＋予約数件で運用可。
* 中大規模: マルチプール + IPAM が前提。VLAN 広告と紐付け必須。

### 5.2 可用性

* 小規模: ルータ 1 台障害＝ネット全停止が許容範囲。
* 中大規模: デュアルサーバ + Anycast VIP など高可用設計。

### 5.3 ログと監査

* 小規模: Syslog 任意。問題時にコンシューマ機器を再起動。
* 中大規模: GDPR/JSOX 対応で 7 年アーカイブ、SIEM 連携が常態化。

### 5.4 自動化 / API

* 小規模: 手動 GUI が主流。
* 中大規模: REST API, Ansible モジュール, Terraform Provider でスコープ追加や予約を IaC 化。

## 6. まとめ

DHCP は単なる IP 配布役を超え、**アドレス管理・ネットワークアイデンティティ・セキュリティ制御の要**へと進化しています。小規模 Wi‑Fi 環境ではシンプル運用で十分ですが、中大規模ネットワークではリレー、冗長化、IPAM、動的 DNS、監査ログまで統合したエコシステムが不可欠です。

> **Key Takeaway** : DHCP の設計範囲はネットワーク規模とビジネス要件で大きく変わる。上流設計段階で「アドレス割当ポリシー」「可用性」「自動化戦略」を合意形成しておくことで、後工程の運用コストと障害リスクを最小化できます。
#0167（2025/06/13）NATの解説

# はじめに：NATが誕生した背景

1990年代後半、IPv4アドレス枯渇が現実味を帯び始めた。そこで登場したのがNetwork Address Translation (NAT)。プライベートIP空間とグローバルIP空間を相互変換し、家庭からエンタープライズ、クラウドまで広く普及した。本稿では、エンジニアが押さえるべきNATのメカニズム、実装、課題、そしてIPv6時代の展望を3000文字で俯瞰する。

## 1. NATの基礎知識

* アドレス枯渇対策：RFC1918で定義された10.0.0.0/8、172.16.0.0/12、192.168.0.0/16の私的アドレス空間を内部に、有限なグローバルアドレスを外部に配置。
* 基本コンセプト：転送経路上でIPヘッダを書き換え、送信元(SNAT)または宛先(DNAT)を置換。典型的ホームルータはNAPT(PAT)でポート番号まで多重化。

## 2. NATテーブルとアルゴリズム

ルータは《内部IP:内部ポート→外部IP:外部ポート》のマッピングエントリを生成し、一定時間アイドルで削除する。実装差分はあれど、多くはハッシュテーブルでO(1)ルックアップを実現。TCPは4タプル、UDPは5タプル＋状態で管理し、ICMPは識別子で追跡する。

## 3. NATの分類

* SNAT：送信元IPを書き換えて外部へ。クラウドVPCのアウトバウンド通信に多用。
* DNAT：宛先IPを書き換えて内部へ。ポートフォワーディングの本質。
* NAPT(PAT)：IP＋ポートを併用し、数万ホストを1個のグローバルIPに集約。
* NAT64/46：IPv6 ↔ IPv4変換。移行期のゲートウェイとして機能。
* NAT66：IPv6↔IPv6のアドレス隠蔽。技術的には可能だが原則非推奨。

## 4. 代表的な実装例

* Linux iptables/nftables：`POSTROUTING -j MASQUERADE` が典型。nf\_conntrackで状態管理。
* Cisco ASA：`nat (inside,outside) dynamic interface` によりSNAT。
* AWS NAT Gateway：スケーラブルなマネージドSNAT。1‐N変換を冗長構成で自動化。

## 5. NAT越え技術

* 直接方式：静的ポートフォワーディング、DMZ、UPnP/PCPによる自動開放。
* 中継方式：STUNで候補取得、TURNでメディアリレー、ICEで経路選択。WebRTCやVoIPで必須。
* トンネル方式：OpenVPN/WireGuardで仮想NICを張り、NATを透過する。

## 6. セキュリティと運用上の論点

* "NAT = ファイアウォール" は誤解。状態追跡は副次的効果に過ぎず、ACLやFWで明示的に制御を。
* ログ：NAPT環境では Syslog+NetFlow で外部ポートを含めて記録しなければ、利用者特定が困難。
* アプリ依存性：FTP, SIP, H.323 などアドレスをペイロードに埋め込むプロトコルはALG(Application Layer Gateway)が必要。

## 7. IPv6時代の再考

IPv6では各ホストがグローバルユニキャストアドレスを持ち、エンドツーエンド接続が復活する設計。ただし企業ポリシー上、アドレス秘匿や多段NAT66を導入するケースもゼロではない。ポイントは「NATで守る」のではなく、IPv6向けステートフルFWとIDS/IPSで層防御を行うこと。

## 8. コンテナ・マイクロサービスとNAT

Dockerはユーザ空間でveth + bridgeを組み、デフォルトでSNAT(MASQUERADE)を適用。Kubernetesではkube-proxyまたはCNIプラグインがNAT/Overlayを制御する。EgressトラフィックのIPを固定化したい場合、AWSのEgress-Only GatewayやStatic Egress NATが解となる。

## 9. NATスケールの課題と最適化

* CGN(Carrier Grade NAT)：ISPが数百万セッションを束ねる。タイムアウト短縮やアグレッシブなポート再利用でスケール。
* ハードウェアオフロード：ASIC/SmartNICでNATルックアップを処理し、CPU負荷を削減。

## 10. まとめ：エンジニアが今押さえるべきポイント

* IPv4運用は当面続く。NATテーブル枯渇・ログ保全・ALGバグに備える。
* 新規システムはIPv6ネイティブ＋FWを前提設計し、NAT依存を減らす。
* NAT越え要件(VoIP/リアルタイム通信)は初期段階で設計に織り込む。
* クラウドではNAT Gateway/Transit Gatewayの料金と性能上限を把握し、必要ならPrivateLinkやDirect Connectを検討。

> **Key Takeaway**: NATはIPv4の延命装置から、クラウド／コンテナ時代のトラフィック制御技術へと役割を変えつつある。IPv6普及後も“アドレス変換”という考え方自体は残るが、セキュリティと観測性を両立させるためには、NAT以外の層での設計が不可欠だ。
商品詳細・カート機能のオプションデータ型ハンドリング実践記録

````markdown
# 商品詳細・カート機能のオプションデータ型ハンドリング実践記録

## 1. 背景・課題意識

ECサイト開発において、「商品オプション」（例：サイズやカラー選択など）データの管理は非常に重要なポイント。  
しかし、バックエンドAPIやDBから返却される「オプションデータ」の型が  
- **配列型**（例：`[{key: 'option1', value: 'A'}, {key: 'option2', value: 'B'}]`）  
- **オブジェクト型**（例：`{"option1": "A", "option2": "B"}`）  
どちらも想定される場合、フロントエンドでの扱いに注意が必要。

**TypeError: ...map is not a function**  
という典型的なエラーもこの「型不一致」によって発生する。

---

## 2. 今日学んだポイント

### 2.1 オプションデータの受け渡しフローと型変換

#### 商品詳細ページからカートまでの流れ
- 商品詳細ページ（`ProductDetailsPage`）で商品情報・オプションデータをAPI取得
- 子コンポーネント（`ProductSelectionForm`など）へpropsでオプションデータを渡す
- さらに`SelectBox`や`ProductItem`等のコンポーネントにオプション配列を渡す

#### 例: オプションデータがオブジェクト型の場合
```js
const productOptions = { "option1": "A", "option2": "B" }
````

#### 例: オプションデータが配列型の場合

```js
const productOptions = [
  { key: 'option1', value: 'A' },
  { key: 'option2', value: 'B' }
]
```

#### 共通で配列型に変換する防御関数

```ts
type Option = { key: string; value: string }

function normalizeOptions(options: any): Option[] {
  if (Array.isArray(options)) return options
  if (options && typeof options === 'object')
    return Object.entries(options).map(([key, value]) => ({
      key,
      value: String(value),
    }))
  return []
}
```

#### 使用例（カート内アイテムのオプション表示時）

```tsx
<ProductItem
  options={normalizeOptions(item.productOptions)}
  ...
/>
```

これにより「オブジェクト型」「配列型」「未定義」のどれがきても安全に対応できる。

---

### 2.2 型不一致・エラーへの対応例

* mapがundefinedやオブジェクトに対して使われるとエラーになる
* `Array.isArray()`で配列かどうかチェックし、オブジェクトなら`Object.entries()`で配列に変換
* APIのレスポンスを完全に信じず、**必ずフロント側で型チェック＆正規化**を行う

---

### 2.3 React/TypeScriptの型安全の恩恵

* コンポーネントPropsの型を厳密に定義することで意図しないデータ流入を防げる
* それでもAPIやDB側の設計が曖昧な場合はnormalize関数で正規化する設計が有効
* 「propsの型（Option\[]）」⇔「API/DBの型（objectまたはarray）」を切り離すことで実装の柔軟性UP

---

### 2.4 フロントでのエラー防止パターン

* 空オブジェクト`{}`、null、undefined、空配列`[]`なども全て`normalizeOptions`で吸収
* どんなデータが来てもUIは安全に動作
* ユーザー体験の一貫性も向上

---

## 3. 所感・学び

今回の実装で

* 「バックエンド都合の不安定なデータ型」はフロント側で正規化して“吸収”する
* フロント側で「Option配列型」を標準インターフェースにすることで、他コンポーネント流用も簡単
* TypeScript×Reactの型・関数活用で**バグ防止**＆**拡張性の高いコード設計**ができる
  と感じた。

特に実務・PJ内でAPI仕様がまだ統一されていないとき、
このような「受け口での正規化処理」を用意することで
大規模開発・多人数開発でもトラブルが少なく、
保守しやすいフロントエンドになると実感。

---

## 参考リンク

* [React ドキュメント](https://react.dev/)
* [TypeScript Handbook - 型の使い方](https://www.typescriptlang.org/docs/)
* [MDN - Object.entries()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/entries)
* [Qiita: map is not a function エラーの対策](https://qiita.com/search?q=map+is+not+a+function)

---

**明日以降も引き続き、実運用を想定した型安全なUI設計・データフローの強化を進めていきます。**

```
```
UBUNTU上でQEMUを用いてXPをインストール

## 起動
以下からISOを取得します。
https://archive.org/details/WinXPProSP3SimplifiedChinese

その後仮想HDDを生成し、ISOから起動しインストールします。
```
qemu-img create -f qcow2 xp.img 20G

qemu-system-i386 \
  -m 512 \
  -hda xp.img \
  -cdrom zh-hans_windows_xp_professional_with_service_pack_3_x86_cd_vl_x14-74070.iso \
  -boot d \
  -vga std \
  -rtc base=localtime \
  -enable-kvm
```

## 起動
画面に従ってインストール
![图片.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/357e5a1e-8570-4874-96c6-3f9eaa7906d7.png)


## 完了
一度電源を落とします
![图片.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/d409e27e-3eaa-4ba8-b2d6-834dfed32f4f.png)

## 再起動
再起動後に解像度を1600×900にするとCtrl+Alt+Fで画面を最大化した時に綺麗に映ります。
```
qemu-system-i386 \
  -m 1024 \
  -hda xp.img \
  -boot c \
  -cpu host \
  -smp 2 \
  -net nic -net user \
  -vga std \
  -rtc base=localtime \
  -enable-kvm \
  -usbdevice tablet
  ```
  ![图片.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/9bd28f00-8a93-4054-83ad-4a5866e51bf7.png)
ChatGPTに聞いた基本設計書の執筆ポイントを抜粋してみた

# はじめに
本記事では、あるプロジェクトで AWSインフラ基盤の基本設計書 を作成した際に、ChatGPTを活用して得られた知見が役立ったため、その内容を紹介します。
特に「設計書の書き方が分からない」「表記や構成で迷う」といった方の参考になれば幸いです。

# 基本設計書とは？
まず、「基本設計書とは何か？」について、ChatGPTに聞いてみた結果が以下です。

> + 要件定義をもとに「どう作るか」を設計する文書
> + システム全体の構成・機能・方式を明確にする
> + 実装・詳細設計・テスト・運用の土台になる

つまり、基本設計書はプロジェクトの上流工程と下流工程をつなぐ、重要なドキュメントです。

# 基本設計書のフォーマットと表記ルール
基本設計書を執筆していくうえで、プロジェクトに標準のテンプレートがあればそれを利用しますが、そうでない場合は一から設計書のフォーマットを作成する必要があります。以下では、私が設計書をまとめるうえで意識した表記・構成ルールを紹介します。

**1. 用語・表記の統一**

| 項目 | 表記例 | 補足 |
|------------|------------|:------------|
| 半角/全角 | 数字・英字・記号は半角、カタカナは全角 | 「10MB」「ユーザー」など |
| 用語の統一 | 「ログイン」 vs「サインイン」→「ログイン」で統一 | 文書内で統一する |
| 略語 | 初出時に定義し、以降は略語を使用 | 「SLA：Service Level Agreement」など |

**2. 数値・単位のルール**

| 項目 | 表記例 | 補足 |
|------------|------------|:------------|
| 数値 | 半角数字を使用、3桁区切り | 例：「1,000件」 |
| 単位との間 | 半角スペース | 「10 秒」「512 MB」など |

**3. 図表・番号付けルール**

| 項目 | 表記例 | 補足 |
|------------|------------|:------------|
| 図の番号 | 「図 x-y：タイトル」形式 | 図 3-2：システム構成図 |
| 表の番号 | 「表 x-y：タイトル」形式 | 表 5-1：データ定義一覧 |

**4. フォーマット・構成ルール**

| 項目 | 表記例 | 補足 |
|------------|------------|:------------|
| フォント | 日本語：MS ゴシック、英数字：Arial または Consolas | Wordであればスタイル作成を推奨 |
| 表の番号 | 「表 x-y：タイトル」形式 | Wordであれば表番号を自動的に割り振ることを推奨 |

# 基本設計書を執筆する際の注意点

以下の点は、設計書を書く上で気を付けるポイントです。

+ 「現行踏襲」という表現は使わない（理由のない設計は避ける）
+ ITに詳しくない方でも理解できる言葉で書く
+ 長文になりすぎないよう、簡潔に表現する
+ 図や表を積極的に活用し、視覚的に分かりやすくする
+ 要件定義との乖離がないよう内容を整合させる
+ 各項目の設計理由や選定根拠を明記する


# AWSインフラ基盤における基本設計書の章構成例

以下は、AWSをベースとしたインフラ基盤における基本設計書の構成例です。

```
第1章 はじめに
1.1 文書の目的

1.2 対象システム・構成範囲

1.3 対象読者

1.4 用語・略語定義

第2章 システム要件と前提
2.1 システムの非機能要件（可用性・性能・セキュリティなど）

2.2 利用AWSアカウントとリージョンの構成

2.3 運用・保守の前提条件（体制、作業分担など）

第3章 全体構成概要
3.1 インフラ構成図（論理構成図／物理構成図）

3.2 構成概要（利用AWSサービス一覧と役割）

3.3 マルチアカウント戦略（必要に応じて）

3.4 環境構成（開発・検証・本番の区分）

第4章 ネットワーク設計
4.1 VPC設計（CIDR、AZ配置、サブネット分割）

4.2 ルーティング設計（IGW、NAT Gateway、TGWなど）

4.3 セキュリティグループ／NACL設計

4.4 ハイブリッド構成（Direct Connect／VPN）【必要に応じて】

第5章 コンピューティング設計
5.1 使用サービス（EC2／ECS／Lambda 等）

5.2 AMI／Auto Scaling設計

5.3 インスタンスタイプと配置戦略（マルチAZ、耐障害性）

5.4 ロール（IAMインスタンスプロファイル）

第6章 ストレージ設計
6.1 S3バケット構成とライフサイクル設定

6.2 EBS設計（ボリュームタイプ、バックアップ）

6.3 その他ストレージ（EFS、FSxなど）

第7章 データベース設計（必要に応じて）
7.1 RDS／Aurora構成（マルチAZ、リードレプリカなど）

7.2 パラメータ設計（暗号化、パッチ管理）

7.3 DynamoDB／ElastiCacheなどの採用時記載

第8章 セキュリティ設計
8.1 IAM設計（ポリシー、ロール、グループ、最小権限の原則）

8.2 暗号化ポリシー（S3、RDS、KMSなど）

8.3 通信暗号化（HTTPS、TLS、ACM）

8.4 WAF／Shield／GuardDuty等の活用方針

第9章 運用・監視設計
9.1 CloudWatchログ・メトリクス設計

9.2 アラートと通知設計（SNS、Lambda連携）

9.3 バックアップ・リストア設計（RTO/RPO含む）

9.4 障害時対応フローと責任分担

9.5 システム変更・デプロイ方式（IaC、CI/CDなど）

第10章 コスト管理・最適化
10.1 コスト見積もり（AWS Pricing Calculator）

10.2 料金の分割とタグ設計（Cost Allocation Tags）

10.3 RI／SP活用方針とスケーリング設計

10.4 モニタリングとアラート（AWS Budgets）

第11章 セキュリティ・コンプライアンス対応
11.1 AWS Well-Architectedフレームワークへの準拠状況

11.2 監査ログ（CloudTrail、Config、Access Analyzer）

11.3 セキュリティチェックリスト（Security Hub等）

11.4 適用される法令や社内規定（ISO、FISCなど）

第12章 付録・参考資料
12.1 設計判断の根拠と比較検討内容

12.2 詳細構成図（PDF/Visio/Draw.ioなど）

12.3 バージョン履歴・更新記録

12.4 用語集・略語集

```
はじめてのバージョン管理：開発を始めるための準備ガイド

# 対象読者
* プログラミングや開発を始めたばかりの人
* 「git？GitHub？聞いたことあるけどよくわからない…」という人

# これから出てくる用語の解説

まずはこのガイドでよく出てくる3つの言葉を、超ざっくり簡単に紹介しておきます。

## gitとは？

「git（ギット）」は、プログラムの作業履歴を記録してくれるツールです。
たとえば、間違ってコードを消してしまっても、「前の状態」に戻すことができます。
ゲームでいう「セーブ機能」のようなものです。

## GitHubとは？

「GitHub（ギットハブ）」は、gitのデータをインターネット上で保存・共有できるサービスです。
チームで開発したり、自分のコードをバックアップしたりできます。

## GitHub Desktopとは？

「GitHub Desktop」は、GitHubをもっとカンタンに使えるようにするためのアプリです。
ふだんは難しいコマンドを使わないといけないgitも、ボタン操作だけで使えるようになります。


# 環境構築をしよう

ここからは、開発を始めるための準備（＝環境構築）をしていきます。

## 1. GitHubのアカウントを作ろう

1. GitHubのサイトにアクセス
   　→ [https://github.com/](https://github.com/)
2. 右上の「Sign up（サインアップ）」をクリック
3. メールアドレスやパスワードを入力して、アカウントを作成します
4. 確認メールが届くので、メール内のリンクをクリックして認証します

後に、作成した時の **メールアドレス** と **ユーザー名** を使用します!!

## 2. gitの環境構築

### 【Windowsの場合】

1. 以下の公式サイトにアクセスします
   　→ [https://git-scm.com/](https://git-scm.com/)

2. 画面中央の「Download for Windows」をクリックして、インストーラー（.exeファイル）をダウンロードします

3. ダウンロードした `.exe` ファイル（例：`Git-2.43.0-64-bit.exe`）をダブルクリックして実行します

4. インストーラーが起動したら、**基本的にすべて「Next」でOK**です。

5. 最後に「Install」をクリック → 完了後「Finish」でインストール終了です

6. **コマンドプロンプトを開いてインストール確認**
   　コマンドプロンプトを起動し、以下のコマンドを入力：

   ```
   git --version
   ```

   例：`git version 2.43.0.windows.1` など、とにかくバージョンが表示されればOK！

---

### 【Macの場合】

1. 「ターミナル」アプリを開きます（Launchpadで「ターミナル」と検索）

2. 以下のコマンドを入力して、Enterキーを押します：

   ```
   git --version
   ```

3. もしgitが入っていない場合は、「Command Line Developer Tools をインストールしますか？」というダイアログが表示されます。
   　→ 「インストール」をクリックして完了を待ちます（数分で終わります）

4. 再び以下のコマンドを実行して、バージョンが表示されればOK：

   ```
   git --version
   ```

---

### 【共通：gitの初期設定をしよう】
Gitをインストールしたら、**あなたの名前とメールアドレスを登録する必要**があります。
これは、「誰がそのコードを書いたか」をGitが記録するための設定です。

> 💡ここで使う名前とメールアドレスは、**先ほどGitHubのアカウント作成で登録したものと同じもの**を使いましょう。
> （GitHubと一致させることで、連携がスムーズになります）

以下のコマンドを、コマンドプロンプト（またはMacのターミナル）で入力してください：

```bash
git config --global user.name "あなたのGitHubユーザー名"
git config --global user.email "あなたのGitHubメールアドレス"
```

**例：**

```bash
git config --global user.name "TaroYamada"
git config --global user.email "taro@example.com"
```

設定内容を確認するには、次のコマンドを入力します：

```bash
git config --list
```

表示されたリストに、`user.name` と `user.email` がちゃんと反映されていればOKです！



## 3. GitHub Desktopのインストール

1. GitHub Desktopのページにアクセス
   　→ [https://desktop.github.com/](https://desktop.github.com/)
2. 「Download for Windows（またはmacOS）」をクリックしてダウンロード
3. ダウンロードしたファイルを開き、画面の指示に従ってインストール

インストール後、最初にGitHubアカウントでログインしておくと便利です。

ここまでできたらお疲れ様！！
AWS完全初心者がBuilderCardsで無双した話

## はじめに
こんにちは。Tsukasaです！
    今日は先日6/3にJAWS-UG初心者支部で行われたBuilderCardsに参加してきたことについて記事にしようと思います。
このイベント実は前から興味があったのですが、中々参加することができませんでした。
初心者支部のみならず、いろんな支部で開催されているようなので、興味のある方は是非チェックしてみてください。それでは早速見ていきましょう！

https://jawsug-bgnr.connpass.com/event/355198/


## BuilderCardsとは

BuilderCardsとはAWSのサービスについてカードゲームを通して学習できるコンテンツです。
JAWS DAYSなどのオフラインイベントではこのBuilderCardsの大会が開かれたりするなど、AWS学習者にとっては知る人ぞ知るカードゲームなのです。ルールや詳細につきましては、下記のリンクからご確認ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2478024/6e63a862-1718-4fd7-b5d5-e00f07655aba.png)




https://aws.amazon.com/jp/builders-flash/202405/japanese-builder-cards/#:~:text=AWS%20BuilderCards%20%E3%81%AF%E3%80%81Amazon%20Web,%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%81%A8%E5%91%BC%E3%81%B0%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82

## 簡単なルール
ルールはリンクから確認してくださいと言いましたが、自分自身のアウトプットのために簡単に説明します。
やることとしては、手持ちのAWSカードのポイントで、AWS-Well-Archtectedカードを集め、そのポイントが一番高い人の勝ちです。

最初はこのようにオンプレミスのカードだけが配布されます。
そこからAWSのカードを順番に引いていき、オンプレミスからAWSに移行するというのがゲームの流れになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2478024/b64df411-95fb-470a-a478-5a368d9911a0.png)

## このゲームで学べること
ゲームなので、勝つことも大切ですが、それ以上に大切なことは、このゲームを通してAWSのサービスについて学べるということです。
1つ1つのサービスについては理解していても複数のサービスを組み合わせるアーキテクチャは初心者にとっては難しいですよね？
ですが、このBuilderCardsではそういったことも学べるのです。
例えば下記のカードを見てください。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2478024/4a4880c5-7f6b-4ad7-868e-c6b3c5a7a4cd.png)

こちらはLambdaとAPI Gatewayのカードです。
この2つは実際によく組み合わせて使うものですよね。
API Gatewayのカードを見ると「compute/containersサービスとの全ての組み合わせに対して」と記載があります。更にその左に①とあります。これはAPI Gatewayとcompute/containersサービスとの組み合わせで1ポイント貰えるという意味になります。Lambdaを見ると、computeと記載があるので、API Gatewayの1ポイント、Lambdaの1ポイント、そしてこの2つを組み合わせた1ポイントの合計で3ポイントを入手できるという意味になります。他にもCloudFrontとS3を組み合わせるとポイントが加点されたりして、相性の良いサービスを組み合わせることで加点されていくのです。
カードにはこのように〇〇と組み合わせた場合といった表記があるので、このゲームで、**複数サービスの組み合わせについて学べるのです。**
特に認定試験ですと、アソシエイトレベル以降で複数サービスの組み合わせに対する問題は頻出なので、このゲームで試験対策もできちゃうわけです。

## 実際にやってみて
この日初心者支部に参加した際、最初にゲームについての説明がありました。
その時、初心者がベテランを倒すことができるのもこのゲームの特徴というのが印象に残りました。
自分みたいな初心者が勝てるだろうか？といった疑問が残ったのです。
因みに私がいた席では、私以外の方ですと、Community Buildersに選出された方、認定資格全冠の方、AWS Japanに在籍されていた方というどこからどうみても強強エンジニアの方しかいませんでした。
4人ともBuilderCardsは初めてでしたので、JAWS DAYSのBuilderCardsで優勝された方が、ルール等を解説してくださり、それを基に進めました。
結果は以下のようになりました。

1回戦目
同率1位で勝利！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2478024/711d942c-7209-4862-a252-82831d8ed965.png)

2回戦目
単独1位で勝利！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2478024/0e85ee88-52e9-4716-9d60-b4156684edd1.png)

先程説明しましたが、AWS-Well-Architectedカードのスコアが多い人が勝ちです。
1回戦目は3,1,1,1,1で7点
2回戦目は1,3,3で7点
何と2回とも勝ってしまいました！！
最初に説明のあったように初心者がベテランに勝つことがあるというのはこういうことだったんですね。
これぞ、正しくジャイアントキリング！(調子乗ってすみません)

## 最後に
いかがでしたでしょうか？
初心者でも十分楽しめますし、勝つこともできました。
そして、ゲームを通してAWSの複数のサービスの組み合わせについても学ぶことができました。
やはり、カードを用いているということもあり、記憶にも定着しやすいなと感じました。
JAWS-UGでは定期的にいろんな支部でBuilderCardsを開催したり、その他ハンズオン等の勉強会も実施しているので、興味のある方は是非参加してみてください！
【Excel】よく使うショートカット

# Excelでよく使う関数やショートカットのメモ

## セルに記載したシート名を参照したい場合
特殊文字を含むシート名はシングルクォーテーションで囲まなければいけないため以下のように書かなければいけない。
```
=INDIRECT("'" & A1 & "'" & "!D4")
```

## ファイル名を取得したい場合
```
=LET(fn, CELL("filename", A1), MID(fn, FIND("[", fn)+1, FIND("]", fn) - FIND("[", fn) -1))
```

## FALSEの件数を数えたい場合
| A | B | C | D | E |
|:-:|:-:|:-:|:-:|:-:|
| TRUE  | TRUE  | TRUE  | FALSE  | TRUE  |
| 1  | 2  | 4  | 8  | 16  |

FALSEの数を数える場合
```
=COUNTIF(A1:E1, FALSE)
```
条件を満たす列の総和を取る場合
```
=SUMPRODUCT(A1:E1 * 1, B1:E1)
```

## 行と列を反転させたい場合
TRANSPOSE関数を使用する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679905/319571a9-7e4a-4a36-a001-051a8b217e47.png)
```
=TRANSPOSE(A1:E3)
```

## １列のデータを表に変換したい場合
「項目名」「項目値」「数値データ」の3つ組のデータが5つある時、表形式にする場合
| データ |
|:-:|
A
a
10
B
b
20
C
c
30
D
d
40
E
e
50

```
=INDEX(A1:A15,SEQUENCE(ROWS(A1:A15)/3,3))
```

| 項目名 | 項目値 | 数値データ |
|:-:|:-:|:-:|
A|	a	|10
B|	b	|20
C|	c	|30
D|	d	|40
E|	e	|50


## ショートカット
### セル操作
| キー | 処理内容 |
|:-:|:-:|
Shift + Space | 行選択
Ctrl + Space | 列選択
Ctrl + -| 選択範囲削除
Ctrl + Shift + ; | 選択範囲挿入
Ctrl + 5 | 取消線
Ctrl + 1 | セル書式設定
F2 | セルの編集

### シート操作
| キー | 処理内容 |
|:-:|:-:|
| Ctrl + Home | シート内の最初のセルへ移動 
| Ctrl + End | シート内の最後のセルへ移動 
Ctrl + PgUp |次のシートへ移動
Ctrl + PgDn |前のシートへ移動
Alt + O H R | シート名変更
Alt + H D S | シート削除
Alt + H I S | シート追加

### 日付入力
Ctrl + ;

### データの区切り位置
Alt + A E
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679905/902f141d-9e5b-4373-a9d1-e7493dc71b44.gif)

### 列幅調整
Alt + H O I
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679905/0963b2d5-4398-460f-9944-ffc0c5ca27c5.gif)

### フィルタ
Ctrl + Shift + L
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679905/fdf5eef1-9485-45c2-a708-ff30202062b3.gif)
KVMのユーザセッションでもホストのbr0を使いたい

■今回の主役はAppArmor。セキュリティの目的で止めること自体は良いけど、
　ちゃんと理由をエラーやログに出すなりして残そうね、意味ないから。
 
 「apparmor-utils」がなければインストールして進みましょう

```
$ apt-file search bin/aa-disable
apparmor-utils: /usr/sbin/aa-disable

$ sudo apt install -y apparmor-utils
```

■今回の環境では、一部stableで動かないような新しいHWがあって、
　kernelバージョンを上げる必要に迫られtestingを使っている。
 
 他も試したけど、bookwormでも同じ手順でいけた。

```
$ head -n 2 /etc/*release
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
NAME="Debian GNU/Linux"
```

■ちなみにbookworm12.2.0以前の環境ではKVMのユーザセッションでホストbr0が使えている

```
$ head -n 2 /etc/*release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"

$ grep cdrom /etc/apt/sources.list
#deb cdrom:[Debian GNU/Linux 12.2.0 _Bookworm_ - Official amd64 NETINST with firmware 20231007-10:28]/ bookworm main non-free-firmware contrib non-free
# (e.g. netinst, live or single CD). The matching "deb cdrom"

$ virsh dumpxml kvm-debian12 | lsec -sep '^    <' br0 | grep -v "mac address"
    <interface type='bridge'>
      <source bridge='br0'/>
      <target dev='vnet0'/>
      <model type='virtio'/>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>

```

■「virsh edit」で構文は間違いなく正しいのに動かないので、
　「権限」か「セキュリティ」だけど、クリーンインストールだしまともなエラーを出さないので、多分後者と予想

■症状は、いつもどおりKVM入れても、
　「ホストのブリッジネットワークを仮想マシンにアサインする」と、
 　システムセッションではできるのに、ユーザセッションではできない。

つまりユーザ権限のときに起きる。一般に権限ならそれなりのエラーメッセージを出力するので、と探していたら、「AppAromor」

そんな気はしてた。やっぱりお前か
 
```
$ sudo aa-status | grep bridge
libvirtd//qemu_bridge_helper
```

■ピンポイントの「qemu_bridge_helper」という粒度で指定することは出来ないので、

```
$ sudo aa-disable libvirtd//qemu_bridge_helper
libvirtd//qemu_bridge_helper does not exist, please double-check the path.
```
■libvirtdごと無効にする

```
$ sudo aa-disable libvirtd
Disabling /usr/sbin/libvirtd.

$ sudo aa-status | grep bridge

$ sudo systemctl restart libvirtd
```
■やっとまともなエラーメッセージに出会えた、権限ね。

```
$ virsh start rhel8.6 
error: ドメイン 'rhel8.6' の起動に失敗しました
error: /usr/lib/qemu/qemu-bridge-helper --use-vnet --br=br0 --fd=34: failed to communicate with bridge helper: stderr=failed to create tun device: Operation not permitted
: Transport endpoint is not connected

$ env LANG=C ls -l /usr/lib/qemu/qemu-bridge-helper
-rwxr-xr-x 1 root root 664280 May  3 18:06 /usr/lib/qemu/qemu-bridge-helper

$ sudo chmod u+s /usr/lib/qemu/qemu-bridge-helper

$ env LANG=C ls -l /usr/lib/qemu/qemu-bridge-helper 
-rwsr-xr-x 1 root root 715864 May 13 03:01 /usr/lib/qemu/qemu-bridge-helper
```

■無事に起動するようになった。
　「lsec」はhttps://github.com/labunix/lsec
 
```
$ virsh start rhel8.6 

$ virsh dumpxml rhel8.6 | lsec -sep '^    <' br0 | grep -v "mac address"
    <interface type='bridge'>
      <source bridge='br0'/>
      <target dev='tap1'/>
      <model type='virtio'/>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
```

■分かったあとなら、次からはlibvirtdで探す方が良さそう

```
$ sudo aa-status | grep libvirtd
   libvirtd
   libvirtd//qemu_bridge_helper
   /usr/sbin/libvirtd (1131) libvirtd
   /usr/sbin/libvirtd (5405) libvirtd
```

■ホストのネットワークを使うことを許可する

```
$ sudo mkdir /etc/qemu
$ sudo cat /etc/qemu/bridge.conf
allow virbr0
allow br0

$ sudo chown -R :libvirt /etc/qemu/
```
QEMUを用いてUBUNTU上にWINDOWS10をインストール

## 起動
仮想HDDを生成し、起動
```
qemu-img create -f qcow2 ~/win10.qcow2 50G

sudo qemu-system-x86_64 \
  -enable-kvm \
  -m 4G \
  -cpu host \
  -smp 4 \
  -cdrom ~/Windows.iso \
  -drive file=~/win10.qcow2,format=qcow2 \
  -boot d \
  -net nic -net user \
  -vga virtio \
  -device virtio-balloon \
  -usb -device usb-tablet \
  -rtc base=localtime
```

## インストール
画面にしたがってインストールします
何度か黒い画面になってSEA　BIOSという文字が出るが再起動しているだけなので慌てない
20分くらいで完了します
![图片.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/166ade6e-8ed7-4285-a91e-13a38db367c6.png)

## 完了
一旦電源を切ります
![图片.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/2ba600c6-eeaf-4975-8acb-8f97836ae2e8.png)

## 再起動
```
sudo qemu-system-x86_64 \
  -enable-kvm \
  -m 4G \
  -cpu host \
  -smp 4 \
  -drive file=~/win10.qcow2,format=qcow2 \
  -boot c \
  -net nic -net user \
  -vga qxl
  -usb -device usb-tablet \
  -rtc base=localtime
```

## 解像度の設定
Ctrl＋Alt＋Fで画面を最大化できますが、解像度の設定をしないと綺麗に移りません。
1600×900が丁度良いくらいに映ります。
![图片.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/27e691b4-2c03-4112-9130-9b950259c8c5.png)

![图片.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/3132316f-9cfe-420e-ad3a-320059d60b06.png)
Pythonの異なるバージョンで仮想環境を作る方法（Windows）

# 背景
- 趣味用のスクレイピングツール作成時、Playwrightの非同期処理を実行するためにPyhon3.11.x が必要らしい
- Python 3.11.x を用いて仮想環境を作成しようとしたらエラー（下記）
```python
PS C:\hoge> py -3.11 -m venv myenv 
No suitable Python runtime found
Pass --list (-0) to see all detected environments on your machine
or set environment variable PYLAUNCHER_ALLOW_INSTALL to use winget
or open the Microsoft Store to the requested version.
```

- `py --list`を実行したところ、Python `3.12.x` と `3.10.x` しかなかった（下記）
```python
PS C:\hoge> py --list
 -V:3.12 *        Python 3.12 (64-bit)
 -V:3.10          Python 3.10 (64-bit)
```

# 方法
- Python公式サイトから Python 3.11.x のインストーラーをDLしてインストール
  - ※起動時に `Add Python.exe to PATH` チェックボックスをオンにすること
```python
PS C:\hoge> py --list
 -V:3.12 *        Python 3.12 (64-bit)
 -V:3.11          Python 3.11 (64-bit)
 -V:3.10          Python 3.10 (64-bit)
```

# 仮想環境作成
- 下記手順でOK
```Python
PS C:\hoge> py -3.11 -m venv myenv
PS C:\hoge> .\myenv\Scripts\Activate.ps1
(myenv) PS C:\hoge> python --version
Python 3.11.9
```
ubuntu20.04は標準サポート期間を終えたのでppa:ondrej/phpのサポート対象から外れた

# 概要

ubuntu20.04が標準サポート期間を終えたことに伴い、ondrej/phpが使えなくなった。
けど、特にエラーとか出ないので、気づくのに少々時間がかかった。

# 詳細

## 環境

vagrantでubuntu20.04の仮想マシンを作り、そこに2つのwebアプリの開発環境を入れていた。
webアプリのphpバージョンは片方が7.4、片方が8.3。
phpの複数バージョン混在には、ppa:ondrej/php を使っていた。

## 発端

環境が壊れたので、vagrant destroy からの vagrant up で再作成した。
再作成後、

```
sudo add-apt-repository ppa:ondrej/php
```

からの

```
sudo apt install php8.3
```

結果は

```
~$ sudo apt install php8.3
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package php8.3
E: Couldn't find any package by glob 'php8.3'
~$
```

一方、7.4はインストールできた。


## 原因

```
sudo add-apt-repository ppa:ondrej/php
``` 

の出力結果の最初にも、https://launchpad.net/~ondrej/+archive/ubuntu/php にも、

> Co-installable PHP versions: PHP 5.6, PHP 7.x, PHP 8.x and most requested extensions are included. Packages are provided for *Current* Ubuntu *LTS* releases (https://wiki.ubuntu.com/Releases).  Expanded Security Maintenance releases ARE NOT supported.

> 雑な訳：セキュリティメンテナンス有効なubuntuのみサポートするよ！

とあります。

そしてubuntuのバージョン一覧を見ると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282159/9d6d2d46-fcbd-4744-8024-01c910805cfd.png)

上記は状況証拠ですが、確証はないのかと探したところ、githubにissueがありました。
https://github.com/oerdnj/deb.sury.org/issues/2243

> 雑な訳：2025.05.29でubuntu20.04は標準サポート終了。それに伴い、ondrej/phpは速やかにubuntu20.04向けのパッケージを削除します。

## 対応

ondrej/phpを使いたいならubuntu22か24にするしかない。
ubuntu20.04では新たにインストールはできないが、環境構築済みのマシンはそのまま使える。

## ちなみに

php7.4が入れられたのは、たまたま標準で入れられるバージョンだったからでした。

# ポエム

説明の最初に書いてると言われればそれまでだけど、エラーメッセージくらい出してほしかったなと。
最初は通信エラーとかかと思ったよ(´・ω・`)
Swift6 handle error, Typed Throws sample code

```
enum ValidationError: Error {
     case invalidInput
     case missingInput
     case alreadyInUse
}

extension ValidationError: LocalizedError {
    var errorDescription: String? {
    switch self {
    case .invalidInput:
        return "xxxxx"
    case .missingInput:
        return "The username cannot be empty"
    case .alreadyInUse:
        return "This username is already in use. Please try again"
    }
}

class InputValidator {
    func validateWithTypedThrow(_ input: String) throws(ValidationError) {
        guard !input.isEmpty else { throw .missingInput }
        guard input.count > 2 else { throw .invalidInput }
        guard !existingUsernames.contains(input) else { throw .alreadyInUse }
    }
}


// Event
Button("Validate") {
    do throws(ValidationError) {
        try validator.validateWithTypedThrow(username)
        self.errorMessage = nil
        self.successMessage = "Validation successful!"
    } catch {
        self.errorMessage = error.localizaedDescription

        switch error {
        case .invalidInput:
            break // do something ex) call api
        case .missingInput:
            break // present alert
        case .alreadyInUse:
            break // do something
        }
    } /* catch let error as ValidationError {
    
    } */
}

```
Unity Catalog の Iceberg REST Catalog API で Databricks 外から Iceberg テーブルを書き込む

# 概要
Data + AI Summit 2025 にて Databricks における Apache Iceberg™ の完全サポートがアナウンスされました。

https://www.databricks.com/blog/announcing-full-apache-iceberg-support-databricks

現在 Unity Catalog は Iceberg REST API をサポートしており、Managed Iceberg の書き込みがサポートされているようです。

https://docs.databricks.com/aws/ja/external-access/iceberg

本記事では、この機能を利用して Databricks の外部から、Iceberg テーブルの書き込みを試してみます。

# 環境
[Databricks Free Edition](https://docs.databricks.com/gcp/ja/getting-started/free-edition) の aws us-east-2 リージョンで試しています。



# 事前準備
これらの事前準備は既に設定済みのワークスペースでは不要な場合があります。

## メタストアの外部データアクセスを有効にする
以下の手順に従って、メタストアの外部データアクセスを有効にします。

https://docs.databricks.com/aws/ja/external-access/admin

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297547/224b45a6-5c67-466b-8f08-73bbdee03cbe.png)

## 外部ロケーションを作成する
Free Edition などで使用されているデフォルトストレージでは、後述する `EXTERNAL SCHEMA USE` を設定することができないようです。
既にS3上に存在するカタログやスキーマが存在する場合はこの手順をスキップできます。
以下の手順に従って外部ロケーションを作成します。

https://docs.databricks.com/aws/ja/connect/unity-catalog/cloud-storage/external-locations

## 外部ロケーションにカタログを作成し、スキーマを作成する
こちらも上記同様、既にS3上に存在するカタログやスキーマが存在する場合はこの手順をスキップできます。

スキーマのみがS3上にあれば良さそうですが、今回はカタログごと外部ロケーションで作成します。

https://docs.databricks.com/aws/ja/catalogs/create-catalog

UIからは以下のように作成できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297547/1bd392d2-d1ff-42a5-8ac2-33f42c8a3f0b.png)

カタログを作ったらその配下にスキーマを作成します。

https://docs.databricks.com/aws/ja/schemas/create-schema

通常の権限に加え、`EXTERNAL USE SCHEMA` (= 外部からの利用) の権限を付与してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297547/a9f32a0a-8bef-4db8-8024-67a302521322.png)


# テーブルの作成
今回は [PyIceberg](https://py.iceberg.apache.org/) を用いて、適当なサンプルデータを書き込みます。
以下の定数を設定し、コードをローカルの Python で実行します。

- `DATABRICKS_HOST`: `https://<your-workspace-url>`
- `DATABRICKS_TOKEN`: [個人用アクセストークン](https://docs.databricks.com/aws/ja/dev-tools/auth/pat)
- `UC_CATATLOG_NAME`: 事前準備で作成したカタログ
- `UC_SCHEMA_NAME`: 事前準備で作成したスキーマ
- `TABLE_NAME`: 作成するテーブル名



```python
import pyarrow as pa
from pyiceberg.catalog import load_catalog

# カタログの接続設定
catalog = load_catalog(
    "rest",
    uri=f"{DATABRICKS_HOST}/api/2.1/unity-catalog/iceberg-rest",
    warehouse=UC_CATATLOG_NAME,
    token=DATABRICKS_TOKEN,
)

# サンプルデータを作成
sample_data = pa.Table.from_arrays(
    [
        pa.array([1, 2]),
        pa.array(["Alice", "Bob"]),
    ],
    names=["id", "name"],
)

# テーブルの作成
try:
    table = catalog.create_table(
        f"{UC_SCHEMA_NAME}.{TABLE_NAME}", schema=sample_data.schema
    )
except Exception as e:
    print(f"Table creation failed: {e}")
    # テーブルが既に存在する場合は取得
    table = catalog.load_table(f"{UC_SCHEMA_NAME}.{TABLE_NAME}")

# 書き込み
table.append(sample_data)
```

# 作成したテーブルの確認
Unity Catalog 上で作成したテーブルを確認することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297547/d2f6ce8f-1eb8-492c-92be-09db7f6e88e2.png)

# Databricks 上からのクエリ
外部から作成した Managed Iceberg はもちろん Databricks 上からクエリすることもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297547/425c5f29-251b-4acc-a06b-e6e981ab67fa.png)
【Python基礎から応用】yield を完全理解！return との違いを解説

Python を学んでいると出てくる `yield`。

「`return` で良くない？」とスルーしがちですが、`yield` を活用すれば  
**省メモリかつ効率的なコード**を書くことができます。

この記事では `yield` の基本から `return` との違い、仕組み、メモリ効率の比較まで、  
初心者〜中級者の方に向けてわかりやすく解説します。

---

## ✅ `yield` と `return` の違い

| 項目           | `return`                              | `yield`                                 |
|----------------|----------------------------------------|------------------------------------------|
| 処理の終了     | 関数を即終了                           | 一時停止。次回は同じ場所から再開         |
| 値の返し方     | 一括で返す（例：リストなど）           | 1つずつ順番に返す（イテレーターになる）  |
| メモリ使用量   | 高くなりがち                           | 必要な時だけ生成。省メモリ                |
| 向いている用途 | 最終的な結果をまとめて返す処理         | ストリーム処理、大規模データ処理など     |

---

## 🌟 `yield` を使うメリット

### 1. メモリ効率が圧倒的に良い

リストをすべてメモリに載せる `return` に比べ、`yield` は1件ずつ処理します。  
そのため、**大規模データ処理に非常に強い**です。

以下はメモリ使用量の比較です。

```python
import sys


def with_yield():
    for i in range(10000):
        yield i


def with_list():
    return [i for i in range(10000)]


gen = with_yield()
lst = with_list()

print(f"yield メモリサイズ: {sys.getsizeof(gen)} bytes")
print(f"return メモリサイズ: {sys.getsizeof(lst)} bytes")
```

```
yield メモリサイズ: 104 bytes
return メモリサイズ: 85176 bytes
```
巨大なリストをメモリに乗せなくていいので、**yieldは圧倒的に省メモリ！!**

## `yield` の値ってどう取り出すの？
`yield` を使った関数は、値ではなく **ジェネレーターオブジェクト**を返します。

```python
def gen():
    yield 1
    yield 2
    yield 3

print(gen())
```
出力
```
<generator object gen at 0x104c3da10>
```
➡ 中身の値はまだ出てこない！
💡 これは何？
これは「ジェネレーターオブジェクト」という特殊なオブジェクトです。
gen() はすぐには値を返さず、値を「あとから順番に取り出せる」状態を返しています。
オブジェクトから中身を取り出すには、`for` 文や `next()` を使う必要があります。

### `for` 文で取り出す

```python
def gen():
    yield 1
    yield 2
    yield 3

for val in gen():
    print(val)
```
出力:
```                                                                         
1
2
3
```

## next() で1個ずつ取り出す
```python
def gen():
    yield 1
    yield 2
    yield 3


g = gen()
print(next(g))
print(next(g))
print(next(g))
```
出力:
```                                                                         
1
2
3
```


## yield の関数は「途中で止まって、また動き出す」
yield の最大の特徴の一つは、関数の処理を一時停止して、次回呼ばれたときにその続きから再開できることです。
returnではできないこの動きが、yield を使う大きな理由の1つです。
```python
def gen():
    print("1つ目")
    yield 1
    print("2つ目")
    yield 2

g = gen()
print(next(g))
print(next(g))
```
このコードでは、yield によって処理が分断されている様子がよくわかります。
最初の next(g) で yield 1 まで実行 → ここで一時停止
2回目の next(g) で中断地点から再開 → yield 2 まで実行
➡ 「再開 → 停止 → 再開…」という流れが yield のキモです。

## ジェネレーターは「1回使い切り」
```python
g = gen()
for i in g:
    print(i)

for i in g:
    print(i)  # → これは何も出ない！
```
➡ ジェネレーターは「1度使ったら空っぽ」になるため、再利用したい場合は gen() を再度呼び出す必要があります。


## ✅ まとめ

⭕️メリット
1. メモリを節約したいとき（大量データを扱うとき）
1. 値を1つずつ順番に処理したいとき
1. 処理を一気にやらず、途中で止めたり再開したいとき


⚠️ yield を使うときの注意点
1. ジェネレーターオブジェクトを取り出すときはfor 文か next() をつかう
1. 処理は途中で止まってる！
1. 1回使ったら終わり！もう一度使うには再実行が必要！


## 最後に
単にreturn を yield に書き換えるだけでは上手くいかないこともあります。
設計の段階から「yield を使う前提」で考える必要があります。

ただ、慣れれば yield はとても強力な道具です。

設計の発想をちょっと変えるだけで、より軽くて・効率的な Python コードが書けるようになります！是非挑戦してみてください！
指定のタブ移動で空ページを表示させたくない

* `window.open`の引数2つ目には特定のタブ（の`windowName`）を指定できるが、そのタブが存在しない場合には**真っ白なページ（about:blank）が新規タブで開かれてしまう**
* 不格好なのでユーザには見せることなく、代わりにアラートやダイアログのような警告を表示したい

```js
function focusOrOpenWindowByName(windowName, url = 'about:blank') {
    let win = window.open('', windowName);
    if (!win || win.closed) {
      // ウインドウを開けなかった場合
      return;
    }
    try {
      if (win.location.href !== 'about:blank') return;
      win.focus();
    } catch (e) {
      // CORSエラー等の場合
      try {
        win.focus();
      } catch (ex) {}
      return;
    }
    if (url !== 'about:blank') {
      // URLを開く
      win.location.href = url;
    } else {
      // 空白タブがある場合は閉じる
      win.close();
      // 警告する
      setTimeout(function () {
          window.alert("指定のタブがありません");
          // ユーザに選択させる場合
          // if (window.confirm("空ページを開きますか？")) {
          //     window.open('', windowName);
          // }
      }, 0);
    }
}
```

* こうなる
    * `windowName`をもつタブが存在しない ⇒ **警告**
    * `windowName`をもつ空タブが開かれている ⇒ **閉じて警告**
    * `windowName`をもつ空でないタブが開かれている ⇒ **そのタブに移動**
* 一度開いてから閉じている所がポイント
【Rails】予約語に気をつけろ！！

## 起きたこと
・既存のプロジェクトにメール機能を追加するにあたって、Mailモデルを作成して実装
・順調に開発が進み本番環境にデプロイしたところ、NoMethodErrorが発生

【エラー内容】
```
undefined method `eager_autoload!' for Mail (call 'Mail.connection' to establish a connection):Class (NoMethodError)
Did you mean? eager_load
```

## 原因
・Rails の初期化プロセスでActionMailerのeager_loadを実行
・その中で Mail.eager_autoload! を呼んでいる(どうやらMailモデルがあるみたい)
・しかし自身が作成したMailクラスにはeager_autoload!が存在しない → NoMethodError

## なぜ開発環境では起きなかったの？
・development.rbでは```config.eager_load = false```となっておりproduction.rbではこれが```true```だったので開発環境では発生しなかった。

## 反省
・安易にモデル名を決めてしまった(後になって思えば流石にMailモデルはどこかで使われている可能性が高そう)
・Railsの継承元のモデル名も干渉するという視点がなかった

## 終わりに
・モデル名の変更により実装した部分の大多数を変更後のモデル名で書き直す必要がありかなり時間と労力を使ったので二度と同じ過ちは繰り返したくない。。

## 余談
・関連するモデルでMailMediaというモデルを作っていたが、スキーマファイルを作成する際、mail_mediasというテーブル名で作成していたところ、```mail.mail_medias```を呼び出す際に「mail_mediaなんてテーブルはない」というエラーが発生していた。
・調べるとmediaの複数形はmediaなので、Railsさんが自動的に複数形変換してくれてmail_mediaテーブルを探しに行ってくれてたってわけ。
・今回は運用のしやすさという観点から```self.table_name = 'mail_medias'```をMailMediaモデルに記述して対応
UE5のC++ Dynamic Debugging

## はじめに

[Enable C++ Dynamic Debugging in Unreal Engine](https://learn.microsoft.com/en-us/visualstudio/debugger/cpp-dynamic-debugging?view=vs-2022#enable-c-dynamic-debugging-in-unreal-engine)を試したときの備忘録です。

:::note warn
Riderでも内部的にはMSBuildでビルドするので Dynamic Debuggingのオプション[`/dynamicdeopt`](https://learn.microsoft.com/ja-jp/cpp/build/reference/dynamic-deopt?view=msvc-170) を解釈して、`MyActor.gen.cpp.alt.obj`等のDynamic Debugging用のシンボルは作成されます。
しかし、デバッグ時にはDynamic Debugging用のシンボルを解釈する機能がないので動きません。
デバッグはVisual Studioが2025/06/13時点だと必要です。

[リクエスト](https://youtrack.jetbrains.com/issue/RIDER-124218?utm_source=chatgpt.com)はされている模様。
:::

## 環境
* Windows 11
* MSVC 14.44.35209 
  * フォルダパスは`C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207` 
* UE 5.7 ([ue5-main](https://github.com/EpicGames/UnrealEngine/tree/ue5-main)のコミットハッシュが`b366e59`時点のもの)
* Rider 2025.1.2
* ビルドターゲット： `Development Editor` 

## 設定、確認

エンジンをエディタ用にビルドするのでゲームプロジェクトの`XxxxEditor.Target.cs`に下記を追加します。
```XxxxEditor.Target.cs
public class XxxxEditorTarget : TargetRules
{
	public XxxxEditorTarget( TargetInfo Target) : base(Target)
	{
        ...

        // Dynamic Debuggingを有効
		WindowsPlatform.bDynamicDebugging = true;
        // ローカルの最新バージョンを利用
		WindowsPlatform.CompilerVersion = "Latest";
        // bDynamicDebugging == trueだと必要とUBTに言われる
		bOverrideBuildEnvironment = true;
	}
}
```

:::note warn
`VCToolChain.cs`の[`IsDynamicDebuggingEnabled`](https://github.com/EpicGames/UnrealEngine/blob/ue5-main/Engine/Source/Programs/UnrealBuildTool/Platform/Windows/VCToolChain.cs#L62-L70)がtrueにならないとDynamic Debugging有効でビルドされないので注意。
有効の場合は`Visual Studio Dynamic Debugging is enabled`とログが表示されます。 
:::

前述のとおり、Dynamic Debuggingの動作はまだVisual Studioのみしかサポートされていないので、Visual Studioで普通にデバッグします。

:::note warn
RiderでDynamic Debugging有効でビルドはできるが、デバッグできない。
:::

試しに下記スクショのようなコードでも変数の値が最適化されて確認できない
という状態になっていないのが確認できます。
このコードに意味はないです。。。 
![2025-06-13_21h54_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958164/9e07702d-3646-48b5-ac3d-22e8a78f4782.png)
Rustの基礎(2) - 数値型と論理型を理解しよう！



前回はRustの基礎(1)として、**文字列の出力方法や変数・定数の宣言方法**についてお伝えしました。  
今回はRustにおける **数値型** と **論理型** について見ていきましょう。

---

## 📊 数値型とは？
数値型とは、**プログラミング言語で数値を扱うためのデータ型**のことです。  
Rustでは大きく分けて以下の2つに分類されます。

- **整数型（符号付き/符号なし）**
- **浮動小数点型（f32, f64）**

### 🧮 整数型（Integer）

- 整数の値を扱います。
- 符号付き：負の値も扱える（`i8`, `i16`, ..., `isize`）
- 符号無し：正の値のみ扱える（`u8`, `u16`, ..., `usize`）

```rust
let a: i32 = 5;
let b: u64 = 100;
```

### 🔢 浮動小数点型（Floating Point）
- 小数を扱います。
- f32（32ビット）と f64（64ビット）があります。
```rust
let x: f64 = 2.5;
let y: f32 = 1.0;
```

### ✅ 型推論と明示
Rustは静的型付けですが、型推論にも対応しています。
```rust
let a = 5;     // i32 と推論される
let b = 2.0;   // f64 と推論される
```
※ i64 や f32 にしたいときは、明示的に型を指定する必要があります。

### ➕ 計算とキャスト
Rustでは計算時に 同じ型同士でなければならない というルールがあります。
```rust
let a = 1 + 3;             // OK
let b = 5 + 2.0;           // エラー
let c = 5 as f64 + 2.0;    // OK（キャスト）
```
キャストには **as** キーワードを使います。

### 🧾 Rustで使える数値型一覧

| 種類     | 型                                          | 例                    |
| ------ | ------------------------------------------ | -------------------- |
| 符号付き整数 | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | `let x: i32 = 10;`   |
| 符号無し整数 | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | `let y: u8 = 255;`   |
| 浮動小数点数 | `f32`, `f64`                               | `let z: f64 = 3.14;` |

### 🔍 論理型（Boolean）
論理型は true か false の2値を取る型で、Rustでは bool を使います。
```rust
let flag: bool = true;
```
比較演算の結果も bool になります。
```rust
let a: bool = 1 == 2;   // false
let b: bool = 1 < 2;    // true
let c: bool = 1 >= 2;   // false
```

### 🧠 まとめ
- Rustには符号付き/符号無しの整数型、浮動小数点型がある
- デフォルトでは i32（整数）と f64（浮動小数点）
- 異なる型同士の計算には as を使ったキャストが必要
- 論理型 bool は true / false を表し、比較演算にも使われる

### 🪄 次回予告
次回は、**タプルと配列** について学んでいきます！
実際のデータのまとまりをどう表現していくか、一緒に見ていきましょう。

本シリーズはNotionでもまとめています。
こちらは私なりにまとめているものになり、考えていることとかも記載しているので、興味のある方は見ていってください。

🔗 Notionで冗長なページはこちら：
👉 https://probable-entrance-3f3.notion.site/Rust-2-20ccd005f170806aa698d1fe660db066?source=copy_link
【AtCoder】ABC409 振り返り📝

:::note info
Zennに置いていた記事をQiitaに転載しています。
:::

## ABC409 - A 
[問題はこちら](https://atcoder.jp/contests/abc409/tasks/abc409_a)
最近フロントエンドばっかり書いていたからPythonの書き方をすべて忘れ去っていて、inputをintにする方法すらわからなくて焦った…
まあ解けたは解けたからOKかな？
```py
n = int(input())
a = input()
b = input()

for i in range(n):
    if(a[i]=="o" and  a[i]==b[i]):
        print("Yes")
        break
    if(i==n-1):
        print("No")
```

## ABC409 - B 
[問題はこちら](https://atcoder.jp/contests/abc409/tasks/abc409_b)
見える範囲のテストケースは通ったのに提出した後のテストケースでWAしてﾜｰｰｰｰ???ってなった。
結局 `5` `5 5 5 5 5` みたいな同じ数字の時がダメだったんだけど、これ見つけるのに15分くらいかかってしまったので、これくらいすぐわかりたかったな～の気持ち。
```py
n = int(input())
a = list(map(int, input().split()))

for i in range (max(a)+1):  #0~max(a)
    count = 0
    for j in range (n): #a[0]~a[n-1]
        if(a[j] >= i):
            count += 1
    if(count < i):
        print(i-1)
        break
    elif(i==max(a)):
        print(i)
```

## ABC409 - C 
[問題はこちら](https://atcoder.jp/contests/abc409/tasks/abc409_c)
これ！！！私の中では解けてるのに！！！TLEです！！！！！！
ﾓｳﾑﾘｨ…
```py
n,l = map(int, input().split())
d = list(map(int, input().split()))


tenP = [0]*n
for i in range(n-1):
    tenP[i+1] = (tenP[i]+d[i])%l

if(l%3 != 0):
    print(0)
else:
    tri = 0
    for i in range(n):
        if(tenP[i] < l/3):
            tri += tenP.count(tenP[i]+l/3)*tenP.count(tenP[i]+2*l/3)
            
    print(tri)
```
## 今回の感想
久々の参加にしてはがんばったかな？
同期とAtCoderの話題で盛り上がっていて、一緒に参加できる人がいるのって楽しいな～の気持ちです。
大学時代は友達いなさ過ぎて何するにも孤独だったので…


## 2025/06/11 追記
QiitaってAtCoderの記事あるんかな～って眺めてたらたまたま見つけてとてもわかりやすかったので、
→ [AtCoder ABC409 振り返り(緑コーダーがPythonでABCD問題)](https://qiita.com/tototti/items/7eafb8d09367e4f7e9f4)

書き直してみた！
```py
n,l = map(int, input().split())
d = list(map(int, input().split()))

# 円周が3の倍数でないときは正三角形が存在しない
if l % 3 != 0:
    print(0)
    exit()


points = [0]*(l+1) # 点Pに何個あるか
points[0] = 1
current = 0

# 各点がどの点に配属されるか
for num in d:
    current = (current+num) % l
    points[current] += 1

# 三角形の数を数える
count = 0
for i in range(l//3 + 1):
    point1 = points[i]
    point2 = points[i + l//3]
    point3 = points[i + 2*(l//3)]
    count += point1 * point2 * point3

print(count)
```
確かにDの各点の位置求めてcountするより、点Pに何個あるかを記録しておく方が計算量少ないよな～
ｸﾞﾜｧ　納得感と敗北感……
WordPressのプラグインを特定する方法

wappalyzerなどのツールを使わず、自力で、WordPressプラグインを特定する方法

トップページのソースを表示する

`wp-content/plugins`を検索

```:wp-content/pluginsを含む行
<script type='text/javascript' src='https://example.or.jp/wp-content/plugins/contact-form-7/includes/swv/js/index.js?ver=5.6.4' id='swv-js'></script>
<script type='text/javascript' src='https://example.or.jp/wp-content/plugins/contact-form-7/includes/js/index.js?ver=5.6.4' id='contact-form-7-js'></script>
<script type='text/javascript' src='https://example.or.jp/wp-content/plugins/contact-form-7/modules/recaptcha/index.js?ver=5.6.4' id='wpcf7-recaptcha-js'></script>
<link rel='stylesheet' id='contact-form-7-css'  href='https://example.or.jp/wp-content/plugins/contact-form-7/includes/css/styles.css?ver=5.6.4' type='text/css' media='all' />
<link rel='stylesheet' id='wp-v-icons-css-css'  href='https://example.or.jp/wp-content/plugins/wp-visual-icon-fonts/css/wpvi-fa4.css?ver=5.9.10' type='text/css' media='all' />
<link rel='stylesheet' id='wp-pagenavi-css'  href='https://example.or.jp/wp-content/plugins/wp-pagenavi/pagenavi-css.css?ver=2.70' type='text/css' media='all' />
```

プラグインを特定
contact-form-7
wp-visual-icon-fonts
wp-pagenavi

なお、ここで見えているバージョンは、プラグインのバージョンではないので注意が必要


readme.txtにアクセスして、プラグインのバージョンを特定

```:プラグインのバージョンを特定するURL
https://example.or.jp/wp-content/plugins/contact-form-7/readme.txt
https://example.or.jp/wp-content/plugins/wp-visual-icon-fonts/readme.txt
https://example.or.jp/wp-content/plugins/wp-pagenavi/readme.txt
```

readme.txt内の `Stable tag:` がプラグインのバージョン

```:例
=== Contact Form 7 ===
Contributors: takayukister
Donate link: https://contactform7.com/donate/
Tags: contact, form, contact form, feedback, email, ajax, captcha, akismet, multilingual
Requires at least: 5.9
Tested up to: 6.1
Stable tag: 5.6.4  <--★バージョン
```