turkopticon

Review requesters on Amazon Mechanical Turk

目前为 2014-12-24 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name turkopticon
  3. // @version 2014.12.22.2056
  4. // @description Review requesters on Amazon Mechanical Turk
  5. // @author Lilly Irani and Six Silberman
  6. // @homepage https://turkopticon.ucsd.edu
  7. // @include http://*.mturk.com/*
  8. // @include https://*.mturk.com/*
  9. // @namespace https://greasyfork.org/users/4606
  10. // ==/UserScript==
  11.  
  12. var TURKOPTICON_BASE = "https://turkopticon.ucsd.edu/";
  13. var API_BASE = "https://turkopticon.ucsd.edu/api/";
  14. var API_MULTI_ATTRS_URL = API_BASE + "multi-attrs.php?ids=";
  15.  
  16. function getRequesterAnchorsAndIds(a) {
  17. //a is a list of anchor DOM elements derived in the previous function
  18. var rai = {};
  19. var re = new RegExp(/requesterId/);
  20. var rf = new RegExp(/contact/);
  21. var isContactLink = new RegExp(/Contact/);
  22. var isImgButton = new RegExp(/img/);
  23. var requestersHere = false;
  24.  
  25. for(var i = 0; i < a.length; i++) {
  26. var href = a[i].getAttribute('href');
  27. if (re.test(href) /*&& !rf.test(href)*/) {
  28. var innards = a[i].innerHTML;
  29. if (!isContactLink.test(innards) && !isImgButton.test(innards)) {
  30. var id = a[i].href.split('requesterId=')[1].split('&')[0]
  31. if (!rai.hasOwnProperty(id)) {
  32. rai[id] = []; }
  33. rai[id].push(a[i]);
  34. requestersHere = true;
  35. }
  36. }
  37. }
  38.  
  39. rai = (requestersHere)? rai : null;
  40. return rai;
  41. }
  42.  
  43. function buildXhrUrl(rai) {
  44. var url = API_MULTI_ATTRS_URL;
  45. var ri = Object.keys(rai);
  46. for(var i = 0; i < ri.length; i++) {
  47. url += ri[i];
  48. if (i < ri.length - 1) { url += ","; } }
  49. return url; }
  50.  
  51. function makeXhrQuery(url) {
  52. var xhr = new XMLHttpRequest();
  53. xhr.open('GET', url, false);
  54. xhr.send(null);
  55. var resp = JSON.parse(xhr.response);
  56. return resp; }
  57.  
  58. function ul(cl, inner) {
  59. return "<ul class='" + cl + "'>" + inner + "</ul>"; }
  60.  
  61. function li(cl, inner) {
  62. return "<li class='" + cl + "'>" + inner + "</li>"; }
  63.  
  64. function span(cl, inner) {
  65. return "<span class='" + cl + "'>" + inner + "</span>"; }
  66.  
  67. function strmul(str, num) {
  68. return Array(num + 1).join(str); }
  69.  
  70. function pad(word, space) {
  71. if (word.length >= space) { return word; }
  72. else { return word + strmul("&nbsp;", space - word.length); } }
  73.  
  74. function long_word(word) {
  75. switch(word) {
  76. case "comm": return "communicativity"; break;
  77. case "pay" : return "generosity"; break;
  78. case "fair": return "fairness"; break;
  79. case "fast": return "promptness"; break; } }
  80.  
  81. function visualize(i, max, size) {
  82. var color;
  83. if (i / max <= 2 / 5) { color = 'red'; }
  84. else if (i / max <= 3 / 5) { color = 'yellow'; }
  85. else { color = 'green'; }
  86. var filled = Math.round((i / max) * size);
  87. var unfilled = size - filled;
  88. var bar = span("bar", span(color, strmul("&nbsp;", filled)) + span("unf", strmul("&nbsp;", unfilled)));
  89. return bar; }
  90.  
  91. function attr_html(n, i) {
  92. return pad(long_word(n), 15) + ": " + visualize(i, 5, 30) + "&nbsp;" + i + " / 5"; }
  93.  
  94. function ro_html(ro) {
  95. var rohtml = "";
  96. if (typeof ro.attrs != 'undefined') {
  97. var keys = Object.keys(ro.attrs);
  98. for (var i = 0; i < keys.length; i++) {
  99. rohtml += li("attr", attr_html(keys[i], ro.attrs[keys[i]])); } }
  100. return rohtml; }
  101.  
  102. function what(ro) {
  103. var str = "";
  104. if (typeof ro.attrs != 'undefined') {
  105. str = li("gray_link", "<a href='" + TURKOPTICON_BASE + "help#attr'>What do these scores mean?</a>"); }
  106. return str; }
  107.  
  108. function nrs(rid, nrevs) {
  109. var str = "";
  110. if (typeof nrevs === 'undefined') {
  111. str = "<li>No reviews for this requester</li>"; }
  112. else { str = "<li>Scores based on <a href='" + TURKOPTICON_BASE + rid + "'>" + nrevs + " reviews</a></li>"; }
  113. return str; }
  114.  
  115. function tos(tosflags) {
  116. var str = "<li>Terms of Service violation flags: " + tosflags + "</li>";
  117. return str; }
  118.  
  119. function rl(rid, name) {
  120. var rl = "<li><a href='" + TURKOPTICON_BASE + "report?requester[amzn_id]=" + rid;
  121. rl += "&requester[amzn_name]=" + name + "'>";
  122. rl += "Report your experience with this requester &raquo;</a></li>";
  123. return rl; }
  124.  
  125. function dropDown(ro, rid) {
  126. var n = ro.name;
  127. var arrcls = "";
  128. if (typeof ro.attrs != 'undefined') { arrcls = "toc"; }
  129. var dd = ul("tob", li(arrcls, "&#9660;") + ul("tom", ro_html(ro) + what(ro) + nrs(rid, ro.reviews) + tos(ro.tos_flags) + rl(rid, n)));
  130. return dd; }
  131.  
  132. function insertInlineCss() {
  133. var css = "<style type='text/css'>\n";
  134. css += ".tob, .tom { list-style-type: none; padding-left: 0; }\n";
  135. css += ".tob { float: left; margin-right: 5px; }\n";
  136. css += ".tob > .tom { display: none; position: absolute; background-color: #ebe5ff; border: 1px solid #aaa; padding: 5px; }\n";
  137. css += ".tob:hover > .tom { display: block; }\n";
  138. css += ".tob > li { border: 1px solid #9db9d1; background-color: #ebe5ff; color: #00c; padding: 3px 3px 1px 3px; }\n";
  139. css += ".tob > li.toc { color: #f33; }\n";
  140. css += "@media screen and (-webkit-min-device-pixel-ratio:0) { \n .tob { margin-top: -5px; } \n}\n"
  141. css += ".attr { font-family: Monaco, Courier, monospace; color: #333; }\n";
  142. css += ".bar { font-size: 0.6em; }\n";
  143. css += ".unf { background-color: #ddd; }\n";
  144. css += ".red { background-color: #f00; }\n";
  145. css += ".yellow { background-color: #f90; }\n";
  146. css += ".green { background-color: #6c6; }\n";
  147. css += ".gray_link { margin-bottom: 15px; }\n";
  148. css += ".gray_link a { color: #666; }\n";
  149. css += "</style>";
  150. var head = document.getElementsByTagName("head")[0];
  151. head.innerHTML = css + head.innerHTML;
  152. }
  153.  
  154. function getNames(rai, resp) {
  155. for(var rid in rai) {
  156. if (rai.hasOwnProperty(rid)) {
  157. if (resp[rid] == "") { // empty response, no data in Turkopticon DB for this ID
  158. resp[rid] = JSON.parse('{"name": "' + rai[rid][0].innerHTML.split("</span>")[0].split(">")[1] + '"}');
  159. }
  160. resp[rid].name = rai[rid][0].innerHTML.split("</span>")[0].split(">")[1]; } } // overwrite name attribute of response object from page
  161. return resp; }
  162.  
  163. function insertDropDowns(rai, resp) {
  164. for(var rid in rai) {
  165. if (rai.hasOwnProperty(rid)) {
  166. for(var i = 0; i < rai[rid].length; i++) {
  167. var td = rai[rid][i].parentNode;
  168. td.innerHTML = dropDown(resp[rid], rid) + " " + td.innerHTML; } } } }
  169.  
  170. insertInlineCss();
  171. var a = document.getElementsByTagName('a');
  172. var reqAnchors = getRequesterAnchorsAndIds(a);
  173. if (reqAnchors) {
  174. var url = buildXhrUrl(reqAnchors);
  175. var resp = makeXhrQuery(url);
  176. resp = getNames(reqAnchors, resp);
  177. insertDropDowns(reqAnchors, resp);
  178. }