Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • d.eisold/enigma
  • Janschubi1993/enigma
  • TsunamiKlaus/enigma
  • alfatrainingkurse/java/enigma
  • FloriN/enigma
  • PaoloPinkel/enigma
6 results
Show changes
Showing
with 2876 additions and 2547 deletions
package projekt.enigma; package projekt.enigma;
import projekt.enigma.model.Codierer;
import javafx.application.Application; import javafx.application.Application;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.scene.Parent; import javafx.geometry.Insets;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.VBox;
import javafx.stage.Stage; import javafx.stage.Stage;
import projekt.enigma.model.Fehler;
import java.io.IOException; import java.io.IOException;
/** /**
* JavaFX App * JavaFX App
* Startklasse fuer JavaFX Application, durch die Erweiterung um die Klasse Application.
* Baut die Benutzeroberflaeche in ihren Grundstrukturen auf.
*/ */
public class App extends Application { public class App extends Application {
/** /**
* TODO Dokumentieren * Deklariert den GuiController.
*/ */
private static Scene scene; private static GuiController gc;
private Codierer c;
/**
* debug : int : fuer die Funktion debug der Klasse Fehler notwendig.
*/
private static int debug;
/**
* Startet die Klasse App und setzt den debug-Wert 1.
*
* @param args : String[] : Standard-Kommandozeilen-Argument.
*/
public static void main(String[] args) {
debug = 0;
launch(args);
}
/**
* Gibt der Getter einen int > 0 zurueck, wird eine Meldung auf der Konsole ausgegeben.
*
* @return debug : int : bestimmt die Eingabe der debung-Methode in der Klasse Fehler.
*/
public static int getDebug() {
return debug;
}
/**
* Initialisierung der Variablen fuer die JavaFX Scene Kenngruppe.
* Abfrage der Kenngruppe und Reaktion auf die Eingabe.
*
* @param primaryStage : Stage : Fenster zur Eingabe der Kenngruppe.
* @throws IOException : wird bei fehlerhafter Eingabe geworfen.
*/
@Override
public void start(Stage primaryStage) throws IOException {
primaryStage.setTitle("Enigma");
primaryStage.setResizable(false);
Label lblEingbae = new Label("Bitte Kenngruppe eingeben!");
TextField tfEingabe = new TextField();
Button btnKenngruppe = new Button("Kenngruppe setzen!");
VBox layout = new VBox();
layout.setSpacing(10);
layout.setPadding(new Insets(20, 30, 10, 30));
btnKenngruppe.setMaxWidth(Double.MAX_VALUE);
// baut die Scene fuer die Kenngruppenabfrage auf
layout.getChildren().addAll(lblEingbae, tfEingabe, btnKenngruppe);
Scene sceKenngruppe = new Scene(layout);
/** // laden der FXML und der Enigma-Ansicht, um Ladezeiten zu verringern
* TODO Dokumentieren FXMLLoader guiLoader = new FXMLLoader(App.class.getResource("gui.fxml"));
* Scene sceApp = new Scene(guiLoader.load(), 962, 677);
* @param fxml
* @throws IOException
*/
static void setRoot(String fxml) throws IOException {
scene.setRoot(loadFXML(fxml));
}
/** /*Bestaetigen der Kenngruppe, Ausgabe einer Fehlermeldung im Fall einer falschen Eingabe und starten
* TODO Dokumentieren des Enigma-Fensters */
* tfEingabe.setOnKeyPressed(e -> {
* @param fxml if (e.getCode() == KeyCode.ENTER) {
* @return if (enter(tfEingabe.getText())) {
* @throws IOException gc = guiLoader.getController();
*/ gc.setKenngruppe(tfEingabe.getText());
private static Parent loadFXML(String fxml) throws IOException { primaryStage.setScene(sceApp);
FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml")); } else {
return fxmlLoader.load(); tfEingabe.setText("");
} new Fehler().showErrorDialog("error", "Kenngruppe falsch",
"Regeln für die Kenngruppe: 4-8 Zeichen sowie nur Buchstaben von A-Z.");
}
}
});
btnKenngruppe.setOnAction(e -> {
if (enter(tfEingabe.getText())) {
gc = guiLoader.getController();
gc.setKenngruppe(tfEingabe.getText());
primaryStage.setScene(sceApp);
} else {
tfEingabe.setText("");
new Fehler().showErrorDialog("error", "Kenngruppe falsch",
"Regeln für die Kenngruppe: 4-8 Zeichen sowie Buchstaben von A-Z.");
}
});
primaryStage.setScene(sceKenngruppe);
primaryStage.show();
}
/** /**
* TODO Dokumentieren * Ueberprueft die Gueltigkeit der Kenngruppeneingabe.
* * Nur Zeichen von A-Z sind zugelassen und die Kenngruppe muss aus mind. 4 und max. 8 Zeichen bestehen.
* @param args *
*/ * @param kenngruppe : String : Eingabewert aus dem Fenster.
public static void main(String[] args) { * @return result : boolean : ist die Kenngruppe ungueltig wird false zurueckgegeben, sonst true.
Application.launch(); */
} private boolean enter(String kenngruppe) {
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
boolean result = true;
/** for (char c : kenngruppe.toUpperCase().toCharArray()) {
* TODO Dokumentieren if (!alphabet.contains(String.valueOf(c))) {
* result = false;
* @param stage break;
* @throws IOException }
*/ }
@Override if ((kenngruppe.length() > 8) || (kenngruppe.length() < 4)) {
public void start(Stage stage) throws IOException { result = false;
scene = new Scene(loadFXML("gui")); }
stage.setScene(scene);
stage.setResizable(true);
stage.show();
}
return result;
}
} }
package projekt.enigma; package projekt.enigma;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.shape.Circle; import javafx.scene.shape.Circle;
import org.apache.http.HttpException; import javafx.stage.StageStyle;
import org.controlsfx.dialog.ProgressDialog;
import projekt.enigma.model.Codierer; import projekt.enigma.model.Codierer;
import projekt.enigma.model.Fehler;
import projekt.enigma.view.ChkBoxGridPane;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
public class GuiController { public class GuiController {
//region Klassenvariablen
private final static String[] walzenNr = {"I", "II", "III", "IV", "V"}; private final static String[] walzenNr = {"I", "II", "III", "IV", "V"};
private final static String[] ringNr = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"}; private final static String[] ringNr = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14",
private final static String[] position = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}; "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"};
private ArrayList<MenuItem> mItem; private final static String[] position = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
"O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
@FXML
private static ToggleButton[] tBtnPort;
private String[] empfangeneNachricht;
private String textEingabe; private String textEingabe;
private String textCodiert; private String textCodiert;
private char chiffrierterBuchstabe;
private boolean resetDisplay; private boolean resetDisplay;
private Codierer codierer; private Codierer codierer;
//region GUI-Elemente
//deklariert die benötigten Buttons
@FXML @FXML
private TextField tfStecker1; private Button btnA, btnB, btnC, btnD, btnE, btnF, btnG, btnH, btnI, btnJ, btnK, btnL, btnM, btnN, btnO, btnP, btnQ,
btnR, btnS, btnT, btnU, btnV, btnW, btnX, btnY, btnZ, btnSenden, btnEmpfangen, btnDelete, btnReset;
@FXML
private TextField tfStecker2;
@FXML
private TextField tfStecker3;
@FXML
private TextField tfStecker4;
@FXML
private TextField tfStecker5;
@FXML
private TextField tfStecker6;
@FXML
private TextField tfStecker7;
@FXML
private TextField tfStecker8;
@FXML
private TextField tfStecker9;
@FXML
private TextField tfStecker10;
@FXML
private Button btnM;
@FXML
private Button btnN;
@FXML
private Button btnB;
@FXML
private Button btnV;
@FXML
private Button btnC;
@FXML
private Button btnX;
@FXML
private Button btnY;
@FXML
private Button btnP;
@FXML
private Button btnL;
@FXML
private Button btnK;
@FXML
private Button btnJ;
@FXML
private Button btnH;
@FXML
private Button btnG;
@FXML
private Button btnF;
@FXML
private Button btnD;
@FXML @FXML
private Button btnS; private Button[] btnArray;
//endregion
//deklariert die benötigten Kreise
@FXML @FXML
private Button btnA; private Circle circA, circB, circC, circD, circE, circF, circG, circH, circI, circJ, circK, circL, circM, circN,
circO, circP, circQ, circR, circS, circT, circU, circV, circW, circX, circY, circZ;
//deklariert die benötigten Label
@FXML @FXML
private Button btnO; private Label lblSpruchschluessel, lblKenngruppe;
//deklariert die MenueButtons
@FXML @FXML
private Button btnI; private MenuButton mBtnWalzPos1, mBtnWalzPos2, mBtnWalzPos3, mBtnNotchPos1, mBtnNotchPos2, mBtnNotchPos3,
mBtnStartPos1, mBtnStartPos2, mBtnStartPos3;
@FXML //deklariert die benötigten Textfelder
private Button btnU;
@FXML
private Button btnZ;
@FXML
private Button btnT;
@FXML
private Button btnR;
@FXML
private Button btnE;
@FXML
private Button btnW;
@FXML
private Button btnQ;
@FXML
private Circle circL;
@FXML
private Circle circM;
@FXML
private Circle circN;
@FXML
private Circle circB;
@FXML
private Circle circV;
@FXML
private Circle circC;
@FXML
private Circle circX;
@FXML
private Circle circY;
@FXML
private Circle circP;
@FXML
private Circle circK;
@FXML
private Circle circJ;
@FXML
private Circle circH;
@FXML
private Circle circG;
@FXML
private Circle circF;
@FXML
private Circle circD;
@FXML @FXML
private Circle circS; private TextArea tfCodiert, tfKlartext;
//deklariert benötigtes GridPane
@FXML
private Circle circA;
@FXML
private Circle circO;
@FXML
private Circle circI;
@FXML
private Circle circU;
@FXML
private Circle circZ;
@FXML
private Circle circT;
@FXML
private Circle circR;
@FXML
private Circle circE;
@FXML
private Circle circW;
@FXML
private Circle circQ;
@FXML
private Label lblL;
@FXML
private Label lblM;
@FXML
private Label lblN;
@FXML
private Label lblB;
@FXML
private Label lblV;
@FXML
private Label lblC;
@FXML
private Label lblX;
@FXML
private Label lblY;
@FXML
private Label lblP;
@FXML
private Label lblK;
@FXML
private Label lblJ;
@FXML
private Label lblH;
@FXML
private Label lblG;
@FXML
private Label lblF;
@FXML
private Label lblD;
@FXML
private Label lblS;
@FXML
private Label lblA;
@FXML
private Label lblQ;
@FXML
private Label lblW;
@FXML
private Label lblE;
@FXML
private Label lblR;
@FXML
private Label lblT;
@FXML
private Label lblZ;
@FXML
private Label lblU;
@FXML
private Label lblI;
@FXML
private Label lblO;
@FXML
private TextField tfCodiert;
@FXML
private TextField tfKlartext;
@FXML
private ProgressBar pbLadeNachricht;
@FXML
private MenuButton mBtnWalzPos1;
@FXML
private MenuButton mBtnWalzPos2;
@FXML
private MenuButton mBtnWalzPos3;
@FXML
private MenuButton mBtnNotchPos1;
@FXML
private MenuButton mBtnNotchPos2;
@FXML
private MenuButton mBtnNotchPos3;
@FXML
private MenuButton mBtnStartPos1;
@FXML
private MenuButton mBtnStartPos2;
@FXML
private MenuButton mBtnStartPos3;
@FXML @FXML
private Label lblLadeNachricht; private ChkBoxGridPane[] chkBoxGridPane;
@FXML @FXML
private Label lblTagesschluessel; private GridPane mainGrid;
@FXML @FXML
private Label lblSpruchschluessel; private AnchorPane anchorPane;
/**
* Initialisiert die Elemente GUI und setzt deren Startwerte
*/
@FXML @FXML
void initialize() { void initialize() {
// Variablen setzen // Variablen setzen
textEingabe = ""; textEingabe = "";
textCodiert = ""; textCodiert = "";
...@@ -352,178 +93,455 @@ public class GuiController { ...@@ -352,178 +93,455 @@ public class GuiController {
menu(mBtnStartPos1, position); menu(mBtnStartPos1, position);
menu(mBtnStartPos3, position); menu(mBtnStartPos3, position);
menu(mBtnStartPos2, position); menu(mBtnStartPos2, position);
btnArray = new Button[]{btnA, btnB, btnC, btnD, btnE, btnF, btnG, btnH, btnI, btnJ, btnK, btnL, btnM, btnN,
btnO, btnP, btnQ, btnR, btnS, btnT, btnU, btnV, btnW, btnX, btnY, btnZ};
//Setze Leucht Event bei Tastendruck tfKlartext.textProperty().addListener((ChangeListener<Object>) (observableValue, o, t1) ->
leuchten(btnA, circA); tfKlartext.setScrollTop(Double.MAX_VALUE));
leuchten(btnB, circB); tfCodiert.textProperty().addListener((ChangeListener<Object>) (observableValue, o, t1) ->
leuchten(btnC, circC); tfCodiert.setScrollTop(Double.MAX_VALUE));
leuchten(btnD, circD); }
leuchten(btnE, circE); //endregion
leuchten(btnF, circF);
leuchten(btnG, circG);
leuchten(btnH, circH);
leuchten(btnI, circI);
leuchten(btnJ, circJ);
leuchten(btnK, circK);
leuchten(btnL, circL);
leuchten(btnM, circM);
leuchten(btnN, circN);
leuchten(btnO, circO);
leuchten(btnP, circP);
leuchten(btnQ, circQ);
leuchten(btnR, circR);
leuchten(btnS, circS);
leuchten(btnT, circT);
leuchten(btnU, circU);
leuchten(btnV, circV);
leuchten(btnW, circW);
leuchten(btnX, circX);
leuchten(btnY, circY);
leuchten(btnZ, circZ);
// Initialisieren des Codierers und setzen der Kenngruppe //region Init
this.codierer = new Codierer();
this.codierer.setKenngruppe("enigma");
// Beim nächsten Tastendruck erstmal das Display löschen damit falschen Nachrichten geschickt werden. /**
this.resetDisplay = true; * init Methode zur Erstellung der Einträge und Action Listener für die einzelnen Menüs
*
* @param button : Button für die die Einträge erstellt werden sollen
*/
private void menu(MenuButton button, String[] str) {
ArrayList<MenuItem> mItem = new ArrayList<>();
// Einstellungen aus dem Logbuch auslesen und setzen for (int i = 0; i < str.length; i++) {
this.setzeTagesSchluessel(); // Eintrag aus str der Arraylist mi hinzufügen
mItem.add(new MenuItem(str[i]));
// MenuItem mi dem Button button hinzufügen
button.getItems().add(mItem.get(i));
int finalI = i;
// Listener für die einzelnen Einträge
mItem.get(i).setOnAction(e -> setMenuBtnText(button, mItem.get(finalI)));
}
} }
/** /**
* TODO: Die Löschen Funktion muss noch ausgeschrieben werden. Der letzte char muss aus beiden * Erzeugt Buttons um die Steckverbindungen zu auszuwählen
* Feldern entfernt werden.
* Der Codierer muss den letzten Buchstaben aus (codierer.nachricht) löschen und die Walzen um eines zurück drehen.
*/ */
@FXML private void myToggleButtons() {
private void loeschen() { if (chkBoxGridPane != null) {
if (textEingabe.length() == 0) { for (ChkBoxGridPane boxGridPane : chkBoxGridPane) {
tfKlartext.setText(""); anchorPane.getChildren().remove(boxGridPane);
} else { }
textEingabe = textEingabe.substring(0, textEingabe.length() - 1); }
tfKlartext.setText(textEingabe); chkBoxGridPane = new ChkBoxGridPane[10];
final ToggleGroup cabelConnect = new ToggleGroup();
tBtnPort = new ToggleButton[chkBoxGridPane.length];
for (int i = 0; i < chkBoxGridPane.length; i++) {
tBtnPort[i] = new ToggleButton(this.codierer.fetchSteckverbindungen()[i][0] + "" +
this.codierer.fetchSteckverbindungen()[i][1]);
tBtnPort[i].setToggleGroup(cabelConnect);
tBtnPort[i].setMinWidth(50.0);
GridPane.setHalignment(tBtnPort[i], HPos.CENTER);
mainGrid.add(tBtnPort[i], i + 1, 8);
this.createPortPane(i);
chkBoxGridPane[i].setVisible(false);
}
// ToggleButtonGroup Listener
cabelConnect.selectedToggleProperty().
addListener((observable, oldValue, newValue) -> {
for (int j = 0; j < chkBoxGridPane.length; j++) {
if (cabelConnect.getSelectedToggle() == tBtnPort[j]) {
this.createPortPane(j);
} else if (cabelConnect.getSelectedToggle() != tBtnPort[j]) {
if (chkBoxGridPane[j] != null) {
chkBoxGridPane[j].setVisible(false);
}
}
}
});
}
/**
* Erstellt ein GridPane mit CheckBoxen an der Position des übergebenen port
*
* @param port => entspricht der Position des gewählten ToggleButton
*/
private void createPortPane(int port) {
if (chkBoxGridPane[port] != null) {
anchorPane.getChildren().remove(chkBoxGridPane[port]);
} }
chkBoxGridPane[port] = new ChkBoxGridPane(
this.codierer,
port,
tBtnPort[port]);
chkBoxGridPane[port].setVisible(false);
chkBoxGridPane[port].setStyle("-fx-background-color: white; -fx-border-color: black;");
chkBoxGridPane[port].setPrefHeight(chkBoxGridPane[port].getCharSize() * 22);
chkBoxGridPane[port].setPrefWidth(85.0);
chkBoxGridPane[port].setPadding(new Insets(10, 10, 10, 10));
chkBoxGridPane[port].setAlignment(Pos.CENTER);
chkBoxGridPane[port].setLayoutX(
(anchorPane.getWidth() / 12) * (port + 1) -
((chkBoxGridPane[port].getPrefWidth() - anchorPane.getWidth() / 12) / 2));
chkBoxGridPane[port].setLayoutY(
mainGrid.getLayoutY() + ((anchorPane.getHeight() -
mainGrid.getLayoutY()) / 10 * 9) - chkBoxGridPane[port].getPrefHeight() - 15);
anchorPane.getChildren().add(chkBoxGridPane[port]);
chkBoxGridPane[port].setVisible(true);
} }
/**
* Wird ausgelöst wenn der gedrückte Button losgelassen wird.
* Setzt die Hintergrundfarbe des Kreises mit dem chiffrierten Buchstaben auf grau,
* durch Aufruf der Methode leuchten.
*
* @param e => übergibt den zuletzt losgelassenen Button
*/
@FXML @FXML
void btnempfangen() { void tasteRauf(MouseEvent e) {
String[] empfangeneNachricht = this.codierer.empfangeNachricht(); for(Button btn : btnArray) {
if (empfangeneNachricht[0] != null) { if (e.getSource() == btn) leuchten(chiffCircle(chiffrierterBuchstabe), BUCHSTABE_LEUCHTET.AUS);
this.tfKlartext.setText(empfangeneNachricht[2]); }
this.tfCodiert.setText(empfangeneNachricht[1]); }
this.resetDisplay = true; //endregion
// Spruchschluessel in das Feld lblSpruchschluessel schreiben //region EventHandler/Listener
lblSpruchschluessel.setText(this.codierer.empfangenerSpruchschluessel(empfangeneNachricht[2]));
this.setzeTagesSchluessel(); /**
} * Wird ausgelöst sobald eine Taste gedrückt wird (beim drücken der Taste)
* Auswertung welche Buchstaben-Taste gedrückt ist.
* Übergabe des entspechenden Buchstaben als Parameter der Methode setText welche den chiffrierten Buchstaben
* in der Klassen-Variablen chiffrierterBuchstabe ablegt.
* Setzt die Hintergrundfarbe des Kreises mit dem chiffrierten Buchstaben auf gelb
*
* @param e => übergibt den momentan gedrückten Buttons
*/
@FXML
void tasteRunter(MouseEvent e) {
for(Button btn : btnArray) {
if (e.getSource() == btn) {
if (setText(btn)) {
leuchten(chiffCircle(chiffrierterBuchstabe), BUCHSTABE_LEUCHTET.AN);
}
}
}
} }
/**
* Auswertung welcher Button (senden, empfangen oder löschen) gedrückt wurde.
* Funktionsaufruf entsprechend des gedrückten Button
*
* @param e => ActionEvent des auslösenden Button
*/
@FXML @FXML
void btnsenden() { private void gedrueckteTaste(ActionEvent e) {
this.tfKlartext.setText(""); if (e.getSource() == btnSenden) {
this.tfCodiert.setText(""); if (tfCodiert.getText().equals("")) {
new Fehler().showErrorDialog("warning", "Haben Sie heute nichts zu sagen?",
"Nutzung von militärischer Infrastruktur ohne Grund ist verboten.");
} else {
sendeFunkspruch();
}
}
if (e.getSource() == btnEmpfangen) empfangeFunkspruch();
if (e.getSource() == btnDelete) loeschen();
if (e.getSource() == btnReset) {
codierer.resetHardware();
this.resetDisplay = true;
this.lblSpruchschluessel.setText("");
this.setzeTagesSchluessel();
}
}
try { /**
this.codierer.sendeNachricht(); * Setzt die Hintergrundfarbe des Kreises (chiffrierter Buchstabe) auf gelb bzw. auf grau.
} catch (HttpException | IOException e) { *
e.printStackTrace(); * @param leuchte => gibt an welcher Kreis (chiffrierter Buchstabe) den Hintergrund ändern soll
* @param shiningLetter => "AN" -> setzt Hintergrundfarbe des Kreises (chiffrierter Buchstabe) auf gelb
* "AUS" -> setzt Hintergrundfarbe des Kreises (chiffrierter Buchstabe) auf grau
*/
private void leuchten(Circle leuchte, BUCHSTABE_LEUCHTET shiningLetter) {
if (shiningLetter == BUCHSTABE_LEUCHTET.AN) leuchte.setStyle("-fx-fill: #FFA500");
else if (shiningLetter == BUCHSTABE_LEUCHTET.AUS) {
leuchte.setStyle("-fx-background-color: grey");
leuchte.setStyle("-fx-border-color: #000000");
} }
}
//endregion
//region Methoden
/**
* Gibt den Buchstabenkreis entsprechend des chiffrierten Buchstabens zurück
*
* @param chiffLetter => chiffrierter Buchstabe
* @return => Kreis des chiffrierten Buchstabens (der leuchten soll)
*/
private Circle chiffCircle(char chiffLetter) {
switch (chiffLetter) {
case 'A':
return circA;
case 'B':
return circB;
case 'C':
return circC;
case 'D':
return circD;
case 'E':
return circE;
case 'F':
return circF;
case 'G':
return circG;
case 'H':
return circH;
case 'I':
return circI;
case 'J':
return circJ;
case 'K':
return circK;
case 'L':
return circL;
case 'M':
return circM;
case 'N':
return circN;
case 'O':
return circO;
case 'P':
return circP;
case 'Q':
return circQ;
case 'R':
return circR;
case 'S':
return circS;
case 'T':
return circT;
case 'U':
return circU;
case 'V':
return circV;
case 'W':
return circW;
case 'X':
return circX;
case 'Y':
return circY;
case 'Z':
return circZ;
}
return null;
} }
/** /**
* Methode zum setzen des menuButton Textes auf das ausgewählte MenuItem * Methode zum setzen des menuButton Textes auf das ausgewählte MenuItem
* *
* @param mb : MenuButton der Walze * @param mBtn : MenuButton der Walze
* @param mi : MenuItem * @param mItm : MenuItem
*/ */
private void listener(MenuButton mb, MenuItem mi) { private void setMenuBtnText(MenuButton mBtn, MenuItem mItm) {
// mb.setText(mi.getText()); if (mBtn.getId().equals(mBtnStartPos1.getId())) {
setzePosition(1, mItm.getText().charAt(0));
if (mb.getId().equals(mBtnStartPos1.getId())) setzePosition(1, mi.getText().charAt(0)); this.codierer.setzeWalzenPosition(0, mItm.getText().charAt(0));
if (mb.getId().equals(mBtnStartPos2.getId())) setzePosition(2, mi.getText().charAt(0)); }
if (mb.getId().equals(mBtnStartPos3.getId())) setzePosition(3, mi.getText().charAt(0)); if (mBtn.getId().equals(mBtnStartPos2.getId())) {
if (mb.getId().equals(mBtnWalzPos1.getId())) setzeWalze(1, mi.getText()); setzePosition(2, mItm.getText().charAt(0));
if (mb.getId().equals(mBtnWalzPos2.getId())) setzeWalze(2, mi.getText()); this.codierer.setzeWalzenPosition(1, mItm.getText().charAt(0));
if (mb.getId().equals(mBtnWalzPos3.getId())) setzeWalze(3, mi.getText()); }
if (mb.getId().equals(mBtnNotchPos1.getId())) if (mBtn.getId().equals(mBtnStartPos3.getId())) {
setzeRing(1, Integer.parseInt(mi.getText()) - 1); setzePosition(3, mItm.getText().charAt(0));
if (mb.getId().equals(mBtnNotchPos2.getId())) this.codierer.setzeWalzenPosition(2, mItm.getText().charAt(0));
setzeRing(2, Integer.parseInt(mi.getText()) - 1); }
if (mb.getId().equals(mBtnNotchPos3.getId())) if (mBtn.getId().equals(mBtnWalzPos1.getId())) {
setzeRing(3, Integer.parseInt(mi.getText()) - 1); setzeWalze(1, mItm.getText());
if (!mBtnWalzPos1.getText().equals(mBtnWalzPos2.getText()) &&
!mBtnWalzPos1.getText().equals(mBtnWalzPos3.getText())) {
this.codierer.setzeWalzeNr(0,
convertRoemischToZahl(mItm.getText()) + 1,
mBtnNotchPos1.getText().charAt(0));
} else {
setzeWalze(1, convertZahlToRoemisch(this.codierer.fetchWalzenNr(0)));
new Fehler().showErrorDialog("error",
"Walze nicht gefunden",
"Es scheint so das wir von jeder Walze nur eine da haben");
}
}
if (mBtn.getId().equals(mBtnWalzPos2.getId())) {
setzeWalze(2, mItm.getText());
if (!mBtnWalzPos1.getText().equals(mBtnWalzPos2.getText()) &&
!mBtnWalzPos2.getText().equals(mBtnWalzPos3.getText())) {
this.codierer.setzeWalzeNr(1,
convertRoemischToZahl(mItm.getText()) + 1,
mBtnNotchPos2.getText().charAt(0));
} else {
setzeWalze(2, convertZahlToRoemisch(this.codierer.fetchWalzenNr(1)));
new Fehler().showErrorDialog("error",
"Walze nicht gefunden",
"Es scheint so das wir von jeder Walze nur eine da haben");
}
}
if (mBtn.getId().equals(mBtnWalzPos3.getId())) {
setzeWalze(3, mItm.getText());
if (!mBtnWalzPos1.getText().equals(mBtnWalzPos3.getText()) &&
!mBtnWalzPos2.getText().equals(mBtnWalzPos3.getText())) {
this.codierer.setzeWalzeNr(2,
convertRoemischToZahl(mItm.getText()) + 1,
mBtnNotchPos3.getText().charAt(0));
} else {
setzeWalze(3, convertZahlToRoemisch(this.codierer.fetchWalzenNr(2)));
new Fehler().showErrorDialog("error",
"Walze nicht gefunden",
"Es scheint so das wir von jeder Walze nur eine da haben");
}
}
if (mBtn.getId().equals(mBtnNotchPos1.getId())) {
setzeRing(1, Integer.parseInt(mItm.getText()) - 1);
this.codierer.setzeRing(0, Integer.parseInt(mItm.getText()) - 1);
}
if (mBtn.getId().equals(mBtnNotchPos2.getId())) {
setzeRing(2, Integer.parseInt(mItm.getText()) - 1);
this.codierer.setzeRing(1, Integer.parseInt(mItm.getText()) - 1);
}
if (mBtn.getId().equals(mBtnNotchPos3.getId())) {
setzeRing(3, Integer.parseInt(mItm.getText()) - 1);
this.codierer.setzeRing(2, Integer.parseInt(mItm.getText()) - 1);
}
tfCodiert.setText("");
tfKlartext.setText("");
} }
/** /**
* Methode zur Erstellung der Einträge und Action Listener für die einzelnen Menüs * Die Löschen Funktion löscht das letzte Zeichen im Klartext sowie im Codiert Feld,
* * der Codierer wird aufgerufen um ebenfalls das letzte Zeichen zu löschen
* @param button : Button für die die Einträge erstellt werden sollen
*/ */
private void menu(MenuButton button, String[] str) { private void loeschen() {
mItem = new ArrayList<>(); if (textEingabe.length() == 0) {
for (int i = 0; i < str.length; i++) { tfKlartext.setText("");
//Eintrag aus str der Arraylist mi hinzufügen tfCodiert.setText("");
mItem.add(new MenuItem(str[i])); } else {
//MenuItem mi dem Button button hinzufügen textEingabe = textEingabe.substring(0, textEingabe.length() - 1);
button.getItems().add(mItem.get(i)); textCodiert = textCodiert.substring(0, textCodiert.length() - 1);
int finalI = i; tfKlartext.setText(textEingabe);
//Listener für die einzelnen Einträge tfCodiert.setText(textCodiert);
ArrayList<MenuItem> finalMi = mItem; codierer.letztesZeichenLoeschen();
mItem.get(i).setOnAction(e -> listener(button, finalMi.get(finalI))); mBtnStartPos1.setText(String.valueOf(this.codierer.fetchWalzen()[0]));
mBtnStartPos2.setText(String.valueOf(this.codierer.fetchWalzen()[1]));
mBtnStartPos3.setText(String.valueOf(this.codierer.fetchWalzen()[2]));
} }
} }
/** /**
* Auswertung welcher Button gedrückt wurde * Holt Nachricht von Klasse Codierer und setzt den chiffrierten Text in das Textfeld tfCodiert,
* sowie den Klartext in das Textfeld tfKlartext. Setzt den Spruchschlüssel
*/
private void empfangeFunkspruch() {
progressDialogue("rx");
try {
if (this.empfangeneNachricht[2] != null && this.empfangeneNachricht[1] != null) {
setzeTagesSchluessel();
tfKlartext.setText(this.empfangeneNachricht[2]);
tfCodiert.setText(this.empfangeneNachricht[1]);
resetDisplay = true;
// Spruchschluessel in das Feld lblSpruchschluessel schreiben
lblSpruchschluessel.setText(codierer.empfangenerSpruchschluessel(this.empfangeneNachricht[2]));
}
} catch (NullPointerException ignored) {
new Fehler().showErrorDialog(
"warning",
"Keiner schreibt dir...",
"Es liegen keine neuen Nachrichten im Funkraum für Sie vor.");
}
}
/**
* Senden der Nachricht mit Hilfe der Klasse Codierer
* Löscht die Textfelder tfKlartext und tfCodiert
*/
private void sendeFunkspruch() {
this.tfKlartext.setText("");
this.tfCodiert.setText("");
progressDialogue("tx");
}
/**
* Methode die das ProgressDialog Fenster erstellt und verwaltet
* *
* @param e => ActionEvent des auslösenden Button * @param strRxTx : String : RX => empfangen
* TX => senden
*/ */
@FXML private void progressDialogue(String strRxTx) {
private void gedrueckteTaste(ActionEvent e) { Task copyWorker = createWorker(strRxTx);
ProgressIndicator pi = new ProgressIndicator();
pi.setProgress(-1);
ProgressDialog dialog = new ProgressDialog(copyWorker);
dialog.initStyle(StageStyle.TRANSPARENT);
dialog.setTitle("Kommunikation zum Funkraum");
if (strRxTx.equals("rx")) {
dialog.setContentText("Empfange Nachricht");
} else if (strRxTx.equals("tx")) {
dialog.setContentText("Sende Nachricht");
}
dialog.setHeaderText(null);
dialog.setGraphic(pi);
dialog.initStyle(StageStyle.UTILITY);
new Thread(copyWorker).start();
dialog.showAndWait();
}
//TODO Anbindung an Klasse Hardware /**
if (e.getSource() == btnA) setText(btnA); * Thread Worker für Nachricht senden / empfangen
if (e.getSource() == btnB) setText(btnB); *
if (e.getSource() == btnC) setText(btnC); * @param strRxTx : String : RX => empfangen
if (e.getSource() == btnD) setText(btnD); * TX => senden
if (e.getSource() == btnE) setText(btnE); * @return boolean
if (e.getSource() == btnF) setText(btnF); */
if (e.getSource() == btnG) setText(btnG); private Task createWorker(String strRxTx) {
if (e.getSource() == btnH) setText(btnH); return new Task() {
if (e.getSource() == btnI) setText(btnI); @Override
if (e.getSource() == btnJ) setText(btnJ); protected Object call() {
if (e.getSource() == btnK) setText(btnK); if (strRxTx.equals("rx")) {
if (e.getSource() == btnL) setText(btnL); empfangeneNachricht = codierer.empfangeNachricht();
if (e.getSource() == btnM) setText(btnM); } else if (strRxTx.equals("tx")) {
if (e.getSource() == btnN) setText(btnN); try {
if (e.getSource() == btnO) setText(btnO); codierer.sendeNachricht();
if (e.getSource() == btnP) setText(btnP); } catch (IOException e) {
if (e.getSource() == btnQ) setText(btnQ); e.printStackTrace();
if (e.getSource() == btnR) setText(btnR); }
if (e.getSource() == btnS) setText(btnS); }
if (e.getSource() == btnT) setText(btnT);
if (e.getSource() == btnU) setText(btnU); return true;
if (e.getSource() == btnV) setText(btnV); }
if (e.getSource() == btnW) setText(btnW); };
if (e.getSource() == btnX) setText(btnX);
if (e.getSource() == btnY) setText(btnY);
if (e.getSource() == btnZ) setText(btnZ);
} }
/** /**
* schreibt Buchstaben des gedrückten Knopfes in Textfeld tfrein * Schreibt Buchstaben des gedrückten Button in Textfeld tfKlartext.
* Übergabe des Buchstaben vom gedrückten Button an die Klasse Codierer
* Ablegen des chiffrierten Buchstaben in der char Variable chiffrierterBuchstabe
* Hinzufügen des chiffrierten Buchstaben in Textfeld tfCodiert
* Aktualisierung der Walzenstellung
* *
* @param b : gedrückter Knopf * @param pressedButton : gedrückter Knopf
*/ */
private void setText(Button b) { private boolean setText(Button pressedButton) {
if (textEingabe.length() < 250) { if (textEingabe.length() < 250) {
if (this.resetDisplay) { if (this.resetDisplay) {
this.tfCodiert.setText(""); this.tfCodiert.setText("");
this.tfKlartext.setText(""); this.tfKlartext.setText("");
this.lblSpruchschluessel.setText("");
this.resetDisplay = false; this.resetDisplay = false;
this.codierer.resetHardware(); this.codierer.resetHardware();
textCodiert = ""; textCodiert = "";
...@@ -533,68 +551,130 @@ public class GuiController { ...@@ -533,68 +551,130 @@ public class GuiController {
// Spruchschluessel in das Feld lblSpruchschluessel schreiben // Spruchschluessel in das Feld lblSpruchschluessel schreiben
lblSpruchschluessel.setText(this.codierer.getSpruchschluessel()); lblSpruchschluessel.setText(this.codierer.getSpruchschluessel());
} }
textEingabe += b.getText(); textEingabe += pressedButton.getText();
textCodiert += this.codierer.codiere(b.getText().charAt(0), true); chiffrierterBuchstabe = codierer.codiere(pressedButton.getText().charAt(0), true);
textCodiert += chiffrierterBuchstabe;
tfKlartext.setText(textEingabe); tfKlartext.setText(textEingabe);
tfKlartext.appendText("");
tfCodiert.setText(textCodiert); tfCodiert.setText(textCodiert);
tfKlartext.appendText("");
// Position der Walzen aktuallisieren // Position der Walzen aktuallisieren
mBtnStartPos1.setText(String.valueOf(this.codierer.getWalzen()[0])); mBtnStartPos1.setText(String.valueOf(this.codierer.fetchWalzen()[0]));
mBtnStartPos2.setText(String.valueOf(this.codierer.getWalzen()[1])); mBtnStartPos2.setText(String.valueOf(this.codierer.fetchWalzen()[1]));
mBtnStartPos3.setText(String.valueOf(this.codierer.getWalzen()[2])); mBtnStartPos3.setText(String.valueOf(this.codierer.fetchWalzen()[2]));
}
}
private void leuchten(Button taste, Circle leuchte) {
taste.setOnMousePressed(mouseEvent -> leuchte.setStyle("-fx-fill: #FFA500")); return true;
taste.setOnMouseReleased(mouseEvent -> { } else {
leuchte.setStyle("-fx-background-color: " + taste.getBackground()); new Fehler().showErrorDialog("error", "Wir wussten das du das testen wirst", "250 Zeichen sind " +
leuchte.setStyle("-fx-border-color: #000000"); "selbst für die Wehrmacht zu viel!");
}); return false;
}
} }
/** /**
* Setzt die Anzeige des entsprechende Gui-Element auf die entsprechende Walze * Konvertiert eine rämische Zahl in eine arabische Zahl
* ->d.h. welche Walze sitzt auf welcher Position
* *
* @param walzeRoemischNr => gibt die Walzennummer an * @param nummer : String : Römische Zahl
* @param walzenPosition => gibt die Position der Walze * @return int : arabische Zahl
*/ */
private void setzeWalze(int walzenPosition, String walzeRoemischNr) { private int convertRoemischToZahl(String nummer) {
int walzeNr = 0; int result = 0;
switch (walzeRoemischNr) {
switch (nummer) {
case "I": case "I":
walzeNr = 0; result = 0;
break; break;
case "II": case "II":
walzeNr = 1; result = 1;
break; break;
case "III": case "III":
walzeNr = 2; result = 2;
break; break;
case "IV": case "IV":
walzeNr = 4; result = 3;
break; break;
case "V": case "V":
walzeNr = 4; result = 4;
break; break;
default: default:
break; break;
} }
return result;
}
/**
* Konvertiert eine arabische Zahl in eine rämische Zahl
*
* @param nummer : int : arabische Zahl
* @return String : römische Zahl
*/
private String convertZahlToRoemisch(int nummer) {
String result = "";
switch (nummer) {
case 0:
result = "I";
break;
case 1:
result = "II";
break;
case 2:
result = "III";
break;
case 3:
result = "IV";
break;
case 4:
result = "V";
break;
default:
break;
}
return result;
}
/**
* Setzt die Anzeige des entsprechende Gui-Element auf die entsprechende Walze
* ->d.h. welche Walze sitzt auf welcher Position
*
* @param walzeRoemischNr => gibt die Walzennummer an
* @param walzenPosition => gibt die Position der Walze
*/
private void setzeWalze(int walzenPosition, String walzeRoemischNr) {
switch (walzenPosition) { switch (walzenPosition) {
case 1: case 1:
mBtnWalzPos1.setText(walzenNr[walzeNr]); mBtnWalzPos1.setText(walzenNr[convertRoemischToZahl(walzeRoemischNr)]);
//codierer.setWalze(walzeNr, walzenPosition)
break; break;
case 2: case 2:
mBtnWalzPos2.setText(walzenNr[walzeNr]); mBtnWalzPos2.setText(walzenNr[convertRoemischToZahl(walzeRoemischNr)]);
break;
case 3:
mBtnWalzPos3.setText(walzenNr[convertRoemischToZahl(walzeRoemischNr)]);
break;
default:
break;
}
}
/**
* Setzt die Anzeige des entsprechende Gui-Element auf die entsprechende Walze
* -> d.h. welche Walze sitzt auf welcher Position
*
* @param walzenPosition => gibt die Position der Walze
* @param walzeNr => gibt die Walzennummer an
*/
private void setzeWalze(int walzenPosition, int walzeNr) {
switch (walzenPosition) {
case 1:
mBtnWalzPos1.setText(walzenNr[walzeNr - 1]);
break;
case 2:
mBtnWalzPos2.setText(walzenNr[walzeNr - 1]);
break; break;
case 3: case 3:
mBtnWalzPos3.setText(walzenNr[walzeNr]); mBtnWalzPos3.setText(walzenNr[walzeNr - 1]);
break; break;
default: default:
break; break;
...@@ -648,71 +728,57 @@ public class GuiController { ...@@ -648,71 +728,57 @@ public class GuiController {
} }
/** /**
* Setzt den aktuellen TagesSchluessel * Setzt den aktuellen TagesSchluessel und zeigt diesen in der GUI an
*/ */
public void setzeTagesSchluessel() { private void setzeTagesSchluessel() {
// Umsprungpunkte anzeigen // Umsprungpunkte anzeigen
mBtnNotchPos1.setText(String.valueOf(this.codierer.fetchRingstellung()[0])); mBtnNotchPos1.setText(String.valueOf(codierer.fetchRingstellung()[0]));
mBtnNotchPos2.setText(String.valueOf(this.codierer.fetchRingstellung()[1])); mBtnNotchPos2.setText(String.valueOf(codierer.fetchRingstellung()[1]));
mBtnNotchPos3.setText(String.valueOf(this.codierer.fetchRingstellung()[2])); mBtnNotchPos3.setText(String.valueOf(codierer.fetchRingstellung()[2]));
// Walzennummern anzeigen // Walzennummern anzeigen
mBtnWalzPos1.setText(String.valueOf(this.codierer.getchWalzenNr()[0])); setzeWalze(1, codierer.fetchWalzenNr()[0]);
mBtnWalzPos2.setText(String.valueOf(this.codierer.getchWalzenNr()[1])); setzeWalze(2, codierer.fetchWalzenNr()[1]);
mBtnWalzPos3.setText(String.valueOf(this.codierer.getchWalzenNr()[2])); setzeWalze(3, codierer.fetchWalzenNr()[2]);
// Position der Walzen anzeigen // Position der Walzen anzeigen
mBtnStartPos1.setText(String.valueOf(this.codierer.getWalzen()[0])); mBtnStartPos1.setText(String.valueOf(codierer.fetchWalzen()[0]));
mBtnStartPos2.setText(String.valueOf(this.codierer.getWalzen()[1])); mBtnStartPos2.setText(String.valueOf(codierer.fetchWalzen()[1]));
mBtnStartPos3.setText(String.valueOf(this.codierer.getWalzen()[2])); mBtnStartPos3.setText(String.valueOf(codierer.fetchWalzen()[2]));
// Steckbrett Felder setzen // Steckbrett Felder setzen
// TODO: Das er das String.valueOf ausgraut, gefällt mir nicht, genauso wie den langen Block. myToggleButtons();
// Hat da noch jemand eine bessere Idee?
tfStecker1.setText( // Felder zurück setzen
String.valueOf(this.codierer.getSteckverbindungen()[0][0]) + this.textCodiert = "";
String.valueOf(this.codierer.getSteckverbindungen()[0][1])); this.textEingabe = "";
tfStecker2.setText( this.tfKlartext.setText("");
String.valueOf(this.codierer.getSteckverbindungen()[1][0]) + this.tfCodiert.setText("");
String.valueOf(this.codierer.getSteckverbindungen()[1][1])); }
tfStecker3.setText(
String.valueOf(this.codierer.getSteckverbindungen()[2][0]) + /**
String.valueOf(this.codierer.getSteckverbindungen()[2][1])); * Lädt die Daten aus dem Codebuch und setzt die Kenngruppe in der Gui
tfStecker4.setText( *
String.valueOf(this.codierer.getSteckverbindungen()[3][0]) + * @param kenngruppe : String : aktuelle Kenngruppe
String.valueOf(this.codierer.getSteckverbindungen()[3][1])); */
tfStecker5.setText( void setKenngruppe(String kenngruppe) {
String.valueOf(this.codierer.getSteckverbindungen()[4][0]) +
String.valueOf(this.codierer.getSteckverbindungen()[4][1])); // Initialisieren des Codierers und setzen der Kenngruppe
tfStecker6.setText( codierer = new Codierer(kenngruppe.toUpperCase());
String.valueOf(this.codierer.getSteckverbindungen()[5][0]) +
String.valueOf(this.codierer.getSteckverbindungen()[5][1])); this.codierer.resetHardware();
tfStecker7.setText(
String.valueOf(this.codierer.getSteckverbindungen()[6][0]) +
String.valueOf(this.codierer.getSteckverbindungen()[6][1]));
tfStecker8.setText(
String.valueOf(this.codierer.getSteckverbindungen()[7][0]) +
String.valueOf(this.codierer.getSteckverbindungen()[7][1]));
tfStecker9.setText(
String.valueOf(this.codierer.getSteckverbindungen()[8][0]) +
String.valueOf(this.codierer.getSteckverbindungen()[8][1]));
tfStecker10.setText(
String.valueOf(this.codierer.getSteckverbindungen()[9][0]) +
String.valueOf(this.codierer.getSteckverbindungen()[9][1]));
/*
* TODO Benötige TestString aus der DB Codebuch
*
* Den Tagesschlüssel bekommst du wie folgt:
* <p>
* // Aktuelle Position der Walzen
* codierer.codebuch.getWalzenlage();
*
* // Position der Ringe
* codierer.codebuch.getRingstellung();
*
* //Position der Steckverbindungen
* codierer.codebuch.getSteckverbindung();
* </p>
*/
// Setzt die Kenngruppe in der GUI
lblKenngruppe.setText("Kenngruppe: " + this.codierer.getKenngruppe());
// Beim nächsten Tastendruck erstmal das Display löschen damit falschen Nachrichten geschickt werden.
resetDisplay = true;
// Einstellungen aus dem Logbuch auslesen und setzen
setzeTagesSchluessel();
} }
private enum BUCHSTABE_LEUCHTET {AN, AUS}
//endregion
} }
package projekt.enigma;
import java.io.IOException;
import javafx.fxml.FXML;
public class KenngruppeController {
@FXML
private void switchToPrimary() throws IOException {
App.setRoot("gui");
}
}
\ No newline at end of file
package projekt.enigma; package projekt.enigma;
/**
import java.sql.SQLException; * Startpunkt des Programms. Startet die Klasse App und damit die GUI.
*/
public class Main { public class Main {
public static void main(String[] args) throws SQLException { /**
* Startet die App
*
* @param args : String[] : Standard-Kommandozeilen-Parameter.
*/
public static void main(String[] args) {
App.main(args); App.main(args);
} }
} }
...@@ -3,25 +3,24 @@ package projekt.enigma.database; ...@@ -3,25 +3,24 @@ package projekt.enigma.database;
import java.sql.*; import java.sql.*;
/** /**
* Dies ist die SQLite Datenbank Klasse * Dies ist die SQLite Datenbank Klasse.
* In der SQLite Datei im Resources Ordner liegt das Codebuch welches benötigt wird um die * In der SQLite Datei im Resources Ordner liegt das Codebuch welches benoetigt wird um die
* Nachrichten mit der Enigma zu ver/entschlüsseln. * Nachrichten mit der Enigma zu ver/entschluesseln.
* Die Datenbank ist statisch und deshalb konnte sie im Resources Ordner hinterlegt werden. * Die Datenbank ist statisch und deshalb konnte sie im Resources Ordner hinterlegt werden.
* Für jeden Tag des Monats (1-31) ist ein eigener Eintrag enthalten welcher über die Funktion * Für jeden Tag des Monats (1-31) ist ein eigener Eintrag enthalten welcher ueber die Funktion
* getCodebuch abgerufen werden kann. * getCodebuch abgerufen werden kann.
* Zurückgegeben wird ein Array welcher in der getCodebuch Funktion genauer dokumentiert ist. * Zurueckgegeben wird ein Array welcher in der getCodebuch Funktion genauer dokumentiert ist.
*/ */
public class DatenbankSqlite { public class DatenbankSqlite {
/** /**
* Verbindung zur SQLite Datenbank aufbauen. * Verbindung zur SQLite Datenbank aufbauen.
* Die Datei liegt in den Resources und ändert sich nicht, * Die Datei liegt in den Resources und aendert sich nicht,
* weshalb der Pfad zu derselben fest hinterlegt ist. * weshalb der Pfad zu derselben fest hinterlegt ist.
* *
* @return conn : Connection * @return conn : Connection: statische Datenbankverbindung.
*/ */
private Connection connect() { private Connection connect() {
String url = "jdbc:sqlite::resource:projekt/enigma/codebuch.sqlite"; String url = "jdbc:sqlite::resource:projekt/enigma/codebuch.sqlite";
Connection conn = null; Connection conn = null;
...@@ -35,15 +34,15 @@ public class DatenbankSqlite { ...@@ -35,15 +34,15 @@ public class DatenbankSqlite {
} }
/** /**
* Liest das Codebuch aus der SQLite Datenbank aus * Liest das Codebuch aus der SQLite Datenbank aus.
* Dieser Funktion muss ein tag als int Wert übergeben werden. * Dieser Funktion muss ein tag als int Wert uebergeben werden.
* Anschließend wir eine Verbindung zur SQLite Datenbank aufgebaut und das Codebuch angefragt. * Anschließend wird eine Verbindung zur SQLite Datenbank aufgebaut und das Codebuch angefragt.
* Dieses wird in ein Object vom Type Codebuch gepackt und zurück gegeben. * Dieses wird in ein Objekt vom Typ Codebuch gepackt und zurueckgegeben.
* *
* Hole den heutigen Eintrag aus der SQLite Datenbank und erstelle daraus ein Codebuch Objekt * Holt den heutigen Eintrag aus der SQLite Datenbank und erstellt daraus ein Codebuch Objekt.
* *
* @param tag : int : Tag für welchen ein Codebuch benötigt wird. * @param tag : int : Tag fuer welchen ein Codebuch benoetigt wird.
* @return String : Die Einstellungen des angefragten Tages * @return String : Die Einstellungen des angefragten Tages.
* <p> * <p>
* String[0] : Tag * String[0] : Tag
* String[1] : Walzenlage * String[1] : Walzenlage
...@@ -52,12 +51,11 @@ public class DatenbankSqlite { ...@@ -52,12 +51,11 @@ public class DatenbankSqlite {
* </p> * </p>
*/ */
public String[] getCodebuch(int tag) { public String[] getCodebuch(int tag) {
String[] codebuch = new String[4]; String[] codebuch = new String[4];
try { try {
Connection conn = this.connect(); Connection conn = this.connect();
PreparedStatement pstm = conn.prepareStatement("SELECT * FROM table_codebuch WHERE Tag=? LIMIT 1"); PreparedStatement pstm = conn.prepareStatement("SELECT * FROM table_codebuch WHERE Tag = ? LIMIT 1");
pstm.setInt(1, tag); pstm.setInt(1, tag);
ResultSet rs = pstm.executeQuery(); ResultSet rs = pstm.executeQuery();
...@@ -67,101 +65,8 @@ public class DatenbankSqlite { ...@@ -67,101 +65,8 @@ public class DatenbankSqlite {
codebuch[2] = rs.getString("Ringstellung"); codebuch[2] = rs.getString("Ringstellung");
codebuch[3] = rs.getString("Steckverbindung"); codebuch[3] = rs.getString("Steckverbindung");
} }
} catch (SQLException ignored) { } catch (SQLException ignored) {}
}
return codebuch; return codebuch;
} }
//region Random New Codebuch generieren
/**
* Setzt zufällige Codebuch Einträge in die SQLite Datenbank
* Tag => int
* Walzenlage => String w1,w2,w3
* Ringstellung => String r1,r2,r3
* Steckverbindungen => s0,s1,s2,s3,s4,s5,s6,s7,s8,s9
*/
/*
public void autoGenCodebuch() throws SQLException {
Connection conn = connect();
conn.setAutoCommit(false);
PreparedStatement pstmtInsert = conn.prepareStatement("INSERT INTO table_codebuch (Tag, Walzenlage, Ringstellung, Steckverbindung) VALUES (?, ?, ?, ?);");
for (int i = 3; i < 32; i++) {
pstmtInsert.setInt(1, i);
pstmtInsert.setString(2, walzenlage());
pstmtInsert.setString(3, ringstellung());
pstmtInsert.setString(4, steckverbindung());
pstmtInsert.executeUpdate();
}
conn.commit();
}
/**
* Generiert einen String aus 3 Zufalls-Zahlen(zwischen 1 und 5)
* die Zahlen sind durch Komma getrennt
* @return String => walzenlage mit drei Kommaseparierten Zufallszahlen zwischen 1 und 5
*/
/*
private static String walzenlage(){
String walzenlage;
Random random = new Random();
int[] w = new int[3];
for (int i = 0; i < 3; i++) {
w[i] = (random.nextInt(5))+1;
if (i==1&&w[0]==w[i])w[i]=(random.nextInt(5))+1;
if ((i==2&&w[0]==w[2])||(i==2&&w[1]==w[i]))w[i]=(random.nextInt(5))+1;
}
walzenlage= w[0]+","+w[1]+","+w[2];
return walzenlage;
}*/
/**
* Generiert einen String aus 3 Zufalls-Zahlen(zwischen 1 und 26)
* die Zahlen sind durch Komma getrennt
* @return String => ringstellung mit drei Kommaseparierten Zufallszahlen zwischen 1 und 26
*/
/*
private static String ringstellung(){
String ringstellung;
Random random = new Random();
int[] w = new int[3];
for (int i = 0; i < 3; i++) {
w[i] = (random.nextInt(26))+1;
}
ringstellung= w[0]+","+w[1]+","+w[2];
return ringstellung;
}*/
/**
* Generiert einen String aus 10 * 2 unterschiedlichen Großbuchstaben
* @return String => 10 Buchstabenkombinationen mit Komma getrennt
*//*
private static String steckverbindung(){
Random rnd = new Random();
String steckverbindung="";
char[] c = new char[20];
for (int i = 0; i < 20; i++) {
c[i] = (char) (rnd.nextInt(26) + 'A');
for (int j = i; j >= 0; j--) {
if (i>j) {
while (c[i]==c[j]) {
c[i] = (char) (rnd.nextInt(26) + 'A');
j= i-1;
}
}
}
}
steckverbindung = ((""+c[0]) + (""+c[1]) +"," +(""+c[2]) +(""+c[3]) + ","+(""+c[4]) +(""+c[5]) + ","+(""+c[6]) +(""+c[7]) + ","
+(""+c[8]) +(""+c[9]) + ","+(""+c[10]) +(""+c[11]) + ","+(""+c[12]) +(""+c[13]) + ","+(""+c[14]) +(""+c[15]) + ","+(""+c[16]) +(""+c[17]) + ","
+(""+c[18]) +(""+c[19]));
// System.out.println(steckverbindung);
// steckverbindung= (String) steckverbindung.subSequence(0,steckverbindung.lastIndexOf(","));
return steckverbindung;
}*/
//endregion
} }
...@@ -6,51 +6,54 @@ import java.time.LocalDate; ...@@ -6,51 +6,54 @@ import java.time.LocalDate;
import java.time.ZoneId; import java.time.ZoneId;
/** /**
* Das Codebuch war eines der essentiel wichtigen Sachen bei der Enigma. * Das Codebuch war eines der essentiell wichtigen Sachen bei der Enigma.
* Jeder Enigma gehörte auch ein Codebuch bei, welches notwendig war um die Nachrichten zu ver/entschlüsseln. * Jeder Enigma gehoerte auch ein Codebuch bei, welches notwendig war um die Nachrichten zu ver/entschluesseln.
* Im Codebuch standen für jeden Tag des Monats die notwendigen Einstellungen welche vorgenommen werden * Im Codebuch standen für jeden Tag des Monats die notwendigen Einstellungen welche vorgenommen werden
* mussten um die Texte zu ver/entschlüsseln. * mussten, um die Texte zu ver/entschluesseln.
* Hiernach wurden die Walzen eingesetzt, die Ringe für den Rücksprung der Walze gesetzt und deren Grundeinstellung * Hiernach wurden die Walzen eingesetzt, die Ringe für den Ruecksprung der Walze gesetzt und deren Grundeinstellung
* vorgenommen. * vorgenommen.
* Bei der Enigma um welche es hier geht (Enigma I) gab es zusätzlich ein Steckbrett, welches ebenfalls im Codebuch * Bei der Enigma I, um welche es hier geht, gab es zusaetzlich ein Steckbrett, welches ebenfalls im Codebuch
* festgelegt war. * festgelegt war.
* <p> * <p>
* Dieses Codebuch Objekt enthält die Einstellungen eines Tages, welche mittels Getter und Setter * Dieses Codebuch enthaelt die Einstellungen eines Tages, welche mittels Getter und Setter
* verarbeitet werden können. * verarbeitet werden koennen.
* <p> * <p>
* Zusätzlich gibt es zu Debug Zwecken eine überschriebene toString Funktion welche das Objekt als String zurück * Zusaetzlich gibt es zu Debug-Zwecken eine ueberschriebene toString Funktion, welche das Objekt als String
* geben kann. * zurueckgeben kann.
*/ */
public class Codebuch { public class Codebuch {
//region Variablen
/** /**
* TODO: Dokumentieren tag * tag : int : gibt den Tag eines Monats an.
* tag : int : gibt den Tag an
*/ */
private int tag; private int tag;
/** /**
* walzenlage : int[] : legt die Positionen der Walzen fest * walzenlage : int[] : legt die Positionen der drei Walzen fest.
*/ */
private int[] walzenlage; private int[] walzenlage;
/** /**
* ringstellung : int[] : TODO ringstellung: char || int ? * ringstellung : int[] : legt die Ringstellungen der drei Walzen fest.
*/ */
private int[] ringstellung; private int[] ringstellung;
/** /**
* steckverbindung : char[][] : stellt die Steckverbindungen im Steckbrett dar * steckverbindung : char[][] : legt die Steckverbindungen im Steckbrett fest.
*/ */
private char[][] steckverbindung; private char[][] steckverbindung;
//endregion
//region Konstruktor
/** /**
* Im Konstruktor werden die Standardwerte gesetzt * Im Konstruktor werden die Standardwerte gesetzt.
* <p> * <p>
* walzenlage : int[3] : Hier wird die Position der drei Walzen festgelegt. * walzenlage : int[3] : Hier wird die Position der drei Walzen festgelegt.
* ringstellung : char[3] : Jede Walze hat einen Ring. Der Index steht für die Walze und der Value für * ringstellung : char[3] : Jede Walze hat einen Ring. Der Index steht fuer die Walze und der Value fuer
* die Position des Ringes. * die Position des Ringes.
* steckverbindung : char[10][] : Zehn Kabel können in das Steckbrett gesteckt werden. In diesem Array werden * steckverbindung : char[10][] : Zehn Kabel koennen in das Steckbrett gesteckt werden. In diesem Array werden
* die Kabel mit ihren jeweiligen Buchsen hinterlegt. * die Kabel mit ihren jeweiligen Buchsen hinterlegt.
*/ */
public Codebuch() { public Codebuch() {
...@@ -65,13 +68,15 @@ public class Codebuch { ...@@ -65,13 +68,15 @@ public class Codebuch {
} }
} }
//endregion
//region Funktionen & Methoden
/** /**
* TODO: Dokumentieren
* Holt den Tagesschluessel aus dem Codebuch ab. Ist kein Tag angegeben, wird der aktuelle Tag genutzt. * Holt den Tagesschluessel aus dem Codebuch ab. Ist kein Tag angegeben, wird der aktuelle Tag genutzt.
* Aus dem Tagesschluessel werden die Werte fuer die Walzenlage, Ringstellung und Steckverbindung * Aus dem Tagesschluessel werden die Werte fuer die Walzenlage, Ringstellung und Steckverbindung
* gesetzt. * gesetzt.
* *
* @param tag : int[] : gibt einen Tag oder mehrere Tage mit * @param tag : int[] : gibt keinen, einen Tag oder mehrere Tage mit.
*/ */
public void fetchTagesschluessel(int... tag) { public void fetchTagesschluessel(int... tag) {
String[] walzenlage, ringstellung, db; String[] walzenlage, ringstellung, db;
...@@ -84,6 +89,7 @@ public class Codebuch { ...@@ -84,6 +89,7 @@ public class Codebuch {
this.setTag(Integer.parseInt(db[0])); this.setTag(Integer.parseInt(db[0]));
// setzen der Walzenlage, Ringstellung, Steckverbindung
walzenlage = db[1].split(","); walzenlage = db[1].split(",");
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
this.setWalzenlage(i, Integer.parseInt(walzenlage[i])); this.setWalzenlage(i, Integer.parseInt(walzenlage[i]));
...@@ -95,14 +101,13 @@ public class Codebuch { ...@@ -95,14 +101,13 @@ public class Codebuch {
} }
this.setSteckverbindung(db[3].split(",")); this.setSteckverbindung(db[3].split(","));
} }
/** /**
* Gibt die aktuelle Instanz des Codebuches als String zurück. * Gibt die aktuelle Instanz des Codebuches als String zurueck.
* Hierbei werden der Tag die Walzenlagen, Ring-/Grundstellung sowie die Steckverbindungen zurück gegeben. * Hierbei werden der Tag die Walzenlagen, Ring-/Grundstellung sowie die Steckverbindungen zurueckgegeben.
* *
* @return String : String des gesamten Objektes * @return String : String des gesamten Objektes.
*/ */
@Override @Override
public String toString() { public String toString() {
...@@ -144,86 +149,93 @@ public class Codebuch { ...@@ -144,86 +149,93 @@ public class Codebuch {
return sb.toString(); return sb.toString();
} }
//endregion
//region Setter
/** /**
* Gibt den Tag dieser Instanz zurück * Setzt die Steckverbindung dieser Instanz.
* *
* @return int : Tag * @param kabel : String[] : Die Steckverbindungen die gesteckt werden sollen.
* Jeder Eintrag im Array ist ein String mit zwei Zeichen.
* Diese werden in zwei chars zerlegt und anschließend im globalen Array gespeichert.
*/ */
public int getTag() { private void setSteckverbindung(String[] kabel) {
return tag; int counter = 0;
for (String stecker : kabel) {
char[] verbindung = new char[2];
verbindung[0] = stecker.charAt(0);
verbindung[1] = stecker.charAt(1);
this.steckverbindung[counter++] = verbindung;
}
} }
/** /**
* Setzt den Tag dieser Instanz * Setzt die Walzenlage dieser Instanz.
* *
* @param tag : int : Tag * @param position : int : Position der Walze.
* @param walzenlage : int : Welche Walze wurde eingesetzt.
*/ */
void setTag(int tag) { this.tag = tag; } private void setWalzenlage(int position, int walzenlage) {
this.walzenlage[position] = walzenlage;
}
/** /**
* Gibt die Walzenlage dieser Instanz zurück * Setzt die Ringstellung dieser Instanz.
* *
* @return String[] : Walzenlage TODO: String[] || int[]? * @param position : int : Auf welche Walze wird der Ring aufgesetzt?
* @param ringstellung : int : An dieser Position soll die nächste Walze weiter gedreht werden.
*/ */
public int[] getWalzenlage() { private void setRingstellung(int position, int ringstellung) {
return walzenlage; this.ringstellung[position] = ringstellung;
} }
/** /**
* Gibt die Ringstellung dieser Instanz zurück * Setzt den Tag dieser Instanz.
* *
* @return String[] : Ringstellung TODO: String[] || int[]? * @param tag : int : Tag.
*/ */
public int[] getRingstellung() { void setTag(int tag) {
return ringstellung; this.tag = tag;
} }
//endregion
//region Getter
/** /**
* Gibt die Steckverbindung dieser Instanz zurück * Gibt den Tag dieser Instanz zurueck.
* *
* @return String[] : Steckverbindung * @return int : Tag.
*/ */
// TODO public int getTag() {
public char[][] getSteckverbindung() { return tag;
return this.steckverbindung;
} }
/** /**
* Setzt die Steckverbindung dieser Instanz * Gibt die Walzenlage dieser Instanz zurueck.
* *
* @param kabel : String[] : Die Steckverbindungen die gesteckt werden sollen. * @return walzenlage : int[] : Walzenlage.
* Jeder Eintrag im Array ist ein String mit zwei Zeichen.
* Diese werden in zwei chars zerlegt und anschließend im globalen
* Array gespeichert.
*/ */
private void setSteckverbindung(String[] kabel) { public int[] getWalzenlage() {
int counter = 0; return walzenlage;
for (String stecker : kabel) {
char[] verbindung = new char[2];
verbindung[0] = stecker.charAt(0);
verbindung[1] = stecker.charAt(1);
this.steckverbindung[counter++] = verbindung;
}
} }
/** /**
* Setzt die Walzenlage dieser Instanz * Gibt die Ringstellung dieser Instanz zurueck.
* *
* @param position : int : Position der Walze * @return ringstellung : int : Ringstellung.
* @param walzenlage : int : Welche Walze wurde eingesetzt
*/ */
private void setWalzenlage(int position, int walzenlage) { public int[] getRingstellung() {
this.walzenlage[position] = walzenlage; return ringstellung;
} }
/** /**
* Setzt die Ringstellung dieser Instanz * Gibt die Steckverbindungen dieser Instanz zurueck.
* *
* @param position : int : Auf welche Walze wird der Ring aufgesetzt? * @return steckerverbindung : char[][] : Steckverbindung.
* @param ringstellung : char : An dieser Position soll die nächste Walze weiter gedreht werden.TODO: String[] || int[]?
*/ */
private void setRingstellung(int position, int ringstellung) { public char[][] getSteckverbindung() {
this.ringstellung[position] = ringstellung; return this.steckverbindung;
} }
//endregion
} }
package projekt.enigma.model; package projekt.enigma.model;
import org.apache.http.HttpException;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Random; import java.util.Random;
/** /**
* Die Codierer Klasse beschreibt den Benutzer welcher die Enigma benutzt. * Die Codierer-Klasse beschreibt den Benutzer, welcher die Enigma benutzt.
* Alle Vorgänge wie z.B. das zusammenbauen der Hardware, auslesen des Codebuches und das anschließende codieren, * Alle Vorgaenge, wie z.B. das zusammenbauen der Hardware, auslesen des Codebuches und das anschließende codieren,
* finden hier statt. Dieser ist quasi die Schnittstelle zwischen der GUI (Hauptmann welcher ihm sagt was er zu * finden hier statt. Dieser ist quasi die Schnittstelle zwischen der GUI (Hauptmann, welcher ihm sagt was er zu
* verschlüsseln hat), der Enigma und dem Funker im Funkraum, welcher die Nachricht im Anschluß versendet. * verschluesseln hat), der Enigma und dem Funker im Funkraum, welcher die Nachricht im Anschluss versendet.
*/ */
public class Codierer { public class Codierer {
/** //region Variablen
* Der Klartext Spruchschlüssel zur codierung der Nachricht /**
*/ * Der Spruchschluessel als Klartext zur Codierung der Nachricht.
private String spruchschluessel; */
/** private String spruchschluessel;
* Der Spruchschlüssel, mit den Tageswerten aus dem Codebuch, codiert
*/ /**
private String spruchschluesselCodiert; * Der Spruchschluessel, mit den Tageswerten aus dem Codebuch, codiert.
/** */
* Die Kenngruppe für die versendeten Nachrichten gedacht sind. Diese ist relevant für den Webservice (Funkraum) private String spruchschluesselCodiert;
*/
private String kenngruppe; /**
/** * Die Kenngruppe fuer die die versendeten Nachrichten gedacht sind.
* Die Nachricht, welche der Benutzer eingibt, wird als String nachricht gespeichert * Diese ist relevant fuer den Webservice (Funkraum).
* und im laufe der Benutzung ergänzt */
*/ private String kenngruppe;
private String nachricht;
/** /**
* Das Hardware Objekt. Hier werden alle Hardware relevanten Baugruppen gespeichert und verarbeitet. * Die Nachricht, welche der Benutzer eingibt, wird als String "nachricht" gespeichert
*/ * und im Laufe der Benutzung ergaenzt.
private Hardware hardware; */
/** private String nachricht;
* Im Codebuch sind die Tageswerte zu finden. Über dieses Objekt kann darauf zugegriffen werden.
*/ /**
private Codebuch codebuch; * Das Hardware-Objekt. Hier werden alle hardwarerelevanten Baugruppen gespeichert und verarbeitet.
/** */
* Der aktuelle Tagesschluessel. Dieser wird aus dem Codebuch ausgelesen und hier hinterlegt. private Hardware hardware;
*/
private String tagesSchluessel; /**
* Im Codebuch sind die Tageswerte zu finden. Ueber dieses Objekt kann darauf zugegriffen werden.
/** */
* Der Konstruktor des Codierers private Codebuch codebuch;
* Hier werden die globalen Variablen auf ihre Standart Werte gesetzt sowie die Objekte Initialisiert. //endregion
*/
public Codierer() { //region Konstruktor
this.nachricht = ""; /**
this.spruchschluessel = ""; * Der Konstruktor des Codierers.
this.spruchschluesselCodiert = ""; * Hier werden die globalen Variablen auf ihre Standardwerte gesetzt sowie die Objekte initialisiert.
this.kenngruppe = ""; */
this.codebuch = new Codebuch(); public Codierer(String kenngruppe) {
this.codebuch.fetchTagesschluessel(); this.nachricht = "";
} this.spruchschluessel = "";
this.spruchschluesselCodiert = "";
/** this.kenngruppe = kenngruppe;
* Hier lesen wir den heutigen Eintrag aus dem Codebuch aus und erstellen ein Codebuch Objekt this.codebuch = new Codebuch();
* Nach dem Codebuch werden dann die Ringe auf die Walzen gesteckt und die Walzen anschließend
* in die Hardware gebaut. this.codebuch.fetchTagesschluessel();
* <br> }
* Ein Reflektor wird definiert, jedoch keine Werte zugewisen, da wir nur einen besitzen und //endregion
* deshalb alle Einstellungen hierfür Statisch im Reflektor definiert haben.
* <br> //region Funktionen & Methoden
* Das Steck wird ebenfalls definiert und die notwendigen Kabel eingesteckt laut dem heutigen //region Reset & Initialisieren
* Codebuch Eintrag.
*/ /**
private void initialisiereHardware() { * 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
// Das Steckbrett initialisieren * in die Hardware gebaut.
Steckbrett sb = new Steckbrett(); * <br>
char[][] verbinder = this.codebuch.getSteckverbindung(); * Ein Reflektor wird definiert, jedoch keine Werte zugewiesen, da wir nur einen besitzen und
* deshalb alle Einstellungen hierfuer statisch im Reflektor definiert haben.
// Für jedes Kabel eine Verbindung auf dem Steckbrett setzen * <br>
for (char[] kabel : verbinder) { * Das Steckbrett wird ebenfalls definiert und die notwendigen Kabel eingesteckt nach dem heutigen
sb.setzeVertauschung(kabel[0], kabel[1]); * Codebucheintrag.
} */
private void initialisiereHardware() {
// Die Hardware aus dem Koffer holen (initialisieren) this.nachricht = "";
this.hardware = new Hardware();
// Das Steckbrett initialisieren
// Den Ring an der Walze anbringen und die Walze dann in die Hardware einsetzen Steckbrett sb = new Steckbrett();
this.hardware.setWalzen(0, this.codebuch.getWalzenlage()[0], this.codebuch.getRingstellung()[0]); char[][] verbinder = this.codebuch.getSteckverbindung();
this.hardware.setWalzen(1, this.codebuch.getWalzenlage()[1], this.codebuch.getRingstellung()[1]);
this.hardware.setWalzen(2, this.codebuch.getWalzenlage()[2], this.codebuch.getRingstellung()[2]); // Für jedes Kabel eine Verbindung auf dem Steckbrett setzen
for (char[] kabel : verbinder) {
// Der Hardware das gesetzte Steckbrett zuweisen sb.setzeVertauschung(kabel[0], kabel[1]);
this.hardware.setSteckbrett(sb); }
// Ein Reflektor Objekt erstellen und der Hardware bekannt geben // Die Hardware aus dem Koffer holen (initialisieren)
this.hardware.setReflektor(new Reflektor()); 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]);
* Hier wird ein neuer Spruchschlüssel generiert. this.hardware.setWalzen(2, this.codebuch.getWalzenlage()[2], this.codebuch.getRingstellung()[2]);
* <p>
* Mit diesem werden die Walzen auf eine neue Startposition gestellt und dem Kopf, mit dem // Der Hardware das gesetzte Steckbrett zuweisen
* Tagesschlüssel codiert, hinzugefügt. this.hardware.setSteckbrett(sb);
* <br>
* Hierfür wird mittels der Funktion "randomBuchstabe" ein zufälliger Buchstabe generiert, // Ein Reflektor-Objekt erstellen und der Hardware bekanntgeben
* und geschaut ob dieser bereits in der globalen Variable (this.spruchschluessel) vorhanden ist. this.hardware.setReflektor(new Reflektor());
* 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. /**
*/ * Setzt die Enigma auf die Einstellungen des aktuellen Tages, aus dem Codebuch zurueck.
public void generateSpruchschluessel() { */
public void resetHardware() {
String klartext = ""; this.initialisiereHardware();
}
while (klartext.length() < 3) {
String temp = this.randomBuchstabe(); /**
if (!klartext.contains(temp)) { * Leert das Nachrichten-Objekt um eine neue Nachricht aufnehmen zu koennen.
klartext += temp; */
} private void resetNachricht() {
} this.nachricht = "";
}
this.spruchschluessel = klartext; //endregion
this.spruchschluesselCodiert = this.codiere(klartext + klartext, false);
//region Nachrichten handler
// Walzen auf den Spruchschlüssel stellen
this.hardware.setzePosition(0, this.spruchschluessel.charAt(0)); /**
this.hardware.setzePosition(1, this.spruchschluessel.charAt(1)); * Befehl, die Nachricht an den Funker zu uebergeben.
this.hardware.setzePosition(2, this.spruchschluessel.charAt(2)); *
* @throws IOException : Die Antwort konnte nicht gelesen werden.
// Die Kenngruppe codieren und in der Nachricht speichern */
this.codiere(this.kenngruppe, true); public void sendeNachricht() throws IOException {
} String kopf = this.generateKopf();
new Funkraum().sendeFunkspruch(new Morsecode().convertBuchstabeToMorsecode(kopf + this.nachricht),
/** this.kenngruppe);
* Der Spruchschlüssel wird, zur internen Verwendung, auch im Klartext gespeichert. this.nachricht = "";
* Wir brauchen diesen dann zum codieren der eigentlichen Nachricht. this.resetHardware();
* }
* @return String : Der klartext Spruchschlüssel
*/ /**
public String getSpruchschluessel() { * Gibt die letzte empfangene Nachricht zurueck.
return this.spruchschluessel; * <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
* Erstellen des Nachrichten Kopfes. * Tageseinstellungen (nachricht[0]) decodiert.
* Hierfür wird die aktuelle Uhrzeit ausgelesen, die Länge der Nachricht sowie der, mit den */
* Tagescodes codierte, Spruchschlüssel. public String[] empfangeNachricht() {
*/ StringBuilder sb = new StringBuilder();
private String generateKopf() { Morsecode mc = new Morsecode();
Calendar cal = Calendar.getInstance(); String[] nachricht = new String[3];
// Uhrzeit an den Kopf hängen // Alte Nachrichten-Variable erstmal leeren
return String.format("%02d%02d", cal.get(Calendar.HOUR), cal.get(Calendar.MINUTE)) + " " + this.nachricht = "";
// Zeichen Anzahl der Nachricht // Abrufen der letzten Nachricht, für unsere Kenngruppe, aus dem Funkraum
this.nachricht.length() + " " + String[] codierteNachricht = new Funkraum().empfangeFunkspruch(this.kenngruppe);
// Spruchschlüssel anhängen // Prüfen ob Nachrichtenlänge > 1 und die codierte Nachricht mehr als drei Felder (" ") hat
this.spruchschluesselCodiert.substring(0, 3) + " " + this.spruchschluesselCodiert.substring(3, 6) + " "; 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]));
* Einen zufälligen Buchstaben aus dem Alphabet generieren.
* In der Funktion gibt es den String Alphabet, in welchem alle zulässigen Zeichen eingetragen sind. sb.append(nachricht[1], 0, 16);
* Aus diesem String wird nun zufällig ein Zeichen ausgewählt und zurück gegeben.
* for (int i = 17; i <= nachricht[1].length(); ) {
* @return String : ein zufällig generierter Buchstabe if ((i + 5) < nachricht[1].length()) {
*/ sb.append(nachricht[1], i, i + 5).append(" ");
private String randomBuchstabe() { i += 5;
return String.valueOf((char) ('A' + new Random().nextInt(26))); } else {
} sb.append(nachricht[1].substring(i));
break;
/** }
* Befehl die Nachricht an den Funker zu übergeben }
* nachricht[1] = sb.toString();
* @throws IOException : Die Antwort konnte nicht gelesen werden }
* @throws HttpException : Die Nachricht konnte nicht abgesendet werden
*/ return nachricht;
public void sendeNachricht() throws IOException, HttpException { }
String kopf = this.generateKopf(); //endregion
new Funkraum().sendeFunkspruch(new Morsecode().convertBuchstabeToMorsecode(kopf + this.nachricht), this.kenngruppe);
this.nachricht = ""; //region Generatoren
}
/**
/** * Hier wird ein neuer Spruchschluessel generiert.
* Gibt die letzte empfangene Nachricht zurück * <p>
* <br> * Mit diesem werden die Walzen auf eine neue Startposition gestellt und dem Kopf, mit dem
* String[0] Tag wann die Nachricht gesendet wurde * Tagesschluessel codiert, hinzugefuegt.
* String[1] = Die verschlüsselte Nachricht * <br>
* String[2] = Nachricht im Klartext * Hierfuer wird mittels der Funktion "randomBuchstabe" ein zufaelliger Buchstabe generiert,
*/ * und ueberprueft, ob dieser bereits in der globalen Variable (this.spruchschluessel) vorhanden ist.
public String[] empfangeNachricht() { * Wenn nicht, wird der Buchstabe dem Spruchschluessel hinzugefügt.
* <br>
this.nachricht = ""; * Dies wir nun so lange gemacht bis der Spruchschluessel eine Laenge von drei Zeichen hat.
Morsecode mc = new Morsecode(); * Die Walzen werden anhand des Spruchschluessels automatisch gestellt.
String[] nachricht = new String[4]; */
String[] codierteNachricht = new Funkraum().empfangeFunkspruch(this.kenngruppe); public void generateSpruchschluessel() {
String klartext = "";
if (codierteNachricht[1] != null) {
nachricht[0] = codierteNachricht[0]; while (klartext.length() < 3) {
nachricht[1] = mc.convertMorsecodeToBuchstabe(codierteNachricht[1]); String temp = this.randomBuchstabe();
nachricht[2] = this.decodiere(nachricht[1], Integer.parseInt(nachricht[0])); if (!klartext.contains(temp)) {
StringBuilder sb = new StringBuilder(); klartext += temp;
}
sb.append(nachricht[1], 0, 16); }
for (int i = 17; i <= nachricht[1].length(); ) {
if ((i + 5) < nachricht[1].length()) { this.spruchschluessel = klartext;
sb.append(nachricht[1], i, i + 5).append(" "); this.spruchschluesselCodiert = this.codiere(klartext + klartext, false);
i += 5;
} else { // Walzen auf den Spruchschlüssel stellen
sb.append(nachricht[1].substring(i)); this.hardware.setzePosition(0, this.spruchschluessel.charAt(0));
break; this.hardware.setzePosition(1, this.spruchschluessel.charAt(1));
} this.hardware.setzePosition(2, this.spruchschluessel.charAt(2));
}
nachricht[1] = sb.toString(); // Die Kenngruppe codieren und in der Nachricht speichern
} this.codiere(this.kenngruppe, true);
}
return nachricht;
} /**
* Erstellen des Nachrichten-Kopfes.
/** * Hierfuer wird die aktuelle Uhrzeit ausgelesen, die Laenge der Nachricht, sowie der, mit dem
* Liest die Kenngruppe aus welche die Maschine gerade besitzt. Früher war dies eine eindeutige Nummer * Tagescode codierte, Spruchschluessel.
* die einer Einheit zugewiesen war. Wir hinterlegen hier einen Benutzernamen. *
* * @return String: Enthaelt die Uhrzeit, die Anzahl der Buchstaben der Nachricht und den Spruchschluessel.
* @return String : Kenngruppe */
*/ private String generateKopf() {
public String getKenngruppe() { Calendar cal = Calendar.getInstance();
return kenngruppe;
} return String.format("%02d%02d", cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)) + " "
+ this.nachricht.length() + " " + this.spruchschluesselCodiert.substring(0, 3) + " "
/** + this.spruchschluesselCodiert.substring(3, 6) + " ";
* Setzt die Kenngruppe welche die Enigma gerade benutzt. }
*
* @param kenngruppe : String : Kenngruppe welche die Enigma gerade benutzt /**
*/ * Generiert einen zufaelligen Buchstaben aus dem Alphabet.
public void setKenngruppe(String kenngruppe) { * 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.
this.kenngruppe = kenngruppe; *
this.initialisiereHardware(); * @return String : ein zufaellig generierter Buchstabe.
*/
} private String randomBuchstabe() {
return String.valueOf((char) ('A' + new Random().nextInt(26)));
/** }
* Gibt die bisher erstellte Nachricht zurück //endregion
*
* @return String : Erstellte Nachricht //region setze Funktionen
*/
public String getNachricht() { /**
return nachricht; * 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).
* Gibt die aktuellen Buchstaben auf den Walzen zurück */
* public void setzeRing(int walzenPosition, int umsprungPunkt) {
* @return char[] : Walzen Array mit der aktuellen Position this.hardware.setzeRing(walzenPosition, umsprungPunkt);
*/ }
public char[] getWalzen() {
char[] walzen = new char[3]; /**
walzen[0] = this.hardware.getWalzen()[0].getAnzeige(); * Setzt die Walze (walzeNr) in die Position (walzenPosition) der Enigma ein.
walzen[1] = this.hardware.getWalzen()[1].getAnzeige(); * Mit Ringstellung(ringstellung) gibt man die Position des Umsprungpunktes an.
walzen[2] = this.hardware.getWalzen()[2].getAnzeige(); *
* @param walzenPosition : int : Position der Walze in der Enigma (1-2-3).
return walzen; * @param walzeNr : int : Nummer der Walze die eingesetzt wird.
} * @param ringstellung : int : Stellung des Ringes.
*/
/** public void setzeWalzeNr(int walzenPosition, int walzeNr, int ringstellung) {
* Hier wird ein einzelner Buchstabe verschlüsselt. this.hardware.setzeWalzenNr(walzenPosition, walzeNr, ringstellung);
* 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 * Setzt den anzuzeigenden Buchstaben (buchstabe) auf der Walze (walzenPosition) und resetet das
* @param save : boolean : Nachricht speichern oder nicht * Nachrichten Objekt
* @return char : Der codierte Buchstabe *
*/ * @param walze : int : Nummer der Walze
public char codiere(char buchstabe, boolean save) { * @param buchstabe : char : Buchstabe der zugewiesen soll
char codiert = this.hardware.codiere(buchstabe); */
if (save) { public void setzeWalzenPosition(int walze, char buchstabe) {
this.nachricht += codiert; this.resetNachricht();
} this.hardware.setzePosition(walze, buchstabe);
}
return codiert;
}
/**
/** * Setzt das Kabel in beide Ports ein und fuegt es dem Steckbrett-Array hinzu.
* Codiert den Übergebenen String. *
* Man muss hier ebenfalls mitgeben ob der codierte String in Codierer.nachricht gespeichert werden soll oder nicht. * @param port : int : Kabel Nummer, welches am Steckbrett eingesteckt wird.
* In der Regel ist dies der Fall. * @param verbindung : String : Verbindung, welche die vertauschten Buchstaben angibt.
* */
* @param klartext : String : Der zu codierende Text public void setzeSteckbrett(int port, String verbindung) {
* @param save : boolean : Nachricht speichern oder nicht if (verbindung.equals("")) {
* @return String : Der codierte Text zusätzlich als Rückgabe verbindung = " ";
*/ }
public String codiere(String klartext, boolean save) {
this.hardware.getSteckbrett().setzeVertauschung(port, verbindung.charAt(0), verbindung.charAt(1));
StringBuilder sb = new StringBuilder(); }
//endregion
for (char buchstabe : klartext.toCharArray()) {
sb.append(this.codiere(buchstabe, save)); //region fetch Funktionen
}
/**
return sb.toString(); * Gibt die Ringstellungen aus dem Codebuch zurueck.
} *
* @return int[] : Array mit den Ringstellungen der drei eingesetzten Walzen.
/** */
* Diese Funktion erwartet als (codierteNachricht) eine korrekte Enigma Nachricht. public int[] fetchRingstellung() {
* Ihr muss auch der Tag der codierung mitgegeben werden. Dieser weiß dein Funker im Funkraum. return this.codebuch.getRingstellung();
* In der Regel ist dies der Tag des Nachrichten empfangs. }
*
* @param codierteNachricht : String : Enigma codierte Nachricht /**
* @param tag : int : Tag der Nachricht * Gibt die Walzennummer aus dem Codebuch zurueck.
* @return String : decodierte Nachricht *
*/ * @return int[] : Array mit den Nummern der drei eingesetzten Walzen.
private String decodiere(String codierteNachricht, int tag) { */
public int[] fetchWalzenNr() {
// Hardware reseten und Tageseinstellungen aus dem Codebuch laden return this.codebuch.getWalzenlage();
this.initialisiereHardware(); }
this.codebuch.fetchTagesschluessel(tag);
/**
String[] nachricht = codierteNachricht.split(" "); * Gibt die Steckverbindungen aus dem Codebuch zurueck.
StringBuilder sb = new StringBuilder(); *
* @return char[][] : Array mit den gesteckten Verbindungen im Steckbrett.
System.out.println(Arrays.toString(nachricht)); */
public char[][] fetchSteckverbindungen() {
// Uhrzeit return this.codebuch.getSteckverbindung();
sb.append(nachricht[0]).append(" "); }
// Zeichen Anzahl der Nachricht /**
sb.append(nachricht[1]).append(" "); * Gibt die aktuellen Buchstaben auf den Walzen zurueck.
*
// Spruchschlüssel * @return char[] : Walzen Array mit der aktuellen Positionen.
String spruchschluessel = this.decodiereString(nachricht[2]); */
sb.append(spruchschluessel).append(" "); public char[] fetchWalzen() {
sb.append(this.decodiereString(nachricht[3])).append(" "); char[] walzen = new char[3];
walzen[0] = this.hardware.getWalzen()[0].getPosition();
// Walzen neu einstellen mit dem Spruchschlüssel walzen[1] = this.hardware.getWalzen()[1].getPosition();
this.hardware.setzePosition(0, spruchschluessel.charAt(0)); walzen[2] = this.hardware.getWalzen()[2].getPosition();
this.hardware.setzePosition(1, spruchschluessel.charAt(1));
this.hardware.setzePosition(2, spruchschluessel.charAt(2)); return walzen;
}
// Nachricht decodieren
sb.append(this.decodiereString(nachricht[4])); /**
* Ueberprueft welche Buchstaben noch zur Vertauschung verfuegbar sind.
return sb.toString(); *
} * @param port: Zahl zwischen 0-9: entspricht der Kabelnummer.
* @return String: liefert einen String mit den verfuegbaren Buchstaben zurueck.
/** */
* Zerlegt den übergebenen String in einen char Array und decodiert jedes Zeichen. public String fetchVerfuegbareBuchstaben(int port) {
* Der String wird dann decodiert zurück gegeben. return this.hardware.getSteckbrett().fetchVerfuegbareBuchstaben(port);
* }
* @param nachricht : String : Der zu decodierende Text
* @return String : Der decodierte Text /**
*/ * Gibt die Walzennummer einer Walze auf Position (walzePos) zurück
private String decodiereString(String nachricht) { *
* @param walzePos : int : Position der Walze
StringBuilder sb = new StringBuilder(); * @return int : Nummer der eingesetzten Walze
*/
for (char buchstabe : nachricht.toCharArray()) { public int fetchWalzenNr(int walzePos) {
if (buchstabe > 0) { return this.hardware.getWalzen()[walzePos].getWalzenNr();
sb.append(this.hardware.codiere(buchstabe)); }
} //endregion
}
//region codierer
return sb.toString();
} /**
* Hier wird ein einzelner Buchstabe verschluesselt.
/** * Man muss hier ebenfalls mitgeben, ob der codierte String in "nachricht" gespeichert werden soll oder nicht.
* Setzt die Enigma auf die Einstellungen des aktuellen Tages, aus dem Codebuch zurück. * In der Regel ist dies der Fall.
*/ *
public void resetHardware() { * @param buchstabe : char : Der zu codierende Buchstabe.
this.initialisiereHardware(); * @param save : boolean : Nachricht speichern oder nicht.
} * @return char : Der codierte Buchstabe.
*/
/** public char codiere(char buchstabe, boolean save) {
* Setzt den anzuzeigenden Buchstaben (buchstabe) auf der Walze (wlazenPosition) char codiert = this.hardware.codiere(buchstabe);
* TODO: Wenn die Walzen, Notches, Kabel, etc. verändert werden, muss die bisherige Nachricht (this.nachricht) gelöscht werden.
* if (save) {
* @param walzenPosition : int : Nummer der Walze this.nachricht += codiert;
* @param buchstabe : char : Buchstabe der zugewiesen soll }
*/
public void setWalze(int walzenPosition, char buchstabe) { return codiert;
this.hardware.setzePosition(walzenPosition, buchstabe); }
}
/**
/** * Codiert den uebergebenen String.
* Setzt den Ring auf der Walze auf einen neuen Umstprungwert. * Man muss hier ebenfalls mitgeben, ob der codierte String in "nachricht" gespeichert werden soll oder nicht.
* * In der Regel ist dies der Fall.
* @param walzenPosition : int : Walze auf die der Ring gesteckt wird *
* @param umsprungPunkt : int : Buchstabe auf dem der Notch sitzt * @param klartext : String : Der zu codierende Text.
*/ * @param save : boolean : Nachricht speichern oder nicht.
public void setRing(int walzenPosition, int umsprungPunkt) { * @return String : Der codierte Text zusaetzlich als Rueckgabe.
this.hardware.setzeRing(walzenPosition, umsprungPunkt); */
} public String codiere(String klartext, boolean save) {
StringBuilder sb = new StringBuilder();
/**
* Setzt die Walze (walzeNr) in die Position (walzenPosition) der Enigma ein. for (char buchstabe : klartext.toCharArray()) {
* Mit (ringstellung) gibt man die Position des Umsprungpunktes an. sb.append(this.codiere(buchstabe, save));
* }
* @param walzenPosition : int : Position der Walze in der Enigma (1-2-3)
* @param walzeNr : int : Nummer der Walze die eingesetzt wird return sb.toString();
* @param ringstellung : int : Stellung des Ringes }
*/
public void setWalzeNr(int walzenPosition, int walzeNr, int ringstellung) { /**
this.hardware.setzeWalzenNr(walzenPosition, walzeNr, ringstellung); * 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.
/** *
* Setzt das Kabel in beide Ports ein und fügt es dem Steckbrett Array hinzu. * @param codierteNachricht : String : Enigma-codierte Nachricht.
* * @param tag : int : Tag der Nachricht.
* @param feldNr : int : Kabel Nummer welches am Steckbrett eingesteckt wird * @return String : decodierte Nachricht.
* @param verbindung : String : Verbindung welche die vertauschten Buchstaben angibt */
*/ private String decodiere(String codierteNachricht, int tag) {
public void setSteckbrett(int feldNr, String verbindung) {
this.hardware.getSteckbrett().setzeVertauschung(verbindung.charAt(0), verbindung.charAt(1)); // Hardware reseten und Tageseinstellungen aus dem Codebuch laden
} this.codebuch.fetchTagesschluessel(tag);
this.initialisiereHardware();
/**
* Prüft ob der Port auf den das Kabel gesteckt werden soll, noch frei ist. // Nachricht splitten mit whitespace als delimiter
* <p> String[] nachricht = codierteNachricht.split(" ");
* TODO: Prüfen ob im aktuellen Feld bereits zwei Buchstaben stehen, wenn ja, nach erfolg dieser Funktion, StringBuilder sb = new StringBuilder();
* setSteckbrett ausführen mit beiden Buchstaben als String
* // Uhrzeit und Zeichenanzahl der Nachricht
* @param buchstabe : char : Der zuletzt eingegebene Buchstabe sb.append(nachricht[0]).append(" ");
* @return boolean : Wenn der Buchstabe nicht vorhanden ist, wird true zurückgegeben, ansonsten false sb.append(nachricht[1]).append(" ");
*/
public boolean pruefeSteckbrettPort(char buchstabe) { // Spruchschluessel
return true; String spruchschluessel = this.decodiereString(nachricht[2]);
}
sb.append(spruchschluessel).append(" ");
/** sb.append(this.decodiereString(nachricht[3])).append(" ");
* Ließt aus der empfangenen Nachricht den Spruchschlüssel aus und gibt ihn zurück.
* // Walzen neu einstellen mit dem Spruchschluessel
* @param empfangeneNachricht : String : Die empfangene Nachricht als String this.hardware.setzePosition(0, spruchschluessel.charAt(0));
* @return String : Der Spruchschlüssel mit welcher die Nachricht codiert wurde. this.hardware.setzePosition(1, spruchschluessel.charAt(1));
*/ this.hardware.setzePosition(2, spruchschluessel.charAt(2));
public String empfangenerSpruchschluessel(String empfangeneNachricht) {
String[] nachricht = empfangeneNachricht.split(" "); // Nachricht decodieren
sb.append(this.decodiereString(nachricht[4]));
return nachricht[2];
} return sb.toString();
}
public int[] fetchRingstellung() {
return this.codebuch.getRingstellung(); /**
} * Zerlegt den uebergebenen String in einen char-Array und decodiert jedes Zeichen.
* Der String wird dann decodiert zurueckgegeben.
public int[] getchWalzenNr() { *
return this.codebuch.getWalzenlage(); * @param nachricht : String : Der zu decodierende Text.
} * @return String : Der decodierte Text.
*/
public char[][] getSteckverbindungen() { private String decodiereString(String nachricht) {
return this.codebuch.getSteckverbindung(); StringBuilder sb = new StringBuilder();
}
for (char buchstabe : nachricht.toCharArray()) {
if (buchstabe > 0) {
sb.append(this.hardware.codiere(buchstabe));
}
}
return sb.toString();
}
//endregion
//region Sonstige
/**
* 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
} }
package projekt.enigma.model;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import projekt.enigma.App;
/**
* In dieser Klasse werden Fehler behandelt und an den User/Admin/Entwickler ausgegeben.
*/
public class Fehler {
/**
* Konstanten die anzeigen ob es sich um eine Funktion oder um eine Nachricht handelt.
*/
private static final String FUNCTION_PREFIX = "- ";
private static final String MESSAGE_PREFIX = "--> ";
/**
* Zeige Fehler Dialog
*
* @param type : String : Art der Meldung (warning/information/error)
* @param subject : String : Titel des Dialoges
* @param message : String : Nachricht der Meldung
*/
public void showErrorDialog(String type, String subject, String message) {
Alert alert;
new Fehler().debug(this.getClass().getName() + "."
+ new Throwable().getStackTrace()[0].getMethodName(), true);
/* Der Titel darf auch als leerer String uebergeben werden, dann wird ein Default gesetzt */
if (subject.equals("")) {
subject = "Es ist ein Fehler aufgetreten";
}
/* Welcher Fehler Typ wurde uebergeben? */
switch (type) {
case "warning":
alert = new Alert(AlertType.WARNING);
break;
case "info":
alert = new Alert(AlertType.INFORMATION);
break;
case "error":
alert = new Alert(AlertType.ERROR);
break;
default:
alert = new Alert(AlertType.NONE);
}
//Anzeige des Alerts definieren
alert.setTitle(subject);
alert.setHeaderText(null);
alert.setContentText(message);
alert.showAndWait();
}
/**
* Unter zuhilfenahme dieser Funktion koennen Debug Meldungen auf der Konsole ausgegeben werden,
* wenn in der App.java der Getter getDebug einen int > 0 zurueck gibt.
* Ueber diesen Getter kann man steuern ob Meldungen in der Konsole angezeigt werden sollen oder nicht.
*
* @param message : String : Nachricht
* @param isFunction : boolean : Gibt an ob ein Funktionsname uebergeben wird oder eine Debug Meldung
*/
public void debug(String message, boolean isFunction) {
if (App.getDebug() != 0) {
if (isFunction) {
System.out.println(FUNCTION_PREFIX + message);
} else {
System.out.println(MESSAGE_PREFIX + message);
}
}
}
/**
* Unter Zuhilfenahme dieser Funktion koennen Debug Meldungen auf der Konsole ausgegeben werden,
* wenn in der App.java der Getter getDebug einen int > 0 zurueck gibt.
* Ueber diesen Getter kann man steuern ob Meldungen in der Konsole angezeigt werden sollen oder nicht.
*
* @param message : String : Nachricht
* @param isFunction : boolean : Gibt an ob ein Funktionsname uebergeben wird oder eine Debug Meldung.
*/
public void debug(String message, boolean isFunction, int debugLevel) {
if (App.getDebug() != 0 && (App.getDebug() >= debugLevel || App.getDebug() == 3)) {
if (isFunction) {
System.out.println(FUNCTION_PREFIX + message);
} else {
System.out.println(MESSAGE_PREFIX + message);
}
}
}
}
\ No newline at end of file
package projekt.enigma.model; package projekt.enigma.model;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair; import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
...@@ -19,96 +18,102 @@ import java.util.ArrayList; ...@@ -19,96 +18,102 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Hier sitzt der Funker * Hier sitzt der Funker.
* Der Funkraum kann Funksprüche empfangen und senden. * Der Funkraum kann Funksprueche empfangen und senden.
* Hierfür wird eine Verbindung zu einem externen Service aufgebaut. * Hierfuer wird eine Verbindung zu einem externen Service aufgebaut.
* Dieser Servive erwartet die Nachrichten im JSON Format. Dazu wird ein k als Kenngruppe * Dieser Servive erwartet die Nachrichten im JSON Format. Dazu wird ein k als Kenngruppe
* (Benutzername) übergeben und falls eine Nachricht gesendet werden soll, zusätzlich ein m mit der Nachricht. * (Benutzername) uebergeben und falls eine Nachricht gesendet werden soll, zusaetzlich ein m mit der Nachricht.
* Beides wird als String gesendet. * Beides wird als String gesendet.
*/ */
class Funkraum { public class Funkraum {
/**
* Zum Empfangen liefert der Server, anstatt der Kenngruppe (k) den Empfangstag der Nachricht mit damit man /**
* die Grundeinstellungen aus dem Codebuch, für diesen Tag, raussuchen kann. * Zum Empfangen liefert der Server, anstatt der Kenngruppe (k), den Empfangstag (t) der Nachricht mit, damit man
* {'m': 'Hello world', 't': '26'} * die Grundeinstellungen aus dem Codebuch, für diesen Tag, raussuchen kann.
* * {'m': 'Hello world', 't': '26'}
* @param kenngruppe : String : Kenngruppe dieser Engiam *
* @return String[] : String Array wobei Index 0 dem Empfangstag entspricht und index 1 der empfangenen Nachricht * @param kenngruppe : String : Kenngruppe dieser Enigma
*/ * @return funkspruch : String[] : String Array wobei Index 0 dem Empfangstag entspricht und Index 1
String[] empfangeFunkspruch(String kenngruppe) { * der empfangenen Nachricht.
* @throws NullPointerException : Exception : Keine Nachricht vorhanden.
String[] funkspruch = new String[2]; */
public String[] empfangeFunkspruch(String kenngruppe) {
HttpClient httpclient = HttpClients.createDefault(); String[] funkspruch = new String[2];
HttpPost httppost = new HttpPost("https://enigma.itstall.de/");
HttpClient httpclient = HttpClients.createDefault();
try { HttpPost httppost = new HttpPost("https://enigma.itstall.de/");
// Anfrage Parameter und Encoding setzen
List<NameValuePair> params = new ArrayList<>(2); try {
params.add(new BasicNameValuePair("k", kenngruppe)); // Anfrage Parameter und Encoding setzen
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); List<NameValuePair> params = new ArrayList<>(2);
params.add(new BasicNameValuePair("k", kenngruppe));
// POST Request ausführen und Rückgabe verarbeiten httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity(); // POST Request ausfuehren und Rueckgabe verarbeiten
HttpResponse response = httpclient.execute(httppost);
if (entity != null) { HttpEntity entity = response.getEntity();
BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));
JSONObject result = new JSONObject(reader.readLine()); if (entity != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));
if (!result.getString("m").isEmpty()) { JSONObject result = new JSONObject(reader.readLine());
funkspruch[0] = result.getString("t");
funkspruch[1] = result.getString("m"); if (!result.getString("m").isEmpty()) {
} funkspruch[0] = result.getString("t");
} funkspruch[1] = result.getString("m");
} catch (UnsupportedEncodingException e) { }
System.out.println("Encoding wird nicht unterstützt."); }
} catch (IOException e) { } catch (UnsupportedEncodingException e) {
System.out.println("HTTP Post war nicht erfolgreich.\nBitte wenden Sie sich an ihren Vorgesetzten."); new Fehler().showErrorDialog("error", "Encoding wird nicht unterstützt",
e.printStackTrace(); "Kommunikation mit dem Feind wird als Landesverrat bestraft");
} } catch (IOException e) {
new Fehler().showErrorDialog("error", "HTTP Post war nicht erfolgreich",
return funkspruch; "Bitte wenden Sie sich an ihren Vorgesetzten.");
} } catch (NullPointerException e) {
new Fehler().showErrorDialog("info", "Keiner schreibt dir...",
/** "Es liegen keine neuen Nachrichten im Funkraum für Sie vor.");
* Dem Service senden wir unsere Nachricht als POST Parameter (m) und unsere Kenngruppe (k). }
* Dieser nimmt die Daten entgegeb und hierlerlegt sie auf seinem Stapel (Datenbank) von dem die Nachrichten
* irgendwann, auf Anfrage, wieder abgerufen werden können. return funkspruch;
* <p> }
* Darauf antworter der Server dann mit einem JSON Object in dem das Ergebnis der Anfrage zu sehen ist.
* {'result': 200} /**
* <p> * Dem Service senden wir unsere Nachricht als POST Parameter (m) und unsere Kenngruppe (k).
* Die 200 heißt hier das alles erfolgreich durchgeführt werden konnte. Steht hier etwas anderes, ist ein Fehler * Dieser nimmt die Daten entgegen und hierlerlegt sie auf seinem Stapel (Datenbank) von dem die Nachrichten
* aufgetreten und die Anfrage war nicht erfolgreich. * irgendwann, auf Anfrage, wieder abgerufen werden koennen.
* In letzterem Fall sollte eine Meldung an den Benutzer ausgegeben werden und ggF später erneut versucht. * <br>
* * Darauf antwortet der Server mit einem JSON Object in dem das Ergebnis der Anfrage zu sehen ist.
* @param funkspruch : String : Der zu sendede Funkspruch * {'result': 200}
* @param kenngruppe : String : Die Kenngruppe dieser Engima * <br>
* @throws IOException : Exception : Funkspruch konnte nicht gesendet werden * Die 200 heisst hier, dass alles erfolgreich durchgefuehrt werden konnte. Steht hier etwas anderes, ist ein Fehler
*/ * aufgetreten und die Anfrage war nicht erfolgreich.
void sendeFunkspruch(String funkspruch, String kenngruppe) throws HttpException, IOException { * In letzterem Fall sollte eine Meldung an den Benutzer ausgegeben werden und ggf. spaeter erneut versucht werden.
*
HttpClient httpclient = HttpClients.createDefault(); * @param funkspruch : String : Der zu sendende Funkspruch
HttpPost httppost = new HttpPost("https://enigma.itstall.de/"); * @param kenngruppe : String : Die Kenngruppe dieser Engima
* @throws IOException : Exception : Funkspruch konnte nicht gesendet werden
// Anfrage Parameter und Encoding setzen */
List<NameValuePair> params = new ArrayList<>(2); public void sendeFunkspruch(String funkspruch, String kenngruppe) throws IOException {
params.add(new BasicNameValuePair("k", kenngruppe)); HttpClient httpclient = HttpClients.createDefault();
params.add(new BasicNameValuePair("m", funkspruch)); HttpPost httppost = new HttpPost("https://enigma.itstall.de/");
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
// Anfrage Parameter und Encoding setzen
// POST Request ausführen und Rückgabe verarbeiten List<NameValuePair> params = new ArrayList<>(2);
HttpResponse response = httpclient.execute(httppost); params.add(new BasicNameValuePair("k", kenngruppe));
HttpEntity entity = response.getEntity(); params.add(new BasicNameValuePair("m", funkspruch));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
if (entity != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent())); // POST Request ausfuehren und Rueckgabe verarbeiten
JSONObject result = new JSONObject(reader.readLine()); HttpResponse response = httpclient.execute(httppost);
if (result.getInt("result") != 200) { HttpEntity entity = response.getEntity();
throw new HttpException("Der andere Funker mag deine Nachricht nicht. Rüge ihn wenn du ihn wieder siehst...");
} if (entity != null) {
} BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));
JSONObject result = new JSONObject(reader.readLine());
} if (result.getInt("result") != 200) {
new Fehler().showErrorDialog("error", "HTTP Exception",
"Der andere Funker mag deine Nachricht nicht. "
+ "Rüge ihn wenn du ihn wieder siehst...");
}
}
}
} }
package projekt.enigma.model; package projekt.enigma.model;
/** /**
* In dieser Klasse wird die Hardware zusammen gefasst. * In dieser Klasse wird die Hardware zusammengefasst.
* Alle Komponenter der Enigma laufen hier zusammen. * Alle Komponenten der Enigma laufen hier zusammen.
* *
* <p> * <p>
* walzen : Walze[] : Ist ein Array der drei eingebauten Walzen Objekte * walzen : Walze[] : Ist ein Array der drei eingebauten Walzen Objekte
* steckbrett : Steckbrett : Das Steckbrett mit den Verbindungen aus dem Codebuch * steckbrett : Steckbrett : Das Steckbrett mit den Verbindungen aus dem Codebuch
* reflektor : Reflektor : Dies ist das Objekt der Reflektors * reflektor : Reflektor : Dies ist das Objekt der Reflektors
* nachricht : String : Die verschlüsselte Nachricht wird in diesem String zusammen gesetzt und gespeichert * nachricht : String : Die verschluesselte Nachricht wird in diesem String zusammengesetzt und gespeichert
* kenngruppe : String : Früher definierte die Kennzeichnung die Einheit welche diese Enigma benutzte. * kenngruppe : String : Frueher definierte die Kennzeichnung die Einheit welche diese Enigma benutzte.
* Wir missbrauchen die Kenngruppe für einen Benutzernamen * Wir missbrauchen die Kenngruppe für einen Benutzernamen
* </p> * </p>
*/ */
public class Hardware { public class Hardware {
//region Variablen
/** /**
* TODO: Dokumentieren * walzen: Walze-Array: erzeugt ein privates Array mit der die Anzahl der Walzen festgelegt wird.
*/ */
private Walze[] walzen; private Walze[] walzen;
private Steckbrett steckbrett;
private Reflektor reflektor;
/**
* Im Konstruktor legen wir die Anzahl der Walzen fest welche die Hardware aufnehmen kann.
* Die Enigma I welche hier nachgebildet werden soll, konnte drei Walzen aufnehmen.
*/
public Hardware() {
this.walzen = new Walze[3];
}
/**
* Setzt eine Walze ein
*
* @param walze : int : Setzt die Walze mit der angegebenen Nummer ein
* @param walzenNr : int : Die Nummer der einzusetzenden Walze
*/
public void setzeWalzenNr(int walze, int walzenNr, int ringstellung) {
this.walzen[walze] = new Walze(walzenNr, ringstellung);
}
/**
* Setzt den Notch der Walze
*
* @param walze : int : Position der Walze
* @param position : int : Umspringpunkt auf der Walze
*/
public void setzeRing(int walze, int position) {
this.walzen[walze].setRingstellung(position);
}
/** /**
* Setzt den Startwert (position) der Walze (walze) * steckbrett: Steckbrett: erzeugt ein privates Steckbrett-Objekt
*
* @param walze : int : Nummer der Walze
* @param buchstabe : char : Buchstabe der zugewiesen soll
*/ */
public void setzePosition(int walze, char buchstabe) { private Steckbrett steckbrett;
this.walzen[walze].setPosition(buchstabe);
}
/** /**
* Verschlüsselt den übergebenen Buchstaben und fügt ihn der Nachricht hinzu * reflektor: Reflektor: erzeugt ein privates Reflektor-Objekt.
*
* @param buchstabe char : Der zu ver/entschlüsselnde Buchstabe
* @return char : Der ver/entschlüsselte Buchstabe
*/ */
public char codiere(char buchstabe) { private Reflektor reflektor;
this.dreheWalzen(); //endregion
buchstabe = this.steckbrett.codiere(Character.toUpperCase(buchstabe)); //region Konstruktor
buchstabe = this.walzen[2].codiere(buchstabe);
buchstabe = this.walzen[1].codiere(buchstabe); /**
buchstabe = this.walzen[0].codiere(buchstabe); * Im Konstruktor legen wir die Anzahl der Walzen fest, welche die Hardware aufnehmen kann.
buchstabe = this.reflektor.codiere(buchstabe); * Die Enigma I, welche hier nachgebildet werden soll, konnte drei Walzen aufnehmen.
buchstabe = this.walzen[0].codiere2(buchstabe); */
buchstabe = this.walzen[1].codiere2(buchstabe); public Hardware() {
buchstabe = this.walzen[2].codiere2(buchstabe); this.walzen = new Walze[3];
buchstabe = this.steckbrett.codiere(buchstabe); }
//endregion
//region Funktionen & Methoden
/**
* Setzt eine Walze ein.
*
* @param walze : int : Setzt die Walze mit der angegebenen Nummer ein.
* @param walzenNr : int : Die Nummer der einzusetzenden Walze.
* @param ringstellung : int : Setzt den Ring der Walze auf die angegebene Nummer.
*/
public void setzeWalzenNr(int walze, int walzenNr, int ringstellung) {
this.walzen[walze] = new Walze(walzenNr, ringstellung);
}
/**
* Setzt den Notch der Walze.
*
* @param walze : int : Position der Walze.
* @param position : int : Umspringpunkt auf der Walze.
*/
public void setzeRing(int walze, int position) {
this.walzen[walze].setRingstellung(position);
}
/**
* Setzt den Startwert (position) der Walze (walze).
*
* @param walze : int : Nummer der Walze.
* @param buchstabe : char : Buchstabe der zugewiesen werden soll.
*/
public void setzePosition(int walze, char buchstabe) {
this.walzen[walze].setPosition(buchstabe);
}
/**
* Verschluesselt den uebergebenen Buchstaben und fuegt ihn der Nachricht hinzu.
* Debug Ausgabe auf der Konsole wird zusaetzlich ausgegeben.
*
* @param buchstabe char : Der zu ver/entschluesselnde Buchstabe.
* @return char : Der ver/entschluesselte Buchstabe.
*/
public char codiere(char buchstabe) {
new Fehler().debug(this.getClass().getName() + "." +
new Throwable().getStackTrace()[0].getMethodName(), true);
buchstabe = Character.toUpperCase(buchstabe);
String debug = String.format("Positionen: W1:%s W2:%s W3:%s",
this.walzen[0].getPosition(),
this.walzen[1].getPosition(),
this.walzen[2].getPosition());
debug += "\nI\tS\t3\t2\t1\tR\t1\t2\t3\tS\n" + buchstabe;
this.dreheWalzen(1);
//Codiere Vorgang wird fuer jede Walze bis zum Reflektor mit der codiere Funktion durchgefuehrt.
//Auf dem Rueckweg wird mit der codiere2 Funktion codiert.
buchstabe = this.steckbrett.codiere(Character.toUpperCase(buchstabe));
debug += "\t" + buchstabe;
buchstabe = this.walzen[2].codiere(buchstabe);
debug += "\t" + buchstabe;
buchstabe = this.walzen[1].codiere(buchstabe);
debug += "\t" + buchstabe;
buchstabe = this.walzen[0].codiere(buchstabe);
debug += "\t" + buchstabe;
buchstabe = this.reflektor.codiere(buchstabe);
debug += "\t" + buchstabe;
buchstabe = this.walzen[0].codiere2(buchstabe);
debug += "\t" + buchstabe;
buchstabe = this.walzen[1].codiere2(buchstabe);
debug += "\t" + buchstabe;
buchstabe = this.walzen[2].codiere2(buchstabe);
debug += "\t" + buchstabe;
buchstabe = this.steckbrett.codiere(buchstabe);
debug += "\t" + buchstabe;
new Fehler().debug(debug, false);
return buchstabe; return buchstabe;
} }
/** /**
* Nach jeder codierung eines Buchstabens müssen die Walzen gedreht werden. * Nach jeder Codierung eines Buchstabens muessen die Walzen gedreht werden.
* Hier überprüfen wir welche der Walzen gedreht werden müssen und stoßen die Vorgang an. * Hier ueberpruefen wir, welche der Walzen gedreht werden muessen und stossen den Vorgang an.
*/ *
private void dreheWalzen() { * @param richtung : int : +1 fuer eine Vorwaertsdrehung und -1 fuer eine Rueckwaertsdrehung.
if (this.walzen[2].dreheWalze()) { */
if (this.walzen[1].dreheWalze()) { public void dreheWalzen(int richtung) {
this.walzen[0].dreheWalze(); if (richtung > 0) {
} for (int i = 0; i < richtung; i++) {
} if (this.walzen[2].dreheWalze(1)) {
} if (this.walzen[1].dreheWalze(1)) {
this.walzen[0].dreheWalze(1);
/** }
* Gibt die verbauten Walzen Objekte zurück }
* }
* @return Walze[] : Array mit den Walzen Objekten } else {
*/ for (int i = 0; i > richtung; richtung++) {
public Walze[] getWalzen() { if (this.walzen[2].dreheWalze(-1)) {
return this.walzen; if (this.walzen[1].dreheWalze(-1)) {
} this.walzen[0].dreheWalze(-1);
}
/** }
* Setzt eine Walze ein und speichert das Objekt im Walzen Array }
* }
* @param position : int : Position der Walze }
* @param walze : int : Die Nummer der Walze //endregion
* @param ringstellung : int : Umsprung Punkt der Walze
*/ //region Setter
public void setWalzen(int position, int walze, int ringstellung) {
this.walzen[position] = new Walze(walze, ringstellung); /**
} * Setzt eine Walze ein und speichert das Objekt im Walzen Array.
*
/** * @param position : int : Position der Walze.
* Gibt das Objekt des Steckbretts zurück * @param walze : int : Die Nummer der Walze.
* * @param ringstellung : int : Umsprungpunkt der Walze.
* @return Steckbrett : Das eingesetzte Steckbrett mit seinen Kabeln wenn eingesteckt */
*/ public void setWalzen(int position, int walze, int ringstellung) {
public Steckbrett getSteckbrett() { this.walzen[position] = new Walze(walze, ringstellung);
return steckbrett; }
}
/**
/** * Gibt das Objekt des Steckbretts zurueck.
* Setzt das übergebene Steckbrett Objekt in die Hardware ein *
* * @return steckbrett : Steckbrett-Objekt: Das eingesetzte Steckbrett mit seinen Kabeln, wenn eingesteckt.
* @param steckbrett : Steckbrett : Objekt des Steckbretts mit allen verbundenen Kabeln */
*/ public Steckbrett getSteckbrett() {
public void setSteckbrett(Steckbrett steckbrett) { return steckbrett;
this.steckbrett = steckbrett; }
}
/**
/** * Setzt das uebergebene Steckbrett Objekt in die Hardware ein.
* Liest den Reflektor aus und gibt ihn zurück *
* * @param steckbrett : Steckbrett : Objekt des Steckbretts mit allen verbundenen Kabeln.
* @return Reflektor : Objekt des Reflektors */
*/ public void setSteckbrett(Steckbrett steckbrett) {
public Reflektor getReflektor() { this.steckbrett = steckbrett;
return reflektor; }
} //endregion
/** //region Getter
* Setzt den Reflektor ein.
* In der Enigma I welche hier nachgebaut wird, gab es nur einen Reflektor. /**
* Spätere Versionen haten zwei oder mehr, deshalb haben wir hier auch schon ein Objekt dafür erstellt, * Setzt den Reflektor ein.
* welches ausgetauscht werden kann. * In der Enigma I, welche hier nachgebaut wird, gab es nur einen Reflektor.
* * Spaetere Versionen hatten zwei oder mehr, deshalb haben wir hier auch schon ein Objekt dafuer erstellt,
* @param reflektor : Reflektor : Das Obejtk des Reflektors * welches ausgetauscht werden kann.
*/ *
public void setReflektor(Reflektor reflektor) { * @param reflektor : Reflektor : Das Objekt des Reflektors.
this.reflektor = reflektor; */
} public void setReflektor(Reflektor reflektor) {
this.reflektor = reflektor;
/** }
* Diese Funktion setzt die Walzen auf ihren Anfangswert zurück.
* Hierfür ist der Buchstabe "A" festgelegt. /**
* Dies wird benötigt um zB einen neuen Spruchschlüssel einzustellen oder eine neue Nachricht zu verfassen. * Gibt die verbauten Walzen Objekte zurück.
*/ *
public void resetWalzen() { * @return walzen : Walze[] : Array mit den Walzen Objekten.
this.getWalzen()[0].setPosition('A'); */
this.getWalzen()[1].setPosition('A'); public Walze[] getWalzen() {
this.getWalzen()[2].setPosition('A'); return this.walzen;
} }
//endregion
} }
package projekt.enigma.model; package projekt.enigma.model;
import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.TreeMap;
/** /**
* Diese Klasse definiert die Zugehörigkeit zwischen den Buchstaben A-Z und dem zugehörigen Morsecode. * Diese Klasse definiert die Zugehoerigkeit zwischen den Buchstaben A-Z und dem Morsecode.
* Die Funktionen sollen Texte von und zu Morsecode konvertieren. * Die Funktionen sollen Texte von und zu Morsecode konvertieren.
*/ */
public class Morsecode { public class Morsecode {
// Anlegen der codeMap als TreeMap
private TreeMap<String, String> codeMap = new TreeMap<>();
/** /**
* Im Konstruktor werden alle verfügbaren Buchstaben (A-Z) und deren zugehörigen * Anlegen der codeMap als TreeMap.
* Morsecodes, der codeMap hinzugefügt. */
*/ private TreeMap<String, String> codeMap;
public Morsecode() {
this.codeMap.put("A", ".-"); /**
this.codeMap.put("B", "-..."); * Im Konstruktor werden alle verfuegbaren Buchstaben (A-Z) und deren zugehoerigen
this.codeMap.put("C", "-.-."); * Morsecodes, der codeMap hinzugefuegt.
this.codeMap.put("D", "-.."); */
this.codeMap.put("E", "."); public Morsecode() {
this.codeMap.put("F", "..-."); codeMap = new TreeMap<>();
this.codeMap.put("G", "--."); this.codeMap.put("A", ".-");
this.codeMap.put("H", "...."); this.codeMap.put("B", "-...");
this.codeMap.put("I", ".."); this.codeMap.put("C", "-.-.");
this.codeMap.put("J", ".---"); this.codeMap.put("D", "-..");
this.codeMap.put("K", "-.-"); this.codeMap.put("E", ".");
this.codeMap.put("L", ".-.."); this.codeMap.put("F", "..-.");
this.codeMap.put("M", "--"); this.codeMap.put("G", "--.");
this.codeMap.put("N", "-."); this.codeMap.put("H", "....");
this.codeMap.put("O", "---"); this.codeMap.put("I", "..");
this.codeMap.put("P", ".--."); this.codeMap.put("J", ".---");
this.codeMap.put("Q", "--.-"); this.codeMap.put("K", "-.-");
this.codeMap.put("R", ".-."); this.codeMap.put("L", ".-..");
this.codeMap.put("S", "..."); this.codeMap.put("M", "--");
this.codeMap.put("T", "-"); this.codeMap.put("N", "-.");
this.codeMap.put("U", "..-"); this.codeMap.put("O", "---");
this.codeMap.put("V", "...-"); this.codeMap.put("P", ".--.");
this.codeMap.put("W", ".--"); this.codeMap.put("Q", "--.-");
this.codeMap.put("X", "-..-"); this.codeMap.put("R", ".-.");
this.codeMap.put("Y", "-.--"); this.codeMap.put("S", "...");
this.codeMap.put("Z", "--.."); this.codeMap.put("T", "-");
this.codeMap.put(" ", "-...-"); this.codeMap.put("U", "..-");
this.codeMap.put("1", ".----"); this.codeMap.put("V", "...-");
this.codeMap.put("2", ".----"); this.codeMap.put("W", ".--");
this.codeMap.put("3", "...--"); this.codeMap.put("X", "-..-");
this.codeMap.put("4", "....-"); this.codeMap.put("Y", "-.--");
this.codeMap.put("5", "....."); this.codeMap.put("Z", "--..");
this.codeMap.put("6", "-...."); this.codeMap.put(" ", "-...-");
this.codeMap.put("7", "--..."); this.codeMap.put("1", ".----");
this.codeMap.put("8", "---.."); this.codeMap.put("2", "..---");
this.codeMap.put("9", "----."); this.codeMap.put("3", "...--");
this.codeMap.put("0", "-----"); this.codeMap.put("4", "....-");
} this.codeMap.put("5", ".....");
this.codeMap.put("6", "-....");
/** this.codeMap.put("7", "--...");
* Diese Funktion überprüft ob das übergebene Buchstabe in der codeMap enthalten ist. this.codeMap.put("8", "---..");
* Wenn es enthalten ist, wird der zugehörige Morsecode zurück gegeben, ansonsten null this.codeMap.put("9", "----.");
* this.codeMap.put("0", "-----");
* @param buchstabe : char : Zu übersetzender Buchstabe }
* @return : String : Das zugehöriger Morsecode aus der codeMap
*/ /**
private String getMorsecode(char buchstabe) { * Diese Funktion ueberprueft ob der uebergebene Buchstabe in der codeMap enthalten ist.
// Testen ob das Char in der codeMap enthalten ist. Wenn ja, raussuchen und zurück geben * Wenn er enthalten ist, wird der zugehoerige Morsecode zurueck gegeben, ansonsten null.
return this.codeMap.getOrDefault(String.valueOf(buchstabe).toUpperCase(), null); *
} * @param buchstabe : char : Zu uebersetzender Buchstabe.
* @return String : Der zugehoerige Morsecode aus der codeMap.
/** */
* Der übergebene String wird in seine einzelnen Zeichen (char) zerlegt und an die Funktion getMorsecode private String getMorsecode(char buchstabe) {
* übergeben und der zugehörige Morsecode raus gesucht. return this.codeMap.getOrDefault(String.valueOf(buchstabe).toUpperCase(), null);
* Mittels eines StringBuilders werden die Ergebnisse zu einem Rückgabe String zusammen gesetzt. }
* Wenn kein zugehöriger Code in der codeMap gefunden wurde, wird das Zeichen ignoriert da es bei der
* Enigma nicht vorhanden war. /**
* * Der uebergebene String wird in seine einzelnen Zeichen (char) zerlegt und an die Funktion getMorsecode
* @param input : String : Zu konventierender Text * uebergeben und der zugehoerige Morsecode rausgesucht.
* @return String : Die in Morsecode konvertierte Text * Mittels eines StringBuilders werden die Ergebnisse zu einem Rueckgabe-String zusammengesetzt.
*/ * Wenn kein zugehoeriger Code in der codeMap gefunden wurde, wird das Zeichen ignoriert da es bei der
public String convertBuchstabeToMorsecode(String input) { * Enigma nicht vorhanden war.
StringBuilder sb = new StringBuilder(); *
String morsecode; * @param input : String : Zu konvertierender Text.
* @return String : Der in Morsecode konvertierte Text.
// Durch alle char im übergebenen String loopen */
for(int i = 0; i < input.length(); i++) { public String convertBuchstabeToMorsecode(String input) {
StringBuilder sb = new StringBuilder();
// Wenn der char in der codeMap enthalten ist, an den Rückgabe String anheften, ansonsten nichts ignorieren. String morsecode;
morsecode = this.getMorsecode(input.charAt(i));
if(morsecode != null) { // Durch alle char im uebergebenen String loopen
sb.append(morsecode).append(' '); for (int i = 0; i < input.length(); i++) {
} morsecode = this.getMorsecode(input.charAt(i));
} if (morsecode != null) {
sb.append(morsecode).append(' ');
// Gibt den konvertierten String zurück }
return sb.toString(); }
}
return sb.toString();
/** }
* Diese Funktion überprüft ob der übergebene Morsecode in der codeMap enthalten ist.
* Wenn er enthalten ist, wird der zugehörige Buchstabe zurück gegeben, ansonsten null /**
* * Diese Funktion ueberprueft ob der uebergebene Morsecode in der codeMap enthalten ist.
* @param morsecode : String : Der zu übersetzende Morsecode * Wenn er enthalten ist, wird der zugehoerige Buchstabe zurueckgegeben, ansonsten null.
* @return : String : Das zugehöriger Buchstaben aus der this.codeMap *
*/ * @param morsecode : String : Der zu uebersetzende Morsecode.
private String getBuchstabe(String morsecode) { * @return : String : Der zugehoerige Buchstabe aus der codeMap.
// Initialisieren des Rückgabe Strings */
String result = null; private String getBuchstabe(String morsecode) {
String result = null;
// Loopt duch die Codemap und erstellt daraus ein Set
for(Entry<String, String> entry : this.codeMap.entrySet()) { // Loopt duch die codeMap und erstellt daraus ein Set
// Wenn Value dem Morsecode entspricht, haben wir unseren Buchstaben gefunden und setzen ihn als Result for (Entry<String, String> entry : this.codeMap.entrySet()) {
if(entry.getValue().equals(morsecode)) { if (entry.getValue().equals(morsecode)) {
result = entry.getKey(); result = entry.getKey();
} }
} }
return result; return result;
} }
/** /**
* Der übergebene String wird in einen String Array zerlegt. Als Trennzeichen wird das Leerzeichen genutzt. * Der uebergebene String wird in ein String-Array zerlegt. Als Trennzeichen wird das Leerzeichen genutzt.
* Anschließend wird der Array durchlaufen und die Elemente an die Funktion getBuchstabe übergeben um den * Anschließend wird das Array durchlaufen und die Elemente an die Funktion getBuchstabe uebergeben um den
* zugehörigen Buchstaben zu erhalten. * zugehoerigen Buchstaben zu erhalten.
* Mittels eines StringBuilders werden die Ergebnisse zu einem Rückgabe String zusammen gesetzt. * Mittels eines StringBuilders werden die Ergebnisse zu einem Rueckgabe String zusammengesetzt.
* Wenn kein zugehöriger Buchstabe in der codeMap gefunden wurde, wird das Zeichen ignoriert da es bei der * Wenn kein zugehoeriger Buchstabe in der codeMap gefunden wurde, wird das Zeichen ignoriert, da es bei der
* Enigma nicht vorhanden war. * Enigma nicht vorhanden war.
* *
* @param input : String : Zu konventierender Morsecode * @param input : String : Zu konvertierender Morsecode.
* @return String : Der in Text konvertierte Morsecode * @return String : Der in Text konvertierte Morsecode.
*/ */
public String convertMorsecodeToBuchstabe(String input) { public String convertMorsecodeToBuchstabe(String input) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String buchstabe; String buchstabe;
String[] morsecodes = input.split(" "); String[] morsecodes = input.split(" ");
// Durch alle char im übergebenen String loopen // Durch alle char im uebergebenen String loopen
for(String morsecode : morsecodes) { for (String morsecode : morsecodes) {
buchstabe = this.getBuchstabe(morsecode);
// Wenn der char in der codeMap enthalten ist, an den Rückgabe String anheften, ansonsten nichts ignorieren. if (buchstabe != null) {
buchstabe = this.getBuchstabe(morsecode); sb.append(buchstabe);
if(buchstabe != null) { }
sb.append(buchstabe); }
}
} return sb.toString();
}
// Gibt den konvertierten String zurück
return sb.toString();
}
} }
...@@ -3,46 +3,28 @@ package projekt.enigma.model; ...@@ -3,46 +3,28 @@ package projekt.enigma.model;
/** /**
* Klasse Reflektor * Klasse Reflektor
* <br> * <br>
* Der Reflektor nimmt einen Buchstaben der Klasse Walze entgegen und und kodiert diesen. * Der Reflektor nimmt einen Buchstaben der Klasse Walze entgegen und codiert diesen.
* Der kodierte Buchstabe wird an die Klasse Walze wieder zurückgegeben. * Der codierte Buchstabe wird an die Klasse Walze wieder zurueckgegeben.
* <br> * <br>
* Prinzipiell verhält sich die Klasse Reflektor wie die Klasse Walze, außer das sie sich * Prinzipiell verhaelt sich die Klasse Reflektor wie die Klasse Walze, ausser das sie sich
* nach Betätigung einer Taste nicht dreht (quasi starr montiert ist) und sie gibt keine Signale * nach Betaetigung einer Taste nicht dreht (quasi starr montiert ist) und sie gibt keine Signale
* an andere Walzen zum drehen. * an andere Walzen zum Drehen.
*/ */
public class Reflektor { public class Reflektor {
/**
* WALZE_ALPHABET : konstanter Char-Array mit den Werten des Alphabeths (26 Werte)
*/
private final Character[] WALZE_ALPHABET = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
/**
* WALZE_REFLEKTOR : konstanter Char-Array mit den Werten des Reflektors (26 Werte)
*/
private final Character[] WALZE_REFLEKTOR = {'E', 'J', 'M', 'Z', 'A', 'L', 'Y', 'X', 'V', 'B', 'W', 'F', 'C', 'R', 'Q', 'U', 'O', 'N', 'T', 'S', 'P', 'I', 'K', 'H', 'G', 'D'};
/** /**
* Funktion codiere * Funktion codiere
* <br> * <br>
* Durchsucht das konstante Char-Array WALZE_ALPHABET nach der Position eines bestimmten * Durchsucht den String alphabet nach der Position des mitgegebenen Buchstabens und
* Buchstabens und gibt den Character an der entsprechenden Position im konstanten * gibt den Character an der entsprechenden Position im String reflektor zurueck.
* Char-Array WALZE_REFLEKTOR zurück.
* *
* @return WALZE_REFLEKTOR[iPositionReflektor]: Character: Der kodierte Buchstabe aus dem Reflektor * @param buchstabe : Character : der zu codierende Buchstabe.
* @return char : Der codierte Buchstabe aus dem Reflektor.
*/ */
public char codiere(Character buchstabe) { public char codiere(Character buchstabe) {
int iPositionReflektor = 0; String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String reflektor = "EJMZALYXVBWFCRQUONTSPIKHGD";
//Ermittelt die Position des Buchstaben "buchstabe" auf der Alphabetswalze
for (int index = 0; index < WALZE_ALPHABET.length; index++) {
if (buchstabe.equals(WALZE_ALPHABET[index])) {
iPositionReflektor = index;
break;
}
}
return WALZE_REFLEKTOR[iPositionReflektor]; return reflektor.charAt(alphabet.indexOf(buchstabe));
} }
} }
package projekt.enigma.model; package projekt.enigma.model;
/** /**
* <p>
* Klasse Steckbrett * Klasse Steckbrett
* <br> * <br>
* Das Steckbrett diente dazu Buchstaben paarweise zu vertauschen noch bevor diese durch die Walzen codiert werden. * Das Steckbrett diente dazu, Buchstaben paarweise zu vertauschen noch bevor diese durch die Walzen codiert werden.
* Die Klasse Steckbrett nimmt bis zu 10 paarweise zu vertauschende Buchstabenpaare entgegen, prueft diese auf * Die Klasse Steckbrett nimmt bis zu 10 paarweise zu vertauschende Buchstabenpaare entgegen, prueft diese auf
* Zulaessigkeit und tauscht diese dann paarweise aus. * Zulaessigkeit und tauscht diese dann paarweise aus.
*/ */
public class Steckbrett { public class Steckbrett {
/** /**
* zaehler: Int, der als Laufvariable genutzt wird * orginalBuchstaben: String : der jeweils den ersten zu vertauschenden Buchstaben enthaelt.
*/ */
private int zaehler; private String originalBuchstaben;
/** /**
* orginalBuchstaben: Character-Array, der jeweils den ersten zu vertauschenden Buchstaben enthält * getauschteBuchstaben: String : der jeweils den zweiten zu vertauschenden Buchstaben enthaelt.
*/ */
private Character[] orginalBuchstaben; private String getauschteBuchstaben;
/**
* getauschteBuchstaben: Character-Array, der jeweils den zweiten zu vertauschenden Buchstaben enthält
*/
private Character[] getauschteBuchstaben;
/** /**
* Konstruktor Steckbrett * Konstruktor Steckbrett
* <br> * <br>
* Erzeugt zwei Charakter-Arrays (orginalBuchstaben und getauschteBuchstaben) der Länge 10. * Erzeugt zwei Strings und initialisiert diese.
*/ */
public Steckbrett() { public Steckbrett() {
originalBuchstaben = "";
orginalBuchstaben = new Character[10]; getauschteBuchstaben = "";
getauschteBuchstaben = new Character[10];
} }
/** /**
* TODO: Fehlerfall kommentieren, bzw. Exceptions werfen ?????
* TODO: Überprüfe Vertauschungen für jeden Buchstaben aufrufen
* Funktion setzeVertauschung * Funktion setzeVertauschung
* <br> * <br>
* Der Funktion setzeVertauschung werden 2 Buchstaben (buchstabe1 und buchstabe2) übergeben. * Der Funktion setzeVertauschung werden 2 Buchstaben (buchstabe1 und buchstabe2) uebergeben.
* buchstabe1 wird in das Character-Array orginalBuchstaben geschrieben. * Zuerst wird ueberprueft ob einer der beiden Buchstaben bereits enthalten ist, was unzulaessig waere.
* buchstabe2 wird in das Character-Array getauschteBuchstaben geschrieben. * <br>
* Anschließend wird die Funktion ueberpruefeVertauschungen aufgerufen. * Anschliessend wird:
* <p>
* buchstabe1 dem String orginalBuchstaben angehaengt.
* buchstabe2 dem String getauschteBuchstaben angehaengt.
* </p>
* *
* @param buchstabe1 : char: Gibt den ersten Buchstaben an, der getauscht werden soll. * @param buchstabe1 : char : Gibt den ersten Buchstaben an, der getauscht werden soll.
* @param buchstabe2 : char: gibt den zweiten Buchstaben an, mit dem der erste getauscht werden soll. * @param buchstabe2 : char : gibt den zweiten Buchstaben an, mit dem der erste getauscht werden soll.
* @return ueberpruefeVertauschungen(): Ueberprueft ob die Vertauschungen zulaessig sind. * @return boolean : Wenn die Vertauschung zulaessig ist, true, ansonsten false.
*/ */
public boolean setzeVertauschung(char buchstabe1, char buchstabe2) { public boolean setzeVertauschung(char buchstabe1, char buchstabe2) {
if (zaehler < orginalBuchstaben.length) { if ((!ueberpruefeVertauschungen(buchstabe1)) && (!ueberpruefeVertauschungen(buchstabe2))
orginalBuchstaben[zaehler] = buchstabe1; && (originalBuchstaben.length() <= 20)) {
getauschteBuchstaben[zaehler++] = buchstabe2; originalBuchstaben += buchstabe1;
getauschteBuchstaben += buchstabe2;
return true;
} else { } else {
System.err.println("Zu viele Vertauschungen angegeben!"); return false;
} }
}
/**
* Funktion setzeVertauschung mit Angabe eines Ports von 1 - 10
* <br>
* Der Funktion setzeVertauschung werden 2 Buchstaben (buchstabe1 und buchstabe2) sowie der Port uebergeben.
* Zuerst wird ueberprueft ob einer der beiden Buchstaben bereits enthalten ist, was unzulaessig waere.
* <br>
* Anschliessend wird:
* <p>
* buchstabe1 in den String orginalBuchstaben auf die Position (steckbrettPort) geschrieben.
* buchstabe2 in den String getauschteBuchstaben auf die Position (steckbrettPort) geschrieben.
* </p>
*
* @param buchstabe1 : char: Gibt den ersten Buchstaben an, der getauscht werden soll.
* @param buchstabe2 : char: gibt den zweiten Buchstaben an, mit dem der erste getauscht werden soll.
* @return boolean : Wenn die Vertauschung zulaessig ist, true, ansonsten false.
*/
public boolean setzeVertauschung(int steckbrettPort, char buchstabe1, char buchstabe2) {
char[] original;
char[] getauscht;
new Fehler().debug("setzeVertauschung(int " + steckbrettPort + ", char |" + buchstabe1 + "|, char |" + buchstabe2 + "|)", false);
if ((!ueberpruefeVertauschungen(buchstabe1) && !ueberpruefeVertauschungen(buchstabe2)) ||
(buchstabe1 == ' ' && buchstabe2 == ' ')) {
return ueberpruefeVertauschungen(); new Fehler().debug("-> Original:\t" + originalBuchstaben, false);
new Fehler().debug("-> Getauscht:\t" + getauschteBuchstaben, false);
original = originalBuchstaben.toCharArray();
getauscht = getauschteBuchstaben.toCharArray();
original[steckbrettPort] = buchstabe1;
getauscht[steckbrettPort] = buchstabe2;
originalBuchstaben = String.valueOf(original);
getauschteBuchstaben = String.valueOf(getauscht);
new Fehler().debug("<- Original:\t" + originalBuchstaben, false);
new Fehler().debug("<- Getauscht:\t" + getauschteBuchstaben, false);
new Fehler().debug("true\tOS: |" + originalBuchstaben + "| GS: |" + getauschteBuchstaben + "|", false);
return true;
} else {
new Fehler().debug("false\tOS: |" + originalBuchstaben + "| GS: |" + getauschteBuchstaben + "|", false);
return false;
}
} }
/** /**
* TODO: Fehlerfall kommentieren, bzw. Exceptions werfen ?????
* TODO: Buchstabe zum überpüfen übergeben
* Funktion ueberpruefeVertauschungen * Funktion ueberpruefeVertauschungen
* <br> * <br>
* Die Funktion ueberpruefeVertauschungen prueft ob die Buchstabenvertauschung zulaessig ist. * Die Funktion ueberpruefeVertauschungen prueft, ob der uebergebene Buchstabe bereits in den beiden Strings
* orginalBuchstaben und getauschteBuchstaben vorhanden ist.
* Eine Buchstabenvertauschung ist zulaessig, wenn keine Dopplungen der zu vertauschenden Buchstaben auftritt * Eine Buchstabenvertauschung ist zulaessig, wenn keine Dopplungen der zu vertauschenden Buchstaben auftritt
* (ein Buchstabe nicht mehrmals vertauscht wird). * (ein Buchstabe nicht mehrmals vertauscht wird).
* *
* @return boolean : result : Flag, der die Zulassigkeit der Vertauschungen zurueckgibt. * @param buchstabe : Character: zu pruefender Buchstabe.
* @return result : boolean : Wenn false, dann darf der Buchstabe genutzt werden. Wenn er schon vorhanden ist,
* wird true zurueckgegeben.
*/ */
public boolean ueberpruefeVertauschungen() { public boolean ueberpruefeVertauschungen(Character buchstabe) {
boolean result = true; boolean result = false;
/*Es wird geprüft: if (originalBuchstaben.contains(String.valueOf(buchstabe)) ||
1. Ob im Array originalBuchstaben Dopplungen enthalten sind. getauschteBuchstaben.contains(String.valueOf(buchstabe))) {
2. Ob im Array originalBuchstaben Buchstaben im Array getauschteBuchstaben enthalten sind. result = true;
3. Ob im Array getauschteBuchstaben Dopplungen enthalten sind.
Tritt einer der Fälle ein, erfolgt eine Konsolenausgabe und der Flag wird auf false gesetzt.
*/
for (int n = 0; n < orginalBuchstaben.length; n++) {
if (orginalBuchstaben.equals(orginalBuchstaben[n]) ||
getauschteBuchstaben.equals(orginalBuchstaben[n]) ||
getauschteBuchstaben.equals(getauschteBuchstaben[n])) {
System.err.println("Vertauschungen enthalten unzulässige Dopplungen");
result = false;
}
} }
return result; return result;
...@@ -102,15 +135,35 @@ public class Steckbrett { ...@@ -102,15 +135,35 @@ public class Steckbrett {
* @return buchstabe : Character : Codierter Buchstabe. * @return buchstabe : Character : Codierter Buchstabe.
*/ */
public char codiere(Character buchstabe) { public char codiere(Character buchstabe) {
for (int index = 0; index < getauschteBuchstaben.length; index++) { if (originalBuchstaben.contains(String.valueOf(buchstabe))) {
if (buchstabe.equals(getauschteBuchstaben[index])) { return getauschteBuchstaben.charAt(originalBuchstaben.indexOf(buchstabe));
buchstabe = orginalBuchstaben[index]; } else if (getauschteBuchstaben.contains(String.valueOf(buchstabe))) {
} else if (buchstabe.equals(orginalBuchstaben[index])) { return originalBuchstaben.charAt(getauschteBuchstaben.indexOf(buchstabe));
buchstabe = getauschteBuchstaben[index]; } else {
} return buchstabe;
} }
return buchstabe;
} }
} /**
* Tauscht die Buchstaben im Alphabet aus und gibt ein modifiziertes Alphabet zurueck.
*
* @param port : int : Platz der getauschten Buchstaben.
* @return alphabet : String : Alphabet mit getauschtem Buchstabenpaar.
*/
public String fetchVerfuegbareBuchstaben(int port) {
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (char c : this.originalBuchstaben.toCharArray()) {
alphabet = alphabet.replace(String.valueOf(c), "");
}
for (char c : this.getauschteBuchstaben.toCharArray()) {
alphabet = alphabet.replace(String.valueOf(c), "");
}
alphabet += originalBuchstaben.charAt(port);
alphabet += getauschteBuchstaben.charAt(port);
return alphabet;
}
}
\ No newline at end of file
...@@ -5,264 +5,184 @@ package projekt.enigma.model; ...@@ -5,264 +5,184 @@ package projekt.enigma.model;
* <br> * <br>
* Erzeugt ein Objekt des Typs Walze mit den Eigenschaften: * Erzeugt ein Objekt des Typs Walze mit den Eigenschaften:
* <br> * <br>
* 1. Walzennummer (Die Walze enthält die 26 Buchstaben des Alphabeths und codiert diese. * 1. Walzennummer (Die Walze enthaelt die 26 Buchstaben des Alphabets und codiert diese.
* 5 verschiedene Walzen stehen zur Auswahl, die jeweils verschieden die Buchstaben des Alphabeths * Fuenf verschiedene Walzen stehen zur Auswahl, die jeweils verschieden die Buchstaben des Alphabets
* paarweise vertauschen) * vertauschen).
* <br> * <br>
* 2. Ringstellung (Umspringpunkt der Walze wird festgelegt. Der Umspringpunkt bestimmt * 2. Ringstellung (Umspringpunkt der Walze wird festgelegt. Der Umspringpunkt bestimmt
* den Drehzeitpunkt der linken Nachbarwalze) * den Drehzeitpunkt der linken Nachbarwalze).
*/ */
public class Walze { public class Walze {
/** //region Variablen
* walzeAlpha : Character[] : Array, dass die Buchstaben des Alphabets enthaelt
*/
private Character[] alphabet;
/** /**
* ringstellung : char : zeigt die Einstellung fuer den Umspringpunkt * Die Anzahl der getaetigten Walzendrehungen.
*/ */
private char ringstellung; private int turns;
/** /**
* walzennr : int : Bestimmt, welche Walze genutzt wird * Das String-Array aller bekannter aktueller Walzen.
*/ */
private int walzennr; private String[] walzen;
/** /**
* alphabet : Character[] : Enthaelt die Buchstaben des Alphabets. Wird im Laufe des Programmes * alphabet : String : enthaelt die Buchstaben des Alphabets.
* aber immer wieder ueberschrieben.
*/ */
private Character[] walzeAlpha; private String alphabet;
/**
* Ueberschriebener Konstruktor, der die Eingangsparameter der Walze mitgibt
*
* @param walzennr : int : Nummer der gewaehlten Walze
* @param ringstellung : int : Einstellung des Umsprungpunktes
*/
public Walze(int walzennr, int ringstellung) {
this.alphabet = new Character[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
this.walzeAlpha = new Character[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
this.setWalzennr(walzennr);
this.setRingstellung(ringstellung);
}
/**
* Sortiert der Walzennummer das passende Character-Array mittels switch zu.
*
* @return walze : Character[] : gibt die gewaehlte Walze zurueck
*/
private Character[] walzenNummer() {
Character[] walze = new Character[26];
// Character-Arrays fuer die Codierung jeder Walze
Character[] walzeEins = {'E', 'K', 'M', 'F', 'L', 'G', 'D', 'Q', 'V', 'Z', 'N', 'T', 'O', 'W', 'Y',
'H', 'X', 'U', 'S', 'P', 'A', 'I', 'B', 'R', 'C', 'J'};
Character[] walzeZwei = {'A', 'J', 'D', 'K', 'S', 'I', 'R', 'U', 'X', 'B', 'L', 'H', 'W', 'T', 'M',
'C', 'Q', 'G', 'Z', 'N', 'P', 'Y', 'F', 'V', 'O', 'E'};
Character[] walzeDrei = {'B', 'D', 'F', 'H', 'J', 'L', 'C', 'P', 'R', 'T', 'X', 'V', 'Z', 'N', 'Y',
'E', 'I', 'W', 'G', 'A', 'K', 'M', 'U', 'S', 'Q', 'O'};
Character[] walzeVier = {'E', 'S', 'O', 'V', 'P', 'Z', 'J', 'A', 'Y', 'Q', 'U', 'I', 'R', 'H', 'X',
'L', 'N', 'F', 'T', 'G', 'K', 'D', 'C', 'M', 'W', 'B'};
Character[] walzeFuenf = {'V', 'Z', 'B', 'R', 'G', 'I', 'T', 'Y', 'U', 'P', 'S', 'D', 'N', 'H', 'L',
'X', 'A', 'W', 'M', 'J', 'Q', 'O', 'F', 'E', 'C', 'K'};
switch (this.walzennr) { /**
case 1: * ringstellung : char : zeigt die Einstellung fuer den Umspringpunkt.
walze = walzeEins; */
break; private char ringstellung;
case 2:
walze = walzeZwei;
break;
case 3:
walze = walzeDrei;
break;
case 4:
walze = walzeVier;
break;
case 5:
walze = walzeFuenf;
break;
}
return walze;
}
/** /**
* TODO: Dokumentieren * walzenNr : int : Bestimmt, welche Walze genutzt wird.
* */
* @return ringstellung : char : gibt die neue Ringstellung als char zurueck private int walzenNr;
*/
public char getRingstellung() {
return ringstellung;
}
/** //endregion
* Setzt die Initiale Ringstellung der Walze.
* Es sind nur Zahlen von 1 - 26 zugelassen.
*
* Die Ringstellung wird zum char umgewandelt.
* Im Fehlerfall wird die Ringstellung standardmaessig auf 'Z' gesetzt.
*
* @param ringstellung : int : Punkt an dem die Walze umspringt
*/
//TODO ??? Setter Ringstellung
public void setRingstellung(int ringstellung) {
if ((ringstellung > 0) && (ringstellung <= 26)) {
this.ringstellung = this.alphabet[ringstellung - 1];
} else {
this.ringstellung = 'Z';
}
}
/** //region Konstruktor
* Dreht die Walze: verschiebt das Alphabet um keine, eine oder mehrere Stellen und ueberschreibt /**
* das Array alphabet mit der neuen Anordnung. * Ueberschriebener Konstruktor, der die Eingangsparameter der Walze mit gibt.
* *
* @param walzenNr : int : Nummer der gewaehlten Walze.
* @param ringstellung : int : Einstellung des Umsprungpunktes.
*/
public Walze(int walzenNr, int ringstellung) {
this.walzen = new String[5];
this.walzen[0] = "EKMFLGDQVZNTOWYHXUSPAIBRCJ";
this.walzen[1] = "AJDKSIRUXBLHWTMCQGZNPYFVOE";
this.walzen[2] = "BDFHJLCPRTXVZNYEIWGAKMUSQO";
this.walzen[3] = "ESOVPZJAYQUIRHXLNFTGKDCMWB";
this.walzen[4] = "VZBRGITYUPSDNHLXAWMJQOFECK";
this.alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
this.turns = 0;
this.setWalzenNr(walzenNr);
this.setRingstellung(ringstellung);
}
//endregion
//region Funktionen & Methoden
/**
* Dreht die Walze: Zaehlt die Umdrehungen (turns) um eins hoch oder runter, je nach Drehrichtung.
* <p>
* Ueberprueft, ob der Umspringpunkt der Walze nach der Drehung erreicht wurde. * Ueberprueft, ob der Umspringpunkt der Walze nach der Drehung erreicht wurde.
* *
* @param drehung : int[] : Anzahl der Drehungen * @param richtung : int : 1 dreht die Walze weiter und -1 dreht sie einen Schritt zurueck.
* @return checkRing : boolean : gibt true zurueck wenn der Umspringpunkt erreicht wurde * @return checkRing : boolean : gibt true zurueck, wenn der Umspringpunkt erreicht wurde.
* TODO: Doku */
*/ boolean dreheWalze(int richtung) {
public boolean dreheWalze(int... drehung) { boolean checkRing = false;
boolean checkRing = false; int korrekturFaktor = 0;
// fuehrt die Verschiebung des Alphabets um eine Stelle durch if ((richtung == -1) || (richtung == 1)) {
verschiebung(); if (richtung == 1) {
this.turns++;
// fuehrt die Verschiebung mehrfach aus, wenn mehrere Drehungen ausgefuehrt werden sollen } else {
if (drehung.length > 0) { korrekturFaktor = 1;
for (int i = 1; i < drehung[0]; i++) { this.turns--;
verschiebung(); }
}
} // gleicht die Ringstellung mit der aktuellen Position ab
if ((this.alphabet.indexOf(this.getPosition()) + korrekturFaktor) % 26
// gleicht die Ringstellung mit der aktuellen Position ab == this.alphabet.indexOf(this.ringstellung)) {
if (this.getPosition().equals(this.ringstellung)) { checkRing = true;
checkRing = true; }
} }
return checkRing; return checkRing;
} }
/**
* Ueberschreibt die Alphabetswalze mit dem, durch die Drehung, verschobenen Alphabet.
* TODO: Dokumentieren
*/
private void verschiebung() {
Character[] neueWalze = new Character[26];
for (int index = 0; index < neueWalze.length; index++) {
neueWalze[(index + 1) % neueWalze.length] = this.walzeAlpha[index];
}
this.walzeAlpha = neueWalze;
}
/** /**
* TODO: Dokumentieren // dass selbe wie getPosition * Codiert den mitgegebenen Buchstaben anhand der gewaehlten Walze.
* Gibt den Buchstaben zurueck der in der Walze aktuell eingestellt ist.
* *
* @return char an der Stelle temp des Alphabets * @param buchstabe : char : Buchstabe, der verschluesselt werden soll.
*/ * @return char : verschluesselter Buchstabe.
public char getAnzeige() { */
int temp = this.fetchArrayIndex('A', this.walzeAlpha); public char codiere(char buchstabe) {
return this.alphabet[temp]; return this.fetchWalze().charAt((this.alphabet.indexOf(buchstabe) + this.turns) % 26);
} }
/**
* Codiert den mitgegebenen Buchstaben anhand der gewaehlten Walze.
*
* @param buchstabe : char : Buchstabe, der verschluesselt werden soll
* @return buchstabe : char : verschluesselter Buchstabe
*/
public char codiere(char buchstabe) {
/* durchsucht die (verschobene) Alphabetswalze nach dem aktuellen Buchstaben und
uebertraegt den Index auf die gewaehlte Codierwalze*/
buchstabe = walzenNummer()[fetchArrayIndex(buchstabe, walzeAlpha)];
return buchstabe; /**
} * Decodiert den mitgegebenen Buchstaben anhand des Alphabets.
*
* @param buchstabe : char : Buchstabe, der decodiert werden soll.
* @return char : decodierter Buchstabe.
*/
char codiere2(char buchstabe) {
return this.alphabet.charAt((this.fetchWalze().indexOf(buchstabe) - this.turns + 520) % 26);
}
/** /**
* Decodiert den mitgegebenen Buchstaben mit Hilfe der (verschobenen) Alphabetswalze * @return String : Gibt den Verschluesselungs-String der ausgewaehlten Walze zurueck.
* */
* @param buchstabe : char : Buchstabe, der decodiert werden soll private String fetchWalze() {
* @return buchstabe : char : decodierter Buchstabe return walzen[walzenNr];
*/ }
public char codiere2(char buchstabe) {
/* durchsucht die gewaehlte Walze nach dem aktuellen Buchstaben und
uebertraegt den Index auf die (verschobene) Alphabetswalze*/
buchstabe = walzeAlpha[fetchArrayIndex(buchstabe, walzenNummer())];
return buchstabe; //endregion
}
/** //region Setter
* TODO: Dokumentieren /**
* Ermittelt den Index eines Characters in einem Array ueber eine for-Schleife * Setzt die Walzennummer. Es stehen fuenf Walzen zur Auswahl.
* *
* @param buchstabe : Character : Buchstabe, dessen Index benoetigt wird * @param walzenNr : int : Walzennummer.
* @param array : Character[] : Array, in dem der Buchstabe vorkommen soll */
* @return result : int : index des Buchstaben private void setWalzenNr(int walzenNr) {
*/ if ((walzenNr > 0) && (walzenNr < 6)) {
private int fetchArrayIndex(Character buchstabe, Character[] array) { this.walzenNr = walzenNr - 1;
// wird mit ungueltigem Wert initialisiert } else {
int result = -1; System.err.println("Keine gültige Walzennummer");
}
for (int i = 0; i < array.length; i++) { }
if (array[i].equals(buchstabe)) {
result = i;
break;
}
}
return result; /**
} * Setzt die Initiale Ringstellung der Walze.
* Es sind nur Zahlen von 1 - 26 zugelassen.
* <br>
* Die Ringstellung wird zum char umgewandelt.
* Im Fehlerfall wird die Ringstellung standardmaessig auf 'Z' gesetzt.
*
* @param ringstellung : int : Punkt an dem die Nachbarwalze umspringt.
*/
void setRingstellung(int ringstellung) {
if ((ringstellung > 0) && (ringstellung <= 26)) {
this.ringstellung = this.alphabet.charAt(ringstellung - 1);
} else {
this.ringstellung = 'Z';
}
}
/** /**
* Setzt die Walzennummer. Es stehen fuenf Walze zur Auswahl. * Stellt die Grundeinstellung der Walze ein.
* * Ermittelt, wie oft die Walze gedreht werden muss, bis die Grundeinstellung erreicht ist.
* @param walzennr : int : Walzennummer *
*/ * @param buchstabe : Character : Einstellung der Walze.
public void setWalzennr(int walzennr) { */
if ((walzennr > 0) && (walzennr < 6)) { void setPosition(Character buchstabe) {
this.walzennr = walzennr; this.turns = alphabet.indexOf(buchstabe);
} else { }
System.err.println("Keine gültige Walzennummer"); //endregion
}
}
/** //region Getter
* TODO: Dokumentieren // das selbe wie getAnzeig? /**
* Gibt den Character zurueck, der aktuell in der Walze eingestellt ist * Gibt den Buchstaben zurueck, der aktuell in der Walze eingestellt ist.
* *
* @return Character am Index 0 des (verschobenen) Alphabets zurueck * @return char : Ermittelte Stelle im Alphabet, anhand der aktuellen Anzahl der Drehungen.
*/ */
public Character getPosition() { Character getPosition() {
return walzeAlpha[0]; return this.alphabet.charAt(turns % 26);
} }
/** /**
* * TODO: Funktionsname hat sich geändert * Getter der Walzennummer.
* Gibt die Grundeinstellung der Walze ein. Nur Buchstaben von A - Z sind zugelassen. * @return walzenNr : int : gibt Walzennummer zurueck.
* Buchstaben werden automatisch in Grossbuchstaben umgewandelt. */
* Ist die Grundeinstellung nicht 'A', wird die Methode dreheWalze() aufgerufen. int getWalzenNr() {
* return this.walzenNr;
* @param buchstabe : Character : Einstellung der Walze }
*/ //endregion
public void setPosition(Character buchstabe) { }
if (Character.isLetter(buchstabe)) { \ No newline at end of file
buchstabe = Character.toUpperCase(buchstabe);
System.arraycopy(this.alphabet, 0, this.walzeAlpha, 0, this.alphabet.length);
if (buchstabe > 'A') {
dreheWalze(this.fetchArrayIndex(buchstabe, this.walzeAlpha));
}
}
}
}
package projekt.enigma.view;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.GridPane;
import projekt.enigma.model.Codierer;
import java.util.Arrays;
/**
* Die Klasse ChkBoxGripPane erweitert das GridPane Objekt.
* Wir erstellen ein GridPane in welches Checkboxen gelegt werden.
* Die Anzahl der Checkboxen wird durch die verfuegbarenBuchstaben festgelegt.
* Für jeden Buchstaben in diesem char Array, wird eine Checkbox erstellt und auf das Gridpane gelegt.
*/
public class ChkBoxGridPane extends GridPane {
// Der globale Checkbox Array
private CheckBox[] checkbox;
// Die Buchstaben die für das jeweilige Pane selectiert werden sollen
private String checkedBuchstaben;
// Die Anzahl der möglichen Checkboxen
private int charSize;
// Das Codierer Objekt. Dieses wird benötigt um auf die Funktionen für das Steckbrett zuzugreifen
private Codierer codierer;
// Der Steckbrett Port für welchen das Pane und die Checkboxen erstellt werden sollen
private int port;
// Die verfügbaren Buchstaben für den jeweiligen Port
private char[] verfuegbareBuchstaben;
// Das Button Objekt des Ports über den dieses Pane gesteuert wird
private ToggleButton tBtnPort;
/**
* Hier werfen wir die Checkboxen auf das Gridpane und weißen ihnen die Propertys zu.
* Außerdem wird hier auch der Listener generiert womit wir prüfen ob die maximale Auswahlmöglichkeit
* erreicht ist.
* Es können maximal zwei Checkboxen ausgewählt werden. Wenn zwei erreicht sind, werden die restlichen Checkboxen
* deaktiviert. Wenn nur noch eine oder keine Box ausgewählt ist, werden die restlichen wieder aktiviert.
* Bei null und zwei Boxen, werden die Buchstaben in das Steckbrett geschrieben.
* Andere Auswahlmöglchkeiten stehen nicht zur Verfügung, da ein Kabel nur zwei Enden hat in der Regel.
*
* @param codierer : Codierer Objekt
* @param port : int
* @param tBtnPort : ToogleButton
*/
public ChkBoxGridPane(Codierer codierer, int port, ToggleButton tBtnPort) {
this.codierer = codierer;
this.port = port;
this.tBtnPort = tBtnPort;
this.verfuegbareBuchstaben = this.codierer.fetchVerfuegbareBuchstaben(this.port).toCharArray();
Arrays.sort(this.verfuegbareBuchstaben);
charSize = this.verfuegbareBuchstaben.length;
this.checkedBuchstaben = tBtnPort.getText();
initializeComponents();
}
/**
* Es wird ein GridPane erzeugt, das zwei Spalten und abhängig von der Länge des
* Arrays (Character[] alphabet) Reihen hat. Das Label der CheckBoxen soll
* abhängig von deren Index links bzw. recht erzeugt werden
*/
private void initializeComponents() {
checkbox = new CheckBox[charSize];
this.setAlignment(Pos.CENTER);
// Für jeden verfügbaren Buchstaben einen Durchlauf
for (int i = 0; i < this.verfuegbareBuchstaben.length; i++) {
if (this.verfuegbareBuchstaben[i] != 20 && this.verfuegbareBuchstaben[i] != ' ') {
checkbox[i] = new CheckBox(this.verfuegbareBuchstaben[i] + "");
checkbox[i].setPadding(new Insets(1, 1, 1, 1));
if (!checkedBuchstaben.equals("")) {
if (!checkedBuchstaben.contains(String.valueOf(this.verfuegbareBuchstaben[i]))) {
checkbox[i].setDisable(true);
} else {
checkbox[i].setSelected(true);
}
} else {
checkbox[i].setSelected(false);
checkbox[i].setDisable(false);
}
// Der Listener für die jeweilige Checkbox
checkbox[i].selectedProperty().addListener((observable, oldValue, newValue) -> {
String portSelection = "";
int zaehler = 0;
// Die selektierten Chechkboxen zählen
for (CheckBox cb : checkbox) {
if (cb != null && cb.isSelected()) {
zaehler++;
}
}
// Wenn nur eine oder keine Checkbox ausgewählt ist
if (zaehler == 1 || zaehler == 0) {
for (CheckBox cb : checkbox) {
if (cb != null && cb.isDisabled()) {
cb.setDisable(false);
}
}
}
// Es ist keine Checkbox ausgewählt
if (zaehler == 0) {
// Daten ins Steckbrett schreiben
this.codierer.setzeSteckbrett(this.port, "");
// Und den Button neu beschreiben
tBtnPort.setText(portSelection);
}
// Das Maximum an selektierten Checkboxen (2) ist erreicht
if (zaehler == 2) {
for (CheckBox cb : checkbox) {
if (cb != null && !cb.isSelected()) {
cb.setDisable(true);
} else {
if (cb != null) {
portSelection += cb.getText();
}
}
}
// Daten ins Steckbrett schreiben
this.codierer.setzeSteckbrett(this.port, "");
this.codierer.setzeSteckbrett(this.port, portSelection);
// Und den Button neu beschreiben
tBtnPort.setText(portSelection);
}
});
// Eine neue Row im Gridpane anlegen für den nächsten Button
this.addRow(i + 1);
this.add(checkbox[i], 2, i + 1, 1, 1);
}
}
// Das Pane anzeigen
this.setVisible(true);
}
/**
* Gibt den Anzahl der zur Verfügung stehenden Buchstaben zurück.
* Anhang dieses Wertes, wird die Anzahl der Checkboxen festgelegt.
*
* @return int : Anzahl der möglcihen chars
*/
public int getCharSize() {
return charSize;
}
}
No preview for this file type
...@@ -4,627 +4,623 @@ ...@@ -4,627 +4,623 @@
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.control.MenuButton?> <?import javafx.scene.control.MenuButton?>
<?import javafx.scene.control.ProgressBar?> <?import javafx.scene.control.ProgressIndicator?>
<?import javafx.scene.control.TextField?> <?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?> <?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.layout.GridPane?> <?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.Pane?> <?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?> <?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.TilePane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Circle?> <?import javafx.scene.shape.Circle?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="677.0" prefWidth="967.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="projekt.enigma.GuiController"> <AnchorPane fx:id="anchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="677.0" prefWidth="962.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="projekt.enigma.GuiController">
<children> <GridPane layoutX="23.0" layoutY="60.0" prefHeight="158.0" prefWidth="237.0" AnchorPane.leftAnchor="23.0" AnchorPane.topAnchor="60.0">
<GridPane layoutY="313.0" prefHeight="393.0" prefWidth="968.0" AnchorPane.bottomAnchor="-7.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="313.0">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="63.0" minHeight="10.0" prefHeight="63.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="41.0" minHeight="10.0" prefHeight="29.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<children> <Label text="Walze" />
<TextField fx:id="tfStecker1" prefHeight="25.0" prefWidth="48.0" GridPane.columnIndex="1" GridPane.rowIndex="7"> <Label text="Ringe" GridPane.rowIndex="1" />
<GridPane.margin> <Label text="Position" GridPane.rowIndex="2" />
<Insets left="10.0" right="10.0" /> <MenuButton fx:id="mBtnWalzPos1" alignment="CENTER_RIGHT" contentDisplay="CENTER" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="I" GridPane.columnIndex="1">
</GridPane.margin> </MenuButton>
</TextField> <MenuButton fx:id="mBtnWalzPos2" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="I" textAlignment="CENTER" GridPane.columnIndex="2">
<TextField fx:id="tfStecker2" prefHeight="25.0" prefWidth="48.0" GridPane.columnIndex="2" GridPane.rowIndex="7"> </MenuButton>
<GridPane.margin> <MenuButton fx:id="mBtnWalzPos3" mnemonicParsing="false" popupSide="TOP" prefHeight="25.0" prefWidth="48.0" text="I" textAlignment="CENTER" GridPane.columnIndex="3">
<Insets left="10.0" right="10.0" /> </MenuButton>
</GridPane.margin> <MenuButton fx:id="mBtnNotchPos1" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="1" textAlignment="CENTER" GridPane.columnIndex="1" GridPane.rowIndex="1" />
</TextField> <MenuButton fx:id="mBtnNotchPos2" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="1" textAlignment="CENTER" GridPane.columnIndex="2" GridPane.rowIndex="1">
<TextField fx:id="tfStecker3" prefHeight="25.0" prefWidth="48.0" GridPane.columnIndex="3" GridPane.rowIndex="7"> </MenuButton>
<GridPane.margin> <MenuButton fx:id="mBtnNotchPos3" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="1" textAlignment="CENTER" GridPane.columnIndex="3" GridPane.rowIndex="1">
<Insets left="10.0" right="10.0" /> </MenuButton>
</GridPane.margin> <MenuButton fx:id="mBtnStartPos1" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="A" textAlignment="CENTER" GridPane.columnIndex="1" GridPane.rowIndex="2">
</TextField> </MenuButton>
<TextField fx:id="tfStecker4" prefHeight="25.0" prefWidth="48.0" GridPane.columnIndex="4" GridPane.rowIndex="7"> <MenuButton fx:id="mBtnStartPos2" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="A" textAlignment="CENTER" GridPane.columnIndex="2" GridPane.rowIndex="2">
<GridPane.margin> </MenuButton>
<Insets left="10.0" right="10.0" /> <MenuButton fx:id="mBtnStartPos3" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="A" textAlignment="CENTER" GridPane.columnIndex="3" GridPane.rowIndex="2">
</GridPane.margin> </MenuButton>
</TextField> </GridPane>
<TextField fx:id="tfStecker5" prefHeight="25.0" prefWidth="48.0" GridPane.columnIndex="5" GridPane.rowIndex="7"> <GridPane layoutX="23.0" layoutY="222.0" prefHeight="60.0" prefWidth="270.0" AnchorPane.leftAnchor="23.0" AnchorPane.topAnchor="222.0">
<GridPane.margin> <columnConstraints>
<Insets left="10.0" right="10.0" /> <ColumnConstraints hgrow="SOMETIMES" maxWidth="206.0" minWidth="10.0" prefWidth="102.0" />
</GridPane.margin> <ColumnConstraints hgrow="SOMETIMES" maxWidth="224.0" minWidth="10.0" prefWidth="168.0" />
</TextField> </columnConstraints>
<TextField fx:id="tfStecker6" prefHeight="25.0" prefWidth="48.0" GridPane.columnIndex="6" GridPane.rowIndex="7"> <rowConstraints>
<GridPane.margin> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<Insets left="10.0" right="10.0" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</GridPane.margin> </rowConstraints>
</TextField> <Label alignment="CENTER_RIGHT" />
<TextField fx:id="tfStecker7" prefHeight="25.0" prefWidth="48.0" GridPane.columnIndex="7" GridPane.rowIndex="7"> <Label text="Spruchschlüssel:" />
<GridPane.margin> <Label fx:id="lblSpruchschluessel" prefHeight="17.0" prefWidth="181.0" GridPane.columnIndex="1" />
<Insets left="10.0" right="10.0" /> <Button fx:id="btnReset" mnemonicParsing="false" onAction="#gedrueckteTaste" text="Zurücksetzen" GridPane.rowIndex="1" />
</GridPane.margin> </GridPane>
</TextField> <GridPane fx:id="mainGrid" layoutX="6.0" layoutY="294.0" prefHeight="377.0" prefWidth="952.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="300.0">
<TextField fx:id="tfStecker8" prefHeight="25.0" prefWidth="48.0" GridPane.columnIndex="8" GridPane.rowIndex="7">
<GridPane.margin>
<Insets left="10.0" right="10.0" />
</GridPane.margin>
</TextField>
<TextField fx:id="tfStecker9" prefHeight="25.0" prefWidth="48.0" GridPane.columnIndex="9" GridPane.rowIndex="7">
<GridPane.margin>
<Insets left="10.0" right="10.0" />
</GridPane.margin>
</TextField>
<TextField fx:id="tfStecker10" prefHeight="25.0" prefWidth="48.0" GridPane.columnIndex="10" GridPane.rowIndex="7">
<GridPane.margin>
<Insets left="10.0" right="10.0" />
</GridPane.margin>
</TextField>
<Button fx:id="btnM" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="M" textFill="#fffdfd" GridPane.columnIndex="9" GridPane.rowIndex="6">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnN" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="N" textFill="#fffdfd" GridPane.columnIndex="8" GridPane.rowIndex="6">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnB" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="B" textFill="#fffdfd" GridPane.columnIndex="7" GridPane.rowIndex="6">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnV" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="V" textFill="#fffdfd" GridPane.columnIndex="6" GridPane.rowIndex="6">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnC" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="C" textFill="#fffdfd" GridPane.columnIndex="5" GridPane.rowIndex="6">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnX" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="X" textFill="#fffdfd" GridPane.columnIndex="4" GridPane.rowIndex="6">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnY" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="Y" textFill="#fffdfd" GridPane.columnIndex="3" GridPane.rowIndex="6">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnP" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="P" textFill="#fffdfd" GridPane.columnIndex="2" GridPane.rowIndex="6">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnL" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="L" textFill="#fffdfd" GridPane.columnIndex="10" GridPane.rowIndex="6">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnK" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="K" textFill="#fffdfd" GridPane.columnIndex="9" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="28.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnJ" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="J" textFill="#fffdfd" GridPane.columnIndex="8" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="28.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnH" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="H" textFill="#fffdfd" GridPane.columnIndex="7" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="28.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnG" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="G" textFill="#fffdfd" GridPane.columnIndex="6" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="28.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnF" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="F" textFill="#fffdfd" GridPane.columnIndex="5" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="28.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnD" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="D" textFill="#fffdfd" GridPane.columnIndex="4" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="28.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnS" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="S" textFill="#fffdfd" GridPane.columnIndex="3" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="28.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnO" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="O" textFill="#fffdfd" GridPane.columnIndex="10" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnI" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="I" textFill="#fffdfd" GridPane.columnIndex="9" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnU" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="U" textFill="#fffdfd" GridPane.columnIndex="8" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnZ" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="Z" textFill="#fffdfd" GridPane.columnIndex="7" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnT" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="T" textFill="#fffdfd" GridPane.columnIndex="6" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnR" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="R" textFill="#fffdfd" GridPane.columnIndex="5" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnE" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="E" textFill="#fffdfd" GridPane.columnIndex="4" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnW" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="W" textFill="#fffdfd" GridPane.columnIndex="3" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnQ" minHeight="44.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="Q" textFill="#fffdfd" GridPane.columnIndex="2" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button minHeight="44.0" mnemonicParsing="false" onAction="#loeschen" prefHeight="48.0" prefWidth="51.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="&lt;" textFill="#fffdfd" GridPane.columnIndex="10" GridPane.rowIndex="5">
<font>
<Font size="18.0" />
</font>
<GridPane.margin>
<Insets left="28.0" />
</GridPane.margin>
</Button>
<Circle fx:id="circL" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="10" GridPane.rowIndex="2" />
<Circle fx:id="circM" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="9" GridPane.rowIndex="2" />
<Circle fx:id="circN" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="8" GridPane.rowIndex="2" />
<Circle fx:id="circB" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="7" GridPane.rowIndex="2" />
<Circle fx:id="circV" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="6" GridPane.rowIndex="2" />
<Circle fx:id="circC" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="5" GridPane.rowIndex="2" />
<Circle fx:id="circX" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="4" GridPane.rowIndex="2" />
<Circle fx:id="circY" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="3" GridPane.rowIndex="2" />
<Circle fx:id="circP" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="2" GridPane.rowIndex="2" />
<Circle fx:id="circK" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="9" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="35.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circJ" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="8" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="35.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circH" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="7" GridPane.rowIndex="1">
<GridPane.margin>
<Insets bottom="4.0" left="42.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circG" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="6" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="35.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circF" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="5" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="35.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circD" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="4" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="35.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circS" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="3" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="35.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circA" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="2" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="35.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circO" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="10" />
<Circle fx:id="circI" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="9" />
<Circle fx:id="circU" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="8" />
<Circle fx:id="circZ" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="7" />
<Circle fx:id="circT" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="6" />
<Circle fx:id="circR" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="5" />
<Circle fx:id="circE" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="4" />
<Circle fx:id="circW" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="3" />
<Circle fx:id="circQ" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="2" />
<Label fx:id="lblL" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="L" GridPane.columnIndex="10" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblM" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="M" GridPane.columnIndex="9" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblN" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="N" GridPane.columnIndex="8" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblB" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="B" GridPane.columnIndex="7" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblV" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="V" GridPane.columnIndex="6" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblC" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="C" GridPane.columnIndex="5" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblX" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="X" GridPane.columnIndex="4" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblY" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="Y" GridPane.columnIndex="3" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblP" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="P" GridPane.columnIndex="2" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblK" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="K" GridPane.columnIndex="9" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="4.0" left="42.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblJ" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="J" GridPane.columnIndex="8" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="4.0" left="42.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblH" alignment="CENTER" minHeight="0.0" prefHeight="27.0" prefWidth="25.0" text="H" GridPane.columnIndex="7" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="6.0" left="50.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblG" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="G" GridPane.columnIndex="6" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="4.0" left="42.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblF" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="F" GridPane.columnIndex="5" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="4.0" left="42.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblD" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="D" GridPane.columnIndex="4" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="4.0" left="42.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblS" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="S" GridPane.columnIndex="3" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="4.0" left="42.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblA" alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="A" GridPane.columnIndex="2" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="4.0" left="42.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblQ" alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="Q" GridPane.columnIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblW" alignment="CENTER" prefHeight="36.0" prefWidth="30.0" text="W" GridPane.columnIndex="3">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="1.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblE" alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="E" textAlignment="CENTER" GridPane.columnIndex="4">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblR" alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="R" textAlignment="CENTER" GridPane.columnIndex="5">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblT" alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="T" textAlignment="CENTER" GridPane.columnIndex="6">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblZ" alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="Z" textAlignment="CENTER" GridPane.columnIndex="7">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblU" alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="U" textAlignment="CENTER" GridPane.columnIndex="8">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblI" alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="I" textAlignment="CENTER" GridPane.columnIndex="9">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label fx:id="lblO" alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="O" textAlignment="CENTER" GridPane.columnIndex="10">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<TilePane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<VBox prefHeight="200.0" prefWidth="152.0" GridPane.columnIndex="11" />
<Button fx:id="btnA" minHeight="35.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="35.0" prefWidth="42.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="A" textFill="#fffdfd" GridPane.columnIndex="2" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
</children>
</GridPane>
<AnchorPane layoutX="241.0" layoutY="130.0" prefHeight="111.0" prefWidth="487.0" AnchorPane.leftAnchor="241.0" AnchorPane.rightAnchor="240.0">
<children>
<VBox layoutX="72.0" layoutY="-89.0" prefHeight="210.0" prefWidth="377.0" AnchorPane.bottomAnchor="-10.0" AnchorPane.leftAnchor="72.0" AnchorPane.rightAnchor="37.0" AnchorPane.topAnchor="-89.0">
<children>
<TextField fx:id="tfKlartext" editable="false" prefHeight="80.0" prefWidth="377.0" />
<Label prefHeight="17.0" prefWidth="385.0" />
<TextField fx:id="tfCodiert" editable="false" prefHeight="79.0" prefWidth="377.0" />
<Label prefHeight="17.0" prefWidth="385.0" />
<Label fx:id="lblLadeNachricht" alignment="BASELINE_CENTER" contentDisplay="CENTER" prefHeight="5.0" prefWidth="377.0" text="Neue Nachricht wird vom Funkraum abgerufen!" />
<ProgressBar fx:id="pbLadeNachricht" prefHeight="10.0" prefWidth="377.0" progress="0.0" />
</children>
</VBox>
</children></AnchorPane>
<GridPane layoutX="23.0" layoutY="60.0" prefHeight="158.0" prefWidth="237.0" AnchorPane.leftAnchor="23.0" AnchorPane.topAnchor="60.0">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<children> <Button fx:id="btnA" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="A" textFill="#fffdfd" GridPane.columnIndex="2" GridPane.rowIndex="5">
<Label text="Walze" /> <font>
<Label text="Ringe" GridPane.rowIndex="1" /> <Font name="System Bold" size="18.0" />
<Label text="Position" GridPane.rowIndex="2" /> </font>
<MenuButton fx:id="mBtnWalzPos1" alignment="CENTER_RIGHT" contentDisplay="CENTER" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="I" GridPane.columnIndex="1"> </Button>
</MenuButton> <Button fx:id="btnP" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="P" textFill="#fffdfd" GridPane.columnIndex="1" GridPane.rowIndex="6">
<MenuButton fx:id="mBtnWalzPos2" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="I" textAlignment="CENTER" GridPane.columnIndex="2"> <font>
</MenuButton> <Font name="System Bold" size="18.0" />
<MenuButton fx:id="mBtnWalzPos3" mnemonicParsing="false" popupSide="TOP" prefHeight="25.0" prefWidth="48.0" text="I" textAlignment="CENTER" GridPane.columnIndex="3"> </font>
</MenuButton> <GridPane.margin>
<MenuButton fx:id="mBtnNotchPos1" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="1" textAlignment="CENTER" GridPane.columnIndex="1" GridPane.rowIndex="1" /> <Insets left="34.0" />
<MenuButton fx:id="mBtnNotchPos2" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="1" textAlignment="CENTER" GridPane.columnIndex="2" GridPane.rowIndex="1"> </GridPane.margin>
</MenuButton> </Button>
<!-- <MenuButton layoutX="93.0" layoutY="114.0" mnemonicParsing="false">--> <Button fx:id="btnY" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="Y" textFill="#fffdfd" GridPane.columnIndex="2" GridPane.rowIndex="6">
<!-- <items>--> <font>
<!-- <MenuItem mnemonicParsing="false" onAction="#z1" text="1" />--> <Font name="System Bold" size="18.0" />
<!-- <MenuItem mnemonicParsing="false" onAction="#z2" text="2" />--> </font>
<!-- <MenuItem mnemonicParsing="false" onAction="#z3" text="3" />--> <GridPane.margin>
<!-- <MenuItem mnemonicParsing="false" onAction="#z4" text="4" />--> <Insets left="34.0" />
<!-- <MenuItem mnemonicParsing="false" onAction="#z5" text="5" />--> </GridPane.margin>
<!-- <MenuItem mnemonicParsing="false" onAction="#z6" text="6" />--> </Button>
<!-- <MenuItem mnemonicParsing="false" onAction="#z7" text="7" />--> <Button fx:id="btnX" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="X" textFill="#fffdfd" GridPane.columnIndex="3" GridPane.rowIndex="6">
<!-- <MenuItem mnemonicParsing="false" onAction="#z8" text="8" />--> <font>
<!-- <MenuItem mnemonicParsing="false" onAction="#z9" text="9" />--> <Font name="System Bold" size="18.0" />
<!-- <MenuItem mnemonicParsing="false" onAction="#z10" text="10" />--> </font>
<!-- <MenuItem mnemonicParsing="false" onAction="#z11" text="11" />--> <GridPane.margin>
<!-- <MenuItem mnemonicParsing="false" onAction="#z12" text="12" />--> <Insets left="34.0" />
<!-- <MenuItem mnemonicParsing="false" onAction="#z13" text="13" />--> </GridPane.margin>
<!-- <MenuItem mnemonicParsing="false" onAction="#z14" text="14" />--> </Button>
<!-- <MenuItem mnemonicParsing="false" onAction="#z15" text="15" />--> <Button fx:id="btnC" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="C" textFill="#fffdfd" GridPane.columnIndex="4" GridPane.rowIndex="6">
<!-- <MenuItem mnemonicParsing="false" onAction="#z16" text="16" />--> <font>
<!-- <MenuItem mnemonicParsing="false" onAction="#z17" text="17" />--> <Font name="System Bold" size="18.0" />
<!-- <MenuItem mnemonicParsing="false" onAction="#z18" text="18" />--> </font>
<!-- <MenuItem mnemonicParsing="false" onAction="#z19" text="19" />--> <GridPane.margin>
<!-- <MenuItem mnemonicParsing="false" onAction="#z20" text="20" />--> <Insets left="34.0" />
<!-- <MenuItem mnemonicParsing="false" onAction="#z21" text="21" />--> </GridPane.margin>
<!-- <MenuItem mnemonicParsing="false" onAction="#z22" text="22" />--> </Button>
<!-- <MenuItem mnemonicParsing="false" onAction="#z23" text="23" />--> <Button fx:id="btnV" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="V" textFill="#fffdfd" GridPane.columnIndex="5" GridPane.rowIndex="6">
<!-- <MenuItem mnemonicParsing="false" onAction="#z24" text="24" />--> <font>
<!-- <MenuItem mnemonicParsing="false" onAction="#z25" text="25" />--> <Font name="System Bold" size="18.0" />
<!-- <MenuItem mnemonicParsing="false" onAction="#z26" text="26" />--> </font>
<!-- </items>--> <GridPane.margin>
<!-- </MenuButton>--> <Insets left="34.0" />
<MenuButton fx:id="mBtnNotchPos3" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="1" textAlignment="CENTER" GridPane.columnIndex="3" GridPane.rowIndex="1"> </GridPane.margin>
</MenuButton> </Button>
<MenuButton fx:id="mBtnStartPos1" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="A" textAlignment="CENTER" GridPane.columnIndex="1" GridPane.rowIndex="2"> <Button fx:id="btnB" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="B" textFill="#fffdfd" GridPane.columnIndex="6" GridPane.rowIndex="6">
</MenuButton> <font>
<MenuButton fx:id="mBtnStartPos2" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="A" textAlignment="CENTER" GridPane.columnIndex="2" GridPane.rowIndex="2"> <Font name="System Bold" size="18.0" />
</MenuButton> </font>
<MenuButton fx:id="mBtnStartPos3" alignment="CENTER_RIGHT" mnemonicParsing="false" prefHeight="25.0" prefWidth="48.0" text="A" textAlignment="CENTER" GridPane.columnIndex="3" GridPane.rowIndex="2"> <GridPane.margin>
</MenuButton> <Insets left="34.0" />
</children> </GridPane.margin>
</GridPane> </Button>
<FlowPane layoutX="736.0" layoutY="51.0" prefHeight="173.0" prefWidth="195.0" AnchorPane.rightAnchor="36.0" AnchorPane.topAnchor="51.0"> <Button fx:id="btnN" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="N" textFill="#fffdfd" GridPane.columnIndex="7" GridPane.rowIndex="6">
<children> <font>
<Button mnemonicParsing="false" onAction="#btnempfangen" prefHeight="80.0" prefWidth="195.0" text="Funkspruch empfangen" /> <Font name="System Bold" size="18.0" />
<Label prefHeight="17.0" prefWidth="195.0" /> </font>
<Button mnemonicParsing="false" onAction="#btnsenden" prefHeight="80.0" prefWidth="195.0" text="An Funker senden" /> <GridPane.margin>
</children> <Insets left="34.0" />
</FlowPane> </GridPane.margin>
<GridPane layoutX="23.0" layoutY="222.0" prefHeight="60.0" prefWidth="270.0" AnchorPane.leftAnchor="23.0" AnchorPane.topAnchor="222.0"> </Button>
<Button fx:id="btnM" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="M" textFill="#fffdfd" GridPane.columnIndex="8" GridPane.rowIndex="6">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnL" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="L" textFill="#fffdfd" GridPane.columnIndex="9" GridPane.rowIndex="6">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnS" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="S" textFill="#fffdfd" GridPane.columnIndex="3" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnD" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="D" textFill="#fffdfd" GridPane.columnIndex="4" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnF" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="F" textFill="#fffdfd" GridPane.columnIndex="5" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnG" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="G" textFill="#fffdfd" GridPane.columnIndex="6" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnH" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="H" textFill="#fffdfd" GridPane.columnIndex="7" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnJ" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="J" textFill="#fffdfd" GridPane.columnIndex="8" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnK" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="K" textFill="#fffdfd" GridPane.columnIndex="9" GridPane.rowIndex="5">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Button fx:id="btnQ" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="Q" textFill="#fffdfd" GridPane.columnIndex="1" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnW" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="W" textFill="#fffdfd" GridPane.columnIndex="2" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnE" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="E" textFill="#fffdfd" GridPane.columnIndex="3" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnR" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="R" textFill="#fffdfd" GridPane.columnIndex="4" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnT" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="T" textFill="#fffdfd" GridPane.columnIndex="5" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnZ" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="Z" textFill="#fffdfd" GridPane.columnIndex="6" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnU" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="U" textFill="#fffdfd" GridPane.columnIndex="7" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnI" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="I" textFill="#fffdfd" GridPane.columnIndex="8" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnO" minHeight="35.0" mnemonicParsing="false" onMousePressed="#tasteRunter" onMouseReleased="#tasteRauf" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="O" textFill="#fffdfd" GridPane.columnIndex="9" GridPane.rowIndex="4">
<font>
<Font name="System Bold" size="18.0" />
</font>
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Button>
<Button fx:id="btnDelete" minHeight="35.0" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="43.0" prefWidth="45.0" style="-fx-background-radius: 100; -fx-background-color: #0d0d0d;" text="&lt;" textFill="#fffdfd" GridPane.columnIndex="10" GridPane.rowIndex="5">
<font>
<Font size="18.0" />
</font>
</Button>
<Circle fx:id="circQ" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="1">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circP" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="1" GridPane.rowIndex="2">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circY" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="2" GridPane.rowIndex="2">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circA" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="2" GridPane.rowIndex="1" />
<Circle fx:id="circS" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="3" GridPane.rowIndex="1" />
<Circle fx:id="circX" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="3" GridPane.rowIndex="2">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circW" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="2">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circE" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="3">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circD" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="4" GridPane.rowIndex="1" />
<Circle fx:id="circC" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="4" GridPane.rowIndex="2">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circV" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="5" GridPane.rowIndex="2">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circB" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="6" GridPane.rowIndex="2">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circN" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="7" GridPane.rowIndex="2">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circM" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="8" GridPane.rowIndex="2">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circL" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="9" GridPane.rowIndex="2">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circF" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="5" GridPane.rowIndex="1" />
<Circle fx:id="circG" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="6" GridPane.rowIndex="1" />
<Circle fx:id="circH" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="7" GridPane.rowIndex="1" />
<Circle fx:id="circJ" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="8" GridPane.rowIndex="1" />
<Circle fx:id="circK" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="9" GridPane.rowIndex="1" />
<Circle fx:id="circR" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="4">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circT" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="5">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circZ" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="6">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circU" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="7">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circI" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="8">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Circle fx:id="circO" fill="#f0f3f5" radius="22.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="9">
<GridPane.margin>
<Insets left="34.0" />
</GridPane.margin>
</Circle>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="L" GridPane.columnIndex="9" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="5.0" left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="M" GridPane.columnIndex="8" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="5.0" left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="N" GridPane.columnIndex="7" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="5.0" left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="B" GridPane.columnIndex="6" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="5.0" left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="V" GridPane.columnIndex="5" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="5.0" left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="C" GridPane.columnIndex="4" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="5.0" left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="X" GridPane.columnIndex="3" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="5.0" left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="Y" GridPane.columnIndex="2" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="5.0" left="41.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="P" GridPane.columnIndex="1" GridPane.rowIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="5.0" left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="K" GridPane.columnIndex="9" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="J" GridPane.columnIndex="8" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="27.0" prefWidth="25.0" text="H" GridPane.columnIndex="7" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="4.0" left="9.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="G" GridPane.columnIndex="6" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="F" GridPane.columnIndex="5" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="D" GridPane.columnIndex="4" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="S" GridPane.columnIndex="3" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" minHeight="0.0" prefHeight="30.0" prefWidth="30.0" text="A" GridPane.columnIndex="2" GridPane.rowIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets bottom="2.0" left="7.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="O" textAlignment="CENTER" GridPane.columnIndex="9">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="I" textAlignment="CENTER" GridPane.columnIndex="8">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="U" textAlignment="CENTER" GridPane.columnIndex="7">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="Z" textAlignment="CENTER" GridPane.columnIndex="6">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="T" textAlignment="CENTER" GridPane.columnIndex="5">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="R" textAlignment="CENTER" GridPane.columnIndex="4">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="E" textAlignment="CENTER" GridPane.columnIndex="3">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" prefHeight="36.0" prefWidth="30.0" text="W" GridPane.columnIndex="2">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets left="42.0" />
</GridPane.margin>
</Label>
<Label alignment="CENTER" prefHeight="30.0" prefWidth="30.0" text="Q" GridPane.columnIndex="1">
<font>
<Font size="23.0" />
</font>
<GridPane.margin>
<Insets left="42.0" />
</GridPane.margin>
</Label>
</GridPane>
<GridPane layoutX="297.0" layoutY="64.0" prefHeight="168.0" prefWidth="585.0">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="130.0" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="224.0" minWidth="10.0" prefWidth="170.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<children> <Button fx:id="btnSenden" alignment="CENTER" contentDisplay="RIGHT" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="70.0" prefWidth="195.0" text="An Funker senden" textAlignment="CENTER" GridPane.columnIndex="1">
<Label alignment="CENTER_RIGHT" text="Tagesschlüssel:" /> <GridPane.margin>
<Label text="Spruchschlüssel:" GridPane.rowIndex="1" /> <Insets left="80.0" />
<Label fx:id="lblTagesschluessel" prefHeight="17.0" prefWidth="181.0" GridPane.columnIndex="1" /> </GridPane.margin>
<Label fx:id="lblSpruchschluessel" prefHeight="17.0" prefWidth="181.0" GridPane.columnIndex="1" GridPane.rowIndex="1" /> </Button>
</children> <Button fx:id="btnEmpfangen" mnemonicParsing="false" onAction="#gedrueckteTaste" prefHeight="70.0" prefWidth="195.0" text="Funkspruch empfangen" GridPane.columnIndex="1" GridPane.rowIndex="1">
</GridPane> <GridPane.margin>
</children> <Insets left="80.0" />
</GridPane.margin>
</Button>
<TextArea fx:id="tfKlartext" prefHeight="66.0" prefWidth="293.0" wrapText="true">
<GridPane.margin>
<Insets bottom="5.0" top="5.0" />
</GridPane.margin>
</TextArea>
<TextArea fx:id="tfCodiert" prefHeight="200.0" prefWidth="200.0" wrapText="true" GridPane.rowIndex="1">
<GridPane.margin>
<Insets bottom="5.0" top="5.0" />
</GridPane.margin>
</TextArea>
</GridPane>
<Label fx:id="lblKenngruppe" layoutX="682.0" layoutY="34.0" prefHeight="17.0" prefWidth="177.0" />
<Pane layoutX="266.0" layoutY="194.0" prefHeight="200.0" prefWidth="354.0" style="-fx-background-color: white; -fx-border-color: black;" visible="false">
<ProgressIndicator layoutX="127.0" layoutY="70.0" prefHeight="99.0" prefWidth="101.0" />
<Label layoutX="79.0" layoutY="27.0" text="Kommunikation mit Funkraum...">
<font>
<Font size="14.0" />
</font>
</Label>
</Pane>
</AnchorPane> </AnchorPane>
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.shape.Circle?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="411.0" prefWidth="512.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="projekt.enigma.KenngruppeController">
<children>
<Label layoutX="81.0" layoutY="29.0" text="Bitte Kenngruppe eingeben!" AnchorPane.leftAnchor="81.0" AnchorPane.rightAnchor="70.0" AnchorPane.topAnchor="29.0" />
<HBox layoutX="107.0" layoutY="141.0" prefHeight="26.0" prefWidth="276.0" AnchorPane.leftAnchor="107.0" AnchorPane.rightAnchor="129.0" AnchorPane.topAnchor="141.0">
<children>
<Button fx:id="secondaryButton" onAction="#switchToPrimary" prefHeight="25.0" prefWidth="142.0" text="Kenngruppe bestätigen!" />
<Label prefHeight="17.0" prefWidth="159.0" text="Label" />
<Button mnemonicParsing="false" prefHeight="25.0" prefWidth="150.0" text="Button" />
</children>
</HBox>
<Circle fill="DODGERBLUE" layoutX="226.0" layoutY="267.0" radius="100.0" stroke="BLACK" strokeType="INSIDE" AnchorPane.leftAnchor="126.0" AnchorPane.rightAnchor="186.0" AnchorPane.topAnchor="167.0" />
<Button fx:id="secondaryButton" layoutX="40.0" layoutY="85.0" onAction="#switchToPrimary" prefHeight="25.0" prefWidth="241.0" text="Kenngruppe bestätigen!" />
</children>
</AnchorPane>
...@@ -11,54 +11,72 @@ public class HardwareTest { ...@@ -11,54 +11,72 @@ public class HardwareTest {
Hardware h = new Hardware(); Hardware h = new Hardware();
h.setReflektor(new Reflektor()); h.setReflektor(new Reflektor());
h.setSteckbrett(new Steckbrett()); h.setSteckbrett(new Steckbrett());
h.setWalzen(0, 1, 1);
h.setWalzen(1, 2, 1);
h.setWalzen(2, 3, 1);
/* /*
Walze nach der Chiffrierung Walze nach der Chiffrierung
Alphabet {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; Alphabet "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
Steckbrett {'B', 'G', 'D', 'F'} Steckbrett "W S L V H Y G I X A"
Steckbrett {'G', 'B', 'F', 'F'} Steckbrett "J E F B K P M Q U C"
Walze 3 {'B', 'D', 'F', 'H', 'J', 'L', 'C', 'P', 'R', 'T', 'X', 'V', 'Z', 'N', 'Y', 'E', 'I', 'W', 'G', 'A', 'K', 'M', 'U', 'S', 'Q', 'O'};
Walze 2 {'A', 'J', 'D', 'K', 'S', 'I', 'R', 'U', 'X', 'B', 'L', 'H', 'W', 'T', 'M', 'C', 'Q', 'G', 'Z', 'N', 'P', 'Y', 'F', 'V', 'O', 'E'}; Walze 3 "E K M F L G D Q V Z N T O W Y H X U S P A I B R C J"
Walze 1 {'E', 'K', 'M', 'F', 'L', 'G', 'D', 'Q', 'V', 'Z', 'N', 'T', 'O', 'W', 'Y', 'H', 'X', 'U', 'S', 'P', 'A', 'I', 'B', 'R', 'C', 'J'}; Walze 2 "V Z B R G I T Y U P S D N H L X A W M J Q O F E C K"
Reflektor {'E', 'J', 'M', 'Z', 'A', 'L', 'Y', 'X', 'V', 'B', 'W', 'F', 'C', 'R', 'Q', 'U', 'O', 'N', 'T', 'S', 'P', 'I', 'K', 'H', 'G', 'D'}; Walze 1 "A J D K S I R U X B L H W T M C Q G Z N P Y F V O E"
Reflektor "E J M Z A L Y X V B W F C R Q U O N T S P I K H G D"
*/ */
char result; char result;
h.resetWalzen(); h.setWalzen(0, 2, 25);
h.setWalzen(1, 5, 25);
h.setWalzen(2, 1, 25);
result = h.codiere('A'); result = h.codiere('A');
Assert.assertEquals("Codiere: A Erwartet P, erhalten " + result, 'P', result); Assert.assertEquals("Codiere: A Erwartet N, erhalten " + result, 'N', result);
result = h.codiere('B'); result = h.codiere('B');
Assert.assertEquals("Codiere: B Erwartet R, erhalten " + result, 'R', result); Assert.assertEquals("Codiere: B Erwartet K, erhalten " + result, 'K', result);
result = h.codiere('I'); result = h.codiere('I');
Assert.assertEquals("Codiere: I Erwartet E, erhalten " + result, 'E', result); Assert.assertEquals("Codiere: I Erwartet V, erhalten " + result, 'V', result);
result = h.codiere('F'); result = h.codiere('F');
Assert.assertEquals("Codiere: F Erwartet A, erhalten " + result, 'A', result); Assert.assertEquals("Codiere: F Erwartet T, erhalten " + result, 'T', result);
h.resetWalzen(); h.setWalzen(0, 2, 25);
result = h.codiere('P'); h.setWalzen(1, 5, 25);
Assert.assertEquals("Decodiere: P Erwartet A, erhalten " + result, 'A', result); h.setWalzen(2, 1, 25);
result = h.codiere('R'); result = h.codiere('N');
Assert.assertEquals("Decodiere: R Erwartet B, erhalten " + result, 'B', result); Assert.assertEquals("Decodiere: N Erwartet A, erhalten " + result, 'A', result);
result = h.codiere('E'); result = h.codiere('K');
Assert.assertEquals("Decodiere: E Erwartet I, erhalten " + result, 'I', result); Assert.assertEquals("Decodiere: K Erwartet B, erhalten " + result, 'B', result);
result = h.codiere('A'); result = h.codiere('V');
Assert.assertEquals("Decodiere: A Erwartet F, erhalten " + result, 'F', result); Assert.assertEquals("Decodiere: V Erwartet I, erhalten " + result, 'I', result);
result = h.codiere('T');
Assert.assertEquals("Decodiere: T Erwartet F, erhalten " + result, 'F', result);
h.resetWalzen(); h.setWalzen(0, 2, 25);
h.setWalzen(1, 5, 25);
h.setWalzen(2, 1, 25);
h.getSteckbrett().setzeVertauschung('B', 'G'); h.getSteckbrett().setzeVertauschung('B', 'G');
h.getSteckbrett().setzeVertauschung('D', 'F'); h.getSteckbrett().setzeVertauschung('D', 'F');
h.getSteckbrett().setzeVertauschung('I', 'L'); h.getSteckbrett().setzeVertauschung('I', 'L');
h.getSteckbrett().setzeVertauschung('M', 'Q'); h.getSteckbrett().setzeVertauschung('M', 'Q');
h.getSteckbrett().setzeVertauschung('T', 'X'); h.getSteckbrett().setzeVertauschung('N', 'X');
h.getSteckbrett().setzeVertauschung('K', 'Y');
h.getSteckbrett().setzeVertauschung('U', 'Z');
h.getSteckbrett().setzeVertauschung('A', 'O');
h.getSteckbrett().setzeVertauschung('E', 'S');
result = h.codiere('I'); result = h.codiere('I');
Assert.assertEquals("Codiere: Erwartet F, erhalten " + result, 'D', result); Assert.assertEquals("Codiere: I Erwartet C, erhalten " + result, 'C', result);
h.resetWalzen(); h.setWalzen(0, 2, 25);
result = h.codiere('D'); h.setWalzen(1, 5, 25);
Assert.assertEquals("Codiere: Erwartet I, erhalten " + result, 'I', result); h.setWalzen(2, 1, 25);
result = h.codiere('C');
Assert.assertEquals("Codiere: C Erwartet I, erhalten " + result, 'I', result);
h.setWalzen(0, 2, 25);
h.setWalzen(1, 5, 25);
h.setWalzen(2, 1, 25);
h.getSteckbrett().setzeVertauschung('A', 'B');
h.getSteckbrett().setzeVertauschung('C', 'D');
result = h.codiere('A');
Assert.assertEquals("Codiere: A Erwartet M, erhalten " + result, 'M', result);
} }
} }
\ No newline at end of file
...@@ -10,22 +10,22 @@ public class WalzeTest { ...@@ -10,22 +10,22 @@ public class WalzeTest {
@Test @Test
public void setRingstellung() { public void setRingstellung() {
Walze w = new Walze(1, 1); Walze w = new Walze(1, 1);
char temp = w.getAnzeige(); char temp = w.getPosition();
Assert.assertEquals('A', temp); Assert.assertEquals('A', temp);
} }
@Test @Test
public void dreheWalze() { public void dreheWalze() {
Walze w = new Walze(1, 3); Walze w = new Walze(1, 4);
assertFalse("false erwartet, true geliefert", w.dreheWalze(2)); assertFalse("false erwartet, true geliefert", w.dreheWalze(1));
char temp = w.getAnzeige(); char temp = w.getPosition();
Assert.assertEquals("C erwartet, " + temp + " zurück gegeben", 'C', temp); Assert.assertEquals("B erwartet, " + temp + " zurück gegeben", 'B', temp);
} }
@Test @Test
public void getAnzeige() { public void getPosition() {
Walze w = new Walze(1, 1); Walze w = new Walze(1, 1);
char temp = w.getAnzeige(); char temp = w.getPosition();
Assert.assertEquals('A', temp); Assert.assertEquals('A', temp);
} }
......