OmniAICreator/Qiita-1.07M huggingface dataset:
clangd導入メモ

## clangdとは
clangの[Language Server Protocol](https://microsoft.github.io/language-server-protocol/) 実装。

LSPはMicrosoftが提唱しているIDE支援のための統一プロトコル。
Language "Server"とあるとおり、言語支援のためのサーバーが常駐する。この手の機構を個別に備えた言語として、TypeScriptのtsserverとか、C#のOmniSharpなどが挙げられるけど、それの汎用版。

clangdはLLVMのフロントであるclangをベースとしたサーバーで、LLVMプロジェクトが[公式に開発](https://clang.llvm.org/extra/clangd.html)している。
コンパイラなので、コンパイルエラーの検出はもちろん、コード補完やフォーマット、定義ジャンプと参照元ジャンプ等には対応している。
なので、clang-formatやRTagsといったclang系ツールも、LSPクライアントを導入してしまえば、これらの個別設定をしなくてよい。

## clangdのインストール

macだと、`brew install llvm` とかするとclangdもインストールされるらしい。未確認。
僕は未だにmacports使ってたせいか、知らんうちに手元に入ってた。`port install llvm-5.0` で勝手にインストールされるらしい。

LLVMのソースからビルドする場合は、 https://clang.llvm.org/get_started.html あたりを読むべし。clangdはclang-tools-extraに入ってるので、`svn co` するのを忘れずに。

インストールしたら、 `--version` で確認できるよ(以下はソースからビルドした版)。

```txt
$ clangd --version
> LLVM (http://llvm.org/):
>   LLVM version 6.0.0svn
>   Optimized build with assertions.
>   Default target: x86_64-apple-darwin16.7.0
>   Host CPU: broadwell
```

## エディタ側
### vim
vimの場合は汎用LSPクライントをインストールし、こいつにclangdのパスを教えてやる流れ。

LSPクライアントはいくつかあるんだけど、僕は https://github.com/prabirshrestha/vim-lsp を利用している。
他と使い比べたわけでもないんだけど、作者がMSの人だしLSP慣れてんのかなーと思ってこれ使ってる。

この人のpluginは vim / nvimの非同期周りを吸収するasync.vimってのが出てくるので、セットでインストールしておく。

```vim
Plug 'prabirshrestha/async.vim'
Plug 'prabirshrestha/vim-lsp'
```

```vim
let g:lsp_log_verbose = 1
let g:lsp_log_file = expand('~/vim-lsp.log')
call lsp#register_server({
    \ 'name': 'clangd',
    \ 'cmd': {server_info->['clangd']},
    \ 'whitelist': ['c', 'cpp', 'objc', 'objcpp'],
    \ })

" オムニ補完設定
autocmd FileType typescript setlocal omnifunc=lsp#complete
```

### VSC
LLVMが拡張作ってるので、これを入れるがよろし。

[vscode-clangd](vscode-https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd#overview)

また、user/projectの設定で、clangdの在処を直接指定することも可能。

```json
{
  "clangd.path": "/absolute/path/to/clangd"
}
```

## `compile_commands.json`

clangdにコンパイラオプションとかを教える場合、[`compile_commands.json`](https://clang.llvm.org/docs/JSONCompilationDatabase.html) を作って、カレントディクレトリなりに置くとclangdがよしなに探索してくれる。
または clangd起動時に `-compile-commands-dir` オプションで、jsonファイルの在処を教える、でもよい。

`compile_commands.json` を作る方法はいくつかある。

例えばcmakeの場合は下記のように、 `CMAKE_EXPORT_COMPILE_COMMANDS` を有効にしてcmakeを実行すると、出力される。

```sh
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 .
```

シンプルにMakefileのみのプロジェクトの場合、[Bear](https://github.com/rizsotto/Bear) を使う。

```sh
bear make
```


Bazelだと、

https://github.com/grailbio/bazel-compilation-database

とか

https://gist.github.com/bsilver8192/0115ee5d040bb601e3b7

があるようだが、きちんと確認してない。
Travis CIのOSXイメージでuser spaceにインストールしたpipが見つからない時のメモ

Travis CIのiOS用ビルドを手直ししているときにpipでawscliをインストールしたときにハマったのでメモ。

# 最初にやってたたこと
```bash
pip install --user awscli
export PATH=$PATH:$HOME/.local/bin
```

awsコマンドを呼ぶと127エラーでTravisが止まる。１２７エラーということはコマンドが見つからないということ。

# Site設定を確認する
`.travis.yml`に以下の`python -m site`を追加してsite設定を確認。

```bash
$ python -m site
sys.path = [
    '/Users/travis/build/hogehoge/mogemoge',
    '/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg',
    '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
    '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
    '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
    '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
    '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
    '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
    '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old',
    '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload',
    '/Users/travis/Library/Python/2.7/lib/python/site-packages',
    '/Library/Python/2.7/site-packages',
    '/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python',
    '/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC',
]
USER_BASE: '/Users/travis/Library/Python/2.7' (exists)
USER_SITE: '/Users/travis/Library/Python/2.7/lib/python/site-packages' (exists)
ENABLE_USER_SITE: True
```

実行可能ファイルは`USER_BASE`の下にある`bin`にあった。

# USER_BASE配下のbinをPATHに追加
`USER_BASE`は`python -m site --user-base`で取得できるので、それを利用してPATHの追加を以下のように変更。無事にawscliでバージョンが確認できた。

```bash
pip install --user awscli
export PATH=$PATH:$(python -m site --user-base)/bin
```

# まとめ
`$HOME/.local/bin`よりも今後は`$(python -m site --user-base)/bin`を使おうと思いました。
本当の本当に最低限のvimの使い方

#viの印象
viと聞くと、どんなイメージでしょうか？
使いやすい！最高！とか、いやEmacsの方が、、という方は対象にしておりませんのでより詳しいページをごらんください。

どちらかというと、何をしているのかわからない。できれば触りたくないという印象をお持ちの方向けです。
そうした方の場合、まずviを使う場面は、あるファイルをちょっとだけ編集したいというときではないでしょうか。たった１文字、１行書き加えたい。だけどviはよくわからない。そんな時に思いだしていただきたいことを最小限で書いてみます。

##viでファイルを開く
コマンドライン上で

```
vi　ファイル名
```
とすることでviがファイルを開いた状態で起動します。指定したファイルがなければ新規のファイルとなります。たまに何かの設定ファイルを開いたつもりなのにまっさらな画面が表示され、保存しても設定が変わらないときがあります。それはファイル名かディレクトリ名を間違えている可能性が高いです。

ディレクトリ名もファイル名も何文字か入力し<kbd>TAB</kbd>を押すと補完してくれます。補完されなかった場合は入力した文字で始まるファイルなどが複数あるということです。その状態で<kbd>TAB</kbd>をもう一度押すと該当する一覧が表示されます。

こうしてviを起動します。

##viのモード
ここがややこしいところですが、viはコマンドモードと挿入モードがあります。
起動時はコマンドモードになっています。ここでキーボードから色々なコマンドを入力することができますが、最低限覚えておけば良いのは　<kbd>i</kbd>、<kbd>w</kbd>、<kbd>q</kbd>、<kbd>ESC</kbd>の４つだけです。
モードの切り替えに使うのは
<kbd>i</kbd> はコマンドモードから挿入モードへ
<kbd>ESC</kbd>はコマンドモードへ映ります。
今、自分がどちらのモードなのかわからない場合はとりあえず<kbd>ESC</kbd>を連打しましょう。何回押してもコマンドモードになってくれます。

##カーソルの移動
viのカーソル移動方法について調べていくとたくさんのコマンドが出てきます。検索や行へジャンプなどありますが、それはまたで大丈夫です。今のviはカーソルが使えます！キーボードの上下左右カーソルでスクロールしながら変更したい箇所をさがしましょう。

##編集
変更したい箇所が見つかったら、<kbd>i</kbd>を押します。画面下部に
```
-- INSERT --
```
や挿入など表示されます。そうするともうなんでもできます。さらにカーソル移動するなり、<kbd>BACKSPACE</kbd>で１文字削除、<kbd>RETURN</kbd>で改行の挿入なりなんでもできます。必要な箇所を編集しましょう。

##保存して終了
作業が完了したら保存して終了です。これを行うときには一旦コマンドモードに入ります。
<kbd>ESC</kbd>を押して<kbd>:</kbd><kbd>w</kbd><kbd>q</kbd>
と入力します。最初のESCを押した時点で画面下部の -- INSERT --は消え、

```

:wq
```
と入力したものがそのまま表示されます。そこで<kbd>ENTER</kbd>を押します。そうするとうまくいけばもとのシェルの画面にもどります。
##保存できない場合
開いているファイルに書き込み権限がなく保存できない場合があります。一旦終了しましょう。１文字も書き換えていなければ終了はコマンドモードで<kbd>:</kbd><kbd>q</kbd>を押して<kbd>ENTER</kbd>すると終了します。しかしどこかを編集していると変更しているのに保存せずに終了するのかと怒られます。
そんな時は<kbd>:</kbd><kbd>q</kbd><kbd>!</kbd>と入力し<kbd>ENTER</kbd>します。そうすると保存せずに終了しシェルに戻れます。
その後書き込み権限を付加するなり

```
sudo vi ファイル名
```
と実行し管理者権限で実行するなりしてください。

##まとめ
これでひとまず
1.　viでファイルを開く

```
vi ファイル名
```
2.　カーソル移動する
キーボードのカーソル使う　

3.　編集する
<kbd>i</kbd>
4.　保存して終了
<kbd>ESC</kbd><kbd>:</kbd><kbd>w</kbd><kbd>q</kbd><kbd>ENTER</kbd>
まで完了するはずです。

##おまけ
しかしやはり、カーソル移動について次のコマンドぐらい覚えておくと便利だと思います。
コマンドモードで
<kbd>:</kbd><kbd>数字</kbd><kbd>ENTER</kbd>　指定した数字の行にジャンプ
<kbd>:</kbd><kbd>文字</kbd><kbd>ENTER</kbd>　指定した文字の検索
<kbd>n</kbd> 次の検索

これができると、テキストなどを見ていてこの設定を書き換えというとき、すぐ該当箇所を編集できます。

viはとても高機能なエディタでこれ以外にもたくさんのコマンドがあります。カーソルで移動などというとviを使いこなしておられる方からは怒られそうです。しかし、「viをマスターしたい」のではなく、今「このファイルを編集したい」という方の参考になれたらと思います。
GCEに端末からsshでアクセス，ファイルの転送

# Google Compute Engineインスタンスへのssh接続 メモ

## 目的

Google Compute Engineで作ったInstanceに，いつも使っているTerminalから，いつものようにsshでAccessしたい。

## 0. ssh鍵の作成

以前の記事を参考に，

[sshの設定（passwordなしでsshログイン（scp）する）](https://qiita.com/hnishi/items/5dec4c7fca9b5121430f)

## 1. ssh鍵のformat

`ssh-rsa [KEY_VALUE] [USERNAME]`

作成したssh鍵のパブリックキーファイルのフォーマットを編集する。
[KEY_VALUE]の後ろの通常はコメントとなる領域を，エディタを使ってユーザー名に書き換える。

例えば，

```
vi ~/.ssh/id_rsa.pub
```

で，ユーザー名（hogehoge@gmail.com）を鍵の末尾に。

`ssh-rsa dsafhdlkaijklafkdlfh...dfjsaifjiof hogehoge@gmail.com`

これを，ブラウザから設定する。

Google Cloud Platform -> Compute Engine -> Metadata -> SSH keys

Edit -> コピペ -> Save

これで準備完了。

## 2. ssh接続

IP address を調べる（VMインスタンス一覧のExternal IPを見ればよい）。

端末から

```
ssh -l hogehoge 104.199.144.176
```

もしくは，

```
ssh -l hogehoge 104.199.144.176 -i ~/.ssh/id_rsa
```

接続できない場合、インスタンスのリブート（再起動）が必要かもしれない。
（ネットワーク設定の再構成）

## 3. ファイル転送

scpを使う。

例えば

```
scp something.txt hogehoge@104.199.144.176:
```

## 参考
公式ドキュメント

- Linuxインスタンスへの接続

https://cloud.google.com/compute/docs/instances/connecting-to-instance

- SSH 認証鍵ペアの設定方法

https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keys
URLSessionTaskDelegate で通信の完了時に URLRequest を取り出す

`URLSessionTaskDelegate` で通信の完了時に `URLRequest` を取り出したいときあるじゃないですか。

そのとき、毎回忘れるけど、`URLSession` から `URLRequest` は取り出せない。取り出せるのは `URLSessionTask` から。

```swift
// MARK: - URLSessionTaskDelegate

func urlSession(_ session: URLSession,
                task: URLSessionTask,
                didCompleteWithError error: Error?) {

    print(task.currentRequest)
}
```

Appleのドキュメントを読むと
https://developer.apple.com/documentation/foundation/urlsessiontask/1411649-currentrequest

２つのリクエストが取得できる。

- var currentRequest: URLRequest?
  - The URL request object currently being handled by the task.
- var originalRequest: URLRequest?
  - The original request object passed when the task was created.

リダイレクトされた時を考えて、`originalRequest` も用意されている。つまりリダイレクトされると `currentRequest` は original とは違ったものになっているようだ。
Mask R-CNN for ROS

ROS Advent Calendar 2017 1日目です。
書いているのはもう25日ですが、枠が埋まってないところを埋めます。

はじめに
============
今回の記事では思いつきで作った[Mask R-CNN の ROS パッケージ](https://github.com/akio/mask_rcnn_ros)を紹介します。

何をするものなのかは動画を見るのが早いので、まずは動画をご覧ください。
[![動画](http://img.youtube.com/vi/nEug0-pD0Ms/0.jpg)](http://www.youtube.com/watch?v=nEug0-pD0Ms)

Mask R-CNN とは
=====================

[Mask R-CNN](https://arxiv.org/abs/1703.06870) はFacebook AI Research の Kaiming He, Ross Girshick らにより提案された、物体インスタンスセグメンテーションのためのアルゴリズムです。
同著者らが関わっていた物体検出アルゴリズム [Faster R-CNN](https://arxiv.org/abs/1506.01497) を改良し、新しい分岐を追加したような構造になっています。
新しい分岐は検出した物体領域バウンディングボックスのうちどのピクセルが物体に含まれているかを表現するマスクを出力する機能を持ちます。

![0-KtaZfpUErYqwH4RX.png](https://qiita-image-store.s3.amazonaws.com/0/217693/172c2737-3c1a-e42b-3e5a-0b001658c1b3.png)
引用元: https://arxiv.org/abs/1703.06870

物体クラス＋物体の含まれる矩形領域＋実際に物体であるピクセル領域を一度に認識することができ、比較的高速（論文の環境で5Hz）に動作する素敵な性能を持っています。実験的な機能のようですが、人間の姿勢推定もできるようです。（この実装ではできない）
ロボットのカメラ画像をこれで処理できたら楽しそうですよね？

ROS パッケージ化
=======================

自分で実装できないことはなさそうなのですが、論文によれば学習にTesla M40 x8で1〜2日かかるそうなので、自前実装を自宅で学習させると一回の学習に１周間以上かかってしまいそうです。EC2などでGPUマシンを借りてもやっても良いのですが、ありがたいことに既に学習済みモデル付きで実装を公開してくれている方々が複数おられます。時間的猶予もあまりないので今回はそれを利用させてもらうことにしました。今回のコードの大部分は、[Matterport, Inc. によるKeras実装](https://github.com/matterport/Mask_RCNN)を元にしています。したがって本パッケージ機能の大部分は彼らの寄与によります。感謝。

ROSに対応させる上で元の実装からの変更点を以下にまとめます。
* Python 2.7 で動作するように細々と修正（ROS Kinetic 対応のため）
* 学習でしか使わない依存パッケージの削除（COCO APIなど）
* 可視化関数の色付けアルゴリズムの変更（同じクラスは同じ色で塗る）
* ROS Node を実装(`mask_rcnn_node`)
* 出力メッセージ型の定義

具体的な使い方はREADMEを書いておいたので、[GitHubページ](https://github.com/akio/mask_rcnn_ros)を参考にしてください。
一応普通のROSパッケージっぽく使えるようにしたつもりです。

実験と結果
============

[RGBD SLAM Datasets](https://vision.in.tum.de/data/datasets/rgbd-dataset) から適当なrosbagファイルをダウンロードしてきて、`play`コマンドでカメラ画像を流し込んでみました。

![mask_r-cnn_2.png](https://qiita-image-store.s3.amazonaws.com/0/217693/d218b29b-08e5-5be6-bbbd-2ee0d8b6cda2.png)

![mask_r-cnn_1.png](https://qiita-image-store.s3.amazonaws.com/0/217693/104b1a97-2da8-89e2-6d6a-32ced345c422.png)

それっぽく処理できていますね。

Intel Core i5-4670 3.4GHz, NVIDIA GeForce 980 Ti な環境で、3.5Hz程度で動きました。
論文によれば980 Tiとほぼ同クラスの計算能力を持つTesla M40において5Hzで動作するそうなので、そこからすると若干パフォーマンスが出ていないようです。
CPUの貧弱さか、ROSメッセージからの変換など実装上の問題か、はたまた別の原因か興味の湧くところですが未調査です。

見て楽しむ以外の用途
==================
* Point Cloudの元のRGB画像に適用して、物体のポイントクラウドだけを切り出すなどすると良さそうです。


既知の問題
=============
* 可視化の部分は元々MatplotlibでプロットしているところからFigureのバッファを取ってきて変換してるのですが、うまく余白が消せませんでした。情報求む。

フィードバック
==============
思いつきで作ったので色々粗が残っていると思います。GitHub での Issue や PullRequest をお待ちしております。
GCP Cloud Shellでコマンドからファイルをダウンロードする

`︙` ボタンを使う手もあるんですがフルパスを `pwd` などから取得するのもめんどうなので。

Cloud Shellを起動して、以下のようにコマンド打つと、ダウンロードダイアログが表示される:

```bash
$ cloudshell dl ${target}
```

download以外のサブコマンドで

- edit (おそらくブラウザ上のテキストエディタだが起動しない...)
- aliases (シェルのaliasを追加。 `eval $(cloudshell aliases)` 的な使い方をする)

もあるみたいです。
【PlayCanvas】無理やりWebWorkerを使ってマルチスレッド化する

#何
不完全ですがPlayCanvas上でWebWorker使ってマルチスレッド化を実現してみます

#やり方
postmessage側とonmessage側のスクリプトをそれぞれ作ります。
postmessage側はPlayCanvasのスクリプトで作成し、適当なエンティティにアタッチしてinitializeに記述します
onmessage側はPlayCanvasスクリプトである必要はありません。

##postmessage側
以下スクリプト作成し適当なエンティティにアタッチします

```javascript:web-worker-test.js
var Webworkertest = pc.createScript('webWorkerTest');

Webworkertest.prototype.initialize = function() {
    
    if(window.Worker) {
        var workerfile;
        workerfile = this.app.assets.find("recive.js");
        
        this.worker = new Worker(workerfile.getFileUrl());
        
        this.worker.onmessage = function(e) {
            var result = e.data;
            console.log("from worker: " + result);
        };
        this.worker.onerror = function(e) {
            console.log(e);
        };
        var data = {
            name: "hello",
            age: 19
        };
        
        this.worker.postMessage(data);
    }
};

Webworkertest.prototype.update = function(dt) {
    
};
```

PlayCanvasのpc.Assets.find()メソッドで呼び出して、Worker()にgetFileUrl()メソッドで渡してあげるところがミソです。

##onmessage側

```javascript:recive.js
onmessage = function(e) {
    console.log(e.data);
};
```

シンプルにコンソール出力のみです。
こちらはアタッチする必要はありません。

#実行
![image.png](https://qiita-image-store.s3.amazonaws.com/0/148084/d6d05ce6-30e0-4cc6-c1a3-a2e85e419b84.png)

実行すると正しくrecive.jsのonmessageが動いていることが確認できます。


#問題
現状Web Workerは"スクリプトファイル単位"で"同一ドメイン"が前提なため、ここから先動かすためにはちょっと問題があります。

##ファイル圧縮すると動かない
ビルド時にConcatenate Scriptsにチェックを入れてビルドすると、内部のスクリプトファイルがすべて圧縮され__game-script.jsという名前に変更されてしまうため、正しく参照されなくなってしまいます

##playcanv.asだとアセットファイルはCDNにあるため動かない
PlayCanvas上でデプロイするとindex.htmlはplaycanv.as上、アセットファイルはAmazon S3のEUリージョンにデプロイされます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/148084/263f6188-d29c-fd0b-4076-20e74777ded6.png)
この状態ではクロスドメインなので当然Workerで呼び出すことはできません。

self hostでクロスドメインにならないような構成に変えてあげれば正しく動作します。
RStudioのGlobal設定(後編)

これは[RStudio Advent Calendar 2017](https://qiita.com/advent-calendar/2017/rstudio)の...18日が空いたままだったので埋めることにした即席の記事(の後編)です。前編は[こちらです](https://qiita.com/kazutan/items/2c66d537d487ec7547a5)。

## RStudioのGlobal Options

RStudioで全体的な設定をする場合，メニューの[Tools] - [Global Option...]から行うこととなります。ここで設定した内容は(当たり前ですが)RStudioを扱う際の全体設定となります。

なお，RStudioにはさらにProject設定があり，Project設定とGlobal設定があった場合にはProject設定が優先されます。また，現在作業している環境やファイル個別で設定がある場合には，そちらが優先されます。

自分が使いやすい環境はGlobal Optionsで設定しておき，個別で必要に応じてProject設定や個別の設定を切り替えるのが上手な使い方だと思います。というわけで，今回はGlobal Opitonsをさらっと紹介してみます。ただ長いので記事を分割し，今回は後編とします。この記事はRStudio v1.1.383での内容となります。

## 前編の内容

[前編](https://qiita.com/kazutan/items/2c66d537d487ec7547a5)で紹介したのは以下の内容です:

- General
- Code
    - Editing
    - Display
    - Saving
    - Completion
    - Diagnostics

それではその続きを紹介していきます。

## Appearance

![11139847.png](https://qiita-image-store.s3.amazonaws.com/0/35118/468ab229-1b92-e471-ef9e-0401d299dd15.png)

ウィンドウなどの見た目設定です。長い時間見つめることになるので，自分にあったものを設定するのは大事でしょう。なおRStudio v1.1.xからダークテーマを設定することができたりします。これについては[こちらの記事](https://kazutan.github.io/blog/2017/05/rstudio-dark-theme/)を参照してください。

## Pane Layout

![1113984.png](https://qiita-image-store.s3.amazonaws.com/0/35118/4219eb5a-cb14-1015-eb7c-3032b2f6e415.png)

RStudioは基本ウィンドウを4分割して使います。それらにどれを割り当てるかを設定します。ここは普段どのような使い方をしているかで変わってくるでしょうから，色々考えて自分に最適な割当を探してみてください。

## Packages

![111439587.png](https://qiita-image-store.s3.amazonaws.com/0/35118/8e0f2440-4102-d879-6318-5e57e94208a7.png)

CRANのミラー設定やパッケージ開発に関する設定です。多くの人が関わるのはCRANミラーですが，個人的にはRStudioのクラウド版(多分デフォルトでなってるはず)がいいと思います。

それ以外の項目については主にパッケージ開発(buildまわり)に関するところですので，パッケージ開発をする人は一度チェックしてみてください。

## R Markdown

![111348907.png](https://qiita-image-store.s3.amazonaws.com/0/35118/65eee1e2-cdcd-ec87-447a-98b196ac4ffe.png)

R Markdownに関する設定項目です。チャンク評価出力をチャンクの下に出すかどうか(Notebook的に使うか)，markdownで読み込ませる画像や数式をインラインで表示するかどうか，などを設定できたりします。

これはそれぞれのRmdファイル編集画面でON/OFFを切り替えられるのですが，「毎回変えるのが面倒だ」という方はぜひこの辺りの設定を見直してください。

## Sweeve

![111839247.png](https://qiita-image-store.s3.amazonaws.com/0/35118/35001b79-c426-fd64-8d2e-cd2ada918d51.png)

Rnwを起こしたりやPDFレンダリングを遂行するのに使用するエンジンの設定などを行います。この辺りを利用している(出力している)方でトラブルが頻発する場合は，この辺りをチェックする必要があるかもしれません。

## Spelling

![1114389073.png](https://qiita-image-store.s3.amazonaws.com/0/35118/5d3b3ec7-3029-2b51-be28-17345214f45d.png)

スペルチェックに関する内容です。省略します。

## Git/SVN

![111398433.png](https://qiita-image-store.s3.amazonaws.com/0/35118/87230073-84d0-f7d5-36f4-6c99e1df9a31.png)

バージョンコントロールに関する設定です。gitの場所やTerminalの場所，RSA鍵の場所などの設定です。gitなどがうまく動かない時は，これらの設定を確認してください。

## Pubilshing

![11134875323.png](https://qiita-image-store.s3.amazonaws.com/0/35118/6fa32e51-716e-987f-3e30-acbab84bcb7f.png)

RPubsやRStudio Connect, ShinyApps.ioなどへ公開するときに使う設定の管理画面です。設定すれば，あとは簡単に公開できるようになります。

## Terminal

![111908734.png](https://qiita-image-store.s3.amazonaws.com/0/35118/c5e680e1-235f-d403-2ce4-6e87454a0f27.png)

v1.1.xから利用できるようになった，Terminalまわりの設定です。使用するShellを選択したり，その他細かい設定項目があります。Terminalを利用する方(特にWindows版ユーザー)は多分Shellでどれを使うかはチェックしたほうがいいでしょう。

## さいごに

駆け足で紹介してきましたが，全部を確認する必要はないと思います。自分がよく使う機能や内容であれば，一度この機会に見直してみるのもいいと思います。自分色にカスタマイズして楽しいRStudioライフを。

**Enjoy!**
CircleCI2 でSlackに通知する

# はじめに

CircieCI 2 便利なんだけど、標準のチャット通知がわりとシンプルすぎて目が滑るため困る。

<img width="299" alt="Slack_-_ROLLCAKE_Inc_.png" src="https://qiita-image-store.s3.amazonaws.com/0/10693/e9fa906f-3739-e281-2b39-f59bbf08102e.png">

ワークフローを使っていると同じような通知が飛んできて、どのステップの通知なのかよくわからないし、自分でメッセージを作りつつ通知したい気持ちになった。

# 例

```yaml
- run:
    name: Slack
    command: |
      GIT_REVISION=`git show -s --format=%H`
      PAYLOAD=`cat << EOS
      {
        "channel": "#test",
        "username": "CI",
        "icon_emoji": ":octocat:",
        "text": "<!here|here> デプロイしたよ :docker:",
        "attachments": [
          {
            "title": "Revision",
            "color": "good",
            "text": "<https://github.com/xxxxxx/xxxxxx/commit/$GIT_REVISION>"
          }
        ]
      }
      EOS
      `
      curl -X POST --data-urlencode "payload=$PAYLOAD" $SLACK_WEBHOOK_URL

```


<img width="288" alt="Slack_-_ROLLCAKE_Inc_.png" src="https://qiita-image-store.s3.amazonaws.com/0/10693/6fc4571e-f082-fde1-f363-d062d2c6254b.png">


いいですね
DataGripでSQLiteを扱う際に関するいくつかのこと

DataGrip便利ですよね。
で、SQLiteを扱う際、ちょっと一筋縄でいかない部分があったのでいくらかまとめてみまた。


# Date and timeの表現方法を変更する。

[SQLiteには日付型が無い](https://sqlite.org/datatype3.html)。
なので、どのように格納されているのか指定する必要がある。

指定方法は、
下図の"Data Source and properties"をクリックすると、ダイアログが出てくるので、その"Advanced"タブの中に

![image.png](https://qiita-image-store.s3.amazonaws.com/0/9662/16dab1b1-95b1-2fb7-d716-c3d8258bb735.png)



1. date_precision
2. date_class
3. date_string_format

が有り、この辺で適宜指定する。

一番重要なのが、"date_class"で、`INTEGER`、`TEXT`、`REAL`を指定できる。

## INTEGERを指定したとき

これは、UnixTimeで格納したと評価される。
この指定の場合、先の"data_precision"で秒か㍉セコンドかの解像度を指定可能となる。

## TEXTの場合

文字通り、TEXTで格納されると評価される。
フォーマットは下にある"date_string_format"で指定する。

## REALの場合

これは、Julian day numbersとして評価される。

# DataViewerの書式

例えば、下記のようなテーブルをこさえたとする。

```sql

CREATE TABLE DateSample(
  Id INT NOT NULL PRIMARY KEY ,
  DateTime DATETIME,
  TimeStamp TIMESTAMP
)

```

このとき、DataViewrは以下のようになる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/9662/4f134925-65b8-4e61-bc02-076667e03640.png)

`DATETIME`指定すると、日付だけ。
`TIMESTAMP`指定すると、日付と時刻
というかたちで、表現域が変わってくるのでその点注意。

ただ、これがフォーマットを別指定可能なのか、変更不可なのかは現状わからなかった。

#まとめ

SQLiteは日付型がないので、その辺の調整する必要が出てくるので、
他のRDBMSとは一風変わった設定があって、そこで引っかかったので、まとめてみました。
Alamofireの導入および準備

<<< Alamofireを利用するには >>>


#CocoaPodsのインストール
###1.ruby gemを最新にする
`$ sudo gem update --system`

###2.インストール
導入方法は簡単で、
`$ sudo gem install cocoapods`
たったこれだけ。

※ OSXがEl Capitan方は、ターミナルで以下のコマンドを打ってください。
`sudo gem install -n /usr/local/bin cocoapods`

###3.セットアップ
`$ pod setup`

次に、 Xcode のプロジェクトがあるディレクトリに移動
(例：デスクトップのtestフォルダにプロジェクトがある場合)
`$ cd \Users\nXXXXX\Desktop\test`

###4.次のコマンドを実行します。※Xcodeは終了しておく
`$ pod init`

これで、 プロジェクトのフォルダ内にPodsfileが生成されるので、ここに導入するライブラリを記述し保存。


#Podsfileの編集

先ほど4.で生成されたPodsfileに、導入したいライブラリ（ここではAlamofire）を書き加える。
Not全コピペ！！！podの場所だけ書き加えてください。

```
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'

target 'rensyuu' do #Xcodeのプロジェクト名が自動的に入ります。ここではrensyuuという名前になっています
  use_frameworks!

    pod "Alamofire" #この行でAlamofireを追加できるので、書き加えてください

  target 'rensyuuTests' do #プロジェクト名Tests（自動挿入）
    inherit! :search_paths
  end

  target 'rensyuuUITests' do #プロジェクト名UITests（自動挿入）
    inherit! :search_paths
  end

def install_pods #場合によってはこの行不要です！
end
```

###5.次のコマンドを実行します。 ※Xcodeは終了しておく
`$ pod install`

完了です。

# Xcodeを開く
*.xcodeprojではなく、生成された *.xcworkspace をXcode で開きます。

#追加で他のライブラリをインストールする
他のライブラリをインストールするときは、先ほどのPodfileにライブラリを追加し、
`$ pod update`
を実行する。
(初心者向け)Swiftで初アプリ - スワイプ動作を追加

Swiftを使って簡単なiPhoneアプリを作ってみます
スワイプ動作を追加してみます

#1. ViewControllerを準備します


- [(初心者向け)Swift3.0で初アプリ - 次画面を追加してみる](https://qiita.com/egplnt/items/2806aa6b88a966a82f8c)
などを参照し、スワイプ動作を追加する画面とその画面に紐付けられたUIViewControlle.swiftを準備します- 


#2. Swipe Gesture Recognizerを追加します


- 画面右下のパレットで「Swipe」を入力し、「Swipe Gesture Recognizer」を表示します

<img width="302" alt="スクリーンショット 2017-12-25 17.09.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/03d6bd60-3755-512d-3354-119948786893.png">

- Main.storyboardで新たに作成した画面にSwipe Gesture Recognizerをドラッグ＆ドロップします

<img width="863" alt="スクリーンショット 2017-12-25 17.10.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/c9ab056b-9f35-3414-b215-5b7b2cadcc0a.png">

- 画面上部の長方形の中に新たに追加されたSwipe Gesture Recognizerのアイコンが登録されることを確認します

#3. スワイプ動作について記述します
- 新たに登録したSwipe Gesture Recognizerを選択し、画面右側のペインで「Attribute inspector」（下向きの矢印のようなアイコン）を選択し、スワイプ動作の向きを指定します



<img width="876" alt="スクリーンショット 2017-12-25 17.10.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/28f9e614-66bc-6852-eb0e-317fc74e3c70.png">

- Xcode画面中央〜左に表示されているナビゲーションペインで新たに作成されたSwipe Gesture Recognizerが表示されることを確認します
 
<img width="1405" alt="スクリーンショット 2017-12-25 17.10.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/368251de-6fb7-a2a5-7660-0e4610ba362c.png">


- Xcode画面中央〜左に表示されているナビゲーションペインで新たに作成されたSwipe Gesture Recognizerを選択し、[Control]を押しながら対象のUIViewController.swiftへドラッグして登録します
<img width="1161" alt="スクリーンショット 2017-12-25 17.12.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/278760a6-8c92-3a59-7d94-b1f0a88777e9.png">

- 追加されたSwipe Gesture Recognizerを選択した状態で画面右端のペインで「Connections inspector」（右端の右向き矢印のようなアイコン）を選択し、登録したSwipe Gesture Recognizerの「Sent Actions」と「Referencing Outlet Collections」が登録されていることを確認します
<img width="1410" alt="スクリーンショット 2017-12-25 17.15.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/43ada9c7-e3a5-85a1-e841-ea5459229985.png">


#4. Simulatorで動作を確認します
- アプリを起動し、スワイプ動作が適用されることを確認します
transform-flow-strip-types と transform-decorators-legacy を同時に使う時、気をつけること

`transform-decorators-legacy` でデコレータと `transform-flow-strip-types` で flowtype を一緒に使う場面ありますよね。

このとき、プラグイン定義の順序が重要になってきます。

# 誤: transform-flow-strip-types を先に定義する

この場合、特定の場合におかしくなります。

```js
  "plugins": [
    "transform-flow-strip-types",
    "transform-decorators-legacy"
  ],
```

具体例として、mobx の `@observable` を使ってみましょう。

```js
class Counter {
  @observable count: ?number;
}
```

これの babel のトランスパイル後のコードはコチラ。

```js
var Counter = function Counter() {
  (0, _classCallCheck3.default)(this, Counter);
};
```

わー。見事に `observable` な定義が無かったことになっていますね。ちなみに

```js
class Counter {
  @observable count: ?number = null;
}
```

と初期値が undefined でなく null だった場合

```js
var Counter = exports.Counter = (_class = function Counter() {
  (0, _classCallCheck3.default)(this, Counter);
 
  _initDefineProp(this, "count", _descriptor, this);
}, _descriptor = _applyDecoratedDescriptor(_class.prototype, "count", [_mobx.observable], {
  enumerable: true,
  initializer: function initializer() {
    return null;
  }
}), _class);
```

とバッチリ定義されるので、ハマったときにさらに解りにくかったります。というか自分が `@observable` だけど上手く動いたり動かなかったりする現象で何が問題なのかを見つけるまでハマりました…。


# 正: transform-flow-strip-types を後に定義する

```js
  "plugins": [
    "transform-decorators-legacy",
    "transform-flow-strip-types"
  ],
```

この定義の場合、デコレータの処理が先にされるため

```js
class Counter {
  @observable count: ?number;
}
```

のトランスパイル後のコードが

```js
var Counter = exports.Counter = (_class = function Counter() {
  (0, _classCallCheck3.default)(this, Counter);
 
  _initDefineProp(this, "count", _descriptor, this);
}, _descriptor = _applyDecoratedDescriptor(_class.prototype, "count", [_mobx.observable], {
  enumerable: true,
  initializer: null
}), _class);
```

と、`undefinded` だったとしても mobx.observable な処理がされ、適切に動作します。
Solidityの開発環境を比較してみる

# はじめに
Solidityの開発環境がいまいちまとまっていなかったので、色々試した結果をまとめた。
自分のメモ的側面が強いが、誰かの役に立てば幸いである。


# EthFiddle
![スクリーンショット 2017-12-25 16.41.22.png](https://qiita-image-store.s3.amazonaws.com/0/220892/43f8f98e-9f46-ab03-bf00-c2e9e54eeda3.png)

https://ethfiddle.com/
EthFiddleはブラウザ上でコントラクトを記述できるので動作確認に便利で、共有する際にはURLを貼り付けるだけなので簡単。
また、chat機能がついていて質問もできる。
ここで一度コントラクトを簡単にテストした後に、gethでコンパイル、デプロイするのがいい。
一方で、実際のネットワークにgethを使わずにデプロイしたり、本格的な開発を行うには難しいかもしれない。

メリット
1. 簡単に動作確認できる
2. チャットルームがあって質問しやすい
3. おしゃれ

デメリット
1. ブラウザ上なので細かい設定ができない
2. メインネットにデプロイできない


# Intellij
https://plugins.jetbrains.com/plugin/9475-intellij-solidity
![スクリーンショット 2017-12-25 16.47.53.png](https://qiita-image-store.s3.amazonaws.com/0/220892/1ed2dd89-305d-c9c8-48ed-cfe3232245d5.png)
JetBrains製のテキストエディタ。
solidityはシンタックスハイライトのみ。
solidityを書くのみだったら他の機能が多すぎるので、オーバースペックという感じ。
実質エディタ+solcとそんなに変わりないけれど、PyCharm等のJetBrains製品に使い慣れていたり、Androidアプリ書いたり、solidityメインの製品じゃない時にいいかもしれない。

つまりSolidityだけ書くなら、他の方がいい。

メリット
1. エディタらしく細かい設定が可能
2. AndroidやJavaといった他の言語を使う開発にも使える

デメリット
1. コンパイル等は結局solcを使ってやるしかない
2. シンタックスハイライトしか機能がない

# Remix
https://remix.ethereum.org/#optimize=false
![スクリーンショット 2017-12-25 16.42.04.png](https://qiita-image-store.s3.amazonaws.com/0/220892/b58e4221-30a5-05d7-75f4-9f6b7cf29bd9.png)

Solidityの公式の開発環境。多機能。
ブラウザ上でコントラクトを記述できて、クライアントさえつけていれば接続してデプロイまでやってくれる。ただし、環境設定がわかりづらい。さらに、一部の環境では動作が不安定な時があったりして、なかなか落ち着いて開発しづらい。
動作確認だけならjavascript VMで動かせる。


メリット
1. 公式なのでコンパイラをほぼ全種類選べる
2. 多機能で出来ないことがほぼなさそう

デメリット
1. 一部環境で正常に機能しない時があった
2. ブラウザ上なのでカスタマイズできない
3. 多機能が故にどの機能がどこにあるのか、分かり辛い


# エディタ&solc
好きなエディタを使える。
筆者はEmacs + solcで開発を行っている。現状はこれで個人開発は完璧。ただ、チーム開発の際に環境が異なって動作しなかったり、何らかの不具合不都合が発生する可能性は否めない。

メリット
1. 柔軟に対応できる

デメリット
1. 複数人開発で環境が違って来たりする

# まとめ
一通り簡単に触った結果なので、機能の見落としがあったりするかもしれないので、実際に使ってみて使いやすい環境というのが一番だと思います。solidityはgethで直接できたコンパイル機能を廃止したりしてるので、未だ開発環境が完全に落ち着いていない段階だと思います。代わりに登場したRemixは筆者が半年前に使ったときはsafari、firefoxで両方ともカクカクして作業にならなかったりしていたが、現在は直っているようなので使ってみようと思う。

結論としてはそこそこ大きなコントラクタは好きなエディタで書いてRemixでデプロイ、コンパイルを試す、という流れが一番良さそうだ。
チュートリアルのような簡単な物を書いているだけならEthFiddleが手軽に確認できるのでおすすめである。
たった3分でできる俳句判定処理

ホワイトプラスのエンジニアの[kaizoa](https://qiita.com/kai-zoa)です。
アドベントカレンダーの最後となりますので季節感出していきます。

季節ということで、Goで渡したテキストから俳句の判定をする実装はないかなと探したところ、[github.com/mattn/go-haiku](https://github.com/mattn/go-haiku)を見つけたので、俳句の世界でアイドル的な存在である[北大路翼さん](https://ja.wikipedia.org/wiki/%E5%8C%97%E5%A4%A7%E8%B7%AF%E7%BF%BC)のツイートを渡してみました。

```shell-session
$ haiku -u 'https://twitter.com/search?l=&q=from%3Atenshinoyodare%20since%3A2017-12-01%20until%3A2017-12-24'
五本指 ソックスで来る サンタさん
年末は 俺を見てゐろ 風邪気味の
アウトロー 俳句アマゾン 詩歌部門
開発者 契約および 開発者
しよう気に なるツイートを 見つけたら
情報は こちら話題の トピックが
```

すごいっ！、年末っぽい俳句が出てきた笑
しかしながら、実際はもっと俳句をツイートしてるのに、ここには引っかかってきませんでした。
これは下記のような五七五の定型じゃない句がまぁまぁあるので、文字数を数えるアプローチでは見つけられないケースが結構あるためです。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">22 サンタクロース(女)は脱がしづらい</p>&mdash; 北大路翼 (@tenshinoyodare) <a href="https://twitter.com/tenshinoyodare/status/944251212802568192?ref_src=twsrc%5Etfw">2017年12月22日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

というわけで北大路さんのツイート限定ですが、確実に俳句を抜き出せる処理を書いてみました。

```go:main.go
package main

import (
	"os"
	"fmt"

	"github.com/dghubble/go-twitter/twitter"
	"github.com/dghubble/oauth1"
	"strings"
	"strconv"
)


func main() {
	config := oauth1.NewConfig(os.Getenv("TWITTER_CONSUMER_KEY"), os.Getenv("TWITTER_CONSUMER_SECRET"))
	token := oauth1.NewToken(os.Getenv("TWITTER_ACCESS_TOKEN"), os.Getenv("TWITTER_ACCESS_SECRET"))

	tweets, _, err:= twitter.NewClient(config.Client(oauth1.NoContext, token)).
		Timelines.
			UserTimeline(&twitter.UserTimelineParams{
		ScreenName: "tenshinoyodare",
		Count: 1000,
	})

	if err != nil {
		panic(err)
	}

	for _, t := range tweets {
		arr := strings.Split(t.Text, " ")
		if len(arr) == 0 {
			continue
		}
		if _, err := strconv.Atoi(arr[0]); err != nil {
			continue
		}
		fmt.Printf("%s\n", t.Text)
	}
}
```

はい、先頭に数字が入ってるかチェックしてるだけです。
歌人の方で句をツイートしてる人の一部は、採番した数字を句の頭に書いていることがあるので、その場合はこれだけで良いのです。

```shell-session
$ go  run main.go
24 大阪で途方にくれるクリスマス
23 東電をぶち殺すためサンタコス
22 サンタクロース(女)は脱がしづらい
21 十字架の人の当日参加かな
20 馬小屋で糞すれば湯気クリスマス
19 どちらかといへば又吉クリスマス
18 神様を踏んで聖夜に集まりぬ
18 五本指ソックスで来るサンタさん
17 落椿が絵文字になつたらよく使ふ
16 手袋を裏返さぬやううまく脱ぐ
15 重ね着の肩をすぼめて座りたる
14 新しい靴の固さに寒気満つ
12 どろどろに固まつてゐるチーズピザ
11 いい人で終はりたくない狸汁
10 年末は俺を見てゐろ風邪気味の
9 通販で買ふと蜜柑がついてくる
8 小さくて汚い店の冬の星
7  返り花日差しにほつとしてゐたる
6 鋭利な便意もうだめ嚔出る
5 風邪引いてゐますが痴漢ぢやありません
4 枯れ木踏む音で手紙が破かれて
```

大したことないコードではありますが、定形に囚われることなく確実に俳句を抜き出せるので最高✌✌
季節感✌✌

🎍🎍では良いお年を🎍🎍

----
ホワイトプラスではエンジニアを募集しています
ホワイトプラスでは、web×リアル領域で「新しい日常を創りたい」エンジニアWanted!!しております。
Jenkinsのスクリプトコンソールでコマンドを実行する

# はじめに

自分のための、ただの備忘録です。
試したときの環境はMacのSierraです。

Jenkinsの設定をしていて、「Jenkinsのコンソールスクリプトからどうやってコマンド実行するんだろう」と思ったのがきっかけ。

# スクリプトコンソールとは
スクリプトコンソールを使うと、Jenkinsサーバやスレーブノード上で、任意のスクリプトを実行することができます。

言語はGroovy！！
（正直、真面目に勉強したことないです。。。Jenkinsを管理するのなら、もっと真面目にやったほうが良いかどうか迷い中）

「**Jenkinsの管理** > **スクリプトコンソール**」で起動。
<img width="700" alt="スクリプトコンソール.png" src="https://qiita-image-store.s3.amazonaws.com/0/33347/7cb4b26e-ab2a-4905-2a35-6424c1d552d2.png">

# コマンド実行

まず結論から。

```groovy
println "pwd".execute().text
```

ダブルクォーテーションで囲んだコマンドを実行して、結果を出力しています。
実行結果は下図。

<img width="700" alt="実行例.png" src="https://qiita-image-store.s3.amazonaws.com/0/33347/1a7a28ac-21fb-ac2c-e2ce-2204a3f7dd6e.png">

`pwd`の結果が、即座に下の方に表示されます。
ちなみに、私のときは`pwd`がしたかったわけではなく、ちょっと`git`コマンドを打ちたくて調べました。

さて。
このスクリプトコンソールから色々と操作できるみたいです。
ただ、今のところそこまでの必要にかられていないという後ろ向きな理由で後回し！
EC-CUBE、サービスロケーターやめるってよ

はじめに、DIとかサービスロケーターについては[こちらのエントリ](http://blog.a-way-out.net/blog/2015/08/31/your-dependency-injection-is-wrong-as-I-expected/)が詳しいので読んでおきましょう。

現在EC-CUBEの次期メジャーバージョンを絶賛開発中です。EC-CUBEの次期バージョンはEC-CUBE3.0系をベースに開発していますが、EC-CUBEをさらに良くするための大きめの変更がいくつかあります。その中の一つとしてサービスロケーターをやめてDI(Dependency Injection)をきちんとやるようにしました。

例えば、次のようなコントローラーが、

```php
namespace Eccube\Controller\Block;

use Eccube\Application;

class CartController
{
    public function index(Application $app)
    {
        $Cart = $app['eccube.service.cart']->getCart();
        return $app->render('Block/cart.twig', array(
            'Cart' => $Cart,
        ));
    }
}
```

こんな感じになります。

```php
namespace Eccube\Controller\Block;

use Eccube\Annotation\Inject;
use Eccube\Application;
use Eccube\Service\CartService;

class CartController
{
    /**
     * @Inject(CartService::class)
     * @var CartService
     */
    protected $cartService;

    public function index(Application $app)
    {
        $Cart = $this->cartService->getCart();
        return $app->render('Block/cart.twig', array(
            'Cart' => $Cart,
        ));
    }
}
```

`CartService`の参照の仕方が変わっています。これだけ？という感じかもしれませんが、実際のコードには`$app`からオブジェクトをルックアップしているコードが大量にあります。実際に対応した適用したプルリクが、[これ](https://github.com/EC-CUBE/ec-cube/pull/2463/files)です。すべてのController/FormType/Repository/Serviceとそれ以外のいくつかのクラスにも手を入れたので、なかなかの変更量(`211 files changed, 5596 insertions, 1858 deletions`)になっています。

## どうやって対応したのか?

これらの対応は、1ファイルづつEC-CUBE開発チームメンバーが心を込めて人の手で修正した温もりのあるコミットになっているのではなく、機械的にやりました。機械的といっても正規表現で一括置換できるものでもなく、いくつかのパターンがあったりして意外と面倒なので、[こんなプログラム](https://github.com/kiy0taka/Symfony-Upgrade-Fixer/blob/experimental/dependency-injection/src/Symfony/Upgrade/Fixer/DependencyInjectionFixer.php)を書きました。詳しくは説明しませんが、ざっくりいうと [PHP CS Fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) の仕組みを使ってコードを書き換えるやつです。

## サービスロケーターやめてどうなったの？

IDEの補完がちゃんと効くようになったとか、今までコンテナにコンポーネントを登録する処理を`ServiceProvider`に書いていたのがなくなったので記述量が減ったとか色々ありますが、一番良かったのが依存が見えるようになったことです。
冒頭のエントリにも書かれていた通り、サービスロケーターで記述されたコードは、いつの間にか依存関係が多くなってしまっています。今回Fixerを使って変換してみるとルックアップしていたオブジェクトがフィールドに宣言されるので、あるクラスがどのくらい依存関係を持っていたのかが一目瞭然となります。今までなんとなく複雑になっているなと思っていたクラスは、フィールドが大量に宣言されていたりするので、早くなんとかしないといけないと気づけるようになります。

また、コンテナをルックアップしていたコードは、依存オブジェクトの初期化が遅延されていましたが、DIによって先にオブジェクトの初期化が行われるようになったため、相互参照や循環参照しているコードは正しく動作しなくなりました。

このように、きちんとDIしてあげることで依存関係にまつわる問題を表面化することができ、これらの問題に対処することができました。また、今後コードを変更していく上でも、依存関係をひとつの指標としてクリーンなコードを保てるようになります。

## 最後に
ここまでは[Pimple](https://pimple.symfony.com/)をDIコンテナにして、独自でInjectionの仕組みを作っていたのですが、現在DIコンテナを別のものに変更しているところです。なので、このエントリで出てきたコードは最終的には少し違う形にはなりますが、サービスロケーターをやめるってのは変わりません。ですので、どこかでEC-CUBEの話が出てきたら「EC-CUBE、サービスロケーターやめるってよ」って噂を流しておいてください。
jQueryで知るのは便利と思うメソッド

##not
指定した要素以外
$("要素").not()

##find
指定した要素から、条件に合う子孫要素を探し出す
$("親要素").find("小要素")

##next
次の要素を取得
$("要素").next()

##nextAll
次以降の要素を取得
$("要素").nextAll()

##prev
前の要素を取得
$("要素").prev()

##prevAll
前の要素全部を取得
$("要素").prevAll()

##siblings
自分以外の兄弟要素を取得
$("要素").siblings()

##data
データ属性を取得する
$("要素").data(属性)




##参照資料：
jQueryでよく使うメソッド
http://chanmako.com/archives/163
よく使うけど忘れがちな『JavaScript、jQueryのコード』まとめ
https://manablog.org/javascript-code/
Bitnami > Redmine > Subversionのインストール


# 前提

BitnamiのRedmineを1.x、2.x、または3.2系　→　3.4へ上げた場合、
Subversionが内包されていないので別途インストールする必用がある。

## 環境
OS:Windows
Bitnami Redmine 3.4.3

## Subversionの導入
以下から最新のSubversionをダウンロードしてインストールする。
[Alagazam\.net: Subversion Windows Installer](http://alagazam.net/)

apacheのバージョンは2.4.xだった

## Apacheの設定
インストールされたフォルダのBin配下の以下のファイルを
\redmine-3.4.3\apache2\modules の下にコピー
* mod_dav_svn.so
* mod_authz_svn.so


C:\Program Files (x86)\Subversion\bin

![image](https://qiita-image-store.s3.amazonaws.com/0/49910/b83caabb-83c7-f1f5-6c05-4a9985817721.png)

/apache2/conf/httpd.confの末尾に以下を追加
`Include "C:/BitNami/redmine-3.4.3/apache2/conf/svn.conf" `


svn.confをconfの下に作成

SVNParentPathにはSVNのリポジトリにしたいフォルダを設定する

```shell-session:svn.conf
# subversion
# LoadModule

LoadModule dav_module       modules/mod_dav.so
LoadModule dav_fs_module    modules/mod_dav_fs.so
LoadModule dav_svn_module   modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so

# set Location
<Location /svn/>
    DAV                 svn
    SVNParentPath       "C:\bitnami_redmine_repository"
    SVNListParentPath   on
</Location>

```

Bitnami のApacheを再起動する

サーバー名/svnにアクセスする。
リポジトリが出てきたらOK
OpenURLSchemeでアプリ起動後に画面遷移


# はじめに
自作アプリにOpenURLSchemeを設定して、他のアプリから起動出来るようにしたのですが、起動後の画面遷移がちょっとややこしかったのと、意外と情報が少なかったのでまとめておきます。

# 全体像
iOSのアプリはアプリ起動時にいくつかのメソッドがCallされます。Call順は、どのように起動したかによって違いますが、OpenURLのタップにより起動した時は、以下のメソッドが呼ばれます。（全てのメソッドは調べていません）

1. applicationWillResignActive
2. applicationWillEnterForeground
3. application(_ app: ,open url: ,options:)
4. applicationDidBecomeActive

タップしたOpenURLの情報は3のurlで取得出来るので、アプリ起動後の画面遷移は3か4に実装することになります。
3はアプリ切り替え前、4はアプリ切り替え後になりますので、画面遷移アニメーションをさせるかさせないかで選択するといいでしょう。

# 実装方法
以下のようなロジックでOpenURLの取得と画面遷移が可能です。アプリへのOpenURLSchemeの設定方法自体はググってみてくださいな。
なお、自作アプリのコードをべたっと貼り付けただけです。

``` swift
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
	let scheme = url.scheme
	if let host = url.host? {
		if let query = url.query? {
       		self.window = UIWindow(frame: UIScreen.main.bounds)
			let storyBoard = UIStoryboard(name: "Main", bundle: nil)
			if let tabBarViewController = storyBoard.instantiateInitialViewController() as? TabBarViewController {
				if let taskableViewController = tabBarViewController.viewControllers?[0] {
					tabBarViewController.selectedViewController = taskableViewController
					self.window?.rootViewController = tabBarViewController;
					self.window?.makeKeyAndVisible()
				}
			}
        }
    }
    return true
}

```

「schedulist://task?10」のようなOpenURLをタップすると、schemeに「schedulist」、hostに「task」、queryに「10」が格納されます。
これらの値を使用して画面遷移をして行きましょう。
Google Cloud Natural Language APIをRubyで実行する

## はじめに
理科大のAdvent Calendar 2017の21日の記事です！(25日に執筆中)
stripeのことを書く予定でしたが卒論でstripeどころかqiita書く時間もなかったので、ちょうど卒論で使ったGoogle Cloud Natural Language API
について書きます。

## Google Cloud Natural Language APIとは

[CLOUD NATURAL LANGUAGE API](https://cloud.google.com/natural-language/?hl=ja)


### 感情分析
ネガポジで-1.0〜1.0で返してくれる
[ドキュメント](https://cloud.google.com/natural-language/docs/analyzing-sentiment?hl=ja)

### エンティティ分析
一般名詞を返してくれる
[ドキュメント](https://cloud.google.com/natural-language/docs/analyzing-entities?hl=ja)

### 構文解析
そのまんま。
[ドキュメント](https://cloud.google.com/natural-language/docs/analyzing-syntax?hl=ja)

### エンティティ感情分析
一般名詞に対する感情を返す
[ドキュメント](https://cloud.google.com/natural-language/docs/analyzing-entity-sentiment?hl=ja)


こんかいは感情分析だけ使った。

## 感情分析のスコアの見方
[感情分析の値の解釈](https://cloud.google.com/natural-language/docs/basics?hl=ja#interpreting_sentiment_analysis_values)




## サンプルコード

ドキュメントにrubyのサンプルコードがあったけど実行すると認証エラーになった。(下記のコードでできたからまだ解決してない)
事前にapi_keyを取得する必要がある。

### curl

request.jsonを作成して


```
{
  "document":{
    "type":"PLAIN_TEXT",
    "content":"これが感情分析したいテキストが入る場所"
  }
}
```

```bash
curl "https://language.googleapis.com/v1beta1/documents:analyzeSentiment?key=hogehogehogehogehoge" \
  -s -X POST -H "Content-Type: application/json" --data-binary @request.json
```

curlは[ここ](https://cloud.google.com/natural-language/docs/reference/rest/?hl=ja)を参照


### ruby

```ruby
require 'net/http'
require 'uri'
require 'json'

uri = URI.parse("https://language.googleapis.com/v1beta1/documents:analyzeSentiment?key=hogehogeohogehoge")
request = Net::HTTP::Post.new(uri)
request.content_type = "application/json"
request.body = ""
request.body = '{
                  "document":{
                    "type":"PLAIN_TEXT",
                    "content": "これが感情分析したいテキストが入る場所"
                  }
                }'

req_options = {
  use_ssl: uri.scheme == "https",
}

response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
  http.request(request)
end

json = JSON.parse(response.body)
p score =  json['documentSentiment']['score']
p magnitude = json['documentSentiment']['magnitude']

```
Ruby on Railsで動的に追加・削除可能な入力フォーム


「Ruby on Railsで動的に追加・削除可能な入力フォームの実装手順
https://www.virment.com/add_and_remove_rails_nested_form_dynamically/

gem 'nested_form_fields'
gem 'jquery-rails'
これが無いと動かない


//= require jquery  <<
//= require rails-ujs
//= require activestorage
//= require turbolinks
//= require_tree .
//= require nested_form_fields  <<

Uncaught ReferenceError: $ is not defined

https://qiita.com/fezrestia/items/e669107a4a6e66618738
google-home-notifierが日本語を喋ってくれない？

#あれ？日本語にならない・・・
[ここ](https://qiita.com/azipinsyan/items/db4606aaa51426ac8dac)などを参照してGoogle Homeに日本語を話して貰おうとしましたがなぜか躓いたのでメモ。
（12/25現在のバグなのでいずれ修正されるかと思います）
##修正方法
google-home-notifier.jsの

```js:google-home-notifier.js
...省略

var ip = function(ip) {
deviceAddress = ip;
return this;
}

...省略
```
を

```js:google-home-notifier.js
...省略

var ip = function(ip, lang = 'ja') {
deviceAddress = ip;
language = lang;
return this;
}

...省略
```
に変更してください。
##リファレンス
[Managed to install without MDNS / found a bug in main-script](https://github.com/noelportugal/google-home-notifier/issues/30)
[GoogleHomeスピーカーに外部からプッシュして自発的に話してもらいます](https://qiita.com/azipinsyan/items/db4606aaa51426ac8dac)
EurekaでRowの再描画

 [Eureka](https://github.com/xmartlabs/Eureka)を使っていて、Rowを再描画したい時があると思います

下記のようにすれば、再描画することができます。

```Swift:VIew.swift
    override func viewDidLoad() {
        super.viewDidLoad()
        // Sectionの設定
　　　　　　　　　　　　　　　　form +++ Section("UserInfo")
            // Rowを設定
            <<< TextRow("Name"){ row in
                row.title = "名前"
                row.placeholder = "Enter text here"
            }    
        form.rowBy(tag: "Name")?.baseValue = data["name"] as! String?
        // 再描画したいRowを選択して.reload()を実行
        form.rowBy(tag: "Name")?.reload()

      }
```
iPhone Xへの対応の仕方について

iOSエンジニアらしく1記事くらいはiOS絡みの内容を書こうかと思います。

## 概要
iPhone X対応は、全3段階に分けられます。
1. 上下の帯をなくす
2. Safe Area Layout Guideを有効にしてコンテンツを収める
3. Safe Area Layout Guide外を活用

iPhone Xの対応を行う場合、「2.」まで行わないとRejectされる可能性があります。

## step1. 上下の帯をなくす
**必要な作業**
1. Xcode 9でBuildを行う

これだけで、iPhone Xで上下の帯が表示されなくなります。

逆に、iPhone Xの対応する気がないのにXcode 9でBuildを行った結果、上下の帯がなくなりHome Indicatorとコンテンツが重なって、一部操作ができないということが起こりえます。これは最悪申請時にRejectとなります。

## step2. Safe Area Layout Guideを有効にしてコンテンツを収める
**必要な作業**
1. `Use Safe Area Layout Guides` にチェックを入れる
	1. Storyboard開き、`Safe Area Layout Guides`を適用させたいViewControllerを選択する
	2. `Navigator`から`File Inspector`を表示する
	3. `Interface Builder Document`の`Use Safe Area Layout Guides` にチェックを入れる
	![ss01.jpg](https://qiita-image-store.s3.amazonaws.com/0/154832/d6a014c7-7ea5-47e8-8623-6f2046adcee8.jpeg)![ss02.jpg](https://qiita-image-store.s3.amazonaws.com/0/154832/915ce793-2d14-ec3f-1804-374bd3bbf2b7.jpeg)

2. `Safe Area Layout Guide`からはみ出ているコンテンツがあれば、`Safe Area Layout Guide`内に収まるように制約を修正

Xcode 9から導入された`Safe Area Layout Guide`の説明は、以下です。
* `Auto Layout Guide`の`Top Layout Guide`と`Bottom Layout Guide`の間の領域が置き換わったモノ
* iOS 9.0以降で使用できる機能

また、Xcode 9からは、`Top Layout Guide`と`Bottom Layout Guide`がDeprecatedになり、`Safe Area Layout Guide`に置き換えるように言及されています。

元からコンテンツを`Top Layout Guide`と`Bottom Layout Guide`の間に収めていれば、特に対応なくチェック1つで`Safe Area Layout Guide`へ移行できます。

## step3. Safe Area Layout Guide外を活用
**必要な作業**
1. コンテンツによってまちまち

これに関しては、可能ならやったほうがいいですが、プロジェクト次第かと思います。

**メリット**
* 見栄えがいい
* iPhone Xを使用しているユーザの満足度が高まる

**デメリット**
* 対応のコストがかかる

例としては、Safariが最たる例だと思うので、`UIWebView`や`WKWebView`を実装している場合は、見習った動きを実装するべきだと思います。

Safe Area Layout Guide外の活用は、今後面白い使い方や良い使い方が出てくるので、それを参考にしていくと良いと思います。(何かいいアプリの例があれば教えて下さい。)
開発を効率化するこまごましたこと

Androidエンジニアの @mapyoです。
開発を効率化する事が好きです。僕が日々やっていて、便利だなと思う事をいくつかご紹介します。


## hub コマンド
コマンドラインから、GitHubのapiと叩いていろいろと操作出来るコマンドです

ざっくり以下を見てもらえればわかるかと思います。
https://hub.github.com/
https://qiita.com/00TATa00/items/ceb4f534af08cde4b921

僕が主に使っているのは以下の２つです。

#### developブランチに対して現在のブランチからプルリクエストを送る
```bash
hub pull-request -o -b develop
```

これでプルリクのタイトルと内容をvimで編集して保存すると、
プルリクが作成され、作成されたプルリクがブラウザの画面で開きます。
(実際には長いのでaliasを設定しています)

ブラウザを開いてぽちぽち作業するよりも、コマンドライン上からちゃちゃっとプルリク作って細かい所修正していく方が効率的に作業が出来ます。

#### 現在ターミナルに表示されているリポジトリをブラウザで開く
```bash
hub browse
```

これでブラウザ上で開く事が出来ます。


## git-checkout-this-pr
プルリクエストをレビューする時にちょっと手元に落としてきてソース見てみたいなと思うことがあると思います。
そんな時は、このコマンドを打てばささっと解決です。

元ネタはこちらです。
http://motemen.hatenablog.com/entry/2014/07/04/git-checkout-this-pr

しかし、月日が流れて動かなくなってしまっているので、個人的にちょこちょこ修正しているので、
もし使いたいという方がいらっしゃいましたらこちらを御覧ください。
https://github.com/mapyo/dotfiles/blob/master/bin/git-checkout-this-pr




## Android Studioで今開いている行をGitHubで開く
Preference→Version Control→Github
こちらでGitHubと連携させるだけ。

後は右クリックでコンテキストメニューを開いて、下の方の
Open on GiHubをクリックするとGitHubで開くようになります！

<img src="https://qiita-image-store.s3.amazonaws.com/0/6878/57ee06aa-ef77-811a-2329-d7bc788ce3a9.png" width="150">


Android Studioだけじゃなく、JetBrains製のエディタであれば同じようにいけるはず。


## Android Studioでコンテキストメニューを開くショートカット

GitHub連携出来たと思ったら、マウスに手を伸ばしていちいち右クリックをおさないといけないのがめんどくさい。
ということでコンテキストメニューをキー操作で開けるようにします。

keymapの画面で`Show Context Menu`と検索して出てきたやつにショートカットを割り当てればOKです。

<img src="https://qiita-image-store.s3.amazonaws.com/0/6878/2704c055-ca50-f656-3c0b-58a576edec5e.png" width="400">



## Gitで１つ前のブランチに戻る
だいぶ雑になってきましたが、以下のコマンドで１つ前にみていたブランチに戻れます

```bash
git checkout -
```


関連ネタとして、

```bash
cd -
```
これで一つ前に見ていたディレクトリに移動するというのがあります。


## Gitでmasterのブランチを最新にして、Merge済のローカルブランチを削除する

https://github.com/mapyo/dotfiles/blob/master/.gitconfig#L19-L20

こんな感じで`.gitconfig`を書いてます。内容を見てもらえればだいたいわかると思いますが、

1. fetch
2. masterにcheckout
3. masterをpull
4. Merge済のローカルブランチを一通り削除

このような流れの処理をしてくれます。
いつも、何かするときには、`git up`を実行して最新にしてからブランチを切ったりするようにしています。
これのdevelopブランチ版で、`git upd`も作ってたりしてます。



## 最後に
いかがでしたでしょうか？今年も残すところあと少しとなりましたね。
少しでも手間がかかる作業を自動化して効率よく開発を進めていきたい今日この頃です。
Windows 10 Fall Creators Update 版のコンピューターを Azure AD に参加 (join) させる方法


# はじめに

Azure AD ってコンピューターを登録して管理することができるらしいよ!

でもなにやら Windows 10 Fall Creators Update 版は「バージョン情報」の画面に「職場または学校への接続」のリンクが無い!
![image](https://qiita-image-store.s3.amazonaws.com/0/213384/b920878d-66e9-4d53-ad9e-95abdad1476c.png)
([Windows 10 Creators Update 版以前のリンクのある画面はこちらを参照 (hateblo.jp)](http://edge.hateblo.jp/entry/2017/08/09/214856))

一体どうすれば…。

ここではそんな疑問を解決してみます。

# やり方

実をいうと「職場または学校への接続」へのリンクは別の場所へ移動されました。
「設定」ウィンドウからホーム > アカウント、と辿ると左ペインに「職場または学校にアクセスする」というリンクがあります。
![image](https://qiita-image-store.s3.amazonaws.com/0/213384/1d1f1fe5-3b09-bee5-b85c-56a65d209bc2.png)

これをクリックすることで、次の画面に遷移します。
![image](https://qiita-image-store.s3.amazonaws.com/0/213384/86c0b65b-6b2a-0a88-6f20-7809616cd7aa.png)

「接続」をクリックすると「職場または学校アカウントのセットアップ」ダイアログに移動します。
![image](https://qiita-image-store.s3.amazonaws.com/0/213384/b9063b6a-902f-a364-3151-9e1c02c9f13d.png)

「このデバイスを Azure Active Directory に参加させる」をクリックし、アカウントとパスワードを入力していきましょう。
![image](https://qiita-image-store.s3.amazonaws.com/0/213384/e9a0fac6-eadd-4fce-2abd-30b332ec81ce.png)
![image](https://qiita-image-store.s3.amazonaws.com/0/213384/92431101-6b50-1299-674a-ef91688768db.png)

すると、「これがあなたの組織のネットワークであることを確認してください」と言われますので、問題なければ「参加する」をクリックしましょう。
![image](https://qiita-image-store.s3.amazonaws.com/0/213384/e38d176b-84ee-dafd-4883-cd90967ffb11.png)

しばらく待たされ…。
![image](https://qiita-image-store.s3.amazonaws.com/0/213384/d5cb37d9-700a-a57f-e0e9-fb28c0a57bbe.png)

無事に参加できたことが表示されます。
![image](https://qiita-image-store.s3.amazonaws.com/0/213384/d532bd12-e924-e4fc-05da-5c260718d6c8.png)

# 確認

登録できたことを確認するには、[Azure ポータル (azure.com) ](https://portal.azure.com/)から Azure Active Directory 画面にアクセスします。
![image](https://qiita-image-store.s3.amazonaws.com/0/213384/e425ea70-705d-73f5-8614-7bb1974a50b3.png)

Azure Active Directory 画面右「デバイス」を選択し、先ほど登録したコンピューターが表示されていることを確認します。
![image](https://qiita-image-store.s3.amazonaws.com/0/213384/cabf0674-fa5e-c6b9-e7bd-ad93184c8cc3.png)

「結合の種類」が「Azure AD joined」になっていれば OK です。

また、コンピューターからも以下のコマンドで確認できます。
AzureADJoined が YES になっていれば OKです。

```
PS C:\WINDOWS\system32> dsregcmd /status

+----------------------------------------------------------------------+
| Device State                                                         |
+----------------------------------------------------------------------+

          AzureAdJoined : YES
(以下省略)
```

# Appendix

書き終わりかけの段階で以下のドキュメントと完全に被ったことが判明しましたとさ。
[Azure Active Directory 参加済みデバイスの設定 (microsoft.com)](https://docs.microsoft.com/ja-jp/azure/active-directory/device-management-azuread-joined-devices-setup)

「結合の種類」が「Azure AD Registered」となっている端末は、Azure AD アカウントでログオンしただけで、Azure AD には登録されていません。
この状態は、「職場または学校アカウントのセットアップ」ダイアログが表示された段階で、そのままメールアドレスを入力していく方向で進めた場合になりますので、もう一度手順を確認してください。

dsregcmd.exe コマンドのパラメーターの意味を詳しく知りたい方は[こちらをご覧ください (microsoft.com)](https://docs.microsoft.com/ja-jp/azure/active-directory/device-management-troubleshoot-hybrid-join-windows-current)。
Visual Studio | WPF > Window > マルチモニタ実行時にウィンドウのHeight, Widthを取得する

```txt:動作環境
Windows 8.1 Pro (64bit)
Microsoft Visual Studio 2017 Community
```

### 関連

- [c++ builder > form > モニタ解像度の取得 > Screen->Monitors[0]->Width; / ->Height; // Screen->PrimaryMonitor->](https://qiita.com/7of9/items/228a65f799f5181e916e)
- [c++ builder > Form > 4つのFormをモニタいっぱいに並べる](https://qiita.com/7of9/items/b858ea2f947629f47810)

### 処理

WPFにてマルチモニタ実行時にウィンドウのHeightやWidthを得るにはどうするか。

StackOverflowのいくつかの回答ではWinFormsを使う例があるが、WPF使用時にWinFormsを使いたくはない。異なる設計思想のものを組合わせるとどこかで帳尻合わせをするためのおかしな実装を誘発するように思う。

WPFではSystemParametersにVirtualScreenがあるようだ。
https://stackoverflow.com/questions/2704887/is-there-a-wpf-equaivalent-to-system-windows-forms-screen

これをSystemParametersのPrimaryScreenHeightなどと合わせて使ってみた。

### code 

```MainWindow.xaml
<Window x:Class="_171225_t1450_multiMonitors.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:_171225_t1450_multiMonitors"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Name="B_monitors" Height="30" Content="Check Monitors"
                Click="B_monitors_Click"/>
    </Grid>
</Window>
```

```MainWindow.xaml.cs
using System.Windows;

namespace _171225_t1450_multiMonitors
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void B_monitors_Click(object sender, RoutedEventArgs e)
        {
            // Primary
            var pheight = SystemParameters.PrimaryScreenHeight;
            var pwidth = SystemParameters.PrimaryScreenWidth;
            // Combined
            var vheight = SystemParameters.VirtualScreenHeight;
            var vwidth = SystemParameters.VirtualScreenWidth;
            //
            string msg = string.Format("Combined: {0}x{1}", vwidth, vheight);
            msg += System.Environment.NewLine;
            msg += string.Format("Primary: {0}x{1}", pwidth, pheight);
            MessageBox.Show(msg);
        }
    }
}
```

### 実行例

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/2f7ec8c3-d20a-5b3b-8938-a75134e3515a.png)

異なる解像度を持つ複数のモニタに対してソフトを実装する場合は、いろいろ考えることはでてきそう。

同じ解像度を持つ複数のモニタに対しては、簡易な処理で対応できる。

### link

- [SystemParameters クラス](https://msdn.microsoft.com/ja-jp/library/system.windows.systemparameters(v=vs.110).aspx)