Greasy Fork

MTurk Wage Reporter

Tracks a best-estimate hourly wage on active HITs being worked.

当前为 2014-07-15 提交的版本,查看 最新版本

// ==UserScript==
// @name				MTurk Wage Reporter
// @namespace			        localhost
// @description			        Tracks a best-estimate hourly wage on active HITs being worked.
// @include				https://www.mturk.com/mturk/accept?*
// @include				https://www.mturk.com/mturk/previewandaccept?*
// @include				https://www.mturk.com/mturk/dashboard*
// @include				https://www.mturk.com/mturk/submit*
// @version				0.3b
// @grant				GM_setValue
// @grant				GM_getValue
// @require				http://code.jquery.com/jquery-2.1.1.js
// @downloadURL
// @updateURL
// @author				DeliriumTremens 2014
// ==/UserScript==

//
// 2014-07-10	0.1b	Beginning development.  Creating timer and tab tracker, as well as initial IndexedDB for storage of data.
//

// ------------------------------------------------------------------------------------------------------------------------------------------------

//	First, create indexedDB variables. 
// Parts borrowed from HITdb
var indexedDB = window.indexedDB || window.webkidIndexedDB || window.mozIndexedDB;

var WageStorage = {};

window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.mozIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.mozIDBKeyRange;

WageStorage.IDBTransactionModes = { "READ_ONLY": "readonly", "READ_WRITE": "readwrite", "VERSION_CHANGE": "versionchange" };

var idbKeyRange = window.IDBKeyRange;

WageStorage.indexedDB = {};
WageStorage.indexedDB.db = null;

// Global catch for indexedDB errors
WageStorage.indexedDB.onerror = function(e) {
	console.log(e);
}

// Check if database exists.  If no database, create one.  
// Parts borrowed from HITdb.
var dbExists = true;
var v = 5;

WageStorage.indexedDB.create = function () {
	var request = indexedDB.open("WageDB", v);
	
	request.onupgradeneeded = function (e) {
		WageStorage.indexedDB.db = e.target.result;
		
		var db = WageStorage.indexedDB.db;
		var newDB = false;
		
		if(!db.objectStoreNames.contains("Wage")) {
			var store = db.createObjectStore("Wage", { keyPath: "hitId" });
			
			store.createIndex("date", "date", {unique: false});
			store.createIndex("reqName", "reqName", {unique: false});
			store.createIndex("reqId", "reqId", {unique: false});
			store.createIndex("reward", "reward", {unique: false});
			store.createIndex("start", "start", {unique: false});
			store.createIndex("stop", "stop", {unique: false});
			
			newDB = true;	
		}	
	db.close();
	}
	request.onsuccess = function(e) {
		WageStorage.indexedDB.db = e.target.result;
		var db = WageStorage.indexedDB.db;
		db.close();
	}
	request.onerror = WageStorage.indexedDB.onerror;
}

// Function for adding HIT data into database
WageStorage.indexedDB.addhit = function () {
	var request = indexedDB.open("WageDB", v);
	
	request.onsuccess = function (e) {
		WageStorage.indexedDB.db = e.target.result;
		
		var db = WageStorage.indexedDB.db;
		var newDB = false;
		
		if(!db.objectStoreNames.contains("Wage")) {
			db.close();
		}
		else {
			var trans = db.transaction(["Wage"],WageStorage.IDBTransactionModes.READ_WRITE);
			var store = trans.objectStore("Wage");

			var request;
			request = store.put({ hitId: hitId[1], date: date, reqName: reqName, reqId: reqId[1], reward: reward, start: wageStart, stop: wageEnd });
		}	
	db.close();
	}
	request.onerror = WageStorage.indexedDB.onerror;
}

// Function for getting current hourly wage for today
WageStorage.indexedDB.getWage = function () {
    var request = indexedDB.open("WageDB", v);
    
	request.onsuccess = function (e) {
        WageStorage.indexedDB.db = e.target.result;
        
        var db = WageStorage.indexedDB.db
        var transaction = db.transaction('Wage','readonly');
        var store = transaction.objectStore('Wage');
        var index = store.index('date');
        var range = IDBKeyRange.only(date);
        
        var results = [];
        var tmp_results = {};
        
        index.openCursor(range).onsuccess = function(event) {
            var cursor = event.target.result;
                if (cursor) {
                    var hit = cursor.value;
                    if (tmp_results[hit.hitId] === undefined) {
                        tmp_results[hit.hitId] = [];
                        tmp_results[hit.hitId][0] = hit.reward;
                        tmp_results[hit.hitId][1] = hit.start;
                        tmp_results[hit.hitId][2] = hit.stop;
                    }
                    cursor.continue();
                }
                else {
                    for (var key in tmp_results) {
                    	results.push(tmp_results[key]);
                    }
                    addTableElement(results);
                }
        }
	}
}

// Script Variables
var wageLost = false;
var wageNix = false;
var wageStart = null;
var wageEnd = null;
var reqId = document.URL.match(/requesterId=(.*?)&/i);

if (reqId) {
	GM_setValue("reqId", reqId);
	}
else {
	reqId = GM_getValue("reqId");
	}

// HIT Data
var hitId = document.URL.match(/hitId=(.*?)&/i);
var reward = parseFloat($('span[class="reward"]:eq(1)').text().replace('$',''));
var reqName = $('input[name="prevRequester"]').val();
var date = new Date();
date = date.toLocaleDateString().replace(/\//g,'-');

// Create table element for showing hourly wage.  Borrowed from Today's Projected Earnings script
var allTds, thisTd;
allTds = document.getElementsByTagName('td');

addTableElement = function (wage) {
    var currStart = 0;
    var currEnd = 0;
    var currWages = [];
    var currWage = 0;
    
    for (var i = 0; i < wage.length; i++) {
        currStart = ((wage[i][1] > currStart) ? wage[i][1] : currStart);
        currEnd = ((wage[i][2] > currEnd) ? wage[i][2] : currEnd);
        currWages.push(((((currEnd - currStart) / 1000) / 3600) * 10000) * wage[i][0]);
    }
    
    for (var i = 0; i < currWages.length; i++) {
        currWage += currWages[i];
    	console.log(currWage);
    }
    
    currWage = parseFloat(currWage/currWages.length).toFixed(2);
    console.log(currWage);
    
    for (var i = 0; i < allTds.length; i++)
	{
    	    thisTd = allTds[i];
        	if ( thisTd.innerHTML.match(/Total Earnings/) && thisTd.className.match(/metrics\-table\-first\-value/) )
        	{
            	    var row = document.createElement('tr');
                	row.className = "even";
 
                	var hourlyWageTitle = document.createElement('p');
                	hourlyWageTitle.innerHTML = "Today's Hourly Wage";
 
                	var cellLeft = document.createElement('td');
                	cellLeft.className = "metrics-table-first-value";
                	cellLeft.appendChild(hourlyWageTitle);
                	row.appendChild(cellLeft);
                       
                	var cellRight = document.createElement('td');
                	cellRight.innerHTML = "$" + currWage + "/hr";
                	row.appendChild(cellRight);
                       
                	thisTd.parentNode.parentNode.insertBefore(row,thisTd.parentNode.nextSibling);
        	}
	}
}

// Timestamp when the HIT is accepted
$(window).ready( function() {
    if (document.URL === "https://www.mturk.com/mturk/dashboard" ) {} // Don't record anything on dashboard, instead add appropriate element to tables
	else {
		wageStart = new Date().getTime();
		console.log("Wage Starting!");
	}
});

// Detect if 'Return HIT' button has been clicked to record timer as zero-earnings. 
// Timestamp when button was clicked to end time spent.
$('a[href*="/mturk/return?"]').on('click', function() {
	wageLost = true;
	wageEnd = new Date().getTime();
});

$('img[name="/submit"]').on('click', function() {
	wageLost = false;
});

// Create database if not created yet
WageStorage.indexedDB.create();
WageStorage.indexedDB.getWage();

// Detect the page unloading and react accordingly.  
// If return button was clicked, record zero wage earnings, otherwise record earnings.
// Timestamp if submitted to end time spent.
$(window).on('beforeunload', function() {
	if (wageLost) {
		// ***** DO STUFF WHEN RETURN CLICKED *****
		reward = 0;
		WageStorage.indexedDB.addhit();
	}
	else {
		// ***** DO STUFF WHEN SUBMITTED *****
		wageEnd = new Date().getTime();
		WageStorage.indexedDB.addhit();
	}
});