Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

starting to do a quiz authoring tool

  • Loading branch information...
commit 6362b9f6e0cf856c9a6bd73eb5ccb8a33f89f904 0 parents
@armandofox armandofox authored
2  .rspec
@@ -0,0 +1,2 @@
+--format nested
+--color
3  Gemfile
@@ -0,0 +1,3 @@
+source :rubygems
+
+gem 'builder'
10 Gemfile.lock
@@ -0,0 +1,10 @@
+GEM
+ remote: http://rubygems.org/
+ specs:
+ builder (3.0.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ builder
40 lib/quiz.rb
@@ -0,0 +1,40 @@
+class Quiz
+ require 'builder'
+ attr_reader :xml
+
+ class MultipleChoiceQuestion
+ attr_accessor :text, :answer, :score
+ end
+
+ def default_options
+ {
+ :open_time => Time.now,
+ :soft_close_time => Time.now + 24*60*60,
+ :hard_close_time => Time.now + 24*60*60,
+ :maximum_submissions => 1,
+ :duration => 0,
+ }
+ end
+
+ def initialize(title, options)
+ @xml = Builder::XmlMarkup.new
+ @xml.instruct!
+ @xml.declare! '!DOCTYPE', 'quiz', 'SYSTEM', '"quiz.dtd"'
+ @title = title
+ options = default_options.merge(options)
+ @xml.metadata do
+ @xml.type 'quiz'
+ @xml.title title
+ end
+ end
+
+ def render
+ @xml.to_s
+ end
+
+ def self.quiz(title, options={})
+ quiz = Quiz.new(title, options)
+ debugger
+ end
+
+end
33 lib/quiz.rb~
@@ -0,0 +1,33 @@
+class Quiz
+ require 'builder'
+
+ class MultipleChoiceQuestion
+ attr_accessor :text, :answer, :score
+ end
+
+ def default_options
+ {
+ :open_time => Time.now,
+ :soft_close_time => Time.now + 1.day,
+ :hard_close_time => Time.now + 1.day,
+ }
+ end
+
+ def initialize(title, options)
+ @xml = Builder::XMLMarkup.new
+ @xml.instruct!
+ @xml.declare! '!DOCTYPE', 'quiz', 'SYSTEM', '"quiz.dtd"'
+ @title = title
+ options = default_options.merge(options)
+ @xml.metadata do
+ type 'quiz'
+ title title
+ end
+ end
+
+ def self.quiz(title, options={})
+ quiz = Quiz.new(title, options)
+ debugger
+ end
+
+end
24 spec/fixtures/example_quiz.rb
@@ -0,0 +1,24 @@
+Quiz.quiz "I. Introduction", :time_limit => 60 do
+ multiple_choice :points => 1 do
+ text %q{A computer program is said to learn from experience E with
+ respect to some task T and some performance measure P if its
+ performance on T, as measured by P, improves with experience E.
+ Suppose we feed a learning algorithm a lot of historical weather
+ data, and have it learn to predict weather. What would be a
+ reasonable choice for P?}
+
+ distractor 'The weather prediction task'
+ explanation 'The task described is weather prediction, so this is Task T.'
+
+ distractor 'The process of the algorithm examining a large amount of historical weather data.'
+ explanation 'It is by examining the historical weather data that the learning algorithm improves its performance, so this is the experience E.'
+
+ answer %q{The probability of it correctly predicting a future date's weather.}
+ explanation %q{This would be a reasonable measure P of measuring our weather predictions' accuracy.}
+
+ distractor 'None of the above.'
+ end
+
+end
+
+
10 spec/quiz_spec.rb
@@ -0,0 +1,10 @@
+require 'spec_helper'
+require 'support/matchers/xml_matcher'
+require 'quiz'
+
+describe Quiz do
+ describe 'when initialized' do
+ subject { Quiz.new('Foo', :maximum_submissions => 2, :start => '2011-01-01 00:00', :time_limit => 60).xml }
+ it { should have_xml_element 'title', :value => 'Foo' }
+ end
+end
1  spec/spec_helper.rb
@@ -0,0 +1 @@
+Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
174 spec/support/matchers/xml_matcher.rb
@@ -0,0 +1,174 @@
+# Check if element exists:
+# <tt>xml.should have_xml_element("account")<tt>
+# Use REXML syntax to address nested elements:
+# <tt>xml.should have_xml_element("account/name")<tt>
+# Check if element has certain value:
+# <tt>xml.should have_xml_element("account/name").with_value("foo")<tt>
+# or:
+# <tt>xml.should have_xml_element("account", :value => "foo")<tt>
+# Check if element has certain attribute:
+# <tt>xml.should have_xml_element("account").with_attribute("type")<tt>
+# Check if attribute has certain value:
+# <tt>xml.should have_xml_element("account").with_attribute("type", "user")<tt>
+# or:
+# <tt>xml.should have_xml_element("account", :type => "user")<tt>
+# Check if element occurs a number of times:
+# <tt>xml.should have_xml_element("account", :count => 2)<tt>
+# Check if element has a number of children named users:
+# <tt>xml.should have_xml_element("account").containing(2).users<tt>
+# or
+# <tt>xml.should have_xml_element("account").containing(2, "users")<tt>
+# or
+# <tt>xml.should have_xml_element("account", :count => 2, :child => :user)<tt>
+# or use generic "element" to count all children regardless of name:
+# <tt>xml.should have_xml_element("account").containing(2).elements<tt>
+
+#NOTE: Currently you cannot combine any of the options
+#TODO: make it possible to combine count, value, attributes
+
+
+class ElementCountProxy
+
+ attr_accessor :element, :element_name
+
+ def initialize(matcher,element=nil)
+ @element = element
+ @element_name = @element.dup if @element
+ @matcher = matcher
+ end
+
+ def matches?(*args)
+ @matcher.matches?(*args)
+ end
+
+ def failure_message
+ @matcher.failure_message
+ end
+
+ def negative_failure_message
+ @matcher.negative_failure_message
+ end
+
+ def method_missing(meth, *args, &blk)
+ @element_name = meth
+ @element = meth.to_s.singularize.dasherize
+ return @matcher
+ end
+
+end
+
+class HaveXmlElement
+
+ def initialize(expected,options={})
+ @expected = expected
+ @value = options.delete(:value)
+ @match_value = @value || false
+ @count = options.delete(:count)
+ @count_proxy = ElementCountProxy.new(self,options.delete(:child)) if options[:child]
+ @attribute_name = options.keys.first
+ @attribute_value = options.values.first
+ @match_attribute_name = @attribute_name || false
+ @match_attribute_value = @attribute_value || false
+ end
+
+ def matches?(actual)
+ @actual = actual
+ begin
+ document = REXML::Document.new(actual)
+ if @match_value
+ compare_values(document.elements[@expected.to_s].text,@value)
+ elsif @match_attribute_value
+ compare_values(document.elements[@expected.to_s].attributes[@attribute_name],@attribute_value)
+ elsif @match_attribute_name
+ document.elements[@expected.to_s].attributes[@attribute_name] ? true : false
+ elsif @count && @count > 0
+ if counted_element && counted_element == 'element'
+ document.elements[@expected.to_s].elements.size == @count ? true : false
+ elsif counted_element
+ document.elements[@expected.to_s].elements[counted_element].size == @count ? true : false
+ else
+ document.elements[@expected.to_s].size == @count ? true : false
+ end
+ else
+ document.elements[@expected.to_s] ? true : false
+ end
+ rescue => e
+ false
+ end
+ end
+
+ def containing(count,child=nil)
+ @count = count
+ @count_proxy = ElementCountProxy.new(self,child)
+ return @count_proxy
+ end
+
+ def with_value(value)
+ @match_value = true
+ @value = value
+ return self
+ end
+
+ def with_attribute(name,value=nil)
+ if name.is_a?(Hash)
+ arr = name.to_a.flatten
+ name = arr[0]
+ value = arr[1]
+ end
+ @match_attribute_name = true
+ @match_attribute_value = value.nil? ? false : true
+ @attribute_name = name
+ @attribute_value = value
+ return self
+ end
+
+ def failure_message
+ "expected \n\n#{@actual}\n to have XML element #{@expected.inspect}#{message_extension}, but it didn't"
+ end
+
+ def negative_failure_message
+ "expected \n\n#{@actual}\n to not have XML element #{@expected.inspect}#{message_extension}, but it did"
+ end
+
+ def counted_element
+ @count_proxy.element
+ end
+
+ def counted_element_name
+ @count_proxy.element_name
+ end
+
+ protected
+
+ def compare_values(target,source)
+ if source.is_a? Regexp
+ target.to_s.match source
+ else
+ target.to_s == source.to_s
+ end
+ end
+
+ def message_extension
+ case
+ when @match_value then " with value \"#{@value}\""
+ when @match_attribute_value then " with attribute \"#{@attribute_name}\" matching \"#{@attribute_value}\""
+ when @match_attribute_name then " with attribute \"#{@attribute_name}\""
+ when @count && @count > 0 && counted_element then " containing #{@count} #{counted_element_name}"
+ when @count && @count > 0 then " appearing #{@count} times"
+ else ""
+ end
+ end
+
+end
+
+def have_xml_element(expected,options={})
+ HaveXmlElement.new(expected,options)
+end
+
+
+RSpec::Matchers.define :have_xml_element do |elt,options={}|
+ match do |subj|
+ HaveXmlElement.new(elt,options).matches?(subj)
+ end
+end
+
Please sign in to comment.
Something went wrong with that request. Please try again.