This commit is contained in:
Harald Mueller 2021-12-02 17:02:58 +01:00
parent 77cb42c370
commit 17b444e069
20 changed files with 548 additions and 2 deletions

View File

@ -0,0 +1,14 @@
package com.doerzbach;
public enum Geschlecht {
maennlich("Herr"),weiblich("Frau");
private final String anrede;
Geschlecht(String anrede) {
this.anrede=anrede;
}
@Override
public String toString() {
return anrede;
}
}

View File

@ -0,0 +1,27 @@
package com.doerzbach;
public class Kunde extends Person {
private int kundenNummer;
private float umsatz;
public Kunde(int kundenNummer,String username, String passwort, String nachName, String vorName, String emailAdresse, String telefonNummer, String mobileNummer, Geschlecht geschlecht,float umsatz) {
super(username, passwort, nachName, vorName, emailAdresse, telefonNummer, mobileNummer, geschlecht);
this.kundenNummer=kundenNummer;
this.umsatz = umsatz;
}
public int getKundenNummer() {
return kundenNummer;
}
@Override
public String getAnrede() {
return "Sehr geehrter "+getGeschlecht()+" "+getNachName();
}
@Override
public String getPasswordPrompt() {
return "Geben sie ihr Passwort ein:";
}
}

View File

@ -0,0 +1,24 @@
package com.doerzbach;
import java.util.Date;
public class Mitarbeiter extends Person {
private String ahvNummer;
private java.util.Date anstellungsDatum;
public Mitarbeiter(String username, String passwort, String nachName, String vorName, String emailAdresse, String telefonNummer, String mobileNummer, String ahvNummer, Date anstellungsDatum, Geschlecht geschlecht ) {
super(username, passwort, nachName, vorName, emailAdresse, telefonNummer, mobileNummer, geschlecht);
this.ahvNummer = ahvNummer;
this.anstellungsDatum = anstellungsDatum;
}
@Override
public String getAnrede() {
return "Hallo "+getVorName();
}
@Override
public String getPasswordPrompt() {
return "Gib dein Passwort ein:";
}
}

View File

@ -0,0 +1,89 @@
package com.doerzbach;
public abstract class Person {
private String username;
private String passwort;
private String nachName;
private String vorName;
private String emailAdresse;
private String telefonNummer;
private String mobileNummer;
private Geschlecht geschlecht;
public boolean checkPasswd(String passwort){
return this.passwort.equals(passwort);
};
public void setGeschlecht(Geschlecht geschlecht) {
this.geschlecht = geschlecht;
}
public Geschlecht getGeschlecht() {
return geschlecht;
}
public String getUsername() {
return username;
}
public Person(String username, String passwort, String nachName, String vorName, String emailAdresse, String telefonNummer, String mobileNummer, Geschlecht geschlecht) {
this.username = username;
this.passwort = passwort;
this.nachName = nachName;
this.vorName = vorName;
this.emailAdresse = emailAdresse;
this.telefonNummer = telefonNummer;
this.mobileNummer = mobileNummer;
this.geschlecht = geschlecht;
}
public void setPasswort(String passwort) {
this.passwort = passwort;
}
public void setNachName(String nachName) {
this.nachName = nachName;
}
public void setVorName(String vorName) {
this.vorName = vorName;
}
public void setEmailAdresse(String emailAdresse) {
this.emailAdresse = emailAdresse;
}
public void setTelefonNummer(String telefonNummer) {
this.telefonNummer = telefonNummer;
}
public void setMobileNummer(String mobileNummer) {
this.mobileNummer = mobileNummer;
}
public String getNachName() {
return nachName;
}
public String getVorName() {
return vorName;
}
public String getEmailAdresse() {
return emailAdresse;
}
public String getTelefonNummer() {
return telefonNummer;
}
public String getMobileNummer() {
return mobileNummer;
}
public abstract String getAnrede();
public abstract String getPasswordPrompt();
}

