OmniAICreator/Qiita-1.07M huggingface dataset:
upstart の「start on stopped rc RUNLEVEL=[345]」ってどういう意味？

調べた時のメモ。
upstart の設定ファイルに「start on stopped rc RUNLEVEL=[345]」と書いてあったがどのような意味かわからず、調べた時のメモ。

# 結論

+ rc job が停止(stopped)したら設定ファイルに記載されたジョブを実行(start)する
+ ランレベルが 3 or 4 or 5 の時のみ実行される
+ rc job は SysVinit のスクリプト群であり、SysVinit のスクリプト群である


# upstart とは

[upstart Overview](http://upstart.ubuntu.com/index.html)

>Upstart is an event-based replacement for the /sbin/init daemon which handles starting of tasks and services during boot, stopping them during shutdown and supervising them while the system is running. 

boot 時の タスクやサービスの起動を処理する /sbin/init デーモンの置き換え変えるためのイベントベースのもの。

# 調査内容

まずは upstart の Getting Started を見る。

[Getting Started](http://upstart.ubuntu.com/getting-started.html)

>Your job is now able to be started and stopped manually by a system administrator, however you also probably want it to be started and stopped automatically when events are emitted. 

手動で起動停止も出来るが、event が emit されたときに 自動で起動・停止も出来る、と。

>You list the events you want to start your job with start on, and the events that stop your job with stop on. 

`start on` もしくは `stop on`というのを書ける。
今回、`start on` なので「何かしらのイベントがあったら exec を実行して起動」させるという意味になる。

もう少し例を見つつ確認したいので [cookbook](http://upstart.ubuntu.com/cookbook/) を見てみる。
以下は`start on stopped job-B`となっている。

[11.25.1   Simple Mutual Exclusion](http://upstart.ubuntu.com/cookbook/#simple-mutual-exclusion)

```
# /etc/init/job-A.conf
start on stopped job-B

script
  # do something when job-B is stopped
end script
```

コメントにある通りで、上記のような書き方の場合、 job-B が終了したら job-A を実行するという意味になる。
今回も `start on stopped` となっていることから「何かしらのイベントが終わったら exec を実行する」という意味となる。

また、他にもいい例があった。

[8.1   Really understanding start on and stop on](http://upstart.ubuntu.com/cookbook/#really-understanding-start-on-and-stop-on)

```
# /etc/init/alsa-mixer-save.conf
start on starting rc RUNLEVEL=[06]
```

>"Run when the rc job emits the starting(7) event, but only if the environment variable RUNLEVEL equals either 0 (halt) or 6 (reboot)".


rc job がスタートしたら実行する。ただし、RUNLEVEL 環境変数が0もしくは6の場合のみ、と。

これを今回のものに置き換えると「rc job が停止したら実行する。ただし、ランレベルが 3 or 4 or 5の時に限る」と。


じゃあこの「rc job」は何なのか、というのも書いてあった。

[8.1.1   The rc Job](http://upstart.ubuntu.com/cookbook/#the-rc-job)


```/etc/init/rc.conf
# /etc/init/rc.conf
start on runlevel [0123456]
stop on runlevel [!$RUNLEVEL]

export RUNLEVEL
export PREVLEVEL

console output
env INIT_VERBOSE

task

exec /etc/init.d/rc $RUNLEVEL
```

>"Run the SysV init script as /etc/init.d/rc $RUNLEVEL when telinit(8) emits the runlevel(7) event for any runlevel".

SysV init スクリプト(/etc/init.d/rc)に 引数RUNLEVEL を渡して telinit イベント発生時に実行する。イベントはどのランレベルでも実行される。
`/etc/init.d/rc`の中身を見ると `/etc/rc.d/rc` は `/etc/rc$runlevel.d/S*`というようになっていた。つまり、上記は SysV init  スクリプト群を実行するということになる。
Microsoft MPI 9.0.1 を入れてみた

この記事は Microsoft MPI (MS-MPI) 9.0.1 をインストールしてみたメモです。

環境は

- Windows 10
- Microsoft MPI 9.0.1
- Visual Studio 2017

です。（2018/6/28 時点で最新版）
C++ を使う前提で書いていますが、この後書くインストール手順で FORTRAN 向けと思われるファイルもセットについてきました。

# MPI について

[Message Passing Interface (MPI)](https://www.mpi-forum.org/) は並列計算の規格の1つです。
それを実装したライブラリを使うことで MPI の機能を使うことができます。
同様に並列計算によく使われる OpenMP はコンパイラで`#pragma omp parallel for`のようなソースコード中の記述を読み取って並列なプログラムを生成するのに対し、MPI はライブラリをリンクしてコンパイルすると使えます。
調べた中で、Visual Studio 上で使えそうだった実装がこれからインストールの説明をする MS-MPI になります。Linux 環境だと [OpenMPI ](https://www.open-mpi.org/) が使えるようです。

# インストール

[Microsoft のホームページ](https://www.microsoft.com/en-us/download/details.aspx?id=56727)（リンクが切れていたら「msmpi」で検索）に行って、msmpisetup.exe と msmpisdk.msi の**両方**をダウンロードして実行します。前者で MPI を実行する用のファイルがインストールされ、後者で MPI を使ったプログラムを作るのに必要なヘッダやライブラリがインストールされます。（ホームページに「or」って書いてあるのはミスリーディングだと思うんですが。）
インストールが終わったあと、コマンドプロンプトを開いて`set MSMPI`を実行すると

~~~~
MSMPI_BIN=C:\Program Files\Microsoft MPI\Bin\
MSMPI_INC=C:\Program Files (x86)\Microsoft SDKs\MPI\Include\
MSMPI_LIB32=C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\
MSMPI_LIB64=C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x64\
~~~~

のようにインストールされたファイルの場所を示す環境変数が表示されます。（コンパイル・リンクの設定に使います。）
また、`set PATH`でパスを確認すると、自動で実行用のファイルがある MSMPI_BIN フォルダをパスに登録してくれていることが確認できます。

# 使用時の設定

（参照：[How to compile and run a simple MS-MPI program](https://blogs.technet.microsoft.com/windowshpc/2015/02/02/how-to-compile-and-run-a-simple-ms-mpi-program/)）

インストールが終わったところで、さっそく使ってみましょう。

特に適用する対象がない方は適当に下のソースコードをコピペしてみてください。

~~~~{.cpp}
#include <mpi.h>
#include <iostream>

int main(int argc, char* argv[])
{
    MPI_Init(&argc, &argv);
    
    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    std::cout << "Hello world from " << rank << "-th process" << std::endl;

    MPI_Barrier(MPI_COMM_WORLD);
    if (rank == 0) {
        std::cout << "Press enter to close" << std::endl;
        std::cin.ignore(10000, '\n');
    }

    MPI_Finalize();

    return 0;
}
~~~~

実行すると

~~~~
Hello world from 0-th process
Hello world from 3-th process
Hello world from 2-th process
Hello world from 1-th process
Press enter to close
~~~~

のようにすべてのプロセスから Hello world するだけのプログラムです（笑）
Visual Studio だと実行終了とともに画面が閉じてしまうため、出力を確認するために `MPI_Barrier` 以降を書いています。

今回、追加のライブラリを使うだけのため、Visual Studio のプロジェクトを作る過程は通常通りです。
作ったプロジェクトに MS-MPI を導入するには、プロジェクトのプロパティ（プロジェクトを右クリックして下の方にある）を開き、次の設定をします。

- C/C++ -> 追加のインクルードディレクトリ に `%MSMPI_INC%;%MSMPI_INC%\x64` (64bitの場合) または`%MSMPI_INC%;%MSMPI_INC%\x86`(32bitの場合) を追加します。
- リンカ -> 追加のライブラリディレクトリ に `%MSMPI_LIB64%` (64bitの場合) または `%MSMPI_LIB32%` (32bitの場合) を追加します。
- リンカ -> 入力 -> 追加の依存ファイル に `msmpi.lib` を追加します。
- デバッグ -> コマンド を`mpiexec.exe`にし、その下のコマンド引数を`-n 4 $(TargetPath)` (4のところはプロセス数) にします。

これでビルドし実行すると MPI でプログラムが動きます。

# あとがき

プログラミングではしばしば「環境構築が最も大変」と言われますが、このライブラリは導入が簡単でよかったです。さて、何を作ろう。
個人的Gitの小技集

#はじめに
どうも、tkszkです:relaxed:
新卒3年目で、今後の人生に危機感を感じたので、Qiita始めました。
これまでROM専でしたがついに投稿してみます。

#目次
はい、本題です。Gitの小技とは？
Gitのチートシートは色々なところに載っているんですが、そうはいっても自分はこうやってるぞというのが何点かあったりするので、それを今回紹介したいと思います。

- squashは git reset で爆速コミット
- git add -N . からの git diff で一括チェック
- git reset 万能説
- git add -p で個別コミット
 
おまけ

- force push を恐れるな（※自分専用のブランチだけね）
- tigを使おう

#squashはgit resetで爆速コミット
※squashとはコミットを1つのコミットにまとめることです
rebaseをするときに、-i をつけるとコミットをどのように処理するか選べる画面に遷移します。

```sh
git rebase -i
                 
pick 6ebb91a add b
pick 43c3b80 add c

# Rebase bb94995..43c3b80 onto bb94995 (2 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
```

上記画面で、"43c3b80"のpickをsquashにすると１つ前のコミット("6ebb91a")に統合されます。
コミット数が2,3個であれば問題ないのですが、squashするときは大抵コミットの数が結構多くなってます。
しかも、だいたい全部squashにして１つのコミットにまとめることが多いんですよね…

その時は

```sh
git reset 6ebb91a
からの
git add .
git commit -m "コミットメッセージ"
```
これで問題なし。squashよりもずっと早くsquashコミットができます。

#git add -N . からの git diff で一括チェック
git diff しても差分が出ないのなんでなん？！？？？
と焦る前に

```sh
git add -N .
```
これで新規ファイルがgitに認知されます。
それ以降 git diff のみで差分が出るので楽。

#git reset 万能説

```sh
# 指定したハッシュ時点の状態に戻す
git reset --hard "コミットハッシュ"

# rebaseミスってもreflogに残っているので大丈夫
# git reflog で戻りたいコミットハッシュを探す
git reset --hard "コミットハッシュ"

# 今のソースコードの状態を保持して、指定したハッシュの状態になる
git reset "コミットハッシュ"
```
#git add -p でファイル内を細分化してコミット
コードレビューを依頼する前によくやります

```sh
git add -p "ファイル名"
```
これは説明が長くなるので、適当にググってください…
https://qiita.com/crifff/items/1abf08bca4ce51db4775

#force push を恐れるな（※ただし自分専用のブランチだけね）
チームによってはforce pushは禁止になっている可能性があります。
そのためforce pushは害悪みたいな印象があるとかないとか…
が、個人の開発ブランチは例外だと思っています。
リモートにあるブランチを整形したブランチに書き換えるので色々恩恵が大きいです。（無駄なブランチの増殖の予防とか恥ずかしいコミットの削除とか…）
チームで使う場合は、git push --force-with-leaseを使いましょう。誰かがコミットしていると弾かれるので万が一の予防になります（てかpushする前にpullしｒ）

#tigを使おう
これは色々な派閥があるので好みですが、tigは良いです。
もう文章を書く体力が尽きたので気になる方は調べてください…（すみません）

#終わりに
はじめての投稿ですが、どうでしょうか？
アウトプットする経験がほぼないので駄文で失礼しました。。
間違いの指摘やまた別の俺流があればどんどん教えてほしいです。
これから引き続き投稿していけるようがんばりますー
Terraformでパラメータのデフォルト値を取得する

## 概要

TerraformでWorkspaceを利用する際に、環境ごとのデフォルトパラメータを取得する方法を紹介します。

## 文字列型のデフォルト値

```text:モジュール呼び出し元
module "ec2" {
  source "modules/ec2"

  instance_type = {
    default     = "t2.micro"
    production  = "m5.large"
  }
  ...
}
```

```text:モジュール呼び出し先
variable "instance_type" {
  default = {}
}

resource "aws_instance" "this" {
   instance_type = "${lookup(var.instance_type, terraform.workspace, var.name["default"])}"
   ...
}
```

上記例の場合、Workspaceが`production`の場合は`m5.large`、`development`や`staging`といった環境であれば`t2.small`が適用される。

## Map型のデフォルト値

`production`環境では`172.29.0.0/16`、その他の環境では`172.30.0.0/16`を許可したい。

```text:モジュール呼び出し元
module "security_group" {
  source "modules/security_group"

  ingress_rules = {
    default = [
      {
        from_port   = "22"
        to_port     = "22"
        protocol    = "tcp"
        cidr_blocks = "172.30.0.0/16"
        description = ""
      }
    ],
    production = [
      {
        from_port   = "22"
        to_port     = "22"
        protocol    = "tcp"
        cidr_blocks = "172.29.0.0/16"
        description = ""
      }
    ]
  }
  ...
}
```

```text:モジュール呼び出し先
variable "security_group" {
  default = {}
}

locals {
  ingress_rules = "${var.ingress_rules[contains(keys(var.ingress_rules), terraform.workspace) ? terraform.workspace : "default"]}"
}

resource "aws_security_group" "this" {
  # (省略)
}

resource "aws_security_group_rule" "ingress_rules" {
  count             = "${length(local.ingress_rules)}"
  security_group_id = "${aws_security_group.this.id}"
  type              = "ingress"
  from_port         = "${lookup(local.ingress_rules[count.index], "from_port")}"
  to_port           = "${lookup(local.ingress_rules[count.index], "to_port")}"
  protocol          = "${lookup(local.ingress_rules[count.index], "protocol")}"
  cidr_blocks       = ["${split(",", lookup(local.ingress_rules[count.index], "cidr_blocks"))}"]
  description       = "${lookup(local.ingress_rules[count.index], "description")}"
  ...
}
```

文字列同様、`lookup`を使おうとすると`lookup: argument 2 should be type string, got type list in`エラーが出てしまう。

https://www.terraform.io/docs/configuration/interpolation.html#lookup-map-key-default-

> This function only works on flat maps and will return an error for maps that include nested lists or maps.

という訳でMapには使えない。

```
${var.ingress_rules[contains(keys(var.ingress_rules), terraform.workspace) ? terraform.workspace : "default"]}
```

このようにMapでキーリストを取得後、Workspaceがキーに含まれてる場合はWorkspaceのルール、含まれていない場合は`default`のルールの配列を取得することで問題を回避できる。
ruby on Railsのメモ

rubyでスマホアプリを作るときに使えるツール

RubyMotion
http://www.rubymotion.com/jp/
Monaca
https://ja.monaca.io/?_ga=2.157691134.590634037.1530120654-254257440.1530120654

[:params]
のような:コロンを使った変数を「シンボル」「シンボル指定」という。
[JANコード] GoogleSpreadsheetでチェックデジットを求める

# これはなに？
GoogleSpreadSheetで使える独自関数です。
商品を流通させる時に便利なJANコードで使用するチェックデジットを求めます。

様々なサイトで求めることが出来ますが、SpreadSheet内で使えるものが、ちょっと検索して見つからなかったので作りました。大したものではないですが、よければ使ってください。

計算式は、このページを参考にしました。
http://www.dsri.jp/jan/check_digit.html

独自関数の作り方はこちらを参照してください。
https://qiita.com/soundTricker/items/c9fa4470c59ef677dd5a

#　ソース

```js
function CHECK_DIGIT(office_num, product_num) {
  
  var check_string = office_num + product_num + "";

  // 標準タイプ（１３文字）のみ対応　チェックデジットを末尾に足して１３文字になる
  if(check_string.length != 12) return "LENGTH_NOT_12";
  
  var total_even = 0;
  for(var idx = 1; idx < check_string.length; idx += 2) total_even += parseInt(check_string[idx]);
  var total_odd = 0;
  for(var idx = 0; idx < check_string.length; idx += 2) total_odd  += parseInt(check_string[idx]);
  
  var three_times_total_even = total_even * 3;
  var total = three_times_total_even + total_odd;
  var last_num = total % 10;
  
  if(last_num == 0){
    return 0; 
  }else{
    return 10 - last_num;
  }
}
```

# 出力例
事業者番号が 123456789 で、
商品番号が 001 の場合、
チェックデジットは 2 になります。
TimeLine入門その１

#TimeLineってなに？
Unity2017になって新しく追加された機能です．僕が使っている範囲の感覚ではAdobeの
premiereとiMovieに似てるなぁって思ってます．Unityのオフィシャルにも映画的コンテンツを作成出来るとも書いてあるのでやはり動画制作に向けて作られているのかなって思ったりしてます．
TimeLine概要
https://docs.unity3d.com/ja/2017.2/Manual/TimelineSection.html

#まずは触ってみる
1.TimeLine Windowを導入
下記のwindowメニューからTimeLineを選択します．
<img width="1419" alt="スクリーンショット 2018-06-28 1.18.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/184790/e70384f1-686f-b609-c492-fbd9ead89df1.png">

2.TimeLineを作成
Createを押すとplayableと言う拡張子のフォルダが生成されます．
(ちょっと見やすいようにエディタを分割して見ました！)
<img width="1440" alt="スクリーンショット 2018-06-28 1.21.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/184790/882cd237-f778-aa1a-8f3d-c7676a58f598.png">

3.Animationの作り方
最初にアニメーションの終点の点のキーを打ち込んで初期値のキーを打ち込んで行く感じです．終点だけAddKeyして動かないぞ，みたいミスが多々あるので初期値のキーを打ち込みを気をつけてください．
![画面収録.gif](https://qiita-image-store.s3.amazonaws.com/0/184790/99779d0b-7e83-86ce-7b2f-f216fb87719a.gif)

4.Animationクリップへの変換
クリップへ変換することで他のオブジェクトへもアニメーションを適用することが容易になります．今回は簡単なアニメーションですが複雑なものになってくると毎回キーを打つのはしんどいので,クリップにすることをおすすめします．
<img width="1383" alt="スクリーンショット 2018-06-28 1.39.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/184790/e27c34ec-985c-fcae-33e2-bca7a87333cc.png">

5.Tips
上段まで汎用的なアニメーションを作成しましたよね？でもそれぞれのオブジェクトによって初期値のずれ（offset）などつけたいと思うのですが下記の図の青の枠の部分でそれができちゃいます！便利です．
<img width="1370" alt="スクリーンショット 2018-06-28 1.51.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/184790/3c0bfc8e-64b9-43c7-0c51-803063194983.png">
セキュアなWebサーバのConfig作成

## メモ
Webサーバのセキュアサイトを構築するにあたり便利なジェネレーション
いくつものM/Wに対応しているので素早く構築するには重宝するかと


[Mozilla SSL Configuration Generator](https://mozilla.github.io/server-side-tls/ssl-config-generator/)

構築したサイトのセキュリティレベルを測るサイト配下のURL

[Scan your site](https://observatory.mozilla.org/)
第16話 テトレーション

この記事は[仮面ライダービルドの数式](https://qiita.com/izmktr/items/e26a624e79bce3edccc9)の第16話です。

```math
2↑↑3=2^{2^2}=16
```

テトレーションと呼ばれる、べき乗の繰り返し演算です。

まず、掛け算は足し算の繰り返しです。

```math
2+2+2=2×3
```

そして、べき乗は掛け算の繰り返しです。

```math
2×2×2=2^3=2↑3
```

最後の式は見慣れない記号です。
これはクヌースの矢印表記と呼ばれる記号です。
コンピュータでべき乗をかくときは、2^3という表記をする事があります。
この^は、実は↑のことで、上矢印がかけないときに代わりに使う表現です。

要は、＋、－、×、÷と同じ仲間なんですね。

さて、べき乗を繰り返してみましょう。

```math
2↑2↑2=2↑↑3\\
```

今までの足し算をまとめたものが掛け算、というふうに、
べき乗をまとめたものを矢印を複数個重ねることで表現します。

今回の式は矢印が2つついた形なので、16になります。

このクヌースの矢印記号は交換法則が成り立ちません。

```math
\begin{align}
(3↑3)↑3&=27↑3&=19683 \\
3↑(3↑3)&=3↑27&=7625597484987
\end{align}
```

そのため、括弧がない場合は後ろから計算します。

```math
3↑3↑3=3↑(3↑3)
```

引き算や割り算が前から計算することを考えると逆になります。
これは、巨大数という、大きな数を作る方法を目的に作られたため、
数値が大きくなる方を採用したためです。

さて、この矢印を更に繰り返してみます。

```math
2↑↑2↑↑2=2↑^2 2↑^2 2=2↑↑↑3=2↑^3 3
```

このように矢印が増えていきます。
何個も重なると見づらいので、べき乗のような数字を付けて表すことが多いです。

では、巨大数の片鱗を見てみましょう。
トリトリと言われる、3が3つでてくる式を計算してみます。

```math
\begin{align}
3↑^33&=3↑^23↑^23=3↑^2(3↑^23)=3↑^2(3↑3↑3)\\
&=3↑^27625597484987\\
&=3↑3↑\cdots↑3 \\
&\quad(7625597484987個)
\end{align}
```

とまぁ、こんなに簡単にヤバそうな数を作ることができます。
JavaScript学習記録５　2018年6月27日分


使用図書
『ここからはじめるJavaScript入門』（井上久夫　2002年1月25日発行）

やったこと
「マウスの動きによって絵が変わるロールオーバーボタンを作る」

・マウスカーソルが重なったときだけ画像を変更する。

```js
 document.img1.src
```
OnMouseOverとOutを使ってマウスカーソルの状態指定、そしてimgで画像を呼び出し。その後別に画像の呼び出し元を指定って感じだね。

・画像をクリックするとページ移動
これと上でやったことを組み合わせて……帰るのはhrefの参照部分だけだ。これは組み合わせているだけみたいだ。

今回は物足りないけど次の章が「関数について」とどう見てもヘビーなので一回切る。うおおおおと言って爆発しよう！
Nginx + Rubyにおける開発

# Nginx + Rubyのアーキテクチャ
- `Nginx + Unicorn + Ruby` と `Nginx + Passenger + Ruby` の違いについて

## Unicornとは、Nginxの違いとは
- 一言でいうと、**Webサーバーとアプリケーションサーバーの違い**
- Webサーバー
    - 代表的なものだと Nginx、Apacheなど
    - リクエストを送った時に、レスポンスを返す
- アプリケーションサーバー
    - Rails用だと Unicorn、Sinatra、Thin、Pumaなど
    - webサーバーから受けたレスポンスをwebサーバーに返す

## Rackとは
- **RubyでWebサーバーを立ち上げるためのインターフェース**
- 指定したミドルウェアやアプリケーションを組み合わせ、Webサーバを立ち上げるためのライブラリを提供する
- これを用い、任意のアプリケーションサーバーでRailsやSinatra等のアプリケーションを動かすことができる

## Unicornとは
- Rackに対応するために作られた**アプリケーションサーバー(Rack Webサーバー)**
    - RubyアプリケーションとWebサーバをつなぐための中間サーバーのこと
- 通常のWebサーバはRackのような機能をサポートしていないため、この中間サーバーが必要になる
- Rack Webサーバー単体でも機能するがレスポンス処理が弱く、ApacheやNginxなどと組み合わせて使われることが一般的

## 「Nginx + Unicorn + Ruby + Rails」 における処理の流れ
- Nginx → Unicorn → Rack → Rails となる

## Passengerとは
- 正式にはPhusion Passenger
- Railsで作成したアプリケーションをWEBサーバー上で動かすための**ApacheやNginxのモジュール**
- モジュールとしてWEBサーバーに組み込むことで、(アプリケーションサーバー無しに)RailsのWEBアプリケーションを動かすことができる一方、アプリケーションサーバーとして利用することもできる。

### Nginx + Unicorn + Ruby のメリット
- **Web3層アーキテクチャ**という設計に基づいた
    - Webサーバ層/アプリケーション層/データベース層
- メリット
    - いずれかの層に変更があった場合、疎結合なので**メンテナンスが容易**になり、対応コストを低く抑えられる
    - 層を分離することで**処理の負荷分散**がされ、より多くの処理が可能

# Rubyフレームワーク比較

## Ruby on Rails
- 簡単にWebアプリケーションを作ることができるフレームワークが作られたことをきっかけに、プログラマーに圧倒的な指示を受けて活発に使われるようになった
- GitHub、Airbnb、Hulu、Basecampと言った多くの企業が採用している優秀なフレームワーク

### Railsにおける原則
- `DRY(Don't Repeat Yourself)`
    - 「同じことを繰り返さない」という意味
    - 同じコードや似たようなコードを何度も書くのは、効率が悪いし、変更に弱い為やめるべきだという発想
- `COC(Convention Over Configuration)`
    - プログラマーの意思よりも「規約(決められたルール)を優先する」という意味
    - アプリケーションを開発するにあたる最善の方法を、ある程度事前に決めてくれている

## Sinatra
- DSL（Domain-Specific Language : 特定の目的に特化した言語）を利用
- **小規模なアプリケーションを簡潔に記述**することを目指したフレームワーク
    - 単純なサイト構成なものに使い、逆に複雑なものにはあまり向いていない
- アップル、BBC、イギリス政府、GitHub等の企業や団体によって利用されており、Railsの次に人気が高い

### 参考文献
- アプリケーションサーバってなに？Webサーバとの違い : https://www.marketingbank.jp/special/cat02/173.php
- ApacheとNginxとPassengerとUnicornの違い【すごい初心者向け】 : http://fujiike.hateblo.jp/entry/2015/08/20/170751
- Railsを動作させるアプリケーションサーバunicornとは？概要やnginxとの違いなど : http://post.simplie.jp/posts/82
- Rails開発におけるwebサーバーとアプリケーションサーバーの違い（翻訳） : https://qiita.com/jnchito/items/3884f9a2ccc057f8f3a3
- Passenger vs Unicorn : https://techmedia-think.hatenablog.com/entry/20120922/1348240737
- Rackとは何か : https://qiita.com/k0kubun/items/248395f68164b52aec4a
- Ruby on Railsだけじゃない！Rubyフレームワーク6選 : https://eng-entrance.com/ruby-framework
- 東京暑いからRailsとSinatraの違いについて熱く語る : http://masa-world.hateblo.jp/entry/2017/07/08/161243
Amazon echo に好きな言葉を発言させる方法（アラーム機能活用）

# 前置き
確認したいことがあるのに、ケータイに出ない＆見ない妻に「ケータイ見て」と、ただそれだけ言いたい。

こういう状況ってないですか。
我が家はよくあります。

こういうときうちではAmazonEchoDotに「ケータイ見て」と言わせています。

※この投稿は、AmazonEchoのひとつの利用方法の紹介です。
　AmazonEcho 持っているけどオブジェになっている人や、AmazonEcho の購入を考えている人向けです。


# 活用場面

- 早急に家族に連絡とって確認したいことがある
- その時間、家族は家にいるはず
- でも、LINEが既読にならない、電話にも出ない
- ただし、家族はマナーモードで気づいていないだけ。Not 着信拒否が前提です！

# 方法（概要）
使うのはAlexaのリマインダー機能です。

- スマホのAmazonAlexaアプリからリマインダーを追加。
- 設定時刻を1分後にします。わずかな時間差でAmazonEchoがしゃべります。
- AmazonEchoは、登録したメッセージをしゃべります。（？のニュアンスも表現します。）

# 方法（より詳しく）
画面イメージは、iOSのAmazonAlexaアプリです。
「今から帰るよ」をAmazonEchoにしゃべらせます。
※実際は「今から帰るよ　のリマインダーです」となります。

1. スマホからAmazon Alexa アプリを起動
　<img width="280" alt="47AD5563-E920-4BC8-BF2D-ADB8B5C4CE06.png" src="https://qiita-image-store.s3.amazonaws.com/0/188272/8f4dbc9e-d2a1-6b92-3e04-08e3f8df11ed.png">



2. 左上のメニューボタンを選択
　<img width="280" alt="273AB0AB-000C-4B77-8186-EA3A2C0DB59D.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/188272/bcf8e65e-f7d1-c81e-6e41-7caad218da45.jpeg">


3. 「リマインダー・アラーム」を選択
　<img width="280" alt="43499D52-D986-4DF3-9A26-A02F968BCD74.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/188272/56b50700-04cd-36f1-697e-abc1166bf45c.jpeg">


4. ⊕マーク（リマインダーを追加）を選択
　<img width="280" alt="2661CF92-F9B0-4635-B294-E84009871969.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/188272/37da01d5-7303-f83c-2fd1-c8ea7c1cf0b3.jpeg">



5. 追加するリマインダーの設定
　<img width="280" alt="DA0A0611-79D5-41D3-93B2-6377182556C4.png" src="https://qiita-image-store.s3.amazonaws.com/0/188272/f998256a-c186-6044-640b-d845ed0e9465.png">

        - 「リマインダーの内容」にAmazonEchoにしゃべらせるメッセージを設定
        - 「時刻」に１分後を選択（デフォルトは現在時刻の30分後になっている）
        - 最近改善されてこの初期値になりました。「日付」「時刻」の初期値に現在時刻＋30分が登録されるようになっています。
        - 以前は日付、時刻に初期値が設定されていない状態でした。わずかな差ですが、よく使う機能としてはちょっと面倒でした。


6. リマインダーの設定後、「保存」を選択
　<img width="280" alt="119B4AAA-0BB6-4B03-9B2B-D5B983DF5602.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/188272/cff9b17d-64c4-075b-d97a-de89f934f4ea.jpeg">


7. リマインダーに追加されるので、発動されるのを待つ
　<img width="280" alt="524B0ABF-3D81-4C70-BD4C-995EF38C1BE7.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/188272/265a5dc1-dad3-a82a-e688-9ef52efe5025.jpeg">



8. 家族からの連絡を待つ
・良好な関係であれば、LINEは既読になり、何かしら反応があるでしょう。



# 今後の期待
- リマインダーの設定時刻について初期値設定（現在時刻+1分とか）ができるとうれしい。
- リマインダー登録のAPIを公開してほしい。IFTTなどで家族へのLINEやSlackの投稿を機にリマインダー登録できるようになるとうれしい。
WSL (Windows Subsystem on Linux) で pandoc メモ

## セットアップ

```bash
$ sudo apt-get update
$ sudo apt-get install 
$ sudo apt-get install pandoc
$ sudo apt-get install texlive-luatex texlive-xetex texlive-lang-japanese
```

## 実行

```bash
# Markdown to HTML
$ pandoc input.md -s -o output.html

# Markdown to PDF
$ pandoc input.md -o output.pdf -V documentclass=ltjarticle --latex-engine=lualatex
```
UbuntuにGitをインストールする

## 環境
- Ubuntu

## Gitをインストールする
以下のコマンドを叩く

```
sudo apt-get install git
```

## Gitがインストールされたか確認する
以下のコマンドを叩き、バージョンが表示されていればOK

```
dpkg -l git
```

## Gitの初期設定を行う
以下のコマンドを叩き、初期設定を行う

```
git config --global user.name [任意のユーザ名]
git config --global user.email [任意のユーザ名]
```
Excel VBA Excelで必ず使う 1ページを全画面表示させるマクロ

#Excelで全画面表示させて1ページを画面いっぱいにする

##条件

###印刷範囲が指定されていること
1ページだけになっていても印刷範囲が指定されていない、空白の場合があります。そういう時は終了します。

###1ページだけになっていること。
複数のページがあるとおそらくうまくいかないので、A4 の縦か横、1ページだけになっているとします。

###改ページプレビューにします
VBAを動かすと強制的に改ページプレビューになります。そうしないと1ページが把握しづらいからです。

###制約が多いが意外と役立つ
1シートにA41枚というはいがいにおおいと思います。これで大体全画面表示です。
本当はディスプレイを回転させたいけど、

## Excel VBAのコード

```visualbasic

Sub xlPringAreaFullScreen()
'For Excel VBA
'現在表示しているシートに、印刷範囲が設定され、かつそれが1ページの場合、改ページプレビューから全画面表示にして、その範囲だけをZoomで表示するマクロ
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = ActiveSheet
Dim prRange As Range
ActiveWindow.View = xlPageBreakPreview 'Excel.XlWindowView 標準、改ページ、レイアウト Const xlNormalView = 1,xlPageBreakPreview = 2, xlPageLayoutView = 3
If ws.PageSetup.PrintArea = "" Then Exit Sub '改ページプレビューで1ページだけのように見えても印刷範囲が設定されていない場合があるため、空白ならキャンセルする
If ws.PageSetup.Pages.Count > 2 Then Exit Sub '1ページ以上ある場合は小さくなるのでとりあえずキャンセルします。そういう仕様です。
Set prRange = ws.Range(ws.PageSetup.PrintArea)
prRange.Select
Application.DisplayFullScreen = True 'フルスクリーンにしてから
ActiveWindow.Zoom = True 'フルスクリーンでは調整できない表示倍率を動かす。
prRange.Cells(1, 1).Activate '印刷範囲の1番右上にする(同時に選択状態を解除する)
End Sub
```
AI系トップカンファレンスNIPS参加者数と世界人口の年ごとの推移をグラフ化する

かなり前の話ですが、AI系トップカンファレンスNIPSの参加者が、昨今のAIブームの影響で指数的に増加しているようです。

<img src="https://qiita-image-store.s3.amazonaws.com/0/139809/6a77c3ea-9cf6-4c44-cfb7-7a977e9f1e41.png" width=400px>
http://answeron.com/machine-learning-bubble/ より引用

このままの増加をたどると世界人口を超えるのではと危惧されています。そこでNIPS参加者数と世界人口の比較を行うグラフを書いてみます。数字は上記サイトのグラフから適当に設定しています。

```python
import numpy as np
import matplotlib.pyplot as plt


x1 = np.arange(2000, 2019)
x2 = np.arange(2018, 2051)
y1 = np.exp((x1 - 2000) / 2) / 4.5
y2 = np.exp((x2 - 2000) / 2) / 4.5
y3 = (x1 - 2000) * 4e+9 / 50 + 6e+9
y4 = (x2 - 2000) * 4e+9 / 50 + 6e+9
plt.xkcd()
plt.plot(x1, y1, "b", label="NIPS Registrations")
plt.plot(x2, y2, "b--", label="NIPS Registrations (Projected)")
plt.plot(x1, y3, "r", label="World Population")
plt.plot(x2, y4, "r--", label="World Population (Projected)")
plt.xticks(np.arange(2000, 2051, 10))
plt.yticks(np.arange(0, 1.6, 0.5) * 1e+10)
plt.xlabel("Year")
plt.ylabel("# People")
plt.title("NIPS Registration Growth")
plt.legend()
plt.show()
```

結果
<img src="https://qiita-image-store.s3.amazonaws.com/0/139809/32117030-b57f-c738-3f57-e9200636d25f.png" width=400px>

ラベルを変えることで、近年急速に増加している事象を世界人口と比較することができます。
awk, sed で csvファイルの処理

#はじめに
CSVファイルをもとにテキストを処理したいこともあります。今回はその例です。

#awk, sed

CSVファイルの内容が以下です。

```text:csv
Satoh Taro, taro@sample.com, 123
Suzuki Hana, hana@sample.com, 124
```

出力させたい内容が以下です。Javaプログラムで使います。

```java:put
put("taro@sample.com","123");
put("hana@sample.com","124");
```
実行させる内容

* 2, 3 列目のみで 区切り文字 , を "," に変更
* 最初に put("
* 最後に ");

それぞれを実行させて以下のようになります。

```shell-session:awk,sed
$ cat test.txt 
Satoh Taro, taro@sample.com, 123
Suzuki Hana, hana@sample.com, 124
$ cat test.txt | awk 'BEGIN {FS=", ";OFS=","} {print $2,$3}'
taro@sample.com,123
hana@sample.com,124
$ cat test.txt | awk 'BEGIN {FS=", ";OFS="\",\""} {print $2,$3}'
taro@sample.com","123
hana@sample.com","124
$ cat test.txt | awk 'BEGIN {FS=", ";OFS="\",\""} {print $2,$3}' | sed "s/^/put(\"/"
put("taro@sample.com","123
put("hana@sample.com","124
$ cat test.txt | awk 'BEGIN {FS=", ";OFS="\",\""} {print $2,$3}' | sed "s/^/put(\"/" | sed "s/\$/\");/"
put("taro@sample.com","123");
put("hana@sample.com","124");

$ cat test.txt | awk 'BEGIN {FS=", ";OFS=","; print "Begin"} {print $2,$3} END {print "End"}'
Begin
taro@sample.com,123
hana@sample.com,124
End
$ echo "taro@sample.com, hana@sample.com" | sed "s/@sample.com/@qiita.com/"
taro@qiita.com, hana@sample.com
$ echo "taro@sample.com, hana@sample.com" | sed "s/@sample.com/@qiita.com/g"
taro@qiita.com, hana@qiita.com
```

awk のポイント
BEGIN - 最初の行を読み込む前に実行
END - 最後の行を読み込んだ後に実行
FS - Field Separator 読み込み時の separator
OFS - Output Field Separator 出力時の separator

sed
s - 置換
g - 1行中のすべてのパターンに対して実行 (指定がなければ1行中の一致した最初のパターンのみ) 今回は g 必要なし

#参考
[【 awk 】コマンド（基本編その3）――テキストの加工とパターン処理・BEGIN・ENDとAWKスクリプト：Linux基本コマンドTips（117） - ＠IT](http://www.atmarkit.co.jp/ait/articles/1706/09/news013.html)
[【 awk 】コマンド（応用編その3）――テキストの加工とパターン処理、配列の活用：Linux基本コマンドTips（209） - ＠IT](http://www.atmarkit.co.jp/ait/articles/1805/24/news021.html)
[【 sed 】コマンド（基礎編その4）――文字列を置き換える／置換した行を出力する：Linux基本コマンドTips（56） - ＠IT](http://www.atmarkit.co.jp/ait/articles/1610/17/news015.html)
ApacheにおけるTRACE メソッドの無効化手順

HTTPにおけるTRACEメソッドの無効化について記載していきます。


#### TRACEメソッドとは
よく、XST関連で話題にあがりますが、ApacheでTRACEメソッドが有効になっている場合に
HTTPヘッダに含まれている情報も盗まれてログイン情報などが奪われてしまうといった形です。こちらが本当に危険なのかはいろいろな議論ありますが、無効化していて困ることもそこまでないのでメモがてら無効化について記載していきます。

cf: [TRACEメソッドって怖いんです](http://blog.masudak.net/entry/20110225/1298636093)
cf: [実はそんなに怖くないTRACEメソッド](https://blog.tokumaru.org/2013/01/TRACE-method-is-not-so-dangerous-in-fact.html)

#### 無効化手順について
手順といっても簡単で2つだけです。

```bash:ステップ1
$ vi /etc/httpd/conf/httpd.conf
```
```bash:/etc/httpd/conf/httpd.conf
#追記
TraceEnable off
```
```bash:ステップ2
$ service httpd restart
```
以上です
機械学習をするための環境構築

# pyenv
これを入れるとシステム環境を汚さずに済む。
Pythonのバージョン変更も簡単に行える。

下記のコマンドを上から順番に実行する。

```
yum install gcc zlib-devel bzip2 bzip2-devel readline readline-devel sqlite sqlite-devel openssl openssl-devel git
git clone https://github.com/yyuu/pyenv.git ~/.pyenv
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
source .bash_profile
```

# Anaconda
機械学習用のライブラリがセットになっていて便利。
個別にインストールしていくのはかなり手間なので初心者におすすめ。

インストールを実施。
`pyenv install anaconda3-5.2.0`

Pythonのバージョン切り替え。
`pyenv global anaconda3-5.2.0`
`pyenv rehash`

切り替えられているか確認する。
`python --version`

# TensorFlow
本体をインストール。
`pip install tensorflow`

# Keras
簡易機械学習ライブラリをインストール。
`pip install keras`
Google Apps ScriptでGithub GraphQL API v4を叩く

## やりたいこと

- gasからGithub GraphQL API v4を叩きたい
    - https://developer.github.com/v4/
- GraphQLをどうやってリクエストにのせればよいのかわからない
- わかった！


## どうやったか

実際に動かしているのはこれです(typescriptで書いてます)
https://github.com/abeyuya/gas-slack-bot-aoba/blob/master/src/lib/github.ts 

以下に関係する箇所を抜粋しておきます

```ts

const accessToken = process.env.GITHUB_ACCESS_TOKEN || "";
const endpoint = "https://api.github.com/graphql";

const graphql = `
{
  user(login: "abeyuya") {
    organizations(last: 5) {
      nodes {
        name
        url
        repositories(last:100) {
          nodes {
            name
            url
            pullRequests(last:30 states:[OPEN] ) {
              nodes {
                url
                title
                reviewRequests(last:10) {
                  nodes {
                    requestedReviewer {
                      ... on User {
                        url
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
`;

const buildRequestOption = (graphql: string) => {
  return {
    method: "post",
    contentType: "application/json",
    headers: {
      Authorization: `bearer ${accessToken}`,
    },
    payload: JSON.stringify({ query: graphql }),
  };
};


export const getAssignedPullRequests = () => {
  const option = buildRequestOption(graphql);
  const res = UrlFetchApp.fetch(endpoint, option);
  const json = JSON.parse(res.getContentText());
  return json;
};

```


graphql自体は [こちら](https://developer.github.com/v4/explorer/) のexplorerで試行錯誤して書いて、その結果をコピペしてきました
chp ファイル内の文字列を一括置換するツール coneta #6

#**chp**
　ファイル内の文字列を一括置換するツール(shスクリプト)です。





#**機能**
　exコマンドを使用して文字列を置換します(※１)。
　被置換文字列(置換される文字列)に正規表現を指定できます。
　置換が行われない場合、ファイルのタイムスタンプは更新されません(※２)。

　　※１　exの`:%s/被置換文字列/置換文字列/g`
　　  実装では`/`ではなくASCII制御文字のENQ(^E、0x05)を使用しています。
　　　問い合わせ(Enquiry)の意味でENQを使っているわけではありません。
　　　通常使わない文字を区切り文字として使用しているだけです。
　　　これまでEOT(^D、0x04)を使っていましたが、Solaris 10でエラーとなったため
　　ENQ(^E、0x05)を使用しています。

　　※２　exは`x`で終了しています。







#**使用方法**

【呼び出し形式】  

~~~bash:
chp 被置換文字列 置換文字列 ファイル(複数)
~~~
【パラメータの説明】  

| パラメータ | 内容 | 備考 |
|:--|:--|:--|
| 第１引数  | 被置換文字列  | exの正規表現 |
| 第２引数  | 置換文字列  | |
| 以降の引数  | ファイル | 複数指定可 |








#**実装**

~~~sh:chp
#!/bin/sh
case $# in
0|1|2)cat <<EOF 1>&2
Usage: chp re string files...
EOF
exit 1
esac

re=$1
str=$2
shift 2

for file in $@
do
ex -s ${file} <<EOF
:%s^E${re}^E${str}^Eg
x
EOF
done
~~~
$\color{red}{\rm 【注意】}$
　^EはENQ(0x05)です。
　ASCII制御コードの入力は以下を参考にしてください。
　　　[viコマンドで制御文字を入力 coneta #2]
(https://qiita.com/EjiriAkira/items/4c8c2deba8b5d283e323)


#**実装(改)**

当然な話ですが、クリップボードコピー＆ペーストした後に制御コード(^E)を修正し忘れたらうまく動きませんでした。
ということで制御コードなし版です。

動作確認はWSL(※)で行いました。

※　uname -s -r -v -m -p -i -o
※　Linux 4.4.0-17763-Microsoft #379-Microsoft Wed Mar 06 19:16:00 PST 2019 x86_64 x86_64 x86_64 GNU/Linux


~~~sh:chp
#!/bin/bash
case $# in
0|1|2)cat <<EOF 1>&2
Usage: chp re string files...
EOF
exit 1
esac
DLMT=$(echo -n -e "\x05")
re=$1
str=$2
shift 2

for file in $@
do
ex -s ${file} <<EOF
:%s${DLMT}${re}${DLMT}${str}${DLMT}g
x
EOF
done
~~~






#**環境**






ホスト　Windows10 COREi7 
VM　　　VirtualBox バージョン 5.2.8 r121009 (Qt5.6.2)
　OS　　CentOS Linux release 7.4.1708 (Core)
　　　　　3.10.0-693.21.1.el7.x86_64 #1 SMP Wed Mar 7 19:03:37 UTC 2018
　　　ex   version 7.4.160
　OS　　SunOS 5.10 Generic_147148-26
　　　ex   標準
　OS　　SunOS 5.11 11.3
　　　ex   version 7.3.600
　OS　　MINGW64_NT-10.0 2.9.0(0.318/5/3) 2017-09-13 23:16
　　　ex   version 8.0.1305
TSLint で独自定義したカスタムルールを適用させる

:writing_hand: [Developing TSLint rules](https://palantir.github.io/tslint/develop/custom-rules/)

## やること 

- 独自ルールが格納されているディレクトリを設定ファイルに記載する
- お約束に従いながら独自ルールを作成する

## 独自ルールを作る上でのお約束

- ルール識別子はケバブケース
 
- ルールファイル名はキャメルケース

- ルールファイル名には接尾辞として`Rule`を含める

- エクスポートされるクラスは、常に`Lint.Rules.AbstractRule`を拡張し、`Rule`というクラス名にする


##### 設定ファイルに独自ルールが格納されているディレクトリと実装ルールを使用する旨を記載する

```json:tslint.json
{
  "rulesDirectory": ["./src/@rules"],
  "rules": {
    "no-imports": true,
    ...
  },
  ...
}  
```

##### お約束に従って独自ルールファイルを作成
 
```typescript:src/@rules/noImportsRule.ts
import * as ts from "typescript";
import * as Lint from "tslint";

// お約束4
export class Rule extends Lint.Rules.AbstractRule {
    public static FAILURE_STRING = "import statement forbidden";

    public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
        return this.applyWithWalker(new NoImportsWalker(sourceFile, this.getOptions()));
    }
}

class NoImportsWalker extends Lint.RuleWalker {

    public visitImportDeclaration(node: ts.ImportDeclaration) {

        this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING));

        // call the base version of this visitor to actually parse this node
        super.visitImportDeclaration(node);
    }
}
```

Lint.RuleWalkerを拡張したクラスの中でvisitから始まるメソッドを使って各
walkerにマッチした表現の時にハンドリングできるようになる。上記メソッドだと「importが宣言された時にここに来ますよ」ということ。walkerの種類は [ここ](https://github.com/palantir/tslint/blob/master/src/language/walker/syntaxWalker.ts) から確認できる。いっぱいある。

ここまできたらあとは実行するのみ

```bash:TSLintのversionが^5.7.0だと事前コンパイルは不要
ts-node node_modules/.bin/tslint src/component/App.tsx
# ERROR: src/component/App.tsx[1, 1]: import statement forbidden
# ERROR: src/component/App.tsx[2, 1]: import statement forbidden
```
優秀な技術者を追い出してしまった事例

## **伝え聞いたある企業での話である。**

### **優れた製品を作り出す著名な研究者**
その企業ではある技術分野でリーダーシップを持っていた。先駆的な研究を学会に発表していると同時に、製品化もしており
その技術を他社にライセンスをしていた。
国内企業でその技術分野ではTop３の一つといってよかっただろう。

### **著名な研究者の名前の論文が出なくなった**
その会社の製品にはかねがね興味をもっていたので、ライブラリの性能を問い合わせることがあった。
しかし、そのライブラリの更新がある時期以降に改善がほとんど進んでいないことを知った。
しかも、ある時期から、論文の主力のメンバーの名前を、論文調査で見かけなくなってしまっていた。

今まで開発の主力を担ってきた人が、何らかの理由によりその会社のその分野から離れてしまったらしいことがわかった。
展示会でその会社のブースを見る限りだと、その企業はその技術は「もう技術的に進展が終わった分野」と思っているらしかった。
使い方の広がりの進展はあっても、技術の本質での進展はないと思っているように思えた。

### **ライブラリの性能比較**
後日、その分野のライブラリを比較調査する機会があった。
そのライブラリの性能は、海外の新興企業に対して、格段に差を開けられていた。
実行速度を別とすると、その分野のオープンソースの実装に対しても劣っていた。

開発を行なった主力の技術者が離れてしまうと、そのアルゴリズムは更新されず、データのチューニングもされず、結果として更新されないままになってしまうことは、私の会社経験でも見てきたところだった。

### **偶然知った移籍先**
いったいどうしたのだろうと思っていたが、そのうちの一人は大学に移っていた。
またそのうちの一人は、別の企業に異動されていたことをとあるタイミングで知った。
その企業が、ベンチマークで高い性能を上げている海外の新興企業だった。

その新興企業では、技術進展のうねりを自分たちのものにして、その前の世代の技術を遥かに上回る性能を達成していた。そしてそのようなことを可能にする開発者の採用を世界的な規模で実施していた。

対する日本の会社の経営陣は、「その技術は安定期に入って、研究開発に投資をしなくていいタイミング」と判断していて、現場の技術者が「大きな進展を遂げている激動の時代に突入したらしい」という感覚と大きな乖離をしているようだった。


### **企業の技術マネジメントをしている人にお願いする。**
優秀な技術者を追い出さないでもらいたい。
技術は人が開発するものです。誰もが同じ水準で開発を成功に導けるものではありません。先駆的な開発を成功に導ける人を獲得するのはとても大変なことなのです。
今ある技術的なリーダーシップを保とうとするには、常に先に進み続ける必要があります。


追記：
### **優秀な技術者の価値**

優秀な技術者は、既存技術の改良ができる。
優秀な技術者は、新しい技術の良し悪しを評価できる。
優秀な技術者は、その得意とする分野の知見を元に、別の分野に対して改良をすることができる。
優秀な技術者は、実現させたい機能に対して、少ないハードウェアリソースで実現する方法を複数の候補のアルゴリズムから選び出すことができます。
優秀な技術者は、新しい技術を必要とする人々に対して、求めるものを理解して説得力のある活動をすることができます。

---
参考事例

http://www.itmedia.co.jp/news/articles/1809/18/news011_4.html
> 国内でも、良い研究者がいっぱいいて、画像認識領域で世界に存在感を示していた企業はあります。ですが、ディープラーニングが出てきたタイミングで拒否反応が出て、苦戦しています。


---
[優秀な技術者を追い出してしまう方法](https://qiita.com/nonbiri15/items/961543c6460432289a02)
[優秀な技術者を追い出してしまった事例2](https://qiita.com/nonbiri15/items/807da07e1e04149b10ed)
[優秀な技術者を追い出してしまった事例3 - 技術を買えばいいは本当か -](https://qiita.com/nonbiri15/items/f96da1b219a627202c3f)
Pythonにランダムにファイルを選択させる

# 概要
私はよく読書のレポートを書きます。そこで、そのレポートの中から毎日1ファイル読み返したいなと思い、その選択をPythonにやってもらうことにしました。自分で選択すると、好みや気分で偏りができる懸念があったからです。
ちなみに、結果は自分専用のSlackにrequestsを使って投げてもらうようにしていますが、今回はランダム選択の部分だけを書きます。

# 環境
windows10
Python3.6.5
Anaconda3

# 実装
## 必要なインポート
```python:Choice_report.py
import glob
import random
```

## ファイルのランダム選択
```python:Choice_report.py
def choice_report():
    reportfiles = [r.split('/')[-1] for r in glob.glob('探索するフォルダのパス')]
    posttext = '本日読み返すレポートは' + random.choice(reportfiles) + 'です。'
    return posttext
```
### ワイルドカード
ワイルドカードを使い、拡張子なんかを指定してあげることも可能です。
以下はPDFファイルを抽出する例です。

```
../Documents/PDF/*.pdf
```

---------------------------------------------
あとは出来たテキストをLINEなりSlackなりに投げてあげるようにすれば勝手が良いです。タスクスケジューラなんかに入れて、自動化するのも良いと思います。

# まとめ
読書と勉強が捗る気がします。
お前たちのJobSchedulerの使い方は間違っている

# 何が間違っているのか
主要な日本語解説記事にて`JobService.jobFinished(JobParameters, boolean)`の呼び出し方がほぼ間違っている[^1]。
以下のように記述されていることがあるが、これは誤りである。

```java
@override
public boolean onStopJob(JobParameters params) {
  jobFinished(params, false);
  return false;
}
```

同様に、`jobFinished`を呼ぶと`onStopJob`が呼ばれるという記事もあるが、それも誤りである。

# Javadocを読む
`jobFinished`は、[Javadoc](https://developer.android.com/reference/android/app/job/JobService#jobFinished(android.app.job.JobParameters,%20boolean))によると、

> Call this to inform the JobScheduler that the job has finished its work. When the system receives this message, it releases the wakelock being held for the job.

と書いてある。
訳すと、「このメソッドを呼ぶことで、**JobSchedulerにジョブが完了したことを通知する**。システムがこの通知を受けると、このジョブのために取得していたwakelockを手放す。」となる。
つまり、jobFinished()が呼ばれたら登録されたジョブの実行は終わったとAndroidは解釈してロックを手放すよ、ということ。

`onStopJob`については、[Javadoc](https://developer.android.com/reference/android/app/job/JobService#onStopJob(android.app.job.JobParameters))にこのように書いてある。

> This method is called if the system has determined that you must stop execution of your job even before you've had a chance to call jobFinished(JobParameters, boolean).

> This will happen if the requirements specified at schedule time are no longer met. For example you may have requested WiFi with JobInfo.Builder.setRequiredNetworkType(int), yet while your job was executing the user toggled WiFi. Another example is if you had specified JobInfo.Builder.setRequiresDeviceIdle(boolean), and the phone left its idle maintenance window.

意訳すると、「このメソッドは、あなたがjobFinished()を呼ぶ機会を得る前(つまりジョブの実行が完了する前)に**実行中のジョブを止める必要がある**場合に呼ばれます。これは、ある特定の条件でのジョブの呼び出しをJobSchedulerに依頼していたため、その条件を満たした際にジョブが呼び出されたが、その実行途中で条件が破られた際に発生します。
たとえば、WiFi接続時のジョブの呼び出しをJobSchedulerに依頼していた場合に、WiFi接続になったためにジョブが呼び出されたが、ジョブの実行中にWiFi接続が切られた場合などです。」となる。
つまり、このメソッドが呼ばれた際の期待値は「**実行中のジョブを止めること**」であって、「**ジョブが完了したことを通知すること**(`jobFinished`を呼ぶこと)」ではない。

# 正しい処理
`onStopJob()`が呼ばれた際にはジョブを止めましょう。


```java
@override
public boolean onStopJob(JobParameters params) {
  stopYourJobImmediately();
  return false;
}
```
wakelockはonStopJobメソッドにてreturnした段階で手放してくれるので、気にしなくて良いです。
> Once this method returns, the system releases the wakelock that it is holding on behalf of the job.

# google様のサンプルコードは・・・？
[googlesamples](https://github.com/googlesamples/android-JobScheduler/blob/master/Application/src/main/java/com/example/android/jobscheduler/service/MyJobService.java)を見ると、

```java
    @Override
    public boolean onStopJob(JobParameters params) {
        // Stop tracking these job parameters, as we've 'finished' executing.
        sendMessage(MSG_COLOR_STOP, params.getJobId());
        Log.i(TAG, "on stop job: " + params.getJobId());

        // Return false to drop the job.
        return false;
    }
```
`MSG_COLOR_STOP`というメッセージを送って処理を止めています。
当然、`jobFinished()`なんて呼んでないですね。

[^1]: "Android JobScheduler onStopJob"で検索して1ページ目に出てくる日本語記事4つのうち、3つが誤り。1つが実装不足。つまり全滅。
OpenSSL ソースリーディング その3

[前回](https://qiita.com/mofu/items/6fb4772e442a86897573)からの続き。
SSL_readを見ます。

## SSL_read
SSL_readはSSL/TLSの暗号データを復号し、読み取る関数です。
ただ、この関数でもコネクションがネゴシエーション状態にある場合はネゴシエーション処理を行います。

```ssl/ssl_lib.c
int SSL_read(SSL *s, void *buf, int num) 
{
    if (s->handshake_func == NULL) {
        SSLerr(SSL_F_SSL_READ, SSL_R_UNINITIALIZED);
        return -1; 
    }

    if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
        s->rwstate = SSL_NOTHING;
        return (0);
    }           
                
    if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
        struct ssl_async_args args;
                
        args.s = s;
        args.buf = buf;
        args.num = num;
        args.type = READFUNC; 
        args.f.func_read = s->method->ssl_read;
            
        return ssl_start_async_job(s, &args, ssl_io_intern);
    } else {    
        return s->method->ssl_read(s, buf, num);
    }           
}           
```

基本的にはSSL_do_handshake関数と同じようなものです。
ただし、ハンドシェイク関数が設定されていない(=コネクト側かアクセプト側かが決定していない)場合や、受信サイドが切れている場合(close_notifyを受信している場合)は、受信処理を行いません。
それ以外の場合はssl_readハンドラが呼び出されます。
このハンドラは大体はssl3_read関数です。

### ssl3_read
ssl3_read_internal関数を呼び出しているだけです。
1段階はさんでいるのは、SSL_peekによるバッファを消費しないで読み取る関数との区別をつけるためと思われます。
peekの場合は、ssl3_read_internalの第4引数を1にします。

```ssl/s3_read.c
int ssl3_read(SSL *s, void *buf, int len) 
{
    return ssl3_read_internal(s, buf, len, 0);
}
```
    
### ssl3_read_internal
暗号データをバイト数指定で読み取る関数です。
ここで呼び出されるssl_read_bytesハンドラは、大体はssl3_read_bytesになります。

```ssl/s3_lib.c
static int ssl3_read_internal(SSL *s, void *buf, int len, int peek)
{
    int ret;

    clear_sys_error();
    if (s->s3->renegotiate)
        ssl3_renegotiate_check(s);
    s->s3->in_read_app_data = 1;
    ret =
        s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, NULL, buf, len,
                                  peek);
    if ((ret == -1) && (s->s3->in_read_app_data == 2)) {
        /*
         * ssl3_read_bytes decided to call s->handshake_func, which called
         * ssl3_read_bytes to read handshake data. However, ssl3_read_bytes
         * actually found application data and thinks that application data
         * makes sense here; so disable handshake processing and try to read
         * application data again.
         */
        ossl_statem_set_in_handshake(s, 1);
        ret =
            s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, NULL, buf,
                                      len, peek);
        ossl_statem_set_in_handshake(s, 0);
    } else
        s->s3->in_read_app_data = 0;
    
    return (ret);
}
```

SSL3_RT_APPLICATION_DATAを指定しているのは、これがssl3_read_internal関数からの呼び出しであることを示すようなもので、アプリケーションデータの読み込みを期待しています。

s->method->ssl_read_bytesの呼び出しを2回行っています。
2回目で行われるs->method->ssl_read_bytesは、ネゴシエーション中なのでSSL/TLSのネゴシエーションデータを期待していたのに、アプリケーションデータである場合です。
この状態に入るのは、クライアントへHelloRequestを送信した後、ネゴシエーションが始まっていない段階で、アプリケーションデータを受信した時です。
この場合、1回目の呼び出しでは、アプリケーションデータの読み込みの許可フラグ(in_read_app_data = 2)が設定され、処理を行わずに一旦関数から復帰します。
そして、2回目の呼び出しでは、ossl_statem_set_in_handshake(s, 1)を呼び出しておくことでハンドシェイクの処理に入ることを防止してから、アプリケーションデータの読み込み処理が行われます。

# 次回
次のssl3_read_bytes関数が長かったので一旦ここで切ります。
次はssl3_read_bytes関数を見ていきます。
VM/インスタンスに自分がSSHでログインできるための設定シェル


待ち合わせまでの時間つぶしに書いたもの。

いつも使い捨てサーバはデフォルトのユーザ(ec2-user/vagrant/ubuntu/centosなど)を使っていたのですが、手元のマシンかでユーザ名の入力やconfigの設定がめんどくさいのと、秘密鍵の管理や登録も面倒なのでEC2のUserDataや。vagrantであれば`config.vm.provision`で渡せるようなユーザ初期設定をするシェルを書いてみた。

```shell

#! /bin/bash

# Replace with yours
USER_TO_ADD=username
GITHUB_ID=github_username

# Create group and user
groupadd $USER_TO_ADD
useradd -g $USER_TO_ADD -d /home/$USER_TO_ADD -s /bin/bash -m $USER_TO_ADD
echo "$USER_TO_ADD ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers

# Set up SSH
mkdir /home/$USER_TO_ADD/.ssh
chown $USER:$USER_TO_ADD /home/$USER_TO_ADD/.ssh
chmod 700 /home/$USER_TO_ADD/.ssh
curl https://github.com/$GITHUB_ID.keys > /home/$USER_TO_ADD/.ssh/authorized_keys 2>/dev/null
echo AllowUsers $USER_TO_ADD >> /etc/ssh/sshd_config
systemctl restart sshd

```
Python atcorderについて

Pythonのアルゴリズム力を強化したいと思い。
競技プログラミングの問題を解いてみることにした。

今日一番よくわからなかった問題

A - 2点間距離の最大値 ( The longest distance )
URL:https://arc004.contest.atcoder.jp/tasks/arc004_1

<自分の回答>
下の中で、while中の　a-=1で文法エラーが出るが、なぜなのか不明
→解決できた。b.append(list(map(int,input().split()))
に記載した閉じ括弧の数が足りなかったため、括弧の数は気をつけなければ、、

```

import math
 
a = int(input())
b = []
c = 0
d = 0
while a > 0:
    b.append(list(map(int,input().split()))
    a -= 1

for x in b:
    for z in b:
        c = math.sqrt((x[0]-z[0])**2 + (x[1]-z[1])**2) 
        if c > d:
            d = c
 
print(d)

```

他の人の回答をみて学ぼうと思う。

下記のサイトで、実践・最強最速のアルゴリズム勉強会　第一回　講義資料(ワークスアプリケーションズ & AtCoder)というAtCorderがアルゴリズムについて説明している資料があり良いと思ったので乗せておく。

https://www.slideshare.net/chokudai/wap-atcoder1

6/27　本日といた問題は3問

・pythonで平方根は
math.sqrt(x) xに数字を入れると平方根が出力される
AmazonLinuxに最新版のNginxを導入する（失敗）

・結果
失敗？？
以下のメッセージが表示された。nginxが廃止されて、nginx-all-modulesが利用されるだとか。でも導入対象nginxはあるので何か失敗しているとおもわれる。
Package nginx is obsoleted by nginx-all-modules, trying to install 1:nginx-all-modules-1.12.1-1.33.amzn1.x86_64 instead

・記載内容
AmazonLinuxにNginxを導入する

・環境
Amazon Linux AMI release 2018.03
Nginx

・参考サイト
[Nginxインストール手順](https://nginx.org/en/linux_packages.html)

・説明
Nginxインストール手順に従い、作業をすすめる。

・手順
\# vi /etc/yum.repos.d/nginx.repo
```[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/rhel/6/$basearch/
gpgcheck=0
enabled=1
priority=10```
\# yum install nginx-1.14.0-1.el6.ngx.x86_64 

・補足１
以下のコマンドで、導入可能なNginxのバージョン一覧を確認可能。
\# yum list --showduplicates nginx

・補足２
Nginxインストール手順には記載されていないが、AmazonLinuxのリポジトリにはプライオリティが10で設定されており、Nginxのリポジトリが利用できなかった。
そのため、Nginxのリポジトリ設定（/etc/yum.repos.d/nginx.repo）にも以下の設定を記述しプライオリティを設定している。
priority=10
Homebrewを用いてGNU系コマンドをインストール（macOS）

こんにちは。
[Homebrew](https://brew.sh/) を用いて macOS へ [GNU系コマンド](https://www.gnu.org/software/) をインストールする方法を調べました[^1][^2][^3][^4]。
[^1]: Homebrew を用いてこれらをインストールすると標準ではどれもコマンド名の先頭には ```g``` が付けらrます（gzip, zcatを除く）。
[^2]: 「[テキスト処理のための標準的なコマンド群の OS X への導入手順](https://qiita.com/eumesy/items/3bb39fc783c8d4863c5f)」、「[homebrew環境構築におけるgnu系コマンドのインストールについて](https://qiita.com/johejo/items/c5af786b2362e1194374)」、また他の多くの Qiita 記事も参考にしました。
[^3]: 「[Homebrew で macOS に GNU コマンドをインストールする](https://yu8mada.com/2018/07/25/install-gnu-commands-on-macos-with-homebrew/)」という記事も参考になりました。
[^4]: ```ps``` コマンドについては、macOS と Linux とでは別物です（OS に依存して作られているので）。

### GNU 版の grep, awk, gzip, tar, sed, time, getopt
下記で、GNU 版の grep awk gzip[^5] tar sed time getopt をインストールできます。

```console
$ brew install grep gawk gzip gnu-tar gnu-sed gnu-time gnu-getopt
```
[^5]: GNU 版の zcat も含まれます。なお macOS の zcat は標準入力に対応しますが、ファイルを引数に取れないようです。

### GNU 系コマンド群 ```*utils```

さらに ```*utils``` という GNU 系コマンド群もインストールするには、

```console
$ brew install binutils findutils diffutils coreutils moreutils
```

これらの中身は：

* [binutils](https://www.gnu.org/software/binutils): ```ar gar ...```
* [coreutils](https://www.gnu.org/software/coreutils): ```cp mv ls ...```
* [diffutils](https://www.gnu.org/software/diffutils): ```diff cmp ...```
* [findutils](https://www.gnu.org/software/findutils): ```find locate xargs ...```
* [moreutils](https://joeyh.name/code/moreutils/): ```pee ...```
LINE BOTからNode.jsで画像を受け取って保存する


調べてもピンポイントな記事がなかったのでメモ。

普段axiosが多いですが、今回は[request](https://www.npmjs.com/package/request)モジュールを使ってます。

Messaging APIのリファレンスの[コンテンツを取得する](https://developers.line.me/ja/docs/messaging-api/reference/#anchor-fcc6cd7ad966ea05230c564c2be362df80c0739d)によると、

`GET https://api.line.me/v2/bot/message/{messageId}/content`で取得できます。

* ユーザー: BOTに画像を送る
* BOT: ユーザーから投稿された画像が上記のURLに保存されるので、取得しにいく

といった流れです。

## コード

記事最後の参考URLでかなり助かったのですが、`encoding: null`にしないと保存した画像が壊れてしまってハマりました苦笑

```server.js
'use strict';

const fs = require('fs');
const config = require('./config');
const express = require('express');
const bodyParser = require('body-parser');
const Request = require('request');
const accessToken = config.line.accessToken;
const app = express();
const PORT = process.env.PORT || 3000;
app.use(bodyParser.json());

app.post('/webhook', (req, res) => {
    if(req.body.events[0].message.type !== 'image') return;

    const options = {
        url: `https://api.line.me/v2/bot/message/${req.body.events[0].message.id}/content`,
        method: 'get',
        headers: {
            'Authorization': 'Bearer ' + accessToken,
        },
        encoding: null
    };
    
    Request(options, function(error, response, body) {
        if (!error && response.statusCode == 200) {
            //保存
            fs.writeFileSync(`./image.jpg`, new Buffer(body), 'binary');
            console.log('file saved');
        } else {
            // @todo handle error
        }
    });
});
app.listen(PORT);
console.log(`Server running at ${PORT}`);
```

ちなみにファイルは全てjpgになる様子なのでファイル名は`image.jpg`で固定してます。

調べたい場合は[file-type](https://www.npmjs.com/package/file-type)モジュールを使うと良さそうでした。

## 参考

* [Node.jsでrequestで画像をダウンロードしようとしてハマったので忘備録](https://qiita.com/nbapps_dev/items/d9c689a61cc5dd8440ee)
They can apply Functor not only Class

FunctionというFunctionをexecute(lop)で呼びだせる(Adapter|Command)で包み，Decorator Patternの発想を用いることによって，動的にTemplate Method == lineup of functionsを生成する．


```
// lop means list of parameters.

var component_1 = {
    execute: (lop) => {
        var reply = null;
        return reply;
    }
}

var exceptionHandler_1 = {
    component: null,
    execute: (lop) => {
        var reply = null;
        try {
            this.component.execute(lop);
        } catch (e) {
        }
        return reply;
    }
};

exceptionHandler_1.component = component_1;
exceptionHandler_1.execute({parameter_1: null, parameter_n: null});

```
jupyterの横幅調整をcss変更で実行

jupyter つかっててデフォルトの画面だと幅せまくね？
とおもったので、横幅調整を調べた。
css変更できるとな。

~/.jupyter/custom/custom.css

にて幅を指定する。 
!important を記載してCSSのセレクタ順位を無視しないと設定が効かないとな。

```css

#notebook-container {
    width: 90% !important;
}

```
師匠に!importantは滅多事ない限りつかうな。と言われたが今がその滅多ないことであることを祈ります。
あとは使ってるノートブックに以下をぶち込むのもありとな。
こっちは未確認なので明日試してみよ〜

```python

from IPython.core.display import display, HTML
display(HTML("<style>.container { width:100% !important; }</style>"))
```

#参考URL

https://stackoverflow.com/questions/21971449/how-do-i-increase-the-cell-width-of-the-jupyter-ipython-notebook-in-my-browser
https://qiita.com/goripon4416/items/a876f8122181b0734a40