Buckyball Racing Club presents: Turbo Hour (Jan 25th - Feb 12th)

Congratulations to the winners and well done to everyone who took part! This seems like it was a difficult race to organise and compile statistics for, so a virtual round of applause is in order for furrycat! It's always good to see a race with the Cobra Mk 3 producing competitive times, as well. I'm not sure when I'll be back in the bubble to race next, so have fun and fly fast, everyone!
 
Wow thank you very much KliggJr that's very kind of you. I'll have a look at what paintjob to get. If you ever need a hand with something in game let me know.

Thanks to Furrycat for organising this and everyone who's made it so entertaining. I'll be back for some more races, I definitely need the practice!
 
Reading cookiehole's wall of text made me notice a great example of convergent evolution at work: those hints of him about realspace and sc travel are point to point exactly the same I came to apply in hours of trials, errors, insurance calls, more errors, more calls...even more errors, oh, how many errors :rolleyes:...

The important difference being, he's able to apply those rules better than me. :D

Let's be honest about it though, the lack of "certain" competitors helped us..."a lot" :p...

Thanks again to furrycat for the impressive work he made in organizing the race, giving it a great background and stuff it with more race data and statistics than one could possibly ask for.
Oh yes, and for giving prizes too!

The ad for the next race should say "Come to the races! We have cookie!" (pun blatantly intended)

See you all for the next one, hoping to fix my sorely missed twist rudder in the meantime!
 
@cookiehole

thanks for sharing the wall of text tips. I had figured most out myself but there are certainly a few in there that i'll be trying out in my next race.

and wow the ORca looks great in Yellow. I might have to invest in the paint job.
 
Agree with everything.

Actually didn't bother A classing power and thrusters, errr ... my bad I expect (slacker).

  • Fuel scoop for occasional top-ups in Ch'ing
  • Biggest possible fuel tank that doesn't add any jumps (not really possible in the shieldless Courier due to Route Planner stupidity)
  • Light D shields for the early non-joker runs
Fuel was an interesting one. It seems liked you could scoop enough from the two Ch'ing passes to not really have to pay too much attention but then a couple of times I found myself really quite low towards the end. Usually tried to cook the Cobra to around 110% heat at Ch'ing to be sure.

Takeoffs and Landings
Very important in this race, but pretty much the usual things. Some small details:
  • Takeoff: I hold upwards thrust before the clamp releases; this is possible because of having it bound to a analogue axis in landing mode.
  • BOOST! Don't boost <5km on a landing approach with the Cobra though. :D
  • Landing pads: Relatively important aswell. I aimed for getting pad 12, 13 or 36, alternatively 28, 43, 27, 42 and 21 (28 and 43 allow for a safer boost-takeoff). Rerequesting docking is the way to go, although there's not much time in these very fast ships.
Takeoff: Wait! What?!? That thing where they broke (ahem, "fixed") being able to hold upwards thrust before the clamp releases (i.e. if you try it these days nothing happens), are you saying that's not true of an analogue control?

BOOST: yup, that 3rd boost in a Cobra approach, it's a tough call. After my early fail (captured in one of my videos I think) I basically stopped myself from doing it as it led to disaster more often than not. Also re: station approach - did anyone else find (escpecially in the Cobra) that on the odd occasion where you dropped out of SC absolutely perfectly lined up (like, staring straight down the barrel of the mailslot), things tended to go badly (e.g. typically overshooting the pad).

Landing pads: you know what, I've never bothered with the old re-request docking permission technique, I like to roll with the punches (this together with my slack attitude towards fine tuning my loadout probably explains why I never quite manage to win these things).

Supercruise
Also very important in this race.
  • The planet in Turbo was a tough candidate for gravity braking as it is extremely small. The exclusion zone is therefore relatively big, especially in Horizons. Racing in 1.5 might be beneficial in this case as the effective exclusion zones are definetly smaller without the big blue zone (that will lead to an emergency drop at gravity braking speeds aswell).
  • Turbo: No big braking effect, easy to overshoot, easy to waste time with not using the full potential of the braking (as the Orbit of the station is relatively high for such a small planet).
  • Unkulcay: Slightly better braking, but difficult to decide whether to do a loop of braking or riding the 6 and then doing a direct approach.
  • 49 D Orionis: Good braking effect, but relatively difficult to get in with the right angle to the station, as the Orbit is relatively low.
  • Vasak: Good braking, definetely the easiest to use candidate and the one with the biggest effect.
  • I went with an initial braking loop in all systems as it is relatively easy and reliable. Especially in a long race like this it is simpler to go full throttle until the the ETA reaches 00:05, then throttle to zero, do a loop after passing the planet, full throttle and second/final approach with planetary braking than the more customized initial approach that is necessary with the ride the 6 + throttle kick + braking on approach thing that is useful with close-to-the-star planets and big ships. I don't know if that made any sense. :p
  • I have the "Show mouse widget" option in the Controls menu enabeled, as it allows for precise aiming in Supercruise and while docking. Also, graphics options on low with "Material Quality" on medium (for the station entrance lights) shortens the time it takes to drop from supercruise.
Planetary braking was definitely tricky with several of these although funnily enough, I think because of the repetition, they were also some of the best SC approaches I've ever done. Once again, personally I'd say the sound was the biggest clue towards flying the perfect SC approach. It's subtle enough that you can tell the difference between a 5-sec that's going to stay at 5-sec and a 5-sec that's going to tip-over into a too fast 4. I experimented quite a lot this time with using exagerrated pitching motions to get those latter approaches back under control.

I've always used the "show mouse widget" - partly because I'm a bit a.n.a.l. and when I point at something, like to know that I'm REALLY pointing RIGHT at it.

Re: turning down the graphics (which I've read about before) ... see above re: being slack and not winning.

Statistics

Well, didn't really keep any accurate records (slack slack slack) but I lost 4 Cobra's and a week of my life (including being late one morning for a very important meeting and having to lie about trains being cancelled).
 
Last edited:
Takeoff: Wait! What?!? That thing where they broke (ahem, "fixed") being able to hold upwards thrust before the clamp releases (i.e. if you try it these days nothing happens), are you saying that's not true of an analogue control?

Correct. I have an evil FreePIE digital-to-analogue script which lets me hold a button and report a vJoy axis so I never had that problem. My Warthog physical switches to hold the cargo scoop open or flight assist off still don't work.
 
Takeoff: Wait! What?!? That thing where they broke (ahem, "fixed") being able to hold upwards thrust before the clamp releases (i.e. if you try it these days nothing happens), are you saying that's not true of an analogue control?
Yes, it's always worked with analogue (I've never had the problem). That's one advantage at least with my leftie two-stick, no throttle setup. I've got loads of analogue axes. :D

Also re: station approach - did anyone else find (escpecially in the Cobra) that on the odd occasion where you dropped out of SC absolutely perfectly lined up (like, staring straight down the barrel of the mailslot), things tended to go badly (e.g. typically overshooting the pad).
When perfectly lined up in my Asp, I tend to get over excited, boost once too often and either hit the back of the station or even end up missing my perfectly aligned approach and hit either the cage or front of the station!

Re: turning down the graphics (which I've read about before) ... see above re: being slack and not winning.
Can't bring myself to turn down the graphics (I'm looking forward to the day that I can play in 4K VR!). So if I ever finish close enough to Cookiehole that the instance loading makes the difference between winning and losing, then I'll consider it a moral victory. ;)

I did notice when I watched one of Cookiehole's earlier videos (perhaps from Aot's race) that his system map loaded much, much faster than mine. They've said that the slow system map will be fixed in 2.1 though, so hopefully this won't matter for long. It's a bit annoying if changing graphics options has a massive effect on the loading time of the rubbish 2d system map!

Well, didn't really keep any accurate records (slack slack slack) but I lost 4 Cobra's and a week of my life (including being late one morning for a very important meeting and having to lie about trains being cancelled).
That is so funny! Repped! :D
 
