Aufgabe Vorschlag A - 1 - Klassen und Methoden implementi… · Abitur Hessen Praktische Informatik LK 2021
Thema: Klassen und Methoden implementieren · Aus der Prüfung LK (2021)
Aufgabenstellung
Lieferservice eines Restaurants
Für den Lieferservice eines Restaurants sollen ein Softwaresystem und eine Datenbank entwickelt werden. Zu einer eingegangenen Bestellung wird ein Lieferauftrag erzeugt, der von einer Fahrerin oder einem Fahrer (im Folgenden Fahrer genannt) mit einem Fahrzeug ausgeführt wird. Lieferungen bis zu 10km Entfernung werden mit einem E-Motorroller ausgefahren, dieser kann mit einem Führerschein der Klassen 'A' oder 'B' gefahren werden. Lieferungen über 10km werden mit einem Kleinwagen ausgefahren, für den ein Führerschein der Klasse 'B' notwendig ist. Der Fahrer mit der längsten Wartezeit erhält den Lieferauftrag. Jeder Fahrer hat eine RFID 1 -Kennung, mittels eines RFID-Chips erhält er Zugang zum Fahrzeug. Im Lieferauftrag werden der Startzeitpunkt der Lieferung sowie die Zeitpunkte der Auslieferung und der Rückkehr zum Restaurant festgehalten.
1 RFID (engl. Radio-frequency identification) ermöglicht das berührungslose Identifizieren von Objekten.
Material 1: UML-Klassendiagramm Lieferservice
Hinweis: Auf alle Attribute kann mittels get- und set-Methoden zugegriffen werden.
Material 2: Klassendokumentationen
Klasse List
List<T>()
erzeugt eine generische Liste mit Elementen des Typs T
add(obj: T)
hängt das Objekt obj vom Typ T am Ende der Liste an.
add(index: int, obj: T)
fügt das Objekt obj vom Typ T an der Position index in die Liste ein.
contains(obj: T): boolean
liefert true, wenn das Objekt obj in der Liste enthalten ist, andernfalls false.
get(index: int): T
liefert das Listenelement an der Position index zurück bzw. null, falls index negativ oder größer gleich der Anzahl der momentan enthaltenen Elemente ist.
remove(index: int): T
entfernt das Listenelement an der Position index. Liefert das entfernte Element zurück bzw. null, falls index negativ oder größer gleich der Anzahl der momentan enthaltenen Elemente ist.
remove(obj: T): boolean
entfernt das Objekt obj aus der Liste. Falls obj mehrmals in der Liste enthalten ist, wird nur das erste Vorkommen entfernt. Der Rückgabewert ist true, falls das Objekt gefunden und entfernt wurde, andernfalls ist er false.
size(): int
liefert die Anzahl der Elemente in der Liste zurück.
Klasse DateTime
DateTime()
erzeugt ein DateTime-Objekt mit dem aktuellen Systemdatum und der aktuellen Systemzeit.
DateTime(date: String, time: String)
erzeugt ein DateTime-Objekt aus einer Zeichenkette im Format "dd.mm.yyyy" und einer Zeichenkette im Format "hh:mm".
millisUntil(other: DateTime): long
liefert die Anzahl der Millisekunden zwischen diesem DateTime-Objekt und other; liegt other zeitlich nach diesem DateTime-Objekt ist das Ergebnis eine positive Zahl, liegt other zeitlich vor diesem Date-Time-Objekt ist das Ergebnis eine negative Zahl.
toString(): String
liefert eine String-Repräsentanz dieses DateTime-Objekts im Format "dd.mm.yyyy hh:mm".
Klasse Serial
port: Name des Ports (z.B. „COM1“)
baud: Baudrate (z.B. 2400 oder 9600)
dataBits: Anzahl der Datenbits, 7 oder 8
stopBits: Anzahl der Stoppbits, 1 oder 2
parity: Parität, 0 für no, 1 für odd, 2 für even parity
Serial(...)
der Konstruktor initialisiert die serielle Schnittstelle, ohne sie zu öffnen.
open(): boolean
öffnet die serielle Schnittstelle; liefert true, wenn die Schnittstelle verwendbar ist.
close()
schließt die serielle Schnittstelle; die Schnittstelle ist dann solange nicht mehr verwendbar, bis sie wieder geöffnet wird.
dataAvailable(): int
liefert die Anzahl der Bytes, die von der seriellen Schnittstelle gelesen werden können.
read(): int
liest ein Byte (0..255) von der serielle Schnittstelle, bzw. −1, wenn die Schnittstelle nicht geöffnet ist. Die Methode blockiert, bis ein Byte verfügbar ist.
write(value: int)
schreibt ein Byte auf die serielle Schnittstelle; ist die Schnittstelle nicht geöffnet geschieht nichts.
Klasse String
String(data: char[])
erzeugt ein String-Objekt aus den Zeichen des Feldes data
equals(str: String): boolean
liefert true, wenn beide Strings gleich sind, andernfalls false.
isEmpty(): boolean
liefert true, wenn der String leer ist, d. h. die Länge 0 hat, andernfalls ist der Rückgabewert false.
startsWith(str: String): boolean
liefert true, wenn der String mit str beginnt, andernfalls false.
Material 3: Vorlage für Sequenzdiagramm
Material 4: UML-Klassendiagramm für die Zugangskontrolle der Fahrzeuge
Hinweise:
Dieses Klassendiagramm zeigt die Software der Fahrzeuge.
Mithilfe der Klasse FunkModul werden Kommandos vom Fahrzeug zur Lieferservice-Verwaltung (Material 1) gesendet und entsprechende Antworten empfangen.
Auf alle Attribute kann mittels get- und set-Methoden zugegriffen werden.
RS232-Protokoll zum Lesen der RFID-Kennung eines Fahrers
Übertragungsparameter: 9600 Baud, 8 Datenbits, 1 Stoppbit, kein Paritätsbit
Steuerzeichen: Start of Text - STX (0x02) und End of Text - ETX (0x03)
6 Datenbytes mit der RFID-Kennung des Fahrers
Prüfzeichen: alle Datenbytes bitweise mit dem XOR-Operator verknüpft
Datenrahmen:
STX
6 Datenbytes (ASCII-Format)
Prüfzeichen
ETX
Beispiel:
Start
Daten
Prüfz.
Ende
Position
0
1
2
3
4
5
6
7
8
Zeichen
STX
'1'
'2'
'1'
'2'
'1'
'2'
'3'
ETX
Zeichencode
0x02
0x31
0x32
0x31
0x32
0x31
0x32
0x33
0x03
Material 5: Struktogramm der run()-Methode der Klasse Controller
Hinweise:
Das Struktogramm zeigt das Entriegeln eines Fahrzeugs zu Beginn einer Fahrt, nur dieser Teil der Methode ist zu implementieren.
Kommandona me, Fahrzeugnummer und RFID-Kennung des Fahrers werden mit einer Leerstelle als Trennzeichen aneinandergehängt und an die Lieferservice-Verwaltung gesendet.
Beispiel: UNLOCK 1147 121212.
Wenn ein Fahrzeug nach 60 Sekunden wieder verriegelt wird, kann niemand in einem Wagen eingesperrt werden. Von innen lässt sich ein Fahrzeug immer öffnen.
Material 6: Auszug aus der Speisen- und Getränkekarte
Pizzen
Classic Preis (in €)
Groß Preis (in €)
Pizza Margherita
(Tomatensauce, Mozzarella, Basilikum)
6,90
8,50
Pizza Hawaii
(Tomatensauce, Ananas, Schinken, Käse)
7,90
9,50
Pizza Salami
(Salami, Käse)
6,50
7,90
Pasta
Preis (in €)
Pasta Arradiata
(cremige Tomatensauce, Knoblauch, Steakpfeffer, Pepperoni)
7,00
Pasta Alba
(Sahnesauce mit Schinken und frischen Champignons)
8,00
Getränke
Vol.
Preis (in €)
Pfand
Mineralwasser
0,5 l
2,00
kein Pfand
Limonade
0,5 l
2,00
25 ct
Limonade
1 l
3,00
25 ct
1 Objektorientierte Entwicklung einer Anwendung
1.1
Überführen Sie die im UML-Klassendiagramm (Material 1) dargestellten Klassen Fahrer und Lieferauftrag in Anweisungen einer objektorientierten Programmiersprache und implementieren Sie die aufgeführten Methoden. [8 BE]
Hinweise: Die Methode ermittleWartezeit() der Klasse Fahrer liefert die seit dem Ende des letzten Lieferauftrags vergangene Zeit in Millisekunden. Der letzte (neueste) Lieferauftrag wurde zuletzt der Liste der Lieferaufträge hinzugefügt. Hatte ein Fahrer noch keinen Lieferauftrag, wird die Wartezeit auf 3 Stunden festgelegt. Der Konstruktor der Klasse Lieferauftrag setzt die aktuelle Zeit als start -Zeit. Eine Dokumentation der Klassen List und DateTime ist in Material 2 zu finden.
1.3
Die Methode sucheFahrer() der Klasse LieferserviceVerwaltung sucht in Abhängigkeit von der zu fahrenden Entfernung einen Fahrer für den Lieferauftrag.
Lieferungen bis zu 10 km Entfernung werden mit einem E-Motorroller ausgefahren, dieser kann mit einem Führerschein der Klasse 'A' gefahren werden. Lieferungen über 10 km werden mit einem Kleinwagen ausgefahren, dafür ist ein Führerschein der Klasse 'B' notwendig. Die Führerscheinklasse 'B' schließt die Klasse 'A' ein, d. h. ein E-Motorroller kann mit Führerscheinklasse 'A' oder 'B' gefahren werden. Der anwesende Fahrer (Attribut arbeitet) mit passendem Führerschein, der gerade nicht auf Tour ist und die längste Wartezeit hat, soll zurückgegeben werden.
Entwickeln Sie ein Struktogramm für diese Methode. [8 BE]
1.4.1
Die run -Methode der Klasse Controller steuert u. a. den Entriegelungsvorgang eines Fahrzeugs. Der Ablauf ist im Struktogramm in Material 5 dargestellt.
Überführen Sie die Klasse Controller in Anweisungen einer objektorientierten Programmiersprache und implementieren Sie den Konstruktor und die Methode run(). [10 BE]
Hinweise: Die Dokumentation der Klasse Serial ist in Material 2 zu finden. Die Methode getTimer() der Klasse Controller liefert die aktuelle Zeit in Millisekunden.
1.4.2
Die Methode readCard() der Klasse RFIDReader liest die auf dem RFID-Chip gespeicherte RFID-Kennung des Fahrers über die serielle Schnittstelle. Das Datenformat (Material 4) sieht ein Prüfzeichen vor. Ist das Prüfzeichen korrekt, wird die RFID-Kennung in Form einer Zeichenkette zurückgegeben. Im Fehlerfall ist der Rückgabewert eine leere Zeichenkette. Implementieren Sie die Methode readCard(). [5 BE]
Hinweise: Die Dokumentation der Klasse String ist in Material 2 zu finden. Die Methode calcCheckChar() ermittelt das Prüfzeichen.
1.6
Eine Gutschrift-Funktion soll ergänzt werden. Wenn eine Kundin oder ein Kunde eine Bestellung aufgibt und vom Eingang der Bestellung bis zur Auslieferung mehr als 45 Minuten vergehen, erhält die Kundin bzw. der Kunde eine Gutschrift in Höhe von 3 Euro, die bei der nächsten Bestellung eingelöst werden kann.
Entwerfen Sie die notwendigen Erweiterungen der Klassen LieferserviceVerwaltung und Kunde mit Beziehungen im UML-Klassendiagramm und implementieren Sie eine Methode zur Zuweisung der Gutschrift für eine bestimmte Bestellung in einer objektorientierten Programmiersprache. [6 BE]

