I survived!

As I mentioned on friday, I were going up to Rena to attend this year’s Birkebeinerrittet this saturday. I can now report happily back that I made it all the way through, even though my body felt like every bit of energy was gone even after 30 kms. I’m suspecting that it might have something to do with me feeling a bit sick the previous days, but things seemed better at friday. My body was however probably not prepared for biking 91 kms, but it made it all the way through.

I finished in 5:47, which is quite crap when compared with other people in my age group (25-29), but I conclude that they probably weren’t as happy when they made it to the finish! This means that I reached two of my goals: finish and not die. I’ll leave the 5 hour mark for some other year (avoiding saying next year is a good tactic).

The ride over the mountains were hard, and we started out by climbing the 500 height meters up to Skramstadsetra (you can see the course profile here). After a bit of forrest riding we hit the first downhill part of the track. One person apparently got seriously injuried here during the race, and I can understand why. I’m usually picking up a few spots in the downhill areas, but when you have several hundred riders close by and people approaching quick from the groups starting behind you, there’s no choice but to take it a bit easy. I made it through the downhill, and then we hit the first “time to get off your bike and climb up this mountain in the middle of the forrest” part. There’s no hope of anyone getting up these hills without getting off their bikes, with mud and dirt everywhere and a steep hill. After this things went a bit flat and rough for a while, and I just stuck together with the people around me. Everyone moved at the same speed anyways, so this is not the place to try to make a run for it.

The next part of the course up to Kvarstad went perfectly OK, but I really felt my body draining of any spare energy. Getting a bike GPS is one of the smartest things I’ve bought this year, but when I’m doing long runs, I fall into the trap of looking at it at just a few minutes intervals. Things seem to go sooooo slow… Well, after stretching my legs at Kvarstad, I started on the next climb. Just as I entered the bottom of the hill, my body apparently thought I was joking, so it went for a small shutdown. I just had to get out of the way and spend a minute at the side of the road, before walking the first hundred meters of the hill. Strangest feeling I’ve ever had, and it confirmed my suspicion that I had been a bit sick during the previous days. Should probably have had some more food before starting the race too, but oh well. After walking a bit of the hill, a guy and three girls from Adecco went past at a slower pace, and as the guy humoursly told me that the point were to bike and not walk, I decided to join them at their pace up the hill. This worked out very nicely, and you should know that you helped me up that hill, even though it wasn’t that steep, it was a hard challenge at the time!

After battling through this stage, things went better until we approached the infamous “Rosinbakken” (the hill of the dried grapes / raisins loosly translated). I think the hill got the name because of how your legs feel after finishing it, but it may very well describe the feeling I had in my legs when I got to it. The hill is just over a kilometer long, and it’s inclination is around 10%, meaning that you climb something like 120 meters while riding the hill. Because of the name the hill has been adopted by the company ica, which welcomes you to the hill and then serves you: yep, raisins, halfwall through the hill. I decided to walk here, as my legs were kaput and I still had quite a few smaller hills to attend to in the next kilometers. Got up on my bike for the last 200 meters of the hill as things were flattening out and rode along with a few bikers I had tagged along with earlier. When we got to the top here, things went a lot flatter and the hills got sleeker. Still not anything easy (as you have 58kms+ and somewhere well above 1000 height meters in your legs), but I realized that I were going to make it, and that my body weren’t going to try to shut me down again.

As I approached the last food and drink station, the guys from the elite class were passing us. They started from Rena 2 hours after my starting time, and jeeeeesus. Those guys are fscking fast. Guess the fact that we were close to the highest point of the course also had something to do with it, but seeing people ride like that uphill was very impressive. I’m never going to put down enough time to be able to come close, but a man can dream!

After the last food and drink station there were just a few hills left before we passed sjusjøen, the turning point of the trip. From Sjusjøen almost everything is smooth sailing: the hills go in the right direction (down), the tarmac reappears for several stints and since you now know that all the hard parts are over, your body is ready to contribute the last few strands of energy.