Glad I'm not the only one finding the exclusion zones of some planets in Horizons a problem for coming in a hurry, the Turbo A one was a b*tch indeed (the planet though, was quite some fun to ride around on :))...at least I don't feel guilty anymore for switching back to 1.5 just for the racing...I had a couple of friends on Steam who saw me with my brand new Horizons (Valentine's gift, done the right way), then constantly switching back and forth between that and 1.5, asking me "hey, is that Horizons so crap that you can't stand it for more than a couple hours at a time?"..."it's a long story mate, I'll explain you one day" :D...

I'll have to try this thing about lowering graphics detail, I didn't expect to impact so much on instance creation time.

About this take-off thing, I think I'm not getting it, I have thrusters bound on digital hat directions, and those also controls the selections in menus, so I couldn't keep them pressed for thrust before launching...but anyway, as soon as I click on "Launch", there's always that split second before clamps release where I start holding upward thrust before the clamps are disengaged, I don't see it like it's robbing me of precious departing time...do you mean that with analog thrust, you have time to reach full upward power and so make a cannon-ball take-off as soon as the clamps are released?

A last thing about my race...that one about anxiety inducing orbital mechanics...those were the starts of my final laps of the race:

Start of lap four:
fskrfX7.jpg

Start of lap five:
DMPGvOQ.jpg

Start of lap six:
VBNJ8jT.jpg

There would have been no lap seven. Talks about having a good motivation for going fast.
 
About this take-off thing, I think I'm not getting it, I have thrusters bound on digital hat directions, and those also controls the selections in menus, so I couldn't keep them pressed for thrust before launching...but anyway, as soon as I click on "Launch", there's always that split second before clamps release where I start holding upward thrust before the clamps are disengaged, I don't see it like it's robbing me of precious departing time...do you mean that with analog thrust, you have time to reach full upward power and so make a cannon-ball take-off as soon as the clamps are released?

I have a T.Flight Hotas X and have the digital up thumb-stick control mapped to upwards thrust (and, as you say, thumbstick also controls menus). So, what I used to do was hit launch and then immediately start holding the up thrust. As soon as the docking clamps released away I'd go. They changed something around 1.4 (maybe even earlier?) so that if I try this now nothing happens. I have to release the up thumbstick and then press it again for the thrusters to engage. So what I do now is hit launch, wait for the release of the docking clamps and then press up thrust. It's kind of like the difference between pushing yourself against the starting gate and going as soon as it's raised versus having to wait for the starting pistol and going once you've heard it (with a penalty if you try to go too soon). They'll be changing the point at which landing gear forces ship slow-down next ... oh wait, they already did. Thanks FD. If you could just remove the clock as well that'd be terrific. /s
 
Let's be honest about it though, the lack of "certain" competitors helped us..."a lot" :p...
I was in fear until the very last seconds of the racing period. Not only about Alot doing a late run, but also about having already used the Courier joker while not being able to fly the Cobra...

and wow the ORca looks great in Yellow. I might have to invest in the paint job.
I made good use of the Black Friday sale :)

I'll have to try this thing about lowering graphics detail, I didn't expect to impact so much on instance creation time.
It's a difference of a split-second up to a couple of seconds between low and high for me, which adds up in a race like this. I hate fiddeling with the options before and after every run and I also don't like the mouse widget, but seeing it in someones videos in one of the last races I tried it and found it useful, especially with gravity braking loops.

About this take-off thing
I have a Thrustmaster T-flight Hotas X and it has an analogue thing meant for rudder control on the throttle (I use the twist axis on the stick for yaw though). I've bound it to lateral thrust in landing mode, mainly for planetary landings, while normally having the thrusters on the hat switch. My takeoff procedure is therefore hit launch - hold analogue upwards thrust - start holding hat switch upwards thrust after launch clamp release - retract landing gear and release analogue upwards thrust - hit boost
It probably saves only 0.2s or so, but it saves the stress of having to hit upwards thrust exactly in the right moment or thinking "this could have cost me a second" :D

those were the starts of my final laps of the race:
Yep, had that too in my last run with the Cobra. While I had some obscured targets in Unkulcay, those were only a few seconds in SC (still too much lost time for a good run). A star obscuring a target is really bad.
 
Last edited:
Now for a look behind the curtain at the race-o-matic.

The race was planned with the idea that the average competitor should be able to complete four laps, which is sixteen stations. That meant that there were going to be a lot of screenshots or videos to go through. As it turned out there were 820 dockings recorded for this race.

I knew even in the planning stage that I needed some way to deal with that volume of data entry. Hence the race-o-matic was born.

