OmniAICreator/Qiita-1.07M huggingface dataset:
複数の非同期処理を実行して結果待つ

今更ですがasync.jsのasync parallelをasync.jsを使わないでやるにはどうしたら良いのか疑問に思ったので試してみました。

# Promise

* try-catchでは同期処理例外しかキャッチできない。（Promiseをtry-catchで囲ってもPromise内部の例外はキャッチできません）
* Promise内部で例外(throw new Error())が発生した場合には、それをrejectとして処理をします。（Promise内で発生した例外は、thenの第二引数、もしくはcatchで取得することが出来ます。）
* thenやcatch内で例外(throw new Error())が起きた場合は、暗黙的にrejectとみなされる。
* thenやcatchがPromise以外を返している場合は、暗黙的にPromise.resolveとみなされる。(thenの第一引数で取得できるが、catchはできない)

Promiseの結果を返すにはPromiseのresolveもしくはrejectを実行する。
thenはPromiseの結果を受けて実行されます。


# async/await

* async functionは呼び出されるとPromiseを返す。
* async functionが値をreturnした場合、Promiseはその値をresolveする。
* async functionがエラーや何らかの値をthrowした場合はその値をrejectする。
* async functionは、await式を含むことできます。await式は、async関数の実行を一時停止し、await式の**Promise**の解決を待つ。(**値がPromiseではなかった場合は値を解決されたPromiseに変換して、それを待ちます。Promiseが拒否された場合、理由となった値をスローします。**)
* async function内のtry-catchではPromise内部で起きた非同期処理例外もキャッチできる。

# 動作確認

## Promise エラーなし

```js
const p1 = new Promise((resolve, reject) => { 
    setTimeout(() => {resolve("one")}, 2000); 
}); 
const p2 = new Promise((resolve, reject) => { 
    setTimeout(() => {resolve("two")}, 1000); 
});

Promise.all([p1, p2]).then(results => { 
    console.log(results);
}).catch(reject => { 
    console.log(reject);
});

// ["one", "two"]
```

## Promise エラーあり

```js
const p1 = new Promise((resolve, reject) => { 
    setTimeout(() => {resolve("one")}, 2000); 
}); 
const p2 = new Promise((resolve, reject) => { 
    setTimeout(() => {resolve("two")}, 1000); 
});
const p3 = new Promise((resolve, reject) => {
    reject("reject message");
});

Promise.all([p1, p2, p3]).then(results => { 
    console.log(results);
}).catch(reject => { 
    console.log(reject);
});

// reject message
```

## async/await エラーなし

```js
async function one() {
    return "one";
}
async function two() { 
    return "two";
}

Promise.all([one(), two()]).then(results => { 
    console.log(results);
}).catch(reject => { 
    console.log(reject);
});

// ["one", "two"]
```

## async/await エラーあり

```js
async function one() {
    return "one";
}
async function two() { 
    return "two";
}
async function three() { 
    throw "reject message";
}

Promise.all([one(), two(), three()]).then(results => { 
    console.log(results);
}).catch(reject => { 
    console.log(reject);
});

// reject message
```

# 補足

## 配列内のものは全てがPromiseである必要もありません。

```js
const p1 = new Promise((resolve, reject) => { 
    setTimeout(() => {resolve("one")}, 2000); 
}); 
const p2 = new Promise((resolve, reject) => { 
    setTimeout(() => {resolve("two")}, 1000); 
});

Promise.all([p1, p2, 3, "4"]).then(results => { 
    console.log(results);
}).catch(reject => { 
    console.log(reject);
});

// ["one", "two", 3, "4"]
```

## thenのcatchのところは以下でも問題ないです。

```js
Promise.all(配列).then(results => { 
    console.log(results)
}, reject => { 
    console.log(reject);
});
```

* Promise.allはawaitでも待てる

```
await Promise.all([p1, p2, p3]);
```

これは全てが解決されるもしくは１つでも拒否されたら即座に返す。

全てのPromiseの結果関係なしに全てを完了を待つ場合は以下を使います。

```
await Promise.allSettled([p1, p2, p3]);
```
Visual Studio Codeの統合ターミナル(コマンドプロンプト)起動時にvenv/conda environmentに入る方法

(2018.4.18追記)
ms-python 拡張 2018.1.0 (01 Feb 2018) にて、ターミナル起動の際に自動で仮想環境をactivateする機能が追加されました。
参考: https://github.com/Microsoft/vscode-python/issues/622

その結果、以下の内容は特に必要はなくなりました。

以下、古い記事
----

# 何の話
Visual Studio Code上でmspython拡張を使ってpython環境を構築している場合、pythonインタプリタの場所は指定できるが、Ctrl+Shift+@で起動する統合ターミナル上でvenvを使うのは少々面倒。
あらかじめvenvをactivateしたシェルからVSCodeを起動する方法もある[^1]が、VSCode起動時に毎回それを行うのは面倒なので、pythonインタプリタの指定とは別に、統合ターミナル起動時にもvenvを有効にする方法を考えた。こちらの記事[^2]からヒントを得た。

# 前提
* Windows + Visual Studio Code環境
* 統合ターミナルとしてコマンドプロンプトを使用している

他の環境にも応用が利くかもしれない。

# 方法
cmd.exeの"/k" オプションにactivateをとらせてあげることで、cmd.exe起動時にactivate.batを実行し、そのままターミナルを残してやればよい。
ワークスペースの設定などに次の項目 "terminal.integrated.shellArgs.windows" を追加する。
初回起動時に、バッチファイルの実行確認ダイアログが出るかもしれない。
これで、Ctrl+Shift+@で開いた瞬間から、統合ターミナル内から仮想環境上のcondaやpipコマンドを使ったり、pythonコンソールを起動できたりするようになる。

##Python venv環境の場合
activate.batを直接実行する

```json
{
    "terminal.integrated.shellArgs.windows": [
        "/k",
        "<venv root>\\Scripts\\activate.bat"
    ]
}
```

## conda environmentの場合
Anacondaの場合は、実行するactivate.batはAnacondaのディレクトリにあるものでよいが、仮想環境名の指定が必要。
起動がちょっと遅い。

```json
{
    "terminal.integrated.shellArgs.windows": [
        "/k",
        "<Anaconda Root>\\Scripts\\activate.bat <conda env name>",
    ]
}
```

