unit ExtrDlg;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, Matrices, MiscRoutines, Spin, SharedData;

type
  TExtrDialog = class(TForm)
    StartEdit: TEdit;
    LabF: TLabel;
    LBFactors: TListBox;
    LabStrt: TLabel;
    LabStop: TLabel;
    EndEdit: TEdit;
    ValBevel: TBevel;
    OkButton: TButton;
    CancelButton: TButton;
    CBMinMax: TComboBox;
    LabStep: TLabel;
    SESteps: TSpinEdit;
    LabWhat: TLabel;
    LabMeth: TLabel;
    CBMethod: TComboBox;
    Bevel2: TBevel;
    LabApp: TLabel;
    SEApps: TSpinEdit;
    CBUseOld: TCheckBox;
    Label1UseOld: TLabel;
    Label2UseOld: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure LBFactorsClick(Sender: TObject);
    procedure CBMethodChange(Sender: TObject);
    procedure Label1UseOldClick(Sender: TObject);
    procedure StartEditExit(Sender: TObject);
    procedure EndEditExit(Sender: TObject);
    procedure SEStepsExit(Sender: TObject);
    procedure SEAppsExit(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  private
    // Имена факторов
    KNames       : PStringList;
    // Количество факторов
    MaxFactors   : integer;
    // Текущий индекс в списке факторов
    CurrentIndex : integer;
    // Заполнение списка названиями фиксированных факторов
    procedure    LBFill;
    // Смена состояния флажка "использовать старое приближение"
    procedure    ChangeUseOld(Flag:Boolean);
    function     Validate:Boolean;
    procedure    Clean;
  public
    // Вектор, содержащий начальные значения факторов
    StartValues  : TStreamableVector;
    // Вектор, содержащий конечные значения факторов
    EndValues    : TStreamableVector;
    // Количество шагов ихменения факторов
    NumSteps     : integer;
    // Количество приближений для метода Монте-Карло
    NumApps      : integer;
    // Истина, если можно использовать старое приближение
    CanUseOld    : Boolean;
    // Установка количества факторов
    procedure    SetFactors(Names:PStringList);
  end;

var
  ExtrDialog: TExtrDialog;

implementation


{$R *.DFM}

function TExtrDialog.Validate;
var
  Stub : double;
begin
  Result:=
    CheckSpinContens(SEApps,'Шагов разбиения') and
    CheckSpinContens(SESteps,'Шагов разбиения') and
    ContainDouble(StartEdit.Text,Stub,'Начальное значение') and
    ContainDouble(EndEdit.Text,Stub,'Конечное значение');
end;

procedure TExtrDialog.Clean;
begin
  SEApps.Value:=ValidInteger(SEApps);
  SESteps.Value:=ValidInteger(SESteps);
  StartEdit.Text:=ValidDouble(StartEdit.Text);
  EndEdit.Text:=ValidDouble(EndEdit.Text);
end;

procedure TExtrDialog.SetFactors;
var
  i : integer;
begin
  Assert(Names<>nil);
  KNames:=Names;
  MaxFactors:=KNames^.Count;
  if(MaxFactors<>StartValues.nSize) then
    StartValues.Recreate(MaxFactors);
  if(MaxFactors<>EndValues.nSize) then
    EndValues.Recreate(MaxFactors);
  for i:=0 to MaxFactors-1 do
  begin
    StartValues.SetElement(i,-1.0);
    EndValues.SetElement(i,1.0);
  end;
  CBMethod.Items.Clear;
  // #warning this one has been removed
  if(False{MaxFactors in [2..4]}) then
  begin
    CBMethod.Items.Add('Сканирование (полный перебор значений)');
    CBMethod.Perform(CB_SETITEMDATA,CBMethod.Items.Count-1,0);
  end;
  CBMethod.Items.Add('Метод Монте-Карло (случайный поиск)');
  CBMethod.Perform(CB_SETITEMDATA,CBMethod.Items.Count-1,1);
  CBMethod.Items.Add('Метод Гаусса - Зейделя (покоординатный спуск)');
  CBMethod.Perform(CB_SETITEMDATA,CBMethod.Items.Count-1,2);
  CBMethod.ItemIndex:=0;
  CurrentIndex:=0;
end;

procedure TExtrDialog.FormCreate(Sender: TObject);
begin
  StartValues.Create(0);
  EndValues.Create(0);
  MaxFactors:=0;
  KNames:=nil;
  NumSteps:=10;
  NumApps:=1000;
  SESteps.Value:=NumSteps;
  SEApps.Value:=NumApps;
  CBMinMax.ItemIndex:=0;
  CBMethod.ItemIndex:=0;
  CurrentIndex:=0;
  CBMethodChange(Self);
end;

procedure TExtrDialog.LBFill;
begin
  LBFactors.Items.Clear;
  CurrentIndex:=0;
  LBFactors.Items.Clear;
  LBFactors.Items.AddStrings(KNames^);
  LBFactors.ItemIndex:=0;
  StartEdit.Text:=FloatToStr(StartValues.GetElement(CurrentIndex));
  EndEdit.Text:=FloatToStr(EndValues.GetElement(CurrentIndex));
end;

procedure TExtrDialog.ChangeUseOld(Flag:Boolean);
begin
  ExtrDialog.CBUseOld.Checked:=Flag;
  ExtrDialog.CBUseOld.Enabled:=Flag;
  Label1UseOld.Enabled:=Flag;
  Label2UseOld.Enabled:=Flag;
end;

procedure TExtrDialog.FormShow(Sender: TObject);
begin
  SESteps.Value:=NumSteps;
  SEApps.Value:=NumApps;
  CBMethodChange(Self);
  Assert(KNames<>nil);
  LBFill;
end;

procedure TExtrDialog.LBFactorsClick(Sender: TObject);
var
  f,s : double;
begin
  if(LBFactors.Items.Count<1) then exit;
  if((not ContainDouble(StartEdit.Text,f,'Начальное значение')) or
     (not ContainDouble(EndEdit.Text,s,'Конечное значение'))) then
    exit;
  if(f=s) then
  begin
    Warning('В поле "Конечное значение" должна находится'+#13+
      'величина, большая '+StartEdit.Text);
    FocusControl(EndEdit);
    LBFactors.ItemIndex:=CurrentIndex;
  end;
  if(f>s) then
  begin
    StartValues.SetElement(CurrentIndex,s);
    EndValues.SetElement(CurrentIndex,f);
  end
  else
  begin
    StartValues.SetElement(CurrentIndex,f);
    EndValues.SetElement(CurrentIndex,s);
  end;
  CurrentIndex:=LBFactors.ItemIndex;
  StartEdit.Text:=FloatToStr(StartValues.GetElement(CurrentIndex));
  EndEdit.Text:=FloatToStr(EndValues.GetElement(CurrentIndex));
end;

procedure TExtrDialog.CBMethodChange(Sender: TObject);
var
  RealIndex : integer;
begin
  RealIndex:=CBMethod.Perform(CB_GETITEMDATA,CBMethod.ItemIndex,0);
  case RealIndex of
  0:
    begin
      // Перебор
      ChangeUseOld(False);
      SESteps.Enabled:=True;
      SEApps.Enabled:=False;
    end;
  1:
    begin
      // Метод Монте - Карло
      ChangeUseOld(CanUseOld);
      SESteps.Enabled:=False;
      SEApps.Enabled:=True;
    end;
  2:
    begin
      // Перебор и покординатный спуск
      ChangeUseOld(CanUseOld);
      SESteps.Enabled:=True;
      SEApps.Enabled:=False;
    end;
  end;
end;

procedure TExtrDialog.Label1UseOldClick(Sender: TObject);
begin
  if(CBUseOld.Enabled) then
    CBUseOld.Checked:=not CBUseOld.Checked;
end;

procedure TExtrDialog.StartEditExit(Sender: TObject);
var
  Stub : double;
begin
  if(not ContainDouble(StartEdit.Text,Stub,'Начальное значение')) then
  begin
    ActiveControl:=StartEdit;
    StartEdit.SelectAll;
  end
end;

procedure TExtrDialog.EndEditExit(Sender: TObject);
var
  Stub : double;
begin
  if(not ContainDouble(EndEdit.Text,Stub,'Конечное значение')) then
  begin
    ActiveControl:=EndEdit;
    EndEdit.SelectAll;
  end
end;

procedure TExtrDialog.SEStepsExit(Sender: TObject);
begin
  if(not CheckSpinContens(SESteps,'Шагов разбиения')) then
    FocusControl(SESteps);
end;

procedure TExtrDialog.SEAppsExit(Sender: TObject);
begin
  if(not CheckSpinContens(SEApps,'Шагов разбиения')) then
    FocusControl(SEApps);
end;

procedure TExtrDialog.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  LBFactorsClick(Self);
  NumSteps:=SESteps.Value;
  NumApps:=SEApps.Value;
end;

procedure TExtrDialog.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if(ChooseResult(Key,ModalResult)<>mrNone) then
    ModalResult:=ChooseResult(Key,ModalResult);
end;

procedure TExtrDialog.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
begin
  CanClose:=ValidateByResult(Validate,Clean,ModalResult);
end;

end.