The application itself isn't a great piece of software engineering. It's PHP on the server side with some Javascript on the client to make recording entries as easy as possible. One area which I do think performed well was the database schema. I spent a bit of time designing it and that effort paid off. Don't expand the spoiler if you don't care about database schemas. Definitely don't expand it if you don't know what they are.
[size=+2]System table[/size]
The first table is the system table which lists a system name and its co-ordinates.
Code:
CREATE TABLE `system`
(
    `id` INTEGER NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(64) NOT NULL,
    `x` FLOAT NOT NULL,
    `y` FLOAT NOT NULL,
    `z` FLOAT NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `name` (`name`),
    UNIQUE INDEX `coords` (`x`, `y`, `z`)
) ENGINE=InnoDB CHARACTER SET='utf8';

Here are the entries for systems in this race:
Code:
+----+--------------+---------+----------+----------+
| id | name         | x       | y        | z        |
+----+--------------+---------+----------+----------+
|  4 | 49 D Orionis |   71.75 |      -47 |   -117.5 |
|  2 | Turbo        | 47.3438 | -52.9688 | -121.906 |
|  6 | Unkulcay     |  30.875 | -56.8438 | -103.469 |
|  8 | Vasak        |  29.625 | -49.0312 | -126.719 |
+----+--------------+---------+----------+----------+

[size=+2]Station table[/size]
The station table records the stations in a given system and some flags which don't apply to this race about whether it's an orbital or planetary station and whether or not it supports large ships.
Code:
CREATE TABLE `station`
(
    `id` INTEGER NOT NULL AUTO_INCREMENT,
    `system_id` INTEGER NOT NULL,
    `name` VARCHAR(64) NOT NULL,
    `orbital` TINYINT(1) DEFAULT 1 NOT NULL,
    `large_pad` TINYINT(1) DEFAULT 1 NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `system_station` (`system_id`, `name`),
    CONSTRAINT `station_FK_1`
        FOREIGN KEY (`system_id`)
        REFERENCES `system` (`id`)
) ENGINE=InnoDB CHARACTER SET='utf8';
Here are the stations from Turbo Hour.
Code:
+----+-----------+-----------------+---------+-----------+
| id | system_id | name            | orbital | large_pad |
+----+-----------+-----------------+---------+-----------+
|  2 |         2 | Kanwar Horizons |       1 |         1 |
|  4 |         4 | Bell Station    |       1 |         1 |
|  6 |         6 | Watts Dock      |       1 |         1 |
|  8 |         8 | Rolland Port    |       1 |         1 |
+----+-----------+-----------------+---------+-----------+

[size=+2]Raikogram table[/size]
The raikogram table acts as a cache to save calculating the distance between systems over and over again. We need to do that to work out lap distances.
Code:
CREATE TABLE `raikogram`
(
    `id` INTEGER NOT NULL AUTO_INCREMENT,
    `system1` INTEGER NOT NULL,
    `system2` INTEGER NOT NULL,
    `distance` FLOAT NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `systems` (`system1`, `system2`),
    INDEX `raikogram_FI_2` (`system2`),
    CONSTRAINT `raikogram_FK_1`
        FOREIGN KEY (`system1`)
        REFERENCES `system` (`id`),
    CONSTRAINT `raikogram_FK_2`
        FOREIGN KEY (`system2`)
        REFERENCES `system` (`id`)
) ENGINE=InnoDB CHARACTER SET='utf8';
To check the distances between any two systems in the race we plug in the foreign keys. Note that there's only one distance record for any pair of systems. The convention is to use the lower of the two system IDs as system1 and the other as system2.
Code:
+----+---------+---------+----------+
| id | system1 | system2 | distance |
+----+---------+---------+----------+
|  7 |       2 |       4 |    25.51 |
| 15 |       2 |       6 |    25.02 |
| 17 |       2 |       8 |    18.78 |
|  9 |       4 |       6 |    44.32 |
| 11 |       4 |       8 |    43.17 |
| 19 |       6 |       8 |    24.56 |
+----+---------+---------+----------+

[size=+2]Race table[/size]
The race table defines a race name, what prizes are available and whether there's a time limit. With no time limit the race is considered to be a traditional dash.
Code:
CREATE TABLE `race`
(
    `id` INTEGER NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(64) NOT NULL,
    `allotted_time` INTEGER,
    `prizes` INTEGER,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `name` (`name`)
) ENGINE=InnoDB CHARACTER SET='utf8';
The Turbo Hour race has a 1h time limit and 6 prizes:
Code:
+----+------------+---------------+--------+
| id | name       | allotted_time | prizes |
+----+------------+---------------+--------+
|  2 | Turbo Hour |          3600 |     63 |
+----+------------+---------------+--------+

