Update 0.1.5 Added Enigma Models I,M3,M4, fixed ring settings

This commit is contained in:
VanitasVitae 2015-08-27 01:48:33 +02:00
parent 2e405429cf
commit 9258c72daa
31 changed files with 2388 additions and 687 deletions

View file

@ -1,10 +1,12 @@
CHANGELOG ENIGMANDROID CHANGELOG ENIGMANDROID
v0.1.5-not.yet.released< v0.1.5-not.yet.released<
*added missing licenses to class files *Added french number spelling
*Added proper documentation *Added Enigma Models M3, M4
*Extended input interpretation (number spelling in different languages, any unknown special *Added option to select different enigma models into options menu
character now becomes 'X' *Added developer class for simple rotor creation (not a feature in the app)
*Fixed broken ring settings
*Fixed false reset of ring settings when switching from/to landscape mode
v0.1.4-15.08.2015< v0.1.4-15.08.2015<
@ -12,6 +14,10 @@ v0.1.4-15.08.2015<
*Fixed some layout issues *Fixed some layout issues
*Fixed anomaly for step by step inputs *Fixed anomaly for step by step inputs
*Added send/receive text functionality *Added send/receive text functionality
*added missing licenses to class files
*Added proper documentation
*Extended input interpretation (number spelling in different languages, any unknown special
character now becomes 'X'
v0.1.3-14.03.2015< v0.1.3-14.03.2015<
*Added About Dialog with ChangeLog-Button *Added About Dialog with ChangeLog-Button

View file

@ -71,7 +71,7 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.2.1/jars" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
@ -87,9 +87,9 @@
<excludeFolder url="file://$MODULE_DIR$/build/outputs" /> <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" /> <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content> </content>
<orderEntry type="jdk" jdkName="Android API 22 Platform (1)" jdkType="Android SDK" /> <orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="support-v4-22.2.1" level="project" /> <orderEntry type="library" exported="" name="support-v4-23.0.0" level="project" />
<orderEntry type="library" exported="" name="support-annotations-22.2.1" level="project" /> <orderEntry type="library" exported="" name="support-annotations-23.0.0" level="project" />
</component> </component>
</module> </module>

View file

@ -1,15 +1,15 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
android { android {
compileSdkVersion 22 compileSdkVersion 23
buildToolsVersion "22.0.1" buildToolsVersion "22.0.1"
defaultConfig { defaultConfig {
applicationId "de.vanitasvitae.enigmandroid" applicationId "de.vanitasvitae.enigmandroid"
minSdkVersion 15 minSdkVersion 15
targetSdkVersion 22 targetSdkVersion 23
versionCode 10 versionCode 11
versionName "0.1.4-15.08.2015-beta" versionName "0.1.5-27.08.2015-beta"
} }
buildTypes { buildTypes {
release { release {
@ -19,5 +19,5 @@ android {
dependencies { dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:support-v4:22.2.1' compile 'com.android.support:support-v4:23.0.0'
} }

View file

@ -1,13 +0,0 @@
package de.vanitasvitae.enigmandroid;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

View file

@ -9,6 +9,7 @@
android:theme="@style/AppTheme" > android:theme="@style/AppTheme" >
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:label="@string/app_name" > android:label="@string/app_name" >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

View file

@ -1,242 +0,0 @@
package de.vanitasvitae.enigmandroid;
import de.vanitasvitae.enigmandroid.rotors.Reflector;
import de.vanitasvitae.enigmandroid.rotors.Rotor;
/**
* Main component of the Enigma machine
* Copyright (C) 2015 Paul Schaub
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* @author vanitasvitae
*/
public class Enigma
{
private Plugboard plugboard;
//Slots for the rotors
private Rotor r1;
private Rotor r2;
private Rotor r3;
//Slot for the reflector
private Reflector reflector;
private boolean doAnomaly = false; //Has the time come to handle an anomaly?
private boolean prefAnomaly; //Do you WANT to simulate the anomaly?
private InputPreparator inputPreparator;
/**
* Create new Enigma with standard configuration.
* Empty Plugboard, reflector B, rotors I,II,III, Positions 0,0,0
*/
public Enigma()
{
initialize();
}
private void initialize()
{
this.r1 = Rotor.createRotorI(0, 0);
this.r2 = Rotor.createRotorII(0, 0);
this.r3 = Rotor.createRotorIII(0, 0);
this.reflector = Reflector.createReflectorB();
plugboard = new Plugboard();
prefAnomaly = true; //TODO: Is this necessary?
}
/**
* Encrypt / Decrypt a given String w.
* w must be prepared using prepare(w) beforehand.
* Doing so changes the state of the rotors but not the state of the plugboard and the
* ringSettings
*
* @param w Text to decrypt/encrypt
* @return encrypted/decrypted string
*/
public String encrypt(String w)
{
//output string
String output = "";
//for each char x in k
for (char x : w.toCharArray())
{
output = output + this.encryptChar(x);
}
//return en-/decrypted string
return output;
}
/**
* Substitute char k by sending the signal through the enigma.
* This rotates the first rotor and eventually also the second/third beforehand.
* Also this method handles the anomaly in case it should happen
*
* @param k input char
* @return substituted output char
*/
public char encryptChar(char k)
{
//Rotate rotors
r1.rotate();
//Eventually turn next rotor (usual turnOver or anomaly)
if (r1.isAtTurnoverPosition() || (this.doAnomaly && prefAnomaly))
{
r2.rotate();
//Set doAnomaly for next call of encryptChar
this.doAnomaly = r2.doubleTurnAnomaly();
//Eventually rotate next rotor
if (r2.isAtTurnoverPosition())
{
r3.rotate();
}
}
int x = ((int) k)-65; //Cast to int and remove Unicode Offset (A=65 in Unicode.)
//Encryption
//forward direction
x = plugboard.encrypt(x);
x = normalize(x + r1.getRotation());
x = r1.encryptForward(x);
x = normalize(x + r2.getRotation() - r1.getRotation());
x = r2.encryptForward(x);
x = normalize(x + r3.getRotation() - r2.getRotation());
x = r3.encryptForward(x);
x = normalize(x - r3.getRotation());
//backward direction
x = reflector.encrypt(x);
x = normalize(x + r3.getRotation());
x = r3.encryptBackward(x);
x = normalize(x - r3.getRotation() + r2.getRotation());
x = r2.encryptBackward(x);
x = normalize(x - r2.getRotation() + r1.getRotation());
x = r1.encryptBackward(x);
x = normalize(x - r1.getRotation());
x = plugboard.encrypt(x);
return (char) (x + 65); //Add Offset again and cast back to char
}
/**
* Normalize the input.
* Normalizing means keeping the input via modulo in the range from 0 to n-1, where n is equal
* to the size of the rotors (in this case fixed to 26, TODO?).
* This is necessary since java allows negative modulo values,
* which can break this implementation
* @param input input signal
* @return "normalized" input signal
*/
public int normalize(int input)
{
return (26+input)%26;
}
/**
* Set config of the enigma
*
* @param conf configuration
*/
public void setConfiguration(int[] conf)
{
if (conf == null || conf.length != 10)
{
initialize();
}
else
{
int ro1 = conf[0];
int ro2 = conf[1];
int ro3 = conf[2];
int ref = conf[3];
int ro1rot = normalize(conf[4] - 1);
int ro2rot = normalize(conf[5] - 1);
int ro3rot = normalize(conf[6] - 1);
int ro1Ring = conf[7];
int ro2Ring = conf[8];
int ro3Ring = conf[9];
//Set rotors
r1 = Rotor.createRotor(ro1, ro1Ring, ro1rot);
r2 = Rotor.createRotor(ro2, ro2Ring, ro2rot);
r3 = Rotor.createRotor(ro3, ro3Ring, ro3rot);
//Set reflector
reflector = Reflector.createReflector(ref);
//catch double turn anomaly on step by step basis
this.doAnomaly = r2.doubleTurnAnomaly();
}
}
/**
* Set the plugboard
* @param p Plugboard
*/
public void setPlugboard(Plugboard p)
{
this.plugboard = p;
}
/**
* Return the configuration, the enigma machine is in right NOW
*
* @return array containing configuration
*/
public int[] getConfiguration()
{
int[] configuration = new int[10];
{
configuration[0] = r1.getType();
configuration[1] = r2.getType();
configuration[2] = r3.getType();
configuration[3] = reflector.getType();
configuration[4] = r1.getRotation();
configuration[5] = r2.getRotation();
configuration[6] = r3.getRotation();
configuration[7] = r1.getRingSetting();
configuration[8] = r2.getRingSetting();
configuration[9] = r3.getRingSetting();
}
return configuration;
}
/**
* Set the inputPreparator
* @param preparator concrete InputPreparator
*/
public void setInputPreparator(InputPreparator preparator)
{
this.inputPreparator = preparator;
}
/**
* Return the inputPreparator
* @return inputPreparator
*/
public InputPreparator getInputPreparator()
{
return this.inputPreparator;
}
/**
* set prefAnomaly variable
* @param b boolean
*/
public void setPrefAnomaly(boolean b)
{
this.prefAnomaly = b;
}
}

View file

@ -5,16 +5,19 @@ import android.app.AlertDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.view.View;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.EditText; import android.view.View;
import android.widget.Spinner;
import android.widget.ArrayAdapter;
import android.widget.Toast; import android.widget.Toast;
import de.vanitasvitae.enigmandroid.enigma.Plugboard;
import de.vanitasvitae.enigmandroid.enigma.inputPreparer.InputPreparer;
import de.vanitasvitae.enigmandroid.layout.LayoutContainer;
/** /**
* Main Android Activity of the app * Main Android Activity of the app
* Copyright (C) 2015 Paul Schaub * Copyright (C) 2015 Paul Schaub
@ -36,41 +39,27 @@ import android.widget.Toast;
*/ */
public class MainActivity extends Activity public class MainActivity extends Activity
{ {
private Spinner rotor1View;
private Spinner rotor2View;
private Spinner rotor3View;
private Spinner reflectorView;
private Spinner rotor1PositionView;
private Spinner rotor2PositionView;
private Spinner rotor3PositionView;
private EditText plugboardView;
private EditText inputView;
private EditText outputView;
private static final int RESULT_SETTINGS = 1; private static final int RESULT_SETTINGS = 1;
private static final String URI_CHANGELOG = "https://github.com/vanitasvitae/EnigmAndroid/blob/master/CHANGELOG.txt"; private static final String URI_CHANGELOG =
"https://github.com/vanitasvitae/EnigmAndroid/blob/master/CHANGELOG.txt";
private Enigma enigma; LayoutContainer layoutContainer;
//memory for the ringSettings protected String prefMachineType;
private int[] ringSettings = {0,0,0}; protected boolean prefAnomaly;
private boolean prefAnomaly; protected String prefNumericLanguage;
private String prefNumericLanguage;
@Override @Override
public void onCreate(Bundle savedInstanceState) public void onCreate(Bundle savedInstanceState)
{ {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
this.initLayout();
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
this.prefAnomaly = sharedPreferences.getBoolean("prefAnomaly", true); this.prefMachineType = sharedPreferences.getString("prefMachineType", getResources().
this.prefNumericLanguage = sharedPreferences.getString("prefNumericLanguage",getResources(). getStringArray(R.array.pref_list_machine_type)[0]);
getStringArray(R.array.pref_alias_numeric_spelling_language)[0]);
this.resetLayout();
ActivitySingleton singleton = ActivitySingleton.getInstance(); ActivitySingleton singleton = ActivitySingleton.getInstance();
singleton.setActivity(this); singleton.setActivity(this);
updateContentView();
layoutContainer = LayoutContainer.createLayoutContainer(prefMachineType);
updatePreferenceValues();
//Handle shared text //Handle shared text
Intent intent = getIntent(); Intent intent = getIntent();
String action = intent.getAction(); String action = intent.getAction();
@ -82,12 +71,102 @@ public class MainActivity extends Activity
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
if (sharedText != null) if (sharedText != null)
{ {
inputView.setText(sharedText); layoutContainer.getInputView().setText(sharedText);
} }
} }
} }
} }
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
private void updateContentView()
{
switch (prefMachineType)
{
case "M4":
this.setContentView(R.layout.activity_main_m4);
break;
case "M3":
this.setContentView(R.layout.activity_main_i_m3);
break;
default:
this.setContentView(R.layout.activity_main_i_m3);
break;
}
}
private void updatePreferenceValues()
{
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
this.setPrefMachineType(sharedPreferences.getString("prefMachineType", getResources().
getStringArray(R.array.pref_list_machine_type)[0]));
this.setPrefAnomaly(sharedPreferences.getBoolean("prefAnomaly", true));
this.setPrefNumericLanguage(sharedPreferences.getString("prefNumericLanguage", getResources().
getStringArray(R.array.pref_alias_numeric_spelling_language)[0]));
}
public void setPrefMachineType(String type)
{
if(prefMachineType == null || !prefMachineType.equals(type))
{
prefMachineType = type;
String savedInput = "";
if(layoutContainer != null)
{
savedInput = layoutContainer.getInputView().getText().toString();
}
updateContentView();
layoutContainer = LayoutContainer.createLayoutContainer(prefMachineType);
layoutContainer.getInputView().setText(savedInput);
}
}
public String getPrefMachineType()
{
if(prefMachineType != null) return prefMachineType;
else
{
updatePreferenceValues();
return prefMachineType;
}
}
public void setPrefAnomaly(boolean anomaly)
{
if(prefAnomaly !=anomaly)
{
prefAnomaly = anomaly;
layoutContainer.getEnigma().setPrefAnomaly(anomaly);
}
}
public boolean getPrefAnomaly()
{
return prefAnomaly;
}
public void setPrefNumericLanguage(String lang)
{
if(prefNumericLanguage == null || !prefNumericLanguage.equals(lang))
{
prefNumericLanguage = lang;
layoutContainer.getEnigma().setInputPreparer(InputPreparer.createInputPreparer(lang));
}
}
public String getPrefNumericLanguage()
{
if(prefNumericLanguage != null) return prefNumericLanguage;
else
{
updatePreferenceValues();
return prefNumericLanguage;
}
}
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) public boolean onCreateOptionsMenu(Menu menu)
{ {
@ -104,14 +183,14 @@ public class MainActivity extends Activity
int id = item.getItemId(); int id = item.getItemId();
if (id == R.id.action_reset) if (id == R.id.action_reset)
{ {
this.resetLayout(); layoutContainer.reset();
Toast.makeText(getApplicationContext(), R.string.message_reset, Toast.makeText(getApplicationContext(), R.string.message_reset,
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
return true; return true;
} }
else if (id == R.id.action_choose_ringstellung) else if (id == R.id.action_choose_ringstellung)
{ {
showRingSettingsDialog(); layoutContainer.showRingSettingsDialog();
return true; return true;
} }
else if (id == R.id.action_settings) else if (id == R.id.action_settings)
@ -126,7 +205,7 @@ public class MainActivity extends Activity
} }
else if (id == R.id.action_send) else if (id == R.id.action_send)
{ {
if(outputView.getText().length() == 0) if(layoutContainer.getOutputView().getText().length() == 0)
{ {
Toast.makeText(this, R.string.error_no_text_to_send, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.error_no_text_to_send, Toast.LENGTH_SHORT).show();
} }
@ -134,7 +213,7 @@ public class MainActivity extends Activity
{ {
Intent sendIntent = new Intent(); Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND); sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, outputView.getText().toString()); sendIntent.putExtra(Intent.EXTRA_TEXT, layoutContainer.getOutputView().getText().toString());
sendIntent.setType("text/plain"); sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to))); startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));
} }
@ -142,36 +221,6 @@ public class MainActivity extends Activity
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
/**
* Updates the enigma to the chosen rotors and plugboard
*
* @param v View
*/
public void updateEnigma(View v)
{
int[] conf = new int[10];
conf[0] = rotor1View.getSelectedItemPosition() + 1;
conf[1] = rotor2View.getSelectedItemPosition() + 1;
conf[2] = rotor3View.getSelectedItemPosition() + 1;
conf[3] = reflectorView.getSelectedItemPosition() + 1;
conf[4] = rotor1PositionView.getSelectedItemPosition() + 1;
conf[5] = rotor2PositionView.getSelectedItemPosition() + 1;
conf[6] = rotor3PositionView.getSelectedItemPosition() + 1;
conf[7] = ringSettings[0];
conf[8] = ringSettings[1];
conf[9] = ringSettings[2];
enigma = new Enigma();
int[][] plugboardConfiguration;
plugboardView.setText(plugboardView.getText().toString().toUpperCase());
plugboardConfiguration = Plugboard.parseConfigurationString(plugboardView.getText().toString());
enigma.setConfiguration(conf);
enigma.setPlugboard(new Plugboard(plugboardConfiguration));
enigma.setPrefAnomaly(prefAnomaly);
enigma.setInputPreparator(InputPreparator.createInputPreparator(prefNumericLanguage));
}
/** /**
* Set the chosen Configuration to the enigma, get the input string from the input textbox and * Set the chosen Configuration to the enigma, get the input string from the input textbox and
* prepare it, set the input to the prepared text, encrypt the prepared input and set the * prepare it, set the input to the prepared text, encrypt the prepared input and set the
@ -180,174 +229,21 @@ public class MainActivity extends Activity
*/ */
public void doCrypto(View v) public void doCrypto(View v)
{ {
if(inputView.getText().length()!=0) { if(layoutContainer.getInputView().getText().length()!=0) {
updateEnigma(null); layoutContainer.getEnigma().setConfiguration(layoutContainer.createConfiguration());
String m = inputView.getText().toString(); layoutContainer.getEnigma().setPlugboard(new Plugboard(layoutContainer.createPlugboardConfiguration()));
m = enigma.getInputPreparator().prepareString(m); String m = layoutContainer.getInputView().getText().toString();
inputView.setText(m); m = layoutContainer.getEnigma().getInputPreparer().prepareString(m);
outputView.setText(enigma.encrypt(m)); layoutContainer.getInputView().setText(m);
updateSpinner(enigma.getConfiguration()); layoutContainer.getOutputView().setText(layoutContainer.getEnigma().encrypt(m));
layoutContainer.updateLayout();
} }
} }
/** /**
* Reset all the spinners and textboxes and the ringsettings memory * Show a Dialog containing information about the app, license, usage, author and a link
* to the changelog
*/ */
private void resetLayout()
{
rotor1View.setSelection(0);
rotor2View.setSelection(1);
rotor3View.setSelection(2);
reflectorView.setSelection(1);
rotor1PositionView.setSelection(0);
rotor2PositionView.setSelection(0);
rotor3PositionView.setSelection(0);
ringSettings = new int[]{0,0,0};
plugboardView.setText("");
inputView.setText("");
outputView.setText("");
}
/**
* Initialize the Layout
*/
private void initLayout()
{
Character[] charArray = new Character[26];
for(int i=0; i<26; i++) {charArray[i] = (char) (65+i);}
rotor1View = (Spinner) findViewById(R.id.rotor1);
ArrayAdapter<CharSequence> rotor1Adapter = ArrayAdapter.createFromResource(this,
R.array.enigma_rotors, android.R.layout.simple_spinner_item);
rotor1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor1View.setAdapter(rotor1Adapter);
rotor2View = (Spinner) findViewById(R.id.rotor2);
ArrayAdapter<CharSequence> rotor2Adapter = ArrayAdapter.createFromResource(this,
R.array.enigma_rotors, android.R.layout.simple_spinner_item);
rotor2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor2View.setAdapter(rotor2Adapter);
rotor3View = (Spinner) findViewById(R.id.rotor3);
ArrayAdapter<CharSequence> rotor3Adapter = ArrayAdapter.createFromResource(this,
R.array.enigma_rotors, android.R.layout.simple_spinner_item);
rotor3Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor3View.setAdapter(rotor3Adapter);
reflectorView = (Spinner) findViewById(R.id.reflector);
ArrayAdapter<CharSequence> relfectorAdapter = ArrayAdapter.createFromResource(this,
R.array.enigma_reflectors, android.R.layout.simple_spinner_item);
relfectorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
reflectorView.setAdapter(relfectorAdapter);
rotor1PositionView = (Spinner) findViewById(R.id.rotor1position);
ArrayAdapter<Character> rotor1PositionAdapter = new ArrayAdapter<>(this.getApplicationContext(),
android.R.layout.simple_spinner_item,charArray);
rotor1PositionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor1PositionView.setAdapter(rotor1PositionAdapter);
rotor2PositionView = (Spinner) findViewById(R.id.rotor2position);
ArrayAdapter<Character> rotor2PositionAdapter = new ArrayAdapter<>(this.getApplicationContext(),
android.R.layout.simple_spinner_item,charArray);
rotor2PositionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor2PositionView.setAdapter(rotor2PositionAdapter);
rotor3PositionView = (Spinner) findViewById(R.id.rotor3position);
ArrayAdapter<Character> rotor3PositionAdapter = new ArrayAdapter<>(this.getApplicationContext(),
android.R.layout.simple_spinner_item,charArray);
rotor3PositionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor3PositionView.setAdapter(rotor3PositionAdapter);
plugboardView = (EditText) findViewById(R.id.plugboard);
plugboardView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
plugboardView.setText(plugboardView.getText().toString().toUpperCase());
}
}
});
inputView = (EditText) findViewById(R.id.input);
outputView = (EditText) findViewById(R.id.output);
inputView.requestFocus();
}
/**
* Update the Spinners to their new Positions
* @param c Configuration
*/
public void updateSpinner(int[] c)
{
rotor1View.setSelection(c[0] - 1);
rotor2View.setSelection(c[1] - 1);
rotor3View.setSelection(c[2] - 1);
rotor1PositionView.setSelection(c[4]);
rotor2PositionView.setSelection(c[5]);
rotor3PositionView.setSelection(c[6]);
}
/**
* Show the dialog where the user can pick the ringsettings and set them if the user doesn't
* abort.
*/
public void showRingSettingsDialog()
{
View ringSettingsView = View.inflate(this, R.layout.dialog_ringsettings, null);
Integer[] ringArray = new Integer[26];
for(int i=1; i<=26; i++) {ringArray[i-1] = i;}
final Spinner ring1 = (Spinner) ringSettingsView.findViewById(R.id.rotor1ring);
ArrayAdapter<Integer> ring1Adapter = new ArrayAdapter<>(this.getApplicationContext(),
android.R.layout.simple_spinner_item,ringArray);
ring1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
ring1.setAdapter(ring1Adapter);
ring1.setSelection(ringSettings[0]);
final Spinner ring2 = (Spinner) ringSettingsView.findViewById(R.id.rotor2ring);
ArrayAdapter<Integer> ring2Adapter = new ArrayAdapter<>(this.getApplicationContext(),
android.R.layout.simple_spinner_item,ringArray);
ring2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
ring2.setAdapter(ring2Adapter);
ring2.setSelection(ringSettings[1]);
final Spinner ring3 = (Spinner) ringSettingsView.findViewById(R.id.rotor3ring);
ArrayAdapter<Integer> ring3Adapter = new ArrayAdapter<>(this.getApplicationContext(),
android.R.layout.simple_spinner_item,ringArray);
ring3Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
ring3.setAdapter(ring3Adapter);
ring3.setSelection(ringSettings[2]);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.title_ringsetting);
builder.setView(ringSettingsView)
.setCancelable(true)
.setPositiveButton(R.string.dialog_positiv, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
ringSettings = new int[]{ring1.getSelectedItemPosition(),
ring2.getSelectedItemPosition(), ring3.getSelectedItemPosition()};
String message = getResources().getString(R.string.dialog_ringsettings_success) + " " + (ringSettings[2]+1) + ", " +
(ringSettings[1]+1) + ", " + (ringSettings[0]+1) + ".";
Toast.makeText(getApplicationContext(), message,
Toast.LENGTH_LONG).show();
}
})
.setNegativeButton(R.string.dialog_negativ, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.cancel();
Toast.makeText(getApplicationContext(), R.string.dialog_ringsettings_abort,
Toast.LENGTH_SHORT).show();
}
}).show();
}
public void showAboutDialog() public void showAboutDialog()
{ {
final View aboutView = View.inflate(this, R.layout.dialog_about, null); final View aboutView = View.inflate(this, R.layout.dialog_about, null);
@ -373,6 +269,12 @@ public class MainActivity extends Activity
}).show(); }).show();
} }
/**
* Handle preference changes
* @param requestCode requestCode
* @param resultCode resultCode (RESULT_SETTINGS is defined at the top)
* @param data data (not important here)
*/
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
@ -380,45 +282,63 @@ public class MainActivity extends Activity
case RESULT_SETTINGS: case RESULT_SETTINGS:
{ {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
this.prefAnomaly = sharedPrefs.getBoolean("prefAnomaly", true); this.setPrefMachineType(sharedPrefs.getString("prefMachineType", getResources()
this.prefNumericLanguage = sharedPrefs.getString("prefNumericLanguage",getResources(). .getStringArray(R.array.pref_list_machine_type)[0]));
getStringArray(R.array.pref_alias_numeric_spelling_language)[0]); this.setPrefAnomaly(sharedPrefs.getBoolean("prefAnomaly", true));
; this.setPrefNumericLanguage(this.prefNumericLanguage = sharedPrefs.getString("prefNumericLanguage", getResources().
getStringArray(R.array.pref_alias_numeric_spelling_language)[0]));
break; break;
} }
} }
} }
/**
* Open the web page with the URL url
* @param url URL of the website
*/
public void openWebPage(String url) { public void openWebPage(String url) {
Uri webpage = Uri.parse(url); Uri webPage = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, webpage); Intent intent = new Intent(Intent.ACTION_VIEW, webPage);
if (intent.resolveActivity(getPackageManager()) != null) { if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent); startActivity(intent);
} }
} }
public static class ActivitySingleton /**
* Singleton that grants access to an Activity from anywhere within the app
*/
public static class ActivitySingleton
{
private static ActivitySingleton instance = null;
private Activity activity;
//private constructor
private ActivitySingleton(){}
//Singleton method
public static ActivitySingleton getInstance()
{ {
private static ActivitySingleton instance = null; if(instance == null) instance = new ActivitySingleton();
private Activity activity; return instance;
private ActivitySingleton(){}
public static ActivitySingleton getInstance()
{
if(instance == null) instance = new ActivitySingleton();
return instance;
}
public void setActivity(Activity activity)
{
this.activity = activity;
}
public Activity getActivity()
{
return activity;
}
} }
/**
* Set an Activity that the Singleton returns
* @param activity activity that's stored
*/
public void setActivity(Activity activity)
{
this.activity = activity;
}
/**
* Returns the stored Activity
* @return stored Activity
*/
public Activity getActivity()
{
return activity;
}
}
} }

