/******************************************************************/
/* Touristendynamik V1.0                                          */
/*                                                                */
/* Ein vereinfachtes Computermodell , mit dem Ziel, die           */
/* langfristig gesehenen Auswirkungen auf ein vom Tourismus       */
/* wenig erschlossenes Gebiet darzustellen, wenn man versucht,    */
/* den Tourismus dieses Gebietes durch Werbung anzukurbeln.       */
/*                                                                */
/* Amiga-Version    © 3/1990 by Jens Köhler                       */
/*                              Dingelstedtstr. 5a                */
/*                              3510 Hann.Münden                  */
/*                              West Germany                      */
/*                                                                */
/* Hinweis: Dieses Programm ist frei kopierbar und darf nicht     */
/*          kommerziell vertrieben werden !!!                     */
/*                                                                */
/*                                                                */
/* Bemerkung: Tourist.h und ftoa.h werden noch benötigt !!        */
/*            Ausserdem wird eine Grafik im RAW-Format bei        */
/*            bedarf nachgeladen.(Dateiname = Tourist.pic)        */
/*                                                                */
/******************************************************************/


#include <exec/exec.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <intuition/intuition.h>
#include <math.h>
#include <libraries/dos.h>
#include <ftoa.h>
#include <Tourist.h>


#define XRANGE 580     /* Max. Abzissengroesse der Zustandsgrafik */
#define YRANGE 185     /* Max. Ordinatengroesse der Zustandsgrafik */
#define XOFFSET 30     /* Linke Ecke der Zustandsgrafik */
#define YOFFSET 210    /* Untere Ecke der Zustandsgrafik */
#define UNULL 1        /* Anfangswert fuer Umwelt */
#define TNULL 1        /* Anfangswert fuer Touristenzahl */
#define AINV 1         /* Anfangswert fuer Infrastruktur */
#define DT 0.07        /* Zeitschritt fuer Raten */
#define ZSPRUNG 50     /* Bereich,wie lange die Simulation weiter(!) laeuft */

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Screen *Screen1;
struct Window *Window1,*Window2,*Window3;
struct RastPort *RPort,*RPort2,*RPort3;
struct IntuiMessage *nachricht,*GetMsg();


float Zeit,g=0.14,w=10.0,U,I,T; /* die wichtigen Groessen */
float Imax,Tmax,Umax;           /* Maxima der Zustandsgroessen */
float Uy,Iy,Ty;                 /* der relative Ordinatenfaktor */
int x;                          /* die "feste" X-Koordinate */
int Zmax=0;                     /* Zeitdauer des Simualtionsablaufes */
char *buffer[1];                /* wird fuer gcvt(); benoetigt */

BOOL ende=FALSE,pause=FALSE,schar=FALSE;
int class,code;

int message ();                /* die Vorwaertsdeklarationen */
void aufbau ();
void menu ();
void gadget ();
void RunModell ();
void PlotU();
void PlotI();
void PlotT();
void Zustand();
void PhaseUT();
void PhaseII();
void GGP();
void GGvonw ();
void Kreuz ();
void Beschrift1 ();
void Beschrift2 ();
void Beschrift3 ();
void ZeigDia();
void Info ();
void WarteW3 ();
void Parameter ();
void Titel();
void Reset ();
void Clean ();

/****************************************************************/
/* Ueberprueft Intuition-Nachrichten                            */
/* ------------------------------------------------------------ */
/* Eingabe-Parameter: keine                                     */
/* Rueckgabewert    : Nachricht-Class  oder NULL                */
/****************************************************************/

int message()
{
int nklasse=0;
struct IntuiMessage *n;

     n= GetMsg(Window1->UserPort);
     while(n)
       {
        nachricht= n;
        nklasse  = n->Class;
        code     = n->Code;
        ReplyMsg(n);
        n = GetMsg(Window1->UserPort);  /* die restlichen abfragen */
       }

return (nklasse);
}


/****************************************************************/
/* Bildschirmaufbau: Oeffnet alle wichtigen Libraries, Screen,  */
/* Windows etc.                                                 */
/* ------------------------------------------------------------ */
/* Eingabe-Parameter: keine                                     */
/* Rueckgabewert    : keine                                     */
/****************************************************************/

void aufbau ()
{
             /* Wozu abfragen ? Warum sollte es nicht da sein ? */
   GfxBase=(struct GfxBase*) OpenLibrary("graphics.library",0L);
   IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library",0L);

   Screen1 = (struct Screen *) OpenScreen (&NewScreen);

   NewWindow1.Screen=Screen1;   /* Zeiger auf den richtigen Screen */


   Window1 = (struct Window*) OpenWindow (&NewWindow1);

   RPort=Window1->RPort;
   SetMenuStrip (Window1,&Menu1);

   LoadRGB4(&Screen1->ViewPort,&Farben[0],4);
   RemakeDisplay ();    /* die neue Farbpalette darstellen */

   ftoa(w,Gadget2SIBuff,4); /* Werbung */
   ftoa(g,Gadget3SIBuff,4); /* Gewinnanteil */

   OffGadget(&Gadget1,Window1,NULL); /* Weiter-Gadget erstmal deaktivieren */
}

