OmniAICreator/Qiita-1.07M huggingface dataset:
プロジェクトの理解度を高めてシゴデキになるためのチェックシート（サーバ構築編）

# はじめに
前のまとめ記事に書いたように、自分が構築するサーバだけではなく
案件の概要というか、全体をある程度理解していないと話にならないと思ったので
チェックリストを今思いつく限りで作成します。

全部設計書を見ればわかることですが、会話のたびに開いていないだろうし
聞かれるたびに設計書開くの待ってたら、自分で見たほうが早いって見放されちゃうんで
「これくらいは覚えておいたほうがいいよ」というのを抜き出したような感じになります。

この記事は自分のため、社内でサーバ構築業務をしている人のため
これからサーバ構築業務に従事する・したいという人のために作成します。
主に初学者向けです。

**多少、私個人の思想が入るので鵜吞みにはせず参考程度にしてください。**

先輩方は、この記事を読んで足りない項目などあったら、DMで指摘してください。

※サーバ構築案件での使用を想定して作成します。
　ネットワーク案件などのチェック観点はこれとは異なると思うので理解してください。

# チェック項目
### 構築するサーバは何のシステムで使われるか
これはざっくりでよいです。また、何のシステムの一部かでもよいです。
このサーバを「何のために」新規構築・更改するのか、が分からないと質問されても
指示されたのでやっています。としか返答できなくなってしまいます。


### 物理の構成
物理関係はオンプレ限定の話になっちゃうかもしれませんが、ネットワークポートなどは
仮想マシンでも把握しておきたいし、仮想化基盤自体が乗っているハードウェアを見る機会があるかもしれないので確認する観点を知っているだけで、周りの話を少し理解できるかもしれないですね。

- **使用するOSバージョン**
当たり前すぎか？と迷いましたが書いときます。
結構細かいところまで覚えておいたほうがよいです。
Windowsなら「Windows Server 20xx Standard」までしっかり。
RHELなら「Red Hat Enterprise Linux 9.x」まで。「9.x」が重要です。

- **ポートの種類と数**
LANポートが何個あって、何個使っているとか
リモート管理用のポートを使っている、使ってないとか
USBのポートは何個あって、使ってないとか
意外と忘れる。
ちゃんと理解すれば忘れないと思うので、設計意図を理解しましょう。

- **電源の構成**
UPSとか冗長とかあります。
つながっている先の電源タップとかたどると、ちゃんと冗長されているかを確認することができます。

- **積んでいる容量**
後の「パーティションをどうやって切るか」の話につながります。
常に考慮しろとは言いませんが、考慮できる人は一流かもしれません…

- **読み込みドライブなどの有無**
DVDドライブとかその他のドライブがあるか
使用できる、できないかですね。
セキュリティ的に使用しないとかもあるので、
あとは構築や運用時に使えないと不便だよねとか
これも考慮できるとできる人ですね。

### 論理の構成
論理の話はオンプレや仮想環境でも同じだと思います。
パラメータを全部暗記しろとは誰も言わないと思うので、
これくらいは分かるのが理想かな？と私が思うものを挙げておきます。

- **パーティション構成**
どんなパーティション構成かは知っといたほうがいいですね。
質問されて「サーバチームなのにわからないのか…」ってなっちゃうと
惨めな気持ちになっちゃいます。

- **ユーザ・グループの数**
これも完全にとはいいませんが、なんとなく覚えているといいかもです。
サーバによって違ったりするので、難しいですが
システムで共通のユーザとかいるので、システムの用途が分かると
ユーザの過不足とかに気づけたりするかもしれないので良いです。

- **必要なアプリケーション**
これもサーバ用途の理解につながると思います。
不要なアプリケーションはアンインストールする、みたいな場合もあるので
要否はしっかり調査して、理由まで言えたら100点だと思います。

- **IPアドレスを何個持っているか**
IPアドレスは基本ですが、いつになっても超重要なので暗記してもいいレベルです。
渡されたIPアドレスも本当に正しいのか確認するのも大切です…

### 接続先の機器
これもめちゃ大事です。
IPアドレスだけ覚えても正直意味がありません。
どこと通信しているのか、何に使われているセグメントなのか
まで考えられると一流かもしれません。

### 通信経路（できたら）
これも大事です。でも難しいので（できたら）と付けました。
サーバがどの機器につながっているのか、どの機器を経由している、セグメントがここで変わっているからルーティングが必要で～…まで考えることができると、
全体が見えてきて、設計の意図が理解できると思います。

# おわりに
偉そうに書かせてもらいました。

上記のポイントが全部できたら「こいつ結構話せるな」って思われると思います。

そうです。
これを全部できても、それくらいしか思われないです。
上には上がいます。
「最強」になるためには、まだまだ道のりは長いです。

私も上に書いてあることが、全部完璧にできているわけではありません。
ですが、次の案件からはこのチェックシートを案件開始時に埋めて
こまめに確認することで、レベルアップしようと計画しています。

この記事の内容が誰かの役に立てば幸いです。
一緒に頑張りましょう。
Windows IIS に Enterprise CA からサーバ証明書を入れる最小手順

## はじめに
モダンブラウザが TLS 証明書として SAN (Subject Alternative Name) をチェックするようになって以降、Windows IIS に組み込まれている証明書要求機能を用いて証明書を作っても、証明書エラー(NET::ERR_CERT_COMMON_NAME_INVALID等)となります。
過去には色々な情報源を参考にさせていただき切り抜けていたのですが、今回あらためて AD CS (ActiveDirectory 証明書サービス) を活用する最小手順を確認、整理して覚書として残しました。
※単に最近 Enterprise CA を触り始めただけだったり...

## 対応概要
1. certreq.exe で CSR 作成～証明書発行まで行う
1. IIS にインポートし動作確認する

## 前提環境
- すべて ActiveDirectory ドメイン傘下の環境
- AD CS として TLS 証明書発行可能な Enterprise CA が構成済み
- IIS が構築済み。サーバ証明書で https 通信をサイトに設定したい

#### 参考) 今回作った検証環境(on Windows 11 Hyper-V)
- AD DS (Windows Server Core 2025 Standard) ... Domain Controller
- AD CS (Windows Server Core 2025 Datacenter) ... Enterprise Root CA
- ドメインメンバーサーバ (Windows Server 2025 Standard) ... IIS 用

## 事前調査・対応
Enterprise CA の [証明機関] 画面から、[証明書テンプレート] を確認する。
Webサーバー用証明書テンプレートが、オリジナルの「Web サーバー」しかない場合には、[証明書テンプレート] > [管理] と進んで複製し、複製物を半角英数字からなる名前にしてから、それを発行しておく。
(今回は WebServerCustom としました。後続手順で CSR を作成する際に日本語名では認識してくれないようでしたので。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3665941/91a8ffcb-7821-440b-8cb7-a3457e3b61eb.png)



※余談ですが、テンプレートのプロパティに [サブジェクト名] というタブがあり、ここに色々と指定できそうな内容がありましたが、試してみても対応困難でした。

## 作業1-a.(.inf ファイル作成)
下記 MS 情報ページの中ほどに RequestPolicy.inf を作成するという内容があるので、
https://learn.microsoft.com/ja-jp/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/ff625722(v=ws.10)#customizing-requestpolicyinf-for-your-environment
この .inf の内容をメモ帳に全て貼り付けて以下に編集、保存する。(今回は C:\Work\req.inf にしました。)

 - [NewRequest] セクション下の Subject を変更
 - EncipherOnly 行は不要(コメント化)
 - [Extensions] セクション下は必要な記載のみに変更、値も適切に設定
 - [RequestAttributes] セクション下は、証明書テンプレート名の指定行のみにする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3665941/75c90f78-4742-4394-b7a2-f98c9e65973e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3665941/6b7d51d2-a133-4c5e-8fef-efc094111646.png)

## 作業1-b.(証明書作成)
コマンドプロンプトか PowerShell コンソールを起動し以下を実行、証明書ファイル .cer ができたことを確認する。社内システム用途であれば Enterprise CA に頼ると便利です。

```
cd C:\Work
certreq -new req.inf req.req
certreq -submit req.req req.cer
```

## 作業2(IISへのインポート～動作確認)
1. IIS を起動し、左ペインのサーバ名をクリックし、中央ペインの [サーバー証明書] アイコンをクリック
1. 右上の [証明書の要求の完了...] をクリックし、以下で進める
    - 作成した req.cer を指定
    - フレンドリ名: 適当でよい
    - 証明書ストア: Web ホスティング
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3665941/5b6fabc3-6078-4236-bef3-5a208ed4f7d7.png)

1. HTTPS 設定したいサイトを選んでバインドを編集し、https を追加する。ここで先ほど追加した証明書を選ぶ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3665941/15bb9b90-b00b-48ce-bf3f-eccdcf1f8a3a.png)

1. ブラウザで動作確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3665941/2d86c0b9-93fc-4699-8636-a794e32287f9.png)

### 今回主に参考にさせていただいた情報
https://qiita.com/carol0226/items/be07b6e11967c31aeb65

ありがとうございます。
awkで最後フィールドを取得する

自分がいるディレクトリのパスを除いたのがほしいなあ、と思った次第で

組み込み変数の `NF` を使用します。

```bash
pwd | awk -F'/' '{print $NF}'
```

`man` を確認すると単にレコード（行）の最後のフィールド（列）の数値を表してるだけなので、
以下のような使い方をすると最後から一つ前、とかも可能。

```bash
pwd | awk -F'/' '{print $(NF - 1)}'
```
Autovacuumについての理解

# トランザクションID
PostgreSQLでは各行のデータに対して以下の情報を記録している。
 
xmin: その行を挿入したトランザクションID
xmax: その行を削除または更新したトランザクションID
 
トランザクションIDは1から約42億（2^32）までのIDを使用可能。
理論的にはトランザクションIDが上限2^32に達する可能性があり、その場合ラップアラウンドをする。
ラップアラウンドが発生すると、次のトランザクションIDが0に戻り再度カウントされていく。

その結果、古いトランザクションIDと新しいトランザクションIDが重複する可能性がある。
これにより、データの整合性が損なわれたり、古いデータと新しいデータが誤認されるリスクが発生する。
 
# 不要なトランザクションID
PostgreSQLではトランザクションが完了するまで他のトランザクションからそのトランザクションの結果が見えないようになっている。
以下の場合はそのトランザクションで使用されたトランザクションIDは不要になる。
 
・行の削除: 行が削除され、その削除が他のすべてのトランザクションから見えるようになった場合
・行の更新: 行が更新されて新しいバージョンが作成され、古いバージョンが他のすべてのトランザクションから見えるようになった場合
 
# Autovacuum
不要となったトランザクションIDを削除するため、PostgreSQLではAutovacuumが行われる。

・削除された行が他のすべてのトランザクションから見えるようになった場合、その行を物理的に削除する。
・更新された行の古いバージョンが他のすべてのトランザクションから見えるようになった場合、その古いバージョンを物理的に削除する
 
これにより、不要なトランザクションIDが解放される。
 
# Freeze
非常に古いトランザクションIDを特別な「Freeze状態」に変更するプロセス。FreezeされたトランザクションIDはカウントされず、新しいトランザクションIDのラップアラウンドの影響を受けないため、ラップアラウンドのリスクを減少させることができる。

# 参考
https://aws.amazon.com/jp/blogs/news/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/
https://www.postgresql.jp/document/16/html/runtime-config-autovacuum.html
【備忘録】AWS CloudWatch概要 + CloudWatch Logs構築手順

# CloudWatch
**モニタリングに関する機能を提供するAWSリソース**

## メトリクスの種類
### 標準メトリクス
AWSがあらかじめ定義しているメトリクス
ex)EC2のCPU使用率・ネットワーク通信量

### カスタムメトリクス
利用者が定義したメトリクス
ex)EC2のメモリ使用率・ディスク使用率

### CloudWatch Alarms
メトリクスのしきい値を超えたらアクションを起こせる機能

### CloudWatch Logs
ログファイルの保存・閲覧・監視ができる機能

## CloudWatch Logs構築手順
**1.IAMロールにポリシーをアタッチ**
**2.AMI作成用インスタンスの立ち上げ**
**3.CloudWatchエージェントのインストール**
**4.AMIの作成**
**5.起動テンプレートの更新**

**1-1.許可を追加からポリシーをアタッチをクリックする**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/5913f8b1-4353-403b-a403-d29f885a9a0e.png)

**1-2.必要なポリシーを選択して、許可を追加する**
![image 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/360d98d2-43cd-4708-a223-a76109e6ca6d.png)

**2-1.AMIからインスタンスを作成する**
![image 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/b293022b-08ff-46b5-b38f-1dd00ac9fca5.png)

**3-1.作成したインスタンスにSSHして、sudo yum install -y amazon-cloudwatch-agentを実行する**
![image 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/f57e4d9b-6d6f-496c-a764-9ab416fb0571.png)

**3-2./opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.jsonに設定を記述する**
![image 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/0b2c1a9b-0539-45ee-acd4-96a44b50d5b2.png)

**3-3.sudo systemctl start amazon-cloudwatch-agentを実行する**
![image 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/0b82a1e0-f91e-4ffa-8ba6-6e88f6a356aa.png)

**3-4.適切にIAMロールをアタッチ出来ていればCloudWatchのロググループからログが見れる**
![image 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/230fd3b8-475c-4c0c-90cb-fdaa0e866c1c.png)

**4-1.インスタンスを選択し、イメージを作成をクリックする**
![image 7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/f0dbd14f-4d14-4d2f-96f2-fb8ce6c2d704.png)

**5-1.テンプレートを変更をクリックする**
![image 8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/5b272a2b-6f2c-4dcd-927b-82e1122f2c91.png)

**5-2.AMIを取得した最新のAMIに切り替える**
![image 9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/770ce204-c503-44ed-98c5-cd4cc759cbba.png)

**5-3.AutoScalingグループの編集をクリックする**
![image 10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/29cc39a5-18da-49aa-b909-bae25c4acce2.png)

**5-4.起動テンプレートのバージョンを最新バージョンに変更する**
![image 11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/631008f5-bf6f-41e1-a396-268a32d43973.png)

**5-5.現在稼働中のインスタンスにも更新を適用するため、インスタンスの更新を開始する**
![image 12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/e57b9aad-6c51-4a18-8f64-138f5f3ab444.png)

**5-6.最小正常率を50%にしてインスタンスの更新を開始するをクリックする**
![image 13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/882f043a-8362-4dcc-bb33-dc74c13b573c.png)
FlutterでiOS18.2 + 18.3.1のシミュレーターでビルドエラーが出る時の対処法

筆者の環境

:::note info
Flutter (Channel stable, 3.22.3, on macOS 15.3.2 24D81 darwin-arm64, locale ja-JP)
Android toolchain - develop for Android devices (Android SDK version 35.0.0)
Xcode - develop for iOS and macOS (Xcode 16.2)
Android Studio (version 2024.3)
:::

Flutterで突然iOSがビルド出来なくなりました。

エラー抜粋
> --- xcodebuild: WARNING: Using the first of multiple matching destinations:
    { platform:iOS Simulator, id:928E96F5-10C9-4187-B5E4-E3B77E4043D0, OS:18.3.1, name:iPhone 16 }
    { platform:iOS Simulator, id:928E96F5-10C9-4187-B5E4-E3B77E4043D0, OS:18.3.1, name:iPhone 16 }
    ** BUILD FAILED **

他ログを見ると、**Library/Developer/Xcode/DerivedData**周りでエラーが出ている模様でした。正直いじった記憶が無いので、途方にくれました💦
## 解決策
https://stackoverflow.com/questions/59957482/unable-to-build-app-for-ios-unable-to-write-module-session-file-session-module/79143057#79143057

こちらの方法を試すことで無事シミュレーターでのビルドが可能になりました。
Xcode → Settings... → Locationsタブの**Derived Data**をDefaultからRelativeに変更します。
![スクリーンショット 2025-03-28 20.36.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2428088/e23f2811-8629-4b32-84ac-075bfa3c5910.png)

現在のDerived DataがDafaultの設定だとFlutterからのBuildに対応できていないようです。(runnerからXcodeで直接ビルドするとDafault設定でもビルドは出来ました)
体感ですが、Swiftで開発している際にDerived Dataの設定がRelativeだと、ビルド時間が長くかかっていると感じました。
面倒ですが、ネイティブでの開発時はDerived Dataを**Default**に、Flutterでの開発時には**Relative**で開発するのが現状は良さそうです。

追記:
Derived Dataが**Relative**の場合、Swiftで開発時にBreakPointを貼ってデバッグしようとすると、ブレークポイントで止まらない現象が発生しました。(これはmacOSが15.4, Xcodeが16.2の場合に発生する模様)

https://developer.apple.com/forums/thread/775563?answerId=827624022#827624022

なので、Xcodeを16.3にアップデートで現状の問題は解決していましたので(Derived Data**Default**でもFlutterでビルド出来る)、アップデートするのが推奨になりそうです(podライブラリの対応次第)
【Windows 11】ローカルアカウントでセットアップする方法

◆ 対象
	•	Windows 11 Home / Pro（特にProで有効）
	•	初期セットアップ中のPC（新規 or リカバリ後）

【手順まとめ】

1. セットアップを進めて「ネットワークに接続しましょう」画面まで進む

→ Wi-Fi一覧が表示される画面。

2. どのWi-Fiにも接続せずにそのまま放置

→ 画面右下の「次へ」がグレーアウトされている状態。

3. キーボードで次のキーを同時に押す：

Shift + F10

→ 黒い「コマンドプロンプト」が表示される。

4. 以下のコマンドを入力して Enter：

oobe\bypassnro

※「oobe」は「オービーイーイー」、「\（バックスラッシュ）」は￥キーでOK。

5. 自動で再起動 → 再度セットアップ画面へ

6. 「インターネットに接続せずに続ける」オプションが出る

→ それを選択。

7. 「ローカルアカウントの作成」画面が表示される

→ 任意のユーザー名とパスワードを入力して進める。

8. セットアップ完了！

【セットアップ後にWi-Fi接続してもOK？】

→ はい、大丈夫です。 ローカルアカウントのまま使えます。
必要があれば後からMicrosoftアカウントを追加することも可能です。


## 追記(2025/3/30)：
Microsoftは、Windows 11の全ての新規インストールにおいて、Microsoftアカウントの使用を必須とする変更を実施した。この変更により、Windows 11 HomeだけでなくProエディションでも、ローカルアカウントのみでのセットアップが不可能となる。

この変更は、2024年3月にリリースされた累積アップデートKB5035942によって実装された。以前は「BYPASSNRO」コマンドを使用してアカウント要件をバイパスすることが可能だったが、このアップデートでその方法も無効化された。

Windows 11の新規インストール（クリーンインストールを含む）では、デスクトップに到達して更なるセットアップを行う前に、インターネットに接続し、Microsoftアカウントでサインインする必要がある。これはMicrosoftが消費者向けWindowsの全バージョンでアカウント要件を強制する初めてのケースである。

企業ユーザーはドメインやその他のアカウントを使用して新しい要件をバイパスできるが、一般ユーザーの選択肢は限られている。Rufusのようなツールを使えば、アカウント要件を削除したインストールイメージを作成することはまだ可能だが、Microsoftは将来的にこれらの方法もブロックする可能性がある。

この変更は、2024年3月から段階的に実装され、2025年3月現在では広く適用されている。
【備忘録】AWS EC2 Auto Scaling概要 + 構築手順

