OmniAICreator/Qiita-1.07M huggingface dataset:
PHP URLパラメータ,GET,POSTについてまとめてみた。

# はじめに
**・前提知識として、httpプロトコルがわかる方。**
**・URLパラメータ,GET,POSTについて、よくわからない方。**
**・Web系に関する知識に興味がある方。**



## URLパラメータ
**・サーバーに情報をおくるために用意する、
　URLの文末に渡す値(変数)などのこと。**
　(クエリ文字列ともよ呼ぶ)
※URLの末尾に『?』を追加しその後に、『パラメータ(値)』
　『URL』+『？』+『パラメータ』

######サンプルコード (aタグを利用して表現)
```php:query.php

<?php 

// 『?』　以降がURLパラメータ
echo '<a href="queryGet.php?valueGet=これはパラメータです">GET</a>';

 ?>
```



## GET
**・httpプロトコルのメソッドの1つ。
　リクエストする情報をURLパラメータで付与する通信方式。**

※GETで送信した値を取得するには**$_GET**を使用。
　$_GETは**連想配列**として値が格納される。

######サンプルコード
```php:query.php

<?php 

// 『?』　以降がURLパラメータ (URLパラメータを付与したので、GETされる)
echo '<a href="queryGet.php?valueGet=これはパラメータです">リンク</a>'; 

 ?>
```


```php:queryGet.php

<?php

// // GETで送信された値を取得し、配列として格納される
echo $_GET['valueGet'];
echo '<br>';

// $_GETが連想配列であるかの確認
 echo gettype($_GET);

 ?>
```
###### 実行結果


**・query.php**
![スクリーンショット 2021-02-26 17.56.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1110232/014ade7b-aa4f-69fc-34be-d67db2b54b95.png)
--- 


**・queryGet.php**

![スクリーンショット 2021-02-26 16.33.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1110232/73993eba-72cc-b513-3fcc-e8fa5f8e8b3c.png)
---





## POST
**・GET同様、httpプロトコルのメソッドの1つ。
　メッセージボディに入力した値を付与する通信方式。**

※フォームから入力された値などが該当する。
　POSTで送信した値を取得するには**$_POST**を使用。
　$_POSTは＄_GETと同様、
　**連想配列**として値が格納される。

######サンプルコード
```php:formPost.php

<form action = "formPost.php" method = "post">
	<br>
	<input type="text" name="valuePost">
	<input type="submit" value="送信">
</form>

```


```php:formPost.php
<?php

// POSTで送信された値を取得し、連想配列として格納される
echo $_POST['valuePost'];
echo '<br>';

// $_POSTが配列であるかの確認
echo gettype($_POST);

 ?>
```


###### 実行結果


**・form.php**

![スクリーンショット 2021-02-26 17.53.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1110232/abb18a76-510c-4b9f-9a12-f50aba4a7921.png)

---


**・formPost.php**
![スクリーンショット 2021-02-26 17.54.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1110232/72484e09-5f58-4d01-4b0e-14d5acbf5a98.png)
---

## まとめ

**・GET,POST↓
　httpプロトコルのメソッド。**

**・GET↓
　URLパラメータを付与して通信。**

**・POST↓
　フォームなどを利用してデータを付与して通信。**

**・＄_GET↓
　GETで送信したデータを取得するために使用。**

**・＄_POST↓
　POSTで送信したデータを取得するために使用。**

######※余談
**・GETはURLに直接付与するので目で見えてしまう。**
　以下のように↓
![スクリーンショット 2021-02-26 18.29.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1110232/90409e32-505a-df6b-f11b-a9aac5e81000.png)

このような理由から、
**機密性の高い情報はGETを使用することは推奨されていません。**

**・POSTはメッセージボディに値を付与するため、
　上記の画像のように確認はできない**


※しかし、通信を盗聴されたら見れるため
　セキュリティには注意が必要。
PowerBI DAX 自前サンプルと疑問

#メジャーによる自動採番

```:DAX
id =
RANKX (
    ALLSELECTED ( 'TABLE' ),
    CALCULATE ( FIRSTNONBLANK ( 'TABLE'[colum], 'TABLE'[colum] ) ),
    ,
    ASC,
    DENSE
)
```

#移動平均値

本当は、VAR interval = -365 をスライサーから変更できるようにしたいがやり方が全くわからない

```:DAX
moving average = 
VAR interval = -365
RETURN
CALCULATE(
    SUMX('TABLE', 'TABLE'[amount]) / DISTINCTCOUNT('TABLE'[date]),
    DATESINPERIOD(
        'TABLE'[date],
        LASTDATE('TABLE'[date])-1,
        interval,
        DAY
    )
)
```


#昨年同月比

```:DAX
YoY_amount =
CALCULATE ( SUM ( 'TABLE'[amount] ), SAMEPERIODLASTYEAR ( [Date] ) )
```

```:DAX
昨年同月比 = [amount] / [YoY_amount]
```

#ピボット解除

```:DAX
/*ピボット解除を実施*/
table for matrix = 
	UNION(
		SELECTCOLUMNS(TABLE_NAME, "日付", TABLE_NAME[Date],CLASS, "Filed1", VALUE, TABLE_NAME[Filed1]),
		SELECTCOLUMNS(TABLE_NAME, "日付", TABLE_NAME[Date],CLASS, "Filed2", VALUE, TABLE_NAME[Filed2]),
		SELECTCOLUMNS(TABLE_NAME, "日付", TABLE_NAME[Date],CLASS, "Filed3", VALUE, TABLE_NAME[Filed3]),
		︙
		SELECTCOLUMNS(TABLE_NAME, "日付", TABLE_NAME[Date],CLASS, "Filed10", VALUE, TABLE_NAME[Filed10])
	)
```



すごいのを見つけました
https://modernexcel7.hatenablog.com/entry/2020/07/21/232836
javascriptでsetAttributeメソッドが発動しているか判定する

# 目的
　以下のようなマス目を、出た目に応じて赤く点灯させる。

| 1 | 2 | 3 | 4 | 5 |
|:-:|:-:|:-:|:-:|:-:|

　１列全て点灯した時点でビンゴとする。

　そのため、特定のマス目が点灯していることを判別したい。

# (1) マス目の要素を取得する
```app.js
const boxNumbers = document.getElementsByName('box')
```
　各マス目のname属性から複数の要素を配列として取得する。
# (2) これを赤く点灯させる
```app.js
boxNumbers[sheetNumbersIndex].setAttribute("style", "background-color:#ff0000;")
```
  　style属性に、赤色の背景色という値を追加
# (3) 当該マス目でイベント発火が生じているか判別
　　点灯前と点灯後の違いをコンソールで調査する

```console.log(boxNumbers[0].style)
点灯前
CSSStyleDeclaration {alignContent: "", alignItems: "", alignSelf: "", alignmentBaseline: "", all: "", …}
点灯後
CSSStyleDeclaration {0: "background-color", alignContent: "", alignItems: "", alignSelf: "", alignmentBaseline: "", all: "", …}
```
　どうやら、boxNumbers[0].styleの中身を見ると、点灯後は、`キー０、値"background-color"`という要素が追加されるらしい。
　

# 結論　
　というわけで、`boxNumbers[0].style[0]`の存在の有無で判別できました。

```app.js
if(boxNumbers[0].style[0])
//点灯前はfalse,点灯後はtrueが返る
```
ロータリーエンコーダのパルスをESP32で読む

※詳細は後日追記するかも。

ロータリーエンコーダのパルスはESP32で無事よめた。コネクタに出てるGPIOがOLEDのI2Cと共通だったので、OLEDを殺す(=初期設定コードをコメントアウト)必要があった。

使用ボード(IO21/22をA相/B相に接続)→
https://amzn.to/3qXEP2W

Special Thanks to ...

https://qiita.com/bleach31/items/256229d006e0b3134341

https://github.com/lewisxhe/esp32-camera-series.git

↑この２つのスケッチを合わせこむ感じで改造しました。
【エラー】-bash: rustc: command not found

# 事象

[The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/ch01-01-installation.html) に従い、記載されているコマンドでLinuxにRustをインストールをした。

> インストールがうまく行けば、以下の行が出現するでしょう:

> ```
> Rust is installed now. Great!
> ```

この行が表示されていることを確認。
しかし、Rustが正常にインストールされているか確かめようとしたところ、下記のエラー。

```
~$ rustc --version
-bash: rustc: command not found
```

# 対処法：ターミナル再起動

一度ターミナルを閉じてから再び開き、再度実行したところ、エラーが解消していた。

```
~$ rustc --version
rustc 1.50.0 (cb75ad5db 2021-02-10)
```

# 原因

コマンドにパスが通っていなかった。
インストール時のメッセージを見てみると、確かに

