OmniAICreator/Qiita-1.07M huggingface dataset:
ServerlessでDynamoDBの更新イベントをトリガーとしてLambdaを実行する

##はじめに
個人的に開発しているアプリ(WrestleGO)を開発する際に使おうとして結局ボツったのですが、DynamoDBの変更イベントをトリガーにしてLambdaを実行させるということをやったので紹介します。Serverless Frameworkを使用して開発しました。

##動作時のバージョン
| name         |  version  |
|:------------:|:---------:|
| ServerlessFW |  1.3.0    |
| node         |  4.6.0    |
| npm          |  2.15.9   |

##事前準備
DynamoDBのテーブルでstreamを有効にしておく必要があるので設定します。
まずは、管理コンソールのDynamoDBから対象のテーブルを選択すると概要タブに"ストリームの管理"ボタンがあるのでこれを押下します。
![SnapCrab_NoName_2016-12-14_10-21-40_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/152513/687d9244-b170-7a8f-98d9-3c8d432f37d8.png)

すると以下のダイアログが表示されます。
テーブル変更イベントが来た際に得られる情報を選択します。処理に必要な情報を選択して有効化を押下します。
![SnapCrab_NoName_2016-12-14_10-21-50_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/152513/494471c7-1aea-5f54-498f-940c5c9076b0.png)

するとストリームが有効になります。ここで表示されるARNは後ほど使用します。
![SnapCrab_NoName_2016-12-14_10-38-20_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/152513/861af367-f32e-2145-06e9-c48666ac02e5.png)



##設定ファイル
次にServerless側の準備です。`serveless.yml`の編集を行います。`functions`にトリガー対象となるDynamoDBテーブルを定義します。
`arn`には事前準備で有効にしたストリームのARNを指定します。`batchSize`というのはこのLambda関数一回のコールでどれだけ処理するかの数です。1件ずつなら1を設定します。最大は10000です。複数のレコードをいっぺんに処理するならLambda関数の中でループ処理が必要になります。`startingPosition`というのは読み取りを開始する位置です。最新のものから順番に読み取る(`LATEST`)か、読み取りされていないものを古い順から読み取る(`TRIM_HORIZON`)かの2種類があります。時間順にデータを処理するなら`TRIM_HORIZON`、最新のデータを使用する設計なら`LATEST`を設定します。`enabled`はLambda関数に設定したこのトリガを有効(`true`)にするか無効(`false`)にするかです。

```serverless.yml
functions:
  dynamotrigger:
    handler: handler.dynamotrigger
    events:
      - stream:
          arn: arn:arn:aws:dynamodb:us-east-1:XXXXXXXXXXXX:table/event_sample_table1/stream/2016-12-14T01:37:13.667
          batchSize: 100
          startingPosition: TRIM_HORIZON
          enabled: true
      - stream:
          arn: arn:aws:dynamodb:us-east-1: XXXXXXXXXXXX:table/event_sample_table2/stream/2016-12-14T01:37:13.667
          batchSize: 100
          startingPosition: TRIM_HORIZON
          enabled: true
```

##Lambda関数での処理
イベントトリガかどうかを判定してパラメータのトリガ元のARNから対象のDynamoDBのテーブルを割り出します。

```js:handler.js
module.exports.dynamotrigger = (event, context, callback) => {
  if('Records' in event && event.Records.length != 0) {
    // イベントトリガの場合
    var source = event.Records[0].eventSourceARN;
    // どのテーブルからのイベントか？arnの文字列からテーブル名を検索して判定
    if(source.indexOf('/event_sample_table1/') != -1) {
      // event_sample_table1テーブルからのトリガを受けて行う処理
    }
    else if(source.indexOf('/event_sample_table2/') != -1) {
      // event_sample_table2テーブルからのトリガを受けて行う処理
    }
    else {
      // 未知のイベント発火時処理
    }
  }
  else {
      // DynamoDBイベントトリガー以外の場合の処理（APIでも実行させたいとかあれば）
  }
};
```

##まとめ
いかがでしたでしょうか？簡単すぎてびびってたじろぎますね。実際WrestleGOを開発するにあたり開発着手に踏み切ったのもServerless Frameworkを触ってその簡単さに驚愕し、「これならできる！」と思わせてくれたからです。現在もかなりのスピードでバージョンアップされているので今後もさらに期待が持てます。
※WrestleGOはアプリをXamarin.Formsで、APIをServerlessFrameworkを用いてAWSのAPI Gateway + Lambda + DynamoDBという構成で作られています。
[C++] Rebinding a reference is not allowed

As described in the title, c++ doesn't allow to rebind a reference. See some sample code.

```cpp
int a = 1;
int b = 2;

int &ref = a;
ref = 5;
cout << a << " " << b << endl; // 5 2

ref = b;
ref = 6; 

cout << a << " " << b << endl; // 6 2
```

We try to rebind the ref to variable `b` and update the value of `b` through reference. But it doesn't work.