# EC2 Auto Scaling
**自動でEC2インスタンスの数を増減させる機能
EC2インスタンスの最大・最初の数を指定する**

### 起動設定
Auto Scalingで起動するEC2インスタンスの情報を設定
- AMI
- インスタンスタイプ
- セキュリティグループ など

### Auto Scalingグループ
Auto Scaling全体の管理
- どの起動設定を使うのか
- 最小/最大のインスタンス数
- 配置するサブネット
- スケーリングポリシー など

### スケーリングの方法
- 手動スケーリング
- スケジュールスケーリング
- 動的なスケーリング

## スケーリングポリシー
### シンプルなスケーリング
1つのメトリクスに対して、1つのしきい値を設定するポリシー
ex)CPU使用率が80%以上なら1つインスタンスを増やす

### ステップスケーリング
1つのメトリクスに対して、複数のしきい値を設定するポリシー

### ターゲット追跡スケーリング
1つのメトリクスに対して、ターゲット値を設定するポリシー
ex)CPU使用率が50%というターゲット値を設定すると、自動的にターゲット値になるようにEC2インスタンスの数を増減してくれる

## クールダウン・ウォームアップ
### クールダウン
Auto Scalingでインスタンスを作成し始めてから、指定した時間内はAuto Scalingで新しくインスタンスを作成しないようにする設定

### ウォームアップ
複数のしきい値を同時に超えた後に、差分となるインスタンス数だけ作成する設定**
以下の**スケーリングポリシー**が適用されている段階で
①CPU使用率80%超えたら1つインスタンスを作成
②CPU使用率90%超えたら2つインスタンスを作成
**ウォームアップ設定あり** かつ **ウォームアップ期間中なら
CPU使用率が90%を超えた段階**で**2つ**インスタンスが作成される
**ウォームアップ期間中でないなら
CPU使用率が90%を超えた段階**で**3つ**インスタンスが作成される

## Auto Scaling構築手順
**1.起動テンプレートの作成**
**2.Auto Scalingグループの作成**

**1-1.起動テンプレート名・AMI・インスタンスタイプ・キーペア・サブネット(AZ分けて冗長化する場合は指定しない)・セキュリティグループ・IAMロールを選択する**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/5e75d958-d2ec-4532-8d07-7e85d7661d81.png)

![image 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/266e1355-ca35-4d82-af90-a6ea56ea1db7.png)

**1-2.正常に作成されましたと表示されればOK**
![image 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/0a8e0f28-e779-4c6c-bf56-6f6aaa7030f1.png)

**2-1.Auto Scalingグループ名・起動テンプレートを指定して次へをクリックする**
![image 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/66841aa7-2c93-428d-8655-ea1bfcc3cc05.png)

**2-2.VPC・サブネットを指定して次へをクリックする**
![image 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/d02c9bfd-7b8c-4dcd-b0d6-661332ba1567.png)

**2-3.アタッチするLB・ELBでのヘルスチェックを選択する**
![image 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/0c54efc3-bb0b-43b3-8030-c210d1f1dce8.png)

![image 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/8585bf58-88b6-4a1e-a208-671e8aca77f1.png)

**2-4.希望するキャパシティ・スケーリング制限を指定してオートスケールするインスタンス数の上限・下限を指定出来る**
![image 7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/9e25ff0e-cbe6-4ec0-99ae-53d09dd9d96f.png)
現在のディレクトリ（パスなし）を取得する

ほかにいい方法があるならぜひ教えていただきたく。

```bash
pwd | awk -F'/' '{print $NF}'
```

または

```bash
pwd | sed -r 's/^.*\///'
```

どちらがいいんだろうか。
もしくはもっとよいやり方があるのだろうか。

---

情報提供いただきました！

変数に突っ込む場合、

```bash
baseline = ${PWD##*/}
```

でいけるそうです。

変数 `PWD` にはおそらく `pwd` コマンドと同様の結果が格納されております。
そして `##` が変数を前方最長一致で除去してくれるので、最後の `/` まで除去してくれるんですね。すごい。 `*` はワイルドカードだ。

もう一つ、

```bash
basename -- "$PWD"
```

~~で標準出力が可能らしいのですが、 `--` がわからなさすぎてまた編集します。。。
なんとなく集合演算というか、論理積なのかな？と思っていますが。。。
または単なる差分なのか~~

で標準出力が可能です。
`--` はオプションの終わりを表します。
`git diff -- [filename]` などでよくお世話になっていました。


コメントでのご教示、ありがとうございました！
年度を計算

# はじめに
日付に関する小ネタを紹介します。
自分の中では当たり前に使っていましたが、職場での反応が良かったので記事にしようと思います。

# 年度を計算
```c#:C#
int fiscalYear;
if (DateTime.Today.Month < 4)
{
    // 1～3月は前年
    fiscalYear = DateTime.Today.Year - 1;
}
else
{
    // 4～12月は当年
    fiscalYear = DateTime.Today.Year;
}
```
日付の3ヶ月前の年を取れば年度が取得できます。
```c#:C#
int fiscalYear = DateTime.Today.AddMonths(-3).Year;
```
条件分岐がなく、シンプルにできました。

# 2つの期間が重なるデータ
2つの期間は以下の6パターンに分けられます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779420/cdf6b0d1-7b56-4c3e-9ac9-f1c2d95ec6e1.png)

期間が重なるデータなので、抽出したいデータは②③④⑤です。
```sql:SQL
SELECT *
  FROM table_1
 INNER JOIN table_2
         ON table_1.id = table_2.id
 WHERE (table_1.startDate >= table_2.startDate
        AND
        table_1.startDate <= table_2.endDate) -- ２，３
    OR (table_2.startDate >= table_1.startDate
        AND
        table_2.startDate <= table_1.endDate) -- ４，５
```
ちょっと分かりづらいです。

ここで期間は必ず6パターンに収まるので、①⑥以外を求めると②③④⑤になります。
```sql:②または③または④または⑤
 WHERE (table_1.startDate >= table_2.startDate
        AND
        table_1.startDate <= table_2.endDate)
    OR (table_2.startDate >= table_1.startDate
        AND
        table_2.startDate <= table_1.endDate)
```
↓
```sql:「① または ⑥」以外
 WHERE NOT (table_1.startDate > table_2.endDate
            OR
            table_2.startDate > table_1.endDate)
```
↓
```sql:①以外 かつ ⑥以外
 WHERE NOT table_1.startDate > table_2.endDate
   AND NOT table_2.startDate > table_1.endDate
```

つまり、こうなります。
```sql:SQL
SELECT *
  FROM table_1
 INNER JOIN table_2
         ON table_1.id = table_2.id
 WHERE table_1.startDate <= table_2.endDate
   AND table_2.startDate <= table_1.endDate
```
【Windows】ファイル名・フォルダ名の一括取得

# 記事概要
フォルダ内に存在するすべてのファイル名・フォルダ名を一括で取得する方法を記載する。

# 前提
- PCはWindowsを使用している

# 手順
1. エクスプローラーでフォルダに移動する
1. アドレスバーに`cmd`と入力し、エンターボタンをクリックする
1. 上記パスで、コマンドプロンプト画面が表示される
1. 下記コマンドを実行する
    | パス | コマンド |
    |---|---|
    | なし | dir /b |
    | あり | dir /b /s |
    
1. ファイル名とフォルダ名がコマンドプロンプト画面に表示される
1. `exit`コマンドを実行し、コマンドプロンプト画面が終了する
タブレット購入記録20250328

# 動機
- 時期的問題
    - 学割利用資格を今年度いっぱいで失う
    - 現在の端末のXiaomi Pad5 256GB版を購入して3年経ちセキュリティアップデート頻度が低下している
- 慢性的不満
    - デフォルトランチャーアプリ
        - デフォルトランチャーアプリが初期から改悪アプデが入り、最大アイコン密度が非常に低い(4*6)
        - デフォルトランチャーアプリがかなりもっさり。表示まで時間がかかる
    - 指紋認証非搭載

# Xiaomi Pad5のよかったところ
不満点(大した不満は無かったが)は前項にて記載した。良かった点を羅列する。
- ディスプレイ性能が良い(解像度 リフレッシュレート)
- 音が良い
- ユーザ切り替え機能やデュアルアプリ機能(メインユーザ サブユーザ)がある(Androidのサポートより前からあった)
- アプリロック機能がある
- 電池持ちに関して不満を感じたことが無い
- ストレージに余裕がある

# タブレットの用途
タブレットに求める要件を決めるにあたって、何に利用していたか、何に利用したいかを記す。
- 外出中の
    - アニメ視聴
    - 地図
    - ブラウザ
    - Twitter
    - PDF閲覧
- プロセカ

# タブレットに求める要件
上記を踏まえて、最低限満たしたい要件を記す。
| 機能 | レベル |
| --- | --- |
| 画面 | 10インチ以上(Xiaomi Pad5と同等以上) |
| ストレージ | 128GB以上 |
| 他人貸与時用の機能 | 有り |
| 最低ソフトウェアアップデート保証 | 現在から３年以上 |
| CPU?性能 | Xiaomi Pad 5より高性能 |
| 価格 | 80000円以内 |

できれば追加で満たしたい要件を記す
| 機能 | レベル |
| --- | --- |
| ストレージ | 256GB以上 |
| 生体認証 | 指紋認証 |
| メーカ | できれば日本と友好国籍企業 |
| 価格 | 60000円以内 |

よくよく考えると、意外と求めるものは少ないんだなぁと。

