2011年11月13日日曜日

CoffeeScriptを学ぶ(2)

JavaScriptはプロトタイプベースのオブジェクト指向だったので、
クラスという概念はなかったのですが、
CoffeeScriptには、クラスという概念があります。
  1. class Hello  
  2.   method:  ->  
  3.     alert "hello"  
"class クラス名"でクラスを宣言できます。
メソッドは、クラスのブロックで
メソッド名: (引数) ->
  メソッド本体
と書きます。

これをJavaScriptに変換すると、下記のようになります。
  1. var Hello;  
  2.   
  3. Hello = (function() {  
  4.   function Hello() {}  
  5.   Hello.prototype.method = function() {  
  6.     return alert("hello");  
  7.   };  
  8.   return Hello;  
  9. })();  

CoffeeScriptのページのサンプルの例を持ってくると
  1. class Animal  
  2.   constructor: (@name) ->  
  3.   
  4.   move: (meters) ->  
  5.     alert @name + " moved #{meters}m."  
Animalとうクラスです。
コンストラクタは "constructor:"で定義できます。
@xxxはインスタンス変数ですね。
ちなみに#{}を使えば、文字列のなかで変数を評価して値を使用できます。(Rubyと同じ構文ですね。)
  1. class Snake extends Animal  
  2.   move: ->  
  3.     alert "Slithering..."  
  4.     super 5  
  5.   
  6. class Horse extends Animal  
  7.   move: ->  
  8.     alert "Galloping..."  
  9.     super 45  
継承はextendsを使います。
superでスーパークラスのメソッドを呼び出すことができます。

やっぱりクラスを使うと、比較的大きなコードを書くときは、考えやすくて便利ですよね。

CoffeeScriptを学ぶ

CoffeeScriptはJvaScriptに変換するための言語で、
Pythonのような文法を持っているのが特徴のようです。

このCoffeeScriptを学ぼうと思い、いくつかのサンプルを書いてみました。
まず基本、FizzBuzzです。
(下記はalertで書いたので実行すると大変なことになるから気をつけてね)
  1. for a in [1..100]  
  2.   if a%15 == 0  
  3.     alert "FizzBuzz"  
  4.   else if a%3 == 0  
  5.     alert "Fizz"  
  6.   else if a%5 == 0  
  7.     alert "Buzz"  
  8.   else  
  9.     alert a  
特徴としては、Pythonのようにインデントがブロックを表しています。
インデントでブロックにすると、やっぱり見やすいですよね。
また、メソッドも()がつかないです。

これをJavaScriptに変換すると、以下のようになります。
  1. var a;  
  2.   
  3. for (a = 1; a <= 100; a++) {  
  4.   if (a % 15 === 0) {  
  5.     alert("fizzbuzz");  
  6.   } else if (a % 3 === 0) {  
  7.     alert("fizz");  
  8.   } else if (a % 5 === 0) {  
  9.     alert("buzz");  
  10.   } else {  
  11.     alert(a);  
  12.   }  
  13. }  
今度はクイックソートを実装してみます。 関数は
関数名 -> (引数)
   (関数本体)
のです。 CoffeeScriptはwhile文が使えます  
  1. sort = (array, l, r) ->  
  2.   mid = ~~(l+r/2)  
  3.   return if l >= r  
  4.   i = l  
  5.   j = r  
  6.   pivot = array[mid]  
  7.   while true  
  8.     while array[i] < pivot  
  9.       i++  
  10.     while array[j] > pivot  
  11.       j--  
  12.     break if i >= j  
  13.     t = array[i]  
  14.     array[i] = array[j]  
  15.     array[j] = t  
  16.   sort array, l, i-1 if l < i-1  
  17.   sort array, j+1, r if j+1 < r  
  18.   
  19. a = [1, 4, 3, 7, 6, 5, 2, 8]  
  20. sort a, 0, 7  
  21. alert a  
下記はJavaScriptに変換したときのコードです。
  1. var a, sort;  
  2.   
  3. sort = function(array, l, r) {  
  4.   var i, j, mid, pivot, t;  
  5.   mid = ~~(l + r / 2);  
  6.   if (l >= r) return;  
  7.   i = l;  
  8.   j = r;  
  9.   pivot = array[mid];  
  10.   while (true) {  
  11.     while (array[i] < pivot) {  
  12.       i++;  
  13.     }  
  14.     while (array[j] > pivot) {  
  15.       j--;  
  16.     }  
  17.     if (i >= j) break;  
  18.     t = array[i];  
  19.     array[i] = array[j];  
  20.     array[j] = t;  
  21.   }  
  22.   if (l < i - 1) sort(array, l, i - 1);  
  23.   if (j + 1 < r) return sort(array, j + 1, r);  
  24. };  
  25.   
  26. a = [1, 4, 3, 7, 6, 5, 2, 8];  
  27. sort(a, 0, 7);  
  28. alert(a);  