View file

@ -0,0 +1,168 @@
package de.vanitasvitae.enigmandroid.enigma;
import de.vanitasvitae.enigmandroid.MainActivity;
import de.vanitasvitae.enigmandroid.enigma.inputPreparer.InputPreparer;
/**
* Main component of the Enigma machine
* This is the mostly abstract base of any enigma machine.
* Copyright (C) 2015 Paul Schaub
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* @author vanitasvitae
*/
public abstract class Enigma
{
protected static String machineType;
protected boolean doAnomaly = false; //Has the time come to handle an anomaly?
protected boolean prefAnomaly; //Do you WANT to simulate the anomaly?
protected InputPreparer inputPreparer;
/**
* Set the enigma to an initial state
*/
public abstract void initialize();
/**
* Set the reflector of the enigma machine to one of type type.
* @param type type indicator of the reflector
* @return success (not every reflector fits in every machine)
*/
public abstract boolean setReflector(int type);
/**
* Set the rotor on position pos to a rotor of type type with ring-setting ringSetting and
* rotation rotation.
* @param pos position of the rotor
* @param type type indicator
* @param ringSetting ringSetting
* @param rotation rotation
* @return success
*/
public abstract boolean setRotor(int pos, int type, int ringSetting, int rotation);
/**
* Encrypt / Decrypt a given String w.
* w must be prepared using prepare(w) beforehand.
* Doing so changes the state of the rotors but not the state of the plugboard and the
* ringSettings
*
* @param w Text to decrypt/encrypt
* @return encrypted/decrypted string
*/
public String encrypt(String w)
{
//output string
String output = "";
//for each char x in k
for (char x : w.toCharArray())
{
output = output + this.encryptChar(x);
}
//return en-/decrypted string
return output;
}
/**
* Set the enigma into the next mechanical state.
* This rotates the first rotor and eventually also the second/third.
* Also this method handles the anomaly in case it should happen.
*/
public abstract void nextState();
/**
* Substitute char k by sending the signal through the enigma.
* The signal passes the plugboard, the rotors and returns back after going through the
* reflector wheel.
*
* @param k input char
* @return substituted output char
*/
public abstract char encryptChar(char k);
/**
* Normalize the input.
* Normalizing means keeping the input via modulo in the range from 0 to n-1, where n is equal
* to the size of the rotors.
* This is necessary since java allows negative modulo values,
* which can break this implementation
* @param input input signal
* @return "normalized" input signal
*/
public abstract int normalize(int input);
/**
* Set config of the enigma
*
* @param conf configuration
*/
public abstract void setConfiguration(int[] conf);
/**
* Set the plugboard
* @param p Plugboard
*/
public abstract void setPlugboard(Plugboard p);
/**
* Return the configuration, the enigma machine is in right NOW
*
* @return array containing configuration
*/
public abstract int[] getConfiguration();
/**
* Set the inputPreparer
* @param preparer concrete InputPreparer
*/
public void setInputPreparer(InputPreparer preparer)
{
this.inputPreparer = preparer;
}
/**
* Return the inputPreparer
* @return inputPreparer
*/
public InputPreparer getInputPreparer()
{
if(inputPreparer == null)
{
MainActivity main = (MainActivity) MainActivity.ActivitySingleton.getInstance().getActivity();
inputPreparer = InputPreparer.createInputPreparer(main.getPrefNumericLanguage());
}
return this.inputPreparer;
}
/**
* set prefAnomaly variable
* @param b boolean
*/
public void setPrefAnomaly(boolean b)
{
this.prefAnomaly = b;
}
/**
* Return the type indicator of the enigma machine
* @return type
*/
public String getMachineType()
{
return machineType;
}
}

View file

@ -0,0 +1,171 @@
package de.vanitasvitae.enigmandroid.enigma;
import android.util.Log;
import de.vanitasvitae.enigmandroid.enigma.rotors.Reflector;
import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor;
/**
* Concrete implementation of an enigma machine of type I
* Copyright (C) 2015 Paul Schaub
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* @author vanitasvitae
*/
public class Enigma_I extends Enigma {
protected Rotor rotor1;
protected Rotor rotor2;
protected Rotor rotor3;
protected Reflector reflector;
protected Plugboard plugboard;
public Enigma_I() {
machineType = "I";
}
@Override
public void initialize()
{
this.setPlugboard(new Plugboard());
//I,II,III, A, 0,0,0, 0,0,0
this.setConfiguration(new int[]{1,2,3,1,0,0,0,0,0,0});
}
@Override
public void nextState()
{
rotor1.rotate();
if (rotor1.isAtTurnoverPosition() || (this.doAnomaly && prefAnomaly))
{
rotor2.rotate();
this.doAnomaly = rotor2.doubleTurnAnomaly();
if (rotor2.isAtTurnoverPosition())
{
rotor3.rotate();
}
}
}
@Override
public char encryptChar(char k)
{
nextState();
int x = ((int) k)-65; //Cast to int and remove Unicode Offset (A=65 in Unicode.)
//Encryption
//forward direction
x = plugboard.encrypt(x);
x = normalize(x + rotor1.getRotation() - rotor1.getRingSetting());
x = rotor1.encryptForward(x);
x = normalize(x - rotor1.getRotation() + rotor1.getRingSetting() + rotor2.getRotation() - rotor2.getRingSetting());
x = rotor2.encryptForward(x);
x = normalize(x - rotor2.getRotation() + rotor2.getRingSetting() + rotor3.getRotation() - rotor3.getRingSetting());
x = rotor3.encryptForward(x);
x = normalize(x - rotor3.getRotation() + rotor3.getRingSetting());
//TODO: CHECK
//backward direction
x = reflector.encrypt(x);
x = normalize(x + rotor3.getRotation() - rotor3.getRingSetting());
x = rotor3.encryptBackward(x);
x = normalize(x + rotor2.getRotation() - rotor2.getRingSetting() - rotor3.getRotation() + rotor3.getRingSetting());
x = rotor2.encryptBackward(x);
x = normalize(x + rotor1.getRotation() - rotor1.getRingSetting() - rotor2.getRotation() + rotor2.getRingSetting());
x = rotor1.encryptBackward(x);
x = normalize(x - rotor1.getRotation() + rotor1.getRingSetting());
x = plugboard.encrypt(x);
return (char) (x + 65); //Add Offset again, cast back to char and return
}
@Override
public int normalize(int input) {
return (input+26) % 26;
}
@Override
public void setPlugboard(Plugboard p)
{
this.plugboard = p;
}
@Override
public int[] getConfiguration()
{
int[] conf = new int[10];
conf[0] = rotor1.getType();
conf[1] = rotor2.getType();
conf[2] = rotor3.getType();
conf[3] = reflector.getType();
conf[4] = rotor1.getRotation();
conf[5] = rotor2.getRotation();
conf[6] = rotor3.getRotation();
conf[7] = rotor1.getRingSetting();
conf[8] = rotor2.getRingSetting();
conf[9] = rotor3.getRingSetting();
return conf;
}
@Override
/**
* conf:
* 0..2 -> rotor1..rotor3 type
* 3 -> reflector type
* 4..6 -> rotor1..rotor3 rotation
* 7..9 -> rotor1..rotor3 ringSetting
*/
public void setConfiguration(int[] conf)
{
this.setRotor(1,conf[0],conf[7],conf[4]);
this.setRotor(2,conf[1],conf[8],conf[5]);
this.setRotor(3,conf[2],conf[9],conf[6]);
this.setReflector(conf[3]);
}
@Override
public boolean setRotor(int pos, int type, int ringSetting, int rotation)
{
if(pos >= 1 && pos <= 3) {
if (type >= 1 && type <= 5) {
Rotor rotor = Rotor.createRotor(type, ringSetting, rotation);
switch (pos) {
case 1:
rotor1 = rotor;
break;
case 2:
rotor2 = rotor;
break;
default:
rotor3 = rotor;
break;
}
return true;
}
}
Log.d("EnigmAndroid/M3/setRot", "Error: Type " + type + " at position " + pos);
return false;
}
@Override
public boolean setReflector(int type)
{
if(type >= 1 && type <= 3)
{
reflector = Reflector.createReflector(type);
return true;
}
Log.d("EnigmAndroid/I/setRef", "Error: Can't set type "+type);
return false;
}
}

View file

@ -0,0 +1,75 @@
package de.vanitasvitae.enigmandroid.enigma;
import android.util.Log;
import de.vanitasvitae.enigmandroid.enigma.rotors.Reflector;
import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor;
/**
* Concrete implementation of an enigma machine model M3
* Copyright (C) 2015 Paul Schaub
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* @author vanitasvitae
*/
public class Enigma_M3 extends Enigma_I
{
public Enigma_M3()
{
machineType = "M3";
}
@Override
public void initialize()
{
this.setPlugboard(new Plugboard());
//I,II,III, B, 0,0,0, 0,0,0
this.setConfiguration(new int[]{1,2,3,2,0,0,0,0,0,0});
}
@Override
public boolean setRotor(int pos, int type, int ringSetting, int rotation)
{
if(pos >= 1 && pos <= 3) {
if (type >= 1 && type <= 8) {
Rotor rotor = Rotor.createRotor(type, ringSetting, rotation);
switch (pos) {
case 1:
rotor1 = rotor;
break;
case 2:
rotor2 = rotor;
break;
default:
rotor3 = rotor;
break;
}
return true;
}
}
Log.d("EnigmAndroid/M3/setRot", "Error: Type " + type + " at position " + pos);
return false;
}
@Override
public boolean setReflector(int type)
{
if(type >= 2 && type <= 3)
{
reflector = Reflector.createReflector(type);
return true;
}
Log.d("EnigmAndroid/M3/setRef", "Error: Can't set type "+type);
return false;
}
}

View file

@ -0,0 +1,214 @@
package de.vanitasvitae.enigmandroid.enigma;
import android.util.Log;
import de.vanitasvitae.enigmandroid.enigma.rotors.Reflector;
import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor;
/**
* Concrete Implementation of the Enigma Machine type M4 of the german Kriegsmarine
* Copyright (C) 2015 Paul Schaub
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* @author vanitasvitae
*/
public class Enigma_M4 extends Enigma
{
private Rotor rotor1;
private Rotor rotor2;
private Rotor rotor3;
private Rotor rotor4;
private Reflector thinReflector;
private Plugboard plugboard;
public Enigma_M4()
{
machineType = "M4";
}
@Override
public boolean setRotor(int pos, int type, int ringSetting, int rotation)
{
if(pos >= 1 && pos <= 3)
{
if(type >= 1 && type <= 8)
{
Rotor rotor = Rotor.createRotor(type, ringSetting, rotation);
switch (pos)
{
case 1: rotor1 = rotor;
break;
case 2: rotor2 = rotor;
break;
default: rotor3 = rotor;
}
return true;
}
else
{
Log.d("EnigmAndroid/M4/setRot", "Error: Type " + type + " at position " + pos);
return false;
}
}
//Thin rotor
else if(pos == 4)
{
if(type >=9 && type <=10) {
rotor4 = Rotor.createRotor(type, ringSetting, rotation);
return true;
}
}
Log.d("EnigmAndroid/M3/setRot", "Error: Type " + type + " at position " + pos);
return false;
}
@Override
public boolean setReflector(int type)
{
if(type >= 4 && type <=5)
{
this.thinReflector = Reflector.createReflector(type);
return true;
}
Log.d("EnigmAndroid/M4/setRef","Error: Can't set type "+type);
return false;
}
@Override
public void initialize()
{
this.setPlugboard(new Plugboard());
this.setConfiguration(new int[]{1,2,3,9,4,0,0,0,0,0,0,0,0});
this.prefAnomaly = true;
}
@Override
/**
* Set the enigma into the next mechanical state.
* This rotates the first rotor and eventually also the second/third.
* Also this method handles the anomaly in case it should happen.
*/
public void nextState()
{
//Rotate rotors
rotor1.rotate();
//Eventually turn next rotor (usual turnOver or anomaly)
if (rotor1.isAtTurnoverPosition() || (this.doAnomaly && prefAnomaly))
{
rotor2.rotate();
//Set doAnomaly for next call of encryptChar
this.doAnomaly = rotor2.doubleTurnAnomaly();
//Eventually rotate next rotor
if (rotor2.isAtTurnoverPosition())
{
rotor3.rotate();
}
}
}
@Override
/**
* Substitute char k by sending the signal through the enigma.
* The signal passes the plugboard, the rotors and returns back after going through the
* reflector wheel.
*
* @param k input char
* @return substituted output char
*/
public char encryptChar(char k)
{
nextState(); //Rotate rotors
int x = ((int) k)-65; //Cast to int and remove Unicode Offset (A=65 in Unicode.)
//Encryption
//forward direction
x = plugboard.encrypt(x);
x = normalize(x + rotor1.getRotation() - rotor1.getRingSetting());
x = rotor1.encryptForward(x);
x = normalize(x - rotor1.getRotation() + rotor1.getRingSetting() + rotor2.getRotation() - rotor2.getRingSetting());
x = rotor2.encryptForward(x);
x = normalize(x - rotor2.getRotation() + rotor2.getRingSetting() + rotor3.getRotation() - rotor3.getRingSetting());
x = rotor3.encryptForward(x);
x = normalize(x - rotor3.getRotation() + rotor3.getRingSetting() + rotor4.getRotation() - rotor4.getRingSetting());
x = rotor4.encryptForward(x);
x = normalize(x - rotor4.getRotation() + rotor4.getRingSetting());
//backward direction
x = thinReflector.encrypt(x);
x = normalize(x + rotor4.getRotation() - rotor4.getRingSetting());
x = rotor4.encryptBackward(x);
x = normalize(x + rotor3.getRotation() - rotor3.getRingSetting() - rotor4.getRotation() + rotor4.getRingSetting());
x = rotor3.encryptBackward(x);
x = normalize(x + rotor2.getRotation() - rotor2.getRingSetting() - rotor3.getRotation() + rotor3.getRingSetting());
x = rotor2.encryptBackward(x);
x = normalize(x + rotor1.getRotation() - rotor1.getRingSetting() - rotor2.getRotation() + rotor2.getRingSetting());
x = rotor1.encryptBackward(x);
x = normalize(x - rotor1.getRotation() + rotor1.getRingSetting());
x = plugboard.encrypt(x);
return (char) (x + 65); //Add Offset again and cast back to char
}
@Override
public int normalize(int input) {
return (input + 26) % 26;
}
@Override
public void setPlugboard(Plugboard p)
{
this.plugboard = p;
}
@Override
public int[] getConfiguration() {
int[] configuration = new int[13];
configuration[0] = rotor1.getType();
configuration[1] = rotor2.getType();
configuration[2] = rotor3.getType();
configuration[3] = rotor4.getType();
configuration[4] = thinReflector.getType();
configuration[5] = rotor1.getRotation();
configuration[6] = rotor2.getRotation();
configuration[7] = rotor3.getRotation();
configuration[8] = rotor4.getRotation();
configuration[9] = rotor1.getRingSetting();
configuration[10] = rotor2.getRingSetting();
configuration[11] = rotor3.getRingSetting();
configuration[12] = rotor4.getRingSetting();
return configuration;
}
@Override
public void setConfiguration(int[] conf)
{
if(conf.length != 13)
{
Log.d("EnigmAndroid/M4/setCon", "Invalid conf array length. conf array length " +
"should be 13 (is "+conf.length+")");
}
else
{
setRotor(1, conf[0], conf[9], conf[5]);
setRotor(2, conf[1], conf[10], conf[6]);
setRotor(3, conf[2], conf[11], conf[7]);
setRotor(4, conf[3], conf[12], conf[8]);
setReflector(conf[4]);
}
}
}

View file

@ -1,10 +1,13 @@
package de.vanitasvitae.enigmandroid; package de.vanitasvitae.enigmandroid.enigma;
import android.app.Activity; import android.app.Activity;
import android.widget.Toast; import android.widget.Toast;
import java.util.ArrayList; import java.util.ArrayList;
import de.vanitasvitae.enigmandroid.MainActivity;
import de.vanitasvitae.enigmandroid.R;
/** /**
* Plugboard of the enigma * Plugboard of the enigma
* Copyright (C) 2015 Paul Schaub * Copyright (C) 2015 Paul Schaub

View file

@ -1,9 +1,7 @@
package de.vanitasvitae.enigmandroid; package de.vanitasvitae.enigmandroid.enigma.inputPreparer;
import java.text.Normalizer;
/** /**
* Preparator class that prepares input text to only consist of [A..Z] * Preparer class that prepares input text to only consist of [A..Z]
* Copyright (C) 2015 Paul Schaub * Copyright (C) 2015 Paul Schaub
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -21,11 +19,11 @@ import java.text.Normalizer;
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* @author vanitasvitae * @author vanitasvitae
*/ */
public abstract class InputPreparator public abstract class InputPreparer
{ {
/** /**
* Prepare the input String in a way that it only contains letters from [A..Z]. * Prepare the input String in a way that it only contains letters from [A..Z].
* Replace special characters and spell numbers. * Replace special characters, remove spaces and spell numbers.
* @param input String * @param input String
* @return prepared String * @return prepared String
*/ */
@ -46,7 +44,7 @@ public abstract class InputPreparator
output = output + replaceNumber(x); output = output + replaceNumber(x);
} }
//x is special symbol //x is special symbol
else else if (x != ' ')
{ {
output = output + 'X'; output = output + 'X';
} }
@ -62,24 +60,25 @@ public abstract class InputPreparator
public abstract String replaceNumber(char input); public abstract String replaceNumber(char input);
/** /**
* Factory method that creates a specific InputPreparator * Factory method that creates a specific InputPreparer
* @param language language alias that specifies the language (de,en) * @param language language alias that specifies the language (de,fr,en)
* @return concrete InputPreparator * @return concrete InputPreparer
*/ */
public static InputPreparator createInputPreparator(String language) public static InputPreparer createInputPreparer(String language)
{ {
switch (language) switch (language)
{ {
case "de": return new InputPreparatorGerman(); case "de": return new InputPreparerGerman();
default: return new InputPreparatorEnglish(); case "fr": return new InputPreparerFrench();
default: return new InputPreparerEnglish();
} }
} }
} }
/** /**
* Concrete implementation of a german InputPreparator * Concrete implementation of a german InputPreparer
*/ */
class InputPreparatorGerman extends InputPreparator class InputPreparerGerman extends InputPreparer
{ {
@Override @Override
public String replaceNumber(char input) { public String replaceNumber(char input) {
@ -100,9 +99,9 @@ class InputPreparatorGerman extends InputPreparator
} }
/** /**
* Concrete implementation of an english InputPreparator * Concrete implementation of an english InputPreparer
*/ */
class InputPreparatorEnglish extends InputPreparator class InputPreparerEnglish extends InputPreparer
{ {
@Override @Override
public String replaceNumber(char input) public String replaceNumber(char input)
@ -120,4 +119,28 @@ class InputPreparatorEnglish extends InputPreparator
default: return "NINE"; default: return "NINE";
} }
} }
}
/**
* Concrete implementation of a french InputPreparer
*/
class InputPreparerFrench extends InputPreparer
{
@Override
public String replaceNumber(char input)
{
switch (input) {
case '0': return "ZERO";
case '1': return "UN";
case '2': return "DEUX";
case '3': return "TROIS";
case '4': return "QUATRE";
case '5': return "CINQ";
case '6': return "SIX";
case '7': return "SEPT";
case '8': return "HUIT";
default: return "NEUF";
}
}
} }

View file

@ -1,4 +1,4 @@
package de.vanitasvitae.enigmandroid.rotors; package de.vanitasvitae.enigmandroid.enigma.rotors;
/** /**
* Reflector of the enigma machine. * Reflector of the enigma machine.
@ -42,33 +42,6 @@ public class Reflector
this.connections = connections; this.connections = connections;
} }
/**
* Creates a reflector of type A
* @return ReflectorA
*/
public static Reflector createReflectorA()
{
return new ReflectorA();
}
/**
* Creates a reflector of type B
* @return ReflectorB
*/
public static Reflector createReflectorB()
{
return new ReflectorB();
}
/**
* Creates a reflector of type C
* @return ReflectorC
*/
public static Reflector createReflectorC()
{
return new ReflectorC();
}
/** /**
* Factory method to create reflectors. * Factory method to create reflectors.
* @param type type of the created reflector * @param type type of the created reflector
@ -81,9 +54,11 @@ public class Reflector
{ {
switch (type) switch (type)
{ {
case 1: return createReflectorA(); case 1: return new ReflectorA();
case 2: return createReflectorB(); case 2: return new ReflectorB();
default: return createReflectorC(); case 3: return new ReflectorC();
case 4: return new ReflectorThinB();
default: return new ReflectorThinC();
} }
} }
@ -141,34 +116,70 @@ public class Reflector
/** /**
* Concrete implementation of ReflectorA * Concrete implementation of ReflectorA
* Used in Enigma I
* AE BJ CM DZ FL GY HX IV KW NR OQ PU ST
*/ */
private static class ReflectorA extends Reflector private static class ReflectorA extends Reflector
{ {
public ReflectorA() public ReflectorA()
{ {
super("A", 1, new Integer[]{4, 9, 12, 25, 0, 11, 24, 23, 21, 1, 22, 5, 2, 17, 16, 20, 14, 13, 19, 18, 15, 8, 10, 7, 6, 3}); super("A", 1, new Integer[]{4,9,12,25,0,11,24,23,21,1,22,5,2,17,16,20,14,13,19,18,15,8,10,7,6,3});
} }
} }
/** /**
* Concrete implementation of ReflectorB * Concrete implementation of ReflectorB
* Used in Enigma I, M3
* AY BR CU DH EQ FS GL IP JX KN MO TZ VW
*/ */
private static class ReflectorB extends Reflector private static class ReflectorB extends Reflector
{ {
public ReflectorB() public ReflectorB()
{ {
super("B", 2, new Integer[]{24, 17, 20, 7, 16, 18, 11, 3, 15, 23, 13, 6, 14, 10, 12, 8, 4, 1, 5, 25, 2, 22, 21, 9, 0, 19}); super("B", 2, new Integer[]{24,17,20,7,16,18,11,3,15,23,13,6,14,10,12,8,4,1,5,25,2,22,21,9,0,19});
} }
} }
/** /**
* Concrete implementation of ReflectorC * Concrete implementation of ReflectorC
* Used in Enigma I, M3
* AF BV CP DJ EI GO HY KR LZ MX NW QT SU
*/ */
private static class ReflectorC extends Reflector private static class ReflectorC extends Reflector
{ {
public ReflectorC() public ReflectorC()
{ {
super("C", 3, new Integer[]{5, 21, 15, 9, 8, 0, 14, 24, 4, 3, 17, 25, 23, 22, 6, 2, 19, 10, 20, 16, 18, 1, 13, 12, 7, 11}); super("C", 3, new Integer[]{5,21,15,9,8,0,14,24,4,3,17,25,23,22,6,2,19,10,20,16,18,1,13,12,7,11});
}
}
/**
* Concrete implementation of thin reflector type b (not equal to normal type b!)
* When used with Rotor Beta on rotation 0, the pair was equivalent to normal reflector B
* S->Beta->ThinB->Beta'->X == X->UKWB->S
* Used in Enigma M4
* E N K Q A U Y W J I C O P B L M D X Z V F T H R G S
*/
private static class ReflectorThinB extends Reflector
{
public ReflectorThinB()
{
super("B", 4, new Integer[]{4,13,10,16,0,20,24,22,9,8,2,14,15,1,11,12,3,23,25,21,5,19,7,17,6,18});
}
}
/**
* Concrete implementation of thin reflector type c (not equal to normal type c!)
* When used with Rotor Gamma on rotation 0, the pair was equivalent to normal reflector C
* S->Gamma->ThinC->Gamma'->X == X->UKWC->S
* Used in Enigma M4
* R D O B J N T K V E H M L F C W Z A X G Y I P S U Q
*/
private static class ReflectorThinC extends Reflector
{
public ReflectorThinC()
{
super("B", 5, new Integer[]{17,3,14,1,9,13,19,10,21,4,7,12,11,5,2,22,25,0,23,6,24,8,15,18,20,16});
} }
} }

View file

