OmniAICreator/Qiita-1.07M huggingface dataset:
ソフトウェアエンジニアをシェアすることのメリット。0.5人月 + 0.5人月 > 1.0 人月 という観測。

言いたいことは、複数のプロジェクトを同時に担当しているエンジニアは特定のプロジェクトの専任となっているエンジニアより効率よく成果を挙げられるのではないかということ。

これは次の二点があるからだ。

 - 各プロジェクトで重複する問題に対しては1つの対処が完了すれば別のプロジェクトでの対処は簡単になる
 - 1つのプロジェクトで得られた学び・気付きを別のプロジェクトに活かせる

なぜ、この思うようになったかというと、いま自分が担当しているプロジェクトで複数プロジェクトを担当することによる恩恵を実際に受けていると感じたからだ。

最近、僕はフリーランスとして二社から同時に開発の仕事を請けている。
そのうち片方の会社のプロジェクトでは僕とは別に二社から仕事を請けている人がいる。
合計３社に跨ってエンジニアがシェアされている状態だ。
三社の技術スタックは同じではないが、それぞれ共通する部分がある。

この状態で開発をしていて、たびたび下記のようなことが起きた。

 - 別件であるやり方がうまくいっているのでこっちでもやりたい
 - ライブラリの使い方に起因するバグを見つけたが、別件のプロジェクトも同じ間違いしていることに気付き問題発生前に直せた
 - 別件でほぼ同じ要件の実装をしたことがあるから同じやり方で実装できる
 - 別件でフレームワークのアップデートをしているのでもう片方ではハマらずにサクッとアップデートできた

片方のプロジェクトでの経験がもう片方のプロジェクトに活かせることが非常に多い。
つまり0.5人月の作業をしていたとしても、本来であれば0.5人月では達成できない成果を出すことができるのだ。
単純に同じ技術スタックの別のプロジェクトに移動するのと比べてもノウハウがすぐに伝わるしタイムリーな問題(フレームワークのアップデートなど)にも強く、同時に複数プロジェクトを担当することのメリットは強いように思える。

この考え方に基づけば、通常どうりプロジェクト専任のエンジニアを配置するより
・2つのプロジェクトに半人月ずつでエンジニアを配置する
・複数社でエンジニアをシェアする
という仕組みにした方が効率はずっといいはずだ。

こうやって書くと机上の空論感がすごいが、自分としては効率が良いという実感がある。
プロジェクトごとの技術レベルを平均化できるというメリットもありそうだ。

深夜に眠れないから暇を持て余して書いたポエムなので、コミュニケーションコストについて
考えるのを忘れていた。
ソフトウェア開発チームにとって人数が増えることはデメリットにもなり得る。
コミュニケーションコストが発生するからだ。
専任のプロダクトマネージャーがいて適切にタスクが分割・割り当てされている環境であれば
コミュニケーションコスト以上のメリットは確実にあると思っている。
galaxy local tool_shedを起動する

# galaxy tool_shedをローカルで起動する

galaxy-stable のイメージで local toolshed を起動する事ができる

```
docker run -it -p 8080:80 -p 8021:21 -p 8022:22 -p 9009:9009 bgruening/galaxy-stable /bin/bash

/galaxy-central# /usr/bin/startup &
./run_tool_shed.sh &
```

しかし、確かに起動はしているが、ホストのブラウザーから、http://localhost:9009
でDocker上で動作しているtoolshedに接続できない

これを行うためには`config/tool_shed.yml`を作成して他のネットワークからの接続を許可する必要がある 

```
$ cp config/tool_shed.yml.sample config/tool_shed.yml
```

`config/tool_shed.yml` の　http: 127.0.0.1:9009 => `http: :9009`に変更する

```
$ ./run_tool_shed.sh &
```

今回はここまで:smile:
laravel blade 内で scss を使うディレクティブ @scss

ずぼらなのでblade内でscssが使いたくなります。

# 使い方

blade内で `@scss` と `@endscss` で挟んだ領域で、scssをcssに変換してくれます。

```html:hoge.blade.php

<style>
@scss
p{
  span{
     i{
        color:red;     
     }
  }
}
@endscss
</style>

```

# 設定方法

## leafo/scssphpをインストール

http://leafo.net/scssphp/


## ScssServiseProvider

```php:app/Providers/ScssServiseProvider
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Blade;

class ScssServiceProvider extends ServiceProvider
{
    public function boot()
    {
        require app_path('../vendor/leafo/scssphp/scss.inc.php');

        Blade::directive('scss', function ($expression) {
            return '<?php $__env->startComponent(\'components.scss\'); ?>';
        });

        Blade::directive('endscss', function ($expression) {
            return '<?php echo $__env->renderComponent(); ?>';
        });
    }

    public function register()
    {
        //
    }
}

```

## config/app.php にProvider追加

```php:config/app.php
    'providers' => [
    ...
    App\Providers\ScssServiceProvider::class,
    ...
```


## scss.blade.php

```php:resources/views/components.scss.blade.php
{!! (new scssc())->compile((string)$slot) !!}
```
Stanford NLPをServer化してみた