2011年11月1日火曜日

第22回HTML5とか勉強会で発表してきました

第22回HTML5とか勉強会で発表してきました。

今回は初心者向けということで、
SVGってどんなことができるの?っていることを理解してもらおうと思い、
とにかく仕様の紹介をしようと思いました。
ちょっと、意図が伝えられなくて、一部の方からは難しかったというご意見をいただきました。
次回同じような機会があれば、その反省をふまえてもっとよい発表を行えればと思っています。

以下が発表に使用したスライドです。


動画も公開されているみたいです。



このような機会を与えていただいた白石さんをはじめHTML5とか勉強会のスタッフの皆様には
本当に感謝をしています。
ありがとうございました!

2011年8月15日月曜日

OAuthの仕組みについてのメモ

ちょっと前に
twitterのOAuth認証についてのエントリを書きましたが、
ちょっとOAuthについて自分の頭の中が整理できていなかったので、
ちょっと整理します。

OAuthってそのそも、

  • アプリケーションがとあるサービスのAPIを使うための、ユーザに認証してもらうための仕組み

  • アプリケーションはとあるサービスのユーザ名やパスワードをユーザから教えてもらう必要がない


  • です。

    で、
    API提供しているとあるサービスとあるサービス => Service Provider
    アプリケーション => Consumer
    
    とそれぞれ呼びます。

    Consumer(アプリケーション)はService Provider(API提供しているとあるサービス)にConsumerの登録を行います。
    登録すると、Consumer KeyとConsumer Secretが発行されます。Consumer Key/Secretはそのアプリケーションを示すトークンです。このConsumer(アプリケーション)はConsumer Key/Secretを使って、Service Providerにリクエストトークンを発行してもらいます。

    リクエストトークンを発行してもらったら、ConsumerはそのリクエストトークンをパラメータとしたURLを使って、Service Provicerのサイトにリダイレクトを行います。

    ユーザーはリダイレクトされたサイト上にて、ConsumerがService ProviderのAPIを使って情報を取得するのを許可します。

    許可したら、Service Providerはあらかじめ登録されたURLへリダイレクトするので、
    Consumerはそこから、アクセストークンをService Providerに要求し、Service ProviderはアクセストークンをConsumerに送信します。

    このアクセストークンがあれば、ConsumerがService ProviderのAPIを使うことができるようになります。

    ざっと書くとこんな感じでしょうか?

    2011年8月7日日曜日

    第1回Androidテスト祭り に行ってきました。

    第1回Androidテスト祭り に行ってきました。
    行ってきましたと言っても、途中から実行委員にまぜてもらったので、
    スタッフとして参加させていただきました。

    ATNDの参加希望者が定員の倍以上になってしまい、
    Androidでの品質の確保については、たくさんの人が関心を持っているのだと思います。
    (困っている人が多いってことですね><) 今回の発表は非常にレベルが高く、 参加していただいた方々の満足度も高かったのではないかと思います。 個人的には、尾上さんの「テスト可能なUI設計パターン」 が勉強になりました。 ちなみに、僭越ながら私も懇親会でLTをしてきました。 スライドは下記になります。
    講演者の皆様、ご来場していただいた皆様、Ustreamを視聴していただいた皆様、本当にありがとうございました。

    2011年8月4日木曜日

    Jenkinsのインストールのメモ

    Jenkinsのインストールのメモ。あくまでもメモです。

    自宅のサーバーがDebianなので、それを使って。

    まず最初にコマンドラインで、
    wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | apt-key add -
    
    をしたあと、
    /etc/apt/sources.listの末尾に
    deb http://pkg.jenkins-ci.org/debian binary/
    
    を追加します。

    その後
    apt-get update
    apt-get install jenkins
    
    をして、インストールします。

    設定に関しては、
    /etc/default/jenkins
    をいじった後、
    /etc/init.d/jenkins restart
    
    をします。

    /etc/default/jenkins
    は、たとえばポートを変えたい時は、HTTP_PORTを帰ればいいです。
    私は、URLに /jenkins を加えたかったので、
    JENKINS_ARGS に --prerix=/jenkins を加えました。

    詳しくは、ここを見るといいかもしれません。

    URLにアクセスすると
    (例えば、http://localhost:8080/jenkins)

    が出てくるはずです。
    デイリービルド等ジョブを作成したい時は、「新規ジョブ作成」を選んでください。

    のページに遷移しますので、
    適当なジョブ名を入力して、基本的にフリースタイル・プロジェクトのビルドを使います。

    あとは、下記の画面が出てくるので、適当に入力していってください。

    2011年7月20日水曜日

    HTML5のpushState

    HTML5には、
    HistoryオブジェクトにpushState()とreplaceState()というメソッドが追加されました。

    pushStateというのは、
    Historyのリストに新しくエントリを追加してしまいます。
    ページ遷移をしていなにのに、Hisotryが追加されるのです。

    下記にコードを示します。
    1. <html>  
    2. <head>  
    3. <script>  
    4. function push_history() {  
    5.   history.pushState("", "", "/example");  
    6. }  
    7. </script>  
    8. </head>  
    9. <body>  
    10. Hello, World!  
    11. <form>  
    12. <input type="button" value="button" onclick="push_history()" />  
    13. </body>  
    14. </html>  

    これにより、
    現在のページが "http://foo.com/hello/index.html " だった場合、
    ボタンをクリックするとURLが第3引数により、"http://foo.com/example" に変化しており、
    戻るのリストをみると、1個Historyが追加されているのがわかります。
    実際に戻るをクリックすると、URLバーが
    "http://foo.com/hello/index.html "
    に戻ります。

    これで、ページを遷移していないのに、
    Historyにエントリを追加して、URLを変更することができます。

    Ajaxとこれを組み合わせた技術を "Pjax" と呼びますが、
    これは別途まとめようと思います。

    twitterのOAuth認証

    OAuthっていうのは、
    APIを使用する認証を行うための仕様のことで、
    パスワードを第3者に教えることなく、トークンのやり取りだけで認証が行えるしくみのことです。

    OAuthってなんなのかは、
    ゼロから学ぶOAuthが参考になるとおもいます。

    で、実際にtwitterでOAuth認証をおこなって、
    つぶやくためのスクリプトを書きました。

    まず、
    http://dev.twitter.com/apps/
    でアプリケーション登録を行います。
    (登録には、twitterアカウントが必要です。)
    で。Consumer Keyと Consumer Scretを取得します。

    で、rubyのOAuthライブラリを使って、
    下記のコードを書きました。

    1. #!/usr/bin/ruby  
    2. require 'rubygems'  
    3. require 'oauth'  
    4.   
    5. consumer = OAuth::Consumer.new(  
    6.   "Consumer Key",  
    7.   "Consumer Secret",  
    8.   :site => "http://twitter.com"  
    9. )  
    10. token = consumer.get_request_token  
    11. puts token.authorize_url #リダイレクト先のURL  
    12. pin = gets.chop  
    13. access_token = token.get_access_token(:oauth_verifier => pin)  
    14. puts access_token.token #アクセストークン のtoken  
    15. puts access_token.secret # アクセストークンの secret  

    token.authorize_url のURLをブラウザに貼付けてページ遷移すると、
    リダイレクト先にpinコードが書いてあるので、
    それをコピーして入力します。

    そうすると、Accessトークンを取得することができます。

    CosumerトークンとAccessトークン
    あとは、twitterライブラリあたりで、
    twitter APIを叩けばOKです。
    以下は、ただ、"Hello, World" をつぶやくスクリプトです。

    1. #!/usr/bin/ruby  
    2. require 'rubygems'  
    3. require 'twitter'  
    4. require 'twitter/console'  
    5.   
    6. Twitter::Client.configure do |conf|  
    7.   conf.oauth_consumer_token = "Consumer Key",  
    8.   conf.oauth_consumer_secret =   "Consumer Secret",  
    9. end  
    10.   
    11. twitter_client = Twitter::Client.new(:oauth_access => {  
    12.   :key => "Access Token Key",  
    13.   :secret => "Access Token Secret"  
    14. })  
    15.   
    16. twitter_client.status(:post"Hello, World");  

    2011年6月14日火曜日

    ATECで発表してきました。

    大分前になってしまいますが、
    ATEC(Android テスト部)で発表してきました。

    ATECでやっているテストをつくるためのAndroidアプリである
    testterに関してです。
    @nowsprintingさんと共同でやってきました。

    以下がプレゼン資料です。


    @nowsprintingさんの資料も下記に載せておきます。


    もし興味がある方は、是非、ATECにご参加ください。
    https://sites.google.com/site/androidtestclub/

    2011年5月2日月曜日

    Objective-Cを学ぶ

    以前Objective-Cについて書きましたが、
    改めてObjective-Cの書き方をざっとまとめてみます。
    下記がわかれば、だいたいソースコードを読めるのではないかと・・・自身ないけど。

    .hファイル
    1. @interface クラス名 : 親クラス名 {  
    2.     int member1;  
    3.     (メンバ変数)  
    4. }  
    5. - (返り値)メソッド1;  
    6. - (返り値)メソッド2:(引数型)引数  
    7. - (返り値)メソッド3_1:(引数型)引数1 メソッド3_2:(引数型)引数2  
    8. @end  
    .mファイル

    1. @implements クラス名  
    2. - (返り値)メソッド1  
    3. {  
    4.   メソッド1の処理  
    5. }  
    6.   
    7. - (返り値)メソッド2:(引数型)引数  
    8. {  
    9.   メソッド2の処理  
    10. }  
    11.   
    12. - (返り値)メソッド3_1:(引数型)引数1 メソッド3_2:(引数型)引数2  
    13. {  
    14.   メソッド3の処理  
    15. }  
    16. @end  

    メソッドの呼び出しは、
    1. [オブジェクト名 メソッド名:引数];  
    です。

    他には、
    ヘッダーの読み込み(includeではなくimport)
    1. #import <UIKit/UIKit.h>  
    他の場所で定義されたクラスの名前
    1. @class クラス名  
    があります。

    また、アクセッサとして、.hに
    1. @property (nonatomic, retain) UIWindow *window;  
    .mに
    1. @synthesize window;  
    と書けば、getter/setterメソッドを自動生成してくれます。


    1. @property (nonatomic, retain) UIWindow *window;  
    の nonatomic は atomicじゃないので、非同期処理は対応しない、 retainは代入したときに参照カウントを1増やして解放されないようにする、っていう意味っぽいです。

    2011年1月25日火曜日

    Erlangで行頭に行番号をつけるプログラムをつくってみた。

    なんとなくつくってみただけ。
    Erlangを普段の業務とかでどれだけ使えるかのテストをかねて。

    file_number.erl
    
    -module(file_number).
    -export([add_file_number/2]).
    
    add_file_number(Readfile, Writefile) ->
      {OK, S} = file:open(Readfile, read),
      {OK, T} = file:open(Writefile, write),
      X = 1,
      read_line(S, T, X),
      file:close(T),
      file:close(S).
    
    read_line(S, T, X) ->
      case io:get_line(S, '') of
        eof ->
          ok;
        Line ->
          io:format(T, "~w~s~s", [X, " ", Line]),
          read_line(S, T, X+1)
      end.
    

    実行してみる
    
    1> c(file_number).
    {ok,file_number}
    2> file_number:add_file_number("test.dat", "test2.dat").
    ok
    

    一応
    行番号がつくこと確認。

    そんだけ。

    2011年1月13日木曜日

    [android]Adapterって何?

    Androidでは
    ListViewやGallery等で
    ArrayAdapterのようなXXXAdapterというものを使用しますが、
    このAdapterとは、いったい何なんでしょうか?

    AdapterというのはViewとデータの橋渡し役で、
    Viewに必要なデータを渡してあげる役割があります。
    例えば、
    getCount()は、Viewに必要なitemの数、
    getItem()は、対応するObjectを返す関数です。
    getViewは、Listのアイテムのように、それぞれのitemに対応するView
    を作って返します。

    以下は、AKB48の総選挙の結果を7位までリスト表示するプログラムです。

    HelloListActivity.java
    
    package jp.android.hellolist;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.ListView;
    
    public class HelloListActivity extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            
            ListView view = (ListView)findViewById(R.id.list_view);
            HelloListAdapter adapter = new HelloListAdapter(this);
            view.setAdapter(adapter);
        }
    }
    

    HelloListAdapter.java
    
    package jp.android.hellolist;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.TextView;
    
    public class HelloListAdapter extends BaseAdapter {
        private LayoutInflater inflater;
        private AKBData data;
    
        public HelloListAdapter(Context context) {
            inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            data = new AKBData();
        }
    
        @Override
        public int getCount() {
            return data.getSize();
        }
    
        @Override
        public Object getItem(int position) {
            return data.getItem(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.list, null);
                TextView tv1 = (TextView)convertView.findViewById(R.id.TextView01);
                tv1.setText(Integer.toString(position + 1));
                TextView tv2 = (TextView)convertView.findViewById(R.id.TextView02);
                tv2.setText(data.getItem(position));
            }
            return convertView;
        }
    
    }
    

    AKBData.java
    
    package jp.android.hellolist;
    
    import java.util.ArrayList;
    
    public class AKBData {
        private ArrayList list;
    
        public AKBData() {
            list = new ArrayList();
            list.add("大島優子");
            list.add("前田敦子");
            list.add("篠田麻里子");
            list.add("板野友美");
            list.add("渡辺麻友");
            list.add("高橋みなみ");
            list.add("小嶋陽菜");
        }
        
        public int getSize() {
            return list.size();
        }
    
        public String getItem(int index) {
            return list.get(index);
        }
    }
    

    main.xml
    
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
    <ListView  
     android:id="@+id/list_view"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        />
    </LinearLayout>
    

    list.xml
    
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 
     android:id="@+id/LinearLayout01"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:orientation="horizontal"
     xmlns:android="http://schemas.android.com/apk/res/android">
     <TextView 
      android:text="@+id/TextView01"
      android:id="@+id/TextView01"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginRight="10dip" />
     <TextView
      android:text="@+id/TextView02"
      android:id="@+id/TextView02"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content" />
    </LinearLayout>
    

    実行結果

    2011年1月10日月曜日

    [android]androidのアプリをHTMLで作れるようにする

    androidのアプリケーションから
    ローカルに保存してあるHTMLを表示させるアプリのサンプルを作ってみました。
    WebViewのaddJavascriptInterface()をつかえば、
    Javascript から Androidのメソッドを呼び出すこともできます。

    ローカルにおくためのHTMLは、
    assetsフォルダに保存しておけば、file: でアクセスできます。
    (assets/index.htmlだったら、file://android_asset/index.htmlでアクセスできる)

    サンプルです。
    HelloHTMLActivity.java
    
    package jp.android.hellohtml;
    
    import android.app.Activity;
    import android.content.Context;
    import android.os.Bundle;
    import android.os.Vibrator;
    import android.util.Log;
    import android.webkit.WebView;
    import android.widget.Toast;
    
    public class HelloHTMLActivity extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            WebView wv = new WebView(this);
            wv.getSettings().setJavaScriptEnabled(true);
            MyJSObj jsobj = new MyJSObj(this);
            wv.addJavascriptInterface(jsobj, "myobj");
            setContentView(wv);
            
            wv.loadUrl("file:///android_asset/index.html");
        }
        
        class MyJSObj {
         private Context context;
         
         public MyJSObj(Context c) {
          this.context = c;
         }
         
         public void showToast(String str) {
          Log.d("tag", str);
          Toast.makeText(context, str, Toast.LENGTH_LONG).show();
         }
         
         public void vibration() {
          Vibrator vibrator = (Vibrator)getSystemService(VIBRATOR_SERVICE);
          vibrator.vibrate(2000);
         }
        }
    }
    
    addJavascriptInterface()は第1引数はjavascriptにバインドしたいオブジェクト、
    第2引数はjavascriptでアクセスするオブジェクトの名前を指定します。

    今回は、MyJSObjのメソッドにアクセスできるようにします。
    showToast() はただのtoastの表示、
    vibration() は2秒間振動します。

    Vibratorを使うときは、
    android.permission.VIBRATE
    の設定を忘れずに。

    index.html
    
    <html>
    <head>
    <title>test content</title>
    <script type="text/javascript">
      function showText() {
        myobj.showToast("test");
      }
      function vibration() {
        myobj.vibration();
      }
    </script>
    </head>
    <body>
    <div>hello</div>
    <input type="button" value="toast" onclick="showText();" />
    <input type="button" value="vibe" onclick="vibration();" />
    </body>
    </html>
    

    実行結果

    実行結果はただのHTMLですが、
    toastをクリックすればtoastがでて、
    vibeをクリックすれば、きちんと2秒間振動することを確認しました。