Open jacob-lee opened 4 years ago
Thanks for writing this up! The erroring external hit submit problem bothers me, although interestingly, on reflection, I don't think I've ever experienced it since I moved away from using the psiturk ad server -- are you using the psiturk ad server? Regardless, I'm in favor of switching.
One band-aid though about the reload being deprecated -- we could simply close the experiment task popup, and have a note on the ad that says "if you have completed the task, refresh this page to see a submit button." Tacky, but would be easy to add.
I've looked into this a bit more. Mturk provides three access points to creating a HIT:
QuestionForm -- this is for internal HITs ExternalQuestion -- this is what we've been using HTMLQuestion -- like a QuestionForm but you can use your own HTML and Javascript
The problem with QuestionForm is that it doesn't seem to make WorkerId, AssignmentId, or HITid available; that is, there is no way to dynamically construct a link with those parameters to send it to external server. This isn't going to work well.
HTMLQuestion is more hopeful. I think it is what is being used by some of the HITs that ask for completion codes. The three parameters are made available and can be manipulated by embedded Javascript. Also these can make use of Crowd HTML, sets the correct submission endpoint and inserts a submit button at the end, e.g.,
<HTMLQuestion xmlns="http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2011-11-11/HTMLQuestion.xsd">
<HTMLContent><![CDATA[
<!DOCTYPE html>
<body>
<script src="https://assets.crowd.aws/crowd-html-elements.js"></script>
<crowd-form>
<crowd-classifier
name="sentiment"
categories="['Positive', 'Negative', 'Neutral', 'N/A']"
header="What sentiment does this text convey?"
>
<classification-target>
Everything is wonderful.
</classification-target>
<full-instructions header="Sentiment Analysis Instructions">
<p><strong>Positive</strong>
sentiment include: joy, excitement, delight</p>
<p><strong>Negative</strong> sentiment include:
anger, sarcasm, anxiety</p>
<p><strong>Neutral</strong>: neither positive or
negative, such as stating a fact</p>
<p><strong>N/A</strong>: when the text cannot be
understood</p>
<p>When the sentiment is mixed, such as both joy and sadness,
use your judgment to choose the stronger emotion.</p>
</full-instructions>
<short-instructions>
Choose the primary sentiment that is expressed by the text.
</short-instructions>
</crowd-classifier>
</crowd-form>
</body>
</html>
]]></HTMLContent>
<FrameHeight>0</FrameHeight>
</HTMLQuestion>
and this might have a pretty good likelihood of working as expected.
The thing is is that HTMLQuestion uses the ExternalQuestion end point, mturk/externalSubmit
. At least some of the trouble we've experienced seems to be random failures of single-shot submits failing.
However, it may be the case that because the HTMLQuestion is not hosted externally that the same-origin policy is no longer a barrier to using XHR to make sure it submits correctly. I think I'm going to look at that more closely.
I sort of like the idea of dropping the window.opener.location.reload(true);
in closepopup.html to use the cross-origin message passing interface instead.
The child window can send the parent a message like this:
window.opener.postMessage(message);
and the parent can set up a listener like this:
<script type="text/javascript">
function openwindow() {
popup = window.open('{{ server_location }}/consent?hitId={{ hitid }}&assignmentId={{ assignmentid }}&workerId={{ workerid }}', 'Popup');
window.addEventListener('message', function(e) {
processChildMessage(e.data);
} , false);
}
function processChildMessage(message) {
console.log(message);
var div = document.getElementById('receiver');
var content = document.createTextNode(message);
div.appendChild(content)}), 4000);
// this div content can be html to submit to mturk.
}
</script>
I tested the message passing between my server and a sandboxed HIT. So seems quite feasible as an alternative.
I have pushed a commit here:
https://github.com/jacob-lee/psiTurk/tree/mturk-submit-refactor
This involves
and is based on the do_debug fix PR still pending.
This does not include a change from using external HIT API. At moment I'm concerned with reports that the submit to mturk button was not showing up for people. The code switches to using postMessage to send messages back and forth between the parent and child windows, with Javascript inducing a reload when it is confirmed.
We recently switched off the ad server which I was hoping would solve this problem (as @deargle mentioned) but it unfortunately doesn't seem to have done that. Are there any plans to add this submit refactor in an upcoming release? If it's not ready yet, what still needs to be done?
Observations:
experiment.py
is gnarly and scary to touch.
The current method used to submit to MTurk is unreliable for reasons largely outside of our control.
We use an HTML-embedded line of JavaScript to force the ad page to reload so that a submit button appears that the user can click, and submit simple POST using mturk's External HIT API.
window.opener.location.reload(true);
uses a flag that is deprecated (not part of the spec) and some browsers no longer support it (see: https://stackoverflow.com/questions/55127650/location-reloadtrue-is-deprecated)I want to propose switching over to the use of Mturk's Internal HIT API, in the manner that most Qualtrics HITs on the mturk site: namely, providing a textbox on the mturk site for the subjects to enter in a provided completion code (e.g. generated by python's uuid.uuid4() on the server).
This would require several components:
1. Construction of the Internal HIT.
For this, we would have a question.xml file; there exists a standardized XML schema for this, e.g.
(note: a FreeTextAnswer isn't probably what we are looking for, but it is what I had on hand to use as an example)
2. Getting submitted completion codes
Mturk will return an xml string with the information we want. We just have to parse the xml, e.g. for the above example:
mturk would return as part of its JSON response the following:
which we could retrieve like this:
(note: we'd probably want to use the defusedxml library, which is less vulnerable to an XML exploit).
So, I'm thinking that we would have status:
UnconfirmedSubmit ConfirmedSubmit DisconfirmedSubmit (they gave the wrong completion code; we would want a manual override of this in case of user error) Approved Bonused