```
Rust is installed now. Great!

To get started you need Cargo's bin directory ($HOME/.cargo/bin) in your PATH
environment variable. Next time you log in this will be done
automatically.
```

とある。

インストール時にホームディレクトリの`.bashrc`が書き換わっていたので、反映させるために再起動が必要だった。

# 追記

再起動の代わりに `source $HOME/.cargo/env` コマンド実行でもいいらしい。
並列計算したいので，numpyレベルでの並列処理を制限したい．


上のレベル（遺伝的アルゴリズムなどの並列化できるアルゴリズムの実行）で並列計算をするので，下のレベル（行列計算時など）でnumpyが自動的に行っているマルチスレッド処理を止める必要がでてきたので方法を調べましたが結構時間を費やしてしまったので，メモを共有しておきます． Visual Studio Code から実行することを想定しています． (デバッグ機能によるか，jupyterインタラクティブ環境を使うかのどちらか)

LinuxかMac環境で試しており，Windows環境は試していません．

### なぜ制限が必要か
コア数32のマシンで並列計算をしたいとします．
一度に30個のプロセスをたててそれらを並列計算にしたいとき，それぞれのプロセスの計算の中でnumpyが自動的に並列計算を行ってしまうと，３０プロセスそれぞれが32スレッドの計算をするということが起こり，計30*32=960のスレッドが走ってしまい，コア数の32を大きく超えるため，オーバーヘッドにより計算効率が落ちます．これを防ぐため，下位のnumpyのレベルでのマルチスレッド数を制限しておく必要があります．

### わかったこと

####numpyといってもどのライブラリを使って並列化しているかは場合により異なる

osの違いやcondaやpipでどこからとってきたか等により，numpyがどの並列ライブラリを使っているかは異なるようです．openblas, mkl, openmp, veclib などの種類があるようです．
どのライブラリを使ってるか調べるには，

```python
print(np.__config__.blas_opt_info['libraries'])
```
とかで確認できるようです．
参考
https://sgryjp.gitlab.io/posts/2020/2020-09-20/

#### 並列化を制限するには，多くの場合環境変数を設定する必要がある

一部のライブラリの場合，コードの中でもスレッドを制限することができますが，多くの場合環境変数で並列のスレッド数を設定することができるようです．


#### vscodeからの実行時に環境変数を設定するには，ワークスペース上に`.env` ファイルを置いておき，そこに環境変数を書き込んでおけば良い．

vscodeからプログラムを動かす場合，プログラムに環境変数を伝えておく必要があります．
`.env`というファイルをワークスペース（多くの場合ファイルがおいてあるフォルダ）に置いて，中に環境変数の設定を書いておけば，vscodeは実行前にこれを読み込み，制限をかけることができるようになります．vscodeのjupyterのインタラクティブ環境を利用してプログラムを動かす場合や，F5で走るデバッグ機能を利用するときは，これでいけます．ただし，再生ボタンのマークをクリックしてRun Python File in Terminal として動かす場合は，このファイルを読み込んでないようです．

公式 https://code.visualstudio.com/docs/python/environments#_environment-variable-definitions-file

#### .envファイルの設定例

ひとつの環境で利用する場合，下記すべて設定する必要はないですが，一応書いておきます．

```bash:.env
OPENBLAS_NUM_THREADS=1
MKL_NUM_THREADS=1
OMP_NUM_THREADS=1
VECLIB_NUM_THREADS=1
NUMEXPR_NUM_THREADS=1

```

### プログラム

２０の並列プロセスを使い，4０個の2000x2000行列の固有値を計算する例です．

```python:multi_example.py
import numpy as np
import time
from multiprocessing import Pool

#%%

def eigs(X):
    # 並列処理する関数．固有値を計算する    
    print(f'X.shape={X.shape}')
    ret = np.linalg.eig(X)
    print('done')
    return(ret)

if __name__ == "__main__":
    p = Pool(20)

    matrices = np.random.rand(40,2000,2000)
    time_start = time.time()    
    result = p.map(eigs, matrices)
    print('elapsed time:{}'.format(time.time()-time_start))
    p.close()
```

実行中に別のターミナルで`top`をみて，プロセスのCPU利用率が100%を超えていなかったり，`load`がとんでもない値になっていなければ，制限をかけることは成功しています．

###ターミナルからの実行

ターミナルからの実行の場合，必要な環境変数のexportを行って

```sh
 export OPENBLAS_NUM_THREADS=1
```

から実行するか，

```sh
python multi_example.py
```

実行時に渡します．

```sh
OPENBLAS_NUM_THREADS=1 python multi_example.py
```
コマンドラインでネットから ino ファイルをダウンロードして置換して Arduino ボードに書き込みをする

コマンドラインでネットから ino ファイルをダウンロードして置換して Arduino ボードに書き込みをします。

まずは前提条件として、arduino-cli のインストールが必要になります。

```bash
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh ;
sudo cp ~/bin/arduino-cli /usr/local/bin/arduino-cli ;
```

次に php などからも arduino の USB シリアルポートにアクセスができるように権限を変更します。

```bash
sudo chmod 777 /dev/ttyUSB0 ;
```

アップロード用の置換前の arduino のスケッチファイル。LED が 0.1秒ごとにチカチカします。

```c:led_100.ino
void setup() {
    pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(100);
    digitalWrite(LED_BUILTIN, LOW);
    delay(100);
}
```

これを 3秒ごとにチカチカするようにPHPで変更してコマンドラインでアップロードをします。

```php:index.php
<?php

$url_ino      = "led_100.ino"; // or http://hogehoge.github/hoge.ino
$replace_from = array("100");
$replace_to   = array("3000");

//system( "ls /dev/ttyUSB*");

$project_name     = basename($url_ino, ".ino");
$project_name_ino = "{$project_name}/{$project_name}.ino";

//
@chmod( $project_name , 0777 );
@mkdir( $project_name );
@chmod( $project_name , 0777 );

$page_ino          = file_get_contents( $url_ino );
$page_ino_replaced = str_replace( $replace_from , $replace_to , $page_ino );

//
@chmod( $project_name_ino , 0777 );
file_put_contents( $project_name_ino , $page_ino_replaced );
@chmod( $project_name_ino , 0777 );

// sudo cp ~/bin/arduino-cli /usr/local/bin/arduino-cli
// sudo chmod 777 /dev/ttyUSB0

# compile and update
$cmd_compile = "arduino-cli compile --fqbn arduino:avr:nano {$project_name_ino}";
system( $cmd_compile );

$cmd_upload = "arduino-cli upload -p /dev/ttyUSB0 -b arduino:avr:nano:cpu=atmega328old {$project_name}";
system( $cmd_upload );
````

実行

````bash
php index.php
````

これで、本来は 0.1秒ごとのチカチカが 3秒ごとのチカチカになっているかと思います。

応用例としては、複数のボードのIPアドレスやMacアドレスの管理、UUIDの指定ができます。
どうしても静的なプロジェクトファイルになりがちなinoファイルを動的に書き換えられるようになるかと思います。

Arduino ってどういうのを書き込んだか忘れるので githubでソースコード、PHP とデータベースで固有番号を付与して管理してもよいでしょう。
AWS障害が起こったときにやること覚書

2/19のAWS障害を受けて、やっておけば良かったことメモ
・対象のAZ確認
　-> アナウンスではap-northeast-1cだけだったが、1a/1dのインスタンスへの疎通も問題なかったか確認すべき

・対象のサービス/インスタンスにsshログインなどし、疎通状況を確認
・アナウンスされている障害範囲以外のサービスに対しても疎通確認を行う (アナウンスよりも影響範囲が広い可能性もある
　-> RDSやElastiCacheなど、EC2以外に利用しているサービスについても疎通確認すべき

・サポートケースを最高優先度で作成
　-> 障害収束後に作成はしたが、障害発生中に作成してサポートを受けるべき

・リアルタイムな障害状況はここで確認
　https://status.aws.amazon.com/#AP_block
【Git】git pullはgit fetchとgit mergeと同じそれは知ってるけど、具体的にはどういうこと？

`git pull` は`git fetch`して`git merge`をするのと同じという話はよく目にする。

しかし、それぞれのコマンドで**オプションや引数が省略された場合にどういった挙動になるのかが曖昧**だったため、それらのコマンドが具体的に何をしているのかを調べてみた。




```
$git pull
```

 ↓ 同じ

```
$git fetch
$git merge
```

##目次

1. [git fetch](#1-git-fetch)
2. [git merge](#2-git-merge)
3. [引数のあるgit pull](#3-引数のあるgit-pull)
4. [よくある使い方](#よくある使い方)



<br>
##1. git fetch
オプションや引数を付けない場合、リモートレポジトリで登録されているoriginにあるすべての追跡ブランチのデータを取得してくる。

つまり、リモートレポジトリとしてoriginが登録されていることが前提となる。


**▼リモートレポジトリ**

```
//登録されているリモートレポジトリの確認
$ git remote 
origin
```

urlを確認したい場合は`git remote -v`で確認できる。


<br>
**▼リモート追跡ブランチ**
リモート追跡ブランチは、`git branch -a`で確認できる。


```
$ git branch -a
* master
  remotes/origin/master
  remotes/origin/aaa
