bit sized

Just another WordPress.com weblog

‘Technology’ カテゴリーのアーカイブ

Ubiquityを使って英単語を調べる

2件のコメント

FireFoxのプラグインでUbiquityというのがあります。他のWebサイトの機能をコマンドとして登録して使用できる、User MashUpを可能にするFirefox上の環境です。将来的にはFirefoxのURLバーに実装されるかも知れません(URLをWebのドキュメントがある場所であると考えるのではなく、Web上のリソースに対するリクエストような考えると割と自然な進歩?)。

ブラウザの新境地? Ubiquityが変える衝撃のブラウザ体験 (1/2):
http://www.itmedia.co.jp/enterprise/articles/0808/31/news003.html

まあ、そういうわけでどういうものかちょっと気になって見てみて、最近APIが公開されたiknowという英語学習SNSの単語検索を呼び出すコマンドを作成してみました。

iknow-search

iknow-search

コード

CmdUtils.CreateCommand({
  name: "iknow_search",
  icon: "http://example.com/example.png",
  homepage: "http://example.com/",
  author: { name: "xxxx", email: "xxxxx@gmail.com"},
  license: "GPL",
  description: "search words or pharase in iknow",
  help: "iknow",
  takes: {"input": noun_arb_text},
  preview: function( pblock, input ) {

    var baseUrl = "http://api.iknow.co.jp/items/matching/${word}.${format}";
    var tempUrl = {"word":input.text,"format":"json"}
    var params = {include_sentences:"true"};

    pblock.innerHTML = "";

    jQuery.getJSON(CmdUtils.renderTemplate(baseUrl,tempUrl),params,function(resp){
      jQuery.each(resp,function(i){
        pblock.innerHTML += this.responses[0].text + "<br/>";
        pblock.innerHTML += this.sentences[0].text + "<br/>";
        pblock.innerHTML += this.sentences[0].translations[0].text + "<br/>";
      });
    });

  },
  execute: function(input) {
    var baseUrl ="http://www.iknow.co.jp/items/search?keyword=${QUERY}";
    var tempUrl = {"QUERY":input.text};
    var urlString = CmdUtils.renderTemplate(baseUrl, tempUrl);
    Utils.openUrlInBrowser(urlString);
  }
});

Ubiquityコマンドの作成
Ubiquityコマンド作成の情報は、現状下記のリンクかソースを見るしかないくらい少なく、しかも上記のコマンドはまだプレビューで訳を表示しEnterキーでiKnowのサイトで該当のアイテム検索結果を表示するのみですが、行数の割には用を足しているかと思います。Ubiquity導入後、Command Editorを使用して上記のコードを貼付ければ使用できます。

Labs/Ubiquity/Ubiquity 0.1 Author Tutorial
https://wiki.mozilla.org/Labs/Ubiquity/Ubiquity_0.1_Author_Tutorial

上のチュートリアルに載っている事ですが簡単に作り方を説明したいと思います。

CmdUtils.CreateCommand({
  name: "hello-world",
  execute: function() {
    displayMessage( "Hello, World!" );
  }
})

ubiquityコマンドは、cmd_<コマンド名>というfunctionがあればそれを参照するのですが、普通はCmdUtils.CreateCommand()というユーティリティ関数を使用して作成します。上記のコードはその最も単純な例です。

CreateCommandに渡すオブジェクトのnameとexecuteというプロパティに、それぞれコマンド名の文字列と実行する関数を指定します。execute(コマンドの実行)はUbiquityのコンソールにコマンド名を入力しEnterを押した時点で実行されます。displayMessage()を実行すると、MacならGrowl,WindowsならUbiquityのコマンドの下に引数に与えた文字列が表示されます。

Hello-worlddisplay hello world

CmdUtilsにはコマンド作成以外にも、ユーザーがブラウザで選択中の箇所にテキストやHTMLを挿入(setSelection),IPから位置情報を取得(getGeoLocation),文字列のテンプレート処理(renderTemplate)などコマンド作成を楽にする関数が用意されており、これまたドキュメントは少ないのですが、ソースはこちらで見る事ができます。

プレビューの表示
Ubiquityではユーザーの入力に応じて出力されるプレビューウインドウがあり、こちらはCreateCommandに渡すオブジェクトのpreviewプロパティに、HTML文字列か関数を指定する事で実現できます。下記は冒頭のコマンドでのpreview部分です。

