OmniAICreator/Qiita-1.07M huggingface dataset:
二次元データの並び替え　python

# やりたいこと

frame_grabber.exeを用いてRPLiDARから取得したデータ（x,y,z）をyに注目して並び替えたい
```
#RPLIDAR SCAN DATA
#COUNT=457
#Angule	Distance	Quality
358.3411 742.0 188
0.9668 735.0 188
1.7468 736.0 188
2.4060 734.0 188
3.0597 733.0 188
3.7134 732.0 188
4.2462 733.0 188
4.9054 731.0 188
5.5591 730.0 188
6.3391 727.0 188
6.8719 728.0 188
7.6520 726.0 188
8.3112 725.0 188
8.9648 725.0 188
9.6240 728.0 188
```

こんな感じにRPLiDARからデータを取得できる！
これをzを消してyを並び替える

# 想定環境
・Jupyter-notebook

# 実際にやってみる

```python
f = open("./a.pts",'r')
data = f.read()
datas_list = data.split('\n')
datas_float = []
for data_list in datas_list:
    datas_float.append(data_list.split(' '))
```

まず初めにptsファイルを読み込む　※これは，txtファイルと同様に読み込めるみたい
次に改行ごとに分けて，スペースごとに区切って，一個ずつのデータとして見る


<div style="text-align: center;">
datas_floatの中身：list <br> 
datas_float[ i ]：list <br>
datas_float[ i ][ j ]：str
</div>

|x座標|y座標|z座標|
|:--:|:--:|:--:|
|'352.1228'|'2101.0'|'188'|
|'352.7765'|'2165.0'|'188'|
|'353.5620'|'1787.0'|'188'|
|・|・|・|
|・|・|・|
|・|・|・|

z座標はいらなくて，x座標,y座標だけをfloat型で取り出せるようにしたい <br>
データの数は1397
そしてこの時はまだstr型
これをfloat型に変換する
</div>

```python
x_list = []
y_list = []
```

x座標，y座標それぞれのリストを作成する

```python
for i in range (len(datas_float)-1):
    for ii in range(2):
        if(ii % 2 == 1):
            x_list.append(datas_float[i][0]) # [i][0]はx座標
        else:
            y_list.append(datas_float[i][1]) # [i][1]はy座標
                                             # [1][2]はz座標
```

<div style="text-align: center;">
この時点ではstr
</div>

|x_list|y_list|
|:--:|:--:|
|'352.1228'|'2101.0'|
|'352.7765'|'2165.0'|
|・|・|
|・|・|
|・|・|
|'351.0132'|'1583.0'|

```python
list_float = []
for i in range(len(x_list)):
    num = []
    num.append(float(x_list[i]))
    num.append(float(y_list[i]))
    list_float.append(num)
```
x座標とy座標を結合させる

```python
list_float_sorted = sorted(list_float, key=lambda x: x[1])
list_float_sorted[:5]
```
要素1に着目てして並び替える

<div style="text-align: center;">
list_float
</div>

|要素0|要素1|
|:--:|:--:|
|201.9979|156.0|
|211.6515|159.0|
|・|・|
|・|・|
|・|・|
|9.1241|2749.0|


これで昇順の並び替え完了しました！！

# おまけ
```python
list_float_sorted = sorted(list_float, key=lambda x: x[1],reverse=True)
list_float_sorted[:5]
```
keyの後に"reverse=True"を指定すると，昇順から降順になる！！
CryEngine2 (Crysis Sandbox2)を起動する方法


# はじめに
この記事は2007年に発売されたゲームCrysisに収録されているSandboxをWindows10で動かすためにいろいろした備忘録です
中身で実際に動作しているゲームエンジンは**CryEngine2**です
[Crysisの購入場所](https://store.steampowered.com/app/17300/Crysis/)はSteamです
ダウンロード後のファイル場所　`C:\Program Files (x86)\Steam\steamapps\common\Crysis\Bin32\Editor.exe`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459889/7c5ed81e-2c0d-2e30-a066-02e8fb97725e.png)

ちゃっかり入ってるんだよね


## 問題
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459889/af1e0233-1b52-17ec-0925-dfa8be6a1534.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459889/e4bdfa5f-1dc7-be76-494f-0fc87b64e99d.png)


ロードも起動もできるけど、そのあとに真っ白な画面になってしまいすぐにクラッシュしてしまう


ということでこれをちゃんと動作させるようにする

## 解決策
結論、古いゲームなので32bit版しかなく64bitでは動かないのが原因
そのため明示的に32bitで起動させるようにすればいいだけ

以下のコマンドをコマンドをCMDで実行する

```
C:\Windows\System32\cmd.exe /C start "" /affinity FE "C:\Program Files (x86)\Steam\steamapps\common\Crysis\Bin32\Editor.exe" %command%
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459889/b682a5c1-547c-a83a-1ad3-bae0e54a2a21.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459889/31def157-d255-a426-a87a-68d4e8a6ed86.png)


ちゃんと実行されている


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459889/284482cb-6d90-e599-6ba8-641ff6cf6bcf.png)


これが２００７年のゲームなのが未だに信じられない


# おわりに
この記事の需要なくね？
Apple M1 に嫌がらせをする（80bit 浮動小数点数）

# これは何？

x86 は、32bit, 64bit の他に 80bit の浮動小数点数を計算する装置を内蔵していて、いずれもめちゃくちゃ速く計算できる。

一方。
Apple M1 は 80bitの浮動小数点数を計算する装置は持っていないので、80bit の浮動小数点数を計算するにはそうとう面倒なことをする必要がある。

じゃあさせてみよう、というのがこの記事の趣旨。

# 前提

C/C++ には普通三種類の浮動小数点数型がある。gcc なんかでは下表のとおりになっている。

|型|x86 / amd64 でのサイズ|Apple M1(arm64) でのサイズ|
|:--|:--|:--|
|float|32|32|
|double|64|64|
|long double|80 [^1] |64|

なので、M1 上でネイティブコードを動かしても 80bit では計算できない。
そこで、amd64 用の 80bit の浮動小数点数をつかうバイナリを作り、Rosetta2 を使って Apple M1 上で動かす。

# 実験

## 環境

マシンは手元にある下記の2台を使った。
* MacBook Pro 14 inch (M1 非Max)
* MacBook Pro (Core i7, Mid 2015)

## ソースコード

そしてソースコード。

```c:c
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>

typedef NUM_T num_t;

long double test(int n)
{
    num_t sum = 0;
    num_t const one = 1.0;
    for (int i = 1; i < n; ++i)
    {
        sum += (one / (i+1))*(one / i);
    }
    return sum;
}

int main(int argc, char const *argv[])
{
    struct timespec start={0}, end={0};
    clock_gettime(CLOCK_REALTIME, &start);
    long double r = test(20000000);
    clock_gettime(CLOCK_REALTIME, &end);
    time_t ds = end.tv_sec - start.tv_sec;
    time_t dn = end.tv_nsec - start.tv_nsec;
    printf("sizeof(num_t) = %zu\n", sizeof(num_t));
    printf("r=%.20Lf t=%f\n", r, ds + dn * 1e-9);
    return 0;
}
```

除算・乗算・加算 を使った無駄な計算。

`NUM_T` は、コンパイラオプションで定義するんだけど、 `float`, `double`, `long double` のいずれか。

## コンパイルオプション

コンパイルオプションは以下の通り。

全種類共通として `-O2`, `-std=c17`, `-fexcess-precision=standard`  を指定。
あとは下表。

|設定名|オプション|
|:--|:--|
|native|なし|
|sse|`-mfpmath=sse -msse2`|
|387|`-mfpmath=387`|

## 実行結果

まずグラフ。縦軸は実行時間なので、上ほど遅い。縦軸対数目盛注意。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6854/e901aeb3-3643-4579-74b9-cdfa0e691167.png)

時間はグラフのとおりなんだけど、計算結果についてもひとつ。

double の場合、`-mfpmath=387` と `-mfpmath=sse -msse2` では計算結果が異なる。計算途中で 80bit を使うかどうかが違うので、差が出てしまう。下表のとおり。

|設定名|浮動小数点関連オプション|計算結果|
|:--|:--|:--|
|native|なし|r=0.99999995000372399190 |
|sse|`-mfpmath=sse -msse2`|r=0.99999995000372399190|
|387|`-mfpmath=387`|r=0.99999995000375718757|

このあたりの話は [浮動小数点数の呪われた世界（x87 と C/C++)](https://qiita.com/Nabetani/items/1d2fcea654da1b1ab9a8) に書いた。

float でも差が出そうなものなんだけど、今回は差が出なかった。

# 感想とか

80bit 浮動小数点数の計算を Apple M1 でやるととても遅いことが確認できた。64bit と 80bit では、100倍以上遅い。

ソースコード上は long double を使っていなくても、 `-mfpmath=387` をつけてしまうと途中の計算で 80bit 浮動小数点数を使ってしまうため、とても遅くなる。

float と double で、Apple M1 native (arm64 native) よりも rosetta (arm64 sse) の方が速いのは、Apple M1 向けだとコンパイラの最適化器が頑張りきれてないということだと思う。あるいは実行時最適化が走ったりするとか？

あと。
こういうときって何グラフを使うのがいいんだろう。
縦軸が対数目盛なので棒グラフは避けたい。
横軸がハードウェアとかコンパイラオプションなので折れ線グラフもありえない。

仕方ないので散布図にしたんだけど、なんか寂しい絵だなと思って。
ふつうどうするんだろ。

----


[^1]: sizeof(long double) は 16 なので 128bit あるが、意味のあるデータは 80bit。
SQL　取得したデータの並び替え・「必要な数だけ」データを取得

##取得したデータの並び替え

####ORDER BY

「ORDER BY」の並べ方は、「昇順」か「降順」を指定します。「昇順」は「小さい数から大きい数へ向かう順序」、「降順」は「大きい数から小さい数へ向かう順序」です。

#####「小さい→大きい」は「ASC」
```
SELECT カラム
FROM テーブル名
ORDER BY カラム ASC;
```

#####「大きい→小さい」は「DESC」
```
SELECT カラム
FROM テーブル名
ORDER BY カラム DESC;
```

##「必要な数だけ」データを取得
「最大で何件取得するか」を指定するためには、「制限する」という意味の「LIMIT」を用います。

```
SELECT カラム
FROM テーブル名
LIMIT データ件数;
```
SQL　特定のデータを取得しよう

##特定のデータを取得
特定のデータを取得するためには、「どこの」という意味を持つ「WHERE」を用います。「SELECT」と「FROM」で「どのテーブルのどのカラムのデータを取得するか」までは決まっていますので、「WHERE」が意味するのは、「どこのレコード（横の行）を取得するか」になります。
「どこのレコード（横の行）のデータを取得するか」を指定するためには、左の図のように「＝」を用いて、「〇〇カラムが〇〇であるレコード」といった意味になるように条件を指定します。

```
SELECT カラム 
FROM テーブル名
WHERE カラム = 数字;
```
文字のデータ型を入力する時は""で挟む
データ型については以下で説明

```
SELECT カラム 
FROM テーブル名
WHERE カラム = "文字";
```
##データ型について
データベースに保存されているデータには、「データ型」と呼ばれるルールがあります。「データ型」とは、テキストデータや数値データ、さらには日付データといったように「データの種類」を示すものです。
データ型の種類については以下の記事を詳細
https://qiita.com/shuhoyo/items/07d28cec6babe788051d

##比較演算子
WHEREの条件では「＝」の他にも比較演算子を活用できる。
例として1000以上であるレコードなどを取得する場合以下になります。

```
SELECT カラム 
FROM テーブル名
WHERE カラム <= 1000;
```

##「ある文字を含むデータ」を取得したい場合
「ある文字を含むデータ」を取得したい場合は、「〜のような」という意味を持つ、「LIKE演算子」を用います。図のようにすることで「指定したカラムが〇〇を含む（〇〇のような）レコード」という条件となります。

####ワイルドカード
LIKE演算子を用いる際に覚えておく必要があるのが「ワイルドカード」です。コンピュータの世界で「ワイルドカード」とは、どんな文字列にも一致することを指す記号です。LIKE演算子では「％」をワイルドカードとして扱います。これにより図では「文字」を含むデータを全て取得しています。

```
SELECT カラム
FROM テーブル名
WHERE カラム LIKE '%文字%';
```
####前方一致
ワイルドカードを文字列の前後どちらかにのみ置くことも可能です。図のように「〇〇%」とした場合、「〇〇」以降はどんな文字列にも一致しますので、「〇〇」で始まる文字列を検索することができます。このような検索を「前方一致」と呼びます。

```
SELECT カラム
FROM テーブル名
WHERE カラム LIKE '%文字';
```
####後方一致
また、図のように「%〇〇」とした場合、「〇〇」より前はどんな文字列にも一致しますので「〇〇」で終わる文字列を検索することができます。このような検索を「後方一致」と呼びます。

```
SELECT カラム
FROM テーブル名
WHERE カラム LIKE '文字%';
```

##一致しないデータを取得したい場合
「〇〇を含まないデータ」や「〇〇に一致しないデータ」のような条件でデータを取得したい場合は「否定」を意味する「NOT演算子」を用います。これまで学習した演算子の前に「NOT」を置くことで、その条件を満たさないデータを取得することが可能です。

```
SELECT カラム
FROM テーブル名
WHERE NOT カラム LIKE '%文字%';
```

##中身がなにかわからない・何のデータも保存されていない場合
データベースには、中身がなにかわからない・何のデータも保存されていない場合などにNULLとなる。
####NULLのデータを取得する
「指定したカラムがNULLであるデータ」を取得するには、「IS NULL」を用います。

```
SELECT カラム
FROM テーブル名
WHERE カラム IS NULL;
```
####NULLではないデータを取得する場合

```
SELECT カラム
FROM テーブル名
WHERE カラム IS NOT NULL;
```
##複数の条件

####AND演算子
AND演算子を使うと、WHEREに複数の条件を指定することができます。「WHERE 条件１ AND 条件２」のようにすることで、条件１と条件２を共に満たすデータを検索することができます。

```
SELECT カラム1,カラム2
FROM テーブル名
WHERE カラム1 = '文字' AND カラム2 = '文字';
```

####OR演算子
OR演算子は、AND演算子と同様に、複数の条件を扱います。「WHERE 条件１ OR 条件２」のようにすることで、条件１または条件２のどちらかを満たすデータを検索することができます。

```
SELECT カラム1,カラム2
FROM テーブル名
WHERE カラム1 = '文字' OR カラム2 = '文字';
```
【Linux】シャットダウン、再起動などをするコマンド

# はじめに

Linuxでシャットダウンや再起動などをするコマンドを紹介します。
デスクトップ環境ごとに違うコマンドもあるので、お使いのLinuxのディストリビューションに注意してください。

# ディストリビューションとデスクトップ環境

主に初心者向け、Windows風、Mac風のものを軽くまとめておきます。
この他のディストリビューションで追記してほしものがあれば、コメントで教えてください。

## GNOME

- Ubuntu
- Zorin OS
- Pop!_OS
- Voyager

正確にはPop!_OSはGNOMEをベースに作られたCOSMICというデスクトップ環境です。

(2022/8/2追記)
Voyager 22.04はGNOMEなのでこちらに移動しました。

## Budgie

- Ubuntu Budgie

## Pantheon
- Elementary OS

## KDE

- Kubuntu
- Feren OS
- Windowsfx (Linuxfx)

## Cinnamon

- Linux Mint Cinnamon Edition

## MATE

- Ubuntu MATE
- Linux Mint MATE Edition

## Xfce

- Xubuntu
- Linux Mint Xfce Edition

## LXQt
- Lubuntu

## Trinity
- Q4OS Trinity

# シャットダウン

```sh
poweroff
```

Q4OS Trinityなど、`poweroff`コマンドが使えない場合は、

```sh
systemctl poweroff
```

# 再起動

```sh
reboot
```

Q4OS Trinityなど、`reboot`コマンドが使えない場合は、

```sh
systemctl reboot
```

# サスペンド（スリープ）

```sh
systemctl suspend
```

# ハイバネート（休止状態）

```sh
systemctl hibernate
```

# ログアウト（ログオフ）

```sh:GNOME,&nbsp;Budgie,&nbsp;Pantheon
killall gnome-session-binary
```

```sh:KDE
killall startplasma-x11
```

```sh:Cinnamon
killall cinnamon-session
```

```sh:MATE
killall mate-session
```

```sh:Xfce
killall xfce4-session
```

```sh:LXQt
killall lxqt-session
```

```sh:Trinity
killall x-session-manager
```

# ロック

```sh:GNOME,&nbsp;Bugdie,&nbsp;Pantheon,&nbsp;KDE,&nbsp;Cinnamon,&nbsp;LXQt
xdg-screensaver lock
```

```sh:MATE
mate-screensaver-command -l
```

```sh:Xfce
xfce4-screensaver-command -l

#ただし、Linux Mint Xfce Editionは、
xdg-screensaver lock

#上のコマンドが失敗したら下のコマンドが実行されるようにOR演算子でつないでもいいかも
xfce4-screensaver-command -l || xdg-screensaver lock
```

```sh:Trinity
kdesktop_lock
```

# 参考
[shutdownコマンドは昔のなごり(今はsystemd)](https://qiita.com/rdonster/items/33e98dea90ce34730e70)
SQL　データを取得しよう

##SQLとは

データベースからデータを取得するためには、「データを取得してください」といったようにデータベースに送る命令（クエリ）が必要です。
SQLとはクエリを書くための言語です。

データベースから、データを取得するためには「SELECT」を用います。このSELECTを用いて、「どのカラムのデータを取得するか」を選びます。
データベースには複数のテーブルが存在する場合があります。
そのため、「FROM」を用いて、SELECTで選んだカラムが「どのテーブルのカラムか」を指定する必要があります。

最後に「ここまでがクエリです」ということをデータベースに伝えるためのセミコロン（；）を加えて完成です。クエリは一行で書くこともできますが、今回は読みやすいように改行して書きましょう。また、SQLは大文字と小文字を区別しないため、小文字で記述しても問題ありません。

```
SELECT カラム FROM テーブル名;
```

##一度に複数のカラムからデータを取得する方法

```
SELECT カラム1,カラム2,カラム3,カラム4 
FROM テーブル名;
```
*でテーブル内の全てのカラムを選択できる

```
SELECT * 
FROM テーブル名;
```
薬物の呼称でWORDLE作った (薬物WORDLE) 【Next.js】

## はじめに

どうもyoshiiです。
今回は新しく作ったアプリの紹介です。
あんま技術的な話とかはないです。

## 薬物WORDLE

薬物の呼称でWORLDEができます。
ぜひ遊んでみてね。

https://drug-wordle.vercel.app/

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">薬物WORDLE作りました<br>俺が薬物の呼称に詳しくないので90個しか単語なくてめちゃくちゃ難しいです<br>この後0時から毎日解答が更新されます<br>ぜひ遊んでみてね<a href="https://t.co/2lrJxIuZaU">https://t.co/2lrJxIuZaU</a><a href="https://twitter.com/hashtag/%E8%96%AC%E7%89%A9WORDLE?src=hash&amp;ref_src=twsrc%5Etfw">#薬物WORDLE</a> <a href="https://t.co/6VaNTYLXL9">pic.twitter.com/6VaNTYLXL9</a></p>&mdash; yoshii🍻 (@ganja_tuber) <a href="https://twitter.com/ganja_tuber/status/1496136959022235650?ref_src=twsrc%5Etfw">February 22, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 制作期間

3日

## 使った技術

Python: 薬物の呼称を収集
Next.js(TypeScript): フロントエンドとAPIルートでバックエンドもちょっと
Firestore: その日の解答情報を保存

## 実装方法を簡単に説明

### 単語の収集方法

薬物をまとめているサイトから、pythonでhtml解析して収集しました。
TypeScriptでもurllibとbeautifulsoupみたいなのほしいなあ…

### 単語の入力方法

ボタンではなく、キーボードで入力できるようにしています。
これは[POKÉDLEさん](https://pokedle.vercel.app/)を参考にしました。

実装方法は、divを6個(今回は6文字なので)flex-boxで並べて、そこにinputを透過して重ねています。

詳しく説明するのはかなり面倒なので、気になったらTwitterとかで聞いてください。

### モーダルビュー

モーダルビューはreact-modalっていうクソ便利なライブラリがあったのでお借りしました。

https://github.com/reactjs/react-modal


## 作ってみて

最近Next.jsのドキュメントを1から全部読んで、なんか作りたいな〜と思ったのがきっかけでした。
APIルートを使えば、サーバー側との簡単なやりとりくらいはNext.jsだけで完結できて便利でした。

Next.jsは個人開発で真価を発揮すると思いました。自分ルールでガンガン書いてもそれなりに綺麗な感じになって、後から修正するのも簡単そうです。

逆に言えば、チーム開発でも、事前にしっかりルールをチーム内で決めておけば、いい速度で開発が進みそうだなと思いました。

## 最後に

普段からなんのありがたみもないアプリを作ったり、飲酒ツイートしかしてないですが、友達になってくれると嬉しいです。

https://twitter.com/ganja_tuber
wslのコマンドラインから、エクスプローラーを開く

# まとめ

* WindowsのWSL上で、カレントディレクトリを、Windowsのエクスプローラーで開くには、以下のようにします。

```(shell)
cmd.exe /C "start `wslpath -w .`"
```

* Windows上で、ファイルを、関連付けられたアプリで開くには、以下のようにします。
  * たとえば、画像ファイルを画像ビューワーで開くには、以下のようにします。
```(shell)
cmd.exe /C "start `wslpath -w ./abc.jpg`"
```

# 解説

上記の内容を、部分部分に分けて、解説します。前から順に説明すると難しいので、後ろから順に説明します。

## wsl上のpathをwindowsのpathに変換
後ろから３文字目の`.`は、カレントディレクトリを表しています。wsl上でpwdしたときに表示される、現在のディレクトリですね。
このカレントディレクトリを

```(shell)
wslpath -w .
```

を実行して、wsl上のpathをwindows上のpathに変換します。
このwslpathの実行は、バッククォート文字「`」で囲まれているので、wsl上のbashによってcmd.exeを実行するよりも前に実行されて実行結果の文字列に置き換わります。

たとえば、wsl上で`/mnt/c`はwindows上の`C:\`なので、実際にwslpathを実行してみると以下のようになります。

```(shell)
$ pwd
/mnt/c
$ wslpath -w .
C:\
```
## コマンドプロンプト上でエクスプローラーの起動

windowsのコマンドプロンプトでは、startコマンドにpathを指定すると、そのpathがエクスプローラーで開きます。

```
Microsoft Windows [Version 10.0.19044.1526]
(c) Microsoft Corporation. All rights reserved.

C:\>start c:\

C:\>
```

## wslからエクスプローラーを起動
上記で説明した「wsl上のpathをwindowsのpathに変換」と「コマンドプロンプト上でエクスプローラーの起動」を組み合わせます。

* コマンドの実行

```(shell)
cmd.exe /C
```

* Windows コマンドインタープリター（コマンドプロンプト）を開始させます。
   * `-C` は、起動オプションで、次の文字列をコマンドとして実行して終了させることを指定しています。

```(shell)
start `wslpath -w .`
```

* startで、指定されたプログラムまたはコマンドを実行するためにウィンドウを開きます。pathが指定された場合は、そのパスをエクスプローラーで開きます。
    * バッククォートで囲まれた部分がcmd.exeを実行する前にwsl上のbashによって先に実行されて、カレントディレクトリのpathをwindows上のpathに変換した文字列に置き換わっています。
Brocade FastironスイッチのVLAN設定

# はじめに

最近，Brocade製のネットワークスイッチ２種(Fastiron, ICX)を使うことになり，いろいろ調べながら使っていました．

経験のあった Cisco CatalystシリーズとはVLAN設定の考え方が違って戸惑ったのでメモしておきます．

異なると感じたのは以下の点です．
* Spanning Tree設定
* VLANとPortの関連付け方
* Native VLANの扱い

# VLANを作る

ここは， Cisco も　Brocadeも同じです．

```
#configure terminal
(config)# vlan 10
```

# Spanning Tree (STP, RSTP)設定

Ciscoではspanning-tree コマンドでスイッチのすべてのVLANに一括設定できます．

```
(config)# spanning-tree mode rapid-pvst
```

BrocadeではVLANごとに設定する必要があるようです．さらに，Layer 3ファームウェアとLayer 2ファームウェアで初期動作が異なり， Layer ２ファームではデフォルト有効，　Layer 3ファームではデフォルト無効とのことです．

なので， BrocadeではVLANを作ったら　spanning tree設定も入れていく必要があります．

```
(config)# vlan 10
(config-vlan-10)# spanning-tree 802-1w
```

ちなみに，Ciscoでは STP+ RSTP+ などの独自拡張プロトコルが使用されていますが，BrocadeスイッチをCiscoスイッチと接続した場合にはBroacdeスイッチがCiscoスイッチの出すパケットを検知して，Cisco動作に合わせるとのこと．

# Port VLANの設定

Ciscoでは Portに対してVLANを設定します．

```
(config)# interface Gi1/0/1 
(config-if)# switchport mode access
(config-if)# switchport access vlan 10
```

BrocadeではVLANに対して untagged ポートを設定します．

```
(config)# vlan 10 
(config-vlan-10)# untagged ethernet 0/1/10
```

# Trunk portの設定

CiscoではPortに対して trunk　(Tag VLANを流す) ことを指定します

```
(config)# interface Gi1/0/1 
(config-if)# switchport mode trunk
```
※機種によっては　trunkのあとにdot1qとプロトコルの指定が必要

Brocadeでは，　VLANに対してtag付きのパケットを通すかどうかを指定します． つまり，　Ciscoでは Port→VLANの順で設定するのに対してBrocadeではVLAN→Portの順で設定します．

```
(config)# vlan 10 
(config-vlan-10)# tagged ethernet 0/1/10
```

Ciscoの方は， trunkの指定を行うと意図的に対象VLANを制限しない限りすべてのVLANがtag付きで流れます．　Brocadeは逆に設定したVLANのみが対象となります．

各VLAN, 各Portのマトリクス全てに設定が必要となりますが，　VLAN,　Portともに一括指定するための書式が用意されています．

## Native VLAN

Native VLANはタグ無しでパケットが流れるVLANです．

Ciscoでは　Port に対して switchport access vlanで指定したIDのVLANがnativeとして扱われます．

BrocadeではVLAN設定にて同一のポートに untagged 1つ, tagged 複数の設定ができますが，それだけでは untagged指定したVLANは流れません．
untagged 指定したVLANをtag VLANと混在させて流すには，対象ポートを明示的に dual-mode 指定する必要があります．

```
(config)# interface ethernet 0/1/10
(config-if-e1000-0/1/10)# dual-mode 10
```

参考: http://docs.ruckuswireless.com/fastiron/08.0.60/fastiron-08060-l2guide/GUID-77B587E9-90F4-4DE7-92EA-BEBD594D184F.html

Ciscoと同一動作にするなら全ポート dual-modeと設定すればよいのでは？と思いましたが，tagged VLANが指定されていないポートでは設定エラーになりました．
グレースケール画像への色付けとスケールバー挿入

◯共焦点などで撮影したグレースケール画像にImageJで色を載せて、
かつ白色のscale barを載せるところでつまづいたので記事にしました。

◯環境
Mac OS Big Sur 11.6
Fiji(ImageJ) Ver. 2.3.0

◯素材-自分で書きました。
![ポッチャマ(3).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2404682/973552d2-d30a-c3eb-75aa-f31d13b69774.jpeg)

◯ImageJ Image>Look up table>Cyan でシアン画像にしました。ポッチャマかわいい。
![ポッチャマ(3)-cyan_266x285.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2404682/0a64bfdf-897d-07dc-afdf-845b8f14d51f.jpeg)

◯スケールバーを挿入するには、
Analyze>Tools>Scale Bar...から挿入できます。このときOverlayのチェックは外します。
実際の長さの情報は、
Analyze>Set Scale...から入力できます。
![ポッチャマ(cyan_scalebar).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2404682/33b02dc8-6521-d9fb-3403-9eef65eab970.jpeg)

◯このとき画像が8bit形式だとスケールバーもシアンになってしまうので注意が必要でした。

![8bit画像の場合.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2404682/730e83f3-6d56-529a-93b6-fcf145919fde.jpeg)

ImageJ上でImage>Typeから“RGB形式”を選択し、
その後スケールバーを挿入すると白色のバーにできました。

![RGB画像の場合.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2404682/871067c0-b6e9-bd55-6a74-9b5fd1819a4d.jpeg)


◯参考にしたページ
ImageJで画像にスケールバーを入れる。
http://life-science-project.com/1418/
TOEIC 500点未満でもGCIHに合格できた話

# はじめに
技術の進歩により英語の学習をしなくてすむ日が来ることを待ち続けて早十数年。DeepLといった素晴らしい翻訳ツールはでてきたものの、エンジニアにとってはまだ英語学習は避けて通れない道かと思います。
私は本当に英語が苦手で過去に受けたTOEICでは400点台でした。
そんな私がうっかりミスで勘違いして申し込んだGCIH試験（**<font color="Red">問題文・選択肢ともに英語</font>**）に合格できた話です。

# GCIHを受験するきっかけ
会社から研修を受けて良いと話があったため以前から興味のあったSANSの研修を受けようと思い探したところ、SECURITY 504が面白そうでかつ「日本語講座・一部日本語教材」と記載があったため受講することにしました。
SECURITY 504はGCIH認定資格に対応しており、研修と試験を同時に申し込むことができます。
そこで思わず「研修が日本語だから試験も日本語なのかな」と考え、試験も同時に申し込みをしました。

そして研修を受けて初めて気づきました。GCIH試験が問題文・選択肢ともに英語であることを。。

# GCIH試験について

* 本番の試験とは別に、練習用の模擬試験を2回受けることができる
* 問題文・選択肢ともに英語
* 問題は106問
* 試験は4時間
* 70％以上のスコアで合格
* ハンズオンの問題あり
* 自宅などで受験可能なリモート試験と、テストセンターで受験するオンサイト試験から選べる
* 教材、ノート、英和辞書など印刷物は持ち込み可能

詳細は以下のとおりです。
https://www.sans-japan.jp/giac/get_certified
https://www.giac.org/certifications/certified-incident-handler-gcih/

# GCIHを受験するまでに行った学習
2021年12月に研修を終了後、2022年2月にGCIHに合格しました。
3ヶ月弱の期間が空いていますが、実際学習したのは3週間程度です。

研修終了後、以下の流れで学習を行いました。

## 2021年12月
Log4j対応に巻き込まれていっさい復習ができませんでした。
教材を見直すことも、英語を学習することもありませんでした。

## 2022年1月
正月をのんびり過ごしそのままダラダラしていたため、この期間でもいっさい復習をしませんでした。
教材を見直すことも、英語を学習することもありませんでした。

## 2022年2月上旬
GCIHの受験期限が4月上旬に迫っているため、ようやく復習を開始しました。
やったことは以下です。

* 教材を全て読み直す
    * 日本語部分のみ読んで英語は飛ばしました
* 重要そうな部分をノートに記載
    * 全15ページくらいのちょっとしたものです
* 教材から重要そうな英単語を抜き出し和訳。和訳したものをノートに記載
    * 英和辞書がわりです

その後、模擬試験1回目を受けてみました。結果は60％。合格が70％以上なので10％足りませんでした。
ただ英語ができないわりには高得点かなと思います。
自作の和訳が役に立ったのと、問題や選択肢を全て日本語訳しなくても単語のつなぎあわせで言いたいことを理解し、回答できることがわかりました。
ちなみに問題の難易度的にはそこまで難しいものではなかったので、英語だけどうにかできれば合格できるという自信が持てました。

## 2022年2月中旬
やったことは以下です。

* 教材から頻出英単語を抜き出し和訳
    * これも和訳したものをノートに記載しました
* 模擬試験で出てきた問題や単語を思い出し和訳
    * 同じくノートに記載しました

その後、模擬試験2回目を受けたところ、72％でギリギリ合格できました。
結局今日まで英語の和訳をノートに記載しただけで、英語の勉強は一切しなくても合格点に届きました。

## 2022年2月下旬
やったことは以下です。

* 教材の重要そうなところのみ読み直す
    * 日本語部分のみ読んで英語は飛ばしました
* 模擬試験で出てきた問題や単語を思い出し和訳
    * いつも通りノートに記載しました
* 教材にインデックスをつけ、どの教材に何の項目が記載されているか暗記
    * 試験中に見たい内容をすぐに見れるようにインデックスをつけました
    * インデックスを探すのに手間取らないように、どの教材に何のインデックスがあるかを丸暗記しました。また、インデックスの中身に何が記載されているかもできる限り暗記しました

## そして受験へ
テストセンターで受験しました。
リモート試験の方が気楽に受験できて良さそうですが、リモート試験の場合は画面越しに英語で試験官と会話しなくてはいけないと聞いたためテストセンターを選びました。

持ち込んだものは、教材・重要部分を記載したノート・和訳を記載したノート、の3種類です。
平日月曜日の午前開始だったためか空いていて快適でした。
ただ同じ部屋にずっと独り言をいう ~~アホな人~~ 迷惑な人がいたため若干気になりましたが、使い捨ての耳栓が提供されていたため何とか対応できました。

約10万円する試験のため会社のお金といえど落ちるわけにはいかないと頑張った結果、81％で合格できました。

# 試験について
記載可能な範囲で記載しています。

* テストセンターは休憩中に飲食不可能
    * テストセンターの係の方にも確認したのですが飲食不可でした。そのため1回トイレに行っただけであとは机の前でひたすらテストを受けました
    * 他の方の体験記を読むとテストセンターでも飲食できているようですので、場所によるのかもしれません
* 本番試験は模擬試験より難しく感じた
    * 英語のレベル的には本番試験も模擬試験も同じくらいに感じました
    * 問われている内容が本番試験の方が難しく感じました

# 結論
TOEIC 500点未満でも英語の和訳をしたノートを持参すれば問題は解ける！！
ただ10問くらいは意図が理解できない問題があったため、
**英語ができない＝試験に不利**
ということは言えます。
複数のxps、oxpsのファイルをpdf化するバッチと複数のpdfを1つのpdfへ結合するバッチ

ghostscriptのサイト
https://www.ghostscript.com/

ダウンロードしてパスを通す必要があるもの

xps、oxpsをpdf化するためにダウンロードするもの
https://www.ghostscript.com/releases/gxpsdnld.html
から
GNU Affero General Public License
の列に有るWindows版のものをダウンロードし、展開しパスを通す

pdfファイルを結合するためにダウンロードするもの
https://www.ghostscript.com/releases/gsdnld.html
から
GNU Affero General Public License
の列に有るWindows版のものをダウンロードし、インストールしパスを通す

使い方
下記oxps2pdf.batとcombinepdf.batのコードをコピペ、保存する。
xps、oxpsのファイルのあるフォルダーへoxps2pdf.batとcombinepdf.batを置きます。

oxps2pdf.batをダブルクリックで処理開始し、pdf化されます。

combinepdf.batの使い方

1つめの引数を、結合後のpdf名とし、それ以降が結合対象pdf名です。少数であれば空白区切りで並べていきます。

```
combinepdf.bat result.pdf 01_ab.pdf 02_cd.pdf
```

結合対象pdf名にはワイルドカードが使えます。(ファイル名の命名が規則的であれば、ある程度は順番に結合されるようです)

```
combinepdf.bat result.pdf 0*_*.pdf
```

----------------------------------------------------------------------------------------------------
oxps2pdf.bat
----------------------------------------------------------------------------------------------------
```
::This software includes the work that is distributed in the Apache License 2.0.
::https://www.apache.org/licenses/LICENSE-2.0

@echo off

for %%A in (*.xps *.oxps) do (
	gxpswin64  -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=%%~nA.pdf %%A
)
```
----------------------------------------------------------------------------------------------------
combinepdf.bat
----------------------------------------------------------------------------------------------------
```
::This software includes the work that is distributed in the Apache License 2.0.
::https://www.apache.org/licenses/LICENSE-2.0

@echo off

setlocal enableDelayedExpansion

for %%A in (%*) do (
	if not defined files (
		set files=%%A
	) else (
		set files=!files! %%A
	)
)

gswin64c -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=%files%

endlocal
```

元記事
https://egg-sandwich.com/blog/2022/01/18/%e8%a4%87%e6%95%b0%e3%81%aexps%e3%80%81oxps%e3%81%ae%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%82%92pdf%e5%8c%96%e3%81%99%e3%82%8b%e3%83%90%e3%83%83%e3%83%81%e3%81%a8%e8%a4%87%e6%95%b0%e3%81%aepdf/
Python マルチスレッドで完全にデッドロックなしでSQLite3を使うためのメモ

# はじめに

トランザクションやらコミットのこと無知な状態でマルチスレッドでsqliteやろうとしたらデッドロックしたのでメモ

# threading.Event()でトランザクション前にスレッドを待機させる

```python
import threading
import random
import time

# event3の中でevent1→event2の順でイベントが実行される
# event1はランダム秒後に開始する、event3の終了を待つ,終了したらevent3_endをclear
# event2はevent1が開始するまで待機状態
# event3はevent1が開始したらevent1をclearにしevent2を待つ
# event3でevent2が開始したらevent2をclearにしevent3の終了を告げる
# 上記繰り返し

test_event1_begin = threading.Event()
test_event2_begin = threading.Event()
test_event3_end = threading.Event()


def test_sql1():
    global test_event3_end
    while True:
        interval = random.uniform(1, 3)
        print(f'evet1　{interval}sec 後に開始')
        time.sleep(interval)
        # event1を開始
        test_event1_begin.set()
        # event3が終了するまで待機
        test_event3_end.wait()
        test_event3_end.clear()


def test_sql2():
    global test_event1_end, test_event2_end
    while True:
        time.sleep(0.001)
        # event1を待機
        test_event1_begin.wait()
        interval = random.uniform(1, 3)
        print(f'evet2　{interval}sec 後に開始', end='\n')
        time.sleep(interval)
        # event2を開始
        test_event2_begin.set()


def test_sql3():
    global test_event1_end, test_event2_end, test_event3_end
    while True:
        time.sleep(0.001)
        test_event1_begin.wait()
        test_event1_begin.clear()
        test_event2_begin.wait()
        test_event2_begin.clear()
        print('event3終了')
        time.sleep(1)
        test_event3_end.set()


def main():
    thread_list = []
    tasks = [test_sql1, test_sql2, test_sql3]
    for task in tasks:
        th = threading.Thread(target=task, args=())
        th.start()
        thread_list.append(th)
    for th in thread_list:
        th.join()


if __name__ == '__main__':
    main()

```
```
evet1　1.198280231761349sec 後に開始
evet2　1.606435444539516sec 後に開始
event3終了
evet1　2.7041704830942663sec 後に開始
evet2　1.2936549765944632sec 後に開始
event3終了
evet1　1.3772512376025186sec 後に開始
evet2　1.7498730389596326sec 後に開始
event3終了
```


# 結論

上記のように別スレッドからEventフラグを使ってスレッド管理するのもありですが、トランザクション処理は単一のスレッドで行ったほうが管理しやすいかなと思いました。パフォーマンスもこっちのほうがいいのでは？

```python
# 以下、DBに反映させたいデータ
q1 = []
q2 = []
q3 = []

def th1():
    while True:
        # q1キューにデータを入れる処理
        q1.append('any')

def th2():
    while True:
        # q2キューにデータを入れる処理
        q2.append('any')

def th3():
    while True:
        # q3キューにデータを入れる処理
        q3.append('any')

def any_transaction():
    global q1,q2,q3
    while True:
        time.sleep(0.001)
        # キューにデータがあれば順次する
        if q1:
            # q1をdbに入れる処理
            pass
        if q1:
            # q1をdbに入れる処理
            pass
        if q1:
            # q1をdbに入れる処理
            pass
````
40 代おっさん GASのカスタム関数について学ぶ

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## カスタム関数

カスタム関数とは
オリジナルのスプレッドシート関数のこと

カスタム関数を作るルール

・スプレッドシートのコンテナバインドスクリプトである
・グローバル関数である
・プライベート関数でない

お試し

```javascript
/**
 * 税込み価格を返すカスタム関数
 * 
 * @param{Number} price - 価格
 * @param{Number} taxRate - 税率(規定値は0.1)
 * @return{Number} - 税込み価格
 * @customfunction
 */
function ZEIKOMI(price, taxRate = 0.1) {
  return price * (1 + taxRate);
}
```

ドキュメンテーションコメントに@customfunctionを含めるとスプレッドシートの保管の候補として表示される。

## 参考資料

<https://www.amazon.co.jp/s?k=google+apps+script+%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80&adgrpid=110264232688&gclid=CjwKCAiA9aKQBhBREiwAyGP5lSl7AJJLCvOEHb4wQgMlyqW1fll5X8GDTT_Rkd1_soUAyIPMXQr26hoClHEQAvD_BwE&hvadid=553833563682&hvdev=c&hvlocphy=1009076&hvnetw=g&hvqmt=b&hvrand=4378489642044417389&hvtargid=kwd-594191211348&hydadcr=4106_13159878&jp-ad-ap=0&tag=googhydr-22&ref=pd_sl_2x1owglv0s_b_p52>
エンジニアのための測度論入門

# はじめに

ルベーグ積分30講を読んで、本格的なルベーグ積分や確率論の書籍に入門しようとすると、E.Hopfの拡張定理（カラテオドリ・ハーンの拡張定理）、ディンキン族定理（$\pi-\lambda$定理）および単調族定理が立ちはだかるかと思います。

そこで、そのハードルを下げて寝っ転がりながら読めるように咀嚼してみました。

エンジニアなので正確なことは書けず、間違いが多々あるかと思います。
その際は、やさしくご指摘頂ければ幸いです。

# E.Hopfの拡張定理

https://onyx-caraway-315.notion.site/E-Hopf-93848e78871645cf964f43cea89ffd63

# ディンキン族定理

https://onyx-caraway-315.notion.site/34713ce0313346769df2bcb78c5a3ed3

# 単調族定理

https://onyx-caraway-315.notion.site/705ae763064d47d1ba6e2365f722a75a
【Android／iOS】Webブラウザのアドレスバーを非表示にする方法

#はじめに
Android／iOSのWebブラウザのアドレスバーを非表示にする方法です。
ネットで調べて出てくることには出てくるのですが、なかなかたどり着かなかったのでQiitaに投稿しておきます。

#やりたいこと
据え置きのタブレット端末でWebアプリを動作させるときに、アドレスバーを非表示にしたい。
↓
調べたところ、Webブラウザの設定でフルスクリーン（アドレスバー非表示）にするのは無理そう。
（フィッシングサイトによる悪用などを考慮している？）
↓
**Webブラウザの設定変更以外の方法でアドレスバーを非表示にしたい。**←今回やりたいこと

#結論
以下のサイトを参考にしました。
[[HTML5] フルスクリーンの開始と解除](https://blog.katsubemakito.net/html5/fullscreen)

対象ページのheadタグ内に以下のmetaタグを記述します。

```html
<!-- iOS用 -->
<meta name="apple-mobile-web-app-capable" content="yes">

<!-- Android用 -->
<meta name="mobile-web-app-capable" content="yes">
```

対象ページへのショートカットをホーム画面に追加し、ホーム画面から対象ページに移動するとアドレスバーが表示されなくなります。

AndroidのChromeブラウザであれば、対象ページを開いた状態でブラウザのメニューから「ホーム画面に追加」を選択することでショートカットを作成できます。
![Screenshot_20220223-131730.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2528939/1aad4cbd-45a5-442b-01f9-4f19862c8927.png)

作成したショートカットから対象ページに移動するとアドレスバーが非表示になります。
![Screenshot_20220223-131743.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2528939/ed3e9592-fd31-ca3f-6ec1-5fc57d6fb948.png)
（スクショ撮るのにXperia 1を使ってるので画面が長い。。。）

アドレスバーが非表示になりました。
![Screenshot_20220222-210550.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2528939/ddd1da04-4cbb-1840-6055-2d9b352a8c4e.png)

ちなみに、普通に表示したとき（アドレスバーあり）はこんな感じです。
![Screenshot_20220222-210438.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2528939/71b01e70-fb33-a7d0-975b-d9ca9507fdbc.png)

Androidを例にしましたが、iOSでも同様です。

#おわりに
Android／iOSのWebブラウザのアドレスバーを非表示にすることで、Webアプリをネイティブアプリっぽくすることができました。
初めからネイティブアプリで作っていれば、こんなことに煩わされなくて済むんですけどね。
モバイルアプリ開発の知見がまだないので、時間があるときに[Udemy](https://www.udemy.com/)あたりで勉強してみようと思います。
Javaの基本ルール(備忘録)

##クラス名とファイル名##

クラス名とファイル名は同じに(頭文字は大文字にしなくてはならない)

```
例　Main.java Sub.java

例　class Main {クラスブロック}   class Sub{クラスブロック}
```

##コメントの記述方式##

コメントは他言語と同様の記述方式を採用しているようです。

```Java
/* コメント本文（複数行記述可能）　*/

// コメント本文　（行末まで記述可能）
```

##変数と定数##

変数と定数の宣言方法です。
定数名は基本的にすべて大文字で記述します。
定数は使用する計算式などで今後変化しないものを入れることが多いです。

```Java
//宣言のみの場合

型 変数名;             例   int age;
final 型 定数名;       例   final double TAX;

//初期値を入れる場合

型 変数名 = 初期値;    例   int age = 22;
final 型 定数名 = 初期値;    例   final double PIE = 3.14;
```
Qiita記事の投稿で使うテク

##目的
Qiitaの投稿を月イチとかでやるとやり方を忘れてしまうので、
<strong>未来の自分へのメモ</strong>として残しておきます。

##使うテク
~~~:見出し(書き方)
#   見出しmax
##  見出しmax-1
### 見出しmax-2
####見出しmax-3
~~~
\#の数で決まる

~~~:番号付きリスト(書き方)
1. あああ
1. あああ
1. あああ
~~~
『1. →数字+ドット+スペース(全て半角)』で記載することが重要。
これをやることにより勝手に連番が振られるようになるため、挿入/削除の修正に強くなる。

~~~:背景黒色(書き方)
~~~:薄灰色と白抜きの文字列
内容
'~~~ ※記載の都合上、頭に'が入ってるが本来は入らない。
~~~
<p>~~~で挟む。前半の~~~の後に":(文字列)"でタイトルっぽい感じが出せる。<br></p>

~~~:caution(書き方)
:::note info
耳より情報
:::

:::note warn
明日より注意
:::

:::note alert
直ちに警告
:::

~~~
実際見た方が早いので、以下に記載する。改行に余裕がないと反応してくれない。

:::note info
耳より情報
:::

:::note warn
明日より注意
:::

:::note alert
直ちに警告
:::

~~~:#(見出し)を#(シャープ)として出す
\#(シャープ)・・・半音上げて
~~~
<p>\を前に付けて利用する。</p>


~~~:\(エスケープ)を\(バックスラッシュ)として出す
<p>\(リバースソリダス)・・・パス区切り記号として使われる</p>
~~~
<p>htmlの"&lt;p>"タグを利用する</p>

##終わりに
構成をフォーマット化することも出来るけど、それだと新しい発見もないので、Markdown記法のやり方だけを残しておきます。
月末日を取得

ORACLEだとそのものズバリの関数があります。

~~~SQL
SELECT LAST_DAY(SYSDATE) AS END_OF_MONTH FROM DUAL;
~~~

C#だと取り敢えず二通り思い浮かびます。
もっとスマートにコードも少なく記述できる方法がありそうな気もしますが。

~~~C#:DaysInMonthを使う
int this_month_days = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);
DateTime endOfMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, this_month_days);
~~~

~~~C#:翌月の月初日から1日前を求める
DateTime endOfMonth  = new DateTime(DateTime.Now.AddMonths(1).Year, DateTime.Now.AddMonths(1).Month, 1).AddDays(-1);
~~~
Swiftで端末情報を取得するコード

Swiftでスマホやタブレットの端末情報を取得する方法。

## ソースコード

```swift
// UDID
UIDevice.current.identifierForVendor!.uuidString

// UUID
UUID().uuidString

// デバイス名
UIDevice.current.name

// システム名(iOSなど)
UIDevice.current.systemName

// システムバージョン(15.1など)
UIDevice.current.systemVersion

// キャリア名(ソフトバンク、ドコモなど)
CTTelephonyNetworkInfo().subscriberCellularProvider?.carrierName

// Mobile Country Code(MCC)(440など)
CTTelephonyNetworkInfo().subscriberCellularProvider?.mobileCountryCode

// Mobile Network Code(MNC)(10など)
CTTelephonyNetworkInfo().subscriberCellularProvider?.mobileNetworkCode

// ISO 3166 country codes(jpなど)
CTTelephonyNetworkInfo().subscriberCellularProvider?.isoCountryCode

```

## 参考
https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes

https://pentan.info/doc/mnc_list_j.html

https://pentan.info/doc/mcc_list.html

## Swiftのお役立ち情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
【JavaScript関数ドリル】Lodash関数の実装【勉強用】_.last関数


#【JavaScript関数ドリル】初級編のlast関数の実装のアウトプット

       
```javascript:last関数の挙動
_.last([1, 2, 3]);
// => 3
```
配列の末尾を返す
##last関数の課題内容
https://youtu.be/bPJjIawWFBI

##last関数に取り組む前の状態
- array.length-1を変数に格納するだけでよさそう
- 関数ドリルの取り組む順番を間違えている気がする

##last関数に取り組んだ後の状態
- そのまま`array[array.length -1]`を返せば1行で済んだ
- 今後も元の配列を破壊していないか確認することにする


##last関数の実装コード

```javascript:
const last = (array) => {
    const lastNum = array.length - 1;
    return array[lastNum];
};

const nums = [1, 2, 3, 4, 5]
console.log(last(nums));
// => 5

console.log(nums);
// => [1, 2, 3, 4, 5]
```



##last関数の解答コード

```javascript:
function last(array) {
  return array[array.length - 1];
}

console.log( last([1, 2, 3]) );
// => 3
```
【MySQL】NULLの取り扱いについて

MySQLでハマった。
NULLは極力使わないほうが良いのではないかとも思っている。
一連の経験について記しておき、誰かの役に立てれば幸いです。

<h2>概要</h2>
「!=」ではNULLを拾わない。。。
<h2>どういうことか？</h2>
あるカラムに、「Null」「1」「5」「10」が入っていたとしよう。
そこでこのカラムの値が1以外のものを抽出しようとする。
<pre>SELECT * FROM (テーブル名) WHERE (カラム名) != 1;</pre>
これで行けると思われる。
しかし、結果として「5」「10」は抽出できるが、「Null」は抽出できない。

<h2>詳細</h2>
SELECT分を実行し、1レコードずつ見ていくとき、
<pre>WHERE (カラム名) != 1</pre>
の(カラム名)に各値が入っていく。つまり、

WHERE (カラム名) != 1
　↓
WHERE 5 != 1
　↓
true

という動きとなるが、nullだった時

WHERE (カラム名) != 1
　↓
WHERE null != 1
　↓
false

となる。よってSELECT文でnullが入っているレコードを抽出できない。
カウントしたいときとかに正確な数字を出すことができないので注意。

<h2></h2>
まだまだ駆け出しの身なので、上記SQL文がそもそも間違っている、とか
よりよいSQLはこうだ、みたいなご意見あればコメントいただけますと幸いです。

また、結果としてこうなる経験をしたが、なぜこのような動きとなるのかはわからない。
ActiveRecord::Enum

## ActiveRecord::Enumとは？

ActiveRecord::Enumとは列挙型、あるいはenum型と呼ばれるものでActiveRecordが提供するenum型は数字のカラムに対してプログラム上で扱える別名を与えるもの。

## ActiveRecord::Enumを使う

例えば、あるモデルにそのモデルの状態（ステータス）を扱うカラムがあるとする。そのようなカラムがあった時にenumを利用するとカラムの値を数字として管理することができる。

```ruby
class Task < ApplicationRecord
  enum status: { # statusと言うカラムの値をenumを使って表現する 
	private:   0,
    draft:     1,
    published: 2,
	}
end
```

このようにすると、statusカラムの値を数字として扱うことができるようになる。

（文字列としても、シンボルとしても指定することができるようになる）

## enumで定義されたカラムの値を確認する

enumを利用すると、データを参照するときにも利点がある

### ステータスの状態を確認するメソッドが提供される

一つ目の利点は、モデルのインスタンスに対してそのステータスの状態を確認するためのメソッドが提供されること。

```ruby
task = Task.first
task.published? # taskが公開済みかどうかを検証している
=> true
```

### enumを利用したscopeを使えるようになる

二つ目の利点は、enumで定義した値を利用したscopeを利用できるようになること。

```ruby
tasks = Task.draft # statusがdraftとなっているtaskを抽出できるようになる（where(status: 'draft')と同じこと）
```

## enumの値を簡単に書き換える

enumの値を書き換えるときは、

```ruby
task = Task.first
task.published!
```

とする（末尾に’!’をつける）ことでそのインスタンスの値を書き換える（DBの値も更新する）ことができる。

## その他のメソッド

### DBに保存されている実際の値を確認する

’before_type_cast’で実際の値を確認することができる。

```ruby
task = task.first
task.status_before_type_cast
=> 2 # 今回の場合、publishedのであれば2と表示される
```

### enumで定義されている値を確認する

enumで定義したカラム名を複数形で呼び出すと定義されている値全てを確認することができる。

```ruby
Task.statuses
=> {"private"=>0, "draft"=>1, "published"=>2}
```
競合対策方法 【初心者向け】


##競合とは
一言で言うと、複数のスレッドで一つのインスタンスを共有すると競合が起きます。こうなることで、インスタンスのフィールドの値を読みだしてから、変更するまでの間に　、別のスレッドが変更してしまいます。いつ実行されるかはプログラミング側で制御することが出来ません。飲食店に例えると、あるお客さんがカレーを注文したが、料理人がカレーを作っている間にカレーからオムライスに変更されてしまったというイメージです。

![スクリーンショット 2022-02-23 9.54.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526916/63bb2789-4558-f81d-25f7-6754d5afe6c2.png)

##対策
結論から言うと、対策はスレッドから処理している間は別のスレッドで処理が実行されないようにすることです。これを__排他制御__と呼びます。排他制御の方法を紹介していきます。

##方法
__synchronizedキーワード__を使用します。パターンは２つあります。
①メソッド宣言に使う場合
②メソッド内の１部の処理だけを対象に使う場合

####メソッド宣言に使う場合
__synchronized__を修飾するだけです。
しかし、メソッド内の処理が複雑であればあるほど、待ち時間が出来てしまいます。

```
public synchronized void method(){
   doSomething;
}
```
####メソッド内の一部の処理だけを対象に使う場合
syncronizedブロックを使用するだけです。どのインスタンスに対して、排他制御するのかをブロック引数として指定します。一部の制御をすることで、待ち時間を最小限にすることが出来ます。

```
void method(){
  syncronized(instance){
     doSomething()
 }
```
##問題点
複数のスレッド間で排他制御された複数のインスタンスを共有していて、それぞれのインスタンス同士が連携することで、__デットロック__が発生してしましいます。解決方法として、ロックする順番をスレッド間で揃える方法があります。また、syncnizedは別のスレッドを待機させるので、パフォーマンスに影響を及ぼしてしまいます。その対策として、単純な処理には実行されないか、一連の処理が完全に終わるかになるような結果が保証されているjava.util.concurrent.atomicパッケージを利用します。

##java.util.concurrent.atomicパッケージのAtomicIntegerクラスの使用例
atomicパッケージのAtomicIntegerクラスを使用して、排他制御していきます。
atomicパッケージにどのようなクラスがあるのかは、下記のサイトを参考にしてください。

https://docs.oracle.com/javase/jp/8/docs/api/java/util/concurrent/atomic/package-summary.html


```Value.java
public class Value {
	private int num = 0;

	public void add(int num) {
		this.num +=num;
	}

	public int get() {
		return num;
	}
}
```
AtomicIntegerクラスのaddAndGedメソッドを使うことで、値の呼び出しから、変更までの間に他のスレッドは処理できない。


```AtomicValue.java
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicValue extends Value{
	private AtomicInteger num = new AtomicInteger(0);
	public void add(int num) {
		//読み出しから値の変更まで他のスレッドからの処理は受けない
		 this.num.addAndGet(num);
	}
	 public int get() {
		 return this.num.intValue();
	 }
}
```
```Sample.java
public class Sample {
	public static void main(String[] args) {
		Value val = new AtomicValue();
		//スレッドプールを２つ作成
		ExecutorService exec = Executors.newFixedThreadPool(2);
		exec.submit(new Task(val));
		exec.submit(new Task(val));

		try {
			Thread.sleep(200);
		}catch(InterruptedException e) {
			throw new RuntimeException(e);
		}
		System.out.println(val.get());
		exec.shutdown();
	}
}

```
```
200
```
##まとめ
競合を防ぐにはsyncronizedキーワードを使用する
デットロックを防ぐにはロックする順番をスレッド間で揃える
【Nuxt】jsonでimportしたテキストが「\n」で改行されない時

# はじめに

こんな感じで`json`にちょっと長めのテキストが入ることってよくありますよね？

```json
  {
    "id": 1,
    "title": "『私』のバランス",
    "img": "option1.svg",
    "text": "「仕事は自分を犠牲にしてでも・・・！」そんな風に考えているあなたへ。このワークに一緒に取り組んでみませんか？",
    "modalImg": "sample.png",
    "link": "training"
  },
```

```vue
<template>
 <div
          class="option"
          v-for="(option, i) of options"
          :key="i"
        >
          <div class="option-img">
            <img
              :src="require(`@/assets/images/options/${option.img}`)"
            />
          </div>
          <p class="option-text">{{ option.text }}</p>
        </div>
</template>

<script lang="ts">
import Vue from 'vue';
import optionsData from '../../assets/json/optionsData.json';

export default Vue.extend({
  data() {
    return {
      options: optionsData
    };
  }
});
</script>
```


この`text`を任意の場所で改行したいな〜っと思い、調べてみました。

https://www.sria.co.jp/blog/2017/09/4108/

👆を参考に`\\n`もしくは`\n`を入れてみました。

```json
  {
    "id": 1,
    "title": "『私』のバランス",
    "img": "option1.svg",
    "text": "「仕事は自分を犠牲にしてでも・・・！」\nそんな風に考えているあなたへ。\nこのワークに一緒に取り組んでみませんか？",
    "modalImg": "sample.png",
    "link": "training"
  },
```



**しかし！！！改行さない！！！**:anguished:

# 追加でcssが必要でした

https://html-coding.co.jp/annex/dictionary/css/white-space/


```vue
<template>
 <div
          class="option"
          v-for="(option, i) of options"
          :key="i"
        >
          <div class="option-img">
            <img
              :src="require(`@/assets/images/options/${option.img}`)"
            />
          </div>
          <p class="option-text">{{ option.text }}</p>
        </div>
</template>

<script lang="ts">
import Vue from 'vue';
import optionsData from '../../assets/json/optionsData.json';

export default Vue.extend({
  data() {
    return {
      options: optionsData
    };
  }
});
</script>

<style scoped lang="scss">
  .option-text {
    white-space: pre-wrap; // 追加！！！
  }
</style>
```

これで改行されるようになりました！！！

`white-space: pre;`だと改行コード`\n`を入れた箇所以外では改行されなくなるので要注意！

# 追記 `v-text`を使いましょう

```vue
 <div class="option-text" v-text="optionText"></div>
```

>Mustache構文{{}}を使用せず、v-text属性を使用しているのは、以下に理由によるものです。
タグ間のインデントや改行も出力されてしまう。
(ESLintを導入している場合)タグ間をすべて続けて書いた場合、1行が長すぎるため改行して記述するようwarningが吐かれる場合がある。

https://zenn.dev/kokota/articles/c2f49e6c35c486






# 参考

https://stackoverflow.com/questions/54979287/replace-n-to-new-line-on-vuejs
『inputタグのvalue属性をe.target.valueを用いてuseStateに管理する』の意味が分からなかったので調べた


#そもそも下記のコードは何がしたいのか？

- inputに入力した値を取り出してuseStateで管理したい。
- なぜなら入力した値を用いて投稿だったり編集ができるから。

```react:HogeHoge
const HogeHoge = () => {
  const [neko, setNeko] = useState({ title: '' })
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setNeko({
      ...neko,
      [e.target.name]: e.target.value,
    })
  }
  return (
    <div>
      <label htmlFor="title">タイトル</label>
      <input
        type="text"
        name="title"
        id="title"
        onChange={handleChange}
        value={neko.title}
      />
    </div>
  )
}
export default HogeHoge

```
 


# まずuseStateを使ってnekoの初期値を設定しています。
ここではキーがtitleで値が空のオブジェクトを、nekoの初期値として設定しています。

```react:HogeHoge
  const [neko, setNeko] = useState({ title: '' })
```
# そしてsetNekoという更新関数を用いてnekoの値を更新
- ここでnekoの初期値をスプレッド構文で展開しています。つまり  `...neko`によって `title: ''`　が取り出されています。その空の値がsetNekoのオブジェクトに代入されています。要するにオブジェクトがクローンされています。

- **そして[e.target.name]: e.target.valueの値が挿入されていきます**

```react:HogeHoge

  const [neko, setNeko] = useState({ title: '' })
  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setNeko({
      ...neko,
      [e.target.name]: e.target.value,
    })
  }
```

```javascript:オブジェクトクローンの例
const foo = { a: 1, b: 2 };
const bar = { ...foo }; // => { a: 1, b: 2 }
```

##[e.target.name]: e.target.valueとは
- inputタグのnameの値と、inputタグのvalueの値を指します。
- 今回はnameが`title`で、valueが`neko.title`です。こうすることでinputタグが2個3個と増えてもname属性とvalue属性を参照しているので、入力値をstateで管理できます。

- また、value属性は入力した値そのものを指します。つまり今回はnekoというオブジェクトのtitleの値が、inputタグのvalue属性になります。

```react:HogeHoge
      <input
        type="text"
        name="title"
        id="title"
        onChange={handleChange}
        value={neko.title}
      />
```

# nekoの出力をコンソールで見てみます

```react:HogeHoge
  const [neko, setNeko] = useState({ title: '' })
  console.log(neko)
  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setNeko({
      ...neko,
      [e.target.name]: e.target.value,
    })
  }
```
![スクリーンショット 2022-02-23 0.12.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1849233/b6a77a59-1371-9605-f73b-739df98fff48.png)
![スクリーンショット 2022-02-23 0.13.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1849233/86da5dfc-38df-7041-907f-5097e975039c.png)

- 最初は空の文字列ですが文字を入力すると、setNekoにvalue属性の値が渡ってきて、nekoが更新されていきます。
- このnekoをAPI及びDBの通信に適用することで投稿機能や編集機能が作れます。
EC2のWindows Server構築時のルーティン

# はじめに
EC2でWindows Serverを起動した際にいつも行っている設定ややり方を忘れがちなあれこれをまとめました。

# Windows Serverを起動する
AWSコンソールでWindows Serverを起動します。今回利用したAMIは```Windows_Server-2022-English-Full-Base-2022.01.19```です。

# RDP(リモートデスクトップ)で接続する
起動後にAdministratorのパスワードを取得してRDP接続するまで。
1. AWSコンソールで起動したインスタンス概要を開いて[接続]ボタンを押す。
1. [RDPクライアント]タブにある[リモートデスクトップファイルのダウンロード]を押すと接続用RDPのショートカットが取得できます。
1. [パスワードを取得]をクリックしてインスタンスに紐づけられたキーペアを読み込むと、Administratorのパスワードが取得できるので、メモしておきます。 
1. 取得したRDPファイルとパスワードで起動したインスタンスにリモートデスクトップ接続ができます。
:::note info
ここで忘れずにパスワードを変更しておくこと
:::

# 日本語化とタイムゾーン変更
1. [Start]ボタンから[Settings]-[Time & Language]-[Language]を選びます。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940466/f3c42c13-ec54-b421-806c-34b7bf30e88d.png)

1. [Language]画面で[Add a Language]ボタンを押して[Japanese]を選択して[Next]ボタンを押す。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940466/fb17583e-ca08-11a8-a551-8bb0bf2f0e7c.png)

1. 必要なチェックボックスをONにして[Install]ボタンを押します。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940466/4a6fa37b-e55b-dbbb-d543-2fe916727d37.png)
1. 完了すると[Window display language]に[日本語]を設定することができます。
1. 再起動を促されますがそのまま[Administrative language setting]からログイン画面や新しいユーザーのデフォルト言語等を日本語に設定することができます。終わったら再起動を促されるので再起動します。
1. [日付と時刻の設定]からタイムゾーンを[U大阪、札幌、東京]に変更する。

# ホスト名変更
1. スタートメニューから[コントロールパネル]を開く
1. [システムとセキュリティ]を開く
1. [システム]を開く
1. PC名変更を行う

# ディスクの拡張や追加など
AWSコンソールのEBSメニューでボリュームを作成したりサイズ変更後にWindows側でディスクを認識させるという流れです。サーバーを停止することなく変更可能です。

## ディスクの拡張
EBSの管理画面上でボリュームを選択して、[変更]を行うことでディスクのサイズを変更できます。

## ディスクの追加
EBSの管理画面からボリュームを作成して、対象のEC2にアタッチすることができます。

## Windowsサーバでディスクを認識させる
EBSの管理画面で変更したディスクの情報をWindows側に認識させます。こちらはWindowsのOS上で管理者権限で行います。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/ebs-using-volumes.html

> タスクバーで、Windows ロゴのコンテキスト (右クリック) メニューを開き、[Disk Management] (ディスクの管理) を選択します。

# おわりに
できればこの作業を自動化できるとよいのですが、日々精進します。
【Firebase】Firestoreからランダムでデータを取得するにはどうすればいいの？

# 背景
個人アプリを作っている中で`Firestoreからランダムで５個だけデータを取得する`実装をしたかったのですが、調査を進めていくとそのような処理はFirebase側では用意されていないようなので、参考資料を元にReact, Firebaseで実装しました。

実装までに躓いたことを主にコードの解説をしていきます。

# 実装したコード

```javascript:hooks/useRandomDocument.tsx
import { useEffect, useState } from "react";
import { projectFirestore } from "../firebase/config";
import { ProductDoc } from "../@types/stripe";
import { useCookies } from "react-cookie";

export const useRandomDocument = () => {
  const [documents, setDocuments] = useState<Array<ProductDoc>>([]);
  const [cookies] = useCookies(["random"]);
  const randomIndex = Number(cookies.random);

  useEffect(() => {
    let indexs: Array<string> = [];
    let randomDocument: Array<ProductDoc> = [];

    async function handleAsync() {
      while (randomDocument.length < 5) {
        const queryIndex = String(Math.floor(Math.random() * randomIndex + 1)); // DBの中に格納されている商品数以下の数字をランダムで出力する
        if (!indexs.includes(queryIndex)) {
          indexs = [...indexs, queryIndex];
          const productsRef = await projectFirestore.collection("products");
          const snapshot = await productsRef
            .orderBy("metadata.random")
            .startAt(queryIndex)
            .endAt(queryIndex)
            .get(); // startAtとendAtを同一に指定することでユニークな結果を出力できる
          const data = snapshot.docs.map((doc) => {
            return { ...(doc.data() as ProductDoc), id: doc.id };
          });
          randomDocument = [...randomDocument, ...data];
          if (randomDocument.length === 5) {
            setDocuments(randomDocument);
          }
        }
      }
    }
    handleAsync();
  }, [randomIndex]);

  return { documents };
};

```

# 今回の味噌

該当ページに遷移したらuseRandomDocumentを発火させます。

Firestoreからランダムに1個データを取得する処理を5個データがrandomDocumentに溜まるまで繰り返し条件を満たしたらuseStateに入れて処理を終了します。

## ■あらかじめ取得するデータにユニークな値`random`をつける

あらかじめ取得するデータに`random:<数字>`を持たせる必要があります。

この下準備をしておくことで後述する`startAt(queryIndex)`と`endAt(queryIndex)`を同じ値で指定して1個のみ取得することができます。

## ■数値をランダムで生成する

先に述べたようにFirestoreからランダムで値を取得できないのでランダムの処理は下記で再現しています。

```javascript
const queryIndex = String(Math.floor(Math.random() * randomIndex + 1)); 
```

## ■between条件でクエリしてデータを取得する

```javascript
const snapshot = await productsRef
            .orderBy("metadata.random")
            .startAt(queryIndex)
            .endAt(queryIndex)
            .get();
```

「あらかじめ取得するデータにつけたrandom」と「ランダムで生成した数値」が合致するデータを取得します。

本来なら`startAt（2月1日）`と`endAt（2月28日）`にして1ヶ月の値をまとめてとってくるのがユースケースらしいですが、`startAt`と`endAt`の引数を同じ値にすることで１個だけデータを取得できます。

特定のデータを１個取得するなら`collection().doc()`の印象でしたが`startAt`と`endAt`の方法もあるのですね。目から鱗でした。

# さいごに

ということで、Firestoreから値をランダムで取得する方法について述べてきましたが、（今回の場合は）５回Firestoreへアクセスするのでパフォーマンスは落ちますし、その際のLoadingなどのUI・UX対策は必須になります。

もし他に良い方法があればご教示いただけますと幸いです。

# 参考URL

https://note.com/iwasakiyoshiteru/n/n23160627d2a9
MySQLのdumpファイルをインポートすると文字化けする

# 概要
商用環境(Webシステム)をローカルに構築しように発生した問題です。
解決方法をメモとして残します。
##ローカル構築時に行った手順
1. ソースコードをローカルにコピー
1. MySQL立ち上げ(docker)
1. dumpファイルをMySQLにインポート
1. DB接続先を修正
1. 動作確認<br>
<font color="Red">→MySQLのデータが文字化けしてしまっている</font>

##対応
dumpファイルのこの行を消す

~~~dump_yyyymmdd.sql
/*!50503 SET NAMES cp932 */;
~~~

##感想
商用環境がWindowsサーバーだったり、MySQLのversionがどうこうとか、ローカルがdockerだからとか、
色々想像で動いてしまったせいで解決に時間がかかりました。情けない！！
aws-cliまわりまとめ


いつも忘れるのでメモ

## aws-cliのインストール（バージョン2系）
▼公式を参考
macOS コマンドラインを使用してすべてのユーザーを対象にインストールおよび更新する  
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-mac.html#cliv2-mac-install-cmd-all-users

```bash
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /

# aws-cliがインストールされた場所
which aws
> /usr/local/bin/aws

# インストールしたaws-cliを確認
aws --version
> aws-cli/2.4.18 Python/3.8.8 Darwin/20.6.0 exe/x86_64 prompt/off

# 不要なパッケージ削除
rm AWSCLIV2.pkg
```

## aws-cli バージョン1系も使いたい場合
▼公式を参考
バンドルされたインストーラを使用した macOS での AWS CLI バージョン 1 のインストール、更新、アンインストール  
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-macos.html#install-macosos-bundled

```bash
which aws
> /usr/local/bin/aws

# version2を退避
mv /usr/local/bin/aws /usr/local/bin/aws2

# version1をインストール
curl "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "awscli-bundle.zip"
unzip awscli-bundle.zip
sudo ./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws


# 場合によってはこんな感じのエラーが出る
> Unsupported Python version detected: Python 2.7
> To continue using this installer you must use Python 3.6 or later.
> For more information see the following blog post: https://aws.amazon.com/blogs/developer/announcing-end-of-support-for-python-2-7-in-aws-sdk-for-python-and-aws-cli-v1/

# エラーが出た場合は使用するpythonのバージョンを指定する
sudo /usr/bin/python3 awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws

## バージョン1がインストールされたか確認
aws --version
> aws-cli/1.22.60 Python/3.8.9 Darwin/21.3.0 botocore/1.24.5

# 不要なパッケージ削除
rm -rf awscli-bundle.zip
rm -rf awscli-bundle
```

```
# アンインストールする場合はrm
rm -rf /usr/local/bin/aws
```

## awsのconfig設定

```bash
# プロファイル作成
aws configure --profile dev-user
> AWS Access Key ID [None]: XXXXXXXXXXXXXXXX
> AWS Secret Access Key [None]: XXXXXXXXXXXXXXXX
> Default region name [None]: ap-northeast-1
> Default output format [None]: json

# プロファイル確認
cat ~/.aws/config
cat ~/.aws/credentials

# aws-cliを使う際はuserを設定
# v1
export AWS_DEFAULT_PROFILE=dev-user
# v2
export AWS_PROFILE=dev-user
```