2010年9月30日木曜日

Autohotkeyで句読点置換,改行除去

このエントリーをはてなブックマークに追加
普段句読点として「,.」を使っている人がいると思いますが,「、。」で文字を使用する場合はタイプし終えてから,置換を「,」=>「、」と「.」=>「。」で2回行う必要があります.

そこで,Autohotkeyを使用して,この作業を簡単に行うスクリプトを書いてみました.
ここではF12キーを押すと,文字を全選択し=>クリップボードにコピー=>どちら方向に置換するか判断=>置換=>クリップボードから貼り付けという作業をしています.

どちら方向に置換するかの判断には,「,」がテキスト中に出てきたら「,.」=>「、。」としています.「.」もしくは両方で判断してもよいかと思います.

ついでに,Shiftを押しながらF12で,改行を除去ようにしてあります.

; Shift+F12: 改行を除去 abc \r\n def => abcdef
; F12: 「、。」 <=> 「,.」

*F12::
 GetKeyState, shiftFg, Shift ; Shiftが押されているか?
 Send, ^a^c   ; テキストをクリップボードにコピー
 str := clipboard
 if shiftFg = D   ; Shift押している場合は改行を消す
 {
  StringReplace, str, str, `r`n, , All
 }
 else
 {
  StringGetPos, pos, str, , ; 全角コンマの位置を検索
  if pos >= 0
  {
   StringReplace, str, str, ,, 、, ALL
   StringReplace, str, str, ., 。, ALL
  }
  else
  {
   StringReplace, str, str, 、, ,, ALL
   StringReplace, str, str, 。, ., ALL
  }
 }
 clipboard := str
 Send, ^v
return

2010年8月24日火曜日

Google Developer Day 2010 DevQuiz

このエントリーをはてなブックマークに追加
Google Developer Day 2010の
DevQuizの回答受付期間が終了しましたね.

みなさん様々な方法で解かれたと思います.
結構面白かったですね.

一応僕の解いたやり方をメモしておきます.
(と言っても特にユニークなやり方でもないと思います)

僕の点数は下記の通りです.

■ラウンド2: Google Maps API
経路最適化問題です.
以下,DevQuizの問題文より

日本国内の場所のリストが与えられます。あなたはそれらをすべて通るようなルートのうち、最短時間のものを計算して、提出してください。ルートの開始点は最初に与えられる場所とし、最後にはもとの位置にもどって来て下さい。 また、各地点を移動するのに必要な時間は Google Maps API の運転ルート案内で得られる秒数を使ってください。

入力:
入力は地点のリストからなります。リストは改行で区切られます。各地点は、地点の名称、緯度、経度からなり、それぞれ空白文字で区切られます。
例) 東京都庁 35.6894875 139.6917064
札幌市役所 43.0627820 141.3535990
:

出力:
解答フォーマットは、地点の名称を空白で区切ったリストとします。始点と終点も与えてください。
例) 東京都庁 札幌市役所 ... 東京都庁


[レベル1]
東京タワー 35.658570 139.745484
宮崎県庁 31.911096 131.423893
佐多岬 30.994560 130.660638
[レベル2]
兼六園 36.562070 136.662419
五条大橋 34.995682 135.767890
襟裳岬 41.926490 143.246642
東京大学 35.712940 139.759590
両国国技館 35.697080 139.792280
鷲宮神社 36.100240 139.656800
[レベル3]
通天閣 34.652554 135.506333
兼六園 36.562070 136.662419
ハウステンボス駅 33.091673 129.796602
襟裳岬 41.926490 143.246642
日本銀行 35.686839 139.771438
国会正門前 35.676293 139.746927
秋吉台 34.234753 131.310094
日本科学未来館 35.619415 139.776550
両国国技館 35.697080 139.792280
幕張メッセ 35.646701 140.036654


レベル1は自分の手でGoogle Mapsから経路探索を行えば十分ですね.
問題はレベル2とレベル3です.
とりあえずレベル2について見ると,兼六園→○→×→□→△→☆→兼六園となり,探索すべきルートは,5!となります.5!=120なので,Google Maps APIより全探索してもOKでしょう.正確には計っていませんが,検索にかかる時間は数秒ですんでいたと思います.

次にレベル3についてです.
レベル3は,通天閣→9カ所→通天閣となり,全探索すると9!回となります.9!=362880となり,これは全探索するには少しつらい.
どうしようか考えたのですが,経由すべき場所をよく見ると,主に東京周辺とそれ以外に分けられることがわかります.
つまり東京周辺グループ{日本銀行,国会正門前,日本科学未来館,両国国技館,幕張メッセ}(幕張メッセだけ千葉ですが)とその他グループ{兼六園,ハウステンボス駅,襟裳岬,秋吉台}です.

ここで,まず,通天閣からその他グループの全ての地域と東京周辺グループの一地域(例えば日本銀行)を通り, 通天閣に戻るルートを検索します.その他グループの地域数は4で,これに東京グループの一地域を加え5!の問題を解きます.これはレベル2と同じ数ですね.そして,例えば下記のような答えが得られたとします.
 (これは答えではありません)
通天閣→兼六園→ハウステンボス駅→日本銀行→襟裳岬→秋吉台→ 通天閣

今度は,ハウステンボス駅から東京グループの各地域を通り,襟裳岬にたどり着くルートを検索します.東京グループの地域数も5なので検索するルート数は5!となり,これも探索可能となります.


■Super Hackers:Shiritori
決められた単語を用いて,サーバーとしりとりで勝負します.
単語が無くなったら負けとなります.
レベル1とレベル2の回答は省きます.
レベル3について.
使う単語は,
xjkfkwvpt,tzsmq,pxbmcesnjns,egcllbcbh,
thbtdo,tkssgbvja,qxbrgzcmfo,qpnkhoirma,qylomri,
onkwrscza,ojpyyi,ohkhkmavpx,aeuni,akgrx,
awhveplfw,idaslbxx,izcwbqihw,ifncjdqsjcb,xmgkmcsw,
xbyhupb,xbcmpszfm,wyccb,wojkom,wzpnyonhet,
bdetytm,bnccrpxt,bngxufabq,mlyiesuet,mnoyargccqq,
mawvlvo,ttsey,ykplamk,yrhtmqv,yygjpuwyp,
qhfag,gnfbckn,gfvnrdfmr,ghnhwrrtmc,ouiimevu,
ucszjfgsf,upxpqzmvie,ueexd,apayifgy,iqjqg,
xpwxsiu,wffhsfwqwjy,bdcrgyg,mjqdu,kkgen,
kexref,kbkrev,kqqwqezr,koucaoe,kvzkcosfllp,
knwdc,kykdnd,krwgpol,kwqulsbbs,kgvwosyh,
nurzk,nvrwtuzkf,ndvlgjvv,nfzhudxnr,npdyzvje,
nkjynp,nqjeefpnwpc,njrhvudad,nemsl,nysikxzxs,
nvzayoh,frkxeqek,fjadqgyn,fqfcbv,fxomlbwkotr,
fakwkpjge,fiwchp,frrlricvsc,fvtcqunvoyd,foqpsspyl,
fggikoous,ffyrh,vhwcvgk,voqtn,vrdomf,
vtnyr,vfiote,vyxfbdp,vqsaeqlc,vsnqd,
vttsaizbdl,veals,vfprmoxmmh,rzttstqlk,reoirnyn,
rfdeienf,rkaibcv,rybmcce,rnoup,rgpuhstjc,
rzfrosbakid,rylywizybzl,rdmcss,rljpgznoh,eltsk,
exdxiyfbugn,eeublwiiidf,ediov,ehvftymilr,esfjynnnp,
esmsxsymcpc,eahgoobid,ewnreexvmtl,eimtomus,
plpykovffk,ptvpsdmjjn,pvlajfcf,pbtvpnnnpv,pvedaer,
piywsfve,puggdtmymhc,pfmywnd,ptkkxjal,
pusevvmqvuh,cwfrgkbodik,clqcn,ccdbuf,cvfdrtdv,
cpltr,cskkmnine,czqzzzwxvp,chwtukwd,cafluoehbl,
cblwnbois,cbsyh,dliovokk,dzfmcbenffn,dcmuejvggkf,
djvzgpspv,dgdhxibsepr,debtnxtqe,dufwuvdp,dwurgc,
dkuol,dohbzxpxshs,dydwrdzadch,ltuck,lxlxaen,
lqxxrf,lecjbv,lghpeqlwxtr,lfpmtue,lvpncp,
lkgqghhc,lzjuud,lchljus,lzzkxh,slxaek,
srten,steeycpf,sepuwxzv,snlonbntjr,shske,
saynsxp,sjvqgzdkpec,suvzved,sjgtl,spmxdoh,
hwfptlzbk,hqgbwovn,hutfyojmqzf,hnusersv,hmber,
hdowqwfe,hooihp,hutlc,hvyzebbd,hykmzl,
hajyxs,llxlapt,lxgcfykha,ljwgmgjjw,shutpq,
snzbqki,sjzgb,hrfjso,hplgjpjcx,hcqim
(相手始まりで相手は最初にxjkfkwvptを選択する)

これ何回か手動でプレイするとわかるのですが,ある文字で始まる単語ではめられます.
例えば「c」で始まる単語は11こあるのですが,これに対して「c」で終わる単語は12個あり,一度「c」で始まる単語を選ぶと,相手は常に「c」で終わる単語を選び,最後には単語が無くなってしまいます.もちろんプログラムを組んで探索しても良いと思いますが,少し単語を分析してみると解法が導けます.

まず,aからzまでの単語の先頭数と末尾数をチェックします.

文字 先頭数 末尾数
a 4 4
b 4 4
c 11 12
d 11 12
e 11 12
f 11 12
g 3 3
h 14 11
i 4 4
j 0 0
k 11 12
l 14 11
m 4 4
n 11 12
o 4 4
p 11 12
q 4 4
r 11 12
s 14 11
t 4 4
u 3 3
v 11 12
w 4 4
x 4 4
y 3 3
z 0 0

表からわかるようにいくつかのパターンが見えてきます.
パターン1:先頭数と末尾数が4 {a,b,i,m,o,q,t,w,x}
パターン2:先頭数と末尾数が3 {g,u,y}
パターン3:先頭数が11,末尾数が12 {c,d,e,f,k,n,p,r,v}
パターン4:先頭数が14,末尾数が11 {h,l,s}
(関係のないjとzは無視します)
ここでパターン3は先ほど言ったように,先にパターン3で始まる単語を選択する状況になったら負けます.
では,パターン3の文字で始まる単語を相手に選択させるためには,パターン3の文字で終わる単語を自分が選択する必要があります.
これは具体的にはパターン2の単語です.例えば,パターン2の一つであるgで始まる単語は,{gfvnrdfmr, ghnhwrrtmc, gnfbckn}があり,全て末尾がパターン3の文字で終わります.

そして,上記の事から,パターン2の文字で終わる単語を相手に選択させれば勝ちとなることがわかります.
少しまとめると
パターン3始まりの単語を相手に選択させる→パターン3終わりの単語を自分が選択する(=パターン2始まるの単語を自分が選択する)→パターン2終わりの単語を相手に選択させるとなります.

さて,ここでパターン1の文字で始まる単語は,4つありますが,その中でパターン2の文字で終わる単語を1つずつあります.

具体的には下記のようになります.

先頭 パターン1の末尾 パターン2の末尾
b mqt g
i bwx g
q aio g
a iwx y
t aoq y
w mbt y
x bmw u
m oqt u
o aix u

相手は初めにxjkfkwvptを選んでるためtからyを取らないように他の単語(末尾がa,o,p)を選択します.後は,g,y,uを取らないように,ゲームを進めていけば勝ちます.

■Super Hackers:PAC-MAN
50
11 7
###########
#.V..#..H.#
#.##...##.#
#L#..#..R.#
#.#.###.#.#
#....@....#
###########

上記のような文字列が与えられ,自機が@で,VHRなどは敵を表します.
#は壁でドットはポイントを表します(ポイントは一度とったら消える)
上下左右及び停止しながら,ポイントを多く集めると言った問題.

とりあえず,敵の動きが決められているので,そのように動く簡単なシミュレータを作り,自機は再帰で探索を行うことにした.
上記の例のような問題だとすぐ解けるのだが,レベル2,レベル3のような問題は,時間がかかり解けない.
例えば迷路探索のように,進む方向がある程度決まっている場合,全探索でも問題はないのだが,今回のように来た道を戻った方が良い場合や,一時停止をして敵が通り過ぎるのを待つ方が良い場合があり,探索数が莫大に増える.
結局,これに対してのいい案は思い浮かばずに,できるだけ長い間プログラムを走らせて良い結果がでたら随時表示してサーバに答えをアップロードした.

他の人を見ると,シミュレータを作って人力でパックマンをプレイして,かなりの高得点(レベル3で500点超え)を出されている方がいたので,その方が手っ取り早かったみたい.

2010年8月18日水曜日

Androidのソースをビルド

このエントリーをはてなブックマークに追加
Ubuntu 9.04 64bit kernel:2.6.28-19-generic
という環境でAndroidのソースコードをビルドしてみました.
結構躓いたのでメモメモ

