The online racing simulator
Time addition penalties - LFS behaviour
While programming the modules that handle the race results for my league website I've come up with some unusual cases that I was curious about how LFS would deal with them. It's about time addition penalties.

The question is: how one driver with a time penalty compares to another one without any penalty but finishes a lap behind.


First test (prueba.mpr attached):

On a 3 laps race with mandatory pitstop, 2 drivers, the leader receives a +30 seconds penalty during his pitstop for speeding in the pitlane. This guy goes on and laps the other driver and finishes the 3 laps race length with his penalty (at this moment the "laps and laptime indicator" in the OSD turns orange). After him the other driver crosses the finish line with 2 laps and no penalty. What happens now? In this case it's quite confussing as the results table doesn't get filled. It only shows the first guy with the '?' in the position. The second driver who crossed the line doesn't appear, he crossed the line after the leader but didn't finish the race yet! This second driver must complete another lap, his third, and then LFS will generate the IS_RES packets for both drivers and sort them accordingly.

Results:
1st: the first guy who received the +30s penalty, with 3 laps and 3:25 total time (+30s added).
2nd: the other guy with no penalty, 3 laps and 3:52 total time.

I think this is OK, but confusing, because the second driver thinks he has finished when he crosses the line after the leader because the laps in the top right corner are orange. The truth is, given the leaders penalty, when he crosses the finish line LFS doesn't consider that the race has finished and so any other driver must complete the race length before comparing times.


Second test (prueba2.mpr attached):

This one is trickier! Now we have 3 cars and 2 laps (no pitstop). Driver A is issued a +45 seconds penalty by the admin (he could have made a jump start and the result would be the same). Driver B runs like hell and catches up to both A and C. When driver B finishes his second lap the order is this: A (+45s) -> B -> C. The time difference between A and C is about 4 seconds at this point. The race is won by B with 2 laps and 1:54 total time. After him C finishes in '?' pos with 1 lap and 1:57 (IS_RES pending for him). Driver A completes his second lap and finishes with 2 laps and 3:29 total time.

Results:
1st: B, 2 laps, 1:54 time.
2nd: A, 2 laps, 3:29 time (+45 added).
3rd: C, 1 lap, 1:57 time.

How does this look? Consider that drivers A and C were 4 seconds apart when B finished the race, with the difference that A was ahead of B and completed a second lap, and C was behind and finished with +1 lap.

If A had been lapped by B he had finished with +1 lap, and with the +45 seconds he would have gone 41 seconds behind C, final results being B -> C -> A.

If C hadn't been lapped by B, both A and C would have done the second lap, and probably the 4 seconds gap wouldn't have grown to more than 45 seconds in that lap. The final result would have been also B -> C -> A.

What happens here is that drivers are sorted first on the number of laps completed, and second on the time elapsed to complete those laps. Driver A has completed one more lap than C, and the +45s penalty doesn't mean any harm to him.

If it had been a stop&go instead of a +45s the thing would change, because at some point he would have needed to complete the penalty and the 4 seconds gap to C would have vanished. And there's no possibility to complete a stop&go on the last lap because you get automatically disqualified for that.



Any thoughts on this? I'm trying to make an automated system that handles penalties well, but I don't know what to do in these situations! What I do know is that I don't like these time addition penalties because they lead to weird consequences like the ones described
Attached files
prueba.mpr - 96.9 KB - 174 views
prueba2.mpr - 109.1 KB - 156 views
Had a quick read.

Situation 1 is really confusing. If I was driver B I really wouldn't know what to do Driver B should be classified one lap down IMO, so LFS shouldn't oblige him to do another lap.

Situation 2 now... From what I know time penalties won't knock you out of the lead lap in real life. One of the example that comes in my mind is the DTM race at Barcelona in 2008(IIRC), when someone(Green IIRC) had a time penalty added after the race which possibly could knock him out of the lead lap and make him loose even more positions if it was issued during the race(with a Drive Through for example).

Of course the situation might look unfair... And I've always wondered why no one had it another look in real life racing. But of course those kind of situations are very rare, even on LFS.
I don't like these situations, but of course they are rare. I gues I'll keep it the way LFS shows it.

I'm going to make a change to add drivers that have completed a certain percentage of the race length (in laps) as classified, which LFS does not. This implies re-sorting the original results in some cases. So I went ahead and thought about other cases that might lead to changing LFS' results because of other conditions.

One example of what I said above, from a FRL race:
http://www.funracingleague.com ... 2_race2_results_race.html

Let's say that the rule say "if a driver completes 90% of the number of laps (rounded down to the nearest whole number), he is considered as classified". Then, on this race in the example driver "[S-R] Pilu" in pos 29th with DNF and 19/20 laps completed (more than 90%), would move up to pos 27th, because he completed 19 laps in less time than "[Q3] nachogo27" and "yacomo87".

