anchor.diff:      Result := 1;
   end;
   
  +function TmUprightDatum.GetDatumKey: IVDDatumKey;
  +begin
  +  Result := FKey;
  +end;
  +
  +function TmUprightDatum.GetPropertyByFieldName(const aFieldName: String): Variant;
  +begin
  +  if aFieldName = FLD_POSITION then
  +    Result := FKey.Position
  +  else if aFieldName = FLD_DELTA then
  +    Result := FEvent.Value
  +  else if aFieldName = FLD_ATTRIBUTE1 then
  +    Result := FEvent.Attribute1.AsVariant
  +  else if aFieldName = FLD_ATTRIBUTE2 then
  +    Result := FEvent.Attribute2.AsVariant
  +  else if aFieldName = FLD_UPRIGHT then
  +    Result := FUpright
  +  else if aFieldName = FLD_HIGHLIGHT then
  +    Result := TmUprightHighlightTypeToVariant(FHighlight)
  +  else if aFieldName = FLD_REMAINING then
  +    Result := FRemaining.AsVariant
  +  else if aFieldName = FLD_LIMIT then
  +    Result := FLimit.AsVariant
  +  else if aFieldName = FLD_DATE then
  +    Result := FEvent.EventDate
  +  else
  +    Result := Null;
  +end;
  +
  +class procedure TmUprightDatum.FillVirtualFieldDefs(aFieldDefs: TmVirtualFieldDefs; aPrefix: String);
  +begin
  +  with aFieldDefs.AddFieldDef do
  +  begin
  +    Name := aPrefix + FLD_POSITION;
  +    DataType:= vftInteger;
  +  end;
  +  with aFieldDefs.AddFieldDef do
  +  begin
  +    Name := aPrefix + FLD_DATE;
  +    DataType := vftDateTime;
  +  end;
  +  with aFieldDefs.AddFieldDef do
  +  begin
  +    Name := aPrefix + FLD_DELTA;
  +    DataType:= vftFloat;
  +  end;
  +  with aFieldDefs.AddFieldDef do
  +  begin
  +    Name := aPrefix + FLD_UPRIGHT;
  +    DataType:= vftFloat;
  +  end;
  +  with aFieldDefs.AddFieldDef do
  +  begin
  +    Name := aPrefix + FLD_LIMIT;
  +    DataType:= vftFloat;
  +  end;
  +  with aFieldDefs.AddFieldDef do
  +  begin
  +    Name := aPrefix + FLD_REMAINING;
  +    DataType:= vftFloat;
  +  end;
  +  with aFieldDefs.AddFieldDef do
  +  begin
  +    Name := aPrefix + FLD_HIGHLIGHT;
  +    DataType:= vftString;
  +    Size := 10;
  +  end;
  +  with aFieldDefs.AddFieldDef do
  +  begin
  +    Name := aPrefix + FLD_ATTRIBUTE1;
  +    DataType:= vftString;
  +    Size := 255;
  +  end;
  +  with aFieldDefs.AddFieldDef do
  +  begin
  +    Name := aPrefix + FLD_ATTRIBUTE2;
  +    DataType:= vftString;
  +    Size := 255;
  +  end;
  +end;
  +
  +class function TmUprightDatum.GetKeyField: String;
  +begin
  +  Result := FLD_POSITION;
  +end;
  +
   { TmUpright }
   
  -function TmUpright.OnCompare(Item1, Item2: Pointer): Integer;
  +function TmUpright.OnCompareData(Item1, Item2: Pointer): Integer;
  +begin
  +  Result := TmUprightDatum(Item1).FEvent.CompareTo(TmUprightDatum(Item2).FEvent) ;
  +end;
  +
  +function TmUpright.OnCompareEvents(Item1, Item2: Pointer): Integer;
   begin
     Result := TmUprightEvent(Item1).CompareTo(TmUprightEvent(Item2)) ;
   end;
   
  +procedure TmUpright.CalculateHighlights;
  +var
  +  i : integer;
  +  tmp : TmUprightDatum;
  +  tmpMin, tmpMax : double;
  +  idxMin, idxMax : integer;
  +begin
  +  if FDataList.Count = 0 then
  +    exit;
  +
  +  tmpMin := 0;
  +  tmpMax := 0;
  +
  +  for i := 0 to FDataList.Count -1 do
  +  begin
  +    tmp:= TmUprightDatum(FDataList.Items[i]);
  +    tmp.FHighlight := uhNone;
  +    if i = 0 then
  +    begin
  +      tmpMin:= tmp.FUpright;
  +      tmpMax:= tmp.FUpright;
  +      idxMin := 0;
  +      idxMax := 0;
  +    end
  +    else
  +    begin
  +      if not mFloatsManagement.DoubleIsLessThan(tmpMin, tmp.FUpright) then
  +      begin
  +        tmpMin := tmp.FUpright;
  +        idxMin := i;
  +      end;
  +      if mFloatsManagement.DoubleIsLessThan(tmpMax, tmp.FUpright) then
  +      begin
  +        tmpMax := tmp.FUpright;
  +        idxMax := i;
  +      end;
  +    end;
  +  end;
  +  TmUprightDatum(FDataList.Items[idxMin]).FHighlight := uhMin;
  +  TmUprightDatum(FDataList.Items[idxMax]).FHighlight := uhMax;
  +end;
  +
   constructor TmUpright.Create;
   begin
  -  FList := TFPList.Create;
  +  FDataList := TFPList.Create;
  +  FEventsList := TObjectList.Create(true);
     FGarbage := TObjectList.Create(true);
  +  FLimitsList := TFPList.Create;
   end;
   
   destructor TmUpright.Destroy;
   begin
  -  FList.Free;
  +  FDataList.Free;
  +  FEventsList.Free;
     FGarbage.Free;
  +  FLimitsList.Free;
     inherited Destroy;
   end;
   
   function TmUpright.Add: TmUprightEvent;
   begin
     Result := TmUprightEvent.Create;
  -  FList.Add(Result);
  -  FGarbage.Add(Result);
  +  FEventsList.Add(Result);
   end;
   
   procedure TmUpright.Calculate;
   var
     i : integer;
  -  tmp : TmUprightEvent;
  +  tmpEvent : TmUprightEvent;
  +  tmpDatum : TmUprightDatum;
     lastValue : double;
  -begin
  -  MergeSort(FList, OnCompare);
  -  lastValue := 0;
  -  for i := 0 to FList.Count -1 do
  -  begin
  -    tmp:= TmUprightEvent(FList.Items[i]);
  -    if i = 0 then
  -      tmp.FUpright:= tmp.Delta
  -    else
  -      tmp.FUpright:= lastValue + tmp.Delta;
  -    lastValue := tmp.FUpright;
  -  end;
  -end;
  -
  -function TmUpright.Count: integer;
  -begin
  -  Result := FList.Count;
  -end;
  -
  -procedure TmUpright.Clear;
  -begin
  -  FList.Clear;
  +  currentLimitIndex : integer;
  +begin
  +  FDataList.Clear;
  +  FLimitsList.Clear;
     FGarbage.Clear;
  -end;
  -
  -procedure TmUpright.GetMinMaxValues (var aMin, aMax : double);
  -var
  -  i : integer;
  -  tmp : TmUprightEvent;
  -begin
  -  aMin := 0;
  -  aMax := 0;
  -
  -  for i := 0 to FList.Count -1 do
  -  begin
  -    tmp:= TmUprightEvent(FList.Items[i]);
  -    if i = 0 then
  -    begin
  -      aMin := tmp.FUpright;
  -      aMax := tmp.FUpright;
  +
  +  for i := 0 to FEventsList.Count - 1 do
  +  begin
  +    tmpEvent:= TmUprightEvent(FEventsList.Items[i]);
  +    if tmpEvent.EventType = etuValue then
  +    begin
  +      tmpDatum := TmUprightDatum.Create;
  +      tmpDatum.FEvent := tmpEvent;
  +      FDataList.Add(tmpDatum);
  +      FGarbage.Add(tmpDatum);
       end
       else
       begin
  -      aMin := Min(aMin, tmp.FUpright);
  -      aMax := Max(aMax, tmp.FUpright);
  +      FLimitsList.Add(tmpEvent);
       end;
     end;
  +
  +  MergeSort(FDataList, OnCompareData);
  +  MergeSort(FLimitsList, OnCompareEvents);
  +  lastValue := 0;
  +
  +  currentLimitIndex:= -1;
  +
  +  for i := 0 to FDataList.Count -1 do
  +  begin
  +    tmpDatum:= TmUprightDatum(FDataList.Items[i]);
  +
  +    if (FLimitsList.Count > currentLimitIndex + 1) then
  +    begin
  +      tmpEvent := TmUprightEvent(FLimitsList.Items[currentLimitIndex + 1]);
  +      while Assigned(tmpEvent) and  DoubleIsLessThan(tmpEvent.EventDate, tmpDatum.FEvent.EventDate) do
  +      begin
  +        inc(currentLimitIndex);
  +        if (FLimitsList.Count > currentLimitIndex + 1) then
  +          tmpEvent := TmUprightEvent(FLimitsList.Items[currentLimitIndex + 1])
  +        else
  +          tmpEvent := nil;
  +      end;
  +    end;
  +
  +    tmpDatum.FKey.FPosition := i + 1;
  +    if i = 0 then
  +      tmpDatum.FUpright:= tmpDatum.FEvent.Value
  +    else
  +      tmpDatum.FUpright:= lastValue + tmpDatum.FEvent.Value;
  +    lastValue := tmpDatum.FUpright;
  +    if currentLimitIndex >= 0 then
  +    begin
  +      tmpEvent := TmUprightEvent(FLimitsList.Items[currentLimitIndex]);
  +      tmpDatum.FLimit.Value := tmpEvent.Value;
  +      tmpDatum.FRemaining.Value := tmpDatum.FLimit.Value + tmpDatum.FUpright;
  +    end;
  +  end;
  +  Self.CalculateHighlights;
  +end;
  +
  +function TmUpright.Count: integer;
  +begin
  +  Result := FDataList.Count;
  +end;
  +
  +procedure TmUpright.Clear;
  +begin
  +  FDataList.Clear;
  +  FEventsList.Clear;
  +  FGarbage.Clear;
  +  FLimitsList.Clear;
  +end;
  +
  +function TmUpright.GetDatum(const aIndex: integer): IVDDatum;
  +begin
  +  Result := TmUprightDatum(FDataList.Items[aIndex]);
  +end;
  +
  +function TmUpright.FindDatumByKey(const aKey: IVDDatumKey): IVDDatum;
  +begin
  +  Result := TmUprightDatum(FDataList.Items[TmUprightValueKey(aKey).Position]);
  +end;
  +
  +function TmUpright.FindDatumByStringKey(const aStringKey: string): IVDDatum;
  +begin
  +  Result := TmUprightDatum(FDataList.Items[StrToInt(aStringKey)]);
   end;
   
   end.
  
positive.code: 
  uses
    Classes, contnrs,
    mUtility, mFloatsManagement;
  
  type
  
    { TmUprightEvent }
  
    TmUprightEvent = class
    strict private
      FEventDate : TDateTime;
      FDelta : double;
      FDescription : string;
      FDatumKey : String;
    private
      FUpright : double;
    public
      constructor Create;
      destructor Destroy; override;
      function CompareTo (aOther : TmUprightEvent) : integer;
  
      property EventDate: TDateTime read FEventDate write FEventDate;
      property Delta: double read FDelta write FDelta;
      property Description: string read FDescription write FDescription;
      property DatumKey: string read FDatumKey write FDatumKey;
      property Upright: double read FUpright;
    end;
  
    { TmUpright }
  
    TmUpright = class
    strict private
      FGarbage : TObjectList;
      FList : TFPList;
  
      function OnCompare (Item1, Item2: Pointer): Integer;
    public
      constructor Create;
      destructor Destroy; override;
  
negative.code:     procedure Calculate;
      function Count : integer;
      procedure Clear;
      function GetDatum(const aIndex : integer) : IVDDatum;
      function FindDatumByKey (const aKey : IVDDatumKey): IVDDatum;
      function FindDatumByStringKey (const aStringKey : string): IVDDatum;
    end;
  
    function TmUprightHighlightTypeToVariant (const aValue : TmUprightHighlightType): Variant;
  
  implementation
  
  uses
    sysutils;
  
  function TmUprightHighlightTypeToVariant(const aValue: TmUprightHighlightType): Variant;
  begin
    if aValue = uhMax then
      Result := 'MAX'
    else if aValue = uhMin then
      Result := 'MIN'
    else
      Result := Null;
  end;
  
  { TmUprightValueKey }
  
  procedure TmUprightValueKey.Assign(aSource: TObject);
  begin
    FPosition := (aSource as TmUprightValueKey).Position;
  end;
  
  function TmUprightValueKey.AsString: string;
  begin
    Result := IntToStr(FPosition);
  end;
  
  { TmUprightEvent }
  
  function TmUprightDatum.GetPosition: integer;
  begin
    Result := FKey.Position;
  end;
  
  constructor TmUprightDatum.Create;
  begin
    FUpright:= 0;
    FHighlight:= uhNone;
    FKey := TmUprightValueKey.Create;
    FLimit := TNullableDouble.Create;
    FRemaining := TNullableDouble.Create;
  end;
  
  destructor TmUprightDatum.Destroy;
  begin
    FKey.Free;
    FLimit.Free;
    FRemaining.Free;
  end;
  
  constructor TmUprightEvent.Create;
  begin
    EventDate:= 0;
    DatumKey:= '';
    Value:= 0;
    EventType:= etuValue;
  
    FAttribute1 := TNullableString.Create;
    FAttribute2 := TNullableString.Create();
  end;
  
  destructor TmUprightEvent.Destroy;
  begin
    FAttribute1.Free;
    FAttribute2.Free;
    inherited Destroy;
  end;
  
  