OmniAICreator/Qiita-1.07M huggingface dataset:
github actionsで、inputで与えられたstringをparseして、arrayとして扱う

# やりたいこと

- github actionsで、手動でE2E自動テストをトリガーしたい
    - このとき、実行するテストシナリオを指定したい
        - 明確に影響範囲が分かっているときなど、全件実行しなくていよいケースをカバーしたい
        - テストを実行するジョブを、matrixを使って簡潔に書きたい
        - inputの型は number/string/boolean/environmentしかサポートされていないため、そのままでは代入できない

そのため、 `fromJSON()` を使ってstringをarrayに変換する必要がありました


# やったこと

要件を分解するとこうです
1. 入力をstringで受け取る
1. `fromJSON()` でparseできる形に変換する (この時点ではまだstring)
1. `fromJSON()` を使い、arrayに変換する
1. 変換したものをmatrixへ代入する


## `fromJSON()` でparseできる形に変換する

これを実現する手法はいくつか考えられますが、今回は筆者が慣れているpythonを使うことにしました
~~令和にshを勉強したくなかったためです~~

ちなみに`runs-on: ubuntu-latest` は2024/01/24現在でubuntu22.04らしく、python3が最初からインストールされています
大変ありがたい

ない場合は `uses: actions/setup-python@v5` で簡単に導入できます

もちろんrubyなどでも同様に実現できると思うので、都度読み替えてください
shではjqあたりと格闘すればできる気がしますが「これpythonのほうが早いな」と思って調べるのを辞めました

### `hoge fuga poyo` を `["hoge", "fuga", "poyo"]` に変換する
pythonはstringをlistに変換する `split()` という大変ありがたい組み込み関数が用意されているので、それを使います
```python
>>>'hoge fuga poyo'.split()
["hoge", "fuga", "poyo"]
```
もうほとんど達成できてますね 神
ちなみに [`split()` は初期状態では半角スペースをセパレータとしています ](https://docs.python.org/ja/3/library/stdtypes.html#str.rsplit)

ただコレだけでは駄目で、ジョブからジョブへ値をパスするには環境変数 `$GITHUB_OUTPUT` を経由する必要があります
pythonの `print()` はそのまんま標準出力をしてくれるので、そのストリームをぶちこめばOKです

```yml
jobs:
  parse-scenario-str-to-array:
    runs-on: ubuntu-latest

    steps:
    - name: parse scenario
      id: parse-scenario
      run: |
        python -c "print('scenario-str=' + str('${{ github.event.inputs.choice-scenario-names }}'.split()))" >> $GITHUB_OUTPUT

    outputs:
      scenario-str: ${{ steps.parse-scenario.outputs.scenario-str }}
```
改行したかったんですがインデントのエラーを吐いちゃうのでとりあえずコレでいきます
薄目で見てください
`$GITHUB_OUTPUT`に `key=value` という値を保存しておけば、別のstepやjobからもkeyを頼りにアクセスすることができるようになります
めでたい

## `fromJSON()` を使い、arrayに変換する

github actionsは、arrayを与えることで「似てるけどちょっと違う条件のジョブ」をたくさん実行できる機能があります
[詳しくは公式ドキュメントを見ましょう](https://docs.github.com/ja/actions/using-jobs/using-a-matrix-for-your-jobs)

静的に書く場合こんなかんじです
```yml
jobs:
  e2e-autotest:
    strategy:
      matrix: ["page-a", "page-b", "page-c"] # ここを動的に差し替えたい
    steps:
    (略)
```

で、公式ドキュメントを見ると [`fromJSON()` なる関数を使えばstringからarrayやdictionaryに変換できるらしい](https://docs.github.com/ja/actions/learn-github-actions/expressions#fromjson)のでやっていきます


```yml
jobs:
  parse-scenario-str-to-array:
    (略)

  e2e-autotest:
    runs-on: ubuntu-latest
    needs: parse-scenario-str-to-array

    strategy:
      matrix:
        scenario-names: ${{ fromJSON(needs.parse-scenario-str-to-array.outputs.scenario-str) }}

    steps:
    - name: E2E自動テスト実行 ${{ matrix.all-scenario-names }}
      run: |
        echo "${{ matrix.all-scenario-names }}"
```
job `parse-scenario-str-to-array` に対して `needs` 経由で触れていますが、多分絶対path?でも触れられると思います(試していません)

一応ハマりどころとしては `fromJSON()` 自体を式として評価する必要があることに注意です
```
:o: ${{ fromJSON(some.variable) }}
:x: fromJSON(${{ some.variable }})
```
PowerVSのPER環境に複数ワークスペース、複数サブネットを作った時の動作確認

PowerVSのPER環境に複数ワークスペース、サブネットを作った時の動作確認をしました。

2024年1月時点で、PERを利用可能なフランクフルト（Frankfurt 1, Frankfurt 2）で確認しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/b2616cdc-a9c6-c595-65cd-22759e8b3928.png)

# 設定作業

・ワークスペースを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/e079139b-9350-bacc-8ddf-459cf8a69e64.png)

・各ワークスペース内にサブネットを作成
・各サブネット上に1つずつLPARを作成
・必要に応じ、各AIX上の静的経路を設定（宛先サブネット宛のパケットのnext hopを、プライベート側ゲートウェイに設定）
・各ワークスペースをTransit Gatewayに接続

PER環境なので、`Direct Link`でなく、`Power Systems Virtual Server`としてTransit Gatewayに接続できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/c79c6451-ec65-ad13-45e5-0f670c5c5268.png)

各ワークスペースから経路情報が広告されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/1a9bda4b-f07a-c14c-4a63-288e7c5c4257.png)

# 結果

下記の通信ができました。
・同一ワークスペース内の異なるサブネット間（ワークスペース1内）
・異なるリージョンのワークスペース間（ワークスペース１とワークスペース３、ワークスペース2とワークスペース3）


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/fb606fcc-7810-b3d6-8583-100bdae815e6.png)


下記の通信も可能です。
・同じリージョンの異なるワークスペース間（ワークスペース1とワークスペース2）

:::note
この通信は、以前はできませんでしたが、2024年5月に可能になりました。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/f74ecc23-864e-3a1d-16d7-ed9db672b704.png)

以上
GeForce RTX 4090で映像出力ができなかった話とその対処法

# はじめに
最近，`GeForce RTX 4090`を購入して，それでPCを組み上げたが，そのときにPCが立ち上がらなくなってしまった．

症状は「電源投入後に十秒程度グラボが光るものの，その後グラボの電源が落ちる」というもの．


# TL;DR
対処法は以下の通り．

- BIOSを書き換える


# 原因究明
そのPCには元々`GeForce GTX 1650`が入っており，それに合わせて電源も変更していた．その際に配線を誤った可能性を考え，`GeForce GTX 1650`に換装して電源を投入したところ，問題なく動作した．
そのため，配線の問題ではないと判断．

そういえば，最新のパーツを使用すると互換性の問題が解消できていない可能性があるとか無いとか？
とはいえ，パーツの互換性は購入してしまった以上どうしようもないので，何か対処法が無いか検索してみる．すると，以下のような記事を発見．

https://www.nichepcgamer.com/archives/nvidia-geforce-rtx-4090-4080-gpu-uefi-firmware-update-tool-1-2.html

なるほど，BIOSのアプデが必要と．


# 対処法
BIOSの更新とのことなので，先ずはマザボの型番を確認．
実は，今回扱っているPCを初めに組んだのは私ではないので，他の部品の品名とか全く分からない......
Google先生に画像検索で確認したところ，おそらく`ASUS TUF B450-PLUS`だと判明．

ASUSからBIOSが提供されているので，それをUSBに書き込み，BIOS Flashbackを使って更新した．
なお，本記事では詳細な方法については記載しない．各メーカの公式ページを見て進めるのが，最も安全であるからである．

いくつかのBIOSのバージョンを試してみたが，私の環境では

https://www.asus.com/jp/motherboards-components/motherboards/tuf-gaming/tuf-b450-plus-gaming/helpdesk_bios?model2Name=TUF-B450-PLUS-GAMING

で無事に動作した．

:::note alert
BIOSの操作はかなりセンシティブで注意事項が多い．PCに疎い人にはオススメできないのはもちろん，ある程度経験のある人でも注意が必要．
個人的には各メーカから出ている注意事項を精読してから取り組むことをオススメし，PCに重要なデータが含まれる場合はバックアップを取ってから作業することをオススメする．
例えば，ASUSであれば以下のページで注意事項が記載されている．