[size=+2]Course table[/size]
The course table defines the stations which make up a race and which of those are the start and/or finish lines. Some races require that the stations be visited in order so there's a field to record that; unused in this race.
Code:
CREATE TABLE `course`
(
    `id` INTEGER NOT NULL AUTO_INCREMENT,
    `race_id` INTEGER NOT NULL,
    `station_id` INTEGER NOT NULL,
    `start_line` TINYINT(1),
    `finish_line` TINYINT(1),
    `station_order` INTEGER,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `race_station` (`race_id`, `station_id`),
    UNIQUE INDEX `start_line` (`race_id`, `start_line`),
    UNIQUE INDEX `finish_line` (`race_id`, `finish_line`),
    UNIQUE INDEX `course_order` (`race_id`, `station_order`),
    INDEX `course_FI_2` (`station_id`),
    CONSTRAINT `course_FK_1`
        FOREIGN KEY (`race_id`)
        REFERENCES `race` (`id`),
    CONSTRAINT `course_FK_2`
        FOREIGN KEY (`station_id`)
        REFERENCES `station` (`id`)
) ENGINE=InnoDB CHARACTER SET='utf8';
For Turbo Hour the course references four stations with Kanwar Horizons being both the start and finish station.
Code:
+----+---------+------------+------------+-------------+---------------+
| id | race_id | station_id | start_line | finish_line | station_order |
+----+---------+------------+------------+-------------+---------------+
|  6 |       2 |          2 |          1 |           1 |          NULL |
|  8 |       2 |          4 |       NULL |        NULL |          NULL |
| 10 |       2 |          6 |       NULL |        NULL |          NULL |
| 12 |       2 |          8 |       NULL |        NULL |          NULL |
+----+---------+------------+------------+-------------+---------------+

[size=+2]Competitor table[/size]
The competitor table defines a race competitor with his CMDR name and, if different, forum name.
Code:
CREATE TABLE `competitor`
(
    `id` INTEGER NOT NULL AUTO_INCREMENT,
    `cmdr_name` VARCHAR(64) NOT NULL,
    `forum_name` VARCHAR(64),
    PRIMARY KEY (`id`),
    UNIQUE INDEX `cmdr_name` (`cmdr_name`)
) ENGINE=InnoDB CHARACTER SET='utf8';
For example:
Code:
+----+------------------+-------------+
| id | cmdr_name        | forum_name  |
+----+------------------+-------------+
|  2 | furrycat         | NULL        |
|  9 | KliggJr          | robinjb     |
+----+------------------+-------------+

[size=+2]Hull table[/size]
The hull table lists the different ship types that people used.
Code:
CREATE TABLE `hull`
(
    `id` INTEGER NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(64) NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `name` (`name`)
) ENGINE=InnoDB CHARACTER SET='utf8';
Very simple:
Code:
+----+----------------------+
| id | name                 |
+----+----------------------+
|  2 | Imperial Courier     |
|  3 | Asp Explorer         |
|  5 | Hauler               |
+----+----------------------+

[size=+2]Ship table[/size]
The ship table records competitors' ships.
Code:
CREATE TABLE `ship`
(
    `id` INTEGER NOT NULL AUTO_INCREMENT,
    `competitor_id` INTEGER NOT NULL,
    `hull_id` INTEGER NOT NULL,
    `name` VARCHAR(64) NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `hull_name` (`competitor_id`, `hull_id`, `name`),
    INDEX `ship_FI_2` (`hull_id`),
    CONSTRAINT `ship_FK_1`
        FOREIGN KEY (`competitor_id`)
        REFERENCES `competitor` (`id`),
    CONSTRAINT `ship_FK_2`
        FOREIGN KEY (`hull_id`)
        REFERENCES `hull` (`id`)
) ENGINE=InnoDB CHARACTER SET='utf8';
For example:
Code:
+----+---------------+---------+------------------------+
| id | competitor_id | hull_id | name                   |
+----+---------------+---------+------------------------+
| 37 |            23 |       2 | Crater Creator         |
| 73 |            41 |       3 | The Nomad              |
+----+---------------+---------+------------------------+

