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
v0.1.5-not.yet.released<
*added missing licenses to class files
*Added proper documentation
*Extended input interpretation (number spelling in different languages, any unknown special
character now becomes 'X'
*Added french number spelling
*Added Enigma Models M3, M4
*Added option to select different enigma models into options menu
*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<
@ -12,6 +14,10 @@ v0.1.4-15.08.2015<
*Fixed some layout issues
*Fixed anomaly for step by step inputs
*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<
*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/dex" />
<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/jacoco" />
<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/tmp" />
</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="library" exported="" name="support-v4-22.2.1" level="project" />
<orderEntry type="library" exported="" name="support-annotations-22.2.1" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.0.0" level="project" />
<orderEntry type="library" exported="" name="support-annotations-23.0.0" level="project" />
</component>
</module>

View file

@ -1,15 +1,15 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
compileSdkVersion 23
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "de.vanitasvitae.enigmandroid"
minSdkVersion 15
targetSdkVersion 22
versionCode 10
versionName "0.1.4-15.08.2015-beta"
targetSdkVersion 23
versionCode 11
versionName "0.1.5-27.08.2015-beta"
}
buildTypes {
release {
@ -19,5 +19,5 @@ android {
dependencies {
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" >
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:label="@string/app_name" >
<intent-filter>
<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.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.ArrayAdapter;
import android.view.View;
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
* Copyright (C) 2015 Paul Schaub
@ -36,41 +39,27 @@ import android.widget.Toast;
*/
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 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;
//memory for the ringSettings
private int[] ringSettings = {0,0,0};
private boolean prefAnomaly;
private String prefNumericLanguage;
LayoutContainer layoutContainer;
protected String prefMachineType;
protected boolean prefAnomaly;
protected String prefNumericLanguage;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
this.initLayout();
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
this.prefAnomaly = sharedPreferences.getBoolean("prefAnomaly", true);
this.prefNumericLanguage = sharedPreferences.getString("prefNumericLanguage",getResources().
getStringArray(R.array.pref_alias_numeric_spelling_language)[0]);
this.resetLayout();
this.prefMachineType = sharedPreferences.getString("prefMachineType", getResources().
getStringArray(R.array.pref_list_machine_type)[0]);
ActivitySingleton singleton = ActivitySingleton.getInstance();
singleton.setActivity(this);
updateContentView();
layoutContainer = LayoutContainer.createLayoutContainer(prefMachineType);
updatePreferenceValues();
//Handle shared text
Intent intent = getIntent();
String action = intent.getAction();
@ -82,12 +71,102 @@ public class MainActivity extends Activity
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
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
public boolean onCreateOptionsMenu(Menu menu)
{
@ -104,14 +183,14 @@ public class MainActivity extends Activity
int id = item.getItemId();
if (id == R.id.action_reset)
{
this.resetLayout();
layoutContainer.reset();
Toast.makeText(getApplicationContext(), R.string.message_reset,
Toast.LENGTH_SHORT).show();
return true;
}
else if (id == R.id.action_choose_ringstellung)
{
showRingSettingsDialog();
layoutContainer.showRingSettingsDialog();
return true;
}
else if (id == R.id.action_settings)
@ -126,7 +205,7 @@ public class MainActivity extends Activity
}
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();
}
@ -134,7 +213,7 @@ public class MainActivity extends Activity
{
Intent sendIntent = new Intent();
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");
startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));
}
@ -142,36 +221,6 @@ public class MainActivity extends Activity
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
* 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)
{
if(inputView.getText().length()!=0) {
updateEnigma(null);
String m = inputView.getText().toString();
m = enigma.getInputPreparator().prepareString(m);
inputView.setText(m);
outputView.setText(enigma.encrypt(m));
updateSpinner(enigma.getConfiguration());
if(layoutContainer.getInputView().getText().length()!=0) {
layoutContainer.getEnigma().setConfiguration(layoutContainer.createConfiguration());
layoutContainer.getEnigma().setPlugboard(new Plugboard(layoutContainer.createPlugboardConfiguration()));
String m = layoutContainer.getInputView().getText().toString();
m = layoutContainer.getEnigma().getInputPreparer().prepareString(m);
layoutContainer.getInputView().setText(m);
layoutContainer.getOutputView().setText(layoutContainer.getEnigma().encrypt(m));
layoutContainer.updateLayout();
}
}
/**
* Reset all the spinners and textboxes and the ringsettings memory
*/
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
* Show a Dialog containing information about the app, license, usage, author and a link
* to the changelog
*/
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()
{
final View aboutView = View.inflate(this, R.layout.dialog_about, null);
@ -373,6 +269,12 @@ public class MainActivity extends Activity
}).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) {
super.onActivityResult(requestCode, resultCode, data);
@ -380,45 +282,63 @@ public class MainActivity extends Activity
case RESULT_SETTINGS:
{
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
this.prefAnomaly = sharedPrefs.getBoolean("prefAnomaly", true);
this.prefNumericLanguage = sharedPrefs.getString("prefNumericLanguage",getResources().
getStringArray(R.array.pref_alias_numeric_spelling_language)[0]);
;
this.setPrefMachineType(sharedPrefs.getString("prefMachineType", getResources()
.getStringArray(R.array.pref_list_machine_type)[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;
}
}
}
/**
* Open the web page with the URL url
* @param url URL of the website
*/
public void openWebPage(String url) {
Uri webpage = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, webpage);
Uri webPage = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, webPage);
if (intent.resolveActivity(getPackageManager()) != null) {
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()
{
if(instance == null) instance = new ActivitySingleton();
return instance;
}
/**
* 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.widget.Toast;
import java.util.ArrayList;
import de.vanitasvitae.enigmandroid.MainActivity;
import de.vanitasvitae.enigmandroid.R;
/**
* Plugboard of the enigma
* Copyright (C) 2015 Paul Schaub

View file

@ -1,9 +1,7 @@
package de.vanitasvitae.enigmandroid;
import java.text.Normalizer;
package de.vanitasvitae.enigmandroid.enigma.inputPreparer;
/**
* 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
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.
* @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].
* Replace special characters and spell numbers.
* Replace special characters, remove spaces and spell numbers.
* @param input String
* @return prepared String
*/
@ -46,7 +44,7 @@ public abstract class InputPreparator
output = output + replaceNumber(x);
}
//x is special symbol
else
else if (x != ' ')
{
output = output + 'X';
}
@ -62,24 +60,25 @@ public abstract class InputPreparator
public abstract String replaceNumber(char input);
/**
* Factory method that creates a specific InputPreparator
* @param language language alias that specifies the language (de,en)
* @return concrete InputPreparator
* Factory method that creates a specific InputPreparer
* @param language language alias that specifies the language (de,fr,en)
* @return concrete InputPreparer
*/
public static InputPreparator createInputPreparator(String language)
public static InputPreparer createInputPreparer(String language)
{
switch (language)
{
case "de": return new InputPreparatorGerman();
default: return new InputPreparatorEnglish();
case "de": return new InputPreparerGerman();
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
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
public String replaceNumber(char input)
@ -121,3 +120,27 @@ class InputPreparatorEnglish extends InputPreparator
}
}
}
/**
* 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.
@ -42,33 +42,6 @@ public class Reflector
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.
* @param type type of the created reflector
@ -81,9 +54,11 @@ public class Reflector
{
switch (type)
{
case 1: return createReflectorA();
case 2: return createReflectorB();
default: return createReflectorC();
case 1: return new ReflectorA();
case 2: return new ReflectorB();
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
* Used in Enigma I
* AE BJ CM DZ FL GY HX IV KW NR OQ PU ST
*/
private static class ReflectorA extends Reflector
{
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
* Used in Enigma I, M3
* AY BR CU DH EQ FS GL IP JX KN MO TZ VW
*/
private static class ReflectorB extends Reflector
{
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
* Used in Enigma I, M3
* AF BV CP DJ EI GO HY KR LZ MX NW QT SU
*/
private static class ReflectorC extends Reflector
{
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
@ -30,7 +30,7 @@ public class Rotor
protected int type;
protected Integer[] connections;
protected Integer[] reversedConnections;
protected int turnOverNotch;
protected Integer[] turnOverNotches;
protected int ringSetting;
protected int rotation;
@ -47,18 +47,18 @@ public class Rotor
* @param reversedConnections inverse wiring used to encrypt in the opposite direction
* (connections[reversedConnections[i]] = i
* 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 rotation rotation of the rotor
*/
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.type = type;
this.connections = connections;
this.reversedConnections = reversedConnections;
this.turnOverNotch = turnOverNotch;
this.turnOverNotches = turnOverNotches;
this.ringSetting = ringSetting;
this.rotation = rotation;
}
@ -66,7 +66,9 @@ public class Rotor
/**
* Factory method that creates a rotor accordingly to the type.
* 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 rotation rotation of the rotor
* @return Concrete rotor
@ -75,77 +77,28 @@ public class Rotor
{
switch (type)
{
case 1: return createRotorI(ringSetting, rotation);
case 2: return createRotorII(ringSetting, rotation);
case 3: return createRotorIII(ringSetting, rotation);
case 4: return createRotorIV(ringSetting, rotation);
default: return createRotorV(ringSetting, rotation);
case 1: return new RotorI(ringSetting, rotation);
case 2: return new RotorII(ringSetting, rotation);
case 3: return new RotorIII(ringSetting, rotation);
case 4: return new RotorIV(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
* @param ringSetting setting of the outer ring
* @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)
* Encrypt an input signal via the internal wiring in "forward" direction towards the reflector
* (using connections)
* @param input signal
* @return encrypted signal
*/
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)
{
return this.reversedConnections[normalize(input)];
return this.reversedConnections[normalize(input)];// + this.ringSetting)];
}
/**
@ -175,7 +128,7 @@ public class Rotor
*/
public int getRotation()
{
return this.rotation - this.getRingSetting();
return this.rotation;
}
/**
@ -192,7 +145,12 @@ public class Rotor
*/
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()
{
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
* @return turnOverNotch
* Returns the positions of the turnover notches in a array
* @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)
* 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
{
@ -269,12 +233,14 @@ public class Rotor
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[]{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)
* 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
{
@ -283,12 +249,14 @@ public class Rotor
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, 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)
* 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
{
@ -297,12 +265,14 @@ public class Rotor
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[]{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)
* 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
{
@ -311,12 +281,14 @@ public class Rotor
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[]{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)
* 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
{
@ -325,7 +297,117 @@ public class Rotor
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[]{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_height="match_parent"
android:id="@+id/input"
android:inputType="textNoSuggestions"
android:inputType="textNoSuggestions|textMultiLine"
android:hint="@string/hint_enigma_type_here" />
<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="hint_enigma_type_here">Hier Tippen</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_rotor2">Walze 2</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_rotor1_position">Position\nWalze 1</string>
<string name="hint_rotor2_position">Position\nWalze 2</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="error_parsing_plugs">Fehler: Fehlerhafte Steckerbrettkonfiguration.</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="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>

View file

@ -4,13 +4,24 @@
<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_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 name="pref_title_numeric_spelling_language">Zahlenbuchstabiersprache</string>
<string name="pref_description_numeric_spelling_language">Sprache in der Zahlen buchstabiert werden sollen.</string>
<string-array name="pref_list_numeric_spelling_language">
<item>Deutsch</item>
<item>Französisch</item>
<item>Englisch</item>
</string-array>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<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="action_version">Version</string>
<string name="action_reset">Reset</string>
@ -16,10 +16,12 @@
<string name="hint_rotor1">Rotor 1</string>
<string name="hint_rotor2">Rotor 2</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_rotor1_position">Position\nRotor 1</string>
<string name="hint_rotor2_position">Position\nRotor 2</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="error_parsing_plugs">Error: Can\'t interpret plugboard input.</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="message_reset">Enigma reset</string>
<string-array name="enigma_rotors">
<string-array translatable="false" name="rotors_1_5">
<item>I</item>
<item>II</item>
<item>III</item>
<item>IV</item>
<item>V</item>
</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>B</item>
<item>C</item>
</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>

View file

@ -4,18 +4,30 @@
<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_description_simulate_anomaly">The double step anomaly causes the middle rotor
to rotate twice, if it is one step before its turnover point.
</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-array name="pref_list_numeric_spelling_language">
<item>German</item>
<item>French</item>
<item>English</item>
</string-array>
<string-array translatable="false" name="pref_alias_numeric_spelling_language">
<item>de</item>
<item>fr</item>
<item>en</item>
</string-array>

View file

@ -2,6 +2,13 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/pref_header_simulation">
<ListPreference
android:key="prefMachineType"
android:title="@string/pref_title_machine_type"
android:summary="@string/pref_description_machine_type"
android:entries="@array/pref_list_machine_type"
android:entryValues="@array/pref_list_machine_type"
android:defaultValue="Enigma I"/>
<CheckBoxPreference
android:key="prefAnomaly"
android:title="@string/pref_title_simulate_anomaly"