べにやまぶろぐ

技術寄りの話を書くつもり

Keynote で作ったスライドを slideshare に上げる時に表紙を画像にするようになった話

以前、

で書いたように日本語フォントを含むスライドを slideshare に上げるとサムネが真っ白になってしまうことがあります。上記エントリー中では "Save as Adobe PDF" で回避する策について書いたのですが、これだと

f:id:beniyama:20150223011337p:plain

のようにプリントの用紙サイズとスライドのサイズが合わずに余計な余白・線が入ってしまいます(あと気のせいでなければそもそも Acrobat Pro が必要な気がする)。

そこで最近はもう潔く一枚目だけ画像にして PDF 化しています。

ただしポイントが2点あり、

  1. Keynote の「(画像)書き出し」を使わないで スライドショーで画面最大化したものをMac のスクリーンキャプチャで画像化する。

  2. 元のスライドを差し替えるのではなく、元のテキストを残して上から画像を被せる(↓こんな感じ)

f:id:beniyama:20150223011349p:plain

ということをしています。

1は Keynote の画像書き出しよりスクリーンキャプチャの方が画質が良い(気がする)ためで、2は下図のように slideshare の Transcript の方に文字が残るから、という理由です(未検証だけど画像だけだと文字は表示されないはず)。

f:id:beniyama:20150223011400p:plain

こんなことしなくても問題ないのが一番良いんですけどね…

デブサミ 2015 【20-B-1】「『GMOプライベートDMP』の開発にあたって取り組んできた DevOps、更にその反省点と現在進行中のカイゼン事例の紹介」 の講演資料を公開しました #devsumi #devsumiB

今回のデブサミでは有難くも公募セッションにて採択していただき、業務開発の中で行っている DevOps の取り組み事例についてお話しすることができました。

『GMOプライベートDMP』の開発にあたって取り組んできた DevOps、更にその反省点と現在進行中のカイゼン事例の紹介

会期中の様子や講演メモなどは別のエントリーで書こうと思いますが、取り急ぎ講演資料をアップしたのでそのお知らせです。

今回は生まれて初めてプレゼン資料に萌えキャラ?を入れるという試みをしましたが、詳しくは下記のサイトをご覧いただければと思います。

あと、「機能横断」と言おうとして「職務横断」と書いてしまっていた事に今頃気づきましたが、もう終わったことなのでそのままにしておきます orz

Firefox で mousemove イベントが発火しなくなったときは preventDefault を確認しよう

自前のドラッグアンドドロップを実装していて、Chrome や Safari では発火している mousemove イベントが Firefox では定常的に上がってこないという事象に悩まされました。

色々調べてみたところ下記の stackoverflow で同じような質問をしている人が。

You should call evt.preventDefault(); in all the mouseXXX handlers. Firefox has default drag/drop handling and you don't want that. It's not a bug in Firefox that it does that.

イベント処理はブラウザによって独自の処理に入ってしまうため、互換性も考えた上でpreventDefault()stopPropagation() をきちんと意識して書かないといけないということを学びました。

ちなみに d3.js の場合は d3.event.sourceEvent.preventDefault() を呼ぶことになります。

『小さくて強い農業をつくる』読書メモ

小さくて強い農業をつくる (就職しないで生きるには21)
久松達央
晶文社
売り上げランキング: 5,676

先日、湘南T-SITE 内の本屋で平積み残り一冊だったこの本、農業 IT にも最近関心を持っていることもあって思わずその場で買ってしまいました。

ソフトウエア開発にもつながる話が多くて色々な至言があったように思います。以下、個人的に響いた箇所のメモです。

『20代で土日が楽しみになったらおしまいだよね』(p.34)

農業へのあこがれで日頃の不満をガス抜き = 腹をくくって人生を決める覚悟がない、との自省。20代でなくても週末が楽しみになってしまっては本末転倒。

『夢のために助成金があるのであって、助成金のための夢ではない』(p.42)

目先の金の算段をつけるサラリーマン的発想で本当の目的を見失わないこと。

『人は人中、地は地中』(p.59)

人も畑も真ん中で揉まれないと良くならない。

『農業って理系の技術職』(p.74)

農学のバックグラウンドがないとやるまでわからない。

『「経験と勘」がない自分には論理と言葉しかない』(p.78)

単純なプロセスであっても詳細に言語化することで問題点を明確にするだけでなく(属人性が排されるので)ノウハウの譲渡にもつながる。仕事は引き継ぎを繰り返すことで人から機能になり、また初めてコアとなる価値がわかる。久松農園ではクラウドで共有している。

『そもそも農業は自然なものではない』(p.87)

経験のない者が漠然と想像していまう農業 = 自然という誤解。

『一人ひとりが作業の内容を理解し、自分の判断で動ける仕組みがないと回らない』(p.94)

久松農園では朝会までにその日の作業内容を個々が予習し理解した上で、自己組織的に作業を行う。スクラム開発にもつながるところがあるように感じる。

『マニュアルはできるだけ初心者が作るようにしています。』(p.99)

熟達者が作ると暗黙知化している細かい行動の記録が抜ける。失敗学によれば「客観的な失敗情報は役に立たない」。

『多くの人が「野菜は美味しいから食べる」という素直さを失っている』(p.144)

「体に良い」、「残すべきではない」、「無農薬だから」と言って食べる・食べさせるより「ただ美味しいから」食べる食い気で考えて欲しい。エロうま。

『時間は未来から過去へ向かって流れている』(p.150)

あらゆる場面で因果を追求することに意味はない。未来に思考を移すべき。

『人は誰でも、半径10mの人間関係に規定されてしまいがち』(p.174)

インターネットは身近な人の外側に真のファンがたくさんいることを教えてくれる。周囲の否定的な意見に屈する必要はない。

『理念なき経済は罪悪であり、経済なき理念は寝言である』(p.199)

有機農業の成り立ちからして商業主義に触れることがタブーだった時代がある。

『自分の労働単価を決めてしまえ』(p.217)

設備投資や事業規模はまず自分が何時間稼働してどれだけ売り上げたいかを決めることから始まる。

『新規就農者とのマッチングがいい選択肢の一つは、間違いなくニッチ狙いの変態型農業』(p.265)

マスプロダクションから脱却し、全ての人が食べる野菜がなくなってきた昨今ではコモディティ型の生産と勝負するのではなく、合理性から脱却した『グッと』くる変態型農業が有効。

『明日のために今日を我慢するという生き方をしている限り、目的は絶対に達成されません』(p.273)

子供は大人になるための準備期間ではなく、子供のときにしかできないことをやる期間。それは大人も同じ。

次は同著者のキレイゴトぬきの農業論(新潮新書)を読んでみようと思います。

キレイゴトぬきの農業論(新潮新書)
新潮社 (2014-03-21)
売り上げランキング: 1,462

『GMO プライベート DMP で ビッグデータ解析をするために アプリクラウドで Apache Spark の検証をしてみた』の資料を公開しました

Apache Spark を今後活用していくに当たって行ったプレ検証の結果について slideshare にアップロードしました。

もう少し詳細な内部の実装や挙動を見ていかないとと思いつつ、いい加減ワードカウントも飽きてきたのでデータ分析にトライしていきたいと考えております。

Slack で発言する Hubot にチャレンジしたらバージョン3系になっててちょっとハマった

最近流行りの ChatOps についていきたい!という純粋なミーハー心と日々のちょっとしたことを自動化したい(ミーティングのリマインダとか、ランチグループ分けとか)という思いから Hubot 使って Slack 連携をさせてみたのですが、最近バージョンが2系から3系に変わったということでウェブ上のドキュメントが微妙に古くなっててハマりました。

特に cron で robot.send() を呼んで定時に発言させたい、というだけだったのですが robot.send {room: "#general"}, "ハロー" とか robot. messageRoom "#general", "ハロー" とかいろいろ試したものの

[Sun Jan 18 2015 23:26:40 GMT+0900 (JST)] ERROR TypeError: Cannot call method 'send' of undefined
2015-01-18T14:26:40.609421+00:00 app[web.1]:   at SlackBot.send (/app/node_modules/hubot-slack/src/slack.coffee:181:16, <js>:216:33)

などとエラーが出てしまい、一瞬そもそも robot.send が呼べていないようにも見えつつ、追ってみると上記エラー内の slack.coffee で

channel = @client.getChannelGroupOrDMByName envelope.room

で channel を取得しているものの特に null チェックをすることなく

channel.send msg

に突入してしまっており、それはそれでまずいのですがそもそも channel が取得できていない様子。

で、色々調べてみると hubot-slack アダプタ v2 から v3 へ – 半月記 に大変よくまとめられていました。

