rturk 2.10.3 → 2.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +1 -0
- data/.travis.yml +1 -2
- data/Gemfile +1 -1
- data/README.markdown +15 -8
- data/examples/create_hit.rb +1 -1
- data/lib/rturk/adapters/assignment.rb +2 -0
- data/lib/rturk/adapters/hit.rb +11 -5
- data/lib/rturk/builders/answer_key_builder.rb +39 -0
- data/lib/rturk/builders/{question_builder.rb → external_question_builder.rb} +14 -14
- data/lib/rturk/builders/qualification_builder.rb +28 -12
- data/lib/rturk/builders/qualifications_builder.rb +3 -1
- data/lib/rturk/builders/question_form_builder.rb +86 -0
- data/lib/rturk/operations/create_hit.rb +16 -8
- data/lib/rturk/operations/register_hit_type.rb +2 -2
- data/lib/rturk/parsers/responses/get_assignments_for_hit_response.rb +21 -5
- data/lib/rturk/parsers/responses/get_hit_response.rb +3 -2
- data/lib/rturk/parsers/responses/get_reviewable_hits_response.rb +20 -5
- data/lib/rturk/parsers/responses/search_hits_response.rb +23 -7
- data/lib/rturk/requester.rb +1 -1
- data/lib/rturk/version.rb +1 -1
- data/rturk.gemspec +3 -2
- data/spec/builders/answer_key_builder_spec.rb +26 -0
- data/spec/builders/{question_spec.rb → external_question_spec.rb} +20 -20
- data/spec/builders/question_form_builder_spec.rb +75 -0
- data/spec/example_question_form.rb +106 -0
- data/spec/example_question_form.xml +64 -0
- data/spec/operations/create_hit_spec.rb +33 -6
- data/spec/requester_spec.rb +8 -0
- data/spec/spec_helper.rb +4 -1
- metadata +114 -121
@@ -1,7 +1,7 @@
|
|
1
1
|
module RTurk
|
2
2
|
class RegisterHITType < Operation
|
3
3
|
|
4
|
-
attr_accessor :title, :description, :reward, :currency, :duration, :keywords, :
|
4
|
+
attr_accessor :title, :description, :reward, :currency, :duration, :keywords, :auto_approval_delay
|
5
5
|
|
6
6
|
|
7
7
|
# @param [Symbol, Hash] qualification_key opts The unique qualification key
|
@@ -54,7 +54,7 @@ module RTurk
|
|
54
54
|
'Reward.Amount' => reward,
|
55
55
|
'Reward.CurrencyCode' => (currency || 'USD'),
|
56
56
|
'Keywords' => keyword_string,
|
57
|
-
'AutoApprovalDelayInSeconds' =>
|
57
|
+
'AutoApprovalDelayInSeconds' => auto_approval_delay }
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -27,9 +27,9 @@
|
|
27
27
|
# </GetAssignmentsForHITResult>
|
28
28
|
|
29
29
|
module RTurk
|
30
|
-
|
30
|
+
|
31
31
|
class GetAssignmentsForHITResponse < Response
|
32
|
-
|
32
|
+
|
33
33
|
def assignments
|
34
34
|
@assignments ||= []
|
35
35
|
@xml.xpath('//Assignment').each do |assignment_xml|
|
@@ -37,7 +37,23 @@ module RTurk
|
|
37
37
|
end
|
38
38
|
@assignments
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
|
+
# todo: test
|
42
|
+
def total_num_results
|
43
|
+
@xml.xpath('//TotalNumResults').inner_text.to_i
|
44
|
+
end
|
45
|
+
|
46
|
+
# todo: test
|
47
|
+
def num_results
|
48
|
+
@xml.xpath('//NumResults').inner_text.to_i
|
49
|
+
end
|
50
|
+
|
51
|
+
# todo: test
|
52
|
+
def page_number
|
53
|
+
@xml.xpath('//PageNumber').inner_text.to_i
|
54
|
+
end
|
55
|
+
|
56
|
+
|
41
57
|
end
|
42
|
-
|
43
|
-
end
|
58
|
+
|
59
|
+
end
|
@@ -49,7 +49,7 @@ module RTurk
|
|
49
49
|
:auto_approval_delay, :description, :reward, :lifetime, :annotation,
|
50
50
|
:similar_hits_count, :assignments_pending_count, :assignments_available_count,
|
51
51
|
:assignments_completed_count, :question_external_url, :qualification_requirement_comparator,
|
52
|
-
:qualification_requirement_value
|
52
|
+
:qualification_requirement_value, :question
|
53
53
|
|
54
54
|
def initialize(response)
|
55
55
|
@raw_xml = response.body
|
@@ -78,7 +78,8 @@ module RTurk
|
|
78
78
|
:assignments_completed_count => 'NumberOfAssignmentsCompleted',
|
79
79
|
:question_external_url => 'Question/*/*[1]',
|
80
80
|
:qualification_requirement_comparator => 'QualificationRequirement/Comparator',
|
81
|
-
:qualification_requirement_value => 'QualificationRequirement/IntegerValue'
|
81
|
+
:qualification_requirement_value => 'QualificationRequirement/IntegerValue',
|
82
|
+
:question => 'Question'
|
82
83
|
)
|
83
84
|
|
84
85
|
@keywords = @keywords.split(', ') if @keywords
|
@@ -17,15 +17,30 @@
|
|
17
17
|
# </GetReviewableHITsResult>
|
18
18
|
|
19
19
|
module RTurk
|
20
|
-
|
20
|
+
|
21
21
|
class GetReviewableHITsResponse < Response
|
22
|
-
|
22
|
+
|
23
23
|
def hit_ids
|
24
24
|
@xml.xpath('//HIT').inject([]) do |arr, hit_xml|
|
25
25
|
arr << hit_xml.inner_text.strip; arr
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
|
+
# todo: test
|
30
|
+
def total_num_results
|
31
|
+
@xml.xpath('//TotalNumResults').inner_text.to_i
|
32
|
+
end
|
33
|
+
|
34
|
+
# todo: test
|
35
|
+
def num_results
|
36
|
+
@xml.xpath('//NumResults').inner_text.to_i
|
37
|
+
end
|
38
|
+
|
39
|
+
# todo: test
|
40
|
+
def page_number
|
41
|
+
@xml.xpath('//PageNumber').inner_text.to_i
|
42
|
+
end
|
43
|
+
|
29
44
|
end
|
30
|
-
|
31
|
-
end
|
45
|
+
|
46
|
+
end
|
@@ -6,7 +6,7 @@ module RTurk
|
|
6
6
|
# <NumResults>2</NumResults>
|
7
7
|
# <TotalNumResults>2</TotalNumResults>
|
8
8
|
# <PageNumber>1</PageNumber>
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# <HIT>
|
11
11
|
# <HITId>GBHZVQX3EHXZ2AYDY2T0</HITId>
|
12
12
|
# <HITTypeId>NYVZTQ1QVKJZXCYZCZVZ</HITTypeId>
|
@@ -27,7 +27,7 @@ module RTurk
|
|
27
27
|
# <NumberOfAssignmentsAvailable>0</NumberOfAssignmentsAvailable>
|
28
28
|
# <NumberOfAssignmentsCompleted>1</NumberOfAssignmentsCompleted>
|
29
29
|
# </HIT>
|
30
|
-
#
|
30
|
+
#
|
31
31
|
# <HIT>
|
32
32
|
# <HITId>ZZRZPTY4ERDZWJ868JCZ</HITId>
|
33
33
|
# <HITTypeId>NYVZTQ1QVKJZXCYZCZVZ</HITTypeId>
|
@@ -49,9 +49,9 @@ module RTurk
|
|
49
49
|
# <NumberOfAssignmentsCompleted>0</NumberOfAssignmentsCompleted>
|
50
50
|
# </HIT>
|
51
51
|
# </SearchHITsResult>
|
52
|
-
|
52
|
+
|
53
53
|
class SearchHITsResponse < Response
|
54
|
-
|
54
|
+
|
55
55
|
def hits
|
56
56
|
@hits ||= begin
|
57
57
|
@xml.xpath('//HIT').inject([]) do |arr, hit_xml|
|
@@ -59,7 +59,23 @@ module RTurk
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
|
+
# todo: merge with GetReviewableHITsResponse and GetAssignmentsForHITResponse
|
64
|
+
# todo: test
|
65
|
+
def total_num_results
|
66
|
+
@xml.xpath('//TotalNumResults').inner_text.to_i
|
67
|
+
end
|
68
|
+
|
69
|
+
# todo: test
|
70
|
+
def num_results
|
71
|
+
@xml.xpath('//NumResults').inner_text.to_i
|
72
|
+
end
|
73
|
+
|
74
|
+
# todo: test
|
75
|
+
def page_number
|
76
|
+
@xml.xpath('//PageNumber').inner_text.to_i
|
77
|
+
end
|
78
|
+
|
63
79
|
end
|
64
|
-
|
65
|
-
end
|
80
|
+
|
81
|
+
end
|
data/lib/rturk/requester.rb
CHANGED
data/lib/rturk/version.rb
CHANGED
data/rturk.gemspec
CHANGED
@@ -25,8 +25,9 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
26
26
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
27
27
|
s.require_paths = ["lib"]
|
28
|
-
s.add_dependency('rest-client'
|
29
|
-
s.add_dependency('nokogiri'
|
28
|
+
s.add_dependency('rest-client')
|
29
|
+
s.add_dependency('nokogiri')
|
30
|
+
s.add_dependency('erector')
|
30
31
|
|
31
32
|
# Development dependencies
|
32
33
|
s.add_development_dependency('rspec', "~> 1.3.1")
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
require 'rturk/builders/answer_key_builder'
|
3
|
+
|
4
|
+
module RTurk
|
5
|
+
describe AnswerKey do
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
end
|
9
|
+
|
10
|
+
class SillyAnswerKey < AnswerKey
|
11
|
+
def answer_key_content
|
12
|
+
Question "Why did the chicken cross the road?"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "is an abstract base class that calls down to 'answer_key_content' in its concrete subclasses" do
|
17
|
+
RTurk::SillyAnswerKey.new.to_xml.should ==
|
18
|
+
"<AnswerKey xmlns=\"#{RTurk::AnswerKey::XMLNS}\">" +
|
19
|
+
"<Question>Why did the chicken cross the road?</Question>" +
|
20
|
+
"</AnswerKey>"
|
21
|
+
end
|
22
|
+
|
23
|
+
# todo: test more
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -1,52 +1,52 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
2
|
require 'cgi'
|
3
3
|
|
4
|
-
describe RTurk::
|
5
|
-
|
4
|
+
describe RTurk::ExternalQuestion do
|
5
|
+
|
6
6
|
before(:all) do
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
it "should build a question" do
|
10
|
-
question = RTurk::
|
11
|
-
question.url.should == 'http://mpercival.com'
|
10
|
+
question = RTurk::ExternalQuestion.new('http://mpercival.com')
|
11
|
+
question.url.should == 'http://mpercival.com'
|
12
12
|
question.frame_height.should == 400
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should build a question " do
|
16
|
-
question = RTurk::
|
16
|
+
question = RTurk::ExternalQuestion.new('http://mpercival.com', :frame_height => 500, :chapter => 1)
|
17
17
|
question.params[:chapter] = 2
|
18
|
-
question.url.should == 'http://mpercival.com?chapter=2'
|
18
|
+
question.url.should == 'http://mpercival.com?chapter=2'
|
19
19
|
question.frame_height.should == 500
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
it "should build a question " do
|
23
|
-
question = RTurk::
|
23
|
+
question = RTurk::ExternalQuestion.new('http://mpercival.com?myparam=true&anotherparam=12', :frame_height => 500)
|
24
24
|
question.url.should == 'http://mpercival.com?myparam=true&anotherparam=12'
|
25
25
|
question.frame_height.should == 500
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
it "should build a question with params" do
|
29
|
-
params = RTurk::
|
30
|
-
CGI.unescape(params).should ==
|
29
|
+
params = RTurk::ExternalQuestion.new('http://google.com/', :id => 'foo').to_params
|
30
|
+
CGI.unescape(params).should ==
|
31
31
|
<<-XML
|
32
32
|
<ExternalQuestion xmlns="http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2006-07-14/ExternalQuestion.xsd">
|
33
|
-
<ExternalURL>http://google.com/?id=foo</ExternalURL>
|
33
|
+
<ExternalURL>http://google.com/?id=foo</ExternalURL>
|
34
34
|
<FrameHeight>400</FrameHeight>
|
35
35
|
</ExternalQuestion>
|
36
36
|
XML
|
37
37
|
end
|
38
38
|
|
39
39
|
it "should build a question without params" do
|
40
|
-
params = RTurk::
|
41
|
-
CGI.unescape(params).should ==
|
40
|
+
params = RTurk::ExternalQuestion.new('http://google.com/').to_params
|
41
|
+
CGI.unescape(params).should ==
|
42
42
|
<<-XML
|
43
43
|
<ExternalQuestion xmlns="http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2006-07-14/ExternalQuestion.xsd">
|
44
|
-
<ExternalURL>http://google.com/</ExternalURL>
|
44
|
+
<ExternalURL>http://google.com/</ExternalURL>
|
45
45
|
<FrameHeight>400</FrameHeight>
|
46
46
|
</ExternalQuestion>
|
47
47
|
XML
|
48
48
|
end
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
require 'rturk/builders/question_form_builder'
|
3
|
+
|
4
|
+
module RTurk
|
5
|
+
describe QuestionForm do
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should build a question, using its xml param as the full QuestionForm since it starts with <QuestionForm" do
|
11
|
+
xml = <<-XML
|
12
|
+
<QuestionForm xmlns="#{RTurk::QuestionForm::XMLNS}">
|
13
|
+
[...]
|
14
|
+
</QuestionForm>
|
15
|
+
XML
|
16
|
+
question = RTurk::QuestionForm.new(:xml => xml)
|
17
|
+
question.to_params.should == xml
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should build a question, using its xml param as the QuestionForm content" do
|
21
|
+
question = RTurk::QuestionForm.new(:xml => "[...]")
|
22
|
+
question.to_params.should ==
|
23
|
+
"<QuestionForm xmlns=\"#{RTurk::QuestionForm::XMLNS}\">[...]</QuestionForm>"
|
24
|
+
end
|
25
|
+
|
26
|
+
class SillyQuestionForm < QuestionForm
|
27
|
+
def question_form_content
|
28
|
+
Question "Why did the chicken cross the road?"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "is an abstract base class that calls down to 'question_form_content' in its concrete subclasses" do
|
33
|
+
RTurk::SillyQuestionForm.new.to_xml.should ==
|
34
|
+
"<QuestionForm xmlns=\"#{RTurk::QuestionForm::XMLNS}\">" +
|
35
|
+
"<Question>Why did the chicken cross the road?</Question>" +
|
36
|
+
"</QuestionForm>"
|
37
|
+
end
|
38
|
+
|
39
|
+
class AnotherSillyQuestionForm < QuestionForm
|
40
|
+
def question_form_content
|
41
|
+
question {
|
42
|
+
question_content {
|
43
|
+
Text "How many licks?" # note: Text vs text vs text_element gotcha
|
44
|
+
}
|
45
|
+
answer_specification {
|
46
|
+
free_text_answer {
|
47
|
+
constraints {
|
48
|
+
is_numeric true
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "allows snake_case element names" do
|
57
|
+
RTurk::AnotherSillyQuestionForm.new.to_xml.should ==
|
58
|
+
"<QuestionForm xmlns=\"#{RTurk::QuestionForm::XMLNS}\">" +
|
59
|
+
"<Question>" +
|
60
|
+
"<QuestionContent>" +
|
61
|
+
"<Text>How many licks?</Text>" +
|
62
|
+
"</QuestionContent>" +
|
63
|
+
"<AnswerSpecification>" +
|
64
|
+
"<FreeTextAnswer>" +
|
65
|
+
"<Constraints>" +
|
66
|
+
"<IsNumeric>true</IsNumeric>" +
|
67
|
+
"</Constraints>" +
|
68
|
+
"</FreeTextAnswer>" +
|
69
|
+
"</AnswerSpecification>" +
|
70
|
+
"</Question>" +
|
71
|
+
"</QuestionForm>"
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
class ExampleQuestionForm < RTurk::QuestionForm
|
2
|
+
def question_form_content
|
3
|
+
Overview do
|
4
|
+
Title do
|
5
|
+
text 'Game 01523, "X" to play'
|
6
|
+
end
|
7
|
+
Text do
|
8
|
+
text 'You are helping to decide the next move in a game of Tic-Tac-Toe. The board looks like this:'
|
9
|
+
end
|
10
|
+
Binary do
|
11
|
+
MimeType do
|
12
|
+
Type do
|
13
|
+
text 'image'
|
14
|
+
end
|
15
|
+
SubType do
|
16
|
+
text 'gif'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
DataURL do
|
20
|
+
text 'http://tictactoe.amazon.com/game/01523/board.gif'
|
21
|
+
end
|
22
|
+
AltText do
|
23
|
+
text 'The game board, with "X" to move.'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
Text do
|
27
|
+
text 'Player "X" has the next move.'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
Question do
|
31
|
+
QuestionIdentifier do
|
32
|
+
text 'nextmove'
|
33
|
+
end
|
34
|
+
DisplayName do
|
35
|
+
text 'The Next Move'
|
36
|
+
end
|
37
|
+
IsRequired do
|
38
|
+
text 'true'
|
39
|
+
end
|
40
|
+
QuestionContent do
|
41
|
+
Text do
|
42
|
+
text 'What are the coordinates of the best move for player "X" in this game?'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
AnswerSpecification do
|
46
|
+
FreeTextAnswer do
|
47
|
+
Constraints do
|
48
|
+
Length :minLength => '2', :maxLength => '2'
|
49
|
+
end
|
50
|
+
DefaultText do
|
51
|
+
text 'C1'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
Question do
|
57
|
+
QuestionIdentifier do
|
58
|
+
text 'likelytowin'
|
59
|
+
end
|
60
|
+
DisplayName do
|
61
|
+
text 'The Next Move'
|
62
|
+
end
|
63
|
+
IsRequired do
|
64
|
+
text 'true'
|
65
|
+
end
|
66
|
+
QuestionContent do
|
67
|
+
Text do
|
68
|
+
text 'How likely is it that player "X" will win this game?'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
AnswerSpecification do
|
72
|
+
SelectionAnswer do
|
73
|
+
StyleSuggestion do
|
74
|
+
text 'radiobutton'
|
75
|
+
end
|
76
|
+
Selections do
|
77
|
+
Selection do
|
78
|
+
SelectionIdentifier do
|
79
|
+
text 'notlikely'
|
80
|
+
end
|
81
|
+
Text do
|
82
|
+
text 'Not likely'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
Selection do
|
86
|
+
SelectionIdentifier do
|
87
|
+
text 'unsure'
|
88
|
+
end
|
89
|
+
Text do
|
90
|
+
text 'It could go either way'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
Selection do
|
94
|
+
SelectionIdentifier do
|
95
|
+
text 'likely'
|
96
|
+
end
|
97
|
+
Text do
|
98
|
+
text 'Likely'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|