Advertisement
Guest User

Untitled

a guest
Dec 4th, 2016
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name         Rainforest Jobs
  3. // @namespace    http://tampermonkey.net/
  4. // @version      47
  5. // @description  collect info from job page
  6. // @author       Paul Sweeney Jr. (Code cleaner), ixamy (original idea)
  7. // @modifier     JrRandy
  8. // @credits      taruga, marco.aguiaram, russ, uangonline2016, mariusb
  9. // @match        https://portal.rainforestqa.com/*
  10.  
  11. // ==/UserScript==
  12.  
  13.  
  14. var script = document.createElement('script');
  15. script.src = 'https://www.gstatic.com/charts/loader.js';
  16. document.head.appendChild(script);
  17.  
  18. window.onload = function () {
  19.     'use strict';
  20.     var EasyCopy = true;  //adjust this variables to control the easy copy/paste stats under the tables (true/false)
  21.     var isCF = true;  //adjust this variable for CrowdFlower of non-crowdflower (true/false)
  22.     var CFinDollar = true; //adjust this variable to show summary table in $ instead of C for CF
  23.     var hideGraph = false;
  24.    
  25.     var Jobs = [];
  26.     var rfLinks = document.querySelectorAll("a.primary");
  27.     if (rfLinks) {
  28.         for (var i = 0; i < rfLinks.length; i++) {
  29.             var link = rfLinks[i];
  30.             if (link.innerHTML === "History" && !link.href.includes("&page_size=100")) {
  31.                 link.href = link.href + "&page_size=100";
  32.             }
  33.         }
  34.     }
  35.  
  36.     var curURL = window.location.href;
  37.     if (!curURL.includes("&page_size=100")) {
  38.         if (curURL.includes("/profile") && !curURL.includes("/edit") || curURL.includes('/tester')) {
  39.             var stats = document.querySelectorAll("span.tester-stat-number");
  40.             var earned = stats[0], jobs = stats[1], bugs = stats[2];
  41.             if (isCF) earned.innerHTML = "$" + (Number(earned.innerHTML.replace("c", "")) / 100);
  42.             var percent = ((parseInt(bugs.innerHTML) / parseInt(jobs.innerHTML)) * 100).toFixed(2);
  43.             bugs.innerHTML =  bugs.innerHTML + " | " + percent + "%";
  44.         }
  45.         return; // skip the script below
  46.     }
  47.  
  48.     var rfTable = document.getElementsByTagName('table')[1];
  49.  
  50.     /** Running the Script **/
  51.  
  52.     var yesterday = new Date(new Date().setDate(new Date().getDate()-1));
  53.     createTable({date: new Date(), text: 'Today'});
  54.     createTable({date: yesterday, text: 'Yesterday'});
  55.  
  56.     /** End Script **/
  57.  
  58.  
  59.     /** Bunch of Functions Below **/
  60.  
  61.     function createTable(day) {
  62.         var requestDate = day.date;
  63.         var paid = 0;
  64.         var pending = 0;
  65.         var jobCount = 0;
  66.         var reCurr = /\d+\.\d{1,2}|\d+/;
  67.         var reCF = /\d+\.0c/;
  68.         var CFFIXED = 2;
  69.         var CFCENT = "";
  70.         var DOLLAR = "$";
  71.         var trainingJobs = 0;
  72.         var STEPPAY = 0.04;
  73.         var timeSpent = 0;
  74.         var ts,a,seconds;
  75.  
  76.         function cleanCurrency(currStr) {
  77.             if (reCF.test(currStr)) isCF = true;
  78.             var cleanCur = currStr.match(reCurr);
  79.             return cleanCur ? Number(cleanCur[0]) : 0;
  80.         }
  81.  
  82.         function isToday(dateStr) {
  83.             if (dateStr === '—') return false;
  84.             var submitDateUTC = dateStr.replace(/ UTC/, "");
  85.             var submitDate = new Date(submitDateUTC);
  86.             return requestDate.getUTCDate() === submitDate.getDate();
  87.         }
  88.  
  89.         function getCell(row, cell) {
  90.             return rfTable.rows[row].cells[cell].innerHTML;
  91.         }
  92.  
  93.         for (var i = 1; i < rfTable.rows.length; i++) {
  94.             // job id to link
  95.             var jobIDcell = rfTable.rows[i].cells[0];
  96.             var id = jobIDcell.innerHTML;
  97.             var link = 'https://portal.rainforestqa.com/retrospective/' + id;
  98.             var hyperlink = document.createElement('a');
  99.             hyperlink.innerHTML = id;
  100.             hyperlink.setAttribute('href', link);
  101.             hyperlink.setAttribute('target', '_blank');
  102.             jobIDcell.innerHTML = "";
  103.             jobIDcell.appendChild(hyperlink);
  104.             // end job id to link
  105.  
  106.             if(isToday(getCell(i, 1) + ' 00:00:01')) {
  107.                 if (cleanCurrency(getCell(i,6)) === 0 && cleanCurrency(getCell(i,5)) === 0) {
  108.                     ts = getCell(i,4);
  109.                     if (ts !== '—') {
  110.                         a = ts.split(':');
  111.                         seconds = (+a[0]) * 60 * 60 + (+a[1]) * 60 + (+a[2]);
  112.                         timeSpent += seconds;
  113.                         trainingJobs += 1;
  114.                     }
  115.                 } else {
  116.                     paid += cleanCurrency(getCell(i,6));
  117.                     pending += cleanCurrency(getCell(i,5));
  118.                     ts = getCell(i,4);
  119.                     if (ts !== '—') {
  120.                         a = ts.split(':');
  121.                         seconds = (+a[0]) * 60 * 60 + (+a[1]) * 60 + (+a[2]);
  122.                         jobCount += 1;
  123.                         timeSpent += seconds;
  124.                     }
  125.  
  126.                 }
  127.             }
  128.         }
  129.  
  130.         if(isCF) {
  131.             if(CFinDollar) {
  132.                 CFFIXED = 2;
  133.                 CFCENT = "";   
  134.                 DOLLAR = "$";
  135.                 STEPPAY = .04;
  136.                 paid = paid/100;
  137.                 pending = pending/100;
  138.             } else {
  139.                 CFFIXED = 0;
  140.                 CFCENT = "c";  
  141.                 DOLLAR = "";
  142.                 STEPPAY = 4;
  143.             }
  144.         }
  145.         var TotalPay = Number(paid) + Number(pending);
  146.         var Bonus=0;
  147.         if (day.text === 'Today') {
  148.             if (jobCount+trainingJobs >= 100) {
  149.                 Bonus = TotalPay/5;
  150.             } else if (jobCount+trainingJobs >= 10) {
  151.                 Bonus = TotalPay/10;
  152.             } else {
  153.                 Bonus = 0;
  154.             }
  155.         } else {
  156.             if (jobCount+trainingJobs >= 100) {
  157.                 Bonus = TotalPay/120*20;
  158.             } else if (jobCount+trainingJobs >= 10) {
  159.                 Bonus = TotalPay/110*10;
  160.             } else {
  161.                 Bonus = 0;
  162.             }
  163.         }
  164.         var Steps = 0;
  165.         if (day.text === 'Today') {
  166.             Steps = TotalPay/STEPPAY;
  167.         } else {
  168.             Steps = (TotalPay-Bonus)/STEPPAY;
  169.         }
  170.         var avgperjob = (Number(paid) + Number(pending))/Number(jobCount);
  171.         var avgsteps = (Steps)/Number(jobCount);
  172.  
  173.  
  174.         function formatSeconds(seconds) {
  175.             var date = new Date(1970,0,1);
  176.             date.setSeconds(seconds);
  177.             return date.toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1");
  178.         }
  179.  
  180.         function formatText(txt) {
  181.             return DOLLAR + txt.toFixed(CFFIXED) + CFCENT;
  182.  
  183.         }
  184.  
  185.         /**  Data Section **/
  186.  
  187.         var tableData = [
  188.             {
  189.                 heading: 'Paid',
  190.                 value: formatText(paid)
  191.             },
  192.             {
  193.                 heading: 'Pending',
  194.                 value: formatText(pending)
  195.             },
  196.             {
  197.                 heading: 'Total',
  198.                 value: formatText(TotalPay)
  199.             },
  200.             {    
  201.                 heading: 'Est. Bonus',
  202.                 value: formatText(Bonus)
  203.             },
  204.             {
  205.                 heading: 'Pay/Job',
  206.                 value: formatText(avgperjob)
  207.             },
  208.             {
  209.                 heading: 'Job Count',
  210.                 value: jobCount
  211.             },
  212.             {
  213.                 heading: 'Training',
  214.                 value: trainingJobs
  215.             },
  216.             {
  217.                 heading: 'Steps',
  218.                 value: Steps.toFixed(0)
  219.             },
  220.             {
  221.                 heading: 'Steps/Job',
  222.                 value: avgsteps.toFixed(2)
  223.             },
  224.             {
  225.                 heading: 'Time',
  226.                 value: formatSeconds(timeSpent)
  227.             }
  228.         ];
  229.  
  230.         var cssData = [
  231.             {
  232.                 selector: 'table#info',
  233.                 rules: [
  234.                     'border-collapse:collapse;',
  235.                     'border-color:#ccc;',
  236.                     'border:none;'
  237.                 ]
  238.             },
  239.             {
  240.                 selector: 'table#info tr th',
  241.                 rules: [
  242.                     'background-color:#f0f0f0;'
  243.                 ]
  244.             },
  245.             {
  246.                 selector: 'table#info tr th, table#info tr td',
  247.                 rules: [
  248.                     'font-family:Arial, sans-serif;',
  249.                     'font-size:14px;',
  250.                     'font-weight:normal;',
  251.                     'padding:10px 5px;',
  252.                     'padding:10px 5px;',
  253.                     'border-style:solid;',
  254.                     'border-width:0px;',
  255.                     'overflow:hidden;',
  256.                     'word-break:normal;',
  257.                     'border-color:#ccc;',
  258.                     'color:#333;',
  259.                     'text-align:center;',
  260.                     'vertical-align:top;'
  261.                 ]
  262.             },
  263.             {
  264.                 selector: 'table#info tr td:nth-child(even)',
  265.                 rules: [
  266.                     'background-color:#fff;'
  267.                 ]
  268.             },
  269.             {
  270.                 selector: 'table#info tr td:nth-child(odd)',
  271.                 rules: [
  272.                     'background-color:#f9f9f9;'
  273.                 ]
  274.             }
  275.         ];
  276.  
  277.         if (day.text === "Today") {  // only need to run this once
  278.             var style = generateCSS(cssData);
  279.             $(style).insertBefore(rfTable);
  280.         }
  281.  
  282.         var div = document.createElement('div');
  283.         var br = document.createElement('br');
  284.         div.appendChild(br);
  285.  
  286.         var title = document.createElement('center');
  287.         title.innerHTML = day.text + "'s Summary";
  288.         div.appendChild(title);
  289.  
  290.         var table = generateTable(day, tableData);
  291.         table.id = "info";
  292.         div.appendChild(table);
  293.  
  294.  
  295.         if (EasyCopy) {
  296.             var textDiv = document.createElement('div');
  297.             textDiv.innerHTML = generateText(day, tableData, ["Steps/Job", "Pay/Job", "Paid", "Pending", "Total", "Est. Bonus"]);
  298.             div.appendChild(textDiv);
  299.  
  300.             console.log("Day:"+day.text);
  301.             var d = day.text=="Today" ? new Date() : new Date(new Date().setDate(new Date().getDate()-1));
  302.             var dia = d.getDate();
  303.             var mes = d.getMonth()+1;
  304.             var ano = d.getFullYear();
  305.             var index;
  306.  
  307.             if(localStorage.jobs !== undefined)  
  308.                 Jobs = JSON.parse(localStorage.getItem("jobs"));
  309.  
  310.             if ( day.text == "Today") {
  311.                 if ( Jobs !== null && Jobs.length >1 ) {
  312.                     index = Jobs.length - 1 ;
  313.                     if (Jobs[index].date !=  dia+"/"+mes+"/"+ano )
  314.                         Jobs.push({ 'date': dia+"/"+mes+"/"+ano, 'paid': jobCount, 'training': trainingJobs, 'steps': parseInt(Steps) });
  315.                     if (Jobs[index].paid != jobCount || Jobs[index].training != trainingJobs) {
  316.                         Jobs[index].paid = jobCount;
  317.                         Jobs[index].training = trainingJobs;
  318.                         Jobs[index].steps =  parseInt(Steps);
  319.                     }
  320.                 } else
  321.                     Jobs.push({ 'date': dia+"/"+mes+"/"+ano, 'paid': jobCount, 'training': trainingJobs, 'steps': parseInt(Steps) });
  322.             }
  323.             if ( day.text == "Yesterday" ) {
  324.                 if ( Jobs !== null && Jobs.length >1 ) {
  325.                     index = Jobs.length - 2;
  326.                     if (Jobs[index].date !=  dia+"/"+mes+"/"+ano )
  327.                         Jobs.push({ 'date': dia+"/"+mes+"/"+ano, 'paid': jobCount, 'training': trainingJobs, 'steps': parseInt(Steps) });
  328.                     if (Jobs[index].paid != jobCount || Jobs[index].training != trainingJobs) {
  329.                         Jobs[index].paid = jobCount;
  330.                         Jobs[index].training = trainingJobs;
  331.                         Jobs[index].steps =  parseInt(Steps);
  332.                     }
  333.                 } else
  334.                     Jobs.splice(index +1,0, { 'date': dia+"/"+mes+"/"+ano, 'paid': jobCount, 'training': trainingJobs, 'steps': parseInt(Steps) });
  335.             }
  336.             console.log(JSON.stringify(Jobs));
  337.             localStorage.setItem("jobs", JSON.stringify(Jobs));
  338.  
  339.         }
  340.  
  341.         $(div).insertBefore(rfTable);
  342.         if (day.text == "Yesterday" && !hideGraph == true) {
  343.             $(div).after('<div id="chart_div" style="width: 924px; height: 250px;"></div>');
  344.             $(div).after('<div id="chart_div2" style="width: 924px; height: 250px;"></div>');
  345.             $("#chart_div").insertBefore(rfTable);
  346.             google.charts.load('current', {'packages': ['corechart']});
  347.             google.charts.setOnLoadCallback(drawChart);
  348.             google.charts.setOnLoadCallback(drawChart2);
  349.             function drawChart() {
  350.                 var items = [];
  351.                 items.push ( [ 'date', 'paid','training' ]);
  352.                 for (var i=0; i < Jobs.length;i++) {
  353.                     items.push ( [  Jobs[i].date,  Jobs[i].paid, Jobs[i].training ] );
  354.                 }
  355.  
  356.                 var data = google.visualization.arrayToDataTable(items);
  357.                 var options = {
  358.                     title : '',
  359.                     legend: { position: 'top', maxLines: 3 },
  360.                     bar: { groupWidth: '75%' },
  361.                     vAxis: {title: 'Job Count'},
  362.                     hAxis: {title: 'Job Date'},
  363.                     seriesType: 'bars',
  364.                     isStacked: true
  365.                 };
  366.                 var chart = new google.visualization.ComboChart(document.getElementById('chart_div2'));
  367.                 chart.draw(data, options);
  368.             }
  369.             function drawChart2() {
  370.                 var items = [];
  371.                 items.push ( [ 'date', 'steps' ]);
  372.                 for (var i=0; i < Jobs.length;i++) {
  373.                     items.push ( [  Jobs[i].date,  Jobs[i].steps ] );
  374.                 }
  375.  
  376.                 var data = google.visualization.arrayToDataTable(items);
  377.                 var options = {
  378.                     title : '',
  379.                     legend: { position: 'top', maxLines: 3 },
  380.                     bar: { groupWidth: '75%' },
  381.                     vAxis: {title: 'Steps'},
  382.                     hAxis: {title: 'Job Date'},
  383.                     seriesType: 'bars',
  384.                     isStacked: false
  385.                 };
  386.                 var chart = new google.visualization.ComboChart(document.getElementById('chart_div'));
  387.                 chart.draw(data, options);
  388.             }
  389.         }
  390.  
  391.     } // end createTable
  392.  
  393.  
  394.     /**  Generators for HTML / TEXT / CSS **/
  395.  
  396.     function generateText(day, data, skip) {
  397.         var text = day.text;
  398.         for (var i = 0; i < data.length; i++) {
  399.             if (skip.indexOf(data[i].heading) !== -1) continue;
  400.             text += " " + data[i].heading + ": " + data[i].value + " |";
  401.         }
  402.         return text;
  403.     }
  404.  
  405.     function generateTable(day, data) {
  406.         var table = document.createElement('table');
  407.         var headingRow = document.createElement('tr');
  408.         var valueRow = document.createElement('tr');
  409.         table.appendChild(headingRow);
  410.         table.appendChild(valueRow);
  411.  
  412.         for (var i = 0; i < data.length; i++) {
  413.             var cell = data[i];
  414.             var headingCell = document.createElement('th');
  415.             var valueCell = document.createElement('td');
  416.             headingCell.innerHTML = cell.heading;
  417.             valueCell.innerHTML = cell.value;
  418.             headingRow.appendChild(headingCell);
  419.             valueRow.appendChild(valueCell);
  420.         }
  421.         return table;
  422.     }
  423.  
  424.     function generateCSS(data) {
  425.         var style = document.createElement('style');
  426.         var cssBody = "";
  427.         for (var i = 0; i < data.length; i++) {
  428.             var selector = data[i].selector;
  429.             var rules = data[i].rules;
  430.             cssBody += selector + " { ";
  431.             for (var r = 0; r < rules.length; r++){
  432.                 var rule = rules[r];
  433.                 cssBody += rule;
  434.             }
  435.             cssBody += " } ";
  436.         }
  437.         style.innerText = cssBody;
  438.         return style;
  439.     }
  440.  
  441. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement