Ensures you are the winning bidder if you want to be.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

891 lines
36 KiB

// ==UserScript==
// @name AlwaysWin-ntsmhf
// @namespace https://git.qhrei.com/steven/alwayswin-ntsmhf/
// @version 0.1
// @description Make sure you are positioned where you want to be in the bidding for each county.
// @author Steven Allen
// @match https://leads.needtosellmyhousefast.com/*
// @require https://code.jquery.com/jquery-3.7.1.min.js
// @require http://crypto.stanford.edu/sjcl/sjcl.js
// @icon https://www.google.com/s2/favicons?sz=64&domain=needtosellmyhousefast.com
// @grant none
// ==/UserScript==
'use strict';
//Load our settings
//localStorage.removeItem('alwayswin_settings');
const verboseLevel=0;
console.log("Loading settings");
var alwaysWinSettingsString = localStorage.getItem('alwayswin_settings');
//console.log(alwaysWinSettingsString);
if(alwaysWinSettingsString == null || alwaysWinSettingsString == undefined) {
const defaultSettings = {"isReloadEnabled":true, "isAutoLoginEnabled":false, "minSecondsBetweenReloads": 60, "maxSecondsBetweenReloads":300, "isGeneralCapEnabled":false, "generalCap":500, "oversight":[]};
const defaultSettingsString = JSON.stringify(defaultSettings);
localStorage.setItem('alwayswin_settings',defaultSettingsString);
alwaysWinSettingsString = defaultSettingsString;
}
var alwaysWinSettings = JSON.parse(alwaysWinSettingsString);
//console.log(alwaysWinSettings);
////////////
// Div injection and auto reload functions
////////////
function getRandomNumberBetween(min, max) {
min = Number(min);
max = Number(max);
return Math.floor(Math.random() * (max - min) + min);
}
function getCheckedValue(fieldName) {
switch (fieldName) {
case "isReloadEnabled":
return reloadIsEnabled() ? "checked": "";
case "isAutoLoginEnabled":
return autoLoginIsEnabled() ? "checked": "";
case "isGeneralCapEnabled":
return generalCapIsEnabled() ? "checked" :"";
default:
return "";
}
return "";
}
function addAlwaysWinStyle(css) {
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) { return; }
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
}
function handleSaveSettings() {
saveSettings();
location.reload();
}
function saveSettings() {
let isReloadEnabledValue = document.querySelector("[name='isReloadEnabled']").checked;
let isAutoLoginEnabledValue = document.querySelector("[name='isAutoLoginEnabled']").checked;
let minSecondsBetweenReloadsValue = document.querySelector("[name='minSecondsBetweenReloads']").value;
let maxSecondsBetweenReloadsValue = document.querySelector("[name='maxSecondsBetweenReloads']").value;
let isGeneralCapEnabledValue = document.querySelector("[name='isGeneralCapEnabled']").checked;
let generalCap = document.querySelector("[name='generalCap']").value;
let capPresidence = document.querySelector("[name='capPresidence']").value;
let oversight = [];
var latestSettings = alwaysWinSettings;
latestSettings.isReloadEnabled = isReloadEnabledValue;
latestSettings.isAutoLoginEnabled = isAutoLoginEnabledValue;
latestSettings.minSecondsBetweenReloads = minSecondsBetweenReloadsValue;
latestSettings.maxSecondsBetweenReloads = maxSecondsBetweenReloadsValue;
latestSettings.isGeneralCapEnabled = isGeneralCapEnabledValue;
latestSettings.generalCap = generalCap;
latestSettings.capPresidence = capPresidence;
if(latestSettings.oversight == null || latestSettings == undefined) {
latestSettings.oversight = oversight;
}
const latestSettingsString = JSON.stringify(latestSettings);
localStorage.setItem('alwayswin_settings',latestSettingsString);
alwaysWinSettingsString = latestSettings;
return latestSettings;
}
function saveCountyInfoStats(newStats) {
let existingStats = [];
//get existing stats if they exist
let existingStatsString = localStorage.getItem('alwayswin_stats');
if(existingStatsString != null && existingStatsString !== undefined) {
existingStats = JSON.parse(existingStatsString);
}
const combinedStats = existingStats.concat(newStats)
const updatedStatsString = JSON.stringify(combinedStats);
localStorage.setItem('alwayswin_stats',updatedStatsString);
//console.log(combinedStats);
}
function reload() {
console.log("Saving settings...");
let alwaysWinSettings = saveSettings();
awLog("Its time to perform a reload.");
awLog("isEnabled: "+ alwaysWinSettings.isReloadEnabled);
awLog("secondsBetweenReloads:"+ alwaysWinSettings.minSecondsBetweenReloads +" - "+ alwaysWinSettings.maxSecondsBetweenReloads);
if(!reloadIsEnabled() ) {
awLog("Reload is not enabled");
return;
}
awLog("Reload is enabled. Reloading...");
location.reload();
}
function reloadIsEnabled(){
var checkedValue = alwaysWinSettings.isReloadEnabled ?? false;// document.querySelector("[name='isReloadEnabled']").checked;
if(checkedValue == true) {
return true;
}
return false;
}
function autoLoginIsEnabled(){
var checkedValue = alwaysWinSettings.isAutoLoginEnabled ?? false;
var retVal = (checkedValue == true);
return retVal;
}
function generalCapIsEnabled () {
var checkedValue = alwaysWinSettings.isGeneralCapEnabled ?? false;
var retVal = (checkedValue == true);
return retVal;
}
function getBidCapForCountyId(countyId) {
//Get the default bidcap from settings
var bidCap = alwaysWinSettings.generalCap;
const countyOversight = alwaysWinSettings.oversight.find(({ id }) => id === countyId);
if(countyFound(countyOversight)) {
bidCap = countyOversight.bidCap;
}
return Number(bidCap);
}
////////////////////////////////////////////////////////////////////////////////////
// Always win code to find and take the highest/tie bid
////////////////////////////////////////////////////////////////////////////////////
function getCountyInfo(countyId){
var county = document.querySelector('[data-subscription_id="'+ countyId +'"].subscription-status');
if(county === null) {
console.log("county "+ countyId +" row not found");
return;
}
let countyRow = county.closest("tr");
let bidController = {};
bidController.countyRow = countyRow;
const bidIncriment = 25; //This is hard coded into site but could change later.
let num_bid = Number(countyRow.querySelector('.bid-controller--bid').value);
let num_tieBid = Number(countyRow.querySelector('.bid-controller').dataset.top_bid);
let num_floorBid = num_tieBid - bidIncriment;
let num_winningBid = num_tieBid + bidIncriment;
let num_clicksToMinWin = 1;
let winGap = (num_tieBid - num_bid);
if(winGap < 1) {
num_clicksToMinWin = (winGap / bidIncriment) + 1;
} else if(winGap > 0) {
num_clicksToMinWin = (winGap + bidIncriment) / bidIncriment;
}
let num_bidCap = getBidCapForCountyId(countyId);
let num_clicksToBidCap = num_clicksToMinWin;
bidController.readTimestamp = new Date();
bidController.isEnabled = county.checked;
bidController.id = county.dataset.subscription_id;
bidController.name = county.closest("div").getElementsByTagName('a')[0].innerText;
bidController.bid = num_bid;
bidController.tieBid = num_tieBid;
bidController.floorBid = num_floorBid;
bidController.winningBid = num_winningBid;
bidController.status = countyRow.querySelector(".bid-status").innerText;//.trim(); //countyRow.querySelector(".bid-status").dataset.bid_status;
bidController.isWinning = (num_bid > num_tieBid);
bidController.isWinningByTooMuch = (num_bid > num_winningBid);
bidController.clicksToMinWin = num_clicksToMinWin;
bidController.bidCap = num_bidCap;
bidController.clicksToBidCap = num_clicksToBidCap;
bidController.btnSave = countyRow.querySelector('.bid-controller-btn--save');
bidController.btnBidUp = countyRow.querySelector('.bid-controller-btn--increment');
bidController.btnBidDown = countyRow.querySelector('.bid-controller-btn--decrement');
return bidController;
}
function winCounty(countyJson, saveChanges) {
if(countyJson?.id == undefined) {
awLog("Unable to find county. So no way to win it.");
return;
}
let countyInfo = countyJson.id + " "+ countyJson.name;
//console.log(countyJson.isWinning +" = "+ countyJson.tieBid +" > "+ countyJson.bid);
//console.log(countyJson.isWinningByTooMuch +" = "+ countyJson.bid +" > "+ countyJson.winningBid);
//console.log("clicksToMinWin: "+ countyJson.clicksToMinWin);
//console.log(countyJson);
if(countyJson.clicksToMinWin == 0) {
//if we made it here no changes were needed to win by just the right amount
//Nothing else to do to win optimally
//console.log(countyInfo +" is already winning by just the right amount");
awLog(countyInfo +" is already winning by just the right amount");
} else if(countyJson.clicksToMinWin > 0) {
//console.log(countyInfo +" is currently loosing. Increasing bid now");
awLog(countyInfo +" is currently loosing by "+countyJson.clicksToMinWin+" Increasing bid now");
for(var i = 0; i < countyJson.clicksToMinWin; i++) {
//console.log("calling btnBidUp.click() for "+ countyInfo);
countyJson.btnBidUp.click();
}
if(saveChanges) {
//console.log("calling btnSave.click() for "+ countyInfo);
countyJson.btnSave.click();
}
} else if (countyJson.clicksToMinWin < 0) {
//console.log(countyInfo +" is winning by too much. Decreasing bid now");
awLog(countyInfo +" is winning by too much. Decreasing bid now");
let clicksRemaining = Math.abs(countyJson.clicksToMinWin);
while(clicksRemaining > 0) {
//console.log("calling btnBidDown.click() for "+ countyInfo);
countyJson.btnBidDown.click();
clicksRemaining--;
}
if(saveChanges) {
//console.log("calling btnSave.click() for "+ countyInfo);
countyJson.btnSave.click();
}
}
}
function tieCounty(countyJson, saveChanges) {
//TODO: implemnt me
let countyInfo = countyJson.id + " "+ countyJson.name;
awLog(countyInfo +" tieCounty code not yet implemented");
}
function watchCounty(countyJson, saveChanges) {
//TODO: implemnt me
let countyInfo = countyJson.id + " "+ countyJson.name;
awLog(countyInfo +" watchCounty code not yet implemented");
}
function ignoreCounty(countyJson, saveChanges) {
//TODO: implemnt me
let countyInfo = countyJson.id + " "+ countyJson.name;
awLog(countyInfo +" ignoreCounty code not yet implemented");
}
function awLog(message) {
console.log(message);
const currentContent = document.getElementById("awLog").innerHTML;
document.getElementById("awLog").innerHTML = currentContent +""+ message +"<br/>";
}
function encryptAndStore(encryptionKey, clearText) {
return JSON.stringify(sjcl.encrypt(encryptionKey, clearText));
}
function unStoreAndDecrypt (encryptionKey, jsonObj) {
return sjcl.decrypt(encryptionKey, JSON.parse(jsonObj));
}
function loginIfNeeded(){
var div_signin = document.querySelector('.signin-box');
var loginIsNeeded = false;
if(div_signin != undefined && div_signin != null) {
loginIsNeeded = true;
if(!alwaysWinSettings.isAutoLoginEnabled) {
console.log("AutoLogin is turned off.");
awLog("AutoLogin is turned off.");
return loginIsNeeded;
}
console.log("A signin dialog exists");
var txt_email = div_signin.querySelector("[id='email']");
var txt_password = div_signin.querySelector("[id='inputPassword']");
var btn_signin = div_signin.querySelector('.btn-signin'); //btn btn-primary btn-block btn-signin
var encKey = alwaysWinSettings.encKey ?? "";
var ntsmhfUser = alwaysWinSettings.ntsmhfUser ?? "";
var ntsmhfPass = alwaysWinSettings.ntsmhfPass ?? "";
if (!encKey) {
encKey = prompt('Script key not set for ' + location.hostname + '. Please enter a random string:','');
alwaysWinSettings.encKey = encKey;
ntsmhfUser = "";
ntsmhfPass = "";
}
if(ntsmhfUser) {
ntsmhfUser = unStoreAndDecrypt(encKey, ntsmhfUser);
} else {
ntsmhfUser = prompt('UserName is not set for '+ location.hostname +'. Enter it now:','');
alwaysWinSettings.ntsmhfUser = encryptAndStore(encKey, ntsmhfUser);
}
if(ntsmhfPass) {
ntsmhfPass = unStoreAndDecrypt(encKey, ntsmhfPass);
} else {
ntsmhfPass = prompt('Password is not set for '+ location.hostname +'. Enter it now:','');
alwaysWinSettings.ntsmhfPass = encryptAndStore(encKey, ntsmhfPass);
}
const latestSettingsString = JSON.stringify(alwaysWinSettings);
localStorage.setItem('alwayswin_settings',latestSettingsString);
//////
txt_email.value = ntsmhfUser;
txt_password.value = ntsmhfPass;
btn_signin.click();
}
return loginIsNeeded;
}
function renderOption(value, selectedValue, displayValue) {
if(displayValue == null || displayValue===undefined) {
displayValue = value;
}
var optionHtml = '<option value="'+ value +'"';
if(value == selectedValue) {
optionHtml += ' selected';
}
optionHtml += '>'+ displayValue +'</option>';
return optionHtml;
}
const Presidence = Object.freeze({
General: "general",
Row: "row",
Highest: "highest",
Lowest: "lowest"
})
const AppliesTo = Object.freeze({
All: "all",
None: "none",
Capped: "capped",
Uncapped: "uncapped"
})
const Oversight = Object.freeze({
Win: "win",
Tie: "tie",
Watch: "watch",
Ignore: "ignore"
})
const Capsource = Object.freeze({
Row: "row",
General: "general"
})
const CapTrigger = Object.freeze({
None: "None",
General: "General",
Row: "Row"
})
function getTrueCap(isGeneralCapEnabled, isRowCapIsEnabled, presidenceValue, generalCapValue, rowCapValue){
//Our response object
function trueCap(trigger, value) {
let response = {};
response.trigger = trigger;
response.value = value;
return response;
}
trueCap.trigger = CapTrigger.None; //Used to identify which cap the trueCap value was derived from.
trueCap.value = null; //The actual calculated true cap
//Do some error handling to start off
if(isGeneralCapEnabled == true && generalCapValue == null) {
if(verboseLevel >= 1) {
console.warn("GeneralCap is enabled but the GeneralCapValue is not set - Acting as if GeneralCap was not enabled.");
}
isGeneralCapEnabled = false;
}
if(isRowCapIsEnabled == true && rowCapValue == null) {
if(verboseLevel >= 1) {
console.warn("RowCap is enabled but the RowCapValue is not set - Acting as if RowCap was not enabled.");
}
isRowCapIsEnabled = false;
}
//Now our actual logic begins
if(isGeneralCapEnabled == false && isRowCapIsEnabled == false) {
return trueCap(CapTrigger.None,null); //No cap available to return
}
if(isRowCapIsEnabled == true && rowCapValue == null) {
//console.warn("RowCap is enabled but the RowCapValue is not set");
return trueCap(CapTrigger.None,null); //No cap available to return
}
if(isGeneralCapEnabled == true) {
switch (presidenceValue) {
case Presidence.General:
//General wins
return trueCap(CapTrigger.General, generalCapValue);
case Presidence.Row:
if(isRowCapIsEnabled == true) {
//Row wins
return trueCap(CapTrigger.Row, rowCapValue);
}
return trueCap(CapTrigger.General, generalCapValue);
case Presidence.Highest:
if(isRowCapIsEnabled == true) {
//Figure out which is higher
if(rowCapValue > generalCapValue) {
//Row wins
return trueCap(CapTrigger.Row, rowCapValue);
}
}
return trueCap(CapTrigger.General, generalCapValue);;
case Presidence.Lowest:
if(isRowCapIsEnabled == true) {
if(rowCapValue < generalCapValue) {
//Row wins
return trueCap(CapTrigger.Row, rowCapValue);
}
}
return trueCap(CapTrigger.General, generalCapValue);;
default:
return trueCap(CapTrigger.General, generalCapValue);;
}
return trueCap(CapTrigger.General, generalCapValue);;
}
//If we made it here then generalCap is not enabled but the row cap may still be enabled
if(isRowCapIsEnabled == true) {
return trueCap(CapTrigger.Row, rowCapValue);
}
//We should never get here
return trueCap(CapTrigger.None, null);
}
function getCapPresidenceOptions(selectedOption) {
var optionsHtml = "";
optionsHtml += renderOption(Presidence.Row, selectedOption, "Row Cap");
optionsHtml += renderOption(Presidence.General, selectedOption, "General Cap");
optionsHtml += renderOption(Presidence.Highest, selectedOption, "Highest Cap");
optionsHtml += renderOption(Presidence.Lowest, selectedOption, "Lowest Cap");
return optionsHtml;
}
function getOversightOptions(countyId, selectedOption) {
var optionsHtml = "";
optionsHtml += renderOption(Oversight.Win, selectedOption);
optionsHtml += renderOption(Oversight.Tie, selectedOption);
optionsHtml += renderOption(Oversight.Watch, selectedOption);
optionsHtml += renderOption(Oversight.Ignore, selectedOption);
return optionsHtml;
}
function countyFound(countyValue) {
return countyValue !== undefined;
}
function upsertOversight(countyOversightJson) {
//console.log(countyOversightJson);
const countyId = countyOversightJson.id;
var countyFoundAt = alwaysWinSettings.oversight.findIndex(({ id }) => id === countyId);
if(countyFoundAt == -1) {
alwaysWinSettings.oversight.push(countyOversightJson);
countyFoundAt = alwaysWinSettings.oversight.length;
}
}
function convertToOversightJson(countyInfoJson, action, isBidCapEnabled){
const countyInfo = {
"id": countyInfoJson.id,
"bidCap": countyInfoJson.bidCap,
"isBidCapEnabled": isBidCapEnabled,
"action": action
};
return countyInfo;
}
function getBidCapReasonIcon(reason) {
switch(reason) {
case 1:
return "🔀";
case 2:
return "⏹";
case 3:
return "🔼";
case 4:
return "🔽";
default:
return "";
}
return "";
}
function getBidCapReason(tieBid, myBid, oversightAction, rowCapIsEnabled, rowCap, generalCapIsEnabled, generalCap, capPresidence, applyPresidenceTo) {
let tieBidNum = Number(tieBid);
let winBidNum = Number(tieBid) + 25;
let generalCapNum = Number(generalCap);
let rowCapNum = Number(rowCap);
let myBidNum = Number(myBid);
//Build our response object
let results = {};
results.shouldApplyCap = false; //Flag to indicate if the cap should be applied
results.reason = 0; //No Cap to start of with
results.trueCap = null; //Default to no true cap
results.capSource = null; //No caps applied
results.myBid = myBidNum;
//WIP - LOTS of rules here - these are just the beginning.
if(generalCapIsEnabled) {
if(capPresidence == Presidence.General) {
if(applyPresidenceTo == AppliesTo.All) {
results.shouldApplyCap = false;
results.capSource = Capsource.General;
results.trueCap = generalCapNum;
switch(oversightAction) {
case Oversight.Win:
if(winBidNum > generalCapNum) {
results.shouldApplyCap = true;
results.reason = 1;
results.myBid = generalCapNum;
return results;
}
//winBidNum <= generalCapNum
results.reason = 2;
results.myBid = myBidNum;
break;
case Oversight.Tie:
if(tieBidNum > generalCapNum) {
results.shouldApplyCap = true;
results.reason = 3;
results.myBid = generalCapNum;
return results;
}
//tieBidNum <= generalCapNum
results.reason = 4;
results.myBid = myBidNum;
break;
case Oversight.Watch:
results.reason = 5;
break;
case Oversight.Ignore:
results.reason = 6;
break;
default:
//We should never get here because all oversight actions have been covered.
}
return results;
}
else if(applyPresidenceTo == AppliesTo.None){
}
else if(applyPresidenceTo == AppliesTo.Capped){
}
else if(applyPresidenceTo == AppliesTo.Uncapped){
}
return results;
}
else if(capPresidence == Presidence.Row) {
return results;
}
else if(capPresidence == Presidence.Highest){
return results;
}
else if(capPresidence == Presidence.Lowest){
return results;
}
}
//If we made it here, generalCapIsEnabled is FALSE so no conflicts should exist
//This means rowCaps are the winners if they are enabled.
if(rowCapIsEnabled) {
switch(oversightAction) {
case Oversight.Win:
if(winBidNum > rowCapNum) {
results.shouldApplyCap = true;
results.reason = 101;
results.trueCap = rowCapNum;
results.capSource = Capsource.Row;
results.myBid = rowCapNum;
return results;
}
//winBidNum <= rowCapNum
results.shouldApplyCap = false;
results.reason = 102;
results.trueCap = rowCapNum;
results.capSource = Capsource.Row;
results.myBid = myBidNum;
break;
case Oversight.Tie:
if(tieBidNum > rowCapNum) {
results.shouldApplyCap = true;
results.reason = 103;
results.trueCap = rowCapNum;
results.capSource = Capsource.Row;
results.myBid = rowCapNum;
return results;
}
//tieBidNum <= generalCapNum
results.shouldApplyCap = false;
results.reason = 104;
results.trueCap = rowCapNum;
results.capSource = Capsource.Row;
results.myBid = myBidNum;
break;
case Oversight.Watch:
results.shouldApplyCap = false;
results.reason = 105;
results.trueCap = null;
results.capSource = Capsource.Row;
results.myBid = myBidNum;
break;
case Oversight.Ignore:
results.shouldApplyCap = false;
results.reason = 106;
results.trueCap = null;
results.capSource = Capsource.Row;
results.myBid = myBidNum;
break;
default:
//We should never get here because all oversight actions have been covered.
}
return results;
}
//Caps are not enabled for this row.
return results;
}
function injectOversight(countyId, action) {
countyId += ""; //cast into string incase number was passed in
//console.log("injecting oversight into county "+countyId);
var countyJson = getCountyInfo(countyId);
if(countyJson === null || countyJson === undefined) {
console.log(" could not find the county row "+countyId);
return;
}
//// BEGIN TempCode TODO: figure out if upsert Code should live in injectOversight
const isBidCapEnabled = false;
const countyOversightJson = convertToOversightJson(countyJson, action, isBidCapEnabled);
upsertOversight(countyOversightJson);
//// END TempCode
let countyRow = countyJson.countyRow;
var oversightCountyDiv = document.createElement('div');
oversightCountyDiv.id = "oversight-county-"+countyId;
oversightCountyDiv.style = "border: 1px dotted gray; padding: 0; margin: 0; font-size: 12px; overflow-x: visible";
var countyDivHtml ='';
countyDivHtml += ''+ countyJson.id +'';
countyDivHtml += ' | <label>tie:'+ countyJson.tieBid +'</label>';
countyDivHtml += ' | <label>margin:'+ countyJson.clicksToMinWin +'</label>';
oversightCountyDiv.innerHTML = countyDivHtml;
var targetContainerCounty = countyRow.firstElementChild;
targetContainerCounty.appendChild(oversightCountyDiv);
var oversightPriceDiv = document.createElement('div');
oversightPriceDiv.id = "oversight-price-"+countyId;
oversightPriceDiv.style = "border: 1px dotted gray; padding: 0; margin: 0; font-size: 12px; overflow-x: visible";
//Begin TODO: move this code block elsewhere IT IS WIP
const settingsCapPresidence = alwaysWinSettings.capPresidence;
const settings_Presidence_RowCap = (settingsCapPresidence == Presidence.Row);
const settings_Presidence_GeneralCap = (settingsCapPresidence == Presidence.General);
const settings_Presidence_HighestCap = (settingsCapPresidence == Presidence.Highest);
const settings_Presidence_LowestCap = (settingsCapPresidence == Presidence.Lowest);
const settingsGeneralCapAppliesTo = Presidence.General
const settings_GeneralCapAppliesTo_None = (settingsGeneralCapAppliesTo == AppliesTo.None)//None of the
const settings_GeneralCapAppliesTo_All = (settingsGeneralCapAppliesTo == AppliesTo.All)//All
const settings_GeneralCapAppliesTo_Capped = (settingsGeneralCapAppliesTo == AppliesTo.Capped)//Capped Only
const settings_GeneralCapAppliesTo_Uncapped = (settingsGeneralCapAppliesTo == AppliesTo.Uncapped)//UnCapped Only
const rowCapControlsShouldBeVisible = (action == Oversight.Win || action == Oversight.Tie); //TODO write logic to determine if the enable Bidcap checkbox and words should be visible
const rowCapCheckboxShouldBeVisible = (action == Oversight.Win || action == Oversight.Tie); //TODO: write logic
const rowCapCheckboxShouldBeDisabled = false; //TODO: write logic
const rowCapCheckboxShouldBeChecked = false; //TODO: write logic
const rowCapInputShouldBeVisible = (action == "win"); //TODO: run thru rules to determine showCapInfo value
const rowCapInputIsBeingOverridden = settings_Presidence_GeneralCap; //TODO: write logic
const rowCapInputShouldBeDisabled = (rowCapInputIsBeingOverridden || !rowCapCheckboxShouldBeChecked); //TODO: write logic
const trueCap = alwaysWinSettings.generalCap; //countyJson.bidCap; //TODO actually calcuate instead of reading from settings
//const trueCap = getTrueCap(isGeneralCapEnabled,isRowCapIsEnabled,presidenceValue,generalCapNum,rowCapNum); //TODO: Uncomment this line once I get the params right.
const capIsCurrentlyBeingAppliedToBid = countyJson.bid > Number(trueCap);
//End TODO
var priceDivHtml ='';
//priceDivHtml += ''+ countyJson.id +'';
priceDivHtml += '<label for="oversightAction-'+countyId+'"><select name="oversightAction-'+ countyId +'" id="oversightAction-'+ countyId +'">'+ getOversightOptions(countyId, action) +'</select></label>';
if(rowCapControlsShouldBeVisible) {
priceDivHtml += ' | <label><input ';
if(rowCapCheckboxShouldBeDisabled) {
priceDivHtml += 'disabled ';
}
priceDivHtml += 'type="checkbox" style="transform:scale(.5);" name="enableBidCap-'+countyId+'"';
if(rowCapCheckboxShouldBeChecked) {
priceDivHtml += ' checked';
}
priceDivHtml += '/>cap';
if(rowCapInputShouldBeVisible) {
priceDivHtml += ' at <input ';
if(rowCapInputShouldBeDisabled) {
priceDivHtml += 'disabled ';
}
priceDivHtml += 'type="text" name="bidCap-'+ countyId +'" id="bidCap-'+ countyId +'" style="font-size:10px; width:40px; height:12px;" value="'+ countyJson.bidCap +'" /></label>';
}
if(rowCapInputIsBeingOverridden) {
priceDivHtml += '<strike>'+ countyJson.bidCap +'</strike> ->'+ alwaysWinSettings.bidCap;//TODO render override html
}
}
if(capIsCurrentlyBeingAppliedToBid) {
priceDivHtml += getBidCapReasonIcon(1) + ' bid is capped at '+ trueCap;
}
//priceDivHtml += '<button disabled id="oversightSave-'+countyId+'" style="font-size:9px;background-color:#aaaaaa;color:#FFFFFF;padding:1px;border-radius:2px;-moz-border-radius:2px;-webkit-border-radius:2px;margin:0px;">Apply</button>';
oversightPriceDiv.innerHTML = priceDivHtml;
var targetContainer = countyRow.lastElementChild;
targetContainer.appendChild(oversightPriceDiv);
}
const sleep = ms => new Promise(res => setTimeout(res, ms))
jQuery(window).on('load',function() {
console.log("Page loaded at: "+ new Date());
let minSecondsBetweenReloads = alwaysWinSettings.minSecondsBetweenReloads ?? 30;
let maxSecondsBetweenReloads = alwaysWinSettings.maxSecondsBetweenReloads ?? 180;
let isReloadEnabled = alwaysWinSettings.isReloadEnabled ?? false;
let isAutoLoginEnabled = alwaysWinSettings.isAutoLoginEnabled ?? false;
let isGeneralCapEnabled = alwaysWinSettings.isGeneralCapEnabled ?? false;
let capPresidence = alwaysWinSettings.capPresidence ?? "row";
let generalCap = alwaysWinSettings.generalCap ?? 500;
let secondsBetweenReloads = getRandomNumberBetween(minSecondsBetweenReloads, maxSecondsBetweenReloads);
//console.log("Next reload should occur in "+ secondsBetweenReloads +" seconds");
//Inject our controls
var newDiv = document.createElement ('div');
var newHtml = '<div class="alwaysWin-ntsmhf" id="alwaysWin-ntsmhf">';
newHtml += '<input type="checkbox" name="isAutoLoginEnabled" '+ getCheckedValue("isAutoLoginEnabled") +'/><label for="isAutoLoginEnabled">Auto Login</label> | ';
newHtml += '<button class="alwaysWinButton" id="alwaysWin-ntsmhf-save" type="button">Save</button><br />';
newHtml += '<input type="checkbox" name="isReloadEnabled" '+ getCheckedValue("isReloadEnabled") +'/><label for="isReloadEnabled">Auto Refresh</label> ';
newHtml += '<label for="minSecondsBetweenReloads">Every</label>:<input id="minSecondsBetweenReloads" type="text" size="3" name="minSecondsBetweenReloads" value="'+minSecondsBetweenReloads+'" /> to <input id="maxSecondsBetweenReloads" type="text" size="3" name="maxSecondsBetweenReloads" value="'+maxSecondsBetweenReloads+'" /> seconds <br/>';
newHtml += '<label for="isGeneralCapEnabled"><input type="checkbox" name="isGeneralCapEnabled" '+ getCheckedValue("isGeneralCapEnabled") +'/>Don&apos;t bid more than</label> ';
newHtml += '<label for="generalCap">:</label><input id="generalCap" type="text" size="5" name="generalCap" value="'+ generalCap+'"/> per county<br />';
newHtml += '<label for="capPresidence" title="If a row and general cap are enabled"><select id="capPresidence" name="capPresidence" />'+ getCapPresidenceOptions(capPresidence) +'</select> takes presidence</label><br/>';
newHtml += '<div id="reloaderData"><div id="countdown"></div><progress value="0" max="100" id="progressBar" style="width: 100%;"></progress></div><div id="awLog" class="alwaysWinLog"></div>';
newHtml += '</div>';
newDiv.innerHTML = newHtml;
addAlwaysWinStyle('.alwaysWin-ntsmhf {position: fixed; top: 0px; left: 0px; background-color: #DDDDDD; border-radius: 5px; padding:2px; box-shadow: 5px 5px 3px #777777;}');
addAlwaysWinStyle('.alwaysWin-ntsmhf .alwaysWinLog {float:left; width:100%; overflow-y: auto; height: 100px; font-size: 0.75em; border-style:ridge; background-color:#FEFEFE;}');
addAlwaysWinStyle('.alwaysWin-ntsmhf .alwaysWinButton { border: none; color: #333333; padding: 1px 2px; text-align: center; text-decoration: none; display: inline-block; font-size: 8x; margin: 1px 1px; cursor: pointer;}');
addAlwaysWinStyle('.alwaysWin-ntsmhf .alwaysWinButton:hover {box-shadow: 0 2px 2px 0}');
addAlwaysWinStyle('.alwaysWin-ntsmhf .alwaysWinButton:active {position: relative; top: 1px;}');
document.body.appendChild (newDiv);
const alwaysWinSave = document.getElementById("alwaysWin-ntsmhf-save");
alwaysWinSave.addEventListener("click", handleSaveSettings);
//Only run our code on certain pages
//console.log(window.location.pathname);
switch (window.location.pathname) {
case "/app":
case "/app/subscriptions":
break;
case "/signin":
break;
default:
return;
}
//Are we logged in?
var logWasNeeded = loginIfNeeded();
if (logWasNeeded) {
return; //don't execute any more code until we are logged in.
}
//Inject our bits into the page for oversight
//TODO: Get rid of these calls and only read injections from settings (possible when apply button is coded)
// For now they will be commented out unless it's a first run of the script
//injectOversight("84035","win"); //washington, OR
//injectOversight("87833","win"); //marion, OR
//injectOversight("84034","tie"); //cascade, MT
//injectOversight("84037","win"); //clackamas, OR
//injectOversight("84038","watch"); //benton, OR
//injectOversight("87835","watch"); //multnomah, OR
//injectOversight("91976","win"); //CLARK, WA
//// Now do the work
let newStats = [];
let oversightCount = alwaysWinSettings.oversight.length;
awLog("Checking "+ oversightCount +" counties");
for(let i = 0; i < oversightCount; i++) {
let currentEntity = alwaysWinSettings.oversight[i];
injectOversight(currentEntity.id, currentEntity.action);
const countyInfoJson = getCountyInfo(currentEntity.id);
//console.log(currentEntity);
switch (currentEntity.action) {
case Oversight.Win:
winCounty(countyInfoJson,true);
break;
case Oversight.Tie:
tieCounty(countyInfoJson,true);
break;
case Oversight.Watch:
watchCounty(countyInfoJson,false);
break;
case Oversight.Ignore:
ignoreCounty(countyInfoJson, false);
break;
default:
break;
}
newStats.push(countyInfoJson);
}
//console.log("Saving county info stats");
const countyInfoStats = saveCountyInfoStats(newStats);
//Start our ui feedback for the enduser
var reloadTimeleft = secondsBetweenReloads;
var reloadTimer = setInterval(function() {
document.getElementById("countdown").innerHTML = "("+secondsBetweenReloads+") Next reload will occur in "+ reloadTimeleft +" seconds.";
var progressBarValue = 100 - Math.floor(100 * (reloadTimeleft / secondsBetweenReloads)); //Calculate percent complete
document.getElementById("progressBar").value = progressBarValue;
if(reloadTimeleft <= 0){
clearInterval(reloadTimer);
document.getElementById("countdown").innerHTML = secondsBetweenReloads +" second reload timer exhausted";
reload();
}
reloadTimeleft -= 1;
}, 1000);
});