OmniAICreator/Qiita-1.07M huggingface dataset:
VScodeのユーザースニペットを生成してくれるシェルスクリプト

Python の import 部分って色々なスクリプトで使い回すこと多いですよね。
**VScode**ではよく使うパターン文を**ユーザースニペット**というjsonファイル(Pythonなら`python.json`)にあらかじめ定義しておくことで、いちいち該当箇所をコピー&ペーストせずに使えて便利！
なのですが、、そもそもそのjson形式に整形するところ（文字列への"" や区切りの , を追加する）にちょっと煩わしさを感じていました。

そこで、登録したいパターン文を貼り付けるだけでVS Codeのユーザースニペットのjson形式に変換してくれるシェルスクリプトを作成しました（実際には ChatGPT に作ってもらいました笑）。

```shell:generate_snippet.sh
#!/bin/bash

# prefix and description can be changed as you like
prefix="my_snippet"
description="This is my custom snippet"

# read multiline input from stdin
IFS= read -d '' -r input

# convert input to an array of lines
lines=()
while IFS= read -r line; do
  lines+=("$line")
done < <(printf '%s' "$input")

# generate the snippet in JSON format
json=$(jq -n --arg prefix "$prefix" --arg description "$description" --rawfile body <(printf '%s\n' "${lines[@]}") '{
  ($prefix): {
    prefix: $prefix,
    body: $body | split("\n"),
    description: $description
  }
}')

# print the JSON snippet
printf '%s\n' "$json"


```

このスクリプトは入力としてテキストを受け取り、それをVS Codeのユーザースニペット形式に変換します。変換されたスニペットはJSON形式で出力されます。

このスクリプトを使用するには **jq** コマンドが必要となります。jqはJSONを操作するためのコマンドラインツールで、多くのLinuxディストリビューションやmacOSで利用できます。

まず`chmod 755 ./generate_snippet.sh`でシェルスクリプトに実行権限を与えてあげます。
スクリプトは標準入力からテキストを受け取るので以下のように使用します。

```
$ ./generate_snippet.sh <<EOF
> # ここに登録したいパターン文を貼り付ける(以下のように複数行もOK)
> import os,sys
> import glob
> import numpy as np
> import matplotlib.pyplot as plt
> EOF # 最後にEOFと打ってエンターを押す
```

すると以下のようなjson形式に整形された出力されるので、これをコピーしてご自身のVS Codeのユーザースニペットに貼り付けてやればOKです。（`prefix`部分等は適宜変更して下さい）
```
{
  "my_snippet": {
    "prefix": "my_snippet",
    "body": [
      "import os,sys",
      "import glob",
      "import numpy as np",
      "import matplotlib.pyplot as plt",
      ""
    ],
    "description": "This is my custom snippet"
  }
}
```
それでは良いVS Codeライフを〜
Goでファイルからフォルダを自動生成

下書きのまま放置してたやつを公開します。
2022年の4月の情報です

# 初めに
初心者がのたのたしながらフォルダを作る話です。
突っ込みどころ等ご了承ください。


# きっかけ
私はとある部活で幹部をしていたのですが、部員全員分のデータ保存フォルダを学校のNASに作る必要があり、手動がめんどくさかったので作りました。


# やりたいこと
テキストファイルを読み込んでフォルダを一括生成。

# プログラム
先に結論から
~~~Go:main.go
func main() {
	// -1-
	file := input("ファイル名を拡張子も含めて入力してください。(.txt)")
	// ファイル形式チェック
	fcheck := strings.Contains(file, ".txt")
	if fcheck == false {
		fmt.Println("無効なファイル形式です。")
		goto Start
	}
	// -2-
	// フォルダを作る
	for scanner.Scan() {
		fmt.Println(num, ".", scanner.Text())
		num++
		er := os.Mkdir(scanner.Text(), 0777)
		if er != nil {
				err(er)
			ers++
		}
	}
}

func input(msg string) string {
	scan := bufio.NewScanner(os.Stdin)
	fmt.Print(msg + ":")
	scan.Scan()
	return scan.Text()
}
~~~

~~~:実行結果
ファイル名を拡張子も含めて入力してください。(.txt):名簿.txt
1 . 織田信長
2 . 豊臣秀吉
3 . 徳川家康
4 . フランシスコ・ザビエル
5 . 西郷隆盛
6 . 大久保利通
7 . 木戸孝允
~~~
main.goと同じ階層にフォルダができます。
それだけ。
Pythonでスイッチのプロコンの操作を取得する

プロコンがパソコンで動くと聞いたのでやってみました

# 環境

Windows 11 Home 22H2
Anaconda 23.1.0
Python 3.10.9
Visual Studio Code 1.77.0

# 完成品

https://github.com/fumikun/procon

![スクリーンショット 2023-04-03 203026.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/967873/e974d53e-6345-e8cc-9b94-ba2f558332ef.png)

:::note warn
任天堂が公式にサポートしているものではないので、自己責任でお願いします。
:::

# 参考

https://www.tenkaichi-hanseikai.com/entry/2022/10/18/153148

https://qiita.com/Kazuhito/items/403d84577cdff1a3ba91

↓プロコンの画像を使わせてもらいました

https://github.com/Brikwerk/nxbt
ローカルブランチを削除したいとき

Gitでプルリクを出し、ブランチがマージされた後にGithub上ではリモートブランチが削除されますが、vscode上のローカルブランチが削除されないときの対処法を記述したいと思います。

不要なリモートブランチを削除する方法
```shell
#ブランチを削除する
$ git branch -d BRANCH_NAM
```

```shell
#マージしていないブランチを削除する方法
$ git branch -D BRANCH_NAM
```

```-D```はまだマージされていないブランチも削除することができます。そのため、使用する場面としては誤って作成してしまったブランチを削除する際に使えます。

ちなみに、リモートブランチもvscode上から削除することができます。

```shell
$ git fetch --prune
#または
$ git fetch -p
```

是非、vscodeのターミナル上で実行してみてください
JavaScriptのコールバック関数について

コールバック関数とは、関数の中で、引数として呼び出される別の関数を指す。
下記の例では、関数displayに引数として呼び出されている関数callbackFunctionをコールバック関数と呼ぶ。

```.js
function display(callbackFunction){
    const calcResult = callbackFunction(2);
    console.log(calcResult);
}

function callbackFunction(number = 3){ //number = 3は、numberの初期値として３を代入するという意味
    return number * 2;
}

debugger; //ブレークポイント。実行時ここで一度処理が止まる。dev tool のstep intoなどで次の処理にすすむ。

display(callbackFunction);
```

この例では、display(callbackFunction);が実行されてからコンソール上に結果が表示されるまでに、次のような処理が行われている。

①引数としてcallbackFunctionを定義した関数displayを定義。
（この時、displayによって呼び出されるcallbackFunctionをコールバック関数と呼ぶ）

②関数callbackFunctionを初期値3の引数numberを指定して定義


③-1display(callbackFunction)によって、display関数に処理が移る
③-2const calcResult = callbackFunction(2)により、callbackFunction関数に引数２が渡される
③-3callbackFunction関数のreturn number * 2により、最終的に数値として4が返される

④display関数内の処理に戻り、const calcResult = callbackFunction(2)に4という数値が格納される

⑤console.log(calcResult);により、コンソールに４が表示される。
【SwiftUI】タップした座標を取得する

# はじめに
`onTapGesture`に`coordinateSpace`という引数が指定できるようになってました。
タップした位置の座標を取得できるようです

# 実装
```swift
import SwiftUI

struct ContentView: View {
    @State private var location: CGPoint? = nil
    
    var body: some View {
        VStack {
            Text(location.map { "\($0.x), \($0.y)" } ?? "No location")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .onTapGesture(coordinateSpace: .local
        ) { location in
            self.location = location
        }
    }
}
```

タップした位置の座標を取得することができました
![Simulator Screenshot - iPhone 14 - 2023-06-04 at 22.02.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/db83352f-efdc-5a7f-e7ea-a5e02fef50c7.png)

# おわり
これを使えば簡単なゲームは作れそうです
URLComponentsを使って、URLを変更する方法

## はじめに
こんにちは!
iOSエンジニアになることを目指して、Swiftの勉強しておりますそこら辺の大学2年生です！

今回は、タイトルにある通りにURLComponentsを使って、URLを変更したいと思います。
ちなみに、なかなかURLを変更したいと思う場面は少ないと思いますので、どういった状況でそのような場面に遭遇したのかというところから軽く説明できればと思います。

