Mturk Hourly

Record time spent working on HITs. Forked from [MTurk Worker] Dashboard Enhancer v2.0.3 by @Kadauchi.

当前为 2018-01-14 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Mturk Hourly
// @namespace    https://greasyfork.org/users/11205
// @version      2.1.2
// @description  Record time spent working on HITs.  Forked from [MTurk Worker] Dashboard Enhancer v2.0.3 by @Kadauchi.
// @author       Kerek
// @include      https://worker.mturk.com/dashboard*
// @include https://worker.mturk.com/projects/*/tasks/*assignment_id=*
// @include https://worker.mturk.com/status_details/*
//@grant GM_setClipboard
// ==/UserScript==

const dashboard = new Object();

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

(function () {

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

    Object.assign(Number.prototype, {
        toNumberDE () {
            return this;
        }
    });

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

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

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

        dashboard.daily_hit_statistics_overview[date] = new Object();

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

            dashboard.daily_hit_statistics_overview[date][currentValue] = value;
            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();
    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 = 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 = 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 = 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 = 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 = `$${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]{4}-[0-9]{2}-[0-9]{2}/)[0] : `total`;

        [`submitted`, `approved`, `rejected`, `pending`, `earnings`].forEach((currentValue, index) => {
            const value = col[index + 1].textContent.toNumberDE();
            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 hourlyRow = document.createElement(`div`);
    hourlyRow.className = `row m-b-sm`;
    border.appendChild(hourlyRow);

    const hourlyText = document.createElement(`div`);
    hourlyText.className = `col-xs-6 col-sm-6 col-lg-6`;
    hourlyRow.appendChild(hourlyText);

    const hourlyStrong = document.createElement(`strong`);
    hourlyStrong.textContent = `Total Hourly`;
    hourlyText.appendChild(hourlyStrong);

    const hourlyTime = document.createElement(`div`);
    hourlyTime.className = `col-xs-3 col-sm-3 col-lg-3 text-xs-right`;
    hourlyTime.textContent = `00:00:00`;
    hourlyRow.appendChild(hourlyTime);

    const hourlyValue = document.createElement(`div`);
    hourlyValue.className = `col-xs-3 col-sm-3 col-lg-3 text-xs-right`;
    hourlyValue.textContent = `$0.00`;
    hourlyRow.appendChild(hourlyValue);


    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/"]`);

    if (today.textContent === `Today`) {
        const date = today.href.match(/[0-9]{4}-[0-9]{2}-[0-9]{2}/)[0];

        if (date === localStorage.WMTD_date) {
            if (!localStorage.WMTD_bonusStart) {
                localStorage.WMTD_bonusStart = dashboard.earnings_to_date.bonuses;
            }
        }
        else {
            if (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 })}`;

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

        async function get(page, rescan) {
            try {
                page = Number.isInteger(page) ? page : 1;

                earningsValue.textContent = `Calculating Page ${page}`;

                const fetchURL = new URL(`https://worker.mturk.com/status_details/${date}`);
                fetchURL.searchParams.append(`page_number`, page);
                fetchURL.searchParams.append(`format`, `json`);

                const response = await fetch(fetchURL, {
                    credentials: `include`
                });

                if (response.status === 429) {
                    return setTimeout(get, 2000, url, rescan);
                }

                const json = await response.json();

                for (const hit of json.results) {
                    hitLog[hit.hit_id] = hit;
                }

                const logLength = Object.keys(hitLog).length;
                const expectedLength = page.toNumberDE() * 20 - 20 + json.num_results;

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

                localStorage.WMTD_lastPage = page;

                if (json.results.length === 20) {
                    return get(++ page, rescan);
                }
                else if (logLength !== json.total_num_results) {
                    hitLog = new Object();
                    return get(1, true);
                }
                else {
                    let projectedEarnings = 0;
                    const reqLog = {};
                        const hourlyLog = {};

                    for (const key in hitLog) {
                        const hit = hitLog[key];

                        if (hit.status !== `Rejected`) {
                            projectedEarnings += hit.reward.amount_in_dollars;
                        }
                        if (!reqLog[hit.requester_id]){
                            reqLog[hit.requester_id] = {
                                requester_id: hit.requester_id,
                                requester_name: hit.requester_name,
                                reward: hit.reward.amount_in_dollars,
                                submitted: 1,
                            };
                        }
                        else {
                            reqLog[hit.requester_id].submitted += 1;
                            reqLog[hit.requester_id].reward += hit.reward.amount_in_dollars;
                        }
                        if (!hourlyLog[hitLog[key].requester_id]){
                                var time_data = localStorage.getItem('time_data.' + hitLog[key].hit_id.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){
                                        hourlyLog[hitLog[key].requester_id] = {
                                            req : hitLog[key].requester_name,
                                            intervals :[[last_start,last_stop]],
                                            totalReward : parseFloat(time_data.split("$#$")[2]),
                                        };
                                    }
                                }
                            }
                            else{
                                var time_data = localStorage.getItem('time_data.' + hitLog[key].hit_id.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){
                                        hourlyLog[hitLog[key].requester_id].intervals.push([last_start,last_stop]);
                                    }
                                    hourlyLog[hitLog[key].requester_id].totalReward += parseFloat(time_data.split("$#$")[2]);
                                }
                            }


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

                    const fragment = document.createDocumentFragment();

                    var total_intervals = [];
                        var total_recorded_earnings = 0;
                        for (var j = sort.length-1; j > -1; j--){
                            var dkey = sort[j];
                            var d_req = reqLog[dkey].requester_name;
                            var d_submitted = reqLog[dkey].submitted;
                            var d_reward = Number(reqLog[dkey].reward).toFixed(2);
                            var d_hourly = "N/A";
                            if (d_req !== "Bonuses" && hourlyLog[reqLog[dkey].requester_id]){
                                var intervals = hourlyLog[reqLog[dkey].requester_id].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,10*60*1000)));
                                total_intervals = total_intervals.concat(d_intervals);
                                total_recorded_earnings += hourlyLog[reqLog[dkey].requester_id].totalReward;
                                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 = "$" + (hourlyLog[reqLog[dkey].requester_id].totalReward / d_time).toFixed(2);
                            }
                            reqLog[dkey].hourly = d_hourly;
                        }
                        total_intervals = mergeIntervals(total_intervals);
                        var total_time = 0;
                        for (i=0;i<total_intervals.length; i++){
                            var s = new Date(parseInt(total_intervals[i][0]));
                            var f = new Date(parseInt(total_intervals[i][1]));
                            //console.log(i, s.toLocaleTimeString(),f.toLocaleTimeString());
                            total_time += (total_intervals[i][1] - total_intervals[i][0])/(1000*60*60);
                        }

                        var total_hourly = '$' + (total_recorded_earnings/total_time).toFixed(2);
                        var hour = Math.floor(total_time);
                        var min = Math.floor((total_time - hour)*60);
                        var sec = Math.floor((total_time - hour - min/60)*3600);
                        var time_display = (hour>0?pad(hour,2) + ":":"") + pad(min,2) + ":" + pad(sec,2);

                        hourlyValue.textContent = total_hourly;
                        hourlyTime.textContent = time_display;

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


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

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

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

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

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

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

                    collapse.appendChild(fragment);

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

        get(date === localStorage.WMTD_date ? localStorage.WMTD_lastPage ? localStorage.WMTD_lastPage.toNumberDE() : 1 : 1, false);
        localStorage.WMTD_date = date;
    }
    else {
        earningsValue.textContent = `N/A`;
        bonusesValue.textContent = `N/A`;
    }
})();
}
else if (location.href.indexOf('worker.mturk.com/status_details') > -1){
	setTimeout(function(){
$('span.reward-column:visible:eq(0)').before('<span class="hourly-column text-xs-right column-header p-x-sm" data-reactid=".2.$header.$2">Hourly</span>');
    $('li.table-row').each(function(){
        var hitId = $(this).find('a[href*="contact_requester"]:eq(0)').attr('href').split('hit_id=')[1].split('&')[0];
                        var feedback = {opened:"N/A",submitted:"N/A", time:"N/A", hourly:"N/A"};

                        var time_data = localStorage.getItem('time_data.' + hitId);
                        if (time_data){
                    feedback = create_feedback(time_data);

                }
$(this).find('.reward-column:visible').before('<span class="p-x-sm column hourly-column text-xs-right"><span class="hourlyCopy" title="Opened: ' + feedback.opened +'&#013;Submitted: ' + feedback.submitted +'&#013;Time: ' + feedback.time +'&#013;Hourly: ' + feedback.hourly +'">' + feedback.hourly+ '</span></span>');


    });

    $('.hourlyCopy').click(function(evt){
        evt.preventDefault();
        //GM_setClipboard($(this).attr('title'));

        GM_setClipboard('Time:' + $(this).attr('title').split('Time:')[1]);
    });
	},500);
}
else if (location.href.indexOf('worker.mturk.com') > -1){
    var hit_returned = false;
    if(typeof(Storage)!=="undefined")
    {
        $('button:contains("Return")').click(function(){
            hit_returned = true;
        });
        store_data('openWorker');
        window.addEventListener('beforeunload', function(){
            store_data('closeWorker');
        });
    }
}





