sheditorとAutoFolderSyncを譲渡します

という二つのAndroidアプリケーションを開発してきましたが、この二つをアクシオン様に譲渡することとしました。

これら二つに関して本日最終アップデートを公開しました。また、2週間後の7月20日にマーケットから取り下げます。

今後私はこの二つのアプリケーションの開発は一切行いません。さらに、以降2年間、sheditorとAutoFolderSyncの名称とロゴを、私もアクシオン様も使わないこととします。

理由

こう決めた大きな理由は、仕事の関係です。いろいろあってAndroidに時間をかけられなくなってきました。
今まで使用していただいた多くの人に感謝しております。ご愛顧ありがとうございました。

Nook Touchのroot取得とePubの日本語表示

http://nookdevs.com/NookTouch_Rooting の通りです。詳しくは説明しません。あしからず。

特に問題はおきませんでしたが、VMWare上のUbuntuでやろうとしたらUSBカードリーダの認識がホストのWindowsと取り合いになったりとかがありました。最初からMacでやればよかった。

USBケーブルはUSBストレージモードでしかつながらないので、Wirelessでつなげます。

filesystem

shellを取ってmountと打つと、

/dev/block/mmcblk0p5 /system ext2 ro,errors=continue 0 0

とread-onlyなことが分かります。これは、

% mount -o rw,remount -t ext2 /dev/block/mmcblk0p5 /system

と打って、read-writeにします。これでいろいろできます。

とりあえずこの二つをしておきました。

  • busyboxのインストール
  • B&Nのupdateを無効化 (注意!! rebootすると起動しなくなるという情報あり。みゃさん、ありがとうございます。)
    • # mv /system/etc/security/otacerts.zip /system/etc/security/otacerts.zip.bak
Fontをインストールする

フォントはttfならばなんでもいいのですが、ぐぐって出てきたMigMixを使ってみます。

これをダウンロードし、送り込みます。どうも標準のリーダーはフォントが決め打ちなようなので、どれか一つをつぶして置き換えます。

% adb pull /system/fonts # フォントのバックアップ
% adb push MigMix-1P-regular.ttf /system/fonts/Trebuchet.ttf
% adb push MigMix-1P-regular.ttf /system/fonts/Trebuchet-Italic.ttf
% adb push MigMix-1P-bold.ttf /system/fonts/Trebuchet-Bold.ttf
% adb push MigMix-1P-bold.ttf /system/fonts/Trebuchet-BoldItalic.ttf

これでTrebuchetにフォントを変更すると、日本語の表示ができます。一部まだ文字化けてるところはありますが…

こんな感じになりました。

ちなみに表示しているのはSphinx逆引き辞典です。Sphinxを使うとreSTからepubに簡単にできるので便利です(宣伝)。

Factory reset

どうもrootを取った状態でrebootすると、 "Your NOOK is starting" と出て起動しなくなります。こうなるともうどうしようもないので、Factory resetをするしかありません。

それには、"Your NOOK is starting..."で止まっている状態で、電源長押しでのrebootを8回連続して繰り返してください。そうすると、Factory resetがかかります。

Factory resetをかけても、無線の設定は残ります。

Nook touchを買いました。

新型Nook、通称Nook touchを買いました。黒船gadgetさんで頼んで、5日ほどで着きました。早い!

第一印象

軽い!小さい!

です。ほんとに軽いです。片手で長時間持っても全然問題ないぐらいです。これはいい。

自分のePUB/PDFを読み込ませる

Barnes & Novel の本は日本からでは買えません。Proxyを使ってアメリカ内からの接続に偽装すれば買えるらしいのですが。

というわけで、基本的に自分が持っているePUB/PDFを読むことになります。MicroSDスロットがあるのでそれで入れてもいいですし、USBでつなげば普通に見えますので、そこで本体メモリ(256MB)に入れてもいいです。

ただし、それを読もうとすると、

  The Nook cannot read this file. It may be an unsupported format.

と表示されてしまいます。これを回避するために、My Files/ の下に My Documents を作ります。

  My Files/Books/  <-- 作っておけばここに置いても読める
  My Files/Documents/
             :
  My Files/My Documents/  <-- これを新しくつくる

と言う感じです。作るだけでいいです。後はMy Files/Booksに置いたものでもちゃんと読んでくれます。なんででしょうね。

空白除去

しかし、やはり6inchのディスプレイではオライリーのpdfを見るのはちょっとつらい。そこで、 オライリーのebookから余白を除去して、Kindleで快適に読む方法のように空白を除去します。これでちょっと読みやすくなりましたが、まだもう一声という感じでしょうか。やっぱりePUBで読みたいですね。

日本語ePUB

