npmで公開しているモジュールを更新する方法

npmで公開しているモジュールをふと更新したくなりまして、やり方を調べてみるもなかなか見つからず困ったことがあったので備忘録的にメモを残しておきます。

ズバリ、以下のコマンドで一発でした。

# npm publish

publishは公開時に使用するコマンドなので、他のコマンド、もしくは何かオプションが必要なのでは!と勘ぐってしまったのが仇となってしまいました。

ちなみにpackage.jsonの version を書き換えないと更新時にエラーになりますので注意が必要です。
(--force で同バージョンに上書きすることも可能ですが、避けた方が良いでしょう)

Passbook用クーポンの中身?

今日はiOS6から追加になった新機能、Passbookのクーポンの中身を解析してみました。

簡単に結論から言うと、必要なファイル一式を拡張子.passとしてzip形式で圧縮した物をクーポンと呼ぶようです。

クーポンのダウンロード

試しにFirefoxのアドオンを駆使してpassbank.jpから無印のクーポンをダウンロードしてみました。
するとD6FxoWjf.passなるファイルがダウンロードできました。これを展開すると以下のようなファイル一式が含まれています。

D6FxoWjf.pass
  - icon.png
  - logo.png
  - manifest.json
  - pass.json
  - signature
  - strip.png

 なんとなくここで気づいた人も居るかもしれませんが、どことなくGoogle Extensionの作りに似ていますね。

manifest.json

manifest.jsonの中身は以下のようになっています。.pass内のファイルをここで関連づけているようです。

{
"icon.png":"67fbd9b18ee48cde3c50235f82dce2a4ece80166",
"logo.png":"6f5005fc44f2b4585049785cc8828fc0bb923b77",
"pass.json":"86a293c842cd1f3e7d7da5c9cabc8a38093f7744",
"strip.png":"1f535e64f8b7ddb648db8242c110d20bffbe1da8",
}

pass.json

次にpass.jsonですが、こちらにクーポンの詳細が記入されているようです。

{
   "formatVersion":1,
   "passTypeIdentifier":"pass.com.passss.general",
   "teamIdentifier":"TJ96KD8A74",
   "serialNumber":"D6FxoWjf_IBGnrrUV",
   "organizationName":"無印良品 有楽町",  
   "description":"ブールドネージュ",
   "backgroundColor":"#F5F5DC",
   "labelColor":"#000000",
   "foregroundColor":"#000000",
   "suppressStripShine":true,
   "logoText":"",
   "relevantDate_": "",
   "associatedStoreIdentifiers_":[],
   "authenticationToken":"0MTXkBS96iEFzaQL",
   "webServiceURL":"https://passss-server.appspot.com/api/pkws/",
   "locations":[{"relevantText":"先着1000名様にプレゼント!","altitude":0.0,"longitude":139.765052,"latitude":35.675531}],
   "barcode" : {
    	"format":"PKBarcodeFormatQR",
    	"message":"D6FxoWjf_IBGnrrUV",
    	"altText":"D6FxoWjf_IBGnrrUV",
    	"messageEncoding" : "iso-8859-1"
   },
   "coupon":{
      "headerFields":[
      ],
      "primaryFields":[
         {                                               
            "key":"p1",
            "label":"",
            "value":"",
            "textAlignment":"PKTextAlignmentLeft"
         }
      ],                           
      "secondaryFields":[
         {                                               
            "key":"s1",
            "label":"",
            "value":"",
            "textAlignment":"PKTextAlignmentLeft"
         }
      ],
      "auxiliaryFields":[
      ],
      "backFields":[
         {                                               
            "key":"B1",
            "label":"説明",
            "textAlignment":"PKTextAlignmentLeft",
            "value":"【無印良品有楽町限定】\nPassbookでクーポンを提示されたお客様、先着1000名様に「ブールドネージュ 80g」をプレゼントします。\n\nブールドネージュは白い雪の玉という名前のフランス菓子で、無印良品で人気No.1のお菓子です。\nアーモンド入りの生地をまるく焼きあげ、粉糖をまぶして仕上げました。\n\n※予定数量に達し次第、終了とさせていただきます。\n※本クーポンのご利用は、お1人様1回限りです。\n※本クーポンを、無印良品 有楽町 1F総合受付にてご提示ください。\n\n無印良品 有楽町\n営業時間:10:00〜21:00\n東京都千代田区丸の内 3-8-3 インフォス有楽町1-3F\nTEL:03-5208-8241"
         }
      ],
      "transitType":"PKTransitTypeGeneric"
   }
}
位置情報について

locationsで位置情報を設定することで、iPhoneが一定距離に近づいた際に通知してくれるのでしょうか?

"locations":[{"relevantText":"先着1000名様にプレゼント!","altitude":0.0,"longitude":139.765052,"latitude":35.675531}],
バーコードの表示形式について

barcodeの項目でクーポンに表示するバーコードの形式を設定しているようです。このクーポンはQRコードかな?

   "barcode" : {
    	"format":"PKBarcodeFormatQR",
    	"message":"D6FxoWjf_IBGnrrUV",
    	"altText":"D6FxoWjf_IBGnrrUV",
    	"messageEncoding" : "iso-8859-1"
   },

 どことなくここまで分かれば自力でもクーポンの作成が出来そうですね。

AndroidでもPassbookのクーポンが利用できる?

未検証ですが、passwalletなるアプリを使用することで、AndroidでもPassbookのクーポンが表示できるようです。
ただし表示するためには個人でクーポンをダウンロードしpasswalletにインポートしてやる必要があるようです。
いずれ検証してみたいと思います。

ずばりクーポンの作り方

以下のサイトで項目に必要な情報を入力することでクーポンの作成が行えます。これって公式?
http://www.passsource.com/

と、今回はこの辺りでそろそろ寝ることにします。
おやすみなさい。。。

JavaとRubyのコード比較その1

同一の仕様を、JavaとRuby、それぞれのプログラミングコードで記述するとどうなるか、について書いてみます。
今回はApacheのアクセスログを解析し、標準出力に出力すると言うまぁシンプルな仕様進めます。

まずはJavaで書くとこんな感じになるでしょうか。
(クラス定義などなどは省略しています)

    FileReader in = new FileReader("/Users/akiiiiiiiio/tmp/access_log");
    BufferedReader br = new BufferedReader(in);
    String line = null;
    while ((line = br.readLine()) != null) {
        Matcher match = pat.matcher(line);
        if (match.matches()) {
            System.out.println("host: " + match.group(1));
            System.out.println("ident: " + match.group(2));
            System.out.println("user: " + match.group(3));
            System.out.println("time: " + match.group(4));
            System.out.println("request: " + match.group(5));
            System.out.println("status: " + match.group(6));
            System.out.println("bytes: " + match.group(7));
            System.out.println("referer: " + match.group(8));
            System.out.println("useragent: " + match.group(9));
        }
    }
    br.close();
    in.close();

次にRubyで実装するこんな感じでしょうか。
(またまたもろもろのクラス定義などは省略しています)

    open("/Users/akio/tmp/access_log", "r") {|f|
        f.each {|line|
            line.scan(
              /^([^ ]*) ([^ ]*) ([^ ]*) \[([^]]*)\] "(.*?)" ([^ ]*) ([^ ]*) "(.*?)" "(.*?)"/) {
              |host,ident,user,time,request,status,bytes,referer,useragent|
                puts "host: " + host
                puts "ident: " + ident
                puts "user: " + user
                puts "time: " + time
                puts "request: " + request
                puts "status: " + status
                puts "bytes: " + bytes
                puts "referer: " + referer
                puts "useragent: " + useragent
            }
        }
    }

どちらのコードもアクセスログの行数だけ以下のような文字列が標準出力に出力されます。

host: xxx.xxx.xxx.xxx
ident: xxx
user: xxx
time: 24/May/2012:20:50:34 +0900
request: GET /wp-admin/post.php?post=7&action=edit&message=1 HTTP/1.1
status: 200
bytes: 71928
referer: http://www.xxx.xxx/wp-admin/post.php?post=7&action=edit
useragent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5
・
・
・

うん。個人的にはRubyの方がシンプルかつ直感的で好きですね。

CentOSにサーバサイドJavaScript、Nodeをインストール

今日はCentOSにサーバサイドJavaScript、Nodeをインストールし、NodeでHello Worldを実行してみます。
一部の界隈では、2011年はサーバーサイドJavaScriptの時代になると言われています。この機会に皆さんもまずはインストールを行ってみては如何でしょうか。

環境

CentOS 5.5 final (VMware Fusion)

Nodeって何?

サーバサイドJavaScriptです。一般的にサーバサイドと言われると、PHPやJava、Rubyなどのプログラミング言語がまず最初に頭に浮かぶと思いますが、なんとNodeを使用するとJacaScriptでサーバサイドプログラミングが実装出来るのです。

Nodeのダウンロード

Nodeをダウンロードします。

# cd /usr/local/src
# wget http://nodejs.org/dist/node-v0.4.6.tar.gz

Nodeのコンパイル、インストール

Nodeを使用するにはコンパイルが必要です。筆者は初め、JavaScriptなのにコンパイル!?と思ってしまいました。
コンパイルでは、主にGoogleのV8エンジンのコンパイルに少し時間がかかります。
なお既にopenssl-devel.i386をインストール済みの場合、openssl-devel.i386のインストールは不要です。

