OmniAICreator/Qiita-1.07M huggingface dataset:
MySQL ユーザー作成 → 権限付与

##はじめに
DB接続ユーザーの権限周りについて基本的な操作をまとめました。
MySQL8の環境になります。


## ユーザー作成 ~ 権限の付与


#### ユーザーを確認する
```.sql
SELECT user, host FROM mysql.user;
```
![スクリーンショット 2021-12-31 18.22.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/fcdbab9c-6a9c-281b-b4b3-376fbe6843ca.png)
このコマンドで`use名r`と`host名`を確認することができる。`SELECT *`のようにアスタリスクで指定しても問題ないが、無駄に多くのカラムが表示されてしまうため、必要なuserとhostに絞って表示している。


#### 新しいユーザーを作成する
```.sql
CREATE USER 'userhoge'@'localhost';
```
![スクリーンショット 2021-12-31 18.23.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/ead16100-6698-77ed-6060-4980bc1b795b.png)
`CREATE USER`によって、新たに`userhoge`というユーザーが作成された。

#### 作成したユーザーの権限を確認する
```.sql
SHOW GRANTS FOR userhoge@'localhost';
```
![権限確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/78732c3a-a9f1-0aeb-e552-f0a4c8942522.png)

`SHOW GRANTS FOR`によって先ほど作成したユーザーである`userhoge`に付与されている権限・ユーザー名・ホストとレベルを確認できる。ちなみに`USAGE`は権限無しという意味になる。

#### 作成したユーザーに権限(CREATE権限)を付与する
```.sql
GRANT CREATE on *.* to userhoge@localhost;
```

![権限作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/7157f4ee-1f0d-97e0-a2b4-8fe5888db9e1.png)
作成済みのuserhogeというユーザーに`GRANT CREATE`を使って権限を付与した。先ほどは`USAGE`だった権限が`CREATE`に更新されている。`CREATE`は「データベースおよびテーブルの作成ができる権限」である。


GRANTで付与できる権限は主に
・ `ALL`：すべての権限(GRANT OPTION および PROXY を除く)
・ `SELECT, UPDATE, INSERT, DELETE`：よくある基本的な操作のやつ
・ `USAGE`：権限無し

などがある。その他や詳細については公式を確認↓


https://dev.mysql.com/doc/refman/8.0/ja/grant.html#:~:text=%E8%A1%A8%C2%A013.11%C2%A0GRANT%20%E3%81%8A%E3%82%88%E3%81%B3%20REVOKE%20%E3%81%AB%E8%A8%B1%E5%8F%AF%E3%81%95%E3%82%8C%E3%82%8B%E9%9D%99%E7%9A%84%E6%A8%A9%E9%99%90


## 権限のレベル
権限のレベルは4種類ある。名前の通りではあるが、`グローバル>データベース>テーブル>カラム`の順に影響範囲が小さくなっていく。
#### グローバルレベル

```.sql
GRANT 権限 ON *.* TO userhoge;
```

#### データベースレベル
```.sql
GRANT 権限 ON db_name.* TO userhoge;
```

#### テーブルレベル
```.sql
GRANT 権限 ON db_name.table_name TO userhoge;
```

#### カラムレベル
```.sql
GRANT 権限  (カラム名) ON db_name.table_name TO userhoge;
```
最適化数学まとめ 1.2（一次形式、二次形式）

#これを知って何が嬉しいか
・多項式をベクトルや行列の形で表せる
・それにより線形代数でよく使う操作で元の多項式の性質がわかる（最大値、最小値など）
#1.一次形式
変数の一次の項のみからなる式を一次形式と呼びます。
n変数の一次形式は以下の通り
$f = a_{1}x_{1}+\ldots+a_{n}x_{n} = \sum_{i=1}^{n}a_{i}x_{i}\ldots(1)$
$a,x$をベクトルの形にすると

$a = \begin{pmatrix}a_{1}\\\ \vdots \\\a_{n} \end{pmatrix}\ldots(2)$

$x = \begin{pmatrix}x_{1}\\\ \vdots \\\x_{n} \end{pmatrix}\ldots(3)$
となります。

(1)は(2)、(3)より、ベクトルの内積として以下のように書けます。
$f = (a,x)\ldots(4)$
(4)を$x_{i}$で偏微分すると、
$\nabla{f} = a$
つまり、一次形式の微分の公式$\nabla{(a,x)}=a$が得られます。
#2.二次形式
変数の二次の項からなる多項式を二次形式と呼びます。
$n$変数の場合は以下の通り
$f = a_{11}x_{1}^2 + a_{22}x_{2}^2+\ldots+a_{nn}x_{n}^2+2a_{12}x_{1}x_{2}+2a_{13}x_{1}x_{3}
+\ldots+2a_{(n-1)n}x_{n-1}x_{n}$
or
$\sum_{i,j=1}^{n}a_{ij}x_{i}x_{j}\ldots(5)$

$a_{ij}=a_{ji}$と仮定して、対称行列$A$とベクトル$x$は
$A = \begin{pmatrix}a_{11}&\ldots&a_{1n}\\\ \vdots&\ddots&\vdots \\\a_{n1} & \ldots & a_{nn}\end{pmatrix}$

$x = \begin{pmatrix}x_{1}\\\ \vdots\\\x_{n}\end{pmatrix}$
上記のベクトルと行列により、(5)は以下の内積の形で書けます。
$f = (x,Ax)$（＊この対称行列$A$は二次形式$f$の係数行列と呼びます）

個人的に$(5)$の$2a_{12}x_{1}x_{2}+2a_{13}x_{1}x_{3}
+\ldots+2a_{(n-1)n}x_{n-1}x_{n}$の部分が嫌だなと思っていたらすぐ後に、二乗和のみの形で表せることがわかりました。（二次形式の標準形）
具体的には、係数行列$A$の固有値を出してあげると二乗和の係数部分が求まります。
#参考文献
「これなら分かる最適化数学」（金谷、２０１５）
回復パーティションを削除。

# 概要

ノートパソコンのｃドライブの空きが足りない。
回復パーティションを削除し、ｃドライブを拡張する。

# 環境

ASUS E200HA
windows 10 home

# 手順

- 管理者でコマンドプロンプトを開く
- diskpartを起動
- list partition
- select partition 3
- delete parttition override
- exit
- ディスクの管理を開く
- ｃドライブを拡張する。


以上。
最適化数学まとめ 2.1（勾配法）

#関数の最適化について
基本的に最適化数学では、ある関数の最大（最小）を知ることに関心があります。（ニューラルネットワークにおける損失関数を最小化する問題など）（そもそも関数の最適化とは最大最小を求めること）
高校で習う数学においては、微分をすることによって最大、最小を求める（解析的に解く）ことができますが、実際の問題を解く際には対象の関数が微分不可能である場合の方が多いです。（コンピュータでは極限、無限小は扱えない、MLでは関数が複雑になりがち等の理由のため）

そこで、数値微分という方法を使って、数値的に問題を解く方法が考えられました。数値微分とは、微分の定義　$f'(x) = lim_{h\to0}\frac{f(x + h)-f(x)}{h}$から極限の操作を取り除いた$f'(x) = \frac{f(x+h)-f(x)}{h}$において、$h$の値を手動で小さな値（0.0001など）にすることで微分計算の近似をするものです。この方法は2点近似と呼ばれます。
一般的には$f'(x) = \frac{f(x+h)-f(x-h)}{2h}$（中心差分公式）の方が近似の精度が高いためよく用いられています。
以下ではこのような数値的な計算手法を使って関数を最適化する方法をまとめます。
##1.1 勾配法
今回はある関数の最小値を求める勾配法（勾配降下法）について考えます。
まず、初期地$x\_0$を設定します。
次に$f'(x_0)$を求め、$f'(x_0)<0$ならば、$x_0$から$x$軸上の正の方向に進み$x_0$を更新します。
$f'(x)>0$ならば負の方向に進み、$x_0$を更新します。
$f'(x)=0$（0にならない可能性があるため、厳密には微小量）となればそこで最小値をとります。
式で表すと以下のようになリます。
$x_{i+1} = x_i - \eta f'(x_i)$
$\eta$は学習率やステップ幅と呼ばれます。これは$x_i$を更新する際にどの位の距離を移動するかを定めるものです。この値はハイパーパラメータと言って人が手動で定めるものです。
Pythonで簡潔に実装すると、以下の通りになります。長くなるので２０回ほどの反復にしましたが、だいぶ0に近づいていることがわかります。


```python:gradient_descent.ipynb
#関数（y = x^2）
def f(x):
    y = x ** 2
    return y
#導関数
def df(x):
    dy = 2 * x
    return dy

η = 0.1                           #学習率
max_iteration = 20                #最大反復回数
x0 = 10                           #初期値
values = [x0]                     #更新する値を格納するリスト

for i in range(max_iteration):
    x0 = x0 - η * df(x0)          # 勾配降下法
    values.append(x0)             # 更新した値をリストに格納する
    print(i, x0)                  #　　更新した値を出力する

#以下出力結果
0 8.0
1 6.4
2 5.12
3 4.096
4 3.2768
5 2.62144
6 2.0971520000000003
7 1.6777216000000004
8 1.3421772800000003
9 1.0737418240000003
10 0.8589934592000003
11 0.6871947673600002
12 0.5497558138880001
13 0.43980465111040007
14 0.35184372088832006
15 0.281474976710656
16 0.22517998136852482
17 0.18014398509481985
18 0.14411518807585588
19 0.11529215046068471

```

