feature creep

The original spec for today: Go out to Anna's. Run some cables.
Use case: Joey is in yurt. Joey has power, and even interwebs.

But this means parking the truck in the area where it got stuck the last two times. Ok, let's add in getting a load of gravel to fix that. Hmm, if we're going to get one load of gravel (over one ton already!), might as well get two...

Hmm, we didn't notice that unloading tons of gravel, for three people with shovels, is 95% of the planned work for today. Oh well, let's do it anyway...

Darn, that super-long ethernet cable that was part of the original plan doesn't work. No link at all, no lights on the cable tester. (Bisection shows the problem affects only half the cable.) At least the power cable worked. I guess that ethernet will have to be dealt with in version 2.0..

Posted
the case of the missing 's'

Ran into a freakish epiphany/gmail bug yesterday where gmails's "new" interface somehow ate the 's' key, preventing it from working in epiphany at all. Even after logging out of gmail.

If any readers of this blog have contacts inside the gmail team, I've filed Debian bug #501691 on epiphany with details about this scary situation.

Personally, a web that can eat 's' keys is not the web I want.

Posted
electric bike

I decided to get an eletric bike when my car died. Couldn't quite stomach buying a new gasoline vehicle at this point in time, didn't really feel like another used car, and the available eletric cars are still too new/expensive/hard to find. While there are some neat NEVs that are not too expensive, they're too limited to be worth my money, and eletric bikes fit into the same general niche. (So do eletric scooters, but I didn't want to spend that much money on an experiment..)

My first try was a disaster. I was thinking that a large cargo capacity would be a good thing, so I gravitated toward trikes. However, the one I tried turned out to be a lemon in several ways, and suffered a catastropic and dangerous controller burnout. So I learned that this eletric bike industry is pretty rough and ready with a lot of junk to avoid. I also learned that I don't enjoy riding trikes.

The second try was a R Martin LX1, which my dad had researched. I got it yesterday, and have ridden it some now, and I agree that it's a good one.

As a bike, it's well built, has a good back disc brake and decent front brake (will be better once I bring it to a bike shop to adjust it better), has a good derailer, and rides well. I'm no expert but it seems about as good as the bike I used to commute with, though the frame is a bit heavier. (IIRC, it was also at least $200 cheaper than that bike!)

On the eletric side, it has a relatively small and light lithium ion battery; the motor is mounted in the hub. It's strong enough to go up hills on its own if you really want it to, but you will end up pedaling to assist, which is good.

I'm undecided whether the six gears are enough ... Seems like I might want a faster gear, to be able to assist the motor more at high speed. I haven't wanted a lower gear yet, but I've not tried to do any hills without the motor's help.

The eletric controls are ok, but not perfect. I worry about accidentially twisting the throttle, although it has to be turned quite far to engage the motor.

Ideally, the pedal assist would turn the motor on exactly when you pedal, and porportionally to how hard. Instead, there'a a lag, and doesn't care how hard you pedal. This can present problems coming up to an intersection or other hazard, where pedal assist kicking in can unexpectedly be more speed than is needed. Seems a waste to have to brake to cut the assist off.

The motor is audible when accellerating, and especially complains when trying to get me up a hill on its own. At speed, or if given a human power assist, it's quieter than the chain, if not silent.

So there's room for improvement (and this would be a fun thing to do some hacking on to improve its response), but it's still a lot of fun. I'd forgotten how much I enjoy riding a bike and getting a nice workout. And it's especially nice to go up a hill pedaling only as hard as you like, to be able to accellerate quickly without standing on the pedals, and to be able to "coast" a long, long, way.

Posted
NC car curse, part 4

I'm getting to the point that I fear driving in North Carolina, because an exceptional percentage of car breakdowns happen to me there. The most recent one actually didn't happen in state, I'd just passed the TN border and was coming down the exceedingly twisty road to Shady Valley when I lost the engine on Mom's car.

About the time I gave up on letting it cool down and trying things, a white convertable pulled up and I got a lift down to Shady. Since this was a beautiful Sunday, the country store there had at least 500 motorcycles out front. I borrowed one of the bikers' cell phones, called a tow, and sat in a rocker on the porch and watched the insanity for an hour.

