2013年12月29日日曜日

Micro Piano

昨日は僕の誕生日でした。Facebookでいろいろな方にお誕生日おめでとうと言われました。
ありがとうございます。ついでなので、僕のほしいものを書いておきます。

ぼく、来年くらいにミニ楽器が流行ると個人的に勝手に思ってます。
ここ数年、高機能なデジタル機器が数千円で買える時代。デジタル楽器も数千円でかなり高機能なものが買えます。

そこで、僕、家におけるグランドピアノほしいのです。
これ、KORGのMicroPiano。アマゾンだと17800円。

http://www.amazon.co.jp/KORG-%E3%83%8A%E3%83%81%E3%83%A5%E3%83%A9%E3%83%AB%E3%83%BB%E3%82%BF%E3%83%83%E3%83%81%E3%83%BB%E3%83%9F%E3%83%8B%E9%8D%B5%E7%9B%A4%E6%90%AD%E8%BC%89-%E3%82%B3%E3%83%B3%E3%83%91%E3%82%AF%E3%83%88%E3%83%BB%E3%83%94%E3%82%A2%E3%83%8E-MICROPIANO-%E3%83%9E%E3%82%A4%E3%82%AF%E3%83%AD%E3%83%BB%E3%83%94%E3%82%A2%E3%83%8E/dp/B0043U631S

おもちゃのピアノのレベルをはるかに超えていて、かなりすごいレベルの演奏ができるようです。
実際の演奏の様子はこちら。
http://www.youtube.com/watch?v=tuZ2LOqV3DI

これが17800円なんて、安すぎ。どうやって作ってるのでしょう。

2013年9月27日金曜日

amazonベーシック

仕事上いろいとな場所でパソコンを使うので、その先でよくUSBハブとかマウスとかHDMIケーブルとかがなくて困ります。
ケーブルのストックを持ってたり電気屋さんに行って買ってもよいんだけど、USBハブとかマウスとかHDMIケーブルとかって2000円くらいする上、何個かストックを持とうとするとすぐに一万円くらいいってしまうのでので、なかなか買う気がしません。

というか、大型量販店って在庫リスクがかさんで利益が出ないからなのか、2000円以下のものを明らかに安く売る気がないのです。

みんなどうしているのか調べたところ、amazonで買えばよいとのこと。とくにケーブル類はamazonベーシックっていうものがあって安いらしい。

USBハブ だいたい500円
HDMIケーブル だいたい600円
無線マウス だいたい800円
HDMI-DVIアダプター だいたい300円

ヨドバシカメラやヤマダ電気で売っている価格の1/3くらいで買えて、しかも送料込み。
大部分が送料を占めている気がしますが、どうやってこの価格でうれるのか不思議でたまりません。
電車とかで秋葉原に買いに行くよりはるかに時間と手間と価格がお得な気がします。

韓国製だけれどプライベートブランドの第三のビールも88円でスーパーで売られているし。
恐るべし価格破壊。

百円のものって、原料を買って工場で作って、海外から輸送して、配送センターから自宅まで届けてるのを一万個全部1人でやったとしても、売上百万円しかないし。
24時間無人で作らない限りこんなに安くできない気がします。どうやって作るとこんなに安くできるのかなぞが深まるばかりです。





2013年9月20日金曜日

37才にして字が書けるようになりました。



うちの二歳八か月の子供が最近お勉強ごっこあそびというものをしていて、僕はそれをまいにちひたすら見させられる。
パパは見てるだけといわれ、見てないとみててといわれ、なにか手を出したり見本を見せてもダメと言われる。

文字の形は全然合っていないんだけれど、どうやらABCを書いているらしい。
うまくかけなくて、ママに書いてもらってそれをよーくみて自分のと比べているよう。

不思議なことに毎日ママの文字を書く姿を見てるだけで、

文字は左から右または上から下に書くこと、
文字と文字の隙間を空けること、
文字は全部同じくらいの大きさに書くこと、
文字に対応する音があること。
字は読める、
字は書ける、
文字がいくつか集まって何かのものを表すこと、
文字がたくさん集まるとなにか意味のあることがかいてあること、
文字は相手に何かを伝えるときに書くもの
自分はママと違ってうまくかけない。
ママは字が書ける。
字を覚えて書くことを勉強というらしい

などいろいろなことを子供は分析して覚えているらしい。
文字を書くアルゴリズムを見るという行為をして導き出しているのである。


これらから分析するに、僕は子供の前で字を書いたことがないので、子供にいろいろ聞いてみた。


Q 保育園の先生は字が書けると思う人

先生は字がかける。


Q パパは字が読めると思う人

パパは字がよめる。

Q パパは字が書けると思う人

パパは字がかけない。


なんかわかったぞ!
どうやらうちの子供はパパが字を書けないと思っていて、私がママに教わった文字を書いてパパに字を教えあげているのである。
そう、勉強をしているのは子供ではなくてパパなのです。

真似をすることとごっこ遊びをすることが、真似をすることを真似することになる。
この単なる欲求行動の組み合わせの中に自然と再帰性がうまれることが人類が文字や文化を獲得し伝承できた仕組みなんだと1人で感動。

そういえば保育園ごっこもいつも僕が赤ちゃん役だし、おうたも僕が歌うとダメといわれるんだよね。
明日朝、子供に言おうと思う、パパに字を教えてくれたらパパ字が書けるようになったよって。



2013年9月11日水曜日

AndroidのActivityはどのように書くのがよいのか

AndroidのアプリケーションをJavaで書くと、いろいろなコールバックのメソッドがいろいろなクラスに散らばってしまいます。
このため、いろいろなクラスがActivityのコンテキストを持ってしまい、メモリ使用量が増えるという欠点があります。
特に、Activityは専用のクラスを作らないといけなかったりひとつのクラスで二つのActivityを管理できないとかいろいろ不便。
そこで他の人はどうしているのかを調べてみました。