v3 ではちょうど逆になって、ハッシュ(#)を付けないようになりました。これが付いていると正しく動作しません。

ということで cron の書き方もいろいろあって悩んだ挙句に最終的には

cronJob = require('cron').CronJob
module.exports = (robot) ->
  new cronJob
    cronTime: "0 58 9 * * 1-5"
    onTick: ->
      robot.send {room: "general"}, "朝会やりますよ ヽ(´・ω・`)/"
      return
    start: true
    timeZone: "Asia/Tokyo"

このように落ち着きました。npm の方で crontime のパッケージを足してあります。

ちなみに robot.send() が無い、という問題はそれはそれであるようで 橋本商会 » hubot-slackアダプタv3にアップデートしたら色々辛かった

websocket接続するまでrobot.sendが無い

と指摘されており、起動直後に send コマンドを実行するような場合は記事内に書かれている

return if typeof robot?.send isnt 'function'

のようなのを挟んでおくと良さそうです。

これから新規で slack 用 hubot 開発する場合は、まだまだ不安定なバージョン3系だということを意識して調査・開発したほうが良さそうです。

Trello のハッシュタグをもとにカードに色づけしてくれる Chrome プラグイン "Colored Hashtag for Trello" を Yeoman を使って作ってみた(その3)

↑ を作ってみたシリーズ、前回の記事 の続きです。

Yeoman の generator-chrome-extension でプロジェクトを作成すると /app/scripts/ 配下に background.js と chromereload.js という二つのスクリプトが生成されます。今回はこの二つのファイルについて調べたことをまとめてみます。

chromereload.js

chromereload.js は LiveReload というツールを通して、ファイルに変更を加えた時に自動的にブラウザをリロードする機能を提供してくれます。

GitHub - yeoman/generator-chrome-extension: Scaffold out a Chrome extension には

Debug task helps reduce your effors during development extensions. If the task detects your changes of source files, Livereload(chromereload.js) reloads your extension.

とありますが、開発中は grunt debug や grunt watch などを走らせておき、例えば

Running "connect:chrome" (connect) task
Started connect web server on http://localhost:9000

というようなメッセージが出力された場合には http://localhost:9000 にアクセスするとアプリケーションの HTML が表示されます。ここで LiveReload - Chrome ウェブストア のような LiveReload プラグインをブラウザに入れておくと、ソースの改変を grunt のタスクが検知、LiveReload がキックされブラウザに websocket で通知がいき、即時的にリロードが走ります。

ちなみに今回作成したプラグインは画面が無かったせいか

f:id:beniyama:20150109004318p:plain

のような素っ気ないファイル一覧が表示されました。これもリアルタイムで更新されます。

background.js

chromereload.js が開発用途だったのに対し、こちらは拡張機能の根幹となるファイルです。これはその名の通りバックグラウンドで走り続ける処理(イベントハンドリングなど)を記述するもので、以前は background.html と合わせて Background Pages と呼ばれていたようですが、Manage events with background scripts - Chrome Developers

Caution: Consider using event pages instead. Learn more.

とあるように現在は Event Pages に移行されているようです。

例えば Colored Hashtag for Trello では

/*global $:false, chrome:false */

chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
  "use strict";

  if (changeInfo.status === 'complete') {
    chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
      chrome.tabs.sendMessage(tabs[0].id, {message: "onUpdated"}, function (response) {
      });
    });
  }
});

のように chrome.tabs.onUpdated イベントにリスナーを張ってページの URL の変化を検出しています。これは Trello がサイドバーなどでページ遷移して URL が変わってもリロードが走らず Chrome 拡張が読み直されない = 遷移先のページで色をつけられない ことに困ったためで、HTML5 History API の使用も疑ったのですが最終的には tabs のイベントをとることで落ち着きました。

イベントリスナの中で chrome.tabs.sendMessage() としていますが、これは background.js と対をなす content_scripts にイベントの検出を通知し、画面描画処理をキックしています。content_scripts についてはまた次回書こうと思います。

ちなみに background.js に console.log() などを仕込んでも通常の開発者コンソールには出てこないため注意が必要です。デバッグログを見るには、chrome://extensions にアクセスして

f:id:beniyama:20150109011959p:plain

↑ のリンクを押すと下記のようなウィンドウが開きますので、そこで確認することができます。

f:id:beniyama:20150109012037p:plain

まだ Event Pages についての理解が浅いので、引き続き Update: Event Pages and Background Pages - Chrome Developers を読み込んでいこうと思います。


↓ 前回の記事

http://beniyama.hatenablog.jp/