您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Record time spent working on HITs.
当前为
// ==UserScript== // @name Mturk Hourly // @author @Kerek // @description Record time spent working on HITs. // @match https://www.mturk.com/mturk/accept* // @match https://www.mturk.com/mturk/preview* // @match https://www.mturk.com/mturk/continue* // @match https://www.mturk.com/mturk/submit // @match https://www.mturk.com/mturk/return* // @match https://www.mturk.com/mturk/statusdetail* // @match https://www.mturk.com/mturk/dashboard // @require http://code.jquery.com/jquery-latest.min.js // @version 1.0 // @grant none // @namespace https://greasyfork.org/users/11205 // ==/UserScript== if (window.location.href == "https://www.mturk.com/mturk/dashboard" && $("#total_earnings_amount").length){ Todays_Projected_Earnings(); } else{ var hit_returned = false; if(typeof(Storage)!=="undefined") { $('img[src="/images/return_hit.gif"]').parent().click(function(){ hit_returned = true; }); store_data('open'); window.addEventListener('beforeunload', function(){store_data('close');}); var $requesters = $('td[class="statusdetailRequesterColumnValue"]'); if ($requesters.length > 0) { $requesters.each(function(){ var hitId = $(this).find('a[href^="/mturk/contact?"]').attr('href').match(/[A-Z0-9]{30}/); var $feedback_value = $(this).parent().find('td[class="statusdetailStatusColumnValue"]').next(); var feedback_str = create_feedback_str(hitId); var status_value = $feedback_value.html() + feedback_str; $feedback_value.html(status_value); }); } } } function Todays_Projected_Earnings(){ var TPEhitLOG = {}; var TPEdetailsLOG = {}; var TPEhourlyLOG = {}; 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 <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><th>Hourly</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"; } 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]"; var x_sorted = Object.keys(TPEdetailsLOG).sort(function(a,b){return TPEdetailsLOG[a].reward - TPEdetailsLOG[b].reward;}); for (var j = x_sorted.length-1; j > -1; j--){ var xkey = x_sorted[j]; var x_req = TPEdetailsLOG[xkey].req; var x_reqid = TPEdetailsLOG[xkey].reqid; var x_submitted = TPEdetailsLOG[xkey].submit; var x_reward = Number(TPEdetailsLOG[xkey].reward).toFixed(2); if (x_req === "Bonuses"){ if (x_reward !== "0.00"){ exportcode += "[tr][td]"+x_req+"[/td][td]"+x_submitted+"[/td][td]$"+x_reward+"[/td][/tr]\n"; } } else { 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"; } } exportcode += "[/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 = {}; TPEhourlyLOG = {}; 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)").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 (!TPEhourlyLOG[TPEhitLOG[key].reqid]){ var time_data = localStorage.getItem('time_data.' + TPEhitLOG[key].hitid.split('&')[0]); if (time_data != null){ var starts = time_data.split("$#$")[3].split('?'); var last_start = starts[starts.length-1]; var stops = time_data.split("$#$")[4].split('?'); var last_stop = stops[stops.length-1]; if (last_start.length && last_stop.length){ TPEhourlyLOG[TPEhitLOG[key].reqid] = { req : TPEhitLOG[key].req, intervals :[[last_start,last_stop]], totalReward : parseFloat(time_data.split("$#$")[2]), }; } } } else{ var time_data = localStorage.getItem('time_data.' + TPEhitLOG[key].hitid.split('&')[0]); if (time_data != null){ var starts = time_data.split("$#$")[3].split('?'); var last_start = starts[starts.length-1]; var stops = time_data.split("$#$")[4].split('?'); var last_stop = stops[stops.length-1]; if (last_start.length && last_stop.length){ //console.log(TPEhourlyLOG[TPEhitLOG[key].reqid].intervals); TPEhourlyLOG[TPEhitLOG[key].reqid].intervals.push([last_start,last_stop]); } // console.log(TPEhourlyLOG[TPEhitLOG[key].reqid].intervals); TPEhourlyLOG[TPEhitLOG[key].reqid].totalReward += parseFloat(time_data.split("$#$")[2]); } } } 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); var d_hourly = "N/A"; if (d_req !== "Bonuses" && TPEhourlyLOG[TPEdetailsLOG[dkey].reqid]){ var intervals = TPEhourlyLOG[TPEdetailsLOG[dkey].reqid].intervals; var d_intervals_sum = 0; for (i=0;i<intervals.length;i++){ d_intervals_sum += (intervals[i][1]-intervals[i][0]); } var d_intervals_avg = d_intervals_sum / intervals.length; var d_intervals = mergeIntervals(intervals); d_intervals = combineIntervals(intervals,Math.max(2*60*1000,Math.min(10*d_intervals_avg,15*60*1000))); console.log(d_req, "padding", Math.min(10*d_intervals_avg,15*60*1000)); var d_time = 0; for (i=0;i<d_intervals.length; i++){ var s = new Date(parseInt(d_intervals[i][0])); var f = new Date(parseInt(d_intervals[i][1])); console.log(d_req, i, s.toLocaleTimeString(),f.toLocaleTimeString()); d_time += (d_intervals[i][1] - d_intervals[i][0])/(1000*60*60); } d_hourly = "$" + (TPEhourlyLOG[TPEdetailsLOG[dkey].reqid].totalReward / d_time).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><td><span class="reward">'+d_hourly+'</span></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><span class="reward">'+d_hourly+'</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)); $('#today_total').text("$"+(Number($('#bonus').text().replace('$','')) +Number($('#TPE_div span.reward').text().replace('$',''))).toFixed(2)); document.title = $('#today_total').text(); 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"); $('#today_total').text("$"+(Number($('#bonus').text().replace('$','')) +Number($('#TPE_div span.reward').text().replace('$',''))).toFixed(2)); } 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 create_feedback_str(hitId) { var time_str = ''; var time_data = localStorage.getItem('time_data.' + hitId); if (time_data === null) { return time_str; } var last_start = time_data.split("$#$")[3].split('?'); last_start = new Date(parseInt(last_start[last_start.length - 1])); var last_finish = time_data.split("$#$")[4].split('?'); last_finish = new Date(parseInt(last_finish[last_finish.length - 1])); console.log(time_data, last_start, last_finish, time_data.split("$#$")[3].split('?'), time_data.split("$#$")[4].split('?')); var reward = time_data.split("$#$")[2]; var time_spent = last_finish - last_start; var h = Math.floor(time_spent/(1000*60*60)); var m = Math.floor((time_spent - h*1000*60*60)/(1000*60)); var s = Math.floor((time_spent - h*1000*60*60 - m*1000*60)/(1000)); // return time_data; // return time_data.split("$#$")[0] + " - " + time_data.split("$#$")[1] + " - " + time_data.split("$#$")[2] + "<br>" +last_start*1000 + "<br>" + last_finish*1000; return "Opened: " + last_start.toLocaleTimeString() + "<br>Submitted: " + last_finish.toLocaleTimeString()+ "<br>Time: " + (h.length?pad(h,2) + ":":"") + pad(m,2) + ":" + pad(s,2) + "<br>Hourly: $" + (reward/((last_finish-last_start)/(60*60*1000))).toFixed(2) ; // return time_data.split("$#$")[0] + " - " + time_data.split("$#$")[1] + " - " + time_data.split("$#$")[2] + "<br>" + (new Date(last_start)).toTimeString() + "<br>" + (new Date(last_finish)).toTimeString(); } function store_data(action_type) { var $isAccepted = $('input[type="hidden"][name="isAccepted"][value="true"]'); if ($isAccepted.length > 0 && !hit_returned) { var hitReview_hitId = $('form[name="hitForm"][action="/mturk/hitReview"] input[name="hitId"]').val(); console.log(hitReview_hitId); var hit_reward = $('form[name="hitForm"][action="/mturk/submit"] input[name="prevReward"]').val().replace('USD',''); console.log(hit_reward); var requester_name = $('td.capsule_field_title:contains("Requester:"):eq(0)').next().text().trim(); var hit_title = $('table:contains("Requester:"):eq(0) table:eq(0)').text().trim(); var now_in_milliseconds = new Date().getTime(); var open_list = ""; var close_list = ""; var stored_copy = localStorage.getItem('time_data.' + hitReview_hitId); if (stored_copy !== null){ open_list = stored_copy.split('$#$')[3]; close_list = stored_copy.split('$#$')[4]; } if (action_type == "open"){ open_list += "?" + now_in_milliseconds; } else{ close_list += "?" + now_in_milliseconds; } var autoapprove_data = requester_name + "$#$" + hit_title + "$#$"+ hit_reward +"$#$" + open_list + "$#$" + close_list; console.log(autoapprove_data); localStorage.setItem('time_data.' + hitReview_hitId, autoapprove_data); } } function mergeIntervals(intervals) { // test if there are at least 2 intervals if(intervals.length <= 1) return intervals; var stack = []; var top = null; // sort the intervals based on their start values intervals = intervals.sort(function (startValue, endValue) { if (startValue[0] > endValue[0]) { return 1; } if (startValue[0] < endValue[0]) { return -1; } return 0; }); // push the 1st interval into the stack stack.push(intervals[0]); // start from the next interval and merge if needed for (var i = 1; i < intervals.length; i++) { // get the top element top = stack[stack.length - 1]; // if the current interval doesn't overlap with the // stack top element, push it to the stack if (top[1] < intervals[i][0]) { stack.push(intervals[i]); } // otherwise update the end value of the top element // if end of current interval is higher else if (top[1] < intervals[i][1]) { top[1] = intervals[i][1]; stack.pop(); stack.push(top); } } return stack; } function combineIntervals(intervals, padding) { // test if there are at least 2 intervals if(intervals.length <= 1) return intervals; var stack = []; var top = null; // push the 1st interval into the stack stack.push(intervals[0]); // start from the next interval and merge if needed for (var i = 1; i < intervals.length; i++) { // get the top element top = stack[stack.length - 1]; // if the current interval doesn't overlap with the // stack top element, push it to the stack if ((intervals[i][0]-top[1]) > padding) { // console.log("hi",(intervals[i][0]-top[1]) + padding); stack.push(intervals[i]); } // otherwise update the end value of the top element // if end of current interval is higher else if (top[1] < intervals[i][1]) { top[1] = intervals[i][1]; stack.pop(); stack.push(top); } } //console.log("stack",stack); return stack; } function pad(n, width, z) { z = z || '0'; n = n + ''; return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; }