GoogleのChromeブラウザのソースをみると、いろいろなイベントはインナークラスで受けて、アウタークラスに処理を委譲しています。
Activitをインナークラスで作ってデリゲートのように使えば、一つのクラスで複数のActivityを管理できるますし、他のイベントも同じような仕組みでいろいろ受けられます。
インナークラスに処理を書くのか、アウタークラスに処理を書くのかは好みの問題ですが、コンテキストもいろいろなクラスに渡さなくてすむので、全体としてきれいにかけそうな気がします。







------------------------------
SomeMain.java
------------------------------
package com.yomei;

import java.io.*;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;

public class SomeMain {

static Handler handler = new Handler();
static Activity activity = null;

public static void onCreate()
{
}

public static void onDestroy()
{
}

//Activityのイベントを受け取るデリゲート
public static class MainActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState){
    activity=this;    super.onCreate(savedInstanceState);
    SomeMain.onCreate();//Outerクラスに委譲
}
@Override
protected void onDestroy() {
    SomeMain.onDestroy();//Outerクラスに委譲
    activity=null;
}

}


------------------------------
AndroidManifest.xml
------------------------------

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.yomei"
      android:versionCode="1"
      android:versionName="1.0">
    <application >
        <activity android:name="com.yomeiSomeMain$MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

2013年9月8日日曜日

Emscriptenを動かしてみた。

GoogleのJavascriptエンジンV8のコードを読んでいると、実行速度の高速化へのしたたかかつはてしない追及、コードの美しさに感動します。

オリンピックの開催候補地が決まるまで起きているつもりなので、最近、いろいろな面白いJavascriptの高速化技術があるので一通り動かしてみました。


Emscripten

C/C++などの言語で書かれたコードをマシン語にして、それをJSでエミュレーションするんですが、最適化をコンパイラーとクロージャーライブラリで行うのが面白いですね。あとコンソールアプリやOpenGLのプログラムを簡単にJSにできるので、昔のゲームとかをWebに移植できそうな気がする。

asm.js

これも計算しか早くならないけど、Javascriptでシュミレーションとか音声合成とかできそうな気がする。



2013年9月7日土曜日

囲碁のルールを勉強してみた

今日、教育テレビの「こども囲碁名人」という番組で小学生が囲碁をしていました。

囲碁のルールは囲んだら取れるしか知らなかったのですが、小学生でも囲碁のルールがわかるのだから僕もわかるはずと思い、長年わからなかった囲んだら取れる以外の囲碁のルールを夕方からずっと勉強してます。

囲碁のルールはもう一つ囲んでいる中には入れられないしかないらしい。
このため、目の形を作ると相手は目の中を取れないこともわかった。


長年の疑問であった、なんであんなとびとびに石を置くのかとか、相手の石のすぐ横に石を置くのか意味はわかってきた。

生き死にを現在勉強中

囲碁のルールは極めて簡単ななんだけど、宇宙を支配する物理法則のようなすごい多様性があっることがわかった。理系のコンピュータ好きの人はみんなきっとはまる。




2013年9月6日金曜日

C++でvar型変数を作ってみた。 その2

以前作ったC++のvar型変数ですが、よくがんがえたら配列の長さとかクリアとか列挙ができず、操作性が悪いことに気づきました。そこで配列の操作関数を追加してみました。

これで、ひとつの変数で、int,文字列、配列、多次元配列、連想配列、ができます。
これに伴い、配列と連想配列の明確な区別をしました。
配列は要素識別子に0から始まり最大要素数-1をとる連続したデータ列。
連想配列は任意の文字列や数値をとる配列
==や!=でnullと0と""と空配列を同じに扱うかどうか悩みます。
var変数の値の設定取得、サイズ取得、同値判定、初期化、破棄、要素選択など基本動作はすべてできます。
あとは+や-など、演算子をオーバーロードすれば完成。

だんだん複雑になってきたのでテストコードを追加しました。


------------------------------
varient.cpp
------------------------------
#include <stdio.h>
#include "variant.h"

#if defined(_WIN32) && !defined(__GNUC__)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif


static var var_null;

var::var()
{
clear();
type=0;
m_val=0;
}

var::var(int v)
{
clear();
type=VAR_TYPE_INT;
m_val=v;
}

var::var(const char*str)
{
var((std::string)str);
}

var::var(std::string str)
{
clear();
type=VAR_TYPE_STRING;
m_str=str;
}


var::var(var& val)
{
(*this)=val;
}


var::~var()
{
clear();
}

void var::clear()
{
var* ret;
std::map<std::string,var*>::iterator ite;

ite=m_map.begin();
while( ite != m_map.end() )
{
ret=(*ite).second;
delete ret;
ite++;
}
type=0;
m_val=0;
m_str.clear();
m_map.clear();

//m_min_array=0;
m_max_array=0;
m_is_array=false;
}

var& var::operator[](const char* str)
{
if(str==NULL){
return var_null;
}
return operator[]((std::string)str);
}

var& var::operator[](std::string str)
{
var* ret=&var_null;

if(type!=0 && type!=VAR_TYPE_MAP){
return *ret;
}

switch(type){
case 0:
type=VAR_TYPE_MAP;
m_is_array=false;
case VAR_TYPE_MAP:
m_is_array=false;
ret=m_map[str];
if(ret==NULL){
ret=new var();
m_map[str]=ret;
}
break;
}
return *ret;
}

var& var::operator[](int v)
{
var* ret=&var_null;
char tmp[64];

tmp[0]=0;
sprintf(tmp,"%d",v);
std::string str=tmp;

if(type!=0 && type!=VAR_TYPE_MAP){
return *ret;
}

switch(type){
case 0:
type=VAR_TYPE_MAP;
m_is_array=true;
case VAR_TYPE_MAP:
ret=m_map[str];
if(ret==NULL){
ret=new var();
m_map[str]=ret;
}
if(m_is_array){
if(v<0)m_is_array=false;
if(m_max_array<v+1)m_max_array=v+1;
}
break;
}
return *ret;
}

void var::tumeru()
{
if(type!=VAR_TYPE_MAP)return;

std::map<std::string,var*>::iterator ite;
std::map<std::string,var*>::iterator old_ite;
bool f_del=false;

type=VAR_TYPE_MAP;
ite=m_map.begin();
while( ite != m_map.end() )
{
var* v;
v=(*ite).second;
if(v->type==0){
f_del=true;
}
old_ite=ite;
ite++;
if(f_del){
m_map.erase(old_ite);
}
f_del=false;
}
}

var& var::at(int n)
{
if(type!=VAR_TYPE_MAP || n<0){
return var_null;
}

tumeru();

std::map<std::string,var*>::iterator ite;
int ct=0;

ite=m_map.begin();
while( ite != m_map.end() )
{
if(ct==n)return *(*ite).second;
ite++;
ct++;
}

return var_null;
}


var& var::operator =(std::string str)
{
clear();

type=VAR_TYPE_STRING;
m_str=str;
return *this;
}

var& var::operator =(int val)
{
clear();

type=VAR_TYPE_INT;
m_val=val;

// 0 is as same as null
//if(val==0){
// type=VAR_TYPE_NULL;
// m_val=0;
//}
return *this;
}


var& var::operator =(var& val)
{
var* ret;
std::map<std::string,var*>::iterator ite;

//clear all
clear();

switch(val.type){
case VAR_TYPE_NULL:
break;
case VAR_TYPE_INT:
type=VAR_TYPE_INT;
m_val=val.m_val;
if(m_val==0){
type=0;
}
break;
case VAR_TYPE_STRING:
type=VAR_TYPE_STRING;
m_str=val.m_str;
break;
case VAR_TYPE_MAP:
std::map<std::string,var*>::iterator ite;
type=VAR_TYPE_MAP;
ite=val.m_map.begin();
while( ite != val.m_map.end() )
{
m_map[(*ite).first]=new var();
*(m_map[(*ite).first])=*(*ite).second;
ite++;
}
break;
}
return *this;
}

var::operator std::string()
{
switch(type){
case 0:
return "null";
case VAR_TYPE_STRING:
return m_str;
case VAR_TYPE_INT:
return toString();
case VAR_TYPE_MAP:
return "objrct";
}
return "broken";
}


var::operator int()
{
switch(type){
case 0:
return 0;
case VAR_TYPE_INT:
return m_val;
case VAR_TYPE_STRING:
return toInt();
}
return -1;
}

const char* var::pchar()
{
switch(type){
case 0:
return "null";
case VAR_TYPE_STRING:
return m_str.c_str();
case VAR_TYPE_INT:
return toString().c_str();
case VAR_TYPE_MAP:
return "objrct";
}
return "broken";
}

int var::toInt()
{
int ret=0;
switch(type){
case 0:
return 0;
case VAR_TYPE_INT:
return m_val;
case VAR_TYPE_STRING:
ret=-1;
sscanf(m_str.c_str(),"%d",&ret);
return ret;
}
return ret;
}

std::string var::toString()
{
std::string ret;
switch(type){
case 0:
return "0";
case VAR_TYPE_INT:
char tmp[64];
tmp[0]=0;
sprintf(tmp,"%d",m_val);
ret=tmp;
return ret;
case VAR_TYPE_STRING:
return m_str;
}
return ret;
}


bool var::operator ==(int v)
{
switch(type){
case 0:
if(v==0)return true;
return false;
}
return false;
}

bool var::operator !=(int v)
{
switch(type){
case 0:
if(v==0)return false;
return true;
}
return true;
}

bool var::operator ==(var& val)
{
switch(type){
case 0:
if(val.type==0)return true;
if(val.type==VAR_TYPE_INT && val.m_val==0)return true;
return false;
case VAR_TYPE_INT:
if(val.type==VAR_TYPE_INT && m_val==val.m_val)return true;
return false;
case VAR_TYPE_STRING:
if(val.type==VAR_TYPE_STRING && m_str==val.m_str)return true;
return false;
case VAR_TYPE_MAP:
//no implement
return false;
}
return false;
}

bool var::operator !=(var& val)
{
switch(type){
case 0:
if(val.type==0)return false;
if(val.type==VAR_TYPE_INT && val.m_val==0)return false;
return true;
case VAR_TYPE_INT:
if(val.type==VAR_TYPE_INT && m_val==val.m_val)return false;
return true;
case VAR_TYPE_STRING:
if(val.type==VAR_TYPE_STRING && m_str==val.m_str)return false;
return true;
case VAR_TYPE_MAP:
//no implement
return true;
}
return true;
}

int var::length()
{
int ret=0;
switch(type){
case 0:
return 0;
case VAR_TYPE_STRING:
return m_str.length();
case VAR_TYPE_INT:
if(m_val>=0)return m_val;
return -m_val;
case VAR_TYPE_MAP:
if(m_is_array){
return m_max_array;
}
tumeru();
ret=m_map.size();
return ret;
}
return ret;
}



------------------------------
varient.h
------------------------------

#include <string>
#include <map>

#define VAR_TYPE_NULL 0
#define VAR_TYPE_INT 1
#define VAR_TYPE_STRING 2
#define VAR_TYPE_MAP 3
#define VAR_TYPE_LIST 4