# yum install openssl-devel.i386
# tar xvfz node-v0.4.6.tar.gz
# cd node-v0.4.6
# ./configure
# make 
# make install

Nodeの実行確認

下記のコマンドを実行し、インストールしたNodeのバージョンが表示されればNodeはインストールされています。
そぉ、NodeはCUIベースで実行します。

# node -d
v0.4.6

NodeでHello Word

それではお決まりのHello Worldを実行してみます。

# node
> var str = "Hello World";
> console.log(str);
Hello World

今日のところは以上になります。
さてさて、これだけではNodeで何が出来るのか、何がすごいのか、がいまいちわからないと思いますので、どこかで別記事を書きたいと思います。

JavaでOCR

今日はJavaでOCRを用いて画像から文字列を取得し、先日インストールしたMeCabを用いて形態素解析してみたいと思います。
OCR用ライブラリは、下記のライブラリを使用させていただきました。
Asprise Java OCR SDK - royalty-free API library with source code examples converting images to word or searchable PDF by extracting text

環境

CentOS 5.5 final (VMware Fusion)
jdk-1.6.0_17

OCR-Javaライブラリを取得

まずはOCR用ライブラリを取得します。
最近では、検索さえ出来れば偉人達が作成した良ライブラリがすぐに見つかる良い時代になりました。w
ちなみにcompat-libstdc++-33.i386に関して、既にインストール済みのかたは必要ありません。

# yum install compat-libstdc++-33.i386
# mkdir /usr/local/src/asprise
# cd /usr/local/src/asprise
# wget http://download.asprise.net/software/ocr-v4/Asprise-OCR-Java-Linux_x86_32bit-4.0.zip

まずはサンプルを実行

OCR-Javaを展開すると、サンプルスクリプトが複数用意されていますので、何はともあれまずはサンプルが実行出来るかを確認します。
コンソール上に下記が出力されればOKです。

# unzip Asprise-OCR-Java-Linux_x86_32bit-4.0.zip
# sh runDemo1.sh 
--- A general sample with both characters and barcodes ---

Welcome to Asprise OCR v4.0 Demo!

Trying to perform OCR on image: /usr/local/src/asprise/sample-images/ocr.gif

---- RESULTS: ------- 
=== ASPRISE OCR SDK EVALUATION ===

1) For licensing information, visit: http://asprise.com/product/ocr
2) This evaluation version replaces all recognized 'q' and 'x' occurrences with stars ('*'). 

[123456789012]
Asprise OCR
Speed. Accuracy.

画像からOCRで読み取った文字列をMeCabを使用して形態素解析してみる

それでは本日の本題です。まずはじめに、下記を参考にJavaからMeCabが使用出来る環境を用意してください。
JavaでMeCab - akiiiiiiiioの日記

環境が用意出来たら、次はJavaクラスを作成します。

# cd /home/akiiiiiiiio
# vi OcrToMecab.java

今回は以下のようなクラスを作成しました。

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import com.asprise.util.ocr.OCR;
import org.chasen.mecab.MeCab;
import org.chasen.mecab.Tagger;
import org.chasen.mecab.Node;

public class OcrToMecab {
    static {
        try {
            System.loadLibrary("MeCab");
        } catch (UnsatisfiedLinkError e) {
            System.exit(1);
        }
    }
    public static void main(String[] args) throws IOException {
        File file = new File(args[0]);
        BufferedImage img = ImageIO.read(file);
        String str = new OCR().recognizeEverything(img);
        System.out.println(new Tagger().parse(str));
    }
}

それではコンパイル、実行してみたいと思います。今回は、OCR-Javaライブラリのサンプル画像をそのまま引数に指定しています。

