OmniAICreator/Qiita-1.07M huggingface dataset:
Docker Multi-Stage BuildsでRailsのイメージを軽量化してみる

# はじめに
RailsのDockerイメージのサイズを半分以下にする事ができました！

# Docker Multi-Stage Buildsとは
Docker17以降のバージョンでDockerfileにFrom句を複数書けるようになりました。
これがマジでヤバイ！

何がヤバイかというと、
複数のビルドしたイメージから必要なものだけをコピーできるということ。
ライブラリを展開する為に必要なツールのインストールなど行う場合が多々あるかと思いますが、最終的なイメージには不要なものもあるかと思います。

そういった不要なものを省く事が簡単にできます。
イメージはなるべくサイズを抑えるべきです。
イメージのビルド、デリバリの時間を圧縮でき、これはCI/CDの基本です。

Docker Multi-Stage Buildsに関しては、こちらの記事で詳しく解説されています。
[Docker multi stage buildで変わるDockerfileの常識](https://qiita.com/minamijoyo/items/711704e85b45ff5d6405)

# Before And After
Rails用のdocker imageのサイズがどのくらい変わるか結果を先にお見せします。

## Before 
771MB

```shell-session
➜  rails_docker git:(master) ✗ docker images | grep web
railsdocker_web                latest              f2772a54bc64        54 seconds ago      771MB
```

## After
355MB
なんと、半分以下のサイズになっています。

```shell-session
➜  rails_docker git:(master) ✗ docker images | grep web   
railsdocker_web                latest              bfeeacbc82e7        12 days ago         355MB
```

# Dockerfile
続いてDockerfileのBefore, Afterを比較してみましょう。
## Before
```dockerfile
FROM ruby:2.3.2-alpine
ENV LANG ja_JP.UTF-8
RUN apk --update add --virtual build-dependencies \
    build-base \
    curl-dev \
    mysql-dev \
    linux-headers
RUN apk --update add \
    bash \
    nodejs \
    mariadb-dev \
    tzdata \
    && rm /usr/lib/libmysqld*

RUN gem install bundler

WORKDIR /tmp
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
ENV BUNDLE_JOBS=4
RUN bundle install
RUN apk del build-dependencies

ENV APP_HOME /myapp
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
COPY . $APP_HOME
```

## After
```dockerfile
FROM ruby:2.3.2-alpine as builder
RUN apk --update add --virtual build-dependencies \
    build-base \
    curl-dev \
    mysql-dev \
    linux-headers
RUN gem install bundler
WORKDIR /tmp
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
ENV BUNDLE_JOBS=4
RUN bundle install
RUN apk del build-dependencies

FROM ruby:2.3.2-alpine
ENV LANG ja_JP.UTF-8
RUN apk --update add \
    bash \
    nodejs \
    mariadb-dev \
    tzdata \
    && rm /usr/lib/libmysqld*
RUN gem install bundler

WORKDIR /tmp
COPY --from=builder /usr/local/bundle /usr/local/bundle

ENV APP_HOME /myapp
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
COPY . $APP_HOME
```

ここでポイントとなるのが、

```
FROM ruby:2.3.2-alpine as builder
```

と、

```
COPY --from=builder /usr/local/bundle /usr/local/bundle
```

です。
あと、`FROM`が２回登場している事がわかります。
最初のビルドで`builder`というエイリアスをつけており、そこから、

```
/usr/local/bundle
```

を次のビルドでコピーしています。
要は、最初のビルドでは`bundle install`するだけが目的です。
その為のツールは全て不要です。

# さいごに
Multi-Stage BuildsによってDockerイメージの軽量化ができました。
もちろん、Multi-Stage Buildsを利用せずとも軽量化はできます。
不要なファイルを手動で個別に削除していけば良いわけです。
しかし、Multi-Stage Buildsを使えば削除の手順を省く事ができるので、Dockerfileの見通しがよくなります。

更に、イメージの軽量化は可能ですが、細かいTipsは割愛します。

RailsのDockerイメージは肥大しやすいので、イメージサイズを少し意識してみてはいかがでしょうか？

快適なDockerライフを。
AmazonLinuxの初期設定：インスタンス立ち上げたらまずやること

EC2でAmazonLinux立ち上げたら最低限これだけはしておいたほうがいいよってものを纏めてみます。
主に自分用で使いますが誰かの参考になれば幸いです。
CloudFormationでも同じことできるようになんないとなー

Advent Calendar忘れてて一日遅れすみません。。

+ 2017.12.19　create

---


パッケージ更新
---
まずパッケージ更新。基本ですね忘れずにやりましょう！

```text:パッケージ更新
# yum update
```

iptablesストップ
---
FWはAWSのセキュリティグループに任せるのが楽なのでこっちは停止しておきます。
***使っちゃいけないということではありません！***

```text:iptablesストップ
# chkconfig ip6tables off
# chkconfig iptables off
# service iptables stop
# service ip6tables stop
```

タイムゾーン変更
---
amazonlinuxは初期設定がUTCなので日本時間にセットします。

```text:タイムゾーン変更
# vi /etc/sysconfig/clock
　　　ZONE="Japan"に変更
ln -sf /usr/share/zoneinfo/Japan /etc/localtime
```

システムパラメータ変更
---
今回はtcp関連中心に設定しておきます。

```text:システムパラメータ変更
# vi /etc/sysctl.conf
以下を追加
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_max_syn_backlog = 20480
net.ipv4.tcp_rmem = 4096 873800 1747600
net.ipv4.tcp_wmem = 4096 873800 1747600
net.ipv4.tcp_mem = 2048000 2048000 2048000
net.ipv4.ip_local_port_range = 11000 65500
net.ipv4.tcp_keepalive_time = 10
net.ipv4.tcp_keepalive_probes = 4
net.ipv4.tcp_keepalive_intvl = 5
net.ipv4.tcp_rfc1337 = 1
fs.file-max = 100000
net.core.somaxconn = 65535

設定反映
# sysctl -p
```

Limit系の変更
---
ファイルオープンエラー対策ですね。上限を広げておきます。

```text:Limit系の変更
# vi /etc/security/limits.d/90-nproc.conf
以下を記述して保存。
*          soft    nproc     65535
root       soft    nproc     unlimited

# vi /etc/security/limits.conf
デフォルト4096の所を65535に変更しておきます。
root soft nofile 65535
root hard nofile 65535
* soft nofile 65535
* hard nofile 65535
```

Historyコマンド設定
---
デフォルト999件までしか追えないのでhistoryサイズ大きくしておくと何かと便利です。

```text:Historyコマンド設定
ユーザのHOMEDIR/.bashrcへ以下を追加
HISTSIZE=99999
HISTTIMEFORMAT='%Y/%m/%d %H:%M:%S '

ユーザ単位ではなく/etc/bashrcで設定してもいいかも
```

プロンプト変更
---
amazonlinuxはホスト名がローカルIPなので分かりづらい。
でもそういう仕様なのでわざわざホスト名変更したくない。
というときに分かりやすくプロンプトでホスト情報表示させるようにしておきます。

```text:プロンプト変更
# vi /etc/bashrc
36行目をわかりやすく変更
  [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h(ここの部分に分かりやすい名前書くと見やすい) \W]\\$ "
```

　

あとは便利なコマンドとかインストールしておけばいいと思います。
**dstat**とかはシステムリソース情報が分かりやすく取れるのでおすすめです！
いろんなコンソールで画面をクリアする

はじめまして。おはようございます。
この記事は、[筋肉エンジニアアドベントカレンダー2017](https://qiita.com/advent-calendar/2017/mdd)の20日目の記事です。
今月頭に待ちに待った Google Home が我が家にやってきまして、毎朝
「OK, Google. おはよう」「おはようございます。今日は12月～」
「OK, Google. いってきます」「またいつでもどうぞ」
なーんて遊んでいるので、絶対に [Actions on Google](https://qiita.com/tags/actionsongoogle) の記事を書くぞ :muscle: と息巻いていたのですが
全く手つかずのまま公開日を迎えてしまいそうなので **代替記事を上げます。**
新年、リベンジしてこの記事にリンク入れられるようにがんばります……！

さて、業務で様々なOSを触る機会のあるエンジニアの皆さん。
ある日は会社支給のWindows PC、またある日は自分の個人端末のMacBookと
いろんな端末を触っていると思います。
そんなときにふと忘れてしまって、検索するほどでもないがモヤモヤ気になるのが コンソールをクリアする方法ですよね。
**……ですよね？**

というわけで自分の備忘録を兼ねてまとめてみました。

# bash
clearコマンド or [Ctrl + l(エル)]

```bash
$clear
```

# macOS
clearコマンド or [command ⌘ -k] or [control ⌃ + l(エル)]

```bash
$clear
```

# Windows コマンドプロンプト のクリア
clsコマンド

```console
C:\>cls
```

# Powershell
内部関数Clear-Host

```powershell
C:\>Clear-Host
```

---

以上です。
キーボードショートカットが使えるものは、コマンドよりもキーボードショートカットのほうが
スクリプトが走ってログが出ている最中でもクリアできたりと便利な気がします。
年末大掃除と一緒につけっぱなしのコンソールも綺麗にしてしまって
2018年をスッキリした気持ちで迎えましょう！
xbrlと殴り合うためにxpathを使う

有価証券報告書のxbrlとかMB単位のやたら力強いxmlで、
まともに殴り合うとつらすぎるので、xpathで必要なところだけ抜き出す話。

xpathはこのあたりがわかりやすい。
https://qiita.com/rllllho/items/cb1187cec0fb17fc650a

# 下準備

サンプルのターゲットはこいつ。
https://www.mizuho-fg.co.jp/investors/financial/report/yuho_201603/data/xbrl_mhbk160627.zip

`~/Downloads` に落としてきてzipを展開しておく。

欲しいところのnamespaceとタグ名は事前に調べておかないとならない。
ここは手作業。
今回は `jpcrp_cor` 名前空間の、タグ名に `BusinessResults` が含まれる要素を抜き出してみる。

## namespace

`<jpcrp_cor:OrdinaryIncomeSummaryOfBusinessResults ...` みたいなタグ名の、コロンの左側の部分がnamespace。
これは要素名と別に指定が必要。

namespaceはroot要素 `<xbrli:xbrl>` の属性にくっついてる。
`jpcrp_cor` の場合はこれ。

`xmlns:jpcrp_cor="http://disclosure.edinet-fsa.go.jp/taxonomy/jpcrp/2013-08-31/jpcrp_cor"`


# で、こう。

```py3
# coding: utf-8

import os
import lxml.etree

file = '%s/Downloads/xbrl_mhbk160627/PublicDoc/jpcrp030000-asr-001_E03532-000_2016-03-31_01_2016-06-27.xbrl' % os.environ["HOME"]
doc = lxml.etree.parse(file)

ns = {
    "jpcrp_cor": "http://disclosure.edinet-fsa.go.jp/taxonomy/jpcrp/2013-08-31/jpcrp_cor",
}

# 'BusinessResults' が含まれてるタグ名で引っ掛ける
xp = "//*[contains(name(), 'BusinessResults')]"
elems = doc.xpath(xp, namespaces=ns)

for x in elems:
    print(x.text)
```
Project Euler Q51 【素数の桁置換】

Project Eulerをワンライナーで解いてみる。
間違っていたらコメントください。


## 問題
$*3$の第$1$桁を置き換えることで, $13, 23, 43, 53, 73, 83$という$6$つの素数が得られる.

$56**3$の第$3$桁と第$4$桁を同じ数で置き換えることを考えよう. この$5$桁の数は$7$つの素数をもつ最初の例である: $56003, 56113, 56333, 56443, 56663, 56773, 56993.$ よって, この族の最初の数である$56003$は, このような性質を持つ最小の素数である.

桁を同じ数で置き換えることで$8$つの素数が得られる最小の素数を求めよ. (注:連続した桁でなくても良い)

##アプローチ(参考サイトを閲覧した後に記載している)
1.置換する桁は何桁でもいい(問題文から読み取れなかった)
2.置換する桁数は$3$の倍数(根拠がよく分からない)
3.$1$の位は置換してはならない(これは分かる)
4.$8$個置換するのだから$0,1,2$のいずれかで置換可能
5.最小の素数には$0,1,2$が$2$つ以上含まれる

## 解答

```bash
$ time seq 100000 999999 |
factor |
awk 'NF==2{print $2}' |
awk -v FS= '{delete s;printf $0" ";for(i=1;i<=NF;i++){s[$i]+=1};print length(s),s[0]"_",s[1]"_",s[2]"_"}' |
awk '{print $1,$3*1,$4*1,$5*1}' |
awk '{for(i=2;i<=NF;i++){if($i<2){continue};printf $1" ";for(j=0;j<=9;j++){printf gensub(i-2,j,"g",$1)" "};print ""}}' |
factor |
tr ' ' '_' |
xargs -n11 |
tr '_' ' ' |
awk '{for(i=1;i<=NF-1;i++){if(0<index($i,":")){if($i*1==$(i+1)){printf $(i+1)" "}}};print ""}' |
awk 'NF==9&&length==(6*9+9){print $1}'
121313

real    0m27.373s
user    0m11.550s
sys     0m19.835s
```

また問題文を正しく読み取れなかった。。
置換する桁数は何桁でもいいだなんて。。

全体的に超強引に解きました。
`gensub`は使わないと忘れる。
非破壊置換だからすごく便利！

## 答え合わせ
こちらのサイト様と一致していればOKとした。
http://kingyojima.net/pje/051.html

## 参考にさせて頂いたサイト様
[Project Euler 51 - 桃の天然水](http://d.hatena.ne.jp/inamori/20090428/p2)
[Project Euler - Problem 51   1.1s (Ruby 1.9)  ツムジのひとりごと](http://tsumuji.cocolog-nifty.com/tsumuji/2009/08/project-euler-7.html)
[これは強力！ AWKとパイプの新しい関係 ～ 時刻を取得する関数、Socket通信、双方向パイプ (1_2)：CodeZine（コードジン）](https://codezine.jp/article/detail/8322)
Google Cloud Repositories を使ってみる


この記事は 2017.12.19 時点のものです。

---

プライベートなリポジトリが欲しいけど、githubに課金するほど継続するプロジェクトかわからない･･･そんな時、GoogleのCloud Source Repositoryの正式版サービスが2017年の5月頃から始まったことを知りました。今回は **[Cloud Source Repositories - Google Cloud Platform](https://cloud.google.com/source-repositories/?hl=ja)** を使い始めるまでを備忘としてまとめます。

以下のセットアップはWindows10で行っています。

## 価格について
![gcpsr-price.png](https://qiita-image-store.s3.amazonaws.com/0/167943/d5bc0029-e96c-9426-681b-1e77d215166c.png)


- プロジェクトあたり5ユーザまで無料
- 50GBまで無料

## 主な特徴
### よいところ
- プライベートリポジトリが利用可能
- Github / Bitbacketリポジトリとの自動ミラーリングによるバックアップが可能
- ブラウザからソースを眺められる（プレビューはまだ貧弱）

### わるいところ
- 住所・クレカ登録が必要
- セットアップ手順が多い
- ローカルに [Cloud SDK](https://cloud.google.com/sdk/?hl=ja) というGCPサービスCLIのインストールが必要
- ユーザ名はフルメールアドレスでかつ、パスワードには自動生成された長ったらしいものしか使えない？

## 利用開始までの手順
1. Google Cloud Platformに登録する（住所＆クレカの入力）
2. GCPコンソール上で新規プロジェクトを作成する
3. 作成したプロジェクトでSource Repositoriesの利用を有効にする
4. リポジトリを作成する
5. ローカルPCにCloud SDKをインストールする
6. ローカルPCでCloud SDKの初期設定（GCPとの接続認証と初期設定）を行う
7. プライベートリポジトリとの認証のためにローカルPCに `netrc` ファイルを作る
8. セットアップ完了！ようやく利用開始できます。

## ちょっと手間取った要点
認証設定ヘルプページではUNIX系向け手順しかありませんでした。

Windows10でかつローカルにgitの1.6以上がインストールされている場合は、ローカルに次のnetrcファイルを作成してください。

```
場所：
C:\Users\{ユーザ名}\_netrc

内容：
machine source.developers.google.com
login {認証時に表示されたusrename}
password {認証時に表示されたpassword}
```

それ以外の手順は多いですが、丁寧な公式ドキュメントがあるので特につまづきませんでした。

## リポジトリのブラウザ上でのプレビュー
### ファイルツリープレビュー
READMEのプレビューを表示してくれない。

![gcpsr-dir.png](https://qiita-image-store.s3.amazonaws.com/0/167943/7274ef8b-eedc-d93a-879c-23f954c6dc48.png)

### ファイルプレビュー
マークダウンは生のテキストで表示されます。シンタックスハイライトも貧弱そうな印象でした。

![gcpsr-js.png](https://qiita-image-store.s3.amazonaws.com/0/167943/12458e5b-9785-dd51-71bb-e4e20ab9139a.png)

## まとめ
サービス開始からまだ日が浅いのもあり、プレビュー機能などがまだ弱い印象でした。

メインで使うなら Bitbucket や Gitlab などのほうが導入コストやソースプレビュー機能などの面で勝っている印象を受けましたが、リポジトリのミラーリング機能というユニークな機能を提供しているので万が一のバックアップ用に第2のリポジトリとしての選択肢には良いかもしれません。

個人的にはもう少し成熟するまでは Bitbucket を使おうかなという印象でした。
データとプライバシーとディープラーニング

今日はプログラミングの話は一切出てきませんが、たまにはこんな話題もいいかなと。

#はじめに
デジタル技術の発展に伴い、データサイエンスや人工知能（AI）などの情報技術を産業・社会の様々な領域に活用しようとする動きが活発化している中で、さまざまなシーンで収集されたデータを活用することによって、これまでにないパーソナライズされた製品・サービスを創造し、新たな社会構造を築く可能性があります。一方で、パーソナルデータにはプライバシーの侵害・情報漏洩の懸念があり、データの利活用が進んでいないのも実情です。


#自分のデータは大事に取り扱ってほしい？国際比較！
みなさんはFacebookやTwitterなど使っていますか？SNSによっては、実名で登録していたりニックネームを使っていたり、様々ですよね。パーソナルデータに関する国際比較アンケートの結果によると、日本人は特にSNSで実名が公開されることに抵抗を感じているようです。

　　

![n3102050.png](https://qiita-image-store.s3.amazonaws.com/0/127614/b5489a1a-6553-baae-666e-50a6f04ee87b.png)　

さらに、パーソナルデータと他の情報を紐づけて、新しいデータを生み出したり様々なサービスに活用することができます。いつの間にか、自分が検索していたキーワードが広告として現れたり、ポップアップでお知らせが出たり、カレンダーに登録されていたり、便利といえば便利なんだけど、ちょっとビックリすることたまにありますよね。世界中の人たちも、そういうのはあまり許容できないみたいですね。


　　![n3102070.png](https://qiita-image-store.s3.amazonaws.com/0/127614/6a82c32b-0679-dd92-1925-14e0286f0270.png)

#Deep Multi-Task Learningでプライバシーを守る
ところで、友達と過ごした楽しい思い出の写真や、公共の場所で撮影した写真をSNSにアップして（悪気はないけれど）他人の写真を勝手に公開してしまうことってありますよね。それで気まずい思いをしたことがある人も少なくないと思います。そこで、配慮が必要な画像からプライバシー保護の対象を抽出し、適切な処理をしてくれる方法について書かれた論文を紹介します。

iPravicyという新しいアプローチは、SNSなどに公開された画像のプライバシー設定を自動化するために開発されました。４つのプロセスを経て、画像の中のプライバシーを保護します。

①人間や車など形あるものと背景を分ける
DCNN（Deep Convolutional Neural Network）とCRF（conditional random fields）モデルを使って、人間とそれ以外のものと背景を識別します。

![image1.png](https://qiita-image-store.s3.amazonaws.com/0/127614/284184a4-2db0-1a2a-cc51-b9201935fa4f.png)

②プライバシー保護の対象のものとそうでないものを分ける
ビジュアルツリー構造を使って、プライバシー保護のクラスを分類します。


③プライバシーに配慮が必要な物体を迅速かつ的確に検出
見た目が似ているプライバシー配慮対象物をちゃんと区別するため、識別力を高めるDeep Multi-Task Learningを使います。



④保護が必要な物体のプライバシー設定を識別
![image2.png](https://qiita-image-store.s3.amazonaws.com/0/127614/185b8c37-a4fe-4fa2-d1dc-2c304f8f3e1c.png)
(a)元画像；(b)人間を抽出；(c)人間の部分だけを切り取り；(d)顔認識；(e)プライバシー保護が必要な対象をぼかす；(f)背景を戻す

詳しい説明は省略しましたが、このようなアプローチは今後サービスに実装され、SNSがもっと使いやすくなるかもしれませんね。しかし、パーソナルデータは画像に限らないため、色々なデータを組み合わせることによって個人が特定される可能性はたくさんあります。プライバシー保護は法律や規制だけでなく、このような技術的観点からの解決するニーズは今後さらに高まってくるでしょう。

ちょっとマジメなお話でした。


##参考文献
・総務省, 情報通信白書平成25年版. 
・Yu, Jun, et al. "iPrivacy: image privacy protection by identifying sensitive objects via deep multi-task learning." IEEE Transactions on Information Forensics and Security 12.5 (2017): 1005-1016.
Archインストールで微妙な躓きと微妙な解決した話

# ArchLinuxインストールバトル
うちの部活でも多くの人が挑んできているArchのインストール、ここ数日私も挑戦していました。
マシンはThinkpad X230、今まではKubuntuで運用してきたもののプロコンの某氏に**クソ**と言われたのでArch入れようかと。

#インストールできたけどBootしない
まぁ、かなり多くの人がGRUBのインストールだったりなんだりで躓くと思いますし、まぁこんなことはありふれてるのでしょうが。
X230はUEFI対応で、GRUB以外にも幾つかの方法でESPパーティションを埋められますが、今回はSystemdを使いました。

#NotFound💢

Systemd自体の導入は極めてシンプルで、GRUBを使う理由が見つからなくなるほどに優秀なのですが・・・
今回やってみたら、Boot時に「vmlinuz-linuxがない」って怒られました。
最初気づかず何回か再インストールするアホなことしてました・・・。

#で？
実はググったらすぐ出てくるので書く必要ないかもなんですけれど、
`pacman -S linux`
で治りましたｗ

というのもこれ、無くなってるのってLinux Kernelらしいのです。
なので、そのまま、Pacmanで入れ直してやれば・・・動いちゃう・・・。

#オチ
なし。なんで書いたんだろう、ああ、備忘録だったそうだった。
Arduino-ESP32 WatchDogTimer

Arduino-ESP32でウォッチドッグタイマーを使用する方法です。
※20181022 esp_restart_noos()コマンドが変更されていましたので更新しました。

WatchDogTimerのサンプル[libraries/ESP32/examples/Timer/WatchdogTimer/WatchdogTimer.ino](https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/Timer/WatchdogTimer/WatchdogTimer.ino
)があります。

```WatchdogTimer.ino
#include "esp_system.h"

#include "esp_system.h"

const int button = 0;         //gpio to use to trigger delay
const int wdtTimeout = 3000;  //time in ms to trigger the watchdog
hw_timer_t *timer = NULL;

void IRAM_ATTR resetModule() {
  ets_printf("reboot\n");
  esp_restart();
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println("running setup");

  pinMode(button, INPUT_PULLUP);                    //init control pin
  timer = timerBegin(0, 80, true);                  //timer 0, div 80
  timerAttachInterrupt(timer, &resetModule, true);  //attach callback
  timerAlarmWrite(timer, wdtTimeout * 1000, false); //set time in us
  timerAlarmEnable(timer);                          //enable interrupt
}

void loop() {
  Serial.println("running main loop");

  timerWrite(timer, 0); //reset timer (feed watchdog)
  long loopTime = millis();
  //while button is pressed, delay up to 3 seconds to trigger the timer
  while (!digitalRead(button)) {
    Serial.println("button pressed");
    delay(500);
  }
  delay(1000); //simulate work
  loopTime = millis() - loopTime;
  
  Serial.print("loop time is = ");
  Serial.println(loopTime); //should be under 3000
}
```

ウォッチドッグを使う順序は以下

1. セットアップ
    - タイマーの初期化 // timer = timerBegin(0, 80, true); //timer 0, div 80
        - 関数の引数はそれぞれ
            - uint8_t num　タイマーの番号　(4つのタイマーのどれを使用するか指定する。0から3まで)
            - uint16_t divider ディバイダ　Set 80 divider for prescaler (see ESP32 Technical Reference Manual for more info).
            - bool countUp　(カウントアップかカウントダウンかを指定する。/*When set  timer 0/1 time-base counter increment. When cleared timer 0 time-base counter decrement.*/)
    - コールバックの指定 // timerAttachInterrupt(timer, &resetModule, true);
    - ウォッチドッグタイマーのタイムアウト時間の指定 // timerAlarmWrite(timer, wdtTimeout * 1000, false)
2. ウォッチドッグタイマーの有効化
    - timerAlarmEnable(timer);  
3. 監視したい場所でタイマーをリセットする。
    - timerWrite(timer, 0); //reset timer (feed watchdog)
4. ウォッチドッグタイマーの無効化
    - timerAlarmDisable(timer);  

トラブルシューティング

```errormessage.sample1
Task watchdog got triggered. The following tasks did not reset the watchdog in time:
- IDLE (CPU 0)
Tasks currently running:
CPU 0: timeCheckTask
CPU 1: loopTask
```
以下を参考にしてください。
https://www.mgo-tec.com/blog-entry-trouble-shooting-esp32-wroom.html/4
1.タブ区切りのファイルをtabulator で表示する

#tabulatorを利用する

[0.タブ区切りのファイルをtabulator で表示する](https://qiita.com/percipere/items/a9502af51a17eab86326)で読み込み用のjsonファイルができたので、これをtabulatorを利用して表示してみる

- jquery v3.2.1, jquery-ui v1.12.1, tabulator v3.3.2を利用
    - head要素のscript及びlink部分
- body要素中のscriptで、tabulatorのテーブルの定義と、jsonの読み込みを実行
    - コラムの定義部:
        - gene_columnsで各コラムを指定
            - title: 表示されるタイトル名
            - field: 対応するデータ要素（ここでは、LRG_RefSeqGeneのヘッダーの各コラム名)
    - tabulatorの初期化
        - columnsにgene_columnsを指定
    - データの読み込み
        - "setData"でjsonを読み取り（ローカルファイルのjsonを指定)

```html:index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"
            integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
    <script src="http://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
            integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/tabulator/3.3.2/css/tabulator.min.css" rel="stylesheet">
    <script type="text/javascript"
            src="https://cdnjs.cloudflare.com/ajax/libs/tabulator/3.3.2/js/tabulator.min.js"></script>
    <title>Tabulator Test</title>
</head>
<body>
<script>
    $(document).ready(function () {
        // コラムの定義
        var gene_columns = [
            {title: "GeneID", field: "GeneID"},
            {title: "Symbol", field: "Symbol"},
            {title: "RSG", field: "RSG"},
            {title: "LRG", field: "LRG"},
            {title: "RNA", field: "RNA"},
            {title: "t", field: "t"},
            {title: "Protein", field: "Protein"},
            {title: "p", field: "p"},
            {title: "Category", field: "Category"}
        ];
        //　tabulatorの設定
        $("#gene-table").tabulator({
            columns: gene_columns
        });
        // ajaxでデータの読み込み
        $("#gene-table").tabulator("setData", "./output.json");
    });
</script>
<h1>LRG_RefSeqGene viewer</h1>
<div id="gene-table"></div>
</body>
</html>
```

ブラウザがローカルファイルの読み取りを許可していない場合には、ローカルファイルの読み取りを許可する必要がある。
Safariの場合には、
Preference => Advanced  で　Show Develop menu in barにチェックし、更に
Develop => Disable Local File Restrictions にチェック

index.htmlをブラウザーで読んで、下記の様なテーブルが表示されたら成功
![Screen Shot 2017-12-19 at 16.55.00.png](https://qiita-image-store.s3.amazonaws.com/0/213053/eabd166e-5dbe-5a78-5217-869c60a6266f.png)

今回はここまで:smiley:
Word 2016 | Excel 2016 > プチフリを解消する > ハードウェアグラフィックアクセラレータを無効にする

```txt:動作環境
Windows 8.1 Pro (64bit)
Office 2016
```

Office 2013からOffice 2016に変更後、プチフリが発生するようになった。
Word 2016では、3ページの資料スクロール時に3秒程度固まる。
Excel 2016では、新規シートにて、Ctrl + 下実行時に3秒程度固まる。

https://support.microsoft.com/en-us/help/3066990/memory-usage-in-the-32-bit-edition-of-excel-2013-and-2016
などを見ると、ハードウェアグラフィックアクセラレータを無効にするという案がある。

Wordのオプションから下記の項目にチェックを付けたところ、プチフリは発生しなくなった。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/0da35195-c0c9-d178-03b7-3712e9ff0def.png)

Excel 2016の方もプチフリ問題が解消していた。WordとExcelで共通設定になっている。
CakePHP2.x系のテストでSQLiteをインメモリで利用する

# テストに時間がかかる！
Cakephpで、なんかテストの完走まで時間かかるようになってきたなー。とか感じる事ありませんか？
プロジェクト立ち上げ当初は3分くらいで完走したけど、テストケース増えて20分くらいかかるようになった。とか。

# SQLiteをインメモリで使う

```php:app/Config/database.php
    public $test = [
        'datasource' => 'Database/Sqlite',
        'persistent' => false,
        'database'   => ':memory:',
        'prefix'     => '',
        'encoding'   => 'utf8',
    ];
```

これで爆速になります。
ラズパイ起動後にIPをメールで自動送信

#**ラズパイ起動後にIPをメールで送信**

最初はGmailでやろうと思ったんですけど、セキュリティ的に弾かれたので別の方法にしました。

また、ここではメールの送信サーバをインストールしてやってますが、めんどくさかったので、送信専用のウェブページ作って、そこをpythonで自動的に送信させよう。（どっちがめんどくさいかは考えない）
http://raspi.seesaa.net/article/421958492.html

実際は下記になります。

#流れ
1. 送信用メールフォームのあるwebページを作る
2. そのページからメールを送るようなpythonプログラムを作る
3. ラズパイからそのプログラムを自動で実行するよう設定する


#メール送信するページ作成
どこかで作ったやつをそのまま持ってきました。

```index.html
<html>
<body>
    <form id="campaign" name="campaign" action="confirm.php" type="post" method="post">
        <p><input type="text" name="ip" id="ip"/></p>
        <input type="submit" value="SUBMIT" />
    </form>
</body>
</html>

```

```confirm.php

<?php
    mb_language("Japanese");
    mb_internal_encoding("UTF-8");
    $to      = 'メールアドレス';
    $subject = 'Raspberrypi IP address';
    $ip=htmlspecialchars($_POST["ip"]);
    $message = $ip;
    $headers = 'From:'. $email . "\r\n";
    mb_send_mail($to, $subject, $message, $headers);
?>

```

ここのURLをhttp://autosendmail.com とします



#ラズパイの自動化設定
`/home/pi/lxsession/LXDE-pi/autostart`
上記ファイルの一番下にこれを追加（ラズパイのOSによって異なると思うので、適宜ググってください。）
```@python /パス/autosend.py
```

ちなみにautosend.pyの中身。


```autosend.py
import netifaces
import mechanize

myip = []

def detectip():
    for iface_name in netifaces.interfaces():
        iface_data = netifaces.ifaddresses(iface_name)
        ip_adressList = iface_data.get(netifaces.AF_INET)
        if ip_adressList != None:
            ip_address = ip_adressList[0]['addr']
            myip.append(ip_address)
    return myip

def sendmail():
    br = mechanize.Browser()
    br.open("http://autosendmail.com")
    br.select_form(nr=0)
    br["ip"] = str(detectip())
    br.submit()

if __name__ == "__main__":
	sendmail()

```

#結果

![ss.jpg](https://qiita-image-store.s3.amazonaws.com/0/212730/7ae317e8-eb75-a3e6-07a7-96eb307a8d3e.jpeg)

少し余計なものも来てますが、十分ですのでこのままいく！

以上です。
Selenium+PhantomJSで無料の翻訳APIっぽいことを実現する

# はじめに
精度の高い翻訳APIを利用しようとすると、どうしても有料のAPIということになってしまい苦学生にはなかなか厳しい…  

そこでをSelenium+PhantomJSで無料で翻訳APIっぽいことを実現します。

# 準備
今回はPython3.6で実装していきます。

まず作業用のディレクトリを作成します。

```console
$ mkdir free_translate
$ cd free_translate
```

Seleniumをインストールします。

```console
$ pip install selenium
```

PhantomJSをインストールします。

```console
$ npm install phantomjs --save
```

# コード
```python3:translate.py
from selenium import webdriver
import time
import sys
import os

def translate(q):
    url = 'https://translate.google.co.jp/?hl=ja&tab=TT#ja/en/'

    user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
    pjs_path = 'node_modules/phantomjs/bin/phantomjs'
    dcap = {
        "phantomjs.page.settings.userAgent": user_agent,
        'marionette': True
    }
    log_name = os.path.abspath(os.path.dirname(__file__)) + '/ghostdriver.log'
    driver = webdriver.PhantomJS(executable_path=pjs_path, desired_capabilities=dcap, service_log_path=log_name)
    driver.get(url)
    input_form = driver.find_element_by_id('source')
    input_form.send_keys(q)
    time.sleep(0.5 * len(q))
    result_form = driver.find_elements_by_id('result_box')
    result = ''
    for i in result_form:
        if i.text:
            result = i.text
            break
    driver.quit()
    return result

if __name__ == '__main__':
    print(translate(' '.join(sys.argv[1:])))
```

# 実行
```console
$ python translate.py こんにちは世界
Hello world
```

実行すると初回警告が出ますが許可して大丈夫です。

# 最後に
無料で翻訳できましたが、とにかく遅い。APIを使うほうが現実的だと思います。
【初心者向け】Ruby、ルビーって言われるけど実際どうなの？

[Ateam Hikkoshi Samurai Inc. Advent Calendar 2017](https://qiita.com/advent-calendar/2017/hikkoshi)　20日目です。
本日は[エイチームコネクト](http://connect.a-tm.co.jp/)の中途2年目、お菓子大好き中年Webエンジニアの@taka999が担当します。

#背景
ここ最近周りでRubyでの開発が更に活発になってきた。
Rubyでナニナニ、Rubyでナニナニって、、、PHPではいかんのかと。。。
何も知らずに文句を垂れるのは芸がないので、WEBエンジニア初心者ながらルビーってのを調べてみることに。

#はじめに
自分自身が『ど初心者』なので、あまりソースコードで説明は出来ないし、参考サイトもソースコードで説明されてないサイトを選んでいます。

まずはありきたりなのですが「Rubyとは」で検索
 ・すべてオブジェクト指向
 ・インタプリタ方式
 ・構文の自由度が高い

なるほど！
プログラミングをやった事がある者には多少分かるが、知らない人には優しくないお言葉。

#特徴1：オブジェクト指向
これを上手く説明できるひとってどれだけいるのだろうか。。。
という自分も何となくでしか理解できていないため以下を参考に。
[5分で絶対に分かるオブジェクト指向](http://www.itmedia.co.jp/im/articles/0703/06/news125.html)
[オブジェクト指向とは何か？わかりやすい例で説明してみた。](https://www.sejuku.net/blog/5973)

オブジェクト（物）は継承でき、基本となる物を作れば、それを元に別のものを簡単に作れ応用も聞く。
ゲームで言うと1つの基本キャラを作り、こいつを元に色と強さを変えたキャラを作っていく感じ。
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/146596/1b255b43-f34f-c59b-f5bd-329e8a6ea32b.png)

#特徴2:インタプリタ方式
プログラミング言語の命令を一つずつ機械語に解釈し実行するから、ソース書いて即実行できるよって方式。

■メリット
プログラム開発途中にちょいちょい実行させながら確認ができるので、プログラムが作りやすくデバッグも容易。

■デメリット
都度一つずつ解釈するため、変数にアクセスする際も識別子とメモリ上の位置のマッピングを確認しながら実行していくので実行速度が遅くなる。

#特徴3:構文の自由度が高い
構文と言われるとコードを見るしか無いのでちょっと記載。

■整数型の変数を定義

```java:Javaの場合
int var = 123;
```
```ruby:Rubyの場合
var = 123
```

■繰り返し

```java:Javaの場合
for (int i = 0; i < 10; i++) {
    System.out.println(i);
}
```
```ruby:Rubyの場合
10.times do |i|
  puts i
end
```

■switch（case）文

```java:Javaの場合
switch(num){
   case 1:
        System.out.println("a");
        break;
   case 2:
   case 3:
   case 4:
        System.out.println("b");
        break;
}
```
```ruby:Rubyの場合
case num
when 1
  puts 'a'
when 2..4
  puts 'b'
end
```

コード量が少なくて済むので楽だね~
文法に制限が少ない分、個々の好みがモロに反映されそう

#フレームワーク
Ruby on Rails、Sinatra、HANAMIなど色々あり。
[Ruby on Railsだけじゃない！Rubyフレームワーク6選](https://eng-entrance.com/ruby-framework)

今までの歴史と人気からみても『Ruby on Rails』一択で良さそう。

#その他
~~Ruby用のライブラリは『gem』と呼ばれていて、かなりの数のgemがあるらしい。~~
Rubyで使われるライブラリを、Gemと呼ばれる形式でパッケージ化された物が多数あるらしい。
イチからわざわざ作らなくても、欲しい機能を探せばヒットする可能性は高く開発が楽ちんになる。
※ライブラリとは、共通的な処理や便利な機能をまとめた外部プログラム
[作業効率が上がる！Rubyの開発で知っておくと便利なgem10選](https://techacademy.jp/magazine/9776)

#まとめ
かいつまんだレベルなので決めつけれないが、PHP含め他の言語でも同じような特徴であるものの、フレームワーク選択に迷わないしライブラリ（gem）も豊富でコードも短く書けちゃうとくれば、開発のしやすそうなRubyから始めるのも有りかと思う。
ただ、既に別の言語（PHPやperlなど）で開発していて困っている事がなければ、わざわざRubyに変更する必要もないかな。
この言語だと開発しやすいとかで選ぶ事もあるけれど、やりたいことを実現させるにはこの言語！って選定していくことが大事だと思う。

#最後に
[Ateam Hikkoshi Samurai Inc. Advent Calendar 2017](https://qiita.com/advent-calendar/2017/hikkoshi)　20日目いかがでしたでしょうか。
明日は[エイチーム引越し侍](http://hikkoshi.a-tm.co.jp/)の一時期心理学にハマったフロントエンジニア@hashimoto-1202が
『vue-rooterを使ってSPAv(シングルページアプリケーション)を作成してみた』
を書いてくれますのでお楽しみに。

# 追伸
エイチームグループでは、一緒にWebサービス・技術の向上、そして未来を創造していく仲間を募集しています。
30代後半で業務系システムエンジニアからWEBエンジニアに変更した私も、新たな挑戦をしながら進んでいますので、今まで一歩を踏み出せなかったエンジニアも、エイチームグループに興味がある方も是非、以下のリンクから応募してください。
皆様からのご応募、お待ちしております！！

> [エイチームグループ採用サイト（Web開発エンジニア職）](http://hikkoshi.a-tm.co.jp/recruit/request.php?ea=[ここにクリックを識別するためのkeyを入れる])
AWS Glueでカンマを含むCSVは読み込めませんでした

# はじめに
* 以下のようなcsvファイルをAWS Glueで読み込んだところカラム名が読み取れずしばらく悩んでましたが、なんてことはないカンマを含む値が読み取れなかっただけでした

```test.csv
Column0,Column1,Column2
hoge,"fu,ge",hage
foo,bar,baz
```

#### `desc test`
* ![スクリーンショット 2017-12-19 16.47.12.png](https://qiita-image-store.s3.amazonaws.com/0/22341/9c4f57f6-e3e8-9a91-5262-4039934fcee7.png)
    * *カラム名が読み取れてない*

#### `select * from test`
* ![スクリーンショット 2017-12-19 16.47.57.png](https://qiita-image-store.s3.amazonaws.com/0/22341/3971de72-8b2e-0823-e13f-c4f9a1d9c573.png)
    * *Colums1の値がカンマで分けられ `"fu` `ge"` に分離してしまっている…*


# 解決策
* CSV以外のフォーマットを利用する
    * JSONなどにすればこの問題は解決できました
    * ただしJSONにする際には1行/レコードになるようにしておかないとAthenaで検索するときにハマるようです、ご注意ください
     * http://mao-instantlife.hatenablog.com/entry/2017/09/16/AWS_Glue%E3%81%AE%E3%81%8A%E8%A9%A6%E3%81%97%EF%BC%9AJSON%E3%82%92%E6%89%B1%E3%81%86%E6%99%82%E3%81%AB%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85%E3%81%8C%E3%81%82%E3%82%8B%E3%81%A3%E3%81%BD%E3%81%84

```test.json
{"Column0":"hoge","Column1":"fu,ge","Column2":"hoge"}
{"Column0":"foo","Column1":"bar","Column2":"baz"}
```
M1グランプリ2017は本当にすごかったのかをグラフ化してみた

## きっかけ

[E2D3](http://e2d3.org/ja/)のワークショップで、[『グラフをつくる前に読む本』](http://amzn.asia/gOd8M0w )の作者・松本健太郎氏が、

> M1グランプリ2017はすごかったですね

と言っていた。

私は、観ていなかったので、本当にすごかったのかどうか、グラフ化してみた。

![m1_orbit.png](https://qiita-image-store.s3.amazonaws.com/0/122504/24ef5980-ad12-3a9a-ea6c-9ab5765b5cdc.png)
[ツールチップを付けたD3.js版はこちら](https://xiushu53.github.io/m1_orbit/)



## 前提・データ収集

まず前提として、M1グランプリ決勝戦は、1stステージで、決勝戦進出の9~10組の出場者が漫才を行い、審査員（毎年、メンバー、人数が変化）が100点満点で審査。その合計の上位3組、ないし、2組が2ndステージに進出し、2度目のネタ披露。審査員はその中で一番面白かったと思う１組に投票。総得票数が一番多かったコンビが優勝となる。また、その中で、敗者復活制度もある。

データは、[M1グランプリ公式サイト](https://www.m-1gp.com/)にあります。
ページ内の「大会の歴史」から過去データにもアクセスできます。

仮説としては、
1. 2017年大会は過去大会よりも、レベルが高かった -> 得点の平均点が高い
2. 接戦・激戦・混戦であった -> 出場組の平均点のばらつきが小さい


ということとして、2017年大会は「きっと、平均点が高く、ばらつきは小さいのでは」と仮定しました。

なお、データは1stステージの各組×審査員の得点のみを使用。今回、2ndステージは考慮してませんので、あしからず。


## 仮説に従ってデータをつくる

* year -> 開催年
* score_mean -> 全組の平均点
* intenseness -> 接戦の度合(1 / 各大会の平均点の標準偏差)
* winner -> 優勝組

※ ばらつきの指標としては、大会ごとに出場者数が違うため、標準偏差にしました。その上で、数が大きいほど、接戦の度合が大きいとしたかったので、逆数を取りました


要約したデータは↓↓

| year | score_mean | intenseness | winner |
|:-----|------------------:|:------------------:|:------:|
| 2017 | 90.60000000000001 | 0.48030906559569353 | とろサーモン |
| 2016 | 90.13333333333333 | 0.4029114820126905 | 銀シャリ |
| 2015 | 89.96296296296295 | 0.5741108388985465 | トレンディエンジェル |
| 2010 | 90.15873015873017 | 0.27406527228459493 | 笑い飯 |
| 2009 | 89.65079365079364 | 0.29908582824533947 | パンクブーブー |
| 2008 | 89.34920634920634 | 0.37482075996745506 | ＮＯＮ ＳＴＹＬＥ |
| 2007 | 87.39682539682539 | 0.23604447261304098 | サンドウィッチマン |
| 2006 | 87.65079365079366 | 0.23362193373224205 | チュートリアル |
| 2005 | 86.98412698412699 | 0.18363211159441903 | ブラックマヨネーズ |
| 2004 | 87.79365079365078 | 0.23109387206456072 | アンタッチャブル |
| 2003 | 85.4920634920635 | 0.16790734071483362 | フットボールアワー |
| 2002 | 79.98412698412699 | 0.20137227201334743 | ますだおかだ |
| 2001 | 71.68999999999998 | 0.10663206977758906 | 中川家 |


## グラフ化

とりあえず、散布図にしてみたが、イマイチだったので、オービットチャートで表現。理由としては、"去年よりも面白かった"など、以前と比べてどうだったかを表現したかったため、時間を持ちこんでみました。

なお、オービットチャートについての詳しい話は[Orbit charts, and why you should use them | Michel Baudin's Blog](http://michelbaudin.com/2013/05/20/orbit-charts-and-why-you-should-use-them/)を参照してください。

話が逸れますが、私は下のオービットチャートはとても好きなグラフです。
ブラジルのGDPとGNIの推移をプロットしたもので、その時代の政権を色で区分しており、どの政権時代に所得格差が広がったのかなどが分かります。
![brazil-gini-versus-gdp-chart.jpg](https://qiita-image-store.s3.amazonaws.com/0/122504/44f096e2-5980-821e-a581-09bf956fca10.jpeg)

オービットチャートは、散布図に時間を付加できるのが強みですが、ただし、時間のスケールが均等でなく、視覚と一致しないところが弱点といえます。
あと、軌跡が重なったりすると、見にくかったりしますので、いい軌跡になるとうれしいです


## グラフを見て結論

* 平均点は歴代１位、接戦度は歴代２位と、M1歴史上のベスト大会に入るのではないでしょうか
* 基本的に平均点、接戦度は上昇傾向にある。再開後2015年大会以降は高いところで留まっている感じ。来年も期待できるのではないでしょうか

よって、結論、来年は見てみよう。
kubectl completion: Bash/Zsh 向けの kubectl のシェル自動補完

## はじめに

Kubernetes のコマンドラインツールである kubectl (cube control[^cube-control]) には Bash/Zsh 向けの shell autocompletion が実装されています。シェル自動補完を利用すればサブコマンドや Pod 名を途中まで入力すれば後は動的に値を候補から補完してくれます。もうリソース名をコピペする必要はありません。

![kubectl completion](https://qiita-image-store.s3.amazonaws.com/0/3780/d7b0afb2-119b-c3b5-bf04-aa5cefdf772f.gif)

[^cube-control]: The canonical pronunciation of kubectl is "cube control". https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.9.md

## シェル補完を有効にする

Bash を使用していれば次のコマンドを実行して `.bashrc` に一行追記します。これで次からのシェルの実行で自動的にシェル補完が有効になります。

```bash
echo "source <(kubectl completion bash)" >> ~/.bashrc
```

macOS で Bash を使用しているなら、Homebrew で bash-completion を事前にインストールする必要があります。

```bash
## macOS 標準の Bash 3.2 を使用しているなら
brew install bash-completion
## Bash 4.1+ なら
brew install bash-completion@2
```

Zsh を使用しているなら、次のコマンドを実行して `.zshrc` に一行追記するだけです。

```bash
echo "source <(kubectl completion zsh)" >> ~/.zshrc
```

## 最近の kubectl completion トピックス

### ショートフラグでのコンテキストのオーバーライドをサポート

kubectl のシェル補完はいくつかのフラグがコンテキストのオーバーライドに対応しており、例えば操作する対象のネームスペースを指定する `--namespace` フラグは Pod 名などのリソース名を入力する前に設定しておくことで、対象のネームスペースのリソースを補完候補として使用してくれるようになります。オーバーライドに対応しているオプションは次のとおりです。

- `--kubeconfig`
- `--cluster`
- `--user`
- `--context`
- `--namespace`
- `--server`

またこれまでショートフラグである `-n` (namespace) や `-s` (server) はオーバーライドに対応していませんでしたが、kubectl 1.9 からこれをサポートしました[^issue-54406]。これによりタイプ数をより少なくすることができます。

![ショートフラグでのコンテキストのオーバーライド](https://qiita-image-store.s3.amazonaws.com/0/3780/d95f12de-2cfb-248a-a40f-4d1c7128c82d.gif)

[^issue-54406]: https://github.com/kubernetes/kubernetes/pull/54406

### Zsh で `--flag=value` 形式でフラグを指定すると補完が壊れる問題を修正

`--flag=value` 形式でフラグを使うのが好きな方に朗報です。Zsh 向けの補完でこのイコールを使う形式でフラグを指定すると補完が壊れる問題がありましたが、これは kubectl 1.8 で修正しました[^issue-48553]。kubeadm でも同様の問題がありましたが、これも修正されています。

![`--flag=value` 形式でフラグを使うのが好きな方に](https://qiita-image-store.s3.amazonaws.com/0/3780/9b113f2b-2381-e4f9-f9a5-f0d2571c2959.gif)

[^issue-48553]: https://github.com/kubernetes/kubernetes/pull/48553

## おわりに

kubectl completion は、現在のところ Bash/Zsh のみのサポートとなっています。Fish 向けには補完スクリプトがあるようです[^fish-for-kubernetes]。また kubectl のインタラクティブシェルである [kube-prompt](https://github.com/c-bata/kube-prompt) は、使用しているシェルに関係なく補完を利用することができるため、こちらもおすすめです。

より快適な Kubernetes ライフを目指して Kubernetes 1.6 から kubectl completion に継続的にコントリビュートしていきました。今後もよりよくなるように取り組んでいきます。

[^fish-for-kubernetes]: https://qiita.com/Ladicle/items/09c129d54a8bb3e13ebb

---

このエントリは、弊社 Z Lab のメンバーによる [Z Lab Advent Calendar 2017](https://qiita.com/advent-calendar/2017/zlab) の19日目として当日業務時間中に書きました。
2017年の振り返り(インフラ)

## 初めに

こんにちは。[CYBIRDエンジニア Advent Calendar](https://qiita.com/advent-calendar/2017/cybird)
21日目はインフラ部所属[@kenchang100kg](https://qiita.com/kenchang100kg)です。
20日目は[@kanacha](https://qiita.com/kanacha)の「iOS・Androidアプリの自動ビルド環境を構築した話」でした。

[@kanacha](https://qiita.com/kanacha)さんの記事よかったですね。
読みやすくまとまってました。

ビルドが人頼りではなくなると担当がいないから提出用のビルドが出来ない！
申請が間に合わない！告知してたイベントが！
なんて事にならないからいいですよね。

## 2017年の振り返り(個人)

個人的な興味があった出来事で振り返ってみると、
EVO2017で日本人プロゲーマーである、ときどさんが優勝、
Steamで販売されてる、PlayersUnknownBattleGroundが爆発的に流行ったり、
他にも色々とビッグタイトルが発売・発表され、
2017年はPCゲーム・コンシューマゲームが熱かったなぁと思ってます。

## 2017年の振り返り(仕事)

2017年のCYインフラ部で起きた特に大きな変化と言えば…

* プロビジョニングツールをChefからItamaeに

* TerraFormでインフラの構築・変更・バージョン管理を行うように

この中で今回はChefからItamaeに何故乗り換えたのか、
弊社で使っていたChefの課題とかを書いていこうかと思います。

## 課題

### 色々覚えることが多い問題

私がCybirdに入社してインフラ部のメンバーとして働き始めた時、
一番最初にやったことがChefの学習でした。
入社するまでこういうプロビジョニングツールに触れてこなかった私は結構苦労しました。
実際に周りのメンバーのChef習熟度もかなりマチマチでした。
ローカルに実行環境を作るにもググると皆やり方が違っていて、
Chefってなんなんだろう、となってしまったりもしました。
また私の後に入った新しいメンバーも最初は結構苦労していました。

### そんなにChefの機能使ってない問題

弊社はPJ単体でみると`chef-solo(chef-zero)`で実行管理するレベルで、
一つ一つはそこまで大きな規模の環境ではありません(20台無いくらい)。
`Resources`とかもそんなに多くの種類は使ってませんでした。
ChefServer構築してそこで一元管理するとかも特に行っておりませんでした。
台数もそんなに多い訳ではないので、この使い方は別に間違っていたとは思わないですが、
そもそもそれだけしか使っていないのであれば、
学習コストが高いChefにこだわる理由があまりないよなぁとは思っていました。

## Chefの反省を活かして

他にも色々とChefを使ってて気に入らない事はあったのですが、
(chefの為だけにrubyがインストールされるとか)
そんな感じでChefを運用してみて色々と反省点が出てきて、
こうなったら改善じゃなくて刷新じゃ！Chef卒業じゃ！となり、
次世代のプロビジョニングツールを探す事にしました。
選定基準は下記方針にしました。

* 手軽に覚えられる物がいいよね
* シンプルな機能だけでいいよね
* ある程度Chefの資産(知識)も使いまわせるといいよね

## itamaeを選んだ

そんな選定基準をクリアしたのがitamaeでした。~~若干出来レース感はあった~~
itamaeはクックパッド社員の荒井良太氏が開発したChef Likeなサーバプロビジョニングツールです。
itamaeの詳細は下記URLを確認いただけると私の説明なんかより100万倍わかりやすいです。

* [Itamae - Infra as Code 現状確認会](https://speakerdeck.com/ryotarai/itamae-infra-as-code-xian-zhuang-que-ren-hui)
* [クックパッドのサーバプロビジョニング事情](http://techlife.cookpad.com/entry/2015/05/12/080000)

Chefから移行して使ってみて非常に良いなぁと思った事をいくつか

* Chefで使ってたレシピがある程度流用出来た
 * `package`,`template`,`link`,`remote_file`,`remote_directory`くらいしか使っていないレシピは割とそのまま持って行けた
 * むしろ`include_recipe`が楽になって助かった

* `itamae`コマンドが叩ければそれだけでOKというシンプルさ
 * リモート実行の際にはsshとsudoが出来ればそれだけOKというシンプルさ、リモートに実行に必要な何かをインストールする必要はない

* ディレクトリ構成に制限がない為、ある程度自分たちの好きな形で管理できる
 * ただこれはよく言われているがある程度ルールを作っておかないとカオスになるので注意が必要
 * 弊社ではitamaeリポジトリWikiの[Best Practice](https://github.com/itamae-kitchen/itamae/wiki/Best-Practice)を参考にしてます

* Chefの下地があれば爆速で理解できる
  * 学習が無駄にはならなかったのがよかった


## 最後に

大規模な環境であればChefServerをたてて、一元管理するのは非常に良いと思います。
ただ弊社のように`chef-solo(chef-zero)`で管理する規模(20台無いくらい)で、
yumでぶち込んで軽くconfig書き換えられるだけでいいんじゃ！な場合は、
お手軽に使えるプロビジョニングツールって感じでおすすめです。

さて、[CYBIRD エンジニア Advent Calendar](http://qiita.com/advent-calendar/2017/cybird)
明日は[@gucchon](https://qiita.com/gucchon)さんの「ゲーム開発をWebViewからUnityに乗り換えて、苦労したこと、良かったこと」です！
社内で一番イケイケのイエスマン。ノーとは言えない男、[@gucchon](https://qiita.com/gucchon)さんの記事楽しみですね。
CSSの拡張メタ言語Lessの&（アンド、アンパサンド）の使い方

ソースコードを読んでいて「& when () {...}」という構文が理解できず「Less アンド」などで検索しましたが、基本的な擬似セレクタの使い方ばかりで「&」の使い方をまとめた記事が無かったので調べました。
CSSに関して初心者のため、内容や用語の間違いなどがありましたらご指摘くださるとありがたいです。

# 使い方

セレクタで使用でき、以下の例のように親セレクタが代入されます。通常のネストはこの例の使い方を短縮した書き方といえます。

```1.less
/* &に親セレクタが代入される */
div {
    color: black;
    & p {
        font-size: 18px;
    }
}
/* この場合は以下のように普通のネストと同じ挙動になる */
div {
    color: black;
    p {
        font-size: 18px;
    }
}

```

```1.css
/* &に親セレクタが代入される */
div {
  color: black;
}
div p {
  font-size: 18px;
}
/* この場合は以下のように普通のネストと同じ挙動になる */
div {
  color: black;
}
div p {
  font-size: 18px;
}
```

擬似セレクタをネストで表現しようとすると間に空白が入ってしまうため、&を使わないと表現できません。classにも使えます。

```2.less
/* 擬似セレクタのネスト*/
a {
    &:link{
        color: black;
    }
}
/* &を使わないと間に空白が入ってしまう */
a {
    :link{
        color: black;
    }
}
/* 単純に代入、展開されるだけなのでclassにも使える */
.search {
    &__input {
        color: black;
    }
    &__button {
        color: red;
    }
}
```
```2.css
/* 擬似セレクタのネスト*/
a:link {
  color: black;
}
/* &を使わないと間に空白が入ってしまう */
a :link {
  color: black;
}
/* 単純に代入、展開されるだけなのでclassにも使える */
.search__input {
  color: black;
}
.search__button {
  color: red;
}
```

僕が困った親セレクタが無い時の挙動ですが、単純にセレクタとしては無視されます。以下のような利用方法があります。

```3.less
/* 親セレクタが無いと無視される */
& {
    p {
        color: black;
    }
}
/* 以下のように複数のスタイルに同条件のGuardを用いるのに使える */
@var: true;
& when (@var = true) {
    button {
        color: black;
    }
    a {
        color: red;
    }
}
/* 上記は以下のようにも書けるが、条件の記述が2個所になってしまう */
button when (@var = true) {
    color: black;
}
a when (@var = true) {
    color: red;
}
```
```3.css
/* 親セレクタが無いと無視される */
p {
  color: black;
}
/* 以下のように複数のスタイルに同条件のGuardを用いるのに使える */
button {
  color: black;
}
a {
  color: red;
}
/* 上記は以下のようにも書けるが、条件の記述が2個所になってしまう */
button {
  color: black;
}
a {
  color: red;
}
```

#親セレクタが複数の場合、&が複数の場合

色々な使いみちがありそうですが、無理に使うとやけどしそうです。

```4.less
/* 親クラスが複数の場合、それぞれ代入される。 */
h1, p {
    div & {
        color: black;
    }
}

/* &は複数利用できる */
a {
    .t&n&k& {
        color: black;
    }
}

/* さらに親セレクタが複数の場合、全組み合わせが作られる */
a, b, c {
    && {
        color: black;
    }
}
```
```4.css
/* 親クラスが複数の場合、それぞれ代入される。 */
div h1,
div p {
  color: black;
}
/* &は複数利用できる */
.tanaka {
  color: black;
}
/* さらに親セレクタが複数の場合、全組み合わせが作られる */
aa,
ab,
ac,
ba,
bb,
bc,
ca,
cb,
cc {
  color: black;
}
```

#参考
- http://less-ja.studiomohawk.com/ - 日本語公式
- http://lesscss.org/ - 英語公式
Angular アプリケーションに ng-bootstrap をインストールする

# ng-bootstrap のインストール

* [Getting started](https://ng-bootstrap.github.io/#/getting-started) に従ってインストール

```
npm install --save @ng-bootstrap/ng-bootstrap
```

* app.module.ts で import 

```ts
import {NgbModule} from '@ng-bootstrap/ng-bootstrap';

@NgModule({
  declarations: [AppComponent, ...],
  imports: [NgbModule.forRoot(), ...],
  bootstrap: [AppComponent]
})
export class AppModule {
}
```

# Angular を最新に

* npm start すると Angular 5 系が必要ということなので 4.4 からアップデート
* 手順は [Angular Update Guide](https://angular-update-guide.firebaseapp.com/) に従う

```bash
npm install @angular/{animations,common,compiler,compiler-cli,core,forms,http,platform-browser,platform-browser-dynamic,platform-server,router}@'^5.0.0' typescript@2.4.2 rxjs@'^5.5.2'
npm install typescript@2.4.2 --save-exact
```

* ついでに angular-cli も 1.5 にアップデート

```bash
npm install @angular/cli@~1.5
```

* codelyzer のバージョンが古くて警告が出る場合は合わせて更新

```bash
npm i codelyzer@~4.0.0
```

# bootstrap のインストール

* ng-bootstrap は bootstrap.css に依存しているのでインストールする

```bash
npm install bootstrap@4.0.0-beta.2
```

* .angular-cli.json に bootstrap.css を読み込む設定を追加

```json
      "styles": [
        "../node_modules/bootstrap/dist/css/bootstrap.css", // この行を追加
        "styles.css"
      ],
```

* [example のテンプレート](https://getbootstrap.com/docs/4.0/examples/starter-template/#)を適用して動作確認

```html:app.component.html
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
  <a class="navbar-brand" routerLink="">TOP</a>

  <div class="collapse navbar-collapse" id="navbarsExampleDefault">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item active">
        <a routerLink="detail">DETAIL</a>
      </li>
    </ul>
  </div>
</nav>

<main role="main" class="container">
  <router-outlet></router-outlet>
</main>
```

```css:style.css
body {
  padding-top: 5rem;
}
.starter-template {
  padding: 3rem 1.5rem;
  text-align: center;
}
```
Pugの記述サンプル

## はじめに
pugでの「ちょっとだけ」便利な記述などを書いているだけなので、
基本的な部分については触れていません。

今回作った[デモ](https://sengokukun.github.io/pug_test/)

## each

```pug:index.pug
	-
     const test = [
      {
        "url": 'https://sample01',
        "text": 'いっこめ',
        "class":'class01'
      },
      {
        "url": 'https://sample02',
        "text": 'にこめ',
        "class":'class02'
      },
      {
        "url": 'https://sample03',
        "text": 'さんこめ',
        "class":'class03'
      },
    ];
     
    ul
      each item in test
        li
          a(href=`${item.url}`)
            span
              | !{item.text}
            span(class=`${item.class}`)
              | pug

```

### each結果
```index.html
    <ul>
      <li>
      	 <a href="https://sample01">
      	  <span>いっこめ</span>
      	  <span class="class01">pug</span>
      	 </a>
      </li>
      <li>
      	 <a href="https://sample02">
      	  <span>にこめ</span>
      	  <span class="class02">pug</span>
      	</a>
      </li>
      <li>
      	<a href="https://sample03">
      	 <span>さんこめ</span>
      	 <span class="class03">pug</span>
      	</a>
      </li>
    </ul>
```

ul liなどでリストや同じ要素を連続して使うときなどに。
クラス名やurlを変えたりする際は、上記の様に呼び出します。(他にも方法はあると思いますが。)

## for
```pug:index.pug
   ul
     - for (let i = 0; i < 3; i++)
       li
         h2(class="class" + `${i}`)
           | たいとる
         a(href="#") ぼたん
```

### for結果
```index.html
    <ul>
      <li>
        <h2 class="class0">たいとる</h2>
        <a href="#">ぼたん</a>
      </li>
      <li>
        <h2 class="class1">たいとる</h2>
        <a href="#">ぼたん</a>
      </li>
      <li>
        <h2 class="class2">たいとる</h2>
        <a href="#">ぼたん</a>
      </li>
    </ul>
```

こちらもリストなどを作る時に便利かも。
画像を連続して出す時(picture1.pngとかで管理していたら)

```
img(src="picture" + `${i}` + ".png")
```
とかでも使えそう。

## 変数
```pug:index.pug
   - const title = "たいとるだよ";
    
   h1
     | !{title}   
```

### 変数結果
```index.html
<h1>たいとるだよ</h1>
```



## まとめ
ベストプラクティスではないとは思いますが、今後も改良して使い勉強していこうと思います。
今度はpug(テンプレートエンジン)の醍醐味でもあるテンプレート作成をしよーかなと。

[ソースコード](https://github.com/sengokukun/pug_test)

## 参考
- [軽量なマークアップ言語 Jade 入門 からの Gulp でコンパイルまで - Gulp で作る Web フロントエンド開発環境 #5](https://tech.recruit-mp.co.jp/front-end/post-2581/)
- [【Pug】ゴリラでもわかるJade改めPug入門](https://blog.mismithportfolio.com/web/20160326pugbegin)
テストしやすいクレジットカード決済をStripe+RSpecで作る

クレジットカード決済に関わる開発って神経を使いますよね。なるべく精神衛生を保ちながら開発を続けるためには、書ける限りテストコードは書きたいところです。

2016年10月に日本でも正式リリースしたStripeは、モダンな感じのインターフェイスのAPIで、決済機能の開発コストをだいぶ下げてくれます。今回はStripeとそのRuby用クライアントライブラリである[stripe-ruby](https://github.com/stripe/stripe-ruby)、そしてRSpecを用いて、テストのしやすいクレジットカード決済の開発を模索します。

# 方法1) Stripeのテスト環境にそのままアクセスする
- この上なくシンプルで最も確実
- 当然ながらRSpecを走らせるたびAPIアクセスが行われるので、何もかもこれでやると実行にべらぼうに時間がかかる

# 方法2) RSpecでMock/Stubを作る
- 作るのが面倒な場合もある。例えばStripeからWebhookで送られてくるイベントとかどうしよう

# 方法3) stripe-mockを使う
- [stripe-mock](https://github.com/stripe/stripe-mock)は、Stripeが公式に提供しているMock用のHTTPサーバ
- 返ってくるデータは完全に固定。そこが後述のstripe-ruby-mockとの違い。

### stripe-mockのセットアップについての補足
基本的に[README](https://github.com/stripe/stripe-mock/blob/master/README.md)にある通りbrew installするだけですが、ライブラリから呼び出すAPIの向き先をこのMockサーバにしたい場合、Ruby版ならばさらに以下の設定が必要。

```ruby
Stripe.api_base = 'http://localhost:12111'
```
ホスト名、ポートはstripe-mockの起動設定によって変えてください。

# 方法4) stripe-ruby-mockを使う

- [stripe-ruby-mock](https://github.com/rebelidealist/stripe-ruby-mock)はサードパーティ製のMockライブラリ
- stripe-rubyからHTTPリクエストをする時の処理に割り込んで、Mockに処理をさせるようにしている。
- WebhookもMock化できる(正確には、Webhookでリクエストされてくるイベントのオブジェクトをそれっぽく生成してくれる)
- 先述のstripe-mockと異なり、POSTされてきたデータをメモリ上に保持しており、リクエストに応じて動的に変化してくれる

### 例

```ruby
# 例えばStripeでCustomerオブジェクトを作ってそのIDをDB上の会員IDと紐付けるメソッドがあるとする
describe PaidService do
  let(:stripe_helper) { StripeMock.create_test_helper } # Mock用のtoken作るために使う必要ある
  before { StripeMock.start } # ここで、オンメモリのDBが作成される
  after { StripeMock.stop } # ここでDBのデータは破棄される

  let(:user) { User.create }
  let(:paid_service) { PaidService.new }

  describe '#register' do
    # ここでStripeにアクセスしてる
    subject { paid_service.register(user, stripe_helper.generate_card_token) }

    it { is_expected.to_not be_nil }
  end
end
```

### 便利なんだけど、少し苦労するところ

- 無効なカード情報(例えば期限切れ)を与えてエラーを発生させたい時、Stripe提供のエラー用テストトークンを用いる事ができない。[StripeMock.prepare_card_error](https://github.com/rebelidealist/stripe-ruby-mock#mocking-card-errors)を用いなければならない。FixtureやFactoryとの相性が少し悪いかもしれない。
- 意外としっかりしていて(?)、内部でデータの整合性をある程度チェックしている。例えば、Plan IDを用いてSubscriptionを作りたいとき、このMockライブラリのオンメモリのDBに登録されていないPlan IDを指定すると、エラーになる。ありがたい事かもしれないけれど、このDBのためのFixtureが欲しくなってくる。
- でも自分でMock作ったりする手間は軽減される。特にWebhook周り。

# 方法5) fake_stripeを使う
- [fake_stripe](https://github.com/thoughtbot/fake_stripe/)も、サードパーティ製のMockライブラリ。やや方法は異なるが、stripe-rubyからのHTTPリクエストに割り込んでMockの値を返すのはstripe-ruby-mockと同じ
- Stripe.jsから呼び出されるJS用のAPIのMockまで用意してあるのが特徴。ただし、現時点(2017年12月)で用意されているのは、v1, v2まで。v3はまだの模様。
- stripe-ruby-mockと異なり、返されるレスポンスはほぼ固定。ただ、create系のAPIが呼ばれると、FakeStripeのクラスで保持しているカウントが増える。APIが実際にコールされた事のテストには便利なのかもしれない。以下は、FakeStripeのSpecにあった例

```ruby
describe "POST /v1/customers" do
  it "increments the customer counter" do
    expect do
      Stripe::Customer.create
    end.to change(FakeStripe, :customer_count).by(1)
  end
end
```

# 結局、何がおすすめか？
人によって好みもあるかと思いますが、自分の場合、APIにリクエストするまでもない単体のテストでMockを使いたい、という場合、今のところstripe-ruby-mockを用いています。先述の通り、使い方に少し癖があるところもありますが、一度セットアップさえしてしまえば楽です。特にWebhook周りが助かります。
Stripeはこうしたサードパーティのライブラリも充実しているのが魅力ですね。Stripe自体に関しても、ドキュメントも充実していてAPIも使いやすく、カスタマイズ自由がきくのでおすすめですよ。皆さんも使ってみてください（決してStripeさんの回し者じゃないです)
.htaccessで特定のファイル（拡張子）に有効期限をつける

GoogleのPageSpeed Insightで画像やファイルに有効期限をつけつけましょう的なことを言われた時に対応した内容をメモ。
.htaccessにファイルの拡張子で判断して有効期限を設定します。（max-ageの数値は秒：2592000秒=30日）

```text
<Files ~ "\.(gif|jpe?g|png|svg|ico|otf|ttf|eot|woff)$">
Header set Cache-Control "max-age=2592000, public"
</Files>

<Files ~ "\.(css|js|html|gz)$">
Header set Cache-Control "max-age=86400, public"
</Files>
```
Android Studioのエラー備忘録


# Error:Cannot get property 'cd' on null object

とあるソースをビルドすると以下のエラーメッセージが出てきた。

```
Error:Cannot get property 'cd' on null object

Consult IDE log for more details (Help | Show Log)
```

`cd`と言う null オブジェクトがあると言われている。 

## 原因

原因は凡ミス。
`cd`を削除する事で修正

```gradle
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.0.0'
    compile 'com.google.android.gms:play-services:9.8.0'
    testCompile 'junit:junit:4.12'
}cd		// ← ここ
```



# DexArchiveMergerException: Unable to merge dex

とあるソースをビルドすると以下のエラーメッセージが出てきた。

```
Error:Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForDebug'.
> java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex
```

よくわからなかったので詳細を得る為にコンパイルオプションに--stacktrace を付けてビルドし直す。
コンパイルオプションは `File -> Setting -> Build, Execution, Deployment -> Compire`にある`Command-line Options`に記載する。

![compiler-options.PNG](https://qiita-image-store.s3.amazonaws.com/0/112253/cfe60da6-a642-4684-efae-91fc581509e7.png)


以下のエラーに変わった。

```
Information:Gradle tasks [:app:assembleDebug]
Error:java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex
Error:java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex
Error:java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex
Error:com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex
Error:com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
```

## 原因

原因は`メソッド数が65k(65536)を超えた為に起きたエラー`の様だ。
`DexIndexOverflowException`をググると以下の情報が出てきたので参考にする。

http://hanyou.mss-g.mobi/wiki/doku.php?id=dexindexoverflowexception_%E9%80%9A%E7%A7%B065k%E5%95%8F%E9%A1%8C_%E3%81%AE%E5%AF%BE%E5%BF%9C


いくつか解決方法があるようだが build.gradle(Module: app) の `android {}` に `multiDexEnabled true` を追加する事で解決した。

```app/build.gradle
android {
	
	// Enabling multidex support.
	multiDexEnabled true
}
```


# Error:Minimum supported Gradle version is...

とあるソースをビルドすると以下のエラーメッセージが出てきた。

```
Error:Minimum supported Gradle version is 4.1. Current version is 2.14.1. If using the gradle wrapper, 
try editing the distributionUrl in C:\AndroidApp\gradle\wrapper\gradle-wrapper.properties to gradle-4.1-all.zip

Consult IDE log for more details (Help | Show Log)
```


gradle-wrapper.properties(gradle Version) の distributionUrl を以下のように変更する。

変更前
`distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip`

変更後
`distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip`


変更後にProjectを再起動する。