## 具体的な場面
個人開発をしているときに、下記の写真のようなimageのURLを取得し、画像のImageを表示しておりました。
```
https://thumbnail.image.rakuten.co.jp/ran/img/2001/0009/784/873/119/328/20010009784873119328_1.jpg?_ex=64x64
```
しかし、解像度が低い(_ex=64x64)ことにより、質の悪い画像が表示されてしまうという現象が起きてしまいました。
この解決方法として、解析度を表している部分だけを変更できればいいなと思い、実装してみました

## 実装
下記のようなメソッドを用意します

```swift
private func imageUrl(_ string: String) -> URL? {
    guard let imageUrl = URL(string: string) else {
        return nil
    }
    var components = URLComponents(url: imageUrl, resolvingAgainstBaseURL: true)

    let queryItems = components?.queryItems?
        .map {
            var copy = $0
            if copy.name == "_ex" {
                copy.value = "512x512"
            }
            return copy
        }
    components?.queryItems = queryItems
    return components?.url
}
```
### 簡単に説明
URLComponents(url, resolvingAgainstBaseURL)を使ってまずは初期化します。
その後、クエリの部分を実際に変更していきます。
個人的にポイントとなるのは、簡略引数名である$0から直接値を変更することはできないのでcopyという変数を作り、そこから変更してあげるところです、
これでこのメソッドを呼び出してあげればURLを変更することができます。
下記に使用例を乗っけておきます

### 使用例
```swift
AsyncImage(url: imageUrl(product.smallImage)) { image in
    image
        .resizable()
        .scaledToFit()
        .frame(maxWidth: .infinity, maxHeight: 120)
} placeholder: {
    ProgressView()
        .frame(height: 120)
}

```
実際に質の高い画像を表示することができました！！

## さいごに
ここまで、ご覧いただきありがとうございました🙇‍♂️
間違いやご指摘等ございましたら、ご教授していただけると幸いです。
これからもアウトプットして行きたいと思います。

## 参考 

https://developer.apple.com/documentation/foundation/nsurlcomponents/1416476-init
【Android】TextWatcherでEditTextの入力を監視する【Kotlin】

# TextWatcher
監視したいEditTextがあるクラスにTextWatcherクラスを継承することで、以下の三つのクラスを使ってそれぞれのタイミングでEditTextに変化が起きた時を冠することができます。
beforeTextChanged


|クラス|タイミング|
|:---|:---|
|beforeTextChanged|変化が起きる直前|
|onTextChanged|変化が起きた時|
afterTextChanged|変化が起きた後


余談ですが、３つのタイミングがありますが 細かく監視をしたい時以外はどれか一つ(afterTextChangedだけ)で問題ないと思います。
なので、TextWatcherを継承したinterfaceを使うことでもっと簡単に書くことができるみたいです。

https://qiita.com/aaaaki/items/86678967e9eb9f62da9b


# 実践


```
class MainActivity : AppCompatActivity(),TextWatcher {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val editText = findViewById<EditText>(R.id.edit_text)
        editText.addTextChangedListener(this)
// addTextChangedListenerないと監視が始まらないので注意

    }

    override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {

    }

    override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {

    }

    override fun afterTextChanged(p0: Editable?) {
        Toast.makeText(this,"変化後", LENGTH_LONG).show()
    }
```

# 参考
https://developer.android.com/reference/android/text/TextWatcher


https://akira-watson.com/android/textwatcher.html

https://qoopmk.hatenablog.jp/entry/2019/09/27/080000
【Bubble】受託開発なら全ページに埋め込みたいエラー処理

bubbleのTipsメモです

# 概要
bubbleのエラーの汎用処理です
受託開発では、エラーの処理をしっかりすることも求められます。
具体的に言うと、
「何かエラーが起きたときは画面にきちんと表示してほしい。
エラーメッセージそのままだとユーザが困るので、ユーザに対する動作も指示して欲しい」
という依頼です。

今回いい感じに処理できる方法を発見したので残しておきます。

## 完成イメージ図
エラーが起きたら画面の最上部に赤字で表示する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/30cba310-82a7-3a68-1918-524b96ae8716.png)

# Design
エラー表示の制御用Groupと、メッセージを表示するTextで構成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/88093f2b-2538-716d-1397-26a48d7d40b7.png)

## Group
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/0a1d5679-e958-4cbc-6f2c-c3cb95ce15a4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/38d80eee-316d-08c1-2780-71d27b8d9811.png)

## Text
Groupに与えられたTextを表示する。
なお、文字色は赤系が良いです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/70472136-dfb0-4966-9e49-0ac87ace969e.png)

# メッセージ
メッセージは汎用的に使えるように、オプションセットに保存しておきます
## Option Sets
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/26e9a99d-d7af-b922-2a97-d02c5a6d4b95.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/2ec065d8-4753-ecc1-a6d1-c8c94d3959aa.png)


# Workflow
全体はこのようになります。
エラー表示のカスタムイベントと、「何らかのエラーが発生したとき」イベント
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/c03c05ee-f91e-3b7e-074a-5e1404757f94.png)

## エラー表示設定方法
カスタムイベントを作成します。エラー表示領域に文字を表示する動作を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/f66624e7-61d2-e87e-62c0-c865fec8dda2.png)

### エラー表示ステップ1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/dee0f75d-0e89-e0ca-9243-025161ce35a2.png)

### エラー表示ステップ2
今回は「エラーが発生しました。管理者へご連絡ください。エラーコード[引数.code]：引数.message」という形式にしました。
どんなメッセージが良いかは依頼者に確認するのが一般的です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/2210afa1-40ac-f65d-f751-6300cb5fe564.png)


## エラーが発生したときの処理設定方法
ここがポイントです。「何らかのエラーが発生したとき」というイベントがあります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/7bbfd419-c519-4fde-3d0a-83303a8216e9.png)

トリガーで先程のイベントを呼び出し。
エラーのメッセージとコードを自動的に取得しているので、渡します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/6a35a248-c2fa-ce79-d158-ab6d37545e66.png)

## 完成したもの
エラーが起きると、以下のように表示されます。
画面の一番上や、ボタンの近く等、エラーメッセージの表示にふさわしい場所に配置して下さい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95299/727c22ec-ac4a-1e7a-9616-4b20f0218504.png)
※Toolbox PluginのJavaScriptで誤ったコマンドを書いた場合の事例
エラーコードが数字でない事もあるようですね。

以上です！
GAによる巡回セールスマン問題の最適化

GA(遺伝的アルゴリズム)は最適化手法の一つで、選択、交叉、突然変異を繰り返すことによる最適化を行うアルゴリズムです。

リポジトリはこちら
https://github.com/hinahina-chips/GA-TSP/tree/main

まずは総距離の短い順にソートしておきます。

以下の操作に従って実装します。
- 選択：エリート選択。上位半分を選択。

```
void select_gene1(){
	long i, j;
    for(i = 0; i < NUM_GENE; i++){
        for(j = 0; j < NUM_CITY; j++) Gene[i][j] = Gene[i % (NUM_GENE / 2)][j]; //上位半分をコピー
    }
}
```
- 交叉：適当に交叉させると同じ都市(City)が同じ経路(Gene)に含まれるということが起こるため、マスク交叉を行う。
```
void kousa_gene_pair(long p1[], long p2[]){
    long mask[NUM_CITY];
	long num_mask;
    long i, j, n = 0;
	num_mask = 0;
	mask[0] = 300;//nになり得ない適当な値を初期値として格納
    for(i = 0;; i++){
        n = num_where(p1, p2[n]); //P2[n]の都市がp1のどの要素番号か返す関数num_where
        if(mask[0] == n) break; //既出の要素番号が出たら終了
        mask[num_mask] = n; //mask配列に格納
        num_mask++;//mask配列の要素をインクリメント
    }
    ex_kousa(p1, p2, mask, num_mask);//交叉用の交換関数
}
```
- 突然変異：一定確率でランダムに入れ替える
```
void mutate_gene_each(long i, long j){
	long n, m, k;
	n = Gene[i][j];
	for(;;){
		m = rand() % NUM_CITY;
		if (m != n) break;
	}

	Gene[i][j] = m;
	
	for(k = 0; k < NUM_CITY; k++){
		if(Gene[i][k] == m) break;
	}
	Gene[i][k] = n;
}
```

とはいってもGAのみでは10都市くらいの小規模な巡回セールスマン問題しか解けませんでした。そこで以下の処理を追加しました。

- 前世代の最適経路と総距離を保存し、現世代の最適経路と比較して良い方を残す

- ローカルサーチを実装して交差している経路を無くす(元論文があるんですけど前すぎて見つからんかった...)

