« 2010年3月 | トップページ | 2010年5月 »

2010年4月の10件の投稿

2010/04/21

NicoBrowser ver.0.6.0 保存ファイル名の命名規則設定

ダウンロードはこちらから。

今回の変更点は以下のとおりです。

  • ver.0.4.xからver.0.5以降にアップグレードできない問題を修正しました。
    • 本バージョンをインストールした後、初回実行前に、次のようにsync4オプションを指定してコマンド実行して下さい。 java –jar NicoBrowser.jar sync4
    • ちなみに、ver.0.5.0から0.6.0へは特別な操作は必要ありません。
  • 保存ファイル名をある程度自由に設定できるようになりました。
    • 従来は動画タイトル名がファイル名になる、という固定動作でした。
    • コンフィグファイル(nicobrowser.properties)を直接編集すると文字エスケープが面倒なので、設定画面から設定する方が楽だと思います。-pオプションを指定してコマンドを実行すれば画面が開きます。 java –jar NicoBrowser.jar –p

ver.0.5.0のときに予告していたver.0.5.1はすっ飛ばして、本バージョンになりました。

新機能のファイル名命名規則ですが、例えば以下のような指定が行えます。

  • さきゅばす互換命名規則: [{id}]{title}
    • 生成例: [sm8994079]クマさんチャーハン
  • NicoCache_nl互換命名規則: {id}{low}_{title}
    • 生成例: sm8994079low_クマさんチャーハン
  • Craving Explorer互換命名規則: {title}
    • 生成例: クマさんチャーハン

その他、ファイル名として使用できない文字を特定の文字に置き換える設定もあります。詳細は添付のREADME.txtを読んでください。

 

元々はNicoCacheと同じ命名規則であれば、NicoCache用のキャッシュとして用いることができて良いのでは、というメールを頂いたことに対する追加機能です。

この点については、現時点でわかっているところで、以下のような注意点があります(メールを頂いて初めてNicoCache(正確にはNicoCache_nl)を利用したので、他にもあるかもしれません)。

  • NicoCache_nl稼働中に追加したキャッシュファイルはそのままでは認識されません。再起動を行うか、再読み込みを行う必要があります。
    • 再読み込みはwww.nicovideo.jpを開いたとき画面右上に表示されるリンク”キャッシュ”から行うことができるようです。
  • 動画IDがsoから始まる公式動画(?)はNicoBrowserではNicoCache_nlと同じようには取得できないことがあります。つまりキャッシュとしてみなされない場合があります。
    • NicoCache_nlではページをスクレイピングしてjavascriptのコードの中から取得しているようです。が、NicoBrowserでこれをやるのはちょっと…というところです。
    • 公式動画の全体に占める割合から考えると、実用上あまり問題はないのかなと思っていますが、どうでしょう…
  • あくまで「互換」なので、同一のファイル名になるわけではありません。NicoCache_nlもいくつか命名ルールを持っている(tidyTitleとか)ようで、そういう独自ルールは置いとこう、という思いもあります。
    • これも実用上は問題ないでしょう。

 

この機能の対応中、そういえば元々はCraving Explorerに命名規則を合わせてたんだった…ということを思い出しました。昔はmp4ファイルも拡張子がflvでダウンロードされてたので、わざわざそういうオプションを付けてたことなんかもありました。

coroid ver.0.3.2 Linux対応

ダウンロードはこちらから。なお、本バージョンはLinux対応のみの修正で、機能的な追加点はありません。

coroidをLinuxで動かせないか、という質問がありましたので、Linux用のバイナリを作成してみました。導入手順はこちらに記載しています。

上記のページにも記載していますが、SDL系のライブラリは添付していませんので別途導入する必要があります。

soを用いるLinuxバイナリを配布した経験がないので、もしかすると環境によって動作しない等があるかもしれません。問題があれば内容をご連絡いただければと思います。

 

Linuxバイナリを配布する場合、SDLみたいなメジャーなシェアードライブラリってどうするのが一般的なんでしょうね。Windowsみたいにexeと同一ディレクトリに置いておけば優先的に読み込んでくれる訳でもないし。

ちなみに私が動作確認したのはPortable Ubuntu Remix上です。普段使用しているLinux PCはGrailsとffmpegを起動させられるスペックがありませんでした…

coroid-server Linux版

