Содержание
1. Введение.
2. Постановка задачи.
3. Структура системы идентификации.
3.1 Блок предварительной обработки.
3.2 Блок идентификации.
4. Алгоритм сравнения двух слов.
5. Представление данных в иерархической структуре.
6. Программная реализация.
6.1 Объекты программирования.
6.2 Описание интерфейса.
7. Заключение.
8. Список литературы.
9. Приложение.
1 Введение.
В последние годы в нашей стране все больше и больше фирм и организаций приобретают вычислительные машины с целью использования их в своем бизнесе. Персональные вычислительные машины стали неотъемлемой частью нашего быта. Они очень удобны для выполнения различных повседневных задач: составления отчетов и графиков работы, ведение бухгалтерии, планирования и оптимизации производства.
Вместе с развитием вычислительной техники развивается также и область производства прикладных и системных программ, без которых компьютеры не представляют никакого интереса для людей непосвященных в программирование. На сегодняшний день много фирм – производителей программной продукции производят универсальные пакеты прикладных и системных программ для широкого спектра повседневных задач. В основном эти пакеты предназначены для решения, каких – то общих задач: составления отчетов, ведения календарей, редактирования различного рода текстов и графической информации. Существуют также пакеты программ для создания различного рода приложений к разным операционным системам.
Целью моей работы являлось создание программы, позволяющей идентифицировать с целью дальнейшего анализа нестандартизованные табличные данные одной предметной области. Можно говорить о тех предметных областях, в которых описание объекта недостаточно формализовано для непосредственного сравнения, но достаточно формализовано для того, чтоб не строить семантическую модель предметной области.
Такая программа была бы полезна, например, для торговой фирмы с большой товарной номенклатурой и множеством поставщиков, позволяя автоматически выбирать оптимального поставщика для каждой товарной позиции.
Для решения поставленной задачи в качестве среды разработки было принято решение использовать C++ Builder 5 поскольку, на мой взгляд, он дает больше свободы творчеству, чем другие средства, предоставляющие те же возможности.
Ниже приведена постановка задачи. Рассмотрена структура системы идентификации. Далее описан алгоритм сравнения данных. А также рассмотрена возможность представления входных данных в виде иерархической структуры, что позволяет ускорить процесс, проводя идентификацию сначала для узлов дерева, а затем для листьев совпавших узлов. Затем приведено краткое описание интерфейса приложения и основных объектов программирования.
2. Постановка Задачи.
Основная проблема рассмотренная в моей работе заключается в том, что табличные данные поступают от разных источников. Это приводит к тому, что описание одного и того же объекта может иметь несколько допустимых представлений. Все они должны идентифицироваться как один объект. Существенным аспектом в идентификации является выбор признаков в процессе предварительной обработки исходных данных. Другим важным аспектом является процесс решения, основанный на использовании этих признаков и обеспечивающих получение результатов идентификации.
Для первого аспекта важным является следующее: какие входные данные можно считать уместными, и какая обработка исходных данных приводит к получению признаков действительно позволяющих проводить идентификацию. Описание объекта в табличной строке (в дальнейшем позиция) представляет собой перечень его характеристик. После предварительной обработки объект будет характеризоваться некоторым набором k признаков, каждый, из которых принимает дискретные значения. Значит можно задать k-мерное векторное пространство, каждая координата которого представляет один признак Ni, i Ì [1 k]. В таком случае объект задается некоторой точкой k-мерного пространства N. Если для двух объектов N1, N2 ввести понятие меры похожести F(N1,N2), то можно определять степень их близости.
Общая схема процесса.
Будем считать, что имеется база данных с иерархической структурой содержащая описания объектов в одном из представлений. Любой из источников можно взять за такую базу данных. В таком случае задача сведется к идентификации входящих описаний объектов на множестве описаний нашей базы данных или, возможно, принятия решения об отказе идентификации. Для входящего описания достаточно будет вычислить значения меры похожести в паре с каждым описанием из нашей базы данных и, выбрав из них наибольшее значение, вынести решение об идентификации или отказе от нее. Не исключено, что такой перебор всех описаний может занять продолжительное время.
Выделим основные задачи этапа предварительной обработки данных и этапа идентификации.
Этап предварительной обработки.
· Выбор и построение процедур фильтрации данных.
· Задача формирования признаков и выбор данных для их формирования.
Этап идентификации.
· Построение адекватного алгоритма, который вычисляет меру похожести двух описаний.
· Задача уменьшения перебора описаний.
Идеи и методы решения этих задач подробнее рассмотрены ниже.
3. Структура системы идентификации.
При настройке системы для предметной области формируется справочник признаков и справочник единиц измерения числовых признаков. Каждый элемент справочника признаков содержит кроме уникального кода и названия содержит информацию о типе признака («строковый», «числовой») и для числового признака ссылку на соответствующий элемент в справочнике единиц измерения. Справочник единиц измерения содержит уникальный код, название единицы измерения и возможно специальную аббревиатуру.
В некоторых ситуациях невозможно или трудно обеспечить полностью автоматическую идентификацию. Выходом из положения может явиться участие человека на отдельных этапах. Работа над программой продолжается, но пока требуется участие пользователя.
На этапе диалога с пользователем требуется сопоставить столбцам таблицы элементы справочника признаков, в каждом столбце может быть несколько числовых признаков и один текстовый. Для некоторых столбцов может не быть соответствующего элемента в справочнике признаков. Эти столбцы сразу исключаются из дальнейшего рассмотрения. В каждой позиции данные из разных столбцов по отдельности поступают на вход блока предварительной обработки.
Теперь данные представляются в виде дерева (об этом будет сказано ниже). Записывается два файла: файл-заголовок, содержащий информацию о соответствии столбцам признаков и файл данных в виде дерева, где узлам соответствуют группы объектов, а листьям - объекты.
3.1 Блок Предварительной обработки.
Блок предварительной обработки производит фильтрацию данных, исправление некоторых ошибок и выполняет разбиение на потенциальные признаки.
Он включает в себя фильтр неинформативных символов, и символов несущих неоднозначный смысл. Это все символы кроме кириллицы, латиницы, цифр и в некоторых случаях точки или запятой (разделитель десятичной части, разделитель дней, месяцев, лет в дате), а также кроме символов определяемых экспертом предметной области (например – «%»). Слова вида XxxXxxxx разбиваются на пару слов. Здесь же осуществляется перевод строки в нижний регистр.
Далее проверка на ошибки раскладки клавиатуры. Если в слове встречаются и латинские и кириллические символы, то те, которых меньше заменяются по таблице соответствия. В таблице соответствия латинский символ соответствует символу кириллицы, если они схожи по написанию или звучанию, например («k» и «к»). Такого рода ошибки, оказывается, могут возникать при наборе документов.
Транскрипция латинских слов. Если в родном языке встречаются иностранные слова, то чаще всего это слова которые либо непереводятся, либо их перевод неуместен (имена собственные, названия, торговые марки и т.д.). В другом описании объекта эти же имена могут встретиться в русской транскрипции. Транскриптор не имеет словаря, работает по матрице транскрипции, с небольшим набором правил. Неточно, но на данном этапе его достаточно, а дальше будет дорабатываться, возможно, будет необходим словарь.
В позиции ищутся и выделяются конструкции типа «Число - Единица Измерения». Единицы Измерения (Е.И.) для этого берутся из справочника единиц измерения, который создается экспертом предметной области по следующему принципу: Е.И. заносится в справочник, если соответствующий числовой признак играет роль при идентификации. Предусматривается несколько аббревиатур для некоторых специальных Е.И Также возможна пустая Е.И Конструкции «Число - Единица Измерения», образуют числовые признаки.
Если после выбора всех конструкций «Число - Единица Измерения» содержимое поля не пусто, оно является строковым признаком. Теперь имеем ряд числовых признаков и один строковый.
3.2 Блок Идентификации.
Рассмотрим сначала общую схему алгоритма вычисления меры похожести двух описаний. Непосредственно говорить о мере похожести можно только для строковых данных. Для сравнения числовых признаков естественно просто задать относительную погрешность. Значит, результатом сравнения двух числовых признаков является булевое значение. Допустим, в двух описаниях присутствует i-ый числовой признак тогда, если результатом сравнения явилось «ЛОЖЬ» легко вынести решение о несовпадении этих описаний. Сложнее когда в одной из них есть этот признак, а в другой нет. Как показал анализ, это могут быть описания одного объекта. Возможно, стоит ввести вес числового признака. Этот вопрос остается открытым в работе.
В Иерархическом идентификаторе выполняется в первую очередь идентификация групп объектов, а лишь потом идентификация соответствующих объектов. Алгоритм идентификации в обоих случаях один. Лишь во втором случае сужается область поиска.
Идея сравнения двух строковых признаков следующая. Каждый строковый признак может быть представлен списком слов, разделителем слов считаетя пробел. Слова сравниваются друг с другом поочередно
4. Алгоритм сравнения двух слов.
Даже в достаточно формализованных предметных областях часто невозможно прямое сравнение слов строковых признаков только из-за различных морфологических конструкций и принятых сокращений.
В ситуации, когда во многих базах данных средства ввода информации не имеют орфрграфического контроля, когда некоторые иностранные слова (например, торговые марки) имеют свободную неустоявшуюся транскрипцию в родном языке возможны ошибки и разнописания.
Сравнивние начала двух слов также может не давать полного эффекта в некоторых случаях. Поэтому отчасти оттого, что сравнение строковых данных одно из слабых звеньев системы, отчасти из-за неизбежных погрешностей транскриптора решено было уделить алгоритму сравнивания слов больше внимания и построить алгоритм, который бы учитывал многие факторы. Идея сравнения двух слов такая. Возьмем алфавит, из которого состоят два сравниваемых слова, и выделим буквы, которые есть и в том и в другом слове. Для примера рассмотрим два слова «алпенгольд» и «альпиенгольд». Их общий алфавит «алпенгоьд». Построим для каждого слова матрицу, в которой столбцам соответствуют номер буквы в алфавите, а строкам позиция буквы в слове. Элемент матрицы (i,j) равен «ИСТИНА», если буква с номером j в алфавите находится в позиции i в слове.
Если теперь сдвигать матрицы друг относительно друга по вертикали на k элементов, то синий участок единиц совпадет при k=0, красный и зеленый при k=2.
Программная реализация этого алгоритма может быть очень простой. Если составить массив
6. Программная реализация.
6.1 Основные объекты программирования.
В листингах приложения идентификаторы соответствуют следующим обозначениям :
Описание основных классов приложения
classTPositions{
void SaveTo(FILE *f);
void LoadFrom(FILE *f);
int LastIn(AnsiString SourceString,AnsiString SubStr);
AnsiString Replace(AnsiString SourceString,AnsiString Replacer,AnsiString Displacer);
AnsiString TransCrypt(AnsiString LatString);
AnsiString MisPrint(AnsiString MisPrinted);
AnsiString GoodString(AnsiString BadString);
void Init(AnsiString Sentence);
AnsiString Sentence(int fl=-1);
void Clear();
};
TMDIBaseClass = class(TMDIChild)
procedure SetGraphParms;
procedure draw; // функция рисования
procedure AddMinMax( first: boolean;//определяет экстремумы
value : real);//функции
function toy(yy: real): integer;//Функции переводят объектные
function tox(xx: real): integer;// координаты в экранные
function tox1(x: integer): real;//и наоборот
function toy1(y: integer): real;
TMDITimeFunc = class(TMDIBaseClass)
// обеспечивают изменение опорных точек спроса
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure GetSplineParms;
procedure SelectedPoint(var no,side:Integer;X, Y: Integer);
TSpline = class
procedure InitHorizont(aSDPoints:integer;
aDPoints:integer;aSDLevelDef:real);
procedure Interpolation;//интерполяция на всем временном интервале
Интерполяция сплайна со свободными границами
procedure InterpolationSplineFree(
var startNo:integer;
SDLeft:integer;
SDRight:integer);
Интерполяция сплайна первого порядка
procedure InterpolationLinear(
var startNo:integer;
SDLeft:integer;
SDRight:integer);
Интерполяция сплайна с фиксированными границами
procedure InterpolationSplineFixed(
var startNo:integer;
RightBorder:boolean;
SDLeft:integer;
SDRight:integer);
function SetPoint(point: integer; side: integer; xx: double; yy:
double): boolean;
function Invert( A:Tmatr; k:integer; var A1:Tmatr ):double;
6.2 Описание интерфейса.
При запуске программы на экране монитора появляется форма с названием ”MainForm”. Это основное окно, которое отображается на экране с самого начала и не исчезает до завершения работы. Оно содержит такое средство управления как главное меню (Main Menu), которое состоит из следующих пунктов: “File”, ”Contractors”, ”Base”, ”Settings”, ”Help”. На рисунке представлен результат работы блока предварительной обработки строковых данных.
Работа с приложением начинается с установки параметров. При выборе в главной форме из меню “Settings” пункта “Common…” появляется окно диалога (рис.4). На котором пользователь при помощи “мыши” формирует справочник признаков и справочник единиц измерения. Далее добавление нового документа осуществляется путем выбора из меню “File” пункта “Add Base”. Открывается окно мастера импорта текстового документа, в котором разделителем полей является символ табуляции.
Для редактирования внутреннего представления документа в иерархической структуре можно использовать следующее окно. “Base\\Edit”. Оценить результат идентификации двух позиций из разных документов, можно используя следующее окно.
Заключение.
В данной работе были решены следующие задачи. Первое, что было сделано – это изучена и проанализирована предметная область - торговые предприятия, продуктов питания. Реализована возможность представления данных в иерархической структуре. Был построен алгоритм, вычисляющий меру похожести двух табличных позиций. Изучена среда разработки приложений C++ Builder 5 и создан проект. На данном этапе разработка приложения не остановлена, она продолжается. Следующим ее этапом будет реализация иерархического идентификатора, улучшение блока транскрипции, возможно, если будет необходимо, перевода с одного языка в другой. Также будет перенесен окончательный выбор признаков в блок предварительной обработки. И, наконец, построение механизма анализа идентифицированных документов.
Список литературы
1. К. Верхаген Р. Дейн Ф. Грун «Распознавание образов. Состояние и перспективы» - Москва: Издательство «Радио и связь» 1985г.
2.
Приложение.
//---------------------------------------------------------------------------
#ifndef PositionH
#define PositionH
#include
const int FlowNum=5;
const int NumbersNum=5;
const int WordsNum=20;
const int ChangeSymbolsNum=1;
const int RusLatErrorsNum=11;
//Ôóíêöèè ôèëüòðà
class TSettings{
public:
AnsiString DelSyms;
AnsiString CyrSyms;
AnsiString LatSyms;
AnsiString NumSyms;
AnsiString NumNDelim;
AnsiString Delimiters;
AnsiString ChangeSyms[ChangeSymbolsNum][2];
AnsiString SpecSyms;
char Errors[RusLatErrorsNum][2]; //îøèáêè
TSettings();
~TSettings();
//Transcript
AnsiString Sim[26][3];
AnsiString Complex[13][2];
AnsiString Control[4][2];
};
//---------------------------------------------------------------------------
#endif
#include
#pragma hdrstop
#include "Position.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
TSettings T;
bool IsQuantity(AnsiString Word)
{
for(int i=1;i if(T.NumSyms.Pos(Word[i])!=0) return(true);
return(false);
}
TSettings::TSettings(){
DelSyms=AnsiString();
CyrSyms=AnsiString();
LatSyms=AnsiString();
NumSyms=AnsiString();
Delimiters=AnsiString();
SpecSyms=AnsiString();
for(int i=0;i for(int j=0;j ChangeSyms[i][j]=AnsiString();
ChangeSyms[0][0]=AnsiString("&");
ChangeSyms[0][1]=AnsiString(" è ");
// ChangeSyms[1][0]=AnsiString("%");
// ChangeSyms[1][1]=AnsiString("% ");
Delimiters=AnsiString(".,");
SpecSyms=AnsiString("%");
//×èñëà
for(int i=48;i NumSyms=NumSyms+AnsiString(char(i));
NumNDelim=NumSyms+AnsiString(DecimalSeparator);
//Ëàòèíñêèå ñèìâîëû
for(int i=65;i LatSyms=LatSyms+AnsiString(char(i));
for(int i=97;i LatSyms=LatSyms+AnsiString(char(i));
//Ðóññêèå ñèìâîëû
for(int i=192;i CyrSyms=CyrSyms+AnsiString(char(i));
//Äëÿ óäàëåíèÿ
for(int i=1;i switch(i){
case 37 :break;
case 38 :break;
case 32 :break;
case 46 :break;
case 44 :break;
default: DelSyms=DelSyms+AnsiString(char(i));
}
for(int i=58;i DelSyms=DelSyms+AnsiString(char(i));
for(int i=91;i DelSyms=DelSyms+AnsiString(char(i));
for (int i=123;i DelSyms=DelSyms+AnsiString(char(i));
Errors[0][0]=char(241); Errors[0][1]=char(99);
Errors[1][0]=char(226); Errors[1][1]=char(98);
Errors[2][0]=char(224); Errors[2][1]=char(97);
Errors[3][0]=char(234); Errors[3][1]=char(107);
Errors[4][0]=char(236); Errors[4][1]=char(109);
Errors[5][0]=char(229); Errors[5][1]=char(101);
Errors[6][0]=char(242); Errors[6][1]=char(116);
Errors[7][0]=char(238); Errors[7][1]=char(111);
Errors[8][0]=char(240); Errors[8][1]=char(112);
Errors[9][0]=char(245); Errors[9][1]=char(120);
Errors[10][0]=char(237); Errors[10][1]=char(104);
//Transcrypt
Control[0][0]=AnsiString("ght");Control[0][1]=AnsiString("ò");
Control[1][0]=AnsiString("ld");Control[1][1]=AnsiString("ëä");
Control[2][0]=AnsiString("e");Control[2][1]=AnsiString("å");
Control[3][0]=AnsiString("er");Control[3][1]=AnsiString("åð");
Complex[0][0]=AnsiString("tch");Complex[0][1]=AnsiString("÷");
Complex[1][0]=AnsiString("ch");Complex[1][1]=AnsiString("÷");
Complex[2][0]=AnsiString("zsh");Complex[2][1]=AnsiString("æ");
Complex[3][0]=AnsiString("sh");Complex[3][1]=AnsiString("ø");
Complex[4][0]=AnsiString("th");Complex[4][1]=AnsiString("ä");
Complex[5][0]=AnsiString("ou");Complex[5][1]=AnsiString("àó");
Complex[6][0]=AnsiString("ea");Complex[6][1]=AnsiString("è");
Complex[7][0]=AnsiString("ow");Complex[7][1]=AnsiString("àó");
Complex[8][0]=AnsiString("ee");Complex[8][1]=AnsiString("è");
Complex[9][0]=AnsiString("oo");Complex[9][1]=AnsiString("ó");
Complex[10][0]=AnsiString("ph");Complex[10][1]=AnsiString("ô");
Complex[11][0]=AnsiString("ui");Complex[11][1]=AnsiString("ó");
Complex[12][0]=AnsiString("aw");Complex[12][1]=AnsiString("î");
Sim[0][0]=AnsiString("a");Sim[0][1]=AnsiString("à");Sim[0][2]=AnsiString("ýé");
Sim[1][0]=AnsiString("e");Sim[1][1]=AnsiString("å");Sim[1][2]=AnsiString("è");
Sim[2][0]=AnsiString("i");Sim[2][1]=AnsiString("è");Sim[2][2]=AnsiString("àé");
Sim[3][0]=AnsiString("o");Sim[3][1]=AnsiString("î");Sim[3][2]=AnsiString("î");
Sim[4][0]=AnsiString("u");Sim[4][1]=AnsiString("à");Sim[4][2]=AnsiString("ó");
Sim[5][0]=AnsiString("y");Sim[5][1]=AnsiString("è");Sim[5][2]=AnsiString("");
Sim[6][0]=AnsiString("b");Sim[6][1]=AnsiString("á");Sim[6][2]=AnsiString();
Sim[7][0]=AnsiString("c");Sim[7][1]=AnsiString("ê");Sim[7][2]=AnsiString("ñ");
Sim[8][0]=AnsiString("g");Sim[8][1]=AnsiString("ã");Sim[8][2]=AnsiString("äæ");
Sim[9][0]=AnsiString("k");Sim[9][1]=AnsiString("ê");Sim[9][2]=AnsiString("ê");
Sim[10][0]=AnsiString("l");Sim[10][1]=AnsiString("ë");Sim[10][2]=AnsiString("ë");
Sim[11][0]=AnsiString("q");Sim[11][1]=AnsiString("êâ");Sim[11][2]=AnsiString("êó");
Sim[12][0]=AnsiString("t");Sim[12][1]=AnsiString("ò");Sim[12][2]=AnsiString();
Sim[13][0]=AnsiString("d");Sim[13][1]=AnsiString("ä");Sim[13][2]=AnsiString();
Sim[14][0]=AnsiString("f");Sim[14][1]=AnsiString("ô");Sim[14][2]=AnsiString();
Sim[15][0]=AnsiString("h");Sim[15][1]=AnsiString("õ");Sim[15][2]=AnsiString();
Sim[16][0]=AnsiString("j");Sim[16][1]=AnsiString("äæ");Sim[16][2]=AnsiString();
Sim[17][0]=AnsiString("m");Sim[17][1]=AnsiString("ì");Sim[17][2]=AnsiString();
Sim[18][0]=AnsiString("n");Sim[18][1]=AnsiString("í");Sim[18][2]=AnsiString();
Sim[19][0]=AnsiString("p");Sim[19][1]=AnsiString("ï");Sim[19][2]=AnsiString();
Sim[20][0]=AnsiString("r");Sim[20][1]=AnsiString("ð");Sim[20][2]=AnsiString();
Sim[21][0]=AnsiString("s");Sim[21][1]=AnsiString("ñ");Sim[21][2]=AnsiString("ç");
Sim[22][0]=AnsiString("v");Sim[22][1]=AnsiString("â");Sim[22][2]=AnsiString();
Sim[23][0]=AnsiString("w");Sim[23][1]=AnsiString("â");Sim[23][2]=AnsiString("ó");
Sim[24][0]=AnsiString("x");Sim[24][1]=AnsiString("êñ");Sim[24][2]=AnsiString();
Sim[25][0]=AnsiString("z");Sim[25][1]=AnsiString("ç");Sim[25][2]=AnsiString();
}
TSettings::~TSettings(){}
void TPositions::SaveTo(FILE *f){
TStringList *SL=new TStringList();
for(int fl=0;fl SL->Add(ABC[fl]);
for(int i=0;i SL->Add(Words[i][fl]);
for(int i=0;i SL->Add(StrNumbers[i][fl]);
SL->Add(Numbers[i][fl]);
}
fputs(SL->CommaText.c_str(),f);
fputs("\n",f);
SL->Clear();
}
delete SL;
}
void TPositions::LoadFrom(FILE *f){
TStringList *SL=new TStringList();
char str[600];
for(int fl=0;fl fgets(str,600,f);
SL->CommaText=AnsiString(str);
ABC[fl]=SL->Strings[0];
for(int i=0;i Words[i][fl]=SL->Strings[i+1];
if(!Words[i][fl].IsEmpty())
WC[fl]++;
}
for(int i=0;i StrNumbers[i][fl]=SL->Strings[2*i+WordsNum+1];
Numbers[i][fl]=SL->Strings[2*i+2+WordsNum].ToDouble();
if(Numbers[i][fl]!=0)
NC[fl]++;
}
SL->Clear();
if(NC[fl]+WC[fl])
FlowCount++;
}
delete SL;
}
AnsiString TPositions::Replace(AnsiString SourceString,AnsiString Replacer,AnsiString Displacer)
{ SourceString.Insert(Replacer,LastIn(SourceString,Displacer));
SourceString.Delete(LastIn(SourceString,Displacer),Displacer.Length());
return(SourceString);
}
int TPositions::LastIn(AnsiString SourceString,AnsiString SubStr)
{int k=0;
while (SourceString.AnsiPos(SubStr))
{k=SourceString.AnsiPos(SubStr);
SourceString.Insert(AnsiString("_"),k);
SourceString.Delete(k+1,1);
}
return(k);
}
AnsiString TPositions::TransCrypt(AnsiString LatString)
{ AnsiString CheckString;
int Opened=0,s=0;
if (LatString.SubString(1,1).AnsiCompare(AnsiString("e"))==0)
LatString[1]='ý';
if(LatString.SubString(1,2).AnsiCompare(AnsiString("ja"))==0)
{LatString.Delete(1,1);LatString[1]='ÿ';}
if (LatString.SubString(1,1).AnsiCompare(AnsiString("y"))==0){
LatString.Delete(1,1);
if(LatString.SubString(1,1).AnsiCompare(AnsiString("e"))==0)
LatString[1]='å';
if(LatString.SubString(1,1).AnsiCompare(AnsiString("a"))==0)
LatString[1]='ÿ';
if(LatString.SubString(1,1).AnsiCompare(AnsiString("o"))==0)
LatString[1]='å';
}
int SSLen=0;
if (LatString.SubString(LatString.Length(),1).AnsiCompare(AnsiString("s"))==0)
s=1;
for (int i=0;i SSLen=T.Control[i][0].Length();
if (LatString.SubString(LatString.Length()-SSLen+1-s,SSLen).AnsiCompare(T.Control[i][0])==0){
LatString=Replace(LatString,T.Control[i][1],T.Control[i][0]);
Opened=T.Control[i][1].Length()+s;i=0;break;
}
}
for (int i=6;i if (LatString.SubString(LatString.Length()-Opened,1).AnsiCompare(T.Sim[i][0])==0)
for (int j=6;j if (LatString.SubString(LatString.Length()-1-Opened,1).AnsiCompare(T.Sim[j][0])==0){
Opened=0;
break;
}
if (Opened)
for(int i=LatString.Length()-Opened;i>=1;i--)
for(int j=0;j if (LatString.SubString(i,1).AnsiCompare(T.Sim[j][0])==0){
LatString=Replace(LatString,T.Sim[j][2],T.Sim[j][0]);
i=0;break;
}
for(int i=0;i while (LatString.AnsiPos(T.Complex[i][0])!=0)
LatString=Replace(LatString,T.Complex[i][1],T.Complex[i][0]);
for(int i=0;i while (LatString.AnsiPos(T.Sim[i][0])!=0)
LatString=Replace(LatString,T.Sim[i][1],T.Sim[i][0]);
return(LatString);
}
/////////////////////////////////Ôóíêöèÿ èùåò îøèáêè ðàñêëàäêè êëàâèàòóðû
AnsiString TPositions::MisPrint(AnsiString MisPrinted){
AnsiString Corrected=AnsiString();
AnsiString WordBufer;
int LatNumber;
int RusNumber;
int j;
while (!MisPrinted.IsEmpty()){
MisPrinted=MisPrinted.TrimLeft();
if ((j=MisPrinted.Pos(" "))!=0){
WordBufer=MisPrinted.SubString(1,j-1);
MisPrinted=MisPrinted.SubString( j+1,MisPrinted.Length() );
}else {
WordBufer=MisPrinted.SubString( j+1,MisPrinted.Length() );
MisPrinted=AnsiString();
}
LatNumber=0;RusNumber=0;
for(int i=1;i if (int(WordBufer[i])97)
LatNumber++;
if ((int(WordBufer[i])+256)224)
RusNumber++;
}
if (RusNumber*LatNumber)
if (RusNumber>LatNumber){
for (int i=1;i for (int k=0;k if (WordBufer[i]==T.Errors[k][1])
WordBufer[i]=T.Errors[k][0];
}else{
for (int i=1;i for (int k=0;k if (WordBufer[i]==T.Errors[k][0])
WordBufer[i]=T.Errors[k][1];
}
if (RusNumber Corrected=Corrected+char(32)+WordBufer;
}
return(Corrected);
}
AnsiString TPositions::GoodString(AnsiString BadString)
{
//Â Ìàëåíüêèå áóêâû
BadString=BadString.Trim();
int lin=0;
AnsiString HLS[2][2];
if(BadString.IsEmpty())
return(AnsiString());
while(lin lin++;
if(lin==1)
continue;
// if(lin==BadString.Length())
// continue;
HLS[1][0]=BadString.SubString(lin,1);
HLS[1][1]=HLS[1][0].LowerCase();
HLS[0][0]=BadString.SubString(lin-1,1);
HLS[0][1]=HLS[0][0].LowerCase();
if(HLS[1][1].AnsiCompare(HLS[1][0])!=0&&
HLS[0][1].AnsiCompare(HLS[0][0])==0){
BadString.Insert(AnsiString(" "),lin);lin++;
continue;
}
if(T.Delimiters.Pos(BadString[lin])==0)
continue;
BadString.Delete(lin,1);
if(T.NumSyms.Pos(BadString[lin-1])==0){
BadString.Insert(' ',lin);
continue;
}
if(lin>BadString.Length())
continue;
if(T.NumSyms.Pos(BadString[lin])==0){
BadString.Insert(' ',lin);
continue;
}
BadString.Insert(DecimalSeparator,lin);
}
int p;
for(int j=0;j while((p=BadString.Pos(T.ChangeSyms[j][0]))!=0){
BadString.Delete(p,1);
BadString.Insert(T.ChangeSyms[j][1],p);
}
lin=0;
while(lin lin++;
if(T.SpecSyms.Pos(BadString[lin])!=0){
if(lin!=BadString.Length())
BadString.Insert(' ',lin+1);
continue;
}
if(T.NumSyms.Pos(BadString[lin])!=0){
if(lin==1)
continue;
if(T.NumNDelim.Pos(BadString[lin-1])!=0)
continue;
if(BadString[lin-1]==' ')
continue;
BadString.Insert(' ',lin);
}
if(T.NumNDelim.Pos(BadString[lin])!=0)
continue;
if(T.DelSyms.Pos(BadString[lin])==0)
continue;
BadString.Delete(lin,1);
BadString.Insert(' ',lin);
}
//Óäàëèòü äâîéíûå ïðîáåëû.
while (BadString.Pos(" ")!=0)
BadString.Delete(BadString.Pos(" "),1);
//Óäàëèòü îñòàëüíûå ñïåö çíàêè
BadString=BadString.LowerCase();
return(MisPrint(BadString));
}
TPositions::TPositions(){
FlowCount=0;
for(int i=0;i WC[i]=0;
NC[i]=0;
ABC[i]=AnsiString();
for(int j=0;j Numbers[j][i]=0;
StrNumbers[j][i]=AnsiString();
}
for(int j=0;j Words[j][i]=AnsiString();
}
}
}
void TPositions::Init(AnsiString Sentence){
if(FlowCount==FlowNum)
return;
Sentence=GoodString(Sentence);
AnsiString Piece;
int SpacePos;
while(!Sentence.IsEmpty()){
Sentence=Sentence.Trim();
if((SpacePos=Sentence.Pos(' '))!=0){
Piece=Sentence.SubString(1,SpacePos-1).Trim();
Sentence=Sentence.Delete(1,SpacePos-1).Trim();
}else{
Piece=Sentence.Trim();
Sentence=AnsiString();
}
if(Piece.IsEmpty())
continue;
if(IsQuantity(Piece)){
StrNumbers[NC[FlowCount]][FlowCount]=Piece;
NC[FlowCount]++;
}else{
Words[WC[FlowCount]][FlowCount]=Piece;
WC[FlowCount]++;
}
}
int p;
for(int i=0;i
for(p=1;p if(!T.NumNDelim.Pos(StrNumbers[i][FlowCount][p]))
break;
Numbers[i][FlowCount]=(StrNumbers[i][FlowCount].SubString(1,p-1).Trim()).ToDouble();
StrNumbers[i][FlowCount]=StrNumbers[i][FlowCount].Delete(1,p-1);
}
for(int i=0;i for(int j=1;j if(ABC[FlowCount].Pos(Words[i][FlowCount].SubString(j,1).Trim())==0)
ABC[FlowCount]+=AnsiString(Words[i][FlowCount][j]);
if(NC[FlowCount]+WC[FlowCount])
FlowCount++;
}
void TPositions::Clear(){
FlowCount=0;
for(int fl=0;fl WC[fl]=0;
NC[fl]=0;
ABC[fl]=AnsiString();
for(int i=0;i StrNumbers[i][fl]=AnsiString();
Numbers[i][fl]=0;
}
for(int i=0;i Words[i][fl]=AnsiString();
}
}
AnsiString TPositions::Sentence(int fl){
AnsiString Sent=AnsiString();
if(fl==-1)
for(int f=0;f for(int i=0;i Sent=Sent+Words[i][f]+AnsiString(' ');
else
for(int i=0;i Sent=Sent+Words[i][fl]+AnsiString(' ');
return(Sent);
}
//---------------------------------------------------------------------------
#ifndef PositionTreeH
#define PositionTreeH
#include
#include "Position.h"
//---------------------------------------------------------------------------
typedef enum {aInit=0,aFind=1,aToList=2} WalkAction ;
class TPositionTree{
public:
int Code;
bool IsGroup;
int Depth;
AnsiString OutPres[FlowNum];
TPositionTree *Next;
TPositionTree *Down;
TPositionTree *Prev;
TPositions IP;
void *Data;
TPositionTree();
~TPositionTree();
void Add(TPositionTree *Node);
void AddChild(TPositionTree *Node);
TPositionTree *Add(int sCode,AnsiString sName);
TPositionTree *AddChild(int Code,AnsiString sName);
void Move(TTreeView *tv,TPositionTree *NewParent);
void Delete();
void DeleteAll();
void DeleteChildren();
void ToTree(TTreeView *tv,TTreeNode *Node);
void ToTreeIts(TTreeView *tv,TTreeNode *Node);
void ToList(TListView *lv);
void SavePositionTo(FILE *f);
bool Save(AnsiString FileName,TProgressBar *ind);
void SaveToFile(FILE *f,TProgressBar *ind);
AnsiString OP();
bool Action(WalkAction ActionIndex,void *Data);
TPositionTree *TreeWalk(WalkAction ActionIndex,void *Data);
TPositionTree *LoadPositionFrom(FILE *f);
void LoadFromFile(FILE *f,TProgressBar *ind);
//void FromFile(AnsiString FileName);
};
TPositionTree *Load(AnsiString FileName,TProgressBar *ind);
TPositionTree *ImportFromFile(AnsiString FileName);
TPositionTree *ImportFromFileCT(AnsiString FileName,bool Price,TProgressBar *ind);
#endif
#include
#include
#pragma hdrstop
#include "PositionTree.h"
#include "Position.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
TPositionTree::TPositionTree(){
Next=NULL;
Down=NULL;
Prev=NULL;
Data=NULL;
Code=0;
for(int i=0;i OutPres[i]=AnsiString();
IsGroup=false;
Depth=0;
}
TPositionTree::~TPositionTree(){}
void TPositionTree::Delete(){
if(Next)
Next->Prev=Prev;
if(Prev){
if(Prev->Next==this)
Prev->Next=Next;
else
Prev->Down=Next;
}
if(Down)
Down->DeleteAll();
if(IsGroup)
((TTreeNode *)Data)->Delete();
delete this;
}
void TPositionTree::DeleteAll(){
if(Down)
Down->DeleteAll();
if(Next)
Next->DeleteAll();
delete this;
}
void TPositionTree::DeleteChildren(){
Down->DeleteAll();
}
void TPositionTree::AddChild(TPositionTree *Node){
if(Down!=NULL){
if(Down->OutPres[0].AnsiCompare(Node->OutPres[0]) Down->Add(Node);
return;
}else Down->Prev=Node;
}
Node->Next=Down;
Down=Node;
Down->Depth=Depth+1;
Down->Prev=this;
}
void TPositionTree::Add(TPositionTree *Node){
if(Next!=NULL){
if(Next->OutPres[0].AnsiCompare(Node->OutPres[0]) Next->Add(Node);
return;
}else Next->Prev=Node;
}
Node->Next=Next;
Next=Node;
Next->Depth=Depth;
Next->Prev=this;
}
TPositionTree *TPositionTree::Add(int sCode,AnsiString sName){
TPositionTree *Node=new TPositionTree();
Node->Code=sCode;
Node->OutPres[0]=sName;
Add(Node);
return(Node);
}
TPositionTree *TPositionTree::AddChild(int sCode,AnsiString sName){
TPositionTree *Node=new TPositionTree();
Node->Code=sCode;
Node->OutPres[0]=sName;
AddChild(Node);
return(Node);
}
void TPositionTree::ToTreeIts(TTreeView *tv,TTreeNode *Node){
TTreeNode *tn;
if(Down!=NULL){
if(Down->IsGroup){
tn=tv->Items->AddChild(Node,Down->OutPres[0]);
tn->Data=Down;
Down->Data=tn;
}
Down->ToTreeIts(tv,tn);
}
if(Next!=NULL){
if(Next->IsGroup){
tn=tv->Items->Add(Node,Next->OutPres[0]);
tn->Data=Next;
Next->Data=tn;
}
Next->ToTreeIts(tv,tn);
}
}
void TPositionTree::ToTree(TTreeView *tv,TTreeNode *Node){
if(IsGroup){
if(Node)
Node=tv->Items->AddChild(Node,OutPres[0]);
else
Node=tv->Items->Add(Node,OutPres[0]);
Node->Data=this;
Data=Node;
if(Down!=NULL){
if(Down->IsGroup){
Node=tv->Items->AddChild(Node,Down->OutPres[0]);
Node->Data=Down;
Down->Data=Node;
}
Down->ToTreeIts(tv,Node);
}
}
}
void TPositionTree::ToList(TListView *lv){
TListItem *li;
if(!lv->Items->Count){
li=lv->Items->Add();
li->Caption=AnsiString(">> . li->Data=Prev;
li->ImageIndex=IsGroup;
li->SubItems->Add("-");
}
li=lv->Items->Add();
li->Caption=IntToStr(Code);
li->Data=this;
li->ImageIndex=IsGroup;
// li->ImageIndex=IsGroup;
// li->SubItems->Add(IntToStr(Code));
for(int i=0;i li->SubItems->Add(OutPres[i]);
}
if(Next!=NULL)
Next->ToList(lv);
}
void TPositionTree::Move(TTreeView *tv,TPositionTree *NewParent){
if(this==NewParent)
return;
TPositionTree *Parent;
TTreeNode *tn;
if(IsGroup&&tv){
tn=((TTreeNode *)Data);
tn->Delete();
}
Parent=Prev;
Data=NULL;
if(Next!=NULL)
Next->Prev=Parent;
if(Parent->Next==this)
Parent->Next=Next;
else
if(Parent->Down==this)
Parent->Down=Next;
NewParent->AddChild(this);
if(IsGroup&&tv){
tn=(TTreeNode *)(NewParent->Data);
ToTree(tv,tn);
}
}
void TPositionTree::SaveToFile(FILE *f,TProgressBar *ind){
if(ind) ind->Position=ind->Position+1;
if(Down){
Down->SavePositionTo(f);
Down->SaveToFile(f,ind);
}else{
fputs("!enddown!",f);
fputs("\n",f);
}
if(Next){
Next->SavePositionTo(f);
Next->SaveToFile(f,ind);
}else{
fputs("!endnext!",f);
fputs("\n",f);
}
}
void TPositionTree::SavePositionTo(FILE *f){
TStringList *SL=new TStringList();
for(int i=0;i SL->Add(OutPres[i]);
}
SL->Add(Code);
SL->Add(int(IsGroup));
SL->Add(Depth);
fputs(SL->CommaText.c_str(),f);
delete SL;
fputs("\n",f);
IP.SaveTo(f);
}
bool TPositionTree::Save(AnsiString FileName,TProgressBar *ind){
FILE *f;
f=fopen(FileName.c_str(),"w");
if(!f)
return(false);
SaveToFile(f,ind);
fclose(f);
ind->Position=0;
return(true);
}
TPositionTree *TPositionTree::LoadPositionFrom(FILE *f){
char str[600];
fgets(str,600,f);
if(AnsiString(str).Trim().AnsiCompare("!endnext!")==0
||AnsiString(str).Trim().AnsiCompare("!enddown!")==0)
return(NULL);
TPositionTree *Node=new TPositionTree();
TStringList *SL=new TStringList();
SL->CommaText=AnsiString(str);
for(int i=0;i Node->OutPres[i]=SL->Strings[i];
Node->Code=SL->Strings[FlowNum].ToInt();
Node->IsGroup=SL->Strings[FlowNum+1].ToInt();
Node->Depth=SL->Strings[FlowNum+2].ToInt();
delete SL;
/* Node->OutPres[0]=AnsiString(str).Trim();
fgets(str,600,f);
Node->Code=AnsiString(str).Trim().ToInt();
fgets(str,600,f);
Node->IsGroup=AnsiString(str).Trim().ToInt();
fgets(str,600,f);
Node->Depth=AnsiString(str).Trim().ToInt(); */
Node->IP.LoadFrom(f);
return(Node);
}
void TPositionTree::LoadFromFile(FILE *f,TProgressBar *ind){
if(ind) ind->Position=ind->Position+1;
TPositionTree *Result=NULL;
if((Result=LoadPositionFrom(f))!=NULL){
AddChild(Result);
Result->LoadFromFile(f,ind);
}
if((Result=LoadPositionFrom(f))!=NULL){
Add(Result);
Result->LoadFromFile(f,ind);
}
}
TPositionTree *Load(AnsiString FileName,TProgressBar *ind){
FILE *f;
f=fopen(FileName.c_str(),"r");
if(!f)
return(NULL);
TPositionTree *Root=new TPositionTree();
Root->OutPres[0]=ChangeFileExt(ExtractFileName(FileName),AnsiString());
Root->IsGroup=true;
Root->Depth=0;
Root->LoadFromFile(f,ind);
fclose(f);
ind->Position=0;
return(Root);
}
TPositionTree *ImportFromFile(AnsiString FileName){
FILE *f;
f=fopen(FileName.c_str(),"r");
if(f==NULL)
return(NULL);
TPositionTree *Drive=new TPositionTree();
TPositionTree *Root;
Drive->Code=0;
Drive->IsGroup=true;
Drive->Depth=0;
Drive->OutPres[0]=ChangeFileExt(ExtractFileName(FileName),AnsiString());
Root=Drive;
char str[100];
AnsiString S;
bool Group; int i=0;
while(fgets(str,100,f)!=NULL){
S=AnsiString(str).Trim();
Group=true-IsQuantity(S);
if(Drive->Depth==0){
Drive=Drive->AddChild(i,S);
i++;
Drive->IsGroup=Group;
continue;
}
if(Group){
Drive=Drive->Add(i,S);
i++;
Drive->IsGroup=Group;
}else
Drive->AddChild(0,S)->IsGroup=Group;
}
fclose(f);
return(Root);
}
TPositionTree *ImportFromFileCT(AnsiString FileName,bool Price,TProgressBar *ind){
if(!FileExists(FileName))
return(NULL);
if(!FileExists(ChangeFileExt(FileName,".hdr")))
return(NULL);
TPositionTree *Drive=new TPositionTree();
TPositionTree *Root;
TPositionTree *New;
Drive->Code=0;
Drive->IsGroup=true;
Drive->Depth=0;
Root=Drive;
int Numerator=0;
TStringList *Y=new TStringList();
TStringList *X=new TStringList();
//Âûÿñíèòü íîìåð ïîòîêà ñ property
int PropertyFlowNum=-1;
Y->LoadFromFile(ChangeFileExt(FileName,".hdr"));
for(int i=1;iCount/2;i++){
X->CommaText=Y->Strings[2*i];
if(X->Strings[0].ToInt()){
PropertyFlowNum=i-1;
break;
}
}
Y->Clear();
X->Clear();
Drive->OutPres[0]=ChangeFileExt(ExtractFileName(FileName),AnsiString());
Y->LoadFromFile(FileName);
bool IsGroup;
for(int i=0;iCount;i++){
X->CommaText=Y->Strings[i];
Numerator++;
IsGroup=false;
if(Price&&PropertyFlowNum!=-1){
if(X->Count>PropertyFlowNum){
if(!IsQuantity(X->Strings[PropertyFlowNum]))
IsGroup=true;
}else
IsGroup=true;
}else{
for(int fl=0;flCount;fl++)
if(!IsQuantity(X->Strings[PropertyFlowNum])){
IsGroup=true;
break;
}
}
if(IsGroup)
New=(Drive=Root->AddChild(!Price*Numerator,X->Strings[0]));
else
New=Drive->AddChild(!Price*Numerator,X->Strings[0]);
New->IsGroup=IsGroup;
for(int j=0;jCount&&j New->OutPres[j]=X->Strings[j];
New->IP.Init(X->Strings[j]);
}
if(ind) ind->Position=Numerator;
}
delete X,Y;
ind->Position=0;
return(Root);
}
bool TPositionTree::Action(WalkAction ActionIndex,void *Data){
switch(ActionIndex){
case aInit:{IP.Clear();
for(int i=0;i IP.Init(OutPres[i]);
return(false);
}
case aToList:{
if(!IsGroup)
((TList *)Data)->Add(this);
return(false);
}
}
return(false);
}
TPositionTree *TPositionTree::TreeWalk(WalkAction ActionIndex,void *Data){
if(Depth==0)
return(Down->TreeWalk(ActionIndex,Data));
if(Action(ActionIndex,Data))
return(this);
TPositionTree *Result;
if(Down)
if((Result=Down->TreeWalk(ActionIndex,Data))!=NULL)
return(Result);
if(Next)
if((Result=Next->TreeWalk(ActionIndex,Data))!=NULL)
return(Result);
return(NULL);
}
AnsiString TPositionTree::OP(){
AnsiString Returned=AnsiString();
for(int i=0;i Returned=Returned+OutPres[i];
}
return(Returned);
}
//---------------------------------------------------------------------------
#ifndef NodeH
#define NodeH
//---------------------------------------------------------------------------
#endif
class Node
{public:
Node *Rgt;
Node *Lft;
char Letter;
long int Statistics;
Node();
~Node();
Node *JumpRight(char FindLet);
Node *RightPaste(char NewLet);
Node *LeftPaste(char NewLet);
Node *JumpLeft(char FindLet);
Node *AddWord(AnsiString Word);
Node *AddWordToEmptyTree(AnsiString Word);
void GetWords(TStrings *List,AnsiString Word=AnsiString());
};
#include
#pragma hdrstop
#include "Node.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//-------------------------------
//Êîíñòðóêòîð
Node::Node()
{
Rgt=NULL;
Lft=NULL;
Letter='@';
Statistics=0;
}
//------------------------------------
Node::~Node()
{if (Rgt!=NULL) Rgt->~Node();
if (Lft!=NULL) Lft->~Node();
}
//-------------------------------------
//Ñîçäàòü óçåë ñïðàâà è âåðíóòü íà íåãî ññûëêó
Node *Node::RightPaste(char NewLet)
{Node *N=new Node;
N->Letter=NewLet;
N->Rgt=this->Rgt;
this->Rgt=N;
return(N);
}
//-------------------------------------
//Ñîçäàòü óçåë ñëåâà è âåðíóòü íà íåãî ññûëêó
Node *Node::LeftPaste(char NewLet)
{Node *N=new Node;
N->Letter=NewLet;
N->Rgt=this->Lft;
this->Lft=N;
return(N);
}
//-------------------------------------
//Äâèãàÿñü âïðàâî íàéòè áóêâó è âåðíóòü íà íå¸ ññûëêó
Node *Node::JumpRight(char FindLet)
{Node *N;
N=this;
while(N->Rgt!=NULL)
{if(N->Rgt->LetterRgt;
else if(N->Rgt->Letter>FindLet)return(N->RightPaste(FindLet));//ñîçäàòü áóêâó è
//âåðíóòü íà íå¸ ññûëêó
else return(N->Rgt);};
//ñîçäàòü áóêâó è âåðíóòü íà íå¸ ññûëêó
return(N->RightPaste(FindLet));
}
//-------------------------------------
//Äâèãàÿñü âëåâî íàéòè áóêâó è âåðíóòü íà íå¸ ññûëêó
Node *Node::JumpLeft(char FindLet)
{
if (this->Lft==NULL) return(this->LeftPaste(FindLet));
if (this->Lft->Letter>FindLet) return(this->LeftPaste(FindLet));
else return(this->Lft);
}
//----------------
//Çàïîëíÿåì ïóñòîå ïîääåðåâî
Node *Node::AddWordToEmptyTree(AnsiString Word)
{char CurrentLet;
Node *N;
N=this;
while(!Word.IsEmpty()){CurrentLet=*Word.SubString(1,1).c_str();
Word=Word.SubString(2,Word.Length());
N=N->JumpLeft(CurrentLet); };
N->Statistics++;
return(N);
}
//----------------
//Äîáàâèòü ñëîâî â äåðåâî
Node *Node::AddWord(AnsiString Word)
{char CurrentLet;
Node *Drive;
if (this->Lft==NULL){ return(AddWordToEmptyTree(Word));};
Drive=this;
while(!Word.IsEmpty()){
do {CurrentLet=*Word.SubString(1,1).c_str();
Word=Word.SubString(2,Word.Length());
Drive=Drive->JumpLeft(CurrentLet);}
while(Drive->Letter==CurrentLet&&!Word.IsEmpty());
if (Drive->Letter!=CurrentLet) Drive=Drive->JumpRight(CurrentLet);
}
Drive->Statistics++;
return(Drive);
}
//---------------------------------------
void Node::GetWords(TStrings *List,AnsiString Word)
{Node *N;
N=this;
if (N->Statistics>0) List->Add(Word+AnsiString(N->Letter));
if (N->Lft!=NULL) N->Lft->GetWords(List,Word+AnsiString(N->Letter));
if (N->Rgt!=NULL) N->Rgt->GetWords(List,Word);
}
//---------------------------------------------------------------------------
#ifndef CompareH
#define CompareH
//---------------------------------------------------------------------------
#include
#include
#include
#include
#include
#include
#include
#include "PositionTree.h"
#include
//---------------------------------------------------------------------------
const int MUPNum=3;
const int MaxID=5;
class TfCompare : public TForm
{
published: // IDE-managed Components
TPanel *Panel1;
TPanel *Panel2;
TPanel *Panel3;
TPanel *Panel4;
TStringGrid *sg;
TButton *Button2;
TOpenDialog *od;
TButton *Button3;
TButton *Button4;
TProgressBar *ProgressBar1;
TEdit *Edit1;
TButton *Button1;
void fastcall FormResize(TObject *Sender);
void fastcall Button1Click(TObject *Sender);
void fastcall Button2Click(TObject *Sender);
void fastcall Button3Click(TObject *Sender);
void fastcall FormCreate(TObject *Sender);
void fastcall FormDestroy(TObject *Sender);
void fastcall Button4Click(TObject *Sender);
void fastcall sgDblClick(TObject *Sender);
private: // User declarations
public: // User declarations
TPositionTree *Base,*Doc;
int CheckSum(AnsiString E1,AnsiString E2,int MaxPayLet);
int String1Compare(AnsiString Str1,AnsiString Str2);
int IsWordInString(AnsiString Word,AnsiString Str,int MaxPayLet);
bool IsQuantity(AnsiString Word);
void ToLists();
TList *BaseL,*DocL;
void nFind(int Index);
AnsiString BaseF,DocF;
bool Compare();
bool GetInfo();
int B[FlowNum][FlowNum];
int D[FlowNum][FlowNum];
int Ids[3][FlowNum];
int United[FlowNum][FlowNum][MaxID];
int Unind[FlowNum][FlowNum];
int FromBaseToDoc[FlowNum][2];
AnsiString MUs[3][FlowNum];
AnsiString Prefix[MUPNum][3];
AnsiString FMU[FlowNum][2*(MUPNum+1)][2];
int PositionsCompare(TPositions Fst,TPositions Snd,int &Numbers);
int StringCompare(int f1,int f2,TPositions Fst,TPositions Snd);
int NumberCompare(int f1,int f2,TPositions Fst,TPositions Snd);
int AnalizeUnitWithMU(AnsiString Unit,int MUIndex,int&Multiplier);
int AnalizePosWithMU(TPositions Fst,int Flow,int MUIndex,int &PosIndex,int &Multiplier);
fastcall TfCompare(TComponent* Owner);
};
int FileSize(AnsiString FileName);
//---------------------------------------------------------------------------
extern PACKAGE TfCompare *fCompare;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "Compare.h"
#include "PositionTree.h"
#include "Position.h"
#include "math.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
const int N=20;
const int X=50;
TfCompare *fCompare;
//---------------------------------------------------------------------------
fastcall TfCompare::TfCompare(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void fastcall TfCompare::FormResize(TObject *Sender)
{
sg->DefaultColWidth=(sg->ClientWidth-2)/2;
}
//---------------------------------------------------------------------------
void fastcall TfCompare::Button1Click(TObject *Sender)
{
if(od->Execute()){
ProgressBar1->Max=FileSize(od->FileName);
if(Base)
delete Base;
Base=Load(od->FileName,ProgressBar1);
}
BaseF=od->FileName;
}
//---------------------------------------------------------------------------
void fastcall TfCompare::Button2Click(TObject *Sender)
{
if(od->Execute()){
ProgressBar1->Max=FileSize(od->FileName);
if(Doc)
delete Doc;
Doc=Load(od->FileName,ProgressBar1);
}
DocF=od->FileName;
}
//---------------------------------------------------------------------------
int TfCompare::CheckSum(AnsiString E1,AnsiString E2,int MaxPayLet)
{
int M1[N][N],M2[N][N],Mc2[N][N],Mc1[N][N];
for(int j=0;j for(int i=0;i {M1[j][i]=0;M2[j][i]=0;
Mc1[j][i]=0;Mc2[j][i]=0;}
int d1=E1.Length();
int d2=E2.Length();
int da;
int MinIm=min(min(2,max(d1-1,1)),max(d2-1,1));
int MaxMov=(min(d1,d2)*X)/100;
int MinSumIm=MaxMov;
int MinPay=MaxPayLet/(MaxMov+1);
int Oc[N];
for(int i=MaxMov;i>=0;i--) Oc[i]=MinPay*(MaxMov+1-i);
Oc[0]=MaxPayLet;
AnsiString abc=AnsiString();
for(int i=1;i if(E2.Pos(E1[i])!=0&&abc.Pos(E1[i])==0)
abc+=E1[i];
da=abc.Length();
if(daint A[N];
for (int i=1;i M1[i-1][abc.Pos(E1[i])]=1;
for (int i=1;i M2[i-1][abc.Pos(E2[i])]=1;
for(int sd=-MaxMov;sd for(int j=1;j for(int i=max(0,sd);i if (M1[i][j]!=0&&M2[i-sd][j]!=0)
{ if(sd>=0) Mc1 [sd][i]++;
if(sd }
}
int Mac[N];int Sz1,Sz2;
for(int i=0;i {Mac[i]=0;Sz1=0;Sz2=0;
for(int j=0;j {if(Mc1[i][j]!=0) Sz1++;
else {Mac[i]+=(Sz1*(Sz1>=MinIm));Sz1=0;}
if(Mc2[i][j]!=0) Sz2++;
else {Mac[i]+=(Sz2*(Sz2>=MinIm));Sz2=0;}
}
}
int Res=0;
for(int i=0;iif(ResRes=0;
for(int i=0;ireturn(Res);
}
bool TfCompare::IsQuantity(AnsiString Word)
{AnsiString Numbers=AnsiString("0527413689");
for(int i=1;i if(Numbers.Pos(Word[i])!=0) return(true);
return(false);
}
int TfCompare::IsWordInString(AnsiString Word,AnsiString Str,int MaxPayLet)
{ int Sum=0;
int SpaceInd=0;
int BestSum=0;
AnsiString Pie;
while(!Str.IsEmpty()){
Str.TrimLeft();
SpaceInd=Str.Pos(' ');
if(SpaceInd!=0){
Pie=Str.SubString(1,Str.Pos(' '));
Str.Delete(1,SpaceInd);
}else{
Pie=Str.Trim();
Str=AnsiString();
}
if(Pie.Trim().IsEmpty()) continue;
Sum=CheckSum(Word,Pie,MaxPayLet);
if(Sum>BestSum) BestSum=Sum;
}
return(BestSum);
}
int TfCompare::String1Compare(AnsiString Str1,AnsiString Str2)
{ AnsiString Pie;
int SpaceInd=0;
int Sum=0;
Str1.Trim();
Str2.Trim();
int Len1=Str1.Length();
int Len2=Str2.Length();
int Base=min(Len1,Len2);
int MaxPayLet=1000/Base;
while(!Str1.IsEmpty()){
Str1.TrimLeft();
SpaceInd=Str1.Pos(' ');
if(SpaceInd!=0){
Pie=Str1.SubString(1,Str1.Pos(' '));
Str1.Delete(1,SpaceInd);
}else{
Pie=Str1.Trim();
Str1=AnsiString();
}
if(Pie.Trim().IsEmpty()) continue;
Sum=Sum+IsWordInString(Pie,Str2,MaxPayLet);
}
return(Sum);
}
int FileSize(AnsiString FileName){
if(!FileExists(ChangeFileExt(FileName,".hdr")))
return(0);
TStringList * Y=new TStringList();
Y->LoadFromFile(ChangeFileExt(FileName,".hdr"));
Y->CommaText=Y->Strings[0];
int R=Y->Strings[1].ToInt();
delete Y;
return(R);
}
void TfCompare::ToLists(){
ProgressBar1->Max=FileSize(DocF);
if(!Base||!Doc)
return;
BaseL->Clear();
DocL->Clear();
Base->TreeWalk(aToList,BaseL);
Doc->TreeWalk(aToList,DocL);
for(int i=0;iCount;i++){
ProgressBar1->Position++;
sg->Cells[0][sg->RowCount-1]=((TPositionTree *)DocL->Items[i])->OP();
sg->RowCount++;
}
ProgressBar1->Position=0;
}
void fastcall TfCompare::Button3Click(TObject *Sender)
{
ToLists();
}
//---------------------------------------------------------------------------
void fastcall TfCompare::FormCreate(TObject *Sender)
{
BaseL =new TList();
DocL = new TList();
}
//---------------------------------------------------------------------------
void fastcall TfCompare::FormDestroy(TObject *Sender)
{
delete DocL,BaseL,Doc,Base;
}
//---------------------------------------------------------------------------
bool TfCompare::GetInfo(){
for(int i=0;i for(int j=0;j B[i][j]=-1;
D[i][j]=-1;
Unind[i][j]=-1;
FromBaseToDoc[i][0]=-1;
FromBaseToDoc[i][1]=-1;
for(int k=0;k United[i][j][k]=-1;
if(i Ids[i][j]=-1;
MUs[i][j]=AnsiString();
}
}
if(!FileExists(ChangeFileExt(BaseF,".hdr")))
return(false);
if(!FileExists(ChangeFileExt(DocF,".hdr")))
return(false);
if(!FileExists("InternalSigns.lst"))
return(false);
if(!FileExists("MeterUnits.lst"))
return(false);
TStringList *X=new TStringList();
TStringList *Y=new TStringList();
//Íàñòðîéêè
Y->Clear();
Y->LoadFromFile("MeterUnits.lst");
for(int j=1;jCount&&j X->CommaText=Y->Strings[j];
for(int i=0;iCount;i++)
MUs[i][j-1]=X->Strings[i];
X->Clear();
}
Y->Clear();
Y->LoadFromFile("InternalSigns.lst");
for(int j=1;jCount&&j X->CommaText=Y->Strings[j];
Ids[0][j-1]=X->Strings[0].ToInt();
if(X->Strings[2].AnsiCompare("DIGIT")==0){
Ids[1][j-1]=1;
for(int i=0;i if(!MUs[0][i].IsEmpty())
if(MUs[0][i].ToInt()==X->Values[X->Names[3]].ToInt())
Ids[2][j-1]=i;
}
else
Ids[1][j-1]=0;
X->Clear();
}
//ôàéëû
Y->Clear();
Y->LoadFromFile(ChangeFileExt(BaseF,".hdr"));
for(int i=1;iCount/2;i++){
X->CommaText=Y->Strings[2*i];
if(!(X->Strings[0].ToInt()))
for(int j=1;jCount&&j B[i-1][j-1]=X->Strings[j].ToInt();
for(int k=0;k if(B[i-1][j-1]==Ids[0][k]){
B[i-1][j-1]=k;
break;
}
}
}
}
Y->Clear();
Y->LoadFromFile(ChangeFileExt(DocF,".hdr"));
for(int i=1;iCount/2;i++){
X->CommaText=Y->Strings[2*i];
if(!(X->Strings[0].ToInt()))
for(int j=1;jCount&&j D[i-1][j-1]=X->Strings[j].ToInt();
for(int k=0;k if(D[i-1][j-1]==Ids[0][k]){
D[i-1][j-1]=k;
break;
}
}
}
}
delete X,Y;
//Åäèíèöû èçìåðåíèÿ
Prefix[0][0]="";Prefix[0][1]="";Prefix[0][2]="0";
Prefix[1][0]="êèëî";Prefix[1][1]="ê";Prefix[1][2]="-3";
Prefix[2][0]="ìèëëè";Prefix[2][1]="ì";Prefix[2][2]="3";
for(int f=0;f if(MUs[1][f].IsEmpty())
continue;
FMU[f][0][0]=MUs[1][f];
FMU[f][0][1]="0";
if(!MUs[2][f].IsEmpty())
FMU[f][1][0]=MUs[2][f];
else
FMU[f][1][0]=MUs[1][f].SubString(1,1);
FMU[f][1][1]="0";
for(int mu=1;mu for(int a=0;a FMU[f][2*mu+a][0]=Prefix[mu][a]+FMU[f][a][0];
FMU[f][2*mu+a][1]=Prefix[mu][2];
}
}
for(int f1=0;f1 for(int f2=0;f2 TStringList* BMU= new TStringList();
TStringList* DMU= new TStringList();
//-----------
int IsBStr=0;
int IsDStr=0;
//-----------
for(int j=0;j if(B[f1][j]!=-1){
if(Ids[1][B[f1][j]]==1)
BMU->Add(Ids[2][B[f1][j]]);
if(Ids[1][B[f1][j]]==0)
IsBStr=1;
}
if(D[f2][j]!=-1){
if(Ids[1][D[f2][j]]==1)
DMU->Add(Ids[2][D[f2][j]]);
if(Ids[1][D[f1][j]]==0)
IsDStr=1;
}
}
int k=0;
while(kCount){
if(BMU->IndexOf(DMU->Strings[k])==-1){
DMU->Delete(k);
k--;
}
k++;
}
Unind[f1][f2]=DMU->Count;
for(int j=0;j United[f1][f2][j]=DMU->Strings[j].ToInt();
}
//---------------------------------
if(DMU->Count)
FromBaseToDoc[f1][1]=f2;
if(IsBStr*IsDStr)
FromBaseToDoc[f1][0]=f2;
//---------------------------------
delete DMU,BMU;
}
return(true);
}
//--------------------------------------------------------------------
int TfCompare::StringCompare(int f1,int f2,TPositions Fst,TPositions Snd){
AnsiString ABC;
for(int i=1;i if(Snd.ABC[f2].Pos(Fst.ABC[f1][i])&&!ABC.Pos(Fst.ABC[f1][i]))
ABC+=Fst.ABC[f1][i];
int minLengthABC=min(Fst.ABC[f1].Length(),Snd.ABC[f2].Length());
if(!minLengthABC)
return(0);
int rABC=ABC.Length()*2;
if(rABC return(0);
int minLength=min(Fst.Sentence(f1).Length(),Snd.Sentence(f2).Length());
int MaxLPayMent=(1000/(minLength));
int AccumPayMent=0;
int MaxCurPayMent;
int CurPayMent;
for(int i=0;i MaxCurPayMent=0;
for(int j=0;j CurPayMent=CheckSum(Fst.Words[i][f1],Snd.Words[j][f2],MaxLPayMent);
if(CurPayMent>MaxCurPayMent)
MaxCurPayMent=CurPayMent;
}
AccumPayMent+=MaxCurPayMent;
}
return(AccumPayMent);
}
int TfCompare::AnalizeUnitWithMU(AnsiString Unit,int MUIndex,int&Multiplier){
/* if(Unit.IsEmpty())
if(MUIndex==FlowNum)
return(2);
else
return(0);*/
int CP;
int MP=0;
int MI=0;
int MaxPay=1;
int UnitLength=Unit.Length();
for(int i=1;i if(Unit.AnsiCompare(FMU[MUIndex][i][0])==0)
CP=MaxPay*UnitLength;
else
CP=CheckSum(Unit,FMU[MUIndex][i][0],MaxPay);
if(CP>MP){
MP=CP;
MI=i;
}
if(CP==MaxPay*UnitLength)
break;
}
Multiplier=pow(10,(FMU[MUIndex][MI][1].ToInt()));
return(MP);
}
int TfCompare::AnalizePosWithMU(TPositions Fst,int Flow,int MUindex,int &PosIndex,int &Multiplier){
int MP=0;
int CP;
int CurMultiplier=0;
for(int i=0;i CP=AnalizeUnitWithMU(Fst.StrNumbers[i][Flow],MUindex,CurMultiplier);
if(CP>MP){
Multiplier=CurMultiplier;
MP=CP;
PosIndex=i;
}
}
return(MP);
}
int TfCompare::NumberCompare(int f1,int f2,TPositions Fst,TPositions Snd){
if(!Unind[f1][f2])
return(0);
int AccumPay=0;
int FMpr;
int SMpr;
int FI,SI;
double E1,E2,E;
// bool MatrixOfUse[MaxID][2];
for(int i=0;i FI=-1;SI=-1;
if(AnalizePosWithMU(Fst,f1,United[f1][f2][i],FI,FMpr))
if(AnalizePosWithMU(Snd,f2,United[f1][f2][i],SI,SMpr)){
E1=(Fst.Numbers[FI][f1]*FMpr);
E2=(Snd.Numbers[SI][f2]*SMpr);
E=fabs(E1-E2)/E1;
if (E AccumPay+=1;
}
else
return(-1);
}
}
return(AccumPay);
}
int TfCompare::PositionsCompare(TPositions Fst,TPositions Snd,int &Numbers){
int Accum=0;
int N=0;
for(int f=0;f if(FromBaseToDoc[f][1]!=-1){
N=NumberCompare(f,FromBaseToDoc[f][1],Fst,Snd);
if(N==-1)
return(0);
Numbers+=N;
}
if(FromBaseToDoc[f][0]!=-1)
Accum+=StringCompare(f,FromBaseToDoc[f][0],Fst,Snd);
}
return(Accum);
}
bool TfCompare::Compare(){
if(!GetInfo())
return(false);
nFind(0);
return(true);
}
void TfCompare::nFind(int Index){
ProgressBar1->Max=FileSize(BaseF);
TPositionTree *BaseNode,*BaseDriveNode,*DocNode;
BaseNode=NULL;
int PayMent=-1;
int CurPayMent;
int Num=0;
int AcNumbers;
DocNode=((TPositionTree *)DocL->Items[Index]);
for(int i=0;iCount;i++){
Num=0;
ProgressBar1->Position++;
BaseDriveNode=((TPositionTree *)BaseL->Items[i]);
CurPayMent=PositionsCompare(DocNode->IP,BaseDriveNode->IP,Num);
if(CurPayMentText.ToInt())
continue;
if(Num continue;
if(CurPayMent>PayMent){
PayMent=CurPayMent;
BaseNode=BaseDriveNode;
AcNumbers=Num;
}
}
/* TRect x,y;*/
if(BaseNode!=NULL)
sg->Cells[1][Index]=BaseNode->OP()+AnsiString(" ")+
IntToStr(PayMent)+AnsiString(" ")+IntToStr(AcNumbers);
else
sg->Cells[1][Index]="---------";
/* double delitel=2000/PayMent;
sg->Canvas->Brush->Color=(clBlue-clRed)/delitel+clRed;
y=sg->CellRect(1,Index);
sg->Canvas->FillRect(y);
//sg->Canvas->Lock(); */
ProgressBar1->Position=0;
}
void fastcall TfCompare::Button4Click(TObject *Sender)
{
GetInfo();
}
//---------------------------------------------------------------------------
void fastcall TfCompare::sgDblClick(TObject *Sender)
{
if(!Base||!Doc||sg->RowCount==1)
return;
TGridRect gr;
gr=sg->Selection;
nFind(gr.Top);
//Compare();
}
//---------------------------------------------------------------------------