#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
# alone : web application framework for small embedded systems.
#               Copyright (c) 2009-2010 Inas Co Ltd. All Rights Reserved.
#
# This file is destributed under BSD License. Please read the COPYRIGHT file.
#
# アンケート集計


class Enquete

  ##
  # 集計
  #
  def totalize()
    total = []
    @enquete_questions.each do |q|
      case q[:answer_pattern]
      when "p1"
        total << EnqueteTotalizeP1.new( q, @persist_base )

      when "p2"
        total << EnqueteTotalizeP2.new( q, @persist_base )

      when "p3"
        total << EnqueteTotalizeP3.new( q, @persist_base )

      when "p4"
        case q[:answer_type]
        when "text"
          total << EnqueteTotalizeP4t.new( q, @persist_base )
        when "int"
          total << EnqueteTotalizeP4i.new( q, @persist_base )
        when "float"
          total << EnqueteTotalizeP4f.new( q, @persist_base )
        end
      end
    end

    return total
  end


  ##
  # 結果ダウンロード
  #
  def download()
    print "回答日時"
    @enquete_questions.each do |q|
      case q[:answer_pattern]
      when "p1","p2"
        print ",Q#{q[:question_number]}"

      when "p3","p4"
        q[:answer_text].split(/\r\n|\r|\n/).count.times do |i|
          print ",Q#{q[:question_number]}-#{i+1}"
        end
      end
    end
    print "\r\n"

    sql = "select max(create_date) as create_date"
    @enquete_questions.each do |q|
      case q[:answer_pattern]
      when "p1","p2"
        sql += ",\nmax(case when question_number=#{q[:question_number]} then answer end) as q#{q[:question_number]}"

      when "p3","p4"
        q[:answer_text].split(/\r\n|\r|\n/).count.times do |i|
          sql += ",\nmax(case when question_number=#{q[:question_number]} and question_number_sub=#{i+1} then answer end) as q#{q[:question_number]}_#{i+1}"
        end
      end
    end
    sql += "\n from enquete_answers _WHERE_ group by answer_id order by create_date;"

    result = @persist_base.select( sql, { :enquete_id=>@values[:enquete_id] } )
    return false if ! result

    result.each do |r|
      text = ""
      r.each do |k,v|
        v = v.to_s.gsub('"', '""')
        text += %Q("#{v}",)
      end
      print text.chop
      print "\r\n"
    end

    return true
  end

end



##
# アンケート集計クラス スーパークラス
#
class EnqueteTotalize
  #@return [Integer]            サンプル数
  @@answer_qty = nil

  #@return [Hash]               質問パラメータ群
  attr_reader :question

  #@return [Array,NilClass]     集計結果
  attr_reader :answers


  ##
  # constractor
  #
  #@param [Hash] q      質問パラメータ群
  #
  def initialize( q, persist_base )
    @question = q

    if ! @@answer_qty
      sql = %Q(
select count(*) as count from (
  select distinct answer_id
    from enquete_answers
    _WHERE_
  ) as x;
)
      res = persist_base.select( sql, { :enquete_id=>q[:enquete_id] } )
      if res
        @@answer_qty = res[0][:count].to_i
      end
    end
  end


  ##
  # （生成時に与えられた）質問パラメータ群から、引数で与えられた種類のパラメータを返す
  #
  def []( k )
    @question[k.to_sym]
  end

  
  ##
  # 回答数を返す
  #
  def self.answer_qty()
    return @@answer_qty
  end
end



