読者です 読者をやめる 読者になる 読者になる

ietty TECH blog

ポケモンGOで会社の近くに出現したポケモンをSlack通知させた話

f:id:mikeda3:20160730152015j:plain ietty社内でも人気のポケモンGOですが、会社の近くにレアポケモンが出現していないかポケビジョンばかり見て仕事にならなくなってしまったので、レアポケモンが出現した時にSlackにメンション付きで通知するようにしました。

とりあえず準備

Slack BOTはHubotで開発し、サーバには無料で使えるHerokuを使います。

HubotはNode.jsで開発ができるので、ポケモンGOのAPI取得部分はjavascriptでポケモンGOのAPIを扱えるPokemon-GO-node-apiを使います。 github.com ※npmに公開されているのでnpm install pokemon-go-node-apiで簡単にインストールできます。

ソースコード

module.exports = (robot) ->
  PokemonGO = require('pokemon-go-node-api')

  # JSON(pokemon-go-node-apiの中にあるpokemon.jsonを日本語化したもの
  pokemonJson = require('./pokemon.json')

  # 通知先チャンネル
  @pokemonUser = room: '#hogehoge'

  # ポケモン捜索先の位置情報
  location = {
    type: 'coords',
    coords: {
      latitude: 35.64780246266644,
      longitude: 139.7102701663971,
      altitude: 10
    }
  }

  # 認証用情報(登録時のgmailのアカウントを入れてください)
  username = 'hogehoge@gmail.com'
  password = '12345678'
  provider = 'google'

  # レアポケモンが出た時に飛ばすメンション
  @pokemonMention = '@hogehoge'

  # 重複して出さないように配列でチェック
  duplicateChackArray = [];

  # APIにリコネクトがないので接続切れを起こさないように10秒に1回ログインして情報を収集する
  setInterval(() =>
    io = new PokemonGO.Pokeio()
    io.init(username, password, location, provider, (err) =>
      if err
        console.log(err)
      console.log('1[i] Current location: ' + io.playerInfo.locationName)
      console.log('1[i] lat/long/alt: : ' + io.playerInfo.latitude + ' ' + io.playerInfo.longitude + ' ' + io.playerInfo.altitude)

      io.GetProfile((err, profile) =>
        if err
          console.log(err)
        console.log('1[i] Username: ' + profile.username)
        io.Heartbeat((err, hb) =>
          if (err)
            console.log(err)
          for val in hb.cells
            if val.NearbyPokemon
              for item in val.NearbyPokemon
                pokemon = pokemonJson.pokemon[parseInt(item.PokedexNumber)-1]
                if duplicateChackArray.indexOf(item.EncounterId.toString()) == -1
                  duplicateChackArray.push(item.EncounterId.toString())
                  # ポケモンのレアリティによってメンションを飛ばすか判定
                  if pokemon.egg == '10 km' || pokemon.egg == 'Not in Eggs'
                    mention = @pokemonMention
                  else
                    mention = ''

                  robot.send @pokemonUser,
                    mention + '\n' + pokemon.name + '(' + pokemon.egg + ') を ' + item.DistanceMeters.toString() + ' メートル圏内に発見!\n' + pokemon.img
        )
      )
    )
  , 10000)

できたもの

f:id:tioken12:20160729201423p:plain

ポケモンの名前の横に出ている◯kmはどの卵から出るポケモンかを表示しています。 その数値からレアリティを判定して、10kmの卵のポケモンと卵から出ないポケモンだけ自分にメンションを飛ばすようにしました。

メンションが飛んできたらポケビジョンで位置を確認してダッシュで捕まえに行きましょう!

Photoshopとcsvデータを連動させて画像を高速量産できる!変数データセットが超便利な件

f:id:mikeda3:20160622180055p:plain こんにちは!iettyデザイナー池田です。

Photoshopには変数データセットという機能があり、csvデータと連動させて複数バージョンの画像をすばやく書き出すことができます! 詳しいやり方についてはAdobeのページをごらんください。

オウンドメディア担当者と連携して、ietty Magazineのアイキャッチ画像を量産する体制を確立したので方法をご紹介します!

続きを読む

WordPressでAPI連携

要件としては、投稿ページ等にAPIで取得したデータを表示させたいということだったので WordPressのwp_remote_get関数を使って取得してみました。

wp_remote_get

wp_remote_get - WordPress Codex

使い方は簡単で、パラメータにURLを指定するだけでデータを取得することができます。

wp_remote_get('http://hogehoge.com/');

また、第2引数に配列でオプションを指定することも可能となります。

// timeoutを10秒に設定
wp_remote_get('http://hogehoge.com/', array('timeout' => 10))

戻り値は配列で返却され、headersやbodyなどがあり、データについてはbody内に格納されています。

※配列の詳細については、こちらを参照

ショートコード化

APIからデータを取得することはできたが、ページの好きな場所に表示させるにはどうしようかと 思ったところ、ショートコードを自作すれば任意の場所に表示させられるじゃないかと思い wp_remote_getで取得したデータをショートコード化してみました。

function.php
<?php

...

function get_remote_by_hogehoge($args) {
  $url = 'http://hogehoge.com/'
  $url = empty($args) ? $url : $url . '?' . http_build_query($args);
  $arr = wp_remote_get($url);

  if (is_wp_error($arr) || $arr['response']) {
    // エラー処理
    ...
  }

  $body = json_decode($arr['body']);

  // 以下省略
  ...
}
add_shortcode('hogehoge', get_remote_by_hogehoge);

...

これで投稿ページ等に[hogehoge]と追加した場合に、データが表示されます。

また、[hogehoge param1=test]等、引数を指定した場合には http://hogehoge.com/?param1=testのように、クエリパラメータを付与できるようにしてみました。

ユーザーストーリーマッピングで大規模改修のプランニングをやってみた

f:id:mikeda3:20160512162456j:plain こんにちは! iettyのデザイナー池田です。

今回はユーザーストーリーマッピングの紹介です!

iettyは2012年2月創業から4年、サービスを支える管理画面を要望に合わせてつぎたしつぎたし作っていましたが、 全体像がわかりづらくなってきました…。長く運営されているサービスならよくあることだと思います。

今まで山ほど積もっている改善要望、いつかやりたいと思っていたこと、全部の夢をまとめた「さいきょうのかんりがめん」にしたい!! でもどこから手をつけていいのかわからない……

そんな問題を解決すべく、管理画面の大規模改修プロジェクトの計画フェーズにユーザーストーリーマッピングを取り入れてみましたので紹介します!

続きを読む

Tips for rails4-autocomplete

github.com

rails4-autocomplete is a very useful gem for textfield auto complete function, but it's not maintained so use it on your own judgement, or use https://github.com/bigtunacan/rails-jquery-autocomplete.

Using rails4-autocomplete let textfield add auto complete function easily.

You can use scope to restrict search result as README says, but sometimes you want to restrict search result by id as well.

So, how do I achieve this?

In controller which you want use auto completion, override get_autocomplete_items like below.

def get_autocomplete_items(parameters)  
    super(parameters).where(some_id: some_ids)
end

Also, you can customize autocomplete suggestions.

To override the autocomplete_xxx_name method which generates automatically like below does the trick.

def autocomplete_xxx_name
    term = params[:term]
    models = Model.joins(other_model).some_scope(term).all
    render json: models.map { |model| { id: model.id, label: model.some_column, value: model.some_column} }
 end

You can join other table, customize suggestion text and choose send value.

LINE BOT API と Riot API で遊んでみた

先着10,000名限定で公開された『BOT API Trial Account』ですが、研究開発の時間を頂けたので少し触ってみました。

そのままテストしてもつまらないので、偶然持っていたLeague of LegendsのProduction APIを使って戦績を返すBOTを作ってみました。

とりあえず準備

LINE BOT API

アカウントの取得方法やAPIの使い方などは、この記事が分かりやすかったので見てください。 qiita.com