@ -1,4 +1,4 @@
package de.vanitasvitae.enigmandroid.rotors; package de.vanitasvitae.enigmandroid.enigma.rotors;
/** /**
* Rotor super class and inner concrete implementations * Rotor super class and inner concrete implementations
@ -30,7 +30,7 @@ public class Rotor
protected int type; protected int type;
protected Integer[] connections; protected Integer[] connections;
protected Integer[] reversedConnections; protected Integer[] reversedConnections;
protected int turnOverNotch; protected Integer[] turnOverNotches;
protected int ringSetting; protected int ringSetting;
protected int rotation; protected int rotation;
@ -47,18 +47,18 @@ public class Rotor
* @param reversedConnections inverse wiring used to encrypt in the opposite direction * @param reversedConnections inverse wiring used to encrypt in the opposite direction
* (connections[reversedConnections[i]] = i * (connections[reversedConnections[i]] = i
* for all i in 0..getRotorSize()-1. * for all i in 0..getRotorSize()-1.
* @param turnOverNotch Position of the turnover notch * @param turnOverNotches Position(s) of the turnover notch(es)
* @param ringSetting setting of the ring that holds the letters * @param ringSetting setting of the ring that holds the letters
* @param rotation rotation of the rotor * @param rotation rotation of the rotor
*/ */
protected Rotor(String name, int type, Integer[] connections, Integer[] reversedConnections, protected Rotor(String name, int type, Integer[] connections, Integer[] reversedConnections,
int turnOverNotch, int ringSetting, int rotation) Integer[] turnOverNotches, int ringSetting, int rotation)
{ {
this.name = name; this.name = name;
this.type = type; this.type = type;
this.connections = connections; this.connections = connections;
this.reversedConnections = reversedConnections; this.reversedConnections = reversedConnections;
this.turnOverNotch = turnOverNotch; this.turnOverNotches = turnOverNotches;
this.ringSetting = ringSetting; this.ringSetting = ringSetting;
this.rotation = rotation; this.rotation = rotation;
} }
@ -66,7 +66,9 @@ public class Rotor
/** /**
* Factory method that creates a rotor accordingly to the type. * Factory method that creates a rotor accordingly to the type.
* Also initialize the rotor with ringSetting and rotation. * Also initialize the rotor with ringSetting and rotation.
* @param type type indicator (1..5) * @param type type indicator (1..10)
* 1..8 -> I..VIII
* 9,10 -> Beta, Gamma
* @param ringSetting setting of the outer ring (0..25) * @param ringSetting setting of the outer ring (0..25)
* @param rotation rotation of the rotor * @param rotation rotation of the rotor
* @return Concrete rotor * @return Concrete rotor
@ -75,77 +77,28 @@ public class Rotor
{ {
switch (type) switch (type)
{ {
case 1: return createRotorI(ringSetting, rotation); case 1: return new RotorI(ringSetting, rotation);
case 2: return createRotorII(ringSetting, rotation); case 2: return new RotorII(ringSetting, rotation);
case 3: return createRotorIII(ringSetting, rotation); case 3: return new RotorIII(ringSetting, rotation);
case 4: return createRotorIV(ringSetting, rotation); case 4: return new RotorIV(ringSetting, rotation);
default: return createRotorV(ringSetting, rotation); case 5: return new RotorV(ringSetting, rotation);
case 6: return new RotorVI(ringSetting, rotation);
case 7: return new RotorVII(ringSetting, rotation);
case 8: return new RotorVIII(ringSetting, rotation);
case 9: return new RotorBeta(ringSetting, rotation);
default: return new RotorGamma(ringSetting, rotation);
} }
} }
/** /**
* Create concrete Rotor of type 1 (I) initialized with ringSetting and rotation * Encrypt an input signal via the internal wiring in "forward" direction towards the reflector
* @param ringSetting setting of the outer ring * (using connections)
* @param rotation rotation of the rotor
* @return RotorI
*/
public static Rotor createRotorI(int ringSetting, int rotation)
{
return new RotorI(ringSetting, rotation);
}
/**
* Create concrete Rotor of type 2 (II) initialized with ringSetting and rotation
* @param ringSetting setting of the outer ring
* @param rotation rotation of the rotor
* @return RotorI
*/
public static Rotor createRotorII(int ringSetting, int rotation)
{
return new RotorII(ringSetting, rotation);
}
/**
* Create concrete Rotor of type 3 (III) initialized with ringSetting and rotation
* @param ringSetting setting of the outer ring
* @param rotation rotation of the rotor
* @return RotorI
*/
public static Rotor createRotorIII(int ringSetting, int rotation)
{
return new RotorIII(ringSetting, rotation);
}
/**
* Create concrete Rotor of type 4 (IV) initialized with ringSetting and rotation
* @param ringSetting setting of the outer ring
* @param rotation rotation of the rotor
* @return RotorI
*/
public static Rotor createRotorIV(int ringSetting, int rotation)
{
return new RotorIV(ringSetting, rotation);
}
/**
* Create concrete Rotor of type 5 (V) initialized with ringSetting and rotation
* @param ringSetting setting of the outer ring
* @param rotation rotation of the rotor
* @return RotorI
*/
public static Rotor createRotorV(int ringSetting, int rotation)
{
return new RotorV(ringSetting, rotation);
}
/**
* Encrypt an input signal via the internal wiring in "forward" direction (using connections)
* @param input signal * @param input signal
* @return encrypted signal * @return encrypted signal
*/ */
public int encryptForward(int input) public int encryptForward(int input)
{ {
return this.connections[normalize(input)]; return this.connections[normalize(input)];// - this.ringSetting)];
} }
/** /**
@ -156,7 +109,7 @@ public class Rotor
*/ */
public int encryptBackward(int input) public int encryptBackward(int input)
{ {
return this.reversedConnections[normalize(input)]; return this.reversedConnections[normalize(input)];// + this.ringSetting)];
} }
/** /**
@ -175,7 +128,7 @@ public class Rotor
*/ */
public int getRotation() public int getRotation()
{ {
return this.rotation - this.getRingSetting(); return this.rotation;
} }
/** /**
@ -192,7 +145,12 @@ public class Rotor
*/ */
public boolean isAtTurnoverPosition() public boolean isAtTurnoverPosition()
{ {
return this.rotation == this.turnOverNotch; for(int x : getTurnOverNotches())
{
//if(x == this.rotation + this.ringSetting) return true;
if(x == this.rotation) return true;
}
return false;
} }
/** /**
@ -206,16 +164,20 @@ public class Rotor
*/ */
public boolean doubleTurnAnomaly() public boolean doubleTurnAnomaly()
{ {
return this.rotation == this.getTurnOver() - 1; for(int x : getTurnOverNotches())
{
if(this.rotation == x-1) return true;
}
return false;
} }
/** /**
* Returns the position of the turnover notch * Returns the positions of the turnover notches in a array
* @return turnOverNotch * @return turnOverNotches
*/ */
public int getTurnOver() public Integer[] getTurnOverNotches()
{ {
return this.turnOverNotch; return this.turnOverNotches;
} }
/** /**
@ -261,6 +223,8 @@ public class Rotor
/** /**
* Concrete implementation of Rotor of type 1 (I) * Concrete implementation of Rotor of type 1 (I)
* Used in Enigma I, M3, M4
* 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
*/ */
private static class RotorI extends Rotor private static class RotorI extends Rotor
{ {
@ -269,12 +233,14 @@ public class Rotor
super("I", 1, super("I", 1,
new Integer[]{4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9}, new Integer[]{4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9},
new Integer[]{20, 22, 24, 6, 0, 3, 5, 15, 21, 25, 1, 4, 2, 10, 12, 19, 7, 23, 18, 11, 17, 8, 13, 16, 14, 9}, new Integer[]{20, 22, 24, 6, 0, 3, 5, 15, 21, 25, 1, 4, 2, 10, 12, 19, 7, 23, 18, 11, 17, 8, 13, 16, 14, 9},
17, ringSetting, rotation); new Integer[]{17}, ringSetting, rotation);
} }
} }
/** /**
* Concrete implementation of Rotor of type 2 (II) * Concrete implementation of Rotor of type 2 (II)
* Used in Enigma I, M3, M4
* 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
*/ */
private static class RotorII extends Rotor private static class RotorII extends Rotor
{ {
@ -283,12 +249,14 @@ public class Rotor
super("II", 2, super("II", 2,
new Integer[]{0, 9, 3, 10, 18, 8, 17, 20, 23, 1, 11, 7, 22, 19, 12, 2, 16, 6, 25, 13, 15, 24, 5, 21, 14, 4}, new Integer[]{0, 9, 3, 10, 18, 8, 17, 20, 23, 1, 11, 7, 22, 19, 12, 2, 16, 6, 25, 13, 15, 24, 5, 21, 14, 4},
new Integer[]{0, 9, 15, 2, 25, 22, 17, 11, 5, 1, 3, 10, 14, 19, 24, 20, 16, 6, 4, 13, 7, 23, 12, 8, 21, 18}, new Integer[]{0, 9, 15, 2, 25, 22, 17, 11, 5, 1, 3, 10, 14, 19, 24, 20, 16, 6, 4, 13, 7, 23, 12, 8, 21, 18},
5, ringSetting, rotation); new Integer[]{5}, ringSetting, rotation);
} }
} }
/** /**
* Concrete implementation of Rotor of type 3 (III) * Concrete implementation of Rotor of type 3 (III)
* Used in Enigma I, M3, M4
* 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
*/ */
private static class RotorIII extends Rotor private static class RotorIII extends Rotor
{ {
@ -297,12 +265,14 @@ public class Rotor
super("III", 3, super("III", 3,
new Integer[]{1, 3, 5, 7, 9, 11, 2, 15, 17, 19, 23, 21, 25, 13, 24, 4, 8, 22, 6, 0, 10, 12, 20, 18, 16, 14}, new Integer[]{1, 3, 5, 7, 9, 11, 2, 15, 17, 19, 23, 21, 25, 13, 24, 4, 8, 22, 6, 0, 10, 12, 20, 18, 16, 14},
new Integer[]{19, 0, 6, 1, 15, 2, 18, 3, 16, 4, 20, 5, 21, 13, 25, 7, 24, 8, 23, 9, 22, 11, 17, 10, 14, 12}, new Integer[]{19, 0, 6, 1, 15, 2, 18, 3, 16, 4, 20, 5, 21, 13, 25, 7, 24, 8, 23, 9, 22, 11, 17, 10, 14, 12},
22, ringSetting, rotation); new Integer[]{22}, ringSetting, rotation);
} }
} }
/** /**
* Concrete implementation of Rotor of type 4 (IV) * Concrete implementation of Rotor of type 4 (IV)
* Used in Enigma M3, M4
* 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
*/ */
private static class RotorIV extends Rotor private static class RotorIV extends Rotor
{ {
@ -311,12 +281,14 @@ public class Rotor
super("IV", 4, super("IV", 4,
new Integer[]{4, 18, 14, 21, 15, 25, 9, 0, 24, 16, 20, 8, 17, 7, 23, 11, 13, 5, 19, 6, 10, 3, 2, 12, 22, 1}, new Integer[]{4, 18, 14, 21, 15, 25, 9, 0, 24, 16, 20, 8, 17, 7, 23, 11, 13, 5, 19, 6, 10, 3, 2, 12, 22, 1},
new Integer[]{7, 25, 22, 21, 0, 17, 19, 13, 11, 6, 20, 15, 23, 16, 2, 4, 9, 12, 1, 18, 10, 3, 24, 14, 8, 5}, new Integer[]{7, 25, 22, 21, 0, 17, 19, 13, 11, 6, 20, 15, 23, 16, 2, 4, 9, 12, 1, 18, 10, 3, 24, 14, 8, 5},
10, ringSetting, rotation); new Integer[]{10}, ringSetting, rotation);
} }
} }
/** /**
* Concrete implementation of Rotor of type 5 (V) * Concrete implementation of Rotor of type 5 (V)
* Used in Enigma M3, M4
* 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
*/ */
private static class RotorV extends Rotor private static class RotorV extends Rotor
{ {
@ -325,7 +297,117 @@ public class Rotor
super("V", 5, super("V", 5,
new Integer[]{21, 25, 1, 17, 6, 8, 19, 24, 20, 15, 18, 3, 13, 7, 11, 23, 0, 22, 12, 9, 16, 14, 5, 4, 2, 10}, new Integer[]{21, 25, 1, 17, 6, 8, 19, 24, 20, 15, 18, 3, 13, 7, 11, 23, 0, 22, 12, 9, 16, 14, 5, 4, 2, 10},
new Integer[]{16, 2, 24, 11, 23, 22, 4, 13, 5, 19, 25, 14, 18, 12, 21, 9, 20, 3, 10, 6, 8, 0, 17, 15, 7, 1}, new Integer[]{16, 2, 24, 11, 23, 22, 4, 13, 5, 19, 25, 14, 18, 12, 21, 9, 20, 3, 10, 6, 8, 0, 17, 15, 7, 1},
0, ringSetting, rotation); new Integer[]{0}, ringSetting, rotation);
}
}
/**
* Concrete implementation of Rotor of type 6 (VI)
* Used in Enigma M3, M4
* J P G V O U M F Y Q B E N H Z R D K A S X L I C T W
*/
private static class RotorVI extends Rotor
{
public RotorVI(int ringSetting, int rotation)
{
super("VI", 6,
new Integer[]{9,15,6,21,14,20,12,5,24,16,1,4,13,7,25,17,3,10,0,18,23,11,8,2,19,22},
new Integer[]{18,10,23,16,11,7,2,13,22,0,17,21,6,12,4,1,9,15,19,24,5,3,25,20,8,14},
new Integer[]{0,13}, ringSetting, rotation);
}
}
/**
* Concrete implementation of Rotor of type 7 (VII)
* Used in Enigma M3, M4
* N Z J H G R C X M Y S W B O U F A I V L P E K Q D T
*/
private static class RotorVII extends Rotor
{
public RotorVII(int ringSetting, int rotation)
{
super("VII", 7,
new Integer[]{13,25,9,7,6,17,2,23,12,24,18,22,1,14,20,5,0,8,21,11,15,4,10,16,3,19},
new Integer[]{16,12,6,24,21,15,4,3,17,2,22,19,8,0,13,20,23,5,10,25,14,18,11,7,9,1},
new Integer[]{0,13}, ringSetting, rotation);
}
}
/**
* Concrete implementation of Rotor of type 8 (VIII)
* Used in Enigma M3, M4
* F K Q H T L X O C B J S P D Z R A M E W N I U Y G V
*/
private static class RotorVIII extends Rotor
{
public RotorVIII(int ringSetting, int rotation)
{
super("VIII", 8,
new Integer[]{5,10,16,7,19,11,23,14,2,1,9,18,15,3,25,17,0,12,4,22,13,8,20,24,6,21},
new Integer[]{16,9,8,13,18,0,24,3,21,10,1,5,17,20,7,12,2,15,11,4,22,25,19,6,23,14},
new Integer[]{0,13}, ringSetting, rotation);
}
}
/**
* Concrete implementation of Rotor of type beta (Griechenwalze Beta)
* Beta was used as a "thin" rotor in the M4. It was thinner than a "normal" rotor, so it
* could be used together with one of the two thin reflectors as one rotor.
* When used together with ReflectorThinB, Beta was equivalent to Reflector B (if rotation == 0)
* That way the M4 was backwards compatible to the M3
* Used in M4
*/
private static class RotorBeta extends Rotor
{
public RotorBeta(int ringSetting, int rotation)
{
super("Beta",9,
new Integer[]{11,4,24,9,21,2,13,8,23,22,15,1,16,12,3,17,19,0,10,25,6,5,20,7,14,18},
new Integer[]{17,11,5,14,1,21,20,23,7,3,18,0,13,6,24,10,12,15,25,16,22,4,9,8,2,19},
new Integer[]{}, ringSetting, rotation);
}
@Override
public void rotate()
{
//Thin rotors are fixed in position, so they dont rotate
}
@Override
public boolean doubleTurnAnomaly()
{
//Nope, no anomaly
return false;
}
}
/**
* Concrete implementation of Rotor of type gamma (Griechenwalze Gamma)
* Gamma was used as a "thin" rotor in the M4. It was thinner than a "normal" rotor, so it
* could be used together with one of the two thin reflectors as one rotor.
* When used together with ReflectorThinC, Gamma is equivalent to Reflector C
* (if rotation == 0). That way the M4 was backwards compatible to the M3
* Used in M4
*/
private static class RotorGamma extends Rotor
{
public RotorGamma(int ringSetting, int rotation)
{
super("Gamma",10,
new Integer[]{5,18,14,10,0,13,20,4,17,7,12,1,19,8,24,2,22,11,16,15,25,23,21,6,9,3},
new Integer[]{4,11,15,25,7,0,23,9,13,24,3,17,10,5,2,19,18,8,1,12,6,22,16,21,14,20},
new Integer[]{}, ringSetting, rotation);
}
@Override
public void rotate()
{
//Thin rotors are fixed in position, so they don't rotate
}
@Override
public boolean doubleTurnAnomaly()
{
//Thin rotors don't do such weird stuff, they're normal just like you and me.
return false;
} }
} }
} }

View file

