From ed96043f86c41e0feabd066163de2a7caa6af43b Mon Sep 17 00:00:00 2001 From: gbernal Date: Sat, 10 Apr 2021 14:49:51 -0400 Subject: [PATCH 1/3] Made changes to make project compatible with psiturk v3 --- README.md | 2 +- config.txt | 237 +++++++++++++++++++-- custom.py | 2 +- static/css/style.css | 26 ++- static/js/task.js | 23 +- templates/closepopup.html | 16 ++ templates/consent.html | 5 +- templates/default.html | 54 +++-- templates/exp.html | 2 +- templates/instructions/instruct-ready.html | 4 +- templates/layouts/layout.html | 20 ++ templates/thanks-mturksubmit.html | 45 ++++ templates/thanks.html | 17 ++ 13 files changed, 390 insertions(+), 63 deletions(-) create mode 100644 templates/closepopup.html create mode 100644 templates/layouts/layout.html create mode 100644 templates/thanks-mturksubmit.html create mode 100644 templates/thanks.html diff --git a/README.md b/README.md index cd2e434..9c9d118 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ account on psiturk.org. **Run live** 1. If all is going well and looks how you expect, `[psiTurk server:on mode:sdbx #HITs:0]$ mode` - to switch to "live" mode -1. `[psiTurk server:on mode:live #HITs:0]$ create hit` - to create the hit on the live server +1. `[psiTurk server:on mode:live #HITs:0]$ hit create` - to create the hit on the live server 1. `[psiTurk server:on mode:live #HITs:0]$ hit list active` - to monitor the progress 1. `[psiTurk server:on mode:live #HITs:0]$ worker approve --hit ` - to approve and pay everyone who has finished diff --git a/config.txt b/config.txt index b42546e..44e1af3 100644 --- a/config.txt +++ b/config.txt @@ -1,35 +1,226 @@ +####################### Psiturk Configuration Defaults ######################### +# +# Example config file. Uncomment lines (remove the `;`) +# in order to override defaults. +# + +############################ HIT Configuration ################################# [HIT Configuration] -title = Draw together - Super EASY and fun! -description = Draw a simple picture using your computer mouse. -amt_keywords = Art, Fun, Creativity +# Title that will be used for the HIT when posted to mturk +# e.g., +# title = Stroop task +title = Draw Legos - Super EASY and fun! + +# Description that will be used for the HIT when posted to mturk +# e.g., +# description = Judge the color of a series of words. +description = Draw a simple picture using your tablet and stylus. + +# Keywords for the HIT on mturk +# e.g., +# keywords = Perception, Psychology +keywords =Art, Fun, Creativity + +# How many hours a given HIT will last on mturk before becoming unavailable +# for new assignments lifetime = 24 + +# Whether the HIT will be restricted to US-located mturkers us_only = true + +# Minimum approval percentage a worker must have to accept the HIT. +# Note! Mturk defaults a worker's approval percentage to 100% until +# they have completed at least 100 hits. approve_requirement = 95 -contact_email_on_error = SOMEUNKNOWN@ADDRESS.COM -ad_group = Draw Together -psiturk_keywords = drawtogether -organization_name = SOME UNKNOWN UNIVERSITY -browser_exclude_rule = MSIE, mobile, tablet +# Minimum number of HITs a worker must have had approved in order to take +# this HIT. See notes for `approve_requirement` -- set this to 100 if an actual +# `approve_requirement` percentage is wanted. +number_hits_approved = 0 + +# Whether a worker must have the master worker qualification to take this hit. +# Note that there is a commission surcharge for using this qualification +;require_master_workers = false + +# qualification_ids, commma-delimited a worker is required to have in order to +# take this HIT +;require_quals = Tablet,stylus + +# qualification_ids, commma-delimited, that will disqualify a worker from +# accepting this HIT +;block_quals = Using a computer mouse to draw + +## Hit Configuration - Ad Url ################################################## +# Config settings for constructing the task's "landing page" +# +# Server domain name for publicly-accessible route to psiturk server. +# If running on heroku, set this to your heroku app url -- +# e.g., "ad_url_domain = example-app.herokuapp.com" +;ad_url_domain = wxyz.herokuapp.com + + +# HTTPS protocol is required by mturk. Only change this if you have a good reason +# to do so. +;ad_url_protocol = https + +# Flask route that points to the ad. "pub" and "ad" both point to the same place, +# but "pub" is safer because of potential issues with ad blockers with a route +# named "ad" +;ad_url_route = pub + +# Alternatively, instead of using `ad_url_* config vars above, +# you may uncomment and use `ad_url`. You may want to use this if your +# experiment is served from a subdirectory off of the domain name. Otherwise, +# leave this as-is. +;;ad_url = %(ad_url_protocol)s://%(ad_url_host)s:%(ad_url_port)s/%(ad_url_route)s + +############################## Database Parameters ############################# [Database Parameters] -database_url = sqlite:///participants.db -table_name = turkdemo +# Participant data will be stored in this database. +# If ON_CLOUD=1, then this defaults to env var $DATABASE_URL, if set. +;database_url = sqlite:///participants.db +# Name of the database table where participant data will be stored +;table_name = assignments + +############################# Server Parameters ################################ [Server Parameters] -host = 0.0.0.0 -port = 22362 -cutoff_time = 30 -logfile = server.log -loglevel = 0 -debug = true -login_username = examplename -login_pw = examplepassword -threads = auto +# Host on which the psiturk gunicorn server will listen when `psiturk server on` +# is run. +# +# If env var ON_CLOUD=1, then this defaults to 0.0.0.0 +;host = localhost + +# Port on which the psiturk gunicorn server will listen when `psiturk server on` +# is run. +# +# If env var ON_CLOUD=1, then this defaults to $PORT env var, if set +;port = 22362 + +# Filename for psiturk server logging. +# +# If ON_CLOUD env var is set, then these both default to stdout (-) +# +;accesslog = /dev/null +;errorlog = server.log +# For backwards compatibility, `logfile` is synonymous with `errorlog`. If +# both are set, `errorlog` will be preferred over `logfile`. +;;logfile = server.log + +# Log level for the psiturk gunicorn server +;loglevel = 2 +# Controls whether the dashboard is enabled +;enable_dashboard = false + +# Controls whether the scheduler will run. If true, then num_threads must be 1 +# Be very careful to only have one scheduler run for a given study in any +# given place! Consider running a separate psiturk server somewhere else, that +# has the same database_url and table_name settings, which you only use +# for its dashboard and task runner. +;do_scheduler = false + +# Login username for the dashboard +login_username = yourusername + +# Login password for the dashboard +login_pw =yourstrongpassword + +# Number of threads for the psiturk gunicorn server to use. Leave to 1 if using +# the task runner! Otherwise, dynamically dependent on the number of cpus. +# If ON_CLOUD=1, then threads defaults to 1. +;threads = auto + +# The secret key used by flask for any secure functions it uses. Not necessary +# to set unless using a secure function. +# e.g., +# secret_key = 'this is my secret key which is hard to guess, i should change this' +;secret_key = + +# The psiturk (gunicorn) server can optionally serve traffic over https. This is +# normally not necessary if the psiturk server is set up behind a reverse proxy +# server, as is the default case with cloud hosting providers such as heroku. +# +# In reverse-proxy situations, +# the reverse proxy communicates with web browsers and other clients over https, +# while communicating on the backend with the gunicorn server over http. The +# psiturk server would only be listening on localhost and would not serve +# traffic directly. +# +# To have gunicorn use https, set both the `certfile` and `keyfile` below to point +# to a project-relative path to the public and private keys respectively. + +# Project-relative path to public keyfile for ssl for gunicorn +# certfile = +;certfile = + +# Project-relative path to private keyfile for ssl for gunicron +# keyfile = +;keyfile = + +# How long in seconds a gunicorn worker should wait for any synchronous calls +# to complete. This would only be relevant if one of your routes makes a +# potentially long-polling api or database call before returning. +;server_timeout = 30 + +################################## Task Parameters ############################# +# Settings used by various task Flask routes [Task Parameters] -experiment_code_version = 1.0 -num_conds = 1 -num_counters = 1 +# The code_version for the task. Logged as a field in the database for each +# participant, useful for data analysis. The random balanced assignment depends +# on this setting -- it will do balanced random assignment within a given codeversion. +# Can be any string value -- recommended to use semantic versioning for analysis +# sanity. +;experiment_code_version = 0.0.1 + +# The number of possible treatments. Used for random balanced assignment. +;num_conds = 1 + +# The number of possible counterbalance conditions. Used for random balanced assignment. +# If you don't know what this is, it is safe to leave it at a default of 1 and +# to only modify `num_conds` above. +;num_counters = 1 + +;contact_email_on_error = youremail@gmail.com + +# A list of web browsers, delineated by commas, that mturkers may _not_ use to +# perform the hit. +# +# The following possible values are checked by using properties on the `user_agents` python library. +# possible values : mobile, tablet, touchcapable, pc, bot, safari +# +# Example of excluding Microsoft Internet Explorer: +# browser_exclude_rule = MSIE +# otherwise, the string is checked against the user_agent_string. Example, to exclude +# internet explorer: +# browser_exclude_rule : MSIE +# +# By default, MISE, mobile, and tablet are all excluded +;browser_exclude_rule = MSIE, mobile, tablet +# Whether workers can perform the hit multiple times. Enforced by the psiturk +# server; not by mturk. +;allow_repeats = false + +# Maximum expected time for a participant to complete the task. +# Exclusively used in determining random assignment -- basically, how long should +# a participant be given to complete the task after starting? How long should the +# task last? This is different than the `duration` specified when running +# `hit create`, because a participant may not start the task immediately after +# accepting it, while the hit `duration` starts ticking as soon as the hit is +# accepted (some workers queue their accepted hits before starting it). +;cutoff_time = 30 + +################################## Shell Parameters ############################ [Shell Parameters] -launch_in_sandbox_mode = true +# the default `mode` into which the psiturk shell will be launched. +# possible values : sandbox, live +;launch_in_mode = sandbox + +# A file location for where to store a history of psiturk shell commands +;persistent_history_file = .psiturk_history + +# A default "reason" for the shell to use when granting bonuses. +# e.g., +# bonus_message = "Thanks for participating!" +;bonus_message = diff --git a/custom.py b/custom.py index 267c994..4fd360b 100644 --- a/custom.py +++ b/custom.py @@ -17,7 +17,7 @@ # load the configuration options config = PsiturkConfig() config.load_config() -myauth = PsiTurkAuthorization(config) # if you want to add a password protect route use this +myauth = PsiTurkAuthorization(config) # if you want to add a password protect route use thispyt # explore the Blueprint custom_code = Blueprint('custom_code', __name__, template_folder='templates', static_folder='static') diff --git a/static/css/style.css b/static/css/style.css index c986f79..be2df10 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -37,8 +37,32 @@ strong { .cool { color: #ccccff; } +.grid-container { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-rows: 0.6fr 1.9fr 0.5fr 1fr; + gap: 0px 0px; + grid-template-areas: + "Header Header Header Header" + "canvas canvas image image" + "buttons buttons buttons buttons" + "footer footer footer footer"; +} + +.Header { grid-area: Header; } + +.canvas { grid-area: canvas; } +.image { grid-area: image; } +.buttons { grid-area: buttons; } + +.footer { grid-area: footer; } +#exampleimagediv{ + position: absolute; + top: 75px; + left: 75px; +} /* these are all the same for now, but easy to modify individually */ #container-ad, #container-error, #container-exp, #container-consent, #container-instructions, #container-questionnaire, #container-gallery { position: absolute; @@ -102,4 +126,4 @@ strong { #error img { padding-right: 10px; padding-top: 15px; -} \ No newline at end of file +} diff --git a/static/js/task.js b/static/js/task.js index 2cd7f3d..297e268 100644 --- a/static/js/task.js +++ b/static/js/task.js @@ -7,23 +7,28 @@ // Initalize psiturk object var psiTurk = new PsiTurk(uniqueId, adServerLoc, mode); + + +var randomLine; // All pages to be loaded var pages = [ "instructions/instruct-ready.html", "stage.html" ]; - -psiTurk.preloadPages(pages); +const init = (async () => { + await psiTurk.preloadPages(pages); +})() var instructionPages = [ // add as a list as many pages as you like "instructions/instruct-ready.html" + ]; var Drawing = function() { - - psiTurk.showPage('stage.html'); + + psiTurk.showPage('stage.html'); var sketchpad = Raphael.sketchpad("editor", { width: 400, height: 400, @@ -58,14 +63,13 @@ var Drawing = function() { }); $('#Next').click(function() { - drawing_data = sketchpad.json(); + drawing_data = sketchpad.json(); psiTurk.recordUnstructuredData("drawing_json", drawing_data); psiTurk.saveData({ - success: function(){ psiTurk.completeHIT(); }, + success: function(){ psiTurk.completeHIT(); }, error: prompt_resubmit }); }); - }; // Task object to keep track of the current phase @@ -74,9 +78,12 @@ var currentview; /******************* * Run Task ******************/ -$(window).load( function(){ +$(window).on('load', async () => { + await init; psiTurk.doInstructions( instructionPages, // a list of pages you want to display in sequence function() { currentview = new Drawing(); } // what you want to do when you are done with instructions + ); + }); diff --git a/templates/closepopup.html b/templates/closepopup.html new file mode 100644 index 0000000..3c6783d --- /dev/null +++ b/templates/closepopup.html @@ -0,0 +1,16 @@ +{% extends 'layouts/layout.html' %} + +{% block head %} + {{ super() }} + +{% endblock %} + +{% block body %} +

