Another Pass at Lineup Generator


Updated Apr 26th, 2023

Season 2:

Allow players to be locked and benched in the UI.

Done by position instead of by single player list. Single player list may be better.

A lock for a QB, TE or DST, is a bit easier. A lock for a flex player, or a single POS with multiple allowed, needs to be handled a little differently to eliminate the chance for duplicates.

Implementing this feature made me see why live state in React could be helpful

Rework Conditions Met Logic

Since we are looking Through so many iterations, efficiency is key.

The order of operations on conditional checks need to make sense and staggering in sequential order may help improve efficiency. You don’t even need to check if it’s under the salary cap if there’s duplicates and you definitely don’t even need to compute a total. If either of the above statements are not true.

Since Implementing the sit/starts feature and the worker the loop has slowed down.

Note on “show message” function:

If the loop is blocking: The show message should be checked inside of the loop.

If the loop is non-blocking: The function showMessage is after the loop and since the loop is currently blocking, the showMessage function doesn’t run until the loop stops. The conditonal check in the showMessage function is unnnecessary since it is the same that checks if the loop should stop.

Automated Data Gathering

Made the data updated process be a lot smoother, using node script and macros in Excel to automatically generating Excel files using node. The process of pulling the data needs is much tighter.

Better Folder Structure

The data definitely needs to live in its own file. Moving functions to a different file required running the project on live server, which took away some ease for me so I scrapped the idea. When the web worker was implemented, this also requires a server, I am tempted to try again to let the different non-captain slates share functions. Still not sure how much this is necessary because I typically just make changes to the “main.js” file and if there are more than a simple change I can copy/paste into “early.js” and “late.js” and update the data source file name.

Code split attempt notes:

Main purpose was to see if I split into smaller functions and try to run loop outside of main thread to make non-blocking. Uses modules to split up code which makes it easier to read/update/maintain/reuse code. Seemed slower although not 100%. Modules needs to run on server (using liveserver before deplyment). This effects speed. Speed Test need to use the same rows of source data

The purpose of refactoring was for organization but really to make the calculations async so it doesn’t lock up the browser

A Look Around

$10 a month gets you access to Rotowire optimizer, (Daily Fantasy Fuel is another great site and free).

Can choose fantasy site, slate, projection source # of lineups

Says due to DK guidelines must perform at least two actions.

Advanced Features here: Liking (increase projected points by 20%), locking, excluding, stacks, projections modes;, custom salaries, custom player pools, exclude entire teams, exclude entire games, export to excel or CSV, Save lineup, get email and text alerts for players in lineup.

People in the YouTube comments were knocking it that it was not a randomizer but linked to projections. People want 150 lineups from a chosen player pool based on chosen player and exposure percentages.

First Pass at V2

Started October 18th 2021. After using it for the first 5 of weeks of the season, I was noticing that I was getting duplicates when I really tried to push the generator to get me the highest possible score. (I think it’s pretty interesting that I wasn’t getting duplicates until I was in the very highest of points threshold).

I first would move was to move the data into a separate file. I’m kind of embarrassed that how long it took me to do this. I kept getting problems with the import export syntax or even the old common.js syntax. Turns out as long as there’s a script tag in the main HTML file I don’t even need to bother with any exporter import syntax It’s available as a global variable.

Next up was to just start building out some logic and I really wanted to focus on no duplicates first. I accomplished this by creating an array of the pool of players that should be available to that position. So for the nine positions there really is nine arrays to choose from. So I had to filter the main data source into the position arrays. Certain positions like the quarterback the defense and the tight end are simple because you’re not pulling multiple players from the same pool. The flex positions probably the hardest because you need to grab a bunch of positions from the main data source and then also filter out all of the previously selected players.

I was running into issues and at first I thought it was because the original Ray has values that are in a string but there’s a bunch of white space. So my first step was to actually create a trimmed array from that master array. This was not the source of the problem.

I realized that the filter logic For multiple things was wrong. Filtering out a single thing was pretty easy but one side needed to filter out multiple things, the logic broke down.

I fixed it by using double ampersand instead of the pipes, essentially saying “a player who’s name is not this guy and player’s name is not this name.” There’s really two things here The first being the and versus the or. The second thing being to actually reference the parameter. Kind of tough to describe verbally.

I was also able to time the function so I know how long it took to cycle through. This is cool because I can kind of gauge the max number of lineups to have like a 3 second time out. Anything more than 3 seconds is really pushing it. I did 2 million lineups in 12 seconds before time out but this is probably not good for you know production. I also added this value to the alert.

One of the things that I noticed is I was running a ton of console logs while I’m trying to figure out what’s going on. These console logs caused a ginormous slowdown. Once I removed it all except for the line that said how long it took both in time and number of lineups the thing became very fast. Other fast is relative because although a half a million lineups in 3 seconds sounds like a lot I’m pretty sure that’s painfully slow in the world of programming.

One of the other things I ran into today was just variable scope. I was originally trying to like break everything down into individual functions to compartmentalize everything and keep the handle click function very lean. I was able to keep the handle click function very lean but the it runs one gigantic function. I have to take another stab at breaking this down further.

Note: a day later it wasn’t just variable scope as much as function chaining, meaning when a function is finished calling the next function and passing it the necessary data. For example, after creating the lineup with no duplicates calling the sumAndCheck() function and passing it the lineup array.

Export HTML table to CSV

There is a dcode video and this article here.

XLSX Package

Download the files manually to get in the folder. Run the scripts that does the following.

Open the DK Salary File and save workbook as xlsx file. Remove unneeded columns, change column headings.

Create a new “all” tab

Move projections CSV data into separate worksheet in new Excel workbook.

Add necessary columns to have all projections in column L

Copy all data from the projections sheets into the all tab, (possible to only copy rows where projection is over minimum of 4?).

Add VLookup formula to each row in salary data tab depending on how many rows are in the all tab

Clean up defenses, name-fixes with if statement?


Update file in project and redeploy.

Object Property Names Can Be In Quotes

If I turn off the prettier feature that is causing this it should work.

On the admin page I was uploading a file, pre-parsed and it was parsing it for me with the quotes. Good for updating on the go using mobile process to gather and clean data.

Admin page is a hidden page that take in a csv file upload and spits out raw JSON object I can copy and paste into my hosting provider’s file manager.

Combine Macros

There’s still some manually cleaning that needs to be done before parsing so although some of the macros should be combined parsing should be kept separate.

Combine “projections to L” and “create_All” Tab

Combine salary sheet and add VLookup macros

This is where we would clean data: dst and name fixes

Run Parse macro

Paste parsed data into project files, save, and drag files to host via ftp

Further Automation Opportunities

Download the files via web scraping?

Have a switch statement or an if/else statement For the defense on the DraftKings salary to match the fantasy pros format. Changing on the salary tab will allow it to only need to be updated in one place. This should be done in the node script.


We need a macro or script for the salary for captain mode slates. Essentially you need to delete all of the rows where the RosPos is captain.

Async Code

Ran code in a promise that resolved immediately and although that made the loop non-blocking the browser was still responsive. The code was “moved off the main thread” but still locks the page. As a test I created a button with alert and button cannot be clicked.

Code below the start of the loop was able to run though.

I realized that there is non-blocking and non-freezing. Running code below the loop code was simple, but the loop, whenever it ran was consuming the entire resources and locking the page.

Non-blocking while loop

Decent article here about how to turn your while loop into non-blocking code. Not really the answer I was looking for.

Web Workers Is The Solution


I think I can keep worker files in separate folders and reference with “/workers/worker.js” and if this works test if different slates can share the same worker files.

Article here that I sought out after realized, after moving a loop off the main thread to make it non-blocking, the loop still freezes the page.

Here is another article.

Show loading spinner while findLineup function runs in the background.

Two Approaches To Starts & Sits Functionality

Approach one is using select dropdowns and populate options dynamically with the players array filtered. Approach two is just a single player table or list with bench/start buttons to more manually control results.

Approach one notes:

Sit 1, sit 2, qb, rb1, rb2, wr1, wr2, wr3, te, flex, dst

The issue with this is since the state is not updated on the fly (with say an SPA using react), the select options can not be updated manually. So we cannot filter out the selected rb1 start from the options for the rb2 start.

