ruql 0.1.5 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,6 +10,40 @@ class JSONRenderer
10
10
  end
11
11
 
12
12
  def render_quiz
13
- @output = @quiz.questions.map {|question| JSON.pretty_generate(question.to_JSON)}
13
+ @quiz.questions.each do |question|
14
+ case question
15
+ when MultipleChoice, SelectMultiple, TrueFalse then render_multiple_choice(question)
16
+ when FillIn then render_fill_in(question) # not currently supported
17
+ else
18
+ raise "Unknown question type: #{question}"
19
+ end
20
+ end
21
+ @output = JSON.pretty_generate(@json_array)
14
22
  end
23
+
24
+ def render_multiple_choice(question)
25
+ question_hash = {
26
+ "text" => question.question_text,
27
+ "answers" => answers_to_json_array(question.answers)
28
+ }
29
+ @json_array.push(question_hash)
30
+ end
31
+
32
+ def answers_to_json_array(answers)
33
+ answers_array = []
34
+ answers.each do |answer|
35
+ answer_json = {
36
+ "text" => answer.answer_text,
37
+ "explanation" => answer.explanation,
38
+ "correct" => answer.correct
39
+ }
40
+ answers_array.push(answer_json)
41
+ end
42
+ answers_array
43
+ end
44
+
45
+ def render_fill_in(q)
46
+ # fill-in-the-blank questions not currently supported
47
+ end
48
+
15
49
  end
