diff --git a/.gitignore b/.gitignore index f642ebe..d1b2870 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,8 @@ __pycache__ node_modules .pydevproject .project +config.local.yml +hit_store.db +www/scans/*.svg +#scanimation/interfa diff --git a/Pipfile b/Pipfile index 4956af7..9f4df52 100644 --- a/Pipfile +++ b/Pipfile @@ -23,4 +23,4 @@ pyserial = "*" python_version = "3.7" [packages.a209065] -path = "./../../AxiDraw_API_v253r3" +path = "./../AxiDraw_API_v253r3" diff --git a/Pipfile.lock b/Pipfile.lock index 6c67caa..38136b4 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "89332bbe3bba257b19a9566bd526d79af55c9ea4671357aab103126c35b67797" + "sha256": "29b194a198b1d9a791ea020295d0ef6d5969969f9d606e2457444485e1bd6f7a" }, "pipfile-spec": 6, "requires": { @@ -17,29 +17,29 @@ }, "default": { "a209065": { - "path": "./../../AxiDraw_API_v253r3" + "path": "./../AxiDraw_API_v253r3" }, "boto3": { "hashes": [ - "sha256:2945d8246e4c8875e3ae4aafffd028330ef681efc33e1475c1a805ed42540403", - "sha256:3d84311ce0f2fba83810f0e840b08e2b66246fc80dbb0a71fb992116f47b95bd" + "sha256:5db4db12a017be2a0b07ec662584b7b9e8afa05894c8aaac145576a7c39a9886", + "sha256:7fb8bf70ff2403991c8ae7bc548333811be6e432c7665721364ea0c858eb824e" ], "index": "pypi", - "version": "==1.10.6" + "version": "==1.10.41" }, "botocore": { "hashes": [ - "sha256:ac1a5caa10e3c4452714b17e6f30f05b4b6e57e0c80b19c1f4d72b234edf6646", - "sha256:fa6b9e619423f3891e7c11b98f2183da8173e3fed995271e93fd4a712ef45777" + "sha256:5bfffa38ebba26ab462bb40e858702390fbe3ae2093a2177a8cde050ad6cb7e3", + "sha256:62ddff63be904781f97ced737836a66f5b72579af788c905cfdab32d2970e15e" ], - "version": "==1.13.6" + "version": "==1.13.41" }, "certifi": { "hashes": [ - "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", - "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef" + "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", + "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" ], - "version": "==2019.9.11" + "version": "==2019.11.28" }, "chardet": { "hashes": [ @@ -124,34 +124,34 @@ }, "lxml": { "hashes": [ - "sha256:02ca7bf899da57084041bb0f6095333e4d239948ad3169443f454add9f4e9cb4", - "sha256:096b82c5e0ea27ce9138bcbb205313343ee66a6e132f25c5ed67e2c8d960a1bc", - "sha256:0a920ff98cf1aac310470c644bc23b326402d3ef667ddafecb024e1713d485f1", - "sha256:1409b14bf83a7d729f92e2a7fbfe7ec929d4883ca071b06e95c539ceedb6497c", - "sha256:17cae1730a782858a6e2758fd20dd0ef7567916c47757b694a06ffafdec20046", - "sha256:17e3950add54c882e032527795c625929613adbd2ce5162b94667334458b5a36", - "sha256:1f4f214337f6ee5825bf90a65d04d70aab05526c08191ab888cb5149501923c5", - "sha256:2e8f77db25b0a96af679e64ff9bf9dddb27d379c9900c3272f3041c4d1327c9d", - "sha256:4dffd405390a45ecb95ab5ab1c1b847553c18b0ef8ed01e10c1c8b1a76452916", - "sha256:6b899931a5648862c7b88c795eddff7588fb585e81cecce20f8d9da16eff96e0", - "sha256:726c17f3e0d7a7200718c9a890ccfeab391c9133e363a577a44717c85c71db27", - "sha256:760c12276fee05c36f95f8040180abc7fbebb9e5011447a97cdc289b5d6ab6fc", - "sha256:796685d3969815a633827c818863ee199440696b0961e200b011d79b9394bbe7", - "sha256:891fe897b49abb7db470c55664b198b1095e4943b9f82b7dcab317a19116cd38", - "sha256:9277562f175d2334744ad297568677056861070399cec56ff06abbe2564d1232", - "sha256:a471628e20f03dcdfde00770eeaf9c77811f0c331c8805219ca7b87ac17576c5", - "sha256:a63b4fd3e2cabdcc9d918ed280bdde3e8e9641e04f3c59a2a3109644a07b9832", - "sha256:ae88588d687bd476be588010cbbe551e9c2872b816f2da8f01f6f1fda74e1ef0", - "sha256:b0b84408d4eabc6de9dd1e1e0bc63e7731e890c0b378a62443e5741cfd0ae90a", - "sha256:be78485e5d5f3684e875dab60f40cddace2f5b2a8f7fede412358ab3214c3a6f", - "sha256:c27eaed872185f047bb7f7da2d21a7d8913457678c9a100a50db6da890bc28b9", - "sha256:c7fccd08b14aa437fe096c71c645c0f9be0655a9b1a4b7cffc77bcb23b3d61d2", - "sha256:c81cb40bff373ab7a7446d6bbca0190bccc5be3448b47b51d729e37799bb5692", - "sha256:d11874b3c33ee441059464711cd365b89fa1a9cf19ae75b0c189b01fbf735b84", - "sha256:e9c028b5897901361d81a4718d1db217b716424a0283afe9d6735fe0caf70f79", - "sha256:fe489d486cd00b739be826e8c1be188ddb74c7a1ca784d93d06fda882a6a1681" + "sha256:00ac0d64949fef6b3693813fe636a2d56d97a5a49b5bbb86e4cc4cc50ebc9ea2", + "sha256:0571e607558665ed42e450d7bf0e2941d542c18e117b1ebbf0ba72f287ad841c", + "sha256:0e3f04a7615fdac0be5e18b2406529521d6dbdb0167d2a690ee328bef7807487", + "sha256:13cf89be53348d1c17b453867da68704802966c433b2bb4fa1f970daadd2ef70", + "sha256:217262fcf6a4c2e1c7cb1efa08bd9ebc432502abc6c255c4abab611e8be0d14d", + "sha256:223e544828f1955daaf4cefbb4853bc416b2ec3fd56d4f4204a8b17007c21250", + "sha256:277cb61fede2f95b9c61912fefb3d43fbd5f18bf18a14fae4911b67984486f5d", + "sha256:3213f753e8ae86c396e0e066866e64c6b04618e85c723b32ecb0909885211f74", + "sha256:4690984a4dee1033da0af6df0b7a6bde83f74e1c0c870623797cec77964de34d", + "sha256:4fcc472ef87f45c429d3b923b925704aa581f875d65bac80f8ab0c3296a63f78", + "sha256:61409bd745a265a742f2693e4600e4dbd45cc1daebe1d5fad6fcb22912d44145", + "sha256:678f1963f755c5d9f5f6968dded7b245dd1ece8cf53c1aa9d80e6734a8c7f41d", + "sha256:6c6d03549d4e2734133badb9ab1c05d9f0ef4bcd31d83e5d2b4747c85cfa21da", + "sha256:6e74d5f4d6ecd6942375c52ffcd35f4318a61a02328f6f1bd79fcb4ffedf969e", + "sha256:7b4fc7b1ecc987ca7aaf3f4f0e71bbfbd81aaabf87002558f5bc95da3a865bcd", + "sha256:7ed386a40e172ddf44c061ad74881d8622f791d9af0b6f5be20023029129bc85", + "sha256:8f54f0924d12c47a382c600c880770b5ebfc96c9fd94cf6f6bdc21caf6163ea7", + "sha256:ad9b81351fdc236bda538efa6879315448411a81186c836d4b80d6ca8217cdb9", + "sha256:bbd00e21ea17f7bcc58dccd13869d68441b32899e89cf6cfa90d624a9198ce85", + "sha256:c3c289762cc09735e2a8f8a49571d0e8b4f57ea831ea11558247b5bdea0ac4db", + "sha256:cf4650942de5e5685ad308e22bcafbccfe37c54aa7c0e30cd620c2ee5c93d336", + "sha256:cfcbc33c9c59c93776aa41ab02e55c288a042211708b72fdb518221cc803abc8", + "sha256:e301055deadfedbd80cf94f2f65ff23126b232b0d1fea28f332ce58137bcdb18", + "sha256:ebbfe24df7f7b5c6c7620702496b6419f6a9aa2fd7f005eb731cc80d7b4692b9", + "sha256:eff69ddbf3ad86375c344339371168640951c302450c5d3e9936e98d6459db06", + "sha256:f6ed60a62c5f1c44e789d2cf14009423cb1646b44a43e40a9cf6a21f077678a1" ], - "version": "==4.4.1" + "version": "==4.4.2" }, "maxminddb": { "hashes": [ @@ -221,22 +221,20 @@ }, "pyyaml": { "hashes": [ - "sha256:0113bc0ec2ad727182326b61326afa3d1d8280ae1122493553fd6f4397f33df9", - "sha256:01adf0b6c6f61bd11af6e10ca52b7d4057dd0be0343eb9283c878cf3af56aee4", - "sha256:5124373960b0b3f4aa7df1707e63e9f109b5263eca5976c66e08b1c552d4eaf8", - "sha256:5ca4f10adbddae56d824b2c09668e91219bb178a1eee1faa56af6f99f11bf696", - "sha256:7907be34ffa3c5a32b60b95f4d95ea25361c951383a894fec31be7252b2b6f34", - "sha256:7ec9b2a4ed5cad025c2278a1e6a19c011c80a3caaac804fd2d329e9cc2c287c9", - "sha256:87ae4c829bb25b9fe99cf71fbb2140c448f534e24c998cc60f39ae4f94396a73", - "sha256:9de9919becc9cc2ff03637872a440195ac4241c80536632fffeb6a1e25a74299", - "sha256:a5a85b10e450c66b49f98846937e8cfca1db3127a9d5d1e31ca45c3d0bef4c5b", - "sha256:b0997827b4f6a7c286c01c5f60384d218dca4ed7d9efa945c3e1aa623d5709ae", - "sha256:b631ef96d3222e62861443cc89d6563ba3eeb816eeb96b2629345ab795e53681", - "sha256:bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41", - "sha256:f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8" + "sha256:0e7f69397d53155e55d10ff68fdfb2cf630a35e6daf65cf0bdeaf04f127c09dc", + "sha256:2e9f0b7c5914367b0916c3c104a024bb68f269a486b9d04a2e8ac6f6597b7803", + "sha256:35ace9b4147848cafac3db142795ee42deebe9d0dad885ce643928e88daebdcc", + "sha256:38a4f0d114101c58c0f3a88aeaa44d63efd588845c5a2df5290b73db8f246d15", + "sha256:483eb6a33b671408c8529106df3707270bfacb2447bf8ad856a4b4f57f6e3075", + "sha256:4b6be5edb9f6bb73680f5bf4ee08ff25416d1400fbd4535fe0069b2994da07cd", + "sha256:7f38e35c00e160db592091751d385cd7b3046d6d51f578b29943225178257b31", + "sha256:8100c896ecb361794d8bfdb9c11fce618c7cf83d624d73d5ab38aef3bc82d43f", + "sha256:c0ee8eca2c582d29c3c2ec6e2c4f703d1b7f1fb10bc72317355a746057e7346c", + "sha256:e4c015484ff0ff197564917b4b4246ca03f411b9bd7f16e02a2f586eb48b6d04", + "sha256:ebc4ed52dcc93eeebeae5cf5deb2ae4347b3a81c3fa12b0b8c976544829396a4" ], "index": "pypi", - "version": "==5.1.2" + "version": "==5.2" }, "requests": { "hashes": [ @@ -262,17 +260,17 @@ }, "six": { "hashes": [ - "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", - "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", + "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" ], - "version": "==1.12.0" + "version": "==1.13.0" }, "sqlalchemy": { "hashes": [ - "sha256:0f0768b5db594517e1f5e1572c73d14cf295140756431270d89496dc13d5e46c" + "sha256:bfb8f464a5000b567ac1d350b9090cf081180ec1ab4aa87e7bca12dab25320ec" ], "index": "pypi", - "version": "==1.3.10" + "version": "==1.3.12" }, "tornado": { "hashes": [ @@ -289,11 +287,10 @@ }, "urllib3": { "hashes": [ - "sha256:3de946ffbed6e6746608990594d08faac602528ac7015ac28d33cee6a45b7398", - "sha256:9a107b99a5393caf59c7aa3c1249c16e6879447533d0887f4336dde834c7be86" + "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293", + "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745" ], - "markers": "python_version >= '3.4'", - "version": "==1.25.6" + "version": "==1.25.7" } }, "develop": {} diff --git a/disable_motors.py b/disable_motors.py index b8f3808..d43c87e 100644 --- a/disable_motors.py +++ b/disable_motors.py @@ -1,6 +1,16 @@ from pyaxidraw import axidraw ad = axidraw.AxiDraw() + +# connect/disconnect once because often first connection attempt fails +ad.interactive() +ad.connect() +ad.pen_raise() +ad.disconnect() + + ad.plot_setup() +ad.pen_raise() ad.options.mode = "manual" ad.options.manual_cmd = "disable_xy" ad.plot_run() + diff --git a/sorteerhoed/HITStore.py b/sorteerhoed/HITStore.py index 0086c5d..798918d 100644 --- a/sorteerhoed/HITStore.py +++ b/sorteerhoed/HITStore.py @@ -60,7 +60,7 @@ class HIT(Base): def getImagePath(self): - return os.path.join('../scanimation/interfaces/frames', f"{self.id:06d}.jpg") + return os.path.join('scanimation/interfaces/frames', f"{self.id:06d}.jpg") # def getImageUrl(self): # return f"{self.id}.jpg" diff --git a/sorteerhoed/central_management.py b/sorteerhoed/central_management.py index c851b41..4e16296 100644 --- a/sorteerhoed/central_management.py +++ b/sorteerhoed/central_management.py @@ -86,6 +86,9 @@ class CentralManagement(): ) self.logger.info(f"Mechanical turk account balance: {self.mturk.get_account_balance()['AvailableBalance']}") + if not self.config['for_real']: + self.logger.info("Remove block from sandbox worker account") + self.mturk.delete_worker_block(WorkerId='A1CK46PK9VEUH5', Reason='Myself on Sandbox') # clear any pending hits: pending_hits = self.mturk.list_hits(MaxResults=100) @@ -173,7 +176,7 @@ class CentralManagement(): self.currentHit.scanned_at = datetime.datetime.utcnow() self.server.statusPage.set('state', self.currentHit.getStatus()) time_diff = datetime.datetime.now() - self.lastHitTime - to_wait = 150 - time_diff.total_seconds() + to_wait = 10 - time_diff.total_seconds() if to_wait > 0: self.logger.warn(f"Sleep until next hit: {to_wait}s") time.sleep(to_wait) @@ -272,8 +275,9 @@ class CentralManagement(): else: sqsHit.submit_hit_at = datetime.datetime.strptime(signal.params['event']['EventTimestamp'],"%Y-%m-%dT%H:%M:%SZ") # Merijn: hier block ik de worker na succesvolle submit, om dubbele workers te voorkomen - self.mturk.create_worker_block(WorkerId=signal.params['event']['WorkerId'], Reason='Every worker can only work once on the taks.') - self.logger.warn("Block worker after submission") + # Disabled after worker mail, use quals instead + #self.mturk.create_worker_block(WorkerId=signal.params['event']['WorkerId'], Reason='Every worker can only work once on the taks.') + #self.logger.warn("Block worker after submission") self.store.saveHIT(sqsHit) @@ -312,7 +316,13 @@ class CentralManagement(): self.logger.info(f"Make HIT {self.currentHit.id}") - question = open(self.config['amazon']['task_xml'], mode='r').read().replace("{HIT_NR}",str(self.currentHit.id)) +# question = open(self.config['amazon']['task_xml'], mode='r').read().replace("{HIT_NR}",str(self.currentHit.id)) + question = ''' + + https://guest.rubenvandeven.com:8888/draw?id={HIT_NR} + 0 + + '''.replace("{HIT_NR}",str(self.currentHit.id)) estimatedHitDuration = self.store.getEstimatedHitDuration() diff --git a/sorteerhoed/plotter.py b/sorteerhoed/plotter.py index c27c6f2..44a0707 100644 --- a/sorteerhoed/plotter.py +++ b/sorteerhoed/plotter.py @@ -52,6 +52,7 @@ class Plotter: self.ad.options.speed_penup = 100 self.ad.options.speed_pendown = 100 self.ad.options.model = 1 # 2 for A3, 1 for A4 + self.ad.options.pen_pos_up = 100 self.park() diff --git a/sorteerhoed/webserver.py b/sorteerhoed/webserver.py index 516954d..fe8f2af 100644 --- a/sorteerhoed/webserver.py +++ b/sorteerhoed/webserver.py @@ -38,7 +38,7 @@ class StaticFileWithHeaderHandler(tornado.web.StaticFileHandler): class WebSocketHandler(tornado.websocket.WebSocketHandler): - CORS_ORIGINS = ['localhost', '.mturk.com', 'here.rubenvandeven.com'] + CORS_ORIGINS = ['localhost', '.mturk.com', 'here.rubenvandeven.com', 'guest.rubenvandeven.com'] connections = set() def initialize(self, config, plotterQ: Queue, eventQ: Queue, store: HITStore): @@ -125,7 +125,8 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler): self.write_message(json.dumps({ 'action': 'submitted', - 'msg': f"Submission ok, please copy this token to your HIT at Mechanical Turk: {self.hit.uuid}" + 'msg': f"Submission ok, please copy this token to your HIT at Mechanical Turk: {self.hit.uuid}", + 'code': str(self.hit.uuid) })) self.close() @@ -284,6 +285,14 @@ class DrawPageHandler(tornado.web.RequestHandler): self.write("HIT already submitted") return + assignmentId = self.get_query_argument('assignmentId', '') + if len(assignmentId) < 1: + logger.critical("Accessing page without assignment id. Allowing it for debug purposes... fingers crossed?") + + previewOnly = False + if assignmentId == 'ASSIGNMENT_ID_NOT_AVAILABLE': + previewOnly = True + previous_hit = self.store.getLastSubmittedHit() if not previous_hit: # start with basic svg @@ -301,7 +310,10 @@ class DrawPageHandler(tornado.web.RequestHandler): .replace("{DRAW_WIDTH}", str(self.draw_width))\ .replace("{DRAW_HEIGHT}", str(self.draw_height))\ .replace("{TOP_PADDING}", str(self.top_padding))\ - .replace("{LEFT_PADDING}", str(self.left_padding)) + .replace("{LEFT_PADDING}", str(self.left_padding))\ + .replace("{SCRIPT}", '' if previewOnly else '')\ + .replace("{ASSIGNMENT}", '' if previewOnly else str(assignmentId)) # TODO: fix unsafe inserting of GET variable + self.write(contents) if 'X-Forwarded-For' in self.request.headers: @@ -311,16 +323,18 @@ class DrawPageHandler(tornado.web.RequestHandler): logger.info(f"Request from {ip}") - self.eventQ.put(Signal('hit.info', dict(hit_id=hit.id, ip=ip))) - try: - geoip = self.geoip_reader.country(ip) - logger.debug(f"Geo {geoip}") - self.eventQ.put(Signal('hit.info', dict(hit_id=hit.id, location=geoip.country.name))) - except Exception as e: - logger.exception(e) - logger.info("No geo IP possible") - self.eventQ.put(Signal('hit.info', dict(hit_id=hit.id, location='Unknown'))) + if not previewOnly: + self.eventQ.put(Signal('hit.info', dict(hit_id=hit.id, ip=ip))) + + try: + geoip = self.geoip_reader.country(ip) + logger.debug(f"Geo {geoip}") + self.eventQ.put(Signal('hit.info', dict(hit_id=hit.id, location=geoip.country.name))) + except Exception as e: + logger.exception(e) + logger.info("No geo IP possible") + self.eventQ.put(Signal('hit.info', dict(hit_id=hit.id, location='Unknown'))) class BackendHandler(tornado.web.RequestHandler): def initialize(self, store: HITStore, path: str): diff --git a/www/assignment.js b/www/assignment.js new file mode 100644 index 0000000..3a491b9 --- /dev/null +++ b/www/assignment.js @@ -0,0 +1,174 @@ +let url = window.location.origin.replace('http', 'ws') +'/ws?' + window.location.search.substring(1); +let svgEl = document.getElementById("canvas"); +let strokeEl = document.getElementById('stroke'); +let submitEl = document.getElementById('submit'); +let resetEl = document.getElementById('reset'); +let messageEl = document.getElementById('message'); +let innerFaceEl = document.getElementById('innerface'); // wrapper within the interface + + +let strokes = []; +let isDrawing = false; +let hasMouseDown = false; +let currentPoint = null; + +let getCoordinates = function(e) { + // convert event coordinates into relative positions on x & y axis + let box = innerFaceEl.getBoundingClientRect(); + let x = (e.x - box['left']) / box['width']; + let y = (e.y - box['top']) / box['height']; + return {'x': x, 'y': y}; +} + +let isInsideBounds = function(pos) { + return !(pos['x'] < 0 || pos['y'] < 0 || pos['x'] > 1 || pos['y'] > 1); +} +let isInsideDrawingBounds = function(pos) { + if(pos['x'] > xPadding && pos['x'] < (xPadding+drawWidthFactor) && pos['y'] > yPadding && pos['y'] < yPadding+drawHeightFactor) { + return true; + } + return false; +} + +let draw = function(e) { + let pos = getCoordinates(e); + + if(!isInsideBounds(pos)) { + // outside of bounds + return; + } + + if(isDrawing && !isInsideDrawingBounds(pos)){ + stopDrawing(pos); + } + if(!isDrawing && hasMouseDown && isInsideDrawingBounds(pos)){ + isDrawing = true; + } + + if(isDrawing) { + strokes.push([pos['x'], pos['y'], 0]); + let d = strokes2D(strokes); + strokeEl.setAttribute('d', d); + } + + console.log([pos['x'], pos['y']], isDrawing); + socket.send(JSON.stringify({ + 'action': 'move', + 'direction': [pos['x'], pos['y']], + 'mouse': isDrawing, + })); +}; + +let stopDrawing = function(pos) { + if(!isDrawing) { + return; + } + isDrawing = false; + //document.body.removeEventListener('mousemove', draw); + + + if(strokes.length > 0){ + // mark point as last of stroke + strokes[strokes.length - 1][2] = 1; + } + socket.send(JSON.stringify({ + 'action': 'up', + 'direction': [pos['x'], pos['y']] + })); +} + +let penup = function(e) { + if(!hasMouseDown) { + return; + } + hasMouseDown = false; + + let pos = getCoordinates(e); + stopDrawing(pos); +}; +let strokes2D = function(strokes) { + // strokes to a d attribute for a path + let d = ""; + let last_stroke = undefined; + let cmd = ""; + for (let stroke of strokes) { + if(!last_stroke) { + d += `M${stroke[0]*svgWidth*10},${stroke[1]*svgHeight*10} `; + cmd = 'M'; + } else { + if (last_stroke[2] == 1) { + d += " m"; + cmd = 'm'; + } else if (cmd != 'l') { + d+=' l '; + cmd = 'l'; + } + let rel_stroke = [stroke[0] - last_stroke[0], stroke[1] - last_stroke[1]]; + d += `${rel_stroke[0]*svgWidth*10},${rel_stroke[1]*svgHeight*10} `; + } + last_stroke = stroke; + + } + return d; +} + +let startDrawing = function(e){ + hasMouseDown = true; +}; + +/*let reset = function() { + strokes = []; + strokeEl.setAttribute('d', ""); + socket.send(JSON.stringify({ + 'action': 'reset', + })); +}*/ + + +let socket = new WebSocket(url); +document.body.addEventListener('mousemove', draw); +document.body.addEventListener('mouseup', penup); +document.body.addEventListener('mousedown', startDrawing); + +socket.addEventListener('message', function(e){ + let msg = JSON.parse(e.data); + console.log('receive', msg); + if(msg['action'] == 'submitted') { + document.body.classList.add('submitted'); + messageEl.innerHTML = msg['msg']; + svgEl.removeEventListener('mousedown', startDrawing); + } + + // submit the completion form only after the shape has been sent to the server + let u = new URL(location); + let url = u.searchParams.get('turkSubmitTo'); + let formEl = document.getElementById('finishedForm'); + document.getElementById('surveycode').value = msg['code']; + formEl.action = url + '/mturk/externalSubmit'; + formEl.submit(); + +// let assignmentId = u.searchParams.get('assignmentId'); +// var formData = new FormData(); +// formData.append('assigmentId', assignmentId); +// let r = new Request(url + '/mturk/externalSubmit', {method: 'POST', body: formData}); +// fetch(r).then(function(response) { +// console.log(response); +// }); +}); + +//resetEl.addEventListener('click', reset); +submitEl.addEventListener('click', function(e){ + if(!strokes.length){ + alert('please draw before submitting'); + return; + } + + socket.send(JSON.stringify({ + 'action': 'submit', + 'd': strokeEl.getAttribute('d') + })); + + document.body.removeEventListener('mousemove', draw); + document.body.removeEventListener('mouseup', penup); + document.body.removeEventListener('mousedown', startDrawing); +}); \ No newline at end of file diff --git a/www/index.html b/www/index.html index 59e174e..914de0a 100644 --- a/www/index.html +++ b/www/index.html @@ -134,7 +134,7 @@ -
+
@@ -146,13 +146,18 @@
  • Drag the mouse to trace the lines drawing above
  • -
  • Follow the lines as precise as possible
  • +
  • Follow the lines as precise as possible, it is only this image to complete the HIT.
  • Press submit when you're done.
  • -
  • You'll receive a submission token, to fill in at Mechanical Turk
  • +
  • Please watch the clock! timing is strict because the tracing is live streamed to us. Unfortunately, due to high abandonment rates we have to keep the timer strict.
+ +
+ + +
@@ -162,174 +167,18 @@
- + + {SCRIPT}