OmniAICreator/Qiita-1.07M huggingface dataset:
Ubuntuを初めて触るド素人がAnacondaを入れてみた

# 概要
PythonといえばAnacondaを入れておけばなんとかなるっしょって感じらしいので、とりあえず軽いノリでそれを入れてみる。
※なんとなくWindowsよりLinux系の方が「やっている感」がある気がしたのでUbuntu16.04で試してみた

# 環境
- Ubuntu16.04(実は初めてUbuntuを触る)

# Anacondaのインストール

## インストーラのダウンロード
ブラウザで下記ダウンロードサイトへアクセス
https://www.anaconda.com/download/#linux

こんな感じのページ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/244394/64c0cd53-64a2-b86b-2503-0dc550c09860.png)


特別な理由でもない限り古いと思われる2.X系を選ぶ理由はなさそうなので、3.6をダウンロード
![image.png](https://qiita-image-store.s3.amazonaws.com/0/244394/4ed2ab64-ba3e-7367-8409-bc727e0ce46a.png)



## Anacondaのインストール

[端末]を起動して、ダウンロードしたやつを実行する

`bash [ダウンロードフォルダ]/Anaconda3-5.1.0-Linux-x86_64.sh`

実行するとこんなメッセージが出てくる。
「ライセンス条項を読め」的なやつっぽい。
`Enter`を押して続ける。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/244394/42ad6229-d31e-77b8-ff4d-866d8ffc680a.png)

こんなのが出てきたら`スペース`を押して読み進めて、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/244394/0fb6e523-cb57-839e-650c-1ce1d3c416cb.png)

これが出てきたら`yes`と入れて承諾。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/244394/7a8d236b-3a1a-440c-d6f5-a0190b60efe5.png)


今度はインストール場所を聞かれているっぽい。
ここではデフォルトのまま（何も入力せずに`Enter`）で進める。
(デフォルトは `/home/user/anaconda3` ？)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/244394/d9a40b3f-d420-c1fa-da8c-e33aa09ac9e2.png)

そうするとインストールが始まる。

次にこんなメッセージが出てくる。
「環境変数`PATH`にインストールするAnacondaのパスを追加するか」を聞いているっぽい。
よくわかんないが、まあたぶん追加したほうが良いだろう(テキトー)、てわけで`yes`を入れて進める。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/244394/babbcc99-eff2-8f73-1554-146d2a9d9dd8.png)

わーい、インストールできたー。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/244394/6b8126f4-ff68-5f28-5c81-37433e9a6fae.png)

## VisualStudio Codeのインストール
前述のメッセージで終わりかと思ったら追撃が…
どうやら「Microsoft VSCode 活かしてるから入れちゃおうぜ」とのこと。ここはお好みで。(入れるのが面倒だったので`no`にした)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/244394/b681d827-64fd-a835-f0bc-dc187b0ab5cf.png)

## 動作確認
インストールが終わったのは良いが、こっからどうするんだ、
ってなったところで調べてみたら、とても参考になるページが。

https://pythondatascience.plavox.info/python%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/anaconda-ubuntu-linux

こちらのページによると、
> `conda -V`

でバージョンを確認。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/244394/208cd77c-1d6d-582f-d76a-0163e2e7431d.png)

> `jupyter notebook`

でJupyter notebookをブラウザ上で起動できるみたい。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/244394/e3f77cfd-8802-8194-ed42-3a24ca1b488a.png)

無事に起動したことを確認できた。めでたし。
参考ページが優秀すぎてこの記事の意味がほとんどない気もするけど、備忘録の意も兼ねて…
fluentdでログの特定文言をSlackに通知する

## 概要
先輩にfluentdでログをgrepし、Slackに通知することができると教わった。
学習のため、自分でも試してみる。