@@ -0,0 +1,148 @@
1
+ class XMLRenderer
2
+ require 'builder'
3
+
4
+ attr_reader :output
5
+ def initialize(quiz,options={})
6
+ @output = ''
7
+ @b = Builder::XmlMarkup.new(:target => @output, :indent => 2)
8
+ @quiz = quiz
9
+ end
10
+
11
+ def render(thing)
12
+ case thing
13
+ when MultipleChoice,SelectMultiple,TrueFalse then render_multiple_choice(thing)
14
+ when FillIn then render_fill_in(thing)
15
+ else
16
+ raise "Unknown question type: #{thing}"
17
+ end
18
+ end
19
+
20
+ def render_quiz
21
+ # entire quiz can be in one question group, as long as we specify
22
+ # that ALL question from the group must be used to make the quiz.
23
+ xml_quiz do
24
+ # after preamble...
25
+ @b.question_groups do
26
+ @b.question_group(:select => @quiz.questions.length) do
27
+ @quiz.questions.each do |question|
28
+ self.render(question)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ @output
34
+ end
35
+
36
+ def render_fill_in(question)
37
+ @b.question :type => 'GS_Short_Answer_Question_Simple', :id => question.object_id.to_s(16) do
38
+ @b.metadata {
39
+ @b.parameters {
40
+ @b.rescale_score question.points
41
+ @b.type 'regexp'
42
+ }
43
+ }
44
+ # since we want all the options to appear, we create N option
45
+ # groups each containig 1 option, and specify that option to
46
+ # always be selected for inclusion in the quiz. If the original
47
+ # question specified 'random', use the 'randomize' attribute on
48
+ # option_groups to scramble the order in which displayed;
49
+ # otherwise, display in same order as answers appear in source.
50
+ @b.data {
51
+ @b.text { @b.cdata!(question.question_text) }
52
+ @b.option_groups(:randomize => !!question.randomize) {
53
+ @b.option_group(:select => 'all') {
54
+ question.answers.each do |answer|
55
+ option_args = {}
56
+ option_args['selected_score'] = answer.correct? ? 1 : 0
57
+ option_args['unselected_score'] =
58
+ question.multiple ? 1 - option_args['selected_score'] : 0
59
+ option_args['id'] = answer.object_id.to_s(16)
60
+ @b.option(option_args) do
61
+ answer_text = answer.answer_text
62
+ if answer_text.kind_of?(Regexp)
63
+ answer_text = answer_text.inspect
64
+ if !question.case_sensitive
65
+ answer_text += 'i'
66
+ end
67
+ end
68
+ @b.text { @b.cdata!(answer_text) }
69
+ @b.explanation { @b.cdata!(answer.explanation) } if answer.has_explanation?
70
+ end
71
+ end
72
+ }
73
+ }
74
+ }
75
+ end
76
+ end
77
+
78
+ def render_multiple_choice(question)
79
+ @b.question :type => 'GS_Choice_Answer_Question', :id => question.object_id.to_s(16) do
80
+ @b.metadata {
81
+ @b.parameters {
82
+ @b.rescale_score question.points
83
+ @b.choice_type (question.multiple ? 'checkbox' : 'radio')
84
+ }
85
+ }
86
+ # since we want all the options to appear, we create N option
87
+ # groups each containig 1 option, and specify that option to
88
+ # always be selected for inclusion in the quiz. If the original
89
+ # question specified 'random', use the 'randomize' attribute on
90
+ # option_groups to scramble the order in which displayed;
91
+ # otherwise, display in same order as answers appear in source.
92
+ @b.data {
93
+ @b.text { @b.cdata!(question.question_text) }
94
+ @b.option_groups(:randomize => !!question.randomize) {
95
+ question.answers.each do |a|
96
+ @b.option_group(:select => 'all') {
97
+ self.render_multiple_choice_answer a, question.multiple
98
+ }
99
+ end
100
+ }
101
+ }
102
+ end
103
+ end
104
+ alias :render_true_false :render_multiple_choice
105
+
106
+ def render_multiple_choice_answer(answer, multiple_allowed)
107
+ option_args = {}
108
+ option_args['selected_score'] = answer.correct? ? 1 : 0
109
+ option_args['unselected_score'] =
110
+ multiple_allowed ? 1 - option_args['selected_score'] : 0
111
+ option_args['id'] = answer.object_id.to_s(16)
112
+ @b.option(option_args) do
113
+ @b.text { @b.cdata!(answer.answer_text) }
114
+ @b.explanation { @b.cdata!(answer.explanation) } if answer.has_explanation?
115
+ end
116
+ end
117
+
118
+ private
119
+
120
+ def options_to_xml(h)
121
+ h.each_pair do |k,v|
122
+ if v.is_a?(Hash)
123
+ @b.__send__(k.to_sym) do
124
+ options_to_xml v
125
+ end
126
+ else
127
+ @b.__send__(k.to_sym, v)
128
+ end
129
+ end
130
+ end
131
+
132
+
133
+ def xml_quiz
134
+ @b.quiz do
135
+ @b.metadata do
136
+ @b.type 'quiz'
137
+ @b.title @quiz.title
138
+ options_to_xml @quiz.options
139
+ end
140
+ @b.preamble
141
+ @b.data do
142
+ yield
143
+ end
144
+ end
145
+ end
146
+
147
+ end
148
+
@@ -1,6 +1,10 @@
1
- class SelectMultiple < MultipleChoice
1
+ class SelectMultiple < Question
2
+
3
+ attr_accessor :multiple
4
+
2
5
  def initialize(text='', opts={})
3
6
  super
7
+ self.question_text = text
4
8
  self.multiple = true
5
9
  end
6
10
 
@@ -0,0 +1,18 @@
1
+ module Ruql
2
+ class Stats
3
+ attr_reader :output, :quiz
4
+ # a pseudo-renderer that just prints stats about the quiz
5
+ def initialize(quiz, options={})
6
+ @quiz = quiz
7
+ @output = []
8
+ end
9
+ def render_quiz
10
+ @output << "%3d questions" % quiz.questions.length
11
+ @output << " %3d (%d points) in no group" % [quiz.ungrouped_questions.length, quiz.ungrouped_points]
12
+ @output << " %3d (%d points) in %d groups" % [quiz.grouped_questions.length, quiz.grouped_points, quiz.groups.length]
13
+ @output << "%3d effective questions on quiz" % quiz.num_questions
14
+ @output << "%3d max points possible" % quiz.points
15
+ @output.join("\n")
16
+ end
17
+ end
18
+ end
@@ -1,6 +1,6 @@
1
1
  class TrueFalse < Question
