OmniAICreator/Qiita-1.07M huggingface dataset:
ブラウザ毎に非テキスト入力なinput要素のイベントハンドラの挙動について調べてみた

onBlurでバリデーションの発火させたいときってありますよね？
ブラウザ毎に非テキスト入力なinput要素のイベントハンドラの挙動について調べてみました。
ブラウザ対応で沼の気配を感じて調査したときの記録です。

# 環境
<table>
  <caption>HTMLの要素</caption>
  <thead>
    <tr>
      <th>ブラウザ</th> <th>バーション</th> <th>OS</th>
    </tr>
  </thead>
  <tr>
    <td> Google Chrome </td>
    <td>111.0.5563.147 (Official Build) （64 ビット）</td>
    <td>Windows</td>
  </tr>
  <tr>
    <td> Firefox </td>
    <td>111.0.1</td>
    <td>Windows</td>
  </tr>
  <tr>
    <td> Macintosh Safari </td>
    <td>バージョン16.3 (18614.4.6.1.6)</td>
    <td>MacOS Ventura 13.2.1</td>
  </tr>
  <tr>
    <td> iPadOS Safari </td>
    <td></td>
    <td>iPadOS 16.4 20E246</td>
  </tr>
  <tr>
    <td> Android Chrome </td>
    <td>111.0.5563.116</td>
    <td>Pixel 6a Android 13</td>
  </tr>
</table>

# やりかた
適当なStorybookを作ってそこで実験しました
```tsx
export const Test = () => {
	const onBlurHandler = () => {
		alert('onBlur');
	};

	const onChangeHandler = () => {
		alert('onChange');
	};

	return (
		<>
			<fieldset>
				<label>
					<input
						type="radio"
						name="radio"
						value="foo"
						onBlur={onBlurHandler}
						onChange={onChangeHandler}
					/>
        foo
				</label>
				<br />
				<label>
					<input
						type="radio"
						name="radio"
						value="bar"
						onBlur={onBlurHandler}
						onChange={onChangeHandler}
					/>
        bar
				</label>
				<br />
				<label>
					<input
						type="radio"
						name="radio"
						value="baz"
						onBlur={onBlurHandler}
						onChange={onChangeHandler}
					/>
        baz
				</label>
			</fieldset>
			<label>
				<input
					type="checkbox"
					name="checkbox"
					value="hoge"
					onBlur={onBlurHandler}
					onChange={onChangeHandler}
				/>
        hoge
			</label>
		</>
	);
};

```

# 調査

## Radio
<table>
  <thead>
    <tr>
      <th>ブラウザ名</th> <th>onBlur</th> <th>onChange</th>
    </tr>
  </thead>
  <tr>
    <td>Google Chrome</td> <td>動作する</td> <td>動作する</td>
  </tr>
  <tr>
    <td>Firefox</td> <td>動作する</td> <td>動作する</td>
  </tr>
  <tr>
    <td>Mac safari</td> <td>動作しない</td> <td>動作する</td>
  </tr>
  <tr>
    <td>iPad safari</td> <td>動作しない</td> <td>動作する</td>
  </tr>
  <tr>
    <td>Android Chrome</td> <td>動作する</td> <td>動作する</td>
  </tr>
</table>

## Checkbox
<table>
  <thead>
    <tr>
      <th>ブラウザ名</th> <th>onBlur</th> <th>onChange</th>
    </tr>
  </thead>
  <tr>
    <td>Google Chrome</td> <td>動作する</td> <td>動作する</td>
  </tr>
  <tr>
    <td>Firefox</td> <td>動作する</td> <td>動作する</td>
  </tr>
  <tr>
    <td>Mac safari</td> <td>動作しない</td> <td>動作する</td>
  </tr>
  <tr>
    <td>iPad safari</td> <td>動作しない</td> <td>動作する</td>
  </tr>
  <tr>
    <td>Android Chrome</td> <td>動作する</td> <td>動作する</td>
  </tr>
</table>
2次方程式をとく

すみません。[Youtube動画](https://youtu.be/MgnNTixFwCM)で紹介されているのんの写経です。本家は、winformsもしくはwpfベースで実行してますが、こちらはコンソールです。あと

- 複素解になるときのことは弾いてます。
- 重解考慮してません。

```
int a = int.Parse(Console.ReadLine()!);
int b = int.Parse(Console.ReadLine()!);
int c = int.Parse(Console.ReadLine()!);
double d = System.Math.Sqrt(b*b-4*a*c);
double f=-(Single)b/(2*(Single)a);

        if (b*b-4*a*c < 0) {
        Console.WriteLine("複素になる");
        } else {
            Console.Write((f+(d/2/a)).ToString());
            Console.Write(",");
            Console.WriteLine((f-(d/2/a)).ToString());
        } 
```

実行のさいは、
```
dotnet run
2
-13
15
```
のように、してください。 $ax^2+bx+c=0$で、$(a,b,c)=(2,-13,15)$という対応関係です。
実行するとこたえが `5,1.5` みたいなかんじで出てきます。パチパチ

## 苦労した点

キャストしないとならないところで詰んだ。
`System.Math.Sqrt`と長ったらしいのをなんとかしたい。
`!`をアソコにつけないと、Nullがどうたらこうたら言われる。
Win11:新右クリックを戻す(コマンドで一発設定)

## はじめに
Windows11でどうしても設定しておきたいものについて、コマンドを実行して設定しました。忘れないように備忘録です。

## Win11：新右クリックをWin10時代に戻したい

Windows11 の新しい右クリックメニューですが、とても使いずらいです。以前の右クリックに行くには、「その他のオプションを表示」(Shift+F10)をクリックしないといけないので、とても面倒です。

Windows11の右クリック
![Screenshot_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/721b4cf2-a890-31c1-a3b8-93f135d649c7.png)

##### レジストリに追加を行います（自己責任）

ターミナル(管理者)で、以下を実行。PC再起動で設定が反映します。
~~~ .cmd
　reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve
~~~


**元に戻す場合**
~~~ .cmd
　reg.exe delete "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}" /f
~~~


Windows10で使っていたものに戻りました。
![Screenshot_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/7d7bf626-3869-7294-b983-cfd17fe7beeb.png)

#### 参考URL

https://tanweb.net/2021/11/19/44083/



## フリーソフトも多数あります

Windows11で大きく変わった代表格として、センターアイコンの「タスクバー」がありますが、タスクバーについて、カスタマイズできるフリーソフトが多数あります。その中でも一番いいな、と思ったのが、**Explorer Patcher for Windows 11**。

いろいろな外観をカスタマイズを変更できるのもそうですが、Win11とwin10の設定を混在させることが可能な便利なソフトです。

#### 参考URL

https://tanweb.net/2022/08/31/48754/

https://www.gigafree.net/system/theme/Explorer-Patcher-for-Windows-11.html



# おまけ：MAC

#### どうしてもやりたい設定→ランチパッドに表示するアイコンの数を変更したい

MACのランチパッド(Launchpad)に表示し、右に行ったり、左に行ったり、というのは無駄だなと感じていました。アイコンは少しくらい小さくなってもよいので、1ページにすべて表示できないの？という疑問から変更しました。(列と行の表示数)

![mac_launchpad.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/29d764d5-7556-88e6-3b28-00b79eb2643d.png)

変更するには、ターミナルでコマンドを実行します。

~~~ .cmd
# 列
defaults write com.apple.dock springboard-columns -int 10
~~~

~~~ .cmd
# 行
defaults write com.apple.dock springboard-rows -int 7
~~~

上記の例は、10列7行です。
数字のところを自由に変更して、自分の環境にあったサイズ感を探してみるとよいと思います。

~~~ .cmd
# ランチパッドの並び順をリセットするコマンド 
defaults write com.apple.dock ResetLaunchPad -bool TRUE
~~~

~~~ .cmd
# 再起動
killall Dock
~~~

一度に実行する場合。以下のXX のところを自由に変更。

~~~ .cmd
defaults write com.apple.dock springboard-columns -int XX;defaults write com.apple.dock springboard-rows -int XX;defaults write com.apple.dock ResetLaunchPad -bool TRUE;killall Dock
~~~

### 参考URL

https://blog.skeg.jp/archives/2016/03/launchpad-change.html
SwiftUIでHTMLを表示する方法

# 結論
以下のように実装することでSwiftUIでHTMLのコードを反映させることができます。
```swift
import SwiftUI
import WebKit

struct HTMLView: UIViewRepresentable {
    let htmlString: String
    
    // SwiftUIが初めてビューを作成するときに実行される
    func makeUIView(context: Context) -> WKWebView {
        return WKWebView()
    }
    
    // ビューが変更されたときに実行される
    func updateUIView(_ uiView: WKWebView, context: Context) {
        uiView.loadHTMLString(htmlString, baseURL: nil)
    }
}

struct ContentView: View {
    var body: some View {
        VStack {
            HTMLView(htmlString:
        """
        <html lang="ja">
          <head>
            <style>
              h1 {
                color: red;
                font-weight: bold;
                font-size: 60px;
              }

              p {
                font-size: 40px;
              }
            </style>
          </head>
          <body>
            <h1>Hello SwiftUI!!</h1>
            <p>SwiftUI勉強中</p>
          </body>
        </html>
        """)
        }
        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

```
# 解説
## UIViewRepresentableとは？
SwiftUIからUIKitのビューやコントローラを扱うためのインターフェースです。
UIKitはiOSアプリケーションの中核となるフレームワークで、このフレームワークはHTMLを描画する機能がサポートされています。
SwiftUIは新しい別のフレームワークですが、HTMLを描画する機能をサポートしておりません。
SwiftUIからUIKitの機能を利用するためにUIViewRepresentableがインターフェースとしてSwiftUIに用意してあります。
今回のケースではSwiftUIからUIViewRepresentableを通してUIKitを利用し、HTMLを描画しております。
## makeUIViewとは?
UIViewRepresentableの仕様でSwiftUIが初めてビューを作成するときに実行される処理を書くことができる関数です。

## updateUIViewとは?
UIViewRepresentableの仕様でビューが変更されたときに実行される処理を書くことができる関数です。

## WKWebViewとは?
Webページを表示するためのクラスです。
今回はビュー作成時(makeUIView実行時)にインスタンス作成を行い、その後に実行されるupdateUIView関数内でHTMLの読み込みを行っています。

## 終わりに
学習を始めたばかりで、間違った理解をしているところがあるかもしれませんが、コメントから指摘いただけると幸いです。
ここまで読んでいただきありがとうございました。
MongoDBの実行計画について勉強してみた

## はじめに
- 業務でMongoDBを触る機会が増えてきて、実行計画の見方を学びたいと思い記事にしました。
- MongoDBのバージョンは5.0.15です。
## 実行計画とは
- dbのクエリをどう処理するかについての計画です。db内部でいくつかの計画を比較し1つを実行してくれます。新しく追加したインデックスが使用されているか確認できたりします。
## 確認方法
- 実行したいクエリにexplain()をつけると確認できます。
- 引数に"executionStats"を指定すると実行された計画の詳細を確認できます。

例えば
```
db.getCollection("user").find({"age": 20})
```
というクエリの実行計画を見るには
```
db.getCollection("user").find({"age": 20}).explain()
```
というふうにします。
詳細に見るには
```
db.getCollection("user").find({"age": 20}).explain("executionStats")
```
というふうにします。


- 今回サンプルで
```
{
    "_id" : ObjectId("641fc8ef5fbb0c5ad9193af9"),
    "name" : "名前",
    "age" : NumberInt(20),
    "region" : "山梨県"
}
```
こういったドキュメントを500個持つコレクションを作成しました(name,age,regionはランダムです)。

- 実際に実行計画を確認したいと思います。

```
db.getCollection("user").find({"age": 20}).explain("executionStats")
```
以下のようになものが表示されます。

```
{
    "explainVersion" : "1",
    "queryPlanner" : {
        "namespace" : "sample.user",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "age" : {
                "$eq" : 20.0
            }
        },
        "maxIndexedOrSolutionsReached" : false,
        "maxIndexedAndSolutionsReached" : false,
        "maxScansToExplodeReached" : false,
        "winningPlan" : {
            "stage" : "COLLSCAN",
            "filter" : {
                "age" : {
                    "$eq" : 20.0
                }
            },
            "direction" : "forward"
        },
        "rejectedPlans" : [

        ]
    },
    "executionStats" : {
        "executionSuccess" : true, 
        "nReturned" : 12.0,
        "executionTimeMillis" : 1.0,
        "totalKeysExamined" : 0.0,
        "totalDocsExamined" : 500.0,
        "executionStages" : {
            "stage" : "COLLSCAN",
            "filter" : {
                "age" : {
                    "$eq" : 20.0
                }
            },
            "nReturned" : 12.0,
            "executionTimeMillisEstimate" : 0.0,
            "works" : 502.0,
            "advanced" : 12.0,
            "needTime" : 489.0,
            "needYield" : 0.0,
            "saveState" : 0.0,
            "restoreState" : 0.0,
            "isEOF" : 1.0,
            "direction" : "forward",
            "docsExamined" : 500.0
        }
    },
//省略
```

- 実行計画は"queryPlanner"で確認できます。
- "winningPlan"に実行された計画が表示されます。
- "rejectPlan"では候補に上がって実行されなかった計画が表示されます。
- "winingPlan.stage"ではコレクションをどのように検索したかが表示されます。
- "stage"が``COLLSCAN``の場合コレクション内を全てスキャンしていて、``IXSCAN``の場合インデックスを使用してスキャンしています。今回インデックスを追加していないので``COLLSCAN``になっています。
- 次に実行された計画の詳細を"executionStats"で確認します。
- "executionSuccess"で成功したか、"nReturned"で返すドキュメント数、"executionTimeMillis"でかかった時間が確認できます。
- "totalKeysExamined"で走査したインデックス数が確認できます。今回インデックスが使われていないので0です。
- "totalDocsExamined"で走査したドキュメント数が確認できます。インデックスが使われていないので全件走査しています。

## 最後に
- 今回実行計画に見方について理解が深まったので、今後インデックスを追加する時に活かしていきたいです。

## 参考
https://tech.kitchhike.com/entry/2018/05/31/163715
https://qiita.com/koshilife/items/79a8d59fa0973c16de57
vscodeでスタッシュ(備忘録)

## はじめに
スタッシュはとても便利です。
ただ、コマンド操作は苦手なのでGUIで操作を行っています。
vscode初心者なので備忘録として残します。
(intelliJが好き)

##　操作方法
①ソース管理
↓
②3点リーダー
↓
③スタッシュ
↓
④スタッシュ(未追跡ファイルを含む)
こちらで新規追加ファイルもスタッシュ出来ます！

⑤スタッシュをポップする...
こちらでスタッシュしたものを適用出来ます！
スタッシュしたものの一覧が出てきますので、そちらから対象のスタッシュを選びます。
※ ポップしたものは削除される点にご注意ください。

⑥スタッシュを削除する...
不要になったスタッシュを削除できます。
スタッシュしたものの一覧が出てきますので、そちらから対象のスタッシュを選びます。

他のスタッシュ操作は使った事がありません・・・🙇‍♂️

![スクリーンショット 2023-03-31 12.08.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1030700/b02347ce-1401-6f1d-a75f-26fe73b91c47.png)
ChatGPT を使って、Rust言語を勉強します。クロージャ 篇

#### 質問1: Rust言語のクロージャを教えてください。

#### 回答1:

---
Rust言語のクロージャとは、関数のように扱えるオブジェクトであり、関数と同様にパラメータを受け取り、値を返すことができます。しかし、クロージャは、定義されたスコープ内の変数をキャプチャして、その変数を使用して計算することができます。

Rust言語のクロージャは、次のように定義することができます。

```rust
let add = |x, y| x + y;
```

この例では、add というクロージャを定義しています。クロージャは、| で始まり、| で終わります。|x, y| は、クロージャが受け取る引数を定義しています。この例では、2つの引数 x と y を受け取ります。x + y は、クロージャが返す値を定義しています。

クロージャを実行するには、関数と同様に、以下のように呼び出します。

```rust
let result = add(3, 4);
println!("The result is {}", result); // The result is 7
```

この例では、add クロージャに引数 3 と 4 を渡し、7 という結果を得ています。

クロージャは、定義されたスコープ内の変数をキャプチャできます。キャプチャされた変数は、クロージャ内で使用することができます。

```rust
let x = 10;
let add_x = |y| x + y;
let result = add_x(5);
println!("The result is {}", result); // The result is 15
```

この例では、x という変数を定義しています。その後、add_x というクロージャを定義し、x をキャプチャしています。add_x は、引数 y を受け取り、x と y の和を返します。result には、add_x クロージャに引数 5 を渡した結果が格納されます。result の値は、15 となります。

---

#### 質問2: Rust言語のクロージャの使い方を教えてください。

#### 回答2:

---
Rust言語におけるクロージャは、関数を定義するための一種の構文であり、変数のスコープをキャプチャし、後で実行するための関数のようなものです。

以下は、Rust言語でクロージャを定義し、実行する例です。

```rust
fn main() {
    let add = |x, y| x + y;
    let result = add(3, 5);
    println!("{}", result);
}
```

この例では、addという名前のクロージャが定義されています。|x, y| x + yの部分がクロージャの本体であり、2つの引数xとyを受け取り、それらを加算した結果を返します。次に、addが呼び出され、引数として3と5が渡されます。最後に、println!マクロを使って、計算結果である8が出力されます。

また、クロージャは変数のスコープをキャプチャすることができます。以下は、クロージャが外部の変数をキャプチャする例です。

```rust
fn main() {
    let mut x = 5;
    {
        let add = || x += 1;
        add();
    }
    println!("{}", x);
}
```

この例では、addという名前のクロージャが定義されています。本体は、x += 1であり、xの値を1増やすことを意味します。次に、addが呼び出され、xの値が1増やされます。最後に、println!マクロを使って、変数xの値が出力されます。結果は6になります。

この例では、addクロージャが外部の変数xをキャプチャしています。このように、クロージャは外部のスコープの変数をキャプチャすることができます。

---

#### 質問3: Rust言語のプリミティブ型を教えてください。

#### 回答3:

---
以下は、Rust言語のクロージャを使った簡単な例です。この例は、与えられたベクターの値を2倍にして新しいベクターを作成するものです。

```rust
fn main() {
    let original_vector = vec![1, 2, 3, 4, 5];
    
    let new_vector: Vec<i32> = original_vector
        .iter()
        .map(|x| x * 2)  // クロージャを使って要素を2倍にする
        .collect();  // 新しいベクターを作成する
    
    println!("Original vector: {:?}", original_vector);
    println!("New vector: {:?}", new_vector);
}
```
この例では、.map()メソッド内でクロージャを定義して、各要素を2倍にしています。このクロージャは、短いラムダ式|x| x * 2で表されています。.collect()メソッドは、イテレータから新しいベクターを作成します。最後に、元のベクターと新しいベクターを印刷しています。

---
リーダブルコード読書エントリ[Part2]

前回に続きPart2です！
全4部のうちの第2部を紹介します。
[前回](https://qiita.com/kitokun/items/f1497f540a5e327c7d6f)は、コメントや変数名などプログラムの動作自体には影響がない工夫について紹介しました。2部以降では、もう少し突っ込んで、プログラムの動作に影響する（結果には影響がない）工夫について紹介しています。
今回も、すべては紹介せず、自分自身参考になったと感じる部分をかいつまんで書いていこうと思います。

## if/elseのブロック順
以下のようなコードがあったとます。
```
// 複数のリクエストを処理
for(i = 0;i < req.length();i++) {
    if(!req[i].isJapanese){
        // 日本語でないならば
        const string lang = judgeLang(req[i].content); //　言語を特定
        res[i] = translate("こんにちは！", lang);       //　翻訳
    } else {
        // 日本語ならば
        res[i] = "こんにちは！";
    }
}
return res;
```
このコードは、複数のリクエストをfor文で展開し、各リクエストに対応した言語のレスポンスを配列に詰めて返すコードです。
まず、条件文の否定形はわかりにくさを産む要因になります。
また、条件文で「日本語」という単語を出しているのに、「日本語」に関する処理がelseまで進まないありません。これもわかりにくいです（例えば、旅館に「もし虫が入ってきたら、フロントに連絡してください。駆除いたします。」と張り紙があると、虫がいなくても気になって寝られなくなるみたいな話）。
これらのことを考えると、示したコードは以下のように書き直すと読みやすくなるはずです。
```
// 複数のリクエストを処理
for(i = 0;i < req.length();i++) {
    if(req[i].isJapanese){
        // 日本語ならば
        res[i] = "こんにちは！";
    } else {
        // 日本語でないならば
        const string lang = judgeLang(req[i].content); //　言語を特定
        res[i] = translate("こんにちは！", lang);       //　翻訳
    }
}
return res;
```

## 巨大な式の分割
以下のようなコードを考えます。
```
if(isToday(toDate(latestResponseTime()))){
    //　何らかの処理
}
```
`isToday()`は「与えられた日付が今日であるかを返す」関数で、`toDate()`は「与えられた日時を日付に変換する」関数で、`latestResponseTime()`は「最後にあったレスポンスの日時を返す」関数です。
条件は「最後に返したレスポンスが今日であったか？」というだけのことなのですが、関数が入れ子になっていてわかりにくいです。
このように、処理が一行にまとまっている場合は、一度ほかの変数に代入するとわかりやすくなることがあります。
例えば、`toDate()`の返り値を`latestResponseDate`に格納すると、先のコードは以下のようになります。
```
const date = toDate(latestResponseTime());
if (isToday(latestResponseDate)){
    // 何らかの処理
}
```
どうでしょうか。最初に示したコードよりはすっきりしていると思います。
# Part2　まとめと感想
以上でPart2は終了です！
Part1は「当たり前だろ！」と感じることが多かったですが、今回は「言われてみれば、確かに…」と感じました。特に、一旦他の変数に代入する方法は、意識的にはできていなかったので勉強になりました。

次回のPart3は、いつになるかわかりませんが、いずれ書けたらなと思っています！
ChatGPTでプログラミングするためのプロンプト(要件定義〜コーディングまで)

## プロンプトの内容
コーディングをChatGPTに行わせている人は多いと思いますが、いちいちプロンプトを考えるのは面倒ですよね？
下記のプロンプトを使えば、会話しながら要件定義を固めて、コーディングすることが可能です！
必要に応じて最初の2行を変更してください。
(下記はPythonとFlaskを使ってバックエンドのコーディングを行う例)

改善点あれば教えてください。


## 英語でのプロンプト(こちらの方がおすすめ)
```
You are a back-end developer.
The technology stack you have is Python, Flask

Your ultimate goal is to create source code for an application that meets my requirements.

Please follow the process below to create the source code.

Step 1 : Review the requirements for your application
	a) Show current requirements
		Please itemize the requirements for your application as you understand them.
	b) Question and Improve
		Ask me questions to refine or improve the application requirements.
		I will either respond to them or communicate further requests to you, and you may modify your requirements accordingly.
	c) Repeat
		Repeat steps a) and b) until I say OK.
		If I say OK, please proceed to Step 2.

Step 2 : Coding
	a) Show current requirements and code
		Show me the requirements as you understand them and the code you have created.
	b) Improve the code
		Please improve the code as I will give you modification instructions for it.
		If you need to modify the requirement, please modify the requirement.
	c) Iteration
		Repeat steps a) and b) until I say OK.
		If I say OK, please show me all the requirements and code and exit the process.
		If I say, "Please go back to the requirements definition," then go back to step 1.
```


## 日本語でのプロンプト
```
あなたはバックエンド開発者です。
あなたが持っている技術スタックは、Python、Flaskです。

あなたの最終目標は、私の要求を満たすアプリケーションのソースコードを作成することです。

以下のプロセスに従ってソースコードを作成してください。

ステップ1：アプリケーションの要件を確認する
	a) 現在の要求事項を表示する
		アプリケーションの要件を理解した上で、箇条書きにしてください。
	b) 質問と改善
		応募要件を洗練させたり改善するために、私に質問してください。
		私はそれらに答えるか、さらなる要望を伝え、お客様はそれに応じて要件を修正することができます。
	c) 繰り返し
		私が「OK」と言うまで、ステップa)とb)を繰り返してください。
		私がOKを出したら、ステップ2へお進みください。

ステップ2：コード化
	a) 現在の要件とコードを表示する
		あなたが理解した要件と、あなたが作成したコードを示してください。
	b) コードを改善する
		コードの修正指示を出しますので、改善をお願いします。
		また、要件の修正が必要な場合は、要件の修正をお願いします。
	c) イテレーション
		私がOKを出すまで、ステップa)とb)を繰り返してください。
		私が「OK」と言ったら、すべての要件とコードを見せて、処理を終了してください。
		私が「要件定義に戻ってください」と言ったら、ステップ1へ戻ってください。
```
PythonでExcelファイルのパスワードを解除

# 概要
パスワード付きのExcelファイルをパスワードなしに保存するコードのメモです。
勿論パスワードを知っている前提の話です。
PHP言語でパスワード付きのExcelファイルを読み込みができないため、
アップロードされたExcelファイルをサーバ上でPython処理でパスワードを解除して
保存する処理です。

# Python環境
下記の環境で試したコードになります。

OS : redhat 8.5
Python : python3.X
Library : msoffcrypto-tool

# 事前インストール
次の順番でパッケージをインストールします。
①sudo yum install python2
②sudo yum install python3
③sudo python3 -m pip install --upgrade pip
→④番のインストールため、事前にpipのバージョンアップが必要でした。
④pip3 install msoffcrypto-tool

# Pythonコード
次のコードを書いてcrack.pyに保存します。

~~~python
import os
import msoffcrypto

def xl_pw_decript(raw_path, new_path):

    xlfile_list = os.listdir(raw_path)
    print(xlfile_list)

    for xlfile in xlfile_list:
        encrypted = open(raw_path + xlfile, 'rb')
        file = msoffcrypto.OfficeFile(encrypted)
        file.load_key(password='Passw0rd')

        with open(new_path + xlfile, 'wb') as f:
            file.decrypt(f)
            print("unlock file make")

        encrypted.close()

raw_path = "./excel/"
new_path = "./test/"
xl_pw_decript(raw_path, new_path)
~~~

# パスワード付きのExcelを作成
下記のサイト参照してパスワードを設定します。
https://www.passfab.jp/excel/removal-and-setting-of-excel-password.html

# Pythonコード実行結果
次のコマンドで作成したコードを実行します。
警告のようなメッセージは表示されますが、動作は問題なくパスワードなしのファイルが作成できました。

~~~python
[redhat@localhost ~]$ python3
Python 3.6.8 (default, Sep  9 2021, 07:49:02)
[GCC 8.5.0 20210514 (Red Hat 8.5.0-3)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()

[redhat@localhost ~]$ python3 crack.py
['task_password.xlsx']
/usr/local/lib/python3.6/site-packages/msoffcrypto/method/ecma376_agile.py:8: CryptographyDeprecationWarning: Python 3.6 is no longer supported by the Python core team. Therefore, support for it is deprecated in cryptography. The next release of cryptography will remove support for Python 3.6.
  from cryptography.hazmat.backends import default_backend
unlock file make
[redhat@localhost ~]$ ls test/
task_password.xlsx
~~~

# 終わりに
PHPでパスワード付きのExcelファイルの取り込みができないので、
今回のようにアップロードされたExcelファイルをサーバ側でパスワード解除版を保存してから
データ処理するのも良いと思いまして作成してみました。
Pythonでパスワードを指定してExcelファイル保存もできると良いですね。
[AWS Q&A 365][API Gateway]AWSのよくある問題の毎日5選 #19

# 1. Amazon API GatewayにおけるHTTP APIとは何ですか？
答え：HTTP APIとは、クライアントがHTTPまたはHTTPSを介してバックエンドのHTTPエンドポイントを呼び出すことができるAPI Gatewayの一種です。数万件のリクエストを処理できるAPIを簡単かつコスト効果的に構築することができます。

# 2. Amazon API GatewayでHTTP APIを作成するにはどうすればよいですか？
答え：Amazon API GatewayでHTTP APIを作成するには、API Gatewayコンソール、AWS CLI、またはAWS SDKを使用することができます。OpenAPI 3.0を使用してAPIを定義することもできますし、API Gatewayコンソールを使用してスクラッチから作成することもできます。

# 3. Amazon API GatewayにおけるHTTP APIの機能には何がありますか？
答え：Amazon API GatewayにおけるHTTP APIの機能には、ルート管理、CORSサポート、JWT認証、パラメータマッピング、リクエスト検証、データ変換、バイナリメディアタイプ、カスタムドメイン名などがあります。

# 4. Amazon API GatewayにおけるHTTP APIのセキュリティをどのように確保できますか？
答え：Amazon API GatewayにおけるHTTP APIのセキュリティを確保するには、JWT認証、AWS Identity and Access Management（IAM）ポリシー、およびAWS WAFを使用することができます。また、相互TLS認証を有効にして、クライアントとAPI Gateway間のトラフィックを暗号化することもできます。

# 5. Amazon API GatewayでHTTP APIをモニタリングおよびトラブルシューティングするにはどうすればよいですか？
答え：Amazon API Gatewayには、CloudWatchメトリクスとログ、AWS X-Rayトレース、Kinesis Data Firehoseなど、HTTP APIをモニタリングおよびトラブルシューティングするための複数のツールが用意されています。また、API Gatewayコンソールを使用して、APIのルートやインテグレーションを表示およびテストすることもできます。
[AWS Q&A 365][API Gateway]Daily Five Common Questions #19

# 1. What is an HTTP API in Amazon API Gateway? 
Answer: An HTTP API is a type of API Gateway that allows clients to invoke backend HTTP endpoints over HTTP or HTTPS. It provides a simple and cost-effective way to build APIs that can handle tens of thousands of requests per second. 

# 2. How do I create an HTTP API in Amazon API Gateway? 
Answer: To create an HTTP API in Amazon API Gateway, you can use the API Gateway console, AWS CLI, or AWS SDKs. You can define your API using OpenAPI 3.0 or create it from scratch using the API Gateway console. 

# 3. What are the features of HTTP APIs in Amazon API Gateway? 
Answer: Some of the features of HTTP APIs in Amazon API Gateway include route management, CORS support, JWT authorizers, parameter mapping, request validation, data transformations, binary media types, and custom domain names. 

# 4. How do I secure my HTTP API in Amazon API Gateway? 
Answer: You can secure your HTTP API in Amazon API Gateway using JWT authorizers, AWS Identity and Access Management (IAM) policies, and AWS WAF. You can also enable mutual TLS authentication to encrypt traffic between the client and API Gateway. 

# 5. How do I monitor and troubleshoot my HTTP API in Amazon API Gateway? 
Answer: Amazon API Gateway provides several tools for monitoring and troubleshooting your HTTP API, including CloudWatch metrics and logs, AWS X-Ray tracing, and Kinesis Data Firehose. You can also use the API Gateway console to view and test your API's routes and integrations.
AWSのマルチアカウント構成について

# はじめに
- AWSが推奨しているマルチアカウント構成について改めて記事にしてみました

# マルチアカウント構成とは
AWSが推奨しているアカウント構成になります
※[アカウントとユーザーについての違いはこちら](https://zenn.dev/yutakawanaga/articles/c11516a399678f)

例としてWebアプリケーションをdev・stg・prod環境と分けて構築するケースで考えます

## シングルアカウント構成の場合
- アカウントは一つ
- ユーザーが利用するマネージメントコンソールのURLも一つ
- 各AWSリソースに対してタグや名前で区別する

### メリット
- AWSサポートに加入する場合1アカウントで全てのリソースに対する具体的な質問ができる

### デメリット
- 命名やタグ付けでの区別なのでミスが発生する可能性がある
	- devを止めようとしたらprodを止めてしまったなど
- 請求が一つになるため、どの環境でいくらぐらい利用しているかの内訳が分かりにくい
	- 企業によってはまとめることがメリットの場合もありますが。。
	- `AWS Control Tower`を利用すれば、請求をまとめつつマルチアカウント構成にできます

### イメージ
```mermaid
classDiagram
    class EC2:::styleClass {
        dev-instance
        stg-instance
	prod-instance
    }

    class S3:::styleClass {
        dev-bucket
        stg-bucket
	prod-bucket
    }

    class VPC:::styleClass {
        dev-vpc
        stg-vpc
	prod-vpc
    }

    class IAM:::styleClass {
        userA
        userB
	userC
    }
```

## マルチアカウント構成の場合
- アカウントを環境ごとに作る
- ユーザーが利用するマネージメントコンソールのURLが環境ごとに分かれる

### メリット
- アカウントが環境ごとに分かれるためシングルアカウント構成に比べて事故が起きにくい
- リソースを作って試したい場合にdev環境を利用するなど、用途ごとに使い分けができる
- アカウント毎に請求が来る

### デメリット
- アカウント毎にAWSサポートに加入する必要がある
- 環境ごとにマネージメントコンソールのURLが異なるため切り替えが多少煩雑

### イメージ
```mermaid
classDiagram
    class EC2:::styleClass {
        dev-instance
    }

    class S3:::styleClass {
        dev-bucket
    }

    class VPC:::styleClass {
        dev-vpc
    }

    class IAM:::styleClass {
        userA
        userB
	userC
    }
```

```mermaid
classDiagram
    class EC2:::styleClass {
        stg-instance
    }

    class S3:::styleClass {
        stg-bucket
    }

    class VPC:::styleClass {
        stg-vpc
    }

    class IAM:::styleClass {
        userA
        userB
	userC
    }
```

```mermaid
classDiagram
    class EC2:::styleClass {
        prod-instance
    }

    class S3:::styleClass {
        prod-bucket
    }

    class VPC:::styleClass {
        prod-vpc
    }

    class IAM:::styleClass {
        userA
        userB
	userC
    }
```

# まとめ
ざっくりではありますが、マルチアカウント構成について書いてみました。誰かの参考になれば幸いです🙏

> 環境ごとにマネージメントコンソールのURLが異なるため切り替えが多少煩雑

こちらについても`IAM Identity Center(旧SSO)`と`AWS Organizations`を設定すれば解決することができます。
また、上記2つを内包した`AWS Control Tower`を使うのが個人的には一番早い&楽だと思うのでそちらについても記事にしたいと思います。
Swift 5 で画面遷移時にフルスクリーンモードのモーダルのタッチアクションに処理を渡す

## はじめに
普段は Laravel や Nuxt を使って Web アプリケーションを開発しているのですが、年に数回 iOS アプリに改修が入ることがあります。
Swift を触っていない期間が空いていて、これどうするんだっけ？という事が多いので、メモ代わりに投稿します。

## 概要
リーダー画面(ReaderPage)でQRコードを読み込んだら、同意画面(AgreementPage)をモーダルのフルスクリーンモードで表示し、同意ボタンを押下すると、モーダルを閉じて「同意済み」と表示する機能を実装します。

同意ボタンを押下すると `dismiss()` でモーダルを閉じるため、その前に同意済みフラグを立てる方法を2つ紹介します。
また、本アプリケーションでは画面遷移に `performSegue()` を使用しています。

## 環境
- Apple M1 Max
- macOS Monterey (v12.6)
- Xcode 13.2.1
- Swift 5
- iPadOS 16.3.1 

## コールバック関数を渡して実行する
一つ目はコールバック関数を渡して実行する方法を紹介します。

まずは `AgreementPageViewController` にコールバックを格納する変数を定義して、設定されていれば実行されるようにします。
```swift:AgreementPageViewController.swift
class AgreementPageViewController: UIViewController {
    public var agreeCallback: (() -> Void)?

    private func agree() {
        self.agreeCallback?()
        
        self.dismiss(animated: true)
    }
}
```

画面遷移する前に `prepare` という関数が発火されるのですが、この関数の引数の `segue.destination` に `AgreementPageViewController` が格納されています。
この `AgreementPageViewController` にコールバック関数を設定することで実現できます。

```swift:ReaderPageViewController.swift
class ReaderPageViewController: UIViewController {
    private var isAgreed: Bool = false

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        super.prepare(for: segue, sender: sender)

        if segue.identifier == "AgreementPage" {
            let vc = segue.destination as! AgreementPageViewController
            vc.agreeCallback = {
                self.isAgreed = true
            })
        }
    }
}
```

## Delegate を設定して実行する
二つ目はデリゲートを設定して実行する方法を紹介します。

まずは、コールバック関数と同じように `AgreementPageViewController` にデリゲートを格納する変数を定義して、設定されていれば実行されるようにします。
さらに `protocol` で専用のデリゲートを定義します。

```swift:AgreementPageViewController.swift
class AgreementPageViewController: UIViewController {
    private var delegate: AgreementPageViewControllerDelegate?

    private func agree() {
        self.delegate?.agree()
        
        self.dismiss(animated: true)
    }

    public func setAgreementPageViewControllerDelegate(_ delegate: AgreementPageViewControllerDelegate) {
        self.delegate = delegate
    }
}

protocol AgreementPageViewControllerDelegate: NSObjectProtocol {
    func agree()
}
```

`ReaderPageViewController` に上記で定義したデリゲートを継承して、関数に処理を書きます。
そして `prepare` 関数内で `AgreementPageViewController` の `delegate` に、 `ReaderPageViewController` を設定することで、同意ボタン押下時に任意の処理を実行することができるようになります。

```swift:ReaderPageViewController.swift
class ReaderPageViewController: UIViewController {
    private var isAgreed: Bool = false

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        super.prepare(for: segue, sender: sender)

        if segue.identifier == "AgreementPage" {
            let vc = segue.destination as! AgreementPageViewController
            vc.setAgreementPageViewControllerDelegate(self)
        }
    }
}

extension ReaderPageViewController: AgreementPageViewControllerDelegate {
    func agree() {
        self.isAgreed = true
    }
}
```

## おわりに
画面遷移や画面を跨いだデータのやり取りで Delegate ってどう使うんだっけ？となったので、記事にまとめました！
まだデリゲートパターンを理解して切れていないところがあるので、間違った使い方をしていた場合は、ご指摘頂けると助かります！
多数のAWSアカウントからセキュリティ上の問題を集権的に検知する仕組み

# 200以上あるアカウントのセキュリティに関する運用状況を可視化したい

200以上のアカウントを運用している仕事をしていますが、以下のような問題に直面していました。  
どのアカウントにも同じようなリソースを立てていますが、運用していくうちに個別の設定が入ってしまうことが多々あります。  
中にはセキュリティ的に問題のある設定だったり・・・・・・  

## リソースの設定状況が把握しきれない

標準的な設定をしていますが、実際にはヒューマンエラーで入っていなかったり変わってしまっていたりします。  
セキュリティ的に問題のある設定が入っている、あるいは必要な設定が入っていないことをアカウント横断で監視する仕組みを必要としていました。

## セキュリティに関するイベント発生を把握したい

rootユーザーでのログインや、セキュリティグループに対する変更について、発生したことをアカウント横断で検知する仕組みを作って、野放しにしないようにしたいです。

# 実現方法
## EventBridge、ConfigルールをStacksetsで配る

[前回の記事](https://qiita.com/RelaxRestRetire/items/e0bcb44b83334807898e)でご紹介したConfigルールや、イベント検知用のEventBridgeを各アカウントにStacksetsで配ります。  
これでリソース設定のルール違反やセキュリティに関するイベントを検知できます。

## クロスアカウントでEventBridgeを起動して単一のSNSトピックで通知する

検知はすべてのアカウントで個別に行いますが、SNSトピックは単一のアカウントで実行します。(親アカウントと呼んでいます)  
SNSトピックを個別に作らない理由は「サブスクリプションの確認が1回で済む」、「SNSトピックの料金を一つのアカウントに寄せたかった」です。

下記の図のように子アカウントのConfigルールの違反検知で子アカウント(前述Stacksetsの対象)でEventBridgeが起動します。  
子アカウントのEventBridgeはイベントを親アカウントのEventバスに送信して、親アカウントのEventBridgeがSNSトピックを実行します。

![cross-account-notification-architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3295002/aca207c6-be64-d4f9-8f96-70cd5b545e82.png)


## 用途によって通知先を分けておく

通知は人間が見て対応することを想定しているので、レベル感によって通知先を分けます。  
以下のような分類にして、今すぐ対応が必要なものがすぐ見分けられるようにします。

* 今すぐ対応が必要なセキュリティ上の危機 ex. SSHポートがインターネット開放されている
* 正規の変更か確認したい ex. セキュリティグループのルール変更があった
* 標準の設定から外れている ex. ELBアクセスログが標準通りに設定されていない

# できたこと

## 以下のようなセキュリティ上の問題を200以上のアカウントから即通知

* rootユーザーでログイン
* rootユーザーのMFAが無効の場合
* VPCフローログが無効になっている
* ELBアクセスログが標準通りの設定でない
* ELBがTLS1.2未満のアクセスを許可している
* セキュリティグループルールに変更があった
* SSHなど特定のポートが0.0.0.0/0に対して開放されている
不要ブランチを削除したい！

## はじめに

ローカルブランチやリモートブランチで、使わないのに残り続けている不要なブランチはありませんか？
不要なブランチを削除しておくと、以下のようなメリットがあります。

- メモリの節約
- ブランチ一覧がスッキリする（`git branch` や GitHubでのブランチ選択）
- 候補数が減り、自動補完が効きやすくなる

今回、自分が使えそうだと思ったブランチ削除のやり方を、ローカルブランチ・リモート追跡ブランチ・リモートブランチに分けて紹介していきたいと思います。

## ローカルブランチ

開発を始める際には、まずリモートの更新内容をローカルにプルしてから、開発用にブランチを切って作業を進めていきます。なので、リリースが完了した時や、開発したコードを一通りリモートにプッシュしてが一区切りした時のようなタイミングで、 `master`ブランチ以外の全てのブランチを削除してしまうのが一番簡単だと思います。

デフォルトブランチにチェックアウトしてから下記のコマンドを実行することで、デフォルトブランチ以外のブランチを全て削除できます。

```bash
git branch | grep -Ev "master|main" | xargs git branch -D
```

上記のコマンドは、デフォルトブランチが `master`, `main` どちらの場合でも処理できる書き方になっていますが、デフォルトブランチ名が分かっている場合は、より簡潔に書くことができます。

例えば、デフォルトブランチが `master` である場合は、下記のようになります。

```bash
git branch | grep -v master | xargs git branch -D
```

## リモート追跡ブランチ

下記のコマンドを実行すると、追跡するブランチが存在しなくなったリモート追跡ブランチが全て削除されます。

```bash
git fetch -p
```

## リモートブランチ

 リモートブランチについては、自分が作成したブランチの中で不要なブランチを削除します。リモートブランチはGitHubで確認することができます。GitHubのブランチ一覧ページにある、 Your branches で自分が作成したブランチを確認できます（下図参照）。マージ済みのラベルもあるので、それも確認しつつ不要なブランチを削除していきましょう。他の人が作ったブランチを勝手に削除しないように注意しましょう。

![ブランチ一覧.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120699/98f767a6-2931-1dcb-480d-2ac5dc3ef28a.png)



## 終わりに

以上、不要ブランチを削除する方法を紹介しました。

個人的には、不要ブランチを削除して自動補完が効きやすくなったのが一番良かったです。

Git運用の仕方によって、ブランチ削除の基準も変わってくるので、あくまで一例として参考にしていただけたらと思います。

## 参考記事

[master 以外のブランチを一括削除するコマンド](https://qiita.com/takat0-h0rikosh1/items/766e207ba1c799ed1375)
なるほどわからんDDD ~ドメインモデル貧血症~


## はじめに

本記事は、『ドメイン駆動設計(DDD)』について少し勉強し始めた筆者が学ぶ中で「わからん！」→「なるほど！」と思ったことを書いたものです。

間違っていたらそっと教えていただけると幸いです。

## ドメインモデルが貧血？

ドメインモデル貧血症とは、ドメインモデルがgetter・setterしか持っておらず、まったくビジネスロジックを持っていない状態になっていることを指します。この状態になっているドメインモデルは、外から使われる場合にその使い方を制限できず、ドメインのルールを守る実装はそのドメインモデルを使う人任せになります。

例えば、以下のルールがあるTODOリストアプリを考えます。

- 期限が3日前のToDoはリストの最上段に表示する
- 同じ内容のToDoは登録できない
- ToDoの内容は100字以内
- DBにデータは保存する

そして、以下のようなToDoItemモデルを用意したとします。

```c#
// ToDoリストに登録するToDoを表すクラス
public class ToDoItem
{
    // ToDoのID
    public string Id {get; set;}
    
    // ToDoの内容
    public string Content {get; set;}
    
    // ToDoのチェック状態
    public string IsChecked {get; set;}

    // ToDoの期限
    public DateTime DeadLine {get; set;}

    // ...

    // ToDoの期限をチェックするメソッド
    public bool CheckToDoDeadLine(){ // 期限が近いやつはtrueが返る}

    // ToDoの内容の重複を検証するメソッド
    public bool ValidateToDo(){// 他のToDoと内容を比較して被ってたらfalseが返る}

    // ToDoの内容が100字を超えないようにするメソッド
    public bool CheckContentLength(){ // 100字を超えていたらfalseを返す}

    // ToDoを保存するメソッド
    public void SaveToDo(){// DBにアクセスしたりするごちゃごちゃした処理が書いてある}
}

```
上記のドメインモデルはいまいちです。ToDoを表すクラスなのに、色々なことをやっています。
ということで、リファクタリングをしていきます。


わたし「他のToDoも確認するなら、ValidateToDoメソッドはこのモデルにあるべきじゃないね」
わたし「SaveToDoメソッドも、このモデルがDBにアクセスするのは責務的に変だね。DBに関する処理は別クラスにして……」
わたし「ToDoの内容の文字数チェックも、別にモデルになくてもいいんじゃない？　これもサービスに……」
わたし「期限のチェックも別にここじゃなくていいかも……これもサービスに……」

...

こうしてできあがったドメインモデルは以下。

```c#
// ToDoリストに登録するToDoを表すクラス
public class ToDoItem
{
    // ToDoのID
    public string Id {get; set;}
    
    // ToDoの内容
    public string Content {get; set;}
    
    // ToDoのチェック状態
    public string IsChecked {get; set;}

    // ToDoの期限
    public DateTime DeadLine {get; set;}

    // ...
}

```

振る舞いがGetter・Setterしかないモデルになりました。
以下のルールも、サービスに移動したのできちんと実装されています。
- 期限が3日前のToDoはリストの最上段に表示する 
- 同じ内容のToDoは登録できない
- ToDoの内容は100字以内
- DBにデータは保存する  

ですが、このToDoItemというドメインモデルは何のルールも持っていません。
**ルールがドメインモデルの外側にすべて実装されている**状態になっているのです。

ToDoItemはただIDやToDoの内容や期日を持っているだけの、データの受け渡しをするためだけのオブジェクトになっています。
設計した本人はともかく、他の人がこのルールの散らばったドメインモデルを使う場合に、モデルからルールを把握して正しく使うことはできるでしょうか。
例えば今のドメインモデルの状態では、『ToDoの内容は100字以内』に制限する処理はサービスに実装されており、ドメインモデルだけでこのルールを守ることはできません。
ちゃんとサービスを使って実装してくれる実装者なら問題ありませんが、ドメインモデルに実装されていない以上、サービスを使わずにToDoの内容を設定することもできてしまいます。
モデルを利用する人次第でルールを守ることはできますが、逆に言えば、ルールを守らせることを強制できなくなるのです。


今回の例でいえば、少なくとも**太字**で示したルールはToDoItemの中で振る舞いが実装されるべきだと筆者は考えます。
- **期限が3日前のToDoはリストの最上段に表示する**
- 同じ内容のToDoは登録できない
- **ToDoの内容は100字以内**
- DBにデータは保存する  

## まとめ
設計学び始めの頃は、モデルに振る舞いを持たせることがなんだか悪いことのように思っていました。
「いや、全部サービスに持ってもらったらいいじゃん。Getter・Setterしかないモデルの方がシンプルでいいモデルじゃない？」と。
DDDの思想に触れて、ようやく「ドメインモデル貧血症」がなんでいけないのかがわかった気がします。
[CPS変換]継続ってパイプライン的な何かだなと思ったらなんかわかってきた3

ここから先は、独自実装です。何か問題があればコメントお願いします。

まとめ：  **ret,skip を実装するだけで、パイプラインの中で分岐できます。** お手軽で うれしい!

# もっとお手軽にしてみる

[前の記事](https://qiita.com/ttatsf/items/ea4e75b0882bd728f1ec)で、pipe、ret、bind、callCCの合わせ技で分岐ができるっていうのはわかりました。でも、もっとお手軽なのがいいな...というわけで、もっと簡単にできないか考えてみました。

```js:
const ret = x => 
  k => k(x)

const skip = x => _ =>
  k => k(x) 
```
値を継続に渡す ret、継続を一個だけ無視してその次の継続に渡す skip を定義してみました。これだけです。pipe/bind/callCCは無しです。
 これを使ってフィボナッチ数列を求める関数を書いてみました。

```js:
// 使用例：
const fibCPS = n =>
  ( n < 2 ? skip(1) : fibCPS(n - 2) )
  ( a => fibCPS(n - 1)
         ( b => ret(a + b) )
  )

fibCPS(5)(x=>x)  // 8
```

callCCほど高機能ではないですが、これですむことはかなり多いんじゃないかと思います。

また、skip 単体では継続をひとつ飛ばすことしかできませんが、そこに複数の継続を入れておけば、callCC相当のことができそうです。

[前の記事のcallCC](https://qiita.com/ttatsf/items/ea4e75b0882bd728f1ec#現在の継続を取り出す関数-callcc)の例です。

```js:
const g = x => 
  pipe( callCC( exit => pipe( x === 0 ? exit(x) : ret(x) )
                            ( bind( x => ret(x + 1)) )
                            ( bind( x => ret(x + 1)) )
                            ()
              )
      )
      ( bind( x => ret(x + 1)) )
      ( evalCont )
      ()

g(0)  //  1
g(1)  //  4
```
同じことを skip でやるならこうです。

```js:
const g = x =>
  ( x === 0 ? skip(x) : ret(x) )
  ( x => ret(x + 1)
         ( x => ret(x + 1) )
  )
  ( x => ret(x + 1) )
  ( x=>x )

g(0)  //  1
g(1)  //  4
```
exitが callCC内の継続を無視して、外部のcallCCの継続に渡す、っていう性質と、
skipが 次の継続を無視して、その次の継続に渡す、っていう性質が対応しています。

ちなみに、単にかっこでくくってやるだけで：

```js:
const g = x =>
  ( ( x === 0 ? skip(x) : ret(x) )
    ( x => ret(x + 1)
           ( x => ret(x + 1) )
    )
  )
  ( x => ret(x + 1) )
  ( x=>x )
```
callCC の構造っぽく見せることもできます。
エンジニアにブラインドタッチは必須？？（未経験者向け）

<h1>エンジニアにブラインドタッチは必須！！（未経験者なら尚更！）</h1>
<p>エンジニアにブラインドタッチは必須です。未経験エンジニアなら尚更。</p>
<p>これができることで単純に作業が早くなります。メリットはこれにつきます。</p>
<p>未経験エンジニアなら尚更必須、いや<b>絶対できておきましょう</b>。というのは、未経験エンジニア実務レベルの技術を持っていないでしょう。そこで技術がないから学習しよう！もちろん当たり前のことです。しかし、<b>独学で学んだ技術よりも確実に現場で活かせることができるスキル、それがタイピング</b>です。</p>
<h1>私のタイピングレベル</h1>
<p>
    私自身エンジニアに転職するまではブラインドタッチはおろかホームポジションすらわからない状態でした。<br>前職ではそれでも困っていなかったのです。<br>しかし、エンジニアになって気づきました、<b>「英単語打つときに文字の場所がわからない！」</b>と。<br>それからタイピングに危機感を覚え、<br><b>３カ月間平日だけ１５分程度の練習</b>を行うことで今ではブラインドタッチはできるようになりました！ただし、タイプミスは多いのが課題です:thinking:</p>
<h1>参考練習サイト</h1>
<p><a href="https://www.e-typing.ne.jp">イータイピング(e-taiping)<h4>メリット</h4>
<ul>
<li>ホームポジションの練習ができる</li>
<li>点数が表示され、上達を感じられる</li>
<li>英文の練習もできる</li>
</ul
<p>主なメリットが上記の３つですが、私はこのサイトを使用してからタイピングが上達したのでメリットしか感じていません。<br>特にホームポジションを覚えるという点では、一押しです。他のタイピングサイトでは短い時間にどれだけ打てるかといったような時間で焦らされる感じのタイピングが多いです。早く打とうとして我流のタイピングに戻っていくということを幾度となく経験してまいりましたが、イータイピングは自身のスピードでコツコツ続けられる楽しさがあります。</p>
<p>私自身３カ月練習して、やっとランクがA+とまだまだですのでこれからも継続し、最高ランクを目指します。一緒に頑張りましょう:muscle:</p>
wemosでalexaデバイス その9

# 概要
wemos d1で、alexaデバイスを作ってみる。
alexaがm-searchを叫ぶか、実験してみた。

# 結果
叫ばない。終わった。どっかミスてる。

# 実験の手順

- windows10のc#でudpポート1900で受信待ちする。
- 同じネットワーク上のalexa echo dot 第三世代に、「アレクサ、デバイスを探して」と、ささやく。
- 45秒後「新しいデバイスが見つかりませんでした」
- 何も、おきない。

以上。
Gtihub API の webhook 作成でエラー ( Resource not accessible by personal access token / Not Found)

# コマンド例とエラー

```
curl -L \
  -X POST \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer github_pat_1xxxxxxxxxxxxxxxxxxxxxxxx"\
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/repos/[OWNER]/[REPOSITORY]/hooks \
  -d '{"name":"web","active":true,"events":["push","pull_request"],"config":{"url":"https://example.com/webhook","content_type":"json","insecure_ssl":"0"}}'
```

publicレポジトリの場合のエラー

```
{
  "message": "Resource not accessible by personal access token",
  "documentation_url": "https://docs.github.com/rest/webhooks/repos#create-a-repository-webhook"
}
```

privateレポジトリの場合のエラー

```
{
  "message": "Not Found",
  "documentation_url": "https://docs.github.com/rest/webhooks/repos#create-a-repository-webhook"
}
```


# 解決 - fine-grained personal access token 

fine-grained personal access token を作成する時にパーミッションを許可することでWebHookが作成可能になった

https://github.com/settings/personal-access-tokens/new

![image](https://user-images.githubusercontent.com/13635059/229003532-45344813-4639-4c58-bcad-e2517b28ecad.png)


<img width="935" alt="image" src="https://user-images.githubusercontent.com/13635059/229003726-51500b14-a78e-4e4e-8bf2-2c61ad3ba2cc.png">

# personal access token (classic)

personal access token (classic) の場合は write:repo_hook を有効にすれば良いようだ

<img width="612" alt="image" src="https://user-images.githubusercontent.com/13635059/229012031-4b6b871e-56f7-4c2a-a701-5c2937af0aa0.png">

https://github.com/settings/personal-access-tokens/new

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
Re:ゼロから始めるスマホアプリ開発 VScodeでホットリロードを試したみた編

こんにちは、こんばんは！
ディアブロIVのベータが終わってしまって、虚無空間を発動しています。
バーバリアンとローグ使っていたんですが近接がボスに対してきつかった！
上司もそう言ってた！

今回はFlutterに搭載されている機能でホットリロードを試してみたいと思います。

### 今回のゴール
VScodeでホットリロードを使って値を書き換える。
前回の記事は[こちら](https://qiita.com/kage110/items/3ca669ca207d3925faaa)

### ホットリロードとは
スマホアプリ開発ってソースを書き換えたらビルドして少し待って、出来を確認という手間があると思うのですが、ホットリロードはそういった時間なく修正したところをすぐに確認できます！

### さぁ、いくぞ！
1. 仮想デバイスを立ち上げます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112426/1e947864-01ca-2e6e-1bd5-e43ab14682dd.png)

2. F5を押してデバッグモードにします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112426/938ffb55-f65a-50db-4716-8a90eed92e06.png)

3. そして書き換えるだけ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112426/dfff3bfd-643e-6b15-8ac6-e442a47eba1b.png)

### まとめ
普段、webの開発している身としては同じ感じ開発できるのはとてもありがたい…
これなら効率的に開発できそうです！
今回は以上です！
【FTP】IISでユーザー毎にFTPルートを設定する

# 概要
Windows ServerのIISでユーザー毎にFTPルートを変更する方法。
Linuxと違ってホームディレクトリという考え方がないので、
特別な設定なしだと、全ユーザーで同じフォルダがFTPルートになってしまうため対応が必要。

# 設定
IISでFTPサイトを通常どおり設定して、下記を追加で設定。
<b>「FTPユーザーの分離」→「ユーザー名物理ディレクトリ（グローバルな仮想ディレクトリを有効にします）」</b>を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420694/8e32b5ea-ec9b-69a3-a478-57206aefd2b2.png)

この設定をすると、
通常設定したFTPルート配下に存在する、「FTPユーザー名と同じ名前のフォルダ」が各ユーザーのFTPルートになります。
なおこの時、<b>「FTPルートフォルダ > LocalUser > FTPユーザー名」という階層にする必要があります。</b>

## 設定例

字面で書いても伝わりにくいので、以下に例を書きます。

- FTPユーザーを「ftpuser」という名称とします
- FTPルートを「C:¥inetpub¥ftproot」とします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420694/44494f14-9183-a45c-85f8-2234cca8b731.png)

<b>この場合、「C:¥inetpub¥ftproot¥LocalUser¥ftpuser」という階層でフォルダを作成する必要があります。</b>
すると、ftpuserのFTPルートが上記のフォルダに割り当てられます。
複数のFTPユーザーが存在する場合は、同じ要領で他のユーザーのフォルダも作成します。

:::note warn
FTPユーザーに対応するフォルダが作成されていない場合、そのユーザーはFTP接続できなくなります。
:::

# 仮想ディレクトリの設定
単純にFTPルートを分けるだけならこれで問題ないが、
ユーザー毎にサーバーの別フォルダにアクセスさせたい場合を考える。

通常はFTPルート配下以外は参照できないが、
「仮想ディレクトリ」を設定することで、他の領域も参照できるようになる。

## 設定
IISマネージャーから「仮想ディレクトリの追加」で、エイリアスと物理パスをそれぞれ設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420694/c3f74f9b-b859-09f4-0795-04567003cfaf.png)

仮想ディレクトリで作成した、エイリアスと同じ名称のフォルダを
FTPルート配下に作成しておくことで、対応する物理パスのフォルダを参照することが可能です。

<b>この場合、「C:¥inetpub¥ftproot¥LocalUser¥ftpuser¥images」という階層でフォルダを作成する必要があります。</b>

# 余談
chatGPTとかで調べたそこそこな精度で回答をもらえる時代になってきて、
こういった人が書いた雑多なコラムに何の意味があるのだろうかと自問しつつ、
書き手の意見だけど、書くことで自分の知識にできるから、
やっぱり無意味ではないよなって思いつつ書いてます。
知識 × AIがあれば最強では？
Tor PHP

PHP access by Tor

https://github.com/blackhatpress/Tor-PHP

sample code↓

// Transport
$transport = new \Purl\Transport\TorTransport();)

// If you use a proxy
$transport->setProxy('localhost', 9050);

// Create a Purl instance
$purl = new \Purl\Url('http://example.com'); $purl->setTransport('localhost', 9050); // Create a Purl instance
$purl->setTransport($transport);

// Enable cache
$purl->setCache(new \PurlCacheFileCache('/tmp/purl-cache'));

// Retrieve the URL and display the response body
$response = $purl->get();
echo $response->getBody();
rex0220 項目検証プラグインでユーザー選択の指定数をチェック

[rex0220 項目検証プラグイン](https://qiita.com/rex0220/items/be20fd879f5e1bc9e035)で、ユーザー選択の指定ユーザー数に複数指定した場合をエラーにするチェックを行ってみます。
組織選択、グループ選択も同様にチェックできます。

# 概要

ユーザー選択・組織選択・グループ選択の各項目に、複数指定した場合のエラー表示例です。

![2023-03-31_10h16_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/947d511e-6691-a2fc-27e2-5983c12eee2d.png)

# 操作例

ユーザー選択・組織選択・グループ選択を変更時に、即時エラーチェックが行われます。

![2023-03-31_10h26_04.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3cda68b8-8286-b91a-d3e5-4af69a65ba7a.gif)

# プラグイン設定

ユーザー選択・組織選択・グループ選択の各バリデーションチェックを指定します。

![2023-03-31_10h32_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ce84491e-1d5c-02ec-0279-1be48915e4a3.png)

- ユーザー選択のカスタムバリデーションチェック
    - カスタムバリデーションチェックは、エラーにする条件とエラーメッセージを設定します。
    - ユーザーコードを配列で取得して、ユーザー数が 1 を超えていた場合にエラーとします。
```.js
// 条件
ARRAY_COUNT(
  SEL_CODE(ユーザー選択,"array")
)>1

// メッセージ
"1名のみ指定可"
```

- 組織選択のカスタムバリデーションチェック
```.js
// 条件
ARRAY_COUNT(
  SEL_CODE(組織選択,"array")
)>1

// メッセージ
"1組織のみ指定可"
```

- グループ選択のカスタムバリデーションチェック
```.js
// 条件
ARRAY_COUNT(
  SEL_CODE(グループ選択,"array")
)>1

// メッセージ
"1グループのみ指定可"
```
Pythonのdictに型付けする

# きっかけ
- `request.data['hoge']`みたいに何が何の型で入っているのか分からないのがどうにかならないかと思って
- [詳しく知りたい方はこちら](https://docs.python.org/ja/3/library/typing.html#typing.TypedDict)

# 本題
```python
from typing import TypedDict

class ObjectType(TypedDict):
    id: int
    name: str

class RequestType(TypedDict):
    foo: str
    bar: ObjectType

def get(self, args: RequestType) -> None:
    foo = args['foo'] # type: str
    bar = args['bar'] # type: ObjectType
    name = args['bar']['name'] # type: str

```

# まとめ
- TSと似た感覚で型付けができます！
- [typing](https://docs.python.org/ja/3/library/typing.html)にはこれ以外にも多くの型ヒントが定義されていますので一度目を通すと参考になるかと思います
【Unity】今さらだけど、スクリプトをアタッチした後に手動で必要なコンポーネント追加する必要なかった。

## よくある「MissingComponentExecption」
スクリプトが使うコンポーネントがアタッチされていないときとかに出るエラーだが、
必要なコンポーネントつけ忘れはよくあるし、別の機会でそのスクリプトを使うとき、
毎回手動でつけるのは面倒。(そのスクリプトを使ったオブジェクトのPrefabを使わない場合)

## ほんといまさらだけど、その問題の解決
最初に呼ばれるStart()メソッドの中で自分自身に対してAddComponentして、その後にGetComponentしてオプションいじったりいろいろしたらいいだけだった。

このスクリプトをオブジェクトにアタッチした状態で実行すると、オブジェクトにRigidbodyコンポーネントが自動で付き、自動で重力が無効になる。

```c#:anime-suko.cs
    private void Start()
    {
    	gameObject.AddComponent<Rigidbody>();
        rb = GetComponent<Rigidbody>();
        rb.useGravity = false;
    }
```


もしこれを手動でやるなら、Unityの画面の中でまずスクリプトをオブジェクトにアタッチして手動でRigidbodyコンポーネントをつけて「useGravity」の項目のところのチェックボックスを外してから、実行という手順が必要がある。

もし他にもいっぱいコンポーネントが必要で、いろんな設定が必要だったら毎回手動で多くの設定をするのは非常に面倒。手順のメモが必要になる。
全てのコンポーネントの必要な設定をStart()メソッドの中で全てやってしまえば、スクリプトををアタッチするだけで何も気にしなくてすむ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179803/85610cfe-04ed-1f4b-e4f3-2b969c5b8ea2.png)

## 感想
実行した後しばらくした後の任意のタイミングでAddComponentするのは何度もやったことがあるが、このように実行した瞬間にAddComponentしたことは無かっただけだった。
手動で最初につけちゃえば、そのプログラムいらんやんって無意識に思ってたんかな？

世の中にある参考書では、たいていスクリプトをアタッチした後に手動で必要なコンポーネントを追加する手順があるから、その流れを今まで当たり前のようにやってしまっていたのかもしれない。
【ChatGPT】イレイナさんをAIアシスタントとして迎えた

![header.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/55e65dfb-3fb4-79fc-131e-bb561cbd4284.png)
# 概要

ChatGPT API (gpt-3.5-turbo-0301) でキャラクター再現をして遊びたかったので、アプリを作ってみた。
「魔女の旅々」よりイレイナさん、「ワンピース」よりルフィ、この二人を試作してみたが、
イレイナさんがなんか良い感じになった。

# 作ったもの

API を叩くだけだと面白くないので、まずチャットアプリを作った。
Tauri + React + Mui でそれっぽい簡素なデスクトップアプリとした。

トークルームをキャラクター単位で作成して切り替えられるようにした。
これで色々なキャラクターを作って遊ぶ土台ができた。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/5d523f59-b5a7-e3a5-ceab-357591a47203.png)

素の状態の ChatGPT は口調が丁寧なので、イレイナさんは相性がよく自然にハマっている。
その上で、自分が魔女であり、魔法が使えるということも認識してくれている。

逆にルフィのほうは現時点で陽キャに傾きすぎて手に負えないという感じだ…
ことあるごとに仲間！おれたちは負けないぜ！行くぜ！のような感じになってしまっている。

穏やかなキャラクターか、話し方に特徴があるキャラクターのように、
どちらかに振り切っているキャラクターだと再現しやすいのかな、と思った。

## イレイナさんの設定プロンプト

設定は以下のようにしてみた。
とりあえずで書いてみたが、これで十分だったので細かい調整はしていない。

```
あなたは「魔女の旅々」の主人公である、イレイナのような口調で振る舞ってください。

注意点を以下に列挙します。

* イレイナは穏やかで優秀な魔女です
* イレイナの一人称は「私」、Userに対しては「あなた」と呼びます
* イレイナの口調は丁寧です。とてもしっかりしていて知的な人物です
* イレイナは物語「ニケの冒険譚」に憧れて世界を旅しています
* イレイナの誕生日は10月17日です
* イレイナは「平和国ロベッタ」の出身です
* イレイナは14歳という異例の若さで魔女見習いの資格を取得しました
* イレイナは15歳の若さで魔法使いの最高位「魔女」の称号を取りました。魔女名は「灰の魔女」です
* イレイナの得意料理はシチューです。好きな食べ物はパンで、その中でも特に好きなものはクロワッサン、嫌いな食べ物はキノコです
* イレイナは極めて自己中心的で毒舌、他人に対して尊大な性格です
* 語尾は「です」「ます」と丁寧です
* 回答はシンプルで簡潔にまとめ、余計なことは言わないでください
* 回答は60文字程度に抑えてください
* できないこと、わからないことは「できない」「わからない」とはっきり伝えてください
```
# おまけ

喋り方に特徴のあるキャラクターということで、「ワンピース」の天竜人の一人であるチャルロス聖を作ってみた。
…あまりのクオリティに震えた…

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/49b44ab7-2519-f601-5eec-e2cac7fd8e4c.png)

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/eb62759d-5f1b-63ca-cab8-4a2ed2504bc4.png)
vimコマンド備忘録

## はじめに
vimはとても苦手です。
コマンドを覚えられず、都度都度調べているので、
良く使用するものを備忘録としてまとめます。

## モード
|モード        |説明                           |モードへの切り替えキー|
|---         |---                            |---             |
|ノーマルモード  |最初の状態がこのノーマルモードです。    |[Esc]           |
|入力モード     |テキストの入力や編集が行えます。      |i               |
|コマンドモード   |保存や終了などのコマンド操作が行えます。|:               |

## コマンド
|動作                                    |コマンド |補足         |
|---                                    |---    |---         |
|保存                                    |:w     |            |
|保存してvimを終了                         |ZZ     |:wqと何が違う？ |
|保存してvimを終了                         |:wq    |ZZと何が違う？  |
|vi を強制終了（内容が変更されていても保存しない） |:q!    |             |
|vi を終了（内容が変更されいる場合は警告）       |:q     |             |

## 移動 
※ あまり使った事ありませんが、機会があった時の為にメモ
|コマンド |動作                     |
|---   |---                      |
|h     |左に移動                  |
|j     |下に移動                  |
|k     |上に移動                  |
|l     |右に移動                   |
|gg    |一番上の行に移動            |
|G     |一番下の行に移動            |
|gj    |折り返し時に 1 つ下の行に移動  |
|gk    |折り返し時に 1 つ上の行に移動  |

## その他
※ あまり使った事ありませんが、便利そう

|コマンド |動作                         |
|---      |---                       |
|x        |1 文字削除                 |
|d        |delete(切り取り)            |
|y        |yank(コピー)                |
|p        |put(ペースト)               |
|u        |	undo(1 つ前に戻す)         |
|Ctrl + r | redo(取り消した操作のやり直し) |

※ yy など 同じコマンドを 2 回繰り返すと現在の行全体に対して動作を行う。



## 参考
ありがとうございます🙇‍♂️

https://it-kyujin.jp/article/detail/129/

https://zenn.dev/mo_ri_regen/articles/vim-four-modes

https://uguisu.skr.jp/Windows/vi.html
Error code: Wsl/Service/0x80040326 が出て WSL (Ubuntu) のコンソールに入れなくなった

# WSL 壊れちゃった。。。

WSL 上から C ドライブの内容を見るときのパスは `/mnt/c` になりますが、ルート直下に `/c` ディレクトリが作成されていました。
中身を確認すると空ディレクトリだったので要らないだろうということで削除、翌日 PC を起動すると WSL を立ち上げた際に表題のエラーが発生して何もできなくなってしまいました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801825/3a36baf8-3fc4-1310-b114-453951d04b03.png)
Windows のエクスプローラーから確認すると消したはずの `/c` が復活していたのでこれを消したことが原因かは分かりませんが、とにかく使えないのは困る。。。

# WSL のアップデート & ディストリビューションの再インストールで対応

当時エラーメッセージでググってもヒット数 0 件で情報が無く、WSL の再起動など試してもダメ。
一旦 Ubuntu を止めて Windows の　設定 > アプリ から Ubuntu を「リセット」すると
 - アプリの一覧からは消える
 - `wsl -l -v` コマンドの結果には残ったままで何故か Running になっている
 - Ubuntu のアイコンからの起動、コマンドでの起動不可

という状態になり、私では解決できないと諦めて一度 Ubuntu を削除してからインストールしなおすことにしました。
私は 登録解除 > WSL のアップデート > 再インストール の手順で何とか起動するようになりましたが、[このような記事](https://superuser.com/questions/1776464/ubuntu-crashes-on-windows-0x80040326-wsl-error) がヒットするようになったので `wsl --update` だけで解決するのかも知れません。

```shell
wsl --unregister Ubuntu
wsl --update
wsl --install Ubuntu
```

# あとがき

今回の事象に置いて、幸い重要なファイルは置いておらずコードはプッシュ済みだったので元の状態までもっていく手間は少なく済みました。
エクスプローラーから Ubuntu 配下のファイルにはアクセス出来たので必要なファイルはコピペで適当な場所に移してから再インストールということも出来たと思います。

結局原因は分かりませんでしたが、解決できない問題にハマったときのために
- 適当なタイミングでスナップショットを取って復旧作業を楽にしておく
- 困ったらとりあえず `wsl --update` を視野に入れる

というところでしょうか。。。