use BigDecimal to compute numeric error margin
test plan: - create numeric answer questions with error margins - copy the course - in the copied quiz, the error margins should match the original course (show as 0.0001 and not something like 0.00009999999999889) fixes CNVS-19615 Change-Id: Iba9e40f9e37323310e6414794139c68d0f1c061c Reviewed-on: https://gerrit.instructure.com/51334 Reviewed-by: James Williams <jamesw@instructure.com> Tested-by: Jenkins QA-Review: Clare Strong <clare@instructure.com> Product-Review: Jeremy Stanley <jeremy@instructure.com>
This commit is contained in:
parent
84215a4e09
commit
01b8bae52d
|
@ -1,3 +1,5 @@
|
|||
require 'bigdecimal'
|
||||
|
||||
module Qti
|
||||
class NumericInteraction < AssessmentItemConverter
|
||||
def initialize(opts={})
|
||||
|
@ -39,11 +41,13 @@ class NumericInteraction < AssessmentItemConverter
|
|||
exact_node = or_node.at_css('stringMatch baseValue')
|
||||
next unless exact_node
|
||||
answer[:numerical_answer_type] = 'exact_answer'
|
||||
exact = exact_node.text.to_f rescue 0.0
|
||||
answer[:exact] = exact
|
||||
exact = exact_node.text rescue "0.0"
|
||||
answer[:exact] = exact.to_f
|
||||
if upper = or_node.at_css('and customOperator[class=varlte] baseValue')
|
||||
margin = upper.text.to_f - exact rescue 0.0
|
||||
answer[:margin] = margin
|
||||
# do margin computation with BigDecimal to avoid rounding errors
|
||||
# (this is also used when _scoring_ numeric range questions)
|
||||
margin = BigDecimal.new(upper.text) - BigDecimal.new(exact) rescue "0.0"
|
||||
answer[:margin] = margin.to_f
|
||||
end
|
||||
@question[:answers] << answer
|
||||
elsif and_node = r_if.at_css('and')
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
require 'bigdecimal'
|
||||
|
||||
module CC
|
||||
module QTI
|
||||
module QTIItems
|
||||
|
@ -340,9 +342,10 @@ module CC
|
|||
or_node.varequal exact, :respident=>"response1"
|
||||
unless answer['margin'].blank?
|
||||
or_node.and do |and_node|
|
||||
margin = answer['margin'].to_f
|
||||
and_node.vargte(exact - margin, :respident=>"response1")
|
||||
and_node.varlte(exact + margin, :respident=>"response1")
|
||||
exact = BigDecimal.new(answer['exact'].to_s)
|
||||
margin = BigDecimal.new(answer['margin'].to_s)
|
||||
and_node.vargte((exact - margin).to_f, :respident=>"response1")
|
||||
and_node.varlte((exact + margin).to_f, :respident=>"response1")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -650,6 +650,38 @@ equation: <img class="equation_image" title="Log_216" src="/equation_images/Log_
|
|||
expect(decoy_assignment_group.reload.name).not_to eql group.name
|
||||
end
|
||||
|
||||
it "should round numeric answer margins sanely" do
|
||||
q = @copy_from.quizzes.create!(:title => "blah")
|
||||
# this one targets rounding errors in gems/plugins/qti_exporter/lib/qti/numeric_interaction.rb (import side)
|
||||
data1 = {:question_type => "numerical_question",
|
||||
:question_text => "what is the optimal matter/antimatter intermix ratio",
|
||||
:answers => [{
|
||||
:text => "answer_text",
|
||||
:weight => 100,
|
||||
:numerical_answer_type => "exact_answer",
|
||||
:answer_exact => 1,
|
||||
:answer_error_margin => 0.0001
|
||||
}]}.with_indifferent_access
|
||||
# this one targets rounding errors in lib/cc/qti/qti_items.rb (export side)
|
||||
data2 = {:question_type => "numerical_question",
|
||||
:question_text => "what is the airspeed velocity of an unladed African swallow",
|
||||
:answers => [{
|
||||
:text => "answer_text",
|
||||
:weight => 100,
|
||||
:numerical_answer_type => "exact_answer",
|
||||
:answer_exact => 2.0009,
|
||||
:answer_error_margin => 0.0001
|
||||
}]}.with_indifferent_access
|
||||
|
||||
q.quiz_questions.create!(:question_data => data1)
|
||||
q.quiz_questions.create!(:question_data => data2)
|
||||
run_course_copy
|
||||
|
||||
q2 = @copy_to.quizzes.where(migration_id: mig_id(q)).first
|
||||
expect(q2.quiz_questions[0].question_data["answers"][0]["margin"].to_s).to eq "0.0001"
|
||||
expect(q2.quiz_questions[1].question_data["answers"][0]["margin"].to_s).to eq "0.0001"
|
||||
end
|
||||
|
||||
it "should not combine when copying question banks with the same title" do
|
||||
data = {'question_name' => 'test question 1', 'question_type' => 'essay_question', 'question_text' => 'blah'}
|
||||
|
||||
|
@ -685,7 +717,7 @@ equation: <img class="equation_image" title="Log_216" src="/equation_images/Log_
|
|||
expect(group2_copy.assessment_question_bank_id).to eq bank2_copy.id
|
||||
end
|
||||
|
||||
it "hould copy stuff" do
|
||||
it "should copy stuff" do
|
||||
data1 = {:question_type => "file_upload_question",
|
||||
:points_possible => 10,
|
||||
:question_text => "why is this question terrible"
|
||||
|
|
Loading…
Reference in New Issue