Do Less: Unlimited After Derail

This is very similar to an earlier post, but I have a couple of extra constraints.

I have a bad habit of playing a little too much online chess. The site I use makes it very easy to get the total number of games played by a user, so I have a very simple script that copies from their API and posts to the Beeminder API for a “do less”-ish goal (not quite “do less” because it’s cumulative).

The problem: if I play 1 game too many, I might as well play another 10 (or 20 or 100) games! And then when I derail at midnight, I go right back to having my normal buffer. I’d like some incentive not to go way over.

Constraints:

  • I can only reliably track cumulative games played
  • Strong preference for making this automatic so I’m not tempted to weasel

Possible solutions I’ve considered:

  • If derails were instant, this would be perfectly solved! I’d get my derail buffer for today, and if I use that I’d have to pay again. I’ve seen some chatter (sorry, lost the links) that we don’t want instant derails because (1) it’s an extra setting, (2) goals where you can get out of the red, and (3) data entry errors, but I think this is a good use case for such an option.

  • The above linked post suggests adding fine print that the additional games will count for the next day. But because the data comes from the API, this is a little tricky.

  • Add an additional goal?

    I’m not sure exactly what. The following aren’t quite right:

    1. max number of games in a day (doesn’t account for accumulated buffer)
    2. track this goal but with 2x the daily limit (it seems hard to keep them in sync).

    Also, if I derail on this second goal I’d probably have the exact same problem :slight_smile:

    Again, I’d really like it to not be manual because I’m tempted to weasel here.

  • set my deadline to be in the evening.

    This is a poor approximation of the “instant derail” option but it gets me a little bit closer.

Would appreciate suggestions!

5 Likes

It seems like you aren’t really that worried about derailing, so might I suggest making the cost a far higher amount? I think if you solve the issue of not derailing at all in the first place, then you don’t have to worry about putting micromeasures in place.

(P.S. Do you think you could share that script? I’ve just started with chess and I’d love to be able to track my games as a do-more goal, haha!)

Given that you’re writing a custom script anyway, you can consider taking advantage of Beeminder’s charge API. You can define in code exactly the conditions in which you want to be charged (extra) money, and have your script apply them automatically.

For instance, perhaps you want to be charged an extra X dollars per game over the limit. So after you script posts its data to the Beeminder API, you might then request from the Beeminder API the goal data, and specifically the baremin field. If it’s negative, you’re in the red, and your script can call the charge endpoint to charge you -X times the baremin value.

This is overly simplistic: it will end up charging you over again each time it runs. So you’ll want it to store a log of how much it has charged you so far each day, and then each time it runs and would charge you, it first subtracts the amount it has already charged you that day.

This requires a bit of software development on your end—you need to implement something a bit more detailed than your current very simple script. But the amount of flexibility it gives you is unmatched: you have absolute control of all the details of when you’ll be charged, and how much.

1 Like

I wonder if there’s a way to manage this on IFTTT… if it was a “never-do” goal, it’d be easy: you could set up a trigger from your Beeminder graph to the charge recipe, and just charge yourself something for every game. But I’m not sure if you could make that conditional and say only after X number of datapoints added… I don’t think so, actually, but maybe this will spark an idea for someone else!

1 Like

It seems like you aren’t really that worried about derailing, so might I suggest making the cost a far higher amount? I think if you solve the issue of not derailing at all in the first place, then you don’t have to worry about putting micromeasures in place.

Yeah, I agree it would be better to avoid derailing at all. :slight_smile: But it’s easier not to derail if I think about it as “I’d have to pay $10 for 10 games of chess” vs. “I’d have to pay $10 for unlimited chess.”

I’ve also accidentally gone over (I don’t get immediate feedback when I’m at -1 game for the day), and my life would be much better if after that I said “eh, I should stop” instead of “might as well take advantage of the only time I can play unlimited games.”

(P.S. Do you think you could share that script? I’ve just started with chess and I’d love to be able to track my games as a do-more goal, haha!)

Sure! I’m on Lichess, not sure if Chess.com has a similar API. I’m concerned only about fast chess (bullet and blitz time controls), which I have a tendency to binge. (I’m thinking about a separate do-more for rapid or classical time controls).

The script runs in bash and depends on curl and jq. I store my auth token in the pass password manager.

GOAL=lichess-fast
GAMES=$(curl https://lichess.org/api/user/znewman01 | jq '.perfs.bullet.games + .perfs.blitz.games')
AUTH_TOKEN=$(pass show beeminder-auth-token)
curl \
   --data "auth_token=${AUTH_TOKEN}&value=${GAMES}" \
   "https://www.beeminder.com/api/v1/users/znewman01/goals/${GOAL}/datapoints.json"

I stick it in a systemd timer to run every hour.

1 Like

Thanks @shanaqui, @zzq for the ideas!

That seems to be exactly what I want – to make each game over the limit painful.

The fact that I’d have to keep some state around is a bit of a bummer, though not necessarily insurmountable. I’d be much happier if I could do this idempotently. One (terrible) workaround would be to use a dummy goal as a datastore. Even better if the API had some way to give charges an ID so a second charge would be rejected. (The fact that there’s a human in the loop before I actually pay money makes experimenting a lot less stressful!)

IFTTT is a good thing to consider, and I might think about moving my “copy over the number of games” bit over there anyway.

Maybe you could put the comment of the game ID in the datapoint, or something? Then you can retrieve the day’s datapoints and look at IDs?

1 Like

My first thoughts were along the lines of Nicky’s suggestion to do something with IFTTT.

Otherwise, are you using the “max buffer” feature that trims your buffer each day at the deadline? If not, you could make your goal have the earliest possible deadline a goal can have, have your mercy days (perhaps mercy units, in this case) set to 0 so that it recommits with no buffer, and then have your script continue adding it for the correct calendar day so that as soon as you play a game above your max, it derails and as soon as you play another game after that, it just derails instantly. One bummer with this is that if you derailed yesterday, you wouldn’t be able to play today. I think this would work and do what you want. I’d test it out, though!

That’s a great thought!

I’m thinking right now something like:

  • @zzq’s idea: after posting a new data point, get the goal and check baremin
  • if baremin < 0
    • plan to charge -baremin times X dollars
    • but check the prior datapoint: if you have a comment in that datapoint, subtract out the charge
    • then put a comment in the latest datapoint that I’ve charged $X today
    • then charge

The main downside is that I might wind up charging multiple times, but that should be rare (hopefully I’ll have stopped by that point).

This is starting to get a little much for a Bash script…and I think it’s really pushing it for IFTTT. I’ll let you know what I come up with.

2 Likes

Hey @znewman01, any update?

Update: Lichess API remains very easy to use! Beeminder API is also quite good. Bash is hard. :slight_smile:

My current attempt looks something like this; it’s not ready for prime time but you might find it inspiring. It almost works; part of the problem is that I only get to test it when I derail which only happens once every few weeks. With some manual futzing it’s fine for me right now so I’m probably going to keep making minor tweaks.

Happy to answer questions if you want to get it working, but no warranty!

5 Likes

Looks like you can get games from chess.com’s api with some munging:

curl https://api.chess.com/pub/player/$USER/stats | jq \
  '. | [.chess_blitz.record, .chess_rapid.record] | [.[].win, .[].loss, .[].draw] | add'

On an unrelated note, I stuck a simple version of this in the cloud running on a cron and it seems to work great! Thanks for the inspiration.

1 Like

Thanks so much for the scripts to fetch chess stats! I’ve added both Lichess and Chess.com to our list of candidate integrations at beeminder.consider.it if people want to vote them up!

2 Likes