Last active
May 28, 2021 23:20
-
-
Save sweeneyapps/7b6b4ff194ce47e5e672964ec0d70068 to your computer and use it in GitHub Desktop.
RF Job History TamperMonkey script ( v.56 )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Rainforest Jobs | |
// @namespace http://tampermonkey.net/ | |
// @version 56 | |
// @description collect info from job page | |
// @author Paul Sweeney Jr. (Code cleaner), ixamy (original idea) | |
// @modifier JrRandy | |
// @credits taruga, marco.aguiaram, russ, uangonline2016, mariusb | |
// @match https://portal.rainforestqa.com/* | |
// @run-at document-end | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
var EasyCopy = true; //adjust this variables to control the easy copy/paste stats under the tables (true/false) | |
var isCF = true; //adjust this variable for CrowdFlower of non-crowdflower (true/false) | |
var CFinDollar = true; //adjust this variable to show summary table in $ instead of C for CF | |
var runCssOnce = true; | |
var rejectionButton; | |
var reviewButton; | |
var rfLinks = document.querySelectorAll("a.primary"); | |
if (rfLinks) { | |
for (var i = 0; i < rfLinks.length; i++) { | |
var link = rfLinks[i]; | |
if (link.innerHTML === "History" && !link.href.includes("&page_size=100")) { | |
link.href = link.href + "&page_size=100"; | |
} | |
if (link.innerHTML.includes("Rejected")) { | |
rejectionButton = link; | |
} | |
if (link.innerHTML.includes("Reviews")) { | |
reviewButton = link; | |
} | |
} | |
} | |
var curURL = window.location.href; | |
if (!curURL.includes("&page_size=100")) { | |
if (curURL.includes("/profile") && !curURL.includes("/edit") || curURL.includes('/tester')) { | |
var earned, jobs, bugs, rejection, score; | |
var allStatsLabel = document.querySelectorAll('.tester-stat-label'); | |
for( var all in allStatsLabel ) { | |
if ( allStatsLabel[all].innerText && allStatsLabel[all].innerText.includes("EARNED") ) { | |
earned = allStatsLabel[all].nextElementSibling; | |
} | |
if ( allStatsLabel[all].innerText && allStatsLabel[all].innerText.includes("JOBS") ) { | |
jobs = allStatsLabel[all].nextElementSibling; | |
} | |
if ( allStatsLabel[all].innerText && allStatsLabel[all].innerText.includes("BUGS") ) { | |
bugs = allStatsLabel[all].nextElementSibling.nextElementSibling; | |
} | |
if ( allStatsLabel[all].innerText && allStatsLabel[all].innerText.includes("SCORE") ) { | |
score = allStatsLabel[all].nextElementSibling.innerText; | |
reviewButton.innerHTML = "Reviews " + "(" + score + ")"; | |
} | |
if ( allStatsLabel[all].innerText && allStatsLabel[all].innerText.includes("REJECTIONS") ) { | |
rejection = allStatsLabel[all].nextElementSibling.innerText; | |
rejectionButton.innerHTML = "Rejected Training Jobs " + "(" + rejection + ")"; | |
} | |
} | |
// debugging for developers only | |
console.log("EARNED: " + earned.innerHTML); | |
console.log("JOBS: " + jobs.innerHTML); | |
console.log("BUGS: " + bugs.innerHTML); | |
console.log("REJECTION: " + rejection); | |
console.log("SCORE: " + score); | |
if (isCF) earned.innerHTML = "$" + (Number(earned.innerHTML.replace("c", "")) / 100); | |
var percent = ((parseInt(bugs.innerHTML) / parseInt(jobs.innerHTML)) * 100).toFixed(2); | |
bugs.innerHTML = bugs.innerHTML + " | " + percent + "%"; | |
} | |
return; // skip the script below | |
} | |
var rfTable = document.getElementsByTagName('table')[1]; | |
var divForTable = document.createElement('div'); | |
$(divForTable).insertBefore(rfTable); | |
var payFilterSelection = document.getElementById('filter_form'); | |
var page100 = document.createElement('input'); | |
page100.type = "hidden"; | |
page100.name = "page_size"; | |
page100.value = "100"; | |
payFilterSelection.appendChild(page100); | |
/** Running the Script **/ | |
var dates = {}; | |
getDates(); // setup dates | |
var dropdownDate = generateDropDown(dates); | |
$(dropdownDate).insertBefore(divForTable); | |
var firstDate = Object.keys(dates)[0]; | |
createTable({date: firstDate, text: firstDate}); | |
/** End Script **/ | |
/** Bunch of Functions Below **/ | |
function getDates() { | |
var tempDates = {}; | |
for (var i = 1; i < rfTable.rows.length; i++) { | |
var rowDate = rfTable.rows[i].cells[1].innerHTML; | |
tempDates[rowDate] = rowDate; | |
} | |
dates = tempDates; | |
} | |
function createTable(day) { | |
var requestDate = day.date; | |
var paid = 0; | |
var pending = 0; | |
var jobCount = 0; | |
var reCurr = /\d+\.\d{1,2}|\d+/; | |
var reCF = /\d+\.0c/; | |
var CFFIXED = 2; | |
var CFCENT = ""; | |
var DOLLAR = "$"; | |
var trainingJobs = 0; | |
var STEPPAY = 0.04; | |
var timeSpent = 0; | |
var ts,a,seconds; | |
function cleanCurrency(currStr) { | |
if (reCF.test(currStr)) isCF = true; | |
var cleanCur = currStr.match(reCurr); | |
return cleanCur ? Number(cleanCur[0]) : 0; | |
} | |
function isToday(dateStr) { | |
if (dateStr === '—') return false; | |
return requestDate === dateStr; | |
} | |
function getCell(row, cell) { | |
return rfTable.rows[row].cells[cell].innerHTML; | |
} | |
for (var i = 1; i < rfTable.rows.length; i++) { | |
// paypal and payza bug fix | |
var cashouttest = /Cashout/g; | |
var broswerCol = getCell(i, 2); | |
if (cashouttest.test(broswerCol)) continue; | |
// | |
if(isToday(getCell(i, 1))) { | |
if (cleanCurrency(getCell(i,7)) === 0 && cleanCurrency(getCell(i,6)) === 0) { | |
ts = getCell(i,4); | |
if (ts !== '—') { | |
a = ts.split(':'); | |
seconds = (+a[0]) * 60 * 60 + (+a[1]) * 60 + (+a[2]); | |
timeSpent += seconds; | |
trainingJobs += 1; | |
} | |
} else { | |
paid += cleanCurrency(getCell(i,7)); | |
pending += cleanCurrency(getCell(i,6)); | |
ts = getCell(i,4); | |
if (ts !== '—') { | |
a = ts.split(':'); | |
seconds = (+a[0]) * 60 * 60 + (+a[1]) * 60 + (+a[2]); | |
jobCount += 1; | |
timeSpent += seconds; | |
} | |
} | |
} | |
} | |
if(isCF) { | |
if(CFinDollar) { | |
CFFIXED = 2; | |
CFCENT = ""; | |
DOLLAR = "$"; | |
STEPPAY = 0.04; | |
paid = paid/100; | |
pending = pending/100; | |
} else { | |
CFFIXED = 0; | |
CFCENT = "c"; | |
DOLLAR = ""; | |
STEPPAY = 4; | |
} | |
} | |
var TotalPay = Number(paid) + Number(pending); | |
var Bonus=0; | |
if (jobCount+trainingJobs >= 100) { | |
Bonus = TotalPay/5; | |
} else if (jobCount+trainingJobs >= 10) { | |
Bonus = TotalPay/10; | |
} else { | |
Bonus = 0; | |
} | |
var Steps = TotalPay/STEPPAY; | |
var avgperjob = (Number(paid) + Number(pending))/Number(jobCount); | |
var avgsteps = (Steps)/Number(jobCount); | |
function formatSeconds(seconds) { | |
var date = new Date(1970,0,1); | |
date.setSeconds(seconds); | |
return date.toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1"); | |
} | |
function formatText(txt) { | |
return DOLLAR + txt.toFixed(CFFIXED) + CFCENT; | |
} | |
/** Data Section **/ | |
var tableData = []; | |
function addTableData(heading, value) { | |
tableData.push({heading: heading, value: value}); | |
} | |
addTableData('Paid', formatText(paid)); | |
addTableData('Pending', formatText(pending)); | |
addTableData('Total', formatText(TotalPay)); | |
addTableData('Est. Bonus', formatText(Bonus)); | |
addTableData('Pay/Job', formatText(avgperjob)); | |
addTableData('Job Count', jobCount); | |
addTableData('Training', trainingJobs); | |
addTableData('Steps', Steps.toFixed(0)); | |
addTableData('Steps/Job', avgsteps.toFixed(2)); | |
addTableData('Time', formatSeconds(timeSpent)); | |
var cssData = []; | |
function addCssData(selector, rules) { | |
cssData.push({selector: selector, rules: rules}); | |
} | |
addCssData('table#info', [ | |
'border-collapse:collapse;', | |
'border-color:#ccc;', | |
'border:none;']); | |
addCssData('table#info', [ | |
'border-collapse:collapse;', | |
'border-color:#ccc;', | |
'border:none;']); | |
addCssData('table#info tr th', ['background-color:#f0f0f0;']); | |
addCssData('table#info tr th, table#info tr td', [ | |
'font-family:Arial, sans-serif;', | |
'font-size:14px;', | |
'font-weight:normal;', | |
'padding:10px 5px;', | |
'padding:10px 5px;', | |
'border-style:solid;', | |
'border-width:0px;', | |
'overflow:hidden;', | |
'word-break:normal;', | |
'border-color:#ccc;', | |
'color:#333;', | |
'text-align:center;', | |
'vertical-align:top;']); | |
addCssData('table#info tr td:nth-child(even)', ['background-color:#fff;']); | |
addCssData('table#info tr td:nth-child(odd)', ['background-color:#f9f9f9;']); | |
addCssData('span#summary > center', ['display: inline;']); | |
if (runCssOnce) { // only need to run this once | |
var style = generateCSS(cssData); | |
$(style).insertBefore(rfTable); | |
runCssOnce = false; | |
} | |
var div = document.createElement('div'); | |
var br = document.createElement('br'); | |
div.appendChild(br); | |
var table = generateTable(day, tableData); | |
table.id = "info"; | |
div.appendChild(table); | |
if (EasyCopy) { | |
var textDiv = document.createElement('div'); | |
textDiv.innerHTML = generateText(day, tableData, ["Steps/Job", "Pay/Job", "Paid", "Pending", "Total", "Est. Bonus"]); | |
div.appendChild(textDiv); | |
} | |
divForTable.innerHTML = ""; | |
divForTable.appendChild(div); | |
divForTable.innerHTML += "<hr />"; | |
} // end createTable | |
/** Generators for HTML / TEXT / CSS **/ | |
function generateText(day, data, skip) { | |
var text = day.text; | |
for (var i = 0; i < data.length; i++) { | |
if (skip.indexOf(data[i].heading) !== -1) continue; | |
text += " " + data[i].heading + ": " + data[i].value + " |"; | |
} | |
return text; | |
} | |
function generateTable(day, data) { | |
var table = document.createElement('table'); | |
var headingRow = document.createElement('tr'); | |
var valueRow = document.createElement('tr'); | |
table.appendChild(headingRow); | |
table.appendChild(valueRow); | |
for (var i = 0; i < data.length; i++) { | |
var cell = data[i]; | |
var headingCell = document.createElement('th'); | |
var valueCell = document.createElement('td'); | |
headingCell.innerHTML = cell.heading; | |
valueCell.innerHTML = cell.value; | |
headingRow.appendChild(headingCell); | |
valueRow.appendChild(valueCell); | |
} | |
return table; | |
} | |
function generateCSS(data) { | |
var style = document.createElement('style'); | |
var cssBody = ""; | |
for (var i = 0; i < data.length; i++) { | |
var selector = data[i].selector; | |
var rules = data[i].rules; | |
cssBody += selector + " { "; | |
for (var r = 0; r < rules.length; r++){ | |
var rule = rules[r]; | |
cssBody += rule; | |
} | |
cssBody += " } "; | |
} | |
style.innerText = cssBody; | |
return style; | |
} | |
function generateDropDown(data) { | |
var dropDown = document.createElement('select'); | |
for (var x in data) { | |
var option = document.createElement('option'); | |
option.setAttribute('value', data[x]); | |
option.innerHTML = data[x]; | |
dropDown.appendChild(option); | |
} | |
dropDown.onchange = function(event) { | |
var date = event.target.value; | |
createTable({date: date, text: date}); | |
}; | |
var title = document.createElement('center'); | |
title.innerHTML = "Summary for "; | |
var span = document.createElement('span'); | |
span.setAttribute("id", "summary"); | |
span.appendChild(title); | |
span.appendChild(dropDown); | |
return span; | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment