OmniAICreator/Qiita-1.07M huggingface dataset:
Kotlinで標準入力をする方法

Kotlinで標準入力をする方法にはいくつかの選択肢があります。この記事では、それぞれの方法の特徴や使い方を紹介します。

## main関数の引数に渡す

Kotlinでは、main関数は引数としてString型の配列を受け取ることができます。この配列には、プログラム実行時にコマンドラインから渡された引数が格納されます。例えば、以下のようなコードを実行すると、

```kotlin
fun main(args: Array<String>) {
    for (arg in args) {
        println(arg)
    }
}
```

コマンドラインから以下のように引数を渡すと、

```
$ kotlinc Main.kt -include-runtime -d Main.jar
$ java -jar Main.jar hello world
```

以下のように出力されます。

```
hello
world
```

この方法では、シンプルな記述で入力を受け取ることができますが、実行時に引数を渡す必要があります。また、引数はすべてString型として扱われるため、数値や真偽値などに変換する場合は別途キャストを行う必要があります。

## readLine関数を使う

readLine関数はKotlin標準ライブラリに含まれる関数で、標準入力から一行分のテキストを読み込むことができます。例えば、以下のようなコードを実行すると、

```kotlin
fun main() {
    println("名前を入力してください")
    val name = readLine()
    println("年齢を入力してください")
    val age = readLine()?.toInt()
    println("名前は${name}、年齢は${age}です")
}
```

コマンドラインから以下のように入力すると、

```
名前を入力してください
Alice
年齢を入力してください
20
```

以下のように出力されます。

```
名前はAlice、年齢は20です
```

この方法では、プログラム実行中に任意のタイミングで入力を受け取ることができます。また、一行ごとに入力を取得するため、空白区切りや改行区切りなどの形式に対応することができます。

しかし、readLine関数はnullや型に注意して使用する必要があります。readLine関数はString?型（null許容型）を返すため、nullチェックやエルビス演算子（?:）などを使って安全に扱う必要があります。また、readLine関数は文字列として読み込むため、数値や真偽値などに変換する場合はtoIntやtoBooleanなどの拡張関数を使ってキャストする必要があります。

## Scannerクラスを使う

ScannerクラスはJava標準ライブラリに含まれるクラスで、標準入力からテキストを区切り文字（デフォルトでは空白）で分割して読み込むことができます。例えば、以下のようなコードを実行すると、

```kotlin
import java.util.Scanner

fun main() {
    val scanner = Scanner(System.`in`)
    println("名前を入力してください")
    val name = scanner.next()
    println("年齢を入力してください")
    val age = scanner.nextInt()
    println("名前は${name}、年齢は${age}です")
}
```

コマンドラインから以下のように入力すると、

```
名前を入力してください
Alice
年齢を入力してください
20
```

以下のように出力されます。

```
名前はAlice、年齢は20です
```

この方法では、readLine関数と同様にプログラム実行中に任意のタイミングで入力を受け取ることができます。また、ScannerクラスはnextIntやnextDoubleなどのメソッドを使って、テキストを数値や真偽値などのプリミティブ型に変換することができます。

しかし、ScannerクラスはJavaのクラスであるため、Kotlinのnull安全性や拡張関数などの機能を利用することができません。また、Scannerクラスは区切り文字で分割するために正規表現を使っており、これが処理速度の低下につながる可能性があります。さらに、Scannerクラスは入力ストリームを同期する必要があるために、他の入出力と競合する可能性があります。

## まとめ

Kotlinで標準入力をする方法には以下の3つがあります。

- main関数の引数に渡す
- readLine関数を使う
- Scannerクラスを使う

それぞれの方法にはメリットとデメリットがあります。用途や目的に応じて使い分けることが大切です。

ソース: Bing との会話 2023/9/24
(1) Kotlinで標準入力あれこれ - Qiita. https://qiita.com/gumimin/items/eafdf66368d7d63f737c.
(2) Kotlinで標準入力 - Qiita. https://qiita.com/yotu/items/44013287fabd8be75aa1.
(3) Kotlinで標準入力あれこれ - Qiita. https://bing.com/search?q=Kotlin%e3%81%a7%e3%81%ae%e6%a8%99%e6%ba%96%e5%85%a5%e5%8a%9b%e3%81%ae%e6%96%b9%e6%b3%95.
mpguiを試してみた

mgp123のcursesベースのラッパープログラムの[mpgui](https://sites.google.com/view/peterrsamuel)をビルドして実行してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/05448412-4155-5570-e8c9-bfa612385abd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/d671e094-f3b3-5247-54ac-c7305d1ec84f.png)

mpg123の垂れ流しで十分な気がします。

またmp3のストリームには対応していないようです。
【タスク管理アプリを作る】②タスク削除、編集機能を追加する。

タスク登録だけじゃ使い物にならないといことで、
削除、編集機能を追加しました。
コードは修正部分のみ抜粋しました。

実装していて、迷う部分がありました。
ご意見いただけると嬉しいです。

■仕様
・タスクを選択して削除ボタンでタスクを消す。
・タスクを選択して編集ボタンで編集画面表示。
・編集画面ではタスクIDの変更が不可にする。

■課題
・タスク登録画面と編集画面はほぼ同じです。
　なので、同じ処理を使うべきか分けるべきか。
　同じ処理を使うなら、どのように条件分岐するべきか。
　これは、デザインパターンとか考えると、いい感じにできるのか。

・バグになるのですが、タスク一覧にはタスク名しか表示していません。
　なので、一覧で選択したタスクを区別する為「タスク名」をキーにして、
　削除したのですが、同じタスク名があると纏めて消えてしまいます。
　ここは、一意な値をキーとすべきでした。

■画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545817/e653f119-80ae-cc0d-a091-36887641aaeb.png)

■コード説明
```cs:MainForm.cs
// 削除ボタンでタスク消す
private void DeleteTaskButton_Click(object sender, EventArgs e)
{
    var taskSelIndex = TaskItemListBox.SelectedIndex;
    if (taskSelIndex == -1)
    {
        MessageBox.Show("削除アイテム未選択です。", "エラー", MessageBoxButtons.OK);
        return;
    }

    var taskName = TaskItemListBox.Items[taskSelIndex].ToString();
    if (taskName != null)
    {
        _data.DeleteTask(taskName);
        UpdateTaskList();
    }
}
```

```cs:TaskDataManager.cs
// タスク一覧データから名前が一致するタスク消す
public void DeleteTask(string taskName)
{
    // TODO:名前一致するタスクが全て消える。
    _taskData.RemoveAll(v => v.Name == taskName);
}

// タスク編集情報更新
public void EditTask(TaskData data)
{
    // 編集前のデータを削除した上で追加する。でないと二重登録される。
    DeleteTask(data.Name);
    _taskData.Add(data);
}

// タスク名をキーにタスクデータを取得
public TaskData GetTaskData(string taskName)
{
    var taskData = _taskData.Where(v => v.Name == taskName).FirstOrDefault();

    // TODO:呼び出し元でNULLチェックが必要になるのは良くない。
    return taskData;
}
```

```cs:RegistTaskForm.cs
public RegistTaskForm(TaskDataManager data, string taskName) : this(data)
{
    // タスク追加か、編集か判断するフラグ。
    isEdit = true;

    var editTaskData = _data.GetTaskData(taskName);
    if (editTaskData != null)
    {
        // 編集データを画面に反映。
        TaskIdNumericUpDown.Value = Convert.ToDecimal(editTaskData.Id);
        TaskNameTextBox.Text = editTaskData.Name;
        DescriptionTextBox.Text = editTaskData.Description;
        if (editTaskData.Type == TaskData.TaskType.Active)
        {
            radioButton1.Checked = true;
            radioButton2.Checked = false;
        }
        else
        {
            radioButton1.Checked = false;
            radioButton2.Checked = true;
        }

        // IDは編集不可
        TaskIdNumericUpDown.Enabled = false;
    }
}

// 入力値チェック
private bool CheckValid(out string message)
{
    if (string.IsNullOrEmpty(TaskNameTextBox.Text))
    {
        message = "名前が入力されていません。";
        return false;
    }

    // TODO:編集中はチェックしない。今後もパターンが増えると条件が複雑化してしまう。。どうしたものか。
    if (!isEdit)
    {
        var id = decimal.ToInt32(TaskIdNumericUpDown.Value);
        if (!_data.IsDuplicateId(id, out message))
        {
            return false;
        }
    }

    // 正常時は空文字列を返す。
    message = string.Empty;
    return true;
}
```
データの視覚化の基本