# 要件を満たすタブレット一覧
| 商品名 | 価格(円) |
| --- | --- |
| iPad 11インチ (A16) Wi-Fi 128GB | 54800 |
| iPad 11インチ (A16) Wi-Fi 256GB | 70800 |
| Xiaomi Pad 7 8GB+256GB | 54980 |
| Xiaomi Pad 7 Pro 8GB+128GB | 67980 |
| Galaxy Tab S6 Lite 2024 | 53570 |
| IdeaTab Pro | 54780 |

どれもそれほど大きく価格は変わらない。
128GBから256GBにアップすると大きく価格上昇。10000円以上の価値は無いと感じ、128GBモデルに絞ることにした。

# 各機種特徴
## iPad A16
- Air Tag探せる
- Appleトークに混じれる
- 指紋認証

## Xiaomi Pad 7
- 今使っているXiaomi Pad 5の後継機種で使い慣れている
- 144Hzディスプレイ
- クアッドスピーカ

## Galaxy Tab S6
- 内蔵ストレージは64GBで別売りSDカード拡張可能
- GPSセンサ搭載

## IdeaPad
- バッテリーでかい 10200mAh
- Android 16まで 2029まで保証
- microSD対応

# 購入
iPad購入しました。
AppleのブランドイメージとAirTag使えることが決め手でした。ここまで悩んでズッコケそうな判断材料でした。
リモート vs フル出社：両方経験して分かった、それぞれのメリット・デメリット

# はじめに
ここ最近、アメリカの大企業を中心に脱リモート化の動きが進んでいます。日本でも徐々に出社回帰の流れが加速しており、フルリモートからオフィス勤務へと移行する企業も増えています。

そんな中、私も社会人4年目にして初めてフル出社を経験しました。これまでのリモート勤務と比較しながら、それぞれのメリット・デメリットについて私の体験を元に考えてみました。

# これまでの勤務形態の変遷
| 年   | 出社頻度       |
|------|--------------|
| 2021 | ほぼリモート  |
| 2022 | 週1,2出社    |
| 2023 | 週1,2出社    |
| 2024 | フルリモート  |
| 2025 | フル出社      |

私は2021年に新卒入社しました。当時はコロナ禍の影響で、基本的にフルリモート勤務でした。その後、週1～2回の出社を伴うハイブリッドワークが続いていましたが、2024年は案件の関係で完全リモートに。そして2025年、別の案件にアサインされたことをきっかけに、フル出社へと移行しました。

# フルリモートについて
## メリット


1. **自己研鑽の時間が取れる**
1. **睡眠の質が上がる**
1. **生活リズムが安定する**
1. **出費が減る**

### 📕 自己研鑽の時間が取れる
通勤がない分、1日あたり約2時間の余裕が生まれました。この時間を活用し、技術書を読んだり、プログラミングの学習を進めたりと、スキルアップに充てることができました。

### 🛏️ 睡眠の質が上がる
私は過去に何度か不眠に悩み、病院に通った経験があります。フルリモートでは通勤のストレスがなく、睡眠時間をしっかり確保できるため、体調管理の面でも非常に助かりました。結果的に、仕事のパフォーマンス向上にもつながりました。

### 🏠 生活リズムが安定する
朝の時間を自由に使えるため、起床後に散歩をしたり、読書をしたりと、規則正しい生活を送ることができました。通勤があると朝の準備に追われますが、リモートなら自分のペースで1日をスタートできます。

### 💰 出費が減る
基本的に自宅で過ごすため、外食や飲み会の機会が減り、結果として支出も抑えられます。私は人と会うのが好きで、誘われたら断らないタイプですが、リモートワークではそもそも誘われる機会が少なくなるため、自然と交際費を節約できました。

## デメリット
フルリモート勤務で感じたデメリットは以下の2つです。

+ **一人の時間が増える**
+ **刺激が少なくなる**

### 😔 一人の時間が増える
業務中は基本的に一人で仕事を進めるため、チームとの一体感が薄れがちです。帰属意識が希薄になり、「自分は本当に会社の一員なのか？」と感じることもありました。特に、仕事で困難に直面したときに孤独感を強く感じることがありました。

### 😣 刺激がなくなる
外に出る機会が減るため、自然と新しい発見が少なくなります。また、オフィスでの雑談や同僚との何気ない会話から生まれるアイデアがなくなるのもデメリットの一つです。意識的に人と会わないと、新たなつながりを作るのが難しくなります。

# フル出社について
## メリット

+ **チームメンバーとの一体感**
+ **コミュニケーションがスムーズになる**

### 😀 チームメンバーとの一体感
今回、私はこのフル出社の案件に2ヶ月間関わりました。そこで初めて「チームで仕事をしている」という感覚を味わうことができました。毎日同じオフィスで働き、対面で議論しながら進めることで、仲間意識が強くなり、プロジェクトへのモチベーションも向上しました。。

### 😁 コミュニケーションがスムーズになる
今まではオンラインでのやり取りが中心でしたが、対面なら細かいニュアンスや表情から相手の意図を汲み取りやすくなります。また、一緒にランチをしたり雑談を交えたりすることで、相手の人となりを知る機会が増え、より円滑なコミュニケーションが取れるようになりました。

## デメリット

+ ***体力的な消耗が激しい***
+ ***睡眠時間の減少***

### 🤧 体力的な消耗が激しい
フル出社の案件では勤務場所が変更されたため、通勤に片道2時間かかり、往復で4時間を費やすことになります。これは想像以上に体力を消耗し、仕事が終わった後はヘトヘトになっていました。長時間の通勤は、それだけでかなりの負担になると実感しました。

### 😴 睡眠時間の減少
通勤時間が長いため、朝は早く起き、夜も早めに寝る必要がありました。結果として、リモートワークのときよりも自由に使える時間が減り、睡眠時間の確保が難しくなりました。体調管理の面では、リモートの方が圧倒的に楽でした。

# 結局どちらが良いのか？
フルリモートとフル出社、それぞれにメリット・デメリットがあり、一長一短です。私個人としては、 ***ハイブリッドワーク***が最適だと感じました。

フルリモートは自由度が高く、体調管理もしやすいですが、一人の時間が多くなりがちです。一方でフル出社は、チームの一体感が高まり、コミュニケーションが円滑になるメリットがあります。

そのため、週2～3回の出社とリモートを組み合わせることで、両者の良い部分を活かしつつ、バランスを取ることができると考えます。企業によって働き方の方針は異なりますが、自分に合ったスタイルを見つけることが、最も重要だと感じました。

# 終わりに
今回、初めてフル出社を経験し、リモートワークとの違いを改めて実感しました。それぞれにメリット・デメリットがあり、一概にどちらが良いとは言えませんが、自分にとって何が最適なのかを考える良い機会になりました。
【Go】RSA暗号を理解するためにサンプルコード書いてみた


## 概要

