在计时应用程序中排序赛车手

时间:2013-04-02 13:41:02

标签: delphi sorting datetime racing

我正在创建一个使用AMB MyLaps解码器P3协议的应用程序。

我无法理解基于圈数和单圈时间对赛车手进行排序的方法。例如,第1个人做了3圈,第2个人做了2圈。但那么我如何订购2人在同一圈的情况呢?

这是我用来保存信息的记录:

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;

为每个赛车手创建一条新记录。

我目前使用的代码是:

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;

但效果不好:)。

4 个答案:

答案 0 :(得分:2)

我从你的评论中假设你已经将问题分解为排序和比较,并且你已经完成了排序部分。这留下了订单比较。

您需要一个功能,首先根据完成的圈数执行词典顺序比较,其次是从本圈开始以来的时间。基本上它看起来像这样:

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;

您会在CompareValue中找到Math,在CompareDateTime找到DateUtils

我不确定的是lastRTCTime值是什么意思。您可能需要否定调用CompareDateTime的结果以获得您想要的结果。

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

另外,如果在一圈中有超车会怎么样?据推测,在赛车手完成当前一圈之前,你将无法检测到这一点。

答案 1 :(得分:1)

不要自己进行排序算法,尝试这种技术(如果你有Delphi版本兼容):Best way to sort an array

你的功能可能如下所示:

uses Types;

function CustomSort(const Left, Right: TTimingRecord): Integer
begin
  If (left.laps > right.laps) then
     result := GreaterThanValue
  else 
  if (left.laps < right.laps) then
      result := LessThanValue
  else 
  begin
      // Same laps count... Test on LastRTCTime 
      if (left.lastRTCTime < right.lastRTCTime) then
          result := GreaterThanValue1
      else
      if (left.lastRTCTime > right.lastRTCTime) then
          result := LessThanValue
      else
          result := EqualsValue; 
  end;
end));

答案 2 :(得分:0)

可能更容易将其视为两种不同的排序。

显然你知道冒泡排序方法,所以我不会进入那个。

对你的排序进行2次传递。 1,你排序圈。

第二,您将浏览整个已排序圈数列表。找到相同圈数值的数组中的起点和终点。从开始点和结束点再次进行排序,但这次仅比较次要值。如果相同值的计数大于1,则迭代所有相同的次要值。

答案 3 :(得分:0)

此代码是关于使用索引对数据进行排序。比冒泡更快的方式。 它是动态的,并提供从数组中的起点到终点进行排序的能力。 代码本身比Bubble-Sort更大,但没有多少算法可以比较速度。 代码(在理解其工作原理时)可以轻松修改以适应大多数类型的排序。在65536个字符串的数组上,它只需要进行17次比较(或者大约有) 与Bubble Sort相比,每个比较周期有更多CPU周期,但仍然是最快的方法之一。 搜索与BTREE一样快。实际的排序可能更慢,但之后数据更容易管理,而不需要平衡树。

享受。

注意:例程并不是实际问题的完整解决方案,但它提供了极快的快速方法的开始。


TYPE
  DynamicIntegerArray = ARRAY OF INTEGER;
  DynamicStringArray  = ARRAY OF STRING;

VAR
  BinSortLo, BinSortMid, BinSortHi : INTEGER; 

FUNCTION FindMid:INTEGER;
  BEGIN
    FindMid:=BinSortLo+((BinSortHi-BinSortLo) DIV 2);
  END;

PROCEDURE ShiftIndexUpAndStorePointer(VAR ArrParamIndex: DynamicIntegerArray; HighBound:INTEGER);
  VAR
    x : INTEGER;
  BEGIN
    FOR x:=HighBound-1 DOWNTO BinSortMid DO ArrParamIndex[x+1] := ArrParamIndex[x];// Shift the index.
    ArrParamIndex[BinSortMid]:=HighBound;// Store the pointer to index at its sorted place
  END;

PROCEDURE BinarySortUp(CONST ArrParam:DynamicStringArray; VAR ArrParamIndex: DynamicIntegerArray; CONST LoBound,HighBound:INTEGER); OVERLOAD;
  VAR
    TempVar : STRING;
  BEGIN
    BinSortLo:=LoBound; BinSortHi:=HighBound; BinSortMid:=FindMid;
    TempVar := ArrParam[HighBound];
    REPEAT
  IF TempVar>ArrParam[ArrParamIndex[BinSortMid]] THEN BinSortLo:=BinSortMid ELSE BinSortHi:=BinSortMid;
  BinSortMid:=FindMid;
    UNTIL (BinSortMid=BinSortLo); {OR (BinSortMid=BinSortHi);}
    IF TempVar>ArrParam[ArrParamIndex[BinSortMid]] THEN INC(BinSortMid);// We always need a last check just in case.
    ShiftIndexUpAndStorePointer(ArrParamIndex,HighBound);
  END;

PROCEDURE DynamicCreateIndex(CONST ArrParam:DynamicStringArray; VAR ArrParamIndex: DynamicIntegerArray; CONST LoBound,HighBound:INTEGER);
  VAR
    x : INTEGER;
  BEGIN
    FOR x:=LoBound TO HighBound DO
    BinarySortUp(ArrParam,ArrParamIndex,LoBound,x);
  END;


BEGIN
{
1. Create your STRING ARRAY as a DynamicStringArray. 
2. Create your INDEX ARRAY as a DynamicIntegerArray.
3. Set the size of these arrays to any INTEGER size and fill the strings with data.
4. Run a call to DynamicCreateIndex(YourStringArray,YourIndexArray,0,SizeOfArray
Now you have a sorted Index of all the strings.

}
END.