ruql 0.1.5 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,4 +1,5 @@
1
1
  class SelectMultiple < MultipleChoice
2
+
2
3
  def initialize(text='', opts={})
3
4
  super
4
5
  self.multiple = true
@@ -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.1'
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,79 +1,108 @@
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.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Armando Fox
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-08 00:00:00.000000000 Z
11
+ date: 2020-06-03 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
@@ -93,33 +122,36 @@ files:
93
122
  - lib/ruql/renderers/html_form_renderer.rb
94
123
  - lib/ruql/renderers/json_renderer.rb
95
124
  - lib/ruql/renderers/qualtrics_renderer.rb
125
+ - lib/ruql/renderers/xml_renderer.rb
96
126
  - lib/ruql/select_multiple.rb
127
+ - lib/ruql/stats.rb
97
128
  - lib/ruql/tex_output.rb
98
129
  - lib/ruql/true_false.rb
99
- - templates/autoqcm.tex.erb
100
- - templates/html5.html.erb
101
- - templates/htmlform.html.erb
130
+ - lib/ruql/version.rb
131
+ - ruql.gemspec
102
132
  homepage: http://github.com/saasbook/ruql
103
133
  licenses:
104
- - MIT
105
- metadata: {}
134
+ - CC By-SA
135
+ metadata:
136
+ allowed_push_host: https://rubygems.org
137
+ homepage_uri: http://github.com/saasbook/ruql
138
+ source_code_uri: http://github.com/saasbook/ruql
106
139
  post_install_message:
107
140
  rdoc_options: []
108
141
  require_paths:
109
142
  - lib
110
143
  required_ruby_version: !ruby/object:Gem::Requirement
111
144
  requirements:
112
- - - '>='
145
+ - - ">="
113
146
  - !ruby/object:Gem::Version
114
147
  version: '0'
115
148
  required_rubygems_version: !ruby/object:Gem::Requirement
116
149
  requirements:
117
- - - '>='
150
+ - - ">="
118
151
  - !ruby/object:Gem::Version
119
152
  version: '0'
120
153
  requirements: []
121
- rubyforge_project:
122
- rubygems_version: 2.2.5
154
+ rubygems_version: 3.0.8
123
155
  signing_key:
124
156
  specification_version: 4
125
157
  summary: Ruby question language
@@ -1 +0,0 @@
1
- <%= yield %>
@@ -1,42 +0,0 @@
1
- <html>
2
- <head>
3
- <title><%= quiz.title %></title>
4
- <style type="text/css" media="all">
5
- body { font-family: Times, serif; }
6
- .header { text-align: right; font-weight: bold; padding-right: 30%; line-height: 300%; }
7
- h1 { text-align: center; }
8
- ol.questions { list-style-type: number; }
9
- li.question { page-break-inside: avoid; border-bottom: 1px solid grey; }
10
- li.multiplechoice ol.answers { list-style-type: lower-alpha; }
11
- li.selectmultiple ol.answers { vertical-align: center; list-style-type: none; list-style-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUAQMAAAC3R49OAAAABlBMVEUAAAD///+l2Z/dAAAAEklEQVQImWNgAIL6/w+ogoEAAKI4Kp2NVIeDAAAAAElFTkSuQmCC'); }
12
- li.truefalse ol.answers { list-style-type: none; }
13
- .correct { color: green; font-weight: bold; border: 1px solid black; padding: 0.2ex; }
14
- .incorrect { color: red }
15
- .explanation { font-style: italic }
16
- .instructions { clear: both; border: 1px solid black; align: center; padding: 2ex; margin: 2ex; }
17
- </style>
18
- </head>
19
- <body>
20
- <div class="header">
21
- <div id="name">Name:</div>
22
- <div id="sid">SID:</div>
23
- </div>
24
- <h1><%= quiz.title %></h1>
25
- <div class="instructions">
26
- <ul>
27
- <li>No books, notes, or electronic devices allowed. </li>
28
- <li>Time limit is 30 minutes.</li>
29
- <li><%= quiz.num_questions %> multiple-choice questions, points indicated per question,
30
- <%= quiz.points %> points total. Points per question are intended
31
- to reflect approximate times they should take, at about 1 point per minute.</li>
32
- <li>For 'select all that apply' questions worth N points,
33
- you get 1/N of the points for each RIGHT answer that you check, plus
34
- 1/N of the points for each WRONG answer that you correctly
35
- leave unchecked. That is, equal weight is given to deciding
36
- whether each choice is part of the right answer or not.</li>
37
- </ul>
38
- <b>Good skill!</b>
39
- </div>
40
- <%= yield %>
41
- </body>
42
- </html>