[前の記事](https://qiita.com/takuyakubo/items/9fb4deb504add1683eb4)で予告した通り、[StanfordNLP](https://github.com/stanfordnlp/stanfordnlp)をFlaskでAPIとweb pageを作ってみました。
詳細は Github [repository](https://github.com/takuyakubo/stanfordNLP_Server) にあります。
ライセンス関係に疎いので、まだ入れていません。やらないと！

## やったこと

Flaskを使って API
![image.png](https://qiita-image-store.s3.amazonaws.com/0/30977/ca6c571e-ca76-e78c-d4cc-990ad48153fe.png)
と web page
![image.png](https://qiita-image-store.s3.amazonaws.com/0/30977/c5733259-f7c3-396e-54e0-f9ce9da20551.png)
を作ってみました。
一応、日本語など他の言語でもできます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/30977/d23809c4-78a2-cc3f-390f-b5bc7a0f40fe.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/30977/b9968357-05ce-c7de-4eb7-1b727477fc5c.png)

## サーバの立ち上げ方
### repositoryのコードを使用する方法 (やや推奨)
repositoryに書いた通りですが、git cloneやzipでダウンロード後、
Python3.7.2環境で `pytorch` `stanfordnlp` `flask` をpip経由などでinstallしてください。
Mac環境であれば、

```bash
pip install -r requirements
```

で完了します。その後、

```bash
python server.py en
```

で英語のparserを起動します。モデル(一言語につき2.7GB程度)のダウンロード、ロードで時間がかかりますが、終わればサーバが立ち上がります。
2回目以降同じ言語のサーバを起動する場合はダウンロードは行われません。

(注意！)前の記事でも書きましたが、`lzma`が入っていないことがあります。`xz`をhomebrewなどでインストールし、その後pythonを再インストールすれば正常に動くようになります。

同様に

```bash
python server.py ja
```

で日本語のparserを起動します。

### docker imageを使う方法
[docker image](https://cloud.docker.com/u/takuyakubo/repository/docker/takuyakubo/usnlp)も作成してあります。こちらは、

```bash
docker run -e LANGUAGE=ja -it -p 5020:5020 takuyakubo/usnlp
```
とすることで起動できます。(日本語の場合、英語にしたい場合は`ja`を`en`に、他の言語は、[公式ページ](https://stanfordnlp.github.io/stanfordnlp/installation_download.html#human-languages-supported-by-stanfordnlp)にある通りです。)
コードを用いるより重いのと、こちらは起動のたびにモデルのダウンロードとロードを行うので時間がかかります（起動に10分程度?)

## やること
色々ありますが、とりあえずのところ

- dockerをもう少しなんとかする
- ライセンスをちゃんとする

はやらないといけないと思っています。
ただ、あまり知識がないので「どうしよう」という状態です。
詳しい方がいらっしゃいましたら教えていただけるとありがたいです。

読んでいただきありがとうございました。

## 参考
公式ページ
https://stanfordnlp.github.io/stanfordnlp/index.html
作成repository
https://github.com/takuyakubo/stanfordNLP_Server
Java List を Group, Sort など

List をグループごとに分けてソート処理

```Java
// グループ
Map<String, List<Object>> map = list.stream().collect(//
    Collectors.groupingBy(o -> o.getKey1()));
// 複数キー
Map<String, List<Object>> map = list.stream().collect(//
    Collectors.groupingBy(o -> o.getKey1() + o.getKey2()));
// 複数キー の null ざつに対応
Map<String, List<Object>> map = list.stream().collect(//
    Collectors.groupingBy(t -> t.getKey1() + (t.getKey2() == null ? "" : t.getKey2())));
 
```

```Java
// ソート
Comparator<Object> comparator = //
    Comparator.comparing(Object::getSort1, Comparator.nullsFirst(Comparator.naturalOrder()))//
    .thenComparing(Object::getSort2, Comparator.nullsFirst(Comparator.naturalOrder()))//
    .thenComparing(Object::getSort3, Comparator.nullsFirst(Comparator.naturalOrder()));
// limit
map.entrySet().forEach(e -> e.getValue().stream().sorted(comparator).limit(100).forEach(l -> System.out.println(e.getKey() + ":" + l.getValue())));

```
【2019年2月版】WindowsのRails5環境構築でsqlite3で躓いた時のメモ

WindowsにRails環境を構築するのって結構大変なんやな...っていうのは知ってた。自分も3回くらい挫折したけど、今回何とか構築できたので、2019年2月の最新情報として参考までに記事にまとめておこう。

## ソリューションとなる環境

- Ruby v2.4.5
- Rails 5.2.2
- sqlite3 v1.3.12
- Windows 10

##　devkitが必要

WindowsではRubyInstallerが使えるが、ここでdevkit付きのものをDLしよう！(たぶん普通はそうする)

## sqlite3ぃぃい

個人的にはまったのがsqlite3のインストールおよびビルド。普通に```rails new [name]```とするとsqlite3のインストールで止まる。エラーメッセージにはライブラリが足りないとかなんとか書いてあるが、助け舟となるQiitaの記事があったので、[こちらの記事](https://qiita.com/yoru722/items/8a633d71148de0f0ae1f)を参照してほしい。しかしこれでもまだ足りない。その理由が[こちらのteratailの質問](https://teratail.com/questions/56708)にある。内容をまとめると以下のようになる。

- sqlite3の公式からWindows用のsqlite3系のDLLとsqlite3のソースをDL
- 先ほどDLしたライブラリ群をsqlite3のインスト時にオプション指定してビルドする
- しかし最新のsqlite3 v1.4ではうまくいかなかった(なぜ?)
- sqlite1.3.10以上じゃないとRuby2.2以上で動作しないからsqlite3 v1.3.12をGemfileで指定する
- Ruby v2.4だとうまくいくらしい(理由はわからない)
- bundle installして終了

## 結論

わからないことがいっぱい...とにかくWindowsでの環境構築は難しいんだなって思いました。少しでも参考になれば幸いです。
AndroidアプリのApplicationIdをbuildTypes内での変更も考慮してresValueにセットする

# はじめに
　XML内でApplicationIdを参照する必要があり、gradleでresValueを使って、ApplicationIdをXMLから参照できるよう定義しようとしました。しかし、buildTypes内でApplicationIdが変更されている場合でこのような事を実現しようとした時に少し詰まってしまいました。調査の結果、解決したのでここにメモしておきます。

# 方法

`applicationVariants`を使用して、各variantごとにresValueを設定します。

```gradle
buildTypes {
    ...
    applicationVariants.all { variant ->
        variant.resValue 'string', 'application_id', applicationId
    }
}

```

# 詰まったところ
　gradle内でApplicationIdを変更していなければ上記のようなコードを書く必要はなく、defaultConfig内で

```gradle
resValue 'string', 'application_id', applicationId
```
とだけ書いてもうまく動作します。

今回の場合、debugビルド時に`applicationIdSuffix`を使い、ApplicationIdを変更していたため、上記のような工夫が必要となりました。

# 参考
https://stackoverflow.com/questions/36279319/how-do-i-include-applicationidsuffix-in-some-generated-resource-value
「開発エラー時のデバッグフロー」と「煮詰まったときの対処法」についてまとめてみた。

## 前置き
「そもそもどうやってデバッグすればいいの」という質問に答えるために、自身がデバッグしているときの思考やフローを的まとめて見ました。
煮詰まったときの対処法もまとめてます。
※ webアプリケーションを想定してます。


#【開発エラー時 対処フロー】
- 原因が直感的(経験的)にわかるとき => そのまま修正
- 直感的にわからないとき
  - エラーメッセージが表示されているとき
     - エラーメッセージをよく読んで意味を理解する
     - 理解できない場合はググって理解する
     - 必要とあれば、書き方があっているかをドキュメントなどを見て確認する。
     - 上記でわかれば、修正。できなければ、下に進む
  - エラーメッセージ出ないエラー(ex. 画面に想定のものが表示されない等) or エラーメッセージの発生原因を探る必要があるとき
     - ブレークポイントを張る or プリントデバック
         - 予期せぬデータが入っている場所、原因となっている場所を特定する
      - コード差分から原因の推定を行う
      - 正常に動作する入力と、異常動作してしまう入力の差分を見つける  
      - 必要とあれば、書き方があっているかをドキュメントなどを見て確認する
      - XX分(ex. 10分)かけてもわからないときは、一度冷静になって別の視点で探す ※ [煮詰まったときは](#煮詰まったときは) 参照
      - YY分(ex. 20分)かけてもわからないときは、周りの人に相談する
          - 相談の際は、「現在行おうとしていること」「現状起こっている問題(エラー)」「現状の状態・変更点(コード)」「調査でわかっていること(わからないこと)」 を簡単に伝える。 (※基本的には対話で伝わっていくので、整理にめちゃめちゃ時間掛ける必要はなし)


# 煮詰まったときは
## 煮詰まったときに意識したいこと - そもそもなぜ煮詰まるのか
基本的に煮詰まったときは、原因は大きく分けて２つ。
本質的に難しい課題を解いてているか、もしくは、**課題設定が間違っているか**。
前者は、例えば、既存アルゴリズムの高速化や、大規模設計など。
後者は、例えば、自身がエラーと推定している部分以外の部分がエラーに関係しているなどの場合。

特に後者の場合は、**難しくない問題を自身で難しくしてしまっている場合がある**。(というか経験的には殆ど後者)
バグがなかなか解決しない場合、自身が後者の罠にハマっていないか、意識する。

下記の手法が「煮詰まり」には有効なことが多い。

## 煮詰まったときに手助けとなる手法
- ラバーダッキング = 問題点をテディベアに話してみる
参: http://www.aoky.net/articles/john_graham_cumming/talking_to_porgy.htm

- コード差分を考える。(動くところまで戻る)
- 二分探索法: コードを半分コメントアウトしてバグが起こるかを繰り返し試す
- 一回寝て(時間をおいて)リセットする！
- 人に相談する
vim設定のまとめ #2 プレビュー用

便利なプレビュー用のプラグインを3つ紹介します。
基本は、私の [dotfiles](https://github.com/nzw/dotfiles) をインストールすることでできるようになっています。

### 環境
```
OS: MacOS Mojave
ツール： iTerm2 + vim
```
## PHP-CS-Fixer
PHPのコードを成形してくれるツールです。
今回は更に、vim上でdiffを確認し、その後成形を反映してくれるプラグインを紹介します。
[参考手順：PHP-CS-Fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer)
<img width="532" alt="スクリーンショット 2019-02-06 0.39.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/11030/4b7bb167-336d-bfca-b110-d97466f9e938.png">
※もちろん入力コマンドは自由に設定可能です。
まず、「PHP-CS-Fixer」をインストールします。
#### 設定方法
```
$ brew install php-cs-fixer
```
次に下記のファイルに追記してください。

```vimscript:.vimrc
" php-cs-fixer
let g:php_cs_fixer_path  = "/usr/local/bin/php-cs-fixer" "インストールした場所を指定
let g:php_cs_fixer_level = "all"                " which level ?
let g:php_cs_fixer_config = "default"           " configuration
let g:php_cs_fixer_php_path = "php"             " Path to PHP
let g:php_cs_fixer_fixers_list = ""             " List of fixers
let g:php_cs_fixer_enable_default_mapping = 1   " Enable the mapping by default (<leader>pcd)
let g:php_cs_fixer_dry_run = 1                  " Call command with dry-run option
let g:php_cs_fixer_verbose = 1                  " Return the output of command if 1, else an inline information.

nnoremap <silent>,pcd :call PhpCsFixerFixDirectory()<CR>
nnoremap <silent>,pcf :call PhpCsFixerFixFile()<CR>
```
```shell:.bashrc
export PATH="$PATH:$HOME/.composer/vendor/bin"
```
vim 上で設定したコマンド（※今回は「,pcd」又は「,pcf」）を入力すると、diff を表示してくれるようになります。


## vim-instant-markdown
次に、Markdown 形式のファイルをプレビューしてくれるプラグインの紹介します。
Plugin：[suan/vim-instant-markdown](https://github.com/suan/vim-instant-markdown)
#### 設定方法

```
$ cd .vim/bundle/
$ git clone https://github.com/suan/vim-instant-markdown.git
$ npm install -g instant-markdown-d
```

```vimscript:.vimrc
...
NeoBundle "vim-instant-markdown"
...
```

Markdown形式のファイルを `vim` で編集して保存すると、

```
vim README.md
```
自動でブラウザに反映されます。
<img width="792" alt="スクリーンショット 2019-02-06 0.02.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/11030/34f470fd-f85c-702f-99c0-d8d2e02181f1.png">

## imgcat
iTerm2 上で画像確認ができる方法を紹介します。

#### 設定方法
下記の、iTermの公式プラグインのコードをコピーします。
[imgcat](https://iterm2.com/utilities/imgcat)

どこに置いても良いのですが、パスが通っている下記にコピーした内容を権限を確認して保存します。

```
$ /usr/local/bin/imgcat
```

保存したファイルを実行し、引数に画像ファイル名を指定すれば、表示されます。

```
$ imgcat [画像ファイル名]
```
![スクリーンショット 2019-02-06 0.23.41.png](https://qiita-image-store.s3.amazonaws.com/0/11030/70b499fc-7e83-7c96-42c8-a8f2dff1154f.png)

[参考URL: 【iTerm2】ターミナル上で画像を表示する方法](https://qiita.com/noraworld/items/ea59c37e48ac0977cc72)
RTC DS3231 AT24C32 時計モジュールをArduinoに繋げて動かす

RTC(リアルタイムクロック)DS3231 AT24C32 時計モジュールをArduinoに繋げて動かす際の手順を記載します。

# 準備
・[Arduino UNO R3 互換品](https://www.amazon.co.jp/スイッチサイエンス-SSCI-GettingStartedArduinoKit-Arduinoをはじめようキット/dp/B0025Y6C5G/ref=sr_1_4?s=toys&ie=UTF8&qid=1548518133&sr=1-4&keywords=Arduino+正規品)
・[RTC DS3231 AT24C32 時計モジュール](https://www.amazon.co.jp/gp/product/B011DT3E36/ref=ppx_yo_dt_b_asin_title_o09__o00_s00?ie=UTF8&psc=1)
・[電池 LIR2032](https://www.amazon.co.jp/gp/product/B074MTLLFT/ref=ppx_yo_dt_b_asin_title_o09__o00_s00?ie=UTF8&psc=1)
・ジャンパーワイヤ　４本（メス-オス）

# 回路図
下記モジュールにジャンパーワイヤを接続してArduinoと繋ぎます。
![001.png](https://qiita-image-store.s3.amazonaws.com/0/344880/fcad4df4-d62b-3fa6-c81b-0e5f37c40509.png)

RTC   -----         Arduino 間を下記の通り配線する。
VCC   <--->    5V
GND   <--->    GND
SDA   <--->    Analog4
SDC   <--->    Analog5

# コード
[参考]記載のライブラリをインストールした後下記を書込み
時刻取得

```c
void setup()
{
  // Setup Serial connection
  Serial.begin(115200);
  // Initialize the rtc object
  rtc.begin();
}

void loop()
{
  // Get data from the DS3231
  t = rtc.getTime();  
  // Send date over serial connection
  Serial.print("Today is the ");
  Serial.print(t.date, DEC);
  Serial.print(". day of ");
  Serial.print(rtc.getMonthStr());
  Serial.print(" in the year ");
  Serial.print(t.year, DEC);
  Serial.println(".");
  
  // Send Day-of-Week and time
  Serial.print("It is the ");
  Serial.print(t.dow, DEC);
  Serial.print(". day of the week (counting monday as the 1th), and it has passed ");
  Serial.print(t.hour, DEC);
  Serial.print(" hour(s), ");
  Serial.print(t.min, DEC);
  Serial.print(" minute(s) and ");
  Serial.print(t.sec, DEC);
  Serial.println(" second(s) since midnight.");
  // Send a divider for readability
  Serial.println("  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -");  
  // Wait one second before repeating :)
  delay (1000);
}

```

時刻設定

```c
// The following lines can be uncommented to set the date and time
rtc.setDOW(TUESDAY);     // Set Day-of-Week to SUNDAY
rtc.setTime(13, 0, 0);     // Set the time to 12:00:00 (24hr format)
rtc.setDate(5, 2, 2019);   // Set the date to January 1st, 2014
```

# テスト
時刻が取得できました。
![IMG_0209.JPG](https://qiita-image-store.s3.amazonaws.com/0/344880/520061c3-362c-d1a9-2732-80038d1bc9af.jpeg)

# 参考
[Library: DS3231](http://www.rinkydinkelectronics.com/library.php?id=73)
　API仕様書は、「Manual:」から参照できます。
　ライブラリは、「ダウンロード」から取得できます。

・[組み込みエンジニアでなくても週末にArduinoを使って遊ぶ](https://qiita.com/seigot/items/958d3f2817a4bdac8754)
・[Arduino Uno 互換品を使おうとした際に、Mac(OS:Siera)上のArduino IDEからシリアルデバイスが見つからない問題を解決した件について](https://qiita.com/seigot/items/1515082a09224563b148)
Githubのorganization以下の全リポジトリをgrepする

# Githubのorganization以下の全リポジトリをgrepする


EOLや脆弱性などで影響調査をしなければならないとき、よく`git grep`をします。
ただ、organization以下全部調べるとなると、何回clone&grepするの？...と、ウンザリ。

Githubの検索でいいじゃんという話もありますが、本当に全量なのかが怪しい...[^1]
[^1]: 検索インデックスに入っていないのか、サマられているのか、ヒットしないことがある...もしかして、やり方が悪い？

なので、CLI上でGithubのorganization以下の全リポジトリをgrepできるやつを作りました。

https://github.com/yhinoz/git-org

## インストール

READMEに書いてある方法か、下記の方法でインストールしてください。

1. [Github Releases](https://github.com/yhinoz/git-org/releases)からバイナリをダウンロード
2. `PATH`の通った場所に移動
3. ファイル名を`git-org`にリネーム

## 使い方

gitのサブコマンドとして利用する事ができます。

```
git org grep -o <organization名> -- <git grep に渡すオプションや引数>
```

例えば、

* organization名 = `yahoojapan`
* 検索パターン = `hoge`
* ignore case
* 行番号表示

を実行したい場合は、

```
git org grep -o yahoojapan -- -i -n hoge
```

とします。
結果はTSV形式で下記のように出力されます。

```
<organization名>/<リポジトリ名>    <file名>    <行番号（オプションを指定していない場合は0）>    <ヒットした行>
```

### プライベートリポジトリにも対応

環境変数`GITHUB_ACCESS_TOKEN`にPersonal Access Tokenをセットすることで、自身が参照できるプライベートリポジトリに対しても実行可能です。

```
export GITHUB_ACCESS_TOKEN="your_personal_access_token"
```

### Github Enterpriseにも対応

環境変数`GITHUB_API_BASE_URL`にGithub EnterpriseのAPIのURLをセットすることで、Github Enterpriseにも実行可能です。

```
export GITHUB_API_BASE_URL="https://your-ghe/api/v3"
```

### 注意

* 一時ディレクトリにorganization以下の全リポジトリをcloneされるため、ディスク容量を圧迫することがあります
    * cloneしたリポジトリはコマンド実行開始/終了時に消去されます
* cloneはSSHで行うので予め、ssh-agentなどで鍵を登録しておく必要があります


## まとめ

このコマンドを作ったことで、調査は結構捗るようになりました。
よかったら使ってみてください :kissing_heart:
pdfuniteで複数のPDFを結合

PopplerのpdfuniteでPDFを結合。
pdftkとかconvertとかあるけど、TeXLive2017以降をインストールしている人は標準で使えるのでこれが一番早いと思われる。

以下のコマンドでディレクトリ内のpdfをoutput.pdfにまとまる。

```bash
pdfunite *.pdf output.pdf
```

-----
* 参考  
https://poppler.freedesktop.org/  
https://texwiki.texjp.org/?Poppler
【RSpec/capybara】fill_inが上手く動作しない

現場で使えるRuby on Rails5 速習実践ガイドの、Chapter5-8（テスト周り）で詰まったのでメモ。

## ログインのテストに失敗
RSpecのfill_inというメソッドを使って、ログインフォームに値を渡した後、投稿が反映されているか確認するというテストでしたが、下記のエラーが出て何度やっても上手くいかず。

```

Failures:

1) タスク管理機能 一覧機能表示 ユーザーがAがログインしている時 ユーザーAが作成したタスクが表示される
Failure/Error: expect(page).to have_content '最初のタスク'
expected to find text "最初のタスク" in "Taskleaf\nログイン\nメールアドレス\nパスワード"

```

エラーのスクショを確認したところ、ログイン失敗どころかログインフォームに値を渡すことすら出来てなかったことが判明。
![スクリーンショット 2019-02-06 0.45.44.png](https://qiita-image-store.s3.amazonaws.com/0/252494/882cb086-d5d9-e469-ca66-70b05c2e3610.png)
見事に何も入ってない。

どうやら間違えていたのはfill_inの使い方だったようです。

## fill_inの書き方を変える
失敗時のコードがこちら。
テスト側

```rb
context 'ユーザーがAがログインしているとき' do
 before do
  # ユーザーAでログインする
  visit login_path
  fill_in "email", with: 'a@example.com'
  fill_in "password", with: 'password'
  click_button 'ログインする'
 end
``` 

ビュー側

```slim
h1  ログイン

= form_with scope: :session, local: true do |f|
  .form-group
    = f.label :email, 'メールアドレス'
    = f.text_field :email, class: 'form-control', id: 'session_email'
  .form-group
    = f.label :email, 'パスワード'
    = f.password_field  :password, class: 'form-control', id: 'session_password'
  = f.submit 'ログインする', class: 'btn btn-primary'
```

教科書通りにやっても上手く値を渡せず...

```rb

   fill_in "email", with: 'a@example.com'
   fill_in "password", with: 'password'
```

試しにこちらのコードを、

```rb
   fill_in "session_email", with: 'a@example.com'
   fill_in "session_password", with: 'password'
```

このように、labelでなくテキストフィールド側のIDに合わせてみたところ、無事に値を渡せて、テスト通りました！

ラベルテキストで上手く特定が出来ないときは、テキストフィールドにIDを付与してやって、そちらで探すといいかもです。
Spring Bootアプリ開発メモ

# ◆開発環境		
- JDK（バージョン：）
- Kotlin（バージョン：）	
- Spring Boot（バージョン：）	
- Eclipse201812	
  - インストールプラグイン

# ◆ハマった個所
- Kotlin
 - Cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6
https://stackoverflow.com/questions/48988778/cannot-inline-bytecode-built-with-jvm-target-1-8-into-bytecode-that-is-being-bui

 - Kotlin+Spring Bootにて「@Configuration class may not be final」的なエラーが出たとき
https://qiita.com/n_morioka/items/7b4f8f96c85223cdb176
Kotlinの末尾再帰(tailrec)のサンプルコード

[Scalaの末尾再帰(tailrec)のサンプルコード - Qiita](https://qiita.com/suin/items/d648e035b3875086b14e)をKotlinに翻訳したもの。

```kotlin
interface Node
data class Directory(val name: String, val children: List<Node> = listOf()) : Node
data class File(val name: String) : Node

val fileTree =
        Directory("Users", listOf(
                Directory("alice", listOf(
                        File(".bashrc"),
                        Directory(".Trash"),
                        Directory("Desktop", listOf(
                                File("photo.jpg"),
                                File("document.docx"),
                                File("spreadsheet.xlsx")
                        ))
                ))
        ))

tailrec fun flattenFilesytem(tree: List<Node>, filenames: List<String> = listOf()): List<String> {
    val first = tree.firstOrNull()
    val rest = tree.drop(1)
    return when (first) {
        is File -> flattenFilesytem(rest, filenames.plus(first.name))
        is Directory -> flattenFilesytem(rest + first.children, filenames.plus(first.name))
        else -> filenames
    }
}

flattenFilesytem(listOf<Node>(fileTree))
//=> res27: kotlin.collections.List<kotlin.String> = [Users, alice, .bashrc, .Trash, Desktop, photo.jpg, document.docx, spreadsheet.xlsx]
```
お前らは危うく一生tapのすばらしさを理解せずに終わるところだった記事

みなさん、Rubyのtap, というメソッドをご存知だろうか。
tapは、Objectのメッソドで、ブロックを引数にとり、ブロックの引数にselfを渡すメソッドだ。

たとえば、以下のように動作する。

```ruby```
"aiueo".tap{|s| puts s} => "aiueo" 
```

ドキュメントを見たとき、多くの人が「は？tapとかwwwこれがどうやって約にたつの？wwww」

と馬鹿にしてスルーするだろう。

だが、馬鹿はお前らだ。tapほどすばらしいメソッドはない。

##tapの利用シーン1

以下のようなコードがある。

```ruby
u = User.new
u.name = 'taro'
u.age = 12
```

tapを使うと次のようになる。

```ruby
u = User.new.tap {|u|
  u.name = 'taro'
  u.age = 12
}
```

この処理のすばらしさは、ユーザーのプロパティーの初期化のスコープをtapのブロックに閉じる事で、どこまでが一体の処理かを明確にすることができる。

このケースのtapの本質は、tapされるobjectのコンテクストを意識させるスコープを作り出す事にある。

いまそこのrubyのコードに、あるオブジェクトを中心とした処理をひとまとめにしたメソッドを作ろうとしていないだろうか。

例えば、以下のようなケースだ。

```ruby
class User {
  def set_properties(name, age)
   this.name = name
   this.age = age
  end
}

u = new User()
u.set_properties(name, age)
```

これは、ユーザーのプロパティーをセットするという一連の処理にまとまりの感覚をもたせるためのメソッドだ。

しかし、そのような目的のメソッドなら、必ずしもメソッドをつくらなくとも、tap一つで見かけ上のscopeのまとまりを作れてしまう。

もう一度見てみよう。美しくはなかろうか。

```ruby
u = User.new.tap {|u|
  u.name = 'taro'
  u.age = 12
}
```


##ユースケース2 変数をスコープ内に埋め込んでグローバルから消し去る

どういうことか。

例えば、以下のように、ユーザーに紐づく写真を削除する処理を考えてみよう

```ruby

u = User.find_by(name: 'taro')
id = u.id
pictures = Picture.where(user_id: id)
pictures.each {|picture| picture.destroy }

```

しかし、この場合目的の処理はpictureの削除だけだ。そのためにグローバルな空間に3つも変数を持つ事になっている。ここでtapを使うと、変数をscopeの内側に入れこみグローバルから消し去ることができる。

```ruby
User.find_by(name: 'taro').tap {|u| 
  id = u.id
  pictures = Picture.where(user_id: id)
  pictures.each {|picture| picture.destroy }
}
```

どうだろうか。グローバルの変数が全て消えた。エレガントだ。

他にも、変数をスコープに閉じることで、変数名をシンプルにすることができる。

```ruby
  user_id = user.id
  Picture.save({parent_id: user_id})
  place_id = place.id
  Picture.save({parent_id: suer_id})

```

Tapを用いると、user_idとplace_idなど呼ばず、どちらもidで処理が出来るようになる。


```ruby
   user.id.tap {|id|
      Picture.save({parent_id: id})
   } 
   place.id.tap { |id|
      Picture.save({parent_id: id})
   }
```

##以上がtapの使い道

上で説明したことをまとめると、tapの使い道は
1. 変数をscopeの中にとじる
2. 対象のオブジェクトのコンテクストを意識したブロックを作り処理のまとまりを表現する

とても重要な役割を持つ。

tapが何もしない愚か者に見えるのは、お前らが愚鈍だからということが分かっただろう。

これからtapに敬意を払っていきよ。
Sageを使うには？WordPressテーマのモダン開発フロー

# 2019年の記事
WPを使うなら、スターターテーマの「Sage」を使いたい。
https://roots.io/sage/

これから手順を説明します。

## 隠しファイル見えるようにする。
定番ですが、最初に設定しておく。

```terminal:terminal
$ defaults write com.apple.finder AppleShowAllFiles TRUE
$ killall Finder
```

## ディレクトリ名をフルパス表示にしておく。
定番ですが、最初に設定しておく。

```terminal:terminal
$ defaults write com.apple.finder _FXShowPosixPathInTitle -boolean true
$ killall Finder
```

## Homebrewをインストールする
定番なので、とりあえずインストールする。

```terminal:terminal
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
## Node.jsをインストールする
バージョン管理はNodebrew以外にもいろいろありますが、
ここではnodebrewを使います。

```terminal:terminal
$ brew install nodebrew
```
## nodebrewでバージョン管理
インストールできる

```terminal:terminal
$ nodebrew install-binary 8.3.0
```

「そんなディレクトリはありません」といわれる場合は、書き込み権限がない場合がある。
権限設定キチッとやるか、先にフォルダ作っておく。フォルダ作ったほうが早い。

```terminal:terminal
$ mkdir .nodebrew
$ mkdir .nodebrew/src
$ mkdir .nodebrew/src/v8.3.0
```

ディレクトリができたら `Node.js`をいれていく

```terminal:terminal
$ nodebrew install-binary 8.3.0
```

一応、比較用に最新の `Node.js` も入れておく。

```terminal:terminal
$ nodebrew install-binary latest
```

インストールされている `Node.js` の一覧を見る

```terminal:terminal
$ nodebrew list
v8.3.0
v11.9.0
current: none
```

8.3.0を使う場合は？

```terminal:terminal
＄ nodebrew use v8.3.0
```

バージョンが切り替わっていることを確認する

```terminal:terminal
$ nodebrew list
v8.3.0
v11.9.0
current: v8.3.0
```

## パスを通す
いちいちディレクトリを書かなくていいように、「パスを通す」という儀式がある。
まずはファイルをつくる。 `/User/YourName/` 直下につくります。

```terminal:terminal
$ touch .bashrc
```

この `.bashrc` というファイルをテキストエディタで開く。
これをコピペします。意味は `Nodebrew` のパスはここを見ますという意味です。

```bash:.bashrc
#!/bin/bash
export PATH=$HOME/.nodebrew/current/bin:$PATH
```
保存する。

```terminal:terminal
$ source ~/.bashrc
```
これでパスが通りました。（意味がわかるのに半年くらいかかる）

## Yarnを入れる
`yarn` は「node_modules」のパッケージマネージャです `npm` でもいいです。

```terminal:terminal
$ brew install yarn
```


## Composerをインストールする
PHPのパッケージ管理をする。

```terminal:terminal
$ brew install composer
```

## テーマファイル置く所へ移動する。
この例は `MAMP` で書いてあります。

```terminal:terminal
$ cd /Applications/MAMP/htdocs/sample/wp-content/themes
```

## プロジェクトを作る。
composerで作ります。ためしに `sage-sample` という名前のプロジェクトを作成します。

```terminal:terminal
$ composer create-project roots/sage sage-sample
```
このあと、いろいろ対話形式で設定をしていけます。Bootstrap4などを
入れることも可能です。

## ビルドする
YARNでコンパイルなどの処理を行います。

```terminal:terminal
$ cd sage-sample
$ yarn build
```

これでWordPressテーマの作成が開始できます。
yarnが一連のコンパイル処理を行ってくれるので、Sassで書けます。
KotlinのList Destructuring

Scalaでは分解(destructuring)を使って、与えられたリストか最初の要素を取り出しつつそれ以降のリストを新たに作ることができる:

```scala
scala> val List(first, rest @ _*) = List(1, 2, 3)
first: Int = 1
rest: Seq[Int] = List(2, 3)
```

調べた限りKotlinはというとこういう分解の構文がないらしい:

```kotlin
>>> val (a, b*) = listOf(1, 2, 3)
error: expecting ')'
val (a, b*) = listOf(1, 2, 3)
         ^
error: property getter or setter expected
val (a, b*) = listOf(1, 2, 3)
```

ちょっと遠回りだけど似たような書き方はこうなる:

```kotlin
>>> val (first, rest) = Pair(list.firstOrNull(), list.drop(1))
>>> first
res4: kotlin.Int? = 1
>>> rest
res5: kotlin.collections.List<kotlin.Int> = [2, 3]
```
デバッグ用の署名証明書 SHA-1 の取得方法

<h1>SHA-1の取得方法</h1>
Flutter×Firebaseでチャットアプリを作ろうとしていた時に、
Androidのプラットフォームの登録の際にSHA-1が必要になったので、
それの取得方法を備忘録的に書くことにした。

```terminal:terminal
keytool -exportcert -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
```

これでイケた。keystoreの場所は各自のPathの場所で。
パスワードの初期値は「android」らしいです。

以上。
(2019/02/05)

---
Go1.11でのDockerの設定

golangも気づけばv1.11.5になっていまして、昔使ってたDockerfileのままでは動かなくなってるものなどがありました。
なので備忘録としてDockerfileの設定を載せておきます。
もし、こんなやり方があるよというのがあれば是非コメントしていただきたいです。

## 本番用

以下のような感じになります。

```Dockerfile:Dockerfile
FROM golang:1.11 AS builder

ENV CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64 \
    GO111MODULE=on

COPY go.mod go.sum /
RUN go mod download

WORKDIR /go/src/github.com/path/to/project
COPY . .

RUN go build -o app


FROM alpine

COPY --from=builder /go/src/github.com/path/to/project/app /app

EXPOSE 8080
ENTRYPOINT ["/app"]
```

multi stage buildをしています。
これによって最終的なイメージサイズがかなり小さくなります。

重要な部分は

```Dockerfile
ENV GO111MODULE=on

COPY go.mod go.sum /
RUN go mod download
```

上の部分です。先に`go mod download`をすることでキャッシュが効かせられるので、新しい必要なライブラリが無ければgoファイルの変更後のビルドの時間を短縮することが出来ます。

`COPY go.mod go.sum /`をするためには予めローカルでgo.modとgo.sumを作っておく必要があります。

```bash:bash
$ go version
go version 1.11.5
$ export GO111MODULE=on
$ go mod init
$ go mod download
```

で`go.mod go.sum`が作成されると思います。


## 開発環境用

一応開発環境用の設定も載せておきます。

```Dockerfile:Dockerfile
FROM golang:1.11

ENV GO111MODULE on

COPY go.mod go.sum /

RUN go mod download && \
    go get github.com/oxequa/realize

WORKDIR /go/src/github.com/path/to/project
COPY . .

CMD realize start --run
```

開発時には[oxequa/realize](https://github.com/oxequa/realize)を使ってます。
realizeはGoのファイルの変更を感知して、リロードしてくれるライブラリです。Dockerでやるにはvolumeをするのを忘れないでください。

```sh:bash
$ docker run -v $PWD:/go/src/github.com/path/to/project image名
```

ちなみに[pilu/fresh](https://github.com/pilu/fresh)というライブラリもあります。
その場合は、上のDockerfileの該当箇所を合わせて直してください。
ドメインオブジェクトからプレゼンテーション層で使うDTOへの値の詰替え


クソ記事投稿週間な今日この頃です。
業務でScalaを使っているのでコードはScalaです。ご了承ください。

## 検討対象のコード

ドメイン層で以下のようなクラスが定義されているとしたときに、
セッターはもちろんのこと、**ゲッターを禁止にするために、属性に`private`がついている前提**であったとします。

```scala
/**
  * 顧客クラス
  *
  * @param name 名前
  * @param age 年齢
  * @param address 住所
  */
case class Customer(private val name: Name, private val age: Age, private val address: Address) {
  // TODO 様々なふるまいが定義されいている
}

case class Name(private val first: String, private val last: String)
case class Age(private val value: Int)
case class PostalCode(private val value: String)
case class City(private val value: String)
case class Address(private val postalCode: PostalCode, private val city: City)
```

アプリケーション層のアプリケーションサービスでプレゼンテーション層に値を返すために、以下のようなクラスが定義されています。

```scala
/**
  * レスポンス用のクラス
  * DTO(Data Transfer Object)
  * ドメインの知識を流用させたくないので、ただの値の入れ物になっている
  */
case class Response(firstName: String,
                    lastName: String,
                    age: Int,
                    address: String)
```

このような場合に、下記のドメインモデルのオブジェクト`Customer`を`Response`に変換するための`domainModelToResponseModel`メソッドをどう実装するのがシンプルかを少し考えました。

```scala
// アプリケーションサービス
object SomeAppService {
  def execute(): Response = {

    // TODO 何かしらの処理がここに入る

    val alice = Customer(
        Name("チョコミント", "クソ野郎"),
        Age(99),
        Address(PostalCode("888-8888"), City("HappyTown")))

    // ドメインモデルをResponse用のDTOに詰めかえる
    // このメソッドの実装について考える
    domainModelToResponseModel(alice)
  }
```

## 考えた結果

**ドメインオブジェクトの属性の`private`修飾子を外してしまうと、ゲッター使い放題を許可してしまうことになる**ので、

**アプリケーション層→プレゼンテーションへの値の詰替え限定**でケースクラスに実装されている`unapply`メソッドを利用するのがいいのかなと思いました。

値の詰替えをする`domainModelToResponseModel`メソッドは以下のようになりました。

```scala
  /**
    * ドメインオブジェクトからレスポンス用のオブジェクトに変換する
    * アプリケーションサービスに定義
    *
    * @param customer ドメインオブジェクトのCustomer
    * @return レスポンス用のオブジェクト(DTO)
    */
  private def domainModelToResponseModel(customer: Customer): Response = {
    // ケースクラスのunapplyメソッドを使って値を取り出す
    val Customer(
    Name(firstName, lastName), 
    Age(age), 
    Address(PostalCode(postalCode), City(city))) = customer

    val address = s"$postalCode $city"
    Response(firstName, lastName, age, address)
  }
```

ついでにファーストクラスコレクションもこんな感じに取り出せます。

```scala
/**
  * Customerのファーストクラスコレクション
  */
case class Customers(private val customers: Set[Customer]) {
  def nonEmpty: Boolean = customers.nonEmpty
  def empty: Boolean = !nonEmpty

  // TODO 様々なふるまいが定義されている
}

val Customers(values) = customers

values.map { customer =>
  val Customer(
  Name(firstName, lastName),
  Age(age),
  Address(PostalCode(postalCode), City(city))) = customer

  val address = s"$postalCode $city"
  Response(firstName, lastName, age, address)
}
```

他の言語だと値の詰替えってどのように実施するのだろうかということが疑問に残りました。単純に考えると、ゲッターぐらいしか思い浮かばなかったです。。
docker-composeでWordPress

## Docker Desktop をダウンロードする。

念の為、docker IDも取得する
https://hub.docker.com/editions/community/docker-ce-desktop-mac
インストールして、実行して、
ツールバーの右上に、クジラのマークが出たら起動。


Dockerがダウンロードされ、動いているかどうか確認。
docker compose も同時にインストールされていると思うので

```terminal:terminal
$ docker compose -v
docker compose version 1.23.2, build 1110ad01
```

ちゃんと動いていればバージョンが出てくる。

## プロジェクトのディレクトリをつくり、そこに入る。

```terminal:terminal
$ mkdir my_wordpress
$ cd my_wordpress/
```

## docker-composeファイルを作り、エディタで開く

```terminal:terminal
$ touch docker-compose.yml
$ vi docker-compose.yml
```

## docker-compose.ymlを編集する
設定ファイルですが、コピペでいける。これはMySQLとWordPressです。

```terminal:docker-compose.yml
version: '3.3'

services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
       WORDPRESS_DB_NAME: wordpress
(ここまだ未検証↓)
   phpmyadmin: 
     image: phpmyadmin/phpmyadmin 
     links: - mysql:mysql 
     ports: - 9191:80 
     environment:
       MYSQL_USERNAME: root 
       MYSQL_ROOT_PASSWORD: pw
       PMA_HOST: mysql
(ここまだ未検証↑)
volumes:
    db_data: {}
```

viで開いた場合は `Ctrl+C` で編集から抜けて `:wq` で保存して閉じる。

## コンテナを立ち上げる
２つのコンテナを同時に立ち上げる。立ち上げた状態を見ておく。

```terminal:terminal
$ docker compose up -d
$ docker compose ps
```

## ブラウザで開く
動いている。
http://localhost:8000
GCP認定資格Professional Cloud Architectを取得したので振り返る

#当記事について
[Google Cloud認定資格 Professional Cloud Architect](https://cloud.google.com/certification/cloud-architect?hl=ja)へ暫定ですが合格したのでどのようなトレーニングをしたのかを振り返ります、

#概要

##筆者スペック
Google Cloud Platformを使って一年程度たちます。ただし、App Engine・Compute Engine・BigQuery等の特定のサービスを個人的に使用しているだけで実業務での経験はありません。
AzureとAWSに関しても同じくらいのレベルです。

##トレーニング時間
2018年末に受験を決意してトレーニングを開始しました。丸一か月と二週間程度トレーニングしております。概ねトレーニングにかかった時間は以下の通りです。曖昧な部分もありますので、概ねの目安としてとらえてもらえれば幸いです。

| 項目      | 時間 |   
|-----------------|------------------:|
|書籍によるトレーニング|4時間|
|公式ドキュメントによるトレーニング|5時間|
|実機を使ったトレーニング|2時間|
|模擬試験の受験|1時間|
|活用事例によるトレーニング|3時間|
|Qiitaへのアウトプット|6時間|
|**合計**|**21時間**|

##トレーニングと理解度の遷移
隔週のトレーニング内容と理解度を振り返れるように記事にまとめてあります。これから受験される方の参考になれば幸いです。
[第１回](https://qiita.com/shuichiro/items/a87f021f05fb8d558756)
[第２回](https://qiita.com/shuichiro/items/97e11704c46b10831cca)
[第３回](https://qiita.com/shuichiro/items/fe243a3e00a0965991a4)
[第４回](https://qiita.com/shuichiro/items/992fe9396e30967d5d17)
[第５回](https://qiita.com/shuichiro/items/9b7427fe82127166be60)
[第６回](https://qiita.com/shuichiro/items/a3ad0d4efbbdb2f0f7ca)

#トレーニング内容
##書籍によるトレーニング
[Google Cloud Platform　エンタープライズ設計ガイド](https://www.amazon.co.jp/Google-Cloud-Platform-%E3%82%A8%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%97%E3%83%A9%E3%82%A4%E3%82%BA%E8%A8%AD%E8%A8%88%E3%82%AC%E3%82%A4%E3%83%89-%E9%81%A0%E5%B1%B1-%E9%99%BD%E4%BB%8B-ebook/dp/B07C85YMCW/ref=sr_1_1?s=books&ie=UTF8&qid=1545889959&sr=1-1)を使用してトレーニングを行いました。GCPのサービスについて網羅的に書かれているため非常に役に立ちました。


##公式ドキュメントによるトレーニング
上記書籍になかったサービスを[公式ドキュメント](https://cloud.google.com/docs/?hl=ja)を読むことでトレーニングを行いました。サービス概要とコンセプトのみ読みました。

##実機を使ったトレーニング
使ったことのないサービスは実際に実機で動かしてみて理解を深めました。公式ドキュメントのクイックスタートを実施し、後追いでソースを眺めてトレーニングを行いました。
ただし、Spanner等の料金がかさみそうなサービスは実機では行いませんでした。

##模擬試験の受験
書籍のトレーニングが終わったところで[模擬試験](https://cloud.google.com/certification/practice-exam/cloud-architect?hl=ja)を受けてみました。正答率は50%程度でした。無料で受けられるのはありがたいです。
出題のされ方と自分の弱いところが解ったので、書籍や公式ドキュメントを読みなおしました。

##活用事例によるトレーニング
総仕上げで[GCP活用事例](https://cloud.google.com/customers/?hl=ja)を読み、アーキテクチャ図が無ければ自分で書いてみました。こちらは回答の無いものですが、課題と解決するためのソリューションを考えるのに非常に役に立ったと思っています。

##Qiitaへのアウトプット
何気にこれが一番時間かかっていますが、とても役に立ちました。
アウトプットを整理することで自分がどこまで理解していて、何が足りないのかが明確になります。特にトレーニング序盤にサービス一覧を作成できたのは網羅率が一目瞭然になったので自身のやる気にも繋がり非常に良かったです。

#試験当日
##復習方法
試験当日は自分でQiitaにまとめた[サービスの一覧](https://qiita.com/shuichiro/items/9b7427fe82127166be60)をスマホで確認しつつ復習しました。
##試験本番
試験時間は2時間、問題数は50問です。
架空の会社の課題解決からサービスの知識を問う問題まで色々と出題されます。特にGoogle Kubernetes Engine（GKE）に関する問題が多かった気がします。

サービスの知識を問う問題では「Datalabにデータの編集機能は無いよね」や「Transfer Applianceってそいういうサービスじゃないよね」的なひっかけ問題が多く、きちんとトレーニングしておけば正解できるものが多かったです。


#最後に
正直、合格できて安心しています。
トレーニングを進めつつアウトプットをする手法を始めて試してみましたが結構良いですね。頭の中がクリアになるので非常にお勧めです。
ezbook X1 Gemini Lake N4100 4GB DDR4 128GB のWifi…

![image.png](https://qiita-image-store.s3.amazonaws.com/0/213689/c7398e96-b2cd-0310-e4ca-e97649561ba4.png)

２万円台で買えるノートパソコンだったので買ってしまいました。
購入後、すぐにSSDを入れ替えてUbuntuやCentOSをインストールしましたが、まったくWifiが認識されてない。
lsmodやネットワーク関係の確認コマンドを打ってもそもそもWifiを認識してない。

Windowsで認識するのかどうか確認のためにSSDを入れてみた。
なんで普通に認識してるんだろう…

`intel(R) Dual Band Wireless-AC3165` というチップらしい。
やっぱりインテルだとLinuxやらDebian系のOSではだめなのかなあ…。

----
（2019/02/09追記）
intel のgemini lakeのCPUなので、
もしかしたらkernelが追いついてないのか？
と思ってソースコードを調べてみた。

https://www.kernel.org/
現在このノートPCのKernelバージョンは4.18。（Ubuntu1810）
4.20が安定版としてリリースされてるようすでした。

```
~/code/backport-iwlwifi$ git grep 3165
drivers/net/wireless/intel/iwlwifi/Kconfig:             Intel 3165 Wi-Fi Adapter
drivers/net/wireless/intel/iwlwifi/cfg/7000.c:#define IWL3165_NVM_VERSION               0x709
drivers/net/wireless/intel/iwlwifi/cfg/7000.c:const struct iwl_cfg iwl3165_2ac_cfg = {
drivers/net/wireless/intel/iwlwifi/cfg/7000.c:  .name = "Intel(R) Dual Band Wireless AC 3165",
drivers/net/wireless/intel/iwlwifi/cfg/7000.c:  .nvm_ver = IWL3165_NVM_VERSION,
drivers/net/wireless/intel/iwlwifi/iwl-config.h:extern const struct iwl_cfg iwl3165_2ac_cfg;
drivers/net/wireless/intel/iwlwifi/pcie/drv.c:/* 3165 Series */
drivers/net/wireless/intel/iwlwifi/pcie/drv.c:  {IWL_PCI_DEVICE(0x3165, 0x4010, iwl3165_2ac_cfg)},
drivers/net/wireless/intel/iwlwifi/pcie/drv.c:  {IWL_PCI_DEVICE(0x3165, 0x4012, iwl3165_2ac_cfg)},
drivers/net/wireless/intel/iwlwifi/pcie/drv.c:  {IWL_PCI_DEVICE(0x3166, 0x4212, iwl3165_2ac_cfg)},

```
とりあえず新しいものだったら入っているみたい。

Kernelのバージョンアップをやってみようと、以下のサイトを参考にさせていただきました。
[Ubuntuのベースバージョンを変えずにLinuxカーネルをアップグレードする方法](https://iberianpig.github.io/posts/2017-02-06_how_to_upgrade_kernel/)
マウスポチポチでKernel入れ替えられるのってすごいですね。

このツールで、Kernelを4.20.7にしましたが、
`lshw -C network` でも、`iwconfig`でもまったくWifiが表示されない…。

詰んだ。(　；∀；)どうしようこれ。

---
（2019/02/24追記）
気になる記事を見つけた。
[Jumper EZBook X1レビュー＆動画 実は廉価版Teclast F5だった!](https://koro-tech.com/gaget/jumper-ezbook-x1)

`Linux Mintでは、タッチパネルとBTは動作しないが、
Antegrosのリナックス・ディストリビューションであれば動作するらしい`

linuxmint-19.1とantergos-19.2-x86_64のインストールを試したけど、
Wifiはno deviceでした…。

windows10だと認識するのにね。。。
iOSのPWAはSNSログインが出来ないので今だに使い物にならないという話

(注: ここでいうPWAとは、ホーム画面に追加することでアプリのように使える機能のことを言います。)

PWAはWeb開発者にとって魅力的な技術であることは間違いなく、積極的に導入していきたいものです。

AndroidのPWAはかなり進歩していて、バグもほとんどありません。そのために[ネコチャ](yurubo.me)でもAndroidはPWAをサポートしています。
## iOSのPWAはSNSログインが出来ないので今だに使い物にならないという話

しかし、問題なのはiOSのPWAです。
iOSのPWAにはSNSログイン(OAuthログイン)にバグが生じるという、Webサービスにとって致命的なバグが存在します。

どうやらプロバイダーからのコールバックを上手く処理することが出来ないようでです。

現状では、SNSログインがあるWebサービスはPWA化は諦めた方が良いでしょう。

[ネコチャ](yurubo.me)では、端末がiOSだと判断した場合はmanifest.jsonファイルへのリンクを消すという方法でiOSでPWAが起動するのを防いでいます。

iOS12.2からはPWAのサポートが強化されるという発表があるので楽しみです。
## 終わりに
私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
        [無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話](https://note.com/kenroda/n/n814347fbdcd7)
（備忘録）Raspbian JessieにCakePHP3をインストールする際に追加インストールしたモジュール

```sh
sudo apt install php7.1-intl
#ext-mbstring
sudo apt install php7.1-mbstring
#ext-dom
sudo apt install php7.1-xml
#DebugKit not enabled. You need to either install pdo_sqlite
sudo apt install php7.1-sqlite3
```
なお、Debian系の場合、php.iniを編集してexpensionの記述を追記する必要は無い。
むしろ、不具合を起こしComposerが動作しなかった。
pythonのread_csvでエラーが出るときの対処法

# 目的
pythonでcsvファイルを読み込む時にpandasのread_csvを使用するが、
エラーがよく出るので対処法をまとめる。

今回はエラーの中身については深く言及せず、考えられる原因とその対処法についてのみ説明する。

## 考えられる主な原因
１、ファイル名が日本語
２、csvファイルの中身に読み取れない文字がある

### １、ファイル名が日本語
ファイル名を保存する際に、日本語で
**東京の天気.csv**
のように保存することがあると思う。

この時にたまにエラーが出る。
その対処法は、

```python
import pandas as pd
pd.read_csv('東京の天気.csv', engine='python')
```
と、engineをpythonに指定すれば解決するかもしれない。

### ２、csvの中身に読み取れない文字がある。
ファイルに指定されている文字コードでは読み取れない文字が入っている場合、エラーが出る。
対処法としては、
１、文字コードを指定する
２、エラーを無視する
の２通り。

１、文字コードを指定する

```python
pd.read_csv('test.csv', encoding='sjis')
```
または

```python
pd.read_csv('test.csv', encoding='cp932')
```

を試す。

それでもダメな場合は、
２、エラーを無視して、無理やりsjisで読み込む。

```python
import codecs as cd
tmp = cd.open('test.csv', 'r', 'sjis', 'ignore')
pd.read_table(tmp)
```

これでもダメな場合は、他に原因があることが多い。
例えば、ファイルの指定場所が間違い、.csvをつけ忘れ、等の凡ミスも疑う。


以上です。
間違いがあればご指摘ください。
CSVファイルを合成する


## ２つのCSVファイルを合成します。

base.csvファイルのキーになるカラムに一致するレコードに対して、
置き換えるカラムに指定されたカラムをreplace.csvファイルの内容に置き換え、
output.csvファイルに書き出す。

*独学プログラマーを読んで初めて作ったPythonのコードなので許してください・・・*

```python:replacecsv.py
# ２つのCSVファイルを合成する

import csv

# キーになるカラム番号
key = 0

# 置き換えるカラム番号
col = 1

data = []

with open("base.csv", "r") as fbase:
    rbase = csv.reader(fbase)
    with open("replace.csv", "r") as fin:
        rin = csv.reader(fin)
        for rowbase in rbase:
            for rowin in rin:
                if rowbase[key] == rowin[key]:
                    rowbase[col] = rowin[col]
                    break
            # print(rowbase)
            data.append(rowbase)

with open("output.csv", "w") as fout:
    wout = csv.writer(fout)
    for wrow in data:
        wout.writerow(wrow)

```
ntpdで「restrict ::: KOD does nothing without LIMITED.」という警告メッセージが出力された際の対応


Debian 9にてntpd 1:4.2.8を使用した際に、ntpd起動時に下記の警告メッセージが発生したので、その場合の対処の一例を記載。

<pre>
ntpd[521]:  restrict 0.0.0.0: KOD does nothing without LIMITED.
ntpd[521]:  restrict ::: KOD does nothing without LIMITED.
</pre>

confを下記のように変更したところ、警告メッセージが発生しなくなった。

<pre>
view /etc/ntp.conf

restrict -4 default kod notrap nomodify nopeer noquery
restrict -6 default kod notrap nomodify nopeer noquery

↓ 上記の箇所を下記のように変更。

restrict -4 default kod notrap nomodify nopeer noquery limited
restrict -6 default kod notrap nomodify nopeer noquery limited

</pre>
UnityでHoloToolkitのSharing機能を使ってボイスチャットする方法

# 概要
MicrosoftがHoloLens用に提供しているUnityツール「HoloToolkit」を使ってボイスチャットを作ってみます。
情報が少なくハマったのでポイントを整理しておきます。


# 全体構成
ローカルネットワーク内でボイスチャットを実現します。
それぞれ以下のIPアドレスが割り振られているとします。
![voicechat.png](https://qiita-image-store.s3.amazonaws.com/0/225840/eac37f49-9712-319a-03e8-ac632a7e69a2.png)


# 動作確認環境
- Windows 10
- Unity 2017.4.17f
- HoloToolkit 2017.4.3.0



# Unityの設定
以下URLのHoloToolkitのHoloToolkit-Unity-2017.4.3.0.unitypackageをダウンロードします。
https://github.com/Microsoft/MixedRealityToolkit-Unity/releases

これをUnityのプロジェクトにImport Assetしてください。



# Sharingの設定
HolotoolkitのAssetからSharingプレハブを探してシーンに追加します。
また、AutoJoinSessionAndRoomスクリプトをアタッチしてください。

次にSharingStageスクリプトのServer Addressをサーバを起動するIPアドレス（192.168.0.10または.20）に設定します。
ただし、サーバを起動しているPC上で動かすのであればlocalhostでも大丈夫です。
![sharing.png](https://qiita-image-store.s3.amazonaws.com/0/225840/978db53f-6413-9a46-ec46-f120d6c11a8d.png)

IsAudioEndpointにチェックが入っているかも確認しておきましょう。

# MicrophoneTransmitterとMicrophoneReceiverの設定
**ここで一番ハマりました。**
HolotoolkitのボイスチャットライブラリであるMicrophoneTransmitterとMicrophoneReceiverをCameraにアタッチすればOK！
と思ったのですが、これだと自分の声が聞こえてくるだけで相手の声が聞こえません。

この問題は各所で議論されていますが解決法が見つかりませんでした。
https://github.com/Microsoft/MixedRealityToolkit/issues/72
>**[branchbark](/branchbark) ** commented [on 10 Mar 2017](#issuecomment-285567128)
Can we do voice commands if we are streaming audio?
I'm having trouble transmitting/receiving any voice at all. I can only hear myself when I speak however I am unable to hear others who have joined the app and they cannot hear me. Other users during the shared experience report the same experience.

https://forums.hololens.com/discussion/7788/voicechat-in-holotoolkit-sharing
> WANGJUN ✭ September 2017
I also have problems by using two scripts(MircrophoneTransmitter.cs,MicrophoneReceiver.cs). My Problem is that I can hear my own voice,also others voice

結論としては非常に簡単で、MicrophoneTransmitterとMicrophoneReceiverを別々のGameObjectにアタッチすればよいだけでした。
それぞれがAudio Sourceにアクセスするので、同じGameObjectだと競合してしまうためだと思われます。

そこでCameraの下に2つ空のGameObjectを作成して、それぞれに上記スクリプトをアタッチしましょう。
![microphone.png](https://qiita-image-store.s3.amazonaws.com/0/225840/8d72d940-1230-8d61-8f9c-3fc01cffa05d.png)

# SharingServerの起動
この手順はどちらか一方のPCで行ってください。
以下URLのHoloToolkitのSource Codeをダウンロードします。
https://github.com/Microsoft/MixedRealityToolkit-Unity/releases

解凍してコマンドプロンプトで以下を実行してください。

```
cd [解凍フォルダ]\External\HoloToolkit\Sharing\Server
SharingService.exe -local
```
※フォルダ構成はバージョンにより異なります。

これで音声を中継するサーバが起動できました。
コマンドプロンプトにサーバアドレスが表示されれば起動に成功しています。



# Unityアプリの起動
それぞれのUnityアプリを起動すると自動でボイスチャットが開始されます。
SharingServerの画面に以下のようなメッセージが表示されていれば、サーバへの接続が成功しています。

```
SharingService: Created Session "DefaultSession" with ID 1 on port 20600
SharingService: User XXX at address 192.168.0.10 joined session DefaultSession
```

以上の手順で、それぞれのPCのマイクから入力した音声がもう一方のPCのスピーカから再生されます。

# トラブルシューティング
サーバへの接続ができない場合などは、アンチウイルスソフトが通信を遮断していないか確認してみましょう。
わからなければソフトを無効にして試してみてください。


# Future work
とりあえずUnityプレイヤーでの動作を確認しました。
今後はHoloLensやその他プラットフォームで利用できるか確認する予定です。
また、ローカルネットワークではなくWANで使えるかも検証したいです。

→（追記）HoloLensでの動作を確認しました。
ただしScripting Backendが.NETじゃないとだめみたいです。
https://github.com/Microsoft/MixedRealityToolkit-Unity/issues/2531
Certified Jenkins Engineerになった

Certified Jenkins Engineer (認定Jenkinsエンジニア)になりました。

調べてもあまり先駆者の情報が出てこなかったこともあり、Qiitaデビューがてら記録を残したいと思います。

下記は2019年1月に私が受験した時点での情報です。公式の情報が最新だと思いますので、受験時は必ずそちらを確認してください。

# 試験概要

- 主催：CloudBees社
- 受験場所：Kryterionのテストセンター
- 受験料：$150
- 設問数：60問
- 合格ライン：40問 (66%)
- 試験時間：1時間半

ちなみにCertified CloudBees Jenkins Engineerという資格もありますが、こちらはCloudBees提供の有償版のJenkins、いわゆるJenkins Enterpriseに関する資格です。

# 公式提供資料

試験に必要な情報はこちらの[公式ページ](https://www.cloudbees.com/jenkins/jenkins-certification)から入手できます。

Study Guideに出題範囲や出題比率、例題など掲載されているため必読です。ただ後述の通り範囲はかなり広く指定されているので全部を網羅するのは難しいです。

FAQは試験の概要を知る上でも一通り読むことをお勧めします。

# 試験勉強

出題カテゴリは以下の4つです。

1. Key CI/CD/Jenkins Concepts
1. Jenkins usage (features and functionality)
1. Building Continuous Delivery (CD) Pipelines
1. CD-as-Code Best Practices

CI/CDの概要や考え方などを形式的にどう学ぶかというのは難しいですが、ソフトウェアエンジニアとしてCI/CDに関わりがあるのであれば特に問題となるレベルではないと思います。

問題なのはJenkinsの機能についてで、これは「〇〇を実現するにはどうするか」「〇〇な設定でどういう挙動になるか」といったかなり具体的な設問がでます。普段Jenkinsを使っているだけでは触れていない機能もあると思うので、Study Guideを見ながら勉強することが重要です。ただ、Study Guideに挙げられている項目は非常に多いので、ある程度絞って取り組むことにはなると思います。
個人的にはPipeline、Security、REST API、Fingerprints、Artifactsあたりは一通り確認しておいてよかったなと思いました。
また、Jenkinsの管理者/利用者の双方の観点からの出題があるので、普段どちらか一方でしかJenkinsに触れていない場合は注意が必要です。

勉強はやっぱり直接触るのが一番なので、私は勉強用のJenkinsを立てていじってました。
Docker Hubから[公式イメージ](https://hub.docker.com/r/jenkins/jenkins/)を引っ張ってくれば一瞬で環境構築できます。またブラウザ設定を英語にすれば英語表記になるので試験と対応のとれた用語で勉強できます。ビルド用のソースはGitHubのプライベートリポジトリに入れておけばやりたい放題です。

最後に、英語ですが語彙も普段目にするようなレベルですし、制限時間も余裕があるので英語が問題になるようなことはなかったです。

# 受験

テストセンターで受験します。ここまでくればパソコンで画面に表示される選択式の問題を淡々と解くだけです。

手ごたえがあったわけではないですが、わりと余裕で合格できていました。

合格すると認定証が掲載されたページのURLがメールで送られてきます。

自分もJenkinsおじさんになったんだなと感慨深い気持ちになれます。

# まとめ

Jenkinsが使える、CI/CDやDevOpsの最低限の知識を持っているということの証明によいのではないのかと思います。自分としても知識の振り返り、新しい知識の習得の両方でよかったと思います。

もっとJenkinsおじさんを日本に増やしましょう。
【2019-2-5更新】MacBookを開発環境にするためにやったこと

# 概要
人生で初めてMacを買った。この喜びは大きい。
今まで、貧乏学生をやってきた私としては、思い切りの良い買い物だった。
また快く買わせてくれた妻に感謝を...

だからMacを最高の開発環境にしようと思った。
これはその備忘録である。

#1.Chromeをインストール
これは、別にMacだからやるわけではないが、個人的にはChromeが気に入っている。
以下からダウンロード

https://www.google.com/intl/ja_ALL/chrome/

#2.iterm2
デフォルトのターミナルでも良いがせっかくなのでiTerm2を入れる。

https://www.iterm2.com/

#3.Ricty Diminished
プログラミング用のフォント

https://www.rs.tus.ac.jp/yyusa/ricty_diminished.html

#4.Homebrew
Linuxにドップリ使っていた私としては、別にパッケージ管理ソフトを入れるというのは新鮮。
（まぁ最近だとAppImageとかあるから不思議じゃないが）

https://brew.sh/

#5.Xcode
iPhoneやアプリ開発をするわけじゃないがせっかくなので入れておく。

https://developer.apple.com/xcode/

#6.Docker
Linuxだとあまり意識せず使っていたが、MacだとLinuxカーネルじゃないからDocker-Machineなる仮想環境上にLinuxが動いていてその上で実行するらしい。

https://docs.docker.com/docker-for-mac/install/

#7.Virtualbox
仮想化のソフト有料とか使っている余裕まではないので、Virtualbox
でも十分な気もする。

https://www.virtualbox.org/wiki/Downloads

#8.Atom
エディターとしてGUIリッチで使いたい時はAtomを使うことにした。

https://atom.io/

#9.Dash
有料だがよいAPI検索用スニペットマネージャー
昔、学生時代にこれを使いこなす社会人に憧れた記憶がある。

https://kapeli.com/dash

#10.Homebrew-cask
HomebrewのコマンドでMacAppがインストール可能とのこと。
先に知っていればよかった。

https://github.com/Homebrew/homebrew-cask

#11.Alfled3
ランチャーアプリ軽量かつ使いやすい

https://www.alfredapp.com/


#あとがき
正直ここまでではLinuxに開発環境構築する時と大差がない。
しかしまだまだ知らないMacの世界があるので試し次第更新していきたい。
SwaggerでLambdaのデバッグ環境を作る(2)：Helperライブラリを使ったLambdaの書き方

前回、SwaggerでLambdaのデバッグ環境を作りました。

　[SwaggerでLambdaのデバッグ環境を作る(1)](https://qiita.com/poruruba/items/e3a46787c79517a815f9)

入力パラメータの受け取り方を示しておきます。
また、Helperライブラリを作っていましたので、その使い方も補足しておきます。

# 入力パラメータ

GET呼び出しで取得するQueryStringは、以下のように受け取ります。

```javascript
var qs = event.queryStringParameters;
```

POST呼び出しで取得するBody部は、以下のように受け取ります。JSONである前提です。

```javascript
var body = JSON.parse(event.body);
```

(参考)
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format

# response.js

これは、JSON形式でレスポンスを返すのに有用なライブラリです。

例えば、以下のようにすると、引数にしたオブジェクトがJSON形式でクライアントに返されます。

定義。

```javascript
const HELPER_BASE = process.env.HELPER_BASE || '../../helpers/';
const Response = require(HELPER_BASE + 'response');
```

使い方。

```javascript
return new Response({ message : 'Hello World' });
```

または、

```javascript
var body = { message : 'Hello World' };
var response = new Response();
response.statusCode = 200;
response.set_body(body);
return response;
```

(参考)
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format

ちなみに、クライアントへJSONを返す方法として以下の方法があります。


```javascript
// ①
exports.handler = async (event, context, callback) => {
	return new Response({ message: 'Hello World' });
};

// ②
exports.handler = async (event, context, callback) => {
	callback(null, new Response({ message: 'Hello World' }) );
};

// ③
exports.handler = async (event, context, callback) => {
	context.succeed( new Response({ message: 'Hello World' } );
};
```

通常は、①か②の方法が使われるかと思います。ただし、①はexport.handlerにasyncを付けた場合だけ使うことができます。

(参考)
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/nodejs-prog-model-handler.html

# redirect.js

これは、クライアント側の表示ページを別のページに切り替えたい場合(リダイレクト)に使います。

定義。

```javascript
const HELPER_BASE = process.env.HELPER_BASE || '../../helpers/';
const Redirect = require(HELPER_BASE + 'redirect');
```

`response.js`の代わりに、以下のように使います。

使い方。


```javascript
exports.handler = async (event, context, callback) => {
	return new Redirect('https://www.google.com');
};
```

以上
React Navigationの画面の遷移を単体テストする時のメモ

**・Jest+Enzymeでテストしている想定**
**・TypeScript**

だいたいテストの流れは下のようになる。

##### 1) shallowで画面コンポーネントを作成

- navigationプロパティは`jest.fn()`で作成し、それぞれのメソッドをspyする。

```tsx

const navigation = jest.fn<NavigationScreenProp<any, any>(() => {
  navigate: jest.fn(),
  ...
});
const navigate = jest.spyOn(navigation, 'navigate');
const wrapper = shallow(<Hoge navigation={navigation} />);
```

##### 2) 画面コンポーネントのメソッドを直接呼び出し、その後spyしたメソッドが正しく呼ばれているか確認

```typescript
await wrapper.instance().hoge();
expect(navigate).toBeCalledWith('NewScreen'); // navigateメソッドが引数'NewScreen'で呼ばれた
```

##### ハマった点

- HoCを使っている場合
    - `wrapper.dive().instance()`でHoCの中にあるコンポーネントを取れる、と書いてる記事が散見されたが、私の場合はうまく取れなかった。そのためHoCで包んでいない素のコンポーネントを使ってテストを書いた。