unit u0001;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, Buttons, Grids, Menus, ToolWin, ComCtrls, Db, DBTables,
  DBGrids, DBCtrls;

type
Tf0001 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Panel3: TPanel;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    Panel4: TPanel;
    Label7: TLabel;
    Database1: TDatabase;
    t_maquinas: TTable;
    t_estados: TTable;
    t_regras: TTable;
    Panel6: TPanel;
    Panel7: TPanel;
    DBGrid1: TDBGrid;
    ds_maquina: TDataSource;
    ds_estados: TDataSource;
    ds_regras: TDataSource;
    DBGrid2: TDBGrid;
    Label2: TLabel;
    Panel9: TPanel;
    t_maquinasDs_maq: TStringField;
    t_maquinasAlfabeto: TStringField;
    t_maquinasAlfabeto_auxiliar: TStringField;
    t_estadosCd_maq: TIntegerField;
    t_estadosNm_estado: TStringField;
    t_estadosTipo: TStringField;
    t_regrasCd_maq: TIntegerField;
    t_regrasNm_estado: TStringField;
    t_regrasNovo_estado: TStringField;
    t_regrasGravacao: TStringField;
    t_regrasDirecao: TStringField;
    t_regrasEntrada: TStringField;
    Gravar_transicoes: TBitBtn;
    
    Panel8: TPanel;
    Panel5: TPanel;
    DeltaGrid: TStringGrid;
    Label1: TLabel;
    TB_Regras: TTable;
    TB_RegrasCd_maq: TIntegerField;
    TB_RegrasNm_estado: TStringField;
    TB_RegrasEntrada: TStringField;
    TB_RegrasNovo_estado: TStringField;
    TB_RegrasGravacao: TStringField;
    TB_RegrasDirecao: TStringField;
    Memo1: TMemo;
    Timer1: TTimer;
    Panel10: TPanel;
    Label9: TLabel;
    StrGrid: TStringGrid;
    Label6: TLabel;
    t_maquinasCd_maq: TIntegerField;
    Panel12: TPanel;
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    Label5: TLabel;
    Edit6: TEdit;
    Sair: TBitBtn;
    ExecutarMaquina: TButton;
    Label3: TLabel;
procedure SairClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
    procedure t_maquinasBeforePost(DataSet: TDataSet);
    procedure t_maquinasBeforeInsert(DataSet: TDataSet);
    procedure ds_maquinaDataChange(Sender: TObject; Field: TField);
    procedure ExecutarMaquinaClick(Sender: TObject);
    procedure PageControl1Change(Sender: TObject);
    procedure Gravar_transicoesClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure BitBtn2Click(Sender: TObject);
private
    s : char;
    { Private declarations }
public
{ Public declarations }
end;

var
  f0001: Tf0001;
  prox:integer; // variavel global para incremento nas tabelas
  const BRANCO = '&';

implementation   

{$R *.DFM}

procedure Tf0001.SairClick(Sender: TObject);
begin
   close;
end;

procedure Tf0001.FormCreate(Sender: TObject);
begin
   // o alias esta sendo criado automaticamente no turing.dpr

   database1.open; //abre banco de dados

   windowstate:=wsmaximized; //maximiza a tela principal

   t_maquinas.open; //ativa as tabelas do bd
   t_estados.open;
   tb_regras.open;
   t_regras.open;

end;

procedure Tf0001.t_maquinasBeforePost(DataSet: TDataSet);
begin
   t_maquinas.fieldbyname('cd_maq').asinteger:=prox;
      // incrementa na hora de inserir registros
end;

procedure Tf0001.t_maquinasBeforeInsert(DataSet: TDataSet);
begin
        with t_maquinas do begin
          last;  //vai para o ultimo registro da tabela
          prox:=fieldbyname('cd_maq').asinteger+1; //ultimo + 1
        end;
end;

//RECEBE NOME DA MAQUINA
procedure Tf0001.ds_maquinaDataChange(Sender: TObject; Field: TField);
begin
        label9.caption:=t_maquinas.fieldbyname('ds_maq').asstring;
end;


//EXECUTA MAQUINA
procedure Tf0001.ExecutarMaquinaClick(Sender: TObject);

    //   R : direita
     //   L : esquerda
     //   AS ENTRADAS DOS ESTADOS SAO TODOS UM CARACTERE
     //   NA ENTRADA DO DELTA AO INVES DE DIGITAR delta(p,1)
     //   E IGUAL A q,W -> R DIGITAR q,W,R

type TMov = record
              cNewState  : char;   //{NOVO ESTADO
              cWrite     : char;   //{VALOR GRAVADO
              cDirection : char;   //{DIRECAO
    end;
var
    iPosicao,iLin,iCol,iTamCad,i,j,x,y,iLCad,Pont,iTamF: integer;
    sCadeia :string;
    sQ,sSigma,sV,sEntDelta : string;
    cQo,c,cQA,cQR : char;
    Aceita, NaoAceita,NaoDeuCaca : boolean;
    MovDelta : array [1..100,1..100] of TMov;
    iColCad : array [1..100] of integer;
    iColEnt : array [1..100] of integer;

//FAZ A LEITURA DA FUNCAO DE TRANSICAO (DELTA)
procedure LeDelta(iNumL,iNumC,y : integer);
var i,j : integer;
    d : string[3];
begin
  for i:=1 to iNumL do     //iNuml = NUMERO DE ESTADOS DA GRADE DeltaGrid
      for j := 1 to iNumC do  //iNumC = NUMERO DE ENTRADAS DA GRADE DeltaGrid
      begin
      TB_Regras.First;
      While not TB_Regras.EOF do begin
        if ((TB_RegrasNm_estado.Value = copy(DeltaGrid.Cells[0,i],1,1))and(TB_RegrasEntrada.Value = copy (DeltaGrid.Cells[j,0],1,1))) then begin
          MovDelta[i,j].cNewState:= TB_RegrasNovo_estado.Value[1];   //NOVO ESTADO
          MovDelta[i,j].cWrite:= TB_RegrasGravacao.Value[1];         //GRAVACAO
          MovDelta[i,j].cDirection:= TB_RegrasDirecao.Value[1];      //DIRECAO

          TB_Regras.Next;
        end else
          TB_Regras.Next;
      end;
  end;
end;

//RETORNA A POSICAO DE c NAS ENTRADAS NO DeltaGrid
function PosEnt(c:char):integer;
var i,ret:integer;
begin
   ret := 0;
   for i:= 1 to iCol do
   if sEntDelta[i] = c then
   begin
      ret := i;
      break;
   end;
   PosEnt :=ret;
end;


//RETORNA A LINHA EM QUE s SE ENCONTRA NO DeltaGrid
function PosQ(s:char):integer;
var i, ret : integer;
begin
   ret := 0;
   for i:= 1 to iLin do
   if sQ[i] = s then
   begin
      ret := i;
      break;
   end;
   PosQ :=ret;
end;

//==========================================================
//ENTRADA : ESTADO, CARACTER

function Move(s,c:char):char; //retorna o proximo estado
var iLinQ, iColEnt,i, LinDelta, ColDelta : integer;
    myRect: TGridRect;
    NovoQ : char;
begin
   iLinQ := PosQ(s);
   iColEnt := PosEnt(c);
   if (iLinQ <> 0) and (iColEnt <> 0) then
   begin
        sCadeia[Pont] := MovDelta[iLinQ,iColEnt].cWrite;  // Grava símbolo
        StrGrid.Cells[Pont-1,0] := sCadeia[Pont]; // grava

        if MovDelta[iLinQ,iColEnt].cDirection = 'R' then inc(Pont)
        else if MovDelta[iLinQ,iColEnt].cDirection = 'L' then dec(Pont);
        NovoQ:= MovDelta [iLinQ,iColEnt].cNewState;    // novo estado
   end
   else NovoQ := cQr;

   {***********   Movimenta Transicoes  *********************}

   LinDelta := PosQ(NovoQ);   //POSICAO DE Q
   ColDelta := PosEnt(sCadeia[Pont]);  // POSICAO DO ALFABETO
   //SELECIONA A CELULA DA STRING QUE ESTA SENDO LIDA
   myRect.Left := ColDelta; //coluna inicial
   myRect.Top := LinDelta;  //linha inicial
   myRect.Right := ColDelta; //coluna final
   myRect.Bottom := LinDelta;//linha final
   DeltaGrid.Selection := myRect;

   {****************  Grava na fita (grid)  *********************}
   StrGrid.Rows[1].clear;  //LIMPA A LINHA DO ESTADO

   StrGrid.Cells[Pont-1,1] := NovoQ; //escreve o estado

  //PINTA A CELULA DO DeltaGrid
   myRect.Left := Pont-1;
   myRect.Top := 1;
   myRect.Right := Pont-1;
   myRect.Bottom := 1;
   StrGrid.Selection := myRect;

   result:=NovoQ;  //retorna novo estado
end;     //move


//===============================================
//VERIFICA SE O ESTADO PERTENCE
//=======================================================
//**************************************************************************
//PROGRAMA INICIAL MAQUINA DE TURING
//**************************************************************************

var k,LinDelta,ColDelta : integer;
    caminho:string;
    myRect : TGridRect;