@ -0,0 +1,107 @@
package de.vanitasvitae.enigmandroid.enigma.util;
/**
* Used to create wiring arrays from strings
* Use strings like "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" as input
* Copyright (C) 2015 Paul Schaub
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* @author vanitasvitae
*/
public class RotorMaker
{
public static final int l = 26;
public static void main(String[] args)
{
if(args.length == l) makeRotor(args);
else if(args.length == 1) makeRotor(prepare(args[0]));
else System.out.println("wrong input format!");
}
public static void makeRotor(String input)
{
makeRotor(prepare(input));
}
/**
* Prepare the string (add spaces)
* @param in input string
* @return prepared string
*/
public static String[] prepare(String in)
{
String[] out = new String[l];
int pos = 0;
for(char x : in.toCharArray())
{
if(x != ' ')
{
try
{
out[pos] = ""+x;
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("String too long!");
return null;
}
pos++;
}
}
if(pos!=l)
{
System.out.println("String too short!");
return null;
}
return out;
}
/**
* Generate Array initializer for the given rotor configuration
* @param input String describing the rotor
*/
public static void makeRotor(String[] input)
{
if(input.length != l) System.out.println("Wrong length! Input must have length "+l+"!");
else
{
Integer[] out1 = new Integer[l];
for(int i=0; i<l; i++)
{
String x = input[i].toUpperCase();
char xc = x.charAt(0);
int xint = (int) xc;
xint = xint - 65;
out1[i] = xint;
}
Integer[] out2 = new Integer[l];
for(int i=0; i<l; i++)
{
out2[out1[i]] = i;
}
String output1 = "{";
String output2 = "{";
for(int i=0; i<l; i++)
{
output1 = output1 + out1[i]+",";
output2 = output2 + out2[i]+",";
}
output1 = output1.substring(0,output1.length()-1) + "}";
output2 = output2.substring(0,output2.length()-1) + "}";
System.out.println("connections :" + output1);
System.out.println("revConnects :" + output2);
}
}
}

View file

@ -0,0 +1,78 @@
package de.vanitasvitae.enigmandroid.layout;
import android.widget.EditText;
import de.vanitasvitae.enigmandroid.MainActivity;
import de.vanitasvitae.enigmandroid.enigma.Enigma;
/**
* Abstract LayoutContainer for Enigma machines
* This class contains the layout and controls the layout elements such as spinners and stuff
* Copyright (C) 2015 Paul Schaub
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* @author vanitasvitae
*/
public abstract class LayoutContainer
{
protected MainActivity main;
protected Enigma enigma;
protected EditText inputView;
protected EditText outputView;
protected int[] ringSettings;
public LayoutContainer()
{
this.main = (MainActivity) MainActivity.ActivitySingleton.getInstance().getActivity();
}
abstract void initialize();
public abstract void reset();
public abstract void updateLayout();
public abstract int[] createConfiguration();
public abstract int[][] createPlugboardConfiguration();
public abstract void showRingSettingsDialog();
public Enigma getEnigma()
{
return enigma;
}
public EditText getInputView()
{
return this.inputView;
}
public EditText getOutputView()
{
return this.outputView;
}
public static LayoutContainer createLayoutContainer(String type)
{
switch (type)
{
case "M4":
return new LayoutContainer_M4();
case "M3":
return new LayoutContainer_M3();
default:
return new LayoutContainer_I();
}
}
}

View file

@ -0,0 +1,224 @@
package de.vanitasvitae.enigmandroid.layout;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import de.vanitasvitae.enigmandroid.R;
import de.vanitasvitae.enigmandroid.enigma.Enigma_I;
import de.vanitasvitae.enigmandroid.enigma.Plugboard;
/**
* Concrete LayoutContainer for the Enigma I layout.
* This class contains the layout and controls the layout elements such as spinners and stuff
* Copyright (C) 2015 Paul Schaub
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* @author vanitasvitae
*/
public class LayoutContainer_I extends LayoutContainer
{
protected Spinner rotor1View;
protected Spinner rotor2View;
protected Spinner rotor3View;
protected Spinner reflectorView;
protected Spinner rotor1PositionView;
protected Spinner rotor2PositionView;
protected Spinner rotor3PositionView;
protected EditText plugboardView;
public LayoutContainer_I()
{
super();
main.setTitle("I - EnigmAndroid");
this.enigma = new Enigma_I();
this.ringSettings = new int[]{0,0,0};
this.rotor1View = (Spinner) main.findViewById(R.id.rotor1);
this.rotor2View = (Spinner) main.findViewById(R.id.rotor2);
this.rotor3View = (Spinner) main.findViewById(R.id.rotor3);
this.reflectorView = (Spinner) main.findViewById(R.id.reflector);
this.rotor1PositionView = (Spinner) main.findViewById(R.id.rotor1position);
this.rotor2PositionView = (Spinner) main.findViewById(R.id.rotor2position);
this.rotor3PositionView = (Spinner) main.findViewById(R.id.rotor3position);
this.plugboardView = (EditText) main.findViewById(R.id.plugboard);
this.inputView = (EditText) main.findViewById(R.id.input);
this.outputView = (EditText) main.findViewById(R.id.output);
initialize();
reset();
}
@Override
void initialize()
{
Character[] rotorPositionArray = new Character[26];
for(int i=0; i<26; i++) {rotorPositionArray[i] = (char) (65+i); /**Fill with A..Z*/}
ArrayAdapter<CharSequence> rotor1Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_1_5,
android.R.layout.simple_spinner_item);
rotor1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor1View.setAdapter(rotor1Adapter);
ArrayAdapter<CharSequence> rotor2Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_1_5,
android.R.layout.simple_spinner_item);
rotor2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor2View.setAdapter(rotor2Adapter);
ArrayAdapter<CharSequence> rotor3Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_1_5,
android.R.layout.simple_spinner_item);
rotor3Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor3View.setAdapter(rotor3Adapter);
ArrayAdapter<CharSequence> reflectorAdapter = ArrayAdapter.createFromResource(main, R.array.reflectors_a_c,
android.R.layout.simple_spinner_item);
reflectorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
reflectorView.setAdapter(reflectorAdapter);
ArrayAdapter<Character> rotor1PositionAdapter = new ArrayAdapter<>(main.getApplicationContext(),
android.R.layout.simple_spinner_item,rotorPositionArray);
rotor1PositionAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
rotor1PositionView.setAdapter(rotor1PositionAdapter);
ArrayAdapter<Character> rotor2PositionAdapter = new ArrayAdapter<>(main.getApplicationContext(),
android.R.layout.simple_spinner_item,rotorPositionArray);
rotor2PositionAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
rotor2PositionView.setAdapter(rotor2PositionAdapter);
ArrayAdapter<Character> rotor3PositionAdapter = new ArrayAdapter<>(main.getApplicationContext(),
android.R.layout.simple_spinner_item,rotorPositionArray);
rotor3PositionAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
rotor3PositionView.setAdapter(rotor3PositionAdapter);
}
@Override
public void reset()
{
rotor1View.setSelection(0); //I
rotor2View.setSelection(1); //II
rotor3View.setSelection(2); //III
reflectorView.setSelection(0); //A
rotor1PositionView.setSelection(0); //0
rotor2PositionView.setSelection(0); //0
rotor3PositionView.setSelection(0); //0
this.ringSettings = new int[]{0,0,0};
inputView.setText("");
outputView.setText("");
plugboardView.setText("");
enigma.setConfiguration(createConfiguration());
enigma.setPlugboard(new Plugboard());
}
@Override
public void updateLayout()
{
int[] conf = enigma.getConfiguration();
rotor1View.setSelection(conf[0]-1);
rotor2View.setSelection(conf[1]-1);
rotor3View.setSelection(conf[2]-1);
reflectorView.setSelection(conf[3]-1);
rotor1PositionView.setSelection(conf[4]);
rotor2PositionView.setSelection(conf[5]);
rotor3PositionView.setSelection(conf[6]);
ringSettings[0] = conf[7];
ringSettings[1] = conf[8];
ringSettings[2] = conf[9];
}
@Override
public int[] createConfiguration()
{
int[] conf = new int[10];
//Rotors 1..3
conf[0] = rotor1View.getSelectedItemPosition() + 1;
conf[1] = rotor2View.getSelectedItemPosition() + 1;
conf[2] = rotor3View.getSelectedItemPosition() + 1;
//Reflector
conf[3] = reflectorView.getSelectedItemPosition() + 1;
conf[4] = rotor1PositionView.getSelectedItemPosition();
conf[5] = rotor2PositionView.getSelectedItemPosition();
conf[6] = rotor3PositionView.getSelectedItemPosition();
conf[7] = ringSettings[0];
conf[8] = ringSettings[1];
conf[9] = ringSettings[2];
return conf;
}
@Override
public int[][] createPlugboardConfiguration() {
return Plugboard.parseConfigurationString(plugboardView.getText().toString());
}
@Override
public void showRingSettingsDialog()
{
Integer[] ringArray = new Integer[26];
for(int i=1; i<=26; i++) {ringArray[i-1] = i;}
View ringSettingsView = View.inflate(main, R.layout.dialog_ringsettings_i_m3, null);
final Spinner ring1 = (Spinner) ringSettingsView.findViewById(R.id.rotor1ring);
ArrayAdapter<Integer> ring1Adapter = new ArrayAdapter<>(main,
android.R.layout.simple_spinner_item,ringArray);
ring1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
ring1.setAdapter(ring1Adapter);
ring1.setSelection(ringSettings[0]);
final Spinner ring2 = (Spinner) ringSettingsView.findViewById(R.id.rotor2ring);
ArrayAdapter<Integer> ring2Adapter = new ArrayAdapter<>(main,
android.R.layout.simple_spinner_item,ringArray);
ring2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
ring2.setAdapter(ring2Adapter);
ring2.setSelection(ringSettings[1]);
final Spinner ring3 = (Spinner) ringSettingsView.findViewById(R.id.rotor3ring);
ArrayAdapter<Integer> ring3Adapter = new ArrayAdapter<>(main,
android.R.layout.simple_spinner_item,ringArray);
ring3Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
ring3.setAdapter(ring3Adapter);
ring3.setSelection(ringSettings[2]);
AlertDialog.Builder builder = new AlertDialog.Builder(main);
builder.setTitle(R.string.title_ringsetting);
builder.setView(ringSettingsView)
.setCancelable(true)
.setPositiveButton(R.string.dialog_positiv, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
ringSettings[0] = ring1.getSelectedItemPosition();
ringSettings[1] = ring2.getSelectedItemPosition();
ringSettings[2] = ring3.getSelectedItemPosition();
String message = main.getResources().getString(
R.string.dialog_ringsettings_success) + " " +
(ringSettings[2]+1) + ", " +
(ringSettings[1]+1) + ", " +
(ringSettings[0]+1) + ".";
Toast.makeText(main, message, Toast.LENGTH_LONG).show();
}
})
.setNegativeButton(R.string.dialog_negativ, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
Toast.makeText(main, R.string.dialog_ringsettings_abort,
Toast.LENGTH_SHORT).show();
}
}).show();
}
}

View file

@ -0,0 +1,115 @@
package de.vanitasvitae.enigmandroid.layout;
import android.widget.ArrayAdapter;
import de.vanitasvitae.enigmandroid.R;
import de.vanitasvitae.enigmandroid.enigma.Enigma_M3;
/**
* Concrete LayoutContainer for the M3 layout.
* This class contains the layout and controls the layout elements such as spinners and stuff
* Copyright (C) 2015 Paul Schaub
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* @author vanitasvitae
*/
public class LayoutContainer_M3 extends LayoutContainer_I
{
public LayoutContainer_M3()
{
super();
main.setTitle("M3 - EnigmAndroid");
this.enigma = new Enigma_M3();
}
@Override
void initialize()
{
Character[] rotorPositionArray = new Character[26];
for(int i=0; i<26; i++) {rotorPositionArray[i] = (char) (65+i); /**Fill with A..Z*/}
ArrayAdapter<CharSequence> rotor1Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_1_8,
android.R.layout.simple_spinner_item);
rotor1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor1View.setAdapter(rotor1Adapter);
ArrayAdapter<CharSequence> rotor2Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_1_8,
android.R.layout.simple_spinner_item);
rotor2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor2View.setAdapter(rotor2Adapter);
ArrayAdapter<CharSequence> rotor3Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_1_8,
android.R.layout.simple_spinner_item);
rotor3Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor3View.setAdapter(rotor3Adapter);
ArrayAdapter<CharSequence> reflectorAdapter = ArrayAdapter.createFromResource(main, R.array.reflectors_b_c,
android.R.layout.simple_spinner_item);
reflectorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
reflectorView.setAdapter(reflectorAdapter);
ArrayAdapter<Character> rotor1PositionAdapter = new ArrayAdapter<>(main.getApplicationContext(),
android.R.layout.simple_spinner_item,rotorPositionArray);
rotor1PositionAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
rotor1PositionView.setAdapter(rotor1PositionAdapter);
ArrayAdapter<Character> rotor2PositionAdapter = new ArrayAdapter<>(main.getApplicationContext(),
android.R.layout.simple_spinner_item,rotorPositionArray);
rotor2PositionAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
rotor2PositionView.setAdapter(rotor2PositionAdapter);
ArrayAdapter<Character> rotor3PositionAdapter = new ArrayAdapter<>(main.getApplicationContext(),
android.R.layout.simple_spinner_item,rotorPositionArray);
rotor3PositionAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
rotor3PositionView.setAdapter(rotor3PositionAdapter);
}
@Override
public void updateLayout()
{
int[] conf = enigma.getConfiguration();
rotor1View.setSelection(conf[0]-1);
rotor2View.setSelection(conf[1]-1);
rotor3View.setSelection(conf[2]-1);
reflectorView.setSelection(conf[3]-2); //B=2 -> 0
rotor1PositionView.setSelection(conf[4]);
rotor2PositionView.setSelection(conf[5]);
rotor3PositionView.setSelection(conf[6]);
ringSettings[0] = conf[7];
ringSettings[1] = conf[8];
ringSettings[2] = conf[9];
}
@Override
public int[] createConfiguration()
{
int[] conf = new int[10];
//Rotors 1..3
conf[0] = rotor1View.getSelectedItemPosition() + 1;
conf[1] = rotor2View.getSelectedItemPosition() + 1;
conf[2] = rotor3View.getSelectedItemPosition() + 1;
//Reflector
conf[3] = reflectorView.getSelectedItemPosition() + 2; //M3 has no B
conf[4] = rotor1PositionView.getSelectedItemPosition();
conf[5] = rotor2PositionView.getSelectedItemPosition();
conf[6] = rotor3PositionView.getSelectedItemPosition();
conf[7] = ringSettings[0];
conf[8] = ringSettings[1];
conf[9] = ringSettings[2];
return conf;
}
}

View file

@ -0,0 +1,254 @@
package de.vanitasvitae.enigmandroid.layout;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import de.vanitasvitae.enigmandroid.R;
import de.vanitasvitae.enigmandroid.enigma.Enigma_M4;
import de.vanitasvitae.enigmandroid.enigma.Plugboard;
/**
* Concrete LayoutContainer for the M4 layout.
* This class contains the layout and controls the layout elements such as spinners and stuff
* Copyright (C) 2015 Paul Schaub
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* @author vanitasvitae
*/
public class LayoutContainer_M4 extends LayoutContainer
{
private Spinner rotor1View;
private Spinner rotor2View;
private Spinner rotor3View;
private Spinner rotor4View;
private Spinner reflectorView;
private Spinner rotor1PositionView;
private Spinner rotor2PositionView;
private Spinner rotor3PositionView;
private Spinner rotor4PositionView;
private EditText plugboardView;
public LayoutContainer_M4()
{
super();
main.setTitle("M4 - EnigmAndroid");
this.enigma = new Enigma_M4();
this.ringSettings = new int[]{0,0,0,0};
this.rotor1View = (Spinner) main.findViewById(R.id.rotor1);
this.rotor2View = (Spinner) main.findViewById(R.id.rotor2);
this.rotor3View = (Spinner) main.findViewById(R.id.rotor3);
this.rotor4View = (Spinner) main.findViewById(R.id.thin_rotor);
this.reflectorView = (Spinner) main.findViewById(R.id.reflector);
this.rotor1PositionView = (Spinner) main.findViewById(R.id.rotor1position);
this.rotor2PositionView = (Spinner) main.findViewById(R.id.rotor2position);
this.rotor3PositionView = (Spinner) main.findViewById(R.id.rotor3position);
this.rotor4PositionView = (Spinner) main.findViewById(R.id.thin_rotor_position);
this.plugboardView = (EditText) main.findViewById(R.id.plugboard);
this.inputView = (EditText) main.findViewById(R.id.input);
this.outputView = (EditText) main.findViewById(R.id.output);
initialize();
reset();
}
@Override
void initialize()
{
Character[] rotorPositionArray = new Character[26];
for(int i=0; i<26; i++) {rotorPositionArray[i] = (char) (65+i); /**Fill with A..Z*/}
ArrayAdapter<CharSequence> rotor1Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_1_8,
android.R.layout.simple_spinner_item);
rotor1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor1View.setAdapter(rotor1Adapter);
ArrayAdapter<CharSequence> rotor2Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_1_8,
android.R.layout.simple_spinner_item);
rotor2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor2View.setAdapter(rotor2Adapter);
ArrayAdapter<CharSequence> rotor3Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_1_8,
android.R.layout.simple_spinner_item);
rotor3Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor3View.setAdapter(rotor3Adapter);
ArrayAdapter<CharSequence> rotor4Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_beta_gamma,
android.R.layout.simple_spinner_item);
rotor4Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
rotor4View.setAdapter(rotor4Adapter);
ArrayAdapter<CharSequence> reflectorAdapter = ArrayAdapter.createFromResource(main, R.array.reflectors_b_c,
android.R.layout.simple_spinner_item);
reflectorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
reflectorView.setAdapter(reflectorAdapter);
ArrayAdapter<Character> rotor1PositionAdapter = new ArrayAdapter<>(main.getApplicationContext(),
android.R.layout.simple_spinner_item,rotorPositionArray);
rotor1PositionAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
rotor1PositionView.setAdapter(rotor1PositionAdapter);
ArrayAdapter<Character> rotor2PositionAdapter = new ArrayAdapter<>(main.getApplicationContext(),
android.R.layout.simple_spinner_item,rotorPositionArray);
rotor2PositionAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
rotor2PositionView.setAdapter(rotor2PositionAdapter);
ArrayAdapter<Character> rotor3PositionAdapter = new ArrayAdapter<>(main.getApplicationContext(),
android.R.layout.simple_spinner_item,rotorPositionArray);
rotor3PositionAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
rotor3PositionView.setAdapter(rotor3PositionAdapter);
ArrayAdapter<Character> rotor4PositionAdapter = new ArrayAdapter<>(main.getApplicationContext(),
android.R.layout.simple_spinner_item,rotorPositionArray);
rotor4PositionAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
rotor4PositionView.setAdapter(rotor4PositionAdapter);
}
@Override
public void reset()
{
rotor1View.setSelection(0); //I
rotor2View.setSelection(1); //II
rotor3View.setSelection(2); //III
rotor4View.setSelection(0); //Beta
reflectorView.setSelection(0); //B
rotor1PositionView.setSelection(0); //0
rotor2PositionView.setSelection(0); //0
rotor3PositionView.setSelection(0); //0
rotor4PositionView.setSelection(0); //0
ringSettings = new int[]{0,0,0,0};
inputView.setText("");
outputView.setText("");
plugboardView.setText("");
enigma.setConfiguration(createConfiguration());
enigma.setPlugboard(new Plugboard());
}
@Override
public void updateLayout()
{
int[] conf = enigma.getConfiguration();
rotor1View.setSelection(conf[0]-1);
rotor2View.setSelection(conf[1]-1);
rotor3View.setSelection(conf[2]-1);
rotor4View.setSelection(conf[3]-9);
reflectorView.setSelection(conf[4]-4);
rotor1PositionView.setSelection(conf[5]);
rotor2PositionView.setSelection(conf[6]);
rotor3PositionView.setSelection(conf[7]);
rotor4PositionView.setSelection(conf[8]);
ringSettings[0] = conf[9];
ringSettings[1] = conf[10];
ringSettings[2] = conf[11];
ringSettings[3] = conf[12];
}
@Override
public int[] createConfiguration()
{
int[] conf = new int[13];
//Rotors 1..4
conf[0] = rotor1View.getSelectedItemPosition() + 1;
conf[1] = rotor2View.getSelectedItemPosition() + 1;
conf[2] = rotor3View.getSelectedItemPosition() + 1;
conf[3] = rotor4View.getSelectedItemPosition() + 9; //Beta is rotor #9
//Reflector
conf[4] = reflectorView.getSelectedItemPosition() + 4; //thinB is reflector #4
conf[5] = rotor1PositionView.getSelectedItemPosition();
conf[6] = rotor2PositionView.getSelectedItemPosition();
conf[7] = rotor3PositionView.getSelectedItemPosition();
conf[8] = rotor4PositionView.getSelectedItemPosition();
conf[9] = ringSettings[0];
conf[10] = ringSettings[1];
conf[11] = ringSettings[2];
conf[12] = ringSettings[3];
return conf;
}
@Override
public int[][] createPlugboardConfiguration() {
return Plugboard.parseConfigurationString(plugboardView.getText().toString());
}
@Override
public void showRingSettingsDialog()
{
Integer[] ringArray = new Integer[26];
for(int i=1; i<=26; i++) {ringArray[i-1] = i;}
View ringSettingsView = View.inflate(main, R.layout.dialog_ringsettings_m4, null);
final Spinner ring1 = (Spinner) ringSettingsView.findViewById(R.id.rotor1ring);
ArrayAdapter<Integer> ring1Adapter = new ArrayAdapter<>(main,
android.R.layout.simple_spinner_item,ringArray);
ring1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
ring1.setAdapter(ring1Adapter);
ring1.setSelection(ringSettings[0]);
final Spinner ring2 = (Spinner) ringSettingsView.findViewById(R.id.rotor2ring);
ArrayAdapter<Integer> ring2Adapter = new ArrayAdapter<>(main,
android.R.layout.simple_spinner_item,ringArray);
ring2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
ring2.setAdapter(ring2Adapter);
ring2.setSelection(ringSettings[1]);
final Spinner ring3 = (Spinner) ringSettingsView.findViewById(R.id.rotor3ring);
ArrayAdapter<Integer> ring3Adapter = new ArrayAdapter<>(main,
android.R.layout.simple_spinner_item,ringArray);
ring3Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
ring3.setAdapter(ring3Adapter);
ring3.setSelection(ringSettings[2]);
final Spinner ring4 = (Spinner) ringSettingsView.findViewById(R.id.rotor4ring);
ArrayAdapter<Integer> ring4Adapter = new ArrayAdapter<>(main,
android.R.layout.simple_spinner_item, ringArray);
ring4Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
ring4.setAdapter(ring4Adapter);
ring4.setSelection(ringSettings[3]);
AlertDialog.Builder builder = new AlertDialog.Builder(main);
builder.setTitle(R.string.title_ringsetting);
builder.setView(ringSettingsView)
.setCancelable(true)
.setPositiveButton(R.string.dialog_positiv, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
ringSettings[0] = ring1.getSelectedItemPosition();
ringSettings[1] = ring2.getSelectedItemPosition();
ringSettings[2] = ring3.getSelectedItemPosition();
ringSettings[3] = ring4.getSelectedItemPosition();
String message = main.getResources().getString(
R.string.dialog_ringsettings_success) + " " +
(ringSettings[3]+1) + ", " +
(ringSettings[2]+1) + ", " +
(ringSettings[1]+1) + ", " +
(ringSettings[0]+1) + ".";
Toast.makeText(main, message, Toast.LENGTH_LONG).show();
}
})
.setNegativeButton(R.string.dialog_negativ, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
Toast.makeText(main, R.string.dialog_ringsettings_abort,
Toast.LENGTH_SHORT).show();
}
}).show();
}
}

View file

@ -0,0 +1,202 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<!-- Hints of the spinners-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/lin_lay_names_1">
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/hint_reflector"/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/hint_thin_rotor"/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/hint_rotor3"/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/hint_rotor2"/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/hint_rotor1"/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/hint_thin_rotor_position"/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/hint_rotor3_position"/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/hint_rotor2_position"/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/hint_rotor1_position"/>
</LinearLayout>
<!-- Spinners -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/lin_lay_1"
android:layout_below="@+id/lin_lay_names_1">
<Spinner
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:id="@+id/reflector">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:id="@+id/thin_rotor"/>
<Spinner
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:id="@+id/rotor3">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:id="@+id/rotor2">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:id="@+id/rotor1">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:id="@+id/thin_rotor_position">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:id="@+id/rotor3position">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:id="@+id/rotor2position">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:id="@+id/rotor1position">
</Spinner>
</LinearLayout>
<!-- Plugboard and button-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/buttons_lay"
android:layout_below="@+id/lin_lay_1"
android:orientation="horizontal">
<EditText
android:layout_width="0dp"
android:layout_weight="75"
android:layout_height="match_parent"
android:id="@+id/plugboard"
android:hint="@string/hint_enigma_plugboard">
</EditText>
<Button
android:layout_width="0dp"
android:layout_weight="25"
android:layout_height="wrap_content"
android:id="@+id/button_crypt"
android:onClick="doCrypto"
android:text="@string/button_crypt"
android:background="@drawable/button"/>
</LinearLayout>
<!-- Textboxes for input and output -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/buttons_lay"
android:layout_alignParentBottom="true"
android:id="@+id/text_layer">
<EditText
android:layout_width="0dp"
android:layout_weight=".50"
android:layout_height="match_parent"
android:id="@+id/input"
android:hint="@string/hint_enigma_type_here" />
<EditText
android:layout_width="0dp"
android:layout_weight=".50"
android:layout_height="match_parent"
android:inputType="none"
android:textIsSelectable="true"
android:id="@+id/output"
android:hint="@string/hint_enigma_code"/>
</LinearLayout>
</RelativeLayout>

View file

@ -159,7 +159,7 @@
android:layout_weight=".50" android:layout_weight=".50"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/input" android:id="@+id/input"
android:inputType="textNoSuggestions" android:inputType="textNoSuggestions|textMultiLine"
android:hint="@string/hint_enigma_type_here" /> android:hint="@string/hint_enigma_type_here" />
<EditText <EditText

View file

@ -0,0 +1,196 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/lin_lay_names_1">
<TextView
android:layout_width="0dp"
android:layout_weight=".20"
android:layout_height="wrap_content"
android:text="@string/hint_reflector"/>
<TextView
android:layout_width="0dp"
android:layout_weight=".20"
android:layout_height="wrap_content"
android:text="@string/hint_thin_rotor"/>
<TextView
android:layout_width="0dp"
android:layout_weight=".20"
android:layout_height="wrap_content"
android:text="@string/hint_rotor3"/>
<TextView
android:layout_width="0dp"
android:layout_weight=".20"
android:layout_height="wrap_content"
android:text="@string/hint_rotor2"/>
<TextView
android:layout_width="0dp"
android:layout_weight=".20"
android:layout_height="wrap_content"
android:text="@string/hint_rotor1"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/lin_lay_1"
android:layout_below="@+id/lin_lay_names_1">
<Spinner
android:layout_width="0dp"
android:layout_weight=".20"
android:layout_height="wrap_content"
android:id="@+id/reflector">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight=".20"
android:layout_height="wrap_content"
android:id="@+id/thin_rotor">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight=".20"
android:layout_height="wrap_content"
android:id="@+id/rotor3">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight=".20"
android:layout_height="wrap_content"
android:id="@+id/rotor2">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight=".20"
android:layout_height="wrap_content"
android:id="@+id/rotor1">
</Spinner>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_below="@+id/lin_lay_1"
android:id="@+id/lin_lay_names_2">
<TextView
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:text="@string/hint_thin_rotor_position"/>
<TextView
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:text="@string/hint_rotor3_position"/>
<TextView
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:text="@string/hint_rotor2_position"/>
<TextView
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:text="@string/hint_rotor1_position"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/lin_lay_2"
android:layout_below="@+id/lin_lay_names_2">
<Spinner
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:id="@+id/thin_rotor_position">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:id="@+id/rotor3position">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:id="@+id/rotor2position">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:id="@+id/rotor1position">
</Spinner>
</LinearLayout>
<EditText
android:layout_width="match_parent"
android:layout_height="30pt"
android:id="@+id/plugboard"
android:inputType="textNoSuggestions"
android:hint="@string/hint_enigma_plugboard"
android:layout_below="@+id/lin_lay_2"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/plugboard"
android:layout_above="@+id/buttons_lay"
android:id="@+id/text_layer">
<EditText
android:layout_width="0dp"
android:layout_weight=".50"
android:layout_height="match_parent"
android:id="@+id/input"
android:inputType="textNoSuggestions|textMultiLine"
android:hint="@string/hint_enigma_type_here" />
<EditText
android:layout_width="0dp"
android:layout_weight=".50"
android:layout_height="match_parent"
android:inputType="none"
android:textIsSelectable="true"
android:id="@+id/output"
android:hint="@string/hint_enigma_code"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/buttons_lay"
android:layout_alignParentBottom="true">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/button_crypt"
android:onClick="doCrypto"
android:text="@string/button_crypt"
android:background="@drawable/button"
/>
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,67 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="5dp"
android:paddingEnd="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/ringsettings_layout_hint">
<TextView
android:layout_width="0dp"
android:layout_weight="25"
android:text="@string/hint_thin_rotor"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="0dp"
android:layout_weight="25"
android:text="@string/hint_rotor3"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="0dp"
android:layout_weight="25"
android:text="@string/hint_rotor2"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="0dp"
android:layout_weight="25"
android:text="@string/hint_rotor1"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ringsettings_layout_hint"
android:id="@+id/ringsettings_layout">
<Spinner
android:layout_width="0dp"
android:layout_weight="25"
android:layout_height="wrap_content"
android:id="@+id/rotor4ring">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight="25"
android:layout_height="wrap_content"
android:id="@+id/rotor3ring">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight="25"
android:layout_height="wrap_content"
android:id="@+id/rotor2ring">
</Spinner>
<Spinner
android:layout_width="0dp"
android:layout_weight="25"
android:layout_height="wrap_content"
android:id="@+id/rotor1ring">
</Spinner>
</LinearLayout>
</RelativeLayout>

View file

@ -11,14 +11,16 @@
<string name="message_choose_ringsettings">Wähle die Ringstellungen für die Walzen:</string> <string name="message_choose_ringsettings">Wähle die Ringstellungen für die Walzen:</string>
<string name="hint_enigma_type_here">Hier Tippen</string> <string name="hint_enigma_type_here">Hier Tippen</string>
<string name="hint_enigma_code">Enigma-Code</string> <string name="hint_enigma_code">Enigma-Code</string>
<string name="hint_enigma_plugboard">Steckerbrett (AZ,BE...)</string> <string name="hint_enigma_plugboard">Steckerbrett (AZ,BE)</string>
<string name="hint_rotor1">Walze 1</string> <string name="hint_rotor1">Walze 1</string>
<string name="hint_rotor2">Walze 2</string> <string name="hint_rotor2">Walze 2</string>
<string name="hint_rotor3">Walze 3</string> <string name="hint_rotor3">Walze 3</string>
<string name="hint_thin_rotor">Walze 4</string>
<string name="hint_reflector">Umkehr-\nWalze</string> <string name="hint_reflector">Umkehr-\nWalze</string>
<string name="hint_rotor1_position">Position\nWalze 1</string> <string name="hint_rotor1_position">Position\nWalze 1</string>
<string name="hint_rotor2_position">Position\nWalze 2</string> <string name="hint_rotor2_position">Position\nWalze 2</string>
<string name="hint_rotor3_position">Position\nWalze 3</string> <string name="hint_rotor3_position">Position\nWalze 3</string>
<string name="hint_thin_rotor_position">Position\nWalze 4</string>
<string name="button_crypt">Ver-/Entschlüsseln</string> <string name="button_crypt">Ver-/Entschlüsseln</string>
<string name="error_parsing_plugs">Fehler: Fehlerhafte Steckerbrettkonfiguration.</string> <string name="error_parsing_plugs">Fehler: Fehlerhafte Steckerbrettkonfiguration.</string>
<string name="error_unable_to_plug_a_b">Kann Stecker nicht setzen: </string> <string name="error_unable_to_plug_a_b">Kann Stecker nicht setzen: </string>
@ -31,18 +33,4 @@
<string name="dialog_ringsettings_abort">Keine Änderungen</string> <string name="dialog_ringsettings_abort">Keine Änderungen</string>
<string name="message_reset">Enigma zurückgesetzt</string> <string name="message_reset">Enigma zurückgesetzt</string>
<string-array name="enigma_rotors">
<item>I</item>
<item>II</item>
<item>III</item>
<item>IV</item>
<item>V</item>
</string-array>
<string-array name="enigma_reflectors">
<item>A</item>
<item>B</item>
<item>C</item>
</string-array>
</resources> </resources>

View file

@ -4,13 +4,24 @@
<string name="pref_header_simulation">Simulation</string> <string name="pref_header_simulation">Simulation</string>
<string name="pref_title_machine_type">Enigma Modell</string>
<string name="pref_description_machine_type">Welches Modell soll simuliert werden?</string>
<string-array translatable="false" name="pref_list_machine_type">
<item>I</item>
<item>M3</item>
<item>M4</item>
</string-array>
<string name="pref_title_simulate_anomaly">Doppelschritt Anomalie</string> <string name="pref_title_simulate_anomaly">Doppelschritt Anomalie</string>
<string name="pref_description_simulate_anomaly">Die Doppelschritt Anomalie lässt die mittlere Walze zweimal rotieren, falls sie sich vor dem Übertragspunkt befindet. <string name="pref_description_simulate_anomaly">Die Doppelschritt Anomalie lässt die mittlere Walze zweimal rotieren,
falls sie sich vor dem Übertragspunkt befindet.
</string> </string>
<string name="pref_title_numeric_spelling_language">Zahlenbuchstabiersprache</string> <string name="pref_title_numeric_spelling_language">Zahlenbuchstabiersprache</string>
<string name="pref_description_numeric_spelling_language">Sprache in der Zahlen buchstabiert werden sollen.</string> <string name="pref_description_numeric_spelling_language">Sprache in der Zahlen buchstabiert werden sollen.</string>
<string-array name="pref_list_numeric_spelling_language"> <string-array name="pref_list_numeric_spelling_language">
<item>Deutsch</item> <item>Deutsch</item>
<item>Französisch</item>
<item>Englisch</item> <item>Englisch</item>
</string-array> </string-array>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="version" translatable="false">0.1.4-15.08.2015</string> <string name="version" translatable="false">0.1.5-27.08.2015</string>
<string name="app_name">EnigmAndroid</string> <string name="app_name">EnigmAndroid</string>
<string name="action_version">Version</string> <string name="action_version">Version</string>
<string name="action_reset">Reset</string> <string name="action_reset">Reset</string>
@ -16,10 +16,12 @@
<string name="hint_rotor1">Rotor 1</string> <string name="hint_rotor1">Rotor 1</string>
<string name="hint_rotor2">Rotor 2</string> <string name="hint_rotor2">Rotor 2</string>
<string name="hint_rotor3">Rotor 3</string> <string name="hint_rotor3">Rotor 3</string>
<string name="hint_thin_rotor">Rotor 4</string>
<string name="hint_reflector">Reflector</string> <string name="hint_reflector">Reflector</string>
<string name="hint_rotor1_position">Position\nRotor 1</string> <string name="hint_rotor1_position">Position\nRotor 1</string>
<string name="hint_rotor2_position">Position\nRotor 2</string> <string name="hint_rotor2_position">Position\nRotor 2</string>
<string name="hint_rotor3_position">Position\nRotor 3</string> <string name="hint_rotor3_position">Position\nRotor 3</string>
<string name="hint_thin_rotor_position">Position\nRotor 4</string>
<string name="button_crypt">En-/Decrypt!</string> <string name="button_crypt">En-/Decrypt!</string>
<string name="error_parsing_plugs">Error: Can\'t interpret plugboard input.</string> <string name="error_parsing_plugs">Error: Can\'t interpret plugboard input.</string>
<string name="error_unable_to_plug_a_b">Unable to plug </string> <string name="error_unable_to_plug_a_b">Unable to plug </string>
@ -32,16 +34,35 @@
<string name="dialog_ringsettings_abort">No changes</string> <string name="dialog_ringsettings_abort">No changes</string>
<string name="message_reset">Enigma reset</string> <string name="message_reset">Enigma reset</string>
<string-array name="enigma_rotors"> <string-array translatable="false" name="rotors_1_5">
<item>I</item> <item>I</item>
<item>II</item> <item>II</item>
<item>III</item> <item>III</item>
<item>IV</item> <item>IV</item>
<item>V</item> <item>V</item>
</string-array> </string-array>
<string-array name="enigma_reflectors"> <string-array translatable="false" name="rotors_1_8">
<item>I</item>
<item>II</item>
<item>III</item>
<item>IV</item>
<item>V</item>
<item>VI</item>
<item>VII</item>
<item>VIII</item>
</string-array>
<string-array translatable="false" name="reflectors_a_c">
<item>A</item> <item>A</item>
<item>B</item> <item>B</item>
<item>C</item> <item>C</item>
</string-array> </string-array>
<string-array translatable="false" name="reflectors_b_c">
<item>B</item>
<item>C</item>
</string-array>
<string-array translatable="false" name="rotors_beta_gamma">
<item>\u03B2</item>
<item>\u03B3</item>
</string-array>
</resources> </resources>

View file

@ -4,18 +4,30 @@
<string name="pref_header_simulation">Simulation</string> <string name="pref_header_simulation">Simulation</string>
<string name="pref_title_machine_type">Enigma Model</string>
<string name="pref_description_machine_type">Which model do you want to simulate?</string>
<string-array translatable="false" name="pref_list_machine_type">
<item>I</item>
<item>M3</item>
<item>M4</item>
</string-array>
<string name="pref_title_simulate_anomaly">Simulate Anomaly</string> <string name="pref_title_simulate_anomaly">Simulate Anomaly</string>
<string name="pref_description_simulate_anomaly">The double step anomaly causes the middle rotor <string name="pref_description_simulate_anomaly">The double step anomaly causes the middle rotor
to rotate twice, if it is one step before its turnover point. to rotate twice, if it is one step before its turnover point.
</string> </string>
<string name="pref_title_numeric_spelling_language">Number spelling language</string> <string name="pref_title_numeric_spelling_language">Number spelling language</string>
<string name="pref_description_numeric_spelling_language">Language, in which numbers are spelled.</string> <string name="pref_description_numeric_spelling_language">Language, in which numbers are spelled.</string>
<string-array name="pref_list_numeric_spelling_language"> <string-array name="pref_list_numeric_spelling_language">
<item>German</item> <item>German</item>
<item>French</item>
<item>English</item> <item>English</item>
</string-array> </string-array>
<string-array translatable="false" name="pref_alias_numeric_spelling_language"> <string-array translatable="false" name="pref_alias_numeric_spelling_language">
<item>de</item> <item>de</item>
<item>fr</item>
<item>en</item> <item>en</item>
</string-array> </string-array>

View file

@ -2,18 +2,25 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/pref_header_simulation"> <PreferenceCategory android:title="@string/pref_header_simulation">
<CheckBoxPreference <ListPreference
android:key="prefAnomaly" android:key="prefMachineType"
android:title="@string/pref_title_simulate_anomaly" android:title="@string/pref_title_machine_type"
android:summary="@string/pref_description_simulate_anomaly" android:summary="@string/pref_description_machine_type"
android:defaultValue="true" /> android:entries="@array/pref_list_machine_type"
<ListPreference android:entryValues="@array/pref_list_machine_type"
android:key="prefNumericLanguage" android:defaultValue="Enigma I"/>
android:title="@string/pref_title_numeric_spelling_language" <CheckBoxPreference
android:summary="@string/pref_description_numeric_spelling_language" android:key="prefAnomaly"
android:entries="@array/pref_list_numeric_spelling_language" android:title="@string/pref_title_simulate_anomaly"
android:entryValues="@array/pref_alias_numeric_spelling_language" android:summary="@string/pref_description_simulate_anomaly"
android:defaultValue="de" /> android:defaultValue="true" />
<ListPreference
android:key="prefNumericLanguage"
android:title="@string/pref_title_numeric_spelling_language"
android:summary="@string/pref_description_numeric_spelling_language"
android:entries="@array/pref_list_numeric_spelling_language"
android:entryValues="@array/pref_alias_numeric_spelling_language"
android:defaultValue="de" />
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>