Mturk Dashboard

Modifies the MTurk dashboard.

当前为 2016-04-23 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Mturk Dashboard
  3. // @namespace http://kadauchi.com/
  4. // @version 1.6.6
  5. // @description Modifies the MTurk dashboard.
  6. // @author Kadauchi
  7. // @icon http://kadauchi.com/avatar1.jpg
  8. // @include https://www.mturk.com/mturk/dashboard*
  9. // @grant GM_log
  10. // @grant GM_setClipboard
  11. // @require https://code.jquery.com/jquery-3.0.0-beta1.min.js
  12. // ==/UserScript==
  13.  
  14. Todays_Projected_Earnings(); // Code cleanup needed.
  15. Todays_Projected_Bonus();
  16. Best_Worst_Case();
  17. Real_Stats();
  18. Changes();
  19. Yearly();
  20.  
  21. function Todays_Projected_Earnings(){
  22. var TPEhitLOG = {}; var TPEdetailsLOG = {};
  23. if (localStorage.TPEhitLOG){
  24. TPEhitLOG = JSON.parse(localStorage.TPEhitLOG);
  25. }
  26.  
  27. var today = $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).prop("href");
  28. var pe = Number(localStorage.TPE_pe) || 0;
  29.  
  30. var $peTR = $('<div id="TPE_div" class="even" style="display:table-row">');
  31. var $peTD1 = $('<td class="metrics-table-first-value">');
  32. var $peTD2 = $('<td>');
  33. var $peA = $('<a href="javascript:void(0)">Today\'s Projected Earnings</a>');
  34. var $TPE_details = $('<span style="color: blue; font-size: 10px; cursor: pointer; float: right;">Details<img style="margin-left: 5px;" src="/media/more.gif" border="0/"></span>');
  35. var $peSPAN = $('<span class="reward">$0.00</span>');
  36. $("td.metrics-table-first-value:contains(Total Earnings)").parent().after($peTR);
  37. $peTR.append($peTD1.append($peA,$TPE_details),$peTD2.append($peSPAN));
  38.  
  39. var $TPED_table = $('<table style="display: none;" width="760" align="center" cellspacing="0" cellpadding="0">');
  40. var $TPED_tboday = $('<tbody>');
  41. var $TPED_tr_1 = $('<tr id="TPE_tr" height="25px"><td width="10" bgcolor="#7fb4cf" style="padding-left: 10px;"></td><td width="100%" bgcolor="#7fb4cf" class="white_text_14_bold">Today\'s Projected Earnings Details&nbsp;&nbsp;<a id="fourmEXPORT" href="javascript:void(0)" class="whatis" >(Forum Export)</a></td><td width="10" align="right" bgcolor="#7fb4cf"></td></tr>');
  42. var $TPED_tr_2 = $('<tr><td class="container-content" colspan="3"><table class="metrics-table" width="100%"><tbody><tr><td width="100%"><table class="metrics-table" width="100%"><tbody id="tbody2"></tbody></table></td></tr></tbody></table></td></tr>');
  43. var $TPED_tr_h = $('<tr class="metrics-table-header-row"><th class="metrics-table-first-header">Requester</th><th>Submitted</th><th>Projected</th></tr>');
  44.  
  45. $("#subtabs_and_searchbar").next().next().after($TPED_table);
  46. $TPED_table.append($TPED_tboday);
  47. $TPED_tboday.append($TPED_tr_1,$TPED_tr_2);
  48. $("#tbody2").append($TPED_tr_h);
  49.  
  50. $("#fourmEXPORT").click(function(){
  51. var exportcode = "";
  52. var bonus = $("#bonus").text();
  53. if (bonus !== "$0.00"){
  54. var total = (Number(pe)+Number(bonus.replace(/[^0-9.]/g, ""))).toFixed(2);
  55. exportcode += "[b]Today's Projected Earnings: $"+Number(pe).toFixed(2)+" + Bonuses: "+bonus+" = $"+total+"[/b]\n";
  56.  
  57. }
  58. else {
  59. exportcode += "[b]Today's Projected Earnings: $"+Number(pe).toFixed(2)+"[/b]\n";
  60. }
  61. exportcode += "[spoiler=Today's Projected Earnings Full Details][table][tr][th][b]Requester[/b][/th][th][b]Submitted[/b][/th][th][b]Projected[/b][/th][/tr]";
  62.  
  63. var x_sorted = Object.keys(TPEdetailsLOG).sort(function(a,b){return TPEdetailsLOG[a].reward - TPEdetailsLOG[b].reward;});
  64. for (var j = x_sorted.length-1; j > -1; j--){
  65. var xkey = x_sorted[j];
  66. var x_req = TPEdetailsLOG[xkey].req;
  67. var x_reqid = TPEdetailsLOG[xkey].reqid;
  68. var x_submitted = TPEdetailsLOG[xkey].submit;
  69. var x_reward = Number(TPEdetailsLOG[xkey].reward).toFixed(2);
  70. if (x_req === "Bonuses"){
  71. if (x_reward !== "0.00"){
  72. exportcode += "[tr][td]"+x_req+"[/td][td]"+x_submitted+"[/td][td]$"+x_reward+"[/td][/tr]\n";
  73. }
  74. }
  75. else {
  76. exportcode += "[tr][td][url=https://www.mturk.com/mturk/searchbar?selectedSearchType=hitgroups&requesterId="+x_reqid+"]"+x_req+"[/url][/td][td]"+x_submitted+"[/td][td]$"+x_reward+"[/td][/tr]\n";
  77. }
  78. }
  79. exportcode += "[/table][/spoiler]";
  80.  
  81. GM_setClipboard(exportcode);
  82. alert("Forum Export copied to your clipboard.");
  83. });
  84.  
  85. $peA.click(function(){
  86. if ($peA.text() === "Today's Projected Earnings"){
  87. var confirmation = confirm("Are you sure you want to recalculate Today's Projected Earnings?");
  88. if (confirmation === true){
  89. TPEhitLOG = {}; TPEdetailsLOG = {}; pe = 0;
  90. $("#tbody2").find("tr.odd, tr.even").remove();
  91. getDATA(today);
  92. $peSPAN.text("$0.00");
  93. }
  94. }
  95. });
  96.  
  97. $TPE_details.click(function(){
  98. $TPE_details.find("img").attr("src", ($TPE_details.find("img").attr("src") === "/media/more.gif") ? "/media/less.gif" : "/media/more.gif");
  99. $TPED_table.toggle();
  100. });
  101.  
  102. if (today){
  103. var date = today.split("encodedDate=")[1];
  104. if (date === localStorage.TPE_date){
  105. $peSPAN.text("$"+Number(pe).toFixed(2));
  106. getDATA(localStorage.TPE_lastpage);
  107. }
  108. else {
  109. localStorage.TPE_date = date;
  110. TPEhitLOG = {}; pe = 0;
  111. $peSPAN.text("$0.00");
  112. getDATA(today);
  113. }
  114. }
  115. else {
  116. $peA.text("Today's Projected Earnings");
  117. $peSPAN.text("$0.00");
  118. }
  119.  
  120. function getDATA(URL){
  121. var page = URL.match(/Number=([0-9]*)/g);
  122. if (page){
  123. $peA.text("Calculating Page "+page.toString().replace(/[^0-9.]/g, ""));
  124. }
  125. else {
  126. $peA.text("Calculating Page 1");
  127. }
  128.  
  129. $.get(URL, function(data){
  130. var $data = $(data);
  131. var $hits = $data.find("#dailyActivityTable").find("tr[valign='top']");
  132. if ($hits.length){
  133. var url = $data.find("a:contains(Next)").eq(0).prop("href");
  134. for (var i = 0; i < $hits.length; i++){
  135. var req = $hits.eq(i).find("td.statusdetailRequesterColumnValue").text().trim();
  136. var title = $hits.eq(i).find("td.statusdetailTitleColumnValue").text().trim();
  137. var reward = $hits.eq(i).find("td.statusdetailAmountColumnValue").text().trim();
  138. var status = $hits.eq(i).find("td.statusdetailStatusColumnValue").text().trim();
  139. var reqid = $hits.eq(i).find("a").prop("href").split("requesterId=")[1].split("&")[0];
  140. var hitid = $hits.eq(i).find("a").prop("href").split("HIT+")[1];
  141.  
  142. if (!TPEhitLOG[hitid]){
  143. TPEhitLOG[hitid] = {
  144. req : req,
  145. title : title,
  146. reward : reward,
  147. status : status,
  148. reqid : reqid,
  149. hitid : hitid
  150. };
  151. }
  152. }
  153. if (url){
  154. getDATA(url);
  155. }
  156. else {
  157. pe = 0;
  158. for(var key in TPEhitLOG){
  159. if (TPEhitLOG[key].status !== "Rejected"){
  160. pe += parseFloat(TPEhitLOG[key].reward.replace(/[^0-9.]/g, ""));
  161. }
  162. if (!TPEdetailsLOG[TPEhitLOG[key].reqid]){
  163. TPEdetailsLOG[TPEhitLOG[key].reqid] = {
  164. req : TPEhitLOG[key].req,
  165. submit : 1,
  166. reward : parseFloat(TPEhitLOG[key].reward.replace(/[^0-9.]/g, "")),
  167. reqid : TPEhitLOG[key].reqid
  168. };
  169. }
  170. else {
  171. TPEdetailsLOG[TPEhitLOG[key].reqid].submit = TPEdetailsLOG[TPEhitLOG[key].reqid].submit + 1;
  172. TPEdetailsLOG[TPEhitLOG[key].reqid].reward = TPEdetailsLOG[TPEhitLOG[key].reqid].reward + parseFloat(TPEhitLOG[key].reward.replace(/[^0-9.]/g, ""));
  173. }
  174. }
  175.  
  176. if (!TPEdetailsLOG.bonuses && $("#bonus").length){
  177. TPEdetailsLOG.bonuses = {
  178. req : "Bonuses",
  179. submit : "N/A",
  180. reward : parseFloat($("#bonus").text().replace(/[^0-9.]/g, "")),
  181. reqid : "N/A"
  182. };
  183. }
  184. else if ($("#bonus").length){
  185. TPEdetailsLOG.bonuses.reward = parseFloat($("#bonus").text().replace(/[^0-9.]/g, ""));
  186. }
  187.  
  188. var d_sorted = Object.keys(TPEdetailsLOG).sort(function(a,b){return TPEdetailsLOG[a].reward - TPEdetailsLOG[b].reward;});
  189. var oddeven = true;
  190. for (var j = d_sorted.length-1; j > -1; j--){
  191. var dkey = d_sorted[j];
  192. var d_req = TPEdetailsLOG[dkey].req;
  193. var d_submitted = TPEdetailsLOG[dkey].submit;
  194. var d_reward = Number(TPEdetailsLOG[dkey].reward).toFixed(2);
  195. if (oddeven){
  196. oddeven = false;
  197. $("#tbody2").append('<tr class="odd"><td class="metrics-table-first-value">'+d_req+'</td><td>'+d_submitted+'</td><td><span class="reward">$'+d_reward+'</span></td></tr>');
  198. }
  199. else {
  200. oddeven = true;
  201. $("#tbody2").append('<tr class="even"><td class="metrics-table-first-value">'+d_req+'</td><td>'+d_submitted+'</td><td><span class="reward">$'+d_reward+'</span></td></tr>');
  202. }
  203. }
  204. localStorage.TPEhitLOG = JSON.stringify(TPEhitLOG);
  205. localStorage.TPE_lastpage = URL;
  206. localStorage.TPE_pe = pe;
  207. $peA.text("Today's Projected Earnings");
  208. $peSPAN.text("$"+Number(pe).toFixed(2));
  209. }
  210. }
  211. else {
  212. setTimeout(function(){ getDATA(URL); }, 2000);
  213. }
  214. });
  215. }
  216. }
  217.  
  218. function Todays_Projected_Bonus(){
  219. var today = $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).prop("href");
  220.  
  221. var $bonusDIV = $('<div id="bonusDIV" class="odd" style="display:table-row">');
  222. $($bonusDIV).append('<td class="metrics-table-first-value"><a href="javascript:void(0)">Today\'s Projected Bonuses</a></td><td><span id="bonus" class="reward">$0.00</span></td>');
  223. $("#TPE_div").after($bonusDIV);
  224.  
  225. if (today){
  226. var date = today.split("encodedDate=")[1];
  227. if (date === localStorage.TPB_date){
  228. if (!localStorage.today_start_bonuses){
  229. localStorage.today_start_bonuses = Number($("#bonus_earnings_amount").text().replace(/[^0-9.]/g, ""));
  230. }
  231. Bonuses(localStorage.today_start_bonuses);
  232. }
  233. else {
  234. var today_approved = Number($("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().text());
  235. if (today_approved === 0){
  236. localStorage.today_start_bonuses = (Number($("#bonus_earnings_amount").text().replace(/[^0-9.]/g, ""))-Number($("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().next().next().next().text().replace(/[^0-9.]/g, "")));
  237. }
  238. else {
  239. localStorage.today_start_bonuses = Number($("#bonus_earnings_amount").text().replace(/[^0-9.]/g, ""));
  240. }
  241. localStorage.TPB_date = date;
  242. Bonuses(localStorage.today_start_bonuses);
  243. }
  244. }
  245.  
  246. function Bonuses(starting_bonus){
  247. var total_bonuses = $("#bonus_earnings_amount").text().replace(/[^0-9.]/g, "");
  248. $("#bonus").text("$"+(Math.round((Number(total_bonuses)-Number(starting_bonus))*100)/100).toFixed(2));
  249. }
  250. }
  251.  
  252. function Real_Stats(){
  253. var approved = Number($("td.metrics-table-first-value:contains(... Approved)").next().text());
  254. var rejected = Number($("td.metrics-table-first-value:contains(... Rejected)").next().text());
  255.  
  256. $("td.metrics-table-first-value:contains(... Approved)").next().next().text(Math.round(((approved)/(approved+rejected))*1000000)/10000+"%");
  257. $("td.metrics-table-first-value:contains(... Rejected)").next().next().text(Math.round(((rejected)/(approved+rejected))*1000000)/10000+"%");
  258. }
  259.  
  260. function Best_Worst_Case(){
  261. var submitted = Number($("td.metrics-table-first-value:contains(HITs Submitted)").next().text());
  262. var rejected = Number($("td.metrics-table-first-value:contains(... Rejected)").next().text());
  263.  
  264. var $under99 = $('<span style="color: orange;"> ('+Math.round((rejected-((1.0 - 99/100)*submitted))/((1.0 - 99/100)-1))+' ≥ 99%)</span>');
  265. var $under95 = $('<span style="color: red;"> ('+Math.round((rejected-((1.0 - 95/100)*submitted))/((1.0 - 95/100)-1))+' ≥ 95%)</span>');
  266.  
  267. $("td.metrics-table-first-value:contains(... Pending)").append($under99,$under95);
  268. $("td.metrics-table-first-value:contains(... Pending)").next().next().text(Math.round(((submitted-rejected)/submitted)*1000000)/10000+"%").css({"color": "green"});
  269. }
  270.  
  271. function Changes(){
  272. var today = $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).prop("href");
  273.  
  274. if (today){
  275. var date = today.split("encodedDate=")[1];
  276. if (date !== localStorage.Changes_date){
  277. localStorage.Changes_date = date;
  278. localStorage.today_submitted = 0;
  279. localStorage.today_approved = 0;
  280. localStorage.today_rejected = 0;
  281. localStorage.today_pending = 0;
  282. }
  283. }
  284.  
  285. var earnings_hits = Number($("#approved_hits_earnings_amount").text().replace(/[^0-9.]/g, ""));
  286. var earnings_bonuses = Number($("#bonus_earnings_amount").text().replace(/[^0-9.]/g, ""));
  287. var earnings_total = Number($("#total_earnings_amount").text().replace(/[^0-9.]/g, ""));
  288. var earnings_transfer = Number($("#transfer_earnings").text().replace(/[^0-9.]/g, ""));
  289. var hits_submitted = Number($("td.metrics-table-first-value:contains(HITs Submitted)").next().text());
  290. var hits_approved = Number($("td.metrics-table-first-value:contains(... Approved)").next().text());
  291. var hits_rejected = Number($("td.metrics-table-first-value:contains(... Rejected)").next().text());
  292. var hits_pending = Number($("td.metrics-table-first-value:contains(... Pending)").next().text());
  293. var today_submitted = Number($("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().text());
  294. var today_approved = Number($("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().text());
  295. var today_rejected = Number($("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().next().text());
  296. var today_pending = Number($("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().next().next().text());
  297.  
  298. if (Number(localStorage.earnings_hits) !== earnings_hits){
  299. $("#approved_hits_earnings_amount").prev().append('<span id="earnings_hits" style="float:right;">+$'+(Math.round((earnings_hits-Number(localStorage.earnings_hits))*100)/100).toFixed(2)+'</span>');
  300. localStorage.earnings_hits = earnings_hits;
  301. }
  302. if (Number(localStorage.earnings_bonuses) !== earnings_bonuses){
  303. $("#bonus_earnings_amount").prev().append('<span id="earnings_bonuses" style="float:right;">+$'+(Math.round((earnings_bonuses-Number(localStorage.earnings_bonuses))*100)/100).toFixed(2)+'</span>');
  304. localStorage.earnings_bonuses = earnings_bonuses;
  305. }
  306. if (Number(localStorage.earnings_total) !== earnings_total){
  307. $("#total_earnings_amount").prev().append('<span id="earnings_total" style="float:right;">+$'+(Math.round((earnings_total-Number(localStorage.earnings_total))*100)/100).toFixed(2)+'</span>');
  308. localStorage.earnings_total = earnings_total;
  309. }
  310. if (Number(localStorage.earnings_transfer) !== earnings_transfer){
  311. if (Number(localStorage.earnings_transfer) > earnings_transfer){
  312. $("#transfer_earnings").prev().append('<span id="earnings_transfer" style="float:right;">-$'+(Math.round((Number(localStorage.earnings_transfer)-earnings_transfer)*100)/100).toFixed(2)+'</span>');
  313. }
  314. else {
  315. $("#transfer_earnings").prev().append('<span id="earnings_transfer" style="float:right;">+$'+(Math.round((earnings_transfer-Number(localStorage.earnings_transfer))*100)/100).toFixed(2)+'</span>');
  316. }
  317. localStorage.earnings_transfer = earnings_transfer;
  318. }
  319. if (Number(localStorage.hits_submitted) !== hits_submitted){
  320. $("td.metrics-table-first-value:contains(HITs Submitted)").append('<span id="hits_submitted" style="float:right;">+'+(hits_submitted-Number(localStorage.hits_submitted))+'</span>');
  321. localStorage.hits_submitted = hits_submitted;
  322. }
  323. if (Number(localStorage.hits_approved) !== hits_approved){
  324. $("td.metrics-table-first-value:contains(... Approved)").append('<span id="hits_approved" style="float:right;">+'+(hits_approved-Number(localStorage.hits_approved))+'</span>');
  325. localStorage.hits_approved = hits_approved;
  326. }
  327. if (Number(localStorage.hits_rejected) !== hits_rejected){
  328. $("td.metrics-table-first-value:contains(... Rejected)").append('<span id="hits_rejected" style="float:right;">+'+(hits_rejected-Number(localStorage.hits_rejected))+'</span>');
  329. localStorage.hits_rejected = hits_rejected;
  330. }
  331. if (Number(localStorage.hits_pending) !== hits_pending){
  332. if (Number(localStorage.hits_pending) > hits_pending){
  333. $("td.metrics-table-first-value:contains(... Pending)").append('<span id="hits_pending" style="float:right;">-'+(Number(localStorage.hits_pending)-hits_pending)+'</span>');
  334. }
  335. else {
  336. $("td.metrics-table-first-value:contains(... Pending)").append('<span id="hits_pending" style="float:right;">+'+(hits_pending-Number(localStorage.hits_pending))+'</span>');
  337. }
  338. localStorage.hits_pending = hits_pending;
  339. }
  340. if (Number(localStorage.today_submitted) !== today_submitted){
  341. $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().append('<span id="today_submitted" style="float:left;">+'+(today_submitted-Number(localStorage.today_submitted))+'</span>');
  342. localStorage.today_submitted = today_submitted;
  343. }
  344. if (Number(localStorage.today_approved) !== today_approved){
  345. $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().append('<span id="today_approved" style="float:left;">+'+(today_approved-Number(localStorage.today_approved))+'</span>');
  346. localStorage.today_approved = today_approved;
  347. }
  348. if (Number(localStorage.today_rejected) !== today_rejected){
  349. $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().next().append('<span id="today_rejected" style="float:left;">+'+(today_rejected-Number(localStorage.today_rejected))+'</span>');
  350. localStorage.today_rejected = today_rejected;
  351. }
  352. if (Number(localStorage.today_pending) !== today_pending){
  353. if (Number(localStorage.today_pending) > today_pending){
  354. $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().next().next().append('<span id="today_pending" style="float:left;">-'+(Number(localStorage.today_pending)-today_pending)+'</span>');
  355. }
  356. else {
  357. $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().next().next().append('<span id="today_pending" style="float:left;">+'+(today_pending-Number(localStorage.today_pending))+'</span>');
  358. }
  359. localStorage.today_pending = today_pending;
  360. }
  361. }
  362.  
  363. function Yearly(){
  364. var totalearnings = Number($("#total_earnings_amount").text().replace(/[^0-9.]/g, ""));
  365. var $reward = $("#table_yearly_earnings").find("span.reward");
  366.  
  367. for (var i = 0; i < $reward.length; i++){
  368. totalearnings -= Number($reward.eq(i).text().replace(/[^0-9.]/g, ""));
  369. }
  370.  
  371. var earnings2016 = Number((totalearnings).toFixed(2)).toLocaleString("en");
  372.  
  373. var $thisyear = $('<tr class="odd"><td class="metrics-table-first-value">2016</td><td id="yearly_earnings_amount"><span class="reward">$'+earnings2016+'</span></td></tr>');
  374. $("#table_yearly_earnings").find("tr.metrics-table-header-row").after($thisyear);
  375. }