Sync all

Webエンジニアの気になる事。困った事もろもろ。

Javascriptでの0埋め

備忘の為に。

    var sequence = 0000;
    sequence= (sequence + this._sequence).slice(-4);


0足してを足してそれから必要分だけ取り出す処理。


JavaScript 第6版

JavaScript 第6版

【MongoDB】2d sphere Indexの注意点

非常に困ったのでメモ。

2d sphere Index

2d Indexは以前からあったのですが適切な球面座標を使えてはいませんでした。
メルカトル図法を思い浮かべるといいかもしれません。

f:id:bulbulpaul:20140131215927g:plain

でもこれでは極点に近い点での正確性が損なわれます。

MongoDB 2.4から追加された2d sphere Indexは地理空間インデックスでGeoJSONフォーマットが使えるようになりました。
これにより当然地球は球状なので適切な球面座標を使って検索する事が出来ます。

f:id:bulbulpaul:20140131220318p:plain

このインデックスを設定する事により、$geoWithin, $geoIntersects のクエリが使用できます。

Polygonなら指定の範囲(outer) 内に更に指定の除外範囲(inner)を作れますし非常に便利な機能です。

f:id:bulbulpaul:20140131220114p:plain

$geoWithin, $geoIntersects

今回ハマった点は広範囲の地理空間を指定する際に困った事が起こりました。

db.hoge.find( { field :
                         { $geoWithin :
                            { $geometry :
                               { type : "Polygon" ,
                                 coordinates : [ [ [ 120.0, 40.0 ] , [120.0, 70.0] , [160.0, 70.0], [160.0, 40.0], [120.0, 40.0] ] ]
                      } } } } )

これは通常の$geoWithinの使い方ですので指定条件内のデータが問題なく通ります。

しかし、以下のクエリは問題があります。

db.hoge.find( { field :
                         { $geoWithin :
                            { $geometry :
                               { type : "Polygon" ,
                                 coordinates : [ [ [-120.0, -40.0 ] , [-120.0, 70.0] , [160.0, 70.0], [160.0, -40.0], [-120.0, -40.0] ] ]
                      } } } } )

実行結果は何も帰ってきません。対象データがないと帰ってきます。

理由は、2d sphere Indexの仕様が半球を越える地理空間のクエリは指定出来ない仕様になっています。

これは恐らく二次元球面の考え方に基づいています。

球(sphere)は2つの半球からなり、半球は円盤と同じになります。

f:id:bulbulpaul:20140201004806p:plain

つまり2つの円から形成される仕組みになります。

一つの円(例:北半球)の円の外の位置はもう一つの円(例:南半球)の位置に存在します。

ですので、別の領域内のデータを検索する事が出来ない為では無いかと思います。

ただし、$geoWithin ,$geoIntersectsの半球の制限はどの方向(角度)でも半球の範囲(long:180, lati: 90)以内なら問題無いようです。

そしてもう一点問題が発生しました。

$orが使えない

地球全体(球)の広い範囲では一度にとれない事がわかったので$orで半球と残りの半球で条件を設定すれば問題無いのでは?
と思い実行した所エラーが帰ってきました。

ドキュメントを確認すると$geoWithin ,$geoIntersectsでは$orが使用できない仕様となっています。

結果:一度に半球を越える広範囲の検索は不可能

2d sphere Indexを設定した所には一度に広範囲の検索は不可能と行った結果になりました。

通常の検索、MapReduceのクエリでは2回別々に投げる事になります。

ただ、ソートやLimitの設定が入ってくるとプログラム上で一捻り必要になりそうです。

MongoDBイン・アクション

MongoDBイン・アクション

SublimeText3でbuildファイルが見つからない

SublimeText3を使ってPython環境の構築をしていて少しハマったのでメモ。
(主にWindows環境)

Pythonをbuildで実行した際に日本語出力があるとエラー発生

これはWindowsのコンソールの文字コードUTF-8ではないので発生との事。

こちらの記事を参考にさせて頂きました。
Windows 環境の Python27 を SublimeText2 で書く前にやる事 - けいれん現象の幽玄美よ

「Preferences → Browse Packages...」を選択。
Python」フォルダ内の「Python.sublime-build」を以下のように修正。

{
	"cmd": ["python", "-u", "$file"],
	"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
	"selector": "source.python",

	"windows":
	{
		"encoding": "cp932",   // Windowsコンソールの文字コード
		"path": "C:/Python33" // 自分のPythonへのパス
	}
}

通常はここ迄でOK.

ただ、今回は不思議な状況に・・・。

Pythonフォルダが無い

「Preferences → Browse Packages...」を選択して表示されるフォルダ内に「Python」フォルダが存在しない。なので当然Python.sublime-buildもない。

というか各言語のフォルダが一つもない。何故?

ファイル検索しても無いのでProgramFiles見てみる。

いろいろ探して見るとProgramFiles\SublimeText3\Packages\Python.sublime-packageというファイルを発見。

圧縮ファイルの様なので解凍してみたところ



あるやん。思いっきりあるやん。

なんでこんな所に?

C:\Users\YourNameHere\AppData\Roaming\Sublime Text 3\Packages内にPythonフォルダを作成して解凍したファイル達を配置。

直りましたね。何これ。

単に言語のフォルダ作ってbuildファイル作れば動くのかな?

通常はあるはずなのになんでだろうか。

SublimeText2はそんな事無いんだけども。

ウェアラブル端末にみる可能性

最近いろいろとウェアラブルデバイスが発表させて来ていますのであっちこっちに興味がいって大変です。

なので、今回簡単にまとめて見てみようと思います。

ウェアラブルデバイスって?

そもそもウェアラブルってなんなの?って方もまだまだ多くいらっしゃいますので解説。

ウェアラブルコンピュータ(wearable computer)とは、身につけて持ち歩くことが出来るコンピュータのこと。


文言のと通り身につけて使うコンピュータの事です。

眼鏡だったり、時計たっだり、腕輪や指輪と種類は様々です。

私の主観が入りますが気になっている所を書いて行きます。

Google Glass

f:id:bulbulpaul:20131012000945j:plain

検索サイトやAndroidで有名なGoogle社が開発している眼鏡型端末です。

使い方としては、自身の視界の端に半透明なサブディスプレイの様に画面が映し出されます。

動かす為には音声認識(※現時点では英語のみ)とGoogleGlass横側のタッチパッドの2種類あります。

Googleは日本語の音声認識技術も保有している企業なので今後は対応して行く可能性はあるかと思います。

出来る事としては

画像や動画の撮影、通話、メール、検索、ブラウザ、ナビ等々・・・少し前のスマホレベルの機能は出来ます。

個人的にマイナスな点としては

眼鏡を既にかけている人は使えない。(眼鏡型の意味ない気がする・・・。)

サブディスプレイ的な使い方なので実際の見ている状態に何か表示を重ねたりは出来ない。

また、現時点では端末にアプリのインストールが原則できない。(今後は変更されるかもしれない。)

どちらにしろ、天下のGoogle謹製ですので広がる可能性としては一番有望かもしれません。

現在は開発者用のモデル($1500)しか無いのですが、一般用にも発売予定。
価格は未定だが$1500より安くなる見通しです。


How it Feels [through Google Glass] - YouTube


GoogleGlass
http://www.google.com/glass/start/

Telepahy One

f:id:bulbulpaul:20131012001339j:plain

セカイ・カメラで一世を風靡した、井口尊仁さんが開発しているGoogleGlass同様のタイプの端末。

機能としてはGoogleGlassと同等ですが異なる点が数点あります。

  • 操作がジェスチャーがメイン。
  • 斜め上の画面を確認する感じのGoogle Glassと異なり、映像が風景に溶け込む。(5インチ程度のディスプレイ)

また、こちらは眼鏡をしている方でも装着する事が出来ます。

個人的にはGoogleGlassよりもスタイリッシュでファッション的にもGlassよりも受け入れやすいのではとも思う。

ただ、コンセプトだけが先行して実際の操作イメージがハッキリイメージできない所は使用シーンを想像しにくくしているのかと思います。

早く開発者用の製品が出ればいいですね。

こちらも正式な発売は未定ですが、価格はGoogleGlassよりも安くなる見通しとの事です。


Telepathy One image - YouTube


Telepahy One
http://tele-pathy.org/

GALAXY Gear

f:id:bulbulpaul:20131012004511j:plain

サムスン電子が開発した時計型端末です。

サムスンスマートフォンやタブレットと同期し、電話、メール、SNS、LINEほかアプリの確認や返信ができる腕時計型端末です。

前述の2つに比べると見劣り感はありますが、いちいちスマホやタブレットを開かずに操作できるのは以外に便利です。

これで健康管理的な事まで出来ればいいですけどそのような機能はありません。

カメラもありますが、使用し難い感が満載です。

現時点で発売が一番近い製品でもあります。


