OmniAICreator/Qiita-1.07M huggingface dataset:
NVR500でDS-LiteとIPv4（固定）の2回線を共存させる設定メモ

IPv6への移行技術の一つIPoE DS-Lite。一般的に、空いているIPv6のバックボーンを利用することで、IPv4の夜の時間帯などの混雑を避けて速度低下が起こらないことが期待される。

今回は速度というよりも、固定IPv4をいつものインターネッツで使うのが嫌で分けたかったのと興味本位でDS-Liteを使ってみることにしたのでメモ
（実は以前から契約はしていたけどずっと設定をサボっていた）

使っているプロバイダはInterlinkで、IPoE DS-Liteは[Zoot Native](https://www.interlink.or.jp/service/zootnative/)というプラン。

FAQにルーター2つ使えばできる構成が紹介されているけれど、この記事の方法で一つでもできます！
https://faq.interlink.or.jp/faq2/View/wcDisplayContent.aspx?id=480

きっとNVR510やRTX1210でも同じような設定でいけると思います。

## やりたいこと

特定のホスト（`192.168.100.xxx`と`192.168.100.yyy`の2つ）はサーバーとして公開しているからIPv4、その他のホストは内側からしかリクエストを飛ばさないからDS-Liteでインターネットに繋ぎたい。

## 前提

* IPv4とDS-Liteの契約は済んでいる
* 「特定のホスト」のプライベートIPを固定しておく（あたりまえ）
    * 本当はIP範囲で分けておいたほうがいい

## ひとことでいうと

pp1をIPv4、tunnel 1をDS-Liteとして、IPアドレスでフィルタを作って、デフォルトゲートウェイ設定する。

## 設定方法

pp1はGUIでIPv4の方を設定しておく（一般的なPPPoE IPv4の設定）。

DS-Liteの設定は、ここに従ってGUIで設定してtunnel1を作っておく（CUIじゃなくてごめんなさい）。
https://faq.interlink.or.jp/faq2/View/wcDisplayContent.aspx?id=660
ただし`ip route default gateway ...`のコマンドだけは打たないでおく。

IPv4を使いたいホストのフィルタを作る。

```
ip filter 600000 pass 192.168.100.xxx,192.168.100.yyy * * * *
```

IPアドレスを`-`で挟めば範囲指定。

default gatewayを設定する。
指定したホストはpp1（IPv4）で接続、その他は全てtunnel 1（DS-Lite）で接続。

```
ip route default gateway pp 1 filter 600000 gateway tunnel 1
```

## 参考

* https://qiita.com/mameendomame/items/910419ef0a761ee346ad
* https://kendev.wordpress.com/2010/03/28/yamaha-rtx1200活用%E3%80%80pcホスト）によって接続先を変える方法/

## その他

もともとのIPv4の夜の速度も相当早かったからかDS-Liteのほうがむしろ遅くなりましたorz
まあ回線を分けることとやってみることを目的としていたので問題なし。

本当はingressの方の接続設定ともまとめたりしたかった。
選択ソート

選択ソート…配列中の最小を選択して、それを左端の値と交換する。
例)53412
 →13452
 →12453
 →12354
 →12345

```c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void SelectionSort();
void MakeArray();
void ShowData();
int main();

const int SIZE = 10;
int data[SIZE];


void MakeArray(){
	int i, num;
	srand((unsigned) time(NULL));

	for(i=0;i<SIZE;i++){
		num=rand()%900 + 100; //取得する値を100~999の間とする
		data[i] = num;
	}
}


void ShowData(){
	for(int i = 0; i < SIZE; i++){
		if(i != SIZE - 1){
			printf("%d, ", data[i]);
		}else{
			printf("%d", data[i]);
		}
	}
	printf("\n");
}

void SelectionSort(){
	int temp;
	int mini;
	int loop = SIZE - 1;

	for(int i = 0; i < loop; i++){
		mini = i;

		for(int j = i + 1;j < SIZE ;j++){
			if(data[j] < data[mini]){
				mini = j;
			}
		}

		if(mini != i){
			temp = data[i];
			data[i] = data[mini];
			data[mini] = temp;
		}
	ShowData();
	}
}

int main(){
	MakeArray();

	printf("(ソート前)\n");
	ShowData();

	SelectionSort();

	printf("(ソート後)\n");
	system("PAUSE");
	return 0;
	}
```
JavaFXでファイルのドラッグ＆ドロップ

# 内容
ファイルがドラッグ＆ドロップされたらそのファイルの絶対パスを表示するプログラム。

# コード
```
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {
	@Override
	public void start(Stage primaryStage) {
		try {
			VBox root = new VBox();

			root.setOnDragOver(event -> {
				Dragboard board = event.getDragboard();
				if (board.hasFiles()) {
					event.acceptTransferModes(TransferMode.MOVE);
				}
			});

			root.setOnDragDropped(event -> {
				Dragboard board = event.getDragboard();
				if (board.hasFiles()) {
					board.getFiles().forEach(file -> {
						root.getChildren().add(new Label(file.getAbsolutePath()));
						System.out.println(file.getAbsolutePath());
					});

					event.setDropCompleted(true);
				} else {
					event.setDropCompleted(false);
				}
			});

			Scene scene = new Scene(root, 400, 400);
			primaryStage.setScene(scene);
			primaryStage.show();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		launch(args);
	}
}

```

# 補足
ファイルをドラッグ＆ドロップするだけでも`setOnDragOver`メソッド内で`acceptTransferModes`を呼び出す記述が必要。ないと動かない。
Swift  CollectionViewCell的使用