[size=+2]Entry table[/size]
The entry table is where things get interesting. We record the race, ship, any endorsements and a bunch of cache data to save future lookups.
Code:
CREATE TABLE `entry`
(
    `id` INTEGER NOT NULL AUTO_INCREMENT,
    `race_id` INTEGER NOT NULL,
    `ship_id` INTEGER NOT NULL,
    `endorsements` INTEGER NOT NULL,
    `lap_distance` FLOAT NOT NULL,
    `start_time` DATETIME NOT NULL,
    `complete_laps` FLOAT NOT NULL,
    `total_distance` FLOAT NOT NULL,
    `penalty_time` INTEGER,
    `bonus_time` INTEGER,
    `raced_time` INTEGER NOT NULL,
    `total_time` INTEGER NOT NULL,
    `fastest_lap` INTEGER NOT NULL,
    `average_lap` INTEGER NOT NULL,
    `best_speed` FLOAT NOT NULL,
    `average_speed` FLOAT NOT NULL,
    PRIMARY KEY (`id`),
    INDEX `entry_FI_1` (`race_id`),
    INDEX `entry_FI_2` (`ship_id`),
    CONSTRAINT `entry_FK_1`
        FOREIGN KEY (`race_id`)
        REFERENCES `race` (`id`),
    CONSTRAINT `entry_FK_2`
        FOREIGN KEY (`ship_id`)
        REFERENCES `ship` (`id`)
) ENGINE=InnoDB CHARACTER SET='utf8';
Here are the prizewinning entries in the race:
Code:
+----+---------+---------+--------------+--------------+---------------------+---------------+----------------+--------------+------------+------------+------------+-------------+-------------+------------+---------------+
| id | race_id | ship_id | endorsements | lap_distance | start_time          | complete_laps | total_distance | penalty_time | bonus_time | raced_time | total_time | fastest_lap | average_lap | best_speed | average_speed |
+----+---------+---------+--------------+--------------+---------------------+---------------+----------------+--------------+------------+------------+------------+-------------+-------------+------------+---------------+
| 51 |       2 |      45 |            8 |       131.29 | 2016-02-01 14:53:15 |          4.86 |         637.67 |            9 |        350 |       3959 |       3959 |         771 |         815 |     613.03 |        579.85 |
| 63 |       2 |      37 |            8 |       131.29 | 2016-02-03 15:35:35 |          5.19 |         681.47 |           85 |        360 |       4045 |       4045 |         758 |         779 |     623.54 |         606.5 |
| 75 |       2 |      47 |            0 |       131.29 | 2016-02-07 13:13:23 |          4.53 |          594.5 |          224 |       NULL |       3824 |       3824 |         830 |         844 |     569.45 |        559.68 |
| 77 |       2 |      35 |            8 |       131.29 | 2016-02-08 00:09:00 |          4.86 |         637.67 |          103 |        268 |       3971 |       3971 |         800 |         817 |      590.8 |        578.09 |
| 87 |       2 |      71 |            8 |       131.29 | 2016-02-12 11:11:00 |          5.19 |         681.47 |          123 |        384 |       4107 |       4107 |         774 |         791 |     610.65 |        597.34 |
| 89 |       2 |      53 |           65 |       113.17 | 2016-02-12 18:34:00 |             1 |         113.17 |         2851 |       NULL |        749 |       3600 |         749 |        3600 |     543.94 |        113.17 |
+----+---------+---------+--------------+--------------+---------------------+---------------+----------------+--------------+------------+------------+------------+-------------+-------------+------------+---------------+

[size=+2]Lap table[/size]
For each entry we record information on individual laps in the lap table. We track hull percentage at the start and end of the lap so as to calculate joker bonus.
Code:
CREATE TABLE `lap`
(
    `id` INTEGER NOT NULL AUTO_INCREMENT,
    `entry_id` INTEGER NOT NULL,
    `lap_number` INTEGER NOT NULL,
    `hull_start` INTEGER,
    `hull_end` INTEGER,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `entry_lap` (`entry_id`, `lap_number`),
    CONSTRAINT `lap_FK_1`
        FOREIGN KEY (`entry_id`)
        REFERENCES `entry` (`id`)
) ENGINE=InnoDB CHARACTER SET='utf8';
cookiehole's winning entry had these laps:
Code:
+-----+----------+------------+------------+----------+----------+
| id  | entry_id | lap_number | hull_start | hull_end | repaired |
+-----+----------+------------+------------+----------+----------+
| 329 |       87 |          1 |        100 |       96 |     NULL |
| 331 |       87 |          2 |         96 |       96 |     NULL |
| 333 |       87 |          3 |         96 |       96 |     NULL |
| 335 |       87 |          4 |         96 |       96 |     NULL |
| 337 |       87 |          5 |         96 |       96 |     NULL |
| 339 |       87 |          6 |       NULL |     NULL |     NULL |
+-----+----------+------------+------------+----------+----------+

