anti scroll

ブラウザと小説の新しい関係を模索する

縦書き文庫のURLが変わります

新しいURLは http://tb.antiscroll.com です。

いつまでもフリーのダイナミックDNSというのもなんですし、本当はもっと早く独自ドメインを取るべきでした。

独自ドメインについては、最初はtategakibunkoっていうのも考えたのですが、ちょっと長いし応用もきかないような気がしたので、このブログのタイトルと同じ名前をドメイン名にしました。

というわけで、今後はサービスをサブドメインでわけて、

auto-machic: http://am.antiscroll.com

縦書き文庫: http://tb.antiscroll.com

となります。

ただ、古いURLでも当分はアクセスできるようにしておくつもりです。

ブラウザと小説の新しい関係を模索する 〜auto-machic〜

auto-machic という、とても実験的な小説サービスをスタートしました。

名前の中に「machi」とあるのは「街〜運命の交差点〜」というゲームに触発された機能がたくさんあるからです。

画面サンプル

f:id:convertical:20140130211932p:plain

f:id:convertical:20140131213527p:plain

f:id:convertical:20140130212644p:plain

デモとしては、小説タイプのサンプルゲームタイプのサンプルがあります。

このサービスで具体的にどんなことができるかというと…

キャラクタを登録できる

作中のキャラクタをデータとして登録できます。

登録すると個別の紹介ページが作成され、プロフィールや出演作品の一覧を見ることができます。

f:id:convertical:20140130204249p:plain

アイコンを伴う台詞表現が書ける

キャラクタを登録すると、作中で「台詞表現」が使えるようになります。

f:id:convertical:20140130204314p:plain

発言の前にキャラクタの名前やアイコンが出るのは、ゲームの世界ではおなじみの機能ですよね。

これにより発言者を仄めかす芝居(…と言ってAはBした、みたいなやつ)を省略できたりします。

執筆の敷居も下がるし、読者も文脈を理解しやすくなるでしょう。一石二鳥!

さらにキャラクタのアイコンをクリックすると、人物の説明がポップアップ。

f:id:convertical:20140130204331p:plain

「この人だれだっけ」みたいなこともなくなるでしょう。超親切!

ザッピング機能

ゲームモードの小説では「ザッピング」といって、キャラクタとキャラクタのストーリーを行き来する機能を付けることができます。

f:id:convertical:20140130204344p:plain

「ゲームモードの小説」というのは、一言で説明すると「多視点型の小説」のことです。

複数の主人公の物語を相互に読み進めながら一つの物語を展開する、まさに「街」みたいな小説を書くことができます。

もちろん「街」でおなじみの「TO BE CONTINUED」を設定することも可能です(でも知らない人にはピンとこないかも)。

チップ機能

その場で説明が必要な言葉をリンクにし、クリックで説明を読むビューアを開かせることができます。

f:id:convertical:20140130204408p:plain

同じページに表示されて、ページ送りできるようになっているので、作品の雰囲気を壊しません。

ゲーム的な演出

小説の見せ方として、随所にゲーム的な演出が入っています。

例えば章と章のつなぎ目は、間奏のようなページを間にはさみ、フェードインやフェードアウトを使います。

ゲームモードでは、時刻とともに時計と背景色も変わります。

章分けをサポート

小説作品では章分けをサポートします。

連載用の作品も書きやすいでしょう。

縦書きも横書きもOK

ビューアの表示は自前開発の組版エンジンnehan.jsです。

ほぼすべてのブラウザで縦書きと横書きが表示できます。

もちろんルビも圏点も画像もHTML5なタグもOK。

対応していないもの

新着とか人気エントリとかランキングのような機能はないです。

コメントとか読了のようなソーシャル的な機能もないです。

また現状ではモバイル環境を想定していません(早めになんとかしたい)。

Vagrantfileでtypoしてvagrant upすると、修正後もtypoした箇所がvboxファイルに残り続けてしまう

嵌ったので、覚え書きです。

昨日、Vagrantという仮想マシンを扱うユーティリテリーがいけてるということで、触ってみたのです。

そしたら、すんなりとVMが用意できて、isoファイルからインストールしようとしなくて良かったなあ、などと喜んでいたのですが、ホストの時間がおかしい?

