アンケート自動集計

  1. アンケートの集計
    cgiの機能を利用しますと、FORMタグで入力されたアンケートデータを集計し、リアルタイムで結果を表示することができます。

  2. 手法
    1. 構成
      まず、アンケートの構造を考えます。ここでは、分類をする大項目と実際の集計を行う小項目から構成されるものとし、基本構造を次のようなテキストファイル:minienq.txt で表現します。

      *年次=4
      1年生
      2年生
      3年生
      4年生
      +使用機器=4
      デスクトップ
      ノート
      携帯端末
      携帯電話

      * や + についた項目が大項目で、続く =<数> で、その小項目の数を指定します。大項目の先頭の記号は、アンケートの選択方式で、 *は 小項目から1個のみ(ラジオボタン)選択し、+ は任意個数(したがってチェックボックス)選択可能とします。 これから、アンケートをとるページは左図のように構成できます。 ページには、他に、名前入力と送信ボタンが追加されています。 この、htmlはこちらを参照してください。

       

       
    2. アンケートのデータ
      アンケートの小項目毎の集計をします。sendボタンを押すと、次のようなFORMタグが出力されます。'name=mito&1=3&2=1&2=3&send=send'
      name=mito は「お名前」の文字、 1=3 は、大項目1番で小項目2番が選択されていることを意味します。 2=1&2=3 は、大項目2番で小項目1,3が選択されていることを意味します。このアンケートデータをとりあえず、連想配列 %hash に記録します。
       
    3. アンケートの集計
       アンケートの集計には、ハッシュ(連想)配列を利用します。大項目と小項目を連結した番号をキーとし、これをキーとして投票数を記憶します。 たとえば、2=3 のフォームデータがあった場合、 2:3 をキーとする連想配列 %total の値を一つ増加します。
       集計結果は、minienq.dat ファイルに記録します。ファイルの初期状態で、次のように項目毎のキーとその集計値を保存します。プログラムの先頭でこのファイルを読み込み、連想配列 %total を初期化します。

      1:1=0
      1:2=0
      1:3=0
      1:4=0
      2:1=0
      2:2=0
      2:3=0
      2:4=0

    4. 集計結果の表示
      集計結果を表示するにも、定義ファイル minienq.txt を利用します。定義ファイルの項目名を表示しながら、大項目を小項目の番号から、%totalに記録されている集計値を表示します。
    5. ファイルのアクセス制御
      CGIでファイルを利用する場合、アクセス制御が必要です。cgiは複数の利用者が同時に利用する可能性がありますから、複数の利用者が同時に同じファイルを呼んだり更新する危険性があるからです。

  3. プログラム(スクリプト)
    1. formデータの読み込む
      formデータの読み込みは、先に紹介した3種の関数を利用します。これで、%formに、各項目のキーが登録されます。

      my $postData = &get_PostData;
      my $hash_ref = &get_FormData($postData);
      my %form = %$hash_ref;

    2. 集計結果の更新
      ここが中心部分です。最初の段落で minienq.dat を読みとり、キーを$name、集計値を$valに読み込み、連想配列の登録します。
       次にアンケート結果の %form のすべてのキーーに対し、%total の値を増加させます。最後に更新した、%total を配列 minienq.dat に書き戻します。
       ここで、書き戻されるデータの順は、元の minienq.dat と同じではありません。keys(%total) で取り出されるキーに順序は一定ではなく、アクセスされたキーが先に取り出されるようです。

        open(File,"minienq.dat");
        while($line=<File>){
          chomp($line);
          ($name,$val)=split(/=/,$line);
          $total{$name}=$val;
          #print "dat:$name= $total{$name}\n";
        }
      
        foreach $key (keys(%form)){
          if( exists($total{$key})) {
            $total{$key}=$total{$key}+1;
            #print "inc: $key\n";
          }
        }
      
        open(WORK,">work.dat");
        foreach $key (keys(%total)){
          print WORK "$key=$total{$key}\n";
        }
      
        close(File);close(WORK);
        unlink("minienq.dat");
        rename("work.dat","minienq.dat");

    3. 結果の表示
      htmlのヘッダ部分と、最後の部分、の書き出しは先の例と同じです。ここでは、集計結果を表示する部分のみを紹介します。minienq.txt ファイルから、先頭の大項目を読み出します。小項目の個数を$numに記録し、小項目の繰り返しを行います。$itemNumが大項目の番号、&iが小項目の番号になります。 $key=$itemNum.":".$i; でキーを合成し、%total から集計値を取り出し、表示します。
       簡単のため、ここでは簡単なテキスト形式で表示していますが、表またはリスト構造で表示する法が見やすいページになるでしょう。
        open(TXT,"minienq.txt");
        $itemNum = 1;
        while($line=<TXT>){
          chomp($line);
          ($name,$num)=split(/=/,$line);
          print'<BR><h3>';print "$name\n";print'</h3><BR>';
          for($i=1;$i <= $num;$i++){
            $line=<TXT>;chomp($line);
            $key=$itemNum.":".$i;
            $val=$total{$key};
            #print "i = $i key= $key \n";
            print "$line:$val\n";print'<BR>';
          }
          $itemNum++;
        }

    4. ソース
      このCGIのソースはこちらを参照してください。(注意:アクセス制御をしていない)

    5. 実行時の環境
      このcgiを実行するには、アンケートを表示するhtmlファイル(minienq/index.htm)を、ホームページからリンクします。また、index.htmと同じフォルダに、cgiのソースファイル(minienq.cgi) 、アンケートの構造を定義したファイル(minienq.txt)、アンケートの集計結果を記録するファイル(minienq.dat)、を配置することが必要です。minienq.datは、最初すべての項目を0に初期化しておく必要があります。

    6. CGIのデバッグ
       CGIをデバッグするときやっかいなことは、CGIとして実行するとPerlの標準出力がネットワークの出力として接続されるため、プログラム(スクリプト)の文法エラーなどが画面に表示されないことです。しかし、CGIとして接続しないと、FORM入力を受け取ることができません。そこで、プログラムの先頭に以下の行を追加します。

       $ENV{'REQUEST_METHOD'}='GET';
       $ENV{'QUERY_STRING'}='name=mito&1=3&2=3&2=1&send=send';

      これは、通常はCGIのデータとして環境変数から受け取るFORM情報を、自分で設定することになります。このプログラムを、CGIではなく、Perlで実行します。
       >perl -w minienq.cgi
      こうすれば、Perl実行時のエラーやページ出力は、コマンドプロンプトとして出力されますから、デバッグが非常に容易になります。ただし、GET方式でもFORMパラメータの受け取りができるようにしておく必要があります。実際に、CGIとして接続する場合は、この2行を コメント にしておきます。

  4. 実行
    このスクリプトを実行して見ましょう。すべてのcgi利用のファイルはeucコードで保存し、minienq.datはrw属性、minienq.cgiにはx属性を設定します。
     実行
    CGIの表示画面は次のようです。



  5. 今後の課題
     
    1. アンケートページの自動生成
      ここではアンケートページは、手作業で作成しましたが、minienq.txtファイルから自動合成することは簡単です。作成するとき、minienq.txtとminienq.datファイルを記録するフォルダを指定できるようにすると、複数のページで同じプログラム(スクリプト)を共用できます。また、集計結果を記録するファイルはここでは、あらかじめ作成してあることを前提にしていますが、ファイルが存在しない場合、自動生成することも可能です。

    2. 結果のグラフ表示
      結果を文字だけでなく、棒グラフで表示すると、見やすいデータになります。棒グラフは、表示幅の画像データを用意し、集計値でこのグラフの長さを IMG タグで指定します。widを横幅の画素数とすると、次のように IMG タグを出力します。
       <IMG SRC=./dotred.gif width=",int($wid)," height=10>

    3. 任意文字型アンケートの表示
      アンケートの項目で、すべての場合が尽くせないことが多いと思います。項目に自由に書き込めるFORM を用意し、それをファイルに記録し表示する機能が必要でしょう。

    4. 練習問題
      minienq.datファイルの形式を変更し、練習問題と解答を用意し、FORMタグで選択した解答を自動採点することも観点にできますね。

    5. ページの意見
      集中的なアンケート調査でなく、各ページにアンケート項目を分散させて、意見を集約することがもできます。大項目の番号を重複しないよう割り当てることが必要です。