[size=+2]Laptime table[/size]
The laptime table records the arrival times at each station along the lap.
Code:
CREATE TABLE `laptime`
(
    `id` INTEGER NOT NULL AUTO_INCREMENT,
    `lap_id` INTEGER NOT NULL,
    `station_order` INTEGER NOT NULL,
    `station_id` INTEGER NOT NULL,
    `arrival` DATETIME NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `lap_arrival` (`lap_id`, `arrival`),
    UNIQUE INDEX `lap_station` (`lap_id`, `station_order`),
    INDEX `laptime_FI_2` (`station_id`),
    CONSTRAINT `laptime_FK_1`
        FOREIGN KEY (`lap_id`)
        REFERENCES `lap` (`id`),
    CONSTRAINT `laptime_FK_2`
        FOREIGN KEY (`station_id`)
        REFERENCES `station` (`id`)
) ENGINE=InnoDB CHARACTER SET='utf8';
Using that information we can calculate individual lap times, work out averages across all competitors and produce a chronological view of the race.
Code:
+------+--------+---------------+------------+---------------------+
| id   | lap_id | station_order | station_id | arrival             |
+------+--------+---------------+------------+---------------------+
| 1573 |    329 |             1 |          2 | 2016-02-12 11:11:00 |
| 1575 |    329 |             2 |          6 | 2016-02-12 11:13:20 |
| 1577 |    329 |             3 |          4 | 2016-02-12 11:17:25 |
| 1579 |    329 |             4 |          8 | 2016-02-12 11:21:12 |
| 1581 |    329 |             5 |          2 | 2016-02-12 11:24:02 |
| 1583 |    331 |             1 |          2 | 2016-02-12 11:24:02 |
| 1585 |    331 |             2 |          6 | 2016-02-12 11:26:39 |
| 1587 |    331 |             3 |          4 | 2016-02-12 11:30:30 |
| 1589 |    331 |             4 |          8 | 2016-02-12 11:34:09 |
| 1591 |    331 |             5 |          2 | 2016-02-12 11:36:56 |
| 1593 |    333 |             1 |          2 | 2016-02-12 11:36:56 |
| 1595 |    333 |             2 |          6 | 2016-02-12 11:39:44 |
| 1597 |    333 |             3 |          4 | 2016-02-12 11:43:39 |
| 1599 |    333 |             4 |          8 | 2016-02-12 11:47:25 |
| 1601 |    333 |             5 |          2 | 2016-02-12 11:50:11 |
| 1603 |    335 |             1 |          2 | 2016-02-12 11:50:11 |
| 1605 |    335 |             2 |          6 | 2016-02-12 11:52:56 |
| 1607 |    335 |             3 |          4 | 2016-02-12 11:56:51 |
| 1609 |    335 |             4 |          8 | 2016-02-12 12:00:36 |
| 1611 |    335 |             5 |          2 | 2016-02-12 12:03:28 |
| 1613 |    337 |             1 |          2 | 2016-02-12 12:03:28 |
| 1615 |    337 |             2 |          6 | 2016-02-12 12:06:19 |
| 1617 |    337 |             3 |          4 | 2016-02-12 12:10:07 |
| 1619 |    337 |             4 |          8 | 2016-02-12 12:13:55 |
| 1621 |    337 |             5 |          2 | 2016-02-12 12:16:40 |
| 1623 |    339 |             1 |          2 | 2016-02-12 12:16:40 |
| 1625 |    339 |             2 |          6 | 2016-02-12 12:19:27 |
+------+--------+---------------+------------+---------------------+

Evil SQL to calculate station-to-station speed:
Code:
select s1.name as station1, s2.name as station2,
  avg((distance / (timestampdiff(second, l1.arrival, l2.arrival) / 3600))) as speed
from laptime l1, laptime l2, station s1, station s2, lap, entry, course, raikogram
where l1.lap_id=l2.lap_id
  and l1.station_id=s1.id
  and l2.station_id=s2.id
  and l1.lap_id=lap.id
  and lap.entry_id=entry.id
  and system1=(
    select case
      when s1.system_id<s2.system_id then s1.system_id
      else s2.system_id
    end
  )
  and system2=(
    select case
    when s1.system_id<s2.system_id then s2.system_id
    else s1.system_id
    end
  )
  and course.race_id=entry.race_id
  and l2.station_order=l1.station_order+1
  and entry.race_id=:race_id
  and entry.id in (:entry_list)
group by station1, station2
order by speed desc
As it turned out people were really good about sending their screenshots in chronological order, or posting videos with a list of interesting timestamps. That made entering data less painful than it might have been, and made me feel bad for submitting all my entries to other people's races in a haphazard manner.

I wasn't expecting the screenshots to be so nicely organised so I spent a lot of time tweaking the race-o-matic to let me enter data in an arbitrary order.

When opening up the entry editor I see the stations laid out in a particular order.

race-o-matic_1.png

I enter the start time of the race in the first row and column. Note how the tool now does two things to make my life easier. It updates the placeholder text for all subsequent fields with the last timestamp, and creates a new lap column.

race-o-matic_2.png

The first station visited by CMDR Aken B. was Watts Dock, which is not the next station in the current order. When I enter the time the tool automatically reorders the lap to make Watts Dock the second station.

race-o-matic_3.png

I don't have to enter a complete timestamp every time, only the shortest changed part at the end. The next leg was Bell Station at 3302-02-12 11:17:25. Because the last timestamp was 3302-02-12 11:13:20 I only have to enter 7:25 and the rest of the (unchanged) timestamp is added for me.

race-o-matic_4.png

race-o-matic_5.png

After I enter the arrival time at Kanwar Horizons the tool automatically fills in the start time for lap 2.

race-o-matic_6.png

Now that the first lap is complete I am not allowed to enter times out of order. Thus the possiblility of making a mistake is lessened, and any attempt to cheat (which needless to say no one did) would be noticed. In the screenshot below I incorrectly entered the second leg time against the third station and the mistake is immediately highlighted.

race-o-matic_7.png

And in the next screenshot I accidentally enter 24:09 instead of the correct 34:09 for the next station. The tool detects the error as it is an earlier time than the last one entered.

race-o-matic_8.png

If people hadn't sent their screenshots in order I could have simply entered the times as I found them. The tool would highlight the discrepancy. In the screenshot below I deliberately enter the return to Turbo and then the next lap's arrival at Rolland.

race-o-matic_9.png

Then when I added the correct time it would automatically sort it into the right column

race-o-matic_10.png

The first docking after an entry's allotted time is up is highlighted in blue and subsequent times, ie times which don't count - are highlighted in orange.

race-o-matic_11.png

In this case the times are legit because the joker was used. If I enter the hull percentages and tick the joker box the tool calculates the bonus time and recolours the dockings. Green fields denote stations visited within bonus time.

race-o-matic_12.png

Once the entry is submitted it is saved to the database. The race standings page of the race-o-matic shows the classification in HTML and with a double click of the mouse copies a BBcode version to the clipboard so I can paste it on to the forum quickly.

Graphs are generated with Plotly.js based on the results of SQL queries run by the tool.

If you braved the spoiler you will have noticed - and if you didn't I am telling you - that entries in the database use real dates so that time calculations work properly. Entering data uses the server's 34th century date. The race-o-matic automatically converts back and forth between epochs.
 
crazy amount of good work went into the race furry well done sir. congrats to cookie and akenb, the clue was in the banner.. courier ftw!
 
I added in cookiehole and Milner's full race videos as I wanted to compare what they were doing and learn everywhere I could improve my time in future. And there are so many things I didn't think of :p

And near the end, it gets pretty close to Cookiehole & Aken B almost lapping me.

Anyway, thought I'd share in case others might want to see the difference also :)
(Skip ahead to 2:05 to start at the comparison)

[video=youtube_share;rEGN2eioCVM]https://youtu.be/rEGN2eioCVM[/video]
 
Last edited:
Top Bottom