##1.2 勾配法の問題点
１つ目の問題点は、勾配を式として用いるため、微分できない関数（連続ではない、もしくは尖っている（例: $f(x)=|x|$など）は扱えません。
２つ目の問題点は、最大、最小以外の極値があれば初期値の与え方によっては、最大、最小値以外の極値に到達してしまう可能性があります。（いわゆる局所最適解）
これを避けるためには、最大値、または最小値をとる点に十分近い初期値を推定して与える必要があります。
３つ目の問題点は、極値が一点のみであったとしても、極値付近の関数形によっては極値に達するまでに時間がかかることがあります。
（この問題を改善するための手法としてニュートン法、共役勾配法、ガウス・ニュートン法、レーベンバーグ・マーカート法が挙げられる）

#参考にしたもの

[MATLAB](https://watlab-blog.com/2020/02/29/gradient-descent/)
「これなら分かる最適化数学」（金谷、２０１５）
[機械学習のための数学おさらい](https://www.slideshare.net/hideoterada5/ss-78954885)
データの前処理まとめ２（カテゴリ変数）

今回はカテゴリ変数の変換についてまとめます。
使用するデータは[House Prices - Advanced Regression Techniques](https://www.kaggle.com/c/house-prices-advanced-regression-techniques/overview)のtrain.csvです。
また、着目する変数はHouseStyleとします。
以下kaggleのdata_description.txtより
>HouseStyle: Style of dwelling
       1Story	One story
       1.5Fin	One and one-half story: 2nd level finished
       1.5Unf	One and one-half story: 2nd level unfinished
       2Story	Two story
       2.5Fin	Two and one-half story: 2nd level finished
       2.5Unf	Two and one-half story: 2nd level unfinished
       SFoyer	Split Foyer
       SLvl	Split Level


データについて

```python:data.ipynb
df['HouseStyle'].describe()
#以下出力
count       1460
unique         8
top       1Story
freq         726
Name: HouseStyle, dtype: object
```


#1.なぜ変換を行うのか
上のデータの例から分かるように、変数が文字列で表されているデータはほとんどの場合そのまま分析に使うことができません。そこで、モデルに適した形への変換が必要となります。（＊数値型であっても、電話番号、郵便番号などの大小関係や連続的な意味を持たないものはカテゴリ変数として扱う）
#2.変換手法
##2.1.one-hot encoding
one-hot encodingでは、n個（今回のケースではn=8）の水準を持つカテゴリ変数をその水準かどうかを二値変数（0or1）を用いることで表現します。
実際に変換して最初の部分だけ表示すると、以下のようになります。

```python:Onehot_Encoding.ipynb
pd.get_dummies(df['HouseStyle']).head()
```

|  | 1.5Fin|1.5Unf|1Story|2.5Fin|2.5Unf|2Story|SFoyer|SLvl|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|  0 |  0 | 0  |0|  0 |  0 |  1 |  0 |0|
|   1|  0 | 0  | 1| 0 | 0  |   0|  0 |0|
|  2 |  0 | 0  |0 | 0 |  0 |  1 |  0 |0|
|  3 | 0  | 0  | 0 | 0| 0  |   1| 0  |0 |
|   4| 0  | 0  | 0  |0| 0  |  1 |  0 |0 |
カテゴリ変数の水準名から自動でデータフレーム型を返してくれるので便利です。
（＊使い方に注意が必要、[こちらのブログに詳細](https://www.haya-programming.com/entry/2019/08/17/184527)）

one-hot encodingの欠点は、特徴量の数がカテゴリ変数の水準数に応じて増えてしまう点にあります。これにより、学習にかかる計算時間や必要なメモリが大きく増えたり、モデルの性能に悪影響を及ぼす可能性が生じます。
この問題に対する対処法は主に３つ考えられます。
１.他の変換手法を試す
２.ある規則でグルーピングして、水準数を減らす
３.頻度の少ないカテゴリを「その他」にまとめる
今回のケースでは直感的に３の対処法が使えそうです。
実際の頻度は以下

```python:n_value.ipynb
df['HouseStyle'].value_counts()
#以下出力結果
1Story    726
2Story    445
1.5Fin    154
SLvl       65
SFoyer     37
1.5Unf     14
2.5Unf     11
2.5Fin      8
Name: HouseStyle, dtype: int64
```
以上より、SFoyer以下はその他としても良さそうです.
#2.2.label encoding
LabelEncodingとは単純に各水準を数字に置き換えるというものです。
今回のデータではカテゴリ変数が０から７までの数値に置き換えられます。
実際にやってみると以下の通りになります。

```python:Label_Encoding
from sklearn.preprocessing import LabelEncoder

feature = ['HouseStyle']
for c in feature:
    lbl = LabelEncoder()
    df[c] = lbl.fit_transform(df[c].values)

df['HouseStyle'].value_counts()
#以下出力結果
2    726
5    445
0    154
7     65
6     37
1     14
4     11
3      8
Name: HouseStyle, dtype: int64

```
上で述べた通り、インデックスの数値が水準を区別する以外の意味を持たないため、このまま訓練データに用いることはあまり適切ではありません。しかし、決定木をベースとした手法では分岐を繰り返すことでこれらの数値を予測に反映することができるので、学習データとして活用できます。（特にGBDTではよく使われている印象がある）

#参考文献
門脇、阪田、保坂、平松　「Kaggleで勝つデータ分析の技術」　技術評論社 (2019/10/9)
最適化数学まとめ1.1（曲線について）


「これなら分かる最適化数学」（金谷、２０１５）を読んだので、理解度の確認を兼ねて要点を簡潔にまとめる。
今回は曲線の法線ベクトルを求めるところまで。
#1.曲線の方程式
（＊何回でも連続微分可能かつ正則と仮定）
平面上の曲線：$f(x,y) = 0$について考える。
当然のようだが$f(x,y)=0$を境界に$f(x,y) < 0$、$f(x,y)>0$の二つの領域に分けられる。
特に円や楕円は内部と外部に分けられるので直感的に分かりやすい。
#2.曲線の法線ベクトル
$f(x,y)=0$上の近接する2点$(\overline{x},\overline{y})$, $(\overline{x}+\Delta{x},\overline{y}+\Delta{y})$について考える。

上の2点は$f(x,y) = 0$上にあることから
$f(\overline{x},\overline{y}) = 0\ldots(1)$
$f(\overline{x}+\Delta{x},\overline{y}+\Delta{y})=0\ldots(2)$
が得られる。

(2)をテイラー展開すると、以下のようになる。(＊２変数の場合のテイラー展開)
$f(\overline{x}+\Delta{x},\overline{y}+\Delta{y}) = f(\overline{x},\overline{y})+\frac{\partial{\overline{f}}}{\partial{x}}\Delta{x}+\frac{\partial{\overline{f}}}{\partial{y}}\Delta{y}+\ldots\ldots(3)$

(1)、(3)より、$\frac{\partial{\overline{f}}}{\partial{x}}\Delta{x}+\frac{\partial{\overline{f}}}{\partial{y}}\Delta{y}+...=0\ldots(4)$
となる。

ここで、ベクトル$\nabla{f}$, $\Delta{x}$を
$\nabla{f} = \begin{pmatrix}\frac{\partial{f}}{\partial{x}} \\\ \frac{\partial{f}}{\partial{}y} \end{pmatrix}$ 

$\Delta{x} = \begin{pmatrix} \Delta{x} \\\ \Delta{y} \end{pmatrix} $
と定義すると、(4)は
$(\nabla\overline{f},\Delta{x})+\ldots=0$
と内積の形で書ける。

$\Delta{x}$が小さいほど$\ldots$の項は急速に小さくなる。つまり、$(\nabla\overline{f},\Delta{x})=0$(内積０)の形に近づくため、ベクトル$\nabla\overline{f}$が点$(\overline{x},\overline{y})$近傍で曲線に直交すると言える。
これはどの点に対しても成立するから、以下の定理を得る。

・定理：曲線$f(x,y)=0$の点$(x,y)$における法線ベクトルは$\nabla{f}$である。
データの前処理まとめ１（時間型）

データ分析をかじり始めたので、学んだことをまとめていきます。
主にkaggleのデータを使います。
今回使うデータはkaggleの[New York City Taxi Fare Prediction](https://www.kaggle.com/c/new-york-city-taxi-fare-prediction/data?select=train.csv"今回使うデータ")です。
train.csvの容量が大きかったので、データ数を5500ほどに削減して利用しました。
#1.時間型データを変換するまでの流れ
##1.1必要なライブラリをimport
```python:import.ipynb
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use('ggplot')
import seaborn as sns
```
##1.2ファイルの読み込み
```python:read_csv.ipynb
df = pd.read_csv('train.csv', nrows=5500)

```

##1.3必要なデータ以外を削除、データの情報を表示
```python:use_data.ipynb
df = df.loc[:,'fare_amount','pickup_datetime']
df.info()
#以下出力結果
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5500 entries, 0 to 5499
Data columns (total 2 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   fare_amount      5500 non-null   float64
 1   pickup_datetime  5500 non-null   object 
dtypes: float64(1), object(1)
memory usage: 86.1+ KB
```
ここでpickup_datetimeの型がobject型であることがわかります。
しかし、基本的に数値型に変換しなければモデルの入力に用いることができないため、pickup_datetimeの型を変換する必要があります。

##1.4データの変換
```python:tr_data.ipynb
df['pickup_datetime'] = pd.to_datetime(df['pickup_datetime'], format="%Y-%m-%d %H:%:M:%S UTC")
df['pickup_datetime'].head()
#以下出力結果
0   2009-06-15 17:26:21
1   2010-01-05 16:52:16
2   2011-08-18 00:35:00
3   2012-04-21 04:30:42
4   2010-03-09 07:51:00
Name: pickup_datetime, dtype: datetime64[ns]

```
これでモデルの入力に用いることができる型に変換できました。
#2.その後の処理
以上の処理から得られたデータにより、様々な特徴量を得ることができます。
例えば、単純に月を特徴量に加えるだけでも、季節性をモデルに反映させることが期待できます。季節性が売り上げに大きく絡む商品の需要予測などに役立ちそうです。（＊十分なデータがある場合）
注意点としては、線形モデルでは周期的な変数から上手く傾向を捉えられない場合があるとのことです。（GBDTなどの決定木系は悪影響は出にくい）
いずれにせよ、目的変数からどういった特徴量が有効か、傾向を捉えるために十分なデータがあるか、あとは用いるモデルとデータとの兼ね合い辺りを考えると良さそうです。
#参考文献
門脇、阪田、保坂、平松　「Kaggleで勝つデータ分析の技術」　技術評論社 (2019/10/9)
Vueの環境変数が設定できず悩んだ件（vite使用）

## process is not definedに悩まされてviteの設定を調べ解決

Vue3でdotenvを使おうとして、`process.env.VUE_APP_HOGEHOGE`を使おうとしたところ、

```
Uncaught ReferenceError: process is not defined
```
というエラーに悩まされました。

Vue3ではdotenvをinstallしなくても使えるようなので、installせずやってみて、
うまくいかないのでinstallしてみてもだめ。

暫し考えて、viteを使っていることが関係している可能性を思いつき、調べてみたらビンゴ。
以下のページに答えがありました。
https://ja.vitejs.dev/guide/env-and-mode.html

viteでは、
`process.env.VUE_APP_HOGEHOGE`
ではなく、
`import.meta.env.VITE_HOGEHOGE`
の形式で読み込めると。

書き換えてみて、無事読み込めました🎉

---

## typescriptの場合の設定

やろうとしていたことは、axiosに食わせるURLの環境変数を.envで設定することだったのですが、

```javascript
const apiUrl: string = import.meta.env.VITE_API_URL
const res = await axios.get(apiUrl)
```

としてbuildしてみると、

```javascript
 Argument of type 'string | boolean | undefined' is not assignable to parameter of type 'string'
```

といった形で型定義で怒られました。

どうしたらいいかも、上記のvite公式ページの下の方に書いてありました。

`src/env.d.ts`に以下のようなinterfaceを追加してやるとOKに。

```javascript
interface ImportMetaEnv {
  readonly VITE_API_URL: string
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}
```

これで無事、vite利用環境にて.envを通して環境変数を使うことができました👍

---

あと、viteにおいては、 .envより、.env.productionなどの方が優先して適用されるようで、環境ごとの.envファイルを準備することが重要とも。
production用のURLは.env.productionに書いて、無事反映されました。

最初、リモートの.envに値を書いてみたのですが、反映されず暫し考えて、build時に別ファイルで設定すべきであることを知った次第で。

---

無事viteで.envが使えるようになって嬉しかったので、備忘録を残しました。
自分用のKivy Launcherを作る

# はじめに

いつの間にか最新版の[Kivy Launcher](https://github.com/kivy/kivy-launcher)のapkがgithub actionsで作られていて普通に落とせるようになっていました。ただこれは

- google play storeに上がっている古い物とは違って最低限の物しか入っていない
- Pythonのversionが[既定値](https://github.com/kivy/python-for-android/blob/06dd1e0a9b301c5d1a4609bec45b966bb8dd012d/pythonforandroid/recipes/python3/__init__.py#L59)
- ABIが[armeabi-v7a](https://github.com/kivy/kivy-launcher/blob/c08066c23827365369b16526241cdbdf44ec2ec7/buildozer.spec#L179)

なのでこれを自分好みに改造しようというのが今回の趣旨です。

# 公式repositoryをfork

改造するわけですから改造用のbranchを作り、公式のmain branchが更新される度にrebaseするような形の運用が良いんじゃないかと思います。この時repositoryの既定branchを改造用のbranchにしてちゃんと改造用のbranchでgithub actionsが動くようにしてあげます。(ココらへんはもっといい方法があるかもしれません。)

# android端末のABIを調べる

[別の記事][betsu]でも書きましたが最適なABIの方が端末の力を最大限に引き出せると思われます。なのでlink先の手順に従ってどれが最適なのか調べます。`adbコマンド`は一度でもbuildozerを使った事があれば`~/.buildozer/android/platform/android-sdk/platform-tools/adb`にありますが、無い人は[SDK Platform Tools](https://developer.android.com/studio/releases/platform-tools?hl=ja)でも落とすと良いんじゃないかと思います。

# 改造

自分は[このように](https://github.com/kivy/kivy-launcher/compare/main...gottadiveintopython:my_own_favor)やりましたが、最適なABIが`armeabi-v7a`では無い人は`android.arch = armeabi-v7a`の部分も、launcherにあまり権限を与えたくない人は`[app:android.permissions]`の部分も弄ると良いと思います。また使いたいPythonのversionが`3.9.9`ではない人は当然その部分も変えて下さい。

# apk生成/インストール

自分のrepositoryへ改造用branchをpushするとapkが出来上がるまで12〜13分でした。無料プランでこの時間でapkが作れるのはありがたいですね。apkを落としたら野良アプリとしてインストール。

# Kivy Launcher上でアプリを実行

launcherの使い方は以前と何も変わっていなかったので省きます。python interpreterの吐くlogを見たい時は端末を開発者モードでPCに繋ぎ、PC側で`adb logcat *:S python:D`と打つだけです。

[betsu]:https://qiita.com/gotta_dive_into_python/items/e7cb3dbecf5784c24ee5
Phoenix 1.6.5にTailwindを追加する方法


[追記]
現在では[phx_gen_tailwind](https://hexdocs.pm/phx_gen_tailwind/Mix.Tasks.Phx.Gen.Tailwind.html#content)をdeps.getして

```
mix phx.gen.tailwind
```
を実行するだけで全て設定されます。

---

基本的には[Mix Task](https://hexdocs.pm/phx_gen_tailwind/Mix.Tasks.Phx.Gen.Tailwind.html#content)を実行するだけで諸々設定してくれます。

あとはassets/css/app.cssに

```elixir:assets/css/app.css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

を追記すれば動くようになります。
20220101 GCP/GCE 覚書

日頃はAWSばっかりなんですが、ちょっとGCPも勉強してみようと思いました。2021年1月1日にはこうでしたというのを書いておきます。

https://qiita.com/Brutus/items/22dfd31a681b67837a74

とか

https://qiita.com/ndxbn/items/7ef0a96e409a5b5837bd

を参考にさせてもらいました。

# GCEを無料で試せるリージョン
GCEを無料で試せるリージョンには変遷があるらしく、説明しているページによって記述が違うのですが、公式日本語版には

> オレゴン: us-west1
アイオワ: us-central1
サウスカロライナ: us-east1

と書かれています。

# WebでShell
鍵作ったり登録したりしなきゃと思っていたんですが、なんかGCEインスタンス作ったらもうSSHボタン一発でWebからShell使えますね。これは便利だ。
XXX over SSHみたいなことをしようと思ったらやっぱり鍵作ったり登録したりが必要なのでしょうが。

# 静的外部IPアドレス（１／９追記）
静的外部IPアドレスは標準VMで使用すると$0.004/hと書かれています。ちゃんと使っていれば無料だと思わせる情報を各所で見たのですが
> *プロモーション: 2020 年 1 月 1 日から 2020 年 3 月 31 日まで、課金は免除されます。

これのことでしょうか？終わってる。
最近はHTTPSじゃないと出来ないことも多い→ドメインが要る→静的IPアドレスが要る。
0.004*24*30で毎月約2.88ドル。
「月額10ドルぐらいで何か作って遊ぼう」
という腹積もりだったので結構イタいです。
ルーティングのネストとは

ルーティングのネストについて勉強したので備忘録としてまとめます。

　ルーティングのネストとは、Twitterなどにある、コメント機能の実装に必要です。
　あるtweet画面の詳細ページを開くと、それに紐づくコメント一覧が出てきます。
これはネストによって、コメントの一つ一つにtweetのidが記録されているからです。

例えばTwitterを例にすると、以下のようなルーティングになります。

```Ruby:ruby.rb
 Rails.application.routes.draw do
  resources :tweets do
     resources :comments, only: :create
  end
 end
```

tweetsコントローラーのルーティングの中に、commetnsコントローラーのルーティングが入れ子構造になっている事が分かります。


#親モデルのidを保持できる
　ネストを行う理由は、親モデルのidを保持できるからです。rails routesコマンドで実行結果を確認してみます。

```
% rails routes

#実行結果
tweet_comments POST   /tweets/:tweet_id/comments(.:format)         comments#create

```
 「/tweets/:tweet_id/comments」とある事から、ネストさせた事でtweet_idがパスに含まれている事が分かります。結果として、コメントした時にそれがどのtweetに紐づいたものかを特定できるようになりました。

反対にネストを外してrails routesしてみます。
 
```
% rails routes

#実行結果
comments POST   /comments(.:format)        comments#create
```
tweetsコントローラーとのネストを外すと、コメントのpathにtweet_idを含められない事が分かります。

#まとめ
　ルーティングのネストを行う理由とは、親モデルのidを関連モデルに保持させる事でした。これによりTwitterなどのコメント機能の実装ができます。
Lambda layersでAWS SDKを使用できるようにする

#ゴール
Lambda上でNode.jsのライブラリ(今回はaws-sdk)を使用できるようにする

#前提
・LambdaのランタイムはNode.js 14.x
・OSはWindows(10 Pro)

#やることたち
①node_modulesのライブラリをDL
②ZipしてLambda layersに登録

#①node_modulesのライブラリをDL
・コマンドプロンプトを開く

・「nodejs」という名前のディレクトリを作成

```
mkdir nodejs
```

・ディレクトリ「nodejs」を選択する

```
cd nodejs
```

・npm(Node Package Manager)を初期化する(設定情報の入力を求められるがすべてEnterでスキップしてもよい)

```
npm init
```

・aws-sdkをインストールする(Node.jsにてほかのライブラリを使用する場合は一緒にインストールしておきましょう)

```
npm install aws-sdk
```

#②ZipしてLambda layersに登録
・①でaws-sdkをインストールした「nodejs」フォルダをエクスプローラーから開き、Zip形式に圧縮

・AWSのコンソールにてLambdaの画面を開き、左メニューからレイヤーを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/1f86fd7f-8eeb-df0c-d0bf-4661a3d49283.png)

・「レイヤーの作成」を押下し、Zipファイル「nodejs」をアップロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/7259c3b7-b639-3a86-9060-8e0f6d93fd92.png)

・ランタイムを選択し、作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/672940c9-fd67-0d6e-902b-caae75f46acd.png)

・完了

これでLambdaの関数を作成した際に本レイヤーを選択することでNode.jsのライブラリが呼び出し可能になります。

※レイヤーの使用方法は以下のリンクを参照
https://qiita.com/DJROU/items/639495bd5003a4fb8262
【レポート】CCNAの実機講習会に参加した

# この記事は

CCNAの実機講習会に参加した時のレポートです。
実機の講習会はいくつかありますが、内部を伝える記事やレポートは少ないので、書くことにしました。
※2021年12月30日時点のレポートです。価格や時間は変更される場合があります。

## なぜ参加したの？

CCNAを取得した/取得に向け学習しているが、実機を触った経験がなかったため。
『`このまま実務に携わって大丈夫か？`』『`そもそも採用してもらえるのか？`』
と不安だったので。
結論から言うと、実機を触った経験がないまま実務に携わるのは、オススメしません。

## どこの講習会に参加した？

* __参加した講習会__

    - 東京（江東区）で開講されている「[__CCNA実機ラボ2021__](https://cisco.connpass.com/)」さんの
「[__ネットワーク勉強会__](https://cisco.connpass.com/event/231985/)」フルコース。

        ![S__67813380.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/f267b03e-c5c6-554c-6cd4-9750ed3d6d5e.jpeg)
    
* __実機講習会の特徴__
    1. 少人数（参加者は2～3人）
    1. 現場経験のあるエンジニアが講師
    1. 分かりやすいテキストと授業
    1. 豊富な機材
        - ひとりひとりが個別の機材を使用（数人で1つの機材ではない）
    1. 短期集中型
        - フルコースは、朝から夕方まで
        - 午前のみのコースや、午後のみのコースもあり
    1. 費用がリーズナブル
        - 1科目　　　　　　　：2千5百円（税込み）
        - 6科目（フルコース）：1万5千円（税込み）

## どんなことしたの？

* __集合__ 🕤 9:20
    - 場　所：会場近くのコンビニ内（ファミリーマート 江東白河四丁目店）
        - アクセス：最寄り駅（菊川駅,  清澄白河駅）から徒歩10分ほど
            - 菊川駅　　：都営地下鉄 新宿線
            - 清澄白河駅：都営地下鉄 大江戸線/東京メトロ 半蔵門線

        ![map.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/b5b7bc58-5dd2-07a3-2b04-be85cd1c86c2.png)
    - 参加者：3人（講師を含む）
    - 持ち物：費用以外とくになし（ペンやノートがあると便利かも）
* __歩いて会場に移動__ 🕤 9:30
    - 会　場：江東区の集会所（集合場所から徒歩数分ほど）
        - トイレ　：あり
        - ＷｉＦｉ：なし
        - 近くにスーパー/自販機：あり

        ![IMG_20211230_174345.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/57049d3f-98c7-5715-d67f-fe7a27e1b8b3.jpeg)

* __簡単な自己紹介__ 🕤 9:40
    - 主催者で講師の [__大谷さん__](https://twitter.com/CCNAHandsOnLab "CCNA実機ラボ2022_おおたに（Twitter）") は、明るくて、気さくな方でした😆

* __実機講習__ 🕙 10:00～17:00
    - 機　材（1人あたり）
        - Ciscoルータ x 6台
        - Ciscoスイッチ x 1台
            - 写真には写っていませんが使用。
        -  ノートPC x 1台
            -  TeraTermを起動して、ルータやスイッチを操作するのに使用。
    - カリキュラム
        - 1科目：Static Routing
        - 小休憩（10分）
        - 2科目：Dynamic Routing(OSPF)
        - 昼休憩（30分）
            - ちなみに、みんなでマックを食べた🍔
        - 3科目：VLAN(access,trunk)
        - 4科目：VLAN Routning
        - 小休憩（10分）
        - 5科目：ACL
        - 6科目：FHRP
    - カリキュラムのレベル
        - レベル：中～高
            - 知識ゼロでの参加は、無理です。
            - CCNA取得済み / 取得に向けて半分程度学習が進んでいる方が良いです。
            - コマンド操作にある程度慣れている方が良いです。
                - 黒い画面が苦手な方は、事前に練習が必要です。

        ![IMG_20211230_174351.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/6a32d635-b2fa-08dc-6932-aeb6800d7761.jpeg)

* __後片付け（撤収）__ 🕔 17:00～18:00頃
    - 各々、写真を撮影したりしました。
    - みんなで機材を撤収したりなど、後片付け。

* __解散__ 🕕 17:00～18:00頃
    - 費用の支払い
    - 簡単にお礼や挨拶をして解散。

## カリキュラムを体験してみたい

* カリキュラムと同程度の [__動画__](https://youtu.be/iYuM10zxSv0 "CCNA実機ラボ") がYouTubeに公開されています（主催者で講師の大谷さんのチャンネル）。
    <iframe width="560" height="315" src="https://www.youtube.com/embed/iYuM10zxSv0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

## 参加した感想は？

内容が濃く、レベルが高かった（最後は、グッタリ）。
「[__Ping-t__](https://ping-t.com/) や 書籍 に書かれていたのは、このことだったのか！」と、
知識と実際の操作が結びつくのが面白かった！
また「身体を動かして学ぶ方が、身に付いてる実感があるな」と思いました。
mapメソッド(Ruby)

Ruby3.0.0
<a href="https://docs.ruby-lang.org/ja/latest/class/Array.html#I_COLLECT"> Arrayクラスmap</a>
mapメソッドは配列を返す

```ruby
#配列の値全てに数式を入力(nは変数)
a[0,1,2]
a.map{|n| n + 1} # => [1,2,3]

#配列の値全てを文字列に変換する
a.map(&:to_s)

#n個✖️nの配列に特定の値(0)を入力する
n = 2
a = Array.new(n).map{Array.new(n,0)}
puts a
# => [[0,0],[0,0]]
```
bor(geth みたいなもの)で leveldb/table: corruption on data-block エラーのメモ(未解決)


# 環境

* Ubuntu 20.04
* X399
* NVMe SSD(XFS format)

# 症状

Matic(a.k.a 0xPolygon)の `bor` でブロック落としていると, 一日くらいするとタイトルのように corruption が起きる(結構頻繁におきる).

`bor` の中身がほぼ `geth` だとすると...

https://github.com/ethereum/go-ethereum/issues/2568

結局原因は不明(SSD 変えたら治ったなどの報告はある)


Chia plotting で Ubuntu + XFS だと高負荷時エラー出ることがあるので, カーネル周りとのかの問題かもしれません
(あとはメモリエラーとか?)

あと, dmesg で 

```
PCIe Bus Error: severity=Corrected, type=Data Link Layer
```

が出ている.

# 解決

不明. 該当のファイルだけ消して.. というのでしのいでもいいのかしら?

# TODO

* [ ] `pci=nommconf` してみる https://l-w-i.net/t/ubuntu/pci_bus_error_100.txt
* [ ] ext4 など Ubuntu で利用する場合に問題の少ない file format を使う(or Ubuntu server を使ってみるなど)
DBのアーキテクチャ種類　備忘録

#目的
DBのアーキテクチャ種類　備忘録

#スタンドアロン
　インターネットなどのネットワークに接続されておらず、「孤立して」動作する。

#クラスタ
シェアードナッシング（サーバーとDBセット）とシェアードディスク（複数サーバーと１つのDB）の2種があった。
シェアードディスクには「Active― Active」と「Active―Stand by」があった。
Active― Active：クラスタを構成するコンポーネントが同時に稼働する
Active―Stand by：クラスタを構成するコンポーネントのうち、同時に稼働するのはActiveのみで、残りは待機(Standby)している
　
「Active―Stand by」には「Hot-Standby」と「Cold-Standby」があった。
Hot-Standby：普段から待機系のデータベースを起動させておくというものです。
Cold-Standby：待機系のデータベースを普段は起動させておらず、現用系のデータベースがダウンした時点で待機系を起動するタイプのもの。

#レプリケーション（複製）
　データベースサーバとストレージのセットを複数用意するもの。

#参考
おうちで学べるデータベースのきほん
Nuxt.jsのmiddlewareを使って権限チェックしたらスパゲティになってしまった話

# はじめに
# 実装したかった仕様
- 当初の仕様では、下記の３つの利用権限のみを管理する想定でした。

```
■利用権限
・ 上級会員権限
・ 中級会員権限
・ 一般メンバー権限
```

- しかし、途中で利用権限とは別で役職で権限を分けるオプション権限が仕様追加になりました。これにより、開発後半で、実装が複雑になっていきました…。

```
■利用権限
・ 上級会員権限
・ 中級会員権限
・ 一般メンバー権限

■役職オプション権限
・ 役員権限
・ 課長権限
・ 部長権限
```

![スクリーンショット 2022-01-01 16.46.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85181/52e1b699-734d-a833-4fae-d29069f12859.png)

- 権限パターン表のイメージ
![スクリーンショット 2022-01-01 16.50.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85181/cb11ef59-1eec-cc8e-a169-b207bd9bc0cf.png)

- 画面上での制御イメージ
![スクリーンショット 2022-01-01 16.51.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85181/288e4a6c-a581-055e-8b05-7449dbd88096.png)



# 実際に実装した内容
## 権限チェックの全体フロー
- ログイン時に権限情報を取得して、それをlocalStorageに格納しておき、middlewareで権限チェックするような構成です。

![スクリーンショット 2022-01-01 16.52.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85181/32dc05e0-8977-b688-d1b4-fd2f739475a4.png)

## 実装内容
![スクリーンショット 2022-01-01 16.57.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85181/f032aa9c-73bf-28b0-976a-bf8cb3fabe84.png)

- 権限に応じた閲覧可能なURL定数をまとめたファイル

```js:permissionConst.js
const permissions = {
  'employee': {
    general: [
    '/admin/organization', 
      '/admin/account'
  ]
  },
  'admin': {
    general: [
      '/admin/organization',
      '/admin/account',
      '/admin/analysis'
    ]
  }
}

```

- 認証周りのmiddlewareファイル


```js:auth.js
// URLが企業管理画面の場合
if (fullPath.startsWith('/admin')) {

  if (permissions === 'admin') {
    // ダッシュボードへ
    redirect('/admin');
  }

  // URLが従業員画面の場合
} else if (fullPath.startsWith('/user')) {

  if (permissions === 'admin') {
    // ダッシュボードへ
    redirect('/user');
  }
}
```

- 権限制御の画面イメージ
![スクリーンショット 2022-01-01 17.04.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85181/74adaf0b-6ed4-8985-a2a7-81473ea638f6.png)

## 実装してみた中での問題点
- 追加で新しい権限の概念が出てきた際にさらにif文地獄になる。
- 新しい権限が増えた時にメニューの表示・非表示の制御が難しくなる。

# 失敗を通しての改善策
- バックエンド側で細かい権限の制御ロジックを書く。
- ビット演算で複数の権限を一意に表現する。
- メニューの表示・非表示もバックエンド側で判別して、JSONで返却し、フロント側ではそのJSONを元にメニューの出し分けを行う。

![スクリーンショット 2022-01-01 17.06.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85181/04f4490a-c32a-c426-26d0-b243b13cee08.png)
JavaとKotlinの基本

#出力

```sample.java
System.out.println("Hello World");
>_コンソール
Hello World
```

```sample.kt
println("Hello World");
>_コンソール
Hello World
```
#変数の定義
```sample.java
//変数の初期化
int number = 3;
String name = "Hanaki";
//変数の更新
name = "Kawatani";
//自己代入の省略形「1を足す」「1を引く」
number++;
number--;
```

```sample.kt
var number: Int = 3
var name = "Hanaki"
//Kotlinには型推論機能があり、型の指定を省略できる
```

#データ型
| 型 | ビット幅 | 種類 
|---|---|---|
| Double | 64ビット | 浮動小数点数 
| Float | 32ビット | 浮動小数点数 
| Long | 64ビット | 整数 
| Int | 32ビット | 整数 
| Short | 16ビット | 整数 
| Byte | 8ビット | 整数 
| String | - | 文字列 
| Char | - | 文字
| ULong | 64(符号なし) | 整数
| UInt | 32(符号なし) | 整数 
| UShort | 16(符号なし) | 整数 
| UByte | 8(符号なし) | 整数
SwiftPackageManagerで導入したパッケージの読み込みを高速化する

# SwiftPMで導入したパッケージの読み込みが遅い

という経験ありませんか？
Xcodeを開いてから編集可能になるまで数分待っているみたいなこともあると思います。
特にFirebaseとかgrpcとか入れていくとどんどん遅くなっていきます。
これらは依存解決に時間がかかっているように見えます。
しかも失敗したらReset Package Cachesしてやり直しです。

![CleanShot 2022-01-01 at 16.46.26@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24979/5538f09c-e82a-c313-9d2e-a3998e25a4db.png)

# なぜか`xcodebuild`で依存性の解決をすると早い

Xcodeのコマンドであるxcodebuildでもswiftpmの依存解決が出来るのですが、実はこっちを使うと早く終わるケースがあります。
自分の環境では20~30%ほど早くなり、失敗することも無くなりました。

```
$ xcodebuild -resolvePackageDependencies
```



# zshでエイリアスを貼る

普段はXcodeを`xed`コマンドで開いているのですが、開く前に上記の`xcodebuild `を走らせる`xxed`エイリアスを定義してみます。

```:zshrc
# xed extension
alias xxed="xcodebuild -resolvePackageDependencies && xed"
```

これで`xxed`でプロジェクトを開くとすぐに編集可能になりました。
WebARENA IndigoのVPSにvnc接続してwindowsアプリを動かす。 その1.インスタンス作成からVNC接続まで 

# 初めに

本記事は以下手順の備忘録です。

1. WebARENA Indigoで作成したUbuntuのインスタンスをVNCでの操作する。
2. wineを導入してwindowsアプリを動かす。

Linux系OSのVPSにVNC接続してwindowsアプリを動かそうとした理由は、
windows系OSのVPSと比較してランニングコストを大幅に下げるためです。

## インスタンスの準備

### 1. 公式のスタートアップガイドと以下サイトを参考にインスタンス作成、ssh接続、初期設定を行う

#### 公式のスタートアップガイド
https://help.arena.ne.jp/hc/ja/sections/360009023513
#### 参考サイト1
https://killtime.blog/webarena-indigo-instantiation-ssh/ (インスタンス作成からSSH接続)
https://killtime.blog/webarena-indigo-initial-settings/ (初期設定)

※私は`ubuntu 20.04 メモリ1G`でインスタンス作成しました。

#### Windowsで「Tera Term」を利用してSSH接続する

#### 接続先情報の確認
接続先のIPアドレスはWebARENA Indigoのコントロールパネルから,
「インスタンス管理 > インスタンス」へ移動して一覧からインスタンス名をクリック
赤枠部分のIPアドレスをコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1863564/38887d8e-9ee0-aea1-2a34-8a3090ec78d5.png)

####「Tera Term」を起動してインスタンスにSSH接続する。
ホストにIPアドレスとTCPポートにポート番号(デフォルトは22)を入力
サービスはsshにチェック入れる
入力後OKを押下する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1863564/654b7b8f-8cd6-af0c-3444-71f09178f53b.png)

##### 認証情報を入力する。
ユーザー(デフォルトはubuntu)を入力
パスフレーズは空欄のまま
「RSA/DSA/ECDSA/ED25519鍵を使う」にチェックを入れる
秘密鍵に公式のスタートアップガイドでSSH鍵作成時に保存した秘密鍵ファイルを選択する。
　　　　 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1863564/8a8342f0-de8f-a532-bad0-d92803e9f60b.png)

メッセージ表示されたらSSH接続成功



```
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.0-91-generic x86_64)
~以下略~
```

### 2. VNCサーバーを立ててVPSをGUIで操作する。

#### 以下の記事を参考にGNOME環境とVNCサーバー(tigervnc)を導入する。
https://qiita.com/_dakc_/items/81ca237dfc4cfec855d9

※ファイヤウォールにVNCサーバーで設定したポートを開放しないとアクセスできないので注意
※VNCはセキュリティがないに等しいので、SSHポートフォワードなどでセキュリティを強化することを推奨

#### VNCサーバーに接続する。(windows)

VNCクライアントソフト(VNC Viewer)をインストールして起動する。

アドレスバーに以下を入力してインスタンスに接続する。

```
< インスタンスのIPアドレス >：< VNCサーバーで設定したポート番号>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1863564/c6f1efed-e4e1-69f7-2eaa-a01a73b2a070.png)

接続成功するとGNOMEデスクトップが表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1863564/26c4a74a-64f8-1945-42a0-9b093792c717.png)

#### 以下に続く
WINEを導入してwindowsアプリを使用する（記事作成中）
MySQLのインデックスとロックについて

全然わかってないので後追記。

# MySQLのインデックスについて

覚えておきたいインデックス用語の種類3つ。

1. クラスタインデックス
1. セカンダリインデックス
1. カバリングインデックス

## 1. クラスタインデックス

* 要は`PRIMARY KEY`(主キー)のこと。
    * `PRIMARY KEY` が定義されていない場合、 `NOT NULL` のユニークインデックスが使用される。

## 2. セカンダリインデックス

* クラスタインデックス以外のインデックスのこと。

## 3. カバリングインデックス

* クエリが必要とするカラムがすべて(セカンダリ)インデックスに含まれている場合、インデックスだけを読めば良いのでとても速い、という話。
    * インデックスのツリーを辿るとき、クラスタインデックスを辿ることなくセカンダリインデックスのみを辿ってレコード取得することになるので速い。

## リンク

* [14.2.13.2 クラスタインデックスとセカンダリインデックス
](https://dev.mysql.com/doc/refman/5.6/ja/innodb-index-types.html)
* [MySQL with InnoDB のインデックスの基礎知識とありがちな間違い](https://techlife.cookpad.com/entry/2017/04/18/092524)
* [MySQLでインデックスを使って高速化するならCovering Indexが使えそう](http://blog.livedoor.jp/sasata299/archives/51336006.html)
* [MySQLのインデックスを学ぶ(1)](https://blog.kyanny.me/entry/20100920/1284992435)
* [知って得するInnoDBセカンダリインデックス活用術！](http://nippondanji.blogspot.com/2010/10/innodb.html)


# MySQL(InnoDB)のロックについて

1. レコードロック(Record lock)
1. ギャップロック(Gap lock)
1. ネクストキーロック(Next-key lock)

## 1. レコードロック

* インデックスレコードに対するロック。

## 2. ギャップロック

* インデックスレコード間（rec1 <= x < rec2）へのレコードの挿入を阻止するロック。

## 3. ネクストキーロック

* インデックスレコードと、その手前のギャップに対するロック。

## リンク

* [良く分かるMySQL Innodbのギャップロック
](https://qiita.com/kenjiszk/items/05f7f6e695b93570a9e1)
* [InnoDBのロックの範囲とネクストキーロックの話](https://blog.kamipo.net/entry/2013/12/03/235900)
* [InnoDB の行レベルロックについて解説してみる](https://abicky.net/2016/11/30/082130/)

## 感想

全然わからん。
uninitialized constant Grape::Validations::Base (NameError)が発生

# 結論
grapeのバージョンv1.6.2 で grape-kaminariのバージョン0.4.1 を使うと
railsコマンド使用時にタイトルのエラーが発生する。

# 原因
```grape-kaminari-0.4.1/lib/grape/kaminari/max_value_validator.rb
module Grape
  module Kaminari
    class MaxValueValidator < Grape::Validations::Base
      def validate_param!(attr_name, params)
        attr = params[attr_name]
        return unless attr.is_a?(Integer) && @option && attr > @option

        raise Grape::Exceptions::Validation.new(
          params: [@scope.full_name(attr_name)],
          message: "must be less than or equal #{@option}",
        )
      end
    end
  end
end
```

3行目の継承元が　`Grape::Validations::Base`　となっていること。

grapeのバージョンが1.5.3だと問題ないが
1.6.2だと
`Grape::Validations::Validators::Base`
としないといけなくなっている。

先ほどぶち当たった問題なので、急ぎ投稿しておく。
PearsonVUEのシステムテストでvmwpが消えてくれない件

<p>ピアソンVUEの試験システムである<strong>OnVUE</strong>で事前システムテストする際に「<strong>vmwp</strong>」が起動していると事前テストが開始できない問題が発生</p>

<p>タスクマネージャーを起動させて終了しようとするとタスクマネージャーも落とせと言われ問題増加…<br>PowerShellでタスクキルしてみようとするも権限が足りないのかキル不可<br>管理者権限でPowerShellを起動して強制削除するもすぐに起動してしまう</p>

<p>多分仮想マシン関係だと思うけどVMwareも起動してないしどうしたものか…と悩んでいたが、最近インストールしたそれっぽいものは<strong>Docker</strong>しかないので犯人決め打ち</p>

<p>起動時にDockerを立ち上げないようすることで「<strong>vmwp.exe</strong>」も起動しなくなった<br></p>

![dockergen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2456260/9825eab5-59ae-f009-0f75-e3e57b819a1b.png)

<p>（ググった所少し前のバージョンまでWindows版Dockerでは起動時立ち上げ☒を外しても起動していた模様）<br>無事OnVUEの事前システムテストが進み試験を受けられることとなった</p>

<p>以上、備忘録でした。<br />次回試験受けるときもピアソンVUEでの自宅試験を受けようと思います。</p>
独学無課金でプログラミング始めたので、記録を残します。

こんにちは。
プログラミングを始めたので備忘録としてアカウントを作りました。
Qiitaを始めたきっかけはこちらの記事でみかけたからです。

https://qiita.com/engineerhikaru/items/5181fbf3e38cfb9b47df

お手柔らかにお願いいたします。

progateに課金を考えましたが、1月は課金分の元を取れる気がしなかったので、とりあえず独学でがんばります。

始めて数日ですが、つまづいたところの備忘録にしたいので、書き残します。
誰かのためになれば幸いです。

#始めたきっかけは海外永住を目指したいから

元々、ワーホリで海外に滞在していました。
コロナ禍で諦めていましたが、やっぱり長く住みたいと思い永住権取得に向けて色々調べました。

プランは

現地で職業訓練学校に通う
↓
気合で就職にこぎつける
↓
ワークビザ獲得
↓
永住権申請

です。

コロナ禍で、永住権取得枠が増えており、IT系の需要も増えているようです。
(甘くないのは重々承知)

未経験なので、学校のお金を貯めつつ自身に合っているかを確かめたいので、とりあえず行動しました。

Twitter開設は面倒なので未定です。

#知識量について

未経験ですが、どんぐりレベルでも一応書いていきます。
##やったことあること
小学生の時にgeocitiesでHP作成を試してみたことあり、HTMLに少し触れていました。
現在はWordpressでブログを所持していますが、基本的に
ググる→コピペで生きています。

## Progate
無料部分の一部を終えました。
HTML&CSS ,JavaScript ,JQuery　の3つです。
現在は、PHPの無料部分に取り組んでいます。

無料部分は全てこなす予定です。

##並行してやること

勉強のための勉強はつまらないので、勉強という名目で同時にYouTubeやwebを使って簡単なものを作っていきます。
現在、取り組んでいるものは
TO DOリストを作っています。
以下の動画を参考にしています。

https://www.youtube.com/watch?v=E08jeQBa1D0&t=2296s

すでに躓きまくっていますが、少しずつ形になっていくのは楽しいです。

#学習の目標

現地の学校に通った時に英語で躓いても「知識で何とかする」ことですが、それは終わりがないので、作品をいくつか作ることを目標とします。

やるべきこととは別な気がしますが、ほしいものがあります。
１つはRPGゲーム、もう1つはある便利ツールです。

これを一応のゴールとします。

やってくうちに色々変わると思いますが、どうぞよろしくお願いします。
AMD CPU搭載PCでAVDのVMアクセラレーションを有効化する

# 目的
- AMD CPU搭載PCでAVDのVMアクセラレーションを有効化する。

# 環境
- PC：Ryzen 5 3400G, ASUS TUF B450M-PLUS GAMING
- OS：Windows10 Professional 21H2
- Android Studio 3.6.3

# 準備

- AMDのCPUでAVDのVMアクセラレーションを有効とするには、以下の条件がある。
  
  * Android SDK Toolsのバージョンが26.1.1以降。
    後述するWindows ハイパーバイザープラットフォーム（WHPX）を使う場合は27.3.1以降。
  * x86ベースのシステムイメージを持つAVD。
  * Windows10 Ver1803以降。
  * 異なるVM（VMware, Virtual Box等）内では有効化できない。VMアクセラレーションを使用するAVDは別のVM内からではなくホストPCから直接実行すること。
  * CPUはRyzen推奨。
- AMD CPU搭載PCの場合、AVDのアクセラレーションを行うには以下2つの選択肢がある。ここでは下記(2)を選択し、(1)については説明しない。
    (1) AVDと同時にHyper-Vを実行する必要がない場合、
        * Android Emulator Hypervisor Driver for AMD Processorsを使う。 
    (2) AVDと同時にHyper-Vを実行する必要がある場合、
        * Windowsハイパーバイザープラットフォーム（WHPX）を使う。

# 作業手順

(1) PCのBIOS（UFEI）でAMD-Vを有効化
個々の環境によるのでPCやマザーボードのマニュアルを参照する。うちの環境では以下の”SVM Mode"を”Enabled"とした。
![211226211756_BIOS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2408239/81f1e0a8-2eee-ddff-629e-4a7b1e7ea861.png)

(2) Hyper-Vとハイパーバイザープラットフォームを有効化する。
タスクバーの検索で「Windowsの機能の有効化または無効化」と入力し、「Windowsの機能」ダイアログを表示後、「Hyper-V」と「Windows ハイパーバイザープラットフォーム」を有効化（チェックボックスをON）する。有効化した後、PCを再起動する。
![WindowsFunctionEnabler.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2408239/af1816f0-84b0-2c0d-c8da-c11ce41db42c.png)

  (3)ハイパーバイザープラットフォームによるアクセラレーション有効化の確認
     - 上記(2)でPC再起動後、アクセラレーションが有効となっているかどうかをエミュレータから確認できる。
     （Android SDKのインストールフォルダ）/emulatorフォルダ以下にあるemulator.exeからAVDを "-avd" オプションで指定して実行する。"Windows Hypervisor Platform accelerator is operational." と表示されればアクセラレーションは有効化されている。
![whpx_running_check.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2408239/ac17a922-d9eb-7ac6-400c-7630f875c7b1.png)

# その他
- コマンドラインによるアクセラレーション有効化は確認できたものの、アクセラレーションの効果（どれくらい速くなったか）は未検証。
- Android Emulator Hypervisor Driver for AMD ProcessorsとWHPXを同時に有効にした場合、次回のシャットダウンまたは起動時に前者のドライバが自動的にアンインストールされるっぽい。時間がかかるので間違えて両方ともインストールしないこと。

# 参考

- [Windows で VM アクセラレーションを設定する](https://developer.android.com/studio/run/emulator-acceleration?hl=ja#accel-vm)
  
- [Windows Hypervisor PlatformによるアクセラレーションでAVDを動かす](https://qiita.com/keicha_hrs/items/455ee2f2cef36e9c6e1c)


# 変更履歴
- 2022/1/1 初版
Symbolブロックチェーンで自分のアカウントへの署名要求を検知する

Symbolブロックチェーンで自分に宛てらてたアグリゲートボンデッドトランザクションを検知する方法を紹介します。

:::note
Symbolはブロックチェーンに詳しくない他分野のスペシャリストでもローコード/ノーコードでセキュアかつデプロイレスなスマートコントラクトを記述できるブロックチェーンとして日本のエンジニアや研究者からも非常に注目される存在となり、いまでは元イーサリアムのプロトコルの改善提案者がコアチームに無報酬で参入するなどプラットフォームとしてその可能性を期待されています。
:::

今回紹介する方法は、アプリ初期表示時の検知とアプリ起動中のリスナー検知の２種類に対応します。つまり、アプリを起動したときにすでに承認待ち状態であるトランザクションと、アプリ起動中に新規に発生した承認を要求するトランザクションを検知することで、すべてのトランザクションを検知対象とすることができます。また、承認待ちが複数人いる場合は自分が署名してもステータスとしては署名待ち状態となり、アプリを再起動するたびに検知してしまいます。すでに署名したトランザクションや、自分が署名する必要のないトランザクションには反応しないようにすることも重要です。

これらはWebSocketを利用してブロックチェーンの状態を確認するための重要なノウハウになりますので、ぜひマスターしておいてください。



# 検知対象アカウントの準備

```js
alice = sym.PublicAccount.createFromPublicKey(
"" ,
networkType
);
```

すでに署名済みであるかどうかを調べるため、公開鍵からパブリックアカウントクラスを生成します。

# 通知ロジック

```js
//アグリゲートトランザクション検知
bondedListener = listener.aggregateBondedAdded(alice.address);
bondedHttp = txRepo.search({
	address:alice.address,
	group:sym.TransactionGroup.Partial
})
.pipe(
	op.delay(2000),
	op.mergeMap(page => page.data)
);

bondedSubscribe = function(observer){
	observer.pipe(

		//すでに署名済みでない場合
		op.filter(_ => {
			return !_.signedByAccount(alice.publicKey);
		})
	).subscribe(_=>{

		txRepo.getTransactionsById(
			[_.transactionInfo.hash],
			sym.TransactionGroup.Partial
		)
		.pipe(
			op.filter(aggTx => aggTx.length > 0)
		)
		.subscribe(aggTx =>{

			//インナートランザクションの署名者に自分が指定されている場合
			if(
				aggTx[0].innerTransactions.find((inTx) 
				=> inTx.signer.equals(alice.publicAccount))!= undefined
			){
				//ここに通知ロジックを記述
			}
		});
	});
}

bondedSubscribe(bondedListener);
bondedSubscribe(bondedHttp);

```

### 解説

##### リスナー検知

```js
bondedListener = listener.aggregateBondedAdded(alice.address);
```

リスナークラスから、ボンデッドトランザクションが追加されたイベントを取得します。

##### 起動時検知

```js
bondedHttp = txRepo.search({
    address:alice.address,
    group:sym.TransactionGroup.Partial
})
.pipe(
    op.delay(2000),
    op.mergeMap(page => page.data)
);
```

対象アドレスのパーシャルトランザクションの存在調べます。
delayにしているのはアプリの他の描画と時間差をつけたいためで、特に必要ではありません。
情報が取得できた場合、ページングされているのでmereMapで中身を取り出します。

##### 証明済み？

上記二種類の検索結果は以下のファンクションに流し込まれます。


```js
bondedSubscribe = function(observer){
    observer.pipe(

        //すでに署名済みでない場合
        op.filter(_ => {
            return !_.signedByAccount(alice.publicKey);
        })
    ).subscribe(_=>{
```

パーシャルTXは既に署名している可能性もあるため、signedByAccountで検査します。

##### トランザクション全体の取得と内容の検査

```js
        txRepo.getTransactionsById(
            [_.transactionInfo.hash],
            sym.TransactionGroup.Partial
        )
        .pipe(
            op.filter(aggTx => aggTx.length > 0)
        )
```

まだ自分が署名していないとわかったら、TX全体を取得します。
これはリスナーイベントで取得した情報にはアグリゲートトランザクションの内部リスト（インナートランザクション）が含まれていない場合があるからです。

##### 署名者に自分が指定されているかチェック

```js
            //インナートランザクションの署名者に自分が指定されている場合
            if(
                aggTx[0].innerTransactions.find((inTx) 
                => inTx.signer.equals(alice.publicAccount))!= undefined
            ){
                //ここに通知ロジックを記述
            }
```

最後のチェックです。
パーシャルトランザクションは自分が送信者である場合も情報が取れてしまいます。
その情報が必要な場合もありますが、今回は署名要求の検知ですので取れない方がいいです。
なので、find関数でリスト内のsignerに自分の公開鍵が指定されているかどうかを調べます。


これで通知ロジックが完成しました。
ぜひお試しください。
個人的備忘録＠その１

個人的備忘録＠その１


問題文
あなたはYuki小学校1年1組の担任であり, 算数のテストの採点をしている。そのテストにはA+Bを計算する問題がある。今、 あなたが採点しようとしている答案にはこの問題に対する答えとしてCが書いてあった。では,この解答は正しいか？

＃制約
0<A,B<100
0<C<200
入力はすべて整数である

＃入力
入力は以下の形式で標準入力から与えられる.
ABC
＃出力
答案が正しければCorrect,間違っていればIncorrectと出力せよ。ただし,最後に改行すること。


＃サンプル
３　５　８
（３＋５＝８なのでCorrect）
４　１　７
（４＋１＝７は成立しないためIncorrect）






自分の書いたコードが下記
import java.util.Scanner;

class Code{
    public static void main(String[]args){
        //1249
        System.out.print("数値を入力してください\n");

        Scanner scanner = new Scanner(System.in);

        int a = scanner.nextInt();
        int b = scanner.nextInt();
        int c = scanner.nextInt();
        
        scanner.close();

        if(a + b == c){
            System.out.print("Correct");
        }else{
            System.out.print("Incorrect");
        }
    }
}




なんか初心者丸出し感（笑）
Django admin.pyファイルの役割

## Django admin.pyファイルの役割とは

admin.pyの使用目的の理解が曖昧だったので、メモとして書いておきます。

アプリで作成したデータベーステーブルを管理画面に表示させるために、admin.pyファイルを使います。

```python:admin.py
# modelをimport
from .models import SampleModel

# modelを追加
admin.site.register(SampleModel)
```
admin.pyファイルにモデルを追加することで、Djangoの管理画面がそのモデルを認識できるようになるということです。
エンジニアともあろうものが、如何に正月を過ごすのか？

　まず、この記事を読む前に、単なる年寄りのたわごとと思って頂いていい。（そうでないと、時間を割いてもらうのが勿体ないので）かつ、この記事が何らかの結論に達することも、期待しないでもらいたい。（何故かというと、自分でもポエムの終着点が読めないので）しかし、なぜここ（Qiita）に書いているのか？（あえて、それは聞かないでほしいけど、何らかのオーディエンスがいると期待しているからで、無駄な書き込みを辞めろとサイト側から指摘が無い限りは、一旦ここに書くことにする）
# 正月を迎えて
　年末から薄々感じていることだが、少し2021を境に世の中が変わってきたように感じている。
もちろん、年末に楽しみにしていた、ダウンタウンの番組も無くなり、紅白歌合戦の会場には、嵐のメンバーを見かけなくなった（司会は二期目になった大泉洋であるが、気づくとテレビの雰囲気も何か違う）。何というか、オリンピックも終わり、菅政権も変わり、眞子さまも結婚して海外に行き、夏目さんは引退し、テレビを通じて知りえる日本というのは、このコロナ禍で大きく変わってしまったような気がする。（それも、コロナの一波、二波と言うような、二、三カ月の波と言うよりは、もっと大きな２，３年と言うような周期の波が、やってきたように感じてしまう）
　2021年を振り返ってみても、世の中がリモートワークや、企業のＤＸ推進などの流れで、若者の付きたい職業がＩＴエンジニア、プログラマという話題の割には、テレビのエンターテインメントには、そのような流れを感じず、相変わらず年末にはＭ１グランプリでアナログな芸人の競い合いを見せつけられている。社会の娯楽がテレビから、ＳＮＳやＹＯＵＴＵＢＥに変わりつつある中で、どうもテレビを通じて見ている世界だけが、何となく取り残されているような気がしてならない。
# ＩＴエンジニアとして
　ＩＴエンジニアたるもの、まさかテレビ番組に一喜一憂して、ぼうっと過ごしている訳にはいかない。（何故かというと、これからの世の中に未来を託す若者たちの夢が、いわゆる我々のＩＴワーカーにかかっているのであれば、我々自身が少なくとも、世間に失望を抱いている人たちと、同じ立ち位置にいてはならないから）
　少なくとも、12/31の夜には、時差の異なる海外の人たちと、リポジトリを共有し、オンラインで全世界のNEWYEARを祝う、そんな先の世の中を真っ先に描かないといけないのであるから。。。
　故に、私自身も正月が来たといえど、ブログには自分の意見を書きつつ、そして2022年の目標もきちんと自分の言葉で発信していく、そんな正月の過ごし方をすべきと思う。
# 今年の予想
　少なくとも2022年は芸能界は確実に衰退する（場合によっては放送業界は確実にインターネットビジネスに参入する）。そして確実にYOUTUBEが重要なインフラに格上げする（少なくとも自身の周りの高齢者は、テレビよりもYOUTUBEが面白いと言っている）。企業のＩＴ教育がさらに進む。学校教育もＩＴエンジニア育成の方向に向かう。ＩＴ以外の業種人口が確実に減り、ＩＯＴやロボット、ＡＩに置き換わる。つらつら、こんなことを書いているが、年末年始の過ごし方も変わっていく。そして紙の年賀状は出さなくなる。
# 自分の持つべきスキルセット
　やはりこれからは、国際コミュニケーション力だと思う。結局はＩＴエンジニアの源流は、如何にグローバルに活動が出来るかと言うことと、同じ位置づけにあると考える。つまりは、英語、中国語、韓国語などの多言語理解が、ますます重要になってくる。そのうちに日本のテレビ番組を見ずに、衛星放送で異国の新年を祝うぐらいの楽しみが妥当な世の中になる。
　正月のテレビが面白くなくなったときは、ＩＴエンジニアはもっと世界に羽ばたくべきと思う。
C#er、Delphiを学ぶ①（Windows10でAirPodsにつなぐ）

# エンプラ系エンジニアの地獄
一週間前、Delphiで開発するアプリのプロジェクトにアサインされた。私はC#erにもかかわらず。大規模な法改正により人月が足りないそう泣

# 年末年始でDelphiを学ぶことに...
むかし、Delphiで簡単なiOSアプリを作ったのだが、文法とかとかが古めかしかったのをおぼえている。年の瀬にあらためて学んでみるとやっぱり書きづらい。とはいえ、Delphiにもいい点があると思っている。ネイティブに近いため、C#より速く動くし、WindowsのAPIと親和性が高いイメージがある。まずは軽いアプリを作って勉強したいなーと思った。

# AirPodsをツールから接続するアプリを作成することに
業務中のWEB会議ではもっぱらAirPodsをイヤホンとして使っています。自動的に接続されないため、Windowsの設定画面から手動でつなぐ必要があるのです。これがまたダルいのでツール叩けばつながる感じのアプリを作ろうって算段です★

# 全体像
- ペアリングされたデバイス(AirPods)を取得
- Bluetoothとのコネクションを作成
- BluetoothのサービスのUUIDを探す
- デバイス(AirPods)と接続

# ペアリングされたデバイス(AirPods)を取得
↓みたいな感じで実装。引数には「AirPods」を指定すればOKかと。

```pascal
function TBluetoothGetter.FindAirPodsDevice(ADeviceName: string)
  : TBluetoothDevice;
var
  BluetoothManager: TBluetoothManager;
  BluetoothAdapter: TBluetoothAdapter;
  BluetoothDeviceObj: TObject;
  BluetoothDevice: TBluetoothDevice;
begin
  BluetoothManager := TBluetoothManager.Current;
  BluetoothAdapter := BluetoothManager.CurrentAdapter;

  for BluetoothDeviceObj in BluetoothAdapter.PairedDevices do begin
    BluetoothDevice := BluetoothDeviceObj as TBluetoothDevice;

    if BluetoothDevice.DeviceName.Contains(ADeviceName) then begin
      Result := BluetoothDevice;
    end;
  end;
end;
```

# Bluetoothとのコネクションを作成
↑で取得したデバイス(TBluetoothDevice)のCreateClientSocket関数を使えばOKっぽいが、第一引数のUUIDが分からんかった。調べてもいまいち的を射た答えがない。**つーかBluetoothって何？**
どうやら、BluetoothのサービスのUUID？を入力すればOKっぽいので自力で探す旅に。

# BluetoothのサービスのUUIDを探す
TBluetoothDeviceにGetServices関数が入っていたので、この中のUUIDを使えばいいと予想。まずは全部リストアップし、対象のUUIDを探す。

```pascal
procedure TBluetoothGetter.ListupBluetoothServiceUUID;
var
  BluetoothDevice: TBluetoothDevice;
  BluetoothService: TBluetoothService;
begin
  BluetoothDevice := FindAirPodsDevice('AirPods');
  if BluetoothDevice = nil then begin
    raise Exception.Create('デバイスが見つかりませんでした。');
  end;

  for BluetoothService in BluetoothDevice.GetServices() do begin
    Writeln('Name:' + BluetoothService.Name + '  ' + 'UUID:' +
      BluetoothService.UUID.ToString);
  end;
end;
```

# デバイス(AirPods)と接続
↑で取得したGUIDを元にSocketを開き、Connect関数を呼ぶ。すると、なんとAirPodsにつながりました。ただ、EBluetoothSocketExceptionが出てきたため、こいつは無視するようにします。

```pascal
procedure TBluetoothGetter.Connect();
var
  BluetoothDevice: TBluetoothDevice;
  BluetoothSocket: TBluetoothSocket;
begin
  BluetoothDevice := FindAirPodsDevice('AirPods');
  if BluetoothDevice = nil then begin
    raise Exception.Create('デバイスが見つかりませんでした。');
  end;

  BluetoothSocket := BluetoothDevice.CreateClientSocket
    (BluetoothServiceUUID, True);
  try
    BluetoothSocket.Connect;
  except
    on E: EBluetoothSocketException do begin
    end;
  end;
end;
```
# 成果物
https://gist.github.com/ryotuxtuki/4c556886c49127afdb49b8cc8cb74009

# 参考にしたURL
- https://docwiki.embarcadero.com/RADStudio/Sydney/en/Using_Classic_Bluetooth
- http://izawa-web.com/bt60/bt60delphi.html
- https://note.com/liuk_net/n/nc25a4b5cf2a4

# 最後に
- Delphi、サンプル少ないよぉ...
    - Bluetoothもとい、DDDのサンプルコードとかほとんどない。
- 学習のハードル高くないかえ...
    - type,interface,implementationとかとか、おまじないを覚えるのが大変
- Bluetoothの実装は楽だった(と思う)
    - 最初はC#で実装しようとしたが、WinRTがどうのこうのと、ConsoleAppで作んのがダルそうだった。
    - DelphiならSystem.BluetoothをusesすればOKなのでよきよき
【Python】ダミーデータ作成【Faker】

テスト等で使用するダーミーデータ作成ができる**Faker**について紹介します。

# 使用準備
pipでFakerをインストールします。

```
pip install faker
```

# 実装
## ダミーデータの作成
``` python
from faker import Faker
fakegen = Faker('ja_JP')
name = fakegen.name() #名前
```

Fakerはロケールを設定できます。
日本語を使用したい時は`Faker('ja_JP')`を設定します。
英語を使用したい時は、`Faker('en')`を設定します。

他言語も設定できます。
詳しくはこちら↓

https://faker.readthedocs.io/en/master/locales.html

### 作成可能な項目
作成可能な項目はこちら↓に分かりやすくまとめてあります。

https://qiita.com/nandymak/items/1ab36e3d5365e8ca2942#%E6%8C%87%E5%AE%9A%E3%81%A7%E3%81%8D%E3%82%8B%E9%A0%85%E7%9B%AE

#### 乱数の生成
乱数の生成はFakerではなくNumpyから生成できます。

``` python
import numpy as np
np.random.randint(0,100)
```

### 作成オプション
#### 文字列の長さ
文字列の長さを制限するには`max_nb_chars`を引数に設定します。
40文字以下の文字列を作成するには↓のように設定します。

``` python
text = fakegen.text(max_nb_chars=40)
```

#### 選択肢を指定し、ランダムに生成
↓のようにあらかじめ設定した選択肢からランダムに生成できます。

* 性別
    * 男
    * 女
* プログラミング言語
    * python
    * php
    * java
    * html

`ext_word_list`を設定することでそのリストから生成するように制限できます。

``` python
fakegen.word(ext_word_list=['男', '女'])
fakegen.word(ext_word_list=['python', 'php', 'java', 'html'])
```

#### 重複なし
重複なしのデータを作成する場合は、`unique`を項目名の前につけます。

```python
city = fakegen.unique.city()
```

当然ですが、
uniqueオプションは、大量にデータ生成をすると`UniquenessException`というExceptionを吐きます。
ユニークな値が尽きたことを意味します。

適当なタイミングで下記コードを差し込むと、`UniquenessException`が回避できます。
が、重複する値が存在する結果が出力されます。

```python
fakegen.unique.clear()
```

## エクセル化
エクセルまたはcsvにしたい時はデータをDataFrame化します。

``` python
faker_list = []
# データを100個作成する
for i in range(100):
    dataList = []

    name = fakegen.name()
    dataList.append(name)

# データフレーム化
df = pd.DataFrame(faker_list)
df.to_excel('../test.xlsx', index=False, header=False)
```
Rocky Linux 8.5 に MariaDB Community Server 10.6 をインストール

CentOS 8 が 2021-12-31 で EOL(End of Life) となりました。

https://www.centos.org/centos-linux-eol/

Rocky Linux 8 に MariaDB Community Server 最新版をインストールしてみます。


# Rocky Linux 8.5 をダウンロード

https://rockylinux.org/download/ から x86_64 用 ブート可能イメージ( https://download.rockylinux.org/pub/rocky/8/isos/x86_64/Rocky-8.5-x86_64-boot.iso )をダウンロードし，VMware 上でブートします。

# yum レポジトリ設定

以下のワンライナーを実行し，yum レポジトリを設定します。

```sh
curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash
```

バージョン指定をしないと， バージョン 10.6 のレポジトリが設定されます。他のバージョンを利用する場合は mariadb_repo_setup のオプションで ```--mariadb-server-version``` でバージョン指定するか，mariadb.repo の baseurl の 10.6 を他のバージョン番号で置換します。

```/etc/yum.repos.d/mariadb.repo
[mariadb-main]
name = MariaDB Server
baseurl = https://dlm.mariadb.com/repo/mariadb-server/10.6/yum/rhel/8/x86_64
gpgkey = file:///etc/pki/rpm-gpg/MariaDB-Server-GPG-KEY
gpgcheck = 1
enabled = 1
module_hotfixes = 1

[mariadb-maxscale]
name = MariaDB MaxScale
baseurl = https://dlm.mariadb.com/repo/maxscale/latest/yum/rhel/8/x86_64
gpgkey = file:///etc/pki/rpm-gpg/MariaDB-MaxScale-GPG-KEY
gpgcheck = 1
enabled = 1

[mariadb-tools]
name = MariaDB Tools
baseurl = https://downloads.mariadb.com/Tools/rhel/8/x86_64
gpgkey = file:///etc/pki/rpm-gpg/MariaDB-Enterprise-GPG-KEY
gpgcheck = 1
enabled = 1
```

https://mariadb.com/docs/deploy/topologies/single-node/community-server-10-6/

# MariaDB Community Server 10.6 のインストール

今回は最新版の 10.6 をインストールしますので，そのまま ```MariaDB-server``` をインストールします。

```
dnf -y install MariaDB-server
```

# MariaDB Monitor の実行

最近のバージョンの MariaDB では，mysql コマンドでなく，mariadb コマンドで MariaDB monitor を起動できます。

```sh
$ sudo mariadb
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 10.6.5-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>
```

2022-01-01 時点で，10.6.5 がインストールされました。

なお，下方互換性のために，mysql コマンドは /usr/bin/mariadb へのシンボリックリンクとなっています。

```
$ ls -l /usr/bin/mysql
lrwxrwxrwx. 1 root root 7 Nov  6 06:41 /usr/bin/mysql -> mariadb
```