The good thing about driving old cars that sometimes break down is that you do get used to dealing with it. I actually enjoyed 95% of the incident.

Oddly, the car started without problems the next morning. Curse indeed.

Posted
relative dates in html

One of html's deficiencies is that it doesn't have a tag to mark up a date.

If html had such a tag, then browsers could display dates using your time zone, and in whatever format you like. Rather than in some random time zone, that is often not even shown, and some random format.

My fav way to see a date is as relative date, such as "two days ago". With a mouseover so I can see the exact, absolute date in the rare case I need it.

It's possible to combine some javascript with html, so that, if javascript is available, a nicely formatted relative date is displayed. And with no javascript, an plain old absolute date is shown. Perhaps the cleanest way to do it is using html like this, combined with javascript that fires on page load, parses the date and replaces it with something nicer:

<span class="date">Fri Oct 17 16:17:02 2008 -0400</span>

But you might want to avoid using the ugly machine-parseable date, since it will still display in any situation where javascript isn't available. To do that, I added an attribute containing the machine-parseable date. I chose to use the "title" attribute, so as a bonus you can hover over it to get a popup with the raw date.

<span class="date" title="Fri Oct 17 16:17:02 2008 -0400">Friday afternoon, October 17th</span>

Update: Happily, html5 adds a time tag. Unhappily, it needs the date in RFC 3339 format, which javascript can't parse with "new Date". So in order to use it, I include the javascript-parsable (also human-readable) date redundantly either inside the body of the tag, or in the title attribute.

<time datetime="2010-04-22T12:07:05.001-04:00">Thu, 22 Apr 2010 12:07:05 -0400</time>

<time datetime="2010-04-22T12:07:05.001-04:00" title="Thu, 22 Apr 2010 12:07:05 -0400" class="relativedate">at noon on Thursday, April 22nd, 2010</time>

So, relatively clean html out of the way, now we just need some javascript to munge in the relative dates. There are various examples out there. The best one, requires the prototype framework.

I try to stay away from javascript frameworks, since I'm not a javascript programmer, and since I dislike page loads pulling in thousands of lines of irrelevant code. So I came up with my own more bare metal implementation, which handles both types of html above.

You can see it in action on my website, or by enabling the relativedate plugin on your own ikiwiki.

