2012年12月25日火曜日

Java Singletonパターンってなに?

こんにちは、B13の小林です
まさかのトリです。びっくりしました
今回は、自分の復習も兼ねてSingletonパターンについて書いてみたいと思います。

Singletonパターンって何?

オブジェクト指向プログラミングでのデザインパターンの一つです。
デザインパターンとは、プログラミングをするときによく直面する問題と、
その解決策をテンプレート化したものの集まりです。
要するにプログラミングの先輩たちが
「俺たちがよく見る問題をきれいに解決する方法
に名前を付けたから、参考にしてね!」
っていうやつです。

で、Singletonパターンは「インスタンスを一つしか生成したくない!」という問題を解決する
方法を記したパターンです。

方法を元に作ったプログラムはこちらになります。

class Singleton{
 private static Singleton instance = new Singleton();

 private Singleton(){}

 public static Singleton getInstance(){
  return instance;
 }
 //この後に使いたいメソッドやフィールドを追加していく
 }

あらかじめinstanceに自分自身を生成しておき、 getInstance()が呼び出されたときに
それを返します。
コンストラクタとinstanceがprivateなので、 getInstance()を使わないとアクセスできないため、
インスタンスを一つしか生成できない形になっています。

 

Singletonパターンはどう役立つの?

インスタンスを2つ以上生成してもムダが増えるだけの場合や
生成時の初期化に時間にかかる場合、
サーバ等のマルチスレッド環境で同じリソースを扱いたい場合
にSingletonパターンを使ってみるといいと思います
しかし、これは個人製作や小規模のプログラムでは必要ないことも多いです。
newを一回しかしないっていうことを守っておけばいいのですから。
なので、特に役立つ場面は
 「インスタンスを一つしか生成したくない!」ということを
「このプログラムに携わる人に知ってもらいたい時」
だと思います。

使う時に気を付けることは?

一つだけ、僕が実際にやったミスを紹介します。
サーバ構築時に上のプログラムを書き換えて
class Singleton{
 private static Singleton instance = null;

 private Singleton(){//いろいろ結構多め}

 public static Singleton getInstance(){
  if(instance == null){
   instance = new Singleton();
  }
  return instance;
 }
 //いろいろ
 }

と「このクラスを最初に使う場合だけ生成する」と書き換えました。
そうするとマルチスレッドのため、同時にgetInstance()を実行される場合があり、
結果的にインスタンスが2つ以上作られてしまったというのがありました。
そうなるとシングルトンの意味がないので、使う際には気を付けてください

まとめ  

Singletonパターンについて書いていきました。 これにかぎらず、デザインパターンは知っていれば、いざ出くわしたときに
「このクラスはこういうことをさせたいんです!」という作った人の意図をスムーズに理解する
ことができると思います。

以上で終わります
ありがとうございました。

2012年12月24日月曜日

僕の彼女を紹介しつつPHPでJSONファイルを扱います!

B13の笹本(偽名)こと大矢です。
今日はアレですね!アレ!という事で今日は僕の彼女を紹介します
こちらが彼女の写真です。ウェブサイトも持っているようです。見てあげてください。
紹介はこのくらいにします。本日はどうも、ありがとうございました。

などとここで終わらせる勇気が無かったのでPHPでのJSONファイルの扱い方について紹介しようと思います。こちらの記事をかなーり参考にしてPHPで使えるJSONクラスを作ってみました。

機能としてはJSONファイルを連想配列として読み込み、追加の処理を行い、また連想配列をJSON文字列として変換し保存する事ができます。
動作としてはコンストラクタの引数から得たファイル名でJSONデータを読み込み、addメソッドでデータを追加し、saveメソッドでJSONデータをファイルとして保存、closeメソッドでファイルを閉じています。ソースコードは以下のような感じです。

class Json {
 private $data;
 private $fp;
 private $filename;
 private $path = "./";

 public function __construct($name){

  $this->filename = $this->path . $name;
  $this->fp = fopen($this->filename,"r+");
  
  if(file_exists($this->filename)){
   flock($this->fp,LOCK_EX);
   $this->data = json_decode(fread($this->fp, filesize($this->filename)));

  }else{
   $this->data = array();
  }
 }

 public function add($data){
  array_push($this->data,$data);
 }

 public function save(){
  $this->fp = fopen($this->filename,"wb");
  fwrite($this->fp,json_encode($this->data));
 }

 public function close(){
  flock($this->fp, LOCK_UN);
  fclose($this->fp);
 }

}

このクラスを用いると以下のような感じになります。


$json = new Json("test.json");

$post_data = array("name" => "笹本","text" => "テストだよ");

$json->add($post_data);

$json->save();
$json->close();

上記の処理でname属性の『笹本』、test属性の『テストだよ』という文字列が『test.json』ファイルに追加されています。これをPOSTのデータ等が追加されるように変更していけば色々な物が作れそうです。

PHPでJsonを扱うには『json_decode』関数と『json_encode』関数を使用しています。 『json_decode』はJSON文字列を連想配列データとして変換。
『json_encode』は連想配列データをJSON文字列に変換してくれます。
MySQLなどのデータも連想配列で返ってくるのでこの関数とデータベースを組み合わせると、よりよくわからない物ができそうです。

ちなみに坂井くんの彼女はこの子らしいです、誰かが言っていました。怒られたら消します。ありがとうございました。

2012年12月23日日曜日

daemontools,使ってますか?(中編)

murayです.23日も終わりに近づいていますが,daemontools使ってますか?(中編)です.

さっそくですが,daemontoolsをインストールしてみましょう.

とりあえずはこのページの通りに,現時点での最新版を落として展開します.
# sudo -i
# curl -O http://cr.yp.to/daemontools/daemontools-0.76.tar.gz
# tar zxvf daemontools-0.76.tar.gz
# cd admin/daemontools-0.76

手順に従ってインストールしてみます.

# ./package/install
Linking ./src/* into ./compile...
Compiling everything in ./compile...
./load envdir unix.a byte.a 
/usr/bin/ld: errno: TLS definition in /lib64/libc.so.6 section .tbss mismatches non-TLS reference in envdir.o
/lib64/libc.so.6: could not read symbols: Bad value
collect2: ld はステータス 1 で終了しました
make: *** [envdir] エラー 1
ダメでした...現在のdaemontoolsは,インストールする前にパッチを当てる必要があります.パッチはここにあります.

# curl -O http://djbware.csi.hu/patches/daemontools-0.76.errno.patch
# patch -p1 < daemontools-0.76.errno.patch
patching file src/error.h

再挑戦します.

# ./package/install
...
Copying commands into ./command...
Creating symlink daemontools -> daemontools-0.76...
Making command links in /command...
Making compatibility links in /usr/local/bin...
Creating /service...
Adding svscanboot to inittab...
init should start svscan now.

今度は成功しました.

さて,本来はこの時点で/etc/inittabにsvscanbootというコマンドが実行されるように書き込まれ,svscanというプログラムが実行されているはずなのですが,なぜか私の環境では(再起動しても)動きませんでした.
そこで,svscanの起動を直接制御できるよう,/etc/init.d/以下に,起動スクリプトを作成しました.

#!/bin/sh
. /etc/init.d/functions

PATH=/usr/local/bin:$PATH

start() {
  if [ -e /var/lock/subsys/svscan ]; then
    action "svscan lockfile exists /var/lock/subsys/svscan: " /bin/false
  else
    action "Starting svscan: " /bin/true
    touch /var/lock/subsys/svscan
    exec env - PATH="$PATH" \
    sh -c 'svscan /service & echo $! > /var/run/svscan.pid'
  fi
}

stop_each_svc() {
  if ls /service/* > /dev/null 2>&1; then
    for s in /service/*; do
      svc -dx $s
      action "Stopping $s: " /bin/true
      if [ -e $s/log ]; then
        svc -dx $s/log
        action "Stopping $s/log" /bin/true
      fi
    done
  fi
}

stop() {
  if [ -f /var/run/svscan.pid ]; then
    kill `cat /var/run/svscan.pid`
    stop_each_svc

    rm -f /var/run/svscan.pid
    rm -f /var/lock/subsys/svscan
    action "Stopping svscan: " /bin/true
  fi
}


case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        stop
        start
        ;;
  *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
esac

exit 0
さて,実際にサービスをdaemontools管理下に入れてみます.動かしたいサービスのディレクトリ等に,serviceというディレクトリを作成し,runという名前の実行可能スクリプトを配置します.このスクリプトにはサービスの起動に必要な処理を記述します.

$ sudo su - bot
$ mkdir some_bot/service
$ vi some_bot/service/run
#!/bin/sh

cd /home/bot/some_bot # サービスディレクトリに移動
exec ./bin/bot.pl 2>&1 # サービスを起動するコマンド

$ chmod +x some_bot/service/run
このserviceディレクトリが,daemontoolsにとっての1つの管理対象になります.runスクリプトを作成したら,/serviceディレクトリに,シンボリックリンクを作成します.

$ sudo ln -s /home/bot/some_bot/service /service

svscanは5秒に1度/serviceを参照するため,これで5秒以内にはrunスクリプトが実行され,サービスが起動されます.

サービスの起動,停止,再起動は,svcコマンドで制御することができます.

$ svc -u some_bot/service # 起動
$ svc -d some_bot/service # 停止
$ svc -t some_bot/service # 再起動

23日の終わりが迫ってきてしまったので,今日はここまで...今回で終わりの予定でしたが,まだいくつか話したいことがあるのでadvent calendar終了後に最終編を書きたいと思います.

2012年12月22日土曜日

jQuery purupuru.js の作り方

こんばんは みたび Fuya です。
きょうはjQueryでプラグインを作ったので紹介したいと思います.
あなたは、jQueryでぷるぷるさせたい事ありますか?
とくに冬至は入力フォームをプルプルさせたい衝動に駆られますよね。

2012年12月21日金曜日

SVG

田胡研で最も低スペックだと自覚している B13 若林 遼です。

正直、自分から皆様に技術的なことを言えることがほとんどないです・・・

なので今回は自分が少しかじっているSVGについて簡単に紹介していきたいと思います。

まずSVGとは・・・?

SVG(Scalable Vector Graphics<スケーラブル・ベクター・グラフィックス>)の略称。・・・らしい。
ベクター方式で2次元グラフィックスを表現するためのXMLベースの言語。


 SVGは、JPEGやPNGなどと異なり、点(ビットマップなど)で画像を表現するのではなく、直線や曲線(ベクター)で画像をWeb上で表現する技術です。
 SVGは、パスの情報だけで描画しているらしく、どれだけ拡大とかしても画質が崩れないそうです。印刷品質を問われる場合などに適しているみたいです。
 HTML5で登場したCanvasに比べて広範囲の描画に適していて、ボタンなどのインターフェース簿品が作りやすいという利点があります。

 

・・・では、簡単に表示したいと思います。
まず、赤い丸の画像を描画し、ボタンを押すと赤い丸が横に移動する簡単なプログラムを作りたいと思います。

HTMLはこんな感じです。↓



JavaScriptはこんな感じです。↓

 以上のプログラムを実行する↓のように表示されるはずです。
 画像なので止まっていますが、ボタンを押すとちゃんと動いてくれます。

















 SVGは専用のjQueryのライブラリ(?)みたいなのがあるのでそれを使うともっと楽に描画やアニメーション機能を使えるようになります。
 詳しく知りたい人は、↓のURLからDLできるので落としてみてください。(英語ですがリファレンスにもなっているので参考になります。)

lhttp://keith-wood.name/svg.html

 私自身のwikiにもわかりやすそうなSVG関係のサイトのURLがありますのでそれも参考にしてみてください。

 今現在このSVGのjsを使ってSVG画像を動かそうと頑張っているところです。
 こんなの↓

今後進展がありましたら、ブログやwikiにあげていきたいと思います。

 最後まで読んでいただきありがとうございました。

2012年12月20日木曜日

Chromeさんの拡張機能をつくろうね

ふたたび Fuya です. 
今日はChrome拡張機能について簡単に紹介したいと思います. 皆さん御存知の通り,Chromeの拡張機能はJavaScriptから出来ています. 
つくりかたを書いて行きたいと思います.

2012年12月19日水曜日

誰でもできる?ターミナル環境設定

どうも!
田胡研b3のnashioこと水野です。


3年生は研究室で活動するようになってから早3ヶ月が経とうとしていますがみんなは今何をやっているのかな?
僕自身はサーバ構築を主にやってきましたがその過程でターミナル環境を整えることがいかに大事かを痛感してきました。

そこでそこで!
研究室でターミナル(特にcygwin)をはじめて使うようになった3年生がたくさんいると思うので(いるよね?)
そういった初心者向けのターミナル環境設定法を紹介したいと思います。


上にも書いたように今回は初心者向けです!
「bashrc、vimrcがんがん編集してるわ!」という人や、「bash?いまどきzshだろ!」という人向けではないのでご了承ください。

今までの話を聞いてさっぱりな人たち!
ターミナル環境の世界へようこそ!

alias設定編

まずはターミナルの調教から始めましょう!

ターミナル環境にはaliasというコマンドがあります。
aliasとは、簡単に言えばターミナルで実行するコマンドにニックネームをつけるモノです。
使い方はターミナルで
alias nickname='command'
と打つだけです。
例えば、
alias hoge='ssh sample.t-lab.cs.teu.ac.jp -l sample'
こうすれば、hogeとターミナルで打つだけでsshできちゃいます。

簡単に自分だけのコマンドや長いコマンドのショートカットを作ることが出来ましたね。調教完了!


しかし、このままでは一度ターミナルを閉じてしまうとaliasが利かなくなってしまいます。

そこで、次は常にターミナルから実行されるようにしましょう。
やり方は
cd
vi .bashrc

これで、.bashrcファイルにaliasを書き込んでいきます。こうすることで常に実行されるようになります。

aliasは自分が使いやすいように調教することが大切です。

普段良く使うコマンド(よく同じサーバにsshする人はsshコマンド、lsにいつもオプションをつけている人はオプション付きで)を登録しましょう。
(いたずらで人のターミナルに設定するのはやめましょうw)


「そんなもんないよ!」という人は以下の設定だけでも書いてみてください。
alias ls='ls --color=auto'
function cdls(){
    \cd $1;
    ls;
}
alias cd=cdls
alias vi=vim
こうすることで、lsをするとファイルとディレクトリ等を色分けして表示するようになる、cdをすると自動的にlsもするようになる、viをコマンドをvimコマンドに書き換える設定です。
こんな感じになり、個人的にこれはおすすめなのでやってみてください。

vimrc設定

vimrcとはテキストエディタvimの設定ファイルです。vimは設定次第で最強のエディタになると言われています。次はvimrcの設定をして行きましょう。

といってもvimの設定は奥が深く自分もほぼ初心者なので簡単な設定のみを紹介します。
設定方法は
cd
vi .vimrc
でファイルに設定を書きこんでいきます。
書きこむ設定は
" カーソルが何行目の何列目に置かれているかを表示する
set ruler
" ステータス行を常に表示する
set laststatus=2
" すべてのモードでマウスが有効
set mouse=a
" 行番号を表示する。
set number
" 閉じ括弧が入力されたとき、対応する開き括弧にわずかの間ジャンプする
set showmatch
" 新しい行を開始したときに、新しい行のインデントを現在行と同じ量にする
set autoindent
" 新しい行を作ったときに高度な自動インデントを行う
set smartindent
" tab が対応する空白の数。
set tabstop=4
" tab の挿入や bs の使用等の編集操作をするときに、tab が対応する空白の数。
set softtabstop=4
" インデントの各段階に使われる空白の数
set shiftwidth=4
" Insertモードで tab を挿入するとき、代わりに適切な数の空白を使う。(有効:expandtab/無効:noexpandtab)
set noexpandtab
" Insertモードで tab を挿入するのに、適切な数の空白を使う
set expandtab 
" 行頭の余白内で Tab を打ち込むと、'shiftwidth' の数だけインデントする
set smarttab
" 検索コマンドを打ち込んでいる間にも、打ち込んだところまでのパターンがマッチするテキストを、すぐに表示する
set incsearch
ものすごく適当に設定を羅列してしまいましたが、このままコピペでもよし、自分に必要なものだけを設定するもよしです。



aliasの設定やvimrcの設定は様々な人が設定を公開していたり、githubにアップしていたりするので「極めたい!」というひとは自分で調べてみてくださいね。

2012年12月18日火曜日

CSS3を駆使して描く!「Donatello」

皆さんこんにちは!B3の坂井(mozuku)です.
AdventCalenderも、もう残り一週間となりました.

普段はWeb班では無いですが、今回はWebっぽいコンテンツ
ドローライブラリ「Donatello」を紹介したいと思います!

Donatelloって?
Donatelloは幾何学模様をJavaScript,CSS3で描くドローライブラリです.
ブラウザ上にどれくらいキレイなグラフィックスを書けるのか,いかに手軽に実現できるのかHTML5によって広がった描画の幅を知るのに最適なライブラリです.

CanvasではなくCSS3で描画するところに「Donatello」の面白さはあるとおもいます!

Canvasの簡単なおさらい
比較にも出したことなのでCanvasも簡単なおさらいをしましょう.
*Canvas Sample
$(document).ready(function(){

 /*create CanvasElement*/
 $('body').append('');
 