##
# アンケート集計クラス  パターン１
#
class EnqueteTotalizeP1 < EnqueteTotalize

  ##
  # constractor
  #
  #@param [Hash] q      質問パラメータ群
  #
  def initialize( q, persist_base )
    super( q, persist_base )

    sql = %Q(
select answer,count(*) as count
  from enquete_answers
  _WHERE_
  group by answer
  order by answer;
)
    @answers = persist_base.select( sql, { :enquete_id=>q[:enquete_id], 
        :question_number=>@question[:question_number], "answer <>"=>"" } )
  end


  ##
  # 集計結果の表示
  #
  #@return [String]     結果のHTML
  #
  def result()
    return "" if ! @answers

    r = %Q(<table class="summary-table">\n)
    @answers.each do |a|
      r += %Q(<tr><td>#{Alone.escape_html(a[:answer])}</td>\n)
      r += %Q(<td class="count">#{a[:count]}件</td></tr>\n)
    end
    return "#{r}</table>\n"
  end
end



##
# アンケート集計クラス  パターン２
#
class EnqueteTotalizeP2 < EnqueteTotalize

  ##
  # constractor
  #
  #@param [Hash] q      質問パラメータ群
  #
  def initialize( q, persist_base )
    super( q, persist_base )

    sql = %Q(
select answer,count(*) as count
  from enquete_answers
  _WHERE_
  group by answer;
)
    @answers = persist_base.select( sql, { :enquete_id=>q[:enquete_id], 
        :question_number=>@question[:question_number] } )
  end


  ##
  # 集計結果の表示
  #
  #@return [String]     結果のHTML
  #
  def result()
    return "" if ! @answers

    qstrings = @question[:answer_text].split( /\r\n|\r|\n/ )

    sum = 0
    @answers.each do |a|
      i = a[:answer].to_i - 1
      next if i < 0
      next if ! qstrings[ i ]
      sum += a[:count].to_i
    end

    r = %Q(<table>\n)
    qstrings.size.times do |i|
      catch(:break) do
        @answers.each do |a|
          if a[:answer].to_i == (i + 1)
            percent = 100.0 * a[:count].to_i / sum
            r += %Q(<tr><td class="item">#{Alone::escape_html(qstrings[i])}</td>\n)
            r += %Q(<td class="count">#{a[:count]}件</td>\n)
            r += %Q(<td class="percent">#{sprintf( "%.1f", percent )}%</td>\n)
            r += %Q(<td><div style="background-color: #77f; width: #{(percent * 4).to_i}px;">&nbsp;</div></td></tr>\n)
            throw :break
          end
        end
        r += %Q(<tr><td class="item">#{Alone::escape_html(qstrings[i])}</td><td class="count">0件</td></tr>\n)
      end
    end

    return "#{r}</table>\n"
  end
end



##
# アンケート集計クラス  パターン３
#
class EnqueteTotalizeP3 < EnqueteTotalize

  ##
  # constractor
  #
  #@param [Hash] q      質問パラメータ群
  #
  def initialize( q, persist_base )
    super( q, persist_base )

    sql = %Q(
select question_number_sub,count(*) as count
  from enquete_answers
  _WHERE_
  group by question_number_sub;
)
    @answers = persist_base.select( sql, { :enquete_id=>q[:enquete_id], 
        :question_number=>@question[:question_number] } )
  end


  ##
  # 集計結果の表示
  #
  #@return [String]     結果のHTML
  #
  def result()
    return "" if ! @answers

    qstrings = @question[:answer_text].split( /\r\n|\r|\n/ )
    r = %Q(<table>\n)
    qstrings.size.times do |i|
      catch(:break) do
        @answers.each do |a|
          if a[:question_number_sub].to_i == (i + 1)
            percent = 100.0 * a[:count].to_i / @@answer_qty
            r += %Q(<tr><td class="item">#{Alone::escape_html(qstrings[i])}</td>\n)
            r += %Q(<td class="count">#{a[:count]}件</td>\n)
            r += %Q(<td class="percent">#{sprintf( "%.1f", percent )}%</td>\n)
            r += %Q(<td><div style="background-color: #77f; width: #{(percent * 4).to_i}px;">&nbsp;</div></td></tr>\n)
            throw :break
          end
        end
        r += %Q(<tr><td class="item">#{Alone::escape_html(qstrings[i])}</td><td class="count">0件</td></tr>\n)
      end
    end

    return "#{r}</table>\n"
  end
end



##
# アンケート集計クラス  パターン４ text
#
class EnqueteTotalizeP4t < EnqueteTotalize

  ##
  # constractor
  #
  #@param [Hash] q      質問パラメータ群
  #
  def initialize( q, persist_base )
    super( q, persist_base )
    
    sql = %Q(
select question_number_sub,answer,count(*) as count
  from enquete_answers
  _WHERE_
  group by question_number_sub,answer
  order by question_number_sub,answer;
)
    @answers = persist_base.select( sql, { :enquete_id=>q[:enquete_id], 
        :question_number=>@question[:question_number], "answer <>"=>"" } )
  end


  ##
  # 集計結果の表示
  #
  #@return [String]     結果のHTML
  #
  def result()
    return "" if ! @answers

    r = ""
    i = 0
    qstrings = @question[:answer_text].split( /\r\n|\r|\n/ )
    qstrings.size.times do |n|
      q_no_sub = n + 1
      r += "#{Alone::escape_html(qstrings[n])}\n"
      r += %Q(<table class="summary-table">\n)
      while i < @answers.size
        if @answers[i][:question_number_sub] == q_no_sub
          r += %Q(<tr><td class="item">#{Alone::escape_html(@answers[i][:answer])}</td>\n)
          r += %Q(<td class="count">#{Alone::escape_html(@answers[i][:count])}件</td></tr>\n)
        else
          break
        end
        i += 1
      end
      r += "</table>\n"
    end

    return r
  end
end



##
# アンケート集計クラス  パターン４ integer
#
class EnqueteTotalizeP4i < EnqueteTotalize

  ##
  # constractor
  #
  #@param [Hash] q      質問パラメータ群
  #
  def initialize( q, persist_base )
    super( q, persist_base )

    sql = %Q(
select question_number_sub, count(*) as count, max(cast(answer as integer)) as max,
    min(cast(answer as integer)) as min, avg(cast(answer as integer)) as avg
  from enquete_answers
  _WHERE_
  group by question_number_sub
  order by question_number_sub;
)
    @answers = persist_base.select( sql, { :enquete_id=>q[:enquete_id], 
        :question_number=>@question[:question_number], "answer <>"=>"" } )
  end


  ##
  # 集計結果の表示
  #
  #@return [String]     結果のHTML
  #
  def result()
    return "" if ! @answers

    r = %Q(<table class="summary-table">\n)
    r += "<tr><td>項目</td><td>件数</td><td>最大</td><td>最小</td><td>平均</td></tr>\n"
    qstrings = @question[:answer_text].split( /\r\n|\r|\n/ )
    qstrings.size.times do |i|
      catch(:break) do
        @answers.each do |a|
          if a[:question_number_sub] == (i + 1)
            r += %Q(<tr><td class="item">#{Alone::escape_html(qstrings[i])}</td>)
            r += %Q(<td style="text-align: right;">#{a[:count]}</td>)
            r += %Q(<td style="text-align: right;">#{a[:max]}</td>)
            r += %Q(<td style="text-align: right;">#{a[:min]}</td>)
            r += %Q(<td style="text-align: right;">#{sprintf( "%.1f", a[:avg].to_f )}</td></tr>\n)
            throw :break
          end
        end
        r += %Q(<tr><td>#{Alone::escape_html(qstrings[i])}</td><td></td><td></td><td></td><td></td></tr>\n)
      end
    end

    return "#{r}</table>\n"
  end
end



##
# アンケート集計クラス  パターン４ float
#
class EnqueteTotalizeP4f < EnqueteTotalize

  ##
  # constractor
  #
  #@param [Hash] q      質問パラメータ群
  #
  def initialize( q, persist_base )
    super( q, persist_base )

    sql = %Q(
select question_number_sub, count(*) as count, max(cast(answer as float)) as max,
    min(cast(answer as float)) as min, avg(cast(answer as float)) as avg
  from enquete_answers
  _WHERE_
  group by question_number_sub
  order by question_number_sub;
)
    @answers = persist_base.select( sql, { :enquete_id=>q[:enquete_id], 
        :question_number=>@question[:question_number], "answer <>"=>"" } )
  end


  ##
  # 集計結果の表示
  #
  #@return [String]     結果のHTML
  #
  def result()
    return "" if ! @answers

    r = %Q(<table class="summary-table">\n)
    r += "<tr><td>項目</td><td>件数</td><td>最大</td><td>最小</td><td>平均</td></tr>\n"
    qstrings = @question[:answer_text].split( /\r\n|\r|\n/ )
    qstrings.size.times do |i|
      catch(:break) do
        @answers.each do |a|
          if a[:question_number_sub] == (i + 1)
            r += %Q(<tr><td class="item">#{Alone::escape_html(qstrings[i])}</td>)
            r += %Q(<td style="text-align: right;">#{a[:count]}</td>)
            r += %Q(<td style="text-align: right;">#{a[:max]}</td>)
            r += %Q(<td style="text-align: right;">#{a[:min]}</td>)
            r += %Q(<td style="text-align: right;">#{a[:avg]}</td></tr>\n)
            throw :break
          end
        end
        r += %Q(<tr><td>#{Alone::escape_html(qstrings[i])}</td><td></td><td></td><td></td><td></td></tr>\n)
      end
    end

    return "#{r}</table>\n"
  end
end