The last part of the track (~6kms) is inside the venue from the 1994 olympics, and the craziest part of the whole track is when you’re going down the hill from the Freestyle skiing event. This is steep. Very steep. Especially when your legs, your arms and your mind is dead tired. This is also where people fall off their bikes, especially if it’s wet and it’s been raining. I just kept my brakes engaged and took the easy way down, slowly descending onto the platform and then riding through the stage where the olympic fire burned for two weeks in 1994. It’s an impressive location and really sets the theme for the finish. A single hill was concealed behind the stadium in a small forest patch, but if you’ve done 90 kms, that’s not going to stop you.

I finally finished after 5 hours and 47 minutes. My parents were there to pick me up, and after getting my diploma and getting off my biking shoes, we set off for home.

Things I’ll remember:

  • The two cows we met — in the track — while biking.
  • All the sheep. Holy Cow! There’s a lot of sheep in the norwegian mountains.
  • Being completely drained of any energy
  • All the great people riding, in particular all those who I tagged along the backwheel of. I never thanked you while riding, but it really made a difference. Hopefully you also tagged along when I decided to ride first for some kms, but it seemed hard to get people to catch on. I hope someone else found my back wheel interesting and used it for all it was worth during a couple of kilometers!
  • I’d also like to thank in particular:
    • A guy from Thales (at least that’s what his backpack said) which I were conversing with through the last 30 kilometers. It really helped! I tried to tag along when you wooshed by together with another group 10 kilometers before the finish, but I lost you after a kilometer.
    • The slowest people from Adecco and ica! It’s great seeing people that are attempting to do things they’ve set out to do, and it was of great help all the way.
    • A girl in a green outfit, a girl in a blue outfit (both group 65, i think) and the guy and girls in the hill when all energy seemed lost. I know I tagged along your back wheels for maybe a bit more than I should, but it really helped. Hope you all made it to the finish line!
    • A guy and a girl from Adecco (also in group 65-67 or something) which rode together. I ended up along with you early on, and then found you again several times along the track. Very inspiring!
  • The poor person who had gotten a puncture with just 5 kilometers to go, inside the olympic venue. That’s got to suck.
  • The elite guys and their incredible speed!
  • The VERY VERY VERY cheerful crowd along the track! You guys cheered, you gave out bananas, you had your own bands, you yelled encouragement. It’s amazing. It really matters. A great thank you to the guy who stood out in the road close to sjusjøen and handed out hi-fives and a gently push on the back to all the amateurs who were just below the top.
  • I’ve learnt one thing: you’re always VERY CLOSE to the top of a hill. At least that’s what the crowd are cheering. It doesn’t matter if it’s right, it’ll always feel like it’s true. And when you get to the top, you feel that they were right all along. It wasn’t really that far.

Well. The final question now is if I’d do it again next year. I’m going to wait a few days before I decide, but… probably. Hopefully I’ll have a better couple of weeks before the race.

Anyways: Congratulations to everyone who finished, and if you’re ever considering going for a very nice, well organized mountain bike run in europe, go to Rena and start in Birkebeinerrittet. It’s something everyone should have done at least one time! I’ve now done it twice (in 1996 and in 2008)!

Birkebeinerrittet Tomorrow

Well, tomorrow’s the day when the regular birkebeinerrittet mountain bike race is held (over 3000 people already finished the race today, in the first “Fredagsbirken”). The organizers had to set up an extra race day because of the number of people signing up; the primary spots were gone in 90 seconds. I’m one of those who managed to get my spot during those 90 seconds, so tomorrow at 13:00 I’m starting from Rena, hopefully finishing in Lillehammer somewhere around five hours later. I’ve just added 3kgs of dead weight to my backpack, as all participants have to have at least 3.5kgs on their back. My dad actually still had the led pack we made for dead weight when I last competed in the race in 1996, so well, it’s going on it’s second run!

Primary goal: finishing Secondary goal: finishing below 5 hours. Third goal: escape death.

World Class Sports Photography

If you’ve ever considered shooting a sporting event or have been wondering what it takes to be a world class sports photographer, the amazing Newsweek 2008 Olympics Picture Blog is the place to be. Three photographers from Newsweek has been shooting for two weeks now, and they’ve been sharing all their experiences and best photos with the world. I’ve learnt loads of stuff about how the real guys do their gigs, and I’m still getting surprised by their persistence to get the good shots. As most photographers they never admit that they got the perfect shot, but the blog is filling up with some of the best photos from the olympics.

