Uses Core,Win2K2,CoolKey,ccontr;
{ Используемые модули - 
  Core    - Основной модуль курсовика, само моделирование.  (C) IE 2002
  Win2K2  - Графический модуль, по возможности, аналогия иделологии 
            Win32 API (C) Microsoft. Win2k2 (C) IE
  CoolKey - Модуль низкоукровневой работы с клавиатурой, используется в Win2k2,
            в головной программе необходим для клавиатурных констант
  CContr  - Модуль для работы с Win2k2, в нем реализованы основные элементы
            интерфейса (EditBox, CheckBox, Button, XYPlot)}
 
TYPE
 {Состояниия системы}
 EStatus = (ST_WAITING,  {Система ожидает старта}
            ST_RUNNING,  {Система в сост. работы}
            ST_FINISHED) {Сислема завершила моделирование};
 
const
 AStatus : array [EStatus] of string[15] = ('Waiting','Running', 'Finished');
 {Сообщения о состоянии системы}

var
 TextOut   : Text;     {Файловый дескриптор текстового вывода результатов}
 RunNum    : Integer;  {Номер запуска системы (по нему различаются файлы вывода}
 RunMode   : boolean;  {Режим работы (рабочий/отладочный)}
 Parent    : hWNd;     {Handle основного окна программы}
 Stat      : EStatus;  {Текущее рабочее состояние}
 OCButtons : Array [1..2] of hWnd; {Handl'ы кнопок [1] - OK, [2] - Stop}
 Edits     : array [1..9] of hWnd; {Handl'ы полей ввода}
 Checks    : array [0..5] of hWnd; {Handl'ы выбираемых кновоп}
 Mode      : hWnd;                 {Handle селектора режима}
 Limits    : array [1..2] of hWnd; {Handl'ы текстовых полей границ графика}
 Realiz    : hWnd;                 {Handle поля ввода числа реализаций}
 RealNum   : UINT32;               {Само число реализаций}
 CurReal   : UINT32;               {Текущий номер раелизации, использеутся 
                                    ислючительно для равномерного распределения
                                    точек в режиме отладки}
 Plot      : hWnd;                 {Handle графика}

{Динамические объекты - элементы системы массового обслуживания}
{ Описание  -  см. заголовок модуля Core.pas}
 Model  : ^CModel;      
 Buffer : PBuffer;
 Device : PDevice;
 Srcs1, Srcs2,Srcs3 : PSource;

 BegVal,                {Начальные/конечные зн-я скорости прибора}
 LastVal : Real;        

 Steps   : integer;     {Число шагов от начального к конечному зн-ю прибора
                         (число точек на графике)}
 CurStep : integer;     {Текущий шаг}

 BufferSize : integer;  {Емкость буфера модели}
 S1,S2,S3 : Real;       {Скорости источников}

 Delta, DovInt : real;  {Настройки вероятностей}

{----------------------------------------------------------------}
Function GetFloat(aH:hWND):real; {Функция считывает вещественное зн-е из поля
                                  ввода}
var
 st : string;
 ret : real;
 i : integer;
begin
  GetWindowText(AH,@st,255);
  Val(st,ret,i);
  GetFloat := ret;
end;
{----------------------------------------------------------------}
Procedure GetParams; {Считывание всех зн-ний из полей ввода}
var
 st : string[50];
 i  : integer;
 v  : real;
begin
  BegVal := GetFloat(Edits[3]);
  LastVal := GetFloat(Edits[4]);
  DovInt := GetFloat(Edits[2]);
  Steps := Round(GetFloat(Edits[5]));
  BufferSize := Round(GetFloat(Edits[6]));
  S1 := Getfloat(Edits[7]);
  S2 := Getfloat(Edits[8]);
  S3 := Getfloat(Edits[9]);
  GetWindowText(Edits[1],@st,50);
  if st[ord(st[0])] = '%' then
   begin
    Val(copy(st,1,ord(st[0])-1),v,i);
    Delta := v/100.0;
   end
  else
    Val(st,Delta,i);
end;

Procedure InitModel; {Начальная инициализация значений модели и 
                      инициализация динамических объектов}
begin
 Delta := 0.1;
 DovInt := 1.64;

 BegVal := 1.0;
 LastVal := 5.0;

 Steps := 20;

 BufferSize := 5;
 S1 := 2.0;
 S2 := 1.0;
 S3 := 5.0;

 New(Buffer, Init(BufferSize));
 New(Device, Init(BegVal));
 New(Model, Init(3,Device,Buffer,Delta,DovInt));

 New(Srcs1,Init(0,S1));
 Model^.AddNewSource(Srcs1);
 New(Srcs2,Init(1,S2));
 Model^.AddNewSource(Srcs2);
 New(Srcs3,Init(2,S3));
 Model^.AddNewSource(Srcs3);
end;

Procedure StartModel; {Процедура подготовки и старта моделирования при 
                       указанных значениях}
var
 XY : TRPoint;
 nm : string;
 i  : UINT8;
begin
  Buffer^.SetBufferSize(BufferSize);
  Device^.Lambda := BegVal;
  Model^.Delta := Delta;
  Model^.DovInt := DovInt;
  Srcs1^.Lambda := S1;
  Srcs2^.Lambda := S2;
  Srcs3^.Lambda := S3;
  Model^.Start;
  for i := 0 to 5 do
    SendMessage(Plot,WM_SETVISIBLE,i,SendMessage(Checks[i],CB_GETCHECK,0,0));

  S1 := GetFloat(Realiz);
  RealNum := round(S1);
  Model^.RealizSteps := RealNum;

  if RunMode then
  begin
   Model^.CalcVer := true;
   XY.X:=0;
   XY.Y:=Steps;
   for i := 0 to 5 do
    begin
     SendMessage(Plot,XP_DELALLPOINTS,i,0);
     SendMessage(Plot,XP_SETXRANGE,i,UINT32(@XY));
    end;
   str(Steps,nm);
   SetWindowText(Limits[2],@nm);
   str(RunNum,nm);
   Inc(RunNum);
   nm := 'result.'+nm;
   Assign(TextOut,nm);
   Rewrite(TextOut);
   end
  else
   begin
     Model^.CalcVer := false;
     Str(RealNum,nm);
     SetWindowText(Limits[2],@nm);
     XY.X:=1;
     XY.Y:=RealNum;
     CurReal:=0;
     for i := 0 to 2 do
     begin
      SendMessage(Plot,XP_DELALLPOINTS,i,0);
      SendMessage(Plot,XP_SETXRANGE,i,UINT32(@XY));
      SendMessage(Plot,WM_SETVISIBLE,i,SendMessage(Checks[i],CB_GETCHECK,0,0));
     end;
     for i := 3 to 5 do
      begin
       SendMessage(Plot,XP_DELALLPOINTS,i,0);
       SendMessage(Plot,WM_SETVISIBLE,i,0);
      end;
   end;
  CurStep := 0;
end;


{Основной обработчик сообщений (messages) от системы (графического модуля).
 По идеологии Win32 API (C) Microsoft - основная процедура всей программы,
 в ней задается вся реакция на действия пользователя, наравне с внутренней
 логикой программы}
Function WindowProc(ahWnd:HWND;aMsg,wParam,lParam:UINT32):UINT32;far;
var
 ps : LPPAINTSTRUCT;
 XY,Max : TRPoint;
 st : string;
 i  : UINT8;
 rt : RECT;
begin
  case aMsg of
    WM_CREATE: {Первое сообщение после создания окна, в нем - инициализация
                и создание всех дочерних окон (полей ввода, и проч.)}
     begin
      OCButtons[1] := CreateWindow('OK','BUTTON',WS_CHILD,
                   66,350,50,30,ahWnd,NULL);
      PostMessage(OCButtons[1],CB_SETID,1,0);
      OCButtons[2] := CreateWindow('Exit','BUTTON',WS_CHILD,
                   152,350,60,30,ahWnd,NULL);
      PostMessage(OCButtons[2],CB_SETID,2,0);

      CreateWindow('Veroyatn','LABEL',WS_CHILD,
                   10,10,140,15,ahWnd,NULL);
      Edits[1]:=CreateWindow('10%','EDIT',WS_CHILD,
                   150,10,140,15,ahWnd,NULL);

      CreateWindow('Dov. Int','LABEL',WS_CHILD,
                   10,30,140,15,ahWnd,NULL);
      Edits[2]:=CreateWindow('0.82','EDIT',WS_CHILD,
                   150,30,140,15,ahWnd,NULL);

      CreateWindow('Beg. Lam ist','LABEL',WS_CHILD,
                   10,50,140,15,ahWnd,NULL);
      Edits[3]:=CreateWindow('1.0','EDIT',WS_CHILD,
                   150,50,140,15,ahWnd,NULL);

      CreateWindow('End Lam ist','LABEL',WS_CHILD,
                   10,70,140,15,ahWnd,NULL);
      Edits[4]:=CreateWindow('5.0','EDIT',WS_CHILD,
                   150,70,140,15,ahWnd,NULL);

      CreateWindow('Steps','LABEL',WS_CHILD,
                   10,90,140,15,ahWnd,NULL);
      Edits[5]:=CreateWindow('20','EDIT',WS_CHILD,
                   150,90,140,15,ahWnd,NULL);

      CreateWindow('Buf size','LABEL',WS_CHILD,
                   10,110,140,15,ahWnd,NULL);
      Edits[6]:=CreateWindow('5','EDIT',WS_CHILD,
                   150,110,140,15,ahWnd,NULL);

      CreateWindow('Lambda 1','LABEL',WS_CHILD,
                   10,130,140,15,ahWnd,NULL);
      Edits[7]:=CreateWindow('2.0','EDIT',WS_CHILD,
                   150,130,140,15,ahWnd,NULL);

      CreateWindow('Lambda 2','LABEL',WS_CHILD,
                   10,150,140,15,ahWnd,NULL);
      Edits[8]:=CreateWindow('1.0','EDIT',WS_CHILD,
                   150,150,140,15,ahWnd,NULL);

      CreateWindow('Lambda 3','LABEL',WS_CHILD,
                   10,170,140,15,ahWnd,NULL);
      Edits[9]:=CreateWindow('5.0','EDIT',WS_CHILD,
                   150,170,140,15,ahWnd,NULL);

      Plot := CreateWindow('Test plot','XYPLOT',WS_CHILD,310,10,300,300,ahWnd,NULL);
      SendMessage(Plot,XP_SETPLOTCOUNT,6,0);
      SendMessage(Plot,XP_SETCOLOR,0,Red);
      SendMessage(Plot,XP_SETCOLOR,1,Green);
      SendMessage(Plot,XP_SETCOLOR,2,Blue);
      SendMessage(Plot,XP_SETCOLOR,3,Magenta);
      SendMessage(Plot,XP_SETCOLOR,4,Yellow);
      SendMessage(Plot,XP_SETCOLOR,5,White);
      XY.X:=0;
      XY.Y:=100;
      SendMessage(Plot,XP_SETYRANGE,0,UINT32(@XY));
      SendMessage(Plot,XP_SETYRANGE,1,UINT32(@XY));
      SendMessage(Plot,XP_SETYRANGE,2,UINT32(@XY));

      Limits[1] := CreateWindow('0','LABEL',WS_CHILD,310,320,20,15,ahWnd,NULL);
      Limits[2] := CreateWindow('20','LABEL',WS_CHILD,560,320,50,15,ahWnd,NULL);

      Checks[0] := CreateWindow('Ist1 Potk (Red)','CHECKBOX',WS_CHILD,
                                10,200,200,15,ahWnd,NULL);
      SendMessage(Checks[0],CB_SETCHECK,0,0);
      Checks[1] := CreateWindow('Ist2 Potk (Green)','CHECKBOX',WS_CHILD,
                                10,220,200,15,ahWnd,NULL);
      SendMessage(Checks[1],CB_SETCHECK,1,0);
      Checks[2] := CreateWindow('Ist3 Potk (Blue)','CHECKBOX',WS_CHILD,
                                10,240,200,15,ahWnd,NULL);
      SendMessage(Checks[2],CB_SETCHECK,0,0);

      Checks[3] := CreateWindow('Ist1 MatO (Magenta)','CHECKBOX',WS_CHILD,
                                10,260,200,15,ahWnd,NULL);
      SendMessage(Checks[3],CB_SETCHECK,0,0);
      Checks[4] := CreateWindow('Ist2 MatO (Yellow)','CHECKBOX',WS_CHILD,
                                10,280,200,15,ahWnd,NULL);
      SendMessage(Checks[4],CB_SETCHECK,1,0);
      Checks[5] := CreateWindow('Ist3 MatO (White)','CHECKBOX',WS_CHILD,
                                10,300,200,15,ahWnd,NULL);
      SendMessage(Checks[5],CB_SETCHECK,0,0);
      Mode := CreateWindow('Test mode','CHECKBOX', WS_CHILD,
                                210,200,100,15, ahWnd, NULL);
      CreateWindow('KMIN','LABEL',WS_CHILD,210,220,50,15,ahWnd,NULL);
      Realiz := CreateWindow('1000','EDIT',WS_CHILD,210,240,70,15,ahWnd,NULL);
      SendMessage(Mode,CB_SETCHECK,0,0);
      RunMode := true;
      SendMessage(Mode,CB_SETID,90,0);
      Randomize;
      Stat := ST_WAITING;
      for i := 0 to 5 do SendMessage(Checks[i],CB_SETID,i+100,0);
      InitModel;
      RunNum := 0;
      PostMessage(ahWnd,WM_PAINT,0,0);
      AddOnFrameMessage(ahWnd);
     end;
    WM_COMMAND:
     {Обработчик команд от конролов (кнопок, полей ввода, кнопок выбора)}
     begin
      case wParam of
       1: if (lParam = 0)  and (Stat <> ST_RUNNING) then begin {OK button pressed}
            GetParams;
            StartModel;
            Stat := ST_RUNNING;
            St := 'STOP';
            SetWindowText(OCButtons[2],@St);
            PostMessage(ahWnd,WM_PAINT,0,0);
            PostMessage(OCButtons[2],WM_PAINT,0,0);
          end;
       2: if lParam = 0 then {нажата кнопка STOP}
           begin
            if Stat = ST_RUNNING then
             begin
              if RunMode then Close(TextOut);
              Stat := ST_WAITING;
              St := 'Exit';
              SetWindowText(OCButtons[2],@St);
              PostMessage(OCButtons[2],WM_PAINT,0,0);
              PostMessage(ahWnd,WM_PAINT,0,0);
             end
            else
              PostMessage(ahWnd,WM_DESTROY,0,0);
           end;
        90: if lParam = 0 then begin {Вкл/выкл режим отладки}
              RunMode := not RunMode;
              for i := 3 to 5 do
                SendMessage(Checks[i],WM_SETVISIBLE,UINT32(RunMode),0);
            end;
      end;
      if (wParam >= 100) and (wParam <=105) and (lParam = 0) then
      begin
        SendMessage(Plot,WM_SETVISIBLE,wParam-100,SendMessage(Checks[wParam-100],CB_GETCHECK,0,0));
      end;
     end;
    WM_ONFRAME:
    {Основной обработчик всей программы, здесь - внутреняя логика. Вызываются
     методы объектов модели для осуществления моделирования. Также происходит
     добавление точек на график, вывод текстовой информации в файл.}
     begin
       if Stat = ST_RUNNING then
        begin
          if Not Model^.Step then
           begin
            if Runmode then begin
             XY.X := CurStep;
             XY.Y := 100*Srcs1^.RefusedReq/Srcs1^.TotalReq;
             SendMessage(Plot,XP_ADDPOINT,0,UINT32(@XY));
             XY.Y := 100*Srcs2^.RefusedReq/Srcs2^.TotalReq;
             SendMessage(Plot,XP_ADDPOINT,1,UINT32(@XY));
             XY.Y := 100*Srcs3^.RefusedReq/Srcs3^.TotalReq;
             SendMessage(Plot,XP_ADDPOINT,2,UINT32(@XY));
             if (Srcs1^.DoneReq <> 0) then
              begin
               XY.Y := Srcs1^.MatWait/Srcs1^.DoneReq;
               SendMessage(Plot,XP_ADDPOINT,3,UINT32(@XY));
              end;
             if (Srcs2^.DoneReq <> 0) then
              begin
               XY.Y := Srcs2^.MatWait/Srcs2^.DoneReq;
               SendMessage(Plot,XP_ADDPOINT,4,UINT32(@XY));
              end;
             if (Srcs3^.DoneReq <> 0) then
              begin
               XY.Y := Srcs3^.MatWait/Srcs3^.DoneReq;
               SendMessage(Plot,XP_ADDPOINT,5,UINT32(@XY));
              end;
             Max.X := 0;
             Max.Y := 0;
             for i := 3 to 5 do
             begin
              SendMessage(Plot,XP_GETYRANGE,i,UINT32(@XY));
              if XY.Y > Max.Y then Max.Y := XY.Y;
             end;
             for i := 3 to 5 do
              SendMessage(Plot,XP_SETYRANGE,i,UINT32(@Max));

             PostMessage(Plot,WM_PAINT,0,0);
             Model^.PrintValues(TextOut);
             inc(CurStep);
             Device^.Lambda := BegVal + (LAstVal-BegVal)/Steps*Curstep;
             if CurStep = Steps+1 then
             begin
              Stat := ST_FINISHED;
              Close(TextOut);
              St := 'Exit';
              SetWindowText(OCButtons[2],@St);
              PostMessage(OCButtons[2],WM_PAINT,0,0);
              PostMessage(ahWnd,WM_PAINT,0,0);
             end
             else
              Model^.Start;
            end else
             begin
              Stat := ST_FINISHED;
              St := 'Exit';
              SetWindowText(OCButtons[2],@St);
              PostMessage(ahWnd,WM_PAINT,0,0);
             end;
           end
           else if not runmode then
            begin
              if CurReal = (RealNum div 100)  then
               begin
                 XY.X := Model^.CurStep;
                 XY.Y := 100*Srcs1^.RefusedReq/Srcs1^.TotalReq;
                 SendMessage(Plot,XP_ADDPOINT,0,UINT32(@XY));
                 XY.Y := 100*Srcs2^.RefusedReq/Srcs2^.TotalReq;
                 SendMessage(Plot,XP_ADDPOINT,1,UINT32(@XY));
                 XY.Y := 100*Srcs3^.RefusedReq/Srcs3^.TotalReq;
                 SendMessage(Plot,XP_ADDPOINT,2,UINT32(@XY));
                 CurReal := -1;
                 PostMessage(Plot,WM_PAINT,0,0);
               end;
              Inc(CurReal);
            end;
        end;
     end;
    WM_DESTROY:
    {Сообщение, приходящее перед завершением работы программы, 
     здесь происходит освобождение памяти и уничтожение объектов модели}
     begin
      if Stat <> ST_WAITING then begin
        Dispose(Model,Done);
        Dispose(Buffer,Done);
        Dispose(Device,Done);
      end;
      DelOnFrameMessage(ahWnd);
      PostQuitMessage(ahwnd);
     end;
    WM_KEYDOWN:
    {Реакция на нажатие клавиши клавиатуры}
      if wParam = ord(SC_ESCAPE) then PostMessage(ahWnd,WM_DESTROY,0,0);

    WM_PAINT:
    {Обработчик прорисовки окна. Выводит только статус моделирования, вся
     остальная прорисовка выполняется дочерними окнами самостоятельно}
     begin
       ps := BeginPaint(ahWNd);
        wSetColor(ps,GlobalPalette.WindowFontColor);
        wSetBgColor(ps,GlobalPalette.ThreeDColor1);
        wSetStyle(ps,SolidFill);
        wSetFontJustify(ps,CenterText,BottomText);
        GetClientRect(ahWnd,@rt);
        wBar(ps,0,rt.b.y - 20, rt.b.x,rt.b.y);
        wTextOut(ps,rt.b.x shr 1, rt.b.y-1, @AStatus[Stat]);
       EndPaint(ps);
     end;
  end;
end;


{ГОЛОВА.}
begin
 if InitWin2K2 = ERR_OK then {Иниц. графической подсистемы}
 if RegisterClass('MSMO',WindowProc) = ERR_OK then
 {Регистрация класса, с таким обработчиком событий}
  begin
    InitCommonControls; {Инициализация стандартных классов}
    Parent:=CreateWindow('Configuration','MSMO',
                         WS_TITLE OR WS_SIZEABLE OR WS_MINMAX,
                         10,10,620,420,
                         NULL,NULL);
    {Создание основного окна}    
    MainRunLoop; {Основной цикл программы}
  end;
 DoneWin2K2; {Завершение работы графической подсистемы}
end.