begin
    // processo principal

    for i:=1 to StrGrid.ColCount-1 do StrGrid.Cols[i].Clear;
      StrGrid.ColCount := length(Edit6.text)+1;
    for i := 0 to StrGrid.ColCount-1 do
      StrGrid.Cells[i,0] := copy(Edit6.text,i+1,1);
    StrGrid.Cells[i-1,0] := BRANCO;
    label9.visible:=false;
    panel10.caption:='Calculando...';
    timer1.Enabled:=false;

    sQ := '';
    t_estados.first;
    While not t_estados.EOF do begin
      sQ := sQ + t_estadosNm_estado.Value;
      t_estados.Next;
    end;
     with t_estados do begin
       first;
       //percorre a tabela de estados buscando accept, reject e inicial
       repeat
          if (fieldbyname('tipo').asstring='s') or (fieldbyname('tipo').asstring='S')
          then cQo := fieldbyname('nm_estado').asstring[1]; //INICIAL
          if (fieldbyname('tipo').asstring='a') or (fieldbyname('tipo').asstring='A')
          then cQA := fieldbyname('nm_estado').asstring[1]; //ACCEPT
          if (fieldbyname('tipo').asstring='r') or (fieldbyname('tipo').asstring='R')
          then cQR := fieldbyname('nm_estado').asstring[1]; //REJECT
          next;
       until (eof);
     end;
     with t_maquinas do begin
       sSigma := fieldbyname('alfabeto').asstring;  //GUARDA ALFABETO
       sV := fieldbyname('alfabeto_auxiliar').asstring;//ALFABETO AUXILIAR (gama)
     end; //with

     iLin := length(sQ);  //GUARDA NUMERO DE ESTADOS
     sEntDelta := sSigma+sV+BRANCO; //PREPARA ENTRADA PARA DeltaGrid
     iCol := length(sEntDelta); //GUARDA NUMERO DE ENTRADAS

     DeltaGrid.Refresh;
     sCadeia := edit6.text;
     sCadeia := sCadeia+BRANCO;//ATUALIZA A CADEIA COM BRANCO

     ColDelta := PosEnt(sCadeia[1]);//GUARDA A POSICAO DO PRIMEIRO SIMBOLO
                                    //DA CADEIA NA ENTRADA EM DeltaGrid
     iTamCad:=length(sCadeia);

     LeDelta(iLin,iCol,y); //Leitura de Delta

     Pont := 1; //APONTA PARA O PRIMEIRO SIMBOLO NA CADEIA
     s := cQo;
     LinDelta := PosQ(s);

     // Pinta a transicao (Delta)
     myRect.Left := ColDelta;
     myRect.Top := LinDelta;
     myRect.Right := ColDelta;
     myRect.Bottom := LinDelta;
     DeltaGrid.Selection := myRect;

     // Pinta a cadeia
      myRect.Left := Pont-1;
      myRect.Top := 1;
      myRect.Right := Pont-1;
      myRect.Bottom := 1;
      StrGrid.Selection := myRect;

     //Grid da cadeia
     StrGrid.Cells[Pont-1,1] := s;  //ESCREVE O ESTADO INICIAL NA CADEIA

     NaoAceita := true;
     NaoDeuCaca := true;
     Memo1.Clear;
     Caminho := cQo+':' + sCadeia;
     Memo1.Lines.Add(Caminho);
     while NaoAceita and NaoDeuCaca do
     begin

         //RECEBE O PROXIMO CARACTER DA CADEIA
        if Pont <= iTamCad then begin
           c := sCadeia[Pont];
        end else c := BRANCO;

        Application.ProcessMessages;
        sleep(500);  //pausa no processamento para que se observe (delay)
        s := Move(s,c); //PEGA NOVO ESTADO

        Caminho := '';
        if (Pont) = 1 then
            Caminho := Caminho + s+':' + sCadeia  // Posicao inicial de q
        else
           for k := 1 to iTamCad do
           if k <> Pont then
              Caminho := Caminho + sCadeia[k] //copia a cadeia
           else  Caminho := Caminho+s+':'+sCadeia[k];

        if Pont > iTamCad then Caminho := sCadeia+ s+':';
        Memo1.Lines.Add(Caminho);

        NaoAceita := s <> cQA;
        NaoDeuCaca:= (s <> cQR);
     end;

     label9.font.Color:=clwhite; //como o fundo sera de cor escura faz a fonte branca
     Caminho := '';

     Aceita := (Not NaoAceita) and NaoDeuCaca;
     timer1.Enabled:=true;

     if Aceita then begin
                     label9.caption:='Palavra aceita';
                     label9.color:=clblue;
                    end
     else begin
                     label9.caption:='Palavra NÃO aceita';
                     label9.color:=clred;
                    end;
     panel10.caption:=label9.caption;
     edit6.SetFocus;//vai para o edit para se digitar uma nova palavra