Callback先にはSSL証明書(Let's Encrypt以外の)が必須らしいので、とりあえず僕の開発用のサーバをCallback URLに指定。

Riot API

Development APIはRiot Games APIからすぐ作れます。

僕の持ってるProduction APIは申請から承認まで3週間ほどかかるのですが、日本サーバにアカウントを移動させたタイミングで使えなくなってたので問い合わせたらすぐに対応してくれました。 f:id:tioken12:20160415194358p:plain

サーバ

ずっと昔に作って放置してたCodeigniterの環境にLINE BOT用のコントローラーを設置し、さきほどのQiitaの投稿をベースに書いてきます。

<?php
public function index() {
  // アカウント情報設定
  $this->channel_id = "[チャンネルID]";
  $this->channel_secret = "[チャンネルシークレット]";
  $this->mid = "[MID]";

  // メッセージ受信
  $json_string = file_get_contents('php://input');
  $json_object = json_decode($json_string);
  $this->content = $json_object->result{0}->content;

  $event_type = "138311608800106203";

  $this->_api_post_request("/v1/events", $event_type, json_encode($this->_create_text($this->_get_summoner_data($this->content->text))));
}

private function _create_text($text) {
  $text = array(
    'toType' => 1,
    'contentType' => 1,
    'text' => $text,
  );

  return $text;
}

private function _api_post_request($path, $event_type, $content) {
  $url = "https://trialbot-api.line.me{$path}";
  $headers = array(
    "Content-Type: application/json",
    "X-Line-ChannelID: {$this->channel_id}",
    "X-Line-ChannelSecret: {$this->channel_secret}",
    "X-Line-Trusted-User-With-ACL: {$this->mid}"
  );

  $post = <<< EOM
{
"to":["{$this->content->from}"],
"toChannel":1383378250,
"eventType":"{$event_type}",
"content":{$content}
}
EOM;

  $curl = curl_init($url);
  curl_setopt($curl, CURLOPT_POST, true);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
   $output = curl_exec($curl);
}

$this->content->text にチャットの内容が入ってくるので、それをサモナー検索用のメソッドに投げて、返ってきた値をcreate_textメソッドに投げることでcallback用の配列に格納し、api_post_requestで $this->content->from に入っているチャットルームIDに向けてメッセージを送信しています。

できたのがこれ

LOL Summoner Info

f:id:tioken12:20160415201310p:plain

チャットで入力したサモナーの戦績をRiot APIから取得して返してくれます!

まだLINE BOT APIがトライアルということもあり、50人までしかフレンドに登録できませんがもしよかったら追加して遊んでみてください。 f:id:tioken12:20160415202007p:plain

re:dashでBusiness Intelligence

こんにちは。iettyの大浜です。 ietty TECH blog初の記事ということで、先日社内に導入したSQLベースのBIツール、re:dashのインストールとダッシュボードの作成をご紹介します。

re:dashとは

re:dashはドキュメントによればデータ連携と可視化のためのオープンソースプラットフォーム(Open Source Data Collaboration and Visualization Platform)

現行版ではどちらかというと可視化の方に重点が置かれているようですが、折れ線、棒グラフ、ヒートマップなどの一通りの可視化の他、複数のデータソースからのデータを1つのダッシュボードでまとめて閲覧する、などは当たり前のようにサクッとできます。

f:id:takemi_ohama:20160413021340p:plain

BIツールとしての最大の特徴はSQLから直接グラフの生成を行うこと。

ETLとかOLAPとかMDXとか、細かいことは抜きにして「SQLを書いたらグラフが出来た」というアドバンテージは計り知れないと感じています。

いつかこういうのを作ろうと思ってたらもうあった、というぐらい「いい感じ」のツールです。

そのほか、re:dashの良いところ、足りないところについてはこちらも推奨。

インストール

AWSの場合はAMIが用意されているのでそれを使うのが良いみたいです。この辺参照。

今回は別のBI系ツール用コンテナと同居させたかったのであえてdockerを使いました。 docker-compose.ymlのサンプルがこちらにあるので、ファイル名を変更してdocker-compose up -dすれば起動します。

あとDBのマイグレーションとSeed(初期ユーザ)の登録が必要ですが、これはドキュメントが詳しいので省略。

データソースの指定

最初に分析する対象のデータソース(DBやストレージ)を指定します。adminグループに属しているユーザに表示される右上のストレージっぽいアイコンをクリックしAdd Data Sourceを選択すると、データソース設定画面に遷移します。

f:id:takemi_ohama:20160411184026p:plain

対象のミドルウエアを選び、それぞれの接続情報を入力してSaveすればOK。接続確認のようなボタンはないので、次のフェーズで実際にクエリを発行して確認することになります。

Add Data Sourceを繰り返して複数のデータソースを登録することも可能です。

クエリ操作

クエリの作成と保存

上部のメニューからQueries-New Queryを選択すると、SQLを入力する画面が開きます。

f:id:takemi_ohama:20160413021620p:plain

複数データソースを登録している場合は、画面下の「Data Source」で、分析対象のデータベースを選択する必要があります。残念ながらいわゆるETLのような複数データソースをJOINしたりマージするような機能はまだないようですね。

SQLはそのDBのネイティブのものが通るようですが、動的なパラメータ設定のようなことをやりたい場合はre:dash独自のやり方で指定することになります。

エディタの右側にschema情報を表示するツリービューがあり、テーブル名やフィールドの簡単な検索ができるので、クエリ書く時の参考になります。

そのうちドラッグ&ドロップかダブルクリックでのエディタへの貼り付けあたりが実装されそうな気が。

SQLをExecuteして期待通りのテーブルが出たら、左上の「New Query」というタイトルをクリックして適切な名前を付けて、Saveすれば、クエリは完成です。

企業で複数人でBIやっていると、特にユーザ情報や購買履歴の分析はそれぞれ似たようなクエリを抱え込んで散逸しているケースが多いので、こういったツールで集めておくだけでもデータの価値は飛躍的に高まります。

Refresh Scheduleを指定しておくと、 SQLを定期的に実行して結果を保持してくれますので、ダッシュボードを使う場合は是非指定しておいてください。

グラフ作成

re:dashオペレーションの一つ目のハイライトがこのグラフ作成になります。

Executeしてテーブルが出力された状態から、グラフを作成していきます。 以下の6つのヴィジュアルから選べます。

  • Boxplot ... 箱ひげ図。四分位点と最大最小値を用いて分布を表示
  • Chart... 折れ線、棒(積み上げ可)、円、散布図を生成
  • Cohort...日次、週次、月次のコホート図を生成
  • Counter...ダッシュボードに現在値を大きな数字で表示する。
  • Map... 緯度経度を指定して世界地図に描画
  • Pivot Table...テーブルをピボットテーブルに組みなおして表示

MapやCohort等、使いどころさえ選べば強力な分析ができそうですが、とりあえずBIダッシュボードとしては、ChartとCounterを押さえておけば十分でしょう。

例)積み上げ縦棒グラフの作成

  • SQLをExecuteして結果をTable表示させる
  • +New Visualizationをクリック
  • セレクタで以下を設定

    • Visualization Type = Chart
    • Chart Type = Bar
    • X Column = 縦軸を表示。ダッシュボードなら通常時系列(日付や月)になります。
    • Y Column = 分析軸(Series)を指定。複数選択可。
    • Name... 任意の名前。
    • Stacking...積み上げをするかどうか。Disableなら横並びに、Enableなら積み上げ。Percentだと帯グラフになります。
    • Group by ... Group by句でY軸を指定することでも積み上げができるようなのですが、MySQLだと全ての軸が同一色になってしまい、ました。使い方要調査。
  • さらにX軸、Y軸(左右2つ)とSeries別のチャートタイプ、順序指定が可能です。

    • Scale... 日付, 線形,対数, カテゴリカルから選択。

    希望のグラフができたら、Saveして保存してください。一つのクエリに対して複数のグラフを設定することが可能です。

クエリの一覧表示

上部メニューでQueries- Queriesと選択していくと、作成されたクエリの一覧が表示されます。

  • My Queries ... 自身が作成したクエリのみ表示
  • All QUeries ... 別のユーザが作成したクエリも表示
  • Drafts ... 名前をNew QueryのままSaveすると、このタブに入るようです

各クエリの実行時間もここに表示されていますので、遅いクエリなどは適宜チューニングするようにしましょう。

ダッシュボード

このような感じでいくつかクエリとチャートを作ったら、、ダッシュボードで1ページにまとめます。

ダッシュボード作成

  • 上部メニュー左のタコメーターのマークをクリックし、New Dashboardを選択
  • 適当な名前を入れる
    • 日本語も入力可能ですが、パーマネントリンクに利用されるのでURL利用可能文字(英数字とハイフン)を使うほうが良いです。
  • タイトル右のアイコンから「+」マーク(Add Widget)を選択

ダッシュボードWidget追加

  • クエリ名、グラフの名称を選択
  • Widget SizeはRegularとDoubleの2種。Regularだとある程度の画面サイズがあれば2段組みになります。

ダッシュボードは毎日見ることで意味が出てくるものですので、できるだけシンプルに、かつ重要なデータを選んで組みましょう。

なお、グラフ同士の配置や順序は次の編集で修正できますので、とりあえず順序は気にせずどんどん追加してかまいません。

ダッシュボードの編集

1ページで表示したいテーブルやグラフを選択し終わったら設定アイコンをクリックして編集します。

f:id:takemi_ohama:20160413022116p:plain

ドラッグ&ドロップが有効ですので、内容の重要度を考慮して配置していきます。

組みあがったらSaveしてダッシュボードの完成。リンクを皆に共有しましょう!