2013年12月24日火曜日
IDを作ったりWorker作ったりめんどくせぇ!! P2Poolで掘る
ソロでGrandcoinを掘るのも飽きた(まだ2,000GDCしか掘ってないけど)ので、再度Anoncoinに戻ろうかと思いましたが、前に使っていたPoolサイトは死んだままです。
なんか数日間は、バックアップ取ってある的なコメントが表示されていたのですが、もはやHTMLすら返さなくなりました。
やはりfeeが0%のとこは、こんなものなんでしょうか。
ということで、別のPoolサイトを探していて見つけたのが、P2Poolです。
どうやら有名なサイトなようで、IDを作ったり、Workerを作ったりといった、めんどくさい登録作業が不要なサイトです。
トップページを表示してみると、いつもの見慣れたPoolサイトテンプレで作成されたものでは無いので、他のサイトとは様子が異なります。
かなり色々な通貨に対応していて、ズラっと設定値一覧が羅列されています。
見ていくと、どうやら通貨ごとにポート番号が分けられているようです。
で、掘り方はというと、画像の設定にしてcudaminerやcgminerで掘るだけです。
ユーザ名は、掘りたい通貨の自分のアドレスで、この場合はAnoncoinのアドレスです。
cudaminer.exe -o http://p2pool.org:11775 -u [自分のアドレス] -p [適当なパスワード]
あとは待つだけなのですが、ページ一番上の各通貨のリンクをクリックすると、現在のPoolの状態が分かります。
通貨のページに遷移すると、いくつかメニューがあります。
Pool stats
Expected time until payoutが45時間となっていて、これは45時間後に支払われるということではなく、確率的に45時間に1回このPoolで新規ブロックを発見するということだと思います。
新規blockを発見するごとに支払いがあるって感じですかね。
DifficultyとPoolのハッシュレートから計算されている確率のようで、いくつかの通貨で実際計算してみましたが大体計算が合うのでそういうことでしょう。
Payout
新規block発見時にどれだけ貰えるかということだと思いますが、全員分足すと1ブロックあたりの報酬である5ANCになるので、貢献度のシェアみたいなもので計算されているんでしょう。
あとは、Poolの状況や、各Miner達のハッシュレート、Payoutがグラフで見れるGraphsなんかも面白いですね。
基本的に後は待つだけですが、しばらく放置した後Walletを開いてみると、「Immature」という項目に0.03915962ANCの表示が。
トランザクションを確認すると以下。
Statusのところが50で、matures in 70 more blockとあるので、新たに120ブロック確認されると、確定するってやつですね。
しばらく時間が経ってからWalletを確認すると以下。
Balanceのほうに移りました。
P2Poolなかなかお手軽ですね。
2013年12月21日土曜日
初ゲット!!Grandcoinをソロマイニング
放置しておいたGrandcoinのWalletを見てみると変化が。
掘れてる!!
1GDCあたり0.00000255(2013/12/21 16:50時点)で取引されているので0.00255BTCで、1BTCあたり653.64999ドル(またずいぶん暴落しましたね)で取引されているので、1.6668074745ドルゲットということですね。
日あたりの電気代とトントンかちょっと儲かるぐらいでしょうか。
まぁもはや儲かるとか損するとかはさておき、数字が増えていくのがなんだか楽しいですね。
Bitcoin暴落とかもはやどうでも良くなってきましたw
ということで、Difficulty2.0ぐらいの通貨であれば、130khash/sのへっぽこGPUでも、日に1回ぐらいは掘れるということですね。
さて、RADEON買ってこようかなぁ。。。
Poolサイトが死んだまま帰ってこない。。Anoncoinを自力で掘る
タイトルの通り、Poolサイトが落ちたっきり帰ってこなくなりました。
いくらか溜まっていたのに送金できないまま。。
そういえば、結局色々弄っているものの、BitcoinどころかAnoncoinやさらにマイナーな通貨も含めて、どの通貨の欠片も手に入れていません。
こうなったら確実に自分のWalletに突っ込むために、自力で掘る方法を試してみます。
自力で掘るといっても、ハッシュアルゴリズムにSHA-256を使っている通貨については、ASIC(いわゆる専用チップ)のせいで、Difficultyがとんでもないことになっていて、ソロマイニングはもはや無理ゲーと化しています。
それに対し、ハッシュアルゴリズムにScryptを使っている通貨についてはASICがまだ無いようで、低Difficultyなものもたくさんあります。
AnoncoinはScrypt系なので、GPUでも掘れるのではないか?
ということで、とりあえずコイツを掘ってみます。
ソロマイニングについて調べていて気づいたことは、この手の仮想通貨は同じソースを元に作られているので、Walletソフトの作りや、設定方法なんかはみんな一緒ということです。
つまり、基本的には通貨を変えても以下の方法で採掘可能です。
まずWalletをインストールし、同期すると以下にフォルダが作成されます。
C:\Users\[ユーザ名]\AppData\Roaming\Anoncoin
※フォルダ名はAnoncoinであればAnoncoin、GrandcoinであればGrandcoinです。
上記のフォルダに設定ファイルを作成します。
テキストファイルを作成し、以下の名前、拡張子に変更します。
anoncoin.conf
※ファイル名はAnoncoinであればanoncoin.conf、Grandcoinであればgrandcoin.confです。
設定ファイルの中身は以下のようにします。
rpcuser=[任意のユーザ名]
rpcpassword=[任意のパスワード]
rpcallowip=127.0.0.1
rpcport=9332
daemon=1
server=1
gen=0
このrpcportが通貨によって異なるようです。
マイニングソフトの起動用にbatファイルを作成します。
batファイルは、作成した設定ファイルにポート番号、ユーザ名、パスワードをあわせて作成します
cudaminer.exe -o http://127.0.0.1:9332 -u [任意のユーザ名] -p [任意のパスワード]
※cudaminerの場合。
あとはWalletを起動して(もともと起動していたのであれば再起動)、作成したbatファイルからcudaminerやcgminerを起動して掘るだけです。
で、まぁ2~3日ぶん回してたわけですが、全く掘れる気配がしません。
以下のようなログが延々流れていきます。
[2013-12-21 00:57:45] GPU #0: GeForce GTX 660, 656640 hashes, 131.14 khash/s
[2013-12-21 00:57:50] GPU #0: GeForce GTX 660, 656640 hashes, 131.16 khash/s
[2013-12-21 00:57:55] GPU #0: GeForce GTX 660, 656640 hashes, 131.08 khash/s
[2013-12-21 00:58:00] GPU #0: GeForce GTX 660, 656640 hashes, 131.27 khash/s
[2013-12-21 00:58:05] GPU #0: GeForce GTX 660, 656640 hashes, 131.14 khash/s
[2013-12-21 00:58:10] GPU #0: GeForce GTX 660, 656640 hashes, 131.24 khash/s
[2013-12-21 00:58:15] GPU #0: GeForce GTX 660, 656640 hashes, 131.01 khash/s
これは何か間違っているのではないかと調べてみたのですが、AnoncoinのDifficultyは35.7576とかで、ちょっとソロではきついレベルでした。
自分の130khash/sそこそこのハッシュレートでは、2週間に一回掘れるぐらいですかね?
ちょっと厳しいです。
ソロマイニングを短期間で確実に成功させるには、さらにDifficultyが低いマイナー通貨にする必要があるので、Difficultyが2.4607ぐらいのGrandcoinを掘ってみます。
Grandcoinはブロックあたり1grand(1,000)支払われる通貨で、今ならそこそこ割りのいい通貨です。
ブロックあたりの支払額以外、特に特色のない通貨のようですが、これだと確率的には1日1回掘れるぐらいだと思うので、せめて1回掘れるまではGrandcoinを採掘しておこうと思います。
2013年12月15日日曜日
NVIDIA買ってしまった。。仮想通貨採掘におけるAMDの優位性
Litecoin関連のサイトで、GPUごとのハッシュレートを一覧にしているサイトがあります。
GPUに応じた微調整のオプションなども記載されていて便利なサイトです。
そこを見ていて残念な事実に気がついたのですが、RADEONとGeForceの間にはまさに越えられない壁がありました。
何も考えずに買ってきたNVIDIA GeForce GTX 660については120khash/sと記載があり、実際にほぼそのくらい出ています。
で、同じ2万円ぐらいの価格のRADEONはどうかと言うと、ATI Radeon R9 270で450khash/sで4倍ぐらいハッシュレートが違います。
消費電力もそんな変わらなそうですし、完全にこっちのほうが効率的です。
R9 270と同等のハッシュレートをNVIDIAで出そうと思うと、NVIDIA GeForce GTX 780 Tiあたりが必要で、7万円とかします。
GTX 660と同じぐらいのハッシュレートのものをRADEONで探すと、7千円ぐらいで売っているATI RADEON HD 6670が127khash/sぐらいです。
完全にRADEON圧勝という感じです。
とりあえず悔しいのでなぜこんなに違うのか調べてみましたが、いまいちよく分かりませんでした。
キーワードとしてはOpenCL、CUDAあたりが関係ありそうです。
ただ、NVIDIAのGPUに特化したCUDAのほうが、DSPやらCellやらにまで対応しているOpneCLよりも最適化出来そうな気がします。
そもそも、わざわざcgminerではなくcudaminerを使う訳ですし、最適化されていると捉えるべきな気がしますが、まぁハード的に向き不向きとかがあるのかも知れませんね。
いまいち釈然としませんが、採掘用にグラボを買い換えるのであれば、余計なことは考えずにRADEONを買いなさいという話です。
ということで、ハッシュレートは低いし、理由も良く分からないし、なんだかしょぼーんな話でした。(´・ω・`)
Anoncoin採掘者は報われるのか??GPUスペックと採掘量と換金レート
Anoncoinを掘り始めたのは、Bitcoinバブルで儲かっている人々の話を聞いて、あの時参入しとけばよかったと後悔したのが始まりです。
今回はAnoncoinの採掘で儲かるのか?という必然の問いに踏み込んでいきます。
WEMINEANC左側のメニューの「STATISTICS」の「Pool」を開くと、ランキングのようなものが表示されるのですが、TOPのユーザのハッシュレートは3,000khash/sを超えています。
TOPのユーザで8.104ANC/Dayとあるので、一日あたり8ANC稼ぎ出しているということでしょうか。
今は1ANCあたり0.008BTCぐらいなので、8ANCということは0.06BTCぐらいということですね。
右側にあるANC/BTCというのは、どうやらANC/DayをBitcoin換算したもののようです。
1.0BTCあたりは900ドルぐらいなので、日に50ドルの収入という計算になります。
一体どんな環境で、どれだけ電力つかってるんでしょうか??
さて、自分の古い低スペックなグラボではどうなるのかというと。。
GeForce GTS 250
12.52 khash/s
ぜんぜんダメですね。
一晩放置しておきましたが、かけらも掘れませんでした。。
せっかく色々調べたのにコレではつまらなすぎるので、ヨドバシに走りました。
GeForce GTX 660
133.11 khash/s
ははww
10倍になりました。
むしゃくしゃしてやりましたが、後悔はしていません。
とりあえずこれでTOPのユーザの30分の一のハッシュレートになったので、日に1ドルから2ドルというとこでしょうか。
電気代がどのくらい跳ね上がるのかにもよりますが、それにしてもなんかプラスな気がします。
GTX 660のゲーム中の消費電力が200Wぐらいとどこかで見たので、ちょと収支を計算してみます。
1000Wの機器を1時間使用した場合の電気代を20円とした場合、200Wなので1時間で4円です。
4円 × 24時間 = 96円
微妙ですが、プラスってことですかね。
まぁ結局は換金レートがアホほど変動するので、レート次第ってところだと思いますが、電気代丸々損するって感じではなさそうです。
まぁこれなら、仮想通貨採掘の業者が存在することにも頷けますね。
ということで、購入したGTX 660に2万円ちょっと費やしたことについては心の奥に封印しつつ、鉱山労働者としてまじめに採掘に励んでいこうと思います。
2013年12月14日土曜日
みんなで採掘してその分け前を貰おう!!Poolサイトを利用してAnoncoinを掘る
今回はPoolサイトの使ってAnoncoinを採掘してみます。
まずは、ここで適当なPoolサイトを探します。
今回は出来たてほやほやで、Feeが0%のWEMINEANCにしてみます。
まずは、左側のメニューの「OTHER」の「Sign Up」からサイトに登録します。
PINは重要なので忘れないようにしましょう。
次に同じくメニューの「OTHER」の「Login」からサイトにログインします。
次に「WORKER」という採掘用のIDを作成します。
ここで設定したIDとPWを使って、実際に採掘作業を実施します。
左側のメニューの「HELP」の「Getting Started」を開くと、採掘方法が書いてあるのですが、採掘ソフトを入手する段階で、CGMinerのダウンロードサイトが落ちててどうにもなりませんでした。
BitcoinやLitecoin関連のサイトを調べていたところ、そもそもAMDのRadeon系なんかを利用している場合はCGMinerを使うのですが、NVIDIAのGeForce系なんかを利用している場合は、cudaMinerというソフトを使うそうです。
まぁBitcoin Forumを見ると使えなくもなさそうですが、深刻なダメージなんてことも書いてあったので、NVIDIAの場合はcudaMinerが無難なようです。まぁそもそもダウンロード出来ませんし。。
自分の環境はNVIDIAなので、早速Bitcoin Forumのこのページからダウンロードします。
自分は一番新しかった「cudaminer-2013-12-10.zip」をダウンロードしました。
32bit用のものと64bit用のものが入っているので、自分の環境にあったものを適当なフォルダに解凍します。
自分は64bitなので、「x64」のフォルダを解凍しました。
このcudaMinerというソフトは、起動オプションをつけて起動して、あとは延々採掘し続けるというCUIのソフトです。
WEMINEANC公式によると設定値は以下とのことです。
STRATUM: stratum+tcp://stratum.wemineanc.com:3333
PORT: 3333
Username: Weblogin.Worker (ユーザーIDとワーカーIDをドットでつなぎます)
Password: Worker Password
毎回同じ起動オプションをつけて起動するので、batファイルを作っておきます。
以下を自分のIDとPWにしてテキストファイルに保存し、拡張子を.batに変えるだけです。
cudaminer.exe -o stratum+tcp://stratum.wemineanc.com:3333 -u Weblogin.Worker -p Worker Password
あとは作成したbatファイルを実行するだけで、採掘者の仲間入りです。
起動すると最初は何か最適化を図っているらしくCPUがガッツリ稼動するのですが、採掘が開始されるとCPU使用率は2%ぐらいになり、代わりにGPUが全力で稼動します。
とりあえずこれで、鉱山労働者の仲間入りが出来ました。
しばらくはまじめに採掘を続けながら、BitcoinバブルのようにAnoncoinのバブルが来ることを祈ることにします。
アングラ世界へ行ってみよう!Anoncoinのインストールと設定
AnoncoinのWalletをインストールしてみます。
まずは、ダウンロードページからインストーラをダウンロードし、ウィザードに沿ってインストールします。
Windowsだとインストーラがあって簡単ですが、Mac版やLinux版もあります。
Mac版はまだBeta扱いみたいですが。
簡単なはずでしたが、インストール完了と共に、Norton先生が「Suspicious.Cloud.9」がどうのと警告を出しました。
大丈夫なんでしょうか?
これは「ウィルスやマルウェア発見!」ではなく、「ウィルスやマルウェア?なの?」程度の警告のようです。
サイトを見ると「危険度1: ほとんど影響なし」とありますが、Nortonのセキュリティ履歴を見ると、思いっきり「リスク高」となっています。
解決しましたって言われても。。。
しかもuninstall.exeのほうが脅威だったと?
ねぇ、本体のほうは?本体のほうは??
不安を抱えながら先に進みます。
初回起動時はblockchainのアップデートに5分程度かかるとありますが、自分の環境では、しばらくSyncが完了しませんでした。
恐らくPCスペックのせいだと思いますが、30分程度でやっと完了。
wallet.datファイルがそのままだと暗号化されていないので、暗号化します。
Settings > Encrypt Wallet からパスワード入れて再起動するだけです。
ちなみに再起動すると、またOut of sync状態になりますが、少し待てば復旧して、以下のような画面になります。
右下には現在の状態を示すアイコンがあり、左の鍵マークは暗号化されていることを表し、真ん中の電波マークはactive connectionsの数、右のチェックマークはSyncが終わっているということです。
で、右上にMiningというメニューがあったので触ってみましたが、CPU使用率100%になって何か計算している風ですが、ウンともスンとも言いません。
まぁそもそもソロでCPUで掘ろうというのが間違っているんでしょう。
ということで、次回はPoolを試してみます。
2013年12月12日木曜日
次のBitcoinを探せ!!アングラ臭のするAnoncoin!
Bitcoinが盛り上がっていたので、この機会に類似の仮想通貨について調べてみます。
Litecoinぐらいになると、既に市場規模も大きくなってきていて面白くないので、どうせならこれから来るかも?みたいな通貨がいいかなぁということで、ターゲットはAnoncoinとします。
Anoncoinの公式サイトには、がっつりアノニマスのロゴや、ガイ・フォークスの仮面の画像が差し込まれており、まさにアングラという雰囲気です。
とあるサイトによると1ANCあたり7.74ドル(2013/12/11時点)とのことなので、Bitcoinの百分の一以下ですが、wikiによると2013年11月頃の市場規模は140,000ドルぐらいで、着実に拡大していっています。
思想的に面白いところは、Anoncoinは主にTORやI2Pで使われることを目的に作られた仮想通貨だというところです。
TORやI2Pはいわゆるアノニマイザで、TORはSOCKSプロキシ、I2PはHTTPプロキシの機能を持つプロトコルです。
TORは遠隔操作事件でも結構有名になったヤツですね。
ちなみに、SOCKSはレイヤー5のセッション層、HTTPはレイヤー7のアプリケーション層で動くプロトコルなので、違うレイヤーで動く同じような目的のプロトコルというところでしょう。
Anoncoinの仕様としては恐らく420万枚が上限で、上限まで徐々に速度を落としながら採掘されていく設定になっています。
完全匿名のネットワークで利用される、完全匿名の通貨。
Bitcoinなどと技術的にどう異なるのかはよく分かりませんが、なんだか他の類似通貨を駆逐して、アングラの世界を制覇しそうな気がしますね。
2013年12月9日月曜日
Bitcoinの採掘はもうオワコンか??
昔から気になっていたものの、日本語の情報も少なかったため特に触らずにいたBitcoinについて。
当時のレートは1BTCあたり10ドルも行かないぐらいで、まだその存在すら知らない人がほとんどでした。
それがいまや、1BTCあたり1,000ドルを超え、Bitcoinで決済できるものもかなり増えているそうです。
現在では流通量も80億ドル以上に跳ね上がっているそうで、かなりの加熱っぷりです。
しかし、通貨の価値が100倍になるって恐ろしい数字ですね。
まぁ、その後数日間で、また500ドル台まで急落したので、不安定なことこの上ないですが。
どうやら流通するBitcoinの半分ぐらいは中国人が持っているなんて話もあり、その中国が通貨として認めない的な声明を発表したことで、大幅な急落を見せたようです。
まぁまだ不安定なBitcoinですが、人民元よりはましと考えた中国人が多かったのでしょうね。
さて、現状どこまでいくのかまったく見えないBitcoinですが、いまさら採掘に参入するとかどうなのか調べてみました。
まず、自分一人で掘る場合。
孤独な採掘者も昔は普通に掘れたっぽいです。
倉庫に余って放置されている、ボロボロのPCを稼動させとくだけでBitcoinが手に入ったみたいです。
採掘というのは、特定の条件のハッシュ値を計算するproof of workと呼ばれる作業で、その見返りにBitcoinを得るというものです。
必要な計算は理論上10分程度かかるように常に難易度が調整され、採掘者側が進化すればするほど難易度も上がっていきます。
つまり、膨大な計算をいかに速く終わらせるかが、Bitcoin採掘の肝になる訳ですが、そうなると採掘競争はどんどん加速していきます。
元はCPUだけで計算していたのが、GPUを利用するようになりその速度は大幅に向上します。
また、それが一般的になっていくと、今度は専用チップを利用するようになり、もはや素人にはお勧め出来ない領域に突入しています。
余ったボロボロのPCでBitcoinを採掘するのは、地下数キロに埋蔵される資源をスコップで掘るようなものですね。
実際にやってみたわけではないのですが、たぶん仕組みから考えると孤独な採掘は無駄な電気代がかかるだけの不毛な作業になりそうです。
次に、一人で掘れないのであれば、集団採掘所で採掘に参加する場合。
有名どころはBitMinterやBitcoin Plusなどで、参加者で協力して採掘し、それぞれの貢献度に応じてBitcoinが分配がされます。
具体的な仕組みは良く分からないけど、いわゆる分散コンピューティング的なことをしているんだと思います。
※邪魔くさいので消しました。
ちなみに、自分のPCでBitcoin Plusを稼動させてみましたが、1時間ぐらい稼動させて0.00000003BTCというなんだかよく分からない金額をゲットしました。
1BTCあたり700ドルで計算しても、月2円ぐらいですかね。
また、送金の最小単位が0.01BTCなので、初めて送金するまでに38年かかりますw
うーん。。
これってちゃんとGPUも使ってくれているんでしょうか?
PCスペックがヘボすぎるからなのか分かりませんが、この結果だけ見ると、人々を組織する側に回らなければ、どうしようもなさそうです。
こうなると採掘はあきらめて、普通の仮想通貨として購入するか、何かの対価として支払いを受けるしかありません。
広告を見るだけでBitcoinが貰えるBitVisitorや、指定されたYoutubeを見るだけのCoinTubeなど、良くある懸賞サイトのような仕組みでBitcoinを受け取れるサイトもあります。
なんだかSecondLifeのキャンプみたいになってきました。
ということで、素人のBitcoinとのかかわり方としては、もはやいわゆるユーザーとしてかかわるのが正解な気がしてきました。
あとは為替差益で儲けるぐらいだと思うので、キプロスの経済危機の時に跳ね上がった例もありますし、中国の経済崩壊へ向けて今のうちにBitcoin買っときましょうかね。
2013年11月20日水曜日
WEBサービスを作ってみよう 第4回 Slim3の最新版へのアップグレード
この辺りからは、WEBサービス構築の概要というよりは、具体的な開発にかかわる話になってきます。
今回は、必要に迫られてSlim3のアップグレードを行ったので、その辺について残しておきます。
まず、WEBサービスを作るにあたって、JSONが大活躍します。
検証はしていませんが、Ajax的な作りでサーバ側はJSONを吐くだけにして、なるべくクライアント側で作業するようにしたほうがコストが安そうです。
やはり、特に無料枠に抑えたいという期待を持って開発するのであれば、いちいちServletやJSPがページをゴリゴリ生成して吐き出すような作りは、コスト的にマズイような気がします。
そこで、JSONの取り扱いですが、Slim3にはModelをJSONに簡単に変換してくれるメソッドがあります。
そのModelMeta.modelsToJson()で以下のエラーが出ました。
java.lang.NoClassDefFoundError: com/google/appengine/repackaged/org/json/JSONObject
Google先生に色々聞いてみたところ、ModelMeta.modelsToJsonでrepackagedなクラスを使ってるために起きているそうです。
repackagedなクラスというのは、SDKの変更で頻繁に変更されるので、あまり使うべきではないみたいですね。
で、解消方法がSlim3のバージョンを「1.0.15」から「1.0.16」にアップグレードすることでした。
Slim3はEclipseからインストールしているんですが、なんで初めっから最新にしてくれないんですかね?
理由は謎のままですが、最新版は以下からダウンロードします。
https://code.google.com/p/slim3/downloads/list
slim3-blank-1.0.16.zip
開発中プロジェクトでライブラリのアップグレードをするなんて、もろもろ動かなくなったりしそうで怖いのですが、やるしかありません。
公式などを見つつビクビクしながら以下の通り実行しました。
1.新しいバージョンのファイルをフォルダに投入
「slim3-1.0.16.jar」を<Project>/war/WEB-INF/libに投入。
「slim3-1.0.16-sources.jar」を<Project>/libsrcに投入。
2.プロジェクトのプロパティ >Javaのビルド・パス > ライブラリー からCLASSPATHの設定を変更
「slim3-1.0.16.jar」と「slim3-1.0.16-sources.jar」を追加。
「slim3-1.0.15.jar」を削除。
3.古いファイルをそれぞれのフォルダからも削除
4.注釈処理に関連した新しいバージョンのファイルをフォルダに投入
「slim3-gen-1.0.16.jar」を<Project>/libに投入。
5.プロジェクトのプロパティ > Javaコンパイラー > 注釈処理 >ファクトリーパス からファクトリパスの設定を変更
「slim3-gen-1.0.16.jar」を追加。
「slim3-gen-1.0.15.jar」を削除。
6.古いファイルをフォルダから削除。
これで今のところは、ちゃんと動いています。
2013年11月10日日曜日
WEBサービスを作ってみよう 第1回 利用言語とインフラ
なんかWEBサービスを作ってみようと思います。
たいした知識も無いのですが、作りながら必要な知識は身につけていけば良いということで、とりあえずやってみます。
あえてタイトルに第1回と付けたのは、いつもこの手のことは継続出来ないので、自分を追い込むための儀式のようなものです。
データベースがRDBではないなど一癖ありそうな感じではありますが。
2013年11月4日月曜日
WEBサービスを作ってみよう 第3回 Slim3の概要
Slim3をいくらか触ってみたので、その概念について。
Slim3におけるControllerは、URLに関連付けられたServletで、基本的な流れはまずControllerを呼び出して処理し、そこからjspを出力するという感じです。
ビジネスロジックが書かれたServiceから、DatastoreのModel読み出しや、保存を実行します。
開発にはEclipseを使うのが一般的で、Slim3 Plugin for Eclipseをインストールして利用します。
Antが使えるので、Antタスクを使ってControllerを作成すると、ControllerとJSPとTestCaseを同時に生成出来、ControllerはURLに関連付くので、servlet-mappingの設定など面倒な作業は不要です。
当然、ServiceやModelを作成する際も、TestCaseを生成してくれます。
Slim3はTDD(Test DrivenDevelopment)という開発手法を推奨していて、コード本体が完成していない状態でまずテストを書いてテストが失敗することを確認し(テストファースト)、次にそれが動くコード本体を書くという流れを繰り返します。
コード本体の書き方も、まずは定数を返すなどの仮実装を行い、徐々に変数を用いた本来のコードに仕上げていって洗練していくという流れです。
この設計手法にはとても共感出来ます。
いっきにコードを書き倒して、もはやどこでしくじったのか訳が分からなくなり、数時間ハマるなんてことを良く経験するので、それを回避出来ます。
TestCaseの生成の重要性が良く分かっていませんでしたが、なるほどこれは重要ですね。
ちなみに、はじめにAntを動かしてみたところ、gen-controllerのところで思いっきりハマりました。
Antを実行すると
java.lang.SecurityException: SHA1 digest error for org/eclipse/swt/graphics/GC.class
と言われてControllerが生成出来ません。
色々調べてみたところ、
どうやらJREのバージョンが異なることで起きていたようで、これで無事Controllerが生成されました。
さて、フレームワークを使うと開発が効率化されるというのがなんとなく分かってきましたが、さらにSlim3はHOT reloadingをサポートしています。
何それ?という感じですが、所謂HOT deployの別称で、アプリケーションサーバを立ち上げたままでも変更したクラスがリロードされるので、いちいち再起動が不要という代物です。
いくつかハマるケースもあるみたいですが、Servletを書き換える度に再起動するのに比べると恐ろしく効率的です。
世の中の人が便利と言ってるモノは、やっぱり便利ですね。
今後は素直に先人の知恵には従おうと思います。
WEBサービスを作ってみよう 第2回 フレームワーク
前回、インフラはGoogle App Engineを使って、言語はJavaと決めました。
今回は次のステップとして、利用するフレームワークについて考えます。
効率的な開発にはフレームワークは欠かせないらしいので、なるべく楽に開発していくためにもここは重要なポイントになります。
どんなものがあるかとGoogle先生に伺うと、Google App Engineで動きそうなものだけでも大量にhitします。
この辺にもGoogle App Engineで使えるフレームワークのリストが載ってますが、まぁ色々な用途の色々なフレームワークがあるようです。
Spring
Tapestry
Wicket
DWR
Tiles
SiteMesh
Grails
Struts 2
...
正直、それぞれどんな用途でどれが最適なのか調べているだけで日が暮れそうです。
また、効率的な開発はとても重要ですが、そもそもフレームワーク無しで作ったことが無い人間が、フレームワークありで作ったところでそのありがたみは分からないでしょう。
ここでめんどくさくなって開発が止まってしまうぐらいなら、フレームワークなんて考えずにゴリゴリ書き始めたほうが良いのではないか?
なんて事を考えていたのですが、検索結果の中に気になるフレームワークがありました。
Slim3は、「Google App Engine/Java 用に最適化されたフルスタックのMVC フレームワーク」であり、また「単にDatastoreのフレームワークとしても使用出来る」とのことで、この手のものでは珍しく日本発のフレームワークだそうです。
Slim3 Datastoreに関しては、Bigtableに特化したLow level APIの薄いラッパーで、Google App EngineのデータストアをJavaから利用する場合の一般的な選択肢であるJDO(Java Data Objects)よりも高速に動作するそうです。
開発の効率化に加えて、そもそもの動作も高速化するということであれば、これは使ってみるしかないでしょう。
ということで、フレームワークはSlim3を使ってみます。
2013年7月28日日曜日
久しぶりのSecondLife!乗り物のSIM越え遅延原因を検証する
今回は久しぶりのSecondLifeで、乗り物でSIMを越える時の引っかかりについて検証します。
コレ結構致命的なレベルで発生していて、SIM越えの度に5秒とか10秒固まるケースもあります。
SIM越えの際にSIM側で何が起きているのかをちゃんと調べるのが正攻法だと思いますが、正直良く分かりません。メモリの確保やらなんやらあるんでしょうね。
まぁ細かいところは良く分からないので、取りあえず色々と実験してみます。
まずは基準としてx:2m y:2mにリサイズしたキューブを用意し、これに飛行機のスクリプトを突っ込みます。
こいつのサイズを変えたりプリム数を変えたり、色々なスクリプトを放り込んだりしながら、SIM境界を20回ぐらい行ったり来たりして、遅延の平均を取ります。
遅延の計測方法はllGetTimestamp()を使ってミリ秒単位で計測します。
■基準
平均遅延:268ms
このぐらいだと少し引っかかるなぁぐらいで特に問題ありません。
■プリムサイズによる差異
・基準のプリムサイズをx:30m y:30mにリサイズ。
平均遅延:275ms
サイズを変えてもあまり変わらないようです。
■プリム数による差異
・基準のプリムを30リンクさせたオブジェクトを利用。
平均遅延:1,000ms
一気に悪化します。
■スクリプトの量による差異
・基準にVICE関連のスクリプトを投入。
平均遅延:998ms
リンクされたプリム数が30の場合と同じぐらい悪化します。
・30プリムのオブジェクトにVICE関連のスクリプトを投入。
平均遅延:1,548ms
当然さらに悪化します。
■スクリプトのファイル数による差異
・基準に300個の変数を定義したスクリプトファイルを投入。
平均遅延:448ms
・基準に30個の変数を定義したスクリプトファイルを10ファイル投入。
平均遅延:744ms
ファイル数が増えると悪化するようです。
ということで、最後のファイル数の部分以外は、何が悪影響というよりは基本的には足し算で、何か実装すればそれだけ遅延が発生するという印象です。
結論としては、何でもかんでも実装するのではなく必要な機能を絞ることと、最適化のためにファイル数を最小にするというところでしょうか。
まぁサンプル数も少なく、SIM側のトラフィックなどの影響もあるでしょうし、どこまで正しいか分かりませんが、なんとなく遅延を減らすには何をすべきかは見えた気がします。
2013年7月8日月曜日
最寄り駅を教えろ!Google Maps APIでマッシュアップ
今回は、Google Maps APIとHeartRails Expressの最寄駅情報取得 APIを連携させて クリックした場所の最寄り駅を取得してみます。
いわゆるマッシュアップというやつですね。
まずはGoogle Maps APIですが、これは思ったより簡単に使えます。
version3になってから、APIキーも無しで使うことが出来るようになり、何の準備もなくScriptを書き始められます。
ScriptタグでGoogle Map APIのJavaScriptを読み込みます。
<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3&sensor=false"> </script>
Body要素の中にMapを表示するためのdiv要素を配置しておきます。
<div id="map_canvas"></div>
Mapを表示するための関数を書きます。
この関数をbody要素のonloadなどに仕込んで利用します。
function initialize() { //表示位置 var myLatitude = 35.147055906927214;//経度 var myLongitude = 139.150131046772;//緯度 //Mapの表示位置、表示方法などの設定値 var mapOptions = { center: new google.maps.LatLng(myLatitude, myLongitude), zoom: 15,//初期のズームレベル mapTypeId: google.maps.MapTypeId.ROADMAP }; //Mapを表示するdiv要素と設定値を渡す var map = new google.maps.Map( document.getElementById("map_canvas"),mapOptions); //Mapがクリックされた時のリスナーを登録 google.maps.event.addListener(map, 'click', clickMap); }
次に、HeartRails Expressの最寄駅情報取得 APIを利用します。
とてもシンプルなAPIで、URLに以下のように経度緯度のパラメータをつけてリクエストを投げると、最寄駅の情報を返してくれます。
レスポンスはXMLとJSONの二択でそれぞれURLが異なり、今回はJSONを使います。
http://express.heartrails.com/api/json?method=getStations&x=135.0&y=35.0
返ってくるJSONの構造は、responseフィールドの中に、stationフィールドがあり、その中に3つぐらいの駅情報が配列として入っています。
都市部などで多いと10ぐらい入っていたりもしますが、基準はよく分かりません。
駅までの距離が近い順に格納されていて、見つからない場合は空っぽのようです。
これをAjaxで拾ってくれば終わりかと思ったのですが、まったくうまくいきません。
NETWORK_ERR: XMLHttpRequest Exception 101
とか文句を言ってまったく相手にしてくれない。
結構な時間悩みに悩んだんですが、普通にクロスドメインはダメなんですね。
で、JSONPに行き着いた訳ですが、これ完全にscriptタグの悪用なのではないでしょうか。
クロスドメインでデータの読み込みが出来ないブラウザの仕様を回避するために、動的にappendChildしたscriptタグから外部scriptファイルを読み込むふりをして、外部データを拾ってきてしまうという。。
なんだか詐欺みたいな仕様です。
その詐欺師コードが以下。
function clickMap(event) { heartrailsURL = "http://express.heartrails.com/api/json?method=getStations&"; heartrailsURL += "x=" + event.latLng.lng() + "&"; heartrailsURL += "y=" + event.latLng.lat() + "&"; heartrailsURL += "jsonp=getStation";//JSONPのコールバック関数 var script = document.createElement('script'); script.src = heartrailsURL; document.body.appendChild(script); } //コールバック関数 function getStation(result) { var resultStr = ""; for(i = 0; i < result["response"]["station"].length; i++) { resultStr += result["response"]["station"][i].line + " "; resultStr += result["response"]["station"][i].name; resultStr += "駅までの距離:" + result["response"]["station"][i].distance + "\n"; } alert(resultStr); }
普通に動きました。
Google Maps APIがテーマだったのですが、何よりJSONPに感動しました。
2013年5月18日土曜日
Androidで音声解析!Visualizerによる高速フーリエ変換(FFT)
今回は、音の周波数を解析して音階を特定するというのをやってみたいと思います。
音階の特定には、時間軸を周波数軸に変換するフーリエ変換という処理で周波数解析を行います。
数式を載せてみたものの、これが本当にフーリエ変換の式なのかすらよく分かりません。
数学的な知識はまったく無いので、フーリエ変換についての説明や考察は一切しません。いや、出来ません。
基本的に勘で進めているので、間違った記述もあるかもしれませんが、取りあえず動いたので完全に間違いという事ではないでしょう。
まずはシンプルに440Hz(Aの音)のsin波を鳴らして、それが440Hzであることが分かればゴールとします。
フーリエ変換を行うには、波形を表示したりといったことにも活用出来るandroid.media.audiofx.Visualizerを利用します。
android.media.audiofxはAPIレベル9(Android2.3)で追加されたパッケージで、イコライザ機能などを簡単に実装するものです。
public Visualizer (int audioSession)
int audioSession 分析対象のMediaPlayerやAudioTrackのセッションID
流れとしては、Visualizerのコンストラクタに解析したいMediaPlayerなどのセッションIDを渡してやり、setCaptureSize()メソッドでキャプチャサイズを設定し、setDataCaptureListener()でリスナーを登録します。
キャプチャサイズを設定するときに利用するVisualizer.getCaptureSizeRange()で返ってくる配列はlengthが2で、index[0]は128、index[1]は1,024です。
つまり、キャプチャサイズは128か1,024しか選択出来ないようです。
129や2,048など別の数字を入れてもエラーにはなりませんが、VisualizerのgetCaptureSize()で確認すると、1,024になっていたので、自動で修正されているようです。
public int setDataCaptureListener (Visualizer.OnDataCaptureListener listener, int rate, boolean waveform, boolean fft)
Visualizer.OnDataCaptureListener listener 登録するリスナー
int rate キャプチャ更新のレート
boolean waveform trueならonWaveFormDataCapture()が呼ばれる
boolean fft trueならonFftDataCapture()が呼ばれる
キャプチャ更新レートの最大値はVisualizer.getMaxCaptureRate()で20,000です。
登録するリスナーはVisualizer.OnDataCaptureListenerインターフェースを実装したもので、以下二つの抽象メソッドがあります。
public abstract void onFftDataCapture (Visualizer visualizer, byte[] fft, int samplingRate)
public abstract void onWaveFormDataCapture (Visualizer visualizer, byte[] waveform, int samplingRate)
onFftDataCapture()がフーリエ変換後のデータを利用するもので、onWaveFormDataCapture()は生のWaveデータを利用するものです。
それではいよいよonFftDataCapture()についてみていきましょう。
まずドキュメントでVisualizerのgetFft (byte[] fft)部分を見ると、index[1]を除くと、byte配列には実数部と虚数部が交互に格納されているようなことが書いてあります。
ソースをちゃんと見ていませんが、onFftDataCapture()で渡されてくるbyte配列も恐らくこれと同じでしょう。
実数?虚数?という感じですが、複素数平面に拡張するには訳があります。
ある波を複数のsin波の合計で表現することがフーリエ変換なのですが、位相のズレを表現するためには虚数が必要なんです。
位相のズレたsin波をsinやcosをフル活用して表現する的な感じですかね。
はい。
あんまり良く分かりません。
まぁここで重要なのは、onFftDataCapture()のbyte配列の実数部がcos波、虚数部がsin波を表すってところです。
※という割には実数部を見ても虚数部を見ても同じところにピークが来ていました。また、ためしにcos波を混ぜてみたらまったく想定していない結果になり、謎は深まるばかりです。
ちなみにどの程度細かく分析が可能かに触れていませんでしたが、実はそんなに細かく分析出来ません。
サンプルレートが44,100Hzであれば、いわゆるナイキスト周波数は22,050Hz(44,100Hz / 2)で、キャプチャサイズが1,024であれば、分解能は21.5332031Hz(44,100Hz / 2 / 1,024)となります。
これはG♭3とG3ぐらいの差なので、音階を完全に特定するには十分とはいえない気がしますが、これが最大値なようなので仕方が無いです。
低周波になってくると音階の区別がつかなくなるってことでしょう。
つまり、サンプルレートが44,100Hzで、キャプチャサイズが1,024であれば、分解能は21.5332031Hzとなり、FFTの結果のbyte配列は恐らく以下のよう解釈すれば良いと思われます。
index[0] 実数部 0Hz~10.76660155Hz
index[1] 実数部 10.76660155Hz~21.5332031Hz
index[2] 実数部 21.5332031Hz~43.0664062Hz
index[3] 虚数部 21.5332031Hz~43.0664062Hz
index[4] 実数部 43.0664062Hz~64.5996093Hz
index[5] 虚数部 43.0664062Hz~64.5996093Hz
・
・
・
440HzのAの音であれば、以下のindex[41]にピークがくるということです。
index[41] 虚数部 430.664062Hz~452.1972651Hz
では実際にやってみましょう。
まずはFFTの結果を拾うところまで。
AudioTrack mAudioTrack; Visualizer mVisualizer; //サンプルレート static int SAMPLE_RATE = 44100; int bufSize = SAMPLE_RATE * 5; //ストリームモードでAudioTrackを利用します mAudioTrack = new AudioTrack( AudioManager.STREAM_MUSIC, SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_DEFAULT, bufSize, AudioTrack.MODE_STREAM, 420);//セッションID mAudioTrack.play(); mVisualizer = new Visualizer(420); // 1024 int captureSize = Visualizer.getCaptureSizeRange()[1]; mVisualizer.setCaptureSize(captureSize); mVisualizer.setDataCaptureListener( new Visualizer.OnDataCaptureListener() { // Waveデータ public void onWaveFormDataCapture( Visualizer visualizer, byte[] bytes, int samplingRate) { } // フーリエ変換 public void onFftDataCapture( Visualizer visualizer, byte[] bytes, int samplingRate) { //このbytesがFFT後のデータ //何度も呼ばれるのでこのデータを分析する }, Visualizer.getMaxCaptureRate(), false,//trueならonWaveFormDataCapture() true);//trueならonFftDataCapture() mVisualizer.setEnabled(true); byte[] audioData = new byte[bufSize]; // A単音 double freqA = 440; double t = 0.0; double dt = 1.0 / SAMPLE_RATE; for (int i = 0; i < audioData.length; i++, t += dt) { audioData[i] = (byte) (Byte.MAX_VALUE * (Math.sin(2.0 * Math.PI * t * freqA))); } mAudioTrack.write(audioData, 0, audioData.length);
これでフーリエ変換後のデータを取得出来ました。
あとはピークがどこに来ているか確認し、分解能を元に周波数を特定すれば良いだけです。
ただし、結果を見てみると概ね正しく解析出来ますが、おかしな数字が出てくることもあります。
index[41] : 441.4306640625
index[41] : 441.4306640625
index[41] : 441.4306640625
index[73] : 785.9619140625
index[73] : 785.9619140625
index[141] : 1518.0908203125
index[169] : 1819.5556640625
index[123] : 1324.2919921875
index[41] : 441.4306640625
index[41] : 441.4306640625
index[41] : 441.4306640625
index[41] : 441.4306640625
index[49] : 527.5634765625
index[41] : 441.4306640625
index[149] : 1604.2236328125
index[149] : 1604.2236328125
index[41] : 441.4306640625
index[41] : 441.4306640625
index[41] : 441.4306640625
正しいindex[41]以外はバラバラですね。
虚数部しか見ていなかったので、位相のズレなどが正しく解釈出来ていないということでしょうか??
まぁちょっと勉強が必要ですね。
2013年4月22日月曜日
テストも簡単!Intel XDKで書いたアプリをAndroidでテストする
前回エミュレータ上では、AndroidでもiPhoneでも動いたthree.jsのサンプルですが、今回は実際に実機でテストしてみます。
XDKのエミュレータの右上にある「App Tester」をクリックします。
作成したProjectがクラウドに転送されます。
転送完了。
右矢印をクリックすると手順の説明が出てきます。
ここからはappMobiのAndroidアプリ「app•lab」をインストールし、Android側で作業します。
アプリを起動し、「enter the lab」から先へ進みます。
「log in now」からブラウザを起動します。
どうやらはじめから画面の右上に表示されている「MY APPS」からでも同じく飛べるようです。
XDKに登録した際のIDとPWを入力してログインします。
先ほど転送したProjectを選択します。
「App Tester」を選択します。
「Test Local」からでも起動出来ますが、その差は良く分かりません。
「Launch」から起動します。
はい、見事動きません。
html5の互換性の問題なのか何なのか。。。
他のサンプルアプリを飛ばしてみたところ普通に動いたので、AndroidのChromeブラウザとthree.jsの問題かもしれません。
たしかにthree.jsで書いたアプリがAndroidで動いているサンプルってあまり見ないんですよね。
そもそもこのXDKのエミュレータは、ブラウザによる対応状況の差異まで考慮されていないのかもしれません。画面サイズによる差異を見る程度の話で、HTML5の互換性を100%と過程しているのだとするとあまり意味無いですね。
何にせよ、3Dで物理演算までの道のりはまだまだ長いです。。
2013年4月21日日曜日
ブラウザで3D!Intel XDKでthree.jsを動かしてみる
では今回はIntel XDKを使って、three.jsのサンプルを動かしてみます。
この辺からthree.jsのサンプルなど含めて一式ダウンロードします。
「examples」フォルダに様々なサンプルが入っているので、Chromeで表示させながら、簡単そうなのを選んでみます。
今回選んだのは、立方体がドラッグするとクルクル回るだけの簡単なサンプル「canvas_geometry_cube.html」です。
今回、XDKの画面で新しく利用するのは、画面左側にある「Reload app」ボタンとエミュレータの右上にある「Show/Hide Debug Console」ボタンです。
前回触ったXDKのエディタ画面で、index.htmlに必要そうなところをコピペしていき、エミュレーションモードに戻ります。
「Show/Hide Debug Console」ボタンでコンソールを開き、「Reload app」ボタンで更新します。
。。。。
動きません。
コンソールを見てみましょう。
なにやら404(Not Found)が出ていますね。
それもそのはず、three.jsのライブラリをコピーするのを忘れていました。
ファイルをコピーし、パスも整えて再度リロードしてみます。
ちゃんと動きました。
マウスでドラッグするとクルクル回ります。
ちなみにリロードボタンの下に「Rotate」ボタンがあって、切り替えられます。
さらに画面右側に「DEVICE EMULATION」という欄があり、デバイスも切り替えられます。
XDKもなかなかお手軽ですが、three.jsもかなりお手軽ですね。
そのうち3Dで物理演算ぐらいまではやってみたいと思います。
ブラウザで開発!初めてのIntel XDK
もともとappMobiが開発していたHTML5開発ツールで、Intelがスタッフごと買収して「Intel XDK」としてリリースしました。
ぱっと見た感じ便利そうだったので、軽く触ってみることにします。
まず立ち上げるとdemoアプリのHello Worldが表示されます。
新しくアプリを作成するには、左上のファイル名の左側にある「START NEW」から新規作成します。
「Project Name」を適当に決めて、今回はウィザードなどは使わずにゼロから作るので「Create your own from scratch.」を選択します。
ちなみに、Project IDは「ID.ProjectName」という規則なのですが、これID変更出来ないんでしょうか??登録に利用したメアドの@前がそのまま表示されます。
画面に「Application Created Successfully!」と表示されて、まっさらなプロジェクトが表示されます。
以下で見えているのはエミュレーションモードで、エディタモードへ遷移するには左上にある先ほどの「START NEW」ボタンの左側「EDITOR」ボタンをクリックします。
開いた画面の左側メニューで編集したいファイルを選択すると画面右側にソースが表示されます。
生成されたindex.htmlのソースを見ると、ブランクというわりには、以下のような何やらテンプレ的なものが並んでいます。
<script type="text/javascript" charset="utf-8" src="_appMobi/appmobi_local_bootstrap.js"></script> <script type="text/javascript" charset="utf-8" src="http://localhost:58888/_appMobi/xhr.js"></script> <script type="text/javascript"> /* This function runs once the page is loaded, but appMobi is not yet active */ var init = function(){ }; window.addEventListener("load",init,false); /* This code prevents users from dragging the page */ var preventDefaultScroll = function(event) { event.preventDefault(); window.scroll(0,0); return false; }; document.addEventListener('touchmove', preventDefaultScroll, false); /* This code is used to run as soon as appMobi activates */ var onDeviceReady=function(){ //Size the display to 768px by 1024px AppMobi.display.useViewport(768,1024); //hide splash screen AppMobi.device.hideSplashScreen(); }; document.addEventListener("appMobi.device.ready",onDeviceReady,false); </script>
ちなみに上記を削除してリロードしてみると、以下のように怒られます。
コピペを指示されたコードは以下。
<!-- the line below is required for access to the appMobi JS library --> <script type="text/javascript" charset="utf-8" src="http://localhost:58888/_appMobi/appmobi.js"></script> <script type="text/javascript" language="javascript"> // This event handler is fired once the AppMobi libraries are ready function onDeviceReady() { //use AppMobi viewport to handle device resolution differences if you want //AppMobi.display.useViewport(768,1024); //hide splash screen now that our app is ready to run AppMobi.device.hideSplashScreen(); } //initial event handler to detect when appMobi is ready to roll document.addEventListener("appMobi.device.ready",onDeviceReady,false); </script>
もともと入っていたコードと内容が違う理由は謎です。
エディタを触った感じ、「Ctrl+C」「Ctrl+Z」「Ctrl+S」などのコマンドもそのまま使えて、特に不便は感じませんでした。
ちなみに保存するとこんなポップアップが出てきます。
後は何か書いてみるだけということで、次回は実際に何か作ってみます。
今回はここまでです。
なぜ中途半端なところで終わっているかというと、調子に乗って「three.js」と「Physijs」で物理演算のサンプルを動かそうと試み、そして動かず時間だけが過ぎていき、無かったことにしたからです。。
2013年4月14日日曜日
Chrome拡張で朝鮮半島に平和を!Browser ActionからScriptを実行する
前回はツールバーのアイコンクリックでポップアップを表示させましたが、今回はアイコンクリックで直接スクリプトを実行します。
拡張のアイコンをクリックすると、innerHTMLを書き換えるスクリプトを仕込みます。
前回と違う点は「permissions」の設定と、「background」の設定です。
「permissions」については必要なものを配列で指定します。
今回はchrome.tabsを利用するために「tabs」を指定するのと、どのサイトでも動くように「http://*/*」(httpから始まるすべてのサイト)を指定。
「background」については、スクリプトを登録しておくとChrome起動時に呼ばれます。
関数を定義しておいたり、リスナーを登録しておいたりなどに利用します。
「browser_action」の「default_popup」は、今回は使わないので削除します。
{ "name": "南北統一", "version": "1.0", "manifest_version": 2, "description": "朝鮮半島を平和にします。", //必要なパーミッションを指定する "permissions": [ "tabs", "http://*/*" ], //バックグラウンドで動く処理 "background": { //スクリプトファイルを登録 "scripts": ["background.js"] }, "browser_action": { "default_icon": "icon.png", "default_title": "統一" } }
続いてスクリプトファイルを作成します。
「chrome.browserAction.onClicked」はツールバーのアイコンがクリックされた際に呼ばれるイベントで、その「addListener」でリスナーを登録しておきます。
「chrome.tabs.executeScript」でタブ内でスクリプトを実行します。
第1引数はスクリプトを実行するtabIdで、現在のタブの場合はnullを指定します。
第2引数は実行するスクリプトの詳細情報オブジェクトで、codeプロパティの場合は「:」の後ろに実行するスクリプトを文字列で指定します。
長々と実行内容を文字列変数に格納しておいてから、executeScriptに渡していますが、もっとうまいやり方がありそうです。
事前に関数を定義しておいてその関数を文字列で渡せば良いかと思ったのですが、やってみたら動きませんでした。
まぁ、ここは動けば良いということで。
unification = ""; unification += "document.body.innerHTML = " + "document.body.innerHTML.replace(/北朝鮮/g,'朝鮮');" + "document.body.innerHTML = " + "document.body.innerHTML.replace(/韓国/g,'朝鮮');"; chrome.browserAction.onClicked.addListener(function() { chrome.tabs.executeScript(null, {code: unification}); });
ちなみにタグやスクリプトも無慈悲に置換されますので、「a」⇒「h1」なんてことも出来ます。
さて、作成した拡張をChromeに登録して実行してみましょう。
これが、
こうなる。
うーん。。
半島の統一には成功したのですが、内戦が激化しましたね。
2013年4月13日土曜日
意外に簡単に作れる!Google Chrome ExtensionsでHello World
普通に使っているものの、書いたことの無かったGoogle Chrome Extensions(拡張機能)。ちょこっと調べてみたところ、HTMLとJavaScriptが分かれば相当お手軽に作れるということが分かりやってみました。
いくつか種類があるのですが、その中でも「Browser Action」という、ツールバーのアイコンをクリックすると動くやつが手軽そうです。
それでは、ツールバーのアイコンをクリックすると、「Hello World!」と表示するだけの簡単なものを作ってみましょう。
1.アイコンを用意する
ツールバーに表示するために19×19(px)の画像を用意します。
拡張機能一覧で表示するためのアイコンは48×48(px)の画像で、無くても動くので今回は用意しません。
2.マニフェストファイルを作成する
「manifest.json」という名前で以下のように作成します。
{ //拡張機能の名前 "name": "Hello World!", //拡張機能のバージョン "version": "1.0", //決まりごとで今は2に設定 "manifest_version": 2, //拡張機能一覧に表示される説明 "description": "Hollo Extensions!", "browser_action": { //先ほど用意したアイコン "default_icon": "icon.png", //アイコンにマウスオーバーした際に表示される文字 "default_title": "Hello World!", //Hello Worldを表示するHTMLファイル "default_popup": "hello.html" } }
3.Hello Worldを表示するHTMLを作成する
styleにmin-widthを設定しないと、変なところで改行されるので「body」に設定します。
<!DOCTYPE html> <html lang="ja"> <head> <meta charaset="utf-8"> </head> <body style="min-width:200px"> <h1>Hello World!</h1> </body> </html>
4.Chromeに登録する
もうあとはChromeに登録するだけです。
アイコンとマニフェストファイルとHTMLを一つのフォルダに放り込み、以下手順で登録します。
メニューから「ツール」の「拡張機能(E)」を開きます。
「デベロッパーモード」にチェックを入れ、「パッケージ化されていない拡張機能を読み込む」から該当のフォルダを選択します。
すぐ下の部分に表示されたら登録成功です。
ちなみに、拡張機能を修正したりした場合は、ここの「リロード(Ctrl+R)」をクリックすると変更が反映されます。
5.実行する
うまくいきました。
しかし、Hello Worldなんて今も使うんですかね??
2013年3月31日日曜日
永遠のいたちごっこ!?Youtubeの動画ファイルURLを特定する
ユーザの思いとYoutubeの中の人の思いは、いつの日も交わることのない平行線です。
ユーザ側はYoutubeサイトを解析して動画ファイルの実体のありかを見つけ出し、Youtube側はサイトの仕組みを定期的に変更しています。
2月頃に解析してファイルのURLを特定出来たのですが、久しぶりに見てみるとまた仕組みが変更になっていました。
さて、いたちごっこの始まりです。
DOMやSAXなどを使って、<script>タグの中から以下が含まれる部分を探し出します。
※ちなみに2月に見たときとはこの変数名が変わっていました。
var ytplayer = ytplayer
これはソース上に一箇所しか表示されないので、すぐ特定出来ます。
該当の場所は以下のような感じで始まります。
<script>var ytplayer = ytplayer || {};ytplayer.config = {"url": "https:
この「ytplayer.config」の中には、以下のように様々な値がJSON形式で入っています。
- url
- url_v9as2
- attrs
- params
- url_v8
- args
- html5
- assets
- min_version
- sts
必要なのは「args」で、またこの中に100個近い値が入っていて、その内以下二つの値を利用します。
- url_encoded_fmt_stream_map
- title
「url_encoded_fmt_stream_map」の中には画質の数だけカンマ区切りでURLエンコードされたデータが入っています。
url=http://r9---sn-ogueynes.c.youtube.com/videoplayback?upn=IAD3bFZV614&mv=m&source=youtube&expire=1364660261&sparams=algorithm%2Cburst%2Ccp%2Cfactor%2Cid%2Cip%2Cipbits%2Citag%2Csource%2Cupn%2Cexpire&algorithm=throttle-factor&cp=U0hVSVZRTl9LS0NONV9OS1JDOkQxNGtBcURXM0pG&id=215b73e77a669a55&sver=3&ms=au&burst=40&mt=1364634922&fexp=919112%2C910071%2C914073%2C916626%2C901449%2C932000%2C906383%2C902000%2C919512%2C929903%2C931202%2C900821%2C900823%2C931203%2C931401%2C908529%2C930807%2C919373%2C930803%2C906836%2C920201%2C929602%2C930101%2C930603%2C900824%2C910223&newshard=yes&factor=1.25&key=yt1&ip=114.185.103.241&itag=17&ipbits=8\u0026type=video/3gpp; codecs="mp4v.20.3, mp4a.40.2"\u0026sig=72F456D7BB44FD11E2FEEFF93BB7E299458D267B.B502EFA76F6358C09848C82085C4EEA0551AC8BA\u0026fallback_host=tc.v8.cache2.c.youtube.com\u0026quality=small\u0026itag=17
データ一つ一つを見ていくと、キーと値が「=」で対になった以下の値が、「\u0026」(&をアスキーコードの16進数であらわしたもの)で区切られています。
- url
- type
- sig
- fallback_host
- quality
- itag
「\u0026」で分割してキーと値に分けた後、「url」の値をデコードして「?」より前と後ろで分割します。
前はコレ。
http://r9---sn-ogueynes.c.youtube.com/videoplayback?
後ろには、キーと値が「=」で対になった以下の値が、「&」で区切られています。
これは全部使いますので、「&」で分割してキーと値に分けます。
- upn
- mv
- source
- expire
- sparams
- algorithm
- cp
- id
- sver
- ms
- burst
- mt
- fexp
- newshard
- factor
- key
- ip
- itag
- ipbits
これに「args」に入っていた「title」を加えます。
「title」はダウンロードした際のファイル名になるので、値はそのままでも個別に指定しても良いです。
「url_encoded_fmt_stream_map」の中にあった「sig」をキーを「signature」に変更して加えます。
キーでソートします。
あとは出来上がったキーと値の組み合わせを、以下のように「url」前半部分につなげてアクセスするだけでダウンロード出来ます。
http://URL?キー=値&キー=値&キー=値&キー=値
いたちごっこは終わらない。。