Skip to content

Commit 6ee329e

Browse files
Brad Horrocksrivernate
authored andcommitted
The turnitin submission endpoint should save originality data
Fires off delayed job that hits the turnitin callback url, creates a submission, and maps originality data into the turnitin_data field. Fixes PLAT-1167 Fixes PLAT-1169 Test Plan: You'll need to have the TurnItIn LTI tool installed, and delayed_jobs running Create an assignment with the submission set to the External Tool for turnitin. As a student, submit the assignment. wait for the delayed job to run. check out /jobs to see whats going on After the job has ran you should see turnitin data, as you would normally with the plugin Change-Id: I5d60d250e91b422b5e77255d715abf2e4712f130 Reviewed-on: https://gerrit.instructure.com/59942 Tested-by: Jenkins Reviewed-by: Nathan Mills <nathanm@instructure.com> Product-Review: Nathan Mills <nathanm@instructure.com> QA-Review: Nathan Mills <nathanm@instructure.com>
1 parent 05be16b commit 6ee329e

5 files changed

Lines changed: 80 additions & 16 deletions

File tree

app/controllers/submissions_controller.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,11 @@ def turnitin_report
539539
@submission = @assignment.submissions.where(user_id: params[:submission_id]).first
540540
@asset_string = params[:asset_string]
541541
if authorized_action(@submission, @current_user, :read)
542-
url = @submission.turnitin_report_url(@asset_string, @current_user) rescue nil
542+
if (report_url = @submission.turnitin_data[@asset_string] && @submission.turnitin_data[@asset_string][:report_url])
543+
url = polymorphic_url([:retrieve, @context, :external_tools], url:report_url, display:'borderless')
544+
else
545+
url = @submission.turnitin_report_url(@asset_string, @current_user) rescue nil
546+
end
543547
if url
544548
redirect_to url
545549
else

app/models/submission.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -301,11 +301,7 @@ def check_turnitin_status(attempt=1)
301301
data[:web_overlap] = res[:web_overlap].to_f
302302
data[:publication_overlap] = res[:publication_overlap].to_f
303303
data[:student_overlap] = res[:student_overlap].to_f
304-
data[:state] = 'failure'
305-
data[:state] = 'problem' if data[:similarity_score] < 75
306-
data[:state] = 'warning' if data[:similarity_score] < 50
307-
data[:state] = 'acceptable' if data[:similarity_score] < 25
308-
data[:state] = 'none' if data[:similarity_score] == 0
304+
data[:state] = Turnitin.state_from_similarity_score data[:similarity_score]
309305
data[:status] = 'scored'
310306
else
311307
needs_retry ||= true

gems/turnitin_api/lib/turnitin_api/outcomes_response_transformer.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ def originality_data
3131
response.body['outcome_originalityreport'].select {|k, _| %w(breakdown numeric).include?(k)}
3232
end
3333

34+
def scored?
35+
originality_data["numeric"]["score"].present?
36+
end
37+
3438
private
3539

3640
def connection

lib/turnitin.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@
1919
require 'turnitin/response'
2020

2121
module Turnitin
22+
def self.state_from_similarity_score(similarity_score)
23+
return 'none' if similarity_score == 0
24+
return 'acceptable' if similarity_score < 25
25+
return 'warning' if similarity_score < 50
26+
return 'problem' if similarity_score < 75
27+
'failure'
28+
end
29+
2230
class Client
2331
attr_accessor :endpoint, :account_id, :shared_secret, :host, :testing
2432

lib/turnitin/outcome_response_processor.rb

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,73 @@
22
module Turnitin
33
class OutcomeResponseProcessor
44

5+
MAX_ATTEMPTS=11.freeze # this one goes to 11
6+
INTERVAL=5.minutes.freeze
57
def initialize(tool, assignment, user, outcomes_response_json)
68
@tool = tool
79
@assignment = assignment
810
@user = user
911
@outcomes_response_json = outcomes_response_json
1012
end
1113

12-
1314
def process
1415
attachment = create_attachment
15-
@assignment.submit_homework(@user ,attachments:[attachment], submission_type: 'online_upload')
16+
submission = @assignment.submit_homework(@user, attachments:[attachment], submission_type: 'online_upload')
17+
self.send_later(:update_originality_data, submission, attachment.asset_string)
1618
end
1719
handle_asynchronously :process, max_attempts: 1, priority: Delayed::LOW_PRIORITY
1820

19-
private
20-
21-
def create_attachment
22-
23-
lti_params = {
21+
def turnitin_client
22+
@turnitin_client ||= (
23+
lti_params = {
2424
'user_id' => Lti::Asset.opaque_identifier_for(@user),
2525
'context_id' => Lti::Asset.opaque_identifier_for(@assignment.context),
2626
'context_title' => @assignment.context.name,
2727
'lis_person_contact_email_primary' => @user.email
28-
}
29-
turnitin_client = TurnitinApi::OutcomesResponseTransformer.new(@tool.consumer_key, @tool.shared_secret, lti_params, @outcomes_response_json)
28+
}
29+
30+
TurnitinApi::OutcomesResponseTransformer.new(
31+
@tool.consumer_key,
32+
@tool.shared_secret,
33+
lti_params,
34+
@outcomes_response_json
35+
)
36+
)
37+
end
38+
39+
def update_originality_data(submission, asset_string, attempt=1)
40+
if turnitin_client.scored?
41+
all_data = submission.turnitin_data || {}
42+
all_data[asset_string] = turnitin_data
43+
submission.update_attribute('turnitin_data', all_data)
44+
submission.turnitin_data_changed!
45+
submission.save
46+
elsif attempt <= MAX_ATTEMPTS
47+
send_at(INTERVAL.from_now, :update_originality_data, submission, asset_string, attempt + 1)
48+
end
49+
end
50+
51+
52+
# dont try and recreate the turnitin client in a delayed job. bad things happen
53+
def send_later(*args)
54+
stash { super(*args) }
55+
end
56+
57+
# dont try and recreate the turnitin client in a delayed job. bad things happen
58+
def send_at(*args)
59+
stash { super(*args) }
60+
end
61+
62+
private
63+
64+
def stash
65+
old_turnit_client = @turnitin_client
66+
@turnitin_client = nil
67+
yield
68+
@turnitin_client = old_turnit_client
69+
end
70+
71+
def create_attachment
3072
attachment = nil
3173
Dir.mktmpdir do |dirname|
3274
turnitin_client.original_submission do |response|
@@ -46,6 +88,16 @@ def create_attachment
4688
attachment
4789
end
4890

91+
def turnitin_data
92+
{
93+
similarity_score: turnitin_client.originality_data["numeric"]["score"].to_f,
94+
web_overlap: turnitin_client.originality_data["breakdown"]["internet_score"].to_f,
95+
publication_overlap: turnitin_client.originality_data["breakdown"]["publications_score"].to_f,
96+
student_overlap: turnitin_client.originality_data["breakdown"]["submitted_works_score"].to_f,
97+
state: Turnitin.state_from_similarity_score(turnitin_client.originality_data["numeric"]["score"].to_f),
98+
report_url: turnitin_client.originality_report_url,
99+
status: "scored"
100+
}
101+
end
49102
end
50-
51103
end

0 commit comments

Comments
 (0)