OmniAICreator/Qiita-1.07M huggingface dataset:
ゼロから始めるLeetCode Day39「494. Target Sum」

#概要
海外ではエンジニアの面接においてコーディングテストというものが行われるらしく、多くの場合、特定の関数やクラスをお題に沿って実装するという物がメインである。

その対策としてLeetCodeなるサイトで対策を行うようだ。

早い話が本場でも行われているようなコーディングテストに耐えうるようなアルゴリズム力を鍛えるサイト。

せっかくだし人並みのアルゴリズム力くらいは持っておいた方がいいだろうということで不定期に問題を解いてその時に考えたやり方をメモ的に書いていこうかと思います。

[Leetcode](https://leetcode.com/)

[ゼロから始めるLeetCode 目次](https://qiita.com/KueharX/items/6ee2502c3b620c795b70)

前回
[ゼロから始めるLeetCode Day38「208. Implement Trie (Prefix Tree)」](https://qiita.com/KueharX/items/c4dc14c167a4a179ba63)

今はTop 100 Liked QuestionsのMediumを解いています。
Easyは全て解いたので気になる方は目次の方へどうぞ。

[Twitter](https://twitter.com/kueharx)やってます。

# 問題
[494. Target Sum](https://leetcode.com/problems/target-sum/)

自然数の配列`nums`と自然数`S`が与えられます。
+と-が与えられるので、配列を全て足すか引いてSの値と一致させるような組み合わせの数を返してください。

>Input: nums is [1, 1, 1, 1, 1], S is 3. 
Output: 5
Explanation: 

>-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3

>There are 5 ways to assign symbols to make the sum of nums be target 3.

こんな感じです。
言いたいことは例から分かると思います。


# 解法

```Python
class Solution:
    def calc(self,nums,index,sums,S):
        if index == len(nums):
            if sums == S:
                self.count += 1
        else:
            self.calc(nums,index+1,sums+nums[index],S)
            self.calc(nums,index+1,sums-nums[index],S)
            
    def findTargetSumWays(self, nums: List[int], S: int) -> int:
        self.count = 0
        self.calc(nums,0,0,S)
        return self.count
# Time Limit Exceeded
```

最初Bruteforceで解こうと思って書いたのですが時間切れになっちゃいました。

なので書き換えました。

```Python
from functools import lru_cache

class Solution:
    def findTargetSumWays(self, nums: List[int], S: int) -> int:
        
        @lru_cache(None)
        def calc(index,S):
            if index == 0:
                 return  int(nums[0] == S) + int(-nums[0] == S)
            return  calc(index-1, S - nums[index]) + calc(index-1, S + nums[index])
    
        return calc(len(nums)-1, S)
# Runtime: 240 ms, faster than 74.28% of Python3 online submissions for Target Sum.
# Memory Usage: 31.5 MB, less than 50.00% of Python3 online submissions for Target Sum.
```

[ゼロから始めるLeetCode Day25「70. Climbing Stairs」](https://qiita.com/KueharX/items/5a8993968c995b074737)
でも登場した`@lru_cache`を使ってヘルパー関数として`calc`を用意して実装しました。

良い感じで実装できたので、学習を続けて形に残しておくのは大事ですね。

今回はこのあたりで。おつかれさまでした。
マイグレーションについて

ツールを使ったAWSへのサーバー移行の考察
https://dev.classmethod.jp/articles/consider-servers-lift/

#####移行ツール
* SMS
    * VMware vSphere または Windows Hyper-V 上の仮想マシンを EC2 へ移行 (レプリケーション) するサービス
* CloudEndure
    * オンプレミスの各サーバーにエージェントをインストールします。 エージェントがサーバーのディスク上のデータブロックをレプリケーションします。

AWS にもレプリケーション先の他に CloudEndure サーバーが必要です。

#####サーバー移行方式
* 増分移行
    * SMS や CloudEndure で継続的に増分レプリケーションをしておき 本番移行直前にサービスを停止し静止点を取って 完全な形で同期をとる方式です。
* Migration Once DataSynchronize Many
    * レプリケーションはあるタイミングで一度切り実施、 その後はアプリケーションに必要なデータのみを差分でコピーしていく方式です。
    * サーバーを重要度で区分して、重要度が高いサーバー群は MODM で、 それ以外は一旦増分移行を行い次フェーズで ”AWS ならでは機能” を使うように構成していくという ハイブリッドなサーバー移行がベターだと考えます。

#####DB移行方式
* DMS
    * 特別なドライバーやソフトウェアを必要することなく オンプレミスのデータベースから AWS 上のデータベースへデータレプリケーションを行います。
    * 同一プラットフォーム同士だけではなく、異なるプラットフォーム (Oracle から PostgeSQL) 間のデータレプリケーションも可能です。
* ネイティブ機能を使った DB 移行

#####VMware Cloud on AWS
> VMware vSphere ベースのオンプレミス環境を AWS 上のベアメタルへ移行し稼働させるサービス

#####クリーンインストール
> まっさらな EC2 を起動し、そのうえに必要なアプリケーションやパッケージをインストールします。 一通りのセットアップが完了したらデータ移行を行います。
【初心者】pandasのcsv読み込みで”[Errno 2] File b'test.csv' does not exist: b'test.csv”が表示された時の対処

#環境
Python 3.6.5 
pandas 0.25.3

#概要
pandas.read_csv()で、カンマ区切りのcsvファイルの読み込む

#発生した課題
FileNotFoundError: [Errno 2] File b'test.csv' does not exist: b'test.csv'
訳：b’test.csv’が見つかりません！

※本来のファイル名は’test.csv’なのですが、なぜbがファイル名の先頭についているかという疑問はこの際置いといて・・・

#データ
test.csv
```
   名前  国語  数学  英語  理科  社会
0  A太   83  89  76  97  76
1  B介   66  93  75  88  76
2  C子  100  84  96  82  94
3  D郎   60  73  63  52  70
4  E美   92  62  84  80  78
5  F菜   96  92  94  92  90
```

#ソースコード
```
import pandas as pd
df = pd.read_csv("test.csv")

print(df)
```

とりあえずまずはcsv読み込んで、コンソールで確認できるか？という初手の確認を行おうとしたときのエラーでした。

#解決法
下記コードを追加して、カレントディレクトリを指定すると問題なく読み込めました。
スクリプトもcsvも同じ階層に置いてたのになんでだろう・・

```
import os

#カレントディレクトリを指定
path = “csvが保存されているディレクトリ”
os.chdir(path)
```
Deno: MongoDB のデータを削除 (Delete)

Deno で MongoDB のデータを削除します。

```ts:mongo_delete.ts
//
//	mongo_delete.ts
//
//					Jan/06/2024
// ----------------------------------------------------------------
import { MongoClient } from "https://deno.land/x/mongo@v0.32.0/mod.ts";
import { config } from "https://deno.land/x/dotenv/mod.ts"
// ----------------------------------------------------------------

console.log ("*** 開始 ***")

const key:string =Deno.args[0]

console.log (key)

const config_env:any = config()
const user:string = config_env.user
const password:string = config_env.password
const db_name:string = config_env.db
const collection_name:string = config_env.collection

const host:string = user + ':' + password + '@localhost'
const port:number = 27017

const url:string = 'mongodb://' + host + ':' + port

console.log("Connecting to " + host + ":" + port)

const client = new MongoClient()
await client.connect(url)

const db = client.database(db_name)
const cities = db.collection(collection_name)

const consolount = await cities.deleteOne({ key: key })

console.log ("*** 終了 ***")

// ----------------------------------------------------------------
```

```text:.env
user='scott'
password='tiger123'
db='city'
collection='saitama'
```

実行コマンド

```bash
deno run --allow-net --allow-write --allow-read --unstable  mongo_delete.ts t1167
```
リモートブランチを削除してローカルのブランチをpushする方法

リモートのブランチ名を変えたいけれど**あ゛~~~~~~**ってなったので備忘録です。

リモートのブランチを表示します

```console
$ git branch -r 
  origin/HEAD -> origin/master
  origin/master
  origin/fix_example
```

ローカルのブランチを表示します

```console
$ git branch
* fix_example
  master
```

ローカルのブランチを書き換える必要が生じた！

```console
$ git branch -m 5.fix_example

$ git branch
* 5.fix_example
  master
```

そのままpushしてもローカルのブランチ名は昔のまま

```console
$ git push
fatal: The upstream branch of your current branch does not match
the name of your current branch.  To push to the upstream branch
on the remote, use

    git push origin HEAD:fix_example

To push to the branch of the same name on the remote, use

    git push origin HEAD

```

`.git/config` を編集します。

```
$ vim .git/config
```

**編集前**

```config
~略~
[branch "5.fix_example"]
         remote = origin
         merge = refs/heads/fix_example
```

**編集後**

```config
~略~
[branch "5.fix_example"]
         remote = origin
         merge = refs/heads/5.fix_example
```

揃えた。
あとはpushします。

```
$ git push
```

力技で解決系なので自己責任でお願いします。
Deno: MongoDB のデータを更新 (Update)

Deno で MongoDB のデータを更新します。

```ts:mongo_update.ts
//
//	mongo_update.ts
//
//					Jan/06/2024
// ----------------------------------------------------------------
function get_current_date_proc ()
{
	const today = new Date ();
	var ddx = today.getFullYear () + "-" + (today.getMonth () +1)
	ddx += "-" + today.getDate ()

	return ddx
}

// ----------------------------------------------------------------
import { MongoClient } from "https://deno.land/x/mongo@v0.32.0/mod.ts";
import { config } from "https://deno.land/x/dotenv/mod.ts"

console.log ("*** 開始 ***")

const key:string =Deno.args[0]
const population_in:number =parseInt(Deno.args[1])

console.log (key + "\t" + population_in)

const config_env:any = config()
const user:string = config_env.user
const password:string = config_env.password
const db_name:string = config_env.db
const collection_name:string = config_env.collection

const host:string = user + ':' + password + '@localhost'
const port:number = 27017

const url:string = 'mongodb://' + host + ':' + port

console.log("Connecting to " + host + ":" + port)

const client = new MongoClient()
await client.connect(url)

const db = client.database(db_name)
const cities = db.collection(collection_name)
const date_mod = get_current_date_proc ()

const { matchedCount, modifiedCount, upsertedId } = await cities.updateOne(
  { key: key },
  { $set: { population: population_in, date_mod: date_mod } },
)

console.log ("*** 終了 ***")

// ----------------------------------------------------------------
```

```text:.env
user='scott'
password='tiger123'
db='city'
collection='saitama'
```

実行コマンド

```bash
deno run --allow-net --allow-write --allow-read --unstable  mongo_update.ts t1164 78253900
```
MockeryのandThrowの引数について学んだ

# 概要
[前回の記事](https://qiita.com/juve_534/items/7ced1a08c0bf1d8d72c0)で紹介しましたが、テストコードでモックを使う際は、Mockeryを使ってます。 
開発を進めて、学んだことがあったのでここに残します。

# TL;DR

* MockeryのandThrowは第一引数がインスタンスか例外クラスで切り分け
* 第一引数が例外クラスのときは、例外クラスがメッセージ、コードの順じゃないとエラーになる
 * etc `AccessDeniedHttpException`

# 本編

やっていたのはLaravelプロジェクトのテスト作成です。
下記のようにクラスの返り値が `AccessDeniedHttpException` でときのものです。

他の例外と同様に書いていました。

```php
<?php

use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Tests\TestCase;
use Mockery;

class HogeTest extend TestCase
{
    public function testHoge($id)
    {
        // setup
        $this->app->bind(fugaRepositoryInterface::class, function () use ($id)) {
            $mock = Mockery::mock(fugaRepository::class);
            $mock->shouldReceive('何かしら')
                 ->once()
                 ->with($id)
                 ->andThrow(AccessDeniedHttpException::class, $message, $code);

            return $mock;
        });

        // exercise
        $hogeService = resolve(hogeServiceInterface::class);

        // verify
        $actual = $hogeService->hoge($id);
        $this->assertTrue($actual);
    }
}
```

```
‌Type error: Argument 2 passed to Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException::__construct() must be an instance of Exception or null, int given, called in mockery/mockery/library/Mockery/Expectation.php on line 607
```

原因を探るべく、[andTrowのコード](https://github.com/mockery/mockery/blob/6c6a7c533469873deacf998237e7649fc6b36223/library/Mockery/Expectation.php#L621)を見てみました。

下記のように第一引数によって処理を分け、 `andReturn` に渡していることがわかります。
先程の例の場合は、 `else` 文を通るので、 `$message, $code, $previous` の順で渡してインスタンスを生成します。

```php
    public function andThrow($exception, $message = '', $code = 0, \Exception $previous = null)
    {
        $this->_throw = true;
        if (is_object($exception)) {
            $this->andReturn($exception);
        } else {
            $this->andReturn(new $exception($message, $code, $previous));
        }
        return $this;
    }
```

次に `AccessDeniedHttpException` のコードをみてみます。
コンストラクタで `$message, $previous, $code` の順で受け取っており、 `andThrow` で渡している引数と順番が違うことがわかります。

そのため、エラーになったというわけですね。

```php
class AccessDeniedHttpException extends HttpException
{
    /**
     * @param string     $message  The internal exception message
     * @param \Exception $previous The previous exception
     * @param int        $code     The internal exception code
     */
    public function __construct($message = null, \Exception $previous = null, $code = 0)
    {
        parent::__construct(403, $message, $previous, [], $code);
    }
}
```

こういったケースで `andThrow` を使うなら、例外インスタンスを生成して渡した方が良さそうですね。

```php
andThrow(new AccessDeniedHttpException($message, null, $code));
```

# まとめ

MockeryのandThrowは第一引数がインスタンスか例外クラスで切り分けしており、第一引数が例外クラスのときは、例外クラスがメッセージ、コードの順じゃないとエラーになるということがわかりました。
etc `AccessDeniedHttpException`

また `andThrow` は内部で `andReturn` を呼んでいることも知れてよかったです。
Deno: MongoDB のデータを読む (Read)

Deno で MongoDB のデータを読みます。

```ts:mongo_read.ts
//
//	mongo_read.ts
//
//					Jan/06/2024
// ----------------------------------------------------------------
import { MongoClient } from "https://deno.land/x/mongo@v0.32.0/mod.ts";
import { config } from "https://deno.land/x/dotenv/mod.ts"

console.log ("*** 開始 ***")

const config_env:any = config()

const user:string = config_env.user
const password:string = config_env.password
const db_name:string = config_env.db
const collection_name:string = config_env.collection

const host:string = user + ':' + password + '@localhost'
const port:number = 27017

const url:string = 'mongodb://' + host + ':' + port

console.log("Connecting to " + host + ":" + port)

const client = new MongoClient()
await client.connect(url)

const db = client.database(db_name)
const cities = db.collection(collection_name)

const count = await cities.countDocuments({})
console.log(count)

const cursor = cities.find({ key: { $ne: null } })
for await (const item of cursor) {
	var str_out = item.key + "\t" + item.name
	str_out += "\t" + item.population
	str_out += "\t" + item.date_mod
	console.log(str_out)
}

console.log ("*** 終了 ***")

// ----------------------------------------------------------------
```

```text:.env
user='scott'
password='tiger123'
db='city'
collection='saitama'
```

実行コマンド

```bash
deno run --allow-net --allow-write --allow-read --unstable mongo_read.ts
```
Deno: MongoDB のデータを作成 (Create)

Deno で MongoDB のデータを作成します。

```ts:mongo_create.ts
//
//	mongo_create.ts
//
//					Jan/06/2024
//
// ----------------------------------------------------------------
function dict_append_proc(dict_aa: {[key: string]: any},id_in:string,
	name_in:string,population_in:number,date_mod_in:string)
{
	var unit_aa:{[key: string]: any} = new Object()

	unit_aa['name'] = name_in
	unit_aa['population'] = population_in
	unit_aa['date_mod'] = date_mod_in

	dict_aa[id_in] = unit_aa

	return	dict_aa
}

// ----------------------------------------------------------------
function data_prepare_proc ()
{
	var dict_aa : {[key: string]: any} = new Object ()

	dict_aa = dict_append_proc (dict_aa,'t1161','さいたま',38729,'2014-9-14')
	dict_aa = dict_append_proc (dict_aa,'t1162','所沢',23157,'2014-5-26')
	dict_aa = dict_append_proc (dict_aa,'t1163','越谷',91426,'2014-8-12')
	dict_aa = dict_append_proc (dict_aa,'t1164','久喜',37864,'2014-9-18')
	dict_aa = dict_append_proc (dict_aa,'t1165','熊谷',67358,'2014-7-14')
	dict_aa = dict_append_proc (dict_aa,'t1166','秩父',51792,'2014-2-12')
	dict_aa = dict_append_proc (dict_aa,'t1167','川越',38251,'2014-5-15')
	dict_aa = dict_append_proc (dict_aa,'t1168','和光',54386,'2014-4-20')
	dict_aa = dict_append_proc (dict_aa,'t1169','新座',27891,'2014-9-24')
	
	return	dict_aa
}

// ----------------------------------------------------------------
import { MongoClient } from "https://deno.land/x/mongo@v0.32.0/mod.ts";
import { config } from "https://deno.land/x/dotenv/mod.ts"

console.log ("*** 開始 ***")
const config_env:any = config()

const user:string = config_env.user
const password:string = config_env.password
const db_name:string = config_env.db
const collection_name:string = config_env.collection

const host = user + ':' + password + '@localhost'
const port = 27017

const dict_aa = data_prepare_proc ()

const url = 'mongodb://' + host + ':' + port
console.log("Connecting to " + host + ":" + port)

const client = new MongoClient()
await client.connect(url)
const db = client.database(db_name)
const cities = db.collection(collection_name)

const deleteCount2 = await cities.deleteMany({ key:  { $ne: null } })
console.log(deleteCount2," deleted.")

for (var id in dict_aa)
	{
	const unit_aa:{[key: string]: any} = dict_aa[id] 
	const insertId = await cities.insertOne({
		key: id,
		name: unit_aa.name,
		population: unit_aa.population,
		date_mod: unit_aa.date_mod,
		})
	}

console.log ("*** 終了 ***")

// ----------------------------------------------------------------
```

```text:.env
user='scott'
password='tiger123'
db='city'
collection='saitama'
```

実行コマンド

```bash
deno run --allow-net --allow-write --allow-read --unstable mongo_create.ts
```
【GCP】請求データの設定

BigQueryで請求用のデータを見やすくできるし、分析できる。

# ドキュメント参照
BigQuery への Cloud Billing エクスポート機能を使用することで、指定した BigQuery データセットに Google Cloud の詳細な課金データ（使用量、費用予測のデータなど）を終日、自動的にエクスポートできます。これにより、BigQuery から Cloud Billing データにアクセスして、詳細な分析を行うことが可能になります。また、Google データポータルでデータを視覚化することもできます。同様の方法でデータを JSON ファイルにエクスポートすることもできます。
https://cloud.google.com/billing/docs/how-to/export-data-bigquery?hl=ja

# 手順
プロジェクト作成
↓
BigQueryで請求用のデータを作成
　データセットの作成
ラベルを2つつけた
↓
請求画面で、設定する。
作成したプロジェクトを選ぶとBilling_exportが自動で選択される。
作成をおせば完了

データが収集されるにはしばらくかかる。

# 関連記事
https://www.apps-gcp.com/biqquery-export-billinggcpdata-datastudio-visualization/
https://qiita.com/sinmetal/items/461329e924929325b23c
https://dev.classmethod.jp/articles/gcp-cost-slack-bot-notify/
https://www.qwiklabs.com/focuses/7114?locale=ja&parent=catalog
Windows 10 May 2020 UpdateでのWSL2導入手順

Windows 10の9回目の大型アップデート「May 2020 Update」でようやくWSL2が使えるようになりました。
以下はWSL2の導入、及びWSLをWSL2に切り替える手順です。

# ⚠︎注意

[「Windows 10 May 2020 Update」でブルースクリーン発生やBluetooth、IMEの不具合](https://pc.watch.impress.co.jp/docs/news/1255346.html)
のような不具合も出ています。作業を行う際はバックアップをきっちり取った方が良いです。
また、この記事を参考にしたことにより生じたあらゆる損害について筆者は一切の責任を負いません。

# 前提

* Windows 10 Pro(多分Homeでも動くが手順は違うと思う)

# Windows 10 May 2020 Update の適用
「Windows 10 May 2020 Update」`2004(Build 19041)`が適用済みでない場合
Windows Updateが降ってくるのを待つでも良いですが以下からUpdateが可能です。
https://www.microsoft.com/en-us/software-download/windows10

# Hyper-Vを無効化する
~~WSLではHyper-Vが必須でしたが、WSL2では不要になりました。~~
Docker for WindowsがWSL2を使用することでHyper-Vが不要になりました。
Hyper-Vを有効化しておくことで[gRPCのport 50051などHyper-Vが予約しているポートとバッティングしているポートを使用しようとする場合](https://github.com/docker/for-win/issues/3171)などで困ることになるので必要なければ無効化しておいた方がよさそうです。

**Powershellを管理者権限**で立ち上げ以下を実行します。

```powershell
Disable-WindowsOptionalFeature -Online -FeatureName $("Microsoft-Hyper-V")
```

# VirtualMachinePlatformとWSLを有効化する

**Powershellを管理者権限**で立ち上げ以下を実行します。

```powershell
Enable-WindowsOptionalFeature -Online -FeatureName $("VirtualMachinePlatform", "Microsoft-Windows-Subsystem-Linux")
```

# WSL2 Linux カーネル更新プログラム パッケージのインストール

以下から「WSL2 Linux カーネル更新プログラム パッケージ」をダウンロードしてきてインストールします。
https://docs.microsoft.com/ja-jp/windows/wsl/wsl2-kernel

# (既にWSLが入ってる場合)ディストリビューションの更新

WSLを既に使用してる場合はディストリビューションの更新が必要です。
**Powershell を管理者権限**で立ち上げて以下を実行します。

* WSLのディストリビューションを検索

```powershell
wsl -l -v
#  NAME            STATE           VERSION
#* Ubuntu-18.04    Running         1
```

* バージョンを2に上げたいディストリビューションを更新

```powershell
wsl --set-version Ubuntu-18.04 2
```

更新までしばらく時間がかかります。

* ディストリビューションのバージョンが「2」に上がったことを確認

```powershell
wsl -l -v
#  NAME            STATE           VERSION
#* Ubuntu-18.04    Running         2
```

# (おまけ) Docker for Windowsの設定変更

* WSL 2 based engine を有効化

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536869/30c593bd-4ce0-e826-a911-74b7d731645d.png)

* WSL INTEGRATION を有効化

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536869/0bac857d-01c3-a698-99cd-67e0054b5f3b.png)


以上で元々Docker for Windowsで動いていたDockerコンテナのWSL2での起動までは確認できました。
【GCP】コンソールのTIPS

・請求画面で、請求対象のアカウントを確認することが可能
　関連する請求アカウントを確認可能

・ホーム画面で、カスタマイズできる。
ニュースやダッシュボードの一覧に飛ぶことは可能
APIの利用状況とかひと目で見れるので、使い安い感じはある。
自分がreviewerになっているPRだけを見る

githubでレビュワーを指定してPRをレビューしてもらう運用にしていると、自分がレビュワーになっているPRどれなんだ？ってなると思います。一覧に表示してくれていれば一番良いのですが、現状そうなってないので探さなきゃいけません。

PRの一覧を表示しているときに、検索窓の中身は

```
is:open is:pr
```

となっていると思います。これを

```
is:open is:pr review-requested:@me 
```

とすると、PRのうち、自分がreviewerに指定されているものだけを見ることができます。
Elasticsearchで使うcurlのコマンド一覧

Elasticsaearchでよく使うcurlコマンドをいつも探しているのでメモ

## 前提

$HOSTNAMEでcurlができる状態

## 参考にしたページ

* [Elasticsearchで最初にぶつかるワードたち](https://qiita.com/a4_nghm/items/94ed0640ed8a15ce1592)
* [Elasticsearch API 一覧](https://medium.com/hello-elasticsearch/elasticsearch-api-83760ce1424b)
* [Elasticsearch マッピング](https://medium.com/hello-elasticsearch/elasticsearch-9a8743746467)

## コマンド

### elasticsearchの基本情報を取得

```
$ curl http://$HOSTNAME:9200
{
  "name" : "node名",
  "cluster_name" : "クラスタ名",
  "cluster_uuid" : "クラスタuuid",
  "version" : {
    "number" : "6.7.1",
    "build_flavor" : "default",
    "build_type" : "rpm",
    "build_hash" : "2f32220",
    "build_date" : "2019-04-02T15:59:27.961366Z",
    "build_snapshot" : false,
    "lucene_version" : "7.7.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}
```

### クラスタのhealthチェック

* statusがgreenが正常
* number_of_nodesはnodeの数。クラスタを組んでいる場合は対象クラスタの数と一致しているか確認する


```
curl http://$HOSTNAME:9200/_cluster/health?pretty=true
{
  "cluster_name" : "クラスタ名",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 3,
  "number_of_data_nodes" : 3,
  "active_primary_shards" : 0,
  "active_shards" : 0,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 0,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 100.0
}
```

### クラスタ間の情報の確認

* となっているのがmaster node

```
$ curl http://$HOSTNAME:9200/_cat/nodes
xx.xxx.xxx.xxx 19 32 0 0.00 0.02 0.05 mdi - {cluster_name}
xx.xxx.xxx.xxx 40 63 3 0.01 0.07 0.07 mdi - {cluster_name}
xx.xxx.xxx.xxx 13 31 1 0.00 0.02 0.05 mdi * {cluster_name}
```

### indexの一覧を取得する

```bash
$ curl http://$HOSTNAME:9200/_aliases?pretty
{
  "empty" : {
    "aliases" : { }
  },
  "index名1" : {
    "aliases" : { }
  },
  "index名2" : {
    "aliases" : { }
  }
  .
  .
}
```

### インデックスのドキュメント数を取得

```bash
$ curl http://$HOSTNAME:9200/_cat/count/{index}

{timestamp} 07:18:46 {ドキュメント数}
```

### x-packでSSL通信で取得する時のコマンド

```
$ curl -u elastic:<パスワード> https://$HOSTNAME:9200 --insecure
{
  "name" : "node名",
  "cluster_name" : "クラスタ名",
  "cluster_uuid" : "クラスタuuid",
  "version" : {
    "number" : "6.7.1",
    "build_flavor" : "default",
    "build_type" : "rpm",
    "build_hash" : "2f32220",
    "build_date" : "2019-04-02T15:59:27.961366Z",
    "build_snapshot" : false,
    "lucene_version" : "7.7.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}
```
Rustをscoop+VScodeで開発環境を整える（備忘録）

# 概要

scoopによるRust開発環境備忘録。

# 環境

- Windows 10
- scoop
- Vscode

# Rustをインストール

```
scoop install rustup
```


# VScodeプラグインをインストール／設定

プラグイン画面にて「Rust」をインストールする。

![コメント 2020-05-26 211948.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159492/b033a697-be16-0cb4-c0fc-01a9a1a480dd.jpeg)

その後、file->preferences->settingにて、「Rust-client: Rustup Path」をscoopでインストールした「rustup.exe」のパスまでを設定する。

![SharedScreenshot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159492/45ce0a71-2703-ab5d-c295-43e4dacde361.jpeg)


# 備考

scoopでは「main」backetに「rust」がありますが、「rustup」を使ってインストールした方が良いです。理由として、vscodeのプラグインが「rustup.exe」のパスを要求されるためです。「rust」の方には「rustup.exe」がありません。

# 参考

- VSCodeでRustの環境を構築しようしたらCouldn't start client Rust Language Server：[https://qiita.com/kozzzz/items/ec272b67c289454b7c87](https://qiita.com/kozzzz/items/ec272b67c289454b7c87)
DenoをVSCodeに対応させる

この前Denoをインストールして、早速VSCodeで書こうとしたのですが、モジュールのimportでエラーが発生してしまいました。
それの解決法がすでにあったので、メモ程度にここに書いておきます。私自身あまりDenoなどに詳しくないので、なにかあったら指摘していただけると幸いです。
ちなみに初投稿です(´・ω・｀)

# どうするの?
実はそのエラーを解決するための拡張機能が用意されていました。
https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno
モジュールのimportでエラーが発生したら、この拡張機能を導入してみてください。
**注意:denoland.vscode-deno以外の拡張機能がありますが(justjavac.vscode-denoなど)、それらはDeprecatedされています。必ずdenoland.vscode-denoを導入しましょう。**
基本的にはワークスペースに.vscode/settings.jsonを作成し、その中に次のように書けば動作します。

```json:settings.json
{
    "deno.enable": true
}
```

<details><summary>入れてもエラーが発生するよ！</summary>
入れたので早速importすると、以下の様なエラーが発生する場合があります。
![スクリーンショット 2020-05-28 14.56.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457036/6071272b-12a2-0bf0-4514-af96bbd93350.png)
エラー文を読むとわかりますが、これはまだコードがローカルにキャッシュされていないことを表すので、気にせず実行してください。実行時に勝手にダウンロードされます。</details>

# 設定
一応設定を解説しておきます。([ここ](https://github.com/denoland/vscode_deno)のREADME.mdをてきとうに翻訳しただけですが。)

- deno.enabled - 拡張機能を有効/無効化します。デフォルトは`true`です。
- deno.alwaysShowStatus - 常にDenoのステータスバーアイテムを表示します。デフォルトは`true`です。
- deno.importmap - インポートマップのパスです。デフォルトは`null`です。
- deno.autoFmtOnSave - 保存時に自動フォーマットを有効/無効化します。デフォルトは`false`です。(**実装されていません**)

# まとめ
![スクリーンショット 2020-05-28 15.06.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457036/0be02c73-412e-9883-6d38-cd1bea48af84.png)
やったね！これでエラーが発生しなくなったよ！ということで、VSCodeでDenoを利用する際は、`denoland.vscode-deno`をインストールしておきましょう。以上です。

# 参考
- https://scrapbox.io/deno-ja/vscode-deno
A2019で今日の日付を取得する

この記事では、A2019を使って今日の日付を取得したい場合のやりかたを説明します。

# 今日の日付は、システム変数のDateに入っている

今日の日付は、システム変数のDateに入っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/85b71f52-1ed9-e4fd-9f67-99cc2bc72097.png)

より正確に言うと、現在日時が入っているので、データとしては何時何分何秒まで入っています。

# Dateのままでは、ファイル名をつけたりメッセージに表示したりはできない

Dateは日時型のため、そのままではファイル名などに使うことはできません。

そのため、一度「日時」アクション配下の「文字列に変換」を使って好きな、文字列のフォーマットに変換する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/046f6d41-be14-7a9b-dac9-72e5737dc47e.png)

使い方は以下のとおりです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/8c0e36f8-9644-87ff-12b8-ef1b1ba4103e.png)

上記のBotを実行すると、このように日付をメッセージ表示することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/f5cdd6f0-f373-328d-0c18-9f70e998d00f.png)

上記の処理はメッセージに表示する処理ですが、同じ要領でファイルやフォルダの名前に日付を入れることもできます。

#注意点

開発に慣れている人には常識かもしれないですが、**MMは大文字、ddは小文字じゃないとだめ**です。

MMを小文字にすると、mm=現在時刻の分数が出てきてしまうため。

ddを大文字にすると、月の日付じゃなく「今日が１年の何番目の日か」（2020年5月28日だったら149）が出てきます。。。

yyまたはyyyyは大文字でも小文字でも大丈夫です。

#もっと詳しく知りたい人にオススメのリンク

RPA Bot さんの記事

https://qiita.com/RPAbot/items/04d82c204450c71995d6

ベンダー公式ドキュメントサイト（日時型のフォーマットについて）
https://docs.automationanywhere.com/bundle/enterprise-v2019/page/enterprise-cloud/topics/aae-client/bot-creator/commands/cloud-date-time-formats.html
Yellowfinのv9ダッシュボードでレポートの値からフィルターを制御する

#概要
前回の記事ではレポートの値をフォームに入れてPOSTしましたが、今回は応用でレポートの値でフィルターを効かせるようにします。
![filter.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223443/ebb993e2-3a85-67ac-16ea-5b6b1dde36d1.gif)
##表示するレポートを選ぶ
今回は、事前にフィルター付きのレポートを用意します。
ここでは、YellowfinのチュートリアルデータであるSkiTeamのデータにあるCamp Performanceのレポートを元にしてCamp Regionのカラムをフィルターにセットします。(演算子:一覧に含む、値:ユーザープロンプト、フィルターの書式→表示→説明でフィルターの名前をfilterRegionに変更しています)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223443/79a14a3e-544a-5209-23b9-603b898411b3.png)
##フィルターの入力スタイル
下記のように「一覧から値を選択」と表示タイプを「一覧」にします。他の表示方法だとJavascriptでフィルターとレポートの同期ができませんでした・・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223443/5c1789d6-cf5f-947a-a747-a989a0b7dea8.png)
##ダッシュボードの作成
ダッシュボードを作成し、先程のレポートをドラッグアンドドロップで配置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223443/3651bde8-5809-fcbd-8b6b-ab433f65be9a.png)
フィルターも同様に、ドラッグアンドドロップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223443/12741d89-3edb-ac4d-247e-77d85798a589.png)
+フィルターボタンを押下し、ポップアップでレポートで作成したフィルターを紐つけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223443/cdb0fb0b-8f85-473c-df79-e0014fcca100.png)
##コードモードの編集
ここからコードモードに変更し、HTMLタブを見ていきます。
###HTMLタブ
大体こんな感じになっていると思います。report-outputタグのnameがレポート名になっています。

```html:dashboard.html
<canvas-area xmlns="http://www.w3.org/1999/xhtml" canvas-uuid="eecfc9c0-fd84-4c5f-a4f4-692b6e8ab85b">
    <report-output widget-uuid="4956314f-eac8-4563-8d65-b394fbb1ae53" report-uuid="db89f236-f4fb-4f3d-852e-9ae2e43f41aa" height="300" top="0" left="353" name="for qiita, Camp Performance" width="400" display-type="TABLE" style="z-index: 1;"></report-output>
    <filter-list widget-uuid="8d08b89d-d2a4-494c-8794-e7d9131e96e6" filter-list-uuid="b15da1ed-9c9b-4e00-9e5c-3ed1fca8dcb2" width="280" height="382" top="0" left="0" hide-control-panel="false" dash-filter-auto-run="false" hide-reset-link="false" name="フィルター一覧(縦)" style="z-index: 2;"></filter-list>
</canvas-area>
```
###JSタブ
レポート変数にhtmlのレポートのnameを指定し、フィルター名はレポート作成時に設定した表示名をthis.apis.filters.getFilterで指定します。


```javascript:jstab.js
let report = this.apis.canvas.select('for qiita, Camp Performance');

/* Use APIs to apply filters */
report.addEventListener('click', (event) => {
	let $row = $(event.target).closest('tr');
	let demographicFilter = this.apis.filters.getFilter('filterRegion');
	let text = $row.find('td').get(0).innerText;
//ちなみにですが、ボタンのクリックイベントにしておいて、あらかじめtext変数を配列にしておけば、複数のフィルターの値で絞り込みができるようになります。
	//let text = ['Europe', 'North America'];

    //this.apis.filters.setFilterValue(demographicFilter.get('filterId'), text);旧API
    demographicFilter.setValue(text);
    this.apis.filters.applyFilters();
})
```
##こんな感じで
レポートの行をクリックした時にイベントが起動して、その行の一番左の値をフィルターに指定するダッシュボードが完成しました。これでより直感的なダッシュボードが作成できるようになるのではないでしょうか。
※一度完成したダッシュボードでも元のレポートやフィルターを変更したり更新したりすると、うまく動かなくなることがあるようです、、、この辺はアップデート待ちなんでしょうかね。。
未経験なのにプログラミングが必要な部署に放り込まれた人が「そこそこの成果」を出すために

#この記事のターゲット

・社内でベテランの立ち位置（30代以降～）になったにもかかわらず未経験の開発部署に配属された
・とりあえず足を引っ張らない程度に働けるようになりたい
・日系の比較的年功序列職のある組織に所属している

#私の立ち位置
　30代にして開発部署に配属される。1年余り主にフロントエンド（JavascriptやJQuery）での開発に携わる。



#本題に入る前に
　近年プログラミングやウェブデザインが「稼げる」と言われている。プログラミングスクールや、エンジニアのオンラインサロンも目に留まるようになってきた。
　確かに、プログラミングを学んで短期で集中して身に着ければ即戦力として就職できるし、現状ではフリーランスとして働いていても案件に困ることはあまりないようだ。
　しかし、これは私の持論であるが、全員がプログラミングに適性があるわけではない。それは地頭の良し悪しではなくその人の持つ特性の問題であり「身につかないから人として劣っている」という問題ではない。
　さて、「未経験なのに開発部署に配属されてしまう」ことは、特にその人が左遷されたわけでも、リストラ候補になったわけでなくても十分起こり得ます。特に日系企業の場合、全体最適を考えた結果個々人の部分最適を無視することはどこででもあります。
　そういう時にとる選択肢としては「任期（2年程度）が終わるまで嵐が過ぎるのを待つ」「開き直って興味を持って頑張ってみる」ということがあります。
　ただ、一回り年下でも優秀な人達がいるような部署で「未経験だけど思いっきり出来るようになってやろう！」と思える人ばかりではないと思います。

　今回は、「そこそこのアウトプット」「そこそこの成果」を出せるようになるためのコツをまとめました。


##2年で使い物になるレベルになると思っておく
爆速で成長しようと思っている人から見たら2年なんて非常に気の長い話ですが、未経験な上にとくに希望してなかった配属の場合、無理したら心を病みます。心を病んでしまったら誰も幸せになりません。
とりあえず「2年」と考えましょう。そういうつもりでコツコツ積み上げて、結果1年で一人前になれたなら自分で自分をほめてあげればいいですし、周囲が積極的にOJT等してくれた場合、もっと早くに一人前になります。

多分無理のある人事なので、周囲もあなたにはエースになることを求めていないと思います。


##後輩に教えてもらうことを恥ずかしいと思わない、敬意を抱く
当然あなたは未経験ですので、年齢が一回り下、役職も下であっても後輩の方が優秀ということは普通にあります。ポンと放り込まれたあなたと違って、何年も（しかも多くの場合は積極的に）開発を行ってきたので、それは当然です。

たとえ相手が部下であっても先輩と接するように敬意を持って接して話を聞きましょう。勿論増長して態度でかくなる後輩はムカつくかもしれませんが、何もわざわざ自分からマウント取りに行くようなみっともないことをする必要はありません。

そういう心構えでいるならば少なくとも嫌われることはないし、「聞きやすい」「教えやすい」職場環境になると思います。


##最低限のLinuxコマンドは何が何でも使えるようになっておく
もしかしたら、これまでのめぐり合わせ次第ではLinuxについて「lsって何ですか？」「絶対パスと相対パスってどう書き分ければいいのですか？」みたいなレベルかもしれません。
はっきり言います。プログラミングに手を付けるのは少々遅くてもいいので、コマンドラインの操作には早いうちに慣れてください。何もシェル芸みたいなことや、grepを使いこなしたような操作まで出来なくてもいいので、カレントディレクトリを移動したり、ファイルのコピーやら削除などの基本的な操作は何が何でもできるようになりましょう。
少し高度な操作は覚えてなくても調べて実行できるくらいにはなりましょう。
これができないと最初から仕事は回りませんし、何か周囲に質問するときもぎこちない動きしか出来なかったら教える側もしんどいです。
また、開発部署があるということは、あなたの組織は何らかの技術系の会社に違いありません。実際にLinuxを業務レベルで使用した経験は、今後たとえ他の部署に回ったとしても必要になってくることは多いです。




以上、未経験のベテランが開発部署に放り込まれた時の振る舞いについてまとめました。気が向いたら更新します。
あなたが、その後プログラミングにはまって開発部署でガンガン成果出すのか、それとも次の人事異動でよその部署に行くのかは会社の都合や部署の人間関係、あなたの趣向によって変わると思います。

ただ、せっかく配属されてしまったのでしたらとりあえず「そこそこの成果」くらいは残しましょう。
Twilio Video SDKを使った時にgetUserMediaが複数回走ってしまう時の対応方法

Twilio Video SDKを使った時に、connectを呼ぶたびに`getUserMedia`が走ってユーザーに許可を求めてしまったのでその対処方法をメモ。

## 環境
- Twilio Video SDK v2.5

## やりたかったこと
最初に`navigator.mediaDevices.getUserMedia()`を実行しstreamを取得して、以後それを使いまわしたかった。

## 起こったこと
Twilio.video.connectを呼ぶたびに、`getUserMedia`が走って、ユーザーに許可を求めてしまう。

## 原因
Twilio.video.connectを実行した時、デフォルトだと自動でstreamを取得し、そのあとのstreamの管理も行ってくれる。

[APIドキュメントはこちら](https://media.twiliocdn.com/sdk/js/video/releases/2.5.0/docs/)

## 対応方法
`navigator.mediaDevices.getUserMedia`で取得した、streamをconnectにオプションとして渡す。

```js

navigator.mediaDevices.getUserMedia({
  audio: true,
  video: true
}).then(function(mediaStream) {
  return Video.connect(token, {
    name: 'my-cool-room',
    tracks: mediaStream.getTracks() // tracksでstreamを渡す
  });
}).then(function(room) {
  room.on('participantConnected', function(participant) {
    console.log(participant.identity + ' has connected');
  });

  room.once('disconnected', function() {
    console.log('You left the Room:', room.name);
  });
}).catch(error => {
  console.log('Could not connect to the Room:', error.message);
});
```
iOSの各種シミュレーターをfzfで選んで起動する

プリミティブな方法だと

```console
$ xcrun simctl list
```

で、起動したいシミュレーターのUUIDを確認して

```console
$ xcrun instruments -w 208E5166-9C5D-4CA5-A9DE-529AD562D311 # iPhone 11 Pro Max
```

とすると指定したシミュレーターが起動するのだが、Xcodeをアプデするとシミュレーターも更新されてしまうので、以前書き留めておいたUUIDが使えなくなる。また調べないといけなくてめんどくさい。

ということで、インクリメンタルに端末名で検索してEnterで起動するようにした。

`.zshrc` に以下を追記

```zsh:.zshrc
function simc() {
  xcrun instruments -w $(xcrun simctl list | grep -v unavailable | grep -E "^\s" | grep -v ":" | fzf  | grep -oE "\((.+?)\)" | grep -oE ".{20,}" | head -n1 | perl -pe "s/(\(|\))//g" )
}
```

fzfが入ってないなら以下を実行。

```console
$ brew install fzf
```

設定を読み込み直して実行。

```console
source ~/.zshrc
```

![simc.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4194/444bb609-a812-bde8-e203-16183c726eb8.gif)
flutter:画像の横並び（Row）で自動的に改行させる

# やりたいこと


複数の画像を横並びで表示させる際、画面右側まで達したら自動的に改行させたい


# 画像の表示方法

flutterでページ内に複数の画像を並べて表示
https://qiita.com/kenichiro-yamato/items/3ea42f7a6cd42a8f4236
を参照。



# Row実装

```dart
      body: Row(
        children: <Widget>[
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/2005/Mountains_Rocks_Lake_2020_Landscape_High_Quality_Photo_1366x768.jpg', width: 125,),
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/1711/Cute_Small_Chicken_2017_Animal_HD_Wallpaper_1366x768.jpg', width: 125,),
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/1501/Fighter_Jets-Military_HD_Wallpaper_1366x768.jpg', width: 125,),
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/1806/FIFA_World_Cup_2018_Peru_Christian_Cueva_1366x768.jpg', width: 125,),
        ],
      ),
```


# 自動で改行しないと、どうなるか？

この例では、3枚までは表示可能だが、4枚になると、画面右側に「工事中のようなマーク」が表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/89612104-b918-3a27-9ec1-81460f7f47e7.png)


# 自動で改行させる方法

RowをWrapに変更する。

```dart
      body: Row(
```

```dart
      body: Wrap(
```


すると、4枚目が自動で改行される。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/79929986-33d0-0ec6-4fb8-5ea6b22313f4.png)



# 完成形 main.dart

```dart

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Wrap(
        children: <Widget>[
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/2005/Mountains_Rocks_Lake_2020_Landscape_High_Quality_Photo_1366x768.jpg', width: 125,),
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/1711/Cute_Small_Chicken_2017_Animal_HD_Wallpaper_1366x768.jpg', width: 125,),
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/1501/Fighter_Jets-Military_HD_Wallpaper_1366x768.jpg', width: 125,),
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/1806/FIFA_World_Cup_2018_Peru_Christian_Cueva_1366x768.jpg', width: 125,),
        ],
      ),
    );
  }
}

```
AWSメモ

# 1-2 AWSインフラストラクチャの概要
* アベイラビリティゾーン：AZ-dは使用してない？
* グローバルサービス：Route53、IAM、CloudFront
* リージョンサービス：VPC、DynamoDB、Lambda
* アベイラビリティサービス：サブネット、EC2、RDS

# 1-4 ネットワークサービス
## VPCの主なサービス
* VPC
* サブネット
    * パブリック：ルートテーブルの0.0.0.0/0(GWへの通信)のTargetがIGWになっている。
    * プライベート：↑とは異なる。
* ルートテーブル
* IGW
* Elastic IP
* エンドポイント
    * ゲートウェイ型はS3 or DynamoDB。それ以外はインターフェイス型。
* NATゲートウェイ
    * プライベートサブネットからインターネットに接続する際に使用。
    * NATゲートウェイを使用しない際はNATインスタンスを構築する。冗長化が必要。
    * Elastic IPが必要。
* ピアリング接続
    * 異なるAWSアカウント間でも接続可能。実際やってる？

## セキュリティの主なサービス
* セキュリティグループ
    * インスタンス単位
* ネットワークACL
    * サブネット単位

## ELB
### Connection Draining
* バックエンドインスタンスの処理が終了してから登録解除する

### クロスゾーン負荷分散
* 各AZのバックエンドインスタンスに均等に割り振り
* ALBでは常に有効

## Auto Scaling
使用してない？

## Route53
* パブリックホストゾーンとプライベートホストゾーンがあって、プライベートホストゾーンは.local

## Direct Connect
使用してない？

## 仮想プライベートゲートウェイ
使用してない？

## CloudFront
* esaを見れば理解できるかも。ディストリビューション、オリジン、エッジロケーション
* オリジンとしてS3を指定する事が多い気がする。
* SSL証明書はどうやって差し替えるんだろう？
* 署名付きURL/カスタムエラーページ/地域制限/ストリーミング配信らへんのパラメータ深掘り

# 1-5 コンピューティングサービス
## EMR
* 大量データを迅速に処理するWebサービス

## ECS
使用してない？

## VM Import/Export
使用してない？

# 1-6 ストレージサービス
## S3
* 署名付きURL：一定時間アクセスを許可するURL
* マルチパートアップロード：大容量のオブジェクトを分割してアップロードする機能
* クロスリージョンレプリケーション：別のリージョンにオブジェクトを自動的に複製する機能
「GSuiteアカウントを用いたAWSへのシングルサインオン」をやってみた

##概要
タイトルどおりです。基本的に[公式ブログ](https://aws.amazon.com/jp/blogs/startup/techblog-saml-gsuite/)通りにやれば出来ました。

##今回詰まった点：
「Step 3: AWS アカウントで IdP の作成」で
IDプロバイダーをブラウザから登録しようと操作すると「ServerError:OK」というエラーメッセージが出て先に進めなかった。

##対応：
CLIで「aws iam create-saml-provider --saml-metadata-document file://xmlファイル名 --name 名前」で登録できた。
[参考](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_providers_create_saml.html#idp-create-identityprovider-CLIAPI)

###おまけ：
Step5に「Role については Role ARN と ID プロバイダーの ARN をコンマ区切りで記載する」とある。
この作業がユーザごとに必要だったのでスプレッドシート＋GASでとりあえず自動化してみた。


```GAS
var userKey;
var resource =
      {
        "customSchemas": {
          "AWS": {
            "Session_Duration": 43200,
            "Role": [
              {
                "type": "work",
                "value": "（Role arnを記載）,(provider arnを記載)"
              }
            ]
          }
        }
      }

function setSAMLInfo(){
  var Assheet = SpreadsheetApp.getActiveSpreadsheet()
  var Asheet = Assheet.getSheetByName("AWS");
  try{
    var data = Asheet.getDataRange().getValues();
    for(i=1;i<data.length;i++){
      var user = AdminDirectory.Users.patch(resource, data[i][0])
    }
  }  catch(e){
    Logger.log(e);
  }
}
```
[React]create-react-appを使わずに環境構築 ~設定ファイル編~

# はじめに
この記事では、以前書いた[[React][mac]create-react-appを使わずに環境構築](https://qiita.com/Masanori_N/items/d3de0fa1029c30e4358e)で作成した設定ファイルの記述について、簡単に説明していきます。

## .babelrc

````
// Babelに関する設定
{
 // Presentsというプラグインのプリセット
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}
````

## .eslintrc.json


````js:.eslintrc.json
{
  "parser": "babel-eslint",
  // ESLintがされる環境の指定 
  "env": {
    // ブラウザーでES6を使用する
    "browser": true,
    "es6": true
  },
  // パーサーの設定
  "parserOptions": {
    // ES6のmodulesを使用する
    "sourceType": "module",
    // JS言語の追加機能の指定
    "ecmaFeatures": {
      // 分割代入を有効にする
      "experimentalObjectRestSpread": true,
      // JSXを有効にする
      "jsx": true
    }
  },
  // ルールのデフォルトを指定
  "extends": ["eslint:recommended", "plugin:react/recommended"],
  // React用のプラグインを指定
  "plugins": ["react"],
  // ルールの設定（ルールのデフォルトと違う設定や、デフォルトにない項目を追加などをする）
  "rules": {
    // console.logを使えるようにする
    "no-console": "off"
  },
  "settings": {
    "react": {
      "version": "detect"
    }
  }
}
````

## webpack.config.js

````webpack.config.js
module.exports = {
  // アプリ起動時に動作すべきJSのソースファイルを指定(複数のファイルを指定可能)
  entry: {
    app: "./src/index.js"
  },
  // 出力されるファイル名、パスを指定
  output: {
    // 絶対パスで指定する必要があるためカレントディレクトリを表す __dirname と連結している
    path: __dirname + '/public/js',
    // [name] と書くと上記 entry で付けたキー(app)が使われる
    filename: "[name].js"
  },
    // webpack-dev-serverの設定
    devServer: {
    // webで公開するディレクトリー(index.htmlがある)のパス
    contentBase: __dirname + '/public',
    // 開発サーバーが使用するポート番号
    port: 8080,
    // webpackが出力するJSのあるディレクトリーが contentBase と異なる場合に指定
    publicPath: '/js/'
  },
  // デバックできるようにmapファイルを作成する指示
  devtool: "eval-source-map",
  mode: 'development',
  // ファイルの種類ごとにloaderを指定
  // test: に書かれている正規表現とマッチする場合、そのオブジェクトに書かれた loader が動く
  module: {
    rules: [{
      // ESLint の loader　を実行
      test: /\.js$/,
      enforce: "pre",
      exclude: /node_modules/,
      loader: "eslint-loader"
    }, {
      // css-loader , style-loader を実行
      test: /\.css$/,
      loader: ["style-loader","css-loader"]
    }, {
      // Babel の loader を実行
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
     }]
  }
};
````

# おわり
最後まで見て頂き、ありがとうございました。
マイグレーションファイルがダブっちまった

## 近況報告
　絶賛就活中でございます。最近やっているのは習慣化ですね。最近，英語と筋トレを習慣化させることができました。いきなり英語は飽きると思ったので，Gacktの母音発音のyoutubeをみて簡単な文を音読しています。考えが改まったことがひとつ，Google翻訳ってあるじゃないですか。あれ，全然翻訳してくれないからゴミだと昔は思っていたんですけど，実際は自身の発音がゴミだったってことがわかりましたw　筋トレは腹筋スクワットメインの運動を自重かつ強度をあげて２０分だけ行なっています。腹筋が生まれて初めて横以外に割れそうな勢いです。そしてここ数日で始めたのは朝型転換です。ここ二ヶ月日付が変わったらアマゾンなプライムでビデオ見まくっていたので，生活習慣の改善として行なっています。

##今回のお題
　**マイグレーションファイルがダブってる**
 　始めたての初心者がいつの間にかハマるやつですね！・・・はい，やらかしました。
　⇨**解決策は片方を消す。以上。**

##マイグレーションファイル
●マイグレーションファイルは噛み砕くとテーブルの設計図です。
　rails db:migrateの際にテーブルを作成更新するときに利用します。一度利用されたマイグレーションファイルはテーブルを再度更新，生成しない限り用いることはありません。実際削除しても問題ありません。

●本当に削除していいの？
　**そこに書かれている情報を二度と使わないのであれば**消してもいいよ。
　開発においてテーブルの変更はなんども行われます。そのときにマイグレーションファイルがないと以前はあったとしてもパソコンがテーブルを読み取れなくてエラーを起こします。また，開発環境で用いたテーブルは本番環境でも使えるわけではなく，本番環境のDBを設置して再度テーブルを組み立てることが多いので，本番の段階でマイグレーションファイルがないのは一大事なわけです。長くなりましたが結論は**もう使わなくてもほっとけ**です。

●ダブった場合
　マイグレーションファイルがダブっている場合も消したらテーブルが作成できなくなると心配になります（自分はなった）。ただ、この場合は同じ設計書が二枚あるだけなので，一枚になっても変わりませんし，マイグレーションファイルの数だけテーブルができるわけではないので安心して片方消してください。

##最後に

内定が欲しい！　エンジニアライフを早く堪能したい！
Rails チュートリアルをやってみる ch1

# やったこと

- ローカル開発環境の準備
- CI/CDの準備
- 第一章のHello World
- 公式Docの確認

# なぜやったのか
- 実際の開発フローに近い段取りをするため

# 次にやること
- Ch2
- GitLab CI/CD を設定した方法についてQiitaの記事にまとめる
- RuboCop, RSpec, Cypress について調べて導入する
- 『初めての自動テスト』を読み始める

ようやく開発のスタートラインについた感じ。
余力がないので、後になるけど調べたこととか、実際にやってみた内容をまとめて記事にしてアウトプットにすると勉強になるし、誰かの役に立つかもしれないから頑張ってやる。
【laravel】「現在のパスワード」をチェックするバリデーション

# 概要
パスワードの変更や特別な操作の際に仕様する「現在のパスワード」を入力してから実行する作業に関する投稿です。


# 考察
下図のような「現在のパスワード」を確認してから「新しいパスワード」を登録する方法の例です。

![screenshot_20200528_131703.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513331/2cb67d07-425d-b804-afe2-c95ff063ddf5.png)

現在のパスワードを確認するだけなら、laravelファサードの`Hash::check()`やPHPの`password_verify()`をコントローラーに記述して実行できます。
ですが、そこにパスワードのバリデーションを関連付けると両方の処理を同時に実行できないという問題が生じます。
これはlaravelのバリデーションが、`値が異なればerrorをreturnしている`からです。
もちろん処理だけなら実行できますが、ユーザーにエラーの原因が見えにくくなり不親切です。


# バリデーションルールを作成する
上記の問題を解決するには「現在のパスワード」をバリデーションルールとして作成すれば解決できます。
「現在のパスワード」を確認するという独自の検証ルールを作成することで二度手間になっていた作業を一度で完結できるようになります。

詳細については以下をご参考ください。
[【laravel】ruleオブジェクトによる検証ルールの追加](https://qiita.com/gone0021/items/7374293c270a99bbf6d8#%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E6%88%90)

## バリデーションルールの作成
ここでは現在のパスワードを検証するために`Rules`でCurrentというバリデーションルールを作成します。
`Rules`は`passes()`がtrueならバリデーションを通過し、falseなら`message()`を返します。

まずはログインしているアカウントのパスワードを取得するために`Auth()`でパスワードを取得します。
そして`Hash()`のcheckメソッドで入力されたパスワードと現在のパスワードを検証します。

```php:Current.php
public function passes($attribute, $value)
{
  $pass = Auth::user()->password;
  return (Hash::check($value, $pass));
}

public function message()
{
  return 'パスワードが一致しません';
}
```

## バリデーションの実行
バリデーションルールに作成した`Current`を記述します。
これであとはコントローラーに設定すれば完了です。
新しいパスワードのバリデーションルールはRegisterコントローラーからのコピペです。

```php:.php
'current_password' => new Current(),
'password' => ['string', 'min:8', 'confirmed',],
```

# 参考
[Laravel 6.x バリデーション / カスタムバリデーションルール]
(https://readouble.com/laravel/6.x/ja/validation.html#rule-alpha-num)
[PHP / password_verify](https://www.php.net/manual/ja/function.password-verify.php)
vueでチェックボックス全選択の作り方

#概要
タイトルの通り、以下のようなチェックボックスを全て選択するチェックボックスを実装する方法
![AGDRec.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83103/824ae070-0cce-9279-66fb-1f5aaaab4209.gif)


#コード
```vue:テンプレート側
<el-row :gutter="24">
  <el-col :span="21" class="disability_name_area_allcheck"
    ><el-checkbox
      v-model="checkAll"
      :indeterminate="isIndeterminate"
      :disabled="!selectRireki.isEditable"
      @change="checkAllObstacles"
      >すべて選択</el-checkbox
    >
  </el-col>
</el-row>
<el-row :gutter="24">
  <el-col :span="24" class="disability_name_area">
    <original-check-list
      v-model="selectedDisabilityCertificateData.body_disability_name"
      item-physical-name="body_disability_name"
      item-display-name=" "
      :option-list="obstaclesList"
      :input-required="false"
      :disabled-condition="!selectRireki.isEditable"
    ></original-check-list>
  </el-col>
</el-row>

```

```vue:スクリプト側
private isIndeterminate: boolean = false;
private checkAll: boolean = false;

checkAllObstacles(val: boolean) {
  if (!this.selectedDisabilityCertificateData) {
    return;
  }
  this.selectedDisabilityCertificateData.body_disability_name = val
    ? this.getObstaclesListKeys()
    : [];
  this.isIndeterminate = false;
}

@Watch("selectedDisabilityCertificateData.body_disability_name")
checkedObstaclesChange(value: Array<boolean>) {
  let checkedCount = value.length;
  this.checkAll = checkedCount === this.obstaclesList.length;
  this.isIndeterminate = checkedCount > 0 && checkedCount < this.obstaclesList.length;
}
```
Laravel Echo Server 【Error: There is already a server running! Use the option '--force' to stop it and start another one.】でサーバーが起動しない時の対処法

Laravel Echo Serverで下記のエラーによりサーバーが起動しない時の対処方です。

```
Error: There is already a server running! Use the option '--force' to stop it and start another one.
```
## laravel-echo-server.lockファイルを削除
<img width="287" alt="スクリーンショット 2020-05-28 11.00.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/e869db31-1780-6fbe-1df7-0c18ed195cf3.png">

larave-echo-server.lockを一度削除し、再起動することで無事Laravel Echo Serverの起動ができました。

```
L A R A V E L  E C H O  S E R V E R

version 1.6.2

⚠ Starting server in DEV mode...

✔  Running at localhost on port 6001
✔  Channels are ready.
✔  Listening for http events...
✔  Listening for redis events...

Server ready!
```
Docker Rails 起動しなくなった

#前提
DockerでRails環境を構築し、突然コンテナが起動しないくなった原因と解決方法について記述します。 

#本題
dockerのアップデート終了後にdocker-compose up -dで立ち上げても一瞬で終了してしまうことがありました。

#原因
すでにサーバーが起動していると認識していたからでした。

まずは、ログを確認します。

```
$ docker-compose up
```
確認すると、、、

```
#省略
　・
　・
　・
db_1               | 2020-05-28T04:13:02.167787Z 0 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
db_1               | 2020-05-28T04:13:02.207302Z 0 [Note] InnoDB: Buffer pool(s) load completed at 200528  4:13:02
db_1               | 2020-05-28T04:13:02.234813Z 0 [Note] Event Scheduler: Loaded 0 events
db_1               | 2020-05-28T04:13:02.235265Z 0 [Note] mysqld: ready for connections.
db_1               | Version: '5.7.30'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
web_1              | => Booting Puma
web_1              | => Rails 5.2.3 application starting in development 
web_1              | => Run `rails server -h` for more startup options
web_1              | A server is already running. Check /app/tmp/pids/server.pid.
web_1              | Exiting
```
上記のように、<code>A server is already running</code>となっており、サーバーがすでに立ち上がっているから終了してしまっていることがわかります。
tmp/pids/server.pidというファイルが原因となってます。
確認してみると、、、

```
$ cat tmp/pids/server.pid
1
```
この１という数字はRails ServerのPID（Process ID）となります。
Linuxでは各プロセスにIDをつけて管理しています。
またDockerでは, プロセスIDが1であるプロセスが終了した場合、コンテナも終了するようになっているとのことです。



#解決方法

```
$ rm tmp/pids/server.pid
```
上記でtmp/pids/server.pidを削除後、再度立ち上げると無事に立ち上がりました！

```
$ docker-compose up -d
```

毎回 rm tmp/pids/server.pid するのも手間であるため、docker-compose.ymlを修正しました。

```docker-compose.yml
#変更前
version: '3'
services:
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app
    ports:
      - 3000:3000
    depends_on:
      - db
    tty: true
    stdin_open: true
    environment:
    - "SELENIUM_DRIVER_URL=http://selenium_chrome:4444/wd/hub"
```

```docker-compose.yml
#変更後
version: '3'
services:
  web:
    build: .
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app
    ports:
      - 3000:3000
    depends_on:
      - db
    tty: true
    stdin_open: true
    environment:
    - "SELENIUM_DRIVER_URL=http://selenium_chrome:4444/wd/hub"
```
以上です。
ブラウザバック禁止

* ブラウザの戻るを禁止

```js
$(function(){
    history.pushState(null, null, null);
    window.addEventListener('popstate', (e) => {
        history.pushState(null, null, null);
    });
});
```

* chromeだと、ページを読み込んだ直後の状態ではブラウザバックでのpopstateイベントが発火しない模様。<br>
画面クリックなど、ユーザーが何かしらアクションをしたら動作する。
* 「確認画面 → <登録処理> → 詳細画面」の後、戻られた場合はgetで必須パラメータチェックで対応とする。
BeanStalk

#Beanstalk
[初心者向け]AWS Elastic Beanstalk
https://qiita.com/yShig/items/2120bba6649321623cad

##Elastic Beanstalk 環境へのアプリケーションのデプロイ
* 新規インスタンス
    * イミュータブル
    * ブルーグリーン
* 既存インスタンス
    * ローリング
    * ワンス
    * バッチ