写真 青い空と雲と建物と木々の緑

nishimotzの日記

  • すごい広島 #4 で Twitter API の勉強

    すごい広島とは 広島のエンジニアやウェブデザイナーが毎週集まって、 もくもくしたり Hackしたり 読書したり する場所です。
    ということで、今週は第4回でした。
    NVDA の作業をしようかと思ったのですが、たまたま Twitter API 1.0 が今日終了したということで、あちこちでソフトやサービスが動かなくなったという話を聞き、久しぶりに Twitter API の勉強をしました。
    よく考えたら、Twitter API はなんどか使ったことがあるのでした。最初に勉強したのは Twitter4r という Ruby のライブラリでした。。
    まずは Apigee で Twitter API 1.1 を叩いてみます。OAuth 認証もやってくれて、JSON で情報が返ってきます。簡単ですね。。簡単すぎてつまらない。。
    The Qube というスクリーンリーダー対応の Twitter クライアントは Python で書かれていて Tweepy というライブラリに依存しているという話。
    なにかライブラリを試してみようか、ということで、調べたら Tweepy の他に Python Twitter というものが見つかりました。
    せっかくなので使ってみました
    が、タイムラインが取れて、ツイートができることは確認できたものの、GetFollowers などを使うと

    twitter.TwitterError: [{u’message’: u’Rate limit exceeded’, u’code’: 88}]

    になってしまい、うまくいかず。。
    そもそも Twitter で何をしたいのか深く考えてなかったので、久しぶりに音声対話アプリを書いてみました。
    書いたのはこんなコードです。
    Windows 8 でこのプログラムを起動して、「今日はWindowsで音声認識を使うプログラムを作りました」「コンピューターいまのをツイートして」といえば、Windows 内蔵の日本語音声認識と日本語音声合成で、下記のようにツイートができました。


    「コンピューターツイッターを読んで」といえばタイムラインを読んでくれます。
    Python でこういうライブラリを使うと HTTP も JSON も文字コード変換もほとんどお任せでいいから便利ですね。。
    静かな「もくもく作業の場」でひとりコンピューターに向かってしゃべり続けてしまい、すみませんでした。今度から突発的に音声認識アプリが書きたくなったときに備えて、常にヘッドセットを持参しようと思います。。
    最近は Mac OS X や Chrome ブラウザにも音声認識機能がついてたりしますが、Windows 8 はクラウドでなくコンピューターの中で音声認識と音声合成をしています。でも作ったものが Twitter アプリだから、やっぱりネットワークにつながってなくてはならないわけで、違いをアピールしにくいです。。
    今日は使いませんでしたが dragonfly – Python-based speech recognition framework – Google Project Hosting は SAPI と Dragon の音声認識APIラッパーらしいです。アプリケーションごとの音声コマンドのライブラリが充実している印象ですが、フレームワークがここまでやるとローカライズが大変かも。。
    ところで、今週土曜日にはNVDA広島勉強会を行います。よろしくお願いします。
    追記(6月14日)
    Twitter クライアントの Qube は無事に API 1.1 対応したそうです:

  • AngularJS と NVDA

    <htmlday> 2013 ということで AngularJS で遊ぼう という勉強会に参加しました。
    AngularJS は Web アプリケーション開発のフレームワークということで、簡潔に書けて保守性が高いのが特長、らしいです。
    しかし、生産性の高い開発手法という話を聞くと「それってアクセシビリティは大丈夫なの?」とつい思ってしまいます。
    そこで、angularjs.org のトップページのビデオで紹介されていた TODO アプリケーションのサンプルをスクリーンリーダー NVDA 日本語版 と Firefox の組み合わせで確認しました。
    書かれたマークアップは内部で標準的なHTMLに変換されているので、フォーカス移動などはちゃんとできるのですが、チェックボックスにフォーカスしたときに、その右側にある項目名を読み上げないので、何の操作をするチェックボックスなのかわかりません。
    ふと aria-labelledby でやればいいんじゃない? と思ったので、下記のように直したところ、うまくチェックボックスの項目名を読み上げるようになりました。
    最初は id をつけるために todos モデルに通し番号のプロパティを追加したのですが、後で $index という特殊プロパティがあることを教わったので、todo.js 側のコントローラーとモデルは書き換えないで実装できました。アクセシビリティのための処理が View だけで完結するのは素晴らしい。AngularJS なかなかよさそうなのでもうちょっと勉強してみたいと思います。
    <htmlday>とは、日本全国でWeb制作者/開発者向けのイベントを同日に開催することで、日本のWebを一層盛り上げようという「お祭り」だったそうで、私も貢献できればと思いブログを書きました。
    ちなみに広島市中心部は「とうかさん」というお祭りの季節です。。
    以下のソースでは bootstrap.cssUnderscore.js を使っています:

    <!doctype html>
    <html ng-app>
      <head>
        <script src="angular.js"></script>
        <script src="underscore.js"></script>
        <script src="todo.js"></script>
        <link rel="stylesheet" href="bootstrap/css/bootstrap.css">
        <link rel="stylesheet" href="todo.css">
      </head>
      <body>
        <h2>Todo</h2>
        <div ng-controller="TodoCtrl">
          <span>{{remaining()}} of {{todos.length}} remaining</span>
          [ <a href="" ng-click="archive()">archive</a> ]
          <ul>
            <li ng-repeat="todo in todos">
              <input aria-labelledby="label{{$index}}" type="checkbox" ng-model="todo.done">
              <span id="label{{$index}}">{{todo.text}}</span>
            </li>
          </ul>
          <form>
            <input type="text" ng-model="todoText"  size="30"
                   placeholder="add new todo here">
            <button ng-click="addTodo()"><i></i>Add</button>
          </form>
          <button ng-click="clearCompleted()"><i></i>Clear Completed</button>
        </div>
      </body>
    </html>
    // todo.js
    function TodoCtrl($scope) {
        $scope.todos = [
    	{text:'learn angular', done:true},
    	{text:'build an angular app', done:false}];
        $scope.addTodo = function() {
    	$scope.todos.push({text:$scope.todoText, done:false});
    	$scope.todoText = '';
        };
        $scope.remaining = function() {
    	var count = 0;
    	angular.forEach($scope.todos, function(todo) {
    	    count += todo.done ? 0 : 1;
    	});
    	return count;
        };
        $scope.archive = function() {
    	var oldTodos = $scope.todos;
    	$scope.todos = [];
    	angular.forEach(oldTodos, function(todo) {
    	    if (!todo.done) $scope.todos.push(todo);
    	});
        };
        $scope.clearCompleted = function() {
    	$scope.todos = _.filter($scope.todos, function(todo) {
    	    return !todo.done;
    	})
        };
    }
  • すごい広島 #3 に行って勉強した

    すごい広島とは 広島のエンジニアやウェブデザイナーが毎週集まって、 もくもくしたり Hackしたり 読書したり する場所です。
    ということで、今週は第3回でした。私は最初の参加(広島Git勉強会から数えて2回目の参加)です。
    たまたま「プロになるためのJavaScript入門」という本を読んでいるところなので、最初の文法の説明を「写経」することにしました。

    プロになるためのJavaScript入門 ~node.js、Backbone.js、HTML5、jQuery-Mobile (Software Design plus)
    河村 嘉之 川尻 剛
    技術評論社
    売り上げランキング: 88,262

    こまかい作業は私の Wiki サイト JavaScript のページに書いたのですが、例えば、なぜ下記のようなものが出てくるのか、いろいろ打ち込んでみてやっとわかってきました:

    > new String({})
    { '0': '[',
    '1': 'o',
    '2': 'b',
    '3': 'j',
    '4': 'e',
    '5': 'c',
    '6': 't',
    '7': ' ',
    '8': 'O',
    '9': 'b',
    '10': 'j',
    '11': 'e',
    '12': 'c',
    '13': 't',
    '14': ']' }

    丁寧に書くとこういうことですね:

    > new String(({}).toString())

    JavaScript では new Object は {} と書けるので、({}) は toString() すると “[object クラス名]” という形式の文字列リテラルが得られる。これを与えて String ラッパークラスに与えるので、その(文字列リテラルではない) String オブジェクトの内部表記である { ‘0’: ‘[‘, ‘1’: … のような結果が返ってくる。。
    前から読もうと思っていたCategorizing values in JavaScript という記事 がまさにこういう話だった。。
    こんなことをもくもくやっていたのですが、集まった人たちがそれぞれ、もくもく何かをやっている状況は、とても刺激的でよい雰囲気でした。
    この「すごい広島」は勉強内容は自由ですが、記録や報告に git/github や Markdown を使うルールになっています。共同作業の練習になるので、興味のあるかたはぜひ。