class var{
public:
var();
var(int v);
var(const char* str);
var(std::string str);
var(var& val);

void clear();

virtual ~var();

var& operator[](std::string str);
var& operator[](const char* str);
var& operator[](int);
var& at(int);

var& operator =(std::string str);
var& operator =(int val);
var& operator =(var& val);

bool operator ==(int);
bool operator !=(int);

bool operator ==(var& val);
bool operator !=(var& val);


// you should implement
//var& operator +=(std::string str);
//var& operator +=(const char* str);
//var& operator +=(int val);
//var& operator +=(var& val);

// you should implement
//var operator +(std::string str);
//var operator +(const char* str);
//var operator +(int val);
//var operator +(var& val);


operator std::string();
operator int();

int toInt();
std::string toString();

int length();
const char* pchar();
private:
void tumeru();

private:

int type;

std::map<std::string,var*> m_map;
std::string m_str;
int m_val;

int m_max_array;
bool m_is_array;
};



------------------------------
varient.cpp
------------------------------

#include <stdio.h>
#include "variant.h"

#if defined(_WIN32) && !defined(__GNUC__)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif

int main(int argc,char* argv[])
{
#if defined(_WIN32) && !defined(__GNUC__)
// _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_WNDW);
// _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
// _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_WNDW);
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
#endif

var a,b,c,d,e,f;

var g=5;
var h="hoge";
var j=(std::string)"hoge";
var k=j;

std::string str;
int i=-1;


//null testing
if(a==NULL)printf("a is null  #### OK ####\n");
else printf("a is NOT null#### NG ####\n");

if(a!=NULL)printf("a is NOT null #### NG ####\n");
else printf("a is null#### OK ####\n");

a["key"]="value";
a[5]=10;

if(a==NULL)printf("a is null #### NG ####\n");
else printf("a is NOT null#### OK ####\n");

if(a!=NULL)printf("a is NOT null#### OK ####\n");
else printf("a is null#### NG ####\n");

//int testing
i=a[5];
printf("i=%d\n",i);
if(i==10)printf("#### OK ####\n");
else printf("#### NG ####\n");


// redbrack testing
b["hoge"]=a;
c=b;
d=c["hoge"];

if(a["key"]==e)printf("a[key]is e #### NG ####\n");
else printf("a[key]is NOT e #### OK ####\n");

if(a["key"]!=e)printf("a[key]is NOT e #### OK ####\n");
else printf("a[key]is e #### NG ####\n");

if(a[5]==f)printf("a[key]is f #### NG ####\n");
else printf("a[key]is NOT f #### OK ####\n");

if(a[5]!=f)printf("a[key]is NOT f #### OK ####\n");
else printf("a[key]is f #### NG ####\n");


e="value";
f=10;
printf("str=>>%s<<\n",((std::string)e).c_str());
if((std::string)e=="value")printf("####  OK ####\n");
else printf("####  NG ####\n");

printf("str=>>%s<<\n",e.pchar());
if((std::string)e.pchar()=="value")printf("#### OK ####\n");
else printf("####  NG ####\n");

if(a["key"]==e)printf("a[key]is e #### OK ####\n");
else printf("a[key]is NOT e #### NG ####\n");

if(a[5]==f)printf("a[key]is f #### OK ####\n");
else printf("a[key]is NOT f #### NG ####\n");


str=a["key"];
a["key"]="hoge!!!!";
printf("str=>>%s<<\n",str.c_str());
if(str=="value")printf("#### OK ####\n");
else printf("#### NG ####\n");

str=d["key"];
printf("str=>>%s<<\n",str.c_str());
if(str=="value")printf("#### OK ####\n");
else printf("#### NG ####\n");

str=a["key"];
printf("str=>>%s<<\n",str.c_str());
if(str=="hoge!!!!")printf("#### OK ####\n");
else printf("#### NG ####\n");

str=a[5];
printf("str=>>%s<<\n",str.c_str());
if(str=="10")printf("#### OK ####\n");
else printf("#### NG ####\n");

a["key"]="123";
i=a["key"];
printf("i=%d\n",i);
if(i=123)printf("#### OK ####\n");
else printf("#### NG ####\n");

a["key"]=0;
i=a["key"];
printf("i=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");


// clear testing
a["key"]=100;
a["key"].clear();
i=a["key"];
printf("i=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");


// length tesintg
a.clear();
if(a==NULL)printf("#### OK ####\n");
else printf("#### NG ####\n");

i=a.length();
printf("a.length()=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");

a=-5;
i=a.length();
printf("a.length()=%d\n",i);
if(i==5)printf("#### OK ####\n");
else printf("#### NG ####\n");

a="";
i=a.length();
printf("a.length()=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");

a="abcdefg";
i=a.length();
printf("a.length()=%d\n",i);
if(i==7)printf("#### OK ####\n");
else printf("#### NG ####\n");

a.clear();
a[7]=70;
a[100]=123;
i=a.length();
printf("a.length()=%d\n",i);
if(i==101)printf("#### OK ####\n");
else printf("#### NG ####\n");

a[-1]=123;
i=a.length();
printf("a.length()=%d\n",i);
if(i==3)printf("#### OK ####\n");
else printf("#### NG ####\n");


// multidimensional array testing
a.clear();
a[15][5]=55;
i=a[15].length();
printf("a[15].length()=%d\n",i);
if(i==6)printf("#### OK ####\n");
else printf("#### NG ####\n");

i=a[15][5];
printf("i=%d\n",i);
if(i==55)printf("#### OK ####\n");
else printf("#### NG ####\n");

//erase test
a.clear();
a["sss"]=5;
a["ttt"]=10;
a["uuu"]=20;
a["ttt"].clear();
i=a.length();
printf("i=%d\n",i);
if(i==2)printf("#### OK ####\n");
else printf("#### NG ####\n");

// at() testing
i=a.at(0);
printf("a.at(0)=%d\n",i);
if(i==5 || i==20)printf("#### OK ####\n");
else printf("#### NG ####\n");

i=a.at(1);
printf("a.at(1)=%d\n",i);
if(i==5 || i==20)printf("#### OK ####\n");
else printf("#### NG ####\n");

i=a.at(2);
printf("a.at(2)=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");

i=a.length();
printf("i=%d\n",i);
if(i==2)printf("#### OK ####\n");
else printf("#### NG ####\n");

return 0;
}


