OmniAICreator/Qiita-1.07M huggingface dataset:
wslでelixir その61

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
練習問題、やってみた。

# 練習問題
Phoenixで、WebSocketをplunkerから叩け。

# 方針
Phoenix.js 使う。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/525264f1-9a8a-09bc-4b86-b3eed888365c.png)



# サンプルコード

```
let chatInput = document.querySelector("#chat-input")
let messagesContainer = document.querySelector("#messages")

const socket = new Socket("ws://localhost:4000/socket");
socket.connect();

const channel = socket.channel("room:lobby", {});
channel.join().receive('ok', resp => console.log(`> joining channel  ${channel.topic}`)).receive("error", reason => console.log(`Error joining channel:`, reason));
channel.onError(e => alert("something went wrong", e))
chatInput.addEventListener("keypress", event => {
	if (event.key === 'Enter')
	{
		channel.push("shout", {body: chatInput.value})
		chatInput.value = ""
	}
})
channel.on('shout', (payload) => {
	const msgItem = document.createElement('li');
	msgItem.innerText = `[${Date()}] ${payload.body}`;
	messagesContainer.appendChild(msgItem);
});

```

# 成果物

https://embed.plnkr.co/plunk/vH7f6HbR1BGR5IRP

以上。
基本情報対策：小学生にもわかる？バブルソートについて

基本情報対策で、ソートアルゴリズムを再度学習しています。

いいおっさんなのですが、理解が及ばず完全理解しようとしています。

素でコードを書けるように微妙に腹落ちしていなかった部分を細かく確認しながら、pythonで再現します。

## バブルソートとは

昇順、降順に合わせて大きい数字（小さい数字）を端に寄せていくアルゴリズムです。

今回は昇順で説明します。

3,2,1という数字があったとしたら、

1:　3,2,1

2:　2,3,1

3:　2,1,3

4:　1,2,3

という４つの動きでソートが完了します。

配列の要素数を繰り返せば、いつか終わるため、配列の要素数をi,jのループで回します。

### まず素直にそのまま書いてみる：

```python
#変数名:sortary:ソｒトにかける配列、n:配列の要素数　i,j:ループ用　
#tmp:temporaryの略で一時的に何かを格納する変数名としてよく使われます。
sortary = [9, 7, 6, 8, 5, 3]

def bubblesort(ary):
    cnt=0
    n = len(ary)
    for i in range(n):#配列分だけ繰り返す
        for j in range(0, n-1):
		#配列数-1まで繰り返す
		#-1なのは、ループ中にj+1を使い、最後の要素に値を入れてるからです。
            cnt=cnt+1
            print(cnt,i,j,ary)
            if ary[j] > ary[j+1]: 
			#左と右を見比べ、右のほうが小さかったら左に入れ替えないとだめよね。 
                tmp = ary[j]
				#入れ替えるために、tmpに左の数字を一時格納する。
                ary[j] = ary[j+1]
				#右の値を左に入れ替える
                ary[j+1] = tmp
				#結果左の値を右に入れ替える。
    return ary

print(bubblesort(sortary))
```

### 出力結果：

```python
1 0 0 [9, 7, 6, 8, 5, 3]
2 0 1 [7, 9, 6, 8, 5, 3]
3 0 2 [7, 6, 9, 8, 5, 3]
4 0 3 [7, 6, 8, 9, 5, 3]
5 0 4 [7, 6, 8, 5, 9, 3]
6 1 0 [7, 6, 8, 5, 3, 9]
7 1 1 [6, 7, 8, 5, 3, 9]
8 1 2 [6, 7, 8, 5, 3, 9]
9 1 3 [6, 7, 5, 8, 3, 9]
10 1 4 [6, 7, 5, 3, 8, 9]
11 2 0 [6, 7, 5, 3, 8, 9]
12 2 1 [6, 7, 5, 3, 8, 9]
13 2 2 [6, 5, 7, 3, 8, 9]
14 2 3 [6, 5, 3, 7, 8, 9]
15 2 4 [6, 5, 3, 7, 8, 9]
16 3 0 [6, 5, 3, 7, 8, 9]
17 3 1 [5, 6, 3, 7, 8, 9]
18 3 2 [5, 3, 6, 7, 8, 9]
19 3 3 [5, 3, 6, 7, 8, 9]
20 3 4 [5, 3, 6, 7, 8, 9]
21 4 0 [5, 3, 6, 7, 8, 9]
22 4 1 [3, 5, 6, 7, 8, 9]
23 4 2 [3, 5, 6, 7, 8, 9]
24 4 3 [3, 5, 6, 7, 8, 9]
25 4 4 [3, 5, 6, 7, 8, 9]
26 5 0 [3, 5, 6, 7, 8, 9]
27 5 1 [3, 5, 6, 7, 8, 9]
28 5 2 [3, 5, 6, 7, 8, 9]
29 5 3 [3, 5, 6, 7, 8, 9]
30 5 4 [3, 5, 6, 7, 8, 9]
[3, 5, 6, 7, 8, 9]
```

ソートできてますね。でもクッソ長い・・・・

よく見ると、大きい順に値が固定されているため、固定されるとに二度と動きませんよね。

でも毎回、配列の末尾までソートのを行っていますので無駄だし処理が重くなります。

そのため、その分ループの回数を減らしてみましょう。

### 修正コード：

```python
sortary = [9, 7, 6, 8, 5, 3]

def bubblesort(ary):
    n = len(ary)
    cnt=0
    for i in range(n):
        for j in range(0, n-i-1):
        #ここを変えただけ
            cnt=cnt+1
            print(cnt,i,j,ary)
            if ary[j] > ary[j+1]:  
                tmp = ary[j]
                ary[j] = ary[j+1]
                ary[j+1] = tmp
    return ary

print(bubblesort(sortary))
```

### 結果：

```python
1 0 0 [9, 7, 6, 8, 5, 3]
2 0 1 [7, 9, 6, 8, 5, 3]
3 0 2 [7, 6, 9, 8, 5, 3]
4 0 3 [7, 6, 8, 9, 5, 3]
5 0 4 [7, 6, 8, 5, 9, 3]
6 1 0 [7, 6, 8, 5, 3, 9]
7 1 1 [6, 7, 8, 5, 3, 9]
8 1 2 [6, 7, 8, 5, 3, 9]
9 1 3 [6, 7, 5, 8, 3, 9]
10 2 0 [6, 7, 5, 3, 8, 9]
11 2 1 [6, 7, 5, 3, 8, 9]
12 2 2 [6, 5, 7, 3, 8, 9]
13 3 0 [6, 5, 3, 7, 8, 9]
14 3 1 [5, 6, 3, 7, 8, 9]
15 4 0 [5, 3, 6, 7, 8, 9]
[3, 5, 6, 7, 8, 9]
```

わわ！半分になった！めっちゃ減りましたね。

これの理屈は、iのループが一回終わると、大きい数字が固定されることに起因します。

iが0以上になると、右から大きい値が決まっているということになるため、nから引いてやると、

決まっている値はソートされなくなります。

### 結論：

ちょっとしたことで処理って軽くなるんだな！

ちょっと賢くなった！
プロトタイプベースのオブジェクト指向について比較して解説してみた

もちろん、JavaScriptのプロトタイプベースのオブジェクト指向について、シンプルに説明いたします。

### 🎨 伝統的なクラスベースのオブジェクト指向
多くの言語（JavaやC++など）では「クラス」という設計図を使って、オブジェクトを作ります。この設計図を基に、同じ型のいくつものオブジェクト（例: 車やロボット）を作成することができます。

伝統的なクラスベースのオブジェクト指向プログラミングについて、シンプルな例を使って説明します。

**イメージ:**
家の設計図（クラス）: 家の設計図には、部屋の数や大きさ、窓の位置などの詳細が含まれています。この設計図を基に、同じ構造の家をいくつでも建てることができます。

実際の家（インスタンス）: 設計図に基づいて実際に建てられた家です。各家はその設計図に従っていますが、中の家具や壁の色などの詳細は異なる場合があります。

```java
// クラスの定義
class Dog {
    String breed;
    String color;

    // コンストラクタ
    Dog(String breed, String color) {
        this.breed = breed;
        this.color = color;
    }

    // メソッドの定義
    void bark() {
        System.out.println("Woof!");
    }
}

// インスタンスの作成
public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog("Golden Retriever", "Yellow");
        myDog.bark(); // Woof!
    }
}
```

上の例では、Dogというクラス（設計図）を定義しています。そして、new Dog("Golden Retriever", "Yellow")でこの設計図を基に「Golden Retriever」という犬のオブジェクト（実体の家）を作成しています。

このクラスベースのアプローチは、型の安全性や継承の明確さ、オブジェクトの振る舞いの再利用性など、多くの利点を持っています。