What can be done instead is limit the number of start options to just the easier ones: QB, DST, TE, and one RB and one WR. By skipping the rb2, wr2, wr3, and flex positions you can achieve close the desired effect. By limiting the player pool, number of random lineups options, is dramatically reduced. BOOM.

dynamically pulling options for select is pretty easy. So is setting variables

The createRandomLineup function needs the selected values so if we define in handleclick then we need to pass into createRandomLineup. We can define array to pass. We may want to handle the starts and sits before going to the createRandomLineup because that runs in the loop so want to kep as many operations as possible out of there.

value of empty select is of type String, and empty string, but is not counted as anything or FALSE in ternary which makes our if statement easier in the createRandom

select options are sorted desc based on projected points. Maybe point in ABC order? Really a thing for the sits

Approach two notes:

We could skip the select/options approach for just a single player table or list with bench/start buttons to more manually control results, (for example, disable the player)? This may React. Clicking the button triggers a function, grey out the player, check to see if an array has items. Example 1: QB is clicked, gray out the QB/all QBs, see if there is an item in the startingQB array. If there is show an error if not then add. Example 2: WR is clicked, gray out the selected WR, see if there is an item in the WR1 array, if not then add to the startingWR1 array, if so then check the WR2 array, and so on.

I like this because we’re not duplicating very long lists of player arrays in select options. There’s one source of truth and the users can also see the projections We could also bring in the CPP color codes. There could be a bunch of buttons at the top of the table that allow you to sort and filter. Example show me only the tight ends sort by cost per player, lock the best one then hit generate.

Step 1: Need a list of players with lock and bench buttons (make filterable like DK)

Need to be able to unlock or unsit players without refreshing the page

Need a warning to prevent unlockable player (second qb or 4th running back)

When the button is selected the player needs to be removed from the base array

basearray, baseArryTrimmed, baseArrayTrimmedAndFiltered,

Benching should be easier than locking

locking multiple players, (all three wrs) may be more difficult than just one (QB, TE, DST)

Locking could be as easy as saying as pushing player objects into a “locked” array. The player pool for that position can have an if statement that says, if there is a player in the locked array, see if it is a quarterback. Could aslo have a lcoked or site array for each position or even rb1, rb2. For example, When locked button is hit check the position and if the postion is tight end check the tightEndLock array for an item. If there is already an item then see if the flexLock array is empty, if not then throw and error. If not put there. Setting the TE variable could just be

Should not need to add a new field in the player object like isBenched or isLocked. If so we can do this programmatically.

Displaying the Starts & Sits DropDown

-UI should be collapsible to keep the generate button flexible
-Need a chevron and close icons instead of a circle. Show or hide with display: none/block based on active class. The icons will need classes.
-Bring in custom icons so we don’t have to bring in font-awesome

Brad had both icons in a button with a class of toggle
.starts-sits__container .chevron {display: block}
.starts-sits__container .closeX {display: none} .closeX {display: block} .chevron {display: none}

I could have collapsible starts and sits or collapsible for each pos or both. If going for individual you need logic like the following:

const toggles = document.querySelectorAll(".faq-toggle")
toggles.forEach(toggle => {
  toggle.addEventListener("click", () => {

Similar Sites

Daily Fantasy Fuel

CSV Upload for Data

Some travel without laptop made me think about updating data on mobile. The node script and macros made me ditch these plans.

CSV upload via HTML for here. Wow wow wow.

Papaparse is cool too. Having trouble displaying as html, is it because keys are strings? Use site like and paste results into Siteground file manager.

Note: since implementing the node script and macros, data can be updated in 10 minutes and so updating via mobile phone is not worth it

Preferred to load data from UI

I can download data, conduct vlookup, cleanse data (naming difs, scratched players, etc.), and save to csv on phone

If I can upload csv file to use as data source I am golden, and can update with or without laptop!

going to try using CDN yt video “How to read CSV files in JS” by Excellence in Excel 7/3/21

A page refresh goes back to the original array? updatedArray stars empty so the

The data will not persist without a database or updating the source. If the upload prints the format to raw then we can paste to the source in siteground.

CSV Download for Users

I’m not sure how much this would help me I should do a test uploading a lineup from a CSV file.