Android(を含めた)グラフ考察メモ

メモ途中)


http://twitter.com/skrb/status/352953655269408770:twitter:detail:right
http://twitter.com/skrb/status/352966096174858240:twitter:detail:right
http://twitter.com/skrb/status/352971928820133888:twitter:detail:right
http://twitter.com/aoetk/status/352986727746510850:twitter:detail:right

なんでこんな話題出てるかというと
ようはランキング等を作った場合に

人種別 ランキング状況
やり込む人 凄い頂点
普通の人 それ見てヒク

でレーダチャートで全体バランス的な総和イメージでぼかしてやると
モチベーション上がるんじゃないか というお話で調べてました
JavaFXネタはスマホエミュレータみたいな画面見れるといいなという話から

レーダチャート自体は

の2パターンが考えられるけど、どっちがベターなんですかね。。(汗

備考)
charts4jで生成されるURLを使う場合[|]がエラーになるのでその箇所のencodeが必要

String url = chart.toURLString();
url = url.replaceAll("\\|", "%7C");


追記)
まあコレに関しても
cocos-2d jsでやれば追加ソフト要らないんじゃない?
みたいな話になるようで、まあ即興で直ぐ作れない自分が恨めしい部分もありますね(汗

あとは自分の得点周辺ユーザ部分のみ表示する

  • ランキンググループ
  • 知り合いグループ

みたいな奴で競わせる?*1

な感じもあるよう。全員ウケするものを考えるのはたしかに難しいよな。。



JNLP周りのメモ)



他のグラフライブラリ)

JFreeChart 使える場合は

が凄く詳しいです。

最近developer.IOで紹介されていた奴




flot_android の自メモ)
多分自分しか使わないネタなので移動。
79KBのサイズなのが特徴で組込んでます。

一応サイズ目安として

  • apk全体のMB数を3〜5MB

という話があるので。大体JS配信型(SSP等)ではない
広告系を入れる場合 1〜1.5MBほどサイズを見ておかないと駄目な点が有

という論旨で
JFreeChartもいいんだけど3MB組み込むのはな。。。(汗



SQLiteなのですが
 Date型持てない => 文字列型 で
という話があるわけなんですが

日付のあるレコードを

HogeDB hogeDB = new HogeDB(this);
ContentValues values = new ContentValues();

//〜中略〜

SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); //★
values.put(DataColumns.DATE_TIME, df.format(new Date()) ); //★
Long id = hogeDB.insert(values);
hogeDB.close();

とかではなく

HogeDB hogeDB = new HogeDB(this);
ContentValues values = new ContentValues();

//〜中略〜

values.put(DataColumns.DATE_TIME, new Date().toString() ); //★
Long id = hogeDB.insert(values);
hogeDB.close();

★みたいな事をしてくれるコードが有るわけです*3
これだとデータのソートとかも出来ないわけですね


Fri Apr 10 01:11:32 Asia/Tokyo 2011
とか入るわけで・・。


で、こんな関数を作って補正するイメージ

private boolean checkDate(String data){
    	try {
    		if(data==null || "".equals(data))return false;
    		String num = data.substring(0,1);
    		Integer.parseInt(num);
    		return true;
    	} catch (NumberFormatException e) {
    		return false;
    	}
}


private String[] sMonthNames= new String[] { "Jan", "Feb", "Mar", "Apr", "May",
            "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
private String fixDate(String data){
    	String ret="";
    	String[] arr = data.split(" ");
    	int arr_len = arr ==null ? 0:arr.length;
    	//[TODO] Fri Apr 10 01:11:32 Asia/Tokyo 2011 なデータを想定

    	int i=0;
    	for(i=0;i<12;i++){
        	if(arr_len > 2 && sMonthNames[i].equals(arr[1])){
        		break;
        	}
    	}
    	ret = String.format("%s/%02d/%s %s",arr[5],i+1,arr[2],arr[3]);

    	return ret;
}

使う方は

String date_time =c.getString(c.getColumnIndex(DataColumns.DATE_TIME));
if(!checkDate(date_time)){
   ContentValues cv = new ContentValues();
   cv.put(DataColumns.DATE_TIME, fixDate(date_time));
   hogeDB.update(id, cv);
}

な感じ。

データさえ残ってればいいじゃん
みたいな論調があったりするんだけど、このデータを使ってグラフ書きたいとか
しようとするとハマるわけで。。

 ようは
flot_androidライブラリを使って
今日一日のグラフを作りたいとかの場合

//全グラフ線配列
Vector<SeriesData> sds = new Vector<SeriesData>(); 

SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
String sToday = df.format(new Date());

int cnt = 0;

//座標データ
Vector<PointData> pds = new Vector<PointData>();

HogeDB hogeDB = new HogeDB(this);
Cursor c = hogeDB.query("date_time desc" );
if (c.moveToFirst()) {
    	boolean b = true;
    	do {

                //〜 略 〜
                int value  =c.getInt(c.getColumnIndex(DataColumns.VALUE)); 
    	    	String sDate =c.getString(c.getColumnIndex(DataColumns.DATE_TIME));
				
    	    	//yyyy/MM/dd のレコードのみ絞込み
    	    	if(!sToday.equals(sDate.split(" ")[0])){
                    	b = c.moveToNext();
    	    	    	continue;
    	    	}
    	    	cnt++;
            	pds.add(new PointData( cnt, value));
            	b = c.moveToNext();
        } while (b);
}
c.close();
hogeDB.close();

//グラフの一本線
SeriesData sd = new SeriesData();
sd.setData(pds);
sd.series.lines.setShow(true);
sd.series.points.show = true;
sd.label="hogehoge";
//sd.series.lines.steps = true;
sds.add(sd);
  • 実際のグラフ描画☆☆
FlotChartContainer fdl = (FlotChartContainer)gDlg.findViewById(R.id.flotdraw);
FlotDraw fd = new FlotDraw(sds, null, null);
fdl.setDrawData(fd);

な感じでかけたりとか。


でもまあ実際は SeriesData の pdsデータが多いと
横軸メモリが細かくなるので、一定周期で

  sds.add(sd); 
  pds  =  new Vector<PointData>();

な感じで作りなおさないと
表示が細かすぎて多分キツイと思う


追加検証メモ)

☆☆ の方法はサンプル通りなのですが
この実装に関しては実は問題があって、

  • このLibrary Pan拡大をサポートしようとしてる
  • FlotChartContainerの実装が中途半端で落ちる
  • 上記コンテナが常に動いてる*4のでメモリリークするよう
    • =>Bitmapにグラフ書いちゃえば良くない?

という方針で変更する

追記)
Galaxy S4で上記コードで上手く動かないので ☆辺りを追記した。

  • setBackgroundDrawable だと何故か実体より小さく表示される
  • setImageBitmapにするとS4のみ繰り返すとリークしてOOM出まくりorz
    • ARGB_4444 => RGB565に色数落とす
    • 他の機種では問題なし

どうも圧縮画像にして設定しないと落ちるらしい。。
正直勘弁して欲しいよな。。。

*1:毎日何回もやるモチベーションが上がる

*2:でもどっかのブログでフル機能使えないからdisってるの見たこと有

*3:やっつけコードに多い

*4:SurfaceView実装なので