program AmigaVirtual;

{$MODE OBJFPC}

const
 threshold = 0.65; //порог обучения/ответа
 defsyl = 4; //длина слога по умолчанию

type
 TDB = array of string; //база данных

var
 DB: TDB;

//Вычисление совпадений строк, результат в диапазоне 0.0 .. 1.0
function CalcSim(A, B: string; syl: integer = defsyl): real;

 //Входит ли строка B в строку S?
 function IsStrInStr(B, S: string): boolean;
 var
  i: integer;
 begin
  IsStrInStr := false;
  for i := 1 to Length(S) - Length(B) + 1 do
   if B = Copy(S, i, Length(B)) then
   begin
    IsStrInStr := true;
    exit;
   end;
 end;

 //Число слогов в строке
 function SylCount(S: string; syl: integer): integer;
 begin
   SylCount := Length(S) - syl + 1;
 end;

var
 Match: integer = 0;
 i: integer;
 C, D: string;
begin
 //Если строки и так одинаковые, выходим
 if A = B then
 begin
  CalcSim := 1;
  exit;
 end;

 //Определяем короткую (D) и длинную (C) строки
 if Length(A) > Length(B) then
 begin C := A; D := B; end else
 begin C := B; D := A; end;

Write(Length(D), ' ', Length(C), ' - ');

//Если наименьшая строка меньше длины слога
 if Length(D) < syl then
 begin
  C := C + Copy(C, 1, Length(D) - 1);
  if IsStrInStr(D, C) then Match := 1;
  CalcSim := Match / SylCount(C, Length(D));
  exit;
 end;

 //Добавляем символы из начала строк в их конец
 C := C + Copy(C, 1, syl - 1);
 D := D + Copy(D, 1, syl - 1);

 //Подсчитываем количество совпадающих слогов
 for i := 1 to Length(C) - syl + 1 do
  if IsStrInStr(Copy(C, i, syl), D) then
   inc(Match);

 //Вычисляем процент совпадений
 CalcSim := Match / SylCount(C, syl) ;
end;

//Загружаем БД из файла
function LoadDB: TDB;
var
 buf: TDB;
begin
 while not eof do
 begin
  SetLength(buf, Length(buf)+1);
  Readln(buf[Length(buf)-1]);
 end;
 LoadDB := buf;
end;

//Ищем в БД максимально совпадающую с LastSent строку
//и выдаём следующую за ней строку
function NextSentence(var DB: TDB; LastSent: string; var MS: real): string;
var
 Sim, MaxSim: real;
 i: integer;
begin
 MaxSim := 0;
 for i := 0 to Length(DB) - 2 do
 begin
  Sim := CalcSim(DB[i], LastSent);
  //Если нашли строку, которая совпадает больше
  if Sim > MaxSim then
  begin
   MaxSim := Sim;
   NextSentence := DB[i + 1];
  end;
 end;
 //Если процент совпадения меньше порога,
 //тогда записываем строку в БД
 if MaxSim < threshold then
 begin
  NextSentence := '[SYSTEM] Нет ответа, фраза запомнена';
  SetLength(DB, Length(DB) + 1);
  DB[Length(DB) - 1] := LastSent;
 end;
 MS := MaxSim;
end;

//Сравниваем две строки между собой
//и выводим результат на экран
procedure SS(A, B: string; syl: integer = defsyl);
begin
 Writeln(A + ':' + B + ' - ', (CalcSim(A, B, syl) * 100):3:2, '%');
end;

//Имитация отправки пользователем строки
procedure Say(S: string);
var
 Sim: real;
begin
 Writeln('Вы: ', S);
 Writeln('AV: ', NextSentence(DB, S, Sim), ' (', (Sim * 100):3:2, '%)');
end;

var
 i: integer;

begin
 DB := LoadDB;
 Say('Как дила?');
 Say('Ну дык чо, о чём побазарим?');
 Say('Да за жизнь нашу блатную');
 Say('О чём побазарим?');
 Say('Побазарим о чём?');
 Say('Скажи, что такое молоко?');
 Say('Молоко - это напиток.');
 Say('Скажи, что такое малако?');
 Say('Скажи, что такое Колыма?');
 Say('Что такое Колыма?');
 Writeln;
 //Распечатываем БД
 Writeln('---- DB dump: ----');
 for i := 0 to Length(DB) - 1 do
  Writeln(DB[i]);
 Writeln;
 SS('abcd', 'fghj');
 SS('abcd', 'nm');
 SS('abcd', 'abfg');
 SS('abcd', 'abce');
 SS('abcd', 'abcd');
 SS('abed', 'abcd');
 SS('abcde', 'abcfr');
 SS('abcdefgh', 'abcd');
 SS('abcdefgh', 'cd');
 SS('abcd', 'abcde');
 SS('abcdef', 'abc');
 SS('abcd', 'cdab');
 SS('abcdef', 'abefcd');
 SS('молоко', 'малако');
 SS('молоко', 'млко');
 SS('молоко', 'Колыма');
 SS('абвгдеёжзи', 'абв', 4);
 SS('абвгдеёжzи', 'абв', 4);
 SS('abcdefghij', 'abc', 4);
 SS('абвгдеёжзи', 'аб', 4);
 SS('абвгдеёжзи', 'а', 4);
 SS('абвгдеёжзи', '', 4);
end.