We’ve got a buttload of gissues in our repo related to issues with ratcheting. Probably the biggest complaint (aside from weird corner cases that cause insta-derails… yipes!) is that for do more goals (actually, all non-do-less goals) we shift the road along the x-axis to accomplish the ratchet, which has the side effect of changing the dates of scheduled road changes in the future. Which sucks. It’s also the reason why autoratchet (and manual ratchet) don’t play nice with weekends off, and other frustrations as well.
So I’ve got a partial fix, but it’s still problematic, because 1) it doesn’t work well with flat spots, and 2) it’ll only give approximate results when there are scheduled rate changes upcoming in your road. But maybe those complaints are minor compared to the annoyance of the date-shifting in the current implementation?
So here’s how the updated algorithm works:
-
vcur
: current datapoint value (aggday-ed, gotten from bbrain) -
rcurd
: current daily rate -
yaw
: good side of the road (-1 => below, 1 => above) -
nbuf
: new buffer (in days)
From these params we calculate the newedge
of the road like this:
newedge = vcur - (nbuf-1)*rcurd.abs*yaw
Generally, to give you one day of buffer, we want to move the road to be exactly on your current datapoint. For zero days of buffer, you want the road to be one-daily-rate’s worth above your current datapoint. For two days of buffer, one-daily-rate’s worth below, etc. (Except by ‘above’ and ‘below’ I mean “in the yawly direction”, hence the business with multiplying by yaw
etc).
This works great when the road has a constant rate. You can just multiply rcurd
by the number of days (actually days less one, because… well, I’ll leave that as an exercise for the reader), and move the road so that it’s that far from the current datapoint.
If the rate changes, however, using the current daily rate is not quite fully correct. To do this perfectly accurately, we’d need to get daily rates for each of the days of buffer you want to keep, and add those up and move the road accordingly.
So if you currently had 8 days of buffer, and you wanted to keep only 3 of those days, but your rate doubled each day this coming week, starting with 1, then to do it fully correctly, the amount of buffer we’d want to give would be 1+2+4
.
Or more generally, assume we have function rate(date)
which returns the daily rate at the given date.
newedge = vcur - (rate(today) + rate(today+1) + rate(today+2))*yaw
This would solve all the problems with upcoming rate changes… though we would probably want to be draconian about only ratcheting roads / road segments where the dir and the sign of the road agreed, and the road was monotonic. Basically non-monotonic roads are the worst.
Now you say “But wait! what about flat roads??” You caught me. I still haven’t addressed the issue of flat roads. With a zero rate segment this all breaks down because when rcur=0
, then newedge == curedge
. This could potentially actually be considered a feature, not a bug? It would mean that autoratchet wouldn’t overwrite your weekends or other scheduled breaks, as the worse it could do is move the road to you current datapoint, and then it would continue along the flat spot from there.
With that in mind, here’s a totally raw brainstorm about different ways to deal with zero-rate segments + ratcheting.
option1:
So one take would be to leave it as is with no zero-rate special case. This would be nice for autoratcheters who also want to schedule breaks sometimes. A user on a flat spot wanting to throw away extra buffer would have to first remove the flat spot manually using the road editor or something. It might be better than making assumptions about what to do with the road otherwise. And if we had a nice tutorial or something about it, and did sensible UX things in the case that you can’t ratchet because you’re on a flat spot", it might be pretty OK?
option2:
We could sort of automatically help out with the above. So rather than just saying “you’re out of luck, go use the road editor”, we’d have a different interface for dealing with flat spots, maybe kind of like an un-break scheduler. If your current rate is zero then the only thing you can do is slide the end of the flat closer. Instead of saying
“You currently have 8 days of buffer. Adjust it so you have [FILL IN THE BLANK] days of buffer”,
we’d say something like
“Ooh, you’re on a flat spot. You have 10 days of flat. Adjust so you have [0-10] days of flat remaining.”
If you threw away the entire flat spot and still had buffer left over, you’d now be back in the regular case, and you could adjust by a certain number of days more. So it’d take two steps to clear a flat spot and move the road closer to you, but it might be simpler (in terms of code) and more clear how it’s going to work and what results you’ll wring. So if you were 8 units above the flat spot, and then had 10 days of flat, we’d make you throw away the 10 days of flat as an explicit first step to ratcheting… like a flat spot ratchet says: “you have 10 days of flat spot. how many days of flat would you like remaining?” and then you can enter between 0-10, and we adjust accordingly. And then if you wanted to ratchet to 0 days of buffer, for example, first you’d have to send flat spot to 0, then as a second step, now you’d have a non-zero daily rate and you’d be allowed to do a regular day-ly ratchet.
option three:
Combine day-ly ratcheting and flat-spot-sliding ratcheting programmatically through the magic of if-statements!
On the one hand it might seem relatively straightforward, but in practice it could get complex and weird, with like, checking for a flat spot, and then sliding, and then rechecking how many days of buffer you have now, and then day-ly ratcheting, and again checking how much buffer, and if there was lots of buffer and lots of weekends off, or something like that it could be real weird?
option four:
Maybe we could do some more limited version of ratcheting when there’s a flat segment. Like maybe you can only ratchet to a beemergency if you’re in a flat segment. We pick some amount (the average rate?, the upcoming rate?, as the user for an amount?) and move the road to be that far above your vcur. So on a flat your only option re ratcheting is “make me do something today” and then we ask you “how much” and you say 10, or whatever, and we make it so you now have to do 10, but the road going forward from today just remains the same.