home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1991 / 09_10 / grdlagen / apfel.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1991-07-19  |  10.6 KB  |  337 lines

  1. (* ------------------------------------------------------ *)
  2. (*                     APFEL.PAS                          *)
  3. (*       Demonstrationsprogramm zur Verteilung von        *)
  4. (*     Rechenkapazitäten auf freie Netzwerk-PCs bei       *)
  5. (*      gemeinsamer Festplattenzugriffsmöglichkeit        *)
  6. (*                 Turbo Pascal ab 5.0                    *)
  7. (*          (c) 1991 Sven de Vries & TOOLBOX              *)
  8. (* ------------------------------------------------------ *)
  9. PROGRAM Mandel;
  10.  
  11. USES Dos, Crt, Graph;
  12.  
  13. CONST
  14.   DatenPfad  = 'K:\COMUNIC\';        { Pfad für gemeinsame }
  15.       { Kommunikationsdateien aller Rechner, ggf. anpassen }
  16.   Max        = 800;     { maximale Anzahl Punkte pro Zeile }
  17.   PausenZeit = 300;   { Pause zwischen zwei Datenzugriffen }
  18.   lux        = -2;    { x-Koord. links unten Apfelmännchen }
  19.   luy        = -1.25;           { linke unter y-Koordinate }
  20.   lx         = 4;                { X-Ausdehnung des Bildes }
  21.   ly         = 2.5;              { Y-Ausdehnung des Bildes }
  22.   MaxIter    = 100;    { max. Anzahl Iterationen pro Punkt }
  23.   nn         = 'NACHRICH.';     { Name der zu versendenden }
  24.                                                 { Arbeiten }
  25.   FarbAnzahl = 10;            { Anzahl verfügbarer Farben, }
  26.                                 { muß ggf. geändert werden }
  27.   MasterID   = 'A';                     { Name des Masters }
  28.  
  29. TYPE
  30.   Arbeit = RECORD
  31.              Feld : ARRAY [0..Max] OF INTEGER;
  32.                          { Zwischenspeicher für eine Zeile }
  33.              MaxX,                         { Spaltenanzahl }
  34.              yy   : INTEGER;                { Zeilennummer }
  35.              x,               { Realkoordinaten des ersten }
  36.              y,                        { Punktes der Zeile }
  37.              dx,       { Veränderung von x und y pro Pixel }
  38.              dy   : REAL ;
  39.              Mode : (Normal, Ende);         { Arbeitsmodus }
  40.            END;
  41.  
  42. VAR
  43.   OwnID                       : CHAR;
  44.                               { Name des eigenen Prozesses }
  45.   ProzessAnzahl               : INTEGER;
  46.   Anzahl_ausgegebener_Zeilen,
  47.   Naechste_Arbeits_Zeile      : INTEGER;
  48.   SpaltenMax, ZeilenMax       : INTEGER; { Grafikauflösung }
  49.   SchrittZahl                 : INTEGER;
  50.                 { Anzahl der Rechenaufträge dieses Sklaven }
  51.  
  52. PROCEDURE MakeMasterOn;
  53. VAR                { meldet an, daß ein Master im Netz ist }
  54.   F : FILE;
  55. BEGIN
  56.   Assign(F, DatenPfad + 'master.on'); ReWrite(F); Close(F);
  57. END;
  58.  
  59. PROCEDURE MakeMasterOff;            { meldet den Master ab }
  60. VAR
  61.   F : FILE;
  62. BEGIN
  63.   Assign(F, DatenPfad + 'master.on'); Erase(F);
  64. END;
  65.  
  66. FUNCTION IsMasterOn : BOOLEAN;
  67. BEGIN                  { testet, ob ein Master im Netz ist }
  68.   IsMasterOn := FSearch(DatenPfad + 'master.on', '') <> '';
  69. END;
  70.  
  71. PROCEDURE SetID(z : CHAR);
  72. VAR       { setzt den nächsten zu vergebenden Rechnernamen }
  73.   F : FILE OF CHAR;
  74. BEGIN
  75.   WHILE NOT((FSearch(DatenPfad + 'nr.id', '') = '')
  76.   AND (FSearch(DatenPfad + 'readallow.id', '') ='')) DO
  77.     Delay(PausenZeit);
  78.                  { wartet, bis niemand mehr Leserechte hat }
  79.   Assign(F, DatenPfad + 'nr.id');         { erst dann darf }
  80.   ReWrite(F);                         { geschrieben werden }
  81.   Write(F, z);
  82.   Close(F);
  83.   Assign(F, DatenPfad + 'readallow.id');
  84.   ReWrite(F);              { zuletzt allen Leserecht geben }
  85.   Close(F);
  86. END;
  87.  
  88. FUNCTION GetID : CHAR;   { holt einen eigenen Rechnernamen }
  89. VAR
  90.   i : CHAR;
  91.   F : FILE OF CHAR;
  92. BEGIN
  93.   REPEAT
  94.     WHILE FSearch(DatenPfad + 'readallow.id', '') = '' DO
  95.       Delay(PausenZeit);
  96.     Assign(F, DatenPfad + 'readallow.id');
  97.     {$I-} Erase(F); {$I+}
  98.   UNTIL IOResult = 0;   { wartet auf erfolgreiches Löschen }
  99.   Assign(F, DatenPfad + 'nr.id');
  100.      { nun besitzt dieser Prozeß die exklusiven Leserechte }
  101.   Reset(F); Read(F, i); Close(F); Erase(F);
  102.   GetID := i;
  103. END;
  104.  
  105. PROCEDURE DelID;  { löscht den nächsten Rechnernamen, kein }
  106. VAR            { weiterer Rechner kann sich noch einloggen }
  107.   i : CHAR;
  108.   F : FILE OF CHAR;
  109. BEGIN
  110.   IF FSearch(DatenPfad + 'readallow.id', '') <> '' THEN
  111.   BEGIN
  112.     Assign(F, DatenPfad + 'readallow.id'); Erase(F);
  113.   END;
  114.   IF FSearch(DatenPfad + 'nr.id', '') <> '' THEN BEGIN
  115.     Assign(F, DatenPfad + 'nr.id'); Erase(F);
  116.   END;
  117. END;
  118.  
  119. PROCEDURE SendeArbeit(VAR a : Arbeit;
  120.                       FromChar, ToChar : CHAR);
  121. VAR        { sendet eine Arbeit von "FromChar" an "ToChar" }
  122.   F                  : FILE OF Arbeit;
  123.   FileName, FileFlag : STRING;
  124. BEGIN
  125.   FileName := DatenPfad + nn + FromChar;
  126.   FileFlag := FileName + 'F' + ToChar;
  127.   FileName := FileName + 'D' + ToChar;
  128.   WHILE FSearch(FileFlag, '') <> '' DO
  129.     Delay(PausenZeit);    { warte, bis letzte Nachricht an }
  130.                                 { "ToChar" abgerufen wurde }
  131.   Assign(F, FileName);                { schreibe Nachricht }
  132.   ReWrite(F); Write(F, a); Close(F);
  133.   Assign(F, FileFlag);                   { erlaube Zugriff }
  134.   ReWrite(F); Close(F);
  135. END;
  136.  
  137. PROCEDURE LeseArbeit(VAR a : Arbeit;
  138.                      VAR FromChar : CHAR; ToChar : CHAR);
  139. { liest eine Arbeit von "FromChar" an "ToChar"; dabei
  140.   funktioniert auch "FromChar='?'". Setzt voraus, daß nur
  141.   "ToChar versucht, die Arbeit zu lesen                    }
  142. VAR
  143.   F                            : FILE OF Arbeit;
  144.   Gefunden                     : SearchRec;
  145.   FileName, FileFlag, FromStrg : STRING;
  146. BEGIN
  147.   FileFlag := DatenPfad + nn + FromChar + 'F' + ToChar;
  148.   Gefunden.Name := '';
  149.   FindFirst(FileFlag, AnyFile, Gefunden);
  150.   WHILE DosError <> 0 DO BEGIN    { warte, bis Lesezugriff }
  151.     Delay(PausenZeit);                       { erlaubt ist }
  152.     FindFirst(FileFlag, AnyFile, Gefunden);
  153.   END;
  154.   FileFlag := DatenPfad + Gefunden.Name;
  155.   FromStrg := Copy(Gefunden.Name,
  156.                    Length(Gefunden.Name) - 2, 1);
  157.   FromChar := FromStrg[1];
  158.   FileName := DatenPfad + nn + FromChar + 'D' + ToChar;
  159.   Assign(F, FileName); Reset(F); Read(F, a); Close(F);
  160.   Erase(F); Assign(F, FileFlag);
  161.   Erase(F); { lösche Fileflag als Signal für Absender, daß }
  162. END;               { eine neue Arbeit gesendet werden kann }
  163.  
  164. PROCEDURE MakeMasterAnmeldung;       { erledigt den Login- }
  165. VAR                { Vorgang für alle untergebenen Rechner }
  166.   z  : CHAR;
  167.   Kb : BOOLEAN;
  168. BEGIN
  169.   z := Succ(MasterID);
  170.   WriteLn('Anmeldung läuft, zum Beenden bitte ');
  171.   WriteLn('eine Taste drücken, nicht jedoch ');
  172.   WriteLn('bevor sich alle gestarteten ');
  173.   WriteLn('Prozesse angemeldet haben.');
  174.   REPEAT
  175.     SetID(z);
  176.     Kb := KeyPressed;
  177.     WHILE NOT Kb AND
  178.      (FSearch(DatenPfad + 'nr.id', '') <> '') DO BEGIN
  179.       Delay(PausenZeit); Kb := KeyPressed;
  180.     END;
  181.     IF NOT Kb THEN BEGIN
  182.       WriteLn ('Rechner ', z, ' eingeloggt');
  183.       Inc(z); Inc(ProzessAnzahl);
  184.     END;
  185.   UNTIL Kb;
  186.   WHILE KeyPressed DO z := (ReadKey);
  187.   WriteLn('Start...');
  188. END;
  189.  
  190. PROCEDURE InitArbeit(VAR a : Arbeit);
  191. VAR
  192.   i : INTEGER;
  193. BEGIN
  194.   WITH a DO BEGIN;
  195.     FOR i := 1 TO Max DO
  196.       Feld[i] := 0;
  197.     MaxX := SpaltenMax; yy := 0; x := lux; y := 0;
  198.     dx := lx / SpaltenMax; dy := ly / ZeilenMax;
  199.     Mode := Normal;
  200.   END;
  201. END;
  202.  
  203. PROCEDURE NeueArbeit(VAR StandardA, a : Arbeit);
  204. BEGIN                           { erzeugt eine neue Arbeit }
  205.   a := StandardA;
  206.   WITH a DO BEGIN
  207.     yy := Naechste_Arbeits_Zeile; y := luy + ly - yy * dy;
  208.   END;
  209.   Inc(Naechste_Arbeits_Zeile);
  210.   IF Naechste_Arbeits_Zeile = ZeilenMax THEN
  211.     StandardA.Mode := Ende;      { genug Zeilen produziert }
  212. END;
  213.  
  214. FUNCTION Iteriere(cr, ci : REAL) : INTEGER;
  215. VAR { führt die Apfelmänncheniteration für einen Punkt aus }
  216.   xr, x, xi : REAL;
  217.   i         : INTEGER;
  218. BEGIN
  219.   xr := 0; xi := 0; i  := 0;
  220.   WHILE (i < MaxIter) AND (xr * xr + xi * xi < 4) DO BEGIN
  221.     x  := xr * xr - xi * xi; xi := xr * xi * 2 + ci;
  222.     xr := x + cr; Inc(i);
  223.   END;
  224.   Iteriere := i;
  225. END;
  226.  
  227. PROCEDURE MacheArbeit(VAR a : Arbeit);
  228. VAR { führt die Apfelmänncheniterationen für einen Job aus }
  229.   x, y : REAL;
  230.   i    : INTEGER;
  231.   b    : LONGINT;
  232. BEGIN
  233.   y := a.y;
  234.   FOR i := 0 TO a.MaxX DO BEGIN
  235.     x := a.x + i * a.dx;
  236.     a.Feld[i] := Iteriere(x,y) MOD FarbAnzahl;
  237.   END;
  238. END;
  239.  
  240. PROCEDURE ArbeitAusgeben(a : Arbeit);
  241. VAR  { gibt das Ergebnis eines Jobs auf dem Bildschirm aus }
  242.   i : INTEGER;
  243. BEGIN
  244.   FOR i := 0 TO a.MaxX DO
  245.     PutPixel(i, ZeilenMax - a.yy, a.Feld[i]);
  246.   Inc(Anzahl_ausgegebener_Zeilen);
  247. END;
  248.  
  249. PROCEDURE SendeErsteArbeiten(StandardA : Arbeit);
  250. VAR       { gibt Arbeitsaufträge für alle anderen Prozesse }
  251.   z : CHAR;
  252.   a : Arbeit;
  253. BEGIN
  254.   FOR z := 'B' TO Chr(Ord(MasterID) + ProzessAnzahl - 1) DO
  255.   BEGIN
  256.     NeueArbeit(StandardA, a); SendeArbeit(a, OwnID, z);
  257.   END;
  258. END;
  259.  
  260. PROCEDURE InitGrafik;
  261. VAR
  262.   GrDriver, GrMode, ErrCode : INTEGER;
  263. BEGIN
  264.   DetectGraph(GrDriver, GrMode);
  265.   InitGraph(GrDriver, GrMode, GetEnv('BGIPATH'));
  266.   ErrCode := GraphResult;
  267.   IF ErrCode <> 0 THEN BEGIN
  268.     WriteLn('Fehler: ', GraphErrorMsg(ErrCode)); Halt(1);
  269.   END;
  270. END;
  271.  
  272. PROCEDURE Slave;
  273. VAR        { ruft alle Routinen mit Sklaventätigkeiten auf }
  274.   a  : Arbeit;
  275.   ch : CHAR;
  276. BEGIN
  277.   SchrittZahl := 0; OwnID := GetID;
  278.   WriteLn('Rechenknecht ', OwnID);
  279.   ch := MasterID;
  280.   WriteLn('Warte auf Daten ', SchrittZahl);
  281.   LeseArbeit(a, ch, OwnID);
  282.   WHILE a.Mode <> Ende DO BEGIN
  283.     Inc(SchrittZahl); WriteLn('Daten da, rechne... ');
  284.     MacheArbeit(a);
  285.     SendeArbeit(a, OwnID, MasterID);
  286.     WriteLn('Warte auf Daten ', SchrittZahl);
  287.     LeseArbeit(a, ch, OwnID);
  288.   END;
  289. END;
  290.  
  291. PROCEDURE Master;
  292. VAR         { ruft alle Routinen mit Mastertätigkeiten auf }
  293.   a, mY, StandardA : Arbeit;
  294.   z                : CHAR;
  295. BEGIN
  296.   ProzessAnzahl := 1;
  297.   MakeMasterOn;
  298.   WriteLn('Master');
  299.   OwnID := MasterID;
  300.   MakeMasterAnmeldung;
  301.   DelID;
  302.   InitGrafik;
  303.   ZeilenMax  := GetMaxY; SpaltenMax := GetMaxX;
  304.   InitArbeit(StandardA);
  305.   IF ProzessAnzahl = 1 THEN
  306.     REPEAT
  307.       a.Mode := Normal;
  308.       NeueArbeit(StandardA, a);
  309.       MacheArbeit(a);
  310.       ArbeitAusgeben(a);
  311.     UNTIL a.Mode = Ende
  312.   ELSE BEGIN
  313.     SendeErsteArbeiten(StandardA);
  314.     a.Mode := Normal;
  315.     REPEAT
  316.       z := '?';
  317.       LeseArbeit(mY, z, OwnID);
  318.       NeueArbeit(StandardA, a);
  319.       SendeArbeit(a, OwnID, z);
  320.       ArbeitAusgeben(mY);
  321.     UNTIL Anzahl_ausgegebener_Zeilen = ZeilenMax;
  322.   END;
  323.   REPEAT UNTIL KeyPressed;
  324.   CloseGraph;
  325.   MakeMasterOff;
  326. END;
  327.  
  328. BEGIN                                      { Hauptprogramm }
  329.   ClrScr;
  330.   Naechste_Arbeits_Zeile := 0;
  331.   Anzahl_ausgegebener_Zeilen := 0;
  332.   IF IsMasterOn THEN Slave
  333.                 ELSE Master;
  334. END.
  335. (* ------------------------------------------------------ *)
  336. (*                 Ende von APFEL.PAS                     *)
  337.