- [[マザーボード] BIOS Flashback™ の使い方](https://www.asus.com/jp/support/FAQ/1038568/)
:::
phpのアロー演算子（->）が意味わからん。

今回は毎回わからなくて困っていたアロー演算子について説明していこうと思います。
過去の記録を遡ってみるとアロー演算子がわからなくて調べるのは３回目でした。
図にもしてみたのでわかりやすくなっているかと思います。

# アロー演算子を一言で表すと
**クラスの関数（メソッド）や変数（プロパティ）を使うためのツール**
です。

これから具体的に説明していきます。

# クラスとは
関数（メソッド）や変数（プロパティ）を持つオブジェクトの雛形です。
オブジェクト指向とは？？ということについては[こちらの記事](https://unison-career.com/engineer-media/6250/)が参考になります。

クラスのコードの例は以下の通りです。
```php
class クラス名{

    public $プロパティA = "プロパティA";
    public $プロパティB = "プロパティB";

    public function メソッド名(){
        //処理内容
    }
}
```

例えば"表紙の色"と"ページ数"を決めてノートを作る例を考えてみましょう。
その場合上記のコードは以下のように書くことができます。
```php
//ノートの設計図クラスnotebook
class notebook{

    //ノートの表紙の色、初期値は青色
    public $color = "青色";
    //ノートのページ数、初期値は５０
    public $pages = "50";

    //ノートを作成するメソッドcreate
    public function create(){
        echo "このノートの表紙は" . $this->color . "で" . $this->pages . "ページあります。";
    }
}
```
この時createでは`$this->color`と記述することで、クラス内のプロパティである`color`の内容を呼び出しています。

# インスタンスを作る

先ほど作った設計図（クラス）を元に実体（インスタンス）を作っていきます。
<details><summary>オブジェクトとインスタンス</summary>

:::note info
オブジェクト：さまざまな実体の総称
インスタンス：クラスを元に作成したオブジェクトの実体のこと
:::
引用：[インスタンスとオブジェクトの違い - ITを分かりやすく解説](https://medium-company.com/%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9-%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88-%E9%81%95%E3%81%84/)
</details>

インスタンスを作るには以下のように記述します。
```php
$インスタンス名 = new クラス名();

//notebookクラスのインスタンスを作成
$mynotebook = new notebook();
```

# 関数を呼び出してみる
ではアロー演算子を使ってクラスnotebookの機能を使ってみます。
```php
//関数createの呼び出し
$mynotebook -> create();
```
呼び出すと、「このノートの表紙は青色で50ページあります。」と出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524128/a4765c49-d815-9994-458a-183bb40ed228.png)


# 変数を呼び出してみる
ではnotebookの変数を呼び出し、表紙の色やページを自分好みに変えてみます。
```php
//表紙を黄色にする
$mynotebook -> color = "黄色";
//３０ページにする
$mynotebook -> pages = "30";
//関数createの呼び出し
$mynotebook -> create();
```
以上の場合「このノートの表紙は黄色で３0ページあります。」と出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524128/54a4cd16-d0db-af0c-2a12-2fa3c1b3be40.png)

# まとめ
これまでのやったことを図にまとめると以下のようになります。
（文字が読みにくかったら申し訳ありません。）

![スクリーンショット 2024-01-24 17.27.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524128/855d3120-2171-65b4-9165-96dfd899baad.png)

少しでも理解していただけると幸いです。
読んでいただきありがとうございました。

### 参考・引用

https://magazine.techacademy.jp/magazine/19296

https://webukatu.com/wordpress/blog/28942/
Visual StudioとPythonでWebスクレイピングを入門してみる

# 概要
[Visual StudioでPythonを試してみる](https://qiita.com/GOROGOROMOGUMOGU/items/9c15a0cf5435ea15163a) で開発環境を作りました。
今回は、もう少しPythonを学習します。
ネタは、Webスクレイピングです。

以下のライブラリを使います。
Requests 2.31.0
Beautiful Soup 4.12.3

# ライブラリのインストール
## パッケージのインストール手順
1\. ソリューションエクスプローラー → Python 環境 → すべてのPython 環境を表示

![すべてのPython環境.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/b01e3e16-c821-7e2b-3d33-ca098829cca8.png)

2\. Python 環境 → パッケージ(PyPl)

![パッケージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/e07e16d1-b5fc-1605-202b-3fa2ae1517a4.png)

3\. 検索フィールドにライブラリ名を入力
　→ [次のコマンドを実行する: pip install ライブラリ名]を押下する
 
![検索フィールド-入力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/96ae922a-b6c4-9049-411e-9b06788de276.png)

4\. 「今すぐ昇格」を選択

![昇格.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/71d4a621-a7aa-b87e-9644-09d99b4a813a.png)

5\. 完了

![完了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/0f73b182-d359-5c23-4e48-921df84dd581.png)

## Requestsライブラリ
検索フィールドに「Requests」を入力して[パッケージのインストール手順](https://qiita.com/GOROGOROMOGUMOGU/items/65ca51c6dd0977b668c8#%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%89%8B%E9%A0%86) を実施する

## Beautiful Soupライブラリ
検索フィールドに「BeautifulSoup4」を入力して[パッケージのインストール手順](https://qiita.com/GOROGOROMOGUMOGU/items/65ca51c6dd0977b668c8#%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%89%8B%E9%A0%86) を実施する

# HTMLデータの取得

Yahooのリアルタイム検索を取得してみる
```py:PythonApplication1.py
import requests
url = "https://search.yahoo.co.jp/realtime"
response = requests.get(url)
print(response.text)
```

実行してみる

![HTMLデータの取得.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/d0dbffb3-b5c6-e202-2fc7-1a95ba4a2a37.png)

# HTMLデータの解析と抽出

Yahooのリアルタイム検索のキーワードを抽出してみる
```py:PythonApplication1.py
import requests
from bs4 import BeautifulSoup

url = "https://search.yahoo.co.jp/realtime"
response = requests.get(url)

soup = BeautifulSoup(response.text, "html.parser")

for item in soup.select('article > h1'):
    print(item.text)
```

実行してみる

![実行する.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/51d9605a-dc4c-101d-1686-221ea2e9013f.png)

実際のページ

![Yahooリアルタイム検索.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/757f37e4-e1e5-038c-6758-6e790dd3d4a9.png)

# 参考URL
[Pythonで始めるWebスクレイピング入門！](https://techplay.jp/column/601)
[手順 5: Python 環境へのパッケージのインストール](https://learn.microsoft.com/ja-jp/visualstudio/python/tutorial-working-with-python-in-visual-studio-step-05-installing-packages?view=vs-2022)
【C】printfのバッファサイズによる処理速度の変化

## TLDR
`setvbuf`で標準出力にバッファを設定して処理時間を計測するだけです。
バッファは大きいほうがいいけど処理速度の向上が期待できるのはある程度の大きさまで。

## printfの仕様
知っている人には当たり前のことですが`printf`は直接コンソールに文字列を出力させる関数ではありません。まずバッファへと内容を書き込み、そののちにバッファからコンソールに出力がなされます。

バッファからコンソールに出力されるタイミングですがデフォルトでは

* バッファサイズを上回る文字数を入力する
* 改行文字を入力する
* `fflush(stdout)`を使う
* プロセスが終了する(このときは文字化けする。なんでだろ)

となっていることが多いです。これは行バッファリングに相当します。
C言語では他に改行文字での出力を行わない完全バッファリングと一切バッファリングを行わないバッファリングなしモードがあります。

## 自分でバッファを設定する
`setvbuf`という関数を使います。第1引数でバッファを設定するストリームを指定し、第2引数で自分で用意したバッファを渡し、第3引数でバッファリングモードを指定します。
* _IONBFがバッファリングなし
* _IOLBFが行バッファリング
* _IOFBFが完全バッファリング

となっています。第4引数はバッファの大きさです。
```c:format
#include <stdio.h>
int setvbuf(FILE *stream, char *buf, int type, size_t size);
```
例えば標準出力(stdout)に対して2文字分4バイトのバッファを設定するとこんな感じです。
```c
char streamBuf[2];
if(setvbuf(stdout,streamBuf,_IOFBF,sizeof(streamBuf)) != 0){
    perror("ERROR\n");
    return 0;
}
```

## バッファサイズによる処理速度の変化
バッファのサイズを変更しながらそれぞれについて`printf`で"Hello World!"を1万回表示し、その処理時間を計測します。
```c:test.c
#include<stdio.h>
#include<time.h>

#define LOOP_MAX 10000
#define BUF_MAX 1024*4

int main(void){
	clock_t cpu_time_start;
	clock_t cpu_time_end;
	double result_time;
	FILE *fp;

	fp = fopen("test.txt","w");
	if(fp == NULL){
		perror("ERROR\n");
		return 0;
	}

	for(int buffer_size = 1 ;buffer_size <= BUF_MAX ;buffer_size *= 2){
		char streamBuf[buffer_size];
		if(buffer_size == 1){
			if(setvbuf(stdout,NULL,_IONBF,0) != 0){
				perror("ERROR\n");
				return 0;
			}
		}else{
			if(setvbuf(stdout,streamBuf,_IOFBF,sizeof(streamBuf)) != 0){
				perror("ERROR\n");
				return 0;
			}
		}
		cpu_time_start = clock();
		for(int i = 0;i < LOOP_MAX;i++){
			printf("Hello World!");
		}
		fflush(stdout);
		cpu_time_end = clock();
		result_time = (double)(cpu_time_end - cpu_time_start)/CLOCKS_PER_SEC;
		fprintf(fp,"%d,%f\n",buffer_size,result_time);
	}
	fclose(fp);
	return 0;
}
```

## 実行結果
注 2バイトに対応するところはバッファなしの結果(_IONBF)
![graph1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629545/37ca4300-04d9-311a-f66a-c4d03f574743.png)
少し見にくいですがバッファが小さいうちはバッファサイズを倍にすると処理時間がおよそ半分になっているのが確認できます。

これはバッファはRAM上にあり、バッファへのアクセス速度は出力(今回は画面)へのアクセス速度に比べて非常に速いために起こっていると考えられます。
例えばバッファが4バイト(2文字分)の場合バッファなしの場合に比べて出力へのアクセス回数は半減しますからそれにより処理時間も半減しています。

横軸は指数オーダーなので縦軸もそれに揃えます。
![graph2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629545/f30df369-a345-c747-338d-c0876471bd2e.png)
バッファが大きくなるにつれ傾きが緩やかになっていくのが確認できます。これはバッファサイズが大きくなるにつれバッファへの書き出しにかかる時間が大きくなって無視できなくなることや、その他オーバーヘッドによるものと考えられます。

バッファとして使える領域は有限ですしただひたすらに大きく設定すればいいってもんでもなさそうです。
fortranでのオブブジェクト指向プログラミング。fortran moduleの使い方を2種類に限定すること

fortran ではシングルトン型のオブジェクト指向プログラミングを志向すべきであり、
そのクラス=インスタンスにmoduleを使うことになる。
プログラム起動時にすでに、それらのインスタンスは生成されている。

この考え方で言えばモジュールには主に以下の2種類の使い方に限定すること

## その１：複数のサブルーチンを取りまとめる。
`複数のサブルーチンがcall-caller treeで結びついているときにその親玉(複数ありえる）を中心に一つのモジュールに入れる`
publicな関数を指定する。原則的にモジュール変数はつかわない（サブルーチンの間のデータのやり取りが見えなくなる。変数のスコープを重視してコードを書くこと）。useしてcallすることで（基本的に必ずonlyをつける）、コンパイラが呼び出し側との間の変数の整合性チェックができる（optional変数、名前結合などでは必須）。単独のサブルーチンをモジュール化しておくのも、これらのご利益を得るために行うこともありえる。

## その２：出力変数をモジュール変数とする。
`サブルーチンを複数含んでいる。同時にモジュール変数も含んでいる。
* サブルーチンの引数はすべて入力引数。入力引数は、指示変数と言えるスカラーや簡単なベクトル（たいていは固定長）だけ。
* モジュール変数に出力する。出力変数はprotectする。
* 他のモジュールの変数を見るときにはuse onlyを書く。

コンセプトとしては、他のモジュール内に格納されているデータ、引数として渡される指示を見て、自分自身の中にデータを作って貯める、ということ。他のモジュールにはそれを変更することはできない。読み出すのみ。アロケートするのもこのモジュール内で行う。

この書き方だとサプルーチン出力を左辺に書けない、などはあるけれど、論理構造としてはクラスを使って書くオブジェクト指向的なコードと同等になる。
「（必要ならば指示的な変数を与えてモジュール初期化。不要な場合も多い）ー＞指示的な変数を与えてのモジュール関数呼び出しでモジュール出力変数をセットする」というのがプログラムの流れになる。モジュールへの入力は基本的にはuse,onlyで他のモジュール変数を参照することで行う。モジュール関数を呼び出すとき、その引数として大きなサイズの変数を受け渡さない。

**そもそもfortranで書けるのはここまで。大きなプログラムをfortranで書くべきでないと思う。**

## (その３：typeの取りまとめなど）
そもそもtypeは極力使わないのがよいと考えているが私はpointer arrayを作る方法（原子ごとに長さの違う配列をつくるなど）がtypeの配列を作る以外に思いつかないのでしかたなく用いている。
https://github.com/tkotani/ecalj/blob/master/SRC/subroutines/m_struc_def.f90
(type s_specは消したいがまだ消せてない）。

---

ただ、プログラミングはどうしても、古い書き方、新しい書き方、試行的な書き方、などが共存するものになる。柔軟対応が必要。syntax sugarのレベルの差異にはこだわりすぎない方がいいーただし場合によれば書き方次第で、論理構造がスッキリとする。人間に読みやすいコードはcopilotにも読みやすい。
Visual StudioでPythonを試してみる

# 概要
必要に迫られてPythonを学習することになりました。
せっかくなので、学習記録を残します。
VSCodeでの記事が多いので、今回はVisual Studio202を使います。

# 開発環境
Windows11 Home 64bit
Python 3.11
Visual Studio2022、コミュニティエディション

 **前提** 
[Visual Studio Community](https://visualstudio.microsoft.com/ja/vs/community/) はインストール済であること

# Python インストール
1\. Microsoft Storeで「Python」を選択して入手する

![pythonダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/94e84735-8bd4-4fea-db0a-1f9dc25c0d96.png)

2\. インストール完了

![pythonダウンロード完了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/0cba9219-1f38-e56a-75a8-916418e3ca18.png)

# Pythonワークロード インストール
1\. Visual Studio Installerで「Python開発」を選択してインストールする

![インストール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/9fb01204-ff72-f38f-255f-e8b8164dbec1.png)


2\. Visual Studioを起動して [新しいプロジェクトの作成] →「Pythonアプリケーション」テンプレートを選択して「次へ」

![pythonアプリケーション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/dc133832-4251-07d7-0cb9-155d65129466.png)

3\. プロジェクト名などを設定して「次へ」
4\. プロジェクト作成完了

![プロジェクト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/fc9966ac-bc29-2438-d311-38a7125980c2.png)

# Hello Worldしてみる
```py:PythonApplication1.py
print("hello world.")
```
開始▶を押下する

![開始.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/ebc6a538-9419-dea6-c4e4-174d31518e54.png)

![Hello World.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674221/b5b3bcdc-eeb7-c4e0-8adb-d362b6cef164.png)


# 参考URL
[Python のインストール](https://learn.microsoft.com/ja-jp/windows/python/beginners#install-python)
[Visual Studio での Python サポートのインストール](https://learn.microsoft.com/ja-jp/visualstudio/python/installing-python-support-in-visual-studio?view=vs-2022)
Ubuntu Linux 上の VirtualBox で Kernel driver not installed エラー

久しぶりに VirtualBox を使ったらエラー。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/1ac66174-cbc0-0d7a-b51b-a06121d830b2.png)

カーネル更新が入ったかな?

# 環境

- Ubuntu 22.04 LTS

```
$ uname -a
Linux nanbuwks-B550M-S2H 6.3.13-060313-generic #202307111431 SMP PREEMPT_DYNAMIC Tue Jul 11 18:37:56 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
```

- VirtualBox 6.1.48

# modprobe でエラー

エラーメッセージの通り、

```
$ sudo modprobe vboxdrv
```
 とすると
 
```
modprobe: FATAL: Module vboxdrv not found in directory /lib/modules/6.3.13-060313-generic
```
エラーが発生しました。

# dkms 

dkms を使います。本来は最初のインストール時に dkms を設定するべきだったのでしょうが、サボってたようです。
```

$ sudo apt-get install virtualbox-dkms
```

これがうまく終わったので、modprobe をしてみます。

```
$ sudo modprobe vboxdrv
```

今回はエラーは発生しませんでした。

このあと、VirtualBox を動作させると無事動きました。
15分でTencent Cloudでパルワールド/Palworldマルチプレイ専用サーバーを立てる方法をご紹介

## はじめに
こんにちは、Tencent Cloudのソリューションアーキテクトのりょうです。
2024.1.23時点で[パルワールド](https://twitter.com/Palworld_JP) を現在プレイ中のSteamユーザーが１８５万人を突破しました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/46b1c0af-6a1b-8377-ca1e-c9afa9b2c0db.png)
歴代ゲーム史上２位！メガヒット！！！
専用サーバーを立てると、友人とプライベートでパルワールドを楽しむことができます。
[パルワールドの公式専用サーバーを立てる方法](https://tech.palworldgame.com/dedicated-server-guide#qa)を参考して、サーバー設定の部分をスクリプト化しているのでコマンドを叩くだけで簡単にTencent Cloudで専用サーバー構築できます。
早速にTencent Cloudで構築してみたいと思います。

## サーバーの購入
コスパを考慮し、Tencent Cloud Lighthouseを選択します。
購入スペック：
|  CPU   | 4Core |
|  ----  | ----  |
| Memory | 16GB |
| Disk  | 150GB |
| OS  | Ubuntu 22.04 LTS |
>安定したサーバー稼働のためには32GB以上を推奨

[Lighthouse購入画面](https://buy.tencentcloud.com/lighthouse)にて購入できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/5d0fbcf0-9794-7408-4b9c-b30a3865a862.png)

【Buy Now】をクリックすると、確認ページに遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/f4eac436-c094-34de-cf81-fb83ca7ca69b.png)
【Submit Order】をクリックすると購入完了！

## サーバー設定
SteamCMDなどインストールをスクリプトで自動化しましたので、
下記のコマンド1行だけで自動的に必要なものをダウンロードしてインストールできます。
``` 
wget -O - https://pal-server-1251810746.cos.accelerate.myqcloud.com/pal-server/Ubuntu/install.sh|sh 
```
ダウンロード＆インストール、約５分かかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/d5f2d622-f0e5-1f6e-aac2-c222643a8da1.png)
コマンドの実行が完了しましたら、`pal-server.servic`のサービスが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/47de710d-eb66-a4fc-3848-85fdda841419.png)

## ネットワークの設定
パルワールドマルチプレイ専用サーバーの通信がport 8211で行うため、Port 8211を開放する必要です。
[Lighthouseコンソール画面](https://console.tencentcloud.com/lighthouse/instance/index?rid=25)にて作成したサーバーをクリックするとPort開放を設定することできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/156c744b-0c75-a0c1-ec65-722f529a1992.png)
`UDP Port 8211`を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/adeb4ca6-32be-f140-6d3f-55b1270a75c5.png)

ここまではサーバーとネットワークの設定が完了！

## サーバーへ接続
ゲームを起動し、【マルチプレイに参加する（専用サーバー）」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/2f32af2b-dd6c-531b-143d-33b65a36f5ae.png)
`サーバーIP:8221`を記入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/3a17367d-e4e5-35d3-4cf1-b6a545f57ff6.png)

以上、パルワールドマルチプレイの専用サーバーの構築が完了しました。友人とプライベートでパルワールドを楽しんでプレイ！
GitHubにSSH接続するためにやったこと

# 内容
- SSH接続とは？
- SSHクライアントとSSHサーバ
- Gitの環境構築(Windows向け)
- GitHubにSSH接続する手順
    1. 公開鍵・秘密鍵の発行
    1. GitHubに公開鍵をアップロード
    1. GitHubへのSSH接続の確認

# 参考サイト
以下のサイトを参考に実施しました。

https://www.kagoya.jp/howto/it-glossary/develop/github_ssh/

# PC環境
OS: Windows11

# SSH接続とは？
　SSHは、遠隔でコンピュータを操作するためのプロトコル(手法)です。主にlinuxなどで用いられます。従来は、TelnetやFTPなどのプロトコルが用いられてきましたが、これらには暗号化の仕組みがないので盗聴などのリスクがありました。SSHでは、[公開鍵暗号方式](https://ja.wikipedia.org/wiki/%E5%85%AC%E9%96%8B%E9%8D%B5%E6%9A%97%E5%8F%B7)によって安全に通信を行うことができるので、現在広く用いられています。GitHubでは、SSH接続だけではなく、HTTPS接続も利用可能なようですが、SSH接続の方が手間が少ないという利点があるそうです。

 # SSHクライアントとSSHサーバ
 　SSH接続の際に、端末側で利用者が操作するソフトウェアのことをSSHクライアントといいます(遠隔操作する側)。一方で、サーバ側で接続を受け付ける方のソフトウェアをSSHサーバといいます。一般的に、SSHサーバはTCPの22番ポートでクライアントの接続を待ち受けています。

# Gitの環境構築
　まず、[Gitの公式サイト](https://git-scm.com/)にアクセスし、ページ内の"Download for Windows"をクリックします。ダウンロードされたインストーラを起動し、指示に従ってインストールを進めます。

 　インストールが終わったら、GitBashというアプリがダウンロードされているはずなので、こちらを起動します。立ち上がったら以下のコマンドを実行してください。ユーザ名とメールアドレスは自分で好きなやつを決めてください。
  ```GitBash:GitBash
  git config --global user.name "ユーザー名"
  ```
  ```GitBash:GitBash
git config --global user.email "メールアドレス"
  ```
  登録情報は以下の2つのコマンドで確認できます。
   ```GitBash:GitBash
git config user.name
git config user.email
  ```

# GitHubにSSH接続する手順
　Gitの環境構築が終わったら、実際にSSH接続を行うための設定を行います。
 
① 公開鍵・秘密鍵の発行
　GitBashにて以下を実行します。保存場所の確認やパスワードの設定確認が行われますが、全部Enterで飛ばしてOKです。
 ```Bash:GitBash
 ssh-keygen -t rsa
 ```
 `ls ~/.ssh`を実行し、id_rsa(秘密鍵)とid_rsa.pub(公開鍵)が生成されていることを確認しましょう。次の手順で公開鍵をGitHubにアップロードしますが、秘密鍵は漏洩しないように大切に保管しましょう。

② GitHubに公開鍵をアップロード
　作成した2つ鍵のうちid_rsa.pub(公開鍵)の方をGitHubにアップロードしていきます。以下のコマンドを実行し、id_rsa.pubの内容をコピーします。
 ```gitbash:GitBash
 clip < ~/.ssh/id_rsa.pub
 ```
 次に、GitHubにアクセスし、「Settings」->「SSH and GPG keys」->「New SSH key」をクリックします。すると、Title, Key type, Keyの3つの情報を入力する画面が表示されるので、以下のように入力します。
 
  Title|Key type| Key 
 -|-|-
 自分の好きなやつ | Authentication Key | 先ほどコピーした公開鍵を張り付ける
 
③ GitHubへのSSH接続の確認
　最後にSSH接続の確認を行います。GitBashで以下のコマンドを実行してください。途中で接続を続けるか確認されるので"yes"と入力します。
```:GitBash
ssh -T git@github.com
```
以上を実行して、自分のユーザ名(githubの方)が表示されたら接続完了です。
コンバータ

```
using System;
using System.Globalization;
using System.Windows.Data;

public class StringToNumericConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is IFormattable formattable)
        {
            return formattable.ToString(null, culture);
        }

        return value?.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string stringValue = value?.ToString();

        if (targetType == typeof(int) || targetType == typeof(int?))
        {
            if (int.TryParse(stringValue, out int intValue))
            {
                return targetType == typeof(int) ? intValue : (int?)intValue;
            }
        }
        else if (targetType == typeof(double) || targetType == typeof(double?))
        {
            if (double.TryParse(stringValue, out double doubleValue))
            {
                return targetType == typeof(double) ? doubleValue : (double?)doubleValue;
            }
        }
        else if (targetType == typeof(decimal) || targetType == typeof(decimal?))
        {
            if (decimal.TryParse(stringValue, out decimal decimalValue))
            {
                return targetType == typeof(decimal) ? decimalValue : (decimal?)decimalValue;
            }
        }
        // Add more numeric types as needed

        return value;
    }
}
```
三角関数を使わず、単純な積和で円を描く

座標の回転

```math:
\begin{eqnarray}
x' & = & x \cos{ \theta } - y \sin{ \theta } \\
y' & = & y \cos{ \theta } + x \sin{ \theta } \\
\end{eqnarray}
```

で $\theta$ が十分小さいとき

```math:
\begin{eqnarray}
\cos{ \theta } & \fallingdotseq & 1 \\
\sin{ \theta } & \fallingdotseq & \theta \\
x' & = & x - y\ \theta \\
y' & = & y + x\ \theta \\
\end{eqnarray}
```

の計算で円描画が可能という記事を約40年くらい前に見た。16 ビット整数を使った演算だと精度が足りず、一周すると元のドットに戻ってこなかった。今なら倍精度浮動小数演算が使えるので試してみる。

```javascript:JavaScript
function drawCircle(ctx, x, y, r) {
    const cnt = Math.trunc(Math.PI * 2 * r);
    const ir = 1 / r;
    let px = r;
    let py = 0;

    ctx.beginPath();
    ctx.moveTo(x + px, y + py);
    for (let n = 0; n < cnt; n++) {
        px -= py * ir;
        py += px * ir;
        ctx.lineTo(x + px, y + py);
    }
    ctx.closePath();
    ctx.stroke();
}
```

赤色で Canvas API の arc() を使って円を描いて、青色の drawCircle() を重ねています。

<p class="codepen" data-height="620" data-default-tab="result" data-slug-hash="KKEvjxq" data-user="ikiuo" style="height: 620px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ikiuo/pen/KKEvjxq">
  円描画テスト</a> by Ikiuo (<a href="https://codepen.io/ikiuo">@ikiuo</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
拡張スロットと拡張カードについて

## 拡張スロットと拡張カードについて
- 拡張スロット

拡張スロットは、コンピュータのマザーボードなどにある、細長い接続端子(接続口、コネクタ)。
機能拡張や性能増強のための拡張カードを差し込み、CPUやメモリなど他の装置と通信するための接続規格。
例えば外部機器との通信インタフェースがない場合にインタフェース用のカードを差し込んだり、
M.2 SSDといった高速なストレージ(NVMe)を差し込んだりする。

拡張スロットのコネクタ形状にはいくつかの規格があり、
コンピュータ内部のデータ転送方式(パラレル、シリアルなど)などによって異なる。
古くはISAバスが標準的だったが、その後PCIバスとなり、さらにその後継の「PCI-e(PCI Express)」 が普及している。
拡張スロットに拡張カードを差し込み通信するには、両者の規格が対応してないとだめよ。

- PCI-e(PCI-Express)

高速にデータ通信を行う目的で決められた「シリアル転送方式の拡張インタフェースの接続規格」
高速なデータ通信を必要とする外部機器をパソコンに接続する際に使われる規格。
簡単に言うとPCI-e に対応した拡張カードを差し込む、拡張スロット側の形状規格だね。

- 拡張カード/インタフェースカード

インタフェースカードは、コンピュータの拡張スロットに差し込む拡張カードの１つ。
外部機器との入出力端子を追加するためのもの。
内臓されていない外部インタフェースを追加することができる。

M.2はSSDの接続端子(接続側)のサイズ規格、
PCI-eは接続規格(接続口)、
NVMeは接続したSSDとの通信プロトコル。
パルワールド(Palworld)をM1 MacBookで起動してみた話

# MacBookでパルワールドをやりたい
周りの友達がスプラトゥーンをやめて最近パルワールドを始めたので、時代に遅れる訳にはいかないなと思ってパルワールドを購入しました。
購入したのは良いものの、自分が唯一持っているWindowsのパソコンはもう買ってから7年目で、唯一使えるパソコンは2021年製のM1 Pro MacBook…
「Macじゃゲームは諦めろw」と煽られたので、無理やりMacBookでパルワールドをインストールし、実行してみた話をしたいと思います。

# AppleのDirectXサポート
実は、Appleさん、この前のWWDC2023でMacOSでのDirectXの実行を可能とするGame Porting Toolkitというものを発表しました。
前はParallels Desktopとかを使って、まずWindowsの仮想マシーンにインストールした上で、Parallels DesktopのDirectX 11互換レイヤーを使ってゲームをやっていたのですが、Game Porting ToolkitがDirectX 11、あとParallels　DesktopがサポートしていなかったDirectX 12もMetalに変換してくれるおかげで、なんとmacOSでも一部のWindows向けのゲームがプレイできるようになったんですね。
また、ARM CPUでx86-64コードを実行できるようにしてくれるRosettaの説明は省きますが、Windows互換レイヤーのWineとRosetta、あとGame Porting Toolkitを使ってパルワールドを実行することになります。
# インストール手順
## Whiskyをインストール
https://getwhisky.app

または
```bash
brew install --cask whisky
```
でWhiskyをインストールします。
そのあと、Whiskyの初期設定を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640781/997e88a8-ef28-c548-b23b-672c9e614313.png)
もし、RosettaとGPTK(Game Porting Toolkit)がインストールされてない場合、メニューからセットアップを押してセットアップも行ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640781/611917a8-a5d9-2e4b-434f-4334d88ed0b6.png)
また、基本設定だとFPSやメモリー使用量が表示されてしまうので、Bottleの設定を変えてHUDをオフにしてあげましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640781/2b95b1bd-92c0-10b6-7025-b2eefddc40c7.png)


## Steamをインストール
https://store.steampowered.com/about/

Windows版Steamをダウンロードしましょう。そのあとは実行したらWhiskyのBottle選択画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640781/cae0e86d-a105-0757-edef-b1b4641c9ec3.png)
実行ボタンを押しても実行されない場合はもう一度ボトルを選択したら正常に実行されます。
Steamのインストール画面が表示されたらSteamのインストールを行ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640781/84d10513-9018-c776-d382-23a02c749198.png)

インストールが終わったら、下のようにSteamをピン留めしたら実行が簡単になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640781/74c3891c-7fff-dfa1-33f0-e9ff659ab33a.png)

## パルワールドのインストール
Steamのパルワールドをインストールしてください。

## パルワールド起動
起動したらパルワールドがまるでWindows環境で実行しているように、快適にプレイできました。
Switchのプロコンとかでプレイしたい場合、Steam Inputをオフにしてください。

# 感想
プレイしてみた結果、思ったよりも快適にプレイできました。全てのオプションを最高にしても平均30fpsは出してくれますが、電源なしだと性能制限がかかってしまうので電源をつけてプレイすることを推奨します。
おそらくシェーダのリコンパイルとかで最初結構リソースが使われるっぽくてカクカクしますが、どんどんシェーダキャッシュが蓄えられるにつれてどんどん快適になってきます。
あと、ノーパソにしては思ったよりも快適にプレイできるというのはかなり驚きでしたね。まだ序盤しかやってないので敵が増えたりマルチプレイの時とかはテストしていませんが、また何かあったらこの記事に追記していきたいと思います。

## 追記
プレイヤーの目ん玉が消えたり、図鑑でパルの目が表示されない問題がありました。(ちょっと怖い)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640781/05d55e21-cc25-22a3-f14c-3d4682c3519a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640781/fe3441f5-e8fb-a34b-59ed-7a7ba5e8673e.png)
centos7にlaravelインストール

今更ですが、Laravelに挑戦！！
今までPHPの開発をベタでやってきましたが、今回はReactと並行して色々試してみようと、まずは環境設定から始めました。
```
PHP7に対応のcomposerをインストール
yum install --enablerepo=remi,remi-php73 composer
mv composer.phar /usr/local/bin/composer
composer create-project laravel/laravel
ではエラーが出るので下記のようにPHP7に対応のLaravelを指定してインストール。
Laravelの7.x系をインストールする
composer create-project laravel/laravel project-name "7.*"
centos7で
cd /var/www/html
に移動
プロジェクトを作成（プロジェクト名のフォルダが作成される）
composer create-project --prefer-dist laravel/laravel sample-laravel2
.......
> @php artisan key:generate --ansi
Application key set successfully.
にて成功
cd sample-laravel2
ls
README.md  bootstrap      config        phpunit.xml  routes      tests
app        composer.json  database      public       server.php  vendor
artisan    composer.lock  package.json  resources    storage     webpack.mix.js
chmod -R 777 storage
chmod -R 777 bootstrap/cache

```
VScodeにて
.envのデータベース設定（事前にMySqlにデータベース用意する。）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/5da2b87e-88c0-65c7-87a6-ef33b6df5601.png" width="50%">
 更に
  app.php上の
'timezone' => 'UTC', を'timezone' => 'Asia/Tokyo',
'locale' => 'en',を'locale' => 'ja',
に変更
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/bf7fab7b-289f-d20a-f342-ccaf68b36476.png" width="50%">

php artisan serve --host IPアドレス --port=portナンバー
Starting Laravel development server: http://ipアドレス:portナンバー

ブラウザにて
http://ipアドレス:portナンバー
![スクリーンショット 2024-02-19 19.50.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/c549fd51-96e4-3358-a596-2b2a9f6ae791.png)
ストレージインタフェースについて

## インタフェースとは、異なるものの境界面を表す言葉。
ICTの世界では機械や人の中間にあり、データをやりとりするものあるいは規約となっている。
以下3つに大別できる。
- ハードウェアインタフェース
- ソフトウェアインタフェース
- ユーザインタフェース

ストレージの場合は「ハードウェアインタフェース」であり、コンピュータ本体とストレージを接続して通信をする際の規約。
コネクタの形状や電気信号の形式を定めている。

## 内蔵/外付けインターフェースとネットワークに特化したインターフェース
ストレージ接続のインタフェースには、内臓インタフェースと外付けインタフェースがある。

#### 1. 内臓インタフェース
内臓インタフェースとは、コンピュータ内部のマザーボード上に直接コネクタが設置されている形式。
その形状によって規格化されている。
HDDやSSDの接続規格にはSCSI、SAS、IDE、ATA、SATAなどがある。

#### 2. 外付けインタフェース
外部インタフェーとはコンピュータの外にコネクタがある形式で、
外部ストレージやマウス、ディスプレイ、電源といったものと接続する。
USBやIEEE 1394といった規格がある。

#### 3. ネットワークに特化したインタフェース
外付けインタフェースの中には、ネットワークに特化しているものもあり、
FC/FCoE/iSCSIといった規格がある。

以下見ておけばとりあえずOKかと思った。
https://www.fujitsu.com/jp/products/computing/storage/lib-f/tech/interface/#sata

##### HBA(Host Bus Adapter)とは
コンピュータ本体に外部との通信機能を追加するための総称。
通常はストレージ(外部記憶装置)を接続するための機能を提供するものをHBAと呼ぶ。

通信制御を行う半導体チップやケーブルの差し込み口(ポート)などで構成され、
コンピュータ本体のマザーボード上に実装されている場合と
拡張カードなどの形で提供され、所定の拡張スロットに装着して使用するものがある。

著名な通信インターフェースの制御機能はコンピュータの
チップセットやCPU（MPU/マイクロプロセッサ）などに統合されていることもあり、その場合は単体のHBAは不要。

広義にはネットワークカード（NIC）やUSBコントローラなど、
ネットワーク機能や周辺機器との通信機能を提供するすべての装置を総称するが、
狭義にはATA/IDEやSATA、SCSI、SAS（Serial Attached SCSI）、Fibre Channelなどの規格に対応した、
ストレージ接続のためのインターフェースカードを指す。
初心者必見!! 知らないと危険なSQLの脆弱性!!【SQLi SQLインジェクション】

# 最初に
今回は初心者が見落としがちな脆弱性について書いてみようと思います。
対策等も書いてありますので、最後まで見ていただければ幸いです。
もし記事に誤字脱字等ありましたらコメント等で教えていただけると幸いです。
# SQLインジェクションって？
簡単に言うと特殊な文字列を入れることによって**情報を抜くことが出来る**という事です。
えー！って思いますよね？詳しく仕組みを見ていきましょう!!
### 具体的にどういう脆弱性？
まず以下の文字列を見てみてください
```
" or "1"="1
```
**何だよこれ**って思いますよね？
この文章こそ今回の脆弱性のカギなんです
SQLite3を使って特定の情報を引き出すときに以下のような文章を使いませんか？
```sql
SELECT * FROM account where password = "ここにプログラムなどから値を代入";
```
実際に自分もNode.jsでsqlite3ライブラリを使って上記のようなものを書いています。

では先ほどの文章を{ここにプログラムなどから値を代入}の部分に入れてみましょう
```sql
SELECT * FROM account where password = "" or "1"="1";


//代入した部分を分かりやすくするとこんな感じ (実際には[]はない)
SELECT * FROM account where password = " [" or "1"="1] ";
```
そうです!!先ほどの文章を入れたことによってpasswordが空白か1=1という式が成り立てば情報を出してくれる式に早変わりしました。
プログラミングをしている皆さんなら分かると思いますが1=1なんて絶対成り立ちますよね？
つまり要約すると**すべてのデータを出してくれる**という事です。
### この脆弱性の危険性
まず第一にアカウントのメールアドレスやパスワードを保存してあるデータベースにSQLインジェクション(この記事で説明してる脆弱性)をかけられると、**すべてのアカウントの情報が漏洩する可能性があります。**
Webサイトを作っている人などは尚更気を付けなくてはいけません
なぜならこのようにデベロッパーツールを使う事でどのような通信をしているのか、たどられて、脆弱性を突かれる可能性が高いからです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2676619/99c000a2-dce6-0a2c-e12f-e9e6b2187188.png)
# 具体的な対策
次はどのような対策を取ればいいかを書いていこうと思います。
### プレースホルダ
まず以下のNode.jsのコードをみてください
```js
let id = '" or "1"="1"'

const db = new sqlite3.Database(":memory:")
db.all("select * from account where id = ?;",[id],(err,rows) => {
    console.log(rows)
})
```
node.jsのsqlite3ライブラリにはプレースホルダというのがあるのでそれを活用します。
プレースホルダでは?の部分に値を代入します。
今回の場合は?の部分に変数idの値が代入されます。
代入されるだけだと意味がないですって？大丈夫です。
この場合はidのなかの値を**文字列として代入**してるんです
前のような場合だとダブルクォーテーションを**特殊文字列として代入**するのでエラーが出るのです。
実行してみるとわかると思います。
このように**ダブルクォーテーションを文字列として代入**できればSQLインジェクションを防ぐことができるんですね

**ダブルクォーテーション = "**

### Node.js以外でも…
自分はNode.js出来ないよ!!って人でも大丈夫です!
自分が調べた限り著名な言語は**調べれば**エスケープ処理のサンプルコードなどが出てくるので、是非調べてみてください

# 最後に
自分が紹介した対策やライブラリ以外にも方法やライブラリは沢山あるので是非調べてみてください
そしてもし友達がSQLインジェクション対策を忘れていたら教えてあげてください!!
自分は他にもNode.jsやTypeScirpt等に関する記事を複数あげているので見ていただければ幸いです。
SANでのストレージに対する読み書きフロー

## SANでのストレージに対する読み書きフローを調べた。

### SANで使用されるプロトコル
SANではFC／FCoE／iSCSIといったプロトコルでストレージとブロックアクセスする。
※いづれのプロトコルもSCSIコマンドをカプセル化するもの。

#### 内臓、外付け、NW経由のストレージアレイの制御
ストレージへの読み書きが必要な際はCPUが制御装置として命令する。(メモリ↔︎ストレージ)
※内蔵ストレージ、外付けストレージの場合はただの箱であるため、
　内蔵または接続されたパソコンやサーバのCPUが制御して読み書きする。
　NW経由で接続するストレージ(ストレージアレイ)はそれ自体が通信読み書きする機能をもち、
　NW経由で流れてくるデータをドライブに書き込んだり、ドライブから読み出したデータをNW経由で送り出したりする。
　まさにサーバとして動作する。

 ##### サーバからの書き込みアクセス例
 ①ファイルシステム上のファイルに書き込み保存するため、サーバがHBAから書き込み命令飛ばす。
　SANストレージのLBA(論理ブロックアドレス)＃10番にSCSIコマンド発行
　（LBA#10に10111001010…を書き込んで〜！）

②ストレージのコントローラがフロントエンドポートでデータを受信し
　キャッシュメモリに書き込む。

③コントローラは書き込み完了（ACK）をサーバに送信する。

④サーバはACKの受信でデータ書き込み完了を認識し、メモリないのデータを削除する。

⑤コントローラはキャッシュメモリに蓄えたデータを、サーバからのI/Oとは非同期で
　バックエンドポートを介してドライブへ書き込む。

※データフローにキャッシュメモリを解することで、
　サーバからの転送速度と物理ドライブの書き込み速度差を吸収する。


##### サーバからの読み込みアクセス例

①サーバが読み取り処理をHBAからネットワークへ送信する。

②コントローラはフロントエンドポートで読み取り処理を受信し、
　要求データを判別する。

③コントローラは要求されたデータをバックエンドポートを介して
　ドライブから読み取り、キャッシュメモリへ書き込む。

④コントローラはキャッシュメモリへ書き込んだデータを
　フロントエンドポートからサーバのHBAへ送信する。

※読み取り処理の過程でキャッシュメモリへデータを配置するのは
　再利用による高速化を実現するため。

・SCSIコマンド
→ストレージとコンピュータが通信/制御を行う際に利用されるコマンド群。
バケットポリシーの設定方法


S3のアクセス管理をする仕組みは大きくわけて３つあります。

・ACL(アクセスコントロールリスト)
・バケットポリシー
・IAMユーザー、IAMロール

このアクセス権限の設定のところの理解がいまいちだったので今回バケットポリシーの設定について記事にまとめてみました。

以下バケットポリシーの例です。バケットポリシーはjsonで記述されます。
```json:json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::your-bucket-name/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "xxx.xxx.xxx.xxx/32"
        }
      }
    }
  ]
}
```

## バケットポリシーの記述方法
具体的にバケットポリシー記述の仕方を解説していきます。

・**Version**:ポリシーのバージョンを示しています。2012-10-17から変わっていないようです。（2024/1/5）

・**Statement**:この部分からアクセス権を定義していきます。

・**Effect**:Allow（許可）、Deny（拒否）のどちらかを記述します。許可リストか拒否リストどちらにするのか選択できます。

**・Principal**:誰に対して許可または拒否するのかを指定します。プリンシパルには以下のものがあります。
Principalには下記のようなものがあります。
AWSアカウント/ルートユーザー
IAMユーザー
IAMロール
AWSサービス
匿名ユーザー（"Principal"に"*"を設定することで、すべてのユーザー（匿名含む）にアクセスを許可）

・**Action**:S3の具体的な操作を記載します。
具体的には以下のようなものがあります。一般的なS3 Actionの例を挙げます。
s3:GetObject
s3:PutObject
s3:DeleteObject
s3:ListBucket

・**Resource**：このポリシーが適用されるバケットとオブジェクトを指定します。
バケットレベルの指定
例: "arn:aws:s3:::バケット名"
オブジェクトレベルの指定
例: "arn:aws:s3:::バケット名/オブジェクト名"
バケット内のオブジェクトを指定します。
例: "arn:aws:s3:::バケット名/*"
のようにワイルドカードを指定して、バケット内のすべてのオブジェクトにポリシーを適用することがよくあります。

・**Condition**
特定の条件が満たされた場合にのみポリシーが適用されるようにするための要素です。より細かいアクセス制御が必要な場合に使用します。
"Condition": { 条件ブロック }
条件ブロックの中にキーとバリューの形式で記述します。IPアドレスに基づく制限をしたり、特定日時に基づく制限など様々な条件をしていできます。


AWSの公式でポリシージェネレーターが用意されています。
ポリシージェネレーターを使う簡単にバケットポリシーの作成ができます。ポリシージェネレーターを使って基礎を作成してから細かい部分をカスタマイズするのがよいでしょう。
[ポリシージェネレーター](https://awspolicygen.s3.amazonaws.com/policygen.html
)
「Oracle database 19c」を手動アンインストールしてみたよ！

## ●現在の状況
「Oracle database 19c」をインストールしたが、ログインができなかった。
どのユーザーを使ってもログインできないため、アンインストールを行うことにした。
「サービス」は、全部止めてのアンインストール。
以下に記載している参考資料のサイトを参考にして手動アンインストールを行う。

## ●実際に行ったアンインストール手順
### （1）サービスを停止する
1. 「コントロールパネル」⇒「Windowツール」⇒「サービス」を開く
1. 「Oracle」から始まる名称のサービスを全て停止する
![Oracleアンインストール（1）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219060/f140c7f8-54c9-de9b-f37b-893ac8c7833a.png)


### （2）フォルダを手動で削除する
1. 以下のOracleフォルダを3箇所削除する

①インストール先のフォルダ
![Oracleアンインストール（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219060/0bcd8055-2410-370f-66f8-ce1ccbdb7839.png)

②C:\Program Files直下のOracleフォルダ
![Oracleアンインストール（3）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219060/26f4c195-19a5-2bff-2e18-d49752de2782.png)


③「スタートボタン」⇒「すべてのプログラムの中にあるOracleフォルダ」

※スタートボタンのフォルダ場所
　⇒「C:\ProgramData\Microsoft\Windows\Start Menu\Programs」

![Oracleアンインストール（4）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219060/cf8e07ee-b205-8b9b-a247-4c1c74b826d9.png)

上記の３つのOracleフォルダを削除する。
その際は、ゴミ箱の中身も削除できているか確認する。
![Oracleアンインストール（5）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219060/0ece4f9a-8959-963f-5335-a4c32de6308a.png)

### （3）レジストリを削除する
1. 「Ctrl」+「R」を押下して、「ファイル名を指定して実行」画面を表示する
1. 「regedit」と入力してレジストリエディタを起動する
![Oracleアンインストール（6）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219060/238a7d6b-ae88-3e9e-1fee-62e14e25693d.png)
1. 以下のレジストリを削除する

* HKEY_CURRENT_USER→Softwareの直下のOracleフォルダ
* HKEY_LOCAL_MACHINE→Softwareの直下のOracleフォルダ
* HKEY_LOCAL_MACHINE→System→CurrentControlSet→ServicesのOracle関連フォルダ

![Oracleアンインストール（7）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219060/e8afb7d9-0286-8091-2095-68ec7a32a3e6.png)


### （4）再起動する
1. 再起動する
※Oracleが「アンインストールされた状態」になり、再インストールが可能となる。

## ☆参考資料
* [Oracleクライアント(client)のアンインストール方法](https://sql-oracle.com/?p=446)
* [Oracleで「INS-35075：指定されたSIDは既に使用されています」というエラーが表示されました。修正方法は？](https://www.web-dev-qa-db-ja.com/ja/oracle11g/oracle%E3%81%A7%E3%80%8Cins35075%EF%BC%9A%E6%8C%87%E5%AE%9A%E3%81%95%E3%82%8C%E3%81%9Fsid%E3%81%AF%E6%97%A2%E3%81%AB%E4%BD%BF%E7%94%A8%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%8D%E3%81%A8%E3%81%84%E3%81%86%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%BE%E3%81%97%E3%81%9F%E3%80%82%E4%BF%AE%E6%AD%A3%E6%96%B9%E6%B3%95%E3%81%AF%EF%BC%9F/824184426/)
データ型の変換(Java、Python)

データ型の変換についてまとめました。
今回は整数型から文字列に変換する場合を比較します。

***Java***

```Java
public class Main1 {
  public static void main(String[] args) {
      // 自分の得意な言語で
      // Let's チャレンジ！！

      //String line = sc.nextLine();
      int A = 437326;
      int B = 9085;
      int ansA = A / B;
      int ansB = A % B;
      //  ラッパークラスを用いて数値を文字列に変換して出力する
      System.out.println(Integer.valueOf(ansA).toString() + " " + Integer.valueOf(ansB).toString());
  }
}
```


***Python***

```python3
A = 437326
B = 9085
ansA = int(A/B)
ansB = A % B
print(str(ansA) + " " + str(ansB))
```

Pythonの方が楽ですね。
SAN(ストレージエリアネットワーク)

サーバにはFC用のHBA、スイッチにはSANスイッチ
ストレージにはFCインタフェースが必要。

SANはストレージ専用ネットワークなので
サーバ↔︎ストレージ間で高速アクセスが可能。

ブロック単位でのアクセスとなる。
ゲームボーイをつくりたい！

![IMG_2667.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683213/9a1f3170-a446-6fdf-ec12-41a77f23a124.jpeg)


このあいだインディーゲーム系イベントに出席したら、出展者がゲームボーイの展示をしていた。なんだろうと手に取るとGBstudioとかいうソフトでゲームをつくりカートリッジに焼き付けて遊べるという。なんでも任天堂が持つゲームボーイに関する版権がきれた？とかで、静かにゲームボーイづくりがブームになっているとか:runner_tone5:

つくりたい。ゲームボーイをつくりたい！

そうときめたら秋葉原にいって、ゲームボーイ買ってこよ。スーパーポテト秋葉原にありました。それが冒頭の緑色のゲームボーイ。買った。

よっしゃ。開発しよか

つづく
teratermマクロとマイコンを使ってUARTでコマンドを送る

# 目的
LTEモデムやGPSモジュールなどをUART接続しコマンドを送るテストをする際の手順をまとめておきます
[USBシリアル変換モジュール](https://akizukidenshi.com/catalog/g/gM-11007/)が手元にあれば直接つないでも良いですが、今回はM5AtomLiteを中継に使います　

## マイコンのスケッチ
ここではESP32内蔵のM5AtomLiteを使ってPCとUSBケーブルで繋いだSerialと
GroveケーブルでUART接続機器（例えばLTEモデムやGPSモジュールなど）と繋いたSerial1間の通信を中継します

[PC] -(USBケーブル)- [[M5Atom](https://www.switch-science.com/products/6262)] - (groveケーブル) - [LTEモデム [M5 CAT-UNIT](https://docs.m5stack.com/en/unit/cat_m)]
```cpp:SerialPassthrough.ino
void setup() {
  Serial.begin(115200);  
  Serial1.begin(115200, SERIAL_8N1, 32,26); //M5atomlite
  delay(1000);
}
void loop() {
  while (Serial1.available()) {
    Serial.write(Serial1.read());
  }
  while (Serial.available()) {
    Serial1.write(Serial.read());
  }
}
```

## teraterm設定
設定　‐　シリアルポート　
‐　ポート：接続してるCOM番号
‐　スピード:115200

## マクロファイル
毎回直接コマンドを入力するのは面倒なのでteratermのマクロを使います
https://teratermproject.github.io/
https://teratermproject.github.io/manual/5/ja/macro/index.html
まずメモ帳等で **ATtest.ttl** ファイルを作成する  

```txt:ATtest.ttl
timeout=5
sendln 'AT'
wait 'OK'
; コメントはセミコロンで
sendln 'AT+CPIN?'
wait 'OK'
sendln 'AT+CNACT=0,0'
wait 'OK'
sendln 'AT+CGDCONT=1,"IP","povo.jp"'
wait 'OK'
sendln 'AT+CNCFG=1,1,"povo.jp"'
wait 'OK'
sendln 'AT+CFUN=1'
wait 'OK'
sendln 'AT+CNMP=38'
wait 'OK'
sendln 'AT+CGATT?'
wait 'OK'
sendln 'AT+COPS?'
wait 'OK'
sendln 'AT+CSQ'
wait 'OK'
sendln 'AT+CPSI?'
wait 'OK'
sendln 'AT+CNACT=0,1'
wait 'OK'
sendln 'AT+CNACT?'
wait 'OK'
```

https://qiita.com/Red_Tomato/items/41dbbb088675aca06676

## マクロ実行
teraterm　
‐　ファイル　‐　新しい接続　‐　シリアル　‐　ポート：マイコンに繋いだCOMを選択　‐　OK
‐　コントロール　‐　マクロ　‐　作成したATtest.ttlファイルを選択　‐　OK

```text:log
AT

