| @技術/プログラミング

jikoku with BitBar

BitBar で私家版通勤タイマー (2) - portal shit! の続き。

時刻表を JSON 化した奴を食わせて 60 分以内(まえの記事では 30 分以内にしてるけど 60 分以内に変えた。パラメーターで調整できるようにすると良さそう)の次の電車一覧と発車時刻までの分数を表示できるようになった。あとはこれを BitBar で扱えるようにする。以下のようなシェルスクリプトを用意した。 BitBar をインストールして pupjq をインストールし、 go get github.com/morygonzalez/jikoku した上で以下のようなシェルスクリプトを ~/bitbar/jikoku.1m.sh という名前で保存すればよい。

#!/bin/sh
export PATH="$HOME/bin:/usr/local/bin:/usr/bin:/bin:$PATH"

echo ":train:"
echo "---"

go_filter=""
return_filter="筑 西 唐"
go_base="http://transit.yahoo.co.jp/station/time/28074/?gid=2480"
return_base="http://transit.yahoo.co.jp/station/time/28236/?gid=6400"

day=`date "+%a"`
hour=`date "+%H"`

if [ $hour -lt 13 ]; then
    go=true
else
    go=false
fi

case ${day} in
    "Sun")
        kind=4
    ;;
    "Sat")
        kind=2
    ;;
    *)
        kind=1
    ;;
esac

if [ $go = true ]; then
    url="${go_base}&kind=${kind}"
    path="/tmp/jikoku_go_${kind}"
    filter=$go_filter
    echo "Go | href=$url"
else
    url="${return_base}&kind=${kind}"
    path="/tmp/jikoku_return_${kind}"
    filter=$return_filter
    echo "Return | href=$url"
fi

if [ ! -f ${path} ] && [ ! -s ${path} ]; then
    curl -s ${url} -o ${path}
else
    current=`date +%s`
    last_modified=`stat -f "%m" ${path}`
    if [ $(($current - $last_modified)) -gt 3600 ]; then
        curl -s ${url} -o ${path}
    fi
fi

echo "---"

cat ${path} |\
    pup 'table.tblDiaDetail [id*="hh_"] json{}' |\
    jq '[.[] | { hour: .children[0].text, minutes: [.children[1].children[].children[].children[].children[].children | map(.text) | join(" ") ] }]' |\
    jikoku -f "${filter}"

echo "---"
echo "Refresh | refresh=true"