"Android make"らへんでググると結構な情報が出てくるのでそちらをご参考ください.
必要なパッケージをインストールして,いざmakeしてみると,


◆エラー内容
/usr/include/gnu/stubs.h:7:27: error: gnu/stubs-32.h: No such file or directory

■対処法
$sudo apt-get install libc6-dev-i386

気を取り直して再度make

◆エラー内容
/usr/bin/ld: cannot find -lstdc++

■対処法
$sudo apt-get install g++-multilib

まだ,あきらめずにmake
◆エラー内容
/usr/bin/ld: cannot find -lz

■対処法
※この問題は64bitにしたから?
getlibsを入れると便利そうなので,下記URLよりgetlibsをダウンロードしインストール
関連ライブラリをインストール
$getlibs -l libz.so libz.so: zlib1g-dev

あきらめたらそこで試合終了 make
◆エラー内容
/usr/bin/ld: cannot find -lncurses

■対処法
sudo apt-get install lib32ncurses5-dev lib32readline5-dev

ようやくこれでビルドできました・・・
長かった.一回makeしてからエラーがでるまでの時間がすごい長かった.(コンパイル時間がすごい長いので注意を)

2010年7月31日土曜日

Happy Hacking Keyboard Blue Esc Key

このエントリーをはてなブックマークに追加
株式会社PFUの創業50周年記念キャンペーンに応募して見事Blue Esc Keyをもらいました!

前回のRed Control Keyも当たり、現在2連勝中です!!!
折角の墨モデルなのに、どんどんとカラフルになってきますねw


2010年7月29日木曜日

Android Activityのライフサイクル

このエントリーをはてなブックマークに追加
AndroidアプリケーションにおけるActivityのライフサイクルについてのまとめ

呼び出されるメソッド順に記述しています.

○アプリ起動時
onCreate
onStart
onResume

○(起動中に)ホームボタン
onPause
onStop

○ホームボタン押し後(onStop後),再度起動
onRestart
onStart
onResume

○(起動中に)バックボタン
onPause
onStop
onDestroy

○(起動中に)画面90°回転
onCreate
onStart
onResume

2010年6月4日金曜日

麻雀あがり判定

このエントリーをはてなブックマークに追加
麻雀のあがり判定について

すっごく簡易化したもので考えてみたけど,
頭を取る→刻子を取る→順子を取る→残りをチェックということでいいのかな?
刻子と順子が逆になったほうがいい場合は,あるのか???

import java.util.ArrayList;
import java.util.List;

public class Test {
   public static void main(String[] args) {
      // 簡略化のために牌は1-9のみ
      // 配列haiのindex番号と牌の枚数が対応している
      // 例) hai[1]<=>1の枚数
      int[] hai = {0,0,2,2,2,2,2,2,2,0};   // 大車輪
//      int[] hai = {0,3,1,1,1,1,1,1,1,4};   // 九連宝燈
//      int[] hai = {0,3,3,3,3,0,0,0,0,2};   // 四暗刻
      int[] c_hai;
      List<Integer> mentu;

      // 頭をまず取る
      for(int i = 1; i < hai.length; i++){
         if(hai[i] >= 2){
            c_hai = hai.clone();
            c_hai[i] -= 2;
            mentu = new ArrayList<Integer>();
            judge(c_hai, mentu, i);
         }
      }
   }
   // 再帰
   static void judge(int[] hai, List<Integer> mentu, int atama){
      if(mentu.size() == 12){
         print(mentu, atama);
      }
      // 刻子を取る
      for(int i = 1; i < hai.length; i++){
         if(hai[i] >= 3){
            mentu.add(i); mentu.add(i); mentu.add(i);
            hai[i] -= 3;
            judge(hai, mentu, atama);
         }
      }
      // 順子を取る
      for(int i = 1; i < (hai.length-2); i++){
         if(hai[i] > 0 && hai[i+1] > 0 && hai[i+2] > 0){
            mentu.add(i); mentu.add(i+1); mentu.add(i+2);
            hai[i]--; hai[i+1]--; hai[i+2]--;
            judge(hai, mentu, atama);
         }
      }
   }
   // 表示
   static void print(List<Integer> mentu, int atama){
      for(int i = 0; i < mentu.size(); i++){
         System.out.print(mentu.get(i) + " ");
         if(i % 3 == 2)
            System.out.print("| ");
      }
      System.out.println(atama + " " + atama);
   }
}


