Skip to content
Snippets Groups Projects
Commit 7bbe5aae authored by Flori N's avatar Flori N
Browse files
parents 7008813d bd734b79
No related branches found
No related tags found
1 merge request!109Master
......@@ -30,6 +30,7 @@ public class GuiController {
//endregion
//region GUI-Elemente
//deklariert die benötigten Buttons
@FXML
private Button btnA, btnB, btnC, btnD, btnE, btnF, btnG, btnH, btnI, btnJ, btnK, btnL, btnM, btnN, btnO, btnP, btnQ,
......@@ -78,15 +79,16 @@ public class GuiController {
menu(mBtnStartPos2, position);
// Initialisieren des Codierers und setzen der Kenngruppe
this.codierer = new Codierer();
this.codierer.setKenngruppe("enigma");
codierer = new Codierer();
if(codierer.getKenngruppe().equals(""))codierer.setKenngruppe("enigma");
else codierer.getKenngruppe();
// Beim nächsten Tastendruck erstmal das Display löschen damit falschen Nachrichten geschickt werden.
this.resetDisplay = true;
resetDisplay = true;
// Einstellungen aus dem Logbuch auslesen und setzen
this.setzeTagesSchluessel();
this.setzeSteckverbindungen();
setzeTagesSchluessel();
setzeSteckverbindungen();
}
//endregion
......@@ -392,8 +394,8 @@ public class GuiController {
setzeRing(2, Integer.parseInt(mItm.getText()) - 1);
if (mBtn.getId().equals(mBtnNotchPos3.getId()))
setzeRing(3, Integer.parseInt(mItm.getText()) - 1);
tfCodiert.setText("");
tfKlartext.setText("");
/* tfCodiert.setText("");
tfKlartext.setText("");*/
}
/**
......@@ -435,19 +437,24 @@ public class GuiController {
/**
* Holt Nachricht von Klasse Codierer und setzt den chiffrierten Text in das Textfeld tfCodiert,
* sowie den Klartext in das Textfeld tfKlartext. Setzt den
* sowie den Klartext in das Textfeld tfKlartext. Setzt den Spruchschlüssel
*/
private void empfangeFunkspruch() {
String[] empfangeneNachricht = this.codierer.empfangeNachricht();
if (empfangeneNachricht[0] != null) {
this.tfKlartext.setText(empfangeneNachricht[2]);
this.tfCodiert.setText(empfangeneNachricht[1]);
this.resetDisplay = true;
String[] empfangeneNachricht = codierer.empfangeNachricht();
System.out.println("text: " + empfangeneNachricht[0]);
System.out.println("Klartext: " + empfangeneNachricht[2]);
System.out.println("codiert: " + empfangeneNachricht[1]);
if (empfangeneNachricht[0]!=null) {
setzeTagesSchluessel();
System.out.println("empfange Nachricht");
tfKlartext.setText(empfangeneNachricht[2]);
tfCodiert.setText(empfangeneNachricht[1]);
resetDisplay = true;
// Spruchschluessel in das Feld lblSpruchschluessel schreiben
lblSpruchschluessel.setText(this.codierer.empfangenerSpruchschluessel(empfangeneNachricht[2]));
lblSpruchschluessel.setText(codierer.empfangenerSpruchschluessel(empfangeneNachricht[2]));
this.setzeTagesSchluessel();
}
}
......
......@@ -18,22 +18,27 @@ public class KenngruppeController {
* Beim drücken der Taste wird überprüft ob die eingegebene Kenngruppe weniger als 9 Zeichen hat und ob die
* eingegebenen Zeichen nur Buchstaben sind.
* Bei einer gültigen Eingabe wird die eingegebene Kenngruppe gespeichert und die Enigma-Anwendung gestartet
*
* @throws IOException :
*/
@FXML
private void btnGui() throws IOException {
if (tfKenngruppe.getText().length() <9) {
for (char c : tfKenngruppe.getText().toCharArray()) {
if (c == 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c == 'f' || c == 'g' || c == 'h' || c == 'i' || c == 'j' || c == 'k' || c == 'l' || c == 'm' || c == 'n' || c == 'o' || c == 'p' || c == 'q' || c == 'r' || c == 's' || c == 't' || c == 'u' || c == 'v' || c == 'w' || c == 'x' || c == 'y' || c == 'z'||c == 'A' || c == 'B' || c == 'C' || c == 'D' || c == 'E' || c == 'F' || c == 'G' || c == 'H' || c == 'I' || c == 'J' || c == 'K' || c == 'L' || c == 'M' || c == 'N' || c == 'O' || c == 'P' || c == 'Q' || c == 'R' || c == 'S' || c == 'T' || c == 'U' || c == 'V' || c == 'W' || c == 'X' || c == 'Y' || c == 'Z') {
cod.setKenngruppe(tfKenngruppe.getText());
//setzt
App.setRoot("gui");
}
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
boolean error = false;
for (char c : tfKenngruppe.getText().toUpperCase().toCharArray()) {
if (!alphabet.contains(String.valueOf(c))) {
error = true;
}
}
if (tfKenngruppe.getText().length() < 9 && !error) {
cod.setKenngruppe(tfKenngruppe.getText().toUpperCase());
//setzt
App.setRoot("gui");
} else {
tfKenngruppe.setStyle("-fx-background-color:#FF0000");
tfKenngruppe.setText("Fehlerhafte Kenngruppe!");
}
}
}
}
......@@ -14,520 +14,521 @@ import java.util.Random;
*/
public class Codierer {
//region Variablen
/**
* Der Klartext Spruchschlüssel zur codierung der Nachricht
*/
private String spruchschluessel;
/**
* Der Spruchschlüssel, mit den Tageswerten aus dem Codebuch, codiert
*/
private String spruchschluesselCodiert;
/**
* Die Kenngruppe für die versendeten Nachrichten gedacht sind. Diese ist relevant für den Webservice (Funkraum)
*/
private String kenngruppe;
/**
* Die Nachricht, welche der Benutzer eingibt, wird als String nachricht gespeichert
* und im laufe der Benutzung ergänzt
*/
private String nachricht;
/**
* Das Hardware Objekt. Hier werden alle Hardware relevanten Baugruppen gespeichert und verarbeitet.
*/
private Hardware hardware;
/**
* Im Codebuch sind die Tageswerte zu finden. Über dieses Objekt kann darauf zugegriffen werden.
*/
private Codebuch codebuch;
//endregion
//region Konstruktor
/**
* Der Konstruktor des Codierers
* Hier werden die globalen Variablen auf ihre Standart Werte gesetzt sowie die Objekte Initialisiert.
*/
public Codierer() {
this.nachricht = "";
this.spruchschluessel = "";
this.spruchschluesselCodiert = "";
this.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 zugewisen, da wir nur einen besitzen und
* deshalb alle Einstellungen hierfür Statisch im Reflektor definiert haben.
* <br>
* Das Steck wird ebenfalls definiert und die notwendigen Kabel eingesteckt laut dem heutigen
* Codebuch Eintrag.
*/
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 bekannt geben
this.hardware.setReflektor(new Reflektor());
}
/**
* Setzt die Enigma auf die Einstellungen des aktuellen Tages, aus dem Codebuch zurück.
*/
public void resetHardware() {
this.initialisiereHardware();
}
/**
* Leer das Nachrichten Objekt um eine neue Nachricht aufnehmen zu können
*/
public void resetNachricht() {
this.nachricht = "";
}
//endregion
//region Nachrichten handler
/**
* Befehl die Nachricht an den Funker zu übergeben
*
* @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 zurück
* <br>
* String[0] Tag wann die Nachricht gesendet wurde
* String[1] = Die verschlüsselte Nachricht
* String[2] = Nachricht im Klartext
*/
public String[] empfangeNachricht() {
// Alte Nachrichten Variable erstmal leeren
this.nachricht = "";
// Morsecode Objekt initialisieren
Morsecode mc = new Morsecode();
// Unser Nachrichten Array soll drei Einträge erhalten
String[] nachricht = new String[4];
// 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.length > 1 && codierteNachricht[1].split(" ").length > 3) {
// Den Tag der Nachricht speichern
nachricht[0] = codierteNachricht[0];
// Die Nachricht von Morsecode in Buchstaben konvertieren
nachricht[1] = mc.convertMorsecodeToBuchstabe(codierteNachricht[1]);
// Die Enigma Nachricht (nachricht[1]) mittels der Tageseinstellungen (nachricht[0]) decodieren
nachricht[2] = this.decodiere(nachricht[1], Integer.parseInt(nachricht[0]));
// StringBuilder initialisieren
StringBuilder sb = new StringBuilder();
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();
} else {
nachricht[0] = "";
nachricht[1] = "";
nachricht[2] = "Es liegen keine neuen Nachrichten im Funkraum für Sie vor.";
}
return nachricht;
}
//endregion
//region Generatoren
/**
* Hier wird ein neuer Spruchschlüssel generiert.
* <p>
* Mit diesem werden die Walzen auf eine neue Startposition gestellt und dem Kopf, mit dem
* Tagesschlüssel codiert, hinzugefügt.
* <br>
* Hierfür wird mittels der Funktion "randomBuchstabe" ein zufälliger Buchstabe generiert,
* und geschaut ob dieser bereits in der globalen Variable (this.spruchschluessel) vorhanden ist.
* Wenn nicht, wird der Buchstabe dem Spruchschlüssel hinzugefügt.
* <br>
* Dies wir nun so lange gemacht bis der Spruchschlüssel eine länge von drei Zeichen hat.
*/
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.
* Hierfür wird die aktuelle Uhrzeit ausgelesen, die Länge der Nachricht sowie der, mit den
* Tagescodes codierte, Spruchschlüssel.
*/
private String generateKopf() {
Calendar cal = Calendar.getInstance();
// Uhrzeit an den Kopf hängen
return String.format("%02d%02d", cal.get(Calendar.HOUR), cal.get(Calendar.MINUTE)) + " " +
// Zeichen Anzahl der Nachricht
this.nachricht.length() + " " +
// Spruchschlüssel anhängen
this.spruchschluesselCodiert.substring(0, 3) + " " + this.spruchschluesselCodiert.substring(3, 6) + " ";
}
/**
* Einen zufälligen Buchstaben aus dem Alphabet generieren.
* In der Funktion gibt es den String Alphabet, in welchem alle zulässigen Zeichen eingetragen sind.
* Aus diesem String wird nun zufällig ein Zeichen ausgewählt und zurück gegeben.
*
* @return String : ein zufällig generierter Buchstabe
*/
private String randomBuchstabe() {
return String.valueOf((char) ('A' + new Random().nextInt(26)));
}
//endregion
//region setzte Funktionen
/**
* Setzt den anzuzeigenden Buchstaben (buchstabe) auf der Walze (walzenPosition) und resetet anschließen das
* Nachrichten Objekt
*
* @param walzenPosition : int : Nummer der Walze
* @param buchstabe : char : Buchstabe der zugewiesen soll
*/
public void setzeWalze(int walzenPosition, char buchstabe) {
this.resetNachricht();
this.hardware.setzePosition(walzenPosition, buchstabe);
}
/**
* Setzt den Ring auf der Walze auf einen neuen Umstprungwert.
*
* @param walzenPosition : int : Walze auf die der Ring gesteckt wird
* @param umsprungPunkt : int : Buchstabe auf dem der Notch sitzt
*/
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) 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 das Kabel in beide Ports ein und fügt 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 nicht, 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 zurück
*
* @return int[] : Array mit den Ringstellungen der drei eingesetzten Walzen
*/
public int[] fetchRingstellung() {
return this.codebuch.getRingstellung();
}
/**
* Gibt die Walzennummer aus dem Codebuch zurück
*
* @return int[] : Array mit den Nummern der drei eingesetzten Walzen
*/
public int[] fetchWalzenNr() {
return this.codebuch.getWalzenlage();
}
/**
* Gibt die Steckverbindungen aus dem Codebuch zurück
*
* @return char[][] : Array mit den gesteckten Verbindungen im Steckbrett
*/
public char[][] fetchSteckverbindungen() {
return this.codebuch.getSteckverbindung();
}
/**
* Gibt die aktuellen Buchstaben auf den Walzen zurück
*
* @return char[] : Walzen Array mit der aktuellen Position
*/
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;
}
//endregion
//region codierer
/**
* Hier wird ein einzelner Buchstabe verschlüsselt.
* Man muss hier ebenfalls mitgeben ob der codierte String in Codierer.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 Übergebenen String.
* Man muss hier ebenfalls mitgeben ob der codierte String in Codierer.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 zusätzlich als Rückgabe
*/
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 weiß dein Funker im Funkraum.
* In der Regel ist dies der Tag des Nachrichten empfangs.
*
* @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
sb.append(nachricht[0]).append(" ");
// Zeichen Anzahl der Nachricht
sb.append(nachricht[1]).append(" ");
// Spruchschlüssel
String spruchschluessel = this.decodiereString(nachricht[2]);
sb.append(spruchschluessel).append(" ");
sb.append(this.decodiereString(nachricht[3])).append(" ");
// Walzen neu einstellen mit dem Spruchschlüssel
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 übergebenen String in einen char Array und decodiert jedes Zeichen.
* Der String wird dann decodiert zurück gegeben.
*
* @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
/**
* Prüft ob der Port auf den das Kabel gesteckt werden soll, noch frei ist.
* <p>
* setSteckbrett ausführen mit beiden Buchstaben als String
*
* @param buchstabe : char : Der zuletzt eingegebene Buchstabe
* @return boolean : Wenn der Buchstabe nicht vorhanden ist, wird true zurückgegeben, ansonsten false
*/
public boolean pruefeSteckbrettPort(char buchstabe) {
return this.hardware.getSteckbrett().ueberpruefeVertauschungen(buchstabe);
}
/**
* Ließt aus der empfangenen Nachricht den Spruchschlüssel aus und gibt ihn zurück.
*
* @param empfangeneNachricht : String : Die empfangene Nachricht als String
* @return String : Der Spruchschlüssel mit welcher die Nachricht codiert wurde.
*/
public String empfangenerSpruchschluessel(String empfangeneNachricht) {
String[] nachricht = empfangeneNachricht.split(" ");
return nachricht[2];
}
/**
* Löscht das letzte Zeichen aus der Nachricht und dreht die Walzen eine Position zurück.
*/
public void letztesZeichenLoeschen() {
this.hardware.dreheWalzen(-1);
}
//endregion
//endregion
//region Setter
/**
* Gibt die bisher erstellte Nachricht zurück
*
* @return String : Erstellte Nachricht
*/
public String getNachricht() {
return nachricht;
}
//endregion
//region Getter
/**
* Liest die Kenngruppe aus welche die Maschine gerade besitzt. Früher war dies eine eindeutige Nummer
* die einer Einheit zugewiesen war. Wir hinterlegen hier einen Benutzernamen.
*
* @return String : Kenngruppe
*/
public String getKenngruppe() {
return kenngruppe;
}
/**
* Setzt die Kenngruppe welche die Enigma gerade benutzt.
*
* @param kenngruppe : String : Kenngruppe welche die Enigma gerade benutzt
*/
public void setKenngruppe(String kenngruppe) {
this.kenngruppe = kenngruppe;
this.initialisiereHardware();
}
/**
* Der Spruchschlüssel wird, zur internen Verwendung, auch im Klartext gespeichert.
* Wir brauchen diesen dann zum codieren der eigentlichen Nachricht.
*
* @return String : Der klartext Spruchschlüssel
*/
public String getSpruchschluessel() {
return this.spruchschluessel;
}
//endregion
//region Variablen
/**
* Der Klartext Spruchschlüssel zur codierung der Nachricht
*/
private String spruchschluessel;
/**
* Der Spruchschlüssel, mit den Tageswerten aus dem Codebuch, codiert
*/
private String spruchschluesselCodiert;
/**
* Die Kenngruppe für die versendeten Nachrichten gedacht sind. Diese ist relevant für den Webservice (Funkraum)
*/
private String kenngruppe;
/**
* Die Nachricht, welche der Benutzer eingibt, wird als String nachricht gespeichert
* und im laufe der Benutzung ergänzt
*/
private String nachricht;
/**
* Das Hardware Objekt. Hier werden alle Hardware relevanten Baugruppen gespeichert und verarbeitet.
*/
private Hardware hardware;
/**
* Im Codebuch sind die Tageswerte zu finden. Über dieses Objekt kann darauf zugegriffen werden.
*/
private Codebuch codebuch;
//endregion
//region Konstruktor
/**
* Der Konstruktor des Codierers
* Hier werden die globalen Variablen auf ihre Standart Werte gesetzt sowie die Objekte Initialisiert.
*/
public Codierer() {
this.nachricht = "";
this.spruchschluessel = "";
this.spruchschluesselCodiert = "";
this.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 zugewisen, da wir nur einen besitzen und
* deshalb alle Einstellungen hierfür Statisch im Reflektor definiert haben.
* <br>
* Das Steck wird ebenfalls definiert und die notwendigen Kabel eingesteckt laut dem heutigen
* Codebuch Eintrag.
*/
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 bekannt geben
this.hardware.setReflektor(new Reflektor());
}
/**
* Setzt die Enigma auf die Einstellungen des aktuellen Tages, aus dem Codebuch zurück.
*/
public void resetHardware() {
this.initialisiereHardware();
}
/**
* Leer das Nachrichten Objekt um eine neue Nachricht aufnehmen zu können
*/
public void resetNachricht() {
this.nachricht = "";
}
//endregion
//region Nachrichten handler
/**
* Befehl die Nachricht an den Funker zu übergeben
*
* @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 zurück
* <br>
* String[0] Tag wann die Nachricht gesendet wurde
* String[1] = Die verschlüsselte Nachricht
* String[2] = Nachricht im Klartext
*/
public String[] empfangeNachricht() {
// Alte Nachrichten Variable erstmal leeren
this.nachricht = "";
// Morsecode Objekt initialisieren
Morsecode mc = new Morsecode();
// Unser Nachrichten Array soll drei Einträge erhalten
String[] nachricht = new String[4];
// 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.length > 1 && codierteNachricht[1].split(" ").length > 3) {
// Den Tag der Nachricht speichern
nachricht[0] = codierteNachricht[0];
// Die Nachricht von Morsecode in Buchstaben konvertieren
nachricht[1] = mc.convertMorsecodeToBuchstabe(codierteNachricht[1]);
// Die Enigma Nachricht (nachricht[1]) mittels der Tageseinstellungen (nachricht[0]) decodieren
nachricht[2] = this.decodiere(nachricht[1], Integer.parseInt(nachricht[0]));
// StringBuilder initialisieren
StringBuilder sb = new StringBuilder();
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();
} else {
nachricht[0] = "";
nachricht[1] = "";
nachricht[2] = "Es liegen keine neuen Nachrichten im Funkraum für Sie vor.";
}
return nachricht;
}
//endregion
//region Generatoren
/**
* Hier wird ein neuer Spruchschlüssel generiert.
* <p>
* Mit diesem werden die Walzen auf eine neue Startposition gestellt und dem Kopf, mit dem
* Tagesschlüssel codiert, hinzugefügt.
* <br>
* Hierfür wird mittels der Funktion "randomBuchstabe" ein zufälliger Buchstabe generiert,
* und geschaut ob dieser bereits in der globalen Variable (this.spruchschluessel) vorhanden ist.
* Wenn nicht, wird der Buchstabe dem Spruchschlüssel hinzugefügt.
* <br>
* Dies wir nun so lange gemacht bis der Spruchschlüssel eine länge von drei Zeichen hat.
*/
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.
* Hierfür wird die aktuelle Uhrzeit ausgelesen, die Länge der Nachricht sowie der, mit den
* Tagescodes codierte, Spruchschlüssel.
*/
private String generateKopf() {
Calendar cal = Calendar.getInstance();
// Uhrzeit an den Kopf hängen
return String.format("%02d%02d", cal.get(Calendar.HOUR), cal.get(Calendar.MINUTE)) + " " +
// Zeichen Anzahl der Nachricht
this.nachricht.length() + " " +
// Spruchschlüssel anhängen
this.spruchschluesselCodiert.substring(0, 3) + " " + this.spruchschluesselCodiert.substring(3, 6) + " ";
}
/**
* Einen zufälligen Buchstaben aus dem Alphabet generieren.
* In der Funktion gibt es den String Alphabet, in welchem alle zulässigen Zeichen eingetragen sind.
* Aus diesem String wird nun zufällig ein Zeichen ausgewählt und zurück gegeben.
*
* @return String : ein zufällig generierter Buchstabe
*/
private String randomBuchstabe() {
return String.valueOf((char) ('A' + new Random().nextInt(26)));
}
//endregion
//region setzte Funktionen
/**
* Setzt den anzuzeigenden Buchstaben (buchstabe) auf der Walze (walzenPosition) und resetet anschließen das
* Nachrichten Objekt
*
* @param walzenPosition : int : Nummer der Walze
* @param buchstabe : char : Buchstabe der zugewiesen soll
*/
public void setzeWalze(int walzenPosition, char buchstabe) {
this.resetNachricht();
this.hardware.setzePosition(walzenPosition, buchstabe);
}
/**
* Setzt den Ring auf der Walze auf einen neuen Umstprungwert.
*
* @param walzenPosition : int : Walze auf die der Ring gesteckt wird
* @param umsprungPunkt : int : Buchstabe auf dem der Notch sitzt
*/
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) 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 das Kabel in beide Ports ein und fügt 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 nicht, 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 zurück
*
* @return int[] : Array mit den Ringstellungen der drei eingesetzten Walzen
*/
public int[] fetchRingstellung() {
return this.codebuch.getRingstellung();
}
/**
* Gibt die Walzennummer aus dem Codebuch zurück
*
* @return int[] : Array mit den Nummern der drei eingesetzten Walzen
*/
public int[] fetchWalzenNr() {
return this.codebuch.getWalzenlage();
}
/**
* Gibt die Steckverbindungen aus dem Codebuch zurück
*
* @return char[][] : Array mit den gesteckten Verbindungen im Steckbrett
*/
public char[][] fetchSteckverbindungen() {
return this.codebuch.getSteckverbindung();
}
/**
* Gibt die aktuellen Buchstaben auf den Walzen zurück
*
* @return char[] : Walzen Array mit der aktuellen Position
*/
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;
}
//endregion
//region codierer
/**
* Hier wird ein einzelner Buchstabe verschlüsselt.
* Man muss hier ebenfalls mitgeben ob der codierte String in Codierer.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 Übergebenen String.
* Man muss hier ebenfalls mitgeben ob der codierte String in Codierer.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 zusätzlich als Rückgabe
*/
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 weiß dein Funker im Funkraum.
* In der Regel ist dies der Tag des Nachrichten empfangs.
*
* @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
sb.append(nachricht[0]).append(" ");
// Zeichen Anzahl der Nachricht
sb.append(nachricht[1]).append(" ");
// Spruchschlüssel
String spruchschluessel = this.decodiereString(nachricht[2]);
sb.append(spruchschluessel).append(" ");
sb.append(this.decodiereString(nachricht[3])).append(" ");
// Walzen neu einstellen mit dem Spruchschlüssel
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 übergebenen String in einen char Array und decodiert jedes Zeichen.
* Der String wird dann decodiert zurück gegeben.
*
* @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
/**
* Prüft ob der Port auf den das Kabel gesteckt werden soll, noch frei ist.
* <p>
* setSteckbrett ausführen mit beiden Buchstaben als String
*
* @param buchstabe : char : Der zuletzt eingegebene Buchstabe
* @return boolean : Wenn der Buchstabe nicht vorhanden ist, wird true zurückgegeben, ansonsten false
*/
public boolean pruefeSteckbrettPort(char buchstabe) {
return this.hardware.getSteckbrett().ueberpruefeVertauschungen(buchstabe);
}
/**
* Ließt aus der empfangenen Nachricht den Spruchschlüssel aus und gibt ihn zurück.
*
* @param empfangeneNachricht : String : Die empfangene Nachricht als String
* @return String : Der Spruchschlüssel mit welcher die Nachricht codiert wurde.
*/
public String empfangenerSpruchschluessel(String empfangeneNachricht) {
String[] nachricht = empfangeneNachricht.split(" ");
return nachricht[2];
}
/**
* Löscht das letzte Zeichen aus der Nachricht und dreht die Walzen eine Position zurück.
*/
public void letztesZeichenLoeschen() {
this.hardware.dreheWalzen(-1);
this.nachricht = this.nachricht.substring(0, this.nachricht.length() - 1);
}
//endregion
//endregion
//region Setter
/**
* Gibt die bisher erstellte Nachricht zurück
*
* @return String : Erstellte Nachricht
*/
public String getNachricht() {
return nachricht;
}
//endregion
//region Getter
/**
* Liest die Kenngruppe aus welche die Maschine gerade besitzt. Früher war dies eine eindeutige Nummer
* die einer Einheit zugewiesen war. Wir hinterlegen hier einen Benutzernamen.
*
* @return String : Kenngruppe
*/
public String getKenngruppe() {
return kenngruppe;
}
/**
* Setzt die Kenngruppe welche die Enigma gerade benutzt.
*
* @param kenngruppe : String : Kenngruppe welche die Enigma gerade benutzt
*/
public void setKenngruppe(String kenngruppe) {
this.kenngruppe = kenngruppe;
this.initialisiereHardware();
}
/**
* Der Spruchschlüssel wird, zur internen Verwendung, auch im Klartext gespeichert.
* Wir brauchen diesen dann zum codieren der eigentlichen Nachricht.
*
* @return String : Der klartext Spruchschlüssel
*/
public String getSpruchschluessel() {
return this.spruchschluessel;
}
//endregion
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment