OmniAICreator/Qiita-1.07M huggingface dataset:
1日目: Mobile Sensor Data Anonymization

# Mobile Sensor Data Anonymization まとめ
## 読んだ論文
Mobile Sensor Data Anonymization
Mohammad Malekzadeh, Richard G. Clegg, Andrea Cavallaro, Hamed Haddadi
https://arxiv.org/abs/1810.11546
上記の論文を読んだので簡単にまとめます．Preprintのみの様子です．
## 3行でまとめる
- スマホ等のセンサデータを用いた研究が流行っているが，センサデータは個人情報を含んでおり，情報暴露のリスクがある．
- 生センサデータをDeepAutoEncoderで個人を特定しづらい（が，元データから離れすぎない）形に変換する．
- 独自の多目的損失関数（式(1)）を定義し評価実験した．

## 損失関数
$$
F(A(\boldsymbol{X})) = \beta_i I(\boldsymbol{U}; A(\boldsymbol{X})) - \beta_a I(\boldsymbol{T}; A(\boldsymbol{X})) + \beta_d d(\boldsymbol{X}, A(\boldsymbol{X})) \tag{1}
$$

ここで，$\boldsymbol{X}$は元のセンサデータ，$A(\boldsymbol{X})$は提案手法で変換後のセンサデータ，$\boldsymbol{U}$はユーザ，$\boldsymbol{T}$は推定対象（今回は行動）である．関数はそれぞれ，$I(\cdot;\cdot)$が相互情報量，$d(\cdot, \cdot)$が距離（今回はMSE）である．各$\beta$は0-1の重みで，匿名性，認識精度，元波形の維持率どれを優先するかトレードオフで決定するパラメータである．
即ち，上記式(1)は変換後の$A(\boldsymbol{X})$からユーザ$\boldsymbol{U}$への相互情報量を下げつつ，$A(\boldsymbol{X})$から対象$\boldsymbol{T}$への相互情報量を上げつつ，$A(\boldsymbol{X})$からと元データ$\boldsymbol{X}$のMSEを下げるようにネットワークを訓練するということになる．

## モデル構造
スタンダードなConvolutional Encoder-Decoderモデルなので詳細は割愛する．

## 評価実験
### 実験設定
- 被験者24名（男14：女10）
- 6行動を2～3セット計測（歩行，走行，階段上り，下り，座る，立つ）
- 加速度とジャイロセンサで50Hz計測
- 評価は2パターンの分離で実施する．
 - ユーザベース：4名（男2：女2）をテスト，残り20名を訓練に使用する．
 - トライベース：各行動の1セットをテスト，残りセットを訓練に使用する．
- センサデータは時系列分割で窓サイズは128(2.56sec)，ストライドは10

### 実験結果
- 比較対象（Baseline）の理解まではせず．．．
- 比較対象と比べ，行動認識精度は微増，個人特定のACCは半分以下に，元データとの離れ具合DTWも最良という結果に．

## まとめ
- センサからの情報暴露を防ぐために，Autoencoderで実用に害がないように変換しようという企画でした．
- 手法はとてもシンプルで読みやすいです．
- 同じような企画としては日本語論文で東大松尾研からも出ていますのでこちらも要チェックですね．
 - ユーザ敵対型ニューラルネットワーク, 人工知能学会論文誌, 32(4), 2017.
 - https://www.jstage.jst.go.jp/article/tjsai/32/4/32_A-GB5/_article/-char/ja/

## 所管
なんとなく一日一編の論文を要約していこうと思い立ったが吉日早速始めてみたものの，論文選定～Qiitaアカウント作成～要約完了まで2時間ほど．手法が簡単だったこともあり，読むことよりもどこ要約するか考えたり，Markdown戸惑ったりすることが多かった気がします．毎日2時間かかってると続かないので，もう少し適当な感じで今後も続けていければと思います．
maximaでquaternionの座標系変換を求める覚書(Unity,UE4,ROS,OpenCV間の変換)

# 前置き
OpenCVやROSと組み合わせてUnityやUE4といったゲームエンジンを使うとき困るのが座標変換です。右手系か左手系か、xは右か前か、プラットフォームごとにバラバラです。

この変換方法についてのメモです。

# 座標系の変換行列

といっても実は難しいことはありません。座標系の変換行列を作って掛けるだけです。

まず、y座標系からx座標系への変換行列(＝x座標系におけるy座標系)を

```math
{}_x^{}R_y \in\mathbb{R}^{3 \times 3}
```
と定義します。このとき、$ {}\_y^{}R_x = {}\_x^{}R_y^{-1} $ と $ {}\_x^{}R_z = {}\_x^{}R_y \cdot {}\_y^{}R_z $ が成り立ちます。


例えばOpenCVの座標系(x-right, y-down, z-forward)からunityの座標系(x-right, y-up, z-forward)へ変換する行列は下記のようになります。

```math
{}_{Unity}^{}R_{OpenCV} =
\begin{bmatrix}1 & 0 & 0\\
0 & -1 & 0\\
0 & 0 & 1\end{bmatrix}
```

同様にROSやUE4との変換行列も定義してみましょう。

```math
{}_{Unity}^{}R_{ROS} =
\begin{bmatrix}0 & -1 & 0\\
0 & 0 & 1\\
1 & 0 & 0\end{bmatrix}
\\
{}_{Unity}^{}R_{UE4} =
\begin{bmatrix}0 & 1 & 0\\
0 & 0 & 1\\
1 & 0 & 0\end{bmatrix}
```

unityへの変換のみを作りましたが、これらを元に相互変換する行列も機械的に作れます。OpenCVからROSなら下記のように求めます。

```math
\begin{eqnarray}
{}_{ROS}^{}R_{OpenCV} 
&=& {}_{ROS}^{}R_{Unity} \cdot {}_{Unity}^{}R_{OpenCV} \\
&=& {}_{Unity}^{}R_{ROS}^{-1} \cdot {}_{Unity}^{}R_{OpenCV} \\
&=& \begin{bmatrix}0 & -1 & 0\\
0 & 0 & 1\\
1 & 0 & 0\end{bmatrix} ^{-1} \cdot
\begin{bmatrix}1 & 0 & 0\\
0 & -1 & 0\\
0 & 0 & 1\end{bmatrix} \\
&=& \begin{bmatrix}0 & 0 & 1\\
-1 & 0 & 0\\
0 & -1 & 0\end{bmatrix}

\\
\end{eqnarray}
```

# 変換方法

y座標系の位置 ${}\_y^{}P \in\mathbb{R}^3$ をx座標系 ${}\_x^{}P$ に変換：

```math
{}_x^{}P = {}_x^{}R_y \cdot {}_y^{}P
```

y座標系の3x3回転行列 ${}\_y^{}R\in SO(3)$ をx座標系 ${}\_x^{}R$ に変換：

```math
{}_x^{}R = {}_x^{}R_y \cdot {}_y^{}R \cdot {}_x^{}R_y^{-1}
```

y座標系の4x4行列 ${}\_y^{}T \in SE(3)$ をx座標系 ${}\_x^{}T$ に変換：

```math
{}_x^{}T = \begin{bmatrix} {}_x^{}R_y & 0 \\ 0 & 1 \end{bmatrix}
\cdot
{}_y^{}T
\cdot
\begin{bmatrix} {}_x^{}R_y^{-1} & 0 \\ 0 & 1 \end{bmatrix}
```

y座標系のquaternion $ {}\_y^{}Q = [x,y,z,w]^T$をx座標系$ {}\_x^{}Q$に変換：

```math
{}_x^{}Q = \begin{bmatrix} {}_x^{}R_y & 0 \\ 0 & 1 \end{bmatrix}
\cdot
{}_y^{}Q
```

# maximaによるquaternionの変換式の導出

位置や回転が上の変換で良いのは分かるのですが、quaternionが本当にこれでよいのか直感的に分からなかったのでmaximaで検算してみました。おまけみたいですが、これが本題！

数式処理システムmaxima
https://wxmaxima-developers.github.io/wxmaxima/

quaternionから3x3行列を求めて座標変換をしてからquaternionに戻して、式がどう変形するかを見ています。上記で示した結果が得られると思います。(回転行列に変換する場合quaternionは符号反転しても等しくなることに留意)

```
/* quaternionから回転行列SO(3) を求める */
skew: matrix(
  [0,-z,y],
  [z,0,-x],
  [-y,x,0]
);
R:ident(3) + 2*skew.skew+2*w*skew;

/* 各プラットフォームの座標系からunityへの変換 */
uRo: matrix([1,0,0], [0,-1, 0], [0,0,1]);  /* opencv to unity */
uRr: matrix([0,-1,0], [0,0, 1], [1,0,0]); /* ros to unity */
uRe: matrix([0,1,0], [0,0, 1], [1,0,0]); /* ue4 to unity */

/* 適用する座標変換 */
dR: uRo$

/* 回転行列に座標変換を適用しquaternionを求める
   wは座標変換では不変のため計算を省く */
mtoq(m):=ratsimp(matrix([4*w^2,m[3,2]-m[2,3],m[1,3]-m[3,1],m[2,1]-m[1,2]])/4/w)$
mtoq(dR.R.invert(dR));
```
YouTubeで字幕なしの海外番組を字幕付きで見る方法(Google Chrome)


