Разработка программы.
Разработка программного продукта "Хроника моего рода" для операционной среды Windows
Процедура DrawTree: осуществляет процесс визуализации генеалогического дерева. В начале заливается цветом фона прямоугольник размером с рисунок дерева, который рассчитывался ранее. На этом фоне рисуются узлы дерева кружочками (персона женского пола) или квадратиками (персона мужского пола). Для этого проходим по всем элементам массива данных и сравниваем поле записи элемента pArpok. pol… Читать ещё >
Разработка программы. Разработка программного продукта "Хроника моего рода" для операционной среды Windows (реферат, курсовая, диплом, контрольная)
Разработанные алгоритмы, приведенные в техническом проекте, реализовывались модулями программы. Модули создавались в среде Borland Delphi 5 [1]. Взаимодействие модулей программы рассмотрено на рис. 1.4.1.2. Ниже некоторые модули описаны подробнее.
Алгоритм ввода, сохранения и изменения информации, а также выдача информации по конкретному узлу генеалогического дерева реализован модулем info1.
1. Модуль info1 — это модуль информации по конкретным узлам.
Переменные, объявленные в модуле:
- · FUpdating — идентификатор выбора стиля текста;
- · miMinInfoCounter — идентификатор минимума вводимой информации;
- · MotherChanged, FatherChanged, HusChanged, ChiChanged — идентификаторы нажатых кнопок;
- · UrlCommaCounter — идентификатор ввода информации.
Процедуры и функции модуля (кроме процедур обработки нажатий кнопок):
- · procedure ClearAll — очищает все поля формы fmMainInfo;
- · procedure SaveInfo (Id: integer) — сохраняет информацию о персоне в массиве персон;
- · function LoadFromArFoto (id: integer; name: string):string — загружает фото для просмотра, в соответствии с информацией из массива ArFoto;
- · function LoadFromArVideo (id: integer; name: string):string — аналогично для видео;
- · function LoadFromArAudio (id: integer; name: string):string — аналогично для аудио;
- · procedure AddName (var list: TListBox;var KolMedia: integer; Name, path: string;var mas: array of TMedia) — сохраняет информацию в медиа массивы;
- · procedure FindAllMedia — находит все медиа файлы, относящиеся к персоне;
- · procedure httpConnect (Sender: TObject) — производит запуск Интернет-броузера;
- · procedure changepic (path:string) — «подгоняет» фото под размеры окна;
- · procedure ConvertData (data: string; live: integer) — инвертирует данные о дате в нужный формат.
- 2. Модуль Pr1 — модуль визуализации дерева. Также в этом модуле организована работа с мышью и масштабирование дерева.
Переменные, объявленные в модуле:
- — Width1, Height1 — высота и ширина рисунка генеалогического дерева;
- — Kol_u — количество поколений в родословной;
- — sum: array [0.100] of integer — одномерный массив, в котором индекс соответствует номеру поколения, а элемент — это количество людей в этом поколении.
- — u_max, u_min — максимальный и минимальный номер поколения. Той персоне, с которой начали строить родословную присваивается нулевое поколение, следующему поколению на единицу больше. Соответственно меньшие поколения на единицу меньше, то есть они будут с отрицательным знаком, напр., -1, -2.
- — kx, ky — коэффициенты сжатия по оси Х и Y.
- — SomeWife — идентификатор принимает значения true (у персоны один супруг) и false (у персоны есть не один заключенный брак или дети вне брака).
Процедуры и функции модуля (кроме процедур обработки нажатий кнопок):
В алгоритм рисования дерева входят две основные процедуры CreateMas и DrawTree, в них еще несколько подпроцедур.
Процедура CreateMas: сначала устанавливаются идентификаторы key и SomeWife. Второй идентификатор принимает значения true (у персоны один супруг) и false (у персоны есть не один заключенный брак или дети вне брака). В начале работы алгоритма этому идентификатору присваивается значение true. Далее вызывается функция max_z, которая подсчитывает общее количество поколений в родословной. Результат этой функции присваивается переменной Kol_u. Следующая процедура CreateArpok создает двумерный массив из одномерного массива PersonAr. В получившемся массиве элементами одной строки являются люди одного поколения. Сортировка массива осуществляется процедурой SortArpok. Муж и жена в одной строке расположены рядом. Процедура FormXY формирует координаты узлов генеалогического дерева. Размеры рисунка дерева рассчитываются процедурой SizePanel. Для того, чтобы дерево находилось не в одной части экрана, если его размеры меньше размеров экрана монитора, его координаты корректируются таким образом, чтобы оно располагалось посередине. После проведенных действий массив pArpok сформирован должным образом.
Функция max_z: рассчитывает общее количество поколений в родословной. Здесь использован простой алгоритм нахождения максимума и минимума, когда на первом этапе за минимум берется заведомо большое число min1:= 1000, за максимум соответственно — маленькое max1:= -1000. Поиск минимума: первый элемент PersonAr[k]. pok сравнивается с min1. Если он меньше, то он становится min1, далее сравниваются остальные элементы. В итоге значение min1 и есть меньшее поколение. Максимум находится аналогично. Общее количество поколений в родословной max_z есть разность max1 и min1. Переменным u_min присваивается значение меньшего поколения, переменной u_max — значение старшего поколения.
Процедура CreateArpok: создает двумерный массив pArpok из одномерного массива PersonAr таким образом, чтобы в каждой строке массива pArpok находились люди одного поколения. В начале формируется одномерный массив sum: array [0.100] of integer. В нем индексу соответствует номер поколения, а значению элемента массива с этим индексом соответствует количество людей в этом поколении. Далее в цикле по j (номер поколения) сначала для нулевого поколения заполняем нулевую строку массива pArpok. Каждый элемент массива PersonAr[k]. pok сравнивается с номером поколения j (сейчас равен 0). Те элементы, которые соответствуют этому поколению, заносятся на j-ую строку массива pArpok. Одновременно с этим подсчитывается количество элементов на этой строке, если оно превосходит соответствующий этому поколению элемент массива sum, то переходим к заполнению следующей строке-поколению.
procedure TfmTree. CreateArpok ();
var s, i, j, k: integer;
begin
for j:=u_min to u_max do
begin
s:=0;
for i:=1 to Kol-1 do
if PersonAr[i]. pok=j then формирование одномерного.
begin массива sum
s:=s+1;
end;
sum[j-u_min]: =s;
end;
for j:=0 to Kol_U do
begin
s:=0;
for k:=1 to Kol do
begin заполнение.
if PersonAr[k]. pok=j+u_min then массива pArpok
begin
if (PersonAr[k]. Fam'') or (PersonAr[k]. Id0) then
begin
pArpok[j, s]: = PersonAr[k];
s:=s+1;
end;
if s=sum[j] then break;
end;
end;
end;
Процедура SortArpok: сортирует массив pArpok так, чтобы супруги в одном поколении размещались рядом. В этой процедуре так же используется массив sum, упоминавшийся в предыдущей процедуре. Проходимся по строкам массива pArpok. Сначала первый элемент запоминаем, как P, следующий, как P1. Если супруг P-го элемента есть P1, то ставим их вместе. (Перемещение элемента осуществляет процедура Change (lvl, p1, p2: integer)). Если нет, то P1 присваиваем значение следующего элемента и сравниваем снова. Достигнут конец строки, тогда P присваивается значение второго элемента, если замены не произошло и третьего элемента, если произошла замена, и продолжается сравнение.
Procedure SortArpok();
var j, i, m, a: integer;
P, P1: TPerson;
begin
for j:=0 to Kol_u do
begin
m:=0;
while m
begin
P:=pArpok[j, m];
a:=0;
for i:=m+1 to sum[j]-1 do
begin
P1:=pArpok[j, i];
if P1. Husbend=p.Id then
begin
Change (j, m+1,i);
a:=a+1;
break;
end;
end;
if a>0 then m:=m+2
else m:=m+1;
end;
end;
end;
Procedure Change(lvl, p1, p2: integer);
var buf: TPerson;
begin
buf:=pArpok[lvl, p1];
pArpok[lvl, p1]: =pArpok[lvl, p2];
pArpok[lvl, p2]: =buf;
end;
На вход процедуры Change(lvl, p1, p2: integer) подается номер уровня lvl, расположение элемента на этой строке p1 и расположение второго элемента p2, который будет ставиться рядом.
Процедура FormXY: формирует координаты узлов генеалогического дерева. Присваиваются каждому человеку координаты x и y. (Именно на месте этих координат будет отображен данный человек.) Заметим, что ближайшие люди находятся на расстоянии 200 пикселей по оси X и 90 пикселей по оси Y. В этой же процедуре происходит выравнивание общего вида дерева.
Процедура DrawTree: осуществляет процесс визуализации генеалогического дерева. В начале заливается цветом фона прямоугольник размером с рисунок дерева, который рассчитывался ранее. На этом фоне рисуются узлы дерева кружочками (персона женского пола) или квадратиками (персона мужского пола). Для этого проходим по всем элементам массива данных и сравниваем поле записи элемента pArpok[j, i]. pol со значением «жен» и «муж». Чтобы нарисовать линию, связывающую двух супругов, выполняются два цикла. Проходимся по строкам массива pArpok, запоминаем идентификатор супруга рассматриваемой персоны. Затем ищем супруга в данной строке и запоминаем индекс этого элемента. Теперь, узнав индексы требуемых элементов, рисуем соединяющую их линию при помощи процедуры LinkOneLayer(xn, y, xk: integer). Так проверяем каждый элемент. Если найденный супруг персоны уже проверялся, то проверяем следующие элементы.
for j:=0 to Kol_U do
begin
for i:=0 to sum[j]-1 do
begin
d:=pArpok[j, i]. Husbend;
if PersonAr[d]. pok pArpok[j, i]. pok then goto l;
if ((d=0) or (d= pArpok[j, i-1]. Id)) then goto l;
for k:=0 to sum[j]-1 do
if (pArpok[j, k]. Id = d) then d1:= k;
LinkOneLayer (pArpok[j, i]. xp, pArpok[j, i]. yp, pArpok[j, d1].xp);
l: d:= -1;
end;
end;
Рисование линии-связи «родители-ребенок» осуществляется похожим образом, что и линия, связывающая супругов. Только здесь следует учитывать, что детей может быть несколько и ребенок имеет указатель на следующего ребенка. Рисование происходит с помощью процедуры LinkTwoLayer(xn, y, xk, xsb, yk: integer) .
for j:=1 to Kol_U do
begin
for i:=0 to sum[j]-1 do
begin
d:=pArpok[j, i]. Husbend;
if ((d=0) or (d= pArpok[j, i-1]. Id)) then goto m1;
for k:=0 to sum[j]-1 do
if (pArpok[j, k]. Id = d) then d1:= k;
d2:= pArpok[j, i]. Children;
if d2=0 then goto m1;
if d2 PersonAr[d]. Children then goto m1;
for k:=0 to sum[j-1]-1 do
if (pArpok[j-1,k]. Id = d2) then d3:= k;
LinkTwoLayer (pArpok[j, i]. xp, pArpok[j, i]. yp, pArpok[j, d1].xp, pArpok[j-1,d3]. xp, pArpok[j-1,d3]. yp);
d4:= pArpok[j-1,d3]. Sist_Broth;
while d40 do
begin
for k:=0 to sum[j-1]-1 do
if (pArpok[j-1,k]. Id = d4) then d3:= k;
LinkTwoLayer (pArpok[j, i]. xp, pArpok[j, i]. yp, pArpok[j, d1].xp, pArpok[j-1,d3]. xp, pArpok[j-1,d3]. yp);
d4:= pArpok[j-1,d3]. Sist_Broth;
end;
m1: d:= -1;
end;
end;
В этой процедуре необходимо охватить все связи между людьми, например, разное количество браков или внебрачные дети. Для этого есть идентификатор SomeWife, принимает значение false в этом случае. Тогда, когда вызывается процедура LinkOneLayer(xn, y, xk: integer) происходит проверка на это идентификатор. В рассматриваемом случае эта линия будет рисоваться ниже и пунктиром.
Если известен только один родитель ребенка, то это тоже учитывается, при этом используется процедура Link(xn, yn, xk, yk: integer). Если супруги находятся на разных поколениях, то рисование линии, связывающей их, осуществляет процедура WrongLink(xn, yn, xk, yk: integer).
for i:=0 to Kol do
begin
m:= PersonAr[i]. MotherId;
f:= PersonAr[i]. FatherId;
if (((PersonAr[i]. MotherId 0) and (PersonAr[i]. FatherId = 0)) or ((PersonAr[i]. MotherId = 0) and (PersonAr[i]. FatherId 0))) then
begin
if PersonAr[i]. MotherId 0 then Link (PersonAr[m]. xp, PersonAr[m]. yp, PersonAr[i].xp, PersonAr[i].yp)
else Link (PersonAr[f]. xp, PersonAr[f]. yp, PersonAr[i].xp, PersonAr[i].yp);
end;
end;
for i:=0 to Kol do
begin
h:= PersonAr[i]. husbend;
if ((PersonAr[i]. pok PersonAr[h]. pok) and (h0)) then WrongLink (PersonAr[i]. xp, PersonAr[i]. yp, PersonAr[h]. xp, PersonAr[h]. yp);
end;
Процедура Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer): при движении мышки по узлу дерева данная процедура обеспечивает высвечивание подсказки с ФИО персоны этого узла. Сравниваются координаты мышки и узла дерева.
Процедура Image1MouseDown(Sender:TObject;Button:TMouseButton;
Shift:TShiftState; X, Y: Integer): при нажатии мышки на узел дерева появляется форма «Информация о конкретном узле дерева». Сама процедура аналогична Image1MouseMove.
Процедура N16Click: обеспечивает уменьшение размеров дерева до размеров экрана монитора. Рассчитываются коэффициенты сжатия по оси Х и Y, kx и ky.
kx:= fmTree. Width/Image1.Width;
ky:= (fmTree.Height-70)/Image1.Height;
Изменяются координаты всех дерева путем умножения на коэффициенты имееющихся координат.
Процедура N17Click: возвращает реальный размер дерева.
ПроцедурыPointM (x, y: integer;Image1:TImage;l:integer) и PointF (x, y: integer;Image1:TImage; l: integer): рисуют узлы дерева, кружочек — это женщина, квадратик — мужчина.
3. Модуль SelFam — этот модуль реализует алгоритм выделения отдельной ветви дерева, описанный ранее в техническом проекте.
Этот алгоритм основан на рекурсивной процедуре Potomok(Id, pos). В качестве входных параметров в процедуре Potomok(Id, pos) номер Id — тот, чьих потомков ищем, Pos — индекс в массиве Mas — место, куда записывается очередной найденный потомок. Цель процедуры сформировать массив Mas, в котором будут находиться только те, кто является потомком выбранного человека. На первое место массива Mas заносится тот самый выбранный человек. Если у человека нет детей и сестер/братьев, то выходим из алгоритма.
Если есть сестры/братья, то проверяем одни ли у них родители. Родители одни — записываем найденного человека в массив Mas. После этого вызываем рекурсивно процедуру Potomok(Id, pos) уже для найденного человека. Так будет продолжаться, пока у найденных сестер/братьев будут находиться дети или их сестры /братья. Если таковых нет, то в массив заносится ребенок выбранного нами человека и вызывается процедура уже для него. Таким образом, в массиве Mas окажутся все потомки выбранного пользователем человека. Можно рисовать. Но в рисовании есть тоже некоторые особенности, которые выполняет процедура DrawBranch.
function Potomok (id:integer; var pos: integer):boolean;
label l;
begin
if ((mas[pos]. Children=0) and (mas[pos]. Sist_Broth=0)) then
begin
roma:=true;
exit;
end;
while mas[pos]. Sist_Broth0 do
begin
//if (((mas[pos]. Husbend PersonAr[mas[pos]. Sist_Broth].MotherId) and (mas[pos]. Husbend = PersonAr[mas[pos]. Sist_Broth].FatherId)) or ((mas[pos]. Husbend = PersonAr[mas[pos]. Sist_Broth].MotherId) and (mas[pos]. Husbend PersonAr[mas[pos]. Sist_Broth].FatherId)) or (mas[pos]. Husbend=0)) then goto l;
if (((mas[pos]. MotherId PersonAr[mas[pos]. Sist_Broth].MotherId) and (mas[pos]. FatherId = PersonAr[mas[pos]. Sist_Broth].FatherId)) or ((mas[pos]. MotherId = PersonAr[mas[pos]. Sist_Broth].MotherId) and (mas[pos]. FatherId PersonAr[mas[pos]. Sist_Broth].FatherId)) {or (mas[pos]. Husbend=0}) then goto l;
pos:=pos+1;
mas[pos]: =PersonAr[mas[pos-1].Sist_Broth];
Potomok (mas[pos]. id, pos);
end;
l: pos:=pos+1;
mas[pos]: =PersonAr[PersonAr[id].Children];
Potomok (mas[pos]. Id, pos);
end;
Процедура DrawBranch: осуществляет рисование ветви дерева в соответствии с массивом Mas. Процедура выполняется аналогично процедуре DrawTree.
4. Модуль Combine — модуль объединения деревьев. Модуль реализует алгоритм объединения деревьев, описанный в техническом проекте.
Главной процедурой этого модуля является процедура ReadFromFile (fname: string). На начальном этапе дерево, с которым мы работаем, находится в массиве PersonAr. В массив PersonAr1 считываем дерево, с которым будем объединять. Сравниваем два массива на предмет общих людей. Присваиваем флажку Id единичку, если общие люди есть. Затем делаем проверку на этот флажок, если не единица, то показываем форму fmSugest с предупреждением «В деревьях нет общих людей». Затем предлагается выбрать другое для объединения дерево или выйти из задачи объединения.
- 5. Модуль files — это модуль, где описаны функции работы с файлами.
- 6. Модуль prgenealogia_begin — это главный модуль программы.
- 7. Модуль enterfam — это модуль информации по конкретным узлам.
- 8. Модуль gedcom — это модуль чтения информации из GedCom файла.
- 9. Модуль gedcom1 — это модуль записи информации в GedCom файл.
- 10. Модуль people — это модуль выбора родственников. В нем предлагается выбрать нужного человека из предложенного списка, либо добавить нового человека. Выбрать можно супруга, мать, отца и детей. Эти действия реализуются процедурами ShowFather, ShowMother, ShowChildren, ShowHusbend. Процедуры аналогичны друг другу. Ниже приведена одна из этих процедур:
procedure TfmChoice. ShowHusbend;
var i: integer;
begin
if PersonAr[tecid]. pol='жен' then
cmbPol.Text:='муж' else cmbPol. Text:='жен';
for i:=1 to Kol do
if ((PersonAr[i]. Husbend=tecid) and (PersonAr[i]. IdtecId)) then
lbPeople.Items.Add (IntToStr (PersonAr[i]. id)+' '+PersonAr[i]. Fam+' '+PersonAr[i]. Name+' '+PersonAr[i]. PatronName);
for i:=1 to Kol do
if PersonAr[i]. IdtecId then
cmbChoice.Items.Add (IntToStr (PersonAr[i]. id)+' '+PersonAr[i]. Fam+' '+PersonAr[i]. Name+' '+PersonAr[i]. PatronName);
end;
- 11. Модуль warningdel— это модуль предупреждения об удалении.
- 12. Модуль name — это модуль ввода названия медиа объекта.
- 13. Модуль husbend — это модуль вопроса о браке родителей.
- 14. Модуль poisk — это модуль информации по конкретным узлам.
Всю информацию по модулю — см. в первой части работы.
15. Модуль poisk1 — это модуль вывода ответа на вопрос пользователя.
Всю информацию по модулю — см. в первой части работы.
16. Модуль statistic — это модуль статистики по текущей родословной.
Всю информацию по модулю — см. в первой части работы.