View File

@ -0,0 +1,4 @@
test.csv
out
sensor.iml
.idea

View File

@ -0,0 +1,83 @@
Sensor Exercise
===============
This code is a solution of the Sensor Exercise.
Exercise on Inheritance, Abstract Classes and Polymorphism
-------
The purpose of this exercise is to demonstrate
inheritance and the use of abstract classes to
specify classes. Polymorphism will then be applied when using the concrete implementations of the abstract class.
Create a class hierarchy that contains several different sensors. They should then address some instances of these sensors and store the readings in different CSV files. An abstract class should contain the specification of all sensors, and concrete implementation classes should then implement the details. A 2-level specification hierarchy will be established.
Tasks
1) **_Specification:_**
Create an abstract class Sensor with the following abstract methods:
getUnit(): This is to return the unit of measurement such as degrees Celsius.
getValue(): The measurement in the unit, i.e. a double such as 17.0
getName(): This should only return the name of the measurement, such as "Outside temperature in Baar".
doMeasurement(): This should actually perform the measurement, i.e. "read out a sensor" for example by addressing a serial interface or making an HTTP request or something else.
2) **_Specification/partial implementation:_**
Create an abstract class for all pressure sensors called PressureSensor. This should extend Sensor.
It should implement the following methods and define the following fields:
private String unit;
protected double measurementValue;
getValue(): simply returns the variable measurementValue.
getUnit(): simply returns the variable unit.
3) Implementation:
Create a child class of PressureSensor Barometric1000PressureSensorImpl that implements the following method:
doMeasurement(): This should write a value between 0.5 and 1.05 into the measurmentValue variable. Here, in reality, the physical sensor would be addressed via an interface of the sensor. This would be very manufacturer-specific and could change from model to model of the manufacturer. That means you would have to read the manuals of the manufacturer of Barometric1000 to program this method in reality. But let's make it easy and just write a random value into the variable measurmentValue.
4) Implementation:
Create a child class of PressureSensor Aqualung2021ProDivePressureSensorImpl and implement the method doMeasurment() which returns values between 0 and 10.0. Again, in reality you would need to read the manuals of Aqualung2021Pro.
5) Specification/partial implementation:
Create and partially implement one of the following abstract
child classes of Sensor analogous to the class PressureSensor:
abstract class TemperatureSensor
abstract class HumiditySensor
abstract class SpeedSensor
6) Implementation:
Implement 2 concrete classes for two models of the abstract class you specified in task 5.
7) Using polymorphism:
Now write a class CsvWriter that reads readings from one of these sensors at a given time interval and writes them to a file. (File name, interval and sensor should be configurable).
- Tip: Create an object of a child class of Sensor and pass it to the constructor of CsvWriter as a parameter together with the interval and the filename.
File format: each line is Comma Separated Value (CSV) i.e. something like _time stamp_,_name of sensor_,_unit_,_measurement_. Each line corresponds to one measurement.
- Implement a method "public void run()" which you then call to actually take the measurements and write them to the file.
8) Create the CsvWriter in a main class and allow the user to select the sensor, the interval and the file name.
9) Optional: Think about how you would write the same data into a database.

View File

