2012年2月24日金曜日

NAVERまとめ疲れ #NAVERまとめ

ないだろ?まだないだろ?
NAVERまとめ疲れって書いた人居ないだろ!
俺一番!俺いちばーーーん!いえーい!
あんまり疲れてません。
疲れたといえば、無駄に色んなGmailのアカウントの予備のメール扱いになってたので、
それらを整理整頓してました。それに疲れました。
プライバシーポリシーも変わるからさっ!エヘ!テヘペロ!
ついでに『NAVERまとめとはなんだったのか』 とか言ってやる!
ざまぁ!ざまぁ!アルファギーク()ざまぁ!

別にNAVERまとめに疲れてはいないけど、要望はありますね。
あ、NAVERまとめへの要望まとめを作ればいいのか。

NAVERのご意見ご要望の掲示板はあって、

http://uservoices.naver.jp/

ちゃんとスタッフの人が(同じような返事が多いが)返事してたりして、
amebaに比べたら100億倍マシだなぁとおもってみたりしています。でも、この公式の掲示板、どのサービス向けなのか、
ユーザが一目見てわからないから、そこらへん何とかして欲しいと思います。
その点、はてなのはてなアイデアってある種画期的ですよね。

http://i.hatena.ne.jp/

というわけで、NAVERまとめへの要望まとめを作ってみた。

http://matome.naver.jp/odai/2133004169489844101

既に同様のまとめがあったら、そっちを使うべきだと思う。
検索してない。エヘ!テヘペロ!
うちの4歳の娘までテヘペロテヘペロ言い出してます。流行ってますね。
そんな感じでした。

2012年2月17日金曜日

期待のJSゲームエンジン enchant.js でキーボードの入力だけ処理させる。

enchant.js 触ってみました。
参考にしたのがこちら。enchant.js でプログラム組む方法が良くわかる。

「enchant.js」でゲームを作ろう! HTML5とJavaScriptによるアクションゲーム制作入門


別に熊とかを動かしたいわけではなく、キーボードの入力だけを処理させたかったので、
そういうことをやってみます。
『キーボードの入力のためだけにenchant.js 使う必要なくない?』と言われそうですが、
まぁ、ものは試し。男は度胸。何でもためしてみるのさ。

最初に書いたのがこんな感じ。
なんとなく jQuery も使っています。

enchant();
$(document).ready(function(){
    var game = new Game(320,320);
        game.onload = function(){
            this.addEventListener("enterframe",function(){
                if(this.input.left) {alert("left") ;}
                if(this.input.right){alert("right");}
                if(this.input.up)   {alert("up")   ;}
                if(this.input.down) {alert("down") ;}
            });
        };
        game.start();
});

MACやスマホはわかりませんが、Windowsでキーボードの矢印キーを押すと、
アラートが出ました。
そこまではよかったものの、
アラートが出続ける…あらら。こまったので、F5キーを連打しました(笑)
で、書き直したのがこんな感じ。

enchant();
$(document).ready(function(){
    var game = new Game(320,320);
        game.onload = function(){
            this.addEventListener("enterframe",function(){
                if(this.input.left) {alert("left") ;this.input.left  = false;}
                if(this.input.right){alert("right");this.input.right = false;}
                if(this.input.up)   {alert("up")   ;this.input.up    = false;}
                if(this.input.down) {alert("down") ;this.input.down  = false;}
            });
        };
        game.start();
});

いちいち それぞれのフラグを false にしてやるわけですね。
これでアラート連発が無くなりました。

まぁ、ただそれだけです。

2012年2月16日木曜日

node.js + jsdom + jQuery で Gumroadで売った商品をブログに貼るブログパーツ作った

完璧に惰性。デザインのセンスなし。
うわーんうわーん。
このページのしたの方にはっつけてあります。
なーんか、iframeってどうなのよ?知らんがな。

なんか、NAVER まとめのブログパーツを no.de で動かしていたんだけど、
サーバが変ぽいので、herokuに変えた。
ついでに、それをイジって Gumroad のブログパーツもつくったった。

導入方法とかは、
Gumroadで売った商品をブログに貼るブログパーツ作った。
http://matome.naver.jp/odai/2132940047075673701

ここに書きました。
適当にやってください。

ソースとか、書かなきゃ駄目か?大したことしてないからいいだろー。てへぺろ。

2012年2月15日水曜日

Gumroadについて

Gumroad っていう、自分の作ったものを Twitter とかで手軽に売れるサービスが話題になってます。 

大体の流れとか、問題点とかは、
 
 個人コンテンツ販売の新時代を開くか 「Gumroad」で同人誌を売ってみる (1/3) - ITmedia ニュース 

ここを読んだらよくわかります。
NAVERまとめ も結構あります。

日本製の派生サービスの Ameroad っていうのもテストで始まってます。
ITメディアの紹介記事ね。
 
Gumroad は 海賊版とか売られたりしたらやばいよ!という記事が多いですね。 



 
 Gumroad の危険性について早めに警鐘を鳴らします 物語を語ろう。物語を創ろう。
 Gumroad の問題点についてもう少し掘り下げてみました。 物語を語ろう。物語を創ろう。 
 RMB: もしあなたの著作物が知らぬ間にGumroadで売られていたら

実際に Gumroad で曲を売ったけど、100%自作曲じゃなくて、
東方(?シューティングゲームだっけ?)の曲のアレンジだったからテンパッた人の話。
 
 話題のGumroadを使って楽曲を販売してみたAnitaSunの記録 - Togetter

昔iTunesで再生している曲タイトルを2ちゃんねるブラウザに送るアプリを作ってくれた fladdict さんが
なんか絡まれている様子のドキュメンタリ。
 
 なんでGumroadに苦言まとめエントリ書く人は『黒いことしてバレると人生ゲームオーバーヤバい』ってことを、誰も書かないの?イデオロギー的な理由とかなの? - Togetter
 
海賊版うんぬんについては、概ね、どうとも思わないというか、fladdictさんの言ってるとおりだなと思う。
お金にする為に Gumroad を使うという前提がある以上、お金にならないことはやらないだろうし。
『お金がかかるものをタダで皆で使おうぜ!』という行動とは違うからなぁ。 
ていうか、fladdict さんに至っては、自分の作ったiPhoneアプリが散々割られているような人なのに、
よく冷静に分析できるなーと思います。
 
mixi の日記でも書いたけど、
オンザクラウドでパーソナルなタレントがマネタイズされるのは素晴らしいよねぇ。手軽だし。
海外法人だからどうだこうだっつったってさー、Twitterだって日本法人できるまで使わなかったの?とか思うし。
Googleは?Yahooは?実際Googleは日本に法人あるけど、安全なの?って思う。

新しい手段が生まれることは素晴らしいと思うし、Gumroad を装うフィッシングサイトが怖いねーと思います。
機能やシステムより、その枠組みの外にある『人間の行動』が怖いわけだから。 
うまく言えないな。例えば、Gumroadの中に居れば安全、
Gumroad だと思って別なサイトに入った人のことはGumroadは守れない、
Gumroad は Gumroad に行きたい人を全て Gumroad に誘導出来ない、
Gumroad は Gumroad に似せたサイトへのアクセスを Gumroad に強制リダイレクト出来ない、という事か。
いずれにせよ、良くないサービスは廃れるだろうし、良くないサービスにならないようにサービスを運営する人は努力するだろうし、って思う。