実験的なバイナリであり、動作確認はUbuntu9.10(i386)でのみ行っています(過去にCentOS5.3(i386)でも確認はしています)。

coroid Linux拡張パック最新(2010/04/23, rev2)版をダウンロードする

 

導入方法

1.

coroidのページからcoroid本体(ver.0.3.2以降)をダウンロードし、適当な場所に展開します。また、このページの「動作環境」に書かれている動作環境も設定して下さい。

2.

さきゅばすのNicobrowser拡張 Linux版のページから拡張パックをダウンロードし、展開後の2ファイルを、coroid/binに配置します。また、このページに記載しているSDL関連ライブラリを導入して下さい。

3.

本エントリ冒頭のリンクからcoroid Linux拡張パックをダウンロードし、展開後の2ファイルを同じくcoroid/binに配置します。

4.

coroid/saccubus.xmlを開き、以下の項目を環境に合わせて修正します。

  • FontPath
    • 使用するフォントのパスを指定して下さい。
    • 例: /usr/share/fonts/truetype/ttf-japanese-gothic.ttf
  • FFnpegPath
    • bin/ffmpeg
    • 今気づきましたが誤字ですね…mじゃなくてnになってる…
  • VhookPath
    • bin/libnicovideo.so.1.0.0
  • ShowVideo
    • デフォルトのtrueだと、動画変換過程が動画ウィンドウで表示されます。不要であればfalseを指定してください。

以上がLinuxで動作させるために必要な設定です。後はcoroidのページの「実行方法」の項を参照して下さい。

2010/04/16

NicoBrowser ver.0.5.0 投稿者設定不具合の修正

動画ページにアクセスした際、ipum用に投稿者名の取得する機能があるのですが、この機能が正常に動作していない問題を修正しました。

また、内部で利用しているライブラリにLiquiBaseというものがあるのですが、ちょっと使い方に問題がありました。具体的には、path.dbの値を途中で変更するとDB関連のエラーでNicoBrowserの起動に失敗する、というものです。この修正を行ったので、従来のver.0.4.Xとは互換性が無くなってしまいました…ので、現在ver.0.4.Xを利用している方は、本バージョンにはアップデートしないで下さい

上記の問題はver.0.5.1で対応する予定です。多分来週中には…

ダウンロードはこちらから。

2010/04/13

さきゅばすのNicoBrowser拡張 ver.1.4.0 Linux対応

ダウンロードはこちらから。

coroidをLinuxで動かせるのか、という質問をもらいました。

coroidは内部ではいくつかのWindowsネイティブバイナリを利用していて、そのうちのひとつにさきゅばすがあります。

Linuxでcoroidを動かすためにはさきゅばすがLinuxで動かないと駄目だろうなあ(他のバイナリはUnix由来のものなので多分そんなに難しくないだろうけど)、と思いながら試してみたところ、いくつかの修正が必要だったものの予想以上にあっさり動作しました。

そんなわけで本バージョンでさきゅばすをLinux対応させてみました。Windowsでの動作は、前回のver.1.3.5から変更はありません。

同梱のffmpegにリンクさせたライブラリはx264とfaadで、これは最低限coroidに必要なものです。それ以外のライブラリは…ビルドが面倒なので見送りました。というか、私が利用しているLinux PCは7-8年ほど前のものなので、ビルドが遅すぎる…こんなときのためのPortable Ubuntuだ!とも思ったのですが、こちらも何かディスクアクセスに違和感があって(ハードディスク自体に問題があるのかも)ビルド環境を整えるのに躊躇してしまいました。Linuxでさきゅばす用のffmpegをビルドしてやる、という方がいらっしゃればありがたいのですが。

なお、現状、Linuxで上記以外のライブラリを用いてエンコードを行いたい場合、Wineを用いてWindows版をLinuxで動かす方法もあるようです[参考: さきゅばすをLinuxで動かす - kento日記]。

さきゅばすのNicoBrowser拡張 Linux版

さきゅばすのNicoBrowser拡張(ver.1.4.0以降)を、Linuxで動作させるようにするための拡張パックです。

動作確認はUbuntu 9.10(i386)で行っていますが、CentOS5.3でも動作すると思います。

