OmniAICreator/Qiita-1.07M huggingface dataset:
ツイートを監視してSlackへ投稿する

# 事のきっかけ

HTC VIVEがほしい！
バーチャル受肉がしたい！

しかし、２０１８年６月現在
同じような考えの人が大勢いるようでどこも品薄入荷待ち状態のVive

ただ、秋葉原のPCショップやドスパラのツイートをみていると不定期で
店舗在庫を入荷しているようなのでそれをいち早くキャッチし店舗にいって
購入してやろうとおもったわけです。

# 実装
nodejsを使って行いました。

事前にTwitterAPIのトークンとSlackのトークンを取得してきます。
ここを参考にしました。
[Twitter REST APIの使い方](https://syncer.jp/Web/API/Twitter/REST_API/)
[Slack API 推奨Tokenについて](https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21)

必要なパッケージはrequestとtwitter

```
npm install request
npm install twitter
```

 ```json:package.json
{
  "name": "twtoslack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "request": "^2.87.0",
    "twitter": "^1.7.1"
  }
}
```

```javascript:app.js
const Twitter = require('twitter');
const request = require('request');

const client = new Twitter({
  consumer_key: '＊＊＊＊＊＊',
  consumer_secret: '＊＊＊＊＊＊',
  access_token_key: '＊＊＊＊＊＊',
  access_token_secret: '＊＊＊＊＊＊'
});

const params = {
    language:'ja', // 取得言語を日本語限定
    track: 'vive', // 検索ワード　vive
}
const stream = client.stream('statuses/filter', params);

stream.on('data', function(event) {
    // RTは除去
    if(event.text.slice(0,2) !== 'RT')
        post(event)
});
stream.on('error', function(err) {
    console.error(err);
});

function post(event) {
    request.post('https://slack.com/api/chat.postMessage',
        {
            form: {
                token: 'SLACK-APIのトークン',
                channel: '#general', //送信先チャンネル名
                username: event.user['name'],
                text: event.text,
            }
        });
}

```
やっていることは単純でTwitterのStreamAPI　statuses/filterを使って
全ユーザのツイートをリアルタイムで取得してRT以外のものを
Slackの指定したチャンネルにポストしています。

RTを除去しているのは同じようなツイートが大量にながれるためです。
ちょうどVIVEのワイヤレスが販売中止になった時期だったのでなかなか荒れました。

# 結果
VIVE購入の意志を決めて次の日に作って監視してたら
ちょうど某PCショップが店舗限定在庫を入荷していたので
難なくViveを入手することに成功しました。

![twtoslack.png](https://qiita-image-store.s3.amazonaws.com/0/257410/a14bbff7-5d4f-8bd3-9ae7-3f91cb5d020c.png)

次はトラッカーの方かな..

ぜひツイッターで各店舗の動向を監視してバーチャル受肉を行いましょう！
VS Code1.24の新機能 - エディタのフォントのみズームする機能

# Visual Studio Code 1.24の新機能
## エディタのフォントのみズームする機能
https://code.visualstudio.com/updates/v1_24#_font-zoom-commands

[従来のズーム機能](https://qiita.com/12345/items/64f4372fbca041e949d0#%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88%E3%82%B5%E3%82%A4%E3%82%BA%E7%B3%BB)はエディタのフォントだけではなく、一緒にアクティビティーバー、サイドバー、ステータスバーも連動してリサイズされた。

![resize.gif](https://qiita-image-store.s3.amazonaws.com/0/181011/19f80867-1d4b-9ae1-bb56-9c900f8628d2.gif)

これはこれで便利なのだが、場合によってはエディタのフォントサイズだけ変えたい場合がある。そのための機能が追加された（なお、従来の形式のズーム機能も引き続き使用できる）。

![font_resize.gif](https://qiita-image-store.s3.amazonaws.com/0/181011/da34ce67-1336-8d2f-600e-59d55894625a.gif)

が、これらの新機能はなぜかデフォルトではキーバインドされておらず、自分でキー設定を行う必要がある。

ショートカットキーの設定画面にて以下のコマンドにキーを割り当てると使用できるようになる。

- `editor.action.fontZoomIn`
- `editor.action.fontZoomOut`
- `editor.action.fontZoomReset`

![image.png](https://qiita-image-store.s3.amazonaws.com/0/181011/677cc78f-b418-b325-9e5a-69ea7db984a3.png)

うん、これは便利！
リリースノートには「プレゼンとかペア・プログラミングの時とかに便利っしょ？」って書いてあるが、まさにそのとおり！
【SQLite】【PostgreSQL】部分文字列切り出しをsubstr関数で共通化


部分文字列を切り出す関数は`substr`を使うと、PostgreSQLとSQLiteで共通のシグネチャとなる。
PostgreSQLには同じ機能を持ったSQL92準拠の構文の関数`substring`もあるが、SQLiteはバージョン3.24.0時点では`substring`を実装していない。

# 構文

```
substr(target, start [, length])
```

`target`は切り出し対象とする文字列、`start`は切り出し開始文字のインデックス（先頭の文字を1とする）、`length`は切り出す文字数。
`length`を省略すると、`start`以降末尾まで切り出す。


# 動作例

postgres (PostgreSQL 9.6.7で確認）

```sql
postgres=# SELECT substr('abcdef', 2, 3);
 substr
--------
 bcd
(1 行)


postgres=# SELECT substr('abcdef', 3);
 substr
--------
 cdef
(1 行)
```


SQLite（SQLite 3.24.0で確認）

```sql
sqlite> SELECT substr('abcdef', 2, 3);
bcd

sqlite> SELECT substr('abcdef', 3);
cdef
```
【ブロックチェーン論文まとめ③】ブロックチェーンとIoTの利益/課題/将来の方向性

#はじめに

第3回です。読み始めてからわりと普通のことしか書いてないことに気づいたので概要だけにします。

# Title
Blockchain with Internet of Things: Benefits,Challenges, and Future Directions
2018/06/05
https://www.researchgate.net/profile/Hany_Atlam/publication/325486515_Blockchain_with_Internet_of_Things_Benefits_Challenges_and_Future_Directions/links/5b111405aca2723d99792f95/Blockchain-with-Internet-of-Things-Benefits-Challenges-and-Future-Directions.pdf

#Abstruct

IoTはコンピュータと人間だけではなく、私たちを取り囲むもののほとんどと接続することを可能にしました。IoTは情報共有により我々の生活をより良いものにすることができますが、一方で、サーバー/クライアントモデルを採用しているという点で、スケーラビリティやセキュリティの面で課題もあります。
すべてのデバイスをサーバー経由で接続および認証する必要があり、単一障害点が発生します。これを解決するのが分散型のネットワークであり、それはたとえばブロックチェーンです。
この論文ではブロックチェーンとIoTの統合の概要について示し、その利点と課題、今後の研究方針について議論します。
また、ブロックチェーンとIoTの統合は新しいビジネスモデルや分散型アプリケーションのための道を切り開くと結論付けます。
問題解決能力を高め、ストレスを減らそう

## 1. はじめに
[世界一やさしい問題解決の授業](https://books.google.co.jp/books/about/%E4%B8%96%E7%95%8C%E4%B8%80%E3%82%84%E3%81%95%E3%81%97%E3%81%84%E5%95%8F%E9%A1%8C%E8%A7%A3%E6%B1%BA%E3%81%AE%E6%8E%88.html?id=ZDUpNwAACAAJ&source=kp_cover&redir_esc=y)
上記の書籍を読んで、学ばせて頂いた内容を自分なりにまとめていきます。

## 2. 問題はストレスに繋がる

仕事やプライベートなど、生きていく上で問題にぶち当たることがよくあります。

 * 処理速度が目的に達しない。
 * 引き継いだプログラムが読みづらい。
 * タバコがやめられない。
 * ダイエットがうまくいかない。
 * etc...

問題が発生すると、作業が滞ってしまったり、他の人へ迷惑をかけてしまったりで、
<font color="Red">**大きなストレス**</font>に繋がります。

しかし、問題解決能力を身に付ければ、仕事がスラスラ進み、他の人からも頼られ、
時間を有意義に使うことができます。
その結果、<font color="Red">**ストレスが激減し、人生が楽しくなる**</font>こと間違いなしです！

## 3. 問題解決するにあたって
問題解決をするには、以下のステップが必要になります。

 1. 現状把握
 2. 原因分析
 3. 計画
 4. 実行
 
中でも<font color="Red">**『原因分析』**</font>がとても重要だと考えます。

## 4. 現状把握
例を元に実際に問題解決を行ってみましょう。
現状把握では「具体的な問題点」を明確にします。

```
ここは500人の社員がいる大企業A社。
山田くんは毎月2回、業務時間を利用しJavaのセミナーを開催しているが、人がなかなか集まらない。
```

## 5. 原因分析

現状把握したあと、やみくもに行動してもダメです。
やみくもに行動して上手くいくこともありますが、エンジニアっぽくないですよね←
~~何よりここで記事が終わってしまいます。~~

社員がセミナーに行かなかった理由は様々です。

 * セミナーの存在を知らなかった。
 * 何かしらの理由でセミナーに行けなかった。
 * 何かしらの理由でセミナーに継続的に行かなかった。

<font color="Red">**問題箇所を特定し、根本的原因を特定することが重要**</font>になります。
問題箇所を特定するにあたり、<font color="Red">**分解**</font>というものが有効です。

### 5-1. 問題箇所を特定する
![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/247638/e2ffa8c8-6a22-e758-9eb2-a2f05d445ae4.png)

分解した結果をもとに、山田くんは社員全員にアンケートメールを送ってみました。

```
質問1：セミナーがあるのを知っているか？
質問2：セミナーに1回でも行ったことあるか？
質問3：継続的にセミナーに行っているか？
```

![2.PNG](https://qiita-image-store.s3.amazonaws.com/0/247638/9e2a9500-bffa-8643-3314-dd4ef2f07493.png)


<font color="Red">**セミナーは知っているが、行ったことがない社員**</font>
の割合が多いため、このグループたちに対して対策ということが分かりました！


### 5-2. 根本的原因を特定する
山田くんは根本的原因を特定するため、
<font color="Red">**セミナーは知っているが、行ったことがない社員**</font>
に対し、「なぜセミナーがあるのを知っているのに来てくれないのか？」
を調査することにしました。

![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/247638/7ee3bd7e-b91f-d2b5-e142-0b04efb52321.png)

## 6. 計画を立てて実行する
原因分析が完了すれば、あとはそれに対する計画を立て実行することになります。

![4.PNG](https://qiita-image-store.s3.amazonaws.com/0/247638/0eb9fbb7-6265-9933-7ae3-c33ecc087e56.png)

### 結果・・・
**セミナーに250人の人が集まりました！
山田くん、問題解決！**

## まとめ
 * 問題解決をするにあたり、<font color="Red">**現状把握、原因分析、計画、実行**</font>をすべき。
 がむしゃらにやっても問題解決にはならない。

 * 原因分析の際、<font color="Red">**分解**</font>を行うことで<font color="Red">**問題箇所**</font>を特定しやすくなる。
 * <font color="Red">**問題箇所**</font>を特定することで、<font color="Red">**根本的原因**</font>を特定しやすくなる。


少しでも参考になりましたら幸いです。
問題解決能力を高め、ストレスの少ない人生を送りましょう！
ファイル名に日付を付けてファイルをコピーする

## はじめに
`PowerShell`でファイルをコピーする際、バックアップを兼ねてファイル名に日付を付ける、というケースがあるとします。
その際に、自動で日付を付ける方法について考えます。

## 前提

|ツール|バージョン|
|---|---|
|PowerShell|5.1.17134.48|
|Visual Studio Code|1.24.0|

今回使うコマンドレットであれば、どのバージョンであっても動作すると思われます。

また、フォルダ構成は以下の通りです。

![ps_folder.PNG](https://qiita-image-store.s3.amazonaws.com/0/15429/fd383b3b-5a48-c91a-efc2-7158ccf81a7c.png)

`source`フォルダのファイルを、`backup`フォルダに移すものとします。

## やり方
### 日付を取得する
本日日付を取得します。

```powershell:backup.ps1
$date = Get-Date -Format "yyyyMMdd";
```

`Get-Date`コマンドレットで、本日日付を取得できます。（`DateTime`型）
`-Format`オプションを付与すると、指定した書式の文字列を取得できます。

書式指定に関しては[こちら](http://tech.guitarrapc.com/entry/2013/01/23/120129)。

### コピーする
`Copy-Item`コマンドレットを使用します。

`Copy-Item`は、単にファイルをコピーするだけでなく、ファイル名を変えてコピーする機能もあります。

`-Destination`にファイル名まで指定するといいです。
ここでは、元のファイル（`memo.txt`）の先頭に、日付を付けます。

```powershell:backup.ps1
$date = Get-Date -Format "yyyyMMdd";

$dest = Join-Path .\backup ($date + "_memo.txt")
Copy-Item -Path ".\source\memo.txt" -Destination $dest -Force
```

## 複数ファイルに対応する
基本的には、ループ内で繰り返しコピーすることとなります。

### フォルダ内のファイルを取得する
`Get-ChildItem`を使用します。

```powershell:backup.ps1
$files = Get-ChildItem -Path .\source -File;
```

今回はファイルのみで良いため、`-File`を付けています。
また、これで返されるオブジェクトはファイルの情報を持っています。

### コピーする
先ほどは、`memo.txt`のように、ファイル名を文字列で直接書いていました。
今回は、フォルダ内の項目をすべて使用するので、ループで取得します。

```powershell:backup.ps1
foreach ($file in $files) {
    $dest = Join-Path .\backup ($date + "_" + $file.Name)
    Copy-Item -Path $file.FullName -Destination $dest -Force
}
```

ファイル情報から、`Name`でファイル名、`FullName`で絶対パスを取得し、使用しています。

### コピーするファイルの条件を指定する
`Get-ChildItem`では、項目を取得する際の条件を指定できます。

詳細は[こちら](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.management/get-childitem?view=powershell-6)を見ていただくとして、一部紹介します。

### 拡張子を指定

```powershell:backup.ps1
$files = Get-ChildItem -Path .\source\*.txt -File;
```

`-Path`で、上のようにワイルドカードを使用します。

### 特定の文字から始まるファイルを除く
例えば、「ファイル名が数字から始まるファイルを除外する」場合、

```powershell:backup.ps1
$files = Get-ChildItem -Path .\source\* -File -Include *.txt -Exclude [0-9]*;
```

のように、`-Include`および`-Exclude`オプションを使って、柔軟に対処することもできます。

## 全文
```powershell:backup.ps1
$date = Get-Date -Format "yyyyMMdd";

$files = Get-ChildItem -Path .\source\* -File -Include *.txt -Exclude [0-9]*;

foreach ($file in $files) {
    $dest = Join-Path .\backup ($date + "_" + $file.Name)
    Copy-Item -Path $file.FullName -Destination $dest -Force
}
```

## 結果
### コピー元
![ps_folder_source.PNG](https://qiita-image-store.s3.amazonaws.com/0/15429/2da59670-7fff-4021-bbe2-8dc832180c38.png)

### バックアップ
![ps_folder_backup.PNG](https://qiita-image-store.s3.amazonaws.com/0/15429/b2e37926-6a43-6039-aaca-99a6a89dd3b3.png)

スクリプトで指定したように、「拡張子が`.txt`」かつ「ファイル名先頭が数字ではない」ファイルが、バックアップされています。
FlutterをBLoCパターンで爆速開発するためのLive Templete

GoogleI/O 2018に参加してFlutterセッションを見てからというもの、すっかりFlutterマンになってます。

FlutterをBLoCパターンで開発するGoogle I/Oの動画が公開されてますが
https://www.youtube.com/watch?v=RS36gBEp8OI

https://youtu.be/RS36gBEp8OI?t=1461
https://youtu.be/RS36gBEp8OI?t=1523
↑ここに注目するとライブテンプレートを使ってシュッと作るのを見て、これは良い!

となったので、作りました。

こんなイメージです。
![bloc.gif](https://qiita-image-store.s3.amazonaws.com/0/132699/bafd5b7a-7845-113f-0234-5241911d39d2.gif)

Android Studio→Preference→Live TempletesからDartを選んで、右上の＋ボタンを選択。
## Sinkを作るパターン
Abbreviationに任意の略語を入力（自分はsnk）
Templete Textに

```dart

Sink<$TYPE$> get $NAME$ => _$NAME$Controller.sink;

final _$NAME$Controller = StreamController<$TYPE$>();
```
を入力。
Templete Text下の`No applicable contexts.`となってるところのDefineを押して
Dart→otherにチェック。

## Streamを作るパターン
手順はSinkと同じです。
Templete Textに

```dart
Stream<$TYPE$> get $NAME$ => _$NAME$Subject.stream;

final _$NAME$Subject = BehaviorSubject<$TYPE$>();
```
を入力。

さぁこれであなたもBLoCパターンをエンジョイ！

現場からは以上です。
Yarnのインストールとよく使うコマンド

npmも最近は、ほぼyarnと同じような仕様・挙動になったので、npmでもいいんだと思いますが、
自分はnpmでいろいろコケたりしたあとでyarnに変えてだいぶ楽になったこともあって、いまもyarnを使っています。（猫好き）

性能的にもいまやほとんどnpmおYarnに肉薄してるらしいですが、巷の検証記事とかを読む限りは、Yarnのほうが、まだ若干早かったり、データサイズが軽かったりするっぽい。（感覚値。真面目に検証はしてないです）

コマンドもすっきりしていて楽チンな印象。
使うひとが増えてくれるかなということで、ゆるく使っている自分の認識をまとめてみます。

# Yarnのインストール

ほぼほぼここに書いてある通りですが。

https://yarnpkg.com/ja/docs/install

```bash
brew install yarn
```
Homebrewからインストールできます。

自分の場合は [n](https://github.com/tj/n) というNode.jsのバージョンを管理するツールを入れてるので

```bash
brew install yarn --without-node
```
というオプション付きでインストールしました。

## おまけ：Node.jsバージョン管理ツール「n」について

Node.jsでNode.jsのバージョンを切り替えるという不思議なツール。
下記の記事を参考してインストールしました。
Node.jsのバージョンをさくっと切り替えられるので便利です。
[nodeのバージョンをnで管理する - Qiita](https://qiita.com/bigplants/items/2d75bf552e0da4a7e822)

# install

```bash
yarn
```
または

```bash
yarn install
```

package.jsonに書かれたパッケージをよしなにインストールしてくれます。
https://yarnpkg.com/ja/docs/cli/install


# add

```bash
yarn add パッケージ名
```
任意のパッケージをインストール。
https://yarnpkg.com/ja/docs/cli/add

`--dev` オプションをつけるとpackage.jsonの`devDependencies`のほうに、オプションなしだと`dependencies`のほうにパッケージ名とバージョンが追記されます。

つくるものはWebサイトとかが多いので、jQueryみたいなサイトの動作に直接必要なものはオプション無しでインストールして、gulpとか開発のためのツールは`--dev`オプションつけてインストールしてますが、ただWebサイト作ってる分には全部オプション無しとかでも、ほぼ実害はないはず。。（自分は気持ち悪いので自分なりの解釈で分けていますが）

参考: ちゃんと使い分けてる? dependenciesいろいろ。 - Qiita
https://qiita.com/cognitom/items/acc3ffcbca4c56cf2b95

# outdated

```bash
yarn outdated
```
巷の最新バージョンと、現在インストールされているバージョンを比べてふるいものをリストアップして表示してくれます。

こんな感じです。

<img width="833" alt="Screen Shot 2018-06-08 at 7.46.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/3374/3968dc51-ff5e-4241-f355-3de25c3ea6df.png">

赤い色で表示されたパッケージはメジャーバージョンアップなど大きな仕様変更が入っているもので、後述の`upgrade`コマンドを実行してもバージョンアップされません。

# upgrade

```bash
yarn upgrade
```
古いバージョンのパッケージを上書きしてくれます。

```bash
yarn upgrade --latest
```
というように、`--latest`オプションをつけると、前述の`outdated`コマンドで赤い文字で表示されたメジャーバージョンアップも反映され、package.jsonに記載されたバージョン番号も最新のものに書き換えられます。
（動作になにかしら影響が出るので可能性が高いので、`--latest`オプションは、その辺り注意が必要）

# remove

```bash
yarn remove パッケージ名
```

パッケージをアンインストール

# run
```bash
yarn run コマンド名
```
または

```bash
yarn コマンド名
```

package.jsonの`scripts`っていうところで定義したコマンドを実行できます。
いわゆる npm scripts というやつで、gulpとかつかわずとも簡単な処理はこれで作れます。

npm-scriptsについて - Qiita
https://qiita.com/axross/items/a2a0d148e40b66074858

yarnの機能というよりはnpmの機能かなという気もしますが、厳密にはyarnの`run`はnpmのそれとちょっと違うらしいです。

yarn run が便利 - Qiita
https://qiita.com/y13i/items/27d39edac23b7a867935
要件定義する上で意識すること

#今回読んだ本
[はじめよう！ 要件定義 ～ビギナーからベテランまで](https://www.amazon.co.jp/%E3%81%AF%E3%81%98%E3%82%81%E3%82%88%E3%81%86%EF%BC%81-%E8%A6%81%E4%BB%B6%E5%AE%9A%E7%BE%A9-%EF%BD%9E%E3%83%93%E3%82%AE%E3%83%8A%E3%83%BC%E3%81%8B%E3%82%89%E3%83%99%E3%83%86%E3%83%A9%E3%83%B3%E3%81%BE%E3%81%A7-%E7%BE%BD%E7%94%9F%E7%AB%A0%E6%B4%8B-ebook/dp/B00WHUP7UE/ref=sr_1_1?s=digital-text&ie=UTF8&qid=1528293114&sr=1-1&keywords=%E3%81%AF%E3%81%98%E3%82%81%E3%82%88%E3%81%86%EF%BC%81+%E8%A6%81%E4%BB%B6%E5%AE%9A%E7%BE%A9+%EF%BD%9E%E3%83%93%E3%82%AE%E3%83%8A%E3%83%BC%E3%81%8B%E3%82%89%E3%83%99%E3%83%86%E3%83%A9%E3%83%B3%E3%81%BE%E3%81%A7)

#「要件定義」とは
そもそも「要件定義」とはなにか。
前提部分から考え直してみると、「要件定義」に対する考え方が少しずつ明確になっていく。

##「要件」とは
「**注文(オーダー)**」と考えるとわかりやすい。
つまり、「**作って欲しい人が、作る人に出す、依頼事項(リクエスト)**」。

##それを踏まえると...
「**依頼事項を明確に定める(定義する)**」ことこそが、「要件定義」。

##なぜ要件定義をするのか
納品するためには、「**作ってほしい人と作る人の間に合意事項を形成する必要**」があるから。
(これがずれていると、トラブルになる可能性も)

#「要件」を整理するために...
##「要望」と「要求」
「こんなことがしたい」「こんなことができたら」という思いこそが「**要望**」。
その要望を言葉にしたものが「**要求**」。

##「要求」を検討する
出来るか出来ないかという「可否判断」。
その判断だけでなく、「代替案」も検討する。

###「代替案」
「不可能の場合に提案するもの」というイメージがあるが、「更に良い方法がある」ときに出すものでもある。

#「要件定義」を行う、その前に
##「企画」を確認する
作るからには、そこには何かしらの「企画意図」がある。
その意図から外れないようなソフトウェアを作らないといけない。

##「全体像」を描く
「システム」を中心に、「利用者」を配置した図を書く。
利用者それぞれに、「そのソフトウェアを使って行うこと」を書く。
そうすることで、「システム」の利用者と利用意図の概略を整理できる。

##利用者の「行動シナリオ」
いわゆる「業務フロー」を整理することで、以下の内容を明確にする。

- 「ソフトウェアを利用するタイミング」
- 「ソフトウェアを利用する理由」
- 「ソフトウェアを利用することで具体的に達成する仕事」

###データのINPUTとOUTPUT
システムの利用箇所も踏まえた「行動シナリオ」を整理する際には、
データのINPUTとOUTPUTが必ず明確になるように検討する。
またデータの受け渡しだけでなく、その「保管場所」を意識することも必要。

#実際の要件定義
##「UI」を考える
###UIを構成する要素
以下の3つの要素で構成される。

- データ項目
- 操作項目
- レイアウト

###画面のラフイメージを描く
ラフイメージを描くことで...

- 「データ項目」(値の表示項目や、入力項目)を設計できる
- 「操作項目」(ボタンなど、操作するもの)を設計できる

###「導線(画面遷移)」を考える
レイアウトと画面遷移のイメージができたら、そこに「イベントトリガー」を書く。
この「イベントトリガー」とは、「ボタンを押す」などの「ユーザの操作」を指す。

##「機能」を考える
###画面遷移図から機能を洗い出す
- 「出力」を決める
    - 遷移先画面を考えて、渡すべき「出力」を考える
    - すなわちソフトウェアの「成果物」
- 「入力」を決める
    - 遷移元画面を元に「入力」を考える

#個人的なポイント
##ドキュメントを書くことの重要さ
作り込まなくてもよいので、何かしらドキュメント化して整理することが必要だと感じた。
(頭の中で整理するのは限界がある。アウトプットした方が整理しやすい。)

特に「**画面遷移図**」。
設計するうえで、ラフで良いので作った方が「システムの処理の流れ」や「ユーザの操作の流れ」が明確になる。



#参考URL
[Part1　今こそ「基本設計」のスキルを見直す](http://tech.nikkeibp.co.jp/it/article/lecture/20070702/276409/?ST=selfup)
ダークウェブにハニーポット

#はじめに
ダークウェブにWOWHoneypotを公開し、Tor経由でアクセスがあるか見てみます。
ダークウェブとは何ぞ？という方は、ググってみてください。

#構築（Torのインストール）
UbuntuにTorをインストールする手順は[Debian/Ubuntu Instructions](https://www.torproject.org/docs/debian.html.en)に記載されていますが、必要なコマンドだけ記載します。
まず、リポジトリにtorprojectを追加します。

```/etc/apt/sources.list
deb https://deb.torproject.org/torproject.org stretch main
deb-src https://deb.torproject.org/torproject.org stretch main
```

gpg keyを使って署名してあげます。
最後にいつものインストールコマンドでtorが入ります。

```terminal..
$ gpg --keyserver keys.gnupg.net --recv A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89
$ gpg --export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | sudo apt-key add -
$ apt update
$ apt install tor deb.torproject.org-keyring
```

#構築（Torの設定）
手順は[Configuring Onion Services for Tor](https://www.torproject.org/docs/tor-onion-service)に記載されています。
ここではWebページを最低限公開するための設定を記載します。
/etc/tor/torrc(設定ファイル)の71、72行目のコメントを外し、Webサーバで待ち受ける出来ように有効化します。
デフォルトは、HiddenServicePort 80 127.0.0.1:80 となっています。
WoWHoneypotは8080で待ち受けているので、待ち受けポートを変える必要があります。
ただ、この設定だとWoWHoneypotにとって送信元は127.0.0.1となってしまうので注意が必要です。

```/etc/tor/torrc
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80 127.0.0.1:8080
```

torを起動すると、/var/lib/tor/hidden_service/hostnameにホスト名が割り当てられます。

```
$ sudo service tor start
$ cat /var/lib/tor/hidden_service/hostname
XXXXXXXXXXX.onion
```

無事に接続できました。
![alt](https://qiita-image-store.s3.amazonaws.com/0/254131/89a90acc-d97b-9531-9df0-d28c9fbe734f.jpeg)

#最後に
onionドメインが公開されてる以外に、簡単にonionドメインを発見することは難しいと思います。
簡単にアクセスできないところにハニーポットを置くのは、あまり意味がないと思いますが、アクセスがあるか確認してみたいと思います。
ServiceWorker のインストールが終わるまで初期化を遅延する & ServiceWorker の更新をユーザーに通知する

## やりたいこと

SEO を気にしないモダンブラウザのウェブアプリでは、初回ロード時にServiceWorker の初期化前に始まったリクエストが、タイミング次第でキャッシュが構築されたりされなかったりする問題がある。同じ動作になることを保証するために、 ServiceWorker の初期化が終わってからJSの読み込みなどを行いたい。

ついでに、裏側でServiceWorkerの更新があったらユーザーにモーダルなどで通知したい。

前提として、生存時間が長い富豪的なSPAを想定している。

## コード

あらゆるJS含むリソースの初期化が前提に出来ないので、フレームワークを使わず、HTMLのインライン一筆書きした。

- /sw.js - serviceWorker
- /main.js - 本来読み込みたいコード


es modules がないブラウザは nomodule を実行して警告する。

```html
<html>

<head>
  <title>PWA</title>
  <meta charset="utf8">
</head>

<body>
  <div class=root>
    Loading...
  </div>
  <script nomodule type=text/javascript>
document.body.innerHTML = "Please use modern browser";
  </script>

  <script type=module>
function setupBrowserFS() {
  return new Promise(resolve => {
    BrowserFS.configure({ fs: "IndexedDB", options: {} }, err => {
      if (err) {
        throw err
      }
      resolve()
    })
  })
}

async function setupServiceWorker() {
  if (navigator.serviceWorker == null) {
    throw new Error('Your browser can not use serviceWorker')
  }

  let installed = !!navigator.serviceWorker.controller
  navigator.serviceWorker.addEventListener('controllerchange', () => {
    if (installed) {
      const modal = document.createElement('div')
      modal.innerHTML = `
        <div style='position: absolute; outline: 1px solid black; right: 10px; bottom: 10px; width: 350px; height: 80px'>
          <div>New version available!</div>
          <span>It will be applied from the next</span> - <button onclick="location.reload()">Reload</button>
        </div>
      `
      document.body.appendChild(modal)
    }
  });

  const reg = await navigator.serviceWorker.register('/sw.js');
  await navigator.serviceWorker.ready
  installed = true

  setInterval(() => {
    reg.update();
  }, 60 * 1000);
}

;(async () => {
  const el = document.querySelector('.root')
  try {
    // SW
    el.innerHTML = 'Checking service worker ...'
    await setupServiceWorker()

    // Run
    el.innerHTML = 'Loading...'
    await import('/main.js')
  } catch (e) {
    el.innerHTML = 'Something wrong: ' + e.message
  }
})()
  </script>
</body>

</html>
```

このコードでは、60s に一回 service worker の更新確認を行っている。更新があったかどうかのヘッダのチェックだけなので軽いはずだが、なんだかんだでリクエスト走るし、なんだかんだでリロードされると思うので、実際は15分に1回ぐらいでいいと思う。

気をつける点は、この index.html を offline cache に突っ込んでる場合、このコードの変更自体が適用されるのが次回の更新、更新が確認できるのが次の次になることだろうか。
Railsプロジェクト新規作成時に毎回やること

- gemの導入
    - pry-rails
    - config
- タイムゾーンをJSTに

```config/application.rb
    config.time_zone = 'Tokyo'
    config.active_record.default_timezone = :local
```
- productionのログレベルを変更

```config/environments/production.rb
config.log_level = :warn
```

- not foundのログを別ファイルに出すようにする

```config/route.rb
    # Not Foundのときログにスタックトレースを残さないようにするため
    # https://stackoverflow.com/a/39289253/5209556
    match '*any' => 'not_found#not_found', via: [:get, :post, :delete, :options, :put, :patch]
```

```app/controllers/not_found_controller.rb
  class NotFoundController < ApplicationController
    # Not Foundだけ別ファイルにログを出す
    NotFoundLogger = Logger.new(Rails.root.join('log', 'not_found.log'))

    # Not Foundのときログにスタックトレースを残さないようにするため
    # https://stackoverflow.com/a/39289253/5209556
    def not_found
      NotFoundLogger.error(request.fullpath)
      render plain: '404 Not Found', status: :not_found
    end
  end
```

- jbuilderのpartialのログが大量に出て邪魔なので、出さないようにする

```config/application.rb
    # jbuilderのpartialのログが大量に出て邪魔なので、出さないようにする
    config.action_view.logger = nil
```
UnityでJavaをインストールしたけどJDKが見つからないエラー

Unity ver 2018.1.3.f1

UnityでAndroidのコンパイルをしたい。

JDKは
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
からダウンロードしインストールした。

その上でJavaをインストールしたけどJDKが見つからならしく後記のエラーが出た。

対処法はmenuから[Unity]→[Preference]でUnity Preferenceから[External tools]を選びAndroidのSDKにJava SDKのフォルダーを指定する。

フォルダーはmacなら
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home
など
<HR>

UnityException: Unable to find suitable JDK installation. Please make sure you have a suitable JDK installation. Android development requires at least JDK 8 (1.8), having JRE only is not enough.  The latest JDK can be obtained from the Oracle website: 
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
UnityEditor.Android.AndroidJavaTools.LocateJDKHome (Boolean allowDialogs)
UnityEditor.Android.AndroidJavaTools.get_javaPath ()
UnityEditor.Android.AndroidSDKTools.RunCommand (System.String[] sdkToolCommand, UnityEditor.Android.WaitingForProcessToExit waitingForProcessToExit, System.String errorMsg)
UnityEditor.Android.AndroidSDKTools.GetSDKBuildToolsDir ()
UnityEditor.Android.AndroidSDKTools.UpdateToolsDirectories ()
UnityEditor.Android.AndroidSDKTools..ctor (System.String sdkRoot)
UnityEditor.Android.AndroidSDKTools.GetInstance ()
UnityEditor.Android.AndroidSDKTools.GetInstanceOrThrowException ()
UnityEditor.Android.ADB.StartServer (UnityEditor.Android.WaitingForProcessToExit waitingForProcessToExit)
UnityEditor.Android.ADB.Run (System.String[] command, UnityEditor.Android.WaitingForProcessToExit waitingForProcessToExit, System.String errorMsg)
UnityEditor.Android.AndroidDeploymentTargetsExtension.GetKnownTargets (UnityEditor.ProgressHandler progressHandler)
UnityEditor.DeploymentTargets.DeploymentTargetManager.GetKnownTargets (BuildTargetGroup targetGroup, BuildTarget buildTarget) (at /Users/builduser/buildslave/unity/build/Editor/Mono/DeploymentTargets/DeploymentTargetManager.cs:58)
UnityEditor.Android.AndroidBuildWindowExtension+<SpawnFetchTargetsThread>c__AnonStorey0.<>m__0 ()
UnityEditor.Android.<SpawnFetchTargetsThread>c__AnonStorey0:<>m__0()
我々がStack Overflowを読むとき、Stack Overflowは我々から何を読み取るのか？

###### (An English translation is available [here](https://dev.to/tomoyukiaota/when-we-read-stack-overflow-what-does-stack-overflow-read-from-us-3b1i).)

# TL;DR
Stack Overflowは、ユーザーから信用を得るために、ユーザーの活動から収集した個人的な情報を開示しています（[Personalized Prediction Data][]）。それをダウンロードして見てみたところ、{技術関連のタグ : 値}というkey-value pairがあり、その値の大きさは、私の各技術領域を数値化したものとして納得できるような内容になっていました。Stack Overflowは現時点の私の技術領域をよく分かっているようであると思いました。

# 前置き

>アメリカではあなたはテレビを見る(watch)。
ソビエトロシアでは、テレビがあなたを監視(watch)する！ 
In America, you watch television. 
In Soviet Russia, television watches you!

この引用は、[ロシア的倒置法](https://ja.wikipedia.org/wiki/%E3%83%AD%E3%82%B7%E3%82%A2%E7%9A%84%E5%80%92%E7%BD%AE%E6%B3%95)というものです。
ソビエトは崩壊しましたが、現代では、FacebookなどのWebサービスを利用する際は、我々がコンテンツをwatchすると同時に、企業も我々をwatchしているかのようです。

企業がユーザーの個人情報を収集する際には、例えば「収集する情報のカテゴリ」「収集した情報の使用目的」などをユーザーに周知しています。これは（少なくとも日本では）個人情報保護法に基づく措置として必要になるためです。

また、単なる法律の話だけではなく、ユーザーに信用してもらうためにも、情報収集の周知は必要になります。この「信用」を得るために、収集した情報を開示してしまおう、という企業があります。開示してしまえば、どのような情報を持っているかが一目瞭然になるためです。

Stack Overflowは、[Personalized Prediction Data][]をユーザーに開示しています。ユーザーはこれをダウンロードして、どんな情報を持っているのか見てみることができます。この記事は、[Personalized Prediction Data][]の中身をのぞいてみた、というものです。

# Personalized Prediction Dataのダウンロード・分析
ダウンロードするためには、Stack Exchangeにログインした上で、[Personalized Prediction Data][]のページにある"Start download"という青いボタンをクリックします。なお、Stack Exchangeにログインしていないと、個人的な情報に関する箇所がnullで埋められたファイルになります。
ダウンロードしたファイルは、以下の構成のJSONファイルになります。（私の場合はこうでしたが、ユーザーごとに一部異なるかもしれません。）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/185010/35bd1dfc-e9b0-1f66-db0b-e7fffd6a0e8d.png)
構成についてのドキュメンテーションがないので、推測で色々なデータを見てみました。
特に面白いと思ったのは、root/Data/TagViewsに入っている{ tag: value }形式のデータです。これは、Stack Overflowのtagとそのtagに対する値が入ったkey-value pairであり、例えば、

```
TagViews : {
  c++: 440,
  javascript: 183,
  ...
}
```

などと入っています。トップ20についてグラフを作成すると、次のようになりました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/185010/7c7ba3a1-c820-bfd8-e07c-ec1807bc644f.png)
この傾向は、私の感覚に合致しています。Stack Overflowは、現時点の私の技術領域を良く分かっているようです。

詳細は、[GitHubのrepository](https://github.com/TomoyukiAota/stack_exchange_personalized_prediction_data)にJupyter notebookを置いたので、それを見てみると良いと思います。
下のバッジをクリックすると、Binderで実行できます。
[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/TomoyukiAota/stack_exchange_personalized_prediction_data/master)

# おわりに

他の企業も収集した情報を開示してくれれば面白いのに、と思いました。


[Personalized Prediction Data]:https://meta.stackexchange.com/users/prediction-data
fish shellでSnapアプリケーションがアプリ一覧に現れないときの対策

例によって防備録。


## Ubuntu 18.04 LTSからSnapがインテグレートされた
これまでもSnapは使えたが、[Ubuntu 18.04では最初から有効になっている](http://gihyo.jp/admin/serial/01/ubuntu-recipe/0515)のに加えて、[command-not-foundでsnapがサポートされた](http://gihyo.jp/admin/serial/01/ubuntu-recipe/0516?page=2#sec3)ことでいい感じになっている

```
todoroki@todoroki-VJZ13B ~> blender

Command 'blender' not found, but can be installed with:

sudo snap install blender
sudo apt  install blender

See 'snap info blender' for additional versions.
```

ここで「snapがあるならそれで行こう」と思って `sudo snap install blender` をする

## で、アプリケーションはいずこ…

インストールが終わって起動してみようと思い、Superキーを押して検索してみる　も　`blender` の名前はどこにもない。
「インストール失敗したのかな？」と考えてもう一度インストールを実行してみるも

```
snap "blender" is already installed, see "snap refresh --help"
```

と言われてしまう。
軽く調べると「Waylandのバグ」とか出てくる(※以前のバージョンで解決済み)のでログアウトしてXorgでログインし直すも特に回復しない。はて。

## snapの.desktopファイルは違うディレクトリにある

もっとよく検索していくと同じような症状を訴えるzshユーザーに出会う。どうやらSnapのデスクトップファイルは他のアプリケーションと異なる場所にあるようで、そのパスがBash以外のシェルだと通っていないためapplicationsに `blender` が表示されなかったということなのね。
[Debian でログインシェルをzshにしている人が snappy を使う場合の注意](https://www.hitsumabushi.org/blog/2018/04/11/1058.html)

上のリンクでは `/etc/profile.d/apps-bin-path.sh` の内容を`zprofile`に移しているが、それはちょっと感があるので別の方法でやってみる

## fish shellで `/etc/profile` を読み込む

`/etc/profile.d/apps-bin-path.sh` 以外にも `/etc/profile.d/` 以下に大事な設定があるかもしれないわけで、全て読み込むことで対応してみる。

### bassのインストール
```
$ fisher edc/bass
```
これでBashスクリプトをFishで読めるようになる。

### `./.config/fish/config.fish` 編集

```fish
# ↓これを追加する
bass source /etc/profile

# ！問題があったらこっちにするといいかも(/etc/profile.d以下だけ読み込み)
if test -d /etc/profile.d
   for i in /etc/profile.d/*.sh
     bass source $i
   end
end
```

これで再ログインしてエラーが何も出ていなければsnapアプリケーションがちゃんと表示されるようになるはず。

## おまけ：snap雑感
Slackとかgnome-calculatorみたいな独自UI！！！！って感じのやつは違和感なく使える。
特にElectron製アプリケーションはいいのでは。（ただElectronアプリってもともとそんなに依存とかなさそうだしsnapの旨味があるかと言われると微妙な気も）

逆にInkscapeとかはGtkのテーマが適用されないので見た目がマッチしなくて(古き良きむきだしGtkのUI)微妙でしたね。。
グローバルのテーマを拾えない問題についてはSnapもFlatpakもこまっているっぽいのでどうにかなるといいね

Gtk+4とかだとやりやすくなるのかな？期待しましょう
「RStudioで始めるRプログラム入門」のメモ（3,4章）

[RStudioではじめるRプログラミング入門/Garrett Grolemund他]( https://www.amazon.co.jp/dp/4873117151/ref=cm_sw_r_tw_dp_U_x_q2-fBbTC95WX5)を読み始めました。詰まったところや、気になったところをメモしていきます。


前回：[「RStudioで始めるRプログラム入門」のメモ（１，２章）](https://qiita.com/ladder80/items/23256f9c93523b4bb405)

#3章：Rのオブジェクト
##型
例えば、普通に”1”という数字の型を判定すると、

```r
> typeof(1)
[1] "double"
```
となり、doubleと判定されるが、コロンを使って配列を作ると

```r
> typeof(1:4)
[1] "integer"
```
となり、integerとして認識されている。読み返してみるとP7に
>コロン演算子は、2つの整数の間に含まれるすべての整数を返します。

と書いてあった。
また、前章で使ったseq関数で同じ数列を再現して判定すると、

```r
> s = seq(1, 4, by=1)
> typeof(s)
[1] "double"
```
という結果になった。

##クラス
(2,2,3)の3次元arrayを作ると、そのクラスは

```r
> ar <- array(c(11:14, 21:24, 31:34), dim=c(2, 2, 3))
> class(ar)
[1] "array"
```
となる。
次にこれを(3,4)の2次元配列にすると

```r
> ar <- array(c(11:14, 21:24, 31:34), dim=c(3,4))
> class(ar)
[1] "matrix"
```
となり、行列として扱われる。

##リスト
リストの中にはリストを入れられる。教科書では2次元配列しか作っていないが、3次元配列も以下のように作れる。

```r
> list <- list(100:110, "R", list(TRUE, FALSE, list(1:5)))
> list
[[1]]
 [1] 100 101 102 103 104 105 106 107 108 109 110

[[2]]
[1] "R"

[[3]]
[[3]][[1]]
[1] TRUE

[[3]][[2]]
[1] FALSE

[[3]][[3]]
[[3]][[3]][[1]]
[1] 1 2 3 4 5
```

リストで行列を作るのか、データフレームを使うのかは時と場合によってちゃんと考えなきゃいけない。

#4章：Rの記法
##添字の始点
Pythonなどは添字の始点が０だが、Rはデータセットに限らず多次元配列もすべて１から始まる。確かにこっちのほうが数学的な操作は直感的でやりやすいかもしれない（主観）。

##shuffle関数について
4.3でShuffle関数なるもの

```r
shuffle <- function(cards){
random <- sample(1:52, size=52)
cards[random, ]
}
```
を作るが、この関数を実行しても元のデータが書き換わることはない。当たり前だけど。
実装例：Translating and Segmenting Multimodal Medical Volumes with Cycle- and Shape-Consistency Generative Adversarial Network

#はじめに
近々CVPR2018で発表される以下の論文
Translating and Segmenting Multimodal Medical Volumes with Cycle- and Shape-Consistency Generative Adversarial Network
https://arxiv.org/abs/1802.09655
を勝手に実装しました。

コードはこちらにupしました
https://github.com/masataka46/Cycle-Shape-GAN-chainer

論文の解説はこちらにupしました
https://qiita.com/masataka46/items/fecb526e7b223585db6a

#実装のポイント
Cycle-GANとの比較で言うと、生成された画像に対してSegmentを行うSegmentorを加えただけ。

#問題設定
ネット上でセグメントされたannotation付きのMRIやCTが見つからなかったため、CityScapeのデータセットを使って以下のような問題設定にした

1.   CityScapeのデータのうち、夏っぽくて快晴の画像３００枚程度をX、秋っぽくて雨または曇りの画像３００枚程度をYとして、XからY、YからXを生成させる
2.   XからYを生成させる$G_Y$は画像を秋でどんよりしたものに変換させることを目指し、YからXを生成させる$G_X$は画像を夏で晴れやかな天気に変換させることを目指す
3.   同時にshape consistencyの効果として、変換させた画像の幾何学的な位置関係が元の画像と同じであることを目指す

#実験と結果
Shape consistencyの効果を見るために、

1. CityScapeのデータとcycle-GAN的なモデル
2. 上記モデルにSegmentorを加えたモデル

の２つで比較実験を行なった。

まず 1. のcycle-GANモデルでの10epoch。
![cycle_gan_10epoch.png](https://qiita-image-store.s3.amazonaws.com/0/116706/a0afb672-a734-02b1-7647-baba342aad76.png)
左端がX、その右がXからYの生成、その右が更にそれからXの生成。

左から4列目がY、その右がYからXの生成、その右が更にそれからYの生成。

一方で2. のcycle-shape-GANでの10epoch
![cycle_shape_gan_10epoch.png](https://qiita-image-store.s3.amazonaws.com/0/116706/d02267a0-ca27-b835-dace-e89209a48548.png)

たかだか10epochでもどんよりが晴れやかに、晴れやかがどんよりに変換されてる。さらに元の幾何学的関係も維持されている。

タスクが簡単過ぎたかな〜。
【A Tour of Go】Basics/More types: structs, slices, and maps. /Exercise: Fibonacci closure (26/27)

A Tour of Go の Exercise を実施したときのメモ。

* Go では case に式がかけるのについ癖で `else if` を使ってしまう。
* あと、余計な初期化をかいてしまうのも会社員時代の名残り
* Exercise ではないが、結果は答えと一緒に出力するようにした

```exercise-fibonacci-closure.go
package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	count := 0
	n1 := 0
	n2 := 0
	return func() int {
		ret := 0
		if count == 0 {
			ret = 0
			n1 = 0
			n2 = 0
		} else if count == 1 {
			ret = 1
			n1 = 0
			n2 = 1
		} else {
			ret = n1 + n2
			n1 = n2
			n2 = ret
		}
		count++
		return ret
	}
}

func main() {
	f := fibonacci()
	ans := []int {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946}
	for _, v := range ans {
		fmt.Println(f(), v)
	}
}
```
* Go 言語っぽくしたつもり
* 複数の変数代入を `n1, n2 = n2, n1 + n2`のように記述できるが、慣れないので気持悪い。コンパイラの違いでバグにならないか心配になってしまう。

```exercise-fibonacci-closure.go
package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	count := 0
	n1 := 0
	n2 := 1
	return func() int {
		ret := 0
		switch {
		case count == 0:
			ret = 0
		case count == 1:
			ret = 1
		default:
			n1, n2 = n2, n1 + n2
			ret = n2
		}
		count++
		return ret
	}
}

func main() {
	f := fibonacci()
	ans := []int {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946}
	for _, v := range ans {
		fmt.Println(f(), v)
	}
}
```
【A Tour of Go】 Basics/More types: structs, slices, and maps./Exercise: Maps (23/27)

A Tour of Go の Exercise を実施したときのメモ。

* ロジックとしては他の言語とそれほど違いはない。
* キーの存在チェックが1回の呼び出しでできるところが便利かも。
    * 他の言語だと haskey などの存在チェックメソッドを呼び出してから値を取得する。

```exercise-maps.go
package main

import (
	"golang.org/x/tour/wc"
	"strings"
)

func WordCount(s string) map[string]int {
	m := make(map[string]int)
	for _,x := range strings.Fields(s) {
		v, ok := m[x]
		if !ok {
			v = 0
		}
		m[x] = v + 1
	}
	return m
}

func main() {
	wc.Test(WordCount)
}
```
Vueライフサイクルの盲点、computedの一発目の発火はmountedより早い



# TL;DR
https://jp.vuejs.org/v2/guide/instance.html#ライフサイクルダイアグラム
よく出てくるこの図ですが、computedって乗ってないんですよね。


さて、もうタイトルで語りたいこと90%くらい語ってるんですが、
要するにcomputedが最初に発火するとき、mountedまでに用意されない
ものを参照するとエラー吐くよ、という話です。

普通は遭遇しないと思いますが、一応…
(というかそういう事態に遭遇する時点で、VueをVueらしく使ってない可能性が高いです。)

# 例

例としてDOMのエレメントを$refを使って参照してみましょう。

## template

```vue
<div id="app">
  <div ref="target">test!!</div>
  <div>{{ text }}</div>
</div>
```

## js

```js
var vm = new Vue({
  el: "#app",
  created() {
    console.log('----- created -----')
    console.log(this.$refs)
  },
  mounted() {
    console.log('----- mounted -----')
    console.log(this.$refs)
  },
  computed: {
    text() {
      console.log('----- computed -----')
      console.log(this.$refs)
    }
  }
});
```

## 結果

```
----- created -----
{}
----- computed -----
{}
----- mounted -----
{target: div}
```

computedが最初に実行されたとき、まだ$refの中身は空っぽですね。

## あとがき

例として無理やり使いましたが、computedの中で$refはあまり使うべきではないです。
最初の発火時にDOMを発見できないですし、その後もリアクティブに発火しないですし…

そもそもcomputed内に限らず、公式でも[あんまり$refつかうなよー](https://jp.vuejs.org/v2/guide/components-edge-cases.html#子コンポーネントインスタンスと子要素へのアクセス)、ってやんわり言ってますしね。
> $refsはコンポーネントの描画後にデータが反映されるだけで、リアクティブではありません。子コンポーネントへの直接操作のための、退避用ハッチのような意味合いです(テンプレート内または算出プロパティから$refsにアクセスするのは避けるべきです)。
[Rails] 特定の名前のカラムがあったら自動で何かする

例
name というカラムがあったら friendly_id で使う。

```rb:/app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  def self.inherited(child)
    super

    if child.column_names.include? 'name'
      child.extend FriendlyId
      child.friendly_id :name
    end
  end
end
```
Jupyter Notebook - インストール and 設定 -

開発を分かりやすくやりたいと思ってた時に
Jupyter Notebookを見つけたのでまずはインストール。
## 環境
PC: High Sierra 10.13.4
VM: CentOS 7 minimal

## インストール
```
$ curl https://repo.continuum.io/archive/Anaconda3-4.3.1-Linux-x86_64.sh -O
```
このあと
$ sh Anaconda3-4.3.1-Linux-x86_64.sh
で終わりかと思ったら、なんかインストールされてなさそうな挙動、、、
調べたら、bzip2 がないとインストール上手くいかないみたい。
(minimal の人コレ入れないとだそうです！)


```
$ sudo yum install bzip2 -y
$ sh Anaconda3-4.3.1-Linux-x86_64.sh 
```
今度こそ。

```
$ python --version
Python 2.7.5
```
あれ入ってない？
そうか再起動か。

```
$ reboot
```
無事入りました！

```
$ python --version
Python 3.6.0 :: Anaconda 4.3.1 (64-bit)
$ jupyter --version
4.2.1
```
でもまだ起動できない、、、。
設定か。。。

## 設定
```
#コンフィグファイル作ってくれる。なんと便利。
$ jupyter notebook --generate-config
```

```
#ポートの設定
/8888
#c.NotebookApp.port = 8888
c.NotebookApp.port = 8888

#パスワード必要なら(下記参照しました。ありがとうございます。)
/passw
c.NotebookApp.password = 'ちょめちょめ'

#どこからでもOK
/App.ip
#c.NotebookApp.ip = 'localhost'
c.NotebookApp.ip = '0.0.0.0'

#起動後にブラウザで開くかどうか
/App.open
#c.NotebookApp.open_browser = True
c.NotebookApp.open_browser = False
```
パスワードの設定方法はココを参考にさせていただきました。
↓↓↓
[Jupyter notebookのパスワード](https://qiita.com/SaitoTsutomu/items/aee41edf1a990cad5be6)

これでMac側でみれました。
ごちそうさまです。

## 感想
それにしても、簡単に構築できんかな。
VM新規で作った時に設定すること忘れそう。
Ansible化でもするか。。。
【2018年6月】忙しい人のためのPower BI Desktop Update

忙しい人のためのPower BI Desktop Update
2018年6月アップデート情報のぼく的まとめです。

![図1.png](https://qiita-image-store.s3.amazonaws.com/0/165789/f992b2ac-eb7c-b2da-9e8a-67c19077efb9.png)




# 注意事項

- このまとめは[PowerBI Blog(公式)](https://powerbi.microsoft.com/ja-jp/blog/)の内容を紹介しています
- 内容は、個人的に解釈や試行を加えています
- 英語が不自由なので、訳や意味などを間違えている可能性があります
- アップデート内容の網羅はしません。原則、「Reporting」と「Analytics」、一部の「Custom Visual」に絞ります
- **作成したところから順次公開します。**途中で挫折してたらスミマセン・・・(´・ω・｀)


# Reporting

## ハイコントラストへの対応
<font color="#999999"><i>High contrast support for reports</i></font>

PowerBIレポート画面が、winodwsのハイコントラストモードに対応しましたよ。というお話。
主に通常配色だとまぶしすぎて見づらい方向けの機能ですね。

<img src="https://qiita-image-store.s3.amazonaws.com/0/165789/160a4cfe-01f6-ec68-4844-ad07fed91907.png" width=700>

この配色を見ると、某 METAL GEAR S〇LID(初代)を思い出してしまうのは私だけ？
 

## ドーナッツチャートの半径制御
<font color="#999999"><i>Donut radius control</i></font>
ドーナッツチャートの内側の半径が自由に制御できるようになりました～。
Excelではおなじみですけどね。


<img src="https://qiita-image-store.s3.amazonaws.com/0/165789/3ef06d37-8042-213f-934e-31929e4f8772.jpeg" width=700>



## 円グラフ・ゴーナッツチャートのラベル位置変更
<font color="#999999"><i>Pie & donut detail labels position</i></font>
円グラフ・ドーナッツチャートのラベルを内側などに位置変更できるようになりました～。
これ、困ってたんですよね。なぜ今までなかったのか。

<img src="https://qiita-image-store.s3.amazonaws.com/0/165789/a36fd586-3bdf-9b93-f104-92412e9f0086.jpeg" width=700>




## 複合チャートのラベル調整
<font color="#999999"><i>Format data labels separately for each measure in a combo chart</i></font>
複合チャートのラベルを個別に調整できるようになりました～。
こちらも特に説明不要ですね。棒グラフと折れ線グラフ、それぞれ任意にラベル編集できます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/165789/237e220a-3bfc-58cc-d809-39c0427e9766.jpeg" width=700>


## モバイル用レイアウトの改善
<font color="#999999"><i>Longer phone reports</i></font>
モバイル用のレイアウトの行が縦に長くなったみたいですね。

<img src="https://qiita-image-store.s3.amazonaws.com/0/165789/2ef8309a-3058-0029-ff09-370da06edd5f.jpeg" width=300>



# Modeling

## データビューでのフィルタ・ソート
<font color="#999999"><i>Filtering and sorting in data view</i></font>
データビュー画面でフィルターなどによるデータチェックができるようになりました。
なにげに使いたいときがあるので、便利です。

<img src="https://qiita-image-store.s3.amazonaws.com/0/165789/c879fced-0b56-a52c-6d0f-13a0e308fc1d.jpeg" width=600>


# 終わりに

今回シンプルな改善で助かりました。
回を重ねるごとに記事内容が適当になりつつある・・・・気を付けます。
Python実装も待たれますねー。

いつも取り上げていませんが、
Data connectivityに関するアップデートも色々充実・改善してるみたいです。門外漢なので取り上げませんが、必要な方はぜひチェックを！
[PowerBIServiceとmobileに関する改善](https://powerbi.microsoft.com/ja-jp/blog/power-bi-service-and-mobile-may-2018-feature-summary/)も定期的に行われていますね。こちらも必要な方はチェックいただくといいかもです。


# 過去Update記事

- [2018年1月](https://qiita.com/h_kobayashi1125/items/9eb4ac99b2f707364eab)
- [2018年2月](https://qiita.com/h_kobayashi1125/items/f0bcfd5eda090fcd325f)
- [2018年3月](https://qiita.com/h_kobayashi1125/items/4137bfe95fcb1b6d106b)
- [2018年4月](https://qiita.com/h_kobayashi1125/items/0b836a74e4f5c77534e5)
- [2018年5月](https://qiita.com/h_kobayashi1125/items/31867fa00c8b33d206e9)


<br>
---

**正確な情報は、必ず公式ブログ等でご確認ください！**
[PowerBI Blog(公式)](https://powerbi.microsoft.com/ja-jp/blog/)
ping値を確認してライン電話を快適にする

## ピン値を低いほうがライン電話が安定する
ネット回線が悪いとライン電話をしていたりすると途切れたりすることがあって嫌ですよね。そうおもって、速い回線を契約する前にまずはピン値を確認しましましょう。
ダウロードスピード、アップロードスピードを見るだけではわかりません。
ピン値を測るアプリがあるのでそれを入れましょう。
##ピン値とはどんなものなのか？
山にやっほーというと声が帰ってきますよね。
その帰ってくるのが速いほどピン値が低いということになります。
つまり、電話でも自分の声が相手に届いたり、相手の声が聞こえたりのスピードがピン値が低いほど良くなります。 
##今後の課題
ピン値の数学定義　上り下りとの関係性
BBc-1のコア機能が何のためにあるかをアプリケーション目線で考えてみた

昨日[このような記事](https://qiita.com/quvox/items/87132694c0b74338d674)を[quvox](https://qiita.com/quvox)さんが書かれました。これを参考にしてBBc-1のコアノードを運営するモチベーションがどこに存在するかを考えてみました。

# 前提  
- [BBc1_design_document_v1.0_ja.pdf](https://github.com/beyond-blockchain/bbc1/blob/develop/docs/BBc1_design_document_v1.0_ja.pdf)を読んでBBc-1が何かをなんとなく理解した人向け

# この記事の狙い  
- 「BBc-1のコアノードって運営するメリットあんの？」という素朴な疑問を解決したい


# コアとは

[こちら](https://qiita.com/quvox/items/87132694c0b74338d674)によるとコア機能の役割は以下のように定義されています。

> - ユーザ(appプロセス)間のメッセージング機能の提供
> - トランザクション/アセットの登録、検索機能の提供
> - トランザクションの署名検証

私のようなズブの素人でもわかるように具体例でそれぞれを解釈してみようと思います。
とりあえず、以降はデジタル通貨のやり取りを例に考えてみます。

## デジタル通貨のやり取りを例に考えてみると

ここでの登場人物は以下とします。

- アプリ利用者（通貨の利用者）  
    - アリス
    - ボブ  
- アプリ運営者(通貨の発行元)  
    - チャーリー  
- コア運営者
    - デイブ

構図的にはこんな感じでしょうか。デイブのコア一つで通貨アプリを支えるというなんとも頼りない構成ですがそこは目をつむってやってください・・・。

![名称未設定.001.jpeg](https://qiita-image-store.s3.amazonaws.com/0/222554/d2b0bb45-ad55-4b3e-000d-4c289e509f28.jpeg)


## 「ユーザ(appプロセス)間のメッセージング機能の提供」とは

> メッセージング機能によって、トランザクションデータを当事者全員に通知します。これによって承認(署名付与)が可能になります。

BBc-1はで重要な**「合意」**という概念によってあるドメイン（ここではデジタル通貨）の中で発生する取引を関係者間で承認し合う、みたいな考えがあります。（詳しくは[こちら](https://qiita.com/quvox/items/b54ea50b890ed928dd2f)）ここではアリスとボブの間で発生するお金のやり取りを発行元のチャーリーが都度承認することがコアによって可能になるということです。「そもそも承認をいちいちする必要あんの？」って思う人は[こちら](https://qiita.com/quvox/items/b54ea50b890ed928dd2f)を読んでください。

![名称未設定.002.jpeg](https://qiita-image-store.s3.amazonaws.com/0/222554/0905c22e-1c0d-a9e0-a696-b72635be1bc9.jpeg)


## 「トランザクション/アセットの登録、検索機能の提供」とは
> トランザクションやアセットの検索機能を提供することで、appプロセスが過去のトランザクションを参照して、新規のトランザクションを承認するかどうかを判断できるようになります。

デジタル通貨はその性質によりコピーできることが問題です。なので当然ですが取引に使われたデジタル通貨は過去に使われてないか（俗に言う二重支払い）確認するためにその履歴を追跡できなければなりません。ビットコインなどのいわゆる「ブロックチェーン」では取引記録を束にした台帳の連鎖を、BBc-1では取引記録の連鎖を生成する機構（[Relation部の説明を参照のこと](https://github.com/beyond-blockchain/bbc1/blob/develop/docs/BBc1_design_document_v1.0_ja.pdf)）が存在します。それらの連鎖（参照関係と言う方が適切でしょうか）を使って過去にさかのぼることをコアが実現するのです。

![名称未設定.003.jpeg](https://qiita-image-store.s3.amazonaws.com/0/222554/383d425c-ec74-aa0f-123b-d0daca80883d.jpeg)



## 「トランザクションの署名検証」とは
> トランザクションの検証についても、中身そのものを解釈するのではなく、付加されている署名が有効かどうかをチェックするのみです。

そして検索機能を使って該当する取引（ここではデジタル通貨）を探し当てるとそれらに付与されている署名が正しいものかを検証して先ほど述べた二重支払いを発見することができるようになります。

> トランザクションの中身が本当に正しい（正当なもの）かどうかは、トランザクション登録の前に当事者間で合意していれば、そこにcoreプロセスが踏み込む必要性がないためです。

上記で言われているように中身の正当性を検証することはしないことに注意しておいてください。

![名称未設定.004.jpeg](https://qiita-image-store.s3.amazonaws.com/0/222554/7c5feae2-964d-a802-bc56-6b1463bb97ff.jpeg)


# まとめると  
- コアノードを運営することでアプリ運営者はコアノードの機能を使って以下のことができるようになる
    - 取引の検知
    - 取引の検索
    - 取引の署名検証
- **デジタル通貨の取引ではコアノードの運営は2重支払いの検知に貢献できる**

# 最後に
- 「これ違う」「これ勘違いされる」「こうしたほうが良い」などご意見お待ちしてます
初めてPMと実装の二刀流を経験して成長を実感した6つのこと

フルスタックエンジニアを目指して日々修行中でございます。
会社ではサーバーサイドエンジニアとして仕事をしています。

今から約8ヶ月前、改め入社してから約7ヶ月が経った頃、
欲張りな私はある社内サイトのリニューアル業務にて、プロジェクトマネージャー（以下PM）を担当することになりました。
そこから成長を実感した6つのことを書きたいと思います。
その前に、担当したプロジェクトの概要と、
解決すべき問題点を共有しておきますね(☝ ՞ਊ ՞)☝ｳｨｰ

#担当したプロジェクトの概要
- リニューアルするサイトは、WordPressで開発された社内の情報共有サイト
- コンセプトは「見やすい！探しやすい！おしゃれ！」
- チームメンバーは計9名（依頼者は別で2名）
    - プロジェクトマネージャー1人（私）
    - インフラ周り2人
    - デザイナー1人
    - コーダー兼フロントエンジニア1人
    - WordPress実装2人（1人は私）
    - 大先輩サポート4人
- プロジェクト期間は6ヶ月間

#解決すべき問題点
- 検索しても欲しい記事が見つかりにくい
- 記事を投稿するにもDBの事情で遂行しにくい
- そもそも連語検索出来ない
- ページ表示速度が重い
etc.


「やります！！！」とは言っては見たものの、プロジェクトというものを全く知らず、頭の中には「プロジェクトX」しか湧いてきませんでしたね。



(☝ ՞ਊ ՞)☝ｳｨｰ

#とにかくがむしゃらにやって見た結果
見事に納期ギリギリでしたが上記の解決すべき問題点を解決＋αまで行い、満足できる状態でリリース完了することが出来ました！
結果までの課程を吹っ飛ばしていますが、一言で言うと、

「大変だったけれど、チームで働くっていいな」

ですね。

#今プロジェクトで成長した6つのこと

##1. 知ったかぶりは何もいいことがない
当初私は、「理解できない自分」が許せなく、いわゆるプライドが高い人間でしたため「分からないことを分かったふり」をしていました。しかし、PMとして業務を遂行するにあたり、要件定義、仕様の決定、システム設計などを知ったかぶりでこなせるはずもありません。。
そんな中、あるチームのメンバーがたくさん私に質問をしてくることに気づき、知ったかぶりをせず、純粋に質問をしてくれるそのメンバーを見て、「何も恥ずかしくないし、むしろかっこいい」と感じ、私のつまらない意地っぱりは気づけば解消されていましたね。
結果、依頼者との認識の齟齬なくプロダクトをリリースすることができました。

##2. ユーザーというものを背負う責任感
最初は楽しくて設計から実装まで行なっていましたが、リリース1ヶ月前あたりになると、全身から次の言葉が冷や汗と共に発せられるんですよね。
「今自分が開発しているこのプロダクトを使う人は本当に喜ぶのだろうか」

その時に、自己満足の虚しさを知ったような気がします。当たり前のことかもしれませんが、よく耳にする「相手のためにやっていればいつか自分に返ってくる」という言葉の意味を深く理解したと思います。自分のためよりも、相手（ユーザー）のために努力する方が量も質も上がりますね。

好きな女の子と仲良くなるためにはどうすればいいか本気で考えるのと近しいと思います。( ´థ౪థ)

##3. チームを最大化させる要因は心地よいコミュニケーション
なぜチームで仕事をするのかと考えた時に、「良いものを作るには、1人では物理的にも精神的にも出来ない」からなんじゃないかと思っています。そんなチームのメンバーは当然全員「人間」な訳で、人間を理解せずにコミュニケーション云々は言えないです。
笑っていると楽しいし、それでいて真剣な仕事の相談も出来たらアイデア出まくりですし頑張ろうという気になります。それが循環しているすごくいいチームでした。
これが、一つのゴールを目指し、いいアウトプットを出すチームの「助け合い」なんだなぁと深く感じましたね。

##4. 実装は、Computerとの会話
PMもやりつつ、WordPressの実装も行なったのですが、WordPressは便利と思う反面、融通が効きにくい仕組みでもあります。自分がしたいことをComputerがわかるように記述してあげるというのが大事で、それをするためにはWordPressさんのことを知らないと出来ないことです。
結果、全てにおいて相手のことを知らないと上手くいかないということですね。
適当に書いてしまったコードから、1ヶ月後くらいにツケが回ってきましたし。。。
(☝ ՞ਊ ՞)☝ｳｨｰ(☝ ՞ਊ ՞)＝☞)՞ਊ ՞) ←こんな感じ

##5. スケジューリングの重要性と難しさ
今回のプロジェクトで自分に一番足りないなと感じたのが、プロジェクト全体を見通して大枠のスケジュールを組み立てることと、それを管理することですね。
自分一人の予定であれば、「気合いダァーーー！！！！」といって根性で納期を守ればいいですが、チーム全体となると話は違います。他のプロジェクトと平行で動いているメンバーもいます。そんな中、大先輩が大枠のスケジュールの引き方を指導してくれ、一気にプロジェクト完遂までの道のりが見えるようになりました。
今当初の自分にアドバイスをするのであれば、「プロジェクトが完了した時を具体的にイメージして、その時全てがどうあるべきかを考えろ」といいますね。考えれば必然なものは思いつくし、足りないものは後からでも補えば良いので。

##6. 要件定義とシステム設計がある程度できたらチームで認識合わせのキックオフをすべき
今プロジェクトは完全に0からのスタート（元データ以外）だったので、事前にリスクヘッジへの対策を練るべきでした。しかし、それをしなかった結果、行き当たりばったりの開発になった部分があり、PMとしての不足です。
キックオフ以外にも、こまめな共有を怠らないのもPMの仕事だと感じました。

#最後に
6ヶ月間のPMと実装の二刀流経験を通して、PMの重要な役割とは、「相手のことを考えた上でのコミュニケーションを如何に取っていくか」なのではないかと感じています。
結果的にリリース後にユーザーからいいコメントをもらえたり、追加の依頼が来たりと、楽しい保守・運用が出来ています。これも、相手のことを考え抜いたチームだからこそ、ユーザー、依頼者から期待をされるのだと思います。

また、PMと開発の二刀流だったことから、システム設計や、工数管理も、本来「実装を依頼する人と実装を依頼される人」のどちらも経験しながらだったから円滑に進められたのかなと感じます。

結論としては、やはり勉強あるのみですね！

(☝ ՞ਊ ՞)＝☞)՞ਊ ՞)(☝ ՞ਊ ՞)＝☞)՞ਊ ՞)(☝ ՞ਊ ՞)＝☞)՞ਊ ՞)
Viewにpathのハードコーディングをしたくないのでdirectを使ってみる

Rails5.1からカスタムURLヘルパーメソッドを作成する`direct`が追加されました。

https://railsguides.jp/5_1_release_notes.html#direct%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%A8resolved%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0

例えばSNSログインを実装して、ツイッターやGitHubに処理を飛ばすlinkをViewに書く際、

```sample.html.haml
%h1 Logins#index
%p Find me in app/views/logins/index.html.haml
= link_to I18n.t("display.users.twitter"), '/auth/twitter' ,class: "btn btn-primary"
%br/
= link_to I18n.t("display.users.github"), '/auth/github' ,class: "btn btn-success"
```

ここのViewの、`/auth/github`が気になる・・・。
でもdevise使ってないからdeviseのメソッドも使えないし、`rails routes`してもPrefix出てこないし・・・、みたいな時に使うとちょうど良い機能な感じです。


```config/routes.rb
Rails.application.routes.draw do
  root to: 'test_view#index'

  resource :login
  get '/auth/:provider/callback', to: 'sessions#create'
  direct(:auth_twitter) { '/auth/twitter' }
  direct(:auth_github) { '/auth/github' }
end
```

上記のコードに書いてある`direct(:auth_twitter) { '/auth/twitter' }`みたいな記述をすることで

```sample.html.haml
%h1 Logins#index
%p Find me in app/views/logins/index.html.haml
= link_to I18n.t("display.users.twitter"), auth_twitter_path, class: "btn btn-primary"
%br/
= link_to I18n.t("display.users.github"), auth_github_path, class: "btn btn-success"
```

このように、`auth_github_path`の形で記述することができます。
（正直微妙な使い方している気もするので、ちゃんとした使い方知っている人いたら教えてくださいm(__)m）
grepコマンドサンプル集（ログ解析編）

## apacheアクセスログから特定の時間帯のアクセスを抽出したい

11時台のアクセスのみを抽出
```grep -w "2018:11" ファイルパス```
11時台のアクセス件数
```grep -c "2018:11" ファイルパス```
Java 9 Optional::stream

下記のようにCompanyとEmployeeクラスがあって、Companyのなかに、たくさんEmployeeがある。

``` Employee.java
public class Employee {
  private String id;
  private String name;
}
```

``` Company.java
public class Company {
  private List<Employee> employees = new ArrayList<>();
  
  public Option<Employee> getEmployeeById(String employeeId) {
    return employees.stream().filter(e -> e.id.equals(employeeId)).findFirst()
  }

  public List<Employee> getEmployeeList(List<String> employeeIds) {
  }
}
```

次、`employeeIds`のリストで`Employee`のリストを取得したくて、`getEmployeeList`を実装したくて、Java8とJava9実装してみる。

```Java8.java
public List<Employee> getEmployeeList(Collection<String> employeeIds) {
  return employeeIds.stream()
    .map(this::getEmployeeById)
    .filter(Optional::isPresent)
    .map(Optional::get)
    .collect(toList());
}
```

```Java9.java
public List<Employee> getEmployeeList(Collection<String> employeeIds) {
  return employeeIds.stream()
    .map(this::getEmployeeById)
    .flatMap(Optional::stream)
    .collect(toList());
}
```

Java 9 の`Optional::stream`のおかげで、`getEmployeeList`のコードが短くなる。
N+1を解決するincludesの書き方備忘録

基本形

```rb
users = User.includes(:projects)
```

こう書くことで、下のような記述の際のN+1に対応できる

```rb
users.each do |user|
  user.projects.name
end
```

もちろん複数も可能

```rb
users = User.includes(:projects, :order)
```

ネストしたい場合はこう
（UserがProjectを所有し、ProjectがTaskを持ち、TaskがTagを持ってCategoryに属している場合）

```rb
user = User.includes(projects: [tasks: %i[tags category]])
```

こんな書き方も
（Userに紐づいているOrderに紐づいているPlanまでincludesする、みたいな場合）

```rb
user = User.includes([{ projects: :tasks }, { order: :plan }, :projects, :order])
```

Docx
https://apidock.com/rails/ActiveRecord/QueryMethods/includes