Compare commits

...

3 Commits

  1. 10
      README.md
  2. 294
      tampermonkey.js

10
README.md

@ -10,7 +10,7 @@ To load the Tampermonkey script:
### Functionality For Release
- [ ] Read from /app/subscriptions to get list of initial counties - if county is missing it automatically gets added.
- [ ] Sitewide bidcap (if any county bid exceeds X only bid up to X for that county)
- [x] Expose Sitewide bidcap (if any county bid exceeds X only bid up to X for that county)
- [x] Save button to persist changes (instead of waiting for refresh code to run)
- [x] Save settings to local storage
- [x] Retrieve settings from local storage
@ -20,11 +20,12 @@ To load the Tampermonkey script:
- [ ] use bidcap when processing each oversight
- [ ] Implement tieCounty code
- [ ] Implement watchCounty code
- [ ] Add cap presidence setting.
- [x] Add cap presidence setting.
- [ ] Add General Cap Applies to option
*If a row and settings cap are enabled then [options🔽] takes presidence.*
```Options
S - SettingsBidCap
G - GeneralBidCap
R - RowCap
H - The highest cap
L - The lowest cap
@ -51,6 +52,9 @@ To load the Tampermonkey script:
- [ ] Stats: Clear Stats
- [ ] if county action is ignore then hide the tr and dont inject oversight
- [ ] expose toggle to hide/show ignored counties in settings (not at row level but read for ignore action at each level)
- [ ] prices based on schedule (dont win ant night...)
- [ ] schedule derived from statistical analysis gathered over time.
### Bugs
- [ ] Figure out session timout/no longer refreshing/ not loaded issue (screensaver?, tab no focus?, os?, browser?)

294
tampermonkey.js

@ -21,7 +21,7 @@ var alwaysWinSettingsString = localStorage.getItem('alwayswin_settings');
//console.log(alwaysWinSettingsString);
if(alwaysWinSettingsString == null || alwaysWinSettingsString == undefined) {
const defaultSettings = {"isReloadEnabled":true, "isAutoLoginEnabled":false, "minSecondsBetweenReloads": 60, "maxSecondsBetweenReloads":300, "bidCap":500, "oversight":[]};
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;
@ -45,6 +45,8 @@ function getCheckedValue(fieldName) {
return reloadIsEnabled() ? "checked": "";
case "isAutoLoginEnabled":
return autoLoginIsEnabled() ? "checked": "";
case "isGeneralCapEnabled":
return generalCapIsEnabled() ? "checked" :"";
default:
return "";
}
@ -71,7 +73,10 @@ function saveSettings() {
let isAutoLoginEnabledValue = document.querySelector("[name='isAutoLoginEnabled']").checked;
let minSecondsBetweenReloadsValue = document.querySelector("[name='minSecondsBetweenReloads']").value;
let maxSecondsBetweenReloadsValue = document.querySelector("[name='maxSecondsBetweenReloads']").value;
let bidCap = document.querySelector("[name='bidCap']").value;
let isGeneralCapEnabledValue = document.querySelector("[name='isGeneralCapEnabled']").checked;
let generalCap = document.querySelector("[name='generalCap']").value;
let capPresidence = document.querySelector("[name='capPresidence']").value;
let oversight = [];
@ -80,7 +85,9 @@ function saveSettings() {
latestSettings.isAutoLoginEnabled = isAutoLoginEnabledValue;
latestSettings.minSecondsBetweenReloads = minSecondsBetweenReloadsValue;
latestSettings.maxSecondsBetweenReloads = maxSecondsBetweenReloadsValue;
latestSettings.bidCap = bidCap;
latestSettings.isGeneralCapEnabled = isGeneralCapEnabledValue;
latestSettings.generalCap = generalCap;
latestSettings.capPresidence = capPresidence;
if(latestSettings.oversight == null || latestSettings == undefined) {
latestSettings.oversight = oversight;
}
@ -135,9 +142,15 @@ function autoLoginIsEnabled(){
return retVal;
}
function generalCapIsEnabled () {
var checkedValue = alwaysWinSettings.isGeneralCapEnabled ?? false;
var retVal = (checkedValue == true);
return retVal;
}
function getBidCap(countyId) {
//Get the default bidcap from settings
var bidCap = alwaysWinSettings.bidCap;
var bidCap = alwaysWinSettings.generalCap;
const countyOversight = alwaysWinSettings.oversight.find(({ id }) => id === countyId);
if(countyFound(countyOversight)) {
bidCap = countyOversight.bidCap;
@ -195,6 +208,10 @@ function getCountyInfo(countyId){
}
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);
@ -315,15 +332,27 @@ function loginIfNeeded(){
return loginIsNeeded;
}
function renderOption(value, selectedValue) {
function renderOption(value, selectedValue, displayValue) {
if(displayValue == null || displayValue===undefined) {
displayValue = value;
}
var optionHtml = '<option value="'+ value +'"';
if(value == selectedValue) {
optionHtml += ' selected';
}
optionHtml += '>'+ value +'</option>';
optionHtml += '>'+ displayValue +'</option>';
return optionHtml;
}
function getCapPresidenceOptions(selectedAction) {
var optionsHtml = "";
optionsHtml += renderOption("row", selectedAction, "Row Cap");
optionsHtml += renderOption("general", selectedAction, "General Cap");
optionsHtml += renderOption("highest", selectedAction, "Highest Cap");
optionsHtml += renderOption("lowest", selectedAction, "Lowest Cap");
return optionsHtml;
}
function getOversightOptions(countyId, selectedAction) {
var optionsHtml = "";
optionsHtml += renderOption("win", selectedAction);
@ -357,6 +386,183 @@ function convertToOversightJson(countyInfoJson, action, isBidCapEnabled){
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) {
const Presidence_General = "general";
const Presidence_Row = "row";
const Presidence_Highest = "highest";
const Presidence_Lowest = "lowest";
const AppliesTo_All = "all";
const AppliesTo_None = "none";
const AppliesTo_Capped = "capped";
const AppliesTo_Uncapped = "uncapped";
const Oversight_Win = "win";
const Oversight_Tie = "tie";
const Oversight_Watch = "watch";
const Oversight_Ignore = "ignore";
const Capsource_Row = "row";
const Capsource_General = "general";
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 bidCapData = {};
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
@ -392,11 +598,65 @@ function injectOversight(countyId, action) {
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 == "row");
const settings_Presidence_GeneralCap = (settingsCapPresidence == "generl");
const settings_Presidence_HighestCap = (settingsCapPresidence == "highest");
const settings_Presidence_LowestCap = (settingsCapPresidence == "lowest");
const settingsGeneralCapAppliesTo = "capped" //[n,a,c,u]
const settings_GeneralCapAppliesTo_None = (settingsGeneralCapAppliesTo == "none")//None of the
const settings_GeneralCapAppliesTo_All = (settingsGeneralCapAppliesTo == "all")//All
const settings_GeneralCapAppliesTo_Capped = (settingsGeneralCapAppliesTo == "capped")//Capped Only
const settings_GeneralCapAppliesTo_Uncapped = (settingsGeneralCapAppliesTo == "uncapped")//UnCapped Only
const rowCapControlsShouldBeVisible = (action == "win" || action == "tie"); //TODO write logic to determine if the enable Bidcap checkbox and words should be visible
const rowCapCheckboxShouldBeVisible = (action == "win" || action == "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 capIsCurrentlyBeingAppliedToBid = countyJson.bid > Number(trueCap);
//End TODO
var priceDivHtml ='';
//priceDivHtml += ''+ countyJson.id +'';
priceDivHtml += '<label><input disabled type="checkbox" style="transform:scale(.5);" name="enableBidCap-'+countyId+'" />cap:<input disabled type="text" name="bidCap-'+ countyId +'" id="bidCap-'+ countyId +'" style="font-size:10px; width:40px; height:12px;" value="'+ countyJson.bidCap +'" /></label>';
priceDivHtml += ' | <label for="oversightAction-'+countyId+'">act:</label><select disabled name="oversightAction-'+ countyId +'" id="oversightAction-'+ countyId +'">'+ getOversightOptions(countyId, action) +'</select>';
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>';
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;
@ -412,19 +672,25 @@ jQuery(window).on('load',function() {
let maxSecondsBetweenReloads = alwaysWinSettings.maxSecondsBetweenReloads ?? 180;
let isReloadEnabled = alwaysWinSettings.isReloadEnabled ?? false;
let isAutoLoginEnabled = alwaysWinSettings.isAutoLoginEnabled ?? false;
let bidCap = alwaysWinSettings.bidCap ?? 500;
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");
//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="isReloadEnabled" '+ getCheckedValue("isReloadEnabled") +'/><label for="isReloadEnabled">Auto Refresh</label> | ';
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>';
newHtml += '<br />';
newHtml += '<button class="alwaysWinButton" id="alwaysWin-ntsmhf-save" type="button">Save</button><br />';
newHtml += '<label for="minSecondsBetweenReloads">Reload 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="bidCap">Don&apos;t bid more than</label>: <input id="bidCap" type="text" size="5" name="bidCap" value="'+ bidCap+'"/> per county<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">If a row and general cap are enabled then <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>';

Loading…
Cancel
Save