動作させるためには、SDL, SDL_ttf, SDL_gfxが導入されている必要があります。ソースからmakeする場合はSDL_ttfがfreetype2に依存していたと思いますので、こちらも必要になります。メジャーなライブラリなので、ディストリビューション公式のパッケージが配布されていたりすると思います。Ubuntuでは、SDLは標準でインストールされている様で、libsdl-ttf2.0-0, libsdl-gfx1.2-4の2パッケージを追加導入することで動作しました。

その他、Linuxで動作させるためには、さきゅばす上で少なくとも以下の設定変更を行う必要があります。

  • 「動画設定」タブの「FFmpeg」を本パックのものに修正する。
    • 例: bin/ffmpeg
  • 同じく「動画設定」タブの「拡張vhookライブラリ」を、本パックのものに修正する。
    • 例: bin/libnicovideo.so.1.0.0
  • 「変換設定」タブの「フォントパス」に、適切なフォントを指定する。
    • 例: /usr/share/fonts/truetype/ttf-japanese-gothic.ttf

 

Linux拡張パック最新版(2010/05/03, rev3)をダウンロードする

ソースコードはWindows版と同じですので、必要な方はさきゅばすのNicoBrowser拡張ページからダウンロードして下さい。ただ、改行コードがCRLFだったり、shファイルに実行権限が付いていなかったりなどの理由で、若干修正していますので、修正後ファイルを以下に置いておきます。私が配布しているffmpegバイナリはライブラリリンクが少ないので、ffmpegはご自身でビルドした方が高画質/高音質な動画を作成できると思います。

ffmpegのビルド手順(上記のソースを使用せず、公式リポジトリからビルドする手順)をこちらに記載していますので、最新版のffmpegを利用したい場合はこちらを参照してください。

2010/04/06

Google Chromeも非同期GET(Ajax GET)がキャッシュされる(特定条件下で)

前回、Android1.6のブラウザで非同期GET/POSTがキャッシュされる、ということを書きました。

この際、PCのブラウザではどのような挙動になっているのか気になったので調べてみました。試したページは前回と同じこちら

PCでのキャッシュロードは、一旦上記ページを開いた後、別のページに飛んで、その後

ブラウザの”戻る”ボタンで戻ってから再度実行しました。

色んなサイトでIEはXMLHttpRequestのGETがキャッシュされる、と書いてありましたが、IE8では仕様変更されたのでしょうか、特に他のブラウザと動作に差異はありませんでした。

一方、Google ChromeのGETは、前回示したAndroidのブラウザと同様、キャッシュロードの場合、GETのレスポンスにもキャッシュが用いられるようでした。ただし、Androidのブラウザと異なり、POSTは都度リクエストを行っているようです。

ついでにiPod touchのSafariでどうなるか試そうと思ったのですが、キャッシュロードされる条件がわかりませんでした…

下の表で、○はサーバにリクエストが行われた、×はリクエストが行われなかったことを表しています[追記:Firefox3.6.3でのアクセスログを見直したところ、Javascript ONの状態で「戻る」ボタンを押すと、ページ自体をサーバにリクエストし直していました。つまりiPod touch Safariと同様でしたので下の表では”?”表記に直しました]。

  サーバロード キャッシュロード
IE8 GET
IE8 POST
Firefox3.6.3 GET
Firefox3.6.3 POST
Safari4.0.5 GET
Safari4.0.5 POST
Google Chrome 5.0.342.8 beta GET ×
Google Chrome 5.0.342.8 beta POST
Android1.6 Browser GET ×
Android1.6 Browser POST ×

Android Browserの挙動説明のついでに、上記ブラウザの挙動もキャプチャしてみました。7分25秒辺りからです。

RFC2616の9章によれば、GETもPOSTもある条件が揃えばキャッシュしても良いみたいですね。今回の件がその条件に当てはまっているのかは理解できていませんが。

あと、昔のSafari(1.3のころ)でもXMLHttpRequestのGETでキャッシュが用いられるという動作になっていたそうで、これの回避策としてリクエストヘッダのIf-Modified-Sinceに古い日付を指定する、というものがあったそうです。jQueryでの設定方法はこちらですね。

でも字面だけ見ると、modifiedなのかどうかって、サーバが判断すること(200(OK)なのか304(Not Modified)なのか)であってクライアントがリクエストするかどうかじゃ無いような気もしますが。今持ってるキャッシュは明らかに指定日付より新しいからリクエストしなきゃ、とかなんでしょうか。でも今持ってるキャッシュが古くても(というか古いからこそ)リクエストしないと分からないような気も。

2010/04/05

coroid ver.0.3.1 トランスコード状況の表示

ダウンロードはこちらから。

私が常用しているブラウザはGoogle Chrome betaなのですが、いつの間にかmp4のインライン再生ができるようになってますね(5.0.342.8 beta)。coroidを手っ取り早く動かすのにPCを使用しているのですが、再生ボタンで再生できるようになってびっくりしました(以前はダウンロードになってました)。Google ChromeにFlash Playerが統合(バンドル?)された、というニュースもありますし、これに関連するんでしょうか。でもバージョン違うしなあ…

本バージョンでの変更点は以下のとおりです。

  • 動画の変換状況が表示できるようになりました。
    • STの列をクリックすると、現在の状況に更新されます。
  • 動画詳細を隠せるようになりました。
    • 従来は一旦表示させるとリロードするまで表示されっぱなしでした。
  • 投稿者メッセージ(動画の説明文)に改行が含まれていると一覧の表示が失敗する不具合を修正しました。
    • sm10203496なんかが該当します。改行が含まれている動画を含む一覧を表示しようとすると、例外メッセージが表示されたページに飛んでしまっていました。
    • 改行って含めることできたんですね…多くの投稿者はスペースで位置調節しているので、てっきりできないものかと。

今回の対応にあたって、色々な動画の変換を行ってみたのですが、変換に失敗する動画結構ありますね…変換処理が終わったように見えたにも関わらず失敗になっている状況も何回か発生たりして(しかも再現性無し)、ちょっとこの部分も見ないとなあ、と思っています。

2010/04/03

Android web browserは非同期POST(Ajax POST)もキャッシュされる場合がある

前回のエントリで記載した問題が解消しました。再現コードはこちら(説明はIssue7519)で、原因は以下のとおりでした。

  • IEではXMLHttpRequestのGETがキャッシュされるため、回避策としてPOSTを利用する、というものがあるが、Android1.6 web browserではPOSTもキャッシュされる場合がある。
  • jQuery.ajaxの引数”cache”は、GETの場合にしか挙動が変わらない。(jQuery 1.4.1。なお上記再現コードは1.3.1ですが同様です。)

まず前者については、前回説明した通りです。サーバロード、メモリロードの状態では非同期リクエストはキャッシュされないのですが、キャッシュロードの状態では一度行ったリクエストは再度サーバへリクエストすることはありません。GETもPOSTも同様です。

GETの場合はIEと同様ダミーGETパラメータを追加することでユニークなURLを生成しキャッシュを回避できます。POST場合は…すみません、jQuery.ajaxでPOSTパラメータの設定方法が分からないので未検証です。

次に後者について。まだ他人のjavascriptを見てどのような挙動になるのか理解するレベルには達していないので、WireSharkを使ってパケットを見てみました。POSTのときはcacheがtrueだろうがfalseだろうが同じリクエストが行われていました。

以上より、jQuery.ajaxをGETにしてなおかつcache:falseを設定することで、キャッシュロードの状態でも非同期リクエストが行えるようになりました。本来POSTであるべきところもGETにしてしまうのは気持ち悪いですが…

また、cache:falseを多用するとAndroid上でのページの読み込みが目に見えて遅くなったような。ページキャッシュのドロップ(ブラウザを開くとホームページ(google.com)に戻ってしまう)も頻発しているような。う~ん。

なお、Grails(gsp)でremoteLinkタグを使用すると、デフォルトではPOSTリクエストになりますし、GETに変えてもパラメータをユニークにする必要がありますので、素直にjQueryを直で使用した方が良いような気がします。

2010/04/02

Android web browserのajax(asynchronous request)の挙動が変だ

変だ、というのはあくまで私の想定していた動作と異なるという意味です。勉強始めたばかりなので本当におかしい動作であるのかどうかは確信持てません。詳しい方、ツッコミお待ちしております。

coroidでjQuery.ajaxを用いた非同期のHTTP通信を行うようにしたのですが、HT-03A(Android1.6)のwebブラウザで想定通りに動かない状況が、ある特定条件下で発生しています。

以下、Android webブラウザの挙動の種類、私がjQuery.ajaxで行っている非同期要求の方法を説明し、その後今回発生している問題について述べます。

 

まず、Androidのwebブラウザの挙動について説明します。webブラウザがページを表示する際、以下の3パターンの表示方法があるようです。

  • サーバにリクエストし、レスポンスを表示する(以下、サーバロードと呼称)
    • ハイパーリンクをクリックする、「再読み込み」ボタンを押す、など。
  • メモリからの再表示(?)(以下、メモリロードと呼称)
    • webブラウザでページを表示している状態から、Homeボタンを押してHomeに戻った後、すぐにまたwebを表示させた場合など。
  • キャッシュからの再表示(?)(以下、キャッシュロードと呼称)
    • webブラウザでページを表示している状態から、Homeボタンを押してHomeに戻った後、他のアプリで作業を行って、その後webアプリを起動した場合。
    • coroidでは、intentで動画プレイヤを起動し動画再生終了後webブラウザに戻ってきた場合は大抵これです。

サーバロードとそれ以外のロードは、PCのwebブラウザでもあるので違いはイメージしやすいと思います。

メモリロードとキャッシュロードは、Androidのプロセスライフサイクルの特性(参考:コンポーネントのライフサイクルANDROID developers デベロッパーガイド)によるものでしょう。

メモリロードとキャッシュロードを画面上の表示から見分ける方法は以下のとおりです。メモリロードは、ページを開くと即座に描画が行われます。一方、キャッシュロードは、画面上部にプログレスバーが表示されます。なお、サーバロードでもプログレスバーは表示されますが、キャッシュロードのプログレスバー進捗は、サーバロードに比べて速いです(ネットワークを介しませんので)。

 

次に、私がHTTP非同期通信を行っている方法について説明します。jQueryを用い、xhtmlのhead部で、$(function(){init();});というような形で初期化関数を呼び、初期化関数の中でテキスト文字列をクリックした場合に非同期リクエストを行う、というようなイベントリスナを設定しています。なお、body onload=”init()”という形も試してみましたが、同じ現象が発生しました。

 

本題の、想定外のwebブラウザ動作について述べます。

サーバロード、メモリロードにおいては、非同期リクエストは正常に発行されています。しかし、キャッシュロードにおいては、リクエストもキャッシュされているようで、以前リクエストしたことがあるURLに対しては実際にはサーバにリクエストが行われません。

検索してみたところ、IEでもAjaxリクエストがキャッシュされてしまうという仕様があるようで、これの対策も記載されていました(参考:IEでAjaxリクエストをキャッシュさせない方法 - PHPプロ!ニュース)。

  • GETでなくPOSTを用いる
  • リクエストのパラメータをユニークにする

初めからPOSTリクエストなので前者は実施済み、後者はjQuery.ajaxの引数cacheで設定すれば良さそう(参考:IEにてAjax通信がキャッシュされる、F5でリフレッシュしてもダメ - 不会忘記的一天)なので試してみましたがこちらでもサーバにリクエストは行いませんでした。

上記サイトで記載されているIEでの現象と同様、Android webブラウザも、再読み込みを行ってもキャッシュは消去されないようです。ただし、再読み込みを行うとサーバロードになりますので、再読み込み直後は想定通りサーバにリクエストが行われます。が、色々操作しているうちにまたキャッシュロードモードになると、昔のキャッシュが使用されるようになり、いつの情報だよ、というようなレスポンスを受け取ってしまうことになりました。なお、webブラウザの設定画面で「キャッシュを消去」を選択すると、それ以前のキャッシュは用いられないようです。

 

まとめます。

  • Android1.6のwebブラウザではAjax通信がキャッシュされないモードとされるモードがある。開発者はこのモードを制御することができないし、エンドユーザには見分けがつかない。
  • Ajax通信がキャッシュされるモードでは、POSTだろうがパラメータ変えようが、過去通信したURLに対してはリクエストを行わない。

…というように見える、というのが現時点での私の見解です。

 

追記:

Issue 2171: Web Browser tries to re-download a webpage that has already been loaded.Comment60を見て、そういえばGoogle Readerはどうなっているのだろう、と思ってhttp://www.google.com/reader/i/ で試してみたところ、フィード表示部分はサーバロードかメモリロードになり、キャッシュロードは発生しないように見えました。ヘッダ部の

Expires: Fri, 02 Apr 2010 12:24:47 GMT

Cache-Control: private, max-age=0

あたりが関係しているのかな、と思ってxhtmlのheadにmeta http-equiv="Cache-Control"なんかを設定して試してしてみたのですが、状況は変わりませんでした。

余談になりますが、Should HTTP header "cache-control: private" force "expires" to 0?というMLのメッセージ中に引用されているコメント(原文はこちら)

According to the spec, 'no-cache' means that the content must be re-validated on every load. It does not mean that the content can not be cached.

は気になるところではあります。

後はGmailみたいにhttps通信の場合でも、サーバロードかメモリロードいずれかになるようです。coroidの通信もhttpsにすれば想定する動作になりました。が、根本的な解決策にはなっていないですね…

取り敢えず、Google Readerの動作を検証すべきでしょうね。

« 2010年3月 | トップページ | 2010年5月 »

other sites

  • follow us in feedly
  • github
  • stackoverflow

ソフトウェアエンジニアとして影響を受けた書籍

  • Christain Bauer: HIBERNATE イン アクション

    Christain Bauer: HIBERNATE イン アクション
    理論と実践が双方とも素晴らしい製品であるHibernate。本書はそのプロダクトを書名に冠していますが、Hibernateを使うつもりがなく、ORマッピングの解説書として読むにしても十分な良書です。Second EditionとしてJava Persistence With Hibernateという書籍も出版されていますが、残念ながら現在のところ 和訳はされていません。-インアクションは2.xの、Java Persistence-は3.1の頃のものなので、最新版とはちょっと違うところもあることに注意。 (★★★★★)

  • アンドリュー・S・タネンバウム: 分散システム 原理とパラダイム 第2版

    アンドリュー・S・タネンバウム: 分散システム 原理とパラダイム 第2版
    クライアント/サーバシステムを構築する上で必要となる知識が総論されてます。Web技術者も、フレームワーク部分を開発するのであれば必読。 (★★★★★)

  • Joel Spolsky∥著: ジョエル・オン・ソフトウェア

    Joel Spolsky∥著: ジョエル・オン・ソフトウェア
    前述の書籍「ソフトウエア開発プロフェッショナル」をより砕いたもの、という感じでしょうか。 前書きではプログラマでなくSE向けの本のように書かれているが、プログラマが読んでも面白い本であると思われます。 SEになった新人(あるいはそういう会社に入る/入りたての人)にとっては、これからどういったことが仕事を遂行していく上で起こりえるのか、どのように考えて行なっていけばいいのか決定する助けになると思います。 元は″Joel on Software″というブログの記事で、web上でも一部日本語で読めます。 http://japanese.joelonsoftware.com/ (★★★)

  • ドナルド・C・ゴース,ジェラルド・M・ワインバーグ: ライト、ついてますか

    ドナルド・C・ゴース,ジェラルド・M・ワインバーグ: ライト、ついてますか
    問題解決(一昔前のの流行語で言うところの『ソリューション』)能力は、システムエンジニアのスキルとして備えるべきもののうちのひとつです。しかし、これは難しい。学校で出されるテストと違い、唯一の、(問題提出者が想定している)解を求めるだけが「問題解決」では無いからです。そもそも、何が問題なのか、それは本当に問題なのか、それは本当に解決すべき問題なのか、その問題解決方法は正しいのか、などを解決しなければ、「その解は正しいのか」に辿りつくことができません。この本の最も良いところのひとつは、本があまり厚くないこと。すぐに読めるし、何回も読み返す気になるでしょう。 (★★★★★)

  • スティーブ・マコネル: ソフトウエア開発プロフェッショナル

    スティーブ・マコネル: ソフトウエア開発プロフェッショナル
    コードコンプリートで有名なスティーブマコネルの著書。新人SEに読んで欲しい。個人として業界の中でどうあるべきか、組織としてどうあるべきか、SEのプロ意識とは?SEの心構え概論、といったところでしょうか。また、業界における資格の重要性についても説かれています。この業界では資格が特に軽んじられる傾向がありますが、この傾向はどんな弊害をもたらすのか、将来的にこの業界は資格に対してどのような姿勢で臨んでいくべきなのか。日経BP社では(他の出版社もだが)最近、似たような類いのあまり面白くない書籍が乱出版されていますが、この本は別格だと思うので安心して購入して欲しいと思います。 (★★★★★)

無料ブログはココログ