P. Pfahler, E. Stümpel
Programmieren in Java, Winter 1997/98
Lösung des 1. Übungsblatt

Aufgabe 2 (Ernst):
==================

Der Ablauf der Konstruktion von Java-Objekten (Folie 66) soll durch Erzeugung
von Testausgabe in Initialisierungscode und Konstruktoren deutlich gemacht
werden. Entwickeln Sie dazu eine Klassenhierarchie aus Klasse und 
Oberklasse und konstruieren Sie ein Objekt derart, daß alle Pfade des
Ablaufdiagramms (Folie 66) durchlaufen werden.

Geben Sie die Java-Quellen von Klasse und Oberklasse ab sowie ein 
Protokoll der erzeugten Testausgabe.

---------------------------------------------------------

Eine moegliche Loesung ist die folgende Klassenhierachie:

 OberKlasse
    |
    +----UnterKlasse

---------------------------------------------------------

//Anfang OberKlasse.java

class OberKlasse
{int a1,a2;
 static int b;

 static { // Initialisierungsblock fuer Klassenvariablen
  System.out.println("Initialisierung der Klassenvariablen von OberKlasse");
  System.out.println("(Zeitpunkt: einmalig bei Laden der Klasse)");
  b = 1;
 }

 { // Initialisierungsblock der Instanzvariablen 
  System.out.println("Initialisierung der Instanzvariablen von OberKlasse");
  System.out.println("(Zeitpunkt: jedesmal bei der Erzeugung eines Objektes und nach super Aufruf)");
 }

 public OberKlasse(int a1, int a2)
 {
  this.a1=a1;
  this.a2=a2;
  System.out.println("Rumpf von Konstruktor: OberKlasse(int a1, int a2)");
 }

 public OberKlasse()
 {
  this(0,0);
  System.out.println("Rumpf von Konstruktor: OberKlasse() mit Aufruf this(O,0)");
 }
}
//Ende Oberklasse.java


//Anfang UnterKlasse.java

class UnterKlasse extends OberKlasse
{
 double c1, c2;
 static double d;

 static {  // Initialisierungsblock fuer Klassenvariablen
  System.out.println("Initialisierung der Klassenvariablen von UnterKlasse");
  System.out.println("(Zeitpunkt: einmalig bei Laden der Klasse)");
  d = 1;
 }

 { // Initialisierungsblock der Instanzvariablen 
  System.out.println("Initialisierung der Instanzvariablen von UnterKlasse");
  System.out.println("(Zeitpunkt: jedesmal bei der Erzeugung eines Objektes und nach super Aufruf)");
 }

 public UnterKlasse(double c1, double c2)
 {
  this.c1=c1;
  this.c2=c2;
  System.out.println("Rumpf von Konstruktor: UnterKlasse(double a1, double a2)");
 }

 public UnterKlasse()
 {
  this(1.0,1.0);
  System.out.println("Rumpf von Konstruktor: UnterKlasse() mit Aufruf this(1.O,1.0)");
 }
}
//Ende Unterklasse.java

//Anfang Test.java

class Test
{
 public static void main(String argv[])
 {
  System.out.println("Erzeuge erste Instanz von UnterKlasse:");
  System.out.println("UnterKlasse i1 = new UnterKlasse()");
  UnterKlasse i1 = new UnterKlasse();
  System.out.println("Erzeuge zweite Instanz von UnterKlasse:");
  System.out.println("UnterKlasse i2 = new UnterKlasse()");
  UnterKlasse i2 = new UnterKlasse();
 }
}
//Ende Test.java


//AUSGABEPROTOKOLL

Erzeuge erste Instanz von UnterKlasse:
UnterKlasse i1 = new UnterKlasse()
Initialisierung der Klassenvariablen von OberKlasse
(Zeitpunkt: einmalig bei Laden der Klasse)
Initialisierung der Klassenvariablen von UnterKlasse
(Zeitpunkt: einmalig bei Laden der Klasse)
Initialisierung der Instanzvariablen von OberKlasse
(Zeitpunkt: jedesmal bei der Erzeugung eines Objektes und nach super Aufruf)
Rumpf von Konstruktor: OberKlasse(int a1, int a2)
Rumpf von Konstruktor: OberKlasse() mit Aufruf this(O,0)
Initialisierung der Instanzvariablen von UnterKlasse
(Zeitpunkt: jedesmal bei der Erzeugung eines Objektes und nach super Aufruf)
Rumpf von Konstruktor: UnterKlasse(double a1, double a2)
Rumpf von Konstruktor: UnterKlasse() mit Aufruf this(1.O,1.0)
Erzeuge zweite Instanz von UnterKlasse:
UnterKlasse i2 = new UnterKlasse()
Initialisierung der Instanzvariablen von OberKlasse
(Zeitpunkt: jedesmal bei der Erzeugung eines Objektes und nach super Aufruf)
Rumpf von Konstruktor: OberKlasse(int a1, int a2)
Rumpf von Konstruktor: OberKlasse() mit Aufruf this(O,0)
Initialisierung der Instanzvariablen von UnterKlasse
(Zeitpunkt: jedesmal bei der Erzeugung eines Objektes und nach super Aufruf)
Rumpf von Konstruktor: UnterKlasse(double a1, double a2)
Rumpf von Konstruktor: UnterKlasse() mit Aufruf this(1.O,1.0)


Aufgabe 3 (Spaß):
=================

Für die grafische Darstellung der Klausurergebnisse zu "Programmieren in
Java" wurde ein Java-Applet entwickelt. Es besteht aus einer Klasse "klausur",
die die Klausurpunkte und Namen der TeilnehmerInnen als Parameter aus der 
zugehörigen HTML-Datei erhält und daraus ein Diagramm aus horizontalen 
Balken erzeugt.