[Here](http://stackoverflow.com/a/728298) is a explanation about this and very easy to understand.

#### Update

Thanks @l1048576 's comment. In C++11 there is a class [`std::reference_wrapper`](http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper) that wraps a reference in a copyable, assignable object.

```cpp
int a = 1;
int b = 2;
std::reference_wrapper<int> ref = a;
ref.get() = 3;
cout << a << " " << b << endl; // 3 2

ref = b;
ref.get() = 5;
cout << a << " " << b << endl; // 3 5
```
AdminerのSQLコマンドで日本語を入力するブックマークレットを作った

# ブックマークレット 
```
javascript:(function(){var a=document.querySelector('pre.sqlarea.jush-sql.jush')||{style:{}};a.style.display='none';var a=document.querySelector('textarea.sqlarea.jush-sql')||{style:{}};a.style.display='';})();
```
# コメント
SQLコマンドで日本語が入力できないので、ひとつの解決策として作りました。ただ、シンタックスは消えてしまいます。

# adminer
https://www.adminer.org/
RTSP対応のカメラをインターネットストリーム配信に利用する。

[動画配信技術Advent Calendar](http://qiita.com/advent-calendar/2016/video_streaming)の14日目です。

といってもこのアドベントカレンダーめちゃくちゃ過疎っていて僕が最初の投稿になります。
観ている人どこまでいるんだろう・・・・

-------------------------------------
2018/07/03追記
なんだか地味にみなさんに閲覧いただけてるようで、じわじわと閲覧数もいいねも増えています。
ニッチなモノではありますが、需要は0ではないんですね。

最後に新たに一部追記を書かせていただきました。
-------------------------------------

定点カメラを様々な用途で利用している企業も多いと思います。
例えばですが、防災用途だったりテレビのお天気のバックに流す映像用途だったり・・・・

その定点カメラの映像をインターネット上でも公開できないか？という相談がいくつか来ます。
基本的にはHDMIやRCA端子(赤白黄のケーブル)に変換をかけてもらって、エンコーダを用意していただくというのが通常回答になりますが、
予算などさまざまな要因があり上記の事ができないといった事もあると思います。

今回はRTSPをRTMPに変換してストリーム配信をしてみましょうという事で書きます。

#必要なモノ（物理）
RTSPサーバ機能を有しているカメラ
配信サーバ
変換サーバ（LANが2つ以上orVLANが利用できる環境を推奨）
※スペック的に問題がなければ変換サーバと配信サーバは同一のものでも構いません

#必要なモノ（ソフト）
OS:LinuxOS
RTMP/HLS配信：nginx（配信サーバにインストール）
RTSP→RTMP変換:ffmpeg（変換サーバにインストール）

#概要図
![qiita_rtsp01.png](https://qiita-image-store.s3.amazonaws.com/0/28655/49f6da10-3d34-c864-f8e0-3848aa6f3c8d.png)

#配信サーバ
nginxでのRTMP/HLS配信は昨年のnginxアドベントカレンダーで掲載した
[nginxでストリーミングサーバを立ててライブ配信する。](http://qiita.com/hagane5563/items/842afe6d6e7100db3a28)
を参照に構築ください。
Adobe Media ServerやWowzaを利用しても問題ありません。

#変換サーバ
ffmpegのインストールはソースから入れるのは結構事前準備（依存ライブラリが多い）が大変ですが根気よく。
（参考）CentOS6でインストールしたもの
Yasm>libx264>libfdk-aac>mp3lame>libvopus>libogg>liborbis>libvpx>libfaac>ffmpeg>MP4Box

準備が完了したら以下のコマンドを
> ffmpeg -i rtsp://ユーザ名:パスワード@カメラのIP/カメラ設定名.amp -c h264 -an -r フレームレート -s 映像サイズ -b:v 映像ビットレート -f flv rtmp://配信サーバIP/プロジェクト名/ストリームキー

例) ffmpeg -i rtsp://hoge:fuga@192.168.0.1/camera.amp -c h264 -an -r 15 -s 720x406 -b:v 512k -f flv rtmp://10.0.0.1/live/camera1

| パラメータ | 設定項目 |例の設定内容|
|:-:|:-:|:-:|
| -c  | 映像コーデックの指定  | H.264でエンコード |
| -an  | 音声コーデック | なしに設定 | 
| -r  | フレームレートの指定  | 15fpsに設定 |
| -s  | 映像サイズ  | 720x406に設定 |
| -b:v  | 映像ビットレート  | 512Kbpsに設定 |
|  -f |  アウトプット | flv(rtmp)に設定 |

定点カメラなどはフルHD（1080p）などで配信設定されている場合もあるので配信用にサイズは調整するのが望ましいです。
フレームレートはお好みですが、定点カメラなどであればそんなに高いフレームレートも必要にならないと思います。
エンコードを開始したら各端末で確認をしてみましょう！

#今後書いていきたい事
今回、カメラのサーバが何らかの原因で停止した場合、ffmpegが停止してしまうためサーバが復旧してもエンコードの自動復旧ができません。
rtmpdumpを利用してその状況を監視し、もし異常であればffmpegを立ち上げ直す等の回避策を現在考えています。
判明したらここでご紹介できればと思っています。

#ということで↑について書いてみた（2018/07/03追記）
結論として、RTMP配信サーバから常に取りに行くような形にしてみました。
配信側のnginx.confの1935ポートの部分を下記のような形で書きます。

```nginx:nginx.conf
rtmp {
  server {
    listen 1935;
    application live1 {
        exec /usr/local/bin/ffmpeg -i rtsp://hoge:fuga@192.168.0.1/camera.amp -c h264 -an -r 15 -s 720x406 -b:v 512k -f flv rtmp://10.0.0.1/live/camera1 2>>/tmp/log;
        live on;
        wait_video on;
    }
  }
}

```
execとしてffmpegのコマンドを書いてやることで対応しました。
今の所動作しています。止まってもまた再開すれば始まります。
max・minを使ってif文を短くできる時があるね

なんかpythonのコード書いてて気付いたのでメモ。初歩的かつ常識的なテクニックかもしれませんが…

aという変数を、ある計算式の結果(some_condition + add_value)がCONSTANTより大きくなるのかならないのかで分岐させたい場合を考えます。

とりあえずif文で適当に書いてみる。

```python:
a = 0
if some_condition + add_value < CONSTANT:
    a = some_condition + add_value
else:
    a = CONSTANT
```

…さすがに冗長すぎる気がするので、初期化(変数宣言)のところにelseの動作をいれてみる。

```python:
a = CONSTANT
if  some_condition + add_value < CONSTANT:
    a = some_condition + add_value
```

これをやってみた後、やってることは some_condition + add_value と CONSTANTの比較だけなので、minを使って1行で済むことに気づきました。

```python:
a = min(some_condition + add_value, CONSTANT)
```

pythonには三項演算子がなくて条件分岐の時にコードが長くなりがちですが、min・maxを使えば多少コードがきれいにかけるのかも。
ToDoの進行状況メモ


エンジンとしては、Todo.lyを使うことにした。理由は、APIがあること、削除、更新、新規登録をAPI経由で行えること。締め切り日を設定しなくてよいこと。ジャンル分けできること。
ローカルのみで保持するかどうかを検討している。異なる可能性が出てくるため。ローカルのみで保持すれば、通信がたやすい。ということは、通信状態によって挙動を変えればよい。WiFiか電話か。
ジャンルをページに割り振ることを検討している。そのためジャンルの変更をUIに割り当てる必要がある。まずはこれか。
Todo.lyに一括登録して、コンテンツを準備する必要がある。それも並行して実現する必要がある。
WindowsのVSCodeでRubyを書きたい。そしてインテリセンスも欲しい。

[Visual Studio Code Advent Calendar 2016](http://qiita.com/advent-calendar/2016/vscode) に未投稿枠があったのでねじ込みました。ちきさんです。

Windows 7 Pro 32bitでRuby環境を構築したのでメモを残します。

要件

- WindowsでRubyを書きたい。
- VSCodeで書きたい。
- Lintも欲しい。
- IntelliSense(AutoComplete)も欲しい。

[Visual Studio Code で Ruby を何とかして書けるようにする](http://d.hatena.ne.jp/deko2369/20160611/1465653006) がとても参考になりました。

## ダウンロード

[RubyInstaller for Windows](https://rubyinstaller.org/downloads/) で下記をダウンロード。

- Ruby (rubyinstaller-2.2.6.exe)
- Development Kit (DevKit-mingw64-32-4.7.2-20130224-1151-sfx.exe)

いずれも32bit用。

(追記)
Windows 10 Pro 64bitでも試しましたが、64bit用RubyとDevelopment Kitではインテリセンスが動きませんでした。なので64bit Windowsであっても**32bit用のRubyとDevelopment Kit**をインストールすることをお勧めします。

## インストール

Rubyをインストール。

`C:\Ruby22` にインストールされるので、 `C:\Ruby22\bin` にPATHを通す。
そして再起動。

---

コマンドプロンプトを開いて `ruby` にPATHが通っていることを確認する。

- `$ ruby --version`
- OUTPUT: `ruby 2.2.6p396 (2016-11-15 revision 56800) [i386-mingw32]`

## gemとか

Development Kitを解凍し、 `C:\RubyTools` フォルダを作って全ファイルを配置する。

コマンドプロンプトを開いて 

- `$ cd C:\RubyTools`
- `$ ruby dk.rb init`
- `C:\RubyTools\config.yml` に `- C:/Ruby22` の記述があることを確認する。
- `$ ruby dk.rb install`
- `$ gem install ruby-debug-ide debase` ← VSCodeのRubyエクステンションに必要
- `$ gem install reek rubocop fasterer debride ruby-lint` ← Lintに必要。全て必要かどうかはわからない。
- `$ gem install rcodetools` ← AutoCompleteに必要
- `$ gem install fastri` ← rcodetoolsインストール時に追加インストールを推奨される

## VSCode

VSCodeにRubyエクステンションをインストール。

ユーザー設定で下記を追加。

```txt:settings.json
  "ruby.lint": {
    "reek": true,
    "rubocop": true,
    "ruby": false, //Runs ruby -wc
    "fasterer": true,
    "debride": true,
    "ruby-lint": true
  }
```

全て必要かどうかはわからないけど、`"ruby": false`は`true`にしない方が良い。なぜなら文字列に全角文字を使っただけでエラーにされるから。

ここで念のため再起動。

## 動作確認

適当なrubyファイル(*.rb)を作り `[1,2,3].e` と入力したときに入力候補が表示されればOK。

![ruby_intellisense.png](https://qiita-image-store.s3.amazonaws.com/0/74793/baed9d30-e16b-dff6-0a57-652762c8e114.png)
コンソールで動くエディタを作る(14日目) カーソル位置の編集その4(文字の削除)

本稿は[自作エディタをつくる Advent Calendar 2016](http://qiita.com/advent-calendar/2016/make_editor)の14日目です、レポジトリは[こちら](https://github.com/tinyco/tiny_code_editor)

# 文字を削除する

文字挿入と同じような手順で、内部DSLであるenum CommandTypeにDELETEを追加し、Backspaceキー(0x7F、13日目より)を割り振ります。

文字挿入のときは末尾文字を次のリストに動かしたりしていましたが、削除は簡単ですね。

削除すると、1文字左に動かします。

カーソルが行頭にあるときは、改行文字を削除することで前後の行が繋がるため、特殊な対応が必要そうです。
ただ、追加時も改行を考慮できていないことに気づきました。うーむ・・・(後述)


# 末尾カーソル問題

削除を実装していて気づいたのですが、
行にn文字あるとき、カーソル位置はn+1箇所あるんですね。

「｜」が配置可能なカーソル位置、行にabcの3文字あるとすると
普通のエディタは｜a｜b｜c｜の4箇所に配置できます。うーむ・・・(持ち越し)

# 行を結合する

行の先頭で削除キーを押したら、行結合処理を開始するようにします。

結合した後に、1文字削除(改行文字の分)して、カーソル位置を元の行末尾位置へ動かします。

最後に、行の文字数等を再計算します。

作ってて気づいたのですが、ファイル先頭・行頭でバックスペースを押すと大抵のエディタで無視されます。

# 改行する

Enter(0x0D)で改行するようにします。0x0Dをそのまま文字として追加しても改行されないようなので、"\n"に置き換えます。

行の後ろにある文字を順に次の行に足していく処理になります。

改行を加える構造体の文字をハードコピーしたあとに、リストを付け替えて処理します。

余談ですが、ファイル名を表示している部分(headerと呼ぶ)の末尾に改行をつけ忘れていて、文字幅が画面ちょうどなので気づいていませんでした。

その結果、一行目が空行だとheader末尾の改行っぽい扱いになって、表示できないバグになってしまい、わりとハマりました。

# 空白文字を打つ

spaceキーを打つと0x20が入力されるのですが、そのまま出力しても空白にならないため`" "`に置き換えました。

# 空行カーソル問題

現状の実装だと、カーソルは背景色を用いて表示しているのですが、空行だと文字がないため背景色がつかない？問題を見つけました。

先に述べた末尾カーソル問題や、12日目の保持しているカーソルの位置どうするか問題と合わせて、現状実装のカーソルの保持方法には問題がありそうです。

# 今日のまとめ

- 文字を削除できるようになりました
- 改行を追加・削除できるようになりました

遅れがちだった更新ですが、頑張って追いつきました。
粗だらけですが、ファイル保存できればだいぶエディタっぽいのではないでしょうか？

![b21ad12e438f194447b239cfa5f3ee09.gif](https://qiita-image-store.s3.amazonaws.com/0/151926/5d133c2e-2fc9-e614-e597-26f8d520de03.gif)
安定なオフィス無線LAN運用のススメ

株式会社LITALICOでインフラエンジニアをやっています。@5kakrです。
LITALICO Advent Calendar 2016も折り返しを過ぎ、14日目の記事となります。

昨日の@klrutsaさんのご案内とは内容を変えまして、
今回は社内ITインフラの中でも無線LANをどう安定的に使っていくかを書いていきたいと思います。

# そもそも無線LANは安定しない？
一昔前は「無線LANは有線LANに比べて、遅いしすぐ切れる」というイメージをみんな持ってました。
オフィスのネットワークに導入しようものなら、「止めてくれ！」という声も上がったりしました。

その原因としては、以下の様な特徴があります。

+ 1つのアクセスポイントで処理できるPC台数が少ない
+ 無線のパケットロスが発生すると、再送のため時間がかかる
+ アクセスポイントを増やそうにも、使用できる電波のチャンネルが少なく、干渉が起きてしまう

今では技術革新が進んで、これら問題はかなり改善されています。
コラボレーションを重視する今の働き方では、フリーデスク環境のため必須となっていて、無線のオフィス環境なんて当たり前になりました。
### では、今は手放しで利用できるか
技術が向上しても、特に気にせず導入すると、やはり安定しない。「自分だけは有線LANを用意して」なんて声も上がってきたりしちゃいます。
# 安定的に使っていくために
オフィス環境では人数と利用場所に合わせて複数台アクセスポイントを設置する必要があります。

高密度のオフィス環境で安定的に使うためのポイントを以下にまとめました。
## 電波チャンネルの見直し
無線LANにはやり取りを行う電波の周波数帯（チャンネル）を分けることが必要で、同じチャンネルに設定していると干渉が発生し、通信に影響が出てしまいます。

| 周波数 | 到着範囲 |チャンネル数| 電波干渉 |
|-----------|------------|------------|------------|
| 2.4GHz       |        広い |14ch|  密集するため干渉が大きい     |
| 5GHz     |      狭い |19ch|    外来電波の影響で落ちることがある    |


最近の無線機器はお互いの無線アクセスポイントが連携して、自動的に利用チャンネルを選択する機能がありますが、これを利用すると意図せず重なってしまうことがあるため、明確なチャネル設計が必要になっている現状です。

###2.4GHz帯は近隣の利用帯域から外す
2.4GHz帯は、到着範囲が広いため、上下左右の建物の電波も届いてしまいます。
[InSSIDer](http://www.metageek.com/products/inssider/)などのソフトウェアを利用し、他の電波の強さを測る必要があります。

###5GHz帯は各種レーダーの影響から外す
5GHz帯は選べるチャネルも多いため、2.4GHz帯と比べ、同一エリアに設置できるアクセスポイント数が多くできます。さらに、最新製品では1.7Gbpsというスピードを出せるという魅力的なチャンネルです。

しかしながら、5GHzを使うにおいて見過ごせない特徴（弊害）があります。

それは、チャンネル数を広げたため、気象レーダーや空港レーダーが利用する周波数帯と重なってしまい、
<b>レーダーを感知したら30秒間通信を止める</b>という機能が義務化されているためです。

この30秒間はユーザーにとってはネットワークダウンとなり、とても大きな影響となります。
そのため、5GHzを使う場合は、速度よりも影響を受けないチャンネルを選ぶことが大切です。

※以下図の青色部分が現在無線LANで利用できる周波数帯で、5.2GHz以外はレーダーの影響が受けてしまいます。
参考：[総務省 「5GHz帯無線LANの周波数帯拡張等に係る技術的条件」の検討開始について](http://www.soumu.go.jp/main_content/000394201.pdf)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/120589/f309321f-0100-ef7c-8509-198640701893.png)

## 通信速度の管理
アクセスポイントは1台に対して複数デバイスが接続する（多い時は50人とか）機械です。ユーザーの一人が大量通信をしてしまうと他のユーザーの通信が遅くなるという現象が発生します。

そのため、チャンネルのほかに通信量の管理が必要です。
### 利用データ量を監視し、制限をかける
例えば、以下の様な大量データのやり取りする通信は上限を設けることで通信の膨張を防ぎ、利用者全員に公平な環境を作ることができます。

* OSアップデート
* 動画閲覧
* 社外ゲスト用のネットワークを提供しているのであればそれも

#おわりに
知っている人にとっては当たり前の情報となってしまいましたが、無線LANの運用について改めて記載させていただきました。

マインド的なポイントとしては、<b>「スピードを求めるより、切れたり遅くなることなく一定に使えること」</b>が無線LANに対する信頼を上げていくものかと思います。

明日は@daisukehさんが「Arduinoを使ったサイクリングナビ」を書いてくれます！
お楽しみに！！
ディプロイAPIの深淵なる世界

# ディプロイAPIの深淵なる世界

この記事は[kintone Advent Calendar](http://qiita.com/advent-calendar/2016/kintone)の14日目として寄稿しています。

## gusuku知ってますよね？
kintoneでのシステム開発に欠かせない[gusuku](https://gusuku.io/)知ってますよね？
ご存じないという方は、[https://gusuku.io/](https://gusuku.io/)をご覧ください。

gusukuのことは知っていただいたとして・・・

## gusukuの中心機能であるアプリケーション配布機能
gusukuの重要な基本機能である「アプリケーション配布機能」ですが、これは、kintone上で作ったあるアプリの設計を、他のアプリに反映する機能です。

これを使うことで、開発用のアプリで行った変更を、本番用アプリに反映することができます。

![gusuku_deploy1.png](https://qiita-image-store.s3.amazonaws.com/0/65942/34122571-57ce-6e51-d200-d7d2a7057db5.png)

>「あぁ、ディプロイAPIで設計情報取ってきて、配布先に送ってるんだね」

そう思ったあなた！
正解ですが、それではまだ不足しているのです。
ディプロイAPIにそのまま渡すだけでは困るケースがあります。

### ルックアップや関連レコードがある場合

開発用アプリが発展してこうのようにルックアップを含む形になったとします。

![gusuku_deploy2.png](https://qiita-image-store.s3.amazonaws.com/0/65942/ccb661b8-c6fa-3d7a-670b-b6bc844e5871.png)

そのままディプロイAPIで配布するとこうなります。

![gusuku_deploy3.png](https://qiita-image-store.s3.amazonaws.com/0/65942/0b62debf-2910-f5e5-e381-056bcbe075fb.png)

これじゃまずいですよね？

gusukuではこのような問題を解決するために、「アプリケーションバンドル」と呼ぶ仕組みを用意しています。
要は、環境間でのアプリの対応関係を管理するものです。

上のようなケースでは、本番用スペースに先に空のアプリBとアプリCを作成しておいて、gusukuにそのアプリを登録して開発用スペースのアプリB、アプリCとひもつけます。

その状態でgusukuで配布すると！

![gusuku_deploy4.png](https://qiita-image-store.s3.amazonaws.com/0/65942/508ec6b3-c9c4-9165-ad92-9b261aa1e5f5.png)

配布処理の中でちゃんとルックアップ先のアプリを本番用のものに切り替えて配布してくれます。

### フィールドコードはユニーク？

kintoneの各フィールドには、フィールドコードというものがあります。
フィールドコードは**「ユニーク」**なものとして定義されています。
ただ、ここでの**「ユニーク」**の定義に問題があります。
ここでの**「ユニーク」**は、あくまでも**「１つのアプリの一連のフォーム設計情報の中で」**という前提がつきます。
gusukuはアプリのバージョン管理ができます。バージョンをまたがってフィールドコードを見たとき、

**バージョン間ではフィールドコードはユニークではない**

のです。フィールドコードがいつでも変更できてしまうことからわかりますよね？
ある時点でのフィールドコード「name」を持つフィールドが次のバージョンでも同じフィールドである保証がありません。
（内部的にはidを持っているようなのでこれをAPIが返してくれるといいんですけど・・・）
以下のように「prefecture」というフィールドコードを持つ「都道府県」というフィールドがあったとします。

![20161214090555_rr4em.png](https://qiita-image-store.s3.amazonaws.com/0/65942/2a8f0a1e-ac80-8270-93ed-c2bd8d7052c5.png)


![20161214090659_nkdsc.png](https://qiita-image-store.s3.amazonaws.com/0/65942/c1e5c1a7-464e-04ec-5051-fa88e102238b.png)

「やっぱ都道府県はプルダウンで選びたい」ということで、これを「ドロップダウン」に変更することになりました。
アプリはこう変わります。

![20161214090917_ogaoj.png](https://qiita-image-store.s3.amazonaws.com/0/65942/9f0244b1-1ce4-334d-846f-d155a91a0b1c.png)

![20161214091001_mq498.png](https://qiita-image-store.s3.amazonaws.com/0/65942/73c3bfac-6943-e798-8be4-f21b3a0cad2a.png)

変更前も変更後も、フィールドコードは「prefecture」になっています。

これをgusukuで配布するとエラーになります。
kintoneはフィールドのタイプ変更に対応していないためです。
ただこうしたいケースはよくあるためgusukuの将来のバージョンで対応する予定にしています。

このようにフィールドコードは、バージョンをまたいだ場合、ユニークなキーとして機能しないという問題があるため、gusukuでは様々なロジックを用いてフィールドの同一性を推論してアプリケーションの配布を行っています。

現在はgusukuで対応できていないパターンもすでにいくつか見えてきているため、今後どんどんgusukuに盛り込んで行く予定です。

ディプロイAPIは深淵なる世界なので、自分でスクリプト書いてお手軽にディプロイしようとするとドハマリするので、gusukuをうまく使いたいですね。
ElectronのMainプロセスでHTTPリクエスト（認証が必要なプロキシ経由）

認証が必要なプロキシ経由でリクエストを送信する方法をメモ。

Rendererプロセス側での通信については、[Electronで認証付きプロキシの認証情報をユーザーに入力してもらう方法 - Qiita](http://qiita.com/iidaapp/items/ff2f6f0327ba3534244e)で分かりやすく書かれていました。
大まかな流れは上記リンク先と同じです。

1. HTTPリクエストの送信 
2. `login`イベントを拾って認証画面を表示
3. 入力情報を受け取り`callback(username, password)`
4. レスポンスを受け取る

Electronではバージョン**1.4.5**から[`net`モジュール](http://electron.atom.io/docs/api/net/)が追加されました。
Node.jsの`http`モジュールではなく、Electronの`net`モジュールを使用する利点として、次のことが挙げられています。

>
* Automatic management of system proxy configuration, support of the wpad protocol and proxy pac configuration files.
* Automatic tunneling of HTTPS requests.
* Support for authenticating proxies using basic, digest, NTLM, Kerberos or negotiate authentication schemes.
* Support for traffic monitoring proxies: Fiddler-like proxies used for access control and monitoring.

要は、プロキシまわりの整備がされているということのようです。

公式のAPIリファレンスを見れば使い方はわかるかと思いますが、簡単に紹介しておきます。

----

# HTTPリクエストの送信

[APIリファレンス](http://electron.atom.io/docs/api/net/)にサンプルコードも載っているので詳細は割愛しますが、

```js:
const request = net.request(options) // リクエストの生成
request.end() // リクエストの送信
```

という形でリクエストを送ります。
引数`options`には次のようなものを含むObjectを渡します。
（直接URLを渡すこともできます。）

* `method`：HTTPリクエストのメソッド。デフォルトはGET。
* `url`：リクエストURL。プロトコル（http/httpsなど）から書く。
* `session`：リクエストと関連している[Session](http://electron.atom.io/docs/api/session)のインスタンス。
* `partition`：リクエストと関連しているパーティション名。デフォルトは空。`session`オプションが指定されている場合は、無視される。
* `protocol`: プロトコル。`scheme:`の形で書く。デフォルトは`http:`。
* `host`：サーバのホスト。ホスト名とポートを`hostname:port`の形で書く。
* `hostname`：サーバのホスト名。
* `port`：サーバのポート番号。
* `path`：リクエストURLのパス部分。

# `login`イベントを拾って認証画面を表示

送信で生成したインスタンスでイベントを拾います。

```js:
request.on('login', (authInfo, callback) => {
  // 認証画面を表示させる処理
  // callbackはグローバルな変数に渡しておく
})
```

# 入力情報を受け取り`callback(username, password)`

そのままですが、グローバル変数に渡しておいたcallbackに入力で受け取ったユーザ名とパスワードを渡して、認証を完了させます。

# レスポンスを受け取る

リクエストに対するレスポンスは`response`イベントを拾って受け取ることができます。

```js:
request.on('response', (response) => {
  // 以下レスポンスボディを表示するサンプル
  let body = ''
  response.on('data', (chunk) => {
    body += chunk
  })
  response.on('end', () => {
    console.log(body)
  })
})
```

他にもいろいろなイベントがあるので、詳細はAPIリファレンスの[ClientRequest](http://electron.atom.io/docs/api/client-request/)を見てください。


----

このnetモジュールにたどり着くまで、古い情報ばかりがヒットして少し苦労しました。
Electronは頻繁に更新されているので、まめにAPIリファレンス見ると良さそうですね。
AmbariによるStormクラスタのモニタリング

この記事は [Hortonworks Advent Calendar 2016](http://qiita.com/advent-calendar/2016/hortonworks) の12/1３（火）のエントリーとして投稿しています。
また、以下の記事の続きとなる内容です。

- [AmbariによるStormクラスタのプロビジョニング](http://qiita.com/takanorig/items/1af7b8d8a791e0cb7633)

HDP（Hortonworks Data Platform）のコンポーネントの一部である Apache Ambari を利用してプロビジョニングされた Apache Storm のクラスタを、Ambari　でどのようにモニタリングできるかを確認してみます。
今回は、Storm を対象にしていますが、Hadoop／Spark／Kafkaなども同様の手順で実施できます。

#概要

Ambariは、クラスタのプロビジョニングだけでなく、サービスやホストのモニタリングも可能です。
特別な設定は不要です。Ambariを利用して構築されたホストは、そこに配備したコンポーネントに応じて、自動でモニタリングの内容も設定されます。
今回は、Zookeeper、および、Stormを含むクラスタを構築した場合のモニタリングを例にして説明します。

##モニタリング内容

##クラスタのモニタリング

最初に表示されるのが、クラスタ全体に関する内容です。
ヘッダーメニューの「Dashboard」をクリックすることで表示されます。

![ambari-monitoring01.png](https://qiita-image-store.s3.amazonaws.com/0/22893/11ede3aa-1970-15dd-9393-34832430c8ad.png)

各グラフをクリックすると、拡大されて、詳細な内容がわかります。
![ambari-monitoring02.png](https://qiita-image-store.s3.amazonaws.com/0/22893/e141e245-9603-b8d1-a953-0e21b25e4b67.png)

ここでは、メモリ、ネットワークI/O、CPUなど、基本的な項目に加えて、Stormのクラスタが含まれているため、Supervisorの項目がありますね。
ただ、この画面は、あまり特徴がなくて、あまり面白くないですね。
Hadoopのクラスタをプロビジョニングした場合は、以下のページにあるように、ダッシュボードにもっと多くの項目が表示されたりします。

http://jp.hortonworks.com/blog/apache-ambari-1-6-1-released/

今は「Metrics」の内容を表示していましたが、今度は、「Heatmaps」のタブの内容を確認してみます。

![ambari-monitoring03.png](https://qiita-image-store.s3.amazonaws.com/0/22893/825de156-bc42-a5ba-9ddd-9b2cbdba4062.png)

Allグリーン状態ではありますが、各ホストのディスク使用量が分かります。
今回は、5台のホストを使っているため、5つのブロックが表示されています。

##ホストのモニタリング

ヘッダーメニューの「Hosts」をクリックして、ホスト名を選択すると、以下のような画面が表示されます。

![ambari-monitoring04.png](https://qiita-image-store.s3.amazonaws.com/0/22893/7c9455f0-92eb-50d2-78fa-02bc0f2a8fcb.png)

１台のホストについて、詳細な状況が分かりますね。

##アラート

ヘッダーメニューの「Alert」をクリックして表示される画面では、各プロセスやリソースの状態が一覧で確認できます。

![ambari-monitoring05.png](https://qiita-image-store.s3.amazonaws.com/0/22893/6dc82f2a-2c93-6a3d-4c4e-8cfb7a4409fa.png)

アラートの内容は、メールで通知などの設定をすることも可能です。

##Stormのサービスのモニタリング

次に、Stormのサービスの状態を確認します。
サイドメニューから「Storm」を選択すると、概要の項目が分かります。

- 「Supervisors」が、**"2/2"** となっており、2台のホストで動作していることが分かります。
- 現在は、何もTopologyをデプロイしていないため、「Free Slots」が **"4/4(100% free)"** と表示されています。

![ambari-storm01.png](https://qiita-image-store.s3.amazonaws.com/0/22893/9da567b8-89e7-ed44-e61e-4bd6a10c59b3.png)

- 次に、1スロット分を利用する、SlidingWindowTopology をデプロイしてみます。

```bash
storm jar ./storm-starter-topologies-*.jar org.apache.storm.starter.SlidingWindowTopology slidingwindow
```

- 少し待つと、スロットが **"3/4(75% free)"** になりました。
- Excutors, tasks の数も増加していることが分かります。

![ambari-storm02.png](https://qiita-image-store.s3.amazonaws.com/0/22893/da20b4e0-0c26-b407-e093-88992df5294f.png)

- さらに、WordCountTopology をデプロイしてみます。

```bash
storm jar ./storm-starter-topologies-*.jar org.apache.storm.starter.WordCountTopology wordcount
```

- 少し待つと、スロットが **"0/4(0% free)"** になり、全スロットが動作する状況になりました。

![ambari-storm03.png](https://qiita-image-store.s3.amazonaws.com/0/22893/8b8a2e74-d9fe-b85c-3581-da3d0f779705.png)

これ以上の詳細は、Storm UIなどをつあって確認していくことになります。
画面上部の**「Quick Links」**をクリックすると、Storm UI の画面を開くこともできます。

#まとめ

Ambari で確認できるメトリクスは、現状では基本的な項目ですが、クラスタを構築して、すぐにこのような情報を確認できるようになるのは便利です。
スループットなども表示できると良いのですが、そこはカスタマイズが必要なようですね。
GrimoireJSのノード・コンポーネントの仕様詳細

(この記事は[GrimoireJSアドベントカレンダー13日目](http://qiita.com/advent-calendar/2016/grimoire)の記事です。)

こんにちは、GrimoireJS-Coreのコアコミッターmoajoです。
**GrimoireJS-Core**は、`html`上に埋め込まれた`goml`をパースして`GOM`ツリーを構築し、`GomlNode`の相互作用を管理するのが主なお仕事です。
今回はGrimoireJSの根幹である**GomlNode/Component**の細かい仕様についての話です。

# 新しいノード・コンポーネントを作る
GrimoireJSを拡張するときは、まず[機能をComponentとしてモジュール化して、それらをコンポーネントやノードとしてまとめます](http://qiita.com/moajo/items/f6cb9cfeec6bbb31ddb0)。
具体的には、

```js:index.js
gr.registerComponent("Component1", {
    attributes: {
      hogehoge: {
        converter: "String",
        defaultValue: null
      }
    },
    $mount: function (arg) {
      console.log("mount");
    },
    $awake: function (arg) {
      console.log("awake");
    },
    $hoge: function (arg) {
      console.log(hoge);
    }
  });
gr.registerComponent("Component2", {
    attributes: {
      hugahuga: {
        converter: "Number",
        defaultValue: 0
      }
    },
    $huga: function (arg) {
      console.log(this.getAttribute("hogehoge").Value);
    }
  });
gr.registerNode("node1", ["Component1"]);
gr.registerNode("node2", ["Component2"], {hugahuga:100}, "node1")
```
ここではコンポーネントとノードを２つづつ登録してますが、こんな感じで`GrimoireInterface`に登録します。
**登録はこれで完結してます**。つまり、コンポーネント・ノードに必要な情報はすべてここに含まれてます。
コンポーネントの方から仕組みを見てみましょう

## Componentの作成
`gr.registerComponent`の引数は、先頭から

0. **コンポーネント名**
1. **コンポーネントのインスタンスかコンストラクタ**
2. **継承元コンポーネント名**

です。
### コンポーネント名
**コンポーネント名は先頭大文字の`CamelCase`が推奨**です。基本的にそうしましょう。**ノード名は`snake-case`**です。

### コンポーネントの属性
コンポーネントは**`attributes`というフィールドで、そのコンポーネントが持つ属性を決めます**。
属性は、

```js:index.js
attributes:{
  属性名:{
    converter:コンバータ名,
    defaultValue:デフォルト値
  }
}
```
というフォーマットです。
コンバータは、`Number`、`String`、`Boolean`、`Enum`などが最初からありますが、

```js:index.js
gr.registerConverter("ConverterName", function(attr,val){
  console.log("this attribute is " + attr.name);
  console.log("value is " + val);
  if(typeof val ==="string"){
    return Number(val)
  }
  if(typeof val ==="number"){
    return val;
  }
});
```
という感じで追加できます。受け取った値を適切に変換して返すだけの関数ですね。
**gomlで文字列で指定された属性は、属性に指定されたコンバータを通して変換され使われます**。
また、コンバータは属性値を設定した時ではなく、**取得するときに遅延実行されます**。

### コンポーネントの$関数
コンポーネントが$で始まる関数を持つとき、それらはGrimoireJSの**メッセージレシーバ**として扱われます。
GrimoireJSではコンポーネント間でメッセージのやりとりがありますが、**それらの対象として扱われるのは先頭に$がつく関数のみ**です。
この関数内では、**`this`はこのコンポーネントのインスタンスにバインドされます**。

### コンポーネントの継承
**コンポーネントは継承できます**。
継承するとすべての属性と関数が引き継がれます。
また、ノードの`getComponent`関数で継承元コンポーネントを指定したときに**継承したコンポーネントも対象になります**。つまり、ポリモーフィズムを持つことができます。

## GomlNodeの作成
ノードは単純に複数のコンポーネントを入れる箱です。
コンポーネントとそれらの属性の初期値を決めて、タグとしてまとめられます。
`gr.registerNode`の引数は、

0. ノード名
1. デフォルトコンポーネントのリスト
2. 属性値
3. 継承元コンポーネント名

です。
コンポーネントのリストはそれが最初から入っているというだけです。属性値もコンポーネントのデフォルト値を上書きしてるだけですね。

### ノード名
さっきも書きましたが、`snake-case`です。

### ノードの継承
ノードも継承できますが、**ここにポリモーフィズムはありません**。
継承によって、コンポーネントリストや属性値を引き継ぎますが、属性値を隠すこともできます。
ノードの継承は、単に追加機能にエイリアスを付けているだけという感じです。

# その他
+ 属性値の優先順位は、**goml>Nodeの初期値>Componentの初期値**です。
+ コンポーネントやノードの継承関係は、**gomlのパース時に**評価されます。
+ コンバータは、変換できないときは`undefined`を返します。
+ また、コンバータにundefinedを通そうとするのは許されず、例外を投げます。
    + 従って、**属性初期値に`undefined`は設定できません。**
Sassで色相差が等間隔のカラバリn個を作る（色相環だけ回すver）

イッテンの色彩論にあるDyad,Complementary,Triad,Tetrad,Pentad,Hexadを関数で得られないかな、とやってみた。

基準色から色相環360度を2,3,4,5,6,,,n等分した時の色をつくる。

```scss
@function Colors($color, $part, $nth:null) {

  // $colorを基準に$partの数だけ色相を等分割して色の配列を作る
  $val: $color;
  @for $i from 1 through $part - 1 {
    $val: append($val, adjust-hue($color, 360deg / $part * $i), comma);
  }
  $colors: $val;

  @if $nth==null {
    // $nthの指定がなければリストで返して
    @return $colors;
  }
  @else {
    //$nthの指定があれば指定番目の色を返す
    @return nth($colors, $nth);
  }
}

// ex) Colors(#d39, 6) -> #d39, #d73, #9d3, #3d7, #39d, #73d
// ex) Colors(#d39, 6, 2); -> #d73

```

体感だと緑系が似た色に見えちゃう。
綺麗に等分された感を出すには明度や彩度も加味した方がいいかもしれない。
![89403a68-1789-6c81-02b6-2003d3cc2393.png](https://qiita-image-store.s3.amazonaws.com/0/54497/60d3ebe6-cdf9-3aee-6234-14c27299c94a.png)


https://jsfiddle.net/1Lqkf0nn/

# 感想

- 期待したほど見た目が綺麗に等分されないので実用性は謎。

- `append()`の使い方を一つ学べた。
  - 調和名を引数にして`adjust-hue($color, 360deg / $part * $i)`を分割する数だけ書いたところで、規則性あるんだからforで回して配列にすればいいんだ。。。と気付いた。

# 課題
社内ドラフトのタイミングで、モヤっとしてたところを分かりやすく指摘してもらった。

> カラーには元から明度／彩度の違いがあって、純色でも黄色が一番鮮やかで青紫が一番暗くなります。
> 単純に色相環を回転させた時に出る違和感はこれが原因です。
> この違和感を克服するために作成されたのが「トーン」で、人間の知覚に馴染むよう明度・彩度を調整してあります。

![2d81d0d0-3c32-5472-23a0-810321089ab0.png](https://qiita-image-store.s3.amazonaws.com/0/54497/7165aac0-3c05-5b75-f0b5-5797235e3e17.png)

> ひとまず彩度だけ調整。
知覚的に彩度落ち気味の色は上げて逆は下げる、みたいな記述追加すればいいんですかね。

**「知覚的に彩度落ち気味の色は上げて逆は下げる」**をうまく組み込みたい。
ETロボコンにチームを出してみた

これは [ETロボコン Advent Calendar 2016](http://qiita.com/advent-calendar/2016/etrobo) 14日目のエントリーです。

# 複数チームエントリー
経緯ははしょりますが、私の所属会社が ETロボコンに出場するようになって今年で3年目となりました。1,2年目は 2チーム、そして今年 2016年は 3チームを出しています。

社内では「ヤングチーム」と「シニアチーム」と呼んでいるのですがそれぞれ異なる意図でエントリーしているので、紹介してみます。

# ヤングチーム
こちらは名前の通りワカモノで構成されたチームです。年によって違うのですが、具体的には 新卒入社 1〜2年目くらいのメンバーで構成しています。2016は新卒入社人数が多かったので、ヤングチームを 2年目までのメンバーで構成し、さらに 2チームに分けてエントリーしています。こちらのエントリーはデベロッパー部門プライマリークラスです。

ヤングチームは **研修としての位置づけを持って活動** しています。入社1年目の社員にとっては、新人研修の一環として、ということになります。

PBL 的な意味合いがあり、組込み開発の設計や実装のスキル獲得だけでなく以下のような面にもフォーカスしています。

  * チーム開発の流れを知る
    * プロジェクトの計画づくり（目標と目的の設定、スケジュール立案とアップデート 等）
    * 進捗管理と定期的なふりかえり
    * タスク分解と自己管理
  * 開発用ツールの習得と習熟
    * バージョン管理システム(git)
    * Issue Tracking System
    * Wiki
    * コミュニケーションツール(Slack)

特に「チーム開発の流れを知る」の部分には [外部の会社](http://www.gentleworks.jp/) に入ってもらい、目標設定ワークショップの開催や、2週間に1回のふりかえりのコーチを行ってもらっています。この研修があるので、ここ3年の間に入社した社員は、ふりかえりに関しては下手な先輩社員よりもずっとやり方が身についているのが私の目から見てもよくわかります。

研修としての位置づけ、という観点で言うと副次的なものではあるのですが ヤングチームのうちの 1チームが今年みごとに チャンピオンシップ大会に出場できたことはやはり単純に嬉しかったし、エントリー3年目にしての初快挙でした。

#シニアチーム

一方、シニアチームの位置づけはずばり **「部活」** です。活動の合言葉は「これから本気出す」で、基本的には毎年 手を上げてくれた人が自分のできる範囲で、好きなように参加する、というのを眼目として、試したいことを楽しみながらやってみてよい、という風にしています。エントリーはデベロッパー部門アドバンストクラスになります。

ちなみに、私はロボコン活動全体のオーガナイザーであり、ヤングチームのメンターでもありますが、なにより自分自身もシニアチームの一員としても楽しんでいます。2014 は L字カーブ難所、2015は二本橋難所、2016 はEV3ブリックのメニュー表示 部分をそれぞれ主に担当しました。

今年もシニアチームはいろいろと楽しく活動しました。すぐ思いつくところだけでも以下のようなものがあり、「あとは設計して実装するだけ」という「外堀はすべて埋めたっ」状態には定評があります。

  * mruby への挑戦
    * 過去2年は C++ で実装していました
  * すべてがクラウドだけで完結する開発環境の構築
    * 参加メンバーのオフィス拠点が分かれていることもあり
    * ソース管理をGitLabにするだけでなく、独自に Azure上に オンラインエディタや CI等のシステムを構築し、ブラウザだけあれば実行バイナリ生成まで行える環境を作りました
    * これは Advent Calendar の別の日で紹介予定です
  * 連絡用 Slackでの bot 作成合戦
    * 今年一番盛り上がったのはこれかもしれません :p

そんな中、実は思いがけない副作用もありました。過去3年間 シニアチームのリーダーは毎年違う人がやっているのですが、敢えて普段の仕事ではまだリーダー層ではないメンバーにリーダーをやってもらっています。すると、思った以上のリーダーシップを発揮してくれるのです。この **新たなリーダーの発見と発掘** という副作用は、個人的に実はロボコンに参加した一番の収穫でした。また、明確なデータはないのですが、シニアチームの部活感は離職率の低下にも寄与していると信じています。

# おわりに

以上、性格の異なる2つのチームについて駆け足で紹介してみました。

ここで書いたことだけでもロボコン活動で得られるものはとても大きいと感じていて、そのためにちょっとお金をだせば解決することは積極的にサポートしています。（レプリカコースの購入と常設場所の確保、各チーム2体ずつの走行体、電池購入、Azure運用費用 等々）

他の組織での活動の意図やその効果についてもぜひとも聞いてみたいところです。
かわいい女の子を持ち帰り方

この記事は eeic （東京大学工学部電気電子・電子情報工学科）その2 Advent Calendar 2016 の16日目の記事です。
はやめに投稿した気がしてきたが、多分大丈夫。

クリスマスも近いし、EEICのみんなさんはかわいい女の子やイケメンを持ち帰りしたいですよね？よね？
21コマでそもそも彼女作れそうではないので、みんなさんに簡単にかわいい女の子を持ち帰り方を教わりたいと思います（上から目線
![687474703a2f2f6e7335302e706f696e74636c6f7564732e6f72672f6173736574732f696d616765732f636f6e74656e74732f6c6f676f732f70636c2f70636c5f686f727a5f6c617267655f706f732e706e67[1].png](https://qiita-image-store.s3.amazonaws.com/0/147779/39dc9b29-ceca-02c4-96b6-6b65ed715a26.png)
http://pointclouds.org/
とりあえず、女の子を用意する、３Ｄモデルが望ましいです。モデル化できるリアル女子でもいいですが、そもそもリアル女の子を用意できる人はオタクにはならない、なる必要がない。
それと厳密な数学モデルを説明してくれと期待してる方はお帰りになってください。
PCL　ポイントクラウドライブラリPOINT CLOUD LIBRARY、あるゆる３次元点群を扱うアルゴリズムの詰まった素晴らしいAPIです。言語サポートは確かにC++だけ。PYTHON　PORTもあるらしいけど
使ったことないので、興味ある人はぜひ見て教えてください。
じゃなにができるの～？という君
具体的になにかできるかというと。
Kinect Fusion
[![ビデオが開けなかった場合に表示されるテキスト](http://img.youtube.com/vi/quGhaggn3cQ/0.jpg)](http://www.youtube.com/watch?v=quGhaggn3cQ)
KINECTを使って３Ｄスキャンするアプリケーション、アルゴリズムはPCLの中にある。
論文
http://research.microsoft.com/en-us/um/people/pkohli/papers/uist_2011.pdf
MSRから出てきたアルゴリズム
一般的なICPの上に、フレイムの間に移動が僅かであると仮定して（計算量的に）シンプル化したアルゴリズム。

それと最近だと、ちょうど先日マカオ（最高）で開催されたSIGGRAPH２０１６でも公開されたものでこちらになります。
Fusion4D
[![ビデオが開けなかった場合に表示されるテキスト](http://img.youtube.com/vi/2dkcJ1YhYw4/0.jpg)](http://www.youtube.com/watch?v=2dkcJ1YhYw4)
論文：http://www.samehkhamis.com/dou-siggraph2016.pdf
オープンソースにはなってないかも（まだ読み終わってない）
上との違ってKINECT２０台くらいで撮ってるけど、それでも今まで一番すごかったしやすい（似たようなシステムに比べて）。

それと、PCLのホームページにいくとインストールマニュアルあるので、説明はしないと思うが、WINDOWSでやるとややめんど。UBUNTUとかがおすすめです。（APT-GETから行けるはず）

これで、君も自宅をスキャンして、３Dモデル入れてみましょう。
実例　：　https://twitter.com/nobelchoco/status/782425311451414528　
PCLでやると割りと簡単にできる（多分そうやってるわけではないが）
流れとしてはスキャンして、ダウンサンプルーー＞距離フィルタリングー＞ポイントの法線を計算してー＞平面検出してアリシアさんをそこに置く仕組みになってるはず。（３Dカスタムめメイドをバイト先のパソコンを入れる勇気がないので、どなたがry）

そして、「KINECT持ってないけど」の君にも、STEREO　VISIONと古き良き手法もあるので、
[![ビデオが開けなかった場合に表示されるテキスト](http://img.youtube.com/vi/bsA6RKUUA3M/0.jpg)](http://www.youtube.com/watch?v=bsA6RKUUA3M)
要は２つのカメラをくっつけて、２つのストリームからの画像を比較して距離を計算するタイプ。
精度かなり下がるけど、OPENCVとかでドキュメントされてて作りやすいです。

最後にスマホじゃできない？という君にも
[![ビデオが開けなかった場合に表示されるテキスト](http://img.youtube.com/vi/AyCkmbqB7ko/0.jpg)](http://www.youtube.com/watch?v=AyCkmbqB7ko)
同じくMSRから２０１４年の論文　：https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/depth4free_SIGGRAPH.pdf

スマホのカメラに赤外線LEDつけるだけでそれなりに精度出るやつ、近距離用なので、女の子（）との触れ合いとして使うのはいいかもしれないが、さきのようなことはできないと思うのでごちゅういを。

以上、彼女を作る技術のまとめのようなものになっております。
興味あるや一緒になにか作りたい人はぜひ僕に声かけてみてください、ツイッタでもリアルでも。
では諸君！セイ夜のご武運を祈る。
RancherOS や Barge で cron を動かす

* CoreOS には (busyboxがないため) crond がない。
* `@reboot`は使えないので注意


## RancherOS

* 0.8-rc2 で確認

```bash:スケジュール保存場所の用意
mkdir -p /home/crontabs /var/spool/cron
ln -s /home/crontabs /var/spool/cron/crontabs
/sbin/crond
```

```bash:cronの設定
$ crontab -e
* * * * * date >> /tmp/a.txt
```

```
tail -F /tmp/a.txt
```

* [Configuring RancherOS](https://docs.rancher.com/os/configuration/running-commands/)

```bash:rancher.yml
ssh_authorized_keys:
- ssh-rsa AAA...

network:
  dns:
    nameservers:
    - 8.8.8.8
    - 8.8.4.4

write_files:
- content: |+
    #!/bin/bash
    mkdir -p /home/crontabs /var/spool/cron
    ln -s /home/crontabs /var/spool/cron/crontabs
    /sbin/crond
    #wait-for-docker
    #docker run -d nginx
  owner: root
  path: /etc/rc.local
  permissions: "0755"
```


```bash:merge
sudo ros config merge < rancher.yml
sudo ros config export
```

## Barge

* すでにcrondが動いている。


busybox crontab -e


sudo busybox crond
cloud-init.ymlを使わずRancherインストールした後ログイン

rancher 1.0 にて確認。

```bash:パスワードを指定する場合
sudo ros install -d /dev/vda -a rancher.password=rancher -f
```

* sshで公開鍵なしでログイン可能。
* 上記だと rancher : rancher でログイン可能になる。

```bash:自動ログイン
sudo ros install -d /dev/vda -a rancher.autologin=tty1
```

* パスワード無しでログイン可能になる。
* パスワード設定していないためssh接続は直後は不可。
デザイナーがjavascriptを理解するまで（演算子編）

##javascriptを理解する上で困ったこと

これまでjavascriptを理解するために「Underscore JS」を読み解いてみました。
その際に困ったこと、javascriptをより理解し、書けるようになる為に必要だと思ったことを書きます。

###なぜ「Underscore JS」なのか？
- 綺麗に書かれているため読みやい
- javascriptを理解するためには良い勉強になる

###そもそもUnderscore JSっていったい何？
- javascriptの便利な関数が集まったライブラリ
- 配列を操作するのに役立つ関数がたくさん書かれている

▼公式ページにはこちらから
http://underscorejs.org/

###実際どのようなことに困ったのか？
私が一番困ったのが?__「演算子」__です。
javascriptで調べても検索にそれらしいものがヒットしなかったからです。

##演算子とは？
「演算子」と一言で言っても種類がたくさんありますが、
「算術演算子」、「等値演算子」、「代入演算子」は皆さん使われていると思います。

例） 
▼算術算子
「+（加算）」、「-（減算）」、「*（乗算）」、「/（除算）」
▼等値演算子
「==（等値）」、「!=（不等値）」

今回私が紹介したい演算子は２つ。
__「単項演算子」__と__「三項演算子」__です。

###単項演算子とは？
値を返したり、型の判別を行うのに使うことができます。
今回私が知らなかったのが下記の３つです。
__「delete」__、__「void」__、__「typeof」__

それぞれの効果は下記の通りです。

- delete・・・オブジェクトからプロパティを削除する
- void　・・・式の戻り値を破棄する（undefinedを返す）
- typeof・・・オブジェクトの型を判断する

###三項演算子とは？
if文を省略して書くことができるすごいやつです。

使用することで長かったif文も短縮できたり、コードを見やすくすることができるのではないかと思います。これからjavascriptを書く際には使っていきたいと思います。

例）if文で書いた時と三項演算子を使った時の比較
▼if文

```js
var a = true;
var b,c= 0;
if(a) {
 b = 1;
 c = 2;
 console.log(b + c);
}

結果：３
```

▼三項演算子使用

```js
var a = true;
var b,c= 0;
a ? b = 1 : b = 0;
a ? c = 2 : c = 0;
console.log(b + c);

結果：３
```

一行の記述でかけるので個人的には見やすいと感じます。
閉じタグ忘れによるエラーも減るのではないかなと・・・。
ただ使いすぎるとソースコードが見づらくなるのも事実なので注意も必要だと思います。

▼参考ページ
MDNさんのJavaScriptリファレンスがわかりやすかったです。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators

##まとめ
演算子を理解することで、javascriptのソースコードがわかるようになったり、
さらに綺麗な書き方ができるので、演算子を上手に活用してコードを書いていきたいと思います。
デザイナーの皆さんも「わからない！」と投げ出さず、一つずつわからないところをなくして自分の可能性を広げていただけたらと思います。
Electronで設定ファイルを扱う

`electron-config`一択。

[sindresorhus/electron-config: Simple config handling for your Electron app or module](https://github.com/sindresorhus/electron-config)

性質上設定ファイルは起動時に読み込みや終了時に設定の保存などに使われる。
ここでの処理がコールバックスタイルで書かれる`electron-json-storage`は扱いづらいだけと個人的には思う。

## 名前の変更

今(2018-06-13)はelectron-storeに名前が変わっています。

[sindresorhus/electron-store: Simple data persistence for your Electron app or module - Save and load user preferences, app state, cache, etc](https://github.com/sindresorhus/electron-store)

## インストール

```
$ npm install --save electron-config
```

## 使い方

公式のUsageそのままだが、使い方に迷うことないだろう。
面白い点として`dot-notation`をサポートしてる。
いちいちオブジェクトを作らず`foo.bar`と文字列で保存できるのは便利だ。

もちろん、メインとレンダラープロセスの両方で使える。

```js
const Config = require('electron-config');
const config = new Config();

config.set('unicorn', '🦄');
console.log(config.get('unicorn'));
//=> '🦄'

// use dot-notation to access nested properties
config.set('foo.bar', true);
console.log(config.get('foo'));
//=> {bar: true}

config.delete('unicorn');
console.log(config.get('unicorn'));
//=> undefined
```

## 例
色々省略したけどだいたいこんな感じにすれば、移動時やリサイズ時にウィンドウの設定が保存される。
それを起動時に読む込んでやるだけで前回のウィンドウが復元される。

```js
const Config = require('electron-config')

const config = new Config({
	defaults: {
		bounds: {
			width: 800,
			height: 600,
		},
	},
})

function createMainWindow() {
	const {width, height, x, y} = config.get('bounds')
	const win = new BrowserWindow({title: 'sample', width, height, x, y})

	win.loadURL(`file://${__dirname}/index.html`)

	['resize', 'move'].forEach(ev => {
		win.on(ev, () => {
			config.set('bounds', win.getBounds())
		})
	})
}

app.on('ready', () => {
	mainWindow = createMainWindow()
})
```
意外と知られていないzabbix公式コンテナイメージ

Tech-Circleのインフラ系はDockerばかりらしい。

ということで、私もDocker + Zabbixの話を書こうと思います。
(流行りだからね。乗らないとね。波にね。かぶりすぎで泣きそう。)

----
##知ってた？

運用監視ツールにZabbixを使用されている皆さん、[公式のドキュメントにあるインストールガイド](https://www.zabbix.com/documentation/3.0/)に**5 Installation from containers**というのがあるのを知っていましたか？

![Screenshot 2016-12-12 22:49:51.png](https://qiita-image-store.s3.amazonaws.com/0/47801/9ae83528-fad8-09f2-9451-8cc64f6f7fed.png)


そうこれ、zabbixが提供しているイメージなんです。

現在提供されているのは3.0と3.2が提供されているようで、導入方法は本当に簡単です。

----
## 簡単だよ

先ずはZabbixのDBとして必要なDBコンテナを立ち上げましょうZabbixコンポーネントではMySQLとPostgreSQLがサポートされています。この例はMySQLです。
で、当然の事ながらパスワードは**例**なので適宜置き換えを。

```bash:mysql-server
docker run --name mysql-server -t \
      -e MYSQL_DATABASE="zabbix" \
      -e MYSQL_USER="zabbix" \
      -e MYSQL_PASSWORD="zabbix" \
      -e MYSQL_ROOT_PASSWORD="zabbix" \
      -d mysql:5.7
```

続いてZabbixのCoreになる部分です。
ここでは接続先のDB情報を指定してください。

```bash:zabbix-server(mysql)
docker run --name zabbix-server-mysql -t \
      -e DB_SERVER_HOST="mysql-server" \
      -e MYSQL_DATABASE="zabbix" \
      -e MYSQL_USER="zabbix" \
      -e MYSQL_PASSWORD="zabbix" \
      -e MYSQL_ROOT_PASSWORD="zabbix" \
      --link mysql-server:mysql \
      --link zabbix-java-gateway:zabbix-java-gateway \
      -p 10051:10051 \
      -d zabbix/zabbix-server-mysql:latest
```

次はwebサーバを指定します。
サポートされているのは Apache2 と Nginx になります。

```bash:zabbix-web(nginx)
docker run --name zabbix-web-nginx-mysql -t \
      -e DB_SERVER_HOST="mysql-server" \
      -e MYSQL_DATABASE="zabbix" \
      -e MYSQL_USER="zabbix" \
      -e MYSQL_PASSWORD="zabbix" \
      -e MYSQL_ROOT_PASSWORD="zabbix" \
      --link mysql-server:mysql \
      --link zabbix-server-mysql:zabbix-server \
      -p 80:80 \
      -d zabbix/zabbix-web-nginx-mysql:latest
```

さてさて、最後にエージェントも導入しましょう。

```bash:zabbix-agent
docker run --name zabbix-agent \
           --link zabbix-server-mysql:zabbix-server \
           -d zabbix/zabbix-agent:latest
```

## あれ・・・出来てしまったぞ・・・

今回の例だとzabbix-web接続を80にしているので、http://dockerIPアドレス/ へ接続すると・・・

![Screenshot 2016-12-13 00:28:35.png](https://qiita-image-store.s3.amazonaws.com/0/47801/75aa6dd7-9cff-b344-9145-144bdfbbdb93.png)

たったこれだけでサーバが出来上がってしまいました。

![Screenshot 2016-12-13 00:30:02.png](https://qiita-image-store.s3.amazonaws.com/0/47801/33ec214b-bea6-6801-b755-7cb99849ee52.png)


今回はZabbixサーバが簡単にできるよというお話をさせていただいてますが、Zabbixサーバ以外にもZabbixプロキシコンテナが用意されています。

例えばZabbixサーバは既に用意されている環境を使用したり、AWSなどのAmazon Linux + RDSを使用。離れた環境ではdockerやrktを使用しZabbixプロキシを構築し、集約・サーバへの送信という組み立ても可能です。

まーったく伝えきれて居ないですが、今後も個人的にZabbixの面白さを伝えて行けたらと思います。
また、裏方でやっている[Zabbix Advent Calendar 2016](http://qiita.com/advent-calendar/2016/zabbix)もぜひ見ていってください。

----
明日は@koudaiii先生ですね。皆さんお楽しみに！
LinqでjoinとかGroup by sumとか。


まとまってないけど、とりあえずメモ。

##JOIN

###INNER JOIN

TableAにTableBとTableCと紐づくIDがあることが前提。

```csharp
var query = from a in db.TableA
            join b in db.TableB on a.id equals b.id
            join c in db.TableC on a.id equals c.Id
            select new { name1 = a.AName, name2 = b.BName, name3 = c.CName};
```

###OUTER JOIN

DefaultIfEmpty()を入れるとOUTER JOINになる。

```csharp
var query = from a in db.TableA
            join b in db.TableB on a.id equals b.id into A
            from x in A.DefaultIfEmpty()
            join c in db.TableC on a.id equals c.id into B
            from y in B.DefaultIfEmpty()
            select new { name1 = a.AName, name2 = x.BName, name3 = y.CName };
```

##Group By + Sum

Group byしてSum。

```csharp
var query = from x in db.TableA
            group x by x.GroupName into A
            select new { A.Key, sum = A.Sum(a => (int)a.Price) };
```

##JOINして複数キーでGroup ByしてSum

いろいろな書き方出来ますが、例えば下記のような感じ。FirstOrDefault()の使い方がポイント。

```csharp
var ret = from a in TableA
          join b in TableB on a.id equals b.id
          group new { a, b } by new { a.item, b.item } into X
          orderby X.FirstOrDefault().a.code
          select new { item1 = X.FirstOrDefault().a.item, sum = X.Sum(x => x.a.status), item2 = X.FirstOrDefault().b.item };
```
技術英語 > [Deferred] Rendering

@ http://3dnchu.com/archives/whats-realtime-rendering/
151ページの資料 page 25

> **<font color=red>Deferred</font>** Rendering

https://www.merriam-webster.com/dictionary/deferred
> withheld for or until a stated time <a deferred payment>

資料を読んでいて気になった英語。
前から時々Deferred Renderingという用語は気になっていたが、調べてなかった。

<hr>
関連して思い出したのは

> It's not until relatively recently that we recognize the value of the nature.

意訳「我々が自然の価値を認識したのは、つい最近のことだ」

16年ほど前に読んだ資料で出てきた。

<hr>
deferとdelayとpostponeなどについては以下に違いを書いている人がいる。

http://english.stackexchange.com/questions/81414/postpone-delay-and-defer
> answered Sep 12 '12 at 19:23
Kit Z. Fox♦

さんの意訳（間違っているかもしれない)

- postpone: 延期する人が「意図的に」行う
- delay: 「意図的に」という意味はない
- defer: 優先度を下げられた場合など. 他者主体による遅延

<hr>
関連

http://www.drbob42.com/examines/examinc1.htm
> Delphi 2010 Delayed Dynamic Link Libraries
コンソールで動くエディタを作る(12日目) カーソル位置の編集その3(文字の追加)

本稿は[自作エディタをつくる Advent Calendar 2016](http://qiita.com/advent-calendar/2016/make_editor)の12日目です、レポジトリは[こちら](https://github.com/tinyco/tiny_code_editor)

更新遅れて申し訳ないです。

# テキストを挿入する

前回まででカーソル位置に対するデータは取得できていた雰囲気になっていたのですが、
いくつかバグを修正ました

- 0始まりと1始まりを勘違いしていた
- 変にキャッシュした計算結果が実際のデータと食い違っていた

が主な要因です。
前者は0始まりに揃えるといった対策を、後者は早すぎる最適化は・・・、といった感じの反省でしょうか。

その取得した位置に対して、以下の処理を順に実行していきます。

- 格納しきれない時は、挿入したい文字列の後ろに空の構造体を追加
- 格納しきれない時は、末尾の文字を後ろの構造体の先頭へ移す(再帰呼び出し)
- 挿入する文字サイズ分、配列を後ろにずらす
- 挿入する文字を配列にコピーする

以上で、カーソルの位置に文字を追加することができました。

わりと私生活と職場などの外部要因でここまで3日に分けて書きましたが(しかも更新遅れた)、
これを読んでエディタを作ろうと思う人がいたら、「ほんとはそこまで難しくないよ」と伝えたいです。

逆に、もっと考えておけばよかったと思うのは以下の３点です

## カーソルの位置を文字数で保持しているが、半角と全角が入り乱れる文でカーソルを上下移動する際は、文字幅で保持していないと違和感がある

(例)「｜」の文字をカーソルと思ってください

```
あいう｜えお
0123456789abcdef

(カーソルを1つ下に移動)

理想(文字幅を考慮)
あいうえお
012345｜6789abcdef

現状(文字数のみで計算)
あいうえお
012｜3456789abcdef
```

いまは後者の実装になっています

普通のエディタ(atomとかvs codeとか)は文字幅を考慮してる・・・いや、してないですね。後者っぽい。
でも動かすと違和感があります。普段半角しか打たないからかな？

## 保持しているカーソルの位置と、実際のカーソル位置がズレたほうが使いやすそう

(例)「｜」の文字をカーソルと思ってください

```
状態1
abc｜de
(空行)
012345

(カーソルを1つ下に移動)

状態2
abcde
｜(空行)
012345

(カーソルを1つ下に移動)

状態3
abcde
(空行)
012｜345
```

状態2のときに、カーソル位置を先頭に戻してしまうと、状態3の時に文字0の位置にカーソルが動きます。

好みもあると思いますが、いっぱんにソースコードを書く時は上のようなカーソル移動をしてほしい気がします。今後の課題ですね。

## 文字を打つと、カーソル位置が1個後ろに行く

気にしたことがなかったですが、言われてみるとそうですね。
盲点でした。直さなきゃ・・・。

# 今日のまとめ

- 文字を打てるようになった

![eb7e9dd63f9ab41317871f56923ce916.gif](https://qiita-image-store.s3.amazonaws.com/0/151926/6dc10f4b-e862-9c27-b6c8-13fd6ee59423.gif)


明日は文字を削除できるようにしたい(忙しくて更新できてなかったので、今日ですが・・)

毎日更新はなかなか大変です。定時退社とはいったい・・・
List型同士で差分を求める

List型同士で、SQLのminus演算子みたいなの（←伝われ）ができたらいいのに、と思って調べてみたところ、Apache Commonsに便利なのがあった。

```java:Sample.java
List<String> list1 = Arrays.asList("a", "b", "e", "f");
List<String> list2 = Arrays.asList("a", "b", "c", "d", "e");

// list1にあってlist2にないものを抽出
@SuppressWarnings("unchecked")
Collection<String> result = CollectionUtils.subtract(list1, list2);

System.out.println(result.toString()); // => [f]
```

CollectionUtils#subtract() の中身としては、第１引数（list1）をもとにArrayListを作って、第２引数（list2）をイテレータでぐるぐる回して１件ずつremoveしているだけのようなので、第１引数（list1）の並び順が保障されている模様。ただ、然るべきデータ型に詰めてやるのが正しいような気はする。

危うく↓みたいな地味に面倒なコードを量産するところだった。

```java:
List<String> result = new ArrayList<String>(list1);
result.removeAll(list2);
```
Debian系LinuxでHDDを移行・抹消するときのコマンドメモ

```
# NTFSのマウント
sudo mount -r -t ntfs-3g /dev/sdx2 /mnt # 読み取り専用
sudo mount -w -t ntfs-3g /dev/sdx2 /mnt # 読み書き

# アンマウント
sudo umount /dev/sdx2

# rsync（パーミッションなどもコピー）
sudo rsync -av /mnt/ /data/1tb
sudo rsync -av -e 'ssh -c aes128-gcm@openssh.com' /mnt/ xxx@xxx:/data/1tb

# rsync（パーミッション以外をコピー）
sudo rsync -rOtv /mnt/ /data/1tb
sudo rsync -rOtv -e 'ssh -c aes128-gcm@openssh.com' /mnt/ xxx@xxx:/data/1tb

# 抹消（opensslをソースにしたdd）
sudo apt-get install -y pv
dev=ata-xxx &&
openssl enc -aes-256-ctr -pass pass:"$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64)" -nosalt </dev/zero \
    | pv -bartpes $(sudo blockdev --getsize64 /dev/disk/by-id/$dev) | sudo dd bs=64K of=/dev/disk/by-id/$dev

# SMARTをデスクトップに保存
dev=ata-xxx &&
sudo smartctl --all /dev/disk/by-id/$dev > ~/デスクトップ/smart$(date "+%Y%m%d")_$dev.txt

# 全領域書き込み・読み取りテスト（抹消にもなる）
dev=ata-xxx &&
sudo badblocks -wvs /dev/disk/by-id/$dev

# バックグラウンドで実行
dev="ata-xxx" &&
nohup sudo badblocks -wv -o badblocks.txt "/dev/disk/by-id/$dev" > "$HOME/$dev.log" &
```
Redmine でチケットのウォッチャーに特定のメンバーを簡単に追加したい

# 対象

* Redmine : 3.3.1
* クライアント : Linux, Firefox 50.0.2

# やりたいこと

チケットのウォッチャーに特定のメンバーを追加することが多い。とする。
その状況の良し悪しはおいておく。

チケットを作成するたびにメンバーを選択して追加する操作をせず、簡単に済ませたい。

# 解決策

## URL パラメーター

新規に作成するチケットが対象。だいたいがこれで良い気がする。

"新しいチケット作成時にウォッチャーのデフォルト値を設定したい - Google グループ"
https://groups.google.com/forum/#!topic/redmine-users-ja/qtllw2sUbNw

> new?issue[watcher_user_ids][]=1&issue[watcher_user_ids][]=2&&issue[watcher_user_ids][]=3
> 
> のように指定してはどうでしょうか。

## 一括編集

作成済みのチケットが対象。

"Redmine 3.3新機能紹介: 複数チケットに対して一括してウォッチャーを追加 | Redmine.JP Blog"
http://blog.redmine.jp/articles/3_3/add-watchers/

## REST API

作成済みのチケットが対象。

http://www.redmine.org/projects/redmine/wiki/Rest_Issues#Adding-a-watcher

説明に

> user_id (required): id of the user to add as a watcher

と書かれていて一回にウォッチャー一人しか追加できない (人数分 POST が必要) と思っていたが、以下のようにコントローラの処理を見て複数人を追加できると分かった。

http://www.redmine.org/projects/redmine/repository/entry/tags/3.3.1/app/controllers/watchers_controller.rb#L36

```rb
  def create
    user_ids = []
    if params[:watcher].is_a?(Hash)
      user_ids << (params[:watcher][:user_ids] || params[:watcher][:user_id])
    else
      user_ids << params[:user_id]
    end
    users = User.active.visible.where(:id => user_ids.flatten.compact.uniq)
    # 以下省略
```

## ブックマークレット

https://support.mozilla.org/ja/kb/bookmarklets-perform-common-web-page-tasks

「新しいチケット」のページを開いている状態で使う。新規に作成するチケットが対象。

```js
javascript:(function() {
    var userIds = [ "6", "7" ];

    var href = $(".search_for_watchers > a").attr("href");
    var url = href ? href.replace(/\/new\?/, "/append?") : href;

    if (url !== href) {
        $.post(url, { "watcher": { "user_ids": userIds } });
    }
})();
```

次。作成済みのチケットのページを開いている状態で使う。作成済みのチケットが対象。

```js
javascript:(function() {
    var userIds = [ "6", "7" ];
    var key = "";

    $.ajax(
        location.href + "/watchers.json",
        {
            "method": "POST",
            "headers": {
                "Content-Type": "application/json",
                "X-Redmine-API-Key": key
            },
            "data": JSON.stringify({ "watcher": { "user_id": userIds } })
        }
    );
})();
```

もう一つ。作成済みのチケットのページを開いている状態で使う。作成済みのチケットが対象。

```js
javascript:(function() {
    var userIds = [ "6", "7" ];

    $.post(location.href + "/watchers", { "watcher": { "user_ids": userIds } });
})();
```
Qiitaニュースのご提案（妄想、ポエム）

Qiitaのホッテントリもはてブみたいに分野別で出るようにならないかなー。
（参考:[はてブニュース](http://labs.ceek.jp/hbnews/)）

例えば、総合、機械学習、フロントエンド、バックエンド、Tips、作業効率化みたいなカテゴリで。
最初に、それぞれのカテゴリで頻出のタグをいくらか手動で選出すれば、あとはそれと共起してるタグを自動で見つけていって、分類とかできると思うんよね。
誰か作って下さい^^

というか、クローラ作ろうと思ったらどこをクロールすればいいんだろ？
クローラ作るのがめんどい。

作るなら、EC2x1 + RDSかなあ。
でもお金ないなあ。。。

Bitcoinで投げ銭してもらうかなあ。。。
クラウドファンディングという手もあるか。。。

投げ銭が集まらなかったら自然消滅するメソッドを使うのもありかなあ。。。