When you need to enter a data point, Trak will make your screen flash white (by default), which should make it both really obvious and unintrusive that you need to enter data.

Entering data can be done efficiently using a keyboard shortcut (by default Option+Space, but you can also change that), and Trak will even show you suggestions as you typed based on your previous activity.

As much as I think using Trak should be a great experience for TagTime users, it is currently very experimental (for all I know it might not even start properly on your computer), so please let me know if you have any feedback or questions, either on this thread or through the feedback form in Trak itself.

Hope you guys like it!

PS: Apologies for the fact that the dmg is quite big. I will try to make it smaller in the future, but this is unfortunately due to important libraries that I am using, such as PySide.

PPS: Trak might take a while to start initially, give it a second before giving up.

16.03.06 Sun 3:05:21.678 PM _main[46266]: Referenced from: /Volumes/Trak/Trak.app/Contents/Resources/lib/python3.4/lib-dynload/PySide/QtCore.so
16.03.06 Sun 3:05:21.678 PM _main[46266]: Reason: image not found

Hopefully the hacky workaround I used will do the trick (I double checked with dtruss and I think it should). Let me know if you still can’t run it (especially if the error changed)

Oh, one important thing that I forgot to mention: multiple tags (‘tag1,tag2’) are largely unsupported (though they are high on my priority list) except for the beeminder integration which does split tags on commas.

Ok I think I fixed this one too. Just tried on another macbook than my own (something I should have done a while ago) and it seemed to run properly. Can you try now (same link as before)?

Alright, good. It’s saying 1, not -1, right (if it’s showing a negative number that’s certainly a problem)?

You can enter things either by clicking on the empty entry in the main ui (a text box will appear), or by pressing the global shortcut, which will show an edit dialog (see settings, by default it should be option+space - note that it might conflict with software like Alfred if they are set up with the same shortcut, so this is definitely a setting you should look at).

Anyway, feedback taken: should be more intuitive how to edit things in the beginning, and maybe should show that notification less aggressively.

Ok, it’s looking good now. Not sure why I couldn’t get the edit dialog to appear before.

Any chance of getting this on the universal ping schedule? It will be really hard for me to transition to this no matter how good it gets if I can’t use both simultaneously for a while.

my $IA = 16807; # constant used for RNG (see p37 of Simulation by Ross)
my $IM = 2147483647; # constant used for RNG (2^31-1)
my $URPING = 1184083200; # ur-ping, ie, the birth of timepie/tagtime!
# $seed is a global variable that is really the state of the RNG
$seed = $initseed = 666;
$gap = 45*60; # 45 minutes between pings on average

And some helper functions:

# Return a random integer in [1,$IM-1]; changes $seed, ie, RNG state
# (This is ran0 from Numerical Recipes and has a period of ~2 billion)
sub ran0 { return $seed = $IA*$seed % $IM; }
# Return a U(0,1) random number
sub ran01 { return ran0()/$IM; }
# Return random number drawn from an exponential distribution with mean $gap
sub exprand { return -1 * $gap * log(ran01()); }
# Round to nearest integer
sub round1 { my($x) = @_; return int($x + .5 * ($x <=> 0)); }

Then define a function prevping that takes the current unixtime and returns the unixtime of the previous ping according to the universal ping schedule. Once you have that you can keep calling nextping() with the timestamp of the last ping to get the time of the next ping.

# Take previous ping time, return random next ping time (unixtime)
# NB: this has the side effect of changing the RNG state ($seed)
# and so should only be called once per next ping to calculate,
# after calling prevping.
sub nextping { my($prev)=@_; return max($prev+1,round1($prev+exprand())); }
# Compute the last scheduled ping time before time t
sub prevping {
my($t) = @_;
$seed = $initseed;
# Starting at the beginning of time, walk forward computing next pings
# until the next ping is >= t.
my $nxtping = $URPING;
my $lstping = $nxtping;
my $lstseed = $seed;
while($nxtping < $t) {
$lstping = $nxtping;
$lstseed = $seed;
$nxtping = nextping($nxtping);
}
$seed = $lstseed;
return $lstping;
}

For posterity, a totally different approach for a different universal ping schedule

Alice Monday (@alice) and I came up with this together but we’ve never actually used this.

The advantage of this version is you could throw away all the fancy math and it would make sense to anyone how and why it works. The disadvantage is it’s more computationally intensive. Also it requires picking a kind of arbitrary parameter for the granularity – how far apart pings in principle can be. I’d suggest .125 seconds since that’s a safe lower bound on human reaction time. (I think the only way this matters is if you want unbiased data on how much time you spend answering TagTime pings.)

Also let’s call an eighth of a second an octant even though that’s sort of an abuse of terminology. We can get the current unixtime measured in octants by multiplying normal unixtime by 8. Or if you get unixtime in milliseconds, multiply it by 8/1000.

On to this alternate algorithm for a different universal ping schedule:

Every single unixtime (in octants) either has a ping or not. The probability of a ping is just 1/(45*60*8) — the denominator being the number of octants in 45 minutes. To make it universal you use the unixtime itself as the seed for the RNG for deciding if that octant has a ping. So, using the ran0 function above, unixtime t has a ping if:

IA * t % IM / IM < 1/(45*60*8)

i.e.,

16807 * t % 2147483647 < 99421

So you can start computing it at any time without worrying about history at all. Of course you don’t want to be running a loop doing a calculation 8 times per second so you walk forward, checking each unixtime (measured in octants) with the above inequality till you find the next one a ping will happen at (on average that means checking the inequality 21,600 times) and just sleep till then.

On reflection, I think it’s inferior to the mathy approach. For one thing, I don’t know if feeding very similar seeds to the RNG spoils it. Seems like it might.

PS: The current universal ping schedule artificially pushes pings forward to ensure that they’re always at least 1 second apart. So probably this version could just do seconds instead of eighths of seconds. Which maybe makes it computationally no big deal. Question remains about whether similar seeds spoils the RNG.

UPDATE: Similar seeds totally does spoil the RNG so forget the idea of using current unixtime as the seed. We could salvage this approach by starting at the dawn of (tag)time and walking forward. We’d only have to do that once when first launching the app.