で、色々と調べたらVagrantfileにて、簡単な設定を追加したら対応できるということで、短い内容だったこともあってコピペせずに直書きしました。

でも起動時にエラーが起きて、Vagrantfileを眺めたら、やっぱりtypoをしていました。

その後、直して再起動したのですが、なぜかvagrant upがこける...

しかも出てくるエラーが奇妙で、USB2.0がどうこうとか、extpackが足りないとか。

で、必死にVirtualboxGUIから色々いじってみたのですが、どうにもうまくいかず。

仕方ないので、すがる思いで

VAGRANT_LOG=debug vagrant up

して、ログを眺めていたら「Config file」なる項目があって、どうやら「〜.vbox」というのがVirtualBox仮想イメージの設定ファイルということがわかりました。

早速これを開いたら、なんとこんな箇所があって...

<ExtraDataItem name="VBoxInternal/Devices/VMDev/0/Config/GetHostTimeDisabled" value="1"/><!-- typo -->
<ExtraDataItem name="VBoxInternal/Devices/VMMDev/0/Config/GetHostTimeDisabled" value="1"/><!-- こっちが正しい設定 -->

上の行がtypoした設定で、下の行が正しい設定(VMMDevというのを「VMDEV」と書いている)。

上のtypoは既にVagrantfile上では直してるのに、前にtypoした箇所の設定がVMの設定ファイルに残り続けてる...

この設定ファイル、先頭の方に「いいか、いじるなよ! 絶対にいじるなよ!」と注意書きをされてるのですが、どうみてもこれが原因なので、typoの箇所を削除。

で、もう一度仮想マシンを立ち上げてみたら普通に立ち上がりました。

午前中いっぱい使ってしまった...下手にtypoもできないこんな世の中じゃ....

ようするにVagrantfileは冪等性のない設定ファイルであり、typoしたままvagrant upすると、そのtypoがキャッシュされたまま設定ファイル(*.vbox)に残り続けることがある...ということはよく覚えておいた方が良さそうです。

縦書き文庫に「チップ記法」を追加しました

チップ記法について

エディタに以下のようなボタンが追加されていますが、これは「チップ記法」という新しい記法のボタンです。

f:id:convertical:20131220172515p:plain

押すと

((タイトル:内容))

などと注入されますが、これがそのままチップ記法の文法になっています。

実際に使ってみる

例えば

新しい((パソコン:パーソナルコンピューターの略))が欲しい。

と書くと、本文ではこんな風に表示されます。

f:id:convertical:20131220173020p:plain

ここで「パソコン」というリンクをクリックすると

f:id:convertical:20131220173046p:plain

みたいに開きます。新しいパソコンが欲しい。

表示は縦書きにしようか横書きにしようか迷ったのですが、補足情報なので横書きを選びました。

エディタから傍点、圏点、見出しなどが入れやすくなりました

エディタ画面のボタンを改善しました。

f:id:convertical:20131219181116p:plain

圏点と傍点はこんな感じで入れられるように。

f:id:convertical:20131219181210p:plain

見出しもこういう風に入れられるようになりました。

f:id:convertical:20131219181253p:plain

アメリカにおける技術書の電子出版ノウハウを綴ったブログが面白かった

アメリカではすっかり電子出版が一般化しているようです。しかし実際はどんな感じなのか知らなかったので、興味本位で読み始めたら面白かった記事を紹介します。

$16,228 earned, 1014 copies sold: Lessons learned from a year as a self-published author

sublime textというエディタの技術書を出版した経験について綴られています。

結果的にかなり儲かったみたいです。副業で書いた電子書籍が1000部も売れて、日本円で160万ぐらいになったなら、そこそこ成功した例なんじゃないでしょうか。

