OmniAICreator/Qiita-1.07M huggingface dataset:
Cognos で表に行・列を追加する

#概要
最近質問されたので投稿しておきます。
Cognos BI & Analytics では、レポートを作成する時のオブジェクトの配置決めの際、「表」をオブジェクトとして置いて、区割りをした「セル」のサイズを指定して、セルの中に実際のグラフを置いて、という事をやっていきます。
下図は、2行 x 2列の表を置いて、それぞれのセルにグラフを一個ずつ配置したものですが、例えばレポートを実行してみると、グラフ同時がくっつき過ぎなので、赤線の箇所に1行追加してスペースを作りたい、みたいな場面は良くあります。
![001.JPG](https://qiita-image-store.s3.amazonaws.com/0/147246/c8c0b8fa-3a41-3a47-3a4b-e15ec1f5fe3a.jpeg)

知ってる人はこの先は読まなくて良いです。知らずに表を作り直している方、そんな方はご参照下さい。

#Cognos BI のReport Aurhotingでの手順
「セル」を選択した状態で、上部黒帯の「表」メニューから、「挿入」、「行を下に挿入」と選択します。
![002.JPG](https://qiita-image-store.s3.amazonaws.com/0/147246/63f647fe-b2d4-49c3-1ac9-b1954d454f5a.jpeg)

追加したい行の数を指定しOK。
![003.JPG](https://qiita-image-store.s3.amazonaws.com/0/147246/ff36d498-12ab-24a3-dc4c-0a28d5d3b36e.jpeg)

肌色にハイライトされている箇所が、新規に追加された行です。
![004.JPG](https://qiita-image-store.s3.amazonaws.com/0/147246/1f76e4af-1eb0-8e1e-a0d2-70576a4ec65a.jpeg)

#Cognos Analytics のレポートでの手順

セルを選択し、表示される画像の様なメニューの「・・・」から、「挿入」、「列を右側に挿入」です。
※今回は列を追加してみました。
![005.JPG](https://qiita-image-store.s3.amazonaws.com/0/147246/3897ad4a-4ee2-792d-f889-5053809d7c0b.jpeg)

列数を指定してOK。
![007.JPG](https://qiita-image-store.s3.amazonaws.com/0/147246/03f7c765-4fcf-751a-af5a-0d0abdae12ba.jpeg)

青色にハイライトされている箇所が、新規に追加された列です。
![008.JPG](https://qiita-image-store.s3.amazonaws.com/0/147246/d211e91f-4130-144e-eecf-81c079982382.jpeg)

以上です。
知らないとレポート作成がひどく苦労しますので。
動的計画法の取り込み方に関する質問

# 動的計画法とは

https://ja.wikipedia.org/wiki/%E5%8B%95%E7%9A%84%E8%A8%88%E7%94%BB%E6%B3%95

# 解きたい問題

1本の水ようかんがある。

3つの切れ目が入っており、最大で4分割できる。

4分割した時の長さは順番にL_1、L_2、L_3、L_4(1<=L_i<=10, 1<=i<=4)で与えられる。

分割した後の長さがなるべく均等になるようにした時の、最大の長さと最小の長さの差を出力せよ。

ただし、最低1箇所は切るものとする

(日本情報オリンピック2017 予選問4 をベースにしたもの)

# 入力パターン

L_1～L_4 が

9
4
6
7

と与えられるとき。

(※) 総当たりで簡単にいけます(2番目の切れ目を切ればOK)が、動的計画法というものを理解したい点をご理解ください

# 現状の理解

動的計画法は、

- 前回の計算結果を、今回の計算に活かす。これを最終段階まで繰り返す

というのが、現状の私なりの理解(不足していると思うので、アドバイス大歓迎です)。

# 試したアプローチ

とりあえず、ゴールの一歩手前である

9
4
6

の段階での最適解を、次に活かすアプローチを考えた。

この場合は、

- 1番目の切れ目に切れば最小9、最大10。-> この時点での最適解！
- 2番目の切れ目を切れば最小6、最大13。
- 両方切れば最小4、最大9。
- 全部切らなければ最小19、最大19(ただし、最後で切ると最適でないのが自明なので除外)

筆者「なるほど、1番目の切れ目で切った結果を使いまわせばよいのか」。

で、最後のL_4

7

を考える。

L_3までの最適解にしたがって計算すると

- 3番目の切れ目を切れば最小7、最大10
- 3番目の切れ目を切らなければ最小9、最大17

差は3となる。

でも、これが答えかというと違ってて、L_3まででは最適でないケースだった

- 2番目の切れ目を切れば最小6、最大13。

の時に、

- 3番目の切れ目を切れば最小6、最大13
- 3番目の切れ目を切らなければ最小13、最大13

と、差が0となるケースが出る。途中段階の最適解を使いまわせないことになる。

# 質問事項

まとめると、

- 途中経過でずっと最適解と思っていたものが、以降の段階で覆される

というケースを、動的計画法の考え方でどう落とし込めばいいかがわからない。どう理解すればいいのでしょうか？

今回は4個のケースだったが、引用元の問題では最大50程度になる。

L_iの大きさも、最大1000程度までになる。

そうすると、49番目までずっと正解の切り方だったものが、最後の50番目で覆されるパターンも出てくる。

例えば、

1
:
(1 が 49個)
:
1
49

という感じのもの。

　・ 49番目まで: 全ての切れ目で切る、が最適解
　・ 最終段階: 最後の切れ目のみ切る、に最適解が変わる

これが理解できれば、動的計画法という得体の知れない魔物の攻略に、一歩近づくと思うのだが...


皆さんの知恵・経験をお貸しいただければと思います。
git-sync (fish version)

https://qiita.com/masarakki/items/27f2cb456b4801ccb31b を読んで普段[fish](https://fishshell.com/)を使っているから、[fish](https://fishshell.com/)で書き直してみた。

https://gist.github.com/py0n/fd07057cc1d3f12e12641ceb7224de0c

```shell:git-sync.fish
function git-sync
	# setup
	type --no-function --quiet git-sync
	if [ $status -ne 0 ]
		command mkdir -p $HOME/.local/bin
		echo -e "#!/bin/sh\nfish -c git-sync" > $HOME/.local/bin/git-sync
		command chmod +x $HOME/.local/bin/git-sync
	end

	# git-sync (fish version)
	#
	# cf. https://qiita.com/masarakki/items/27f2cb456b4801ccb31b
	command git fetch --all --prune

	set -l modifieds (command git status --porcelain --untracked-files=no | string length)

	if count $modifieds >/dev/null 2>&1
		command git stash
	end

	set -l current (command git branch | string match --entire --regex '^\* ' | string split ' ')[2]

	command git checkout master
	command git pull --rebase

	for b in (command git branch --no-color --merged | string match --entire --invert --regex '^\* ' | string trim)
		command git branch -d $b
	end

	for b in (command git branch --no-color -vv | string match --entire --regex '\[[A-Za-z0-9_\/\.\-]*: gone\]' | string trim)
		command git branch -D  (string split --max 1 ' ' $b)[1]
	end


	if command git checkout $current
		count $modifieds >/dev/null 2>&1; and command git stash pop
	else
		count $modifieds >/dev/null 2>&1; and command git stash drop
	end
end
```

最初に `git-sync` を実行すると `$HOME/.local/bin` に `git-sync` を作成する。

```bash:git-sync
#!/bin/sh
fish -c git-sync
```

次からは `git sync` でOK。
[fluentd] buffer pluginの理解

## buffer plugin 概要

公式の翻訳しながら理解を進める

## buffer の構造

![fluentd-v0.14-plugin-api-overview.png](https://qiita-image-store.s3.amazonaws.com/0/47896/7a23d18a-b00f-5c0b-d61a-83353d2a6c13.png)

<img width="257" alt=" 2018-04-27 17.31.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/47896/afc4d589-61e8-7692-e796-5ce01794ff3a.png">


buffer は Chunk の集合  
Chunk は 1 つの blob に連結されたイベントの集合  
それぞれの Chunk は file か memory で管理される

buffer は Chunk を 2 つの場所に分けて管理

* stage と呼ばれる Chunk を入力ソース(Event)で埋めていく場所
* queue と呼ばれる送信前のチャンクが待機している場所

新しく作成された全てのチャンクは
stage に入れられ、時間内に queue に移動される (その後転送される)

## retry の振る舞い

受信側が何かしらのエラーで届けられなくなっても  
送信側で障害を正常に処理するメカニズムが入っている

デフォルトでリトライの試行間隔を指数的に増やしていく
(最初の待機時間が 1 の場合の例)

```
1 2   4       8               16
x-x---x-------x---------------x-------------------------
│ │   │       │               └─  4th retry (wait = 8s)
│ │   │       └─────────────────  3th retry (wait = 4s)
│ │   └─────────────────────────  2th retry (wait = 2s)
│ └─────────────────────────────  1th retry (wait = 1s)
└───────────────────────────────  FAIL
```

fluentd は 上記アルゴリズムを調整している点がある

**待機間隔の分散**
計算された秒数に`0.875 ~ 1.125`をランダムにかける  
`retry_randomize` を false にすれば無効になる

**最大待機時間の設定**
例えば`retry_max_interval`を`5s`にした場合  
上記の例で 8s 待つことはなくなる

そもそも指数関数的なリトライ処理をさせたくない場合は  
`retry_type`を`periodic`にする

## リトライの終了判定(書き込み成功以外)

デフォルトで次の条件で再試行のループを抜ける

* `retry_max_times`に達した。(default: none なので  無制限)
* 最初の再試行から経過した時間が`retry_timeout`に達した(default: 72h)

これらのイベントが発生した場合、出力 queue 内の全てのチャンクは破棄されてしまう  
 破棄したくない場合は、`retry_forever`を有効にする

## 参考

公式
https://docs.fluentd.org/v1.0/articles/buffer-plugin-overview

buffer option 詳細
https://docs.fluentd.org/v1.0/articles/buffer-section#retries-parameters

forward protocol v1
https://github.com/fluent/fluentd/wiki/Forward-Protocol-Specification-v1
[fluentd] output plugin の理解

## output plugin について

公式みながら翻訳  
設定値については省略

### mode

buffering と flush に関する 3 つの mode がある

* Non-Buffered mode

  * data を buffering せず、結果を即時書き込みしない

* Synchronous Buffered mode

  * buffered Chunk を stage と queue で管理する

* Asynchronous Buffered mode
  * buffered Chunk を stage と queue で管理するが、Chunk を後でコミットする

buffer セクションが指定しない場合、fluentd が適切な mode を選択する  
buffer をサポートしない output plugin で設定すると  
fluentd がエラーを出力する

`flush_mode` は

* default
* lazy
* interval
* immediate

default の挙動はソース見てください
[src](https://github.com/fluent/fluentd/blob/master/lib/fluent/plugin/output.rb)
一応 default でも flush_interval 設定すれば反映される


## 参考
https://docs.fluentd.org/v1.0/articles/output-plugin-overview
え、まだRaspberry Piに繋ぎに行くのにIPアドレスつかってんの？ｗｗｗ

# raspberrypi.localというホスト名

macOSやWindowsからなら、


```shell-session
ssh pi@raspberrypi.local
```

として、いちいちIPアドレスなんか指定せずに接続できる。

新しめのraspbianだとたぶんavahiとか勝手に入っている気がする。

違っていたらごめんなさい。

# 関連記事

- [Raspberry Piの温度をgRPCを使ってElectronで作ったデスクトップマスコットに表示させた](https://abrakatabura.hatenablog.com/entry/2018/06/16/070747)
- [goroutineを使って高速にLAN内の*.localなホスト名の一覧を取得するツールを作った](https://abrakatabura.hatenablog.com/entry/2018/07/04/213245)
Windows 10 Fall Creators Update にアップデートしたら vagrant up で仮想マシンが起動しない場合の対処方法

ある日突然、 仮想マシンを起動しようと `vagrant up` を実行したら、エラーが発生して仮想マシンが起動しなくなってしまいました。

エラーメッセージから下記にたどり着きました。（エラーメッセージは失念・・。）
下記と結論は同じですが、解決方法が少々異なるため記録を残しておきます。

- [[vagrant][windows10]Windows + VirtualBox (+ vagrant) でvagrant upできなくなったとき - Qiita](https://qiita.com/VTRyo/items/1b7a439844f93fd3b033)

## 結論

Vagrant, VirtualBox をアップデートし、 Vagrant のプラグインを再インストールして解決しました。

## 環境

- Windows 10 Fall Creators Update (1709)
- Vagrant 1.9.5
- VirtualBox 5.1.22

## 対処方法

以降、順を追って記載します。

### Vagrant アップデート

Windows のパッケージマネージャ chocolatey 経由で Vagrant をインストールしていたため、 `choco upgrade vagrant` コマンドで Vagrant をアップデートします。

アップデート前後での Vagrant のバージョンの変化です。

- before: 1.9.5
- after: 2.0.4

### VirtualBox アップデート

Vagrant と同じく chocolatey 経由で `choco upgrade virtualbox` コマンドで VirtualBox をアップデートします。

アップデート前後での VirtualBox のバージョンの変化です。

- before: 5.1.22
- after: 5.2.8

### Vagrant プラグインの再インストール

Vagrant, VirtualBox のアップデート完了後、 `vagrant up` を実行したところ、次は下記エラーが発生してしまいました。

```powershell
> vagrant up
Vagrant failed to initialize at a very early stage:

The plugins failed to initialize correctly. This may be due to manual
modifications made within the Vagrant home directory. Vagrant can
attempt to automatically correct this issue by running:

  vagrant plugin repair

If Vagrant was recently updated, this error may be due to incompatible
versions of dependencies. To fix this problem please remove and re-install
all plugins. Vagrant can attempt to do this automatically by running:

  vagrant plugin expunge --reinstall

Or you may want to try updating the installed plugins to their latest
versions:

  vagrant plugin update

Error message given during initialization: Unable to resolve dependency: user requested 'sahara (> 0)'
```

選択肢は下記3点あるようです。

1. vagrant plugin repair
2. vagrant plugin expunge --reinstall
3. vagrant plugin update

今回は、選択肢2に Vagrant を最近アップデートした場合・・とあったので、選択肢2のコマンドを実行し、 Vagrant のプラグインを再インストールしました。

```powershell
> vagrant plugin expunge --reinstall

This command permanently deletes all currently installed user plugins. It
should only be used when a repair command is unable to properly fix the
system.

Continue? [N]:

Vagrant expunge has been declined. Skipping removal of plugins.

Vagrant will now attempt to reinstall user plugins that were removed.
Installing the 'sahara' plugin. This can take a few minutes...
Fetching: open4-1.3.4.gem (100%)
Fetching: Platform-0.4.0.gem (100%)
Fetching: popen4-0.1.2.gem (100%)
Fetching: sahara-0.0.17.gem (100%)
Fetching: micromachine-2.0.0.gem (100%)
Fetching: vagrant-vbguest-0.15.1.gem (100%)
Bundler, the underlying system Vagrant uses to install plugins,
reported an error. The error is shown below. These errors are usually
caused by misconfigured plugin installations or transient network
issues. The error from Bundler is:

Unable to resolve dependency: user requested 'vagrant-vbguest (= 0.14.2)'
```

最終的に失敗しているようなメッセージですが、おもむろに `vagrant up` を実行したところ、無事に仮想マシンが起動しました。

## 参考文献

- [[vagrant][windows10]Windows + VirtualBox (+ vagrant) でvagrant upできなくなったとき - Qiita](https://qiita.com/VTRyo/items/1b7a439844f93fd3b033)
ファイルやデータの中身が完全一致することを確認する

## MDハッシュ値とは

* ファイルやデータを数学的に圧縮したもの
* 値は32個の16進数（128bit）で構成される文字列
* ファイルの偽造防止などに使用
* ファイルやデータの中身が一つでも違うと全く違ったハッシュ値となる。
* ファイル名が違っても内容が同じであればハッシュ値は同じになる。

[以下参照]
https://eng-entrance.com/linux-command-md5sum#MD

## md5コマンド

このコマンドを使うと、ファイルの中身が完全一致しているかどうかをファイルの中身を見ずに確認することができる。

### ファイルの中身が違うとき

```
$ md5 Gemfile
MD5 (Gemfile) = b891a1e1dbe819f00667ec6fca6a2d27
$ md5 Gemfile.lock
MD5 (Gemfile.lock) = e57e685955d52d632cdb94d7a325ebc9
```

MDハッシュ値が一致しない

### ファイルの中身が同じとき

```
$ md5 Gemfile
MD5 (Gemfile) = b891a1e1dbe819f00667ec6fca6a2d27
$ md5 Gemfile
MD5 (Gemfile) = b891a1e1dbe819f00667ec6fca6a2d27
```

MDハッシュ値が一致する


## 参考文献

https://eng-entrance.com/linux-command-md5sum#MD
ガウス過程入門 : ガウス分布からガウス過程へ

ガウス過程はたいてい回帰モデルの拡張として導入されることが多いです。しかし、その場合回帰モデルのベイズ推定を理解してからでないと、ガウス過程がなんなのかよく分かりません。この記事では、とりあえずガウス過程の定義とPythonコードの例だけをガウス分布から順を追って説明します。

## ガウス分布
まず、確率分布のひとつであるガウス分布の確率密度関数は、平均$\mu$と分散$\sigma^2$をパラメーターとして次のように定義されます。
$$
p(x) := \frac{1}{ \sqrt{2\pi \sigma^2} } \exp(-\frac{(x - \mu)^2}{2\sigma^2} ) \sim \mathcal{N}(\mu, \sigma^2)
$$

平均$\mu=0$、分散$\sigma^2 = 1$のガウス分布の確率密度関数と標本をプロットするコードは次のように書けます。

```python
import numpy as np
import matplotlib.pyplot as plt
import seaborn
from scipy.stats import norm

# 平均
mu = 0
# 標準偏差 ( = 分散^{1/2} )
sigma = 1

x = np.linspace(-5, 5)
# 確率密度関数
p = norm.pdf(x, mu, sigma)
plt.plot(x, p)
# 標本
s = np.random.normal(mu, sigma, 500)
count, bins, ignored = plt.hist(s, normed=True)
```
![1.png](https://qiita-image-store.s3.amazonaws.com/0/35175/90bf1317-0f45-f615-37a1-6782f07d3880.png)


## 多次元ガウス分布
次に、多次元ガウス分布の確率密度関数は$N$次元の平均ベクトルの$\mu$と$N\times N$の分散共分散行列$\Sigma$をパラメーターとして、次のように定義されます。

$$
p(x) := \frac{1}{\sqrt{ (2\pi)^n |\Sigma| }} \exp(-\frac{1}{2} (x-\mu)^T \Sigma^{-1} (x-\mu)) \sim \mathcal{N}(\mu,\Sigma)
$$

平均$\mu = (0, 0)$、分散共分散行列

```math
\Sigma = \begin{pmatrix} 1& -0.5\\ -0.5  & 1.5\end{pmatrix}
```

の2次元ガウス分布の確率密度関数と標本をプロットするコードは次のように書けます。scipy、numpyを使えば関数を呼ぶだけです。

```python
from scipy.stats import multivariate_normal

# 2次元のメッシュの座標とその座標での値をしまう3次元の変数を用意
N = 60
X = np.linspace(-4, 4, N)
Y = np.linspace(-4, 4, N)
X, Y = np.meshgrid(X, Y)
pos = np.empty(X.shape + (2,))
pos[:, :, 0] = X
pos[:, :, 1] = Y

# 平均
mu_multi = np.array([0., 0.])
#　分散共分散行列
Sigma_multi = np.array([[ 1. , -0.5], [-0.5,  1.5]])

# 確率密度関数
F = multivariate_normal(mu_multi, Sigma_multi)
p_multi = F.pdf(pos)
cset = plt.contourf(X, Y, p_multi )

# 標本
s_multi = np.random.multivariate_normal(mu_multi, Sigma_multi, 100)
plt.scatter(s_multi[:,0], s_multi[:,1])
```

![2.png](https://qiita-image-store.s3.amazonaws.com/0/35175/380e3a14-f844-8e78-5af6-3327ec38e99c.png)

## ガウス過程
ガウス過程は、無限次元のガウス分布と考えることができます。

任意の時刻の集合$t = (t_1, t_2, \cdots, t_k)$に対して、関数$f(t)$が平均$\mu=m(t)$、分散共分散行列$\Sigma = K(t,t)$の$k$次元ガウス分布に従うとき、すなわち、$f(t) \sim N( m(t), K(t,t) )$となるとき、$f(t)$をガウス過程と呼びます。また、分散共分散行列の要素$k(t_i, t_j)  = (K(t,t))_{ij}$をカーネル関数と呼びます。

平均を0ベクトル、
$$
m(t) = (0, \cdots, 0)
$$

カーネル関数をパラメーター$\sigma, l$をもつ
$$
k(t_i, t_j) = \sigma^2 \exp (-\frac{1}{2l^2} (t_i-t_j)^2)
$$
としたときの(このカーネル関数はsquared exponential  カーネルと呼ばれます)、ガウス過程のサンプル経路をプロットするコードは次のようになります。

ここでポイントは、カーネル関数が時刻の距離についての指数関数になっているので、定性的には微小時間離れた2点の相関係数はほぼ1になり、このカーネル関数を使ったガウス過程はなめらかになります。

```python
t = np.linspace(0, 10)
t = np.reshape(t, (1,t.size))

# カーネル関数を成分にもつ行列
def K(t):
    sigma = 1
    l = 1
    rows = np.repeat(t, t.size, axis=0)
    cols = np.repeat(t.T, t.size, axis=1)
    mat = cols-rows
    return sigma**2  * np.exp(- np.multiply(mat , mat) / (2 * l **2))

Sigma = K(t)
mu = np.zeros(t.size)
s_gp = np.random.multivariate_normal(mu, Sigma)
plt.plot(t[0,:], s_gp)
```

![3.png](https://qiita-image-store.s3.amazonaws.com/0/35175/3e0a2747-eb29-cdb0-ca94-1357d14a49bb.png)

## 参考文献
* http://www.gaussianprocess.org/gpml/chapters/
* https://www.youtube.com/watch?v=BS4Wd5rwNwE
* https://scipython.com/blog/visualizing-the-bivariate-gaussian-distribution/
関数のオーバーライド/オーバーロードの違い


## オーバーライド（override）

親クラスで定義されているメソッドを子クラスで上書きするなど、 **再定義** すること。

## オーバーロード（overload）
同一クラス内で、引数の異なる同一名のメソッドを複数定義すること。
【R】複数要素が1セルに格納されている時のダミー変数の作り方

# 動機
ダミー変数を作りたいけど、dfの一つのカラムにカンマ区切りでデータが入ってしまっていてそのままdummiesパッケージを使うことができなかったので作成しました。

# 実装
該当のデータdfはこんな感じです。
X_name:データ名, X_data:１セルにカンマ区切りで入っているカテゴリ名

```
> df
   X_name        X_data
1  place_A             T
2  place_B         I,C,E
3  place_C         G,O,D
4  place_D         P,O,T
5  place_E         D,O,G
6  place_F         C,A,T
7  place_G   G,U,N,D,A,M
8  place_H             O
9  place_I         I,N,F
10 place_J           A,I
...
16 place_P     U,R,B,A,N
17 place_Q     G,A,R,D,E
18 place_R       H,O,R,N
19 place_S     S,E,I,K,O
20 place_T       F,I,S,H
21 place_U       D,E,C,K
22 place_V           G,L
23 place_W       H,E,L,P
24 place_X           M,E
25 place_Y             S
26 place_Z           O,S
```

このままだとどうにも扱えないので、splitstackshapeパッケージという、一つのセルにデータが格納されているときに剥がしてくれるありがたいパッケージがあるので使います。

```r
library(tidyverse)
library(dummies)
library(splitstackshape)

df.filtered <- df %>% 
  cSplit("X_data", ",", direction = "long") # ,区切りのデータを剥がして縦に格納
```

処理後のデータはこんな感じです。

```
> df.filtered
     X_name X_data
 1: place_A      T
 2: place_B      I
 3: place_B      C
 4: place_B      E
 5: place_C      G
 6: place_C      O
 7: place_C      D
 8: place_D      P
 9: place_D      O
10: place_D      T
...
74: place_V      G
75: place_V      L
76: place_W      H
77: place_W      E
78: place_W      L
79: place_W      P
80: place_X      M
81: place_X      E
82: place_Y      S
83: place_Z      O
84: place_Z      S
```
このdf.filteredをdummiesパッケージを利用してダミー変数にします。そしてそのダミー変数データフレームをX_dataに対してグルーピングし、足し合わせることで欲しい結果を得ることができます。

```r
df.dummy <- df.filtered %>%
  select(c('X_data')) %>% 
  dummy.data.frame() %>% # ダミー変数を作成
  data.frame(X_name = df.filtered$X_name, .) %>% 
  group_by(X_name) %>% #　X_nameでグルーピング
  summarise_each(funs(sum)) #それぞれのcolumnに対してsumする
```
# 生成物

```
df.dummy
# A tibble: 26 x 22
   X_name  X_data.A X_data.B X_data.C X_data.D X_data.E X_data.F X_data.G X_data.H X_data.I
   <fct>      <int>    <int>    <int>    <int>    <int>    <int>    <int>    <int>    <int>
 1 place_A        0        0        0        0        0        0        0        0        0
 2 place_B        0        0        1        0        1        0        0        0        1
 3 place_C        0        0        0        1        0        0        1        0        0
 4 place_D        0        0        0        0        0        0        0        0        0
 5 place_E        0        0        0        1        0        0        1        0        0
 6 place_F        1        0        1        0        0        0        0        0        0
 7 place_G        1        0        0        1        0        0        1        0        0
 8 place_H        0        0        0        0        0        0        0        0        0
 9 place_I        0        0        0        0        0        1        0        0        1
10 place_J        1        0        0        0        0        0        0        0        1
```

# おわりに
もっとマシな実装があったら教えてください。
WindowsでRuby on Rails

# WindowsでRuby on Rails
WindowsでRuby on Railsを使う方法は、ローカルにインストールする方法と、PaizaCloudなどのクラウドIDEを使う方法があります。

業務でバリバリ開発する場合などはローカルでインストールする方がいいですが、環境設定などが必要になりますので、まずはクラウドIDEを利用することもできます。

# WindowsでRuby on Rails(クラウドIDE編)

[PaizaCloud](https://paiza.cloud/ja/)のサイトを開きます。

アカウントを作成してログインし、サーバを作成します。サーバ作成時に、"MySQL"を指定しておくといいです。

以上です・・・

PaizaCloudの画面の左側にアプリケーション一覧が開きますので、ターミナルでコマンドを入れて見ます。

```
$ rails new myapp
$ cd myapp
$ rails server
```

画面左側に3000番のアイコンがでてくるので、クリックすると表示されます。

PaizaCloudを使って、WindowsでRuby on Railsを開発するには、以下の記事なども参考になります。

https://paiza.hatenablog.com/entry/paizacloud_ruby_on_rails/2017/12/14

# WindowsでRuby on Rails(ローカルインストール編)

WindowsのローカルでRuby on Railsを使う場合、まずはRubyInstallerを使ってWindowsにRubyをインストールします。

[RubyInstallerのサイト](https://rubyinstaller.org/downloads/)からWindows用のRubyをダウンロードします。

右矢印のある推奨バージョンがいいと思います。

次に、[Windows版SQLite](http://sqlite.org/download.html)をダウンロード、インストールします。

そして、gemコマンドで、WindowsにRuby on Railsをインストールします。

```
$ gem install rails
```

以上で完了です。
フォントサイズ変更jsを作ってみたメモ

#前提条件
- 拡大ボタンをクリックすると文字サイズが大きくなる。
- 拡大は5回行える。
- 標準ボタンをクリックすると最小サイズになる。
- 標準ボタンをクリック時と5段階目の時に拡大ボタンをクリックするとアラートが表示される。
- Cookieの保存は「[cookies.js](https://developer.mozilla.org/ja/docs/Web/API/Document/cookie/Simple_document.cookie_framework)」を使用

#ボタン作成
##HTML
```html
<ul>
  <li><button type="button" id="js-fs-normal">標準</button></li>
  <li><button type="button" id="js-fs-large">拡大</button></li>
</ul>
```

##CSS
```css
button {
  font-size: 100%;
}
.is-fs-m {
  font-size: 120%;
}
.is-fs-l {
  font-size: 140%;
}
.is-fs-xl {
  font-size: 160%;
}
.is-fs-xxl {
  font-size: 180%;
}
.is-fs-xxxl {
  font-size: 200%;
}
```

##JavaScript
```JavaScript

//標準ボタンのHTML取得
const BtnFsNormal = document.getElementById('js-fs-normal');
//拡大ボタンのHTML取得
const BtnFsLarge = document.getElementById('js-fs-large');
// htmlタグ取得
const RootTag = document.documentElement;
// alert出力文
const MaxMessage = encodeURIComponent('これ以上文字のサイズを大きくできません。');
const ResetMessage = encodeURIComponent('標準文字サイズに戻しますか？');

//拡大回数カウント用
let fsUpCount = 0;

// 標準ボタン
BtnFsNormal.addEventListener('click', function(){
  setFsReset();
  return false;
});
// 拡大ボタン
BtnFsLarge.addEventListener('click', function(){
  setFsUp();
  return false;
});

function setFsUp(){
  if(fsUpCount === 5) {
    alert(decodeURIComponent(MaxMessage));
  }else if(fsUpCount === 4) {
    RootTag.classList.add('is-fs-xxxl');
    RootTag.classList.remove('is-fs-xxl');
    fsUpCount = 5;
  }else if(fsUpCount === 3) {
    RootTag.classList.add('is-fs-xxl');
    RootTag.classList.remove('is-fs-xl');
    fsUpCount = 4;
  }else if(fsUpCount === 2) {
    RootTag.classList.add('is-fs-xl');
    RootTag.classList.remove('is-fs-l');
    fsUpCount = 3;
  }else if(fsUpCount === 1) {
    RootTag.classList.add('is-fs-l');
    RootTag.classList.remove('is-fs-m');
    fsUpCount = 2;
  }else if(fsUpCount === 0) {
    RootTag.classList.add('is-fs-m');
    fsUpCount = 1;
  }else if(fsUpCount === null) {
    RootTag.classList.add('is-fs-m');
    fsUpCount = 1;
  }
  BtnFsNormal.classList.remove('is-active');
  BtnFsLarge.classList.add('is-active');

  // cookieに保存
  docCookies.setItem('fsCookies', fsUpCount, 30, '/');
}

function setFsReset(){
  let resetModal = confirm(decodeURIComponent(ResetMessage));
  if (resetModal) {
    fsUpCount = 0;
    RootTag.removeAttribute('class');
  }
  // cookieに保存
  docCookies.setItem('fsCookies', fsUpCount, 30, '/');
}

function getCookie(){
  fsUpCount = docCookies.getItem('fsCookies');
  if(fsUpCount > 0) {
    setFsUp();
  }
}

window.addEventListener('load', getCookie, false);

```

#実際作成した物
<p data-height="265" data-theme-id="0" data-slug-hash="jxVboo" data-default-tab="js,result" data-user="vent2015" data-embed-version="2" data-pen-title="フォントサイズ変更jsを作ってみたメモ" class="codepen">See the Pen <a href="https://codepen.io/vent2015/pen/jxVboo/">フォントサイズ変更jsを作ってみたメモ</a> by vent@青眼鏡君 (<a href="https://codepen.io/vent2015">@vent2015</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
githubのリポジトリで別アカウントでのclone許可

## 目的

開発サーバ等でgit cloneする場合に各自のアカウントに依存しない設計にしたい。  

## 開発サーバ等のアカウントで秘密鍵作成

```bash
ssh-keygen -t rsa -b 4096 -C "develop.ruizu" #すべて空で作成
```

## githubにdeploykeysを追加

下記を参考にする。

[Qiita:GithubのDeploy Keysを登録してパスワードなしでアクセスする](https://qiita.com/master-of-sugar/items/a9892879f6e9cb9f3c97)

## git cloneする

```bash
cd /opt/
git clone git@github.com:private_account/webserver
```

個人のアカウントを開発サーバ等に設定するのは属人性を増やすので基本的にはしない。
ほんとメモだけど。
FlaskアプリをApache + mod_wsgi on windowsで動かす


この組み合わせがたぶん安牌、てゆか他に候補がない。

# その他のサーバ候補

- uwsgi with cygwin

linuxではuwsgi使ってるので魅力的だったが、
cygwinでトラブりたくなかった。

- iis + wfastcgi

wfastcgiはMicrosoft製のライブラリ。
WSGIをFastCGIしてくれる。
python3.4までしかサポートしていないっぽいのと、エラーメッセージ系が全然だったので中止。

# 環境のインストール
## mod_wsgi

mod_wsgiを起点にインストールするライブラリを決める。
公式ではwindows向けライブラリの最新版は止まっているので、こちらを使わせていただきました。

[Unofficial Windows Binaries for Python Extension Packages](https://www.lfd.uci.edu/~gohlke/pythonlibs/#mod_wsgi)

今回はpython3.6 + amd64は決まっていたので、
> mod_wsgi‑4.5.24+ap24vc14‑cp36‑cp36m‑win_amd64.whl
> mod_wsgi‑4.6.4+ap24vc14‑cp36‑cp36m‑win_amd64.whl

の２択、新しい方のmod_wsgi‑4.6.4+ap24vc14‑cp36‑cp36m‑win_amd64.whlを使いました。

## python
https://www.python.org/downloads/windows/
こちらからダウンロードしてインストール、ちゃんと環境変数を通す。
普通にダウンロードすると32bitが落ちてきてしまうので、ちゃんと64bitを明示的に落としてインストールします。

## Apache
公式では配布が止まっているので、サードパーティからダウンロード。
https://httpd.apache.org/docs/current/platform/windows.html#down
今回はApacheHaus版を落としました。

mod_wsgiに合わせて、ap24vc14をダウンロードします。
vc14はVisualC++のバージョンでVisualC++2015でコンパイルされたことを示す。

Apacheはc:¥Apach24フォルダに解凍。
そうしないと、mod_wsgiでインストールパスの設定が必要になります。

サービス登録

```
cd c:¥Apache24¥bin
httpd -k install
```

## mod_wsgiのインストール
pip install mod_wsgi‑4.6.4+ap24vc14‑cp36‑cp36m‑win_amd64.whl

環境があってれば、正しくインストールされます。

## apacheへmod_wsgiの登録

コマンドプロンプトで"mod_wsgi-express module-config"を実行

```
mod_wsgi-express module-config

LoadFile "c:/python36/python36.dll"
LoadModule wsgi_module "c:/python36/lib/site-packages/mod_wsgi/server/mod_wsgi.cp36-win_amd64.pyd"
WSGIPythonHome "c:/python36"
```

wsgi_moduleのコマンドが出るので、この３行をhttpd.confへ貼り付けて起きます。

## wsgi起動スクリプトの作成

flaskアプリをapplicationという名前でimportします。
mod_wsgiがapplicationを拾ってrunしてくれる。

```/your/app/path/yourapplication.wsgi
import sys
sys.path.insert(0, 'c:/your/app/path')

from yourappname import app as application

```

## VirtualHostへ登録
```
<VirtualHost localhost>
    DocumentRoot "C:/your/app/path/"

    WSGIScriptAlias / "C:/your/app/path/yourapplication.wsgi"

    <Directory "C:/your/app/path/">
      Require all granted
    </Directory>
</VirtualHost>
```

## 完了
あとはhttpdサービスをリスタートすれば登録されているはずです。

## 参考

- 公式
http://flask.pocoo.org/docs/0.12/deploying/mod_wsgi/ 

- Python Windows で mod_wsgi を Apache に組み込む方法
https://qiita.com/h_digitalhearts/items/279ec1dfd28cb9693a1f
【SpatiaLite】不正なジオメトリを正しくするMakeValid

WKTで`POLYGON`を作ったときに、うっかり始点と終点を一致させず、経路を閉じ忘れることがあります。

```sql
SELECT
	IsValid(g) AS IsValid,
	IsValidReason(g) As IsValidReason
FROM (
	SELECT
		GeomFromText(
			'POLYGON((0 0, 0 1, 1 1, 1 0))',
			4326
		) AS g
)
;

-- 0, Invalid: Unclosed Rings were detected
```

`MakeValid`はこういった不正なジオメトリを、形を崩さずに正しいジオメトリに直そうとしてくれます。

```sql
SELECT
	AsText(g2) AS geom_text,
	IsValid(g2) AS IsValid
FROM (
	SELECT
		MakeValid(g) AS g2
	FROM
	(
		SELECT
			GeomFromText(
				'POLYGON((0 0, 0 1, 1 1, 1 0))',
				4326
			) AS g
	)
)
;

-- POLYGON((0 0, 0 1, 1 1, 1 0, 0 0)),	1
```

また、`POLYGON`で与えた頂点が描く軌跡は、交わってはいけません。交わってしまう状態を自己交差 (self-intersection) といいます。

```sql
SELECT
	IsValid(g) AS IsValid,
	IsValidReason(g) AS IsValidReason
FROM (
	SELECT
		GeomFromText(
			'POLYGON((0 0, 0 1, 2 1, 2 2, 1 2, 1 0, 0 0))',
			4326
		) AS g
)
;

-- 0, Self-intersection[1 1]
```

この場合、座標 (1, 1) で自己交差がおきています。
このような`POLYGON`も`MakeValid`で正常化できます。

```sql
SELECT
	AsText(g2) AS geom_text,
	IsValid(g2) AS IsValid
FROM (
	SELECT
		MakeValid(g) AS g2
	FROM (
		SELECT
			GeomFromText(
				'POLYGON((0 0, 0 1, 2 1, 2 2, 1 2, 1 0, 0 0))',
				4326
			) AS g
	)
)
;

-- MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((1 1, 1 2, 2 2, 2 1, 1 1))), 1
```

自己交差が起こっていた座標 (1, 1) で2つの`POLYGON`に分けられ、`MULTIPOLYGON`になりました。
AWS AppSync で可変長引数を取るクエリを書く　(JSONで渡す)


可変長引数を配列で渡せないものだと思っていたら、JSON.stringfy で文字列にしなくても渡すことが出来ました。


Schema

```
input AttributeTypeInput {
	attribute_type_id: ID!
	max: Float!
	min: Float!
}
type Query {
searchItemsByAttribute( attribute_type_inputs: [AttributeTypeInput]): [Item]
}
```

query

```
query searchItem{
  searchItemsByAttribute(
  attribute_type_inputs: [{
    attribute_type_id:  1,
    min: 1,
    max: 10000000000
  }]){
    name
  }
}
```

request mapping template

```
"params":{
        "body": {
            "from": 0,
            "size": 50,
            "query":{"bool":{"must":[
            #foreach($attribute_type in $context.arguments.attribute_types) 
            {"term":{"units.attribute_type_id":"${attribute_type.attribute_type_id}"}},
            {"range":{"units.value":{"lte":"${attribute_type.max}","gte":"${attribute_type.min}"}}},
             #end
            ],
            }
                
            }
        }
    }
```
PowershellでCollection返すFunction作ったら返り値変わってびっくりしたのでメモ

## 何か返り値がおかしい

- ADのグループメンバーを対応表をもとに別のADのユーザーに変換するのをつくってた

``` powershell
function convertToAnotherGroupMembers ($groupName) {
    $resurt = New-Object System.Collection.ArrayList
    foreach ($member in (Get-ADGroupMember $groupName)) {
        if (($convertMember = (対応表で変換する処理) -ne $null) {
            $result.Add($convertMember)
        }
    }
    return $result
}

$converGroupMembers = convertToAnotherGroupMembers("groupA");

```

- 結果みてみたら0とか1とか入ってた

```
> $converGroupMembers
0
1
user1のAD情報
...
```

- ステップ実行してみたらreturn直前のときにはそんなもん入ってなかった。funcrionから抜けたときに変換されてるみたい

- 調べてると数字部分はMemberの数だけ入ってることが分かった。つまりArrayList.Addの戻り値
- そーいえば実行してるときにAddメソッドしたらコンソールに０とか１とかでてたなと思いだす。
- functionでCollectionを返却するとストリームまで返却されるらしい。

## 解決策

- ストリームにださなきゃいい
- [void]つければ戻り値いらないと判断されストリームにもでなくなる
- ちなみにクラスのreturnはそのまま返すらしい。パイプのため？

``` powershell
function convertToAnotherGroupMembers ($groupName) {
    $resurt = New-Object System.Collection.ArrayList
    foreach ($member in (Get-ADGroupMember $groupName)) {
        if (($convertMember = (対応表で変換する処理) -ne $null) {
            [void]$result.Add($convertMember)
        }
    }
    return $result
}

$convertGroupMembers = convertToAnotherGroupMembers("groupA");

---
> $convertGroupMembers
user1のAD情報
user2のAD情報
...

```

### **Powershell でちゃんとコーディングしようとするとスーパー辛い、せめてC#で書かせろ**

- まぁ便利なんだけど・・・
【WSL】ホームディレクトリ変更手順

「Windows Subsystem for Linux（WSL）」では、Ubuntu環境が特殊なディレクトリに隠蔽されており、アクセスがしにくかったため、ホームディレクトリを通常使っているWindowsフォルダに変更した際の手順メモ。
# WSLのホームディレクトリ用のフォルダをWindows上に作成
私の場合はCドライブ配下に「linux_home」というフォルダを作成した。

# Windows上のフォルダがWSL上から見えるか確認
WSL上から、Windows上のCドライブは/mnt/c/でアクセス可能なため、lsコマンドでディレクトリのリストを表示し、「linux_home」が見えるか確認する。

```bash
$ ls -la /mnt/c
```
# ホームディレクトリのパスを変更
etc/passwdファイルのホームディレクトリの設定箇所を/mnt/c/linux_homeに変更する。

```bash
$ sudo vim /etc/passwd

（↓ユーザ名の行を探し/home/xxxを「/mnt/c/linux_home」に変更）
{ubuntu上のユーザ名}:x:1000:1000:,,,:/mnt/c/linux_home:/bin/bash
```
# WSLをexitして再起動後、変更が反映されているか確認
起動後のディレクトリが/mnt/c/linux_homeになっているかpwdコマンドで確認する。

```bash
$ pwd
/mnt/c/linux_home
```
google ocr で できること php編

google ocr でできること。
いろいろあるが、

・顔画像解析
・テキスト抽出

この2つ以外は使いみち無さそう。
サンプルコードをどうぞ。

```

<?php

namespace App\Controller;
use App\Controller\AppController;

use Google\Cloud\Vision\VisionClient;

class HogesController extends AppController
{

    public function face()
    {
        $projectId = "carbide-parser-*****";

        $vision = new VisionClient([
            'projectId' => $projectId,
            //鍵ファイルを指定
            'keyFile' => json_decode(file_get_contents(CONFIG.'warai.json'), true)
        ]);

//        ローカルファイル
//        顔写真では無い
        $image = $vision->image(file_get_contents(WWW_ROOT."img/best1.png"), ['FACE_DETECTION']);

//        顔写真である
//        $image = $vision->image(file_get_contents("https://matching-profile.west.edge.storage-yahoo.jp/e9/99/personals-1522845620-384368/profile/m6d1XU-95167300.jpg?AWSAccessKeyId=AKIQHJ6XDD9Y76EXB37&Expires=1524810790&Signature=61UP%2Bq8jXAKQAQiwY6WUyW%2BVRao%3D"), ['FACE_DETECTION']);



        $result = $vision->annotate($image);

        if(!empty($result->info()['faceAnnotations'])){
            echo "顔写真です";
        } else {
            echo "顔写真ではありません";
        }


        $this->autoRender = false;

    }

    public function ocr()
    {

        $projectId = "carbide-parser-******";

        $vision = new VisionClient([
            'projectId' => $projectId,
            //鍵ファイルを指定
            'keyFile' => json_decode(file_get_contents(CONFIG.'warai.json'), true)

        ]);



//        テキスト抽出
        $img = 'https://cdn-ak.f.st-hatena.com/images/fotolife/r/ryo_abe/20171209/20171209221150.jpg';
        $image = $vision->image(file_get_contents($img), ['TEXT_DETECTION']);
        $result = $vision->annotate($image);
//
//
//        //テキストを表示
        pd($result->info()['textAnnotations'][0]['description']);

        //ここまで テキスト抽出




        $this->autoRender = false;
    }



}



```

こんな感じでそれぞれ
顔かどうか判断したり、OCRで画像のテキストのみ引っこ抜いたりできる。
Firebase Functions の割り当てメモリを変更する

[この前の記事](https://qiita.com/seigo-pon/items/e96f6c274d670d865124)で作ったnode.jsの関数ですが、実は使ってると問題がありました。
何回か実行してると突然無反応になるんです。
というか、落ちてるっぽいんです。

最初は、なんやこれー？と悩んだんですが、途中で気づきました。
これ、使ってる辞書のデータがデカすぎてメモリオーバーフローしてんじゃない？

落ちてる箇所は安定しないのですが、ほぼ必ず二回以上しりとりを繰り返すとエラーとなってるようです。
やっぱそれっぽい。

確かに辞書データ、ファイルにすると5MBぐらいいってるんで、キツいんでしょうか。そもそもデフォルトのメモリっていくつやねん。

ということで調べてみました。

## Firebase Functions と Cloud Functions
Firebase Functionsにデプロイした関数は、実際にはGoogle CloudのCloud Funcstionsにデプロイされます。

Google Cloud はここから行きます。
https://cloud.google.com/?hl=ja

Googleのプロジェクトは全てのサービスで共有されてるので、ここのコンソールでFirebaseで作成したプロジェクトを選択できます。
そこからCloud Funstionsを選択すると、すでに関数が追加されています。

## Cloud Functions の割り当てメモリ
Cloud Functionsのスペックはここら辺に書いてあります。
https://cloud.google.com/functions/pricing?hl=ja

デフォルトの割り当てメモリは **256MB** です。

## Cloud Functionsの割り当てメモリ変更
めちゃくちゃ分かりづらいのですが、Cloud Functionsページで関数名を選択すると詳細ページに行きます。
右端のメニューボタンは削除とかログとかのショートカットです。関係ないので注意してください。

![関数.png](https://qiita-image-store.s3.amazonaws.com/0/7690/752bc5cc-6f67-8bb8-a8bc-28e08020f33b.png)

トップのメニューから編集を選択。

![編集.png](https://qiita-image-store.s3.amazonaws.com/0/7690/770feb30-8870-78e7-09da-955ee0164c0f.png)

割り当てられるメモリで、今より多めのメモリを選択して保存します。

![メモリ.png](https://qiita-image-store.s3.amazonaws.com/0/7690/5e1b5dac-495d-b1dd-cb91-c7ec20edd5b4.png)

![メモリ選択.png](https://qiita-image-store.s3.amazonaws.com/0/7690/11ff2248-a4f4-b1ba-2d36-e343feadbeb4.png)

一度変更すると保存されるので、再度デプロイしてもそのままです。

## 所感
1GBに変更すると特に問題なくなりました。よかったよかった。

しかし、256MBもあるのに5MB程度のデータアクセスで落ちるってのも解せないんすよね。

以上です。
VPCエンドポイントを使ってプライベートサブネットからS3へアクセスする。

# はじめに
通常、S3などのVPC外のサービスへは外部ネットワークへアクセスできる必要があります。ですが、VPCエンドポイントを使うとプライベートサブネットからも簡単にVPC外のサービスへアクセスが可能になります。

![vpcendpoint-off.jpg](https://qiita-image-store.s3.amazonaws.com/0/82090/f4a83362-cc92-2847-80de-32fa28eaaa37.jpeg)
![vpcendpoint-on.jpg](https://qiita-image-store.s3.amazonaws.com/0/82090/759069ec-5b29-2109-37fe-4df1b5ea88f0.jpeg)


# エンドポイントの作成
まず、**AWS管理コンソール**から**VPCサービス**へ移動します。
左側ペインの**エンドポイント**から、**「エンドポイントの作成」**をクリックします。

サービスカテゴリ：AWSサービス
サービス名：com.amazonaws.ap-northeast-1.s3

<img width="1226" alt="スクリーンショット 2018-04-15 14.37.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/82090/a4b73d5b-231c-96e0-3c94-2b88fe3dc8ac.png">

次に、利用したいVPCを選択するとルートテーブルがリストされます。利用したいサブネットがアタッチされているルートテーブルを選択します。

![スクリーンショット 2018-04-15 14.41.54.png](https://qiita-image-store.s3.amazonaws.com/0/82090/66f126a3-6c50-1b92-102a-1d26d6d52cb0.png)

ポリシーは今回はフルアクセスにし、**「エンドポイントの作成」**をクリックします。

![スクリーンショット 2018-04-15 14.42.37.png](https://qiita-image-store.s3.amazonaws.com/0/82090/7d9fd5ef-690a-d349-299e-bbaf225b6607.png)

ステータスが使用可能になったらOKです。

![スクリーンショット 2018-04-15 14.43.26.png](https://qiita-image-store.s3.amazonaws.com/0/82090/ef855867-7e67-89ee-2243-0eca6a5f30a9.png)


# S3へアクセス
それではアクセスして確認してみます。

```bash:アクセス確認
$ aws s3 ls s3://koh3i/
2018-03-17 06:46:22       5330 SampleApp_Linux.zip
```

S3サービスへアクセスできました。
また、その他のサービスへアクセスしようとしてもできません。


# おわりに
今まではVPC外のサービスへアクセスするには インターネットゲートウェイやNATゲートウェイを利用する必要がありました。ですが、VPCエンドポイントを使えば簡単にプライベートサブネットからアクセスできるようになるのでとても便利です。
GenymotionでInstagramは使えない？！

GenymotionでInstagramのサインインができなくなり、色々と調べていました。
以前、Genymotionのエミュレーターの高いバージョンでは、Instagramが動かないことがあると知り、
Android４のバージョンで使っていました。
このことを思い出して、バージョン４のをアップデートして、エミュレーターが起動できるようにしました。
でも、ログイン（サインイン）できませんでした。

色々なブログを読んだ結果、無料版のGenymotionでは、完全な通信を再現できないので、アプリによっては、通信ができなくなる場合があるのでは？と推測するに至りました。

実は、Facebookやツイッターは、ログインできたのです。
ネット検索も、正常にできます。
でも、Instagramだけは、通常のログインもFacebookアカウントを使ったログインもできない状況です。
Instagramで、Facebookを使ったログインのボタンには、ちゃんと私の名前が表示されていました。

そのため、何らかの手段の通信のみ無料版のGenymotionはできないと思います。

色々調べている中で、NoxPlayer6というエミュレーターを知りました。
https://jp.bignox.com/
公式サイトから、早速ダウンロードしました。

私は、Macなのでレビューの画面とは多少違いました。
マルチで使う機能は、使えないようです。
そのため、Androidのバージョンを５.１に上げるという内容は、試すことができないです。
私の環境では、バージョン４.４になっています。

![スクリーンショット 2018-04-27 14.19.26.png](https://qiita-image-store.s3.amazonaws.com/0/20977/dc4e6a7f-de5a-09da-d718-518609b7d3b6.png)

起動すると、エミュレーターの状態になります。

![スクリーンショット 2018-04-27 14.20.29.png](https://qiita-image-store.s3.amazonaws.com/0/20977/62360c27-9100-170e-2a7b-77dab6141929.png)

問題のInstagramですが、ちゃんとログインできました。
初期は、タブレットの画面のように横向きになっています。
携帯電話にすると、スマホの縦長の画面にできます。

Androidのバージョン７など高いバージョンのエミュレーターは、純正？またはGenymotionを使うことになると思いますが、低いバージョンのAndroidでも良いアプリ開発なら、NoxPlayer6がおすすめのように思いました。

##apkファイルの実装方法
デバッグでapkファイルをNoxPlayer6にインストールするときは、画像の赤丸のアイコンをクリックします。
![スクリーンショット 2018-04-27 14.28.23.png](https://qiita-image-store.s3.amazonaws.com/0/20977/be43f195-4e93-4ccf-0406-0721aab38e42.png)
ファイルを開くことができる画面になりますので、目的のファイルまでたどり着いてから「開く」をクリックするとインストールできます。

私が今作っているアプリは、バージョンが５.０.１以上を対象にしているので、NoxPlayer6では起動することはできないですが、インストールできることは確認できました。

Genymotionのように、ファイルをドラッグ&ドロップできないです。
そのため最初から、ファイル転送のアプリがインストールされているのかもしれません。

##追記
エミュレーターをroot化できます。
画面右上の歯車のアイコンをクリックすると、設定画面になります。
この中に、root化の選択ができる項目があります。
root化すると、直接ドラッグ&ドロップで、ファイル転送できます。
JavaScriptでfilterしてmapを実行したい


配列にダブルクォートで囲われた動物達がいます。
重複をなくして、さらにダブルクォートを取り除きたい。普通にfilterとmapでやると

```javascript
let animals = ['"cat"', '"dog"', '"cat"', '"bird"', '"dog"'];

// filterで重複を取り除いてからmapで文字列置き換え
animals = animals.filter(function(element, index, array) {
  return array.indexOf(element) === index;
}).map(function(element) {
  return element.replace(/"/g, '');
});
=> [ 'cat', 'dog', 'bird' ]
```

もうちょっとエレガントに書けないかと思い関数化してすっきり！

```javascript
let unique = function(element, index, array) {
  return array.indexOf(element) === index;
};

let replace = function(element) {
  return element.replace(/"/g, '');
};

let animals = ['"cat"', '"dog"', '"cat"', '"bird"', '"dog"'];
animals = animals.filter(unique).map(replace);
=> [ 'cat', 'dog', 'bird' ]
```
clickイベント内での返り値と他要素との関連

クリックイベント内で、親要素のイベントがごっちゃになったり
return false; と return;の違いがよくわかっていなかったので整理。

```html
<div id="parent">
  <div id="hoge"></div>
</div>
```

```js
$(document).on('click', '#parent', function(e){
  alert('#parent');
});

$(document).on('click', '#hoge', function(e){
  // クリックした要素のイベントキャンセル
  // aタグのクリックやチェックボックスのクリックなど
  e.preventDefault();
  
  // 親要素への伝搬キャンセル
  e.stopPropagation();
  
  // e.preventDefault() + e.stopPropagation()
  return false;
  
  // ちなみに下記の場合は、関数の処理終了だけで
  // 要素イベントも起こるし、親要素への伝搬もする。
  return;
  
});
```
Node.js10のfs/promisesきたよー

# Node.jsのcurrentにversion10がきた

Promiseでかけるfsが来た。Experimentalなので注意。

## 試す

Node.jsのcurrentでversion10が来たのでfs/promisesを試してみる。

nodebrewで入れてるので更新

```bash
nodebrew install-binary 10
nodebrew use 10
```

```js
const fs = require('fs/promises')
```

で引っ張ってくるとPromiseバージョンのAPIを使える。
[これ](https://qiita.com/tsuuuuu_san/items/0561dc30898f7ff0bd07#new-promise%E3%81%8C%E9%82%AA%E9%AD%94%E3%81%AA%E4%BB%B6) の最後のと同じことをする

## コード

上記でやっている、
ファイル1を取ってきてその中に書いてあるパスのファイル2の内容を出力
をやってみる。

```js
const fs = require('fs/promises');

(async () => {
  const nextFile = await fs.readFile('./next.txt', 'utf8');
  const message = await fs.readFile(nextFile.trim(), 'utf8');

  console.log('async/await:', message);
})()
.catch((err) => console.log(err.message));
```

使い方の違いはない。
Util等でpromisifyするのと比べて関数を引っ張ってくるのがわかりやすい。

## 実行結果

```bash
% node index.js
(node:5106) ExperimentalWarning: The fs/promises API is experimental
async/await: Hello Node10
```

ExperimentalWarning って出てる。

warnなし

```bash
% node --no-warnings index.js
async/await: Hello Node10
```

はやく安定版にしてけれ
RaspberryPiをリモートで制御する。

#1.はじめに
RaspberryPiのセッティングをしたのは良いが、ケーブルが沢山あり。
それだけで机を埋めてしまうので、パソコンからリモートアクセスすることをしたい。
![s_DSC00358.JPG](https://qiita-image-store.s3.amazonaws.com/0/244043/e937b102-1d7e-4821-7950-bded6deacc73.jpeg)

#2.目的
CUI（コマンド）、GUI（画面）でRaspberryPiにアクセス出来るようになる。

#3.前提
・パソコンはMacBookAir
・RaspberryPiは[こちら](https://qiita.com/S_ODA/items/3600b4492747e66f5df7)でセッティングしたものです
・両方とも同じネットワーク環境に接続しておいて下さいませ。

⇨Windows設定はマシーンがないので、画像が取れないのです。。。

#4.リモート制御
##4-1.CUI
###4-1-1.RaspberryPi側の設定
ターミナルを起動して

```sh:cmd
sudo raspi-config
```

下記のような画面になりますので、「5.Interfacing Options」を選択します。
![s_DSC00359.JPG](https://qiita-image-store.s3.amazonaws.com/0/244043/e5b2f607-5cd4-32da-3332-9d8e09258578.jpeg)

次に「P2 SSH」を選択します。
（後述するGUIでは「P3 VNC」を選択するので、この段階でやってもOKです。）
![s_DSC00360.JPG](https://qiita-image-store.s3.amazonaws.com/0/244043/2f0349a7-49ee-bc5b-2615-153471a1f0b3.jpeg)

次に「＜はい＞」を選択します。
![s_DSC00361.JPG](https://qiita-image-store.s3.amazonaws.com/0/244043/f0be7937-aacf-9725-d171-0eccb6b3591f.jpeg)


セッティング画面に戻りますので、「ESC」キーで終了します。

次にRaspberryPiのIPを調べます。
ターミナルで下記コマンドを実行

```sh:cmd
ifconfig
```
wlan0というカテゴリがありますので、inet の横にあるIP：XXX.XXX.XXX.XXXをメモしておきます。

###4-1-2.パソコン側の設定
ターミナルで下記を実行し、RaspberryPiにアクセスします。

```sh:cmd
# RaspberryPi側のIPを指定する。
ssh pi@XXX.XXX.XXX.XXX

# Passwordが問われますが、デフォルトでは「raspberry」です。
```

↓こんな感じでMacBookからRaspberryPiにアクセスできます。
![スクリーンショット 2018-04-27 13.21.43.png](https://qiita-image-store.s3.amazonaws.com/0/244043/479624df-a0c9-1a58-1bc9-32a5cd5d4191.png)


##4-2.GUI

###4-2-1.RaspberryPi側の設定
ターミナルを起動して

```sh:cmd
sudo raspi-config
```

画面はCUIと同じなので省略しますが、
・「5.Interfacing Options」を選択します。
・次に「＜はい＞」を選択します。
・セッティング画面に戻りますので、「ESC」キーで終了します。
　
　
次にVNC（Virtual Network Computing）をインターネット経由で取得・インストールします。

```sh:cmd
sudo apt-get update
sudo apt-get install tightvncserver
```

色々と関連モジュールがDownLoadされますが、インストールが終われば


```sh:cmd
tightvncserver
```

始めは２種類のPassWord設定を求められます。
・更新可能
・参照のみ（設定しなくてもOK）


###4-2-2.パソコン側の設定
MacBookでのリモート接続ですが、下記手順を追います。
Windowsでいうリモートデスクトップと同じと解釈していますので、Wisdows側でも出来ると思う。

```sh:手順
# RaspberryPi側のIPを指定する。
Finder ⇨ 移動 ⇨ サーバへ移動 ⇨ vnc://XXX.XXX.XXX.XXX:5901 
# 「tightvncserver」実行時に設定したPassWordを入力
```

アクセスできますと、こんな感じで見えるのです。
![s_DSC00363.JPG](https://qiita-image-store.s3.amazonaws.com/0/244043/6f5589bd-9852-e7e9-5023-b8c1e39e7ce3.jpeg)


#5.ちなみに
CLIでのシャットダウンコマンドは下記となります。
表示された時間後に落ちます。

```sh:cmd
sudo shutdown
```
分からない言葉を検索したら英語のサイトばっかり出てきてすぐ閉じちゃうアナタへ

# **:bear:自己紹介:bear:**

何を隠そうタイトルで書いたのは１か月くらい前のワタシです。
コードを書いているとわからない言葉にブチ当たって、その度に検索しますが、
上位に出てくる英語のサイト見ても拒否反応しかしない…。


英語のサイトは即閉じて、下位表示の更新日の古い日本語のサイトで比較的わかりそうな言葉を調べて…なんて。理解さえできればダイレクトに答えに辿り着ける英語表記のサイトを見て見ぬふりをしていたが故に、答えがわからないばかりか、膨大に無駄な時間を費やしていた(とやっと気付いた)35歳新人プログラマです。


# **１か月で何があったかって？**
ス〇ードラーニングを始めたわけでも、英会話スクールに通ったわけでもありません。
Googleの拡張機能というやつを見つけたのですよ。 (￣ー￣)ﾆﾔﾘ

元々Google翻訳をブックマークバーに入れて、そりゃもう毎日使っていました。
エラー出るたびに全部貼ってエラーの内容を理解したり、英語のページを全コピして読んでました。
でもそれだと、全部テキスト書出ししてるようなもので文脈とか解説とかは分かりにくいのです。

そこでページ丸ごと翻訳出来たら便利なのにな～って思ってたら
Googleの拡張機能にGoogle翻訳を追加するというのに辿り着きました。

# **もう英語なんか怖くないぜ～(拡張機能を追加しよう)**
スマホに色んなアプリを入れるみたいにGoogle chromeに色んな機能を追加することが出来るんですね
 　☞　[拡張機能をインストールする、管理する](https://support.google.com/chrome_webstore/answer/2664769?hl=ja)

念のため画像も貼っておきます。![拡張機能のインストール画面の画像.png](https://qiita-image-store.s3.amazonaws.com/0/237418/b276f822-7188-8c9f-12d2-7097446c6b3b.png)

　　**[Chrome ウェブストア](https://chrome.google.com/webstore/category/extensions?hl=ja) で Google翻訳  で検索してChromeに追加するだけ!!!!**
![拡張.png](https://qiita-image-store.s3.amazonaws.com/0/237418/7bb5a7a1-74d0-f7b7-8abb-4eeb355978be.png)

そうすると、素晴らしいショートカットが出来るんです。
![拡張が追加されたら表示されてる.png](https://qiita-image-store.s3.amazonaws.com/0/237418/599c8b0f-0c3f-d7d3-dd58-d2b5f26cc7c8.png)

では参考までに…丸っと翻訳してみます。ジャーン!!!読めます。英語がサッパリなワタシでも😻
![BEFOREandAFTER.png](https://qiita-image-store.s3.amazonaws.com/0/237418/d9ae166b-cb51-dbbe-92f5-a34096be3b17.png)

# **おまけ(英語で書いてあるドキュメントだって翻訳できるよー)**
Google翻訳にファイルを読み込ませれば、英語のドキュメントも日本語に出来ますがファイルサイズに上限があって、サイズの大きなドキュメントは分割してからじゃないと翻訳できませんでした。

でも、最近良いサイトを見つけたので書き残します。
https://www.onlinedoctranslator.com/
![screencapture-onlinedoctranslator-2019-05-28-15_01_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237418/be53f172-1107-0013-9fb9-bd42e839eccd.png)
結構大きなサイズのpdfでもWi-Fiがサクサクなら時間かからずに翻訳してくれます。


★゜・。英語が得意じゃない同士の方々のストレスが減って早く答えに辿り着けますように・゜★
GoogleマップURLのパラメータブロック構文

#概要
ブラウザ版GoogelaマップのURLには'!'で区切られた謎パラメータ群が付いてくることがよくあります。

例えばこんなのです:
>https://www.google.com/maps/place/%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB%E5%90%88%E5%90%8C%E4%BC%9A%E7%A4%BE/@35.660411,139.7287178,19z/data=!3m2!4b1!5s0x60188b77a7f6fcf5:0x60c9ffa23520351!4m5!3m4!1s0x60188b770913970d:0xccc3467fcb15b353!8m2!3d35.660411!4d139.729265

このURLの"data="以降がこの記事で対象にするパラメータブロック部分です。
>!3m2!4b1!5s0x60188b77a7f6fcf5:0x60c9ffa23520351!4m5!3m4!1s0x60188b770913970d:0xccc3467fcb15b353!8m2!3d35.660411!4d139.729265

いったいこのURLは何を言っているのか、気になる人には非常に気になり、気にならない人には本当にどうでもいい事柄かと思いますが、私気になりますので調べました。

この呪文に行きあたって心が折れた人の支えになれれば幸いです。

#注意
この記事ではパラメータブロックの構文のみに注目しています。
パラメータブロックが指し示す意味や動作については言及しませんので、悪しからずご了承ください。

また、記載内容は私が勝手に推測したものです。間違っている可能性もあることに留意してください。

#正体
インデックス、型、値で構成される要素の配列を表現しています。配列は入れ子構造を取ることができます。
最上位にルート配列が存在します。

上記の例ですと、

```
!3m2!4b1!5s0x60188b77a7f6fcf5:0x60c9ffa23520351!4m5!3m4!1s0x60188b770913970d:0xccc3467fcb15b353!8m2!3d35.660411!4d139.729265
```

これは次のように展開されます:

```
!3m2
	!4b1
	!5s0x60188b77a7f6fcf5:0x60c9ffa23520351
!4m5
	!3m4
		!1s0x60188b770913970d:0xccc3467fcb15b353
		!8m2
			!3d35.660411
			!4d139.729265
```
長い行も短い行もありますが、すべて1行1要素で記述してあります。
要素は全てインデックスと型と値を持ち、型に応じて値の記述フォーマットが変わってきます。

#要素
要素は全て次の構文で構成されます。例外は確認していません。

```
! + インデックス(整数) + 型(英字1文字) + 値(文字列)
```

各部の連結部にスペースなどを含むことは許されません。
インデックスは正の整数のみが許されるものと思われます。0以下の値は確認していません。
型の大文字小文字は区別されます。確認されている例ではすべて英小文字です。

##例
|要素|インデックス|型|値|
|---|---|---|---|
|!3m2|3|m(配列)|2(続く2要素が配列に含まれる)|
|!4b1|4|b(論理値)|1(true)|
|!5s0x6018...|5|s(文字列)|0x6018...|
|!4m5|4|m(配列)|5(続く5要素が配列に含まれる)|
|!3m4|3|m(配列)|4(続く4要素が配列に含まれる)|
|!1s0x6018...|1|s(文字列)|0x6018...|
|!8m2|8|m(配列)|2(続く2要素が配列に含まれる)|
|!3d35.660411|3|d(実数)|35.660411|
|!4d139.729265|4|d(実数)|139.729265|

#インデックス
**配列の添字とは異なります**。構文的には重複が許され、インデックスの重複するすべての要素が有効です。
ただし解釈する側で取捨される状況はあり得ます。

列挙型の要素が同じインデックスで並ぶ例はよく見られます。

インデックスの数値が連続する必要はなく、数値の大小関係に従った並び順も(おそらく)求められません。

#型と値
一覧を次に示します:

|型|値|備考|
|---|---|---|
|m|配列要素数(0以上の整数)|値は後に続く要素数を示す<br>子配列の要素数も含むことに注意|
|b|真偽値<br>(0=偽,1=真,それ以外もたぶん真)|
|i|整数|
|d|実数|
|e|列挙値(整数)|
|u|符号なし整数?|見かけたことがあるような気がする|
|h|16進数|見かけたことがあるような気がする。<br>"0x"のような接頭詞は付かなかったような気がする|
|s|文字列|原則的にはURIエンコードされている<br>たまに'+'をスペースにデコードしない受け手の処理系があるので注意<br>(その場合は%20でエンコードする)|
|z|文字列?|たまにある。sとの違いは不明|

##配列
'm'で示される配列要素の注意点を挙げます。

###要素数の解釈
要素数は子配列の要素数も含みます。
`!1m3!2m2!3i0!4i0!5i0!6i0!7i0` というパラメータブロックがあった場合、

次の解釈は間違いです:

```
!1m4
	!2m2 //1m4の要素1
		!3i0
		!4i0
	!5i0 //1m4の要素2
	!6i0 //1m4の要素3
	!7i0 //1m4の要素4
```

正しい解釈は次の通りです:

```
!1m4
	!2m2
		!3i0
		!4i0
	!5i0 //ここまでの4要素が!1m4の下に付く
!6i0
!7i0
```

正しく生成されたパラメータブロックであれば、ネストした配列要素数の帳尻は合うはずです。

#要素数0の配列
あり得ます。実例も確認されています。

`!1m0!2m2!3i0!4i0` というパラメータブロックはルール通りに次のように解釈されます:

```
!1m0
!2m2
	!3i0
	!4i0
```

#所感
ほんとに誰得な情報ですが、これと格闘する羽目になった場合にパーサーを書くのは結構楽しい作業になります。お勧めです。
PowerShellでタスクスケジューラにジョブを登録する

バッチをタスクスケジューラに登録する必要があったのでこれもスクリプトで書いた.

## Script

「SampleTask」というタスク名で毎日00:00:00にユーザーhogeでSample.batを実行したい場合はこんな感じ.

``` powershell
$taskName = "SampleTask"
$executeTime = "00:00:00"
$programPath = "C:\Sample.bat"
$user = "hoge"
$pass = "password"

$trigger = New-ScheduledTaskTrigger -Daily -at $executeTime
$action = New-ScheduledTaskAction -Execute $programPath
Register-ScheduledTask -TaskName $taskName -Trigger $trigger -Action $action -User $user -Password $pass
```
Mac版 Node.js環境構築方法まとめ

## 概要

ReactやElectronでの開発を行うにあたって、Node.js開発環境は必須になります。
今回は、MacでNode.js環境を構築する方法についてまとめます。

所要時間: 約10分

## 注意

2018年4月26日において最新安定版のNode.jsのバージョン(**v8.11.1**)での構築方法をまとめます。

## Node.js環境が構築されているかを確認

Node.jsの環境構築を行う前に、今利用しているMacにNode.js環境があるか
もしくは、**v8.11.1**より古いものを利用しているかの確認を行います。

### 1. ターミナルを起動

#### Spotlight検索を起動

キーボードの`⌘ (コマンドキー)`と`Space (スペースキー)`を同時押しでこちらの画面が表示されます。

<img width="1680" alt="2018-04-27_12-56-01.png" src="https://qiita-image-store.s3.amazonaws.com/0/190699/f7fdbdb1-d579-5607-5213-b298bafd3175.png">


#### Spotlight検索を起動後にすること

「ターミナル」と入力して下さい。  
こちらの画像のような表示結果になるので、`Enter (エンターキー)`を押して下さい。

<img width="1680" alt="2018-04-27_10-49-08.png" src="https://qiita-image-store.s3.amazonaws.com/0/190699/80105363-f3ec-8c20-697e-c4b19655d426.png">

### 2. インストール確認

ターミナルに、下記のとおり、`node -v`と入力しEnterを押下します。

Enterを押して、下記の画像のような表記になれば、Node.jsがインストールされていない環境になります。

![スクリーンショット 2018-04-27 13.14.14.png](https://qiita-image-store.s3.amazonaws.com/0/190699/fa15860f-7659-5c48-098b-7d70ec909386.png)

インストールされていれば、下記画像のように表示されますが、**v8.11.1**でなかった場合、続けて環境構築を行いましょう。

![2018-04-26_10-14-21.png](https://qiita-image-store.s3.amazonaws.com/0/190699/95142f68-a8e0-83d0-150e-3b5e7abb412a.png)

## Node.js導入方法

### ndenvとは

https://github.com/riywo/ndenv

Node.jsのバージョン管理ツールです。
インストール・アンインストールができます。

### 導入手順

順番にコマンドをコピーして貼り付けます。
1から5まで一つずつ実施しますが、一つ貼り付けるごとに`Enter (エンターキー)`を押して下さい。

1. `git clone https://github.com/riywo/ndenv ~/.ndenv` (ndenvをダウンロードします)
2. `echo 'export PATH="$HOME/.ndenv/bin:$PATH"' >> ~/.bash_profile` (PATH環境変数にndenvを登録します)
3. `echo 'eval "$(ndenv init -)"' >> ~/.bash_profile` (ターミナル起動時にndenvを有効にします)
4. `exec $SHELL -l` (1~3までの実行結果を反映します)
5. `git clone https://github.com/riywo/node-build.git $(ndenv root)/plugins/node-build` (nodeをインストールするのに必要なものをダウンロードします)

続いて、ターミナルで`ndenv`と入力し、`Enter (エンターキー)`を押して下さい。

<img width="570" alt="2018-04-26_10-03-12.png" src="https://qiita-image-store.s3.amazonaws.com/0/190699/bf464adc-7d13-c7e2-d134-515d3399616e.png">

こちらの画像のように、たくさんの英語が羅列されていれば成功です。

引き続き、`ndenv install v8.11.1`を入力して`Enter (エンターキー)`を押して下さい。

<img width="565" alt="2018-04-26_10-10-46.png" src="https://qiita-image-store.s3.amazonaws.com/0/190699/72556e9c-97f6-b4f2-897c-5432595ca826.png">

画像の様な結果が表示されます。

最後に、`ndenv global v8.11.1`を入力して`Enter (エンターキー)`を押して下さい。

## バージョンの確認

今回の導入方法で２つMacにインストールされるものがあります。

- Node.js
- npmというモジュールの管理ツール

それぞれを確認してみましょう。
順番にコマンドをコピーして貼り付けます。
1から２まで一つずつ実施しますが、一つ貼り付けるごとに`Enter (エンターキー)`を押して下さい。

1. `node -v`
2. `npm -v`

<img width="568" alt="2018-04-26_10-14-21.png" src="https://qiita-image-store.s3.amazonaws.com/0/190699/1ed0a573-48ee-f3ee-a37f-0ed86f2ae023.png">

画像のように「Node.js」のバージョンが**v8.11.1**と「npm」のバージョンが**5.6.0**になっていれば成功です。

## あとがき

MacでのReact、Electron開発にて必須なNode.js開発環境の構築方法についてまとめました。
Node.jsの導入方法は[Homebrew](https://brew.sh/index_ja)など様々ありますが、今回はNode.jsのバージョンを**v8.11.1**に固定したくて、まとめ記事を共有してみました。

別途、[Yarn](https://yarnpkg.com/lang/ja/)の導入方法もまとめたいと思います。
ありがとうございました。