OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerコンテナをシンプルにまとめる

#Dockerコンテナとは
まず、DockerとはDocker社が開発したコンテナ型仮想化ソフトウェアである。
そして、コンテナとはプログラムを実行するための仮想空間である。
#通常の仮想化とコンテナ型仮想化の違い

まず、仮想化とはホストとなる1台のコンピュータの上に、
仮想的に複数のコンピュータ（ゲストマシン）を構築する技術です。

コンテナ型仮想化の特徴は、"OSを仮想化しない"ということです。
要は、ホストOSを使用するため、ゲストOSが必要ない
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350277/577f1636-1f27-2236-94c9-955ca65de115.jpeg)
#特徴
①実行環境を柔軟に選択できる
　コンテナとは、プログラムと実行環境がパッケージ化されたものである。
　⇒このバッチはpythonにしよう、別のバッチはphpにしようなど。

②起動がはやい
　OSを仮想化しないため

③配布性が高い
　Dockerエンジンをインストールしているマシンでは、
　基本的にコンテナを起動することが可能
　⇒★OSの違いが影響することはあります。（windows,Linuxなど）
　　それはそうですよね、ホストＯＳ使ってますもん。

④コンテナ単位でリソース（メモリ、CPU）が独立している
　このバッチは、メモリXX、CPUXXにしようなど。
　複数コンテナを並列で起動しても、メモリ、CPUの食い合いをしない。
　※もちろんDBに接続する場合はまた別の話となりますが。

#サンプル（コンテナ実行プログラム、python例）

①プログラム
　XXX.py
②Dockerfile
　※実行環境の構築

↓↓↓
例）コンテナ起動時に"Helloworld"を出力したい場合
※試してはないですが(>_<)

①helloworld.py

```
print('Helloworld')
```

②Dockerfile

```
FROM python:3.6.8-alpine3.8　　←ベースイメージ
WORKDIR /temp　　←コンテナのディレクトリ
COPY ./helloworld.py .　　←プログラムをコピー
RUN pip install boto3　　←必要に応じてライブラリをインストール（awsのsdk）
RUN apk update && \　　←必要に応じてライブラリをインストール（postgresql操作）
    apk add postgresql-libs && \  
    apk add --virtual .build-deps gcc musl-dev postgresql-dev && \  
    pip install psycopg2 && \  
    apk --purge del .build-deps  
RUN pip install mysql-connector-python-rf　　←（mysql操作）
CMD [ "python", "./helloworld.py"]　　←コンテナ処理開始時に指定のプログラムを実行
```

▼ベースイメージは下記より
※公開リポジトリなので、officialとついているものを使用するのが安全
https://hub.docker.com/

　また、サイズを抑えると、コンテナの起動がはやい、
　データ転送量が下がるなどのメリットがある。
　→alpineがいいのかなぁ。試してみてプログラムが動かなければ、別のＯＳにかえたり試行錯誤。

▼pythonのライブラリは下記より
https://pypi.org/

#＋α
AWSにECSというサービスがあります。
これは、Dockerコンテナを管理コントロールするシステムです。
使用している時間だけ課金されるため（秒単位）、
起動がはやいコンテナのメリットを享受することができます。
The Boring Flutter Development Show Ep.1 で使われた article.dart 相当のものをつくる

# 背景