内容を要約すると、こんな感じです。

  • twitterは営業ツールとしては殆ど役に立たない。フォロアーをカスタマーに変えることは難しい。
  • 一方でメールは最強の営業ツールである。
  • 値段は相場(アメリカでは$9.99が相場だと思われている)じゃなく、自分が考える価値で付ける。安売りしない。
  • 自分の場合は$19で売り出した。sublime textを使うような顧客はリッチな客が多いと踏んだからだ。
  • 自分の使っているLeanPubというサイトでは、購入者が好意で余計に払うことが出来るオプションを設定できるのだが、38%もの購入者が余計に払ってくれた(中には$50出してくれた人もいた!)。それは全売り上げの48%にも上った。
  • 営業活動が突如として泣かず飛ばすになって、売り上げが横ばいになることもあるけど、めげない。いつブレークするかは誰にもわからない。
  • 自分の場合は有名ブロガーに紹介されたり、他の出版社から出版を依頼されたり、他の執筆者に一緒に書籍のセット売りをしないか、と持ち掛けられたりした。
  • 技術書を出版した上で後悔していることとしては、初版に内容を盛り込みすぎたこと。技術変革のスピードは速い。書いてすぐに内容が陳腐化してしまった。コンパクトなボリュームを、タイムリーに出すほうが良さそうだ。


こういう感じです。

とにかく営業ツールとしてのメールの強力さを強調しておられるように感じました。

実際この方のブログを見ても、記事の最後とかサイドバーの目立つ場所にメーリングリストへの登録案内があります。

それだけメールを重視しているということなんでしょう。

ホームページもツイッターも、こういう風に明確な目的を持った上で運営したら、結果に結びつきやすいのかもしれませんね。

この方も始めたばかりの頃は、100人ぐらいしかフォロアーがいなかったし、ブログも両手で数えられるぐらいの人数しかアクセスがなかった、とのこと。

何事もやり方しだいってことなのかなあ……

何かしらの電子出版を志している人にとっては、参考になる話しなんじゃないでしょうか。

unicode substring of OCaml for application layer

cwn経由でextlibにUTF8.substringが定義されたと知り、じゃあオレオレな実装からサヨナラできるかな、と思って試してみましたが、

assert_equal (UTF8.substring "hoge" 0 5) "hoge"

は残念ながら "out of range" という例外で終わってしまう……

extlibのsubstringは、LLなsubstringとは違い、境界を超えるような値の定義を許さないみたいです。

でもこれだと、常に利用者が境界値のチェックを義務付けられるわけで、アプリケーション側からは使いにくいかなあと。

だって、例外を捕まえるにしても out of rangeってだけじゃ、どういう風に溢れたのかわからないですし。

substring "hoge" 0 100 で溢れるのも、substring "hoge" 100 1で溢れるのも、同じ例外ですよね。

でもLLな感覚のsubstringなら、前者は"hoge"を返したいし、後者は空文字を返したい。

というわけで、以下がjingooでの実装です(jingoo/jg_utils.mlより抜粋)。

open ExtLib

let rec substring base count str =
  let len = UTF8.length str in
  if base >= len || count = 0 then
    ""
  else if base = 0 && count >= len then
    str
  else if base < 0 then
    substring (len + base) count str
  else if base + count >= len then
    let lp = UTF8.nth str base in
    let rp = UTF8.next str (UTF8.last str) in
    String.sub str lp (rp - lp)
  else
    let lp = UTF8.nth str base in
    let rp = UTF8.nth str (base + count) in
    String.sub str lp (rp - lp)


振る舞い方はこんなです。

assert_equal (substring  0  0)  "hoge"  ""
assert_equal (substring  0  1)  "hoge"  "h"
assert_equal (substring  0  4)  "hoge"  "hoge"
assert_equal (substring  0  5)  "hoge"  "hoge"
assert_equal (substring  1  1)  "hoge"  "o"
assert_equal (substring  2  1)  "hoge"  "g"
assert_equal (substring  3  1)  "hoge"  "e"
assert_equal (substring  4  1)  "hoge"  ""
assert_equal (substring  5  0)  "hoge"  ""
assert_equal (substring  5  1)  "hoge"  ""

(** negative base *)
assert_equal (substring  (-1)  1)  "hoge"  "e"
assert_equal (substring  (-2)  1)  "hoge"  "g"
assert_equal (substring  (-3)  1)  "hoge"  "o"
assert_equal (substring  (-4)  1)  "hoge"  "h"
assert_equal (substring  (-4)  2)  "hoge"  "ho"
assert_equal (substring  (-4)  3)  "hoge"  "hog"
assert_equal (substring  (-4)  4)  "hoge"  "hoge"
assert_equal (substring  (-4)  5)  "hoge"  "hoge"
assert_equal (substring  (-5)  1)  "hoge"  "e"