上記の実行結果は下記のようになる
------------------------------------------------------
3 4 5 | 3 4 5 | 6 7 8 | 6 7 8 | 2 2
2 3 4 | 2 3 4 | 6 7 8 | 6 7 8 | 5 5
2 3 4 | 2 3 4 | 5 6 7 | 5 6 7 | 8 8
------------------------------------------------------

2010年6月1日火曜日

Android marketへの登録およびアプリのアップロード

このエントリーをはてなブックマークに追加
◆Android marketへの登録方法
Android marketへの登録については下記サイトを参考にさせていただきました.
注意点としては,登録料として$25が必要となります.
また,クレジッドカード払いとなるのですが,JCBは使えません.

Android Marketのユーザ登録開始&登録方法(1) « 突然消失するかもしれないブログ

◆アップロードに関して
apkファイルをアップロードする際,アプリケーションに対して署名を行う必要があります.Eclipseを使用している人は,簡単に署名を行えます.
署名に関しては,下記サイトが参考となりました.

八角研究所 : Android で再開する Java プログラミング(13) - Android Market で作品を公開しよう!

注意点として,Android marketにアップロードするアプリは,動作を保証するバージョンを明記する必要があるということです.
アプリのAndroidManifest.xmlにて,

<uses-sdk android:minsdkversion="4" />

等を記載しましょう.4はAndroid SDK1.6を指しますので,そこはご自分のアプリの最小バージョンを明記しましょう.

ちなみに,私は,仕事効率化カテゴリーに「MultiSearch」というアプリケーションをアップロードしました.


公開して2日間経ちましたが30ダウンロードされているみたいです.嬉しいです.

以下,説明&アプリのスクリーンショットです.よろしければお使いください.

--
MultiSearchは、検索のためのユーティリティソフトウェアです。
MultiSearchでは、ドロップダウンメニューから、検索サイトを選択し、文字列を検索することで、その該当検索サイトから直接 検索結果を取得できます。そのため、無駄なステップを踏む必要がなく、快適に検索を行うことができます。現在、対応している検索サイトは、Wikipedia、英辞郎、クックパッ ド、e-Words、はてなキーワード、Acronyms(頭字語検索)となっています。





TeX早見表

このエントリーをはてなブックマークに追加
論文等を制作する際に使用する組版ソフト「TeX」の早見表を制作しました.

 TeXの環境構築等については言及していないので,ある程度TeXを触ったことがあるユーザをターゲットとしています.

具体的な内容は下記のようになっています.
・箇条書き
・画像・図の張り方
・表の張り方
・参考文献の書き方
・各種記号
・各種書体
・数式
・その他Tips集

ダウンロードは下記から行ってください.
http://ayakixlablog.web.fc2.com/tex_hayami.pdf

2010年5月13日木曜日

Androidでスレッドの利用

このエントリーをはてなブックマークに追加
Androidでスレッドの利用方法です.

Handlerを使います.

注意点が必要なのはメインスレッドではないスレッドで,ViewなどのGUI部品を触れないということです.
なので,GUI部品を触るのは,メインスレッドでやりましょう.


import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
public class Temp extends Activity implements Runnable {
private ProgressDialog progressDialog;
/** Called when the activity is first created. */
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
do();
}

private void do(){
// 通信中ダイアログの表示
progressDialog = new ProgressDialog(this);
progressDialog.setTitle("データ取得中");
progressDialog.setMessage("しばらくお待ちください");
progressDialog.setIndeterminate(false);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.show();
Thread thread = new Thread(this);
thread.start();
}
public void run() {
// 時間のかかる処理をここに記述
try{
// 今回はわざと3秒間スリープ
Thread.sleep(3000);
} catch (InterruptedException ie){
} ///////////////////////

handler.sendEmptyMessage(0);
}

private Handler handler = new Handler() {
public void handleMessage(Message msg) {
// 処理終了時の動作をここに記述

/////////////////////////
// プログレスダイアログ終了
progressDialog.dismiss();
}
};
}

Androidで画面サイズの取得

このエントリーをはてなブックマークに追加
Androidで画面サイズを取得するやり方メモ

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int width = metrics.widthPixels; // 横幅サイズを取得
int height = metrics.heightPixels; // 縦幅サイズを取得

Androidのエミュレータ利用法

このエントリーをはてなブックマークに追加
EclipseでAndroid開発をしている際,Eclipseの[実行]からAndroidアプリケーションで実行をすると思います(そして,エミュレータが立ち上がり挙動を確かめる.).

しかし,エミュレータを起動するのには,結構な時間がかかります.

