API Question about fetching the values for the Beginning/End of Ak. Horizon

I’m trying to create some code to automate adding a specific day off per week or weekends, etc. through the API.

Am coming across the following n00b problem: I don’t know how to get the values for the centre of the road for the beginning and end of the Akrasia Horizon. I need this both to protect people (and myself) from “oopses”, but also so that I never run into the “you’re trying to make this week’s slope easier” problem.

This is a portion of what I have. (Much of this will change once it’s working, and then I’ll fix it to loop until the goal’s end date, rather than specifying each section manually. I’m just trying to get the framework right first.) What I’m trying to figure out is what belongs in place of the array for the two bolded lines? (I couldn’t find a way to fetch the value of the centre of the road today, which would have made inferring the rest easier… Though, my way would encounter problems if there were a rate change somewhere inside the Ak. Horizon, so I’m sure there’s something better.)

  $init = reset($road);
  $sect1 = array($yesterday,0,null);  // (You can ignore this. This is just a "cleaning up the graph's past" thing. It won't stay in the final version.)
  $akrasiaS = array($startToday,0,null); // Ak.Horizon Start    ( to leave the points between    
  $akrasiaE = array($inOneWeek,0,null); //    Ak.Horizon End        the akrasia horizon as-is   )

  $sect4 = array($inTwoWeeks,null,0);
  $sect5 = array($in15Days,null,$myRate);
  $sect6 = array($inThreeWeeks,null,0);
  $sect7 = array($in22Days,null,$myRate);
  $dial = end($road);

  try {
    $api->getGoalApi()->editGoal($goal->slug, array('roadall'=>json_encode(array($init,$sect1,$akrasiaS,$akrasiaE,$sect4,$sect5,$sect6,$sect7,$dial))));
  } catch (Exception $e) {
    return 1;
  return 0;


(Alternatively, is there a way to run the take-a-break feature through the api, without specifying anything about the pre-Akrasia Horizon values? I.e., something like “road dial” but leaving out the details for the whole road, which I think the road dial api function needs. (I should probably test whether that’s even right, now that I think about it.))

1 Like


Hmm… I’m unable to bold the lines I wanted to because it’s in the code block, but I meant for the following lines:

$akrasiaS = array($startToday,0,null); // Ak.Horizon Start ( to leave the points between
$akrasiaE = array($inOneWeek,0,null); // Ak.Horizon End the akrasia horizon as-is )

In other words, how do I get the value of the start of the akrasia horizon period as well as the end of the akrasia horizon period, so that I’m never messing up that portion of the graph?

1 Like

In my (still in-progress, honest!) implementation of perhaps the same thing, I’ve taken a naïve approach:

horizon = today + datetime.timedelta(weeks=1)

I’ve not done much in the way of testing yet, but we’ll see how it works out.

1 Like

I’m afraid I don’t get it. What api function does that run in order to get the value of the road for the respective times? (Sorry, I’m objectively terrible at this.)

1 Like

Sorry to take so long to jump in here! The line of code @dutchie posted is just setting the horizon as today plus one week. But @chipmanaged’s question is how to determine the values of the road at various points in time (such as today, or today plus one week). Here is python code to do that, given the full road matrix as returned by the roadall parameter for the Goal endpoint.

DIY    = 365.25      # this is what physicists use, eg, to define a light year
SID    = 86400       # seconds in a day

SECS = { 'y' : DIY*SID,     # Number of seconds in a year, month, etc
         'm' : DIY/12*SID,
         'w' : 7*SID,
         'd' : SID,
         'h' : 3600         }

siru = SECS[runits] # seconds in rate units

# Helper for roadfunc. Return the value of the segment of the YBR at time x, 
# given the start of the previous segment (tprev,vprev) and the rate r. 
# (Equivalently we could've used the start and end points of the segment, 
# (tprev,vprev) and (t,v), instead of the rate.)
def rseg(tprev, vprev, r, x): 
  if exprd and r*(x-tprev) > 230: return 1e100 # bugfix: math overflow
  return vprev*exp(r*(x-tprev)) if exprd else vprev+r*(x-tprev)

# Take a full road matrix and a time t; return value of the centerline at time t
def roadfunc(road, x):
  if   x<road[0][0]: return road[0][1] # in case you want values before road start
  for i in range(1, len(road)):
    if x<road[i][0]: return rseg(road[i-1][0], road[i-1][1], road[i][2]/siru, x)
  return road[-1][1]

So for example, once you have the above, you can see how much the yellow brick road expects you to do between today and the akrasia horizon with:

roadfunc(road, today+7*24*3600) - roadfunc(road, today)

Ah yes, sorry. I misinterpreted what was meant by “value”, and PHP code is too scary for me to read and understand.

Update! Turns out the API already had what you needed – rah and delta – but they were undocumented until now. Thanks again, @insti!

(Implementing roadfunc may still be worthwhile but if you just care about the values of the road today and at the akrasia horizon, the API gives you those directly. Well, almost directly. The road value today is curval + delta. The road value at the akrasia horizon is rah.)

It looks to me like the centre of the road for today isn’t necessarily
curval+delta, but curval-(delta*yaw). Does that make sense, or am I doing
something unnecessary?


That makes sense.
(yaw lets you know which side of the road is good.)

1 Like

How do you compute “today” in the code example? I mean, what hour / timezone should today be in to make this all work out?

1 Like

PST, I believe

Do you know what time, in PST? And are you sure it is PST and not Pacific Time (does it switch to PDT when Pacific Time switches to PDT, or does it stay PST even when Pacific Time isn’t observing it?).


Times in roads matrices get standardized internally to noon Eastern time, switching from EST => EDT with the calendar. This is legacy and I think that Danny might have mentioned something under the impression that we were using dates everywhere, which is not quite/yet true.

Does that help?


Thanks, I’ll check it out and get back to you.