Samsung Galaxy Gear: A Long Time Coming - YouTube


GALAXY Gear 
http://www.samsung.com/jp/consumer/mobilephone/galaxy-gear/galaxy-gear/SM-V7000ZKAKDI

MYO

f:id:bulbulpaul:20131012005921j:plain

こちらは少し趣向の違った腕輪型端末です。

筋肉の動きを読み取ってそれを入力機器としてスマホ、パソコン、ゲーム、家電や電子機器を操作できる事が出来る端末です。

ムービーではパソコンやテレビゲーム、ラジコン等々非常に幅の広く転用できる事がわかります。

様々な機器で使う事ができる点や筋肉の信号を取得するので場所を構わず動的に使用できる点は非常に素晴らしい点かと思います。

個人的には障がい支援機器としても非常に優秀な機器かと思っています。

現在予約(価格は$149)を受け付けており、出荷が2014年の初頭の予定です。


MYO - Wearable Gesture Control from Thalmic ...

MYO
https://www.thalmic.com/en/myo/

Ring

f:id:bulbulpaul:20131012010922j:plain

こちらは最近発表された指輪型端末。

まだまだ未確定な要素を含んでいる端末ですが非常に未来的かつスタイリッシュなデバイスかと思います。

装着している指や手のジェスチャーで操作をします。

TVと書いてテレビをオンにしたり、請求書の上で「$12」と書いて支払いを済ませたり、Ringを装着した人と握手してお互いの情報をやりとりするといった事が公開された映像に映されています。

MYOと同じく接続する端末は必要になりますが新しい入力端末としても面白い一品かと思います。

こちらもTelepahy Oneと同様に日本からの製品なので頑張ってほしい所です。

発売時期や価格は未定。


视频: Ring -Shorcut Everything- - YouTube

Ring
http://logbar.jp/ring/

ウェアラブルの可能性


本当に様々な端末も多く生まれています。

ここに書けていない端末も多くあります。

今迄の様に複雑な操作方法ではなくシンプルでより直感的に生活になじむ端末が求められるのかもしれません。

昔の漫画で描いていた未来が少しづつですが現実になって来ています。

不可能を可能に変え、新たな体験や感動、世界観を作るのがITの役割だと私は思っています。

一般的な普及はもちろんですが、ウェアラブルデバイスを身につける事によって今迄つながっていなかった人と何ががつながるような気がしてなりません。

私もITによる障がい支援を進めていますが、こういった機器で新たな体験を生み出せるように開発を頑張りたいと思います。

SQLiteで微妙に出来ない事

SQLiteでしょうもなく詰まった事のメモ書き。

insert into hoge 
(hoge_id, hoge_name, hoge_detail)
values
(1,"田中","アフロ"),
(2,"佐藤","パンチ");

何とこのvalusの複数指定が出来ない!

サーバー型のDBに慣れすぎていたよ・・・。

insert into hoge 
(hoge_id, hoge_name, hoge_detail)
values
(1,"田中","アフロ");

insert into hoge 
(hoge_id, hoge_name, hoge_detail)
values
(2,"佐藤","パンチ");

の様なSQL文を流さないといけない。

なので複数データ作成時はコード側で整形が必要ですね。

ポップアップウィンドウ展開時にPOST通信でデータを送信する

JavaScriptで新たにポップアップウィンドウを作成し、通常はGET通信で新たにページを取得するのですが、展開時に多くのデータを送信出来ないデメリットがあります。

なので展開時にPOST通信で処理してみました。

ポップアップウィンドウのPOST通信

1.まずabout:blunkで開く

まずはポップアップウィンドウを空で開きます。

//空のポップアップウィンドウの作成。
exportWin = windowPostOpen("", "popup", false, true, false);

//ウィンドウ作成
function windowPostOpen(url, title, toolbar, scrollbar, fullscreen){
    var option = "location=no, directories=no, status=yes";
    if (scrollbar == true) {
        option = option + ", scrollbars=yes";
    } else {
        option = option + ", scrollbars=no";
    }
    var width = screen.availWidth;
    var height = screen.availHeight;
    if (width > 1024) width = 1024;
    if (height > 768) height = 768;
    var left = (screen.availWidth - width) / 2;
    var top = (screen.availHeight - height) / 2;
    if (toolbar == true) {
        option = option + ", toolbar=yes, menubar=yes, resizable=yes";
        option = option + ", width=" + (width-8) + ", height=" + (height-58-78) + ", left=" + left + ", top=" + top;
    } else {
        option = option + ", toolbar=no, menubar=no, resizable=yes";
        option = option + ", width=" + (width-8) + ", height=" + (height-58) + ", left=" + left + ", top=" + top;
    }

    return window.open(url, title, option);
}

