-
Notifications
You must be signed in to change notification settings - Fork 31
/
xml_renderer.rb
148 lines (136 loc) · 4.52 KB
/
xml_renderer.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
class XmlRenderer
require 'builder'
attr_reader :output
def initialize(quiz,options={})
@output = ''
@b = Builder::XmlMarkup.new(:target => @output, :indent => 2)
@quiz = quiz
end
def render(thing)
case thing
when MultipleChoice,SelectMultiple,TrueFalse then render_multiple_choice(thing)
when FillIn then render_fill_in(thing)
else
raise "Unknown question type: #{thing}"
end
end
def render_quiz
# entire quiz can be in one question group, as long as we specify
# that ALL question from the group must be used to make the quiz.
xml_quiz do
# after preamble...
@b.question_groups do
@b.question_group(:select => @quiz.questions.length) do
@quiz.questions.each do |question|
self.render(question)
end
end
end
end
@output
end
def render_fill_in(question)
@b.question :type => 'GS_Short_Answer_Question_Simple', :id => question.object_id.to_s(16) do
@b.metadata {
@b.parameters {
@b.rescale_score question.points
@b.type 'regexp'
}
}
# since we want all the options to appear, we create N option
# groups each containig 1 option, and specify that option to
# always be selected for inclusion in the quiz. If the original
# question specified 'random', use the 'randomize' attribute on
# option_groups to scramble the order in which displayed;
# otherwise, display in same order as answers appear in source.
@b.data {
@b.text { @b.cdata!(question.question_text) }
@b.option_groups(:randomize => !!question.randomize) {
@b.option_group(:select => 'all') {
question.answers.each do |answer|
option_args = {}
option_args['selected_score'] = answer.correct? ? 1 : 0
option_args['unselected_score'] =
question.multiple ? 1 - option_args['selected_score'] : 0
option_args['id'] = answer.object_id.to_s(16)
@b.option(option_args) do
answer_text = answer.answer_text
if answer_text.kind_of?(Regexp)
answer_text = answer_text.inspect
if !question.case_sensitive
answer_text += 'i'
end
end
@b.text { @b.cdata!(answer_text) }
@b.explanation { @b.cdata!(answer.explanation) } if answer.has_explanation?
end
end
}
}
}
end
end
def render_multiple_choice(question)
@b.question :type => 'GS_Choice_Answer_Question', :id => question.object_id.to_s(16) do
@b.metadata {
@b.parameters {
@b.rescale_score question.points
@b.choice_type (question.multiple ? 'checkbox' : 'radio')
}
}
# since we want all the options to appear, we create N option
# groups each containig 1 option, and specify that option to
# always be selected for inclusion in the quiz. If the original
# question specified 'random', use the 'randomize' attribute on
# option_groups to scramble the order in which displayed;
# otherwise, display in same order as answers appear in source.
@b.data {
@b.text { @b.cdata!(question.question_text) }
@b.option_groups(:randomize => !!question.randomize) {
question.answers.each do |a|
@b.option_group(:select => 'all') {
self.render_multiple_choice_answer a, question.multiple
}
end
}
}
end
end
alias :render_true_false :render_multiple_choice
def render_multiple_choice_answer(answer, multiple_allowed)
option_args = {}
option_args['selected_score'] = answer.correct? ? 1 : 0
option_args['unselected_score'] =
multiple_allowed ? 1 - option_args['selected_score'] : 0
option_args['id'] = answer.object_id.to_s(16)
@b.option(option_args) do
@b.text { @b.cdata!(answer.answer_text) }
@b.explanation { @b.cdata!(answer.explanation) } if answer.has_explanation?
end
end
private
def options_to_xml(h)
h.each_pair do |k,v|
if v.is_a?(Hash)
@b.__send__(k.to_sym) do
options_to_xml v
end
else
@b.__send__(k.to_sym, v)
end
end
end
def xml_quiz
@b.quiz do
@b.metadata do
@b.type 'quiz'
@b.title @quiz.title
options_to_xml @quiz.options
end
@b.preamble
@b.data do
yield
end
end
end
end