あー。マネタイズってところで思い出したけど、
うちの嫁から聞いたんだけど、
アメブロを使っている奥様の間で、ヤフオクとかを使わないで、
アメブロの中だけで物の売り買いをしてるらしいよ。中古の子供服とか。
他のブログサービスだとそういうのは禁止されているらしいけど、
アメブロは禁止されていない(?)らしく、そういう売買の行動があるらしい。
当然物品のやりとりに必要な個人情報とか、口座番号は、
相手に開示したりするんだろうけど、そういうことに抵抗がないのはなんなんだろうな?と思う。


で、俺もGumroadで何か売ろうかなーという感じになってきたので、
カリフォルニア州の法律的に問題が無ければ、
アート作品として、ようじょのパンツ姿の写真を $10 で売ろうと思います。
この記事のはてなブックマークのコメントにうp!と書いた人が10人以上居たら通報販売します。

2012年2月14日火曜日

NAVERまとめのブログパーツを作った。

※2012/02/15 なんかサーバに繋がらなくなってるなぁ。なんでだろ。

公式を見ても、人気のまとめのブログパーツしかないみたいな感じだったので、
よく確認もしないで作った。
全然反省とかはしていない。
公式のものがあるなら、それを使ったほうがいいし、
公式のものがないなら、それが出来るまでの箸休めです。

動作は、このページの右側にあるやつを見て確認してください。
使い方やなんやらは、
http://matome.naver.jp/odai/2132921992271736701
からどうぞ。

最初は php でやろうかなーとか思ったんですが、
勉強をかねて、node.js でやりました。
node.js で jsdom + jQuery でスクレイピングしているので、
blogparts.no.de からのアクセスとかを 403  されたら使えなくなります。

jsdom + jQuery でのスクレイピングは、
過去に思いっきり自分用というか、当時の会社用で、
×××の○○○○○をごっそり抜き出すようなものを作ったことがあるのですが、
他の人がアクセスするようなものを作ったことが無かったので、
http で サーバを立てるところからお勉強でした。

NAVERのサーバにあるCSSを link rel したり png ファイル読み込もうとしたんですが、
うまくいかない感じだったので、
ソースに直で 長ったらしい CSS 書いたり、

こちら
[JavaScript] dataスキームURI生成(画像データのBase64変換)
で base64に画像変換してみたりしました。

取り合えず、動いたので良かったです。

あ、ソースコードはこんな感じです。インチキくさい。
修正すべき点とかご指摘いただけたらと思います。不慣れなもんで。フヒヒヒヒ。てへぺろ。

var http   = require("http"),
    url    = require("url"),
    qs     = require("querystring"),
    XHR    = require("xmlhttprequest").XMLHttpRequest;
    jsdom  = require("jsdom"),
    jq     = "http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js";