データの視覚化は，データ分析と理解において非常に重要な役割を果たす。
Juliaという高性能なプログラミング言語を使用して，データの視覚化を行う基本的な方法について紹介する。
Juliaは高速で柔軟な言語であり，データの視覚化にはさまざまなツールやライブラリが利用できる。
以下に示す例は簡単なものであるが，個々の関数は多くの機能を持っている。
それぞれの関数のオンラインヘルプは `? scatter` のようにすれば得られる。

### データの視覚化の基本

#### 1. Juliaのインストールとセットアップ

データの視覚化を始める前に，Juliaをインストールし，必要なパッケージをセットアップする必要がある。
Juliaの公式ウェブサイト（https://julialang.org/）から最新バージョンをダウンロードし，インストールする。
次に，データ可視化に使用するパッケージをインストールする。主要なパッケージとして，Plots.jlやGR.jlがある。
以下の例では，日本語（漢字かな）を使用するので pyplot を使っているが，そもそも日本語を使うための準備も必要である。

#### 2. データの読み込み

データの視覚化には，まずデータを読み込む必要がある。
CSV.jlやDataFrames.jlなどのパッケージを使用して，データをJuliaに読み込む。
データは通常，表形式で保存され，各列が変数を表す。
以下の例では一つの変数データがベクトルに収められている場合の使用法を述べているが，通常はCSVファイルからデータフレームに読み込みデータ列を指定してグラフを描く。

#### 3. 散布図の作成

散布図は，データのパターンや相関関係を視覚化するための基本的なツールである。
Plots.jlを使用して，データをプロットし，散布図を作成する。
例えば，以下のコードで簡単に散布図を描画できる。


```julia
using Plots

# データの読み込み
x = randn(1000)
y = randn(1000)

# 散布図の作成
pyplot(size=(400, 400), label="", fontfamily="IPAMincho")
scatter(x, y, xlabel="X軸ラベル", ylabel="Y軸ラベル", title="散布図")
```
![fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611739/2830770b-25ad-6bc6-5013-71a844f2ba47.png)

#### 4. ヒストグラムの作成

ヒストグラムは，データの分布を理解するのに役立つ。
データの範囲を階級に分割し，各階級内のデータの頻度を表示する。
Plots.jlを使用して，ヒストグラムを簡単に作成できる。


```julia
using Plots

# データの読み込み
x = randn(1000)  # ランダムなデータ

# ヒストグラムの作成
histogram(x, xlabel="値", ylabel="頻度", title="ヒストグラム")
```
![fig2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611739/864501f3-faa4-4da3-77ee-8818adf3a0f9.png)

#### 5. 折れ線グラフの作成

データの時間変化や連続データの可視化には，折れ線グラフが役立つ。
Plots.jlを使用して，折れ線グラフを描画する。


```julia
using Plots

# データの作成
x = 1:10
y = [1, 3, 2, 4, 6, 5, 8, 7, 9, 10]

# 折れ線グラフの作成
plot(x, y, xlabel="X軸ラベル", ylabel="Y軸ラベル", title="折れ線グラフ")
```
![fig3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611739/04c2303b-649f-1883-197f-8a0a38ec9af2.png)
【Gitコマンド】コミットメッセージ変更方法

自分がコミットメッセージを間違えた時に実行する方法を備忘録として残しておきます。

:::note alert
記載されている内容は、プッシュする前のコミットメッセージの変更方法です。
:::

### 目次
* 直前のコミットメッセージを変更する方法
* 2つ以上前のコミットメッセージを変更する方法

## 直前のコミットメッセージを変更する方法
まずは過去のコミットを確認しましょう。
```
git log --oneline
```
`--oneline`をつけることで、以下のようにコミット番号とコミットメッセージが1列に揃った形で表示されます。

```
00000000 直前のコミット //ここのコミットメッセージを変更する
11111111 2つ前のコミット
22222222 3つ前のコミット
```
今回は、直前にコミットしたコミットメッセージを変更します。
直前のコミットを修正する場合は、`--amend`オプションを使用します。

```
git commit --amend -m "修正後のコミットメッセージ"
```

:::note info
--amendオプション
現在のステージの状態で直前のコミットをやり直すためのオプション。
-mをつけることで、コミットメッセージを修正できる。
:::

もう一度`git log --oneline`を叩いて実行結果を見てみましょう。
直前のコミットメッセージが修正されているはずです。

```
00000000 修正後のコミットメッセージ
11111111 2つ前のコミット
22222222 3つ前のコミット
```
## 2つ以上前のコミットメッセージを変更する方法

次は2つ以上前のコミットメッセージを修正します。
`git log --oneline`実行して、修正したいコミットメッセージがいくつ前のコミットなのかを確認します。

```
git log --oneline
```
実行結果
```
00000000 直前のコミット //1つ前のコミット
11111111 2つ前のコミット // 2つ前のコミット //ここのコミットメッセージを変更する
22222222 3つ前のコミット // 3つ前のコミット
```
今回は2つ前のコミットメッセージを修正したいので、以下コマンドの`HEAD~`の後に、`2`を入力して実行します。

```
git rebase -i HEAD~2
```
実行結果、以下のように2つ目のコミットが1番上に表示されている状態で、viエディタが開きます。

```
pick 11111111 2つ前のコミット
pick 22222222 3つ前のコミット

# Rebase ~~~~~
# ~~~~~~~~~~~~
```

viエディタが開いたら、編集モードに切り替えて、コミットメッセージを修正したいコミットの左に記載されている、`pick`を`edit`に変更します。
変更が完了したら、編集モードを終了し、保存してviエディタを終了させます。

```
edit 11111111 2つ前のコミット
pick 22222222 3つ前のコミット

# Rebase ~~~~~
# ~~~~~~~~~~~~

:wq // 入力してEnter
```

:::note info
モード切り替え
viエディタを開いた時点では、コマンドモードになっています。
キーボードの「i」(insertのi)を押すことで、編集モードに切り替わります。
編集が完了したら、「esc」を押すとコマンドモードに切り替わります。
:::


:::note info
変更を保存
編集画完了後、閲覧モードの状態で「:wq」を入力後、Enterを押すと編集内容が保存され、エディタが閉じます。
編集を保存しない場合は、「:q!」を入力することで、編集内容を破棄してエディタが閉じます。
:::

ここまでの操作でeditに指定したコミットまで、状態が戻っていることになります。
従って、直前のコミットを修正する時に使用した、`--amend`を使って、コミットメッセージを修正します。

```
git commit --amend -m "修正後のコミットメッセージ"
```

直前のコミットメッセージ変更の操作と違って、2つ以上前のコミットメッセージを修正した際は、これで終わりではありません！
以下のコマンドで作業完了です。

```
git rebase --containue
```

必ず最後に確認しましょう。
変更が反映されています。

```
00000000 修正後のコミットメッセージ
11111111 2つ前のコミット
22222222 3つ前のコミット
```

## 最後に

以上。
こういうのまとめてほしいとかあれば、コメントください。
今更知った、`:is()`について

## `is()`とは
 CSSの擬似クラス関数で、セレクターのリストを引数に取り、リスト中のセレクターのいずれか一つに当てはまる要素をすべて選択する。
多くのセレクターを小さくまとめて書くのに便利。
### 使用例
- 簡略化前
```
/* 3 層（以上）の順序なしリストに四角形を使用 */
ol ol ul,
ol ul ul,
ol menu ul,
ol dir ul,
ol ol menu,
ol ul menu,
ol menu menu,
ol dir menu,
ol ol dir,
ol ul dir,
ol menu dir,
ol dir dir,
ul ol ul,
ul ul ul,
ul menu ul,
ul dir ul,
ul ol menu,
ul ul menu,
ul menu menu,
ul dir menu,
ul ol dir,
ul ul dir,
ul menu dir,
ul dir dir,
menu ol ul,
menu ul ul,
menu menu ul,
menu dir ul,
menu ol menu,
menu ul menu,
menu menu menu,
menu dir menu,
menu ol dir,
menu ul dir,
menu menu dir,
menu dir dir,
dir ol ul,
dir ul ul,
dir menu ul,
dir dir ul,
dir ol menu,
dir ul menu,
dir menu menu,
dir dir menu,
dir ol dir,
dir ul dir,
dir menu dir,
dir dir dir {
  list-style-type: square;
}
```
- 簡略化後
```
/* 3層（以上）の順序なしリストに四角形を使用 */
:is(ol, ul, menu, dir) :is(ol, ul, menu, dir) :is(ul, menu, dir) {
  list-style-type: square;
}
```
## `:is()`と`:where()`の違い
- `:is()`：セレクター全体の詳細度にカウントされる
-  `:where()`：[詳細度](https://developer.mozilla.org/ja/docs/Web/CSS/Specificity "詳細度")の値が0
AndroidStudioのコンソールの文字化けを治す方法

# はじめに
Flutterのアプリ開発でAndroidStudioを使用していた時のこと。
あるプロジェクトの実行時にエラーが発生したので確認したところ、コンソールの一部が文字化けしており詳細が確認できませんでした。

# 解決方法
Helpタブ　→　Edit Custom VM Options(何か聞かれたウィンドウが出てきたらcreateを押す)　→　AndroidStudioを再起動してプロジェクトを実行

これで解決出来ました。
「ライブラリのコンピューターの種類 'X86' がターゲットのコンピューターの種類' x64' と競合しています」の対処方法

2日前にC言語を学習し始めたところで、早速定番の箇所でつまずいたので事例と対処の記録まで。

# 環境
- Windows10
- Visual Studio 2022

# エラーの内容
「ライブラリのコンピューターの種類 'X86' がターゲットのコンピューターの種類' x64' と競合しています」


下記のように、プラットフォームの設定を確認しても「x64」できちんと設定されているので原因がわからず計2時間ぐらい試行錯誤…。
https://qiita.com/sketchbooks99/items/97ec33cecdb9db6e3eb9

# 対処方法
Developer Command Prompt for VS 2022 から x64 Native Tools Command Prompt for VS 2022の使用に切り替えたら無事コンパイルできた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564033/67488099-c1d5-a77c-fa40-2306f2a9da1e.png)