@ -0,0 +1,67 @@
Sensor übung
============
Dieser Code ist eine Lösung zur übung.
Übung zu Vererbung, abstrakten Klassen und Polymorphismus
-----------------
Mit dieser Übung sollen an einem praktischen Beispiel die Vererbung, der Einsatz von abstrakten Klassen zur Spezifizierung von Klassen, gezeigt werden. Bei der Benutzung der konkreten Implementationen der Abstrakten Klasse soll dann Polymorphismus angewandt werden.
Erstellen sie eine Klassenhierarchie, die mehrere verschiedene Sensoren enthält. Einige Instanzen dieser Sensoren sollten sie dann ansprechen und die Messwerte in verschiedenen CSV-Files speichern. Eine Abstrakte Klasse soll die Spezifikation von allen Sensoren enthalten, und konkrete Implementationsklassen sollen dann die Details implementieren. Dabei wird eine 2-Stufige Spezifikationshierarchie aufgebaut.
Aufgaben
-
1) Spezifikation:
Erzeugen sie ein Abstrakte Klasse Sensor mit den folgenden abstrakten Methoden:
getUnit(): Diese soll die Einheit der Messung zurückgeben wie zum Beispiel Grad Celsius
getValue(): Die Messung in der Einheit, d.h. ein double wie zum Beispiel 17.0
getName(): Diese soll nur den Namen des Messwerts zurückgeben, wie zum Beispiel "Aussentemperatur in Baar"
doMeasurement(): Diese soll die Messung wirklich durchführen, d.h. einen "Sensor auslesen" zum Beispiel indem eine serielle Schnittstelle angesprochen wird oder ein HTTP-Request gemacht wird oder etwas anderes.
2) Spezifikation/Teil-Implementation:
Erzeugen sie eine abstrakte Klasse für alle Drucksensoren mit dem Namen PressureSensor. Diese soll Sensor erweitern.
Diese soll folgende Methoden verwirklichen und folgende Felder definieren:
private String unit;
protected double measurementValue;
getValue(): gibt einfach die Variable measurementValue zurück.
getUnit(): gibt einfach die Variable unit zurück.
3) Implementation: Erzeugen sie eine Kind-Klasse von PressureSensor Barometric1000PressureSensorImpl die folgende Methode implementiert:
doMeasurement(): Diese solle einen Wert zwischen 0.5 und 1.05 in den measurmentValue Variable schreiben. Hier würde in der Realität der physische Sensor über eine Schnittstelle des Sensors angesprochen. Das wäre dann sehr herstellerspezifisch und könnte von Modell zu Modell des Herstellers auch noch ändern. Das heisst, sie müssten die Manuals des Herstellers von Barometric1000 lesen, um diese Methode in der Realität zu programmieren. Aber wir machen es uns einfach und geben schreiben einfach einen Zufallswert in die Variable measurmentValue.
4) Implementation: Erzeugen sie eine Kind-Klasse von PressureSensor Aqualung2021ProDivePressureSensorImpl und implementieren sie die Methode doMeasurment() die Werte zwischen 0 und 10.0 zurückgibt. Auch hier müssten sie in der Realität die Manuals von Aqualung2021Pro lesen.
5) Spezifikation/Teil-Implementation: Erzeugen und Teil-Implementieren sie eine der folgenden Abstrakten Kind-Klassen von Sensor analog zur Klasse PressureSensor:
abstract class TemperatureSensor
abstract class HumiditySensor
abstract class SpeedSensor
6) Implementation: Implementieren sie 2 Konkrete Klassen für zwei Modelle der von ihnen in Aufgabe 5 spezifizierten Abstrakten Klasse.
7) Benutzen von Polymorphismus: Schreiben sie jetzt eine Klasse CsvWriter welche von einem dieser Sensoren in einem vorgegeben Zeitintervall Messwerte ausliest und diese dann in ein File schreibt. (Filenamen, Intervall und Sensor soll konfigurierbar sein).
• Tipp: Sie erzeugen ein Objekt einer Kind-Klasse von Sensor und übergeben diese an dem Konstruktor von CsvWriter als Parameter zusammen mit dem Intervall und dem Filenamen.
Fileformat: jede Zeile ist Comma Separated Value (CSV) d.h. sowas wie <zeitstempel>,<measurment>,<unit>,<name of sensor>. Jede Zeile entspricht einer Messung.
• Implementieren sie eine Methode "public void run()" welche sie dann aufrufen um die Messungen wirklich zu machen und diese ins File zu schreiben.
8) Erzeugen sie den CsvWriter in einer Main-Klasse und ermöglichen sie dem Benutzer den Sensor, das Intervall und den Filenamen auszuwählen.
9) Optional: Überlegen sie sich, wie sie dieselben Daten in eine Datenbank schreiben würden.