#はじめに
最近英語の勉強がてらCNN（ニュース）をYouTubeで見るのですが，字幕がついておらず，ニュースキャスターも早口なので，中身を追うのがなかなか大変です．
そんな中，[WebSpeechAPI](https://developer.mozilla.org/ja/docs/Web/API/Web_Speech_API)なるものの存在を知って，Google Chromeだと音声入力でテキストを生成できるサイトをいくつか見かけました．

 - [Googleによる公式デモ](https://www.google.com/chrome/demos/speech.html)
 - [ブラウザでマイク入力から書き起こしを行うツールを作った](https://mizchi.hatenablog.com/entry/2019/01/20/203241)

このWebSpeechAPIを上手く使ったら，YouTubeとかで，海外の番組だけど字幕が付いてないような動画でも字幕が生成できるのではないかと思ったので，簡易的に音声から字幕を，リアルタイムでかつ直前の区間のみ生成してくれるアプリを作りました．

#実物
公式のspeech.htmlを少し弄って作ったものが以下となります。
[ページ](https://verb55nta.github.io/WebSpeechAPI/)
[GitHub](https://github.com/verb55nta/WebSpeechAPI)

# 使い方
ページを開いたら，右上に緑色の矢印があるので，これをクリックしてください．
そうしたら録音モードになって赤い丸が出てきて字幕生成モードに入るので，字幕を生成させたい音声を再生してください．
字幕は，最大で10 word分表示されます
（Google公式デモだと際限なく字幕が表示されるのが嫌だったので，今回改造するモチベーションになりました）
英語以外でも，単語が区切られているものだったら上手くいくので，フランス語やドイツ語などでもいけると思います
（中国語はAPIが切れ目のある文字を出力してくれなかったので，際限なく文字が流れます）

#動作イメージ
![subtitle.png](https://qiita-image-store.s3.amazonaws.com/0/213113/a8354f9a-189f-33a2-b7d7-062038d45cc0.png)

今回はすごく簡易的なものなので，Chromeを2つ起動して，片方をYouTube，もう片方を今回作ったページを表示しています．
下のほうに写ってる"that I know that that was a cartoon but do"という文字列が実際に音声から生成されたものです．
YouTubeを上に重ねてあげると見やすいです．

# (必須)PCで再生した音声をマイク入力にする
今回使用するWebSpeechAPIは，マイクの入力をGoogleの文字起こしに投げるので，PCで再生される音声をマイク入力に直接繋いであげないといけません．
Windows環境においては，ステレオミキサーという機能があり，これを使うことでPCで再生した音声を直接マイク入力に繋げることが出来ます．
(参考) [ステレオミキサーの基礎 – VIPで初心者がゲーム実況するには](https://www18.atwiki.jp/live2ch/pages/151.html)
基本的にはこのサイトに従えばステレオミキサーの設定は上手くいくはずですが，一部のPCではステレオミキサーが存在しないということがありえます．（ノートPCに多い？）
その場合はステレオミキサーの存在するサウンドカードに対応したPCを手に入れるか，オーディオインターフェイス等の周辺機器でPCの出力をマイク入力に繋げる等の解決策が一応あります．
Linuxを使ってる人だったらsoxとか適当に弄ればなんとかなりそうです．

# やってみた感想
遅延とか大丈夫かなぁと思ったのですが，割と遅延なく正確に字幕を出してくれるので，結構字幕が参考に出来る感じです．流石Google様や...
ただ同時に二人が話すときとか（CNNでは頻繁にある），BGMが激しい時とかはなかなか厳しいです．

# 終わりに
見た目がショボイのは許してください...(JavaScriptほとんど弄ったことが無いので)
Chromeを二つ起動しなきゃいけないのはダサいですが，動画の上に字幕を付けるとかだとまたさらにextensionみたいなものを作らないといけないとかありそうなので，今回はここまでということで...
Windowsで開発に使用するツールをまとめました

# まっさらなWindowsを渡された
Linuxサーバ(C言語)開発をするにも関わらず、作業端末としてまっさらなWindowsを渡されました。
せっかくなので、ひとつひとつ開発に必要なツールを調べながら集めてインストールしたので、
まとめました。

## 圧縮・解凍
中身を気にしないで圧縮・解凍するケースが多いので`Lhaplus`を愛用していました。
最近では7zも扱うことが増え`7-Zip`も使ったりしてましたが、
[**PeaZip**](http://www.peazip.org/)が優秀ですね。しばらく使います。

## 無料Office
Word・Excelで資料が多く作られているので、Officeが欲しい。
「作業するからライセンスちょうだい」とは言えないので
無料Officeとして[**LibreOffice**](https://ja.libreoffice.org/)を使用します。

PDFは、本家[**Adobe Acrobat Reader DC**](https://get.adobe.com/jp/reader/enterprise/)を使用します。

## バージョン管理ツール
とりあえず[**Git for Windows**](https://gitforwindows.org/)を入れます。
私は[**TortiseGit**](https://tortoisegit.org/)をGUIツールとして入れています。

## Diffツール
[**WinMerge**](http://winmerge.org/?lang=ja)以外におすすめレベルのツールを知らないです。
`TortiseGit`の後でインストールすると差分・マージ連携までやってくれます。

## 端末エミュレータ
このあたりから作業内容によって必要なものが変わります。
冒頭にも記載しましたがメイン作業はLinuxサーバ開発なのであしからず。

端末エミュレータは`Tera Term`をずっと使っていましたが、最近は[**Rlogin**](http://nanno.dip.jp/softlib/man/rlogin/)にハマってます。
多数の接続先も管理しやすいですし、
「ファイル転送」の機能(SFTP)があるので、別途ファイル転送ツールを用意する必要がありません。
端末エミュレータはビルド、ログ参照をメインに使用しています。

## エディタ
端末エミュレータ使ってvi叩いてもいいのですが、最近は[**Visual Studio Code**](https://code.visualstudio.com/)を使用しています。

拡張機能として以下を入れています。
・ [Japanese Language Pack for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=MS-CEINTL.vscode-language-pack-ja)
・ [C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)
・ [SFTP](https://marketplace.visualstudio.com/items?itemName=liximomo.sftp)もしくは[SSH FS](https://marketplace.visualstudio.com/items?itemName=Kelvin.vscode-sshfs)
　 Windows上にファイル転送するorしないで使い分けています。 
・ [Uncrustify](https://marketplace.visualstudio.com/search?term=Uncrustify&target=VSCode&category=All%20categories&sortBy=Relevance)
・ [GitLens](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
・ [GitHistory](https://marketplace.visualstudio.com/items?itemName=donjayamanne.githistory)
・ [Doxygen Documentation Generator](https://marketplace.visualstudio.com/items?itemName=cschlosser.doxdocgen)

## SQL開発
[**A5:SQL Mk-2**](https://a5m2.mmatsubara.com/)を使用しています。

## ソケットテスト
[**SocketDebugger**](https://www.udom.co.jp/sdg/freeedition.html)でバイナリ送受信してます。

## 仕様書作成
[**Graphviz**](http://www.graphviz.org/download/)と[**Doxygen**](http://www.doxygen.nl/download.html)で出力させます。
Wordとかで書いてもプログラムと同期が取れてないこと多いので…

## 最後に
なんだかんだで、集めて入れるだけで１時間以上かかっちゃうときが多いです。
サイレントインストールできるようにしときたいですね。
Dockerエラーと立ち向かうPart1

# Docker難しいけど便利
初投稿です。よろしくお願いします。Docker何にもわからずこれはやばいと思って勉強し始めました。
Dockerを勉強し始めてはや1週間たちました。記事の内容（ボリューム）は少ないですがこつこつDockerの記事をあげていこうと思います。今回はDockerのエラー対応

## エラー内容
以下のエラーが出ました。

```
ERROR: for chap07_webserver_1  Cannot start service webserver: driver failed programming external connectivity on endpoint chap07_webserver_1 ...
ERROR: for webserver  Cannot start service webserver: driver failed programming external connectivity on endpoint chap07_webserver_1 ...
Bind for 0.0.0.0:80: unexpected error (Failure EADDRINUSE)
ERROR: Encountered errors while bringing up the project.
```

docker-compose.ymlで定義したポート番号80を使ってwebserverを立ち上げようとしたところこのエラーが出ました。簡単な話、このポート番号で何かしら使用されているというわけです。

# 解決方法
上記原因でも述べましたが、このポート番号で使用しているプロセスを削除しましょう。

```
# 僕の場合はポート80をしているので80で実行しました
$ sudo lsof -i:80

COMMAND   PID   USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
nginx      60   root    6u  IPv4 0xdd8ec12c4a4ab873      0t0  TCP *:http (LISTEN)
```
上の表から、nginxが使用されていますね。正直いつ起動したかわかりませんが。。
とりあえず消しましょう。

```
# 占領箇所を特定したら、そのプロセスをkillする
$ sudo kill 80
```
再度、```docker-compose up --build```するとうまくいきました。

最初は「再起動すればうまくいくだろう！！！」と思ってましたが、何一つエラーが消えないので。。メモがわりに投稿しました。

以上です。ありがとうございました。
Rubyで大きい数字に対して億万などの単位をつける方法

Rubyで大きい数字に対して億万などの単位をつける方法を開設します。

## Rubyで大きい数字に対して億万などの単位をつける方法
次の様な関数を定義して使用すると良いです。

```ruby
def to_ja(num)
  num = num.to_s
  if num.length > 8
    "#{num[0..-9].gsub(/^0+/, '')}億#{num[-8..-5].gsub(/^0+/, '')}万#{num[-4..-1].gsub(/^0+/, '')}"
  elsif num.length > 4
    "#{num[0..-5].gsub(/^0+/, '')}万#{num[-4..-1].gsub(/^0+/, '')}"
  else
    num
  end
end

```
## 終わりに
私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
        [無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話](https://note.com/kenroda/n/n814347fbdcd7)
Spring Boot おぼえがき

いまさらながら Spring Boot に触れてみたので備忘録として理解したことをメモ。

# Hello World的な
とりあえず本家の [Getting started](https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/html/getting-started.html#getting-started-introducing-spring-boot) を読んでみる。

> Spring Boot makes it easy to create stand-alone, production-grade Spring-based Applications that you can run.

__スタンドアロンで商用レベルのSpringベースのアプリを動かせるよ！__　って感じですかね。

## 必要なもの
* Java（あたりまえですが）
* Maven（ビルドツール）　※GradleでもOK。

## 動かし方
いくつかのやり方があるが、__いずれもWebサーバ＋アプリサーバを起動してからデプロイすることなく、ワンタッチでアプリ起動までこぎつけている。__この辺が「スタンドアロン」という感じ？


### Spring Boot CLI で起動
CLIをダウンロードし、binフォルダの中にあるsprint.batを使って、Javaで書いたアプリ（クラスファイル）を起動してみる。

```
spring run 作成したクラスファイル
```

で起動するだけで、Webサーバ＋アプリサーバが起動して localhost:8080 で Hello World が出る。

### mvn spring-boot:run で起動
pom.xmlに必要な定義を書き、コントローラ的クラスを書いて Maven からアプリを起動してみる。

```
mvn spring-boot:run
```

でビルドされて、Webサーバ＋アプリサーバが起動して localhost:8080 で Hello World が出る。

### Executable Jar で起動
pom.xmlに必要な定義を書き、コントローラ的クラスを書いて Maven で jar を作成しアプリを起動してみる。

```
mvn package
java -jar （Jarファイル）
```

で、Webサーバ＋アプリサーバが起動して localhost:8080 で Hello World が出る。
この Executable Jar 、どうもそのままサービス起動停止用バッチファイルとかにも使えるらしい。
参考 [Spring Boot の Fully Executable Jar はなぜ動くのか](https://creasys.org/rambo/articles/5a5e94b4b7d6a9ba61f7)


# RESTfulなWebAPIおためし
[Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/)を読み進める。

## 基本構成
RESTfulなWebAPIの実装サンプルを通して基本構成を理解。

* representation  
いわゆるPOJOでOK。JSONへの変換はJackson2を利用して  
`MappingJackson2HttpMessageConverter`クラスが自動的にやってくれる。
* controller
  * `@RestController`  
  クラスに設定。コントローラとしての役割を持たせるためのアノテーション。  
  * `@RequestMapping`  
  メソッドに設定。サーブレットパスとメソッドとのマッピング。  
  `@RequestMapping(method=POST)`のようにメソッド指定しないと、全メソッド共通でマッピングする。  
  * `@RequestParam`  
  クエリパラメータとのマッピング。defaultValue=xxx で指定されない場合のデフォルト値の指定が可能。  
* application  
executableなjarとして動かす場合にはmain()を持ったApplicaitonクラスを作成する。  
  * `@SpringBootApplication`  
  `@EnableAutoConfiguration`と`@ComponentScan`と`@Configuration`をまとめて実装するためのアノテーション。
  * `@EnableAutoConfiguration`  
  フツーのSpringで`<bean id="xxx">`してたあの定義ファイルの役割をやってくれるためのアノテーション。  
  Bean定義を書かなくてもアプリが動いちゃうってことは、これがSpring-bootの嬉しさのキモ？  
  (参考) [Spring BootのAutoConfigureの仕組みを理解する](https://qiita.com/kazuki43zoo/items/8645d9765edd11c6f1dd)  
  
## 実行
上記を実装して`mvn spring-boot:run`でサーバ起動。  
`http://localhost:8080/xxxxx` (xxxxxはリソース名) にアクセスすると、  
コントローラのマッピングされたメソッドが呼び出されJSONが返却される。

## 気づいたこと
* ↑のRESTfulなサンプルアプリを作成して`mvn spring-boot:run`したら、  
`http://localhost:8080/greeting`でレスポンスが表示されるようになったが、  
Getting Started で作成済だった`Example.java`が動かなくなった。  
（`http://localhost:8080/`でHello World!が出なくなった）  
⇒クラスの階層が以下のようになっていた。  
`project/src/main/java/Example.java`  
`project/src/main/java/hello/Application.java`  
Example.javaを、src/main/java/helloパッケージ配下に移動したら、動作した。  
`@ComponentScan`が自身より上位の階層をスキャンしないから…だろうか。（自信なし）  

# 今後
[公式のガイド的なページ](https://spring.io/guides/)をひたすら読んでいく。
理解したことを追記していく。
Mac，Ubuntuのプロンプト設定[折り返しが変]

# はじめに
最近，Macbook Proを購入して色々とセッティングをしています．その過程で，terminal環境をカッコよくしようと思って，Promptを自分好みに変更しました．

本記事では，Macでのプロンプトの設定とその際に直面した”折り返しがおかしい”という問題の解決策も紹介していきます．
並行して使っているUbuntuでも同じ問題が発生し，この方法での解決を確認しました．

# TL;DR
最終的には以下のようになりました．結果だけ欲しい方はそのままコピーすると良いと思います．

```~/.bashrc
GREEN="\[\e[1;32m\]"
PURPLE="\[\e[1;34m\]"
COLOR_RESET="\[\e[0m\]"
export PS1="${GREEN}\u ${PURPLE}\w ${GREEN}$ ${COLOR_RESET}"
```

# Macで`~/.bashrc`が読み込まれない場合
Macでの初期状態のプロンプトは`/private/etc/bashrc`に記述されています．PS1の書き方は下で紹介します．

これは，`~/.bash_profile`に記述すると紹介されているサイトがあったのですが，できなかったため`~/.bashrc`に記述しました．
ちなみに，Macでは初期設定では`~/.bashrc`を読み込まないようになっているらしく，`~/.bash_profile`を以下のように作成する必要があります．

```~/.bash_profile
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
```

# PS1の書き方
プロンプトの設定の基本は先ほど記述した
```prompt base
export PS1=""
```

ですが，書ける文字は決まった文字だけでなく，`ユーザ名`や`パス`，`時刻`などもあります．
それらを表示するためにはエスケープシーケンス(?)を使う必要があります．使用できる文字は以下のものがあります．
Macでバックスラッシュを入力するのは，`Option + ¥`です．

|文字|表示されるもの|
|---|---|---
|\\u|ユーザ名|
|\\w|カレントディレクトリのパス|
|\\W|カレントディレクトリ名|
|\\d|日付|
|\\D|時間|
|\\h|ホスト名(ドメインなし)|
|\\H|ホスト名|
|\\j|起動しているジョブ数|
|\\I|仮想端末の番号|
|\\n|改行(LF)|
|\\r|改行(RL)|
|\\s|シェル名|
|\\t|時刻（１２時間表示）|
|\\T|時刻（２４時間表示）|
|\\@|時刻（１２時間表示）|
|\\A|時刻（２４時間表示）|
|\\v|bashのバージョン|
|\\V|bashのバージョン|
|\\!|history上のコマンド番号|
|\\#|コマンド番号|
|\\$|rootでは`#`,userでは`$`|
|\\nnn|8進数表示|
|\\\\|`\`|
|\\[|ターミナル操作のシーケンス文字列の開始|
|\\]|ターミナル操作のシーケンス文字列の終了|

私は

    [username] [path] $ [command]

というプロンプトにしたかったため，`~/.bashrc`には以下のように記述しました．（上のものと同じ）

```:.bashrc
GREEN="\[\e[1;32m\]"
PURPLE="\[\e[1;34m\]"
COLOR_RESET="\[\e[0m\]"
export PS1="${GREEN}\u ${PURPLE}\w ${GREEN}$ ${COLOR_RESET}"
```
# 長いコマンドを入力する時の折り返しがおかしい！！
これが一番苦戦したのですが，「ここで初めてPS1を設定したよ」という方は先ほどのPS1の例では問題解決後のものを紹介したので，見なくて大丈夫です．

## おかしい挙動
折り返しの挙動がおかしいというのは，長いコマンドを入力していると，ある程度までプロンプトの右に表示されたら同一行の一番左に戻ってプロンプトをかき消してしまう状態です．

## 対策内容
ネットで調べると，エスケープシーケンスを`\[\]`で囲む必要があるみたいです．
その問題が発生した時点では`.bashrc`は以下のようになっていました．

```:.bashrc(修正前)
GREEN="\e[1;32m"
PURPLE="\e[1;34m"
COLOR_RESET="\e[0m"
export PS1="${GREEN}\u ${PURPLE}\w ${GREEN}$ ${COLOR_RESET}"
```

エスケープシーケンスを`\[\]`で囲んだら解決しました．

```:.bashrc(修正後，先ほどのものと同じ）
BOLD_GREEN="\[\e[1;32m\]"
BOLDPURPLE="\[\e[1;34m\]"
COLOR_RESET="\[\e[0m\]"
export PS1="${GREEN}\u ${PURPLE}\w ${GREEN}$ ${COLOR_RESET}"
```

# おまけ
先ほど載せたものは自分で使う緑と紫しか色を設定していませんでしたが，他の色の設定したものも以下に紹介しておきます．必要ならコピーして使ってください．

```:PromptColorPreference
BLACK="\[\e[0;30m\]"
RED="\[\e[0;31m\]"
GREEN="\[\e[0;32m\]"
YELLOW="\[\e[0;33m\]"
BLUE="\[\e[0;34m\]"
PURPLE="\[\e[0;35m\]"
CYAN="\[\e[0;36m\]"
WHITE="\[\e[0;37m\]"
BOLD_BLACK="\[\e[1;30m\]"
BOLD_RED="\[\e[1;31m\]"
BOLD_GREEN="\[\e[1;32m\]"
BOLD_YELLOW="\[\e[1;33m\]"
BOLD_BLUE="\[\e[1;34m\]"
BOLD_PURPLE="\[\e[1;35m\]"
BOLD_CYAN="\[\e[1;36m\]"
BOLD_WHITE="\[\e[1;37m\]"
UNDER_BLACK="\[\e[4;30m\]"
UNDER_RED="\[\e[4;31m\]"
UNDER_GREEN="\[\e[4;32m\]"
UNDER_YELLOW="\[\e[4;33m\]"
UNDER_BLUE="\[\e[4;34m\]"
UNDER_PURPLE="\[\e[4;35m\]"
UNDER_CYAN="\[\e[4;36m\]"
UNDER_WHITE="\[\e[4;37m\]"
BACK_BLACK="\[\e[30m\]"
BACK_RED="\[\e[31m\]"
BACK_GREEN="\[\e[32m\]"
BACK_YELLOW="\[\e[33m\]"
BACK_BLUE="\[\e[34m\]"
BACK_PURPLE="\[\e[35m\]"
BACK_CYAN="\[\e[36m\]"
BACK_WHITE="\[\e[37m\]"
COLOR_RESET="\[\e[0m\]"
```
SNATとDNATの設定方法

LinuxにおけるSNAT、DNATの設定方法について確認したのでメモ。
前提としては、NAT用ルータとしてではなくパケット送信する端末としての設定である。
よく使うことが想定されるのは[1-1]及び[2-1]である。

# 環境

```shell
[root@SYSLOG02 ~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
[root@SYSLOG02 ~]# uname -a
Linux SYSLOG02.strike-lab 3.10.0-862.9.1.el7.x86_64 #1 SMP Mon Jul 16 16:29:36 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
```

# 1. SNAT（送信元IPアドレスの変換）
## 1-1. 特定の通信先に対し、送信元のアドレスを変換する
宛先IPアドレスが[192.168.1.31]であった場合、送信元IPアドレスを[192.168.1.254]に変換する

```shell
[root@SYSLOG02 ~]# iptables -t nat -A POSTROUTING -d 192.168.1.31 -j SNAT --to-source 192.168.1.254
```
### 想定される利用シーン
システム連携先からNAT用アドレスを払い出され、NATしないといけないとき

## 1-2. 送信元が特定のIPである場合、送信元のアドレスを変換する
送信元IPアドレスが[192.168.1.32]であった場合、送信元IPアドレスを[192.168.1.254]に変換する

```shell
[root@SYSLOG02 ~]# iptables -t nat -A POSTROUTING -s 192.168.1.32 -j SNAT --to-source 192.168.1.254
```

### 想定される利用シーン
送信元IPアドレスを偽装したいとき（UDP限定）。
TCPの場合にこれを実行してしまうと3wayハンドシェイクを行う際におかしなことになる。

# 2. DNAT（宛先IPアドレスの変換）
## 2-1. 特定の通信先に対し、宛先のアドレスを変換する
宛先IPアドレスが[192.168.1.31]であった場合、宛先IPアドレスを[192.168.1.254]に変換する

```shell
[root@SYSLOG02 ~]# iptables -t nat -A OUTPUT -d 192.168.1.31 -j DNAT --to-destination 192.168.1.254
```
### 想定される利用シーン
グローバルIPアドレスを有するホストに対し通信をするシステムなどを検証するとき。
通信先のシステムをプライベートIPアドレスを有する端末で作成し、そのアドレスにNATさせたり。

## 2-2. 送信元が特定のIPである場合、宛先のアドレスを変換する
送信元IPアドレスが[192.168.1.32]であった場合、宛先IPアドレスを[192.168.1.254]に変換する

```shell
[root@SYSLOG02 ~]# iptables -t nat -A OUTPUT -s 192.168.1.32 -j DNAT --to-destination 192.168.1.254
```
### 想定される利用シーン
暫定的にすべての通信先を1箇所に向けたいとき。
[AWK] 最大値、最小値、パーセンタイルの集計

# モチベーション
パーセンタイルを出したいとき、
Rなら

```r
score <- seq(0,100)
summary(score)
quantile(score, 0.5)
```
などで一発ですが、これを**AWK**でやってみました。

```sh
seq 1 100 |
awk 'BEGIN{min="inf"}{
    if(max<$1) max=$1;
    if(min>$1) min=$1;
    percentile[NR]=$1}
    END{asort(percentile);
    print max,
    percentile[int(NR*0.75)],
    percentile[int(NR*0.5)],
    percentile[int(NR*0.25)],
    min
}'

```

# 工夫したところ
ついでのつもりでやった最小値で苦労しました…

`min`は何かしら入力データの最小値よりも大きな数値を指定しないといけないのですが、
具体的な数値を入力するには入力データの最大値がわかっていないといけません。
これは面倒なので取りうる値の最大値である`"inf"`を代入することにしました。

# 追記

`asort`がGNU拡張のため, POSIX準拠は以下のようになります. 

```sh
yes | head -n 100 | awk '{print NR}' | # seqコマンドのPOSIX代替
sort -n |
awk 'BEGIN{min="inf"}{
    if(max<$1) max=$1;
    if(min>$1) min=$1;
    percentile[NR]=$1}
    END{
    print max,
    percentile[int(NR*0.75)],
    percentile[int(NR*0.5)],
    percentile[int(NR*0.25)],
    min
}'

```
配列(1次元,2次元)と辞書

先日WinActorの配列と辞書を使ったシナリオを作ったが、
その説明で困ったので、説明資料として作成してみる。

# まず配列
はっきり言えば、Excelを思い浮かべれば完了
A列しかないのが1次元配列
列がB列以降もあるのが2次元配列
## 1次元配列
| A:日付 |
|:-:|
|2019/3/18|
|2019/3/19|
|2019/3/20|
どう使うのかは、どう使えるのかはアイデア次第。

## 2次元配列
| A:日付 | B:開始日 | C:終了日 | D:前週の日曜日 | E:曜日 |
|:-:|:-:|:-:|:-:|:-:|
|2019/3/18|2019/3/18|2019/3/22|2019/3/17|月|
|2019/3/19|2019/3/19|2019/3/23|   |火|
|2019/3/20|2019/3/20|2019/3/24|   |水|
|2019/3/21|2019/3/21|2019/3/25|   |木|
もう殆どExcel

# 続いて辞書
これは殆ど1次元配列
但し、通常の配列が行番号や列番号(2次元配列の場合)で指定するのに対して、名前(技術的にはキー値と呼びます)で指定できるのが特徴。
また、設定した値が変更できないことも特徴。

| A:日付 |
|:-:|
|2019/3/18|
|2019/3/19|
|2019/3/20|
このような１次元配列で3/19の行を参照する場合には行番号の1で参照する。

仮に以下のような日付と曜日を関連付けた２次元配列があったとする。

| A:日付 | B:曜日 |
|:-:|:-:|
|2019/3/18|月|
|2019/3/19|火|
|2019/3/20|水|

上記の配列で2019/3/19の曜日を探す場合には、行単位で繰り返し、
配列[0][A列]は2019/3/18だから違う
配列[1][A列]が2019/3/19だからこの行
つまり、曜日は配列[1][B列]として自分で繰り返し処理が必要になる。

しかし辞書の場合には

| キー:日付 | データ:曜日 |
|:-:|:-:|
|2019/3/18|月|
|2019/3/19|火|
|2019/3/20|水|

の時に辞書[2019/3/19]とすると火と値が検索できる。
自分では繰り返し処理も記入しないで良いので、処理がスッキリします。
思い浮かべるのはA/B列があるExcelで間違い無いですが、自分で行方向に検索処理を作らなくてもさっと検索してくれる。
ちなみに、キーの値は重複(同じ値)を持つことはできません。
「とりあえずでクラスを作るのはやめよう」という話

「オブジェクト指向完全に理解したマン」は誰もが通る道です。オブジェクト指向にすれば、悪夢のようなグローバル変数スパゲティや、どんなメンバを持ってるのかさっぱりわからない継承無間地獄を生み出すことを防ぐことができます。

しかし、新規でコードを作ることになったとき「**とりあえずクラス作っとこ**」って思ってませんか？

#クラスの落とし穴
##単なる「グローバル変数もどき」を作ってるだけではないですか？
オブジェクト指向を使えば、確かに関数のスコープをクラスに閉じ込めることができます。「**これグローバル変数にしたいけど、グローバル変数はバッドプラクティスだから、クラス作ってメンバ変数にしとこう**」って思ってませんか？

```python:グローバル変数を使う例
Nx=100
#...
```

```python:mainクラスに閉じ込めた例
class main:
   #クラス変数の場合
   self.Nx=100

   #インスタンス変数の場合
   def __init__(self):
      self.Ny=100
   #...

if __name__ == "__main__":
   myobj=main()
   #...
```

javaのような純粋なオブジェクト指向言語ではこの書き方は正しいのかも知れません。ですがそういうわけでもない言語で**いちいちmainクラスを作成してインスタンス化する意味はあるのでしょうか？**if文以下を書く分コード量が増えてませんか？

##コンポジットが最強だと思ってませんか？
オブジェクト指向で書かれたライブラリも非常に多いので、ライブラリのクラスを再利用したくなることも多いと思います。そのとき、一緒に抱えるデータがあるとき、クラスにまとめたくもなるでしょう。

クラスを再利用したいとき、真っ先に思い出すのは継承ですが、**むやみな継承はメンバのありかをわからなくするので一般にはバッドプラクティスとされます**。

```python:むやみな継承
#こんなimportが書いてあると超最悪
from hogelib import *
from fugalib import *

class myclassA(myclassB):
   #引数の数をよく覚えてくださいね
   def Bmethod(self,arg1,arg2):
      #...

#---------------------------------
# 超長い記述
#---------------------------------
if __name__ == "__main__":
   myobj=myclassA()

   myobj.Bmethod(1) #これってどこの関数呼んでるんですか？
```

これを回避するために使われるのが**コンポジット**という手法です。新たなクラスのメンバにクラスインタスタンスを持たせることで、関数名のスコープを閉じ込めることができます。OOPのバイブルとして有名なGoF本にも基本原則として「コンポジット使え」って書いてあります。

```python
class myclassA:
   def __init__(self):
      self.myobj=myclassB()
```

しかし、そんなコンポジットにもデメリットはあります。**myclassAのメソッドとしてBmethodを直接呼び出すことはできない**ことです。呼び出せるようにするには定義してやる必要があります。

```python
   def Bmethod(self,args):
      myobj.Bmethod(args)
```
この例では1つだけだったのでよかったですが、**もしmyclassBが大量のメソッドを持っていたとしても全部書き直しますか？**

#クラスにもオーバーヘッドがかかる
クラスは結構高級な機能です。高級な機能にはオーバーヘッドがかかるものです。パフォーマンスが重要な場面ではそのオーバーヘッドが命取りになることもあります。

個人的な経験ですが**クラスを作ると5分かかった処理が、バラして書くと数秒になったことがあります**。言語やコンパイラによっては最適化がうまくなされずにえげつなくオーバーヘッドがかかることもあるのです。

#果たしてそれはシステムとして再利用されうるのか？
ここまで**オブジェクト指向は万能ではない**ことを書いてきました。それでもオブジェクト指向が使われるのにはきちんとした理由があります。それは**再利用がしやすい**ということです。

コンポジットのところでmyclassAを定義するのは死ぬほど面倒だと書きましたが、逆に一度定義してしまえばmyclassAのデータ構造や処理を再利用できます。一般に再利用可能なコードはそうでないものと比べて工数がかかるものですが、再利用するときいちから書き直すよりはかかりません。

しかし、最初のmainクラスのように**一回ポッキリで再利用することもないコードを工数をかけてわざわざクラス化する必要はあるのでしょうか**。

#まとめ
クラスを使うと抽象的でエレガントなコードが書けるので、中級プログラマはついつい多用してしまいがちです。ですがその裏にはコーディング、パフォーマンスでコストもかかっているのです。**OOPを使うことはコストと再利用性のトレードオフ**なのです。

クラスを作るときは「**本当にそのクラスを再利用することがある？**」と一度問うてみてから考えましょう。
DjangoとRailsの違いをいろいろ説明

書いている人間は、お仕事でDjangoをメインにしていて、最近Railsを勉強中という感じです。
なので、バランス悪いのは許してください。

Djangoに比べるとRailsはバージョンアップごとに変化が大きいので取り逃しはかなりありそうです。
内容は気づいたたびに追加していく予定。

# 設計思想
## CoC
設定より規約ってやつ。
Railsを触れば触るほど出来た仕組みだなぁと思う。ほとんどの場合うまくいきそう。Djangoもある程度はあるけど、frameworkとして組み込まれてる感じはない。だから迷う、そして失敗する。

## mvc
大きな違いはviewのところ。
Railsは一般的なMVCアーキテクチャーで語られているが、DjangoはわざわざMVTと言っているだけあって、Templateに対する意識が強い。
Djangoとしては、Templateはエンジニアだけではなく、デザイナのような人に任せる可能性がある、だからpythonを持ち込まない、としている。
逆にRailsは積極的にエンジニアに任せようとしている気がしている。
hamlとかsassとか。


# Model関係

|比較対象  | Django | Rails|
|:-------|:-------:|:----:|
| 表名|{アプリケーション名}_{モデル名}(全部小文字)|{モデル名}(全部小文字)
|自動で付加されるカラム|id|id<br>created_at<br>updated_at|
|1対1の関係|models.OneToOneField(モデルのクラス)|has_one :{モデル名小文字}|

# Query関係
## 参照
いろいろ見てて、そもそもわかったこと。
DjangoはQuerySetという言い方しているこの仕組みは、基本的には遅延評価という仕組みが備わっている。
~~一方でRailsは基本的にはその場で実行される(たぶん)。~~
where,all,page,order,includeじゃないときはその場でSQLが実行される。
逆に、find_in_batchesのような仕組みで遅延評価に近い動きをするという感じ。
どちらにしても、気を付ければどちらでもOKだが、書き方がかなり変わってくると思う。

Djangoのfilterはwhereと似ていて、whereの戻り値はActiveRecord_Relationになるので、メソッドチェインで書ける。

|比較対象  | Django | Rails                 |
|:-------|:-------:|:---------------------:|
|pk参照1件|〇.objects.get(pk=1)    |〇.find(1)|
|pk参照複数|list(〇.objects.filter(pk__in=[1,10]))|〇.find([1,10])|
|指定なし1件|〇.objects.all()[0]|〇.take|
|最初の1件|〇.objects.first()|〇.first|
|最後の1件|〇.objects.last()|〇.last|
|最初の3件|〇.objects.order_by('id')[0:3]|〇.first(3)|
|条件一致した1件目|〇.objects.filter(age=10)[0]|〇.find_by(age: 10)|
|全件|〇.objects.all()|〇.all|
|条件-等価|〇.objects.filter(name='AAA')|〇.where(name: 'AAA')|
|条件-in|〇.objects.filter(type__in=[1,2,3]|〇.where(type: [1,2,3])|
|範囲指定|〇.objects.filter(pub_date__range=(start_date, end_date))|〇.where(pub_date: start_date..end_date)|

# Form関係

とは書いたものの、Djangoでは明確にFormとModelは分離されているが、Railsは基本的に概念としては存在してない。
ただ、DjangoのFormの要素は、Modelを利用して表現している場合が多そう。要はValidationとかModelへの加工だったりするので、上手く色々継承して表現するっぽい。
Railsで言う所のViewを省略して書ける機能もDjangoのFormにはあるが、それはRailsにはなく、Gemを使うかHelperの何かしらを使う感じ。
PlantUML Web 版で UML を作って Slack に貼る

PlantUML Web 版で UML を作って Slack に貼ってみます。

* [PlantUML Web Server](http://www.plantuml.com/plantuml/uml/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000)

```
@startuml
title: 肉を食べるバランスループ
(肉を食べる) --> (旨さに興奮する)
(旨さに興奮する) --> (汗をかく)
(汗をかく) --> (体重): -
(肉を食べる) --> (体重): +
@enduml
```

![スクリーンショット_031319_110007_PM.jpg](https://qiita-image-store.s3.amazonaws.com/0/43480/98204592-7b51-6e68-bcc8-3dba96c8f0d1.jpeg)

## Slack にはる
生成結果の画像URL ( http://www.plantuml.com/plantuml/png/SoWkIImgAStDuIh9BCb9jL9uqTJvk6dIoyNp7pVkVDpK_RXvmkFcbO-RDpzkslcuUVNZvZsFcwTpQQ2fqbJGrRLJq7WsVSNZngcF6rU_wEXukdJTuyQP83akRE88FHkd0qrwtDZzkB5Vamk52rNnPE_ab-szcbOAkXZseglGvd98pKi1-WO0 ) をSlackに貼ります

![スクリーンショット_031319_110114_PM.jpg](https://qiita-image-store.s3.amazonaws.com/0/43480/e3a313d0-6472-66bc-222e-c63f06f4ec75.jpeg)
[備忘録]NodeMCUにファームウェアをFlashする


# NodeMCUにファームウェアをFlashする
まずFirmwareを得る
[ESP8266のフォームウェア](https://www.espressif.com/en/support/download/at?keys=esp8266)

次にFlash用ソフトを得る
Toolsの中からFlash Download Tools (ESP8266 & ESP32)をダウンロード(windowsの場合)
[Flash Download Tools (ESP8266 & ESP32)](https://www.espressif.com/en/products/hardware/esp8266ex/resources)
readme.txtを参考にアドレスも書き込んでください。


## 注意点
以下の画像の左下に３つほどボタンがありますが、まずERASEで既にあるファームウェアを削除してください。
それについで、STARTを押すと成功します。


![WS000013.jpg](https://qiita-image-store.s3.amazonaws.com/0/294146/3c6dac38-92c8-31c8-8f50-2ff356ed1185.jpeg)
laravelのサービスクラスでデータを取りたいとき

ファットコントローラー過ぎて、データ取得ロジックをどこかにやりたい。
そんなときには、サービスクラスを使うといいらしい。
実際にサービスクラスを作成し、データを取得してみた。

データを取得するのは1メソッドを呼ぶだけだが、他の４つのファイルに設定を書く必要がある。
さらに、classを作成するので

```bash
$ composer dump-autoload
```
をたたく必要がある。


```php:app/Services/HogeService.php
<?php

namespace App\Services;

use App\Models\Hoge;

class BookKeepServices
{
    public function getHoge ()
    {
        return Hoge::all();
    }
}
```

```bash
# 新しくサービスプロバイダを作りたいときはこちら。今回は元からあるものを編集する
$ php artisan make:provider RiakServiceProvider
```


```php:app/Providers/AppServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Services\HogeServices;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('HogeServices', HogeServices::class);
    }
}
```
```php:app/Facades/HogeService.php

<?php

namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class BookKeepServices extends Facade
{
    protected static function getFacadeAccessor() {
        return 'HogeServices';
    }
}
```

```php:config/app.php
 'aliases' => [
        // 中略
        'HogeServices' => App\Facades\HogeServices::class,
```

```php:app/Http/Controllers/HogeController.php
$hoges = HogeServices::getHoge();
```

ブロックチェーンエンジニアのブログ
【Laravel】サービスクラス作成手順
https://daiki-sekiguchi.com/2018/08/31/laravel-how-to-make-service-class/
Go言語でMySQL の基本的操作（SELECT、UPDATE、INSERT）を行う

#実行環境
環境はMacにインストールされたGo1.11.2、MySQLは8.0.15です。

####MySQLコネクション
sqlパッケージのOpen関数に、ユーザ名:パスワード@IPアドレス/データベース名の順で記述する。Open関数の戻り値はsql.DB。また、sqlパッケージとmysqlドライバーパッケージをインポートする。

```go
package main

import (
	"fmt"
	"log"
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
)


func main() {
	db, err := sql.Open("mysql", "forge:forge@tcp(127.0.0.1:3333)/webapp")
	if err != nil{
		log.Fatal("db error.")
	}
	defer db.Close()
}
```

####SELECT
db.Query()にでSELECT文を渡す。rowsに結果セットが格納されるため、rows.Next()で一行一行処理を行う。Scan()に変数ポインタを渡し、DBの結果をセットする。また、引数にはSELECTしたカラム数分指定する必要があるので少し注意が必要。User構造体の変数に結果をセットしている。

```go
	rows, err := db.Query("select id,code,email,name,password from tbl_users")
	if err != nil {
		log.Fatal(err)
	}
	var userResult []User
	for rows.Next() {
		user := User{}
		if err := rows.Scan(&user.id,&user.code,&user.email,&user.name,&user.password); err != nil {
			log.Fatal(err)
		}
		userResult = append(userResult,user)
	}
	for _,u := range userResult{
		fmt.Println("code: ", u.code,", email: ", u.email,
			", name: ", u.name,", password: ",u.password)
	}
```

####INSERT
Prepare()にINSERT文を渡して、Exec()にプリペアードステートメントを指定してSQLを実行する。

```go
	// insert
	ins, err := db.Prepare("INSERT INTO tbl_users(code,email,name,password) VALUES(?,?,?,?)")
	if err != nil {
		log.Fatal(err)
	}
	ins.Exec("golang-2019", "golang+001@gmail.com","Jhon","123456")
```

####UPDATE
ほぼ、INSERTと同様。Prepare()に文を渡して、Exec()にプリペアードステートメントを指定してSQLを実行する。

```go
	//update
	upd, err := db.Prepare("UPDATE tbl_users set password = ? where name = ? ")
	if err != nil {
		log.Fatal(err)
	}
	upd.Exec("67890", "Jhon")
```

#雑感
DB操作は他の言語とほぼ変わらなく問題なく利用出来そう。SELECTの場合は、構造体（エンティティ）に値をセット、リポジトリクラス（UserRepository)やDBアクセス用のファサードを用意すると良さそう。

###参考
http://www.golangprograms.com/example-of-golang-crud-using-mysql-from-scratch.html
https://teratail.com/questions/110152
https://www.pospome.work/entry/2017/02/18/172307
https://github.com/golang/go/blob/master/src/database/sql/example_test.go
pythonのmockでwith句を使ったテストを実行する

mockを使ったテストを行っていて、検索してもなかなか解決策が見つからなかったので投稿。

結局公式ページから推測して結論を出しました。

# With句で使うClass
まずはテスト対象となるWith句を使える形にしたclassのサンプル

```python:sampleblock.py
class SampleBlock():
    def __enter__(self):
        pass

    def get_hoge(self):
        return "hoge"

    def __exit__(self, exc_type, exc_value, tb):
        pass
```
そして使う側のサンプル。
with句でくくりながらもそれ自身にメソッドが存在して、引数によってそれが実行されるかどうかが決まるみたいな使われ方。

```python:runner.py
import sampleblock as sb

def hogehoge(flg):
    with sb.SampleBlock() as sampleblock:
        if flg:
            sampleblock.get_hoge()
```
# 実際のテストコード
引数によって、このsampleblockのget_hogeが呼び出されたかどうかを確認するチェックを行ったときどうするか？という問題でした。
もう一つ条件があって、enterとかexitに通信関係の仕組みが入っていてそこはmockにしておきたいというわがままの叶えたい。

```python:test_hogehoge.py
import unittest
from unittest.mock import patch 

import runner

class HogeHogeTest(unittest.TestCase):
    def test_true(self):
        with patch('sampleblock.SampleBlock') as mock_obj:
            runner.hogehoge(true)
            self.assertTrue(mock_obj.return_value.__enter__.return_valuecalled)

    def test_false(self):
        with patch('sampleblock.SampleBlock') as mock_obj:
            runner.hogehoge(false)
            self.assertFalse(mock_obj.return_value.__enter__.return_valuecalled)
```

callをいったん出力して導き出した答え。
ちょっとこれはわかりづらい。with句特有の動きなのかどうかは検証が必要ですね。
実際のプログラムを書き換えて投稿しているので、間違っていたら指摘お願いします。
daemontools のインストール

# 概要
https://cr.yp.to/daemontools/install.html
に沿ってインストールしたところ、次のようなエラーが出てうまく行かなかった。
（centos7）

```
./load envdir unix.a byte.a
/usr/bin/ld: errno: /lib64/libc.so.6 内セクション .tbss の TLS 定義は envdir.o 内の非 TLS 参照と一致しません
/lib64/libc.so.6: シンボルを読み込めませんでした: 不正な値です
collect2: エラー: ld はステータス 1 で終了しました
make[1]: *** [envdir] エラー 1
make[1]: ディレクトリ `/package/admin/daemontools-0.76/compile' から出ます
make: *** [daemontools] エラー 2
```

# 解決策
以下のようにファイルを書き換えて実行すると、うまくいった。

```
[root@localhost ~]# cat /package/admin/daemontools/compile/conf-cc
gcc -O2 --include /usr/include/errno.h

This will be used to compile .c files.
```
yumコマンドが使えない際の対処法


## CentOS6における対処法
CentOS6でyumが使えない場合、yumにロックが掛かっていることが多い。
よって以下のコマンドをサーバー上で実行すれば解消される。

```
rm -f /var/run/yum.pid
```


## CentOS7における対処法
CentOS7でこの問題が起きた場合は少々面倒くさい。まずは上記のコマンドを試してほしい。それでも解決できない場合にはDNSが未設定である可能性が高い。

よって以下のコマンドでresolv.confを編集する。

```
vi /etc/resolv.conf
```

初期時点でDNSに関する設定を行っていない場合、ファイルは存在するが何も記述されていないはずである。
以下のように追記しよう。

```:resolve.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
```

これでDNSを設定することに成功した。


# 追記
CentOS6系でyumによるインストールが失敗する時は、

```
yum clean all
```

でキャッシュを消すと直るケースもあるようだ。

　

また、今回設定するのに使用した以下のDNSサーバーは、無料で使えるGoogle Public DNSである。

```
nameserver 8.8.8.8
nameserver 8.8.4.4
```

nkojimaさん、ご指摘ありがとうございました。

#終わりに
ファイル名を誤ってvi/vimコマンドを使いファイルを開いてしまった場合には「:q!」で保存せずに強制的に終了すれば問題ない。
CS193p class note - 7 Multiple MVCs, Timer and Animation

###### Memo:
- Split view can only do its thing property on iPad/iPhone+
- Segues: `Show Segue`(will push in a Navigation Controller, else Modal), `Show Details`(will show in Detail of a Split View or will push in a Navigation Controller), `Modal Segue`(take over the entire screen while the MVC is up), `Popover Segue`(make the MVC appear in a little popover window)
- Segues always create a new instance of an MVC


```swift
// preparing for a segue
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let identifier = segue.identifier {
        switch identifier {
        case "Show Graph":
            if let vc = segue.destination as? GraphViewController {
                // set up GraphViewController
            }
        default: break
        }
    }
}
```
- Timer: Used to execute code periodically

```swift
private weak var timer: Timer?
timer = Timer.scheduledTimer(withTimeInterval: 2.0, 
                                      repeats: true,
                                        block: { 
    timer in
    // your code here
})
```
- we stop the timer by calling `timer.invalidate()`. If your pointer to the timer is `weak`, it will be set to nil at this point. This is nice because an invalidated timer like this is no longer of any use to you.
- It may help system performance by setting the timer's property `tolerance`
- UIView animation: changes to certain UIView properties can be animated over time. (frame/center, bounds, transform, alpha, backgroundColor)
macOSターミナルでssh接続できない場合の原因と対処法

# ssh接続ができなくなる原因
```ssh-keygen -A```を実行したため。

# エラー内容


```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the XXXXXX key sent by the remote host is
SHA256:xxxx.
Please contact your system administrator.
```

# 対処法
以下のコマンドをターミナル上で打ち込めば解消できる

```
ssh-keygen -R [IPアドレス]
```

再びssh接続すれば問題ない
Screenshot for https://stackoverflow.com/questions/55142212

This is additional information to the below page.
https://stackoverflow.com/questions/55142212

# First Time
`greeting` variable is visible.
![image.png](https://qiita-image-store.s3.amazonaws.com/0/268550/19145d58-fc53-5e87-017b-66642a37e79b.png)

# After reloaded.
`greeting` variable is not visible.

![image.png](https://qiita-image-store.s3.amazonaws.com/0/268550/2c65c1cc-4e4b-1c9f-3de0-9194810115e2.png)
プログラミング初学者が独学のモチベ上がるブログ

###何回も離脱しては戻る初学者向け

progateもドットインストールも、youtubeやniconicoで丸コピで何か動かした経験もあるのにいまだにプログラミングができない状態。
単純に数が足りないのか、邁進邁進という気持ちにさせてくれました。
http://www.dt30.net/gachinko/?p=573#PHPRuby2
PRML演習問題1.3

![1章 序論-6.jpg](https://qiita-image-store.s3.amazonaws.com/0/221435/e0b8b6a6-77e6-f140-988f-f6a4b2d5b6ea.jpeg)
![1章 序論-7.jpg](https://qiita-image-store.s3.amazonaws.com/0/221435/3ccbf386-3655-e57a-d1c9-e4475ce97848.jpeg)
【Android】SoftEther Server へ Android で接続【L2TP/IPsec】

[【Centos7】SoftEther Server 構築手順【L2TP/IPsec】](http://qiita.com/nobu-maple/items/61f51baa9965dbd6fb04)で構築したVPNサーバへAndroidから接続する手順です

特にアプリをインストールすることなく、Android標準機能だけで接続します



#サーバ側の設定：
　（上記記事で設定した内容のおさらい）

★１　グローバルIPアドレス：12.34.56.78　（ダミーですよ）
　　　SecureNAT：有効
　　　SecureNATのDHCP：有効
　　　L2TP over IPsec サーバー機能：有効
★２　IPsec 事前共有鍵の文字列：ipsecvpn
★３　仮想HUB名：VpnHub1
★４　ユーザ名：HubUser1
★５　ユーザパスワード：HubUser1Pass

（★部分はダミー値です、実サーバの設定に合わせましょう）

ファイアウォールでIPsecのUDP500とUDP4500を開放済み


# Androidの設定：

　設定 ->
　　無線とネットワーク ->
　　　もっと見る ->
　　　　VPN ->
　　　　　追加 ->　で、新規のVPN接続設定を追加

　※ メニュー構成はAndroidのバージョンやメーカ機種により異なります（似たような構成のはず）

```
 名前：　　適当に
 タイプ：　　L2TP/IPSec PSK
 サーバーアドレス：　　12.34.56.78　（★１の設定）
 L2TPセキュリティ保護：　（未使用）
 IPSecID：　（未使用）
 IPSec事前共有鍵：　　ipsecvpn　　（★２の設定）

 ユーザ名：　HubUser1@VpnHub1　　（★３★４の設定）
 パスワード：　HubUser1Pass　　（★５の設定）
```

この設定を保存


# Android から SoftEther VPN Server へ接続
　設定 ->
　　無線とネットワーク ->
　　　もっと見る ->
　　　　VPN 

を開いて、上記で保存した「名前」を押して

開いた画面の　［接続］　を押すと、SoftEther VPN Server へ接続できるはず
画面上部の通知領域に「鍵マーク」が出てればVPN接続できてるはずです

もしできなかった場合は、SoftEther VPN Server側のログを見てみるとよろしいかと思います

サーバのアドレスとか MaxSession とかユーザ名とかパスワードとかHub名とかIPSec事前共有鍵の文字列とか、もろもろ確認していけばつながるハズです


---

ちなみに、上記記事の[【Centos7】SoftEther Server 構築手順【L2TP/IPsec】](http://qiita.com/nobu-maple/items/61f51baa9965dbd6fb04)で構築したVPNサーバは、外部につながる設定にはなっていません
仮想HUBを物理LANへ接続していないため、外部ネットワークにはつながらないようになってます
（仮想HUBに接続した端末同士でのやり取りに限定した VPN Serverになっています）


VPN経由で外部ネットワーク（サーバを立てた地域でのネット接続）を利用したい場合はローカルブリッジを作成する際に物理LANカードに接続するように設定を行ってくださいです
cpanm でTkのビルドエラーを解決する



# 起きたこと：

実行コマンド

```console
$ cpanm Tk
```

そうすると、ログから失敗することがわかりました。

原因を追跡しました。次のmakeでエラーになりました・・・


```console
$ cd jpeg && make libjpeg.a
make[2]: ディレクトリ '/home/HogeDesu/.cpan/build/Tk-804.034-1/JPEG/jpeg' に入ります
make[2]: 'libjpeg.a' は更新済みです.
make[2]: ディレクトリ '/home/HogeDesu/.cpan/build/Tk-804.034-1/JPEG/jpeg' から出ます
make[2]: ディレクトリ '/home/HogeDesu/.cpan/build/Tk-804.034-1/JPEG/jpeg' に入ります
make[2]: 'all' に対して行うべき事はありません.
make[2]: ディレクトリ '/home/HogeDesu/.cpan/build/Tk-804.034-1/JPEG/jpeg' から出ます
make[2]: ディレクトリ '/home/HogeDesu/.cpan/build/Tk-804.034-1/JPEG/jpeg' に入ります
make[2]: *** ターゲット 'test_dynamic' を make するルールがありません.  中止.
make[2]: ディレクトリ '/home/HogeDesu/.cpan/build/Tk-804.034-1/JPEG/jpeg' から出ます
make[1]: *** [Makefile:871: subdirs-test_dynamic] エラー 2
make[1]: ディレクトリ '/home/HogeDesu/.cpan/build/Tk-804.034-1/JPEG' から出ます
make: *** [Makefile:1439: subdirs-test_dynamic] エラー 2
  SREZIC/Tk-804.034.tar.gz
  /usr/bin/make test -- NOT OK
//hint// to see the cpan-testers results for installing this module, try:
  reports SREZIC/Tk-804.034.tar.gz
```

test_dynamicをビルドできないようです。

makefileをじっくり見れば、どのソースをビルドしているかをわかるかもしれませんが、めんどくさいからしませんでした。

G先生に頼って調べても原因不明だったが、とりあえず次のコマンドを試したら成功しました。。
原因？不明と言ってるだろう💢 make libjepeg.a　のすべてが悪いです。

#やったこと：

```console
$ sudo apt-get install libjpeg-dev libpng-dev
```


EOF
markdownをpptxで変換


[Typora](https://typora.io)というmarkdown editorがあるんですがそこでWordファイルでexportをすると

「pandocを設置してください」

というポップアップが出ます。

pandocの設置をするとWordファイルでよく変換ができます。

Wordファイルはこれでいいけど、markdownをpptxで変換ができるかなと思ってpandocサイトを調べてみました。

[https://pandoc.org/MANUAL.html]

やっぱりpptxの変換機能がありました。まず簡単に基本ファイルを変換してみました。

<img width="1392" alt="basic.png" src="https://qiita-image-store.s3.amazonaws.com/0/55902/3dccf3de-fe53-4d40-daa0-750c1a1b5375.png">


この結果でそのまま使えるかはちょっと疑問が起きます。場合によって様々なテンプレがあるのでこれではちょっとまずいですね。

マニュアルをよく見たらこんなoptionが発見できます。

~~~~
--reference-doc=Filename
~~~~

reference-docはドキュメントの生成時テンプレになるファイルです。マニュアルではdocsまたodtファイルしか書いてないですが、pptxもできます。

**PowerPoint**

The specific requirement is that the template should contain the following four layouts as its first four layouts:

1. Title Slide
2. Title and Content
3. Section Header
4. Two Content

テンプレには最小4個のスライドが要るしタイトル、タイトルとコンテンツ、セクション・ヘッダ、コンテンツ2個がそのものです。それを従うpptxファイルを「デザイン」タブから用意します。(自作も構いませえん)

<img width="1392" alt="reference.png" src="https://qiita-image-store.s3.amazonaws.com/0/55902/c71fea3e-4c83-0e41-5e61-b8ce83fe14d3.png">


* ファイル名：ref.pptx
  * １番目：title slide
  * ２番目：section header
  * ３番目：title + content
  * ４番目：title + 2contets



これをpptxでそのままダウンして(reference.pptx)mdファイルで変換してみました。

mdファイル(test.md)

```markdown
% Habits
% John Doe
% March 22, 2005
# In the morning
## Getting up
- Turn off alarm
- Get out of bed
## Breakfast
- Eat eggs
- Drink coffee
# In the evening
## Dinner
- Eat spaghetti
- Drink wine
```

コマンドは

```
pandoc test.md -f markdown -s -o test.pptx --reference-doc=ref.pptx
```

結果ファイルは以下のように作られます。

<img width="1392" alt="finalfile.png" src="https://qiita-image-store.s3.amazonaws.com/0/55902/e080fed6-5550-c584-ae31-e12f2fc20721.png">




以前では[marp](http://https://yhatt.github.io/marp/)を作ってスライドを作成しましたがpptxの変換を支援しないししテンプレの2個しかないので不便でした。でもpandocを使うとpptxを100%まではないですがそれなりにmarkdownファイルをpptxで共有することができます。
【Node.js】google-spreadsheet-npmにおける同期処理について

前回の続きで、SpreadSheetから取得した値を格納した変数を別の関数内で使おうと思ったらつまづいた
[Node.jsでGoogleSpreadSheetから値を取得する](https://qiita.com/risuto_nishimura/items/9d13e3a412e99935312b)

#別の関数内でグローバルに変数を使う
例えば、この取得関数内だけではなく別関数内でも変数を受け渡したい場合に、JSの特性上、**JavaScript以外（例えばデータベース等）に仕事を任せてる間、その処理を待たないで次へ進める**ので同期処理にしないと変数に格納されないまま処理が実行される場合がある。

詳しく知りたい人は先人の知恵を借りよう。
[JavaScriptの同期、非同期、コールバック、プロミス辺りを整理してみる](https://qiita.com/YoshikiNakamura/items/732ded26c85a7f771a27)

なので、格納した変数をグローバルに使いたい場合は**async**や**Promise**を使って同期処理になるようにしなければならない。

#サンプルコード（Promise ver.)
```index.js
//パッケージを読み込む
var GoogleSpreadsheet = require('google-spreadsheet');

//必要情報の格納
var test_sheet = new GoogleSpreadsheet('<spreadsheet key>');
var credentials = require('./上記参考サイト内の連携処理でインストールしたファイル名（拡張子は .json） ');

//データ格納用配列の用意
var array =[];

//関数実行順宣言
get_function()
.then(use_function)
.then((response) => {
  console.log("all done!");
});

//データ取得関数
function get_function(){
  return new Promise((resolve,reject) => {
    test_sheet.useServiceAccountAuth(credentials, function(err){
      //sheetデータの取得
      test_sheet.getInfo(function(err, data){
      sheet = data;
      //取得したsheetの中に自分の取得したいシート名があるかチェック
      for(var i in sheet.worksheets) {
        if(sheet.worksheets[i].title === 'シート名') {
          sheet.worksheets[i].getRows(function(err, rows) {
            for(var i in rows) {
              array.push（rows[i].欲しい情報のカラム名）;
            };
            resolve();
          });
        };
      };
    });
  });
};

//取得データ使用関数
function use_function(passVal){
  return new Promise((resolve,reject) => {
    console.log(array);
  };
  resolve();
};
```
Node.jsってやっぱり楽しい。
【Node.js】GoogleSpreadSheetから値を取得する

GoogleSpreadSheetからGASやGCFなどを使ってデータを取得して処理する

#参考ページ

Google Apps API Keyの取得
[http://www.yoheim.net/blog.php?q=20160411
](http://www.yoheim.net/blog.php?q=20160411)[https://techblog.lclco.com/entry/2018/11/30/120000](https://techblog.lclco.com/entry/2018/11/30/120000)

#google-spreadsheet

[https://www.npmjs.com/package/google-spreadsheet](https://www.npmjs.com/package/google-spreadsheet)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/354659/d745308f-0a58-0f6d-4b51-66ed69796eae.png)

#サンプルコード


```index.js
//パッケージを読み込む
var GoogleSpreadsheet = require('google-spreadsheet');

//必要情報の格納
var test_sheet = new GoogleSpreadsheet('<spreadsheet key>');
var credentials = require('./上記参考サイト内の連携処理でインストールしたファイル名（拡張子は .json） ');

//データ格納用変数の用意
var sheet;

//連携の認証
test_sheet.useServiceAccountAuth(credentials, function(err){
  //sheetデータの取得
   test_sheet.getInfo(function(err, data){
   sheet = data;
     //取得したsheetの中に自分の取得したいシート名があるかチェック
     for(var i in sheet.worksheets) {
       if(sheet.worksheets[i].title === 'シート名') {
         sheet.worksheets[i].getRows(function(err, rows) {
          for(var i in rows) {
            var value = rows[i].欲しい情報のカラム名;

              //valueに入った値を使って処理を行う

            };
          });
        };
      };
   });
});

```

他の関数内でも変数をグローバルに使いたい時はこちら
[JavaScriptにおける同期処理について](https://qiita.com/risuto_nishimura/items/fa4d508ef94fa178f762)
npmの簡単な使い方

[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしているryota_miraidenshiです。
今回は、JavaScriptを勉強しているときに出てきたnpmパッケージについてまとめておきます。

#npmとは
npmはパッケージと呼ばれる誰かが作った便利な機能を検索やインストール、バージョン管理などするためのものです。
使いたいディレクトリ内で

```
npm install
```

とすることでnpmをイントールします。

このnpmを使って様々な機能をインストールすることでその機能を使用することができます。


#機能の一例と実行まで
例えば「出てくる文字に色をつけて強調したい！」というとき。
chalkをインストールすることでターミナルでの出力に色をつけることができます。
使いたいディレクトリの直下で

```
npm install --save chalk
```

を実行しましょう。
あとは、使いたいコードの中でインポートしておく必要があります。
今回だったら

```
import chalk from "chalk";
```

とコードの一番最初に追加します。
最後に以下のコマンドで実行します。

```
npm run start
```

#package.jsonについて
上で「--save」とあったと思いますが、これは実はpackage.jsonというファイルに保存するためのコマンドです。
というのも、このファイルはバージョンなどの情報をJSON形式で記録して依存関係をまとめたファイルで、別の環境での作業やチームで同じ環境で作業する場合に使われる便利なものになっています。


#終わりに
今回はnpmの簡単な使い方についてまとめました。
プログラム初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正しますのでどんどん指摘してください。
React16.7 Suspense & React.lazy + TypeScriptでRoute-based code splittingする



webpack + React16.6以降（Suspense + React.lazy） + TypeScriptな環境で
Route-based code splittingをするためのTips。
ハマりどころに着目し、 `// Point:` コメントを振ってあります。

公式：
https://reactjs.org/docs/code-splitting.html#route-based-code-splitting

## ルーティング部分

ページごとにコード分割を図るべく、ページのエンドポイントとなるコンポーネントをdynamic import。
React16.7より登場の `Suspense`、`React.lazy()` を使う。

```tsx:routes.tsx

import * as React from 'react'
import { Route, Switch } from 'react-router-dom'
import App from './path/to/App'

// Point: static importではなくdynamic importをReact.lazyでラップする
const Page1 = React.lazy(() => import('./path/to/Page1'))

export default (
  <App>
    {/* Point: React.Suspenseでルーティング部分をラップ。
        fallbackにはPage1コンポーネントが読み込まれるまでの間表示するコンポーネントを指定 */}
    <React.Suspense fallback={<div>Loading...</div>}>
      <Switch>
        <Route exact path="/page1" component={Page1} />
      </Switch>
    </React.Suspense>
  </App>
)
```

## webpack

分割されたコードはoutput.publicPath配下に生成される。
また、`ExtractTextPlugin`を利用している場合は`allChunks`オプションを指定することで
分割されたコンポーネント内でimportされているCSSも対象にする。

```webpack.config.js
const webpack = require('webpack')
const path = require('path')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: ['babel-polyfill', './src/index.tsx'],
  output: {
    path: path.join(__dirname, 'public/assets'),
    // Point: ${publicPath}${chunkFilename}に分割後のファイルが配置される
    publicPath: '/assets/',
    filename: '[name].bundle.js',
    chunkFilename: '[name].bundle.js'
  },
  ...
  resolve: {
    modules: ['node_modules'],
    extensions: ['.ts', '.tsx', '.js', '.pcss', 'css']
  },
  plugins: [
    // Point: dynamic importするコンテンツがcssをimportする場合は、allChunks: trueオプションが必要
    new ExtractTextPlugin({ filename: '[name].bundle.css', allChunks: true }),
    new webpack.HotModuleReplacementPlugin(),
    new ForkTsCheckerWebpackPlugin(),
    new HtmlWebpackPlugin({
      hash: true,
      filename: path.join(__dirname, './public/index.html'),
      template: './src/index.template.ejs',
      inject: 'body'
    })
  ]
})


```

## tsconfig

moduleオプションには`commonjs`、`amd`、`system`、`umd`、`es2015`または`esnext`が指定できるが、
dynamic importが有効なバージョンを指定する必要がある。

```js
{
  "compilerOptions": {
    "baseUrl": ".",
    "lib": ["dom", "es7"],
    "outDir": "public",
    "module": "esnext", // Point: moduleを esnext にすることでdynamic importを有効化する
    "target": "es6",
    "sourceMap": true,
    "inlineSourceMap": false,
    "inlineSources": false,
    "experimentalDecorators": true,
    "noUnusedParameters": true,
    "noUnusedLocals": true,
    "noEmitOnError": false,
    "keyofStringsOnly": true,
    "jsx": "react",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true
  }
}
```


---

### まとめ


Code Splittingによってメインのバンドルサイズが小さくなるので、初回ロード速度が大幅改善、データ転送量が減るのがメリットですが、コンポーネントの分割を行うためにコードが煩雑化しがちでした。

しかし、React16.6以降ではSuspenseとReact.lazyを駆使することで単純なコードで実現可能です。
TypeScriptでの実現も容易ですので、今後のReactプロジェクトにカジュアルに導入していくことができそうです。
（create-react-appで作った設定なら、特に意識せずそのままdynamic importも使えます！）

他にもつまづきポイントがあったら随時追記していきたいと思いますので、コメントもお待ちしております。

では　よきCode Splittingライフを！