 /*create 2d context obj*/
 var context = $('canvas').get(0).getContext('2d'); 

 /*draw square*/ 
 context.beginPath();
 context.moveTo(20,20);
 context.lineTo(120,20);
 context.lineTo(120,120);
 context.lineTo(20,120);
 context.closePath();
 context.stroke();

});

ソースコードの内容はこんな感じです.
beginPath:描画開始宣言
moveTo:始点座標の指定
lineTo:終点座標の指定
closePath:描画終了宣言

このソースコードで図のような描画ができます.
lineTo等を見ればわかるとおり、座標位置等を意識し描画しています.
ここでの肝は「ソースから安易には正方形だとは読みとれないこと」です.

Donatelloで描画してみる
百聞は一見に如かずサンプルをとりあえずみてみましょう.
*Donatello Sample
$(document).ready(function(){
 /*Convert DOM Element*/
 var paper = Donatello.paper('paper-div', 20, 20, 500, 500);
 /*draw ellipse*/
 var ellipse = paper.ellipse(250, 250, 120, 75, {
  'stroke-width':4,
  'stloke': '#FFFFFF'
 });
 
});

Donatelloは上記のような形で記述します.
Donatelloの描画領域はpaperと呼ばれ、DOM要素となっています.
また、描画される要素も個々にDOM要素として描画されます。