Ihre Aufgabe besteht darin, zwei kleine Änderungen vorzunehmen:

a) Fügen Sie einen neuen Parameter "scheinlimit" ein, der angeben soll
wieviele Punkte man mindestens braucht, um den Schein zu bekommen.
Auch dieser Parameter soll von der HTML-Seite an das Applet übergeben werden
(so wie z.B. "anz_teiln"). Die Balken der TeilnehmerInnen, die das Schein-
kriterium erfüllen sollen grün gezeichnet werden, die anderen rot.

b) In das horizontale Balkendiagramm soll eine senkrechte Linie zur 
Markierung der durchschnittlich erreichten Punktezahl eingefügt werden.

--------------------------
Die Loesung sieht so aus:
--------------------------
Java-Klausur


--------------------------------------------------
und wird erzeugt durch die folgenden Aenderungen:
--------------------------------------------------


<!-- ANFANG: klausurNEU.html  -->
<title>Java-Klausur</title>
<hr>
<applet code="klausurNEU.class" width=400 height=620>

<!-- NEUER PARAMETER: scheinlimit -->
<param name=scheinlimit value="10">
<!--  -->

<param name=anz_teiln value="26">
<param name=t1_punkte value="10">
<param name=t1_name value="Ampel,Alf">
           .
           .
           .
<param name=t26_name value="Zaun, Zenzi">
</applet>
<hr>
<!-- ENDE: klausur.html   -->



// ANFANG klausurNEU.java
// Ergebnisse der Klausur "Programmieren in Java" als Balkendiagramm

import java.awt.*;

public class klausurNEU extends java.applet.Applet {
  String                title = "Klausurergebnis ´Programmieren in Java'";
  int                   fontsize = 12;
  int                   anz_teiln;
  int                   punkte[];
  String                namen[];
  int                   scale = 10;
  int                   max_namen_länge = 0;
  int                   balken_abstand = 10;
  Font                  courier = new Font("Courier", Font.BOLD, fontsize);

/*
 * NEUE VARIABLEN:
 */
  int			scheinlimit;	// Bestehensgrenze
  int			durchschnitt;	// durchschnittliche Punktzahl


  public void init() {
    String rs;
    

    //WERT VON SCHEINLIMIT 
    rs = getParameter("scheinlimit");
    scheinlimit = Integer.parseInt(rs);


    // die anzahl der klausurteilnehmerInnen
    rs = getParameter("anz_teiln");
    anz_teiln = Integer.parseInt(rs);
    
    // punkte- und namenslisten
    punkte = new int[anz_teiln];
    namen = new String[anz_teiln];
    
    for (int i=0; i < anz_teiln; i++) {
      // lies punkte und namen der teilnehmerInnen
      rs = getParameter("T" + (i+1)+ "_punkte");
      punkte[i] = (rs == null) ? 0 : Integer.parseInt(rs);
      rs = getParameter("T" + (i+1) + "_name");
      namen[i] = (rs == null) ? "Niemand, Norbert" : rs;
      
      // die länge des längsten namens merken wir uns
      if (getFontMetrics(courier).stringWidth(namen[i]) > max_namen_länge)
        max_namen_länge = getFontMetrics(courier).stringWidth(namen[i]);


      // MERKE GESAMTPUNKTZAHL
      durchschnitt += punkte[i];

    }

    // BERECHNE DEN DURCHSCHNITTSWERT (PRUEFE anz_teiln != 0)   
    if (anz_teiln != 0)
     durchschnitt /= anz_teiln;
    else
     durchschnitt = 0; 

  }
  
  public void paint(Graphics g) {
    int cx, cy;

    // NEUE PARAMETER: 
    int x0, y0;


    g.setFont(courier);

    // schreibe die überschrift
    g.setColor(Color.black);
    g.drawString(title, 5, 15);
    
    for (int i=0; i < anz_teiln; i++) {
      // setze x- und y-koordinaten
      cx = max_namen_länge + 10;
      cy = (fontsize + balken_abstand) * i + balken_abstand + 30;

      // schreibe den namen
      g.setColor(Color.black);
      g.drawString(namen[i], 5, cy + fontsize);
      

      // MALE DEN BALKEN GRUEN ODER ROT
      if (punkte[i] < scheinlimit)
       g.setColor(Color.red);		//NICHT BESTANDEN
      else
       g.setColor(Color.green);

      g.fillRect(cx, cy, punkte[i] * scale, fontsize);

      g.setColor(Color.black);		//FARBE ZUM SCHREIBEN DER PUNKTZAHL
      
      // schreibe punktzahl neben den balken
      g.drawString("" + punkte[i], 
                   cx + (punkte[i] * scale) + 10,
                   cy + fontsize);
    }

    // SENKRECHTE (SCHWARZE) LINIE BEI DURSCHNITTSWERT MALEN
    // WIR VERWENDEN HIERZU g.drawLine(int,int,int,int) AUS java.awt.Graphics
    x0 = max_namen_länge + 10 + durchschnitt*scale;
    y0 = balken_abstand + 20;				//(x0,y0) OBERER ANFANGSPUNKT DER LINIE
    cx = x0;
    cy = y0+(fontsize + balken_abstand)*anz_teiln;	//(cx,cy) ENDPUNKT
    g.drawLine (x0, y0, cx, cy);			// AKTUELLE FARBE IST SCHWARZ

  }
}
// ENDE klausurNEU.java