############################################################################ # Copyright 2009 Benjamin Kellermann # # # # This file is part of dudle. # # # # Dudle is free software: you can redistribute it and/or modify it under # # the terms of the GNU Affero General Public License as published by # # the Free Software Foundation, either version 3 of the License, or # # (at your option) any later version. # # # # Dudle is distributed in the hope that it will be useful, but WITHOUT ANY # # WARRANTY; without even the implied warranty of MERCHANTABILITY or # # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public # # License for more details. # # # # You should have received a copy of the GNU Affero General Public License # # along with dudle. If not, see . # ############################################################################ require "hash" require "yaml" require "time" require "pollhead" require "timepollhead" class Poll attr_reader :head, :name YESVAL = "ayes" MAYBEVAL = "bmaybe" NOVAL = "cno" def initialize name,type @name = name case type when "normal" @head = PollHead.new when "time" @head = TimePollHead.new else raise("unknown poll type: #{type}") end @data = {} @comment = [] store "Poll #{name} created" end def sort_data fields parsedfields = fields.collect{|field| field == "timestamp" || field == "name" ? field : @head.cgi_to_id(field) } if parsedfields.include?("name") until parsedfields.pop == "name" end @data.sort{|x,y| cmp = x[1].compare_by_values(y[1],parsedfields) cmp == 0 ? x[0] <=> y[0] : cmp } else @data.sort{|x,y| x[1].compare_by_values(y[1],parsedfields) } end end def to_html(edituser, showparticipation = true) ret = "\n" ret += @head.to_html sort_data($cgi.include?("sort") ? $cgi.params["sort"] : ["timestamp"]).each{|participant,poll| if edituser == participant ret += participate_to_html(edituser) else ret += "\n" ret += "\n" @head.each_column{|columnid,columntitle| klasse = poll[columnid] case klasse when nil value = UNKNOWN klasse = "undecided" when YESVAL value = YES when NOVAL value = NO when MAYBEVAL value = MAYBE end ret += "\n" } ret += "" ret += "\n" end } # PARTICIPATE ret += participate_to_html(edituser) unless @data.keys.include?(edituser) || !showparticipation # SUMMARY ret += "\n" @head.each_columnid{|columnid| yes = 0 undecided = 0 @data.each_value{|participant| if participant[columnid] == YESVAL yes += 1 elsif !participant.has_key?(columnid) or participant[columnid] == MAYBEVAL undecided += 1 end } if @data.empty? percent_f = 0 else percent_f = 100*yes/@data.size end percent = "#{percent_f}%" unless @data.empty? if undecided > 0 percent += "-#{(100.0*(undecided+yes)/@data.size).round}%" end ret += "\n" } ret += "" ret += "
" ret += participant ret += " #{EDIT}" if showparticipation ret += "#{value}#{poll['timestamp'].strftime('%d.%m, %H:%M')}
total#{yes}
\n" ret end def participate_to_html(edituser) checked = {} if @data.include?(edituser) @head.each_columnid{|k| checked[k] = @data[edituser][k]} else edituser = $cgi.cookies["username"][0] unless @data.include?($cgi.cookies["username"][0]) @head.each_columnid{|k| checked[k] = NOVAL} end ret = "\n" ret += " " ret += "\n" @head.each_column{|columnid,columntitle| ret += "" [[YES, YESVAL],[NO, NOVAL],[MAYBE, MAYBEVAL]].each{|valhuman, valbinary| ret += "" } ret += "
" } ret += "" if @data.include?(edituser) ret += "" ret += "
" else ret += "" end ret += "\n" ret += "\n" ret end def comment_to_html ret = "
" ret += "

Comments

" unless @comment.empty? @comment.each_with_index{|c,i| time,name,comment = c ret += <
#{name} said on #{time.strftime("%d.%m, %H:%M")}   #{comment}
COMMENT } end # ADD COMMENT ret += <
says 
ADDCOMMENT ret += "
\n" ret end def history_selectform(revision, selected) ret = <
Show only history items concerning: " ret += "" if revision ret += <
FORM ret end def history_to_html(middlerevision,only) log = VCS.history if only != "" case only when "comments" match = /^Comment .*$/ when "participants" match = /^Participant .*$/ when "columns" match = /^Column .*$/ else raise "invalid value #{only}" end log = log.comment_matches(match) end log.around_rev(middlerevision,11).to_html(middlerevision,only) end def add_participant(olduser, name, agreed) name.strip! if name == "" maximum = @data.keys.collect{|e| e.scan(/^Anonymous #(\d*)/).flatten[0]}.compact.collect{|i| i.to_i}.max maximum ||= 0 name = "Anonymous ##{maximum + 1}" end htmlname = CGI.escapeHTML(name) action = '' if @data.delete(CGI.escapeHTML(olduser)) action = "edited" else action = "added" end @data[htmlname] = {"timestamp" => Time.now } @head.each_columnid{|columnid| @data[htmlname][columnid] = agreed[columnid.to_s] } store "Participant #{name.strip} #{action}" end def delete(name) htmlname = CGI.escapeHTML(name.strip) if @data.has_key?(htmlname) @data.delete(htmlname) store "Participant #{name.strip} deleted" end end def store comment File.open("data.yaml", 'w') do |out| out << "# This is a dudle poll file\n" out << self.to_yaml out.chmod(0660) end VCS.commit(CGI.escapeHTML(comment)) end ############################### # comment related functions ############################### def add_comment name, comment @comment << [Time.now, CGI.escapeHTML(name.strip), CGI.escapeHTML(comment.strip).gsub("\r\n","
")] store "Comment added by #{name}" end def delete_comment index store "Comment from #{@comment.delete_at(index)[1]} deleted" end ############################### # column related functions ############################### def delete_column columnid title = @head.get_title(columnid) if @head.delete_column(columnid) store "Column #{title} deleted" return true else return false end end def edit_column(oldcolumnid, newtitle, cgi) parsedtitle = @head.edit_column(oldcolumnid, newtitle, cgi) store "Column #{parsedtitle} #{oldcolumnid == "" ? "added" : "edited"}" if parsedtitle end def edit_column_htmlform(activecolumn, revision) @head.edit_column_htmlform(activecolumn, revision) end end