複雑な例ではこのような描画が可能です.
for( var i=0; i < 8; i ++ ) {
    var x = Math.cos( i*Math.PI/4 )*r;
    var y = Math.sin( i*Math.PI/4 )*r;
    var circle = paper.ellipse( 250 + x, 250 + y, 120, 75, { 
        'stroke-width': 4*i,
        'stroke': colors[i%8],
        'stroke-style': 'solid'
    });
    ellipse.rotate( (i*Math.PI/4)*180/Math.PI );
}

このソースであれば、以下の図のような描画が行えます。

ここでDonatelloを使う4つの利点をあげたいと思います.
・描画領域は'紙'と呼ばれる一つのオブジェクトとして管理されること
・四角や円、楕円、多角形といった形を描画するという仕組み→コードの理解が安易
・描画された形は一つのオブジェクトであること
・jQuery等外部ライブラリへの対応


特に3つ目の1つ1つがオブジェクトであるという点はCanvasでの描画と違い、一度描いたものの一部分だけを操作できる等の利点であるといえます.


まとめ
Webデザイナー等にとってはCSS等の知識を使って扱えるDonatelloは便利かも
CanvasだけがHTML5での描画方法じゃない!
(SVG⇔Donatello変換ソフトウェアとかあったら便利そう!)←言うのはタダ


これだけじゃなくHTML5と総括される技術分野は様々なチャレンジ要素があるとおもいます。
Web系なみなさんどんどん遊びましょう!(そして面白いことを紹介してください!)

記事を見て気になったら↓
dnewcome/Donatello - Github


そんなこんなで本当に触りだけとなりましたが、Donatelloのご紹介とさせていただきます.

以上mozukuでした!

2012年12月17日月曜日

wiiリモコンのJavaScript

こんにちは!倉本です.
enchant.jsについて紹介しようかと思ったのですが,
西崎君に先を越されたのでwiiリモコンのJavaScriptについて書きます!

wiiインターネットチャンネルでは,特別なオブジェクトを用いるだけで,
wiiリモコンのひねりやセンサーバーとの距離を簡単に取得できます.

window.opera.wiiremote オブジェクト

これがwiiリモコンのプロパティを保持したオブジェクトになります.
このオブジェクトのupdate(num)というメソッドを呼び出すことで
リモコンの状態を保持したオブジェクトが返ってきます.
numはプレイヤーの番号で,0~3の数字を指定します.
オブジェクトのプロパティは以下の一覧の通りです.

    
プロパティ 説明
isEnabled wiiリモコンが接続されている場合,1.
isDataValid データが有効な場合,1.
isBrowsing ブラウジングしているwiiリモコンの場合,1
dpdX
dpdY
ポインティング位置.
hold ボタンを押している間,対応したボタンのフラグが立つ.
※ブラウジングしているwiiリモコン(isBrowsing が1であるwiiリモコン)は
 Bボタンのみ取得できる.
dpdRollX
dpdRollY
カーソルの傾き方向ベクトル.
ベクトルの長さは 1 ,右下がプラス方向.
dpdDistance センサーバーとwiiリモコンの距離.遠いほど大きい値になる.
dpdValidity ポインティング位置を認識するために用いたオブジェクトの個数.

それでは,実際に使ってみるために以下のようにJavaScriptをかいてみました.

(function(){
 var defaultDistance = 0;
 $(document).ready(function(){
  setInterval('UpdateWiiRemote()', 100);
 });
 function UpdateWiiRemote(){
  var pad = opera.wiiremote.update(0);
  if (pad.isEnabled && pad.isDataValid){
   if(defaultDistance == 0){
    defaultDistance = round2(pad.dpdDistance);
   }
   if(round2(rad * 180 / Math.PI) >= 45){
    $("#action").html("右!");
   }
   else if(-45 >= round2(rad * 180 / Math.PI)){
    $("#action").html("左!");
   }
   else if(defaultDistance-0.2 >= round2(pad.dpdDistance)){
    $("#action").html("前!");
   }
   else if(round2(pad.dpdDistance) >= defaultDistance+0.15){
    $("#action").html("後!");
   }
   else{
    $("#action").html("ストップ");
   }
  }
  else{
   $("#action").html("未接続");
  }
 }
 function round2(v){
  return Math.round(v*100)/100;
 }
})();

簡単に解説しますと,
・opera.wiiremote.update(0)で1Pのwiiリモコンの情報取得.
・isEnabledとisDataValidでwiiリモコンが接続されていて,データが有効か確認.
・有効であった場合,そのプロパティに応じてアクションを判定.
以上をsetIntervalでまわします.

アクションついて,
傾きは左右どちらかに45度以上傾いているかどうかで判断します.
距離は最初に1度,デフォルト距離としてセンサーバーとwiiリモコンの距離を保持しておき,それと現在の距離を比べて判断します.

こんな感じで傾きと距離の判定を活かして,アクションゲームっぽいのが作れそうですね!
誰かやってみてください!(他力本願)

お粗末な内容でしたが最後まで読んでくれた方,ありがとうございました.


2012年12月16日日曜日

私が田胡研サーバを仮想化したわけ : |┃