OK
AT+CPIN?

+CPIN: READY

OK
AT+CNACT=0,0

OK

+APP PDP: 0,DEACTIVE
AT+CGDCONT=1,"IP","povo.jp"

OK
AT+CNCFG=1,1,"povo.jp"

OK
AT+CFUN=1

OK
AT+CNMP=38

OK
AT+CGATT?

+CGATT: 1

OK
AT+COPS?

+COPS: 1,0,"KDDI",7

OK
AT+CSQ

+CSQ: 23,99

OK
AT+CPSI?

+CPSI: LTE CAT-M1,Online,（略）

OK
AT+CNACT=0,1

OK

+APP PDP: 0,ACTIVE
AT+CNACT?

+CNACT: 0,1,"**.***.***.****"　（IPアドレス）
+CNACT: 1,0,"0.0.0.0"
+CNACT: 2,0,"0.0.0.0"
+CNACT: 3,0,"0.0.0.0"

OK

```

証明書等の転送にはsendfileコマンドを使うとよさそう
（SSL接続のテストは未検証）
```
sendln 'AT+CFSINIT'
wait 'OK'
sendln 'AT+CFSWFILE=3,"RootCA.crt",0,1970,10000'
wait 'DOWNLOAD'
sendfile 'C:\RootCA.crt' 1
wait 'OK'
sendln 'AT+CFSRFILE=3,"RootCA.crt",0,1970,0'
wait 'OK'
sendln 'AT+CFSTERM'
wait 'OK'
sendln 'AT+CSSLCFG="convert",2,"RootCA.crt"'
wait 'OK'
```
## バイナリーデータの送受信
こちらの記事を参照

https://qiita.com/ishturk/items/a1130ab4a5c8c9ffb523
goroutineを使用する際に注意すべきこと

for文で並行処理をしたい状況はたくさんあると思います。

```go
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
	wg.Add(1)
	go func() {
		defer wg.Done()
		fmt.Println(i)
	}()
}
wg.Wait()
```

上記のコードを実行すると、どのような結果が得られると思いますか？

```shell
5
10
10
10
7
10
10
10
10
10
```

実行するごとに、異なる結果が出ると思います。
これは、goroutineの中で変数`i`を表示するときにはすでに、`for`ループが終了してしまっているからです。
これを回避するには、ループのスコープの中で新しい変数を宣言します。
この変更により、各ゴルーチンはそれぞれの`v`の値をキャプチャします。

```go
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
	v := i // 追加
	wg.Add(1)
	go func() {
		defer wg.Done()
		fmt.Println(v)
	}()
}
wg.Wait()
```

これを実行すると、期待通りの結果が得られることがわかります。

```shell
0
2
3
1
7
9
8
4
6
5
```

また、以下のように無名関数の引数として渡すことでも、解決することができます。

```go
nums := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
var wg sync.WaitGroup
for _, v := range nums {
	wg.Add(1)
	go func(num int) {
		defer wg.Done()
		fmt.Println(num)
	}(v)
}
wg.Wait()
```
thymeleaf : TemplateInputException でハマった件_変数定義編

## 背景
JUNITでControlelerのテストをしている際、以下の事象に遭遇した。

## エラーログ
Caused by: org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/******.html]" - line 263, col 30)
Caused by: org.attoparser.ParseException: (Line = 263, Column = 30) Malformed markup: Attribute "th:with" appears more than once in element

 要は、Thymeleafの書き方がいけなかったっぽい。。

 ## エラーが発生した箇所
 divタグ内で使用する変数を「th:with」で定義したのだが、１つにまとめないといけないらしい。（まあ確かにそうか笑）
 ```html:エラーが出た箇所
 <div class="inner"
    th:with="isWorking = ${applyDetailViewDto.entryResume.isWorking}"
    th:with="jobChangeCount = ${applyDetailViewDto.entryResume.jobChangeCount}">