var style = function(){
    var str  = "";
        str += "*{font-size:10px;}";
        str += ".MdMTMTtlList01{margin-left:0;padding-left:0;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Item,.MdMTMTtlList02 .mdMTMTtlList02Item,.MdMTMTtlList03 .mdMTMTtlList03Item{display:table;*display:inline;width:100%;}";
        str += ".MdMTMTtlList01{overflow:hidden;*zoom:1;margin-bottom:-15px;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Item{margin:16px 0 0 0;padding:0 0 15px 0;border-bottom:1px solid #f2f2f2;margin-bottom:-1px;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Item:first-child{margin-top:0;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Thumb,.MdMTMTtlList02 .mdMTMTtlList02Thumb,.MdMTMTtlList03 .mdMTMTtlList03Thumb{display:table-cell;*display:inline;*zoom:1;width:60px;height:60px;padding:0 13px 0 0;vertical-align:middle;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Thumb a,.MdMTMTtlList02 .mdMTMTtlList02Thumb a,.MdMTMTtlList03 .mdMTMTtlList03Thumb a{display:block;width:60px;height:60px;overflow:hidden;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Txt,.MdMTMTtlList02 .mdMTMTtlList02Txt,.MdMTMTtlList03 .mdMTMTtlList03Txt{display:table-cell;*display:inline;*zoom:1;vertical-align:middle;word-wrap:break-word;table-layout:fixed;width:100%;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Ttl,.MdMTMTtlList02 .mdMTMTtlList02Ttl,.MdMTMTtlList03 .mdMTMTtlList03Ttl{display:inline;font-size:10px;font-weight:bold;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Ttl a:link,.MdMTMTtlList01 .mdMTMTtlList01Ttl a:visited,.MdMTMTtlList02 .mdMTMTtlList02Ttl a:link,.MdMTMTtlList02 .mdMTMTtlList02Ttl a:visited,.MdMTMTtlList03 .mdMTMTtlList03Ttl a:link,.MdMTMTtlList03 .mdMTMTtlList03Ttl a:visited{text-decoration:none;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Ttl a:hover,.MdMTMTtlList01 .mdMTMTtlList01Ttl a:active,.MdMTMTtlList01 .mdMTMTtlList01Ttl a:focus,.MdMTMTtlList02 .mdMTMTtlList02Ttl a:hover,.MdMTMTtlList02 .mdMTMTtlList02Ttl a:active,.MdMTMTtlList02 .mdMTMTtlList02Ttl a:focus,.MdMTMTtlList03 .mdMTMTtlList03Ttl a:hover,.MdMTMTtlList03 .mdMTMTtlList03Ttl a:active,.MdMTMTtlList03 .mdMTMTtlList03Ttl a:focus{text-decoration:underline;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Thumb+.mdMTMTtlList01Txt{width:593px;max-width:593px;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Draft{color:#959595;font-size:10px;font-weight:bold;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01TimeStamp{color:#afafaf;font-size:10px;}";
        str += ".MdMTMTtlList01 .MdSocialCountList01{margin-top:2px;}";
        str += ".MdMTMTtlList01 .MdMsgDisp01{display:table-caption;margin-bottom:4px;}";
        str += ".MdSocialCountList01{margin-left:0;padding-left:0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Li{display:inline-block;*display:inline;*zoom:1;margin-left:7px;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Li:first-child{margin-left:0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Ico{display:inline-block;*display:inline;*zoom:1;overflow:hidden;margin:0;padding:0;border:none;background:url('data:image/png;base64,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') no-repeat 0 0;text-align:left;vertical-align:middle;text-indent:-9999px;*text-indent:0;*line-height:9999px;*word-wrap:normal;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Hatena .mdSocialCountList01Ico{width:12px;height:12px;margin-top:-4px;*margin-top:0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Twitter .mdSocialCountList01Ico{width:12px;height:12px;margin-top:-4px;*margin-top:0;background-position:-15px 0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Facebook .mdSocialCountList01Ico{width:12px;height:12px;margin-top:-4px;*margin-top:0;background-position:-30px 0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Comment .mdSocialCountList01Ico{width:14px;height:13px;margin-top:-2px;*margin-top:0;background-position:-50px 0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Good .mdSocialCountList01Ico{width:13px;height:14px;margin-top:-4px;*margin-top:0;background-position:-70px 0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Comment,.MdSocialCountList01 .mdSocialCountList01Good,.MdSocialCountList01 .mdSocialCountList01View{margin:0 -2px 0 0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Label{margin:0 5px 0 0;color:#7b7b7b;font-family:Tahoma,Arial,Helvetica,sans-serif;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Num{font-weight:bold;color:#7b7b7b;font-family:Tahoma,Arial,Helvetica,sans-serif;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Hatena .mdSocialCountList01Num,.MdSocialCountList01 .mdSocialCountList01Twitter .mdSocialCountList01Num,.MdSocialCountList01 .mdSocialCountList01Facebook .mdSocialCountList01Num{margin-left:4px;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Comment .mdSocialCountList01Num,.MdSocialCountList01 .mdSocialCountList01Good .mdSocialCountList01Num{margin-left:5px;}";
    return str;
}
var app = http.createServer(function(req,res){
    res.writeHead(200,{"Content-Type":"text/html"});
    var prm = url.parse(req.url,true);
    if(req.method == "GET" && prm.query && prm.query.mode){
        var mode  = prm.query.mode;
        if(mode != "matome.naver"){res.statusCode=403;res.write("403 Forbidden");res.end();return;}
        var usr   = prm.query.usr.replace(/script|\"|\'|\(|\)|\{|\}|\:|\;|\,|function/gi,"");
        if(!usr || usr == ""){res.statusCode=403;res.write("403 Forbidden");res.end();return;}
        var naver = "http://matome.naver.jp/mymatome/" + usr;
        var xhr = new XHR();
            xhr.onreadystatechange = function(){
                if(this.readyState == 4){
                    var con  = this.responseText;
                    var doc  = jsdom.jsdom(con);
                    var win  = doc.createWindow();
                    var body = "";
                    jsdom.jQueryify(win,jq,function(win,$){
                        body = $(".mdMypageMTMList01Item").html();
                        res.write("<!DOCTYPE html><html lang='ja'><head><meta charset='UTF-8'>");
                        res.write("<style>" + style() + "</style>");
                        res.write("</head><body>");
                        res.write(body);
                        res.write("</body></html>");
                        res.end();
                    });
                }
            };
            xhr.open("GET",naver);
        xhr.send();
    }else{
        res.end();
    }
});
app.listen(80);

javascript で 出来る色んな事をまとめた。

NAVERまとめでまとめました。

JavaScript でこんなことも出来るのか!なまとめ
http://matome.naver.jp/odai/2132918730570646901


まぁ、Twitterで既に見た人も居ると思うけども。
個人的に、『おっ!こんなこともできるのかー!』みたいのを纏めた。
見た目的に凄いのもあれば、
『こういうのはウィンドウズのアプリケーションじゃないと出来ないと思ってたよー』
みたいなのもあります。


javascript っていうと、範囲が広いんだよなぁ。
『こりゃ凄い』みたいなのを、素直な気持ちで纏めて行きたいと思います。
他の人にとっては大したことなくても、
俺にとって凄ければそれでいいじゃないの。人間だもの。みつを。

『一昔前というか、俺がインターネットを始めた時は、
javascript って嫌われてたなー』

というのを、ついつい、何度も書いてしまう。

例えば、ゲームに関して言えば、
その頃のブラウザゲームというと、
CGIで都度ページをリロードして遊ぶようなゲームだった気がする。
FLASHも3が出たかどうかみたいな感じで。
ブラウザで遊べるJAVAのゲームもあったけど、凄く重くて、みたいな気がした。
その頃とは、凄く変わったんだなーと思う。

ブラウザにプラグインを入れなくてもゲームが出来るってところは、
凄い事だと思う。
Java、Flashみたいに、なんか、コンパイルされたファイル(.jar とか .swf)じゃなくても、
.js で誰でも作れる、中を覗ける、改造できるっつーのも、魅力ではあるよねぇ。

でも、html に <embed> って書くか、 <canvas> って書くかに変わっただけな気もする。
それが、凄いことなんだけど、不思議だよねぇ。


javascript で pdf が作れる、 zip が作れる、 psd を開ける、 lzh を開ける、
サーバが立てられちゃう、iPhone アプリが作れちゃうつーのは、
とっても楽しいことだなーと思う。

そういえば、
javascript と同じようにあの頃嫌われていた ActiveX はどうなったんだろう。


2012年2月13日月曜日

Google Street View 上に Three.js の 3D グラフィックを表示

実行結果は

http://psychedesire.webcrow.jp/stmon/

キャラクタがボヨンボヨンします。
WebGL対応のブラウザで開いてください。Chromeとかなら大丈夫だと思うよ。



コチラより。
今のところGoogleに怒られていません。
まぁ、アクセス自体が無いからねぇ。

3D オブジェクトは、メタセコイアで作り、それを Blender にインポートして、Blender から .js に変換しました。
mesh.rotation.x とかが動かない?よくわからないので、
camera.rotaion.x とかで無理矢理キャラクタをボヨンボヨン動かしています。

殆どのやり方は、


空が狭い: Three.jsでMQOデータを表示するまで

こちらを参考にしましたが、違うやり方をしたのが2点あって、
1点が、
Blender に メタセコイアのデータ .mqp をインポートする場合は、
 
 Blender2.5~2.6 - とあるPGの研究記録Ⅱ(レコーダー)

このインポータを使いました。Blender の最新 2.6.1 にも対応しています。

2点目が、
Blender から Three.js への エクスポータが、現状 2.6.0 にしか対応していないので、
 \Blender\2.61\scripts\addons\io_mesh_threejs\__init__.py
の28行目の 2.6.0 を 2.6.1 に書き換えました。

苦労した点、というわけじゃないけど、
ブラウザで3Dオブジェクトを表示したときに、どこにオブジェクトがあるのか、わからなかったので、
カメラの位置とかを色々動かして、なんとか最適なカメラポジションとか設定しました。
なんせ、3Dがわからないので。
コツとしては(?)オブジェクトを、ステージに対して、凄く巨大にすればいいみたいです。
あと、何故か、上下逆転する?ので、Blender上でY軸に180度回転させたりしています。

画像的に言うと、メタセコで






こうやって作って、
Blenderで

こうしてから、Three.js にエクスポートしてる感じです。。。
よくわからないけど、 これでうまくいった。
取り合えず、素材を6個作るので限界だった~。
3Dで凄い造型を作る人って、凄いよね。

マウスのイヴェント処理に応じて、3Dオブジェクトのカメラ位置を変えたり、
連動してストリートビューの表示を変えたり出来たら、見た目部分はOKかなーと思います。
あとは、部品だよね。これは。あまりにショボすぎるけど、
フリーのやつ使うのもねー。せっかくだから自作したいもんねー。

Googleに怒られるまで、チョコチョコイジって遊びたいですね。

2012年2月11日土曜日

各種3D製作ソフトのファイルを Three.js 用JSONに変換する方法まとめ

英語が多くて、なんか嘘が多そうな予感。

色々見てみたのですが、
それぞれのソフトで、.obj にしてから、convert_obj_three.py というのを使って、
JSON にコンバートするみたいです。
python のコンバータ convert_obj_three.py は

https://github.com/alteredq/three.js/tree/master/utils/exporters



https://github.com/mrdoob/three.js/tree/master/utils/exporters

ここにあります。
AutodeskFBX・Blender・3DS MAXは専用のエクスポートモジュールやプラグインがあるみたいですね。
mrdoob さんのほうが最新みたいですが、
blender の古いバージョンのプラグインとかは alterdq さんのほうにしかなかったり?するみたい。
動作デモは、

http://alteredqualia.com/tmp/three/examples/obj_convert_test.html

ここにあります。


3DS MAX
専用のエクスポータもあるようなのですが、
.obj に出力してからのほうが綺麗みたい?です。
.obj への出力の仕方が書いてありました。
http://bkcore.com/blog/3d/webgl-three-js-workflow-tips.html

MAYA こちらも .obj にしてから、みたいですね。。
http://blog.stickmanventures.com/2011/11/17/convert-a-model-from-maya-to-webgl-for-use-with-three-js/

md2
やりかたはこちら(日本語)。
http://d.hatena.ne.jp/nakamura001/20120206/1328542607

デモはこちら
http://oos.moxiecode.com/js_webgl/md2/index.html

なんでこんなのまとめたかというと、.x ファイルという 3D のファイルがあって、
それを Three.js で使えるようにするJSONコンバータを作りかけていたんですが、
ものすごくワケが判らなくなってやめましたw

俺が使ってるメタセコイアでも、

http://homepage1.nifty.com/garbagesoft/tools.html

ここにあるプラグイン使えば(?) obj に出来るぽいんだけど、
プラグインを使えるのはシェアウェア版のみなのだよ。なのだよ…

Google Street View にモンスターが出現するWebアプリ作った。



超適当です。アハハハハ。
 ストモンと言います。ここで見れますよ。
http://psychedesire.webcrow.jp/stmon/

Google Map API の v3 というのが出ていて、
それだと、 Flash ではなく、 html5 で Street Viewが見れるようなので、
思い切ってやっちゃいました!エヘヘヘヘ。
知らなかったわぁ~。

Googleストリートビュー内で銃を撃てる『Google Shoot View』が閉鎖

まぁ、こういう前例があるので、直ぐに使えなくなると思いますけども。

GoogleChromeでしか動かないかも知れません。
他のブラウザは試してないです。

郵便番号を入れると、
その郵便番号近辺の地域で卵が孵ります。
で、勝手にモンスターの種類が決まります。

その内容でよければ、名前をつけて保存してください。
保存したモンスターは、ストモンって書いたアイコンを押せば見れます。
他は何も出来ません。

ほんとは、Three.js で作った3Dオブジェクトを表示させたかったけど、
心の中の悪魔が、
『どうせGoogleに消せって言われるんでしょ?』
と言ったので、凄く適当になりました。


製作時間10時間ほどです。
データストレージは WebStorage(localStorage) なので、
サーバ側に何か残したりしていません。
郵便番号投げると住所のJSONを返してくれるAPIがあったので、
使わせていただきました。

郵便番号検索API by グルーブテクノロジー株式会社

スマホと連動すれば楽しいのになぁとか、
夢が広がるんですけどね。残念だなぁ。

2012年2月8日水曜日

Three.js と Google Street View で 街にモンスター出現

なんて出来たら楽しいんじゃないかと思ったので、やってみた。

みんなが使っている、インターネットを見るためのソフト(ブラウザ)に、
Javascriptでプログラムを組んだりするだけで、
3Dの画像なんかを表示する技術が出来つつあります。

Three.js というJavascriptフレームワークを使うと、3Dグラフィックをブラウザに楽に描画できます。

でも、3Dグラフィックをコードだけでプログラミングするのはめんどうくさい。
巷には、 ShadeやPoser、3DSMAX、メタセコイア、六角大王、Blenderなど、
3Dグラフィックを出来るだけ簡単に作れるようなソフトがあって、
そんなソフトと同じように、Three.js用のデータを作れるものが、ThreeFabという名前で公開されています。

Moongift さんの紹介記事
Three.js対応。Webブラウザ上で3Dモデルを作成「ThreeFab」

で、これを使いながら、GoogleStreetView上に、自分の作った3Dグラフィックを描画できないかという実験です。
あ、結果から言うと、失敗です。

まずは、ThreeFab の準備。
ThreeFab はGit 上にありますので、
Git が既に使えるという状態であれば、
Windowsのコマンドプロンプトを開いて、
cd c:\
git clone git://github.com/blackjk3/threefab
とすれば、
Cドライブ直下の threefab というディレクトリ に ファイルがダウンロードされ展開されます。
C:\threefab\index.html を GoogleChrome にドラッグアンドドロップすれば、
ThreeFab が使えます。(この使い方であってるのか?取り合えず動いた)
で、実際に3Dオブジェクトを作ってみた。





なんだこのタコチュウ。
で、出来たので(多分10分くらいで作った)、右上のエクスポートを押すと、
なんかいっぱいJavascriptコードが表示されるので、どっかにコピーしておきます。

次は Google Street View。
まずは、

http://code.google.com/intl/ja/apis/maps/documentation/javascript/v2/services.html

ここの左上の登録してAPIキーを取得をクリックして、
APIキーを取得します。
使うウェブサイトのアドレスを入れたら、APIキーが取得できると思うので、
Javascript のところに書いてあるものをまるっとコピーします。

で、どうやって使うかというと、

ストリートビューを表示する

ここに書いてあるのを改造しちゃいましょう。でへ。てへぺろ。
ていうか、openspc2.org って、色々なサンプルがあって凄いよねぇ。

で、なんかうまいことやろうと思ったけど、ThreeFab から export した Javascript のコードが動かない。
よく見ると、ところどころ、必要ないっぽい }); が存在している…
そこの部分をコメントアウトしても、なんか何にも表示されないし。
まぁ、仕方ない。こういう時は、あきらめよう。検索しても何も出てこない。
つか、そもそも Three.js の使い方が判らないからなー。

