OmniAICreator/Qiita-1.07M huggingface dataset:
社会人のための健康ライフハック

皆さまはじめまして。
本記事は、「アプレッソ Advent Calendar 2016」6日目の記事です。

突然ですが、私はエンジニアではありません。
エンジニアではないのですが、エンジニアの方々と席を並べてお仕事をしているご縁もあり、
この度記事を書かせていただく運びとなりました。

「とにかく技術にまつわるネタを書きます。」という趣旨ですが、
私からは健康に関する技術ということで、
「社会人のための健康ライフハック」を紹介していこうと思います。

世の中には「健康のためなら死んでもいい」というくらいのスタンスで
ストイックな生活をされている方もいますが、
以下はすべて私の実感によるものであり、よって、とても緩いライフハックとなります。
そんなの常識でしょ～！となるような内容もあるかと思いますがご容赦ください。

*※本記事の内容はすべて個人の感想であり、効能を保証するものではありません*


# 眼の負担を減らす
**・ディスプレイの明るさは可能な限り暗くする**
**・眼鏡をかけるならブルーライトカットのものを**

エンジニアに限らず、多くの方がPCを長時間使用する日々を送っているかと思います。
私は社会人になり長時間PCを使用するようになった当初、
それまでは無かった頭痛に悩まされたのですが、
解決すべく試行錯誤をした結果、上記を実行するに至りました。
これが功を成したのかは不明ですが、結果的に私の頭痛は軽減したので
頭痛や目の疲れに悩む方はぜひお試しください。

因みに私のディスプレイ（ノートPC）の設定はこれです。