2
2
 
3
- def initialize(text='', correct_answer=false, opts=nil)
3
+ def initialize(text, correct_answer, opts=nil)
4
4
  super
5
5
  opts ||= {}
6
6
  opts[:explanation] ||= ''
@@ -0,0 +1,3 @@
1
+ module Ruql
2
+ VERSION = '1.0.5'
3
+ end
@@ -0,0 +1,43 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'ruql/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'ruql'
8
+ s.version = Ruql::VERSION
9
+ s.summary = "Ruby question language"
10
+ s.description = "Ruby-embedded DSL for creating short-answer quiz questions"
11
+ s.authors = ["Armando Fox"]
12
+ s.email = 'fox@berkeley.edu'
13
+ s.homepage = 'http://github.com/saasbook/ruql'
14
+ s.license = 'CC By-SA'
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ if s.respond_to?(:metadata)
19
+ s.metadata["allowed_push_host"] = "https://rubygems.org"
20
+
21
+ s.metadata["homepage_uri"] = s.homepage
22
+ s.metadata["source_code_uri"] = s.homepage
23
+ #s.metadata["changelog_uri"] = ''
24
+ else
25
+ raise "RubyGems 2.0 or newer is required to protect against " \
26
+ "public gem pushes."
27
+ end
28
+
29
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
30
+ s.files = Dir.chdir(File.expand_path('..', __FILE__)) do
31
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
32
+ end
33
+
34
+ s.executables << 'ruql'
35
+
36
+ s.require_paths= ['lib']
37
+
38
+ s.add_development_dependency "bundler", "~> 1.17"
39
+ s.add_development_dependency "rake", "~> 10.0"
40
+ s.add_development_dependency "byebug"
41
+ s.add_development_dependency "rspec", "~> 3.0"
42
+ s.add_development_dependency "rspec_its"
43
+ end
metadata CHANGED
@@ -1,83 +1,113 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Armando Fox
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-08 00:00:00.000000000 Z
11
+ date: 2020-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
+ name: bundler
14
15
  requirement: !ruby/object:Gem::Requirement
15
16
  requirements:
16
- - - '>='
17
+ - - "~>"
17
18
  - !ruby/object:Gem::Version
18
- version: '3.0'
19
+ version: '1.17'
20
+ type: :development
19
21
  prerelease: false
20
- name: builder
21
22
  version_requirements: !ruby/object:Gem::Requirement
22
23
  requirements:
23
- - - '>='
24
+ - - "~>"
24
25
  - !ruby/object:Gem::Version
25
- version: '3.0'
26
- type: :runtime
26
+ version: '1.17'
27
27
  - !ruby/object:Gem::Dependency
28
+ name: rake
28
29
  requirement: !ruby/object:Gem::Requirement
29
30
  requirements:
30
- - - '>='
31
+ - - "~>"
31
32
  - !ruby/object:Gem::Version
32
- version: '1.0'
33
+ version: '10.0'
34
+ type: :development
33
35
  prerelease: false
34
- name: getopt
35
36
  version_requirements: !ruby/object:Gem::Requirement
36
37
  requirements:
37
- - - '>='
38
+ - - "~>"
38
39
  - !ruby/object:Gem::Version
39
- version: '1.0'
40
- type: :runtime
40
+ version: '10.0'
41
41
  - !ruby/object:Gem::Dependency
42
+ name: byebug
42
43
  requirement: !ruby/object:Gem::Requirement
43
44
  requirements:
44
- - - '>='
45
+ - - ">="
45
46
  - !ruby/object:Gem::Version
46
- version: '2.0'
47
+ version: '0'
48
+ type: :development
47
49
  prerelease: false
48
- name: rspec
49
50
  version_requirements: !ruby/object:Gem::Requirement
50
51
  requirements:
51
- - - '>='
52
+ - - ">="
52
53
  - !ruby/object:Gem::Version
53
- version: '2.0'
54
- type: :development
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
+ name: rspec
56
57
  requirement: !ruby/object:Gem::Requirement
57
58
  requirements:
58
- - - ~>
59
+ - - "~>"
59
60
  - !ruby/object:Gem::Version
60
- version: '4.0'
61
+ version: '3.0'
62
+ type: :development
61
63
  prerelease: false
62
- name: activesupport
63
64
  version_requirements: !ruby/object:Gem::Requirement
64
65
  requirements:
65
- - - ~>
66
+ - - "~>"
66
67
  - !ruby/object:Gem::Version
67
- version: '4.0'
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec_its
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
68
76
  type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  description: Ruby-embedded DSL for creating short-answer quiz questions
70
- email: fox@cs.berkeley.edu
84
+ email: fox@berkeley.edu
71
85
  executables:
72
86
  - ruql
73
87
  extensions: []
74
88
  extra_rdoc_files: []
75
89
  files:
90
+ - ".gitignore"
91
+ - ".travis.yml"
92
+ - Gemfile
93
+ - LICENSE
94
+ - README.md
95
+ - Rakefile
96
+ - bin/console
76
97
  - bin/ruql
98
+ - bin/setup
99
+ - examples/estilo.css
100
+ - examples/example.rb
101
+ - examples/file.html
102
+ - examples/help.txt
103
+ - examples/preguntas-TFG-20140224-0050.txt
104
+ - examples/preguntas-TFG-20140224-0050.xml
105
+ - examples/prueba.js
77
106
  - lib/ruql.rb
78
107
  - lib/ruql/answer.rb
79
108
  - lib/ruql/dropdown.rb
80
109
  - lib/ruql/fill_in.rb
110
+ - lib/ruql/json.rb
81
111
  - lib/ruql/multiple_choice.rb
82
112
  - lib/ruql/open_assessment/criterion.rb
83
113
  - lib/ruql/open_assessment/open_assessment.rb
@@ -93,34 +123,37 @@ files:
93
123
  - lib/ruql/renderers/html_form_renderer.rb
94
124
  - lib/ruql/renderers/json_renderer.rb
95
125
  - lib/ruql/renderers/qualtrics_renderer.rb
126
+ - lib/ruql/renderers/xml_renderer.rb
96
127
  - lib/ruql/select_multiple.rb
128
+ - lib/ruql/stats.rb
97
129
  - lib/ruql/tex_output.rb
98
130
  - lib/ruql/true_false.rb
99
- - templates/autoqcm.tex.erb
100
- - templates/html5.html.erb
101
- - templates/htmlform.html.erb
131
+ - lib/ruql/version.rb
132
+ - ruql.gemspec
102
133
  homepage: http://github.com/saasbook/ruql
103
134
  licenses:
104
- - MIT
105
- metadata: {}
106
- post_install_message:
135
+ - CC By-SA
136
+ metadata:
137
+ allowed_push_host: https://rubygems.org
138
+ homepage_uri: http://github.com/saasbook/ruql
139
+ source_code_uri: http://github.com/saasbook/ruql
140
+ post_install_message:
107
141
  rdoc_options: []
108
142
  require_paths:
109
143
  - lib
110
144
  required_ruby_version: !ruby/object:Gem::Requirement
111
145
  requirements:
112
- - - '>='
146
+ - - ">="
113
147
  - !ruby/object:Gem::Version
114
148
  version: '0'
115
149
  required_rubygems_version: !ruby/object:Gem::Requirement
116
150
  requirements:
117
- - - '>='
151
+ - - ">="
118
152
  - !ruby/object:Gem::Version
119
153
  version: '0'
120
154
  requirements: []
121
- rubyforge_project:
122
- rubygems_version: 2.2.5
123
- signing_key:
155
+ rubygems_version: 3.0.8
156
+ signing_key:
124
157
  specification_version: 4
125
158
  summary: Ruby question language
126
159
  test_files: []