[^1]: [virtualenvのPython仮想環境をVisual Studio Codeにも有効させる](https://qiita.com/thatbin/items/2de0a0c1ea21af10f6e3)
[^2]: [VSCodeのcmdをUTF-8で使う](https://qiita.com/te2ji/items/873e1bb42ef9b3a52c1d)
VPPでSRv6を動かしたメモ

1.はじめに
2.VPPインストール
3.VPP起動確認
4.VPP設定
5.動作確認 - パケットを見てみよう
6.まとめ

#はじめに
イベントで、VPPを使ったSRv6のデモを実施したので、その覚書となります。
SRv6については、以下のリンクに資料がありますので、ご参照ください。
[Segment Routingチュートリアル](https://www.janog.gr.jp/meeting/janog40/program/sr)


#VPPインストール
確認は、すべて仮想マシン上で実施しています。

OSは、ubuntu-16.04.3を使用
VPPのインストールは以下のリンクを参考にしています。
[VPP Install Ubuntu/Debian](https://wiki.fd.io/view/VPP/Installing_VPP_binaries_from_packages#Ubuntu.2FDebian)

VPPのバージョンは、18.01を選択してみました。

特にはまることもなくインストールは終了しました。

#VPP起動
VPP3:~$ sudo vppctl
vpp#
vpp# show version
vpp v18.01-rc1~13-g9a5e61d~b17 built by jenkins on ubuntu1604-basebuild-8c-32g-363 at Wed Jan 10 19:50:03 UTC 2018

I/Fの状況を確認

vpp# show interface
              Name               Idx       State          Counter          Count
GigabitEthernet13/0/0             2        down
GigabitEthernetb/0/0              1        down
local0                            0        down



#VPP設定：
今回は、以下のような構成で試験をしてみました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197927/172a4bd4-34a3-171b-3514-2609623a874c.png)

SRv6に関連するVPPの設定は以下の通りです
<details><summary>VPP1設定</summary><div>


``` 

sr policy add bsid A1::A3 next A2::1 next A3::1 insert
sr steer l3 1100::a/64 via sr policy bsid A1::A3
sr localsid address A1::1 behavior end psp

```

</div></details>

<details><summary>VPP2設定</summary><div>

``` 

sr localsid address A2::1 behavior end

```

</div></details>

<details><summary>VPP3設定</summary><div>

``` 

sr policy add bsid A3::A1 next A2::1 next A1::1 insert
sr steer l3 1000::a/64 via sr policy bsid A3::A1
sr localsid address A3::1 behavior end　psp

```

</div></details>

#動作確認 - パケットを見てみよう



``` 

Site-A:
Site-A#ping 1100::1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 1100::1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 12/36/49 ms
Site-A#

```

VPP1 - VPP2間

![image.png](https://qiita-image-store.s3.amazonaws.com/0/197927/c3b0fbcf-d93b-2f38-f04d-4bded5debd40.png)


VPP2 - VPP3間

![image.png](https://qiita-image-store.s3.amazonaws.com/0/197927/f2e5a601-3da7-e560-49a7-094d5997c538.png)

#まとめ
SRv6の動作をVPPを使って確認することができました。
いろいろなユースケースが提案されていますので、今後に期待です。
v1801.01 の CentOS 7 Vagrant box に日本語ロケールを追加する方法

v1710.01 は在ったんだけどな。。。

## vagrant up 直後
```
[vagrant@localhost ~]$ localectl list-locales | grep -i ja
[vagrant@localhost ~]$
```

日本語ロケールが無い。。。

## glibc-common 再インストール
```
[vagrant@localhost ~]$ sudo yum -y reinstall glibc-common
(省略)
[vagrant@localhost ~]$
```

```
[vagrant@localhost ~]$ localectl list-locales | grep -i ja
ja_JP
ja_JP.eucjp
ja_JP.ujis
ja_JP.utf8
japanese
japanese.euc
[vagrant@localhost ~]$
```

大丈夫っぽい。

## ロケール設定
```
[vagrant@localhost ~]$ sudo localectl set-locale LANG=ja_JP.UTF-8
[vagrant@localhost ~]$ sudo localectl set-keymap jp106
[vagrant@localhost ~]$ sudo localectl set-keymap jp-OADG109A
[vagrant@localhost ~]$ localectl status
   System Locale: LANG=ja_JP.UTF-8
       VC Keymap: jp-OADG109A
      X11 Layout: jp
       X11 Model: jp106
     X11 Options: terminate:ctrl_alt_bksp
[vagrant@localhost ~]$
```

ここでログインし直し。

```
[vagrant@localhost ~]$ echo $LANG
ja_JP.UTF-8
[vagrant@localhost ~]$ ls -lA
total 16
-rw-------. 1 vagrant vagrant 275  1月 19 02:23 .bash_history
-rw-r--r--. 1 vagrant vagrant  18  9月  6 16:25 .bash_logout
-rw-r--r--. 1 vagrant vagrant 193  9月  6 16:25 .bash_profile
-rw-r--r--. 1 vagrant vagrant 231  9月  6 16:25 .bashrc
drwx------. 2 vagrant vagrant  29  1月 19 02:14 .ssh
[vagrant@localhost ~]$
```

大丈夫っぽい。(2 回目)
Emacs 起動時にパッケージを自動でインストールする方法

イカした Emacs Lisp をご紹介したい。

とはいっても私が書いたわけではなく[ここにある](https://github.com/purcell/emacs.d/blob/master/lisp/init-elpa.el#L35-L61)ものを脳死でコピペしただけなのだが。

## 使い方

```elisp
(require 'package)
(setq package-archives
  '(("gnu" . "https://elpa.gnu.org/packages/")
     ("melpa" . "https://melpa.org/packages/")
     ("org" . "http://orgmode.org/elpa/")))
(package-initialize)

(defun require-package (package &optional min-version no-refresh)
  "Install given PACKAGE, optionally requiring MIN-VERSION.
If NO-REFRESH is non-nil, the available package lists will not be
re-downloaded in order to locate PACKAGE."
  (if (package-installed-p package min-version)
    t
    (if (or (assoc package package-archive-contents) no-refresh)
      (if (boundp 'package-selected-packages)
        ;; Record this as a package the user installed explicitly
        (package-install package nil)
        (package-install package))
      (progn
        (package-refresh-contents)
        (require-package package min-version t)))))

(defun maybe-require-package (package &optional min-version no-refresh)
  "Try to install PACKAGE, and return non-nil if successful.
In the event of failure, return nil and print a warning message.
Optionally require MIN-VERSION.  If NO-REFRESH is non-nil, the
available package lists will not be re-downloaded in order to
locate PACKAGE."
  (condition-case err
    (require-package package min-version no-refresh)
    (error
      (message "Couldn't install optional package `%s': %S" package err)
      nil)))
```

を `init.el` の最初らへんに追加して準備完了

### 使用例

multiple-cursors というパッケージを使いたいとする。

ただ追加するだけでいい場合は、

```elisp
(require-package 'multiple-cursors)
```

これだけで、 emacs 起動時にパッケージが存在しなければダウンロードを試みてくれる。

追加した上で更に設定したい場合は、

```elisp
(when (maybe-require-package 'multiple-cursors)
  (global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
  (global-set-key (kbd "C->") 'mc/mark-next-like-this))
```

とすると multiple-cursors のダウンロードに成功した場合のみ下の global-set-key が呼ばれる。

素敵
Windows Mixed Reality のシミュレーション機能

Windows Mixed Reality immersive headsets向けにアプリを動作確認するときは、ヘッドセットをかぶってモーションコントローラを持って行うと思いますが、コントローラの電池はすぐ切れるし、コードを変更してちょっとだけ確認したいときに毎回ヘッドセットをかぶるのが煩わしくなったりするときありませんか？
私はあります。
一瞬だけ画面を確かめて終了なんてときはいちいちかぶるの面倒くさいですし、コーディング中にスリープになっていることもしばしば。

そんなときはシミュレーション機能を使っています。
ヘッドセットをつないでいなくても、つないでいてもシミュレーションに入ることができます。

![winmr.jpg](https://qiita-image-store.s3.amazonaws.com/0/212713/f2a15b66-760e-7d47-db53-4533a3b76b8d.jpeg)

上の画像の赤丸の一番左のアイコンにカーソルを持っていくと「開発者向け」とツールチップが表示されます。
そのままクリックするとシミュレーションが開きます。
赤丸のヘッドセットのスイッチをクリックするとシミュレーションモードに入り、ヘッドセットを装着していない状態でもクリフハウスに入れます。
コントローラーの左右もそのままONにすると、コントローラーもシミュレートできるようになります。
シミュレーションの環境は通常通り使用している内容を引き継ぎます。

ここまでは、ググったら出てきたのですが、操作方法の説明が見つからなくてわからないまま放置していました。
ところがふとした拍子に、英語版ウインドウズだと、操作方法がウインドウに書かれていることが判明しました。

以下に判明したキー操作を書きます。

マウスやゲームパッドでもできるようですが、私自身がキーボードのみで操作しているため、キーボードのみ書きます。
操作するには入力設定にの「キーボードを使ってシミュレーションする」にチェックが必要です。


|キー      |       動作   |
|:-:|:-:|
|Windows+Y|入力の切り替え<br>メインディスプレイ上部に青帯が出ているときが<br>MR操作モード|
|カーソル|HMD上下左右の首振り|
|W|前進
|S|後退|
|A|左移動|
|D|右移動|
|Q|時計回りにロール|
|E|反時計回りにロール|
|shift|押しながら上記の操作を<br>すると早く動く|
|左ALT+| 押しながら左コントローラーの制御<br>操作はHMDと同じ|
|左ALT+F9|入力切り替えでMR操作モードになっているときに<br>左コントローラーの切断、接続|
|右ALT+| 押しながら右コントローラーの制御<br>操作はHMDと同じ|
|右ALT+F10|入力切り替えでMR操作モードになっているときに<br>右コントローラーの切断、接続|

F9,F10のみMR操作モードになっていないと操作できませんでした。

そして、上記操作はアプリ実行時でも有効です。Unity制アプリで試しました。
これでちょっとしたテストはヘッドセットかぶらなくても確認できますね。

※「MR操作モード」という単語は説明の為に私が勝手に作ったものです。
Let's write CWL with Emacs!

Hi!

I need a good editor to write CWL.
Here are my requirements for good editor for CWL:
- syntax highlight
- on-the-fly syntax checking (if possible)

Therefore I developed [cwl-mode](https://github.com/tom-tan/cwl-mode) to write CWL with Emacs.

# How to install

## Add MELPA repository for package.el
You can find cwl-mode in [MELPA](https://melpa.org) repository.
To add MELPA to your package repository, add the following code to `init.el`.

```el:init.el
(require 'package)
(add-to-list 'package-archives
 '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
```

## Install cwl-mode
You can install it by `M-x package-install cwl-mode`.

## (optional) Install Flycheck
Emacs can provide on-the-fly syntax checking for CWL after installing Flycheck.
You can install it by `M-x package-install flycheck` because it is also provided in MELPA repository.

### Install syntax checking tools
CWL checker in Flycheck uses [`schema-salad-tool`](https://github.com/common-workflow-language/schema_salad) and CWL syntax definition written in [SALAD](http://www.commonwl.org/v1.0/SchemaSalad.html) format.

You can install `schema-salad-tool` from [PyPI](https://pypi.python.org/pypi) by using the following command.

```shell-session
$ pip install schema_salad
```

The syntax definition file is provided in [CWL repository in Github](https://github.com/common-workflow-language/common-workflow-language).
This article uses the definition file that is bundled with [`cwltool`](https://github.com/common-workflow-language/cwltool), that is a reference implementation of workflow engine for CWL.

You can install it using the following command:

```shell-session
$ pip install cwltool
```

### Set up CWL checker
Set the path for `CommonWorkflowLanguage.yml` to `flycheck-cwl-schema-path`.
Please fix the path for `CommonWorkflowLanguage.yml` if needed.

```el:init.el
(setq flycheck-cwl-schema-path "/Users/tom-tan/.pyenv/versions/3.6.2/lib/python3.6/site-packages/cwltool/schemas/v1.0/CommonWorkflowLanguage.yml")
```

# Done!
You can see the contents of CWL file highlighted when you open files whose names are ended with `.cwl`.
Also, your Emacs can provide on-the-fly syntax checking feature after you install [Flycheck](http://www.flycheck.org).
Have fun!

See also: [Emacs でも CWL を編集したい！](https://qiita.com/tm_tn/items/79eec754338d152b092d) (same article in Japanese)
pycharmから、anacondaの環境を使いたい。osx

#やりたいこと

anacondaで環境を作っていて、pycharmからそこの環境を使いたいとおもいました。

#anacondaの環境しらべる

<img width="499" alt="スクリーンショット 2018-01-19 20.55.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/65391/2ddd32e3-dd15-7693-9806-9ef6acac7f48.png">
今回例として、python35というanacondaの環境をpycharmで利用しようと思います。

まずは、anacondaの仮想環境のpathを取得します。僕の場合は下記のようなpathでした。envsの中に環境があるので、そこまでのpathをコピーします。
```/Users/ユーザー名/anaconda2/envs/python35```
#pycharm側設定

次にpycharm側で、preferrence -> Project:プロジェクト名 -> project interpreter にいきます。project inspecterのリストボックスの横、歯車マークのボタンを押して、add localします
<img width="1026" alt="スクリーンショット 2018-01-19 21.44.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/65391/bfbb945e-1816-6ed3-8c6c-3b5ae58943f2.png">

表示されたAdd Local Python Interpreter画面で、Existing environmentを選択し、Interpreterに下記のpathを記入してOK。
```/Users/ユーザー名/anaconda2/envs/python35/bin/python```

<img width="886" alt="スクリーンショット 2018-01-19 21.51.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/65391/5c2de47c-756b-9899-aed9-3789be300a5a.png">

これで、anaondaの環境と連携されました。
Yenten(YTN)のマイニングプールを作ったので裏側公開！　序章（マイニング編）

※移転しました。
[xshsaku にわかエンジニアブログ](http://xshsaku.coiner.site/)

## Yenten(YTN)のマイニングプールを作ったので裏側公開！

[円天恋な〜プール](https://ytn.coiner.site/)

## まず初めにYentenとは

<img alt="yenten price" src="https://www.coingecko.com/ja/%E3%82%A6%E3%82%A3%E3%82%B8%E3%82%A7%E3%83%83%E3%83%88%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88/%E3%83%81%E3%83%83%E3%82%AB%E3%83%BC/yenten/jpy.jpg">

[円天公式サイト](https://conan-equal-newone.github.io/yenten/index2.html)

「円天詐欺」についてはググってください。無関係ですが。

仮想通貨として、突如現れたYenten(YTN) 発行日は2017/10となっています。
ネタでしかない通貨ですが、日本のみならず、海外マイナー（採掘者）にも人気が高く値段も高騰しています。
※本家サイトもところどころジョークが入っている。

相場は1/19時点で `1YTN=40円台` 

ホワイトペーパーというほどでもないですが、
`本プロジェクトはASICマイニングを撲滅することによってCO2排出を制限しより良い環境を作っていこう` という記載があります。

### ASIC耐性とは

ASICは一定のアルゴリズムに対し、優れた計算能力をもつ機械です。対応するアルゴリズム専用に作られているためアルゴリズム変更となるとASIC機器はほぼ電気代だけを使うゴミになります。

Yenten(YTN) のアルゴリズムは `yescryptr16` と呼ばれる仕組みでASICといったマイナー専用機器を排他するように設計されています。※可変的にアルゴリズムが変わる。

またアルゴリズムを計算する際の必要メモリ大きくGPUでは困難な設計となっているため、高度なサーバースペックは要求されません。

そのため、みなさんが利用しているPCもしくはラズパイ、スマートフォンでも採掘は可能です。

※注意：Bitzenyも同じくCPUマイニングとなっている `yescrypt` ですがアルゴリズム方式は異なります。

## マイニングプールを作るには

早速本題に入ります。

マイニングプールを作るには以下の手順を踏む必要があります。

1. 仮想通貨ウォレットの構築
2. Stratumサーバーというウォレットの操作、マイニング（アルゴリズム計算）を行うサーバーの構築
3. [MPOS](https://github.com/MPOS/php-mpos) PHPで作られたフロントエンドの構築

の3点から成り立ちます。

### マイニングプールを作る前にまずマイニング（採掘）をしてみよう

[円天恋な〜プール](https://ytn.coiner.site/)

こちらに現在手数料かからないプールを作っていますので、登録してマイニングを実施してみましょう。

[Git](https://github.com/JayDDee/cpuminer-opt/releases)

Windowsの方は `cpuminer-opt-3.7.9-windows.zip` をLinux/Macはソースコードをダウンロードしコンパイルします。

```bash:LinuxMac
$ wget 'https://github.com/JayDDee/cpuminer-opt/archive/v3.7.10.tar.gz'
$ tar xzf v3.7.10.tar.gz
$ cd cpuminer-opt-3.7.10
$ chmod 700 autogen.sh
$ touch  ChangeLog
$ ./autogen.sh
$ ./configure CFLAGS="-O3 -march=native -funroll-loops -fomit-frame-pointer"
$ make
```

これでマイニングに必要なバイナリが出来るはずです。
実際に動かす際はカレントディレクトリで以下のようにコマンドを実行します。

```
$ ./minerd -a yescryptr16 -o stratum+tcp://ytn.coiner.site:12100 -u `User`.`worker` -p `password`
```

実行すると以下のようにログが出てきます。 yay!!!が出てくればOK!

```
[2018-01-19 21:30:27] accepted: 1307/1307 (100.00%), 0.10 khash/s (yay!!!)
[2018-01-19 21:30:41] thread 0: 1432 hashes, 0.11 khash/s
[2018-01-19 21:30:41] accepted: 1308/1308 (100.00%), 0.11 khash/s (yay!!!)
[2018-01-19 21:30:41] thread 0: 15 hashes, 0.14 khash/s
[2018-01-19 21:30:41] accepted: 1309/1309 (100.00%), 0.14 khash/s (yay!!!)
```

ずっと稼働させたい時には、nohupをつけて実行するといいでしょう。他にもsystemdに登録するなど

```
$ echo "./minerd -a yescryptr16 -o stratum+tcp://ytn.coiner.site:12100 -u `User`.`worker` -p `password`" > mining.sh
$ nohup bash mining.sh &
```

ログをみたい時はnohup.outをtailするなりしてください。

次回はマイニングプールを作るには？に記載した以下3点を掲載していきますー。
余力があれば。

**TODO**

1. 仮想通貨ウォレットの構築
2. Stratumサーバーというウォレットの操作、マイニング（アルゴリズム計算）を行うサーバーの構築
3. [MPOS](https://github.com/MPOS/php-mpos) PHPで作られたフロントエンドの構築

寄付いただくと記事を書くスピードが上がるかもしれませんw

BTC: `3MHwSRfFwUtJJ1ZMDitFfvx1n7FffFvXRu`
ETH: `0xEa00632a438dc250136f5d40cf80EcB1fA24E027`
ZNY: `Zkub2vUJYeURsqnad81dE7R4S5bYWNgnm8`
ZEC: `t1RKPqQtUHZPMPVfdt34Fd6PKLWcP2kMGL2`


仮想通貨技術を使ったシステムの（構築など）相談をされたい方は、プロフィールのメールまでご連絡ください。
Ubuntu16.04(on WSL)にRubyをインストールする

Windows Subsystem for Linux上で動くUbuntuにRubyをインストールしてみたので、その手順をメモとして公開します（目新しい情報はないと思います）。
今回は複数バージョンのRubyを使うことを想定し、rbenvとruby-buildを用いてRuby環境を構築することにしました。

# rbenvとruby-buildのインストール
## まずはインストール済みパッケージのアップデート

```console
$ sudo apt-get update
$ sudo apt-get upgrade
```
## ruby-buildに必要なパッケージをインストール
必要なパッケージはruby-buildの[Wiki](https://github.com/rbenv/ruby-build/wiki)に記載されています。

```console
$ sudo apt-get install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev
```

## rbenvのインストール
rbenvの[Basic GitHub Checkout](https://github.com/rbenv/rbenv#basic-github-checkout)に従うだけ。とても簡単。

```console
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
```

bashの拡張機能が早くなるようなので、おまじない的に実行しておく（失敗しても気にしない）

```console
$ cd ~/.rbenv && src/configure && make -C src
```

Pathの設定とrbenvをシェルに統合するためのおまじない

```console
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
```

## ruby-buildのインストール
ruby-buildの[Installation](https://github.com/rbenv/ruby-build#installation)にある"As an rbenv plugin"に従うだけ。

```console
$ mkdir -p "$(rbenv root)"/plugins
$ git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
```

さて、ここまで終われば後はRubyをインストールするだけです。

## Rubyのインストール
インストール可能なRubyのバージョンを調べる

```console
$ rbenv install --list
```
ずらずら～っとインストール可能なRubyが表示されるので、目的のバージョンを探します。
今回は2.5.0をインストールしてみました。
実行するとこんな感じにインストールが始まります。そこそこ時間がかかります。

```console
$ rbenv install 2.5.0
Downloading ruby-2.5.0.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.0.tar.bz2
Installing ruby-2.5.0...
Installed ruby-2.5.0 to /home/cocoabreak/.rbenv/versions/2.5.0
```

これだけではまだRubyを使うことができません。試しに以下のコマンドを実行してみると……

```console
$ ruby --version
rbenv: ruby: command not found

The `ruby' command exists in these Ruby versions:
  2.5.0
```
こんな感じにコマンドが無いよと怒られます。
これはRubyのインストールは行ったものの、どのバージョンを使用するかまだrbenvに教えてないからです。

Rubyをインストールした後に一度rehashして、使うバージョンを指定しましょう。今回はディレクトリー単位にRubyのバージョンを切り替えられるよう、localモードでバージョン指定しています。

```console
$ rbenv rehash
$ rbenv local 2.5.0
```

改めてRubyのバージョンを確認してみましょう。

```console
$ ruby --version
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]
```

無事Rubyが使えるようになりました。
テスト駆動開発による組み込みプログラミング～モック＆フラッシュドライバ編～

今までの続き。

[テスト駆動開発による組み込みプログラミングをgoogletestでやる](https://qiita.com/tomoyuki-nakabayashi/items/816e35f2099b021992dd)
[テスト駆動開発による組み込みプログラミングをgoogletestでやる8章](https://qiita.com/tomoyuki-nakabayashi/items/19014f5904cfe2d860f8)

# 前置き

[Amazon.co.jp: テスト駆動開発による組み込みプログラミング ―C言語とオブジェクト指向で学ぶアジャイルな設計](https://www.amazon.co.jp/%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E3%81%AB%E3%82%88%E3%82%8B%E7%B5%84%E3%81%BF%E8%BE%BC%E3%81%BF%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-%E2%80%95C%E8%A8%80%E8%AA%9E%E3%81%A8%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%81%AA%E8%A8%AD%E8%A8%88-James-W-Grenning/dp/4873116147)

繰り返しになりますが、組込みでテスト駆動開発を行うにあたってのバイブルです。10章ではFlashドライバを題材として、モックを扱います。
ただ、本に書いてある内容を動かそうとするだけで、それなりの難易度です。色々端折られていて、本の内容を写経しただけでは動きません！（サンプルとして完成したコードは配布されています）

そこで、テストを1個1個、順番に動かしたレポジトリを用意しました。
https://github.com/tomoyuki-nakabayashi/TDDforEmbeddedC_FlashDriver

コミット履歴を整理するのが面倒なので、最初からやってみたい方は、pass FirstWrite(SHA:cba030eac89b87e6a9d3ce33a0418e99db8c1a0b)から始めて下さい。

# MockIOのコード

本の中で紹介されているMockは200行以上もあり、とっつきにくいです。
googlemockが非常に優秀なので、同じことが次の25行くらいでできます。

```cpp
#ifndef TEST_MOCK_MOCK_IO_H_
#define TEST_MOCK_MOCK_IO_H_
#include "gmock/gmock.h"
#include "IO.h"

class MockIO {
public:
  MOCK_METHOD1(IO_Read, ioData(ioAddress));
  MOCK_METHOD2(IO_Write, void(ioAddress, ioData));
};

extern MockIO *mockIO;

extern "C" {
  void IO_Write(ioAddress addr, ioData data)
  {
    return mockIO->IO_Write(addr, data);
  }

  ioData IO_Read(ioAddress addr)
  {
    return mockIO->IO_Read(addr);
  }
}

#endif //  TEST_MOCK_MOCK_IO_H_
```

ね、簡単でしょう？

# テストコードからのモックの使い方

例えば、テスト対象コードのFlash_Write(address, data)を呼び出したときに、IO_Write(address, data)が1度呼び出されることをテストしたい場合は、次のようになります。

```cpp
TEST_F(FlashDriverTest, WriteSucceeds_ReadyImmediately)
{
  EXPECT_CALL(*mockIO, IO_Write(address, data)).Times(1);
  int result = Flash_Write(address, data);
}
```

事前にmockIOのオブジェクトを用意する必要があります。
googlemockはオブジェクトを使いまわすと、前回のEXPECT_CALLを引き継いでしまって意図せぬ動作になります。テストケースごとに作り直すと楽です。

```cpp
#include "mock/MockIO.h"
MockIO *mockIO;

class FlashDriverTest : public ::testing::Test
{
  virtual void SetUp()
  {
    mockIO = new MockIO();
  }

  virtual void TearDown()
  {
    delete mockIO;
  }
};
```

モックからの返り値を設定した場合は、次のようにアクションを設定します。
これでIO_Read()を呼び出したときに返り値として、ReadyBitを返してくれます。

```cpp
TEST_F(FlashDriverTest, WriteSucceeds_ReadyImmediately)
{
  EXPECT_CALL(*mockIO, IO_Read(StatusRegister)).WillOnce(Return(ReadyBit));
  int result = Flash_Write(address, data);
}
```

# 余談

C言語の関数をモックする場合は、モックの扱いに注意が必要です。過去めちゃくちゃハマりました。C言語の関数をモックしていて困ったら連絡下さい。力になれるかもしれません。
モックをグローバル領域に置かないといけないため、複数のテスト用ソースコードからモックを共有したい場合は、どこかで1度だけ、モックのポインタを定義するようにして下さい。
マルチスレッドで動かすと動作がおかしくなりそうですが、今までのところ、問題になったことはないです。

.cファイルをnamespace内でincludeして、namespace内で固有のモックオブジェクトを作ることもできます。この方法を取ると、モックオブジェクトの共有が不要になりますが、対象の.cファイルがc++のコンパイラでコンパイルされてしまい、厳密なC言語のテストにならないです。

本の残りも随時やっていきます。
PhpStormで楽チンansible-vault

# はじめに
PhpStorm使ってるともう全部PhpStormでやりたくなりますよね？
ってことで下みたいに今回はansible-vaultのencryptとdecryptをコンテキストメニューでdecrypt、encryptできるよう設定してやりましょう。
![使用](https://qiita-image-store.s3.amazonaws.com/0/68254/48f4839b-4c3c-9667-78c9-3bc86263e460.png)


# 設定方法

PhpStormの設定を下記のようにやります。
![設定](https://qiita-image-store.s3.amazonaws.com/0/68254/ccbd8d59-e0e3-81da-82e0-7774deba5ed8.png)


| key      | value         |
|----------|---------------|
|Name      | (encryptの場合) encrypt<br>(decryptの場合) decrypt   |
|Group     | ansible-vault |
|Program   | /usr/local/bin/ansible-vault |
|Arguments |(encryptの場合)<br> --vault-password-file=/etc/ansible-vault-password encrypt \$FilePath\$ <br>(decryptの場合)<br> --vault-password-file=/etc/ansible-vault-password decrypt \$FilePath$|
|Working directory | \$FileDir$ |

``/etc/ansible-vault-password``にansible-vaultのパスワードを記載します。

これでOKです！
PyQt5 > UDP > echo server > Multicast版? | non-Multicast版

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04 LTS desktop amd64
TensorFlow v1.2.1
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
ADDA v.1.3b6
PyQt5 v5.5.1
```

プロジェクト開始: https://qiita.com/7of9/items/4077c92b9a773e054193


### 処理概要

- UDP (ポート7000)で受信
- 受信した文字をそのままエコーバックする

### 参考

https://stackoverflow.com/questions/23605825/not-receiveing-datagram-with-pyqt5-multicast-udp

### code v0.1 > Multicast版?

```udp_echoserver_180119.py
import PyQt5.QtNetwork as qtn

'''
v0.1 Jan. 19, 2018
  - echo back
'''

UDP_PORT = 7000

groupaddr = qtn.QHostAddress("192.168.0.1") 
udp = qtn.QUdpSocket()
udp.setSocketOption(qtn.QAbstractSocket.MulticastLoopbackOption,1)
udp.setSocketOption(qtn.QAbstractSocket.MulticastTtlOption,32)
udp.bind(qtn.QHostAddress.AnyIPv4,UDP_PORT,qtn.QUdpSocket.ShareAddress)
ni = qtn.QNetworkInterface()
udp.joinMulticastGroup(groupaddr,ni)

while True:
    if udp.hasPendingDatagrams():
        data,host,port = udp.readDatagram(udp.pendingDatagramSize())
        udp.writeDatagram(data, host, port)
        print(data)
        print(host)
        
udp.leaveMulticastGroup(groupaddr)
udp.close()
```


## 実行

受信側はUbuntu 16.04 LTSで、送信側はRaspberry Piとしている。

```txt:run(Ubuntu)
$ python3 udp_echoserver_180119.py 
b'test\n'
<PyQt5.QtNetwork.QHostAddress object at 0x7f4143108908>
b'test\n'
<PyQt5.QtNetwork.QHostAddress object at 0x7f4143108978>
...
```

```txt:run(RPi)
pi@raspberrypi ~ $ echo "test" | nc -u 192.168.0.9 7000
test
^C
pi@raspberrypi ~ $ echo "test" | nc -u 192.168.0.9 7000
test
^C
...
```

### code v0.2 > non-Multicast版


```udp_echoserver_180119.py
import PyQt5.QtNetwork as qtn

'''
v0.2 Jan. 19, 2018
  - remove multicast feature
v0.1 Jan. 19, 2018
  - echo back
'''

UDP_PORT = 7000

udp = qtn.QUdpSocket()
udp.bind(UDP_PORT)

while True:
    if udp.hasPendingDatagrams():
        data,host,port = udp.readDatagram(udp.pendingDatagramSize())
        udp.writeDatagram(data, host, port)
        print(data.decode("utf-8"))
        print(host)

udp.close()

```
MemoryEnhancer + PyQt5 > 入門 > LCD表示

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04 LTS desktop amd64
TensorFlow v1.2.1
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
ADDA v.1.3b6
PyQt5 v5.5.1
```

### 概要

プロジェクト開始: https://qiita.com/7of9/items/4077c92b9a773e054193

PyQt5を触ってみる。

### 参考

- [PyQt5とpython3によるGUIプログラミング［１］](https://qiita.com/kenasman/items/70a3ef914b0e7e55a123)

### code

```test_pyqt5_180119.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import  *


def main():
    app = QApplication(sys.argv)
    w = QWidget()
    w.resize(250, 150)
    w.setWindowTitle('Window01')

    WiNum = QLCDNumber()
    BoxLay = QVBoxLayout()
    BoxLay.addWidget(WiNum)
    w.setLayout(BoxLay)

    WiNum.display(3.14)

    w.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()
```

### 実行


```bash
$ python3 test_pyqt5_180119.py
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/26f1a077-b2ea-a3aa-fe48-038c22cf55bf.png)

### Link

http://doc.qt.io/qt-5/qlcdnumber.html

### setDigitCount() > 表示桁を増やす

参考: http://dorafop.my.coocan.jp/Qt/Qt006.html

```test_pyqt5_180119.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import  *


def main():
    app = QApplication(sys.argv)
    w = QWidget()
    w.resize(250, 150)
    w.setWindowTitle('Window01')

    WiNum = QLCDNumber()
    BoxLay = QVBoxLayout()
    BoxLay.addWidget(WiNum)
    w.setLayout(BoxLay)

    WiNum.setDigitCount(10)
    WiNum.display(3.141592653589)

    w.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

```


![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/09b037c3-7663-11b7-9691-e065b0759daf.png)
3gドングルを使いATコマンドで日本語のSMSを送信する

# 前書き
ATコマンドについて、日本語で書かれた記事がほとんどありません。

最近Soracomの方がATコマンドについて書かれていましたが、非常に勉強になります。
これから始めてみる方はとても参考になるのではないでしょうか。

- http://bearmini.hatenablog.com/entry/at-command1



# やりたいこと
ATコマンドを使い、携帯に日本語（UCS2）でSMSを送信します。

以下、間違いなどがあれば指摘してもらえると助かります。

# 環境

RaspberryPiを使います。

- RasbperryPi3

```
$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 9.1 (stretch)
Release:        9.1
Codename:       stretch
```
- 3gドングル
    - AK-020 : https://soracom.jp/products/ak-020/
    - Soracom Air Sim : https://soracom.jp/products/
- 携帯
    - HUAWEI P9 lite
    - Android 7.0

# SMSを送る
まずは普通に（GSM 7 bit≒Asciiで）SMSを送ってみます（[参考](https://en.wikipedia.org/wiki/GSM_03.38#GSM_7-bit_default_alphabet_and_extension_table_of_3GPP_TS_23.038_/_GSM_03.38)）。

Linuxの場合、ドングルを刺すと`/dev/ttyUSB0~3`が作られます。
このうち、ATコマンドを発行してみると、`ttyUSB0`と`ttyUSB1`がmodemとして動作していることがわかります。
どちらを使ってもよいのですが、今回は`ttyUSB1`を使用します。

例によって`screen`をインストールし、以下のコマンドを実行していきます。
以下、`>> `は端末上で入力するコマンド、`<< `はmodemからの応答を表します。

```
$ screen /dev/ttyUSB1 115200
>> AT+CFUN=1
<< OK
>> AT+CMGF=1
<< OK
>> AT+CMGS="電話番号"
> test(Ctrl-z)
<< +CMGS: ***
<<
<< OK
```
おくられました。よかったですね。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/48543/6cc225a2-2a22-3944-25e1-017d19d57f8d.png)

各コマンドはそれぞれ以下のような意味を持ちます。

- AT+CFUN=1  
modemの機能制限に関する設定です。  
1は機能制限をとっぱらいます。
- AT+CMGF=1  
SMSを送信モードを設定します。  
text modeで送信します。
- AT+CMGS="電話番号"  
電話番号に対してSMSを送信します。  
> test(Ctrl-z)  
はtestと入力した後にCtrl-zを入力します。

# 日本語（UCS2）でSMSを送る

USC2（USC2 ⊂ UTF-16）でSMSを送ります。

```
$ screen /dev/ttyUSB1 115200
>> AT+CFUN=1
<< OK
>> AT+CMGF=1
<< OK
>> AT+CSMP=1,167,0,8
<< OK
>> AT+CSCS="UCS2"
<< OK
>> AT+CMGS="電話番号"
> 3042(Ctrl-z)
<< +CMGS: ***
<<
<< OK
```
送られました。よかったですね。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/48543/1bd96ddd-fb85-2eed-1f5b-c43b5d10ec10.png)

- AT+CSMP=1,167,0,8  
SMSの送信や保存についての設定です。  
UCS2で送信する場合、4番目の要素が重要で、8とする必要があります。  
8ではなく24（Flash message）にすると地震速報とか緊急速報的なメッセージの出方をします（[参考](https://en.wikipedia.org/wiki/Data_Coding_Scheme#DCS_Values)）。
- AT+CSCS="UCS2"  
エンコードを設定します。  
モジュールによってはUCS2に対応していない場合があります。  
対応しているかどうかは、`AT+CSCS=?`で確認ができます。  
AK-020の場合は以下のような感じです。

```
AT+CSCS=?
+CSCS: ("IRA", "GSM", "HEX", "PCCP437", "8859-1", "UCS2", "UCS2_0X81")
```

このエンコードの設定は受信するSMSにも影響するので、一つのmodemでSMSを送受信する場合は気を付けましょう。
GSM 7 bitに設定したい場合は8859-1を設定します。
また、携帯によって表示が異なりますが、UCS2で使える絵文字も送ることができます。

![3.png](https://qiita-image-store.s3.amazonaws.com/0/48543/3b9fd237-3d73-fcf6-b606-e79fdd25ab46.png)

# 参考

- http://www.smssolutions.net/
- http://www.developershome.com/
- https://ja.wikipedia.org/wiki/Unicode%E3%81%AEEmoji%E3%81%AE%E4%B8%80%E8%A6%A7

# 雑談

SMSを送受信するだけなら、直接ATコマンドを実行しなくても、[gammu](https://wammu.eu/gammu/)という良いツールがあります。
GPLですがPythonなどにライブラリも公開されていますし、1行のコマンドでSMSの送受信を行うこともできます。
ただ、色々試したのですがどうしてもUCS2でSMSを送信することができませんでした・・・。

コードから使いたく、自前で超簡単なものを作りましたので、よかったら[どーぞ](https://gist.github.com/miyako-ep/00c888ce35d86e6a685e82118e82ecd0#file-attest-rb)。
YouTube DATA APIを利用し、再生リスト内の動画のタグ情報を取得する。

**YouTube DATA API**を利用すると、YouTube上の様々な情報を操作できます。
https://developers.google.com/youtube/v3/docs/

少しニッチな使い方ですが、再生リスト内の動画のタグ情報を取得しようとしたときのメモです。

## 動画からタグ情報を取得する。
まずは、通常の動画のタグ情報の取得方法。

YouTube DATA APIの**Videos**を利用することで、動画に登録されているタグ情報を取得することができます。
https://developers.google.com/youtube/v3/docs/videos/list

```javascript:JavaScript
$.ajax({
  url: 'https://www.googleapis.com/youtube/v3/videos', // YouTube DATA API: videos
  dataType: 'json',
  data: {
    part: 'snippet',
    id: '8OROgK7r7MU', // タグを取得したいYouTubeのvideoId
    maxResults: 50,
    key: 'xxx' // APIキー
  }
})
.done(function(vidoeRes) {
  console.log(vidoeRes.items[0].snippet.tags); // タグを取得
});
```
**videoId**は、動画URLの`v=8OROgK7r7MU`部分です。
https://www.youtube.com/watch?v=8OROgK7r7MU

また、APIキーは、事前に取得しておきましょう。
https://developers.google.com/youtube/registering_an_application

## 再生リストの各動画のタグ情報を習得する。
続いて、本題。

YouTube DATA APIの**playlistItems**を利用すると、再生リストに登録されている各動画の情報を取得することができます。
https://developers.google.com/youtube/v3/docs/playlistItems/list

しかし、**playlistItems**で取得した動画の情報には、タグの情報がありません。
そこで、**playlistItems**で取得した**videoId**をもとに、**videos**でもう一度動画情報を取得し、再生リストの各動画のタグ情報を取得します。

```javascript:JavaScript
let videoIdArray = [];
let _tagsArray = [];
let tagsArray = [];

// PlaylistItems APIで各動画の情報を取得
$.ajax({　
  url: 'https://www.googleapis.com/youtube/v3/playlistItems', // YouTube DATA API: PlaylistItems
  dataType: 'json',
  data: {
    part: 'snippet',
    playlistId: 'PLC9941FF2E16B9532', // Youtube 再生リストID
    maxResults: 50,
    key: 'xxx'
  }
})
.done(function (playlistItemRes) {
  const videos = playlistItemRes.items;
  
  for (let i = 0; i < videos.length; i++) {
    let _videoId = videos[i].snippet.resourceId.videoId;
    videoIdArray.push(_videoId); // videoIdのみ抽出し、配列位に格納
  }

  for (let i = 0; i < videoIdArray.length; i++) {
    let videoId = videoIdArray[i];

    // videos　API で各動画の情報を再度取得
    _tagsArrey.push($.ajax({
      url: 'https://www.googleapis.com/youtube/v3/videos', // YouTube DATA API: videos
      dataType: 'json',
      data: {
        part: 'snippet',
        id: videoId,
        maxResults: 50,
        key: 'xxx'
      }
    }));
  }
  $.when.apply($, _tagsArray).done(function (){　// 再生リストの順番を保証
    for (let i = 0; i < arguments.length; i++) {
      tagsArray.push(arguments[i][0].items["0"].snippet.tags);
    }
    
    console.log(tagsArray);　// タグの情報が配列に格納されています。
  });
});
```

再生リストの順番の保証は、こちらを参考にさせていただきました。
[結果の順番を保証して、且つ『並列』でAjax通信を行う方法](https://qiita.com/YusukeHirao/items/bca14c5f2fe4026fd4d7)
GCPインスタンスに複数外部IPを設定


インスタンスに直接IPアドレスを設定するのかと思っていましたが、何やら転送ルールなるものを設定して
任意の条件のリクエストをフォワーディングさせることで設定できるようです。

## 参考URL

https://cloud.google.com/compute/docs/protocol-forwarding/


## まず静的IPアドレスを必要な数だけ予約

## ターゲットインスタンスを作成

```
gcloud compute target-instances create [target-instance-name] --instance [ex-instance-name]
```

#### 補足

```
# 一覧表示
gcloud compute target-instances list
# 取得
gcloud compute target-instances describe [TARGET_INSTANCE]
# 削除
gcloud compute target-instance delete [TARGET_INSTANCE]
```


## 転送ルールを作成

```
# ポート80に来た `111.111.111.111` へのTCPリクエストを `[instance-name]` へ転送する
gcloud compute forwarding-rules create [forwarding-rule-name]] \
    --ip-protocol TCP \
    --ports 80 \
    --target-instance [instance-name] \
    --address 111.111.111.111

# ポート80に来た `222.222.222.222` へのTCPリクエストを `[instance-name]` へ転送する
gcloud compute forwarding-rules create [forwarding-rule-name]] \
    --ip-protocol TCP \
    --ports 80 \
    --target-instance [instance-name] \
    --address 222.222.222.222
```

#### 補足

```
一覧表示
gcloud compute forwarding-rules list
```


## Nginxで対象のIPアドレスを使う場合

下記のエラーがでてしまう

```
[root@hoge-instance nginx]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: [emerg] bind() to 12.34.56.78:80 failed (99: Cannot assign requested address)
nginx: configuration file /etc/nginx/nginx.conf test failed
```

下記の設定で回避

```
echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
```
[iOS] WKWebViewでJavaScriptを使って、CSSの追加をする

```swift
// ドキュメントを表示する前にJavaScriptで以下のCSSを追加している。
// var newStyle = document.createElement('style');
// newStyle.type = 'text/css';
// document.getElementsByTagName('head').item(0).appendChild(newStyle);
// css = document.styleSheets.item(0);
// css.insertRule('#header{display:none;}',0); // 非表示
// css.insertRule('a{pointer-events: none;}',0); // リンク無効
let js = "var newStyle = document.createElement('style');newStyle.type = 'text/css';document.getElementsByTagName('head').item(0).appendChild(newStyle);css = document.styleSheets.item(0);css.insertRule('#header{display:none;}',0);css.insertRule('#page>:not(article){display:none;}', 0);css.insertRule('a{pointer-events: none;}',0);"

func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
    webView.evaluateJavaScript(js)
}
```
ネットワーク　メモ

# write erase

初期化

# enable 

root

# conft

# int vlan 1

vlan1のインターフェースを設定するコマンド。

# ip addr [ip-addr] [net-mask]

ip addrを設定

# no shutdown

最初は落ちているので立ち上がらせるコマンド。

# exit

# int fastether 0

fastether 0の設定

vlanはデフォルトで1
# router ospf 1

ospfでルーティングを設定
通信相手を指すIDを1として設定（1以外でも大丈夫）

# network [ip-addr] [wild-mask] area [area-number]

（例）network 172.16.0.0 0.0.0.255 area 0

# ルーティングテーブルを見る

show ip route

# loopbackアドレスの設定

int loopback 0

# 忘れた

show ip int

# running-configを見る

show run

# ケーブルの豆知識

違うものをつなぐときはストレート
同じもの同士をつなぐ時はクロス
（最近のものはストレートでも良いものが多い）

# ルーティング

ip route [addr] [netmask] [dst-addr]

# 保存

write memory

# ルートフィルタリング（OSPF）

```
(config)ip prefix-list [filter-name] deny [ip-addr]/[prefix]
(config)router ospf 1
(config-router)distribute-list prefix [filter-name] in
```

# 設定

```
auto eth1
iface eth1 inet static    #ここでStaticにすることでIPを固定にする設定にする
iface eth1 dhcp    #dhcpになる
address 192.168.xx.xx     #設定したいIPアドレス
netmask 255.255.x.x       #設定したいIPアドレスのネットマスク
gateway 192.168.x.x       #設定したいIPアドレスのゲートウェイ
dns-nameservers 192.x.x.x #DNSのサーバーIPを書き込む
```

# iptables

・状態を見る

```
iptables --list -v
```

・設定

```
iptables -t filter -A INPUT -p tcp --dport 22 -j ACCEPT
#-t:
# タイプ設定。通常はfilter。
#-A:
# ADD。設定を追加する。INPUTやOUTPUTなどを指定できる。-Dで消せる。
#-p:
# プロトコル。tcpを指定するとTCPになる。
#--dport:
# -pの直後に指定することでポートを指定できる。送信先のポート。
#-j:
# ジョブ。ACCEPTやDROPなどがある。
```

・参考

https://qiita.com/Tocyuki/items/6d90a1ec4dd8e991a1ce#%E8%A8%AD%E5%AE%9A%E3%81%AE%E7%A2%BA%E8%AA%8D%E6%96%B9%E6%B3%95
uniteからdeniteに移行したメモ

Denite.nvim
https://github.com/Shougo/denite.nvim
> Dark powered asynchronous unite all interfaces for Neovim/Vim8

vim用の高機能ファイラーです。
NeoVimかVim8で動作します。

## インストール

下記参照
http://yellowho.hatenablog.com/entry/2016/11/11/021346

いろいろ書いてありますが、python3とtypingというのを入れたらうごきました。

```
$ brew install python3
$ pip3 install --upgrade pip setuptools wheel
$ pip3 install typing
```

vimで下記実行

```
:echo has('python3')
=> 1が出ればOK
```

### NeoBundleを使用した場合

下記を追記してインストール

```.vimrc
NeoBundle 'Shougo/denite.nvim'
```
vimで下記実行

```
:NeoBundleInstall
```

### dainを使用した場合

未検証

## 設定

Unite.vimを使っていた影響で表示などそちらに寄せてます

```vim:.vimrc
nnoremap [denite] <Nop>
nmap <C-c> [denite]

"現在開いているファイルのディレクトリ下のファイル一覧。
nnoremap <silent> [denite]f :<C-u>DeniteBufferDir
      \ -direction=topleft -cursor-wrap=true file file:new<CR>
"バッファ一覧
nnoremap <silent> [denite]b :<C-u>Denite -direction=topleft -cursor-wrap=true buffer<CR>
"レジスタ一覧
nnoremap <silent> [denite]r :<C-u>Denite -direction=topleft -cursor-wrap=true -buffer-name=register register<CR>
"最近使用したファイル一覧
nnoremap <silent> [denite]m :<C-u>Denite -direction=topleft -cursor-wrap=true file_mru<CR>
"ブックマーク一覧
nnoremap <silent> [denite]c :<C-u>Denite -direction=topleft -cursor-wrap=true bookmark<CR>
"ブックマークに追加
nnoremap <silent> [denite]a :<C-u>DeniteBookmarkAdd<CR>

".git以下のディレクトリ検索
nnoremap <silent> [denite]k :<C-u>Denite -direction=topleft -cursor-wrap=true
      \ -path=`substitute(finddir('.git', './;'), '.git', '', 'g')`
      \ file_rec/git<CR>

call denite#custom#source('file'    , 'matchers', ['matcher_cpsm', 'matcher_fuzzy'])

call denite#custom#source('buffer'  , 'matchers', ['matcher_regexp'])
call denite#custom#source('file_mru', 'matchers', ['matcher_regexp'])

call denite#custom#alias('source', 'file_rec/git', 'file_rec')
call denite#custom#var('file_rec/git', 'command',
  \ ['git', 'ls-files', '-co', '--exclude-standard'])

call denite#custom#map('insert', '<C-N>', '<denite:move_to_next_line>', 'noremap')
call denite#custom#map('insert', '<C-P>', '<denite:move_to_previous_line>', 'noremap')
call denite#custom#map('insert', '<C-W>', '<denite:move_up_path>', 'noremap')


```

### 使い方

下記は上記設定にした場合のキーマップです。
.vimrcをいじると自分の好きなキーにマッピングできます。

```
Ctrl+c f : 開いているファイルのディレクトリにあるファイル一覧
Ctrl+c b : バッファ一覧
Ctrl+c m : 以前開いていたファイル一覧
```

## 課題

ctags検索だけやたら遅くていい方法を探し中
→
https://qiita.com/hisawa/items/fc5300a526cb926aef08
fzf.vimを使ってます(2019.03.12追記)
GASで既存のサイトの表示確認し、200以外のコードが返ってきたらslackに通知する

- google driveにspreadsheetを作成する
- sheet名をsiteにし、A列にurlを書く（複数可）
![スクリーンショット 2018-01-19 18.28.52.png](https://qiita-image-store.s3.amazonaws.com/0/24013/ba172f94-4952-507c-b335-903ae1ab727b.png)

- スクリプトエディタを開く
![スクリーンショット 2018-01-19 18.29.09.png](https://qiita-image-store.s3.amazonaws.com/0/24013/66715f03-e02c-3cdc-fadb-17445d1ce0a2.png)

- 書く

```gas
function sitesCheck(){
  var urls = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("site").getRange("A:A").getValues();
  for(var i=0; i < urls.length; i++) {
    var url = urls[i][0];
    if(0 < url.length) {
      var res = UrlFetchApp.fetch(url);
      Logger.log(res.getResponseCode());
      Logger.log(res.getHeaders());
      var code = res.getResponseCode();
      if(code !== 200) {
        var channel = "#company";
        pushSlack("<!everyone> 落ちてると思うので確認してください。 code:" + code +　 " " + url,"サイトチェックくん",channel);
      }
    }
  }
}

function pushSlack(msg,username,channel){
  var options = {"method":"POST"};
  var payload = {};
  payload.text = msg;
  payload.username = username;
  payload.channel = channel;
  options.payload = JSON.stringify(payload);
  Logger.log(payload);
  var slackUrl = "https://hooks.slack.com/services/" + "keyなど";
  UrlFetchApp.fetch(slackUrl, options);
}  

```
- トリガーを設定(30分毎にチェックするようにしました)
![スクリーンショット 2018-01-19 18.40.13.png](https://qiita-image-store.s3.amazonaws.com/0/24013/7c780be6-1511-fa84-5afe-f85653b5d447.png)

- 以上！
Fakerを利用してテストごとにテストデータを入れる方法


fixtureでデータの管理をしていたが、テストデータが増えると辛い面が多かった。
そこで、RubyのFactoryGirlのようにテストごとにデータを作りたかった。

## 環境

PHP 7.0
cakePHP 3.4

## Faker

https://github.com/fzaninotto/Faker

フェイクデータを作ってくれるライブラリです。
フェイクデータ以外にもデータを作成してDBに突っ込んでくれる機能があるようなのでそれを利用します。

### インストール

composerを使ってインストール

    composer require fzaninotto/faker


### 使い方

この辺を参考にしてやってみる。

https://github.com/fzaninotto/Faker/blob/master/readme.md#populating-entities-using-an-orm-or-an-odm

例えばUsersTableのテストを行う場合。

```php:UsersTableTest.php

public function setUp()
{
    // 他の初期処理省略

    // 初期処理でpopulatorの作成、cakePHP以外のORMの指定も可能
    $this->populator = new \Faker\ORM\CakePHP\Populator(
        \Faker\Factory::create()
    );
}

// 実際のテスト
public function testHogehoge()
{
    $this->populator->addEntity(
        'Users',
        10, // 10件データを作成する
        [
            // データを指定したい場合はここで指定
            'birthday' => '2018-01-19'
        ]
    );
    // 戻り値は作成されたデータのID
    $insertedPKs = $this->populator->execute();

    $this->assertCount(10, $insertedPKs['User']);

}

```

アソシエーションの紐付けを指定したい場合は普通にやってもうまくいかなかったが、下記のようにするとなんとかできた。

```php:UsersTableTest.php

public function testHogehoge()
{
    $this->populator->addEntity('Groups', 5);
    $this->populator->addEntity(
        'Users',
        1,
        [
            'birthday' => '2018-01-19'
        ],
        [
            // アソシエーションIDの指定はここで指定
            'belongsToGroups' => function($user){
                $user->group_id = 3;
                return $user; 
            }
        ]
    );

    $insertedPKs = $this->populator->execute();

    $user = User->find()->where(['id' => $insertedPKs['User']])->first();
    $this->assertCount(3, $user->group_id);
}

```

これで、なんとかテストごとにデータを入れれそう。
Raspberry PiでUSB Web CAMの動画を配信する ～mjpg-streamer自動化編～

# Raspberry PiでUSB Web CAMの動画を配信する ～mjpg-streamer自動化編～

SysmtedにServiceとして登録することで、電源投入時にmjpg-streamerを自動起動するようにする。

## 使用機材
- Raspberry Pi 2 Bodel B
- Logicool HD Web CAM C270
- 8GBのmicro SD Card

## OS
- RASPBIAN STRETCH LITE (2017-11-29)

## 手順

既にRaspbianをSD CardにInstallしてあるものとする。
[インストール方法については公式を参考](https://www.raspberrypi.org/documentation/installation/installing-images/README.md)

次にmjpg-streamerをInstallしてあるものとする。
[インストール方法についてはこちらの記事を参照](https://qiita.com/cactanaka/items/c9c54d8842138f0f5313)

Raspberry Piを起動し、ログインしておく。(今回の作業では標準ユーザー Pi で作業している。)

### 以下のコマンドでデバイスのIDを探す

```Shell
sudo systemctl list-units -t device
```

筆者環境では *sys-devices-platform-soc-3f980000.usb-usb1-1\x2d1-1\x2d1.3-1\x2d1.3:1.2-sound-card1.device* にC270が見つかった。

### Systemdに設定を登録し、有効化する

editorでSystemdの設定ファイルを作成する。

```Shell
sudo nano /etc/systemd/system/mjpg-streamer.service
```

以下の設定を流し込む。

```Shell
[Unit]
Description=MJPG-Streamer with /dev/video0.
After=udev.target
After=sound.target
After=syslog.target

BindsTo=sys-devices-platform-soc-3f980000.usb-usb1-1\x2d1-1\x2d1.3-1\x2d1.3:1.2-sound-card1.device
After=sys-devices-platform-soc-3f980000.usb-usb1-1\x2d1-1\x2d1.3-1\x2d1.3:1.2-sound-card1.device

[Service]
type=simple
ExecStart=/usr/local/bin/mjpg_streamer -i 'input_uvc.so -d /dev/video0 -r 640x480 -n -y' -o 'output_http.so -w /var/www -p 8080'

[Install]
WantedBy=multi-user.target
WantedBy=sys-devices-platform-soc-3f980000.usb-usb1-1\x2d1-1\x2d1.3-1\x2d1.3:1.2-sound-card1.device
```

Systemdに対して自動実行を有効にする

```Shell
sudo systemctl enable mjpg-streamer.service
```

### 補足
- USBデバイスなので何らかのタイミングで値が変わる可能性がある
    - 筆者環境では今のところ問題は起きていない
- USB Web CAMがSound Card扱いになっているように見えるが、これが仕様なのかはよくわからない

## 参考文献

[Linux でデバイスを接続している時だけ動くサービスを作る](https://qiita.com/propella/items/dcc1c14f71e5f06f3a88)
イーサリアムのアカウント作成部分はどうするのか？

<h2>イーサリアムのアカウント作成部分について</h2>
<p>ターミナルにどのように記述すれば正しく機能してくれるのでしょうか？</p>

> personal.newAccount()
Passphrase: 
Repeat passphrase: 
...
"0x13118d9a345f83433506e20f8e9ae8cb0dddc5e9"
cronで前に起動しているプロセスを殺したい時の罠

# pkill

一般的なサービスではあまりない状況かもしれないですが、趣味で常時起動しているプログラムなどを定期的に再実行させたりしたい事はよくあると思います。
そんな時に特定のプロセスをkillして、再度開始用のコマンドを実行したいのですがプロセスのIDは毎回変わるのでIDからkillするのはやりにくいです。そんな時に役に立つのが pkill です。

```
pkill -f python
```

とやるとpythonで実行されているプログラムを一掃します。基本的な認識としては

```
ps aux | grep python
```

これで見つかるプロセスを一掃してくれるイメージです。

# cronでpkill

これでいい感じにkillはできるのでその後実行したいと思いcronにこう書いたとします。

```
0 7 * * * pkill -f python && python /path/to/example.py
```

毎日7時にexample.pyを実行しているプロセスを再起動させようとしています。
しかし実はこれだとプロセスのkillはされますがexample.pyはpythonで実行されません。

※ pythonを例に出していますが、どんなコマンドに関しても同様です。

この現象が起きた時現象をググりたくてもなんて検索したら良いのか分からず、cron関連の問題だと思ってだいぶ時間を使ってしまいました…
（pkillのexitコードが && に続かないものなのかと思ったりして && を ; に変えてみたり…）

ただ、背景がわかると至極当然の流れでした。

まず前提として

```
ps aux | grep python
```

このコマンドを実行した時に、 `ps aux | grep python` このコマンドそのものも結果として出力されています。pythonという文字を含むプロセスを検索しているのですから、検索しているプロセスそのものもヒットするのは当たり前すぎて見逃しがちですがここにヒントが有りました。

pkillの-fオプションで指定した文字列もgrepと同様自分自身のプロセスも検索対象として検索します。その結果、 `pkill -f python && python /path/to/example.py` を実行しているプロセスはkill対象となります。なので自分で自分をkillします。まさかの自殺です 😊

あとはわかると思いますがpkill実行後にpythonコマンドを実行するプロセスがpkill実行時に死んでいくのですからpythonコマンドは実行されません。

# 対策
原因は分かったとしてじゃあどうしたら良いのか。

実はpkillの-fオプションには正規表現が使えます。なので

```
0 7 * * * pkill -f pytho[n] && /path/to/startscript.sh
```

こんな風に書きます。

前半は正規表現でpythoと[n]（[]はその中の任意の文字）なので `python` はこの正規表現にヒットします。しかし `pytho[n]` という文字列は `pytho[n]` という正規表現ではヒットしません。何を言っているか分からなくなりそうですが前者は文字列として、後者は正規表現として見るというのがミソです。

さらに後半に `python /path/to/example.py` と書いてしまうとここが `pytho[n]` にヒットしてしまうのでスクリプトにしてしまって `python` という文字を含まないように実行します。
このスクリプト内でpythonを実行すればプロセスとしてはpythonという文字列を含んだプロセスができ、そのプロセスを殺すことで実質終了させられる、かつcronで実行されたコマンド自体はkillされずに再度/path/to/startscript.shの実行まで進める、という訳ですね。

おんなじ悩みを抱える人がどこかにいる気がしたので書いてみました。