unit uIVRClient;

interface

uses
  Classes, SysUtils, syncobjs, Windows;

type TTask = (SIPNone,SIPConnect, SIPRecord, SIPPlay, SIPDisconnect,
    SIPDigits, SIPCall, SIPSendDTMF);


type
  TIVR = class(TThread)
  private
    { Private declarations }
     Digits: string;
     LockIVR: TCriticalSection;
  protected
    procedure Execute; override;
  public
    Connected: Boolean;
    chan: Integer;
    PlayFileName: string;
    RecordFileName: string;
    Task: TTask;
    WaitingTask: TTask;
    SIPAddr: string;
    AuthorID: string;
    Subject: string;
    DTMFDigit: Char;
    Worktype: string;
    StartupDir: string;
    FileLength: Integer;
    GoodAuthor: Integer;
    BadAuthor: Integer;
    GoodSubject: Integer;
    BadSubject: Integer;
    GoodWorktype: Integer;
    BadWorktype: Integer;
    GoodLength: Integer;
    BadLength: Integer;
    OKLength: Integer;
    IVRStatus: ShortString;
    Logging: Boolean;
    procedure DoDisconnect;
    procedure Connect;
    procedure Disconnect;
    procedure PlayFile(FileName: string);
    procedure RecordFile(FileName: string);
    procedure Log(s: string);
    procedure LogBad(s: string);
    procedure AddDigit(d: Char);
    procedure CallServer;
    procedure Send(s: string);
    procedure SendDigit(c: char);
    procedure CollectStats;
    function GetDelimitedField(s:string;DelimitStart: Char; DelimitEnd: Char): string;
  end;

implementation


function GetFileSizeFromName(FileName: string): Integer;

var
f: file of Byte;

begin
 Result := 0;
 try
    if FileExists(FileName) = true then begin
        AssignFile(f, FileName);
        // 02/25/03 placed try/except around Reset and FileSize
        // to insure that CloseFile is called.
        try
            Reset(f);
            Result := FileSize(f);
        except

        end;
        CloseFile(f);
    end;
 except

 end;

end;


procedure TIVR.Execute;
var
SubjectID: Integer;
FirstTime: Boolean;
Count: Integer;
MaxCount: Integer;
t: Integer;
s: string;
begin
  { Place thread code here }

  StartupDir:= GetCurrentDir;
  LockIVR:= TCriticalSection.Create;

  Log('IVR Client Starting ...');

  SubjectID:= (Chan+ 1) * 100000;
  FirstTime:= True;
  Count:= 0;
  MaxCount := 1000;
  GoodAuthor:= 0;
  BadAuthor:= 0;
  GoodSubject:= 0;
  BadSubject:= 0;
  GoodWorktype:= 0;
  BadWorktype:= 0;
  GoodLength:= 0;
  BadLength:= 0;
  OKLength:= 0;

  Sleep(3000 * Chan);

  FileLength := GetFileSizeFromName(StartupDir + '\Prompts\author.mlw');
  IVRStatus:= '???';
  
  While (Terminated = False) do
  begin
       Connected:= False;

       if Count >= MaxCount then begin
           Sleep(5000);
           if Count = MaxCount then begin
                Log('IVR Finished, Count = ' + IntToStr(Count));
                Count:= Count + 1;
           end;
           Continue;
       end;
       Count:= Count + 1;
       task:= SIPNone;
       WaitingTask:= SIPNone;
       AuthorID := IntToStr(100 + Chan);
       Worktype:= '1';
       Digits := '';
       DTMFDigit:= '0';
       SubjectID:= SubjectID + 1;
       Subject := IntToStr(SubjectID);
       Log('Begin Conversation v1.0: ' + SIPAddr);

       CallServer;
       if FirstTime then begin
            Sleep(2000);
            FirstTime:= False;
       end;

       if Connected then Sleep(2000);
       if Connected then Send(AuthorID + '#');   //Author
       if Connected then Sleep(1000);
       if Connected then Send(WorkType + '#');   //Worktype
       if Connected then Sleep(1000);
       if Connected then Send(Subject + '#'); //Subject
       if Connected then Sleep(1000);

       if Connected then Send('2');       //record
       if Connected then Sleep(500);
       if Connected then PlayFile('author.mlw'); //This file will be recorded by the server
       if Connected then Sleep(250);
       if Connected then Send('7');       //playback
       if Connected then Sleep(1000);
       if Connected then Send('8');       //Request Info
       
       for t:= 0 to 60 do begin
           LockIVR.acquire;
           s:= Digits;
           LockIVR.release;
           if Pos('#',s) > 0 then
                break;
           sleep(1000);
           if Not Connected then break;
       end;
       CollectStats;

       if Connected then DoDisconnect;

       Sleep(1000);

  end;
  Log('<<<< Terminated >>>>');
  LockIVR.Free;
end;

procedure TIVR.DoDisconnect;
begin
    Log('Enter DoDisconnet');
    if Connected then Disconnect;
    Log('Exit DoDisconnet');
end;
procedure TIVR.Connect;
begin
    Log('Enter Connect');
    Task:= SIPConnect;
    Suspended:= True;
    Log('Exit Connect');
end;

procedure TIVR.Disconnect;
begin
    Log('Enter Disconnect');
    Task:= SIPDisconnect;
    Suspended:= True;
    Log('Exit Disconnect');
end;

procedure TIVR.PlayFile(FileName: string);
begin
   Log('Enter PlayFile: ' + FileName);
   PlayFileName:= FileName;
   Task:= SIPPLay;
   Suspended:= True;
   Log('Exit PlayFile');
end;
procedure TIVR.RecordFile(FileName: string);
begin
    Log('Enter RecordFile: ' + FileName);
    RecordFileName:= FileName;
    Task:= SIPRecord;
    Suspended:= True;
    Log('Exit RecordFile');
end;

procedure TIVR.Send(s: string);
var
i, Len: Integer;
begin
    Log('Enter Send[' + s + ']');
    Len := Length(s);
    for i := 1 to Len do begin
       SendDigit(s[i]);
       if Not Connected then break;
    end;
    Log('Exit Send');
end;

procedure TIVR.SendDigit(c: Char);
var
s: string;
begin
    s:= c;
    Log('Enter SendDigit[' + s + ']');
    DTMFDigit:= c;
    Task:= SIPSendDTMF;
    Suspended:= True;
    Sleep(500);
    Log('Exit SendDigit[' + s + ']');
end;

procedure TIVR.CallServer;
begin
    Log('Enter CallServer');
    Task:= SIPCall;
    Suspended:= True;
    if Connected then
        Log('Exit CallServer: Connected')
    else
        Log('Exit CallServer: Not Connected')
end;


procedure TIVR.AddDigit(d: Char);
begin
   Log('Enter AddDigit[' + d + ']');
   LockIVR.acquire;
    try
        Digits := Digits + d;
        Log('Exit AddDigit[' + Digits + ']');
    finally
     LockIVR.Release;
    end;
end;

procedure TIVR.Log(s: string);

var
    Filename: string;
    LogFile: TextFile;
begin
    try
        if Not Logging then exit;
        Filename := StartupDir + '\IVRCLIENT' + IntToStr(chan) + ' .log';
        AssignFile(LogFile, Filename);
        if FileExists(Filename) then
            Append(LogFile)
        else
            Rewrite(LogFile);

        Writeln(LogFile, DateTimeToStr(Now) + ':IVR:' + s);
    except

    end;

    try
        CloseFile(LogFile);
    except

    end;

end;

procedure TIVR.LogBad(s: string);

var
    Filename: string;
    LogFile: TextFile;
begin
    try
        Filename := StartupDir + '\BAD_IVR' + IntToStr(chan) + ' .log';
        AssignFile(LogFile, Filename);
        if FileExists(Filename) then
            Append(LogFile)
        else
            Rewrite(LogFile);

        Writeln(LogFile, DateTimeToStr(Now) + ':IVR:' + s);
    except

    end;

    try
        CloseFile(LogFile);
    except

    end;

end;
procedure TIVR.CollectStats;
var
MyAuthor, MySubj, MyWorktype, MyLength, MyJob, s, x: string;
MyLen, Diff: Integer;
Bad: Boolean;
begin

    LockIVR.acquire;
    s:= Digits;
    LockIVR.release;

    Bad:= False;
    Log('Collect Stats[' + s +']');
    MyJob:=   GetDelimitedField('J' + s,'J','A');
    MyAuthor  := GetDelimitedField(s,'A','B');
    MySubj  := GetDelimitedField(s,'B','C');
    MyWorktype := GetDelimitedField(s,'C','D');
    MyLength := GetDelimitedField(s,'D','#');
    
    x:= 'Job[' + MyJob + '] Author[' + MyAuthor + '] Subj[' + MySubj + '] Worktype[' + MyWorktype
        + '] Recorded Length[' + MyLength + '] Proper Length[' + IntToStr(FileLength) + ']' ;

    Log(x);

    if MyAuthor = AuthorID then begin
        GoodAuthor := GoodAuthor + 1
    end else begin
        BadAuthor:= BadAuthor + 1;
        Bad:= True;
    end;

    if MySubj = Subject then begin
        GoodSubject := GoodSubject + 1
    end else begin
        BadSubject:= BadSubject + 1;
        Bad:= True;
    end;

    if MyWorktype = Worktype then begin
        GoodWorktype := GoodWorktype + 1
    end else begin
        BadWorktype:= BadWorktype + 1;
        Bad:= True;
    end;

    try
        MyLen:= StrToInt(MyLength);
    except
        MyLen := 0;
    end;

    Diff := (FileLength - MyLen) div 8000;

    if Diff < 0 then Diff := - Diff;
    if Diff <= 2 then begin
        GoodLength := GoodLength + 1
    end else if Diff <= 4 then begin
        OKLength:= OKLength + 1
    end else begin
        BadLength:= BadLength+ 1;
        Bad:= True;
    end;

    s:= Format('%4d %7d %7d %7d %7d %7d %7d %7d %7d %7d',[Chan, GoodAuthor, BadAuthor,
        GoodSubject, BadSubject, GoodWorktype, BadWorktype, GoodLength, OKLength, BadLength]);

    IVRStatus := s;

    if Bad then begin
         LogBad(x);
    end;
end;

function TIVR.GetDelimitedField(s:string;DelimitStart: Char; DelimitEnd: Char): string;
var
i,j, len: Integer;
x: string;
begin
    Result := '';
    len := Length(s);
    x := '';
    for i := 1 to len do begin
        if s[i] = DelimitStart then begin
           for j := i + 1 to len do begin
              if s[j] = DelimitEnd then begin
                Result := x;
                exit;
              end;
              if (s[j] >= '0') and ( s[j] <= '9') then
                x := x + s[j]
              else
                exit;
           end;
        end;
    end;
end;


end.