# 参考にした文献
https://www.kkaneko.jp/tools/win/ninja.html
トリボナッチ数列&テトラナッチ数列（PHP）

トリボナッチ数列・・・自身の前の３つの数字を足した数列。
テトラナッチ数列・・・自身の前の４つの数字を足した数列。

~~~
<?php
//20個のトリボナッチ数列を求める

//求める個数
$number=20;

//トリボナッチ数列を求める関数
function tribo($num) {
    if($num==0){
        return 0;
    }
    if($num==1){
        return 0;
    }
    if($num==2){
        return 1;
    }
    $tri=0; 
    $tri_0=0;
    $tri_1=0;
    $tri_2=1;
    for($i=3;$i<=$num;$i++) {
        //トリボナッチ数を求める
        $tri=$tri_0+$tri_1+$tri_2;
        //各々の数の更新
        $tri_0=$tri_1;
        $tri_1=$tri_2;
        $tri_2=$tri;
    }
   return $tri;
}

//結果の表示 	
for($i=0;$i<=$number;$i++) {
    echo ($i.": ".tribo($i))."\n";
}
?>
~~~
結果
~~~
0: 0
1: 0
2: 1
3: 1
4: 2
5: 4
6: 7
7: 13
8: 24
9: 44
10: 81
11: 149
12: 274
13: 504
14: 927
15: 1705
16: 3136
17: 5768
18: 10609
19: 19513
20: 35890
~~~

~~~
<?php
//20個のテトラナッチ数列を求める

//求める個数
$number=20;

//テトラナッチ数列を求める関数
function tetra($num) {
    if($num==0){
        return 0;
    }
    if($num==1){
        return 0;
    }
    if($num==2){
        return 0;
    }
    if($num==3){
        return 1;
    }
        
    $tet=0; 
    $tet_0=0;
    $tet_1=0;
    $tet_2=0;
    $tet_3=1;
        
    for ($i=4;$i<=$num;$i++) {
        //テトラナッチ数を求める
        $tet=$tet_0+$tet_1+$tet_2+$tet_3;
        
        //各々の数の更新
        $tet_0=$tet_1;
        $tet_1=$tet_2;
        $tet_2=$tet_3;
        $tet_3=$tet;
    }
    return $tet;
}

//結果の表示 	
for($i=0;$i<=$number;$i++) {
    echo ($i.": ".tetra($i))."\n";
}
?>
~~~
結果
~~~
0: 0
1: 0
2: 0
3: 1
4: 1
5: 2
6: 4
7: 8
8: 15
9: 29
10: 56
11: 108
12: 208
13: 401
14: 773
15: 1490
16: 2872
17: 5536
18: 10671
19: 20569
20: 39648
~~~
なんかもっと簡略化できる気もする。
MacでWindowsキーボードの変換・無変換を使い、英数・かな入力切り替えする方法　

Mac利用者で外付けキーボードとしてWindowsキーボードを使っている方向け（たくさんいると嬉しいです、、、）
スペースキーの左右にある変換・無変換を使って、Mac（JIS配列）の英数・かなと同じように入力切り替えする方法を紹介します。

（MacのUS配列でJIS配列の英数・かなキーと同じように変換する方法もあります！）

## この設定で実現できること
1. US配列の⌘キーでJIS配列の英数・かなキーと同じように入力切り替え
1. Windows用キーボード利用時にスペースの左右にある無変換キーと変換キーでJIS配列の英数・かなキーと同じように入力切り替え

## 対象者
- Mac利用者
    - US配列利用者
    - Windows用の外付けキーボード利用者

## 必要な設定

