OmniAICreator/Qiita-1.07M huggingface dataset:
SQLでできない事をやってみる（その2：AggregateByKey）

#はじめに

　SparkでSQLで出来る事をあえてLow-LevelなAPIで書いているケースが
割合多かったので、SQLでできない事をSparkのヘタなScala例として記載。

#例

　同一UserIDについて、各座標の合計とそのユークリッド距離をID順に計算し、ユークリッド距離/その点数の合計を計算し、点数の多い順に並べる。
　例はspark-testing-baseを使ってUnitTestチックに挑戦しています。（厳密にはSQLでも出来るんだけど、サブクエリを書かないといけないものを入れています。）

```scala:testAggregateBy.scala
import com.holdenkarau.spark.testing.{DataFrameSuiteBase, DatasetSuiteBase, RDDComparisons, SharedSparkContext}
import org.scalatest.FunSuite
import org.apache.spark.sql.{Dataset, Row, SparkSession}

/* 入出力クラス */
case class TestLog(userID:String,Location:String, Id:Int, x:Int,y:Int)
case class calcResult(actionNum:Int,distSum:Double,distAvg:Double)

class testAggregateBy extends FunSuite with DatasetSuiteBase with Serializable {

  test("aggregateByTest") {
    val spark = SparkSession.builder().master("local").getOrCreate()

    import spark.implicits._

    /* 入力データ */
    val testData=
      Seq(
        TestLog("AAA", "公園1", 1, 360,120),
        TestLog("AAA", "公園2", 2, 180,150),
        TestLog("AAA", "公園3", 5, 360,40),
        TestLog("BBB", "公園4", 7, 360,30),
        TestLog("BBB", "店2", 8, 0,50)
      )

    /* 出力データ */
    val result =Seq(
      calcResult(
        3,
        testAggregateMain.calcDist(360,120,180,150)
          + testAggregateMain.calcDist(360,40,180,150),
        (testAggregateMain.calcDist(360,120,180,150)
          + testAggregateMain.calcDist(360,40,180,150)) / 3
      ),
      calcResult(
        2,
        testAggregateMain.calcDist(360,30,0,50),
        testAggregateMain.calcDist(360,30,0,50) / 2
      )
    )

    val result2 = result.toDS()
    val data = sc.parallelize(testData).toDS()
    val ans3 = testAggregateMain.aggMain(data,spark)
　　
　　/* 結果比較 */
    assertDatasetEquals(ans3, result2)


  }

}
```
```scala:testAggregateByMain.scala
import org.apache.spark.sql.{Dataset, Row, SparkSession}

object testAggregateMain {

  /* ユークリッド距離の計算 */
  def calcDist(x1:Int,y1:Int,x2:Int,y2:Int):Double = Math.sqrt(Math.pow((x1 - x2),2) + Math.pow((y1 - y2),2))

 /* ユーザ単位の距離及び座標点の数の合計を算出 */
  def calcKPI (x:TestLog,y:List[TestLog]):(Int,Double) = {
    if (y.isEmpty) (1,0)
    else (1 + calcKPI(y.head,y.tail)._1,
      calcDist(x.x,x.y,y.head.x,y.head.y)+calcKPI(y.head,y.tail)._2)
  }

  /* 同一パーティション内の計算 データ量が少ない時は1パーティションで計算される。*/
  def seqOp(x:calcResult,y:Iterable[TestLog]):calcResult = {
    val allData = y.toList.sortWith((l1,l2) => l1.Id < l2.Id)
    val ans = calcKPI(allData.head,allData.tail)
    calcResult(ans._1, ans._2,ans._2 / ans._1)
  }

  /* 複数のパーティション内の計算結果のマージ方法 データ量が少ない時は実行されない？ */
  def combOp(x:calcResult,y:calcResult):calcResult =
    calcResult(x.actionNum + y.actionNum,x.distSum + y.distSum,(x.distSum + y.distSum) / (x.actionNum + y.actionNum))

 /* 処理本体 */
  def aggMain(input:Dataset[TestLog],spark:SparkSession):Dataset[calcResult] = {
    import spark.implicits._
    input.rdd.map(x => (x.userID,x))
      .groupByKey()
      .aggregateByKey(calcResult(0,0,0))(seqOp,combOp)
      .values
      .toDS
      .sort($"actionNum".desc)

  }

}
```
#引っかかったところ