```

## 修正後
```html:修正後のソース
<div class="inner" 
    th:with="isWorking = ${applyDetailViewDto.entryResume.isWorking}, 
        jobChangeCount = ${applyDetailViewDto.entryResume.jobChangeCount}">
```

これでOK！
《Windows》社内共有サーバのファイルへのリンクが他の社員から開けないと言われる問題

仕事をしていて、社内共有サーバに書類を置き、それを他のメンバーに通知する際に、そのファイルへの「リンクをコピー」して案内文に入れたりすると、そのファイルの場所までのフルパスが表示されます。
その場合、共有サーバに「ホスト名」や「PC名」が設定されていると、下記のような感じでその名称が入ります。

` \\共有サーバ名\フォルダ名\ファイル名 `

この「共有サーバ名」が固有の名前になっていることで、他の社員が他のPCからリンクをクリックした時に、同じネットワーク内で共有サーバに接続しているにもかかわらず、当該リンクが開けないという現象が起こることがあります。
私の勤務する会社でもこの問題が起こり、解決を依頼されたので、どのように解決したかを書いておきます。

インターネットで調べると、たいていは「《共有サーバ名》を《IPアドレス》に変えてから通知しましょう」というような解決方法が見つかります。確かにこれで解決しますが、業務でそういう機会が多い場合に毎回それをやるのは面倒です。

できれば、共有サーバ内のファイルのリンクをコピーしたら最初からIPアドレスが付いたリンクが取得できる方が良いですよね。
なので、共有サーバのIPアドレス付きのリンクが作れるように、下記の方法を試してください。

まずは共有サーバのIPアドレスを調べます。
エクスプローラーから「ネットワーク」をクリックし、該当の共有サーバのアイコンを右クリックして「プロパティ」を選択すると下の方に「IPアドレス」が書いてあるので、コピーします。

Windowsのスタートボタンの横の検索窓に、頭に「\\」を付けてさきほどのコピーしたIPアドレスを入力します。
検索結果として「コマンドの実行」というメニューが出るのでクリックします。
エクスプローラーにIPアドレスが表示された共有サーバのアイコンが出てきます。
（エクスプローラーのパス表示窓に直接入力でもできるかもしれませんが、検証してません。）

このとき、エクスプローラーのサイドバーの「ネットワーク」アイコンの下に、このIPアドレスのアイコンが表示されます。
このアイコンをそのままドラッグ・アンド・ドロップでデスクトップに持っていくと、「デスクトップにリンクを作成」と表示されてショートカットアイコンが作られます。

このアイコンから共有サーバにアクセスすると、サーバ内ファイルのリンクがIPアドレス付きになります。

` \\共有サーバのIPアドレス\フォルダ名\ファイル名 `

※この状況を自宅で再現できなかったので、説明用の画像がぜんぜん無くてすみません。困ってる人の役に立てれば幸いです。
v-data-table の選択色 ( Vue3 + Vuetify3 )

## Vuetify3 の破壊的変更はかなり破壊的

2023年いっぱいでVue2のサポートが終了し、いやいやながらVue3移行をしました。Vue3対応のVuetify3には破壊的変更が多いですね。

`v-data-table` は長らく正式リリースできずにいたため、ぎりぎり(間に合ってはいない)で対応する羽目になりました。

## 

で、この`v-data-table`ですが、Vuetify2では選択行(`tr`タグ)に特別なclassを指定していたので、色の変更(薄い灰色)がされていたが、Vuetify3ではそのような選択行のclassがないため、色がつかない。
困った。

### Vuetify3 `v-data-table` の仕様 (セクション：選択)
https://vuetifyjs.com/en/components/data-tables/basics/#selection

### Vuetify2 `v-data-table` の仕様 (セクション：選択)
https://v2.vuetifyjs.com/ja/components/data-tables/#section-884c306e9078629e

## 対策: CSSで `:has()` を指定

```sample_v3.css
tr:has(i.mdi-checkbox-marked)  {
  background-color: #f5f5f5;
}
```

対策はCSSの `:has()` で選択時にチェックボックスが表示されているかを見ることにした。

https://developer.mozilla.org/ja/docs/Web/CSS/:has

もし、表の中で`v-checkbox-btn`を別途使う場合はこれだけでは不十分になる。その場合は、自分で選択時に見えない`div.selected_line`みたいなclassを用意しておいて、上記と同様に`:has()`で見るのがよさそう。
リザーブドサービス一覧の備忘録

### リザーブド系

ーリザーブド　
　　　　　　インスタンス
      　　　　　　キャッシュノード
            　　　　　　キャパシティ
                  　　　　　　ノード

#### 対象サービス

インスタンス   　　　　　→EC2,RDS,OpenSearch Service(旧:ElasticSearch Service 2021年9月8日に変更)
キャッシュノード 　　　→ElastiCache
キャッシュキャパシティ →DynamoDB,CloudFront
キャッシュノード     　　　→Redshift

以上となります。
ここは違う等々ございましたら教えていただけますと幸いです。

---
ありがとうございます参考文献

[円安対策にも有効！「Savings Plans」AWSの「リザーブドインスタンス（RI）」とは？比較や概要、Amazon EC2での料金事例も紹介](https://cloudnavi.nhn-techorus.com/archives/1738#:~:text=%E3%83%AA%E3%82%B6%E3%83%BC%E3%83%96%E3%83%89%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%81%A8Savings%20Plans%E3%81%AE%E5%A4%A7%E3%81%8D%E3%81%AA%E9%81%95%E3%81%84%E3%81%AF,%E3%81%AE%E9%81%95%E3%81%84%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82 "円安対策にも有効！「Savings Plans」AWSの「リザーブドインスタンス（RI）」とは？比較や概要、Amazon EC2での料金事例も紹介")

[リザーブドインスタンスによるAWSコストの削減](https://www.stylez.co.jp/columns/reduce_aws_costs_with_reserved_instances/#RI "リザーブドインスタンスによるAWSコストの削減")


[Amazon OpenSearch Service 名称変更 - 変更の概要](https://docs.aws.amazon.com/ja_jp/opensearch-service/latest/developerguide/rename.html "")
終端文字を書かなかったことによる測定器のタイムアウト

測定器で得られる値をワンクリックでエクセルに格納していくプログラムを書こうとした際に、タイムアウトエラーを経験したので記載する。


```.Python
spectrum_analyzer = rm.open_resource(visa_address)

spectrum_analyzer.write_termination = '\n'
spectrum_analyzer.read_termination = '\n'
```

これを書かないと、測定器が送られてきた制御プログラムがどこまでかわからず、タイムアウトしてします。
これを書くことにより、プログラムの最後がわかり、タイムアウトせずに実行することができた。