1. まず、下記のアプリ（無料）をダウンロードします。
[Karabiner-Elements](https://karabiner-elements.pqrs.org/)

1. ダウンロードが完了したら、下記画像のように「Complex Modifications」を押し、「Add rule」を押してください。
![スクリーンショット 2023-09-24 午後1.51.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510209/6297dbff-88c1-8543-13a1-b36de3bfd96a.png)

1. 下記画像の「Import more ...」の部分を押します。
![スクリーンショット 2023-09-24 午後1.57.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510209/658b3951-c461-a122-ba00-9cad61e3a37e.png)

1. こちらのリンクに飛ぶので、画像①・画像②の順番でクリックし、インポートします。
画像①
![スクリーンショット 2023-09-24 午後2.02.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510209/d552aa0d-38dc-c7a1-bbc4-73d7aa9771ac.png)
画像②
![スクリーンショット 2023-09-24 午後2.05.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510209/7fbc1bb8-f97e-9826-3062-3fd30b9cdcda.png)

1. こちらをクリックしてインポートします。
![スクリーンショット 2023-09-24 午後2.08.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510209/cac6c17e-6b5b-029a-5be2-17b6f643ccda.png)

1. 「コマンドキーを単体で押したときに、、、、」のEnableをクリックします。![スクリーンショット 2023-09-24 午後2.10.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510209/ed8f978b-6a50-2595-94f4-406b744f0a9e.png)
ここまでの設定を完了すると、US配列でもJIS配列と同じように左右の⌘キーを使って英数・かなキーを変換できるようになります。

1. ここからは、外部キーボード用の設定をしていきます。「Simple Modifications」をクリックし、設定したい外部キーボードを選択します。（私の場合はUSB KBを選択します。）

1. 画像①の「Add item」をクリックしたら、上記に空の設定項目が出てきます。そしたら、青い下矢印の部分をクリックします。画像②のように項目がでてきますので、「Japanese」の「PCキーボードの無変換キー」を選択します。同じように右側の項目も画像③のように、「Modifier keys」の「left_command」をクリックします。
画像①
![スクリーンショット 2023-09-24 午後2.23.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510209/f959e354-a18b-a956-742f-122a0d7344f7.png)
画像②
![スクリーンショット 2023-09-24 午後2.24.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510209/07353dc4-b0ee-60c7-9a5a-9617c24ca6d4.png)
画像③
![スクリーンショット 2023-09-24 午後2.24.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510209/c9de2347-ea66-628b-1a50-452b8c52f1e9.png)
これで、無変換キーを⌘キー（左）に割り当てが完了しました。
同じように手順8をもう一度繰り返して、変換キーも⌘キー（右）に割り当ててください。（「Japanese」の「PCキーボードの変換キー」を、「Modifier keys」の「right_command」に割り当てる）
下記画像のように設定できれば完了です。
![スクリーンショット 2023-09-24 午後2.40.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510209/c530f640-45d0-c18e-ecf2-7b97c9170cda.png)


## まとめ
いかがでしたでしょうか？
以上で、Windows用外部キーボードをMacで利用しても、MacのJIS配列キーボードと同じように、スペースキーの左右で英数・かなの変換ができるようになったとおもいます。
お疲れ様でした！
【Mac M1】nvmでのnode.jsバージョン管理 とyarnを追加した話

next.jsでコード書いてる時に、macを久々再起動したら
```
The engine “node” is incompatible with this module.
```
エラーがでる原因としては、next.jsのプロジェクトで必要としているnodeバージョンが18以上なのに
それ以下のv16が入っていたから。

で、nodenvとかnodebrewとかnvmとか、nodeのバージョン管理をするには色々な方法があるのだけど、
普段nodeのバージョン変更とか滅多にしないので、前どれでやったかを忘れてしまったりする。
今回は結局nvmでやりました。

# 最初に
自分の環境で行った手順です。
※Mac M1 13.2
環境によって変わりうる可能性もあるため、
・node.jsのバージョンがうまく変わらない
・node.jsのバージョンを変えたら、yarnが使えなくなった

時に、うまくいかない時に試す、くらいの感覚でいていただければと思います。
※また、nvmはすでに入れている前提です。

◼️nvm公式
https://github.com/nvm-sh/nvm#set-default-node-version


# 手順
まずは現在pcにインストールしているnvmバージョンを確認

```
nvm ls
```
今現在使いたいnodeがなければ、バージョンを指定してインストールする。

```
nvm install <version>
```

その上で、デフォルトのバージョンを指定（18とかを指定）
```
nvm alias default 18.xx.xx
```

## yarnも一緒に消えた！
nvmで使うバージョンを変えた後、yarnがそのnodeには入ってないぞ！と言うエラーが出る場合があります。
その場合は下記の手順でyarnを入れておくと改善しました。
※nvmでyarnを入れる方法もあるが、それだとターミナルを再起動するたびリセットされる様子。。
```
brew install yarn --ignore-dependencies
```
AWS S3 Glacierにある大量のアーカイブを全部消す

# はじめに
そもそもそんな操作をする事は無いのでしょう。
単純なワンライナーですが長いのでメモ。

# いきさつ
Synology製NASには[Glacier Backup](https://kb.synology.com/ja-jp/DSM/help/GlacierBackup/help?version=7)というNASのディレクトリをS3 Glacierにバックアップするアプリがあります。
自宅NASのバックアップ動作確認で不要になったボールトを削除する事になり、本来であればNAS側からボールト削除操作を実行するべきだったのですが・・・
パソコン初心者なので、誤ってAWS側のアクセスキーを先に削除してしまいました。（本当は深夜飲酒中にシステム操作したせいです。）
別のアクセスキーを再登録してもNAS側操作はエラーとなり、仕方なくCLIから操作する事にしました。
しかし、ボールトを削除するためには格納されているアーカイブを全削除しなければならず、アーカイブの総数は10000件以上もあったのです。リファレンスのように手動ではやってられません。

# 結論
- 生成したアーカイブリストJSONファイルの`ArchiveId`を抽出し、`delete-archive`コマンドに渡す

# どうする
https://qiita.com/atsonic/items/8090cae004f115cdaaa6

こちらの記事にある通り、アーカイブリスト取得まで進めます。
「何をするにも時間がかかる」という知見は同記事から頭にいれておきます。
アーカイブリストの結果ファイルは本文も`output.json`としています。

## JSONにあるアーカイブを消す
``` bash
jq '.ArchiveList[].ArchiveId' output.json | xargs -I {} aws glacier delete-archive --account-id [アカウントID] --vault-name [ボールト名] --archive-id="{}"
```
シェルから`jq`コマンドが使えました。
これで`ArchiveID`キーの値だけを取り出し、`xargs`コマンドで引数のアーカイブIDに該当する部分を`jq`の出力で置換するだけです。
これで`ArchiveId`キー毎に`delete-archive`コマンドが実行されます。
エラーが無ければ標準出力はありません。
対象アーカイブが多すぎると待ち時間で接続がタイムアウトする可能性があるので、その場合は`nohup`のバックグラウンド実行も併用しておきましょう。

# 終わりに
酒飲んでシステムを触るのはやめようね。。。

# 参考
AWS公式リファレンス: [Delete an Archive in S3 Glacier by Using the AWS CLI](https://docs.aws.amazon.com/amazonglacier/latest/dev/getting-started-delete-archive-cli.html)
each文で出力するデータの数を指定する方法

# 目的
検索をかけても自分の理想とする記事がなかなか見つけることができなかったためこちらに使用方法をまとめます。

# 数の指定
例えばpostsテーブルがあったとして5つ取得したいと考えたときコントローラ ビューファイルに以下のように記述します。

```ruby:posts_controller.rb
@posts = Post.all
```
```ruby:viewファイル
<% @posts.limit(5).each do |post| %>
# ~~~~~
<% end %>
```
上記のようにeachメソッドを使う前にlimitメソッドで数を指定する流れでできました。

# まとめ
データを一部取得したいときに便利かと思いました。

# 参考記事
https://railsdoc.com/page/limit
SSHポートフォワーディングについて

# SSHポートフォワーディングについて #

SSHサーバー内でたてたwebアプリをローカルのブラウザから確認したい場合の手順について

- ローカルのポート：8000
- SSHサーバーのIP：11.111.111.11
- SSHサーバーのユーザー：root
- SSHサーバー内のアプリのポート：10080
- SSHサーバー内のアプリのIPアドレス：11.111.111.12
の場合

```
ssh -L 8000:11.111.111.12:10080 -Nf root@11.111.111.11
```

でSSHのポートフォワーディングの設定が完了。
ちなみにオプションは接続しっぱなしにするための設定で下記のような内容になっています。

-f : バックグラウンド起動
-N : コマンド実行なし
【Laravel】バリデーションの作成

システム開発を行う上でバリデーションは必須の機能になります。
今回はそのバリデーションの書き方について説明していきます。

開発環境
・PHP8.0.8
・Laravel 9.52.8
・MacOS M1チップ

## なぜバリデーションが必要なのか
そもそもバリデーションとはユーザーによって開発者の期待しない値が送信されたときにその入力値によってバグがおきないように事前に入力制御するものです。
通常だとバリデーションされた値はデータベース上に登録されず、再度ユーザーに入力を促します。

## バリデーションの作成
バリデーションを行うためのファイルを下記コマンドを使用して作成していきます。
作成後はapp/Http/Requestsフォルダに作成したファイルが作成されています。

```php
php artisan make:request SampleFormRequest(ファイル名)
```

## バリデーションの書き方
```php:SampleFormRequest.php
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

lass SampleFormRequest extends FormRequest
{

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, mixed>
     */
    public function rules()
    {
        return [
            'name' => 'required|max:255',
            'email' => 'required|email|unique:users|max:255'
          ];
    }
}
```
バリデーションの条件としてはrules()の　returnの中に記述していきます。
例えばrequiredは必須入力を促すバリデーション、max：255は入力文字数の制限をするなどがあります。
その他のルールに関しては下記URLを参考にしてください。

ルール参照：https://readouble.com/laravel/8.x/ja/validation.html

## Controller
```php:SampleController.php
public function sampleShow(SampleFormRequest $request)
    {
        $validated = $request->validated();

        return redirect('index');
    }
```
Controlllerには引数としてSampleFormRequest（バリデーション）を記載します。
``$request->validated()`` でバリデーションを行います。

## view
```php
@if ($errors->has('name'))
<div>
{{ $errors->first('name') }}
</div>
@endif
```
各入力フォームに対して特定のメッセージを出した方がユーザーにとってはわかりやすいですよね！
``$errors->has('項目名')`` 　を記載し、``$errors->first('name')``で実際のエラーメッセージを
出力します。

## まとめ
今回はバリデーションについて説明しました。
バリデーションは本来バックエンドで行います。
フロントでもバリデーションのような入力制御は可能ですが、フロントでは悪意のあるユーザー側がいくらでも入力値を操作できるため、フロントのみの制御のみだと不安です。
そのためにバックエンドでしっかりとバリデーションを行い、アプリケーションを正しく運用する必要があります。
Proxmox Backup Serverをデプロイする

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。
今回はProxmox Backup Serverをデプロイしていきたいと思います。

# Proxmox Backup Serverとは？

Proxmox公式サイトから引用します

>Proxmox Backup Server は、VM、コンテナ、物理ホストをバックアップおよび復元するためのエンタープライズ バックアップ ソリューションです。Proxmox Backup Server は、完全に重複排除された増分バックアップをサポートすることで、ネットワーク負荷を大幅に軽減し、貴重なストレージ スペースを節約します。強力な暗号化とデータの整合性を確保する方法により、完全に信頼されていないターゲットであっても、安全にデータをバックアップできます。

https://www.proxmox.com/en/proxmox-backup-server/overview

# HWスペック

Backup Server用に用意したHWのスペックは以下としております。
![image (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/b697e022-28cd-9177-5991-141ec96c1f20.png)

# 参考サイト
公式が用意しているドキュメントになります。
ここにデプロイ方法だけではなく、HWスペック等も書いています。

https://pbs.proxmox.com/docs/

# 構築
## Backup ServerのISOイメージの取得
以下のサイトに最新版がありますので、ローカルの端末にインストールします。

https://www.proxmox.com/en/downloads

![image (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/5ed41a3c-3901-7221-a11b-60419722522a.png)

## 設定投入
設定を開始します。
GUIかCUIかを選択できるっぽいです。今回はWebインターフェースで操作したいのでGraphicalを選択します。
![image (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/9e5884b1-dff6-9f47-d24f-da503341eed7.png)

同意書が表示されます。
I agreeを押下します。
![image (16).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/d0cb54bc-f45c-1891-c612-ed9a1930c173.png)

/dev/sdaが選択されていることを確認して次に進む。
![image (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/ecbb0d69-72a5-a4cb-1c91-06f21b61155e.png)

以下のように設定をして次に進みます。
![image (18).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/f472e43f-a78f-683d-7934-1501b2703354.png)

パスワードとメールアドレスを入力して次に進みます。
このパスワードはrootのパスワードとなります。
![image (19).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/055d05aa-0397-67e0-fdf8-7976aeac6e48.png)

Backup ServerのIPアドレス、ゲートウェイ、DNSを設定します。
![image (20).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/9e782ecd-5aa4-64d1-59eb-2b1556b14e87.png)

最終確認画面になります。
確認して次に進むと環境構築が始まりますので、暫く待ちます。
![image (21).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/18313241-205d-6672-356b-08fba1e54293.png)

構築が完了するとhttps://"Backup ServerのIPアドレス":8007でWebUIにアクセスすることができます。
ユーザはroot。パスワードは入力したもので入れます。
![image (22).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/9c90b1cf-7657-0e24-7e30-bbc58422c301.png)

管理画面は以下のようになっています。
実際にどうやってバックアップをしていくのかは今後確認していきます。
![image (23).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/9c84adb1-eee6-3c8f-68af-1802879cfebb.png)
Git CLIでの操作

# Git CLIでの操作 #

GUIを最近使用しており、コマンドを忘れてしまっていたので、備忘録

## ブランチについて ##
- ブランチを確認
    ```
    git branch
    ```

- リモートのブランチも確認
    ```
    git branch -a
    ```

- ブランチ作成
    ```
    git branch {$ブランチ名}
    ```

- フェッチ
    ```
    git fetch
    ```

- チェックアウト
    ```
    git checkout {$ブランチ名}
    ```

- 新規ブランチをチェックアウト
    ```
    git checkout -b {$ブランチ名}
    ```

- 新しいブランチをpush
    ```
    git push -u origin {$リモートブランチ名}
【UE5】Geometry Scripting：プロシージャルに石畳や岩場をつくる【追記】

[article-part1]: https://qiita.com/Rinderon/items/70765fb914d2242a448e
[article-part2]: https://qiita.com/Rinderon/items/ff59cc272d759876f246

:::note info
対象バージョンUE5.2.1
:::

:::note info
Geometry Scriptingを使うには「Geometry Script」プラグインを有効にする必要があります。
:::

# はじめに

プロシージャルに石畳や岩場を作る[【前編】][article-part1]と[【後編】][article-part2]では、UVのUnwrapは手動で行うしかないようだと書いたが、後日、Unwrapを行うノードが見つかったので、ここに紹介する。

# 【前編】【後編】のブループリントグラフの修正箇所

[【前編】][article-part1]と[【後編】][article-part2]どちらも、「Set Mesh UVs From Planar Projection」を使ってXY平面による投影でUVを作っていた。
これを以下のように書き換える。

## Before
![20230924_01_UnwrapBefore.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/e14a4d58-06ba-f9b7-77f6-75839eb17a1b.jpeg)

## After
![20230924_02_UnwrapAfter.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/f8dbccb6-7347-d930-28c4-bbd2fba2369d.jpeg)

- <b>Set Mesh UVs From Planar Projection</b>は残しておく。Unwrapには元となるUVマップが必要だが、平面投影で作られたUVマップはUnwrapのためには都合が良い形をしているため。
- <b>Recompute Mesh UVs</b>：これがUnwrap相当の処理をしてくれるノード。ただし、UV値にリアルスケールでの数値が入る(…と思われる)挙動をするので、この後、UV値の大きさを調整した方が良い。
- <b>Repack Mesh UVs</b>：UVアイランドの重なりなどを解消して、(0,0)～(1,1)の範囲にすべてのUVアイランドが入るように、並べなおしてくれる。
- <b>Scale Mesh UVs</b>：タイリングの密度をスケーリングで調整する。Repack Mesh UVsで(0,0)～(1,1)の範囲に入ってくれているので、どれだけスケーリングすればよいかのイメージは湧きやすい。

以下に、これらのノードによってUVがどのように変化するかを紹介する。

### Set Mesh UVs From Planar Projection後

XY平面に投影された状態なので、3D空間では垂直に近い面が、UV空間での面積が非常に小さい。(結果、テクスチャが延びる)
![20230924_04_UV_PlanarProjection.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/da7c752b-cbb7-7d09-5c45-21a549ea1155.jpeg)

### Recompute Mesh UVs後

ポリゴンの面積などの応じてええ感じにUVを調整してくれているはずだが、UV座標に非常に大きな値が入っているため、UVエディタの限界まで広げてみても、まだ画面に収まらない。これを次のRepackで修正する。
![20230924_05_UV_Recompute.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/50a47f81-b941-f635-6e16-a40f88808798.jpeg)

### Repack Mesh UVs後

Repackで(0,0)～(1,1)の範囲に収まったので、やっとRecompute Mesh UVsの結果が確認できる。
3D空間で垂直に近い面でも、UV空間でも十分な面積が得られ、テクスチャが延びなくなった。
※代償として、3D空間で水平に近い面の面積が多少小さくなるが、許容できる範囲だろう。
![20230924_06_UV_Repack.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/74212980-9d20-781a-a52f-22508d706d4d.jpeg)

### Scale Mesh UVs後

(0,0)～(1,1)の範囲に収まっている状態だと、岩に対してテクスチャが大きすぎるので、スケールをかけてタイリングを起こす。これで、程よい密度感になった。
![20230924_07_UV_Scale.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/9669b136-1145-c6b2-1a8e-5a8e93edd0d2.jpeg)

## 結果の比較

左：以前の方法(平面投影のみ)、右：今回の方法(Unwrap)。
中央奥は平行投影のみのものをStatic Mesh化してから、UVエディタでUnwrapしたもの。
中央奥と同様、右は垂直面でのテクスチャの延びがなく、見た目も遜色ない。
これでStatic Mesh化してからUVエディタで調整する手作業が不要になった。
![20230924_03_Compare.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/263a8170-25ff-43d5-5790-e1ad449ccf0c.jpeg)
condaで新しい仮想環境を作りjupyterlabで利用できるようにするまでの備忘録

仮想環境構築からjupyter labで利用できるようにする。毎回忘れるので備忘録として。

# condaの新しい仮想環境を作る

```
(base) $ conda create -n new_env python=3.10
(base) $ conda activate new_env 
(new_env) $
```

ここら辺でテキトーに追加のパッケージのインストール

```
(new_env) $ pip install pandas
```

# jupyter labに登録

```
(new_env) $ conda install notebook ipykernel -y
(new_env) $ ipython kernel install --user --name new_env
(new_env) $ jupyter kernelspec list
```
aws-saa対策

## 対策
わからないことをざっくりまとめます。

### プライベートサブネット上のインスタンスのインターネット接続
以下の対応を行うことで、プライベートサブネット上のインスタンスとインターネットの接続経路が確保される
1. 共存するサブネット内のパブリック上にNATゲートウェイを構成
2. カスタムルートテーブルを定義、インターネットトラフィック用にアプリケーション層のプライベートサブネットへ関連付けする。

※ルートテーブル、サブネットが別のサブネットやインターネットと通信するためにはルートテーブルの作成、およびアタッチ（紐づけ）が必要

---

### EC2インスタンスのステータス
1. 休止：インスタンスのサスペンド。メモリも保存される。
　→（メモリ上に保管されているデータをルートEBSボリュームに格納されたファイルに保存して、一時停止前の状態を保持）
2. 停止：インスタンスのシャットダウン。
3. 終了：インスタンスの削除。起動や接続は不可能。

※メモリデータの保持が必要で、かつ（EBSとEIPを除いて）費用を軽減したい場合ソリューションの際は「休止」ステータスを選択

---

### EC2へプライベート　IPv4アドレスを使用して接続を行うシナリオがある場合、EC2の単一障害時にスタンバイ機へトラフィックを流したい
1. セカンダリ Elastic Network Interfaceを設定する。
   プライマリIPへの疎通ができなくなった場合にEC2に切り替わりネットワークインターフェースの冗長化することができる。

---

### AWS S3を使用して静的ウェブサイトをホストする際、バケットに対してJavascript認証済みリクエストを行いたい

1. バケットにおいてCORSの設定を有効化する

※通常は実行されず、ブロックされる。
QGISのバージョン更新

たまーにQGISを開くととてつもなくバージョンが古くて、毎回バージョン更新しているのでメモ。何も複雑なことはありませんが。

①旧版のアンインストール (Macの場合アプリをゴミ箱に移動すればよいだけ、のはず。)
②<a href="https://qgis.org/ja/site/forusers/download.html#">ダウンロードページ</a>から所望のバージョンのインストーラをダウンロード
③画面の指示に従ってインストール
【SPA】クリックイベントを計測できる方法調査

個人アプリを制作するにあたってSPAでのクリックイベントを計測できるようにしたいのと、クリックイベントでの回数がユーザーにも見れるようにしたい。

## GA4だと制限がある
GA4だと、イベントに指定できるパラメータの数は 25 個までです。
>制限事項
リクエストに指定できるイベントの数は 25 個までです。
イベントに指定できるパラメータの数は 25 個までです。
イベントに指定できるユーザー プロパティの数は 25 個までです。

引用：
https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?hl=ja&client_type=firebase

う〜ん、微妙ですね。。。
25個までの制限じゃ、足りないんですよね。

## FirebaseのFirestore（NoSQL）を使う

ざっくりとGPTにコストの見積もりを出してもらった。

質問
Firebaseで以下のアーキテクチャでアプリを作成したい
vue.jsとNosqlで作成したいです。コストはどれぐらいですか？
認証系はいらないですし、アクションを押したら検証するために数値を計測するためにNosqlを使っているようなイメージの構成です。

回答
Firebaseの利用料:

FirestoreやRealtime Database: これらのサービスは、読み取り、書き込み、削除の操作ごとに料金が発生します。また、データの保存にも料金が発生します。無料プランでは一定の読み書きとストレージが無料で提供されていますが、それを超えると料金が発生します。
Hosting: Firebase Hostingは、無料プランでもかなりの利用が可能で、高速なコンテンツ配信ネットワーク（CDN）とHTTPSを提供します。

Firestoreを確認しても、そんなにコストがかからなそう。
NoSQLだけでも100円いくかな？ってぐらいだと思う。

>リージョン米国
1 日あたりの無料割り当て	無料割り当て超過分の料金（単価）	課金の単位
ドキュメントの読み取り	50,000	$0.06	ドキュメント 100,000 点あたり
ドキュメントの書き込み	20,000	$0.18	ドキュメント 100,000 点あたり
ドキュメントの削除	20,000	$0.02	ドキュメント 100,000 点あたり
保存データ	1 GB のストレージ	$0.18	GB/月
引用：https://cloud.google.com/firestore/pricing?hl=ja

## まとめ
AWSだとlightsailでRDB使おうとすると1000円以上は行くし、Firebaseを使ってコスパ良く個人アプリを作っていこうと思います。
[TypeScript]Function lacks ending return statement and return type does not include 'undefined'


> Function lacks ending return statement and return type does not include 'undefined'
> 機械翻訳： 関数に終了 return ステートメントがなく、戻り値の型に「未定義」が含まれていません

例えば、以下のソースコードは find() が IDBResponse を返すことを期待しているが for 文 で関数が終了しているので何かしらの戻り値が必要だ。

```typescript
async find(): Promise<IDBResponse> {
  const maxRepeat = 5;
  const exponent = 3;
  const sleep = (ms: number) => new Promise((res) => setTimeout(res, ms));
  for (let counter = 0; counter < maxRepeat + 1; counter++) {
    try {
      const response = await this.dbConnection.execute<DBSuccessResponse[]>(SQL);
      return response;
    } catch (error) {
      if (counter === maxRepeat) {
        throw error;
      }
      const sleepTime = Math.pow(exponent, counter) * 1000;
      await sleep(sleepTime);
    }
  }
}
```

TypeScript は厳格に型チェックを行いますので、関数がすべてのコードパスで予期される戻り値を返すことを確認する必要がある。エラーメッセージは、関数が全てのパスで戻り値を返していないことを示している。

undefined を戻り値の型に定義すれば一応は解決するが、なるべく不要な型定義はしたくない。その場合は明示的に find() 関数の最後に Error を throw してやると良い。

```diff
    }
+    throw new Error('Unexpected error in find method.'); // この行は実際には到達しません。戻り値またはエラーが返されることを保証するために含めています。
  }
}

```
GitHubアクションのワークフローを使ってリリースを作成する方法


こんにちは，ご覧いただきありがとうございます。
前回，`package.json`を更新したら`npm publish`されるワークフローについてまとめました。

https://qiita.com/ikepu-tp/items/8c7e9975d3f3864afc48

ついでにこのタイミングで`release-v*`のブランチ作成とリリース作成も自動化することにしました。

## 作ったもの

`/.github/workflows/npm-publish.yml`を次のように作成した。
`secrets`に`NPM_TOKEN`という名前でNPMJSで発行したトークンを保存しておいてください。

```diff_yaml:npm-publish.yml
name: npm publish

on:
  push:
    branches:
      - main
    paths:
      - package.json
  workflow_dispatch:

jobs:
  publish:
    runs-on: ubuntu-latest

    permissions:
      contents: write

    steps:
      - uses: actions/checkout@v3
        with:
          ref: main

      - uses: actions/setup-node@v3
        with:
          node-version: 18
          registry-url: "https://registry.npmjs.org"

      - name: install
        run: yarn install

      - name: build
        run: yarn build
        
+      - name: create release branch
+        run: |
+          git config --global user.name 'github-actions[bot]'
+          git config --global user.email '41898282+github-actions[bot]@users.noreply.github.com'
+          git branch release-${{ env.RELEASED_VERSION }}
+          git push -u origin release-${{ env.RELEASED_VERSION }}
+          git branch -a
+
+      - name: create release
+        run: |
+          curl -X POST \
+            -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
+            -d "{ \"tag_name\": \"${{ env.RELEASED_VERSION }}\", \"name\": \"${{ env.RELEASED_VERSION }}\", \"generate_release_notes\": true }" \
+            https://api.github.com/repos/ikepu-tp/react-mvc/releases

      - name: publish
        run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}

```

## 参考

https://zenn.dev/kshida/articles/auto-generate-release-note-with-calver

https://github.com/increments/qiita-cli/blob/main/.github/workflows/publish-package.yml
【ChatGPT無】ポジティブにして欲しいです。


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

　今回は、ちょっと落ち込むことがあり、ChatGPTさんに協力を要請してみました。

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

　まぁ、
　　たいした
　　　落ち込みでは
　　　　ありません。

　ネタの提供になった、
　　となれば、気分も上昇しますw

　まずはPrompt。
　　うん、たいしたものでは
　　　ありませんねw
```Text:ポジティブ思考にPrompt
ポジティブな思考になるように、私を諭してください。
```
　で、回答です。
***
***ChatGPT***
もちろんです。ポジティブな思考を促進するためのアドバイスをお伝えします：

1. **成功を振り返ろう:** 過去の成功体験を思い出してみてください。その成功はあなたの能力や頑張りの証拠です。成功したことを思い出すことで、自信を取り戻しましょう。

2. **自分の強みを認識しよう:** あなた自身の強みやポジティブな特性について考えてみてください。他人と比較するのではなく、自分自身を受け入れ、誇りに思いましょう。

3. **挑戦を成長の機会と捉えよう:** 過去の困難や挑戦は、成長の機会でした。それらの経験から学んだことを大切にし、将来の自分に役立てましょう。

4. **未来への自信を持とう:** 自分の将来に対して希望と自信を持ってください。目標を設定し、そのために努力することで、明るい未来を築けます。

5. **自分を愛そう:** 最も重要なのは、自分を愛することです。自己評価を高め、自分を受け入れることで、ポジティブな思考が生まれます。

自分の強みと成功を信じ、未来に対して楽観的で前向きな姿勢を持つことが、ポジティブな思考を育む一歩です。
***

　ええと、正直に言います。

　こんなんで、上がるか！！

　まぁ、
　　これで、鬱憤が、
　　　多少、抜けた？ので、良し！

　いや、突っ込まないでねw

　今回は、以上。
Power Query workout - テーブルは行ごとに処理される

エディタでボタンポチポチっていう操作だから、手続きの積み重ねのような動作をしているように思ってしまうかもしれない。ヒトはその方が理解しやすいだろうし、クエリの定義もしやすいってことなのでしょう。だけど、Power Query の中の人 Mashup engine の動作は異なる。

Mashup engine がクエリを評価するとき、その評価結果や途中経過を保存することはない。クエリに定義された処理に必要と判断されれば一時的にキャッシュすることがあるだけだし、Power Query エディタでステップごとに参照できる状態はプレビューであって評価結果や途中経過でもない。

"テーブルは行ごとに処理される" という動作は、 **ストリーミング** という Power Query の基本的な/動作ふるまいのうちのひとつだ。ストリーミングを説明しやすいのでタイトルとして取り上げた。

# たとえば
ストリーミングは Table.AddColumn に限ったはことではないけど、わかりやすいので。
## テーブルに列の追加するとき行われる処理について
```text:Power Query
// Query1
let
    Source = Table.FromColumns(
        {
            List.Numbers( 1, 5 )
        },
        type table [Column1 = nullable Int64.Type]
    ),
    AddedColumn2 = Table.AddColumn(
        Source, "Column2",
        each [Column1] + 10,
        Int64.Type
    ),
    AddedColumn3 = Table.AddColumn(
        AddedColumn2, "Column3",
        each [Column1] * 10,
        Int64.Type
    )
in
    AddedColumn3
```
というクエリの結果は、5行3列のテーブルになる。Power Query エディタでのステップは、
- Source: 5行1列のテーブル
- AddedColumn2: 列を追加
- AddedColumn3: 列を追加

となるが、5行のテーブルに列が追加されるのではなく、行ごとで列を追加する動作を5回繰り返す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193509/6585ebdc-349c-6a73-4ab5-16f684e54442.png)
この動作ができないとステップごとに途中経過を保存することが必要になり、メモリがどれだけあっても足りなくなるから、行ごとの処理は合理的な動作。

### クエリを分割しても同じ
このクエリのステップをそれぞれ個別のクエリに分割しても動作は変わらない。

```text
// Query2_1
let
    Source = Table.FromColumns(
        {
            List.Numbers( 1, 5 )
        },
        type table [Column1 = nullable Int64.Type]
    )
in
    Source
```
```text
// Query2_2
let
    Source = Query2_1,
    AddedColumn2 = Table.AddColumn(
        Source, "Column2",
        each [Column1] + 10,
        Int64.Type
    )
in
    AddedColumn2
```
```text
// Query2_3
let
    Source = Query2_2,
    AddedColumn3 = Table.AddColumn(
        Source, "Column3",
        each [Column1] * 10,
        Int64.Type
    )
in
    AddedColumn3
```

# 思ったこと🙄
そもそも、**Power Query エディタの追加編集したステップの順で処理されるとは限らない** のである。

# その他
https://powerbi.connpass.com/

- [Power BI 勉強会 - connpass](https://powerbi.connpass.com/)
- [Power BI Desktop を使い始めるには](http://qiita.com/PowerBIxyz/items/6c4735cb5b5712e70981)
- [Excel で Power Query を使い始めるには](http://qiita.com/PowerBIxyz/items/52e563037b855a099ca9)
Docker CEのインストールについて

# Docker CEのインストール #

Docker Desktopを利用できず、Docker CEを利用したい場合のインストールメモ。
ここではUbuntu22.04で利用したい場合のコマンドを記載します

公式ページ（https://docs.docker.com/engine/install/ubuntu/ ）を参考にインストールしていきます。

```
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done

sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
```

インストール後
```
docker -v
```
でバージョンが表示されればインストール完了です。

## docker-composeのインストール ##

```
switch_version=$(curl -fsSL -o /dev/null -w "%{url_effective}" https://github.com/docker/compose-switch/releases/latest | xargs basename)
sudo curl -fL -o /usr/local/bin/docker-compose \
    "https://github.com/docker/compose-switch/releases/download/${switch_version}/docker-compose-linux-$(dpkg --print-architecture)"

sudo chmod +x /usr/local/bin/docker-compose
```

インストール後
```
docker-compose -v
```
でバージョンが表示されればインストール完了です。
Youtubeのチャンネル別に最新動画を全部見たい

# 動画の自動再生が歯抜け再生されるのがイヤ
最近、といっても１年位前からだがYoutubeを頻繁に見始めた。
気に入ったチャンネルが１０個くらいあってそれを巡回しているだけなのだが、少し間が開くとチャンネルに２，３個動画が追加されていたりして。
これだけ連続で見て最新動画に追いつきたい。だけど自動再生は歯抜けで過去の動画に飛ばしたりする動き。プチストレス。
そのプチストレスをgreasemonkyスクリプトで解決してみた。
greasyformに登録なんかもしちゃったりして。
[youtube-create-sorted-playlist-related-channnels-when-clicked](https://greasyfork.org/ja/scripts/475584-youtube-create-sorted-playlist-related-channnels-when-clicked)

# スクリプト
```javascript:code
    // ==UserScript==
    // @name        youtube-create-sorted-playlist-related-channnels-when-clicked
    // @namespace   Violentmonkey Scripts
    // @match       https://www.youtube.com/*
    // @grant       none
    // @version     1.0
    // @author      -
    // @description 2023/9/18 17:09:04
    // @require     https://code.jquery.com/jquery-1.12.4.js
    // @license MIT
    // ==/UserScript==
    var enable_flag = true; // until page reload
    var str_enablebtn_txt = "#auto create channnel's playlist: ";
     
    var func_tmp01 = function(str_link) {
    	str_link += "&list=UL01234567890";
    	document.location = str_link;
    };
    document.addEventListener('yt-navigate-finish', () => {
        // enable / disable btn
        var place = $(document).find("ytd-playlist-panel-renderer > div:nth-child(1), yt-chip-cloud-renderer > div:nth-child(1), body > yt-live-chat-app");
        var enable_btn = $('<span class="ycsprcwc_btn01" style="display: inline-block; padding: .25em .5em; color:#FFF; font-size: 1.5em; background: #333; border: 2px dotted #FFF; border-radius: .35em; text-decoration: underline; cursor: pointer;">'+str_enablebtn_txt+((enable_flag)?"on":"off")+'</span>');
        if ($('body .ycsprcwc_btn01:visible').length < 1) {
            place.prepend(enable_btn);
        }
        // Check URL
        var str_link = String(window.location.href);
        if (/\&list\=/.test(str_link)) { return; }
        if (/watch\?v\=/.test(str_link)) {
            if (enable_flag) {
                func_tmp01(str_link);
            }
        }
    });
    $(document).on("click", ".ycsprcwc_btn01", (e) => {
        if (enable_flag) {
            enable_flag = false;
        } else {
            enable_flag = true;
        }
        $('.ycsprcwc_btn01').text(str_enablebtn_txt+((enable_flag)?"on":"off"));
    });
```

# 解説と感想
func_tmp01のとこで謎の文字列をURLに添加してるが、ここを変えれば自分好みの順番に再生リストをソートできるぞ。

基本はリロードが余計に走らないようにURL判定して、有効化フラグを見つつ、URLを書き換えているだけ。
トリガは動画クリックなど、ページ遷移でURLが変化したときに発火されるイベント。
有効化／無効化ボタンはいちいちgreasemonky側で制御させるのが面倒な一時的な利用が多いと思われたため追加した。
フラグはＦ５など自前でページリロードを行うまでは保持してくれるようだ。（通常のリンククリックページ遷移ではリセットされない）

自分でGreaseMonkeyのスクリプトを作るのは初めてだったが、簡単にできてしまった。
GreaseMonkyとは、要するにブラウザのcss差し替えプラグインのjs版だと捉えていい。
特定のサイトで自分の好きなスクリプトを動かすことができる。
実際、こんなに簡単なコードで１年来の悩みが解決できてしまった。

ほかに、[YouTubeで自動翻訳字幕（日本語）を常にオン](https://greasyfork.org/ja/scripts/391647-youtube%E3%81%A7%E8%87%AA%E5%8B%95%E7%BF%BB%E8%A8%B3%E5%AD%97%E5%B9%95-%E6%97%A5%E6%9C%AC%E8%AA%9E-%E3%82%92%E5%B8%B8%E3%81%AB%E3%82%AA%E3%83%B3)なんかがよく海外動画を見る人には便利かもしれない。
つかおう、GreaseMonkey！
Node.jsとmysql2/promiseでqueryを使ったデータの取得

# はじめに
Node.jsとmysql共に初めたてなのですが、mysql2でのデータ取得ができるまでかなり時間がかかったので、データ取得の方法を共有したいと思います。

# コード内容
自分の場合はcreateConnectionをうまく動作させることができなかったためcreatePoolを使っています。
またconnection.queryはそのまま使うとエラーが出るため、async/awaitを使ってconnection.queryでデータを取得しています。
``` js
const mysql = require('mysql2/promise');

//host,user,password,databaseの部分は接続したい先によって変えてください
const connection = mysql.createPool({
    host: 'your_host',
    user: 'your_user',
    password: 'your_password',
    database: 'your_database'
});

//your_tableの部分は適するテーブルの名前に変えてください
async function getQuery() {
    try {
        const [results, fields] = await connection.query('SELECT * FROM your_table');
        console.log(results);
    } catch (err) {
        console.error(err);
    }
}

getQuery();
```
以上のコードでyour_tableにカラムが入っていればconsoleに表示されるはずです。
ROSによるカメラキャリブレーション(円形パターンを使う場合)

## カメラ内部パラメータとは

カメラ画像に映った物体が3次元空間上でどこにあるのかを求めるために、画像座標系と空間座標系の変換行列(=内部パラメータ)を求める必要がある

## rosを使ったキャリブレーション

一部のカメラでは内部パラメータが/camera_infoトピックで出力されている場合があるが、そうでないカメラでもsensor_msgs/Imageトピックが出ていれば、camera_calibrationパッケージで内部パラメータを推定する事ができる

```bash
#四角形パターン(チェッカーボード)を使う場合
rosrun camera_calibration cameracalibrator.py --square 0.04 --size 4x11 image:=/usb_cam/image_raw
```

--squareには四角形の1辺の長さ、--sizeには白と黒の四角形の交点の数(四角形の数ではない)を指定する

image:=の後はカメラから出ているsensor_msgs/Imageトピック名を指定する

## 円形パターンを使う場合

円形パターンを使うときの情報があまり無いので書いておく

円形パターンの対称/非対称の違いについては[Mathworksの解説ページ](https://jp.mathworks.com/help/vision/ug/calibration-patterns.html)が分かりやすい

対称パターンはステレオカメラには使えないらしい

### 対称パターン

円が格子状に並んでいるもの

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155998/7b2c0e72-dbf4-9d14-96a0-4aca91d224bc.png)

**--pattern circles**を追加し、--squareには円の中心間の距離[m]、--sizeには円の配置を指定する

```bash
rosrun camera_calibration cameracalibrator.py --pattern circles --square 0.04 --size 4x11 image:=/usb_cam/image_raw
```

### 非対称パターン

円が段違いに配置されているもの

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155998/9462c30b-edbf-8789-1578-4c4f6c5081e7.png)

**--pattern acircles**を追加し、--squareには円の中心間の距離[m]、--sizeには円の配置を指定する

```bash
rosrun camera_calibration cameracalibrator.py --pattern acircles --square 0.04 --size 4x11 image:=/usb_cam/image_raw
```

## 非対称パターンのサイズの考え方

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155998/55a170a3-6b77-93e9-19d7-4a8cc6eaf580.png)

引数を間違えるとキャリブレーションが開始しないので注意

## 画像引用

[Calibration Patterns -MathWorks](https://jp.mathworks.com/help/vision/ug/calibration-patterns.html)
[Camera Calibration Patterns -nerian.com](https://nerian.com/support/calibration-patterns/)
UpCloudに後からSSH接続先を増やしたい

# UpCloudに後からSSH接続先を増やしたい #

UpCloudを利用した際に後からSSH接続を増やす方法についての備忘録です。
https://upcloud.com/

Upcloudは、サーバーを立ち上げると時に、管理者ページからSSHの接続先を設定することができます。しかし、後からSSH接続を増やすときにはサーバー側で設定する必要があります。
まずは既に登録してあるSSHでサーバにログインします。SSHなどでサーバーにログインできない場合は、upcloudの管理画面の「console」の「Open the console connection」を使用してください。

ログイン後rootでない場合はrootに切り替えてください
```
sudo su
```

authorized_keysに公開鍵を追加します。

```
vim ~/.ssh/authorized_keys;
```

これで設定は完了し、ssh接続が新たにできるようになります。
GitHubアクションのワークフローを使ってNPMライブラリを公開する方法


こんにちは，ご覧いただきありがとうございます。
前回，NPMライブラリの作り方を簡単にまとめました。

https://qiita.com/ikepu-tp/items/90e32aac354e0a5b0b6e

ただ，毎回`npm publish`をするのは大変なのでGitHubのアクションを使って自動化します。

## 作ったもの

`/.github/workflows/npm-publish.yml`を次のように作成した。
`secrets`に`NPM_TOKEN`という名前でNPMJSで発行したトークンを保存しておいてください。

```yaml:npm-publish.yml
name: npm publish

on:
  push:
    branches:
      - main
    paths:
      - package.json
  workflow_dispatch:

jobs:
  publish:
    runs-on: ubuntu-latest

    permissions:
      contents: write

    steps:
      - uses: actions/checkout@v3
        with:
          ref: main

      - uses: actions/setup-node@v3
        with:
          node-version: 18
          registry-url: "https://registry.npmjs.org"

      - name: install
        run: yarn install

      - name: build
        run: yarn build

      - name: publish
        run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}

```
ectoで自動生成したSQLでカラム名が重複した際に気になった

# 困ったこと
ecto で同じテーブルをjoinした際に、カラム名が被るので気になった
(実害はなし)

# 原因
同じテーブルなのでしょうがない

# 対応

fragmentで別名をつけるのが簡単そう

```elixir
from (

~~~
select %{
~~~
item_name_1: fragment("i1.name AS item1_name"),
item_name_2: fragment("i2.name AS item2_name")
})
|> Repo.all()
```
【SwiftUI】ドラッグでぐりぐり操作できるText部品

# つくったもの
SwitUIのTextをドラッグでぐりぐりと操作できるようにしてみました。
![demo5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77444/b9229eca-9557-1552-71e2-b1e65b89e482.gif)

## できること
- テキストの回転、サイズ変更
- テキストの色の変更
- テキストのドラッグ移動

## 使用方法
```swift
FancyText(text: "Sample Text")
```

```swift
// フォントサイズと色を指定する場合
let fontSize = UIFont.preferredFont(forTextStyle: .largeTitle).pointSize
FancyText(text: "Sample Text", fontSize: fontSize, color: Color.primary)
```

# 実装ポイント
標準のTextをそのまま使用し、overlayを使って動作を拡張しました。DragGestureでドラッグ操作を捕捉し、rotationEffectで回転を反映させます。

## 回転角度の求め方
仮想的な外周円を設定し、DragGestureで通知される移動座標から、ピタゴラスの定理と三角関数を順番に適用し、Textの角度と大きさを求めていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77444/3982e682-9137-0adc-5d30-abc85b98650f.png)

```swift:(実装コードの抜粋)
Image(systemName: "arrow.counterclockwise")
    .padding(4)
    .clipShape(Circle())
    .position(handlePosition)
    .gesture(
        DragGesture()
            .onChanged { value in
                // 中心点からハンドルとの距離(外周円の半径)
                let dx = value.location.x - center.x
                let dy = value.location.y - center.y
                r = sqrt(pow(dx, 2) + pow(dy, 2))
                
                // ハンドル位置とのオフセット角度
                offsetAngle = atan2(rectSize.height, rectSize.width)
                
                // 長方形の回転角度（ハンドルが右下角にあるためその分補正する）
                rotationAngle = atan2(dy, dx) - offsetAngle
                
                // 外周円に内接する長方形の辺の長さ
                // https://keisan.casio.jp/exec/system/1161228786
                let newWidth = r * 2 * sin(centralAngle1 / 2)
                let newHeight = r * 2 * sin(centralAngle2 / 2)
                
                // 位置とサイズを更新
                DispatchQueue.main.async {
                    handlePosition = CGPoint(x: center.x + dx, y: center.y + dy)
                    rectSize = CGSize(width: newWidth, height: newHeight)
                }
            }
    )

```

## 再タップ時のハンドル座標の求め方
Textをもう一度タップした場合はハンドルを再表示するために、現在の回転角度からハンドルの座標を求める必要があります。回転行列の公式を利用して、ハンドル(長方形)の４点の座標を求めます。

```swift
func rotatedRectangleVertices(center: CGPoint, size: CGSize, angle: CGFloat) -> [CGPoint] {
    let halfWidth = size.width / 2.0
    let halfHeight = size.height / 2.0
    
    // 長方形の4つの頂点（中心を原点として）
    let points = [
        CGPoint(x: -halfWidth, y: -halfHeight),
        CGPoint(x: halfWidth, y: -halfHeight),
        CGPoint(x: -halfWidth, y: halfHeight),
        CGPoint(x: halfWidth, y: halfHeight)
    ]
    
    return points.map { point in
        // 回転行列を使用して各点を回転させる
        let x = center.x + (point.x * cos(angle) - point.y * sin(angle))
        let y = center.y + (point.x * sin(angle) + point.y * cos(angle))
        return CGPoint(x: x, y: y)
    }
}
```


## サンプルコード
https://github.com/yuppejp/FancyTextSample

## 参考URL
- [弓形の計算方法 - keisan](https://keisan.casio.jp/exec/system/1161228786)
- [2次元の回転行列 - 「なんとなくわかる」大学の数学・物理・情報](https://www.krrk0.com/two-dimensional-rotationmatrix/)