みんなー!! 文化して (ry

こんにちわ,何故か2度目の登場 sakura です.
田胡研アドベントカレンダーも 16日目 となりました.

本来であれば,2度目は田胡研ファイル鯖のファイルシステムについて書こうかなーと思っていたのですが,前回の記事が長くなってしまったので,前回 (7日目:私が田胡研サーバを仮想化したわけ:序) の続きを書いていきます.

もう一度前回の記事を読んでもらえればわかると思いますが,前回 「バックアップの簡略化」 について書いていないので,今回はそれに関係する事を主に書いていきます,

2012年12月15日土曜日

daemontools,使ってますか?(前編)

 kawaです.

daemontoolsって知ってますか?

簡単に言えば,ソフトウェアをサービスとして動かしたいときに使えるdaemonizeツールキットという感じでしょうか.

daemonと聞くと,「UnixなどのOSにおいて,fork&execしたプロセスから切り離されてinitプロセスの子供となりバックグラウンドで動作するプロセス」という正しそうな定義を述べることができる人も入れば,「/etc/init.d/httpd start ってやったら動くやつでしょ」などという程度の理解の人もいると思います.

一般に,Unixの世界におけるdaemonといえば,(familyやディストリビューション等によって場所は異なることもありますが)/etc/init.d/以下に起動スクリプトがあって,起動するとバックグラウンドで動作して,なんらかのサービスを内外に向けて提供するソフトウェアないしプロセスを指します.例を挙げるなら,httpd(Apache http server)やmysqld(mysql server),crond(cronを定期実行してくれるサービス),syslogd(システムロギングを提供するサービス)などがありますよね.

さて,我々が普段作成するソフトウェアでも,daemon化したいなーと思うものはたくさんあります.例えば最近私が作った物では,IRCのbotなんかそうですね.

IRCのbotは,起動したらこちらの意思で終了するかシステム自体をshutdownしたりrebootするまでずっと動いていてほしいので,まさにdaemonとして動いてほしいわけです.

しかし,前述したような意味での"daemon"化は,ちょっとめんどくさいのです.Wikipediaに,daemon化するための手順が簡単に書かれていますが,ちょっと面倒ですよね.

また,作成するプログラム自体に,daemonとして動作させるためのコードを記述するよりも,実行者がdaemonとして起動するのか,普通のforeground processとして起動するのかを選択できたほうが,開発するとき便利です.

daemonとして記述されてない普通の実行可能ファイルを,手軽にdaemonライクに動かすことができる便利なコマンドとして,nohupがあります.

$ nohup <command> > /dev/null 2>&1 &

nohupコマンドは,引数として与えたコマンドを実行してくれます.なぜそれがdaemonのように振る舞うのでしょうか.それには,Unixにおけるプロセスについて少しお勉強が必要です.

Terminalからコマンドとして実行されたプロセスは,親プロセスの終了と同時に死んでしまいます.つまり,みなさんよくご存知の,バックグラウンドプロセスを生成する魔法"&"を用いた以下のようなコマンド実行では,プロセスをバックグラウンドで動かすことは可能ですが,実行したシェルが終了したと同時にバックグラウンドプロセスも終了してしますのです.

$ <command> &

これは,親プロセスが終了すると,子プロセスにはSIGHUPというシグナルが送られるためです.これを受け取ると特別シグナルハンドリングをしていないプロセスは終了するようになっています.nohupコマンドは,引数として受け取ったコマンドを,このSIGHUPを無視するようにして実行してくれるのです.

nohupで起動されたプロセスの挙動を,プロセスヒエラルキーをわかりやすく表示してくれる,ps axjfで確認してみましょう.無限ループを実行するperlワンライナーを実行してみます.

 $ nohup perl -e ' 1 while 1 ' > /dev/null 2>&1 &

nohupを用いて起動したプロセスは,親であるzshプロセスが生きている間は,以下のようにzshの子プロセスとして動作しています.

 $ ps axjf
 ...
20872 20873 20873 20873 pts/8    21019 Ss    1000   0:00  \_ zsh
20873 21012 21012 20873 pts/8    21019 RN    1000   0:23      \_ perl -e  1 while 1
 ...

しかし,ひとたびzshプロセスを終了させると,以下のようにどのttyにも所属せず,プロセスヒエラルキーにおいてもトップレベル,つまり,initプロセス子プロセスとして動作していることが分かります.

$ ps axjf
...
1 21012 21012 20873 ?           -1 RN    1000   0:45 perl -e  1 while 1  
...

nohupを用いることで,とりあえずdaemonなプロセスは作れますが,実際は,daemonをまとめて管理する機構がないと不便です.例えば,システムのboot後にdaemonを起動してくれたり,daemonの出力するログを取ってくれたり,起動,停止,再起動を制御したりといったことです.

これらを,面倒なdaemon化コードを記述したり,複雑な起動スクリプト(/etc/init.d/ にあるような)をいちいち記述しなくても可能にしてくれるのが,daemontoolsなのです.

前編ではUnixにおけるdaemonについてのお話になってしまいましたが,後編ではdaemontoolsのインストールから使用法,たごけんで動いているいくつかのサービスの例を紹介したいと思います.

2012年12月14日金曜日

csonv.jsを使ってみる

こんにちは.14日担当の與那覇です.

今回は「csonv.js」の紹介をしたいと思います.
これは,CSV形式のデータをJSON形式に変換してくれるJavaScriptライブラリです.

使い方はとっても簡単,任意のファイル名を以下のように指定してやるだけです.
var data = 'hoge.csv'.toObjects();
これで「hoge.csv」ファイルの中身のCSV形式のデータがJSON形式で出力されるようになります.便利!

しかしこの「csonv.js」,いくつか落とし穴があります.

「csonv.js」で扱うCSVファイルは少々特殊な書き方をしなければなりません.
読み込むファイルは以下のような書き方をします.
id;name;age
integer;string;integer
1;Mike;20
2;Kate;18
1行目はJSONのキー名,2行目は値の形式です.データそのものは3行目以降に記述します. 数値ならば「integer」,文字ならば「string」と設定してやらなければいけません. この値を複数形(ex. strings)にしてやると,1つのキーに対し複数の値を指定することが出来ます.


id;name;age;like
integer;string;integer;strings
1;Mike;20;running,touring
2;Kate;18;reading,swimming
また,サンプルに示している通り,データのセパレータにはセミコロンが使用されています. ExcelファイルでCSVファイルを作成すると,セパレーターはデフォルトでカンマが付きます.
また,カンマは1つのキーで複数のデータを扱う際のセパレーターになっているので,Terapad等で開いて置換する,というのも面倒になります.
というわけで,JSのほうを少々弄ることにします.
「csonv.js」ファイル内,149行目辺りにセパレーターの指定があるので,columnを「,」,arrayを「;」に変更します.

これでExcelでCSVファイルを作っても利用できるようになります. ExcelからCSVファイルを作ると,最後に空行が出来てしまうので,それは削除しておきましょう.

既存の技術をカスタマイズして使いやすくするのもなかなか楽しいですね.

2012年12月13日木曜日

enchant.jsでプログラミング!

enchant.jsとは?

HTML5とJavaScriptで簡単にゲームが作れるライブラリです! 以上.

ハッカソンでぼくが作ったくまのゲームをベースに説明していきます.

・どんなゲームか?

 画面中央にいるひらめに,くまが当たるとくまが消えます.それを回避しゴールまでくまを導くのがゲームの趣旨です.



・操作方法
 ゲームで下のくま達は基本的に右側に走ります.くまをクリックしてやることによりランダムでくまを動かすことが出来ます.

因みに,ひらめもPCの十字キーを使い操作できます.


HTMLはbodyの中に何も書きません.headに準備くらいですね.
ぼくはこんな感じでで書きました.

 






↑<body>の中身を書かないのはきれい好きです.

続いて,javascript

enchant();
window.onload = function(){
    var i;
    var game = new Game(320, 320);
    var directx =1;
    var directy =1;
    

    game.fps = 10;
    game.preload("chara1.png");
    game.preload("hirame.gif");
    game.onload = function(){
    
        //hirame
        hirame = new Sprite(32, 32);
        hirame.image = game.assets["hirame.gif"];
        hirame.x = 280;
        hirame.y = 60;
       
        hirame.frame = 5;
        game.rootScene.addChild(hirame);
        //kuma
        newbear = new Array();
        for(i =0; i <= 40; i++){
            newbear[i] = new Sprite(32, 32);
            newbear[i].image = game.assets["chara1.png"];
            newbear[i].x = 0;
            newbear[i].y = i*32;
            newbear[i].frame = 5;
            game.rootScene.addChild(newbear[i]);
        
        
            newbear[i].addEventListener("enterframe", function(){
                this.x += 1;
                this.frame = this.age % 2 + 6;
                if(this.x > 320){
                    var uho ="
クリア!
"; $("body").append(uho); $("div#kuria").css("color","blue"); game.stop(); } if(this.within(hirame, 40)) { game.rootScene.removeChild(this); } }); newbear[i].addEventListener("touchstart", function(){ this.x += Math.random()*10; this.y += Math.random()*10; this.frame = this.age % 2 + 6; }); } hirame.addEventListener("enterframe", function(){ hirame.x -=15*directx; hirame.y -=15*directy; }); hirame.addEventListener(Event.ENTER_FRAME, function(){ if (game.input.left && (hirame.x > 0)){ hirame.x = hirame.x - 30; } if (game.input.right && (hirame.x < game.width-hirame.width)){ hirame.x = hirame.x + 30; } if (game.input.down && (hirame.y > 0)){ hirame.y = hirame.y + 30; } if (game.input.up && (hirame.y < game.width-hirame.width)){ hirame.y = hirame.y - 30; } }); hirame.addEventListener(Event.ENTER_FRAME, function(){ // 画面外かどうか調べる if ((hirame.x < 0) || (hirame.x > (game.width-hirame.width))){ directx = directx * -1; } if ((hirame.y < 0) || (hirame.y > (game.height-hirame.height))){ directy = directy * -1; } }); }; game.start(); };


説明
1行目ではenchant.jsの呼び出しです.
3~6行目は変数宣言です.4行目は画面の大きさ設定でブラウザの左上からx軸y軸ともどもに320px設定しました.
9行目は1秒間に何回画面が更新されるかです.10回に設定してます.
10,11行目はくまとひらめ(キャラクター)の画像の先読み込みです.
15行目はひらめの大きさ指定です.4行目と同じ形で指定してます.
16行目は11行目でpreloadした画像を指定しています.
17,18行目はひらめの初期ポジションです.17行目はx軸,18行目はy軸を設定してます.
21行目のrootSceneとはgameオブジェクトにはデフォルトであたえられている1つの Scene オブジェクトです.
今回はSceneという機能を使わなかったのですが,RPG等でいうとバトル前→バトル→バトル後みたいに画面がかわりますよね.そういうことができる機能です.
33行目は"enterframe"というイベントが起きたときの処理を書いています.
36~43行目はクリアになった時の処理です.
42行目はゲームが終わりになる処理です.
44行目はひらめとくまが当たったときの処理です.
45行目のremoveChildでくまが消えます.
48行目はマウスでクリックしたときの処理です.
61~74行目はボタンイベントです.game.input.○○で○○のボタンを押したときの処理がかけます.
75行目~83行目はひらめが画面外に消えそうになったら方向を帰る処理です.
85行目はgameスタートの処理です.

以上です!
簡単なので是非やってみてください!





2012年12月12日水曜日

ディレクトリの監視!

どもども。内山です。
今日はレーシングバイクのすばらしさについ書きます

ラッキーストライクカラーのバイクとライダーは、
SUZUKI RGV-Γ / ケビン・シュワンツ
という、1988年から1995年までの8シーズンでGP通算25勝を記録した伝説的なライダーです。
そして、青いバイクは、ケビン・シュワンツに憧れた内山という小僧が乗っている、RGV250Γという、RGV-Γのレプリカバイクです。
マルボロカラーのバイクは、
YAMAHA YZR500 / ウェイン・レイニー
 ロスマンズカラーのバイクは
HONDA NSR500 / ワイン・ガードナー  です。とにかくかっこいいですね!!!

はい、本題に入ります。
Linuxでのディレクトリ、ファイルの監視 についてです。
筆者はCentOS6.2及び6.3を使用してます。

キーワードは、「inotify」と、「fsniper」!


この2つの説明を見てみると、
  • inotify API はファイルシステムイベントを監視するための機構を提供する。
  • fsniperを使用すると、監視対象のディレクトリを指定し、
    それらのディレクトリで新しいファイルが作成されたときにスクリプトを実行することができる。
とあります。
inotifyは、ファイルやディレクトリに変化があると、
どんな操作があったのかを教えてくれるみたいですね。
一方、fsniperはinotifyを利用し、変化があるとスクリプトを実行してくれるみたいですね。
まずはinotify-toolsをインストールしてみます。 
# yum install inotify-tools      (RedHat 系の場合)
# apt-get install inotify-tools  (Debian 系の場合)
はい。インストール完了です。
inotifywait と inotifywatch というコマンドが使えるようになります。
inotifywait は、指定したファイルやディレクトリに変化があると、 その旨出力してくれるコマンドらしいです。
inotifywatch は、指定したファイルやディレクトリに対する操作内容をまとめ、 統計結果を出力してくれるコマンドらしいです。
えーっと、waitさんは何か起きたらすぐに教えてくれる人で、
watchさんは終了の合図があるまで記録をとり続ける人みたいですね。はい。
まずはhogetestディレクトリを作り、inotifywaitで監視させてみます。
引数に-mを指定することで、一度で終了せずに監視を続けてくれます。 
# mkdir /hogetest
# inotifywait -m /hogetest
Setting up watches.  
Watches established.
フォアグラウンドで動くので、別の端末からhogetestにtest.txtを作ってみます。
# touch /hogetest/test.txt
すると、inotifywaitを実行中の端末に 
/testdir/ CREATE test.txt
/testdir/ OPEN test.txt
/testdir/ ATTRIB test.txt
/testdir/ CLOSE_WRITE,CLOSE test.txt
と表示されました! 
touchコマンドだけでも、ファイルを作成し、ファイルを開いて属性を変更していることがわかりますね。
このように、inotifywaitコマンドは何か操作が行われた際のイベント情報を出力してくれます。
起動スクリプトを書いて、重要なディレクトリを監視させてlogファイルに記録を残すようにすれば、 トラブル時には役にたつかもしれませんね。
この辺でinotifyさんは終わりにします。
 
次に、fsniperです。
yumで拾ってこれないので、この辺からtar.gzファイルをダウンロードして、
いつも通りにインストールします。
# tar -xzf fsniper-1.3.1.tar.gz 解凍
# cd fsniper
# ./configure
...
checking for a BSD-compatible install... /usr/bin/install -c
checking for magic_open in -lmagic... no
configure: error: libmagic not found
はい。なんか怒られますね。libmagicがねーよ!って怒られているのでインストールします。
# yum install file-devel      (RedHat 系の場合)
# apt-get install libmagic-dev  (Debian 系の場合)
今度こそconfigureするぞー(棒
# ./configure
...
checking for magic_open in -lmagic... yes
checking for pcre_version in -lpcre... no
configure: error: libpcre not found
(^ω^#)ピキピキ
# yum install pcre-devel
気を取り直して、
# make
# make install
たぶんインストールできましたね。
--version でバージョンを確認できます
今、実行しても、設定ファイルがみつからないよ!と怒られます。
# fsniper --help
        --help
                Prints this help text.
        --version
                Prints version information.
        --daemon
                Run as a daemon.
        --verbose
                Turns on debug text.
        --sync
                Sync mode (for debugging).
        --log-to-stdout
                Log to stdout alongside the usual log file.
# fsniper --version
fsniper v1.3.1
# fsniper --verbose
error: could not open config file: /root/.config/fsniper/config
というわけで、configファイルを作ります。 
watch {
 /hogetest {
  */* {
   handler = cp %% /home/hoge/Desktop/
  }
 }
}
上記の設定は、先ほど作成したhogetestディレクトリに何かファイルが作られたら
それをhogeさんのデスクトップにコピーするように書きました。 
fsniper --daemon で走らせてみます。 
# fsniper --daemon
#touch //hogetest/test2.txt
#ls //home/hoge/Desktop/
test.txt test2.txt
 
こんな感じでディレクトリやファイル監視して、
任意のスクリプトを実行させることができました。
アップローダーにファイルがアップロードされたら、
ファイル一覧を転送したりと、いろいろ活用できそうですね! 
 
凄いね!やったね!
おしまい。まる。 

2012年12月11日火曜日

jQueryのイベントのバブリングについて

何か,管理者権限持ってる人に記事消されて,
「イラッ」としたので今日はボイコットするつもりだったんですけど,
岩見君に「それはアカンやろ!」って言われたので遅ればせながら書きました.


jQueryのイベントのバブリングについて

タイトルではjQueryとありますが,イベントバブリングはJavaScript共通です.

イベントのバブリングとはつまり,イベントの伝達のことを指します.

まずは下記の青いオブジェクトをクリックしてください(alertが3回表示されるかと思います)

ちなみに三色は親子孫関係にあります.

青から緑へ,緑から赤へ,イベントが伝わりました.

ではここで,青オブジェクトのon('click')関数の最後に「return false」を入れてみます.

今回は青のみが表示されました.

「return false」はイベントのバブリングを完全に止めてしまいます.

疑り深い人は,緑オブジェクトをクリックしてみてください.

緑から赤へはしっかりとイベントのバブリングが発生します.

<a>タグでhrefのリンクを無効化する際によく使われますね.



「e.stopPropagation」と「e.preventDefault」

ごちゃごちゃ説明するのも……なので、

「return false」は「e.stopPropagation」と「e.preventDefault」を同時に呼んだ効果があります.

「e.stopPropagation」+「e.preventDefault」=「return false」です。

先ほどの<a>タグで説明すると,「e.stopPropagation」は親要素へのバブリングを止める効果はありますが,自身のhrefを止める効果はありません.

反対に「e.preventDefault」は親要素へのバブリングを止める効果はありませんが,自身のhrefを止める効果があります.

同時に使用することで「return false」と同じ,イベントのバブリングを完全に止める効果があります.

<a>タグは入っていませんが、下記は「e.stopPropagation」で親要素へのバブリングを止めたものです.

jQuery UIを駆使してCMSを作っていたときにつまずいた部分です.

(本当はjQuery UIが絡んでもうちょっとややこしいところだけど,長くなりそうだから逃げたなんてことはない.絶対に.)




2012年12月10日月曜日

PythonでのWebプログラミング

PythonでのWebプログラミング

今朝起きたらカレンダーでアドベントカレンダー担当がでってビックリしたから、以下の記事は多分足りない部分が多いけど、読んだらちょっと面白そうと思われる人がいるんでしたら、遠慮なく、声かけて下さい。。。そしたらもうちょっと細かく説明する。



簡単なウェブプログラミングと言われると多くの人はRORを考えると思うけど、実は多くの言語が複数フレームワークがある。今回はPythonと言うスクリプト言語について軽く話すつもり。Pythonにも複数フレームワークがあって例として以下のリンクがある:

今回はその中の1つ、Djangoの使い方をもうちょっと細かく見るつもり。

Django

まず、djangoがまだインストールしていなければ、Debian系のLinuxシステムの場合は簡単に以下のコマンドでインストール出来る。

    apt-get install python-django

Djangoはインストールし終わったら、新たなプロジェクトを作成して見よう。

    django-admin.py startproject tester

このコマンドを実行すれば「tester」と言うフォルダが出来て、その中身は以下の通り、

    /tester
        manage.py
        /tester
            __init__.py
            settings.py
            urls.py
            wsgi.py

このファイルの中に基本的にいじるファイルは「settings.py」と「url.py」のみ。
現状の何もないプロジェクトを一回動かして見たいでした、以下のコマンドはテストサーバを起動する。

    python2 manage.py runserver











次のステップは「/tester/settings.py」の中にデータベースの設定。今回はmysqlを使うだけどDjangoはPostgres,sqlite3,Oracleも対応している。使うデータベースとpythonモジュールをインストール確認して。debian系だったら、Pythonモジュールは「python-mysqldb」と言われる。データベースとデータベースユーザを作ったから、「tester/settings.py」のDB部分に以下のように変更すれば完成。


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'tester',                      # Or path to database file if using sqlite3.
        'USER': 'tester',                      # Not used with sqlite3.
        'PASSWORD': 'unko',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

設定があっていれば、

    python2 manage.py syncdb

のコマンドでDBのセットアップスクリプトが動かす。最初の質問はこのDjangoプロジェクトにスーパユーザを作成するかどうか。「yes」を答えて、次にそのユーザ名、eメール、パスワードを入力すれば、DB設定のインストールは完成。

次はこのプロジェクトのアプリを作成するので、

    python2 manage.py startapp unko

を作成しよう。これ実行したらアプリディレクトリを以下の通りで作成する。

    /unko
        __init__.py
        models.py
        tests.py
        views.py

こん回のアプリはシンプルはポールアプリ作成するつもりから、Djangoを使う場合は基本的にDBのデザインから始まるので「unko/models.py」で以下のような感じにしよう。

from django.db import models

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Chose(models.Model):
    poll = models.ForeignKey(poll)
    choise = models.CharField(max_length=200)
    votes = models.IntegerField()

このようなシンプルなコードで、Djangoはデータベーステーブルとテーブル接続APIも作成する。ただDjangoはまだこのアプリのアクセスパス知らないから「/tester/settings.py」の「INSTALLED_APPS」の最後に

    'unko',

を追加する必要。「python2 manage.py syncdb」また実行すれば、新しく追加したテーブルをDBにも追加する。

次はadminサイトを有効するので先ほどの「/tester/settings.py」の「INSTALLED_APPS」へ、

    'django.contrib.admin',

のコメントを外して「/tester/urls.py」の中に

    from django.contrib import admin
    admin.autodiscover()

とそのしたの

    url(r'^admin/', include(admin.site.urls)),

のコメントも外しましょう。そしたらテストサーバを動かしたら、「0.0.0.0:8000/admin」へアドミン画面がアクセス出きるんだが、ログインしても何も出来ないから,「/unko/admin.py」のファイルを作成し、以下の通りにすればアドミンユーザはポールは作成出来るようになる。

from unko.models import Poll
from unko.models import Choise
from django.contrib import admin
class ChoiceInLine(admin.StackedInLine):
    model = Choise
    extra = 3
class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,  {'fields':['question']}),
        ('Date information', {'fields':['pub_date'], 'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]
admin.site.register(Poll, PollAdmin)

この上のコードはアドミン画面作成だけではなく、ポールの作成画面ちょっと綺麗に整理するも!
「python2 manage.py syndb」をした後で、テストサーバからアクセス出来るようになる





















これからは利用者を見れる部分につつける,まずURLの設定にいじってみよう。
「/tester/url.py」の中に以下の行を追加すればポールのURLルールは完成。見たら多分分かるだけど、regexでURLをマッチし、unkoアプリのviewsの部分にリダイレクトする感じ。

    url(r'^polls/$', 'unko.views.index'),
    url(r'^polls/(?P<poll_id>\d+)/$', 'unko.views.detail'),
    url(r'^polls/(?P<poll_id>\d+)/results/$', 'unko.views.results'),
    url(r'^polls/(?P<poll_id>\d+)/vote/$', 'unko.views.vote'),

次は「/unko/views.py」に見よう。元々からぽけど、先ほどのURLの部分のリダイレクトをカッチする関数を作る必要。以下のviewはindex,detail,vote,resultの四つのviewをを作成した。
その中voteの関数以外全てテンプレートも利用するので後シンプルなテンプレもはっておく。


from django.shortcuts import get_object_or_404, render_to_response
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.template import RequestContext
from unko.models import Poll, Choise

def index(request):
    latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
    t = loader.get_template('polls/index.html')
    c = Context({
        'latest_poll_list': latest_poll_list,
    })
    return HttpResponse(t.render(c))

def detail(request, poll_id):
    p = get_object_or_404(Poll, pk=poll_id)
    return render_to_response('polls/detail.html', {'poll': p},
                               context_instance=RequestContext(request))

def vote(request, poll_id):
    p = get_object_or_404(Poll, pk=poll_id)
    try:
        selected_choise = p.choise_set.get(pk=request.POST['choise'])
    except (KeyError, Choise.DoesNotExist):
        # Redisplay the poll voting form.
        return render_to_response('polls/detail.html', {
            'poll': p,
            'error_message': "You didn't select a choice.",
        }, context_instance=RequestContext(request))
    else:
        selected_choise.votes += 1
        selected_choise.save()
        return HttpResponseRedirect(reverse('polls.views.results', args=(p.id,)))

def results(request, poll_id):
    p = get_object_or_404(Poll, pk=poll_id)
    return render_to_response('polls/results.html', {'poll': p})

テンプレを利用するためtester/settings.pyのTEMPLATE_DIRSに好きなディレクトリを登録して、そのディレクトリの中にpollフォルダをつくって。
pollフォルダのなかに「index.html」を作成する。そのファイルは上のviewsのindexを呼び出す手Mプレになるから、以下ようにする際、あるポールを一覧を表示する。

{% if latest_poll_list %}
    <ul>
    {% for poll in latest_poll_list %}
        <li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

次はdetailed.htmlを以下の通りだと、ポールの選択をラジオボタン付きのフォームで表示する。

<h1>{{ poll.question }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="/polls/{{ poll.id }}/vote/" method="post">
{% csrf_token %}
{% for choise in poll.choise_set.all %}
    <input type="radio" name="choise" id="choise{{ forloop.counter }}" value="{{ choise.id }}" />
    <label for="choise{{ forloop.counter }}">{{ choise.choice }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>


最後のresults.htmlは以下の感じで、ポールの各選択とポイントほ表示する。

<h1>{{ poll.question }}</h1>
<ul>{% for choise in poll.choise_set.all %}    <li>{{ choise.choice }} -- {{ choise.votes }} vote{{ choise.votes|pluralize }}</li>{% endfor %}</ul>
<a href="/polls/{{ poll.id }}/">Vote again?</a>



これよんだら多分分かりにくいけど何とかなるかも。。。。