Collection View 笔记
01 在故事板中拖一个Collection View控件，设置个图片，加一个imageView，设置它的大小,使其大小适应，
将ViewController的dataSource连接上，要是不连接的，在viewController中写   collentionView.Datasourece = self
![Snip20180104_9.png](https://qiita-image-store.s3.amazonaws.com/0/227685/da4073d9-cce3-3a8e-453a-e183cad67cc1.png)
02 新建并指定ConllectionViewCell 对应的的类（继承UIviewControllerCell），设置它的Identifier 
![Snip20180104_12.png](https://qiita-image-store.s3.amazonaws.com/0/227685/43acefcd-e0f5-c1d0-3d0c-9ca94eec57b0.png)
![Snip20180104_11.png](https://qiita-image-store.s3.amazonaws.com/0/227685/194d323d-e992-9463-051a-f63e30ea0f72.png)
03 在ViewController中，让它继承UICollectionViewDataSource
![Snip20180104_14.png](https://qiita-image-store.s3.amazonaws.com/0/227685/5fb56329-8c39-0f28-05a8-e37cc6059b09.png)
04 然后实现UICollectionViewDataSource协议的方法

```
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        
        return  1//返回的行数
    }
    
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "myCell", for: indexPath)  as! myCellCollectionViewCell  // myCell是ConllectionViewCell的Identifier，as后面是ConllectionViewCell对应的类
        cell.imageView.image = UIImage(named: "moon-1859616_1920.jpg”)//图片的名字
        return cell //返回cell 的内容
    }

```
## 源码 https://github.com/honest666/CollectionVeiwCell
バブルソート

バブルソート…•配列の末尾から隣接する要素を順番に比べていき、大小関係が逆ならば交換する。
例53421
 →15342
 →12534
 →12354
 →12345


```c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void BubbleSort();
void MakeArray();
void ShowData();
int main();


const int SIZE = 10;
int data[SIZE];

void MakeArray(){
	int i, num;
	srand((unsigned) time(NULL));

	for(i=0;i<SIZE;i++){
		num=rand()%900 + 100; //取得する値を100~999の間とする
		data[i] = num;
	}
}

void ShowData(){
	for(int i = 0; i < SIZE; i++){
		if(i != SIZE -1){
			printf("%d, ", data[i]);
		}else{
			printf("%d", data[i]);
		}
	}
	printf("\n");
}

void BubbleSort(){
	int cnt = SIZE - 1;
	int tmp;

	for(int i = 0;i < cnt; i++){

		for(int j = cnt;i < j; j--){	
	
			if(data[j] < data[j-1]){
				tmp = data[j];
				data[j] = data[j-1];
				data[j-1] = tmp;
			}else{
				continue;
			}
		}
	ShowData();
	}
}

int main(){
	MakeArray();

	printf("(ソート前)\n");
	ShowData();

	BubbleSort();

	printf("(ソート後)\n");
	system("PAUSE");
	return 0;
}
```
LINEBOTで自分好みの秘書BOTを作ってみる

# プロローグ
作ってみたいと思ったきっかけは大きく2つ!

一つは投稿時点での作業場でBOTが効果的に活用されています．
Gitlabをhookさせて必要に応じて内容を送って人間に教える，何かサーバでエラーが発生したらエラー内容を教えたりと，すべきことや，することを漏れなく人間に教えるインフラが確立されてました．
日常的なすることを教えてくれる秘書は欲しいですが，どっかの社長でも芸能人でも無いし，そもそも雇う経済力もないので，秘書BOTで作ろうと思いました．

しかし，「それならググればいっぱいあるやんけ!」ってなります．
はい，確かにいっぱいありますが，そんな時に見つけたのがこれ．
「[バグをドラゴンと呼ぶ運用を始めて1ヶ月くらいたった](http://konifar.hatenablog.com/entry/2015/05/02/003449)」
ここで思ったのは「教え方で楽しくできる」ということです．
つまり，普通の秘書じゃなくて自分が好きなキャラを秘書として雇っちゃおう!という着想に至りました．
ラブライバーの私にとって，曜ちゃんやヨハネ様を秘書として雇えるなんて素晴らしすぎるので，やるしか無いですね，はい(キャラ説明は割愛)．

# 要件定義
幸か不幸か私の妄想力は留まることを知らないので，現実的要件，中間的要件，理想的要件の3つに便宜的に分けます．
各々の基準はそれぞれの項目で説明することにします．

## 現実的要件
「自分好みの秘書BOT」を実現するにあたって必要不可欠，絶対実装したい仕様がここになります．

* Googleカレンダーを使ってスケジュールを教えてくれる
  * 当日にイベントがあったら，朝に通知
  * 「スケジュール教えて!」って言ったら，今日から1週間のイベントを教える
* BOTの口調が曜ちゃん

## 中間的要件
欲しい仕様だけど，今後の開発を考えたらサーバ側に環境構築が必要だったりでちょっと時間がかかりそうな仕様，現実的要件ほど必須性が無い仕様がここ．

* 「ヨハネ，召喚」って言ったら，秘書がヨハネ様に切り替わる
  * 当然，口調もヨハネ様になる
  * 「曜ちゃん，帰ってきて!」って言ったら秘書が曜ちゃんになる
* Gmailで重要なメールが来たら教えてくれる

## 理想的要件
最終的に実装したい仕様だけど，時間とかで到底無理だったり，そんなに欲しくないけど秘書って言ったらこんなことするよねorしそう・・・なやつ．

* 「丸々な秘書にして」って言ったら，秘書がそんな感じになる
  * 「関西人な秘書にして」→「今日は○○があるさかい，気をつけてな」みたいな
  * ゆくゆくはベースを作って各々で口調を設定できる様にしたい
* BOTを通じてスケジュールの登録ができる
* 「公的書類 書き方」「電話応対 取り次ぎ」って言ったら，そのテンプレを教えてくれる

# 開発環境
このシリーズの開発にあたって使うことになるだろうなやつです．
現実的要件を満たす範疇でリストアップします(中間的要件以降を開発する気になったらその時にリストアップします)．

* BOTサーバはSinatra(Ruby)+passenger+Apache(これらは既に作ってます)
* タイトルの通り，LINEを使います(LINE@アカウントが要ります，これも既に作ってます)
* Googleカレンダー
* GAS

とりあえずこれくらい・・・?

# その他
これから開発していきますが，自分の記事管理と「無かったら自分で作る精神」が自分の中であるので，その意味も込めてタグに「ないもの作るシリーズ」をつけてます．

これから投稿するこのシリーズの記事は技術的に困ったところや，これ使ったらよりスマートに書けるor設計できるやんけ!みたいなことを書いていきます．

既に作ったBOTサーバ，LINEBOTのアカウント作成は割愛します(書く気力&余力があれば別記事で投稿します)
MineoSim+iPhone(脱獄)の構成でテザリングを使えるようにしてみた


Mineoのsimに変えてからと言うものテザリングができなくて不便だったので使えるようにしてきたときのメモ

公式ページの対応表
http://mineo.jp/device/devicelist/au/
※下記環境の構成では公式にはテザリングができません

# 使用デバイス情報

・Mineo sim auプラン(Aプラン)
・iPhone6Plus(脱獄 iOS8.1)

# TetherMeをインストールする

cydiaに対応OSのバージョンがあったのでTetherMe for iOS 10/9/8を購入してインストール

![1.jpg](https://qiita-image-store.s3.amazonaws.com/0/223901/62f2ee1e-689d-3774-f65e-ec97a1d14ef7.jpeg)


# TetherMeを使用してテザリングを使用してみる

**インストールしただけでは設定画面にインターネット共有が表示されません**

TetherMeで一度「インターネット共有をオン」にすると以後は設定画面に「インターネット共有」が表示されます。

![3.jpg](https://qiita-image-store.s3.amazonaws.com/0/223901/d43c006c-8012-d5d3-b0e6-83f9b55f7b07.jpeg)

![2.jpg](https://qiita-image-store.s3.amazonaws.com/0/223901/c98fc6f8-2898-1bf8-9904-a45eacc7535a.jpeg)

あとは通常の使用方法と同じになります


# まとめ

正式な使い方ではないので自己責任でという感じではありますがそれでも格安simでなおかつテザリングまでできるMineoは素敵です。
【Chrome Developer Tools】実例で学ぶelementタブで出来ること～CSS・border/padding編

先日、こちらの記事で :arrow_down: Chrome Develper ToolsでCSSのmarginをシミュレーションしてみましたが。
[【Chrome Developer Tools】実例で学ぶelementタブで出来ること～CSS・margin編](https://qiita.com/mtanabe/items/20710fac6489f3e18c32)

paddingとborderも同じようにシミュレーションできます。
ちょっとやってみましょう:sparkles: 

# この記事で学ぶこと
1. border・paddingのシミュレーション方法。
2. border・paddingを設定したときの要素の縦横のサイズについて。
3. 画面の読み方について。

# paddingとborderをシミュレーションする
marginをシミュレーションしたときに起動したこの画面 :arrow_down:
![002_100.png](https://qiita-image-store.s3.amazonaws.com/0/188980/7b2a512e-3756-f419-9ced-d430ce2bf799.png)
よく見なくても、「padding」と「border」って書いてありますね :sweat_smile:
marginをシミュレーションした時と同じように、ダブルクリックして好きな値を設定してみてください。

## paddingとは？
marginを「外側の隙間」とするならば、paddingは「内側の隙間」です。
枠線の内側に少し隙間を作りたい時は、paddingの値を設定します。

## borderとは？
文字通り「枠線」です。
borderの値を大きくすると、太めの枠線になります。
Developer ToolsのElementsタブを見るとわかるように、上下左右バラバラに設定可能です。
設定箇所・太さを変えることで、見出しっぽく使うこともできます。

# 実際に設定してみた
ある日のQiita Advent Calendar 2017のページをサンプルに使います。
Webテクノロジーの１ブロックについて、
1. 左borderを10px
2. 上paddingを10px
を設定してみました。そうするとこんな感じになります :arrow_down: 
![004_070.png](https://qiita-image-store.s3.amazonaws.com/0/188980/1dad14c0-78ef-ca05-e21f-b97b8b899cae.png)
:warning:見やすくするためにborderの色を濃い目に変えてあります。

左borderが効いているため、左枠だけが極太になっています。
また、上paddingを入れたために、緑の「Webテクノロジー」の見出しの上と枠線との間に隙間ができました。

## １カードの縦幅・横幅はいくつなんだろうか？
こちらの記事 :arrow_right: [【Chrome Developer Tools】実例で学ぶelementタブで出来ること～CSS・margin編](https://qiita.com/mtanabe/items/20710fac6489f3e18c32) で定義した通り、１カードは 

```HTML
<div class="adventCalendarCard"> </div>
```
:arrow_up: このdivタグとなります。
よって、縦幅と横幅は以下の通りとなります。
　横幅 :arrow_right: ```左border:10px + divタグ本体 + 右border:1px```
　縦幅 :arrow_right: ```上border:1px + 上padding:10px + divタグ本体 + 下border:1px```
どちらも、実線の内側すべてを足し合わせた値です。

# ところで実線と点線って・・・？
ここだけ、実線ですよね？ほかは点線なのに、ここだけ実線で区切られてます。
![003_100.png](https://qiita-image-store.s3.amazonaws.com/0/188980/0ab2859c-a52e-14d3-cbe7-fc7d6f4f0826.png)
これは、「外」と「内」の境目を意味しています。
borderとpaddingは内側で、marginだけが外側です。
これはつまり、上記で計算している横幅と縦幅を計算するときに使う値の境目とも言えます。

# まとめ
- paddingとborderもmarginと同じようにシミュレーションできる。
- 要素のサイズを求めるにはmargin以外の値を縦・横それぞれ足し合わせればよい（そのための目印が実線）。
Arduinoを使って「振動で伝える温度計」を作る

##実は２号機
以前から「振動温度計」、つまり振動で何度か伝える温度計作りに挑戦しています。
限りなく電子工作＆Arduinoのプログラミングのことを知らない中で作った１号機は、電源電圧のことをきちんと考えていなかったり、Arduinoからの出力で直接振動モーターを回したりで、動作不安定極まりなし（笑）。それらに気づかせてくれたという意味では、貴重な１号機でしたが。

そして反省をもとに作ったのが、この２号機です。

![振動温度計２号機.jpg](https://qiita-image-store.s3.amazonaws.com/0/228034/4ef30351-fcb2-d8cd-6ba6-2cd84e490c7c.jpeg)

##主な使用部品
+ マイコンボード：[Adafruit Trinket 3.3V版] (https://www.adafruit.com/product/1500)
+ 温度センサ：[LM61CIZ] (http://akizukidenshi.com/catalog/g/gI-11160/)
+ 振動モーター：[LA4-503AC2](http://akizukidenshi.com/catalog/g/gP-06786/)　※電流増幅用にトランジスタ（2SC1815)を使っています。
+ 電源昇圧＆安定化：[昇圧型ＤＣＤＣコンバータ　ＳｔｅｐＵＰ・ＤＩＰ　３．３Ｖタイプ　Ｖｅｒ２](http://akizukidenshi.com/catalog/g/gM-05720/)

ちなみに基盤上にボタンがありますが、本来ケースにボタンを付けたかったものの、あるところでお披露目するにはどうしても時間がなく、仕方なく基盤上に直接付けた（苦笑）と言う具合です。

##動機
ちなみこれ、目と耳両方不自由な人、いわゆる盲ろう者でも使える温度計があってもいいんじゃないか、それなら振動で伝えるようにすればいいんじゃないか＆振動なら電子工作的にも音声とか出すより楽だし、というのがそのスタートでした。もちろん目だけの方（視覚障害者）でもいいですし、健常者の人でも使い道あるかもです。

##振動のルール
基盤上のボタンを押すと、温度に応じた振動をします。
ルールは、十の位が長い振動、一の位が短い振動、マイナスの場合は、十の位より長い振動が最初にあるようにしています。
つまり２３℃の場合は「ブーン ブーン ブンブンブン」です。

##改善したい点
動作が安定したので、人に説明することができるようになったのですが、実際に使ってもらえるようにするには、以下を改善しないといけません。

+ ちゃんとしたケース、できればナイスなデザインなものにしたい。
+ ケースにちゃんとボタンをつけたい。
+ 電源スイッチがないものを作りたい。

とくに３つ目は、Arduinoのスリープ機能を使うことになると思のだけど、その方法がよくわからず苦戦中。ケースの問題も難しいですね。。

まだまだ苦戦は続きます。
Angular アプリケーションを GitHub Pages で公開する方法

Angular アプリケーションを公開する方法を模索していましたが GitHub Pages が一番簡単だったのでそのメモです

## angular-cli-ghpages
* [angular-cli-ghpages](https://github.com/angular-schule/angular-cli-ghpages) というパッケージを使用します
* angular-cli-ghpages を使うための条件は下記です
    * Node.js 4.x 以上
    * Git 1.7.6 以上
    * Angular CLI で作った Angular アプリケーションであること
* 今回は下記の環境で試しています
    * Node.js 8.9.0
    * Git 2.14.3
    * Angular CLI 1.5.4

## 使い方
* angular-cli-ghpages をインストール

```
$ yarn global add angular-cli-ghpages
```

* 今回公開したいリポジトリ名を angular-tour-of-heroes とします

```
$ cd angular-tour-of-heroes/
$ ng build --prod --base-href "https://kasaharu.github.io/angular-tour-of-heroes/"
$ angular-cli-ghpages
```

* 上記コマンドを実行すると dist/ ディレクトリ配下が gh-pages ブランチとして push されます
    * コミットメッセージはデフォルト "Auto-generated commit" 

### オプション
* ブランチ名を変えたい場合
    * 下記のオプションで、 deploy ブランチに push します

```
$ angular-cli-ghpages --branch=deploy
```

* コミットメッセージを変えたい場合
    * 下記のオプションで、コミットメッセージを Deployment にします

```
$ angular-cli-ghpages --message="Deployment"
```

* dry-run

```
$ angular-cli-ghpages --dry-run
```

## GitHub Pages で公開
* angular-cli-ghpages を使って gh-pages ブランチへの push まで済んでいるので、あとはリポジトリの設定を変えます
* Setting を選び、 GitHub Pages の項目で使用するブランチを gh-pages に変更するだけで完了です

<img width="595" alt="gh-pages.png" src="https://qiita-image-store.s3.amazonaws.com/0/28573/0f0b322d-6a1e-b5b0-b05a-23212fd381ae.png">

## 確認
* 公開したページ(https://kasaharu.github.io/angular-tour-of-heroes) を見ると、ちゃんとデプロイされています

## 参考ページ
* [angular-cli-ghpages - GitHub](https://github.com/angular-schule/angular-cli-ghpages)
* [Deploy to GitHub Pages](https://github.com/angular/angular-cli/wiki/stories-github-pages)
* [Enabling GitHub Pages to publish your site from master or gh-pages](https://help.github.com/articles/configuring-a-publishing-source-for-github-pages/#enabling-github-pages-to-publish-your-site-from-master-or-gh-pages)
Elixirの静的型チェックの確認 - リテラル型


結論。
Elixirの静的型チェックで、文字列を指定してすることはできない。
長さぐらいは可能。
同様のことをしたいならatomを使う。
ちゃんと確認してないが、Erlangでも同じだろう。

# 具体的に

便宜上[Flow](https://flow.org/en/)と比較する。

Flowで以下のような型をElixirで表現するにはどうするか。

```javascript
// @flow
function sample(hoge_or_goro: "hoge" | "goro") {}

sample("hoge")    // Ok
sample("hogehoge") // Error
sample("goro")    // Ok
```

* https://flow.org/try/#0PTAEAEDMBsHsHcBQjIFcB2BjALgS1uqAM4CGAtgA7QCmAFABawDm1A+rAE6tOewBcoAESMWg0AB8hPDrEEBKAQDdYuACagA3gF9kpSjVrDm1eYj1U6RliJNyz5C4emy7iIA

関数sampleは `"hoge"`か`"goro"`という値しか受け取らないようにしたい。

Elixirでは以下のようにするのが良さそう

```elixir
defmodule Sample do
  @spec sample(:hoge | :goro) :: nil
  def sample(hoge_or_goro), do: nil
  
  def test(:hoge), do: nil  # Ok
  def test2(:hogehoge), do: nil # Error
  def test3(:goro), do: nil # Ok
  def test4(:mogu), do: nil # Error
end
```

bitstringを使う場合はせいぜい長さを指定するぐらいはできる

```elixir
defmodule Sample do
  @spec sample(<<_::32>) :: nil
  def sample(hoge_or_goro), do: nil
  
  def test("hoge"), do: nil  # Ok
  def test2("hogehoge"), do: nil # Error
  def test3("goro"), do: nil # Ok
  def test4("mogu"), do: nil # Ok (Errorにしたい)
end
```

`@spec sample(<<"hoge"::32>> :: nil`みたいにかきたいがコンパイルできない。

# 数値リテラル

数値は可能。
まずは、Flowの場合の例

```javascript
// @flow
function sample(one_or_three: 1 | 3) {}

sample(1) // Ok
sample(2) // Error
sample(3) // Ok
sample(1+2) // Error (Okにしたくはある)
```
* https://flow.org/try/#0PTAEAEDMBsHsHcBQkCuA7AxgFwJazaAM4CGAtgA7QCmAFPlQPqwBODWAFs1VQFygCMoAD6gAzAEpQAbwC+iRCQrUa-SSFAB5ANYKylWgCY1YAKLNmLXUtoTQ67Vf0qA1EbunzLUDW2BrBkDqDID6DIDyDID2DIBCDIDRDOKIQA

```elixir
defmodule Sample do
  @spec sample(1 | 3) :: nil
  def sample(one_or_three), do: nil

  def test(), do: hoge(1)  # Ok
  def test2(), do: hoge(2) # Error
  def test3(), do: hoge(3) # Ok
  def test4(), do: hoge(1+2) # Ok (やったぜ)
end
```

# 参考

* https://hexdocs.pm/elixir/typespecs.html#types-and-their-syntax
Visual Code Studio 力技PHP Remote Interpritor

## コンセプト
バッチファイルを使用してリモートのサーバーのコマンドを実行用というのが基本コンセプトです。
実行するコマンドを変えればphpunitも実行できます。
docker上のコマンドも実行できます。
ちなみに別にこんな方法をとらずとも構文チェックはできます。

## 構成
- Visual Studio Code(以下vscode)
- VirtualBox
- コマンドラインで使えるSSHクライアント  
  今回はGit-Bash
- Ubuntu（SSHサーバーがあればほかのOSでもOK）
- PHP

##前準備
VirtualBox上のLinuxに開発できる環境を用意します
今回の例ではソースはディレクトリ共有する形で使用します。
パスフレーズが設定されていないSSHのカギを用意します。

##バッチファイルの処理の中身
行うことは大きく2つです

- ファイルパスをWindowsのワークスペースのパスからLinux上の実行フォルダーのパスに変換する
- sshコマンドでリモートのコマンドを実行する

##設定手順
注意：複数のプロジェクトフォルダーがある場合、今回の設定をすると警告が表示されうまく動きません。ユーザー個別の設定にすれば大丈夫なのですが、その場合は複数のプロジェクトで設定が共有されるので注意してください。

- ファイル設定から「php.validate.executablePath」を探しワークスペースに設定をコピー
- 「.vscode」にバッチファイルを作成。今回は「php.bat」
- 先ほどコピーしたワークスペースの設定の「php.validate.executablePath」に「.vscode/php.bat」を指定
- php.batの中に内容コピーして必要な変更


これで準備完了です。phpファイルを編集すると「php.bat」が動作します。

##バッチファイルの中身

```Bat
@echo off
set REMOTE_HOST=<リモートホストのIP>
set REMOTE_USER=<リモートユーザーID>
set REMOTE_CMD=php
set SSH="c:\Program Files\Git\usr\bin\ssh.exe"
set SSH_OPTION=
set LOCAL_SRC_PATH=%CD%
set REMOTE_SRC_PATH=

set param=%1
set param=%param% %2
set param=%param% %3
set param=%param% %4
set param=%param%=%5
set param=%param% %6
set param=%param% %7
set param=%param%=%8
set param=%param% %9
shift
set file=%9
set file=%file:\=/%
set s=%LOCAL_SRC_PATH%
set strlen=0
:LOOP_HEAD
if defined s (
    set s=%s:~1%
    set /A strlen+=1
    goto :LOOP_HEAD
)
set /A strlen+=1

setlocal enabledelayedexpansion
set file=!file:~%strlen%!

set CMD=!SSH!
set CMD=%CMD% !SSH_OPTION!
set CMD=%CMD% -l !REMOTE_USER! 
set CMD=%CMD% !REMOTE_HOST!
set CMD=%CMD% !REMOTE_CMD!
set CMD=%CMD% !param!
set CMD=%CMD% !REMOTE_SRC_PATH!%file%
rem for debug print
rem echo %CMD%>> debug.log

%CMD%
endlocal
```


##Batファイル内の設定について
バッチファイルにはいくつか設定すべき項目があります

- リモートホスト
- リモートユーザー
- SSHの鍵（デフォルトは.ssh/id_rsaを使用）
- ローカル側のソースのルートパス（デフォルトはワークスペースパス）
- リモートが側の実行のルートパス（例えば/var/www/htmlなど）

##うまく動作しない場合
　最終的に実行されるコマンドをファイルに出力します。バッチフィルの下部にあるremを外して実行してください。実行するとファイルが作成され、バッチファイルが作成しているコマンドが記載されています。
　チェックすべきポイント設定変更した内容です。あっているように思われるのであればコマンドプロンプトで実行してみましょう。エラーの内容が表示されると思います。
　よくある間違いは次の通りです

- リモートホストのアドレスとリモートホストのユーザーが違う
- パスワードが求められる（鍵が違う）
- パスフレーズを要求される（指定した鍵にパスフレーズが指定してあった）
- リモートのファイルパスが違う

　うまく動かないポイントが見つかったらあとはバッチファイルの設定を直したり、バッチファイルそのものを修正してきちんと実行できる形に出力できるまで修正してください
　そこまでできれば大丈夫なはずです。
対象サーバーの使用できるcipherの確認

sslscanというツールを使用して確認する。
[https://github.com/rbsec/sslscan](https://github.com/rbsec/sslscan)

#コンパイルに必要なライブラリのインストール

```
yum install -y git gcc zlib-devel
```

#GitからClone

```
git clone https://github.com/rbsec/sslscan.git
```

#make実行

```
cd sslscan/
make static
```

#確認
※バージョン番号にstaticと表示され、OpenSSLがdevであればOK


```
./sslscan --version
		1.11.11-rbsec-static
		OpenSSL 1.0.2-chacha (1.0.2g-dev)

```

#使い方

```
sslscan 192.168.1.1:443
```

接続可能な暗号スイートのみ表示させる場合

```
sslscan --no-failed 192.168.1.1:443
```


このエラーはSSLv2をチェックしようとした際にopensslがSSLv2をすでにサポートしていないため発生するエラー

```
ERROR: Could not create CTX object.
ERROR: Scan has failed for host 192.168.11.101
```

SSL/TLSのバージョンを指定したい場合は以下

```
sslscan --no-failed --ssl3 192.168.xx.xxx:8443
sslscan --no-failed --tsl1 192.168.xx.xxx:8443
sslscan --no-failed --tsl11 192.168.xx.xxx:8443
sslscan --no-failed --tsl12 192.168.xx.xxx:8443
```

#出力結果
OpenSSL書式で出力されるため、[OpenSSLドキュメントサイト](https://www.openssl.org/docs/manmaster/man1/ciphers.html#CIPHER-SUITE-NAMES)からRFC表記とのマッピングを参照のこと。

```
 Supported Server Cipher(s):
    Accepted  TLSv1  128 bits  ECDHE-RSA-AES128-SHA
    Accepted  TLSv1  128 bits  DHE-RSA-AES128-SHA
    Accepted  TLSv1  112 bits  ECDHE-RSA-DES-CBC3-SHA
    Accepted  TLSv1  112 bits  EDH-RSA-DES-CBC3-SHA
    Accepted  TLS11  128 bits  ECDHE-RSA-AES128-SHA
    Accepted  TLS11  128 bits  DHE-RSA-AES128-SHA
    Accepted  TLS11  112 bits  ECDHE-RSA-DES-CBC3-SHA
    Accepted  TLS11  112 bits  EDH-RSA-DES-CBC3-SHA
    Accepted  TLS12  128 bits  ECDHE-RSA-AES128-GCM-SHA256
    Accepted  TLS12  128 bits  ECDHE-RSA-AES128-SHA256
    Accepted  TLS12  128 bits  ECDHE-RSA-AES128-SHA
    Accepted  TLS12  128 bits  DHE-RSA-AES128-GCM-SHA256
    Accepted  TLS12  128 bits  DHE-RSA-AES128-SHA256
    Accepted  TLS12  128 bits  DHE-RSA-AES128-SHA
    Accepted  TLS12  112 bits  ECDHE-RSA-DES-CBC3-SHA
    Accepted  TLS12  112 bits  EDH-RSA-DES-CBC3-SHA
```
(Ubuntu desktop 16.10)にJenkinsを再インストールする。

この記事は、Ubuntu desktop 16.10 に Jenkins をインストール後、動作しないので再インストールをする手順について、記載したものです。

== やってみたこと
まずは、通常の手順でインストールをしてみると、エラーが出力されましたが、そのまま進めて、jenkins をインストールしてみました。
以下のコマンドでインストールを実施します。
(1) sudo wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
(2) sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
(3) sudo apt-get update
(4) sudo apt-get install jenkins

これで、http:XX.XX.XX.XX:8080 でアクセスすると、例外で落ちます。

== 本題、Jenkinsを再インストールする
ここからは、あまり記事が無かったので、やってみた手順を記載します。
(1) sudo service jenkins stop                           : jenkinsのサービスを停止する。
(2) sudo apt-get --purge remove oracle-java7-installer  : javaパッケージ削除
(3) sudo apt-get --purge remove jenkins                 : jenkinsパッケージ削除
(4) sudo wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
(5) sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
(6) sudo apt-get update
(7) sudo apt-get install jenkins
(8) sudo service jenkins start

これで、再度、http:XX.XX.XX.XX:8080 でアクセスすると、正常にページが表示されました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/157744/382dc794-658e-8e91-d2c8-5ac5ce5d78fd.png)
pv コマンドの --rate-limit はどのように転送レート制限をしているのか


ちょっと気になって調べたメモ。バージョンは CentOS 7 の pv-1.4.6-1.el7。

```c
if (state->rate_limit > 0) {
    gettimeofday(&cur_time, NULL);
    if ((cur_time.tv_sec > next_ratecheck.tv_sec)
        || (cur_time.tv_sec == next_ratecheck.tv_sec
        && cur_time.tv_usec >=
        next_ratecheck.tv_usec)) {
        target +=
            ((long double) (state->rate_limit)) /
            (long double) (1000000 /
                   RATE_GRANULARITY);
        pv_timeval_add_usec(&next_ratecheck,
                    RATE_GRANULARITY);
    }
    cansend = target;
}
```

`RATE_GRANULARITY` がマイクロ秒単位のレートとチェックする間隔で `target` に次の `RATE_GRANULARITY` までに転送出来る量を計算して `target` に加算して `cansend` に入れる。

`RATE_GRANULARITY` の値は 100000 だったので 0.1 秒ごと。

```c
if ((0 < state->size) && (state->stop_at_size)
    && (0 >= cansend) && eof_in && eof_out) {
    written = 0;
} else {
    written =
        pv_transfer(state, fd, &eof_in, &eof_out,
            cansend, &lineswritten);
}
```

`pv_transfer()` の `cansend` の値は１回の read/write のサイズとして使われる。

```c
if (state->linemode) {
    since_last += lineswritten;
    total_written += lineswritten;
    if (state->rate_limit > 0)
        target -= lineswritten;
} else {
    since_last += written;
    total_written += written;
    if (state->rate_limit > 0)
        target -= written;
}
```

転送が終わったら実際に転送した量を `target` から減算する。

---

転送開始してから I/O が詰まってレートが期待より小さくなると `target` の値がどんどん大きくなって、I/O の詰まりが外れたときに一気に流れる。

```sh
time (dd 'if=/dev/zero' bs=1M count=10) | pv -L 1M > /dev/null
# 10+0 records in
# 10+0 records out
# 10485760 bytes (10 MB) copied, 9.8449 s, 1.1 MB/s
# 
# real    0m9.941s
# user    0m0.002s
# sys     0m0.021s

time (sleep 10; dd 'if=/dev/zero' bs=1M count=10) | pv -L 1M > /dev/null
# 10+0 records in
# 10+0 records out
# 10485760 bytes (10 MB) copied, 0.00900839 s, 1.2 GB/s
# 
# real    0m10.033s
# user    0m0.004s
# sys     0m0.031s
```

あくまでもトータルのレートが制限されるだけで、一時的に詰まったりするとめちゃめちゃでかいのが流れることがある。
CodeIQ「『タワー・ビルディング』問題」に参加しました。

[CodeIQ「『タワー・ビルディング』問題」](https://codeiq.jp/q/3459)の公開期間が終了したということで、提出回答(Ruby)を共有したいと思います(´・ω・｀) 詳しい問題内容については後日、CodeIQ Magazineで解説とともに公開されると思うので、そちらを参照お願いします(権利関係とかがよくわからないので)。

__2018-01-11追記:__ 問題&解説がCodeIQMagazineで公開されていました!! [「数学の問題をプログラミングで解こう！「『タワー・ビルディング』問題解説 」](https://codeiq.jp/magazine/2018/01/56722/)

```rb
@cache = {}

def f(n, a, b)
  ky = [n, a, b]
  return @cache[ky] if @cache.key?(ky)

  if a < 0 || b < 0 || n < 0
    val = 0
  elsif n == 0
    val = 1    
  else
    val = f(n - 1, a - 1, b) + f(n - 2, a, b - 1)
  end

  @cache[ky] = val % 1000003 
end

n, a, b = STDIN.gets.split.map(&:to_i)
puts f(n, a, b)
```

「高さ1の箱を最大a個、高さ2の箱を最大b個使って、高さnになる組み合わせの総数」は

- 「高さ1の箱を最大a-1個、高さ2の箱を最大b個使って、高さn-1になる組み合わせの総数」
- 「高さ1の箱を最大a個、高さ2の箱を最大b-1個使って、高さn-2になる組み合わせの総数」

をそれぞれ足し合わせたものになります。上記の解答はこれを再帰を利用して実装しただけの単純なものになります。ただし再帰を利用するので「初期条件」と「StackOverFlow」には注意する必要があり、後者については「メモ化」(一度計算した条件を覚えておく)ことにより、その対策としています。
こんにちは、Babel! まずはbabylonとbabel-generatorのみを用いて、コード変換入門にトライ

Qiita初投稿です。
実は去年の段階でアカウントは作っていたのですが、もっと良いコードや面白い記事が書けたらポストしようと思っていました。
でもそんな日はきっと訪れないし、それって英語の発音を気にして英語をなかなかしゃべれないのと同じじゃん！と思い、もう書くことにしました。
下書きだけ書いてうじうじしているより、投稿しちゃったほうが面白いしね！ :dolphin::joy:

## コーディングタイムコンパイル、メタプログラミング、トランスパイル

[これからの時代のメタプログラミングJavaScriptの正義を語ろう](https://qiita.com/erukiti/items/0c6154e7ca7ad51f19ff)

[さよならボイラープレート。s2sによる高速reduxアプリケーション構築](https://qiita.com/akameco/items/e1489c6bbf3439ec6ca4)

去年の暮れ頃に上記の記事に出会い、メタプログラミングやトランスパイルやコーディングタイムコンパイルといった言葉に魅了されました。そして、元旦には下のような記事も投稿しました。

[2018年元旦、コーディングタイムコンパイルにメタプログラミング、トランスパイルという単語が、僕の心を捉えて離さない件](http://shinshin86.hateblo.jp/entry/2018/01/01/145349)

要はハマったわけです。
ただ、自身はこういう分野の知識が絶望的にないため、``よし、俺も今日からメタプログラマーだ！``という風にすぐにはなれないことに気づき、絶望しました。
さて、真っ暗な穴の底で絶望するのは簡単ですが、底から這い上がるのは楽しいです。
まずはbabelを使って簡単な変換コードを書くところから初めて見ることにしました。
というわけで、タイトルとなります。

## babylonとbabel-generatorだけあれば、とりあえず変換できそう

早速やってみます。以下、備忘録的な形となります。

インストール

```bash
yarn add babylon babel-generator
```

コード書く

```js
const babylon = require('babylon');
const generate = require('babel-generator').default;

const sampleCode = `
console.log("Goodmorning!!");
console.log("Hello!!");
console.log("Goodnight!!");
`

// ASTに変換
const ast = babylon.parse(sampleCode);

// console.log内の文字列を"Hi!"に変換
ast.program.body.forEach(function(n1) {
  n1.expression.arguments[0].value = "Hi!";
});

// ASTからJavaScriptコードを生成し、codeを取得する
const transformedCode = generate(ast, sampleCode).code;
console.log(transformedCode);

```

実行結果は下記の通り

```bash
node hello-world.js

console.log("Hi!");
console.log("Hi!");
console.log("Hi!");
```

難しいと思いこんでいたASTが少しだけ身近になったような気がしました。
列や見出しの並び替え順序を指定するには

案外にFAQなので。
並び替えの順序は "列" ごとに指定しない限り用意された **照合順序** に従う。なので、意図する順序で並び替えるためにはその順序を示す **"列"** を用意し指定する必要がある。
Power BI Desktop や Power BI Service では照合順序を変更するオプションはないけれども、データモデルが作成されたときに適用された照合順序を使い続けることになるので問題はないでしょう。

参考：[言語および照合順序 (Analysis Services) | Microsoft Docs](https://docs.microsoft.com/ja-jp/sql/analysis-services/languages-and-collations-analysis-services)

# こういうときにどうするか
![1](https://qiita-image-store.s3.amazonaws.com/0/193509/a7d70a23-a5cc-2aa6-3f3d-2d9d9d42ab82.png)
数値ではないので 照合順序 通りにソートされるんですよね。なので、順序を指定したい。
蛇足ですが、例にある "地方"の並び順は必ずこうなるとは限らない。漢字を使用しない言語環境はこの順序にならないし、もしかすると漢字を使うけれども非日本語な環境ではまた別の順序になるかもしれない。

# 列の並び替え
データ ビューで設定 | 該当の列を選択し、[モデリング]タブ - [列で並び替え]
既定では "列"自身が利用されているので、順序を示す値をもつ "列"を指定

![2](https://qiita-image-store.s3.amazonaws.com/0/193509/d50ca765-c321-3436-7dc1-d4095000acb3.png)

日付テーブルの [月]列 に対し、[MonthNumber] を順序を示す列として利用されてますね。

順序を指定する値で対象の値を特定できない( 1対1 の関係にない ) 場合は設定できない。
![3](https://qiita-image-store.s3.amazonaws.com/0/193509/677fa227-d1e0-1d76-2717-3596bb1a8d13.png)


# その他
- [Power BI 勉強会 - connpass](https://powerbi.connpass.com/)
- [Power BI Desktop を使い始めるには](https://qiita.com/PowerBIxyz/items/6c4735cb5b5712e70981)
Python dmatrix() ダミー変数化

formulaでダミー変数化したいとき


#必要なモジュールを呼び出します
```.py
import pandas as pd
import patsy
```

#サンプルのデータフレームを準備します
![スクリーンショット 2018-01-04 18.08.00 2.png](https://qiita-image-store.s3.amazonaws.com/0/147821/b8084178-47c2-8631-0141-4c83f66f83c7.png)
こんなかんじです。


#a, b, x1, x2の列をダミー変数化します。
（カテゴリカルな列のみ展開されます）
![スクリーンショット 2018-01-04 18.08.00.png](https://qiita-image-store.s3.amazonaws.com/0/147821/c3827bfc-4ea0-c44c-8c12-c5182ad23150.png)
dmatrix("formulaでどのカラムを展開するか指定", 展開前のデータフレーム名)
でダミー変数化を行うことができます。
return_type="dataframe" の指定をすることで、
展開後のデータをデータフレームの形にしておくことができます。


#その他
詳しく知りたい方は[こちら](http://patsy.readthedocs.io/en/latest/quickstart.html)

Rでのダミー変数化、相互作用項の作成も書いたのでよければ見てください
[その1](https://qiita.com/daifuku_mochi2/items/2885dc02ac4bfc284e06)
[その2](https://qiita.com/daifuku_mochi2/items/b132dd5049feee6db7d0)
[Xamarin]MVVMの練習



## はじめに

[XamarinのBindingについて](https://qiita.com/yakumomo/items/502ad60ca9bcf615c128)という記事を見つけた。

この記事の内容は、元になるSwitchに応じて、別の複数のSwitchのオン・オフをするという内容。

元記事はすべてC#（コメントではXAMLのみ）で書かれているのだが、練習のためにMVVMで書くとどうなるかやってみた。



## コード

### ViewModel

```csharp:MainPageViewModel.cs
using Prism.Mvvm;
using Prism.Navigation;

namespace BindableObjectTest.ViewModels {
    public class MainPageViewModel : BindableBase, INavigationAware {
        private bool switch1Status;
        public bool Switch1Status {
            get { return switch1Status; }
            set {
                SetProperty(ref switch1Status, value);
                Switch2Status = switch1Status;
                Switch3Status = switch1Status;
            }
        }
        private bool switch2Status;
        public bool Switch2Status {
            get { return switch2Status; }
            set { SetProperty(ref switch2Status, value); }
        }
        private bool switch3Status;
        public bool Switch3Status {
            get { return switch3Status; }
            set { SetProperty(ref switch3Status, value); }
        }

        public MainPageViewModel() {
        }

        public void OnNavigatedFrom(NavigationParameters parameters) {

        }

        public void OnNavigatedTo(NavigationParameters parameters) {
        }

        public void OnNavigatingTo(NavigationParameters parameters) {

        }
    }
}
```

### XAML

```xml:MainPage.xaml
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
    prism:ViewModelLocator.AutowireViewModel="True"
    x:Class="BindableObjectTest.Views.MainPage"
    Title="MainPage">
	<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
        <Switch IsToggled="{Binding Switch1Status}" />
        <Switch IsToggled="{Binding Switch2Status}" />
        <Switch IsToggled="{Binding Switch3Status}" />
	</StackLayout>
</ContentPage>
```


## 結論

個人的には、MVVMで書くほうが動作がわかりやすい気がします。
model.matrix() でダミー変数化と相互作用項

ダミー変数化（カラムの横持ち変換）と相互作用項の作成について。


#適当なデータフレームを作成しておく

```.r
> # データフレームの生成
> df <- data.frame(x=c('a', 'b', 'c'),
+                  y=c(1, 2, 3),
+                  z=c('aa','bb','cc')
+                  )
```


#作成したデータは以下のような構成

```
> df
  x y  z
1 a 1 aa
2 b 2 bb
3 c 3 cc

> str(df)
'data.frame':	3 obs. of  3 variables:
 $ x: Factor w/ 3 levels "a","b","c": 1 2 3
 $ y: num  1 2 3
 $ z: Factor w/ 3 levels "aa","bb","cc": 1 2 3
```

x,y列が今回はfactor型であることに注意。
data.matrix()で展開するとfactor型の列内の要素をそれぞれの列へ展開できないが、
model.matrix()を使用するとできる。

#ダミー変数化する

```
> #上で作成したdfをダミー変数化、展開するカラムはx,y,z
> matrix_df <- model.matrix(as.formula(~0+x+y+z),
+                           data = df)

> matrix_df
  xa xb xc y zbb zcc
1  1  0  0 1   0   0
2  0  1  0 2   1   0
3  0  0  1 3   0   1
attr(,"assign")
[1] 1 1 1 2 3 3
attr(,"contrasts")
attr(,"contrasts")$x
[1] "contr.treatment"

attr(,"contrasts")$z
[1] "contr.treatment"
```
factor型であるx列とz列は展開され、ダミー変数化されている。
numeric型であるy列は展開されずそのまま残っている。

※as.formula()内の"0+"について、
例えば、x列を展開する際、a,bの要素を展開すればcの要素は確定する。
(a=0,b=0ならc=1。など)
このような場合でも、cを展開するというオプションを"0+"で指定できる。


#交互作用項の追加

```
> matrix_df2 <- model.matrix(as.formula(~0　+x　+y　+x*y　+x*y*z),
+                            data = df)
> matrix_df2
  xa xb xc y zbb zcc xb:y xc:y xb:zbb xc:zbb xb:zcc xc:zcc y:zbb y:zcc xb:y:zbb xc:y:zbb
1  1  0  0 1   0   0    0    0      0      0      0      0     0     0        0        0
2  0  1  0 2   1   0    2    0      1      0      0      0     2     0        2        0
3  0  0  1 3   0   1    0    3      0      0      0      1     0     3        0        0
  xb:y:zcc xc:y:zcc
1        0        0
2        0        0
3        0        3
attr(,"assign")
 [1] 1 1 1 2 3 3 4 4 5 5 5 5 6 6 7 7 7 7
attr(,"contrasts")
attr(,"contrasts")$x
[1] "contr.treatment"

attr(,"contrasts")$z
[1] "contr.treatment"
```

x,y,xとyの相互作項,xとyとzの相互作用項列を生成している。
factor型であるx列とz列の相互作用項にはダミー変数が格納されるが、
factor型であるx列とnumeric型であるy列の相互作用項には、numeric型のy列の値が格納される。

#その他
caret dummuyVars()での方法は[こっち](https://qiita.com/daifuku_mochi2/items/2885dc02ac4bfc284e06
)
caret dummyVars()でダミー変数化

xgboostなど、formulaが使用できないときにmatrixの作成が必要。
(formula はここがわかりやすかった　
http://ill-identified.hatenablog.com/entry/2017/04/30/004258)
caretパッケージのdummyVars()を使用したダミー変数化について書きます。


#適当なデータフレームを作成しておく

```.r
> # データフレームの生成
> df <- data.frame(x=c('a', 'b', 'c'),
+                  y=c(1, 2, 3),
+                  z=c('aa','bb','cc')
+                  )
```
#作成したデータは以下のような構成

```
> df
  x y  z
1 a 1 aa
2 b 2 bb
3 c 3 cc

> str(df)
'data.frame':   3 obs. of  3 variables:
 $ x: Factor w/ 3 levels "a","b","c": 1 2 3
 $ y: num  1 2 3
 $ z: Factor w/ 3 levels "aa","bb","cc": 1 2 3
```

#caret::dummyVars()を使用したダミー変数化

```
> library(caret)

> #dummy変数化
> df_dummy <- dummyVars(~.,data=df)
> df_dummy2<- as.data.frame(predict(df_dummy, df))

> df_dummy2
  x.a x.b x.c y z.aa z.bb z.cc
1   1   0   0 1    1    0    0
2   0   1   0 2    0    1    0
3   0   0   1 3    0    0    1
```
factor型であるx列とz列は展開され、ダミー変数化されている。
numeric型であるy列は展開されずそのまま残っている。
centOS7.0にRをインストール

EPELリポジトリ(CentOS標準のリポジトリでは使用できないパッケージを、yum コマンドでインストールできるようにするリポジトリ)を追加してから、
centOS7.0にRをインストールします。


```.bash
#EPELリポジトリの追加
sudo yum install -y epel-release

#Rのインストール
sudo yum install -y R
```

Rパッケージのインストールは以下。
'igraph' が入っているところに任意のパッケージを入力してください。

```.bash
sudo su - -c "R -e \"install.packages('igraph', repos='http://cran.rstudio.com/')\""
```

必要なパッケージをインストール後、

```.bash
R
```

を実行するとRに入ることができる。


抜ける時は

```.R
quit()
```
Hive 複数要素を展開して、複数行にする(LATERAL VIEW/split/explode)

##内容
1.したいこと
2.クエリと解説
2_1.split()の挙動
2_2.explode()の挙動


##1.したいこと

| usr |  item_list|
|:---:|:------:|
|  A  |  aaa,bb,c  |
|  B  |  a,bb  |
|  C  |  ss     |

ユーザごとに購入したアイテムが入っているテーブル(テーブル名はdataとする)は、
item_listの1カラムにitemがたくさん入っている構造だが、これを
以下のtemカラムのように1行1アイテムの構造にしたい。

| usr |  item_list|
|:---:|:------:|
|  A  |  aaa  |
|  A  |  bb  |
|  A  |  c  |
|  B  |  a  |
|  B  |  bb  |
|  C  |  ss     |


##2.クエリと解説

```.sql
SELECT
        usr,
        item
FROM
        data
LATERAL VIEW
        explode( split( item_list, ',' ) ) item_list2 as item
```

上記のように
item_listカラムを、
①split()で1アイテムずつに分割する。
②explode()で1カラムにする。
③LATERAL VIEW でビューにして、元のdataテーブルの横につけている。
という順番で作成できるが、以下で①、②、③の挙動を見る。


##2_1.split()の挙動

###split()で1アイテムずつに分割する

```.sql
--item_listを、カンマが出てきたら分割
SELECT
        split(item_list, ',') as item
FROM
        data
```

###結果

|item_list|
|:------:|
|  ["aaa"],["bb"],["c"]  |
|  ["a"],["bb"]  |
|  ["ss"]     |

カンマが出てきたときに分割されていることが確認できました。
ここでの重要なポイントは、配列になっているということです。
2_2.で行う、explode()を使用するためには、配列にしておく必要があります。


##2_2.explode()の挙動

###explode()で1アイテム1行にする

```.sql
SELECT
        explode(split(item_list, ',')) as item
FROM
        data
```

###結果
|  item_list|
|:------:|
|  aaa  |
|  bb  |
|  c  |
|  a  |
|  bb |
|  ss |

itemごとに1行になっていることが確認できました。

##2_3.LATERAL VIEW の挙動

###LATERAL VIEWでVIEWを作る
以下のように、2_1,2_2で解説したものを、
LATERAL VIEWでVIEWにしてitemというカラムを作成し、
元のdataテーブルの横につけている。

```.sql
SELECT
        usr,
        item
FROM
        data
LATERAL VIEW
        explode( split( item_list, ',' ) ) item_list2 as item
```

###結果

| usr |  item_list|
|:---:|:------:|
|  A  |  aaa  |
|  A  |  bb  |
|  A  |  c  |
|  B  |  a  |
|  B  |  bb  |
|  C  |  ss     |



完成。
Jupyter notebookで列をすべて表示したい

Jupyter Notebookでデータフレームを表示すると、
表示列が多すぎる時、途中の列が「・・・」という表示になってしまう。
省略せずに全部表示させたい時にはこれ。


```.python
import pandas as pd

#現在の最大表示列数の出力
pd.get_option("display.max_columns")

#最大表示列数の指定（ここでは50列を指定）
pd.set_option('display.max_columns', 50)
```

以下で、最大表示行数の指定もできる。

```.python
import pandas as pd

#現在の最大表示行数の出力
pd.get_option("display.max_rows")

#最大表示行数の指定（ここでは50行を指定）
pd.set_option('display.max_rows', 50)
```
基本のMPI

# MPIを使用するその前に
 [ここ](https://qiita.com/kkk627/items/49c9c35301465f6780fa)を見ると、ノード間並列を行う前に、NFSとパスワードなしssh接続ができる状態にしておく事が重要らしい。

# MPIの種類
 MPI並列をやろうかなと思った時に最初の壁がMPIの実装が２種類(open mpi と mpich )あるけどどっち使った方が良いのか？という事です。  
 結論から言うと、ベンチマークを取って比較して速い方を使うというのが良いでしょう。
 それで、両方使う時に問題になるのが、使い方の違いとMPI環境の切り替えです。
 そこで、ここでは両方とも使って開発できるようにすることを目指します。
 普通のスパコンだとコマンド一つで切り替える事ができるようになっています。  
 後は、[mpienv](http://freak-da.hatenablog.com/entry/2017/06/09/155506)のような物を使うと良いです。

# MPIのインストール
 仕様OS: ubuntu 16.04
 apt-get install openmpi mpich でインストールできるはず。
 インストールした後、 mpirun.openmpi と mpirun.mpich が存在する事を確認してください。

# MPI並列をしたいプログラムをコンパイルする。
 ubuntuの場合は、apt-getで比較的簡単にインストールすることができるのですが、問題は使い方です。  
 例としてはfortranを使っていますが、他言語でも同じです。適宜変えてください。
 openmpi + gfortranの場合

 ```
 $  mpif90.openmpi test.f90
 ```

 openmpi + ifortの場合

 ```
 $ env OMPI_FC=ifort mpif90.openmpi test.f90
 ```

 mpich + gfortranの場合

 ```
 $ mpif90.mpich  test.f90
 ```

 mpich + ifortの場合

 ```
 $ mpif90.mpich -fc=ifort test.f90
 ```

# MPI並列での実行
 次は実行の仕方です。
 コンパイル時に使ったMPI環境で実行しましょう（当然）。

 ```
 $ mpirun.mpich -np 2 ./test.out
 ```

 や

 ```
 $ mpirun.openmpi -np 2 ./test.out
 ```

 で実行できます。  

# MPI並列実行での環境設定
 プログラムを実行している時に、 stack size や OMP_NUM_THREADS を変更したい時がある。
 でも、他ノードではstack size や OMP_NUM_THREADS がデフォルトの設定になっている場合があるので、実行時に変更したい。

 ```
 $ mpirun.mpich -np 2 bash -c "ulimit -s unlimited && export OMP_STACKSIZE=1G && export OMP_NUM_THREADS=2 && ./test.out input.txt "
 ```

 みたいなオプションで変更可能。  

# HOSTの設定
 mpirun.openmpi や mpirun.mpich で実行する時、どのノードを使うかという設定をファイルに書く事がある。
 その時、問題になるのが両方の環境で書式が違うこと。   

## mpichの場合  

 ```
 mpirun.mpich -np 2 -f hostfile ./test.out 
 ```

 hostfileの中身は

 ```
 hostname:slots
 ```

 みたいな感じになっている。HOSTNAMEじゃなくてIPアドレスでも良い。例えば、

 ```
 192.168.0.1:4
 192.168.0.2:4
 ```

 でも良いようだ。

## openmpiの場合  

 ```
 mpirun.openmpi -np 2 -hostfile hostfile ./test.out
 ```

 hostfileの中身は

 ```
 hostname slots=4
 192.168.0.1 slots=4
 ```

 という感じ。IPアドレスでも良い。  

# gdb使ってデバッグしたい  
 コンパイルを -g オプションを使ってコンパイルした時、 segmentation fault が起これば、起こった場所が表示される。 これは便利。
 しかし、mpirunをしている場合は、どのMPIプロセスで落ちたのかがわからなくて厄介。
 という訳で、gdbでデバッグしたい場合の対処法。

 ```
 mpirun.mpich -np 2  xterm -hold -e gdb -ex run --args ./test.out input.txt
 ```

 みたいなコマンドで、mpiプロセス毎にgdbが立ち上がって便利。  

# トラブルシューティング
 なんらかのエラーが出る場合に原因を把握するための一連のコマンド

 - MPIが正常にインストールされているか確認  
 $ mpirun.openmpi -np 2  bash -c   'hostname'  
 みたいなコマンドで確認する。複数ノードを使う場合も同様。
 - 1ノードでは実行できるが、複数ノードを使うとエラーが出る  
 環境変数等を確認しましょう。echo コマンド等が使用できます。  
$ mpirun.openmpi -np 2  bash -c   'ulimit -a'  

 
 


# 参考になったもの
centOS使用の場合: https://qiita.com/kkk627/items/49c9c35301465f6780fa
curlを使って5秒ごとにhtmlから特定の情報のみを抜き出してテキストファイルに出力

##やりたいこと
- [rippleチャート](https://www.coingecko.com/ja/%E7%9B%B8%E5%A0%B4%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88/%E3%83%AA%E3%83%83%E3%83%97%E3%83%AB/jpy)の現在の価格を5秒ごとにテキストファイルに出力させるscriptを作成する

##まずは周辺の情報を取得
```ruby:terminal
$ curl -s 'https://www.coingecko.com/ja/%E7%9B%B8%E5%A0%B4%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88/%E3%83%AA%E3%83%83%E3%83%97%E3%83%AB/jpy' | ggrep -oP '(?<=<span>)(.+)(?=</span>)'
```
- ggrep → Homebrewのコマンド → 先読み、後読み機能が付いているのがgrepとの違い
    - -o
        - 正規表現に一致した部分のみを返す
    - -P
        - Perlの正規表現を有効にする


結果

```ruby:terminal
15,726,286,988,711¥
405.9534¥
15,726,286,988,711¥
298.35287¥
432.55378¥
988,417,787,080¥
15,726,286,988,711¥
298.35287¥
432.55378¥
988,417,787,080¥
405.9534¥</span></b>です。現在の流通量は 38.7 十億 で取引された合計は <span>988,417,787,080¥
405.9534¥
15,726,286,988,711¥
988,417,787,080¥
```
欲しいのは以下の頭の`405.9534`！他のはいらん！

`405.9534¥</span></b>です。現在の流通量は 38.7 十億 で取引された合計は<span>988,417,787,080¥`

よってさらに絞り込みをする。

##もっと絞り込む
```ruby:terminal
$ curl -s 'https://www.coingecko.com/ja/%E7%9B%B8%E5%A0%B4%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88/%E3%83%AA%E3%83%83%E3%83%97%E3%83%AB/jpy' | ggrep -oP '(?<=<span>)(.+)(?=</span>)' | grep '</span></b>' | cut -d\¥ -f1
```
- cut 
    - -d
        - deleteする。-d\¥ にすることで、¥で区切るため、¥より前の情報のみを出力することができる。
    - -f1
        - 抽出するフィールドの番号を指定する。この場合は1列目だけを抽出

結果

```ruby:terminal
405.9534
```

##上記の値を5分ごとにファイルに出力する

```ruby:terminal
watch -n 300 "curl -s 'https://www.coingecko.com/ja/%E7%9B%B8%E5%A0%B4%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88/%E3%83%AA%E3%83%83%E3%83%97%E3%83%AB/jpy' | ggrep -oP '(?<=<span>)(.+)(?=</span>)' | grep '</span></b>' | cut -d\¥ -f1 >> ripple.txt"
```

watchコマンドで-nの後に300を指定することで300秒ごとにcurlコマンドを実行することができる。
ripple.txtはDesktopに予め作成しておいたファイルです。

次はこの値をスマホに通知したい！！
構造体のスロットをオプション的に自由に初期化したい

Common Lisp の構造体はCの構造体と同じで、中身はただの配列、かつfancyなイニシャライザのようなものはない。スロット(Cにおけるメンバ)の初期値を指定できるだけである。これでは不便。

たとえば、下のようなあまり意味のないhashtableのwrapperを作ってみるとする。

```lisp
(defstruct hash
  (hash (make-hash-table) :type hash-table))
```

これでは、make-hash-tableに`:test`や`:synchronized`などのキーワード引数を与えることが出来ない。

```lisp
(defvar *h* (make-hash))
(setf (hash-hash *h*) (make-hash-table :test 'equal))
```

これでは不便だなあ。非効率だなあ。

ところで、`defstruct` には `:constructor` オプションがある。これをいじればナントカなる気がする。

```lisp
(defstruct (hash (:constructor make-hash (&key hash)))
  (hash (make-hash-table) :type hash-table))

(defvar *h* (make-hash :hash (make-hash-table :test 'equal)))
```

しかしこれでも、 `make-hash-table` を明示的に書かないといけないのはイケてない気がする。

とおもいきや、実はこんなことが出来る。

```lisp

(defstruct (hash (:constructor make-hash (&key (test 'eql)
                                               &aux (hash (make-hash-table :test test)))))
  hash)

LIB> (make-hash :test 'equal)
#S(HASH :HASH #<HASH-TABLE :TEST EQUAL :COUNT 0 {10115325C3}>)

LIB> (make-hash :test 'eql)
#S(HASH :HASH #<HASH-TABLE :TEST EQL :COUNT 0 {1011534233}>)

LIB> 
```

`:constructor` オプションを使えばコンストラクタの関数名と引数シグネチャを変更できるのだが、引数の名前がスロットの名前に一致していれば、その変数の値がスロットに代入される。また、引数は左から順に評価され、また先に評価された引数の値を見ることが出来る。そこで、関数に好きなだけ変数もどきを追加できる `&aux` を使えば、イニシャライザやメソッドなどがなくても、任意の処理を行うことが出来る。

この用法は [boa lambda list](http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/sec_3-4-6.html) で明示的に許されている。

さて、それでは同じ方法で `slot-option` のほうの値を操作することはできるだろうか? CLHSによると `slot-initform` は `defstruct` の定義された `lexical environment` で評価されるのであって、コンストラクタの引数はこれに影響を与えることができない。すなわち、以下は許されない。

```lisp
(defstruct (hash (:constructor make-hash (&key (test 'eql))))
  (hash (make-hash-table :test test)))
```

のはずなんだけど、SBCLではこれができてしまう。

```lisp
LIB> (make-hash :test 'eql)
#S(HASH :HASH #<HASH-TABLE :TEST EQL :COUNT 0 {1005A13EF3}>)
LIB> (make-hash :test 'equal)
#S(HASH :HASH #<HASH-TABLE :TEST EQUAL :COUNT 0 {1005A17D93}>)
```

conformしてないといえばしてない。たとえば、以下の動作は非準拠だと思われる。

```lisp
(let ((test 'equal))
  (defstruct (hash (:constructor make-hash (&key (test 'eql))))
    (hash (make-hash-table :test test))))

LIB> (make-hash)
#S(HASH :HASH #<HASH-TABLE :TEST EQL :COUNT 0 {1005A196C3}>)
```

正しくは lexical environment の値を使うべきなので `#S(HASH :HASH #<HASH-TABLE :TEST EQUAL :COUNT 0>)` が返ってくるはずである。
複数のフォームコンポーネントを一括バリデート with VeeValidate

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

Vue 用のバリデーションプラグイン [VeeValidate](http://vee-validate.logaretm.com/index.html)。
ディレクティブで適用させることができ、config ファイルで細かくカスタマイズできたりと、設定が楽なことからお気に入りのプラグインです。

VeeValidate でのフォームの一括バリデートは「コンポーネントごと」となってしまうため、フォームをコンポーネントに分けた場合、親コンポーネントから一括バリデートをするには一手間かかります。

すべての子コンポーネントでバリデートをし、その結果を受け取る仕組みを `async / await` を使って実装してみました。

参考：[async/await 入門（JavaScript）](https://qiita.com/soarflat/items/1a9613e023200bbebcb3)

# TL;DR
- VeeValidate を使用して、複数の子コンポーネントのフォームをバリデート
- 各フォームコンポーネントの `$validator.validateAll()` の結果を親コンポーネントで取得
- `async / await` を使って実装

# 実装してみる
VeeValidate の実装方法は[公式](http://vee-validate.logaretm.com/index.html)や以下の記事をご参照ください。

- [Vue.jsを使ってて、フロントサイドのバリデーションには VeeValidate が便利](https://qiita.com/acro5piano/items/2be6068b0647ecffcd86)

VeeValidate を使用しているコンポーネント Form1, Form2, Form3 がある場合、親コンポーネントの vue ファイルは以下のように記述します。

```html:parent.vue

<template>
  <div>
    <form1 ref="Form1"/>
    <form2 ref="Form2"/>
    <form3 ref="Form3"/>

    <button @click="getAllValidationResult">
      確認
    </button>
  </div>
</template>

<script>

  // それぞれのコンポーネントで VeeValidate を使用

  import form1 from './form1'
  import form2 from './form2'
  import form3 from './form3'

  export default {
  	components: {
      form1, form2, form3
    },
    methods: {
    	validateAllForms: async function () {

    		// $validator.validateAll() は、エラーがなければ true が返る
    		// 一つでもエラーがあれば false が返る

    		const isOkForm1 = await this.Form1.$validator.validateAll(),
    		      isOkForm2 = await this.Form2.$validator.validateAll(),
    		      isOkForm3 = await this.Form3.$validator.validateAll()

            // すべての await が処理されたら return

            return isOkForm1 && isOkForm2 && isOkForm3
    	},

    	getAllValidationResult () {
    		this.validateAllForms()
    		  .then((response) => {

    		  	// すべてのフォームでエラーがなければ response は true になる

    		  	if (response) {

    		  		// 全フォームでエラーがない場合の処理

    		  	}
    		  })
    	}
    }
  }
</script>
```

# おわりに
子コンポーネントの関数を直接実行するのでアンチパターンな気がしますが、emit を使用した方法が思いつきませんでした...。
この方法で行くのなら `$validator.validateAll()` は直接実行せず、ラッパーをかませた方がいいですね。

# 参考資料
- VeeValidate
  - [http://vee-validate.logaretm.com/index.html](http://vee-validate.logaretm.com/index.html)
- Vue.jsを使ってて、フロントサイドのバリデーションには VeeValidate が便利
  - [https://qiita.com/acro5piano/items/2be6068b0647ecffcd86](https://qiita.com/acro5piano/items/2be6068b0647ecffcd86)
- async/await 入門（JavaScript）
  - [https://qiita.com/soarflat/items/1a9613e023200bbebcb3](https://qiita.com/soarflat/items/1a9613e023200bbebcb3)
Herokuデプロイで失敗したときの対処

Railsチュートリアル13章を取り組んでいた時に、最後の最後でHerokuにデプロイできず苦戦したので、その時のメモです。

```
$ git heroku push master
```
Herokuにデプロイしようとすると、このようなエラーが出ました。

```
remote:  !     Precompiling assets failed.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed
remote: Verifying deploy...
remote: 
remote: !	Push rejected
```

このような警告が出ていたものの、結果的には、Bundlerのバージョンの違いは特に問題なかったようです。

```
remote:        Warning: the running version of Bundler (1.15.2) is older than the version that created the lockfile (1.16.1). We suggest you upgrade to the latest version of Bundler by running `gem install bundler`.
remote:        The latest bundler is 1.16.1, but you are currently running 1.15.2.
```

問題となっていたのはこの箇所

```
remote: -----> Detecting rake tasks
remote: -----> Preparing app for Rails asset pipeline
remote:        Running: rake assets:precompile
remote:        rake aborted!
remote:        LoadError: cannot load such file -- fog
```

「リスト 13.58: GemfileにCarrierWaveを追加する」でGemファイルのバージョンを指定せずに最新版を使ってしまったことが原因だったようです。

```
gem 'carrierwave',             '1.1.0'
gem 'mini_magick',             '4.7.0'
gem 'fog-aws',                 '2.0.0'
```
新しいバージョンで利用する際には、
CarrierWaveのGitHubにあるように、以下のように設定して解決できました。

```
# Gemfile
gem 'fog-aws', group: :production
gem 'carrierwave', '~> 1.0'


# config/initializers/carrierwave.rb
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
  if Rails.env.production?
    config.storage :fog
    config.fog_provider = 'fog/aws'
    config.fog_credentials = {
      provider:              'AWS',
      [...]
    }
    [...]
  else
    config.storage :file
    config.enable_processing = false if Rails.env.test?
  end
end
```

参考：https://github.com/carrierwaveuploader/carrierwave/issues/1648
Djangoのバージョンを1.11から2.0にする

特にむずかしいことはなかった
https://docs.djangoproject.com/ja/2.0/howto/upgrade-version/

```
# python
Python 3.6.1 (default, Aug 20 2017, 06:03:52) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-18)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> print(django.get_version())
1.11.4
```

```
 pip install -U Django
```

```
# python
Python 3.6.1 (default, Aug 20 2017, 06:03:52) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-18)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> print(django.get_version())
2.0.1
```

urlモジュールを使っていた部分でエラー吐くようになったので
https://docs.djangoproject.com/ja/2.0/intro/tutorial01/
この辺のurls.pyを参考にして直した

例えばこの辺り

```
from django.conf.urls import include, url 

urlpatterns = [                                                                  
url(r'^accounts/', include('accounts.urls')),                               

```

を


```
from django.conf.urls import include, path

urlpatterns = [                                                                  
path('accounts/', include('accounts.urls')),                               

```

こんな感じになおすとエラーが解消された

/xxxxx/models.py

もう一箇所エラーを吐いていて
```
hoge = models.ForeignKey(fuga)
```
ってやっていたところがこけ始めたので

エラーメッセージみると

```
TypeError: __init__() missing 1 required positional argument: 'on_delete'
```
って、出てきたのでDjango2.0になってon_deleteが必須の引数になったらしい

参考
https://torina.top/detail/297/