```
void local_gene(){
    long i,j;
    long p[NUM_CITY];
    long p_bef[NUM_CITY];

    for(i = 0; i < NUM_GENE; i++){
        for(j = 0; j < NUM_CITY; j++){
            p[j] = Gene[i][j];	//遺伝子情報を1次元配列pに一時的に格納
            p_bef[j] = Gene[i][j];
        }

        local_each(p);

        for(j = 0; j < NUM_CITY; j++){
        	Gene[i][j] = p[j];//一次元配列pをGeneに戻す
        }
    if (F_local == 1){
   	    fprintf(Fp_deb, "before local_sort in local_each\n"); 
   	    for (j = 0; j < NUM_CITY; j++) fprintf(Fp_deb, "%ld", p_bef[j]);
   	    fprintf(Fp_deb, "\n");
   	    
		fprintf(Fp_deb, "after local_sort in local_each\n"); 
		output_gene(i);
		
	}
	
	
	}
	
}

void local_each(long p[]){
    long i, j, g, k;
    double vii, v_ij, vij, vjj;
	

    
	for(i = 0; i < NUM_CITY-2; i++){
        for(j = i+2; j < NUM_CITY; j++){
            
            vij = kyori(p[i], p[j]);
            v_ij =kyori(p[i + 1], p[(j + 1) % NUM_CITY]);
            vii = kyori(p[i], p[i + 1]);
            vjj = kyori(p[j], p[(j + 1) % NUM_CITY]);
            
            if((vij + v_ij) < (vii + vjj)) {
            	F_local = 1;
				local_sort( i+1, j, p);//localサーチの条件	
		    }
				
		}
	}		
}
```
- 後半は突然変異の処理確率を減らす

### 結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2887302/d5a6e135-812d-ec9f-83ce-88e1d3c18d25.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2887302/d9b682ea-59f6-0e8b-27fa-c1bd6622cfd0.png)

ローカルサーチを入れたおかげでどちらも交差点はなくなっていますね。最適化も進んでいるのでGAは有効であるということが分かります。面白い...
pythonでMIDIが再生できないときにやったこと

# 結論
スピーカにつながっていると思っていたポートが、中継機（MIDIスルー）だった。
[TiMidity++](https://wiki.archlinux.jp/index.php/Timidity%2B%2B)を起動し、出力機器を作成したら再生できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287677/b063d5e0-4a3c-2af5-98c7-3076c0cc0b52.png)
↓TiMidity++を起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287677/a73bbcf2-d4f3-6f5f-3080-40f8e8052c5d.png)

# 環境
* OS
    * Ubuntu 22.04 x86_64