/****************************************************************/
/* Ruft das Unterprogramm des angewaehlten Menuepunktes auf     */
/* ------------------------------------------------------------ */
/* Eingabe-Parameter: keine                                     */
/* Rueckgabewert    : keine                                     */
/****************************************************************/

void menu()
{

  if(MENUNUM(code) != MENUNULL)
    switch(MENUNUM(code))
      {
       case  0: switch(ITEMNUM(code))      /* Optionen */
                  {

                   case  0: Info();        /* Info */
                            break;

                   case  1: OffGadget(&Gadget1,Window1,NULL);  /* Weiter-Gadget deaktivieren */
                            RunModell(0);  /* Neustart Simulation */
                            break;

                   case  2: Parameter();   /* Modellparameter */
                            break;

                   case  3: PhaseUT(Zmax); /* Phasendiagramm */
                            break;

                   case  4: GGvonw();      /* Gleichgewicht von w */
                            break;

                   case  5: ZeigDia();    /*  Simulationsdiagramm */
                            break;

                   case  6: PhaseII();;     /* Programm beenden */
                            break;



                  }; /* case */
                break;


      }; /* switch */
}

/****************************************************************/
/* Ruft das Unterprogramm des angewaehlten Gadgets auf          */
/* ------------------------------------------------------------ */
/* Eingabe-Parameter: die letzte aktuelle Intuition-Nachricht   */
/* Rueckgabewert    : keine                                     */
/****************************************************************/
void gadget ()
{
  struct Gadget *igad;
  int id;

  igad = (struct Gadget *) nachricht->IAddress;
  id = igad->GadgetID;


    switch(id)
     {
       case 2:
              Zmax+=ZSPRUNG;            /* Weiter-Gadget */
              RunModell(Zmax);
              break;

     };
}


/****************************************************************/
/* Starte das Simulationsmodell                                 */
/* ------------------------------------------------------------ */
/* Eingabe-Parameter: Zeitpunkt des Simulationsablaufes         */
/* Rueckgabewert    : keine                                     */
/****************************************************************/

void RunModell(start)
int start;
{

if (start == 0)  Reset ();

     Clean();
     Titel("Ich berechne die drei Zustandsgrößen in Abhängigkeit von der Zeit");
     Kreuz();

   for (Zeit=start; Zeit<start+ZSPRUNG ; Zeit+=DT) /* Das Maximum suchen */
       {
        Zustand();
       }

   Ty = (YRANGE-1)/Tmax; /* an Zustandsgrafik anpassen */
   Iy = (YRANGE-1)/Imax;
   Uy = (YRANGE-1)/Umax; /* Umwelt hat das Intervall [0,1] */


  x=XOFFSET+XRANGE-1;      /* Die feste X-Koordinate */


  Beschrift1();            /* Achsenbeschriftung */
  Beschrift2();


  if (start == 0) Reset(); /* Bei Neustart */

  for (Zeit=start; Zeit<start+ZSPRUNG ; Zeit+=DT)
      {
       ScrollRaster(RPort,1,0,XOFFSET+1,YOFFSET-YRANGE+1,XOFFSET+XRANGE-1,YOFFSET-1);
       Zustand();
       PlotU();              /* Grafik ausgeben */
       PlotI();
       PlotT();
      }

  OnGadget(&Gadget1,Window1,NULL); /* Nach Durchlauf Weiter-Gadget freigeben */

}


/****************************************************************/
/* Grafische Ausgabe der Zustandsgroesse U                      */
/* ------------------------------------------------------------ */
/* Eingabe-Parameter: keine                                     */
/* Rueckgabewert    : keine                                     */
/****************************************************************/

void PlotU()
{
int y;

   y=YOFFSET-Uy*U;  /* Uy*U eigentlich nicht noetig da U=[0,1] */

     SetAPen(RPort,1);
     WritePixel(RPort,x,y);
}

/****************************************************************/
/* Grafische Ausgabe der Zustandsgroesse T                      */
/****************************************************************/

void PlotT()
{
int y;

   y=YOFFSET-Ty*T;

     SetAPen(RPort,2);
     WritePixel(RPort,x,y);
}

/****************************************************************/
/* Grafische Ausgabe der Zustandsgroesse I                      */
/****************************************************************/