## fluentdとプラグインを導入
[公式サイト](https://docs.fluentd.org/v1.0/articles/install-by-rpm)を参考に導入を進める。

シェルを実行する

```
curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.sh | sh
```

プラグインを導入

```
// Slack通知のプラグイン
$ td-agent-gem install fluent-plugin-slack
// grepのプラグイン
$ td-agent-gem install fluent-plugin-grep
```

設定ファイルに記載

```:/etc/td-agent/td-agent.conf
<source>
  type tail
  path ログファイル名
  pos_file ログファイル名.pos
  format none
  tag error_log_detail
</source>

<match error_log_detail>
  type grep
  regexp1 message message
  add_tag_prefix slack
</match>

<match slack.*>
  type slack
  webhook_url 通知するチャンネルのWebfookURL
  channel 通知するチャンネル名
  username fluentd
  flush_interval 5s
  color warning
  icon_emoji :ghost:
  message_keys message
  message "引っ掛ける文言"
</match>
```
fluentdを起動

```
systemctl start td-agent
```
これで準備はOK。
あとはログファイルに書き出されると下記のようにSlackに通知される。

<img width="428" alt="スクリーンショット 2018-03-19 0.07.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/39671/fb54af27-cfff-ff0c-c1d5-5c77590bea99.png">

これで文言を引っ掛けてが発生したらすぐに検知できるようになった。

## 参考
https://qiita.com/jumbOrNot/items/c7ae01f1456ef61f66a8
https://qiita.com/minamijoyo/items/1bb277383d8d2d2c7c11
顔関連の記事について整理する

顔関係の記事が多数になってきて、それらの関係がわかりにくくなったので整理する。

## **顔検出**

| 記事 | OpenCV | dlib | 深層学習 | SVM | Cascade | |
|------|:--------:|:--------:|:--------:|:--------:|:--------:|:---|
| [Haar Cascadesを用いた顔検出](https://qiita.com/nonbiri15/items/c8e666c4964d09ace652) | o | - | - | - | o |opencv/samples/python/facedetect.py |
| [OpenCVに含まれる深層学習ベースの顔検出](https://qiita.com/nonbiri15/items/01df1d8743767cd341a1)| o | -  | o | - | - | opencv/samples/dnn/resnet_ssd_face_python.py |
| [OpenCV 以外の場所にある深層学習ベースの顔検出を調査中](https://qiita.com/nonbiri15/items/927d202e7d95e6e81ae5)| - | -  | o | - | - |
|[Python + dlibで顔検出](https://qiita.com/shngt/items/64ff4130f377ddca5973) by @shngt | - | o | - | o | - |dlib.get_frontal_face_detector() |
|dlibのCNNでの顔検出 | - | o | o | - | - | [cnn_face_detector.py](https://github.com/davisking/dlib/blob/master/python_examples/cnn_face_detector.py)|

[OpenCV 以外の場所にある深層学習ベースの顔検出を調査中(3)](https://qiita.com/nonbiri15/items/616403ed75430586e73c)


## 頭部検出
[頭部検出について調査中](https://qiita.com/nonbiri15/items/3716d2a2376d47d30f2c)


## **顔器官点の検出**・

[顔向き推定について調査中](https://qiita.com/nonbiri15/items/f6910a993457a1862632)
 

| 記事 | OpenCV | dlib | 深層学習 | SVM | Cascade |
|------|:--------:|:--------:|:--------:|:--------:|:--------:|
|[dlibで顔のパーツ検出を行う](http://tadaoyamaoka.hatenablog.com/entry/2016/09/23/105815) | | o | | - | - |


[深層学習が用いられている顔の属性推定について調査中](https://qiita.com/nonbiri15/items/e097066a9d39972b994b)

次の記事はとても丁寧に書かれている。
[Kaggle Facial Keypoints DetectionをKerasで実装する](https://elix-tech.github.io/ja/2016/06/02/kaggle-facial-keypoints-ja.html)


## **顔追跡**
Face Tracker
https://github.com/kylemcdonald/FaceTracker
[FaceTrackerをインストールする。 - はまった点(2017.11.04)](https://qiita.com/nonbiri15/items/b40209df4f2e8fe9330a)

追跡自体については次の記事を参照するとよさそう。

[OpenCV Tracking API について](http://irohalog.hatenablog.com/entry/opencv_tracking_api) by IrohaLog





## **顔照合**

| 記事 | OpenCV | dlib | sciki-learn | |
|------|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|
| [「OpenCV 3.3.0 Face Recognition with OpenCV」への補足記事](https://qiita.com/nonbiri15/items/66c643575cbe7224ffcc) | o |  | | opencv_contrib/modules/face/samples |
| [dlibベースの顔照合プログラム face_recognition ](https://qiita.com/nonbiri15/items/f95b5fb01ae38980c9ce)|  | o |  | https://github.com/ageitgey/face_recognition | 
| [scikit-learn の顔照合の実装](https://qiita.com/nonbiri15/items/d1f6fdc1bae94096ba9f)| |  | o | http://scikit-learn.org/0.16/auto_examples/applications/face_recognition.html |
|[顔照合のオープンソースの実装について調査中](https://qiita.com/nonbiri15/items/a552dc3f6d3d692c0b11) | | | 
|[OpenFace(顔照合) について調査中](https://qiita.com/nonbiri15/items/c720dbf17c8eaf229c54) | |o | |


顔照合が近年大幅に改善している理由の一つは、顔の正規化の精度の向上を利用しやすくなったことがあるようです。
昔の顔検出ではラスタースキャンをする関係上、位置ずれを許容するような検出器を使っていました。そのため、位置ずれを許容する検出器で検出した後に、目の特徴点をエッジ検出で求めることがされていました。

現在は、深層学習の場合にはラスタースキャンという枠組みが存在せず、オブジェクトらしい領域を選択したあとでオブジェクトの種類を判定する枠組みなどがあります。そのため、深層学習が普及した以降では、それ以前と大幅な違いを生じています。
Sentryをローカル環境で立ち上げる（docker-compose 編）

エラーモニタリングサービスであるSentryはOSSで公開されていて、公式の手順に沿えば、誰でも構築できる。とはいえ、ちょっとした挙動確認をしたいときに公式の手順だと不便なので、docker-compose.ymlにまとめた。

設定ファイルは次の通り。

## docker-compose.yml

```yaml
version: '3'
services:
  sentry:
    container_name: sentry
    image: sentry
    env_file:
      - .env
    ports:
      - '9000:9000'
    depends_on:
      - db
      - redis
    tty: true
    stdin_open: true
  cron:
    container_name: sentry-cron
    image: sentry
    command: run cron
    env_file:
      - .env
    depends_on:
      - db
      - redis
  worker:
    container_name: sentry-worker
    image: sentry
    command: run worker
    env_file:
      - .env
    depends_on:
      - db
      - redis
  redis:
    container_name: sentry-redis
    image: redis
    volumes:
      - redis-data:/data
    ports:
      - '6379:6379'
  db:
    container_name: sentry-postgres
    image: postgres
    environment:
      POSTGRES_USER: sentry
      POSTGRES_PASSWORD: secret
    volumes:
      - pg-data:/var/lib/postgresql/data
    ports:
      - '5432:5432'
volumes:
  redis-data:
  pg-data:
```

## .env

```
SENTRY_POSTGRES_HOST=db
SENTRY_POSTGRES_PORT=5432
SENTRY_DB_USER=sentry
SENTRY_DB_PASSWORD=secret
SENTRY_REDIS_HOST=redis
SENTRY_REDIS_PORT=6379
SENTRY_SECRET_KEY=***YOUR_SECRET_KEY***
```

## ビルド手順

```
# 秘密鍵の生成: 生成後 .env の SENTRY_SECRET_KEY にセットする
$ docker-compose run --rm sentry config generate-secret-key

# DB初期化と初期ユーザーの作成
$ docker-compose run --rm sentry upgrade

# 起動: http://localhost:9000でアクセス可能
$ docker-compose up -d
```

なお、次のリポジトリをチェックアウトすれば、Dockerに慣れていない場合でも、5分程度でセットアップできる（はず）

[yhirano55/sentry-docker-compose](https://github.com/yhirano55/sentry-docker-compose)

## 参考

本記事のdocker-compose.ymlは、Sentryの公式イメージの「How to setup a full Sentry instance」をまとめたので、不明点があればそちらを確認してほしい。

https://hub.docker.com/_/sentry/
初めてのVim〜見た目をどうにかしてみる〜

# はじめに

仕事でVimを使いそうなので、家で弄ってみる。
まずは見た目を「[Vim Bootstrap](https://vim-bootstrap.com/)」を使って整える。

# 見た目

何もしていない状態。

<img width="656" alt="スクリーンショット 2018-03-18 22.47.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/99926/cd839bfb-b9e9-d491-04bc-5bd67399b8a0.png">

# ダウンロード

[Vim Bootstrap](https://vim-bootstrap.com/)にアクセスする。

<img width="1440" alt="スクリーンショット 2018-03-18 23.06.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/99926/284a7c5e-5eea-ad4d-65f7-56c8d1d16bb2.png">

使う言語を選ぶ。

<img width="1440" alt="スクリーンショット 2018-03-18 23.11.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/99926/022390fd-a86f-2aa0-3c91-1d42220bcdb7.png">

Generate!

<img width="1304" alt="スクリーンショット 2018-03-18 23.12.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/99926/987796db-6eeb-bce4-4d88-510ff49f3e55.png">

# ~/.vimrc作成

ダウンロードした「generate.vim」の内容をそのまま.vimrcにコピペ。

# Vim起動

最初は必要なpackageがインストールされる。
で、見た目はこんな感じに。

<img width="762" alt="スクリーンショット 2018-03-18 23.19.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/99926/ce12e405-57b5-c411-c914-03f9dcd63530.png">

# 最後に

[Vim Bootstrap](https://vim-bootstrap.com/)はお手軽なんですね。
初心者には嬉しいサービスです。
アンチパターンコード 「ウォーターフォール型関数呼び出し(仮)」


# ウォーターフォール型関数呼び出し(仮)とは

関数内で何か処理をして別の関数を呼び出し、呼び出し先でもまた何か処理をして別の関数を呼び出す、という深い呼び出し階層になったコードです。

```python:ウォーターフォール型関数呼び出し(仮)
def func1():
    # process 1
    # :
    func2()

def func2():
    # process 2
    # :
    func3()

def func3():
    # process 3
    # :
:
```

# 例：テキスト変換スクリプト

例として、テキストファイルを読み込んで大文字を小文字に変換して別のファイルへ出力するスクリプトをウォーターフォール型関数呼び出し(仮)で書いてみます。

```python:例：テキスト変換スクリプト
import sys

def main(input_file, output_file):
    with open(input_file, 'r') as f:
        lines = f.readlines()
    convert_lines(lines, output_file)

def convert_lines(input_lines, output_file):
    output_lines = [line.lower() for line in input_lines]
    write_file(output_file, output_lines)

def write_file(output_file, lines):
    with open(output_file, 'w') as f:
        f.writelines(lines)

if __name__ == '__main__':
    main(sys.argv[1], sys.argv[2])
```

# 問題点

- コードが追いにくい
    - 呼び出し階層が深く、全体でやっていることを追うのがとても面倒
- 適切な関数名が付けにくい
    - `convert_lines`は各行の変換だけでなくファイルの書き込みもおこなっているので、不適切な関数名
    - かといって他の名前も付けにくい
- テストがしにくい
    - `convert_lines`では各行の変換だけでなくファイルの書き込みもおこなっているので、これをテストするには書き込んだファイルを検証しなくてはならない

# 改善

- 各関数でやることを1つにする(他のことをやっている関数を呼び出さない)
- 全体を制御する関数を追加する

```python:改善前
def func1():
    # process 1
    # :
    func2()

def func2():
    # process 2
    # :
    func3()

def func3():
    # process 3
    # :
:
```
↓

```python:改善後
def main():
    func1()
    func2()
    func3()

def func1():
    # process 1
    # :

def func2():
    # process 2
    # :

def func3():
    # process 3
    # :
:
```



```python:例：テキスト変換スクリプト(改善後)
import sys


def main(input_file, output_file):
    input_lines = read_file(input_file)
    output_lines = convert_lines(input_lines)
    write_file(output_file, output_lines)


def read_file(input_file):
    with open(input_file, 'r') as f:
        lines = f.readlines()
    return lines


def convert_lines(input_lines):
    output_lines = [line.lower() for line in input_lines]
    return output_lines


def write_file(output_file, lines):
    with open(output_file, 'w') as f:
        f.writelines(lines)


if __name__ == '__main__':
    main(sys.argv[1], sys.argv[2])
```

# 結果

- コードが追いやすい
    - `main`を見れば、①ファイルを読み込んで、②各行を変換して、③ファイルに書き込む、という全体の流れがわかる
- 適切な関数名を付けやすい
    - 各関数でやっていることが１つなので適切な名前を付けやすい
- テストがしやすい
    - 各関数でやっていることが１つなのでテストをしやすい
    - `convert_lines`ではアウトプットの文字列リストを検証するだけでいい
VISUAL ASSISTを便利に使いたい

#すっごく良いのでもっと使いたくなった
今回は前回に引き続いて「痒い所」を直していきます。

前回の記事は導入編ですのでどうぞ。
[VISUAL ASSISTがとっても優秀な件](https://qiita.com/sy_/items/20717560a0c9e914e5e5)


#Alt+カーソルキーの操作が変わってしまう
地味にショートカットが入っています。このままでも良いよという方は次へ飛ばしてください

1. [VAssistX] -> [Help] -> [Keyboard Shortcuts] -> [Customize...]
VAssistX.ScopeNextとVAssistX.ScopePeviousのショートカットを削除するか別のショートカットに割り当てる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/175864/dc1653cb-1ffa-434a-9e30-aaf177c749e4.png)

1. 元のショートカットを割り当て直す
[Edit.MoveSelectedLinesDown]
[Edit.MoveSelectedLinesUp]
日本語の場合
[編集.選択した行を下へ]
[編集.選択した行を上へ]

#関数のコメントスニペットを組織のフォーマットに合わせたい
良く使うけどちゃんと書くの面倒なのでフォーマットだけでもすぐに出してくれるとありがたい。
しかし、ワンクリックでいけるのに**思ったフォーマットじゃない**のでがっかりしてました。

[コンテキストメニュー(右クリック)] -> [Quick Actions and Refactorings] -> [Edit Refactoring Snippets...] -> [Document Method]

ここで右のウインドウをテキストでエディットすると自分の好みに設定できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/175864/35093974-0e00-9215-e43a-94833d6286d4.png)

何か色々環境変数的なものがあるらしいのですが、詳しく調べてません。
私は一先ず欲しい形に出来たので画像のように並べました。

すると下記の感じに一発でポン（あ、いや既にスニペット使いの人はフーンなんでしょうけど）。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/175864/6be6be75-50c5-1ca8-5cff-2ec04eba4c04.png)

デフォルトでは下記のようになっています。

```.txt:Default
//************************************
// Method:    $SymbolName$
// FullName:  $SymbolContext$
// Access:    $SymbolVirtual$$SymbolPrivileges$$SymbolStatic$
// Returns:   $SymbolType$
// Qualifier: $MethodQualifier$
// Parameter: $MethodArg$
//************************************
```

# Open File In Solution

[Shift+Alt+O]で開きます。ただ欲しいファイルを開くだけなら、ソリューションエクスプローラより、こちらの方がショートカットで開けて時短になるかもしれません。
![va.png](https://qiita-image-store.s3.amazonaws.com/0/175864/8f8c4eab-83e6-512b-b510-01c928450015.png)
Devise SNSログインの場合はconfirmationをスキップすべし

Deviseを利用したログイン機能を作成しているとき、どうしても以下のようなエラーが出てつまったので、解決方法をメモとして残しておこうと思います。

<img width="1035" alt="スクリーンショット 2018-03-18 23.01.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/242288/794b3e11-97d5-c56c-2e15-0043210f3f1d.png">

## 解決手段
なんか、confirmationのところでエラーが出てるっぽい。
↓
そういえば、メール認証の場合はメールに送られたリンクをクリックしてアカウント確認を行なっていたことを思い出す。
↓
ただ、SNSログインにそんなことは必要ないはず。
SNSログインの場合は、アカウント確認をなくせばいい。
↓
解決法あった!!

```
user.skip_confirmation!
user.save
```
↓
このコードは、saveの前に設定しておく。
confirmationはsaveする前に発火するので。
ネットワークのソフトウェア化に関する各標準化団体での検討状況（2018/02/05セミナー報告）

ISOC-JP/TTC共催セミナーである「ネットワークのソフトウェア化に関する各標準化団体での検討状況」を受講してのレポートです。セミナーの内容そのものよりも、ネットワークのソフトウェア化という文脈に対する考察が多いです。
http://www.ttc.or.jp/j/info/topics/rep20180205/

※ISOC-JP：Internet Society (ISOC)の日本支部
※TTC：一般社団法人情報通信技術委員会

## 総評
セミナーでは5G通信のネタが多め。また要素技術の標準化に関する内容が多く実案件に直接繋がる話は少なめでした。

### ネットワークのソフトウェア化について
懇親会での会話や各種勉強会を出ている中での自分なりの解釈からなぜネットワークのソフトウェア化が言われているのか？をまとめてみます。実際に下記の流れでNW構築がうまくいっている事例があるかは知りたいところ。

- 市場環境や顧客ニーズなどの「素早い変化」に如何にして対応するかが重要視されており、ソフトウェア開発はアジャイルやリーン開発でその変化に対応している。SoE（System of Engagement。ジェフェリー・ムーアが2011年に言及）などの概念も出てきている。
- インフラ開発でもInfrastructure as Codeといった形で、ソフトウェア開発の手法を取り入れてより早くインフラ環境を変化させる動きが出てきている。パブリッククラウドも、ハードウェア資産を持たなくてよいという他に、調達期間の削減というメリットにより受け入れられたという側面がある（※1）
- ネットワークのソフトウェア化も、上記の素早い変化への対応という流れから起きている。またソフトウェア化により、大量のデータを取得して活用しようというデータドリブン志向もあると考えられる。

※1：パブリッククラウドの利点について、別のセミナーでカシオのIT部門の大熊部長と話したところ、「調達期間の劇的な短縮」「ハードウェアのイニシャル投資の削減」「勝手に進化するインフラ」があるとのこと。3番目の利点は、NW-JAWSのセミナーでSORACOMの人も言っていた。

### 懇親会で東大の中尾教授から聞いた話
- 東大発ベンチャーで総務省と組んで無線基地局をほぼソフトウェアで作って、実際にパケットを流している。1ヶ月くらいで認可が降りたがこれは異例のスピード。
- 無線基地局はほぼソフトウェア化してるので、様々なデータが取得できる。構想していたことの成功例としてSORACOMを挙げていた。
- NWを用いた価値創出の方法の一つとして、ネットワークを通る大量のデータをもとにした機械学習での分析が挙げられる。CiscoDNAも機械学習を取り入れているのがポイントだったはず。「通信の秘密」の観点で大丈夫か気になるが。
- 東大ではソフトウェア化/機械学習への対応としてPythonを大学の講義に追加した。
- 5G通信ではよくスライスという表現がされるが、東大ではスライスではなくソフトウェア化という表現に変えている。

### セミナーで面白かった点や気になった点
- ITU（国際電気通信連合。国連の組織）ではNWの仮想化の実装方式だけでなく、NWのソフトウェア化後のビジネスモデルや運用についても検討されている
- IETFでbess(bgp enabled services)という付加情報をBGPに載せるための手法が検討されている。BGP Flowspecと同じイメージ？※BGP関連ではNTT発OSSとしてGoBGPがあり、ソフトウェアによる制御を前提とした設計を採用している。GoBGPはコンテナ技術のDockerのNW制御で使えたりする。
- 5G通信のスライスの実装はNFVで実現する模様。NW専用機器を高性能汎用サーバに置き換える思想。つまり、ベンダーロックインの回避を狙っている。※OpenFlowの二の舞いになるかも？
- ヨーロッパでは国をまたいだスライスの運用管理も想定しており、標準化は要検討事項。
- スライスはライフサイクルをどうするかが課題としてあり、AIと組み合わせることが検討されている。

- ITUで、「5Gを含む将来網のための機械学習」を検討するFocusGroupが2017/11に設立。
http://www.ttc.or.jp/maedablog/2017/2017-11-16/

上記のように、ネットワークにおいてもソフトウェア化の検討が進んでいます。
Jenkinsのビルドジョブをdockerコンテナ上で行う

# 動機 
## Jenkinsが汚れていくのは見ていられない
Jenkinsでjavaだけではなく、python、nodejs、rubyのビルドを行う場合はそれぞれの環境をインストールしなければならず、Jenkinsの中身が汚くなってしまいます。

特にJenkinsをコンテナとして運用する場合、変更をイメージとしてcommitしなければいけません。

## Jenkinsでのコンテナビルドって面倒そうだと思っていた、が
Jenkinsfileもあまり浸透してないこともあり、werckerみたいに、dockerイメージを選んでyamlを書けば自動でやってくれるようなイメージがなかったです。

が、下記サイト様を閲覧し、Jenkinsfileで気楽にできることを知りました。

# 参考
初めての Jenkins と Declarative Pipeline
https://qiita.com/propella/items/77060dac98b9034f69bb

Jenkinsジョブ（ビルド～テスト）をDockerコンテナ上で実行する ～Docker Pipeline Pluginを使ってみる～
http://kimulla.hatenablog.com/entry/2017/06/13/003123

# Jenkins環境構築
dockerコンテナとしてJenkinsを起動します。
OSはAmazon Linuxを使用しました。

Jenkinsの公式サイトを確認したところ、BlueOceanコンテナをおすすめされたので、こちらを使ってみます。
https://jenkins.io/doc/book/installing/

```
docker run \
  -u root \
  --rm \  
  -d \ 
  -p 8080:8080 \ 
  -p 50000:50000 \ 
  -v jenkins-data:/var/jenkins_home \ 
  -v /var/run/docker.sock:/var/run/docker.sock \ 
  jenkinsci/blueocean 
```

rootユーザで起動し、dockerはホストと共用する設定のようです。
--rmは実際に利用する場合は消さないといけませんね。

起動後、初期設定を行います。（初期設定は割愛します）

# Open Blue Ocean
メイン画面に「Open Blue Ocean」というタブが追加されているため、クリックすると今どきのUIに飛びます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/237745/fecea2eb-4c51-0bef-c803-2e1f5102b0ef.png)

なかなかカッコいいですね。
設定ボタンを押すと今までのJenkinsの設定画面が出てくるのはご愛敬です。

Jenkinsの裏側としては、pipelineジョブでリポジトリを設定しているので、pipelineジョブと同じ使い方をすればOKです。

# Jenkinsfileによるdockerコンテナでのビルド

Jenkinsfileを書きます。
これをリポジトリのトップディレクトリに配備すると、自動でJenkinsが読み取ってくれます。

```
pipeline {
    agent { docker 'python:3.6' }
    stages {
        stage('setup') {
            steps {
                sh 'pip install -r requirements.txt'
            }
        }
        stage('build') {
            steps {
                sh 'python manage.py test'
                junit 'TEST-*.xml'
            }
        }
    }
}
```

肝となるのがagent部分で、dockerイメージを指定すると、

ビルドコンテナ立ち上げ
↓
ビルドコンテナ上のカレントディレクトリにリポジトリ取得

をよしなに行ってくれます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/237745/925f0641-aad9-571c-bc6c-6f479d01a5bf.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/237745/815deb02-c721-b9d3-4021-f63aeec0d78d.png)

circleciやwerckerみたいな今どきのフラットデザインUIです。

# おわりに
Jenkinsでコンテナビルドが簡単にできました。
これでwerckerなどのCIツールの手軽さで、コンテナ内を汚すこともなくビルドができそうですね。



唯一の難点というかイケてない点が、Jenkinsfileがgroovyということですね。
他のCIツール同様yamlで書けるようになると嬉しいのですが、プラグインがJavaである関係でしょうね。
gitignore_globalでgit管理するファイルをグローバルで設定する

## .gitignoreにいちいち.DS_Storeとか追加したくない
グローバルで管理できないのか調べてみた。

やりかたは簡単でターミナルで

```bash
// グローバルの.gitignoreファイルを作成
$git config --global core.excludesfile ~/.gitignore
```

すると自分のホームディレクトリ(/Users/UserName)に.gitignore_globalが作成されるので、git管理したくないファイルをここに設定する。

## .gitignore_globalでどのファイルを管理すればいいのか？
githubが推奨しているっぽいのは以下の模様。
.gitignore_globalには以下を書いておけば問題ないと思う。

```.gitignore_global
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
```

[参考：github/gitignore](https://github.com/github/gitignore/blob/master/Global/macOS.gitignore)

## .gitignore_globalを有効化する
ターミナルで以下のコマンドを叩く

```bash
// グローバルの.gitignoreファイルを作成
$git config --global core.excludesfile ~/.gitignore_global
```

もしくは、~/.gitconfigに以下を記述する。↑のコマンドを叩くと.gitconfigに同じ記述がされる

```.gitconfig
[core]
    excludesfile = /Users/your_user_name/.gitignore_global
```


## プロジェクトごとの.gitignoreではどのファイルを管理すればいいのか？
プロジェクト次第だけど、これもgithubが公開しているものが参考になりそう。
[githubが推奨するgitignore](https://github.com/github/gitignore)

ElmとかElixirとか新しめの言語も対応している。
Red Hat Enterprise Linux に GNOME Shell でログインする

![gdm-screen](https://qiita-image-store.s3.amazonaws.com/0/67627/67f721db-0113-c777-914e-fb265ae4c637.png)

Red Hat Enterprise Linux に GNOME Shell でログインする方法をメモっとく。[ThinkPad X1 Carbon に Red Hat Enterprise Linux をインストールする](https://qiita.com/takuya0301/items/19acffe4e84b2bdb15a9)の続き。

# GNOME Shell でログインする

歯車マークをクリックして、GNOME を選択することで GNOME Shell でログインすることができるようになる。あとは Password を入力して、Sign in をクリックすればログインできる。

---

今回は Red Hat Enterprise Linux に GNOME Shell でログインする方法を説明した。次回は Google Chrome をインストールする方法を説明する。
ROSでの複数マシンでのノード起動いろは

ROSで複数マシンで複数ノードを起動する方法をミニマムなサンプルで説明。

# 環境
- PC: デスクトップマシン(192.168.11.3) / RaspberryPi3(192.168.11.12)
- OS: Ubuntu 16.04
- ROS: ROS Kinetic

# やること
- デスクトップマシンをROS Masterとして、デスクトップマシンおよびラズパイ上で同じノードを１つずつ起動

# 前準備
- デスクトップとラズパイ間で、パスワード無しでsshできるようにする（互いの公開鍵id_rsa.pubを ~/.ssh/authorized_keysに登録）
- デスクトップの.bashrcに `export ROSLAUNCH_SSH_UNKNOWN=1` を追記

# ROSLAUNCH
```xml:starter.launch
<launch>

  <arg name="user" default="$(env USER)" />

  <machine name="main" address="192.168.11.3" env-loader="/home/$(arg user)/ros_work/src/mypkg/env/machine1.sh" />
  <machine name="sub" address="192.168.11.12" env-loader="/home/$(arg user)/ros_work/src/mypkg/env/machine2.sh" />

  <node pkg="mypkg" type="node.py" name="main_node" machine="main">
    <param name="myparam" value="hello main" />
  </node>

  <node pkg="mypkg" type="node.py" name="sub_node" machine="sub">
    <param name="myparam" value="hello sub" />
  </node>

</launch>
```

# マシンのセットアップスクリプト
```sh:machine1.sh
#!/bin/bash

u="$USER"
CATKIN_SHELL="bash"
export ROS_MASTER_URI="http://192.168.11.3:11311"
export ROS_IP="192.168.11.3"
. /home/$u/ros_work/devel/setup.bash
exec "$@"
```
```sh:machine2.sh
#!/bin/bash

u="$USER"
CATKIN_SHELL="bash"
export ROS_MASTER_URI="http://192.168.11.3:11311"
export ROS_IP="192.168.11.12"
. /home/$u/ros_work/devel/setup.bash
exec "$@"
```

# テスト用のノード
```py:node.py
#!/usr/bin/python
# coding: utf-8
import rospy

if __name__ == '__main__':
  rospy.init_node('node')
  sense = rospy.get_param('~myparam')
  rate = rospy.Rate(1)
  while not rospy.is_shutdown():
    rospy.loginfo('msg: %s' % sense)
    rate.sleep()
```

# 起動方法
- ラズパイ側に上記を適宜構成で入れたworkspaceをコピー。デスクトップ側とディレクトリ構成が同じになっていないとダメ。
- デスクトップ側で `roslaunch mypkg starter.launch` で起動。（パッケージ名は適当）
mailxのcertificate verify error

# smtpsで，自己署名だとmailxがエラーをはく
対策

```shell
cat ~/.mailrc
# root証明書の位置を指定
set ssl-ca-file=~/rootCA.pem
# または，証明書検証を無視する（非推奨）
set ssl-verify=ignore
```

日本語の記事が見つからなかったので
Rust メモ にゃ


## Install & Setup

```bash
$ curl https://sh.rustup.rs -sSf | sh
$ source $HOME/.cargo/env
```

* [Rustの開発環境セットアップ](https://dev.classmethod.jp/server-side/language/rust-setup-with-rustup/)

## Project Structure

[The Cargo Book](https://doc.rust-lang.org/cargo/index.html)

[Project Layout](https://doc.rust-lang.org/cargo/guide/project-layout.html)

```
.
├── Cargo.lock
├── Cargo.toml
├── src
│   ├── bin
│   │   └── another_executable.rs
│   ├── lib.rs
│   └── main.rs
└── tests
    └── some-integration-tests.rs
```


## First Step

[First Steps with Cargo](https://doc.rust-lang.org/cargo/getting-started/first-steps.html)

```bash
$ cargo new hello_world --bin
$ cd hello_world
$ cargo build
$ ./target/debug/hello_world
$ cargo run
```

## Emacs

```
list-packages
rust-mode -> Install
flycheck-rust -> Install
```

* [rust-mode](https://github.com/rust-lang/rust-mode)
* [wiki emacs Rust](http://wikemacs.org/wiki/Rust)
*  [気付いたらRustの環境構築がかなり楽になってた](http://keens.github.io/blog/2016/12/29/kizuitararustnokankyoukouchikugakanarirakuninatteta/)
Artisan::queue()でキューを指定可能にする

# Artisan::queueのキュー指定について

Laravelのジョブは以下のようにキューを指定可能ですが、

```php:emailsキューに登録
Job::dispatch()->onQueue('emails');
```

`Artisan::queue()` ではキューの指定がなく、必ず default キューに入るようになっています。
実装を見てみると、`Artisan::queue()` の実体は `Illuminate\Foundation\Console\Kernel::queue()` で、 `Illuminate\Contracts\Queue` インタフェースを実装したクラスの push メソッドを実行しています。

```php:Illuminate\Foundation\Console\Kernel
    public function queue($command, array $parameters = [])
    {
        $this->app['Illuminate\Contracts\Queue\Queue']->push(
            'Illuminate\Foundation\Console\QueuedJob', func_get_args()
        );
    }
```

接続を database にしている場合は、下記の実装になっています。
第3引数の $queue がデフォルトnullになっていますね。

```php:Illuminate\Queue\DatabaseQueue
    public function push($job, $data = '', $queue = null)
    {
        return $this->pushToDatabase(0, $queue, $this->createPayload($job, $data));
    }
```

さらに中身を見ていくと、 $queue を指定しなかった場合は以下のメソッドで default キューに登録していました。

```php:Illuminate\Queue\DatabaseQueue
    protected function getQueue($queue)
    {
        return $queue ?: $this->default;
    }
```

ということで、やはり `Artisan::queue()` では必ず default キューに入るようになっています。
Artisan::queue() の場合もキューを指定可能にしたい。

# 対応方法

`App\Console\Kernel` に queue メソッドを追加して、オーバーライドします。
（第3引数に $queue を追加しています）

```php:App\Console\Kernel
    public function queue($command, array $parameters = [], $queue = null)
    {
        $this->app['Illuminate\Contracts\Queue\Queue']->push(
            'Illuminate\Foundation\Console\QueuedJob', [$command, $parameters], $queue
        );
    }
```

これでキューを指定可能になりました。

# キューワーカ

キューワーカ起動時に `--queue` オプションでキューを指定します。

```
php artisan queue:work --queue=queue_1
```

複数キューがある場合は、ワーカも複数起動します。

```
php artisan queue:work --queue=queue_2
```
.npmrc に記載されてしまう authToken を git 上で無視する

↓エントリーを見て `.npmrc` を作ってみた

https://teppeis.hatenablog.com/entry/2015/12/configure-npm-init

```sh
init-author-name=Takagi Kensuke
init-author-email=janus.wel.3@gmail.com
init-license=MIT
```

と、ここまでは良かったんだけど npm にログインしたら　authToken が記載されるようになってしまった

```sh
//registry.npmjs.org/:_authToken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```

設定ファイルはすべからく git 管理しているのでこれはちょっとまずい
というわけで↓エントリーを見てこの行だけ無視する設定をしてみた

https://qiita.com/0829/items/dd87c00942e366c56a41

`.gitconfig` にフィルターを作成する
ここでは authToken が記載される行を削除するようにしてみた

https://github.com/januswel/dotfiles/blob/master/.gitconfig#L56-L58

```ini
[filter "ignore-npmrc"]
    smudge = cat
    clean = sed '/^\\/\\/registry\\.npmjs\\.org\\/:_authToken/d'
```

で、設定ファイルを管理している git repo に `.gitattribute` を作成

https://github.com/januswel/dotfiles/blob/master/.gitattributes

```
.npmrc filter=ignore-npmrc
```

これで authToken が git から無視されるようになった :raised_hands:
【Ruby】ブロックの小さなサンプル

参考
https://qiita.com/kidach1/items/15cfee9ec66804c3afd2

```ruby
# &でブロックを引数に
def exec_block(&block)
  block.call
end

exec_block do
  p "p_bloack"
end


####Proc
proc = Proc.new do
  p "proc_new"
end

proc.call

#### yield
def exec_block2(&block)
  yield
end

exec_block2 do
  p "block2"
end
```
PlayFramework 2.6 開発準備

前回に引き続きアウトプットしていくコーナー
https://qiita.com/lunalice/items/5f02d0cd42bf412f1d00

今回はやっとこさ参考書をざらっと読んだので次はやりたい事をまとめて知識と整合性を合わせて行く時間です。もちろん全部頭に入って体に染み付いているというわけではない。なので作ってみましょうという感じ。（ざらっと過ぎて体に染みてない感が強い

やりたい事をざっとまとめてワイヤーフレーム（Justinmind）とか作ってアウトプットイメージを固めて行きたいなっていう感じ。全部やった事ないので新鮮ですね。

顧客なんていないし要件定義するほどの上流工程を味わった事ないので、ここは私が現場で改善したい事をまとめる。こうしておくとルーティングと画面遷移辺りのイメージが沸き安くなりコーディングが捗る（と思いたい）

【要件定義】
・私「現場で席替えする度に端末変更が入ってブックマークとか移動するの面倒臭いのでアカウントに紐付けてブックマークの共有とか出来ないかなぁー」

上記を改善する為の機能を上げていく。
・ユーザー登録（CRUDユーザーテーブル）
・ユーザー認証画面
・ブックマーク管理画面（CRUDユーザーテーブルと紐付いたブックマークテーブル）

ざっと考えて上記みたいな感じ。
次はどうやって作っていこうかフェーズ

【環境について】
何を使ってやっていこうか？って事で参考書見ながらherokuがPlayアプリに最適とか書かれてたのでメイン柱をPlayFrameWork with herokuでやって行きたい。自分が見た情報が古かったのかherokuってruby on rails専用環境って認識だったので目から鱗。いつか触るつもりだったのでナイスタイミング。

・プログラム言語：JAVA＋scala
・フレームワーク：PlayFrameWork
・データベース：PostgreSQL
・本番環境：heroku

ちなみにherokuはPaaS（プラットフォーム・アズ・ア・サービス）って製品でOSやサーバーが揃ってる状態になっている為、前回サーブレットアプリ作った時はVPSにサーバー立ててApacheとかtomcatとかごにゃごにゃやっていたものが軽減される新設設計。インフラ関係触りたいならvpsで頑張るのがいいと思うけどアプリ動かしたいとかだとherokuでいいと思ったり。で、herokuのインフラとして使われてるのがAWSって奴で、最近のインフラで結構使われてるのを見るので次のフェーズにはAWSを使ってなんか作りたいと思ってる。

【テーブル定義】
定義って程でもないがMVC作る時modelから作るパターンが多いらしいのでざっくり考えてみる。

ユーザーテーブル
・ID
・名前
・パスワード
・メールアドレス（迷い中）
・登録日
・ログイン日時

ガチもののサービスを作るわけではないが、ユーザー登録してパスワード忘れた時にメールアドレスがないと詰むよなぁと思いつつ、とりあえず作ってみようフェーズだと流石に過ぎた機能で実装とテストに時間が凄まじくかかりそうなのでちょっと迷い中。ログイン日時を付けたのはメンテが出来ない状態でも半年経過したらユーザー使用してないね削除しましょうねってあくまで個人運用の観点であったらいいかなって。もちろんガチもののサービスでユーザーデータがつがつ消したら死ぬので別に確保したりするんだろうなぁ

ブックマークテーブル
・ID
・ユーザーID
・URL
・備考
・画像（迷い中）

出来るかわからないが、ユニークユーザーデータ毎にブックマークを格納しなければならないので、ユーザーIDで紐付けた感じに出来ないかなぁ（願望）、他者のブックマークが見えるのは流石に情報つーつー過ぎるのでテーブルからデータ持ってきた時重複しているURLをカウントして結構このURL人気高いねって感じにしたい。この手のものをクラウドにするとそれ検索サイトでよくね？ってなっちゃいそうなのであくまでアカウント単位で。画像データについては非常に迷うところでブックマークした時に画像なんて登録しないですね？だが画像のやり取りは経験値として蓄積したいねって感じで。

上記インフラエンジニアでもない素人客先常駐SESが想定してるものなので効率のいい方法とかこうしたほうがいいとかあればコメント下さいとっても喜びます。

とりあえず本日はここまで。


【雑記】
やっとこさpaizaで問題消化トロフィー揃ったのでランクA・S辺りぽつぽつしていきたい。
難しいというか問題がややっこしくて頭使わないとなんだけど、少し読み違えると仕様漏れて時間と点数取れない深みに嵌る。問題自体は出来ない感じはなく多分forifでいけると思う。後はその時のひらめきが問題とあってるかどうか。
来週からオファー頂いた企業様とかお話して行きたいと思ってます。未熟ですがよろしくお願いします。
やりたい事やらないといけない事がいっぱい。
bashでもfzf+fasdで簡単ディレクトリ移動

# 前提条件

+ macOS 10.13.3 High Sierra
+ iTerm2 3.1.5
+ bash 4.4.12
+ fzf 0.17.1
+ fasd 1.0.1 

# ディレクトリ移動を簡単に
　ターミナルの操作のうち、ディレクトリ移動の操作は思いの外多い。以下のようなコマンドを日常的にたたいている。

```bash
> cd <移動したいディレクトリ>
```

　このコマンドはシェルの補完機能により比較的簡単に操作できるが、正確に入力する必要がある。複数の独立したレポジトリの移動のような操作が加わる場合以外と労力がかかる。
　補完に強いシェルに乗り換えるという解決作もあるが、移動に特化したコマンドを活用する方法もある。

## autojump

　`autojump` というユーティリティを導入すると、一度移動したディレクトリであれば、構成する文字列の一部を入力するだけで簡単に移動できる。
　`j`というエイリアスでだいたい正確に移動できる。

```bash
> j <移動したいディレクトリを構成する一部の文字列>
```

autojump：https://github.com/wting/autojump

## fasd

　`autojump`も良いが、より高速に補完も優れる`fasd`というユーティリティーを見つけた。こちらは補完もスムーズで且つ見やすい。`autojump`と同じように、`z`というエイリアスで移動できる。

```bash
> z <移動したいディレクトリを構成する一部の文字列>
```

fasd：https://github.com/clvv/fasd

# fzfでfasdを更に快適に

　この`z`コマンドと`fzf`を組み合わせると快適なことこの上ない。
　`fzf`とは選択的インターフェイスを実現する（easy finder）と呼ばれるジャンルのユーティリティーである。
　調べたところ、`zsh`でのサンプルを見つけたが、どうも`bash`で同様のことをしているサンプルは見つからなかった。
　以下のように`.bashrc`に記述すればよい。

```bash:.bashrc
unalias z
z() {
  if [[ -z "$*" ]]; then
    cd "$(fasd_cd -d | fzf -1 -0 --no-sort --tac +m | sed 's/^[0-9,.]* *//')"
  else
    cd "$(fasd_cd -d | fzf --query="$*" -1 -0 --no-sort --tac +m | sed 's/^[0-9,.]* *//')"
  fi
}
```

　これで、bashでも煩わしいディレクトリ移動から開放される。
　`fasd`単体と同じように`z`コマンドで利用できる。

## 補足
　fzfの導入が前提となっている。
　fzf以外の選択的インターフェイスを実現する方法でも同様のことが実現できる。

fzf：https://github.com/junegunn/fzf
Google Apps ScriptのdoPostでJSONなパラメータのPOSTリクエストを受ける

Google Apps Script（GAS）は HTTPSリクエストを受け取り処理を行うというサーバレスなAPIサーバを導入することができる。（参考: [Web Apps  |  Apps Script  |  Google Developers](https://developers.google.com/apps-script/guides/web)）
それを使って、JSONフォーマットで記述されたリクエストパラメータでPOSTリクエストを送り、何かしらやろうとしたところ少しハマった。

## JSONパラメータを受けparseする
例えばこんなリクエストを送った場合を想定。リクエストパラメータをJSONフォーマットで記述されている。

```
curl -X POST -H "Content-Type: application/json" -d '{"value": "AAA"}' <GASウェブアプリケーションのURL>
```

このような時は以下のように書くことでリクエストパラメータをオブジェクトで受けることができる。

```javascript
function doPost(e) {
  var params = JSON.parse(e.postData.getDataAsString());  // ※
  var value = params.value;  // => "AAA"が取れる
  
  // 何らかの処理...
  
  var output = ContentService.createTextOutput();
  output.setMimeType(ContentService.MimeType.JSON);
  output.setContent(JSON.stringify({ message: "success!" }));
  
  return output;
}
```

少し解説すると、コード内 `※`を付けているところが今回のキモ。
`Content-Type: application/json` を付けているものの、GAS的にはそれを見ていない(?)ようで `e.postData` は [FileUpload](https://developers.google.com/apps-script/reference/ui/file-upload)クラスになっており、これは[blob](https://developers.google.com/apps-script/reference/base/blob)クラスを継承したクラス。
なので、[`.getDataAsString()`](https://developers.google.com/apps-script/reference/base/blob#getDataAsString())メソッドでJSON文字列を得ることができ、それを`JSON.parse`することでJavaScriptのオブジェクトに変換している、ということを行っている。


## ちなみに
以下のように `e.parameter` を使うと何も取れないので注意。おそらくこの `parameter` は"クエリパラメータ"のことだと思われる。

```javascript
function doPost(e) {
  var value = e.parameter.value;
  
  console.log(e.parameter);  // => 空オブジェクト( {} )
  console.log(value);        // => undefined
  ...
}
```
メモ：exiftoolで画像のEXIF情報を変更する

MacやWindows、Linuxなどで利用可能なExiftool。
すでに色々なところで情報はありますが、自分の備忘録代わりのメモ書きです。
（しばらく放置してたWSLをやっとこさ動かした記念に）

#「photo.jpg」を、DateTimeOriginal、CreateDateともに「2015/2/7 12時32分16秒」にする場合

 exiftool -DateTimeOriginal="2015:02:07 12:32:16" -CreateDate="2015:02:07 12:32:16" -FileModifyDate="2015:02:07 12:32:16" photo.jpg
exiftool -AllDates="2015:03:07 08:44:04" photo.jpg

* FileAccessDateとFileInodeChangeDateは変更できない。

# フォルダ中のJPGファイルの、三つの日付のEXIF情報を、テキストファイルに書き出す
exiftool -DateTimeOriginal -CreateDate -FileModifyDate *.JPG > ExifDateList.txt
exiftool -AllDates *.JPG > datelist.txt
exiftool -AllDates *.jpg > datelist.txt
exiftool -AllDates *.jpg *.JPG *.jpeg *.JPEG > datelist.txt

exiftool -AllDates -ExifImageWidth -ExifImageHeight -ImageWidth -ImageHeight -ImageSize *.jpg *.JPG *.jpeg *.JPEG > exifinfo.txt
exiftool -AllDates -ExifImageWidth -ExifImageHeight -Make -Model -Software -ImageWidth -ImageHeight -ImageSize *.jpg *.JPG *.jpeg *.JPEG > exifinfo.txt

# ファイル名を日付にする
exiftool "-filename<createdate" -d %Y-%m-%d_%H-%M-%S%%-c.%%e *.jpg *.JPG
exiftool "-filename<DateTimeOriginal" -d %Y-%m-%d_%H-%M-%S%%-c.%%e *.jpg *.JPG
Lambda関数で現在日付を使った処理を書くときにちょっとハマった

#経緯
先日、**「実行時の現在日付」を取得して、それをもとに処理をする**みたいなLambda関数を書いてて、
少しはまったので共有。実行環境は**node.js 6.10**。現在日付の取得にはnode.jsの日付処理ライブラリである
**[Moment.js](https://momentjs.com/)**を使用した。
...けど上記の環境じゃなくても起きるような事象だと思う。

#修正前

```javascript:index.js
const moment = require('moment');

//現在日付を取得
const CURRENT_DATETIME = moment().format('YYYYMMDDHHmmssSSS');

exports.handler = function (event, context, callback) {

    //CURRENT_DATETIME を使ってなんやかんやする。
...
}

```

##挙動
関数を何度かテスト実行しても現在日時を保持するCURRENT_DATETIMEの値が**初回実行時の値から変化しない**、
というものだった。

Lambdaに慣れた人にとっては、上記のコードは「こんなんちゃんと動かないに決まってんだろ」と思うような
モノかもしれないが、自分は最初このコードがおかしいということに気づくのに少し時間がかかってしまった。
というのもこのコード、**ある程度短い間隔で連続実行されない限りはちゃんと動いてしまう**ためである。

##なぜ動かなかったか
多くの方がご存知の通り、AWS Lambdaは**関数実行時にコンテナを生成し、そのコンテナ内で定義した関数を実行する。**
というアーキテクチャになっている。また**連続して呼び出された場合は**、１度使用したコンテナを破棄せず、
次の関数呼び出し時にそのまま再利用することで、関数実行時のコンテナ生成のオーバーヘッドを減らすという
工夫が行われている。

ここで気にするべきなのが、この「定義した関数」というのはハンドラとして定義した関数(今回で言うとexports.handlerで
設定した無名関数)のことであるという点である。
上のコードを実際に動かした結果から想像するに、**ハンドラ外に書かれたコード(requireとか定数定義とか)は、
コンテナ生成時に１度だけ処理され、以後同じコンテナ上では処理されない**らしい...。

つまり今回のバグは、関数の実行に同じコンテナが再利用されることで、最初のコンテナ生成時に
初期化された現在日時の定数が使われ続けていた、というのが原因だったというわけである。


#修正後

```javascript:index.js(修正)
const moment = require('moment');

exports.handler = function (event, context, callback) {

    //現在日付を取得
    const CURRENT_DATETIME = moment().format('YYYYMMDDHHmmssSSS');

    //CURRENT_DATETIME を使ってなんやかんやする。

...
}

```

現在日時の初期化をハンドラ内に引っ越すだけでちゃんと動くようになった。


#まとめ

AWS Lambdaは非常に便利だが、最低限動作の原理を頭に入れていないと今回のようにバグを生んでしまうことになる。
今回の例以外にも、一時的なファイル入出力場所として使える/tmpディレクトリを利用する場合、
そこに前回実行時のゴミファイルが残っているみたいなことも想定できるので注意したい。
Haskellでコマンドライン引数を受け取る

[こっち](https://qiita.com/taashi/items/07bf75201a074e208ae5)で、Pythonでコマンドライン引数を受け取る方法のメモを書いたが、そういえばこっちもやったことなかったので、Haskellでもメモ。

# コマンドライン引数を受け取る
System.EnvironmenモジュールのgetArgsを使用する。コマンドライン引数のリストが取得できる。

```commandline_args.hs
import           System.Environment (getArgs)

main :: IO ()
main = do
  args <- getArgs
  putStrLn $ args !! 0
  putStrLn $ args !! 1
```

```
$ stack runghc commandline_args.hs a b
```
で実行すると、
出力は、

```
a
b
```

となる。
Pythonとは違い、引数リストに実行ファイル名は、含まれない。

# 実際の使用時
実際使用する際は、おそらく、いくつの引数を受け取ったかを確認し、
さらに、期待する形の入力かをチェックする必要がありそう。


```fizzBuzz.hs
import           Data.Char          (isDigit)
import           System.Environment (getArgs)


main :: IO ()
main = do
  let isDigitOnly cs = foldl (\b c -> b && isDigit c ) True cs
  args <- getArgs
  if 1 <= length args
  then do
    let n = (args !! 0)
    if isDigitOnly n
    then
      fizzBuzz (read n :: Int)
    else
      putStrLn "Argument is not digit"
  else
    putStrLn "Arguments are too short"

  return ()

fizzBuzz n
  | n <= 0 = return ()
  | otherwise = do
      fizzBuzz $ n - 1
      fizzBuzz' n

fizzBuzz' n
  | multiplesOf15 = putStrLn $ prefix ++ "FizzBuzz"
  | multiplesOf3  = putStrLn $ prefix ++ "Fizz"
  | multiplesOf5  = putStrLn $ prefix ++ "Buzz"
  | otherwise     = putStrLn $ prefix ++ show n
    where
      multiplesOf3  = n `mod` 3 == 0
      multiplesOf5  = n `mod` 5 == 0
      multiplesOf15 = multiplesOf3 && multiplesOf5
      prefix = show n ++ " : "
```

- 引数無し

引数無しエラー

```
$ stack runghc commandline_args.hs
Arguments are too short
```

- 引数が数値じゃない

引数タイプエラー

```
$ stack runghc commandline_args.hs a
Argument is not digit

```

- 引数が数値

正常実行

```
$ stack runghc commandline_args.hs 15
1 : 1
2 : 2
3 : Fizz
4 : 4
5 : Buzz
6 : Fizz
7 : 7
8 : 8
9 : Fizz
10 : Buzz
11 : 11
12 : Fizz
13 : 13
14 : 14
15 : FizzBuzz
```

- 引数が数値で、複数存在

最初の1つを使用し実行

```
$ stack runghc commandline_args.hs 3 5 15
1 : 1
2 : 2
3 : Fizz
```
Djangoは管理ユーザと一般ユーザを分離できない

丸3日費やして達した結論。

# 何がやりたかったか
DjangoでWEBアプリを作りたい。

当然「管理ユーザ」と「アプリユーザ」でテーブルは分けたい。
（「admin_users」と「app_users」みたいな感じで）

# 結論
結論としては「djangoでは無理」。

頑張ってる人は諦めた方が吉。

詳細はいずれ書く。
AWS料金の節約方法について（実運用から）

AWSは便利だが、何も考えずに使い続けると結構な料金になることがある。
料金の節約について、実際開発や運用をしていて模索したことなどをまとめる。
詳しい人は既にやっていると思うので、意識してなかった人向け。

# まずは現状分析
## 月額料金詳細をチェックする

rootなどでログインして1月いくらかかっているのか、どのコンポーネントに費用が特にかかっているかを分析する
開発内容によるが、大体はEC2とRDSに掛かっていると思われる

## AWS費用のチェック方法

rootアカウントにログイン
↓
アカウントメニュー選択
↓
請求書で今月の詳細を確認

# AWS料金節約方法

ここではEC2とRDSに料金がかかっている前提で検討する

## STEP1:不要なコンポーネントを削除

当たり前ことであるが、以外と不要なものがあるのでチェックする

・不要なEC2/RDSなどなどコンポーネント削除
→立ち上げっぱなしで忘れているものなどを削除する。よくある。。。

・不要なAMI（EBS）/RDSスナップショットを削除
→AMIはバックアップ後放置しがち
→RDSスナップショットは、RDSのバックアップ期間を小さくする
 特に壊れた時以外のロールバック以外必要なければ1日で十分

・他リージョンの不要なコンポーネント削除
→新しいコンポーネントを試したの作り忘れ

## STEP2:起動しているコンポーネントを安くする
・EC2を使わない時間（夜間など）に停止させる
以下AWSCLIが実行可能なサーバにスクリプトを配置

```shell:start_instance.sh
#!/bin/bash
AWS_CONFIG_FILE=[ユーザ名]/.aws/credentials

for i in `cat /root/script/instances.txt`
do
        aws ec2 start-instances --instance-ids $i
done
```

```shell:stop_instance.sh
#!/bin/bash
AWS_CONFIG_FILE=[ユーザ名]/.aws/credentials

for i in `cat /root/script/instances.txt`
do
        aws ec2 stop-instances --instance-ids $i
done
```

起動・停止したいEC2インスタンスIDを記載
```config:instances.txt
i-xxxxxxxxxx
i-xxxxxxxxxx
```

crontabで時間設定
```config:/etc/crontab
00 08 * * 1-5 root /root/script/start_instances.sh > /dev/null 2>&1
00 00 * * * root /root/script/stop_instances.sh > /dev/null 2>&1
```

・DBの期間停止
→PostgreSQLなどのRDSの一部はインスタンスの停止ができるようになった
 EC2停止同様に、RDSも時間停止させる

cronでdbごとに設定するのが一番早い
```config:/etc/crontab/
00 08 * * 1-5 root aws rds start-db-instance --db-instance-identifier [DB識別子] > /dev/null 2>&1
00 00 * * * root aws rds stop-db-instance --db-instance-identifier [DB識別子] > /dev/null 2>&1
```

・リザーブインスタンス導入
→EC2/RDSはリザーブドインスタンスとして1年または3年契約ができる
 開発後の維持管理などは年間契約が多いため、1年契約をやりやすい
参照：
https://dev.classmethod.jp/cloud/aws/how-to-buy-reserved-instances/

・スポットインスタンス導入 （EC2コンソールのスポットリクエストがやりやすい）
→維持管理など、EC2内の構成がほぼ変わらない段階であれば、スポットインスタンスを適用することを考えられる
 スポットインスタンスはAMIを前提

参照：
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/spot-requests.html
https://recipe.kc-cloud.jp/archives/321

# まとめ
いきなり全てを導入しなくても、以下の順で検討していけばいい
①不要なものを削除する
②使ってない時間を停止するようにする
③リザーブドインスタンス/スポットインスタンスの導入

下にいくほど構成や契約に縛りが出てくるため、開発状況を見てのバランスが大事
①②を開発時
③を衰退期や維持管理で実施するのがよい

費用削減について、感覚的には②で3割減 ③で7割減 ①はうっかり残していたもの次第。。。

もちろんWebサーバなどをたくさん用意する必要がある運用構成や顧客がOKというならいきなり③のほうがよい
Intellijのhtmlのインデントが気になる

htmlタグとheadタグの直下の子要素にインデントがほしかったので設定を変更する。

### 変更前

<img width="291" alt="bf.png" src="https://qiita-image-store.s3.amazonaws.com/0/26393/42c43fcd-4cb5-0f0e-746d-4031a2b9d733.png">


### 変更後

<img width="293" alt="af.png" src="https://qiita-image-store.s3.amazonaws.com/0/26393/a76ad7a1-f29c-c849-74b4-f0c52f45d784.png">

## 設定変更

`Editor > Code Style > HTML` 内の `Other` タブを選択し
`Do not indent children of:`パラメータ から　htmlとbodyを削除する

<img width="673" alt="Preferences.png" src="https://qiita-image-store.s3.amazonaws.com/0/26393/9a574784-e1ed-af8e-133a-06effab2cbc4.png">
Macを購入したので設定をメモしておく

#前提
 macbook 12インチ　2017

#インストールしたもの
  0  セキュリティソフト
　　　まずはここからスタートです

　１　karabiner
     キー設定変更ツールUSキーのmacを買ったので日本語慣れした手に合わせて変更してしました。
　　　右のcommandをかなに変更し、左を英数に変更
     提供元　https://pqrs.org/osx/karabiner/
     記事　　https://beadored.com/the-original-karabiner-elements-command-switching-eisuu-kana/

　２　Xcode
　　　iOS用のIDEです
　　　提供元　App Store

　３　Home brew
　　　パッケージを管理し、インストールが楽になります
　　　Command Line Tools for Xcode
     提供元　コマンドラインから書きコマンドを入力する
　　　　　　　　xcode-select --install
     記事　　https://qiita.com/_daisuke/items/d3b2477d15ed2611a058

　　　Home brew
     提供元　https://brew.sh/index_ja
　　　　　　　　→コマンドラインから下記コマンドを入力
　　　　　　　　　/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

　４　エディター
     dein.vim
　　　起動が速いのと使っている人が多そうなので使用しました。
     提供元　https://github.com/Shougo/dein.vim
　　　記事　https://qiita.com/tomo62/items/57a9cc3abf92be5ea119

　５　pyenv 
　　　pythonを切り替えるために入れました。
     提供元 https://github.com/pyenv/pyenv  
　　　記事　https://qiita.com/koooooo/items/b21d87ffe2b56d0c589b

  6  anaconda 
　　　pythonのパッケージです。まとめて入れるのに楽なのでanacondaにしました。
     提供元 https://www.anaconda.com/download/#macos
　　　実際のインストールはpyenv経由のためコマンドラインからインストールする
　　　　pyenv install anaconda3-4.3.1 

  7  vimプラグイン
　　　Vimはそれだけでコーディングするのも地獄なのでplug-inを設定し、適宜使えるようにしました。
　　　起動時のplug-in
　　　'Shougo/dein.vim'
　　　'Shougo/vimproc.vim'
　　　'Shougo/neosnippet-snippets'
　　　'ervandew/supertab'
　　　'w0rp/ale'

　　　必要時は以下を設定　インデントと補完がメインです
　　　'Vimjas/vim-python-pep8-indent'
　　　'nathanaelkane/vim-indent-guides'
　　　'davidhalter/jedi-vim'
　　　'Shougo/neosnippet'
　　　'Shougo/neocomplete'
Google Apps Scriptで、同一プロジェクト内で分割された.gsファイルの関数を使う方法

タイトルのように同じプロジェクトで、.gsファイルを分割してコードの見通しを良くしたいということがあると思います。
例えば `slack.gs` はSlackに通知する処理を書いて、`main.gs` にはmain処理がありそのmainの中で `slack.gs` にある関数を使うなど。

そんな時は __何も考えずに他の.gsファイルに記述された関数を書けばOK__ です。

以下は一例です。

- `slack.gs`

```javascript
function notifySlack(payload) {
  var payload = {
    text: message,
    icon_emoji: ":smile:",
    username: "Google Apps Script",
  }
  var options = {
    method: "post",
    contentType: "applidation/json;",
    payload: JSON.stringify(payload),
  }
  
  UrlFetchApp.fetch("<INCOMMING WEBHOOK URL>", options);
}
```

- `main.gs`

```javascript
function main() {
  // 何らかの処理...
  
  // Slackへ通知
  notifySlack('SOME MESSAGE!')
}
```

`require`等必要なく、これだけでOKです。
便利ですね、Google Apps Script。
KotlinでRealmを使ってみた

#はじめに

サーバーと通信しないちょっとしたアプリを作るとき、ほぼ必要になるのがデータベースです。（通信するときでも使うけど）
今まではお手軽に使えるSQliteとかいう簡易的なものが使われてきました。
が、いい加減古いんじゃね？ってことで最近Realmというデータベースが使われはじめてます。（たぶん）

#Realmって？
一言で書くとSQliteのような端末内で動くDBです。
SQliteの代替として使う事を目的に作られました。

じゃあ別にSQliteでええやん

って思うかもしれません。が、SQliteよりもメリットが多いのです。
前々からあるけど4.3でkotlin正式対応したので使ってみることに。

#使うメリットって？

###メリット1：速い

とにかくメリットはこれに集約されます。速い。sqliteの数倍の速度はあるみたい。（詳しくは調べてみてください）

###メリット2：構造がシンプル

これが個人的に一番なのですが、メソッドに引数を渡すだけで保存出来るのはシンプルで使いやすいかと。
端末内に保存するときってちょっとしたデータであるケースが殆どだと思うので・・・！
~~unityのplayerprefみたいにお手軽に使える・・・！~~

###メリット3：iOS/Android両対応

両プラットフォーム共通で使えるのは学習コスト的にいいなと。
特にkotlinの場合、swiftと似ているので本当に親和性が高くて便利です。
変に書き方を変え無くてもいい。


#実際に使ってみると？

ということで能書きはいいので使用方法を。

###appのbuildgradleにpathを追加する

```gradle:build.gradle
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'realm-android'
```

###projectのbuildgradleにも追加

```gradle:build.gradle
classpath "io.realm:realm-gradle-plugin:5.0.0"
```
＊一応最新版プラグインを確認しておくことをおすすめします

###Applicationを継承したクラスを作って初期化

アプリ起動したらonCreateで有効化しちゃいます。
Applicationを継承したクラスの頭でinitしておくとどこからも使えて便利。

```kotlin:SampleApp
class SampleApp: Application() {

    override fun onCreate() {
        super.onCreate()

        //Realmの初期化
        Realm.init(this)
        val config = RealmConfiguration.Builder().build()
        Realm.setDefaultConfiguration(config)
    }

}
```


###RealmObjectを継承したクラスを作ってテーブルとかの設定する

当然ＤＢの情報設定が必要になります。ので設定する。
kotlinの場合、型推論で定義すると後からめんどくさい事になる可能性あり・・・
ちなみにアノテーションいらないのですが、超わかりにくくなるので書くこと推奨。
ここのクラスをopen属性にしないと継承、オーバーライドできないので注意

```kotlin:SampleObj
open class SampleObj: RealmObject() {

    @PrimaryKey
    var id : Int? = null
    @Required
    var name = ""

}
```

これで準備は整いました。次は実際に使用する方法

###書き込んでみる

RealmObjectで設定した情報をキーに書き込みます。
書き込む時は必ずトランザクションする必要があります。

```kotlin:Example.kt

class Example : Activity() {

    override fun onCreate() {
        super.onCreate()

        //keyを設定して
        val id = 1
        //initしたインスタンスをとってきて、トランザクションで書き込み
        realm = Realm.getDefaultInstance()
        realm.executeTransaction { realm ->
            val obj = realm.createObject(SampleObj::class.java!!, id)
            obj.name = "test"
        }
    }

}
```
これでidが1のレコードのnameにtestと書き込む事が出来ました。

###読み出してみる

読み出しはメソッドを使ってやります。
findAllだとオブジェクトのレコード全件。
findFirstだと一致するレコードをとってきます。

```kotlin:Example.kt

class Example : Activity() {

    override fun onCreate() {
        super.onCreate()

        realm = Realm.getDefaultInstance()
        //idが1のレコードをとってくる
        val id1 = realm.where(SampleObj::class.java).equalTo("id", "1").findFirst()
        //全件取得
        val all = realm.where(SampleObject::class.java).findAll()
    }

}
```



最後にはオブジェクトをdestroyしておきましょう

```kotlin:Example.kt

class Example : Activity() {

    override fun onDestroy() {
        super.onDestroy()

        realm.close()
    }

}
```

#おわりに

ざっとですがこんな感じで使えます。メリットはとにかく早いと言う点がありますが、そもそもシングルビューなアプリだったらそんなに体感出来ないような気がしないこともない。
簡単に使えるのでとりあえず使ってみて考えよう・・・
seaborn日本語表示設定

# 目的

Pythonで使うseabornのチャートを日本語表示できるようにする。

# 実行環境

実行環境は以下の通り。

```
Python version 3.5.3 |Anaconda custom (64-bit)| (default, May 15 2017, 10:43:23) [MSC v.1900 64 bit (AMD64)]
Pandas version 0.20.1
Matplotlib version 2.0.2
Seaborn version 0.7.1
```

# 現状の課題

matplotlibでは既定フォントがDejaVu Serifになっており、日本語を表示しようとしても文字化けしてしまう。また、多くの日本語フォント（.ttc）に対応していない。

# 解決方法

## 1. 使用可能なフォント一覧を表示

以下のコードを実行し、現在使用可能なフォント一覧を表示する。

```python
import matplotlib.font_manager
print([f.name for f in matplotlib.font_manager.fontManager.ttflist])
```

実行結果は下記の通り。この中に日本語対応フォントがあればそれを使用する。自分の場合はなかったため、新たにフォントを追加する必要がある。

```python
['DejaVu Sans Mono', 'STIXSizeTwoSym', ..., 'Berlin Sans FB', 'Niagara Engraved']
```


## 2. 日本語フォントのダウンロード

matplotlibで使用可能な日本語フォントをダウンロードする。
matplotlibでは.ttf, .otfファイルをサポートしている。使用可能なフォントは下記のとおり。

- [IPA Gothic](https://ipafont.ipa.go.jp/old/ipaexfont/download.html)
- [Noto Sans CJK JP](https://www.google.com/get/noto/#sans-jpan) 

ダウンロードしzipファイルを解凍後、インストールする。


## 3. matplotlib設定変更

フォントをインストールしただけではmatplotlibのデフォルトフォントとして使用できないため、matplotlib設定ファイルを書き換え、デフォルトのフォントを変更する。
matplotlib設定ファイルの場所は次のコードで確認できる。

```python
import matplotlib
print(matplotlib.matplotlib_fname())
```

実行結果

```python
C:\Users\Username\Anaconda3\lib\site-packages\matplotlib\mpl-data\matplotlibrc
```


```~mpl-data\matplotlibrc``` をテキストエディタで開き、以下の部分を変更する。
デフォルトでは```DejaVu Sans```になっている。


```
#font.sans-serif     : DejaVu Sans, 
```

変更後

```
#font.sans-serif     : IPAPGothic, DejaVu Sans, 
```


## 4. seaborn設定変更

次に、```C:\Users\Username\Anaconda3\Lib\site-packages\seaborn\rcmod.py```をテキストエディタで開き、以下の部分を変更する。

83行目付近

```python
def set(context="notebook", style="darkgrid", palette="deep",
        font="IPAPGothic", font_scale=1, color_codes=False, rc=None):
```

193行目付近

```python
"font.family": ["IPAPGothic"],
```

194行目付近

```python
"font.sans-serif": ["Arial", "Liberation Sans","Bitstream Vera Sans", "IPAPGothic"],
```

## cache削除

matplotlibは```C:\Users\Username\.matplotlib\fontList.py3k.cache```を参照するため、```~mpl-data\matplotlibrc```を変更しただけではフォントは変更されない。

matplotlibをimportする前に、```.matplotlib\fontList.py3k.cache```を削除する。



# 結果

seabornで描画したグラフが日本語表示される。

# 課題

- matplotlib, seabornをアップデートするたびに設定し直さなければならない。


# 参考にしたリンク

- [Macにおけるmatplotlibの日本語表示](https://openbook4.me/sections/1674)
- [matplotlibで日本語](https://qiita.com/yniji/items/3fac25c2ffa316990d0c)
- [matplotlib, seabornの日本語表示](https://qiita.com/u1and0/items/3b4d0f3e5514c9893d89)
- [3分でmatplotlibを日本語対応させる](https://qiita.com/knknkn1162/items/be87cba14e38e2c0f656)