preview: function( pblock, input ) {

    var baseUrl = "http://api.iknow.co.jp/items/matching/${word}.${format}";
    var tempUrl = {"word":input.text,"format":"json"}
    var params = {include_sentences:"true"};

    pblock.innerHTML = "";

    jQuery.getJSON(CmdUtils.renderTemplate(baseUrl,tempUrl),params,function(resp){
      jQuery.each(resp,function(i){
        pblock.innerHTML += this.responses[0].text + "<br/>";
        pblock.innerHTML += this.sentences[0].text + "<br/>";
        pblock.innerHTML += this.sentences[0].translations[0].text + "<br/>";
      });
    });

  },.....

previewは第一引数にpreviewエリアに表示するDOM要素を、第二引数にユーザーから渡されるコマンドの引数をとっています。コマンドの引数はtakeプロパティで、どのnoun_typeで取得するか指定できます。

  takes: {"input": noun_arb_text},

引数データの扱い
noun_typeは引数の制約や、コマンドの補完機能(例えば日付データが入力されたら、日付データを引数にとるコマンドをUbiquityがサジェストする)に使用され、下記のようなnoun_typeがあります。また、CmdUtilsを使用してカスタムのnoun_typeを作成する事ができます。

  • noun_type_arb_text
  • noun_type_date
  • noun_type_language
  • noun_type_people
  • noun_type_place
  • noun_type_tab

noun_typeのソースは下記で確認する事ができます
nountypes.js

一方、コマンドの引数としてpreviewやexecute(の第二引数)に渡されるオブジェクトは、下記のようなプロパティを持ちます。

  • inputObject.text // 文字列
  • inputObject.html //タグを含む整形されたHTML
  • inputObject.data // 文字列以外のnoun_typeのデータ
  • inputObject.summary // 長い文字列の要約版

iknow-searchのpreviewで行っているのは、コマンドの引数から(テンプレート機能を使用して)URL文字列を組み立て、JSONでリクエストを取得、preview用のDOMに結果を反映するという一連の処理ですが、uqibuityではjQueryが使用できるため簡単に実装できます。

また同様に、コマンド入力後Enterを押した時に実行されるexecuteでは、Utils.openUrlInBrowser()を使用してブラウザで該当のURL(検索結果ページ)を開くようになっています。

まだまだ発展途上(というかできたばかり)のコンセプトですが、Webの機能をお手軽にコマンドにできるのはこれから重宝しそうです。

追記:Ubiquity のアップデートに合わせて、コードも少し書き換えました

投稿者: t4ku

2月 8, 2009 3:05 pm

Programming, Technology への投稿

Processingでグラフ

コメントなし

前から少し気になっていたProcessingという言語について、ちょうど本屋におもしろそうなオライリー本が出ていたので買ってみました。

ビジュアライジング・データ ―Processingによる情報視覚化手法

簡単な例としてグラフの作成があったので、自分でも日本の人口統計を使ってグラフを書いてみました。

Population growth in Japan