そこで,エミュレータを立ち上げたまま,コマンドでプログラム(*.apk)をダウンロードする方法を記載します.
[]内は環境に合わせて書き換えてください.

<エミュレータの立ち上げ方>
emulator -avd [AVD名]

<ダウンロード方法>
adb install [*.apk]adb install -r [*.apk]   // すでにエミュレータ内にapkがある場合は,再インストールのためrオプションを書きます.
adb -d install [*.apk] // 実機にインストールする場合
adb -e install [*.apk] // エミュレータにインストールする場合

2010年4月26日月曜日

Server returned HTTP response code: 403 for URLに対して

このエントリーをはてなブックマークに追加
Javaです.

URLConnectionを使って,HTTPコネクションをはり,HTMLを取得する際,下記のように書く.

import java.io.*;
import java.net.*;

public class MyURLConnection {
public static void main(String[] args) {
try {
URL url = new URL("http://example.com/");
URLConnection conn = url.openConnection();
BufferedReader in = new BufferedReader( new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}


ただ,サイトによっては,
java.io.IOException: Server returned HTTP response code: 403 for URL:
というエラーが発生する.
そこで,下記のように,ヘッダを設定するとすんなり通る.

import java.io.*;
import java.net.*;

public class MyURLConnection {
public static void main(String[] args) {
try {
URL url = new URL("http://example.com");
URLConnection conn = url.openConnection();
/////////////////////////////////////////////////////
conn.setRequestProperty("User-agent","Mozilla/5.0");
/////////////////////////////////////////////////////
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}


これは,ヘッダが正しく設定されてないHTTPコネクションに対しては,サーバ側が受理しないことがあるため(よくわからないプログラムからアクセスされていると推測できる).
そこで,ヘッダを設定してあげると通る.

ということでいいのかな???

2010年4月25日日曜日

Androidでカメラ画像取得→ソケット転送

このエントリーをはてなブックマークに追加
Androidのカメラを使用したかったのでサンプルプログラムを書いてみた.

ついでに,取得した画像をPCにソケットで転送しPCのディスプレイ上で表示した.




以下,プログラム.
カメラ画像の取得については,↓のサイトを参考にした.
Androidメモ

画像の解像度は,デフォルトサイズでは,2048×1536(1M~1.2M)となり,転送に時間がかかったので,480×320に変更した.

[Android側-CameraTest.java]
package com.blogspot.ayakix_lablog.camera;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class CameraTest extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new CameraView(this));
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}


[Android側-CameraView.java]
package com.blogspot.ayakix_lablog.camera;
import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.BufferedOutputStream;
import java.net.Socket;

public class CameraView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holder; //ホルダー
private Camera camera; //カメラ
private static final int WIDTH = 480;
private static final int HEIGHT = 320;
private static final int PORT = 4680;
private static final String IP_ADDR = "1.1.1.1"; // IPアドレス

public CameraView(Context context) {
super(context);
// サーフェイスホルダーの生成
holder=getHolder();
holder.addCallback(this);
//プッシュバッッファの指定
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public void surfaceCreated(SurfaceHolder holder) {
// カメラの初期化
try {
camera=Camera.open();
camera.setPreviewDisplay(holder);
} catch (Exception e) {
}
}

public void surfaceChanged(SurfaceHolder holder,int format,int w,int h) {
// カメラのプレビュー開始
Camera.Parameters parameters=camera.getParameters();
parameters.setPictureSize(WIDTH, HEIGHT);
parameters.setPreviewFormat(PixelFormat.JPEG);
camera.setParameters(parameters);
camera.startPreview();
}

public void surfaceDestroyed(SurfaceHolder holder) {
// カメラのプレビュー停止
camera.setPreviewCallback(null);
camera.stopPreview();
camera.release();
camera=null;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction()==MotionEvent.ACTION_DOWN) {
takePicture();
camera.startPreview();
}
return true;
}

public void takePicture() {
// カメラのスクリーンショットの取得
camera.takePicture(null, null,new Camera.PictureCallback() {
public void onPictureTaken(byte[] data,Camera camera) {
sendData(getContext(), data);
}
});
}

private void sendData(Context context, byte[] data){
// ソケットの作成
Socket socket;
BufferedOutputStream out;
try{
socket = new Socket(IP_ADDR, PORT);
out = new BufferedOutputStream(socket.getOutputStream());
out.write(data);
if(out != null) out.close();
if(socket != null) socket.close();
} catch (Exception ex){
ex.printStackTrace();
}
}
}


[Android側-AndroidManifest.xml]















[PC側-Main.java]
import java.io.*;
import java.net.*;

public class Main {
private static final int PORT = 4680;

public static void main(String argv[]) {
System.out.println("サーバ起動");
int num = 0;
ServerSocket serverSocket = null;
while(true){
try {
// サーバーソケットの生成
if(serverSocket == null) serverSocket = new ServerSocket(PORT);
// クライアントからの接続を待ちます
Socket socket = serverSocket.accept();
BufferedOutputStream out = new BufferedOutputStream(
new FileOutputStream(new File(num + ".jpg")));
// 入力ストリームを取得
BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
byte[] buf = new byte[1024];
int len;
while((len=in.read(buf))!=-1){
out.write(buf, 0, len);
}
// GUIで画像を表示
new GUIExe(num);
// 入出力ストリームを閉じる
out.flush();
out.close();
in.close();
System.out.println("done");
// ソケットを閉じる
socket.close();
num++;
} catch(Exception e) {
e.printStackTrace();
}
}
}
}

class GUIExe extends Thread {
private int num;

public GUIExe(int num) {
this.num = num;
this.start();
// スレッド開始
}
public void run() {
new GUI(num);
}
}


[PC側-GUI.java]
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class GUI extends JFrame {
private int num;
private final int WIDTH = 480;
private final int HEIGHT = 320;

public GUI(int num){
this.num = num;
this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});

this.setBounds(0, 0, WIDTH, HEIGHT);
this.setLocation(num/3*WIDTH, num%3*HEIGHT);
this.setUndecorated(true);
this.setVisible(true);
}

public void paint(Graphics g){
Graphics2D g2 = (Graphics2D)g;
BufferedImage readImage = null;
try {
readImage = ImageIO.read(new File(num + ".jpg"));
} catch (Exception e) {
e.printStackTrace();
readImage = null;
}
if (readImage != null){
g2.drawImage(readImage, 0, 0, WIDTH, HEIGHT, this);
}
}
}

