(*--------------------------------------------------------------------------
 :Program.    Statistik.mod
 :Author.     Marcus Stratmann
 :Address.    Böttcherstraße 13, D-4250 Bottrop-Kirchhellen
 :Phone.      02045/5191
 :Copyright.  Public Domain
 :Language.   MODULA-II
 :Translator. M2Amiga v3.3d
 :Imports.    typdefs, IntuiOps
 :History.    V1.0,  26-Sep-89
 :History.    V1.1,  16-May-90
 :Contents.   Displays information about goals and results
--------------------------------------------------------------------------*)

IMPLEMENTATION MODULE Statistik;   (* $S- $R- $V- $F- *)

FROM Conversions IMPORT ValToStr;
FROM Exec        IMPORT WaitPort, GetMsg, ReplyMsg;
FROM Graphics    IMPORT ScrollRaster;
FROM IntuiOps    IMPORT Fenster, WriteWin, WriteZahl, WriteRealZahl, Linie,
                        OeffneSpezFenster, SchliesseFenster, MyRequest,
                        InitGadget, KeineDaten, Beep;
FROM Intuition   IMPORT IDCMPFlags, IDCMPFlagSet, WindowFlags,
                        WindowFlagSet, Gadget, PropInfo, Image, propGadget,
                        GadgetFlags, GadgetFlagSet, ActivationFlags,
                        ActivationFlagSet, PropInfoFlags, PropInfoFlagSet,
                        IntuiMessagePtr, selectDown, RemoveGadget,
                        AddGadget;
FROM Storage     IMPORT ALLOCATE, DEALLOCATE, Available;
FROM Strings     IMPORT Insert, last;
FROM SYSTEM      IMPORT ADR;
FROM typdefs     IMPORT Namen, Daten, StatistikBerechnet, AnzMan;

CONST
  MaxAnzeige = 12;
  ToreOSX = 6;      (* Offsets *)
  ToreOSY = 34;
  HATorOSX = 27;
  HATorOSY = 158;
  AusgOSX = 395;
  AusgOSY = HATorOSY;
  RelTorOSX = 231;
  RelTorOSY = HATorOSY;
  SortTorOSX = 432;
  SortTorOSY = 41;


TYPE
  ToreRecord = RECORD
                 Anzahl, ID: CARDINAL;
               END;
  GameRecordPointer = POINTER TO GameRecord;
  GameRecord = RECORD
                 Heim, Gast: CARDINAL;
                 Next: GameRecordPointer;
               END;

VAR
  Tore: ARRAY[0..10],[0..10] OF CARDINAL;
  Tore2: ARRAY[0..120] OF ToreRecord;
  HeimTore, AuswTore, GsmtTore, HeimSiege, Unentschieden, AuswSiege,
    AnzahlSpiele, Ergebnisse, Stellungen: CARDINAL;
  ScrollGadget, ScrollGadget2: Gadget;
  ScrollInfo, ScrollInfo2: PropInfo;
  ScrollImage, ScrollImage2: Image;
  Message: IntuiMessagePtr;
  Class: IDCMPFlagSet;
  Code: CARDINAL;

