hitode909の日記

以前はプログラミング日記でしたが、今は子育て日記です

Asanaのダッシュボード内のバーンアップチャートに予測線と完了日をプロットするChrome拡張

Asanaのダッシュボードに置けるバーンアップチャートには今後の予測を表示する機能がなく、過去の実績だけが表示されている。

Asanaのバーンアプチャートの例

一方、よくあるバーンアップチャートはこんな感じで、予測線が引かれていて、タスクがこれだけあって、タスクの完了ペースはこうなってて、このペースが続けばいつ終わりそうです、という予測ができるようになっている。

差し込みの多いプロダクト開発のスケジュールの精度を上げるためにはバーンアップチャートがおすすめです - スタディサプリ Product Team Blog


タスク管理にはAsanaを使いながら、いつ終わるかも予測したい。

既存手法

社内ではいくつかのアプローチが試みられていた。

タスク一覧をCSVをエクスポートして、Google Sheetsにインポートしてバーンアップチャートを構築する

最初に試みられた手法がこれで、更新するたびに何度かクリックが必要。
インポート後にExcel的な関数でデータを加工したり、不要なタスクをチャートの計算外にしたり、ということが自由にできるのは魅力なのだけど、毎度繰り返される更新の手間が、その魅力を上回っている印象だった。

Google Apps Scriptを使ってAsanaのAPIを叩き、定期的にGoogle Sheetsにインポートしてバーンアップチャートを構築する

AsanaのAPIを使って引っ張ってくる手法。これは更新は全自動でよいし、インポート後にExcel技を使えるのも良かったのだけど、初回のセットアップが面倒で、Asanaのプロジェクトを作るたびにシートの用意が必要。
うちのチームでは、早ければ数週間で終わる単位のプロジェクトをどんどん作る使い方をしているので、Asanaのプロジェクト構築時の手間もなるべく楽にしていきたい。

落書き

Scrapboxにスクショを貼って、ハンドドローイングで落書きして終了日を予測する手法。

職人技

お手軽だし、もうこれでいいんじゃない?という気持ちもあったのだけど、個人のドローイング能力に依存するので結果が安定しない、結果の安定を求めて練習していくと、やっていることが家紋レンダリング職人にだんだん近づいていく、という課題があった。

「同じ色で家紋を6つ並べる。なかなか描けるものじゃない。長年やれば自然とできるようになるんだけど」

すーっと紋章上絵師 / 日本仕事百貨

バーンアップチャート構築を楽にしたい

個人的には、日常的に繰り返す工程は楽になってほしいし、可能なら自動化して0クリックになってほしい。
バーンアップチャートの構築と更新を自動化して、予測線を自動的に引いて、いつ終わりそうか、誰が見ても明らかで、解釈のブレがないようにしたい、と思って、試行錯誤していた。

画像解析

Google Colaboratoryを使うと、OpenCVを呼び出せる。
スクショからラインを2本検出したら自然と予測線になるのでは?と思ったけどそんなに甘い世界じゃなかった。
ちょっと調べてでてきたサンプルのプログラムを動かしてみると、前処理としてグレイスケールにする時点で片方の線が消え去ってしまったり、線分はみつけられてもグラフの端の縦棒が検出されたりと、みつけたい特徴をうまく与えないと、期待する結果は得られない。

うまくいかない様子

日付の文字に含まれる無数の線分が検出されたところで、この手法では道のりが長そうと思って、すぐに断念した。普段から画像解析に慣れてる人ならすんなりできるだろうと思う。
もし動いたとしても、これをどう自動化するのか?という課題は残る。
ただ、今回採用した案(後述)よりは、画像を直接見ている分、うまくいけばAsanaじゃなくても動きそうで、それっぽいグラフさえあれば予測できるという、どこでも使える夢の技術っぽさはある。写真を送るとバーンアップチャートっぽい部分をみつけて、どんな画像であっても、いつ終わりそう、とか教えてくれるbotを作れるとおもしろいと思う。

SVGをパースして落書きする

いろんな手法を試すうちに、Asanaの画面内に直接見えるようにするのが一番手っ取り早いだろうと考え始めた。
勝手に書いたJavaScriptを動かして、Asanaのダッシュボードの画面内に完了予想日を描画させたい。

