unit class_values;

interface

uses user_types;

//константы действий в функицях поиска максимума минимума, сортировки
CONST FIND_MAX = 0;
      FIND_MIN = 1;

      SORT_UP  = 0;
      SORT_DOWN = 1;
{$REGION 'КЛАСС ЗНАЧЕНИЯ'}
type
  TRDValues = class (TObject)
    private
       data_values: TRDValues_array;
       min: extended;
       max: extended;
       avr: extended;

       function array_summ ( in_array: TRDValues_array;
                           in_number_of_elements: integer ):extended;
       function Sort_Array ( in_array:TRDValues_array;
                            in_number_of_elements, in_dir:integer ):TRDValues_array;
       function Find_max_min ( in_array: TRDValues_array;
                              in_number_of_elements, in_min_max: integer;
                              var in_position: integer):extended;
    public
       constructor Create; virtual;

       function Get_min (var in_pos: integer): extended;
       function Get_max (var in_pos: integer): extended;
       function Get_avr (): extended;

       function Get_values (): TRDValues_array;

       function Sort_asc (): TRDValues_array;
       function Sort_desc (): TRDValues_array;

       function Set_all_values( in_values: TRDValues_array ): boolean;
       function Set_one_value( in_value: extended;
                               in_position: integer): boolean;
end;

{$ENDREGION}
implementation

constructor TRDValues.Create;
var i:integer;
begin
  inherited Create;
  //инициализация
  for i := 1 to REPEAT_AMOUNT do
    begin
      self.data_values[ i ] := 0;
    end;
  self.min := 0;
  self.max := 0;
  self.avr := 0;
end;

function TRDValues.Get_min(var in_pos:integer):extended;
begin
  in_pos := 0;
  result := Find_max_min( self.data_values, REPEAT_AMOUNT, FIND_MIN, in_pos );
end;

function TRDValues.Get_max(var in_pos:integer):extended;
begin
  in_pos:=0;
  result := Find_max_min( self.data_values, REPEAT_AMOUNT, FIND_MAX, in_pos );
end;

function TRDValues.Get_avr():extended;
begin
  Assert( ( REPEAT_AMOUNT > 0 ), 'Значения количества повторов недопустимо!'+'{78661A7E-4879-432F-B33F-B8CDEF30BFAE}' );
  /////////////////////////////////////////////////////////////////////////\
  //расчет среднего должен учитывать 0 в значениях!
  ////////////////////////////////////////////////////////////////
  result := self.array_summ( self.data_values, REPEAT_AMOUNT ) / REPEAT_AMOUNT;
end;

function TRDValues.Sort_asc (): TRDValues_array;
begin
  result := Sort_Array( self.data_values, REPEAT_AMOUNT, 0 );
end;

function TRDValues.Sort_desc (): TRDValues_array;
begin
  result := Sort_Array( self.data_values, REPEAT_AMOUNT, 1 );
end;

function TRDValues.Get_values (): TRDValues_array;
begin
  result := self.data_values;
end;

function TRDValues.Set_all_values( in_values: TRDValues_array ): boolean;
begin
  try
    self.data_values := in_values;
  finally
    result := true;
  end;
end;

function TRDValues.Set_one_value( in_value: extended; in_position: integer): boolean;
begin
Assert( ( ( 0 < in_position ) and ( in_position < REPEAT_AMOUNT + 1 ) ),
        'Значение позиции числа в массиве недопустимо!'+'{46271C86-5F70-403C-AF21-04B5812956F5}' );
  try
    self.data_values[ in_position ] := in_value;
  finally
    result := true;
  end;
end;

function TRDValues.array_summ( in_array: TRDValues_array; in_number_of_elements: integer): extended;
  var temp_summ:extended;
  I: Integer;
begin
  temp_summ := 0;
  for I := 1 to in_number_of_elements do
    begin
      temp_summ := temp_Summ + in_array[ i ];
    end;
  result := temp_summ;
end;

function TRDValues.Sort_Array( in_array: TRDValues_array; in_number_of_elements, in_dir: integer): TRDValues_array;
//dir 0 - по возрастанию
//dir 1 - по убыванию
Var d,
    i: integer;
    temp_array_elemrnt: extended;
    replace_flag: boolean; { пpизнак пеpестановки }
begin
   d := in_number_of_elements div 2;  { начальное значение интеpвала }
   while ( d > 0 ) do
    begin { цикл с yменьшением интеpвала до 1 }
     { пyзыpьковая соpтиpовка с интеpвалом d }
     replace_flag:=true;
     while replace_flag do
        begin  { цикл, пока есть пеpестановки }
          replace_flag := false;
          for i := 1 to in_number_of_elements - d do
            begin
              { сpавнение эл-тов на интеpвале d }
              if in_dir = SORT_UP then
                begin
                  if in_array[ i ] > in_array[ i+d ] then
                    begin
                      { пеpестановка }
                      temp_array_elemrnt := in_array[ i ];
                      in_array[ i ] := in_array[ i+d ];
                      in_array[ i+d ] := temp_array_elemrnt;
                      replace_flag := true;  { пpизнак пеpестановки }
                    end; { if ... }
                end
              else if in_dir = SORT_DOWN then
                begin
                   if in_array[ i ] < in_array[ i+d ] then
                    begin
                      { пеpестановка }
                      temp_array_elemrnt := in_array[ i ];
                      in_array[ i ] := in_array[ i+d ];
                      in_array[ i+d ] := temp_array_elemrnt;
                      replace_flag := true;  { пpизнак пеpестановки }
                    end; { if ... }
                end;
            end; { for ... }
        end; { while k }
     d := d div 2;  { yменьшение интеpвала }
    end;  { while d>0 }
result := in_array;
end;

function TRDValues.Find_max_min(in_array:TRDValues_array; in_number_of_elements, in_min_max:integer; var in_position:integer):extended;
//min_max 0 - max
//min_max 1 - min
var
  min_max_pos: integer; // номер минимального элемента массива
  i: integer; // номер элемента, сравниваемого с минимальным
begin
  in_position := 0;
  min_max_pos := 1;
  try
    // поиск минимального элемента
    min_max_pos := 1; // пусть первый элемент минимальный
    for i := 2 to in_number_of_elements do
      begin
        if in_min_max = FIND_MAX then
          begin
            if in_array[ i ] < in_array[ min_max_pos ] then
              begin
                min_max_pos := i;
              end;
          end
        else if in_min_max = FIND_MIN then
          begin
            if in_array[ i ] > in_array[ min_max_pos ] then
              begin
                min_max_pos := i;
              end;
          end
      end;
  finally
     in_position := min_max_pos;
     result := in_array[ min_max_pos ];
  end;
end;


end.