I had no idea they did such an amount of remote triggered shots, and while I’m not going to start doing photography for a living any time, at least I know a few tricks if I ever find myself at a track and field event. Awesome. Worth a read, and hopefully they’ll keep it up for all time to come for people to learn more about photography and watch a great collection of stunning pictures.

Getting To Grips With Too Human

Silicon Knights have finally managed to get Too Human out for a release, and I spent thirty minutes tonight trying out the demo from Xbox Live. I’m probably one of the few people who actually are quite interested in games but never knew much about Too Human before trying it out. I had read a few reviews and their conclusions seem to cover most of the elements of the game.

It’s not hard to see that the game had a lot of potential. There are large number of enemies. There are RPG elements. There are loot to get. Fat gear. Skills. Runes. Classes. And a very high speed gameplay that mainly includes pointing your stick against the enemies and watching them die by your enormous sword. I love gigantic swords. No penis jokes, please.

Therefore it’s sad to see it brought into yet-another-troubled-attempt by several questionable design decisions. First of all; don’t fuck with the right control stick. This moves the camera. Period. Most games use it that way, we expect it to work that way. In a game where there are 20 enemies approaching you from all directions at the same time, moving the camera is important. Instead, the game decides what to show you. You can reset the viewport, but hey, I already have a control stick that actually could let me move the viewport around. That would be fantastic.

OK, we’re in a magical world where the camera works perfect. No troubles at all (well, we’re not in Too Human any longer apparently, but ride with me here) and everything is perfect. Suddenly you’re somewhere else. What. Hm. I can control my character, but .. hey, this is not where I’m supposed to be. The developers thought that a flashback was a cool idea to explain something about the motivation for where I’m going and what I’m going to kill, but telling me that they were going to show a flashback or do something else.. Well, not so much. Let the sequences play out in the history, not at arbitary locations along the road. It sucks. And why on the earth was I teleported into a green land, just to have to run through the parts the camera just moved backwards from?! I’ve already seen that greeeeeen shit, man.

If Too Human ever gets the planned sequel (it’s supposed to be a trilogy), I’ll provide the name for free. Invisible Wall. The demo is full of them. There are invisible walls everywhere, and magically you can’t fall off anywhere there are any height involved. You can’t jump over simple obstacles, even though your character has the jumping capabilities of a squirrel on speed. I hate invisible walls. They’re invisible. They’re walls. They’re just HEEEY! YOU CAN’T SEE ME BUT I’LL JUST FUCK THE ENTIRE IMMERSIVE PART OF THE GAME UP. AND I’LL DO IT AGAIN. AND AGAIN.

The weird part is that the demo actually were a bit fun. Not WOOOW THIS IS GREAT-fun, but the occasionally things worked nicely. I’m even going to consider buying it when it gets dirt cheap because of vendors over stocking on the hype.

I just hate invisible walls.

Unit-Testing Code Which Uses a Database

How to unit-test code that interacts with a database appeared on the blog of Baron Schwartz, and to be really boring, I agree with what he’s writing. Unit-testing database connectivity and storage is not hard. If it is, it might be a good time to redo that architecture you’ve been talking about.

An important point that Baron mentions is that you _NEVER_ _EVER_ run your tests on your production servers. That will of course be disastrous, as your tests needs a predefined state of the database to be valid for testing. The solution I’ve been using to handle this, is to always set up my environment to use another database when doing the tests. This way, you’ll never end up with running the tests on a live database by accident. I handle this in my AllTests.php file, where the test suites and shared fixtures are set up. We dump the contents of the developer database (databasename), create a new database (databasename_test) and insert all the current table structures and indexes. This way we get an accurate copy of the table definitions currently defined by the developer (so that we don’t run the tests against an old set of tables), and we test that the code works as it should with the active definitions.

The simplest way to do this, is to use mysqldump and mysql through a call to exec. If you’re not in a trusted environment, please, please, please add the appropriate shell argument escape commands. It can however be argued that if you’re allowing random people to change your database login information, you probably have bigger problems than doing unit testing..

exec('mysqldump -u ' . $username . ' -p' . $password . ' ' . $dbname . ' | mysql -u ' . $username . ' -p' . $password . ' ' . $database . '_test');

