Feb 12 2009

Why I switched to Git

I love it when someone else writes what I’ve been meaning to write, so I don’t have to write it.

This article covers the reasons why I switched from mercurial to git, about as well as he could possibly hope to without consulting me, reading my mind, or being me. It’s a bit creepy.

He explains it very well (probably better than I would) and has more insight into the technical details than I do.

While we’re on the subject, you should all go read git for computer scientists so you can think like a git. If you already have a CS background, it’s quite painless I assure you.


Jul 30 2008

gedtag

Have you ever tried to import aunt Millie’s n-thousand-person GEDCOM into your database? You either ended up with a reeking mess of a database, gave up and restored from a backup, or went insane trying to clean up the mess. Believe me, I know. And my family GEDCOMs are fairly well-behaved. But then there’s always Ancestral File or online generated GEDCOMs.

This is no laughing matter. In fact, it has been the single most debilitating roadblock to me doing any real genealogy since I got the bug as a teenager.

I think I finally have a way to tame the beast. It’s not a magic bullet—there will still be a lot of mind-numbing match/merge. But it will maintain order and the integrity of the database.

First, start with a clean slate. If you have an existing database, export it to GEDCOM and make a new database. This step isn’t strictly necessary but keeps things ultra clean. If you’re afraid you’ll lose information in the export/import, you need a different genealogy program.

Now, sort your GEDCOMs to import by their importance and reliability. Your original database export probably comes near the top of this list, although not necessarily. Write this down. In fact, write everything down when doing anything in genealogy.

Now, take that first GEDCOM and run it through my magic filter. This will add REFN tags to your GEDCOM that look something like this: hans@fugal.net,2008-07-30:foo.ged/INDI/I1. This tag tells you the submitter’s email (or name), the date in the GEDCOM file (or today’s date), the name of the original GEDCOM file, and the identifying information for this particular record. In short, it keeps track of where that record came from. It will show up in PAF as the custom ID, and likely in other software in a similar manner.

Now import the GEDCOM. In PAF, there is an option on import to reuse RINs. Uncheck this option. The import screen tells you that highest RIN currently used. Take note of this RIN. Now every record in the import will have a RIN above this RIN. The RIN is easier to use in match and merge (it’s right there, you don’t have to dig for it), so the tags we added are for posterity’s sake.

Now, do the match and merge. Did you know that PAF has the ability to match and merge based on the _UID tags it spits out in GEDCOMs? That means if this GEDCOM and the GEDCOM(s) you’ve already imported have a common ancestor, the universally unique IDs will match, and you know without a doubt that someone thought they were the same person already. You can breeze through these merges with confidence that you won’t merge people you shouldn’t. Likewise there is an AFN match and merge, which is almost as trustworthy. (I’m a bit paranoid so I always double-check anything coming from Ancestral File. Maybe it’s because there are about 5 versions of me in Ancestral File, most of which can’t even spell my name right.) Finally, go through the other options (name, soundex) and do a thorough match/merge.

Now, go through all the remaining RINs greater than the RIN you noted earlier. These are the new people in your database. Get to know them. See where they sit in the pedigree. Read the notes. Make sure they meet your quality standards. Add sources if you know of them. Make notes of missing information, questionable stuff to research, etc. You should have a whole truckload of research tasks to do after this import—and some of them you should do before the next import (you’ll recognize these if you take the time to think of them and write them down). Actually you should do that with every person you merge in the previous step as well, since they will merge into lower RINs. Don’t hit that merge button until you’ve done the quality check!

After weeks, months, or years of doing this on Sunday afternoon, you will have a meticulous database that works for you. You will have laid a solid foundation which will impower your future research efforts. You will not be sorry.


Jul 9 2008

k20

I finished the promised K-20 meter. I imaginatively called it k20, and you can find it at http://hans.fugal.net/src/k20. Here’s a screenshot:

k20 screenshot

From left to right, read average (VU), peak (instantaneous with 26 dB / 3 sec
falloff), maximum peak, and overs.

This is pure unadulterated printf() abuse. No ncurses. Not that I have
anything against ncurses, just that I’m lazy. Of course you need an ANSI
capable terminal, but I’m sure you can find one lying around.


Jul 9 2008

opg ftw

Few things about programming (in most languages) are less enjoyable than
writing option parsing code. On the other hand, few things are more irritating
to users than no -h and no options where options are needed (or
underdeveloped option parsers). In few languages is it more painful to do
option parsing than it is in C.

So I did what any sane lunatic would do. I wrote an option parser generator. I think it’s quite nice. This input:

usage: foo [options] other stuff
-f --foo          bool     Short name, long name, type, help text.
-b --bar=name     char*    This has a required string argument.
-z --baz=decibels int?     Optional integer argument
-q --quux=MACH    float    char*, int, and float are the recognized types

Any line not starting with a dash is copied into the help message verbatim.

becomes this output (a header and source file):

/* This file is automatically generated by opg */
#ifndef _OPG_H
#define _OPG_H

struct options {
    int   f; /* foo */
    char* b; /* bar */
    int   z; /* baz */
    float q; /* quux */
};

/* Print usage and exit(1) */
void usage(void);

/* Parse options, populate opts, adjust argc/argv */
void parse_options(int *argc, char * const *argv, struct options *opts);

#endif

/* This file is automatically generated by opg */
#include "opts.h"

...

void usage(void)
{
    puts("usage: foo [options] other stuff");
    puts("  -f  --foo             Short name, long name, type, help text.");
    puts("  -b  --bar=name        This has a required string argument.");
    puts("  -z  --baz[=decibels]  Optional integer argument");
    puts("  -q  --quux=MACH       char*, int, and float are the recognized types");
    puts("");
    puts("Any line not starting with a dash is copied to the help message verbatim.");

    exit(1);
}

void parse_options(int *argc, char * const *argv, struct options *opts)
{
    ...
}

http://hans.fugal.net/src/opg. Enjoy.


Feb 28 2008

Simple RSS

Have you ever thrown together a simple static webpage, only to find down the road that you want to add an RSS feed? What are your options? Maintain an ugly XML file by hand, or migrate to a big slow messy CMS. Yeah, no fun.

Sars is a simple RSS domain specific language. This:

# This is a YAML stream (http://yaml.org) but you don't need to know much YAML
# to get the hang of it.
# There are multiple "documents". The first document is the channel information:
---
title: Foo News Feed
link: http://example.com/foo/
description: News for the Foo Project
webmaster: you@example.com

# The second and subsequent documents are items. The first line is the title,
# the second line is the date, and the rest is the item description (Markdown).
# Because line endings are important, don't forget the pipe character.
--- |
Really Exciting Title
2/28/08 12:00
This is where I pontificate
about the really exciting fish
that is sitting on my plate.

Here's a [download link](http://example.com/foo/foo-1.0.tar.gz).

--- |
Another Item
2/28/08 12:04
You know, it doesn't really matter what order you put them in, since they each
have dates.

becomes this:

<?xml version="1.0"?>
<rss version="2.0">
<channel>
    <title>Foo News Feed</title>
    <link>http://example.com/foo/</link>
    <description>News for the Foo Project</description>
    <lastBuildDate>Thu, 28 Feb 2008 12:07:32 -0700</lastBuildDate>
    <generator>yaml2rss</generator>
    <webMaster></webMaster>

    <item>
        <title>Really Exciting Title</title>
        <description>&lt;p&gt;This is where I pontificate
about the really exciting fish
that is sitting on my plate.&lt;/p&gt;

&lt;p&gt;Here's a &lt;a href=&quot;http://example.com/foo/foo-1.0.tar.gz&quot;&gt;download link&lt;/a&gt;.&lt;/p&gt;</description>
        <pubDate>Thu, 28 Feb 2008 12:00:00 -0700</pubDate>
        <guid>http://example.com/foo//2008-02-28T12:00:00-07:00</guid>
    </item>

    <item>
        <title>Another Item</title>
        <description>&lt;p&gt;You know, it doesn't really matter what order you put them in, since they each
have dates.&lt;/p&gt;</description>
        <pubDate>Thu, 28 Feb 2008 12:04:00 -0700</pubDate>
        <guid>http://example.com/foo//2008-02-28T12:04:00-07:00</guid>
    </item>

</channel>
</rss>

Any questions?


Feb 28 2008

Crème Rappel v2.2

I’ve released yet again. Go to the web page for the details. Now Crème Rappel has its own RSS feed so I’ll shut up about here now.


Aug 26 2006

sourdough calculator 0.2

My sourdough
calculator
had a
major bug in the calculations. If you followed its instructions you got much
higher hydration than you asked for. e.g. if you asked for 68% hydration at 20%
starter inoculation, you got a dough that was 74% hydration. Oops. It’s been
fixed and can be downloaded at the same
place
. Other changes include different
defaults (500g 68% hydration loaf with 20% start) and volume measurements for
the scale-deprived.


Jun 21 2006

mg

My body is going on a diet (not me, but that’s another post), but we all know
it’s no fun to go on a diet unless you get a nifty digital scale and make cool
graphs of your progress. Over on the left you’ll see my cool graph which I
generate with a small ruby script (less than 60 LOC) and even smaller shell
script. The use case is simple. Every day after weighing myself I do simply
this:

mg $my_weight_today

You too can make cool graphs if you mosey on over to my src page.


Jun 5 2006

Constructors, coercion and casting, oh my!

This little bit of C++ trivia I may have known once but had forgotten. If you
have the appropriate constructor, the compiler will happily coerce for you:

class Foo
{
public:
Foo(int);
int i;
};

int bar(Foo f)
{
return f.i;
}

int main(void)
{
return bar(42);
}

You can also explicitly cast, which is useful when you are feeling explicit, or
want to cast to a subclass for polymorphic reasons.


May 24 2006

Summer of Code 2006

It’s official! I am one of the recipients of Google’s Summer of Code grant.
That means I get paid $4500 to improve Ardour according
to my proposal over the summer. Combined with the GAANN fellowship I’ve
received this means I can spend most of the time this summer writing code for
Ardour and studying for quals.

My proposal was to modify Ardour so that plugins can be applied to regions
instead of just tracks, both for realtime processing and bounced to disk. This
is a feature I have sorely missed in Ardour, as it is an important tool for
making electronic music and musique concrete efficiently. The other half is to
add undo/redo serialization of the current undo system to allow unlimited undo
across program instances.

I’m really excited for this opportunity. It will be my first serious
involvement with a big and important open source project as a developer. I’ve
often told myself I needed to get involved with one, and now I have an ideal
opportunity to do just that.

There are two other SoC recipients for Ardour. One is adding basic MIDI recording and playback, and the other is doing a Windows port.