Tune Reminder

We’re going to Newfoundland later this year, and as a result I have a list of tunes I’d really like to learn before I get there, and I need to brush up on the ones I already know. (The sad truth is there isn’t a lot of chance in Michigan to practice many of these tunes with other musicians.)

Years ago I wrote a Perl 6 script to help me track what I needed to practice. I meant to make it use spaced repetition, but the truth is I got so caught up using Niecza and GTK# to implement a simple GUI interface for the program I never got around to actually adding the spaced repetition part. I used it for a bit, and then it fell into disrepair.

Well, I’ve dusted off the repo it was in and added a new script which attempts to do an approximation of actual spaced repitition. And it was beautifully simple to write, barring a small bug in the Mix class that lizmat++ fixed before I could even break out the rakudo source.

The first slightly tricky bit is initializing the record of how you’re doing on each team. I wanted it to be able to handle the case where you’re running the code for the first time and have no records yet, and the case where there have been new tunes added. Each tune gets a level between 0 and 5.

my @status;
if $status-database.IO.e {
    my $file = from-json($status-database.IO.slurp);
    @status = @$file, 0 xx ($tunes.GetNumberTunes - @$file);
} else {
    @status = 0 xx $tunes.GetNumberTunes;

I used the JSON::Tiny module to handle I/O of the records, and initialize tunes not seen before with 0.

The main loop of the code is very straightforward:

loop {
    my $mix = @status.kv.map(-> $tune, $status { $tune => 1 / 2 ** $status }).Mix;
    my $tune = $mix.roll;
    say $tunes.GetTuneName($tune);
    given prompt "Know / Don't Know / Quit: " {
        when "q" | "Q" { last; }
        when "k" | "K" { @status[$tune] = (@status[$tune] + 1) min 5 }
        when "d" | "D" { @status[$tune] = (@status[$tune] - 1) max 0 }
    say "";

First I create a Mix based on the each tune’s status. The idea is that the higher the status level for the tune, the less likely you are to be prodded about it. Mix.roll is used to choose a random tunes with those weights taken into account. Then we print the name of the tune and use a simple combination of given and prompt to record how you did. (Note that this version doesn’t have any error checking here!)

Once you’ve hit “q” to exit the loop, the final line just records changes to the tune status file:

spurt($status-database, to-json($@status));

All-in-all, quite easy to code, and I’m already using it to help direct my practice!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: