OmniAICreator/Qiita-1.07M huggingface dataset:
エンジニアリング組織論への招待のCh1だけ読んでみた

エンジニアリング組織論への招待
 - Chapter1 思考のリファクタリング

Chapter1を大雑把にまとめると「エンジニアリング」とはなんぞ？という話。
まだChapter1しか読み終わっていないが面白かったので自分用にピックアップ/整理してみた。
※もっといろいろと書いているけど書き出すとキリがないので結構適当だし、感想もところどころに混じってます。


## 工学とは、エンジニアリングとは
工学とは何かを「実現」していく学問。
ここでいう「実現」というのは、曖昧な状態からスタートし、具体的・明確さを増やす行為。
この曖昧さが「不確実さ」
この過程が「実現」

この曖昧さ/不確実さを減らしていくということが「エンジニアリング」の本質とも言える。
曖昧さ/不確実さというのは「わからないこと」のこと。
人間にとって、「わからないこと」というのは本質的には「未来」と「他人」ぐらいしかない。
つまりエンジニアリングというのはこの「未来」や「他人」という不確実性と向き合って、それらを減らしていく必要がある。
ただ、この「わからないもの」に向き合うということには「不安」が伴われる。

情報を生み出すことが不確実性を下げることにつながるが、
ソフトウェアを書く以外にも不確実性の削減はできるし、それもまた「エンジニアリング」の一部と言える。


## 論理的思考の盲点
論理的思考というのはつまり演繹的思考のこと。
論理的思考には２つの重大な前提がある

- ルールと事象を正しく認知できること
- 正しく演繹できること

この二つができないと論理的に考えることはできないが、そもそも正しく認知することはかなりむつかしい。
また、「論理的に考える」には、「非論理的に考えてしまう」瞬間を知ることが大事。

これはわかる。
たまに思考してるときに、「あ、今感情で判断したなー」って時があるし。


## 観測できないものは制御できない
観測できるのはあくまで結果であって能力などではない。でも「行動」は観測できる。
他人の「スキル」や「心境」は観測できるものではないけども、そこから生まれる行動は観測できる。
コントロールできるものを使って間接的に制御するしかない。

## 視野、視座、視点
「良い」プログラマには問題解決のための眼がある。
人間はそもそも完全な全体像を捉えることはできないので、それらを受け入れ視野視座視点を広く鋭く高く考えるように鍛えていくことが大事。

## 人間の不完全さを受け入れる
重要なのは自分の知性に対する絶え間ない疑いと、自分自身への洞察力。内省する力と言い換えることもできる。
自分自身がどのようなタイミングで間違った認知をし、間違った意思決定をしてしまうのかを知ることが重要。

よく言われる「失敗学」と同じような発想？

「自分は他人ではない」という当たり前の事実から立脚して、いかにコミュニケーションの不確実性を減らしていけるか？
これがエンジニアリングにとって重要な態度になる。
真に組織に求められるコミュニケーション能力というのは、コミュニケーションの不確実性を減少させる能力のことといえる。

# 勝手なまとめ
乱暴に簡単にざっくりとまとめてしまうと
何かをしようとした時のスタートはどうしたって曖昧さが多いし、それに対してやりたいことを実現していこうとするために情報を生み出していく必要がある。
ただ、その段階において思考や情報の非対称性、限定的な合理性によってカオスが生じてしまう。
って感じかな。
演繹法と仮説法は似てるけど全然違うというのは言われないと気がつかないかも。
仮説を立てるのはスキルではなくその仮説となる発想が出せるかどうかというのも面白い。
PDCAサイクルを回しているけど、その仮説/検証ってちゃんとわかってる？というのは意識しないといけないんだろうなとも思う。


