TAChart: TCalculatedChartSource.AccumulationRange = 0 now means to accumulate from the start of the source

git-svn-id: trunk@28803 -
This commit is contained in:
ask 2010-12-22 11:38:40 +00:00
parent 7abae0cdec
commit 1e97fa9ad8
3 changed files with 81 additions and 63 deletions

View File

@ -96,10 +96,9 @@ type
FCount: Cardinal;
FStart: Cardinal;
FSum: TChartDataItem;
procedure AddValue(const AItem: TChartDataItem);
function EndIndex: Cardinal; inline;
function GetCapacity: Cardinal; inline;
procedure Put(AIndex: Integer; const AItem: TChartDataItem);
procedure Remove(AIndex: Integer);
procedure SetCapacity(AValue: Cardinal); inline;
public
procedure AddFirst(const AItem: TChartDataItem);
@ -107,7 +106,8 @@ type
procedure Clear; inline;
function GetPLast: PChartDataItem;
procedure GetSum(var AItem: TChartDataItem);
procedure RemoveLast;
procedure RemoveLast; overload;
procedure RemoveValue(const AItem: TChartDataItem);
property Capacity: Cardinal read GetCapacity write SetCapacity;
end;
@ -138,24 +138,40 @@ begin
raise EBufferError.Create('');
FStart := (FStart + Cardinal(High(FBuf))) mod Capacity;
if FCount = Capacity then
Remove(FStart)
RemoveValue(FBuf[FStart])
else
FCount += 1;
Put(FStart, AItem);
FBuf[FStart] := AItem;
AddValue(AItem);
end;
procedure TChartSourceBuffer.AddLast(const AItem: TChartDataItem);
begin
if Capacity = 0 then
raise EBufferError.Create('');
if FCount = Capacity then begin
Remove(FStart);
Put(FStart, AItem);
FStart += 1;
end
else begin
FCount += 1;
Put(EndIndex, AItem);
if Capacity > 0 then
if FCount = Capacity then begin
RemoveValue(FBuf[FStart]);
FBuf[FStart] := AItem;
FStart += 1;
end
else begin
FCount += 1;
FBuf[EndIndex] := AItem;
end;
AddValue(AItem);
end;
procedure TChartSourceBuffer.AddValue(const AItem: TChartDataItem);
var
i, oldLen: Integer;
begin
with FSum do begin
Y += AItem.Y;
oldLen := Length(YList);
SetLength(YList, Max(Length(AItem.YList), oldLen));
for i := oldLen to High(YList) do
YList[i] := 0;
for i := 0 to Min(High(YList), High(AItem.YList)) do
YList[i] += AItem.YList[i];
end;
end;
@ -183,47 +199,29 @@ end;
procedure TChartSourceBuffer.GetSum(var AItem: TChartDataItem);
begin
if FCount = 0 then
raise EBufferError.Create('Empty');
AItem.Y := FSum.Y;
AItem.YList := Copy(FSum.YList);
end;
procedure TChartSourceBuffer.Put(AIndex: Integer; const AItem: TChartDataItem);
var
i, oldLen: Integer;
begin
FBuf[AIndex] := AItem;
with FSum do begin
Y += AItem.Y;
oldLen := Length(YList);
SetLength(YList, Max(Length(AItem.YList), oldLen));
for i := oldLen to High(YList) do
YList[i] := 0;
for i := 0 to Min(High(YList), High(AItem.YList)) do
YList[i] += AItem.YList[i];
end;
end;
procedure TChartSourceBuffer.Remove(AIndex: Integer);
var
i: Integer;
begin
with FBuf[AIndex] do begin
FSum.Y -= Y;
for i := 0 to Min(High(FSum.YList), High(YList)) do
FSum.YList[i] -= YList[i];
end;
end;
procedure TChartSourceBuffer.RemoveLast;
begin
if FCount = 0 then
raise EBufferError.Create('Empty');
Remove(EndIndex);
RemoveValue(FBuf[EndIndex]);
FCount -= 1;
end;
procedure TChartSourceBuffer.RemoveValue(const AItem: TChartDataItem);
var
i: Integer;
begin
with AItem do begin
FSum.Y -= Y;
for i := 0 to Min(High(FSum.YList), High(YList)) do
FSum.YList[i] -= YList[i];
end;
end;
procedure TChartSourceBuffer.SetCapacity(AValue: Cardinal);
begin
if AValue = Capacity then exit;