2013年9月5日木曜日

AndroidのWebViewにキーイベントを送る

AndroidのWebViewはタブレットやスマートフォン用にカスタマイズされているため、キーイベントがほとんどきません。
このため、キーボードやゲームパッドで操作するWebViewベースのAndroidアプリを作ることができません。
せっかくいろいろなUSBデバイスやBluetoothデバイスがつながるのに、これらをWebViewで利用できないなんてとても不便です。

ネットで調べても答えが見つからなかったのでいろいろ考えてキーイベントをきっちっと受け取れるWebViewを作ってみました。

ActivityのdispatchKeyEvent()にはイベントがくるので、webview.loadUrl()でJavaScriptを実行させます。
javaScript側ではcreateEvent()でイベントを作って、initEvent()でキーボードイベントを作成、最後にdispatchEvent()でイベントを送信します。

とりあえず方向キーのキーイベントを送るサンプルを作ってみました。
これでどんなキーイベントもWebViewに送れます。

------------------------------------------------------------------------

public class SomeMain extends Activity{

public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    webview.getSettings().setJavaScriptEnabled(true);
    webview.loadUrl("file:///android_asset/index.html");
    setContentView(webview);
}

public boolean dispatchKeyEvent(KeyEvent e) {
    int keyCode=e.getKeyCode();
    if (e.getAction() == KeyEvent.ACTION_UP) {
        switch(keyCode){
        case 19:
            webview.loadUrl("javascript: "
                +"try{"
                +"var evt = document.createEvent('Events');"
                +"evt.initEvent('keydown', true, true);"
                +"evt.keyCode = 38;"
                +"window.dispatchEvent(evt);"
                +"}catch(e){}"
            );
            return true;
        case 20:
            webview.loadUrl("javascript: "
                +"try{"
                +"var evt = document.createEvent('Events');"
                +"evt.initEvent('keydown', true, true);"
                +"evt.keyCode = 40;"
                +"window.dispatchEvent(evt);"
                +"}catch(e){}"
            );
            return true;
        case 21:
            webview.loadUrl("javascript: "
                +"try{"
                +"var evt = document.createEvent('Events');"
                +"evt.initEvent('keydown', true, true);"
                +"evt.keyCode = 37;"
                +"window.dispatchEvent(evt);"
                +"}catch(e){}"
            );
            return true;
        case 22:
            webview.loadUrl("javascript: "
                +"try{"
                +"var evt = document.createEvent('Events');"
                +"evt.initEvent('keydown', true, true);"
                +"evt.keyCode = 39;"
                +"window.dispatchEvent(evt);"
                +"}catch(e){}"
            );
            return true;
        }
    }
    if (e.getAction() == KeyEvent.ACTION_DOWN) {
        switch(keyCode){
        case 19:
            webview.loadUrl("javascript: "
                +"try{"
                +"var evt = document.createEvent('Events');"
                +"evt.initEvent('keyup', true, true);"
                +"evt.keyCode = 38;"
                +"window.dispatchEvent(evt);"
                +"}catch(e){}"
            );
            return true;
        case 20:
            webview.loadUrl("javascript: "
                +"try{"
                +"var evt = document.createEvent('Events');"
                +"evt.initEvent('keyup', true, true);"
                +"evt.keyCode = 40;"
                +"window.dispatchEvent(evt);"
                +"}catch(e){}"
            );
            return true;
        case 21:
            webview.loadUrl("javascript: "
                +"try{"
                +"var evt = document.createEvent('Events');"
                +"evt.initEvent('keyup', true, true);"
                +"evt.keyCode = 37;"
                +"window.dispatchEvent(evt);"
                +"}catch(e){}"
            );
            return true;
        case 22:
            webview.loadUrl("javascript: "
                +"try{"
                +"var evt = document.createEvent('Events');"
                +"evt.initEvent('keyup', true, true);"
                +"evt.keyCode = 39;"
                +"window.dispatchEvent(evt);"
                +"}catch(e){}"
            );
            return true;
        }
    }
    return super.dispatchKeyEvent(e);
}

}



2013年9月3日火曜日

C++でvar型変数を作ってみた。

C++言語にはJavaScriptやPythonのようなインタープリタ言語で使われているvariant型のvar変数がありません。
boost::variantというライブラリがありますが、他の言語と比べるとあまり似ていません。

なので頭の体操を兼ねて、C++のvar型を作ってみました。


var型の「+」と「+=」がまだありませんが、必要になったらそのうち作ります。


------------------------------
variant.cpp
------------------------------
#include <stdio.h>
#include "variant.h"

#if defined(_WIN32) && !defined(__GNUC__)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif


static var var_null;

var::var()
{
type=0;
m_val=0;
}

var::var(int v)
{
type=VAR_TYPE_INT;
m_val=v;
}

var::var(const char*str)
{
var((std::string)str);
}

var::var(std::string str)
{
type=VAR_TYPE_STRING;
m_str=str;
}


var::var(var& val)
{
(*this)=val;
}