It would be very interesting to get more information about which measures Baron advocates for detecting a production system. We have configuration settings for our applications which also defines if this is a development or production system, in addition to the fact that our testing code only touches databases which end in _test.

Internet Explorer 8 and Their XSS Filter

There’s an interesting post up on the technet Security Vulnerability Research & Defense blog, providing a deeper look into how the XSS filter destined for release together with Internet Explorer 8 works. While it looks like a novel approach, I’m not sure how many of the actual attacks will be detected and guarded against. It will be interesting to get to play around with it later, and if it works as good as they say, it’ll provide some protection for the users of Internet Explorer against a class of attacks.

They provide several examples of issues that will not be mitigated by this filter, which includes attacks where the content is inserted directly into javascript (instead of spawning from an HTML-context).

Trackday with Norsk Sportsvogn Klubb at Rudskogen

Marius and I attended yet another trackday by Norsk Sportsvogn Klubb (NSK) at Rudskogen today, and here are the best shots from the day (I spent most of the day in the passenger seat of the GT2, so not many shots today).

Teodor and Iselin
Teodor and Iselin

Udo Starting the Long Corner
Udo Starting the Long Corner

GT3 in Queue
GT3 in Queue

Classic Ford Mustang
Classic Ford Mustang

Bonus: I got one of my n95 pictures in the local newspaper: Trailer tips over at local road. You can even see the GT2 as a black line in the left corner of the image. Didn’t have time to do anything proper, as we were just speeding past on our way to Rudskogen.

The Results of our Weekend Challenge

The weekend PHP size competiton I mentioned on friday has come to an end, with the results being as follows:

      CNU (253 bytes)
      Helge (261 bytes)
      Ymgve (267 bytes)
      Me (365 bytes)
      dibon&zep (which never delivered, but had working solutions)

For those who are interested in the strategies and tactics employed by the contestants, I’ve included a small write-up and analysis of the various contributions. We decided early on that using eval() and gzinflate on the content were something that everyone could apply, so the size would be counted for the decompressed code. If any contestant implemented their own decompressor in the user space code themselves, we would accept that. It would not be any advantage anyways, as the decompressor code would eat up more space than the best contributions used in total.

I’ve included the writers own comments if they had any. The biggest change in size happened when people started using one dimensional strings instead of arrays.

CNU’s contribution

';if($d==' ')$q[]=$x;$d=$c;}$q=$b='';}$b.=$l;$w=strlen($l);}

Helge’s contribution


Helge also included an annotated version with comments in norwegian:

 * $l = én linje (av maps.txt)
 * $m = ett map
 * $w = vidden til et kart
 * $d = distansen til et vilkårlig punkt
 * $v = open/closed-array (putter både squares 
        of interest og visited squares her)
 * $u = "current square", utgangspunktet til å 
        generere naboer
 * $n = nabo
 * $x = hjelpevariabel for å generere $n
 * $y = hjelpevariabel for å generere $u

/* Klarte aldri å finne en måte å skippe initialisering av 
   $m her.. (den resettes på siste linja og.. føles waste)
   * En idé var å bruke to for(;;)'s istedenfor en foreach 
   og continue, men jeg tror jeg hadde økt i kode da.. */

/* Foreach var nyttig fant jeg ut.. den stopper når filen er 
   ferdig lest av seg selv, så slipper kode på sjekking av det, 
   $f[$y++], osv. */
