[Www] [Worker] Mturk Dashboard

Modifies the Www and Worker MTurk dashboard.

当前为 2017-12-07 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         [Www] [Worker] Mturk Dashboard
// @namespace    http://kadauchi.com/
// @version      1.8.1
// @description  Modifies the Www and Worker MTurk dashboard.
// @author       Kadauchi
// @icon         http://i.imgur.com/oGRQwPN.png
// @include      https://www.mturk.com/mturk/dashboard*
// @grant        GM_log
// @grant        GM_setClipboard
// @require      https://code.jquery.com/jquery-3.0.0-beta1.min.js
// @include      https://worker.mturk.com/dashboard*
// @grant        GM_xmlhttpRequest
// @connect      mturk.com
// ==/UserScript==

if (location.href.indexOf(`https://www.mturk.com/mturk/dashboard`) !== -1) {
	var LOADED = $("#total_earnings_amount").length;
	if (LOADED){

		// Functions that can be commented out if you don't want it to run.
		Todays_Projected_Earnings();
		Todays_Bonuses();
		Best_Worst_Case();
		Real_Stats();
		Changes();
		Yearly();
		Goal();

	}
}

if (location.href.indexOf(`https://worker.mturk.com/dashboard`) !== -1) {
	initialize();

	// Functions that can be commented out if you don't want it to run.
	allApprovedRate();
	allRejectedRate();
	fourDigitPercents();
	rejectionsBelow99();
	rejectionsBelow95();
	totalLast45Days();
	hitStatusChanges(); // partially working
	todaysActivity();
}

// Don't touch anything below here.
function Todays_Projected_Earnings(){
	var TPEhitLOG = {}; var TPEdetailsLOG = {}; var pe = 0;

	var today = $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).prop("href");

	var $peTR = $('<div id="TPE_div" class="even" style="display:table-row">');
	var $peTD1 = $('<td class="metrics-table-first-value">');
	var $peTD2 = $('<td>');
	var $peA = $('<a href="javascript:void(0)">Today\'s Projected Earnings</a>');
	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>');
	var $peSPAN = $('<span class="reward">$0.00</span>');
	$("td.metrics-table-first-value:contains(Total Earnings)").parent().after($peTR);
	$peTR.append($peTD1.append($peA,$TPE_details),$peTD2.append($peSPAN));

	var $TPED_table = $('<table style="display: none;" width="760" align="center" cellspacing="0" cellpadding="0">');
	var $TPED_tboday = $('<tbody>');
	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>');
	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>');
	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>');

	$("#subtabs_and_searchbar").next().next().after($TPED_table);
	$TPED_table.append($TPED_tboday);
	$TPED_tboday.append($TPED_tr_1,$TPED_tr_2);
	$("#tbody2").append($TPED_tr_h);

	$("#fourmEXPORT").click(function(){
		var exportcode = "";
		var bonus = $("#bonus").text();
		if (bonus !== "$0.00"){
			var total = (Number(pe)+Number(bonus.replace(/[^0-9.]/g, ""))).toFixed(2);
			exportcode += "[b]Today's Projected Earnings: $"+Number(pe).toFixed(2)+" + Bonuses: "+bonus+" = $"+total+"[/b]\n";

		}
		else {
			exportcode += "[b]Today's Projected Earnings: $"+Number(pe).toFixed(2)+"[/b]\n";
		}

		var today_submitted   = $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().text();
		var today_approved    = $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().text();
		var today_rejected    = $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().next().text();
		var today_pending     = $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().next().next().text();


		exportcode +=
			'[spoiler=Today\'s Projected Earnings Overview][table]' +
			'[tr][td]Submitted[/td][td]' + today_submitted + '[/td][/tr]' +
			'[tr][td]Approved[/td][td]' + today_approved + '[/td][/tr]' +
			'[tr][td]Rejected[/td][td]' + today_rejected + '[/td][/tr]' +
			'[tr][td]Pending[/td][td]' + today_pending + '[/td][/tr]' +
			'[/table][/spoiler]';


		GM_setClipboard(exportcode);
		alert("Forum Export copied to your clipboard.");
	});

	$peA.click(function(){
		if ($peA.text() === "Today's Projected Earnings"){
			var confirmation = confirm("Are you sure you want to recalculate Today's Projected Earnings?");
			if (confirmation === true){
				TPEhitLOG = {}; TPEdetailsLOG = {}; pe = 0;
				$("#tbody2").find("tr.odd, tr.even").remove();
				getDATA(today);
				$peSPAN.text("$0.00");
			}
		}
	});

	$TPE_details.click(function(){
		$TPE_details.find("img").attr("src", ($TPE_details.find("img").attr("src") === "/media/more.gif") ? "/media/less.gif" : "/media/more.gif");
		$TPED_table.toggle();
	});

	if (today){
		var date = today.split("encodedDate=")[1];
		if (date === localStorage.TPE_date){
			if (localStorage.TPEhitLOG){
				TPEhitLOG = JSON.parse(localStorage.TPEhitLOG);
			}
			pe = Number(localStorage.TPE_pe) || 0;
			$peSPAN.text("$"+Number(pe).toFixed(2));
			getDATA(localStorage.TPE_lastpage);
		}
		else {
			localStorage.TPE_date = date;
			localStorage.Goal_progress = 0;
			TPEhitLOG = {}; pe = 0;
			$peSPAN.text("$0.00");
			getDATA(today);
		}
	}

	function getDATA(URL){
		var page = URL.match(/Number=([0-9]*)/g);
		if (page){
			$peA.text("Calculating Page "+page.toString().replace(/[^0-9.]/g, ""));
		}
		else {
			localStorage.removeItem("TPEhitLOG");
			localStorage.Goal_progress = 0;
			$peA.text("Calculating Page 1");
		}

		$.get(URL, function(data){
			var $data = $(data);
			var $hits = $data.find("#dailyActivityTable").find("tr[valign='top']");
			var pagereqerr = $data.find("td.error_title:contains(You have exceeded the maximum allowed page request rate for this website.)").length;
			var noactivity = $data.find("#dailyActivityTable").find("td:contains(You have no HIT activity on this day matching the selected status.)").length;
			if ($hits.length){
				console.log("hit length");
				var url = $data.find("a:contains(Next)[href*=statusdetail]").eq(0).prop("href");
				for (var i = 0; i < $hits.length; i++){
					var req = $hits.eq(i).find("td.statusdetailRequesterColumnValue").text().trim();
					var title = $hits.eq(i).find("td.statusdetailTitleColumnValue").text().trim();
					var reward = $hits.eq(i).find("td.statusdetailAmountColumnValue").text().trim();
					var status = $hits.eq(i).find("td.statusdetailStatusColumnValue").text().trim();
					var reqid = $hits.eq(i).find("a").prop("href").split("requesterId=")[1].split("&")[0];
					var hitid = $hits.eq(i).find("a").prop("href").split("HIT+")[1];

					if (!TPEhitLOG[hitid]){
						TPEhitLOG[hitid] = {
							req    : req,
							title  : title,
							reward : reward,
							status : status,
							reqid  : reqid,
							hitid  : hitid
						};
					}
				}
				if (url){
					getDATA(url);
				}
				else {
					pe = 0;
					for(var key in TPEhitLOG){
						if (TPEhitLOG[key].status !== "Rejected"){
							pe += parseFloat(TPEhitLOG[key].reward.replace(/[^0-9.]/g, ""));
						}
						if (!TPEdetailsLOG[TPEhitLOG[key].reqid]){
							TPEdetailsLOG[TPEhitLOG[key].reqid] = {
								req    : TPEhitLOG[key].req,
								submit : 1,
								reward : parseFloat(TPEhitLOG[key].reward.replace(/[^0-9.]/g, "")),
								reqid  : TPEhitLOG[key].reqid
							};
						}
						else {
							TPEdetailsLOG[TPEhitLOG[key].reqid].submit = TPEdetailsLOG[TPEhitLOG[key].reqid].submit + 1;
							TPEdetailsLOG[TPEhitLOG[key].reqid].reward = TPEdetailsLOG[TPEhitLOG[key].reqid].reward + parseFloat(TPEhitLOG[key].reward.replace(/[^0-9.]/g, ""));
						}
					}

					if (!TPEdetailsLOG.bonuses && $("#bonus").length){
						TPEdetailsLOG.bonuses  = {
							req    : "Bonuses",
							submit : "N/A",
							reward : parseFloat($("#bonus").text().replace(/[^0-9.]/g, "")),
							reqid  : "N/A"
						};
					}
					else if ($("#bonus").length){
						TPEdetailsLOG.bonuses.reward = parseFloat($("#bonus").text().replace(/[^0-9.]/g, ""));
					}

					var d_sorted = Object.keys(TPEdetailsLOG).sort(function(a,b){return TPEdetailsLOG[a].reward - TPEdetailsLOG[b].reward;});
					var oddeven = true;
					for (var j = d_sorted.length-1; j > -1; j--){
						var dkey = d_sorted[j];
						var d_req = TPEdetailsLOG[dkey].req;
						var d_submitted = TPEdetailsLOG[dkey].submit;
						var d_reward = Number(TPEdetailsLOG[dkey].reward).toFixed(2);
						if (oddeven){
							oddeven = false;
							$("#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>');
						}
						else {
							oddeven = true;
							$("#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>');
						}
					}
					localStorage.TPEhitLOG = JSON.stringify(TPEhitLOG);
					localStorage.TPE_lastpage = URL;
					localStorage.TPE_pe = pe;
					$peA.text("Today's Projected Earnings");
					$peSPAN.text("$"+Number(pe).toFixed(2));
					localStorage.Goal_percent = ((Number(localStorage.TPE_pe)/Number(localStorage.Goal_goal))*100);
					localStorage.Goal_progress = Number(pe)-Number(localStorage.Goal_goal);
					if ($("#goalDIV").length){
						$("#progress").width(Number(localStorage.Goal_percent)+"%");
						$("#progressper").text(Number(localStorage.Goal_progress).toFixed(2));
					}
					Unsynced();
				}
			}
			else if (noactivity){
				console.log("no activity");
				localStorage.TPE_lastpage = URL;
				localStorage.TPE_pe = 0;
				localStorage.Goal_progress = 0;
				$peA.text("Today's Projected Earnings");
				$peSPAN.text("$0.00");
			}
			else if (pagereqerr) {
				console.log("set timeout");
				setTimeout(function(){ getDATA(URL); }, 2000);
			}
		});
	}

	function Unsynced(){
		var hitscalced = Object.keys(TPEhitLOG).length;
		var submitted  = Number($("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().text());

		if (hitscalced < submitted){
			$peSPAN.css({backgroundColor:"red"});
		}
		else {
			$peSPAN.css({backgroundColor:""});
		}
	}
}

function Goal(){
	if (!localStorage.Goal_percent){
		localStorage.Goal_percent = 0;
	}
	if (!localStorage.Goal_progress){
		localStorage.Goal_progress = 0;
	}
	if (!localStorage.Goal_goal){
		localStorage.Goal_goal = 25.00;
	}
	if ($("#bonusDIV").length){
		var $goalDIV0 = $('<div id="goalDIV" class="even" style="display:table-row">');
		$($goalDIV0).append('<td class="metrics-table-first-value"><div id="progressbar" style="width: 100%; height: 7px; border: 1px solid #7fb4cf; border-radius: 3px; overflow: hidden; margin-top: 3px; text-align: center; -webkit-user-select: none; -moz-user-select: none;"><div id="progress" style="height: 100%; background-color: #7fb4cf; -webkit-user-select: none; -moz-user-select: none;"></div></div></td><td><span id="progressper" class="reward">0%</span></td>');
		$("#bonusDIV").after($goalDIV0);
	}
	else {
		var $goalDIV1 = $('<div id="goalDIV" class="odd" style="display:table-row">');
		$($goalDIV1).append('<td class="metrics-table-first-value"><div id="progressbar" style="width: 100%; height: 7px; border: 1px solid #7fb4cf; border-radius: 3px; overflow: hidden; margin-top: 3px; text-align: center; -webkit-user-select: none; -moz-user-select: none;"><div id="progress" style="height: 100%; background-color: #7fb4cf; -webkit-user-select: none; -moz-user-select: none;"></div></div></td><td><span id="progressper" class="reward">0%</span></td>');
		$("#TPE_div").after($goalDIV1);
	}

	$("#progress").width(Number(localStorage.Goal_percent)+"%");
	$("#progressper").text(Number(localStorage.Goal_progress).toFixed(2));

	$("#progressbar").dblclick(function(e){
		e.preventDefault();
		var goal = prompt("Please enter your goal", localStorage.Goal_goal);
		if (goal !== null) {
			localStorage.Goal_goal = goal.replace(/[^0-9.]/g, "");
			localStorage.Goal_percent = ((Number(localStorage.TPE_pe)/Number(localStorage.Goal_goal))*100);
			localStorage.Goal_progress = Number(localStorage.TPE_pe)-Number(localStorage.Goal_goal);
			$("#progress").width(Number(localStorage.Goal_progress)+"%");
			$("#progressper").text(Number(localStorage.Goal_progress).toFixed(2));
		}
	});
}

function Todays_Bonuses(){
	var today = $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).prop("href");

	var $bonusDIV = $('<div id="bonusDIV" class="odd" style="display:table-row">');
	$($bonusDIV).append('<td class="metrics-table-first-value"><a href="javascript:void(0)">Today\'s Bonuses</a></td><td><span id="bonus" class="reward">$0.00</span></td>');
	$("#TPE_div").after($bonusDIV);

	if (today){
		var date = today.split("encodedDate=")[1];
		if (date === localStorage.TB_date){
			if (!localStorage.today_start_bonuses){
				localStorage.today_start_bonuses = Number($("#bonus_earnings_amount").text().replace(/[^0-9.]/g, ""));
			}
			Bonuses(localStorage.today_start_bonuses);
		}
		else {
			var today_approved = Number($("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().text());
			if (today_approved === 0){
				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, "")));
			}
			else {
				localStorage.today_start_bonuses = Number($("#bonus_earnings_amount").text().replace(/[^0-9.]/g, ""));
			}
			localStorage.TB_date = date;
			Bonuses(localStorage.today_start_bonuses);
		}
	}

	function Bonuses(starting_bonus){
		var total_bonuses  = $("#bonus_earnings_amount").text().replace(/[^0-9.]/g, "");
		$("#bonus").text("$"+(Math.round((Number(total_bonuses)-Number(starting_bonus))*100)/100).toFixed(2));
	}
}

function Real_Stats(){
	var approved = Number($("td.metrics-table-first-value:contains(... Approved)").next().text());
	var rejected = Number($("td.metrics-table-first-value:contains(... Rejected)").next().text());

	$("td.metrics-table-first-value:contains(... Approved)").next().next().text(Math.round(((approved)/(approved+rejected))*1000000)/10000+"%");
	$("td.metrics-table-first-value:contains(... Rejected)").next().next().text(Math.round(((rejected)/(approved+rejected))*1000000)/10000+"%");
}

function Best_Worst_Case(){
	var submitted = Number($("td.metrics-table-first-value:contains(HITs Submitted)").next().text());
	var rejected  = Number($("td.metrics-table-first-value:contains(... Rejected)").next().text());
	var approved  = Number($("td.metrics-table-first-value:contains(... Approved)").next().text());
	var pending   = Number($("td.metrics-table-first-value:contains(... Pending)").next().text());

	var $under99 = $('<span style="color: orange;"> ('+Math.round((rejected-((1.0 - 99/100)*submitted))/((1.0 - 99/100)-1))+' ≥ 99%)</span>');
	var $under95 = $('<span style="color: red;"> ('+Math.round((rejected-((1.0 - 95/100)*submitted))/((1.0 - 95/100)-1))+' ≥ 95%)</span>');
	var $worst   = $('<span style="color: red;">\n'+Math.round(approved/(approved+rejected+pending) * 1000000)/10000+'%</span>');

	$("td.metrics-table-first-value:contains(... Pending)").append($under99,$under95);
	$("td.metrics-table-first-value:contains(... Pending)").next().next().text(Math.round(((submitted-rejected)/submitted)*1000000)/10000+"%").css({"color": "green"}).append($worst);
}

function Changes(){
	var today = $("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).prop("href");

	if (today){
		var date = today.split("encodedDate=")[1];
		if (date !== localStorage.Changes_date){
			localStorage.Changes_date = date;
			localStorage.today_submitted = 0;
			localStorage.today_approved  = 0;
			localStorage.today_rejected  = 0;
			localStorage.today_pending   = 0;
		}
	}

	var earnings_hits     = Number($("#approved_hits_earnings_amount").text().replace(/[^0-9.]/g, ""));
	var earnings_bonuses  = Number($("#bonus_earnings_amount").text().replace(/[^0-9.]/g, ""));
	var earnings_total    = Number($("#total_earnings_amount").text().replace(/[^0-9.]/g, ""));
	var earnings_transfer = Number($("#transfer_earnings").text().replace(/[^0-9.]/g, ""));
	var hits_submitted    = Number($("td.metrics-table-first-value:contains(HITs Submitted)").next().text());
	var hits_approved     = Number($("td.metrics-table-first-value:contains(... Approved)").next().text());
	var hits_rejected     = Number($("td.metrics-table-first-value:contains(... Rejected)").next().text());
	var hits_pending      = Number($("td.metrics-table-first-value:contains(... Pending)").next().text());
	var today_submitted   = Number($("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().text());
	var today_approved    = Number($("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().text());
	var today_rejected    = Number($("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().next().text());
	var today_pending     = Number($("a[href^='/mturk/statusdetail?encodedDate']:contains(Today)").eq(0).parent().next().next().next().next().text());

	if (Number(localStorage.earnings_hits) !== earnings_hits){
		$("#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>');
		localStorage.earnings_hits = earnings_hits;
	}
	if (Number(localStorage.earnings_bonuses) !== earnings_bonuses){
		$("#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>');
		localStorage.earnings_bonuses = earnings_bonuses;
	}
	if (Number(localStorage.earnings_total) !== earnings_total){
		$("#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>');
		localStorage.earnings_total = earnings_total;
	}
	if (Number(localStorage.earnings_transfer) !== earnings_transfer){
		if (Number(localStorage.earnings_transfer) > earnings_transfer){
			$("#transfer_earnings").prev().append('<span id="earnings_transfer" style="float:right;">-$'+(Math.round((Number(localStorage.earnings_transfer)-earnings_transfer)*100)/100).toFixed(2)+'</span>');
		}
		else {
			$("#transfer_earnings").prev().append('<span id="earnings_transfer" style="float:right;">+$'+(Math.round((earnings_transfer-Number(localStorage.earnings_transfer))*100)/100).toFixed(2)+'</span>');
		}
		localStorage.earnings_transfer = earnings_transfer;
	}
	if (Number(localStorage.hits_submitted) !== hits_submitted){
		$("td.metrics-table-first-value:contains(HITs Submitted)").append('<span id="hits_submitted" style="float:right;">+'+(hits_submitted-Number(localStorage.hits_submitted))+'</span>');
		localStorage.hits_submitted = hits_submitted;
	}
	if (Number(localStorage.hits_approved) !== hits_approved){
		$("td.metrics-table-first-value:contains(... Approved)").append('<span id="hits_approved" style="float:right;">+'+(hits_approved-Number(localStorage.hits_approved))+'</span>');
		localStorage.hits_approved = hits_approved;
	}
	if (Number(localStorage.hits_rejected) !== hits_rejected){
		$("td.metrics-table-first-value:contains(... Rejected)").append('<span id="hits_rejected" style="float:right;">+'+(hits_rejected-Number(localStorage.hits_rejected))+'</span>');
		localStorage.hits_rejected = hits_rejected;
	}
	if (Number(localStorage.hits_pending) !== hits_pending){
		if (Number(localStorage.hits_pending) > hits_pending){
			$("td.metrics-table-first-value:contains(... Pending)").append('<span id="hits_pending" style="float:right;">-'+(Number(localStorage.hits_pending)-hits_pending)+'</span>');
		}
		else {
			$("td.metrics-table-first-value:contains(... Pending)").append('<span id="hits_pending" style="float:right;">+'+(hits_pending-Number(localStorage.hits_pending))+'</span>');
		}
		localStorage.hits_pending = hits_pending;
	}
	if (Number(localStorage.today_submitted) !== today_submitted){
		$("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>');
		localStorage.today_submitted = today_submitted;
	}
	if (Number(localStorage.today_approved) !== today_approved){
		$("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>');
		localStorage.today_approved = today_approved;
	}
	if (Number(localStorage.today_rejected) !== today_rejected){
		$("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>');
		localStorage.today_rejected = today_rejected;
	}
	if (Number(localStorage.today_pending) !== today_pending){
		if (Number(localStorage.today_pending) > today_pending){
			$("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>');
		}
		else {
			$("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>');
		}
		localStorage.today_pending = today_pending;
	}
}

function Yearly(){
	var totalearnings = Number($("#total_earnings_amount").text().replace(/[^0-9.]/g, ""));
	var $reward = $("#table_yearly_earnings").find("span.reward");

	for (var i = 0; i < $reward.length; i++){
		totalearnings -= Number($reward.eq(i).text().replace(/[^0-9.]/g, ""));
	}

	var earnings2016 = Number((totalearnings).toFixed(2)).toLocaleString("en");

	var $thisyear = $('<tr class="odd"><td class="metrics-table-first-value">2017</td><td id="yearly_earnings_amount"><span class="reward">$'+earnings2016+'</span></td></tr>');
	$("#table_yearly_earnings").find("tr.metrics-table-header-row").after($thisyear);
}

function Hide_HIT_DB(pending, PEday, PEweek){
	var tbody    = $("#approved_hits_earnings_amount").parent().parent().addClass("tbody");
	var $css = '<style type="text/css">\n';
	if (pending){
		$css += ".tbody > .odd:nth-child(8), .even:nth-child(8) {display: none;}\n";
	}
	if (PEday){
		$css += ".tbody > .odd:nth-child(9), .even:nth-child(9) {display: none;}\n";
	}
	if (PEweek){
		$css += ".tbody > .odd:nth-child(10), .even:nth-child(10) {display: none;}\n";
	}
	$("head").append($css);
}

function initialize() {
	Object.assign(String.prototype, {
		number () {
			return Number(this.replace(/[^0-9.]/g, ``));
		}
	});

	const rows = document.getElementById(`dashboard-hits-overview`).getElementsByClassName(`row`);

	window.dashboard = {
		hits_overview: {
			approved: rows[0].getElementsByClassName(`text-xs-right`)[0].textContent.number(),
			pending: rows[2].getElementsByClassName(`text-xs-right`)[0].textContent.number(),
			rejected: rows[3].getElementsByClassName(`text-xs-right`)[0].textContent.number(),
		},
		daily_hit_statistics_overview: {
			total: {
				submitted: 0,
				approved: 0,
				rejected: 0,
				pending: 0,
				earnings: 0,
			}
		},
		earnings_to_date: {
			bonuses: document.getElementById(`dashboard-earnings-to-date`).getElementsByClassName(`text-xs-right`)[2].textContent.number()
		}
	};

	for (const row of document.getElementsByClassName(`daily_hit_statuses`)) {
		const col = row.children;
		const date = col[0].children[0].href.match(/([0-9])+/)[0];

		window.dashboard.daily_hit_statistics_overview[date] = {};

		[`submitted`, `approved`, `rejected`, `pending`, `earnings`].forEach((currentValue, index) => {
			const value = col[index + 1].textContent.number();

			window.dashboard.daily_hit_statistics_overview[date][currentValue] = value;
			window.dashboard.daily_hit_statistics_overview.total[currentValue] += value;
		});
	}
}

function allApprovedRate() {
	const overview = dashboard.hits_overview;

	const row = document.createElement(`div`);
	row.className = `row m-b-sm`;

	const col1 = document.createElement(`div`);
	col1.className = `col-xs-7`;
	row.appendChild(col1);

	const strong = document.createElement(`strong`);
	strong.textContent = `All Approved Rate`;
	col1.appendChild(strong);

	const col2 = document.createElement(`div`);
	col2.className = `col-xs-5 text-xs-right`;
	col2.textContent = `${((overview.approved + overview.pending) / (overview.approved + overview.pending + overview.rejected) * 100).toFixed(4)}%`;
	row.appendChild(col2);

	const additional = document.getElementById(`HitsOverviewAdditionalInfo`);
	additional.parentNode.insertBefore(row, additional);
}

function allRejectedRate() {
	const overview = dashboard.hits_overview;

	const row = document.createElement(`div`);
	row.className = `row m-b-sm`;

	const col1 = document.createElement(`div`);
	col1.className = `col-xs-7`;
	row.appendChild(col1);

	const strong = document.createElement(`strong`);
	strong.textContent = `All Rejected Rate`;
	col1.appendChild(strong);

	const col2 = document.createElement(`div`);
	col2.textContent = `${(overview.approved / (overview.approved + overview.rejected + overview.pending) * 100).toFixed(4)}%`;
	col2.className = `col-xs-5 text-xs-right`;
	row.appendChild(col2);

	const additional = document.getElementById(`HitsOverviewAdditionalInfo`);
	additional.parentNode.insertBefore(row, additional);
}

function fourDigitPercents() {
	const overview = dashboard.hits_overview;

	for (const row of document.getElementById(`dashboard-hits-overview`).getElementsByClassName(`row`)) {
		if (row.textContent.indexOf(`Approval Rate`) !== -1) {
			row.getElementsByClassName(`text-xs-right`)[0].textContent = `${(overview.approved / (overview.approved + overview.rejected) * 100).toFixed(4)}%`;
		}
		if (row.textContent.indexOf(`Rejection Rate`) !== -1) {
			row.getElementsByClassName(`text-xs-right`)[0].textContent = `${(overview.rejected / (overview.approved + overview.rejected) * 100).toFixed(4)}%`;
		}
	}
}

function rejectionsBelow99() {
	const overview = dashboard.hits_overview;

	const row = document.createElement(`div`);
	row.className = `row m-b-sm`;

	const col1 = document.createElement(`div`);
	col1.className = `col-xs-7`;
	row.appendChild(col1);

	const strong = document.createElement(`strong`);
	strong.textContent = `Rejections ≤ 99%`;
	col1.appendChild(strong);

	const col2 = document.createElement(`div`);
	col2.textContent = Math.round((overview.rejected - (0.01 * (overview.approved + overview.rejected + overview.pending))) / -0.99).toLocaleString();
	col2.className = `col-xs-5 text-xs-right`;
	row.appendChild(col2);

	const additional = document.getElementById(`HitsOverviewAdditionalInfo`);
	additional.insertBefore(row, additional.lastChild);
}

function rejectionsBelow95() {
	const overview = dashboard.hits_overview;

	const row = document.createElement(`div`);
	row.className = `row m-b-sm`;

	const col1 = document.createElement(`div`);
	col1.className = `col-xs-7`;
	row.appendChild(col1);

	const strong = document.createElement(`strong`);
	strong.textContent = `Rejections ≤ 95%`;
	col1.appendChild(strong);

	const col2 = document.createElement(`div`);
	col2.textContent = Math.round((overview.rejected - (0.05 * (overview.approved + overview.rejected + overview.pending))) / -0.95).toLocaleString();
	col2.className = `col-xs-5 text-xs-right`;
	row.appendChild(col2);

	const additional = document.getElementById(`HitsOverviewAdditionalInfo`);
	additional.insertBefore(row, additional.lastChild);
}

function totalLast45Days() {
	const table = document.querySelector(`.mturk-table.hits-statuses`);

	const row = table.insertRow(1);
	row.className = `daily_hit_statuses`;

	const date = row.insertCell(0);
	date.textContent = `Total`;
	date.className = `hidden-xs-down col-sm-2 col-md-2`;

	const submitted = row.insertCell(1);
	submitted.textContent = window.dashboard.daily_hit_statistics_overview.total.submitted;
	submitted.className = `text-xs-right col-xs-3 col-sm-2 col-md-2`;

	const approved = row.insertCell(2);
	approved.textContent = window.dashboard.daily_hit_statistics_overview.total.approved;
	approved.className = `text-xs-right col-xs-3 col-sm-2 col-md-2`;

	const rejected = row.insertCell(3);
	rejected.textContent = window.dashboard.daily_hit_statistics_overview.total.rejected;
	rejected.className = `text-xs-right col-xs-3 col-sm-2 col-md-2`;

	const pending = row.insertCell(4);
	pending.textContent = window.dashboard.daily_hit_statistics_overview.total.pending;
	pending.className = `text-xs-right col-xs-3 col-sm-2 col-md-2`;

	const earnings = row.insertCell(5);
	earnings.textContent = `$${window.dashboard.daily_hit_statistics_overview.total.earnings.toLocaleString(`en-US`, { minimumFractionDigits: 2 })}`;
	earnings.className = `text-xs-right col-xs-3 col-sm-2 col-md-2`;
}

function hitStatusChanges() {
	const oldDashboard = localStorage.dashboard ? JSON.parse(localStorage.dashboard) : null;
	localStorage.dashboard = JSON.stringify(dashboard);

	for (const row of document.getElementsByClassName(`daily_hit_statuses`)) {
		const col = row.children;
		const date = col[0].children[0] ? col[0].children[0].href.match(/([0-9])+/)[0] : `total`;

		[`submitted`, `approved`, `rejected`, `pending`, `earnings`].forEach((currentValue, index) => {
			const value = col[index + 1].textContent.number();
			const oldValue = oldDashboard ? oldDashboard.daily_hit_statistics_overview[date][currentValue] : 0;

			if (value !== oldValue) {
				const change = value - oldValue;
				const changeString = change.toFixed(2).toString().replace(`.00`, ``);

				if (Math.round(change * 100) !== 0) {
					const span = document.createElement(`span`);
					span.textContent = change > 0 ? `+${changeString}` : changeString;
					span.style.float = `left`;
					span.style.fontSize = `70%`;
					col[index + 1].appendChild(span);
				}
			}
		});
	}
}

function todaysActivity() {
	const container = document.createElement(`div`);
	container.className = `row m-b-xl`;

	const col = document.createElement(`div`);
	col.className = `col-xs-12`;
	container.appendChild(col);

	const h2 = document.createElement(`h2`);
	h2.className = `m-b-md`;
	h2.textContent = `Today's Activity`;
	col.appendChild(h2);

	const row = document.createElement(`div`);
	row.className = `row`;
	col.appendChild(row);

	const col2 = document.createElement(`div`);
	col2.className = `col-xs-12`;
	row.appendChild(col2);

	const border = document.createElement(`div`);
	border.className = `border-gray-lightest p-a-sm`;
	col2.appendChild(border);

	const earningsRow = document.createElement(`div`);
	earningsRow.className = `row m-b-sm`;
	border.appendChild(earningsRow);

	const earningsText = document.createElement(`div`);
	earningsText.className = `col-xs-7 col-sm-6 col-lg-7`;
	earningsRow.appendChild(earningsText);

	const earningsStrong = document.createElement(`strong`);
	earningsStrong.textContent = `Projected Earnings`;
	earningsText.appendChild(earningsStrong);

	const earningsValue = document.createElement(`div`);
	earningsValue.className = `col-xs-5 col-sm-6 col-lg-5 text-xs-right`;
	earningsValue.textContent = localStorage.todaysearnings || `$0.00`;
	earningsRow.appendChild(earningsValue);

	const bonusesRow = document.createElement(`div`);
	bonusesRow.className = `row m-b-sm`;
	border.appendChild(bonusesRow);

	const bonusesText = document.createElement(`div`);
	bonusesText.className = `col-xs-7 col-sm-6 col-lg-7`;
	bonusesRow.appendChild(bonusesText);

	const bonusesStrong = document.createElement(`strong`);
	bonusesStrong.textContent = `Bonuses`;
	bonusesText.appendChild(bonusesStrong);

	const bonusesValue = document.createElement(`div`);
	bonusesValue.className = `col-xs-5 col-sm-6 col-lg-5 text-xs-right`;
	bonusesValue.textContent = localStorage.todaysbonuses || `$0.00`;
	bonusesRow.appendChild(bonusesValue);

	const collapse = document.createElement(`div`);
	collapse.id = `TodaysActivityAdditionalInfo`;
	collapse.className = `collapse`;
	border.appendChild(collapse);

	const hr = document.createElement(`hr`);
	hr.className = `m-b-sm m-t-0`;
	collapse.appendChild(hr);

	const hr2 = document.createElement(`hr`);
	hr2.className = `m-b-sm m-t-0`;
	border.appendChild(hr2);

	const control = document.createElement(`a`);
	control.className = `collapse-more-less`;
	control.href = `#TodaysActivityAdditionalInfo`;
	control.setAttribute(`aria-controls`, `TodaysActivityAdditionalInfo`);
	control.setAttribute(`aria-expanded`, `false`);
	control.setAttribute(`data-toggle`, `collapse`);
	border.appendChild(control);

	const more = document.createElement(`span`);
	more.className = `more`;
	control.appendChild(more);

	const plus = document.createElement(`i`);
	plus.className = `fa fa-plus-circle`;
	more.appendChild(plus);

	const moreText = document.createTextNode(`\nMore\n`);
	more.appendChild(moreText);

	const less = document.createElement(`span`);
	less.className = `less`;
	control.appendChild(less);

	const minus = document.createElement(`i`);
	minus.className = `fa fa-minus-circle`;
	less.appendChild(minus);

	const lessText = document.createTextNode(`\nLess\n`);
	less.appendChild(lessText);

	const side = document.querySelector(`.col-md-push-8`);
	side.insertBefore(container, side.firstChild);

	const today = document.querySelector(`a[href^="/status_details/"]`);

    console.log(`today b`)
	if (today.textContent === `Today`) {
        console.log(`today a`)
		const date = today.href.match(/([0-9])+/)[0];

		if (date === localStorage.WMTD_date) {
			if (!localStorage.WMTD_bonusStart) {
				localStorage.WMTD_bonusStart = window.dashboard.earnings_to_date.bonuses;
			}
		}
		else {
			if (window.dashboard.daily_hit_statistics_overview[date].approved === 0) {
				localStorage.WMTD_bonusStart = dashboard.earnings_to_date.bonuses - dashboard.daily_hit_statistics_overview[date].earnings;
			}
			else {
				localStorage.WMTD_bonusStart = dashboard.earnings_to_date.bonuses;
			}
		}

		bonusesValue.textContent = `$${(dashboard.earnings_to_date.bonuses - localStorage.WMTD_bonusStart).toLocaleString(`en-US`, { minimumFractionDigits: 2 })}`;

		const hitLog = date === localStorage.WMTD_date ? localStorage.WMTD_hitLog ? JSON.parse(localStorage.WMTD_hitLog) : {} : {};

		const get = async (url, rescan) => {
			try {
				const page = url.match(/Number=([0-9]*)/);

				earningsValue.textContent = `Calculating Page ${page ? page[1] : `1`}`;

				const response = await new Promise((resolve) => {
					GM_xmlhttpRequest({
						method: `GET`,
						url: url,
						onload: resolve
					});
				});
				const text = response.responseText;

				if (text.indexOf(`You have exceeded the maximum allowed page request rate for this website.`) !== -1) {
					return setTimeout(get, 2000, url, rescan);
				}

				if (text.indexOf(`You have no HIT activity on this day matching the selected status.`) !== -1) {
					return false;
				}

				localStorage.WMTD_lastPage = url;

				const doc = new DOMParser().parseFromString(text, `text/html`);

				const hits = doc.getElementById(`dailyActivityTable`).querySelectorAll(`tr[valign="top"]`);

				if (hits.length) {
					for (const hit of hits) {
						const td = hit.children;
						const obj = {
							req: td[0].textContent.trim(),
							tit: td[1].textContent.trim(),
							rew: td[2].textContent.trim().number(),
							sta: td[3].textContent.trim(),
							rid: td[0].getElementsByTagName(`a`)[0].href.match(/requesterId=([A-Z0-9]+)/)[1],
							hid: td[0].getElementsByTagName(`a`)[0].href.match(/hitId=([A-Z0-9]+)/)[1]
						};

						hitLog[obj.hid] = obj;
					}

					const logLength = Object.keys(hitLog).length;
					const expectedLength = (page ? page[1].number() * 25 - 25 : 0) + hits.length;

					if (!rescan && logLength !== expectedLength) {
						return get(today.href, true);
					}
					else {
						localStorage.WMTD_hitLog = JSON.stringify(hitLog);
					}

					const next = doc.querySelector(`img[src="/media/right_arrow.gif"]`);

					if (next) {
						return get(next.parentElement.href.replace(`worker`, `www`), rescan);
					}
					else {

						let projectedEarnings = 0;
						const reqLog = {};

						for (const key in hitLog) {
							if (hitLog[key].status !== `Rejected`) {
								projectedEarnings += hitLog[key].rew;
							}
							if (!reqLog[hitLog[key].rid]){
								reqLog[hitLog[key].rid] = {
									req: hitLog[key].req,
									submit: 1,
									reward: hitLog[key].rew,
									reqid: hitLog[key].rid
								};
							}
							else {
								reqLog[hitLog[key].rid].submit += 1;
								reqLog[hitLog[key].rid].reward += hitLog[key].rew;
							}
						}

						const sort = Object.keys(reqLog).sort((a, b) => reqLog[a].reward - reqLog[b].reward);

						const fragment = document.createDocumentFragment();

						for (let i = sort.length - 1; i > -1; i--) {
							const key = sort[i];
							const req = reqLog[key].req;
							const submit = reqLog[key].submit;
							const reward = `$${reqLog[key].reward.toLocaleString(`en-US`, { minimumFractionDigits: 2 })}`;

							const reqRow = document.createElement(`div`);
							reqRow.className = `row m-b-sm`;
							fragment.appendChild(reqRow);

							const requester = document.createElement(`div`);
							requester.className = `col-xs-6`;
							reqRow.appendChild(requester);

							const requesterStrong = document.createElement(`strong`);
							requesterStrong.textContent = req;
							requester.appendChild(requesterStrong);

							const submitValue = document.createElement(`div`);
							submitValue.className = `col-xs-3 text-xs-right`;
							submitValue.textContent = submit;
							reqRow.appendChild(submitValue);

							const rewardValue = document.createElement(`div`);
							rewardValue.className = `col-xs-3 text-xs-right`;
							rewardValue.textContent = reward;
							reqRow.appendChild(rewardValue);
						}

						collapse.appendChild(fragment);

						earningsValue.textContent = `$${projectedEarnings.toLocaleString(`en-US`, { minimumFractionDigits: 2 })}`;
					}
				}
			}
			catch (error) {
				console.error(error);
			}
		};

		get(date === localStorage.WMTD_date ? localStorage.WMTD_lastPage ? localStorage.WMTD_lastPage : today.href : today.href, false);

		localStorage.WMTD_date = date;
	}
	else {
		earningsValue.textContent = `N/A`;
		bonusesValue.textContent = `N/A`;
	}
}