MTurk QualSorter

Keep track of qualifications and create a more sortable list.

目前为 2014-08-13 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name MTurk QualSorter
  3. // @namespace localhost
  4. // @description Keep track of qualifications and create a more sortable list.
  5. // @version 0.1b
  6. // @include https://www.mturk.com/mturk/dashboard*
  7. // @include https://www.mturk.com/mturk/qualtable*
  8. // @require http://code.jquery.com/jquery-2.1.1.js
  9. // @require http://code.jquery.com/ui/1.10.3/jquery-ui.js
  10. // @require http://cdn.jsdelivr.net/tablesorter/2.17.4/js/jquery.tablesorter.js
  11. // @resource jqtable http://cdn.jsdelivr.net/tablesorter/2.17.4/css/theme.default.css
  12. // @grant GM_setValue
  13. // @grant GM_getValue
  14. // @grant GM_addStyle
  15. // @grant GM_getResourceText
  16. // @author DeliriumTremens 2014
  17. // ==/UserScript==
  18.  
  19. //
  20. //
  21. // GET CSS MODULES
  22. //
  23. var jqtableCSS = GM_getResourceText("jqtable");
  24. GM_addStyle(jqtableCSS);
  25. //
  26. // END CSS MODULES
  27. //
  28. //
  29. // ******************************************************************
  30. //
  31. //
  32. // START VARIABLE DEFINITIONS
  33. //
  34. var qualCount = null; // hold onto that sweet, sweet qual count
  35. var qualPrev = GM_getValue("quals"); // store the previous qual count
  36. var qualDiff = 0; // difference in qual count between dashboard refreshes
  37. var nextPage = "https://www.mturk.com/mturk/findquals?requestable=false&earned=true";
  38.  
  39. $.get("https://www.mturk.com/mturk/findquals?requestable=false&earned=true", function(data) {
  40. var $quals = $(data).find('td[class="title_orange_text"]').text().trim();
  41. $quals = $quals.substr(8);
  42. qualCount = $quals.slice(0, -8);
  43. qualCount = parseInt(qualCount);
  44. qualDiff = qualCount - qualPrev;
  45. addQualElement();
  46. GM_setValue("quals",qualCount);
  47. });
  48.  
  49. var qualObject = {}; // Storage for qualification details to be sent to database
  50. var QualStorage = {}; // QualStorage object definition
  51. var Scraping = true; // Used to start and kill scraping
  52. var scrapeNumber = 0; // Unused currently
  53. var currScrape = null; // Container for current page being scraped
  54. //
  55. // END VARIABLE DEFINITIONS
  56. //
  57. //
  58. // ******************************************************************
  59. //
  60. //
  61. // START INDEXEDDB METHODS
  62. //
  63. var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
  64. window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.mozIDBTransaction;
  65. window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.mozIDBKeyRange;
  66. var idbKeyRange = window.IDBKeyRange;
  67. QualStorage.indexedDB = {};
  68. QualStorage.indexedDB.db = null;
  69. var v = 1; // Database version.
  70. var dbExists = true; // Boolean if database exists.
  71.  
  72. // Method for creating the new database.
  73. QualStorage.indexedDB.create = function () {
  74. var request = indexedDB.open("QualDB", v);
  75. request.onupgradeneeded = function (e) {
  76. QualStorage.indexedDB.db = e.target.result;
  77. var db = QualStorage.indexedDB.db;
  78. var newDB = false;
  79. if(!db.objectStoreNames.contains("Quals")) {
  80. var store = db.createObjectStore("Quals", {
  81. keyPath: "qualId"
  82. });
  83. store.createIndex("qualName", "qualName", {
  84. unique: false
  85. });
  86. store.createIndex("author", "author", {
  87. unique: false
  88. });
  89. store.createIndex("desc", "desc", {
  90. unique: false
  91. });
  92. store.createIndex("assDate", "assDate", {
  93. unique: false
  94. });
  95. store.createIndex("retDate", "retDate", {
  96. unique: false
  97. });
  98. store.createIndex("users", "users", {
  99. unique: false
  100. });
  101. store.createIndex("value", "value", {
  102. unique: false
  103. });
  104. newDB = true;
  105. }
  106. db.close();
  107. }
  108. request.onsuccess = function (e) {
  109. QualStorage.indexedDB.db = e.target.result;
  110. var db = QualStorage.indexedDB.db;
  111. db.close();
  112. }
  113. //request.onerror = console.log(request.errorCode);
  114. }
  115.  
  116. QualStorage.indexedDB.addQual = function (qual) {
  117. var request = indexedDB.open("QualDB", v);
  118. var qualPut = qual;
  119. request.onsuccess = function (e) {
  120. QualStorage.indexedDB.db = e.target.result;
  121.  
  122. var db = QualStorage.indexedDB.db;
  123. var newDB = false;
  124.  
  125. if (!db.objectStoreNames.contains("Quals")) {
  126. db.close();
  127. } else {
  128. var trans = db.transaction(["Quals"], 'readwrite');
  129. var store = trans.objectStore("Quals");
  130. var request;
  131.  
  132. request = store.put({
  133. qualId: qualPut["qualId"],
  134. qualName: qualPut["qualName"],
  135. author: qualPut["author"],
  136. desc: qualPut["desc"],
  137. assDate: qualPut["assDate"],
  138. retDate: qualPut["retDate"],
  139. users: qualPut["users"],
  140. value: qualPut["value"]
  141. });
  142. request.onsuccess = function (e) {
  143. }
  144. request.onerror = function (e) {
  145. }
  146. }
  147. db.close();
  148. }
  149. request.onerror = QualStorage.indexedDB.onerror;
  150. }
  151.  
  152. QualStorage.indexedDB.getQuals = function () {
  153. var request = indexedDB.open("QualDB", v);
  154.  
  155. request.onsuccess = function (e) {
  156. QualStorage.indexedDB.db = e.target.result;
  157.  
  158. var db = QualStorage.indexedDB.db;
  159. var transaction = db.transaction('Quals', 'readonly');
  160. var store = transaction.objectStore('Quals');
  161.  
  162. var results = [];
  163. var tmp_results = {};
  164.  
  165. store.openCursor().onsuccess = function (event) {
  166. var cursor = event.target.result;
  167. if (cursor) {
  168. var qual = cursor.value;
  169. if (tmp_results[cursor.key] === undefined) {
  170. tmp_results[cursor.key] = [];
  171. tmp_results[cursor.key][0] = qual.qualId;
  172. tmp_results[cursor.key][1] = qual.qualName;
  173. tmp_results[cursor.key][2] = qual.author;
  174. tmp_results[cursor.key][3] = qual.desc;
  175. tmp_results[cursor.key][4] = qual.assDate;
  176. tmp_results[cursor.key][5] = qual.retDate;
  177. tmp_results[cursor.key][6] = qual.users;
  178. tmp_results[cursor.key][7] = qual.value;
  179. }
  180. cursor.continue();
  181. } else {
  182. for (var key in tmp_results) {
  183. results.push(tmp_results[key]);
  184. }
  185. buildQualTable(results);
  186. }
  187. }
  188. db.close();
  189. }
  190. }
  191. //
  192. // END INDEXEDDB METHODS
  193. //
  194. //
  195. // ******************************************************************
  196. //
  197. //
  198. // START SCRAPER METHODS
  199. //
  200. getNextURL = function (data) {
  201. var nextURL = $(data).find('a[href^="/mturk/viewquals"]:contains("Next")').attr("href");
  202. return nextURL;
  203. }
  204.  
  205. scrapeQuals = function (nextPage) {
  206. QualStorage.indexedDB.create();
  207. var nextPage = nextPage;
  208. var currPage = $.get(nextPage, function(data) {
  209. var maxpagerate = $(data).find('td[class="error_title"]:contains("You have exceeded the maximum allowed page request rate for this website.")');
  210. if (maxpagerate.length === 0) {
  211. $('.updateLink').html(parseInt((scrapeNumber / qualCount) * 100) + "\%");
  212. var qualId = $(data).find('a[id*="requestQualLink"]');
  213. var title = $(data).find('a[class="capsulelink"]');
  214. scrapeNumber += title.length;
  215. var author = $(data).find('td[class="capsule_field_title"]:contains("Author:")').next();
  216. var value = $(data).find('td[class="capsule_field_title"]:contains("Qualification Value:")').next();
  217. var users = $(data).find('td[class="capsule_field_title"]:contains("Qualified Users:")').next();
  218. var description = $(data).find('td[class="capsule_field_title"]:contains("Description:")').next();
  219. var dateassigned = $(data).find('td[class="capsule_field_title"]:contains("Date Assigned:")').next();
  220. var dateretake = $(data).find('td[class="capsule_field_title"]:contains("Retake date:")').next();
  221. for (var i = 0; i < title.length; i++) {
  222. qualObject["qualId"] = qualId.eq(i).attr("href").split('=')[1];
  223. qualObject["qualName"] = title.eq(i).text().trim();
  224. qualObject["author"] = author.eq(i).text().trim();
  225. qualObject["desc"] = description.eq(i).text().trim();
  226. qualObject["assDate"] = dateassigned.eq(i).text().trim();
  227. qualObject["retDate"] = dateretake.eq(i).text().trim();
  228. qualObject["users"] = users.eq(i).text().trim();
  229. qualObject["value"] = value.eq(i).text().trim();
  230. QualStorage.indexedDB.addQual(qualObject);
  231. qualObject = {};
  232. }
  233. nextPage = getNextURL(data);
  234. if (! nextPage) {
  235. $('.updateLink').html("Update ");
  236. } else {
  237. setTimeout(scrapeQuals(nextPage), 500);
  238. }
  239. } else {
  240. setTimeout(scrapeQuals(nextPage), 2000);
  241. }
  242. });
  243. }
  244.  
  245. //
  246. // END SCRAPER METHODS
  247. //
  248. //
  249. // ******************************************************************
  250. //
  251. //
  252. // START EVENT HANDLERS
  253. //
  254. addQualElement = function () {
  255. var allas, thisa;
  256. allas = document.getElementsByTagName('a');
  257. for (var i = 0; i < allas.length; i++)
  258. {
  259. thisa = allas[i];
  260. if ( thisa.innerHTML.match(/Transfer Earnings/))
  261. {
  262. var hed = document.createElement('tr');
  263. hed.className = "metrics-table-header-row";
  264. var qualsHeader = document.createElement('th');
  265. qualsHeader.innerHTML = "Qualifications";
  266. qualsHeader.className = "metrics-table-first-header";
  267. hed.appendChild(qualsHeader);
  268. var qualsValue = document.createElement('th');
  269. qualsValue.innerHTML = "Value";
  270. hed.appendChild(qualsValue);
  271. var row = document.createElement('tr');
  272. row.className = "odd";
  273. var qualsAssignedText = document.createElement('p');
  274. qualsAssignedText.setAttribute("name", "qualTitle");
  275. qualsAssignedText.innerHTML = "Qualifications Assigned &nbsp;";
  276. var cellLeft = document.createElement('td');
  277. cellLeft.className = "metrics-table-first-value";
  278. cellLeft.appendChild(qualsAssignedText);
  279. row.appendChild(cellLeft);
  280. var cellRight = document.createElement('td');
  281. cellRight.innerHTML = qualCount + " (+" + qualDiff + ")";
  282. row.appendChild(cellRight);
  283. thisa.parentNode.parentNode.parentNode.insertBefore(hed,thisa.parentNode.parentNode.nextSibling);
  284. hed.parentNode.insertBefore(row,hed.nextSibling);
  285. //thisa.parentNode.parentNode.parentNode.insertBefore(row,thisa.parentNode.parentNode.nextSibling);
  286. $('p[name="qualTitle"]').append('<a href="#" class="updateLink" >Update </a>');
  287. $('p[name="qualTitle"]').append('<button title="View Qual Table" name="qualTableBut" class="qualTableBut" style="position:absolute;border-style:none;width:7px;height:10px;padding:0;margin-left:10px;margin-top:2px;background-image:url(https://i.imgur.com/iu7zXPz.png);background-color:transparent;cursor:pointer;"></button>').button();
  288. }
  289. }
  290. }
  291.  
  292. buildQualTable = function (qualStore) {
  293. $('#qualTable').append('<thead><tr><th>Qualification ID</th><th>Qualification Name</th><th>Author</th><th>Description</th><th>Assigned Date</th><th>Retake Date</th><th>Users</th><th>Value</th></tr></thead>');
  294. $('#qualTable').append('<tbody></tbody>');
  295. for (var j = 0; j < qualStore.length; j++) {
  296. var qualRow = String(".qualRow" + j);
  297. var tr = document.createElement("tr");
  298. tr.setAttribute('class', ('qualRow' + j));
  299. $(tr).append("<td>" + qualStore[j][0] + "</td>");
  300. $(tr).append("<td>" + qualStore[j][1] + "</td>");
  301. $(tr).append("<td>" + qualStore[j][2] + "</td>");
  302. $(tr).append("<td style='width:350px'>" + qualStore[j][3] + "</td>");
  303. $(tr).append("<td>" + qualStore[j][4] + "</td>");
  304. $(tr).append("<td>" + qualStore[j][5] + "</td>");
  305. $(tr).append("<td>" + qualStore[j][6] + "</td>");
  306. $(tr).append("<td>" + qualStore[j][7] + "</td>");
  307. $('#qualTable tbody').append(tr);
  308. }
  309. $('#qualTable').tablesorter();
  310. }
  311.  
  312. $(document).on('click', '.updateLink', function () {
  313. scrapeQuals(nextPage);
  314. });
  315.  
  316. $(document).ready( function () {
  317. if (document.URL === "https://www.mturk.com/mturk/qualtable") {
  318. $('body').html('');
  319. var qualTable = document.createElement("table");
  320. qualTable.setAttribute('class', 'tablesorter');
  321. qualTable.setAttribute('id', 'qualTable');
  322. $('body').append(qualTable);
  323. var qualElements = QualStorage.indexedDB.getQuals();
  324. }
  325. });
  326.  
  327. $(document).on('click', '.qualTableBut', function () {
  328. window.open("https://www.mturk.com/mturk/qualtable", '_blank');
  329. });
  330. //
  331. // END EVENT HANDLERS
  332. //
  333. //