PROCEDURE SortiereTore;

  VAR
    l, vgl, i, temp: CARDINAL;

  BEGIN
    l := 0;
    REPEAT
      vgl := l;
      FOR i := l + 1 TO 120 DO
        IF Tore2[i].Anzahl > Tore2[vgl].Anzahl THEN
          vgl := i;
        END;
      END;
      IF Tore2[vgl].Anzahl = 0 THEN
        Ergebnisse := l;
        RETURN;   (* Spart 'ne Menge Zeit, da viele Nullen vorhanden *)
      END;
      IF vgl # l THEN
        temp := Tore2[l].Anzahl;
        Tore2[l].Anzahl := Tore2[vgl].Anzahl;
        Tore2[vgl].Anzahl := temp;
        temp := Tore2[l].ID;
        Tore2[l].ID := Tore2[vgl].ID;
        Tore2[vgl].ID := temp;
      END;
      INC(l);
    UNTIL l = 120;
    Ergebnisse := 121;
  END SortiereTore;


PROCEDURE StatistikBerechnung;

  VAR
    HeimTor, GastTor: INTEGER;
    i, j: CARDINAL;

  BEGIN
    FOR i := 0 TO 10 DO
      FOR j := 0 TO 10 DO
        Tore[i,j] := 0;
      END;
    END;
    FOR i := 0 TO 120 DO
      Tore2[i].ID := i;
      Tore2[i].Anzahl := 0;
    END;
    HeimTore := 0;
    AuswTore := 0;
    HeimSiege := 0;
    Unentschieden := 0;
    AuswSiege := 0;
    FOR i := 1 TO AnzMan DO
      FOR j := 1 TO AnzMan DO
        HeimTor := Daten[i,0,j];
        IF HeimTor > -1 THEN
          GastTor := Daten[j,1,i];
          INC(HeimTore, HeimTor);
          INC(AuswTore, GastTor);
          IF HeimTor > GastTor THEN
            INC(HeimSiege);
          ELSIF HeimTor = GastTor THEN
            INC(Unentschieden);
          ELSE
            INC(AuswSiege);
          END;
          IF HeimTor > 10 THEN
            HeimTor := 10;
          END;
          IF GastTor > 10 THEN
            GastTor := 10;
          END;
          INC(Tore[HeimTor,GastTor]);
          INC(Tore2[HeimTor*11+GastTor].Anzahl);
        END;
      END;
    END;
    GsmtTore := HeimTore + AuswTore;
    AnzahlSpiele := HeimSiege + Unentschieden + AuswSiege;
    StatistikBerechnet := TRUE;
    SortiereTore;
  END StatistikBerechnung;


PROCEDURE ZeigeStatistik;

  VAR
    win: Fenster;
    i, j, zeile, Pos, AltPos: CARDINAL;
    GadPos: INTEGER;


  PROCEDURE ZeigeTore(start, alt: INTEGER);

    VAR
      HeimTor, GastTor, zeile: CARDINAL;
      i, diff: INTEGER;

    BEGIN
      i := start;
      diff := start - alt;
      IF ABS(diff) < MaxAnzeige THEN
        IF diff <= 0 THEN   (* scroll down *)
          zeile := SortTorOSY;
        ELSE
          i := i + MaxAnzeige - diff;
          zeile := (MaxAnzeige - diff) * 8 + SortTorOSY;
        END;
        ScrollRaster(win^.rPort, 0, 8 * diff, SortTorOSX, SortTorOSY - 6,
                     SortTorOSX + 144, MaxAnzeige * 8 +SortTorOSY - 7);
      ELSE
        zeile := SortTorOSY;
      END;
      REPEAT
        HeimTor := Tore2[i].ID DIV 11;
        GastTor := Tore2[i].ID MOD 11;
        WriteZahl(win, HeimTor, 2, SortTorOSX, zeile);
        IF HeimTor = 10 THEN
        WriteWin(win, SortTorOSX, zeile, " +");
        END;
        WriteWin(win, SortTorOSX + 16, zeile, ":      (     %)");
        WriteZahl(win, GastTor, -2, SortTorOSX + 24, zeile);
        IF GastTor = 10 THEN
          WriteWin(win, SortTorOSX + 24, zeile, "+ ");
        END;
        WriteZahl(win, Tore2[i].Anzahl, 2, SortTorOSX + 48, zeile);
        WriteRealZahl(win, FLOAT(Tore2[i].Anzahl) * 100.0 /
                      FLOAT(AnzahlSpiele), 4, 1, SortTorOSX + 80, zeile);
        INC(i);
        INC(zeile, 8);
      UNTIL (zeile > (MaxAnzeige - 1) * 8 + SortTorOSY) OR (i = alt) OR
            (Tore2[i].Anzahl = 0);
    END ZeigeTore;


  PROCEDURE BehandleGadget;

    BEGIN
      Pos := TRUNC(FLOAT(ScrollInfo.vertPot) / 65535.0 *
                   FLOAT(Stellungen - MaxAnzeige));
      IF Pos # AltPos THEN
        ZeigeTore(Pos, AltPos);
        AltPos := Pos;
      END;
    END BehandleGadget;


  PROCEDURE BehandleMouse;

    VAR
      xPos, yPos: INTEGER;
      SpielWin: Fenster;
      SpielListe: GameRecordPointer;
      count, SpielPos, AltSpielPos, Stellungen2: CARDINAL;
      Titel, add: ARRAY[0..15] OF CHAR;
      err: BOOLEAN;



    PROCEDURE ZeigeSpiele(start, alt: INTEGER);

      VAR
        Heim, Gast: CARDINAL;
        i, zeile, diff: INTEGER;
        Zeiger: GameRecordPointer;

      BEGIN
        diff := start - alt;
        IF ABS(diff) < 10 THEN
          IF diff <= 0 THEN   (* scroll down *)
            zeile := 18;
          ELSE
            start := start + 10 - diff;
            zeile := (10 - diff) * 8 + 18;
          END;
          ScrollRaster(SpielWin^.rPort, 0, 8 * diff, 10, 12, 480, 91);
        ELSE
          ScrollRaster(SpielWin^.rPort, 0, 80, 10, 12, 480, 91);
          zeile := 18;
        END;
        i := 0;
        Zeiger := SpielListe;
        WHILE i # start DO
          Zeiger := Zeiger^.Next;
          INC(i);
        END;
        REPEAT
          Heim := Zeiger^.Heim;
          Gast := Zeiger^.Gast;
          WriteWin(SpielWin, 10, zeile, Namen[Heim]);
          WriteWin(SpielWin, 218, zeile, "-");
          WriteWin(SpielWin, 234, zeile, Namen[Gast]);

          WriteZahl(SpielWin, Daten[Heim,0,Gast], 2, 440, zeile);
          WriteWin(SpielWin, 456, zeile, ":");
          WriteZahl(SpielWin, Daten[Gast,1,Heim], -2, 464, zeile);
          INC(i);
          INC(zeile, 8);
          Zeiger := Zeiger^.Next;
        UNTIL (zeile > 90) OR (i = alt) OR (Zeiger = NIL);
      END ZeigeSpiele;


    PROCEDURE BehandleSpielGadget;

      BEGIN
        SpielPos := TRUNC(FLOAT(ScrollInfo2.vertPot) / 65535.0 *
                          FLOAT(Stellungen2 - 10));
        IF SpielPos # AltSpielPos THEN
          ZeigeSpiele(SpielPos, AltSpielPos);
          AltSpielPos := SpielPos;
        END;
      END BehandleSpielGadget;


    PROCEDURE CreateGameList(Tor1, Tor2: INTEGER): BOOLEAN;

      VAR
        Zeiger1, Zeiger2: GameRecordPointer;
        i, j: CARDINAL;

      BEGIN
        SpielListe := NIL;
        count := 0;
        FOR i := 1 TO AnzMan DO
          FOR j := 1 TO AnzMan DO
            IF (Daten[i,0,j] = Tor1) OR ((Daten[i,0,j] > 9) AND (Tor1 =10 ))
                THEN
              IF (Daten[j,1,i] = Tor2) OR ((Daten[j,1,i] > 9) AND
                  (Tor2 = 10)) THEN
                IF Available(SIZE(GameRecord)) THEN
                  ALLOCATE(Zeiger1, SIZE(GameRecord));
                  Zeiger1^.Heim := i;
                  Zeiger1^.Gast := j;
                  Zeiger1^.Next := NIL;
                  IF SpielListe = NIL THEN
                    SpielListe := Zeiger1;
                  ELSE
                    Zeiger2^.Next := Zeiger1;
                  END;
                  Zeiger2 := Zeiger1;
                  INC(count);
                ELSE
                  RETURN FALSE;
                END;
              END;
            END;
          END;
        END;
        RETURN TRUE;
      END CreateGameList;


    PROCEDURE DeleteGameList;

      VAR
        Zeiger1, Zeiger2: GameRecordPointer;

      BEGIN
        Zeiger1 := SpielListe;
        WHILE Zeiger1 # NIL DO
          Zeiger2 := Zeiger1^.Next;
          DEALLOCATE(Zeiger1, SIZE(GameRecord));
          Zeiger1 := Zeiger2;
        END;
        SpielListe := NIL;
      END DeleteGameList;


    BEGIN  (* BehandleMouse *)
      xPos := (win^.mouseX - ToreOSX - 30 + 4) DIV 32;
      yPos := (win^.mouseY - ToreOSY + 8) DIV 10;
      IF (xPos < 0) OR (xPos > 10) OR (yPos < 0) OR (yPos > 10) THEN
        RETURN;
      END;
      IF NOT CreateGameList(yPos, xPos) THEN
        Beep;
        RETURN;
      END;
      IF SpielListe = NIL THEN
        RETURN;
      END;
      Stellungen2 := count;
      IF Stellungen2 < 10 THEN
        Stellungen2 := 10;
      END;
      WITH ScrollInfo2 DO
        vertPot := 0;
        IF Stellungen2 > 10 THEN
          vertBody := TRUNC(65535.0 / FLOAT(Stellungen2) * 10.0 + 1.0);
        ELSE
          vertBody := 65535;
        END;
      END;
      IF yPos < 10 THEN
        ValToStr(yPos, FALSE, Titel, 10, 2, " ", err);
      ELSE
        Titel := " +";
      END;
      Insert(Titel, last, ":");
      IF xPos < 10 THEN
        ValToStr(xPos, FALSE, add, 10, 1, " ", err);
      ELSE
        add := "+";
      END;
      Insert(Titel, last, add);
      ValToStr(count, FALSE, add, 10, 4, " ", err);
      Insert(Titel, last, add);
      Insert(Titel, last, " Spiel");
      IF count > 1 THEN
        Insert(Titel, last, "e");
      END;
      SpielWin := OeffneSpezFenster(50, 45, 520, 95,
                                    IDCMPFlagSet{closeWindow, mouseMove},
                                    WindowFlagSet{windowClose, windowActive},
                                    ADR(ScrollGadget2), ADR(Titel));
      IF SpielWin = NIL THEN
        RETURN;
      END;
      ZeigeSpiele(0, 0);
      AltSpielPos := 0;
      LOOP
        WaitPort(SpielWin^.userPort);
        Message := GetMsg(SpielWin^.userPort);
        Class := Message^.class;
        Code := Message^.code;
        ReplyMsg(Message);
        IF closeWindow IN Class THEN
          EXIT;
        ELSE
          BehandleSpielGadget;
        END;
      END;
      SchliesseFenster(SpielWin);
      DeleteGameList;
    END BehandleMouse;


  BEGIN  (* ZeigeStatistik *)
    IF AnzMan = 0 THEN
      KeineDaten;
      RETURN;
    END;
    IF NOT StatistikBerechnet THEN
      StatistikBerechnung;
    END;
    IF AnzahlSpiele = 0 THEN
      IF MyRequest(ADR("Statistik"), "Ohne Spiele keine Statistik!", " OK ",
                   " OK ", TRUE, TRUE) THEN END;
      RETURN;
    END;
    Stellungen := Ergebnisse;
    IF Stellungen < MaxAnzeige THEN
      Stellungen := MaxAnzeige;
    END;
    WITH ScrollInfo DO
      vertPot := 0;
      IF Stellungen > MaxAnzeige THEN
        vertBody := TRUNC(65535.0 / FLOAT(Stellungen) * FLOAT(MaxAnzeige)
                          + 1.0);
      ELSE
        vertBody := 65535;
      END;
    END;
    win := OeffneSpezFenster(0, 15, 640, 210, IDCMPFlagSet{closeWindow,
                             mouseMove, mouseButtons},
                             WindowFlagSet{windowClose, windowActive},
                             ADR(ScrollGadget), ADR("Statistik"));
    IF win # NIL THEN
      FOR i := 0 TO 10 DO
        zeile := i * 10 + ToreOSY;
        IF i # 10 THEN
          WriteZahl(win, i, 3, i * 32 + ToreOSX + 30, ToreOSY - 12);
          WriteZahl(win, i, 3, ToreOSX, zeile);
        ELSE
          WriteWin(win, 366 + ToreOSX, ToreOSY -12, "+");
          WriteWin(win, ToreOSX + 16, zeile, "+");
        END;
        FOR j := 0 TO 10 DO
          IF Tore[i,j] # 0 THEN
            WriteZahl(win, Tore[i,j], 3, j * 32 + ToreOSX + 30 , zeile);
          END;
        END;
      END;
      Linie(win, ToreOSX + 12, ToreOSY - 10, 362, TRUE);
      Linie(win, ToreOSX + 26, ToreOSY - 18, 118, FALSE);

      WriteWin(win, HATorOSX + 60, HATorOSY, "Tore");
      WriteWin(win, HATorOSX, HATorOSY + 12, "Heim:      (     %)");
      WriteWin(win, HATorOSX, HATorOSY + 20, "Ausw:      (     %)");
      WriteWin(win, HATorOSX, HATorOSY + 32, "Gsmt:");
      WriteWin(win, HATorOSX, HATorOSY + 40, "Sais:");
      Linie(win, HATorOSX, HATorOSY + 23, 151, TRUE);
      WriteZahl(win, HeimTore, 4, HATorOSX + 48, HATorOSY + 12);
      WriteZahl(win, AuswTore, 4, HATorOSX + 48, HATorOSY + 20);
      WriteZahl(win, GsmtTore, 4, HATorOSX + 48, HATorOSY + 32);
      IF GsmtTore > 0 THEN
        WriteRealZahl(win, FLOAT(HeimTore) * 100.0 / FLOAT(GsmtTore),
                      4, 1, HATorOSX + 96, HATorOSY + 12);
        WriteRealZahl(win, FLOAT(AuswTore) * 100.0 / FLOAT(GsmtTore),
                      4, 1, HATorOSX + 96, HATorOSY + 20);
      END;
      WriteRealZahl(win, FLOAT(GsmtTore) / FLOAT(AnzahlSpiele)
                    * FLOAT(AnzMan) * FLOAT(AnzMan-1), 4, 0, HATorOSX + 48,
                    HATorOSY + 40);

      WriteWin(win, AusgOSX + 56, AusgOSY, "Spielausgänge");
      WriteWin(win, AusgOSX, AusgOSY + 12, "Heimsiege:         (     %)");
      WriteWin(win, AusgOSX, AusgOSY + 20, "Unentschieden:     (     %)");
      WriteWin(win, AusgOSX, AusgOSY + 28, "Auswärtssiege:     (     %)");
      WriteWin(win, AusgOSX, AusgOSY + 40, "Gesamt:            Spiel");
      IF AnzahlSpiele > 1 THEN
        WriteWin(win, AusgOSX + 192, AusgOSY + 40, "e");
      END;
      Linie(win, AusgOSX, AusgOSY + 31, 215, TRUE);
      WriteZahl(win, HeimSiege, 3, AusgOSX + 120, AusgOSY + 12);
      WriteZahl(win, Unentschieden, 3, AusgOSX + 120, AusgOSY + 20);
      WriteZahl(win, AuswSiege, 3, AusgOSX + 120, AusgOSY + 28);
      WriteZahl(win, AnzahlSpiele, 3, AusgOSX + 120, AusgOSY + 40);
      WriteRealZahl(win, FLOAT(HeimSiege) * 100.0 / FLOAT(AnzahlSpiele),
                    4, 1, AusgOSX + 160, AusgOSY + 12);
      WriteRealZahl(win, FLOAT(Unentschieden) * 100.0 / FLOAT(AnzahlSpiele),
                    4, 1, AusgOSX + 160, AusgOSY + 20);
      WriteRealZahl(win, FLOAT(AuswSiege) * 100.0 / FLOAT(AnzahlSpiele),
                    4, 1, AusgOSX + 160, AusgOSY + 28);

      WriteWin(win, RelTorOSX, RelTorOSY, "Tore pro Spiel");
      WriteWin(win, RelTorOSX + 16, RelTorOSY + 12, "Heim:");
      WriteWin(win, RelTorOSX + 16, RelTorOSY + 20, "Ausw:");
      WriteWin(win, RelTorOSX + 16, RelTorOSY + 32, "Gsmt:");
      Linie(win, RelTorOSX + 16, RelTorOSY + 23, 79, TRUE);
      WriteRealZahl(win, FLOAT(HeimTore)  / FLOAT(AnzahlSpiele),
                    4, 2, RelTorOSX + 64, RelTorOSY + 12);
      WriteRealZahl(win, FLOAT(AuswTore)  / FLOAT(AnzahlSpiele),
                    4, 2, RelTorOSX + 64, RelTorOSY + 20);
      WriteRealZahl(win, FLOAT(GsmtTore) / FLOAT(AnzahlSpiele),
                    4, 2, RelTorOSX + 64, RelTorOSY + 32);

      ZeigeTore(0, 0);
      AltPos := 0;
      WriteWin(win, SortTorOSX + 8, SortTorOSY - 14, "Ergebnisse:");
      WriteZahl(win, Ergebnisse, -3, SortTorOSX + 104, SortTorOSY - 14);

      Linie(win, 0, 142, 640, TRUE);
      Linie(win, 400, 10, 132, FALSE);
      Linie(win, 204, 142, 68, FALSE);
      Linie(win, 368, 142, 68, FALSE);

      LOOP
        WaitPort(win^.userPort);
        Message := GetMsg(win^.userPort);
        Class := Message^.class;
        Code := Message^.code;
        ReplyMsg(Message);
        IF closeWindow IN Class THEN
          EXIT;
        ELSIF (mouseButtons IN Class) AND (Code = selectDown) THEN
          GadPos := RemoveGadget(win, ADR(ScrollGadget));
          BehandleMouse;
          GadPos := AddGadget(win, ADR(ScrollGadget), Pos);
        ELSE
          BehandleGadget;
        END;
      END;
      SchliesseFenster(win);
    END;  (* IF win # NIL *)
  END ZeigeStatistik;


BEGIN
  InitGadget(ScrollGadget, SortTorOSX + 150, SortTorOSY -6, 20,
             8 * MaxAnzeige, GadgetFlagSet{},
             ActivationFlagSet{followMouse}, propGadget, ADR(ScrollImage),
             NIL, ADR(ScrollInfo), 1, NIL);
  InitGadget(ScrollGadget2, 490, 12, 20, 80, GadgetFlagSet{},
             ActivationFlagSet{followMouse}, propGadget, ADR(ScrollImage2),
             NIL, ADR(ScrollInfo2), 1, NIL);
  ScrollInfo.flags := PropInfoFlagSet{autoKnob, freeVert};
  ScrollInfo2.flags := PropInfoFlagSet{autoKnob, freeVert};
END Statistik.