### 🍪 プロトタイプベースのオブジェクト指向（JavaScriptの場合）
こちらのアプローチでは、実際のオブジェクトを使って、新しいオブジェクトを「コピー」したり「継承」したりします。この「元となる」オブジェクトを「プロトタイプ」と呼びます。

**イメージ：**
クッキーカッター（伝統的なクラスベース）: クッキーカッターを使って、同じ形のクッキーをたくさん作ることができます。

クッキーの断片を使って新しいクッキーを作る（プロトタイプベース）: 既存のクッキーの一部を取って、新しいクッキーを作成します。この既存のクッキーが「プロトタイプ」となります。

**なぜこの方法が役立つのか？**
柔軟性: 既存のオブジェクトを編集して、新しいオブジェクトを簡単に作成することができます。
効率性: メモリを効果的に使用することができます。多くのオブジェクトが同じプロトタイプを共有している場合、それらの共通の機能は一度だけメモリに保存されます。

```js
let dog = {
    breed: "unknown",
    bark: function() {
        console.log("Woof!");
    }
};

let myDog = Object.create(dog);
myDog.breed = "Golden Retriever";

console.log(myDog.breed); // Golden Retriever
myDog.bark(); // Woof!
```

ここで、dogはプロトタイプとして機能し、myDogはdogから継承して新しく作られたオブジェクトです。

このプロトタイプベースのアプローチは、特にJavaScriptのような動的な言語において、オブジェクト指向の設計を非常に柔軟にする要因となっています。
Hyper-V VMでOpenCoreを使用する

# 目的

- Hyper-V VM上でOpenCoreを使用できるようにする
- これによって何が出来るかは不明
- macOSは起動せず(VMのハードが不明)

Hyper-V VM上でOpenCoreを起動させる記事です

:::note info
これを活用し何かに成功したり、この記事が役立つような事があればコメントで教えていただけると嬉しいです
:::

# 手順
## 1. 空の仮想マシンを作成する
Hyper-V Managerから仮想マシンを作成します。UEFIブートを使用するため、必ず第二世代を選択してください。VM名は`OpenCore`とします。これに関してはネットに大量に情報があるので割愛します。

作成後、以下のように設定してください。
- `Security` -> `Secure Boot` -> `Enable Secure Boot`
    - (必須) チェックを外す
- `Memory` -> `Dynamic Memory` -> `Enable Dynamic Memory`
    - (推奨)チェックを外す
- `Processor` -> `Number of virtual processors`
    - (推奨) 4 ※後述
- `Checkpoints` -> `Checkpoint Types` -> `Enable checkpoints`
    - (推奨) チェックを外す
- `Automatic Start Action`
    - (推奨) Nothingを選択
- `Automatic Stop Action`
    - (任意) Shut down guest operating systemを選択

:::note info
デフォルト値はホストコンピューターが物理コア数のようです。OpenCoreはコンシューマ向けプロセッサを想定している為、なるべく2~8コアなど一般的な数値としましょう。HEDTは動作事例が少ないのでステップ3で苦戦を強いられるかもしれません。
:::

## 2. 空のVHDXを作成・初期化する
### 作成
ここでは、パスを`C:\work\OpenCore.VHDX`とします。
> PowerShell(管理者)
```powershell
md C:\work\
diskpart
create vdisk maximum=1024 file=C:\work\OpenCore.VHDX type=expandable
exit
```
### 初期化
> PowerShell(管理者)
```powershell
Mount-VHD -Path "C:\work\OpenCore.VHDX"
diskmgmt.msc
```
ディスクの初期化ポップアップが出てくるので、MBRで初期化します。初期化したVHDXで"新しいシンプルボリューム"を実行し、ウィザードに従って初期化します。ここではドライブレターを`D:`とします。フォーマットはFAT32です。

これでVHDXの作成・初期化は完了です。
引き続き、OpenCoreを導入していきます。

## 3. OpenCoreを導入する
OpenCore EFIの構築はホスト構成に強く依存するので割愛します。
dortania OpenCore-Install-Guideなどを見てホストコンピューターに合うよううまく構成してください。

> 例：今回のホスト構成
> ```
> Ryzen Threadripper 1950X
> DDR4 64GB
> ASRock Fatal1ty X399 Professional Gaming
> ```
> EFIは[こちら](https://github.com/luchina-gabriel/BASE-EFI-AMD->RYZEN-THREADRIPPER)のGitHubリポジトリよりお借りしました。
> (`マザボの型番 OpenCore site:github.com`などで調べると、構成済みのEFIが配布されている場合があります。)

EFIが完成(または入手)できたら、`EFI`フォルダーをDドライブのルートにコピーします。
完了したら、OpenCore.VHDXのマウントを解除します。
> PowerShell(管理者)
```powershell
Dismount-VHD -Path "C:\work\OpenCore.VHDX"
```
これで`D:`は解放され、OpenCore起動用の仮想ディスクファイルは完成です。

## 4. Hyper-V仮想マシンにOpenCoreを適用する
Hyper-V仮想マシンに作成したOpenCore入りVHDXを追加します。
> PowerShell(管理者)
```powershell
Add-VMHardDiskDrive -vmname OpenCore -Path C:\work\OpenCore.VHDX
```

> Hyper-V Managerを使用する場合：
> 1. 1で作成した仮想マシンを選択
> 2. 右のメニューから`Settings...`をクリック
> 3. ハードウェアの`SCSIコントローラー`を選択
> 4. `Hard Drive`を選択して`Add`をクリック

# 起動
Hyper-V Managerから仮想マシンをダブルクリック -> `Start`
下記の画面になれば成功です。 

- OpenCore Release版
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222532/b4e5f4ec-7a56-b677-0e76-c2a597031ef2.png)

- OpenCore Debug版
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222532/24397954-b914-940e-20a0-09f68cd7e152.png)
:::note warn
起動後、一瞬文字が映ってブラックアウトする場合は、一時停止/再開で改善するかもしれません。(Hyper-Vのバグかな？)
:::

# 最後に
お疲れさまでした。誤りなどがあればお知らせください。活用事例やアイデアも嬉しいです。


