mirror of
https://github.com/vanitasvitae/EnigmAndroid.git
synced 2024-11-22 04:12:06 +01:00
Update 0.1.5 Added Enigma Models I,M3,M4, fixed ring settings
This commit is contained in:
parent
2e405429cf
commit
9258c72daa
31 changed files with 2388 additions and 687 deletions
|
@ -1,10 +1,12 @@
|
||||||
CHANGELOG ENIGMANDROID
|
CHANGELOG ENIGMANDROID
|
||||||
|
|
||||||
v0.1.5-not.yet.released<
|
v0.1.5-not.yet.released<
|
||||||
*added missing licenses to class files
|
*Added french number spelling
|
||||||
*Added proper documentation
|
*Added Enigma Models M3, M4
|
||||||
*Extended input interpretation (number spelling in different languages, any unknown special
|
*Added option to select different enigma models into options menu
|
||||||
character now becomes 'X'
|
*Added developer class for simple rotor creation (not a feature in the app)
|
||||||
|
*Fixed broken ring settings
|
||||||
|
*Fixed false reset of ring settings when switching from/to landscape mode
|
||||||
|
|
||||||
|
|
||||||
v0.1.4-15.08.2015<
|
v0.1.4-15.08.2015<
|
||||||
|
@ -12,6 +14,10 @@ v0.1.4-15.08.2015<
|
||||||
*Fixed some layout issues
|
*Fixed some layout issues
|
||||||
*Fixed anomaly for step by step inputs
|
*Fixed anomaly for step by step inputs
|
||||||
*Added send/receive text functionality
|
*Added send/receive text functionality
|
||||||
|
*added missing licenses to class files
|
||||||
|
*Added proper documentation
|
||||||
|
*Extended input interpretation (number spelling in different languages, any unknown special
|
||||||
|
character now becomes 'X'
|
||||||
|
|
||||||
v0.1.3-14.03.2015<
|
v0.1.3-14.03.2015<
|
||||||
*Added About Dialog with ChangeLog-Button
|
*Added About Dialog with ChangeLog-Button
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.2.1/jars" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.0/jars" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
|
||||||
|
@ -87,9 +87,9 @@
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Android API 22 Platform (1)" jdkType="Android SDK" />
|
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" exported="" name="support-v4-22.2.1" level="project" />
|
<orderEntry type="library" exported="" name="support-v4-23.0.0" level="project" />
|
||||||
<orderEntry type="library" exported="" name="support-annotations-22.2.1" level="project" />
|
<orderEntry type="library" exported="" name="support-annotations-23.0.0" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
|
@ -1,15 +1,15 @@
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 22
|
compileSdkVersion 23
|
||||||
buildToolsVersion "22.0.1"
|
buildToolsVersion "22.0.1"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "de.vanitasvitae.enigmandroid"
|
applicationId "de.vanitasvitae.enigmandroid"
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 22
|
targetSdkVersion 23
|
||||||
versionCode 10
|
versionCode 11
|
||||||
versionName "0.1.4-15.08.2015-beta"
|
versionName "0.1.5-27.08.2015-beta"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
|
@ -19,5 +19,5 @@ android {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
compile 'com.android.support:support-v4:22.2.1'
|
compile 'com.android.support:support-v4:23.0.0'
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,6 +9,7 @@
|
||||||
android:theme="@style/AppTheme" >
|
android:theme="@style/AppTheme" >
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
|
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||||
android:label="@string/app_name" >
|
android:label="@string/app_name" >
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,16 +5,19 @@ import android.app.AlertDialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.view.View;
|
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.EditText;
|
import android.view.View;
|
||||||
import android.widget.Spinner;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Plugboard;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.inputPreparer.InputPreparer;
|
||||||
|
import de.vanitasvitae.enigmandroid.layout.LayoutContainer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main Android Activity of the app
|
* Main Android Activity of the app
|
||||||
* Copyright (C) 2015 Paul Schaub
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
@ -36,41 +39,27 @@ import android.widget.Toast;
|
||||||
*/
|
*/
|
||||||
public class MainActivity extends Activity
|
public class MainActivity extends Activity
|
||||||
{
|
{
|
||||||
private Spinner rotor1View;
|
|
||||||
private Spinner rotor2View;
|
|
||||||
private Spinner rotor3View;
|
|
||||||
private Spinner reflectorView;
|
|
||||||
private Spinner rotor1PositionView;
|
|
||||||
private Spinner rotor2PositionView;
|
|
||||||
private Spinner rotor3PositionView;
|
|
||||||
|
|
||||||
private EditText plugboardView;
|
|
||||||
private EditText inputView;
|
|
||||||
private EditText outputView;
|
|
||||||
|
|
||||||
private static final int RESULT_SETTINGS = 1;
|
private static final int RESULT_SETTINGS = 1;
|
||||||
private static final String URI_CHANGELOG = "https://github.com/vanitasvitae/EnigmAndroid/blob/master/CHANGELOG.txt";
|
private static final String URI_CHANGELOG =
|
||||||
|
"https://github.com/vanitasvitae/EnigmAndroid/blob/master/CHANGELOG.txt";
|
||||||
|
|
||||||
private Enigma enigma;
|
LayoutContainer layoutContainer;
|
||||||
//memory for the ringSettings
|
protected String prefMachineType;
|
||||||
private int[] ringSettings = {0,0,0};
|
protected boolean prefAnomaly;
|
||||||
private boolean prefAnomaly;
|
protected String prefNumericLanguage;
|
||||||
private String prefNumericLanguage;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState)
|
public void onCreate(Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
this.setContentView(R.layout.activity_main);
|
|
||||||
this.initLayout();
|
|
||||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
this.prefAnomaly = sharedPreferences.getBoolean("prefAnomaly", true);
|
this.prefMachineType = sharedPreferences.getString("prefMachineType", getResources().
|
||||||
this.prefNumericLanguage = sharedPreferences.getString("prefNumericLanguage",getResources().
|
getStringArray(R.array.pref_list_machine_type)[0]);
|
||||||
getStringArray(R.array.pref_alias_numeric_spelling_language)[0]);
|
|
||||||
this.resetLayout();
|
|
||||||
ActivitySingleton singleton = ActivitySingleton.getInstance();
|
ActivitySingleton singleton = ActivitySingleton.getInstance();
|
||||||
singleton.setActivity(this);
|
singleton.setActivity(this);
|
||||||
|
updateContentView();
|
||||||
|
layoutContainer = LayoutContainer.createLayoutContainer(prefMachineType);
|
||||||
|
updatePreferenceValues();
|
||||||
//Handle shared text
|
//Handle shared text
|
||||||
Intent intent = getIntent();
|
Intent intent = getIntent();
|
||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
|
@ -82,12 +71,102 @@ public class MainActivity extends Activity
|
||||||
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
|
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||||
if (sharedText != null)
|
if (sharedText != null)
|
||||||
{
|
{
|
||||||
inputView.setText(sharedText);
|
layoutContainer.getInputView().setText(sharedText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfigurationChanged(Configuration newConfig) {
|
||||||
|
super.onConfigurationChanged(newConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateContentView()
|
||||||
|
{
|
||||||
|
switch (prefMachineType)
|
||||||
|
{
|
||||||
|
case "M4":
|
||||||
|
this.setContentView(R.layout.activity_main_m4);
|
||||||
|
break;
|
||||||
|
case "M3":
|
||||||
|
this.setContentView(R.layout.activity_main_i_m3);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.setContentView(R.layout.activity_main_i_m3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePreferenceValues()
|
||||||
|
{
|
||||||
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
this.setPrefMachineType(sharedPreferences.getString("prefMachineType", getResources().
|
||||||
|
getStringArray(R.array.pref_list_machine_type)[0]));
|
||||||
|
this.setPrefAnomaly(sharedPreferences.getBoolean("prefAnomaly", true));
|
||||||
|
this.setPrefNumericLanguage(sharedPreferences.getString("prefNumericLanguage", getResources().
|
||||||
|
getStringArray(R.array.pref_alias_numeric_spelling_language)[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrefMachineType(String type)
|
||||||
|
{
|
||||||
|
if(prefMachineType == null || !prefMachineType.equals(type))
|
||||||
|
{
|
||||||
|
prefMachineType = type;
|
||||||
|
String savedInput = "";
|
||||||
|
if(layoutContainer != null)
|
||||||
|
{
|
||||||
|
savedInput = layoutContainer.getInputView().getText().toString();
|
||||||
|
}
|
||||||
|
updateContentView();
|
||||||
|
layoutContainer = LayoutContainer.createLayoutContainer(prefMachineType);
|
||||||
|
layoutContainer.getInputView().setText(savedInput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefMachineType()
|
||||||
|
{
|
||||||
|
if(prefMachineType != null) return prefMachineType;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updatePreferenceValues();
|
||||||
|
return prefMachineType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrefAnomaly(boolean anomaly)
|
||||||
|
{
|
||||||
|
if(prefAnomaly !=anomaly)
|
||||||
|
{
|
||||||
|
prefAnomaly = anomaly;
|
||||||
|
layoutContainer.getEnigma().setPrefAnomaly(anomaly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getPrefAnomaly()
|
||||||
|
{
|
||||||
|
return prefAnomaly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrefNumericLanguage(String lang)
|
||||||
|
{
|
||||||
|
if(prefNumericLanguage == null || !prefNumericLanguage.equals(lang))
|
||||||
|
{
|
||||||
|
prefNumericLanguage = lang;
|
||||||
|
layoutContainer.getEnigma().setInputPreparer(InputPreparer.createInputPreparer(lang));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefNumericLanguage()
|
||||||
|
{
|
||||||
|
if(prefNumericLanguage != null) return prefNumericLanguage;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updatePreferenceValues();
|
||||||
|
return prefNumericLanguage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu)
|
public boolean onCreateOptionsMenu(Menu menu)
|
||||||
{
|
{
|
||||||
|
@ -104,14 +183,14 @@ public class MainActivity extends Activity
|
||||||
int id = item.getItemId();
|
int id = item.getItemId();
|
||||||
if (id == R.id.action_reset)
|
if (id == R.id.action_reset)
|
||||||
{
|
{
|
||||||
this.resetLayout();
|
layoutContainer.reset();
|
||||||
Toast.makeText(getApplicationContext(), R.string.message_reset,
|
Toast.makeText(getApplicationContext(), R.string.message_reset,
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (id == R.id.action_choose_ringstellung)
|
else if (id == R.id.action_choose_ringstellung)
|
||||||
{
|
{
|
||||||
showRingSettingsDialog();
|
layoutContainer.showRingSettingsDialog();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (id == R.id.action_settings)
|
else if (id == R.id.action_settings)
|
||||||
|
@ -126,7 +205,7 @@ public class MainActivity extends Activity
|
||||||
}
|
}
|
||||||
else if (id == R.id.action_send)
|
else if (id == R.id.action_send)
|
||||||
{
|
{
|
||||||
if(outputView.getText().length() == 0)
|
if(layoutContainer.getOutputView().getText().length() == 0)
|
||||||
{
|
{
|
||||||
Toast.makeText(this, R.string.error_no_text_to_send, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.error_no_text_to_send, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
@ -134,7 +213,7 @@ public class MainActivity extends Activity
|
||||||
{
|
{
|
||||||
Intent sendIntent = new Intent();
|
Intent sendIntent = new Intent();
|
||||||
sendIntent.setAction(Intent.ACTION_SEND);
|
sendIntent.setAction(Intent.ACTION_SEND);
|
||||||
sendIntent.putExtra(Intent.EXTRA_TEXT, outputView.getText().toString());
|
sendIntent.putExtra(Intent.EXTRA_TEXT, layoutContainer.getOutputView().getText().toString());
|
||||||
sendIntent.setType("text/plain");
|
sendIntent.setType("text/plain");
|
||||||
startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));
|
startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));
|
||||||
}
|
}
|
||||||
|
@ -142,36 +221,6 @@ public class MainActivity extends Activity
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the enigma to the chosen rotors and plugboard
|
|
||||||
*
|
|
||||||
* @param v View
|
|
||||||
*/
|
|
||||||
public void updateEnigma(View v)
|
|
||||||
{
|
|
||||||
int[] conf = new int[10];
|
|
||||||
conf[0] = rotor1View.getSelectedItemPosition() + 1;
|
|
||||||
conf[1] = rotor2View.getSelectedItemPosition() + 1;
|
|
||||||
conf[2] = rotor3View.getSelectedItemPosition() + 1;
|
|
||||||
conf[3] = reflectorView.getSelectedItemPosition() + 1;
|
|
||||||
conf[4] = rotor1PositionView.getSelectedItemPosition() + 1;
|
|
||||||
conf[5] = rotor2PositionView.getSelectedItemPosition() + 1;
|
|
||||||
conf[6] = rotor3PositionView.getSelectedItemPosition() + 1;
|
|
||||||
conf[7] = ringSettings[0];
|
|
||||||
conf[8] = ringSettings[1];
|
|
||||||
conf[9] = ringSettings[2];
|
|
||||||
|
|
||||||
enigma = new Enigma();
|
|
||||||
|
|
||||||
int[][] plugboardConfiguration;
|
|
||||||
plugboardView.setText(plugboardView.getText().toString().toUpperCase());
|
|
||||||
plugboardConfiguration = Plugboard.parseConfigurationString(plugboardView.getText().toString());
|
|
||||||
enigma.setConfiguration(conf);
|
|
||||||
enigma.setPlugboard(new Plugboard(plugboardConfiguration));
|
|
||||||
enigma.setPrefAnomaly(prefAnomaly);
|
|
||||||
enigma.setInputPreparator(InputPreparator.createInputPreparator(prefNumericLanguage));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the chosen Configuration to the enigma, get the input string from the input textbox and
|
* Set the chosen Configuration to the enigma, get the input string from the input textbox and
|
||||||
* prepare it, set the input to the prepared text, encrypt the prepared input and set the
|
* prepare it, set the input to the prepared text, encrypt the prepared input and set the
|
||||||
|
@ -180,174 +229,21 @@ public class MainActivity extends Activity
|
||||||
*/
|
*/
|
||||||
public void doCrypto(View v)
|
public void doCrypto(View v)
|
||||||
{
|
{
|
||||||
if(inputView.getText().length()!=0) {
|
if(layoutContainer.getInputView().getText().length()!=0) {
|
||||||
updateEnigma(null);
|
layoutContainer.getEnigma().setConfiguration(layoutContainer.createConfiguration());
|
||||||
String m = inputView.getText().toString();
|
layoutContainer.getEnigma().setPlugboard(new Plugboard(layoutContainer.createPlugboardConfiguration()));
|
||||||
m = enigma.getInputPreparator().prepareString(m);
|
String m = layoutContainer.getInputView().getText().toString();
|
||||||
inputView.setText(m);
|
m = layoutContainer.getEnigma().getInputPreparer().prepareString(m);
|
||||||
outputView.setText(enigma.encrypt(m));
|
layoutContainer.getInputView().setText(m);
|
||||||
updateSpinner(enigma.getConfiguration());
|
layoutContainer.getOutputView().setText(layoutContainer.getEnigma().encrypt(m));
|
||||||
|
layoutContainer.updateLayout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset all the spinners and textboxes and the ringsettings memory
|
|
||||||
*/
|
|
||||||
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()
|
public void showAboutDialog()
|
||||||
{
|
{
|
||||||
final View aboutView = View.inflate(this, R.layout.dialog_about, null);
|
final View aboutView = View.inflate(this, R.layout.dialog_about, null);
|
||||||
|
@ -373,6 +269,12 @@ public class MainActivity extends Activity
|
||||||
}).show();
|
}).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle preference changes
|
||||||
|
* @param requestCode requestCode
|
||||||
|
* @param resultCode resultCode (RESULT_SETTINGS is defined at the top)
|
||||||
|
* @param data data (not important here)
|
||||||
|
*/
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
|
||||||
|
@ -380,41 +282,59 @@ public class MainActivity extends Activity
|
||||||
case RESULT_SETTINGS:
|
case RESULT_SETTINGS:
|
||||||
{
|
{
|
||||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
this.prefAnomaly = sharedPrefs.getBoolean("prefAnomaly", true);
|
this.setPrefMachineType(sharedPrefs.getString("prefMachineType", getResources()
|
||||||
this.prefNumericLanguage = sharedPrefs.getString("prefNumericLanguage",getResources().
|
.getStringArray(R.array.pref_list_machine_type)[0]));
|
||||||
getStringArray(R.array.pref_alias_numeric_spelling_language)[0]);
|
this.setPrefAnomaly(sharedPrefs.getBoolean("prefAnomaly", true));
|
||||||
;
|
this.setPrefNumericLanguage(this.prefNumericLanguage = sharedPrefs.getString("prefNumericLanguage", getResources().
|
||||||
|
getStringArray(R.array.pref_alias_numeric_spelling_language)[0]));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the web page with the URL url
|
||||||
|
* @param url URL of the website
|
||||||
|
*/
|
||||||
public void openWebPage(String url) {
|
public void openWebPage(String url) {
|
||||||
Uri webpage = Uri.parse(url);
|
Uri webPage = Uri.parse(url);
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, webpage);
|
Intent intent = new Intent(Intent.ACTION_VIEW, webPage);
|
||||||
if (intent.resolveActivity(getPackageManager()) != null) {
|
if (intent.resolveActivity(getPackageManager()) != null) {
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton that grants access to an Activity from anywhere within the app
|
||||||
|
*/
|
||||||
public static class ActivitySingleton
|
public static class ActivitySingleton
|
||||||
{
|
{
|
||||||
private static ActivitySingleton instance = null;
|
private static ActivitySingleton instance = null;
|
||||||
private Activity activity;
|
private Activity activity;
|
||||||
|
|
||||||
|
//private constructor
|
||||||
private ActivitySingleton(){}
|
private ActivitySingleton(){}
|
||||||
|
//Singleton method
|
||||||
public static ActivitySingleton getInstance()
|
public static ActivitySingleton getInstance()
|
||||||
{
|
{
|
||||||
if(instance == null) instance = new ActivitySingleton();
|
if(instance == null) instance = new ActivitySingleton();
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an Activity that the Singleton returns
|
||||||
|
* @param activity activity that's stored
|
||||||
|
*/
|
||||||
public void setActivity(Activity activity)
|
public void setActivity(Activity activity)
|
||||||
{
|
{
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the stored Activity
|
||||||
|
* @return stored Activity
|
||||||
|
*/
|
||||||
public Activity getActivity()
|
public Activity getActivity()
|
||||||
{
|
{
|
||||||
return activity;
|
return activity;
|
||||||
|
|
168
app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma.java
Executable file
168
app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma.java
Executable 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,13 @@
|
||||||
package de.vanitasvitae.enigmandroid;
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugboard of the enigma
|
* Plugboard of the enigma
|
||||||
* Copyright (C) 2015 Paul Schaub
|
* Copyright (C) 2015 Paul Schaub
|
|
@ -1,9 +1,7 @@
|
||||||
package de.vanitasvitae.enigmandroid;
|
package de.vanitasvitae.enigmandroid.enigma.inputPreparer;
|
||||||
|
|
||||||
import java.text.Normalizer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preparator class that prepares input text to only consist of [A..Z]
|
* Preparer class that prepares input text to only consist of [A..Z]
|
||||||
* Copyright (C) 2015 Paul Schaub
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -21,11 +19,11 @@ import java.text.Normalizer;
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
* @author vanitasvitae
|
* @author vanitasvitae
|
||||||
*/
|
*/
|
||||||
public abstract class InputPreparator
|
public abstract class InputPreparer
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Prepare the input String in a way that it only contains letters from [A..Z].
|
* Prepare the input String in a way that it only contains letters from [A..Z].
|
||||||
* Replace special characters and spell numbers.
|
* Replace special characters, remove spaces and spell numbers.
|
||||||
* @param input String
|
* @param input String
|
||||||
* @return prepared String
|
* @return prepared String
|
||||||
*/
|
*/
|
||||||
|
@ -46,7 +44,7 @@ public abstract class InputPreparator
|
||||||
output = output + replaceNumber(x);
|
output = output + replaceNumber(x);
|
||||||
}
|
}
|
||||||
//x is special symbol
|
//x is special symbol
|
||||||
else
|
else if (x != ' ')
|
||||||
{
|
{
|
||||||
output = output + 'X';
|
output = output + 'X';
|
||||||
}
|
}
|
||||||
|
@ -62,24 +60,25 @@ public abstract class InputPreparator
|
||||||
public abstract String replaceNumber(char input);
|
public abstract String replaceNumber(char input);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method that creates a specific InputPreparator
|
* Factory method that creates a specific InputPreparer
|
||||||
* @param language language alias that specifies the language (de,en)
|
* @param language language alias that specifies the language (de,fr,en)
|
||||||
* @return concrete InputPreparator
|
* @return concrete InputPreparer
|
||||||
*/
|
*/
|
||||||
public static InputPreparator createInputPreparator(String language)
|
public static InputPreparer createInputPreparer(String language)
|
||||||
{
|
{
|
||||||
switch (language)
|
switch (language)
|
||||||
{
|
{
|
||||||
case "de": return new InputPreparatorGerman();
|
case "de": return new InputPreparerGerman();
|
||||||
default: return new InputPreparatorEnglish();
|
case "fr": return new InputPreparerFrench();
|
||||||
|
default: return new InputPreparerEnglish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implementation of a german InputPreparator
|
* Concrete implementation of a german InputPreparer
|
||||||
*/
|
*/
|
||||||
class InputPreparatorGerman extends InputPreparator
|
class InputPreparerGerman extends InputPreparer
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public String replaceNumber(char input) {
|
public String replaceNumber(char input) {
|
||||||
|
@ -100,9 +99,9 @@ class InputPreparatorGerman extends InputPreparator
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implementation of an english InputPreparator
|
* Concrete implementation of an english InputPreparer
|
||||||
*/
|
*/
|
||||||
class InputPreparatorEnglish extends InputPreparator
|
class InputPreparerEnglish extends InputPreparer
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public String replaceNumber(char input)
|
public String replaceNumber(char input)
|
||||||
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package de.vanitasvitae.enigmandroid.rotors;
|
package de.vanitasvitae.enigmandroid.enigma.rotors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reflector of the enigma machine.
|
* Reflector of the enigma machine.
|
||||||
|
@ -42,33 +42,6 @@ public class Reflector
|
||||||
this.connections = connections;
|
this.connections = connections;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a reflector of type A
|
|
||||||
* @return ReflectorA
|
|
||||||
*/
|
|
||||||
public static Reflector createReflectorA()
|
|
||||||
{
|
|
||||||
return new ReflectorA();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a reflector of type B
|
|
||||||
* @return ReflectorB
|
|
||||||
*/
|
|
||||||
public static Reflector createReflectorB()
|
|
||||||
{
|
|
||||||
return new ReflectorB();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a reflector of type C
|
|
||||||
* @return ReflectorC
|
|
||||||
*/
|
|
||||||
public static Reflector createReflectorC()
|
|
||||||
{
|
|
||||||
return new ReflectorC();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method to create reflectors.
|
* Factory method to create reflectors.
|
||||||
* @param type type of the created reflector
|
* @param type type of the created reflector
|
||||||
|
@ -81,9 +54,11 @@ public class Reflector
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case 1: return createReflectorA();
|
case 1: return new ReflectorA();
|
||||||
case 2: return createReflectorB();
|
case 2: return new ReflectorB();
|
||||||
default: return createReflectorC();
|
case 3: return new ReflectorC();
|
||||||
|
case 4: return new ReflectorThinB();
|
||||||
|
default: return new ReflectorThinC();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +116,8 @@ public class Reflector
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implementation of ReflectorA
|
* Concrete implementation of ReflectorA
|
||||||
|
* Used in Enigma I
|
||||||
|
* AE BJ CM DZ FL GY HX IV KW NR OQ PU ST
|
||||||
*/
|
*/
|
||||||
private static class ReflectorA extends Reflector
|
private static class ReflectorA extends Reflector
|
||||||
{
|
{
|
||||||
|
@ -152,6 +129,8 @@ public class Reflector
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implementation of ReflectorB
|
* Concrete implementation of ReflectorB
|
||||||
|
* Used in Enigma I, M3
|
||||||
|
* AY BR CU DH EQ FS GL IP JX KN MO TZ VW
|
||||||
*/
|
*/
|
||||||
private static class ReflectorB extends Reflector
|
private static class ReflectorB extends Reflector
|
||||||
{
|
{
|
||||||
|
@ -163,6 +142,8 @@ public class Reflector
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implementation of ReflectorC
|
* Concrete implementation of ReflectorC
|
||||||
|
* Used in Enigma I, M3
|
||||||
|
* AF BV CP DJ EI GO HY KR LZ MX NW QT SU
|
||||||
*/
|
*/
|
||||||
private static class ReflectorC extends Reflector
|
private static class ReflectorC extends Reflector
|
||||||
{
|
{
|
||||||
|
@ -172,4 +153,34 @@ public class Reflector
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package de.vanitasvitae.enigmandroid.rotors;
|
package de.vanitasvitae.enigmandroid.enigma.rotors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotor super class and inner concrete implementations
|
* Rotor super class and inner concrete implementations
|
||||||
|
@ -30,7 +30,7 @@ public class Rotor
|
||||||
protected int type;
|
protected int type;
|
||||||
protected Integer[] connections;
|
protected Integer[] connections;
|
||||||
protected Integer[] reversedConnections;
|
protected Integer[] reversedConnections;
|
||||||
protected int turnOverNotch;
|
protected Integer[] turnOverNotches;
|
||||||
|
|
||||||
protected int ringSetting;
|
protected int ringSetting;
|
||||||
protected int rotation;
|
protected int rotation;
|
||||||
|
@ -47,18 +47,18 @@ public class Rotor
|
||||||
* @param reversedConnections inverse wiring used to encrypt in the opposite direction
|
* @param reversedConnections inverse wiring used to encrypt in the opposite direction
|
||||||
* (connections[reversedConnections[i]] = i
|
* (connections[reversedConnections[i]] = i
|
||||||
* for all i in 0..getRotorSize()-1.
|
* for all i in 0..getRotorSize()-1.
|
||||||
* @param turnOverNotch Position of the turnover notch
|
* @param turnOverNotches Position(s) of the turnover notch(es)
|
||||||
* @param ringSetting setting of the ring that holds the letters
|
* @param ringSetting setting of the ring that holds the letters
|
||||||
* @param rotation rotation of the rotor
|
* @param rotation rotation of the rotor
|
||||||
*/
|
*/
|
||||||
protected Rotor(String name, int type, Integer[] connections, Integer[] reversedConnections,
|
protected Rotor(String name, int type, Integer[] connections, Integer[] reversedConnections,
|
||||||
int turnOverNotch, int ringSetting, int rotation)
|
Integer[] turnOverNotches, int ringSetting, int rotation)
|
||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.connections = connections;
|
this.connections = connections;
|
||||||
this.reversedConnections = reversedConnections;
|
this.reversedConnections = reversedConnections;
|
||||||
this.turnOverNotch = turnOverNotch;
|
this.turnOverNotches = turnOverNotches;
|
||||||
this.ringSetting = ringSetting;
|
this.ringSetting = ringSetting;
|
||||||
this.rotation = rotation;
|
this.rotation = rotation;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,9 @@ public class Rotor
|
||||||
/**
|
/**
|
||||||
* Factory method that creates a rotor accordingly to the type.
|
* Factory method that creates a rotor accordingly to the type.
|
||||||
* Also initialize the rotor with ringSetting and rotation.
|
* Also initialize the rotor with ringSetting and rotation.
|
||||||
* @param type type indicator (1..5)
|
* @param type type indicator (1..10)
|
||||||
|
* 1..8 -> I..VIII
|
||||||
|
* 9,10 -> Beta, Gamma
|
||||||
* @param ringSetting setting of the outer ring (0..25)
|
* @param ringSetting setting of the outer ring (0..25)
|
||||||
* @param rotation rotation of the rotor
|
* @param rotation rotation of the rotor
|
||||||
* @return Concrete rotor
|
* @return Concrete rotor
|
||||||
|
@ -75,77 +77,28 @@ public class Rotor
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case 1: return createRotorI(ringSetting, rotation);
|
case 1: return new RotorI(ringSetting, rotation);
|
||||||
case 2: return createRotorII(ringSetting, rotation);
|
case 2: return new RotorII(ringSetting, rotation);
|
||||||
case 3: return createRotorIII(ringSetting, rotation);
|
case 3: return new RotorIII(ringSetting, rotation);
|
||||||
case 4: return createRotorIV(ringSetting, rotation);
|
case 4: return new RotorIV(ringSetting, rotation);
|
||||||
default: return createRotorV(ringSetting, rotation);
|
case 5: return new RotorV(ringSetting, rotation);
|
||||||
|
case 6: return new RotorVI(ringSetting, rotation);
|
||||||
|
case 7: return new RotorVII(ringSetting, rotation);
|
||||||
|
case 8: return new RotorVIII(ringSetting, rotation);
|
||||||
|
case 9: return new RotorBeta(ringSetting, rotation);
|
||||||
|
default: return new RotorGamma(ringSetting, rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create concrete Rotor of type 1 (I) initialized with ringSetting and rotation
|
* Encrypt an input signal via the internal wiring in "forward" direction towards the reflector
|
||||||
* @param ringSetting setting of the outer ring
|
* (using connections)
|
||||||
* @param rotation rotation of the rotor
|
|
||||||
* @return RotorI
|
|
||||||
*/
|
|
||||||
public static Rotor createRotorI(int ringSetting, int rotation)
|
|
||||||
{
|
|
||||||
return new RotorI(ringSetting, rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create concrete Rotor of type 2 (II) initialized with ringSetting and rotation
|
|
||||||
* @param ringSetting setting of the outer ring
|
|
||||||
* @param rotation rotation of the rotor
|
|
||||||
* @return RotorI
|
|
||||||
*/
|
|
||||||
public static Rotor createRotorII(int ringSetting, int rotation)
|
|
||||||
{
|
|
||||||
return new RotorII(ringSetting, rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create concrete Rotor of type 3 (III) initialized with ringSetting and rotation
|
|
||||||
* @param ringSetting setting of the outer ring
|
|
||||||
* @param rotation rotation of the rotor
|
|
||||||
* @return RotorI
|
|
||||||
*/
|
|
||||||
public static Rotor createRotorIII(int ringSetting, int rotation)
|
|
||||||
{
|
|
||||||
return new RotorIII(ringSetting, rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create concrete Rotor of type 4 (IV) initialized with ringSetting and rotation
|
|
||||||
* @param ringSetting setting of the outer ring
|
|
||||||
* @param rotation rotation of the rotor
|
|
||||||
* @return RotorI
|
|
||||||
*/
|
|
||||||
public static Rotor createRotorIV(int ringSetting, int rotation)
|
|
||||||
{
|
|
||||||
return new RotorIV(ringSetting, rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create concrete Rotor of type 5 (V) initialized with ringSetting and rotation
|
|
||||||
* @param ringSetting setting of the outer ring
|
|
||||||
* @param rotation rotation of the rotor
|
|
||||||
* @return RotorI
|
|
||||||
*/
|
|
||||||
public static Rotor createRotorV(int ringSetting, int rotation)
|
|
||||||
{
|
|
||||||
return new RotorV(ringSetting, rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encrypt an input signal via the internal wiring in "forward" direction (using connections)
|
|
||||||
* @param input signal
|
* @param input signal
|
||||||
* @return encrypted signal
|
* @return encrypted signal
|
||||||
*/
|
*/
|
||||||
public int encryptForward(int input)
|
public int encryptForward(int input)
|
||||||
{
|
{
|
||||||
return this.connections[normalize(input)];
|
return this.connections[normalize(input)];// - this.ringSetting)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -156,7 +109,7 @@ public class Rotor
|
||||||
*/
|
*/
|
||||||
public int encryptBackward(int input)
|
public int encryptBackward(int input)
|
||||||
{
|
{
|
||||||
return this.reversedConnections[normalize(input)];
|
return this.reversedConnections[normalize(input)];// + this.ringSetting)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -175,7 +128,7 @@ public class Rotor
|
||||||
*/
|
*/
|
||||||
public int getRotation()
|
public int getRotation()
|
||||||
{
|
{
|
||||||
return this.rotation - this.getRingSetting();
|
return this.rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -192,7 +145,12 @@ public class Rotor
|
||||||
*/
|
*/
|
||||||
public boolean isAtTurnoverPosition()
|
public boolean isAtTurnoverPosition()
|
||||||
{
|
{
|
||||||
return this.rotation == this.turnOverNotch;
|
for(int x : getTurnOverNotches())
|
||||||
|
{
|
||||||
|
//if(x == this.rotation + this.ringSetting) return true;
|
||||||
|
if(x == this.rotation) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -206,16 +164,20 @@ public class Rotor
|
||||||
*/
|
*/
|
||||||
public boolean doubleTurnAnomaly()
|
public boolean doubleTurnAnomaly()
|
||||||
{
|
{
|
||||||
return this.rotation == this.getTurnOver() - 1;
|
for(int x : getTurnOverNotches())
|
||||||
|
{
|
||||||
|
if(this.rotation == x-1) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the position of the turnover notch
|
* Returns the positions of the turnover notches in a array
|
||||||
* @return turnOverNotch
|
* @return turnOverNotches
|
||||||
*/
|
*/
|
||||||
public int getTurnOver()
|
public Integer[] getTurnOverNotches()
|
||||||
{
|
{
|
||||||
return this.turnOverNotch;
|
return this.turnOverNotches;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -261,6 +223,8 @@ public class Rotor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implementation of Rotor of type 1 (I)
|
* Concrete implementation of Rotor of type 1 (I)
|
||||||
|
* Used in Enigma I, M3, M4
|
||||||
|
* E K M F L G D Q V Z N T O W Y H X U S P A I B R C J
|
||||||
*/
|
*/
|
||||||
private static class RotorI extends Rotor
|
private static class RotorI extends Rotor
|
||||||
{
|
{
|
||||||
|
@ -269,12 +233,14 @@ public class Rotor
|
||||||
super("I", 1,
|
super("I", 1,
|
||||||
new Integer[]{4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9},
|
new Integer[]{4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9},
|
||||||
new Integer[]{20, 22, 24, 6, 0, 3, 5, 15, 21, 25, 1, 4, 2, 10, 12, 19, 7, 23, 18, 11, 17, 8, 13, 16, 14, 9},
|
new Integer[]{20, 22, 24, 6, 0, 3, 5, 15, 21, 25, 1, 4, 2, 10, 12, 19, 7, 23, 18, 11, 17, 8, 13, 16, 14, 9},
|
||||||
17, ringSetting, rotation);
|
new Integer[]{17}, ringSetting, rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implementation of Rotor of type 2 (II)
|
* Concrete implementation of Rotor of type 2 (II)
|
||||||
|
* Used in Enigma I, M3, M4
|
||||||
|
* A J D K S I R U X B L H W T M C Q G Z N P Y F V O E
|
||||||
*/
|
*/
|
||||||
private static class RotorII extends Rotor
|
private static class RotorII extends Rotor
|
||||||
{
|
{
|
||||||
|
@ -283,12 +249,14 @@ public class Rotor
|
||||||
super("II", 2,
|
super("II", 2,
|
||||||
new Integer[]{0, 9, 3, 10, 18, 8, 17, 20, 23, 1, 11, 7, 22, 19, 12, 2, 16, 6, 25, 13, 15, 24, 5, 21, 14, 4},
|
new Integer[]{0, 9, 3, 10, 18, 8, 17, 20, 23, 1, 11, 7, 22, 19, 12, 2, 16, 6, 25, 13, 15, 24, 5, 21, 14, 4},
|
||||||
new Integer[]{0, 9, 15, 2, 25, 22, 17, 11, 5, 1, 3, 10, 14, 19, 24, 20, 16, 6, 4, 13, 7, 23, 12, 8, 21, 18},
|
new Integer[]{0, 9, 15, 2, 25, 22, 17, 11, 5, 1, 3, 10, 14, 19, 24, 20, 16, 6, 4, 13, 7, 23, 12, 8, 21, 18},
|
||||||
5, ringSetting, rotation);
|
new Integer[]{5}, ringSetting, rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implementation of Rotor of type 3 (III)
|
* Concrete implementation of Rotor of type 3 (III)
|
||||||
|
* Used in Enigma I, M3, M4
|
||||||
|
* B D F H J L C P R T X V Z N Y E I W G A K M U S Q O
|
||||||
*/
|
*/
|
||||||
private static class RotorIII extends Rotor
|
private static class RotorIII extends Rotor
|
||||||
{
|
{
|
||||||
|
@ -297,12 +265,14 @@ public class Rotor
|
||||||
super("III", 3,
|
super("III", 3,
|
||||||
new Integer[]{1, 3, 5, 7, 9, 11, 2, 15, 17, 19, 23, 21, 25, 13, 24, 4, 8, 22, 6, 0, 10, 12, 20, 18, 16, 14},
|
new Integer[]{1, 3, 5, 7, 9, 11, 2, 15, 17, 19, 23, 21, 25, 13, 24, 4, 8, 22, 6, 0, 10, 12, 20, 18, 16, 14},
|
||||||
new Integer[]{19, 0, 6, 1, 15, 2, 18, 3, 16, 4, 20, 5, 21, 13, 25, 7, 24, 8, 23, 9, 22, 11, 17, 10, 14, 12},
|
new Integer[]{19, 0, 6, 1, 15, 2, 18, 3, 16, 4, 20, 5, 21, 13, 25, 7, 24, 8, 23, 9, 22, 11, 17, 10, 14, 12},
|
||||||
22, ringSetting, rotation);
|
new Integer[]{22}, ringSetting, rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implementation of Rotor of type 4 (IV)
|
* Concrete implementation of Rotor of type 4 (IV)
|
||||||
|
* Used in Enigma M3, M4
|
||||||
|
* E S O V P Z J A Y Q U I R H X L N F T G K D C M W B
|
||||||
*/
|
*/
|
||||||
private static class RotorIV extends Rotor
|
private static class RotorIV extends Rotor
|
||||||
{
|
{
|
||||||
|
@ -311,12 +281,14 @@ public class Rotor
|
||||||
super("IV", 4,
|
super("IV", 4,
|
||||||
new Integer[]{4, 18, 14, 21, 15, 25, 9, 0, 24, 16, 20, 8, 17, 7, 23, 11, 13, 5, 19, 6, 10, 3, 2, 12, 22, 1},
|
new Integer[]{4, 18, 14, 21, 15, 25, 9, 0, 24, 16, 20, 8, 17, 7, 23, 11, 13, 5, 19, 6, 10, 3, 2, 12, 22, 1},
|
||||||
new Integer[]{7, 25, 22, 21, 0, 17, 19, 13, 11, 6, 20, 15, 23, 16, 2, 4, 9, 12, 1, 18, 10, 3, 24, 14, 8, 5},
|
new Integer[]{7, 25, 22, 21, 0, 17, 19, 13, 11, 6, 20, 15, 23, 16, 2, 4, 9, 12, 1, 18, 10, 3, 24, 14, 8, 5},
|
||||||
10, ringSetting, rotation);
|
new Integer[]{10}, ringSetting, rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implementation of Rotor of type 5 (V)
|
* Concrete implementation of Rotor of type 5 (V)
|
||||||
|
* Used in Enigma M3, M4
|
||||||
|
* V Z B R G I T Y U P S D N H L X A W M J Q O F E C K
|
||||||
*/
|
*/
|
||||||
private static class RotorV extends Rotor
|
private static class RotorV extends Rotor
|
||||||
{
|
{
|
||||||
|
@ -325,7 +297,117 @@ public class Rotor
|
||||||
super("V", 5,
|
super("V", 5,
|
||||||
new Integer[]{21, 25, 1, 17, 6, 8, 19, 24, 20, 15, 18, 3, 13, 7, 11, 23, 0, 22, 12, 9, 16, 14, 5, 4, 2, 10},
|
new Integer[]{21, 25, 1, 17, 6, 8, 19, 24, 20, 15, 18, 3, 13, 7, 11, 23, 0, 22, 12, 9, 16, 14, 5, 4, 2, 10},
|
||||||
new Integer[]{16, 2, 24, 11, 23, 22, 4, 13, 5, 19, 25, 14, 18, 12, 21, 9, 20, 3, 10, 6, 8, 0, 17, 15, 7, 1},
|
new Integer[]{16, 2, 24, 11, 23, 22, 4, 13, 5, 19, 25, 14, 18, 12, 21, 9, 20, 3, 10, 6, 8, 0, 17, 15, 7, 1},
|
||||||
0, ringSetting, rotation);
|
new Integer[]{0}, ringSetting, rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of Rotor of type 6 (VI)
|
||||||
|
* Used in Enigma M3, M4
|
||||||
|
* J P G V O U M F Y Q B E N H Z R D K A S X L I C T W
|
||||||
|
*/
|
||||||
|
private static class RotorVI extends Rotor
|
||||||
|
{
|
||||||
|
public RotorVI(int ringSetting, int rotation)
|
||||||
|
{
|
||||||
|
super("VI", 6,
|
||||||
|
new Integer[]{9,15,6,21,14,20,12,5,24,16,1,4,13,7,25,17,3,10,0,18,23,11,8,2,19,22},
|
||||||
|
new Integer[]{18,10,23,16,11,7,2,13,22,0,17,21,6,12,4,1,9,15,19,24,5,3,25,20,8,14},
|
||||||
|
new Integer[]{0,13}, ringSetting, rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of Rotor of type 7 (VII)
|
||||||
|
* Used in Enigma M3, M4
|
||||||
|
* N Z J H G R C X M Y S W B O U F A I V L P E K Q D T
|
||||||
|
*/
|
||||||
|
private static class RotorVII extends Rotor
|
||||||
|
{
|
||||||
|
public RotorVII(int ringSetting, int rotation)
|
||||||
|
{
|
||||||
|
super("VII", 7,
|
||||||
|
new Integer[]{13,25,9,7,6,17,2,23,12,24,18,22,1,14,20,5,0,8,21,11,15,4,10,16,3,19},
|
||||||
|
new Integer[]{16,12,6,24,21,15,4,3,17,2,22,19,8,0,13,20,23,5,10,25,14,18,11,7,9,1},
|
||||||
|
new Integer[]{0,13}, ringSetting, rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of Rotor of type 8 (VIII)
|
||||||
|
* Used in Enigma M3, M4
|
||||||
|
* F K Q H T L X O C B J S P D Z R A M E W N I U Y G V
|
||||||
|
*/
|
||||||
|
private static class RotorVIII extends Rotor
|
||||||
|
{
|
||||||
|
public RotorVIII(int ringSetting, int rotation)
|
||||||
|
{
|
||||||
|
super("VIII", 8,
|
||||||
|
new Integer[]{5,10,16,7,19,11,23,14,2,1,9,18,15,3,25,17,0,12,4,22,13,8,20,24,6,21},
|
||||||
|
new Integer[]{16,9,8,13,18,0,24,3,21,10,1,5,17,20,7,12,2,15,11,4,22,25,19,6,23,14},
|
||||||
|
new Integer[]{0,13}, ringSetting, rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of Rotor of type beta (Griechenwalze Beta)
|
||||||
|
* Beta was used as a "thin" rotor in the M4. It was thinner than a "normal" rotor, so it
|
||||||
|
* could be used together with one of the two thin reflectors as one rotor.
|
||||||
|
* When used together with ReflectorThinB, Beta was equivalent to Reflector B (if rotation == 0)
|
||||||
|
* That way the M4 was backwards compatible to the M3
|
||||||
|
* Used in M4
|
||||||
|
*/
|
||||||
|
private static class RotorBeta extends Rotor
|
||||||
|
{
|
||||||
|
public RotorBeta(int ringSetting, int rotation)
|
||||||
|
{
|
||||||
|
super("Beta",9,
|
||||||
|
new Integer[]{11,4,24,9,21,2,13,8,23,22,15,1,16,12,3,17,19,0,10,25,6,5,20,7,14,18},
|
||||||
|
new Integer[]{17,11,5,14,1,21,20,23,7,3,18,0,13,6,24,10,12,15,25,16,22,4,9,8,2,19},
|
||||||
|
new Integer[]{}, ringSetting, rotation);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void rotate()
|
||||||
|
{
|
||||||
|
//Thin rotors are fixed in position, so they dont rotate
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doubleTurnAnomaly()
|
||||||
|
{
|
||||||
|
//Nope, no anomaly
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of Rotor of type gamma (Griechenwalze Gamma)
|
||||||
|
* Gamma was used as a "thin" rotor in the M4. It was thinner than a "normal" rotor, so it
|
||||||
|
* could be used together with one of the two thin reflectors as one rotor.
|
||||||
|
* When used together with ReflectorThinC, Gamma is equivalent to Reflector C
|
||||||
|
* (if rotation == 0). That way the M4 was backwards compatible to the M3
|
||||||
|
* Used in M4
|
||||||
|
*/
|
||||||
|
private static class RotorGamma extends Rotor
|
||||||
|
{
|
||||||
|
public RotorGamma(int ringSetting, int rotation)
|
||||||
|
{
|
||||||
|
super("Gamma",10,
|
||||||
|
new Integer[]{5,18,14,10,0,13,20,4,17,7,12,1,19,8,24,2,22,11,16,15,25,23,21,6,9,3},
|
||||||
|
new Integer[]{4,11,15,25,7,0,23,9,13,24,3,17,10,5,2,19,18,8,1,12,6,22,16,21,14,20},
|
||||||
|
new Integer[]{}, ringSetting, rotation);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void rotate()
|
||||||
|
{
|
||||||
|
//Thin rotors are fixed in position, so they don't rotate
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doubleTurnAnomaly()
|
||||||
|
{
|
||||||
|
//Thin rotors don't do such weird stuff, they're normal just like you and me.
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
202
app/src/main/res/layout-land/activity_main_m4.xml
Executable file
202
app/src/main/res/layout-land/activity_main_m4.xml
Executable 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>
|
|
@ -159,7 +159,7 @@
|
||||||
android:layout_weight=".50"
|
android:layout_weight=".50"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/input"
|
android:id="@+id/input"
|
||||||
android:inputType="textNoSuggestions"
|
android:inputType="textNoSuggestions|textMultiLine"
|
||||||
android:hint="@string/hint_enigma_type_here" />
|
android:hint="@string/hint_enigma_type_here" />
|
||||||
|
|
||||||
<EditText
|
<EditText
|
196
app/src/main/res/layout/activity_main_m4.xml
Executable file
196
app/src/main/res/layout/activity_main_m4.xml
Executable 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>
|
67
app/src/main/res/layout/dialog_ringsettings_m4.xml
Executable file
67
app/src/main/res/layout/dialog_ringsettings_m4.xml
Executable 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>
|
|
@ -11,14 +11,16 @@
|
||||||
<string name="message_choose_ringsettings">Wähle die Ringstellungen für die Walzen:</string>
|
<string name="message_choose_ringsettings">Wähle die Ringstellungen für die Walzen:</string>
|
||||||
<string name="hint_enigma_type_here">Hier Tippen</string>
|
<string name="hint_enigma_type_here">Hier Tippen</string>
|
||||||
<string name="hint_enigma_code">Enigma-Code</string>
|
<string name="hint_enigma_code">Enigma-Code</string>
|
||||||
<string name="hint_enigma_plugboard">Steckerbrett (AZ,BE...)</string>
|
<string name="hint_enigma_plugboard">Steckerbrett (AZ,BE…)</string>
|
||||||
<string name="hint_rotor1">Walze 1</string>
|
<string name="hint_rotor1">Walze 1</string>
|
||||||
<string name="hint_rotor2">Walze 2</string>
|
<string name="hint_rotor2">Walze 2</string>
|
||||||
<string name="hint_rotor3">Walze 3</string>
|
<string name="hint_rotor3">Walze 3</string>
|
||||||
|
<string name="hint_thin_rotor">Walze 4</string>
|
||||||
<string name="hint_reflector">Umkehr-\nWalze</string>
|
<string name="hint_reflector">Umkehr-\nWalze</string>
|
||||||
<string name="hint_rotor1_position">Position\nWalze 1</string>
|
<string name="hint_rotor1_position">Position\nWalze 1</string>
|
||||||
<string name="hint_rotor2_position">Position\nWalze 2</string>
|
<string name="hint_rotor2_position">Position\nWalze 2</string>
|
||||||
<string name="hint_rotor3_position">Position\nWalze 3</string>
|
<string name="hint_rotor3_position">Position\nWalze 3</string>
|
||||||
|
<string name="hint_thin_rotor_position">Position\nWalze 4</string>
|
||||||
<string name="button_crypt">Ver-/Entschlüsseln</string>
|
<string name="button_crypt">Ver-/Entschlüsseln</string>
|
||||||
<string name="error_parsing_plugs">Fehler: Fehlerhafte Steckerbrettkonfiguration.</string>
|
<string name="error_parsing_plugs">Fehler: Fehlerhafte Steckerbrettkonfiguration.</string>
|
||||||
<string name="error_unable_to_plug_a_b">Kann Stecker nicht setzen: </string>
|
<string name="error_unable_to_plug_a_b">Kann Stecker nicht setzen: </string>
|
||||||
|
@ -31,18 +33,4 @@
|
||||||
<string name="dialog_ringsettings_abort">Keine Änderungen</string>
|
<string name="dialog_ringsettings_abort">Keine Änderungen</string>
|
||||||
<string name="message_reset">Enigma zurückgesetzt</string>
|
<string name="message_reset">Enigma zurückgesetzt</string>
|
||||||
|
|
||||||
<string-array name="enigma_rotors">
|
|
||||||
<item>I</item>
|
|
||||||
<item>II</item>
|
|
||||||
<item>III</item>
|
|
||||||
<item>IV</item>
|
|
||||||
<item>V</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="enigma_reflectors">
|
|
||||||
<item>A</item>
|
|
||||||
<item>B</item>
|
|
||||||
<item>C</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -4,13 +4,24 @@
|
||||||
|
|
||||||
<string name="pref_header_simulation">Simulation</string>
|
<string name="pref_header_simulation">Simulation</string>
|
||||||
|
|
||||||
|
<string name="pref_title_machine_type">Enigma Modell</string>
|
||||||
|
<string name="pref_description_machine_type">Welches Modell soll simuliert werden?</string>
|
||||||
|
<string-array translatable="false" name="pref_list_machine_type">
|
||||||
|
<item>I</item>
|
||||||
|
<item>M3</item>
|
||||||
|
<item>M4</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string name="pref_title_simulate_anomaly">Doppelschritt Anomalie</string>
|
<string name="pref_title_simulate_anomaly">Doppelschritt Anomalie</string>
|
||||||
<string name="pref_description_simulate_anomaly">Die Doppelschritt Anomalie lässt die mittlere Walze zweimal rotieren, falls sie sich vor dem Übertragspunkt befindet.
|
<string name="pref_description_simulate_anomaly">Die Doppelschritt Anomalie lässt die mittlere Walze zweimal rotieren,
|
||||||
|
falls sie sich vor dem Übertragspunkt befindet.
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
<string name="pref_title_numeric_spelling_language">Zahlenbuchstabiersprache</string>
|
<string name="pref_title_numeric_spelling_language">Zahlenbuchstabiersprache</string>
|
||||||
<string name="pref_description_numeric_spelling_language">Sprache in der Zahlen buchstabiert werden sollen.</string>
|
<string name="pref_description_numeric_spelling_language">Sprache in der Zahlen buchstabiert werden sollen.</string>
|
||||||
<string-array name="pref_list_numeric_spelling_language">
|
<string-array name="pref_list_numeric_spelling_language">
|
||||||
<item>Deutsch</item>
|
<item>Deutsch</item>
|
||||||
|
<item>Französisch</item>
|
||||||
<item>Englisch</item>
|
<item>Englisch</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<string name="version" translatable="false">0.1.4-15.08.2015</string>
|
<string name="version" translatable="false">0.1.5-27.08.2015</string>
|
||||||
<string name="app_name">EnigmAndroid</string>
|
<string name="app_name">EnigmAndroid</string>
|
||||||
<string name="action_version">Version</string>
|
<string name="action_version">Version</string>
|
||||||
<string name="action_reset">Reset</string>
|
<string name="action_reset">Reset</string>
|
||||||
|
@ -16,10 +16,12 @@
|
||||||
<string name="hint_rotor1">Rotor 1</string>
|
<string name="hint_rotor1">Rotor 1</string>
|
||||||
<string name="hint_rotor2">Rotor 2</string>
|
<string name="hint_rotor2">Rotor 2</string>
|
||||||
<string name="hint_rotor3">Rotor 3</string>
|
<string name="hint_rotor3">Rotor 3</string>
|
||||||
|
<string name="hint_thin_rotor">Rotor 4</string>
|
||||||
<string name="hint_reflector">Reflector</string>
|
<string name="hint_reflector">Reflector</string>
|
||||||
<string name="hint_rotor1_position">Position\nRotor 1</string>
|
<string name="hint_rotor1_position">Position\nRotor 1</string>
|
||||||
<string name="hint_rotor2_position">Position\nRotor 2</string>
|
<string name="hint_rotor2_position">Position\nRotor 2</string>
|
||||||
<string name="hint_rotor3_position">Position\nRotor 3</string>
|
<string name="hint_rotor3_position">Position\nRotor 3</string>
|
||||||
|
<string name="hint_thin_rotor_position">Position\nRotor 4</string>
|
||||||
<string name="button_crypt">En-/Decrypt!</string>
|
<string name="button_crypt">En-/Decrypt!</string>
|
||||||
<string name="error_parsing_plugs">Error: Can\'t interpret plugboard input.</string>
|
<string name="error_parsing_plugs">Error: Can\'t interpret plugboard input.</string>
|
||||||
<string name="error_unable_to_plug_a_b">Unable to plug </string>
|
<string name="error_unable_to_plug_a_b">Unable to plug </string>
|
||||||
|
@ -32,16 +34,35 @@
|
||||||
<string name="dialog_ringsettings_abort">No changes</string>
|
<string name="dialog_ringsettings_abort">No changes</string>
|
||||||
<string name="message_reset">Enigma reset</string>
|
<string name="message_reset">Enigma reset</string>
|
||||||
|
|
||||||
<string-array name="enigma_rotors">
|
<string-array translatable="false" name="rotors_1_5">
|
||||||
<item>I</item>
|
<item>I</item>
|
||||||
<item>II</item>
|
<item>II</item>
|
||||||
<item>III</item>
|
<item>III</item>
|
||||||
<item>IV</item>
|
<item>IV</item>
|
||||||
<item>V</item>
|
<item>V</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="enigma_reflectors">
|
<string-array translatable="false" name="rotors_1_8">
|
||||||
|
<item>I</item>
|
||||||
|
<item>II</item>
|
||||||
|
<item>III</item>
|
||||||
|
<item>IV</item>
|
||||||
|
<item>V</item>
|
||||||
|
<item>VI</item>
|
||||||
|
<item>VII</item>
|
||||||
|
<item>VIII</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array translatable="false" name="reflectors_a_c">
|
||||||
<item>A</item>
|
<item>A</item>
|
||||||
<item>B</item>
|
<item>B</item>
|
||||||
<item>C</item>
|
<item>C</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string-array translatable="false" name="reflectors_b_c">
|
||||||
|
<item>B</item>
|
||||||
|
<item>C</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array translatable="false" name="rotors_beta_gamma">
|
||||||
|
<item>\u03B2</item>
|
||||||
|
<item>\u03B3</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -4,18 +4,30 @@
|
||||||
|
|
||||||
<string name="pref_header_simulation">Simulation</string>
|
<string name="pref_header_simulation">Simulation</string>
|
||||||
|
|
||||||
|
<string name="pref_title_machine_type">Enigma Model</string>
|
||||||
|
<string name="pref_description_machine_type">Which model do you want to simulate?</string>
|
||||||
|
<string-array translatable="false" name="pref_list_machine_type">
|
||||||
|
<item>I</item>
|
||||||
|
<item>M3</item>
|
||||||
|
<item>M4</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string name="pref_title_simulate_anomaly">Simulate Anomaly</string>
|
<string name="pref_title_simulate_anomaly">Simulate Anomaly</string>
|
||||||
<string name="pref_description_simulate_anomaly">The double step anomaly causes the middle rotor
|
<string name="pref_description_simulate_anomaly">The double step anomaly causes the middle rotor
|
||||||
to rotate twice, if it is one step before its turnover point.
|
to rotate twice, if it is one step before its turnover point.
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
<string name="pref_title_numeric_spelling_language">Number spelling language</string>
|
<string name="pref_title_numeric_spelling_language">Number spelling language</string>
|
||||||
<string name="pref_description_numeric_spelling_language">Language, in which numbers are spelled.</string>
|
<string name="pref_description_numeric_spelling_language">Language, in which numbers are spelled.</string>
|
||||||
<string-array name="pref_list_numeric_spelling_language">
|
<string-array name="pref_list_numeric_spelling_language">
|
||||||
<item>German</item>
|
<item>German</item>
|
||||||
|
<item>French</item>
|
||||||
<item>English</item>
|
<item>English</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array translatable="false" name="pref_alias_numeric_spelling_language">
|
<string-array translatable="false" name="pref_alias_numeric_spelling_language">
|
||||||
<item>de</item>
|
<item>de</item>
|
||||||
|
<item>fr</item>
|
||||||
<item>en</item>
|
<item>en</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,13 @@
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/pref_header_simulation">
|
<PreferenceCategory android:title="@string/pref_header_simulation">
|
||||||
|
<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
|
<CheckBoxPreference
|
||||||
android:key="prefAnomaly"
|
android:key="prefAnomaly"
|
||||||
android:title="@string/pref_title_simulate_anomaly"
|
android:title="@string/pref_title_simulate_anomaly"
|
||||||
|
|
Loading…
Reference in a new issue