Returning to HIT window.

+

You are being redirected back to the HIT window, which should refresh. + If you do not see the HIT submission form when you return, try refreshing + the page.

+{% endblock %} diff --git a/templates/consent.html b/templates/consent.html index a028ddf..136185d 100644 --- a/templates/consent.html +++ b/templates/consent.html @@ -24,11 +24,10 @@

We need your consent to proceed


+ +{% endblock %} diff --git a/templates/thanks.html b/templates/thanks.html new file mode 100644 index 0000000..729036a --- /dev/null +++ b/templates/thanks.html @@ -0,0 +1,17 @@ +{% extends 'layouts/layout.html' %} +{% block body %} +
+
+ + +
+
+

Thanks for your participation!

+
+
+ Our records suggest you have already completed this task. Thank you. + You cannot complete the same experiment twice. +
+
+
+{% endblock %} From 16084dd83ce172067ee5b7199d1e04231c5f1a33 Mon Sep 17 00:00:00 2001 From: gbernal Date: Sat, 10 Apr 2021 14:52:42 -0400 Subject: [PATCH 2/3] version change for readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c9d118..ed4cf3b 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ drawtogether a psiturk-compatible experiment based on the drawtogther crowdsource program by @dmarkant -developed with psiturk version 1.0.10dev +developed with psiTurk version 3.1.0 + How to use ---------- From 81cc34f68e11b819df1ce25df218a672509c6e74 Mon Sep 17 00:00:00 2001 From: gbernal Date: Sat, 10 Apr 2021 16:47:25 -0400 Subject: [PATCH 3/3] Update custom.py cleaned up extra text --- custom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom.py b/custom.py index 4fd360b..267c994 100644 --- a/custom.py +++ b/custom.py @@ -17,7 +17,7 @@ # load the configuration options config = PsiturkConfig() config.load_config() -myauth = PsiTurkAuthorization(config) # if you want to add a password protect route use thispyt +myauth = PsiTurkAuthorization(config) # if you want to add a password protect route use this # explore the Blueprint custom_code = Blueprint('custom_code', __name__, template_folder='templates', static_folder='static')