go_base には往路の、 return_base には復路の Yahoo! 乗換案内時刻表の URL が入る。 go_filterback_filter はユーザーごとに行き先を絞り込みたいだろうから(自分の場合は福岡市地下鉄の JR 筑肥線直通電車だけを絞り込みたかったので行き先表示に「筑」「西」「唐」が含まれるものだけがフィルタリングされるようにした。BitBar はファイル名を 1h.sh1m.sh とすることで 1 時間おきの実行や 1 分おきの実行など実行間隔を指定できる。

ちなみに当初は 5m.sh にしていたが、次の列車までの時間を表示するソフトが 5 分おきに実行とかだったらまずいことに気がついた。メニューバーで確認してまだ余裕だと思ってたら間に合わなかったみたいな事態になる。毎分処理が走らなければ意味がない。毎分実行しても問題ないよう( Yahoo! 乗換案内に迷惑をかけないよう)、時刻表を一時間キャッシュするようにした。もっと長期間キャッシュしても良いのだろうけど、 13 時を境に往路と復路を切り替えるようにしているので、まぁ 60 分もキャッシュすれば十分サーバーリソースにやさしいかなと思い、このような作りにしている。

最初は curlpupjq を組み合わせて簡単に作れないかな、と思ってやり始めて意外と簡単にできそうだと思っていたけど結局は結構複雑になってしまった。 Go で書いた jikoku コマンドの方も複雑かつ終電後の翌朝始発を考慮できていなくていまいち感がある。時刻表は平日と土曜、日曜祝日で異なるので安易に当日のデータを翌日のデータとして使い回せない(曜日判定しないといけない)。たとえば金曜日の終電後に翌朝の始発を金曜日の時刻表を使って表示してしまうとまずい。ちゃんと土曜日の時刻表を使わないといけない。しかし時刻表自体は curl で HTML を取得して pupjq で JSON に整形しているので、翌日の時刻表が必要になっても Go コマンドの方からはどうしようもない。

  • 時刻表の HTML を取得 (いまは curl でやってる)
  • HTML から必要な要素を取り出す (いまは pup でやってる)
  • 取り出した情報を使いやすい形式に直す (いまは pupjq でやってる)
  • 次の電車を表示する (いまは自作の jikoku コマンドでやってる)

という四つのステップを全部 Go でやった方がよいのかもしれない。そもそも jq 職人だったら jikoku コマンドみたいなものは不要で、次の電車を表示するところまで jq でできてしまうのかもしれない。

ちょっともやっとした感じは残ったけどなかなか便利ですのでよかったらご利用ください。

なお pupjq に依存してますんでインストールが必要です。

brew install pup
brew install jq

| @技術/プログラミング

BitBar で私家版通勤タイマー (1) - portal shit! の続き。

JSON から情報を読み取って出力する奴は Ruby で書こうかなと思っていたんだけど、先日新しい上司と 1 on 1 をしていてどんな言語を使えるかの話になったときに Ruby と PHP とコールドフュ〜ジョン(と片手間 JavaScript )くらいしか使える言語がないということが判明してダメだと思ったので無理矢理 Go 言語で書いてみた。クソコードなので恥ずかしい。

package main

import (
    "encoding/json"
    "fmt"
    "os"
    "strconv"
    "strings"
    "time"
)

type Hour struct {
    Hour    string
    Minutes []string
}

func printLefts(m int, minutes []string, hour string) {
    for i := 0; i < len(minutes); i++ {
        mindes := strings.Split(minutes[i], " ")
        min := mindes[0]
        var Dest string
        if len(mindes) > 1 {
            Dest = mindes[1]
        }
        _m, _ := strconv.Atoi(min)
        left := _m - m
        if left > 0 && left < 30 {
            leftS := strconv.Itoa(left)
            takeM := fmt.Sprintf("%02d", _m)
            Str := leftS + " minutes left to " + hour + ":" + takeM
            if Dest != "" {
                Str = Str + " " + Dest
            }
            fmt.Println(Str)
        }
    }
}

func main() {
    decoder := json.NewDecoder(os.Stdin)
    timetable := make([]Hour, 0)
    decoder.Decode(&timetable)
    t := time.Now()
    h := t.Hour()
    m := t.Minute()
    var CurrentHour, NextHour Hour
    for i := 0; i < len(timetable); i++ {
        hour := timetable[i]
        _h, _ := strconv.Atoi(hour.Hour)
        if _h == h {
            CurrentHour = hour
            NextHour = timetable[i+1]
            break
        }
    }
    minutes := CurrentHour.Minutes
    printLefts(m, minutes, CurrentHour.Hour)
    if m > 44 {
        nextMinutes := NextHour.Minutes
        printLefts(m-60, nextMinutes, NextHour.Hour)
    }
}

こんな感じに表示される。

私家版通勤タイマー

あとはこれを BitBar で良い感じに読めるように出力内容を調整していけば良い。

Go 言語、 2 年くらい前に gyowitter っての作って Yo が来たら Twitter に晒すってのやってた以来に触った。変数のスコープとかがわかりづらかったし、 PHP っぽい雰囲気もある。やっぱり Ruby の方が書きやすいし好きだけど歯を食いしばって使ってみる。

| @WWW

マイコミジャーナルにTumblrの紹介記事が掲載されたらしい。しかし内容がピント外れ気味らしく、ちょっと違うんじゃね、という意見がリブログされてるのをDashboardで読んだ。

僕もマイコミジャーナルの当該連載記事を読みにいったんですけど、2年前にTwitterとTumblrが紹介され始めた頃によく読んだ記事とさほど内容は変わらない感じで、これじゃTumblrの楽しさは伝わらんだろうなーと思いました。

かくいう自分自身、ほんのひと月前までTumblrの面白さは分かってなかった。とにかくキモなのは、Firefox + Greasemonkey + AutoPagerize + Minibuffer + LDRize + Tomblooが必須だということです。これらのツールについて触れてなかったらTumblrを紹介したことにはならないんじゃないかな。Tumblrの中の人は想定してなかっただろうけど、これらのAdd-on、Greasemonkeyスクリプトが無かったら、Tumblrの性格はまったく違っていたものになったと思う。少なくとも僕にとってはそう。ユーザーサイドのハックやツールがウェブサービスを規定する例の典型だと思う。

Tumblrは何が面白いのか?

僕は最初Tumblrを始めた頃は、画像をポストしたりポエムを書いたりしてたんですけど、これはいま思うと使い方間違ってたと思う。Tumblrはポエムを綴る場じゃなくて、人をフォローして「Dashboardを掘る場」なんですよね。

これも最近Dashboardで読んだんですけど、こういう記事があった。

tumblrの凄いのはfollow。followは情報ではなく、人に対しての行為。ブログをRSSリーダーに登録する行為に似ているのですが、ブログは前述のようにインプット・消化・アウトプットの一連の流れの結果がRSSに出力されるわけですが、tumblrはひたすらインプット。入力情報だけになっているのが特徴。

だからDashboardには私がfollowしているエージェント(笑)からの秘密情報がタップリ流れてくるのです。エロ画像から世界情勢まで、それはもう幅広いです。スポーツ新聞や夕刊紙なんてメじゃないです。

tumblr:情報過多で情報発信とのバランスシートが崩れてる ([の] のまのしわざ)

最後の スポーツ新聞や夕刊紙なんてメじゃないです ってところがこの文章のキモですね。はっきり言って、書店に並んでる雑誌とかつまんないと感じられるくらい、Tumblrは圧倒的な質と量の情報を浴びることが出来る。北朝鮮のミサイル関連だったら、誰かがその道の専門家のブログから引用してきた文章を、NHKの速報を見ながら読むことができる。雑誌だったら数日から一週間経ってからしかフォローできない内容を、Tumblrはリアルタイムでフォローしてくれるのです。ここが凄い。

Tumblrはネット全体を対象にしたふぁぼったーのようなもの

ある程度Twitterを使ってる人なら分かると思うけど、Twitterはポストするだけじゃなく、スターを付ける(ふぁぼる)という行為も楽しいんですよね。DJがレコードを掘るのに近い感覚。「こんな面白いポスト見つけてきたぜー」っていうの。この対象をWeb全体に拡張したのがTumblrだと僕は思ってます。

そう、最近つくづく思うことなんですけど、Tumblrはインターネット全体を対象にしたふぁぼったーなんですよね。ブログなどウェブコンテンツのキモの部分を引用してきて、「ほれどうだ!」とDashboardに投げかける。それをReblogするのはTwitterでスター付ける(ふぁぼる)のに似た感覚。「あ、これいい」という賛意を示す感覚で僕はReblogしてます。

だからむかし TumblrにReblogする人って後から見直すのかね みたいな記事を書いたけど、これは的外れなわけですね。一ヶ月ほどどっぷり浸かってみて得られた結論だけど、Tumblrは情報をクリップしといてアーカイブする場所じゃない。刹那的にどんどん情報を浴びまくる場所ですね。

尽きることのないネタの宝庫

とにかく、面白い情報をReblogしてる人をFollowすれば、ロシアのフリーダムな掲示板にポストされてるポルノ画像から政界や芸能界の裏話、最新のニュース、Wikipediaのマニアックな部分の記述など、ネタがザクザク出てくる。僕は一時期はTwitterにハマってましたけど、いまはすっかりTumblrアディクトです。

決して万人にはお勧めしません。時間を無駄に過ごすことが怖くない人だけ、Tumblr始めてみてください。これまでになかったウェブの世界が眼前に広がります。