Search code examples
delphisortingdatetimeracing

Sorting Racers in timing application


I am creating an application which uses the AMB MyLaps decoder P3 Protocols.

I can't get my head around a way to sort the racers out based on laps and lap times. For example, the person in 1st has done 3 laps, the person in 2nd has done 2 laps. But then how do I order a situation where 2 people are on the same lap?

This is the record I'm using to hold the information:

type
  TTimingRecord = record
    position: integer;
    transId: integer;
    racerName:  string;
    kartNumber: integer;
    lastPassingN: integer;
    laps: integer;
    lastRTCTime:  TDateTime;
    bestTimeMs: Extended;
    lastTimeMs: Extended;
    gapTimeMs:  Extended;
    splitTimeMs:  Extended;
    timestamp:  TDateTime;
  end;

A new record is created for each racer.

The code I'm currently using is:

procedure sortRacers();
var
  Pos, Pos2: Integer;
  Temp: TTimingRecord;
  GapTime: Extended;
begin
  for Pos := 0 to length(DriversRecord)-1 do
  begin
    for Pos2 := 0 to Length(DriversRecord)-2 do
    begin
      if(DriversRecord[Pos2].laps < DriversRecord[Pos2+1].laps)then
      begin
        Temp := DriversRecord[Pos2];
        DriversRecord[Pos2] := DriversRecord[Pos2+1];
        DriversRecord[Pos2+1] := Temp;
      end
      else if DriversRecord[Pos2].laps = DriversRecord[Pos2+1].laps then
           begin
             if DriversRecord[Pos2].lastRTCTime > DriversRecord[Pos2+1].lastRTCTime then
             begin
              Temp := DriversRecord[Pos2];
              DriversRecord[Pos2] := DriversRecord[Pos2+1];
              DriversRecord[Pos2+1] := Temp;
             end;
           end;
    end;
  end;

  for pos := 1 to length(DriversRecord) -1 do   //Gap Time
  begin
    if DriversRecord[Pos].laps = DriversRecord[0].laps then
    begin
      DriversRecord[Pos].gapTimeMs := DriversRecord[Pos].lastRTCTime - DriversRecord[0].lastRTCTime;

      DriversRecord[Pos].splitTimeMs := DriversRecord[Pos].lastRTCTime - DriversRecord[Pos-1].lastRTCTime;
    end;
  end;
end;

But doesn't work too well :)


Solution

  • I'm assuming from your comment to the question, that you have decomposed the problem into sorting and comparing, and that you have got the sorting part covered. Which leaves order comparison.

    You need a function that will perform a lexicographic order comparison based first on the number of laps completed, and secondly on the time since the start of this lap. Basically it will look like this:

    function CompareRacers(const Left, Right: TTimingRecord): Integer;
    begin
      Result := CompareValue(Left.laps, Right.laps);
      if Result=0 then
        Result := CompareDateTime(Left.lastRTCTime, Right.lastRTCTime);
    end;
    

    You'll find CompareValue in Math and CompareDateTime in DateUtils.

    What I'm not sure about is what the sense of the lastRTCTime values is. You may need to negate the result of the call to CompareDateTime to get the result you desire.

    Result := -CompareDateTime(Left.lastRTCTime, Right.lastRTCTime);
    

    Also, what happens if there is overtaking during the lap? Presumably you won't be able to detect that until the racers complete the current lap.