Asanaのダッシュボードに表示されているグラフはSVGで作られているようだった。
SVGはベクタ画像で、下に貼ったのはMDNから持ってきた例だけど、pathという線分をあらわす要素のd属性の中に、どこからどこにこういうカーブで移動するよ、という命令が記されている。これをパースすればよい。

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <path fill="none" stroke="red"
    d="M 10,30
       A 20,20 0,0,1 50,30
       A 20,20 0,0,1 90,30
       Q 90,60 50,90
       Q 10,60 10,30 z" />
</svg>
https://developer.mozilla.org/ja/docs/Web/SVG/Attribute/d

SVGを読んでこの先の展開と完了日を予測する、というのを機械的にやるとしたら、こんな手順。

  1. 画面内のバーンアップチャートをあらわすSVGを探して、順に見ていく
  2. SVG内のグラフのpathのd属性の値をパースして、数字の推移を抜き出す
  3. 先頭の変化のない部分は開発が始まる前の期間だとみなしてデータを捨てておく
  4. 完了済みポイントは今後も線形に伸びると想定して、線形回帰して、pathを追加してレンダリングする
  5. 総ポイントは今後増えないものと想定して、pathを追加して線を引く
  6. 2本の線の交点が完了予測日なのでcircleでプロットする
  7. 交点はだいたい画面外に飛び出てしまうので、SVGのviewBox属性を書き換えて、交点が見えるくらいに縮小表示する


これをJavaScriptで実装して、実行するとこの通り。
Asanaのダッシュボード内のバーンアップチャートに勝手に線と円が追加されて、このペースで開発が進むといつ終わりそうかが可視化される。このペースで行くとグラフの端から1.5ヶ月後の、11月中旬くらいに終わりそう、と読み解ける。

予測成功


いますぐお試しいただけるChrome拡張がこちら。
これをインストールしてAsanaの適当なダッシュボードを開くだけで、バーンアップチャートに予測機能が追加される。当初の目論見通り、0クリックで使える。
chrome.google.com

どこかにuser.jsをぽんと置いといて配布、で済めばよかったのだけど、同僚のPCに1クリックでインストールしてもらうためには、Chrome拡張にするのがよさそうだった。
最近は審査があって、適当に1行説明を書いて出したら2〜3回リジェクトされてしまった。画像を貼って、このグラフはこう読むんです、という説明を書いたら、ようやく通してもらえた。
Chrome拡張のソースコードはこちら。
github.com

同じものがHatena::Letにもある。
最初、CSPに阻まれて動かなかったのだけど、実験的機能の@javascript_urlで回避できると教えてもらえた。
ページの内容を読みに来るChrome拡張を入れるのは不気味、という人は、こちらのほうがまだ手動実行なので抵抗が少ないかもしれない。
let.hatelabo.jp

感想

他人の書いたSVGを機械的に読む、というと、数字をめちゃくちゃに書き換えてグリッチさせる、くらいしかやったことなかったのだけど、意味ある情報を抜き出して、ちゃんと動いたので満足度が高い。
交点が具体的にいつなの?というラベルのプロットもしたいのだけど、X軸のラベルが6/28みたいな日付だったり、Octという月単位だったりバラバラなので、テキストの列からヒューリスティックに次の日付を求める実装が必要そうになって、まだ手を出せていない。何パターンか用意すれば終わりのはずだと思うので、そのうちやりたい。

実装を読むと分かるのだけど、highcharts-tracker-lineクラスのついた要素を探す、とかやっているので、Asana側のマークアップがすこしでも変われば壊れてしまう。
そういう儚い方法で実現されているので、頻繁に壊れたり直したりが発生するはずで、こんなに壊れるならポチポチクリックしてGoogle Sheetにインポートしたほうがトータルでは工数が少なかったね、となるかもしれない。
でも、どちらか選べるなら、楽になる見込みなく手作業で定期的にコツコツやる人生じゃなくて、壊れてない間は全自動で最高、という、瞬間的な享楽を求めていく人生をおくりたいと思う。