[The Boring Flutter Development Show [Pilot Episode]](https://youtu.be/yr8F2S3Amas) で出てくる `article.dart` は、Ep.1 の時点でデータがハードコードされています。
写経するにあたって適当なコードがほしかったので、[Hacker News API](https://github.com/HackerNews/API) を叩いて `article.dart` ファイルを生成するコードを書きました。
せっかくなので共有します。

# 使い方

1. 次節にあるコード `index.js` をローカルにコピー
2. `npm install` を実行
3. `node index.js` を実行

node v10.14.2、windows 10 で動作確認しました。

別に最新である必要はないんだよという人は、結果を gist に貼っているのでコピーしてください。
https://gist.github.com/noobar/9ba5b41f6e02986e077809e18f7b09e7

# コード

やっていることは次の通りです。

1. `/v0/topstories.json` を叩いて Top Stories にある記事の記事IDを取得
2. 1.で取得したIDで `/v0/item/[ID].json` を叩き、記事情報を取得
3. 2.で取得した記事情報を適切にフォーマットする
4. `article.dart` に文字列を書き込む

```index.js
const fs = require('fs');
const os = require('os');
const url = require('url');
const moment = require('moment');
const request = require('request-promise-native');

const hackerNewsUrl = 'https://hacker-news.firebaseio.com';

const sleep = msec => new Promise(resolve => setTimeout(resolve, msec));


(async () => {
    // 記事のIDリストを取得
    const ids = await request({
        uri: `${hackerNewsUrl}/v0/topstories.json`,
        json: true
    });
    
    // 各IDに対して記事内容を取得し、パースしたものを articles に詰め込む
    const articles = [];
    for (let i=0; i<30; i++) {
        const reqURI = `${hackerNewsUrl}/v0/item/${ids[i]}.json`
        console.log(`Requesting ${i + 1}/30 ${reqURI}`);

        const article = await request({
            uri: reqURI,
            json: true
        });
        articles.push({
            text: article.title,
            domain: url.parse(article.url).hostname,
            by: article.by,
            age: moment.unix(article.time).fromNow(), // "5 hours ago" のような形式に変換
            score: article.score,
            commentsCount: article.descendants
        });

        // リクエスト間隔を設ける
        await sleep(500);
    }

    // なんとなくJSONファイルを保存
    fs.writeFileSync('./articles.json', JSON.stringify(articles, null, '  '));

    // articles.dart をつくる
    let fileBody = [
        'class Article {',
        '  final String text;',
        '  final String domain;',
        '  final String by;',
        '  final String age;',
        '  final int score;',
        '  final int commentsCount;',
        '  ',
        '  const Article({',
        '    this.text,',
        '    this.domain,',
        '    this.by,',
        '    this.age,',
        '    this.score,',
        '    this.commentsCount',
        '  });',
        '}',
        '',
        'final articles = [',
        ''
    ].join(os.EOL);

    fileBody += articles.map(a => {
        return [
            '  new Article(',
            `    text: "${a.text}",`,
            `    domain: "${a.domain}",`,
            `    by: "${a.by}",`,
            `    age: "${a.age}",`,
            `    score: ${a.score},`,
            `    commentsCount: ${a.commentsCount},`,
            '  ),'
        ].join(os.EOL)
    }).join(os.EOL);

    fileBody += os.EOL + '];'

    fs.writeFileSync('./article.dart', fileBody);
})();
```

作法として、リクエスト間隔を500msとっています。
CypressでTypescriptを使いたいが、Custom Commandsをsupport/commands.tsにすると色々崩れる時の解決方法

# "cypress": "^3.4.1"現在
## Cypressのテストを.tsで書くのは簡単

[Transpiling TypeScript test files][1]にあるように

1. tsconfig.jsonを書く
2. テストファイルを`.ts`にする
3. テストをTypescriptで書く

これだけで良い

## Cypressの[Custom Commands][2]もTypescriptで書きたい

上の状態で`support/commands.js`をJavascriptのまま書くなら何も問題が無いが、これすらも`support/commands.ts`とTypescriptで書こうとすると色々問題が出てくる

直接的な解決方法は[この例][3]にある[repo][7]を見れば分かるが、流れとしては

1. Cypressは素の状態では`support/index.js`を読み込む
2. `support/index.js`は`support/commands.js`を読み込む
3. これによりCustom Commandsが使えるようになる

なので

1. `support/commands.js`を`support/commands.ts`にするには
1. `support/index.js`を`support/index.ts`にしないといけない
2. `support/index.ts`にしたのなら、Cypressに`support/index.ts`を読み込むように指示しないといけない
3. この為、configの[supportFile][4]を変更しないといけない
4. 更にはこれらのtsをトランスパイル出来るように色々インストールしておかないといけない


## 解決方法

**`plugins/index.js`に何か追加していたなら、事前に`plugins/index.js`はバックアップしておいた方が良い**
**@bahmutov/add-typescript-to-cypressがざっくり上書きする！**

1. `yarn add -D @babel/core @babel/preset-env @bahmutov/add-typescript-to-cypress babel-loader typescript webpack` を追加でインストール
2. `plugins/index.js`の内容が変わっているので、追加内容があったのなら編集
3. cypress.jsonに`"supportFile": "cypress/support/index.ts"`を追加（パスはcypress.jsonの位置から見て相対で）
4. `support/index.js`を`support/index.ts`に
5. `support/commands.js`を`support/commands.ts`に
6. `support/commands.ts`内に[declare global][5]を記載する
7. `support/commands.ts`内に[export {}][6]を記載する


後は通常通りcypressを走らせられるし、IntelliSenseも効く



[1]: https://docs.cypress.io/guides/tooling/typescript-support.html#Transpiling-TypeScript-test-files
[2]: https://docs.cypress.io/api/cypress-api/custom-commands.html#Syntax
[3]: https://docs.cypress.io/guides/tooling/typescript-support.html#Examples-1
[4]: https://docs.cypress.io/guides/references/configuration.html#Folders-Files
[5]: https://github.com/omerose/cypress-support/blob/master/cypress/support/commands.ts#L43
[6]: https://github.com/omerose/cypress-support/blob/master/cypress/support/commands.ts#L54
[7]: https://github.com/omerose/cypress-support
CentOS 7 に Node.js をインストールする手順

Node.js には公式レポジトリがある。詳しくは [README](https://github.com/nodesource/distributions/blob/master/README.md) 参照。

以下では、執筆時での安定版 (10.x）をインストールする。

`sudo -i` で管理者になっておくと便利。

### レポジトリの作成
```
# curl -sL https://rpm.nodesource.com/setup_10.x | bash -
```

### インストール
```
# yum install nodejs
```

### 確認
```
$ node -v
$ npm -v
```

### npm を最新版にアップデート
```
# npm update -g
```

### 確認
```
$ npm -v
```
Cloud Functions 最低限（Firestoreトリガー編）


Firestoreでのデータの生成、変更、削除等をトリガーに処理を実行するfirestoreトリガーを試してみたいと思います。
なお、HTTP（リクエストによる）トリガーについては[こちら](https://qiita.com/zaburo/items/fa810a22cc132ae1317d)をどうぞ。

## 前提

* Firebaseを利用したり、Functionを作成するための環境が整っていること。
  * まだの方はこちらをどうぞ。

## 実装

最低限の実装はおおよそ下記のような感じかと。

下記の例では、firestoreのshareという名前のCollectionのparamsというドキュメントに対して、create, update, deleteのいずれかが実行されたことをトリガーに処理（コンソールにHello Trigger!と表示）を実行します。

```js:index.js
const functions = require('firebase-functions');

exports.helloTrigger = functions.firestore.document('share/params').onWrite((change, context) => {
    console.log("Hello Trigger！");
    return 0;
});
```

>return 0;を入れているのはError: Value for argument "data" is not a valid Firestore document.とかいうエラーがログに出るのを防ぐためです。

## 実行の確認（デバッグ）

### 実行

実行は、別のプログラム等からdb.collection('share').doc('params').set({color:'red'});等のダミーコマンド実行して、トリガーの対象となっているドキュメントを生成（更新・削除）してみます。

いちいちテストのためにスクリプト書くのも面倒なので私は[SQL Tabsというツール](https://www.sqltabs.com/)と使ってデータを生成させたり、更新させたりしてます。あまり複雑な処理はできなくて不満もありますが、無いよりマシです。

### console.log()の出力をどこで確認するのか？

HTTPトリガーの場合は、出力にエラーを含ませればディバッグできますが、Firestoreトリガーの場合、console.log()を使う必要がありますが、もちろんローカルコンソールに出力はされません。コード中のconsole.log()はFirebaseコンソールのFunctionsのログにて確認できます。

下記のような感じで出力が確認できます。

![スクリーンショット 2019-09-22 7.08.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/c8d2e2ac-c975-6866-3b70-5458359e7e6d.png "スクリーンショット 2019-09-22 7.08.41.png")

なお、return 0;を入れないと、下記のようならErrorログが出力されます。

![スクリーンショット 2019-09-22 7.12.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/ef2e17df-3042-f3b0-9454-dc46b2f2336e.png "スクリーンショット 2019-09-22 7.12.30.png")


## 少し応用

私はあるドキュメントの変更をトリガーに別のDB(RDBとか）に必要な情報を書き込むような処理がしたいと考えていますので、それを意識したコードを書いてみます。とはいえ、無料でつかえるクラウドSQLサーバが無いので、とりあえずFirestoreに書き込みをしてみます。

* share/paramsの変更を起点に、logsに（ログ風の）データを書き込んでいます。
* functionが展開されるリージョンを東京に指定しています。

```js:index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

const db = admin.firestore();

exports.helloTrigger = functions.region('asia-northeast1').firestore.document('share/params').onWrite((change, context) => {
    db.collection('logs').add({
        param: 'hoge',
        after: change.after.data(),
        before: change.before.data(),
        created_at: admin.firestore.FieldValue.serverTimestamp(),
    });
    console.log("hoge");
    return 0;
});
```

## ワイルドカードの利用

ワイルドカードがいまいち何なのかわからなかったので確認してみました。

例えば、下記のようなコードを準備して、

```
exports.helloTrigger = functions.region('asia-northeast1').firestore.document('share/{doc_name}').onWrite((change, context) => {
    let doc_name = context.params.doc_name;
    console.log(doc_name);
    console.log(change.after.data());
    console.log(change.before.data());
    return 0;
});
```

```
db.collection('share').doc('params').set({});
```

を実行すると、paramsが出力され、

```
db.collection('share').doc('configs').set({});
```

を実行するとconfigsが出力されます。つまり、db操作時にパラメータを渡してやるとそれをfunction側で取得できるような仕組みのようです。

あるコレクションを監視し、どのドキュメンにどのような処理がされたか？などを知るにはいいのかもしれない（逆に、特定のドキュメントのみを関しするシーンの方が少ないか・・・）。


いまひとつ理解が足りないので継続探求するということで。
Webカメラ、ネットワークカメラ、USBカメラの違い

#　前提
深層学習による画像認識などで、USBカメラを使うことがあると思う。
そのカメラに関して、
「Webカメラ」「ネットワークカメラ」「USBカメラ」などの言葉があるが、
その使い分けが不明瞭なため、調査した。

###　前提の補足
次項の調査結果とは異なるが、
10年以上前あたりの頃は、「Webカメラ」と言えば、HTTPに対応したものであったはず。
今の「ネットワークカメラ」に近い定義だった気がする。
そうでないと、「Web」という文言が含まれているのが説明できないと思う。

#　調査結果
ネットで調べた結果を引用する形で示す。

###　引用１
『WEBカメラ監視の基本！ウェブカメラとは？IPカメラとは？違いやおすすめ解説！ 』
（　ttps://bouhancamera-choice.com/post-662/　）
という記事より引用。

ネットワークカメラとは

>簡単に説明すると、ネットワークカメラとは、「パソコン等の制御機器が不要で映像の記録と伝送が出来るビデオカメラ」のことです。有線・無線LANを通じて記録した映像をそのデータを保存するレコーダーまで伝送します。IP(インターネット・プロトコル）と呼ばれる通信方式を用いて伝送するため、IPカメラ(アイピーカメラ)と呼ばれることもあります。記録した映像を圧縮し、LANケーブルなどを通じてストリーミング再生・通信を行うので直接接続される機器はNVR(ネットワークビデオレコーダー)やスイッチングハブになります。

　　　
>ネットワークカメラに対してWebカメラとは、USBケーブルなどを利用してPCと接続し、PC側のソフトウェアを利用して撮影や録画、録画した情報の伝送などを行うカメラのことです。


###　引用2
『Webカメラとは違う「ネットワークカメラ」選びの基本とは？ (1/2)』
（　https://www.itmedia.co.jp/pcuser/articles/1408/27/news051.html　）
という記事より引用。

>そもそもWebカメラとの違いは？
　さて、このネットワークカメラだが、ビデオチャットなどに用いるいわゆる「Webカメラ」と混同する人が多いようだ。カメラであるという点を除けばまったくの別物なのだが、まずはこの違いについてきちんと押さえておこう。
　まずWebカメラは、PCに接続して利用するのが前提で、単体では動作しない。最近はOS側がドライバを持っていることがほとんどで、接続すると自動的に認識が行われ、利用可能になる。接続方式はUSBが一般的で、電源はUSBのバスパワーで供給される。ノートPCの画面上部に内蔵されているのもこのWebカメラであり、ビデオチャットなどで利用者自身を撮影するのが一般的な使い方だ。
　これに対してネットワークカメラは、それ自体がIPアドレスを持ち、PCに接続することなく単体で動作する。撮影した映像をチェックするためにはPCないしはスマートフォン、タブレットなどが別途必要になるが、撮影そのものはPCがなくとも行える。それゆえPCを常時起動させていなくても利用できるのがメリットだ。
　接続方式は有線LANケーブルが基本で、ハブないしはルータに接続して使用する。利用者自身を撮影するという使い方はあまりせず、俯瞰（ふかん）して広い範囲を撮影する使い方が主だ。

###　引用３
『Wikipedia　Webカメラ』
（　https://ja.wikipedia.org/wiki/Webカメラ　）
の記事より引用。

**前者２つの引用とはかなり違う。**

Webカメラとは

>Webカメラ（ウェブカメラ）は、WWW、インスタントメッセージ、PCビデオ等を使用して、撮影された画像にアクセスできるリアルタイムカメラのこと。広義にはライブカメラ（生中継カメラ）一般を指す。一般的に、撮影された画像は、リアルタイム、または一定間隔で保存される。PCに接続しリアルタイム画像転送の可能なUSB、IEEE 1394等のインタフェースを持ったカメラを指すほか、ネットワークインタフェースを持ち、WWWでアクセス可能なカメラのついた組み込み機器（ネットワークカメラ）を含むこともある。 

#　まとめ
コメントなどあれば、お願いします。
（たぶん、若い人が、Webカメラと言う場合は、ネットワークカメラじゃないものを指していると思う。）
USBカメラに関しては、記載、省略します。

古い用語辞典か、そのようなサイトを見つけたら、そのときWebカメラの定義を確認します。
オススメのターミナル初期設定の手順

## Iceberg

まず、次のページから [Iceberg](https://github.com/cocopon/iceberg.vim) の、macOS 用のプロファイルをダウンロードし、ターミナルに追加して、デフォルトとして設定します。

https://cocopon.github.io/iceberg.vim/#macosTerminalApp
![プロファイル](https://i.gyazo.com/d685b305088a777f55d552bf17ffdad0.png)
また、Vim 用のカラースキーマも、GitHub からダウンロードして、

https://github.com/cocopon/iceberg.vim/

次のページに書いてある通りに、配置してから、Vim の設定をいじりましょう。

https://www.vim.org/scripts/script.php?script_id=4820

```
$ mkdir ~/.vim/colors
$ cp colors/iceberg.vim ~/.vim/colors/
```

```~/.vimrc
syntax on
colorscheme iceberg
```

## フォント

次に、[Homebrew](https://brew.sh/) をインストールしたことがないなら、次のコマンドを実行した上で、

```
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

プログラミング用フォント [Cica](https://github.com/miiton/Cica) を追加して、ターミナルの環境設定から、これを使用するように変更してみてください。

```
$ brew tap homebrew/cask-fonts
$ brew cask install font-cica
```

変更前のフォントによっては、相対的に、かなり文字が小さくなったりするので、サイズも調整する必要があるかもしれません。

## Bash

そして、Bash の設定ファイルも、とりあえず、適当に作成して、

``` ~/.bashrc
export PS1="\[\e[1;32m\]\u@[\t]\[\e[0m\]:\[\e[1;34m\]\w\[\e[0m\]$ "
alias ls='ls -AFG'
HISTTIMEFORMAT="%Y/%m/%d(%a) %T $ "
```

次のコマンドで実行し、表示を確認しましょう。

```
$ source ~/.bashrc
```

また、ターミナル起動時に、自動的に `~/.bashrc` を読み込むようにするため、以下のファイルも作成しておきました。

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

他にも忘れている設定があったら、随時、追加していきたいと思います。

ちなみに、Z Shell（ zsh ）の場合の設定については「 [Mac のデフォルトシェルが bash から zsh に変更された機に乗じて乗り換える手順](https://qiita.com/normalsalt/items/5b71fbd03721800de4a0) 」を参照して頂ければ幸いです。
Laravelの "This action is unauthorized" を変更する

# 何がしたい？

LaravelにはFormRequestやGateといった「特定のユーザーに特定の操作を許可しない」という権限管理機能が備わっていますが、そこで弾かれたときの**エラーメッセージが英語**です。多言語対応のLaravelさんならそんなのサクッと変更できるでしょ！と思ったのですが、意外とさっくりできず、グーグル先生もなかなか教えてくれなかったので、僭越ながら穴埋め係させていただきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129854/be581577-2d1b-3041-a2f8-705dead4d350.png)

※この画面はAJAXでのHTTPエラーをswalで表示するという、参画しているアプリのフロント画面です。Laravel標準だと黒い画面か白い画面が出ると思います。

Laravel5.5で実装。ソース見る限りではLaravel5.3～Laravel6.0に対応。

# 結論

例外のハンドラに追加します。メソッドがすでにある場合は、`parent::prepareException($e)` の前にコードを追加します。

```php:app\Exceptions\Handler.php
    /**
     * 例外の型を変換する
     */
    protected function prepareException(Exception $e)
    {
        // これを追加
        if( $e instanceof \Illuminate\Auth\Access\AuthorizationException ) {
            $e = new \Illuminate\Auth\Access\AuthorizationException(
                '許可されていません',
                $e->getCode(),
                $e // $eがもともと持っていた情報を失わないように引き継ぐ
            );
        }

        // ↑ あえてデフォルトの動作の前に実行する
        $e = parent::prepareException($e);

        return $e;
    }
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129854/e2cdc326-4300-c1af-22b8-17c5c58d9027.png)


# 解説

## AuthorizationException のデフォルトメッセージ

「This action is unauthorized」というのは AuthorizationException のデフォルトのメッセージなのですが、Laravel6.0でも、それはハードコーディングされています。

```php:Illuminate/Auth/Access/AuthorizationException.php
    public function __construct($message = null, $code = null, Exception $previous = null)
    {
        parent::__construct($message ?? 'This action is unauthorized.', 0, $previous);
        $this->code = $code ?: 0;
    }
```

エラーや例外処理のメッセージ（例えば「Syntax Error」とか）が多言語対応していないのはふつうなことで、問題はそれをそのまま表示しようとすること。どこかで置き換えしてやるのが良さそうです。

どこで？

## prepareException

例外処理ならHander。[特定の例外の型変換をするprepareException](https://qiita.com/kd9951/items/b1bccc4666976ec90dcc#%E5%9E%8B%E5%A4%89%E6%8F%9B) が適任です。今回は型はそのまま、メッセージだけ載せ替えたい。

ただ、AuthorizationException はデフォルトの型変換として AccessDeniedHttpException に変換されています。

```php:Illuminate/Foundation/Exceptions/Handler.php
    if ($e instanceof AuthorizationException) {
        $e = new AccessDeniedHttpException($e->getMessage(), $e);
    }
```

だったら、AccessDeniedHttpException のメッセージをカスタマイズすべき？ うーむ悩ましいところですが。今回は 「AuthorizationExceptionのデフォルトメッセージを英語にしたい（その後 AccessDeniedHttpException に変換されてどう処理されるかは知らぬ）」という AuthorizationException に固有の問題なので AuthorizationException を変換対象としました。

なので、デフォルトの変換処理 `parent::prepareException($e)` の前に型変換を行っています。




# こんな記事も書いています

Laravelのちょっとマニアックな視点から、誰も書かない記事を書いています（笑
合わせてご覧いただけると幸いです（＾＾）


- 【例外処理】 [エラー画面やAPIエラーから独自エラーまで！ フローチャートでちゃんと理解するLaravelの例外処理とケーススタディ
](https://qiita.com/kd9951/items/b1bccc4666976ec90dcc)
- 【バリデータ】 [フロー図で理解するLaravelバリデータの仕組みと、チーム開発でのケーススタディ](https://qiita.com/kd9951/items/e797b17c03fc8e8f414b)
- 【バリデータ】 [Modelでバリデーションする(2行で) ＋ Laravel5のバリデーションの仕組み解説(5秒で)](https://qiita.com/kd9951/items/c06d107aa4018295aa25)
TableauとPower BIの簡易比較

## はじめに

　[Power BI 勉強会 @ 東京 #14](https://powerbi.connpass.com/event/137295/)に参加し、[Power BIの利用経験に関するLT](https://speakerdeck.com/ishiayaya/power-bi-0-dot-5keyue-tableau-5nian)をしてきました（[リンクのSpeakerdeckを参照願います](https://speakerdeck.com/ishiayaya/power-bi-0-dot-5keyue-tableau-5nian)）。元々約5年、Talbeauユーザーなので、そういったバックグラウンドをもつ方がちょっとつまづきやすい、というところや、ここ大きく違うしすげーよな、みたいなことを、37枚のスライドを10分で時間どおり終えましたがw、40分もらったらそれはそれなりに話せる内容なので、初Qiitaとしてトライとして、2つの大きな特徴を比較した表を書きます。

## どっちがいいのか
　ツール比較論でいくと、「○○が上だよね」「○○は話にならない」などの意見がよく聞かれます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/363c8ecc-b433-a1f1-cd78-953d27ec3cbc.png" width="50%">
　というのが意見です。どちらもおためしの無料版があり、仕事で使うには共有時の、最低限のアクセス権のことで、最も安いライセンスから有償版を使うことになるでしょう。なので、この問いは、どっちでもいいことです。

## TableauとPower BIの大きな特徴の比較![PowerBI-Tableau.017.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/862bb863-7ca4-72f1-49a2-6c1084fe9ee2.png)

## 関連メモ

- [Tableau経験者のPowerBI利用に関する気づきメモ](https://qiita.com/ishiayaya/items/be2103301df1a7581859)
LinuxノートPCだってMacOSっぽく3本指/4本指ジェスチャーしたい！

業務でMacOSを触る機会が増えてきたので、コンテキストスイッチ減らすためにも、
`libinput-gestures`を利用して、自宅のLinuxでもなるべく近しい操作をできるようにしてみた。  

~~かっこよく~~ｽｯｽと3本指でブラウザバックしたいのです。

# 動作環境

* Fedora30  

```
$ uname -srvo
Linux 5.2.11-200.fc30.x86_64 #1 SMP Thu Aug 29 12:43:20 UTC 2019 GNU/Linux
```

# libinputインストール

* 標準リポジトリには`libinput-gestures`が無いので、coprにあるリポジトリを有効化する。  
* 公式的にはArch LinuxとDebian/Ubuntu以外はビルドしてね、って事らしいがCoprでrpm配布されているので使う。  
* Copr嫌って方はlinuxbrewで入れるか、`make install`してください。

```
$ sudo dnf copr enable mhoeher/multitouch
$ sudo dnf install libinput.x86_64 libinput-devel.x86_64 xorg-x11-drv-libinput.x86_64 libinput-gestures
```

# libinput設定

* キーボードショートカット次第なのだが、こんな感じに設定。

```
$ cat << _'EOT'_ >> ~/.config/libinput-gestures.conf
# 3本指右スワイプでブラウザ進む(alt+Right)
gesture swipe right	xdotool key alt+Right

# 3本指右スワイプでブラウザ戻る(alt+Left)
gesture swipe left	xdotool key alt+Left

# 4本指上スワイプでMacのMission Control(control+alt+Up)
# Linux的な名称は`Show the window selection screen` (control+alt+Up)
gesture swipe up 4 xdotool key control+alt+Up

# 4本指下スワイプで仮想デスクトップ一覧の表示
# Linux的な名称は`Show the workspace selection screen` (control+alt+Down)
gesture swipe down 4 xdotool key control+alt+Down

# 仮想デスクトップの切り替え
gesture swipe left 4 xdotool key ctrl+alt+Left
gesture swipe right 4 xdotool key ctrl+alt+Right
_EOT_
```

# 自動起動設定

```
$ libinput-gestures-setup autostart
```

# 起動

```
$ libinput-gestures-setup start
```

# 設定確認

```
$ libinput-gestures-setup status
libinput-gestures is installed.
libinput-gestures is set to autostart.
libinput-gestures is running.
libinput-gestures is using custom configuration.
$ 
```

正直Macに比べたらもっさり感が否めないけど、これで3本指ｽｯｽが可能に…！
(もっさり感はスペックのせい？)

# 参考
* Linuxのタッチパッドでピンチ・3本指・4本指ジェスチャーを使う  
https://qiita.com/onokatio/items/c386da501d11a9735915  
* 公式README  
https://github.com/bulletmark/libinput-gestures/blob/master/README.md  
* CoprにあるFedora用パッケージのインストール - Neovimを事例として -  
https://qiita.com/iwaim@github/items/04b349b44770c887e102
ローカルリポジトリ削除

```
$ rm -rf .git
```
参考サイト
https://ja.stackoverflow.com/questions/5734/git-%E4%B8%8D%E8%A6%81%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E5%89%8A%E9%99%A4%E6%96%B9%E6%B3%95%E3%81%AF
[IDL] RGB Synthesis Using Himawari-8/AHI Weather Satellite Data and Superposition of Aerosol Optical Thickness (AOD) From COMS/MI Weather Satellite Data

[Characteristic]

- Synthesis and superposition techniques are required for the Clianian Satellite 1 (COMS/MI) and Himawari Satellite 8 (Himawari-8/AHI) data, and this program is designed to achieve this purpose.

[Function]

- Read longitude and binary data for Terra/MODIS data Read Himawari-8/AHI data
- Read raw data and convert to reflectance for Himawari-8/AHI materials
- Calculate solar zenith angle (SZA), solar azimuth (SAA), satellite zenith angle (VZA), satellite azimuth (VAA), and relative azimuth (RAA) for RGB composite images
- Conversion to Red, Green, Blue using reflectance for each channel
- Read raw data for COMS/MI data and convert to aerosol optical thickness
- Aerosol Optical Thickness Mapping After RGB Synthesis

[How to]

- Locate Terra/MODIS data in the same directory 
- Run source code (idl -e Visualization_Using_Terra_MODIS_Data)Check the visualization result
- Stores Cheonlian Satellite 1 and Himawari Satellite 8 data in the same directory 
- Run source code (idl -RGB_Composite_Image_Using_Himawari8_Data_And_Aerosol_Optical_Thickness_Superimposition_Using_COMS_Data)
- Check the visualization result

[OS]

- Linux
- Window 10

[Language]

- IDL

[Source Code]

- RGB Synthesis Using Himawari-8/AHI Weather Satellite Data and Superposition of Aerosol Optical Thickness (AOD) From COMS/MI Weather Satellite Data
    - https://shlee1990.tistory.com/50
- Visualization of RGB Composite Image Using Himawari-8/AHI Weather Satellite Data
    - https://shlee1990.tistory.com/66
- Visualization Using Terra/MODIS Weather Satellite Data
    - https://shlee1990.tistory.com/47
- Visualization by Landcover and Cloud Fraction Using Terra/CERES Weather Satellite Data
    - https://shlee1990.tistory.com/64
- Taylor Diagram Visualization
    - https://shlee1990.tistory.com/65

[Result]

- RGB synthesis using Himawari-8/AHI data and superposition of aerosol optical thickness (AOD) from COMS/MI data
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213021/e683d969-ba81-80dd-82ce-f5e5df9fc600.png)
[GrADS] Visualization Using Grib Format of ECMWF Model Result

[Characteristic]

- Visualization tools are needed to understand ECMWF model results, and this program is software designed to accomplish this purpose.

[Function]

- Convert grib data to another format
    - [Method 1] converting grib-> ctl using wgrib batch file
    - [Method 2] grib-> NetCDF conversion using ncl library
- Visualize in ctl or NetCDF format

[Materials]

- Data : Surface temperature in ECMWF model
- Period : June 2016
[Method]

- None
[How to]

- Same directory location for libraries required for GrADS visualization
    - xcbar.gs (Source : http://kodama.fubuki.info/wiki/wiki.cgi/GrADS/script?lang=jp)
    - worldmap (Source : ftp://cola.gmu.edu/grads/boundaries/worldmap)
    - convert grib data to ctl
    - [Method 1] converting grib-> ctl using wgrib batch file
        - [Step 1] Download grib2ctl.pl source code
        - ```wget "ftp://ftp.cpc.ncep.noaa.gov/wd51we/wgrib.scripts/grib2ctl.pl"```
        - [Step 2] wgib.c source code download
        - ```wget "ftp://ftp.cpc.ncep.noaa.gov/wd51we/wgrib/wgrib.c"```
        - [Step 3] Compiling with wgrib.c
        - ```gcc wgrib.c -o wgrib```
        - [Step 4] Setting and Granting wgrib and GrADS Environment Variables
        - ```open grib2ctl.pl```
        - ```$wgrib=’wgrib’```
        - ```$wgrib=’/usr/local/bin/wgrib```
        - ```$pdef_dir=’/usr/local/lib/grads```
        - ```chmod 755 grib2ctl.pl```
        - [Step 5] Transform ctl according to analysis site and prediction field 
            - Analyst Field
                - ```grib2ctl.pl grib_file > grib_file.ctl```
                - ```gribmap -i grib_file.ctl -0```
            - Prediction
                - ```grib2ctl.pl -verf grib_file > grib_file.ctl```
                - ```gribmap -i grib_file.ctl```
    - [Method 2] grib-> NetCDF conversion using ncl library
        - ncl_convert2nc grib_file > input.nc
        - Visualization_Using_Grib_Format_of_ECMEF_Model_Result.csh)
        - Check the visualization result

[OS]

- Linux

[Language]

- GrADS
- ShellScript (csh)

[Source Code]

- Visualization Using Grib Format of ECMWF Model Result
    - https://shlee1990.tistory.com/71
- Visualization Using ASCII Format Radiation Transfer Model (RTM) Result
    - https://shlee1990.tistory.com/69
- Visualization using Medium Weather Model (WRF ARW)
    - https://shlee1990.tistory.com/67



[Result]
- Worldmap visualization required for GrADSFig. Worldmap visualization required for GrADS.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213021/c75c26b8-5907-662d-f87b-9e2f1af2aa44.png)


- Visualize surface temperature using ECMWF model results
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213021/51f54636-b048-4af1-efda-2177aae9f8dc.png)
[Python] Visualization Using ASCII Format of Himawari-8/AHI and Aqua/CERES Weather Satellite Data

[Characteristic]

- Visualization tools are needed to understand ASCII data in the form of ASCII, and this program is software designed to accomplish this purpose.

[Function]

- Scatter plots using Himawari-8/AHI and Aqua/CERES data 
- Mapping with Himawari-8/AHI and Aqua/CERES Data

[Materials]

- Data : Spatio-temporal agreement with Himawari-8/AHI and Aqua/CERES
- Period : October 01, 2016
- Resolution : 2 km

[Method]

- None

[How to]

- Input Directory Same Directory Location
- Run the source code (run Jupyter notebook)
- Check the visualization result

[OS]

- Window 10

[Language]

- Python 2.7

[Source Code]

- Visualization Using ASCII Format of Himawari-8/AHI and Aqua/CERES Weather Satellite Data
    - https://shlee1990.tistory.com/51
- Visualization Using Binary Format of COMS/MI Weather Satellite Data
    - https://shlee1990.tistory.com/70
- MOHID Ocean circulation model mapping (file reading and function setting)
    - https://shlee1990.tistory.com/72
- Visualization of flow rate vectors, SST, and salinity using MOHID ocean circulation model results files.
    - https://shlee1990.tistory.com/65
- Visualization of flow rate vectors, SST, and salinity using MOHID ocean circulation model results files.
    - https://shlee1990.tistory.com/73
- Time series graph using radiometer brightness temperature data
    - https://shlee1990.tistory.com/74
- Visualization of Temperature and Humidity Contours by Elevation Using Radiometer and Radiosonde Observations
    - https://shlee1990.tistory.com/75

[Result]

- Downward Shortwave Radiation at the top of the Atmosphere Using Himawari-8/AHI Data

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213021/708e08c3-cd84-59fd-74b1-e38ee4385321.png)

- Downward Shortwave Radiation (DSR) at ths Surface Using Aqua/CERES Data

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213021/54db951b-367a-1cef-00db-171daf3d3be4.png)

- Percent Error of Downward Shortwave Radiation (DSR) at ths Surface Using Himawari-8/AHI Data and Aqua/CERES Data

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213021/400511dc-ccf8-1ae6-2217-7914fc09d170.png)

- Downward Shortwave Radiation (DSR) at the Surface Using Himawari-8/AHI and Aqua/CERES Data
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213021/46a7decb-6fbc-4df2-c855-0087ed9b6ed4.png)
DockerでSnes9xを動かして遊びたい！

Linux Mint 18.3 (Sylvia) を使っているが、Ubuntu（と言うか、Debian）の仲間のOSでは、Snes9xは動かないので、ZSNESで我慢しなければならないらしい。
しかし、ZSNESにはゲームをする上で許容できない以下の問題がある。

- ファンクションキーのガイドがないため、セーブ（ロード）したいのにうっかりロード（セーブ）しやすい
- サウンドノイズや再生不良が頻繁に起こる

[こちらのサイト](https://do-you-linux.com/blog/2017/07/28/linux-%E3%82%B2%E3%83%BC%E3%83%A0%E3%82%A8%E3%83%9F%E3%83%A5%E3%83%BC%E3%83%AC%E3%83%BC%E3%82%BF%E3%83%BC-ps-ps2-n64-psp%E3%83%95%E3%82%A1%E3%83%9F%E3%82%B3%E3%83%B3%E3%82%B9%E3%83%BC%E3%83%95/)によれば、FedoraならSnes9xが動作するとのことなので、Linux Mint上のDockerコンテナとして起動したFedoraでSnes9xを動かそうと考えた。

# 手順

以下に示す通り、順番にファイルの作成、および、コマンドの実行を行う。

## Dockerfile

適切なディレクトリ（例：~/docker/fedora30_snes9x）を作成し、そこに以下のDockerfileを作成する。

``` Dockerfile
FROM fedora:30
RUN dnf -y install wget
RUN wget http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-30.noarch.rpm
RUN rpm -Uvh rpmfusion-nonfree-release-30.noarch.rpm
RUN dnf -y install snes9x-gtk
RUN dnf -y install dbus-x11
RUN dnf -y install libGL
```

## build.sh

いちいち長いコマンドを打つのが面倒なので、前述のDockerfileと同じディレクトリに以下のbuild.shを作成しておくと良い。

``` sh
#!/bin/sh
docker build -t fedora30/snes9x .
```

## run.sh

さらに長いコマンドを打つのはもっと面倒なので、前述のDockerfileと同じディレクトリに以下のrun.shを作成しておくと良い。
以下を見れば分かる通り、 $HOME/snes を /root/snes にマッピングしている。
これは、ホストの $HOME/snes にROMファイルを置くことを想定している。

``` sh
#!/bin/sh
docker run -it --name=fedora30_snex9x \
--net host \
-e DISPLAY=$DISPLAY \
-v $HOME/.Xauthority:/root/.Xauthority \
-v $HOME/snes:/root/snes \
-v /tmp/.X11-unix:/tmp/.X11-unix -v /var/lib/dbus:/var/lib/dbus \
-v /var/run/dbus:/var/run/dbus -v /etc/machine-id:/etc/machine-id \
--device=/dev/dri:/dev/dri --device=/dev/snd:/dev/snd \
--device=/dev/input:/dev/input \
fedora30/snes9x bash
```

## ビルド＆起動

以下のコマンドを実行し、Dockerコンテナをビルドして起動しよう。
なお、便宜上 $ で始まる行はDockerホスト、 # で始まる行はDockerコンテナで実行するコマンド。

```
$ cd ~/docker/fedora30_snes9x
$ chmod +x build.sh
$ chmod +x run.sh
$ ./build.sh
$ ./run.sh
# cd /root/snes
# snes9x-gtk
```

![Screenshot from 2019-09-22 03-04-36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167705/0f94d5bc-5e20-1d05-a380-e7544a6efe82.png)

## Snes9xの設定

以下の初期設定は必須である。

- View → Change Size で適切なサイズを選択
- Options → Controller Ports → SNES Port 1 → Joypad を選択してキーボード使用
- Options → Preferences → Sound で Dynamic rate control をオンでノイズ低減
- Options → Preferences → Joypads → Buttons でキーボードの割り当て

もともとなのか、環境のせいかは不明だが、設定変更を行うと不正終了することがある。
それでも繰り返し設定すれば、設定は反映されるのでめげずに進めて欲しい。

# 参考

以下がなかったら実現困難だったので、とても感謝している。

- [古賀政純の「攻めのITのためのDocker塾」：第22回 Dockerで3Dゲームを動かす――稼働編 (1/3)](https://www.itmedia.co.jp/enterprise/articles/1605/18/news001.html)
- [Docker コンテナ上で動く X11 アプリケーションのウィンドウをディスプレイに表示させる](https://qiita.com/hoto17296/items/7c1ba10c1575c6c38105)

# 追記

- Fedoraリポジトリのバイナリが悪いのか、Dockerコンテナ環境が悪いのか、Snes9xのメニューを表示したときなどにcore dumpするときがあり、安定性に欠けるのが残念である。Windows版の安定性はかなり優れている。
SIMカードのATR, PPS(ETSI TS 102 221;6章)

ETSI TS 102 221 V16.0.0をベースに自分の知識の整理のためにまとめます。
これ単独で理解するのは難しく、他の章やISO7816などを適宜読んでいく必要があります。
特にATRコマンドの内容は、ISO7816-3に規定されているので、このドキュメントだけでは学びきれません。別途記事を作成予定です。

### 簡単用語解説

**ATR(Answer to Reset)**
SIMカードを刺したデバイスの電源を入れた時、最初に両者の間でどのようなやりとりがされるか
**ターミナル**
要するにSIMを差し込む端末、デバイス（i.e.スマホとか）
**F**
Clock rate conversion integer
**D**
Baud rate adjustment indicator
この値が大きいほど、Elementary Time Unitが小さくなります。
**Elementary Time Unit(etu)**
1ビットの伝送時間を表す単位
etu = F/D * 1/f

### 6.3.0 ATR(Answer to Reset)のイントロダクション

- リセットが行われてから、UICCからターミナルへ送られる最初のコマンド
- ISO-7816-3で規定されている
- ターミナルは送信プロトコルのインターフェースキャラクターを受け取れる
- T=0,1しか扱わないターミナルであっても、T=0,1以外のものや、ヒストリカルバイト、チェックバイトを受け取れなければならない
- T=15 グローバルインターフェースキャラクターがターミナルからUICCへと返される

### 6.3.1 ヒストリカルバイトのコーディング

- ヒストリカルバイトは外部に、カードをどのように扱うかを提示する
- 詳しくはISO-7816-4に規定
- カテゴリインジケーターはUICCから送信される最初の1バイト
- 値が80であれば、ヒストリカルバイトはCOMPACT-TLVであらわされる
- カードから最初に送信される情報は”card data service”オブジェクトでなければならない。（タグは31）
- 次に送信される情報は”card capability”オブジェクトである。（タグは73）
- その他のデータはオプション

### 6.3.2 スピードエンハンスメント

- ターミナルとUICCはデフォルトである(F,D)=(372,1)に加え、最低でも(F,D)=(512,8),(512,16)をサポートする。
- もしターミナルが他の値でPPSを要求した場合、それに従う。
- FとDの値はATRのTA1に存在。
- ISO-7816-3に記載されている以上の速度を出すために、Dのアディショナルバリューが定義されている


### 6.3.3 グローバルインターフェース

- グローバルインターフェースバイトは、ATRのT=15インディケーションの後に存在
- グローバルインターフェースはオプションで、T=15を指し示すtDi(i>2)に存在の有無が記載されている
- tAi(i>2)の内容とコーディング方法はISO-7816-3にて定義
- tBi(i>2)については下記を参照

| 　b8-b1  | 意味                                     |
|----------|------------------------------------------|
| 00000000 | 追加のサポートなし                       |
| 10010000 | ローインピーダンスドライバーとプロトコル |
| 11000000 | インターチップUSB                        |
| 10100000 | UICC-CLF (ETSI TS 102 613)               |
| 10001100 | セキュアチャネル (ETSI TS 102 484)       |
| 10000010 | eUICC                                    |

他の値は全てRFU

### 6.4 PPS Procedure

**PPS:Protocol and Parameter Selection**

- **デフォルト以外の伝送パラメーターを使うための決まりごと**
- ターミナルとUICCの両方でサポート
- 代替のパラメーターの内容はATRに記載される（ISO7816-3、本稿6.3.3の表に準拠）
- PPS1では、ターミナルはUICCに指定された範囲の値を選ぶ
- PPS2は、ATRのT=15の後の初めのtBi(i>2)のみで使われ、コーディングもtBiと同等である
- PPS2の値は、ターミナルによってサポートされる機能による
- tBiの機能をサポートしないターミナルでは、PPS2をサポートする必要はない
- ターミナルが、カードから提供されるATRのTA1の解釈に失敗した場合、デフォルトの(372,1)を用いる前に、利用可能な最速の(Fi,Di)を用いて最低でも1つのPPSを実行しなければならない。
firebase initでエラーが起こる。

## firebaseにログインしているのにエラー

```
$ firebase init
// 色々進めるとエラーが起こる
Error: Failed to list Firebase projects. See firebase-debug.log for more info.
```

色々調べてみると

>firebase-toolsをアップグレードすると、認証トークンが無効になる可能性があります。ログアウトして再度ログインするだけです

これが怪しい。

参考
https://stackoverflow.com/questions/57941289/how-do-i-solve-error-failed-to-list-firebase-projects-see-firebase-debug-log

## ログアウトして再度ログイン

```
$ firebase logout
$ firebase login
```

これでfirebase initがうまくいきました。
動的計画法 (Dynamic Programming：DP) 学習メモ　～by Python～　Part 1

# はじめに
動的計画法について学んだことを初心者視点でなるべく簡潔にまとめる
”[Educational DP contest/DPまとめコンテスト（EDPC）](https://atcoder.jp/contests/dp/)”の問題を解くことを目標に進めていく
今回は簡単な問題を解きながら動的計画法の基礎を学ぶ

※※※　参考にさせていただいた記事
[動的計画法超入門！ Educational DP Contest の A ～ E 問題の解説と類題集
](https://qiita.com/drken/items/dc53c683d6de8aeacf5a)[典型的な DP (動的計画法) のパターンを整理 Part 1 ～ ナップサック DP 編 ～](https://qiita.com/drken/items/a5e6fe22863b7992efdb)

# 具体的に学ぶ
__問題
n個の整数 a[0],a[1],…,a[n−1]が与えられる。これらの整数から何個かの整数を選んで総和をとったときの、総和の最大値を求めよ。また、何も選ばない場合の総和は 0 であるものとする。__
***
仮に3個の整数 1,-2,3が与えられたとする

```
n = 3
a[0] = 1
a[1] = -2
a[2] = 3
(a = [1 -2 3])
```


まず、全探索で考える
<img width="363" alt="DP１.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500055/c871c435-5f4e-6fe9-f9bb-a910c351e424.png">
（青線はa[0~3]を足す操作、赤線は足さない操作）
右端の列の8個の数字が得られる
つまり、最大の値は4
このとき計算量はO(2^n)となり、nが大きくなると計算に時間がかかる
***

そこで、不必要な計算を除いていく
矢印を一つ進めるごとに出現する2つの数字を比較し、大きい方の数字だけ生かしていけばよい
小さい方の数字以降の計算は除外するように考える
<img width="352" alt="DP2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500055/6b74c813-64b2-9c15-ed60-3da12b47cdf2.png">
このとき、上図の黄色のマスを辿っていくことで最終的に最大値を得られることが分かる
この黄色マスのリスト（名前をdpとする）を作成することを目標とする
***
以下、実装手順
***
①黄色マスの数字を順番に保存するリスト（長さは4(=n+1)となる）を作成する
（※初期状態（dp[0]のこと）を0とする）

```
dp = [0]*4
```
***
②黄色マス2マス目 (dp[1]) への移動において、最大値をとるためには初期状態 (dp[0]) に a[0] を足した方が良いのかを判定する

```
dp[1] = max(dp[0],dp[0]+a[0])
```
***
③黄色マス3マス目 (dp[2]) への移動において、最大値をとるためには2マス目 (dp[1]) に a[1] を足した方が良いのかを判定する

```
dp[2] = max(dp[1],dp[1]+a[1])
```
***
④黄色マス4マス目 (dp[3]) への移動において、最大値をとるためには3マス目 (dp[2]) に a[2] を足した方が良いのかを判定する

```
dp[3] = max(dp[2],dp[2]+a[2])
```
***
⑤完成した黄色マスの数字リストから答えを出力する
（今回はリストの一番最後の数字のため dp[-1]）

```
print(dp[-1])
```
***
まとめると

```
dp = [0]*4
dp[1] = max(dp[0],dp[0]+a[0])
dp[2] = max(dp[1],dp[1]+a[1])
dp[3] = max(dp[2],dp[2]+a[2])
print(dp[-1])
```
となる
***
これを拡張して、nがどんな値をとっても対応できるようにする

```
dp = [0]*(n+1)
dp[1]   = max(dp[0],dp[0]+a[0])
dp[2]   = max(dp[1],dp[1]+a[1])
dp[3]   = max(dp[2],dp[2]+a[2])
...
...
...
dp[n-1] = max(dp[n-2],dp[n-2]+a[n-2]) 
dp[n]   = max(dp[n-1],dp[n-1]+a[n-1])
print(dp[-1])
```

これをfor文を用いて表現する

```
dp = [0]*(n+1)
for i in range(n):
    dp[i+1] = max(dp[i],dp[i]+a[i])
print(dp[-1])
```

これで完成

# おわりに
動的計画法を簡単な具体例を用いて考えた
今後は実際の問題に対して応用していくことを考える
次回、EDPC_A,Bを解く
fakerを使用してダミーデータの生成 (RubyOnRails)

#初めに
ダミーデータを用意する時、便利なgemがあったのでメモを残します。

#体験談
自作のecサイトを作成した際、ダミーユーザを用意する必要がありました。
そこで、ユーザ情報の登録を手作業で約30名ほど登録しました。（約30分かかり大変でした）
また、seedを使い商品の登録をしましたがこちらも一個一個情報を入力するので、かなりの時間を掛けました。

最近、ダミーデータを簡単に且つ大量に生成してくれるgemを見つけました。
私のような者が今後出ないように簡単にダミーデータを生成する方法を紹介します。

#開発環境
・ruby-2.5.5
・Rails 5.2.3

#やり方
fakerというgemを使用します。
以下に導入、設定方法を記します。

##gemの用意
```ruby:Gemfile
gem 'faker'
```
***※`bundle install`を忘れずに***

##seedの設定
app/db/seed.rbに設定を記述します。

```ruby:seed.rb
50.times do |n|
  name = Faker::Name.name 
  email = Faker::Internet.email
  password = "password"
  User.create!(name: name,
               email: email,
               password: password,
               password_confirmation: password,
               )
end
```
***※最後に`rails db:seed`を忘れずに***

たったこれだけで、ユーザのダミーデータを５０個生成することができます。

#参考資料
・[Fakerを使ってみました！（使い方と実行例）](https://qiita.com/ginokinh/items/3f825326841dad6bd11e)
・[fakerのgithub](https://github.com/faker-ruby/faker)

#最後に
様々なデータを生成できる（ポケモンとかドラゴンボールとか)のでぜひ利用してみてください。
集合被覆問題をPuLPで解く

集合被覆問題をPythonで解きたい、と思ったときに調べているとこちらのサイトに出会った。
http://www.nct9.ne.jp/m_hiroi/light/pulp06.html
このサイトにある集合被覆問題についてのコードは私が調査していた問題にちょうどマッチしていたので参考にさせてもらった。こちらのコードではtkinterで実行結果を描画しているが、私はmatplotlibで表現したいと思い、すこし手を加えさせてもらった。

施設配置問題における集合被覆問題は、施設設置可能集合Mと、利用者集合Nが与えられた時、各施設がなるべくすべての利用者をカバーするように、コストと施設数を最小化し、施設の配置を決定することを目的とする。
定式化すると、

```math
Min\quad \sum_{j=1}^{n}x_{j}\\
s.t.\quad \sum_{j=1}^{n}w_{ij}x_{j}\geqq1\quad \forall i\in M \\
x_{j}, w_{ij}\in 0, 1 \quad \forall j \in N\\
M=\{1,2,3,\cdots,m\}\\
N=\{1,2,3,\cdots,n\}
```

i : 利用者のいる場所
j：施設設置可能地点
M：利用者集合
N：施設設置可能地点集合
xi：地点 i に設置するか否か
wij：地点 i にいる利用者が施設設置可能地点 j の施設への需要があるか否か

今回は、利用者を平面上にランダムに n 個配置し、半径 r 内にある施設を利用できる条件で、集合被覆問題を解く。
n=25, r=20とし、フィールドを80x80の中で最小の配置を考えることにする。

```python
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import random, math, time
import pulp

# 入力データ作成、利用者・施設設置可能点生成
def make_data(n, upper):
    random.seed(5)
    X = [random.randint(0, upper) for i in range(n)]
    Y = [random.randint(0, upper) for i in range(n)]
    return [X, Y]

# 利用者(p1)と施設(p2)の距離を測る
def distance(p1, p2):
    dx = p1[0] - p2[0]
    dy = p1[1] - p2[1]
    return math.sqrt(dx * dx + dy * dy)

# 需要変数(二値変数)行列を生成
def make_matrix(ps, r):
    def check(a):
        if a <= r: # 半径がr以下であれば要素を1に、そうでなければ要素を0
            return 1
        else:
            return 0

    unit_list = [] # plotできるようにn次正方行列に整形
    for n,m in zip(ps[0], ps[1]):
        unit = (n,m)
        unit_list.append(unit)

    return [[check(distance(p1, p2)) for p2 in unit_list] for p1 in unit_list]

# グラフ上に描画する
def draw(ps, fs, r):
    fig = plt.figure(figsize=(7,7))
    ax = plt.axes()
    x = np.arange(0, 80, 0.1)
    plt.scatter(ps[0], ps[1], s=20) # 利用者

    for k, (i,j) in zip(fs, zip(ps[0], ps[1])):
        if k.value() == 1: # 施設を設置する場合
            plt.scatter(i, j, s=20, color='red')
            c = patches.Circle(xy=(i, j), radius=r, fill=False) # カバー範囲
            ax.add_patch(c)
        else:
            pass

    plt.axis('scaled')
    ax.set_aspect('equal') # 縦横比を調整
    plt.grid()
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_xticks(np.linspace(0, 80, 9))
    ax.set_yticks(np.linspace(0, 80, 9))
    plt.show()

# 解く
def solver_set(ps, r):
    size = len(ps[0])
    cs = make_matrix(ps, r) # 入力データ生成
    prob = pulp.LpProblem('set-cover')
    fs = [pulp.LpVariable('f{}'.format(i), cat='Binary') for i in range(size)] # 施設設置変数
    prob += pulp.lpSum(fs) # 目的関数
    for c in cs:
        prob += pulp.lpDot(c, fs) >= 1 # 制約条件

    s = time.time() # 時間計測
    status = prob.solve() # 問題が解けたのか、状態確認
    print('Status', pulp.LpStatus[status])
    print('z 施設数：', prob.objective.value())
    print('処理時間：', time.time() - s)
    draw(ps, fs, r)

n = 25 # 利用者・施設を合わせた地点数
r = 20 # 半径
upper = 80 # 乱数の上限値
solver_set(make_data(n, upper), r)

# 結果
# Status Optimal
# z 施設数： 9.0
# 処理時間： 0.05631732940673828
```

![mySCP1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280072/1d3b77aa-2878-2567-d512-a074b09ac687.png)

無事、実行結果を描画できた。
例外処理 Exception

Exceptionには３種類ある。
①Error系例外（catchする必要がない）
②Exception系例外（catchしなければならない）
③RuntimeException系例外（catchしなくてもいい）

②Exception系例外（チェック例外）はcatchしなければコンパイルエラーになる。

ファイルの読み書き中などにエラーでプログラムが落ち、ファイルが開いたままの状態になる。
その際に有効なのが、try~catch~finally文である。
try {
// 本来の処理
} catch (Exception e) {
// 例外処理
} finally {
// 常に動く処理
}

例外の伝播
mainメソッドからsubメソッドを呼び、
subメソッドからsubsubメソッドを呼び出す処理があるとする。
subsubメソッドでExceptionが発生した場合、
catchされない限り、呼び出し元のメソッドにたらいまわしにされる。
これを例外の伝播と呼ぶ。
だが、Exception系例外の場合、catchしなければコンパイルエラーになるため、
例外の伝播は起きないのだが、メソッドを宣言する際にスロー宣言を行うことで、例外の伝播が許可される。
public static void main method (String str) throws IOException {
sub();
}

0922追記
Exception系例外（チェック例外）の具体的な種類について
・IOException（入出力関係の例外）
・SQLException（DB系の例外）
・ClassNotFoundException（クラスが見つからない）
・InstantiationException（インスタンス化不可のクラスをnewした時）
・InterruptedException（スレッドへの割り込み）
・NoSuchFieldException（クラスに要求したフィールドがない）
・NoSuchMethodException（クラスに要求したメソッドがない）
GitHub Actions で Flutter の analyze + test を走らせる (+ Codecov)

## 前置き
"[Flutter でも Codecov を導入して test モチベを上げよう!](https://qiita.com/sensuikan1973/items/551572dc8ec92cc90fdb)" で書いたように、CircleCI で Flutter の analyze + test を走らせて Codecov で coverage を眺められるようにしているのですが、[GitHub Actions](https://github.com/features/actions) で同様のことをやってみました。

## Workflow をどう書くか
### 結論
先に結論となるファイルを示すとこんな感じです。
シンプルなサンプルにしました。
これで **`flutter analyze` + `flutter test` + `codecov への upload`** が出来ちゃいます:ok_woman_tone1:
あ、`.codecov.yml` は配置してあるものとします。

```..github/workflows/flutter_analyze_and_test.yaml
name: flutter_analyze_and_test

on:
  pull_request:
    types: [opened, synchronize]
  push:
    branches:
      - master

jobs:
  test:
    name: sample test sensuikan1973
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - uses: actions/setup-java@v1
        with:
          java-version: '12.x'
      - uses: subosito/flutter-action@v1
        with:
          channel: 'stable'
      - run: flutter pub get
      - run: flutter analyze
      - run: flutter test --verbose --coverage --coverage-path=~/coverage/lcov.info
      - uses: codecov/codecov-action@v1.0.2
        with:
          token: ${{secrets.CODECOV_TOKEN}}
          file: ~/coverage/lcov.info
```

PR 上ではこんな感じに表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159680/b25da06f-3f6b-1bf5-4aa0-9ea0f1858f6a.png)
ちなみに、CircleCi ほど cache 周りを頑張れないのが辛いのですが、今後強化されていくんだと思います。

### 依存
[Marketplace](https://github.com/marketplace) で気になる単語を調べると、既に色々出ています！
今回使わせてもらったのは以下 2 つ。

- [Codecov GitHub Action](https://github.com/marketplace/actions/codecov) : 早くも公式で出ているので、これを使う
- [Flutter action](https://github.com/marketplace/actions/flutter-action) : サードパーティとして早くも出ているものがあったので使わせてもらいました。

### hook
[events-that-trigger-workflows](https://help.github.com/en/articles/events-that-trigger-workflows) に書かれているように、とても大量のトリガーが用意されていて、すごい色々なことに使えそうですね。
今回はとりあえず、PR の更新(push)のタイミング, master への push のタイミング で走らせたかったので、こんな風に書きました。

```yaml
on:
  pull_request:
    types: [opened, synchronize]
  push:
    branches:
      - master
```

### secrets
これは Settings から定義します。ここです〜
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159680/21e71a4e-4d21-169e-497e-818adca32e49.png)

## バッジも出せる
いいですねー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159680/1067d83b-42bc-9ec2-3c80-d04409a75c42.png)
詳細は [公式ドキュメント](https://help.github.com/ja/articles/configuring-a-workflow#referencing-an-action-from-a-public-repository) を参照のこと。
KotlinのNull Safety攻略ガイド

## Null Safetyって何？
Null Safety = **変数がNullの場合に安全に処理を行ってくれる**
もう少し端的に述べると**NullPointerExceptionを防いでくれる**。
Java経験がある方なら一度は経験したことのあるNullPointerException。
nullのメンバにアクセスしようとする際にNullPointerExceptionが生じ、アプリをクラッシュさせてしまう。
Null Safetyはこの事象を防ぐことを目的としている。

## Non-NullとNullable
kotlinの変数の型にはNon-NullとNullableの2種類が存在する。

- Non-Null：null代入されない想定の型(null非許容) 
- Nullable：nullが代入される想定の型(null許容)

上記のように、簡単に述べるとnullが代入できるかできないかの違いとなる。
実際にコードに記述する際はどうなるのか？

```kotlin
class MainActivity: AppCompatActivity() {
  //kotlinでnullを非許容するとする型宣言(Non-Null)
  var non_null_text: String = ""

  //kotlinでnullを許容する型宣言(Nullable)
  var nullable_text: String? = ""

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //コンパイルエラー
        non_null_text = null
        //nullが代入される
        nullable_text = null
    }
}
```

一般的なkotlinの型宣言は`non_null_text`のような形になると思うが、これだとnullは許容してくれない。
そのため、`nullable_text`のように型名の後に`?`をつけて宣言を行うことでnullを許容してくれるようになる。

## Safe Callsと!! Operator
nullが入ってもいいように`String?`で型宣言も行い、試しに`nullable_text.length`でも実行してみようと思ったが、エラーが生じてしまった。
エラー内容は`only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?`となっている。
冒頭でも述べたが、これはnullのメンバにアクセスすることでNullPointerExceptionが生じてしまうことを示している。
エラーの解決策としては、内容にも書かれているように`?.`か`!!.`をつければいい。
ただし、この２つは意味合いはまったく異なるものであることは理解しておいて欲しい。
コードの記述方法は２つとも似ている。

```kotlin
val length1 = nullable_text?.length
val length2 = nullable_text!!.length
```
上記の記述でコンパイルエラーはなくなる。
nullable_textがnullだった場合に、２つがどのような挙動をするのかというと、`length1`では処理が通るが、`length2`では**NullPointerExceptionが生じ、クラッシュしてしまう**。

- `?.(Safe calls)`

`?.`を使用すると、もし変数がnullでなければそのまま処理を行うが、変数がnullの場合は処理を行わずにnullを返すようになる。
そのため、アプリがクラッシュするようなことはなくなる。

- `!!.(!! Operator)`

`!!.`を使用すると、もし変数がnullでなければそのまま処理を行うが、変数がnullの場合はNullPointerExceptionを返すようになる。
そのため、アプリがクラッシュする。

上記のような違いがあるので、使い分けは慎重に、特に`!!.`は気をつけて使用する必要がありそう。

## エルビス演算子
`?.`を用いて`nullable_text?.length`が使用できるようになったが、`nullable_text`がnullの時は空文字を代入したい...
そのような時に役立つのがエルビス演算子`?:`になる。

```kotlin
//nullable_textがnullの場合、length1にはnullが代入されてしまう
val length1 = nullable_text?.length
//nullable_textがnullの場合、length2には""(空文字)が代入される
val length2 = nullable_text?.length ?: "
```

エルビス演算子は、`?:`より左側の処理がnullでないのであればそのまま処理を行い、nullであるのならば`?:`より右側の処理を行う。
ただし、`?:`より右側の処理が行われるのは`?:`より左側がnullの時のみである。
django

djangoで出る
Firefoxだと出てChromeだと出ない

```
----------------------------------------
Exception happened during processing of request from ('192.168.1.15', 55025)
Traceback (most recent call last):
  File "C:\Users\{UserName}\AppData\Local\Programs\Python\Python37\lib\socketserver.py", line 650, in process_request_thread
    self.finish_request(request, client_address)
  File "C:\Users\{UserName}\AppData\Local\Programs\Python\Python37\lib\socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "C:\Users\{UserName}\AppData\Local\Programs\Python\Python37\lib\socketserver.py", line 720, in __init__
    self.handle()
  File "C:\Users\{UserName}\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\servers\basehttp.py", line 171, in handle
    self.handle_one_request()
  File "C:\Users\{UserName}\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\servers\basehttp.py", line 179, in handle_one_request
    self.raw_requestline = self.rfile.readline(65537)
  File "C:\Users\{UserName}\AppData\Local\Programs\Python\Python37\lib\socket.py", line 589, in readinto
    return self._sock.recv_into(b)
ConnectionAbortedError: [WinError 10053] 確立された接続がホスト コンピューターのソウトウェアによって中止されました。
----------------------------------------
```
数学　マルコフの不等式

#マルコフの不等式

任意の確率変数Xと a>0 に対して (期待値E[|X|]が存在するとき)、

```math
P(|X| \geq a) \leq \frac{E[|X|]}{a}
```
確率論における基本的な不等式。

#マルコフの不等式の意味
```math
P(|X| \geq a)
```
はXの絶対値がa以上となる確率を表している。E[|X|]は|X|の期待値。

マルコフの不等式は、|X|の期待値が大きくなければ|X|が大きくなる確率はそんなに高くないことを表している。


##参考
https://mathtrain.jp/markovinequality
ググり方に見るエンジニアの個人間の認知方法の壁について

```
秋刀魚の塩焼きが美味しい新宿の居酒屋
```
と

```
新宿 居酒屋 秋刀魚 塩焼き
```
とググる人では何が違うのか考えてみよう
って問題提起の記事です。
何かしらの答えが記述されているわけではないので、そのつもりでお読みください。

##### ( 2019/09/25 追記 )  
何件かコメント頂いておりますので、ぜひコメントもお読みください。
個人的には、nao_nao_naさんに頂いたコメントが、僕が文章化出来ていなかった部分を、
明文化して代言して頂いたような内容だったので、ぜひ。

## 記事を書いた経緯
個人的にはずっと考えていたのですが、エンジニアをしている友達と飲んだ時に話をしたら以外と盛り上がったので、色々な方の意見を聞ければと思い、帰り道でザーッと書いています。


## 考え始めた理由
OJTのメンターとして新人君と関わると、「単語で区切ってググる」人と、「文章で書いてググる」人がいることに気づきました
その2グループを考えると、総じて「単語で区切ってググる」人の方がエンジニアとしての技術習得が早いような気がします。
その2グループの差の原因が明確になれば、新人君の指導に役立つのではと思い、考え始めました。

## この問題のゴールとしたいこと
ググり方の違いの、出来るだけ原始的な？1次的な？理由を見出すことです。
さらに言えば、その理由は、「勉強しろ」的な解決方法ではなく、考え方やアプローチの仕方で改善できるものであることが望ましいです。
##### ( 2019/09/25 追記 )  
あくまで「違いの理由」について議論したいと考えています。
なので、決して「単語で検索する方が優秀」と論じたい訳ではなく、
むしろ、文章でググる派の方から、「文章でググる方がこういう点でメリットがある！」という
意見を頂けると最高かなと考えています。


## 僕や友達が思った理由の候補
もはや脳科学の領域なので、明確な答えはでていませんが、僕や友達が思った理由の候補は以下のような感じです。
・地頭の違い
・経験の差によるもの
・より汎用的な単語への言い換え力
・推理力/類推力の違い


一つずつ少し触れていくと、

・地頭の違い
→つまるところはこれだと僕個人的には思っています。が、それでは「勉強しろ」で終わってしまうので、便宜上却下かなぁ。

・経験の差によるもの
→たしかにそれは間違いないけど、「単語でググってる」人は何か失敗体験があったのかというと、必ずしもそんなことはない気がするので、微妙ですかね。

・汎用的な単語への言い換え力
→「汎用的な単語へ置き換える間に接続詞が省略されていく。からその言い換え力に起因するのではないか。」という意見がありました。なるほど、たしかに。でも、そうすると、「じゃあその言い換え力は何によるものなの？」となるので、本質の答えではないような気がします。

・推理力/類推力の違い
これも一つ前と同じですね。一因ではあるような気がしますが、1次的な原因ではないような気がします。


## 僕個人の考え
つまるところは「地頭の違い」ってところに落ち着くと思ってます。
なぜならそれ以上は脳科学の世界になるので、門外漢の私が議論しても仕方がないからです。

### じゃぁなぜまだ考えるのか
この問題について議論する過程ででてくる「もしかしてこれが理由では？」は新人君だけではなく、僕のような若手〜中堅エンジニアにとっても有益な「新しい装備」のような「新しい考え方」を得る一助になるのではないかと、考えているからです。


## 記事を読んでいただいたみなさんにお願いしたいこと
理由などはつけず、コメント書き逃げでも良いので、「もしかしてこれが原因では？」と思う内容をコメントして頂ければ幸いです。
頂いたコメントについては、(記載がない場合は)理由など含めて考察してみようかと思っています。


もし、この議論について、「地頭の差」以外の結論に帰着することがあれば、プログラミング教育界は次のステップに進むのでは、と勝手に思っています。


#### 追伸
この問題は言うなれば禅問答 みたいなものなので、答えがでるとは思っていません。
この問題について考えるのが好きな人は、禅問答自体も好きだと思うので、是非、色々と調べてみて下さい。