Three.js のサンプルコードを表示することにします。
Three.js もGit にあります。
いちいち clone とかしなくても、 Git のページをちょっと下にスクロールすると、
Minified Library って書いたリンクがあるので、それをダウンロードして使うと良いです。
その下にサンプルコードがある(赤い線の立方体がアニメーションするやつ)ので、
それをまんまコピペした。

で、ぽこぽこ書いてみた。
[CSS]
        <style>
*{margin:0;padding:0;vertical-align:middle;}
#streetview{
    position:absolute;
    top     :0;
    left    :0;
    width   :640px;
    height  :480px;
}
#three{
    position:absolute;
    top     :0;
    left    :0;
    width   :640px;
    height  :480px;
}
        </style>

[Javascript]
// Three.js のサンプルコード
    var camera, scene, renderer,geometry, material, mesh;
    function init() {
        scene = new THREE.Scene();
        // camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
        camera = new THREE.PerspectiveCamera( 75, 640 / 480, 1, 10000 );
        camera.position.z = 500;
        scene.add( camera );
        geometry = new THREE.CubeGeometry( 200, 200, 200 );
        material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
        mesh = new THREE.Mesh( geometry, material );
        scene.add( mesh );
        renderer = new THREE.CanvasRenderer();
        // renderer.setSize( window.innerWidth, window.innerHeight );
        renderer.setSize("640","480");
        // document.body.appendChild( renderer.domElement );
        $("#three").append(renderer.domElement);
    }

    function animate() {
        // note: three.js includes requestAnimationFrame shim
        requestAnimationFrame( animate );
        render();
    }

    function render() {
        mesh.rotation.x += 0.01;
        mesh.rotation.y += 0.02;
        renderer.render( scene, camera );
    }