function create_feedback(time_data)
{

    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));
    var f = {opened:last_start.toLocaleTimeString(), submitted:last_finish.toLocaleTimeString(), time: ((h > 0 ? (pad(h,2) + ":"):"") + pad(m,2) + ":" + pad(s,2)), hourly: '$' + (reward/((last_finish-last_start)/(60*60*1000))).toFixed(2)};
    console.log(f);
    return f;
 //   return "Opened: " + last_start.toLocaleTimeString() + "<br>Submitted: " + last_finish.toLocaleTimeString()+ "<br>Time: " + (h > 0 ? (pad(h,2) + ":"):"") + pad(m,2) + ":" + pad(s,2) + "<br>Hourly: $" + (reward/((last_finish-last_start)/(60*60*1000))).toFixed(2) ;
}

function store_data(action_type)
{
        if (!hit_returned){
			setTimeout(function(){
            var now_in_milliseconds = new Date().getTime();
            var hitReview_hitId = window.location.href.split('tasks/')[1].split('?')[0];
            console.log(action_type);

            var $data_holder = $('a:contains("HIT Details"):eq(0)').parent().attr('data-react-props');
            var requester_name = JSON.parse($data_holder).modalOptions.requesterName;
            var hit_title = JSON.parse($data_holder).modalOptions.projectTitle;
            var hit_reward = JSON.parse($data_holder).modalOptions.monetaryReward.amountInDollars;
            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 == "openWorker"){
                open_list += "?" + now_in_milliseconds;
            }
            else if (action_type == "closeWorker"){
                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);
			},350);

        }
}

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;
}

function Remove_Old_Data(){
    var today = new Date();
    var date = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate();
    if (localStorage.getItem('mturkHourlyRemovalDate') != date){
        console.log('mturk hourly data older than 45 days has been cleared');

        //thanks to @ChrisTurk for the old key removal code:
        Object.keys(localStorage)
            .forEach(function(key){
            if (/^time_data\./.test(key)) {
                console.log(localStorage[key]);
                var stored = localStorage[key].split(/\?/).pop(); // grabs last timestamp from the stack
                // days * hours * min * sec * 1000 [millisec 'cause of the way its stored]
                if (($.now()-stored) > 14*24*60*60*1000) {
                    // console.log('older than 14 days');
                    localStorage.removeItem(key); //uncomment this line to delete keys
                } else {
                    //  console.log('fresh memes'); //less than 1 day old, don't delete it.
                }
            }
        });
        localStorage.setItem('mturkHourlyRemovalDate',date);
    }
}