2.formを作成作成

//form作成
var form = document.createElement("form");
//target属性は、どこにアクションURLを開くかを指定します。
form.target = "popup";
//POST通信設定。
form.method = 'post';
//遷移先のaction設定。
form.action = '/action.php';

3.input要素を作成し送信データを設定

POSTで通信するためにtype="hidden"にデータ設定。

//input type='hidden' を作成し、送信データを設定。
var submitType = document.createElement("input");
submitType.setAttribute("name", "hoge");
submitType.setAttribute("type", "hidden");
submitType.setAttribute("value", "送信データ");

//form に作成したinput要素を追加。
form.appendChild(submitType);
var body = document.getElementsByTagName("body")[0];

4.フォームの送信

一旦DOMに追加しないと送信出来ないので送信時のみ追加し送信後に削除。

var body = document.getElementsByTagName("body")[0];

//一旦domに書き出して
body.appendChild(form);
//送信!
form.submit();
//送信後に作成したform要素の削除
body.removeChild(form);

▼▼▼▼▼▼▼▼▼▼以下全ソース▼▼▼▼▼▼▼▼▼▼

//空のポップアップウィンドウの作成。
exportWin = windowPostOpen("", "popup", false, true, false);

//form作成
var form = document.createElement("form");
//target属性は、どこにアクションURLを開くかを指定します。
form.target = "popup";
//POST通信設定。
form.method = 'post';
//遷移先のaction設定。
form.action = '/action.php';

//input type='hidden' を作成し、送信データを設定。
var submitType = document.createElement("input");
submitType.setAttribute("name", "hoge");
submitType.setAttribute("type", "hidden");
submitType.setAttribute("value", ”送信データ”);

//form に作成したinput要素を追加。
form.appendChild(submitType);
var body = document.getElementsByTagName("body")[0];

//一旦domに書き出して
body.appendChild(form);
//送信!
form.submit();
//送信後に作成したform要素の削除
body.removeChild(form);

//ウィンドウ作成
function windowPostOpen(url, title, toolbar, scrollbar, fullscreen){
    var option = "location=no, directories=no, status=yes";
    if (scrollbar == true) {
        option = option + ", scrollbars=yes";
    } else {
        option = option + ", scrollbars=no";
    }
    var width = screen.availWidth;
    var height = screen.availHeight;
    if (width > 1024) width = 1024;
    if (height > 768) height = 768;
    var left = (screen.availWidth - width) / 2;
    var top = (screen.availHeight - height) / 2;
    if (toolbar == true) {
        option = option + ", toolbar=yes, menubar=yes, resizable=yes";
        option = option + ", width=" + (width-8) + ", height=" + (height-58-78) + ", left=" + left + ", top=" + top;
    } else {
        option = option + ", toolbar=no, menubar=no, resizable=yes";
        option = option + ", width=" + (width-8) + ", height=" + (height-58) + ", left=" + left + ", top=" + top;
    }

    return window.open(url, title, option);
}

jQuery1.9での動的に生成した要素に対するイベント指定

jQuery1.9で早速ハマったことをメモっておきます。

動的生成要素に対するイベント指定

仕事でMVCフレームワークを使ってサーバーをJSON吐き出し機にして

動的にコンテンツを表示したりするときがあります。

ですが動的に追加された要素に対してイベントを追加しようとしてもできません。

以前までなら .live()関数で指定可能だったのですが・・・。

.live()関数の廃止

jQuery1.9では.live()関数が廃止されました。

1.7から追加された .on() 関数を使用するように変更されました。

と入っても前から推奨は .on()関数なのですが。

個人的に可読性が下がるかなと思って .live()派でした。

そもそも.live()は将来的に追加されつ要素(動的に追加される)に対しても指定ができる関数でした。

以前はこんな感じに

$('#hoge').live('click',function(){
alert("動的に追加したコンテンツ。");
});

それを .on()関数に書き換えると

$(document).on('click','#hoge',function(){
  alert("動的に追加したコンテンツ。");
});

このようにdocument要素に対して「.on()」を実行し、引数にセレクタを渡します。

慣れたらわかるんですけど最初は読みにくいんよね。

すると動的に生成された要素に対してもイベントをつけることができます。