書き散らしてから気が付いたけど、Qiitaに広木さんご当人が[記事を書かれている](https://qiita.com/hirokidaichi/items/195d42ee056ea85a3150)のね。
Pythonista Documentation

英語がわからないので機械翻訳しました。
# Pythonista Documentation
ようこそ！これはPythonistaのドキュメントです。公式のPython 3.5.1のドキュメントに基づいており、
Pythonista向けに特別に開発された追加のモジュール。
ご質問、ご意見、またはPythonistaで作成したことを共有したい場合は、[コミュニティフォーラム](http://omz-software.com/pythonista/forums)をご覧ください。

[Using Pythonista(Pythonistaの使用)](http://omz-software.com/pythonista/docs/ios/pythonista.html)

- PythonistaのUIの概要、いくつかのヒントと秘訣

[What's New in Pythonista](http://omz-software.com/pythonista/docs/ios/new.html)

- 詳細リリースノート

[Pythonista Modules](http://omz-software.com/pythonista/docs/ios/index.html)

- iOS専用に開発された追加モジュール

[Community Forums](http://omz-software.com/pythonista/forums)

- フォーラムにアクセスして、他のPythonistasとアイデアを共有

[Language Tutorial](http://omz-software.com/pythonista/docs/tutorial/index.html)

- 公式のPython言語チュートリアル

[Library Reference](http://omz-software.com/pythonista/docs/tutorial/index.html)

- これをあなたの枕の下に置いてください

[Language Reference](http://omz-software.com/pythonista/docs/reference/index.html)

- 構文と言語の要素について説明します。

[Global Module Index](http://omz-software.com/pythonista/docs/py-modindex.html)

- すべてのモジュールへのクイックアクセス

[General Index](http://omz-software.com/pythonista/docs/genindex.html)

- すべての関数、クラス、用語

[Glossary(用語集)](https://qiita.com/maboy/private/e08137a6d39242c61fdd)

- 説明される最も重要な用語

[What's New in Python(Pythonの新機能)](http://omz-software.com/pythonista/docs/whatsnew/index.html)

***

[NumPy User Guide](http://omz-software.com/pythonista/numpy/user/index.html)

- NumPyは、Pythonを使った科学計算の基本パッケージです。

[NumPy Reference](http://omz-software.com/pythonista/numpy/reference/index.html)

- NumPyのリファレンスドキュメント

[matplotlib Documentation](http://omz-software.com/pythonista/matplotlib/index.html)

- matplotlibはPython 2Dプロットライブラリです。

[SymPy Documentation](http://omz-software.com/pythonista/sympy/index.html)

- SymPyはシンボリック数学のためのPythonライブラリです。

***

[About the documentation](http://omz-software.com/pythonista/docs/about.html)

[History and License of Python](http://omz-software.com/pythonista/docs/license.html)

[NumPy License](http://omz-software.com/pythonista/docs/numpy/license.html)

[Copyright](http://omz-software.com/pythonista/docs/copyright.html)
Oracleレスポンスファイルの設定箇所だけ確認する(grepで空行とコメントを除外する)



レスポンスファイルの設定箇所だけ確認する
→ grep で空行とコメント（#）を除外する。

#コマンド

``grep -v -e '^\s*#' -e '^\s*$' db_install.rsp``


#実行例

```
$ grep -v -e '^\s*#' -e '^\s*$' db_install.rsp
oracle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_v18.0.0
oracle.install.option=INSTALL_DB_SWONLY
UNIX_GROUP_NAME=oinstall
INVENTORY_LOCATION=/u01/app/oraInventory
ORACLE_HOME=/u01/app/oracle/product/18.0.0/dbhome_1
ORACLE_BASE=/u01/app/oracle
oracle.install.db.InstallEdition=EE
oracle.install.db.OSDBA_GROUP=dba
oracle.install.db.OSOPER_GROUP=dba
oracle.install.db.OSBACKUPDBA_GROUP=dba
oracle.install.db.OSDGDBA_GROUP=dba
oracle.install.db.OSKMDBA_GROUP=dba
oracle.install.db.OSRACDBA_GROUP=dba
oracle.install.db.CLUSTER_NODES=
oracle.install.db.config.starterdb.type=
oracle.install.db.config.starterdb.globalDBName=
oracle.install.db.config.starterdb.SID=
oracle.install.db.ConfigureAsContainerDB=
oracle.install.db.config.PDBName=
oracle.install.db.config.starterdb.characterSet=
oracle.install.db.config.starterdb.memoryOption=
oracle.install.db.config.starterdb.memoryLimit=
oracle.install.db.config.starterdb.installExampleSchemas=
oracle.install.db.config.starterdb.password.ALL=
oracle.install.db.config.starterdb.password.SYS=
oracle.install.db.config.starterdb.password.SYSTEM=
oracle.install.db.config.starterdb.password.DBSNMP=
oracle.install.db.config.starterdb.password.PDBADMIN=
oracle.install.db.config.starterdb.managementOption=
oracle.install.db.config.starterdb.omsHost=
oracle.install.db.config.starterdb.omsPort=
oracle.install.db.config.starterdb.emAdminUser=
oracle.install.db.config.starterdb.emAdminPassword=
oracle.install.db.config.starterdb.enableRecovery=
oracle.install.db.config.starterdb.storageType=
oracle.install.db.config.starterdb.fileSystemStorage.dataLocation=
oracle.install.db.config.starterdb.fileSystemStorage.recoveryLocation=
oracle.install.db.config.asm.diskGroup=
oracle.install.db.config.asm.ASMSNMPPassword=
```
【JavaScript】繰り返しの処理 while文 と for文 について学ぶ

__「ノンプログラマのためのJavaScript はじめの一歩」 第2章 JavaScriptの文法 より__

## while文

- 繰り返し処理の基本的な書き方
- 色んな繰り返しを柔軟に書くことができる
- 繰り返し処理を終了するための処理文がないと無限ループになってしまう

```javascript
while (条件式) {
  処理文;
}
```

## for文

- 初期化式・条件式・更新式 をまとめて1箇所に書く
- 繰り返す回数がわかっていて、単純な繰り返し処理を書くのに適している

```javascript
for (初期化式; 条件式; 更新式) {
  処理文;
}
```

## 迷ったところ

while文 と for文 をどう使い分けるのか？
調べてみると、繰り返し処理にはこの2つ以外にも種類があることがわかった。
ただ、本に紹介されていない使い方も含めて考えてみたものの、今の段階ではそこまで想定することはできなかった。

for文 でできることは while文 でもできるけど、そういう用途であれば「初期化式・条件式・更新式」を1箇所にまとまっている点で for文 の方がよさそう。
現段階では「繰り返す回数がわかっている場合は、for文を使う」という結論に至った。

-----

###### 参考サイト

- <a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Loops_and_iteration" target="_blank">ループと反復処理 - JavaScript | MDN</a>
AVS をRaspberry Piで動かすための"クライアント ID"について

### はじめに
Raspberry Pi B3上でAVS(Alexa Voice Service)を動かそうとしたときに、認証エラーが発生。
チュートリアルやavs-device-sdkのissueをみるもはっきりわからず。
この記事では私がハマった部分について詳細を記載します。

## 前提条件
Raspberry Pi B3
OS: NOOBS 2.8.2 Release Date 2018-6-28
https://www.raspberrypi.org/downloads/noobs/

avs-device-sdk
https://github.com/alexa/avs-device-sdk/

## リファレンス
Raspberry Pi Quick Start Guide with Script
https://github.com/alexa/avs-device-sdk/wiki/Raspberry-Pi-Quick-Start-Guide-with-Script

その他のプラットフォームおよびデバイス向けのコードベースのリンク
https://developer.amazon.com/ja/docs/alexa-voice-service/code-based-linking-other-platforms.html

Input AVS Credentials
https://developer.amazon.com/ja/docs/alexa-voice-service/input-avs-credentials.html

## ハマったところ
Alexa起動時の認証プロセス時に認証されない。
 UNRECOVERABLE AUTHORIZATION ERROR: INVALID_CBL_CLIENT_IDの発生
 Entering limited interaction mode:
![2018-09-02-120811_1824x984_scrot.jpg](https://qiita-image-store.s3.amazonaws.com/0/110541/c5682cc8-eccd-1541-b4ab-d7ebdf2e8b0c.jpeg)


# CLIENT IDについて
Build前に、config.txtにCLIENT IDとPRODUCT IDを記載します。しかしこのCLIENT IDが非常にわかりづらい落とし穴になります。

![2018-09-02-120438_1824x984_scrot.jpg](https://qiita-image-store.s3.amazonaws.com/0/110541/c589f690-9dae-e902-96bb-dc5b27f01e26.jpeg)

開発者コンソール上に登録したには以下のように表示されています。
ここに「クライアントID」と記載されており、これをクライアントIDに記載してしまいます。
SDK 1.6もしくはそれより前のバージョンにはこのクライアントIDを記載する必要がありました。
しかしSDK1.7からはこちらのクライアントIDを記載すると上記のように認証エラーが発生しています。

![2018-09-02-121007_1824x984_scrot.jpg](https://qiita-image-store.s3.amazonaws.com/0/110541/142b3ed0-e55b-7ee0-81b2-f4d9634951af.jpeg)

![2018-09-02-121406_1824x984_scrot.jpg](https://qiita-image-store.s3.amazonaws.com/0/110541/720848f1-398e-fe5e-c978-da4a7c0feb02.jpeg)

## 対処方法
Raspberry Piにてavsを使用する場合には、使用するクライアントIDを新たに生成する必要があるようです。
上記の「マイ商品」の中にある「セキュリティプロファイル」をクリックします。

![2018-09-02-121137_1824x984_scrot.jpg](https://qiita-image-store.s3.amazonaws.com/0/110541/09120486-d29b-1587-7091-38e8e42248e2.jpeg)

この中の「他のデバイスやプラットフォーム」をクリックします。

![2018-09-02-121240_1824x984_scrot.jpg](https://qiita-image-store.s3.amazonaws.com/0/110541/013fd133-b85f-2437-e28a-afa2447ea929.jpeg)


クライアントID名を記載し、一般IDをクリックするとavsdp_device_settings_client_id_titleが生成されます。このavsdp_device_settings_client_id_titleこそが、Raspberry Piにてsetup.txtに記載するCLIENT IDの部分に記載するIDとなります。

![2018-09-02-121209_1824x984_scrot.jpg](https://qiita-image-store.s3.amazonaws.com/0/110541/0711c245-5e26-7373-c1fa-b435a53cecc7.jpeg)

## 終わりに
1.7のリリース直前のSDK1.6からavsに取り組みはじめ、1.7になり、認証ができなくなり、ハマってしまいました。
Security Profile Managementのタブの中に「Web Setting|Android/Kindle Settings|iOS Settings」とあり、肝心な「Other Device/Platform」が表示されずにハマってしまいました。
「他のデバイスやプラットフォーム」を探すのにちょっと時間がかかってしまいました。
Webでのチュートリアルにもこの点を詳細な情報がなかったのですが、いつの間にか公式なチュートリアルも記載されておりました。
英語版ですが、非常にわかりやすく、詳細についてはこちらの記事を参照されるのが良いかと思います。

https://developer.amazon.com/ja/docs/alexa-voice-service/input-avs-credentials.html
macのwgetで連番のファイルをダウンロード

&#x1f530; 自分用の思い出しメモ

連番になっているファイルをDLしたかったので、`wget`で連番でDLしようと探す。
参考：[wgetでこういう時はこうする!! - Qiita](https://qiita.com/hirohiro77/items/b774908436ec032df719)

```shell:だめ
$ wget -O 保存先-{00..99}.jpg http://ダウンロードしたい.ページ/{00..99}.jpg 
```

環境依存かも知れないが、何故か出来なかった。
1桁のときに何故か01,02など2桁にならなかった。
実際のURLには{}とか[]とか半角スペースが混じっており、%付きの文字（パーセント・エンコーディングというらしい）になっていたからかも。

なので以下のやり方を試す

参考：[wgetで連番ダウンロード - ヒトデと珈琲](http://starfishandcoffee.seesaa.net/article/187710941.html)

```shell:できた
$ for i in `seq -w 1 99`; do wget -O 保存先-${i}.jpg http://ダウンロードしたい.ページ/${i}.jpg; done
```

できた。

▪ 追記(2019/09/30)
小生がshellをfish shellにしたため、上記では動かなくなったので以下追記

```shell:fishでもできた
$ for i in (seq -w 1 99); and wget -O 保存先-$i.jpg http://ダウンロードしたい.ページ/$i.jpg; end
```

for文でdoneじゃなくendを使う、というので詰まった。
また、サブコマンドは `$` なしの `()` で記述。展開される。
あと、doではなくandというのもなかなか独特。
極めつけが変数の展開で、 `$` の後 `{}` が要らない。
なんつーやつだ。
リニアモーターカーの加速度等をiPhoneで計測してみた

リニアモーターカーの試乗に当たりました。そこで、山梨の実験センターまで乗りに行き、iPhoneで加速度等を測ってみました。実は2度目なのですが、前回はミスで上手く測れて無かったので、今回はリベンジです。

使用したのはiPhoneのアプリ「[SensorLog](http://sensorlog.berndthomas.net/)」です。このアプリは加速度だけではなく、角速度や姿勢、GPSデータ、気圧計などのデータも含めて100Hzで保存するという優れものです。これを2台のiPhoneで動かして、平均を取っています。

リニアの試乗は約30分、実験線を2往復します。ただし乗降駅が途中にあるので、最初は駅からバックで東京側の端まで走行し、そこから前に500km/hを出して長野側の端へ。さらにまた500km/hでバックして東京側へ。（この際最初よりも、やや長野側に停車する模様。）そして駅に戻るという、足し算すると2往復になる感じです。

早速加速度を取り出してみます。正が東京側への加速です。加速度だけ見ると、新幹線と同じぐらいですね。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/117634/4542081e-e594-2e7d-e3ff-d6e2db3d578b.png)

これを積分すると速度のグラフが得られます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/117634/1e64e01f-0173-9034-088c-52492f373772.png)

もう一度積分すると、位置のグラフとなります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/117634/6d3d0173-d8eb-9fe1-5675-0a0478d75952.png)

いやいや、iPhoneの加速度計ごときで、最初と最後がこんなにぴったりと合うわけないじゃん、と思われるかもしれませんが、はい、その通りです。実際には積分するとかなり発散してしまうため、

* 最初と最後は同じ位置
* 最初と最後は速度が0
 
といった拘束条件を取り入れて、加速度計のバイアスなどを修正しています。そこまでやると、何となくそれらしいグラフが作れるものですね。

GPSの記録で答え合わせをしてみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/117634/16155ba0-35fa-012f-dbdc-10efbfcfea81.png)

赤い線がGPSの記録で、オレンジの部分はGPSの誤差（標準偏差？）を表しています。トンネルが途切れるような所でしか取れていないので、線が水平になっている部分では一番左端の点のみが信用できると思われます。それを考慮すると、まあまあ良い線を行っていると思います。

次のグラフは、位置と速度の相平面図です。横軸に位置、縦軸に速度を取ってプロットするとこんな感じになります。電車に詳しい人って、この図が好きですよね。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/117634/e86afe77-5b4e-9b5d-dcd7-1dc1811735f8.png)


速度と加速度の相平面図です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/117634/49e129c6-cb0d-0fd7-3df4-4efd314324a3.png)
最初の5秒間を取り出すとこんな感じ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/117634/0bc61062-b5db-4fda-fcfd-b82f2ce977a0.png)


最初の2分間ではこうなります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/117634/29d100a0-5077-206f-a1ec-9de56a598533.png)

130km/h辺りで急に落ちていますが、ちょうどリニアが車輪走行から浮上走行に切り替わった瞬間がここです。車輪抵抗が無くなるので加速度はむしろ上がりそうなものですが、下がっているのは加速に使っていた電力の一部を浮上用に回すから？

不満点は、500km/hの定速区間がもっと長かった気がすることです。色々なノイズを拾ってしまい、iPhoneでは限界があります。データを見て楽しむぐらいはなんとか出来るかなという感じです。
【新人向け】ペアプロ入門

## この記事の対象
- ペアプロをやったことないのでやり方を知りたい
- ペアプロをやっているがうまくいかない
- ペアプロをやっているがイマイチ目的がわからない

上記に当てはまる人に対して何らかの参考になればと思い、書かせてもらいます。
かくいう私も、ペアプロ歴半年くらいで、まだまだ未熟なのですが、ようやくペアプロの面白みがわかってきたところです。

## ペアプロとは
はじめにペアプロについて簡単に説明させていただきます。私が実際にやっていることベースで書いていくので、書籍に書いてあることとは多少乖離があるかもしれませんが、ご容赦ください。

#### 1つのプログラムを2人で開発する
ペアプロ中は常に2人1組で、ドライバー（実装する人）とオブザーバー（見守る人※厳密には見守るだけではない）に分かれます。ドライバーはコーディングするだけでなく、これから何をしようとしているかなどを事細かにオブザーバーに伝えます。オブザーバーはドライバーが何をしようとしているかを聞き出します。また、ドライバーがハマった時などにオブザーバーは答えを教えるのではなく、ドライバーが気づきを得られるようなヒントを出すと良いです。

#### 適当な時間で入れ替わる
基本的には20分〜30分で入れ替わるようにしています。ただし、後述するペアの組み方によってはここのバランスを変えるのはありだと思っています。

#### コミュニケーションをよくとる
ペアプロ中、沈黙が30秒続くのはよろしくないです。というか、気まずくなります。なので、ドライバーが喋っていないときは、オブザーバーがしっかりコントロールをし、何をしているのか？何に詰まっているのか？などを聞いてあげるようにします

#### 小さな目標を設定する
ペアプロを開始する前に、ゴールの設定を必ずしましょう。慣れないうちは2~3時間（ペアを2セット〜3セット）で達成するような小さな目標が好ましいです。 

#### こまめに休憩をとる
良いペアプロができているときは、とにかく疲れます。なので、集中が切れそうなときは遠慮なく休憩を要求しましょう！

#### 相手と自分へのリスペクトを忘れない
最後に精神論的なことではありますが、お互いを尊敬しあいましょう。ペアプロは自分の技術をひけらかすための場所ではありません。また、できないからといって萎縮する必要もありません。お互いを良きバディだと思い、お互いを信じあい、目の前のタスクに集中するように心がけましょう。

## ペアプロの目的
続いてペアプロの目的・メリットを私が享受している範囲で列挙していきます。

#### 技術の共有ができる
まず一番最初に浮かぶのが教育的観点です。経験の浅いプログラマにとっては、1人でAPIを1本実装することはなかなかハードルの高いことです。ですが、ペアプロでペアがいることでそのような実装も可能になり、自信を醸成することができます。

#### レビューコストが減る
ペアプロをすることで、最低限の品質は担保されます。なので自然とレビューコストは下がります。実際にソロコーディングとペアプロで実装されたもので比較すると、ペアプロで実装されたものの方がバグやtypoは少ない傾向にありました。また、レビューできる人間が増えるという側面もあります。

#### 新規参入者の受け入れコストが減る
プロジェクトに新規参入者が増える度に、命名規則やコーディングルールを教えることで毎回コストが発生します。しかし、ペアプロを実施することで常に、片方がレビューしている状態になれるので、この問題を解決することができます。

#### チームビルディングにつながる
実際、ペアプロをするまではプロジェクト内の人のことをあまり知らなかったのですが、ペアプロをしてからはコミュニケーションが活発になり、お互いのことをよく知るようになりました。

#### ハマる時間が短くなる
これは、プログラマなら誰もが通ったことがあることだと思いますが、新しい技術を使うタイミングや何か新しい処理を加えるときに、どハマりします。その時にペアプロだと、お互いに話をしているときにどこでハマっているのか閃いたり、オブザーバーが先回りして調べておくことができます。

#### ペアプロ≠コスト増
よくペアプロをやることで、単純にコストが倍になるのでは？という指摘を受けるのですが、上述のメリットのとおり、ペアプロとソロコーディングでコストの差は、ほとんどないと感じてます。なんなら、ペアプロの方が早いケースもあります。もちろん、ベテランだけのチームとかでしたらソロコーディングの方が早いでしょうが、一般的なチームであれば、おおむね当てはまると思います。

## ペアの組み方

最後にペアの組み方について触れておきます。
まず、前提としてプログラマを3種類（ベテラン・中堅・新人）に分類するとします。基本的にはどの組み合わせで組んでも問題はないのですし、様々なペアを試してるべきではあるのですが、ペアの組み方で求められることや気をつけなければならないことがあります。その点について、特に気をつけるべき組み合わせを見ていきたいと思います。

#### ベテラン＆ベテラン
この組み合わせには、この2人にしかできないようなハイレベルなタスクをやることが求められます。ただ、このペアは経験や実力があるが故に、こだわりすぎてしまうというリスクもあるので、どこかでそのような欲求を抑えることも求められます。

#### ベテラン＆新人
この組み合わせには、新人がベテランに依存しすぎるリスクが潜んでいます。なので、新人がドライバーをやる時間を多めに儲け、アウトプットの場にするなど調整が必要です。

#### 新人＆新人
この組み合わせは自信を喪失させないように気をつける必要があります。あまり高度な目標を課してしまうと、達成できずに自信を喪失させてしまいます。なので、極力難易度を抑え、達成が見込めるようなタスクを課して、自信をつけさせることを目的とします。

## まとめ
簡単ではありますが、私の経験ベースでペアプロについてまとめさせてもらいました。私自身、ペアプロを開始したばかりの頃はあまり乗り気ではなかったのですし、先輩と組むことが憂鬱な時もありました。ですが、今ではペアプロを本当に面白いと思っています。また新たな気づきを得たらここに追記したいと思っています。
Kerasにおける"_make_predict_function()"の重要性

#背景

- Kerasでモデルを作った際(modelという変数としよう)、公式ドキュメントでは、推論するときにmodel.predict関数を使えばいい、としている。
- その中で、実はmodelクラスには_make_predict_functionというものが存在している。この関数は、推論前に以下のようにして実行できる。これは何なのか？と思い調べたら、めちゃくちゃ重要だった。

```
model._make_predict_function()
```

# _make_predict_function()の意味

- 普通モデルが実行されるとき、「GPU上でのモデルのビルドとコンパイル」そして「実行」という２段階の処理が行われる。
- 以下のページの議論によると、 **実は普通にmodel.predict()をいきなり呼ぶと、この２段階の処理が毎回実行されて、めちゃくちゃ遅くなっている** のだという。
- そこで、 **_make_predict_function()を先に実行しておくと、predictするときに「GPU上でのモデルのビルドとコンパイル」が行われず、単に「実行」だけできるようになり、処理が高速化される** らしい。
- しかも、公式ドキュメントには載っていないらしい笑
    - https://github.com/keras-team/keras/issues/6124

#まとめ

- 単純にpredictを使っていると、pythonプログラムによってはエラーで落ちてしまい、実行できなくなったりするので、要注意！
    - 私の場合は、ROSから画像データを読み込んで画像認識するpythonプロラムで以下のようなエラーがでましたが、_make_predict_function()を使うことでエラーがでなくなりました。
    
```
ValueError: Tensor Tensor("0_conv_1x1_parts/BiasAdd:0", shape=(?, 80, 60, 8), dtype=float32) is not an element of this graph.
```

- Kerasでの推論プログラムでは、_make_predict_function()を使いましょう！
bitcoind 覚書き



# 通常起動
```shell:general
$ bitcoind
```
特にオプションを付けずに起動すると、macOSの場合`/Users/<user>/Library/Bitcoin`にデータが保存される。
初起動の場合、Bitcoinディレクトリは自動生成される。
実際のチェーンデータは`Bitcoin/blocks`配下にダウンロードされていく。


# データディレクトリを指定して起動
```shell:datadir1
$ bitcoind -datadir=<dir_path>
```
デフォルトの`/Users/<user>/Library/Bitcoin`ではない場所にデータを保存したい場合に使用する。`<dir_path>`で指定したディレクトリに`Bitcoin`ディレクトリが生成される。
Bitcoinのブロックチェーンはとても大きなデータ(2018/9初頭時点で230GB〜)になるため、僕は外部SSDに保存しています。USB接続したSSDのマウントポイントが`/Volumes/BITCOIN-SSD`とすると以下のようになる。

```shell:datadir2
$ bitcoind -datadir=/Volumes/BITCOIN-SSD
...起動...

$ cd /Volumes/BITCOINSSD | ls
Bitcoin
$ ls Bitcoin
banlist.dat       blocks            debug.log         mempool.dat
bitcoin.conf      chainstate        fee_estimates.dat peers.dat         wallets
```
ちなみに、僕は毎度`-datadir=xxxx`とオプションを付けるのが面倒なので、
`/Users/<user>/Library/Bitcoin`に`/Volumes/BITCOIN-SSD/Bitcoin`へのシンボリックリンクをつけている。

```shell
ln -s /Volumes/BITCOIN-SSD/Bitcoin /Users/<user>/Library/Bitcoin
```
こうすることで、毎度オプションつけなくても`bitcoind`だけで希望のディレクトリを利用している。


# Testnet Mode
開発時に、毎度本番データを使う人はまずいないと思います。
Bitcoinも然りで、そのために`testnet`というものがあります。
→　[testnet](https://en.bitcoin.it/wiki/Testnet)
`testnet`は本番チェーンとは完全に切り離されており、実際の通貨としては使用できない仕様となっているということです。現在はversion3の`Testnet3`が運用されています。テストデータとはいえ、世界中の人のテスト取引データが書き込まれているちゃんとしたテストデータなので、本番に準じた環境としてテストできそうです。
`testnet`のトランザクション履歴はこのサイトで確認することもできます。
→　[BLOCKCYPHER](https://live.blockcypher.com/btc-testnet/)

`testnet`を利用して`bitcoind`を起動する場合は、`-testnet`オプションを付けます。

```shell:testnet
$ bitcoind -testnet
```
このモードで起動した場合、`Bitcoin`ディレクトリ配下に`testnet3`ディレクトリが生成され、そこにブロックチェーンデータなどがダウンロードされていきます。そのデータサイズは9月初頭現在14GB程度です。
また、`bitcoind`と対話する際には、`bitcoin-cli`にも`-testnet`オプションを付ける必要があります。

ちなみに、`testnet`もテストとはいえ本番Bitcoinと同じくそのコインの数は有限です。コインは [Bitcoin Testnet Faucet](https://kuttler.eu/en/bitcoin/btc/faucet/) などで取得することができますが、このサイトでも言及されているとおり、不要になったら送り返して次の開発者が使えるようにしてあげましょう、とのことです。譲り合い。


# Regtest Mode
これは`testnet`よりももっとローカル開発寄りなモードです。完全にプライベートデータとして１からチェーンを始めることができます。機能的には`testnet`とほぼ同じです。`testnet`と大きく異なる点は、**任意のタイミングで新しいブロックを追加できる**ということです。`testnet`はマイニングによって10分程度おきにブロックに組み込まれていきますが、`regtest mode`ではそういった制限がありません。

```shell:regtest
$ bitcoind -regtest
```
このモードで起動すると、`Bitcoin`ディレクトリ配下に`regtest`ディレクトリが生成され、そこにブロックチェーンデータなどがダウンロードされていきます。その後、ここでは割愛しますが`bitcoin-cli`で始まりのブロックを生成するなどを経て、実際に使用できるようになります。
`regtest`ディレクトリを削除すれば、再度まっさらな状態から始めることができます。


#### つづく
Dialogflowを使ったActions on Googleの新規作成

# はじめに

超初心者が，超初心者用にActions on Google（GoogleAssistantアプリ）の作成手順を書き記しておきます．
**備忘録**

使用するものは以下の通りです．

- Actions on Google
- Dialogflow 

# 目次

1. Actions on Googleの新規作成
2. Dialogflowとの接続
3. インテント作成


## Actions on Googleの新規作成

まず [コンソール](https://console.actions.google.com/) にアクセスします．
Add/import project から，名前・使用場所・使用言語を選択します．
overviewが出てくるので，上から順番に作成していきます．

### invocation (呼び出し名）

ここでアプリ呼び出し名と，アプリ内で使用される合成音声を選択します．呼び出し名は
「（呼び出し名）　につないで」
「（呼び出し名）　と話す」
のように使用するので **言いづらくない** ようにしましょう．

## Dialogflowとの接続

Build your Action -> Add Actionと進み，Costom IntentをBuildします．
ここでDialogflowとGoogle Accountが接続されます．（ログインとか求められたらしてね！）

接続するActions on Googleの名前（1で作成）や，Dialogflow側の名前を設定する．

## インテント作成

### Default welcome intentの編集

Resposesを編集し，アプリに接続した時の応答を編集します．
多くの場合，アプリの説明を入れておきます．

### カスタムインテントの作成

create intentから新規作成します．

- Intent name -> Fulfillmentで使用する
- Training phrases -> このインテントを呼び出すのに使用する発話サンプル
- Action and parameters -> 数字や県名などEntityとして取り出したいものを設定
- Responses -> ランダム返答するときに使用．Fulfillmentを使う場合は空欄
- Fullfillment -> このインテントでFulfillmentを使用するなら　Call for this intent　をEnableにする

## テスト

Dialogflow右部にある `See how it works in Google Assistant` からActions on Googleに戻ることで，確認テストを行うことが可能．

# おわり

**context**って何だろう...
アクションオブジェクトでできること

# アクションオブジェクトとは
LINEでbuttonや、Flex Messageのtextからアクションを呼び出すことができます。

現在 [公式リファレンス](https://developers.line.me/ja/reference/messaging-api/#action-objects)では、7種類のAction Objectが登録されています。(2018/09/01現在)
今回の記事では、それぞれのActionについてまとめ、URIアクションではさらに自由度の高いことを表現ができるので、それについても記述します。

## 基本的なアクションのJSON

基本的な構造として、typeとlabelを持ちます。
typeはアクションの種類を表現し、labelはLINE上で表示されるtextのmessageです。

```json
{  
   "type":"_action_type_",
   "label":"_display_label_",
}
```

### ポストバックアクション
[ポストバックアクション](https://developers.line.me/ja/reference/messaging-api/#postback-action)は、dataの中にボタンの情報を保存し、サーバーに返すことができます。
また、ボタンが抑えれた時にbotからtextを返すこともできます。(非推奨で廃止される予定でありますが、ユーザー側からメッセージを送信することも可能です。

```json
{  
   "type":"postback",
   "label":"ItemName",
   "data":"action=detail&itemid=111",
   "text":"ItemName"
}
```

### 日時選択アクション
[日付選択アクション](https://developers.line.me/ja/reference/messaging-api/#datetime-picker-action)では、ポストバックアクションの情報に加えOSのデフォルトの日付入力を利用し、`日付`/`時間`/`日付+時間`の情報を選択することができます。

フォームを入力した際のデフォルトの日付も設定することができ、`initial`で、起動の日付を選択することが可能です。

この機能を利用すると調整さんのようなbotは簡単にできそうですね :)

```json
{  
   "type":"datetimepicker",
   "label":"Select date",
   "data":"entryId=12345",
   "mode":"date",
   "initial":"2018-09-01",
   "max":"2018-08-01",
   "min":"2018-10-10",
}
```

## めっちゃできるよURIアクション
```json
{  
   "type":"uri",
   "label":"Buy",
   "uri":"https://example.com/pay/confirm"
}
```

[URIアクション](https://developers.line.me/ja/reference/messaging-api/#uri-action)から、`http`/`https`/`line`/`tel`を開くことができます。

他のLINE APIと連携させることもできます。
`https`からはLINE Payを起動させることができます。
LINE Loginを利用して、外部のwebサービスと連携させる。
また、`line`からは[LIFF(LINE Front-end Framework)](https://developers.line.me/ja/docs/liff/overview/)を起動させることができ、Webアプリとの連携も簡単にできます。

LINE URIが指定した[URIスキーム](https://developers.line.me/ja/docs/messaging-api/using-line-url-scheme/)を利用すれば、アクションオブジェクトでできない他の関連botへの誘導や設定画面を開いてbeaconの設定をしてもらうなどのことができます。


### その他のアクション
その他のアクションは非常にシンプルなので割愛させていただきます。気になったアクションがあればLINEの公式を参照してください。

その他 : [メッセージ](https://developers.line.me/ja/reference/messaging-api/#message-action)/[カメラ](https://developers.line.me/ja/reference/camera-api/#uri-action)/[カメラロール](https://developers.line.me/ja/reference/camera-roll-api/#uri-action)/[位置情報](https://developers.line.me/ja/reference/location-api/#uri-action)

# まとめ
今回はアクションオブジェクトについてまとめました。
アクションオブジェクトは`Button`/`Flex Message`から利用することができ、テキスト入力と比べてUXを格段にあげることができるので、是非利用してみてください。
15分単位で丸めた現在日時をdatetime-localで表示する

# はじめに
「[FlaskとHerokuでタイムズカープラス最安プラン選択アプリを作る](https://qiita.com/torukashima/items/f09a68dafddf6a634923)」の日時入力に`datetime-local`を使っているのですが，初期表示を与える処理をJavaScriptで書きました．そのメモを残しておきます．

# 日時を15分単位で丸める

[タイムズカープラス](https://plus.timescar.jp/)では，15分単位で料金が設定されています．貸出開始時刻も返却予定時刻も，X時00分，15分，30分，45分のいずれかから選びます．15分よりも細かい表示は必要ありません．

そこで，現在の時刻を15分単位で丸めます．

```javascript:JS
var date = new Date();
date.setMinutes(Math.round(date.getMinutes() / 15) * 15);
```
念の為，処理前と処理後の「分」を書いておきます．

| date.getMinutes()|Math.round(date.getMinutes() / 15) * 15|
|:-----:|:---:|
| 0〜 7 | 0  |
| 8〜22 |15  |
|23〜37 |30  |
|38〜52 |45  |
|53〜59 |60  |


# 丸めた日時を表示させる
`datetime-local`についての[MDNの記述](https://developer.mozilla.org/ja/docs/Web/HTML/Element/Input/datetime-local)を読むと，`value`属性に，`yyyy-mm-ddThh:MM`と言うフォーマットで日時を与えれば，表示できるとわかります．

また，

>JavaScriptの`Date`には、数値の日時情報を正しく整形された文字列に変換したり、手動で行ったりするメソッドがいくつかあります。例えば、この用途では`Date.toISOString()`メソッドが利用できます。

と書いてあるのですが，`toISOString()`で得られる[タイムゾーンは常に 0 UTCオフセット](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)のため，そのままでは使えません．

そこで，`getTimezoneOffset()`を使って[UTCオフセットを分単位で取得](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset)し，マイナスしてから文字列にします．

```html:HTML
<input type="datetime-local" name="foo" />
```

```javascript:JS
window.onload = function() {
    var date = new Date();
    date.setMinutes(Math.round(date.getMinutes() / 15) * 15 
        - date.getTimezoneOffset());
    var foo = document.querySelector('input[name="foo"]');
    foo.value = date.toISOString().substr(0, 16);
}
```


一応これでできるのですが，`date`が表す日時を，先頭16文字を取得するためだけにずらしてしまっているので，なんか気持ち悪いです．

`toLocaleString()`あたりを使えば良いのかもしれませんが，フォーマットが環境依存で安定しません．

# 別の手段
原始的（？）ですが，手でフォーマットを整えるやり方もあります．結局こういう感じにしておくのがラクなのかも．

```html:HTML
<input type="datetime-local" name="foo" />
```

```javascript:JS
window.onload = function() {
    var date = new Date();
    date.setMinutes(Math.round(date.getMinutes() / 15) * 15);

    var yyyy = ('0000' + date.getFullYear()).slice(-4);
    var mm = ('00' + (date.getMonth() + 1)).slice(-2);
    var dd = ('00' + date.getDate()).slice(-2);
    var hh = ('00' + date.getHours()).slice(-2);
    var MM = ('00' + date.getMinutes()).slice(-2);

    var foo = document.querySelector('input[name="foo"]');
    foo.value = yyyy + '-' + mm + '-' + dd + 'T' + hh + ':' + MM;
}
```

# おわりに

最終的には`datetime-local`は使わず，年月日時分それぞれを`<select>`要素で設定できるようにしようと思うので，「別の手段」に近い形にする予定です．
wxPythonのListCtrlのヘッダーの色を変える方法

wxPythonで黒ベースのGUIにするのが目的。リストコントロールのヘッダーの色を変更します。wx.ListCtrlはヘッダーの色を変更することができませんでした。wx.Gridはヘッダーの色を変更することができるのですが、白い3Dの枠線を変更することができませんでした。そして、UltimateListCtrlを使えばできることが分かりました。
<img src='https://qiita-image-store.s3.amazonaws.com/0/253995/49226e77-1f6b-b8cd-2822-2f0ba880e915.png' width=70%>

```python:main.py
import wx
from wx.lib.agw import ultimatelistctrl as ULC

# ヘッダーレンダラー
class UltimateHeaderRenderer(object):
    def __init__(self, parent):
        super().__init__()

    def DrawHeaderButton(self, dc, rect, flags):
        # ヘッダカラー
        color = wx.Colour(40,40,200)
        dc.SetBrush(wx.Brush(color, wx.BRUSHSTYLE_SOLID))
        dc.SetBackgroundMode(wx.SOLID)
        dc.SetPen(wx.TRANSPARENT_PEN)

        # 仕切り線を消すため広げる
        rect.x -= 1
        rect.width += 1
        dc.DrawRectangle(rect)
        
        # 仕切り線
        dc.SetPen(wx.Pen('#FF0000',1))
        dc.DrawLine(rect.x, rect.y, rect.x, rect.y+rect.height)
        
        dc.SetPen(wx.TRANSPARENT_PEN)
        dc.SetBackgroundMode(wx.TRANSPARENT)  

    def GetForegroundColour(self):
        return wx.Colour(255,255,255)

# リストコントロール
class UltimateListCtrl(ULC.UltimateListCtrl):
    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, wx.ID_ANY, agwStyle=wx.LC_REPORT, style=wx.BORDER_NONE)
        self.SetBackgroundColour('#444444') 
        self.SetForegroundColour('#FFFFFF') 

    def InsertColumn(self, col, text, width):
        info = ULC.UltimateListItem()
        info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_FORMAT
        info._format = 0
        info._text = text
    
        # レンダラー 
        klass = UltimateHeaderRenderer(self)
        info.SetCustomRenderer(klass) 
        
        self.InsertColumnInfo(col, info)
        self.SetColumnWidth(col, width)

class MainFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(400,200))
        p = wx.Panel(self, -1)
        
        self.list = UltimateListCtrl(p)
        self.list.InsertColumn(0, text='Path', width=180)
        self.list.InsertColumn(1, text='Date', width=100)  
        self.list.InsertColumn(2, text='Size', width=-3) #-3=FULL  
        
        self.list.InsertStringItem(0, 'AAAA')
        self.list.SetStringItem(0, 1, '2018/1/1')
        self.list.SetStringItem(0, 2, '1000')

        self.list.InsertStringItem(1, 'BBBB')
        self.list.SetStringItem(1, 1, '2018/2/2')
        self.list.SetStringItem(1, 2, '2000')

        sizer = wx.FlexGridSizer(rows=1, cols=1, vgap=1, hgap=1)
        sizer.Add(self.list, 0, wx.EXPAND, 0)
        sizer.AddGrowableCol(0)
        sizer.AddGrowableRow(0)
        p.SetSizer(sizer)
       
if __name__ == '__main__':
    app = wx.App(False)
    main = MainFrame(None, -1, 'UltimateListCtrl')
    main.Show(True)
    app.MainLoop()           
```
現在時点の年齢を出力する関数(Excel)

エクセルなどの表計算ソフトで年齢を入力したいことがあると思います。
しかし、年齢は毎年増えていくので入力し直すのが手間です。
(システム的にも年は取りたくないものです:cry:)

`DATEDIF` 関数を使えば、その手間を解消できます。
誕生日がわかれば `DATEDIF("{誕生日}", TODAY(), "Y")` で現在時点での年齢を出力できます。
(誕生日がわからない？ そこはうまく聞き出してください:wink:)

```:関数の例
= DATEDIF("2000/01/01", TODAY(), "Y")
```

```:出力結果
18
```

`DATEDIF` 関数は `DATEDIF(開始日, 終了日, 単位)` というパラメータになっているので、「誕生日から現在時点までの日数を年のみ出力する」という計算をすることで年齢が出力されるということです。

ちなみにエクセルだけでなくGoogleスプレッドシートでも使えます:clap:
phpstorm自動アップロード設定

まず、サーバー接続
ファイル→設定→デプロイ→必要な情報入力
注意するのはアプロード先のパス設定
図をご参考
![q11.png](https://qiita-image-store.s3.amazonaws.com/0/286146/a680f6e5-609d-3c7f-ebc0-00e95c74a494.png)
![q12.png](https://qiita-image-store.s3.amazonaws.com/0/286146/f551272f-6898-68c1-9506-ab9019a9cf49.png)
【SQL】4大命令


## 基本となる4大命令
- SELECT文
- UPDATE文
- INSERT文
- DELETE文

### SELECT文
テーブルからデータを指定して取得する

```sql
SELECT 列名... FROM テーブル名 (WHERE 条件式)
```

### UPDATE文
テーブルのデータを書き換える

```sql
UPDATE テーブル名 SET 列名=値1, 列名2=値2, ... (WHERE 条件式)
```
※注:WHEREのないUPDATEは**全レコードが更新される**。

### INSERT文
テーブルにデータを追加する

```sql
INSERT INTO テーブル名 (列名1, 列名2, 列名3, ...) VALUES (値1, 値2, )
```
### DELETE文
テーブルに存在するデータを削除する

```sql
DELETE FROM テーブル名 (WHERE 条件式)
```
※注:WHEREのないDELETEは**全レコードが消去**される。

## WHERE句について
WHERE句は結果が必ず`真(true)` ,`偽(false)`となる必要がある。

### 主な比較演算子
|比較演算子|意味|
|:------ |:---|
|=| 左右の値が等しい|
|<|左辺は右辺より小さい|
|>|左辺は右辺より大きい|
|<=|左辺は右辺の値以下|
|>=|左辺は右辺の値以上|
|<>|左右の値が等しくない|

### NULL判定
※注 : NULLは`=`では判定できない

- NULLであることを判定する => `式 IS NULL`
- NULLでないことを判定する => `式 IS NOT NULL`

### LIKE演算子
LIKE演算子に使えるパターン文字

|パターン文|意味|
|:--|:--|
|%|任意の0文字以上の文字列|
|_(アンダースコア)|任意の文字列|

### BETWEEN演算子
ある範囲内に値が収まっているかを判定する

```sql
式 BETWEEN 値1　AND 値2
```

### IN/NOT IN演算子
`IN演算子` => 値が( )内の複数の値のいずれかに**合致する**かを判定する

```sql
式 IN (値1, 値2, 値3, ...)
```

`NOT IN演算子` => 値が( )の複数の値のいずれかに**合致しない**かを判定する

```sql
式 NOT IN (値1, 値2, 値3, ...)
```

### ANY/ALL演算子
複数の値と大小を大小を比較したい場合に用いる。
使用する場合は必ず**その直前に比較演算子をつけて利用する**

#### ANY演算子
値リストのそれぞれと比較して、**いずれかが真なら真**

```sql
式　基本比較演算子 ANY (値1, 値2, 値3, ...)
```

#### ALL演算子
値リストのそれぞれと比較して、**すべて真なら真**

```sql
式 基本比較演算子　ALL (値1, 値2, 値3, ...)
```

### 論理演算子
#### AND演算子
2つの条件式の**両方が**真の場合、真となる

```sql
条件式1 AND 条件式2
```

#### OR演算子
2つの条件式の**どちらかが**真ならば、真となる

```sql
条件式1 OR 条件式2
```

### NOT演算子

```sql
NOT 条件式
```

### 論理演算子の優先度
`NOT > AND > OR` の優先順位にしたがって処理される。
※ 優先順位を引き上げたい時には、条件式を`( )`で括る。


参考図書 : [スッキリわかるSQL入門](http://amzn.asia/d/diFEu7A)
Raspberry Piによるスクレイピング 環境構築（Selenium + Chromiumドライバ）

# はじめに
本記事は、Raspberry PiにSelenium + Chromiumドライバのスクレイピング環境を構築するための記事です。

静的なhtmlコンテンツを取得するurllibは、JavaScriptなどの動的なページに対応していません。そこで、SeleniumでWebブラウザを操作することで、動的なページに対するスクレイピングができます。また、Seleniumは、Google Chrome、Firefox、IE、Opera等複数のWebブラウザに対応しています。

## 環境
Raspberry Pi（※1） + Selenium + Chromium

[Linux用のChromeドライバ](https://sites.google.com/a/chromium.org/chromedriver/home)だと、プラットフォームが違うので対応していないため、Chromiumドライバを使用します。Chromiumドライバは[こちら](https://launchpad.net/ubuntu/trusty/+package/chromium-chromedriver)よりダウンロード可能です。

なお、最新のChromiumドライバのchromium-chromedriver 65（※2）では動作しないため、古いバージョンである[chromium-chromedriver 61](https://launchpad.net/ubuntu/trusty/armhf/chromium-chromedriver/61.0.3163.79-0ubuntu0.14.04.1196)をインストールします。

（※1）Raspbian GNU/Linux 9.3 (stretch)
（※2）本記事執筆時点

## 構築手順
1. Seleniumをインストールする
`$ pip3 install selenium`

2. Seleniumのインストール確認
`$ pip3 list | grep selenium`
3. debパッケージをインストールする
`$ sudo dpkg -i chromium-chromedriver_61.0.3163.79-0ubuntu0.14.04.1196_armhf.deb`
4. Chromiumドライバのインストール確認
`$ ls -l /usr/lib/chromium-browser/chromedriver`

## 動作確認

- 動作確認プログラム

```python
#! /usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
sys.path.append('/home/pi/.local/lib/python3.5/site-packages/')
from selenium import webdriver

browser = webdriver.Chrome(executable_path="/usr/lib/chromium-browser/chromedriver")
browser.get('https://www.google.com/')
```

- 動作確認
![スクリーンショット 2018-08-30 00.09.44.png](https://qiita-image-store.s3.amazonaws.com/0/221759/563120f1-8934-6ce5-25de-818c9f65b72c.png)

Raspberry PiにVNCでログインしてプログラムを実行すると、Webブラウザ（Chrome）が起動し指定したページを開きます。
vue-cli インストール手順（ver. 2018 - 2019）

宮崎在住エンジニアのジョウ(@JotarO_Oyanagi) です。

2018年9月現在、**vue-cli**　をインストールする手順として、「このツール、手順でインストールしておくと、今後使える構成なんじゃないか」というものをご紹介します。

# TL;DR
- **これから vue-cli をインストールする方**に向けた内容です。
- **anyenv**、**ndenv**、**yarn** を使用してインストールします。
- すでに **Node.js** や、そのバージョン管理ツールをインストールされている方で、**anyenv**、**ndenv** を使用される方は **Node.js をアンインストールしておく必要**があります。

参考：[Mac OS X からNode.jsをアンインストールする](http://suzuki-koya.hatenablog.com/entry/2017/10/05/032408)

# anyenv のインストール＆設定

各言語のパッケージマネージャーのパッケージマネージャーです（ややこしい）。

参考：[anyenv](https://github.com/riywo/anyenv)

### インストール
```
$ git clone https://github.com/riywo/anyenv ~/.anyenv
```

### 設定
```
$ echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(anyenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
```

# ndenv のインストール

Node.js のバージョン管理ツールです。

```
$ anyenv install ndenv
$ source ~/.bash_profile
```


# node-build のインストール

ndenv で node をインストールするためにインストールします。

```
$ git clone https://github.com/riywo/node-build.git $(ndenv root)/plugins/node-build
```

# node のインストール

vue-cli をインストールするために。

```
$ ndenv install v8.11.4
$ ndenv rehash
$ ndenv global v8.11.4
$ node -v
v8.11.4
```

# yarn のインストール

npm で vue-cli をインストールしてもいいのですが、インストール時間がより速いので yarn をパッケージマネージャーとして用意します。

```
$ npm install -g yarn
$ source ~/.bash_profile
```

# vue-cli のインストール

いよいよ vue-cli のインストールです！

```
$ yarn global add @vue/cli
```

# あとは

以下のコマンドで、バージョン情報が表示されれば完了です！

```
$ vue --version
```
線形代数のメモ

線形代数のメモ

# ベクトルの基本
n項の縦ベクトルの表記。

```math
\boldsymbol{a}=
\left(
  \begin{array}{c}
    a_1 \\
    a_2 \\
    \vdots \\
    a_n
  \end{array}
\right)
```

## ベクトルの和
単純にベクトル同士の成分の和。

```math
\boldsymbol{a}+\boldsymbol{b}=
\left(
\begin{matrix}
a_{1}+b_{1}\\a_{2}+b_{2}\\\vdots\\a_{n}+b_{n}
\end{matrix}\right)
```

## スカラー倍
```math
c\boldsymbol{a}=
\left(
\begin{matrix}
ca_{1}\\ca_{2}\\\vdots\\ca_{n}
\end{matrix}\right)
```


## ベクトルの内積
成分ごとの積の和。

```math
\boldsymbol{a}\cdot\boldsymbol{b}=
\displaystyle \sum_{i=1}^{n} a_i b_i
```
## 要素積
ベクトルの各要素を掛け合わせたもの。

```math
\boldsymbol{a}\odot\boldsymbol{b}=
\left(
  \begin{array}{c}
    a_1 b_1 \\
    a_2 b_2\\
    \vdots \\
    a_n a_n
  \end{array}
\right)
```

# 行列の基本

m×n行列

```math
\begin{eqnarray}
\boldsymbol{A} = \left(
  \begin{array}{cccc}
    a_{ 11 } & a_{ 12 } & \ldots & a_{ 1n } \\
    a_{ 21 } & a_{ 22 } & \ldots & a_{ 2n } \\
    \vdots & \vdots & \ddots & \vdots \\
    a_{ m1 } & a_{ m2 } & \ldots & a_{ mn }
  \end{array}
\right)
\end{eqnarray}
```

次も同じ意味。

```math
\boldsymbol{A}=\left(a_{ij}\right)
```

## 正方行列
行と列が同じ数の行列

```math
\begin{eqnarray}
\boldsymbol{A} = \left(
  \begin{array}{ccc}
    a_{ 11 } & a_{ 12 } & \ldots & a_{ 1n } \\
    a_{ 21 } & a_{ 22 } & \ldots & a_{ 2n } \\
    \vdots & \vdots & \ddots & \vdots \\
    a_{ n1 } & a_{ n2 } & \ldots & a_{ nn }
  \end{array}
\right)
\end{eqnarray}
```

## 対角行列
対角成分以外が全て0の正方行列。

```math
\begin{eqnarray}
\begin{pmatrix}
  a_{ 11 } &   &  & 0 \\
    & a_{ 22 } &  &   \\
    &   & \ddots &   \\
  0 &   &  & a_{ nn } 
\end{pmatrix}
\end{eqnarray}
```


## 単位行列
対角成分が全て1の対角行列。

```math
\begin{eqnarray}
\begin{pmatrix}
  1 &   &  & 0 \\
    & 1 &  &   \\
    &   & \ddots &   \\
  0 &   &  & 1
\end{pmatrix}
\end{eqnarray}
```

## 行列の和
AとBはm×n行列として

```math
\begin{eqnarray}
\boldsymbol{A} + \boldsymbol{B} = 
\left(a_{ij}+b_{ij}\right)=
\left(
  \begin{array}{cccc}
    a_{11}+b_{11} & a_{12}+b_{12} & \ldots & a_{1n}+b_{1n} \\
    a_{21}+b_{21} & a_{22}+b_{22} & \ldots & a_{2n}+b_{2n} \\
    \vdots & \vdots & \ddots & \vdots \\
    a_{m1}+b_{m1} & a_{m2}+b_{m2} & \ldots & a_{mn}+b_{mn}
  \end{array}
\right)
\end{eqnarray}
```

## 行列のスカラー倍

```math
\begin{eqnarray}
c\boldsymbol{A} = 
\left(ca_{ij}\right)=
\left(
  \begin{array}{ccc}
    ca_{11} & ca_{12} & \ldots & ca_{1n} \\
    ca_{21} & ca_{22} & \ldots & ca_{2n} \\
    \vdots & \vdots & \ddots & \vdots \\
    ca_{n1} & ca_{n2} & \ldots & ca_{nn}
  \end{array}
\right)
\end{eqnarray}
```

## 行列の積

## 正則行列

## 転置行列

## 直交行列

## 行列式

## 逆行列

## 行列の計算の法則

## 固有ベクトルと固有値

## 対角化

# 続く

# 参考URL
* [機械学習を学ぶ上で抑えておきたい数学](http://s0sem0y.hatenablog.com/entry/2016/09/29/041421)
* [Qiitaの数式チートシート](https://qiita.com/PlanetMeron/items/63ac58898541cbe81ada)
* [Easy Copy MathJax](http://easy-copy-mathjax.xxxx7.com/)
【SQL入門】CHARとVARCHARの違い

## CHAR型
- 固定長の文字列データを扱うデータ型。
- **CHAR(10)**と指定された列の場合、**格納される列は常に10バイト**になる。
- **10バイトに満たない場合**は文字列の右側に空白が追加され、**10バイトぴったりに調整される**。

## VARCHAR型
- `CHAR型`と異なり、格納する**文字列の長さの調整はされない**。
- `VARCHAR(10)`と指定された列の場合、10バイト以下の文字列でも、それに合わせた領域が確保される為、そのままの長さで格納することが可能。
- ただし、最大長以上(10バイト以上)の文字列の格納はできない。

## どう使い分けるか
- `CHAR型`は、`郵便番号`や`社員番号`など、**データの桁数が決まっている**もの向け。
- `VARCHAR型`は、`氏名`や`書籍名`など、**データ桁数が変動する**可能性のあるもの向け。

## その他
MySQLの場合、CHAR/VARCHARともに、()内の数値は格納できる最大文字数。
CHARは0~255まで、VARCHARは0~65535の範囲で指定可能。

参考図書 : [スッキリわかるSQL入門](http://amzn.asia/d/diFEu7A)
Djangoチュートリアル　アプリ作成(1)[DBの設定・ブラウザで開く]

#Djangoチュートリアル

下のリンクのDjangoチュートリアルを参考にしながらアプリを作成していきます。
[Django Tutorial](https://djangogirlsjapan.gitbooks.io/workshop_tutorialjp/content/django_start_project/)

##設定変更
まずは、ディレクトリを作成して仮想環境を構築します。

```
$ mkdir Django_tutorial
$ cd Django_tutorial
$ python3 -m venv myvenv
$ ls
myvenv
```

次にこの`myvenv` ディレクトリに移動して、プロジェクトを作成します。

```
$ cd myvenv
$ django-admin startproject mysite .
$ ls
bin		lib		mysite
include		manage.py	pyvenv.cfg
```

このような中身になったと思います。
コマンドの最後にピリオド (.) があることを確認してください。これは、現在の作業ディレクトリにDjangoをインストールするということを示すので、とても重要です。
`manage.py` はサイト管理用のスクリプトです。これで、他のものを一切インストールすることなく、コンピューター上でWebサーバーを動かすことができるようになります。

次に、`mysite/settings.py` の中を少し変更していきます。
`settings.py` は、サイトの設定ファイルです。
エディタで開いて以下の箇所をこのように変更してください。
１０６行目あたりにあります。

```
LANGUAGE_CODE = 'ja-JP'

TIME_ZONE = 'Asia/Tokyo'

USE_TZ = False
```

## データベース(DB)の設定
Djangoには、`sqlite3`というデータベースソフトウェアが標準装備されています。
`mysite/settings.py`ファイルの次の箇所で、セットアップされています。

```python

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
```

次のコマンドを実行してDBを作成します。

```
$ python3 manage.py migrate
```

実行するとこのような画面が出てきます。

```
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying sessions.0001_initial... OK
```

次にサーバーを動かして、Webサイトがうまく動いているか確認しましょう。
manage.pyファイルを含むディレクトリにいることを確認してください。

```
$ ls
bin		include		manage.py	pyvenv.cfg
db.sqlite3	lib		mysite

$ python3 manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
September 02, 2018 - 01:50:26
Django version 2.1, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
```

このような画面になったら以下のURLからブラウザを開いてください。
http://127.0.0.1:8000/
<img width="1228" alt="スクリーンショット 2018-09-02 1.52.45.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/285122/a341ed4b-904a-2a34-17c5-4038e0649e0f.jpeg">
このような画面が出ていたら完了です！！
Pythonで競プロに挑む日誌 vol.4 ~and と or~

# 現在の目標
* 今年の10月内に茶色を取得する **←イマココ**
* 年内に緑色を取得する
* [APG4b](https://beta.atcoder.jp/contests/apg4b) で C++ にも手を出す

#今日の問題
ABC083B - Some Sums 
https://beta.atcoder.jp/contests/abs/tasks/abc083_b

**結果**

```answer1.py
# coding: utf-8
N, A, B = map(int, input().split())
 
ans = 0
for i in range(1,N+1):
    lis_i = [int(x) for x in list(str(i))]
    val = sum(lis_i)
    if (val >= A) and (val <= B):
        ans += i
 
print(ans)

# 実行時間：36 ms
# メモリ　：2940 KB
# コード長：222 Byte
# 得点　　：200/200
```
すんなり解けたかな, と思います.

内包表記をもっと活用できないかと粘ってみました↓

```answer2.py
# coding: utf-8
N, A, B = map(int, input().split())
 
ans = [i
       for i in range(1,N+1)
       if (sum([int(j) for j in list(str(i))])) >= A and (sum([int(j) for j in list(str(i))])) <= B]
 
print(sum(ans))

# 実行時間：49 ms
# メモリ　：3404 KB
# コード長：215 Byte
# 得点　　：200/200
```
うーん, 粘った割には美しくないですね. あと、実行速度も遅かった.

---
**疑問**
answer2 を考える途中で, "&" と "and" の使い分けがよくわからなくなりました.

```and_&.py
# and だと正解となる
if (sum([int(j) for j in list(str(i))])) >= A and (sum([int(j) for j in list(str(i))])) <= B]

# & だと不正解
if (sum([int(j) for j in list(str(i))])) >= A & (sum([int(j) for j in list(str(i))])) <= B]
```
調べてみると, 違いは下記にあるようです. 

* and : bool 演算
* &   : bit 演算

if 文の条件式判定には bool 値が使われるので, and や or を使うのが正しそうだと理解しました. & は 2 進数同士の演算に使うものなんですね. 

* https://qiita.com/keisuke-nakata/items/e0598b2c13807f102469
* http://www.tohoho-web.com/python/operators.html

ただ, answer1 の if 文判定は and でも & でも通ったんですよ...  うーむ, よくわからん.

いやぁ, 先は長そうですな.  慌てず焦らず, 楽しみながら続けていこうと思います.


# 明日やること
[ABC088B - Card Game for Two ](https://beta.atcoder.jp/contests/abs/tasks/abc088_b)を解く.
YouTubeの急上昇の履歴みれるサイトつくった【なくすと】

# tl;dr
- [ここ](https://github30.github.io/youtube-trends/) から閲覧できます。
- 急上昇に入る動画がどんな動画化かデータドリブンに予測するために、まずはデータを集めてみました。(粒度は1分です。)
- Wayback Machineでも収集できますが、英語のyoutubeだけだったり頻度が数時間おきだったりします。

データは [こちら](https://drive.google.com/drive/folders/1jOjoLB0T1c32QCzjvaRAI-wT-EtlU_gB)  にあるので焼くなり煮るなりしてください。

# まとめ
- ある程度データが集まったら、急上昇に入る動画か判断するAI作ろうとおもいましゅ。

# 追記
GASのurlのパスに追記した(/exec/hogehoge)ことで閲覧できない状態になっておりました。
すみません。
Azure WebAppsにNuxt.js+Expressの環境をDockerでデプロイしたときのメモ


App ServiceのWebAppsのDockerのやつ（Web App for Containersというらしい）にDockerでNuxt.js+Expressのアプリケーションをデプロイした時のメモです。

けっこうハマって@horihiroさんに色々質問して助けてもらいました。ものすごく感謝です。

けっこうハマってて途中経過などをメモってなかったのでとりあえずこの流れでできたよってところのメモだけ残しておきます。

## テンプレート作成

vue-cliでテンプレート作成します。

```
vue init nuxt-community/express-template .
```

`package.json`はこのまま。 ここのstartの箇所で`nuxt build`が入ってるのがポイントで、WebApps側がイメージを起動する際にnuxt buildでビルドが走り、`.nuxt`フォルダが生成されます。これがないとnuxtが起動しないっぽい。

```package.json
・
・
・
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt build && nuxt start",
    "precommit": "npm run lint",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore ."
  },
・
・
・
```

## .dockerignore

`.dockerignore`をルートに設置。


```.dockerignore
node_modules/
npm-debug.log
.nuxt/
```

## Dockerfile

`Dockerfile`もルートに設置。 `alpine`イメージを使うと良いっぽいのでこんな記述

* `npm i --production --no-progress`: `--production`でdevdependenciesのモジュール読み込みを無くして、`--no-progress`でプログレス表示を無くしてあげるとある程度早くモジュールの読み込みができるっぽい
* `npm cache clean -f`: キャッシュクリアしないとバグるのと`-f`もつけておかないとバグってました。
* EXPOSE: ポート指定
* ENV HOST: たしか0.0.0.0に指定しないとうまく起動しない

```Dockerfile
FROM node:10.9.0-alpine

RUN mkdir -p /app
COPY . /app
WORKDIR /app

RUN npm i --production --no-progress && npm cache clean -f

EXPOSE 3000
ENV HOST 0.0.0.0

CMD ["npm", "start"]
```

## デプロイ

この状態でbuildしてイメージを固めて

```
docker image build -t n0bisuke/express-test:latest .
```

docker hubにプッシュします。

```
docker push n0bisuke/express-test
```

WebApps側でアプリケーションをDocker指定で作成して`n0bisuke/express-test:latest`を指定しましょう。

![](https://i.gyazo.com/384e18c3c030e81f352494c6d19c3a5a.png)

アプリケーション設定でPORTを指定。ここも指定がないとうまく起動してくれません。

![](https://i.gyazo.com/3b65721ab0d418ab1b6c59417628fcb0.png)

## 確認

うまく起動できると、こんな感じでNuxt.js+Expressのテンプレートそのままのページが無事に表示されました

![](https://i.gyazo.com/681cdf9a5b6bf8aab95ba88e72fe141e.png)
Go + RFC 8292 Voluntary Application Server Identification (VAPID) for Web Push

[Go + RFC 8219 Message Encryption for Web Push](https://qiita.com/nokamoto/items/457e4907615a50d6294e) の続き。

[RFC 8292 Voluntary Application Server Identification (VAPID) for Web Push](https://tools.ietf.org/html/rfc8292) 理解のため読みつつ Go での Application Server 側の実装をなぞる。

[実装コード](https://github.com/nokamoto/webpush-101/pull/12)

ここまでの実装により PushService への HTTP リクエストが送信できるようになる。

## [Application Server Self-Identification](https://tools.ietf.org/html/rfc8292#section-2)

```bash
openssl ecparam -name prime256v1 -genkey -noout -out vapid_private.pem
openssl ec -in vapid_private.pem -text -noout -conv_form uncompressed | grep '^priv:' -A 3 | tail -n 3 | tr -d ' \n:' | xxd -r -p | base64
openssl ec -in vapid_private.pem -text -noout -conv_form uncompressed | grep '^pub:' -A 5 | tail -n 5 | tr -d ' \n:' | xxd -r -p | base64
```

VAPID のため ApplicationServer のキーペアが必要となる。
公開鍵の方は [​PushManager.subscribe](https://developer.mozilla.org/en-US/docs/Web/API/PushManager/subscribe) で `applicationServerKey` でも同じものを渡す。

```go
func newJwt(endpoint, subject string, expiry int64, priv *ecdsa.PrivateKey) (string, error) {
	origin, err := url.Parse(endpoint)
	if err != nil {
		return "", err
	}
	audience := fmt.Sprintf("%s://%s", origin.Scheme, origin.Host)

	token := jwt.NewWithClaims(jwt.SigningMethodES256, jwt.MapClaims{
		"aud": audience,
		"exp": expiry,
		"sub": subject,
	})

	return token.SignedString(priv)
}
```

リクエストに含める JWT には `aud` と `exp` を最低限指定する。
[Application Server Contact Information](https://tools.ietf.org/html/rfc8292#section-2.1) として `sub` を含めても良い。

```
Authorization: vapid
      t=eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL3
        B1c2guZXhhbXBsZS5uZXQiLCJleHAiOjE0NTM1MjM3NjgsInN1YiI6Im1ha
        Wx0bzpwdXNoQGV4YW1wbGUuY29tIn0.i3CYb7t4xfxCDquptFOepC9GAu_H
        LGkMlMuCGSK2rpiUfnK9ojFwDXb1JrErtmysazNjjvW2L9OkSSHzvoD1oA,
      k=BA1Hxzyi1RUM1b5wjxsn7nGxAszw2u61m164i3MrAIxHF6YK5h4SDYic-dR
        uU_RCPCfA5aq9ojSwk5Y2EmClBPs
```

これらの情報から上記のような Authorization ヘッダーを生成する。

```go
func addAuthorizationHeader(req *http.Request, endpoint, subject string, expiry int64, pair *ApplicationServerKeyPair) error {
	t, err := newJwt(endpoint, subject, expiry, pair.priv)
	if err != nil {
		return err
	}

	k := pair.pub

	req.Header.Add("Authorization", fmt.Sprintf("vapid t=%s,k=%s", t, k))

	return nil
}
```

[Token Parameter ("t")](https://tools.ietf.org/html/rfc8292#section-3.1) は生成した JWT を指定する。
[Public Key Parameter ("k")](https://tools.ietf.org/html/rfc8292#section-3.2) は base64url エンコーディングされた公開鍵を指定する。

## (Go) bytes to ecdsa.PrivateKey

```go
func (pair *ApplicationServerKeyPair) SetBase64StdEncodingPrivateKey(key string) error {
	b, err := base64.StdEncoding.DecodeString(key)
	if err != nil {
		return err
	}

	d := big.Int{}

	pair.priv = &ecdsa.PrivateKey{
		PublicKey: ecdsa.PublicKey{Curve: curve},
		D:         d.SetBytes(b),
	}

	return nil
}
```

`ecdsa.PrivateKey` を既存のものから生成する方法がいまいち分からなかったが、なんとか動いた。
あるいは [ParseECPrivateKeyFromPEM](https://godoc.org/github.com/dgrijalva/jwt-go#ParseECPrivateKeyFromPEM) からファイルを pem ファイルからの読み込みこむことも可能そうだった。
ESLintでJavaScriptのブラウザ依存を構文チェック

フロントエンドを開発していると、複数のブラウザに対応する状況は日常茶飯事です。
普段からフロントエンドを開発していない人にとって、JavaScriptのどの構文がどのブラウザで利用できるかを把握することは、非常に困難です。

そこで、 [amilajack/eslint-plugin-compat](https://github.com/amilajack/eslint-plugin-compat) を利用してJavaScriptのブラウザ依存の構文チェックをする方法を紹介します。

![eslint-plugin-compat.gif](https://qiita-image-store.s3.amazonaws.com/0/54838/3e2058b8-deff-5bc1-fa86-c15eb7c43dba.gif)

# eslint-plugin-compat
eslint-plugin-compat は JavaScript のブラウザ依存を構文チェックするESLintのプラグインです。

対象ブラウザの設定は [browserslist/browserslist](https://github.com/browserslist/browserslist) に準拠して記述します。

# インストール
npmを利用してインストールします。

```
$ npm init -y
$ npm install --save-dev eslint eslint-plugin-compat
```

# 使い方
## .eslintrcに設定を追記
`.eslintrc`に eslint-plugin-compat を利用するための設定情報を追記します。

 ```json:.eslintrc
{
  "env": {
    "browser": true
  },
  "plugins": ["compat"],
  "rules": {
    "compat/compat": "error"
  }
}
```

## 対象ブラウザ一覧の設定
`package.json`に構文チェックの対象とするサポートブラウザの一覧を記述していきます。
記述方法の詳細については [browserslist/browserslist]
(https://github.com/browserslist/browserslist#full-list) を参照してください。

今回はChromeの最新2バージョンとIE11を対象ブラウザとします。

```json:package.json
{
  "browserslist": [
    "last 2 Chrome versions",
    "ie 11"
  ]
}
```

## 構文チェックを実行
```javascript:index.js
const result = fetch('google.com')
```

サンプルコードに対してESLintを実行してみます。

```zsh
$ npx eslint index.js

/Users/tomohiro/workspace/compat-test/index.js
  1:1  error  fetch is not supported in IE 11  compat/compat

✖ 1 problem (1 error, 0 warnings)
```

[Fetch API](https://developer.mozilla.org/ja/docs/Web/API/Fetch_API) がIE11でサポートされていないことを、構文エラーで教えてくれました d(>_< )!!

# エディタでリアルタイムに構文チェックする
eslint-plugin-compat はESLintのプラグインなので、エディタにESLintのプラグインを導入すればそのままエディタ上でも確認できるようなります。

例えば Visual Studio Code の場合は、[ESLintのプラグイン](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) をインストールするだけでOKです。

# さいごに
JavaScriptのブラウザ依存は普段フロントエンド開発しない人からしたら鬼門なので、
CIに組み込んで自動チェックできる仕組みを導入すれば、開発の心理的安全性が向上します。