(This code is in the public domain, but do note that I'm not a javascript programmer, really. Also, ikiwiki contains a newer (maintained) version.)


var dateElements;
window.onload = getDates;

function getDates() {
    dateElements = getElementsByClass('date');
    for (var i = 0; i < dateElements.length; i++) {
        var elt = dateElements[i];
        var title = elt.attributes.title;
        var d = new Date(title ? title.value : elt.innerHTML);
        if (! isNaN(d)) {
            dateElements[i].date=d;
            if (! title) {
                elt.title=elt.innerHTML;
            }
        }
    }

    showDates();
}

function showDates() {
    for (var i = 0; i < dateElements.length; i++) {
        var elt = dateElements[i];
        var d = elt.date;
        if (! isNaN(d)) {
            elt.innerHTML=relativeDate(d);
        }
    }
    setTimeout(showDates,30000); // keep updating every 30s
}

function getElementsByClass(cls, node, tag) {
        if (document.getElementsByClass)
                return document.getElementsByClass(cls, node, tag);
        if (! node) node = document;
        if (! tag) tag = '*';
        var ret = new Array();
        var pattern = new RegExp("(^|\\s)"+cls+"(\\s|$)");
        var els = node.getElementsByTagName(tag);
        for (i = 0; i < els.length; i++) {
                if ( pattern.test(els[i].className) ) {
                        ret.push(els[i]);
                }
        }
        return ret;
}

var timeUnits = new Array;
timeUnits['minute'] = 60;
timeUnits['hour'] = timeUnits['minute'] * 60;
timeUnits['day'] = timeUnits['hour'] * 24;
timeUnits['month'] = timeUnits['day'] * 30;
timeUnits['year'] = timeUnits['day'] * 364;
var timeUnitOrder = ['year', 'month', 'day', 'hour', 'minute'];

function relativeDate(date) {
    var now = new Date();
    var offset = date.getTime() - now.getTime();
    var seconds = Math.round(Math.abs(offset) / 1000);

    var ret = "";
    var shown = 0;
    for (i = 0; i < timeUnitOrder.length; i++) {
        var unit = timeUnitOrder[i];
        if (seconds >= timeUnits[unit]) {
            var num = Math.floor(seconds / timeUnits[unit]);
            seconds -= num * timeUnits[unit];
            if (ret)
                ret += "and ";
            ret += num + " " + unit + (num > 1 ? "s" : "") + " ";

            if (++shown == 2)
                break;
        }
        else if (shown)
            break;
    }

    if (! ret)
        ret = "less than a minute "

    return ret + (offset < 0 ? "ago" : "from now");
}

discussion

Posted
debhelper option parsing overhaul

I've been meaning to fix debhelper's option parsing code for a while (7 years?!), and finally got around to it with version 7.1.0, in experimental.

Now debhelper commands can define their own command-line options. This is especially useful for third-party commands that couldn't add new options before, without pestering or bribing me. (Bribes still happily accepted however.)

It's in experimental because I removed global support for a large number of lesser-used options. Some of these might be used by third-party debhelper commands -- if so, they will be broken by this change, and need to define those options themselves.

Also, it used to be possible to pass nonsensical options to a command, like "dh_strip --include-conffiles --no-restart-on-upgrade". To avoid breaking unknown numbers of packages that might do things like this, I've made debhelper start warning about such things. This warning will be converted to an error as soon as I dare.

Posted
anatomy of an atrocious announcement

Here are some tricks that you can use to ensure that your announcement to debian-devel-announce has maximal negative utility.

hide who's talking

Make sure that your announcement does not start off by making clear who's speaking. The announcement will have a From line with your name on it, and that's good enough. Everyone knows who you are, what groups you're a member of, and can guess what group you're speaking for ... or whether you're just speaking for yourself.

Throughout the annoucement, be use to use terms like "We plan", "let us describe", "we are considering", "This is where our proposal comes in.", etc.

Maybe in a footnote include a clue such as a mention of "the NM-Committee", but be sure to not sign the announcement with the name of any group or team or set of people, so that the reader is left guessing about who this "we" is all the way to the end and beyond.

(And hey, "cabal" is a fun word.)

weasel words

Scatter throughout the announcement some vaguely worded digs at things you disagree with. The key here is to make clear what you really mean, while providing enough plausible deniability that you can deny having said it later.

So you might say ...

Some time ago a few Developers thus went and pushed forward the "Debian Maintainer" status.

... Thus implying that this was a few malcontents who should be ignored. Sure, the whole project voted for this, and so you should be sure to allude to that vote somewhere else. Maybe in a different paragraph entirely, you could refer to "Debian Maintainers (DM) [GR-DM]". (It would be excessive to have that footnote refer to a bogus url like http://vote.debian.org/something.)

the big lie

Make sure that your announcement starts off all bright and cheery on the surface, with just a hint of deadly steel jaws underneath. Something like:

If you are an existing Debian Developer or Debian Maintainer, don't be afraid, we are not going to take anything away from you.

Natter on for many, many pages of trivilities, good ideas, bad ideas, half-baked ideas, conflicting acronyms, and useless footnotes. Then spring the trap:

In future this will be a list maintained by the NM-committee. At the time of migrating from the old to the new way, Ftpmaster will convert the existing DM-Upload-Allowed fields into that list, so there  should be no interruption in your ability to upload.

And ability to upload is all that matters. Who cares about the regression back to the tyranny of unix permissions? Who cares that DDs won't be able to decide when they trust a DM to upload their package, or that DMs won't be able to sign up quickly and easily, or that DMs will have to petition a disinterested committe to change anything?

Nothing will have changed, nothing will be taken away, nothing to see here, move along: The big lie.

Posted
anonymous git push to ikiwiki

So, ikiwiki keeps wikis in git. But until today, that's only meant that the wiki's owners can edit it via git. Everyone else was stuck using the web interface.

Wouldn't it be nice then if anyone could check out the wiki source, modify it, and push it back? Now you can!

git clone git://git.ikiwiki.info/
cd git.ikiwiki.info
vim doc/sandbox.mdwn
git commit -a -m "I'm in your git, editing your wiki."
git push

The secret sauce, that makes this not a recipe for disaster but just a nice feature, is that ikiwiki checks each change as it's pushed in, and rejects any changes that couldn't be made to the wiki with a web browser.

So if you use ikiwiki for a wiki, you might want to turn on untrusted git push.

Posted
I voted

I voted early because Sullivan County, TN is phasing in new voting machines this election. On election day, they will use the old touch screen system, while early voters get to test the "new" paper system.

The new system is sure to please fans of paper. However, it has two flaws that were obvious to me. I have no way of knowing that my vote will be counted as I filled it out, and I realized half way through that election officials can determine how I voted. Here's why...

You have two pieces of paper during the vote. A registration sheet is signed by the voter. A paper ballot has little rectangles that the votor fills in with a ballpoint pen in the privacy of the voting booth. The instructions say to fill in choices completely. Since the voting booths have a hard top, it's difficult to write on them with a ballpoint, let alone fill in little squares completely. The natural thing to do? Slide your second piece of paper under the ballot, so the pen can dig in better. If you don't think about it, you'll probably do this unconciously.

Half-way through, I realized that I was leaving imprints on the registration paper, with my name on it, that corresponded to my choices on the ballot. Due to the two-column layout, and the distinctive spacing between different choices, it's possible to look at those imprints and determine exactly how I voted. The registration paper has to be handed in at the end, so the official who sits there all day collecting these has plenty of time to work this out and determine the votes of anyone. (I moved my ballot around and re-filled in squares to try to confuse things.)

(Relatedly, one has to carry the paper ballot around the room to take it to the voting machine. It's difficult to keep the ballot obscured while doing this, since you can't fold it, and since they take the registration paper before the ballot, so you can't keep the ballot covered with it either.)

The second obvious flaw is that once I fed my ballot into the voting machine, which presumably scanned it and put it in a safe, there was only a confimation that "you've voted!". There was no way to verify that it had counted my vote as I'd marked it.


Most voting system work seems to be in the direction of advocating paper ballots for paper ballots' sake. This doesn't seem like the right approach to me. Is no-one working on writing down the characteristics that an ideal voting system would have, and trying to make them all requirements?

My take on requirements of an ideal voting system are:

  1. Only living people in the set of registered voters may vote.
  2. Each votor can only vote once.
  3. The votor should be able to verify that his vote was counted correctly.
  4. There must be a way for the votor to prove if his vote was not counted.
  5. The votor must not be able to prove which way he voted (to avoid payoffs, intimidation, etc).
  6. Others must not be able to determine how a votor voted.
  7. Individual votes must be retained to allow recounts.
  8. The entire vote data should be published so that the results can be verified by third parties.
  9. The system must scale to many millions of voters.
  10. The correctness of the entire voting system should be formally provable.

The paper ballot system I experienced today fails on at least points #2 [A] , #3 (see above), #4 (I walked away with nothing I can use to prove anything), #5 (I can video my vote), #6 (see above), and #8 [B]. At least it scales well though.

The old touch screen system failed most of the same points, though it made at least a small attempt to satisfy #3 (by confirming the vote onscreen) -- and it failed #7, and probably scaled worse.

Outside of the American election system, I've participated in voting systems that seem able meet requirements #1 [C], #2, #3, #4, #7, #8, and #10.

To me, #10 is the most important point, but it seems to be the one that is neglected most. Some of the points may be worth weakening if they block other points. Is it really worth avoiding giving me something to prove how I've voted, and banning taking cameras into the polling place, in order to meet point #5, if this defeats point #4?

I'm curious what requirments I may have left out too. My list is just a rough stab at it. The real point is to analyze voting systems, and reject ones that don't provably meet criteria. Until it becomes accepted practice to do that, our voting systems will not get appreciably less flawed.


[A] If you can get two copies of the ballot, you can vote twice ... fairly easy with a friend on the inside to arrange for the two copies to get "stuck together", and another one at the vote scanner to allow you to scan both.

[B] The ballots could be published, but there's no way to prove all of them, or the true ballots would be. And in reality, they're either shredded, or locked away, or tossed in a dumpster, or variously all three.

[C] Mostly. Perfectly accomplishing #1 is harder than most of the other points, and may be worth leaving out of scope.

discussion

Posted