LFS doesn't consider drivers who haven't finished the race for the race results (which is a shame), and you can't either grab that info from the MPR replay header (it only contains info about finished drivers). I'm controlling that via insim, but in case the insim fails I want to have some tool to get info about players who participated in the race but didn't finish. I tried LFSStats CSV files but they contain too little info
-
(DarkTimes) DELETED by DarkTimes
Normally, IRL, if the driver who won gets a time penalty given, the race results and timings are calculated based on that driver not having had the penalty, as time penalties are often challenged. The penalty is then added afterwards.
IMO this would be the best way for LFS to handle it.

However in the case of your DTM example, I'm not sure how it could be calculated to be fair (especially if the driver with the penalty wasn't the leader).

Regarding %age of laps for classification, that would probably be best handled by InSim (using the data received as each person completes a lap to keep lapcounts throughout the race) as there are so many possible variations on classification rules.
I don't know if InSim sends a packet with the "<PLAYER> did not finish" messages. If it doesn't, that would be a nice feature to have, containing info about number of laps. That wouldn't include players who entered spectate to clear the track prior to the final lap though afaik.
The problem with players that don't finish the race is that they can join the track several times during one race and do some laps one time, some other laps another time and so on. It's hard for LFS to consider those players into the final results and that's why we only have results for players who actually finish the race.

I'm controlling this manually using LAP and RES packets. Every time a player completes a lap I store a result for him with his current info. Basically I build all the info contained in an IS_RES packet based on what I get from the IS_LAP. If the player enters pits, spectates or loses connection, his result is stored at that point and if he rejoins the track again he won't generate new results. This is the way I get results from everybody, even drivers who didn't complete a single lap.

I wrote a small InSim application called "CSV Generator" to generate CSV files with results for races and qualys and it's working quite well at the moment, but some situations are tricky. I was going to use LFS Stats CSV files but I didn't have enough info in them, so I wrote my own and made some fixes for drivers who rejoin track after having participated in the race (ie, "driver starts race -> driver disconnects -> driver reconnects -> driver joins track when race is over" would make him appear as "0 laps completed" in LFS Stats).
Yes, pruning results from InSim can be complicated if you want to handle DNFs. You have to decide exactly what you consider to be a DNF. When I have written such a program before, I have counted anyone who leaves (PLL) before they have received a result (RES) to be a DNF. Here is a very rough idea of the logic I have implemented.
  • Race start, create blank result for each player with DNF flag set to true
  • Add each completed lap to current result
  • If player leaves and rejoins, clear result laps
  • If player gets RES, set DNF to false
  • Race ends*, log results
This basically gives you a big array of result objects for everyone in the race. To get the actual race results you need to sort the array in a certain order.
  • Sort by DNF
  • Sort by laps completed (count of all completed laps)
  • Sort by total elapsed time (sum of all completed lap times)
In previous programs I have written this has given me a nice list of results, correctly ordered with the DNFs last. If someone leaves and rejoins, only their most recent start is logged, which I think is fair. You could switch it round so only their first result is logged, or even log all their results and sort them by time etc..

Anyway, I've probably not explained this very well, I can knock up some examples tomorrow when I'm sober if you need.

* Race ends if number of results == total number of players, if a TINY_REN is received, or if a new race starts (RST).
B compleaded the distance first, A compleated the distance, C only did half distance.

It does not matter that he was only four seconds away, it matters that he did not do an equal amount of distance to everyone else, he should be last because he did not do the same race distance as the people on the lead lap.
Real race results don't take into consideration distance travelled, they are taken from your relative position the last time you completed a lap. Also measuring distance is fraught with issues (plus not how it is done in real life). There is a thread somewhere on the forum where I have discussed this at length. I'm not saying my way is the best, simplest or most efficient, but I determined it back when I was running leagues, and it gives almost 100% results, depending on what your definition of DNF in LFS is.
Quote from Dygear :B compleaded the distance first, A compleated the distance, C only did half distance.

It does not matter that he was only four seconds away, it matters that he did not do an equal amount of distance to everyone else, he should be last because he did not do the same race distance as the people on the lead lap.

Extrapolate 2 laps / 1 lap, to 40 laps / 39 laps, so it's not "half the distance". The fact that A completed the distance does not mean that he should have completed it.

Let's say that driver B, the winner, completes all 40 laps in 40:00. Let's now say that driver A, with +45s penalty, completes 39 laps in 39:55. Then he completes 40 laps in 40:57, and we add +45 to this for a final total of 41:42.

If you had applied the +45s penalty on lap 39 instead of 40, the time for A at the end of lap 39 would have been 39:55 + 45 = 40:40. This means that he has taken longer to complete 39 laps (40:40) than what driver B took to complete 40 (40:00), which can be considered as "driver A finishes with 39 laps (+1 lap) with a total time of 40:40 (penalty included)".

I think that is the key, that you must apply the penalty at each lap and decide if the driver has already finished or not. That's what I'm going to do. When a player finishes a lap I check if he has a penalty and then compare his total time on the previous lap + penalty to the finishing time of the race winner.

I just woke up, I will think about it more later today.

FGED GREDG RDFGDR GSFDG