View File

@ -238,7 +238,7 @@ type
property AccumulationMethod: TChartAccumulationMethod
read FAccumulationMethod write SetAccumulationMethod default camNone;
property AccumulationRange: Integer
read FAccumulationRange write SetAccumulationRange default 0;
read FAccumulationRange write SetAccumulationRange default 1;
property Origin: TCustomChartSource read FOrigin write SetOrigin;
property Percentage: Boolean
@ -999,35 +999,43 @@ end;
procedure TCalculatedChartSource.CalcAccumulation(AIndex: Integer);
var
i: Integer;
i, ar: Integer;
begin
FHistory.Capacity := AccumulationRange;
ar := IfThen(AccumulationRange = 0, MaxInt, AccumulationRange);
if FIndex = AIndex - 1 then begin
ExtractItem(FItem, AIndex);
FHistory.AddLast(FItem);
end
else if FIndex = AIndex + 1 then begin
i := AIndex - AccumulationRange + 1;
if i < 0 then
FHistory.RemoveLast
if AccumulationRange = 0 then begin
ExtractItem(FItem, FIndex);
FHistory.RemoveValue(FItem);
ExtractItem(FItem, AIndex);
end
else begin
ExtractItem(FItem, i);
FHistory.AddFirst(FItem);
i := AIndex - AccumulationRange + 1;
if i < 0 then
FHistory.RemoveLast
else begin
ExtractItem(FItem, i);
FHistory.AddFirst(FItem);
end;
FItem := FHistory.GetPLast^;
end;
FItem := FHistory.GetPLast^;
end
else begin
FHistory.Clear;
for i := Max(AIndex - AccumulationRange + 1, 0) to AIndex do begin
for i := Max(AIndex - ar + 1, 0) to AIndex do begin
ExtractItem(FItem, i);
FHistory.AddLast(FItem);
end;
end;
FHistory.GetSum(FItem);
if AccumulationMethod = camAverage then begin
FItem.Y /= Min(AccumulationRange, AIndex + 1);
FItem.Y /= Min(ar, AIndex + 1);
for i := 0 to High(FItem.YList) do
FItem.YList[i] /= Min(AccumulationRange, AIndex + 1);
FItem.YList[i] /= Min(ar, AIndex + 1);
end;
end;
@ -1057,6 +1065,7 @@ end;
constructor TCalculatedChartSource.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FAccumulationRange := 1;
FIndex := -1;
FHistory := TChartSourceBuffer.Create;
FListener := TListener.Create(@FOrigin, @Changed);
@ -1095,7 +1104,7 @@ begin
if Origin = nil then exit(nil);
Result := @FItem;
if FIndex = AIndex then exit;
if (AccumulationMethod = camNone) or (AccumulationRange = 0) then
if (AccumulationMethod = camNone) or (AccumulationRange = 1) then
ExtractItem(FItem, AIndex)
else
CalcAccumulation(AIndex);

View File

@ -89,14 +89,25 @@ begin
AssertEquals((102 + 202) / 2, FSource[1]^.Y);
AssertEquals(102, FSource[0]^.Y);
rng := TMWCRandomGenerator.Create;
rng.Seed := 89237634;
FSource.AccumulationRange := 5;
for i := 1 to 100 do begin
j := rng.GetInRange(5, FSource.Count - 1);
AssertEquals(IntToStr(j), (j - 1) * 100 + 2, FSource[j]^.Y);
rng := TMWCRandomGenerator.Create;
try
rng.Seed := 89237634;
for i := 1 to 100 do begin
j := rng.GetInRange(5, FSource.Count - 1);
AssertEquals(IntToStr(j), (j - 1) * 100 + 2, FSource[j]^.Y);
end;
FSource.AccumulationRange := 0;
FSource.AccumulationMethod := camSum;
rng.Seed := 23784538;
for i := 1 to 20 do begin
j := rng.GetInRange(0, FSource.Count - 1);
AssertEquals(
IntToStr(j), (j + 1) * (j + 2) * 50 + (j + 1) * 3, FSource[j]^.YList[0]);
end;
finally
rng.Free;
end;
rng.Free;
end;
procedure TCalculatedSourceTest.Percentage;