diff --git a/src/main/java/projekt/enigma/model/Codierer.java b/src/main/java/projekt/enigma/model/Codierer.java index 28907b55f1975bb9aeaf4e171ad45c51c2bf4bcf..913b8db6d6cbfef4bed7c7b7f25448d0a112f431 100644 --- a/src/main/java/projekt/enigma/model/Codierer.java +++ b/src/main/java/projekt/enigma/model/Codierer.java @@ -1,7 +1,5 @@ package projekt.enigma.model; -import org.apache.http.HttpException; - import java.io.IOException; import java.util.Calendar; import java.util.Random; @@ -14,503 +12,506 @@ import java.util.Random; */ public class Codierer { - //region Variablen - /** - * Der Spruchschluessel als Klartext zur Codierung der Nachricht. - */ - private String spruchschluessel; - - /** - * Der Spruchschluessel, mit den Tageswerten aus dem Codebuch, codiert. - */ - private String spruchschluesselCodiert; - - /** - * Die Kenngruppe fuer die die versendeten Nachrichten gedacht sind. - * Diese ist relevant fuer den Webservice (Funkraum). - */ - private String kenngruppe; - - /** - * Die Nachricht, welche der Benutzer eingibt, wird als String "nachricht" gespeichert - * und im Laufe der Benutzung ergaenzt. - */ - private String nachricht; - - /** - * Das Hardware-Objekt. Hier werden alle hardwarerelevanten Baugruppen gespeichert und verarbeitet. - */ - private Hardware hardware; - - /** - * Im Codebuch sind die Tageswerte zu finden. Ueber dieses Objekt kann darauf zugegriffen werden. - */ - private Codebuch codebuch; - //endregion - - //region Konstruktor - - /** - * Der Konstruktor des Codierers. - * Hier werden die globalen Variablen auf ihre Standardwerte gesetzt sowie die Objekte initialisiert. - */ - public Codierer(String kenngruppe) { - this.nachricht = ""; - this.spruchschluessel = ""; - this.spruchschluesselCodiert = ""; - this.kenngruppe = kenngruppe; - this.codebuch = new Codebuch(); - - this.codebuch.fetchTagesschluessel(); - } - //endregion - - //region Funktionen & Methoden - //region Reset & Initialisieren - - /** - * Hier lesen wir den heutigen Eintrag aus dem Codebuch aus und erstellen ein Codebuch-Objekt. - * Nach dem Codebuch werden dann die Ringe auf die Walzen gesteckt und die Walzen anschließend - * in die Hardware gebaut. - * <br> - * Ein Reflektor wird definiert, jedoch keine Werte zugewiesen, da wir nur einen besitzen und - * deshalb alle Einstellungen hierfuer statisch im Reflektor definiert haben. - * <br> - * Das Steckbrett wird ebenfalls definiert und die notwendigen Kabel eingesteckt nach dem heutigen - * Codebucheintrag. - */ - private void initialisiereHardware() { - this.nachricht = ""; - - // Das Steckbrett initialisieren - Steckbrett sb = new Steckbrett(); - char[][] verbinder = this.codebuch.getSteckverbindung(); - - // Für jedes Kabel eine Verbindung auf dem Steckbrett setzen - for (char[] kabel : verbinder) { - sb.setzeVertauschung(kabel[0], kabel[1]); - } - - // Die Hardware aus dem Koffer holen (initialisieren) - this.hardware = new Hardware(); - - // Den Ring an der Walze anbringen und die Walze dann in die Hardware einsetzen - this.hardware.setWalzen(0, this.codebuch.getWalzenlage()[0], this.codebuch.getRingstellung()[0]); - this.hardware.setWalzen(1, this.codebuch.getWalzenlage()[1], this.codebuch.getRingstellung()[1]); - this.hardware.setWalzen(2, this.codebuch.getWalzenlage()[2], this.codebuch.getRingstellung()[2]); - - // Der Hardware das gesetzte Steckbrett zuweisen - this.hardware.setSteckbrett(sb); - - // Ein Reflektor-Objekt erstellen und der Hardware bekanntgeben - this.hardware.setReflektor(new Reflektor()); - } - - /** - * Setzt die Enigma auf die Einstellungen des aktuellen Tages, aus dem Codebuch zurueck. - */ - public void resetHardware() { - this.initialisiereHardware(); - } - - /** - * Leert das Nachrichten-Objekt um eine neue Nachricht aufnehmen zu koennen. - */ - public void resetNachricht() { - this.nachricht = ""; - } - //endregion - - //region Nachrichten handler - - /** - * Befehl, die Nachricht an den Funker zu uebergeben. - * - * @throws IOException : Die Antwort konnte nicht gelesen werden. - * @throws HttpException : Die Nachricht konnte nicht abgesendet werden. - */ - public void sendeNachricht() throws IOException, HttpException { - String kopf = this.generateKopf(); - new Funkraum().sendeFunkspruch(new Morsecode().convertBuchstabeToMorsecode(kopf + this.nachricht), - this.kenngruppe); - this.nachricht = ""; - this.resetHardware(); - } - - /** - * Gibt die letzte empfangene Nachricht zurueck. - * <br> - * nachricht[0]: String[]: Tag, an dem die Nachricht gesendet wurde. - * nachricht[1]: String[]: Die verschluesselte Nachricht von Morsecode in Buchstaben konvertiert. - * nachricht[2]: String[]: Nachricht im Klartext. Die Enigma Nachricht (nachricht[1]) mittels der - * Tageseinstellungen (nachricht[0]) decodiert. - */ - public String[] empfangeNachricht() { - StringBuilder sb = new StringBuilder(); - Morsecode mc = new Morsecode(); - String[] nachricht = new String[3]; - - // Alte Nachrichten-Variable erstmal leeren - this.nachricht = ""; - - // Abrufen der letzten Nachricht, für unsere Kenngruppe, aus dem Funkraum - String[] codierteNachricht = new Funkraum().empfangeFunkspruch(this.kenngruppe); - - // Prüfen ob Nachrichtenlänge > 1 und die codierte Nachricht mehr als drei Felder (" ") hat - if ((codierteNachricht[1] != null) && (codierteNachricht[1].split(" ").length > 3)) { - nachricht[0] = codierteNachricht[0]; - nachricht[1] = mc.convertMorsecodeToBuchstabe(codierteNachricht[1]); - nachricht[2] = this.decodiere(nachricht[1], Integer.parseInt(nachricht[0])); - - sb.append(nachricht[1], 0, 16); - - for (int i = 17; i <= nachricht[1].length(); ) { - if ((i + 5) < nachricht[1].length()) { - sb.append(nachricht[1], i, i + 5).append(" "); - i += 5; - } else { - sb.append(nachricht[1].substring(i)); - break; - } - } - nachricht[1] = sb.toString(); - } - - return nachricht; - } - //endregion - - //region Generatoren - - /** - * Hier wird ein neuer Spruchschluessel generiert. - * <p> - * Mit diesem werden die Walzen auf eine neue Startposition gestellt und dem Kopf, mit dem - * Tagesschluessel codiert, hinzugefuegt. - * <br> - * Hierfuer wird mittels der Funktion "randomBuchstabe" ein zufaelliger Buchstabe generiert, - * und ueberprueft, ob dieser bereits in der globalen Variable (this.spruchschluessel) vorhanden ist. - * Wenn nicht, wird der Buchstabe dem Spruchschluessel hinzugefügt. - * <br> - * Dies wir nun so lange gemacht bis der Spruchschluessel eine Laenge von drei Zeichen hat. - * Die Walzen werden anhand des Spruchschluessels automatisch gestellt. - */ - public void generateSpruchschluessel() { - String klartext = ""; - - while (klartext.length() < 3) { - String temp = this.randomBuchstabe(); - if (!klartext.contains(temp)) { - klartext += temp; - } - } - - this.spruchschluessel = klartext; - this.spruchschluesselCodiert = this.codiere(klartext + klartext, false); - - // Walzen auf den Spruchschlüssel stellen - this.hardware.setzePosition(0, this.spruchschluessel.charAt(0)); - this.hardware.setzePosition(1, this.spruchschluessel.charAt(1)); - this.hardware.setzePosition(2, this.spruchschluessel.charAt(2)); - - // Die Kenngruppe codieren und in der Nachricht speichern - this.codiere(this.kenngruppe, true); - } - - /** - * Erstellen des Nachrichten-Kopfes. - * Hierfuer wird die aktuelle Uhrzeit ausgelesen, die Laenge der Nachricht, sowie der, mit dem - * Tagescode codierte, Spruchschluessel. - * - * @return String: Enthaelt die Uhrzeit, die Anzahl der Buchstaben der Nachricht und den Spruchschluessel. - */ - private String generateKopf() { - Calendar cal = Calendar.getInstance(); - - return String.format("%02d%02d", cal.get(Calendar.HOUR), cal.get(Calendar.MINUTE)) + " " - + this.nachricht.length() + " " + this.spruchschluesselCodiert.substring(0, 3) + " " - + this.spruchschluesselCodiert.substring(3, 6) + " "; - } - - /** - * Generiert einen zufaelligen Buchstaben aus dem Alphabet. - * In der Funktion gibt es den String "Alphabet", in welchem alle zulaessigen Zeichen eingetragen sind. - * Aus diesem String wird nun zufaellig ein Zeichen ausgewaehlt und zurueckgegeben. - * - * @return String : ein zufaellig generierter Buchstabe. - */ - private String randomBuchstabe() { - return String.valueOf((char) ('A' + new Random().nextInt(26))); - } - //endregion - - //region setze Funktionen - - /**TODO: Wird nicht benutzt - * Setzt den anzuzeigenden Buchstaben (buchstabe) auf der Walze (walzenPosition) und setzt anschliessend das - * Nachrichten-Objekt zurueck. - * - * @param walzenPosition : int : Nummer der Walze. - * @param buchstabe : char : Buchstabe der zugewiesen werden soll. - */ - public void setzeWalze(int walzenPosition, char buchstabe) { - this.resetNachricht(); - this.hardware.setzePosition(walzenPosition, buchstabe); - } - - /**TODO: Wird nicht benutzt - * Setzt den Ring auf der Walze auf einen neuen Umsprungwert. - * - * @param walzenPosition : int : Walze auf die der Ring gesteckt wird. - * @param umsprungPunkt : int : Umspringpunkt (Signal an linke Walze zum Drehen). - */ - public void setzeRing(int walzenPosition, int umsprungPunkt) { - this.hardware.setzeRing(walzenPosition, umsprungPunkt); - } - - /**TODO: Wird nicht benutzt - * Setzt die Walze (walzeNr) in die Position (walzenPosition) der Enigma ein. - * Mit Ringstellung(ringstellung) gibt man die Position des Umsprungpunktes an. - * - * @param walzenPosition : int : Position der Walze in der Enigma (1-2-3). - * @param walzeNr : int : Nummer der Walze die eingesetzt wird. - * @param ringstellung : int : Stellung des Ringes. - */ - public void setzeWalzeNr(int walzenPosition, int walzeNr, int ringstellung) { - this.hardware.setzeWalzenNr(walzenPosition, walzeNr, ringstellung); - } - - /**TODO: Wird nicht benutzt - * Setzt das Kabel in beide Ports ein und fuegt es dem Steckbrett-Array hinzu. - * - * @param port : int : Kabel Nummer, welches am Steckbrett eingesteckt wird. - * @param verbindung : String : Verbindung, welche die vertauschten Buchstaben angibt. - * @return boolean : Wenn true, darf das Kabel gesteckt werden, wenn false, steckt da bereits schon eines. - */ - public boolean setzeSteckbrett(int port, String verbindung) { - return this.hardware.getSteckbrett().setzeVertauschung(port, verbindung.charAt(0), verbindung.charAt(1)); - } - //endregion - - //region fetch Funktionen - - /** - * Gibt die Ringstellungen aus dem Codebuch zurueck. - * - * @return int[] : Array mit den Ringstellungen der drei eingesetzten Walzen. - */ - public int[] fetchRingstellung() { - return this.codebuch.getRingstellung(); - } - - /** - * Gibt die Walzennummer aus dem Codebuch zurueck. - * - * @return int[] : Array mit den Nummern der drei eingesetzten Walzen. - */ - public int[] fetchWalzenNr() { - return this.codebuch.getWalzenlage(); - } - - /** - * Gibt die Steckverbindungen aus dem Codebuch zurueck. - * - * @return char[][] : Array mit den gesteckten Verbindungen im Steckbrett. - */ - public char[][] fetchSteckverbindungen() { - return this.codebuch.getSteckverbindung(); - } - - /** - * Gibt die aktuellen Buchstaben auf den Walzen zurueck. - * - * @return char[] : Walzen Array mit der aktuellen Positionen. - */ - public char[] fetchWalzen() { - char[] walzen = new char[3]; - walzen[0] = this.hardware.getWalzen()[0].getPosition(); - walzen[1] = this.hardware.getWalzen()[1].getPosition(); - walzen[2] = this.hardware.getWalzen()[2].getPosition(); - - return walzen; - } - - /** - * Ueberprueft welche Buchstaben noch zur Vertauschung verfuegbar sind. - * - * @param port: Zahl zwischen 0-9: entspricht der Kabelnummer. - * @return String: liefert einen String mit den verfuegbaren Buchstaben zurueck. - */ - public String fetchVerfuegbareBuchstaben(int port) { - return this.hardware.getSteckbrett().fetchVerfuegbareBuchstaben(port); - } - //endregion - /** Gibt die Walzennummer einer Walze auf Position (walzePos) zurück - * - * @param walzePos : int : Position der Walze - * @return int : Nummer der eingesetzten Walze - */ + //region Variablen + /** + * Der Spruchschluessel als Klartext zur Codierung der Nachricht. + */ + private String spruchschluessel; + + /** + * Der Spruchschluessel, mit den Tageswerten aus dem Codebuch, codiert. + */ + private String spruchschluesselCodiert; + + /** + * Die Kenngruppe fuer die die versendeten Nachrichten gedacht sind. + * Diese ist relevant fuer den Webservice (Funkraum). + */ + private String kenngruppe; + + /** + * Die Nachricht, welche der Benutzer eingibt, wird als String "nachricht" gespeichert + * und im Laufe der Benutzung ergaenzt. + */ + private String nachricht; + + /** + * Das Hardware-Objekt. Hier werden alle hardwarerelevanten Baugruppen gespeichert und verarbeitet. + */ + private Hardware hardware; + + /** + * Im Codebuch sind die Tageswerte zu finden. Ueber dieses Objekt kann darauf zugegriffen werden. + */ + private Codebuch codebuch; + //endregion + + //region Konstruktor + + /** + * Der Konstruktor des Codierers. + * Hier werden die globalen Variablen auf ihre Standardwerte gesetzt sowie die Objekte initialisiert. + */ + public Codierer(String kenngruppe) { + this.nachricht = ""; + this.spruchschluessel = ""; + this.spruchschluesselCodiert = ""; + this.kenngruppe = kenngruppe; + this.codebuch = new Codebuch(); + + this.codebuch.fetchTagesschluessel(); + } + //endregion + + //region Funktionen & Methoden + //region Reset & Initialisieren + + /** + * Hier lesen wir den heutigen Eintrag aus dem Codebuch aus und erstellen ein Codebuch-Objekt. + * Nach dem Codebuch werden dann die Ringe auf die Walzen gesteckt und die Walzen anschließend + * in die Hardware gebaut. + * <br> + * Ein Reflektor wird definiert, jedoch keine Werte zugewiesen, da wir nur einen besitzen und + * deshalb alle Einstellungen hierfuer statisch im Reflektor definiert haben. + * <br> + * Das Steckbrett wird ebenfalls definiert und die notwendigen Kabel eingesteckt nach dem heutigen + * Codebucheintrag. + */ + private void initialisiereHardware() { + this.nachricht = ""; + + // Das Steckbrett initialisieren + Steckbrett sb = new Steckbrett(); + char[][] verbinder = this.codebuch.getSteckverbindung(); + + // Für jedes Kabel eine Verbindung auf dem Steckbrett setzen + for (char[] kabel : verbinder) { + sb.setzeVertauschung(kabel[0], kabel[1]); + } + + // Die Hardware aus dem Koffer holen (initialisieren) + this.hardware = new Hardware(); + + // Den Ring an der Walze anbringen und die Walze dann in die Hardware einsetzen + this.hardware.setWalzen(0, this.codebuch.getWalzenlage()[0], this.codebuch.getRingstellung()[0]); + this.hardware.setWalzen(1, this.codebuch.getWalzenlage()[1], this.codebuch.getRingstellung()[1]); + this.hardware.setWalzen(2, this.codebuch.getWalzenlage()[2], this.codebuch.getRingstellung()[2]); + + // Der Hardware das gesetzte Steckbrett zuweisen + this.hardware.setSteckbrett(sb); + + // Ein Reflektor-Objekt erstellen und der Hardware bekanntgeben + this.hardware.setReflektor(new Reflektor()); + } + + /** + * Setzt die Enigma auf die Einstellungen des aktuellen Tages, aus dem Codebuch zurueck. + */ + public void resetHardware() { + this.initialisiereHardware(); + } + + /** + * Leert das Nachrichten-Objekt um eine neue Nachricht aufnehmen zu koennen. + */ + private void resetNachricht() { + this.nachricht = ""; + } + //endregion + + //region Nachrichten handler + + /** + * Befehl, die Nachricht an den Funker zu uebergeben. + * + * @throws IOException : Die Antwort konnte nicht gelesen werden. + */ + public void sendeNachricht() throws IOException { + String kopf = this.generateKopf(); + new Funkraum().sendeFunkspruch(new Morsecode().convertBuchstabeToMorsecode(kopf + this.nachricht), + this.kenngruppe); + this.nachricht = ""; + this.resetHardware(); + } + + /** + * Gibt die letzte empfangene Nachricht zurueck. + * <br> + * nachricht[0]: String[]: Tag, an dem die Nachricht gesendet wurde. + * nachricht[1]: String[]: Die verschluesselte Nachricht von Morsecode in Buchstaben konvertiert. + * nachricht[2]: String[]: Nachricht im Klartext. Die Enigma Nachricht (nachricht[1]) mittels der + * Tageseinstellungen (nachricht[0]) decodiert. + */ + public String[] empfangeNachricht() { + StringBuilder sb = new StringBuilder(); + Morsecode mc = new Morsecode(); + String[] nachricht = new String[3]; + + // Alte Nachrichten-Variable erstmal leeren + this.nachricht = ""; + + // Abrufen der letzten Nachricht, für unsere Kenngruppe, aus dem Funkraum + String[] codierteNachricht = new Funkraum().empfangeFunkspruch(this.kenngruppe); + + // Prüfen ob Nachrichtenlänge > 1 und die codierte Nachricht mehr als drei Felder (" ") hat + if ((codierteNachricht[1] != null) && (codierteNachricht[1].split(" ").length > 3)) { + nachricht[0] = codierteNachricht[0]; + nachricht[1] = mc.convertMorsecodeToBuchstabe(codierteNachricht[1]); + nachricht[2] = this.decodiere(nachricht[1], Integer.parseInt(nachricht[0])); + + sb.append(nachricht[1], 0, 16); + + for (int i = 17; i <= nachricht[1].length(); ) { + if ((i + 5) < nachricht[1].length()) { + sb.append(nachricht[1], i, i + 5).append(" "); + i += 5; + } else { + sb.append(nachricht[1].substring(i)); + break; + } + } + nachricht[1] = sb.toString(); + } + + return nachricht; + } + //endregion + + //region Generatoren + + /** + * Hier wird ein neuer Spruchschluessel generiert. + * <p> + * Mit diesem werden die Walzen auf eine neue Startposition gestellt und dem Kopf, mit dem + * Tagesschluessel codiert, hinzugefuegt. + * <br> + * Hierfuer wird mittels der Funktion "randomBuchstabe" ein zufaelliger Buchstabe generiert, + * und ueberprueft, ob dieser bereits in der globalen Variable (this.spruchschluessel) vorhanden ist. + * Wenn nicht, wird der Buchstabe dem Spruchschluessel hinzugefügt. + * <br> + * Dies wir nun so lange gemacht bis der Spruchschluessel eine Laenge von drei Zeichen hat. + * Die Walzen werden anhand des Spruchschluessels automatisch gestellt. + */ + public void generateSpruchschluessel() { + String klartext = ""; + + while (klartext.length() < 3) { + String temp = this.randomBuchstabe(); + if (!klartext.contains(temp)) { + klartext += temp; + } + } + + this.spruchschluessel = klartext; + this.spruchschluesselCodiert = this.codiere(klartext + klartext, false); + + // Walzen auf den Spruchschlüssel stellen + this.hardware.setzePosition(0, this.spruchschluessel.charAt(0)); + this.hardware.setzePosition(1, this.spruchschluessel.charAt(1)); + this.hardware.setzePosition(2, this.spruchschluessel.charAt(2)); + + // Die Kenngruppe codieren und in der Nachricht speichern + this.codiere(this.kenngruppe, true); + } + + /** + * Erstellen des Nachrichten-Kopfes. + * Hierfuer wird die aktuelle Uhrzeit ausgelesen, die Laenge der Nachricht, sowie der, mit dem + * Tagescode codierte, Spruchschluessel. + * + * @return String: Enthaelt die Uhrzeit, die Anzahl der Buchstaben der Nachricht und den Spruchschluessel. + */ + private String generateKopf() { + Calendar cal = Calendar.getInstance(); + + return String.format("%02d%02d", cal.get(Calendar.HOUR), cal.get(Calendar.MINUTE)) + " " + + this.nachricht.length() + " " + this.spruchschluesselCodiert.substring(0, 3) + " " + + this.spruchschluesselCodiert.substring(3, 6) + " "; + } + + /** + * Generiert einen zufaelligen Buchstaben aus dem Alphabet. + * In der Funktion gibt es den String "Alphabet", in welchem alle zulaessigen Zeichen eingetragen sind. + * Aus diesem String wird nun zufaellig ein Zeichen ausgewaehlt und zurueckgegeben. + * + * @return String : ein zufaellig generierter Buchstabe. + */ + private String randomBuchstabe() { + return String.valueOf((char) ('A' + new Random().nextInt(26))); + } + //endregion + + //region setze Funktionen + + /** + * Setzt den Ring auf der Walze auf einen neuen Umsprungwert. + * + * @param walzenPosition : int : Walze auf die der Ring gesteckt wird. + * @param umsprungPunkt : int : Umspringpunkt (Signal an linke Walze zum Drehen). + */ + public void setzeRing(int walzenPosition, int umsprungPunkt) { + this.hardware.setzeRing(walzenPosition, umsprungPunkt); + } + + /** + * Setzt die Walze (walzeNr) in die Position (walzenPosition) der Enigma ein. + * Mit Ringstellung(ringstellung) gibt man die Position des Umsprungpunktes an. + * + * @param walzenPosition : int : Position der Walze in der Enigma (1-2-3). + * @param walzeNr : int : Nummer der Walze die eingesetzt wird. + * @param ringstellung : int : Stellung des Ringes. + */ + public void setzeWalzeNr(int walzenPosition, int walzeNr, int ringstellung) { + this.hardware.setzeWalzenNr(walzenPosition, walzeNr, ringstellung); + } + + /** + * Setzt den anzuzeigenden Buchstaben (buchstabe) auf der Walze (walzenPosition) und resetet das + * Nachrichten Objekt + * + * @param walze : int : Nummer der Walze + * @param buchstabe : char : Buchstabe der zugewiesen soll + */ + public void setzeWalzenPosition(int walze, char buchstabe) { + this.resetNachricht(); + this.hardware.setzePosition(walze, buchstabe); + } + + + /** + * TODO: Wird nicht benutzt + * Setzt das Kabel in beide Ports ein und fuegt es dem Steckbrett-Array hinzu. + * + * @param port : int : Kabel Nummer, welches am Steckbrett eingesteckt wird. + * @param verbindung : String : Verbindung, welche die vertauschten Buchstaben angibt. + * @return boolean : Wenn true, darf das Kabel gesteckt werden, wenn false, steckt da bereits schon eines. + */ + public boolean setzeSteckbrett(int port, String verbindung) { + return this.hardware.getSteckbrett().setzeVertauschung(port, verbindung.charAt(0), verbindung.charAt(1)); + } + //endregion + + //region fetch Funktionen + + /** + * Gibt die Ringstellungen aus dem Codebuch zurueck. + * + * @return int[] : Array mit den Ringstellungen der drei eingesetzten Walzen. + */ + public int[] fetchRingstellung() { + return this.codebuch.getRingstellung(); + } + + /** + * Gibt die Walzennummer aus dem Codebuch zurueck. + * + * @return int[] : Array mit den Nummern der drei eingesetzten Walzen. + */ + public int[] fetchWalzenNr() { + return this.codebuch.getWalzenlage(); + } + + /** + * Gibt die Steckverbindungen aus dem Codebuch zurueck. + * + * @return char[][] : Array mit den gesteckten Verbindungen im Steckbrett. + */ + public char[][] fetchSteckverbindungen() { + return this.codebuch.getSteckverbindung(); + } + + /** + * Gibt die aktuellen Buchstaben auf den Walzen zurueck. + * + * @return char[] : Walzen Array mit der aktuellen Positionen. + */ + public char[] fetchWalzen() { + char[] walzen = new char[3]; + walzen[0] = this.hardware.getWalzen()[0].getPosition(); + walzen[1] = this.hardware.getWalzen()[1].getPosition(); + walzen[2] = this.hardware.getWalzen()[2].getPosition(); + + return walzen; + } + + /** + * Ueberprueft welche Buchstaben noch zur Vertauschung verfuegbar sind. + * + * @param port: Zahl zwischen 0-9: entspricht der Kabelnummer. + * @return String: liefert einen String mit den verfuegbaren Buchstaben zurueck. + */ + public String fetchVerfuegbareBuchstaben(int port) { + return this.hardware.getSteckbrett().fetchVerfuegbareBuchstaben(port); + } + + /** + * Gibt die Walzennummer einer Walze auf Position (walzePos) zurück + * + * @param walzePos : int : Position der Walze + * @return int : Nummer der eingesetzten Walze + */ public int fetchWalzenNr(int walzePos) { - return this.hardware.getWalzen()[walzePos].getWalzenNr(); - } + return this.hardware.getWalzen()[walzePos].getWalzenNr(); + } + //endregion + + //region codierer + + /** + * Hier wird ein einzelner Buchstabe verschluesselt. + * Man muss hier ebenfalls mitgeben, ob der codierte String in "nachricht" gespeichert werden soll oder nicht. + * In der Regel ist dies der Fall. + * + * @param buchstabe : char : Der zu codierende Buchstabe. + * @param save : boolean : Nachricht speichern oder nicht. + * @return char : Der codierte Buchstabe. + */ + public char codiere(char buchstabe, boolean save) { + char codiert = this.hardware.codiere(buchstabe); + + if (save) { + this.nachricht += codiert; + } + + return codiert; + } + + /** + * Codiert den uebergebenen String. + * Man muss hier ebenfalls mitgeben, ob der codierte String in "nachricht" gespeichert werden soll oder nicht. + * In der Regel ist dies der Fall. + * + * @param klartext : String : Der zu codierende Text. + * @param save : boolean : Nachricht speichern oder nicht. + * @return String : Der codierte Text zusaetzlich als Rueckgabe. + */ + public String codiere(String klartext, boolean save) { + StringBuilder sb = new StringBuilder(); + + for (char buchstabe : klartext.toCharArray()) { + sb.append(this.codiere(buchstabe, save)); + } + + return sb.toString(); + } + + /** + * Diese Funktion erwartet als (codierteNachricht) eine korrekte Enigma-Nachricht. + * Ihr muss auch der Tag der Codierung mitgegeben werden. Dieser weiss dein Funker im Funkraum. + * In der Regel ist dies der Tag des Nachrichtenempfangs. + * + * @param codierteNachricht : String : Enigma-codierte Nachricht. + * @param tag : int : Tag der Nachricht. + * @return String : decodierte Nachricht. + */ + private String decodiere(String codierteNachricht, int tag) { + + // Hardware reseten und Tageseinstellungen aus dem Codebuch laden + this.codebuch.fetchTagesschluessel(tag); + this.initialisiereHardware(); + + // Nachricht splitten mit whitespace als delimiter + String[] nachricht = codierteNachricht.split(" "); + StringBuilder sb = new StringBuilder(); + + // Uhrzeit und Zeichenanzahl der Nachricht + sb.append(nachricht[0]).append(" "); + sb.append(nachricht[1]).append(" "); + + // Spruchschluessel + String spruchschluessel = this.decodiereString(nachricht[2]); + + sb.append(spruchschluessel).append(" "); + sb.append(this.decodiereString(nachricht[3])).append(" "); + + // Walzen neu einstellen mit dem Spruchschluessel + this.hardware.setzePosition(0, spruchschluessel.charAt(0)); + this.hardware.setzePosition(1, spruchschluessel.charAt(1)); + this.hardware.setzePosition(2, spruchschluessel.charAt(2)); + + // Nachricht decodieren + sb.append(this.decodiereString(nachricht[4])); + + return sb.toString(); + } + + /** + * Zerlegt den uebergebenen String in einen char-Array und decodiert jedes Zeichen. + * Der String wird dann decodiert zurueckgegeben. + * + * @param nachricht : String : Der zu decodierende Text. + * @return String : Der decodierte Text. + */ + private String decodiereString(String nachricht) { + StringBuilder sb = new StringBuilder(); + + for (char buchstabe : nachricht.toCharArray()) { + if (buchstabe > 0) { + sb.append(this.hardware.codiere(buchstabe)); + } + } + + return sb.toString(); + } //endregion - //region codierer - - /** - * Hier wird ein einzelner Buchstabe verschluesselt. - * Man muss hier ebenfalls mitgeben, ob der codierte String in "nachricht" gespeichert werden soll oder nicht. - * In der Regel ist dies der Fall. - * - * @param buchstabe : char : Der zu codierende Buchstabe. - * @param save : boolean : Nachricht speichern oder nicht. - * @return char : Der codierte Buchstabe. - */ - public char codiere(char buchstabe, boolean save) { - char codiert = this.hardware.codiere(buchstabe); - - if (save) { - this.nachricht += codiert; - } - - return codiert; - } - - /** - * Codiert den uebergebenen String. - * Man muss hier ebenfalls mitgeben, ob der codierte String in "nachricht" gespeichert werden soll oder nicht. - * In der Regel ist dies der Fall. - * - * @param klartext : String : Der zu codierende Text. - * @param save : boolean : Nachricht speichern oder nicht. - * @return String : Der codierte Text zusaetzlich als Rueckgabe. - */ - public String codiere(String klartext, boolean save) { - StringBuilder sb = new StringBuilder(); - - for (char buchstabe : klartext.toCharArray()) { - sb.append(this.codiere(buchstabe, save)); - } - - return sb.toString(); - } - - /** - * Diese Funktion erwartet als (codierteNachricht) eine korrekte Enigma-Nachricht. - * Ihr muss auch der Tag der Codierung mitgegeben werden. Dieser weiss dein Funker im Funkraum. - * In der Regel ist dies der Tag des Nachrichtenempfangs. - * - * @param codierteNachricht : String : Enigma-codierte Nachricht. - * @param tag : int : Tag der Nachricht. - * @return String : decodierte Nachricht. - */ - private String decodiere(String codierteNachricht, int tag) { - - // Hardware reseten und Tageseinstellungen aus dem Codebuch laden - this.codebuch.fetchTagesschluessel(tag); - this.initialisiereHardware(); - - // Nachricht splitten mit whitespace als delimiter - String[] nachricht = codierteNachricht.split(" "); - StringBuilder sb = new StringBuilder(); - - // Uhrzeit und Zeichenanzahl der Nachricht - sb.append(nachricht[0]).append(" "); - sb.append(nachricht[1]).append(" "); - - // Spruchschluessel - String spruchschluessel = this.decodiereString(nachricht[2]); - - sb.append(spruchschluessel).append(" "); - sb.append(this.decodiereString(nachricht[3])).append(" "); - - // Walzen neu einstellen mit dem Spruchschluessel - this.hardware.setzePosition(0, spruchschluessel.charAt(0)); - this.hardware.setzePosition(1, spruchschluessel.charAt(1)); - this.hardware.setzePosition(2, spruchschluessel.charAt(2)); - - // Nachricht decodieren - sb.append(this.decodiereString(nachricht[4])); - - return sb.toString(); - } - - /** - * Zerlegt den uebergebenen String in einen char-Array und decodiert jedes Zeichen. - * Der String wird dann decodiert zurueckgegeben. - * - * @param nachricht : String : Der zu decodierende Text. - * @return String : Der decodierte Text. - */ - private String decodiereString(String nachricht) { - StringBuilder sb = new StringBuilder(); - - for (char buchstabe : nachricht.toCharArray()) { - if (buchstabe > 0) { - sb.append(this.hardware.codiere(buchstabe)); - } - } - - return sb.toString(); - } - //endregion - - //region Sonstige - - /**TODO: Wird nicht benutzt - * Prueft ob der Port auf dem das Kabel gesteckt werden soll, noch frei ist. - * <p> - * setSteckbrett ausfuehren mit beiden Buchstaben als String. - * - * @param buchstabe : char : Der zuletzt eingegebene Buchstabe. - * @return boolean : Wenn der Buchstabe nicht vorhanden ist, wird true zurueckgegeben, ansonsten false. - */ - public boolean pruefeSteckbrettPort(char buchstabe) { - return this.hardware.getSteckbrett().ueberpruefeVertauschungen(buchstabe); - } - - /** - * Liest aus der empfangenen Nachricht den Spruchschluessel aus und gibt ihn zurueck. - * - * @param empfangeneNachricht : String : Die empfangene Nachricht als String. - * @return String : Der Spruchschluessel, mit welcher die Nachricht codiert wurde. - */ - public String empfangenerSpruchschluessel(String empfangeneNachricht) { - String[] nachricht = empfangeneNachricht.split(" "); - - return nachricht[2]; - } - - /** - * Loescht das letzte Zeichen aus der Nachricht und dreht die Walzen eine Position zurueck. - */ - public void letztesZeichenLoeschen() { - this.hardware.dreheWalzen(-1); - this.nachricht = this.nachricht.substring(0, this.nachricht.length() - 1); - } - //endregion - //endregion - - //region Getter - - /** - * Liest die Kenngruppe aus, welche die Maschine gerade besitzt. Frueher war dies eine eindeutige Nummer, - * die einer Einheit zugewiesen war. Wir hinterlegen hier einen Benutzernamen. - * - * @return String : Kenngruppe - */ - public String getKenngruppe() { - return kenngruppe; - } - - /** - * Der Spruchschluessel wird, zur internen Verwendung, auch im Klartext gespeichert. - * Wir brauchen diesen dann zum Codieren der eigentlichen Nachricht. - * - * @return String : Der Klartext des Spruchschluessels - */ - public String getSpruchschluessel() { - return this.spruchschluessel; - } - //endregion + //region Sonstige + + /** + * TODO: Wird nicht benutzt + * Prueft ob der Port auf dem das Kabel gesteckt werden soll, noch frei ist. + * <p> + * setSteckbrett ausfuehren mit beiden Buchstaben als String. + * + * @param buchstabe : char : Der zuletzt eingegebene Buchstabe. + * @return boolean : Wenn der Buchstabe nicht vorhanden ist, wird true zurueckgegeben, ansonsten false. + */ + public boolean pruefeSteckbrettPort(char buchstabe) { + return this.hardware.getSteckbrett().ueberpruefeVertauschungen(buchstabe); + } + + /** + * Liest aus der empfangenen Nachricht den Spruchschluessel aus und gibt ihn zurueck. + * + * @param empfangeneNachricht : String : Die empfangene Nachricht als String. + * @return String : Der Spruchschluessel, mit welcher die Nachricht codiert wurde. + */ + public String empfangenerSpruchschluessel(String empfangeneNachricht) { + String[] nachricht = empfangeneNachricht.split(" "); + + return nachricht[2]; + } + + /** + * Loescht das letzte Zeichen aus der Nachricht und dreht die Walzen eine Position zurueck. + */ + public void letztesZeichenLoeschen() { + this.hardware.dreheWalzen(-1); + this.nachricht = this.nachricht.substring(0, this.nachricht.length() - 1); + } + //endregion + //endregion + + //region Getter + + /** + * Liest die Kenngruppe aus, welche die Maschine gerade besitzt. Frueher war dies eine eindeutige Nummer, + * die einer Einheit zugewiesen war. Wir hinterlegen hier einen Benutzernamen. + * + * @return String : Kenngruppe + */ + public String getKenngruppe() { + return kenngruppe; + } + + /** + * Der Spruchschluessel wird, zur internen Verwendung, auch im Klartext gespeichert. + * Wir brauchen diesen dann zum Codieren der eigentlichen Nachricht. + * + * @return String : Der Klartext des Spruchschluessels + */ + public String getSpruchschluessel() { + return this.spruchschluessel; + } + //endregion }