View File

@ -0,0 +1,14 @@
package com.doerzbach;
public class Aqualung2021ProDivePressureSensorImpl extends PressureSensor{
@Override
public String getName() {
return "Aqualung2021ProDive";
}
@Override
public void doMeasurement() {
measurementValue=10.0*Math.random();
}
}

View File

@ -0,0 +1,14 @@
package com.doerzbach;
public class Barometric1000PressureSensorImpl extends PressureSensor{
@Override
public String getName() {
return "Barometer1000";
}
@Override
public void doMeasurement() {
measurementValue=0.5+0.55*Math.random();
}
}

View File

@ -0,0 +1,61 @@
package com.doerzbach;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CsvWriter implements Runnable{
public final Object syncObject =new Object(); // This is only used for multithreading waiting and Notification
private long interval;
private String filename;
private Sensor sensor;
private boolean running=true;
private int maxNumberOfMeasurements = -1; // Default is to run for ever
BufferedWriter bw;
DateFormat df= new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
public CsvWriter(long interval, String filename, Sensor sensor) throws IOException {
this.interval = interval;
this.filename = filename;
this.sensor = sensor;
bw=new BufferedWriter(new FileWriter(filename,true));
}
public CsvWriter(long interval, String filename, Sensor sensor, int maxNumberOfMeasurements) throws IOException {
this(interval,filename,sensor);
this.maxNumberOfMeasurements = maxNumberOfMeasurements;
}
public void run() {
while(running&& maxNumberOfMeasurements !=0) {
if(maxNumberOfMeasurements>0) maxNumberOfMeasurements--;
sensor.doMeasurement();
doOutput();
try {
synchronized (syncObject) {
syncObject.wait(interval); // This is the multithreading variant of waiting interval ms
}
} catch (InterruptedException e) {
System.out.println("Got notified to stop sleeping...");
running=false;
}
}
}
private void doOutput() {
try {
bw.write(df.format(new Date()) + "," + sensor.getName() + "," + sensor.getUnit() + "," + sensor.getValue() + "\n");
bw.flush();
} catch (IOException iox){
System.err.println("IOException during in doOutput");
iox.printStackTrace(System.err);
}
}
public void stop() {
running=false;
}
}

View File

@ -0,0 +1,81 @@
package com.doerzbach;
import java.io.IOException;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
Scanner scanner = new Scanner(System.in);
int choice;
do {
Sensor s = null;
System.out.println("Choose your Sensor");
System.out.println("0 EXIT");
System.out.println("1 Aqualung2021ProDivePressureSensor");
System.out.println("2 Barometric1000PressureSensor");
System.out.println("3 TemperaturInBaar");
System.out.println("4 Thermo2000");
System.out.printf("Make your choice:");
choice = scanner.nextInt();
switch (choice) {
case 0:
break;
case 1:
s = new Aqualung2021ProDivePressureSensorImpl();
break;
case 2:
s = new Barometric1000PressureSensorImpl();
break;
case 3:
s = new TemperaturInBaarImpl();
break;
case 4:
s = new Thermo2000Impl();
break;
default:
System.out.println("No valid choice");
}
if (s != null) {
System.out.print("Enter Interval in ms:");
long interval=scanner.nextLong();
System.out.print("Enter number of Measurments:");
int numberOfMeasurements=scanner.nextInt();
System.out.printf("Create a writer with filename text.csv, interval of %d ms and maximal number of measurements of %d using Sensor %s%n",interval,numberOfMeasurements,s.getClass());
CsvWriter w = new CsvWriter(interval, "test.csv", s, numberOfMeasurements);
System.out.println("let it run");
w.run();
}
} while (choice != 0);
// Now comes the multithreaded version, which is not part of the exercise.
// Read it if you are interested.
System.out.println("Create two CsvWriters w1 and w2 with 2 different sensors writing both to the same file test.csv but at different intervals");
Sensor s1 = new Aqualung2021ProDivePressureSensorImpl();
CsvWriter w1 = new CsvWriter(30000, "test.csv", s1);
Sensor s2 = new Thermo2000Impl();
CsvWriter w2 = new CsvWriter(500, "test.csv", s2);
System.out.println("Create two threads t1 and t2 if the writes w1 and w2");
Thread t1 = new Thread(w1); // w1 and w2 implement the Runnable interface which is required for a thread.
Thread t2 = new Thread(w2);
System.out.println("Start Threads t1 and t2");
t1.start(); // This starts the Thread t2 and the Thread is executing run() method of w1
t2.start(); // This starts the Thread t2 and the Thread is executing run() method of w2
System.out.println("Wait for 10 seconds now");
Thread.sleep(10000); // Lets wait for 10 seconds before we continue
System.out.println("Set the running flag to false using the stop() method of CsvWriter");
w1.stop(); // This will set the running flag to alse in w1 and w2 and the loop will end...
w2.stop();
System.out.println("Now we have to notify all Threads to wake up from syncObject.wait(interval)...");
synchronized (w1.syncObject) {
w1.syncObject.notify();
}
synchronized (w2.syncObject) {
w2.syncObject.notify();
}
System.out.println("....and join the threads to wait for them to exit");
t1.join();
t2.join();
}
}