Population growth in Japan

  1. FloatTable data;
  2. PFont plotFont;
  3. float plotX1,plotY1;
  4. float plotX2,plotY2;
  5. float labelX,labelY;
  6. float dataAreaWidth;
  7. float dataAreaHeight;
  8. final float dataOffsetY = 30;
  9. float volumnInterval = 10000;
  10. float dataCeil;
  11. int []years;
  12. int yearMin;
  13. int yearMax;
  14. int yearInterval;
  15. float dataMin;
  16. float dataMax;

  17. void setup(){
  18. plotFont = createFont(“SansSerif”,20);
  19. textFont(plotFont);
  20. //load csv file
  21. data = new FloatTable(“ppl1920-1990-grs-t.csv”);
  22. years = int(data.getRowNames());
  23. yearMin = years[0];
  24. yearMax = years[years.length -1];
  25. yearInterval = 10;
  26. dataMin = data.getColumnMin(0);
  27. dataMax = data.getColumnMax(0);
  28. println(ceil(dataMax/volumnInterval));
  29. dataCeil = ceil(dataMax/volumnInterval) * volumnInterval;
  30. size(600,400);
  31. smooth();
  32. plotX1 = 160;
  33. plotY1 = 80;
  34. plotX2 = width - plotX1/2;
  35. plotY2 = height - plotY1;
  36. labelX = plotX1 -110;
  37. labelY = plotY2 +40;

  38. dataAreaWidth = plotX2 - plotX1;
  39. dataAreaHeight = plotY2- plotY1;
  40. }
  41. void draw(){
  42. background(022); // (1)background color
  43. fill(044);
  44. rectMode(CORNERS);
  45. noStroke();
  46. rect(plotX1,plotY1,plotX2,plotY2);
  47. strokeWeight(0.4);
  48. stroke(254);
  49. drawDataArea();
  50. stroke(112);
  51. strokeWeight(0.1);
  52. drawLabels();
  53. }

  54. void drawLabels(){
  55. drawTitleLabel();
  56. drawAxisLabels();
  57. drawYearLabels();
  58. drawYearGrid();
  59. drawVolumnLabels();
  60. }
  61. void drawTitleLabel( ) {
  62. fill(112);
  63. textSize(15);
  64. textAlign(CENTER,CENTER);
  65. text(“Population growth in Japan\n 1920 to 2000″,(plotX1+plotX2)/2,plotY1 - 40);
  66. }
  67. void drawAxisLabels( ) {
  68. fill(112);
  69. textSize(13);
  70. textLeading(15);
  71. textAlign(CENTER, CENTER);
  72. text(“Total \npopulation\n(Thousand)”, labelX, (plotY1+plotY2)/2);
  73. textAlign(CENTER);
  74. text(“Year”, (plotX1+plotX2)/2, labelY);
  75. }

  76. void drawYearLabels(){
  77. fill(112);
  78. textSize(12);
  79. textAlign(LEFT);
  80. int rowCount = data.getRowCount();
  81. for(int i=0;i < rowCount;i++){
  82. if(years[i] % yearInterval ==0){
  83. String yearText = data.getRowName(i);
  84. float x = map(int(yearText),yearMin,yearMax,plotX1,plotX2);
  85. text(yearText,x,plotY2+12);
  86. }
  87. }
  88. }

  89. void drawYearGrid(){
  90. int rowCount = data.getRowCount();
  91. for(int i=0;i < rowCount;i++){
  92. if(years[i] % yearInterval ==0){
  93. float x = float(data.getRowName(i));
  94. x = map(x,yearMin,yearMax,plotX1,plotX2);
  95. line(x,plotY2,x,plotY1);
  96. }
  97. }
  98. }

  99. void drawVolumnLabels(){
  100. fill(112);
  101. textSize(10);
  102. textAlign(RIGHT);
  103. float x = plotX1;
  104. float y;
  105. for(float v = floor(dataMin/volumnInterval)*volumnInterval;v <= dataCeil;v+= volumnInterval){
  106. y = map(v,floor(dataMin/volumnInterval)*volumnInterval,dataCeil,plotY2,plotY1);
  107. line(x-10,y,x,y);
  108. //println(v);
  109. text(floor(v),x-20,y+4);
  110. }
  111. }

  112. void drawDataArea(){
  113. beginShape();
  114. int rowCount = data.getRowCount();
  115. for(int i=0;i < rowCount;i++){
  116. float value = data.getFloat(i,0);
  117. float x = map(years[i],yearMin,yearMax,plotX1,plotX2);
  118. float y = map(value,floor(dataMin/volumnInterval)*volumnInterval,dataCeil,plotY2,plotY1);
  119. vertex(x,y);
  120. }
  121. endShape();
  122. }

  123. void keyPressed( ) {
  124. saveFrame(“japan_pl_##.png”);
  125. }

processing実行後に何かキーを押すと、連番で”japan_pl_01.png”という画像が保存されます。FloatTableというクラスは本のサンプルコードに含まれているものですが、http://benfry.com/writing/archives/3 からダウンロードできます。人口のCSVは統計局からダウンロードしたものをタブ区切りのcsvにしてます。

こんな感じで

  1. Year    Total
  2. 1920 55963
  3. 1921 56666
  4. 1922 57390
  5. 1923 58119
  6. 1924 58876
  7. 1925 59737
  8. 1926 60740.9
  9. 1927 61659.3
  10. 1928 62595.3
  11. 1929 63460.6
  12. 1930 64450
  13. 1931 65457
  14. 1932 66434
  15. 1933 67432
  16. 1934 68309
  17. 1935 69254
  18. 1936 70114
  19. 1937 70630
  20. 1938 71013
  21. 1939 71380
  22. 1940 71933
  23. 1941 71933
  24. 1942 71933
  25. 1943 71933
  26. 1944 73064
  27. 1945 71998
  28. 1946 73114
  29. 1947 78101
  30. 1948 80002
  31. 1949 81773
  32. 1950 83200
  33. 1951 84573
  34. 1952 85852
  35. 1953 87033
  36. 1954 88293
  37. 1955 89276
  38. 1956 90259
  39. 1957 91088
  40. 1958 92010
  41. 1959 92973
  42. 1960 93419
  43. 1961 94285
  44. 1962 95178
  45. 1963 96156
  46. 1964 97186
  47. 1965 98275
  48. 1966 99054
  49. 1967 100243
  50. 1968 101408
  51. 1969 102648
  52. 1970 103720
  53. 1971 105014
  54. 1972 107332
  55. 1973 108710
  56. 1974 110049
  57. 1975 111940
  58. 1976 110089
  59. 1977 114154
  60. 1978 115174
  61. 1979 116133
  62. 1980 117060
  63. 1981 117884
  64. 1982 118693
  65. 1983 119483
  66. 1984 120235
  67. 1985 121049
  68. 1986 121672
  69. 1987 122264
  70. 1988 122783
  71. 1989 123255
  72. 1990 123611
  73. 1991 124043
  74. 1992 124452
  75. 1993 124764
  76. 1994 125034
  77. 1995 125570
  78. 1996 125864
  79. 1997 126166
  80. 1998 126486
  81. 1999 126686
  82. 2000 126926

Processingを一言で説明しようとすると、Javaの描写機能を使用しやすいインタフェースで提供する言語環境(なのかな?)でしょうが、なんでProcessingに興味をもっていたかというと、これを使用した作品(っていうのがいいですね)に興味深いというか斬新なものが多かったからな訳です。

MusicBox: a truly powerful visualization of your music library:http://www.crunchgear.com/2008/12/15/musicbox-a-truly-powerful-visualization-of-your-music-library/
音楽のライブラリを可視化するソフト。ファイルのメタデータ(作者やジャンルなど)のみではなく、実際の音声データをスキャンしてマッピングする。

Aligning humans and mammals:http://benfry.com/infoseed/
人間とほ乳類の遺伝子配列をならべて描写した画像

Base26:http://toxi.co.uk/p5/base26/
英語の言葉同士の慣例性を表現した図。

仕事ではほとんどCRUDなWEBアプリケーションしか見ないのですが、こういうデータの重要性もさることながらどう見せるかでどれだけ印象や理解度が変わるかという事を考えるとおもしろい。色々遊んでみようと思います。

投稿者: t4ku

2月 3, 2009 3:44 am

Programming, Technology への投稿

タグ:

google reader – スター付きアイテムのRSSフィード

コメントなし

google readerはすごい。

検索機能、ショートカットや、AJAXによるスムーズでシンプルなUI。

でも、自分が読んでいるRSSフィードのフィードも出力してくれるのは結構隠れたいい機能だと思う。これがどういう事を意味するかというと、、、

  • Aさんが、毎日100個のニュースやブログのフィードを見ているとする。Aさんは自分の観点で「これは!!」と思うエントリ(10個くらい)にスターを付ける。
  • Aさんの友人で、Aさん程ネットのヘビーユーザーではないBさんは、Aさんの「スター付アイテム」のRSSフィードを購読する事で、Aさんが重要だと思ったことを10分の1の労力で発見できる。しかも「Aさんの目きき力」も借りることになる。

フィードの設定
他人にフィードを公開するには、フィードやタグについて個別に共有設定で「公開」と設定しなければ、ならない(FeedのURLは共有設定をしてなくても分かるが、未公開だとユーザーIDとPWで認証が必要になる)。

やり方は簡単。

  1. [設定] リンクをクリックします。
  2. [タグ] をクリックします。
  3. チェックボックスを使用して、共有するタグを選択します。 代わりにスター付きアイテムを共有することもできます。
  4. [共有を変更] メニューから [公開] を選択します。

google reader - 共有�定

エントリごとに、共有するという手もあるがちょっと手間な気がする。こちらはフッター部分の「共有」をクリックするだけ。後は、共有アイテムのフィードURLを登録すればよい。

共有 - エントリごと

↓下記のような記事を見ると、Webの広がりというか可能性を感じずにはいられない…

 小林氏はこれらのWebユーザーをさらに、さまざまなWebコンテンツを無償で創造する「クリエータ」、Web上の情報を関連付ける「エディタ」、Web上の情報の価値を判定する「バリュア」の3種類に分類。閲覧のみのレーシーバーを3284万人、クリエーターを783万人、エディタを 1476万人、バリュアを951万人と推測。さらにそれらすべてを行う人々をCEVと定義して234万人と推測し、その中でも毎日活動している人が63万人いるとした。

NRIの調査によると、CEVが1日にWebに費やす時間は3.9時間なので、そのうちの半分をCEV活動に費やしているとすると、1日2時間×365日×63万人で約4億時間になり、東京都の最低時給739円で換算すると年間3400億円規模にもなると試算した。

エレクトロニクス市場における日本の地位は大きく低下
BtoCのEC市場は2012年に10兆円規模に~NRIがトレンド予測
http://www.atmarkit.co.jp/news/200712/19/nri.html

投稿者: t4ku

12月 29, 2007 1:32 pm

Technology への投稿

タグ: , ,

SaaSとソフトウェア屋さん – 37Signalsの答え

1件のコメント

すごいエントリだなっと思ったので、日本語にしてみた。SaaSというとイニシャルコストが安いとかセキュリティやサーバー管理の手間が省けるといったユーザーの視点からの議論が多いけれども、Web開発者から見た本質とはこういう事なのだと思う。

Ask 37signals: Installable software?

企業内部で使用できるようにアプリケーションを販売する予定はありますか?

私達がインストーラブル・ソフトウェアを販売する可能性はほとんどないでしょう。これはソフトウェアにというより、ビジネス上の観点からです。

  • もし、そうすればまったく別の企業になってしまうでしょう

インストーラブル・ソフトウェアを開発、販売、配給するためには今とは根本的に異なる企業にならなければならないでしょう。今ほどアジャイル開発できなくなるだろうし、今よりハッピーではなくなるでしょう。

インストーラブル・ソフトウェアを作るとすると、多大なお金と時間を テクニカルサポートに費やし、より多くのドキュメントを作成し、開発スピードを遅らせ、そして最終的には私達のアプリケーションのカスタマーエクスペリエンスをうまくコントロールできなくなってしまうでしょう。他の企業にとってはたいした問題ではないかも知れませんが、私達にとっては大変なマイナスです。

  • 「ホスティング = 開発環境と動作環境をうまく管理できる 」

ソフトウェアというものは、多様な環境でうまく動作させる事が難しいものです。
Webベースのソフトウェアでは単一の動作環境上でうまく動作するように、コードを書けばよいのです。私達はプロダクトをセットアップするのに必要なハードウェアとソフトウェアを責任をもって組み合わせればよいだけです。この意義はとてつもなく大きいものです。

  • 「インストーラブル = マズい事が起こりやすい 」

デスクトップアプリケーションでも、顧客の環境にセットアップされたWebアプリケーションでも、大本となるコードは単一でしょうが(あなたがカスタムバージョンを顧客ごとに作成していない限りは)、手に負えないくらい際限なく多様な動作環境に向き合わなければならないでしょう。提供するアプリケーションのインストールやアップグレードや一般的なパフォーマンスに影響を与えるOSやサードパーティのソフトウェアやハードウェアを熟知していないと、なにかマズい事が起こった時、原因を突き止めるのが非常に難しくなってしまいます。また顧客の環境にインストールする場合、異なるバージョンのRuby,Rails,MySQLなどが存在するとますます困難です。

  • 後方互換性とういう悩みの種

さらに、インストーラブル・ソフトウェアを販売すると、後方互換性にも取り組まなければなりません。最新バージョンが3.2だとします、数千人のユーザーが3.1ではなく3.0を使用していたらアップグレード手順はどうなるでしょう?そして、まだ2.9や2.9.7を使用しているユーザーについてはどうしましょう?後方互換性を維持するという事は、多分ソフトウェアのアップデートにとって最大の障害でしょう。

もちろん、ブラウザー間の相違やブラウザーのバージョンの違いといった点ではWebベースのホスティングアプリケーションも似たような問題はありますが、それはWebベースのインストーラブル・ソフトウェアでも変わりません。そういった問題はどちらにも存在するので、チャラです。

  • アップデート・サイクル

最後に、Webベースのソフトウェアは顧客側の作業を必要とせず、たちどころにすべての顧客に対してアップデートを行うことができます。つまり、顧客に何の負担をかけるもなく、日次で(もしくは一日に何度も)ソフトウェアをアップデートできるということです。インストーラブル・ソフトウェアのアップデート・サイクルはたいていもっと長くなってしまいます、なぜならユーザーにアップデートを毎日ダウンロードするようお願いしなくてすむよう、リリースをまとめることの方が重要だからです。

このように言う事で、デスクトップ・アプリケーションやインストーラブル・ソフトウェアがなくなるとか、魅力がないとか言いたいのではありません。しかし、今のところWebベースのホスティング・アプリケーションという私達が好むやり方にこだわりたいと思います。

投稿者: t4ku

12月 25, 2007 1:34 pm