program AnaData;
{$MODE OBJFPC}{$H+}
uses
Classes, StrUtils, DateUtils, SysUtils;
var
DataList : TStringList;
PlateTimes : TStringList;
// Sort List on index (automatically comes platenumber and then time provided
// tha the list stored on disk is listed in order of time.
function SortListOnIndex(List: TStringList; ListIndex1: Integer; ListIndex2: Integer):Integer;
var
Index1, Index2: Integer;
begin
Index1 := StrToInt(ExtractWord(1, List[ListIndex1], [',']));
Index2 := StrToInt(ExtractWord(1, List[ListIndex2], [',']));
result := Index1 - Index2;
end;
// sort list on plate, then time (and if those fail !? , then index)
function SortListOnPlate(List: TStringList; ListIndex1: Integer; ListIndex2: Integer):Integer;
var
Index1, Index2: Integer;
Plate1, Plate2 : Integer;
Time1 , Time2 : TDateTime;
DTSettings : TFormatSettings;
begin
Plate1 := StrToInt(ExtractWord(2, List[ListIndex1], [',']));
Plate2 := StrToInt(ExtractWord(2, List[ListIndex2], [',']));
result := Plate1 - Plate2;
// platenumbers are the same, differentiate with time
if (result = 0) then
begin
DTSettings.TimeSeparator := ':';
DTSettings.DecimalSeparator :='.';
DTSettings.ShortTimeFormat := 'hh:nn:ss.zzz';
Time1 := StrToTime(ExtractWord(3, List[ListIndex1], [',']), DTSettings);
Time2 := StrToTime(ExtractWord(3, List[ListIndex2], [',']), DTSettings);
Result := CompareDateTime(Time1, Time2);
// should not be happening but just in case differentiate on index
if (Result = 0) then
begin
Index1 := StrToInt(ExtractWord(1, List[ListIndex1], [',']));
Index2 := StrToInt(ExtractWord(1, List[ListIndex2], [',']));
result := Index1 - Index2;
end;
end;
end;
function SortListOnTime(List: TStringList; ListIndex1: Integer; ListIndex2: Integer):Integer;
var
Index1, Index2 : Integer;
Time1 , Time2 : TDateTime;
DTSettings : TFormatSettings;
begin
DTSettings.TimeSeparator := ':';
DTSettings.DecimalSeparator :='.';
DTSettings.ShortTimeFormat := 'hh:nn:ss.zzz';
Time1 := StrToTime(ExtractWord(3, List[ListIndex1], [',']), DTSettings);
Time2 := StrToTime(ExtractWord(3, List[ListIndex2], [',']), DTSettings);
Result := CompareDateTime(Time1, Time2);
// in case times are same, sort on first entry measured/listed.
if (Result = 0) then
begin
Index1 := StrToInt(ExtractWord(1, List[ListIndex1], [',']));
Index2 := StrToInt(ExtractWord(1, List[ListIndex2], [',']));
result := Index1 - Index2;
end;
end;
procedure DumpList(List: TStringList);
var
i : Integer;
Index : String;
Plate : String;
Time : String;
LineS : String;
begin
WriteLn('==================');
for i := 0 to Pred(List.Count) do
begin
LineS := List[i];
Index := ExtractWord(1, LineS, [',']);
Plate := ExtractWord(2, LineS, [',']);
Time := ExtractWord(3, LineS, [',']);
WriteLn('item[',i:2,']', ' index = ', Index:3,' Plate = ', Plate:3, ' Time = ', Time);
end;
WriteLn('==================');
end;
procedure DumpPlateTimes(List: TStringList);
var
i : Integer;
begin
WriteLn('==================');
for i := 0 to Pred(List.Count)
do WriteLn('item[', i:2,'] = ', List[i]);
WriteLn('==================');
end;
procedure ExtractPlateTimes(SortedList: TStringList; PlateTimeList: TStringList);
var
SortedIndex : Integer;
PlateNr : Integer;
CurrentPlate : Integer;
TimeAsStr : String;
PlateTimes : String;
begin
CurrentPlate := -1;
PlateTimes := '';
for SortedIndex := 0 to Pred(SortedList.Count) do
begin
PlateNr := StrToInt(ExtractWord(2, SortedList[SortedIndex], [',']));
// account for the very first entry;
if CurrentPlate = -1 then CurrentPlate := PlateNr;
// Platenumbers differs from previous so add data to platelist
// and re-init some variables
if (CurrentPlate <> PlateNr) then
begin
PlateTimeList.Add(IntToStr(CurrentPlate) + ',' + PlateTimes);
PlateTimes := '';
CurrentPlate := PlateNr;
end;
TimeAsStr := ExtractWord(3, SortedList[SortedIndex], [',']);
// account for (not) first entry
if (PlateTimes <> '') then PlateTimes := PlateTimes + ',';
// Add next time for current active plate
PlateTimes := PlateTimes + TimeAsStr;
end;
// i initially forgot to these two lines below
// we stil could have a last entry which was not written
if (PlateTimes <> '') then PlateTimeList.Add(IntToStr(CurrentPlate) + ',' + PlateTimes);
end;
procedure AnalyzeData(List: TStringList);
var
i : Integer;
begin
// 'insert' index number, just because we can
for i := 0 to Pred(List.Count)
do List[i] := IntToStr(i) + ',' + List[i];
// Dump the list as is
DumpList(List);
// sort the list on Platenumber
List.CustomSort(@SortListOnPlate);
DumpList(List);
// sort the list on times
List.CustomSort(@SortListOnTime);
DumpList(List);
// dump plate times into another stringlist
List.CustomSort(@SortListOnPlate); // Make sure to sort on plate + time
ExtractPlateTimes(List, PlateTimes); // Store individual plates + times into another stringlist
DumpPlateTimes(PlateTimes); // print the list
end;
begin
PlateTimes := TStringList.Create;
DataList := TStringList.Create;
DataList.LoadFromFile('Data.txt');
// remove the "Plate,Time" header
if (DataList.Count > 0) then DataList.Delete(0);
AnalyzeData(DataList);
DataList.Free;
PlateTimes.Free;
end.