```


上記の状態の場合、`git fetch`を実行すると、origin/masterと、`origin/aaa`からコミット履歴を取得してくる。

コミット履歴が更新されるのは、そのコマンドを実行したブランチではなく、`origin/master`と`origin/aaa`。


###更新されたコミット履歴の確認
リモート追跡ブランチのコミット履歴を確認するには、

・`$ git log origin/<ブランチ名>`を実行すればいい。

`--online`や`--graph`オプションを付ければ見やすく表示できる。



<br>
##2. git merge
オプションや引数を付けない場合、現在のブランチのリモート追跡ブランチをマージする。

もしmasterブランチで`git merge`を実行したのであれば、

```
$ git merge origin master
```

を実行したのと同じになる。


<br>
**※注意点**
master以外の別のブランチにいる場合（例えばブランチaaa）だと、master/masterではなく、そのリモートレポジトリ（origin/aaa）のコミット履歴を統合することになる。

ここが、単なる`git pull`の落とし穴。

自分専用のブランチで作業している場合は、`git pull`したところで何も更新されない。

もし、master以外のブランチで作業していて、リモートレポジトリのマスターのコミットを`git merge`したい場合は、

```
$git pull origin master
```

 ↓ 同じ

```
$git fetch 
$git merge origin master
```

となる。



<br>
##3. 引数のあるgit pull
では、リモートレポジトリとブランチを指定したgit pullはどういった処理になるのか？

```
$ git pull origin aaa
```

 ↓

```
$git fetch origin aaa
$git merge origin aaa
```

git fetchで、指定したリモートレポジトリ(origin)のブランチ(aaa)からデータを取得してくる。

`git merge`で取得してきたコミットを、**コマンドを実行したブランチにマージ**する。


<br>
##よくある使い方
複数人で実施しているプロジェクトでよくある使い方は、自分の作業環境を最新状態に保つために、

自分が**ブランチを切って作業をしている時に、masterの更新情報を取得して定期的にマージ**すること。

コマンドでみると、

```
$ git pull origin master
```

 ↓

```
$git fetch origin master
$git merge origin master
```

を実行していることになる。


<br>
以上。
【AppClips】Provisioning profile "iOS Team Provisioning Profile: Hoge" doesn't support the On Demand Install Capable capability. の対処法

AppClipsを実機ビルドしようとするとこのようなエラーが発生しました。

~~~
Provisioning profile "iOS Team Provisioning Profile: Hoge" doesn't support the On Demand Install Capable capability. 
~~~

![スクリーンショット 2021-02-26 17.31.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678728/1f021551-bd12-7fb1-872a-5947612ecc95.png)

調べてみると同様の症状が発生している人は多く見かけましたが、解決に至っている人を見つけられませんでした。

##解決方法
大前提として**Apple Developer Program**に加入している必要があります。

公式ドキュメントでその様な記述は見つけられませんでしたが、無料アカウントだと実機ビルドでできない様です。

##### 1．まずはじめに、下記リンクよりApp ClipのIdentifierを作成します。

https://developer.apple.com/account/resources/identifiers/list

##### 2．次に画像のような手順で、親アプリのIDを選択し、AppClip用のIDを作成します。

![スクリーンショット 2021-02-26 17.39.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678728/e4b0c003-1735-0984-5f95-c73fe03566ba.png)
![スクリーンショット 2021-02-26 17.40.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678728/ebebce39-d006-ed34-af7f-08913c180bfa.png)

作成する際に、On Demand Install Capableにチェックがついているか確認してください。
![スクリーンショット 2021-02-26 17.56.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678728/bf10d829-1801-6a29-4b84-709af3150501.png)


##### 3．Identifierが作成完了すると、Signingのエラーが消えてビルドできる様になります。
![スクリーンショット 2021-02-26 17.41.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678728/76e46088-0fb6-37b1-1753-de892d2a88e3.png)


##最後に
**Apple Developer Program**に加入していないと実機でのビルドができないので、
AppClipを試そうとしている方は気をつけてください
ではまた👋
Linuxにdockerをワンパンでインストールする方法

# まとめ
Rancherがワンパンでインストールできるスクリプトを提供してくれてる模様

```
curl https://releases.rancher.com/install-docker/<dockerのバージョン>.sh | sh
```
dockerのバージョンは[ここ](https://github.com/docker/docker-ce/releases)で確認
htaccess記述まとめ

基本はレンタルサーバーでの記述

```.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
# ここに記述をする
</IfModule>
```

#リダイレクト

```.htaccess
#特定のディレクトリをリダイレクト
# AAA.com/news/ → AAA.com/product/news/
RewriteRule ^news/$ product/news/ [R=301,L]
```
```.htaccess
#特定のページをリダイレクト
# AAA.com/company/about.html → AAA.com/company/
RewriteRule ^company/about.html$ /company/ [R=301,L]
```

```.htaccess
#パラメーター付きURLをリダイレクト
# AAA.com/news/?item=hoge → AAA.com/news/
RewriteCond %{QUERY_STRING} ^item=hoge$
RewriteRule ^news/$ /news/? [L,R=301]

#パラメーター付きURLをリダイレクト（複数つなげることも可）
# AAA.com/news/?item=hoge → AAA.com/news/
# AAA.com/news/?item=foo → AAA.com/news/
# 複数設定する場合は[OR]を指定
RewriteCond %{QUERY_STRING} ^item=hoge$ [OR]
RewriteCond %{QUERY_STRING} ^item=foo
RewriteRule ^news/$ /news/? [L,R=301]
```

```.htaccess
#パラメーター付きURLをリダイレクト
# AAA.com/news/page/2/?item=hoge → AAA.com/news/
RewriteCond %{QUERY_STRING} ^item=hoge$
RewriteRule ^news/page/([0-9]+)/$ /news/? [L,R=301]
```

「QUERY_STRING」でクエリーを見にいく。
複数指定も可。
Firebase Authenticationのユーザー認証用のIDトークンをコマンド一発で取ってくる方法

Firebase Authentication、便利ですよね。
ログインや認証の機構を丸投げしてるプロダクトも数多くあると思います。

Firebase AuthenticationのIDトークン（JWT）を認証に使ったAPIの開発等でAPIレスポンスの確認をするにあたって、実際のユーザーのIDトークンがすぐにほしいケースが結構あるのですが、
クライアントSDKなしでIDトークンをパッと取得する方法が思いの外わかりにくかったので備忘録的に残しておきます。

※Admin SDKの認証トークンの話ではなく、ユーザー認証用のIDトークンの話です！

## 前提

メールアドレス・パスワードでのログインが出来るユーザーをFirebase Authへ登録しておいて下さい。

![スクリーンショット 2021-02-26 17.17.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129872/51b42ec6-527d-a4c0-e8ae-c4a3d724881a.png)

## コマンド

Firebase Authenticationと互換性のあるGCPのプロダクトであるIdentity PlatformにてREST APIが提供されています。 [^1]
こちらに記載があるのですがひっそりとしていてFirebase Authenticationの文脈で探してると見つけるのが結構難しいです。

https://cloud.google.com/identity-platform/docs/use-rest-api#section-sign-in-email-password

```zsh:Request
curl 'https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=[API_KEY]' \
-H 'Content-Type: application/json' \
--data-binary '{"email":"[user@example.com]","password":"[PASSWORD]","returnSecureToken":true}'
```

`[API_KEY]`にはFirebaseのクライアントアプリセットアップ時にダウンロードした`google-services.json`や`GoogleService-Info.plist`に含まれるAPI_KEYの項目で置き換えて下さい。
`email`と`password`には言わずもがなFirebase Authへ登録したときに用いたものを入力して下さい。

このcurlコマンドを叩くとレスポンス内に`idToken`という項目の入ったjson文字列が返されるので、その文字列がIDトークン（JWT）として使えるのでFirebase Authによる認証付きのAPIへのアクセスもすぐに確認できるはずです。

```json:Response
{
  "localId": "ZY1rJK0eYLg...",
  "email": "[user@example.com]",
  "displayName": "",
  "idToken": "[ID_TOKEN]",
  "registered": true,
  "refreshToken": "[REFRESH_TOKEN]",
  "expiresIn": "3600"
}
```

ちなみにIDトークンの有効期限は1時間なので、期限切れして401が返されるようになってしまったら再度このコマンドを叩いて再取得して下さい。

## おわり

出来るだろうなと思いつつ~~しばらく調べてもわからなくて~~クライアントのアプリを動かしてブレークポイント等を貼ってIDトークンを抜き取ってたりしたのでずいぶん楽になりました。

[^1]: というかこの2つのプロダクトのバックエンドって同一なのでは？
【docker】ローカルサーバーが遅い！快適に開発する方法

#解決方法と原因
原因は、**ローカルホストだと名前解決に時間がかかる事から起こります。**

##ローカルホスト名を確認

```
$ hostname
XXX.local
```

##/etc/hosts の編集する

権限が必要なため、sudoでvimを開いて編集していきます。

```
$ sudo vi /etc/hosts
```

>hosts（ホスツ）ファイルは、ドメインとIPを関連付ける行うファイルです。もう少し詳しく書けば、IPアドレスとホスト名の組み合わせが一覧で記載されているファイルです。

```
127.0.0.1   localhost XXX.local
::1         localhost XXX.local
```

このように編集して終了です。

#参考
[ローカルサーバーのレスポンスが遅いときはホスト名をマップする](https://qiita.com/kaelaela/items/eebfdd33227b26f88d5c)

[【Mac】hostsファイルの場所と変更方法！ターミナルとテキストエディットどちらでも！](https://satopedia.com/mac-hosts/)
[VSCode] LaTeX Workshopの編集画面の波線を非表示にする。

texファイルの編集画面が警告・lintの波線だらけになるのを防ぐ方法を考えた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245977/5938d35d-1c62-7948-32ba-5ab4a279f6d6.png)


プロジェクトかVisual Studio Codeの設定のsettings.jsonのどちらかひとつ以上に、すべてのログのメッセージを無視する項目を追加すればよい。

```
"latex-workshop.message.latexlog.exclude": [".*"]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245977/ac1f32a7-6303-b6a9-b68a-e90dd405bdd0.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245977/6db9f37e-875c-6bee-aff7-7957a1535b40.png)

#Ref
https://texwiki.texjp.org/?Visual%20Studio%20Code%2FLaTeX
ローカルマシンで感情分析

最初はgoogle colaboratryを使っていたのですが、諸事情あってローカルマシンで文章の感情分析をしました。
#環境
Virtual BoxのCentOS7
Python2.7.5
pip 21.0.1
#必要なモジュールをインストール
```
pip3 install urllib3
```
urllibだとインストールできないので注意

```
pip3 bs4
pip3 re
pip3 matplotlib
```
#辞書を作成
emotionsというディレクトリを作成。その下に感情に対する単語が書かれた
辞書を作成。name_uncoded.txtというように作成。

#コード
コードはhttps://qiita.com/e10persona/items/7a7643b266c2bdfbf7d0
を参考にしました。

```
from bs4 import BeautifulSoup
import re
import numpy as np
import matplotlib.pyplot as plt


def get_emotional_words():
    emotions = ["donshoku", "inntou", "kinsenyoku", "ikari", "hitan", "taida", "kyoei", "kouman"]
    emotional_words = {}
    for emotion in emotions:
        emotional_words[emotion] = []
        with open("emotions/" + emotion + "_uncoded.txt", "r") as f:
            for line in f:
                line = line.replace('\n', '')
                emotional_words[emotion].append(line)
    return emotional_words


def count_emotional_words(sentences, emotional_words):
    count_emotions = [0] * len(emotional_words.keys())
    for idx, emotion in enumerate(emotional_words.keys()):
        for word in emotional_words[emotion]:
            count_emotions[idx] += sentences.count(word)
    return count_emotions


def main(url, title):
    sentences = url
    emotional_words = get_emotional_words()
    count_emotions = count_emotional_words(sentences, emotional_words)
    emotional_kanji = ["貪食", "淫蕩", "金銭欲", "怒り", "悲嘆", "怠惰", "虚栄", "高慢"]
    labels = list(emotional_kanji)
    values = count_emotions
    print(labels)
    print(count_emotions)
```

#文章を入力
```
bun = "エロいこと考えてたらお腹が減りました"↲
main(bun, "文章")
```
適当な文章を入力

#分析結果
['貪食','淫蕩','金銭欲','怒り','悲嘆','怠惰','虚栄','高慢']
[19,20,19,19,19,19,0,0]
辞書をちゃんと作り込まなかったので微妙なスコアになりましたが、分析はできました。
<Vagrant+VirtualBox(centos7)>ローカル仮想環境にnginxをインストール起動してみた

#はじめに

バージョンは以下で、挑戦。

```
Vagrant:2.2.14
VirtualBox:Oracle VM VirtualBox Manager 6.1.16
centos:7 2004.01
nginx:1.18.0
```

#1.VagrantでVMware(VirtualBox)を起動
こちらを参考に
[(Vagrant+VirtualBox)ローカルで仮想環境を立ち上げてみる](https://qiita.com/ichi_zamurai/items/7c89fde212a86883d0f0)

仮想環境を立ち上げた。

```bash
vagrant up
```

#2.VirtualBox内にログイン
こちらのコマンドで、仮想環境内にログイン。

```
vagrant ssh
Last login: Fri Feb 26 07:38:33 2021
```

##ハマりポイント
`vagrant up`で起動時に、

```ruby
config.vm.synced_folder ".", "/vagrant",
```
としていると、2回目の起動時に、
仮想サーバー内の`/vagrant/`が上書きされて、sshに必要な`/vagrant/.ssh/`が消されちゃうので、
例えば、**3階層にしておく**といいっぽい。

```ruby
config.vm.synced_folder ".", "/home/vagrant/working_directory",
```

#3.nginxの導入
コマンドはこれ。

```
sudo su -
rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm 
yum install nginx
```
###<解説>
- `sudo su -`：管理者rootにユーザー切り替え。
- `rpm`コマンド：`centos7`に合った`nginx`のパッケージをインストール
    - Red Hat系のLinuxディストリビューションで使われている`RPM（Red Hat Package Manager）パッケージ`を扱うことができるパッケージ管理コマンド
    - `-i`：install
    - `-v`：情報表示を増やす
    - `-h`：インストール時の経過を「#」マークで表示
- `yum`コマンド：yumコマンドでnginx自体をインストール
    - `CentOS`などで使われている「`Yum(Yellowdog Updater Modified)`」というパッケージ管理システム


####rpmとyumの使い分け
CentOSのようにYumに対応している環境なら基本的に`yum`コマンドでパッケージのインストールやアップデートなどを行い、
新しいソフトウェアやマイナーなソフトウェアなど、yumコマンドではまだ扱えないパッケージに対しては、`rpm`コマンドを使うと良い


#4.nginxの起動/停止
```shell
# 起動
sudo systemctl start nginx
# ステータス確認
sudo systemctl status nginx
# 停止
sudo systemctl stop nginx
# 自動起動設定もできる
sudo systemctl enable nginx
```
※権限があれば、`sudo`なくても大丈夫。

###無事、サーバーが立ち上がった！！！

![スクリーンショット 2021-02-26 17.17.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1075243/de8a9f2f-50d7-9f04-9294-b9ad35cea4ec.png)



#5. 仮想環境から抜けて、仮想環境も停止
```
exit
logout
Connection to 127.0.0.1 closed.
```
exitでポンポンポンポンしまくる。

抜けたら、

```
vagrant halt
```

停止を確認。

```
==> default: [vagrant-hostsupdater] Removing hosts
==> default: [vagrant-hostsupdater] Removing hosts
==> default: Attempting graceful shutdown of VM...
==> default: [vagrant-hostsupdater] Removing hosts
==> default: [vagrant-hostsupdater] Removing hosts
==> default: [vagrant-hostsupdater] Removing hosts
==> default: [vagrant-hostsupdater] Removing hosts
==> default: [vagrant-hostsupdater] Removing hosts
==> default: [vagrant-hostsupdater] Removing hosts
==> default: [vagrant-hostsupdater] Removing hosts
==> default: [vagrant-hostsupdater] Removing hosts
```
※`vagrant-hostsupdater`は便利なプラグインです。`etc/hosts`を自動で更新してくれる。



#まとめ

仮想環境(VMware)のOS(centOS7)にサーバー（ミドルウェアnginx）が立ち上がった。
なんだか、一つの魔法を使って村を作った気分だ。（感動）

以上、
ありがとうございました。
[Node.js] MySQLのIN句をプレースホルダーで表す


#概要

Node.jsでMySQLを扱うにあたり、
IN句のリスト部分をプレースホルダーで表すには、どのようにすれば良いかを以下に記していきます。


#本題の前に...
(本題しか興味ない人は、すっ飛ばしてください)
##Node.jsでMySQLを扱うためにインストール

`npm i -S mysql promise-mysql`

##Node.jsでMySQLプレースホルダーを扱うときの基本

例えば、プレースホルダーなしで書こうとすると以下のようになります。(良くない例です)

```javascript:【NG例】プレースホルダーなし
const userid = 1 ;
const sql = `SELECT * FROM users WHERE userid = ${userid} ;`
```

このままだと、SQLインジェクションの格好の餌食となってしまうため、
プレースホルダーを使って書き直します。

```javascript:【OK例】プレースホルダーあり
const userid = 1;
const sql = `SELECT * FROM users WHERE userid = ? ;`
const res = await conn.query(sql, userid);
//この場合、
//SELECT * FROM users WHERE userid = 1;
//というクエリを投げたことになる
```

変数が2つ以上になる場合は、

```javascript:【OK例】変数が2つ以上の場合
const userid = 1;
const classname = 'G';
const sql = `SELECT * FROM users WHERE userid = ? AND classname = ? ;`
const res = await conn.query(sql, [userid, classname] );
//この場合、
//SELECT * FROM users WHERE userid = 1 AND classname = 'G';
//というクエリを投げたことになる
```
のように、配列に変数を格納することで表すことができます。

#本題「IN句のリストをプレースホルダで表したい」
以下のように書くことで、IN句もプレースホルダーを用いて表すことができます。

```javascript:IN句でプレースホルダーを使う
const sql = `SELECT * FROM users WHERE userid NOT IN (?) ;`
const excludedId = [1, 3, 4];
const res = await conn.query(sql, [excludedId] );
```

これで、userid = 1, 3, 4 以外の行を抽出することができました。

##ちょっとだけ解説
複数の変数がある場合、その変数の個数分「?」を用意する必要があると上述しました。
今回の場合、

```javascript:リストを?で表す
const excludedId = [1, 3, 4];
const sql = `SELECT * FROM users WHERE userid NOT IN (?,?,?) ;`
```

のように書かれていてほしいわけです。
しかしながら、状況によって
?の個数が3つから4つ、5つと変動していくことも考えられ、上記のように書くのは現実的ではありません。

そこで、
「1,3,4をそれぞれ変数として見る」のではなく、
「[1,3,4]という配列を、1つの変数として捉える」ことで解決できます。
リストに渡したい配列さえあれば、その配列を引数に渡すだけで
簡単にクエリを作ることが出来ました。

##注意点

ちなみに、以下のやり方ではエラーが出ます。

```javascript:【NG例】IN句でプレースホルダーを使う
const sql = `SELECT * FROM users WHERE userid NOT IN (?) ;`
const excludedId = [1, 3, 4];
const res = await conn.query(sql, excludedId);
```

複数の変数が出てくる場合は
[userid, classname]のように配列に変数を格納して、渡しますよね。

しかし今回の場合、[1,3,4]という配列を一つの変数として扱いたいので、
`const res = await conn.query(sql, excludedId );`
のように配列を渡してしまうと、
その中の要素である、1,3,4という3つの数値が、変数として見られてしまいます。

そのため必ず、配列を配列で括って書くようにしましょう。

#余談「Node.jsでクエリを確認するためには」
プレースホルダーで書いていると、
実際、自分の思ったところに正しい変数が入っているか不安になることもあると思います。
そこで、以下のような書き方をすると
実際に投げられているクエリを確認することができ、大変便利です。

```javascript:クエリ確認

const excludedId = [1, 3, 4];
const sql = mysql.format(`select * from users where userid NOT IN (?) ;`, [excludeId] );
console.log(sql); //select * from users where userid NOT IN (1,3,4) ;
```

#終わりに
IN句のリストをプレースホルダーで表している例があまりなかったので
先輩の助けを借り、今回記事にしてみました。
参考になれば幸いです。

#参考
 - [Node.jsでMySQLを使うメモ](https://qiita.com/PianoScoreJP/items/7ed172cd0e7846641e13)
【Cisco】showコマンドのオプションについて

#はじめに
CiscoIOSでのshowコマンドのオプションをまとめました。
例えばshowrunコマンドは出力されるconfigが多くて
見たいところをすぐに見つけられないのが悩みやったけど
オプションを使って抜粋して出力したらええやないかい。

#対象
・Cisco触っている人

#showコマンドのオプション
オプションを使う場合は必ず、「|」(パイプ)を挟んで使用すること。

```
include	 include以後に記載した文字列が含まれる行を返す
exclude	 exclude以後に記載した文字列が含まれない行を返す
begin	 begin以後に記載した文字列から始まる行以下の行をすべて返す
section	 section以後に記載した文字列に関連するsectionを返す
```
個人的にはsectionコマンドはめちゃくちゃ使うイメージ
interfaceの設定内容を見たいってときに重宝する。

例えば、includeの場合

```
show run | include interface GigabitEthernet0/0/0
```
上記のコマンド結果は

```
Router#show run | include interface GigabitEthernet0/0/0
interface GigabitEthernet0/0/0
```
interfaceのポート部分しか持ってこれないのに対して、
sectionオプションだと

```
show run | section interface GigabitEthernet0/0/0
```
interfaceの中身までしっかり閲覧できる。

```
Router#show run | section interface GigabitEthernet0/0/0
interface GigabitEthernet0/0/0
 no ip address
 duplex auto
 speed auto
 shutdown
```
#注意点
特にないです。
ガンガン使ってみましょう。


#参考
http://blog.feasible-lab.com/cisco-ios-show-command/
大変参考になりました。
ECSのタスク定義で起きたエラーを「awslogs」で確認する方法

毎日投稿しているのですが、本当にネタが尽きない。

今友人の頼みでVue.jsとLaravel、Firebase、Stripe、AWSを使ってサイトを制作しているのですが、世の中便利になったと毎日感じております。

今日はそんなこんなでDockerで作ったコンテナを実際のサーバーで動かしたときってECRのリポジトリへプッシュしてECSでタスクやらクラスターを作成しますよね。

ただ、最近ECSでクラスターを作成し、タスクを実行するときに何回やってもエラー起きたんです。

ECSのクラスターでエラーが起きた時ってどこで起きたかが非常に分かりづらい。。。

それを解決してくれるのが**awslogs**です！

今日はそのawslogsをECSで使用する方法をお教えします！！

めちゃめちゃ簡単なので、ECSのタスク定義でエラーが出て困っている方はぜひご利用ください。

それでは説明していきます！！

#IAMユーザーの権限#

IAMユーザーで作業を行う場合、下記の権限を追加してください。

・CloudWatchFullAccess

IAMユーザーで作業を行わない場合はスキップしてください。

#awslogsの設定#

タスク定義で「コンテナの追加」から任意のコンテナを作成します。

その時に「ストレージとログ」で「ログドライバー」を「awslogs」にします。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/9c7370f3-06c3-98a9-4f80-81e10ff494da.png)


すると画像のように勝手に設定されます。

このままで大丈夫です。

#タスク実行画面からawslogsの確認#

クラスター内でタスクの実行を行い、実行したタスクの画面の画面へ行き、コンテナ内で以下の画像のように「CloudWatchのログを表示」をクリック。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/100ccc54-8fa2-aebc-ffb9-fa62ab12597c.png)


するとCloudWatch内でログが表示されます！

このようにしてクラスター内のタスクで起きたエラー内容を確認することができます。

プログラミングはエラー解決にかける時間の方が多いのでこういったところからエラー解決時間を減らしていきましょう！！

以上、「ECSのタスク定義で起きたエラーを「awslogs」で確認する方法」でした！

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

あと、最近「ココナラ」で環境構築のお手伝いをするサービスを始めました。

気になる方はぜひ一度ご相談ください！

Thank you for reading
【勉強会資料】ecs-cliでハマったこととecspressoの紹介

# 前書き

- 社内勉強会用の資料です
- 自分が発表できるレベルの文章と内容しかありません
- 間違ってたらごめんなさい

# Amazon ECS とは

![スクリーンショット 2021-02-26 13.15.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641465/1a2c9839-ad81-3a34-a65a-6c1f1bf0e83b.png)

- docker-compose.ymlを元にコンテナ定義、タスク定義が作成できる
- cluster, serviceが作成済みであれば、このタスク実行して！と投げるだけで良いのでとても楽

# ecs-cli の使い方

## コマンド例

- 設定作成
  - `ecs-cli configure --region ap-northeast-1 --cluster ${cluster-name} --config-name ${config-name}`
- タスク作成
  - `ecs-cli compose --project-name ${service-name} --file ${compose-path} service create --cluster-config ${config-name}`
- タスクで任意のコマンドを実行する
  - `ecs-cli compose --project-name ${service-name} run --cluster-config ${config-name} ${service-name} "echo Hello"`
- デプロイ

# ハマった点: `ecs-cli compose run ${cmd}` は $cmd の終了コードを取得できない

## 期待した動作

1. ecs-cliくん！このコマンドをそのタスクで実行して！
2. 開発者さん！了解やで！......（待機）
3. よっしゃ！ちゃんと終わったで！ or ほーん！？なんか異常終了したで！？
4. ecs-cliくんあざ！終了状態は......（echo $?) なるほどな......(暗黒微笑)