end;


procedure Tf0001.PageControl1Change(Sender: TObject);
var i, j : integer;
begin
  TB_Regras.Filter := 'Cd_maq = '+ IntToStr(t_estadosCd_maq.Value);
  TB_Regras.Refresh;


  //Limpa as celulas da tabela
  for i:=1 to DeltaGrid.ColCount-1 do
  DeltaGrid.Cols[i].Clear;

  //copia alfabeto para a tabela delta = DeltaGrid
  for i:=1 to length(t_maquinasAlfabeto.Value) do
  DeltaGrid.Cells[i,0]:=(copy(t_maquinasAlfabeto.Value,i,1));
   //copia alfabeto auxiliar para a tabela delta = DeltaGrid
  for j:=1 to length(t_maquinasAlfabeto_auxiliar.Value) do
  DeltaGrid.Cells[j+i-1,0]:=(copy(t_maquinasAlfabeto_auxiliar.Value,j,1));

  DeltaGrid.Cells[j+i-1,0]:=(BRANCO);//(225));
  DeltaGrid.ColCount := j+i;

  with t_estados do begin
     first;
     i := 1;
     while not eof do begin   //copia estados para celula(0,lin)
       DeltaGrid.Cells[0,i]:=(t_estadosNm_estado.Value);
       next;
       inc(i);
     end;
  end;
  DeltaGrid.RowCount := i;
   //----- carrega stringgrid com dados da tabela ---------
  for i:=1 to DeltaGrid.RowCount-1 do begin // percorre os estados qi no grid (coluna)
    for j:=1 to DeltaGrid.ColCount-1 do begin // percorre os simbolos (linha)
      TB_Regras.First;
      While not TB_Regras.EOF do begin
        if ((TB_RegrasNm_estado.Value = copy(DeltaGrid.Cells[0,i],1,1))and(TB_RegrasEntrada.Value = copy (DeltaGrid.Cells[j,0],1,1))) then begin
          DeltaGrid.Cells[j,i] := TB_RegrasNovo_estado.Value+','+
                                      TB_RegrasGravacao.Value+','+TB_RegrasDirecao.Value;
          TB_Regras.Next;
        end else
          TB_Regras.Next;
      end;
    end;
  end;


   // -----------------------------------------------------

end;

procedure Tf0001.Gravar_transicoesClick(Sender: TObject);
var  i,j : integer;
begin
  t_estados.FIRST;
  while not t_estados.eof do begin
    while not t_regras.eof do t_regras.delete;
    t_estados.next;
  end;
  for i:=1 to DeltaGrid.RowCount-1 do begin // percorre os estados qi no grid (coluna)
    for j:=1 to DeltaGrid.ColCount-1 do begin // percorre os simbolos (linha)
      if (DeltaGrid.Cells[j,i] <> '') then begin
        t_regras.insert;
        t_regrasNm_estado.Value := copy (DeltaGrid.Cells[0,i],1,1); // pega o estado
        t_regrasEntrada.Value:= copy (DeltaGrid.Cells[j,0],1,1);
        t_regrasNovo_estado.Value := copy (DeltaGrid.Cells[j,i],1,1);
        t_regrasGravacao.Value := copy (DeltaGrid.Cells[j,i],3,1);
        t_regrasDirecao.Value := copy (DeltaGrid.Cells[j,i],5,1);
        t_regras.post;
      end;
    end;
  end;
end;

procedure Tf0001.Timer1Timer(Sender: TObject);
begin
   //faz piscar o label9 (resultado)
   label9.visible:= not label9.Visible;
end;

procedure Tf0001.BitBtn1Click(Sender: TObject);
begin
       if messagedlg('Excluir a máquina '+t_maquinas.fieldbyname('ds_maq').asstring+'? ',
           mtConfirmation, [mbYes, mbNo], 0) = mrYes then
       begin

        with t_regras do begin
           while not eof do
             delete;
        end;
        with t_estados do begin
           while not eof do
             delete;
        end;
        with t_maquinas do begin
             delete;
        end;
       end;

end;

procedure Tf0001.BitBtn2Click(Sender: TObject);
var i : integer;
begin
   for i:=0 to StrGrid.rowcount-1 do
     StrGrid.Rows[i].Clear;

   Panel10.color := clsilver;
   Panel10.Caption := 'Digite outra palavra';
   Panel10.Visible := True;
   Label9.Visible := False;
   Timer1.Enabled := false;
   memo1.Clear;
   Edit6.Clear;
   Edit6.SetFocus;
end;

end.