var::~var()
{
var* ret;
std::map<std::string,var*>::iterator ite;

ite=m_map.begin();
while( ite != m_map.end() ) 
{
ret=(*ite).second;
delete ret;
ite++;
}
}

var& var::operator[](const char* str)
{
if(str==NULL){
return var_null;
}
return operator[]((std::string)str);
}

var& var::operator[](std::string str)
{
var* ret=&var_null;
if(type!=0 && type!=VAR_TYPE_MAP){
return *ret;
}

switch(type){
case 0:
type=VAR_TYPE_MAP;
case VAR_TYPE_MAP:
ret=m_map[str];
if(ret==NULL){
ret=new var();
m_map[str]=ret;
}
break;
}
return *ret;
}

var& var::operator[](int v)
{
var* ret=&var_null;
char tmp[64];

tmp[0]=0;
sprintf(tmp,"%d",v);
std::string str=tmp;

if(type!=0 && type!=VAR_TYPE_MAP){
return *ret;
}

switch(type){
case 0:
type=VAR_TYPE_MAP;
case VAR_TYPE_MAP:
ret=m_map[str];
if(ret==NULL){
ret=new var();
m_map[str]=ret;
}
break;
}
return *ret;
}

var& var::operator =(std::string str)
{
if(type!=0 && type!=VAR_TYPE_STRING){
return var_null;
}
type=VAR_TYPE_STRING;
m_str=str;
return *this;
}

var& var::operator =(int val)
{
if(type!=0 && type!=VAR_TYPE_INT){
return var_null;
}
type=VAR_TYPE_INT;
m_val=val;
return *this;
}

var& var::operator =(var& val)
{
var* ret;
std::map<std::string,var*>::iterator ite;

//clear all
ite=m_map.begin();
while( ite != m_map.end() )
{
ret=(*ite).second;
delete ret;
ite++;
}
m_map.clear();
type=0;

switch(val.type){
case VAR_TYPE_INT:
type=VAR_TYPE_INT;
m_val=val.m_val;
break;
case VAR_TYPE_STRING:
type=VAR_TYPE_STRING;
m_str=val.m_str;
break;
case VAR_TYPE_MAP:
std::map<std::string,var*>::iterator ite;
type=VAR_TYPE_MAP;
ite=val.m_map.begin();
while( ite != val.m_map.end() )  // 先頭まで
{
m_map[(*ite).first]=new var();
*(m_map[(*ite).first])=*(*ite).second;
ite++;
}
break;
}

return *this;
}

var::operator std::string()
{
if(type==0){
return "null";
}
if(type==VAR_TYPE_STRING){
return m_str;
}
if(type==VAR_TYPE_INT){
return toString();
}
if(type==VAR_TYPE_MAP){
return "objrct";
}
return "broken";
}


var::operator int()
{
if(type==VAR_TYPE_INT){
return m_val;
}
if(type==VAR_TYPE_STRING){
return toInt();
}
return -1;
}

const char* var::pchar()
{
if(type==0){
return "null";
}
if(type==VAR_TYPE_STRING){
return m_str.c_str();
}
if(type==VAR_TYPE_INT){
return toString().c_str();
}
if(type==VAR_TYPE_MAP){
return "objrct";
}
return "broken";
}

int var::toInt()
{
int ret=0;
if(type==VAR_TYPE_STRING){
sscanf(m_str.c_str(),"%d",&ret);
}
return ret;
}

std::string var::toString()
{
std::string ret;
if(type==VAR_TYPE_INT){
char tmp[64];
tmp[0]=0;
sprintf(tmp,"%d",m_val);
ret=tmp;
}
return ret;
}


bool var::operator ==(int v)
{
if(v==0 && type==0)return true;
return false;
}

bool var::operator !=(int v)
{
if(v==0 && type==0)return false;
return true;
}

bool var::operator ==(var& val)
{
switch(type){
case 0:
if(val.type==0)return true;
return false;
case VAR_TYPE_INT:
if(val.type==VAR_TYPE_INT && m_val==val.m_val)return true;
return false;
case VAR_TYPE_STRING:
if(val.type==VAR_TYPE_STRING && m_str==val.m_str)return true;
return false;
case VAR_TYPE_MAP:
//no implement
return false;
}
return false;
}

bool var::operator !=(var& val)
{
switch(type){
case 0:
if(val.type==0)return false;
return true;
case VAR_TYPE_INT:
if(val.type==VAR_TYPE_INT && m_val==val.m_val)return false;
return true;
case VAR_TYPE_STRING:
if(val.type==VAR_TYPE_STRING && m_str==val.m_str)return false;
return true;
case VAR_TYPE_MAP:
//no implement
return true;
}
return true;
}



#if 1

int main(int argc,char* argv[])
{
#if defined(_WIN32) && !defined(__GNUC__)
// _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_WNDW);
// _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
// _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_WNDW);
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
#endif

var a,b,c,d,e,f;

var g=5;
var h="hoge";
var j=(std::string)"hoge";
var k=j;

std::string str;
int i=-1;

if(a==NULL)printf("a is null\n");
else printf("a is NOT null\n");

if(a!=NULL)printf("a is NOT null\n");
else printf("a is null\n");

a["key"]="value";
a[5]=10;

if(a==NULL)printf("a is null\n");
else printf("a is NOT null\n");

if(a!=NULL)printf("a is NOT null\n");
else printf("a is null\n");

i=a[5];

b["hoge"]=a;
c=b;
d=c["hoge"];

if(a["key"]==e)printf("a[key]is e\n");
else printf("a[key]is NOT e\n");

if(a["key"]!=e)printf("a[key]is NOT e\n");
else printf("a[key]is e\n");

if(a[5]==f)printf("a[key]is f\n");
else printf("a[key]is NOT f\n");

if(a[5]!=f)printf("a[key]is NOT f\n");
else printf("a[key]is f\n");

e="value";
f=10;
printf("str=>>%s<<\n",((std::string)e).c_str());
printf("str=>>%s<<\n",e.pchar());

if(a["key"]==e)printf("a[key]is e\n");
else printf("a[key]is NOT e\n");

if(a[5]==f)printf("a[key]is f\n");
else printf("a[key]is NOT f\n");


str=a["key"];
a["key"]="hoge!!!!";
printf("i=%d\n",i);
printf("str=>>%s<<\n",str.c_str());

str=d["key"];
printf("str=>>%s<<\n",str.c_str());

str=a["key"];
printf("str=>>%s<<\n",str.c_str());

str=a[5];
printf("str=>>%s<<\n",str.c_str());

a["key"]="123";
i=a["key"];
printf("i=%d\n",i);


return 0;
}


#endif

------------------------------
variant.h
------------------------------
#include <string>
#include <map>

#define VAR_TYPE_NULL 0
#define VAR_TYPE_INT 1
#define VAR_TYPE_STRING 2
#define VAR_TYPE_MAP 3
#define VAR_TYPE_LIST 4


class var{
public:
var();
var(int v);
var(const char* str);
var(std::string str);
var(var& val);

virtual ~var();

var& operator[](std::string str);
var& operator[](const char* str);
var& operator[](int);

var& operator =(std::string str);
var& operator =(int val);
var& operator =(var& val);

bool operator ==(int);
bool operator !=(int);

bool operator ==(var& val);
bool operator !=(var& val);


// you should implement
//var& operator +=(std::string str);
//var& operator +=(const char* str);
//var& operator +=(int val);
//var& operator +=(var& val);

// you should implement
//var operator +(std::string str);
//var operator +(const char* str);
//var operator +(int val);
//var operator +(var& val);


operator std::string();
operator int();

int toInt();
std::string toString();

// you should implement
//std::string typeOf();
//int length();


const char* pchar();

private:

int type;

std::map<std::string,var*> m_map;
std::string m_str;
int m_val;
};


2013年8月31日土曜日

透き通るような青

最近、うちの嫁が写真をとってフォトブックというものをつくっているので、僕も対抗して
作ってやる。

夏なので透き通るような青の写真を撮ってみました。
iphone4sでも結構きれいに写真とれるんですね。




ミラーレスのnex5も良い感じ


2013年8月28日水曜日

たんぱく質の構造

電子の軌道の計算方法を勉強していたら、原子間の共有結合の結合角度と結合距離さえわかればどんな分子でも構造を表現できることがわかりました。

さらに調べると、世の中にはProtain Data Bank(http://www.rcsb.org/pdb/home/home.do)というところにたんぱく質と遺伝子の情報が全部数値化されて公開されているようです。

表示は、PyMol(http://www.pymol.org/)という分子モデルビュワーがあってそれを使うときれいなCGが作れるようです。

たんぱく質は数十から数百のアミノ酸のできていて、そのアミノ酸同士の結合パターンは10種類。
n個のアミノ酸からできていると10のn乗回の計算をしないと、それぞれの部分がどの結合になるのかコンピュータで構造を求められないのもわかりました。だから解析装置で解析しないといけないのね。


ということで、僕の長年の夢である、ヒトのヘモグロビンのデータ(http://www.rcsb.org/pdb/explore.do?structureId=1LFQ)を取得して、たんぱく質の立体構造を出力してみました。






黄色の色のアンテナの網みたいな部分に酸素がくっつくみたい。

いろいろなウイルスとかのデータもあって結構面白い。
僕が大学生のときにこんな面白いものがあったらもっと勉強したのに。



2013年8月27日火曜日

電子の軌道計算

最近、大学時代に勉強したけどわからなかったことをインターネットで勉強してます。
まずこれ、シュレーディンガー方程式。

http://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%A5%E3%83%A
C%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%AC%E3%83%BC%E6%96%B9%E7%A8%8B%E5%BC%8F
 
大学時代に、ハミルトニアンとか難解な数式がたくさんあってさっぱり意味がわからなかんですが、最近はネット上にいろいろな資料が乗っていて、一週間くらい毎日朝から深夜までひたすら物理を勉強してたら、ついにわかった。


方程式の解を求めるのは至難の業なのですが、誰かが説いた解があれば、それをもとにいろいろな計算ができるようです。

水素原子の周りをまわる電子の軌道の波動関数を計算してみました。



 

わかってしまえば意外と簡単じゃん。
こんなふうに簡単に電子の軌道を計算して図にすることができます。
次はタンパク質とか水分子の軌道計算してみようかなぁ。


-----------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

double PI = 3.141592653589793238462;
double Factorial(int n);
double Factorial2(int n, int m);
const int n_max = 4;
const int kizami = 200;
const double L = 80.0;
double Laguerre( int k, int n, double x);           //ラゲール陪関数
double Legendre( int m, int l, double x);           //ルジャンドル陪関数

double bai=20000;


void* cbmp(int w,int h){
unsigned char* ret;
int sz;
sz=w*h*4+54;
ret=malloc(sz);
memset(ret,0,sz);

ret[0]='B';
ret[1]='M';

ret[2]=sz &255;
ret[3]=(sz>>8) &255;
ret[4]=(sz>>16) &255;
ret[5]=(sz>>24) &255;

ret[10]=54;

ret[14]=40;

ret[18]=w &255;
ret[19]=(w>>8) &255;

ret[22]=(-h) &255;
ret[23]=((-h)>>8) &255;
ret[24]=255;
ret[25]=255;

ret[26]=1;
ret[28]=32;



return (void*)ret;

}

void fbmp(void* vp)
{
if(vp==NULL)return;
free(vp);
}

void wbmp(void* vp,char* fn)
{
int sz;
unsigned char* p;
FILE* fp;

if(vp==NULL || fn==NULL)return;

p=vp;
p+=2;

sz=(*p);
sz|=(*(p+1))<<8;
sz|=(*(p+2))<<16;
sz|=(*(p+3))<<24;

fp=fopen(fn,"wb");
if(fp==NULL)return;
fwrite(vp,1,sz,fp);
fclose(fp);

}

void pbmp(void*vp, int x,int y,int b,int g,int r)
{
int off;
unsigned char* p;
int w;


p=vp;

w=p[18] | p[19]<<8;

off=y*w*4+x*4+54;
if(r<0)r=0;
if(r>255)r=255;
if(g<0)g=0;
if(g>255)g=255;
if(b<0)b=0;
if(b>255)b=255;

p[off]=b;
p[off+1]=g;
p[off+2]=r;
p[off+3]=255;

}

void abmp(void*vp, int x,int y,int b,int g,int r)
{
int off;
unsigned char* p;
int w;


p=vp;

w=p[18] | p[19]<<8;

off=y*w*4+x*4+54;
if(r<0)r=0;
if(r>255)r=255;
if(g<0)g=0;
if(g>255)g=255;
if(b<0)b=0;
if(b>255)b=255;

b+=p[off];
g+=p[off+1];
r+=p[off+2];

if(r<0)r=0;
if(r>255)r=255;
if(g<0)g=0;
if(g>255)g=255;
if(b<0)b=0;
if(b>255)b=255;

p[off]=b;
p[off+1]=g;
p[off+2]=r;

}


int main(){

  double r_min = 0.0;
  double r_max =  40.0;
  const int Z = 1;

  int l,m,n;




  for(n=1; n<=n_max; n++)
  {
    for(l=0; l<n; l++)
    {
      for(m=0; m<=l; m++)
      {
        void* fp;
        char str[200];
int ix,iy;

sprintf(str, "Psi%d_%d_%d.bmp", n, l, m);
fp=cbmp(kizami,kizami);

 for(ix=0; ix<kizami; ix++ )
        {
          for(iy=0; iy<kizami; iy++ )
          {
            double x = - L/2.0 + L * (double)(ix)/(double)(kizami);
            double y = - L/2.0 + L * (double)(iy)/(double)(kizami);
            double z =0;
            double r = sqrt(pow(x,2)+pow(y,2)+pow(z,2));
            double theta = acos(z/r);
            double phi;
double R,Y;
int cc;


            if(y>=0) phi = acos(x/r);
            else phi = 2.0*PI - acos(x/r);
            if(r==0){
              theta = 0;
              phi = 0;
            }
            R = 2.0/pow((double)(n),2) * sqrt(Factorial(n-l-1)/Factorial(n+l))
* exp(-r/(double)(n)) * pow( 2.0*r/(double)(n),l) 
*Laguerre(2*l+1, n-l-1, 2.0*r/(double)(n))  ;
            Y = pow(-1.0, m) * sqrt((double)(l)+1.0/2.0) 
* Factorial(l-m)/Factorial(l+m) * Legendre(m,l,cos(theta));
            if(m==0) {
              //fprintf(fp,"%f %f %f\n",x,y,R*Y);
cc=(int)(R*Y*bai);
if(cc>=0)
pbmp(fp,ix,iy,0,0,cc);
else
pbmp(fp,ix,iy,-cc,0,0);
            }else{
              double Yx = Y * cos((double)(m)*phi);
              double Yy = Y * sin((double)(m)*phi);
              //fprintf(fp,"%f %f %f %f\n",x,y,R * Yx,R * Yy);
cc=(int)(R*Yx*bai);
if(cc>=0)
pbmp(fp,ix,iy,0,0,cc);
else
pbmp(fp,ix,iy,-cc,0,0);
cc=(int)(R*Yx*bai);
if(cc>=0)
abmp(fp,ix,iy,0,0,cc);
else
abmp(fp,ix,iy,-cc,0,0);
            }
          }
        }
wbmp(fp,str);
        fbmp(fp);
      }
    }
  }
}
double Laguerre( int k, int n, double x)
{
  double sum=0;
  int m;
  for(m=0; m<=n; m++){
    sum += pow(-x,m)*Factorial(n+k)/Factorial(n-m)/Factorial(k+m)/Factorial(m);
  }
  return sum;
}
double Legendre( int m, int l, double x)
{
  int mm = abs(m);
  int ll;
  double r0, r1, r2;

  if( mm>l )  return 0;
    r0 = 0.0;
    r1 = pow(1.0-x*x, (double)(mm)/2.0) * Factorial2(2*mm-1, 2);
    if( mm==l && m>=0) return r1;
    if( mm==l && m<0)  return r1 * pow(-1.0,mm) * Factorial(l-mm)/Factorial(l+mm) ;
    for(ll = mm+1; ll<=l; ll++ ){
      r2 = ((2.0*ll-1.0)*x*r1 - (ll+mm-1.0)*r0)/(ll-mm);
      r0 = r1;
      r1 = r2;
    }
  if(m>=0) return r2;
  else return r2 * pow(-1.0,mm) * Factorial(l-mm)/Factorial(l+mm) ;
}
double Factorial(int n)
{
  double F = 1.0;
  int i;

  if( n<=0 ) return 1.0;
  for(i=n; i>=2; i--){
    F *= (double)(i);    
  }
  return F;
}
double Factorial2(int n, int m)
{
  double F = 1.0;
  int i;
  if( n<=0 ) return 1.0;
  for(i=n; i>=2; i=i-m){
    F *= (double)(i);    
  }
  return F;
}