foreach(file("maps.txt") as $l) {
        /* Når $l=="\n" (som betyr slutten på et kart) skal 
           vi slutte å appende til $m og heller breake if'en 
           så vi kan starte pathfinding */
        $l != "\n" &&

        /* Bruker en 1-dimensjonal string istedenfor array 
           (= win!) */
        ($m .= $l) +

        /* Trenger vidden når jeg skal regne ut naboene til et 
           gitt felt. */
        $w = strlen($l)
        /* Gjør så $l blir feedet en ny linje av kartet vårt til 
           kartet er ferdig */

    /* Pathfinding start! */
        /* Setter $y og $d[starten] lik 0, og putter startposisjon 
           inn i $v i samma slengen. */
        $y = $d[ $v[] = strpos($m, '.') ] = 0;

         * Gjør så for(;;) breaker når sluttposisjon-$u blir 0 
         * (synonymt med $u == strpos($m, 'X');
         * Tar også neste $u fra $v i samma slengen */
        strpos($m, 'X') - $u = $v[ $y++ ];
        /* For hver nabo */
            /* Genererer naboer.
             * Den starter på -width (som blir opp), går så til -1 
               (som blir venstre), 1 (som blir høyre) og tilslutt 
               width (som blir ned) */
            $x = -$w;
            $x <= $w;
            $x += $x+1 ? $w-1 : 2
            /* Om naboen (summen av $u og $x) er i $v: continue */
            in_array($n = $u+$x, $v) | /* fancy bitwise or som kan 
                                          brukes fordi det er snakk 
                                          om 2 booleans */

            /* Om naboen er en '#' på kartet: continue */
            $m[$n] == "#" ||

            /* Hvis ikke, sett distansen til naboen lik distansen 
               til $u + 1 og putt naboen inn i $v */
            $d[ $v[] = $n ] = $d[$u]+1;

    /* Skriv ut distansen til $u (skal være sluttpunktet nå) */
    echo "$d[$u]\n";

    /* Disse må resettes.. */

Ymgve's contribution

foreach(file("maps.txt")as$l){for($i=0;-75<$e=ord($l[$i++])-88;$m[]=$e+56?$e:1e6,$z=array(-1,1,-$i,$i))$e+42||$q[0]=count($m);if($i<3){for($d=$k=$c=0;;$c++-$k||$i++&$k=$d)for($j=4;$j;$g>$i&&($g=$i)&$q[++$d]=$p)if(!$g=&$m[$p=$q[$c]+$z[--$j]])break 2;echo"$i

My own contribution

Breadth-first Search, Delivered Version, 365 bytes:


This is mostly your usual run-of-the-mill BFS, where the search itself is implemented as a simple queue.

We loop through all the lines in the file (observe that you can remove the space character on both sides of as, saving you two bytes!):


The part within the else condition builds the map to search for the exit point:

    // for each line in the file, we do this

The for() loops through each character on the line, until it hits the newline marker at the end. Instead of entering "\n", you simply use the actual newline. This way you save another byte. The map ($m) is then populated using the current y,x coordinate (y being the line, x being the character on that line).

$m[$y][$x]=$l[$x]=="#"?0:$l[$x] can be expanded to:

if ($l[$x] == "#")
    $m[$y][$x] = 0;
    $m[$y][$x] = $l[$x];

Meaning that if the character is a wall, we store the value zero; if any other value, we store the character itself. We'll use this attribute when searching to determine when we've reached our goal. All of this is kept inside the for()-construct itself. The only thing contained in the for()-loop, is the statement if($l[$x]=='.')$q[]=array($y,$x,0);. This checks if the current character is the starting point, and if that's the case, adds it to our queue of points to check (making it the starting point of our BFS).

When we hit an empty line in the file (through the if("
"==$l) check), we execute our BFS.

    /* while $q is valid (this handles empty labyrinths), we fetch the 
        current y and x coordinates, in addition to d, the distance to 
        the location we're fetching from the queue. No {} here, as the 
        for only contains the if() statement below. */

        /* if this spot has a value (remember that we assigned 0 to walls, 
            while we kept the character value for other fields when we 
            parsed the file. We use empty() as the coordinates may not be 
            valid indexes into the array, as we don't do any checks when 
            we add them. one call to empty() is better than four ifs and 
            duplicate array references). */
            // create a reference (saves one byte instead of referencing $m[$y][$x] twice.

            /* if we've found the X, echo the distance to the X. Under any 
                under circumstance, you'd break; out of the for/while here, 
                but as bytes count more than speed, we save six bytes by 
                searching the whole labyrinth instead of ending early. Funny 
                detail: as echo is a language construct, you can skip the space. 
                If the character is not 'X', we simply echo an empty string 
                instead of using a conditional echo. Saves a couple of bytes. */

            // unset the value, so that we don't visit this node again.

            /* add all neighbours to our queue. We pre-increment $d, instead 
                of adding +1 in all the adds. */
        /* Reset the values. PHP generates a warning if a value has never
            been set before when used, but will happily accept null values 
            as empty arrays or 0. The double assignment is also a trick worth 
            remembering to save bytes. */

Some of tricks used in the competition

  • Multi-variable assignment: $a=$b=0;
  • Actual newline when detecting a newline: if ($a=="
  • Using null to be able to reset both integers and arrays in one statement.
  • The more code you can fit into a for() statement, the better. You get three "free" line endings by doing this. for(;;) is the same length as while(), but you can get several statements evaluated.
  • You can skip the spaces in foreach().
  • Create references to avoid using long array indices several times.
  • The ternary operator (?:) is your friend!
  • Remember that {}'s can be dropped when you have a single statement that contains all subsequent code (as long as you don't get any conflicts with else etc. on different levels):
    for(;;) <-- no { here.
    if ()


  • Simulating arrays with strings

The scripts were run with a set of pre-made labyrinths and a collection of 20 random labyrinths (more like maps, but they still test the code the same). The script for creating the labyrinths is available here. All delivered contributions passed all tests.

Translating Drizzle to Norwegian

As Monty asked for help with translations of the current strings available in Drizzle on his blog yesterday, I sat down a couple of hours yesterday and a couple of hours today to at least attempt to contribute something to the project. As my primary language is Norwegian and I have some experience writing, I decided to tackle the Norwegian (Bokmål, not Nynorsk) translation of Drizzle. I’ve currently finished the 358 available messages, but I’d really appreciate it if someone spent a couple of minutes / hours to read through them and confirm that my assumptions are sane.

The most troubling part when it comes to definitions are the issue of MySQL/Drizzle’s ‘relay log’ which I translated into ‘replikasjonslogg’ – which mainly means “replication log”. This sounds much better in Norwegian, but suddenly the code mentioned both a “replication log” and a “relay log”. I tried finding out what the semantic difference in MySQL were, but were unable to grok anything from the MySQL manual or through a Google search. If anyone has any advice here, it’d be very appreciated. I also made a few notes of where there are obvious errors in the original english strings:

Error on close of '%'s (Errcode: %d)
 - Located in mysys/errors.c:28 

Can't read value for symlink '%s' (Error %d)
 - Located in mysys/errors.c:47 
Can't create symlink '%s' pointing at '%s' (Error %d)
 - Located in mysys/errors.c:48
Copy text Error on realpath() on '%s' (Error %d)
 - Located in mysys/errors.c:49 

%*s(Defaults to on; use --skip-%s to disable.)
 - Missing space
 - Located in mysys/my_getopt.c:1170 

The event could not be processed no other hanlder error happened
 - hanlder
 -  Located in mysys/my_handler_errors.h:118 

SSL information in the master info file ('%s') are ignored because this MySQL slave was compiled without SSL support.
 - MySQL
 - Located in drizzled/rpl_mi.cc:276 

Slave I/O thread killed while waitnig to reconnect after a failed registration on master
 - waitnig
 - Located in drizzled/slave.cc:90 

Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog'..
 - mysqlbinlog
 - Located in drizzled/slave.cc:1864 

Found wrong key definition in %s; Please do "ALTER TABLE '%s' FORCE " to fix it!
 - feil spaceplass
 - Located in drizzled/table.cc:1162 

Table '%-.64s' was created with a different version of MySQL and cannot be read
 - MySQL
 - Located in drizzled/table.cc:1818 

I could probably submit a patch for this, but seeing as the source is very much in flux these days, I think I’ll wait until it settles down a bit — unless someone is interesting in reviewing and committing an “unimportant” patch at this stage.

BTW: Launchpad worked great for doing translations, so I’m going to look into using gettext and Launchpad for doing translations for pwned.no and my other services in the future.

Finding Your Way Around for the Weekend

If you’re interested in a bit of a weekend challenge, we’re currently hosting a small PHP coding competition at one of the IRC channels I’m active in. The challenge’s deadline is this sunday (10th of August, 2008) at midnight (if you’re in another timezone, just use your own sunday’s midnight), but the challenge should always prove interesting later too.

If you’re interested in trying to solve labyrinths with the smallest amount of source code, this might be for you!