## 実際の動作

1. ecs-cliくん！このコマンドをそのタスクで実行して！
2. 開発者さん！了解やで！
3. よっしゃ！**「このコマンドをそのタスクで実行しろと命令する」**ことが終わったで！（終了コード0）
4. 違うそうじゃない(鈴木雅之)

`ecs-cli compose run "false"`的なことをしても終了コードが0になる <- やばい

# 何がやばいの

- 完了しても、失敗しても、終了コードが0（異常なし）になる
- CIで失敗が取れないのでめちゃくちゃ気づきにくい
  - 普段からCIを信用しているとなおさら（信用しないはしたくない）

## 実際にあったケース

CIで、テストが通ったら手動でapproveして自動デプロイさせる、ということをしている。流れこんな感じ。

1. テスト(CIのdocker imageで実行される)
2. タスク定義登録(CIのdocker imageで実行される)
3. **ecs-cliでdb:migrate(タスク定義に設定されているdocker imageで実行される)**
  - ここが絶対通る（成功とは言っていない）ようになる
4. デプロイ(CIのdocker imageで実行される)

- タイミングによってはdb:migrateが正常終了しない場合でもデプロイされることがある
- **db:migrateが失敗していてもデプロイが実行される**
  - デプロイ自体が失敗すればまだ良いが、そのままデプロイされてしまった場合、いつ落ちるか分からない状況に気づかず運用することになる
  - やばい！！！！！

この時の原因は

# タスク内で実行したコマンドの終了コードが取れるものを使おう

というわけでecspresso

- <https://github.com/kayac/ecspresso>

# ecspresso でコマンドを実行してみる

- `ecspresso run --config ${config-path} --overrides="$overrides"`
    - 直接コンテナに上書きする
    - 文字列の配列にする `"echo hoge"` -> `"echo", "hoge"`

こんな感じでやってます。

```bash
cmd=$(echo ${raw_cmd} | sed -e "s/^/\"/" -e "s/\$/\"/" -e "s/ /\", \"/g")
overrides=$(cat <<OVERRIDES
{
  "ContainerOverrides": [
    {
      "Command": [
        $cmd
      ],
      "Name": "app"
    }
  ]
}
OVERRIDES
)
ecspresso run --config ${config-path} --overrides="$overrides"
```

# ecspresso の詳細

開発者の方がアドベントカレンダーとして詳細な使い方を記載しています。

https://adventar.org/calendars/5916

# 嬉しかった点

- 設定をコマンドの引数として設定する必要が無くなった
    - serviceごとに存在するconfig.ymlを指定するだけで良い
- 既存リソースの設定をinitコマンドで自動出力できるので、既にECSを使用していれば導入がとても楽
    - https://zenn.dev/fujiwara/articles/4847fb822f2820
- 環境変数の扱いがめっちゃ楽
    - docker imageのrevisionなどを環境変数で渡す必要があったりした
    - https://zenn.dev/fujiwara/articles/ecspresso-20201205
- 手軽なお布施手段がある 買いましょう
    - https://zenn.dev/fujiwara/books/ecspresso-handbook#

# そのうち

まがじーんで清書したい気持ちが湧いてきたのでするかも
[Jetpack Compose] Jetpack Compose Beta!


- https://android-developers.googleblog.com/2021/02/announcing-jetpack-compose-beta.html

## What's In Beta

- 🆕 Coroutines support
- 🆕 Accessibility support for Talkback - support for other technologies will be in Stable
- 🆕 Easy to use Animations, with a completely new API since alpha.
- Interoperability with Views
- Material UI Components, all with @Sampled code
- Lazy Lists - Jetpack Compose's take on RecyclerView
- DSL-based Constraint Layout
- Modifiers
- Testing
- Theming and Graphics, with easy support for Dark and Light mode
- Input and gestures
- Text and editable text
- Window management


<iframe width="560" height="315" src="https://www.youtube.com/embed/Ef1xKWjA9E8" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<iframe width="560" height="315" src="https://www.youtube.com/embed/9US35jaiWIw" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<iframe width="560" height="315" src="https://www.youtube.com/embed/CcE28cMDHf8" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<iframe width="560" height="315" src="https://www.youtube.com/embed/vRjJAWh6JPE" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
GitHub コマンドでcloneからpushまでの手順

#超初心者向け
##~gitコマンドでcloneからcommitまでの手順~

cliコマンドを使ってリポジトリをcloneしたい場所に移動する

```
cd "ローカルリポジトリーを置きたい場所"
```
移動先にリモートリポジトリーを設置する

```
git clone "HTTPSのURL"
```
自分のHTTPSのURLはWEB版のgithubの自分のリポジトリーにいき
緑色のcodeを押すと出てきます。

そして自分のbranchを確認します。

```
git branch
```
すると、*mainがでてくると思います。
そこで新しくbranchを作成します。

```
git branch 新しいbranch名
```

これでbranchは作成できます。その後branchの切り替えを行います