Lösung
Nach den offiziellen Korrekturhinweisen
1.1 Überführen Sie die im UML-Klassendiagramm dargestellten Klassen Fahrer und Lieferauftrag in Anweisungen einer objektorientierten Programmiersprache und implementieren Sie die aufgeführten Methoden.
Lösung: ```java public class Fahrer { private static int autowert = 0; private int fahrernr; private String vorname; private String nachname; private String rfidKennung; private char fuehrerscheinklasse; private boolean arbeitet; private boolean aufTour; private List<Lieferauftrag> lieferauftraege; public Fahrer(String vn, String nn, String rfid, char fk) { this.fahrernr = ++autowert; this.vorname = vn; this.nachname = nn; this.rfidKennung = rfid; this.fuehrerscheinklasse = fk; this.arbeitet = false; this.aufTour = false; this.lieferauftraege = new List<Lieferauftrag>(); } public long ermittleWartezeit() { long wartezeit; if (lieferauftraege.size() > 0) { Lieferauftrag letzterAuftrag = lieferauftraege.get(lieferauftraege.size() - 1); DateTime wartetSeit = letzterAuftrag.getEnde(); wartezeit = wartetSeit.millisUntil(new DateTime()); } else { wartezeit = 3 * 60 * 60 * 1000; // 3 Std in Millisekunden } return wartezeit; } public void hinzufuegen(Lieferauftrag la) { this.lieferauftraege.add(la); } } public class Lieferauftrag { private Bestellung bestellung; private DateTime start; private DateTime ausgeliefert; private DateTime ende; private Fahrer fahrer; private Fahrzeug fahrzeug; public Lieferauftrag(Bestellung bestellung, Fahrer f, Fahrzeug fz) { this.bestellung = bestellung; this.bestellung.setLieferauftrag(this); this.start = new DateTime(); this.ausgeliefert = null; this.ende = null; this.fahrer = f; this.fahrzeug = fz; } } ```
1.3 Entwickeln Sie ein Struktogramm für die Methode sucheFahrer().
Lösung: Das Struktogramm initialisiert `wartezeit := 0`, `fahrerFürAuftrag := null` und `passendeFk := 'A'`. Falls `entfernung > 10`, wird `passendeFk := 'B'` gesetzt. Anschließend wird in einer Schleife über alle Fahrer iteriert: Wenn ein Fahrer arbeitet, nicht auf Tour ist und eine passende Führerscheinklasse besitzt, wird seine Wartezeit mit `ermittleWartezeit()` ermittelt. Ist diese größer oder gleich der bisherigen `wartezeit`, wird er als Zwischenergebnis gemerkt und `wartezeit` aktualisiert. Am Ende wird `fahrerFürAuftrag` zurückgegeben.
1.4.1 Überführen Sie die Klasse Controller in Anweisungen einer objektorientierten Programmiersprache und implementieren Sie den Konstruktor und die Methode run().
Lösung: ```java public class Controller { private FunkModul funkModul; private RFIDReader reader; private Fahrzeug fahrzeug; public Controller(String comPort, Fahrzeug fahrzeug) { funkModul = new FunkModul(); this.fahrzeug = fahrzeug; Serial serial = new Serial(comPort, 9600, 8, 1, 0); if (serial.open()) { reader = new RFIDReader(serial); } } public void run() { char response; String rfidKennung; while (true) { if (reader.isCardAvailable()) { rfidKennung = reader.readCard(); if (!rfidKennung.isEmpty()) { this.funkModul.send("UNLOCK " + fahrzeug.getFahrzeugnr() + " " + rfidKennung); response = this.funkModul.receive(); if (response == 0x06) { // ACK, Fahrzeug entriegeln fahrzeug.unlock(); // Fahrzeug wieder absperren, wenn es nicht gestartet wurde startTimer(); while (getTimer() / 1000 < 60 && !fahrzeug.hasStarted()); if (!fahrzeug.hasStarted()) { fahrzeug.lock(); funkModul.send("LOCK " + fahrzeug.getFahrzeugnr() + " " + rfidKennung); } } else { display("Karte nicht authorisiert"); } } else { display("Karte nicht lesbar"); } } } } } ```
1.4.2 Implementieren Sie die Methode readCard() der Klasse RFIDReader.
Lösung: ```java public String readCard() { String response = ""; char checkValue; char[] data = new char[6]; while (readChar() != 0x02); // warte auf STX // lies Zeichen von der Schnittstelle for (int i = 0; i < data.length; i++) { data[i] = readChar(); } // lies Pruefzeichen checkValue = readChar(); // wenn naechstes Zeichen ein ETX ist, geht es weiter if (readChar() == 0x03) { if (checkValue == calcCheckChar(data)) { response = new String(data); } } return response; } ```
1.6 Entwerfen Sie die notwendigen Erweiterungen der Klassen LieferserviceVerwaltung und Kunde mit Beziehungen im UML-Klassendiagramm.
Lösung: Erweiterung des UML-Klassendiagramms: - In der Klasse `LieferserviceVerwaltung` wird die Methode `+ ermittleGutschrift(bestellung : Bestellung)` ergänzt. - Eine Assoziation von `LieferserviceVerwaltung` zu `Kunde` (Navigierbarkeit zu Kunde, Multiplizität `*`, Rollenname `- kunden`). - Klasse `Kunde` mit den Attributen `- name : String`, `- telefon : String`, `- gutschrift : boolean` und Konstruktor `+ Kunde(name : String, telefon : String, ladresse : Adresse)`.
1.6 Implementieren Sie eine Methode zur Zuweisung der Gutschrift für eine bestimmte Bestellung in einer objektorientierten Programmiersprache.
Lösung: ```java public void ermittleGutschrift(Bestellung bestellung) { DateTime beginn = bestellung.getBestellEingang(); DateTime ausgeliefert = bestellung.getLieferauftrag().getAusgeliefert(); long millis = beginn.millisUntil(ausgeliefert); if (millis > 45 * 60 * 1000) { bestellung.getBesteller().setGutschrift(true); } } ```
Die ausführliche Erklärung Schritt für Schritt (mit KI) gibt es mit Premium. Premium
Löse sie direkt hier: automatische Korrektur, Hinweise und Lösung Schritt für Schritt.
‹ Aufgabe Vorschlag C - 1.6 · LK 2022 · Aufgabe Vorschlag B - 1 - Klassen und Methoden implementi… · LK 2021 ›
Mehr Aufgaben zu Klassen und Methoden implementieren
- Aufgabe Vorschlag A - 2 · LK 2022
- Aufgabe Vorschlag A - 2.5.1 · LK 2022
- Aufgabe Vorschlag B - 1.5 · LK 2022
- Aufgabe Vorschlag C - 1.2 · LK 2022
- Aufgabe Vorschlag C - 1.6 · LK 2022
- Aufgabe Vorschlag B - 1 - Klassen und Methoden implementi… · LK 2021
- Aufgabe Vorschlag C - 1 - Klassen und Methoden implementi… · LK 2021