jeff 9/2/2026 2:13:52 PM | The short version:
It's a good idea.
In the previous and (even) most recent program versions, that wasn't an option - because the underlying framework/source code designed to do that did not exist.
However, recent code changes I've been quietly making under the hood DOES make that an option - because the underlying framework now exists (even though I created that framework for a completely different purpose.)
I think I can add an Enhanced Setting option to toggle display of Workouts and Running Lines in chronological order ON and OFF:
When ON - Workouts and Running Lines will display in chronological order (in the running lines area.)
When OFF - Workouts and Running Lines will display separately - with Running Lines above and Workouts below.
The long version:
One of the (many) things I've been quietly working on is program execution speed.
Dating back to the very first downloadable data files I used (Brisnet mid to late 1980's) dates for running lines and workouts have always been formatted as 8 character string text:
"YYYYMMDD"
One of the slowest operations a CPU can perform is evaluating string data.
This is the response from Google AI after asking the question "why does it take a CPU so much time to evaluate string data types?"
It takes a CPU more time to evaluate strings because text data has a variable length, uses complex character encodings, and requires byte-by-byte comparisons instead of instant single-cycle math.
Each set of 8 character string date text has three parts: Year, Month, and Day of Month.
As a result, during a Calc Races or DBBuild, the CPU doesn't perform one string evaluation every time it encounters an 8 character date string:
It has to stop and perform three separate string evaluations:
1. Parse the Year 2. Parse the Month 3. Parse the Day of Month
And from there, it has to perform a fourth operation: Assemble the individual parts into a Date variable.
Think of the number of horses entered on a typical race card (60 to 90?) Multiply that by the number of combined running lines and workouts (15 to 20? and add one more 8 character date string for today's race date.)
Multiply that by 4 -- the number of operations needed to convert each 8 character date string to an actual Date Variable.
But wait, there's more. You also need to calculate the difference in days between today's race date and each of the past race dates for running lines and workouts.
There are a LOT of operations that need to be performed when it comes to Dates alone.
Back in the mid to late 1980's I literally had no idea how much of a bottleneck those 8 character date strings were creating.
However, by the mid 1990's I had a very good idea.
A few months ago I decided to do something about it.
I identified the places in JCapper source code where 8 character date strings are concentrated the most - and started there:
1. I created a series of Arrays to contain actual Dates: RaceDates() WoDates() HorseDates() HorseDatesSorted()
RaceDays() WoDays() HorseDays() HorseDaysSorted()
2. I wrote new code that executes once only at the point in the program where data for each horse is read from the .JCP file.
The RaceDates() Array is populated with today's race date and the dates of the most recent 10 running lines.
The WoDates() Array is populated with the dates of the most recent 10 workouts.
The HorseDates() Array is populated with today's race date, the dates of the most recent 10 running lines, and the dates of the most recent 10 workouts.
The HorseDatesSorted() Array is populated with today's race date, the dates of the most recent 10 running lines, and the dates of the most recent 10 workouts -- sorted in Chronological Order.
Fyi, the HorseDatesSorted() Array is the needed framework piece that needed to be created in order to display Works and Running Lines in chronological order.
The RaceDays(), WoDays(), HorseDays(), and HorseDaysSorted() Arrays are populated once only immediately after the Dates Arrays - but instead of dates they contain the number of days between today's Race Date and each of the Dates (Workout or Running Line) from the horse's past performance record.
The above Arrays have global scope throughout the JCapper program. They are populated once only for each horse and can be accessed from any part of the program - including the PPs Generator.
That means:
1. Workouts and Running Lines can be displayed vertically in chronological order.
2. Execution Speed for parsing dates is measurably faster because the 8 character date strings for each horse only need be processed once.
Afterwards, the Arrays can be accessed directly as needed. Accessing the Arrays directly is significantly faster than parsing an 8 character date string.
Right now as I type this, I've been able to shave a few seconds off the time it takes to run a SQL Calc Races and/or SQL DBBuild.
In all honesty, I wish I had done it that way when I first started creating the program. (It would have been significantly faster from the word go.)
Dates aren't the only bottleneck.
There are others: Names for Rider, Trainer, Owner, Factors, Preset Filter Codes, Dynamic Filter Codes, Track Codes, etc. -- and for crying out loud the Angles String.
For max execution speed each of those should be evaluated using a unique number stored in a table - preferably a long integer.
Again, looking back I wish I had done it that way. Had I done so the program would be significantly faster.
Going forward, as I implement the Dates and Days Arrays (and other execution speed rewrites) in more and more places in JCapper source code:
I should be able to reduce the amount of time it takes to run a SQL Calc Races and/or SQL DBBuild significantly.
-jp .
|