化けます。タイトルとかファイル名は日本語で表示されているのでフォントは入っているようです。しかし、表示のところで使ってるフォントが対応していないみたいです…

対応策1 -> 失敗

ここに書いてあるように、ePUBのstyle.cssをDroidSansFallback.ttfに変更してみましたが、だめでした。

@font-face { 
font-family: "DroidFont", serif, sans-serif; 
font-weight: normal; 
font-style: normal;
src: url('res:///system/fonts/DroidSansFallback.ttf'); 
} 
@font-face { 
font-family: "DroidFont", serif, sans-serif; 
font-weight: bold; 
font-style: normal; 
src: url('res:///system/fonts/DroidSansFallback.ttf'); 
} 
@font-face { 
font-family: "DroidFont", serif, sans-serif; 
font-weight: normal; 
font-style: italic; 
src: url('res:///system/fonts/DroidSansFallback.ttf'); 
} 
@font-face { 
font-family: "DroidFont", serif, sans-serif; 
font-weight: bold; 
font-style: italic; 
src: url('res:///system/fonts/DroidSansFallback.ttf'); 
} 
body { 
   margin-right: 8pt; 
   font-family: 'DroidFont', serif; 
}

でも変化なしです。 (ちなみに、上記はCreativeCommonsライセンスです)

対応策2 -> 失敗

こっちに書いてあるように、フォントを置いて、そこを指すようにしてみましたが、だめでした。

@font-face {
	font-style: italic;
	font-family: 'LiberationSerif', serif, sans-serif;
	font-weight: normal;
	src: url('res:///system/media/sdcard/my fonts/LiberationSerif-Italic.ttf');
}
@font-face {
	font-style: normal;
	font-family: 'LiberationSerif', serif, sans-serif;
	font-weight: normal;
	src: url('res:///system/media/sdcard/my fonts/LiberationSerif-Regular.ttf');
}
@font-face {
	font-style: italic;
	font-family: 'LiberationSerif', serif, sans-serif;
	font-weight: bold;
	src: url('res:///system/media/sdcard/my fonts/LiberationSerif-BoldItalic.ttf');
}
@font-face {
	font-style: normal;
	font-family: 'LiberationSerif', serif, sans-serif;
	font-weight: bold;
	src: url('res:///system/media/sdcard/my fonts/LiberationSerif-Bold.ttf');
}
body {
	margin-right: 8pt;
	font-family: 'LiberationSerif', serif;
}
うーん。

rootを取るしか無いかなぁ、というあたりで今日はここまで。

reST/Markdownで書けるHTML slide generator、landslide

Twitterで@voluntas さんがつぶやいていた landslide を使ってみると、結構いいことが分かりました。

サンプルを作りましたので、ここに置いておきます。

画像の扱いに問題があったりしますが、現在も開発されているようですので、解決していくのではないでしょうか。

インストールも簡単ですし、しばらくはこれでスライド作ってみることにします。


.... blockdiag directiveを追加してみるとか、いいかも?

ライト、ついてますか

ライト、ついてますか―問題発見の人間学

ライト、ついてますか―問題発見の人間学

某ぽに勧められて、「ライト、ついてますか」という本を読んだ。いろいろと面白いことが書かれてあったのでここにメモします。自分用のメモで書評じゃないので、その点を注意して欲しいです。

問題とは
「問題とは、望まれた事柄と認識された事柄の間の相違である」

従って、問題を解決する方法は二種類ある。

  • 1. 望みを変える
  • 2. 認識を変える

この2については結構気がつかないことが多い。

問題はなんなのか

問題を持ちかけられたからといって、それが本当に問題とは限らない。

「彼らの解決方法を問題の定義と取り違えるな」

そしてもう一つ。

「正しい問題定義が得られたという確信は決して得られない。(問題が解けた後でも)
だが、その確信を得ようとする努力は決してやめてはいけない」

「問題はなにか?」は常に自問自答し続けなければならない。

認識
「問題によってはそれを認識するところが一番難しいこともある」

問題は欲求と認識との相違であるため、欲求がそもそもなければ問題ではない。しかし、別の人に取っては異なる。

「キミの問題定義を外国人や盲人や子供について試してみよう。
またキミ自身が外国人や盲人や子供になってみよう」

これにより、別の問題が浮かび上がってくるかもしれない。「新しい視点は必ず新しい不適合を作り出す」。

言葉

認識を変える簡単な方法の一つは言葉を使うこと。

「問題が言葉の形になったら、それがみんなの頭に入るまで言葉をもて遊んでみよう」

「Mary had a little lamb」

という言葉があったとき、各単語を強調してみる。強調した単語を、「ほんとに?」と考えてみる。

  • MARY had a little lamb
  • Mary HAD a little lamb
  • Mary had A little lamb
  • Mary had a LITTLE lamb
  • Mary had a little LAMB

一単語だけじゃなくて連続した複数の単語でもいい。

辞書方式

各単語について意味を類語辞書をひき、違うけど同じ意味の言葉にしてみる。

言葉遊びのゴールデン・リスト
  • 強調の置き場所を変えてみる (上述)
  • 肯定を否定に、否定を肯定に変えてみる
  • 「てもよい(may)」を「なければならない(must)」に変えてみる。またその逆
  • 「または(or)」を「と…の一方(either or」に変えてみる。またその逆
  • 「および(and)」を「または(or)」に変えてみる。またその逆
  • 積極的に定義が与えられている術語を選んで、文中のそれが現れた場所を定義の文句で置き換えてみる
  • 「等」「以下同様」「ほか」などとあったら、そこにもう一つ実例を付け加えてみる
  • 説得的な言葉(「明らかに(obviously)」、「ゆえに(therefore)」、「明瞭に(clearly)」、「確かに(certanly)」など)を探して、それらが代表しているはずの論証でそれらを置き換えてみる
  • 文またはパラグラフが表しているものを絵に描いてみようとする
  • 言葉で書いてあるものを式で表す
  • 式を言葉で表す
  • 図がなにをいっているかを言葉で表す
  • 「読者(you)」を「筆者(me)」で置き換える
  • 「筆者(me)」を「読者(you)」で置き換える
  • 「われわれ(we)」と「読者(you)」を「双方(both parties)」で置き換える
  • 「一つの(a)」を「その(the)」で置き換える。またその逆
  • 「一部の(some)」を「全部の(every)」で置き換える。またその逆
  • 「つねに(always)」を「あるとき(sometime)」で置き換える
  • 「あるとき(sometime)」を「決して…ない(never)」で置き換える
理解
「他人が自分の問題を自分で完全に解けるときに、それを解いてやろうとするな」

問題を解決できるなら首を突っ込まないほうがいい。そのほうがいい結果になるし、モチベーションがある。そして、

「もしそれが彼らの問題なら、それを彼らの問題にしてしまえ」

自分の問題ならやる気が出るよね。そしてこれの発展形。

「もしある人物が問題に関係あって、しかもその問題を抱えていないなら、
何かをやってそれをその人物の問題にしてしまおう」

巻き込んでしまえ。

気づき

相手がすでにそれなりの知識・経験がある場合、ごちゃごちゃと問題の可能性を指摘するより、注意を喚起して気づかせたほうが良い場合がある。

ライト、ついてますか

本当にその問題を解きたいか?

問題だと思ってたことは実は問題じゃなかった、あるいは、問題が違ってた、ということは良くある。

「人々は、くれといったものを出してやるまでは何が欲しかったかを知らぬものである」

Python純正の全文検索ライブラリ、Whooshを使ってみた

本当はPython Mini Hack-a-thonでやろうと思ってたネタだったのですが、その前にちょっと準備しておくかーと思ってたらいつのまにか結構やっちゃってたんでまとめておきます。

Whooshとは

whooshPython純正の全文検索エンジンのライブラリです。Javaで書かれた全文検索エンジンであるLuceneの影響をかなり受けています。というか、はっきり言ってLuceneとほぼ同じです。

今回はこのwhooshを使って手元のMLを検索してみる、全文検索ツールを試しに作ってみました。

schemeの作成

Whooshでは検索するためにIndexを作成しますが、それにはまずSchemeを定義します。

Indexにはtitleとかurlとか、ドキュメントそのもの以外の情報も格納できます。Schemeとは、Index中のドキュメントに格納されてるフィールドの定義です。どんなフィールドが使えるかは、Whoose.fields.* で定義されています。

今回は、こんな感じにします。

from whoosh.fields import Schema, ID, STORED, NGRAM

schema = Schema(path=ID(stored=True, unique=True),
                body=NGRAM(stored=True))

NGRAMというのは、N-Gramで保持する情報を示します。それ以外であればTEXTなどを使えばいいでしょう。

Indexの作成

Indexの実体はディレクトリです。index.create_inでindexを作成します。

import os, os.path
from whoosh import index

if not os.path.exists("indexdir"):
    os.mkdir("indexdir")
    index.create_in("indexdir", schema)

ix = index.open_dir(indexdir)

ドキュメントの登録

次にIndexにドキュメントを登録します。それにはまずindexを開きます。

import whoosh.index as index

ix = index.open_dir("indexdir")

ドキュメントを登録するには、writer.add_documentを使います。ドキュメントを追加し終わったら、忘れずにcommitします。必要に応じてindexをcloseします。

writer=ix.writer();

for file_path in filenames:
    content = get_content(file_path) # ファイルの中身を読み出すメソッド
    if (content):
        writer.add_document(path=unicode(file_path), body=content)
try:
    writer.commit(optimize=True)
except:
    print "add failed"
    writer.cancel()

ix.close()

なお、unicode()としているぐらいで、登録する情報はUnicodeでないといけません。この点注意してください。

Indexから削除

ドキュメントを削除するために使えるメソッドが用意されています。ここでdocnumとは、内部で使っている番号で、searcher.document_number()を使って得られます。

  • delete_document(docnum)
    • 削除する
  • is_deleted(docnum)
    • 削除されたかチェック
  • delete_by_term(fieldname, termtext)
    • termにマッチしたドキュメントを削除
  • delete_by_query(query)
    • queryにマッチしたドキュメントを削除

Indexの更新

ドキュメントを置き換えたい場合は削除してからまた追加してください。

writer.delete_by_term('path', indexed_path)
to_index.add(indexed_path)

IndexWriter.update_document を使うと便利です。その場合、Scehemeの少なくとも一つはUniqueでないといけません。

writer.update_document(unique_id=u"1", content=u"Replace me")
writer.update_document(unique_id=u"1", content=u"Replacement")

idが1のドキュメントにupdateを二回かけています。この場合、最終的に"Replace me"というドキュメントが削除され、"Replacement"というドキュメントに置き換えられます。

Incrimental Index

すでにドキュメントが追加されているindexに、さらにドキュメントを追加する場合はincrimental indexを使います。

といっても別に特別なメソッドがあるわけではなく、indexを開き、writerを作り、単に writer.add_document() を呼び出すだけです。

検索

検索にはSearcherオブジェクトを使います。

ix = open_index(indexdir)

searcher = ix.searcher()

parser = QueryParser("body", schema = ix.schema)
querystring = unicode(querystring, 'utf-8') # hard coding
q = parser.parse(querystring)
results = searcher.search(q)

for r in results:
    print r["body"]
        
ix.close()

QueryParserでparserを作り、parserにqueryの文字列をセットした後に、searchします。

評価

7227通、74MB分のMLアーカイブを使って評価してみました。

indexの大きさ

indexの大きさは、なんと558MBになってしまいました。ちょっと大きすぎじゃね?ちなみに、NGRAMはデフォルトではminimum lengthが2,max lengthが4で、今回はそのまま使いました。

indexの大きさがindex作成時間に効いているんじゃないかとも思いますが、深くは追求していません。

速度評価

評価環境は

です。まあそもそもVMWareで試しているぐらいでちゃんとした評価じゃないんで、あくまで参考程度にしてください。

評価にはBenchmarkerを使いました。

評価項目は

  • 7227件のメールを writer.add_documentする
    • ファイルを開き、読み込み、add_documentします
    • UTF8に変換済みなので、変換コストはなし
  • writer.commitする
    • Optimize=True 付き

の二件です

## benchmarker:       release 3.0.1 (for python)
## python platform:   linux2 [GCC 4.4.5]
## python version:    2.6.6
## python executable: /home/shirou/Works/VEnvs/pydev/bin/python

##                       user       sys     total      real
add_document         743.2500   12.4200  755.6700  763.3811
commit               895.2400  374.5700 1269.8100 3539.8293

## Ranking               real
add_document         763.3811 (100.0%) *************************
commit              3539.8293 ( 21.6%) *****

## Ratio Matrix          real    [01]    [02]
[01] add_document    763.3811  100.0%  463.7%
[02] commit         3539.8293   21.6%  100.0%

検索は

##                       user       sys     total      real
search                 0.1500    0.0600    0.2100    0.2624

です。この程度であればはっきり言って一瞬です。

というわけで、体感としては70MB程度の文書でもindexの追加にはかなり時間がかかりますが、検索は早い、という感じでしょうか。

これ以上の大規模になった場合にどうなるかはめんどいので検証していません。しかし、個人で簡単に使いたい、という場合には結構有効なのではないでしょうか。

おまけ: Google App Engine対応

Python純正となれば、Google App Engineで動かしてみたい、という気になる人が100人ぐらいいると思いますが、残念ながらindexがディレクトリ、すなわちファイルシステムを前提としているため、動きません。

しかし、whooshはstore.Storageという形で抽象化しており、その中にfiledb.gaeというクラスがあり、これを使えばblobstore上にindexを置くことで、GAE上でも動作することができるようです。

ただ、gae.pyのコメントに書かれているとおり、実験的なクラスなことに注意してください。なお、ぼくは(まだ)試していません。