# javac -cp /usr/local/src/mecab-java-0.97/MeCab.jar:/usr/local/src/asprise/aspriseOCR.jar OcrToMecab.java
# export LD_LIBRARY_PATH=/usr/local/src/mecab-java-0.97/:/usr/local/src/asprise/
# java -cp .:/usr/local/src/mecab-java-0.97/MeCab.jar:/usr/local/src/asprise/aspriseOCR.jar OcrToMecab \
> /usr/local/src/asprise/sample-images/ocr.gif
=	記号,一般,*,*,*,*,=,=,=,,
=	記号,一般,*,*,*,*,=,=,=,,
=	記号,一般,*,*,*,*,=,=,=,,
ASPRISE	名詞,固有名詞,組織,*,*,*,*
O	記号,アルファベット,*,*,*,*,O,オー,オー,,
C	記号,アルファベット,*,*,*,*,C,シー,シー,,
R	記号,アルファベット,*,*,*,*,R,アール,アール,,
SDK	名詞,固有名詞,組織,*,*,*,*
EVALUATION	名詞,一般,*,*,*,*,*
=	記号,一般,*,*,*,*,=,=,=,,
=	記号,一般,*,*,*,*,=,=,=,,
=	記号,一般,*,*,*,*,=,=,=,,
1	名詞,数,*,*,*,*,1,イチ,イチ,,
)	記号,括弧閉,*,*,*,*,")",")",")",,
For	感動詞,*,*,*,*,*,*
licensing	感動詞,*,*,*,*,*,*
information	感動詞,*,*,*,*,*,*
,	記号,読点,*,*,*,*,",",",",",",,
visit	名詞,固有名詞,組織,*,*,*,*
:	記号,一般,*,*,*,*,:,:,:,,
http	名詞,固有名詞,組織,*,*,*,*
:	記号,一般,*,*,*,*,:,:,:,,
/	記号,一般,*,*,*,*,/,/,/,,
/	記号,一般,*,*,*,*,/,/,/,,
asprise	名詞,固有名詞,組織,*,*,*,*
.	記号,句点,*,*,*,*,.,.,.,,
com	名詞,固有名詞,組織,*,*,*,*
/	記号,一般,*,*,*,*,/,/,/,,
product	名詞,固有名詞,組織,*,*,*,*
/	記号,一般,*,*,*,*,/,/,/,,
ocr	名詞,固有名詞,組織,*,*,*,*
2	名詞,数,*,*,*,*,2,ニ,ニ,,
)	記号,括弧閉,*,*,*,*,")",")",")",,
This	感動詞,*,*,*,*,*,*
evaluation	感動詞,*,*,*,*,*,*
version	感動詞,*,*,*,*,*,*
replaces	感動詞,*,*,*,*,*,*
all	感動詞,*,*,*,*,*,*
recognized	感動詞,*,*,*,*,*,*
'	記号,一般,*,*,*,*,"'","'","'",,
q	記号,アルファベット,*,*,*,*,q,キュー,キュー,,
'	記号,一般,*,*,*,*,"'","'","'",,
and	名詞,固有名詞,組織,*,*,*,*
'	記号,一般,*,*,*,*,"'","'","'",,
x	記号,アルファベット,*,*,*,*,x,エックス,エックス,,
'	記号,一般,*,*,*,*,"'","'","'",,
occurrences	名詞,固有名詞,組織,*,*,*,*
with	名詞,固有名詞,組織,*,*,*,*
stars	名詞,一般,*,*,*,*,*
(	記号,括弧開,*,*,*,*,"(","(","(",,
'	記号,一般,*,*,*,*,"'","'","'",,
*	記号,一般,*,*,*,*,*,*,*,,
'	記号,一般,*,*,*,*,"'","'","'",,
)	記号,括弧閉,*,*,*,*,")",")",")",,
.	記号,句点,*,*,*,*,.,.,.,,
[	記号,括弧開,*,*,*,*,[,[,[,,
1	名詞,数,*,*,*,*,1,イチ,イチ,,
2	名詞,数,*,*,*,*,2,ニ,ニ,,
3	名詞,数,*,*,*,*,3,サン,サン,,
4	名詞,数,*,*,*,*,4,ヨン,ヨン,,
5	名詞,数,*,*,*,*,5,ゴ,ゴ,,
6	名詞,数,*,*,*,*,6,ロク,ロク,,
7	名詞,数,*,*,*,*,7,ナナ,ナナ,,
8	名詞,数,*,*,*,*,8,ハチ,ハチ,,
9	名詞,数,*,*,*,*,9,キュウ,キュー,,
0	名詞,数,*,*,*,*,0,ゼロ,ゼロ,,
1	名詞,数,*,*,*,*,1,イチ,イチ,,
2	名詞,数,*,*,*,*,2,ニ,ニ,,
]	記号,括弧閉,*,*,*,*,],],],,
Asprise	名詞,固有名詞,組織,*,*,*,*
OCR	名詞,固有名詞,組織,*,*,*,*
Speed	名詞,一般,*,*,*,*,*
.	記号,句点,*,*,*,*,.,.,.,,
Accuracy	名詞,一般,*,*,*,*,*
.	記号,句点,*,*,*,*,.,.,.,,
EOS

つらつらと上記のように出力されれば今回の目的は完了です。
今回ご紹介したOCRライブラリを用いれば、画像の全文検索システムなんかもJavaのみで簡単に作成することが出来ると思います。
ただしOCR-Java付属のLICENSE-EVALUATION.txtにも記載がありますが、当ライブラリはあくまで個人の責任の範囲で使用されることをお勧めします。w