# 参考文献
[Testing UEFI on Hyper-V](https://github.com/tandasat/MiniVisorPkg/blob/master/Docs/Testing_UEFI_on_Hyper-V.md)

# 編集履歴
#3. 05/17 2024 リンク切れを修正
#2. 09/17 2023
#1. 09/16 2023
JavaScriptとTypeScriptの違いをわかりやすく解説してみた

### 概要
TypeScriptをよく聞くけど、
JavaScriptとTypeScriptって何がどう違うの？という疑問のある方向けに、
今回は、わかりやすくおもちゃのブロックを使った例で比較してご説明します！

##### おもちゃのブロック

JavaScript: 
いろんな形や色のブロックがたくさんあります。好きなように組み合わせて遊べます。でも、正しい形で組み合わせないと、あとから崩れやすくなることも。

TypeScript: 
このブロックもJavaScriptのブロックと同じように見えますが、組み合わせる前に、「この形のブロックとこの色のブロックはこう組み合わせるんだよ」という指示があるので、正しく組み合わせるのが少し楽になります。

##### 何が得られるか

JavaScript: 
自由に組み合わせて遊べるので、すぐに楽しい遊びができます。でも、間違えると後で直すのが大変。

TypeScript: 
最初は「この形とこの色をこう組み合わせるんだ」というルールを学ぶ必要があるので、ちょっと大変。でも、そのおかげで間違いを早く見つけることができる。

##### 結果

JavaScript: 
速く作れるけど、後で問題が出ることも。

TypeScript: 
最初は学ぶことが多いけど、安全に遊べる。

要するに、JavaScriptは自由にプログラミングできる言語で、TypeScriptはその上で「こうした方がいいよ」というおすすめのルールが追加された言語だと考えるとわかりやすいです。


では、具体的にみてみましょう。

#### 1. 型システム
JavaScript:
JavaScriptは動的型付け言語です。変数に格納される値の型は、実行時まで分からないことが多いです。

```js
let value = "Hello";
value = 123; // これはOK
```

TypeScript:

TypeScriptは静的型付け言語です。変数、関数の引数、返り値などの型を指定することができます。
```ts
let value: string = "Hello";
value = 123; // これはエラー
```

https://qiita.com/ri-oo/items/42c85fea9a2d7b95db31

#### 2. クラスとインターフェース
JavaScript:
ES6からクラスをサポートしていますが、インターフェースのような厳密な型の仕組みは提供していません。

TypeScript:
TypeScriptでは、クラスの他にもインターフェースを利用して、オブジェクトの形を定義することができます。

```ts
interface Person {
  firstName: string;
  lastName: string;
}
```

https://qiita.com/ri-oo/items/52f4aba181ce24df1d91


#### 3. 高度な型機能
JavaScript:
JavaScriptには型の概念が限られています。

TypeScript:
联合型、交差型、リテラル型、タプルなど、高度な型システムをサポートしています。

#### 4. コンパイルエラー
JavaScript:
文法的に問題がなければ、実行時までエラーがわからないことが多いです。

TypeScript:
コードをコンパイルする際、型やその他のエラーを事前に検出することができます。

#### 5. ツールのサポート
JavaScript:
有名なエディタやIDEは、JavaScriptのコード補完やリファクタリングをサポートしています。

TypeScript:
TypeScriptの型情報を利用することで、エディタやIDEはより高度なコード補完、リファクタリング、定義への移動などの機能を提供します。

#### まとめ:
TypeScriptは、JavaScriptのスーパーセットとして開発されました。そのため、JavaScriptのすべての機能を持ちながら、追加の機能とツールを提供しています。TypeScriptの主な利点は、強力な型システムとコンパイル時のエラーチェックにあります。これにより、大規模なプロジェクトやチームでの開発が容易になります。
VisualStudio2022の.NETプロジェクトのReleaseビルドで.pdbファイルを生成しないようにする方法

ググったけどなぜか無かったので。
~~VS2022 というより .NET 側の設定だけど。~~
(2023/09/17訂正) *.csproj ファイルは .NET 用ではなくてビルドツールの MSBuild 用の設定ファイルでした。 
(参考: [プロジェクト ファイルについて | Microsoft Learn](https://learn.microsoft.com/ja-jp/aspnet/web-forms/overview/deployment/web-deployment-in-the-enterprise/understanding-the-project-file) )

# 方法

プロジェクトファイル ( YOUR_PROJECT_NAME.csproj ) に以下を追加。

```
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
    <DebugType>full</DebugType>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Release'">
    <DebugType>none</DebugType>
</PropertyGroup>
```
[flutter] extendsとimplementsの違いをまとめてみた。


## はじめに

今回はextendsとimplementsの違いをまとめてみました。

分かっているようで、何と無く使っている人も多いのではないでしょうか。
結構頑張って調べたので読んでくれた方の役に立てれば幸いです。

さっそく本題ですが、extends(継承)とimplements(実装)は**全く別物といって差し支えありません。**
そういう意味では、そもそもextendsとimplementsの違いを取り上げるのもおかしな話かもしれません。（？）

まあ細かいところはあまり気にせず、今回はそれぞれ一つずつ説明していきます。

## 結論

|     | １、親クラスの強制実装 |２、複数指定 
|---|---|---
|extends| ❌ |❌  
|implements| ⭕️ | ⭕️  


※１、implementsは全ての関数をオーバーライドする必要があります。

※２、一つのクラスに対して一つの親クラスのみを継承できるのに比べて、インターフェースは一つのクラスの複数個実装できます。


これだけど不親切かと思いますので、一つずつ説明していきます。

## implements(実装)とは

多くの人にとって、extends(継承)の方が親しみがあると思います。
なのであえてimplements(実装)の方から説明させて頂ければと思います。




結論ですが、**implementsとはインターフェースの機能を実装するためのものです。**


インターフェースとはなんぞやってことですが、以下のサイトでとってもわかりやすいので目を通すことをお勧めします。

https://www.gixo.jp/blog/5159/



簡単にまとめると、インターフェイスとは、**implementsで実装したクラスには、任意のメゾットを必ず実装しなければならないという制約のことです。**

```dart

// インターフェースの定義
abstract class Animal {
  void makeSound();
}

// インターフェースを実装するクラス１
class Dog implements Animal {
  @override
  void makeSound() {
    print('ワンワン');
  }
}

// インターフェースを実装するクラス２
class Cat implements Animal {
  @override
  void makeSound() {
    print('ニャー');
  }
}
```


上記コードの通り、インターフェース自体の定義は**abstractをクラスの前に記載して実装します。**

あとはextendsと同じように、implementsでインターフェイスを実装するクラスを作成します。


```dart

void main() {
  final dog = Dog();
  final cat = Cat();

  dog.makeSound(); // ワンワン
  cat.makeSound(); // ニャー
}

```

なお上記コードはインターフェイスを実装するクラスを使用する具体例です。

とにかくポイントとしては、**インターフェスを実装したクラスは必ず、インターフェースに記載されている関数（メゾット）を必ず全て実装しなければならないことです。**

### extends(継承)とは

extends(継承)に関しては以下の記事がわかりやすいかと思います。


https://blog.flutteruniv.com/flutter-dart-extends/

簡単に説明すると、extends(継承)とはクラスの拡張と呼ばれて、
あるクラスの独自の機能を保持しつつ継承した親クラスのメゾット（関数）や変数も使用することができます。
implemntsよりもよりカスタム性が硬いことが特徴です。

実際のコードを見ていきましょう。

```dart

class Animal {
  String name;
  
  Animal(this.name);
  
  void makeSound() {
    print('$name が音を鳴らしました');
  }
}

class Dog extends Animal {
  Dog(String name) : super(name);

///親クラスから継承したメゾット
///親クラスから継承したメゾットは実装しなくてもよい。
  @override
  void makeSound() {
    print('$name がワンワンと鳴きます');
  }
///親クラスにはないDogクラスの独自メゾット
  void fetch() {
    print('$name がボールを取ってきます');
  }
}
```
implementsとは異なり、親クラスのメゾットを必ず実装しなければならないという原則はありません。
従って上記のコードでいうところのmakeSound()はコメントアウトしてもうまく動作します。

あくまでextendsはクラスの拡張をイメージすることが大事に思います。


### extendsとimplementsの違いについて。


|     | １、親クラスの強制実装 |２、複数指定 
|---|---|---
|extends| ❌ |❌  
|implements| ⭕️ | ⭕️  


※１、implementsは全ての関数をオーバーライドする必要があります。

※２、一つのクラスに対して一つの親クラスのみを継承できるのに比べて、インターフェースは一つのクラスの複数個実装できます。

### 参考資料
https://blog.flutteruniv.com/flutter-dart-extends/

https://www.gixo.jp/blog/5159/

https://zenn.dev/iwaku/articles/2020-12-16-iwaku


### 最後に

読んでいただきありがとうございました。
もし何かこの記事にご指摘などございましたらコメントいただけますと幸いです。
クラスとインターフェイスについてわかりやすく解説してみた

### 🚗 クラス (Class)
イメージ: 車の設計図

##### 説明: 
クラスは、オブジェクトの「設計図」のようなものです。この設計図に基づいて、具体的なオブジェクト（インスタンス）を作成します。

##### 特徴: クラスには変数（車の色やサイズなどの属性）とメソッド（車ができる動作、例: 走る、止まる）が定義されます。

```ts
class Car {
  color: string;

  constructor(color: string) {
    this.color = color;
  }

  drive() {
    console.log("Vroom!");
  }
}

const myCar = new Car("red");
myCar.drive(); // Vroom!
```


### 📜 インターフェース (Interface)
イメージ: 必要な機能のチェックリスト

##### 説明: 
インターフェースは、あるオブジェクトが持つべき属性やメソッドの「形」や「構造」を定義します。具体的な動作や実装は含まれません。

##### 特徴: 主にオブジェクトの形を保証するために使用され、それが実際にどのように動作するかは定義しません。

```ts
interface Vehicle {
  color: string;
  drive(): void;
}

class Car implements Vehicle {
  color: string;

  constructor(color: string) {
    this.color = color;
  }

  drive() {
    console.log("Vroom!");
  }
}

```

### まとめ
クラス: 実際に作るものの設計図。それが何を持っていて、何ができるかを定義する。
インターフェース: あるものが持つべき形や構造のチェックリスト。具体的な動作は書かない。
静的型付け言語と動的型付け言語についてわかりやすく解説してみた

###  🎒 静的型付け言語（Static Typing）
イメージ: 事前に中身が決められているバッグ

##### 説明:
静的型付け言語では、バッグを買うときに「このバッグは本だけ入れるためのもの」と決められています。
例: 本専用のバッグを買ったら、そのバッグには本しか入れることができません。

##### 利点: 
何を入れるかが決まっているので、間違って他のものを入れる心配がありません。

##### 欠点：
事前に型が固定されているため、コードの柔軟性が制限される場面があります。

##### 代表的な言語: TypeScript, Java, C++

### 🛍️ 動的型付け言語（Dynamic Typing）
イメージ: 中身を何でも自由に選べるショッピングバッグ

##### 説明: 
動的型付け言語では、バッグを買うときに何を入れるかを決めなくてもOK。後で何を入れるか自由に選ぶことができます。
例: ショッピングバッグには、今日は本を入れ、明日は水筒やお弁当箱を入れることができます。

##### 利点: 
とても柔軟で、後からバッグの中身を変えることが容易です。
##### 欠点: 
しかし、注意しないと、想定外のもの（例: 必要のないものや禁止されているもの）をバッグに入れてしまうことがあるかもしれません。

##### 代表的な言語: JavaScript, Python, Ruby
JavaScript 押さえておきたい用語集


JavaScriptとは、ウェブブラウザやサーバーサイドで動作するスクリプト言語の一つです。最初はブラウザ上での動的なインタラクションを提供するために生まれましたが、現在ではNode.jsといったサーバーサイドの技術にも広く使用されています。JavaScriptはプロトタイプベースのオブジェクト指向言語で、関数型プログラミングの要素も持っています。

以下、用語の解説です。

## オブジェクト (Object)

オブジェクトとは、キーと値のペアの集合です。JavaScriptでは、オブジェクトは非常に柔軟で、動的にプロパティやメソッドを追加、削除することができます。

```js
const person = {
  name: 'Taro',
  age: 25,
  greet: function() {
    console.log('Hello, my name is ' + this.name);
  }
};
```

## プロパティ (Property)

オブジェクトに関連付けられた値や関数を指します。上記の例でいうと、nameとageはpersonオブジェクトのプロパティです。

## コンストラクタ (Constructor)

コンストラクタは、新しいオブジェクトのインスタンスを生成するための特別なメソッドです。JavaScriptでは、関数をコンストラクタとして使用することができます。
```js
function Person(name, age) {
  this.name = name;
  this.age = age;
}

const taro = new Person('Taro', 25);

```

## 関数 (Function)

JavaScriptでの関数は第一級オブジェクトです。つまり、関数は変数に代入されたり、他の関数の引数や戻り値として使用されることができます。


```js
function greet(name) {
  return 'Hello, ' + name + '!';
}

```

## クロージャ (Closure)

関数が定義されたスコープの変数にアクセスする能力を持つ関数を指します。この概念は、プライベート変数やファクトリ関数の実装に役立ちます。

```js
function createCounter() {
  let count = 0;
  return function() {
    count++;
    return count;
  };
}

```

## プロトタイプ (Prototype)

JavaScriptはプロトタイプベースのオブジェクト指向プログラム言語であり、オブジェクトはプロトタイプから継承されるメソッドやプロパティを持ちます。

```js
function Dog(name) {
  this.name = name;
}

Dog.prototype.bark = function() {
  console.log(this.name + ' says woof');
};
```


## 非同期処理 (Asynchronous)

JavaScriptはシングルスレッドで動作するため、非同期処理は特に重要です。Promiseやasync/awaitといった概念を使用して非同期処理を扱うことができます。

```js
function fetchData() {
  return new Promise((resolve, reject) => {
    // 仮の非同期処理
    setTimeout(() => {
      resolve('Data fetched!');
    }, 1000);
  });
}

fetchData().then(data => console.log(data));

```

## this

thisはJavaScriptの特殊なキーワードで、現在の実行コンテキストやオブジェクトを指します。関数やメソッドの中でのthisの値は、その関数がどのように呼び出されるかによって変わることがあります。


## モジュールシステム

JavaScriptでは、コードをモジュール化して再利用性やメンテナンス性を向上させることができます。importやexportを使ってモジュールを分割・統合することが可能です。

### まとめ
これらはJavaScriptの基本的な概念や特徴の一部です。実際のプロジェクトや学習の過程で、さまざまなライブラリやフレームワークとともにこれらの概念を深く理解していくことが重要です。
DBにはなぜスキーマが必要なのか

データベースの構造において、スキーマを挟む理由はいくつかあります。
以下に主な理由を挙げます

名前空間の提供：スキーマはデータベース内でテーブルやビュー、ストアドプロシージャなどのオブジェクトの名前空間を提供します。これにより、同じデータベース内で同じ名前のテーブルやビューを持つことができますが、それらは異なるスキーマに属しているために区別されます。

権限管理：スキーマを使用することで、特定のユーザーやグループに対して、そのスキーマに属するオブジェクトへのアクセス権限を一括で設定することができます。これにより、データベースのセキュリティ管理が容易になります。

オブジェクトの整理：スキーマを使用することで、関連するテーブルやビューなどのオブジェクトをグループ化して整理することができます。例えば、給与に関するテーブルやビューは「給与」スキーマに、商品に関するテーブルやビューは「商品」スキーマに格納することで、データベースの構造がわかりやすくなります。

移行とデプロイの容易さ：スキーマを使用することで、特定のスキーマに属するオブジェクト群をまとめてエクスポートやインポートすることが容易になります。これにより、データベースの移行やデプロイがスムーズに行えます。

複数のアプリケーションの共存：異なるアプリケーションやプロジェクトが同じデータベースを使用する場合、それぞれのアプリケーションやプロジェクトに対応するスキーマを作成することで、オブジェクトの衝突を避けることができます。

以上のように、スキーマはデータベースの構造や管理を効率的に行うための重要な要素となっています。
【Javascript+fetch】ファイルのダウンロード機能を実装する

### 実装する処理
今回はボタン押下で「.csv」や「.xlsm」ファイルをダウンロードする。という機能を実装したいと思います。(備忘録を込めて)
- 実装環境については以下です。
    - React × Typescript　（今回の実装内容ではtsの恩恵はあまり受けませんが、、）
    - material ui ([docs](https://mui.com/))
### fetchについて
今回使用する[fetch](https://developer.mozilla.org/ja/docs/Web/API/fetch)とは、
>　fetch() はグローバルのメソッドで、ネットワークからリソースを取得するプロセスを開始し、レスポンスが利用できるようになったら履行されるプロミスを返します。
>
>このプロミスはそのリクエストに対するレスポンスを表す Response で解決します。

と、あるようにネットワークからデータを取得できるメソッドとなってます。
(*昔は、[XMLHttpRequest](https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest)を使ってたみたいですが、現在ではfetchを推奨しているようです。)

### 実装内容
実装内容としては以下のフローにしていきたいと思います。
#### 1. プロジェクトを作成
```
npx create-react-app my-app --template typescript
```
#### 2. ダウンロードするファイを作成
今回はプロジェクト内に/public/documentを作成して、その中にDLファイルを作成しておきます。
![スクリーンショット 2023-09-16 12.38.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2239673/f588f9ef-30bc-7d59-ce9c-8faf7eefd4f7.png)
#### 3. コード記述
適当に「csvダウンロード」と「Excelダウンロード」ボタンを作って、ボタン押下で「fetch」させ、各種ファイルをダウンロードする内容の実装にしていきます。

<details><summary>サンプルコード</summary>


```typescript:src/index.tsx
export const Download = () => {
  // Excelをfetchで取得
  const onClickDownloadExcel = async () => {
    const response = await fetch("/document/sample.xlsm", { method: "get" });
    if (response.ok) {
      const blob = await response.blob();
      const url = window.URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = "sample.xlsm";
      a.click();
    }
  };
  // CSVをXMLHttpRequestで取得
  const onClickDownloadCsv = async () => {
      // 処理内容はファイル名が.csvになるだけで、Excelと同じ
  }
  return (
    <Container component="main" maxWidth="xs">
      <CssBaseline />
      <div style={{ margin: "150px" }} />
      <Button
        type="submit"
        fullWidth
        variant="contained"
        onClick={onClickDownloadExcel}
      >
        Excelダウンロード
      </Button>
      <div style={{ margin: "15px" }} />
      <Button
        type="submit"
        fullWidth
        variant="contained"
        onClick={onClickDownloadCsv}
      >
        CSVダウンロード
      </Button>
    </Container>
  );
}
```
</details>




#### 実際の画面
![スクリーンショット 2023-09-16 13.11.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2239673/c4286501-36f1-afb8-79f4-34fcb22c7a44.png)
### 解説
1. まずは`async/await`を使って`fetch`の結果を待ちます。
2. `resuponse.ok`が`true`ならダウンロードを開始します。(elseでエラー時の処理を記述した方が良さそう:rolling_eyes:) 
3. データの取得に成功したら、レスポンスタイプを``blob``にして受け取ります。
4. あとは`<a>`タグを生成してダウンロードさせます。

### 最後に
以上が簡単なファイルダウンロードの実装でした。
また、今回初めて`fetch`メソッドを使ってみましたが、POSTパターンや第2引数の`options`も便利そうなパラメーターがあったので、今後触ってみたいなと思いました。
### 参考
* [fetch](https://developer.mozilla.org/ja/docs/Web/API/fetch)
* [Fetch](https://ja.javascript.info/fetch)
* [XMLHttpRequest](https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest)
DドライブのHDD換装をWindows再インストールなしで行った話

# はじめに

Cドライブを換装した話はネット上に良くあるので、今回は以下のようなDドライブを換装した話をします。

- システムドライブではない（Windowsがインストールされていない）
- アプリケーションがインストールされている
- Dropbox フォルダを含んでいる
- デスクトップ、ドキュメントなどが配置されている

上記のような条件があったため、今回は以下の手順を行いました。

1. Macrium Reflect Free Edition でドライブをクローンする
2. Windows をセーフモードで起動する設定にし、電源を切る
3. 古い HDD を取り外し、新しい HDD を SATA ケーブルで接続する
4. セーフモード（コマンドプロンプト）で起動し、diskpart でドライブレターを変更する

セーフモードでドライブレターを変更したのは、自動起動するサービスやアプリケーションがどのように Dドライブにアクセスしているか、そのパターンが詳しく分からなかったため、なるべく不具合の発生を抑えたかったからという理由になります。コマンドプロンプトであれば、デスクトップやドキュメントへのアクセスもないかなと思ったのでこのようにしました。

# 1. ドライブをクローンする

クローンするだけですのでどのソフトを使っても問題ないと思います。下の画像は Macrium Reflect Free Edition のスクリーンショットになります。ただ、EaseUS Todo Backup Free ではクローン機能は2023年現在は有料化されていて出来ませんでした。

今回はクローン先のディスクの容量が異なっていたので、自動でパーティションサイズを拡張する設定にします。

また、SATA ケーブルが手元になかったので、SATA to USB 3.0 変換ケーブルを使用してクローンしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78152/fc8ae704-ac3c-a3dd-b280-cc054ea0e2fc.png)

# 2. Windows をセーフモードで起動する設定にし、電源を切る

次回起動時にセーフモードを選べるように Windows の設定を変更し、PC の電源を切ります。Windows 10 の場合は以下の記事の通りの手順で設定できます。

https://support.microsoft.com/ja-jp/windows/windows-10-%E3%81%AE%E3%82%BB%E3%83%BC%E3%83%95-%E3%83%A2%E3%83%BC%E3%83%89%E3%81%8A%E3%82%88%E3%81%B3%E3%81%9D%E3%81%AE%E4%BB%96%E3%81%AE%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E8%A8%AD%E5%AE%9A%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B-7551aac3-21b5-c646-06ee-31e0e6a5e4dc

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78152/243488be-83e3-de13-5b2a-0eb06d78155e.png)


# 3. 古い HDD を取り外し、新しい HDD を SATA ケーブルで接続する

最終的に新しい HDD は PC ケース内に収めたいので、このタイミングで物理的に HDD を差し替えます。

# 4. セーフモード（コマンドプロンプト）で起動し、ドライブレターを変更する

PC の電源を入れると起動方法を聞かれるので、「セーフモードとコマンドプロンプト」を選択します。

するとコマンドプロンプトが起動するので、DISKPART コマンドを使用してドライブレターを変更します。

https://qiita.com/nkojima/items/1f4c61262156a98c58e3

```
C:\Windows\system32>diskpart

(中略)

DISKPART> list volume

  Volume ###  Ltr Label     Fs   ...
  ----------  --- --------- ----
  Volume 0     C  Cドライブ  NTFS ...
  Volume 1     H  ボリューム NTFS ...
```

新しい HDD のドライブレターが `H:` になっているので、これを `D:` にします。

```
DISKPART> select volume=1

ボリューム 1 が選択されました。

DISKPART> remove letter=H

DiskPart はドライブ文字またはマウント ポイントを正常に削除しました。

DISKPART> assign letter=D noerr

DiskPart はドライブ文字またはマウント ポイントを正常に割り当てました。

DISKPART> list volume

  Volume ###  Ltr Label     Fs   ...
  ----------  --- --------- ----
  Volume 0     C  Cドライブ  NTFS ...
* Volume 1     D  ボリューム NTFS ...
```

この後 exit で終了すると画面が閉じてしまい、電源の切り方が分からなかったので、PC の電源ボタン短押しで電源を切りました。

以上で作業は完了になります。必要に応じてボリュームラベルなども変更を行ってください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78152/dea05b92-f931-b32b-0e1b-b20193924601.png)

お疲れ様でした！
discord.pyでユーザーごとに固有の値を保存する

# 初めに
discord.pyで、ユーザーごとに固有のデータ(戦績など)を保存したくなったので作りました。

# コード
まず普通にjsonファイルを読み込みます。
```py:main.py
# memberごとになにかしらのデータを保存する
with open("member.json", "r", encoding="utf-8") as json_file:
    member_data = json.load(json_file)
```
つぎに、メッセージが入力されたとき、ユーザーidを用いてすでに登録されたメンバーなのか確かめます。
```py:main.py
@client.event
async def on_message(message):
    global member_data
    if message.author == client.user:
        return

    # 新たなメンバーがいたら登録する、名前が変わったら更新する
    # 要注意！！message.author.id は int型、jsonファイルのmember_dataを検索するときの、keyはstr型、python側では関係ない
    if str(message.author.id) not in member_data:
        new_data = {
            "name": message.author.name,
            "data": [
                {
                    "name": "a_history",
                    "value": 0
                },
                {
                    "name": "b_history",
                    "value": 0
                }
            ]
        }
        member_data[message.author.id] = new_data

        with open("member.json", "w", encoding="utf-8") as json_file:
            json.dump(member_data, json_file, ensure_ascii=False, indent=4)
        with open("member.json", "r", encoding="utf-8") as json_file:
            member_data = json.load(json_file)
        print(message.author.id, message.author.name, "を新たに登録しました")
    elif message.author.name != member_data[str(message.author.id)]["name"]:
        member_data[str(message.author.id)]["name"] = message.author.name

        with open("member.json", "w", encoding="utf-8") as json_file:
            json.dump(member_data, json_file, ensure_ascii=False, indent=4)
        with open("member.json", "r", encoding="utf-8") as json_file:
            member_data = json.load(json_file)
        print(message.author.id, message.author.name, "の名前を更新しました")
```
member.jsonは以下のようになっています。用途によって書き換えてください。

```json:member.json
{
    "123456789012345": {
        "name": "hoge",
        "data": [
            {
                "name": "a_history",
                "value": 0
            },
            {
                "name": "b_history",
                "value": 1
            }
        ]
    },
    "123456789012346": {
        "name": "huga",
        "data": [
            {
                "name": "a_history",
                "value": 2
            },
            {
                "name": "b_history",
                "value": 30
            }
        ]
    }
}
```
【AWS】Amazon Linux 2023 AMIでpythonサーバーを起動する

## 準備

Amazon Linux 2023 AMIをベースにEC2インスタンスを作成し、ssh接続する。

## やり方

Amazon Linux 2023 AMIにはデフォルトでpython3がインストールされている。

```bash
$ python3 --version
Python 3.9.16
```

下記コマンドでhttpサーバーを起動する

```bash
$ python3 -m http.server 3000
Serving HTTP on 0.0.0.0 port 3000 (http://0.0.0.0:3000/) ...
```

python2では下記コマンドで起動する

```bash
$ python --version

$ python -m SimpleHTTPServer [ポート番号]
```

Python 2にあったSimpleHTTPServerという標準ライブラリのモジュールが、Python 3ではhttp.serverというモジュールに統合されたとのこと（[Python 3ではSimpleHTTPServerではなくhttp.serverを使う](https://tacamy.hatenablog.com/entry/2017/01/04/155137)）。
【AWS】sshで多段接続できない

## やったこと

図のようにAWS上のPublic subnet内に構築したEC2 bastionからPrivate subnet内に構築したEC2インスタンスに多段接続しようとした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2907902/ec40b597-1e3c-9c3c-cb55-b881b578daf7.png)


## エラー内容

下記エラーが表示された。

```bash
$ ssh web01
channel 0: open failed: connect failed: Connection timed out
stdio forwarding failed
kex_exchange_identification: Connection closed by remote host
Connection closed by UNKNOWN port 65535
```

## 原因

<font color="red">EC2 bastionのセキュリティグループにデフォルトセキュリティグループを適用していなかった。</font>

デフォルトセキュリティグループは全てのインバウンドトラフィックを許可する設定になっており、Private subnet内のEC2インスタンスには適用していたため、それでssh接続できるものと思っていた。

しかし、デフォルトセキュリティグループは`このセキュリティグループに割り当てられたすべてのリソースからのインバウンドトラフィックを許可します。`([デフォルトのセキュリティグループ](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/default-custom-security-groups.html#default-security-group))とのことで、通信を行いたいリソース同士に適用する必要があった。


## 解決法

EC2 bastionのセキュリティグループにデフォルトセキュリティグループを適用した。

Actions > Security > Change security groups から追加できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2907902/50eac173-37ff-665f-0760-9460e3548486.png)

もし、デフォルトセキュリティグループを追加しない場合は、Private subnetのEC2インスタンスのセキュリティグループでEC2 bastionからのsshのインバウンドルールを追加することでも通信可能。
WSL ってどうやってインストールするの？？

# how to install `wsl2`

1. windows の機能の有効化または無効化
    1. Linux 用 Windows サブシステムを有効化
        ![Windows の機能のキャプチャ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445915/789f75bd-bd0f-d5a7-36a4-d51aa55e7324.png)
1. install applications from `Microsoft Store`
    1. `Ubuntu`
        ![Ubuntu](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445915/2b25203d-77d9-e95b-ea4f-e18dfed4c70d.png)
    1. `vscode`
        ![vscode](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445915/2fff9b1e-f59a-902d-e1d2-95ba712c4d96.png)
1. `powershell` で実行
    1. `ubuntu` をディストリビューションとしてインストール

        ```wt
        wsl --install -d Ubuntu
        ```

        ![実行結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445915/73ad0cc0-0d8d-e82f-22a0-a086077b7d7a.png)

    1. 文字化けエラーが出たのでアプデして対処

        ```wt
        wsl --update
        ```

        ![実行結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445915/f1ee79bc-cfa7-d350-7525-48d0aeaf7da1.png)

    1. 任意のユーザー名・パスワードを設定

        ![実行結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445915/f39db321-21e2-8462-2537-8489f4ad29f8.png)

    1. `wsl` 内に入っていることを確認

        ```bash
        pwd
        ll
        ```

        ![実行結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445915/dacb0dfd-04eb-d4c9-e7f5-a249b6d0200d.png)

    1. `wsl` のバージョンが2であることを確認

        1. wsl から退出

            ```bash
            exit
            ```
        
        1. `powershell` で確認

            ```wt
            wsl -l -v
            ```

        ![実行結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445915/17edb182-3fb2-e74d-168b-1ec199e2f328.png)

1. `vscode` で開いてみる
    `F1` or `ctrl`+`shift`+`p` でコマンドパレットを開き、
    `>wsl: Connect to WSL` より `wsl` を起動する

    ![wsl起動](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445915/11b17b87-3b9a-2c39-7f7b-129188caf8cb.png)
    ![実行結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445915/7e326bf2-16a7-fc92-1b0c-26ab8f27ea0a.png)

1. `vscode` のターミナルを開く
    `ctrl`+`shift`+`` ` ``で新しいターミナルを開くと `wsl` のターミナル操作ができて幸せになれます。
    ![実行結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445915/60c60a5f-3b16-4d9d-bdc6-03b59b48345c.png)

## 参考サイト

- [以前のバージョンの WSL の手動インストール手順](https://learn.microsoft.com/ja-jp/windows/wsl/install-manual#step-1---enable-the-windows-subsystem-for-linux)
- [WSL を使用して Windows に Linux をインストールする方法](https://learn.microsoft.com/ja-jp/windows/wsl/install#step-4---download-the-linux-kernel-update-package)
- [WSL 開発環境を設定する](https://learn.microsoft.com/ja-jp/windows/wsl/setup/environment#set-up-your-linux-username-and-password)
C#でYAMLファイルを読み込みたい

# 1. はじめに
* C#でYAMLファイルを読み込んでクラスで扱えるようにしたい
* 共通的にユーティリティとして準備しておきたい

# 2. 開発環境
* C#
* .NET 6
* YAML
* Visual Studio 2022
* Windows 11

# 3. 事前準備
* NuGetより```YamlDotNet```をインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/4575562a-cc2b-8884-b97f-3caec3aca431.png)

# 4. ソースコード
## 4.1. YAML用ユーティリティ
```Csharp:YamlLoadUtil.cs
using System.Text;
using YamlDotNet.Serialization;

namespace Util
{
    public class YamlLoadUtil
    {
        // デシリアライザ設定
        private static readonly IDeserializer _deserializer;
        // エンコーディング設定
        private static readonly EncodingProvider _provider;
        private static readonly Encoding _encoding;

        static YamlLoadUtil()
        {
            // エンコーディングプロバイダ作成(Shift-JIS)
            _provider = System.Text.CodePagesEncodingProvider.Instance;
            _encoding = _provider.GetEncoding("shift-jis")!;

            // デシリアライザインスタンス作成
            _deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().Build();
        }

        /// <summary>
        /// YAMLファイルを読み込みオブジェクトを返却する
        /// </summary>
        /// <typeparam name="T">オブジェクト</typeparam>
        /// <param name="filename">YAMLファイル名</param>
        /// <returns>T; オブジェクト</returns>
        public static T Load<T>(string filename) where T : class
        {
            // YAMLファイルの読み込み
            var input = new StreamReader(filename, _encoding);

            // yamlデータのオブジェクトを作成
            var result = _deserializer.Deserialize<T>(input);

            // 結果を返却
            return result;
        }
    }
}
```

## 4.2. YAMLファイル
```YAML
- No: 1
  Name: "名前1"
  BirthDay: "1月1日"
  BloodType: "A"
- No: 2
  Name: "名前2"
  BirthDay: "2月2日"
  BloodType: "B"
```

## 4.3. YAML用クラスファイル
```Csharp
[ToString]
public class Foo
{
    public int No { get; set; }            //No
     public string? Name { get; set; }       //名前
     public string? BirthDay { get; set; }   //誕生日
     public string? BloodType { get; set; }  //血液型
}
```

## 4.4. （参考）ユーティリティを使用しない場合
```Csharp:
// テキスト抽出
var input = new StreamReader("yaml/Sample.yaml", Encoding.UTF8);

// デシリアライザインスタンス作成
var deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().Build();

// yamlデータのオブジェクトを作成
var deserializeObject = deserializer.Deserialize<List<Foo>>(input);

// デバッグ出力
deserializeObject.ForEach(x => Debug.Print(x.ToString()));
```

# 5. 参考文献

https://qiita.com/miwazawa/items/939dc4227475cf78672f

https://github.com/aaubry/YamlDotNet
【vue3, composionAPI】リアクティブな変数を定義する

 ## 概要
 リアクティブな変数を定義する方法がいくつかあるので整理した
 
 ## ref() もしくは reactive() を使用する
 ### ref() を使用する場合
 #### 特徴
 - template 内で参照する場合は.value をつけなくて良い
 - プリミティブ型、オブジェクトのどちらに対しても使用できる

 ### reactive() を使用する場合
 #### 特徴
 - 別のオブジェクトにラップされず、オブジェクト自体がリアクティブになる。そのため、常に .value が不要
 - プリミティブ型には使用できない
   - 以下の例だと、コンソールにエラーメッセージが出力される他、値の変更が検知されない

```vue
<script setup>
import { reactive } from 'vue'

const reactive_primitive = reactive(1) //value cannot be made reactive: 1
const reactive_object = reactive(["a", "b"]) // ok

console.log(reactive_primitive)
console.log(reactive_object)

</script>

<template>
  <div>
    <button @click="reactive_primitive++">reactive_primitive</button>
    <p>reactive_primitive : {{ reactive_primitive }}</p> <!-- クリックで値を変更しても反映されない -->
    <button @click="reactive_object.push('push!')">reactive_object</button>
  </div>
</template>
 ```

 ### どちらを使用するべき？
 reactive() では以下のような制約があることから、公式ドキュメントでは基本的に ref() の使用が推奨されている
 - reactive() ではプリミティブ型を保持できない
 - オブジェクト全体を置換できない
 - 分割代入できない

 参考 https://ja.vuejs.org/guide/essentials/reactivity-fundamentals.html#limitations-of-reactive

 ## 算出プロパティ
 ### 変数を用いてリアクティブな状態を宣言する場合
 ref(), reactive() に変数を渡した場合、戻り値は元の変数のプロキシとなるため、元の変数の変更は検知されない <br>
 元の変数の変更を検知したい場合は、computed() によって定義した算出プロパティを使用する
 - 以下の例では、ボタンを押す毎に x がインクリメントされるが、computed で定義した値だけが再計算される

```vue.js
<script setup>
import { ref, computed } from 'vue'
const x = ref(1)
const calculate_with_ref = ref(x.value)
const calculate_with_computed = computed(() => x.value + 1) // 算出プロパティの定義
</script>

<template>
  <div>
    <button @click="x++">x is {{ x }}</button>
    <p>ref : {{ calculate_with_ref }}</p>
    <p>computed : {{ calculate_with_computed }}</p>
  </div>
</template>
```
Rspec Capybaraでdatetime_fieldを入力する方法

## plan新規作成のテスト中

##### ここにcapybaraで自動入力させたい
```plan.index.erb
<%= f.datetime_field :start_time %>
```
##### これでは
```plans_spec.rb
fill_in 'plan_start_time', with: '2023-01-01 12:00:00'
```
##### こんな感じでうまく入力されない
capybaraでのスクリーンショット
![スクリーンショット 2023-09-16 12.29.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194180/a0c1d8b6-50ac-fdb7-5d5b-d03a1499bb8f.png)


##### ここでの質問を参考に
https://stackoverflow.com/questions/40304521/how-to-fill-in-a-datetime-local-field-with-capybara

##### これに変更
```plans_spec.rb
fill_in 'plan_start_time', with: "09202023\t0000a"
```
![スクリーンショット 2023-09-16 12.27.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194180/185a7d08-b733-9d1c-6fd6-f6d369a18973.png)

##### 入力されました
```
Plans_system
  Plan新規登録
    フォームの入力値が正常の場合
      Planの新規作成が成功し表とカレンダーのどちらにも表示されていること

Finished in 25.65 seconds (files took 14 seconds to load)
1 example, 0 failures
```
##### テストも通りました
Raspberry Pi用 4.01インチ ACeP 7色e-Paper ディスプレイ 640×400 を動かしてみた

# はじめに

# Raspberry Pi OS

Raspberry Pi Imager v1.7.5

Raspberry Pi OS (64-bit)

https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2023-05-03/2023-05-03-raspios-bullseye-arm64-lite.img.xz

Raspberry Pi 4B (4GB)

# 7色 Eインクディスプレイ

https://www.switch-science.com/products/7341

https://www.waveshare.com/wiki/4.01inch_e-Paper_HAT_(F)

# 手順

## SPIの有効化

```bash
sudo raspi-config
```

Interfacing Options -> SPI -> Yes を選択する。

再起動する。

```bash
sudo reboot
```

## Pythonライブラリのインストール

```bash
sudo apt update
sudo apt upgrade
sudo apt-get install python3-pip python3-pil python3-numpy
sudo pip3 install RPi.GPIO spidev
```

# サンプルデモのプログラムを動かす

```bash
sudo apt install git
git clone https://github.com/waveshare/e-Paper.git
cd e-Paper/RaspberryPi_JetsonNano/python/examples/
python3 epd_4in01f_test.py
```

![IMG_2470.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/d8dbfc10-7e83-8d31-cb80-f0d85ec19b7e.jpeg)

![IMG_2471.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/0aa57f7b-d07e-1b37-0112-68b56ee518cf.jpeg)

# 電子ペーパーへ画像を表示する

## パレット画像(テキスト形式)を用意する

```txt: palette.txt
# ImageMagick pixel enumeration: 7,1,255,srgb
0,0: (0,0,0)  #000000  black
1,0: (255,255,255)  #FFFFFF  white
2,0: (0,255,0)  #00FF00  lime
3,0: (0,0,255)  #0000FF  blue
4,0: (255,0,0)  #FF0000  red
5,0: (255,255,0)  #FFFF00  yellow
6,0: (255,128,0)  #FF8000  srgb(255,128,0)
```

## パレット画像(テキスト形式)をPNG形式へ変換する

ImageMagickのconvertコマンドを使用する。

```bash
sudo apt install imagemagick
convert palette.txt palette.png
```

(palette.png)
![palette2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/32fa37d9-4923-acaf-18cc-1d08d6b66d1f.png)


## Stable Diffusionで生成された画像ファイル(512x512)の画像サイズ(640x400)とディザー形式へ変換する

```bash
convert image.png -rotate '-90<' -dither FloydSteinberg -resize 640x400 -gravity Center -extent 640x400 -remap palette.png tmp.bmp
```

## 電子ペーパーへ表示する。

サンプルデモのライブラリを使用して、画像ファイル(640x400)を電子ペーパーへ表示します。

```bash
cp ../lib/waveshare_epd/epd4in01f.py ./
cp ../lib/waveshare_epd/epdconfig.py ./
```

epd4in01f.py の 下記1行を修正する。

```python
from . import epdconfig
↓
import epdconfig
```

image.py を作成して実行する。

```bash
python3 image.py
```

```python: image.py
#!/usr/bin/python
# -*- coding:utf-8 -*-
import sys
import os
import logging
import epd4in01f
import time
from PIL import Image,ImageDraw,ImageFont
import traceback

logging.basicConfig(level=logging.DEBUG)

try:
    logging.info("Start")
    epd = epd4in01f.EPD()
    logging.info("init and Clear")
    epd.init()
    epd.Clear()
    
    logging.info("read tmp.bmp file")
    Himage = Image.open('tmp.bmp')
    epd.display(epd.getbuffer(Himage))
    time.sleep(3)
    
    logging.info("Goto Sleep...")
    epd.sleep()
    
except IOError as e:
    logging.info(e)
    
except KeyboardInterrupt:    
    logging.info("ctrl + c:")
    epd4in01f.epdconfig.module_exit()
    exit()
```

![IMG_2473.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/cac5b285-2c0a-c924-ba07-6f398edd058d.jpeg)
Pythonでlist.index()メソッドの実行速度が気になったので測定してみた

## list.index()ってどれくらい早いの？

Pythonのリスト（配列）の要素のインデックス、つまり、その要素が何番目に格納されているかを取得するにlistの`index()`メソッドを使う。

```python
>>> [10,20,30,40,50].index(20)
1
```

これがどのくらいの実行速度か気になったので測定してみた。

## 測定環境
```shell
python3 --version
Python 3.10.11
```

## 測定対象
他の方法と比較した方が分かりやすいので、いくつかと比較してみる。

- 比較対象
  - 線形探索(linear_search)
  - list.index (index_search) <- 今回気になるヤツ
  - 二分探索(binary_search)
  - bisectライブラリ(bisect_search)

bisectは挿入位置を見つけるためのライブラリだが、要素自体のインデックス取得もやれるので候補に入れてみる。


## 測定内容
0 <= n < 50000の値が昇順に格納された配列から、すべての値のindexを見つけ出す速度を測定する。
つまり50000回インデックスの取得を実行する。
見つからない場合はテストケースに入れない。

## コード

```python3
import bisect
import time


def linear_search(arr: list[int], target: int):
    for i in range(len(arr)):
        if arr[i] == target:
            return i
    return -1


def index_search(arr: list[int], target: int):
    try:
        return arr.index(target)
    except ValueError:
        return -1


def binary_search(arr: list[int], target: int):
    left = 0
    right = len(arr) - 1
    while left <= right:
        mid = (left + right) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] > target:
            right = mid - 1
        elif arr[mid] < target:
            left = mid + 1
    return -1


def bisect_search(arr: list[int], target: int):
    index = bisect.bisect_left(arr, target)
    if index != len(arr) and arr[index] == target:
        return index
    else:
        return -1


def keisoku(search):
    ELEMENT_COUNT = 50000
    arr = [i for i in range(ELEMENT_COUNT)]

    start = time.time()
    for target in range(ELEMENT_COUNT):
        search(arr, target)
    end = time.time()

    print(f"{search.__name__: <13}: {end - start}")


if __name__ == "__main__":
    keisoku(linear_search)
    keisoku(index_search)
    keisoku(binary_search)
    keisoku(bisect_search)
```

`keisoku`関数はsearch関数を実行して、実行速度を標準出力するだけのWrapper。

## 結果
```python3
linear_search: 56.06361961364746
index_search : 11.071388006210327
binary_search: 0.1294879913330078
bisect_search: 0.022607803344726562
```

Python上で実装した線形探索より**約5倍**早い。結構早い。
これは`list.index()`がCPythonで実装されているからだろうけども、実装コード自体は公開されていないのか、見れない（場所知ってる人教えてください）。
https://github.com/python/cpython/blob/main/Objects/listobject.c

二分探索よりはかなり遅い。`list.index()`は配列がソートされていることを前提にしていないので当然。二分探索はソート済みの配列でないとサーチ自体できない。
とはいえ、速度差があるのは事実なので、配列がソートされているならば二分探索を自分で実装してでもやったほうが早い。

自分で実装してでもと言ったが、それならば`bisect`を使った方がいい。
`binary_search`と`bisect_search`でも5倍以上差がある。これも`bisect`は処理系が`CPython`だから。
下記のbisectの実装を見る限り、実装自体は上記`binary_search`のコードとさほど変わらない。

https://github.com/python/cpython/blob/main/Lib/bisect.py#L74-L107

# まとめ
- list.index()はまぁまぁ早い。CPythonだから。
- とはいっても二分探索よりは遅い。Pythonで実装した二分探索よりも遅い。
- 配列が巨大でソート済前提ならば`bisect`は有効な選択肢
【ChatGPT無】表現方法の指定による出力の違いを見ます。


　どうも、カーブミラーです。

　今回は、表現方法による出力の違いを見ていきます。アイディア出しにどうぞ。

:::note info
本記事は、ChatGPT（無料版）で
行なっております。GPT4での確認
はできておりません。あしからず。
:::

　本題に入る前に。

　Google SGEをご使用の方へ。
　　Search Labsの有効無効を
　　　確認してください。

　左上の三角フラスコマークを
　　タップすれば、
　　　確認できます。

　これが、オフになっている
　　可能性があります。

　おそらく、
　　一定期間で、
　　　オフになるのでは
　　　　ないかと思われます。
***
　さて、表現方法を
　　どのように変えたら
　　　どのように変わるのか、を
　　　　見てみたいと思います。

　単純に、
　　アイディアを求めても、
　　　平凡なものばかりですよね。

　欲しいものには、
　　届きません。

　十人十色の
　　アイディアが
　　　欲しいんですけどね。

　そこで、
　　表現方法を
　　　指定してみて、
　　　　どう変化するか、を
　　　　　見てみます。

　まずは、
　　基本となるPromptと
　　　その出力です。
***
***User***
キャッチコピーを考えてください。
箇条書き（説明不要）でお願いします。
ものは、化粧水です。

***ChatGPT***
もちもち肌への第一歩
肌に溺れるうるおい
自然美肌の秘密
輝く素肌へのシンプルな選択
肌を愛し、肌が愛するもの
***
　これをベースに
　　Promptを書きます。
　　　上記の出力を
　　　　比較するために、
　　　　　Promptに組み込みます。

　まずは「過激な表現」。
***
***User***
キャッチコピーを考えてください。
箇条書き（説明不要）でお願いします。
ものは、化粧水です。
過激な表現でお願いします。

以下の内容を変更してください。
・もちもち肌への第一歩
・肌に溺れるうるおい
・自然美肌の秘密
・輝く素肌へのシンプルな選択
・肌を愛し、肌が愛するもの

***ChatGPT***
1. 肌の救世主、美の真打者
2. うる肌革命、今始まる
3. 超極上！肌への究極の愛情注入
4. 肌が叫ぶ！極上の美容液登場
5. 肌の秘密兵器、最高峰登場
***
　4番は、なんか痛そうw

　さて、次に「やさしい表現」。
***
***User***
キャッチコピーを考えてください。
箇条書き（説明不要）でお願いします。
ものは、化粧水です。
やさしい表現でお願いします。

以下の内容を変更してください。
・もちもち肌への第一歩
・肌に溺れるうるおい
・自然美肌の秘密
・輝く素肌へのシンプルな選択
・肌を愛し、肌が愛するもの

***ChatGPT***
1. 自然な美しさへの扉を開く
2. しっとり美肌を手に入れよう
3. 肌に寄り添う美容の魔法
4. きらめく素肌への一歩
5. 肌への愛が実る美しさ
***
　やさしさを
　　感じられますね。

　さて、
　　最後に「冗談ぽい表現」。
***
***User***
キャッチコピーを考えてください。
箇条書き（説明不要）でお願いします。
ものは、化粧水です。
冗談ぽい表現でお願いします。

以下の内容を変更してください。
・もちもち肌への第一歩
・肌に溺れるうるおい
・自然美肌の秘密
・輝く素肌へのシンプルな選択
・肌を愛し、肌が愛するもの

***ChatGPT***
1. "ぷるぷる肌を手に入れて、モチモチに挑戦！"
2. "肌にジャブとハグ、ウルウル感を満喫しよう！"
3. "秘密は、自然美肌にアリ！"
4. "素肌をブライトンアップ、シンプルな美の選択！"
5. "肌愛のプロ、肌との愛の物語"
***
　冗談ぽい？

　妙に、
　　ラップ調？

　でも、
　　なくもないキャッチコピーかも。
***
　さて、
　　こうして表現を
　　　変えてみたわけですが、
　　　　いかがだったでしょうか。

　これは、
　　出力の条件を
　　　絞り込んだ結果です。

　つまり、
　　どんなアイディア出しも
　　　きちんとChatGPTに
　　　　条件として、提示しないと
　　　　　平凡なものしか
　　　　　　出力されない、
　　　　　　　ということです。

　表現の仕方は、
　　上記以外にも
　　　たくさんあります。

　それらを探って、
　　良いアイディアを
　　　求めてください。

　以上。
【SwiftUI】角丸ボタンを作る。

備忘録

# 背景
下記のAPIで角丸ボタン作れるみたいだが、Deprecatedになっている
https://developer.apple.com/documentation/familycontrols/familyactivityiconview/cornerradius(_:antialiased:)

そのため、角丸ボタンを他の方法で作ったけど少し時間が掛かったのでQiitaに残しておく

# ソースコード

```Swift
struct RoundedRectangleButton: View {
    // 各パラメータ
    var text: String
    var textColor: Color
    var backgroundColor: Color
    var fontWeight: Font.Weight
    var cornerRadius: CGFloat
    var width: CGFloat
    var height: CGFloat
    var action: () -> Void
    
    var body: some View {
        Button(action: { action() }, label: {
            ZStack(content: {
                RoundedRectangle(cornerRadius: cornerRadius)
                    .fill(backgroundColor)
                    .frame(width: width, height: height)
                
                Text(text)
                    .foregroundColor(textColor)
                    .fontWeight(fontWeight)
            })
        })
    }
}

struct HogeView: View {
    var body: some View {
    // do something...

    RoundedRectangleButton(text: "リセット",
        foregroundColor: .white,
        backgroundColor: .red,
        fontWeight: .semibold,
        cornerRadius: 10,
        width: view.size.width / 2,
        height: 48) {
            // ボタンアクション
        }
    }
}
```

下記のようなボタンが作れるようになる
![IMG_0832.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743730/2b41609b-6185-521f-0f08-b40037c8cd0a.jpeg)
terraform開発でコマンド実行時に「No such file or directory」が表示された場合


## 事象
久しぶりにTerraform学習のためTerraformコマンドを実行したところ以下のようなエラーが表示されました。
```
$ terraform -v
/usr/local/Cellar/tfenv/3.0.0/lib/tfenv-exec.sh: 行 43: /usr/local/Cellar/tfenv/3.0.0/versions/0.14.6/terraform: No such file or directory
```

なぜかterraformのバイナリが削除され、terrafromコマンドが実行できない状態でした。
## 環境
Mac 12.4
tfenv 3.0.0

## 解決
対象のバージョンを一度アンインストールして、再インストールして解決しました。
```
$ tfenv uninstall 0.14.6
$ tfenv install 0.14.6
```
LeetCodeのEvaluate Reverse Polish Notation解いてみた

# 始めに
時間はかかったがMedium問題を初見で解けたのでまとめてみる。
LeetCodeを使い始めて1ヶ月だが実力不足を感じる日々
同じようにもがいてる人の一助になれば幸いです

ちなみにより良い解法は存在すると思うので色々とコメント頂けると勉強になります！


# 問題
https://leetcode.com/problems/evaluate-reverse-polish-notation/description/

問題は**逆ポーランド記法**の配列を計算して返す関数の作成
逆ポーランド記法？？と思った方もいると思うので軽く解説
```
["2","1","+","3","*"]
↓
(2 + 1) * 3 = 9
```
上記のように計算対象の後に演算子が来るようなものを逆ポーランド記法という。
逆ポーランド記法というのは後置記法とも呼ばれ、私たちが馴染みある記法は中置記法というらしい

この問題に出会わなければ知らなかった...


# 考察
こんな感じでスタックを使い、順番にオペランドをスタックに追加していき、直前の値と演算子で計算していけばいけそう
```
["2","1","+","3","*"]
↓
[2, 1] -> 2 + 1
↓ 3を追加
[3, 3] -> 3 * 3

答え9
```
- スタックを使い効率的に解く
- オペランドと演算子の判別
- 演算子の処理
- 除算の取り扱い

上記のポイントを意識しながら解いていく


# 解法
## オペランドと演算子の判別
演算子以外はスタックに追加していく
```python
stack = []
for token in tokens:
    if token not in  ["+", "-", "*", "/"]:
        stack.append(token)
```

## 各演算子の結果をスタックに追加
スタックの直前の値ともう一つ前の値をpopして各演算子で計算
この時、引き算と割り算のみx,yの順番を気をつける必要がある
```python
elif token == "+":
    x,y = int(stack.pop()), int(stack.pop())
    stack.append(x + y)
elif token == "-":
    x,y = int(stack.pop()), int(stack.pop())
    stack.append(y - x)
elif token == "*":
    x,y = int(stack.pop()), int(stack.pop())
    stack.append(x * y)
elif token == "/":
    x,y = int(stack.pop()), int(stack.pop())
    stack.append(int(y / x))
```

問題文にもある通り、除算の時は切り捨てになるようにする
```python
stack.append(int(y / x))
```

あとはスタックの先頭をpopすればOK
いかに全文載せておきます
```python
class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        stack = []
        for token in tokens:
            if token not in  ["+", "-", "*", "/"]:
                stack.append(token)
            elif token == "+":
                x,y = int(stack.pop()), int(stack.pop())
                stack.append(x + y)
            elif token == "-":
                x,y = int(stack.pop()), int(stack.pop())
                stack.append(y - x)
            elif token == "*":
                x,y = int(stack.pop()), int(stack.pop())
                stack.append(x * y)
            elif token == "/":
                x,y = int(stack.pop()), int(stack.pop())
                stack.append(int(y / x))

        return int(stack.pop())
```


# 感想
逆ポーランド式とは初対面ですが、　それほど難しい訳では無かったので初見で解けました。
Mediumは初見で突破できる問題が少なかったので多少は成長したのかも？
この問題でLeetCodeで解いた問題数が50問を超えたので振り返りながら精進してみよう