summaryrefslogtreecommitdiff
path: root/grampstypen.pas
diff options
context:
space:
mode:
Diffstat (limited to 'grampstypen.pas')
-rw-r--r--grampstypen.pas2050
1 files changed, 2050 insertions, 0 deletions
diff --git a/grampstypen.pas b/grampstypen.pas
new file mode 100644
index 0000000..4505324
--- /dev/null
+++ b/grampstypen.pas
@@ -0,0 +1,2050 @@
+unit grampstypen;
+
+interface
+
+uses classes, matheunit;
+
+type
+ tExtendedArray = array of extended;
+ tIntArray = array of longint;
+ tIntArrayArray = array of tIntArray;
+ tBooleanArray = array of boolean;
+ tPointArray = array of tPoint;
+ tPointArrayArray = array of tPointArray;
+ tEreignisart = (eaDummy,eaGeburt,eaTod,eaHochzeit,eaTaufe,eaBeerdigung,eaSonstiges);
+ t4DPoint = record
+ x,y,z,u: longint;
+ end;
+ tExtPoint = record
+ x,y: extended;
+ end;
+ tSchrittErgebnis = record
+ besserAlsVorher,
+ faktorNeutralisiert: boolean;
+ Platzveraenderung: longint;
+ end;
+ t4DPointArray = array of t4DPoint;
+ tParameterAttribut = object
+ istKoordinate,istUnabhaengig,wirdBenutzt: boolean;
+ procedure setzeKoordinate(ik: boolean);
+ procedure setzeUnabhaengig(iu: boolean);
+ procedure setzeBenutzt(wb: boolean);
+ procedure fromChar(c: char);
+ function toChar: char;
+ end;
+ tParameterAttributArray = array of tParameterAttribut;
+ tGenerikum = class
+ ID: string;
+ index: longint;
+ constructor create;
+ destructor destroy; override;
+ procedure init(g: tGenerikum); dynamic;
+ function istGleich(g: tGenerikum): boolean; dynamic;
+ end;
+ tGenerikumArray = array of tGenerikum;
+ tEreignis = class;
+ tEreignisArray = array of tEreignis;
+ tPerson = class;
+ tPersonArray = array of tPerson;
+ tFamilie = class;
+ tFamilieArray = array of tFamilie;
+ tVerknuepfung = class;
+ tVerknuepfungArray = array of tVerknuepfung;
+ tMMInteraktion = class;
+ tMMInteraktionArray = array of tMMInteraktion;
+ tMFInteraktion = class;
+ tMFInteraktionArray = array of tMFInteraktion;
+ tFFInteraktion = class;
+ tFFInteraktionArray = array of tFFInteraktion;
+
+ tEreignis = class (tGenerikum)
+ Jahr: longint;
+ Art: tEreignisart;
+ function istDummy: boolean;
+ constructor create;
+ destructor destroy; override;
+ procedure init(e: tGenerikum); override;
+ function istGleich(e: tGenerikum): boolean; override;
+ end;
+ tPerson = class (tGenerikum)
+ Anfang,Ende: tEreignis;
+ Ereignisse: array[tEreignisart] of tEreignis;
+ KindIn: tFamilie;
+ ElterIn: tFamilieArray;
+ inputIn,outputIn: tVerknuepfungArray;
+ inMMInteraktion: tMMInteraktionArray;
+ inMFInteraktion: tMFInteraktionArray;
+ Vorname,Nachname: string;
+ p1,p2,p3: longint;
+ constructor create;
+ destructor destroy; override;
+ procedure entferneElterIn(wo: tFamilie);
+ procedure entferneKindIn(wo: tFamilie);
+ procedure fuegeInputInHinzu(wo: tVerknuepfung);
+ procedure entferneInputIn(wo: tVerknuepfung);
+ procedure fuegeOutputInHinzu(wo: tVerknuepfung);
+ procedure entferneOutputIn(wo: tVerknuepfung);
+ procedure fuegeInMMInteraktionHinzu(wo: tMMInteraktion);
+ procedure entferneInMMInteraktion(wo: tMMInteraktion);
+ procedure fuegeInMFInteraktionHinzu(wo: tMFInteraktion);
+ procedure entferneInMFInteraktion(wo: tMFInteraktion);
+ procedure init(p: tGenerikum); override; overload;
+ procedure init(p: tGenerikum; var es: tEreignisArray); overload;
+ procedure init(p: tGenerikum; var es: tEreignisArray; var fs: tFamilieArray); overload;
+ procedure init(p: tGenerikum; var es: tEreignisArray; var fs: tFamilieArray; darfErzeugen: boolean); overload;
+ function anzahlVerbindungen: longint;
+ function istGleich(p: tGenerikum): boolean; override;
+ function elterVonFamilie(eNum: longint): tFamilie;
+ function istElterIn(f: tFamilie): boolean;
+ end;
+ tFamilie = class (tGenerikum)
+ Anfang: tEreignis;
+ verheiratet: boolean;
+ Eltern: array[0..1] of tPerson;
+ Kinder: tPersonArray;
+ inMFInteraktion: tMFInteraktionArray;
+ inFFInteraktion: tFFInteraktionArray;
+ constructor create;
+ destructor destroy; override;
+ procedure entferneElter(wen: tPerson);
+ procedure entferneKind(wen: tPerson);
+ procedure fuegeInMFInteraktionHinzu(wo: tMFInteraktion);
+ procedure entferneInMFInteraktion(wo: tMFInteraktion);
+ procedure fuegeInFFInteraktionHinzu(wo: tFFInteraktion);
+ procedure entferneInFFInteraktion(wo: tFFInteraktion);
+ procedure init(f: tGenerikum); override; overload;
+ procedure init(f: tGenerikum; var Es: tEreignisArray; var Ps: tPersonArray); overload;
+ procedure init(f: tGenerikum; var Es: tEreignisArray; var Ps: tPersonArray; darfErzeugen: boolean); overload;
+ function anzahlVerbindungen: longint; inline;
+ function istGleich(f: tGenerikum): boolean; override;
+ function hatKind(p: tPerson): boolean; inline;
+ function hatElter(p: tPerson): boolean; inline;
+ end;
+ tVerknuepfung = class
+ private
+ _outP: tPerson;
+ procedure wOutP(p: tPerson);
+ public
+ index: longint;
+ Input: array[0..1,'x'..'y'] of Longint;
+ Lambda: Longint;
+ Output: array['x'..'y'] of Longint;
+ property outP: tPerson
+ read _outP
+ write wOutP;
+ destructor destroy; override;
+ function istGleich(v: tVerknuepfung; p2p: tIntArray): boolean;
+ end;
+ tMMInteraktion = class
+ private
+ __Ps: array[0..1] of tPerson;
+ function r_Ps(i: longint): tPerson; inline;
+ procedure w_Ps(i: longint; p: tPerson);
+ public
+ index: longint;
+ Laenge: extended;
+ property _Ps[i: integer]: tPerson
+ read r_Ps
+ write w_Ps;
+ destructor destroy; override;
+ function istGleich(ia: tMMInteraktion): boolean;
+ end;
+ tMFInteraktion = class
+ private
+ __P: tPerson;
+ __F: tFamilie;
+ procedure w_P(p: tPerson);
+ procedure w_F(f: tFamilie);
+ public
+ index: longint;
+ Laenge: extended;
+ property _P: tPerson
+ read __P
+ write w_P;
+ property _F: tFamilie
+ read __F
+ write w_F;
+ destructor destroy; override;
+ function istGleich(ia: tMFInteraktion): boolean;
+ end;
+ tFFInteraktion = class
+ private
+ __Fs: array[0..1] of tFamilie;
+ function r_Fs(i: longint): tFamilie; inline;
+ procedure w_Fs(i: longint; f: tFamilie);
+ public
+ index: longint;
+ property _Fs[i: integer]: tFamilie
+ read r_Fs
+ write w_Fs;
+ destructor destroy; override;
+ function istGleich(ia: tFFInteraktion): boolean;
+ end;
+
+ tZusammenhangskomponente = class
+ public
+ Familien: tFamilieArray;
+ constructor create;
+ destructor destroy; override;
+ function grenztAn(p: tPerson): boolean;
+ procedure verschmelzeMit(zhk: tZusammenhangskomponente);
+ procedure UmfeldEinfuegen(Fs: tFamilieArray; p: tPerson);
+ end;
+
+ tGraph = class
+ private
+ function entferneBlaetter(var f: tIntArray): tIntArray;
+ function Pfadigkeit(Ks: tIntArray; a,b: longint): longint; // 0 -> zu wenig; 1 -> ein Pfad; 2-> zu viel
+ function etwasDoppelt: boolean; overload;
+ function etwasDoppelt(Ks: tIntArray): boolean; overload;
+ function etwasRedundant(Ks1,Ks2: tIntArray): boolean;
+ procedure dumpKantenArray(Ks: tIntArray);
+ public
+ Ecken,Kanten: tPointArray;
+ constructor create;
+ destructor destroy; override;
+ function findeKreise: tIntArrayArray;
+ function findeKreise(f: tIntArray): tIntArrayArray;
+ end;
+
+ tSortObject = class
+ oG: tGenerikum;
+ oMM: tMMInteraktion;
+ oMF: tMFInteraktion;
+ oFF: tFFInteraktion;
+ oV: tVerknuepfung;
+ ID: string;
+ constructor create;
+ procedure assign(g: tGenerikum); overload;
+ procedure assign(i: tMMInteraktion); overload;
+ procedure assign(i: tMFInteraktion); overload;
+ procedure assign(i: tFFInteraktion); overload;
+ procedure assign(v: tVerknuepfung); overload;
+ end;
+ tSortObjectArray = array of tSortObject;
+
+function paramsGleich(p1,p2: longint; p2p: tIntArray): boolean; inline;
+function pEreignisToStr(E: tEreignis): string; inline;
+function pFamilieToStr(F: tFamilie): string; inline;
+function pPersonToStr(P: tPerson): string; inline;
+function tEreignisToStr(E: tEreignis): string; inline;
+function tPersonToStr(P: tPerson): string; inline;
+function tFamilieToStr(F: tFamilie): string; inline;
+function tVerknuepfungToStr(V: tVerknuepfung): string; inline;
+function tMMInteraktionToStr(I: tMMInteraktion): string; inline;
+function tMFInteraktionToStr(I: tMFInteraktion): string; inline;
+function tFFInteraktionToStr(I: tFFInteraktion): string; inline;
+function findeEreignis(var Es: tEreignisArray; eID: string): tEreignis;
+function findeFamilie(var Fs: tFamilieArray; fID: string): tFamilie; overload;
+function findeFamilie(var Fs: tFamilieArray; fID: string; darfErzeugen: boolean): tFamilie; overload;
+function findePerson(var Ps: tPersonArray; pID: string): tPerson; overload;
+function findePerson(var Ps: tPersonArray; pID: string; darfErzeugen: boolean): tPerson; overload;
+function findeMMInteraktion(var MMs: tMMInteraktionArray; var Ps: tPersonArray; ia: string): tMMInteraktion;
+function findeMFInteraktion(var MFs: tMFInteraktionArray; var Ps: tPersonArray; var Fs: tFamilieArray; ia: string): tMFInteraktion;
+function findeFFInteraktion(var FFs: tFFInteraktionArray; var Fs: tFamilieArray; ia: string): tFFInteraktion;
+procedure loescheEreignis(var Es: tEreignisArray; eID: string);
+procedure loescheFamilie(var Fs: tFamilieArray; fID: string);
+procedure loeschePerson(var Ps: tPersonArray; pID: string);
+procedure mergePerson(var Ps: tPersonArray; var P: tPerson);
+procedure mergeFamilie(var Fs: tFamilieArray; var F: tFamilie);
+function importEreignis(s: string; var Es: tEreignisArray): tEreignis;
+function importPerson(s: string; var Ps: tPersonArray; var Es: tEreignisArray; var Fs: tFamilieArray): tPerson;
+function importFamilie(s: string; var Ps: tPersonArray; var Es: tEreignisArray; var Fs: tFamilieArray): tFamilie;
+function strToTVerknuepfung(var Ps: tPersonArray; s: string): tVerknuepfung;
+function importMMInteraktion(var Ps: tPersonArray; s: string): tMMInteraktion;
+function importMFInteraktion(var Ps: tPersonArray; var Fs: tFamilieArray; s: string): tMFInteraktion;
+function importFFInteraktion(var Fs: tFamilieArray; s: string): tFFInteraktion;
+function importFamilieArray(var s: string; var Fs: tFamilieArray): tFamilieArray;
+function importPersonArray(var s: string; var Ps: tPersonArray): tPersonArray;
+procedure strToTIntArray(var s: string; var A: tIntArray);
+function Permutation(n: longint): tIntArray;
+function sortStringFromObject(g: tGenerikum): string; overload;
+function sortStringFromObject(i: tMMInteraktion): string; overload;
+function sortStringFromObject(i: tMFInteraktion): string; overload;
+function sortStringFromObject(i: tFFInteraktion): string; overload;
+function sortStringFromObject(v: tVerknuepfung): string; overload;
+function sortiere(arr: tGenerikumArray): tGenerikumArray; overload; inline;
+function sortiere(arr: tMMInteraktionArray): tMMInteraktionArray; overload; inline;
+function sortiere(arr: tMFInteraktionArray): tMFInteraktionArray; overload; inline;
+function sortiere(arr: tFFInteraktionArray): tFFInteraktionArray; overload; inline;
+function sortiere(arr: tVerknuepfungArray): tVerknuepfungArray; overload; inline;
+function sortiere(arr: tSortObjectArray): tSortObjectArray; overload; inline;
+procedure sortiere(var arr: tSortObjectArray; von,bis: longint; mi,ma: string); overload;
+
+implementation
+
+uses sysutils;
+
+function paramsGleich(p1,p2: longint; p2p: tIntArray): boolean;
+begin
+ if p2=-1 then result:=p1=-1
+ else result:=p2p[p2]=p1;
+end;
+
+function pEreignisToStr(E: tEreignis): string;
+begin
+ if assigned(E) then
+ result:=E.ID
+ else
+ result:='NIL';
+end;
+
+function pFamilieToStr(F: tFamilie): string;
+begin
+ if assigned(F) then
+ result:=F.ID
+ else
+ result:='NIL';
+end;
+
+function pPersonToStr(P: tPerson): string;
+begin
+ if assigned(P) then
+ result:=P.ID
+ else
+ result:='NIL';
+end;
+
+function TEreignisToStr(E: TEreignis): String;
+begin
+ TEreignisToStr:=
+ E.ID+' '+
+ inttostr(E.Jahr)+' '+
+ inttostr(Integer(E.Art));
+end;
+
+function TPersonToStr(P: TPerson): String;
+var
+ ea: TEreignisart;
+ I: Longint;
+begin
+ result:=
+ P.ID+' '+
+ pEreignisToStr(P.Anfang)+' '+
+ pEreignisToStr(P.Ende)+' ';
+ for ea:=low(TEreignisart) to high(TEreignisart) do
+ result:=result+PEreignisToStr(P.Ereignisse[ea])+' ';
+ result:=result+
+ pFamilieToStr(P.KindIn)+' '+
+ inttostr(length(P.ElterIn))+' ';
+ for I:=0 to length(P.ElterIn)-1 do
+ result:=result+
+ pFamilieToStr(P.ElterIn[I])+' ';
+ result:=result+
+ ''''+P.Vorname+''' '+
+ ''''+P.Nachname+''' '+
+ inttostr(P.P1)+' '+
+ inttostr(P.P2)+' '+
+ inttostr(P.P3);
+end;
+
+function TFamilieToStr(F: TFamilie): String;
+var
+ I: Longint;
+begin
+ result:=
+ F.ID+' '+
+ PEreignisToStr(F.Anfang)+' '+
+ inttostr(byte(F.Verheiratet))+' '+
+ pPersonToStr(F.Eltern[0])+' '+
+ pPersonToStr(F.Eltern[1])+' '+
+ inttostr(length(F.Kinder));
+ for I:=0 to length(F.Kinder)-1 do
+ result:=result+' '+
+ pPersonToStr(F.Kinder[I]);
+end;
+
+function TVerknuepfungToStr(V: TVerknuepfung): String;
+begin
+ result:=
+ pPersonToStr(V.outP)+' '+
+ inttostr(V.Input[0,'x'])+' '+
+ inttostr(V.Input[0,'y'])+' '+
+ inttostr(V.Input[1,'x'])+' '+
+ inttostr(V.Input[1,'y'])+' '+
+ inttostr(V.Lambda)+' '+
+ inttostr(V.Output['x'])+' '+
+ inttostr(V.Output['y']);
+end;
+
+function TMMInteraktionToStr(I: TMMInteraktion): String;
+begin
+ result:=
+ pPersonToStr(I._Ps[0])+' '+
+ pPersonToStr(I._Ps[1])+' '+
+ myfloattostr(I.Laenge);
+end;
+
+function TMFInteraktionToStr(I: TMFInteraktion): String;
+begin
+ TMFInteraktionToStr:=
+ pPersonToStr(I._P)+' '+
+ pFamilieToStr(I._F)+' '+
+ myfloattostr(I.Laenge);
+end;
+
+function TFFInteraktionToStr(I: TFFInteraktion): String;
+begin
+ TFFInteraktionToStr:=
+ pFamilieToStr(I._Fs[0])+' '+
+ pFamilieToStr(I._Fs[1]);
+end;
+
+function findeEreignis(var Es: tEreignisArray; eID: String): tEreignis;
+var i: longint;
+begin
+ if eID='NIL' then begin
+ result:=nil;
+ exit;
+ end;
+ for i:=0 to length(Es)-1 do
+ if Es[i].ID=eID then begin
+ result:=Es[i];
+ exit;
+ end;
+ result:=tEreignis.create;
+ result.ID:=eID;
+ setlength(Es,length(Es)+1);
+ Es[length(Es)-1]:=result;
+ Es[length(Es)-1].index:=length(Es)-1;
+end;
+
+function findeFamilie(var Fs: tFamilieArray; fID: String): tFamilie;
+begin
+ result:=findeFamilie(Fs,fID,true);
+end;
+
+function findeFamilie(var Fs: tFamilieArray; fID: String; darfErzeugen: boolean): tFamilie;
+var i: longint;
+begin
+ if fID='NIL' then begin
+ result:=nil;
+ exit;
+ end;
+ for i:=0 to length(Fs)-1 do
+ if Fs[i].ID=fID then begin
+ result:=Fs[i];
+ exit;
+ end;
+ if darfErzeugen then begin
+ result:=tFamilie.create;
+ result.ID:=fID;
+ setlength(Fs,length(Fs)+1);
+ Fs[length(Fs)-1]:=result;
+ Fs[length(Fs)-1].index:=length(Fs)-1;
+ end
+ else
+ result:=nil;
+end;
+
+function findePerson(var Ps: tPersonArray; pID: String): tPerson;
+begin
+ result:=findePerson(Ps,pID,true);
+end;
+
+function findePerson(var Ps: tPersonArray; pID: String; darfErzeugen: boolean): tPerson;
+var i: longint;
+begin
+ if pID='NIL' then begin
+ result:=nil;
+ exit;
+ end;
+ for i:=0 to length(Ps)-1 do
+ if Ps[i].ID=pID then begin
+ result:=Ps[i];
+ exit;
+ end;
+ if darfErzeugen then begin
+ result:=tPerson.create;
+ result.ID:=pID;
+ setlength(Ps,length(Ps)+1);
+ Ps[length(Ps)-1]:=result;
+ Ps[length(Ps)-1].index:=length(Ps)-1;
+ end
+ else
+ result:=nil;
+end;
+
+function findeMMInteraktion(var MMs: tMMInteraktionArray; var Ps: tPersonArray; ia: string): tMMInteraktion;
+var
+ i: longint;
+begin
+ for i:=0 to length(MMs)-1 do
+ if tMMInteraktionToStr(MMs[i])=ia then begin
+ result:=MMs[i];
+ exit;
+ end;
+ setlength(MMs,length(MMs)+1);
+ MMs[length(MMs)-1]:=importMMInteraktion(Ps,ia);
+ MMs[length(MMs)-1].index:=length(MMs)-1;
+end;
+
+function findeMFInteraktion(var MFs: tMFInteraktionArray; var Ps: tPersonArray; var Fs: tFamilieArray; ia: string): tMFInteraktion;
+var
+ i: longint;
+begin
+ for i:=0 to length(MFs)-1 do
+ if tMFInteraktionToStr(MFs[i])=ia then begin
+ result:=MFs[i];
+ exit;
+ end;
+ setlength(MFs,length(MFs)+1);
+ MFs[length(MFs)-1]:=importMFInteraktion(Ps,Fs,ia);
+ MFs[length(MFs)-1].index:=length(MFs)-1;
+end;
+
+function findeFFInteraktion(var FFs: tFFInteraktionArray; var Fs: tFamilieArray; ia: string): tFFInteraktion;
+var
+ i: longint;
+begin
+ for i:=0 to length(FFs)-1 do
+ if tFFInteraktionToStr(FFs[i])=ia then begin
+ result:=FFs[i];
+ exit;
+ end;
+ setlength(FFs,length(FFs)+1);
+ FFs[length(FFs)-1]:=importFFInteraktion(Fs,ia);
+ FFs[length(FFs)-1].index:=length(FFs)-1;
+end;
+
+procedure loescheEreignis(var Es: tEreignisArray; eID: string);
+var i,j: longint;
+begin
+ if eID='NIL' then
+ exit;
+ for i:=0 to length(Es)-1 do
+ if Es[i].ID=eID then begin
+ Es[i].free;
+ for j:=i+1 to length(Es)-1 do begin
+ Es[j-1]:=Es[j];
+ Es[j-1].index:=j-1;
+ end;
+ setlength(Es,length(Es)-1);
+ exit;
+ end;
+end;
+
+procedure loescheFamilie(var Fs: tFamilieArray; fID: string);
+var i,j: longint;
+begin
+ if fID='NIL' then
+ exit;
+ for i:=0 to length(Fs)-1 do
+ if Fs[i].ID=fID then begin
+ Fs[i].free;
+ for j:=i+1 to length(Fs)-1 do begin
+ Fs[j-1]:=Fs[j];
+ Fs[j-1].index:=j-1;
+ end;
+ setlength(Fs,length(Fs)-1);
+ exit;
+ end;
+end;
+
+procedure loeschePerson(var Ps: tPersonArray; pID: string);
+var i,j: longint;
+begin
+ if pID='NIL' then
+ exit;
+ for i:=0 to length(Ps)-1 do
+ if Ps[i].ID=pID then begin
+ Ps[i].free;
+ for j:=i+1 to length(Ps)-1 do begin
+ Ps[j-1]:=Ps[j];
+ Ps[j-1].index:=j-1;
+ end;
+ setlength(Ps,length(Ps)-1);
+ exit;
+ end;
+end;
+
+procedure mergePerson(var Ps: tPersonArray; var P: tPerson);
+var i: longint;
+begin
+ for i:=0 to length(Ps)-1 do
+ if Ps[i].ID=P.ID then begin
+ P.free;
+ P:=Ps[i];
+ exit;
+ end;
+ setlength(Ps,length(Ps)+1);
+ Ps[length(Ps)-1]:=P;
+ Ps[length(Ps)-1].index:=length(Ps)-1;
+end;
+
+procedure mergeFamilie(var Fs: tFamilieArray; var F: tFamilie);
+var i: longint;
+begin
+ for i:=0 to length(Fs)-1 do
+ if Fs[i].ID=F.ID then begin
+ F.free;
+ F:=Fs[i];
+ exit;
+ end;
+ setlength(Fs,length(Fs)+1);
+ Fs[length(Fs)-1]:=F;
+ Fs[length(Fs)-1].index:=length(Fs)-1;
+end;
+
+function ImportEreignis(S: string; var Es: tEreignisArray): tEreignis;
+var i: Longint;
+ found: boolean;
+begin
+ result:=tEreignis.create;
+ result.ID:=leftStr(S,pos(' ',S)-1);
+ found:=false;
+ for i:=0 to length(Es)-1 do
+ if result.ID = Es[i].ID then begin
+ result.free;
+ result:=Es[i];
+ found:=true;
+ break;
+ end;
+ if not found then begin
+ setlength(Es,length(Es)+1);
+ Es[length(Es)-1]:=result;
+ Es[length(Es)-1].index:=length(Es)-1;
+ end;
+ delete(S,1,pos(' ',S));
+ result.Jahr:=strtoint(leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ result.Art:=TEreignisart(strtoint(S));
+end;
+
+function ImportPerson(S: string; var Ps: tPersonArray; var Es: tEreignisArray; var Fs: tFamilieArray): tPerson;
+var i: longint;
+ found: boolean;
+ ea: TEreignisart;
+begin
+ result:=tPerson.create;
+ result.ID:=leftStr(S,pos(' ',S)-1);
+ found:=false;
+ for i:=0 to length(Ps)-1 do
+ if Ps[i].ID = result.ID then begin
+ result.free;
+ result:=Ps[i];
+ found:=true;
+ break;
+ end;
+ if not found then begin
+ setlength(Ps,length(Ps)+1);
+ Ps[length(Ps)-1]:=result;
+ Ps[length(Ps)-1].index:=length(Ps)-1;
+ end;
+ delete(S,1,pos(' ',S));
+ result.Anfang:=findeEreignis(Es,leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ result.Ende:=findeEreignis(Es,leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ for ea:=low(TEreignisart) to high(TEreignisart) do begin
+ result.Ereignisse[ea]:=findeEreignis(Es,leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ end;
+ result.KindIn:=findeFamilie(Fs,leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ result.ElterIn:=ImportFamilieArray(S,Fs);
+ delete(S,1,1);
+ result.Vorname:=leftStr(S,pos('''',S)-1);
+ delete(S,1,pos('''',S)+2);
+ result.Nachname:=leftStr(S,pos('''',S)-1);
+ delete(S,1,pos('''',S)+1);
+ result.P1:=strtoint(leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ result.P2:=strtoint(leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ result.P3:=strtoint(S);
+end;
+
+function ImportFamilie(s: string; var Ps: tPersonArray; var Es: tEreignisArray; var Fs: tFamilieArray): tFamilie;
+var i: longint;
+ found: boolean;
+begin
+ result:=tFamilie.create;
+ result.ID:=leftStr(S,pos(' ',S)-1);
+ found:=false;
+ for i:=0 to length(Fs)-1 do
+ if Fs[i].ID = result.ID then begin
+ result.free;
+ result:=Fs[i];
+ found:=true;
+ break;
+ end;
+ if not found then begin
+ setlength(Fs,length(Fs)+1);
+ Fs[length(Fs)-1]:=result;
+ Fs[length(Fs)-1].index:=length(Fs)-1;
+ end;
+ delete(S,1,pos(' ',S));
+ result.Anfang:=findeEreignis(Es,leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ result.Verheiratet:=leftStr(S,pos(' ',S)-1)='1';
+ delete(S,1,pos(' ',S));
+ result.Eltern[0]:=findePerson(Ps,leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ result.Eltern[1]:=findePerson(Ps,leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ S:=S+' ';
+ result.Kinder:=importPersonArray(S,Ps);
+end;
+
+function strToTVerknuepfung(var Ps: tPersonArray; S: String): tVerknuepfung;
+var i: Longint;
+ c: Char;
+begin
+ S:=S+' ';
+ result:=tVerknuepfung.create;
+ result.outP:=findePerson(Ps,leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ for i:=0 to 1 do
+ for c:='x' to 'y' do begin
+ result.Input[i,c]:=strtoint(leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ end;
+ result.Lambda:=strtoint(leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ for C:='x' to 'y' do begin
+ result.Output[C]:=strtoint(leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ end;
+end;
+
+function importMMInteraktion(var Ps: tPersonArray; S: String): tMMInteraktion;
+var i: Longint;
+begin
+ result:=tMMInteraktion.create;
+ for i:=0 to 1 do begin
+ result._Ps[i]:=findePerson(Ps,leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ end;
+ result.Laenge:=mystrtofloat(S);
+end;
+
+function importMFInteraktion(var Ps: tPersonArray; var Fs: tFamilieArray; S: String): tMFInteraktion;
+begin
+ result:=tMFInteraktion.create;
+ result._P:=findePerson(Ps,leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ result._F:=findeFamilie(Fs,leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ result.Laenge:=mystrtofloat(S);
+end;
+
+function importFFInteraktion(var Fs: tFamilieArray; S: String): tFFInteraktion;
+var i: longint;
+begin
+ result:=tFFInteraktion.create;
+ S:=S+' ';
+ for i:=0 to 1 do begin
+ result._Fs[i]:=findeFamilie(Fs,leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ end;
+end;
+
+function ImportFamilieArray(var S: String; var Fs: tFamilieArray): tFamilieArray;
+var I: Longint;
+begin
+ setlength(result,strtoint(leftStr(S,pos(' ',S)-1)));
+ delete(S,1,pos(' ',S));
+ for I:=0 to length(result)-1 do begin
+ result[I]:=findeFamilie(Fs,leftStr(S,pos(' ',S)-1));
+ result[I].index:=I;
+ delete(S,1,pos(' ',S));
+ end;
+end;
+
+function ImportPersonArray(var S: String; var Ps: tPersonArray): tPersonArray;
+var I: Longint;
+begin
+ setlength(result,strtoint(leftStr(S,pos(' ',S)-1)));
+ delete(S,1,pos(' ',S));
+ for I:=0 to length(result)-1 do begin
+ result[I]:=findePerson(Ps,leftStr(S,pos(' ',S)-1));
+ result[I].index:=I;
+ delete(S,1,pos(' ',S));
+ end;
+end;
+
+procedure StrToTIntArray(var S: String; var A: TIntArray);
+var I: Longint;
+begin
+ setlength(A,strtoint(leftStr(S,pos(' ',S)-1)));
+ delete(S,1,pos(' ',S));
+ for I:=0 to length(A)-1 do begin
+ A[I]:=strtoint(leftStr(S,pos(' ',S)-1));
+ delete(S,1,pos(' ',S));
+ end;
+end;
+
+function Permutation(n: Longint): TIntArray;
+var
+ I,J: integer;
+begin
+ if n<=0 then setlength(result,0)
+ else begin
+ result:=Permutation(n-1);
+ I:=random(n);
+ setlength(result,n);
+ for J:=n-1 downto I+1 do
+ result[J]:=result[J-1];
+ result[I]:=n-1;
+ end;
+end;
+
+// tParameterAttribut **********************************************************
+
+procedure tParameterAttribut.setzeKoordinate(ik: boolean);
+begin
+ if istKoordinate=ik then begin
+ write('Parameter ist bereits als ');
+ if not ik then write('nicht-');
+ writeln('Koordinate markiert!');
+ halt;
+ end;
+ istKoordinate:=ik;
+end;
+
+procedure tParameterAttribut.setzeUnabhaengig(iu: boolean);
+begin
+ if istUnabhaengig=iu then begin
+ write('Parameter ist bereits als ');
+ if iu then write('un');
+ writeln('abhängig markiert!');
+ halt;
+ end;
+ istUnabhaengig:=iu;
+end;
+
+procedure tParameterAttribut.setzeBenutzt(wb: boolean);
+begin
+ if wirdBenutzt=wb then begin
+ write('Parameter ist bereits als ');
+ if not wb then write('un');
+ writeln('benutzt markiert!');
+ halt;
+ end;
+ wirdBenutzt:=wb;
+end;
+
+procedure tParameterAttribut.fromChar(c: char);
+begin
+ if (c<'0') or (c>'7') then begin
+ writeln(''''+c+''' ist kein gültiger Wert für Parametereigenschaften, sondern nur 0..7.');
+ halt;
+ end;
+ istKoordinate:=odd(ord(c)-ord('0'));
+ istUnabhaengig:=odd((ord(c)-ord('0')) shr 1);
+ wirdBenutzt:=odd((ord(c)-ord('0')) shr 2);
+end;
+
+function tParameterAttribut.toChar: char;
+begin
+ result:=char(ord('0') + byte(istKoordinate) + 2*byte(istUnabhaengig) + 4*byte(wirdBenutzt));
+end;
+
+// tGenerikum ******************************************************************
+
+constructor tGenerikum.create;
+begin
+ inherited create;
+ fillchar(ID,sizeof(ID),#0);
+ index:=-1;
+end;
+
+destructor tGenerikum.destroy;
+begin
+ setlength(ID,0);
+ inherited destroy;
+end;
+
+procedure tGenerikum.init(g: tGenerikum);
+begin
+ ID:=g.ID;
+ index:=g.index;
+end;
+
+function tGenerikum.istGleich(g: tGenerikum): boolean;
+begin
+ result:=ID=g.ID; // Index wird absichtlich nicht mit überprüft, da die Reihenfolge im Array egal sein soll
+end;
+
+// tEreignis *******************************************************************
+
+function tEreignis.istDummy: boolean;
+begin
+ result:=(Art=eaDummy) or (Jahr=0);
+end;
+
+constructor tEreignis.create;
+begin
+ inherited create;
+ jahr:=0;
+ Art:=eaDummy;
+end;
+
+destructor tEreignis.destroy;
+begin
+ inherited destroy;
+end;
+
+procedure tEreignis.init(e: tGenerikum);
+begin
+ inherited init(e);
+ if not (e is tEreignis) then begin
+ writeln('Ereignis kann nicht mit nicht-Ereignis initialisiert werden!');
+ halt;
+ end;
+ jahr:=(e as tEreignis).Jahr;
+ Art:=(e as tEreignis).Art;
+end;
+
+function tEreignis.istGleich(e: tGenerikum): boolean;
+begin
+ result:=inherited istGleich(e);
+ if not (e is tEreignis) then begin
+ writeln('Ereignis kann nicht mit nicht-Ereignis verglichen werden!');
+ halt;
+ end;
+ result:=result and ((e as tEreignis).Jahr=Jahr) and ((e as tEreignis).Art=Art);
+end;
+
+// tPerson *********************************************************************
+
+constructor tPerson.create;
+var ea: tEreignisart;
+begin
+ inherited create;
+ Anfang:=nil;
+ Ende:=nil;
+ for ea:=low(ea) to high(ea) do
+ Ereignisse[ea]:=nil;
+ KindIn:=nil;
+ fillchar(ElterIn,sizeof(ElterIn),#0);
+ fillchar(inputIn,sizeof(inputIn),#0);
+ fillchar(outputIn,sizeof(outputIn),#0);
+ fillchar(Vorname,sizeof(Vorname),#0);
+ fillchar(Nachname,sizeof(Nachname),#0);
+ fillchar(inMMInteraktion,sizeof(inMMInteraktion),#0);
+ fillchar(inMFInteraktion,sizeof(inMFInteraktion),#0);
+ P1:=-1;
+ P2:=-1;
+ P3:=-1;
+end;
+
+destructor tPerson.destroy;
+var
+ i: longint;
+begin
+ if assigned(KindIn) then
+ KindIn.entferneKind(self);
+ for i:=0 to length(ElterIn)-1 do
+ if assigned(ElterIn[i]) then
+ ElterIn[i].entferneElter(self);
+ setlength(ElterIn,0);
+ setlength(Vorname,0);
+ setlength(Nachname,0);
+ if length(inMMInteraktion)<>0 then
+ raise Exception.create('Diese Person ist noch in einer MMInteraktion verzeichnet!');
+ setlength(inMMInteraktion,0);
+ if length(inMFInteraktion)<>0 then
+ raise Exception.create('Diese Person ist noch in einer MFInteraktion verzeichnet!');
+ setlength(inMFInteraktion,0);
+ inherited destroy;
+end;
+
+procedure tPerson.entferneElterIn(wo: tFamilie);
+var
+ i,j: longint;
+begin
+ for i:=length(ElterIn)-1 downto 0 do
+ if ElterIn[i]=wo then begin
+ for j:=i+1 to length(ElterIn)-1 do
+ ElterIn[j-1]:=ElterIn[j];
+ setlength(ElterIn,length(ElterIn)-1);
+ end;
+end;
+
+procedure tPerson.entferneKindIn(wo: tFamilie);
+begin
+ if KindIn=wo then
+ KindIn:=nil;
+end;
+
+procedure tPerson.fuegeInputInHinzu(wo: tVerknuepfung);
+var
+ i: longint;
+begin
+ for i:=0 to length(inputIn)-1 do
+ if inputIn[i]=wo then
+ writeln(inputIn[i+length(inputIn)].outP.id);
+ setlength(inputIn,length(inputIn)+1);
+ inputIn[length(inputIn)-1]:=wo;
+end;
+
+procedure tPerson.entferneInputIn(wo: tVerknuepfung);
+var
+ i,j: longint;
+begin
+ for i:=length(inputIn)-1 downto 0 do
+ if inputIn[i]=wo then begin
+ for j:=i+1 to length(inputIn)-1 do
+ inputIn[j-1]:=inputIn[j];
+ setlength(inputIn,length(inputIn)-1);
+ end;
+end;
+
+procedure tPerson.fuegeOutputInHinzu(wo: tVerknuepfung);
+var
+ i: longint;
+begin
+ for i:=0 to length(outputIn)-1 do
+ if outputIn[i]=wo then
+ writeln(outputIn[i+length(outputIn)].outP.id);
+ setlength(outputIn,length(outputIn)+1);
+ outputIn[length(outputIn)-1]:=wo;
+end;
+
+procedure tPerson.entferneOutputIn(wo: tVerknuepfung);
+var
+ i,j: longint;
+begin
+ for i:=length(outputIn)-1 downto 0 do
+ if outputIn[i]=wo then begin
+ for j:=i+1 to length(outputIn)-1 do
+ outputIn[j-1]:=outputIn[j];
+ setlength(outputIn,length(outputIn)-1);
+ end;
+end;
+
+procedure tPerson.fuegeInMMInteraktionHinzu(wo: tMMInteraktion);
+begin
+ setlength(inMMInteraktion,length(inMMInteraktion)+1);
+ inMMInteraktion[length(inMMInteraktion)-1]:=wo;
+end;
+
+procedure tPerson.entferneInMMInteraktion(wo: tMMInteraktion);
+var
+ i,j: longint;
+begin
+ for i:=length(inMMInteraktion)-1 downto 0 do
+ if inMMInteraktion[i]=wo then begin
+ for j:=i+1 to length(inMMInteraktion)-1 do
+ inMMInteraktion[j-1]:=inMMInteraktion[j];
+ setlength(inMMInteraktion,length(inMMInteraktion)-1);
+ end;
+end;
+
+procedure tPerson.fuegeInMFInteraktionHinzu(wo: tMFInteraktion);
+begin
+ setlength(inMFInteraktion,length(inMFInteraktion)+1);
+ inMFInteraktion[length(inMFInteraktion)-1]:=wo;
+end;
+
+procedure tPerson.entferneInMFInteraktion(wo: tMFInteraktion);
+var
+ i,j: longint;
+begin
+ for i:=length(inMFInteraktion)-1 downto 0 do
+ if inMFInteraktion[i]=wo then begin
+ for j:=i+1 to length(inMFInteraktion)-1 do
+ inMFInteraktion[j-1]:=inMFInteraktion[j];
+ setlength(inMFInteraktion,length(inMFInteraktion)-1);
+ end;
+end;
+
+procedure tPerson.init(p: tGenerikum);
+begin
+ inherited init(p);
+ if not (p is tPerson) then begin
+ writeln('Person kann nicht mit nicht-Person initialisiert werden!');
+ halt;
+ end;
+ Vorname:=(p as tPerson).Vorname;
+ Nachname:=(p as tPerson).Nachname;
+ P1:=(p as tPerson).P1;
+ P2:=(p as tPerson).P2;
+ P3:=(p as tPerson).P3;
+end;
+
+procedure tPerson.init(p: tGenerikum; var es: tEreignisArray);
+var
+ ea: tEreignisArt;
+begin
+ init(p);
+ Anfang:=FindeEreignis(es,pEreignisToStr((p as tPerson).Anfang));
+ Ende:=FindeEreignis(es,pEreignisToStr((p as tPerson).Ende));
+ for ea:=low(tEreignisArt) to high(tEreignisArt) do
+ Ereignisse[ea]:=FindeEreignis(es,pEreignisToStr((p as tPerson).Ereignisse[ea]));
+end;
+
+procedure tPerson.init(p: tGenerikum; var es: tEreignisArray; var fs: tFamilieArray);
+begin
+ init(p,es,fs,true);
+end;
+
+procedure tPerson.init(p: tGenerikum; var es: tEreignisArray; var fs: tFamilieArray; darfErzeugen: boolean);
+var
+ i,j: longint;
+begin
+ init(p,es);
+ KindIn:=findeFamilie(fs,pFamilieToStr((p as tPerson).KindIn),darfErzeugen);
+ if assigned(KindIn) and
+ not KindIn.hatKind(self) then begin
+ setlength(KindIn.Kinder,length(KindIn.Kinder)+1);
+ KindIn.Kinder[length(KindIn.Kinder)-1]:=self;
+ end;
+ setlength(ElterIn,length((p as tPerson).ElterIn));
+ for i:=length(ElterIn)-1 downto 0 do begin
+ ElterIn[i]:=findeFamilie(fs,pFamilieToStr((p as tPerson).ElterIn[i]),darfErzeugen);
+ if assigned(ElterIn[i]) and
+ not ElterIn[i].hatElter(self) then
+ ElterIn[i].Eltern[byte((p as tPerson).ElterIn[i].Eltern[1]=p)]:=self
+ else begin
+ for j:=i+1 to length(ElterIn)-1 do
+ ElterIn[j-1]:=ElterIn[j];
+ setlength(ElterIn,length(ElterIn)-1);
+ end;
+ end;
+end;
+
+function tPerson.anzahlVerbindungen: longint;
+begin
+ result:=length(ElterIn)+byte(assigned(KindIn));
+end;
+
+function tPerson.istGleich(p: tGenerikum): boolean;
+var
+ ea: tEreignisart;
+ i,j,cnt: longint;
+begin
+ result:=inherited istGleich(p);
+ if not (p is tPerson) then begin
+ writeln('Person kann nicht mit nicht-Person verglichen werden!');
+ halt;
+ end;
+ result:=
+ result and
+ (Vorname=(p as tPerson).Vorname) and
+ (Nachname=(p as tPerson).Nachname) and
+ Anfang.istGleich((p as tPerson).Anfang) and
+ Ende.istGleich((p as tPerson).Ende);
+ for ea:=low(tEreignisArt) to high(tEreignisArt) do
+ result:=
+ result and ((Ereignisse[ea]=(p as tPerson).Ereignisse[ea]) or Ereignisse[ea].istGleich((p as tPerson).Ereignisse[ea]));
+ result:=result and (pFamilieToStr(KindIn)=pFamilieToStr((p as tPerson).KindIn));
+ result:=result and (length(ElterIn)=length((p as tPerson).ElterIn));
+ if result then
+ for i:=0 to length(ElterIn)-1 do begin
+ cnt:=0;
+ for j:=0 to length(ElterIn)-1 do
+ if pFamilieToStr(ElterIn[i])=pFamilieToStr((p as tPerson).ElterIn[j]) then
+ inc(cnt);
+ result:=result and (cnt=1);
+ end;
+end;
+
+function tPerson.elterVonFamilie(eNum: longint): tFamilie;
+var
+ i: longint;
+begin
+ result:=nil;
+ for i:=0 to length(elterIn)-1 do
+ if elterIn[i].Eltern[eNum]=self then begin
+ if result<>nil then begin
+ writeln('*** Warnung ***');
+ writeln('Rückgabewert nicht eindeutig, Person '+pPersonToStr(self)+' ist Elter '+inttostr(eNum)+' in mehreren Familien!');
+ exit;
+ end;
+ result:=elterIn[i];
+ end;
+end;
+
+function tPerson.istElterIn(f: tFamilie): boolean;
+var
+ i: longint;
+begin
+ result:=false;
+ for i:=0 to length(elterIn)-1 do
+ result:=result or (elterIn[i]=f);
+end;
+
+// tFamilie ********************************************************************
+
+constructor tFamilie.create;
+begin
+ inherited create;
+ Anfang:=nil;
+ Verheiratet:=false;
+ Eltern[0]:=nil;
+ Eltern[1]:=nil;
+ fillchar(Kinder,sizeof(Kinder),#0);
+ fillchar(inMFInteraktion,sizeof(inMFInteraktion),#0);
+ fillchar(inFFInteraktion,sizeof(inFFInteraktion),#0);
+end;
+
+destructor tFamilie.destroy;
+var
+ i: longint;
+begin
+ for i:=0 to length(Kinder)-1 do
+ if assigned(Kinder[i]) then
+ Kinder[i].entferneKindIn(self);
+ for i:=0 to length(Eltern)-1 do
+ if assigned(Eltern[i]) then
+ Eltern[i].entferneElterIn(self);
+ setlength(Kinder,0);
+ if length(inMFInteraktion)<>0 then
+ raise Exception.create('Diese Familie ist noch in einer MFInteraktion verzeichnet!');
+ setlength(inMFInteraktion,0);
+ if length(inFFInteraktion)<>0 then
+ raise Exception.create('Diese Familie ist noch in einer FFInteraktion verzeichnet!');
+ setlength(inFFInteraktion,0);
+ inherited destroy;
+end;
+
+procedure tFamilie.entferneElter(wen: tPerson);
+var
+ i,anz: longint;
+begin
+ anz:=0;
+ for i:=0 to length(Eltern)-1 do
+ if Eltern[i]=wen then begin
+ inc(anz);
+ Eltern[i]:=nil;
+ end;
+ if anz=0 then begin
+ writeln('Ich habe den Elter '''+wen.ID+''' nicht in Familie '''+ID+''' gefunden!');
+ halt;
+ end;
+ if anz>1 then begin
+ writeln('Ich habe den Elter '''+wen.ID+''' mehrmals in Familie '''+ID+''' gefunden!');
+ halt;
+ end;
+end;
+
+procedure tFamilie.entferneKind(wen: tPerson);
+var
+ i,j,anz: longint;
+begin
+ anz:=0;
+ for i:=length(Kinder)-1 downto 0 do
+ if Kinder[i]=wen then begin
+ inc(Anz);
+ Kinder[i]:=nil;
+ for j:=i+1 to length(Kinder)-1 do
+ Kinder[j-1]:=Kinder[j];
+ setlength(Kinder,length(Kinder)-1);
+ end;
+ if anz=0 then begin
+ writeln('Ich habe das Kind '''+wen.ID+''' nicht in Familie '''+ID+''' gefunden!');
+ halt;
+ end;
+ if anz>1 then begin
+ writeln('Ich habe das Kind '''+wen.ID+''' mehrmals in Familie '''+ID+''' gefunden!');
+ halt;
+ end;
+end;
+
+procedure tFamilie.fuegeInMFInteraktionHinzu(wo: tMFInteraktion);
+begin
+ setlength(inMFInteraktion,length(inMFInteraktion)+1);
+ inMFInteraktion[length(inMFInteraktion)-1]:=wo;
+end;
+
+procedure tFamilie.entferneInMFInteraktion(wo: tMFInteraktion);
+var
+ i,j: longint;
+begin
+ for i:=length(inMFInteraktion)-1 downto 0 do
+ if inMFInteraktion[i]=wo then begin
+ for j:=i+1 to length(inMFInteraktion)-1 do
+ inMFInteraktion[j-1]:=inMFInteraktion[j];
+ setlength(inMFInteraktion,length(inMFInteraktion)-1);
+ end;
+end;
+
+procedure tFamilie.fuegeInFFInteraktionHinzu(wo: tFFInteraktion);
+begin
+ setlength(inFFInteraktion,length(inFFInteraktion)+1);
+ inFFInteraktion[length(inFFInteraktion)-1]:=wo;
+end;
+
+procedure tFamilie.entferneInFFInteraktion(wo: tFFInteraktion);
+var
+ i,j: longint;
+begin
+ for i:=length(inFFInteraktion)-1 downto 0 do
+ if inFFInteraktion[i]=wo then begin
+ for j:=i+1 to length(inFFInteraktion)-1 do
+ inFFInteraktion[j-1]:=inFFInteraktion[j];
+ setlength(inFFInteraktion,length(inFFInteraktion)-1);
+ end;
+end;
+
+procedure tFamilie.init(f: tGenerikum);
+begin
+ inherited init(f);
+ if not (f is tFamilie) then begin
+ writeln('Familie kann nicht mit nicht-Familie initialisiert werden!');
+ halt;
+ end;
+ Verheiratet:=(f as tFamilie).Verheiratet;
+end;
+
+procedure tFamilie.init(f: tGenerikum; var Es: tEreignisArray; var Ps: tPersonArray);
+begin
+ init(f,Es,Ps,true);
+end;
+
+procedure tFamilie.init(f: tGenerikum; var Es: tEreignisArray; var Ps: tPersonArray; darfErzeugen: boolean);
+var
+ i,j: longint;
+begin
+ init(f);
+ Anfang:=findeEreignis(Es,pEreignisToStr((f as tFamilie).Anfang));
+ for i:=0 to 1 do begin
+ Eltern[i]:=findePerson(Ps,pPersonToStr((f as tFamilie).Eltern[i]),darfErzeugen);
+ if assigned(Eltern[i]) and
+ not Eltern[i].istElterIn(self) then begin
+ setlength(Eltern[i].ElterIn,length(Eltern[i].ElterIn)+1);
+ Eltern[i].ElterIn[length(Eltern[i].ElterIn)-1]:=self;
+ end;
+ end;
+ setlength(Kinder,length((f as tFamilie).Kinder));
+ for i:=length(Kinder)-1 downto 0 do begin
+ Kinder[i]:=findePerson(Ps,pPersonToStr((f as tFamilie).Kinder[i]),darfErzeugen);
+ if assigned(Kinder[i]) then
+ Kinder[i].KindIn:=self
+ else begin
+ for j:=i+1 to length(Kinder)-1 do
+ Kinder[j-1]:=Kinder[j];
+ setlength(Kinder,length(Kinder)-1);
+ end;
+ end;
+end;
+
+function tFamilie.anzahlVerbindungen: longint;
+var
+ i: longint;
+begin
+ result:=length(Kinder);
+ for i:=0 to 1 do
+ result:=result+byte(assigned(Eltern[i]));
+end;
+
+function tFamilie.istGleich(f: tGenerikum): boolean;
+var
+ i,j,cnt: longint;
+begin
+ result:=inherited istGleich(f);
+ if not (f is tFamilie) then begin
+ writeln('Familie kann nicht mit nicht-Familie verglichen werden!');
+ halt;
+ end;
+ result:=
+ result and
+ (Verheiratet=(f as tFamilie).Verheiratet) and
+ (Anfang.istGleich((f as tFamilie).Anfang));
+ for i:=0 to 1 do
+ result:=
+ result and
+ (pPersonToStr(Eltern[i])=pPersonToStr((f as tFamilie).Eltern[i]));
+ result:=result and (length(Kinder)=length((f as tFamilie).Kinder));
+ if result then
+ for i:=0 to length(Kinder)-1 do begin
+ cnt:=0;
+ for j:=0 to length(Kinder)-1 do
+ if pPersonToStr(Kinder[i])=pPersonToStr((f as tFamilie).Kinder[j]) then
+ inc(cnt);
+ result:=result and (cnt=1);
+ end;
+end;
+
+function tFamilie.hatKind(p: tPerson): boolean;
+var
+ i: longint;
+begin
+ result:=false;
+ for i:=0 to length(Kinder)-1 do
+ result:=result or (Kinder[i]=p);
+end;
+
+function tFamilie.hatElter(p: tPerson): boolean;
+begin
+ result:=(Eltern[0]=p) or (Eltern[1]=p);
+end;
+
+// tVerknuepfung ***************************************************************
+
+procedure tVerknuepfung.wOutP(p: tPerson);
+begin
+ if assigned(outP) then begin
+ if assigned(outP.KindIn) then begin
+ if assigned(outP.KindIn.Eltern[0]) then
+ outP.KindIn.Eltern[0].entferneInputIn(self);
+ if assigned(outP.KindIn.Eltern[1]) then
+ outP.KindIn.Eltern[1].entferneInputIn(self);
+ outP.entferneOutputIn(self);
+ end;
+ end;
+ _outP:=p;
+ if assigned(outP) then begin
+ if assigned(outP.KindIn) then begin
+ if assigned(outP.KindIn.Eltern[0]) then
+ outP.KindIn.Eltern[0].fuegeInputInHinzu(self);
+ if assigned(outP.KindIn.Eltern[1]) then
+ outP.KindIn.Eltern[1].fuegeInputInHinzu(self);
+ outP.fuegeOutputInHinzu(self);
+ end;
+ end;
+end;
+
+destructor tVerknuepfung.destroy;
+begin
+ if assigned(outP) then begin
+ if assigned(outP.KindIn) then begin
+ if assigned(outP.KindIn.Eltern[0]) then
+ outP.KindIn.Eltern[0].entferneInputIn(self);
+ if assigned(outP.KindIn.Eltern[1]) then
+ outP.KindIn.Eltern[1].entferneInputIn(self);
+ end;
+ outP.entferneOutputIn(self);
+ end;
+ inherited destroy;
+end;
+
+function tVerknuepfung.istGleich(v: tVerknuepfung; p2p: tIntArray): boolean;
+var
+ i: longint;
+ c: char;
+begin
+ result:=
+ (pPersonToStr(outP)=pPersonToStr(v.outP)) and
+ paramsGleich(Lambda,v.Lambda,p2p);
+ for c:='x' to 'y' do begin
+ result:=result and paramsGleich(Output[c],v.Output[c],p2p);
+ for i:=0 to 1 do
+ result:=result and paramsGleich(Input[i,c],v.Input[i,c],p2p);
+ end;
+end;
+
+// tMMInteraktion **************************************************************
+
+function tMMInteraktion.r_Ps(i: longint): tPerson;
+begin
+ result:=__Ps[i];
+end;
+
+procedure tMMInteraktion.w_Ps(i: longint; p: tPerson);
+begin
+ if assigned(_Ps[i]) then
+ _Ps[i].entferneInMMInteraktion(self);
+ __Ps[i]:=p;
+ if assigned(_Ps[i]) then
+ _Ps[i].fuegeInMMInteraktionHinzu(self);
+end;
+
+function tMMInteraktion.istGleich(ia: tMMInteraktion): boolean;
+var
+ i: longint;
+begin
+ result:=Laenge=ia.Laenge;
+ for i:=0 to 1 do
+ result:=result and (pPersonToStr(_Ps[i])=pPersonToStr(ia._Ps[i]));
+end;
+
+destructor tMMInteraktion.destroy;
+begin
+ if assigned(_Ps[0]) then
+ _Ps[0].entferneInMMInteraktion(self);
+ if assigned(_Ps[1]) then
+ _Ps[1].entferneInMMInteraktion(self);
+ inherited destroy;
+end;
+
+// tMFInteraktion **************************************************************
+
+procedure tMFInteraktion.w_P(p: tPerson);
+begin
+ if assigned(_P) then
+ _P.entferneInMFInteraktion(self);
+ __P:=p;
+ if assigned(_P) then
+ _P.fuegeInMFInteraktionHinzu(self);
+end;
+
+procedure tMFInteraktion.w_F(f: tFamilie);
+begin
+ if assigned(_F) then
+ _F.entferneInMFInteraktion(self);
+ __F:=f;
+ if assigned(_F) then
+ _F.fuegeInMFInteraktionHinzu(self);
+end;
+
+function tMFInteraktion.istGleich(ia: tMFInteraktion): boolean;
+begin
+ result:=
+ (Laenge=ia.Laenge) and
+ (pPersonToStr(_P)=pPersonToStr(ia._P)) and
+ (pFamilieToStr(_F)=pFamilieToStr(ia._F));
+end;
+
+destructor tMFInteraktion.destroy;
+begin
+ if assigned(_P) then
+ _P.entferneInMFInteraktion(self);
+ if assigned(_F) then
+ _F.entferneInMFInteraktion(self);
+ inherited destroy;
+end;
+
+// tFFInteraktion **************************************************************
+
+function tFFInteraktion.r_Fs(i: longint): tFamilie;
+begin
+ result:=__Fs[i];
+end;
+
+procedure tFFInteraktion.w_Fs(i: longint; f: tFamilie);
+begin
+ if assigned(_Fs[i]) then
+ _Fs[i].entferneInFFInteraktion(self);
+ __Fs[i]:=f;
+ if assigned(_Fs[i]) then
+ _Fs[i].fuegeInFFInteraktionHinzu(self);
+end;
+
+function tFFInteraktion.istGleich(ia: tFFInteraktion): boolean;
+var
+ i: longint;
+begin
+ result:=true;
+ for i:=0 to 1 do
+ result:=result and (pFamilieToStr(_Fs[i])=pFamilieToStr(ia._Fs[i]));
+end;
+
+destructor tFFInteraktion.destroy;
+begin
+ if assigned(_Fs[0]) then
+ _Fs[0].entferneInFFInteraktion(self);
+ if assigned(_Fs[1]) then
+ _Fs[1].entferneInFFInteraktion(self);
+ inherited destroy;
+end;
+
+// tZusammenhangskomponente ****************************************************
+constructor tZusammenhangskomponente.create;
+begin
+ inherited create;
+ fillchar(Familien,sizeof(Familien),#0);
+ setlength(Familien,0);
+end;
+
+destructor tZusammenhangskomponente.destroy;
+begin
+ setlength(Familien,0);
+ inherited destroy;
+end;
+
+function tZusammenhangskomponente.grenztAn(p: tPerson): boolean;
+var i,j: longint;
+begin
+ result:=false;
+ for i:=0 to length(Familien)-1 do begin
+ for j:=0 to 1 do
+ result:=result or (assigned(Familien[i].Eltern[j]) and (p.ID=Familien[i].Eltern[j].ID));
+ for j:=0 to length(Familien[i].Kinder)-1 do
+ result:=result or (p.ID=Familien[i].Kinder[j].ID);
+ end;
+end;
+
+procedure tZusammenhangskomponente.verschmelzeMit(zhk: tZusammenhangskomponente);
+var i,j: longint;
+ gefunden: boolean;
+begin
+ for i:=0 to length(zhk.Familien)-1 do begin
+ gefunden:=false;
+ for j:=0 to length(Familien)-1 do
+ gefunden:=gefunden or (zhk.Familien[i].ID=Familien[j].ID);
+ if not gefunden then begin
+ setlength(Familien,length(Familien)+1);
+ Familien[length(Familien)-1]:=zhk.Familien[i];
+ end;
+ end;
+end;
+
+procedure tZusammenhangskomponente.UmfeldEinfuegen(Fs: tFamilieArray; p: tPerson);
+var i,j: longint;
+ gefunden: boolean;
+begin
+ for i:=0 to length(Fs)-1 do begin
+ gefunden:=false;
+ for j:=0 to 1 do
+ gefunden:=gefunden or (assigned(Fs[i].Eltern[j]) and (p.ID=Fs[i].Eltern[j].ID));
+ for j:=0 to length(Fs[i].Kinder)-1 do
+ gefunden:=gefunden or (p.ID=Fs[i].Kinder[j].ID);
+ if gefunden then begin
+ for j:=0 to length(Familien)-1 do
+ gefunden:=gefunden and (Familien[j].ID <> Fs[i].ID);
+ if gefunden then begin
+ setlength(Familien,length(Familien)+1);
+ Familien[length(Familien)-1]:=Fs[i];
+ end;
+ end;
+ end;
+end;
+
+// tGraph **********************************************************************
+
+constructor tGraph.create;
+begin
+ inherited create;
+ fillchar(Ecken,sizeof(Ecken),#0);
+ setlength(Ecken,0);
+ fillchar(Kanten,sizeof(Kanten),#0);
+ setlength(Kanten,0);
+end;
+
+destructor tGraph.destroy;
+begin
+ setlength(Ecken,0);
+ setlength(Kanten,0);
+end;
+
+function tGraph.entferneBlaetter(var f: tIntArray): tIntArray;
+var i,j,n1,n2,anz: longint;
+ gefunden: boolean;
+begin
+ setlength(result,0);
+ anz:=0;
+ repeat
+ gefunden:=false;
+ for i:=length(f)-1 downto 0 do begin // nur Kanten, die noch dabei sind, können gelöscht werden
+ n1:=0;
+ n2:=0;
+ for j:=0 to length(f)-1 do begin // angrenzende Kanten, die noch dabei sind, zählen
+ n1:=n1 + byte((Kanten[f[j]].x=Kanten[f[i]].x) or (Kanten[f[j]].y=Kanten[f[i]].x));
+ n2:=n2 + byte((Kanten[f[j]].x=Kanten[f[i]].y) or (Kanten[f[j]].y=Kanten[f[i]].y));
+ end;
+ if (n1<=1) or (n2<=1) then begin // nur die Kante i selbst hängt an einer ihrer Ecken
+ gefunden:=true;
+ if anz>=length(result) then
+ setlength(result,anz+1024);
+ result[anz]:=f[i];
+ inc(anz);
+ for j:=i+1 to length(f)-1 do // aus dem Rennen
+ f[j-1]:=f[j];
+ setlength(f,length(f)-1);
+ end;
+ end;
+ until not gefunden;
+ setlength(result,anz);
+end;
+
+function tGraph.Pfadigkeit(Ks: tIntArray; a,b: longint): longint; // 0 -> zu wenig; 1 -> ein Pfad; 2-> zu viel
+var i,j,k,ich,letzter: longint;
+begin
+ ich:=a;
+ letzter:=-1;
+ repeat
+ j:=-1;
+ k:=0;
+ for i:=0 to length(Ks)-1 do begin
+ if (Kanten[Ks[i]].x=ich) and (Kanten[Ks[i]].y<>letzter) then begin // vorwärts immer, rückwärts nimmer
+ j:=Ks[i];
+ inc(k);
+ end;
+ if (Kanten[Ks[i]].y=ich) and (Kanten[Ks[i]].x<>letzter) then begin // vorwärts immer, rückwärts nimmer
+ j:=Ks[i];
+ inc(k);
+ end;
+ end;
+ if k=0 then begin // hier geht es nicht weiter
+ result:=0;
+ exit;
+ end;
+ if k>1+byte((letzter=-1) and (a=b)) then begin // hier gibt es eine Weggabelung
+ result:=2;
+ exit;
+ end;
+ if Kanten[j].x=ich then begin
+ letzter:=ich;
+ ich:=Kanten[j].y;
+ end
+ else begin
+ letzter:=ich;
+ ich:=Kanten[j].x;
+ end;
+ until ich=b;
+ result:=1;
+end;
+
+function tGraph.etwasDoppelt: boolean;
+var Ks: tIntArray;
+ i: longint;
+begin
+ setlength(Ks,length(Kanten));
+ for i:=0 to length(Ks)-1 do
+ Ks[i]:=i;
+ result:=etwasDoppelt(Ks);
+end;
+
+function tGraph.etwasDoppelt(Ks: tIntArray): boolean;
+var i,j: longint;
+begin
+ result:=false;
+ for i:=0 to length(Ks)-2 do
+ for j:=i+1 to length(Ks)-1 do
+ result:=
+ result or
+ ((Kanten[Ks[i]].x = Kanten[Ks[j]].x) and (Kanten[Ks[i]].y = Kanten[Ks[j]].y)) or
+ ((Kanten[Ks[i]].x = Kanten[Ks[j]].y) and (Kanten[Ks[i]].y = Kanten[Ks[j]].x));
+end;
+
+function tGraph.etwasRedundant(Ks1,Ks2: tIntArray): boolean;
+var i,j: longint;
+begin
+ result:=false;
+ for i:=0 to length(Ks1)-1 do
+ for j:=0 to length(Ks2)-1 do
+ result:=
+ result or
+ ((Kanten[Ks1[i]].x = Kanten[Ks2[j]].x) and (Kanten[Ks1[i]].y = Kanten[Ks2[j]].y)) or
+ ((Kanten[Ks1[i]].x = Kanten[Ks2[j]].y) and (Kanten[Ks1[i]].y = Kanten[Ks2[j]].x));
+end;
+
+procedure tGraph.dumpKantenArray(Ks: tIntArray);
+var
+ i: longint;
+begin
+ writeln(length(Ks));
+ for i:=0 to length(Ks)-1 do
+ writeln(' '+inttostr(Kanten[Ks[i]].x)+' -- '+inttostr(Kanten[Ks[i]].y));
+end;
+
+function tGraph.findeKreise: tIntArrayArray;
+var Farben: tIntArray;
+ i: longint;
+begin
+ setlength(result,0);
+ setlength(Farben,length(Kanten));
+ for i:=0 to length(Farben)-1 do // alles noch dabei
+ Farben[i]:=i;
+ entferneBlaetter(Farben);
+ if length(Farben)>0 then begin
+ result:=findeKreise(Farben);
+ exit;
+ end;
+end;
+
+function tGraph.findeKreise(f: tIntArray): tIntArrayArray;
+var j,k,l,m: longint;
+ loeschung,
+ sicherung: tIntArray;
+begin
+ setlength(result,0);
+ setlength(sicherung,length(f)-1);
+ for j:=0 to length(sicherung)-1 do
+ sicherung[j]:=f[j];
+ loeschung:=entferneBlaetter(sicherung);
+ if length(sicherung)>0 then begin // es sind noch Kanten da, also auch noch Kreise!
+ result:=findeKreise(sicherung); // alle bisher gefundenen Kreise
+ setlength(sicherung,length(sicherung)+length(loeschung)+1);
+ for j:=0 to length(loeschung)-1 do // alle gelöschten Kanten wieder einfügen ...
+ sicherung[length(sicherung)-j-2]:=loeschung[j];
+ sicherung[length(sicherung)-1]:=f[length(f)-1]; // ... wirklich alle!
+ for j:=0 to length(result)-1 do begin // jedem Kreis, der noch in sicherung ist ...
+ m:=-1;
+ for k:=0 to length(result[j])-1 do
+ if m=-1 then
+ for l:=0 to length(sicherung)-1 do
+ if sicherung[l]=result[j,k] then begin // die l-te Kante der Sicherung ist im j-ten Kreis (die k-te Kante)
+ m:=l;
+ break;
+ end;
+ if m=-1 then begin
+ writeln('interessanter Weise habe ich keine Kanten gefunden ...');
+ halt(1);
+ end;
+ for k:=m+1 to length(sicherung)-1 do // ... wird eine noch vorhandene Kante gelöscht ...
+ sicherung[k-1]:=sicherung[k];
+ setlength(sicherung,length(sicherung)-1);
+ entferneBlaetter(sicherung); // ... und dann die Blätter entfernt
+ end;
+ // jetzt sollte ein einziger, "neuer", Kreis verblieben sein
+ if pfadigkeit(sicherung,Kanten[sicherung[0]].x,Kanten[sicherung[0]].x)<>1 then begin
+ writeln('Die Pfadigkeit ist '+inttostr(pfadigkeit(sicherung,Kanten[sicherung[0]].x,Kanten[sicherung[0]].x))+' und nicht 1!');
+ writeln('Der Programmierer hat sich geirrt.'); // offenbar ist es kein einfacher Kreis :-/
+ halt(1);
+ end;
+ setlength(result,length(result)+1);
+ setlength(result[length(result)-1],length(sicherung));
+ for j:=0 to length(sicherung)-1 do
+ result[length(result)-1,j]:=sicherung[j];
+ exit;
+ end;
+
+ setlength(result,1); // es war der letzte Kreis
+ setlength(result[0],length(loeschung)+1);
+ for j:=0 to length(loeschung)-1 do
+ result[0,j]:=loeschung[j];
+ result[0,length(loeschung)]:=f[length(f)-1];
+
+ if pfadigkeit(result[0],Kanten[result[0,0]].x,Kanten[result[0,0]].x)<>1 then begin
+ writeln('Die Pfadigkeit ist '+inttostr(pfadigkeit(result[0],Kanten[result[0,0]].x,Kanten[result[0,0]].x))+' und nicht 1!');
+ writeln('Der Programmierer hat sich geirrt.'); // offenbar ist es kein einfacher Kreis :-/
+ writeln('f:');
+ dumpKantenArray(f);
+ writeln('result[0]:');
+ dumpKantenArray(result[0]);
+ writeln('loeschung:');
+ dumpKantenArray(loeschung);
+ halt(1);
+ end;
+end;
+
+// tSortObject *****************************************************************
+
+constructor tSortObject.create;
+begin
+ inherited create;
+ oG:=nil;
+ oMM:=nil;
+ oMF:=nil;
+ oFF:=nil;
+ oV:=nil;
+ fillchar(ID,sizeof(ID),#0);
+ ID:='';
+end;
+
+procedure tSortObject.assign(g: tGenerikum);
+begin
+ oG:=g;
+ oMM:=nil;
+ oMF:=nil;
+ oFF:=nil;
+ oV:=nil;
+ ID:=sortStringFromObject(g);
+end;
+
+procedure tSortObject.assign(i: tMMInteraktion);
+begin
+ oG:=nil;
+ oMM:=i;
+ oMF:=nil;
+ oFF:=nil;
+ oV:=nil;
+ ID:=sortStringFromObject(oMM);
+end;
+
+procedure tSortObject.assign(i: tMFInteraktion);
+begin
+ oG:=nil;
+ oMM:=nil;
+ oMF:=i;
+ oFF:=nil;
+ oV:=nil;
+ ID:=sortStringFromObject(oMF);
+end;
+
+procedure tSortObject.assign(i: tFFInteraktion);
+begin
+ oG:=nil;
+ oMM:=nil;
+ oMF:=nil;
+ oFF:=i;
+ oV:=nil;
+ ID:=sortStringFromObject(oFF);
+end;
+
+procedure tSortObject.assign(v: tVerknuepfung);
+begin
+ oG:=nil;
+ oMM:=nil;
+ oMF:=nil;
+ oFF:=nil;
+ oV:=v;
+ ID:=sortStringFromObject(oV);
+end;
+
+// allgemeine Funktionen *******************************************************
+
+function sortStringFromObject(g: tGenerikum): string;
+begin
+ result:=g.ID;
+end;
+
+function sortStringFromObject(i: tMMInteraktion): string;
+begin
+ result:=pPersonToStr(i._Ps[0])+','+pPersonToStr(i._Ps[1]);
+end;
+
+function sortStringFromObject(i: tMFInteraktion): string;
+begin
+ result:=pPersonToStr(i._P)+','+pFamilieToStr(i._F);;
+end;
+
+function sortStringFromObject(i: tFFInteraktion): string;
+begin
+ result:=pFamilieToStr(i._Fs[0])+','+pFamilieToStr(i._Fs[1]);
+end;
+
+function sortStringFromObject(v: tVerknuepfung): string;
+begin
+ result:=pPersonToStr(v.outP);
+end;
+
+function sortiere(arr: tGenerikumArray): tGenerikumArray; overload; inline;
+var
+ saIn,saOut: tSortObjectArray;
+ i: longint;
+begin
+ setlength(saIn,length(arr));
+ for i:=0 to length(saIn)-1 do begin
+ saIn[i]:=tSortObject.create;
+ saIn[i].assign(arr[i]);
+ end;
+ saOut:=sortiere(saIn);
+ setlength(result,length(saOut));
+ for i:=0 to length(result)-1 do begin
+ result[i]:=saOut[i].oG;
+ saOut[i].free;
+ end;
+ setlength(saIn,0);
+ setlength(saOut,0);
+end;
+
+function sortiere(arr: tMMInteraktionArray): tMMInteraktionArray; overload; inline;
+var
+ saIn,saOut: tSortObjectArray;
+ i: longint;
+begin
+ setlength(saIn,length(arr));
+ for i:=0 to length(saIn)-1 do begin
+ saIn[i]:=tSortObject.create;
+ saIn[i].assign(arr[i]);
+ end;
+ saOut:=sortiere(saIn);
+ setlength(result,length(saOut));
+ for i:=0 to length(result)-1 do begin
+ result[i]:=saOut[i].oMM;
+ saOut[i].free;
+ end;
+ setlength(saIn,0);
+ setlength(saOut,0);
+end;
+
+function sortiere(arr: tMFInteraktionArray): tMFInteraktionArray; overload; inline;
+var
+ saIn,saOut: tSortObjectArray;
+ i: longint;
+begin
+ setlength(saIn,length(arr));
+ for i:=0 to length(saIn)-1 do begin
+ saIn[i]:=tSortObject.create;
+ saIn[i].assign(arr[i]);
+ end;
+ saOut:=sortiere(saIn);
+ setlength(result,length(saOut));
+ for i:=0 to length(result)-1 do begin
+ result[i]:=saOut[i].oMF;
+ saOut[i].free;
+ end;
+ setlength(saIn,0);
+ setlength(saOut,0);
+end;
+
+function sortiere(arr: tFFInteraktionArray): tFFInteraktionArray; overload; inline;
+var
+ saIn,saOut: tSortObjectArray;
+ i: longint;
+begin
+ setlength(saIn,length(arr));
+ for i:=0 to length(saIn)-1 do begin
+ saIn[i]:=tSortObject.create;
+ saIn[i].assign(arr[i]);
+ end;
+ saOut:=sortiere(saIn);
+ setlength(result,length(saOut));
+ for i:=0 to length(result)-1 do begin
+ result[i]:=saOut[i].oFF;
+ saOut[i].free;
+ end;
+ setlength(saIn,0);
+ setlength(saOut,0);
+end;
+
+function sortiere(arr: tVerknuepfungArray): tVerknuepfungArray; overload; inline;
+var
+ saIn,saOut: tSortObjectArray;
+ i: longint;
+begin
+ setlength(saIn,length(arr));
+ for i:=0 to length(saIn)-1 do begin
+ saIn[i]:=tSortObject.create;
+ saIn[i].assign(arr[i]);
+ end;
+ saOut:=sortiere(saIn);
+ setlength(result,length(saOut));
+ for i:=0 to length(result)-1 do begin
+ result[i]:=saOut[i].oV;
+ saOut[i].free;
+ end;
+ setlength(saIn,0);
+ setlength(saOut,0);
+end;
+
+function sortiere(arr: tSortObjectArray): tSortObjectArray;
+var
+ i: longint;
+ mi,ma: string;
+begin
+ setlength(result,length(arr));
+ if length(arr)=0 then exit;
+ mi:=arr[0].ID;
+ ma:=arr[0].ID;
+ for i:=0 to length(result)-1 do begin
+ result[i]:=arr[i];
+ if cmpStr(mi,arr[i].ID)>0 then
+ mi:=arr[i].ID;
+ if cmpStr(ma,arr[i].ID)<0 then
+ ma:=arr[i].ID;
+ end;
+ sortiere(result,0,length(result)-1,mi,ma);
+end;
+
+procedure sortiere(var arr: tSortObjectArray; von,bis: longint; mi,ma: string);
+var
+ li,re: longint;
+ pivot: string;
+ tmp: tSortObject;
+begin
+ if (von>=bis) or (mi=ma) then exit;
+ li:=von;
+ re:=bis;
+ pivot:=mitte(mi,ma);
+
+ while li<=re do begin
+ while (li<=re) and
+ (cmpStr(arr[li].ID,pivot)<=0) do
+ inc(li);
+ while (li<=re) and
+ (cmpStr(arr[re].ID,pivot)>=0) do
+ dec(re);
+ if li>=re then continue;
+ tmp:=arr[li];
+ arr[li]:=arr[re];
+ arr[re]:=tmp;
+ tmp:=nil;
+ inc(li);
+ dec(re);
+ end;
+ if li<>re+1 then begin
+ writeln('Fehler bei der Pivotisierung: li='+inttostr(li)+' und re='+inttostr(re));
+ halt;
+ end;
+ sortiere(arr,von,li-1,mi,pivot);
+ sortiere(arr,re+1,bis,pivot,ma);
+end;
+
+end.