// StreetView の 描画
var makeStreetView = function(callback){
    var streetObj = new GStreetviewPanorama(document.getElementById("streetview"));
    var sibuya = new GLatLng(35.660748,139.701762);
    streetObj.setLocationAndPOV(sibuya);
    if(callback && typeof(callback) == "function){callback();}
};

$(document).ready(function(){
    makeStreetView(function(){
        init();
        animate();
    });
});

[html]
    <body>
        <div id='three'></div>
        <div id='streetview'></div>
    </body>

みたいにしたけど、残念。Google Street View はFlashで動くので、z-index が効きません。
なので、Google Street View の上に、3Dオブジェクトを描画することが出来ませんでした。
Google Street View の下のレイヤに、赤い立方体が回っている感じになった。

Flash コンテンツが z-index を無視して覆い被さってしまう件
[flash][javascript] Flash の z-index を Javascript から有効にする
z-indexを無視してFlashが上に重なってしまうのに対処

色々調べたけど、まぁ、無理だなぁ。
あとからパラメタ書き換えたけど、うまくいかなかった。

つか、そもそも、Google Street View のAPI利用規約とかにひっかかりそうなので、
だめだろうな。うむ。


『地図上のロゴや属性を改変したり、見えにくくしないでください。』

って書いてあるしね。
でもまぁ、ブラウザで Three.js を使ったりすることを体験できたから良かった。
サンプルをみてるだけで満足することが多いので、
何かしら自分で作ってみることって大事ですよね。
結局サンプルはっつけただけの記事書いておいて、ですけど、そう思います。

html5 の pushState が 動かなかったのと、jQuery と html5 data と pushState。

原因:ローカルにおいてあるファイル(file://~/index.html) を開いていたから。
Windows環境ではダメでした。
<script>
 var url = "http://localhost/hoge";
 history.pushState(null,null,url);
</script> 
とかやってもダメでした。

単純に『pushState file://』で検索しても出てこない。
俗に言う、凡ミス(てへぺろ)の領域なんだろうけど、
そんな事で5分間とか時間を無駄にする人が二度と現れない事を祈ります。
適当なサーバに置けば、ちゃんと動きました。

html5 では、data-hoge-moge みたいな、オレオレアトリビュートで、
ほーむぺーじに情報を付け加えられるそうです。
jQueryMobile とかで使われているやつですね。Microdata とかと繋がっていくとかどうとか。
Microdata については、

HTML5の新要素「data要素」に繋がる Microdataのプロパティについて

この記事が詳しいです。
RSSとかXMLとかhtmlって、データベースの行とか、データベースのテーブルとしても使えたらいいよね?
みたいなのを、ずっと色々やってて、うまくいかなかったけど、
なんかやっとうまくいくんじゃね?みたいな感じなのかなーと、
勝手に見てましたけど、違ったらごめんなさい。
検索エンジンに対してのページ解析とかにも関っていったり、
SocialGraph っつか、まぁ、SNS とか、そういうのにも関ってくるよーみたいなものだそうですよ。
この辺について変なことを書くと、森ボーイという人からツッコミが入るので、さらっとふわっとしか書きません。

で、この data要素data属性使って pushState いじくりゃいいんじゃね?みたいなのを書きました。
まぁ、きっと、色んな人が既に書いてるものですけど。多分。めげずに Fight!

<script>
    $(document).ready(function(){
        $("nav").on("click","li",functioni(){
            var data = $(this).data("hogeHuga"); *
            var url  = "";
            for(var i in data){
                url += "/" + encodeURIComponent(data[i].replace(/\"|\'|\(|\)/gi,""));
            }
            history.pushState(null,null,url); // "/hirama/hokkaido"になるとおもう
        });
    });
</script>

<nav>
    <ul>
        <li data-hoge-huga='{"name":"hirama","state":"hokkaido"}'>おれっちひらまっち</li>
    </ul>
</nav>
こんな感じになりました。
jQuery の on を使ってみましたよ!うほ。
jQueryの on off は、この記事がわかりやすかったです。
赤で * 書いてあるところが大事みたいです。

html 上は、 data-hoge-huga って書いてあるんだけど、
この中身を取り出すときは、 hogeHuga って、キャメルクラッチ キャメルケースになるそうです。
キャメルクラッチについては、ここが詳しいです。
jQuery でデータを呼び出す時は、この例のような書き方をすると、object 型になります。

[追記:
 <data hoge='1234'>ほげー</data> ← data要素
 <span data-hoge='1234'>ほげー</span> ←data属性
 というそうです。森ボーイこと forestk さんご指摘ありがとうございます!
 そうだよね。要素っつったら、<a></a> だもんね。エレメント。
 属性つったら、 href='' だもんね。アトリビュート。
 jQuery で要素を取るんだったら、普通に $("data").attr("hoge") で取るのか?おう?あれ?
]

この辺の挙動については、

意外と要注意 HTML5データ属性とjQuery Data APIの関係まとめ

ここに詳しく載っています。

で、for in でデータを基にURLつくって、pushState にホイと渡す感じですね。
渡すだけだと、ただブラウザのURLが変わるだけなので、
このデータに基づいて、ajax かなんかでデータのやり取りをして、なんかする感じ。
そこらへんは、

AjaxでもURLを更新して履歴を作れるHTML5のpushState試してみた

この記事が良くわかります。
応用というか、canvas ていう線を書いたりするやつも交えて使っているのが、

history.pushState、history.replaceState

この記事です。
うむ。うむうむ。

ええと、こんな感じでした。これで何をするのかは、わかりません。

2012年2月7日火曜日

Google Adwords の人から電話が来た





 最近、PV数も増えたし、広告を載せようということで、
GoogleとAmazonの広告を載せ始めました。

で、←の画像の広告が出てきたので、
なんだろーこれと思ってクリックしたら、
Googleに広告が出せるよ!ていう、GoogleAdwordsが3000円分タダで使えるよーって案内だった。

『Androidアプリの宣伝して貰えばいいずwwwwww』と思って、
名前と電話番号と、会社のHPなんてないから、AndroidマーケットのURLを入れて送ったら、
GoogleAdwordsの人から電話が来た。

なんか、企業情報にあたる情報(名前とか電話番号とか住所とか)と、
プライバシーポリシーが無いとダメですってことだったらしい。
まぁ、マーケットのページには、俺の住所も電話番号も載ってないよなーと思ったので、
『じゃあ、ブログがあるんで、そこに書いてもいいすか?』って言ったら、
OKっぽいので、このブログに電話番号とかプライバシーポリシーとかを載せることにしてみる。

なんか、電話で打ち合わせをしながら、広告掲載とかするみたい。
へぇ~。前居た会社とかで、求人広告の打ち合わせとかした事があるんだけど、
そんな感じなのだろうか。面白そう。

あーいう電話営業は、Googleの人じゃなくて、代理店の人とかが電話してるのかなー?
アウトソーシングってやつ?どんな風になってるんだろーなぁ。
もうコールセンタ業とか足を踏み入れたくないな、と思いつつ、
やっぱり興味出てきちゃうよねぇ。

LivedoorBlog にエロブログを作るまでをNAVERまとめした。


僕が LivedoorBlog にエロブログを作るまでにやった事

なんのこっちゃないスクリプトですねぇ。

1・エロイ画像を投稿しがちなTumblrを集めてくる。
2・APIでJSON取って来て、type=photo の画像のアドレスを集める。
3・新しい画像を全部ダウンロードする
4・ダウンロードした画像のサムネイル版を作る
5・AmazonS3にアップロード
6・画像とかのURLをLivedoorBlogに記事としてメールで投稿する。

みたいな感じ。
全然、Blogへの愛がないからかわからないけど、収入にはなりませんね。
PV数も全然上がらないしなー。
逆に、AmazonS3にお金払っている分赤字ですね(笑)
ちゃんと記事を書いているエロブログって、
なんていうの?『魅惑の黒タイツ画像で抜こうずwwwww』とか『この素人エロ杉wwww』 とか、
ブログエントリ毎に画像を選んでいるから、みんな見るんだろうなーと思います。
俺のはあからさまに機械的だもんなー。

でも、結局みんな、エロ画像が見れれば、それでいい!って話じゃないの?とも思うけど、
ん~。でもまぁ、やっぱ、入り口が大事というか、
『よぉし!このブログタイトルならば、さぞかしエロイ画像に違いない!』
と思い、期待に胸膨らませながら、ブログエントリを開いて見る、というところに、
男の浪漫?あるんじゃない?うん。俺はわかってる。

2012年2月6日月曜日

Titanium Mobile で参考にしたものをNAVERまとめしてみた。

作ったまとめはコチラにあります。

最近流行ってますよね。お金もらえるらしいし。へぇ~。
エロイ画像を見るためにしか、殆ど使ってなかったNAVERまとめですが、
Firefoxのお気に入りがエラい事沢山溜まってしまい、
今 Blogger でまとめ始めていたので、Blogger でまとめるのをやめて、NAVERまとめにしてみました。
まぁ、べんりっちゃあ、便利かなぁ。

はてなブックマークとか、SBMサービスって、
エントリに対して何かしらタグをつけていって、
それが蓄積されたときに、付けられたタグ側から見て、まとめになってる感じ。
NAVERまとめみたいなのは、その逆なだけなんだよねぇ。

その、見る人側的に、見たい、探したいものが決まっている時は、
NAVERまとめがいいんだろうなと思います。
SBMサービスは個人の関心事を緩く誰かの関心事と繋げるものっぽい?ので、
用途がNAVERまとめとはそもそも違うけども。
SBMのが、Twitter的で、
NAVERまとめのが、Blog的だなーと思った。

NAVERまとめの欠点?というか、そんなのがあるとすれば、
例えば、SBMのトップページで [これはひどい] ってタグを選べば、
全てのユーザが [これはひどい] とタグをつけたエントリがズラズラ出てくると思うんだけど、
NAVERまとめは、同じようなまとめが乱立しないのかな?って思う。
そういう秩序みたいなのは、どうなってるんだろう。

GitみたいにForkして、そこから先は俺はこう纏めるぜ!みたいに、
枝分かれして、集束いけば、きっとある程度、
情報の美しく纏まって行く様みたいなのが、あると思うけど。
纏めに対してタグ(トピック)をつけたり、複数人で編集出来たりするみたいだけど、
お金が絡むと、人間は難しいからなぁ。とか、色々、気を揉むよね。おっさんだから。

トピックが重複するまとめ達の中に含まれるアイテム(URLとか画像)で登場回数の多いものとかが、
見る側にとって大事だと思うんだけど、
そういったものを表示するものってあるのかなー?
javascript css html5 というトピックのついた A というまとめ上のURL X,Y,Z
javascript node.js html5 express というトピックのついた B というまとめ上のURL V,W,X

があったら、 javascript html5 というトピックにおいて、 X というURLは、大事だよね。ていう、意味ね。

なんせ、エロ画像しか見てないからわからない。
画像をZIPでダウンロードできる麿ボタンとかつけたらいいと思うよ本当に。

JSON かどうか評価する関数 isJson を作った。

結構、JSONをパースする度に、try catch して、
タブが深くなるので、
簡易的にJSONか評価する関数を作った。
ColdFusion ってやつだと、そういう関数があるみたいだけど、
Javascript ではないっぽい?
jQuery でもないっぽい?
まぁ、大して難しいものでもないので、良ければ使ってください。

var isJson = function(arg){
    arg = (typeof(arg) == "function") ? arg() : arg;
    if(typeof(arg) != "string"){return false;}
    try{arg = (!JSON) ? eval("(" + arg + ")") : JSON.parse(arg);return true;}catch(e){return false;}
}

alert(isJson(1));                 // false
alert(isJson({data:"hoge"}));     // false
alert(isJson('{"data":"hoge"}')); // true
alert(isJson("{'data':'hoge'}")); // false
alert(isJson(function(){return '{"data":"hoge"}';})); // true

ちゃんと、
'{"data":"hoge"}'

"{'data':'hoge'}"
を区別して評価してくれて良かった。

つか、JSON.parse() が出来るかどうかって、
(!JSON) で判別していいのかしら?
eval() は、昔どっかのブログでグローバルをなんちゃらとか書いてあった気がしたので、
できるだけ、JSON.parse() 使えたら使えるようにしたいんだけどもねぇ。
でも、JSON.parse() より eval() のほうが速いよ!っていうのも見た気がした。

Chrome16 と Firefox3.6.x で動作確認済みですー。

2012年2月5日日曜日

Cloud 9 で Git と連携する。 heroku に node.js のコードを deploy する。

 
Blogger、画像付記事が書き辛いな…勝手に回り込む…

まぁいいか。
Cloud9からGitと連携できるっぽいことに気づいたので、
画像付で親切に書いてみます。

なんで画像付で親切に書くかというと、
あとで自分でやり方がわからなくなるからです。

まず、ログインして、ダッシュボードで、
Githubの横の activate って書いた緑の字を押します。










そしたら、Githubのウィンドウが開くので、
IDとパスワードを入れてログインを押します。
















OAuth認証みたいな感じで、
Allow か Denyか聞いてきます。
レッチリの Dani California はかっこいい曲ですが、
ここでは Allow を選びます。 







すると、ダッシュボード左にGithubで使ってるプロジェクトが表示されました。
やったね!
まぁ、別に今はこれをどうこうする気はないので、放置。
あとでどうこうする時に、記事にしますね。

ちなみに、givmero っていうのは、
俺が作ったエロブログです。

今のところ、
Tumblrのエロ画像を良く貼っているところから画像をダウンロードして、
画像をAmazonS2にアップロードしたのち、
Livedoorブログに記事を投稿するようなPHPスクリプトですが、
Gitにコードを置いていません。残念。
ブログ自体は givmero ここらへんです。18歳以上の人だけ開いてね!












はい。画像転載バラ撒きクソエロブログはどうでもいいので、
次はCloud9で書いたコードを heroku にdeploy するやりかたです。

まず、プロジェクトから、rssgetter を開きます。
開いたら、左の deploy って書いた気球?をクリックして、
Create a Deploy Server をクリックします。





















deploy 先を選べます。
Heroku Joyent(no.de) Windows Azure が選べます。

























今はFreeのMacheneが作れないからか、
Joyentは有料のものしか表示されません…
























というわけで、heroku.com、君に決めた!という感じで、
heroku にサインインします。
heroku にアカウント持っている前提で話し進めます。
それくらいググれ。

常に優しい男はダメ。
たまに突き放す。そして、大事なときに、包み込む。
これが、本当の、男の愛情表現。わかる?
俺は自分で言ってて何がなんだか全然わかりません。


















でー、ボタン押したらメアドとパスワード入れろって言われるから、
入れてサインインを押します。押しめんします。

俺のオシメンは市井由理だね。
東京パフォーマンスドールの話だけど。






















穴井夕子はどうでもいいので、
サインインが完了すると、今 heroku.com 上にある
自分のアプリ名が表示されます。
今回は今あるのとは別なのを使いたいので、
create new を押します。オシメンします。
俺のオシメn(ry




















hatenaone という名前をつけてAddを押してみます。























完了すると、
hatenaone.herokuapp.com が作られます。

早速なので、Deployを押してみましょう!





package.json がねーぞと言われました。
あら。Cloud9上で書くのを忘れてました。
書いてもう一回やってみる。







今度はProcfileがねーよと言われました。
heroku で使うもの一式を
Cloud9上で準備しなきゃだめなんですねー。
web:node server.js って書くだけだから別にいいけど。

詳細は
http://devcenter.heroku.com/articles/node-js
この辺を見てください。





で、全部準備してDeployして、うまく動いたら
こんな風にActiveになります。

さっき作ったserver.js は、
その名前とは裏腹にサーバ機能をつけてないので、
hatenaone.herokuapp.com にアクセスしても意味はないのですが、
そこらへんちゃんとやれば、
ちゃんとできるはずです。

こんな感じでした。


Cloud 9 で node.js 開発 & オレオレ はてなOne 作った。

Cloud9 という IDE 統合開発環境?が人気みたいです。
Web上で開発が出来るっていうスグレモノみたいです。
node.js をいじることが増えたので、ちょっと使ってみることにします。

http://c9.io/#home

ココにアクセスすると、すぐ左に、表示名とメアドを入れる所があるので、
そこを埋めると、入れたメアド宛にアクティベートコードつきURLみたいなのが届きます。

























 ほんで、そのURLをクリックすると、パスワードを設定しろとか言われるので、
パスワードを入れると、ダッシュボードの画面になります。























で、早速適当にプロジェクトなんて作ってみます。
RSSをJSONにするようなやつを造ろうと思うので、
RSSGetterとか名前をつけて、CREATEします。
Git とか FTP とか色々やりかたを選べるみたいですが、
取りあえず Git でやってみる。



















CREATEを押すと、プロジェクトができるので、
START EDITINGを押してみます。


















しばらーくまっていると、こんな画面になります。
Show this quick start on startup のチェックをはずして、
Just the Editor Please を押してみます















NewFileしてみたり、OpenFileしてみたりするけど、
なんか、タブは増えても、書いたり出来ない…




















これはブラウザが悪いな。多分。
ということで、ブラウザをFirefox 3.6.x から Chrome 16 に変えます。























動いた動いた。

node.js で RSS をパースするには、node-feedparser というのを使えばいいみたいです。

node-feedparser

http://stackoverflow.com/questions/5722638/node-js-rss-module


ほうほう。
RSSの更新日付とかのことも考えて、日付のフォーマットを簡単に変えられるやつも使いたい。

node-datetime

var dt = dateformat((new Date),"yyyymmddHHMMSS");
こんな感じなのかなー?まぁ、やってみよう。
























とりあえず、こんな感じになりました。

オレオレ はてなOne ですね。

var XHR        = require("xmlhttprequest").XMLHttpRequest;
var FeedParser = require('feedparser');
var dateFormat = require('dateformat');

var HatenaOne  = function(usr,callback){this.usr = usr;this.callback = callback;this.init();};
    HatenaOne.prototype = {
        hatena     :["b","d","h"],
        myFav      :[],
        getFavList : function(callback){
        // お気に入りに入れているユーザ一覧を取ってくる
            var self = this;
            var url  = "http://www.hatena.ne.jp/" + this.usr + "/favorites.json";
            var xhr  = new XHR();
            try{
                xhr.onreadystatechange = function(){
                    if(this.readyState == 4){
                        var json = this.responseText;
                            json = JSON.parse(json);
                        self.myFav = json.favorites;
                    }
                };
                xhr.open("GET",url);
                xhr.send();
            }catch(e){
            }finally{
                if(typeof(callback) == "function"){callback();}
            }
        },
        getFeed    : function(){
        // お気に入りのユーザのはてダRSSとかはてブRSSとかフォトライフのRSSとか取ってくる
            var name = "";
            var url  = "";
            for(var i = 0,l = this.myFav.length;i < l;i ++){
                name = this.myFav[i].name;
                for(var j = 0,m = this.hatena.length;j < m;j ++){
                    url  = "http://" + this.hatena[i] + ".hatena.ne.jp/" + name + "/rss";
                    (function(self,url,cnt,parser){
                        parser.on("article",function(json){
                            self.myFav[cnt].time = dateFormat(json.pubDate,"yyyymmddHHMMSS");
                            if(typeof(self.callback) == "function"){self.callback(json);}
                        });
                        parser.parseFile(url);
                    })(this,url,i,(new FeedParser()));
                }
            }
        },
        init       : function(){
            var self = this;
            this.getFavList(function(){self.getFeed();});
        }
    };
   
var hoge = new HatenaOne("psychedesire",function(json){console.log(JSON.stringify(json));});

self.myFav[cnt].time = dateFormat()~のあたりが自信ない。書式これでいいのか?つか、
parser.on した json が一個ずつなのか、配列で返されてるのかちゃんとみてないので、
json.length とかやったりとかして、うまく書き換えて、
前回取得日より新しい更新だけを取得する、とか、
そういう処理を書いてください。そんくらい書けよって話しなんだけどね(笑

var dt = dateFormat(json.pubDate,"yyyymmddHHMMSS");
dt -= 0;
if(self.myFav[i].time &&self.myFav[i].time > dt && typeof(self.callback) == "function"){
 self.callback(json);
 self.myFav[i].time = dt;
}

こうですね。IF文長いね。まぁいいか。
てか、これこのままだと1回しか取得しないので、
init のところで setInterval() とかしなきゃだめだね。

ポイントは、(function(){})() してるところです。ああしないと、非同期?にならないはず。
此間、

timeline.js という非同期処理連携用ライブラリを作成

こういうのを見つけたので、こういうのを使えば調子良いのかも知れないですけど。

ご指摘とか、変だよとか、死ねとか、そういうのあったら言って下さい。死にませんけど。

あ、あと、package.json は

    "dependencies" : {
        "xmlhttprequest"  : "1.2.2"
      , "dateformat"      : "1.0.2-1.2.3"
      , "feedparser"      : "0.9.1"
    },

これみたいです。dateformat のヴァージョンがちょっと変わってるねーと思った。

あ、で、cloud9 の使い勝手ですけど、一応!とか×とか出てきたりしてくれるので、
勉強になりました。
for文の中で function 使うなとか言われました。テヘペロ。むしろテヘベロ。

joyent (no.de) がなんかおかしい件

1・smartmachine hoge.no.de を作る。
2・わけが判らなくなってきたので、 hoge.no.de を削除する。
3・smartmachine moge.no.de を作る。その日いっぱいはちゃんと動いてた。
4・今日、ブラウザで moge.no.de が繋がらなくなる。
5・でも、ssh moge.no.de が繋がる。git push moge.no.de master もできる。
6・おかしいと思って、hoge.no.de をブラウザで開く。開ける…
7・sshで moge.no.de を開いて、ブラウザで hoge.no.de を開いたら、
hoge.no.de のログが ssh moge.no.de に表示される。。。
8・moge.no.de の server.js の内容を更新 (git commit して push moge.no.de) して、
ブラウザでhoge.no.de を開くと、
hoge.no.de が更新されている。あっれー?あっれー?あっれー?
  moge.no.de は、ブラウザで開けない。
9・一応、ssh hoge.no.de してみたけど、これは繋がらない。ちゃんと削除されている…

ちなみに、
ping hoge.no.de したときのIPアドレスと、
ping moge.no.de したときのIPアドレスは違う。

えへっ。えへえへっ。どーすりゃいいのだろうかー。
昨日までは、moge.no.de は繋がってた。
う~ん。ミステリー。 あんまりよくわかってないんだけど、こういうものなの?
SSHの設定とか調べてみたけど、ちゃんとしてある、というか、
hoge.no.de に ssh で繋がらないので、そこは普通なのだ。

hoge.no.de を ブラウザで開いて、 moge.no.de の内容が表示されつつ、
moge.no.de がブラウザで開けないのに、 hoge.no.de の内容が更新される という、
きっと、サブドメインのところがぐちゃぐちゃになってるんだろうなーみたいな?そんな感じ?俺はしてる?てーきーなー?

2012年2月3日金曜日

Titanium と no.de(Joyent) のSocket.io で WebSocket

というわけで、WebView ではなんか xhr-polling になるので、
Titanium自体で WebSocket しちゃう実装である、

ti-websocket-client.js を使ってみたんですが、

なんか、WebSocket で繋げない。

ti-websocket-client.js を使って、Socket.io を Titanium で使えるようにした、

Socket.io-titanium を使ってみるも、xhr-polling すらできない。
handshake はするけど、そこから先がタイムアウトして無限ループする。

サーバ側で、
    io.set("transports",["xhr-polling"]);
    io.set("polling duration",10);
みたいに、heroku と同じように xhr-polling を設定してみたけど、今度は Android エミュレータが強制終了した。

なんで WebSocket じゃなくて、xhr-polling になるんだろ。なんか、サーバが悪い気がしてきた。

で、そういや Windows でも node.js サーバ動かせるんだったーということで、
今 no.de で動かしているのをまんま Windows の node.js で動かして、
ローカルにある html ファイル と WebSocket でやりとりさせたら、
昨日はxhr-polling になった Chrome で 、 ちゃんと WebSocket で動きやがったよコンチクショー。
サーバが悪いのかー。かー。
Windows の node.js サーバ、 0.6.7 だからかな?関係ないか。
no.de のサーバマシン を別なのにしてみたけど、変わりなく。

ていうか、no.de のサーバマシンを新しいのにしたら、
npm で WARN invalid config node-version "v0.6" とか出てるし…

config.json

というファイルを作って、その中に、

{"version":"v0.6.8"}

とだけ書いて保存して push すればよいです。

あ、一応、no.de で No Space Commits とか言われたら、
server.js とか package.json とかの文字コードが UTF-8N CRLF の文字コードじゃないからだと思います。

んー。ローカルにある file://~/test.html が http://localhost:3000/ を開くから良いのであって、
file://~/test.html が http://hoge.no.de:80 を開くから、 xhr-polling になるのかなー。
Safariだと、ちゃんと no.de と WebSocket できるもんなー。

なんか、だんだんわけがわからなくなってきた。
とりあえず、xhr-polling だろうがなんだろうが、やりとりできりゃいいから、
Titanium 自体にWebSocketさせるのをやめて、WebView に WebSocket つか、xhr-polling させよ。

Titanium (WebView) と no.de(Joyent)のSocket.io で WebSocket

をやってみた。取り合えず、エミュレータ(Android 2.2)で動かしてみている。
取り合えず、WebView で WebSocket できるかなーということで、
WebView のHTMLに Socket.io で通信するようなコードを書いてみたけど、
残念ながら、xhr-polling でやりとりするみたい。
接続が切れてしまうことがあるみたいなので、こりゃーだめだなー。
エミュレータ上で動くAndroidのバージョンを上げればいいのかも知れないけど、
前にバージョンをあげたらおかしなことになったので(笑)、やめておくことにします。
てか、動かして判ったけど、
WebViewのhtmlにDOMのデータを書き込む(つか、画像とかも読み込む)のにスゲーパワーを使うらしく、落ちる。
一気にデータを読み込むからねぇ。

前に書いたWebSocketプロトコルを Titanium にしゃべらせるやつでやってみます。

http://blog.masuidrive.jp/index.php/2011/12/04/socket-with-titanium/

これね。
つか、これを機会にコードを全部書き直そう。そうしようそうしよう。

2012年2月2日木曜日

no.de(joyent) で Socket.io 使って WebSocket出来ない。

が、出来ない!
出来ないわけではない。というか、勝手に xhr-polling になる。
すなわち、WebSocket サーバが立ち上がらないのである。グヌヌヌヌ。

http://d.hatena.ne.jp/sugyan/20111026/1319561275

有名なすぎゃーんさんのはてダでも書いてった。
んぐおー。
Firefox 3.6.x だと、 xhr-polling でもなんとかなるんだが、
Chrome 16.x だと、途中でセッション切れるんだよなぁ。困った。
Safari と Opera は知らん。古いバージョンしか入ってない。

でも、色々見ていくと、一時はっていうか、WebSocket使えてる人もいるっぽい?


https://twitter.com/#!/sugyan/status/155515435951980545

ブラウザが悪いのかー?んん~。
node-websocket-server でWebSocketでつなぎに行っても、200返ってこねーもんな。
Safariだと良いとか言う話し?なので、やってみる。
というわけで、やってみたら、確かに WebSocket で通信できた。
じゃあ、ブラウザの問題なのだね。じゃあ、放置!

2012年2月1日水曜日

no.de で npm がおかしかった件と、heroku で WebSocket(xhr-polling)

node.js のPaaS(だっけ?)で有名な no.de ってところがあるんですが、
そこで、package.json とかに npm で入れて欲しいやつを

    "dependencies" : {
        "socket.io"       : "0.8.7",
        "xmlhttprequest"  : "1.3.0"
    }

とか書いて(勿論これだけじゃダメだけど)も、
node.js のバージョンが0.4.12じゃnpm が動かねーよバーカってエラーが出るんだけど、
node -v
やると、node.js のバージョンが 0.6.8て出てきて、困ってた。

http://discuss.joyent.com/viewtopic.php?id=31932

ここでFixするやりかたがやっと出てきたので書いておきます。
Windowsだと、cmd.exe を開いて


ssh admin@your-machine.no.de
ってやってrootで入って 
 
sudo bash
vi /opt/nodejs/service-starter

service-starter をvi で開いて、
 
20行目の
NODE=/opt/nodejs/v0.4/bin/node
NODE=/home/node/local/nodejs/bin/node
に書き直して保存して、 
 
一回 ssh からログアウトして、
 
ssh your-machine.no.de
今度は普通のユーザでログインして 
node-service-deploy

ってやればいいみたいです。
 
あ、ssh の公開鍵とかあれこれやってからね。
 
このエラーのおかげで、昨日は色々困ってた。
困ったついでに、heroku でSocket.io でWebSocketもどきを動かすやり方を覚えた。
WebSocketもどきと書いたのは、
heroku ではまだWebSocketが使えない(今後使えるようになるかも知らん)ので、
xhr-polling でやるしかない。

サーバ側のJS
var io = require('socket.io').listen(3000);
 io.set("transports",["xhr-polling"]); //※ここ
 io.set("polling duration",10); //※ここ
 io.sockets.on('connection', function (socket) {
  socket.on('message', function (data){
   try{
    data = JSON.parse(data);
    socket.send("オウム返し" + data.messagebody);
   }catch(e){console.log(e);}
  });
 });

クライアント側のJS
<script type='text/javascript' src='socket.io.js'></script>
<script type='text/javascript'> 
var socket = io.connect("http://hoge.herokuapp.com:3000/");
socket.on('message',function(data){ // なんかメッセージ貰ったとき
 try{
  var json = eval("(" + data + ")");
  if(!json || json == null || typeof(json) == "undfined"){
   return;
  }
  socket.send(json.messagebody);
 }catch(e){
 }
});
socket.on('connect', function () {
 data = {messagebody : "ちんちんもげろ"};
 data = JSON.stringify(data); //接続できたとき
 socket.send(data);
});
</script>
こんなんでいいみたいです。

クライアントが使う socket.io.js がどこにあるのかわからなかったから、socket.io 使わなかったけど、
 
https://github.com/LearnBoost/socket.io-client
 
ここにあるやつダウンロードして、
dist ていうディレクトリの中に
socket.io.js か、 socket.io.min.js のどっちかをコピーして使えばいいみたいですよ。
勉強になりましたねー。うほうほ。

xhr-polling 使ってみたけど、
とりあえずコンソールがエライことになるというか、
接続しては切断してまた接続しては切断するので、
やっぱ WebSocket 普通に使えたほうがいいなーという感じです。
あわただしそうで、大変そうだもの。サーバが。