require "pathname" require "markaby" require "camping/session" Markaby::Builder.set(:indent, 2) Camping.goes :Anne IMAGE_DIR = Pathname.new(__FILE__).dirname + "images" module Anne include Camping::Session secret "JeMoeder" def self.create Anne::Models.create_schema end end module Anne::Models class User < Base end class Vote < Base belongs_to :user end class BasicFields < V 1.0 def self.up create_table User.table_name do |t| t.string :study, :gender, :spaciousness, :email t.integer :study_year t.boolean :colorblind, :prize, :results t.timestamps end create_table Vote.table_name do |t| t.string :image, :choice t.integer :user_id end end def self.down drop_table User.table_name drop_table Vote.table_name end end end module Anne::Helpers def next_image all_images = Pathname.glob(IMAGE_DIR + "*.jpg").map { |img| img.basename.to_s } all_votes = Anne::Models::Vote.find(:all, :conditions => { :user_id => @state["user"].id }) voted_images = all_votes.map { |vote| vote.image } remaining_images = all_images - voted_images return nil, 100 if remaining_images.empty? return remaining_images.sort_by { rand }.first, 100 - (remaining_images.length * 100.0 / all_images.length).ceil end end module Anne::Controllers class Index def get render :intro end end class Start def get return redirect Vote if @state["user"] render :start end def post @state["user"] = User.create( :study => @input.user_study, :study_year => @input.user_study_year, :gender => @input.user_gender, :colorblind => @input.user_colorblind == "ja", :spaciousness => @input.user_spaciousness) redirect Vote end end class Vote def get return redirect Index if not @state["user"] image, progress = next_image return redirect Finish if image.nil? render :vote, image, progress end def post choice = if @input.left then "left" elsif @input.right then "right" else raise "no choice made!" end vote = Anne::Models::Vote.create( :user_id => @state["user"].id, :image => @input.image, :choice => choice ) redirect Vote end end class ImageX def get(file) unless file =~ /\.\./ headers["Content-Type"] = "image/jpeg" headers["X-Sendfile"] = (IMAGE_DIR + file).to_s else @status = 403 "You're not allowed to retrieve #{file}!" end end end class Finish def get return redirect Index if not @state["user"] return redirect Vote unless next_image.first.nil? # FIXME: check whether email/prize/results have been sent, and redirect to Thanks. render :finish end def post user = User.find(@state["user"].id) raise "unknown user" if user.nil? user.email = @input.email user.prize = !@input.prize.nil? user.results = !@input.results.nil? user.save redirect Thanks end end class Style < R '/style\.css' STYLE = File.read(__FILE__).gsub(/.*__END__/m, '') def get @headers['Content-Type'] = 'text/css; charset=utf-8' STYLE end end class Thanks def get render :thanks end end end module Anne::Views def layout xhtml_strict do head do title "Enquête ruimtelijke effecten" link :rel => "stylesheet", :type => "text/css", :media => "screen", :href => "/style.css" end body do div.header! do h1 "Enquête ruimtelijke effecten" end div.content! { self << yield } div.footer! { "Copyright © 2010 Anne Pijl, Bram Senders, Paul van Tilburg" } end end end def intro p "Met deze enquête worden een aantal ruimtelijke effecten onderzocht. " + "Je krijgt 39 keer een plaatje met twee afbeeldingen te zien. " + "Je kiest welke afbeelding, de linker of de rechter afbeelding, " + "je ruimtelijker ervaart. " + "In welk plaatje zie je meer diepte, welk plaatje lijkt jou het meest " + "3-dimensionaal? Als je het niet weet, klik je op een willekeurige " + "afbeelding. De test duurt 5 á 10 minuten. Succes!" p "Doe de test volledig om kans te maken op de prijs." p "– Anne Pijl" a "Start de enquête!", :href => R(Start) p "(Jij logt in vanaf #{@env["REMOTE_ADDR"]}.)" end def make_select(label_name, name, options) p do label label_name, :for => name select :name => name do options.each { |option_str| option option_str } end end end def start h2 "Persoonlijke karakteristieken" p "Graag zou ik ten behoeve van de statistiek het volgende van je willen weten:" form :action => R(Start), :method => :post do make_select "Faculteit:", "user_study", ["niet van toepassing", "Biomedische Technologie", "Bouwkunde", "Electrical Engineering", "Industrial Design", "Scheikundige Technologie", "Industrial Engineering & Innovation Sciences", "Technische Natuurkunde", "Werktuigbouwkunde", "Wiskunde & Informatica"] make_select "Studiejaar", "user_study_year", ["niet van toepassing"] + (1998..2009).to_a make_select "Geslacht", "user_gender", ["", "man", "vrouw"] make_select "Ben je kleurenblind?", "user_colorblind", ["nee", "ja"] make_select "Vind je dat je een goed ruimtelijk voorstellingsvermogen hebt?", "user_spaciousness", ["neutraal", "ja", "nee"] input :type => "submit", :value => "Start de enquete" end end def vote(image, progress = 0) h2 "Welk beeld is ruimtelijker?" # FIXME: resize all images # FIXME: split all images in two parts and make it possible two select an image. img :src => R(ImageX, image), :width => "80%" form :action => R(Vote), :method => :post do input :type => "hidden", :name => "image", :value => image input :type => "submit", :name => "left", :value => "Links" input :type => "submit", :name => "right", :value => "Rechts" end # FIXME: make a nice div with two spans of the following. p "Woep, je bent al op #{progress}%!" end def finish h2 "Dank je wel voor het meedoen aan dit onderzoek." p "Als je geïnteresseerd bent in de resultaten van de enquête of je wilt " + "meedingen naar de prijs, vul dan hier je e-mailadres in." form :action => R(Finish), :method => :post do p do label "E-mailadres", :for => "email" input :type => "text", :name => "email" end p do input :type => "checkbox", :name => "prize", :checked => true label "Ik wil een vette prijs winnen!", :for => "prize" end p do input :type => "checkbox", :name => "results", :checked => true label "Ik ben een nieuwsgierig aagje en ik wil het naadje van je kous weten!", :for => "results" end p "Je e-mailadres wordt enkel gebruikt voor de enquête resultaten en " \ "om je op de hoogte te stellen als je gewonnen hebt." input :type => "submit", :value => "Verstuur" end end def thanks h2 "Bedankt!" p "Je antwoorden zijn verstuurd." end end # FIXME: Insert some TU/e styling here __END__ /* Style sheet for the Anne Survey Camping app */ body { color: white; background-color: black; }