void PlotI()
{
int y;

   y=YOFFSET-Iy*I;

     SetAPen(RPort,3);
     WritePixel(RPort,x,y);

}


/****************************************************************/
/* Berechnet die Zustandsgroessen U,T,I als Funktion der Zeit   */
/* ------------------------------------------------------------ */
/* Eingabe-Parameter: keine                                     */
/* Rueckgabewert    : keine                                     */
/****************************************************************/

void Zustand()
{
float URate,IRate,TRate;

    URate=U*(0.1*g*T*U*U+(0.2*g*I-1.1*g*T-1)*U+g*T-0.2*g*I-0.1*T+1);
    IRate=I*(0.06*g-0.16)+0.3*T*(1-0.1*U-g+0.1*g*U);
    TRate=-0.5*T+0.5*w*U*I;

    U=U+DT*URate;
    T=T+DT*TRate;
    if (T>Tmax) Tmax=T;

    I=I+DT*IRate;
    if (I>Imax) Imax=I;

}

/****************************************************************/
/* Stellt  U und T als Phasendiagramm dar - also f(U)=T         */
/* ------------------------------------------------------------ */
/* Eingabe-Parameter: Zeitpunkt des Simulationsablaufes         */
/* Rueckgabewert    : keine                                     */
/****************************************************************/

void PhaseUT(start)
int start;
{
float Ualt,Talt;
int x1,y1,x2,y2;

if (schar == FALSE)
{
  Clean();
  Titel("Ich berechne das Phasendiagramm Umwelt-Touristenanzahl");
  Kreuz();


   SetAPen (RPort,1);                         /* die Achsenbezeichnungen */
   Move (RPort,XOFFSET-10,YOFFSET-YRANGE+10);
   Text (RPort,"U",1);

   SetAPen (RPort,2);
   Move (RPort,XOFFSET+XRANGE-124,YOFFSET+9);
   Text (RPort,"-> Touristenanzahl",18);
}
    if(start == 0) Reset();

  for (Zeit=start; Zeit<start+ZSPRUNG ; Zeit+=DT) /* Das Maximum suchen */
      {
       Zustand();
      }

    Ty = (XRANGE-1)/Tmax;
    Uy = (YRANGE-1)/Umax;

  Beschrift1();

  SetAPen(RPort,3);

  if(start == 0) Reset();

  for (Zeit=start; Zeit<start+ZSPRUNG ; Zeit+=DT)
    {
     Ualt=U;
     Talt=T;
     Zustand ();

     x1=Ty*Talt+XOFFSET;
     y1=YOFFSET-Ualt*YRANGE;

     x2=Ty*T+XOFFSET;
     y2=YOFFSET-U*YRANGE;

     Move(RPort,x1,y1);
     Draw(RPort,x2,y2);
   }

}

/****************************************************************/
/* Stellt  U und T als Phasendiagramm/Schar dar, w wird von 0   */
/* bis 10 durchlaufen                                           */
/* ------------------------------------------------------------ */
/* Eingabe-Parameter: Zeitpunkt des Simulationsablaufes         */
/* Rueckgabewert    : keine                                     */
/****************************************************************/

void PhaseII()
{
float walt;

   Clean();
   Titel("Ich berechne das Phasendiagramm/Schar Umwelt-Touristenanzahl");
   Kreuz();   

   SetAPen (RPort,2);
   Move (RPort,XOFFSET+XRANGE-124,YOFFSET+9);
   Text (RPort,"-> Touristenanzahl",18);


   walt=w;
   schar=TRUE;
   
   for (w=0; w<10 ; w+=0.5)
   {
   PhaseUT(0);
   }
    
w=walt;
schar=FALSE;

}
/****************************************************************/
/* Berechnet die Gleichgewichtspunkte U,I und T als Funktion    */
/* der Werbung                                                  */
/* ------------------------------------------------------------ */
/* Eingabe-Parameter1 : gew  := Gewinnanteil-Faktor (0...1)     */
/* Eingabe-Parameter2 : werb := Grad der Werbung (0..10)        */
/* Rueckgabewert      : keine                                   */
/****************************************************************/

void GGP(gew,werb)
float gew,werb;
{
float hilf;

    hilf= 25-( (6*g-16)/(3*w*(g-1)) );

    if (hilf < 0 )
        {
          pause=TRUE;
          return;
         }
       else pause=FALSE;

    U=5+sqrt(hilf);           /* mathematisch richtig waere  */
                              /* eigentlich U=5+-sqrt(hilf); */
    if (U<0 )
      {
       U=0;
       pause=TRUE;
       return;
      }
       else pause = FALSE;
    if (U>Umax ) Umax=U;


    I=(10*(U-1))/(U*(g*(2+w*(10+U*(U-1)))-w));
    if (I<0)
      {
       I=0;
       pause = TRUE;
       return;
      }
       else pause = FALSE;
    if (I>Imax) Imax=I;


    T=U*I*w;
    if (T<0)
     {
      T=0;
      pause = TRUE;
     }
       else pause =FALSE;



}

/****************************************************************/
/* Zeichnet die Gleichgewichtspunkte U,I und T als Funktion der */
/* Werbung                                                      */
/* ------------------------------------------------------------ */
/* Eingabe-Parameter2 : keine                                   */
/* Rueckgabewert      : keine                                   */
/****************************************************************/

void GGvonw()
{
float stepx;
float walt;

Clean ();
Imax=Umax=Tmax=1;

    Titel("Ich berechne die Gleichgewichtspunkte in Abhängigkeit von der Werbung");
    Kreuz();

    walt=w; /* Rette w */

    for (w=0; w<10 ; w+=0.04)  /* Suche Maxima */
        {
         GGP(g,w);
        }


    stepx=(XRANGE-2)/250;

    Uy=(YRANGE-1)/Umax;
    Ty=(YRANGE-1)/Tmax;
    Iy=(YRANGE-1)/Imax;

    SetAPen (RPort,1);
    Move (RPort,XOFFSET+XRANGE-40,YOFFSET+9);
    Text (RPort,"-> w",4);

    Beschrift3();

    x=XOFFSET+1;

    for (w=0 ; w<10 ; w+=0.04)
        {
         GGP(g,w);
         if (pause== FALSE)
           {
            PlotU();
            PlotT();
            PlotI();
           }
         x+=stepx;
        }

 w=walt; /* w zurueck */

}


/****************************************************************/
/* Zeichnet ein Koordinatenkreuz im Form eines Rechteckes       */
/* ------------------------------------------------------------ */
/* Eingabe-Parameter: keine                                     */
/* Rueckgabewert    : keine                                     */
/****************************************************************/

void Kreuz()
{

  SetAPen(RPort,0);  /* Fuell-Farbe = Hintergrund */
  SetOPen(RPort,1);      /* Umrandungsfarbe */
  RectFill(RPort,XOFFSET,YOFFSET-YRANGE,XOFFSET+XRANGE,YOFFSET);
  BNDRYOFF(RPort);  /* SetOPen rueckgaengig */

}




/****************************************************************/
/* Ist bei RunMod. PhaseUT & GGP fuer die Achsenbeschr. etc.    */
/* zustaendig                                                   */
/* ------------------------------------------------------------ */
/* Eingabe-Parameter: keine                                     */
/* Rueckgabewert    : keine                                     */
/****************************************************************/

void Beschrift1() /* RunModell & PhaseUT */
{
char Ausgabe[40],Max[10];

  SetAPen (RPort,1);                    /* Zeit */
  Move (RPort,XOFFSET,YOFFSET+8);
  strcpy (Ausgabe,"Zeit ");
  itoa (Zmax,Max);
  strcat(Ausgabe,Max);
  strcat(Ausgabe," bis ");
  itoa (Zmax+ZSPRUNG,Max);
  strcat(Ausgabe,Max);
  strcat(Ausgabe," Einheiten");
  Text (RPort,Ausgabe,strlen(Ausgabe));


     SetAPen (RPort,1);                            /* Ordinate */
     Move (RPort,XOFFSET-10,YOFFSET-YRANGE+10);
     Text (RPort,"U",1);

     Move (RPort,XOFFSET,YOFFSET+16);              /* Umwelt */
     Text (RPort,"Umwelt mit dem Intervall [0,1]",30);

     SetAPen (RPort,2);
     Move (RPort,XOFFSET,YOFFSET+24);              /* Touristen */
     strcpy(Ausgabe,"Touristenanzahl von 0 bis ");
     ftoa (Tmax,Max,4);
     strcat(Ausgabe,Max);
     Text(RPort,Ausgabe,strlen(Ausgabe));


     SetAPen (RPort,1);
     Move (RPort,XOFFSET,YOFFSET+40);           /* Parameter */
     strcpy(Ausgabe,"GAnteil (g)=");
     ftoa(g,Max,4);
     strcat(Ausgabe,Max);
     strcat(Ausgabe,"  Werbung (w)=");
     ftoa(w,Max,4);
     strcat(Ausgabe,Max);
     Text(RPort,Ausgabe,strlen(Ausgabe));

}


void Beschrift2() /* RunModell */
{
char Ausgabe[40],Max[10];

     SetAPen (RPort,2);
     Move (RPort,XOFFSET-18,YOFFSET-YRANGE+19);
     Text (RPort,"^T",2);

     SetAPen (RPort,3);
     Move (RPort,XOFFSET-18,YOFFSET-YRANGE+28);
     Text (RPort,"|I",2);
     Move (RPort,XOFFSET,YOFFSET+32);              /* Infra */
     strcpy(Ausgabe,"Infrastruktur von 0 bis ");
     ftoa (Imax,Max,4);
     strcat(Ausgabe,Max);
     Text(RPort,Ausgabe,strlen(Ausgabe));


     SetAPen (RPort,1);                            /* Abzisse */
     Move (RPort,XOFFSET+XRANGE-90,YOFFSET+8);
     Text (RPort,"-> Zeit",7);

}

void Beschrift3() /* GGP */
{
char Ausgabe[40],Max[10];

     SetAPen (RPort,1);                            /* Ordinate */
     Move (RPort,XOFFSET-10,YOFFSET-YRANGE+10);
     Text (RPort,"U",1);
     Move (RPort,XOFFSET,YOFFSET+16);              /* Umwelt */
     strcpy (Ausgabe,"Umwelt 0 bis ");
     ftoa (Umax,Max,4);
     strcat(Ausgabe,Max);
     Text (RPort,Ausgabe,strlen(Ausgabe));

     SetAPen (RPort,2);
     Move (RPort,XOFFSET,YOFFSET+24);              /* Touristen */
     strcpy(Ausgabe,"Touristenanzahl von 0 bis ");
     ftoa (Tmax,Max,4);
     strcat(Ausgabe,Max);
     Text(RPort,Ausgabe,strlen(Ausgabe));
     Move (RPort,XOFFSET-18,YOFFSET-YRANGE+19);
     Text (RPort,"^T",2);

     SetAPen (RPort,3);
     Move (RPort,XOFFSET-18,YOFFSET-YRANGE+28);
     Text (RPort,"|I",2);
     Move (RPort,XOFFSET,YOFFSET+32);              /* Infra */
     strcpy(Ausgabe,"Infrastruktur von 0 bis ");
     ftoa (Imax,Max,4);
     strcat(Ausgabe,Max);
     Text(RPort,Ausgabe,strlen(Ausgabe));

}


/*************************************************************************/
/* Einlesen und darstellen des Simulations-Diagrammes im Bitmap-Format   */
/* --------------------------------------------------------------------- */
/* Uebergabe-Parameter : keine                                           */
/* Rueckgabe-Werte     : keine                                           */
/*************************************************************************/

void ZeigDia()
{
struct BitMap *ptr;
int i;
ULONG datei;
UBYTE *puffer[4];
USHORT Dunkel[] = {0,0,0,0};

  LoadRGB4(&Screen1->ViewPort,&Dunkel[0],4);  /* DISPLAY OFF */
  RemakeDisplay ();


  NewWindow3.Screen=Screen1;

  Window3 = (struct Window*) OpenWindow (&NewWindow3);

  RPort3=Window3->RPort;


   datei = Open("Tourist.pic",MODE_OLDFILE);   /* Datei oeffnen */
   if (datei == NULL)
     {
      CloseWindow(Window3);
      LoadRGB4(&Screen1->ViewPort,&Farben[0],4);  /* DISPLAY ON */
      RemakeDisplay ();
      return;
     }

    ptr = RPort->BitMap;   /* Zeiger auf BitMAP-Anfang ermitteln */

  for (i=0 ; i<2 ; i++)
   {
    puffer[i] = ptr->Planes[i];     /* Zeiger auf BitPlanes ermitteln */
    Read(datei,puffer[i],20480);  /* Datei einladen, Bitplanegroesse = 20480 */
   }

  Close(datei);
  LoadRGB4(&Screen1->ViewPort,&Farben[0],4);  /* DISPLAY ON */
  RemakeDisplay ();
  WarteW3();
  CloseWindow (Window3);
}

/*************************************************************************/
/* Ausgabe des Infotextes                                                */
/* --------------------------------------------------------------------- */
/* Uebergabe-Parameter : keine                                           */
/* Rueckgabe-Werte     : keine                                           */
/*************************************************************************/

void Info()
{
int len,i,ii,y=0;

char *info1[140]={
"Touristendynamik V1.0",
"",
"Amiga-Version    © 3/1990 by Jens Köhler       ",
"                             Dingelstedtstr. 5a",
"                             3510 Hann.Münden  ",
"                             West Germany      ",
"",
"Hinweis: Dieses Programm ist frei kopierbar und darf nicht",
"         kommerziell vertrieben werden !!!                ",
"",
"",
"**** Wer oder was ist Touristendynamik ? ****",
"",
"Touristendynamik  wurde  von einer Gruppe von Leuten der Gesamthochschule",
"Kassel  im  Seminar  >Modellbildung und Simulation< im WS 89/90 bei Herrn",
"Prof.   Dr.   Ing.   Hartmut  Bossel  entwickelt.   Aufgabe  war  es, ein",
"einfaches   Modell   zu  erstellen,  welches  die  langfristig  gesehenen",
"Auswirkungen  auf ein vom Tourismus wenig erschlossenes Gebiet darstellt,",
"wenn  man  versucht, den  Tourismus  dieses  Gebietes durch Werbung anzu-",
"kurbeln.    Das  Modell  befaßt  sich  in  dieser  Hinsicht  mit  den   3",
"Zustandsstandsgrößen  Umwelt,  Touristenanzahl  und Grad  der Infrastruk-",
"tur.   Der  Grad  der  Infrastruktur wird in diesem Modell so betrachtet,",
"daß  ein  hoher  Grad nicht gleichbedeutend  ist mit hoher Attraktivität,",
"wie  es  ja  an einigen Orten mit Massentourismus üblich ist, sondern die",
"Idylle des Ortes steht vielmehr im Vordergrund.                          ",
"",
"Der  Anwender  hat  die  Möglichkeit den Grad der Werbung und den Gewinn-",
"anteil,  d.h.   wieviel  vom erwirtschafteten Gewinn wieder in die Umwelt",
"gesteckt werden soll, zu variieren und deren Auswirkungen zu untersuchen.",
"",
"Dieses Touristenmodell wurde bereits in einfacherer Ausführung mit PROSIM",
"unter  TURBO-Pascal  und  mit DYSAS unter GW-Basic getestet.  Interessant",
"ist  die  Tatsache,  daß  auch andere von H.  Bossel frühere  entwickelte",
"Touristenmodelle ein ähnliches Systemverhalten gezeigt haben.            ",
"",
"**** Wie wurde TOURISTENDYNAMIK entwickelt ? ****",
"",
"Dieses  Programm  ist ein Beispiel dafür, wie Simualtionen bzw.  komplexe",
"dynamische  Prozeße  in  der  Technik,  Ökologie,  Physik, Chemie und der",
"Psychologie  in Modellen dargestellt und dann auf den Computer übertragen",
"werden können.                                                           ",
"Dazu ganz kurz zur Vorgehensweise:Zuerst wird in der Regel ein Wortmodell",
"erstellt.  Daraus entsteht dann ein Wirkungsdiagramm, welches dem darauf-",
"folgendem Simualtionsdiagramm sehr ähnlich sieht. Das Simulationsdiagramm",
"zu TOURISTENDYNAMIK z.B.  ist unter dem vorletzten Menüpunkt zu sehen.   ",
"",
"Aus dem Simulationsdiagramm werdem dann folgende Gleichungen ablesen:",
"UDEG    = UMWELT*TOURIST*.1",
"IKOST   = .2*INFRA         ",
"TEIN    = TOURIST          ",
"UKOST   = UDEG             ",
"NETEIN  = TEIN-UKOST-IKOST ",
"UINVEST = GANTEIL*GEWINN   ",
"HILF    = 1+UINVEST        ",
"UABW    = 1-UMWELT         ",
"NREG    = UABW*UMWELT*HILF ",
"ATTRAK  = WERB*UMWELT*INFRA",
"TZU     = .5*ATTRAK        ",
"TB      = .5*TOURIST       ",
"IANTEIL = 1-GANTEIL        ",
"INVEST  = GEWINN*IANTEIL   ",
"IAUF    = .3*INVEST        ",
"ZERFALL = .1*INFRA         ",
"",
"Daraus folgen die Ratengleichungen",
"",
"UMWELT = UMWELT+DT*(NREG-UDEG)  ",
"TOURIST= TOURIST+DT*(TZU-TB)    ",
"INFRA  = INFRA+DT*(IAUF-ZERFALL)",
"",
"Diese Gleichungen können auch zusammengefaßt werden zu:",
"",
"URate = U*(0.1*g*T*U*U+(0.2*g*I-1.1*g*T-1)*U+g*T-0.2*g*I-0.1*T+1)",
"IRate = I*(0.06*g-0.16)+0.3*T*(1-0.1*U-g+0.1*g*U)                ",
"TRate = -0.5*T+0.5*w*U*I                                         ",
"",
"U=U+DT*URate",
"T=T+DT*TRate",
"I=I+DT*IRate",
"",
"Das sind die im Programm von TOURISTENDYNAMIK verwendeten Gleichungen.",
"",
"Anhand  dieser  Gleichungen  lassen  sich nun Aussagen z.B.  über Gleich-",
"gewichtspunkte und Eigenarten des Modells (stabil, instabil etc.) machen.",
"Dazu  sind aber umfangreiche Berechnungen über Differentiale und Matrizen",
"nötig, deren Darstellung hier zu weit führen würde.                      ",
"",
"**** Kurzanleitung zu TOURISTENDYNAMIK V1.0 *****",
"",
"1. Info:",
"Hier können die eben gesehenen  Informationen nochmal  aufgerufen werden.",
"",
"2. Neustart Simulation:",
"Hier   wird  der  Simulationsablauf  bei  Zeit=0  mit  den  eingestellten",
"Parametern  gestartet.  Es wird der Verlauf aller Zustandsgrößen gezeigt.",
"Sollte  einmal  eine  oder  mehrere  Zustandsgrößen  fehlen, so liegt das",
"daran,  daß  bei der  Vorberechnung dieser Zustandsgrößen Zahlenbereichs-",
"überschreitungen  stattgefunden  haben.   Das  kann aber auch während des",
"Ablaufes  passieren !  Dieser 'Fehler' tritt besonders schnell bei g>0.14",
"und  höherer  Werbung auf.  Wird das 'WEITER'-Gadget gedrückt, so erfolgt",
"ein Simulationsdurchlauf für die nächsten 50 Zeiteinheiten.  Anschließend",
"kann man sich dann auch das entsprechende Phasendiagramm UT anschauen.   ",
"",
"3. Modellparameter:",
"Hier können die Modellparameter Gewinnanteil (g) und die Werbung (w) ver-",
"ändert  werden.  Für w sind laut Simulationsdiagramm eigentlich nur Werte",
"von  0 bis 10 und für g Werte zwischen 0 und 1 erlaubt.  Eine Überprüfung",
"der   eingegebenen   Zahlen   findet   nicht  statt.   Zufriedenstellende",
"Ergebnisse lassen sich aber in der Regel für 0< g <= 0.14 erzielen.      ",
"",
"4. Phasendiagramm UT:",
"Hier  werden  U  und  T  als  Phasendiagramm  dargestellt.   Entsteht als",
"Phasendiagramm eine Art geschlossener Kreis (z.B.  für w=8 und g=0.13) so",
"schwingt das System.  Entsteht eine Art 'Schnecke', so handelt es sich um",
"eine gedämpfte Schwingung (w=8, g=0.11).                                 ",
"",
"5. Gleichgewicht w",
"Hier  werden die Gleichgewichtspunkte des Systems als Funktion von w dar-",
"gestellt  ( g  kann  über  Modellparameter  verändert  werden  ! ).   Ein",
"Gleichgewichtspunkt  ist  dann erreicht, wenn die drei Zustandsgrößen auf",
"feste Werte zulaufen.  Bei der Voreinstellung z.B.  (w=10, g=0.14) findet",
"eine  Zusammenbruch  des  Systems  statt,  d.h.   hier  liegen  die  drei",
"Gleichgewichtspunkte alle bei null.                                      ",
"",
"6. Simualtionsdiagramm",
"Hier  wird  das  Simulationsdiagramm von TOURISTENDYNAMIK angezeigt.  Die",
"Grafik  wird  nachgeladen. Hierzu muß  die Datei TOURIST.PIC im aktuellen",
"(!) Verzeichniss stehen.                                                 ",
"",
"7. PhaseUT-Schar",
"Hier der Parameter w von 0 bis 10 durchlaufen  und  dann jeweils das Pha-",
"sendiagramm gezeichnet. Es entsteht eine Schar von Kurven.               ",
"ACHTUNG !  BENÖTIGT LANGE RECHENZEITEN !!!",
"",
"**** Schlußwort ****",
"",
"Zum Schluß noch meinen Dank an Hagen Kähny, mit dem ich die umfangreichen",
"Berechnungen  durchgeführt habe, Rainer Umbach für die ftoa()-Rotine  und",
"Helmut Hauff für die Hilfestellungen.                                    ",
"                                             Hann.Münden, 14. April 1990 "
};



  NewWindow3.Screen=Screen1;
                                    /* Window oeffnen */
  Window3 = (struct Window*) OpenWindow (&NewWindow3);

  RPort3=Window3->RPort;


  for (ii=0; ii<7; ii++) /* Sieben Textseiten */
   {
    for (i=ii*20;i<ii*20+20;i++,y++) /* info1 */
        {
         len = 320-TextLength(RPort3,info1[i],strlen(info1[i]))/2;
         Move (RPort3,len,y*9+20); /* Mittig ausgeben */
         Text (RPort3,info1[i],strlen(info1[i]));
        }
    SetAPen(RPort3,2);
    Move (RPort3,XOFFSET,y*9+35);
    Text (RPort3,"--> Bitte linken Mausknopf drücken",34);
    y=0;
    WarteW3();
    WarteW3();
    SetAPen(RPort3,0);  /* Fuell-Farbe = Hintergrund */
    RectFill(RPort3,3,10,633,251); /* Und loeschen */
    SetAPen(RPort3,3);
   }

  CloseWindow (Window3);

}


/*************************************************************************/
/* Wartet auf Mausklick in Window3                                       */
/* --------------------------------------------------------------------- */
/* Uebergabe-Parameter : keine                                           */
/* Rueckgabe-Werte     : keine                                           */
/*************************************************************************/

void WarteW3 ()
{

 for (;;)
 {
   Wait(1L<<Window3->UserPort->mp_SigBit);  /* Is irgendwas da ?? */

    nachricht = GetMsg(Window3->UserPort);

   while (nachricht)
     {
      class = nachricht->Class;
      ReplyMsg(nachricht);
      nachricht = GetMsg(Window3->UserPort);

     }
      if(class == MOUSEBUTTONS)
        {
         return;
        }

  }

}


/*************************************************************************/
/* Parameter des Modells eingeben                                        */
/* --------------------------------------------------------------------- */
/* Uebergabe-Parameter : keine                                           */
/* Rueckgabe-Werte     : keine                                           */
/*************************************************************************/

void Parameter()
{

  NewWindow2.Screen=Screen1;
  Window2 = (struct Window*) OpenWindow (&NewWindow2);

  RPort2=Window2->RPort;

  SetAPen(RPort2,1);
  Move (RPort2,125,55);
  Text (RPort2,"Grad der Werbung (0..10)",24);

  Move (RPort2,105,94);
  Text (RPort2,"Gewinnanteil in die Umwelt (0..1)",33);

   for (;;) /* Wartet auf CloseWindow von Window2 */
    {
      Wait(1L<<Window2->UserPort->mp_SigBit); /* Is irgendwas da ?? */

      nachricht = GetMsg(Window2->UserPort);
      while (nachricht)
         {
          class   = nachricht->Class;
          code    = nachricht->Code;
          ReplyMsg(nachricht);
          nachricht = GetMsg(Window2->UserPort);
         }

        if(class == CLOSEWINDOW)
          {
           w=atof(Gadget2SIBuff);  /* Werbung (0..10) */
           g=atof(Gadget3SIBuff);  /* Gewinnanteil (0..1) */
           Reset();                 /* fuer Neustart der Simulation */
           OffGadget(&Gadget1,Window1,NULL); /* Weiter-Gadget erstmal deaktivieren */
           class=0;
           CloseWindow (Window2);
           return;
          }

    }

}

/*************************************************************************/
/* Titel im Hauptwindow zu einer Grafik ausgeben                         */
/* --------------------------------------------------------------------- */
/* Uebergabe-Parameter : was := "Ueberschrift"                           */
/* Rueckgabe-Werte     : keine                                           */
/*************************************************************************/

void Titel (was)
char *was;
{

         SetAPen(RPort,1);
         Move (RPort,XOFFSET,20);
         Text (RPort,was,strlen(was));

}

/*************************************************************************/
/* Alle wichtigen Groessen zurueckstellen                                */
/* --------------------------------------------------------------------- */
/* Uebergabe-Parameter : keine                                           */
/* Rueckgabe-Werte     : keine                                           */
/*************************************************************************/

void Reset ()
{

   Tmax=Imax=Umax=1;       /* Umwelt hat das Intervall [0,1] */
   U=UNULL;                /* U,I,T auf Anfangswert */
   I=AINV;
   T=TNULL;
   Zmax=0;

}

/*************************************************************************/
/* Das Hauptwindow loeschen                                              */
/* --------------------------------------------------------------------- */
/* Uebergabe-Parameter : keine                                           */
/* Rueckgabe-Werte     : keine                                           */
/*************************************************************************/

void Clean()
{

  SetAPen(RPort,0);  /* Fuell-Farbe = Hintergrund */
  RectFill(RPort,3,10,633,251);
  RefreshGadgets(&Gadget1,Window1,NULL);

}


/****************************************************************/
/* Die MAIN-FUNKTION                                            */
/****************************************************************/

_main ()
{

aufbau ();   /* erstmal alles aufbauen */
ZeigDia();      /* und dann die Infos ausgeben */

 Move (RPort,148,130); /* Mittig ausgeben  */
 Text (RPort,"Nur zu !  Ich warte auf Reaktionen ......!?",43);


  while (ende == FALSE)                      
       {
        Wait(1L<<Window1->UserPort->mp_SigBit); /* Is was ?? */ 

        class=message ();
        if(class == MENUPICK) menu(); 
        if(class == GADGETUP) gadget ();
        if(class == CLOSEWINDOW) ende=TRUE;  /* Programm beenden */
       };


CloseWindow (Window1);   /* Alles wieder freigeben */
CloseScreen (Screen1);
CloseLibrary (GfxBase);
CloseLibrary (IntuitionBase);

}