![aaa.png](https://qiita-image-store.s3.amazonaws.com/0/146571/f19ec87e-bcc1-bb16-d27b-fb98c782a143.png)


# 良い睡眠のためにカフェインを控える
**・18時以降はカフェインを摂取しない**
　**→代用のノンカフェイン飲料はルイボスティーとフルーツ酢**

睡眠の質に関しては「睡眠前に布団でスマホをいじるのはやめましょう」と
よく言われていますね。ただ、私にとってはハードルが高かったため
出来ることを無理なく行った結果、現在は上記に落ち着いています。

私には10年以上もの期間、夕食後にコーヒーを飲む習慣があったのですが、
昨年にふとした思い付きで夜のコーヒーを絶ってみたところ、
なんだか寝起きの調子が良い気がするぞ、となりそのまま続いている次第です。
代わりに何を飲もう、と調べた結果ルイボスティーが健康に良さそう！となったのですが、
味に癖があり、1年飲み続けた今でも慣れません。笑。
フルーツ酢は色々な味のものがあり、色々試している最中です。
飲み方は水割りも良いですが、無糖の炭酸水割りがおすすめです。


# 身体を温める
**・ロング腹巻**
**・電気ブランケット**

上記2点とも、今年から使い始めたものです。

腹巻には天才バカボンのイメージが強くあり、
「ただでさえ無い腹回りのくびれがますます無くなってしまうのでは…」
と思っていたのですが、薄手で胸から尻までをすっぽり覆うロングタイプのものを
見つけて購入してからはすっかり愛用品となってます。
これで多少寝相が悪くとも、睡眠中にお腹を冷やすのを防げますし、
冬の朝の着替え時の防御力が上がります。

また電気ブランケットは、電気代が電気ストーブよりも安くなることを
期待して取り入れてみたのですが、
使ってみたら電気ストーブ以上に下半身を温めてくれる優れものでした。
(もちろん上半身にも使用できますが、私は椅子に座る際に腰～脚に巻いて使用しています)
持ち運べる炬燵（足先のぞく）といった感じでとてもおすすめです。
<BR>
* * *
以上、とてもささやかな内容ですがお役立ていただけますと幸いです。

寒さが厳しくなるうえに仕事も忙しくなる12月、
皆さまお身体に気を付けてお過ごしください。
BigQueryのStandardSQLのUDFでSTRUCT型を返すときは`<...>`で型を指定する


はじめに
=======

BigQueryのStandardSQL では、`CREATE [TEMPORARY] FUNCTION` でちょっとした関数を定義できますが、STRUCT型を返すときの書き方がなかなかググれなかったのでメモです。

書き方
========

STRUCT型の中身を `<` `>` で囲って指定すればOKです。

例
-----

```sql
CREATE TEMPORARY FUNCTION parse_json(json_str STRING) 
RETURNS STRUCT<name STRING, birthday STRING, mail STRING> 
LANGUAGE js AS """
  return JSON.parse(json_str);
""";

SELECT parse_json('{"name": "hogehoge", "birthday": "2000-01-01", "pref": 31}') as user
```

↓ 結果


|Row| user.name|user.birthday|user.mail|
|--:|---------:|------------:|--------:|
|1  |hogehoge  |2000-01-01   |null     |

となります。

`<>` で指定しなかった列 `pref` は出力されませんし、キーが無かった`mail`は`null`になります。

さいごに
========

一応、ここ https://cloud.google.com/bigquery/docs/reference/standard-sql/migrating-from-legacy-sql には書いてあるんですが、みつけるまでに時間がかかりました。。
任意のアプリケーションをショートカットキー(ホットキー)で起動できるducko作った

# 経緯

巷のスーパーエンジニアの方々はコマンドラインベースで作業をされるとのことで、私もそれに習って、コマンドラインベースで作業をしようと画策。cmd.exeをいちいちスタートメニューから選択して実行するわけにもいかないので、デスクトップにショートカットアイコンを作成し、そこにショートカットキーを設定してキーボードから起動できるようにしていました。ですが、起動が遅い、ショートカットキーを押してから3秒くらい待たされる。すごいストレス。ならば、常にcmd.exeが起動していて、いつもは裏に隠れているけど、ショートカットキーを押したら表示されるようなアプリを作ればいいのでは？と思いつく。

# 成果物

そして出来上がったものがこちらになります。

https://github.com/bamchoh/ducko

# ビルド方法

* `go build` でビルドをするとなぜか終了を待つようになってしまうので、`mingw32`を起動して、`make`しないといけません。

# 使い方

```
> ducko -hotkey O -exec cmd.exe /k init.cmd
```

引数にショートカットキー(CTRL+ALT+指定したキー(A-Z))と起動したいアプリケーションを渡して起動すると、裏で起動して、ショートカットキーの入力を待ちます。ショートカットキーを押すと、指定したアプリケーションが起動します。

今のところショートカットキーはCTRL+ALTは固定です。アルファベットのみ変更可能です。タスクスケジューラでログイン時に起動するようにしておけばよいのではないでしょうか。

ちなみに `-work` を指定すると起動する作業ディレクトリを設定することができます。

# 名前の由来

子プロセス抱えてずっと起動しているその姿が抱っこしている母親のようだということで、だっこ -> dakko -> ducko になりました。

...

ええ、ダジャレです。

# 課題

* 使い始めて1日も経っていないので、アレですが、これでほんとに便利になるのかなぁとちょっと疑心暗鬼です。

# 参考資料

猫でもわかるプログラミング
http://www.kumei.ne.jp/c_lang/

本物の golang を... 本物の Gopher を、お見せしますよ。
http://qiita.com/mattn/items/b7889e3c036b408ae8bd
SATソルバーMiniSatとSugarを導入

`Sugar`を急遽使用することになったので、
`MiniSat`と`Sugar`を新たに購入した`Mac`に導入してみました。




- **MiniSat**: 充足可能問題の解を導出するSATソルバーの1つ。
(参考：[MiniSat公式HP](http://minisat.se/Main.html))


- **Sugar**: SAT型の制約ソルバー。高速なMiniSatを用いる。
(参考：[Sugar公式HP](http://bach.istc.kobe-u.ac.jp/sugar/))


# 今回の環境 (前提)
- macOS Sierra 10.12.1
- Homebrew  "1.1.1"
- gcc version 5.4.0
- Java 5導入済み
- Perl 5導入済み (Macのデフォルト)



# MiniSat導入
公式HPからダウンロードして、パッチ適用やutils/System.ccを書き換えなどが必要…と思いきや、Homebrewで簡単にインストールできることが判明！ 以下のコマンドから、インストールできます。


**1. インストール**

```
$ brew install minisat
```


*<実行結果>*


```
==> Downloading https://homebrew.bintray.com/bottles/minisat-2.2.0.el_capitan.bo
######################################################################## 100.0%
==> Pouring minisat-2.2.0.el_capitan.bottle.1.tar.gz
🍺  /usr/local/Cellar/minisat/2.2.0: 4 files, 91.8K
```

  

**2. 実行確認**

以下のコマンドで、適当なディレクトリにてMiniSatが実行できるか確かめてみます。

```
$ minisat
```


以下のようなものが出れば成功です。

*<実行結果>*

```
Reading from standard input... Use '--help' for help.
============================[ Problem Statistics ]=============================
|                                                                             |
```

# Sugar導入


**1. インストール**


[Sugar公式HP](http://bach.istc.kobe-u.ac.jp/sugar/)から最新版Version 2.2.1(sugar-v2-2-1.zip)をダウンロードして解凍。
ダウンロードしたフォルダに移動します。

```
$ cd sugar-v2-2-1/bin
```


環境設定する必要があるため、このbin内のsugarを以下のように自分の環境に合わせて編集する。


```
my $version = "v2-2-1";
my $java = "java";
my $jar = "/Users/ユーザ名/Desktop/sugar-v2-2-1/bin/sugar-v2-2-1.jar";  //ダウンロードしたファイル内のjarファイルの位置を指定
my $solver0 = "/usr/local/bin/minisat";
my $solver0_inc = "minisat-inc";
my $tmp = "/Users/ユーザ名/Desktop/sugar-v2-2-1/tmp_sugar/sugar$$";  //tmp_sugarなどの適当なディレクトリをあらかじめ作成しておき、指定
```


その後、usr/local/binにsugarを移します。

```
$ mv sugar /usr/local/bin
```



これでひとまず導入は完了です。


**2. 実行確認**
次に、minisatと同じく、適当なディレクトリにてSugarが実行できるか確かめてみます。

```
$ sugar
```


出力として、help的なものが出れば成功です。


# Sugar実行例


`$ sugar [options] cspfile名`で実際にcspファイルを実行できます。



試しに、 ダウンロード場所/sugar-v2-2-1/examplesに移り、exampleの1つを実行してみます。


```
$ sugar nqueens-8.csp
```


*<実行結果>*

```
s SATISFIABLE
a q_1	7
a q_2	2
a q_3	4
a q_4	1
a q_5	8
a q_6	5
a q_7	3
a q_8	6
a
```


上記のような1つの解が出れば、成功です。
mac(macOS Sierra)で音声入りの動画（画面キャプチャ）を取る方法

mac(macOS Sierra)で音声入りの動画（画面キャプチャ）を取りたくなったため、実施方法を調べ、実施した。
調べるのに意外と時間がかかったため、まとめる


## 必要なもの
- macOS Sierra
- QuickTime Player
- Soundflower
- LadioCast

## 使用するソフトの説明
### QuickTime Player
動画を取るために使用
macOS Sierra標準アプリケーション

### Soundflower
音声入りの動画（画面キャプチャ）を作るために使用

### LadioCast
音声入りの動画（画面キャプチャ）を取っている際に、自分でも音声を聞けるようにするために使用する。
そのため、音を聞く必要がなければ、Soundflowerのみで動画を作ることは可能


## 導入
以下をインストールして下さい。
Soundflowerをインストールする
https://github.com/mattingalls/Soundflower/releases/tag/2.0b2


LadioCastをインストールする
https://itunes.apple.com/app/ladiocast/id411213048

## 手順
### 1. システムサウンド設定
システム環境設定→サウンドからSoundflower(2ch)を選択
   
   ![サウンド_と_Mac_Quick_Time_Player_で音声入りの動画を取る方法.png](https://qiita-image-store.s3.amazonaws.com/0/118618/339cac59-eba7-9d36-ba95-ce4b7d95b3e7.png "サウンド_と_Mac_Quick_Time_Player_で音声入りの動画を取る方法.png")

　　もしくはメニューバーに音量を表示している場合、クリックし設定
　　
### 2. LadioCast設定
LadioCastを起動

   ![ミキサー_.png](https://qiita-image-store.s3.amazonaws.com/0/118618/76f1a8cf-2a17-63bb-d559-2520351d2158.png "ミキサー_.png")
   
上記に変更する。
入力1：Soundflower(2ch)
出力メイン：内蔵出力

### 3. QuickTime Player設定
QuickTime Playerを起動
左上のメニューからファイル→新規画面収録すると以下の画面になるので▼をクリックし、Soundflower(2ch)を選択

![画面収録_と_Mac_QuickTime_Player_.png](https://qiita-image-store.s3.amazonaws.com/0/118618/6a96d6ae-a974-b127-2f6b-864a0841756b.png "画面収録_と_Mac_QuickTime_Player_.png")


### 4. 録画
録画ボタンを押す。


## 参考
Soundflowerを用いて音声入りの画面キャプチャを撮る方法
http://qiita.com/Sasakky/items/09e3bc1536f0569fc893
すぐできる！Java100本ノックをSlackに自動投稿するBot

# はじめに
先日、[JJUG CCC 2016 Fall](http://www.java-users.jp/ccc2016fall/)に参加してきました。
その中で[Java100本ノック](https://github.com/JustSystems/java-100practices/)が紹介されており、面白そうだから社内でもやってみようかという話になりました。
Slackに問題を自動投稿するBotをスプレッドシートとGASで作ってみたので、よければ参考にしてみてください。

## 手順
### １．問題番号を保存するスプレッドシート作成
![Java100本ノックSlackBot_-_Google_スプレッドシート.png](https://qiita-image-store.s3.amazonaws.com/0/41569/aad9d741-5f11-25ce-430e-78cc7c620751.png)

### ２．スクリプトエディタを開く
スプレッドシートのメニューから「ツール」→「スクリプトエディタ」を選択します。

### ３.GASにSlackAppライブラリを導入する
スクリプトエディタのメニューから「リソース」→「ライブラリ」を選択し、以下のLibrary Keyを入力します。

SlackAppのLibrary Key →　M3W5Ut3Q39AaIwLquryEPMwV62A3znfOO

### ４．Slackのトークンを発行
[こちらの記事](https://elstreet.style/?p=1124)を参考に、Slackのトークンを発行します。

### ５．コード作成
スクリプトエディタに以下のコードを貼り付けます。
TOKEN定数は上記で取得したトークンに置き換えてください。

```js
var URL = "https://github.com/JustSystems/java-100practices/tree/master/contents/";
var TOKEN = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // 取得したトークンを貼り付け

function main() {
  // 平日のみ投稿
  var today = new Date();
  if(isJapaneseHoliday(today) || today.getDay() == 0 ||today.getDay() == 6){return;} 
  
  var qNumRange = SpreadsheetApp.getActiveSheet().getRange(1, 2);
  var qNum = qNumRange.getValue();
  postSlackMessage(qNum);
  
  // 問題インクリメント
  qNum++;
  if(qNum > 100){ qNum = 1;}
  qNumRange.setValue(qNum);
}


function postSlackMessage(qNum) {
  var slackApp = SlackApp.create(TOKEN); //SlackApp インスタンスの取得
 
  var options = {
    channelId: "#java100knock",
    userName: "Java100本ノックBot",
    message: "今日の問題はこちら！\n" + 
             URL + ('000' + qNum).slice( -3 ) // 問題番号0埋め         
  };
 
  slackApp.postMessage(options.channelId, options.message, {username: options.userName});
}

function isJapaneseHoliday(date) {
  var year = date.getFullYear();
  var month = date.getMonth();
  var day = date.getDate();
  
  var startDate = new Date();
  startDate.setFullYear(year, month-1, day);
  startDate.setHours(0, 0, 0, 0);

  var endDate = new Date();
  endDate.setFullYear(year, month-1, day);
  endDate.setHours(23, 59, 59, 999);

  var cal = CalendarApp.getCalendarById("ja.japanese#holiday@group.v.calendar.google.com");
  var holidays =  cal.getEvents(startDate, endDate);

  return holidays.length != 0;
}
```

この状態でmainメソッドを実行すると、Slackのjava100knockチャンネルに問題が投稿されます。

### 6.起動トリガーを設定
スクリプトエディタのトリガーアイコン（時計のマーク）より、トリガーを設定します。
![Java100Knock.png](https://qiita-image-store.s3.amazonaws.com/0/41569/09aed4a2-b51d-d41d-69e2-bcaca7bc1def.png)

この設定で毎朝8~9時に問題が自動投稿されます。(ソース内で平日のみ投稿するように制御しています）

投稿された問題は以下のような感じになります。
![Slack_-_Paygent.png](https://qiita-image-store.s3.amazonaws.com/0/41569/50daabff-e270-aa33-b985-d2d0faf129d4.png)


#### 参考
- [Slack BotをGASでいい感じで書くためのライブラリを作った](http://qiita.com/soundTricker/items/43267609a870fc9c7453#botとして動かしてみる)
- [初心者がGASでSlack Botをつくってみた](http://tech.camph.net/slack-bot-with-gas/)
- [GoogleAppsScriptで日本の祝日を取得する](http://qiita.com/kamatama_41/items/be40e05524530920a9d9)
Prezto の command-not-found なる module を使ってみた。

`Prezto` という `Zsh` plugin を使っています。 Install 方法は


`zplug` と `prezto` を install してみた。
http://qiita.com/ticonz/items/fae0d576b3bb00857b50

に書きました。

`$HOME/.zplug/repos/sorin-ionescu/prezto/modules` ( ただしこの directory は上の記事の方法で install したときのもの。標準とは異なる ) を見ると、いろいろと module が用意されています。今回はそのうち `command-not-found` なるものを使ってみました。

# 導入

次の方法 0 、 1 のどちらでも大丈夫です。

## 方法 0
`.zshrc` に

```
if [[ -s "${ZDOTDIR:-$HOME}/.zplug/repos/sorin-ionescu/prezto/modules/command-not-found/init.zsh" ]]; then
  source "${ZDOTDIR:-$HOME}/.zplug/repos/sorin-ionescu/prezto/modules/command-not-found/init.zsh"
fi
```

と書きます。

## 方法 1

上の記事の方法で `zplug` を install した場合、 `.zshrc` に

```
source ~/.zplug/init.zsh

zplug "sorin-ionescu/prezto"

zplug load --verbose
```

があるはずです。これの `zplug "sorin-ionescu/prezto"` の次の行に

```
zplug "modules/command-not-found", from:prezto
```

を加えます。

この方法はコメントで教えていただきました。ありがとうございます。

# 機能

未 install の command を `Zsh` で打つと、 install 方法が表示されるようになります。

## 例 0

```
$ tcsh
```

の結果

### before

```
zsh: command not found: tcsh
```

### after

```
The program 'tcsh' is currently not installed. You can install it by typing:
sudo apt install tcsh
zsh: command not found: tcsh
```

## 例 1

```
$ qmail
```

の結果

### before

```
zsh: command not found: qmail
```

### after

```
No command 'qmail' found, did you mean:
 Command 'dmail' from package 'uw-mailutils' (universe)
 Command 'qail' from package 'qmail' (universe)
 Command 'kmail' from package 'kmail' (universe)
 Command 'mail' from package 'mailutils' (universe)
 Command 'tmail' from package 'uw-mailutils' (universe)
 Command 'cmail' from package 'xboard' (universe)
 Command 'rmail' from package 'masqmail' (universe)
 Command 'rmail' from package 'postfix' (main)
 Command 'rmail' from package 'exim4-daemon-light' (main)
 Command 'rmail' from package 'exim4-daemon-heavy' (main)
 Command 'rmail' from package 'rmail' (universe)
 Command 'rmail' from package 'courier-mta' (universe)
 Command 'wmail' from package 'wmail' (universe)
zsh: command not found: qmail
```

# 所感

これは便利だと思います。 `command not found` と言われた後、ぐぐったり `apt-cache search` で探す手間が省けます。
入社してから読むようになったWebサイト、ニュースサイト

#はじめに
「[新人AdventCalendar2016](http://qiita.com/advent-calendar/2016/freshman_engineer)」5日目の記事です。
本記事がQiita初投稿です。

#世の中にはこんなにも情報が溢れていた！
4月に入社してからもう年の瀬。これまでに業務を行う上で、助けられた、ためになった、参考にしてきたサイトを紹介します。プログラミング、機械学習、IT業界に関するサイトが主です。

#紹介
1. [Qiita](http://qiita.com/)
ここにたどり着いているのだから紹介も何も…という感じですが、私は主にトラブルシューティングで参考させていただいています。

2. [teratail](https://teratail.com/)
お世話になったことはまだないですが、
・回答の早さ
・回答率の高さ
はすごいなぁと眺めているところです。

3. [dots.](https://eventdots.jp/)
勉強会探しに使っています。
渋谷にあるdots.にも数回行ってみたこともあります。きれいなところです。

4. [connpass](https://connpass.com/)
dots.同様に勉強会探しに使っています。個人的にはこちらのほうが見やすく好きです。

5. [IT media](http://www.itmedia.co.jp/)
業界ニュースからディープなニュースまで扱っているIT総合情報ポータル。

6. [こみねのメモ](https://www.ibm.com/developerworks/community/wikis/home?lang=ja#!/wiki/%E3%81%93%E3%81%BF%E3%81%AD%E3%81%AE%E6%8A%80%E8%A1%93%E3%83%A1%E3%83%A2)
IBM developer Worksの中にあるサイト。業務上、IBM製品の技術に触れることが多いので、参考にさせていただいています。

7. [Think IT](https://thinkit.co.jp/)
株式会社インプレスが運営している技術解説サイト。


8. [とほほのWWW入門](http://www.tohoho-web.com/)
Webサイト作成、プログラミングをする上で基礎的なところをお世話になったサイト。


#おわりに
ブックマークしているサイトの紹介でした。
記事のブラッシュアップは後々していく形で、AdventCalendarの記事に入れておきます。
明日は[@_popopopoon_](http://qiita.com/_popopopoon_)さんです。
concrete5(CMS)をウェブサービスのベースとして活用する

この記事は[concrete5 Japan Advent Calendar 2016](http://www.adventar.org/calendars/1439)の５日の記事です。4日の記事はtao-sさんの[Ver.8 から使えるExpressオブジェクトとは？](http://c5blog.xross-cube.com/express%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%A8%E3%81%AF/)です。

本日の記事は、ウェブサービスをconcrete5ベースで作ったので、その経過を紹介する、というものです。

## 作ったウェブサービス
[マイ見積](https://my-mitsu.jp/)を作りました。ホームページの訪問者が、フォームの項目を選ぶと、金額を自動計算して、見積書PDFを発行できるサービスです。問い合わせフォームの高機能版と考えてもらうと分かりやすいと思います。
通常は見積書を受注側が作るケースが多いですが、発注側が自分で項目を選んで見積作成する、ということでマイ見積という名前にしています。

![my-mitsu-jp.png](https://qiita-image-store.s3.amazonaws.com/0/31643/66164d25-70e7-987b-5012-5f1658939c67.png)

マイ見積の前段階として、[計算フォーム](http://calculator.jp/)というウェブサイトも公開しています。

## concrete5を使うメリット
concrete5を使うメリットについては、以下のようなものがあります。

- concrete5の標準機能で、アカウント管理機能など、ウェブサービスに必要な機能をかなりカバーしている
- 公式サイトで、追加機能がパッケージとして公開されている
- 自社で追加開発した機能をパッケージとして公開できる

実際、アカウントを登録する、アカウント毎に実行できる機能を制御する、など、ユーザー管理に関する部分の多くが、concrete5の標準機能として用意されています。また追加パッケージも、審査済みのものが公式サイトで公開されているので、安心して利用することができます。

パッケージ利用は主に以下の２つです。

- concrete5の標準機能では課金機能が用意されていないのですが、[Membership Subscriptions](http://www.concrete5.org/marketplace/addons/membership-subscriptions)というアドオンがあるので、こちらをベースにしています。日本円を選択できるようにカスタマイズしたり、日本語訳を追加したりして利用しています。
- マイ見積では、マイページへのリンクを管理バーに表示しているのですが、ここは[Link to Edit Profile](http://www.concrete5.org/marketplace/addons/link-to-edit-profile) をベースにカスタマイズしています。
- ログインを通知するために、[Login Alert](https://www.concrete5.org/marketplace/addons/login-alert)アドオンを利用しています。

さらに、ウェブサービス作成のために開発した機能を、公式サイトで公開することができます。マイ見積でも追加開発を行いました。

### 追加開発した機能
今回のウェブサービスで追加開発した機能は、

- 自動計算javascript、見積PDFを作成する機能
- 画像アップロードをドラッグドロップで行う機能

です。追加開発した機能を公式サイトで公開することで、多くの人に使ってもらうことができ、フィードバックが得られます。また有料で販売することもできるので、収益を得ることもできます。この辺は、12月12日のアドベントカレンダーで書きます。

ドラッグドロップで画像アップロードする機能は、[Simple Image Block](http://www.concrete5.org/marketplace/addons/simple-image-block)として公開していますので、誰でも利用することができます。標準のファイルマネージャ経由で画像をアップロードするのがまどろっこしい、という方などに便利です。

見積PDFを作成する機能は、公開に向けて準備中です。

## concrete5で作るデメリット
これまではメリットを書きましたが、デメリットもあります。concrete5はオープンソースなので理論上は自由に改変できますし、コアファイルをオーバーライドする仕組みも用意されていますが、concrete5の標準機能を大きく変更するのは大変です。

今回の案件で困ったのは、

- ブロック間の情報の共有
- ページの所有者が一人

です。

「ブロック間の情報の共有」は、ブロックからページ属性を参照・変更することで対処しました。こうすると、ブロックAでページ属性Xを変更する、ブロックBでページ属性Xを参照する、という方法で、情報を受け渡しできます。
実装上はかなり楽な方法ですが、しかし、こうすることにより、同一ページ上にブロックAは一個のみ、と制限されるので、この点は注意が必要ですが。

「ページの所有者が一人」は、複数ユーザーで同一ページを編集可能にしたい場合に、ページ所有者が複数設定できるのが一番シンプルに実装できそうだな、と考えたからです。
別の方法として、グループをたくさん用意する、という方法も検討したのですが、最終的には、ウェブサービスとしては、複数アカウントでの編集機能を提供しない、という形にしました。


6日の記事はhissyさん[concrete5 サイトをAMPに対応させる](https://concrete5.co.jp/blog/concrete5-amp)です。
Git 使用中にまさかの

仕事でgitを使っていて不要になったbranchを削除しようとしていて、

```
# git branch -d hoge 
error: The branch 'hoge' is not fully merged.
If you are sure you want to delete it, run 'git branch -D hoge'.
```

で-dだと削除できず、-Dで行いなさいみたいになった。
なんでできないんだと思ってgitのヘルプを使って調べようと思いました。

その時に

```
# git branch --help
Launching default browser to display HTML ...
```

ふぁΣ(ﾟДﾟ)
コンソールに出てくると思っていたらまさかのhtml呼出し
いや、こんな機能あったんかいw
みたいな状況になり笑いましたw

ちなみに

```
# git branch -h
```

でconsoleに表示みたいですね

ちなみに
git branch -dとgit branch -D
の違いは
git branch -d 「変更がすべてmergeされたブランチを削除するとき」
git branch -D 「mergeされていない変更が残っているブランチを削除するとき」
みたいですね

まだまだ知らない事ばかりです。

それではみなさん、よきgitライフをおおくりください!
JavaScriptのSpreadOperatorはhasOwnPropertyを見ていない？

何かおかしいところあったら教えてください。

## ことの発端

テスト用のデータとして、`['test1', 'test2', 'test3']`のように、100要素くらいある配列をサクッと生成してみたかった。

そして最終的に行き着いたのが次のコードだった。

```js
[...(Array(10))].map((_, i) => `test${i}`);
```

その後調べてみると、より正しそうな方法を書いたブログを見つけたので、実際に使うときはここを参考にすると良さそう。

[JavaScriptで0からn-1までを要素にもつArrayを作成する方法](http://blog.scheakur.com/post/96000209437/javascript%E3%81%A70%E3%81%8B%E3%82%89n-1%E3%81%BE%E3%81%A7%E3%82%92%E8%A6%81%E7%B4%A0%E3%81%AB%E3%82%82%E3%81%A4array%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95)

さて、上記のブログで目的は達成されたが、何故自分が書いたコードが動いていたのだろう。色々と試してみた。

**動作確認環境：Chrome 55.0**

## JavaScriptの配列の不思議

これは割と知っている人も多いことだと思うけど、`Array(10)`と`[10]`は違う。前者は「サイズが10の配列を作成」で、後者は「10という要素を持つ配列を作成」だ。

これを利用して、「10回ループを回すだけ」の目的で配列を作ろうとした。そのときのコードが以下。

```js
Array(10).forEach(e => console.log('hoge'));
```

ただし、これは期待通りに動かない。原因は、`Array()`が**lengthプロパティは持つが、配列の各要素は持たない配列**を生成するためだ。


よくわからないことを言っている気がするけど、次のサンプルを見ると明確だ。

```js
Array(10).length;
// => 10

Array(10).hasOwnProperty(0);
// => false

[10].hasOwnProperty(0);
// => true
```

ここからわかる事は、Arrayの`map`・`forEach`などの関数は、lengthプロパティだけでなくhasOwnProperty（又はそれに類するもの）を元にループを回すか判定しているということだ。

## 

そんなこんなで`Array(10).forEach()`というコードは動かないことがわかった。

そこで、（これは完全に思いつきで）ES2016のSpread Operatorを使ってみたらどうだろうと、試してみた。Spread Operatorは、オブジェクトや配列を展開してくれる式だ。

例えば、次のように使える。

```js
const aray1 = [1, 2, 3];
const array2 = [...array1, 4, 5];

console.log(array2);
// => [1, 2, 3, 4, 5]
```

今回のケースだと、こういう形になる。

```js
[...(Array(10))].forEach(e => console.log('hoge'));
```

すると、これは期待通りに動き、`hoge`が10回出力される結果となった。Spread Operatorにより、lengthのみだった配列が、要素を持った通常の配列に変換された。

```js
Array(10)
// => [undefined × 10]

[...(Array(10))]
// => [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]
```

つまりSpread Operatorは、**配列が実際に要素を持っているかどうかによらず、lengthの情報から配列の展開を行っている**らしい。`Array()`で初期化した配列は要素を持たないので、`undefined`を10個持つ配列に変換されたようだ。

ちなみに`Array.from()`でもSpreadOperatorと同様の結果になった。

```js
Array.from(Array(10))
// => [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]
```

## 結論

`map`や`forEach`は`hasOwnProperty`相当の評価を行ってループを回しているが、Spread Operatorではその判定は無い。

さて、これが何の役に立つのか...
カスタマーサポート活用のすすめ

[mixiグループアドベントカレンダー2016](http://qiita.com/advent-calendar/2016/mixi) 5日目は [manji602](http://qiita.com/manji602/items/8b53a55601b7e1d9e240) さんに続きCS部門開発チームからの2人目の刺客、私 otoyo がみなさまのサービスの縁の下の力持ち、カスタマーサポート部門についてゆるーくご紹介していきますのでリラークスしてお付き合いくださいね。

## 問い合わせたことってありますか？

あれは私がまだ28歳だった頃、土曜日だったでしょうか、スーパーから帰宅するとマンションの入り口にスーツをきた2人組の男性が立っていて、声をかけられました。
聞くと光回線の営業のようです。曰く、「大家さんの意向で回線を入れ替えることになったからサインして欲しい」。
今思えばどう見ても怪しいのですが、契約書に名前を書いてしまったのです。
やっぱりおかしいと思った当時28歳で無知で世間知らずの私は慌ててプロバイダのサポートに電話しました。
あのときの電話担当の方の口調、言葉遣い、思いやりは28歳になった今でも心に残っています。相当焦っていた28歳の私を早く安心させたいという気持ちが対応だけでなく言外にも伝わってきたからです。
「掛けた恩は水に流し、受けた恩は石に刻め」という言葉があるように、良い対応は必ずお客様の心に残ります。
街が赤と緑に染まるこの時期だからこそ、本日はみなさまがお客様に最高の体験をプレゼントするための一助になるようCS(カスタマーサポート/顧客満足)の活用について書きたいと思います。

## CSってなにをしているの？

「0次解決」という言葉を聞いたことがあるでしょうか？
お客様からいただいたお問い合わせに対し、CSスタッフのサポートや案内によって問題が解決するのは1次解決です。0次解決とはお問い合わせに発展しない、すなわちお客様であるユーザーが困らない状態を指します。
サポート不要のカスタマーサポート、一見矛盾しているようですが、これがCSの大きな目標の1つです[^1]。
[^1]: CSと一口に言っても、カスタマーサポート (Customer Support)、顧客満足 (Customer Satisfaction) などいろいろな意味を持っています。

お問い合わせ対応は業務の中で大きなウェイトを占めていますが、CSではそれ以外にも、ヘルプやお問い合わせフォームの管理、通報対応や不正対策なども行っています。

## CSは宝の山

どんなサービスでも、目指しているのはユーザーを楽しくしたり便利にしたりといった価値を提供することで、間違ってもユーザーを不便にしてやろうなんてサービスはないと思います。
それなのになかなか思うようにスタートアップが成長しない、良かれと思って行った施策が批判や不満の対象になる・・・なんてことはよくありますよね。
そんなときはCSスタッフに聞いてみましょう。「ユーザーが困っていることはなにか？」と。
CSは日々お客様と向き合っているので、お客様が何を望んでいるか、何に困っているかを誰よりもよく知っています。
残念なことにサービスの立ち上げ時や繁忙期には、しばしばリソースの都合で後回しにされがちですが、「サービスを使うのは誰か」という基本に立ち返ってみれば、CSの情報を活かさない手はないということはわかっていただけるでしょう[^2]。
[^2]: お問い合わせがすべてのお客様の意見を反映しているわけではないことに注意が必要です。

## CSデータの活用例

問い合わせは1件1件に注目することも大切ですが、何件も集まると時間や件数、不具合やリリース内容による傾向の変化など、多くの情報を持つようになるためマクロ的に見ることも重要です。
CSデータの活用の一例として、私が作成した問い合わせ数アラート(zenalert)をご紹介します。

問い合わせ数アラートとは、その名のごとく問い合わせ数が閾値を超えるとアラートするシステムです。

![zenalert1.png](https://qiita-image-store.s3.amazonaws.com/0/12897/6b998cbe-9079-e38a-8766-52aa9e289f71.png)

弊社ではチャットツールとしてSlackを、CS対応のメールツールとしてZendeskを導入しています(が、ツールは何でも構いません)。
問い合わせ数アラートは、CRONで一定時間ごとにZendeskから入信件数を取得し、閾値を超えていたらSlackに通知する仕組みになっています。


![Screen Shot 2016-12-04 at 3.04.23 PM.png](https://qiita-image-store.s3.amazonaws.com/0/12897/930a8c24-9d91-6ffb-f21f-b000288b92f9.png)

熟練のエンジニアであれば1時間足らずで作れるくらいシンプルなつくりですが、シンプルなつくりに似合わず2つの大きなメリットがあります。

### 1. エラーログに現れない不具合が察知できる

すべての不具合がエラーログに現れてくれれば良いですが、ときにはそうでない不具合も起こります。
問い合わせ数アラートがあれば問い合わせ件数の増加となってそれらを察知でき、被害を最小限に食い止めることができます。

### 2. アラートを起点としたコミュニケーションが発生する

問い合わせ数を可視化することでサービス運営者に関心を持ってもらえ、「どんな問い合わせが増えていますか？」「○○関連が増えてます」といった運営者とCSとのコミュニケーションが発生します。普段からのコミュニケーションが重要なのは言うまでもありません。

Slackにアラートするだけでなく、閾値を超えなかったときのデータも含めてグラフ化し、いつでも傾向が見られるようにしておくとなお良いですね。

## おわりに

CSが何を目標としどんなことをしているか、またCSデータの活用例について書きました。
以前社外のCS関係者とお話しさせていただく機会があり、問い合わせ数アラートをご紹介したところ「うちにも欲しい！」と好評だったのと同時に、アイデアはあるものの形にしてくれるエンジニアがそばにいなくて困っているCS担当者が多いということを知りました。
みなさまが少しでもCSに興味を持ち、お客様の満足度が向上し、結果としてみなさまのサービスに良い循環が生まれれば良いなと星に願いつつ締めくくりとさせていただきます。ありがとうございました。

明日6日は [@Kuniwak](http://qiita.com/Kuniwak) 氏が私と違ってちゃんとしたことを書いてくれそうですよ。
「いいね」ボタンを押さないことにしました

わざわざ記事にするまでもないことなんだけど，前に「[「ストック」ボタンを救済して](http://qiita.com/spiegel-im-spiegel/items/7d906f8cce5973de5292)」を書いた手前もあるし（しかも微妙に参照されているようで）一応の落とし前をつけておこうかな，と。

（予防線を張っておくと，これは私がこうするという表明で，他のユーザのやり方にケチをつけるものではありません）

「[「ストック」ボタンを救済して](http://qiita.com/spiegel-im-spiegel/items/7d906f8cce5973de5292)」のコメントでもちょろんと書いたけど，「<i class="fa fa-folder" aria-hidden="true"></i>ストック」ボタンを押すときって「<i class="fa fa-thumbs-up" aria-hidden="true"></i>いいね」ボタンも押さないといけないような強迫観念に駆られるのが個人的に面白くなかった。また「<i class="fa fa-thumbs-up" aria-hidden="true"></i>いいね」ボタンだけを押すというシチュエーションは現時点までになかったので，これも私の中で違和感になっていた。

で，以下の記事を見かけたのだ。

- [「いいね」が使えないのはどう考えてもQiitaが悪い - Qiita](http://qiita.com/bezeklik/items/e28ab36e1071e761a277)

この中の

> 動機付けという観点が欠落した今回の仕様変更は、さながら理想だけに先走ってインセンティブを考慮せずに制度設計に失敗する日本国政府のようである。

という部分で納得してしまった。少なくとも私には Qiita で「<i class="fa fa-thumbs-up" aria-hidden="true"></i>いいね」ボタンを押すインセンティブは存在しない。もし「いいね」を表明したいのならそれは Qiita ではなく Facebook や（あまり使わないけど）Twitter や（アカウント持ってないけど）はてなブックマークとかですればいいんぢゃん！ ってことである。意味付けのよく分からない Contribution は無視することにした。

もちろん将来はどうなるかは分からない。今回 Qiita が「<i class="fa fa-thumbs-up" aria-hidden="true"></i>いいね」ボタンを設置したことで「共感」を目的とした記事が増える可能性もあるし，そうなれば「<i class="fa fa-thumbs-up" aria-hidden="true"></i>いいね」ボタンを押すインセンティブも出てくるかもしれない。
（もっとも Qiita がそういうサービスになった時に私自身がそこに commit し続けるかどうかは微妙だけど）

そうそう。コメントに対する「<i class="fa fa-thumbs-up" aria-hidden="true"></i>いいね」（かつての Thanks）ボタンの運用はこれまでどおりです。
AWS EC2 RHEL 6 で VPC の DHCP options set による resolv.conf の書き換えを無効化する

/sbin/dhclient-script に対して以下のパッチを当てることで resolv.conf の書き換えを防ぐことができます。

```
@@ -87,10 +87,6 @@
            fi
        done

-       if [ "${is_in}" = "false" ]; then
-          # Add domain name to search list (#637763)
-          sed -i -e "s/${search}/${search} ${domain}/" /etc/resolv.conf
-       fi
     fi
 }

@@ -135,14 +131,14 @@
             echo "nameserver ${nameserver}" >> ${rscf}
         done

-        change_resolv_conf ${rscf}
+        #change_resolv_conf ${rscf}
         rm -f ${rscf}

         if [ -n "${search}" ]; then
             eventually_add_hosts_domain_to_search "${search}"
         fi

-        fix_context /etc/resolv.conf
+        #fix_context /etc/resolv.conf
     elif [ -n "${new_dhcp6_name_servers}" ] ||
          [ -n "${new_dhcp6_domain_search}" ]; then
         rscf="$(mktemp /tmp/XXXXXX)"
@@ -168,14 +164,14 @@
             echo "nameserver ${nameserver}" >> ${rscf}
         done

-        change_resolv_conf ${rscf}
+        #change_resolv_conf ${rscf}
         rm -f ${rscf}

         if [ -n "${search}" ]; then
             eventually_add_hosts_domain_to_search "${search}"
         fi

-        fix_context /etc/resolv.conf
+        #fix_context /etc/resolv.conf
     fi
 }

@@ -465,7 +461,7 @@
         hostname ${new_host_name}
     fi

-    make_resolv_conf
+    #make_resolv_conf

     if [ -n "${DHCP_TIME_OFFSET_SETS_TIMEZONE}" ] &&
        [[ "${DHCP_TIME_OFFSET_SETS_TIMEZONE}" = [yY1]* ]]; then
@@ -545,7 +541,7 @@

             add_ipv6_addr_with_DAD

-            make_resolv_conf
+            #make_resolv_conf
             ;;

         RENEW6|REBIND6)
@@ -554,11 +550,6 @@
                [  ! "${new_ip6_address}" = "${old_ip6_address}" ]; then
                 add_ipv6_addr_with_DAD
             fi
-
-            if [ ! "${new_dhcp6_name_servers}" = "${old_dhcp6_name_servers}" ] ||
-               [ ! "${new_dhcp6_domain_search}" = "${old_dhcp6_domain_search}" ]; then
-                make_resolv_conf
-            fi
             ;;

         DEPREF6)
```
今からでも遅くない！テストコードからKotlinを導入してみる

Kotlin、盛り上がってますよね。新しいプロジェクトを作るなら Kotlin したいんですが、既存プロジェクトでも Kotlin をしたい気持ちもあるでしょう。しかし、大きくなった既存プロジェクトにいきなり Kotlin を導入するのも骨が折れます。そこで今回は、大きなプロジェクトでもちょっとずつ Kotlin が始められるよう、まずはテストコードから Kotlin をしてみる最短ステップをここに残しておこうと思います。

## 現在の構成

弊社の Android アプリのコードは Java でできています。テストコードは Robolectric 3.1.2 で、IDE は AndroidStudio 2.2 です。IntelliJ Plugin の Kotlin Plugin も入っています。

## 構成管理

プロジェクトのルートにある`build.gradle`に、Kotlin のプラグインを追加します。

```groovy:build.gradle
buildscript {
  // ...
  dependencies {
    // ...
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.5-2"
  }
}
```

つぎに、アプリモジュールの`build.gradle`に、Kotlin の依存を宣言します。今回はテストでのみ Kotlin を使うので、以下のように`testCompile`を追加しています。

```groovy:app/build.gradle
apply plugin: 'kotlin-android'

dependencies {
  testCompile "org.jetbrains.kotlin:kotlin-stdlib:1.0.5-2"
  testCompile "org.jetbrains.kotlin:kotlin-test-junit:1.0.5-2"
}
```

## 既存のテストコードの変換

なにか適当に簡単なテストを対象に、Java から Kotlin へ変換してみましょう。
Java のファイルを選択し、Code -> Convert Java File to Kotlin File するだけ。ね、簡単でしょう😃

## テスト実行

AndroidStudio で試す場合は、テストコードを選択してから右クリックメニューの「Run XXXTest」で実行できます。CLI ならテスト用のタスクを実行します。

BUILD SUCCESSFUL と出たら優勝です。

## おわりに

新しい言語の導入というと、その作業だけでも結構大変なんじゃないかと思っていましたが、拍子抜けするほど簡単でした。IDE ではうまく動くけど CLI では動かない、ということもありがちなパターンだとは思いますが、Kotlin の導入に際してはそのようなトラブルもなく、今日も WerckerCI は元気にアプリをビルドしてくれています。
AWS CloudFront 署名付きcookieの作り方

# はじめに
CloudFrontでプライベートなコンテンツを配布する必要があり、署名付きcookieを使うことになりました。公式のドキュメントに説明はありますが、ドキュメントが分散していたり、わかりづらかったので手順をまとめてみました。

# 手順
## 1. CloudFront用のキーペアを作成する
コンソールから作成する方法と、ローカルでキーペアを作成してからAWSにアップロードする方法とがある。
コンソールから作成する方法は、このページ（http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html )の「AWS マネジメントコンソールで CloudFront キーペアを作成するには」を参照。
プライベートキーをダウンロードして、「private_pk.pem」のファイル名で保存する。また、アクセスキーをメモしておく。

ルートアカウントでログインしないと、CloudFront用のキーペアは作成できないので注意。IAMユーザーでキーペアを作成しようとすると、権限がないとのエラーになる。

## 2. ポリシーステートメントを用意する

ポリシーステートメントの例: 

```json
{"Statement":[{"Resource":"http*://test.example.com/*","Condition":{"DateLessThan":{"AWS:EpochTime":1501372800}}}]}
```
JSON形式でドメインや有効期限などを設定する。他にも、DateGreaterThanやIpAddress(特定のIPからのみアクセスを許可)といったオプショナルパラメータを指定できる。「policy.json」のファイル名で保存する。

パラメータの説明はこちらを参照: http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-setting-signed-cookie-custom-policy.html#private-content-custom-policy-statement-cookies-values

## 3. 1.で作ったポリシーステートメントをbase64エンコードする

```bash
cat ./policy.json | openssl base64 | tr '+=/' '-_~'
```

「./policy.json」は2.で作ったポリシーステートメントのパス。trは、URLクエリ内の無効な文字を置き換えるため。上のコマンドで出力された文字列をメモしておく。
コマンドの説明はこちらを参照: http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-linux-openssl.html

## 4. 1で作ったポリシーステートメントを署名し、base64エンコードする

```
cat ./policy.json | openssl sha1 -sign ./private_pk.pem | openssl base64 | tr '+=/' '-_~'
```
「./private_pk.pem」は、1.でダウンロードしたプライベートキーのパス。上のコマンドで出力された文字列をメモしておく。

## 5. cookieをセットする
CloudFront-Key-Pair-Id={1.でメモしたアクセスキー}
CloudFront-Policy={3.で作ったbase64エンコードされたポリシーステートメント}
CloudFront-Signature={4.で作った署名済みのポリシーステートメント}
で、プライベートコンテンツをダウンロードするブラウザにcookieをセットする。

コード例: 

```js
// cfKeyPairId/cfPolicy/cfSignatureに、上記の値が入っている
document.cookie = "CloudFront-Key-Pair-Id=" + cfKeyPairId + "; "
document.cookie = "CloudFront-Policy=" + cfPolicy + "; "
document.cookie = "CloudFront-Signature=" + cfSignature + "; "
```

## 6. 動作チェック
正しく設定できていれば、5.でcookieをセットしたブラウザからだけ、ポリシーステートメントで指定したURLにアクセスできる。
LaTeX 書式・便利集

## クリックで指定ディレクトリを開く

```latex
\usepackage{url}
\url{file://c:/}
```

## ファイルパス記述

```latex
\usepackage[obeyspaces]{url}
\path{C:\Program Files}
```
- `obeyspaces`オプション：スペース文字削除を停止
- **参考**：[TeX でファイルパスを記述する方法: tmishina's diary](http://tmishina.cocolog-nifty.com/blog/2007/03/tex-9d96.html "TeX でファイルパスを記述する方法: tmishina's diary")

## pdf の挿入
- [LaTeX で PDF の一部だけ表示したい(1) - Acetaminophen’s diary](http://acetaminophen.hatenablog.com/entry/2015/07/18/233500)
- [にっき♪: pdfpages](https://abenori.blogspot.jp/2015/07/pdfpages.html)

## `itemize` 環境に図表挿入
- 箇条書きの点が図表の一番上にくる

```latex
\item \raisebox{-\height}{図表コード}
```

## `hyperref` 系
- [hyperref.sty: LaTeX パッケージ](http://www.biwako.shiga-u.ac.jp/sensei/kumazawa/tex/hyperref.html "hyperref.sty: LaTeX パッケージ")

```latex
\href{url}{text}
```

## 余白調整
```latex
\usepackage[top=10truemm,bottom=10truemm,left=10truemm,right=10truemm]{geometry}
```
- `10truemm` で結構ギリギリまで使用可能

## `subsubsection` 環境まで目次番号生成
```latex
\setcounter{tocdepth}{3}
```

## 特殊文字の扱い
```latex
usepackage{pifont}
¥ding{192} % ➀を出力
```

- **参考**
    - [LaTeXで丸1などを出力する - Qiita](http://qiita.com/ryokbys/items/ce8fed47627e9bc9346a "LaTeXで丸1などを出力する - Qiita")
    - [pifont.sty: LaTeX パッケージ](http://www.biwako.shiga-u.ac.jp/sensei/kumazawa/tex/zapfdingbats.html "pifont.sty: LaTeX パッケージ")
 
## 挿入した文字付きイメージを pdf の検索機能でヒットさせる
- powerpoint で作成し、pdf で保存

## ブラウザで楽して表生成
-  [Create LaTeX tables online](http://www.tablesgenerator.com/ "Create LaTeX tables online")

## エラー wiki
- [TeX のエラーメッセージ - TeX Wiki](https://texwiki.texjp.org/?TeX%20%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8#navigator "TeX のエラーメッセージ - TeX Wiki")
SQLチューニング: ソートを発生させないインデックス設計

SQLのクエリを実行するとき、ボトルネックになりがちな演算の1つにソートがあります。
全レコードを並び替えるため、レコード数が多ければ多いほどそのコストも増大していきます。

ソートが発生するケースはいろいろありますが、代表的なのは「Order BY」句で明示的にデータの並び替えを指定する場合ですね。

```sql
	-- int型のカラムが5つのテーブル 100万レコードINSERT済
	-- SQLServerで実行

	SELECT
		 column4
		,column5
	FROM SomeTable
	WHERE column2 = 2
	ORDER BY column3 -- 並び替え
```

実行プラン
![図1.png](https://qiita-image-store.s3.amazonaws.com/0/148310/6f425667-b813-f4d2-6923-ecdf33bc64af.png)


100万レコード中、40万レコードくらいを返すSQLです。レコードをあまり絞り込めないWhere句のため、Sortに大きなコストがかかっています。

そこでインデックスを追加します。

```
CREATE NONCLUSTERED INDEX [IX1] ON [dbo].[SomeTable]
(
	[column2] ASC
	,[column3] ASC
)
INCLUDE ([column4], [column5])
GO
```

実行プラン
![図2.png](https://qiita-image-store.s3.amazonaws.com/0/148310/f7f81e4c-3562-e9b5-1586-db9048a6bdde.png)


実行プランがIndexSeekに変化しました。高速に処理できています。

ポイントは以下の3点です。
1. OrderByで使うカラムを、OrderByで指定するときと同じ並び順でインデックスに格納
2. 付加列ではない、インデックスに存在するカラムが全てWHERE句で指定されている（今回の例でいうと、column2でインデックス並び替えてるのに、Where句で指定しなかったら結局column3でのソートが発生しちゃうので）
3. クエリ内のカラムは全てインデックス内に存在する（＝ルックアップが不要）

今回はわざとソートにコストがかかるようなクエリを発行していますが、実際はOrderByをつけていてもWhere句で絞込んだ結果10レコードとかになるのであれば、ソートのコストは無視できます。

最終的には発行するクエリの性質から最適なインデックスを導く必要がありますが、OrderByなどによってソートが発生するようなクエリでは今回の設計方針が役にたつケースがあると思います。
Emacsで日本語フォントを個別設定


![Screenshot_2016-12-05_10-40-27.png](https://qiita-image-store.s3.amazonaws.com/0/103885/670778a9-4b0a-ec52-26fd-fdbbfed8c5b9.png)

今の所の最適解。
日本語とそれ以外でフォントを分ける設定。

```lisp:init.el
;; Basic font
(custom-set-faces
 '(default ((t (
                :foundry "Source Code Pro" :family "Source Code Pro")))))

;; Japanese font
(set-fontset-font t 'japanese-jisx0208 (font-spec :family "IPAExGothic"))
```

もともと日本語も良い感じに表示されていたのに、
OS再インストールしたら日本語が明朝体で表示されるように変わってしまった。

そのため上記設定を適用したら、いい感じになった。
「null安全」という訳語の背景

「null安全」という訳語が色々と議論を呼んでいるようです。本質的でない話に多くの開発者のリソースが割かれるのは本意ではないので、僕が「null安全」という訳語を使った背景を説明します。

もし **コンパイル時（または静的解析時）にチェックすることで `null` による実行時エラーを起こさない** という概念を表す用語として、「null安全」より適切なものがあれば教えていただけるとうれしいです（新しく用語の提案ではなく、すでに用いられている用語で）。

## null safety を「null安全」と訳した理由

[元投稿](http://qiita.com/koher/items/e4835bd429b88809ab33)にも書きましたが、「null安全」は **_null safety_** の訳で、 [Kotlin で使われています](https://kotlinlang.org/docs/reference/null-safety.html)。これが Kotlin のオリジナルかはわからないですが、僕の知る限りでは Kotlin 以外では _null safety_ という用語は使われていないように思います。

当初は「null安全」ではなく「nullセーフ」と書こうと考えていました。単純に、僕の周りでは「nullセーフ」と呼ばれていたからです。しかし、調べてみても Kotlin のページで null-safe という用語は使われていないですし、 null-safe でググってもヒットするのは null-safe operator とかばかりで、 **コンパイル時（または静的解析時）にチェックすることで `null` による実行時エラーを起こさない** という性質を表す形容詞として null-safe と呼ばれているケースは多くなさそうでした。そのため、「nullセーフ」という訳語を使うべきか再検討することにしました。

しかし、 _null safety_ を「nullセーフティ」や「null安全性」と訳してしまうと「nullセーフティな言語」や「null安全性な言語」とは言えないので使い勝手が悪いです。[ググってみると](https://www.google.co.jp/search?q=null%E5%AE%89%E5%85%A8&tbs=cdr:1%2Ccd_max:2016%2F11%2F05)「null安全」という訳が見つかりました。 **「null安全」であればあくまで null safety の訳としたままで、日本語における形容詞的な派生として「null安全な言語」という使い方をしても自然です。** それが、僕が _null safety_ でも「nullセーフティ」でも「null安全性」でも「nullセーフ」でもなく、「null安全」という訳語を使った理由です。

それが気に入らなければ null-safe や「nullセーフ」など、好きに呼べばいんんじゃないかと思います。僕自身も無理な日本語訳は好きじゃないです。 _共変_ や _反変_ より _covariant_, _contravariant_ の方が好きです。 null-safe が一般的な用語なら null-safe と呼びたいところです。

## null safety という用語の是非

_null safety_ を「null安全」と訳すのが適切かというのとは別に、 **コンパイル時（または静的解析時）にチェックすることで `null` による実行時エラーを起こさない** という概念を _null safety_ と呼ぶのが適切かということも議論になっているようです。

次の理由から、僕の知る限り _null safety_ はこの概念を表すのに最も適した用語です。

### 他に適した用語が見つからない

_option type_, _maybe type_, _optional type_ などの用語はありますが、これらは `null` に相当する値を保持できる型を表す語であり、その結果として _null safety_ が実現できるだけです。 _null safety_ の概念自体を表すわけではなりません。

僕の探した限り、 _null safety_ 以外にその概念を表す適当な用語が見つかりませんでした。他により良い用語があれば僕も知りたいので教えてほしいです。

### 単語の選び方が自然である

「ぬるぽだって問題があったら停止するので安全じゃないか。安全=safetyの意味がわかりづらい。」という意見もあるようです。しかし、 C 言語等の `NULL` のデリファレンスが未定義な言語と比べれば「安全」かもしれませんが、静的な型検査で見つけられるエラーを実行時にまで持ち越して、潜在バグを生み出しかねないものを「安全」と呼ぶのは無理があるように思います。

僕は、 null safety という用語は type safety からのアナロジーで考えると自然だと思います。
Drupal7で管理者のパスワードを忘れた時にすること

Drupal7で開発中、万が一管理者（サイト構築時に作成したアカウント）のパスワードを忘れてしまった時の方法を記述します。

## Drupalのusersテーブルについて
Drupal7のユーザーテーブルは以下のようになっている

``mysql> desc users;``

| Field|Type|Null|Key|Default|Extra|
|---|---|---|---|---|---|---|
| uid              | int(10) unsigned | NO   | PRI | 0       |       |
| name             | varchar(60)      | NO   | UNI |         |       |
| pass             | varchar(128)     | NO   |     |         |       |
| mail             | varchar(254)     | YES  | MUL |         |       |
| theme            | varchar(255)     | NO   |     |         |       |
| signature        | varchar(255)     | NO   |     |         |       |
| signature_format | varchar(255)     | YES  |     | NULL    |       |
| created          | int(11)          | NO   | MUL | 0       |       |
| access           | int(11)          | NO   | MUL | 0       |       |
| login            | int(11)          | NO   |     | 0       |       |
| status           | tinyint(4)       | NO   |     | 0       |       |
| timezone         | varchar(32)      | YES  |     | NULL    |       |
| language         | varchar(12)      | NO   |     |         |       |
| picture          | int(11)          | NO   | MUL | 0       |       |
| init             | varchar(254)     | YES  |     |         |       |
| data             | longblob         | YES  |     | NULL    |       |


パスワードを忘れてしまって変更をしたい場合は、usersテーブルのpassフィールドの値を変更すればパスワードを変更をすることができる。
ちなみに管理者（サイト構築時に作成したアカウント）のuidは１である。

## パスワード変更のための文字列を用意する
passフィールドに入る値はハッシュ化された値が入るためパスワードにしたい文字列のハッシュを用意します.Drupal７にはハッシュを作るスクリプトが以下にあるでこれを使う。

``./scripts/password-hash.sh abcdefg``

``password: abcdefg 		hash: $S$DOy6K2AlgtD8pzi0Bdc8pHej5F12fHMmsLJG5mim9aYdq4FLEqfo``


## パスワードを変更する
tableに先ほど作成した。hashの値を挿入する

``UPDATE users SET pass ='$S$DOy6K2AlgtD8pzi0Bdc8pHej5F12fHMmsLJG5mim9aYdq4FLEqfo' WHERE uid = 1;``

drushが入っていれば以下のようにコマンドを叩くことによって変更することもできるらしい。（こちらは試していません。）
``drush upwd --password="abcdefg" "管理者（サイト構築時に作成したアカウント）"``

## 補足：パスワードロックがかかってしまった場合
drupalでは標準で連続５回同じユーザーのパスワードを間違えるとそのユーザーで一定期間ログインできなくなっている。

これを解消にするにはfooldテーブルの任意の値を消去すれば可能
``desc flood;``

| Field|Type|Null|Key|Default|Extra|
|---|---|---|---|---|---|---|
| fid        | int(11)      | NO   | PRI | NULL    | auto_increment |
| event      | varchar(64)  | NO   | MUL |         |                |
| identifier | varchar(128) | NO   |     |         |                |
| timestamp  | int(11)      | NO   |     | 0       |                |
| expiration | int(11)      | NO   | MUL | 0       |                |

ログイン失敗時にはeventフィールドの値failed_login_attempt_ipとfailed_login_attempt_userがセットで作成されるためこの自分のアクセスに対応するこのセットを消去することによって一定期間待つ必要は無くなります。

## 参考にしたページ
https://www.drupal.org/node/1023428
https://www.drupal.org/node/44164
stylusでいい感じに連番をふる

小ネタです。

stylusで、イテレーション使って
.number-1
.number-2
...
みたいなクラスに対して、contentに数字を入れるようなルールを定義したいとき。すごく普通にやりますと、

```ng.styl:stylus
for i in (1..5)
  .number-{i}
    &::before
      content i
```

```ng.css:css
.number-1::before {
  content: 1;
}
.number-2::before {
  content: 2;
}
.number-3::before {
  content: 3;
}
.number-4::before {
  content: 4;
}
.number-5::before {
  content: 5;
}
```

こうなります。駄目です。

stackoverflowで見かけたやつですと、

```ng2.styl:stylus
for i in (1..5)
  .number-{i}
    &::before
      content \'i\'
```

```ng2.css:css
.number-1::before {
  content: ' 1 ';
}
.number-2::before {
  content: ' 2 ';
}
.number-3::before {
  content: ' 3 ';
}
.number-4::before {
  content: ' 4 ';
}
.number-5::before {
  content: ' 5 ';
}
```

何だこのスペース。
気にしなきゃいいのかもしれないけれど、たまにレイアウトに干渉するのが難点。

いろいろ内部関数なども調べてみたけれど、まったく関係なく

```good.styl:stylus
for i in (1..5)
  .number-{i}
    &::before
      content "" + i
```

```good.css:css
.number-1::before {
  content: '1';
}
.number-2::before {
  content: '2';
}
.number-3::before {
  content: '3';
}
.number-4::before {
  content: '4';
}
.number-5::before {
  content: '5';
}
```

なんというかトンチみたいな解決法でした。考えすぎでした。
PHP5系のプロジェクトにPhanでの静的解析を導入してみた

# やりたいこと

PHP7へのバージョンアップに向けて問題箇所の洗い出しを行いたい。
PHPConferenceで紹介されていたPhanを試してみたい。
紹介の詳しい内容は http://inside.pixiv.net/entry/2016/11/11/202656
導入についても参考にさせていただきました！

# 環境

CentOS6.7
PHP5.6.6

# 問題点

PhanはPHP7系が必要

# やったこと

## PHP7を既存のPHP5.6と別に入れる

epel,remiリポジトリを追加してphp7.0とphanで必要となるphp-ast,php-sqlite3を入れます。

```
$ sudo yum -y install epel-release
$ sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
$ sudo yum install php70 php70-php-ast php70-php-sqlite3 --enablerepo=epel,remi
```

別で入れたphp7.0は下記のように実行できます。

```
$ php70 --version
PHP 7.0.13 (cli) (built: Nov  8 2016 21:32:10) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
```

## Phanを入れる

今回はphar形式で導入してみます。

```
$ curl -L https://github.com/etsy/phan/releases/download/0.6/phan.phar -o phan.phar;
$ php70 phan.phar
```

エラーが出なければインストールはOKです。

## Phanを動かしてみる

設定ファイルを記述する必要があります。

.phan/config.php を作成します。
https://github.com/etsy/phan/wiki/Getting-Started#creating-a-config-file
公式のものを参考に。

解析対象のディレクトリはdirectory_list, 対象から外してほしいディレクトリは　exclude_analysis_directory_listにそれぞれ追加します。

```
$ php70 ~/phan.phar
```

これで静的解析を実行できます。
また、実行時に -o[ファイル名] を指定するとアウトプットを指定ファイルに出力してくれます。
Memo: AWS re:Invent 2016: Tuesday Night Live with James Hamilton

AWS re:Invent 2016: Tuesday Night Live with James Hamilton
https://www.youtube.com/watch?v=AyOAjFNPAbA

意外と詳細は話してなかった。

# Pros of building Network Switch / Router.

* Cost
* Simple and reliable
    * Pager of ours rings. Thus has the motivation to keep it simple.
    * Single source of requirement. (AWS)
* Speed to debug / fix issues
    * No need to duplicate in other sites. No one has the same scale of an environment to test.

# Notes:

* 25G = 1 wave, 40G = 4 waves (4x10Gbps).
* Tomahawk .. did not hear it's custom ASIC
* Custom silicon = small silicon with 2x25GbE offloading server load.
* Offloading to hardware will provide 1/10 latency, 1/10 power, 1/10 cost.
* Reducing latency is difficult. Hardware = us/ns -> Software = ms.
* Storage
    * 2014 : 880 disks/rack
    * now: 1110 disks/rack. 8.8~11PB in a rack. 2778 lbs of storage.
AWS S3においたjson形式のログファイルをAthenaからSQLクエリでみてみた

# 概要
先日発表されたAmazon Athenaを導入するか検討したいのでまずは軽く触ってみた。
[Amazon Web Services ブログ参考](https://aws.amazon.com/jp/blogs/news/amazon-athena-interactive-sql-queries-for-data-in-amazon-s3/)

# 手順

## json形式のログファイルをs3上に置く
![スクリーンショット 2016-12-05 午前9.12.08.png](https://qiita-image-store.s3.amazonaws.com/0/34039/05a5f397-d861-4a06-8efd-76d626113496.png)


## AthenaでS3上のパスとテーブル定義を行う
データベース、テーブル名、S3上ログを置いているパスを記載する
![スクリーンショット 2016-12-05 午前9.16.30.png](https://qiita-image-store.s3.amazonaws.com/0/34039/8ab1af3f-d2b7-e496-a7d4-6e6e26aa1659.png)

ログファイルの形式を指定する
![スクリーンショット 2016-12-05 午前9.14.23.png](https://qiita-image-store.s3.amazonaws.com/0/34039/41fbdaeb-edae-edb9-b1aa-3b8988ecc676.png)

カラムを定義する
![スクリーンショット 2016-12-05 午前9.15.27.png](https://qiita-image-store.s3.amazonaws.com/0/34039/146850c7-3ddd-9f88-1806-e79bc2ee66ac.png)

パーティションを追加は、しないで`create table`する
![スクリーンショット 2016-12-05 午前9.15.50.png](https://qiita-image-store.s3.amazonaws.com/0/34039/7c5cf702-557b-2184-b706-8567cce1ed63.png)

Query Editorからログをみてみる
![スクリーンショット 2016-12-05 午前9.16.46.edited.png](https://qiita-image-store.s3.amazonaws.com/0/34039/ab563887-9c50-2be6-bc41-c8dbdaa9eeb2.png)
AWSのPHP7.0環境でpearを使ってMailとMail_Mimeをインストール

PHP7系を使っている場合はPHP7対応のpearを使いましょう。

以下のコマンドでインストールできます。

    sudo yum install php7-pear

MailとMail_Mimeのインストールはそれぞれ以下の通り。コマンド名がpear7なので注意。

    sudo pear7 install -a Mail
    sudo pear7 install -a Mail_MIME
KUSANAGIマスコットキャラクター「さや」

#四コマ

![IMG_4277.jpg](https://qiita-image-store.s3.amazonaws.com/0/152252/a8ae9773-34a4-9acf-388b-f07a4c8a030a.jpeg)

(入社当日に…)
「KUSANAGIをテーマにしたアドベントカレンダー書きませんか？」
「はい、書きます。」

とは言ってもKUSANAGIのシステム的なところについては先輩方の方が圧倒的に「詳しく」、「わかりやすく」、書いていただけると思うので、マスコットキャラクターをイメージして四コマ描かせていただきました。

面接の日、案内されたオフィスで一番最初に目についたのがこのKUSANAGIのキャラクターでした。クールで凛としてスタイリッシュなイメージがありながらも、クールな自分を出そうとするあまり空回ってしまう部分があるんじゃないか！と勝手に設定を想像していました。

ただ、見ての通り、ペン入れと下塗りさえも間に合いませんでした。今日の朝描いてきました。

#マスコットキャラクター「KUSANAGI」の設定

![saya-987x10241-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/152252/621d26d1-a83a-58df-7d6c-7a967668f647.jpeg)

>名前
>>草薙 沙耶
(Kusanagi Saya)

>プロフィール
>>近未来の地球、仮想世界で戦う女性サイボーグ戦士。
草薙家に代々伝わる家宝の剣「KUSANAGI」と共に戦う。
KUSANAGI 装備時に加速して戦闘する。
口癖は「遅いわね。止まって見えるわ..」

こってるなぁ。
やっぱりキャラクターは設定が濃いほうがいいですよね。

また機会があれば漫画・記事書かせてください。
ここまで読んでくれてありがとうございます。

(文責：阿部)
pip listでwarningメッセージが表示されたときの対処

# 概要

* pipを9.0.1にアップデートしたところ `pip list` でwarningメッセージが表示されるようになって邪魔なので黙らせる。

# 経緯
* 「pipコマンドをアップグレードしない？」と言われたので

```bash
$ pip list
pip (8.1.1)
setuptools (20.3)
You are using pip version 8.1.1, however version 9.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
```

* 勧められるままアップグレードしたところ

```bash
$ pip install --upgrade pip
Collecting pip
  Downloading pip-9.0.1-py2.py3-none-any.whl (1.3MB)
Installing collected packages: pip
  Found existing installation: pip 8.1.1
    Uninstalling pip-8.1.1:
      Successfully uninstalled pip-8.1.1
Successfully installed pip-9.0.1
```

* なんかwarningが表示されるようになった（悲）

```bash
$ pip list
DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning.
pip (9.0.1)
setuptools (20.3)
```

# 対処方針
* メッセージ通り、pip.confに記述します。
* ただ、自分の環境にはpip.confがなかったので少し迷いました。
* 自分の環境とは、virtualenvでPythonを切り替えるものです。（→ [Amazon Linux上にPython3.5.2の環境を導入する](http://qiita.com/shinsaka/items/d9df609b81ab1170487e) ）

# 対処手順

* Pythonのトップディレクトリに `pip.conf` を設置すると読み込んでくれるようです。
* `~/py352` へPythonをインストールしてある場合は、そのディレクトリ直下です。
* `format`へ`columns`または`legacy`を指定します

```:~/py352/pip.conf
[list]
format=columns
```

# 確認

* warningメッセージ無しで表示されるようになりました。

```bash
$ pip list
Package    Version
---------- -------
pip        9.0.1
setuptools 20.3
```
yarn upgrade-interactive が超便利


rails 5.1で取り込まれそうになっていたりまた熱い動きがありそうなyarnさん。
いつの間にか入っていた`upgrade-interactive`コマンドが非常に便利だった。

https://github.com/yarnpkg/yarn/pull/1444

今日現在（2016/12/05）、公式ドキュメントにまだ載ってないが、便利すぎるのでみんな使ったほうが良いと思う

### 準備

yarnを最新にしておく。
v0.17.0 以上であれば利用できる。

```
$ yarn self-update
```

### 何が出来るか？

npm outdatedの超すごい奴という認識で良い気がする。
upgradeをinteractiveに出来る。（名前のまま）

```
$ yarn upgrade-interactive
```

これを叩くとこんな画面が出て来る

![9__yarn_upgrade-interactive__node_.png](https://qiita-image-store.s3.amazonaws.com/0/7307/ef478d4d-1e8f-b96b-e308-ec1e8c222c0a.png "9__yarn_upgrade-interactive__node_.png")

アップグレードが出来るパッケージが表示される。
カーソルを動かしてアップグレードしたいパッケージを選び、<kbd>Space</kbd>キーで選択する。<kbd>a</kbd>キー（all)を押すと、全選択、<kbd>i</kbd>キーを押すとフラグが反転する。

選んだら<kbd>Enter</kbd>キーで実行

![7__inuscript_MacBook-Air____office_some_project__zsh_.png](https://qiita-image-store.s3.amazonaws.com/0/7307/dbefa563-551b-dda1-758c-f6e1867a6323.png "7__inuscript_MacBook-Air____office_some_project__zsh_.png")

これだけでアップグレード完了！

マジで便利すぎる。yarn依存症になってしまいそう。
イケてる形態素解析エンジン「juman++」をrubyから実行できるようにする！

[Atraeアドベントカレンダー](http://qiita.com/advent-calendar/2016/atrae)の四日目です。

# はじめに

形態素解析エンジンにjuman++というのがあります
結構いい感じに使えそうなので、これをrubyから触れるようになることが今回の目的です。

そこでググル先生にお尋ねしたところ、コマンドラインを触るためのライブラリとして、
「open3」というのがあることがわかったので今回はそれを使って見ようと思います。


# 環境
- Mac OSX ver. 10.11.6


# やること
- juman++をインストールする
- open3の使い方を理解する
- open3からjuman++をたたくためのラッパーを作成する


# 1. juman++のインストール

```
brew install jumanpp
```

# 1-2. juman++の使い方

```
$ jumanpp ハロー、ワールド
=> ハロー はろー ハロー 感動詞 12 * 0 * 0 * 0 "代表表記:ハロー/はろー" 、 、 、 特殊 1 読点 2 * 0 * 0 NIL
ワールド わーるど ワールド 名詞 6 普通名詞 1 * 0 * 0 "代表表記:ワールド/わーるど カテゴリ:場所-その他"
EOS
```

# open3の使い方を理解する

open3とは

>プログラムを実行し、そのプロセスの標準入力、標準出力、標準エラー出力にパイプを繋ぎます

らしいです。


とりあえず叩いてみましょう。

```
pry(main)> require 'open3'
pry(main)> Open3.popen3('jumanpp')
=> [#<IO:fd 13>, #<IO:fd 14>, #<IO:fd 16>, #<Thread:0x007fa025099ee0 sleep>]
```

のように配列が返ってきます。
順に`stdin`, `stdout`, `stderr`, `wait_thr`のようです。

juman++を使う場合、`stdin`にテキストを渡して、`stdout`から解析結果を取得できればよさそうですね。

- `stdin`引数を渡すためには、`puts`
- `stdout`から結果を取得するには、`read`



をそれぞれ使えば、望む結果が得られそうです。

早速試してみましょう。

```
pry(main)> stdin, stdout, stderr, wait_the = Open3.popen3('jumanpp')
=> [#<IO:fd 13>, #<IO:fd 15>, #<IO:fd 18>, #<Thread:0x007fb50f671af8 sleep>]

pry(main)>stdin.puts 'ハロー、ワールド'
=> nil

[23] pry(main)> stdout.read
=> "ハロー はろー ハロー 感動詞 12 * 0 * 0 * 0 \"代表表記:ハロー/はろー\"\n、 、 、 特殊 1 読点 2 * 0 * 0 NIL\nワールド わーるど ワールド 名詞 6 普通名詞 1 * 0 * 0 \"代表表記:ワールド/わーるど カテゴリ:場所-その他\"\nEOS\n"
```

結構簡単に求める結果を得ることができました(∩´∀｀)∩ﾜｰｲ


# ラッパーを作ろう

これを簡単に使えるように、module化しておきましょう。
ソースコードは以下のとおりです。

```ruby
require 'open3'

module Jumanpp
  class Parser
    def initialize
      @stdin, @stdout, @stderr, @thread = Open3.popen3('jumanpp')
    end

    def parse(text)
      print(text)
      @stdin.close # stdinを閉じる
      stdout_to_array
    end


    def print(text)
      @stdin.puts text
    end

    def stdout_to_array
      # EOSやNILなどを削除したり
      @stdout.read.gsub(/\nEOS\n/, '').split(/NIL/)
    end

    # threadをkillするために一応つけとく
    def kill
      @stdin.close unless @stdin.closed?
      @thread.kill
    end
  end
end
```

使い方はこんな感じ

```
pry(main)> jumanpp=Jumanpp::Parser.new
pry(main)> jumanpp.parse 'ハロー、ワールド'
=> ["ハロー はろー ハロー 感動詞 12 * 0 * 0 * 0 \"代表表記:ハロー/はろー\"\n、 、 、 特殊 1 読点 2 * 0 * 0 ",
 "\nワールド わーるど ワールド 名詞 6 普通名詞 1 * 0 * 0 \"代表表記:ワールド/わーるど カテゴリ:場所-その他\""]
```


# おわり

というわけでjuman++をrubyから使うことができるようになりました。
ほとんどopen3の話でしたがｗ

juman++は口語に強い形態素解析エンジン（という認識）なのでSNSの投稿やチャットなどを解析させると色々捗るかもしれません！！

macさえアレばお手軽に試せるのでみなさんも是非お試してください！！