View File

@ -0,0 +1,12 @@
package com.doerzbach;
public abstract class PressureSensor extends Sensor{
private String unit="Bar";
protected double measurementValue;
public double getValue(){
return measurementValue;
}
public String getUnit(){
return unit;
}
}

View File

@ -0,0 +1,8 @@
package com.doerzbach;
public abstract class Sensor {
public abstract double getValue();
public abstract String getUnit();
public abstract String getName();
public abstract void doMeasurement();
}

View File

@ -0,0 +1,14 @@
package com.doerzbach;
public class TemperaturInBaarImpl extends TemperaturSensor{
@Override
public String getName() {
return "Temperatur in Baar";
}
@Override
public void doMeasurement() {
measurementValue=0+30*Math.random();
}
}

View File

@ -0,0 +1,12 @@
package com.doerzbach;
public abstract class TemperaturSensor extends Sensor{
private String unit="Grad Celsius";
protected double measurementValue;
public double getValue(){
return measurementValue;
}
public String getUnit(){
return unit;
}
}

View File

@ -0,0 +1,15 @@
package com.doerzbach;
public class Thermo2000Impl extends TemperaturSensor{
@Override
public String getName() {
return "Thermo2000";
}
@Override
public void doMeasurement() {
measurementValue=-50+Math.random()*300;
}
}

View File

@ -0,0 +1,7 @@
package com.doerzbach;
public final class Uhrzeit {
static boolean entspricht(Zeit zeit1,Zeit zeit2){
return zeit1.equals(zeit2);
}
}

View File

@ -39,6 +39,6 @@
- (13 min) [Lasten- und Pflichtenheft. Warum brauche ich das z.B. als Webdesigner?](https://www.youtube.com/watch?v=-4Tq83wZFw8&t=1s)
## Auftrag / Aufgabe
- [Aufgabe Variante A Projektplanung](../uebungen/M306_2_AufgabeA_Projektplanung.docx)
- [Aufgabe Variante B Projektplanung](../uebungen/M306_2_AufgabeB_Projektplanung.docx)
- [Aufgabe Gameplanung Projektplanung](../uebungen/M306_2_Aufgabe_Gameplanung_Projektplanung.docx)
- [Aufgabe MigrationSmartphone Projektplanung](../uebungen/M306_2_Aufgabe_MigrationSmartphone_Projektplanung.docx)
- [Template für die Aufgabe](../uebungen/M306_2_Aufgabe_Projektplanung_Template.docx)