一人で制作する場合は直接mainを使っていいかなとなるかもしれませんが
そう思う人はTECH ACADEMYさんの[この記事](https://techacademy.jp/magazine/6235)を見てもらうのがわかりやすいと思います。

```
git checkout 作成したbranch名
```

この2つを一緒に行えるコマンドもあるので、追記しておきます。

```
git checkout -b 新しいbranch名
```

Gitのローカルリポジトリにファイルを追加する（commit対象にする）

```
git add ＊
```
＊でファイルをすべてcommit対象にします。

ローカルリポジトリーからリモートリポジトリーにコミットする（-mの先はコミットするときのコメント内容）

```
git commit -m "コメント内容"
```

mainブランチにpullリクエストを送る。

```
git push origin 作成したbranch名
```
ここまでがcloneからpushまでの流れです。

##そもそもプルリクエストとは、
コードの変更をレビュワーに通知し、マージを依頼する機能です。 コードのレビューを受けることで、1人で作ると気がつかないコードの指摘やバグや記述ミスの発見ができ、コードの品質を高めます。 レビュワーにとっても、他人が書いたコードを読むことで新しい書き方を発見できるというメリットがあります。

####ここまで完了したら、githubを見に行きcreate pull リクエストを作成します。

ここからは`npm i`した際のリモートリポジトリーに上げる際にnode_modulesのあげない設定です
node_modulesに関してはpackage.json,package-lock.jsonがあればnpm iでダウンロードできるためリモートリポジトリーに上げる必要もないですし、ファイル数が多いためおすすめしません

フォルダ直下に

```
touch .gitignore
```
作成します。
そして.gitignoreの中に記述する内容は

```
node_modules/
ファイルのパターン一致でコンパイルなどで生成したファイルを指定する場合
*.com
*.class
*.dll
*.exe
*.o
*.so
```
これでnode_modulesだけリモートリポジトリーに上がらないようになります

あくまで僕のメモとして作成致しましたが誰かの役にたてると嬉しいです。
Terraformで作るAurora Serverless (MySQL 5.7互換)

皆さん、Aurora Serverlessは、使っていますか？
通常RDSを立ち上げる際には、ユーザ数の想定などをして、DBのインスタンスサイズを決めるかと思いますが、
Aurora Serverlessは、その見積もりすらも不要で立ち上げる事ができてしまいます。
このページは、Terraformで、Aurora Serverlessを、作る方法をご紹介します。

## Aurora Serverlessの特徴
はじめにAurora Serverlessならではの特徴をご紹介します。

### キャパシティ
RDSの性能になります。
`1、2、4、8、16、32、64、128、256`から選べ、数値×2GBのメモリの性能になります。
最小値から最大値の間で自動にスケールします。


### 一時停止
`auto_pause ` の設定で、接続が無い状態が一定時間経過後(`seconds_until_auto_pause`)、DBが一時停止状態になります。
停止時は、DBインスタンスの料金がかかりません。
ただし、再起動に若干の時間はかかるので、`seconds_until_auto_pause`の値には注意が必要です。



# Terraform

## 環境
- Terraform v0.14.7
- Aurora MySQL 2.x(MySQL 5.7互換)

## tfファイル
```terraform
// RDS用セキュリティグループ
resource "aws_security_group" "demo" {
  //このセキュリティグループを紐付けるVPCのIDを指定 ex.vpc-xxxxx
  vpc_id = aws_vpc.main.id
  name   = "rds-demo"

  ingress {
    protocol  = "tcp"
    from_port = 3306
    to_port   = 3306
    // DBへの接続を許可するcidrをlistで指定  ex.["xxx.xxx.xxx.xxx/24","yyy.yyy.yyy.yyy/24"]
    cidr_blocks = [aws_vpc.main.cidr_block]
  }

  egress {
    protocol    = "-1"
    from_port   = 0
    to_port     = 0
    cidr_blocks = ["0.0.0.0/0"]
  }
}
// RDS用サブネットグループ
resource "aws_db_subnet_group" "demo" {
  name = "rds-demo"
  # サブネットグループに入れるサブネットのIDをlistで指定 ex.["subnet-xxxxxx","subnet-yyyyy"]
  subnet_ids = [aws_subnet.frontend.id, aws_subnet.backend.id]
}

// RDSクラスター(Aurora Serverless)
resource "aws_rds_cluster" "demo" {
  cluster_identifier = "aurora-cluster-demo"
  engine_mode        = "serverless"
  //デフォルトはaurora(mysql5.6)のため、mysql5.7の場合は必ずengine="aurora-mysql"の指定が必要です
  engine               = "aurora-mysql"
  engine_version       = "5.7"
  database_name        = "mydb"
  master_username      = "xxxxxxxx"
  master_password      = "xxxxxxxx"
  db_subnet_group_name = aws_db_subnet_group.demo.name
  // 削除時にスナップショットを作成しない
  skip_final_snapshot    = true
  vpc_security_group_ids = [aws_security_group.demo.id]

  scaling_configuration {
    //接続がない場合に、一時停止する
    auto_pause = true
    //一時停止するまでの時間(秒)
    seconds_until_auto_pause = 300
    //スケール可能なキャパシティーユニットの最大値
    max_capacity = 16
    //キャパシティーユニットの最小値
    min_capacity = 1
    //タイムアウト時に強制的にスケーリング
    timeout_action = "ForceApplyCapacityChange"
  }
}
```




## Terraform公式サイト
### Resource: aws_security_group

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group

### Resource: aws_db_subnet_group

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group

### Resource: aws_rds_cluster

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster


## 追加でおすすめの設定
- 削除保護（デフォルトはfalse）
  - `deletion_protection = true`
- バックアップの保持期間(デフォルトは1日)
  - `backup_retention_period = 7`
- 削除時にスナップショットを作成する(false時)
  - `skip_final_snapshot    = false`  
  - デフォルトはfalseなので、この項目を削除してもよい




では、よきTerraformライフを！！！
Blenderにはオブジェクトの選択順序がない

Maya等では、

```
string $sl[] = `ls -sl`;
```

などとすると、選択した順番にオブジェクト名が配列の中に追加される。

しかし、Blenderには選択順序がないので配列の中の順番はテキトーになるらしい。
順序くらい作って欲しいよね。

代わりに、最後に選択したオブジェクトを以下のコマンドで取得する
最後に選択したオブジェクトは、アクティブになっているのでこれで取得できる

```
bpy.context.active_object
```

選択中のすべてのオブジェクトは

```
bpy.context.selected_objects
```
で取得できるので、これらを組み合わせる必要がある。


自分用メモ
Python Kivyを1つに収めるサンプル

```python
#-*- coding: utf-8 -*-

from kivy.lang import Builder
Builder.load_string("""
<TextWidget>:
	BoxLayout:
		orientation: 'vertical'
		size: root.size

		TextInput:
			text: root.text

		Button:
			id: button1
			text: "OK"
			font_size: 48
			on_press: root.buttonClicked()
""")

from kivy.app import App
from kivy.uix.widget import Widget

from kivy.properties import StringProperty 

class TextWidget(Widget):
	text = StringProperty()

	def __init__(self, **kwargs):
		super(TextWidget, self).__init__(**kwargs)
		self.text = ''

	def buttonClicked(self):
		for i in range(5):
			self.text += str(i) + '\n'

class TestApp(App):
	def __init__(self, **kwargs):
		super(TestApp, self).__init__(**kwargs)
		self.title = 'greeting'

	def build(self):
		return TextWidget()

if __name__ == '__main__':
	TestApp().run()
```
コードはほとんど以下の記事で書かれているものの引用です。
https://qiita.com/dario_okazaki/items/7892b24fcfa787faface

kvファイルとpythonファイルを1つにまとめるのどうやるんだっけっと
毎回ググるのがダルくなってきたので自分用にメモ
アプリケーションの簡易カスタマイズ ⇒ Lightning Experience でのアクションの動作について

１．アクションはレコードページのどの領域に表示されますか?
２．レコードホームページ上のアクションの順序は何に基づいていますか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/8cd54c66-6602-b06b-6263-5e2e4521a517.png)
Unityのサブスレッドで5msごとに処理

Unityのサブスレッドで5msごとに処理
多分こんな感じ

以下を参考にしました。
https://teratail.com/questions/109591

```C#
using UnityEngine;
using System.Threading;
using System;

public class UnitySubThreadTimer : MonoBehaviour
{
    Thread thread;
	
	// Start is called before the first frame update
	void Start()
    {
        thread = new Thread(new ThreadStart(SubThread));
        thread.Start();
    }
	void SubThread()
	{
		//Process once every 5ms
		long next = DateTime.Now.Ticks + 50000;
		long now;

		while (true)
		{
			try
			{
				Debug.Log(Time.time);
			}
			catch
			{
			}

			do
			{
				now = DateTime.Now.Ticks;
			} 
			while (now < next);
			next += 50000;
		}
	}

	void Stop()
	{
		thread.Abort();
	}

	void OnApplicationQuit()
	{
		thread.Abort();
	}
}
```
daeファイル作成時に気を付けること

Mayaでdaeファイルをexportすると、ソフトウェアによってはblendShapeが読み込まれない。
exportしたdaeファイルをテキストエディタ等で開いて、「RELATIVE」を「NORMALIZED」にすべて書き換えると使えるようになる。

また、ピボットポイントを変更してもそのままだと反映されないので、修正→ピボットをベイク処理をしておく必要がある
初心者向けコマンド実行時の注意事項

初心者でターミナルの利用やプログラミングを始めて、注意しなきゃなと思ったことをピックアップします。

# この記事について
- 作者は基本的にCent OSイメージのVMを使っています。そのため記載されるCent OS向けのコマンドであることが多いです。
- 記事にしたくなり次第ピックアップします。
- 適宜フォーマットを修正します。
- 不明点等ございましたら、お気軽にお問い合わせください。
- 他にも「これも初心者の方に伝えてあげてほしい！」というものがあればお気軽にお問い合わせください。

# 注意したいこと

## ログを残す

何を実行したのかわかるように、ログは残しましょう。自動でログを残す設定にしておくとよいでしょう。
設定の仕方は、、「`<ターミナルソフト名> ログ 自動`」などでググっていただければわかると思います。

## 作業ディレクトリがどこであるかを意識する

本当にそのディレクトリでコマンドを実行してよいのか、今一度確認しましょう。
「今どのディレクトリにいるんだっけ？」というときは、`pwd`コマンドで確認できます(windowsの場合は`cd`コマンド)。
特に、`curl`コマンドや`wget`コマンドなどでダウンロードする場合、指定しない場合は実行したディレクトリにダウンロードされます。

## `mv`コマンドを活用する

`wget`や`curl`でダウンロードしていじくった後、再度ダウンロードしたくなった場合
⇒`rm`コマンドでファイルを削除する前に、`mv`コマンドで名前を変えてしまいましょう。
削除してしまうと、復帰ができません。本当に削除してしまってよいでしょうか？

```
# example
$ ls
hoge

$ mv hoge hoge_old

$ ls
hoge_old

$ wget https://hoge

$ ls
hoge hoge_old
```

## `cp`コマンドを活用する

ファイルを試しに編集したい場合
⇒そのまま`vi`コマンドで編集する前に、`cp`コマンドで新しい名前のファイルを作っておきましょう。
その修正をもとに戻したいとき、簡単に戻せます。

```
# example
$ ls
hoge.txt fuga.txt

$ cp hoge.txt hoge_ed.txt

$ ls
hoge.txt hoge_ed.txt fuga.txt

$ vi hoge_ed.txt
<編集>

# やっぱ修正やめたい
$ rm hoge_ed.txt
```

<!-- Links -->

[hoge]: hoge
csv を json に変換する PowerShell ワンライナー

あらかじめ json に変換したい csv ファイルの文字コードを`Shift-JIS`または`UTF-8 with BOM`にしておくこと。

2021-06-17 追記：入力ファイルの文字コードを指定することで文字化けを回避できるようになりました。

```powershell:CSVファイルがShift_JISの場合
gc .\input.csv | ConvertFrom-Csv | ConvertTo-Json > output.json
```

```powershell:CSVファイルがUTF8の場合
gc -Encoding UTF8 .\input.csv | ConvertFrom-Csv | ConvertTo-Json > output.json
```
[Swift/FirebaseAuth] 一度ログインしたらログイン画面をスキップする方法

Firebase Authentication を使ってユーザーの認証を行うアプリを作る際、一度新規登録・ログインをしたら次アプリを開くときログイン画面をスキップしてくれるコードを紹介します。

この記事ではすでに FirebaseAuth を使って新規登録・ログイン画面と処理が完成してることを前提とします。これらのやり方は [Firebase Official Doc](https://firebase.google.com/docs/auth/ios/start)が丁寧に説明してくれてるので参考にしてください！

##Code
この処理は ``SceneDelegate.swift`` で行います。
まず FirebaseAuth ライブラリをインポートします。

```swift:SceneDelegate.swift
import FirebaseAuth
```
SceneDelegate クラスの中に以下のメソッドを書きます。

```swift:SceneDelegate.swift
    func skipLogin() {
         //使ってるストーリーボード（何もいじってない限り ファイル名は"Main.storyboard" なので "Main" と記入。
         let storyboard = UIStoryboard(name: "Main", bundle: nil)

         //ログイン後に飛びたいストーリボード。Identifier は Main.storyboard で設定。
         let homeViewController = storyboard.instantiateViewController(identifier: "HomeVC")
         
         //rootViewController (初期画面）を homeViewController にする。
         window?.rootViewController = homeViewController

         //画面を表示。
         window?.makeKeyAndVisible()
     }

```
ちなみに storyboard ID はここで設定します。
![スクリーンショット 2021-02-26 午後4.01.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831968/2714ce47-d6bf-66ea-3abc-55ba24c6fabf.png)

``skipLogin()``メソッドが書き終わったらあとは次のメソッドの中に呼ぶだけです！

```swift:SceneDelegate.swift
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let _ = (scene as? UIWindowScene) else { return }
        
        -----ここから付け足す-----
        //もし一度ログインしたユーザーだったら skipLogin() を呼ぶ。
        if Auth.auth().currentUser != nil {
           skipLogin()
        }
        //rootController がデフォルトで新規登録・ログイン画面についていれば else文はいらない。
    }

```

これで、一度ログインしたら次からログイン画面をスキップできるようになります！
L4T 32.5にアップデートする際の注意点

### [L4T](https://developer.nvidia.com/embedded/linux-tegra) 32.5

[L4T 32.5のRelease Notes]
(https://docs.nvidia.com/jetson/l4t/pdf/Jetson_Linux_Driver_Package_Release_Notes_R32.5_GA.pdf)に、以下のような記述があります。

* Boot firmware: Updated for all Jetson Nano developer kits to relocate boot firmware to integrated QSPI-NOR memory. Developer kits use a micro SD card only for OS/app storage after this change.
* Booting without micro SD card: All Jetson Nano developer kits now display a warning screen if no micro SD card is inserted, then attempt to boot from other supported media.

という記述があります。

ブートローダが、QSPI-NOR側にR32.5から統合されたようです。

このあたりの仕様変更を把握しないままに、R32.5でSDにシステムを構築して、従来と同じように、別のJetson NanoでセットアップしたSDをそのまま、新しいJetson Nanoに挿入して使用できると思っていた私は、パニクってしまいました。2021/02/19の夕方のお話しでした。

ということで、R32.4.4の時代のセクタを残したままにしておけば、新しいJetson Nano、つまり、まだ、QSPI-NORにブートローダが統合される前のものでも、システムを起動することができるようです。

具体的には、R32.4.4で一度セットアップして、それをクイックフォーマットして、R32.5のSDイメージを書き込んで、もう一度セットアップ、という手順を踏んでみました。

そのSDを、まだ一度もブートしたことがない新しいJetson Nanoに挿入して起動するとブートできました。

そして、、、ブートしただけで、QSPI-NORが更新されたようです。SDなしで起動しても、画面にSD入ってないよと教えてくれるようになりました。

ということで、当たり前のことですが、新しいバージョンにアップデートするときは、Release Noteぐらいはちゃんと読まないといけないですね。

ってな記事を投稿しようとしてるときに、もう、L4T 32.5.1が2021/02/24にリリースされていますね。。メジャーバージョンのRelease Noteを読まないとわからなくなってしまいましたね。。

あと、[Jetson Nano Boot Flow](https://docs.nvidia.com/jetson/l4t/Tegra%20Linux%20Driver%20Package%20Development%20Guide/bootflow_jetson_nano.html#wwconnect_header)に、Jetson Nanoの起動シーケンスが説明されていますので、また別途、必要に応じて、精読しておこうと思います。
【テスト自動化】Playwrightでファイルのアップロードのテスト

# Playwrightでファイルのアップロードのテスト【テスト自動化】
・[Playwright](https://playwright.dev/)でテスト自動化をかんたんに
・インストール等は他ドキュメントが詳しいので省略します
・ファイルのアップロードが必要な場合

# 環境
・Windows10 64bit
・node.js v14.15.5
・cygwin

# Playwright とは
- https://github.com/microsoft/playwright
- https://playwright.dev/

> Playwrightは、Chromium、Firefox、WebKitを単一のAPIで自動化するNode.jsライブラリです。
> 常に環境に配慮し、機能があり、信頼性が高く、高速なクロスブラウザーWeb自動化を可能にするように構築されています。

個人的な感想ですが、「Windows で *webkit (safari)* も実行できる」ブラウザテスト自動化用のツール。
Selenium（最近はあまり触っていないですが・・・）より使った感じは良好。
待ちの処理も優秀でかなり使いやすいと感じました。あと動画が撮れちゃうのもイイですね。
いろいろな言語に対応してますが、ここでは node.js のスクリプトで載せます。

# ブラウザ起動など
```console
npx playwright wk https://www.wikipedia.org/
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108113/e2379415-139c-fd54-a8ef-9dbf2a55881c.png)

・使い方
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108113/68d7a1e8-a749-6478-8ec7-32308ddba975.png)
codegen とするとブラウザが起動し操作した内容をスクリプトにしてくれます。（最初はこれを使うと便利）

# ファイルをアップロードさせる方法
```js
    const [ fileChooser ] = await Promise.all([
        page.waitForEvent('filechooser'),
        page.click('text="ファイルを選択"'),
    ]);

    await fileChooser.setFiles('c:/path/to/upload.jpg');
    await page.waitForSelector('text="upload.jpg"');
```
text="ファイルを選択" の所がファイル選択ダイアログを開くボタン。
ダイアログを開く際に、filechooser と一緒に待たせることでファイルをアップロードすることができます。
最後の waitForSelector ではアップロード後のファイル名を(jsで)表示させ、検知させてアップロード完了まで待たせてます。
この辺は実装内容によって変わってくると思います。

# span にある内容を取得したい場合（おまけ）
```js
const spanText = await page.$eval('//span[contains(text(),"%s")]/following-sibling::span[1]'.replace("%s", target),
                    el => el.innerHTML);
```
※target 文字列の入ったspan の次の span の中身を取得
xpath で自由に設定できるので自在に取れます。

# video を撮影したい場合（おまけ）
```js
    const context = await browser.newContext({
        locale: 'ja-JP',
        timezoneId: 'Asia/Tokyo',
        viewport: { width: 1000, height: 900 },
        recordVideo: { dir: 'd:/tmp/playwright/videos/' },
    });
```
コンテキストの設定に設定すると勝手に撮影して保存してくれます。

以上、お疲れさまでした！
子供でも知ってる Eureka

## Eurekaは？
EurekaはSpringCloud Netflix 一つのブランチです。
### 主な機能
EurekaはRESTにもとにして、クラウド上のサービス発見とフェイルオーバを転移可能にするサービスです。
サービスの登録と発見は分散システムにとって非常に重要です。サービス発見と登録により、サービス呼び出しのプロファイルを変更することなく、サービスへのアクセス、サービスの識別子を使用する可能です。Eurekaはzookeeperとdubboなどのフレームワークを似ています。

![2021-02-26 152041.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517198/f9ab5a87-95eb-aae8-5e9a-229ddd06fde9.png)


### Eurekaサービスの配置
まずはpom.xmlの配置です。

```xml
<!--eureka-server -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
```

そしてエントリーファイルに注釈@EnableEurekaServerが忘れないように書きます。

次にymlプロファイルを作成します:
```yaml
server:
  port: 7001	#server's port
eureka:
  instance:
    hostname: localhost #eureka Servername
  client:
    register-with-eureka: false     
    fetch-registry: false    
    service-url:     #サービスURLを設置
       defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
```
そこまでサーバーの方は配置完了

### Eurekaクライアントの配置

まずはpom.xmlの配置です。

```xml
<!--eureka-server -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
```

そしてエントリーファイルに注釈@EnableEurekaClientが忘れないように書きます。

次にymlプロファイルを作成します:
```yaml
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka	#eurekaサービスのURL
```
そこまでクライアントの方は配置完了

以下はURLで訪問した画面です。
![20210226155435.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517198/7e47c2d6-4e86-9e20-d7df-cdefad15ec96.jpeg)