# 事象
MIDIを勉強したくて、pythonの[mido](https://mido.readthedocs.io/en/latest/)ライブラリを使ってみました。
チュートリアル通り実施するも、スピーカから音が出ず、困っていました。
スクリプトはエラーなく動いているので、音声出力まわりで調査していきました。

midoライブラリを使用し、MIDIポートを一覧を出力してみました。
```python:
$ python       
Python 3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import mido
>>> print(mido.get_output_names())
['Midi Through:Midi Through Port-0 14:0', 'Midi Through:Midi Through Port-0 14:0']
```

MIDIのド初心者なので、ポートは何でもいいかなと思っていましたが、ここがだめだったみたいです。
どのOSにも共通して、MIDIをPCのスピーカから再生するためには、仮想的なMIDI出力ポートを用意しなければなりませんでした。

# 実施事項
[Timidity++の公式サイト](https://wiki.archlinux.jp/index.php/Timidity%2B%2B)の手順通り、インストールしました。
その後、下記のコマンドでtimidity++を実行しました。
```
$ timidity -iA
```
再度MIDIポートを確認し、増えていることを確認
```python:
$ python       
Python 3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import mido
>>> print(mido.get_output_names())
['Midi Through:Midi Through Port-0 14:0', 'Midi Through:Midi Through Port-0 14:0', 'TiMidity:TiMidity port 0 129:0', 'TiMidity:TiMidity port 1 129:1', 'TiMidity:TiMidity port 2 129:2', 'TiMidity:TiMidity port 3 129:3']
```
上記の設定後に、midiのチュートリアルで、TiMidityのポートを選択し、スクリプトを動かしたところ、きちんと再生されました。

ちなみに、[aconnectgui](https://packages.ubuntu.com/search?keywords=aconnectgui)を使うとGUIでMIDIポートを確認、操作できます。
スクショは、同ソフトを使用し、作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287677/8a50e24c-81af-eeed-f477-e1b3c98cfbcf.png)
PythonでMIDIを再生すると、RtMidiOut ClientがTiMidityの仮想ポートに出力されていることを確認しました。

# 参考資料
とても感謝しています。
[MIDI 仮想キーボードと物理キーボードを Ubuntu で試す](https://qiita.com/nanbuwks/items/055cffd9beb2caf4acb0)

MACの場合はこちらの対応が必要そうです。
[Outputting MIDI sound from Python Mido library on Mac](https://stackoverflow.com/questions/40498625/outputting-midi-sound-from-python-mido-library-on-mac)
ジリ貧 が 全く思い出せない時のためのキーワード

じり貧 | ジリ貧

・じりじりと貧しくなること
経済面以外だと
・じりじりと良くない状況に落ち込むこと
という意味も

じりじりと | 少しずつ | 徐々に | だんだんと

貧しく | 良くない状況に | 絶望に | 破滅に | 貧乏に

なる | 落ち込む | 近づいていく | 近づく | 迫る

こと | 様子
WSL2 意外に親切

# 通常のアップグレード
## 18.04LTSから20.04または22.04へアップグレードしておきたい。

:::note info
インフォメーション
OS周りを触っている方は18.04がサポート切れなのはご存じですよね！
これはアップグレードせねばならん！
:::

- ネットを徘徊すると正統派の記事が出てきます。

https://zenn.dev/ryuu/articles/upgrade-ubuntu2204-wsl

- 18.04のコンソールを漫然とたたくとうまくいきません。

```WSL2:ターミナル
sudo apt update
sudo apt upgrade -y

wsl --list --online

xxxx4@DESKTOP-GU0J5GF:~$ $ sudo apt dist-upgrade && sudo apt install update-manager-core
$: command not found
xxxx@DESKTOP-GU0J5GF:~$ sudo vi /etc/update-manager/release-upgrades
xxxx4@DESKTOP-GU0J5GF:~$ sudo do-release-upgrade -d
Checking for a new Ubuntu release
There is no development version of an LTS available.
To upgrade to the latest non-LTS develoment release
set Prompt=normal in /etc/update-manager/release-upgrades.
xxxx@DESKTOP-GU0J5GF:~$

```

- こちらの解説にもあるように新規でインストールするのが王道です。
- ただし、いろいろやっていると面倒だなと思うことがあろう様です。

**要するに普通に拒否されます(設定を変更しても)**


----
![屏幕截图 2023-06-04 21.14.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155177/5ada2808-a2b9-a7cd-b821-de1c5e1b8842.png)

よく見ると普通のUbuntu がありますね。
こちらを開くと・・・・


```WSL:ターミナル

Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.10.102.1-microsoft-standard-WSL2 x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sun Jun  4 20:41:52 JST 2023

  System load:  0.6                Processes:             8
  Usage of /:   0.7% of 250.98GB   Users logged in:       0
  Memory usage: 2%                 IPv4 address for eth0: 172.29.255.120
  Swap usage:   0%


0 updates can be applied immediately.


The list of available updates is more than a week old.
To check for new updates run: sudo apt update


This message is shown once a day. To disable it please create the
/home/xxxx4/.hushlogin file.
xxxx4@DESKTOP-GU0J5GF:~$ uname -a
Linux DESKTOP-GU0J5GF 5.10.102.1-microsoft-standard-WSL2 #1 SMP Wed Mar 2 00:30:59 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
xxxx4@DESKTOP-GU0J5GF:~$



```

- 途方にくれたらひとまず、インストール済みのプログラムを確認するといいかもしれません。

:::note info
インフォメーション
- 私の環境では 内蔵GPUがQuadro Legacy シリーズと言われるP1000でVRAM 4GB。
- Omniverse のインストールが拒否される悲しいカードです。
- Windows 上ならゲーミングPCがいいと思います。
:::

- 下手に当時ワークステーションを名乗っていたために拡張性はたかいものの、重い・重い・重い。
- Deep Learning,AIって何？ってところで購入の為、重い処理には使えません。
- 基本的にWindows Anacondaマシーンとして余生を過ごしています。


<details><summary>余談(道に迷っている若手エンジニアの皆様へ)</summary>



:::note info
あるある？
- 力のない部門に所属すると機器にこまる＝プロジェクト早く完了しないと古くなったゴミマシーンでがんばらねばならない。
- 自主性の名のもとに除去不可能な障壁の突破が求められる＝政治問題なので一介のエンジニアではどうにもならない。
- あちらこちらでエンジニア（ソフト開発系）が求められるのはこういうこと？
- ちなみに私の専門のハード系はメーカでないとさらに力はないです。
:::

</details>
jetpack composeでCoilを使うときに注意したいこと

# 初めに
今回は、jetpack composeでCoilを使うときに注意したいことを紹介していきます
### 本文
Coilを使って画像を表示しようとした際に表示したい画像のサイズが大きすぎたり小さすぎるとCoil側が勝手に補正を入れるようになっています。
そのため、オリジナルのサイズを表示するには下記のようにサイズを指定しないといけません
```kotlin
model = ImageRequest.Builder(LocalContext.current)
            .size(Size.ORIGINAL)
```
### 最後に
自分が実装をしているときに画像のサイズがオリジナルと違うせいで座標と合わずに手こずったので備忘録的に記事にしました
どなたかのお役に立てれば幸いです
Promise、async/await

## Promiseの基本
非同期処理を行うためのPromise、async/awaitについて解説していきます。

Promiseは「pending」、「fulfilled」、「rejected」の状態を持ちます。

- pending: 非同期処理がまだ完了していない状態
- fulfilled: 非同期処理が成功し、結果が利用可能な状態
- rejected: 非同期処理が失敗し、エラーが発生した状態

Promiseが生成されると、まずはpending状態になります。
その後、非同期処理が成功すればfulfilledに、失敗すればrejectedの状態が変わります。

## Promiseの作成と利用

Promiseは以下のように作成します。

```javascript
const promise = new Promise((resolve, reject) => {
  // 非同期処理
});
```
この非同期処理が成功すればresolve関数を、失敗すればreject関数を呼び出します。
それぞれの関数には、非同期処理の結果またはエラー情報を引数として渡すことができます。

Promiseの結果はthenメソッドを使って取得します。
このメソッドは、Promiseがfulfilled状態になったときに実行されるコールバック関数を登録するためのものです。
```javascript
promise.then((result) => {
  // 非同期処理の結果を利用する
});
```

また、Promiseがrejected状態になったときにはcatchメソッドを使ってエラーを処理します。
```javascript
promise.catch((error) => {
  // エラーの処理
});
```

繋げて利用することも可能です
```javascript
promise
  .then((result) => {
      // 非同期処理の結果を利用する
  })
  .catch((error) => {
      // エラーの処理
  });
```

## async/awaitの基本
async/awaitは、JavaScriptにおける非同期処理をより簡潔に書くための機能です。
asyncとawaitはキーワードで、一緒に使われることが多いです。

asyncは関数に付けられ、その関数が必ずPromiseを返すことを示します。
そのPromiseの結果は、関数の戻り値として得ることができます。
```javascript
async function fetchData() {
  return "data";
}

const promise = fetchData();
```
上記の例では、fetchData関数はPromiseを返します。
このPromiseはすぐにfulfilled状態になり、その結果は文字列"data"です。

## awaitの利用
awaitは、Promiseの結果を待つために使われます。
awaitはasync関数の中でのみ使用できます。
```javascript
async function fetchData() {
  const response = await fetch("https://example.com/data");
  const data = await response.json();
  return data;
}
```
上記の例では、fetch関数はサーバーからデータを取得するPromiseを返します。
awaitはこのPromiseがfulfilledになるのを待ち、その結果をresponse変数に代入します。

その後、response.jsonメソッドはレスポンスのボディを解析するPromiseを返します。
再びawaitがこのPromiseがfulfilledになるのを待ち、その結果をdata変数に代入します。

最終的に、fetchData関数は解析されたデータを含むPromiseを返します。

## Promise.allを使った例
Promise.allとasync/awaitを使えば、更に簡潔に書くことができます。
```javascript
async function fetchAllData() {
  const response1 = fetch("https://example.com/data1");
  const response2 = fetch("https://example.com/data2");
  const response3 = fetch("https://example.com/data3");

  const responses = await Promise.all([response1, response2, response3]);

  const data1 = await responses[0].json();
  const data2 = await responses[1].json();
  const data3 = await responses[2].json();

  return [data1, data2, data3];
}
```
分かりやすいように書いていますが短縮すると下記になります
```javascript
async function fetchAllData() {
  const urls = ["https://example.com/data1", "https://example.com/data2", "https://example.com/data3"];
  const responses = await Promise.all(urls.map(url => fetch(url)));
  return await Promise.all(responses.map(response => response.json()));
}
```

## async/awaitによるエラーハンドリング
```javascript
async function fetchData() {
  try {
    const response = await fetch("https://example.com/data");
    return await response.json();
  } catch (error) {
    // エラーの処理
    console.error("Error:", error);
  }
}
```
上記の例では、fetch関数やresponse.jsonメソッドがエラーをスローすると、そのエラーはcatchブロックで捕捉されます。
エラーの詳細はerror変数に代入され、それを使ってエラーの処理を行います。

# まとめ
JavaScriptのPromiseとasync/awaitは、非同期処理を扱うための強力なツールです。Promiseは非同期処理の結果を表現するオブジェクトで、async/awaitはその非同期処理をより直感的に書くための機能です。
これらの機能をうまく使いこなすことで、非同期処理を含む複雑なプログラムも簡潔にかつ効率的に書くことができます。
さくらのクラウドシェル(無料)でNode-REDを動かしてみた

# はじめに

2023年5月25日からさくらインターネットでブラウザから無料で利用できるクラウドシェル環境がリリースされました。

https://www.sakura.ad.jp/services/cloudshell/

会員IDが無くても利用できますが、登録するとアウトバウンド(外向け)通信が使用できるので、ngrokを使用して外部からNode-REDを使用することができます。

# 手順

クラウドシェル環境のnode.jsのバージョンはv12で、npmコマンドも使用できないため、最初にv14にバージョンアップします。

```bash
nvm install v14
```

ngrokをインストールします。

```bash
curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list && sudo apt update && sudo apt install ngrok
```

Node-REDをインストールします。Node-RED起動後に「メニュー」→「パレットの管理」からノードを追加することも可能ですが、よく利用するノードをコマンドラインから追加しておきます。

```bash
npm init -y
npm i node-red
npm i node-red-dashboard
npm i node-red-contrib-aedes
```

ターミナル画面が1つだけで使い勝手が悪いので、tmuxを起動して複数のターミナルを使用できるようにします。

```bash
tmux
```

tmuxのターミナル操作は以下のとおりです。

- Ctrl+B c → 新しいターミナルを作成する
- Ctrl+B p → ターミナルを移動する(前)
- Ctrl+B n → ターミナルを移動する(後)

1つのターミナルでNode-REDを起動し、もう1つのターミナルでngrokを起動します。

```bash
# terminal 1
node node_modules/node-red/red.js -u ./
```

```bash
# terminal 2
ngrok config add-authtoken [アクセストークン]
ngrok http 1880
```

# 画面

![image_01_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/6627706b-4e84-ad66-4007-48dcd11e42cd.jpeg)
![image_02_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/be9e3e26-de17-8628-63c1-b51bdab5a346.jpeg)
![image_03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/041f1139-3712-ba85-83bb-291cebe40dae.jpeg)
![スクリーンショット 2023-06-04 21.03.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/83777d05-f043-673c-5062-8f728499cf2d.png)
tfenvを使ってTerraformをインストールする

# やりたいこと
macにTerraformをインストールする

# やりかた
terraformそのものをインストールするのではなく、terraformのバージョン管理（pyenv的な）をやってくれる「tfenv」というツールをインストールする。
[tfenv公式ドキュメント](https://github.com/tfutils/tfenv)

### tfenvをインストールする
```bash
$ brew install tfenv
```

### 現在インストールできるバージョンを確認する
```bash
$ tfenv list-remote
1.5.0-rc1
1.5.0-beta2
1.5.0-beta1
1.5.0-alpha20230504
1.5.0-alpha20230405
1.4.6
...
```

### 特定のバージョンのterraformをインストールする

最新バージョンをインストールするときは以下
```bash
$ tfenv install latest
```

バージョンを指定してインストールするときは以下
```bash
$ tfenv install 1.3.2
```

### インストールしたバージョンの一覧を表示する
```bash
$ tfenv list
  1.4.6
  1.3.2
```


### インストールしたバージョンのTerraformを使用できるようにする
```bash
$ tfenv use 1.3.2
$ terraform -v
Terraform v1.3.2
```
pyenvの使い方

### pyenvのインストール

インストール
```sh
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
```

zshを使っている場合は.zshrcに、bashを使っている場合は.bash_profileに以下を追加

```sh
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
```

必要なら
```sh
source  ~/.zshrc
```
で反映させます

### pyenvの使い方

同期
```sh
pyenv rehash
```
リスト表示
```sh
pyenv install --list
```
環境のダウンロード
```sh
pyenv install 3.11.0
```
設定
```sh
pyenv local 3.11.0
```
(local をglobal にするとどのディレクトリでも環境が上書きされるようになる)
確認
```sh
python --version
```
パッケージのインストール例
```sh
python -m pip install beautifulsoup4
```
(pipを直接使うとシステムのコマンドが実行されてしまうので注意)
設定解除
```sh
pyenv local --unset
```

https://qiita.com/ukei2021/items/2920ebeefc806714b812

https://qiita.com/koooooo/items/b21d87ffe2b56d0c589b

https://qiita.com/ksugawara61/items/ba9a51ebfdaf8d1a1b48

### パッケージをプロジェクトごとに設定したい(簡易バージョン)

-tオプションを使用する

例
```sh
python -m pip install beautifulsoup4 -t site-packages
```
実行する前にPYTHONPATHを設定しておく必要がある
```sh 
export PYTHONPATH="./site-packages"
```

サンプル
```sh
python ./test.py
```

```test.py
import bs4
print(bs4.__version__)
```

#### 参考

https://qiita.com/non_cal/items/1f3a910eb55427b193a3

### virtualenvを使う場合(高度)

virtualenvをインストール
```
git clone https://github.com/pyenv/pyenv-virtualenv.git ~/.pyenv/plugins/pyenv-virtualenv
```

pyenvと同様に.zshrcに追加
```sh
eval "$(pyenv virtualenv-init -)"
```

環境を作成
```sh
pyenv virtualenv 3.11.0 sandbox3
```

有効化
```sh
pyenv activate sandbox3
```

pipの確認
```sh
pip --version
```

環境下でのインストール
```sh
pip install beautifulsoup4==4.12.0
```
(パッケージは~/.pyenv/versions/sandbox3/site-packages/以下に保存される)

無効化(環境を抜ける)
```sh
pyenv deactivate
```

リスト確認
```sh
pyenv virtualenvs
```



https://qiita.com/m3y/items/45c7be319e401b24fca8

https://qiita.com/ksato9700/items/5d9eba10fe6b8e064178

https://ccieojisan.net/post-1337/

https://qiita.com/ksato9700/items/5d9eba10fe6b8e064178

#### 追記
virtualenvの主要部分はvenvとしてPython標準に取り込まれていたそうです
ただ一部はマージされなかったので未だにインストールは必要です

https://virtualenv.pypa.io/en/latest/

https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e
『Django4 Web アプリ開発実装ハンドブック』のサインアップページでアドレス入力欄がでなかった話

# 概要

以下の「Django4 Web アプリ開発実装ハンドブック」の第7章の369～386ページにかけてサインアップページを作成しているときに、そのページにメールアドレス入力欄がなかった。本のページに見誤りやすい部分があり、正誤表の通りにコードを修正したところ、メールアドレス入力欄が出るようになった。

https://www.amazon.co.jp/Django4-Web%E3%82%A2%E3%83%97%E3%83%AA%E9%96%8B%E7%99%BA-%E5%AE%9F%E8%A3%85%E3%83%8F%E3%83%B3%E3%83%89%E3%83%96%E3%83%83%E3%82%AF-Python%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E5%AE%9A%E7%95%AA%E3%82%BB%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3-%E3%83%81%E3%83%BC%E3%83%A0%E3%83%BB%E3%82%AB%E3%83%AB%E3%83%9D/dp/4798067172 

## 説明

本書の371ページに以下の様なコードが記載してある。

```python
from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser

class CustomUserCreationForm(UserCreationForm):
    class  Meta:
        model = CustomUser
        fields = ("username", "email", "password1", "password2")
```

ところが、印刷の間違いで本来黒色で印刷するべきところ（```class  Meta:```の行）が、コメントアウトを示す灰色で印刷してあった。そのため、本来上のようにあるべきところが、以下の様なクラスに見間違えてしまった。

```python
from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser

class CustomUserCreationForm(UserCreationForm):
    model = CustomUser
    fields = ("username", "email", "password1", "password2")
```

本来、UserCreationFormはデフォルトでmodel属性としてUserを読み込む。そのため、入力フォームとしてユーザー名、メールアドレス、パスワード＊２を要求するところ、ユーザー名とパスワードだけを入力するページになってしまった。

## 解決方法

[本書のサポートページ](https://www.shuwasystem.co.jp/support/7980html/6717.html)の正誤表には、```class  Meta:```の行が黒色でなく灰色で印刷してあるための旨が記載してある。それを正しく修正すればサインアップページにメールアドレス入力欄が出るようになる。
JavaScriptのmapメソッドについて

## はじめに
実務でmapメソッドについて触れる機会があり、foreachメソッド、filterメソッドとの違いについて調べた内容の備忘録です。

## 結果
・forEachメソッドは処理を実行するのみで、戻り値を持たない。
・mapメソッドは戻り値を返す。
・filterメソッドは処理の条件にあってはまる配列の要素を戻り値で返す。

一つずつ簡単に解説します。
## forEachメソッド
配列の繰り返し処理を行う点は他のメソッドと同様ですが、実行するのみで、戻り値がありません。
そのため配列の中に代入していく必要があります。
```javascript:
let number = [1,2,3,4,5]

number.forEach(value => {
  number.push(value * 2);
});
// number = [2,4,6,8,10]
```
returnで値を受け取ろうとするとundefinedになります。

```javascript:
let number = [1,2,3,4,5]

let result = number.forEach(value => {
  return value * 2;
});
// undefined
```

繰り返し処理で戻り値を受け取りたい場合はmapメソッドを使用します。

## mapメソッド
mapメソッドの記述方法はforEachと同じです。
```javascript:
let number = [1,2,3,4,5]

let result = number.map(value => {
  return value * 2;
});
// result = [2,4,6,8,10]
```
mapメソッドを使用すると戻り値として値を受け取ることができます。

## filterメソッド
filterメソッドは条件に当てはまる要素のみを配列にして戻り値に返します。

```javascript:
let number = [1,2,3,4,5]

let result = number.map(value => {
  return value / 3;
});
// result = [3]
```
filterメソッドを使用すると3で割り切れる要素のみを返します。

## まとめ
forEachメソッドはあまりコードを書く際には適切でないことが多い。
条件で絞り出す際はfilterメソッドやその他の関数を用いた方がシンプルでわかりやすくなる。

## 補足
mapメソッドを使用した際に`Uncaught TypeError: hoge.map is not a function`と表示される際は、型が配列ではなく、オブジェクトになっている場合が多い。その場合はオブジェクトを配列に直す必要がある。

https://qiita.com/JrPageboy/items/b9d60d31d953933f1090
【作業メモ】GCPでTerraformからウェブサーバデプロイ (GCPチュートリアル)

## はじめに
GCP登録して無料クレジット$300もらったので気になってたTerraformをいじる
公式に親切なチュートリアルがあったのでチュートリアル通りに操作

チュートリアル
「Terraform を使用して基本的な Flask ウェブサーバーをデプロイする」
https://cloud.google.com/docs/terraform/get-started-with-terraform?hl=ja

- チュートリアルは右ペインに出ているので、1画面でチュートリアルとコンソール表示して作業できる
- チュートリアルとコンソール画面で操作対象の表示名が違ったりする
→チュートリアルの本文中に、作業手順によってはクリックすると操作するべき場所にスポットライトを当ててくれるボタンがあるので、操作する場所が分からなかったら押してみよう

作業としては、Terraformから仮想マシンをデプロイし、仮想マシンにSSH接続してFlaskアプリ(サーバとエンドポイント)を作成するというシンプルなもの


チュートリアル進めていて引っかかったところを以下にメモ

## 1. 仮想マシンのデプロイ
必要なコマンドはチュートリアルに書いてくれているので今回はとりあえずコピーしてmain.tfファイルを作成する。


コンソールでデプロイしたらCompute Engine APIを有効にしているはずなのにエラーになった
terraform initで初期化してから再度applyで仮想マシン作成できた

## 2. カスタムSSHファイアウォールを作成する
SSH接続を許可するようファイアウォールを設定し、VMインスタンスに接続する
main.tfファイルに追記すればOK

ファイアウォールにSSH接続を許可する設定が無いときとか、接続が明らかに失敗するだろうというときは、接続中に上手くいかない可能性が高いってメッセージが出る
(自分はファイアウォールの設定反映されてないままSSH接続しようとした)

## 3. VMのポート5000を開く 
ローカルPCからウェブサーバーに接続できるよう、ファイアウォールルールに追記
ウェブサーバ接続用URLを出力するロジックも追記
main.tfファイルの差分反映は前の手順と同じなのでここはサクサク

## 4. ウェブサーバにアクセス
URLからアクセスしてHello Cloud!と表示されているのを見る。

## 5. リソースの削除
terraform destroyでリソースを一気に全消し


## 終わりに
今回参考にしたチュートリアルはガチで親切なので、IaC全然分からないけどTerraform触ってみたいというときにおすすめ


<!-- 編集後記>
<!-- QiitaとZennで微妙にMarkdownの記法違うんだね...>
<!-- nanoで編集やりづら...文字がすぐ被って訳分からん、コンソールからエディタ画面切り替えて編集しても反映されない...泣>
おニューのmacでターミナルを整える【iTerm2】

# やりたいこと
まっさらなmacで、ターミナルを使いやすくする

# iTerm2の導入
iTerm2とは、デフォルトでmacに入っているターミナルよりもいい感じのターミナルである（雑）

[こちら](https://iterm2.com/)からiTerm2をダウンロードする
ダウンロードしたらアプリケーションフォルダに移動させましょう

# iTerm2の色変更
デフォルトでは文字が全部白で大変読みづらいため、いいかんじのカラーテーマに変更する

[こちら](https://cocopon.github.io/iceberg.vim/)からテーマ「iceberg」をダウンロードする
iTerm2の preferences > Profiles > Colors を開く。
Profileを追加してicebergとか名前をつける。
右下の`Color presets`タブから、ダウンロードしたテーマのファイル（`iceberg.itermcolors`）をimportする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320845/4eb8cdf7-ed4e-95d6-9c11-d06e68e417ed.png)


`.zshrc`に以下を書き込む
```
export CLICOLOR=1
```
`source ~/.zshrc`してターミナルを再起動する




# 表示されるものの変更（pure）
今いるディレクトリや、gitブランチ名もいい感じに表示してくれるライブラリ「pure」を導入します
ソースは[こちら](https://github.com/sindresorhus/pure)です。
brewでインストールする
```bash
brew install pure
```
`.zshrc`に以下を書き込む
```
autoload -U promptinit; promptinit
prompt pure
```
`source ~/.zshrc`してターミナルを再起動する

# 結果
いいかんじ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320845/e4dc5fce-e7c8-bbef-3684-20464674ad85.png)
deviseでユーザー登録ができない時の仮説

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/b872d7d8-a2e5-c53d-fa58-3765b02e28e8.png)
どこまでやったかを整理する。
deviseをインストール
・モデルを作成
・マイグレーションファイルにカラムを追加
・form_withでf.labelとf.text_fieldにusersテーブルのカラム名を入れてフォームを作成した
・この状態でフォームに入力してもデータベースに保存されない場合のチェックリストです。
1. バリデーションの確認：モデルで変な制約をかけていないか確認する。
2. migrationファイルの制約:テーブル作成の際に変な制約をかけていないか確認する。
3. ストロングパラメーター：deviseはストロングパラメーターが使用できないので、代わりにdevise_parameter_sanitizerを使用します。
4. アソシエーション：テーブルを一つしか作成していない状態なら関係ないが、複数テーブルがある場合はhas_many　複数形,blongs_to　単数系、などを確認する。
5. passwordのカラム名：deviseでのusersテーブルのカラム（デフォルトではencryped_password）ですが、form_withのパスワードとパスワード再入力では、それぞれカラム名をpassword、password_confimationと記述しないといけません。これはpasswordとpassword_confimationが同じかどうかをチェックし、同じならばencryped_passwordに暗号化した文字列を返すという機能がdeviseに実装されているからです。
【Paiza問題集】条件分岐/AND+OR

# Paiza問題集
Pythonで回答

## 条件分岐/AND+OR

### Step01 AND
```Python
"""
AND
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__bool_step1

問題
2つの整数A、Bが与えられます
AとBが両方とも10以上の場合はYESを、そうではない場合はNOを出力してください
"""

A, B = map(int, (input().split()))
print("YES" if A >= 10 and B >= 10 else "NO")
```

### Step02 大文字判定
```Python
"""
大文字判定
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__bool_step2

問題
大文字または小文字のアルファベットCが与えられます
Cが大文字の場合はYESを、そうではない場合はNOを出力してください
"""

print("YES" if input().isupper() else "NO")
```

### Step03 OR
```Python
"""
OR
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__bool_step3

問題
2つの整数A、Bが与えられます
A,Bの少なくとも一方が10以上の場合はYESを、そうではない場合はNOを出力してください
"""

A, B =map(int, input().split())
print("YES" if A >= 10 or B >= 10 else "NO")
```

### Step04 NOT
```Python
"""
NOT
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__bool_step4

問題
整数Xが与えられます
Xが10以上ではない場合はYESを、Xが10以上である場合はNOを出力してください
"""

print("YES" if not int(input())>=10 else "NO")
```

### Step05 AND+NOT
```Python
"""
AND+NOT
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__bool_step5

問題
2つの整数A、Bが与えられます
以下の条件を満たす場合はYESを、そうではない場合はNOを出力してください。
「Aが10以上」かつ「Bが10以上ではない」
"""

A, B = map(int, input().split())
print("YES" if (A>=10) and (not B >=10) else"NO")
```

### Final問題集 AND+OR
```Python
"""
AND+OR

問題
3つの整数X,Y,Zが与えられます
「Xが10以上」かつ「Yが10以上」の場合はYESを、そうではない場合はNOを出力してください
ただし、「Zが10以上の」場合はXとYの値にかかわらず、必ずYESを出力してください
"""

X, Y, Z = map(int, input().split())

if Z >= 10:
    print("YES")
else:
    print("YES" if X>=10 and Y>=10 else "NO")
```
JJUG CCC 2023 Spring 個人メモ

2023/06/04 (日) 開催。
オンライン参加したセッションの個人的なメモ。

別のセッション見ながら無音声で見てたりするのもある。

# セッション一覧
https://sessionize.com/api/v2/y7inyq6y/view/GridSmart


# Spring Boot 2 から 3 へバージョンアップしてみた
- [Migration Guide](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide) に目を通すべし
- package `javax` -> `jakarta` ひたすら置換
- Spring MVC の trailing slash の問題 (マッチングの仕様変更)
- Spring Security
  - 認証 Filter の dispatch type が全てが対象になる
  - 認証エラーで forward したら forward した先でまた同じ Filter が適用され無限ループ
  - `spring.security.filter.dispatcher-types` で指定して回避
- 複数プロジェクト間で version catalog 導入し、バージョンを統一
- Spring Boot Migrator というツールがある (gradle は当時サポートされていなかった)


# サーバレス Java の今
https://speakerdeck.com/xblood/sabaresujavanojin-snapstarttoweb-adapterwoji-sete
- SnapStart
  - Java コールドスタートの INIT 時間を軽減
  - lifecycle hook は利用できない
- AWS Lambda Web Adapter
  - Lambda Extension として動作
  - Docker とかも対応
  - Dockerfile に COPY を一つ書く必要がある
  - SAM CLI で簡単にビルド・デプロイ可能
  - API GW, Lambda Function URL, ALB からの起動みサポート。
    - EventBrdige, S3 Event, SQS からのインテグレーションは未サポート
- Graal VM 注意点
  - リフレクションの動的要素対応ができない。
    トレースエージェントツールを使って reflect-config.json の生成が必要
- AWS Lambda Powertools for Java
  - 構造化ログ
  - カスタムメトリクス
  - AWS X-Ray
- Amazon CloudWatch Embeded Metric Format (EMF)
  - 標準出力の中に埋め込めるらしい
- CloudWatch Synthetics
  - E2E テスト的なことできる。それをメトリクスにできる
- K6
  - 負荷テストツール


# SpringBoot+Kotlinで使うExposed
https://speakerdeck.com/wenas/jjug-ccc-2023-exposed
- JOOQ 的な感じ。DSL チックに SQL を書く
- Java から使うのは無理ぽ


# Virtual Threads - 導入の背景と、効果的な使い方
https://speakerdeck.com/skrb/virtual-thread-dao-ru-nobei-jing-to-xiao-guo-de-nashi-ifang-372a94a6-b5dc-448d-b1d1-e8750efdafcb
- JVM が管理する軽量スレッド
  - 他言語の Fiber に相当
- スループット向上
  - I/O を多く含むシステムで効果的
  - 応答時間はちょっとだけ悪化
- 従来のスレッドと使い方は同じ
- PlatformThread / CarrierThread
- VirtualThread
  - java.lang.VirtualThread
  - unmount() / mount()
  - Continuation.yield(xxx); // 非公開クラス
- ユースケース
  - `Executors#newVirtualThreadPerTaskExecutor()`
  - `Executors#newThreadPerTaskExecutor(Thread.ofVirtual().factory())`
  - ExecutorService は java 19 から AutoCloseable になって try-with-resource できるようになる。
  - synchronized はなるべく使わないようにする
    - synchronized はリソースへのアクセスを 1 つのスレッドだけに限定するという指示。
      他のスレッドをブロックされてしまう。
      対策：
      - Immutable class の利用
      - 処理の受け渡しには Callable を使う
      - どうしてもロックが必要なら ReentrantLock とかを使う
  - ThreadLocal を使わない(えー...)
    - mutable API であり、スケールしない
    - ScopedValue で代用する (Java 21 Preview)
  - Thread は使い回さない。使い捨てる。
- WebFlux とか R2DBC を無理して導入しなくても良さそう(感想)


# コンテナ環境でのJava性能チューニング
- `-Xmx` より `-XX:MaxRAMPercentage` の方が安全らしい。


# JUnitテストをCI環境で並列で実行する方法とその速度,スケーラビリティ
https://speakerdeck.com/nabedge/junittesutowocihuan-jing-debing-lie-deshi-xing-surufang-fa-tosonosu-du-sukerabiritei

- self-hosted runner 使え
- ./gradle test -Pshard=1/3
  ```yaml
  strategy:
    matrix:
        shard: [1/3, 2/3, 3/3]
    steps:
      run ./gardlew createTestList
      run ./gradlew test-Pshard=${{matrix.shard}}
  ```
- SpringTestCase のコンテキストは可能な限り再利用される。揃えた方がいい。
- GitHub の normal runner のコスパは EC2 でやるなら t3.large に相当
- Spring やめて Quarkus 使え


# 補足
発表スライドが公開されたらリンク追加しようと思います。
[HTML・CSS] block,Inline,Inline-blockについて

HTML・CSSのblock,Inline,Inline-blockの違いについてまとめます

○前提
HTML・CSSの要素の表示形式には種類があり下記３種がよく使用される
・Inline要素
・block要素
・Inline-block要素
これらは要素の幅や高さの調節に用いられる

○各表示形式の特徴
・Inline要素とは
→block要素の内容として用いられる要素
　(例)
　　aタグ,imgタグ spanタグなど
　(特徴)
　　* 要素の幅は中身と同じ大きさになる
　　* 要素同士が横に並ぶ
　　* 幅（width）と高さ（height）が指定できない
　　* 余白（padding・margin）が指定できない
　　* 要素の配置を返すことができる
　　
・block要素とは
　→コンテンツをまとめるために用いられる要素
　(例)
　　div,p,h1など
　(特徴)
　　* 要素の幅はブラウザ幅いっぱいになる
　　* 要素同士が縦に並ぶ
　　* 幅（width）と高さ（height）が指定できる
　　* 余白（padding・margin）が指定できる
　　* 要素の配置は変えられない。

・Inline-block要素
　→block要素とInline要素の中間の要素で、
　　inline要素でwidth,heightを指定したり、
　　Block要素で横方向に並べたい際にこのinline-block要素を使用する
 　(特徴)
　　* 要素の幅は中身と同じ大きさになる
　　* 要素同士が横に並ぶ
　　* 幅（width）と高さ（height）が指定できる
　　* 余白（padding・margin）が指定できる
ucan-labさんの環境構築でDockerに任意の環境変数を使用する


laravelの構築をする時に
ucan-labさんのdockerを使わせてもらってます。
すごい便利なのですが、Dockerを知ってたら当たり前なんでしょうが、環境変数を用意しておかないとデフォルト設定しか反映されない。

- APP_DEBUG=${APP_DEBUG:-true}の部分はbashの環境変数にAPP_DEBUGが入ってないと反映されない。APP_DEBUGの環境変数がない場合はtrueを使用。envコマンドで環境変数は見れる。

ひとまず下記のコマンドを叩くようにしました。

```
export $(cat ./src/.env)
```



```:docker-compose.yml
services:
  app:
    build:
      context: .
      dockerfile: ./infra/docker/php/Dockerfile
      target: ${APP_BUILD_TARGET:-development}
    volumes:
      - type: bind
        source: ./src
        target: /workspace
      - type: volume
        source: psysh-store
        target: /root/.config/psysh
        volume:
          nocopy: true
    environment:
      - APP_DEBUG=${APP_DEBUG:-true}
      - APP_ENV=${APP_ENV:-local}
      - APP_URL=${APP_URL:-http://localhost}
      - LOG_CHANNEL=${LOG_CHANNEL:-stderr}
      - LOG_STDERR_FORMATTER=${LOG_STDERR_FORMATTER:-Monolog\Formatter\JsonFormatter}
      - DB_CONNECTION=${DB_CONNECTION:-mysql}
      - DB_HOST=${DB_HOST:-db}
      - DB_PORT=${DB_PORT:-3306}
      - DB_DATABASE=${DB_DATABASE:-laravel}
      - DB_USERNAME=${DB_USERNAME:-phper}
      - DB_PASSWORD=${DB_PASSWORD:-secret}
```


https://github.com/ucan-lab/docker-laravel/blob/main/compose.yml


もっといい処理がある場合は教えてください。
【Pico W書籍フォロー記事】Raspberry Pi Pico Wの電流計測

Arduino IDEを使ったRaspberry Pi Pico書籍シリーズの第３段を出版しました。
今回は、Wi-FiやBluetoothが使えるようになったRaspberry Pi Pico Wのネタです。
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/27c7b4da-e98b-ee6d-e8b8-4a7c03b3ae03.png)](https://www.amazon.co.jp/gp/product/B0C6ZYRZL8?&linkCode=ll1&tag=jksoft-22&linkId=91b3c9018fc6c16c8451c1968d667227&language=ja_JP&ref_=as_li_ss_tl)

https://www.amazon.co.jp/gp/product/B0C6ZYRZL8?&linkCode=ll1&tag=jksoft-22&linkId=91b3c9018fc6c16c8451c1968d667227&language=ja_JP&ref_=as_li_ss_tl

書籍の中で、電池駆動のためにRaspberry Pico Wに流れる電流を測りながら省電力化にトライしているネタがありますが、この電流計測の方法について紹介します。

## 使用機材

電流計測に使ったのは、Nordic Semiconductor社の販売している[Power Profiler Kit Ⅱ](https://www.nordicsemi.com/Software-and-tools/Development-Tools/Power-Profiler-Kit-2)です。
200nAまでの電流が計測できるのと1秒に10万回の計測ができるので、ミリ秒単位、マイクロ秒単位で動作しているマイコンの消費電流を測るのに向いています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/f329ed41-5e5e-acfa-5c0f-45a0543a2e8f.png)

計測対象の電源として、Power Profiler Kit Ⅱ（以降PPK2）に給電しているUSBから供給することも出来ますし、電池などの外部電源から供給して電流を測ることができます。

私は、mouserで購入しました。
https://www.mouser.jp/ProductDetail/Nordic-Semiconductor/nRF-PPK2?qs=hd1VzrDQEGilgnS3iQ3EVw%3D%3D

## 接続
Raspberry Pi Pico WもRaspberry Pi Picoと同様に外部から電源を供給する用のVSYSピンがあります。
Raspberry Pi Pico Wは、昇降圧の電源回路を内蔵しているので、VSYSは1.8～5.5Vの範囲で入力できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/191e830f-58c3-f8ca-8070-3984ffb74c07.png)

こことGNDにPPK2のVOUTとGNDをつなぎます。
外部電源から供給する場合は、VINとGNDにつなぎます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/1f12878c-7072-5d1e-f478-25ef4706cc7c.png)

## 計測
PPK2をPCにつなぎ、専用のアプリで計測を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/6784908f-aa8e-662d-8f1e-c099a16f07e4.png)
計測した結果は、PPK2で開く用のファイルかCSVで保存することが出来ます。

ちなみにRaspberry Pi Pico Wは、Wi-Fi通信を行うとだいたい250mAぐらいまで流れています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/f829a20d-6ca8-c7d5-8db5-278f69b41cda.png)

## 最後に
PPK2は、マイコン回路を電池駆動するときにプログラムが想定通り動作して、ちゃんと消費電力を節約できているか確認するのに重宝しています。
価格は1万円以上しますが、安価なものとは性能が段違いなので、価値は十分にあると思います。
Windows11入りPCを買ったら勝手にOneDriveに同期されたのでそれを拒否した件

# はじめに

PCを買い替えたのですが、外付けHDDからファイルを持ってきたら、ファイル名を変更しようとすると勝手にファイル名が全選択される事象が起きました。
調べてみると、OneDrive上にファイルを同期しているときにこのような現象がみられるそうです。

**勝手に同期してくれるな！** ということで、ここに備忘録をまとめておきます。

# ファイル名を変更しようとすると勝手にファイル名が全選択される事象

> 困ったこと
> Windows10のエクスプローラでファイルの名前変更をしている最中、1秒ごとぐらいに強制的に全選択状態になり、ファイル名の一部を書き換えようとしたのにすべて消えてしまうされてしまうという事象が発生していました。

https://toripedia.net/win10-explorer-automatically-all-selected/

まさにこの現象でした。

# OneDriveの同期を切る

https://www.fmworld.net/cs/azbyclub/qanavi/jsp/qacontents.jsp?PID=9911-2928

無事解決しました。よかったよかった。

# おわりに

勝手にクラウドに私のファイルをアップロードするのはやめていただきたいのです。（お小遣い帳とか、人には見せたくないファイルも入っているので）

（おわり）
【VSCode】TODOコメントを一覧表示する方法

## 拡張機能をインストールする

TODOコメントを一覧表示するために「Todo Tree」をインストールします。

https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree&ssr=false#overview

インストールすると以下のように「Todo Tree」のアイコンが表示され、クリックするとTODOの一覧が表示されます。

![スクリーンショット 2023-06-04 18.04.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/b830ce44-e049-176b-7230-299c07918746.png)

## TODOとして認識されるタグを設定する

TODOとして認識されるタグはデフォルトで次のようになっています。

```json:settings.json
{
  "todo-tree.general.tags": [
    "BUG",
    "HACK",
    "FIXME",
    "TODO",
    "XXX",
    "[ ]",
    "[x]",
  ]
}
```

この`"todo-tree.general.tags"`の項目を変更することでTODOとして認識されるタグを設定できます。

## アイコンやハイライトを変更する

ツリーに表示されるアイコンやエディターでのハイライトを変更するには次の設定を変更します。

```json:settings.json
  "todo-tree.highlights.customHighlight": {
    "BUG": {
      "icon": "bug"
    },
    "HACK": {
      "icon": "tools"
    },
    "FIXME": {
      "icon": "flame"
    },
    "XXX": {
      "icon": "x"
    },
    "[ ]": {
      "icon": "issue-draft"
    },
    "[x]": {
      "icon": "issue-closed"
    }
  }
```

`"todo-tree.highlights.customHighlight"`では次の設定ができます。

`foreground` - エディターのハイライトおよびルーラーのマーカーの前景色を設定する。

`background` - エディターでハイライトの背景色を設定する。

`opacity` - 背景色の透明度を設定するパーセント値。

`fontWeight`、`fontStyle`、`textDecoration` - 標準の CSS 値でハイライトのスタイルを設定する。

`borderRadius` - ハイライトの背景の境界線の半径を設定する。

`icon` - ツリービューに別のアイコンを設定する。アイコンは以下のいずれかから選択。codiconから選択する場合には「$(*icon*)」で指定。

https://octicons.github.com

https://microsoft.github.io/vscode-codicons/dist/codicon.html

`iconColour` - ツリー内のアイコンの色を設定する。指定しない場合は、前景色または背景色が使用される。色は前景色と背景色ごとに指定可能。

`gutterIcon` - エディターのガターにアイコンを表示するには「true」に設定する。

`rulerColour` - 概要ルーラーのマーカーの色を設定する。指定しない場合は、デフォルトで前景色が使用される。色は前景色と背景色ごとに指定可能。

`rulerOpacity` - ルーラーマーカーの不透明度を設定する。

`rulerLane` - オーバービュールーラーのマーカーのレーンを設定する。指定しない場合は、デフォルトで「right」が設定される。「left」、「center」、「right」、「full」のいずれかを設定可能。「none」を使用してルーラー マーカーを無効にすることも可能。

`type` - エディター内でどの部分を強調表示するか設定する。有効な値は次のとおり。
- `tag` - タグのみを強調表示
- `text` - タグとタグの後のテキストを強調表示
- `tag-and-comment` - コメント文字 (または一致の開始部分) とタグを強調表示
- `tag-and-subTag` - 上記と同様だが、サブタグもハイライト可能 (カスタムハイライトで定義された色を使用)
- `text-and-comment` - コメント文字 (または一致の開始部分)、タグ、およびタグの後のテキストを強調表示
- `line` - タグを含む行全体を強調表示
- `whole-line` - タグを含む行全体をエディターの全幅まで強調表示
- `capture-groups:n,m...` - 正規表現からのキャプチャグループを強調表示。「n」は正規表現へのインデックス
- `none` - 文書内の強調表示を無効にする

`hideFromTree` - ツリーからタグを非表示にする。ファイル内ではハイライト表示される。

`hideFromStatusBar` - タグがステータスバーのカウントに含まれないようにする。

`hideFromActivityBar` - タグがアクティビティバーのバッジ数に含まれないようにする。

`"todo-tree.highlights.customHighlight"`で設定されていないタグは`"todo-tree.highlights.defaultHighlight"`の設定が適用されます。

## 隠しファイルを対象に含める

デフォルトでは隠しファイルは検索の対象外となっています。
隠しファイルを検索対象に含めるには次のように設定を変更します。

```json:settings.json
{
  "todo-tree.filtering.includeHiddenFiles": true
}
```
[Material UI v5] 独自Themeをカスタマイズする方法's

<h1>Material UI v5　独自Themeカスタマイズ方法　</h1>
<h2>はじめに</h2>

こんにちは、京都人です。名古屋でフロントエンドエンジニアをやっております。

この度、新規プロジェクトでMUIを使い倒す実装方針なりましたので、そのキャッチアップ兼、来年新卒で入るエンジニアの後輩さんのための、実務導入も兼ねて記載している背景になります。

<h2>目次</h2>
    <ul>
      <li>themeから独自スタイルをカスタマイズする</li>
      <li>defaultPropsを変更したいとき</li>
      <li>スタイルの上書き</li>
      <li>ownerStateにthemesのスタイルを読み込みたい</li>
    </ul>

<h2>themeから独自スタイルをカスタマイズする</h2>
<p>
createTheme内に記載していきます。基本的になんでもスタイルを変更できます。以下が記述サンプルになります。
</p>

```
const theme = createTheme({
    palette: {
        primary: {
            main: Colors.primary,
        },
        secondary: {
            main: Colors.secondary,
        },
    },
    components: {
        SampleComponent: {
            defaultProps: {
                sampleProps: true,
            },
        },
    },
});
```

<p>
全ての既存MUIコンポーネントのスタイルや擬似要素のスタイルを変更することが可能になる。
<ul>
<li>
<h3>defaultPropsを変更したいとき</h3>
<p>既存Propsのスタイルが変更可能になります。基本的に、MUIコンポーネントのDocsのページ最下部にButton-APIのリンクがあるので、そのリンク先のProps内ならなんでも変更可能です。</p>

```
  components: {
    MuiButtonBase: {
      defaultProps: {
        disableRipple: true,
      },
    },
  },
```
</li>

<li>
    <h3>スタイルの上書き</h3>
        <p>styleOverridesオブジェクト内に記述することで、既存のMUIコンポーネントのスタイルを変更することが可能になります。rootはベーススタイルという意味です。</p>

```
  components: {
    MuiButton: {
      styleOverrides: {
        root: {
          fontSize: '1rem',
        },
      },
    },
  },
```
<p>さらに条件を分けてスタイルをカスタマイズしたい場合の記述方法もあります。その際は「ownerState」を使用します。</p>

```
styleOverrides: {
    root: ({ ownerState }) => ({
        ...(ownerState.variant === 'contained' &&
            ownerState.color === 'primary' && {
                backgroundColor: '#202020',
                color: '#fff',
    }),
}),
```
<p>今回の場合だと、既存Propsのvariantがconteinedの時且つ、既存PropsのcolorがPrimaryのときのスタイルを設定しています。このように複数のPropsが存在する場合のスタイル分けも可能になります。</p>
</li>

<li>
<h3>ownerStateにthemesのスタイルを読み込みたい</h3>
<p>いちいちゼロからCSSを書いていられない場合は、themeを追加して回避することができます。</p>

```
components: {
    MuiSlider: {
      styleOverrides: {
        valueLabel: ({ ownerState, theme }) => ({
          ...(ownerState.orientation === 'vertical' && {
            backgroundColor: 'transparent',
            color: theme.palette.grey[500],
          }),
        }),
      },
    },
  },

```
</li>
</ul>