Mturk Hourly

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

目前為 2018-01-14 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 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);
    }
}