・ZeroValueの考え方
・SepOpとCombOpの違い
・Task not Serializable(ClassがSerializableになってないので）
【CPUの創りかた】74HC74（フリップフロップ）メモ

# メモ

- クロックをHにするタイミングのD（入力）の状態を保持する
- PRとCLRは常にHにしておく
- 保持したあとはD（入力）の値によらず、保持じた内容を出力する
    - 	「参考」の解説サイトが分かりやすい

![IMG_6069.JPG](https://qiita-image-store.s3.amazonaws.com/0/50690/d37f02fb-d9fa-f8d5-b293-833eca2bb725.jpeg)


# 参考
「74HC74」の解説 - しなぷすのハード製作記 https://synapse.kyoto/glossary/glossary.php?word=74HC74

TC74HC74AP/AF https://www.marutsu.co.jp/contents/shop/marutsu/datasheet/TC74HC74A.pdf
Google App Engine のGo 1.11 runtimeで"cannot import internal package"エラーが解消された

掲題の通りです。

既存のGo1.9までのRuntimeでは、depなどを使って、
`vendor`ディレクトリ以下に`google.golang.org/appengine`パッケージが
存在する状態だと、`gcloud app deploy`コマンドが失敗する現象がありました。

[GitHubのIssue](https://github.com/golang/appengine/issues/106)
Qiitaにも記事あり => [gcloud app deploy で cannot import internal package エラー](https://qiita.com/najeira/items/02eca8357c58d1460a51)

自分もハマったのですが、GoのRuntimeを1.11にすれば直ります。

### （参考）Go 1.11へのMigration
ここに記載あり => [Migrating your App Engine app from Go 1.9 to Go 1.11](https://cloud.google.com/appengine/docs/standard/go111/go-differences)

主に`app.yaml`が変わっています。
思いつくとこだけメモしておきます。

- `api_version`は廃止されるのでruntimeにバージョンを記載する。 例) `runtime: go111`
- `threadsafe`は廃止される。デフォルトTrueになる。
- `skip_files`は廃止される。代わりに`.gcloudignore`を使う。
- 必ず`main()`関数を用意する。
- `google.golang.org/appengine`パッケージをimportして使ってる場合は、`appengine.Main()`を実行する。
    - [このサンプルの書き方](https://github.com/GoogleCloudPlatform/golang-samples/blob/master/appengine/gophers/gophers-1/main.go)とかはそのまま使えました 


以上です。
balena Dashとラズパイ3でWebフレームを作る

Balena（バレナと読む？）という企業がIotアプリをWebで簡単に構築/管理できるプラットフォームを公開してたので、実際に使ってみた。

## Balenaのプラットフォームとは？
[公式の説明](https://www.balena.io/what-is-balena)を日本語化すると

>コアとなるBalenaプラットフォーム、つまり私たちがbalenaCloudと呼ぶものは、デバイス、サーバー、そしてクライアントサイドのソフトウェアを網羅しています
デバイスが弊社のホストOS（balenaOS）でセットアップされると、コードをbalenaビルドサーバーにプッシュして、コンテナにパッケージ化してフリートに配信することができます。
Webダッシュボード、またはCLIとSDKを介した当社のAPIを介して、すべてのデバイスとそれらの実行中のサービスを管理、監視、および更新できます。

自分が触った感覚と理解で言うと

- `balenaCloud`からラズパイ3向けの`balenaOS`をダウンロード
- OSをsdカードに焼いてラズパイ3で起動
- GithubからダウンロードしたDockerコンテナを`balena-cli`でアプリにpush
- `balenaDash`というWeb管理画面からラズパイ3の管理/操作を行えるサービスが使えるようになる

## balenaDashで出来ること

- Instagramフォトストリーム（ハッシュタグまたはユーザーに基づく）
- GrafanaまたはDatadogを使用したデータ中心のダッシュボード
- Googleフォトからのライブデジタルフォトフレームフィード
- Flightradar24や Flightawareなどのサービスの表示
- デジタル水槽やクラゲの表示
- ストリーミングウェブカメラディスプレイ（例：NASA HDEV）
- NyanCatの24時間ライブディスプレイ
- ホームオートメーションダッシュボード

今回はラズパイ3 ＋ 5inchディスプレイ でYoutubeを表示してみる。

## 用意するもの
ラズパイ3
microSDカード
HDMIディスプレイ（できれば小型）

## 自分の作ったもの
ラズパイ＋ディスプレイでYoutubeを延々とループ再生する。
YoutubeのURLはWeb管理画面で指定する。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">balenaCloud + RaspberryPi3 + Display(HDMI 5inch) = Web Frame👍🖥️🎞️<br>.<br>.<br>.<a href="https://twitter.com/hashtag/balenacloud?src=hash&amp;ref_src=twsrc%5Etfw">#balenacloud</a> <a href="https://twitter.com/hashtag/iot?src=hash&amp;ref_src=twsrc%5Etfw">#iot</a> <a href="https://twitter.com/hashtag/raspberrypi?src=hash&amp;ref_src=twsrc%5Etfw">#raspberrypi</a> <a href="https://twitter.com/hashtag/programmerlife?src=hash&amp;ref_src=twsrc%5Etfw">#programmerlife</a> <a href="https://twitter.com/hashtag/softwareengineer?src=hash&amp;ref_src=twsrc%5Etfw">#softwareengineer</a> <a href="https://twitter.com/hashtag/photooftheday?src=hash&amp;ref_src=twsrc%5Etfw">#photooftheday</a> from Instagram <a href="https://t.co/nKK1SgwzOa">https://t.co/nKK1SgwzOa</a> <a href="https://t.co/oUcDAq40EP">pic.twitter.com/oUcDAq40EP</a></p>&mdash; ikemura23 (@ikemura_jp) <a href="https://twitter.com/ikemura_jp/status/1086554770226274304?ref_src=twsrc%5Etfw">2019年1月19日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 手順
Make a web frame with Raspberry Pi in 30 minutes https://www.balena.io/blog/make-a-web-frame-with-raspberry-pi-in-30-minutes/

## 備考
説明すると長くなるので、手順のURLを見てほしい。
すごく簡単にIoTアプリケーションが構築できるし、専門知識がなくてもbalenaDashを使った色々作れそう。
[自分用メモ] ansibleでtarget hostのIPアドレスを取得する


ただのメモです。

変数 `ansible_default_ipv4.address` で取得できる。
`ansible_eth0.ipv4.address` で取得できる場合も多いが、targetのIPアドレスが必ずしもeth0に設定されているとは限らないので前者が良さそう。

> https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html
Firebase apiKey ってさらしていいの? ほんとに?

界隈でちょくちょく質問されているのを見るので調べたことをまとめてみました。
結論だけで言うと、「よい」です。

# Firebase apiKey? なに?

Firebase project を作成すると projectId はもちろん apiKey や databaseURL などが作成され、これを使うことで機能が使えるようになります。Firebase console でいうと Project 設定などから [アプリを追加] すると取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210165/3243875b-56ed-a1f3-025f-6e05f2c5b132.png)
詳しい手順はこちら。https://support.google.com/firebase/answer/7015592?authuser=0

```javascript:(値は仮です)
  var config = {
    apiKey: "CcN0p0MAIzavPCNkmXSyAy4xhKwCF6CqbX5TcvL",
    authDomain: "example.firebaseapp.com",
    databaseURL: "https://example.firebaseio.com",
    projectId: "example",
    storageBucket: "example.appspot.com",
    messagingSenderId: "032531346579"
  };
  firebase.initializeApp(config);
```

"apiKey" っていう名前がよくないと思うのですが、(Firebase らしく) client に含めて使う == エンドユーザーの手元に直接届く/保存される、すなわち public 情報である前提のものです。


### 実は ...?

この設定値、そもそも Firebase Hosting を有効にすると、**自動で** そのサイトから /__/firebase/init.js という path で参照できるようになります。Hosting を Authentication などとあわせて使うときのために、最初から置いてくれているわけです。気が利いてますね。このあたりは使い方が以下にドキュメントされています。

https://firebase.google.com/docs/hosting/reserved-urls#sdk_auto-configuration

```HTML
<!-- load Firebase SDK before loading this file -->
<script src="/__/firebase/init.js"></script>
```

こういうところから見ても、公開前提の値であり隠すようなものではないということがわかります。
というかこんな便利なことはもっと宣伝してほしい。
(angular/fire でこれを使ってうまく初期化する方法は模索中)


# よかった ... のだね?

はい。ただし、一部気をつけることがあります。

### Firestore

この設定値がわかると、その project の Firestore にかんたんにアクセスできます。Firestore の設定が test mode になっていて rule があまくなっていると、データを抜かれたり荒らされたりするかもしれません。

たとえば。当初ある project では Firestore のみ Admin API からだけ利用するつもりでいたので Firestore の rule はあまり気にしていなかったが、リリース直前になって簡単なサイトが必要になったので Hosting を有効にしたら config が公開されて... というシナリオが考えられます。

もともとはじぶんで疑問に思って web にあたってみたのですが、このあたりが参考になりました。
https://stackoverflow.com/questions/37482366/is-it-safe-to-expose-firebase-apikey-to-the-public

たしかに、Firebase project で billing が有効になっていると利用料を増やす嫌がらせとかはできそうですね。ただそれはサイトの利用を単に増やすだけ (なつかしの F5 アタック的な) でもできるので、特有の事情とは言えないかも。

### そして? 他にもあるかも?

危険はあらゆる場所に潜んでいる。何かあったら教えてください。


更新 20200105 : console で config の取得方法が変わっていたので更新しました。
Webサイト内でのユーザ行動解析ツールUserHeatを使用する為の5STEP

# UserHeatとは

https://userheat.com

Webサービスをユーザーがどう利用しているかを以下の視点で分析し、ヒートマップを生成してくれるサービスです。

* マウスをどう動かしているか
* どこがクリックされているか
* どこが読まれているか
* どこからの離脱が多いか
* どこで利用を終了しているか

#### 無料プランでも約1000種類のページ、30万PVまで利用できます。
※上限を超えても、勝手に課金される事は無いとの事です。

# 導入

## STEP1

https://userheat.comにアクセスして、利用開始。
計測したいサイトのFQDNを指定し、会員登録します。

## STEP2

ログインし、メニューの「解析タグ発行」から埋め込みスクリプトをコピーします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/184760/f7345258-83c6-ec88-42e5-c9e6d4668214.png)

## STEP3
コピーしたスクリプトを登録したFQDNの解析したいページ全てのheadタグに埋め込みます。
シンプルなRailsアプリだと、`app/view/layout/application.erb.html`に貼り付けるだけです。

```html:app/view/layout/application.erb.html
<!-- User Heat Tag -->
<script type="text/javascript">
XXXXXXXXXX
XXXXXXXXXX
</script>
<!-- End User Heat Tag -->
```

## STEP4
アクセスが溜まるのを待つ。
解析には各ページ50～100Pvが必要との事です。

## STEP5
UserHeatのマイページ>「解析結果の一覧」から、解析結果を確認します。
https://userheat.com/summaries

以下の様に、ヒートマップがページのキャプチャにマッピングされて表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/184760/0b29eb6a-ec3a-3ff9-e4a9-9a962ae2eb17.png)
※ クエリパラメータは指定できない為、パラメータ必須のページはキャプチャが取得でき         ません。
   上記画像のページはユーザがログインしている場合、クリックがされている箇所に
   テキスト投稿フォームが表示される仕様ですので、何も表示されていません。
Convert SJIS to UTF8 on chrome browser

Third-party libraries are no longer needed to convert SHIFT-JIS files to utf8.

```javascript
const a = await fetch(url).then( res => res.arrayBuffer() )
const decoder = new TextDecoder("shift_jis")
const utf8 = decoder.decode(body)
```

- [Can I use\.\.\. TextDecoder](https://caniuse.com/#feat=textencoder)
- [How to convert ArrayBuffer to and from String  \|  Web  \|  Google Developers](https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String)
Dockerコマンド

##Dockerのバージョンを確認

```
$ docker --version
```

##取得したイメージを一覧表示

```
$ docker images
```

##Docker Hubレジストリからイメージを検索

```
$ docker search キーワード
```

##Docker Hubレジストリからイメージを取得

```
$ docker image pull イメージ名[:タグ名]
タグ名: Pulling from イメージ名
xxxxxxxxxxxx: Pull complete ← レイヤもダウンロード
yyyyyyyyyyyy: Pull complete ← レイヤもダウンロード
.
.
.
Digest: sha256:4520b6a66d2659dea2f8be5245eafd5434c954485c6c1ac882c56927fe4cec84 ← イメージに一意に付与される値（イメージに変更があった場合、値が変わる）
Status: Downloaded newer image for イメージ名
```

#イメージを削除

```
$ docker rmi イメージID
```

#現在起動しているコンテナを表示

```
$ docker ps
```

-aオプション
全てのコンテナを表示
-qオプション
起動しているコンテナのコンテナIDを表示

##コンテナを停止

```
$ docker container stop コンテナIDまたはコンテナ名
```
コンテナを削除する場合、先に停止しておく必要があります

##コンテナを削除

```
$ docker container rm コンテナIDまたはコンテナ名
```

###コンテナ内のファイルをホストにコピー

```
$ docker container cp コンテナIDまたはコンテナ名:コンテナ内のファイルパス ホストのファイルパス

ホストのファイルをコンテナにコピーすることもできる
$ docker container cp ホストのファイルパス コンテナIDまたはコンテナ名:コンテナ内のファイルパス
```


---
Docker v 1.13でDocker CLIの再編成が行われました
https://www.docker.com/blog/whats-new-in-docker-1-13/
Python SQL規約チェック

SQLの規約チェックが必要になる局面があって
うまいところPythonと正規表現で対処できないか試行錯誤した自分向けメモ。

Excelのマクロで規約違反検出を行っているのですが
これが遅い上に端末CPUを長時間100％専有するという、非効率極まりなく
また誤検知も多く使い勝手の悪いもので

で、Pythonで書き換えてJenkinsで自動実行する仕組みにしました。

さまざま４０ケース程度の規約チェックを書いたのですが
前処理が必要なものもあったり、直接正規表現を投げて解決する様々でした。

規約以前に構文ミスがあるものの検出は考えることも多いものでした。
ちょっとだけサンプルコードを記録しておきます。

**DELETEの直後にFROMが来ないSQL**

```
import re

a = 'DELETE FROM aaaa\n'
b = 'DELETE bbbbb\n'
r = re.compile(r'(?=.*DELETE)(?!.*FROM).*$')

for x in r.finditer(a):
    print(x)

for x in r.finditer(b):
    print(x)
```
<_sre.SRE_Match object; span=(0, 12), match='DELETE bbbbb'>

**DELETE構文でWHEREを指定していないSQLを検出**

```
a = 'DELETE FROM aaaa WHERE\n'
b = 'DELETE FROM bbbbb\n'
r = re.compile(r'(?=.*DELETE\b)(?!.*WHERE\b).*$')

for x in r.finditer(a):
    print(x)

for x in r.finditer(b):
    print(x)
```
<_sre.SRE_Match object; span=(0, 17), match='DELETE FROM bbbbb'>


**関数を使った語句にASで再度名前を定義していないSQL**

```
#SQLS = ['SELECT LEFT(ALPHA,3) AS B FROM SYSIBM.SYSDUMMY1',
#        'SELECT LEFT(ALPHA,4) FROM SYSIBM.SYSDUMMY1',]

SQLS = ['SELECT LEFT(ALPHA,3) AS B FROM SYSIBM.SYSDUMMY1',
        'SELECT LEFT(UTF16_VAR, 2, CODEUNITS16) AS A, LEFT(UTF16_VAR, 2, CODEUNITS32) B, HEX (LEFT(UTF16_VAR, 2, OCTETS)) AS C FROM SYSIBM.SYSDUMMY1',
        'SELCT * FROM A']

r = re.compile(r'.*\(.+\)\s(?!AS)')

for sql in SQLS:
    for x in r.finditer(str(sql)):
        print(x)
```
<_sre.SRE_Match object; span=(0, 77), match='SELECT LEFT(UTF16_VAR, 2, CODEUNITS16) AS A, LEFT>
JavaScriptのスプレッド構文で、ArrayやObjectをマージ

こちらの[投稿](https://qiita.com/h-naito/items/062ef0f5dbdae73fe814)の[コメント](https://qiita.com/h-naito/items/062ef0f5dbdae73fe814#comment-403b4d407ff08398a047)で、スプレッド構文(`...`)もつかえるとアドバイスを頂きましたのでまとめてみました。

#スプレッド構文とは
>Array や String などの iterable オブジェクトをその場で展開します
(引用元：https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax)

検索してサンプルを見ると配列を例にしている事が多いですが、実際にはObject（`{ }`）にも使用できます。


#文法
ピリオド3つ(`...`)を展開したい物の前に記述します。

```JavaScript
...Array
...Object
```

##コード例
```JavaScript
// 関数の引数
const array01 = [1, 2, 3];
MyFunction(...array01)
```
```JavaScript
// 配列をマージ
const array02 = [10, 20, 30, 40];
const mergeArray = [...array01, ...array02];
// output [1,2,3,10,20,30,40]
// concantだと、[].concat(array01, array02);

// 配列に追加
let arr = [99, 999, 9999];
arr = [...arr, 10000];
// output [99,999,9999,10000]
// pushだと、arr.push(10000);

// コピー
const array03 = [...array02];
```

```JavaScript
// objectをコピー
const object03 = {...object01};

//objectをマージ
const object01 = { foo: 'bar', x: 42 };
const object02 = { bar: 'baz', y: 13 };
const mergeObj = {...object01, ...object02};
/* 
output:
{
  "foo": "bar",
  "x": 42,
  "bar": "baz",
  "y": 13
}
*/
```

#どんな時に使う？
初期化でオブジェクトをマージしたい時
データを加工したいとき（ユーザーからのinputで画面に表示させたいものを変化させるとか。）

#注意したい事
ネストしているもの（多次元）には向かないです。
iterable オブジェクトだけに使えます。


#参考
スプレッド構文
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax

JSのスプレッド演算子を理解する
https://qiita.com/akisx/items/682a4283c13fe336c547
railsでslackのチャンネルにメッセージを送ってみた

##動機
友人とwebサイトを制作していて、"contact" のように外部の人たちが私たちに連絡を取れるページを作ろうという話になりました。しかし、共有のメールアドレスをもっていないので、それ以外の方法はないかと考えたところ、slackにメッセージを送ればいいという結論になり、ついでに記事をかいています。(圧倒的な雑さ)
##概要
1.使用したgem
2.コード
3.欠点
4.その他
#1.使用したgem
使用したgemは'slack-notifier'というgemです。このgemを入れて,githubに書かれている手順にしたがって
https://github.com/stevenosloan/slack-notifier
上がgemのgithubです。英語ですが、slackにメッセージをお車での手順は簡単なので試していけばうまく行くと思います。

https://kut-fencers.slack.com/apps/A0F7XDUAZ-incoming-webhooks?next_id=0
上のリンク先から次のページに飛び、あとは流れでやります。設定以外は特にいじらなくても大丈夫です。
設定が完了したら<font color="Red">Webhook URL</font>をコピーしておいてください。
![Screen Shot 2019-01-20 at 22.20.23.png](https://qiita-image-store.s3.amazonaws.com/0/288717/c48e9a04-a53b-80aa-908e-d8b5aaca58b1.png)

#2.コード
ルーティングは index と create　を使いました。　
今回は送るだけの実験なのでcssを用意してません。
viewについて特にいうことはありません。

```index.html.erb
<%= form_tag("top#create", method: "post") do %>
  <%= label_tag(:name, "name:") %>
  <!-- 一つ目がどの入力ボックスとひもづけるか、だからしたと同じにする。右がラベルの名前 -->
  <%= text_field_tag(:name) %>
  <!-- これはparams[:name]で参照できる -->
  <%= label_tag(:message, "message:") %>
  <%= text_field_tag(:message) %>
<br>
  <%= submit_tag("send") %>
<% end %>
```
![Screen Shot 2019-01-20 at 22.16.55.png](https://qiita-image-store.s3.amazonaws.com/0/288717/cbac7078-ab10-9a24-7e63-a04328b137f8.png)

```controller
  def index
  end

  def create
    slack_name = params[:name]
    message =  "<!here> " +params[:message]
    notifier = Slack::Notifier.new "コピーしたWebhook URL"
    notifier.ping message, username: slack_name
  end
```
これでsendボタンをクリックして、createページに遷移した際にslackにメッセージが送信されます。https://api.slack.com/docs/message-formatting このページにも書いてありますが<!here>のように記述することでmentionを飛ばすことができます。ちなみに@hereは現在アクティブなユーザーにのみ通知がmentionのようです。忘れないようにしたければ@channelが確実だと思われます。
![Screen Shot 2019-01-21 at 23.23.05.png](https://qiita-image-store.s3.amazonaws.com/0/288717/2c5bb5ca-a58d-5661-aca0-2712e8d29719.png)
#3.欠点
このコード自体は問題ありません。しかし、いくつか追加すべき機能があります。
~~・newページを更新してもメッセージが送信されてしまう。~~ 
2019/01/31. 使用するルーティングをnewからcreateに変更することで解決しました。
・誰が送信したのか名前以外で判別しずらい(アイコンが変わらない)
上記の欠点はこれから修正していきたいと思います。
#4.その他
2019/01/20 記事を投稿
2019/01/21 mentionの記述を追加、画像を追加
2019/01/31 リロードの問題を解決。はっきりとした理由はわからないのでまた追記します。
誤字脱字、記事の間違いなどを指摘していただけるとありがたいです。
Phoenix on GKE

PhoenixをGKEで動かせるようにした。
本番リリースとかとは違って漸進的に動作確認しながら開発を進行したかったのでなるべく本番環境に近い環境&&コスト抑えめを実現するためにいろいろ考えた

## 構成
GKE上に構築
* Phoenix(何も考えずにインスタンスを借りると定価で請求されちゃうのでプリエンプティブノードで立ててる)

GCE上に構築
* Postgres(普通にインスタンスを借りると高いのでUSリージョンでf1-microの無料枠で立ててる)

通信周り
* ingress(通信周りはどうしようもないので定価で請求されちゃう(´・ω・｀))

とりあえずこんな感じ


## Dockerfile

コンテナビルドするときに使ったDockerfile
実は `MIX_ENV=prod`にするとアセットが読み込まれなくてどうしたらいいかかなり悩んだ。
`npm i && node node_modules/brunch/bin/brunch build`が大切だった

```dockerfile

FROM elixir:1.7.4-alpine

WORKDIR /app

RUN apk add --update nodejs nodejs-npm

RUN mix local.hex --force && \
  mix archive.install --force https://github.com/phoenixframework/archives/raw/master/phx_new.ez && \
  mix local.rebar --force

COPY . .

RUN mix deps.get

RUN cd assets && \
  npm i && \
  node node_modules/brunch/bin/brunch build

RUN mix compile
RUN mix phx.digest

CMD ["mix", "phx.server"]
```

## deployment

マニフェストはkompose使ってdocker-compose.ymlをコンバートしたものを改造してる感じ
Phoenixはステートレスをキープするのでボリュームのマウントとかはしない。

```yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: web-server
  name: web-server
spec:
  replicas: 2
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: web-server
    spec:
      containers:
        - image: gcr.io/GCP_PROJECT/web_server
          imagePullPolicy: Always
          name: web-server
          command:
            - "mix"
            - "phx.server"
          ports:
            - containerPort: 4000
              name: web-server
          envFrom:
            - configMapRef:
                name: web-server
          readinessProbe:
            httpGet:
              port: 4000
              path: /health_check
                      
```
Swift：NSImageのドット絵をそのまま拡大(リサイズ)する

# 概要
画像のリサイズのとき`ImageView`の機能の余計なお世話で勝手に色を補間してしまいますよね．（特に`Scaling`で`Proportionally Up or Down`なんか選ぶと）ドット絵を用いる時はこの仕様は邪魔ですね．そこで，画像のリサイズの際，補間をさせずにそのまま拡大する方法を調べて実装してみました．

# ソース

`resize`という`Extension`を書いてみました．

```swift:
extension NSImage {
    public func resize(targetSize: CGSize) -> NSImage? {
        let wRatio = targetSize.width / self.size.width
        let hRatio = targetSize.height / self.size.height
        var newSize: CGSize
        if(wRatio > hRatio) {
            newSize = CGSize(width: self.size.width * hRatio,
                             height: self.size.height * hRatio)
        } else {
            newSize = CGSize(width: self.size.width * wRatio,
                             height: self.size.height * wRatio)
        }
        guard let imageData = self.tiffRepresentation else { return nil }
        guard let cgImage = NSBitmapImageRep(data: imageData)?.cgImage else { return nil }
        guard let bitmapContext = CGContext(data: nil,
                                            width: Int(newSize.width),
                                            height: Int(newSize.height),
                                            bitsPerComponent: 8,
                                            bytesPerRow: 4 * Int(newSize.width),
                                            space: CGColorSpaceCreateDeviceRGB())//   DeviceGray(),
                                            bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else { return nil }
        
        let rect = CGRect(origin: CGPoint.zero, size: newSize)
        bitmapContext.interpolationQuality = CGInterpolationQuality.none
        bitmapContext.draw(cgImage, in: rect)
        guard let newImageRef = bitmapContext.makeImage() else { return nil }
        let newImage = NSImage(cgImage: newImageRef, size: newSize)
        return newImage
    }
}
```

```swift:使用例
let imageView = NSImageView(frame: NSRect(x: 0, y: 0, width: 200, height: 100))
let nsImage = NSImage(imageLiteralResourceName: "DotImage")
imageView.image = nsImage.resize(targetSize: imageView.frame.size)
```
LaravelのModel（Eloquent）で取得時のデフォルト値を指定する

よく忘れて探すのでメモ。

```php:User.php
class User extends Authenticatable
{
    use Notifiable;
    protected static function boot()
    {
        parent::boot();
        User::retrieved(function($user) {
            if(!$user->profile_image_url){
                 $user->profile_image_url = asset('/img/default_profile_image.png');
            }
        });
    }
}
```
上記はDBにないデータが渡ってきて混乱するので、
このやり方するよりは下記のようにModel生成時にデフォルト値を指定する方法をおすすめします。

```php:User.php
class User extends Authenticatable
{
    use Notifiable;
    protected static function boot()
    {
        parent::boot();
        User::creating(function($user) {
            $user->profile_image_url = asset('/img/default_profile_image.png');
        });
    }
}
```

あとで見てて気づいたのですが、下記のような方法もあるみたいです。

```php:User.php
class User extends Authenticatable
{
    use Notifiable;

    protected $attributes = [
        'profile_image_url' => asset('/img/default_profile_image.png'),
    ];
}
```
Raspberry Pi 3 虹色スプラッシュスクリーン？で固まった時の対処法

##2台目のRaspberryPi
Raspberry Piを会社のパティーのビンゴ大会でいただいたので、１年ほど前に買って放置していたRaspberryPi zero みたいなやつと合わせて２台になった、ちょうどいいのでIoTマスターになるぞいと意気込んで一度だけ起動した、Raspberry Pi zeroからmicroSDから引っこ抜いていいやつらしい3の方に突っ込んだ矢先、事は起こった。

##画面が虹色スプラッシュスクリーンで固まる
全ケーブルを接続しいざ出陣と意気揚々とMicroUSBを挿すがうまく起動しない
画面が虹色のスプラッシュスクリーンなような画面で固まってしまった。

![IMG_6490.JPG](https://qiita-image-store.s3.amazonaws.com/0/316758/83c8cef4-742b-ff29-cc62-fa9a05d6aeee.jpeg)


色々調べた結果、microSDに入れていたRaspbianOSのバージョンが古かったらしい。
時代の進化ってすごい。

ホームページ↓から最新版をダウンロードして再度トライし直したら無事起動した。
https://www.raspberrypi.org/downloads/raspbian/

##反省
バージョンアップ大切。
Ruby on Railsの環境構築

こんにちは[@yukifreeworld12](https://twitter.com/yukifreeworld12)です。

今回Railsの環境構築についての流れを説明します、
環境構築はなかなか難しく、必要なソフトウェアのことも知っていないと何が必要でどうすれば良いのかわからないので
簡単にどのソフトウェアが必要でどう行った流れで進めるのか、また使うコマンドを解説していきます。
※ちなみにエディタは「ATOM」を使って行いましたが他のエディタでも大丈夫です。
## 簡単な流れ

1、「Command Line Tools for Xcode」
        　　　　　　↓
2、　「Homebrew(パッケージ管理)」
　　　　　　↓
3、「rbenv(バージョン管理)」
 　　　　　　↓
4、　　　「Ruby」
　　　　　　↓
5、　　「bundler」
　　　　　　↓
6、　　　「Rails」
　　　　　　↓
7、　 　「MySQL」
この順で必要な7つのソフトをインストールしていきます。

## 実際に環境構築してみよう
1,**Command Line Tools for Xcodeのインストール**
ターミナルで
`$ xcode-select --install`

もしerror: Command Line Tools are already installedと表示された場合はすでにインストールされているのでそのまま気にせず進めて大丈夫です。

2,**Homebrewのインストール**
[Homebrew](https://brew.sh/index_ja.html)の公式サイトにアクセスし、インストールと書かれた下にある
コードをコピーしてコマンドに貼り付けて実行します。
これで完了です。

3,**rbenvのインストール**
`$ brew install rbenv`
これと一緒にruby-buildといRubyRubyに必要なツールもインストールします。
`$ brew install ruby-build`
`$ rbenv -v`と入力するとバージョンの確認が行えます。

インストールは完了したので今インストールしたのを使えるように設定していきます。
*PATHを通すコマンド*
`$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile`
`$ echo 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi' >> ~/.bash_profile`
今作成されたファイル.bash_profileの再読み込みを行います。
`$ source ~/.bash_profile`

4,**Rubyのインストール**
いよいよRubyのインストールを行います。コマンドによって時間がかかったり、止まっているように感じることがありますが少し待てば動くので焦って無理にエディタを閉じたりしないように気をつけてください。
下記のコマンドでインストール可能なバージョンが確認できます。
`$ rbenv install -l`
今回は2.4.1でインストールしていきたいと思います。
`$ rbenv install 2.4.1`
*バージョンの適用*
`$ rbenv global 2.4.1`
`$ rbenv rehash`
*バージョンの確認*
`$ ruby -v`
これでRubyのインストールが完了しました。

5,**bundlerのインストール**
これは簡単でgemコマンド１つでOKです。
`$ gem install bundler`

6,**Railsのインストール**
遂にRailsのインストールです。
`$ gem install rails`
バージョンの確認コマンド
`$ rails -v`

7,**MySQLのインストール**
最後にデータベースであるMySQLをインストールして環境構築完了です。
`$ brew install mysql@5.7`
*PATHを通す*
`echo 'export PATH="/usr/local/opt/mysql@5.7/bin:$PATH"' >> ~/.bash_profile`
`source ~/.bash_profile`
次に次回からターミナルを立ち上げると自動で起動するようになるコマンドを入れます。
`$ brew services start mysql@5.7`

## これで完了
無事何事もなくRailsの環境構築が出来て入ればと思います。
環境構築は難しいので少しでも参考になれば幸いです。

##最後に
今日も見てくれてホンマありがとな!!
記事がええなと思ったらフォローといいねホンマよろしくな!!
(ジョーブログ風に)
Oracleのジョブを削除する方法

以下で削除できる。

```SQL
--- ジョブ「JOB01」を削除する場合
--- ジョブの存在を確認
SELECT * FROM DBA_SCHEDULER_JOBS WHERE JOB_NAME='JOB01';

--- 対象ジョブを削除
BEGIN
DBMS_SCHEDULER.DROP_JOB('JOB01');
END;
/

--- ジョブが削除されていることを確認
--- 「レコードが選択されませんでした」と表示されればOK
SELECT * FROM DBA_SCHEDULER_JOBS WHERE JOB_NAME='JOB01';
```
Vue.jsのUnitテストフレームワーク

Vue.jsで開発プロジェクトのUnitテストフレームワークを決めるために、2019年1月時点での状況を調査した。調査ではフレームワークの機能の違いではなく、実際の開発プロジェクトでの利用状況を中心に見ている。

### 結論

これまではMochaと様々なライブラリを組み合わせて使うのが主流であったが、セットアップの簡単さと実行効率の良さから、今後はJestに開発者が流れていくことが予想される。Vue.jsでは[@vue/cli-plugin-unit-jest](https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-unit-jest)を使うと簡単にセットアップができる。

### 調査の詳細

#### Vue CLI

Vue CLIでは2つのプラグインが提供されている。

* [vue/cli-plugin-unit-mocha](https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-unit-mocha)
* [@vue/cli-plugin-unit-jest](https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-unit-jest)

#### Mocha vs Jest

長く使われてきたMochaに対して、Facebookが開発するJestが台頭してきている。[stachshare](https://stackshare.io/stackups/jest-vs-mocha)を参照すると、利用者は歴史が長い分Mochaの方が多いが、GitHubのスター数はJestが上回っている。

いくつかの企業においても、MochaからJestに乗り換える動きが出てきている。AirbnbとeBayの事例紹介記事を以下に要約した。

(1) [Migrating from Mocha to Jest](https://medium.com/airbnb-engineering/unlocking-test-performance-migrating-from-mocha-to-jest-2796c508ec50)

* AirbnbでのMochaからJestへの移行について紹介されている。
* MochaとJestのAPIが類似しており、テストにもコーディング規約を設けていたため、テストコードをほとんど書き換える必要なく、メソッド名の変換コードを入れる程度の対応で移行できた。
* MochaではIstanbulを使いカバレッジを計算していたが、時間がかかるため独自に並列化する処理を実装していた。Jestでは並列化の仕組みが予め備わっているため、テスト実行の仕組みを単純化できた。
* Jestはラウンドロビン方式での並列化、プロセス間でのbabel変換キャッシュの共有により高速なテスト実行が可能となっている。Mocha（独自並列化あり）では開発環境で45分かかっていたテストがJestでは14.5分（ビルドサーバー上では12分 → 4.5分）に短縮できた。
* Jestは各テストファイルを独立して実行するため、他のテストのコンテキストの影響を受けず、不安定なテストが発生しにくい。また、意図せず他のテスト依存したテストを書いてしまっても原因を見つけるのが容易になる。
* Jest導入により開発体験も向上し、開発者からも前向きなフィードバックが寄せられた。

(2) [Into the Great Unknown — Migrating from Mocha to Jest](https://ebaytech.berlin/into-the-great-unknown-migrating-from-mocha-to-jest-3baced083c7e)

* eBay（ベルリンオフィス）で開発するサービスのテストをMochaからJestへ移行した手順が紹介されている。
* 多くのライブラリを組み合わせる必要があったMochaに比べて、Jestはオールインワンでセットアップが簡単になった。
* [jest-codemods](https://github.com/skovhus/jest-codemods)を使うことで、Mocha、chai等で書かれたコードをある程度自動変換できるが、以下の手作業が必要であった。
  * テストファイル名置換
  * Sass読み込み設定を追加
  * [Jest ESLint plugin](https://www.npmjs.com/package/eslint-plugin-jest)を追加（エディタでのLintエラー回避）
  * ChaiをJestで動かすための変換コードを追加（参考：[Combining Chai and Jest matchers](https://medium.com/@RubenOostinga/combining-chai-and-jest-matchers-d12d1ffd0303)）

補足として、[Reddit](https://www.reddit.com/r/vuejs/comments/8myjfs/testing_jest_or_mocha/)での議論でもJestを支持する投稿が多かった。一方でJestの不安視する理由としては、開発の中心がFacebookであることによる開発の継続性への心配が挙がっている。
Wake on Lan 有効化設定はネットワークアダプターの設定から。ただし、表示されていない場合がある。

#概要
Wake on Lanという便利な機能を知っているだろうか？パソコンの電源スイッチを押すのではなく、接続しているLANに特殊な信号を送ることでPCの電源を入れる機能だ。各サイトをみて設定しようとしたが、デフォルトのままだと、Windowsの設定画面に出てこない。ネットワークアダプターの設定ソフトウェア（IntelPROSet）をインストールすると、WOLの設定プロパティが出てきた。もしWOLの設定が見当たらない場合は、ネットワークアダプターを調べてみるといい。

#環境
- Lenovo ThinkCenter M73Tiny
- Windows10 64bit
- ネットワークアダプターはIntel製

#ポイント
- BIOSの設定
- ネットワークアダプターの設定（WOLの設定がない！）
- インテルPROSetソフトウェアのインストール
- ネットワークアダプターの設定（WOLの設定が表示された）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/340432/738a57ba-6384-3c4b-2ef3-b83eefb9d697.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/340432/ae55d545-d6e0-9f1b-3a0b-cd990bfd9af8.png)


#参考
https://blog.treedown.net/entry/2016/05/01/010000
https://downloadcenter.intel.com/ja/search?keyword=Intel+Pro+Set
接続中のOracleのサーバーとインスタンスを確認する方法

SQL*Plusで
以下のコマンドを打つだけ。

```SQL
SELECT SYS_CONTEXT('USERENV','DB_NAME') from dual;
SELECT SYS_CONTEXT('USERENV','INSTANCE_NAME') from dual;
```

第2引数の値を変えると色々見れる。
【JavaScript 】mapとfilter

# mapとfilter

```javascript:
'use strict';

const a = [0, 1, 2];

// map
let a2 = a.map(value => value * 2);
console.log(a2); // [0, 2, 4]

// 上記と同じ処理
a2 = [];
a.forEach(value => {
    a2.push(value * 2);
});
console.log(a2); // [0, 2, 4]

// filter
let odd = a.filter(value => value % 2 === 1);
console.log(odd); // [1]

// 上記と同じ処理
odd = [];
a.forEach(value => {
    if (value % 2 === 1) {
        odd.push(value);
    }
});
console.log(odd); // [1]
```
※Google Chrome で確認
※ES8
一意制約を動的に利用したい

|     id           |       id_type     |                   |
|:-----------------|:------------------|:------------------|
| id_0001          |              main |                   |
| id_0002          |               sub |                   |
| id_0001          |              main |        新規登録 NG |
| id_0002          |               sub |        新規登録 OK |

例えばid_typeが"main"の時だけIDを一意にしたい、id_typeが"sub"の時はidの重複を許可する
というようなことをしたいときは以下のように制約を張れば良い

#Oracle：ファンクション索引

```sql
CREATE UNIQUE INDEX インデックス名 ON テーブル名 (CASE WHEN id_type='main' THEN id ELSE NULL END);
```

#PostgreSQL：部分インデックス

```sql
CREATE UNIQUE INDEX インデックス名 ON テーブル名 USING btree (id) WHERE id_type='main';
```

##MySQL：Generated Column
使い方、未調査。
railsアプリをHerokuにpushするときにエラー("You must use Bundler 2 or greater with this lockfile.")

MacOS
rails 5.1.6

herokuにpushすると以下のエラーが出る。

```terminal
$ git push heroku master
Total 0 (delta 0), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Ruby app detected
remote:
remote:  !
remote:  !     You must use Bundler 2 or greater with this lockfile.
remote:  !
~省略~
remote:  !     Push rejected, failed to compile Ruby app.
remote:
remote:  !     Push failed
remote: Verifying deploy...
remote:
remote: !       Push rejected to ***.
remote:
To https://git.heroku.com/***.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/***.git'
```

"You must use Bundler 2 or greater with this lockfile."
はどうすればいいんじゃ？と調べた結果、
以下コマンドでビルドパッケージを追加

```terminal
$ heroku buildpacks:set https://github.com/bundler/heroku-buildpack-bundler2
Buildpack set. Next release on rails-tutorial-iwato will use https://github.com/bundler/heroku-buildpack-bundler2.
Run git push heroku master to create a new release using this buildpack.
```

もう一度
git push heroic master
で無事herokuにpushできた。
React NativeでTypeScriptを使う2019

## 前提
```
$ react-native -v
react-native-cli: 2.0.1
```

react-nativeは0.57.8

## 本題
前にReactNativeに触ったのは2017年の夏くらいだったので、ずいぶん方法が変わっていて驚きました。React NativeをTypeScriptで書きたいという話です。新規プロジェクトを作る時の話なので、既存プロジェクトに適用したいときはよしなにどうぞ(よくわかってない)

結論から述べると、`react-native init MyProj --template typescript`としてあげるとTypeScriptを使ったプロジェクトが作成されるようになったみたいです。

[Using TypeScript with React Native · React Native](https://facebook.github.io/react-native/blog/2018/05/07/using-typescript-with-react-native)

ここに書いてた。

ところがどっこい、型がぶっ壊れてても実行できてしまいます。例えばこんなコード。

```tsx
const add = (x: number, y: number): number => x + y;

interface Props { }
export default class App extends Component<Props> {
  render() {
    return (
      <View style={styles.container}>
        <Text>{add(1, "hoge")}</Text>
      </View>
    );
  }
}
```

Add関数は、number型を2つ取るはずが、第2引数が文字列でも実行されてしまい…

![image.png](https://qiita-image-store.s3.amazonaws.com/0/20371/bcead5a6-81dc-48d3-c9a4-7d58e56a5952.png)

こうなる。そうじゃねぇ…。

VSCodeを使っているので、エディタの画面ではエラーを吐いてくれます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/20371/177d3545-b429-5ac7-8388-d36f9f542632.png)

どうしてこうなってしまうのか、調べたところ以下の記事に当たりました。

[React Native v0.57がTypeScriptに対応したらしいので動かしてみた - Qiita](https://qiita.com/Nkzn/items/cf1516136d2db981fbb9)

記事冒頭を引用させていただくと、

> React NativeのTypeScript対応は、Babel 7のTypeScript対応に乗っかった形で実現されています。
> 
>  ここで重要なのは、 Babelはtscを内部で実行するわけではない ということです。
> 
> 今回導入された@babel/preset-typescriptは、FlowTypeの babel-plugin-flow-strip-types と同様に、TypeScript/FlowからTypeScript/Flow特有の文法を引き剥がせば、Babelでパース可能なJSになる という発想で作られています。

と書かれています。

なるほど。

Babelでは型チェックを行なっていないので、先ほど示したようなコードが実行できてしまったわけですね。(VSCodeは裏側でtscを実行してエラーを出しているので、ちゃんと型と合わないところでエラーが出ていたものと考えられます。)

というわけで、上記記事にも書いていますが、型チェックだけをtscでやってやるのが正しいみたいです。

上記記事では、tsconfig.jsonも自分で書かれていますが、`--template typescript`で作成されたプロジェクトにはtsconfig.jsonがあらかじめ入っているので、それを使ってやればよさそうです。
JavaScript初学者が躓きかけたメソッド達

<h1>JavaScript初学者が<br>躓きかけたメソッド達。</h1>
一からJavaScriptを学んでいるが、初めてスムーズに理解が進まなかったので自分用メモとして残します。

<ul>
<li>unshift();</li>
<li>push();</li>
<li>shift();</li>
<li>pop();</li>
<li>splice();</li>
</ul>
<ul>
<li>forEach();</li>
<li>map();</li>
<li>filter();</li>
</ul>
<ul>
<li>Object.keys();</li>
<li>Object.values();</li>
<li>Object.entries();</li>
</ul>
GCPのAssociateCloudEngineerを受験しました

受験しました。利用したもの、テストを受けた感想を書きます。

###事前知識
・他のパブリッククラウドベンダの資格を取得している
・Google Cloud Platformの業務経験なし
・応用情報処理技術者程度の知識

###受けるきっかけ
AWSの業務経験はあるが、他のベンダも知らないと近い将来生き残れないんじゃ...
とずっと考えていました。昨年から少しずつGCPを触って知識を広げていて
横断して知識を整理したいと思い、今月受験しました。

###受験の準備
知識を体系的に整理して、各サービスごとの概要と役割
また、Googleが推奨する利用方法を改めて整理しました。
整理した資料は以下の通り。

**公式ドキュメントを再度熟読した**
（特に試験範囲のサービスの「コンセプト」「リソース」のページを重点）
https://cloud.google.com/docs/

**各サービスのUI、コマンド体系を一通り動かす**
各サービスごとに、どのような概念や利用方法があるのかを
改めて確認しておく。ボタン／メニュー／コマンドを確かめておく

**書籍を読む**
入門Kubernetesなど

**模擬試験を受ける**
受けられるが、受けたことで本試験で役に立った印象ありません。

### 試験を受けて
試験内容を見ると、サービスの概要を問うテストだと思っていたが
以下のような課題に対して解決策を答える問題が多かったです。
・特定の状況に対してGCPでどのように解決するか？
・いくつか選択肢があり最短で実現できるのはどれか？
・実現方法は複数あるが、GCPが推奨しているのはどれか？

問題と選択肢を何度か読めば、自身が触ったことのないサービスでも
明らかに間違いだとわかる選択肢が必ずあり
冷静に進めるのがすごく大切だと思いました。。
（また、選択肢を1つに絞れない問題も5個ぐらいあり、印象で選びました笑）

試験終了後、結果は暫定で出ましたが
数日後にメールで連絡が来るそうです。
結果が出ましたら、更新いたします。

2019/01/22 21:46追記
通ってました
![スクリーンショット 2019-01-22 21.45.38.png](https://qiita-image-store.s3.amazonaws.com/0/110457/b31bbd48-3cff-7665-7a52-da9538ed6e66.png)

次は以下を受験予定です。
https://www.microsoft.com/en-us/learning/azure-exams.aspx#exam-az-100-section
https://www.microsoft.com/en-us/learning/azure-exams.aspx#exam-az-101-section
【JavaScript 】配列の全ての要素に対して処理を実行する

# 配列の全ての要素に対して処理を実行する

```javascript:
'use strict';

const a = [0, 1, 2];

// for
for (let i = 0; i < a.length; i++) {
    console.log(a[i]);
}
// 0
// 1
// 2

// forEach
a.forEach(value => {
    console.log(value);
});
// 0
// 1
// 2

a.forEach((value, index) => {
    console.log(`a[${index}] = ${value}`);
});
// a[0] = 0
// a[1] = 1
// a[2] = 2
```
※Google Chrome で確認
※ES8
AWS上の踏み台サーバを経由して、対象のインスタンスに接続する。part1

# やること

* VPC、サブネット、セキュリティグループ、ピアリングあたりの理解を深めるために、別々のVPC上にたてたEC2インスタンスの疎通を確かめてみる。
* Windows10の環境で、awscliを使ってみる。
* 具体的な構成は以下のよう。

![AWS_bastion_全体.jpg](https://qiita-image-store.s3.amazonaws.com/0/105281/9a0dd4c7-94c0-d190-c0d5-e960e95ca0af.jpeg)

# awscliを使う準備

1. ```pip install awscli```コマンドを打ってawscliをインストールする（MSI インストーラもある）
2. https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/getting-started_create-admin-group.html に従ってAdministrator を作成
3. ```aws configure```コマンドを打って、awscliとAdministratorを紐づける

# bastionのインスタンス生成

## bastionを入れるVPCを整備

### 1. bastion用VPC作成  

```
aws ec2 create-vpc --cidr-block 10.1.0.0/16 
aws ec2 create-tags --resources vpc-0074168dfa72a5826 --tags Key=Name,Value=bastion_cli
```
### 2. bastion用サブネット作成  

```
aws ec2 create-subnet --vpc-id vpc-0074168dfa72a5826 --cidr-block 10.1.0.0/24
aws ec2 create-tags --resources subnet-0bb7116ca38f5a80f --tags Key=Name,Value=bastion_subnet_cli
```
### 3. インターネットゲートウェイの作成  

```
aws ec2 create-internet-gateway
```
### 4. bastion用VPCにインターネットゲートウェイをアタッチ  

```
aws ec2 attach-internet-gateway --vpc-id  vpc-0074168dfa72a5826 --internet-gateway-id igw-06c61291eaba0ac1f
```
### 5. bastion用VPCにカスタムルートテーブルを作成  

```
aws ec2 create-route-table --vpc-id vpc-0074168dfa72a5826
```
### 6. インターネットゲートウェイへのすべてのトラフィック (0.0.0.0/0) をポイントするルートテーブルでルートを作成  

```
aws ec2 create-route --route-table-id rtb-0362a010826fc18bc --destination-cidr-block 0.0.0.0/0 --gateway-id igw-06c61291eaba0ac1f
```
### 7. サブネットとカスタムルートテーブルを紐づける  

```
aws ec2 associate-route-table  --subnet-id subnet-0bb7116ca38f5a80f --route-table-id rtb-0362a010826fc18bc
```

## bastionのインスタンス作成
### 1. キーペアを作成する  

```
aws ec2 create-key-pair --key-name bastion_cli_key --query 'KeyMaterial' --output text > bastion_cli_key.pem
```
### 2. bastionインスタンス用セキュリティグループ作成。22番ポートにくるSSHのみ許可  

```
aws ec2 create-security-group --group-name SSHAccess --description "Security group for SSH access" --vpc-id vpc-0074168dfa72a5826
aws ec2 authorize-security-group-ingress --group-id sg-04fa98bf54b2c3602 --protocol tcp --port 22 --cidr 0.0.0.0/0
```
### 3. EC2インスタンス作成。無料枠のAMI（Amazonマシンイメージ）を選択  

```
aws ec2 run-instances --image-id ami-0d7ed3ddb85b521a6 --count 1 --instance-type t2.micro --key-name bastion_cli_key --security-group-ids sg-04fa98bf54b2c3602 --subnet-id subnet-0bb7116ca38f5a80f
```
### 4. ElasticIPを新規発行  

```
aws ec2 allocate-address --domain vpc
```
### 5. ElasticIPをEC2インスタンスにアタッチ  

```
aws ec2 associate-address --allocation-id eipalloc-0cab4412fd7b91c64 --instance i-03472fc06af6b8690
```
### 6. SSHで該当のインスタンスに接続できるか確認（powershell使用）  

```
ssh -i .ssh\bastion_cli_key.pem ec2-user@52.198.210.184
```

うまく接続できていれば、以下の図まではできている。
![AWS_bastion_1.jpg](https://qiita-image-store.s3.amazonaws.com/0/105281/ab8e69b5-8fed-37d1-5d02-214bba2b63c4.jpeg)


# 疑問に思った点、つまずいた点

* VPC消したら紐づくセキュリティグループも消える？→消える
* VPC内にEC2たてるとなると、サブネットが必ずいる？→いる
* awscliの`--query`はwindows10のコマンドプロンプトではうまく実行できない。powershellを使う


つづく
https://qiita.com/nannany/items/db7f73d403d75f81881e
Qiitaプチ炎上の著者が語る、ネットでの炎上対策はどうする？自然災害時のレジリエンスの持ち方、メンタル対策と根本的に同じかもしれない。悪いイメージの咀嚼を止める。人間の心理構造について理解する。マインドフルネスと瞑想の習慣はとても役立つ。いつ起こるかわからない自然災害、ネット炎上対策のリテラシ。

Qiitaプチ炎上の著者が語る、ネットでの炎上対策はどうする？自然災害時のレジリエンスの持ち方、メンタル対策と根本的に同じかもしれない。悪いイメージの咀嚼を止める。人間の心理構造について理解する。マインドフルネスと瞑想の習慣はとても役立つ。いつ起こるかわからない自然災害、ネット炎上対策のリテラシ。


# 炎上についてはいくばくか経験があるので、この機会に、

10個位のトピックを語れるような気もする。まず今の心理状態は、全くひどい状態ではない。むしろ5分前ぐらいには、ついいたずら心が芽生えて、どんなネタにしてやろうかと、ワクワクさを感じていた位だ。

# だけど、人間は誕生の予測不可能性を持っていると思う。

つまり、自分の心理状態がどうなるかと言う事は、予測ができない。これは災害時にも言えることだ。例えば大震災で心にダメージをおうとき、最初は全く大丈夫のように思える。

だがこれが、じわじわと感覚の麻痺が終わると、ボディーブローのように恐怖や、心理的ダメージが深まってゆくのだ。これはある意味必然的な心の働きだとも言えるけれども、ある部分では、悪いイメージ、ショッキングなイメージを頭の中で咀嚼してしまうからこそ、起こるかもしれない。

詳しい心理学的な話はわからない。だが、マインドフルネスを理念実践している僕は、なんというか、どのぐらいダメージを受けるかは自分が決められるような気がする。

ここにはとても複雑な心理的昆布のようなものが働いている。なんというか、逆説的なロジックというか。心理的昆布じゃないよ。コンボだ。

# これはうまく伝わらないと思うのだけれど、自分がどれだけダメージを負っているかと考えること自体が、自分にダメージを負わせていくことだ。

この感覚がわかるだろうか。自分自身を判断している時、まさにその真っ最中、僕らは自分自身の心の色に影響与える。

ネットでの炎上と、その対策。これはほぼ、自然災害の時にメンタルを立て直す方法と同じなのではないだろうか。片方はデジタルで、片方はアナログかもしれないけれど、人間の心がレジリエンスを発揮するその法則は同じのような気がする。

まずショックがあり、その次に麻痺状態が起こり、ハイテンションな状態になる。そしてしばらくして、衝撃がだんだんと伝わり、痛みが増してくる。そしてフラッシュバックが起こったり、何度も悪いことを頭の中で反芻することによって、自分自身で自分の脳にダメージを負わせるターンに入る。

# マインドフルネスの技術や、セルフトークの技術が役立つのは、この頭の中での反芻行為を、方向付けることができたり、客観視できることだ。

そして、自分自身の状態も1秒単位で敏感に察知することができる。これはマインドフルですね技術の方。例えば、ほんのつい1秒前までメンタルは問題ないように思えたのに、1秒後には何か問題が生じている。

この心の異常状態をいち早く察知できることが、レジリエンスを保つ上ではとても重要だと思う。なぜなら、異常事態を自分自身が検知できずに、自分のメンタルは大丈夫だと言うイメージを持ったまま、放置する事はとても危険だからだ。

# ここで言う検知、客観視、察知した後の対応については、心や肉体のとてもディティールに至る部分の説明が必要なので、これはマインドフルネスの深い世界の中の話になる。

野球でも1本ヒットを打つためにものすごく語り切れない位の多くの技術が必要なように、心の自立も、それぐらい奥深いものであるから、短いツイートで語ることができない。だけどマインドフルネスや瞑想の瞬間は本当にオススメだ。

ところでいくら記事がプチ炎上したからといって、人間の興味関心は本当に、光よりも早く移ろうであるから、なるべく早くこの波に乗って、炎上対策というか、炎上から関連して考えたことについて、少しでも人の耳に入れてみたいものである。

こういう時でも、iPhoneの音声入力など、いつでもどこでもアウトプットができる環境があると、機敏に人にメッセージを伝えることができて、良いかもしれない。

ところで京都での人狼ゲームではしゃぎすぎて、喉がガラガラなのに、iPhoneの音声入力で語っている俺だぜ。ボイストレーニングも必要かもしれないな。
 https://t.co/QKvZPUSJ3a

![image](https://user-images.githubusercontent.com/13635059/51439039-f71ec700-1cf7-11e9-9f4b-71a2d754c8d9.png)


---

https://twitter.com/yumainaura

https://github.com/YumaInaura/YumaInaura/issues









<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
文字コード関係と正規表現

文字化けするときは下記のようにすると上手くいくことがよくある。

``` python
with open(path,encoding='utf-8_sig') as f:
    text=f.read()
```

正規表現で文字を取り出すサンプル

``` python
import re, codecs, pandas as pd
path=r'input\taobao_utf8.txt'
with open(path,encoding='utf-8_sig') as f:
    text=f.read()
str='[0-9]{4}-[0-9]{2}-[0-9]{2}.+\)'
rs = re.compile(str).findall(text)
str_date='[0-9]{4}-[0-9]{2}-[0-9]{2}'
str_shop='\([0-9]+\)'
result=[[re.compile(str_date).findall(s), 
         re.compile(str_shop).findall(s)] 
         for s in rs]
```
Railsチュートリアル躓き→解決箇所:2.1 アプリケーションの計画

#問題: heroku createできない

- 環境: AWSCloud9
バージョン設定はRailsチュートリアル内容に準じる。

- エラー表示： 
heroku: command not found

- 解決法: https://teratail.com/questions/121247
上記ページ記載の手順を実行。
heroku-cliのインストールで解決しました。
自分の場合はnodeバージョンは問題ありませんでした。
SQLアンチパターンは勉強するのに、炎上アンチパターンは勉強しないの? エンジニアの国語力について、人知れず記事を書いたつもりが、プチ炎上の要素がたくさん詰まっていた件。iPhone音声入力で日本語がおかしい。複数のツッコミどころ。感情的になりやすいトピック。炎上に必要な燃料が勢ぞろい。



# ふと書いた記事が、思いのほかプチ炎上していたんだぜ。

[エンジニアには国語的能力が重要だ。実は言語的能力が80%を占める文系の仕事だとさえ思える。理系的な要素だけでプログラミングが成り立つと思ったら間違えた。ロマンロランのジャンクリストフを読もう。良い小説だから。日本語や言語的なものを大いに愛そうじゃないか。僕らプログラマは。 - Qiita](https://qiita.com/YumaInaura/items/8a0cc0721ae78175bce4)

![image](https://user-images.githubusercontent.com/13635059/51438972-e7eb4980-1cf6-11e9-8525-a0178b4e3f06.png)

![image](https://user-images.githubusercontent.com/13635059/51438990-3dbff180-1cf7-11e9-9665-c3c8beeaa3d7.png)

# Twitter 民の反応

Aさん

>タイトル要約できてないから日本語力低そう

Bさん

>言語能力の破綻した意味不明なメールを送信する人間を野放しにする企業が存在する事こそ害悪である

Cさん

>吐きそう

# お褒めに預かるお言葉もいくつか

頂いていた気がする

# 他の人のツイートに着想を得て、エンジニアの国語力について書いたもの。



僕はiPhoneの音声入力で、Twitterでツイートした結果を、ほとんど誤字脱字も修正せずに、技術情報サイトにポストしているわけだけれど、いくつかの燃料が重なった。 https://t.co/C7krn15QPY

ふともとの技術共有サイトを見てみると、なんでこんなにアクセスがあるんだろうと思ったら、はてなブログのホットエントリーに入ったり、Twitterでほんの少しだけパズっていたみたいだ。

# こういう時と言うのは、1番最初はとても笑えている状態。笑い飛ばせる感じがする。



だけど、炎上と言うものがだんだんと自分にダメージを負わせて、考えれば考えるほど、どつぼにはまるパタンが、今までの人生では多かったな。

プチプチ炎上した理由としては、1つは、日本語について語っている記事なのに、日本語がおかしかったこと。これはiPhoneの音声入力と言う、入力デバイスの問題が大きい。



もう一つは、エンジニアには理系的な能力より、国語的な能力の方が大事だと言う、そもそもエンジニアを煽りやすい内容だったこと

# 要するに、1つの記事を援助させようと思ったら、なんだかちょっとおかしいと言うような、ポイント複数作っておいて、様々な燃料、花火のように爆発物も、その中に用意しておくと良いかもしれない。

炎上と言うものの歴史も長いので、炎上の対策はおろか、うまく炎上させる方法、炎上マーケティングの手法も、相当に作り込まれてきているんじゃないだろうか。

例えば、ものすごく役立つ記事、いいねが千個ぐらいつく記事であっても、そのコメントの中には暴言とか人格否定的な言葉も含まれるし、ちょっと前にバズっていた著者の人は、Twitterで話しかけても返事がなく、もしかしたら悩みのツボに入ったのかなと勝手に想像している。

ましてや今回のような、面白おかしく揶揄されるターゲットとしての現場であれば、なおさら、著者のダメージは深く大きいかもしれない。なので、僕らは思いもよらない炎上に備えて、メンタルの持ち方を練習しておくべきかもしれない。少なくとも心構えぐらいは。

# ところでこうやって僕が語っているのも、このプチ炎上が、自分の心にどう作用するのか分からないので、せめて予防対策的に、セルフトークで自分自身と語って、免疫をばらまいておこうと言うような気持ちだ。

人はやはりとても社会的な動物なので、たとえデジタルの策の間の中であっても、1つずつの人の反応や言葉に、大きな反応をせざるをえない。今は冷静に書かれているとしても、今日や明日、自分がどう感じるかわからないのだから。

ここで語りたい事は3つぐらいある。いくつかの問題がやはり、複合的に絡み合っている。SNSの社会的評価の問題。自分では思いもよらなかったものが炎上したときの問題。その時の自分のメンタルの持ち方。マインドフルネスに関して。感情の予測不可能性。

ところで、こういったようにダメージを受けかねないときは、それを咀嚼するのは最悪の行為だ。僕らは、何かショッキングな言葉を言われたときに、それを何度も咀嚼して飲み干そうとするけれど、心理学的に言うとそれは、最悪の行為らしい。

# 何がメンタルにとって正しい対策なのか、僕には分からない。これは非常に難しい問題で、炎上に無理に対抗すれば、さらに傷を深めるだけだし、多勢に無勢で、とてもこの戦いは数ではかなわない。いや、戦いだと言うフレーミングもあれなのだけれど。

なんだかんだ言って、マインドフルネスやセルフトークの技術が、とても役立っていると思う。後は自営業時代、自分が運営しているサイトで何度も2ちゃんねるの人に炎上させられて、多少はバットケースがわかっていると言う経験も。

どうしたらベストなのかわからないけれど、やっちゃいけないアンチパタンは何個かあると思う。必死になって抵抗して、自分の正当性を主張すること。

炎上の渦の中に飲み込まれるように、すべてのメッセージに反応をつけてしまうこと。後は、ただひたすら頭を下げて謝罪したり、誤解を解くのもよくない。自分の心に反する自己抑圧は、これもダメージを負わせるだろう。

# まだまだ、あまりに多くのことが語りそうなので、今回は一旦筆を置くことにしようか。

SQLアンチパターンは勉強するのに、炎上アンチパターンは勉強しないの? エンジニアの国語力について、人知れず記事を書いたつもりが、プチ炎上の要素がたくさん詰まっていた件。iPhone音声入力で日本語がおかしい。複数のツッコミどころ。感情的になりやすいトピック。炎上に必要な燃料が勢ぞろい。 https://t.co/kKDvl0Fk5o

---

https://twitter.com/yumainaura

https://github.com/YumaInaura/YumaInaura/issues









<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
GithubにStripeの本番環境を間違えてアップロードしてしまった時

API Keysが公開された場合、新しいKeyに変更（Roll keys）することは可能でございます。

1）ダッシュボードの「開発者」＞「APIキー」にアクセス：https://dashboard.stripe.com/account/apikeys
2）変更したいKeyの右側にある「・・・」ボタンをクリック
3）「ロールキー」を選択
4）変更前のKeyはいつまで有効にするかを設定
5）パスワードを入力

変更前のKeyの有効期限は、immediatelyの方が良いかと思います。
<img width="248" alt="スクリーンショット 2019-01-20 21.02.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/216701/b02e58c4-ce58-1ec0-e997-851cd54c16c0.png">
気をつけましょう！！
ソフトウェア営業だけど、プログラミング始めます。

はじめまして。
ソフトウェア営業をしている20代です。

ひょんなことからプログラミングを始めました。
この業界にいる以上、技術者と会話するのが必須でただの営業に思われたくなかったというのもあります。

当初はJavaで学び、Java Silverまで取得しましたが、何か個人で生み出せるのか？というところに行き詰まり、
Rubyを学ぼうとしています。

Ruby on Rails含めてアウトプットしていくので、よろしくお願いいたします。
CentOS7 で Python 仮想環境を作る

# はじめに

CentOS7 で Python3.6、Python2.7 の仮想環境を作る方法をまとめておきます。

# Python3.6 で仮想環境を作る

CentOS7 の場合 epel から Python 3.6 をインストールできる。
Python3.3以降、venvが標準パッケージである。
venvで仮想環境を作る。

## Python3.6 + venv を入れる

```bash
yum install epel-release -y
yum-config-manager --disable epel
yum install --enablerepo="epel" python36 -y
```

## 仮想環境を作る

```bash
mkdir -pv $HOME/.venv
python36 -mvenv $HOME/.venv
```

## 仮想環境を有効にする

```bash
source $HOME/.venv/bin/activate
```

## 仮想環境を終了する

```bash
deactivate
```

# Python2.7 で仮想環境を作る

virtualenv を使う。

## virtualenv を入れる

```bash
yum install python-virtualenv -y
```

## 仮想環境を作る

```bash
yum install python-virtualenv -y
virtualenv -p /usr/bin/python2.7 $HOME/.virtualenv
```

## 仮想環境を有効にする

```bash
source $HOME/.virtualenv/bin/activate
```

## 仮想環境を終了する

```bash
deactivate
```

# 参考文献

virtualenv
https://virtualenv.pypa.io/en/latest/

venv
https://docs.python.org/3/library/venv.html

https://qiita.com/kumarstack55/items/0babae3f4f7180985217

@k8uwall さんコメント:
https://qiita.com/kumarstack55/items/0babae3f4f7180985217#comment-a889976a05d9cf81c5bd
> python-virtualenvをインストールしなくてもpython36だけ入れればvenv使えます。
苦手なDNS, SMTPをどう克服するか

ネットワークが専門だといいながら、苦手な領域が２つある。

１つは、DNS。

特に設定。

もう一つは、SMTP。

特に設定。

どちらも、魔法のような呪文が必要。

同じくらい苦手なものにBGPがある。
こちらは、設定する機会が少ないために、熟練していないだけという言い訳をしている。

ちなみに、今日、ブラウザでうまくつながらない２つのサイトを確かめた。


```
$ nslookup autosar.org
;; Got SERVFAIL reply from 2402:6b00:3e94:e600:1266:82ff:fe0d:42d4, trying next server
Server:		192.168.0.1
Address:	192.168.0.1#53

** server can't find autosar.org: SERVFAIL

$ dig autosar.org

; <<>> DiG 9.10.6 <<>> autosar.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 10169
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;autosar.org.			IN	A

;; Query time: 312 msec
;; SERVER: 2402:6b00:3e94:e600:1266:82ff:fe0d:42d4#53(2402:6b00:3e94:e600:1266:82ff:fe0d:42d4)
;; WHEN: Sun Jan 20 20:36:55 JST 2019
;; MSG SIZE  rcvd: 40
```


```
 nslookup www.searchdesk.com
Server:		2402:6b00:3e94:e600:1266:82ff:fe0d:42d4
Address:	2402:6b00:3e94:e600:1266:82ff:fe0d:42d4#53

Non-authoritative answer:
Name:	www.searchdesk.com
Address: 124.241.196.221

 dig www.searchdesk.com

; <<>> DiG 9.10.6 <<>> www.searchdesk.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47705
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.searchdesk.com.		IN	A

;; ANSWER SECTION:
www.searchdesk.com.	71471	IN	A	124.241.196.221

;; Query time: 13 msec
;; SERVER: 2402:6b00:3e94:e600:1266:82ff:fe0d:42d4#53(2402:6b00:3e94:e600:1266:82ff:fe0d:42d4)
;; WHEN: Sun Jan 20 20:37:58 JST 2019
;; MSG SIZE  rcvd: 63

```