2010年4月15日木曜日

Firefoxアドオン-vimperatorのプラグインmulti_requester.js

このエントリーをはてなブックマークに追加
FirefoxのアドオンにVimperatorというものがあります.
[参考] 
Vimperator :: Add-ons for Firefox
Firefox Hacks:Vimperator――FirefoxをVim風のキーバインドで操作 - ITmedia エンタープライズ

デフォルトでもとても便利で重宝しているのですが,カスタマイズ性が高く,プラグインを導入することでより利便性が高まります.

今回はmulti_requester.jsというプラグインを導入したので,メモします.
[参考]
[vimperator]リクエスト結果をバッファ出力(muilti_requester.js) – suVeneのアレ

リンク先にもあるように,複数の検索ページからリクエスト結果をvimperatorのバッファ部分に出力することができます.

使用可能な検索エンジンは下記ページを参考にしてください.

アイテム - データベース: Multi Requester - wedata


検索エンジンの例を挙げます.カッコ内はコマンド例です.

 [alc (:mr alc 検索文字)]
 和英-英和辞書であるアルクからデータを引っ張ってきます.Webページで知らない単語があった場合,バッファに文字を出せるため,タブを切り替えたり ページを移動することなく,辞書をひくことができ,便利です.



[Yahoo 天気予報 (:mr weather-yahoo 地名or郵便番号 )]
Yahoo 天気予報からデータを引っ張ってきます.必要最小限のデータだけを引っ張ってくるので,見やすいです.


[php リファレンス検索 (:mr php-search 検索文字)]
phpの関数等を調べることができます.



ちなみに,multi_requester以外にも便利なプラグインがたくさんあります.
下記ページからダウンロードし, pluginフォルダの中にjsファイルを置くだけで使用可能となります.
/lang/javascript/vimperator-plugins/branches/2.2 – CodeRepos::Share – Trac

2010年2月1日月曜日

ArduinoにLCDを接続

このエントリーをはてなブックマークに追加
ArduinoにLCDを接続してみました.

まず,関連部品を購入します.
今回購入したのは,秋月電子から
LCDキャラクタディスプレイモジュール 20×4行バックライト付き
14Pフラットケーブル
小型ボリューム 5KΩB
です.
小型ボリュームは,LCDのコントラストを調整するためです.(作ってみてわかったのですが,コントラストを調整しないとちゃんと表示されません)

LCDはこんな感じ
 

まず,ハンダづけを行います.




久しぶりにハンダづけを行いました・・・ちょっと汚くなってしまった・・・.でもまぁ,OK
 ボリュームにも必要に応じてハンダづけを行います.
全体はこんな感じ




今回はボタンを押した回数をカウントするプログラムを作成してみました.


プログラムはこのようになります.

#include <LiquidCrystal.h>
#define BUTTON 9
#define LCD_ROWS 4
#define LCD_COLS 20

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int count = 0;
int before_button = LOW;

void disp_count(){
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Count :");
  lcd.print(count);
}

void setup(){
  pinMode(BUTTON, INPUT);
  lcd.begin(LCD_COLS, LCD_ROWS);
  lcd.clear();
  disp_count();
}

void loop(){
  int button_input = digitalRead(BUTTON);
  delay(10);
  
  if( before_button == LOW && button_input == HIGH){
    count++;
    disp_count();
  }
  before_button = button_input;
}

2010年1月30日土曜日

Arduinoで2進数カウンタ

このエントリーをはてなブックマークに追加
Arduinoを購入しました.
Arduinoは,基板(マイコンボード)と開発環境で構成されたフィジカルコンピューティングシステムです.

特徴としてオープンソースハードウェアであることが挙げられます.

Arduinoには用途に応じて様々な種類のボードが用意されていますが,今回購入したのは,一通りの基本機能を搭載したArduino Duemilanoveです.
Amazonにて「Arduinoをはじめようキット」を4200円で買いました.
付属品はこんな感じ
 
※Arduinoは,USB経由で給電とプログラムの書き込みを行うのですが,この「Arduinoをはじめようキット」にはUSBケーブルがついてません!!(はじめようキットなのに・・・)
そのため,自分でB端子のUSBを用意する必要があります.

Arduino本体はこんな感じ
・USB端子
・電源プラグ
・デジタル入出力ポート×14
・3.3V電源
・5V電源
・アナログ入力ポート×6
・アナログ出力ポート×6
・リセットスイッチ(プログラムを初めから実行する)
・モニター用端子
 


開発環境のダウンロードは下記サイトから行えます.お使いのOSに合ったファイルをダウンロードしてください.
http://arduino.cc/en/Main/Software

Windowsの場合,arduino-00**.zipをダウンロードするかと思います.
展開してから,arduino.exeをダブルクリックしてください.これだけで実装環境の構築が終わりました.
※arduino.exeはJavaVM上で動作します.そのため,事前にJavaをインストールする必要があります.

プログラムの実行手順は下記の通りです.
1. プログラムを記述
2. エラーがないか確認(一番左のVerifyボタン)
3. アップロード(右から2番目のUploadボタン)
うまくアップロードできると,Arduinoが点滅します.
もし,アップロード時にエラーがでるようでしたら,デバイスマネージャにて,正しくデバドラがインストールされているか,また,接続されているCOMポートの番号と実装環境のTools->Serial Portで選択されているCOMポートの番号が一致しているかを確かめてください.

試しに,付属の光素子とスイッチを使用して光に反応する2進数カウンタを作ってみました.
ちょっとわかりにくいですが・・・



ソースはこちら
C-likeですね.define部分は接続した入出力ポートに合わせてください.
setup関数は一番初めに一度だけ実行される関数.loop関数はプログラムの本体となり,ここに記述されている内容が繰り返し実行されます.

#define LED3 8
#define LED2 7
#define LED1 6
#define BUTTON 9
#define INTERVAL 10
#define CDS 10

int count = 0;
int before_cds = LOW;

void setup(){
  pinMode(LED3, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED1, OUTPUT);
  pinMode(BUTTON, INPUT);
  pinMode(CDS, INPUT);
}
void check_count(){
  if((count & 4) == 4){
    digitalWrite(LED3, HIGH);
  } else {
    digitalWrite(LED3, LOW);
  }
  if((count & 2) == 2){
    digitalWrite(LED2, HIGH);
  } else {
    digitalWrite(LED2, LOW);
  }
  if((count & 1) == 1){
    digitalWrite(LED1, HIGH);
  } else {
    digitalWrite(LED1, LOW);
  }
}

void loop(){
  int cds_input = digitalRead(CDS);
  int button_input = digitalRead(BUTTON);
  delay(INTERVAL);
  
  if(cds_input != before_cds){
    before_cds = cds_input;
    if(cds_input == HIGH){
      count++;
    }
  }
  check_count();
  
  if( button_input == HIGH ){
    count = 0;
    check_count();
  }
}