OmniAICreator/Qiita-1.07M huggingface dataset:
HSP3.5 HGIMG4 でヘルプに書かれてないイベント動作紹介

小ネタですが、HSP3.5 のヘルプには登場しないイベント動作がいくつかあります。

# event_setwork2 が存在する

event_setwork2 によって work2 値が変更できます。
work と同じく event_work2, event_addwork2 も存在し、work と同様の仕様です。

# event_prmadd が存在する

event_prmadd が存在します。
追加引数で最小と最大で範囲を制限することができます。

# event_uv が存在する

event_uv が存在します。
現状では PRMSET_SPRCELID にセットするのと同様の効果があるようですが、HGIMG3 にはすでに event_uv があり意図は同じですが、UVの指定方法が異なっています。

# まとめてサンプル

サンプルコードは以下のようになります。

```hs
#include "hgimg4.as"

#const WID_DOT 2

	sx = ginfo(26)
	sy = ginfo(27)

	gpreset
	setcls CLSMODE_SOLID, 0x000033

	celload dirinfo(5) + "\\tamadot.png", WID_DOT
	celdiv WID_DOT, 64,64, 32,32

	dim evs,3

	newevent ev
	event_setwork2 ev, 1,2,3
	evs.0 = ev

	newevent ev
	event_uv ev, 28
	event_wait ev, 10
	event_uv ev, 29
	event_wait ev, 10
	event_uv ev, 30
	event_wait ev, 10
	event_uv ev, 31
	event_wait ev, 10
	event_jump ev, 0
	evs.1 = ev

	newevent ev
	event_wait ev, 120
	event_prmadd ev, PRMSET_SPRCELID, 1, 44,44+3
	event_jump ev, 0
	evs.2 = ev

	dim ids,3
// 左
	gpspr id, WID_DOT, 39, 2
	setscale id, 2,2,2
	setpos id, sx/2 - 128, sy/2
	setevent id, evs.0
	ids.0 = id
// 中
	gpspr id, WID_DOT, 24, 2
	setscale id, 2,2,2
	setpos id, sx/2, sy/2
	setevent id, evs.1
	ids.1 = id
// 右
	gpspr id, WID_DOT, 44, 2
	setscale id, 2,2,2
	setpos id, sx/2 + 128, sy/2
	setevent id, evs.2
	ids.2 = id

	ddim v,3

	repeat
		getreq fps, SYSREQ_FPS
		redraw 0
		gpdraw

		font "",48
		pos 16,16
		color 224,224,224
		mes strf("%2d [fps]", fps)

		getwork2 ids.0, v.0, v.1, v.2
		fv2str v
		mes "work2: " + refstr
		
		redraw 1
		await 1000/60
	loop
```

|実行結果1|
|:-:|
|![z08ex1.png](https://qiita-image-store.s3.amazonaws.com/0/213145/0507d151-be28-6b4d-0cfc-afd809e0732b.png)|
|work2 がセットできる|

|実行結果2|
|:-:|
|![z08ex2.png](https://qiita-image-store.s3.amazonaws.com/0/213145/baea01b9-8f03-a45a-0ebb-7832908fc68c.png)|
|右端のアニメーションは上限IDに対応する盾で止まる|

以上、小ネタでした。

# 参考

HSP3.5 hgimg4 を基礎から理解したい方は以下の記事がとてもおすすめです。

* [Hot Soup Processor Advent Calendar 2017 の17日目: HSP3.5 で hgimg4 （再）入門](https://qiita.com/exrd/items/3fa31353df396ef53312)
ZYBOでxillinux-2.0を動かすまで＃１（Ubuntu16.04使用）

zyboを購入したタイミングでxillinuxも２．０があったのでやってみることにしました。

**動作環境**
HP ProBook 6560b - 15.6" - Core i5 2410M SSD 256GB 4GB
Ubuntu 16.04LTS
Vivado 2017.3.1
基本的にこのgeting_started_zynqを使用する。
http://xillybus.com/downloads/doc/xillybus_getting_started_zynq.pdf

**ファイルの準備**
まず、ダウンロードしてくるものは２つ。
１）xillinux-2.0ｃのBoot Partition Kit
http://xillybus.com/downloads/xillinux-eval-zybo-2.0c.zip
２）SDカードのイメージファイル
http://cloud.xillybus.com/xillinux-2.0-beta.img.gz
１）を落としたら早速解凍
解凍先に下記のフォルダが出来ます。

```
xillinux-eval-zybo-2.0c/verilog
xillinux-eval-zybo-2.0c/vhdl
xillinux-eval-zybo-2.0c/vivado-essentials
xillinux-eval-zybo-2.0c/blockdesign
xillinux-eval-zybo-2.0c/bootfiles
xillinux-eval-zybo-2.0c/cores
xillinux-eval-zybo-2.0c/runonce
xillinux-eval-zybo-2.0c/system
```

**ｖｈｄファイル編集**

ガイドのP.13に記載があるが、これを読み飛ばしてvivadoのGenerate bitstreamを実行してエラーになった。

```
”For Vivado projects, this file is vivado-essentials/xillydemo.xdc, and for ISE projects
it’s the UCF file in the chosen ’src’ directory under verilog/ or vhdl/.”
```

vivadoでbitstreamを生成する場合は制約ファイルを配置して、vhdlを書き換えるとのこと。
verilogディレクトリかvhdlディレクトリのどちらかでいいらしいのでvhdlで進める。
制約ファイル：vivado-essentials/xillydemo.xdc をvhdl/src配下に置く。
あとはガイドに沿ってvhdl/src/xillydemo.vhd のXillydemoブロックにある下記3行をコメントアウト

``` xillidemo.vhd
（--を頭に着ける）
PS_CLK : IN std_logic;
PS_PORB : IN std_logic;
PS_SRSTB : IN std_logic;
で、次の下記3行のコメントを外す。
-- signal PS_CLK : std_logic;
-- signal PS_PORB : std_logic;
-- signal PS_SRSTB : std_logic;
```

**プロジェクト生成**
ｖｈｄファイルの編集が終わったらVivadoを起動し、メニューから Tools＞Run Tcl Script を選択しvhdl配下のxillydemo-vivado.tcl を実行する。
これで、Projectファイルが作成される。
少々時間がかかるが Tcl Consoleに下記のメッセージが表示されたかを確認。

```
INFO: Project created: xillydemo
```

終わったらVivadoの左ペインからGenerate bitstreamを押してbitstreamを作成。
ワーニングはいくつか出るがエラーがなければOKらしい。
bitstreamが完了すると次のステップを求められるが、bitstreamだけあればいいのでここではCancelを選択。
出来上がると下記に配置される。

```
vhdl/vivado/xillydemo.runs/impl_1/
```

これをSDイメージと一緒にSDカードへ落としてやればよいみたいだがここでお時間です。
つづく。
自然言語処理における評価法のまとめ

## はじめに
自然言語処理においては、「翻訳」「要約」「対話」「質問応答」など様々な難しいタスクが存在しています。どのタスクにも共通して問題になってくるのが、生成した解答の評価方法についてです。

例えば、翻訳タスクで「猫がマットの上にいます」を英語に訳す際、「The cat is on the mat」も「There is a cat on the mat」も同様に上手く訳しているように思えますが、これらを上手く評価することは簡単ではなさそうです。

そのため、自然言語処理では生成した文章に対して様々な評価方法が考案されており、以下にそれらを紹介していきます。


## BLEU
言わずと知れたBilingual Evaluation Understudy (BLUEではないことに注意）
*BLEU: a Method for Automatic Evaluation of Machine Translation*

翻訳タスクでよく使われる評価方法です。**人間が翻訳した文章に似ていれば似ているほど、機械が生成した文は正しそうだ**という前提に基づいています。
$ BLEU = e^{(1-r/c)}  exp(\sum^{N}_{n=1}w\_{n}logp\_{n} )$

まず、BLEUスコアの式は以上のようになっています。ここで
$ r $ は人間が翻訳した文の長さ
$ c $ は機械が翻訳した文の長さ
$ w_{n} $は適当な重み
$ p_{n} $はmodified n-gram precisionsです

*以下では、機械生成文をCandidate、人間が生成した文をReferenceと呼んでいます*
#### **modified n-gram precision**
まず単なるprecisionでは、生成文の良さを上手く評価できないことはすぐにわかります。例えば、
Candidate: the the the the the the the
に対して
Reference: The cat is on the mat
の場合、Candidateの全単語（theのみですが）は、全てReferenceに含まれているのでprecisionは$ 7/7 = 1　$です。しかし、Candidateが明らかに正しい翻訳文でないのは直感的にわかります。
そこでこのmodified n-gram precisionが本論文で提案されています。この手法は単純で、precisionを計算するときにReference中の単語は一回使うともう使えないという制約を加えているのみです。先ほどの例だと、Referenceのtheは一度使われるともう無いものと見なされるのでmodified precisionは$ 1/7 $になります。これをn-gramに対して行います。

#### **brevity penalty**
しかし、modified n-gram precisionだけでは評価方法として十分ではありません。そこで、precisionに対するrecallのような概念を取り入れます。ReferenceよりCandidateのほうが長いパターンのときはすでにmodified precisionでペナルティが課されるのでここではそれは無視し、CandidateよりReferenceの方が長いパターンに対してペナルティを課します。それがBLEU式の$ e^{(1-r/c)} $です。これをペナルティとしていれておくことで、Candidateが単に短いためにmodified precisionが高くなり、BLEUが高くなるというのを防いでいます。







## RE score

作成中です…


## 参考文献
*BLEU: a Method for Automatic Evaluation of Machine Translation* http://delivery.acm.org/10.1145/1080000/1073135/p311-papineni.pdf?ip=60.71.111.57&id=1073135&acc=OPEN&key=4D4702B0C3E38B35%2E4D4702B0C3E38B35%2E4D4702B0C3E38B35%2E6D218144511F3437&CFID=842433085&CFTOKEN=70833176&__acm__=1513773224_878c065403b6588eedd7ba928001a76a
JNIビギナーの役に立つかも知れない投稿

# 導入

酷いタイトルですね。
最近JNIに触れる機会があったので、備忘を兼ねて、
**「JNIビギナーがJNIでネイティブコード（dll）を動かすまで」**
を簡単に書きたいと思います。

***

## おことわり
※筆者の脳内Javaは6からアップデートされていません。
　なぜだか自動アップデートされないんですよね。ふしぎ。
　よって、内容に誤りを含んでいる可能性が多分にあります。
　（Javaのソースほぼ出てこないのでたぶん大丈夫と思いたい）

***

## 開発環境

* Windows 10 Pro 64bit
* Java 8
* Eclipse Neon
* Visual Studio 2015 

***

# [JNI](https://ja.wikipedia.org/wiki/Java_Native_Interface) #とは

~~リンククリックして読んでください。~~
「ネイティブコードをJavaから実行するやーつ」です（適当）

***

# ほな早速JNIを…

***

## 使う前に…

***

### そのコード、Javaで書けるよ

あとで「なんでJavaで書けるのにJNI使ったの」とか突っ込まれて困りそうなら、それは「JNIを使わずに、Javaで書いた方が良い」ということかもしれないですね。

***

### [JNA](https://github.com/java-native-access/jna)とか[SWIG](http://www.swig.org/)のほうが（たぶん）簡単に書ける

JNIはネイティブコード側に手を加える必要があります。
パフォーマンスとか気にしないのであれば、[JNA](https://github.com/java-native-access/jna)や[SWIG](http://www.swig.org/)を検討してみると幸せになれます。
きっと。

***

### 【悲報】64bit Javaさん、32bit dllを呼べない

ということなのでちゃんと合わせましょう。
64bit Javaで動かすなら64bit dllにしましょう。

***

### そのネイティブコード、マルチスレッド対応してる？

もし対応していなかったら、悲劇が起きるかも知れません。
必要なら対応しましょう。無理ならラッパー書いて排他制御するなり…（つらいね…）。

***

# やっとJNIを使います

***

## 呼び出し側Javaソース（`JNISample.java`）

```java
package com.hoge.jnisample;

public class JNISample {
  // ネイティブの関数宣言
  private native String nativeFunction(String name);

  // 実行するモジュールをロード
  static {
    System.loadLibrary("libfuga");
  }

  // ネイティブコード実行
  public String executeNative(String name) {
    return this.nativeFunction(name);
  }
}
```

***

## classファイル（JNISample.class）生成

先のソースをコンパイルして、classファイル（JNISample.class）を生成します。

```bat
javac JNISample.java
```

***

## ネイティブ側のヘッダを生成

`javah` コマンドを使用して、C（C++）のヘッダを生成します。コマンドの構文は、

```bat
javah -classpath {classpath} -d {ヘッダ出力ディレクトリ} {（パッケージ名.）クラス名}
```

***
今回は、以下のようなディレクトリ構成です。

```
java
└ com
  └ hoge
    └ jnisample
      ├ JNISample.java
      └ JNISample.class
```

コマンドはこうなります。（`java`ディレクトリで実行します）

```bat
javah -classpath .\ -d ..\jniheader com.hoge.jnisample.JNISample
```

これで、`java`ディレクトリと同階層の`jniheader`ディレクトリにヘッダファイルが生成されます。

***

## 生成されたヘッダファイル（`com_hoge_jnisample_JNISample.h`）

```cpp
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_hoge_jnisample_JNISample */

#ifndef _Included_com_hoge_jnisample_JNISample
#define _Included_com_hoge_jnisample_JNISample
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_hoge_jnisample_JNISample
 * Method:    nativeFunction
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_hoge_jnisample_JNISample_nativeFunction
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif
```

***

## あとはC（C++）で関数を実装してビルドするだけ！

ですが、

* `jni.h` のパスを「追加のインクルードディレクトリ」へ忘れず追加しましょう。
    * 手順はググればいくらでも出てくるのでここでは割愛します。
* 詳細な実装についてはこれまた割愛しますが、jナントカ型（`jobject`, `jstring`等）は変換が必要です。
    * ググればいくらでも出てｋ(ry

***

## 最後の一仕事：環境変数PATHにネイティブモジュールのパスを追加

* 手順はググればいくらでもｄ(ry

***

## いざ、実行

動きました？

***

# まとめ

JNI、意外と難しくないですよね。
もっと小難しいイメージでしたが、ぽんこつえんじにあでもあんしんでした。
この投稿が、JNIビギナーの皆様のお役に立ちましたら幸いです。

***

# 編集後記

後半の手抜きっぷり。正直反省しています。
スライドモード向けに書いてみたけど、通常モードで読みにくいかな。
vue-cli + element ui（参考URLのリンクのみ）

## 参考にしたページ、記事

#### 1. 基本的にはこちらの手順で作業を進める
[Vue.jsのコンポーネント詰め合わせ「Element」がスゴかった](https://s8a.jp/vue-js-library-element#%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B)

#### 2. localのimportをこちらの記載に書き換える
[[Vue.js] vue-cliで作成したプロジェクトにelement-uiを導入する](https://qiita.com/tackeyy/items/67177c792ee627a0b3af)
Riot 3.7と4つの値

Riot 3.7にアップデートしたところ、今まで動いていたコードがうまく動かなくなってしまいました。

# falsyな値

JavaScriptには、falsyな値（条件式に入れると`false`として処理される値）が7つあります[^1]。

* `false`
* `null`
* `undefined`
* `0`
* `-0`
* `''`（空文字列）
* `NaN`

Riot 3.7では、このうち数値でない4つ（`false`、`null`、`undefined`、`''`（空文字列））の挙動が3.6以前と違ってきます。

# 実際にやってみた
まずは[こちらのPlunkr](http://plnkr.co/edit/cxAmRtAfCNUEqsFUtD8J?p=preview)を御覧ください。ラジオボタンを生成して、`onchange`で`value`を`alert`するようにしてあるだけですが、`false`、`null`、`undefined`、`''`の4つは、「on」という妙な値を表示します[^2]。これは、Riotで値のない`value`属性を削除してしまっているからということです（[Issue](https://github.com/riot/riot/issues/2455)）。そして、`value`のないラジオボタンは`on`という値を持つものとみなされるので、このような挙動となります。

# 対策
なかなかバグの方は解決しないので、対策を考えてみました。

## Q1: HTMLとして書き出したい値は何？
Riotが最終的に生成するのはHTMLである以上、その結果は何かしらの**文字列**となります。最終結果が`false`という形で必要なのなら、`"false"`という文字列にすれば、この問題は影響しません。ただ、最終型として空文字列を出力したいのなら、この方法は使えません。

## Q2: 属性なしではまずいですか？
多くの属性では、`attr=''`とした場合と、`attr`がない場合で動作は変わりません。影響しないのなら、入っていないままでも特に困りません。ただ、一部には意味が違う例があります。

* `type`が`radio`や`checkbox`の`<input>`の場合、`value`なしでは`value="on"`とみなされることがあります。
* `<img>`の`alt`については、`alt=""`だと「画像は装飾なのでテキスト化不要」、`alt`なしでは「画像はテキストで代替不能」と、テキストにならない点では同じですが、セマンティクスは正反対になります。
* （絶賛募集中）

## Q3: 他の手段はありませんか？
`<img>`の`alt`はどうしようもなさそうですが、`<input>`の`value="on"`については直接`radio`や`checkbox`を出力に使わず、`hidden`で値を出力させるようにすれば、`value`なしが`value=""`と同じように動いてくれます。


[^1]: 厳密に言えば言語外＆規格外ですが、昔のIEとの互換上、`document.all`はfalsyに評価されます。
[^2]: Plunkerの過去版に、Riot 3.6.3で動かしているものがありますが、そちらでは`false`は「false」と、残り3つは空文字列が表示されます。
Rubyのmixinの振る舞いを#~methodsを使って確認する

# 環境
Ruby 2.4.3

# 準備
下のようなmoduleとclassを用意します。

```main.rb
module Included
  def self.included_class_method; end

  def included_public_instance_method; end

  protected

  def included_protected_instance_method; end

  private

  def included_private_instance_method; end

  module_function

  def included_module_function; end
end

module Extended
  def self.extended_class_method; end

  def extended_public_instance_method; end

  protected

  def extended_protected_instance_method; end

  private

  def extended_private_instance_method; end

  module_function

  def extended_module_function; end
end

class A
  include Included
  extend Extended
end
```

# テスト

## インスタンスメソッド

```rb
# public
A.public_instance_methods
# => [:included_public_instance_method, :remove_instance_variable, ...]

# protected
A.protected_instance_methods
# => [:included_protected_instance_method]

# private
A.private_instance_methods
# => [:included_private_instance_method, :included_module_function, :DelegateClass, ...]
```

モジュール関数はprivateのインスタンスメソッドとしてincludeされるようです。
あとはまあ予想通りです。

## 特異メソッド

```rb
# 特異メソッド
A.singleton_methods
# => [:extended_public_instance_method, :extended_protected_instance_method]
```

## クラスメソッド

最後にクラスメソッドです。

```rb
# public
A.public_methods
# => [:extended_public_instance_method, :new, :allocate, :superclass, :<=>, ...]
A.public_methods(false)
# => [:extended_public_instance_method, :new, :allocate, :superclass]

# protected
A.protected_methods
# => [:extended_protected_instance_method]
A.protected_methods(false)
# => [:extended_protected_instance_method]

# private
A.private_methods
# => [:extended_private_instance_method, :extended_module_function, :initialize, :inherited, :using, ...]
A.private_methods(false)
# => [:extended_private_instance_method, :extended_module_function, :initialize, :inherited]
```

やはりモジュール関数はextendではprivateなクラスメソッドになるようです。
また、あまり予想していなかったことですが、`#new`や`#initialize`等がfalseを渡したときにも含まれます。よくよく考えてみると自明ですが、これらはClassクラスのインスタンスメソッドです。

```rb
Class.instance_methods(false)
# => [:new, :allocate, :superclass]
Class.private_instance_methods(false)
# => [:initialize, :inherited]
```

# まとめ
- インスタンスメソッドはアクセス修飾子はそのままにinclude or extendされる
- クラスメソッドはinclude or extendされない
- モジュール関数はprivateのインスタンスメソッドとしてincludeされる
- モジュール関数はprivateのクラスメソッドとしてextendされる

# 補足
今回使いませんでしたが、
`#methods`は`#public_methods` + `#protected_methods`,
`#instance_methods`は`#public_instance_methods` + `#protected_instance_methods`
tmux-個人的おすすめプラグイン

# このページについて
個人的に便利だなと感じた、tmuxプラグインを載せていきます。
tmuxにプラグインを導入する方法については [こちら](https://qiita.com/Cj-bc/items/7227c45cdfc86a927b44)

# List

* tmuxのプラグインマネージャー: *tpm/tmux-sensible*
* status_barに電池残量表示: *tmux-battery*
* status_barにwifi接続状況表示: *tmux-online-status*
* status_barにcpu使用率を表示: *tmux-cpu*
* pane内のurlに素早くアクセス: **tmux-urlview**
* 再起動後もtmux画面を保持する: **tmux-resurrect**

# tpm/tmux-sensible
tmuxのプラグインマネージャーを扱うために必要なプラグイン。
これがあるとプラグインの導入・管理も楽々！
url: https://github.com/tmux-plugins/tpm


# tmux-battery
status_barに電池残量を表示してくれる。mac等でフルスクリーンモードの時など便利
url: https://github.com/tmux-plugins/tmux-battery

# tmux-online-status
status_barにwifi接続状況を表示してくれる。同じくmac等でフルスクリーンモードの時など便利
url: https://github.com/tmux-plugins/tmux-online-status

# tmux-cpu
 status_barにcpu使用率を表示してくれる。~~やったね、これでアクティビティモニタ開かなくても見れる！~~ これまた、mac等でフルスクリーンモードの時など便利
url : https://github.com/tmux-plugins/tmux-cpu

# tmux-urlview
 `prefix`+`<ctrl>+u`で、現在使っているpaneに表示されているurlのリストを表示、選択してwebブラウザでそのurlを開くことができる。

```sh
 <X_X>:~ $https://qiita.com/Cj-bc/items/7227c45cdfc86a927b44
 -bash: https://qiita.com/Cj-bc/items/7227c45cdfc86a927b44: No such file or directory
 <X_X>:~ $https://google.co.jp
 -bash: https://google.co.jp: No such file or directory
 <X_X>:~ $https://youtube.com
 -bash: https://youtube.com: No such file or directory
```
このように同じurlが複数ある場合でも

```sh
UrlView 0.9: (3 matches) Press Q or Ctrl-C to Quit!

->    1 https://qiita.com/Cj-bc/items/7227c45cdfc86a927b44
      2 https://google.co.jp
      3 https://youtube.com

```
重複せずに数えてくれる。便利。

url: https://github.com/tmux-plugins/tmux-urlview

# tmux-resurrect
tmuxのセッションは、たとえ`<prefix>`+`d`でデタッチしていたとしてもPC本体を再起動するとデフォルトでは消えてしまう。そんな時助かるのがこれ。
`<prefix>`+`<Ctrl>+s`で現在のセッションを丸ごとセーブしてくれる。
設定によっては、各pane上で動いているプログラムのプロセスまで保存してくれる。(設定は下記)
`set -g @resurrect-capture-pane-counts 'on'`

url: https://github.com/tmux-plugins/tmux-resurrect
Drupal 8 の Page Manager で作成したページのタイトルを RouteEnhancer で変更する

Drupal 8 の Page Manager モジュールでページを作成する際に、「〇〇リスト」といった“〇〇”を動的に出力しないといけない場合があります。その対応の際に、RouteEnhancer を使ったところ割と楽に変更する部分を作成できたのでそれを記載します。

## TL;DR

RouteEnhancer を使うと、applies と enhance のメソッド定義と yaml の記述だけでタイトルを動的に設定できる。

## RouteEnhancer の概要と設定方法

RouteEnhancer とは、**作成された Route** に条件を設定して後から変更することができるクラスです。 RouteEnhancer を使用するためには、`module_name.service.yml` に下記のような記述が必要になります。

```yaml:module_name.service.yml
services:
  module_name.example_route_enhancer:
    class: Drupal\module_name\Routing\ExampleRouteEnhancer
    tags:
      - { name: route_enhancer }
```

もし、RouteEnhancer 内部で Drupal のサービスを使用したい場合は、下記のように arguments の設定を追加し、arguments に `[@service_name1, @service_name2]` の形式で記述します。

```yaml:module_name.service.yml
services:
  module_name.example_route_enhancer2:
    class: Drupal\module_name\Routing\ExampleRouteEnhancer2
    arguments: [@current_user, @entity_type.manager]
    tags:
      - { name: route_enhancer }
```

## RouteEnhancer クラスのメソッド

 TL;DR でも記述した通り、クラスのメソッドは基本的には applies と enhance のみになります。

### applies

enhance で変更を加える Route の条件を判断するメソッドです。引数に Route オブジェクトのみが来るので、下記のようにPage Manager で設定したパスを指定するのがベストだと思います。

```php
public function applies(Route $route) {
  return $route->getPath() === '/hogehoge/{nid}/list';
}
```

### enhance

enhance は Route オブジェクトに設定されたデフォルト値を変更するためのメソッドです。Page Manager で設定したパラメータに紐づく値は下記のコードのようになります。（前述の `/hogehoge/{nid}/list` なら `$default['nid']`）
ページの内容を表示する variant は `$defaults['page_manager_page_variant']` に代入されているので、この内容を変更するとページのタイトルを変更することができます。

```php
public function enhance(array $defaults, Request $request) {
  // /hogehoge/{nid}/list ならパラメータ名が nid になる
  /** @var \Drupal\node\Entity\Node $node */
  $node = $defaults['nid'];
 
  // Page Manager の PageVariant Entity を取得してタイトルを動的に設定する
  /** @var \Drupal\page_manager\Entity\PageVariant $variant */
  $variant = $defaults['page_manager_page_variant'];
  $variant_settings = $variant->get('variant_settings');
  $variant_settings['page_title'] = $node->label() . '一覧';
  $variant->set('variant_settings', $variant_settings);
  return $defaults;
}

```

もし、Drupal のサービスを利用する場合は、下記のようにコンストラクタのメソッドを作成し、サービスをクラス内のプロパティとして設定する必要があります。

```php
// 先述の ExampleRouteEnhancer2 なら下記のようになる
public function __construct(AccountProxy $current_user, EntityTypeManager $entity_type_manager) {
  $this->currentUser = $current_user;
  $this->entityTypeManager = $entity_type_manager;
}
```

## まとめ

本記事では、Page Manager モジュールでパラメータが設定されたページのタイトルを RouteEnhancer を使用して動的に変更する方法を記載しました。RouteEnhancer では、既存の Route に対して変更を加えることができるため、未確認ですが Page Manager で設定した内容に限らず、`routing.yml` で設定した内容（`_form` など）を変えることも可能だと思います。
AtomでAnaconda Promptを使う方法

WindowsでMinicondaを使っている場合の設定方法です．

1. Platformio Ide Terminalをインストール．
2. Platformio Ide TerminalのSetting画面で，
  + Auto Run Command: `path\to\miniconda\Scripts\activate.bat root`
  + Shell Override: `C:\Windows\System32\cmd.exe`

`activate.bat`の引数は仮想環境名を指定します．仮想環境を使っていないなら`root`とします．もちろん，後から別の環境を`activate`できます．Shellはデフォルト設定だとうまくいかなかったので，コマンドプロンプトを絶対パスで指定しました．上記２つのセッティングを適切に行えば，LinuxやMacでもできると思います．

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/115267/10a7ffff-a564-7433-c03c-30f8bf058bce.png)
RaspberryPi2 + Volumio　+ モバイルwifi = ネットワークオーディオ

そういえば家にRaspberryPiが転がっているのを思い出した。

何か使えないかと思い音楽再生機を簡単に作ってみた

現在は諸事情によりモバイルwifiで生きているのだが、その環境でできないか考えてやってみた。


構成は
メインPC
DALIのスピーカー
Toppingという中華アンプ
モバイルwifi
RaspberryPi2(Volumioインストール済み)

これら既に家にあるものでできるだろうと考えたのが甘かった、、、

結論から言うと別途ルーターを用意した


1. まず、メインPCのLANとルーターのLANを繋ぐ(WANではない)
2. RaspberryPiとルーターのLANを繋ぐ(WANではない)
3. メインPCのブラウザからhttp://volumio.local/　とか　直接IPをタイプしてアクセスする
4. アクセスすると無線wifiの一覧が出るのでモバイルwifiを選択してpassを入力
5. wifiの設定が完了したらメインPCとRaspberryPiからLANケーブルを抜く

以上でモバイルwifiでなんちゃってネットワークオーディオ環境が作れる。

簡単に説明したが、もっと詳しく知りたい方はご連絡ください
一時的なSSOサーバのログイン監視

# 一時的なSSOサーバのログイン監視

## はじめに
AWSのEC2インスタンスにリバースプロキシ型のSSO(Single Sign On)をのせていて、
Zabbixでログイン監視をしていたのですが、
一旦、Zabbixを外すことにしたので、一時的にログイン監視を入れることになったお話です。
※ 説明ながい・・:unamused:

## Zabbixってなんすか？
簡単に言いますと、
　サーバー動いてんの？
　ログイン出来ないよ・・
　アプリ死んでない？
　メモリ枯渇してるっぽい・・等、
統合的にまるっとサーバを監視するツールになります。
詳しくはWikiで。
https://ja.wikipedia.org/wiki/Zabbix

このZabbixを使ってログイン監視をしていたけれど、
今回、この便利なZabbixを停止して、
取り急ぎ、ログイン監視だけ組み込んでみました。
※メモリや容量辺りはAWSのCloudWatchでOK:thumbsup:

## Jenkins使うかな
やっぱりここはCIツール界のエース Jenkins を活用して、
定期的な監視運用を進める事にしました。
※ cronは古すぎます・・・

## ざっくりアーキテクト
Jenkinsで定期的にログイン監視を行い、
ログイン失敗したらSNSへ通知 ⇒ Lambdaへ依頼 ⇒ Twilioから電話 ⇒ がっかり・・
という流れにしました。
※ Lambda ⇒ Twilio連携は元から使っていたので

![image.png](https://qiita-image-store.s3.amazonaws.com/0/217966/aa864ff7-7d9d-d65f-fba7-99050618299c.png)

## ログイン監視シェル
Jenkinsから叩くログイン監視シェルはこんな感じ。
ログインしてログアウトして問題無ければ終了ですね。
※ログアウトしとかないとセッション溜まるし。

SNSへの通知もシェルの中で実行しています:v_tone3:

```shell

#!/bin/sh

# Topic ARN指定 -> Lambdaへ依頼するためのTopic
snsname="arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:telephone-call"

# 第一パラメータ：証明書チェック有無(0：無、1：有)
# 第二パラメータ：SSOサーバURL
# 今回はgetoptも使わず直で指定
if [ $# -ne 2 ]; then
  exit 9
fi

# 第一パラメータが 0 なら証明書チェックをSKIP(-kオプション追加)
sslopt=""
if [ ${1} -eq 0 ]; then
  sslopt="-k"
fi
# 第二パラメータ格納
sso_url=${2}

# cookeファイルパス定義
cookie_file=$(cd $(dirname $0) && pwd)"/tmp/cookie.txt"

# sso login 実行
# ログイン後のページに "SSO TOP Page" が含まれていればログイン成功
# 諸事情によりステータスコードは見ていない
login=`curl -v ${sso_url} -d 'ACCOUNTUID=ADMIN' -d 'PASSWORD=ADMINPASSWD' ${sslopt} -c ${cookie_file} -L | grep "SSO TOP Page" | wc -l`

# login失敗したらSNS Topicへ通知
if [ ${login} != 1 ]; then
  # SNSへ通知 「SSOへのログインに失敗しました。」と電話で連絡
  aws sns publish --region ap-northeast-1 \
      --message "SSOへのログインに失敗しました。" \
      --topic-arn ${snsname}
  exit 9;
fi

# logout 実行
logout=`curl ${sso_url} -d 'LOGOUT=SSO_LOGOUT' -b ${cookie_file} ${sslopt} -o /dev/null -w '%{http_code}\n'`

# ステータスコードが200以外はエラー
# logout 失敗したらSNS Topicへ通知
if [ ${logout} != 200 ]; then
  # SNSへ通知 「SSOへのログアウトに失敗しました。」と電話で連絡
  aws sns publish --region ap-northeast-1 \
      --message "SSOへのログアウトに失敗しました。" \
      --topic-arn ${snsname}
  exit 9;
fi

exit 0;
```
## おわり
Lambda ⇒ Twilio で電話するところは元々存在していたので、
説明は省きましたがざっとこんな感じです。
もっと色々方法あると思いますが、サクッと対応という感じであれば良い方法かなと。
プログラムで操作できる照明 『Philips Hue』のお話。

# はじめに
この記事はWHITEPLUS Advent Calendar 2017の24日目です。

こんにちは。株式会社ホワイトプラス、マーケターの@harupoです。

今回は、ワイもかつては一応エンジニアやってん・・・という思いを胸に、プログラムで操作できる照明の話を書こうと思います。

# スマートIoT照明 『Philips Hue』とは
皆さんは、Philips社が販売している「Hue」という照明をご存知でしょうか。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/31123/5bb1b242-27a0-18f9-3999-abdac7b27b94.png)
出典：[Philips Hue](http://www2.meethue.com/ja-jp/)

「Hue」は見た目こそ普通の電球ですが、スマホやタブレットから照明のON/OFF、明るさや色を調整することができる特徴があります。

「…で？」

と思ったことでしょう。

「スマホで操作？　壁にあるスイッチを押せばいいじゃない。」
「調光できる？　一般的な色以外、普段の生活で使わないでしょ。」

はい、__全くその通り__です。

雰囲気の良い写真を持ってきて、Hueの魅力を伝えようと試みましたが、
冷静になって考えてみるとそうなりますよね。なお、上記は妻のセリフです。

けど、ちょっと待っていただきたい。

「Hue」は、スマホでちょいちょいと操作できるだけの照明ではないのです。

__APIを使って制御できるんです。__
自分で作成したプログラムからAPIを実行して、「Hue」を操作することができる。
つまり、__利用する側の創意工夫__によって、__利用用途は無限大__に広がるわけです。

……え？ でも私はプログラムを書いたことがない？

大丈夫です。__ご安心ください。__

エンジニアじゃなくても、ちゃんと色々できるようになっています。
実際に、エンジニアからマーケターとして転生した私でも「Hue」を使えているのです。
冷ややかな妻の視線を除けば、何の問題もなく便利に使えています。

まずは、「Hue」の公式アプリの機能を見て見ましょう。

# 公式アプリだけでも色々遊べる
1. ルーチン設定
    2. タイマー連動
        * 起床時間に合わせて徐々に照明を明るくする。
        * 就寝時間に合わせて徐々に照明を暗くする。
        * 特定の時刻に照明を操作する。
    3. GPS連動
        * 外出したときに自動的に照明を消す。
        * 帰宅したときに自動的に照明をつける。

2. シーン設定
    * 任意の写真から色を抽出して照明を調光する。 
        * 例：夕暮れのシーン・北極のオーロラ・マグロのお寿司など

3. スマートスピーカー連携
    * AlexaやSiriから照明を操作することができる。
        * 例：「Hey, Siri 照明をもっと明るくして」

これらの事を、プログラムを１行も書く事なく実現することができます。
公式アプリだけでも結構遊べます。いえ、便利に使えます。

# マグロのお寿司の写真で調光してみよう
Hue公式アプリには、好きな写真を読み込ませて、その写真の色合いを照明で再現する機能があります。なんと便利な機能なのでしょう。

具体的な例として、「鮪のお寿司」の写真を読み込ませてみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/31123/0236f379-c3a9-2745-ed7e-7c815d8e1509.png)
* 読み込んだ画像はこれ

これが……
　
　

　　

<img src="https://qiita-image-store.s3.amazonaws.com/0/31123/0e34016c-be7b-1e88-e27f-fb354b96c799.png" width="60%"/>
こうなります。右上のランプがシャリ部分ですね。

ちなみに、天井のHue以外にデスクの上にも2つのHueランプがあるのですが、こちらもセットでマグロ仕様になります。

私は大変楽しいのですが、やはり妻の目線は冷凍マグロのように冷たいです。

# APIを使って自由にHueを操作する
さて、APIを使うとどのようなことができるのでしょうか。
ホワイトプラスの社員目線で考えてみます。

1. マーケティング
    1. 目標数値が達成したら、ハッピーな演出で照明が点滅する。
2. システム
    3. 障害が発生すると、照明が赤く光ってお知らせする。(https://hacklog.jp/works/52108)
    4. プログラミングするときに、青系の光にして集中力を高める。
3. プロダクト
    4. 衣類の検品時にシミの見落としがないように、どんな環境でも同じ照度・色温度を再現できるようにセンサーとHueを連動させて調光する。

10分くらい考えてみましたが、なかなか出て来ません。
「それは照明を制御する以外の方法が適しているのでは？」→「いかにも。」の自問自答。

いい感じのアイディアを思いついた人は、是非[こちらから「話を聞きに行きたい」]((https://www.wantedly.com/companies/whiteplus))を押してご連絡ください。そして一緒に楽しく働きましょう。

# 最後に
今回は紙面の都合で、APIを使ったチュートリアルまで踏み込むことができませんが、興味を持たれた方は是非Hueを[まとめ買い](https://www.amazon.co.jp/s/ref=nb_sb_noss?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&url=search-alias%3Dcomputers&field-keywords=hue)して、[開発資料](https://developers.meethue.com/documentation/getting-started
)を参考に楽しい照明生活を送ってくださいね！


## ホワイトプラスでは、一緒に働くマーケターを募集しています。
* [リネットの新規獲得ユニットリーダー候補募集！](https://www.wantedly.com/projects/175172)
* [クリーニング業界に変革をもたらす18卒・19卒マーケッター募集!!](https://www.wantedly.com/projects/152852)
Twitter の いいねをした方の ID の取得 (Python3)

次のページを参考にしました。
[Getting list of users who favorited a status](https://stackoverflow.com/questions/28982850/twitter-api-getting-list-of-users-who-favorited-a-status)

スクレイピングで、twitter の いいねをした方の ID の取得する方法です。２５個のID　までが取得可能です。
取得した配列の最後の要素は、投稿者の ID になります。


```py3:get_favorited.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#	get_favorited.py
#
#						Dec/20/2017
# ------------------------------------------------------------------
import urllib.request
import urllib.error
import re
import sys
#
def get_user_ids_of_post_likes(post_id):
	try:
		url = 'https://twitter.com/i/activity/favorited_popup?id=' + str(post_id)
		json_data = urllib.request.urlopen(url).read()
		found_ids = re.findall(r'data-user-id=\\"+\d+', json_data.decode('utf-8'))
		unique_ids = list(set([re.findall(r'\d+', match)[0] for match in found_ids]))
		return unique_ids
	except urllib.error.HTTPError:
		return False
#
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
post_id = 877792536680476672
array_aa = get_user_ids_of_post_likes(post_id)
#
icount = 0
for user_id in array_aa:
	print(icount,user_id)
	icount += 1
#
sys.stderr.write("len(array_aa) = %d\n" % len(array_aa))
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

次の環境で動作を確認しました。

```text
$ uname -a
Linux iwata 4.19.4-arch1-1-ARCH #1 SMP PREEMPT Fri Nov 23 09:06:58 UTC 2018 x86_64 GNU/Linux
$ python --version
Python 3.7.1
```
NIPS2017の話

# NIPS 2017 参加報告
[NIPS2017](https://nips.cc/Conferences/2017) に参加してきましたので、その報告がQiitaになかったのでいい機会ですのでします。
Neural Information Processing Systems(NIPS)は機械学習系のトップカンファレンスで、今年で31回目の国際会議です。
採択された論文は[NIPS Proceedings](http://papers.nips.cc/book/advances-in-neural-information-processing-systems-30-2017)から見ることができます。 

## 概要

* 日時 2017/12/04 - 12/09
* 場所 ロングビーチ, ロサンゼルス
* 参加人数　8,000人
* 投稿数 3,240
* 採択数 679(21%)
    * オーラル　40
    * スポットライト　112
    * ポスターのみ　527
* 傾向
    * Algorithm,DeepLearning,Applicationがほとんど

![レジストレーション待ち](https://i.imgur.com/BB22Luu.jpg)

![参加登録の早さ](https://i.imgur.com/AYGGuL0.jpg)

![参加人数](https://i.imgur.com/bG2tl7M.jpg)


![採択数](https://i.imgur.com/hDhWxSr.jpg)

![分野別統計](https://i.imgur.com/5uYr56p.jpg)


![ポスター会場](https://i.imgur.com/haYC1Sz.jpg)

![ホールA](https://i.imgur.com/kwLPW8x.jpg)





## はやりそうな分野
会場で感じた雰囲気とNIPS日本人会等の参加者間の交流にて感じたこと

### Meta Learning
* チュートリアルの[Deep Learning: Practice and Trends](https://drive.google.com/file/d/1SuwiICLERd7SfYo3FiqNG0tCEBUjKcT7/view)やシンポジウムの
[Metalearning symposium](http://metalearning-symposium.ml/)にて取り上げられた。
* Few Shot Learning等の技術要素は個々で認識していたが、これらの分野のことをMetaLearningと呼ぶことを認識した
* 天才による体系的な説明はわかりやすい

### Graph構造、非ユークリッド幾何上でのCNN
* チュートリアルの[Geometric Deep Learning on Graphs and Manifolds](https://www.dropbox.com/s/zdosxw3nc3f1p2r/NIPS-GDL.pdf)で話された内容。
* ユークリッド空間に配置された画像・音声・文章は如何にCNNに持っていくかによって解決された。しかし、非ユークリッドなデータではCNNではチャレンジングな問題。
* 空間的もしく周波数領域でのConvolutionを定義することで、グラフデータ等の非ユークリッドなデータでもうまくいくようになってきた。


## 現地に行く意義
### 著者との交流
* 論文を読んでもいまいち腹落ちしない内容でも、著者の説明を聞くとすんなりと理解できる
* 単なる著者が人間に
* GitHub上のプルリクもしやすくなるかな
 
### 参加者との交流で情報収集
* 現地で日本人で集まり情報収集を行うことで、今後のつながりに期待できる
* 世界には同業他社が意外と多いのでその分野で交流できる
* いたるところでオフ会
* というか学会そのものがオフ会

### 発表に対する反応を見る
* どの発表がウケていたか
* どの発表が熱い議論がなされていたか
* 業界としてどちらに行きそうか、どの分野を注視すべきか
* やはり現地のライブ感は重要

### 会議全体のレベル感を知る
* NIPS初参加の身としては、通す前に一度様子を見てレベル感を知ることができる
* applicationの発表だとしても、ポスターで議論すると理論的な防御手段を持っているレベルだった
Bootstrap3でnavを使うとタイトル行とナビゲーション行を分割（２行）にできない


やりたいことは単純で１行目をタイトルだけ。
２行目にナビゲーションの行を作りたい。

が、`bootstrap3`の`nav`のサンプルを使うと全部が１行にタイトルとナビゲーションがあって思い通りにならない。
なので、頑張ってみたお話。

# やりたいコト
- １行目をタイトルだけにする
- ２行目をナビゲーションにする

![ナビゲーション・バー_≪_コンポーネント_≪_Bootstrap3日本語リファレンス.png](https://qiita-image-store.s3.amazonaws.com/0/32902/b8fd41cc-b493-200a-921e-4bcd53ae7ab2.png "ナビゲーション・バー_≪_コンポーネント_≪_Bootstrap3日本語リファレンス.png")

# ソース
```erb
    <header class="jumbotron title text-center">
      <h1><%= link_to "MAPACHANNEL", root_path %></h1>
    </header>
    <div class="btn-group btn-group-justified btn-group-lg">
      <%= link_to root_path, class: "btn btn-default" do %>
        <%= fa_icon("commenting comment-info", text: "人気") %>
      <% end %>
      <%= link_to root_path, class: "btn btn-default" do %>
        <%= fa_icon("commenting comment-info", text: "新着") %>
      <% end %>
      <%= link_to root_path, class: "btn btn-default" do %>
        <%= fa_icon("commenting comment-info", text: "見つける") %>
      <% end %>
      <%= link_to root_path, class: "btn btn-default" do %>
        <%= fa_icon("commenting comment-info", text: "サイトについて") %>
      <% end %>
    </div>
```

↓html展開後

```html
	<header class="jumbotron title text-center">
      <h1><a href="/">MAPACHANNEL</a></h1>
	</header>
	<div class="btn-group btn-group-justified btn-group-lg">
      <a class="btn btn-default" href="/">
        <i class="fa fa-commenting fa-comment-info"></i> 人気
      </a>
      <a class="btn btn-default" href="/">
        <i class="fa fa-commenting fa-comment-info"></i> 新着
      </a>
      <a class="btn btn-default" href="/">
        <i class="fa fa-commenting fa-comment-info"></i> 見つける
      </a>
      <a class="btn btn-default" href="/">
        <i class="fa fa-commenting fa-comment-info"></i> サイトについて
      </a>    
	</div>
```

```css
// title
.jumbotron {
  padding: 20px 0;
  margin: 0px;
}

.title{
  background-color: #222;
  border-color: #090909;
  h1 {
    font-size: 24px;
    a {
      color: #FFF;
    }
  }
}
```

- 1行目のタイトル部分は`jumbotron`を使って作成
なんか別のやり方でやると妙なスペースが入ってどうしようもなかったので。
ただ普通に指定すると`padding-top: 48px`、`padding-bottom: 48px`が指定されていて領域広すぎるので調整する`padding`を設定した

- ２行目は`nav`を使わなくてもいいじゃね？とふと思い`btn-group`を使ったらすんなり出来た


で完成したのが、こんな感じ。

![Mapachannel.png](https://qiita-image-store.s3.amazonaws.com/0/32902/cf9e3928-ce0f-0bff-00ff-cb9b499c51ad.png "Mapachannel.png")

なんとなくいい感じになったので、めでたしめでたし。
アプリケーションからS3内の画像を移動させる時にアクセス権限を付与する

とあるプロジェクトで、ユーザーの投稿を論理削除し後々復活させると、
復活させた画像のパブリックアクセスのオブジェクト読み取り権限が無くなっていたのでその対応。
rails4環境です。

# 結論から

オプションでaclを指定します。

# 使用例
```rb
s3 = Aws::S3::Resource.new

# 対象にする画像オブジェクトを取得
object = s3.bucket("バケット名").object("対象ファイルのパス")

# 付与するオプションを定義。今回の肝。
options = {acl: 'public-read'}

# 移動先の定義
location = "移動先のパス"

# aclオプションを付けて指定先にコピー
object.copy_to(location, options)

# 元の画像は削除
object.delete
```

# 参考
http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#copy_to-instance_method

http://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/acl-overview.html
PythonのCGIで日本語が文字化けしたときの対処法

# 環境
Pythonのバージョン: Python3.6.2 32bit版
OS:Windows 10
# 内容
PythonのCGIスクリプトから出力したHTMLの日本語部分が文字化けする

# 解決方法

```py3:hello_world.py
import sys
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
```
のような記述でエンコード設定する
Slackのゲストアカウント管理が大変なのでbotを作った

これは[ドワンゴ Advent Calendar 2017](https://qiita.com/advent-calendar/2017/dwango) 21日目の記事です。急遽決まったのであわててコネタを書いています。

![slack](https://camo.qiitausercontent.com/158c73d201e496109493a72771863b9304236f0e/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3130333234372f62666461323530642d623836372d323739662d636539632d3632313565353838346230342e706e67)

## ドワンゴとSlack

ぼくは技術コミュニケーション室というポジションで働いています。この組織については[去年書いた](http://ch.nicovideo.jp/dwango-engineer/blomaga/ar1161598)ので読んでいただけると幸いです。

さて、部署のタスクのひとつとして「Slackの管理」というのがあります。ドワンゴはエンジニアを中心にSlackをヘビーユースしており（今年受けた[取材記事](https://seleck.cc/1063)をご参照ください）、その利用はエンジニア以外にも広がっています。

その結果出てくるのが、社外の方との連絡にもSlackを使いたい、という要求。標準的に使われるコミュニケーションツールで社員以外ともコミュニケーションができると、仕事が捗ることこの上なしですね。

## ゲストアカウント

Slackもそういうニーズは把握しているので、早くから[ゲストアカウント](https://get.slack.help/hc/ja/articles/202518103-%E3%83%9E%E3%83%AB%E3%83%81%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%AB%E3%82%B2%E3%82%B9%E3%83%88-%E3%82%B7%E3%83%B3%E3%82%B0%E3%83%AB%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%AB%E3%82%B2%E3%82%B9%E3%83%88)という仕組みが用意されています。

ドワンゴではセキュリティ部門と相談し、業務上必要かつ棚卸しが適切に行われているのであれば、社外の方にもシングルチャンネルゲストのアカウントを発行しています。

## 棚卸しと有効期限

ところが人間とは怠惰なものなので、ほっておくと棚卸しなど無限にさぼってしまいます。もちろんそこもSlackはお見通しで、ゲストアカウントには解除期限を設定することができます。

適切な有効期限をつけてアカウントを発行し、必要なものを延長していくことで、社外の方との便利なコミュニケーションをセキュリティリスクを抑えて維持できる、というのが目論見です。

しかし人間とはどこまでも怠惰で、自分が申請したゲストアカウントがいつ解除されるかを管理しておくことすらできません。ゲストアカウントは解除される48時間前に「inviteした管理者」にslackbotから通知が来るのです。つまり、ゲスト本人も申請者も、そのアカウントがいつ解除されるかを知ることができないのです。

## そこでSlarinですよ

ぼくもエンジニアなので、困りごとは技術で解決するのが本分です。意図せぬアカウントの解除に困り果てた申請者も、ぼくの仕事を肩代わりしてくれているアシスタント（…についてはどこかで語りたいが今は略）も、コードを書いて助けようじゃありませんか。

前置きが長くなりましたがそのために作ったSlack botが[Slarin](https://github.com/kwappa/slarin/)です。

## Slarinの機能

### メールアドレスのような文字列を投げつけるとアカウントを検索し寿命を教えてくれる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/1994/2c540964-4438-819b-a0b6-afaf1eeb145e.png)

全チャンネルで動くのも微妙なので、動作することを許可するチャンネルを `.env` で指定できるようにしています。ログをどう取ろう…と一瞬考えたのですが、Slackに吐き出せば十分だなと気づきました。

### DMすると自分のアカウントの寿命を教えてくれる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/1994/764134cd-3d0b-4d96-823d-7575f0aa8997.png)

ゲストが自分のアカウントの寿命を知るための手段としてDMを利用することにしました。ゲストアカウントは自分のいるチャンネルのユーザーしか見えないので、Slarinをinviteしておく必要があります。

## 技術的に

一昨年のカレンダーに[書いた](http://randd.kwappa.net/2015/12/25/652)のと同じく[ruboty](https://github.com/r7kamura/ruboty)を使っています。新しいことを試すには時間がなさすぎた…。

ザザッと書いたのでテストはないしコードも雑ですが、メールアドレスを抽出する部分だけはスプレッドシートから雑にペーストするなどのユースケースが考えられるため、[正規表現で頑張って](https://github.com/kwappa/slarin/blob/master/handlers/ruboty-slarin/lib/ruboty/slarin/slack_client.rb#L43-L45)しまいました。

## まとめ

ドワンゴのSlackは仕事のツールとしてはもちろん、エンタメとしても大変楽しめるツールです。興味のあるソフトウェアエンジニアの方は、ぜひ[こちら](http://nico.ms/job/)からご連絡ください！
Vue.jsの開発環境を構築してみる

Vue.js を触る機会があったので、書くまででもないがインストール手順を書いてみた。

## はじめに
この記事は、npm コマンドが既に使えるようになっていることが前提。


## インストール
インストールは、ターミナルでnpm コマンドを使う。vue-cli のパッケージをインストールすることで、すぐに開発環境を準備することができる。

```
npm install -g vue-cli
```
## プロジェクトの開始、テンプレートの準備
Vue.js で開発するために必要なファイル等を、ターミナルを起動させて下記のコマンドを実行しプロジェクトを作成する。

```
vue init webpack プロジェクト名
```
コマンド実行後、プロジェクトを作成するにあたり、色々とターミナルで聞かれるが、全てEnter で進めてよい。プロジェクト作成後、プロジェクト名のディレクトリが作成されている。

## 実行後のVue.jsの稼働確認

作成したプロジェクト名のディレクトリに入り、下記のコマンドを実行する。(依存関係のパッケージをインストール並びにプロジェクトの稼働確認)

```
cd プロジェクト名
npm install
npm run dev
```
コマンド実行後、Vue.jsのWebサーバが起動する。http://localhost:8080 をブラウザで開き、Vue.jsのロゴマークがついているページが表示されたら、Vue.jsの環境構築は完了。※ WebサーバのURL は8080のポート番号が既に使われている場合は異なる。

## 参考URL
Vue.js の公式サイト。
https://jp.vuejs.org/v2/guide/installation.html
Azure上にGitlabを立てる

#手順概要
* Azure マーケットプレースから`Gitlab Community Edition`を選択する。
* サイズは最小動作構成の`DS1 Standard`(1Core 3.5G)にする。
* VM起動したら、ブラウザで80ポートにアクセスする。
* rootパスワード設定画面になるので、パスワード入力する
* ログイン画面で、ユーザ名`root`、パスワード`<設定したパスワード>`でログインする
* 参考:詳細手順（英語）
[How to Setup a GitLab Instance on Microsoft Azure \| GitLab](https://about.gitlab.com/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/)

# メール送信設定
`/opt/gitlab/embedded/service/gitlab-rails/config/environments/production.rb`の`config.action_mailer.delivery_method`の項目を以下の様に編集して、再起動する。

```production.rb
  ### 設定例 ###

  config.action_mailer.delivery_method = :smtp
  # Defaults to:
  # # config.action_mailer.sendmail_settings = {
  # #   location: '/usr/sbin/sendmail',
  # #   arguments: '-i -t'
  # # }
  config.action_mailer.smtp_settings = {
    :address              => "<smtp host>",
    :port                 => 587,
    :domain               => 'example.com',
    :user_name            => '<login name>',      # 省略可能
    :password             => '<login password>',  # 省略可能
    :authentication       =>  :login,             # 省略可能
    :enable_starttls_auto => true                 # 省略可能
  }
```

　　- 参考：[GitLab からの通知メールを設定する \| まくまく Git ノート](https://maku77.github.io/git/gitlab/email-settings.html)

　　- SendgridのSMTPを使用する場合は、以下を参考にする:
　　　　[SMTPの接続情報を教えてください。 – サポート](https://support.sendgrid.kke.co.jp/hc/ja/articles/204187885-SMTP%E3%81%AE%E6%8E%A5%E7%B6%9A%E6%83%85%E5%A0%B1%E3%82%92%E6%95%99%E3%81%88%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84-)
　　  　　→　認証情報にAPIキーを使用する場合、ユーザ名は`apikey`固定、パスワードは生成されたAPIキーとなるので注意

# メール確認なしでユーザ登録できるようにする
メールサーバが立てられない場合などに、回避策として実施。
[GitLabで新しいユーザーをメールによる認証なしで登録したい \- Qiita](https://qiita.com/ptiringo/items/249fc23c02484a485646)
 ※要root権限のため、sudoで編集する。要再起動

他に、管理画面からユーザを選択して強制追加する方法もある。

# HTTPS通信を有効化する
[Gitlab CEでLet's Encryptの証明書を使ってHTTPS通信を有効にする \- Qiita](https://qiita.com/sunack/items/7b80bb7114cf6384346e)

#（参考）日本語化

[GitHub \- ksoichiro/i18n\-patch: Replacing codes for i18n with patterns\.](https://github.com/ksoichiro/i18n-patch)
Azureのマーケットプレースで公開されているgitlabのバージョンに一致する日本語パッチは公開されていないため、バージョンアップ等の対応してから日本語パッチを充てる必要がある。未検証。
（READMEでもNGの旨記載されていますが、別の近いバージョンのパッチを無理やりあてたところ、スタイルが壊れました）
UITableViewの上部にsearchBarを固定する方法

#はじめに
tableViewにsearchBarを追加し、スクロールすると普通はsearchBarが隠れてしまうと思います。
しかし、この設定だとユーザーがsearchBarを用い、新たに検索をしたいとなった時に、tableViewを上部までスクロールしないといけません。
これは結構不便ですよね？
今回はその改善策について書いていこうと思います。

#よくある実装
よくある実装では、searchBarが隠れてしまっています。

![よくある実装2.gif](https://qiita-image-store.s3.amazonaws.com/0/204266/9ab07de4-268e-6939-af5d-339e8b7b0959.gif)


#改善した実装
改善した実装では、searchBarが隠れることなく常に表示されています。

![完成形動画2.gif](https://qiita-image-store.s3.amazonaws.com/0/204266/8d69caa8-a9cf-df5c-3018-02098dc9cfcf.gif)

#開発環境
- Xcode9
- Swift4
- iOS 10.0

#実装方法
実装方法について触れていきたいと思います。
よくある実装は、tableViewのheaderViewにsearchBarを追加することによって実現しています。
逆に改善した実装は、tableViewのsectionViewにsearchBarを追加することによって実現しています。

tableViewのsectionには、tableViewの上部に固定されるという仕組みがあります。
その仕組みを用いて、実装していきます。
※tableViewのstyleがplainの時に限り、tableViewの上部に固定されます。groupedの場合は固定されません。

```swift:TableViewController.swift
import UIKit

class TableViewController: UITableViewController {
    
    let array:[String] = ["東京スカイツリー","東京タワー","東京駅","歌舞伎座","築地市場","皇居","雷門","国会議事堂","両国国技館","レインボーブリッジ","お台場海浜公園","フジテレビ本社ビル","東京ドームシティ","大江戸温泉物語","浅草花屋敷","すみだ水族館","上野動物園","アクアパーク品川","渋谷109"]

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    //section使う時に必須のメソッド
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return ""
    }

    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let searchBar = UISearchBar()
        searchBar.placeholder = "観光地を入力してください"
//        search.delegate = self //これを書かないとsearchButtonClickedとかのdelegate動かない
        return searchBar
    }

    //searchBarの幅に合わせる為に必要な処理
    override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 44
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return array.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = array[indexPath.row]
        return cell
    }
}
```

このようにして実装することができます！

#最後に
自分はこの実装が施されたアプリを見て、どのような仕組みで実装しているのか分からず、結構悩んでいたので、自分と似た人の役に立てればなと思います！
vim-Tips集

# 目次

1. 編集中のファイルの名前を確認する
2. 文字列を置換する

(随時追加予定)

# 1.編集中のファイルの名前を確認する
編集中のファイルの名前を確認するには、`<Ctrl>+g`を押します。
それだけです。

# 2.文字列を置換する
コマンドモードで`:%s/<置換対象文字列>/<置換後文字列>`  
ファイル中の全ての対象文字列を置換するには、コマンドの最後に`/g`をつけます。
`:%s/<置換対象文字列>/<置換後文字列>/g`
ちょっとずつ読むドメイン駆動設計 第四部 戦略的設計 第十四章 モデルの整合性を維持する5 共有カーネル

# これまでの十四章
- [第四部 戦略的設計 第一四章 モデルの整合性を維持する](https://qiita.com/YasuhiroKimesawa/items/6e8e5503a05ce9515a79)
- [境界づけられたコンテキスト](https://qiita.com/YasuhiroKimesawa/items/901ac764340275b93d61)
- [継続的な統合](https://qiita.com/YasuhiroKimesawa/items/6a58743c90c5b707c29d)
- [コンテキストマップ](https://qiita.com/YasuhiroKimesawa/items/626384c84145870ec5af)

今日から数回に分けてコンテキスト同士を接続するパターンを読んでいきます。

# 共有カーネル
複数のコンテキスト間で、**共有のモデルを持つパターン**。モデルだけでなく、**コード、関連するデータベース設計も含まれる**。

Evansによると、**まとまりのないチーム**が変換層と修復作業に時間がかかる場合、共有カーネルを使うことでうまくいく**ことがある**と説明されています。
なんとなくネガティブなパターンのようにも見えますね。

## 共有カーネルの注意点
複数のコンテキストで共有する分、その維持には結構な労力がかかりそうです。

- 変更するには、両方のチームの合意が必要
- 稼働しているシステムは頻繁に統合する
- 両チームのテストが通ること

Evansも言っていますが、このパターンはコンテキスト内の他のモデルに比べて、変更が自由にできないことがわかります。

共有するのは、コアドメインのこともあるし、汎用サブドメインの場合もあるとのことですが、コアドメインを共有するのはちょっと辛みがありそう。

# 名前がついているのがとても大事

このようなパターンをこれからいくつか見ていくのですが、共有カーネルのようにちょっとネガティブなパターンも含まれています。
ただ、こういった接続をしているアプリケーションってありますよね。

DDDを採用している、していないに関わらず、システム間同士のやりとりというのは普通に行われていますし、そのやりとりの仕方というのは自然とこれらのパターン（パターン名を知っている、知らないに関わらず)を選択していると思います。
なかには理由が曖昧なまま接続していることもあるでしょう。

ここで、パターンを知り、パターン名を設計で使うことで、より明確な理由付けと明確な設計ができるようになるかと思います。
「このサブシステムとの連携は共有カーネルでは保守が大変そうですね。腐敗防止層で対応しましょう。」とか「APIをこちらから提供するので、顧客/供給者の関係でお願いします。」とか。

特にこれらのパターンは複数のチーム間で適用されるものなので、元々設計に慎重さが求めれるところだと思います。
パターンを明示的に適用することで、チーム間でのコミュニケーションがやりやすくなり、結論も出しやすくなるのではと思っています。
Firebase FunctionsのConfigへJSON形式のファイルからsetする

# 概要
Firebase Cloud FunctionsのConfigへJSON形式のファイルからsetする方法の共有です。

# コマンド
```shell:terminal
firebase functions:config:set service_account="$(cat service-account.json)"
```

# 背景
Firebase Cloud Functionsで、Firebase Admin SDKに用意されているAPI（ユーザー管理 APIなど）を使用する際には、サービス アカウントが必要です。

しかし、サービスアカウントを作成・ダウンロードしたjsonファイルを元に変数を設定したかったのですが、「firebase functions:config:set」を使って、key=valueで1つずつ設定するのは果てしなく面倒くさい！と思って調べてみたところ、ちゃんとGitHubのissueに同じ悩みの人がいました。
https://github.com/firebase/firebase-tools/issues/406

# 参考
Firebase Cloud Functionsの環境変数設定に関する公式ドキュメント
https://firebase.google.com/docs/functions/config-env
RailsのテストをRspecで書くときの小便利な手法


この記事は、[「ソフトウェアテストの小ネタ Advent Calendar 2017」](https://qiita.com/advent-calendar/2017/software-testing-koneta
)の20日目の記事です。

Rubyの標準クラスには想像以上に便利なメソッドがあります。常識でしょ! というみなさまもいらっしゃると思いますが、Rails開発者は意外と Rubyを知らないものなので。そして、無いと思ってるものは探せないので。それっぽい穴場なメソッドをリストアップしてみました。

知っているとテスト目的が明確になったり、テストコードが見通しよくなる、かもしれないです。


# Integer#times

N回繰り返す、ってテストでは良くやりますね。

```
3.times do |i|
	# 繰り返したい操作
end

```

注意点としては、times は手動テストケースだったら「〜を N回行う」と書くようなケースにだけ使うことです。
モデルインスタンスのリストを作成したいときは、FactoryGirl の create_list や build_list を使いましょう。
配列に何かしたいときは、後述のやり方のどれかの方がきっと読みやすいです。


# Array#each_with_index

「Rubyには ++演算子はないの?」って聞かれた時は、このメソッドでだいたい納得して頂けると思います。

```
hoges.each_with_index do |hoge, i|
	# i=0 から hoges.size-1 まで
end
```

# Array#each(&:method)


配列の各要素に対して、methodを呼んでくれます。


```
items.each(&:method)
```

↑と↓が同じ意味です。

```
items.each do |item|
  item.method
end
```

以下は、テストデータの準備でletやbeforeの中で多用するパターンです。

```
# itemsは、ActiveRecordの配列
# itemsの中をテスト目的に合わせて操作した後
items.each(&:save)

```


# Array#map

配列から配列が出て来る便利メソッド。
良く使うのは、日付がからむパターンです。

```
# Hogeモデルは dateフィールドを持っている
# FactoryGirlで、Hogeモデルを定義済
# dateフィールドに、start_date 〜 end_date を1日づつ入れたデータを用意したい場合
(start_date .. end_date).to_a.map{|d| build(:hoge, date: d)}
```



# Array#zip

2つ以上の配列を並べて順番に処理したいときに使います。
データドリブン的なテストを書きたいときに重宝します。

```
hoges.zip(moges, koges).each do |hoge, moge, koge|
 	# hoges[n], moges[n], koges[n] の処理
end
```


「はやく知っておけばラクだった！」と思ったことのある機能を挙げてみました。
個人的には、実行コードにも増して、テストコードの可読性は重要と考えておりますので、この記事がその一助になれば幸いです。
ブロックチェーンの専門家100人に入るPaolo tasca氏が 「LinkerCoinICO」の諮問委員に


![KakaoTalk_20171220_105843403.png](https://qiita-image-store.s3.amazonaws.com/0/225167/f8dea6c7-1b0e-313a-7091-c52a63af964e.png)


ブロックチェーンの専門家100人に入るPaolo tasca氏が 「LinkerCoinICO」の諮問委員に



ブロックチェーンの技術専門家、パオロタスカ（Paolo Tasca）博士（UCL：University College London経済学教授）が、全世界仮想貨幣を繋げる（Network of Netowkrs）LinkerCoinのICOを国際的に飛躍させるために、諮問委員として活動を宣言した。


> http://bitlife.cryptopie.com/paolo-tasca-as-an-adviser/
> https://www.linkercoin.com/jp
ActiveRecordのscopeをインスタンスに対しても使いたい


# 渋谷.rb[:20171220]の相談LTネタです。
https://shibuyarb.doorkeeper.jp/events/68506

---

# kaiba
- twitter @ kaiba
- 日本酒に執着がある
- うっかり飲み会を入れてしまったのでLTだけしたら出ます…

---

# こんな商品モデル、こんなscopeがあったとする

```ruby
class Item < ActiveRecord::Base
  scope :buyable, (-> {
    where(safety: true)
    .where(ero: false)
    .where(grotesque: false)
    .where(has_copyright: true)
    .where(deleted_at: nil)
  })
end
```

---

# 商品は表示だけはしたい
![image.png](https://qiita-image-store.s3.amazonaws.com/0/21799/2281dfbd-858d-125f-31d1-ca64d7f60b92.png)

---

# こうしたいけど怒られる
```ruby
class ItemsController < ApplicationController
  def show
    @item = Item.find_by(id: p[:id])
    if @item.buyable?
      # ...
```

---

# つらい
```ruby
class Item < ActiveRecord::Base
  def buyable?
    safety && !ero && !grotesque? && 
      has_copyright? && deleted_at.blank? 
  end
end
```

---

# そうじゃないしSQL発行されるのやだ
```ruby
class Item < ActiveRecord::Base
  def buyable?
    Item.buyable.where(id: id).present?    
  end
end
```

---

# ここにみなさまから貰ったアドバイスを書く
- `Item.buyable.where(id: id).present?` で自分を探しちゃうのもありだが、N+1問題やキャッシュを考えて使うべき
- railsには抽象化された条件がないので条件をがんばって抽象化する?
- `Item.buyable.values`を見ると WhereClauses でwhere条件が得れれるのでそこをみて頑張ってやることもできる(黒魔術)
windowsでnuxt.js+element uiを動かす

## git bash でnuxtjs+element uiを動かす
前の投稿でbash on windowsを使用したのですが
別に普通にwindowsで動きましたのでそのメモを記載します。

## インストールするもの
・node
・git for windows

## git bash のhomeディレクトリを変更
[こちらを参照してください](https://qiita.com/nyoro_712/items/08596c7ae522f85cca28)

## nuxtを導入
### git bash でディレクトリを作成

   `$ mkdir nuxt`
   `$ cd nuxt`

### package.jsonをnuxtディレクトリに作成

 ```json
{
  "name": "nuxt",
  "version": "1.0.0",
  "description": "Nuxt.js project",
  "author": "hiro",
  "private": true,
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "precommit": "npm run lint"
  },
  "dependencies": {
    "nuxt": "^1.0.0-rc11",
    "vue": "^2.5.3",
    "vue-server-renderer": "^2.5.3",
    "vue-template-compiler": "^2.5.3",
    "element-ui": "^2.0.8"
  },
  "devDependencies": {
    "babel-eslint": "^7.2.3",
    "eslint": "^4.3.0",
    "eslint-config-standard": "^10.2.1",
    "eslint-loader": "^1.9.0",
    "eslint-plugin-html": "^3.1.1",
    "eslint-plugin-import": "^2.7.0",
    "eslint-plugin-node": "^5.1.1",
    "eslint-plugin-promise": "^3.5.0",
    "eslint-plugin-standard": "^3.0.1"
  }
}
```
### npmのインストール

`$ npm i`

### nuxtを実行
`$ npm run dev`

### http://localhost:3000にブラウザでアクセス

以上
AWS EC2 タグを指定してAnsibleを実行する

# はじめに
Ansibleでサーバーに命令を実行する場合、インベントリーファイルに実行先サーバーのIPアドレスを定義する。一方でAWSのEC2はデフォルトでは再起動するたびにIPアドレスが変わってしまう。Elastic IPを使うとIPアドレスを固定することも可能であるが、費用もかかる。こんなときに便利なのがIPアドレスの代わりにAWS のEC2のタグを指定してAnsibleを実行する方法である。以下にその方法を紹介する。

# 前提
■ Ansibleサーバーが構築済、かつ対象サーバーとAnsible実行ユーザーでssh実行可能であること
　> 下の「手順」では例として、Ansible実行ユーザー名はansibleとする。

■ AWSコンソールでAnsible実行先サーバー（EC2）にタグが付与されていること
　> 下の「手順」では例として、付与されたタグはrole（キー）=webserver（値）とする。

■ AWSコンソールでIAM ユーザーのアクセスキーを作成済であること
　> 下の「手順」では例として、アクセスキーIDをxxxxxxxx、シークレットアクセスキーをyyyyyyyyとする。

# 手順
**以下の手順は全てAnsibleサーバーにて実行する。**
### ➀ アクセスキー情報を設定する

　`# vi /home/ansible/.aws/credentials`

※credentialsファイルはAnsible実行用sshユーザーのホームディレクトリーの下に置く。上の例ではansibleユーザーとしている。ユーザー名は適宜、読み替えること。

　credentialsファイル内に以下の3行を記載する。
　-----ここから-----
　[default]
　aws_access_key_id = xxxxxxxx
　aws_secret_access_key = yyyyyyyy
　-----ここまで-----

※xxxxxxxx/yyyyyyyyには実際の値を指定する。

### ② botoのインストール

botoはAWSを操作するためのPython SDKである。botoをインストールするためにはまずpythonのパッケージ管理ツールであるpipをyumでインストールし、pipでbotoをインストールする。

　`# yum install python-pip`
　`# pip install boto`

### ③ ec2.py/ec2.iniをgithubからダウンロードして編集する

ec2.pyはAWS EC2のインベントリー情報（タグ含む）を取得するスクリプトである。ec2.iniはec2.pyの設定ファイルである。

■ ダウンロード元
　> https://github.com/ansible/ansible/tree/devel/contrib/inventory

■ 配置先
　> ec2.py/ec2.iniともにインベントリーファイルの配置先と同じフォルダに配置する。
　> ec2.pyは配置後、chmodで実行権限を付与する。

■ ec2.iniの修正箇所
　ec2.iniは以下の箇所を修正する。（ec2.pyは修正不要）
　> region = ap-northeast-1a（修正）
　> instance_filters = tag:role=webserver（追加）
　> rds = false（コメントアウト解除）
　> elasticache = false（コメントアウト解除）
　> destination_variable = private_dns_name（修正）
　> vpc_destination_variable = private_ip_address（追加）
　> cache_max_age = 0（追加）

### ④ playbookのhostsの指定の修正

playbook内のhostsを指定している箇所にタグを使用するように修正する。

- 修正例

    `hosts: tag_role_webserver`

※role（キー）およびwebserver（値）は適宜、読み替えること

### ⑤ playbookの実行確認

以下のplaybookコマンドを実行し、タグ指定したEC2がリストアップされることを確認する。

　`# ansible-playbook -i <inventoryファイル> <playbookファイル> --list-hosts`

以上