- [**暗号技術入門 第3版**](https://amzn.asia/d/4EzqngT)に出てきたRSA暗号を理解するためにサンプルコード書いてみた
- パッケージなどは使わずに内部的な処理の理解を優先した最小限の実装

## サンプルコード


```go
package main

import "fmt"

// わかりやすくするため最小の素数を使う
const (
	p, q = 3, 5
)

// Nの生成
func generateN() int {
	n := p * q
	return n
}

// Lの生成
func generateL() int {
	l := (p - 1) * (q - 1)
	return l
}

// Eの生成
// 1 < E < L
// gcd(E, L) = 1
func generateE(l int) int {
	e := 2
	for e < l {
		if gcd(e, l) == 1 {
			break
		}
		e++
	}
	return e
}

// gcd(E, L) = 1を満たしているかをチェック
func gcd(e, l int) int {
	for l != 0 {
		e, l = l, e % l
	}
	return e
}

// Dの生成
// 1 < D < L
// E * D mod L = 1
func generateD(e, l int) int {
	d := 1
	for {
		if (e * d) % l == 1 {
			break
		}
		d++
	}
	return d
}

// 暗号化(復号化にも使用)
// m^e mod n
func modExp(m, e, n int) int {
	result := 1
	for e > 0 {
		if e % 2 == 1 {
			result = (result * m) % n
		}
		m = (m * m) % n
		e /= 2
	}
	return result
}

func main() {
	n := generateN() // 15
	l := generateL() // 8
	e := generateE(l) // 3
	d := generateD(e, l) // 3

	// 平文にはN未満の数値を指定
	target := 8 
	// 暗号化
	encrypted := modExp(target, e, n)
	// 復号化
	decrypted := modExp(encrypted, d, n)
	
	fmt.Println("平文:", target)
	fmt.Println("暗号化:", encrypted)
	fmt.Println("復号化:", decrypted)
}

// 出力
// 平文: 8
// 暗号化: 2
// 復号化: 8

```
🎉 楽しく学ぶDDD（ドメインモデルの設計編）！

## :cherry_blossom: はじめに

こんにちは！DDDを楽しく学んだところで、今日はさらにステップアップして「ドメインモデルの設計方法」を詳しく見ていきましょう！

## 📚 ドメインモデルの設計ってどうやるの？

ドメインモデルを作るときには、「モノ（エンティティ・値オブジェクト）」と「コト（操作や振る舞い）」を具体的に整理していきます。

## 🧸 ドメインモデルを作る３つのポイント！

### ① エンティティ（識別できるモノ）
エンティティは「それがどれなのかを識別できるモノ」のこと。

例えば学校なら「生徒」や「先生」がエンティティ。生徒Aさんと生徒Bさんは別の人だよね。それをちゃんと区別するために、IDや番号を使うよ。

🎯 **エンティティの例（生徒）**
- 識別子（ID、生徒番号）
- 属性（名前、学年、クラス）
- 振る舞い（授業を受ける、宿題をする）

### ② 値オブジェクト（区別が必要ないモノ）
値オブジェクトは、特に区別する必要がない情報のこと。

例えば「クラスの名前」は値オブジェクト。1年1組という名前は、どれも同じ意味で使えるよね！

🍀 **値オブジェクトの例（クラス名）**
- 値（「1年1組」などのクラス名）
- 不変条件（1年～6年の範囲であること）

### ③ 情報（属性）と操作（振る舞い）
ドメインモデルでは、各エンティティや値オブジェクトがどんな情報を持っているか（属性）、どんな操作や動きができるか（振る舞い）を明確にします。

🌈 **情報（属性）の例**
- 生徒の名前、生徒番号、クラス
- 教室番号、設備の有無

🌟 **操作（振る舞い）の例**
- 生徒が授業を受ける、宿題を提出する
- 教室で授業を開催する、掃除をする

### ④ 不変条件（必ず守るルール）
ドメインモデルには、必ず守るルール「不変条件」があるよ！

例えば、学校のクラス名なら「1年～6年までしか使えない」など、絶対に守らないといけない条件があるんだ。

📝 **不変条件の例**
- 生徒番号は重複しない
- クラスは1年～6年のみ使える

## 🎨 実際の設計手順は？

1. ドメインを整理する（学校なら生徒、先生、教室など）
2. エンティティと値オブジェクトを決める（識別が必要かどうかで分ける）
3. 各オブジェクトが持つ情報（属性）と操作（振る舞い）を決める
4. 不変条件（絶対に守るべきルール）を設定する

## 🚀 ドメインモデルを設計するメリット

- 明確なルールができて、混乱が減る！
- チームみんなが同じ理解でスムーズに作業できる！
- 後から機能を追加しても、きれいに整理できる！

次は[リポジトリの設計編](https://qiita.com/shinkawa_misaki/items/36a8fd6cc31581302b9a)です✨😄🚀
iPad Proに有線アーケードコントローラー（アケコン）を接続する方法

iOS向けRetroarchがリリースされたのでiPadで有線アケコン（HORI ファイティングエッジ刃）をつないで遊べないか試行錯誤した結果成功したのでメモ。

接続は以下のようにした。
アケコン <-> Brook Wingman NS <-> USB-A,C変換 <-> iPad Pro(11インチ M1 iPadOS 18.3.1)
[参考]Wingman NS
![2007096761.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302877/ef83d712-a0af-4d10-bab7-99c09ced5e84.jpeg)

https://www.brookaccessory.com/detail/81849027/

Retroarchの設定からドライバ -> コントローラーをmfiにする

以上でiPad上のRetroarchでアケコンの入力が反映されることを確認できた。

ROMはSteamで購入したゲームなどから合法的に入手しましょう！
[参考]
https://krsw.5ch.net/test/read.cgi/steam/1652279411
🎉 楽しく学ぶDDD（ドメイン駆動設計）！

## :cherry_blossom: はじめに

こんにちは！DDDって聞いたことあるけど難しそう？
大丈夫、今日は明るく楽しく学んでいきましょう！

## 🌈 DDDって何だろう？

DDD（ドメイン駆動設計）は、「難しいことを整理して、みんなが同じ理解で仲良く進められるようにする方法」です！

## 🚀 大切な4つのポイントを覚えよう！

### ① ドメイン
ドメインとは、プロジェクトで注目しているテーマの領域のこと！学校を例にすると、「授業」「クラブ活動」「学校行事」などがドメインだよ。

### ② 境界づけられたコンテキスト
同じ言葉でも場所が変わると意味が違うこともあるよね。それを避けるために同じ意味を共有するグループ、それが「境界づけられたコンテキスト」です！

🎒 **学校の場合**
- 「授業コンテキスト」：「宿題」「テスト」「授業」など、勉強に関する言葉。
- 「クラブ活動コンテキスト」：「練習」「試合」「大会」など、部活の言葉。

こうすると、混乱なく楽しく話せるよね！

### ③ ドメインモデル

ドメインモデルとは、業務の中の『モノ』（例：エンティティや値オブジェクト）と、それに伴う『コト』（例：操作やイベント）を表現したモデルのこと。学校だとこんな感じ！

🎓 **モノ（物）**
- 生徒：名前、学年、クラスの情報を持ち、授業に参加する、宿題をするという行動ができる。
- 教室：教室番号、設備などを持ち、授業を開く、掃除をする行動ができる。

🎯 **コト（事）**
- 授業をする
- テストを受ける
- 試合に出る

### ④ ユビキタス言語

**ユビキタス言語**は、チームのみんなが同じ意味で使う「共通の言葉」。
この**ユビキタス言語**は**境界づけられたコンテキストごと**に定義され、コンテキスト間では同じ単語でも別の意味を持っていて構いません。
境界づけられたコンテキストごとに同じ言葉を使うことで、分かりやすくスムーズに話が進みます！


例えば「授業」と決めたら、授業コンテキスト内ではみんな「授業」という言葉を変えずに使うようにするんだ！

## 🎈DDDの嬉しいポイント！

- みんなで同じ言葉を使えるから楽しくスムーズに進む！
- わかりやすく整理されて、間違いや誤解が減る！
- 複雑なことでも明るくクリアに！チームがひとつになれる！

次は[ドメインモデルの設計編](https://qiita.com/shinkawa_misaki/items/43d6e3fe3a3c3d8c7df5)です✨😄🚀
日時を文字列にしたり、日時から数値を取得したり

日時を取得する色々な関数
```
Now()
```
現在日時を取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740014/d0243698-a2db-4e16-b54b-41076ff8380b.png)
テキストラベルに記載するとこんな感じ。表示はされていませんが秒もちゃんと取得できています。

※ただアプリで表示した際の日時が取得できるだけなので、その瞬間の日時を取得するにはOnSelectプロパティで変数に格納したり、時計のように機能させるにはタイマーコントロールと組み合わせるなど工夫が必要です

```
Text(Now(),"yyyy年mm月dd日ddd HH:mm:ss") //2025年03月28日金曜日 21:02:48
```
テキスト関数と組み合わせて日時を文字列に

日時から数値を取得する便利な関数もあります。

```
Year(Now()) //年
```
```
Month(Now())  //月
```
```
Day(Now()) //日
```
```
Hour(Now()) //時
```
```
Minute(Now()) //分
```
```
Second(Now()) //秒
```

業務アプリで割と使うのが年度の取得
```
//年度の取得
If(
    Month(Now()) < 4,
    Year(Now()) - 1,
    Year(Now())
)
```
数値で取得できるので、計算ができます。

```
//今の年度を変数に格納
Set(_nendo,
    If(
        Month(Now()) < 4,
        Year(Now()) - 1,
        Year(Now())
    )
)
```
アプリ起動時に変数に入れておくと、アプリ全体で使えるので便利です。
高火力DOKでAPIを使ってタスクを実行する

## はじめに
高火力 DOKでAPIを使ってタスクを実行する方法について解説します。

高火力 DOKは、さくらインターネットが提供するコンテナ型GPUサービスです。
https://www.sakura.ad.jp/koukaryoku-dok/

通常、タスクの作成や実行はダッシュボードから操作できますが、APIを利用することで自動化や外部ツールとの連携が可能になります。

## 前提
- 高火力 DOKのアカウントを持っている
    - [サービスを使い始めるには](https://manual.sakura.ad.jp/cloud/koukaryoku-container/getting-started.html#id11)
- さくらのクラウド APIキーを持っている
    - [APIキー](https://manual.sakura.ad.jp/cloud/api/apikey.html)

#### 注意事項
- 今回は、利用規約への同意を行なっている前提となります
詳細は[サービスを使い始めるには](https://manual.sakura.ad.jp/cloud/koukaryoku-container/getting-started.html#id11) を参照してください
- APIキーの権限として、以下を前提としています。

| 項目 | 設定 |
|:-----------|:------------|
| アクセスレベル    | 作成・削除 |
| 他サービスへのアクセス権 | 高火力DOK|

参考画像
![create api.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282233/e167676d-e52f-4e22-89cd-2548d39884b0.png)

## 高火力 DOK API
- [タスクの登録](https://manual.sakura.ad.jp/koukaryoku-dok-api/spec.html)と[API使用例](https://manual.sakura.ad.jp/cloud/iotpf/api.html)を参考にタスクを登録します

今回は、[ubuntu](https://hub.docker.com/_/ubuntu)イメージを使用して、`printenv`するタスクを作成します。

```
curl -u "<アクセストークン>:<アクセストークンシークレット>" \
  -X POST https://secure.sakura.ad.jp/cloud/zone/is1a/api/managed-container/1.0/tasks/ \
  -H "Content-Type: application/json" \
  -d '{
    "name": "example-task",
    "containers": [
      {
        "image": "ubuntu:latest",
        "command": ["printenv"],
        "environment": {
          "EXAMPLE_ENV": "example"
        },
        "plan": "v100-32gb"
      }
    ]
  }'
```

`plan` は使用するGPUインスタンスの種類を表します。  
利用可能なプラン一覧は [公式ドキュメント](https://manual.sakura.ad.jp/cloud/koukaryoku-container/specification.html)を参照してください。

以下のように応答が返ってきたら成功ですYatta!!!
```
{
  "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "created_at": "2025-03-28T20:00:00.000000+09:00",
  "updated_at": "2025-03-28T20:10:00.000000+09:00",
  "canceled_at": null,
  "name": "example-task",
  "http_uri": null,
  "containers": [
    {
      "index": 0,
      "registry": null,
      "image": "ubuntu:latest",
      "command": [
        "printenv"
      ],
      "entrypoint": [],
      "environment": {
        "EXAMPLE_ENV": "example"
      },
      "http": null,
      "plan": "v100-32gb",
      "start_at": null,
      "stop_at": null,
      "execution_seconds": null,
      "exit_code": null
    }
  ],
  "status": "waiting",
  "error_message": "",
  "artifact": null,
  "tags": []
}
```

ダッシュボードからも実行を確認できました\wa-i/
![dok task.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282233/bc3b84b6-d1bd-4739-81ac-54691c1bbc1b.png)

## まとめ

この記事では、高火力DOKのAPIを使ってタスクを実行する手順を説明しました。

高火力DOKではAPIを使ってログ取得やタスクの状態取得、停止なども可能なので、CI/CDやバッチ処理にも活用できます。ぜひ色々試してみてください！

ここまで読んでいただきありがとうございました 🙌

## 参考文献
- [さくらのクラウド マニュアル APIキー](https://manual.sakura.ad.jp/cloud/api/apikey.html)
- [さくらのクラウド マニュアル API使用例](https://manual.sakura.ad.jp/cloud/iotpf/api.html)
- [高火力 DOK ドキュメント](https://manual.sakura.ad.jp/cloud/manual-koukaryoku-container.html)
- [高火力 DOK APIドキュメント](https://manual.sakura.ad.jp/koukaryoku-dok-api/spec.html)
Discord Botを作ろう！Pythonでボイスチャットを管理する方法


## 🔍 目次
1. [はじめに](#はじめに)
2. [前提条件](#前提条件)
3. [必要なライブラリのインストール](#必要なライブラリのインストール)
4. [Botトークンを安全に管理する](#botトークンを安全に管理する)
5. [Discord Botのコード](#discord-botのコード)
6. [Botの実行方法](#botの実行方法)
7. [トラブルシューティング](#トラブルシューティング)
8. [おわりに](#おわりに)

## はじめに
Discordはゲーマーやコミュニティ向けのチャットツールとして人気ですが、自分専用のBotを作ることで、サーバー管理がより便利になります。  
この記事ではPythonを使って「ボイスチャットのミュート・ミュート解除」を行うDiscord Botの作成方法を解説します。

## 前提条件
- Python 3.x がインストールされていること
- Discordアカウントとサーバーを持っていること
- Pythonの基本文法 (関数・変数・モジュールのインポートなど) を理解していること

## 必要なライブラリのインストール
まずは、`discord.py`と`.env`ファイルを利用するための`python-dotenv`をインストールします。

```sh
pip install discord.py python-dotenv
```

## Botトークンを安全に管理する
Botのトークンをコードに直接書くと、誤って公開してしまう危険があります。  
そこで`.env`ファイルを使ってトークンを管理する方法を紹介します。

### `.env` ファイルを作成
プロジェクトフォルダ内に `.env` というファイルを作成し、以下のように記述します。

```
DISCORD_BOT_TOKEN={取得したBotのトークン}
```

### Pythonコード内で読み込む
`dotenv` を使って `.env` の値を取得します。

```python
import os
from dotenv import load_dotenv

load_dotenv()
TOKEN = os.getenv("DISCORD_BOT_TOKEN")
```

## Discord Botのコード
以下のコードを`bot.py`として保存し実行すると、VCのミュート管理が可能なBotが動作します。

```python
import discord
from discord.ext import commands
import os
from dotenv import load_dotenv

# .env ファイルからトークンを読み込む
load_dotenv()
TOKEN = os.getenv("DISCORD_BOT_TOKEN")

intents = discord.Intents.default()
intents.voice_states = True
intents.guilds = True
intents.message_content= True

bot= commands.Bot(command_prefix='!', intents=intents)

@bot.command()
async def mute(ctx, member: discord.Member):
    """ 指定したメンバーをミュート """
    if member.voice and member.voice.channel:
        await member.edit(mute=True)
        await ctx.send(f'{member.name} をミュートしました。')
    else:
        await ctx.send(f'{member.name} はVCにいません。')

@bot.command()
async def unmute(ctx, member: discord.Member):
    """ 指定したメンバーのミュートを解除 """
    if member.voice and member.voice.channel:
        await member.edit(mute=False)
        await ctx.send(f'{member.name} のミュートを解除しました。')
    else:
        await ctx.send(f'{member.name} はVCにいません。')

@bot.command()
async def mute_all(ctx):
    """ VC内の全メンバーをミュート """
    if ctx.author.voice and ctx.author.voice.channel:
        members = ctx.author.voice.channel.members
        for member in members:
            await member.edit(mute=True)
        await ctx.send("VC内の全メンバーをミュートしました。")
    else:
        await ctx.send("あなたはVCにいません。")

@bot.command()
async def unmute_all(ctx):
    """ VC内の全メンバーのミュートを解除 """
    if ctx.author.voice and ctx.author.voice.channel:
        members = ctx.author.voice.channel.members
        for member in members:
            await member.edit(mute=False)
        await ctx.send("VC内の全メンバーのミュートを解除しました。")
    else:
        await ctx.send("あなたはVCにいません。")

# Botを起動
bot.run(TOKEN)
```

## Botの実行方法
1. [Discord Developer Portal](https://discord.com/developers/applications) でBotを作成し、トークンを取得
2. `.env`ファイルにトークンを保存
3. ターミナルで`python bot.py`を実行

## トラブルシューティング
- **Botがサーバーに参加していない場合** → サーバーに追加する
- **Botに権限がない場合** → 管理者権限を付与する
- **Botがミュートできない場合** → `Manage Members`権限を確認する

## おわりに
この記事ではPythonを使ってDiscord Botを作成し、ボイスチャットのミュート/ミュート解除を管理する方法を紹介しました。<br>  
Botの機能を拡張すれば、音楽再生や自動メッセージ送信などさまざまな用途に応用できます。
ぜひ自分なりの Botを作ってみてください。
NestJSでロールベースの認可を実現する

皆さん、こんにちは。

今回は「NestJSでロールベースの認可を実現する」について紹介させていただきます。

NestJSでロールベースの認可を実現するには、カスタムガードを作成し、ルートハンドラーに付与したメタデータをチェックする方法が一般的です。以下に、その基本的な定義方法とサンプルコードを示します。

# RolesGuardの作成

RolesGuardは、NestJSのCanActivateインターフェースを実装し、リクエスト時にユーザのロール情報をチェックします。ガード内では、Reflectorサービスを利用して、エンドポイントに付与したロールメタデータを取得します。

```typescript
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';

@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private readonly reflector: Reflector) {}

  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    // エンドポイントに設定されたロールメタデータを取得
    const requiredRoles = this.reflector.get<string[]>('roles', context.getHandler());
    
    // ロールが設定されていなければアクセスを許可
    if (!requiredRoles) {
      return true;
    }
    
    // HTTPリクエストからユーザ情報を取得（認証済みのユーザ情報が格納されている前提）
    const request = context.switchToHttp().getRequest();
    const user = request.user;
    
    // ユーザが存在し、かつユーザのロールにrequiredRolesのいずれかが含まれているかチェック
    return user && user.roles && requiredRoles.some(role => user.roles.includes(role));
  }
}

```

# Rolesデコレーターの作成

RolesGuardが参照するためのロール情報は、カスタムデコレーターで付与します。これにより、各ルートハンドラーで必要なロールを簡単に設定できます。

```typescript
import { SetMetadata } from '@nestjs/common';

export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
```

# コントローラーでの使用例

作成したRolesGuardとRolesデコレーターを利用して、特定のエンドポイントにアクセス制限を実装します。

```typescript
import { Controller, Get, UseGuards } from '@nestjs/common';
import { Roles } from './roles.decorator';
import { RolesGuard } from './roles.guard';

@Controller('cats')
@UseGuards(RolesGuard) // コントローラー単位でガードを適用
export class CatsController {
  
  @Get()
  @Roles('admin') // このエンドポイントはadminロールを持つユーザのみアクセス可能
  findAll() {
    // エンドポイントの処理
    return 'This route is restricted to admins.';
  }
}
```

# 解説

- Reflectorの利用:
Reflectorサービスは、メタデータ（ここではroles）を取得するために使います。これにより、デコレーターで設定されたロール情報をガードで読み出すことができます。

- リクエストのユーザ情報:
認証処理（例えばPassportを利用）によって、リクエストオブジェクトにuserプロパティが追加されている前提です。ここからユーザのロール情報（例：user.roles）を取得し、必要なロールと照合します。

- 柔軟な設計:
ロールが設定されていないエンドポイントはデフォルトでアクセスを許可するようにしているため、特に制限が不要なルートはそのまま利用できます。

このように、NestJSではカスタムガードとデコレーターを組み合わせることで、柔軟なロールベース認可を簡単に実装できます。各プロジェクトの要件に合わせて、ガードのロジックやエラーハンドリングをさらにカスタマイズすることも可能です。

今日は以上です。

ありがとうございました。
よろしくお願いいたします。
Intelコンパイラのインストール（Ubuntu 22.04 LTS）

# 概要
無償利用が可能になったintelコンパイラを導入した際の備忘録。


# 環境
- OS: Ubuntu 22.04 (Windows11 wsl2)

# intel oneAPIのインストール
## intel oneAPI Base Toolkitのインストール
intel oneAPI BaseToolkit をwgetで取得。最新版はHPで確認(2025/3/28時点では2025.0.1)。

```
$ wget https://registrationcenter-download.intel.com/akdlm/IRC_NAS/dfc4a434-838c-4450-a6fe-2fa903b75aa7/intel-oneapi-base-toolkit-2025.0.1.46_offline.sh
```


1. ローカル環境でのインストール
    インストールはshで可能。オプションなしの場合、GUIでインストールすることとなる。
    ```
    $ sh intel-oneapi-base-toolkit-2025.0.1.46_offline.sh -a --silent --cli --eula accept
    ```
    おそらくデフォルトのインストール先は${HOME}/intel/oneapi/。
    インストール先を変えたい場合には、オプションをつけずに
    ```
    $ sh intel-oneapi-base-toolkit-2025.0.1.46_offline.sh 
    ```
    を実行し、custom installationで変更可能（場所は左下のわかりにくい場所にある）。以降の選択肢は任意でOK。
　

2. ルートへのインストール
    ルート環境にインストールする場合にはsudoをつければよい。
    ```
    $ sudo sh intel-oneapi-base-toolkit-2025.0.1.46_offline.sh -a --silent --cli --eula accept
    ```
    

## intel oneAPI HPC Toolkitのインストール

基本的に、Base Toolkitと同じ。intel oneAPI HPC Toolkit をwgetで取得。最新版はHPで確認(2025/3/28時点では2025.0.1)。

```
$ wget https://registrationcenter-download.intel.com/akdlm/IRC_NAS/b7f71cf2-8157-4393-abae-8cea815509f7/intel-oneapi-hpc-toolkit-2025.0.1.47_offline.sh
```

1. ローカル環境でのインストール
    インストールはshで可能。オプションなしの場合、GUIでインストールすることとなる。
    ```
    $ sh intel-oneapi-hpc-toolkit-2025.0.1.47_offline.sh -a --silent --cli --eula accept
    ```
    おそらくデフォルトのインストール先は${HOME}/intel/oneapi/。
    インストール先を変えたい場合には、オプションをつけずに
    ```
    $ sh intel-oneapi-hpc-toolkit-2025.0.1.47_offline.sh
    ```
    を実行し、custom installationで変更可能（場所は左下のわかりにくい場所にある）。以降の選択肢は任意でOK。
　

2. ルートへのインストール
    ルート環境にインストールする場合にはsudoをつければよい。
    ```
    $ sudo sh intel-oneapi-hpc-toolkit-2025.0.1.47_offline.sh -a --silent --cli --eula accept
    ```
    

## 環境設定

インストール後にコマンドを使えるようにするには、
```
. <インストール先>/<toolkit-version>/oneapi-vars.sh
```
とする。インストール先がローカル環境のデフォルト、バージョンが2025.0.1の場合
```
. ${HOME}/intel/oneapi/2025.0/oneapi-vars.sh
```
とすれば、コマンドが使える。常にインテルコンパイラを使う場合には、~/.bashrcに上記を追記しておく。


<br>

参考URL
https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit-download.html
https://www.intel.com/content/www/us/en/developer/tools/oneapi/hpc-toolkit-download.html
SSHを楽にする！

# 記事概要
SSHの実施方法はいくつかありますが、少しでも楽をしたい、という思いで
ちょっとずつ改善を重ねたので、その内容を共有します。

:::note info
SSH（Secure Shell）とは、ネットワーク経由で他のコンピューターや機器を
遠隔操作するためのプロトコルです。
:::

### 前提
●公開鍵認証でのSSHを想定
●鍵は事前に作成し、以下準備しておく
　・公開鍵の中身をサーバ側のauthorized_keysに記載
　・秘密鍵をクライアント側で保持
　※サーバ利用サービスによっては勝手が違うかもしれないのでご了承ください。。
●SSHに必要な情報は以下表のとおり
| SSHに必要な情報 | 当記事での設定（適当です。あくまでイメージアップのため） |
|:-|:-|
|接続先ホスト名|www.test.com|
|接続先ポート番号|22|
|ユーザ名|test_user|
|秘密鍵のパスワード|秘密鍵生成時に設定したパスワード|
|秘密鍵のパス|~/.ssh/test.pem|


### ステップ1：Tera Term（SSHクライアントソフト）でのSSH
まずはTera Termを使ってのSSHを習得しました。
GUIベースで入力できるのでわかりやすいですが、
各項目を毎回入力するのがだんだん面倒になってきました。。

＜入力イメージ＞

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3992896/4c89136e-bd9d-4343-9a41-7cec9783c3a7.png" width=60%>

<br>
<br>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3992896/b552555c-f6be-440c-9a10-404d58ed0513.png" width=80%>

<br>
<br>

### ステップ2：CLIからのSSHコマンド（コマンド内でパラメータ指定）
次にCLI（コマンドライン）でのSSHを習得しました。
事前にコマンド内容を控えておけば、コピペ＋Enterで接続可能です。
ただしコピペが少し面倒。。

```Linux:SSH接続コマンド（Linux）
ssh -i 秘密鍵のパス -p ポート番号 ユーザ名@接続先ホスト名
※秘密鍵にパスワード設定している場合、当コマンド入力後にパスワード入力が必要
```

```Linux:SSH接続コマンド例（Linux）
ssh -i ~/.ssh/test.pem -p 22 test_user@www.test.com
```
<br>

### ステップ3：CLIからのSSHコマンド（config内でパラメータ指定）
configファイルに必要なパラメータを定義しておけば
「ssh ホスト名のエイリアス」のコマンド入力で簡単に接続できるように！

:::note info
configファイルは「.ssh/」の配下に配置します。
:::

＜configファイルの設定＞
```Linux:configファイル
# SSH接続先のホスト名のエイリアス（短縮名）
Host test
  # 接続先サーバのホスト名 or パブリックIP
  HostName www.test.com
  # sshポート番号(省略可：省略したら22)
  Port 22
  # ログインするユーザ名
  User test_user
  # ローカル端末に保存した秘密鍵のパス指定
  IdentityFile ~/.ssh/test.pem
```

```Linux:SSH接続コマンド例（Linux）
ssh test
※秘密鍵にパスワード設定している場合、当コマンド入力後にパスワード入力が必要
```
<br>

### 応用編：踏み台サーバ経由でのSSH
あるサーバに踏み台サーバを経由して接続したい場合も、
config設定しておけば簡単なコマンド入力で接続可能です。

```Linux:configファイル
# 「www.test.com」経由で「www.test2.com」に接続（秘密鍵は同じである前提）
Host test2
  HostName www.test2.com
  Port 22
  User test2_user
  # 踏み台サーバ(www.test.com：短縮名はtest)を経由してログイン
  # ※「-W %h:%p」は最終目的地（%hはtest2のホスト名、%pはtest2のポート番号を指す）
  ProxyCommand ssh test -W %h:%p
  # ローカル端末に保存した秘密鍵のパス指定（testと同じ秘密鍵を利用）
  IdentityFile ~/.ssh/test.pem
```
```Linux:SSH接続コマンド例（Linux）
ssh test2
※秘密鍵にパスワード設定している場合、当コマンド入力後にパスワード入力が必要
　（testへの接続とtest2への接続のため、パスワード入力も2回必要）
```

＜参考サイト＞

https://dev.classmethod.jp/articles/bastion-multi-stage-ssh-only-local-pem/


## 最後に
最初はSSHするのに毎回30秒くらいかかっていたのが、
今は5～10秒（ターミナル起動＋sshコマンド入力）に短縮されました。
仕事柄、SSHする機会が多いので、だいぶ楽になったと実感しています。

読んでいただいた方のご参考になれば幸いです。
storybookにRSCの設定

## バージョン

```json
  "devDependencies": {
    "next": "14.2.24",
    "@storybook/nextjs": "^8.6.10",
    "@storybook/react": "^8.6.9",
    "storybook": "^8.6.9",
    }
```

## 当初の対応

[こちらの記事](https://zenn.dev/cybozu_frontend/articles/fc8a96f6b04f47)を拝見し、storybook8では`.storybook/main.js`の記述は下記にしてました。

```tsx
const config: StorybookConfig = {
  // 省略
  features: {
    experimentalNextRSC: true,
  },
};
export default config;
```

この記述から下記のエラーによると、そんなものはないとのことでした。

```json
オブジェクト リテラルは既知のプロパティのみ指定できます。'experimentalNextRSC' は型 '{ argTypeTargetsV7?: boolean | undefined; legacyDecoratorFileOrder?: boolean | undefined; disallowImplicitActionsInRenderV8?: boolean | undefined; experimentalRSC?: boolean | undefined; viewportStoryGlobals?: boolean | undefined; backgroundsStoryGlobals?: boolean | undefined; developmentModeForBuild?: boolean | unde...' に存在しません。
```

## 正規の記述

```tsx
const config: StorybookConfig = {
  // 省略
  features: {
    experimentalRSC: true,
  },
};
export default config;
```

ちゃんと公式見よう。

## 参考記事

https://storybook.js.org/docs/get-started/frameworks/nextjs#react-server-components-rsc
C#でzlibで圧縮・展開

.NET 6.0以降、zlibを使うには`ZLibStream`を使えば追加のパッケージ無しで簡単にできるみたいです。

# 圧縮
適当なデータ（今回は「zlibテスト」というUTF8の文字列）を圧縮してみます。`ZLibStream`のインスタンスを作るときは、圧縮後のデータを書き込むStreamを渡します。さらに`CompressionMode.Compress`を指定し、圧縮モードで動作するようにします。作成した`ZLibStream`に圧縮元のデータを書き込むことで、zlibで圧縮されたデータが手に入ります。
```csharp
var data = Encoding.UTF8.GetBytes("zlibテスト");
using var compressed = new MemoryStream();
using (var zlibStream = new ZLibStream(compressed, CompressionMode.Compress))
    zlibStream.Write(data, 0, data.Length);

Console.WriteLine(BitConverter.ToString(compressed.ToArray()));
```

出力結果はこんな感じでした。
```
78-9C-AB-CA-C9-4C-7A-DC-DC-F6-B8-69-E7-E3-E6-0E-00-32-5A-07-AA
```

# 展開
先ほど得られたバイト列から、元の文字列を得られるかを試してみます。`ZLibStream`をnewするときには、圧縮後のデータを書き込むStreamを渡します。`CompressionMode.Decompress`を指定して展開モードで動作するようにします。

```csharp
byte[] compressedData = [0x78, 0x9C, 0xAB, 0xCA, 0xC9, 0x4C, 0x7A, 0xDC, 0xDC, 0xF6, 0xB8, 0x69, 0xE7, 0xE3, 0xE6, 0x0E, 0x00, 0x32, 0x5A, 0x07, 0xAA];
using var compressed = new MemoryStream(compressedData);
using var zlibStream = new ZLibStream(compressed, CompressionMode.Decompress);
using var decompressed = new MemoryStream();

zlibStream.CopyTo(decompressed);
Console.WriteLine(Encoding.UTF8.GetString(decompressed.ToArray()));
```

出力結果はこんな感じです。ちゃんと元に戻ってます。

```
zlibテスト
```

# まとめ
圧縮・展開どちらをするにしても、`ZlibStream`のコンストラクタの第一引数には**圧縮後のデータのStream**を渡す必要があります。`ZlibStream`についての記事はあまりないみたいですが、かなり簡単に使える印象でした。
Contact Form7を用いて、フォーム入力時の日時を成形してメールに表示する

### 背景
wordpress開発においてContact Form7を用いてフォームを作成する際、メールに（yyyy年mm月dd日 hh:mm）という形式で送信日時を表示する必要がありました。

しかし、日時のデフォルト表記は決まっており、そのままでは理想通りの成形（yyyy年mm月dd日 hh:mm）ができない状態でした。

同じような成形を行なっているナレッジが少なかったことから、備忘録という形で記事にさせていただきます。
<br>
### 実現したいこと
管理者用メール、フォール送信者用メールの**2つのメールに（yyyy年mm月dd日 hh:mm）形式の日時を表示させる**こと。
<br>
### 結論
**以下のコードをfunctions.phpに記載し、WordPress管理画面で[custom-date]を用いること**で、フォーム送信の日時を自分好みに成形して表示させることができます。
```php:functions.php
// フォーム入力時の日時を整形してメールに表示
add_action('wpcf7_before_send_mail', 'add_custom_cf7_date_before_mail');
function add_custom_cf7_date_before_mail($wpcf7_data)
{
    date_default_timezone_set('Asia/Tokyo');
    $current_date = date('Y年n月j日 G:i');

    // メールのプロパティを取得し [custom-date] を置換
    $mails = ['mail' => $wpcf7_data->prop('mail'), 'mail_2' => $wpcf7_data->prop('mail_2')];

    foreach ($mails as $key => &$mail) {
        if (!empty($mail)) {
            $mail['body'] = str_replace('[custom-date]', $current_date, $mail['body']);
        }
    }

    $wpcf7_data->set_properties($mails);
    return $wpcf7_data;
}
```
<br>

### コード部分の説明

#### 関数宣言部分
```php:functions.php
add_action('wpcf7_before_send_mail', 'add_custom_cf7_date_before_mail');
function add_custom_cf7_date_before_mail($wpcf7_data)
```
wpcf7_before_send_mailは、Contact Form 7 がメールを送信する前に呼ばれるフックであり、add_custom_cf7_date_before_mailという関数をこのフックに登録しています。
※メール送信する前に呼ばれる＝メール送信時の日時取得が可能

また、**$wpcf7_dataは送信フォーム全体のデータ（フォームの内容やメール設定など）が入ったオブジェクトであり、これを引数として受け取ることでフォームに設定されたメールの本文を取得できる**ようになります。


<br>

#### 現在時刻の取得部分
```php:functions.php
// タイムゾーンを東京に合わせる
date_default_timezone_set('Asia/Tokyo');
// function実行時刻（フォーム送信時刻）を取得し、「'Y年n月j日 G:i'」という形式に成形
$current_date = date('Y年n月j日 G:i');
```

PHPのdate()関数を使うことで、現在の日時（時刻を含む）を取得し、好きなフォーマットで表示することが可能になります。

<br>

#### メール設定の取得部分
```php:functions.php
// メールのプロパティを取得し [custom-date] を置換
$mails = ['mail' => $wpcf7_data->prop('mail'), 'mail_2' => $wpcf7_data->prop('mail_2')];
```

Contact Form 7 には2つのメール送信設定があり、
**・mail → 管理者宛のメール
・mail_2 → ユーザー（フォーム送信者）宛のメール**
と設定されています。

ここではそれぞれのメール設定を配列として取得しています。

<br>

#### custom-dateの置換部分
```php:functions.php
foreach ($mails as $key => &$mail) {
        if (!empty($mail)) {
            // メール本文（$mail['body']）に含まれている [custom-date] という文字列を、変数 $current_date の値に置き換える。
            $mail['body'] = str_replace('[custom-date]', $current_date, $mail['body']);
        }
}
```
foreachを用いてメールごとに（管理者宛のメール、フォーム送信者宛のメール）、**メール本文に含まれている[custom-date] という文字列を、変数 $current_date の値に置き換えています。**


<br>

### Wordpress側の説明

管理画面のサイドバーより、「お問い合わせ」>「コンタクトフォーム」> タイトルを選択 >「メール」のメッセージ本文に、[custom-date]を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2336238/e49391d8-9cc0-4953-83bd-8eef7d85b604.png)

<br>

以上の流れで、（yyyy年mm月dd日 hh:mm）形式の日時を表示することができました！
同一オリジンポリシーは何故必要？

初めまして！！標準体重の65kgを目指して、全力で増量中のそうまです！！(現在 57kg)

今回は、同一オリジンポリシーの必要性について調査した事を纏めています！！

# 同一オリジンポリシーとは？

以下でもチラッと書きましたが、同一オリジンポリシー（Same-Origin Policy）とは、異なるオリジンのリソースにはアクセスできないという、セキュリティ上の制約のことを指します。

https://qiita.com/sato-souma/items/16ccac05ca04b2966050

# 疑問に思った事

何も知らない初心者からすると、同一オリジンポリシー（Same-Origin Policy）がなぜ必要なのか、正直ピンときませんでした。
CORSの設定が必要だったり、認証の仕組みでリクエストを制御できるならそれで十分じゃないの？と思っていたからです。

## CSRFを防ぐため
アクセス可能範囲を制限し、CSRF(クロスサイトリクエストフォージェリ)のような攻撃を防ぐため。

先ほどの記事でも少しだけ書いてたんですが、正直あまり分かってはいませんでした...。
まずは、CSRFとは何かを見ていきます。

### CSRFとは？

#### 攻撃方法

CSRF攻撃では、以下のようなケースが考えられます！

1. ユーザーが銀行サイトにアクセスしてログインする

2. セッション情報が保持されたまま、SNSなどで悪意のあるサイトのリンクをクリックしてしまう

3. 悪意のあるサイトが自動でスクリプトを実行し、ブラウザに保存されたCookieを使って、銀行サイトに送金リクエストを送信する

![頭整理.drawio (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100170/3efbe19b-ad69-47d2-9c9b-25eaf43d8f2a.png)


引用 : https://www.ipa.go.jp/security/vuln/websecurity/csrf.html

#### 攻撃対象

1. 対象の銀行サイトにログイン済みのユーザー（＝有効なセッションを保持している）
1. 銀行サーバーが、同一オリジン以外からのリクエストを制限していない（＝CORSやCSRFトークンの対策が不十分）
1. ブラウザが、SameSite属性などでCookieの送信制限がされていない

## つまり？
同一オリジンポリシーによって、JavaScriptなどを通じて外部のオリジンから自分のオリジンのデータへアクセスすることが制限されるため、悪意あるサイトからのレスポンスの読み取りや、セッション情報の不正取得を防ぐことができる。

これにより、CSRFやXSSといった攻撃への対策の一部として機能する。

## 認証ではダメなのか？
僕は当初、リクエストが通るかどうかの観点だけで物事を見てしまっていて、「同じリクエストを制限する仕組みなら、認証だけでええやん」と思っていました。

しかしそれは大きな間違いでした。…恥ずかしい。

認証は「誰がアクセスしようとしているか」を判断してリクエストを制限する仕組みであり、
一方で同一オリジンポリシーは「どこからアクセスしようとしているか」を確認して制限する仕組みです。
つまり、目的そのものがまったく異なるものでした。

# 纏め

同一オリジンポリシーは**アクセスの場所**を, 認証は**アクセスする人物**を制限する仕組みであり、目的が全く異なるためどちらもよく考えて設定するべきだという事がわかりました！！！
Geminiでいろいろな惑星を描いてもらった。

# 概要

Geminiでいろいろな惑星を描いてもらいました。

# 実装

以下のようなリクエストをしました。

```
美しい惑星を描いてみてください。
```

![美しい惑星_20250328.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/2d58b8f3-a79c-48c0-909b-d05a20689ae2.png)

こんな惑星に住んでみたいです。

```
水が豊かな惑星を描いてみてください。
```

![水が豊かな惑星_20250328.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/7db1f383-6b78-4579-9b66-ae8b266b5ebb.png)

これは地球っぽいですね。

```
炎が燃えている、火の惑星を、描いてみてください。 
```

![炎が燃えている、火の惑星_20250328.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/72772e5f-f9a7-4fd2-9646-0c634fce2f60.png)

こんな惑星あるんだろうか。惑星というか恒星かな。

```
双子（対になっている）になっている惑星を2つ描いてみてください。片方は燃えていて、もう片方は水が豊か。
```

![双子（対になっている）になっている惑星を2つ_20250328.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/be08eb14-cdf6-4821-87a5-bb74c2d1ea03.png)

これはなさそう。

```
2つの惑星に分離してみてください。 
```

![2つの惑星に分離_20250328.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/b801fbc0-ab75-4da1-bc0c-deeb6ae2a990.png)

どっちもいい感じの惑星です。

```
森林で満たされている惑星を1つ描いてみてください。 
```

![森林で満たされている惑星_20250328.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/42d0896d-4664-4f82-9b82-3029711398d3.png)

視点は引けないかな。

```
全体像が見えるように視点を修正してみてください。
```

![全体像が見えるように視点を修正_20250328.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/18abef20-bf50-45f2-b9b3-c48549ba5fc0.png)

ま、こんなもんかな。短く指定するのは難しいかも。コツが必要かも。

# まとめ

何かの役に立てばと。