Compare commits
44 Commits
v0.1.5-27.
...
master
Author | SHA1 | Date |
---|---|---|
Paul Schaub | f45a4129ab | |
Paul Schaub | e100617f43 | |
Paul Schaub | 1dbeb7f530 | |
Paul Schaub | a31a653b2e | |
Paul Schaub | bad1850170 | |
Paul Schaub | f4cfdaaf26 | |
Paul Schaub | 2961cd4c1f | |
Paul Schaub | 6259280078 | |
Paul Schaub | eaf39dbd56 | |
Paul Schaub | 3e45620d0d | |
mimi89999 | 309deb5429 | |
Paul Schaub | c4cf30baa3 | |
Paul Schaub | d43fb4c9dd | |
Free Educational Software for Mobile Devices - Translations to Brazilian Portuguese | 7c83ae82d3 | |
Free Educational Software for Mobile Devices - Translations to Brazilian Portuguese | 04137eefab | |
vanitasvitae | 7001ea0565 | |
vanitasvitae | 8cf9eda715 | |
vanitasvitae | 85cdb31e5e | |
vanitasvitae | 6ac769df94 | |
vanitasvitae | 9417045100 | |
vanitasvitae | dae5e47b6c | |
vanitasvitae | dc5c8fdb82 | |
vanitasvitae | 1fac879035 | |
vanitasvitae | e72bd31ccd | |
vanitasvitae | 0d9dfb6b0d | |
VanitasVitae | d1d3211cca | |
VanitasVitae | 8cd2b6467b | |
VanitasVitae | 992c9a924d | |
VanitasVitae | 8bab418e2b | |
VanitasVitae | 2bc5e62265 | |
VanitasVitae | f9b7be4ea0 | |
VanitasVitae | 074b2b30c5 | |
VanitasVitae | e4a0e3ccb8 | |
VanitasVitae | 95f449d743 | |
VanitasVitae | 82e21e48ec | |
VanitasVitae | 8e49652f91 | |
VanitasVitae | 63682d6462 | |
VanitasVitae | 802b51f91d | |
VanitasVitae | 0fa6344f27 | |
VanitasVitae | 9d021aaa29 | |
VanitasVitae | 5e584acede | |
VanitasVitae | c5a0b549b7 | |
VanitasVitae | 3b71d21c71 | |
VanitasVitae | 129af285c3 |
|
@ -0,0 +1,30 @@
|
||||||
|
tmp/
|
||||||
|
*.tmp
|
||||||
|
*.bak
|
||||||
|
*.log
|
||||||
|
*~*
|
||||||
|
*.iml
|
||||||
|
out/
|
||||||
|
.idea/
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.gradle
|
||||||
|
app/build/
|
||||||
|
build/
|
||||||
|
gradle-app.setting
|
||||||
|
!gradle-wrapper.jar
|
||||||
|
*.class
|
||||||
|
.mtj.tmp/
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.ear
|
||||||
|
hs_err_pid*
|
||||||
|
*.apk
|
||||||
|
*.ap_
|
||||||
|
*.dex
|
||||||
|
bin/
|
||||||
|
gen/
|
||||||
|
local.properties
|
||||||
|
proguard/
|
||||||
|
.navigation/
|
||||||
|
gen-external-apklibs
|
|
@ -0,0 +1,99 @@
|
||||||
|
# Changelog EnigmAndroid
|
||||||
|
|
||||||
|
## v1.0.2-01.01.2019
|
||||||
|
### Changes
|
||||||
|
* Added support for fastlane metadata
|
||||||
|
* Remove What's new dialog
|
||||||
|
|
||||||
|
## v1.0.1-12.01.2018
|
||||||
|
### Changes
|
||||||
|
* Added language: Brazilian-Portuguese
|
||||||
|
|
||||||
|
## v1.0.0-05.05.2017
|
||||||
|
### Changes
|
||||||
|
* Added Enigma KD
|
||||||
|
* Added "protocol version" to QR-Code-shared configuration strings.
|
||||||
|
This breaks backwards compatibility to older versions, but I added it to enable backwards compatibility in upcoming releases.
|
||||||
|
* Configurations can now be shared to EnigmAndroid as text
|
||||||
|
* Moved preference management to SettingsActivity
|
||||||
|
* Added dialog to choose whether to share configuration via text or via QR-code
|
||||||
|
* Same for receiving
|
||||||
|
* Added TextBox to configuration-share-dialog that lets the user see and copy the
|
||||||
|
configuration string.
|
||||||
|
* Added Whats-new-Dialog
|
||||||
|
* New Icon!
|
||||||
|
* Added Script to automatically generate icons
|
||||||
|
* Reformatted code
|
||||||
|
### TODO
|
||||||
|
* Add tips on long clicks at parts
|
||||||
|
* Move KD right below K
|
||||||
|
* Add intent filters to recognize and automatically handle shared/copied configuration Strings .These are Strings starting with "EnigmAndroid/"
|
||||||
|
* Write tests to ensure correct functionality (Pull Requests welcome)
|
||||||
|
* Add multi-Enigma (select any rotor/reflector etc. Probably wont happen too soon)
|
||||||
|
|
||||||
|
## v0.1.9-09.10.2015
|
||||||
|
### Changes
|
||||||
|
* Added option to share/receive configurations via QR-Code (ZXing Barcode Scanner)
|
||||||
|
* Prevent user from setting incomplete reflector wiring
|
||||||
|
* Add option to generate configuration from passphrase
|
||||||
|
* Reworked Enigma definition (available Rotors/Reflectors/ Entrywheels
|
||||||
|
* Completely verified correct functionality of Enigma T
|
||||||
|
* Added number spelling in spanish, italian
|
||||||
|
* Added backwards compatibility to API level 10 (Gingerbread 2.3.3)
|
||||||
|
|
||||||
|
## v0.1.8-27.09.2015
|
||||||
|
### Changes
|
||||||
|
* Added Enigma G31
|
||||||
|
* Added Enigma G312
|
||||||
|
* Added Enigma G260
|
||||||
|
* Replaced Enigma K with Enigma K, K (Swiss) and K (Swiss, Airforce)
|
||||||
|
* Added Enigma R
|
||||||
|
* Changed identifiers of enigma models
|
||||||
|
* Changed landscape layout of enigma model d
|
||||||
|
* Updated the about-dialog text.
|
||||||
|
* Shortened EnigmaStateBundle
|
||||||
|
* Added different colors to the plugboard-/pluggable reflector dialog. This helps to differentiate connections.
|
||||||
|
* Reworked InputPreparer using decorator pattern and added options to customize input preparation
|
||||||
|
* Reworked Reflector-/Rotor creation/management
|
||||||
|
* Added Button to set the Enigma into a random configuration
|
||||||
|
|
||||||
|
## v0.1.7-15.09.2015
|
||||||
|
### Changes
|
||||||
|
* Added Enigma K
|
||||||
|
* Added Enigma T
|
||||||
|
* Created Plugboard-/pluggable Reflector-Setting-Dialog
|
||||||
|
|
||||||
|
## v0.1.6-10.09.2015
|
||||||
|
### Changes
|
||||||
|
* Fixed about dialog (outdated manual)
|
||||||
|
* Updated CHANGELOG (oops)
|
||||||
|
* Added Enigma D
|
||||||
|
* Added rotor names to ringSettingsDialog
|
||||||
|
* Reworked major parts of the app once again :)
|
||||||
|
* Added option to break messages up into blocks
|
||||||
|
|
||||||
|
## v0.1.5-27.08.2015
|
||||||
|
### Changes
|
||||||
|
* Added french number spelling
|
||||||
|
* Added Enigma Models M3, M4
|
||||||
|
* Added option to select different enigma models into options menu
|
||||||
|
* Added developer class for simple rotor creation (not a feature in the app)
|
||||||
|
* Fixed broken ring settings
|
||||||
|
* Fixed false reset of ring settings when switching from/to landscape mode
|
||||||
|
|
||||||
|
## v0.1.4-15.08.2015
|
||||||
|
### Changes
|
||||||
|
* Reworked the core implementation to follow some principals of Software Engineering
|
||||||
|
* Fixed some layout issues
|
||||||
|
* Fixed anomaly for step by step inputs
|
||||||
|
* Added send/receive text functionality
|
||||||
|
* added missing licenses to class files
|
||||||
|
* Added proper documentation
|
||||||
|
* Extended input interpretation (number spelling in different languages, any unknown special character now becomes 'X'
|
||||||
|
|
||||||
|
## v0.1.3-14.03.2015
|
||||||
|
### Changes
|
||||||
|
* Added About Dialog with ChangeLog-Button
|
||||||
|
* Moved Version Info into About Dialog
|
||||||
|
* Updated License Files
|
||||||
|
* Fixed Landscape Layout
|
|
@ -1,26 +0,0 @@
|
||||||
CHANGELOG ENIGMANDROID
|
|
||||||
|
|
||||||
v0.1.5-not.yet.released<
|
|
||||||
*Added french number spelling
|
|
||||||
*Added Enigma Models M3, M4
|
|
||||||
*Added option to select different enigma models into options menu
|
|
||||||
*Added developer class for simple rotor creation (not a feature in the app)
|
|
||||||
*Fixed broken ring settings
|
|
||||||
*Fixed false reset of ring settings when switching from/to landscape mode
|
|
||||||
|
|
||||||
|
|
||||||
v0.1.4-15.08.2015<
|
|
||||||
*Rewrite of the core implementation to follow some principals of Software Engineering
|
|
||||||
*Fixed some layout issues
|
|
||||||
*Fixed anomaly for step by step inputs
|
|
||||||
*Added send/receive text functionality
|
|
||||||
*added missing licenses to class files
|
|
||||||
*Added proper documentation
|
|
||||||
*Extended input interpretation (number spelling in different languages, any unknown special
|
|
||||||
character now becomes 'X'
|
|
||||||
|
|
||||||
v0.1.3-14.03.2015<
|
|
||||||
*Added About Dialog with ChangeLog-Button
|
|
||||||
*Moved Version Info into About Dialog
|
|
||||||
*Updated License Files
|
|
||||||
*Fixed Landscape Layout
|
|
|
@ -1,19 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module external.linked.project.id="EnigmAndroid" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
|
||||||
<component name="FacetManager">
|
|
||||||
<facet type="java-gradle" name="Java-Gradle">
|
|
||||||
<configuration>
|
|
||||||
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
|
|
||||||
<option name="BUILDABLE" value="false" />
|
|
||||||
</configuration>
|
|
||||||
</facet>
|
|
||||||
</component>
|
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
|
|
||||||
<exclude-output />
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
|
@ -1,280 +1,676 @@
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 2, June 1991
|
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
GNU GENERAL PUBLIC LICENSE
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
Preamble
|
Preamble
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
The GNU General Public License is a free, copyleft license for
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
software and other kinds of works.
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software--to make sure the software is free for all its users. This
|
The licenses for most software and other practical works are designed
|
||||||
General Public License applies to most of the Free Software
|
to take away your freedom to share and change the works. By contrast,
|
||||||
Foundation's software and to any other program whose authors commit to
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
share and change all versions of a program--to make sure it remains free
|
||||||
the GNU Lesser General Public License instead.) You can apply it to
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
your programs, too.
|
your programs, too.
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
When we speak of free software, we are referring to freedom, not
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
have the freedom to distribute copies of free software (and charge for
|
have the freedom to distribute copies of free software (and charge for
|
||||||
this service if you wish), that you receive source code or can get it
|
them if you wish), that you receive source code or can get it if you
|
||||||
if you want it, that you can change the software or use pieces of it
|
want it, that you can change the software or use pieces of it in new
|
||||||
in new free programs; and that you know you can do these things.
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
To protect your rights, we need to prevent others from denying you
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
These restrictions translate to certain responsibilities for you if you
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
distribute copies of the software, or if you modify it.
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
For example, if you distribute copies of such a program, whether
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
you have. You must make sure that they, too, receive or can get the
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
source code. And you must show them these terms so they know their
|
or can get the source code. And you must show them these terms so they
|
||||||
rights.
|
know their rights.
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
distribute and/or modify the software.
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
that everyone understands that there is no warranty for this free
|
that there is no warranty for this free software. For both users' and
|
||||||
software. If the software is modified by someone else and passed on, we
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
want its recipients to know that what they have is not the original, so
|
changed, so that their problems will not be attributed erroneously to
|
||||||
that any problems introduced by others will not reflect on the original
|
authors of previous versions.
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
Some devices are designed to deny users access to install or run
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
modified versions of the software inside them, although the manufacturer
|
||||||
program will individually obtain patent licenses, in effect making the
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
protecting users' freedom to change the software. The systematic
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
The precise terms and conditions for copying, distribution and
|
||||||
modification follow.
|
modification follow.
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
TERMS AND CONDITIONS
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
0. Definitions.
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
|
||||||
under the terms of this General Public License. The "Program", below,
|
|
||||||
refers to any such program or work, and a "work based on the Program"
|
|
||||||
means either the Program or any derivative work under copyright law:
|
|
||||||
that is to say, a work containing the Program or a portion of it,
|
|
||||||
either verbatim or with modifications and/or translated into another
|
|
||||||
language. (Hereinafter, translation is included without limitation in
|
|
||||||
the term "modification".) Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Program's
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
source code as you receive it, in any medium, provided that you
|
works, such as semiconductor masks.
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Program or any portion
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
of it, thus forming a work based on the Program, and copy and
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
distribute such modifications or work under the terms of Section 1
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
above, provided that you also meet all of these conditions:
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
a) You must cause the modified files to carry prominent notices
|
A "covered work" means either the unmodified Program or a work based
|
||||||
stating that you changed the files and the date of any change.
|
on the Program.
|
||||||
|
|
||||||
b) You must cause any work that you distribute or publish, that in
|
To "propagate" a work means to do anything with it that, without
|
||||||
whole or in part contains or is derived from the Program or any
|
permission, would make you directly or secondarily liable for
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
infringement under applicable copyright law, except executing it on a
|
||||||
parties under the terms of this License.
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
c) If the modified program normally reads commands interactively
|
To "convey" a work means any kind of propagation that enables other
|
||||||
when run, you must cause it, when started running for such
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
interactive use in the most ordinary way, to print or display an
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
announcement including an appropriate copyright notice and a
|
|
||||||
notice that there is no warranty (or else, saying that you provide
|
|
||||||
a warranty) and that users may redistribute the program under
|
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
identifiable sections of that work are not derived from the Program,
|
to the extent that it includes a convenient and prominently visible
|
||||||
and can be reasonably considered independent and separate works in
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
themselves, then this License, and its terms, do not apply to those
|
tells the user that there is no warranty for the work (except to the
|
||||||
sections when you distribute them as separate works. But when you
|
extent that warranties are provided), that licensees may convey the
|
||||||
distribute the same sections as part of a whole which is a work based
|
work under this License, and how to view a copy of this License. If
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
the interface presents a list of user commands or options, such as a
|
||||||
this License, whose permissions for other licensees extend to the
|
menu, a prominent item in the list meets this criterion.
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
1. Source Code.
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
The "source code" for a work means the preferred form of the work
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
for making modifications to it. "Object code" means any non-source
|
||||||
a storage or distribution medium does not bring the other work under
|
form of a work.
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may copy and distribute the Program (or a work based on it,
|
A "Standard Interface" means an interface that either is an official
|
||||||
under Section 2) in object code or executable form under the terms of
|
standard defined by a recognized standards body, or, in the case of
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
a) Accompany it with the complete corresponding machine-readable
|
The "System Libraries" of an executable work include anything, other
|
||||||
source code, which must be distributed under the terms of Sections
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
b) Accompany it with a written offer, valid for at least three
|
The "Corresponding Source" for a work in object code form means all
|
||||||
years, to give any third party, for a charge no more than your
|
the source code needed to generate, install, and (for an executable
|
||||||
cost of physically performing source distribution, a complete
|
work) run the object code and to modify the work, including scripts to
|
||||||
machine-readable copy of the corresponding source code, to be
|
control those activities. However, it does not include the work's
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
System Libraries, or general-purpose tools or generally available free
|
||||||
customarily used for software interchange; or,
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
c) Accompany it with the information you received as to the offer
|
The Corresponding Source need not include anything that users
|
||||||
to distribute corresponding source code. (This alternative is
|
can regenerate automatically from other parts of the Corresponding
|
||||||
allowed only for noncommercial distribution and only if you
|
Source.
|
||||||
received the program in object code or executable form with such
|
|
||||||
an offer, in accord with Subsection b above.)
|
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
The Corresponding Source for a work in source code form is that
|
||||||
making modifications to it. For an executable work, complete source
|
same work.
|
||||||
code means all the source code for all modules it contains, plus any
|
|
||||||
associated interface definition files, plus the scripts used to
|
|
||||||
control compilation and installation of the executable. However, as a
|
|
||||||
special exception, the source code distributed need not include
|
|
||||||
anything that is normally distributed (in either source or binary
|
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
|
||||||
operating system on which the executable runs, unless that component
|
|
||||||
itself accompanies the executable.
|
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
2. Basic Permissions.
|
||||||
access to copy from a designated place, then offering equivalent
|
|
||||||
access to copy the source code from the same place counts as
|
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
All rights granted under this License are granted for the term of
|
||||||
except as expressly provided under this License. Any attempt
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
void, and will automatically terminate your rights under this License.
|
permission to run the unmodified Program. The output from running a
|
||||||
However, parties who have received copies, or rights, from you under
|
covered work is covered by this License only if the output, given its
|
||||||
this License will not have their licenses terminated so long as such
|
content, constitutes a covered work. This License acknowledges your
|
||||||
parties remain in full compliance.
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
5. You are not required to accept this License, since you have not
|
You may make, run and propagate covered works that you do not
|
||||||
signed it. However, nothing else grants you permission to modify or
|
convey, without conditions so long as your license otherwise remains
|
||||||
distribute the Program or its derivative works. These actions are
|
in force. You may convey covered works to others for the sole purpose
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
of having them make modifications exclusively for you, or provide you
|
||||||
modifying or distributing the Program (or any work based on the
|
with facilities for running those works, provided that you comply with
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
the terms of this License in conveying all material for which you do
|
||||||
all its terms and conditions for copying, distributing or modifying
|
not control copyright. Those thus making or running the covered works
|
||||||
the Program or works based on it.
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
6. Each time you redistribute the Program (or any work based on the
|
Conveying under any other circumstances is permitted solely under
|
||||||
Program), the recipient automatically receives a license from the
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
makes it unnecessary.
|
||||||
these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
this License.
|
this License.
|
||||||
|
|
||||||
7. If, as a consequence of a court judgment or allegation of patent
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
infringement or for any other reason (not limited to patent issues),
|
patent license under the contributor's essential patent claims, to
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
excuse you from the conditions of this License. If you cannot
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
License and any other pertinent obligations, then as a consequence you
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
may not distribute the Program at all. For example, if a patent
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
license would not permit royalty-free redistribution of the Program by
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
all those who receive copies directly or indirectly through you, then
|
the Program, the only way you could satisfy both those terms and this
|
||||||
the only way you could satisfy both it and this License would be to
|
License would be to refrain entirely from conveying the Program.
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
13. Use with the GNU Affero General Public License.
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
Notwithstanding any other provision of this License, you have
|
||||||
patents or other property right claims or to contest validity of any
|
permission to link or combine any covered work with a work licensed
|
||||||
such claims; this section has the sole purpose of protecting the
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
integrity of the free software distribution system, which is
|
combined work, and to convey the resulting work. The terms of this
|
||||||
implemented by public license practices. Many people have made
|
License will continue to apply to the part which is the covered work,
|
||||||
generous contributions to the wide range of software distributed
|
but the special requirements of the GNU Affero General Public License,
|
||||||
through that system in reliance on consistent application of that
|
section 13, concerning interaction through a network will apply to the
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
combination as such.
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
14. Revised Versions of this License.
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
the GNU General Public License from time to time. Such new versions will
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
9. The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
address new problems or concerns.
|
address new problems or concerns.
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
Each version is given a distinguishing version number. If the
|
||||||
specifies a version number of this License which applies to it and "any
|
Program specifies that a certain numbered version of the GNU General
|
||||||
later version", you have the option of following the terms and conditions
|
Public License "or any later version" applies to it, you have the
|
||||||
either of that version or of any later version published by the Free
|
option of following the terms and conditions either of that numbered
|
||||||
Software Foundation. If the Program does not specify a version number of
|
version or of any later version published by the Free Software
|
||||||
this License, you may choose any version ever published by the Free Software
|
Foundation. If the Program does not specify a version number of the
|
||||||
Foundation.
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
10. If you wish to incorporate parts of the Program into other free
|
If the Program specifies that a proxy can decide which future
|
||||||
programs whose distribution conditions are different, write to the author
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
public statement of acceptance of a version permanently authorizes you
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
to choose that version for the Program.
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
15. Disclaimer of Warranty.
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
||||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
{one line to give the program's name and a brief idea of what it does.}
|
||||||
|
Copyright (C) {year} {name of author}
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
{project} Copyright (C) {year} {fullname}
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
|
@ -1,2 +1,24 @@
|
||||||
# EnigmAndroid
|
# EnigmAndroid
|
||||||
Android implementation of the famous Enigma machine
|
|
||||||
|
|
||||||
|
[<img src="https://f-droid.org/badge/get-it-on.png" alt="Get it on F-Droid" height="80">](https://f-droid.org/app/de.vanitasvitae.enigmandroid)
|
||||||
|
|
||||||
|
Android implementation of the famous Enigma machine.
|
||||||
|
|
||||||
|
Check out the website at [Jabberhead.tk](https://blog.jabberhead.tk/EnigmAndroid/).
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|
<div style="display:flex;" >
|
||||||
|
<img src="https://raw.githubusercontent.com/vanitasvitae/EnigmAndroid/master/fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png" width="40%" >
|
||||||
|
<img src="https://raw.githubusercontent.com/vanitasvitae/EnigmAndroid/master/fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png" width="40%" style="margin-left:15px;" >
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display:flex;" >
|
||||||
|
<img src="https://raw.githubusercontent.com/vanitasvitae/EnigmAndroid/master/fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png" width="40%" >
|
||||||
|
<img src="https://raw.githubusercontent.com/vanitasvitae/EnigmAndroid/master/fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png" width="40%" style="margin-left:15px;" >
|
||||||
|
</div>
|
||||||
|
|
||||||
|
If you want to support me with a donation, feel free to do so :)
|
||||||
|
|
||||||
|
btc: 1MW2DobbNFfcjxTSYzJhtkmiNS7efwaWFX
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
/build
|
||||||
|
/src/main/java/de/vanitasvitae/enigmandroid/enigma/util/
|
||||||
|
/src/androidTest/
|
||||||
|
/src/main/res/render-icon.sh
|
95
app/app.iml
|
@ -1,95 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="EnigmAndroid" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
|
||||||
<component name="FacetManager">
|
|
||||||
<facet type="android-gradle" name="Android-Gradle">
|
|
||||||
<configuration>
|
|
||||||
<option name="GRADLE_PROJECT_PATH" value=":app" />
|
|
||||||
</configuration>
|
|
||||||
</facet>
|
|
||||||
<facet type="android" name="Android">
|
|
||||||
<configuration>
|
|
||||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
|
||||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
|
||||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
|
||||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
|
||||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
|
|
||||||
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
|
|
||||||
<afterSyncTasks>
|
|
||||||
<task>generateDebugAndroidTestSources</task>
|
|
||||||
<task>generateDebugSources</task>
|
|
||||||
</afterSyncTasks>
|
|
||||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
|
||||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
|
||||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
|
||||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
|
|
||||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
|
||||||
</configuration>
|
|
||||||
</facet>
|
|
||||||
</component>
|
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
|
||||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
|
||||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
|
|
||||||
<exclude-output />
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.0/jars" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
<orderEntry type="library" exported="" name="support-v4-23.0.0" level="project" />
|
|
||||||
<orderEntry type="library" exported="" name="support-annotations-23.0.0" level="project" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
|
@ -1,23 +1,28 @@
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 23
|
compileSdkVersion 25
|
||||||
buildToolsVersion "22.0.1"
|
buildToolsVersion "25.0.3"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "de.vanitasvitae.enigmandroid"
|
applicationId "de.vanitasvitae.enigmandroid"
|
||||||
minSdkVersion 15
|
minSdkVersion 11
|
||||||
targetSdkVersion 23
|
targetSdkVersion 25
|
||||||
versionCode 11
|
versionCode 18
|
||||||
versionName "0.1.5-27.08.2015-beta"
|
versionName "1.0.2-01.01.2019"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lintOptions {
|
||||||
|
disable 'MissingTranslation'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
compile 'com.android.support:support-v4:23.0.0'
|
compile 'com.android.support:support-v4:25.3.1'
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,18 +4,19 @@
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
android:fullBackupContent="false"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
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" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEND" />
|
<action android:name="android.intent.action.SEND" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
|
@ -0,0 +1,506 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009 ZXing authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.zxing.integration.android;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>A utility class which helps ease integration with Barcode Scanner via {@link Intent}s. This is a simple
|
||||||
|
* way to invoke barcode scanning and receive the result, without any need to integrate, modify, or learn the
|
||||||
|
* project's source code.</p>
|
||||||
|
*
|
||||||
|
* <h2>Initiating a barcode scan</h2>
|
||||||
|
*
|
||||||
|
* <p>To integrate, create an instance of {@code IntentIntegrator} and call {@link #initiateScan()} and wait
|
||||||
|
* for the result in your app.</p>
|
||||||
|
*
|
||||||
|
* <p>It does require that the Barcode Scanner (or work-alike) application is installed. The
|
||||||
|
* {@link #initiateScan()} method will prompt the user to download the application, if needed.</p>
|
||||||
|
*
|
||||||
|
* <p>There are a few steps to using this integration. First, your {@link Activity} must implement
|
||||||
|
* the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:</p>
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||||
|
* IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
|
||||||
|
* if (scanResult != null) {
|
||||||
|
* // handle scan result
|
||||||
|
* }
|
||||||
|
* // else continue with any other code you need in the method
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* <p>This is where you will handle a scan result.</p>
|
||||||
|
*
|
||||||
|
* <p>Second, just call this in response to a user action somewhere to begin the scan process:</p>
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* IntentIntegrator integrator = new IntentIntegrator(yourActivity);
|
||||||
|
* integrator.initiateScan();
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* <p>Note that {@link #initiateScan()} returns an {@link AlertDialog} which is non-null if the
|
||||||
|
* user was prompted to download the application. This lets the calling app potentially manage the dialog.
|
||||||
|
* In particular, ideally, the app dismisses the dialog if it's still active in its {@link Activity#onPause()}
|
||||||
|
* method.</p>
|
||||||
|
*
|
||||||
|
* <p>You can use {@link #setTitle(String)} to customize the title of this download prompt dialog (or, use
|
||||||
|
* {@link #setTitleByID(int)} to set the title by string resource ID.) Likewise, the prompt message, and
|
||||||
|
* yes/no button labels can be changed.</p>
|
||||||
|
*
|
||||||
|
* <p>Finally, you can use {@link #addExtra(String, Object)} to add more parameters to the Intent used
|
||||||
|
* to invoke the scanner. This can be used to set additional options not directly exposed by this
|
||||||
|
* simplified API.</p>
|
||||||
|
*
|
||||||
|
* <p>By default, this will only allow applications that are known to respond to this intent correctly
|
||||||
|
* do so. The apps that are allowed to response can be set with {@link #setTargetApplications(List)}.
|
||||||
|
* For example, set to {@link #TARGET_BARCODE_SCANNER_ONLY} to only target the Barcode Scanner app itself.</p>
|
||||||
|
*
|
||||||
|
* <h2>Sharing text via barcode</h2>
|
||||||
|
*
|
||||||
|
* <p>To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(CharSequence)}.</p>
|
||||||
|
*
|
||||||
|
* <p>Some code, particularly download integration, was contributed from the Anobiit application.</p>
|
||||||
|
*
|
||||||
|
* <h2>Enabling experimental barcode formats</h2>
|
||||||
|
*
|
||||||
|
* <p>Some formats are not enabled by default even when scanning with {@link #ALL_CODE_TYPES}, such as
|
||||||
|
* PDF417. Use {@link #initiateScan(java.util.Collection)} with
|
||||||
|
* a collection containing the names of formats to scan for explicitly, like "PDF_417", to use such
|
||||||
|
* formats.</p>
|
||||||
|
*
|
||||||
|
* @author Sean Owen
|
||||||
|
* @author Fred Lin
|
||||||
|
* @author Isaac Potoczny-Jones
|
||||||
|
* @author Brad Drehmer
|
||||||
|
* @author gcstang
|
||||||
|
*/
|
||||||
|
public class IntentIntegrator {
|
||||||
|
|
||||||
|
public static final int REQUEST_CODE = 0x0000c0de; // Only use bottom 16 bits
|
||||||
|
private static final String TAG = IntentIntegrator.class.getSimpleName();
|
||||||
|
|
||||||
|
public static final String DEFAULT_TITLE = "Install Barcode Scanner?";
|
||||||
|
public static final String DEFAULT_MESSAGE =
|
||||||
|
"This application requires Barcode Scanner. Would you like to install it?";
|
||||||
|
public static final String DEFAULT_YES = "Yes";
|
||||||
|
public static final String DEFAULT_NO = "No";
|
||||||
|
|
||||||
|
private static final String BS_PACKAGE = "com.google.zxing.client.android";
|
||||||
|
private static final String BSPLUS_PACKAGE = "com.srowen.bs.android";
|
||||||
|
|
||||||
|
// supported barcode formats
|
||||||
|
public static final Collection<String> PRODUCT_CODE_TYPES = list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "RSS_14");
|
||||||
|
public static final Collection<String> ONE_D_CODE_TYPES =
|
||||||
|
list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "CODE_39", "CODE_93", "CODE_128",
|
||||||
|
"ITF", "RSS_14", "RSS_EXPANDED");
|
||||||
|
public static final Collection<String> QR_CODE_TYPES = Collections.singleton("QR_CODE");
|
||||||
|
public static final Collection<String> DATA_MATRIX_TYPES = Collections.singleton("DATA_MATRIX");
|
||||||
|
|
||||||
|
public static final Collection<String> ALL_CODE_TYPES = null;
|
||||||
|
|
||||||
|
public static final List<String> TARGET_BARCODE_SCANNER_ONLY = Collections.singletonList(BS_PACKAGE);
|
||||||
|
public static final List<String> TARGET_ALL_KNOWN = list(
|
||||||
|
BSPLUS_PACKAGE, // Barcode Scanner+
|
||||||
|
BSPLUS_PACKAGE + ".simple", // Barcode Scanner+ Simple
|
||||||
|
BS_PACKAGE // Barcode Scanner
|
||||||
|
// What else supports this intent?
|
||||||
|
);
|
||||||
|
|
||||||
|
private final Activity activity;
|
||||||
|
private final Fragment fragment;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
private String message;
|
||||||
|
private String buttonYes;
|
||||||
|
private String buttonNo;
|
||||||
|
private List<String> targetApplications;
|
||||||
|
private final Map<String,Object> moreExtras = new HashMap<>(3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param activity {@link Activity} invoking the integration
|
||||||
|
*/
|
||||||
|
public IntentIntegrator(Activity activity) {
|
||||||
|
this.activity = activity;
|
||||||
|
this.fragment = null;
|
||||||
|
initializeConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param fragment {@link Fragment} invoking the integration.
|
||||||
|
* {@link #startActivityForResult(Intent, int)} will be called on the {@link Fragment} instead
|
||||||
|
* of an {@link Activity}
|
||||||
|
*/
|
||||||
|
public IntentIntegrator(Fragment fragment) {
|
||||||
|
this.activity = fragment.getActivity();
|
||||||
|
this.fragment = fragment;
|
||||||
|
initializeConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeConfiguration() {
|
||||||
|
title = DEFAULT_TITLE;
|
||||||
|
message = DEFAULT_MESSAGE;
|
||||||
|
buttonYes = DEFAULT_YES;
|
||||||
|
buttonNo = DEFAULT_NO;
|
||||||
|
targetApplications = TARGET_ALL_KNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitleByID(int titleID) {
|
||||||
|
title = activity.getString(titleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessageByID(int messageID) {
|
||||||
|
message = activity.getString(messageID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getButtonYes() {
|
||||||
|
return buttonYes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setButtonYes(String buttonYes) {
|
||||||
|
this.buttonYes = buttonYes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setButtonYesByID(int buttonYesID) {
|
||||||
|
buttonYes = activity.getString(buttonYesID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getButtonNo() {
|
||||||
|
return buttonNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setButtonNo(String buttonNo) {
|
||||||
|
this.buttonNo = buttonNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setButtonNoByID(int buttonNoID) {
|
||||||
|
buttonNo = activity.getString(buttonNoID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> getTargetApplications() {
|
||||||
|
return targetApplications;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setTargetApplications(List<String> targetApplications) {
|
||||||
|
if (targetApplications.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("No target applications");
|
||||||
|
}
|
||||||
|
this.targetApplications = targetApplications;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSingleTargetApplication(String targetApplication) {
|
||||||
|
this.targetApplications = Collections.singletonList(targetApplication);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String,?> getMoreExtras() {
|
||||||
|
return moreExtras;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void addExtra(String key, Object value) {
|
||||||
|
moreExtras.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiates a scan for all known barcode types with the default camera.
|
||||||
|
*
|
||||||
|
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
|
||||||
|
* if a prompt was needed, or null otherwise.
|
||||||
|
*/
|
||||||
|
public final AlertDialog initiateScan() {
|
||||||
|
return initiateScan(ALL_CODE_TYPES, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiates a scan for all known barcode types with the specified camera.
|
||||||
|
*
|
||||||
|
* @param cameraId camera ID of the camera to use. A negative value means "no preference".
|
||||||
|
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
|
||||||
|
* if a prompt was needed, or null otherwise.
|
||||||
|
*/
|
||||||
|
public final AlertDialog initiateScan(int cameraId) {
|
||||||
|
return initiateScan(ALL_CODE_TYPES, cameraId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiates a scan, using the default camera, only for a certain set of barcode types, given as strings corresponding
|
||||||
|
* to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants
|
||||||
|
* like {@link #PRODUCT_CODE_TYPES} for example.
|
||||||
|
*
|
||||||
|
* @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for
|
||||||
|
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
|
||||||
|
* if a prompt was needed, or null otherwise.
|
||||||
|
*/
|
||||||
|
public final AlertDialog initiateScan(Collection<String> desiredBarcodeFormats) {
|
||||||
|
return initiateScan(desiredBarcodeFormats, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiates a scan, using the specified camera, only for a certain set of barcode types, given as strings corresponding
|
||||||
|
* to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants
|
||||||
|
* like {@link #PRODUCT_CODE_TYPES} for example.
|
||||||
|
*
|
||||||
|
* @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for
|
||||||
|
* @param cameraId camera ID of the camera to use. A negative value means "no preference".
|
||||||
|
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
|
||||||
|
* if a prompt was needed, or null otherwise
|
||||||
|
*/
|
||||||
|
public final AlertDialog initiateScan(Collection<String> desiredBarcodeFormats, int cameraId) {
|
||||||
|
Intent intentScan = new Intent(BS_PACKAGE + ".SCAN");
|
||||||
|
intentScan.addCategory(Intent.CATEGORY_DEFAULT);
|
||||||
|
|
||||||
|
// check which types of codes to scan for
|
||||||
|
if (desiredBarcodeFormats != null) {
|
||||||
|
// set the desired barcode types
|
||||||
|
StringBuilder joinedByComma = new StringBuilder();
|
||||||
|
for (String format : desiredBarcodeFormats) {
|
||||||
|
if (joinedByComma.length() > 0) {
|
||||||
|
joinedByComma.append(',');
|
||||||
|
}
|
||||||
|
joinedByComma.append(format);
|
||||||
|
}
|
||||||
|
intentScan.putExtra("SCAN_FORMATS", joinedByComma.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// check requested camera ID
|
||||||
|
if (cameraId >= 0) {
|
||||||
|
intentScan.putExtra("SCAN_CAMERA_ID", cameraId);
|
||||||
|
}
|
||||||
|
|
||||||
|
String targetAppPackage = findTargetAppPackage(intentScan);
|
||||||
|
if (targetAppPackage == null) {
|
||||||
|
return showDownloadDialog();
|
||||||
|
}
|
||||||
|
intentScan.setPackage(targetAppPackage);
|
||||||
|
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
|
||||||
|
attachMoreExtras(intentScan);
|
||||||
|
startActivityForResult(intentScan, REQUEST_CODE);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start an activity. This method is defined to allow different methods of activity starting for
|
||||||
|
* newer versions of Android and for compatibility library.
|
||||||
|
*
|
||||||
|
* @param intent Intent to start.
|
||||||
|
* @param code Request code for the activity
|
||||||
|
* @see android.app.Activity#startActivityForResult(Intent, int)
|
||||||
|
* @see android.app.Fragment#startActivityForResult(Intent, int)
|
||||||
|
*/
|
||||||
|
protected void startActivityForResult(Intent intent, int code) {
|
||||||
|
if (fragment == null) {
|
||||||
|
activity.startActivityForResult(intent, code);
|
||||||
|
} else {
|
||||||
|
fragment.startActivityForResult(intent, code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String findTargetAppPackage(Intent intent) {
|
||||||
|
PackageManager pm = activity.getPackageManager();
|
||||||
|
List<ResolveInfo> availableApps = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||||
|
if (availableApps != null) {
|
||||||
|
for (String targetApp : targetApplications) {
|
||||||
|
if (contains(availableApps, targetApp)) {
|
||||||
|
return targetApp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean contains(Iterable<ResolveInfo> availableApps, String targetApp) {
|
||||||
|
for (ResolveInfo availableApp : availableApps) {
|
||||||
|
String packageName = availableApp.activityInfo.packageName;
|
||||||
|
if (targetApp.equals(packageName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AlertDialog showDownloadDialog() {
|
||||||
|
AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
|
||||||
|
downloadDialog.setTitle(title);
|
||||||
|
downloadDialog.setMessage(message);
|
||||||
|
downloadDialog.setPositiveButton(buttonYes, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
|
String packageName;
|
||||||
|
if (targetApplications.contains(BS_PACKAGE)) {
|
||||||
|
// Prefer to suggest download of BS if it's anywhere in the list
|
||||||
|
packageName = BS_PACKAGE;
|
||||||
|
} else {
|
||||||
|
// Otherwise, first option:
|
||||||
|
packageName = targetApplications.get(0);
|
||||||
|
}
|
||||||
|
Uri uri = Uri.parse("market://details?id=" + packageName);
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||||
|
try {
|
||||||
|
if (fragment == null) {
|
||||||
|
activity.startActivity(intent);
|
||||||
|
} else {
|
||||||
|
fragment.startActivity(intent);
|
||||||
|
}
|
||||||
|
} catch (ActivityNotFoundException anfe) {
|
||||||
|
// Hmm, market is not installed
|
||||||
|
Log.w(TAG, "Google Play is not installed; cannot install " + packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
downloadDialog.setNegativeButton(buttonNo, null);
|
||||||
|
downloadDialog.setCancelable(true);
|
||||||
|
return downloadDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Call this from your {@link Activity}'s
|
||||||
|
* {@link Activity#onActivityResult(int, int, Intent)} method.</p>
|
||||||
|
*
|
||||||
|
* @param requestCode request code from {@code onActivityResult()}
|
||||||
|
* @param resultCode result code from {@code onActivityResult()}
|
||||||
|
* @param intent {@link Intent} from {@code onActivityResult()}
|
||||||
|
* @return null if the event handled here was not related to this class, or
|
||||||
|
* else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning,
|
||||||
|
* the fields will be null.
|
||||||
|
*/
|
||||||
|
public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||||
|
if (requestCode == REQUEST_CODE) {
|
||||||
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
|
String contents = intent.getStringExtra("SCAN_RESULT");
|
||||||
|
String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT");
|
||||||
|
byte[] rawBytes = intent.getByteArrayExtra("SCAN_RESULT_BYTES");
|
||||||
|
int intentOrientation = intent.getIntExtra("SCAN_RESULT_ORIENTATION", Integer.MIN_VALUE);
|
||||||
|
Integer orientation = intentOrientation == Integer.MIN_VALUE ? null : intentOrientation;
|
||||||
|
String errorCorrectionLevel = intent.getStringExtra("SCAN_RESULT_ERROR_CORRECTION_LEVEL");
|
||||||
|
return new IntentResult(contents,
|
||||||
|
formatName,
|
||||||
|
rawBytes,
|
||||||
|
orientation,
|
||||||
|
errorCorrectionLevel);
|
||||||
|
}
|
||||||
|
return new IntentResult();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defaults to name "TEXT_TYPE".
|
||||||
|
*
|
||||||
|
* @param text the text string to encode as a barcode
|
||||||
|
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
|
||||||
|
* if a prompt was needed, or null otherwise
|
||||||
|
* @see #shareText(CharSequence, CharSequence)
|
||||||
|
*/
|
||||||
|
public final AlertDialog shareText(CharSequence text) {
|
||||||
|
return shareText(text, "TEXT_TYPE");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shares the given text by encoding it as a barcode, such that another user can
|
||||||
|
* scan the text off the screen of the device.
|
||||||
|
*
|
||||||
|
* @param text the text string to encode as a barcode
|
||||||
|
* @param type name of data to encode. See {@code com.google.zxing.client.android.Contents.Type} constants.
|
||||||
|
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
|
||||||
|
* if a prompt was needed, or null otherwise
|
||||||
|
*/
|
||||||
|
public final AlertDialog shareText(CharSequence text, CharSequence type) {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||||
|
intent.setAction(BS_PACKAGE + ".ENCODE");
|
||||||
|
intent.putExtra("ENCODE_TYPE", type);
|
||||||
|
intent.putExtra("ENCODE_DATA", text);
|
||||||
|
String targetAppPackage = findTargetAppPackage(intent);
|
||||||
|
if (targetAppPackage == null) {
|
||||||
|
return showDownloadDialog();
|
||||||
|
}
|
||||||
|
intent.setPackage(targetAppPackage);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
|
||||||
|
attachMoreExtras(intent);
|
||||||
|
if (fragment == null) {
|
||||||
|
activity.startActivity(intent);
|
||||||
|
} else {
|
||||||
|
fragment.startActivity(intent);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<String> list(String... values) {
|
||||||
|
return Collections.unmodifiableList(Arrays.asList(values));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void attachMoreExtras(Intent intent) {
|
||||||
|
for (Map.Entry<String,Object> entry : moreExtras.entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
Object value = entry.getValue();
|
||||||
|
// Kind of hacky
|
||||||
|
if (value instanceof Integer) {
|
||||||
|
intent.putExtra(key, (Integer) value);
|
||||||
|
} else if (value instanceof Long) {
|
||||||
|
intent.putExtra(key, (Long) value);
|
||||||
|
} else if (value instanceof Boolean) {
|
||||||
|
intent.putExtra(key, (Boolean) value);
|
||||||
|
} else if (value instanceof Double) {
|
||||||
|
intent.putExtra(key, (Double) value);
|
||||||
|
} else if (value instanceof Float) {
|
||||||
|
intent.putExtra(key, (Float) value);
|
||||||
|
} else if (value instanceof Bundle) {
|
||||||
|
intent.putExtra(key, (Bundle) value);
|
||||||
|
} else {
|
||||||
|
intent.putExtra(key, value.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009 ZXing authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.zxing.integration.android;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.</p>
|
||||||
|
*
|
||||||
|
* @author Sean Owen
|
||||||
|
*/
|
||||||
|
public final class IntentResult {
|
||||||
|
|
||||||
|
private final String contents;
|
||||||
|
private final String formatName;
|
||||||
|
private final byte[] rawBytes;
|
||||||
|
private final Integer orientation;
|
||||||
|
private final String errorCorrectionLevel;
|
||||||
|
|
||||||
|
IntentResult() {
|
||||||
|
this(null, null, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
IntentResult(String contents,
|
||||||
|
String formatName,
|
||||||
|
byte[] rawBytes,
|
||||||
|
Integer orientation,
|
||||||
|
String errorCorrectionLevel) {
|
||||||
|
this.contents = contents;
|
||||||
|
this.formatName = formatName;
|
||||||
|
this.rawBytes = rawBytes;
|
||||||
|
this.orientation = orientation;
|
||||||
|
this.errorCorrectionLevel = errorCorrectionLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return raw content of barcode
|
||||||
|
*/
|
||||||
|
public String getContents() {
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return name of format, like "QR_CODE", "UPC_A". See {@code BarcodeFormat} for more format names.
|
||||||
|
*/
|
||||||
|
public String getFormatName() {
|
||||||
|
return formatName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return raw bytes of the barcode content, if applicable, or null otherwise
|
||||||
|
*/
|
||||||
|
public byte[] getRawBytes() {
|
||||||
|
return rawBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return rotation of the image, in degrees, which resulted in a successful scan. May be null.
|
||||||
|
*/
|
||||||
|
public Integer getOrientation() {
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return name of the error correction level used in the barcode, if applicable
|
||||||
|
*/
|
||||||
|
public String getErrorCorrectionLevel() {
|
||||||
|
return errorCorrectionLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
int rawBytesLength = rawBytes == null ? 0 : rawBytes.length;
|
||||||
|
return "Format: "+formatName+'\n'+"Contents: "+contents+'\n'+"Raw bytes: ("+rawBytesLength+" bytes)\n"+"Orientation: "+orientation+'\n'+"EC level: "+errorCorrectionLevel+'\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,344 +1,509 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package de.vanitasvitae.enigmandroid;
|
package de.vanitasvitae.enigmandroid;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.ClipData;
|
||||||
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.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
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.text.InputType;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import de.vanitasvitae.enigmandroid.enigma.Plugboard;
|
import com.google.zxing.integration.android.IntentIntegrator;
|
||||||
|
import com.google.zxing.integration.android.IntentResult;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
|
||||||
import de.vanitasvitae.enigmandroid.enigma.inputPreparer.InputPreparer;
|
import de.vanitasvitae.enigmandroid.enigma.inputPreparer.InputPreparer;
|
||||||
import de.vanitasvitae.enigmandroid.layout.LayoutContainer;
|
import de.vanitasvitae.enigmandroid.layout.LayoutContainer;
|
||||||
|
import de.vanitasvitae.enigmandroid.layout.PassphraseDialogBuilder;
|
||||||
|
|
||||||
/**
|
|
||||||
* Main Android Activity of the app
|
|
||||||
* 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 MainActivity extends Activity
|
public class MainActivity extends Activity
|
||||||
{
|
{
|
||||||
private static final int RESULT_SETTINGS = 1;
|
private static final int RESULT_SETTINGS = 1;
|
||||||
private static final String URI_CHANGELOG =
|
private static final String URI_CHANGELOG =
|
||||||
"https://github.com/vanitasvitae/EnigmAndroid/blob/master/CHANGELOG.txt";
|
"https://github.com/vanitasvitae/EnigmAndroid/blob/master/CHANGELOG.txt";
|
||||||
|
public static final String APP_ID = "EnigmAndroid";
|
||||||
|
public static final int latest_protocol_version = 1;
|
||||||
|
public static final int max_protocol_version = 256;
|
||||||
|
|
||||||
LayoutContainer layoutContainer;
|
private LayoutContainer layoutContainer;
|
||||||
protected String prefMachineType;
|
|
||||||
protected boolean prefAnomaly;
|
|
||||||
protected String prefNumericLanguage;
|
|
||||||
|
|
||||||
@Override
|
private SecureRandom secureRandom;
|
||||||
public void onCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
|
||||||
this.prefMachineType = sharedPreferences.getString("prefMachineType", getResources().
|
|
||||||
getStringArray(R.array.pref_list_machine_type)[0]);
|
|
||||||
ActivitySingleton singleton = ActivitySingleton.getInstance();
|
|
||||||
singleton.setActivity(this);
|
|
||||||
updateContentView();
|
|
||||||
layoutContainer = LayoutContainer.createLayoutContainer(prefMachineType);
|
|
||||||
updatePreferenceValues();
|
|
||||||
//Handle shared text
|
|
||||||
Intent intent = getIntent();
|
|
||||||
String action = intent.getAction();
|
|
||||||
String type = intent.getType();
|
|
||||||
|
|
||||||
if (Intent.ACTION_SEND.equals(action) && type != null) {
|
@Override
|
||||||
if ("text/plain".equals(type))
|
public void onCreate(Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
|
super.onCreate(savedInstanceState);
|
||||||
if (sharedText != null)
|
secureRandom = new SecureRandom();
|
||||||
{
|
ActivitySingleton.getInstance().setActivity(this);
|
||||||
layoutContainer.getInputView().setText(sharedText);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
}
|
SettingsActivity.SettingsSingleton.getInstance(prefs, getResources());
|
||||||
}
|
layoutContainer = LayoutContainer.createLayoutContainer();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
//Handle shared text
|
||||||
public void onConfigurationChanged(Configuration newConfig) {
|
Intent intent = getIntent();
|
||||||
super.onConfigurationChanged(newConfig);
|
String action = intent.getAction();
|
||||||
}
|
String type = intent.getType();
|
||||||
|
if (Intent.ACTION_SEND.equals(action) && type != null) {
|
||||||
|
if ("text/plain".equals(type))
|
||||||
|
{
|
||||||
|
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||||
|
if (sharedText != null)
|
||||||
|
{
|
||||||
|
//If shared text consists of an encoded configuration, try to restore it
|
||||||
|
if(sharedText.startsWith(APP_ID+"/"))
|
||||||
|
restoreStateFromCode(sharedText);
|
||||||
|
//Else put it in the input text box
|
||||||
|
else
|
||||||
|
layoutContainer.getInput().setRawText(sharedText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateContentView()
|
public SecureRandom getSecureRandom()
|
||||||
{
|
{
|
||||||
switch (prefMachineType)
|
return this.secureRandom;
|
||||||
{
|
}
|
||||||
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()
|
public void onDialogFinished(EnigmaStateBundle state)
|
||||||
{
|
{
|
||||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
layoutContainer.getEnigma().setState(state);
|
||||||
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)
|
@Override
|
||||||
{
|
public boolean onCreateOptionsMenu(Menu menu)
|
||||||
if(prefMachineType == null || !prefMachineType.equals(type))
|
{
|
||||||
{
|
this.getMenuInflater().inflate(R.menu.main, menu);
|
||||||
prefMachineType = type;
|
return true;
|
||||||
String savedInput = "";
|
}
|
||||||
if(layoutContainer != null)
|
|
||||||
{
|
|
||||||
savedInput = layoutContainer.getInputView().getText().toString();
|
|
||||||
}
|
|
||||||
updateContentView();
|
|
||||||
layoutContainer = LayoutContainer.createLayoutContainer(prefMachineType);
|
|
||||||
layoutContainer.getInputView().setText(savedInput);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPrefMachineType()
|
@Override
|
||||||
{
|
/**
|
||||||
if(prefMachineType != null) return prefMachineType;
|
* Handle Options menu clicks
|
||||||
else
|
*/
|
||||||
{
|
public boolean onOptionsItemSelected(MenuItem item)
|
||||||
updatePreferenceValues();
|
{
|
||||||
return prefMachineType;
|
int id = item.getItemId();
|
||||||
}
|
if (id == R.id.action_reset)
|
||||||
}
|
{
|
||||||
|
layoutContainer.resetLayout();
|
||||||
|
Toast.makeText(getApplicationContext(), R.string.message_reset,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (id == R.id.action_send_message)
|
||||||
|
{
|
||||||
|
if(layoutContainer.getOutput().getText().length() == 0)
|
||||||
|
{
|
||||||
|
Toast.makeText(this, R.string.error_no_text_to_send, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Intent sendIntent = new Intent();
|
||||||
|
sendIntent.setAction(Intent.ACTION_SEND);
|
||||||
|
sendIntent.putExtra(Intent.EXTRA_TEXT, layoutContainer.getOutput().getModifiedText());
|
||||||
|
sendIntent.setType("text/plain");
|
||||||
|
startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (id == R.id.action_choose_ringsetting)
|
||||||
|
{
|
||||||
|
layoutContainer.showRingSettingsDialog();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(id == R.id.action_share_configuration)
|
||||||
|
{
|
||||||
|
showShareConfigurationDialog();
|
||||||
|
}
|
||||||
|
else if (id == R.id.action_restore_configuration)
|
||||||
|
{
|
||||||
|
showReceiveConfigurationDialog();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (id == R.id.action_random_configuration)
|
||||||
|
{
|
||||||
|
layoutContainer.getEnigma().randomState();
|
||||||
|
layoutContainer.syncStateFromEnigmaToLayout();
|
||||||
|
Toast.makeText(getApplicationContext(), R.string.message_random,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
layoutContainer.getOutput().setText("");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (id == R.id.action_settings)
|
||||||
|
{
|
||||||
|
Intent i = new Intent(this, SettingsActivity.class);
|
||||||
|
startActivityForResult(i, RESULT_SETTINGS);
|
||||||
|
}
|
||||||
|
else if (id == R.id.action_about)
|
||||||
|
{
|
||||||
|
showAboutDialog();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
public void setPrefAnomaly(boolean anomaly)
|
/**
|
||||||
{
|
* Set the chosen Configuration to the enigma, get the input string from the input text box and
|
||||||
if(prefAnomaly !=anomaly)
|
* prepare it, set the input to the prepared text, encrypt the prepared input and set the
|
||||||
{
|
* encrypted string to the output text box and update the spinners to their new positions.
|
||||||
prefAnomaly = anomaly;
|
* @param v View
|
||||||
layoutContainer.getEnigma().setPrefAnomaly(anomaly);
|
*/
|
||||||
}
|
public void doCrypto(View v)
|
||||||
}
|
{
|
||||||
|
layoutContainer.doCrypto();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getPrefAnomaly()
|
/**
|
||||||
{
|
* Start an intent to share the configuration as QR-Code via Barcode Scanner
|
||||||
return prefAnomaly;
|
*/
|
||||||
}
|
private void shareConfigurationAsQR()
|
||||||
|
{
|
||||||
|
IntentIntegrator QRIntegrator = new IntentIntegrator(this);
|
||||||
|
layoutContainer.syncStateFromLayoutToEnigma();
|
||||||
|
String encoded_state = APP_ID+"/"+layoutContainer.getEnigma().getEncodedState().toString(16);
|
||||||
|
Log.d(APP_ID, "Sharing configuration to QR: "+encoded_state);
|
||||||
|
QRIntegrator.shareText(encoded_state);
|
||||||
|
}
|
||||||
|
|
||||||
public void setPrefNumericLanguage(String lang)
|
/**
|
||||||
{
|
* Start an intent to share the configuration as text
|
||||||
if(prefNumericLanguage == null || !prefNumericLanguage.equals(lang))
|
*/
|
||||||
{
|
private void shareConfigurationAsText()
|
||||||
prefNumericLanguage = lang;
|
{
|
||||||
layoutContainer.getEnigma().setInputPreparer(InputPreparer.createInputPreparer(lang));
|
Intent sendIntent = new Intent();
|
||||||
}
|
sendIntent.setAction(Intent.ACTION_SEND);
|
||||||
}
|
sendIntent.putExtra(Intent.EXTRA_TEXT,
|
||||||
|
APP_ID+"/"+layoutContainer.getEnigma().getEncodedState().toString(16));
|
||||||
|
sendIntent.setType("text/plain");
|
||||||
|
startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));
|
||||||
|
}
|
||||||
|
|
||||||
public String getPrefNumericLanguage()
|
/**
|
||||||
{
|
* Start the barcode app to scan a barcode for configuration
|
||||||
if(prefNumericLanguage != null) return prefNumericLanguage;
|
*/
|
||||||
else
|
private void receiveConfigurationQR()
|
||||||
{
|
{
|
||||||
updatePreferenceValues();
|
IntentIntegrator integrator = new IntentIntegrator(this);
|
||||||
return prefNumericLanguage;
|
integrator.initiateScan();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public boolean onCreateOptionsMenu(Menu menu)
|
* Show a dialog to restore a configuration
|
||||||
{
|
*/
|
||||||
this.getMenuInflater().inflate(R.menu.main, menu);
|
private void receiveConfigurationText()
|
||||||
return true;
|
{
|
||||||
}
|
new PassphraseDialogBuilder().showDialog();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
/**
|
* Show a Dialog containing information about the app, license, usage, author and a link
|
||||||
* Handle Options menu clicks
|
* to the changelog
|
||||||
*/
|
*/
|
||||||
public boolean onOptionsItemSelected(MenuItem item)
|
private void showAboutDialog()
|
||||||
{
|
{
|
||||||
int id = item.getItemId();
|
final View aboutView = View.inflate(this, R.layout.dialog_about, null);
|
||||||
if (id == R.id.action_reset)
|
//Get and set Version code
|
||||||
{
|
PackageInfo pInfo = null;
|
||||||
layoutContainer.reset();
|
try{ pInfo = getPackageManager().getPackageInfo(this.getPackageName(), 0);}
|
||||||
Toast.makeText(getApplicationContext(), R.string.message_reset,
|
catch (PackageManager.NameNotFoundException e){ e.printStackTrace();}
|
||||||
Toast.LENGTH_SHORT).show();
|
assert pInfo != null;
|
||||||
return true;
|
String version = pInfo.versionName+ " ("+pInfo.versionCode+")";
|
||||||
}
|
TextView versionText = (TextView) aboutView.findViewById(R.id.about_version_section);
|
||||||
else if (id == R.id.action_choose_ringstellung)
|
versionText.setText(version);
|
||||||
{
|
|
||||||
layoutContainer.showRingSettingsDialog();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (id == R.id.action_settings)
|
|
||||||
{
|
|
||||||
Intent i = new Intent(this, SettingsActivity.class);
|
|
||||||
startActivityForResult(i, RESULT_SETTINGS);
|
|
||||||
}
|
|
||||||
else if (id == R.id.action_about)
|
|
||||||
{
|
|
||||||
showAboutDialog();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (id == R.id.action_send)
|
|
||||||
{
|
|
||||||
if(layoutContainer.getOutputView().getText().length() == 0)
|
|
||||||
{
|
|
||||||
Toast.makeText(this, R.string.error_no_text_to_send, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Intent sendIntent = new Intent();
|
|
||||||
sendIntent.setAction(Intent.ACTION_SEND);
|
|
||||||
sendIntent.putExtra(Intent.EXTRA_TEXT, layoutContainer.getOutputView().getText().toString());
|
|
||||||
sendIntent.setType("text/plain");
|
|
||||||
startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
//Build and show dialog
|
||||||
* Set the chosen Configuration to the enigma, get the input string from the input textbox and
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
* prepare it, set the input to the prepared text, encrypt the prepared input and set the
|
builder.setTitle(R.string.title_about_dialog);
|
||||||
* encrypted string to the output textbox and update the spinners to their new positions.
|
builder.setView(aboutView)
|
||||||
* @param v View
|
.setCancelable(true)
|
||||||
*/
|
.setPositiveButton(R.string.dialog_positive, new DialogInterface.OnClickListener()
|
||||||
public void doCrypto(View v)
|
{
|
||||||
{
|
public void onClick(DialogInterface dialog, int id)
|
||||||
if(layoutContainer.getInputView().getText().length()!=0) {
|
{
|
||||||
layoutContainer.getEnigma().setConfiguration(layoutContainer.createConfiguration());
|
dialog.dismiss();
|
||||||
layoutContainer.getEnigma().setPlugboard(new Plugboard(layoutContainer.createPlugboardConfiguration()));
|
}
|
||||||
String m = layoutContainer.getInputView().getText().toString();
|
})
|
||||||
m = layoutContainer.getEnigma().getInputPreparer().prepareString(m);
|
.setNegativeButton(R.string.button_show_changelog, new DialogInterface.OnClickListener()
|
||||||
layoutContainer.getInputView().setText(m);
|
{
|
||||||
layoutContainer.getOutputView().setText(layoutContainer.getEnigma().encrypt(m));
|
public void onClick(DialogInterface dialog, int id)
|
||||||
layoutContainer.updateLayout();
|
{
|
||||||
}
|
dialog.cancel();
|
||||||
}
|
openWebPage(URI_CHANGELOG);
|
||||||
|
}
|
||||||
|
}).show();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a Dialog containing information about the app, license, usage, author and a link
|
* Show a dialog where the user can choose between sharing the configuration via QR-code or
|
||||||
* to the changelog
|
* via string (intent or copy-to-clipboard)
|
||||||
*/
|
*/
|
||||||
public void showAboutDialog()
|
private void showShareConfigurationDialog()
|
||||||
{
|
{
|
||||||
final View aboutView = View.inflate(this, R.layout.dialog_about, null);
|
final String configuration = APP_ID+"/"+layoutContainer.getEnigma().getEncodedState().toString(16);
|
||||||
|
final View shareView = View.inflate(this, R.layout.dialog_two_options, null);
|
||||||
|
LinearLayout l = (LinearLayout) shareView.findViewById(R.id.dialog_two_options_lay);
|
||||||
|
EditText e = new EditText(this);
|
||||||
|
e.setText(configuration);
|
||||||
|
e.setInputType(InputType.TYPE_NULL);
|
||||||
|
e.setOnClickListener(new View.OnClickListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onClick(View v)
|
||||||
|
{
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB){
|
||||||
|
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||||
|
ClipData clip;
|
||||||
|
clip = ClipData.newPlainText("label", configuration);
|
||||||
|
clipboard.setPrimaryClip(clip);
|
||||||
|
} else{
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
android.text.ClipboardManager clipboard = (android.text.ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
|
||||||
|
clipboard.setText(configuration);
|
||||||
|
}
|
||||||
|
Toast.makeText(getApplicationContext(), R.string.message_clipboard, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
l.addView(e);
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
builder.setTitle(R.string.dialog_title_share_configuration)
|
||||||
|
.setView(shareView).setCancelable(true);
|
||||||
|
final Dialog d = builder.create();
|
||||||
|
Button one = (Button) shareView.findViewById(R.id.dialog_two_options_1);
|
||||||
|
one.setText(R.string.dialog_share_qr);
|
||||||
|
one.setOnClickListener(new View.OnClickListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onClick(View v)
|
||||||
|
{
|
||||||
|
shareConfigurationAsQR();
|
||||||
|
d.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Button two = (Button) shareView.findViewById(R.id.dialog_two_options_2);
|
||||||
|
two.setText(R.string.dialog_share_code);
|
||||||
|
two.setOnClickListener(new View.OnClickListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onClick(View v)
|
||||||
|
{
|
||||||
|
shareConfigurationAsText();
|
||||||
|
d.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
d.show();
|
||||||
|
}
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
/**
|
||||||
builder.setTitle(R.string.title_about_dialog);
|
* Show a dialog, where the user can choose between scanning QR-code and entering a string to
|
||||||
builder.setView(aboutView)
|
* restore the encoded configuration
|
||||||
.setCancelable(true)
|
*/
|
||||||
.setPositiveButton(R.string.dialog_positiv, new DialogInterface.OnClickListener()
|
private void showReceiveConfigurationDialog()
|
||||||
{
|
{
|
||||||
public void onClick(DialogInterface dialog, int id)
|
final View shareView = View.inflate(this, R.layout.dialog_two_options, null);
|
||||||
{
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
dialog.dismiss();
|
builder.setTitle(R.string.dialog_title_restore_configuration)
|
||||||
}
|
.setView(shareView).setCancelable(true);
|
||||||
})
|
final Dialog d = builder.create();
|
||||||
.setNegativeButton(R.string.button_show_changelog, new DialogInterface.OnClickListener()
|
Button one = (Button) shareView.findViewById(R.id.dialog_two_options_1);
|
||||||
{
|
one.setText(R.string.dialog_restore_qr);
|
||||||
public void onClick(DialogInterface dialog, int id)
|
one.setOnClickListener(new View.OnClickListener()
|
||||||
{
|
{
|
||||||
dialog.cancel();
|
@Override
|
||||||
openWebPage(URI_CHANGELOG);
|
public void onClick(View v)
|
||||||
}
|
{
|
||||||
}).show();
|
receiveConfigurationQR();
|
||||||
}
|
d.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Button two = (Button) shareView.findViewById(R.id.dialog_two_options_2);
|
||||||
|
two.setText(R.string.dialog_restore_code);
|
||||||
|
two.setOnClickListener(new View.OnClickListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onClick(View v)
|
||||||
|
{
|
||||||
|
receiveConfigurationText();
|
||||||
|
d.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
d.show();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle preference changes
|
* Handle Activity Results
|
||||||
* @param requestCode requestCode
|
* @param requestCode requestCode
|
||||||
* @param resultCode resultCode (RESULT_SETTINGS is defined at the top)
|
* @param resultCode resultCode (RESULT_SETTINGS is defined at the top)
|
||||||
* @param data data (not important here)
|
* @param data data
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
|
switch (requestCode) {
|
||||||
|
//Come back from Settings
|
||||||
|
case RESULT_SETTINGS:
|
||||||
|
{
|
||||||
|
applyPreferenceChanges();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Receive from QR
|
||||||
|
case IntentIntegrator.REQUEST_CODE:
|
||||||
|
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
|
||||||
|
if (scanResult != null) {
|
||||||
|
String content = scanResult.getContents();
|
||||||
|
if(content == null) Log.e(APP_ID, "Error! Received nothing from QR-Code!");
|
||||||
|
else {
|
||||||
|
Log.d(APP_ID, "Received " + content + " from QR-Code!");
|
||||||
|
restoreStateFromCode(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (requestCode) {
|
/**
|
||||||
case RESULT_SETTINGS:
|
* Handle changes in preferences and apply those changes to the app
|
||||||
{
|
*/
|
||||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
private void applyPreferenceChanges()
|
||||||
this.setPrefMachineType(sharedPrefs.getString("prefMachineType", getResources()
|
{
|
||||||
.getStringArray(R.array.pref_list_machine_type)[0]));
|
SettingsActivity s = SettingsActivity.SettingsSingleton.getInstance();
|
||||||
this.setPrefAnomaly(sharedPrefs.getBoolean("prefAnomaly", true));
|
if(s.prefMachineTypeChanged())
|
||||||
this.setPrefNumericLanguage(this.prefNumericLanguage = sharedPrefs.getString("prefNumericLanguage", getResources().
|
{
|
||||||
getStringArray(R.array.pref_alias_numeric_spelling_language)[0]));
|
layoutContainer = LayoutContainer.createLayoutContainer();
|
||||||
break;
|
}
|
||||||
}
|
if(s.prefMessageFormattingChanged())
|
||||||
|
{
|
||||||
|
layoutContainer.setEditTextAdapter(s.getPrefMessageFormatting());
|
||||||
|
}
|
||||||
|
if(s.prefNumericLanguageChanged())
|
||||||
|
{
|
||||||
|
layoutContainer.setInputPreparer(InputPreparer.createInputPreparer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
/**
|
||||||
}
|
* Set EnigmAndroid into a certain state as described in the QR-Code
|
||||||
|
* @param mem content of the QR-Code
|
||||||
|
*/
|
||||||
|
public void restoreStateFromCode(String mem)
|
||||||
|
{
|
||||||
|
if(!mem.startsWith(APP_ID+"/"))
|
||||||
|
{
|
||||||
|
Toast.makeText(this, R.string.error_no_valid_qr, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String inputString = layoutContainer.getInput().getText();
|
||||||
|
mem = mem.substring((APP_ID+"/").length());
|
||||||
|
BigInteger s = new BigInteger(mem, 16);
|
||||||
|
int protocol_version = Enigma.getValue(s, max_protocol_version);
|
||||||
|
s = Enigma.removeDigit(s, max_protocol_version);
|
||||||
|
Log.d(APP_ID,
|
||||||
|
"Try to restore configuration from BigInteger value "+s.toString()+" in protocol version "+protocol_version+".");
|
||||||
|
SettingsActivity.SettingsSingleton.getInstance()
|
||||||
|
.setPrefMachineType(Enigma.chooseEnigmaFromSave(s));
|
||||||
|
layoutContainer = LayoutContainer.createLayoutContainer();
|
||||||
|
layoutContainer.getEnigma().restoreState(Enigma.removeDigit(s,20), protocol_version);
|
||||||
|
layoutContainer.setInputPreparer(InputPreparer.createInputPreparer());
|
||||||
|
layoutContainer.syncStateFromEnigmaToLayout();
|
||||||
|
layoutContainer.getInput().setText(inputString);
|
||||||
|
layoutContainer.getOutput().setText("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the web page with the URL url
|
* Set EnigmAndroid into a state calculated from the seed.
|
||||||
* @param url URL of the website
|
* @param seed seed
|
||||||
*/
|
*/
|
||||||
public void openWebPage(String url) {
|
public void applyStateFromSeed(String seed)
|
||||||
Uri webPage = Uri.parse(url);
|
{
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, webPage);
|
String inputString = layoutContainer.getInput().getText();
|
||||||
if (intent.resolveActivity(getPackageManager()) != null) {
|
SettingsActivity.SettingsSingleton.getInstance()
|
||||||
startActivity(intent);
|
.setPrefMachineType(Enigma.chooseEnigmaFromSeed(seed));
|
||||||
}
|
layoutContainer = LayoutContainer.createLayoutContainer();
|
||||||
}
|
layoutContainer.getEnigma().setStateFromSeed(seed);
|
||||||
|
layoutContainer.setInputPreparer(InputPreparer.createInputPreparer());
|
||||||
|
layoutContainer.syncStateFromEnigmaToLayout();
|
||||||
|
layoutContainer.getInput().setText(inputString);
|
||||||
|
layoutContainer.getOutput().setText("");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singleton that grants access to an Activity from anywhere within the app
|
* Open the web page with the URL url
|
||||||
*/
|
* @param url URL of the website
|
||||||
public static class ActivitySingleton
|
*/
|
||||||
{
|
private void openWebPage(String url) {
|
||||||
private static ActivitySingleton instance = null;
|
Uri webPage = Uri.parse(url);
|
||||||
private Activity activity;
|
Intent intent = new Intent(Intent.ACTION_VIEW, webPage);
|
||||||
|
if (intent.resolveActivity(getPackageManager()) != null) {
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//private constructor
|
/**
|
||||||
private ActivitySingleton(){}
|
* Singleton that grants access to an Activity from anywhere within the app
|
||||||
//Singleton method
|
*/
|
||||||
public static ActivitySingleton getInstance()
|
public static class ActivitySingleton
|
||||||
{
|
{
|
||||||
if(instance == null) instance = new ActivitySingleton();
|
private static ActivitySingleton instance = null;
|
||||||
return instance;
|
private Activity activity;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
//private constructor
|
||||||
* Set an Activity that the Singleton returns
|
private ActivitySingleton(){}
|
||||||
* @param activity activity that's stored
|
//Singleton method
|
||||||
*/
|
public static ActivitySingleton getInstance()
|
||||||
public void setActivity(Activity activity)
|
{
|
||||||
{
|
if(instance == null) instance = new ActivitySingleton();
|
||||||
this.activity = activity;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the stored Activity
|
* Set an Activity that the Singleton returns
|
||||||
* @return stored Activity
|
* @param activity activity that's stored
|
||||||
*/
|
*/
|
||||||
public Activity getActivity()
|
public void setActivity(Activity activity)
|
||||||
{
|
{
|
||||||
return activity;
|
this.activity = activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Returns the stored Activity
|
||||||
|
* @return stored Activity
|
||||||
|
*/
|
||||||
|
public Activity getActivity()
|
||||||
|
{
|
||||||
|
return activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
268
app/src/main/java/de/vanitasvitae/enigmandroid/SettingsActivity.java
Executable file → Normal file
|
@ -1,34 +1,254 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package de.vanitasvitae.enigmandroid;
|
package de.vanitasvitae.enigmandroid;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceActivity;
|
import android.preference.PreferenceActivity;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that represents the settings activity.
|
* Class that represents the settings activity.
|
||||||
* Copyright (C) 2015 Paul Schaub
|
* Use the singleton to get an instance of this class to get preferences
|
||||||
|
|
||||||
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 SettingsActivity extends PreferenceActivity
|
public class SettingsActivity extends PreferenceActivity
|
||||||
{
|
{
|
||||||
@Override
|
public static final String PREF_NUMERIC_LANGUAGE = "prefNumericLanguage";
|
||||||
protected void onCreate(Bundle savedInstanceState)
|
public static final String PREF_MACHINE_TYPE = "prefMachineType";
|
||||||
{
|
public static final String PREF_MESSAGE_FORMATTING = "prefMessageFormatting";
|
||||||
super.onCreate(savedInstanceState);
|
public static final String PREF_REPLACE_SPECIAL_CHARACTERS = "prefReplaceSpecialCharacters";
|
||||||
//noinspection deprecation
|
public static final String PREF_SAVED_ENIGMA_STATE = "prefSavedEnigmaState";
|
||||||
addPreferencesFromResource(R.xml.pref_page);
|
public static final String PREF_VERSION_NUMBER = "prefVersionNumber";
|
||||||
}
|
|
||||||
}
|
private String previousPrefNumericLanguage;
|
||||||
|
private String previousPrefMachineType;
|
||||||
|
private String previousPrefMessageFormatting;
|
||||||
|
private boolean previousPrefReplaceSpecialCharacters;
|
||||||
|
private String previousPrefSavedEnigmaState;
|
||||||
|
|
||||||
|
private SharedPreferences prefs;
|
||||||
|
private Resources res;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
//noinspection deprecation
|
||||||
|
addPreferencesFromResource(R.xml.pref_page);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSharedPreferences(SharedPreferences prefs)
|
||||||
|
{
|
||||||
|
this.prefs = prefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResources(Resources res)
|
||||||
|
{
|
||||||
|
this.res = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isFullyInitialized()
|
||||||
|
{
|
||||||
|
if (prefs == null)
|
||||||
|
{
|
||||||
|
Log.e(MainActivity.APP_ID,
|
||||||
|
"SharedPreferences not initialized via setSharedPreferences!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (res == null)
|
||||||
|
{
|
||||||
|
Log.e(MainActivity.APP_ID, "Resources not initialized via setResources!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefNumericLanguage()
|
||||||
|
{
|
||||||
|
if (isFullyInitialized())
|
||||||
|
return prefs.getString(
|
||||||
|
PREF_NUMERIC_LANGUAGE,
|
||||||
|
res.getStringArray(R.array.pref_alias_message_formatting)[0]);
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrefNumericLanguage(String lang)
|
||||||
|
{
|
||||||
|
if (isFullyInitialized())
|
||||||
|
prefs.edit().putString(PREF_NUMERIC_LANGUAGE, lang).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean prefNumericLanguageChanged()
|
||||||
|
{
|
||||||
|
if (this.previousPrefNumericLanguage == null || !this.previousPrefNumericLanguage.equals(
|
||||||
|
getPrefNumericLanguage()))
|
||||||
|
{
|
||||||
|
this.previousPrefNumericLanguage = this.getPrefNumericLanguage();
|
||||||
|
Log.d(MainActivity.APP_ID, PREF_NUMERIC_LANGUAGE+" changed!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether special characters will be replaced.
|
||||||
|
* If the SettingsActivity is not fully initialized return false and ignore preference.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean getPrefReplaceSpecialCharacters()
|
||||||
|
{
|
||||||
|
return isFullyInitialized() && prefs.getBoolean(PREF_REPLACE_SPECIAL_CHARACTERS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrefReplaceSpecialCharacters(boolean replace)
|
||||||
|
{
|
||||||
|
if (isFullyInitialized())
|
||||||
|
prefs.edit().putBoolean(PREF_REPLACE_SPECIAL_CHARACTERS, replace).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean prefReplaceSpecialCharactersChanged()
|
||||||
|
{
|
||||||
|
boolean changed = previousPrefReplaceSpecialCharacters != getPrefReplaceSpecialCharacters();
|
||||||
|
if (changed)
|
||||||
|
{
|
||||||
|
previousPrefReplaceSpecialCharacters = getPrefReplaceSpecialCharacters();
|
||||||
|
Log.d(MainActivity.APP_ID, PREF_REPLACE_SPECIAL_CHARACTERS+" changed!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefMachineType()
|
||||||
|
{
|
||||||
|
if (isFullyInitialized())
|
||||||
|
return prefs.getString(PREF_MACHINE_TYPE,
|
||||||
|
res.getStringArray(R.array.pref_alias_machine_type)[0]);
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrefMachineType(String pref)
|
||||||
|
{
|
||||||
|
if (isFullyInitialized())
|
||||||
|
prefs.edit().putString(PREF_MACHINE_TYPE, pref).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean prefMachineTypeChanged()
|
||||||
|
{
|
||||||
|
if (this.previousPrefMachineType == null || !this.previousPrefMachineType.equals(
|
||||||
|
getPrefMachineType()))
|
||||||
|
{
|
||||||
|
this.previousPrefMachineType = this.getPrefMachineType();
|
||||||
|
Log.d(MainActivity.APP_ID, PREF_MACHINE_TYPE+" changed!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefSavedEnigmaState()
|
||||||
|
{
|
||||||
|
if (isFullyInitialized())
|
||||||
|
return prefs.getString(PREF_SAVED_ENIGMA_STATE, "-1");
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param state HEX
|
||||||
|
*/
|
||||||
|
public void setPrefSavedEnigmaState(String state)
|
||||||
|
{
|
||||||
|
if (isFullyInitialized())
|
||||||
|
prefs.edit().putString(PREF_SAVED_ENIGMA_STATE, state).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean prefSavedEnigmaStateChanged()
|
||||||
|
{
|
||||||
|
if (this.previousPrefSavedEnigmaState == null || !this.previousPrefSavedEnigmaState
|
||||||
|
.equals(getPrefSavedEnigmaState()))
|
||||||
|
{
|
||||||
|
this.previousPrefSavedEnigmaState = this.getPrefSavedEnigmaState();
|
||||||
|
Log.d(MainActivity.APP_ID, PREF_SAVED_ENIGMA_STATE+" changed!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefMessageFormatting()
|
||||||
|
{
|
||||||
|
if (isFullyInitialized())
|
||||||
|
return prefs.getString(SettingsActivity.PREF_MESSAGE_FORMATTING,
|
||||||
|
res.getStringArray(R.array.pref_alias_message_formatting)[0]);
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrefMessageFormatting(String format)
|
||||||
|
{
|
||||||
|
if (isFullyInitialized())
|
||||||
|
prefs.edit().putString(PREF_MESSAGE_FORMATTING, format).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean prefMessageFormattingChanged()
|
||||||
|
{
|
||||||
|
if (this.previousPrefMessageFormatting == null || !this.previousPrefMessageFormatting
|
||||||
|
.equals(getPrefMessageFormatting()))
|
||||||
|
{
|
||||||
|
this.previousPrefMessageFormatting = this.getPrefMessageFormatting();
|
||||||
|
Log.d(MainActivity.APP_ID, PREF_MESSAGE_FORMATTING+" changed!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersionNumber()
|
||||||
|
{
|
||||||
|
if (isFullyInitialized())
|
||||||
|
return prefs.getInt(PREF_VERSION_NUMBER, -1);
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersionNumber(int v)
|
||||||
|
{
|
||||||
|
if (isFullyInitialized())
|
||||||
|
prefs.edit().putInt(PREF_VERSION_NUMBER, v).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SettingsSingleton extends SettingsActivity
|
||||||
|
{
|
||||||
|
private static SettingsActivity instance;
|
||||||
|
|
||||||
|
private SettingsSingleton()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SettingsActivity getInstance(SharedPreferences prefs, Resources res)
|
||||||
|
{
|
||||||
|
instance = new SettingsActivity();
|
||||||
|
instance.setSharedPreferences(prefs);
|
||||||
|
instance.setResources(res);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SettingsActivity getInstance()
|
||||||
|
{
|
||||||
|
if (instance == null)
|
||||||
|
{
|
||||||
|
instance = new SettingsActivity();
|
||||||
|
Log.d(MainActivity.APP_ID, "Created new SettingsActivity!");
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,168 +1,291 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package de.vanitasvitae.enigmandroid.enigma;
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import de.vanitasvitae.enigmandroid.MainActivity;
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
import de.vanitasvitae.enigmandroid.enigma.inputPreparer.InputPreparer;
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main component of the Enigma machine
|
* Main component of the Enigma machine
|
||||||
* This is the mostly abstract base of any enigma machine.
|
* This is the mostly abstract base of any enigma machine.
|
||||||
* Copyright (C) 2015 Paul Schaub
|
* 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
|
public abstract class Enigma
|
||||||
{
|
{
|
||||||
protected static String machineType;
|
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;
|
|
||||||
|
|
||||||
/**
|
boolean doAnomaly = false; //Has the time come to handle an anomaly?
|
||||||
* Set the enigma to an initial state
|
|
||||||
*/
|
|
||||||
public abstract void initialize();
|
|
||||||
|
|
||||||
/**
|
ArrayList<EntryWheel> availableEntryWheels;
|
||||||
* Set the reflector of the enigma machine to one of type type.
|
ArrayList<Rotor> availableRotors;
|
||||||
* @param type type indicator of the reflector
|
ArrayList<Reflector> availableReflectors;
|
||||||
* @return success (not every reflector fits in every machine)
|
|
||||||
*/
|
|
||||||
public abstract boolean setReflector(int type);
|
|
||||||
|
|
||||||
/**
|
Random rand;
|
||||||
* 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);
|
|
||||||
|
|
||||||
/**
|
Enigma()
|
||||||
* Encrypt / Decrypt a given String w.
|
{
|
||||||
* w must be prepared using prepare(w) beforehand.
|
establishAvailableParts();
|
||||||
* Doing so changes the state of the rotors but not the state of the plugboard and the
|
initialize();
|
||||||
* 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.
|
* In this method, available EntryWheels, Rotors and Reflectors can be defined.
|
||||||
* This rotates the first rotor and eventually also the second/third.
|
*/
|
||||||
* Also this method handles the anomaly in case it should happen.
|
protected abstract void establishAvailableParts();
|
||||||
*/
|
|
||||||
public abstract void nextState();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Substitute char k by sending the signal through the enigma.
|
* Add a Rotor to the ArrayList of available rotors for this machine.
|
||||||
* The signal passes the plugboard, the rotors and returns back after going through the
|
* Also set the index of the Rotor.
|
||||||
* reflector wheel.
|
* @param r Rotor
|
||||||
*
|
*/
|
||||||
* @param k input char
|
void addAvailableRotor(Rotor r)
|
||||||
* @return substituted output char
|
{
|
||||||
*/
|
if(availableRotors == null) availableRotors = new ArrayList<>();
|
||||||
public abstract char encryptChar(char k);
|
availableRotors.add(availableRotors.size(), r.setIndex(availableRotors.size()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
void addAvailableEntryWheel(EntryWheel e)
|
||||||
* Normalize the input.
|
{
|
||||||
* Normalizing means keeping the input via modulo in the range from 0 to n-1, where n is equal
|
if(availableEntryWheels == null) availableEntryWheels = new ArrayList<>();
|
||||||
* to the size of the rotors.
|
availableEntryWheels.add(availableEntryWheels.size(), e.setIndex(availableEntryWheels.size()));
|
||||||
* 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);
|
|
||||||
|
|
||||||
/**
|
void addAvailableReflector(Reflector r)
|
||||||
* Set config of the enigma
|
{
|
||||||
*
|
if(availableReflectors == null) availableReflectors = new ArrayList<>();
|
||||||
* @param conf configuration
|
availableReflectors.add(availableReflectors.size(), r.setIndex(availableReflectors.size()));
|
||||||
*/
|
}
|
||||||
public abstract void setConfiguration(int[] conf);
|
|
||||||
|
|
||||||
/**
|
public ArrayList<EntryWheel> getAvailableEntryWheels()
|
||||||
* Set the plugboard
|
{
|
||||||
* @param p Plugboard
|
return availableEntryWheels;
|
||||||
*/
|
}
|
||||||
public abstract void setPlugboard(Plugboard p);
|
|
||||||
|
|
||||||
/**
|
public ArrayList<Rotor> getAvailableRotors()
|
||||||
* Return the configuration, the enigma machine is in right NOW
|
{
|
||||||
*
|
return availableRotors;
|
||||||
* @return array containing configuration
|
}
|
||||||
*/
|
|
||||||
public abstract int[] getConfiguration();
|
|
||||||
|
|
||||||
/**
|
public ArrayList<Reflector> getAvailableReflectors()
|
||||||
* Set the inputPreparer
|
{
|
||||||
* @param preparer concrete InputPreparer
|
return availableReflectors;
|
||||||
*/
|
}
|
||||||
public void setInputPreparer(InputPreparer preparer)
|
|
||||||
{
|
|
||||||
this.inputPreparer = preparer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
EntryWheel getEntryWheel(int index)
|
||||||
|
{
|
||||||
|
if(availableEntryWheels == null || availableEntryWheels.size() == 0) return null;
|
||||||
|
return availableEntryWheels.get(index % availableEntryWheels.size()).getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
Rotor getRotor(int index)
|
||||||
|
{
|
||||||
|
if(availableRotors == null || availableRotors.size() == 0) return null;
|
||||||
|
return availableRotors.get(index % availableRotors.size()).getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
Rotor getRotor(int index, int rotation, int ringSetting)
|
||||||
* Return the inputPreparer
|
{
|
||||||
* @return inputPreparer
|
return getRotor(index).setRotation(rotation).setRingSetting(ringSetting);
|
||||||
*/
|
}
|
||||||
public InputPreparer getInputPreparer()
|
|
||||||
{
|
|
||||||
if(inputPreparer == null)
|
|
||||||
{
|
|
||||||
MainActivity main = (MainActivity) MainActivity.ActivitySingleton.getInstance().getActivity();
|
|
||||||
inputPreparer = InputPreparer.createInputPreparer(main.getPrefNumericLanguage());
|
|
||||||
}
|
|
||||||
return this.inputPreparer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
Reflector getReflector(int index)
|
||||||
* set prefAnomaly variable
|
{
|
||||||
* @param b boolean
|
if(availableReflectors == null || availableReflectors.size() == 0) return null;
|
||||||
*/
|
return availableReflectors.get(index%availableReflectors.size()).getInstance();
|
||||||
public void setPrefAnomaly(boolean b)
|
}
|
||||||
{
|
|
||||||
this.prefAnomaly = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
Reflector getReflector(int index, int rotation, int ringSetting)
|
||||||
* Return the type indicator of the enigma machine
|
{
|
||||||
* @return type
|
return getReflector(index).setRotation(rotation).setRingSetting(ringSetting);
|
||||||
*/
|
}
|
||||||
public String getMachineType()
|
|
||||||
{
|
/**
|
||||||
return machineType;
|
* Set the enigma to an initial state
|
||||||
}
|
*/
|
||||||
|
protected abstract void initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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/encryptString
|
||||||
|
* @return encrypted/decrypted string
|
||||||
|
*/
|
||||||
|
public String encryptString(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();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the enigma into a completely random state using a unseeded SecureRandom object.
|
||||||
|
*/
|
||||||
|
public void randomState()
|
||||||
|
{
|
||||||
|
this.rand = ((MainActivity) (MainActivity.ActivitySingleton.getInstance().getActivity()))
|
||||||
|
.getSecureRandom();
|
||||||
|
generateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the enigma to a random state based on the initialization of rand.
|
||||||
|
* Don not choose a rotor twice, set random rotations, ringSettings, ukw and possibly
|
||||||
|
* plugboard / rewirable ukw configurations.
|
||||||
|
*/
|
||||||
|
protected abstract void generateState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
protected abstract char encryptChar(char k);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the state of the enigma
|
||||||
|
* @param state new state
|
||||||
|
*/
|
||||||
|
public abstract void setState(EnigmaStateBundle state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an object representing the current state of the enigma
|
||||||
|
* @return state
|
||||||
|
*/
|
||||||
|
public abstract EnigmaStateBundle getState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the rand into a certain state based on seed.
|
||||||
|
* Then set the enigmas state.
|
||||||
|
* @param seed passphrase
|
||||||
|
*/
|
||||||
|
public void setStateFromSeed(String seed)
|
||||||
|
{
|
||||||
|
rand = new Random(seed.hashCode());
|
||||||
|
generateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void restoreState(BigInteger mem, int protocol_version);
|
||||||
|
|
||||||
|
public BigInteger getEncodedState()
|
||||||
|
{
|
||||||
|
return getEncodedState(MainActivity.latest_protocol_version);
|
||||||
|
}
|
||||||
|
protected abstract BigInteger getEncodedState(int protocol_version);
|
||||||
|
|
||||||
|
private static String numToMachineType(int n)
|
||||||
|
{
|
||||||
|
int m = 13;
|
||||||
|
n = (m+(n+m)%m)%m; //Problem? Trolololo
|
||||||
|
switch (n) {
|
||||||
|
case 0: return "I";
|
||||||
|
case 1: return "M3";
|
||||||
|
case 2: return "M4";
|
||||||
|
case 3: return "G31";
|
||||||
|
case 4: return "G312";
|
||||||
|
case 5: return "G260";
|
||||||
|
case 6: return "D";
|
||||||
|
case 7: return "K";
|
||||||
|
case 8: return "KS";
|
||||||
|
case 9: return "KSA";
|
||||||
|
case 10: return "R";
|
||||||
|
case 11: return "T";
|
||||||
|
case 12: return "KD";
|
||||||
|
default: return "KD";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String chooseEnigmaFromSeed(String seed)
|
||||||
|
{
|
||||||
|
return numToMachineType(seed.hashCode() % 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String chooseEnigmaFromSave(BigInteger save)
|
||||||
|
{
|
||||||
|
return numToMachineType(getValue(save, 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the name indicator of the enigma machine
|
||||||
|
* @return name
|
||||||
|
*/
|
||||||
|
public String getMachineType()
|
||||||
|
{
|
||||||
|
return machineType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param s source
|
||||||
|
* @param d domain (max value) of the value
|
||||||
|
* @return value
|
||||||
|
*/
|
||||||
|
public static int getValue(BigInteger s, int d)
|
||||||
|
{
|
||||||
|
BigInteger o = s.mod(BigInteger.valueOf(d)).add(BigInteger.valueOf(d)).mod(BigInteger.valueOf(d));
|
||||||
|
return Integer.valueOf(o.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove a digit of domain d from source s
|
||||||
|
* @param s source
|
||||||
|
* @param d domain (max value)
|
||||||
|
* @return trimmed source
|
||||||
|
*/
|
||||||
|
public static BigInteger removeDigit(BigInteger s, int d)
|
||||||
|
{
|
||||||
|
s = s.subtract(s.mod(BigInteger.valueOf(d)));
|
||||||
|
s = s.divide(BigInteger.valueOf(d));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param s source
|
||||||
|
* @param b base (max value)
|
||||||
|
* @param v actual value
|
||||||
|
* @return lengthened source
|
||||||
|
*/
|
||||||
|
public static BigInteger addDigit(BigInteger s, int v, int b)
|
||||||
|
{
|
||||||
|
s = s.multiply(BigInteger.valueOf(b));
|
||||||
|
s = s.add(BigInteger.valueOf(v % b));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,208 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that contains a possible state of an enigma machine.
|
||||||
|
* Used to store and transport configuration and settings.
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class EnigmaStateBundle{
|
||||||
|
private String machineType;
|
||||||
|
|
||||||
|
private int typeEntryWheel;
|
||||||
|
|
||||||
|
private int typeRotor1;
|
||||||
|
private int typeRotor2;
|
||||||
|
private int typeRotor3;
|
||||||
|
private int typeRotor4;
|
||||||
|
|
||||||
|
private int rotationRotor1;
|
||||||
|
private int rotationRotor2;
|
||||||
|
private int rotationRotor3;
|
||||||
|
private int rotationRotor4;
|
||||||
|
|
||||||
|
private int ringSettingRotor1;
|
||||||
|
private int ringSettingRotor2;
|
||||||
|
private int ringSettingRotor3;
|
||||||
|
private int ringSettingRotor4;
|
||||||
|
|
||||||
|
private int typeReflector;
|
||||||
|
|
||||||
|
private int rotationReflector;
|
||||||
|
private int ringSettingReflector;
|
||||||
|
|
||||||
|
private int[] configurationPlugboard;
|
||||||
|
|
||||||
|
private int[] configurationReflector;
|
||||||
|
|
||||||
|
// --Commented out by Inspection START (07.11.15 19:46):
|
||||||
|
// public String getMachineType()
|
||||||
|
// {
|
||||||
|
// return this.machineType;
|
||||||
|
// }
|
||||||
|
// --Commented out by Inspection STOP (07.11.15 19:46)
|
||||||
|
|
||||||
|
// --Commented out by Inspection START (07.11.15 19:46):
|
||||||
|
// public void setMachineType(String type)
|
||||||
|
// {
|
||||||
|
// this.machineType = type;
|
||||||
|
// }
|
||||||
|
// --Commented out by Inspection STOP (07.11.15 19:46)
|
||||||
|
|
||||||
|
public int getTypeRotor1() {
|
||||||
|
return typeRotor1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTypeRotor1(int typeRotor1) {
|
||||||
|
this.typeRotor1 = typeRotor1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTypeRotor2() {
|
||||||
|
return typeRotor2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTypeRotor2(int typeRotor2) {
|
||||||
|
this.typeRotor2 = typeRotor2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTypeRotor3() {
|
||||||
|
return typeRotor3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTypeRotor3(int typeRotor3) {
|
||||||
|
this.typeRotor3 = typeRotor3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTypeRotor4() {
|
||||||
|
return typeRotor4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTypeRotor4(int typeRotor4) {
|
||||||
|
this.typeRotor4 = typeRotor4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRotationRotor1() {
|
||||||
|
return rotationRotor1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRotationRotor1(int rotationRotor1) {
|
||||||
|
this.rotationRotor1 = rotationRotor1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRotationRotor2() {
|
||||||
|
return rotationRotor2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRotationRotor2(int rotationRotor2) {
|
||||||
|
this.rotationRotor2 = rotationRotor2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRotationRotor3() {
|
||||||
|
return rotationRotor3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRotationRotor3(int rotationRotor3) {
|
||||||
|
this.rotationRotor3 = rotationRotor3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRotationRotor4() {
|
||||||
|
return rotationRotor4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRotationRotor4(int rotationRotor4) {
|
||||||
|
this.rotationRotor4 = rotationRotor4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRingSettingRotor1() {
|
||||||
|
return ringSettingRotor1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRingSettingRotor1(int ringSettingRotor1) {
|
||||||
|
this.ringSettingRotor1 = ringSettingRotor1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRingSettingRotor2() {
|
||||||
|
return ringSettingRotor2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRingSettingRotor2(int ringSettingRotor2) {
|
||||||
|
this.ringSettingRotor2 = ringSettingRotor2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRingSettingRotor3() {
|
||||||
|
return ringSettingRotor3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRingSettingRotor3(int ringSettingRotor3) {
|
||||||
|
this.ringSettingRotor3 = ringSettingRotor3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRingSettingRotor4() {
|
||||||
|
return ringSettingRotor4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRingSettingRotor4(int ringSettingRotor4) {
|
||||||
|
this.ringSettingRotor4 = ringSettingRotor4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTypeReflector() {
|
||||||
|
return typeReflector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTypeReflector(int typeReflector) {
|
||||||
|
this.typeReflector = typeReflector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTypeEntryWheel() {
|
||||||
|
return typeEntryWheel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTypeEntryWheel(int typeEntryWheel) {
|
||||||
|
this.typeEntryWheel = typeEntryWheel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] getConfigurationPlugboard() {
|
||||||
|
return configurationPlugboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigurationPlugboard(int[] configurationPlugboard) {
|
||||||
|
this.configurationPlugboard = configurationPlugboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] getConfigurationReflector() {
|
||||||
|
return configurationReflector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigurationReflector(int[] configurationReflector) {
|
||||||
|
this.configurationReflector = configurationReflector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRotationReflector() {
|
||||||
|
return rotationReflector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRotationReflector(int rotationReflector) {
|
||||||
|
this.rotationReflector = rotationReflector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRingSettingReflector() {
|
||||||
|
return ringSettingReflector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRingSettingReflector(int ringSettingReflector) {
|
||||||
|
this.ringSettingReflector = ringSettingReflector;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,221 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Plugboard;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of an enigma machine of name D
|
||||||
|
* This machine has a rewirable UKW, non changeable rotors.
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class Enigma_D extends Enigma {
|
||||||
|
|
||||||
|
private EntryWheel entryWheel;
|
||||||
|
private Rotor rotor1;
|
||||||
|
private Rotor rotor2;
|
||||||
|
private Rotor rotor3;
|
||||||
|
private Reflector reflector;
|
||||||
|
|
||||||
|
public Enigma_D()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
machineType = "D";
|
||||||
|
Log.d(MainActivity.APP_ID, "Created Enigma D");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void establishAvailableParts()
|
||||||
|
{
|
||||||
|
addAvailableEntryWheel(new EntryWheel.EntryWheel_QWERTZ());
|
||||||
|
|
||||||
|
addAvailableRotor(new Rotor.Rotor_K_D_I(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_K_D_II(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_K_D_III(0, 0));
|
||||||
|
|
||||||
|
addAvailableReflector(new Reflector.ReflectorEnigma_D_G31());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize()
|
||||||
|
{
|
||||||
|
this.entryWheel = availableEntryWheels.get(0);
|
||||||
|
this.rotor1 = availableRotors.get(0);
|
||||||
|
this.rotor2 = availableRotors.get(1);
|
||||||
|
this.rotor3 = availableRotors.get(2);
|
||||||
|
this.reflector = availableReflectors.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nextState()
|
||||||
|
{
|
||||||
|
rotor1.rotate();
|
||||||
|
if (rotor1.isAtTurnoverPosition() || this.doAnomaly)
|
||||||
|
{
|
||||||
|
rotor2.rotate();
|
||||||
|
this.doAnomaly = rotor2.doubleTurnAnomaly();
|
||||||
|
if (rotor2.isAtTurnoverPosition())
|
||||||
|
{
|
||||||
|
rotor3.rotate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void generateState() {
|
||||||
|
int rot1 = rand.nextInt(26);
|
||||||
|
int rot2 = rand.nextInt(26);
|
||||||
|
int rot3 = rand.nextInt(26);
|
||||||
|
int rotRef = rand.nextInt(26);
|
||||||
|
int ring1 = rand.nextInt(26);
|
||||||
|
int ring2 = rand.nextInt(26);
|
||||||
|
int ring3 = rand.nextInt(26);
|
||||||
|
int ringRef = rand.nextInt(26);
|
||||||
|
|
||||||
|
this.rotor1.setRotation(rot1).setRingSetting(ring1);
|
||||||
|
this.rotor2.setRotation(rot2).setRingSetting(ring2);
|
||||||
|
this.rotor3.setRotation(rot3).setRingSetting(ring3);
|
||||||
|
|
||||||
|
this.reflector.setRotation(rotRef).setRingSetting(ringRef)
|
||||||
|
.setConfiguration(Plugboard.seedToReflectorConfiguration(rand));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 = entryWheel.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting());
|
||||||
|
x = rotor1.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting() + rotor2.getRotation() - rotor2.getRingSetting());
|
||||||
|
x = rotor2.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor2.getRotation() + rotor2.getRingSetting() + rotor3.getRotation() - rotor3.getRingSetting());
|
||||||
|
x = rotor3.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor3.getRotation() + rotor3.getRingSetting() + reflector.getRotation() - reflector.getRingSetting());
|
||||||
|
//backward direction
|
||||||
|
x = reflector.encrypt(x);
|
||||||
|
x = rotor1.normalize(x + rotor3.getRotation() - rotor3.getRingSetting() - reflector.getRotation() + reflector.getRingSetting());
|
||||||
|
x = rotor3.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor2.getRotation() - rotor2.getRingSetting() - rotor3.getRotation() + rotor3.getRingSetting());
|
||||||
|
x = rotor2.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting() - rotor2.getRotation() + rotor2.getRingSetting());
|
||||||
|
x = rotor1.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting());
|
||||||
|
x = entryWheel.encryptBackward(x);
|
||||||
|
return (char) (x + 65); //Add Offset again, cast back to char and return
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
this.entryWheel = getEntryWheel(state.getTypeEntryWheel());
|
||||||
|
this.rotor1 = getRotor(state.getTypeRotor1(), state.getRotationRotor1(), state.getRingSettingRotor1());
|
||||||
|
this.rotor2 = getRotor(state.getTypeRotor2(), state.getRotationRotor2(), state.getRingSettingRotor2());
|
||||||
|
this.rotor3 = getRotor(state.getTypeRotor3(), state.getRotationRotor3(), state.getRingSettingRotor3());
|
||||||
|
this.reflector = getReflector(state.getTypeReflector(),
|
||||||
|
state.getRotationReflector(),
|
||||||
|
state.getRingSettingReflector())
|
||||||
|
.setConfiguration(state.getConfigurationReflector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnigmaStateBundle getState()
|
||||||
|
{
|
||||||
|
EnigmaStateBundle state = new EnigmaStateBundle();
|
||||||
|
|
||||||
|
state.setTypeEntryWheel(entryWheel.getIndex());
|
||||||
|
|
||||||
|
state.setTypeRotor1(rotor1.getIndex());
|
||||||
|
state.setTypeRotor2(rotor2.getIndex());
|
||||||
|
state.setTypeRotor3(rotor3.getIndex());
|
||||||
|
|
||||||
|
state.setRotationRotor1(rotor1.getRotation());
|
||||||
|
state.setRotationRotor2(rotor2.getRotation());
|
||||||
|
state.setRotationRotor3(rotor3.getRotation());
|
||||||
|
|
||||||
|
state.setRingSettingRotor1(rotor1.getRingSetting());
|
||||||
|
state.setRingSettingRotor2(rotor2.getRingSetting());
|
||||||
|
state.setRingSettingRotor3(rotor3.getRingSetting());
|
||||||
|
|
||||||
|
state.setTypeReflector(reflector.getIndex());
|
||||||
|
state.setRotationReflector(reflector.getRotation());
|
||||||
|
state.setRingSettingReflector(reflector.getRingSetting());
|
||||||
|
state.setConfigurationReflector(reflector.getConfiguration());
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreState(BigInteger s, int protocol_version)
|
||||||
|
{
|
||||||
|
switch(protocol_version)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
int rot1 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring1 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rot2 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring2 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rot3 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring3 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rotRef = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ringRef = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
|
||||||
|
this.rotor1 = getRotor(0, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(1, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(2, rot3, ring3);
|
||||||
|
this.reflector = getReflector(0, rotRef, ringRef);
|
||||||
|
this.reflector.setConfiguration(s);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: Log.e(MainActivity.APP_ID, "Unsupported protocol version "+protocol_version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getEncodedState(int protocol_version) {
|
||||||
|
BigInteger s = Plugboard.configurationToBigInteger(reflector.getConfiguration());
|
||||||
|
s = addDigit(s, reflector.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, reflector.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRotation(), 26);
|
||||||
|
|
||||||
|
s = addDigit(s, 6, 20); //Machine #6
|
||||||
|
s = addDigit(s, protocol_version, MainActivity.max_protocol_version);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the Enigma machine of name G31 (Abwehr)
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class Enigma_G260 extends Enigma_G31
|
||||||
|
{
|
||||||
|
public Enigma_G260()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
machineType = "G260";
|
||||||
|
Log.d(MainActivity.APP_ID, "Created Enigma G260");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void establishAvailableParts()
|
||||||
|
{
|
||||||
|
addAvailableEntryWheel(new EntryWheel.EntryWheel_QWERTZ());
|
||||||
|
addAvailableRotor(new Rotor.Rotor_G260_I(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_G260_II(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_G260_III(0, 0));
|
||||||
|
addAvailableReflector(new Reflector.Reflector_K_G260());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getEncodedState(int protocol_version)
|
||||||
|
{
|
||||||
|
BigInteger s = BigInteger.valueOf(reflector.getRingSetting());
|
||||||
|
s = addDigit(s, reflector.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRotation(), 26);
|
||||||
|
|
||||||
|
s = addDigit(s, rotor3.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor2.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor1.getIndex(), availableRotors.size());
|
||||||
|
|
||||||
|
s = addDigit(s, 5, 20); //Machine #5
|
||||||
|
s = addDigit(s, protocol_version, MainActivity.max_protocol_version);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,230 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the Enigma machine of name G31 (Abwehr)
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class Enigma_G31 extends Enigma
|
||||||
|
{
|
||||||
|
private EntryWheel entryWheel;
|
||||||
|
Rotor rotor1;
|
||||||
|
Rotor rotor2;
|
||||||
|
Rotor rotor3;
|
||||||
|
Reflector reflector;
|
||||||
|
|
||||||
|
public Enigma_G31()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
machineType = "G31";
|
||||||
|
Log.d(MainActivity.APP_ID, "Created Enigma G31");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void establishAvailableParts()
|
||||||
|
{
|
||||||
|
addAvailableEntryWheel(new EntryWheel.EntryWheel_QWERTZ());
|
||||||
|
addAvailableRotor(new Rotor.Rotor_G31_I(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_G31_II(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_G31_III(0, 0));
|
||||||
|
addAvailableReflector(new Reflector.ReflectorEnigma_D_G31());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize()
|
||||||
|
{
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(0);
|
||||||
|
this.rotor2 = getRotor(1);
|
||||||
|
this.rotor3 = getRotor(2);
|
||||||
|
this.reflector = getReflector(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nextState()
|
||||||
|
{
|
||||||
|
rotor1.rotate();
|
||||||
|
if (rotor1.isAtTurnoverPosition())
|
||||||
|
{
|
||||||
|
rotor2.rotate();
|
||||||
|
if (rotor2.isAtTurnoverPosition())
|
||||||
|
{
|
||||||
|
rotor3.rotate();
|
||||||
|
if(rotor3.isAtTurnoverPosition())
|
||||||
|
{
|
||||||
|
reflector.setRotation(reflector.getRotation()+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void generateState()
|
||||||
|
{
|
||||||
|
int r1, r2=-1, r3;
|
||||||
|
r1 = rand.nextInt(3);
|
||||||
|
while(r2 == -1 || r2 == r1) r2 = rand.nextInt(3);
|
||||||
|
r3 = 3 - r1 - r2;
|
||||||
|
|
||||||
|
int rot1 = rand.nextInt(26);
|
||||||
|
int rot2 = rand.nextInt(26);
|
||||||
|
int rot3 = rand.nextInt(26);
|
||||||
|
int rotRef = rand.nextInt(26);
|
||||||
|
int ring1 = rand.nextInt(26);
|
||||||
|
int ring2 = rand.nextInt(26);
|
||||||
|
int ring3 = rand.nextInt(26);
|
||||||
|
int ringRef = rand.nextInt(26);
|
||||||
|
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.reflector = getReflector(0, rotRef, ringRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 = entryWheel.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting());
|
||||||
|
x = rotor1.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting() + rotor2.getRotation() - rotor2.getRingSetting());
|
||||||
|
x = rotor2.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor2.getRotation() + rotor2.getRingSetting() + rotor3.getRotation() - rotor3.getRingSetting());
|
||||||
|
x = rotor3.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor3.getRotation() + rotor3.getRingSetting() + reflector.getRotation() - reflector.getRingSetting());
|
||||||
|
//backward direction
|
||||||
|
x = reflector.encrypt(x);
|
||||||
|
x = rotor1.normalize(x + rotor3.getRotation() - rotor3.getRingSetting() - reflector.getRotation() + reflector.getRingSetting());
|
||||||
|
x = rotor3.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor2.getRotation() - rotor2.getRingSetting() - rotor3.getRotation() + rotor3.getRingSetting());
|
||||||
|
x = rotor2.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting() - rotor2.getRotation() + rotor2.getRingSetting());
|
||||||
|
x = rotor1.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting());
|
||||||
|
x = entryWheel.encryptBackward(x);
|
||||||
|
return (char) (x + 65); //Add Offset again, cast back to char and return
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
this.entryWheel = getEntryWheel(state.getTypeEntryWheel());
|
||||||
|
this.rotor1 = getRotor(state.getTypeRotor1(), state.getRotationRotor1(), state.getRingSettingRotor1());
|
||||||
|
this.rotor2 = getRotor(state.getTypeRotor2(), state.getRotationRotor2(), state.getRingSettingRotor2());
|
||||||
|
this.rotor3 = getRotor(state.getTypeRotor3(), state.getRotationRotor3(), state.getRingSettingRotor3());
|
||||||
|
this.reflector = getReflector(state.getTypeReflector(),
|
||||||
|
state.getRotationReflector(), state.getRingSettingReflector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnigmaStateBundle getState() {
|
||||||
|
EnigmaStateBundle state = new EnigmaStateBundle();
|
||||||
|
|
||||||
|
state.setTypeEntryWheel(entryWheel.getIndex());
|
||||||
|
|
||||||
|
state.setTypeRotor1(rotor1.getIndex());
|
||||||
|
state.setTypeRotor2(rotor2.getIndex());
|
||||||
|
state.setTypeRotor3(rotor3.getIndex());
|
||||||
|
|
||||||
|
state.setRotationRotor1(rotor1.getRotation());
|
||||||
|
state.setRotationRotor2(rotor2.getRotation());
|
||||||
|
state.setRotationRotor3(rotor3.getRotation());
|
||||||
|
|
||||||
|
state.setRingSettingRotor1(rotor1.getRingSetting());
|
||||||
|
state.setRingSettingRotor2(rotor2.getRingSetting());
|
||||||
|
state.setRingSettingRotor3(rotor3.getRingSetting());
|
||||||
|
|
||||||
|
state.setTypeReflector(reflector.getIndex());
|
||||||
|
state.setRotationReflector(reflector.getRotation());
|
||||||
|
state.setRingSettingReflector(reflector.getRingSetting());
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreState(BigInteger s, int protocol_version)
|
||||||
|
{
|
||||||
|
switch (protocol_version)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
int r1 = getValue(s, availableRotors.size());
|
||||||
|
s = removeDigit(s, availableRotors.size());
|
||||||
|
int r2 = getValue(s, availableRotors.size());
|
||||||
|
s = removeDigit(s, availableRotors.size());
|
||||||
|
int r3 = getValue(s, availableRotors.size());
|
||||||
|
s = removeDigit(s, availableRotors.size());
|
||||||
|
|
||||||
|
int rot1 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring1 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rot2 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring2 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rot3 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring3 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rotRef = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ringRef = getValue(s, 26);
|
||||||
|
|
||||||
|
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.reflector = getReflector(0, rotRef, ringRef);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: Log.e(MainActivity.APP_ID, "Unsupported protocol version "+protocol_version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getEncodedState(int protocol_version)
|
||||||
|
{
|
||||||
|
BigInteger s = BigInteger.valueOf(reflector.getRingSetting());
|
||||||
|
s = addDigit(s, reflector.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRotation(), 26);
|
||||||
|
|
||||||
|
s = addDigit(s, rotor3.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor2.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor1.getIndex(), availableRotors.size());
|
||||||
|
|
||||||
|
s = addDigit(s, 3, 20); //Machine #3
|
||||||
|
s = addDigit(s, protocol_version, MainActivity.max_protocol_version);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the Enigma machine of name G31 (Abwehr)
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class Enigma_G312 extends Enigma_G31
|
||||||
|
{
|
||||||
|
public Enigma_G312()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
machineType = "G312";
|
||||||
|
Log.d(MainActivity.APP_ID, "Created Enigma G312");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void establishAvailableParts()
|
||||||
|
{
|
||||||
|
addAvailableEntryWheel(new EntryWheel.EntryWheel_QWERTZ());
|
||||||
|
addAvailableRotor(new Rotor.Rotor_G312_I(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_G312_II(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_G312_III(0, 0));
|
||||||
|
addAvailableReflector(new Reflector.Reflector_G312());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getEncodedState(int protocol_version)
|
||||||
|
{
|
||||||
|
BigInteger s = BigInteger.valueOf(reflector.getRingSetting());
|
||||||
|
s = addDigit(s, reflector.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRotation(), 26);
|
||||||
|
|
||||||
|
s = addDigit(s, rotor3.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor2.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor1.getIndex(), availableRotors.size());
|
||||||
|
|
||||||
|
s = addDigit(s, 4, 20); //Machine #4
|
||||||
|
s = addDigit(s, protocol_version, MainActivity.max_protocol_version);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,171 +1,239 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package de.vanitasvitae.enigmandroid.enigma;
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import de.vanitasvitae.enigmandroid.enigma.rotors.Reflector;
|
import java.math.BigInteger;
|
||||||
import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor;
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Plugboard;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implementation of an enigma machine of type I
|
* Concrete implementation of an enigma machine of name I
|
||||||
* Copyright (C) 2015 Paul Schaub
|
* 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 {
|
public class Enigma_I extends Enigma
|
||||||
protected Rotor rotor1;
|
{
|
||||||
protected Rotor rotor2;
|
EntryWheel entryWheel;
|
||||||
protected Rotor rotor3;
|
Rotor rotor1;
|
||||||
|
Rotor rotor2;
|
||||||
|
Rotor rotor3;
|
||||||
|
Reflector reflector;
|
||||||
|
|
||||||
protected Reflector reflector;
|
Plugboard plugboard;
|
||||||
|
|
||||||
protected Plugboard plugboard;
|
public Enigma_I()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
machineType = "I";
|
||||||
|
Log.d(MainActivity.APP_ID, "Created Enigma I");
|
||||||
|
}
|
||||||
|
|
||||||
public Enigma_I() {
|
@Override
|
||||||
machineType = "I";
|
protected void establishAvailableParts() {
|
||||||
}
|
addAvailableEntryWheel(new EntryWheel.EntryWheel_ABCDEF());
|
||||||
|
addAvailableRotor(new Rotor.Rotor_I(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_II(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_III(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_IV(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_V(0,0));
|
||||||
|
addAvailableReflector(new Reflector.Reflector_A());
|
||||||
|
addAvailableReflector(new Reflector.Reflector_B());
|
||||||
|
addAvailableReflector(new Reflector.Reflector_C());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize()
|
public void initialize()
|
||||||
{
|
{
|
||||||
this.setPlugboard(new Plugboard());
|
this.plugboard= new Plugboard();
|
||||||
//I,II,III, A, 0,0,0, 0,0,0
|
this.entryWheel = getEntryWheel(0);
|
||||||
this.setConfiguration(new int[]{1,2,3,1,0,0,0,0,0,0});
|
this.rotor1 = getRotor(0, 0, 0);
|
||||||
}
|
this.rotor2 = getRotor(1, 0, 0);
|
||||||
|
this.rotor3 = getRotor(2, 0, 0);
|
||||||
|
this.reflector = getReflector(0);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextState()
|
public void nextState()
|
||||||
{
|
{
|
||||||
rotor1.rotate();
|
rotor1.rotate();
|
||||||
if (rotor1.isAtTurnoverPosition() || (this.doAnomaly && prefAnomaly))
|
if (rotor1.isAtTurnoverPosition() || this.doAnomaly)
|
||||||
{
|
{
|
||||||
rotor2.rotate();
|
rotor2.rotate();
|
||||||
this.doAnomaly = rotor2.doubleTurnAnomaly();
|
this.doAnomaly = rotor2.doubleTurnAnomaly();
|
||||||
if (rotor2.isAtTurnoverPosition())
|
if (rotor2.isAtTurnoverPosition())
|
||||||
{
|
{
|
||||||
rotor3.rotate();
|
rotor3.rotate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char encryptChar(char k)
|
protected void generateState() {
|
||||||
{
|
int r1, r2=-1, r3=-1;
|
||||||
nextState();
|
r1 = rand.nextInt(5);
|
||||||
int x = ((int) k)-65; //Cast to int and remove Unicode Offset (A=65 in Unicode.)
|
while(r2 == -1 || r2 == r1) r2 = rand.nextInt(5);
|
||||||
//Encryption
|
while(r3 == -1 || r3 == r2 || r3 == r1) r3 = rand.nextInt(5);
|
||||||
//forward direction
|
int ref = rand.nextInt(3);
|
||||||
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
|
int rot1 = rand.nextInt(26);
|
||||||
public int normalize(int input) {
|
int rot2 = rand.nextInt(26);
|
||||||
return (input+26) % 26;
|
int rot3 = rand.nextInt(26);
|
||||||
}
|
int ring1 = rand.nextInt(26);
|
||||||
|
int ring2 = rand.nextInt(26);
|
||||||
|
int ring3 = rand.nextInt(26);
|
||||||
|
|
||||||
@Override
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
public void setPlugboard(Plugboard p)
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
{
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
this.plugboard = p;
|
this.reflector = getReflector(ref);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
this.plugboard = new Plugboard();
|
||||||
public int[] getConfiguration()
|
plugboard.setConfiguration(Plugboard.seedToPlugboardConfiguration(rand));
|
||||||
{
|
}
|
||||||
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
|
@Override
|
||||||
/**
|
public char encryptChar(char k)
|
||||||
* conf:
|
{
|
||||||
* 0..2 -> rotor1..rotor3 type
|
nextState();
|
||||||
* 3 -> reflector type
|
int x = ((int) k)-65; //Cast to int and remove Unicode Offset (A=65 in Unicode.)
|
||||||
* 4..6 -> rotor1..rotor3 rotation
|
//Encryption
|
||||||
* 7..9 -> rotor1..rotor3 ringSetting
|
//forward direction
|
||||||
*/
|
x = plugboard.encrypt(x);
|
||||||
public void setConfiguration(int[] conf)
|
x = entryWheel.encryptForward(x);
|
||||||
{
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting());
|
||||||
this.setRotor(1,conf[0],conf[7],conf[4]);
|
x = rotor1.encryptForward(x);
|
||||||
this.setRotor(2,conf[1],conf[8],conf[5]);
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting() + rotor2.getRotation() - rotor2.getRingSetting());
|
||||||
this.setRotor(3,conf[2],conf[9],conf[6]);
|
x = rotor2.encryptForward(x);
|
||||||
this.setReflector(conf[3]);
|
x = rotor1.normalize(x - rotor2.getRotation() + rotor2.getRingSetting() + rotor3.getRotation() - rotor3.getRingSetting());
|
||||||
}
|
x = rotor3.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor3.getRotation() + rotor3.getRingSetting());
|
||||||
|
//backward direction
|
||||||
|
x = reflector.encrypt(x);
|
||||||
|
x = rotor1.normalize(x + rotor3.getRotation() - rotor3.getRingSetting());
|
||||||
|
x = rotor3.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor2.getRotation() - rotor2.getRingSetting() - rotor3.getRotation() + rotor3.getRingSetting());
|
||||||
|
x = rotor2.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting() - rotor2.getRotation() + rotor2.getRingSetting());
|
||||||
|
x = rotor1.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting());
|
||||||
|
x = entryWheel.encryptBackward(x);
|
||||||
|
x = plugboard.encrypt(x);
|
||||||
|
return (char) (x + 65); //Add Offset again, cast back to char and return
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setRotor(int pos, int type, int ringSetting, int rotation)
|
public void setState(EnigmaStateBundle state)
|
||||||
{
|
{
|
||||||
if(pos >= 1 && pos <= 3) {
|
plugboard.setConfiguration(state.getConfigurationPlugboard());
|
||||||
if (type >= 1 && type <= 5) {
|
entryWheel = getEntryWheel(state.getTypeEntryWheel());
|
||||||
Rotor rotor = Rotor.createRotor(type, ringSetting, rotation);
|
rotor1 = getRotor(state.getTypeRotor1(), state.getRotationRotor1(), state.getRingSettingRotor1());
|
||||||
switch (pos) {
|
rotor2 = getRotor(state.getTypeRotor2(), state.getRotationRotor2(), state.getRingSettingRotor2());
|
||||||
case 1:
|
rotor3 = getRotor(state.getTypeRotor3(), state.getRotationRotor3(), state.getRingSettingRotor3());
|
||||||
rotor1 = rotor;
|
reflector = getReflector(state.getTypeReflector());
|
||||||
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
|
@Override
|
||||||
public boolean setReflector(int type)
|
public EnigmaStateBundle getState()
|
||||||
{
|
{
|
||||||
if(type >= 1 && type <= 3)
|
EnigmaStateBundle state = new EnigmaStateBundle();
|
||||||
{
|
|
||||||
reflector = Reflector.createReflector(type);
|
state.setConfigurationPlugboard(plugboard.getConfiguration());
|
||||||
return true;
|
|
||||||
}
|
state.setTypeEntryWheel(entryWheel.getIndex());
|
||||||
Log.d("EnigmAndroid/I/setRef", "Error: Can't set type "+type);
|
|
||||||
return false;
|
state.setTypeRotor1(rotor1.getIndex());
|
||||||
}
|
state.setTypeRotor2(rotor2.getIndex());
|
||||||
|
state.setTypeRotor3(rotor3.getIndex());
|
||||||
|
|
||||||
|
state.setTypeReflector(reflector.getIndex());
|
||||||
|
|
||||||
|
state.setRotationRotor1(rotor1.getRotation());
|
||||||
|
state.setRotationRotor2(rotor2.getRotation());
|
||||||
|
state.setRotationRotor3(rotor3.getRotation());
|
||||||
|
|
||||||
|
state.setRingSettingRotor1(rotor1.getRingSetting());
|
||||||
|
state.setRingSettingRotor2(rotor2.getRingSetting());
|
||||||
|
state.setRingSettingRotor3(rotor3.getRingSetting());
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreState(BigInteger s, int protocol_version)
|
||||||
|
{
|
||||||
|
switch (protocol_version)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
int r1 = getValue(s, availableRotors.size());
|
||||||
|
s = removeDigit(s, availableRotors.size());
|
||||||
|
int r2 = getValue(s, availableRotors.size());
|
||||||
|
s = removeDigit(s, availableRotors.size());
|
||||||
|
int r3 = getValue(s, availableRotors.size());
|
||||||
|
s = removeDigit(s, availableRotors.size());
|
||||||
|
int ref = getValue(s, availableReflectors.size());
|
||||||
|
s = removeDigit(s, availableReflectors.size());
|
||||||
|
int rot1 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring1 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rot2 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring2 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rot3 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring3 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.reflector = getReflector(ref);
|
||||||
|
|
||||||
|
this.plugboard = new Plugboard();
|
||||||
|
plugboard.setConfiguration(s);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: Log.e(MainActivity.APP_ID, "Unsupported protocol version "+protocol_version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getEncodedState(int protocol_version) {
|
||||||
|
BigInteger s = Plugboard.configurationToBigInteger(plugboard.getConfiguration());
|
||||||
|
s = addDigit(s, rotor3.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRotation(), 26);
|
||||||
|
|
||||||
|
s = addDigit(s, reflector.getIndex(), availableReflectors.size());
|
||||||
|
s = addDigit(s, rotor3.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor2.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor1.getIndex(), availableRotors.size());
|
||||||
|
|
||||||
|
s = addDigit(s, 0, 20); //Machine #0
|
||||||
|
s = addDigit(s, protocol_version, MainActivity.max_protocol_version);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,227 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the Enigma machine of name K
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class Enigma_K extends Enigma
|
||||||
|
{
|
||||||
|
private EntryWheel entryWheel;
|
||||||
|
Rotor rotor1;
|
||||||
|
Rotor rotor2;
|
||||||
|
Rotor rotor3;
|
||||||
|
Reflector reflector;
|
||||||
|
|
||||||
|
public Enigma_K()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
machineType = "K";
|
||||||
|
Log.d(MainActivity.APP_ID, "Created Enigma K");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void establishAvailableParts()
|
||||||
|
{
|
||||||
|
addAvailableEntryWheel(new EntryWheel.EntryWheel_QWERTZ());
|
||||||
|
addAvailableRotor(new Rotor.Rotor_K_D_I(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_K_D_II(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_K_D_III(0,0));
|
||||||
|
addAvailableReflector(new Reflector.Reflector_K_G260());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize()
|
||||||
|
{
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(0, 0, 0);
|
||||||
|
this.rotor2 = getRotor(1, 0, 0);
|
||||||
|
this.rotor3 = getRotor(2, 0, 0);
|
||||||
|
this.reflector = getReflector(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nextState()
|
||||||
|
{
|
||||||
|
rotor1.rotate();
|
||||||
|
if (rotor1.isAtTurnoverPosition() || this.doAnomaly)
|
||||||
|
{
|
||||||
|
rotor2.rotate();
|
||||||
|
this.doAnomaly = rotor2.doubleTurnAnomaly();
|
||||||
|
if (rotor2.isAtTurnoverPosition())
|
||||||
|
{
|
||||||
|
rotor3.rotate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void generateState() {
|
||||||
|
int r1, r2=-1, r3;
|
||||||
|
r1 = rand.nextInt(3);
|
||||||
|
while(r2 == -1 || r2 == r1) r2 = rand.nextInt(3);
|
||||||
|
r3 = 3 - r1 - r2;
|
||||||
|
|
||||||
|
int rot1 = rand.nextInt(26);
|
||||||
|
int rot2 = rand.nextInt(26);
|
||||||
|
int rot3 = rand.nextInt(26);
|
||||||
|
int rotRef = rand.nextInt(26);
|
||||||
|
int ring1 = rand.nextInt(26);
|
||||||
|
int ring2 = rand.nextInt(26);
|
||||||
|
int ring3 = rand.nextInt(26);
|
||||||
|
int ringRef = rand.nextInt(26);
|
||||||
|
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.reflector = getReflector(0, rotRef, ringRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 = entryWheel.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting());
|
||||||
|
x = rotor1.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting() + rotor2.getRotation() - rotor2.getRingSetting());
|
||||||
|
x = rotor2.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor2.getRotation() + rotor2.getRingSetting() + rotor3.getRotation() - rotor3.getRingSetting());
|
||||||
|
x = rotor3.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor3.getRotation() + rotor3.getRingSetting() + reflector.getRotation() - reflector.getRingSetting());
|
||||||
|
//backward direction
|
||||||
|
x = reflector.encrypt(x);
|
||||||
|
x = rotor1.normalize(x + rotor3.getRotation() - rotor3.getRingSetting() - reflector.getRotation() + reflector.getRingSetting());
|
||||||
|
x = rotor3.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor2.getRotation() - rotor2.getRingSetting() - rotor3.getRotation() + rotor3.getRingSetting());
|
||||||
|
x = rotor2.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting() - rotor2.getRotation() + rotor2.getRingSetting());
|
||||||
|
x = rotor1.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting());
|
||||||
|
x = entryWheel.encryptBackward(x);
|
||||||
|
return (char) (x + 65); //Add Offset again, cast back to char and return
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
this.entryWheel = getEntryWheel(state.getTypeEntryWheel());
|
||||||
|
this.rotor1 = getRotor(state.getTypeRotor1(), state.getRotationRotor1(), state.getRingSettingRotor1());
|
||||||
|
this.rotor2 = getRotor(state.getTypeRotor2(), state.getRotationRotor2(), state.getRingSettingRotor2());
|
||||||
|
this.rotor3 = getRotor(state.getTypeRotor3(), state.getRotationRotor3(), state.getRingSettingRotor3());
|
||||||
|
this.reflector = getReflector(state.getTypeReflector(), state.getRotationReflector(), state.getRingSettingReflector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnigmaStateBundle getState()
|
||||||
|
{
|
||||||
|
EnigmaStateBundle state = new EnigmaStateBundle();
|
||||||
|
|
||||||
|
state.setTypeEntryWheel(entryWheel.getIndex());
|
||||||
|
|
||||||
|
state.setTypeRotor1(rotor1.getIndex());
|
||||||
|
state.setTypeRotor2(rotor2.getIndex());
|
||||||
|
state.setTypeRotor3(rotor3.getIndex());
|
||||||
|
|
||||||
|
state.setRotationRotor1(rotor1.getRotation());
|
||||||
|
state.setRotationRotor2(rotor2.getRotation());
|
||||||
|
state.setRotationRotor3(rotor3.getRotation());
|
||||||
|
|
||||||
|
state.setRingSettingRotor1(rotor1.getRingSetting());
|
||||||
|
state.setRingSettingRotor2(rotor2.getRingSetting());
|
||||||
|
state.setRingSettingRotor3(rotor3.getRingSetting());
|
||||||
|
|
||||||
|
state.setTypeReflector(reflector.getIndex());
|
||||||
|
state.setRotationReflector(reflector.getRotation());
|
||||||
|
state.setRingSettingReflector(reflector.getRingSetting());
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreState(BigInteger s, int protocol_version)
|
||||||
|
{
|
||||||
|
switch (protocol_version)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
int r1 = getValue(s,availableRotors.size());
|
||||||
|
s = removeDigit(s,availableRotors.size());
|
||||||
|
int r2 = getValue(s,availableRotors.size());
|
||||||
|
s = removeDigit(s,availableRotors.size());
|
||||||
|
int r3 = getValue(s,availableRotors.size());
|
||||||
|
s = removeDigit(s,availableRotors.size());
|
||||||
|
|
||||||
|
int rot1 = getValue(s,26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int ring1 = getValue(s,26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int rot2 = getValue(s,26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int ring2 = getValue(s,26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int rot3 = getValue(s,26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int ring3 = getValue(s,26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int rotRef = getValue(s,26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int ringRef = getValue(s,26);
|
||||||
|
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.reflector = getReflector(0, rotRef, ringRef);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: Log.e(MainActivity.APP_ID, "Unsupported protocol version "+protocol_version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getEncodedState(int protocol_version)
|
||||||
|
{
|
||||||
|
BigInteger s = BigInteger.valueOf(reflector.getRingSetting());
|
||||||
|
s = addDigit(s, reflector.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRingSetting(),26);
|
||||||
|
s = addDigit(s, rotor3.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRingSetting(),26);
|
||||||
|
s = addDigit(s, rotor2.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRotation(), 26);
|
||||||
|
|
||||||
|
s = addDigit(s, rotor3.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor2.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor1.getIndex(), availableRotors.size());
|
||||||
|
|
||||||
|
s = addDigit(s, 7, 20); //Machine #7
|
||||||
|
s = addDigit(s, protocol_version, MainActivity.max_protocol_version);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,240 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Plugboard;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of an enigma machine of name D
|
||||||
|
* This machine has a rewirable UKW, non changeable rotors.
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class Enigma_KD extends Enigma {
|
||||||
|
|
||||||
|
private EntryWheel entryWheel;
|
||||||
|
private Rotor rotor1;
|
||||||
|
private Rotor rotor2;
|
||||||
|
private Rotor rotor3;
|
||||||
|
private Reflector reflector;
|
||||||
|
|
||||||
|
public Enigma_KD()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
machineType = "KD";
|
||||||
|
Log.d(MainActivity.APP_ID, "Created Enigma KD");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void establishAvailableParts()
|
||||||
|
{
|
||||||
|
addAvailableEntryWheel(new EntryWheel.EntryWheel_QWERTZ());
|
||||||
|
|
||||||
|
addAvailableRotor(new Rotor.Rotor_KD_I(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_KD_II(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_KD_III(0, 0));
|
||||||
|
|
||||||
|
addAvailableReflector(new Reflector.ReflectorEnigma_KD());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize()
|
||||||
|
{
|
||||||
|
this.entryWheel = availableEntryWheels.get(0);
|
||||||
|
this.rotor1 = availableRotors.get(0);
|
||||||
|
this.rotor2 = availableRotors.get(1);
|
||||||
|
this.rotor3 = availableRotors.get(2);
|
||||||
|
this.reflector = availableReflectors.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nextState()
|
||||||
|
{
|
||||||
|
rotor1.rotate();
|
||||||
|
if (rotor1.isAtTurnoverPosition() || this.doAnomaly)
|
||||||
|
{
|
||||||
|
rotor2.rotate();
|
||||||
|
this.doAnomaly = rotor2.doubleTurnAnomaly();
|
||||||
|
if (rotor2.isAtTurnoverPosition())
|
||||||
|
{
|
||||||
|
rotor3.rotate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void generateState() {
|
||||||
|
int r1, r2=-1, r3;
|
||||||
|
r1 = rand.nextInt(3);
|
||||||
|
while(r2 == -1 || r2 == r1) r2 = rand.nextInt(3);
|
||||||
|
r3 = 3 - r1 - r2;
|
||||||
|
|
||||||
|
int rot1 = rand.nextInt(26);
|
||||||
|
int rot2 = rand.nextInt(26);
|
||||||
|
int rot3 = rand.nextInt(26);
|
||||||
|
int rotRef = rand.nextInt(26);
|
||||||
|
int ring1 = rand.nextInt(26);
|
||||||
|
int ring2 = rand.nextInt(26);
|
||||||
|
int ring3 = rand.nextInt(26);
|
||||||
|
int ringRef = rand.nextInt(26);
|
||||||
|
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.reflector = getReflector(0, rotRef, ringRef);
|
||||||
|
this.reflector.setRotation(rotRef).setRingSetting(ringRef)
|
||||||
|
.setConfiguration(Plugboard.seedToReflectorConfiguration(rand));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 = entryWheel.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting());
|
||||||
|
x = rotor1.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting() + rotor2.getRotation() - rotor2.getRingSetting());
|
||||||
|
x = rotor2.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor2.getRotation() + rotor2.getRingSetting() + rotor3.getRotation() - rotor3.getRingSetting());
|
||||||
|
x = rotor3.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor3.getRotation() + rotor3.getRingSetting() + reflector.getRotation() - reflector.getRingSetting());
|
||||||
|
//backward direction
|
||||||
|
x = reflector.encrypt(x);
|
||||||
|
x = rotor1.normalize(x + rotor3.getRotation() - rotor3.getRingSetting() - reflector.getRotation() + reflector.getRingSetting());
|
||||||
|
x = rotor3.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor2.getRotation() - rotor2.getRingSetting() - rotor3.getRotation() + rotor3.getRingSetting());
|
||||||
|
x = rotor2.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting() - rotor2.getRotation() + rotor2.getRingSetting());
|
||||||
|
x = rotor1.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting());
|
||||||
|
x = entryWheel.encryptBackward(x);
|
||||||
|
return (char) (x + 65); //Add Offset again, cast back to char and return
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
this.entryWheel = getEntryWheel(state.getTypeEntryWheel());
|
||||||
|
this.rotor1 = getRotor(state.getTypeRotor1(), state.getRotationRotor1(), state.getRingSettingRotor1());
|
||||||
|
this.rotor2 = getRotor(state.getTypeRotor2(), state.getRotationRotor2(), state.getRingSettingRotor2());
|
||||||
|
this.rotor3 = getRotor(state.getTypeRotor3(), state.getRotationRotor3(), state.getRingSettingRotor3());
|
||||||
|
this.reflector = getReflector(state.getTypeReflector(),
|
||||||
|
state.getRotationReflector(),
|
||||||
|
state.getRingSettingReflector())
|
||||||
|
.setConfiguration(state.getConfigurationReflector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnigmaStateBundle getState()
|
||||||
|
{
|
||||||
|
EnigmaStateBundle state = new EnigmaStateBundle();
|
||||||
|
|
||||||
|
state.setTypeEntryWheel(entryWheel.getIndex());
|
||||||
|
|
||||||
|
state.setTypeRotor1(rotor1.getIndex());
|
||||||
|
state.setTypeRotor2(rotor2.getIndex());
|
||||||
|
state.setTypeRotor3(rotor3.getIndex());
|
||||||
|
|
||||||
|
state.setRotationRotor1(rotor1.getRotation());
|
||||||
|
state.setRotationRotor2(rotor2.getRotation());
|
||||||
|
state.setRotationRotor3(rotor3.getRotation());
|
||||||
|
|
||||||
|
state.setRingSettingRotor1(rotor1.getRingSetting());
|
||||||
|
state.setRingSettingRotor2(rotor2.getRingSetting());
|
||||||
|
state.setRingSettingRotor3(rotor3.getRingSetting());
|
||||||
|
|
||||||
|
state.setTypeReflector(reflector.getIndex());
|
||||||
|
state.setRotationReflector(reflector.getRotation());
|
||||||
|
state.setRingSettingReflector(reflector.getRingSetting());
|
||||||
|
state.setConfigurationReflector(reflector.getConfiguration());
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreState(BigInteger s, int protocol_version)
|
||||||
|
{
|
||||||
|
switch (protocol_version)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
int r1 = getValue(s, availableRotors.size());
|
||||||
|
s = removeDigit(s, availableRotors.size());
|
||||||
|
int r2 = getValue(s, availableRotors.size());
|
||||||
|
s = removeDigit(s, availableRotors.size());
|
||||||
|
int r3 = getValue(s, availableRotors.size());
|
||||||
|
s = removeDigit(s, availableRotors.size());
|
||||||
|
|
||||||
|
int rot1 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring1 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rot2 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring2 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rot3 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring3 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rotRef = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ringRef = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
|
||||||
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.reflector = getReflector(0, rotRef, ringRef);
|
||||||
|
this.reflector.setConfiguration(s);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: Log.e(MainActivity.APP_ID, "Unsupported protocol version "+protocol_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getEncodedState(int protocol_version) {
|
||||||
|
BigInteger s = Plugboard.configurationToBigInteger(reflector.getConfiguration());
|
||||||
|
s = addDigit(s, reflector.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, reflector.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRotation(), 26);
|
||||||
|
|
||||||
|
s = addDigit(s, rotor3.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor2.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor1.getIndex(), availableRotors.size());
|
||||||
|
|
||||||
|
s = addDigit(s, 12, 20); //Machine #12
|
||||||
|
s = addDigit(s, protocol_version, MainActivity.max_protocol_version);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the Enigma machine of name K (Switzerland, Airforce)
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class Enigma_K_Swiss_Airforce extends Enigma_K
|
||||||
|
{
|
||||||
|
public Enigma_K_Swiss_Airforce()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
machineType = "KSA";
|
||||||
|
Log.d(MainActivity.APP_ID, "Created Enigma KSA");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void establishAvailableParts()
|
||||||
|
{
|
||||||
|
addAvailableEntryWheel(new EntryWheel.EntryWheel_QWERTZ());
|
||||||
|
addAvailableRotor(new Rotor.Rotor_K_Swiss_Airforce_I(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_K_Swiss_Airforce_II(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_K_Swiss_Airforce_III(0,0));
|
||||||
|
addAvailableReflector(new Reflector.Reflector_K_G260());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getEncodedState(int protocol_version)
|
||||||
|
{
|
||||||
|
BigInteger s = BigInteger.valueOf(reflector.getRingSetting());
|
||||||
|
s = addDigit(s, reflector.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRingSetting(),26);
|
||||||
|
s = addDigit(s, rotor3.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRingSetting(),26);
|
||||||
|
s = addDigit(s, rotor2.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRotation(), 26);
|
||||||
|
|
||||||
|
s = addDigit(s, rotor3.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor2.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor1.getIndex(), availableRotors.size());
|
||||||
|
|
||||||
|
s = addDigit(s, 9, 20); //Machine #9
|
||||||
|
s = addDigit(s, protocol_version, MainActivity.max_protocol_version);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the Enigma machine of name K (Switzerland)
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class Enigma_K_Swiss_Standard extends Enigma_K
|
||||||
|
{
|
||||||
|
public Enigma_K_Swiss_Standard()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
machineType = "KS";
|
||||||
|
Log.d(MainActivity.APP_ID, "Created Enigma KS");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void establishAvailableParts()
|
||||||
|
{
|
||||||
|
addAvailableEntryWheel(new EntryWheel.EntryWheel_QWERTZ());
|
||||||
|
addAvailableRotor(new Rotor.Rotor_KSwiss_Standard_I(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_KSwiss_Standard_II(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_KSwiss_Standard_III(0,0));
|
||||||
|
addAvailableReflector(new Reflector.Reflector_K_G260());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getEncodedState(int protocol_version)
|
||||||
|
{
|
||||||
|
BigInteger s = BigInteger.valueOf(reflector.getRingSetting());
|
||||||
|
s = addDigit(s, reflector.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRingSetting(),26);
|
||||||
|
s = addDigit(s, rotor3.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRingSetting(),26);
|
||||||
|
s = addDigit(s, rotor2.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRotation(), 26);
|
||||||
|
|
||||||
|
s = addDigit(s, rotor3.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor2.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor1.getIndex(), availableRotors.size());
|
||||||
|
|
||||||
|
s = addDigit(s, 8, 20); //Machine #8
|
||||||
|
s = addDigit(s, protocol_version, MainActivity.max_protocol_version);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,75 +1,99 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package de.vanitasvitae.enigmandroid.enigma;
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import de.vanitasvitae.enigmandroid.enigma.rotors.Reflector;
|
import java.math.BigInteger;
|
||||||
import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor;
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Plugboard;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implementation of an enigma machine model M3
|
* Concrete implementation of an enigma machine model M3
|
||||||
* Copyright (C) 2015 Paul Schaub
|
* 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 class Enigma_M3 extends Enigma_I
|
||||||
{
|
{
|
||||||
public Enigma_M3()
|
public Enigma_M3()
|
||||||
{
|
{
|
||||||
machineType = "M3";
|
super();
|
||||||
}
|
machineType = "M3";
|
||||||
@Override
|
Log.d(MainActivity.APP_ID, "Created Enigma M3");
|
||||||
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
|
@Override
|
||||||
public boolean setReflector(int type)
|
protected void establishAvailableParts()
|
||||||
{
|
{
|
||||||
if(type >= 2 && type <= 3)
|
addAvailableEntryWheel(new EntryWheel.EntryWheel_ABCDEF());
|
||||||
{
|
addAvailableRotor(new Rotor.Rotor_I(0, 0));
|
||||||
reflector = Reflector.createReflector(type);
|
addAvailableRotor(new Rotor.Rotor_II(0,0));
|
||||||
return true;
|
addAvailableRotor(new Rotor.Rotor_III(0,0));
|
||||||
}
|
addAvailableRotor(new Rotor.Rotor_IV(0,0));
|
||||||
Log.d("EnigmAndroid/M3/setRef", "Error: Can't set type "+type);
|
addAvailableRotor(new Rotor.Rotor_V(0,0));
|
||||||
return false;
|
addAvailableRotor(new Rotor.Rotor_VI(0,0));
|
||||||
}
|
addAvailableRotor(new Rotor.Rotor_VII(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_VIII(0,0));
|
||||||
|
addAvailableReflector(new Reflector.Reflector_B());
|
||||||
|
addAvailableReflector(new Reflector.Reflector_C());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void generateState() {
|
||||||
|
int r1, r2=-1, r3=-1;
|
||||||
|
r1 = rand.nextInt(8);
|
||||||
|
while(r2 == -1 || r2 == r1) r2 = rand.nextInt(8);
|
||||||
|
while(r3 == -1 || r3 == r2 || r3 == r1) r3 = rand.nextInt(8);
|
||||||
|
int ref = rand.nextInt(2);
|
||||||
|
|
||||||
|
int rot1 = rand.nextInt(26);
|
||||||
|
int rot2 = rand.nextInt(26);
|
||||||
|
int rot3 = rand.nextInt(26);
|
||||||
|
int ring1 = rand.nextInt(26);
|
||||||
|
int ring2 = rand.nextInt(26);
|
||||||
|
int ring3 = rand.nextInt(26);
|
||||||
|
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.reflector = getReflector(ref);
|
||||||
|
|
||||||
|
this.plugboard = new Plugboard();
|
||||||
|
plugboard.setConfiguration(Plugboard.seedToPlugboardConfiguration(rand));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getEncodedState(int protocol_version) {
|
||||||
|
BigInteger s = Plugboard.configurationToBigInteger(plugboard.getConfiguration());
|
||||||
|
s = addDigit(s, rotor3.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRotation(), 26);
|
||||||
|
s = addDigit(s, reflector.getIndex(), availableReflectors.size());
|
||||||
|
s = addDigit(s, rotor3.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor2.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor1.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, 1, 20); //Machine #1
|
||||||
|
s = addDigit(s, protocol_version, MainActivity.max_protocol_version);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,214 +1,320 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package de.vanitasvitae.enigmandroid.enigma;
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import de.vanitasvitae.enigmandroid.enigma.rotors.Reflector;
|
import java.math.BigInteger;
|
||||||
import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Plugboard;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete Implementation of the Enigma Machine type M4 of the german Kriegsmarine
|
* Concrete Implementation of the Enigma Machine name M4 of the german Kriegsmarine
|
||||||
* Copyright (C) 2015 Paul Schaub
|
* 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
|
public class Enigma_M4 extends Enigma
|
||||||
{
|
{
|
||||||
private Rotor rotor1;
|
private ArrayList<Rotor> availableThinRotors;
|
||||||
private Rotor rotor2;
|
private EntryWheel entryWheel;
|
||||||
private Rotor rotor3;
|
private Rotor rotor1;
|
||||||
|
private Rotor rotor2;
|
||||||
|
private Rotor rotor3;
|
||||||
|
|
||||||
private Rotor rotor4;
|
private Rotor rotor4;
|
||||||
private Reflector thinReflector;
|
|
||||||
|
|
||||||
private Plugboard plugboard;
|
private Reflector reflector;
|
||||||
|
|
||||||
public Enigma_M4()
|
private Plugboard plugboard;
|
||||||
{
|
|
||||||
machineType = "M4";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public Enigma_M4()
|
||||||
public boolean setRotor(int pos, int type, int ringSetting, int rotation)
|
{
|
||||||
{
|
super();
|
||||||
if(pos >= 1 && pos <= 3)
|
machineType = "M4";
|
||||||
{
|
Log.d(MainActivity.APP_ID, "Created Enigma M4");
|
||||||
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
|
private void addAvailableThinRotor(Rotor r)
|
||||||
public boolean setReflector(int type)
|
{
|
||||||
{
|
if(availableThinRotors == null) availableThinRotors = new ArrayList<>();
|
||||||
if(type >= 4 && type <=5)
|
availableThinRotors.add(availableThinRotors.size(), r.setIndex(availableThinRotors.size()));
|
||||||
{
|
}
|
||||||
this.thinReflector = Reflector.createReflector(type);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Log.d("EnigmAndroid/M4/setRef","Error: Can't set type "+type);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
private Rotor getThinRotor(int index)
|
||||||
public void initialize()
|
{
|
||||||
{
|
if(availableThinRotors == null || availableThinRotors.size() == 0) return null;
|
||||||
this.setPlugboard(new Plugboard());
|
return availableThinRotors.get(index % availableThinRotors.size()).getInstance();
|
||||||
this.setConfiguration(new int[]{1,2,3,9,4,0,0,0,0,0,0,0,0});
|
}
|
||||||
this.prefAnomaly = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
private Rotor getThinRotor(int index, int rotation, int ringSettings)
|
||||||
/**
|
{
|
||||||
* Set the enigma into the next mechanical state.
|
Rotor r = getThinRotor(index);
|
||||||
* This rotates the first rotor and eventually also the second/third.
|
if(r == null) return null;
|
||||||
* Also this method handles the anomaly in case it should happen.
|
return r.setRotation(rotation).setRingSetting(ringSettings);
|
||||||
*/
|
}
|
||||||
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
|
@Override
|
||||||
/**
|
protected void establishAvailableParts()
|
||||||
* Substitute char k by sending the signal through the enigma.
|
{
|
||||||
* The signal passes the plugboard, the rotors and returns back after going through the
|
Log.d(MainActivity.APP_ID, "Established");
|
||||||
* reflector wheel.
|
addAvailableEntryWheel(new EntryWheel.EntryWheel_ABCDEF());
|
||||||
*
|
addAvailableRotor(new Rotor.Rotor_I(0, 0));
|
||||||
* @param k input char
|
addAvailableRotor(new Rotor.Rotor_II(0,0));
|
||||||
* @return substituted output char
|
addAvailableRotor(new Rotor.Rotor_III(0,0));
|
||||||
*/
|
addAvailableRotor(new Rotor.Rotor_IV(0,0));
|
||||||
public char encryptChar(char k)
|
addAvailableRotor(new Rotor.Rotor_V(0,0));
|
||||||
{
|
addAvailableRotor(new Rotor.Rotor_VI(0,0));
|
||||||
nextState(); //Rotate rotors
|
addAvailableRotor(new Rotor.Rotor_VII(0, 0));
|
||||||
int x = ((int) k)-65; //Cast to int and remove Unicode Offset (A=65 in Unicode.)
|
addAvailableRotor(new Rotor.Rotor_VIII(0,0));
|
||||||
//Encryption
|
addAvailableThinRotor(new Rotor.Rotor_M4_Beta(0, 0));
|
||||||
//forward direction
|
addAvailableThinRotor(new Rotor.Rotor_M4_Gamma(0, 0));
|
||||||
x = plugboard.encrypt(x);
|
addAvailableReflector(new Reflector.Reflector_Thin_B());
|
||||||
x = normalize(x + rotor1.getRotation() - rotor1.getRingSetting());
|
addAvailableReflector(new Reflector.ReflectorThinC());
|
||||||
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
|
@Override
|
||||||
public int normalize(int input) {
|
public void initialize()
|
||||||
return (input + 26) % 26;
|
{
|
||||||
}
|
Log.d(MainActivity.APP_ID, "Initialized");
|
||||||
|
this.plugboard = new Plugboard();
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(0, 0, 0);
|
||||||
|
this.rotor2 = getRotor(1, 0, 0);
|
||||||
|
this.rotor3 = getRotor(2, 0, 0);
|
||||||
|
this.rotor4 = getThinRotor(0, 0, 0);
|
||||||
|
this.reflector = getReflector(0);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPlugboard(Plugboard p)
|
/**
|
||||||
{
|
* Set the enigma into the next mechanical state.
|
||||||
this.plugboard = p;
|
* 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)
|
||||||
|
{
|
||||||
|
rotor2.rotate();
|
||||||
|
//Set doAnomaly for next call of encryptChar
|
||||||
|
this.doAnomaly = rotor2.doubleTurnAnomaly();
|
||||||
|
//Eventually rotate next rotor
|
||||||
|
if (rotor2.isAtTurnoverPosition())
|
||||||
|
{
|
||||||
|
rotor3.rotate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getConfiguration() {
|
protected void generateState() {
|
||||||
int[] configuration = new int[13];
|
int r1, r2=-1, r3=-1;
|
||||||
configuration[0] = rotor1.getType();
|
int r4;
|
||||||
configuration[1] = rotor2.getType();
|
int ref;
|
||||||
configuration[2] = rotor3.getType();
|
r1 = rand.nextInt(8);
|
||||||
configuration[3] = rotor4.getType();
|
while(r2 == -1 || r2 == r1) r2 = rand.nextInt(8);
|
||||||
|
while(r3 == -1 || r3 == r2 || r3 == r1) r3 = rand.nextInt(8);
|
||||||
|
r4 = rand.nextInt(2);
|
||||||
|
ref = rand.nextInt(2);
|
||||||
|
|
||||||
configuration[4] = thinReflector.getType();
|
int rot1 = rand.nextInt(26);
|
||||||
|
int rot2 = rand.nextInt(26);
|
||||||
|
int rot3 = rand.nextInt(26);
|
||||||
|
int rot4 = rand.nextInt(26);
|
||||||
|
int rotRef = rand.nextInt(26);
|
||||||
|
int ring1 = rand.nextInt(26);
|
||||||
|
int ring2 = rand.nextInt(26);
|
||||||
|
int ring3 = rand.nextInt(26);
|
||||||
|
int ring4 = rand.nextInt(26);
|
||||||
|
int ringRef = rand.nextInt(26);
|
||||||
|
|
||||||
configuration[5] = rotor1.getRotation();
|
this.entryWheel = getEntryWheel(0);
|
||||||
configuration[6] = rotor2.getRotation();
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
configuration[7] = rotor3.getRotation();
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
configuration[8] = rotor4.getRotation();
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.rotor4 = getThinRotor(r4, rot4, ring4);
|
||||||
|
|
||||||
configuration[9] = rotor1.getRingSetting();
|
this.reflector = getReflector(ref, rotRef, ringRef);
|
||||||
configuration[10] = rotor2.getRingSetting();
|
|
||||||
configuration[11] = rotor3.getRingSetting();
|
|
||||||
|
|
||||||
configuration[12] = rotor4.getRingSetting();
|
this.plugboard = new Plugboard();
|
||||||
return configuration;
|
this.plugboard.setConfiguration(Plugboard.seedToPlugboardConfiguration(rand));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setConfiguration(int[] conf)
|
/**
|
||||||
{
|
* Substitute char k by sending the signal through the enigma.
|
||||||
if(conf.length != 13)
|
* The signal passes the plugboard, the rotors and returns back after going through the
|
||||||
{
|
* reflector wheel.
|
||||||
Log.d("EnigmAndroid/M4/setCon", "Invalid conf array length. conf array length " +
|
*
|
||||||
"should be 13 (is "+conf.length+")");
|
* @param k input char
|
||||||
}
|
* @return substituted output char
|
||||||
else
|
*/
|
||||||
{
|
public char encryptChar(char k)
|
||||||
setRotor(1, conf[0], conf[9], conf[5]);
|
{
|
||||||
setRotor(2, conf[1], conf[10], conf[6]);
|
nextState(); //Rotate rotors
|
||||||
setRotor(3, conf[2], conf[11], conf[7]);
|
int x = ((int) k)-65; //Cast to int and remove Unicode Offset (A=65 in Unicode.)
|
||||||
setRotor(4, conf[3], conf[12], conf[8]);
|
//Encryption
|
||||||
setReflector(conf[4]);
|
//forward direction
|
||||||
}
|
x = plugboard.encrypt(x);
|
||||||
}
|
x = entryWheel.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting());
|
||||||
|
x = rotor1.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting() + rotor2.getRotation() - rotor2.getRingSetting());
|
||||||
|
x = rotor2.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor2.getRotation() + rotor2.getRingSetting() + rotor3.getRotation() - rotor3.getRingSetting());
|
||||||
|
x = rotor3.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor3.getRotation() + rotor3.getRingSetting() + rotor4.getRotation() - rotor4.getRingSetting());
|
||||||
|
x = rotor4.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor4.getRotation() + rotor4.getRingSetting());
|
||||||
|
//backward direction
|
||||||
|
x = reflector.encrypt(x);
|
||||||
|
x = rotor1.normalize(x + rotor4.getRotation() - rotor4.getRingSetting());
|
||||||
|
x = rotor4.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor3.getRotation() - rotor3.getRingSetting() - rotor4.getRotation() + rotor4.getRingSetting());
|
||||||
|
x = rotor3.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor2.getRotation() - rotor2.getRingSetting() - rotor3.getRotation() + rotor3.getRingSetting());
|
||||||
|
x = rotor2.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting() - rotor2.getRotation() + rotor2.getRingSetting());
|
||||||
|
x = rotor1.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting());
|
||||||
|
x = entryWheel.encryptBackward(x);
|
||||||
|
x = plugboard.encrypt(x);
|
||||||
|
return (char) (x + 65); //Add Offset again and cast back to char
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
rotor1 = getRotor(state.getTypeRotor1(), state.getRotationRotor1(), state.getRingSettingRotor1());
|
||||||
|
rotor2 = getRotor(state.getTypeRotor2(), state.getRotationRotor2(), state.getRingSettingRotor2());
|
||||||
|
rotor3 = getRotor(state.getTypeRotor3(), state.getRotationRotor3(), state.getRingSettingRotor3());
|
||||||
|
rotor4 = getThinRotor(state.getTypeRotor4(), state.getRotationRotor4(), state.getRingSettingRotor4());
|
||||||
|
reflector = getReflector(state.getTypeReflector());
|
||||||
|
plugboard.setConfiguration(state.getConfigurationPlugboard());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnigmaStateBundle getState()
|
||||||
|
{
|
||||||
|
EnigmaStateBundle state = new EnigmaStateBundle();
|
||||||
|
state.setTypeEntryWheel(entryWheel.getIndex());
|
||||||
|
|
||||||
|
state.setTypeRotor1(rotor1.getIndex());
|
||||||
|
state.setTypeRotor2(rotor2.getIndex());
|
||||||
|
state.setTypeRotor3(rotor3.getIndex());
|
||||||
|
state.setTypeRotor4(rotor4.getIndex());
|
||||||
|
|
||||||
|
state.setRotationRotor1(rotor1.getRotation());
|
||||||
|
state.setRotationRotor2(rotor2.getRotation());
|
||||||
|
state.setRotationRotor3(rotor3.getRotation());
|
||||||
|
state.setRotationRotor4(rotor4.getRotation());
|
||||||
|
|
||||||
|
state.setRingSettingRotor1(rotor1.getRingSetting());
|
||||||
|
state.setRingSettingRotor2(rotor2.getRingSetting());
|
||||||
|
state.setRingSettingRotor3(rotor3.getRingSetting());
|
||||||
|
state.setRingSettingRotor4(rotor4.getRingSetting());
|
||||||
|
|
||||||
|
state.setTypeReflector(reflector.getIndex());
|
||||||
|
|
||||||
|
state.setConfigurationPlugboard(plugboard.getConfiguration());
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreState(BigInteger s, int protocol_version)
|
||||||
|
{
|
||||||
|
switch (protocol_version)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
int r1 = getValue(s, availableRotors.size());
|
||||||
|
s = removeDigit(s, availableRotors.size());
|
||||||
|
int r2 = getValue(s, availableRotors.size());
|
||||||
|
s = removeDigit(s,availableRotors.size());
|
||||||
|
int r3 = getValue(s, availableRotors.size());
|
||||||
|
s = removeDigit(s,availableRotors.size());
|
||||||
|
int r4 = getValue(s, availableThinRotors.size());
|
||||||
|
s = removeDigit(s,availableThinRotors.size());
|
||||||
|
int ref = getValue(s, availableReflectors.size());
|
||||||
|
s = removeDigit(s,availableReflectors.size());
|
||||||
|
|
||||||
|
int rot1 = getValue(s, 26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int ring1 = getValue(s, 26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int rot2 = getValue(s, 26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int ring2 = getValue(s, 26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int rot3 = getValue(s, 26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int ring3 = getValue(s, 26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int rot4 = getValue(s, 26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int ring4 = getValue(s, 26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int rotRef = getValue(s, 26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int ringRef = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
|
||||||
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.rotor4 = getThinRotor(r4, rot4, ring4);
|
||||||
|
this.reflector = getReflector(ref, rotRef, ringRef);
|
||||||
|
this.plugboard = new Plugboard();
|
||||||
|
plugboard.setConfiguration(s);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: Log.e(MainActivity.APP_ID, "Unsupported protocol version "+protocol_version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getEncodedState(int protocol_version) {
|
||||||
|
BigInteger s = Plugboard.configurationToBigInteger(plugboard.getConfiguration());
|
||||||
|
s = addDigit(s, reflector.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, reflector.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor4.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor4.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRotation(), 26);
|
||||||
|
|
||||||
|
s = addDigit(s, reflector.getIndex(), availableReflectors.size());
|
||||||
|
s = addDigit(s, rotor4.getIndex(), availableThinRotors.size());
|
||||||
|
s = addDigit(s, rotor3.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor2.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor1.getIndex(), availableRotors.size());
|
||||||
|
|
||||||
|
s = addDigit(s, 2, 20);
|
||||||
|
s = addDigit(s, protocol_version, MainActivity.max_protocol_version);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,231 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the Enigma machine of name R ("Rocket", Reichsbahn)
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class Enigma_R extends Enigma
|
||||||
|
{
|
||||||
|
private EntryWheel entryWheel;
|
||||||
|
private Rotor rotor1;
|
||||||
|
private Rotor rotor2;
|
||||||
|
private Rotor rotor3;
|
||||||
|
|
||||||
|
private Reflector reflector;
|
||||||
|
|
||||||
|
public Enigma_R()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
machineType = "R";
|
||||||
|
Log.d(MainActivity.APP_ID, "Created Enigma R");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void establishAvailableParts() {
|
||||||
|
addAvailableEntryWheel(new EntryWheel.EntryWheel_QWERTZ());
|
||||||
|
addAvailableRotor(new Rotor.Rotor_R_I(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_R_II(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_R_III(0,0));
|
||||||
|
addAvailableReflector(new Reflector.Reflector_R());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize()
|
||||||
|
{
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(0);
|
||||||
|
this.rotor2 = getRotor(1);
|
||||||
|
this.rotor3 = getRotor(2);
|
||||||
|
this.reflector = getReflector(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nextState()
|
||||||
|
{
|
||||||
|
rotor1.rotate();
|
||||||
|
if (rotor1.isAtTurnoverPosition() || this.doAnomaly)
|
||||||
|
{
|
||||||
|
rotor2.rotate();
|
||||||
|
this.doAnomaly = rotor2.doubleTurnAnomaly();
|
||||||
|
if (rotor2.isAtTurnoverPosition())
|
||||||
|
{
|
||||||
|
rotor3.rotate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void generateState()
|
||||||
|
{
|
||||||
|
int r1, r2=-1, r3;
|
||||||
|
r1 = rand.nextInt(3);
|
||||||
|
while(r2 == -1 || r2 == r1) r2 = rand.nextInt(3);
|
||||||
|
r3 = 3 - r1 - r2;
|
||||||
|
|
||||||
|
int rot1 = rand.nextInt(26);
|
||||||
|
int rot2 = rand.nextInt(26);
|
||||||
|
int rot3 = rand.nextInt(26);
|
||||||
|
int rotRef = rand.nextInt(26);
|
||||||
|
int ring1 = rand.nextInt(26);
|
||||||
|
int ring2 = rand.nextInt(26);
|
||||||
|
int ring3 = rand.nextInt(26);
|
||||||
|
int ringRef = rand.nextInt(26);
|
||||||
|
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.reflector = getReflector(0, rotRef, ringRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 = entryWheel.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting());
|
||||||
|
x = rotor1.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting() + rotor2.getRotation() - rotor2.getRingSetting());
|
||||||
|
x = rotor2.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor2.getRotation() + rotor2.getRingSetting() + rotor3.getRotation() - rotor3.getRingSetting());
|
||||||
|
x = rotor3.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor3.getRotation() + rotor3.getRingSetting() + reflector.getRotation() - reflector.getRingSetting());
|
||||||
|
//backward direction
|
||||||
|
x = reflector.encrypt(x);
|
||||||
|
x = rotor1.normalize(x + rotor3.getRotation() - rotor3.getRingSetting() - reflector.getRotation() + reflector.getRingSetting());
|
||||||
|
x = rotor3.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor2.getRotation() - rotor2.getRingSetting() - rotor3.getRotation() + rotor3.getRingSetting());
|
||||||
|
x = rotor2.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting() - rotor2.getRotation() + rotor2.getRingSetting());
|
||||||
|
x = rotor1.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting());
|
||||||
|
x = entryWheel.encryptBackward(x);
|
||||||
|
return (char) (x + 65); //Add Offset again, cast back to char and return
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
this.entryWheel = getEntryWheel(state.getTypeEntryWheel());
|
||||||
|
this.rotor1 = getRotor(state.getTypeRotor1(), state.getRotationRotor1(), state.getRingSettingRotor1());
|
||||||
|
this.rotor2 = getRotor(state.getTypeRotor2(), state.getRotationRotor2(), state.getRingSettingRotor2());
|
||||||
|
this.rotor3 = getRotor(state.getTypeRotor3(), state.getRotationRotor3(), state.getRingSettingRotor3());
|
||||||
|
this.reflector = getReflector(state.getTypeReflector(), state.getRotationReflector(), state.getRingSettingReflector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnigmaStateBundle getState() {
|
||||||
|
EnigmaStateBundle state = new EnigmaStateBundle();
|
||||||
|
|
||||||
|
state.setTypeEntryWheel(entryWheel.getIndex());
|
||||||
|
|
||||||
|
state.setTypeRotor1(rotor1.getIndex());
|
||||||
|
state.setTypeRotor2(rotor2.getIndex());
|
||||||
|
state.setTypeRotor3(rotor3.getIndex());
|
||||||
|
|
||||||
|
state.setRotationRotor1(rotor1.getRotation());
|
||||||
|
state.setRotationRotor2(rotor2.getRotation());
|
||||||
|
state.setRotationRotor3(rotor3.getRotation());
|
||||||
|
|
||||||
|
state.setRingSettingRotor1(rotor1.getRingSetting());
|
||||||
|
state.setRingSettingRotor2(rotor2.getRingSetting());
|
||||||
|
state.setRingSettingRotor3(rotor3.getRingSetting());
|
||||||
|
|
||||||
|
state.setTypeReflector(reflector.getIndex());
|
||||||
|
state.setRotationReflector(reflector.getRotation());
|
||||||
|
state.setRingSettingReflector(reflector.getRingSetting());
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreState(BigInteger s, int protocol_version)
|
||||||
|
{
|
||||||
|
switch (protocol_version)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
int r1 = getValue(s,availableRotors.size());
|
||||||
|
s = removeDigit(s,availableRotors.size());
|
||||||
|
int r2 = getValue(s,availableRotors.size());
|
||||||
|
s = removeDigit(s,availableRotors.size());
|
||||||
|
int r3 = getValue(s,availableRotors.size());
|
||||||
|
s = removeDigit(s,availableRotors.size());
|
||||||
|
|
||||||
|
int rot1 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring1 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rot2 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring2 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rot3 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ring3 = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int rotRef = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ringRef = getValue(s, 26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.reflector = getReflector(0, rotRef, ringRef);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: Log.e(MainActivity.APP_ID, "Unsupported protocol version "+protocol_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getEncodedState(int protocol_version)
|
||||||
|
{
|
||||||
|
BigInteger s = BigInteger.valueOf(reflector.getRingSetting());
|
||||||
|
s = addDigit(s, reflector.getRotation(), 26);
|
||||||
|
|
||||||
|
s = addDigit(s, rotor3.getRingSetting(),26);
|
||||||
|
s = addDigit(s, rotor3.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRingSetting(),26);
|
||||||
|
s = addDigit(s, rotor2.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRotation(), 26);
|
||||||
|
|
||||||
|
s = addDigit(s, rotor3.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor2.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor1.getIndex(), availableRotors.size());
|
||||||
|
|
||||||
|
s = addDigit(s, 10, 20); //Machine #10
|
||||||
|
s = addDigit(s, protocol_version, MainActivity.max_protocol_version);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,228 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.EntryWheel;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Reflector;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.parts.Rotor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the Enigma machine of name T Tirpitz
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class Enigma_T extends Enigma
|
||||||
|
{
|
||||||
|
private EntryWheel entryWheel;
|
||||||
|
private Rotor rotor1;
|
||||||
|
private Rotor rotor2;
|
||||||
|
private Rotor rotor3;
|
||||||
|
private Reflector reflector;
|
||||||
|
|
||||||
|
public Enigma_T()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
machineType = "T";
|
||||||
|
Log.d(MainActivity.APP_ID, "Created Enigma T");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void establishAvailableParts() {
|
||||||
|
addAvailableEntryWheel(new EntryWheel.EntryWheel_T());
|
||||||
|
addAvailableRotor(new Rotor.Rotor_T_I(0, 0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_T_II(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_T_III(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_T_IV(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_T_V(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_T_VI(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_T_VII(0,0));
|
||||||
|
addAvailableRotor(new Rotor.Rotor_T_VIII(0,0));
|
||||||
|
addAvailableReflector(new Reflector.ReflectorEnigma_T());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(0);
|
||||||
|
this.rotor2 = getRotor(1);
|
||||||
|
this.rotor3 = getRotor(2);
|
||||||
|
this.reflector = getReflector(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nextState()
|
||||||
|
{
|
||||||
|
rotor1.rotate();
|
||||||
|
if (rotor1.isAtTurnoverPosition() || this.doAnomaly)
|
||||||
|
{
|
||||||
|
rotor2.rotate();
|
||||||
|
this.doAnomaly = rotor2.doubleTurnAnomaly();
|
||||||
|
if (rotor2.isAtTurnoverPosition())
|
||||||
|
{
|
||||||
|
rotor3.rotate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void generateState() {
|
||||||
|
int r1, r2=-1, r3=-1;
|
||||||
|
r1 = rand.nextInt(8);
|
||||||
|
while(r2 == -1 || r2 == r1) r2 = rand.nextInt(8);
|
||||||
|
while(r3 == -1 || r3 == r2 || r3 == r1) r3 = rand.nextInt(8);
|
||||||
|
|
||||||
|
int rot1 = rand.nextInt(26);
|
||||||
|
int rot2 = rand.nextInt(26);
|
||||||
|
int rot3 = rand.nextInt(26);
|
||||||
|
int rotRef = rand.nextInt(26);
|
||||||
|
int ring1 = rand.nextInt(26);
|
||||||
|
int ring2 = rand.nextInt(26);
|
||||||
|
int ring3 = rand.nextInt(26);
|
||||||
|
int ringRef = rand.nextInt(26);
|
||||||
|
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.reflector = getReflector(0, rotRef, ringRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 = entryWheel.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting());
|
||||||
|
x = rotor1.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting() + rotor2.getRotation() - rotor2.getRingSetting());
|
||||||
|
x = rotor2.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor2.getRotation() + rotor2.getRingSetting() + rotor3.getRotation() - rotor3.getRingSetting());
|
||||||
|
x = rotor3.encryptForward(x);
|
||||||
|
x = rotor1.normalize(x - rotor3.getRotation() + rotor3.getRingSetting() + reflector.getRotation() - reflector.getRingSetting());
|
||||||
|
//backward direction
|
||||||
|
x = reflector.encrypt(x);
|
||||||
|
x = rotor1.normalize(x + rotor3.getRotation() - rotor3.getRingSetting() - reflector.getRotation() + reflector.getRingSetting());
|
||||||
|
x = rotor3.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor2.getRotation() - rotor2.getRingSetting() - rotor3.getRotation() + rotor3.getRingSetting());
|
||||||
|
x = rotor2.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting() - rotor2.getRotation() + rotor2.getRingSetting());
|
||||||
|
x = rotor1.encryptBackward(x);
|
||||||
|
x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting());
|
||||||
|
x = entryWheel.encryptBackward(x);
|
||||||
|
return (char) (x + 65); //Add Offset again, cast back to char and return
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(EnigmaStateBundle state) {
|
||||||
|
this.entryWheel = getEntryWheel(0);
|
||||||
|
this.rotor1 = getRotor(state.getTypeRotor1(), state.getRotationRotor1(), state.getRingSettingRotor1());
|
||||||
|
this.rotor2 = getRotor(state.getTypeRotor2(), state.getRotationRotor2(), state.getRingSettingRotor2());
|
||||||
|
this.rotor3 = getRotor(state.getTypeRotor3(), state.getRotationRotor3(), state.getRingSettingRotor3());
|
||||||
|
this.reflector = getReflector(state.getTypeReflector(), state.getRotationReflector(), state.getRingSettingReflector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnigmaStateBundle getState()
|
||||||
|
{
|
||||||
|
EnigmaStateBundle state = new EnigmaStateBundle();
|
||||||
|
|
||||||
|
state.setTypeRotor1(rotor1.getIndex());
|
||||||
|
state.setTypeRotor2(rotor2.getIndex());
|
||||||
|
state.setTypeRotor3(rotor3.getIndex());
|
||||||
|
|
||||||
|
state.setRotationRotor1(rotor1.getRotation());
|
||||||
|
state.setRotationRotor2(rotor2.getRotation());
|
||||||
|
state.setRotationRotor3(rotor3.getRotation());
|
||||||
|
|
||||||
|
state.setRingSettingRotor1(rotor1.getRingSetting());
|
||||||
|
state.setRingSettingRotor2(rotor2.getRingSetting());
|
||||||
|
state.setRingSettingRotor3(rotor3.getRingSetting());
|
||||||
|
|
||||||
|
state.setTypeReflector(reflector.getIndex());
|
||||||
|
state.setRotationReflector(reflector.getRotation());
|
||||||
|
state.setRingSettingReflector(reflector.getRingSetting());
|
||||||
|
state.setTypeEntryWheel(entryWheel.getIndex());
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreState(BigInteger s, int protocol_version)
|
||||||
|
{
|
||||||
|
switch (protocol_version)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
int r1 = getValue(s,availableRotors.size());
|
||||||
|
s = removeDigit(s,availableRotors.size());
|
||||||
|
int r2 = getValue(s,availableRotors.size());
|
||||||
|
s = removeDigit(s,availableRotors.size());
|
||||||
|
int r3 = getValue(s,availableRotors.size());
|
||||||
|
s = removeDigit(s,availableRotors.size());
|
||||||
|
|
||||||
|
int rot1 = getValue(s,26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int ring1 = getValue(s,26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int rot2 = getValue(s,26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int ring2 = getValue(s,26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int rot3 = getValue(s,26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int ring3 = getValue(s,26);
|
||||||
|
s = removeDigit(s,26);
|
||||||
|
int rotRef = getValue(s,26);
|
||||||
|
s = removeDigit(s, 26);
|
||||||
|
int ringRef = getValue(s,26);
|
||||||
|
|
||||||
|
this.rotor1 = getRotor(r1, rot1, ring1);
|
||||||
|
this.rotor2 = getRotor(r2, rot2, ring2);
|
||||||
|
this.rotor3 = getRotor(r3, rot3, ring3);
|
||||||
|
this.reflector = getReflector(0, rotRef, ringRef);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: Log.e(MainActivity.APP_ID, "Unsupported protocol version "+protocol_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger getEncodedState(int protocol_version)
|
||||||
|
{
|
||||||
|
BigInteger s = BigInteger.valueOf(reflector.getRingSetting());
|
||||||
|
s = addDigit(s, reflector.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor3.getRingSetting(),26);
|
||||||
|
s = addDigit(s, rotor3.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor2.getRingSetting(),26);
|
||||||
|
s = addDigit(s, rotor2.getRotation(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRingSetting(), 26);
|
||||||
|
s = addDigit(s, rotor1.getRotation(), 26);
|
||||||
|
|
||||||
|
s = addDigit(s, rotor3.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor2.getIndex(), availableRotors.size());
|
||||||
|
s = addDigit(s, rotor1.getIndex(), availableRotors.size());
|
||||||
|
|
||||||
|
s = addDigit(s, 11, 20); //Machine #11
|
||||||
|
s = addDigit(s, protocol_version, MainActivity.max_protocol_version);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,164 +0,0 @@
|
||||||
package de.vanitasvitae.enigmandroid.enigma;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import de.vanitasvitae.enigmandroid.MainActivity;
|
|
||||||
import de.vanitasvitae.enigmandroid.R;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plugboard of the enigma
|
|
||||||
* Copyright (C) 2015 Paul Schaub
|
|
||||||
|
|
||||||
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 Plugboard
|
|
||||||
{
|
|
||||||
Integer[] plugs;
|
|
||||||
|
|
||||||
public Plugboard()
|
|
||||||
{
|
|
||||||
plugs = new Integer[26];
|
|
||||||
}
|
|
||||||
|
|
||||||
public Plugboard(int[][] configuration)
|
|
||||||
{
|
|
||||||
setConfiguration(configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Plugboard(String configuration)
|
|
||||||
{
|
|
||||||
setConfiguration(parseConfigurationString(configuration));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the plugboard according to the given array.
|
|
||||||
*
|
|
||||||
* @param configuration two dimensional array of plugs
|
|
||||||
*/
|
|
||||||
public void setConfiguration(int[][] configuration)
|
|
||||||
{
|
|
||||||
if(configuration != null) {
|
|
||||||
boolean validConfiguration = true;
|
|
||||||
plugs = new Integer[26];
|
|
||||||
for (int[] p : configuration) {
|
|
||||||
if (!setPlugs(p[0], p[1])) {
|
|
||||||
validConfiguration = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!validConfiguration) plugs = new Integer[26];
|
|
||||||
}
|
|
||||||
else plugs = new Integer[26];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse configuration from input string
|
|
||||||
* input must have the following form: "" or "XY" or "XY,VW" or "XY,...,AB"
|
|
||||||
* A character must not be inside the input multiple times. Exception is ','
|
|
||||||
* This is not catched here!
|
|
||||||
* @param input String that codes the configuration
|
|
||||||
* @return two dimensional array of plugged symbols
|
|
||||||
*/
|
|
||||||
public static int[][] parseConfigurationString(String input)
|
|
||||||
{
|
|
||||||
Activity activity = MainActivity.ActivitySingleton.getInstance().getActivity();
|
|
||||||
//If length != 0,2,5,8... ( ,XY, XY-VW, ...)
|
|
||||||
if(((input.length()+1)%3)!=0&&input.length()!=0)
|
|
||||||
{
|
|
||||||
Toast.makeText(activity.getApplicationContext(), R.string.error_parsing_plugs,
|
|
||||||
Toast.LENGTH_LONG).show();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
input = input.toUpperCase();
|
|
||||||
ArrayList<int[]> plugList = new ArrayList<>();
|
|
||||||
int[] plug = new int[2];
|
|
||||||
for (int i = 0; i < input.length(); i++) {
|
|
||||||
int c = input.charAt(i) - 65;
|
|
||||||
if (c < 0 || c > 25) {
|
|
||||||
if (i % 3 != 2) {
|
|
||||||
Toast.makeText(activity.getApplicationContext(), R.string.error_parsing_plugs,
|
|
||||||
Toast.LENGTH_LONG).show();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (i % 3 == 0) {
|
|
||||||
plug = new int[2];
|
|
||||||
plug[0] = c;
|
|
||||||
}
|
|
||||||
if (i % 3 == 1) {
|
|
||||||
plug[1] = c;
|
|
||||||
plugList.add(plug);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int[][] parsedConfiguration = new int[plugList.size()][2];
|
|
||||||
for(int i=0; i<plugList.size(); i++)
|
|
||||||
{
|
|
||||||
parsedConfiguration[i] = plugList.get(i);
|
|
||||||
}
|
|
||||||
return parsedConfiguration;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the given plugs (connect a and b)
|
|
||||||
* Return false, if something goes wrong (plugs already used somehow)
|
|
||||||
* @param a first plug
|
|
||||||
* @param b second plug
|
|
||||||
* @return success
|
|
||||||
*/
|
|
||||||
public boolean setPlugs(int a, int b)
|
|
||||||
{
|
|
||||||
Activity activity = MainActivity.ActivitySingleton.getInstance().getActivity();
|
|
||||||
if(a==b)
|
|
||||||
{
|
|
||||||
Toast.makeText(activity.getApplication().getApplicationContext(),
|
|
||||||
activity.getResources().getText(R.string.error_unable_to_plug_a_b).toString()
|
|
||||||
+" "+(char)(a+65)+","+(char) (b+65),Toast.LENGTH_LONG).show();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(plugs[a] != null || plugs[b] != null)
|
|
||||||
{
|
|
||||||
Toast.makeText(activity.getApplication().getApplicationContext(),
|
|
||||||
activity.getResources().getText(R.string.error_plug_already_in_use).toString()
|
|
||||||
+" "+(char) (a+65)+","+(char)(b +65), Toast.LENGTH_SHORT).show();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
plugs[a] = b;
|
|
||||||
plugs[b] = a;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encrypt input via plugboard connections
|
|
||||||
* @param input input symbol to encrypt
|
|
||||||
* @return encrypted symbol
|
|
||||||
*/
|
|
||||||
public int encrypt(int input)
|
|
||||||
{
|
|
||||||
if(plugs[input]==null) return input;
|
|
||||||
else return plugs[input];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma.inputPreparer;
|
||||||
|
|
||||||
|
import android.widget.EditText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter-like connector between text fields and string-outputting-whatever blah
|
||||||
|
* Use this to modify the way strings get displayed without modifying the string itself.
|
||||||
|
*/
|
||||||
|
public abstract class EditTextAdapter
|
||||||
|
{
|
||||||
|
EditText editText;
|
||||||
|
String content;
|
||||||
|
|
||||||
|
EditTextAdapter(EditText editText)
|
||||||
|
{
|
||||||
|
this.editText = editText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the unmodified text
|
||||||
|
* @return content
|
||||||
|
*/
|
||||||
|
public String getText()
|
||||||
|
{
|
||||||
|
if(editText.getText().length() != 0)
|
||||||
|
return content;
|
||||||
|
else return content = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModifiedText()
|
||||||
|
{
|
||||||
|
return editText.getText().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the text to both the content and the editText without modifying it
|
||||||
|
* @param text text
|
||||||
|
*/
|
||||||
|
public void setRawText(String text)
|
||||||
|
{
|
||||||
|
this.content = text;
|
||||||
|
this.editText.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method needs to be overwritten by the programmer.
|
||||||
|
* The coder has to make sure, content gets set to text and also that the editText element
|
||||||
|
* gets updated with the modified text
|
||||||
|
* @param text text
|
||||||
|
*/
|
||||||
|
public abstract void setText(String text);
|
||||||
|
|
||||||
|
public static EditTextAdapter createEditTextAdapter(EditText editText, String type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case "4": return new EditTextAdapterGap(editText, 4);
|
||||||
|
case "5": return new EditTextAdapterGap(editText, 5);
|
||||||
|
case "6": return new EditTextAdapterGap(editText, 6);
|
||||||
|
case "no": return new EditTextAdapterNoGap(editText);
|
||||||
|
default: return new EditTextAdapterNoGap(editText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EditTextAdapterNoGap extends EditTextAdapter
|
||||||
|
{
|
||||||
|
public EditTextAdapterNoGap(EditText editText)
|
||||||
|
{
|
||||||
|
super(editText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setText(String text)
|
||||||
|
{
|
||||||
|
this.content = text;
|
||||||
|
this.editText.setText(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EditTextAdapterGap extends EditTextAdapter
|
||||||
|
{
|
||||||
|
int blockSize;
|
||||||
|
public EditTextAdapterGap(EditText editText, int blockSize)
|
||||||
|
{
|
||||||
|
super(editText);
|
||||||
|
this.blockSize = blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setText(String text)
|
||||||
|
{
|
||||||
|
this.content = text;
|
||||||
|
String out = "";
|
||||||
|
int i;
|
||||||
|
for(i=0; i<text.length()/blockSize; i++)
|
||||||
|
{
|
||||||
|
out = out + text.substring(i*blockSize, (i+1)*blockSize);
|
||||||
|
out = out + " ";
|
||||||
|
}
|
||||||
|
out = out + text.substring(i*blockSize);
|
||||||
|
this.editText.setText(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,146 +1,253 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package de.vanitasvitae.enigmandroid.enigma.inputPreparer;
|
package de.vanitasvitae.enigmandroid.enigma.inputPreparer;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
import de.vanitasvitae.enigmandroid.SettingsActivity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preparer 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
|
|
||||||
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 InputPreparer
|
public abstract class InputPreparer {
|
||||||
{
|
InputPreparer child;
|
||||||
/**
|
|
||||||
* Prepare the input String in a way that it only contains letters from [A..Z].
|
|
||||||
* Replace special characters, remove spaces and spell numbers.
|
|
||||||
* @param input String
|
|
||||||
* @return prepared String
|
|
||||||
*/
|
|
||||||
public String prepareString(String input)
|
|
||||||
{
|
|
||||||
input = input.toUpperCase();
|
|
||||||
input = input.replace("Ä","AE").replace("Ö","OE").replace("Ü","UE").replace("ß","SS");
|
|
||||||
String output = "";
|
|
||||||
|
|
||||||
for (char x : input.toCharArray())
|
public String prepareString(String in) {
|
||||||
|
if (child != null)
|
||||||
|
return child.prepareString(this.prepare(in));
|
||||||
|
else
|
||||||
|
return prepare(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String prepare(String input);
|
||||||
|
|
||||||
|
public static InputPreparer createInputPreparer()
|
||||||
|
{
|
||||||
|
MainActivity main = (MainActivity) MainActivity.ActivitySingleton.getInstance().getActivity();
|
||||||
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(main);
|
||||||
|
|
||||||
|
boolean replaceSpecialChars = sharedPreferences.getBoolean(SettingsActivity.PREF_REPLACE_SPECIAL_CHARACTERS, true);
|
||||||
|
String num_lang = sharedPreferences.getString(SettingsActivity.PREF_NUMERIC_LANGUAGE, main.getResources().
|
||||||
|
getStringArray(R.array.pref_alias_numeric_spelling_language)[0]);
|
||||||
|
InputPreparer inPrep = new RemoveIllegalCharacters();
|
||||||
|
if(replaceSpecialChars) inPrep = new ReplaceSpecialCharacters(inPrep);
|
||||||
|
switch (num_lang)
|
||||||
{
|
{
|
||||||
if (x >= 65 && x <= 90) //x in [A..Z]
|
case "de": inPrep = new ReplaceNumbersGerman(inPrep);
|
||||||
{
|
break;
|
||||||
output = output + x;
|
case "en": inPrep = new ReplaceNumbersEnglish(inPrep);
|
||||||
}
|
break;
|
||||||
else if (x >= 48 && x <= 57) //x in [0..9]
|
case "fr": inPrep = new ReplaceNumbersFrench(inPrep);
|
||||||
{
|
break;
|
||||||
output = output + replaceNumber(x);
|
case "sp": inPrep = new ReplaceNumbersSpanish(inPrep);
|
||||||
}
|
break;
|
||||||
//x is special symbol
|
case "it": inPrep = new ReplaceNumbersItalian(inPrep);
|
||||||
else if (x != ' ')
|
break;
|
||||||
{
|
default:
|
||||||
output = output + 'X';
|
break;
|
||||||
}
|
}
|
||||||
|
return inPrep;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ReplaceSpecialCharacters extends InputPreparer {
|
||||||
|
// --Commented out by Inspection START (07.11.15 19:47):
|
||||||
|
// public ReplaceSpecialCharacters() {
|
||||||
|
// this.child = null;
|
||||||
|
// }
|
||||||
|
// --Commented out by Inspection STOP (07.11.15 19:47)
|
||||||
|
|
||||||
|
public ReplaceSpecialCharacters(InputPreparer child) {
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String prepare(String input) {
|
||||||
|
input = input.toUpperCase();
|
||||||
|
return input.replace("Ä", "AE").replace("Ö", "OE").replace("Ü", "UE").replace("ß", "SS").replace(" ","");
|
||||||
}
|
}
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract method that spells numbers in a certain language specified by the implementation
|
* Concrete implementation of a german InputPreparer
|
||||||
* @param input character
|
|
||||||
* @return spelled number
|
|
||||||
*/
|
*/
|
||||||
public abstract String replaceNumber(char input);
|
public static class ReplaceNumbersGerman extends InputPreparer {
|
||||||
|
// --Commented out by Inspection START (07.11.15 19:47):
|
||||||
|
// public ReplaceNumbersGerman() {
|
||||||
|
// this.child = null;
|
||||||
|
// }
|
||||||
|
// --Commented out by Inspection STOP (07.11.15 19:47)
|
||||||
|
|
||||||
|
public ReplaceNumbersGerman(InputPreparer child) {
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String prepare(String input) {
|
||||||
|
input = input.replace("0", "NULL")
|
||||||
|
.replace("1", "EINS")
|
||||||
|
.replace("2", "ZWEI")
|
||||||
|
.replace("3", "DREI")
|
||||||
|
.replace("4", "VIER")
|
||||||
|
.replace("5", "FUENF")
|
||||||
|
.replace("6", "SECHS")
|
||||||
|
.replace("7", "SIEBEN")
|
||||||
|
.replace("8", "ACHT")
|
||||||
|
.replace("9", "NEUN");
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method that creates a specific InputPreparer
|
* Concrete implementation of a french InputPreparer
|
||||||
* @param language language alias that specifies the language (de,fr,en)
|
|
||||||
* @return concrete InputPreparer
|
|
||||||
*/
|
*/
|
||||||
public static InputPreparer createInputPreparer(String language)
|
public static class ReplaceNumbersFrench extends InputPreparer {
|
||||||
|
// --Commented out by Inspection START (07.11.15 19:47):
|
||||||
|
// public ReplaceNumbersFrench() {
|
||||||
|
// this.child = null;
|
||||||
|
// }
|
||||||
|
// --Commented out by Inspection STOP (07.11.15 19:47)
|
||||||
|
|
||||||
|
public ReplaceNumbersFrench(InputPreparer child) {
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String prepare(String input) {
|
||||||
|
input = input.replace("0", "ZERO")
|
||||||
|
.replace("1", "UN")
|
||||||
|
.replace("2", "DEUX")
|
||||||
|
.replace("3", "TROIS")
|
||||||
|
.replace("4", "QUATRE")
|
||||||
|
.replace("5", "CINQ")
|
||||||
|
.replace("6", "SIX")
|
||||||
|
.replace("7", "SEPT")
|
||||||
|
.replace("8", "HUIT")
|
||||||
|
.replace("9", "NEUF");
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of an english InputPreparer
|
||||||
|
*/
|
||||||
|
public static class ReplaceNumbersEnglish extends InputPreparer {
|
||||||
|
// --Commented out by Inspection START (07.11.15 19:47):
|
||||||
|
// public ReplaceNumbersEnglish() {
|
||||||
|
// this.child = null;
|
||||||
|
// }
|
||||||
|
// --Commented out by Inspection STOP (07.11.15 19:47)
|
||||||
|
|
||||||
|
public ReplaceNumbersEnglish(InputPreparer child) {
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String prepare(String input) {
|
||||||
|
input = input.replace("0", "ZERO")
|
||||||
|
.replace("1", "ONE")
|
||||||
|
.replace("2", "TWO")
|
||||||
|
.replace("3", "THREE")
|
||||||
|
.replace("4", "FOUR")
|
||||||
|
.replace("5", "FIVE")
|
||||||
|
.replace("6", "SIX")
|
||||||
|
.replace("7", "SEVEN")
|
||||||
|
.replace("8", "EIGHT")
|
||||||
|
.replace("9", "NINE");
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of a spanish InputPreparer
|
||||||
|
*/
|
||||||
|
public static class ReplaceNumbersSpanish extends InputPreparer {
|
||||||
|
// --Commented out by Inspection START (07.11.15 19:47):
|
||||||
|
// public ReplaceNumbersSpanish() {
|
||||||
|
// this.child = null;
|
||||||
|
// }
|
||||||
|
// --Commented out by Inspection STOP (07.11.15 19:47)
|
||||||
|
|
||||||
|
public ReplaceNumbersSpanish(InputPreparer child) {
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String prepare(String input) {
|
||||||
|
input = input.replace("0", "CERO")
|
||||||
|
.replace("1", "UNO")
|
||||||
|
.replace("2", "DOS")
|
||||||
|
.replace("3", "TRES")
|
||||||
|
.replace("4", "CUATRO")
|
||||||
|
.replace("5", "CINCO")
|
||||||
|
.replace("6", "SEIS")
|
||||||
|
.replace("7", "SIETE")
|
||||||
|
.replace("8", "OCHO")
|
||||||
|
.replace("9", "NUEVE");
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of a spanish InputPreparer
|
||||||
|
*/
|
||||||
|
public static class ReplaceNumbersItalian extends InputPreparer {
|
||||||
|
// --Commented out by Inspection START (07.11.15 19:47):
|
||||||
|
// public ReplaceNumbersItalian() {
|
||||||
|
// this.child = null;
|
||||||
|
// }
|
||||||
|
// --Commented out by Inspection STOP (07.11.15 19:47)
|
||||||
|
|
||||||
|
public ReplaceNumbersItalian(InputPreparer child) {
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String prepare(String input) {
|
||||||
|
input = input.replace("0", "ZERO")
|
||||||
|
.replace("1", "UNO")
|
||||||
|
.replace("2", "DUE")
|
||||||
|
.replace("3", "TRE")
|
||||||
|
.replace("4", "QUATTRO")
|
||||||
|
.replace("5", "CINQUE")
|
||||||
|
.replace("6", "SEI")
|
||||||
|
.replace("7", "SETTE")
|
||||||
|
.replace("8", "OTTO")
|
||||||
|
.replace("9", "NOVE");
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Final Stage" of Input preparing. This should always be called last
|
||||||
|
* (choose this as the inner most capsule of InputPreparers)
|
||||||
|
* This cant have child InputPreparers.
|
||||||
|
* This Input preparer removes all characters from the string besides A..Z
|
||||||
|
*/
|
||||||
|
public static class RemoveIllegalCharacters extends InputPreparer
|
||||||
{
|
{
|
||||||
switch (language)
|
public RemoveIllegalCharacters()
|
||||||
{
|
{
|
||||||
case "de": return new InputPreparerGerman();
|
this.child = null;
|
||||||
case "fr": return new InputPreparerFrench();
|
|
||||||
default: return new InputPreparerEnglish();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
protected String prepare(String in)
|
||||||
* Concrete implementation of a german InputPreparer
|
|
||||||
*/
|
|
||||||
class InputPreparerGerman extends InputPreparer
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public String replaceNumber(char input) {
|
|
||||||
switch (input)
|
|
||||||
{
|
{
|
||||||
case '0': return "NULL";
|
String out = "";
|
||||||
case '1': return "EINS";
|
for(char c : in.toUpperCase().toCharArray())
|
||||||
case '2': return "ZWEI";
|
{
|
||||||
case '3': return "DREI";
|
if(c>=65 && c<=90) out = out+c;
|
||||||
case '4': return "VIER";
|
}
|
||||||
case '5': return "FUENF";
|
return out;
|
||||||
case '6': return "SECHS";
|
|
||||||
case '7': return "SIEBEN";
|
|
||||||
case '8': return "ACHT";
|
|
||||||
default: return "NEUN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concrete implementation of an english InputPreparer
|
|
||||||
*/
|
|
||||||
class InputPreparerEnglish extends InputPreparer
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public String replaceNumber(char input)
|
|
||||||
{
|
|
||||||
switch (input) {
|
|
||||||
case '0': return "ZERO";
|
|
||||||
case '1': return "ONE";
|
|
||||||
case '2': return "TWO";
|
|
||||||
case '3': return "THREE";
|
|
||||||
case '4': return "FOUR";
|
|
||||||
case '5': return "FIVE";
|
|
||||||
case '6': return "SIX";
|
|
||||||
case '7': return "SEVEN";
|
|
||||||
case '8': return "EIGHT";
|
|
||||||
default: return "NINE";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concrete implementation of a french InputPreparer
|
|
||||||
*/
|
|
||||||
class InputPreparerFrench extends InputPreparer
|
|
||||||
{
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String replaceNumber(char input)
|
|
||||||
{
|
|
||||||
switch (input) {
|
|
||||||
case '0': return "ZERO";
|
|
||||||
case '1': return "UN";
|
|
||||||
case '2': return "DEUX";
|
|
||||||
case '3': return "TROIS";
|
|
||||||
case '4': return "QUATRE";
|
|
||||||
case '5': return "CINQ";
|
|
||||||
case '6': return "SIX";
|
|
||||||
case '7': return "SEPT";
|
|
||||||
case '8': return "HUIT";
|
|
||||||
default: return "NEUF";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma.parts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of several EntryWheels
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class EntryWheel
|
||||||
|
{
|
||||||
|
private final int type;
|
||||||
|
private final String name;
|
||||||
|
private int index;
|
||||||
|
private final String summary;
|
||||||
|
private final Integer[] connections;
|
||||||
|
private final Integer[] reversedConnections;
|
||||||
|
|
||||||
|
EntryWheel(int type, String name, String summary, Integer[] connections, Integer[] reversedConnections)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
this.name = name;
|
||||||
|
this.summary = summary;
|
||||||
|
this.connections = connections;
|
||||||
|
this.reversedConnections = reversedConnections;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new EntryWheel of the same type as the callee
|
||||||
|
* @return new EntryWheel
|
||||||
|
*/
|
||||||
|
public EntryWheel getInstance()
|
||||||
|
{
|
||||||
|
return createEntryWheel(this.type).setIndex(this.getIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt an input signal via the internal wiring in "forward" direction towards the reflector
|
||||||
|
* (using connections)
|
||||||
|
* @param input signal
|
||||||
|
* @return encrypted signal
|
||||||
|
*/
|
||||||
|
public int encryptForward(int input)
|
||||||
|
{
|
||||||
|
return this.connections[normalize(input)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private int normalize(int input)
|
||||||
|
{
|
||||||
|
return (input+this.connections.length)%this.connections.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntryWheel setIndex(int index)
|
||||||
|
{
|
||||||
|
this.index = index;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex()
|
||||||
|
{
|
||||||
|
return this.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt an input signal via the internal wiring in "backwards" direction (using
|
||||||
|
* reversedConnections)
|
||||||
|
* @param input signal
|
||||||
|
* @return encrypted signal
|
||||||
|
*/
|
||||||
|
public int encryptBackward(int input)
|
||||||
|
{
|
||||||
|
return this.reversedConnections[normalize(input)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private EntryWheel createEntryWheel(int type)
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return new EntryWheel_QWERTZ();
|
||||||
|
case 2:
|
||||||
|
return new EntryWheel_T();
|
||||||
|
default: return new EntryWheel_ABCDEF();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EntryWheel_ABCDEF extends EntryWheel
|
||||||
|
{
|
||||||
|
public EntryWheel_ABCDEF()
|
||||||
|
{
|
||||||
|
super(0, "ABCDEF", "abcdefghijklmnopqrstuvwxyz",
|
||||||
|
new Integer[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25},
|
||||||
|
new Integer[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EntryWheel as used in the Enigma models D, K, G
|
||||||
|
* Q W E R T Z U I O A S D F G H J K P Y X C V B N M L
|
||||||
|
*/
|
||||||
|
public static class EntryWheel_QWERTZ extends EntryWheel
|
||||||
|
{
|
||||||
|
public EntryWheel_QWERTZ()
|
||||||
|
{
|
||||||
|
super(1, "QWERTZ", "qwertzuioasdfghjkpyxcvbnml",
|
||||||
|
new Integer[]{9,22,20,11,2,12,13,14,7,15,16,25,24,23,8,17,0,3,10,4,6,21,1,19,18,5},
|
||||||
|
new Integer[]{16,22,4,17,19,25,20,8,14,0,18,3,5,6,7,9,10,15,24,23,2,21,1,13,12,11});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EntryWheel as used only in the Enigma Type T Tirpitz
|
||||||
|
* K Z R O U Q H Y A I G B L W V S T D X F P N M C J E
|
||||||
|
*/
|
||||||
|
public static class EntryWheel_T extends EntryWheel
|
||||||
|
{
|
||||||
|
public EntryWheel_T()
|
||||||
|
{
|
||||||
|
super(2, "KZROUQ", "kzrouqhyaigblwvstdxfpnmcje",
|
||||||
|
new Integer[]{8,11,23,17,25,19,10,6,9,24,0,12,22,21,3,20,5,2,15,16,4,14,13,18,7,1},
|
||||||
|
new Integer[]{10,25,17,14,20,16,7,24,0,8,6,1,11,22,21,18,19,3,23,5,15,13,12,2,9,4});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,219 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma.parts;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.inputPreparer.InputPreparer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugboard of the enigma
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class Plugboard
|
||||||
|
{
|
||||||
|
private static final int[] empty = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25};
|
||||||
|
private int[] plugs;
|
||||||
|
|
||||||
|
public Plugboard()
|
||||||
|
{
|
||||||
|
plugs = Arrays.copyOf(empty, empty.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Plugboard(int[] conf)
|
||||||
|
{
|
||||||
|
this.plugs = conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfiguration(int[] conf)
|
||||||
|
{
|
||||||
|
this.plugs = conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("UnusedReturnValue")
|
||||||
|
public BigInteger setConfiguration(BigInteger b)
|
||||||
|
{
|
||||||
|
String s = "";
|
||||||
|
|
||||||
|
int x;
|
||||||
|
while((x = Enigma.getValue(b, 27)) != 26 && b.compareTo(BigInteger.ZERO) > 1)
|
||||||
|
{
|
||||||
|
s = ((char) (x+65))+s;
|
||||||
|
b = Enigma.removeDigit(b, 27);
|
||||||
|
}
|
||||||
|
this.setConfiguration(stringToConfiguration(s));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] getConfiguration()
|
||||||
|
{
|
||||||
|
return this.plugs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt input via plugboard connections
|
||||||
|
* @param input input symbol to encryptString
|
||||||
|
* @return encrypted symbol
|
||||||
|
*/
|
||||||
|
public int encrypt(int input)
|
||||||
|
{
|
||||||
|
return plugs[(input+plugs.length)%plugs.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interpret a String of Pairs as a configuration for the plugboard
|
||||||
|
* Any char with an even index is connected to the successor.
|
||||||
|
* in must not contain duplicates!
|
||||||
|
* @param in String representation of pairs (eg. AXBHCS...)
|
||||||
|
* @return connections as int[]
|
||||||
|
*/
|
||||||
|
public static int[] stringToConfiguration(String in)
|
||||||
|
{
|
||||||
|
String pairs = trimString(new InputPreparer.RemoveIllegalCharacters().prepareString(in));
|
||||||
|
int[] out = Arrays.copyOf(empty, empty.length);
|
||||||
|
//Check if in is too long or odd
|
||||||
|
int l = pairs.length();
|
||||||
|
if(l>1 && (pairs.length() > 26 || pairs.length()/2 == (pairs.length()-1)/2))
|
||||||
|
{
|
||||||
|
//Odd length. remove last char. Information loss!
|
||||||
|
pairs = pairs.substring(0,pairs.length()-1);
|
||||||
|
}
|
||||||
|
//Modify out
|
||||||
|
for(int i=0; i<pairs.length()/2; i++)
|
||||||
|
{
|
||||||
|
int a = (int) (pairs.toCharArray()[i*2])-65;
|
||||||
|
int b = (int) (pairs.toCharArray()[(i*2)+1])-65;
|
||||||
|
out[a] = b;
|
||||||
|
out[b] = a;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all duplicate chars x from the String except the first appearance of x.
|
||||||
|
* String MUST be in upper case!
|
||||||
|
* @param in String
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
private static String trimString(String in)
|
||||||
|
{
|
||||||
|
in = in.toUpperCase();
|
||||||
|
for(int i=0; i<26; i++)
|
||||||
|
{
|
||||||
|
char x = (char)(i+65);
|
||||||
|
int index = in.indexOf(""+x);
|
||||||
|
if(index != in.lastIndexOf(""+x))
|
||||||
|
{
|
||||||
|
//Remove all duplicates of x
|
||||||
|
in = in.substring(0, index) + in.substring(index+1).replace(""+x,"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a configuration from a seeded PRNG.
|
||||||
|
* Not all connections have to be done.
|
||||||
|
* @param rand Seeded PRNG
|
||||||
|
* @return configuration
|
||||||
|
*/
|
||||||
|
public static int[] seedToPlugboardConfiguration(Random rand)
|
||||||
|
{
|
||||||
|
int connectionCount = rand.nextInt(14); //0..13
|
||||||
|
int[] out = empty;
|
||||||
|
for(int i=0; i<connectionCount; i++)
|
||||||
|
{
|
||||||
|
int rA = rand.nextInt(26);
|
||||||
|
while(out[rA] != rA) rA = (rA+1)%26;
|
||||||
|
int rB = rand.nextInt(26);
|
||||||
|
while(out[rB] != rB) rB = (rB+1)%26;
|
||||||
|
out[rA] = rB;
|
||||||
|
out[rB] = rA;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a configuration with full set of connections from a seeded PRNG
|
||||||
|
* @param rand Seeded PRNG
|
||||||
|
* @return configuration
|
||||||
|
*/
|
||||||
|
public static int[] seedToReflectorConfiguration(Random rand)
|
||||||
|
{
|
||||||
|
int[] out = Arrays.copyOf(empty,empty.length);
|
||||||
|
for (int i=0; i<out.length/2; i++) {
|
||||||
|
int rA = rand.nextInt(26);
|
||||||
|
while (out[rA] != rA) rA = (rA + 27) % 26;
|
||||||
|
int rB = rand.nextInt(26);
|
||||||
|
while (out[rB] != rB || rA == rB) rB = (rB + 27) % 26;
|
||||||
|
out[rA] = rB;
|
||||||
|
out[rB] = rA;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a configurations array back to a String representation
|
||||||
|
* @param c array
|
||||||
|
* @return String representation
|
||||||
|
*/
|
||||||
|
private static String configurationToString(int[] c)
|
||||||
|
{
|
||||||
|
String out = "";
|
||||||
|
for(int i=0; i<c.length; i++) // c.length = 26 (mostly)
|
||||||
|
{
|
||||||
|
if(c[i] != i && out.indexOf((char)(c[i])+65)==-1)
|
||||||
|
{
|
||||||
|
out += (char) (i+65);
|
||||||
|
out += (char) (c[i]+65);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BigInteger configurationToBigInteger(int[] a)
|
||||||
|
{
|
||||||
|
String s = configurationToString(a);
|
||||||
|
BigInteger l = BigInteger.ZERO;
|
||||||
|
l = Enigma.addDigit(l,26,27);
|
||||||
|
for(char c : s.toCharArray())
|
||||||
|
{
|
||||||
|
int i = (int) (c);
|
||||||
|
i-=65;
|
||||||
|
l = Enigma.addDigit(l,i,27);
|
||||||
|
}
|
||||||
|
Log.d(MainActivity.APP_ID, "Save configuration plugs: "+l.toString());
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] bigIntegerToConfiguration(BigInteger b)
|
||||||
|
{
|
||||||
|
String s = "";
|
||||||
|
int x;
|
||||||
|
while((x = Enigma.getValue(b, 27)) != 26 && b.compareTo(BigInteger.ZERO) > 1)
|
||||||
|
{
|
||||||
|
s = ((char) (x+65))+s;
|
||||||
|
b = Enigma.removeDigit(b, 27);
|
||||||
|
}
|
||||||
|
Log.d(MainActivity.APP_ID, "Restored: "+s);
|
||||||
|
return stringToConfiguration(s);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,355 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.enigma.parts;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reflector of the enigma machine.
|
||||||
|
* The reflector was used to reflect the scrambled signal at the end of the wiring back to
|
||||||
|
* go through another (reversed but not inverting) process of scrambling.
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class Reflector
|
||||||
|
{
|
||||||
|
private final int type;
|
||||||
|
private final String name;
|
||||||
|
private int index;
|
||||||
|
private final String summary;
|
||||||
|
private int[] connections;
|
||||||
|
private int rotation;
|
||||||
|
private int ringSetting;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This constructor is not accessible from outside this class file.
|
||||||
|
* Use the one of the createReflector* methods instead to create concrete Reflectors from
|
||||||
|
* outside this class file
|
||||||
|
* @param type name indicator of the reflector
|
||||||
|
* @param connections wiring of the reflector as Integer array
|
||||||
|
*/
|
||||||
|
Reflector(int type, String name, String summary, int[] connections)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
this.name = name;
|
||||||
|
this.summary = summary;
|
||||||
|
this.connections = connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reflector getInstance()
|
||||||
|
{
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
return createReflector(this.type).setIndex(this.getIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reflector getInstance(int rotation, int ringSetting)
|
||||||
|
{
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
return createReflector(this.type).setIndex(this.getIndex())
|
||||||
|
.setRotation(rotation).setRingSetting(ringSetting);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reflector setIndex(int index)
|
||||||
|
{
|
||||||
|
this.index = index;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex()
|
||||||
|
{
|
||||||
|
return this.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRotation()
|
||||||
|
{
|
||||||
|
return rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRingSetting()
|
||||||
|
{
|
||||||
|
return ringSetting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reflector setRotation(int rotation)
|
||||||
|
{
|
||||||
|
this.rotation = rotation;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reflector setRingSetting(int ringSetting)
|
||||||
|
{
|
||||||
|
this.ringSetting = ringSetting;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reflector setConfiguration(int[] c)
|
||||||
|
{
|
||||||
|
this.connections = c;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("UnusedReturnValue")
|
||||||
|
public BigInteger setConfiguration(BigInteger b)
|
||||||
|
{
|
||||||
|
String s = "";
|
||||||
|
|
||||||
|
int x;
|
||||||
|
while((x = Enigma.getValue(b, 27)) != 26 || b.compareTo(BigInteger.ZERO) > 1)
|
||||||
|
{
|
||||||
|
s = ((char) (x+65))+s;
|
||||||
|
b = Enigma.removeDigit(b, 27);
|
||||||
|
}
|
||||||
|
Log.d(MainActivity.APP_ID, "Restored: " + s);
|
||||||
|
this.setConfiguration(Plugboard.stringToConfiguration(s));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] getConfiguration()
|
||||||
|
{
|
||||||
|
return connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to create reflectors.
|
||||||
|
* @param type name of the created reflector
|
||||||
|
* 1 -> ReflectorA
|
||||||
|
* 2 -> ReflectorB
|
||||||
|
* 3 -> ReflectorC
|
||||||
|
* 4 -> ReflectorThinB
|
||||||
|
* 5 -> ReflectorThinC
|
||||||
|
* 6 -> ReflectorEnigma_D_KD_G31
|
||||||
|
* 7 -> Reflector_K
|
||||||
|
* 8 -> Reflector_T
|
||||||
|
* 9 -> Reflector_G312
|
||||||
|
* 10 -> Reflector_G260
|
||||||
|
* 11 -> Reflector_R
|
||||||
|
* default -> ReflectorB
|
||||||
|
* @return Reflector
|
||||||
|
*/
|
||||||
|
private static Reflector createReflector(int type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 0: return new Reflector_A();
|
||||||
|
case 1: return new Reflector_B();
|
||||||
|
case 2: return new Reflector_C();
|
||||||
|
case 10: return new Reflector_Thin_B();
|
||||||
|
case 11: return new ReflectorThinC();
|
||||||
|
case 20: return new ReflectorEnigma_D_G31();
|
||||||
|
case 21: return new ReflectorEnigma_KD();
|
||||||
|
case 30: return new Reflector_G312();
|
||||||
|
case 40: return new Reflector_K_G260();
|
||||||
|
case 50: return new Reflector_R();
|
||||||
|
case 60: return new ReflectorEnigma_T();
|
||||||
|
|
||||||
|
default:
|
||||||
|
Log.e(MainActivity.APP_ID," Tried to create Reflector of invalid name "+type);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Substitute an input signal via the wiring of the reflector with a different (!) output.
|
||||||
|
* The output MUST not be equal to the input for any input, since this was not possible
|
||||||
|
* due to the electronic implementation of the historical enigma machine.
|
||||||
|
* @param input input signal
|
||||||
|
* @return encrypted (substituted) output
|
||||||
|
*/
|
||||||
|
public int encrypt(int input)
|
||||||
|
{
|
||||||
|
return this.connections[normalize(input)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the size (ie the number of wires/length of the connections array) of the reflector
|
||||||
|
* @return size
|
||||||
|
*/
|
||||||
|
private int getRotorSize()
|
||||||
|
{
|
||||||
|
return this.connections.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 reflector. This is necessary since java allows negative modulo values,
|
||||||
|
* which can break this implementation
|
||||||
|
* @param input input signal
|
||||||
|
* @return "normalized" input signal
|
||||||
|
*/
|
||||||
|
private int normalize(int input)
|
||||||
|
{
|
||||||
|
return (input + this.getRotorSize()) % this.getRotorSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of ReflectorA
|
||||||
|
* Used in Enigma I
|
||||||
|
* AE BJ CM DZ FL GY HX IV KW NR OQ PU ST
|
||||||
|
*/
|
||||||
|
public static class Reflector_A extends Reflector
|
||||||
|
{
|
||||||
|
public Reflector_A()
|
||||||
|
{
|
||||||
|
super(0, "A", "EJMZALYXVBWFCRQUONTSPIKHGD",
|
||||||
|
new int[]{4,9,12,25,0,11,24,23,21,1,22,5,2,17,16,20,14,13,19,18,15,8,10,7,6,3});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of ReflectorB
|
||||||
|
* Used in Enigma I, M3
|
||||||
|
* AY BR CU DH EQ FS GL IP JX KN MO TZ VW
|
||||||
|
*/
|
||||||
|
public static class Reflector_B extends Reflector
|
||||||
|
{
|
||||||
|
public Reflector_B()
|
||||||
|
{
|
||||||
|
super(1, "B", "YRUHQSLDPXNGOKMIEBFZCWVJAT",
|
||||||
|
new int[]{24,17,20,7,16,18,11,3,15,23,13,6,14,10,12,8,4,1,5,25,2,22,21,9,0,19});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of ReflectorC
|
||||||
|
* Used in Enigma I, M3
|
||||||
|
* AF BV CP DJ EI GO HY KR LZ MX NW QT SU
|
||||||
|
*/
|
||||||
|
public static class Reflector_C extends Reflector
|
||||||
|
{
|
||||||
|
public Reflector_C()
|
||||||
|
{
|
||||||
|
super(2, "C", "FVPJIAOYEDRZXWGCTKUGSBNMHL",
|
||||||
|
new int[]{5,21,15,9,8,0,14,24,4,3,17,25,23,22,6,2,19,10,20,16,18,1,13,12,7,11});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of thin reflector name b (not equal to normal name 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
|
||||||
|
*/
|
||||||
|
public static class Reflector_Thin_B extends Reflector
|
||||||
|
{
|
||||||
|
public Reflector_Thin_B()
|
||||||
|
{
|
||||||
|
super(10, "Thin-B", "ENKQAUYWJICOPBLMDXZVFTHRGS",
|
||||||
|
new int[]{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 name c (not equal to normal name 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
|
||||||
|
*/
|
||||||
|
public static class ReflectorThinC extends Reflector
|
||||||
|
{
|
||||||
|
public ReflectorThinC()
|
||||||
|
{
|
||||||
|
super(11, "ThinC", "RDOBJNTKVEHMLFCWZAXGYIPSUQ",
|
||||||
|
new int[]{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});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pluggable Reflector of the Enigma machine of name D and G31
|
||||||
|
* Standard wiring: AI,BM,CE,DT,FG,HR,JY,KS,LQ,NZ,OX,PW,UV
|
||||||
|
* Has additional ringSetting and can rotate
|
||||||
|
*/
|
||||||
|
public static class ReflectorEnigma_D_G31 extends Reflector
|
||||||
|
{
|
||||||
|
public static final int[] defaultWiring_D_G31 = {8,12,4,19,2,6,5,17,0,24,18,16,1,25,23,22,11,7,10,3,21,20,15,14,9,13};
|
||||||
|
public ReflectorEnigma_D_G31()
|
||||||
|
{
|
||||||
|
super(20, "Ref-D", "Default: IMETCGFRAYSQBZXWLHKDVUPOJN", Arrays.copyOf(defaultWiring_D_G31,defaultWiring_D_G31.length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pluggable Reflector as used in the Enigma of Type KD
|
||||||
|
* Standard wiring: KOTVPNLMJIAGHFBEWYXCZDQSRU
|
||||||
|
* Has additional ringSetting and can rotate
|
||||||
|
*/
|
||||||
|
public static class ReflectorEnigma_KD extends Reflector
|
||||||
|
{
|
||||||
|
public static final int[] defaultWiring_KD = {10,14,19,21,15,13,11,12,9,8,0,6,7,5,1,4,22,24,23,2,25,3,16,18,17,20};
|
||||||
|
public ReflectorEnigma_KD()
|
||||||
|
{
|
||||||
|
super(21, "Ref-KD", "Default: KOTVPNLMJIAGHFBEWYXCZDQSRU", Arrays.copyOf(defaultWiring_KD, defaultWiring_KD.length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reflector as used in the Enigma name G-312 Abwehr
|
||||||
|
* R U L Q M Z J S Y G O C E T K W D A H N B X P V I F
|
||||||
|
*/
|
||||||
|
public static class Reflector_G312 extends Reflector
|
||||||
|
{
|
||||||
|
public Reflector_G312()
|
||||||
|
{
|
||||||
|
super(30, "Ref-G312", "RULQMZJSYGOCETKWDAHNBXPVIF",
|
||||||
|
new int[]{17,20,11,16,12,25,9,18,24,6,14,2,4,19,10,22,3,0,7,13,1,23,15,21,8,5});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reflector as used in the Enigma name G-260 Abwehr
|
||||||
|
* I M E T C G F R A Y S Q B Z X W L H K D V U P O J N
|
||||||
|
*/
|
||||||
|
public static class Reflector_K_G260 extends Reflector
|
||||||
|
{
|
||||||
|
public Reflector_K_G260()
|
||||||
|
{
|
||||||
|
super(40,"Ref-K/G260", "IMETCGFRAYSQBZXWLHKDVUPOJN",
|
||||||
|
new int[]{8,12,4,19,2,6,5,17,0,24,18,16,1,25,23,22,11,7,10,3,21,20,15,14,9,13});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reflector as used in the Enigma Type R "Rocket" (Reichsbahn)
|
||||||
|
* Q Y H O G N E C V P U Z T F D J A X W M K J S R B L
|
||||||
|
*/
|
||||||
|
public static class Reflector_R extends Reflector
|
||||||
|
{
|
||||||
|
public Reflector_R()
|
||||||
|
{
|
||||||
|
super(50, "Ref-R", "QYHOGNECVPUZTFDJAXWMKJSRBL",
|
||||||
|
new int[]{16,24,7,14,6,13,4,2,21,15,20,25,19,5,3,9,0,23,22,12,10,8,18,17,1,11});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reflector as used in the Enigma name T (Tirpitz)
|
||||||
|
* G E K P B T A U M O C N I L J D X Z Y F H W V Q S R
|
||||||
|
*/
|
||||||
|
public static class ReflectorEnigma_T extends Reflector
|
||||||
|
{
|
||||||
|
public ReflectorEnigma_T()
|
||||||
|
{
|
||||||
|
super(60, "Ref-T", "GEKPBTAUMOCNILJDXZYFHWVQSR",
|
||||||
|
new int[]{6,4,10,15,1,19,0,20,12,14,2,13,8,11,9,3,23,25,24,5,7,22,21,16,18,17});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,186 +0,0 @@
|
||||||
package de.vanitasvitae.enigmandroid.enigma.rotors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reflector of the enigma machine.
|
|
||||||
* The reflector was used to reflect the scrambled signal at the end of the wiring back to
|
|
||||||
* go through another (reversed but not inverting) process of scrambling.
|
|
||||||
* 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 Reflector
|
|
||||||
{
|
|
||||||
protected String name;
|
|
||||||
protected int type;
|
|
||||||
protected Integer[] connections;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This constructor is not accessible from outside this class file.
|
|
||||||
* Use the one of the createReflector* methods instead to create concrete Reflectors from
|
|
||||||
* outside this class file
|
|
||||||
* @param name phonetic name of the reflector (usually A,B,C)
|
|
||||||
* @param type type indicator of the reflector (A->1,...,C->3)
|
|
||||||
* @param connections wiring of the reflector as Integer array
|
|
||||||
*/
|
|
||||||
protected Reflector(String name, int type, Integer[] connections)
|
|
||||||
{
|
|
||||||
this.name = name;
|
|
||||||
this.type = type;
|
|
||||||
this.connections = connections;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method to create reflectors.
|
|
||||||
* @param type type of the created reflector
|
|
||||||
* 1 -> ReflectorA
|
|
||||||
* 2 -> ReflectorB
|
|
||||||
* anything else -> ReflectorC
|
|
||||||
* @return ReflectorA | ReflectorB | ReflectorC
|
|
||||||
*/
|
|
||||||
public static Reflector createReflector(int type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case 1: return new ReflectorA();
|
|
||||||
case 2: return new ReflectorB();
|
|
||||||
case 3: return new ReflectorC();
|
|
||||||
case 4: return new ReflectorThinB();
|
|
||||||
default: return new ReflectorThinC();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Substitute an input signal via the wiring of the reflector with a different (!) output.
|
|
||||||
* The output MUST not be equal to the input for any input, since this was not possible
|
|
||||||
* due to the electronic implementation of the historical enigma machine.
|
|
||||||
* @param input input signal
|
|
||||||
* @return encrypted (substituted) output
|
|
||||||
*/
|
|
||||||
public int encrypt(int input)
|
|
||||||
{
|
|
||||||
return this.connections[normalize(input)];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the type indicator of the reflector
|
|
||||||
* @return type
|
|
||||||
*/
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return this.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return phonetic name of the reflector
|
|
||||||
* @return name
|
|
||||||
*/
|
|
||||||
public String getName()
|
|
||||||
{
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the size (ie the number of wires/length of the connections array) of the reflector
|
|
||||||
* @return size
|
|
||||||
*/
|
|
||||||
private int getRotorSize()
|
|
||||||
{
|
|
||||||
return this.connections.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 reflector. This is necessary since java allows negative modulo values,
|
|
||||||
* which can break this implementation
|
|
||||||
* @param input input signal
|
|
||||||
* @return "normalized" input signal
|
|
||||||
*/
|
|
||||||
private int normalize(int input)
|
|
||||||
{
|
|
||||||
return (input + this.getRotorSize()) % this.getRotorSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concrete implementation of ReflectorA
|
|
||||||
* Used in Enigma I
|
|
||||||
* AE BJ CM DZ FL GY HX IV KW NR OQ PU ST
|
|
||||||
*/
|
|
||||||
private static class ReflectorA extends Reflector
|
|
||||||
{
|
|
||||||
public ReflectorA()
|
|
||||||
{
|
|
||||||
super("A", 1, new Integer[]{4,9,12,25,0,11,24,23,21,1,22,5,2,17,16,20,14,13,19,18,15,8,10,7,6,3});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concrete implementation of ReflectorB
|
|
||||||
* Used in Enigma I, M3
|
|
||||||
* AY BR CU DH EQ FS GL IP JX KN MO TZ VW
|
|
||||||
*/
|
|
||||||
private static class ReflectorB extends Reflector
|
|
||||||
{
|
|
||||||
public ReflectorB()
|
|
||||||
{
|
|
||||||
super("B", 2, new Integer[]{24,17,20,7,16,18,11,3,15,23,13,6,14,10,12,8,4,1,5,25,2,22,21,9,0,19});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concrete implementation of ReflectorC
|
|
||||||
* Used in Enigma I, M3
|
|
||||||
* AF BV CP DJ EI GO HY KR LZ MX NW QT SU
|
|
||||||
*/
|
|
||||||
private static class ReflectorC extends Reflector
|
|
||||||
{
|
|
||||||
public ReflectorC()
|
|
||||||
{
|
|
||||||
super("C", 3, new Integer[]{5,21,15,9,8,0,14,24,4,3,17,25,23,22,6,2,19,10,20,16,18,1,13,12,7,11});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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,413 +0,0 @@
|
||||||
package de.vanitasvitae.enigmandroid.enigma.rotors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rotor super class and inner concrete implementations
|
|
||||||
* The rotors were the key feature of the enigma used to scramble up input signals into
|
|
||||||
* encrypted signals difficult to predict. The rotors rotated to achieve a poly-alphabetic
|
|
||||||
* substitution which was hard to break. Each signal passes the rotor twice. Once in "forward"-
|
|
||||||
* direction and once in "backwards"-direction. There was a set of 3 out of 5 rotors inside the
|
|
||||||
* enigma machine M4.
|
|
||||||
* 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 Rotor
|
|
||||||
{
|
|
||||||
protected String name;
|
|
||||||
protected int type;
|
|
||||||
protected Integer[] connections;
|
|
||||||
protected Integer[] reversedConnections;
|
|
||||||
protected Integer[] turnOverNotches;
|
|
||||||
|
|
||||||
protected int ringSetting;
|
|
||||||
protected int rotation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This constructor is not accessible from outside this class file.
|
|
||||||
* Use one of the createRotor* factory methods instead to create concrete Rotors.
|
|
||||||
* Note that connections and reversedConnections MUST be of the same size and that
|
|
||||||
* neither connections nor reversedConnections respectively MUST have any number between
|
|
||||||
* 0 and connections.length-1 only once (ie they represent permutations)
|
|
||||||
* @param name phonetic name of the rotor (usually I,II,...V)
|
|
||||||
* @param type type indicator (I -> 1,...,V -> 5)
|
|
||||||
* @param connections wiring of the rotor as Integer array
|
|
||||||
* @param reversedConnections inverse wiring used to encrypt in the opposite direction
|
|
||||||
* (connections[reversedConnections[i]] = i
|
|
||||||
* for all i in 0..getRotorSize()-1.
|
|
||||||
* @param turnOverNotches Position(s) of the turnover notch(es)
|
|
||||||
* @param ringSetting setting of the ring that holds the letters
|
|
||||||
* @param rotation rotation of the rotor
|
|
||||||
*/
|
|
||||||
protected Rotor(String name, int type, Integer[] connections, Integer[] reversedConnections,
|
|
||||||
Integer[] turnOverNotches, int ringSetting, int rotation)
|
|
||||||
{
|
|
||||||
this.name = name;
|
|
||||||
this.type = type;
|
|
||||||
this.connections = connections;
|
|
||||||
this.reversedConnections = reversedConnections;
|
|
||||||
this.turnOverNotches = turnOverNotches;
|
|
||||||
this.ringSetting = ringSetting;
|
|
||||||
this.rotation = rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method that creates a rotor accordingly to the type.
|
|
||||||
* Also initialize the rotor with ringSetting and rotation.
|
|
||||||
* @param type type indicator (1..10)
|
|
||||||
* 1..8 -> I..VIII
|
|
||||||
* 9,10 -> Beta, Gamma
|
|
||||||
* @param ringSetting setting of the outer ring (0..25)
|
|
||||||
* @param rotation rotation of the rotor
|
|
||||||
* @return Concrete rotor
|
|
||||||
*/
|
|
||||||
public static Rotor createRotor(int type, int ringSetting, int rotation)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case 1: return new RotorI(ringSetting, rotation);
|
|
||||||
case 2: return new RotorII(ringSetting, rotation);
|
|
||||||
case 3: return new RotorIII(ringSetting, rotation);
|
|
||||||
case 4: return new RotorIV(ringSetting, rotation);
|
|
||||||
case 5: return new RotorV(ringSetting, rotation);
|
|
||||||
case 6: return new RotorVI(ringSetting, rotation);
|
|
||||||
case 7: return new RotorVII(ringSetting, rotation);
|
|
||||||
case 8: return new RotorVIII(ringSetting, rotation);
|
|
||||||
case 9: return new RotorBeta(ringSetting, rotation);
|
|
||||||
default: return new RotorGamma(ringSetting, rotation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encrypt an input signal via the internal wiring in "forward" direction towards the reflector
|
|
||||||
* (using connections)
|
|
||||||
* @param input signal
|
|
||||||
* @return encrypted signal
|
|
||||||
*/
|
|
||||||
public int encryptForward(int input)
|
|
||||||
{
|
|
||||||
return this.connections[normalize(input)];// - this.ringSetting)];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encrypt an input signal via the internal wiring in "backwards" direction (using
|
|
||||||
* reversedConnections)
|
|
||||||
* @param input signal
|
|
||||||
* @return encrypted signal
|
|
||||||
*/
|
|
||||||
public int encryptBackward(int input)
|
|
||||||
{
|
|
||||||
return this.reversedConnections[normalize(input)];// + this.ringSetting)];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the type indicator (usually 1..5)
|
|
||||||
* @return type indicator
|
|
||||||
*/
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return this.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the current rotation of the rotor.
|
|
||||||
* The rotation consists of the actual rotation - the ringSetting
|
|
||||||
* @return rotation-ringSetting
|
|
||||||
*/
|
|
||||||
public int getRotation()
|
|
||||||
{
|
|
||||||
return this.rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increment rotation of the rotor by one.
|
|
||||||
*/
|
|
||||||
public void rotate()
|
|
||||||
{
|
|
||||||
this.rotation = normalize(this.getRotation()+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true, if the rotor is at a position, where it turns over the next rotor by one
|
|
||||||
* @return rotation==turnOverNotch
|
|
||||||
*/
|
|
||||||
public boolean isAtTurnoverPosition()
|
|
||||||
{
|
|
||||||
for(int x : getTurnOverNotches())
|
|
||||||
{
|
|
||||||
//if(x == this.rotation + this.ringSetting) return true;
|
|
||||||
if(x == this.rotation) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true, if the rotor is in a position where the double turn anomaly happens.
|
|
||||||
* The double turn anomaly (german: Doppelsprung-Anomalie) is an anomaly in the rotor movement
|
|
||||||
* caused by the mechanical implementation of the enigma.
|
|
||||||
* Whenever the rightmost rotor turns the middle rotor AND the middle rotor is only one move
|
|
||||||
* from turning the leftmost rotor, the middle rotor turns again with the next character.
|
|
||||||
* So technically there are only 26*25*26 possible rotor settings for any but firmly 3 rotors.
|
|
||||||
* @return rotation == turnOverNotch-1
|
|
||||||
*/
|
|
||||||
public boolean doubleTurnAnomaly()
|
|
||||||
{
|
|
||||||
for(int x : getTurnOverNotches())
|
|
||||||
{
|
|
||||||
if(this.rotation == x-1) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the positions of the turnover notches in a array
|
|
||||||
* @return turnOverNotches
|
|
||||||
*/
|
|
||||||
public Integer[] getTurnOverNotches()
|
|
||||||
{
|
|
||||||
return this.turnOverNotches;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return ringSettings of the rotor
|
|
||||||
* @return ringSetting
|
|
||||||
*/
|
|
||||||
public int getRingSetting()
|
|
||||||
{
|
|
||||||
return this.ringSetting;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the phonetic name of the rotor
|
|
||||||
* @return name
|
|
||||||
*/
|
|
||||||
public String getName()
|
|
||||||
{
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the size (ie the number of wires/size of the connections array)
|
|
||||||
* of the rotor
|
|
||||||
* @return size
|
|
||||||
*/
|
|
||||||
public int getRotorSize()
|
|
||||||
{
|
|
||||||
return this.connections.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 rotor. 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 (input + this.getRotorSize()) % this.getRotorSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
{
|
|
||||||
public RotorI(int ringSetting, int rotation)
|
|
||||||
{
|
|
||||||
super("I", 1,
|
|
||||||
new Integer[]{4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9},
|
|
||||||
new Integer[]{20, 22, 24, 6, 0, 3, 5, 15, 21, 25, 1, 4, 2, 10, 12, 19, 7, 23, 18, 11, 17, 8, 13, 16, 14, 9},
|
|
||||||
new Integer[]{17}, ringSetting, rotation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concrete implementation of Rotor of type 2 (II)
|
|
||||||
* Used in Enigma I, M3, M4
|
|
||||||
* A J D K S I R U X B L H W T M C Q G Z N P Y F V O E
|
|
||||||
*/
|
|
||||||
private static class RotorII extends Rotor
|
|
||||||
{
|
|
||||||
public RotorII(int ringSetting, int rotation)
|
|
||||||
{
|
|
||||||
super("II", 2,
|
|
||||||
new Integer[]{0, 9, 3, 10, 18, 8, 17, 20, 23, 1, 11, 7, 22, 19, 12, 2, 16, 6, 25, 13, 15, 24, 5, 21, 14, 4},
|
|
||||||
new Integer[]{0, 9, 15, 2, 25, 22, 17, 11, 5, 1, 3, 10, 14, 19, 24, 20, 16, 6, 4, 13, 7, 23, 12, 8, 21, 18},
|
|
||||||
new Integer[]{5}, ringSetting, rotation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concrete implementation of Rotor of type 3 (III)
|
|
||||||
* Used in Enigma I, M3, M4
|
|
||||||
* B D F H J L C P R T X V Z N Y E I W G A K M U S Q O
|
|
||||||
*/
|
|
||||||
private static class RotorIII extends Rotor
|
|
||||||
{
|
|
||||||
public RotorIII(int ringSetting, int rotation)
|
|
||||||
{
|
|
||||||
super("III", 3,
|
|
||||||
new Integer[]{1, 3, 5, 7, 9, 11, 2, 15, 17, 19, 23, 21, 25, 13, 24, 4, 8, 22, 6, 0, 10, 12, 20, 18, 16, 14},
|
|
||||||
new Integer[]{19, 0, 6, 1, 15, 2, 18, 3, 16, 4, 20, 5, 21, 13, 25, 7, 24, 8, 23, 9, 22, 11, 17, 10, 14, 12},
|
|
||||||
new Integer[]{22}, ringSetting, rotation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concrete implementation of Rotor of type 4 (IV)
|
|
||||||
* Used in Enigma M3, M4
|
|
||||||
* E S O V P Z J A Y Q U I R H X L N F T G K D C M W B
|
|
||||||
*/
|
|
||||||
private static class RotorIV extends Rotor
|
|
||||||
{
|
|
||||||
public RotorIV(int ringSetting, int rotation)
|
|
||||||
{
|
|
||||||
super("IV", 4,
|
|
||||||
new Integer[]{4, 18, 14, 21, 15, 25, 9, 0, 24, 16, 20, 8, 17, 7, 23, 11, 13, 5, 19, 6, 10, 3, 2, 12, 22, 1},
|
|
||||||
new Integer[]{7, 25, 22, 21, 0, 17, 19, 13, 11, 6, 20, 15, 23, 16, 2, 4, 9, 12, 1, 18, 10, 3, 24, 14, 8, 5},
|
|
||||||
new Integer[]{10}, ringSetting, rotation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concrete implementation of Rotor of type 5 (V)
|
|
||||||
* Used in Enigma M3, M4
|
|
||||||
* V Z B R G I T Y U P S D N H L X A W M J Q O F E C K
|
|
||||||
*/
|
|
||||||
private static class RotorV extends Rotor
|
|
||||||
{
|
|
||||||
public RotorV(int ringSetting, int rotation)
|
|
||||||
{
|
|
||||||
super("V", 5,
|
|
||||||
new Integer[]{21, 25, 1, 17, 6, 8, 19, 24, 20, 15, 18, 3, 13, 7, 11, 23, 0, 22, 12, 9, 16, 14, 5, 4, 2, 10},
|
|
||||||
new Integer[]{16, 2, 24, 11, 23, 22, 4, 13, 5, 19, 25, 14, 18, 12, 21, 9, 20, 3, 10, 6, 8, 0, 17, 15, 7, 1},
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,78 +1,192 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package de.vanitasvitae.enigmandroid.layout;
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
import de.vanitasvitae.enigmandroid.MainActivity;
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
import de.vanitasvitae.enigmandroid.SettingsActivity;
|
||||||
import de.vanitasvitae.enigmandroid.enigma.Enigma;
|
import de.vanitasvitae.enigmandroid.enigma.Enigma;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.inputPreparer.EditTextAdapter;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.inputPreparer.InputPreparer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract LayoutContainer for Enigma machines
|
* Abstract LayoutContainer for Enigma machines
|
||||||
* This class contains the layout and controls the layout elements such as spinners and stuff
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
* Copyright (C) 2015 Paul Schaub
|
* 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
|
public abstract class LayoutContainer
|
||||||
{
|
{
|
||||||
protected MainActivity main;
|
final EditText inputView;
|
||||||
protected Enigma enigma;
|
private final EditText outputView;
|
||||||
|
|
||||||
protected EditText inputView;
|
EditTextAdapter input;
|
||||||
protected EditText outputView;
|
EditTextAdapter output;
|
||||||
|
|
||||||
protected int[] ringSettings;
|
InputPreparer inputPreparer;
|
||||||
|
final MainActivity main;
|
||||||
|
|
||||||
public LayoutContainer()
|
public abstract Enigma getEnigma();
|
||||||
{
|
protected abstract void assembleLayout();
|
||||||
this.main = (MainActivity) MainActivity.ActivitySingleton.getInstance().getActivity();
|
public abstract void resetLayout();
|
||||||
}
|
protected abstract void setLayoutState(EnigmaStateBundle state);
|
||||||
|
public abstract void syncStateFromLayoutToEnigma();
|
||||||
|
public void syncStateFromEnigmaToLayout()
|
||||||
|
{
|
||||||
|
this.setLayoutState(getEnigma().getState());
|
||||||
|
}
|
||||||
|
public abstract void showRingSettingsDialog();
|
||||||
|
|
||||||
abstract void initialize();
|
LayoutContainer()
|
||||||
public abstract void reset();
|
{
|
||||||
public abstract void updateLayout();
|
main = (MainActivity) MainActivity.ActivitySingleton.getInstance().getActivity();
|
||||||
public abstract int[] createConfiguration();
|
setEnigmaLayout();
|
||||||
public abstract int[][] createPlugboardConfiguration();
|
this.inputView = (EditText) main.findViewById(R.id.input);
|
||||||
public abstract void showRingSettingsDialog();
|
this.outputView = (EditText) main.findViewById(R.id.output);
|
||||||
|
input = EditTextAdapter.createEditTextAdapter(inputView,
|
||||||
|
SettingsActivity.SettingsSingleton.getInstance().getPrefMessageFormatting());
|
||||||
|
output = EditTextAdapter.createEditTextAdapter(outputView,
|
||||||
|
SettingsActivity.SettingsSingleton.getInstance().getPrefMessageFormatting());
|
||||||
|
inputPreparer = InputPreparer.createInputPreparer();
|
||||||
|
assembleLayout();
|
||||||
|
finishLayout();
|
||||||
|
}
|
||||||
|
|
||||||
public Enigma getEnigma()
|
public void doCrypto()
|
||||||
{
|
{
|
||||||
return enigma;
|
if(inputView.getText().length()!=0)
|
||||||
}
|
{
|
||||||
|
syncStateFromLayoutToEnigma();
|
||||||
|
String message = inputView.getText().toString();
|
||||||
|
message = inputPreparer.prepareString(message);
|
||||||
|
input.setText(message);
|
||||||
|
output.setText(getEnigma().encryptString(message));
|
||||||
|
setLayoutState(getEnigma().getState());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public EditText getInputView()
|
public EditTextAdapter getInput()
|
||||||
{
|
{
|
||||||
return this.inputView;
|
return this.input;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EditText getOutputView()
|
public EditTextAdapter getOutput()
|
||||||
{
|
{
|
||||||
return this.outputView;
|
return this.output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LayoutContainer createLayoutContainer(String type)
|
public static LayoutContainer createLayoutContainer()
|
||||||
{
|
{
|
||||||
switch (type)
|
return createLayoutContainer(SettingsActivity.SettingsSingleton.getInstance().getPrefMachineType());
|
||||||
{
|
}
|
||||||
case "M4":
|
|
||||||
return new LayoutContainer_M4();
|
|
||||||
case "M3":
|
|
||||||
return new LayoutContainer_M3();
|
|
||||||
default:
|
|
||||||
return new LayoutContainer_I();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private static LayoutContainer createLayoutContainer(String enigmaType)
|
||||||
|
{
|
||||||
|
switch (enigmaType) {
|
||||||
|
case "I":
|
||||||
|
return new LayoutContainer_I();
|
||||||
|
case "M3":
|
||||||
|
return new LayoutContainer_M3();
|
||||||
|
case "M4":
|
||||||
|
return new LayoutContainer_M4();
|
||||||
|
case "D":
|
||||||
|
return new LayoutContainer_D();
|
||||||
|
case "K":
|
||||||
|
return new LayoutContainer_K();
|
||||||
|
case "KS":
|
||||||
|
return new LayoutContainer_K_Swiss();
|
||||||
|
case "KSA":
|
||||||
|
return new LayoutContainer_K_Swiss_Airforce();
|
||||||
|
case "T":
|
||||||
|
return new LayoutContainer_T();
|
||||||
|
case "R":
|
||||||
|
return new LayoutContainer_R();
|
||||||
|
case "G31":
|
||||||
|
return new LayoutContainer_G31();
|
||||||
|
case "G312":
|
||||||
|
return new LayoutContainer_G312();
|
||||||
|
case "G260":
|
||||||
|
return new LayoutContainer_G260();
|
||||||
|
case "KD":
|
||||||
|
return new LayoutContainer_KD();
|
||||||
|
default:
|
||||||
|
return new LayoutContainer_I();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add ArrayAdapter, contents and layouts to Spinner
|
||||||
|
* @param view Spinner
|
||||||
|
* @param resourceID ID of the referenced array (eg. R.array.rotor_1_8)
|
||||||
|
*/
|
||||||
|
void prepareSpinnerAdapter(Spinner view, int resourceID) {
|
||||||
|
MainActivity main = (MainActivity) MainActivity.ActivitySingleton.getInstance().getActivity();
|
||||||
|
|
||||||
|
ArrayAdapter<CharSequence> ad = new ArrayAdapter<CharSequence>(main,
|
||||||
|
android.R.layout.simple_spinner_item,
|
||||||
|
main.getResources().getTextArray(resourceID));
|
||||||
|
|
||||||
|
ad.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
ad.setDropDownViewTheme(main.getTheme());
|
||||||
|
view.setAdapter(ad);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add ArrayAdapter, contents and layouts to Spinner
|
||||||
|
* @param view Spinner
|
||||||
|
* @param array Character array
|
||||||
|
*/
|
||||||
|
void prepareSpinnerAdapter(Spinner view, Character[] array)
|
||||||
|
{
|
||||||
|
MainActivity main = (MainActivity) MainActivity.ActivitySingleton.getInstance().getActivity();
|
||||||
|
ArrayAdapter<Character> adapter = new ArrayAdapter<>(main,
|
||||||
|
android.R.layout.simple_spinner_item, array);
|
||||||
|
adapter.setDropDownViewResource(
|
||||||
|
android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
adapter.setDropDownViewTheme(main.getTheme());
|
||||||
|
view.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInputPreparer(InputPreparer inputPreparer)
|
||||||
|
{
|
||||||
|
this.inputPreparer = inputPreparer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEditTextAdapter(String type)
|
||||||
|
{
|
||||||
|
String in = input.getText();
|
||||||
|
String out = output.getText();
|
||||||
|
input = EditTextAdapter.createEditTextAdapter(inputView, type);
|
||||||
|
input.setText(in);
|
||||||
|
output = EditTextAdapter.createEditTextAdapter(outputView, type);
|
||||||
|
output.setText(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setMainActivityLayout()
|
||||||
|
{
|
||||||
|
setEnigmaLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected void setEnigmaLayout();
|
||||||
|
|
||||||
|
private void finishLayout()
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma_D;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete LayoutContainer for the D layout.
|
||||||
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class LayoutContainer_D extends LayoutContainer
|
||||||
|
{
|
||||||
|
private Enigma_D enigma;
|
||||||
|
|
||||||
|
private Spinner rotor1PositionView;
|
||||||
|
private Spinner rotor2PositionView;
|
||||||
|
private Spinner rotor3PositionView;
|
||||||
|
private Spinner reflectorPositionView;
|
||||||
|
|
||||||
|
public LayoutContainer_D()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
main.setTitle("D - EnigmAndroid");
|
||||||
|
this.resetLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setEnigmaLayout()
|
||||||
|
{
|
||||||
|
MainActivity.ActivitySingleton.getInstance().getActivity().setContentView(R.layout.activity_main_d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assembleLayout()
|
||||||
|
{
|
||||||
|
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.reflectorPositionView = (Spinner) main.findViewById(R.id.reflector_position);
|
||||||
|
Button reflectorWiring = (Button) main.findViewById(R.id.button_reflector);
|
||||||
|
reflectorWiring.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
new PluggableDialogBuilder(getEnigma().getState()).showDialogReflector();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Character[] rotorPositionArray = new Character[26];
|
||||||
|
for(int i=0; i<26; i++) {rotorPositionArray[i] = (char) (65+i); /*Fill with A..Z*/}
|
||||||
|
|
||||||
|
prepareSpinnerAdapter(rotor1PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(rotor2PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(rotor3PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(reflectorPositionView, rotorPositionArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetLayout()
|
||||||
|
{
|
||||||
|
enigma = new Enigma_D();
|
||||||
|
setLayoutState(enigma.getState());
|
||||||
|
output.setText("");
|
||||||
|
input.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLayoutState(EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
this.rotor1PositionView.setSelection(state.getRotationRotor1());
|
||||||
|
this.rotor2PositionView.setSelection(state.getRotationRotor2());
|
||||||
|
this.rotor3PositionView.setSelection(state.getRotationRotor3());
|
||||||
|
this.reflectorPositionView.setSelection(state.getRotationReflector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void syncStateFromLayoutToEnigma()
|
||||||
|
{
|
||||||
|
EnigmaStateBundle state = getEnigma().getState();
|
||||||
|
state.setRotationRotor1(rotor1PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor2(rotor2PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor3(rotor3PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationReflector(reflectorPositionView.getSelectedItemPosition());
|
||||||
|
getEnigma().setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Enigma_D getEnigma()
|
||||||
|
{
|
||||||
|
return this.enigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showRingSettingsDialog()
|
||||||
|
{
|
||||||
|
new RingSettingsDialogBuilder.RingSettingsDialogBuilderRotRotRotRef().
|
||||||
|
createRingSettingsDialog(getEnigma().getState());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma_G260;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LayoutContainer for the Enigma Model G260
|
||||||
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class LayoutContainer_G260 extends LayoutContainer_G31
|
||||||
|
{
|
||||||
|
public LayoutContainer_G260()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
main.setTitle("G260 - EnigmAndroid");
|
||||||
|
this.resetLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetLayout() {
|
||||||
|
enigma = new Enigma_G260();
|
||||||
|
setLayoutState(enigma.getState());
|
||||||
|
output.setText("");
|
||||||
|
input.setText("");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma_G31;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LayoutContainer for the Enigma Model G31
|
||||||
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class LayoutContainer_G31 extends LayoutContainer
|
||||||
|
{
|
||||||
|
Enigma enigma;
|
||||||
|
|
||||||
|
private Spinner rotor1View;
|
||||||
|
private Spinner rotor2View;
|
||||||
|
private Spinner rotor3View;
|
||||||
|
|
||||||
|
private Spinner rotor1PositionView;
|
||||||
|
private Spinner rotor2PositionView;
|
||||||
|
private Spinner rotor3PositionView;
|
||||||
|
private Spinner reflectorPositionView;
|
||||||
|
|
||||||
|
public LayoutContainer_G31()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
main.setTitle("G31 - EnigmAndroid");
|
||||||
|
this.resetLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setEnigmaLayout()
|
||||||
|
{
|
||||||
|
MainActivity.ActivitySingleton.getInstance().getActivity().setContentView(R.layout.activity_main_g_k_r_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Enigma getEnigma() {
|
||||||
|
return this.enigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assembleLayout() {
|
||||||
|
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.rotor1PositionView = (Spinner) main.findViewById(R.id.rotor1position);
|
||||||
|
this.rotor2PositionView = (Spinner) main.findViewById(R.id.rotor2position);
|
||||||
|
this.rotor3PositionView = (Spinner) main.findViewById(R.id.rotor3position);
|
||||||
|
this.reflectorPositionView = (Spinner) main.findViewById(R.id.reflector_position);
|
||||||
|
|
||||||
|
Character[] rotorPositionArray = new Character[26];
|
||||||
|
for(int i=0; i<26; i++) {rotorPositionArray[i] = (char) (65+i); /*Fill with A..Z*/}
|
||||||
|
|
||||||
|
prepareSpinnerAdapter(rotor1View, R.array.rotors_1_3);
|
||||||
|
prepareSpinnerAdapter(rotor2View, R.array.rotors_1_3);
|
||||||
|
prepareSpinnerAdapter(rotor3View, R.array.rotors_1_3);
|
||||||
|
prepareSpinnerAdapter(rotor1PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(rotor2PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(rotor3PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(reflectorPositionView, rotorPositionArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetLayout() {
|
||||||
|
enigma = new Enigma_G31();
|
||||||
|
setLayoutState(enigma.getState());
|
||||||
|
output.setText("");
|
||||||
|
input.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLayoutState(EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
this.rotor1View.setSelection(state.getTypeRotor1());
|
||||||
|
this.rotor2View.setSelection(state.getTypeRotor2());
|
||||||
|
this.rotor3View.setSelection(state.getTypeRotor3());
|
||||||
|
this.rotor1PositionView.setSelection(state.getRotationRotor1());
|
||||||
|
this.rotor2PositionView.setSelection(state.getRotationRotor2());
|
||||||
|
this.rotor3PositionView.setSelection(state.getRotationRotor3());
|
||||||
|
this.reflectorPositionView.setSelection(state.getRotationReflector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void syncStateFromLayoutToEnigma()
|
||||||
|
{
|
||||||
|
EnigmaStateBundle state = getEnigma().getState();
|
||||||
|
state.setTypeRotor1(rotor1View.getSelectedItemPosition());
|
||||||
|
state.setTypeRotor2(rotor2View.getSelectedItemPosition());
|
||||||
|
state.setTypeRotor3(rotor3View.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor1(rotor1PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor2(rotor2PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor3(rotor3PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationReflector(reflectorPositionView.getSelectedItemPosition());
|
||||||
|
getEnigma().setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showRingSettingsDialog()
|
||||||
|
{
|
||||||
|
new RingSettingsDialogBuilder.RingSettingsDialogBuilderRotRotRotRef().
|
||||||
|
createRingSettingsDialog(getEnigma().getState());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma_G312;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LayoutContainer for the Enigma Model G312
|
||||||
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class LayoutContainer_G312 extends LayoutContainer_G31
|
||||||
|
{
|
||||||
|
public LayoutContainer_G312()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
main.setTitle("G312 - EnigmAndroid");
|
||||||
|
this.resetLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetLayout() {
|
||||||
|
enigma = new Enigma_G312();
|
||||||
|
setLayoutState(enigma.getState());
|
||||||
|
output.setText("");
|
||||||
|
input.setText("");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,224 +1,132 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package de.vanitasvitae.enigmandroid.layout;
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
import de.vanitasvitae.enigmandroid.R;
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
|
||||||
import de.vanitasvitae.enigmandroid.enigma.Enigma_I;
|
import de.vanitasvitae.enigmandroid.enigma.Enigma_I;
|
||||||
import de.vanitasvitae.enigmandroid.enigma.Plugboard;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete LayoutContainer for the Enigma I layout.
|
* Concrete LayoutContainer for the Enigma I layout.
|
||||||
* This class contains the layout and controls the layout elements such as spinners and stuff
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
* Copyright (C) 2015 Paul Schaub
|
* 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
|
public class LayoutContainer_I extends LayoutContainer
|
||||||
{
|
{
|
||||||
protected Spinner rotor1View;
|
private Enigma_I enigma;
|
||||||
protected Spinner rotor2View;
|
|
||||||
protected Spinner rotor3View;
|
|
||||||
protected Spinner reflectorView;
|
|
||||||
protected Spinner rotor1PositionView;
|
|
||||||
protected Spinner rotor2PositionView;
|
|
||||||
protected Spinner rotor3PositionView;
|
|
||||||
|
|
||||||
protected EditText plugboardView;
|
Spinner rotor1View;
|
||||||
|
Spinner rotor2View;
|
||||||
|
Spinner rotor3View;
|
||||||
|
Spinner reflectorView;
|
||||||
|
Spinner rotor1PositionView;
|
||||||
|
Spinner rotor2PositionView;
|
||||||
|
Spinner rotor3PositionView;
|
||||||
|
|
||||||
public LayoutContainer_I()
|
public LayoutContainer_I()
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
main.setTitle("I - EnigmAndroid");
|
main.setTitle("I - EnigmAndroid");
|
||||||
this.enigma = new Enigma_I();
|
this.resetLayout();
|
||||||
this.ringSettings = new int[]{0,0,0};
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setEnigmaLayout()
|
||||||
|
{
|
||||||
|
MainActivity.ActivitySingleton.getInstance().getActivity().setContentView(R.layout.activity_main_i_m3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assembleLayout()
|
||||||
|
{
|
||||||
this.rotor1View = (Spinner) main.findViewById(R.id.rotor1);
|
this.rotor1View = (Spinner) main.findViewById(R.id.rotor1);
|
||||||
this.rotor2View = (Spinner) main.findViewById(R.id.rotor2);
|
this.rotor2View = (Spinner) main.findViewById(R.id.rotor2);
|
||||||
this.rotor3View = (Spinner) main.findViewById(R.id.rotor3);
|
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.rotor1PositionView = (Spinner) main.findViewById(R.id.rotor1position);
|
||||||
this.rotor2PositionView = (Spinner) main.findViewById(R.id.rotor2position);
|
this.rotor2PositionView = (Spinner) main.findViewById(R.id.rotor2position);
|
||||||
this.rotor3PositionView = (Spinner) main.findViewById(R.id.rotor3position);
|
this.rotor3PositionView = (Spinner) main.findViewById(R.id.rotor3position);
|
||||||
this.plugboardView = (EditText) main.findViewById(R.id.plugboard);
|
this.reflectorView = (Spinner) main.findViewById(R.id.reflector);
|
||||||
this.inputView = (EditText) main.findViewById(R.id.input);
|
Button setPlugboardButton = (Button) main.findViewById(R.id.button_plugboard);
|
||||||
this.outputView = (EditText) main.findViewById(R.id.output);
|
setPlugboardButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
new PluggableDialogBuilder(getEnigma().getState()).showDialogPlugboard();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
initialize();
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void initialize()
|
|
||||||
{
|
|
||||||
Character[] rotorPositionArray = new Character[26];
|
Character[] rotorPositionArray = new Character[26];
|
||||||
for(int i=0; i<26; i++) {rotorPositionArray[i] = (char) (65+i); /**Fill with A..Z*/}
|
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,
|
prepareSpinnerAdapter(rotor1View, R.array.rotors_1_5);
|
||||||
android.R.layout.simple_spinner_item);
|
prepareSpinnerAdapter(rotor2View, R.array.rotors_1_5);
|
||||||
rotor1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
prepareSpinnerAdapter(rotor3View, R.array.rotors_1_5);
|
||||||
rotor1View.setAdapter(rotor1Adapter);
|
prepareSpinnerAdapter(reflectorView, R.array.reflectors_a_c);
|
||||||
ArrayAdapter<CharSequence> rotor2Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_1_5,
|
prepareSpinnerAdapter(rotor1PositionView, rotorPositionArray);
|
||||||
android.R.layout.simple_spinner_item);
|
prepareSpinnerAdapter(rotor2PositionView, rotorPositionArray);
|
||||||
rotor2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
prepareSpinnerAdapter(rotor3PositionView, rotorPositionArray);
|
||||||
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
|
@Override
|
||||||
public void reset()
|
public void resetLayout()
|
||||||
{
|
{
|
||||||
rotor1View.setSelection(0); //I
|
enigma = new Enigma_I();
|
||||||
rotor2View.setSelection(1); //II
|
setLayoutState(enigma.getState());
|
||||||
rotor3View.setSelection(2); //III
|
output.setText("");
|
||||||
reflectorView.setSelection(0); //A
|
input.setText("");
|
||||||
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
|
@Override
|
||||||
public void updateLayout()
|
public void setLayoutState(EnigmaStateBundle state)
|
||||||
{
|
{
|
||||||
int[] conf = enigma.getConfiguration();
|
this.rotor1View.setSelection(state.getTypeRotor1());
|
||||||
rotor1View.setSelection(conf[0]-1);
|
this.rotor2View.setSelection(state.getTypeRotor2());
|
||||||
rotor2View.setSelection(conf[1]-1);
|
this.rotor3View.setSelection(state.getTypeRotor3());
|
||||||
rotor3View.setSelection(conf[2]-1);
|
this.reflectorView.setSelection(state.getTypeReflector());
|
||||||
reflectorView.setSelection(conf[3]-1);
|
this.rotor1PositionView.setSelection(state.getRotationRotor1());
|
||||||
rotor1PositionView.setSelection(conf[4]);
|
this.rotor2PositionView.setSelection(state.getRotationRotor2());
|
||||||
rotor2PositionView.setSelection(conf[5]);
|
this.rotor3PositionView.setSelection(state.getRotationRotor3());
|
||||||
rotor3PositionView.setSelection(conf[6]);
|
|
||||||
ringSettings[0] = conf[7];
|
|
||||||
ringSettings[1] = conf[8];
|
|
||||||
ringSettings[2] = conf[9];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] createConfiguration()
|
public void syncStateFromLayoutToEnigma()
|
||||||
{
|
{
|
||||||
int[] conf = new int[10];
|
EnigmaStateBundle state = getEnigma().getState();
|
||||||
//Rotors 1..3
|
state.setTypeRotor1(rotor1View.getSelectedItemPosition());
|
||||||
conf[0] = rotor1View.getSelectedItemPosition() + 1;
|
state.setTypeRotor2(rotor2View.getSelectedItemPosition());
|
||||||
conf[1] = rotor2View.getSelectedItemPosition() + 1;
|
state.setTypeRotor3(rotor3View.getSelectedItemPosition());
|
||||||
conf[2] = rotor3View.getSelectedItemPosition() + 1;
|
state.setTypeReflector(reflectorView.getSelectedItemPosition());
|
||||||
//Reflector
|
state.setRotationRotor1(rotor1PositionView.getSelectedItemPosition());
|
||||||
conf[3] = reflectorView.getSelectedItemPosition() + 1;
|
state.setRotationRotor2(rotor2PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor3(rotor3PositionView.getSelectedItemPosition());
|
||||||
conf[4] = rotor1PositionView.getSelectedItemPosition();
|
getEnigma().setState(state);
|
||||||
conf[5] = rotor2PositionView.getSelectedItemPosition();
|
|
||||||
conf[6] = rotor3PositionView.getSelectedItemPosition();
|
|
||||||
|
|
||||||
conf[7] = ringSettings[0];
|
|
||||||
conf[8] = ringSettings[1];
|
|
||||||
conf[9] = ringSettings[2];
|
|
||||||
|
|
||||||
return conf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Enigma_I getEnigma()
|
||||||
public int[][] createPlugboardConfiguration() {
|
{
|
||||||
return Plugboard.parseConfigurationString(plugboardView.getText().toString());
|
return this.enigma;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showRingSettingsDialog()
|
public void showRingSettingsDialog()
|
||||||
{
|
{
|
||||||
Integer[] ringArray = new Integer[26];
|
new RingSettingsDialogBuilder.RingSettingsDialogBuilderRotRotRot().
|
||||||
for(int i=1; i<=26; i++) {ringArray[i-1] = i;}
|
createRingSettingsDialog(getEnigma().getState());
|
||||||
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,124 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma_K;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LayoutContainer for the Enigma Model K
|
||||||
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class LayoutContainer_K extends LayoutContainer
|
||||||
|
{
|
||||||
|
Enigma enigma;
|
||||||
|
|
||||||
|
private Spinner rotor1View;
|
||||||
|
private Spinner rotor2View;
|
||||||
|
private Spinner rotor3View;
|
||||||
|
|
||||||
|
private Spinner rotor1PositionView;
|
||||||
|
private Spinner rotor2PositionView;
|
||||||
|
private Spinner rotor3PositionView;
|
||||||
|
private Spinner reflectorPositionView;
|
||||||
|
|
||||||
|
public LayoutContainer_K()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
main.setTitle("K - EnigmAndroid");
|
||||||
|
this.resetLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setEnigmaLayout()
|
||||||
|
{
|
||||||
|
MainActivity.ActivitySingleton.getInstance().getActivity().setContentView(R.layout.activity_main_g_k_r_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Enigma getEnigma() {
|
||||||
|
return this.enigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assembleLayout() {
|
||||||
|
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.rotor1PositionView = (Spinner) main.findViewById(R.id.rotor1position);
|
||||||
|
this.rotor2PositionView = (Spinner) main.findViewById(R.id.rotor2position);
|
||||||
|
this.rotor3PositionView = (Spinner) main.findViewById(R.id.rotor3position);
|
||||||
|
this.reflectorPositionView = (Spinner) main.findViewById(R.id.reflector_position);
|
||||||
|
|
||||||
|
Character[] rotorPositionArray = new Character[26];
|
||||||
|
for(int i=0; i<26; i++) {rotorPositionArray[i] = (char) (65+i); /*Fill with A..Z*/}
|
||||||
|
|
||||||
|
prepareSpinnerAdapter(rotor1View, R.array.rotors_1_3);
|
||||||
|
prepareSpinnerAdapter(rotor2View, R.array.rotors_1_3);
|
||||||
|
prepareSpinnerAdapter(rotor3View, R.array.rotors_1_3);
|
||||||
|
|
||||||
|
prepareSpinnerAdapter(rotor1PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(rotor2PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(rotor3PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(reflectorPositionView, rotorPositionArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetLayout() {
|
||||||
|
enigma = new Enigma_K();
|
||||||
|
setLayoutState(enigma.getState());
|
||||||
|
output.setText("");
|
||||||
|
input.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLayoutState(EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
this.rotor1View.setSelection(state.getTypeRotor1());
|
||||||
|
this.rotor2View.setSelection(state.getTypeRotor2());
|
||||||
|
this.rotor3View.setSelection(state.getTypeRotor3());
|
||||||
|
this.rotor1PositionView.setSelection(state.getRotationRotor1());
|
||||||
|
this.rotor2PositionView.setSelection(state.getRotationRotor2());
|
||||||
|
this.rotor3PositionView.setSelection(state.getRotationRotor3());
|
||||||
|
this.reflectorPositionView.setSelection(state.getRotationReflector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void syncStateFromLayoutToEnigma()
|
||||||
|
{
|
||||||
|
EnigmaStateBundle state = getEnigma().getState();
|
||||||
|
state.setTypeRotor1(rotor1View.getSelectedItemPosition());
|
||||||
|
state.setTypeRotor2(rotor2View.getSelectedItemPosition());
|
||||||
|
state.setTypeRotor3(rotor3View.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor1(rotor1PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor2(rotor2PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor3(rotor3PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationReflector(reflectorPositionView.getSelectedItemPosition());
|
||||||
|
getEnigma().setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showRingSettingsDialog()
|
||||||
|
{
|
||||||
|
new RingSettingsDialogBuilder.RingSettingsDialogBuilderRotRotRotRef().
|
||||||
|
createRingSettingsDialog(getEnigma().getState());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,133 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma_KD;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LayoutContainer for the Enigma Model K
|
||||||
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class LayoutContainer_KD extends LayoutContainer
|
||||||
|
{
|
||||||
|
private Enigma enigma;
|
||||||
|
|
||||||
|
private Spinner rotor1View;
|
||||||
|
private Spinner rotor2View;
|
||||||
|
private Spinner rotor3View;
|
||||||
|
|
||||||
|
private Spinner rotor1PositionView;
|
||||||
|
private Spinner rotor2PositionView;
|
||||||
|
private Spinner rotor3PositionView;
|
||||||
|
private Spinner reflectorPositionView;
|
||||||
|
|
||||||
|
public LayoutContainer_KD()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
main.setTitle("KD - EnigmAndroid");
|
||||||
|
this.resetLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setEnigmaLayout()
|
||||||
|
{
|
||||||
|
MainActivity.ActivitySingleton.getInstance().getActivity().setContentView(R.layout.activity_main_kd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Enigma getEnigma() {
|
||||||
|
return this.enigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assembleLayout() {
|
||||||
|
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.rotor1PositionView = (Spinner) main.findViewById(R.id.rotor1position);
|
||||||
|
this.rotor2PositionView = (Spinner) main.findViewById(R.id.rotor2position);
|
||||||
|
this.rotor3PositionView = (Spinner) main.findViewById(R.id.rotor3position);
|
||||||
|
this.reflectorPositionView = (Spinner) main.findViewById(R.id.reflector_position);
|
||||||
|
Button reflectorWiring = (Button) main.findViewById(R.id.button_reflector);
|
||||||
|
reflectorWiring.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
new PluggableDialogBuilder(getEnigma().getState()).showDialogReflector();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Character[] rotorPositionArray = new Character[26];
|
||||||
|
for(int i=0; i<26; i++) {rotorPositionArray[i] = (char) (65+i); /*Fill with A..Z*/}
|
||||||
|
|
||||||
|
prepareSpinnerAdapter(rotor1View, R.array.rotors_1_3);
|
||||||
|
prepareSpinnerAdapter(rotor2View, R.array.rotors_1_3);
|
||||||
|
prepareSpinnerAdapter(rotor3View, R.array.rotors_1_3);
|
||||||
|
|
||||||
|
prepareSpinnerAdapter(rotor1PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(rotor2PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(rotor3PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(reflectorPositionView, rotorPositionArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetLayout() {
|
||||||
|
enigma = new Enigma_KD();
|
||||||
|
setLayoutState(enigma.getState());
|
||||||
|
output.setText("");
|
||||||
|
input.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLayoutState(EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
this.rotor1View.setSelection(state.getTypeRotor1());
|
||||||
|
this.rotor2View.setSelection(state.getTypeRotor2());
|
||||||
|
this.rotor3View.setSelection(state.getTypeRotor3());
|
||||||
|
this.rotor1PositionView.setSelection(state.getRotationRotor1());
|
||||||
|
this.rotor2PositionView.setSelection(state.getRotationRotor2());
|
||||||
|
this.rotor3PositionView.setSelection(state.getRotationRotor3());
|
||||||
|
this.reflectorPositionView.setSelection(state.getRotationReflector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void syncStateFromLayoutToEnigma()
|
||||||
|
{
|
||||||
|
EnigmaStateBundle state = getEnigma().getState();
|
||||||
|
state.setTypeRotor1(rotor1View.getSelectedItemPosition());
|
||||||
|
state.setTypeRotor2(rotor2View.getSelectedItemPosition());
|
||||||
|
state.setTypeRotor3(rotor3View.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor1(rotor1PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor2(rotor2PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor3(rotor3PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationReflector(reflectorPositionView.getSelectedItemPosition());
|
||||||
|
getEnigma().setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showRingSettingsDialog()
|
||||||
|
{
|
||||||
|
new RingSettingsDialogBuilder.RingSettingsDialogBuilderRotRotRotRef().
|
||||||
|
createRingSettingsDialog(getEnigma().getState());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma_K_Swiss_Standard;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LayoutContainer for the Enigma Model K
|
||||||
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class LayoutContainer_K_Swiss extends LayoutContainer_K
|
||||||
|
{
|
||||||
|
public LayoutContainer_K_Swiss()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
main.setTitle("KS - EnigmAndroid");
|
||||||
|
this.resetLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetLayout() {
|
||||||
|
enigma = new Enigma_K_Swiss_Standard();
|
||||||
|
setLayoutState(enigma.getState());
|
||||||
|
output.setText("");
|
||||||
|
input.setText("");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma_K_Swiss_Airforce;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LayoutContainer for the Enigma Model K
|
||||||
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class LayoutContainer_K_Swiss_Airforce extends LayoutContainer_K
|
||||||
|
{
|
||||||
|
public LayoutContainer_K_Swiss_Airforce()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
main.setTitle("KSA - EnigmAndroid");
|
||||||
|
this.resetLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetLayout() {
|
||||||
|
enigma = new Enigma_K_Swiss_Airforce();
|
||||||
|
setLayoutState(enigma.getState());
|
||||||
|
output.setText("");
|
||||||
|
input.setText("");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,115 +1,111 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package de.vanitasvitae.enigmandroid.layout;
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
import android.widget.ArrayAdapter;
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
import de.vanitasvitae.enigmandroid.R;
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
|
||||||
import de.vanitasvitae.enigmandroid.enigma.Enigma_M3;
|
import de.vanitasvitae.enigmandroid.enigma.Enigma_M3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete LayoutContainer for the M3 layout.
|
* Concrete LayoutContainer for the M3 layout.
|
||||||
* This class contains the layout and controls the layout elements such as spinners and stuff
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
* Copyright (C) 2015 Paul Schaub
|
* 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 class LayoutContainer_M3 extends LayoutContainer_I
|
||||||
{
|
{
|
||||||
|
private Enigma_M3 enigma;
|
||||||
|
|
||||||
public LayoutContainer_M3()
|
public LayoutContainer_M3()
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
main.setTitle("M3 - EnigmAndroid");
|
main.setTitle("M3 - EnigmAndroid");
|
||||||
this.enigma = new Enigma_M3();
|
this.resetLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void initialize()
|
protected void assembleLayout()
|
||||||
{
|
{
|
||||||
|
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.rotor1PositionView = (Spinner) main.findViewById(R.id.rotor1position);
|
||||||
|
this.rotor2PositionView = (Spinner) main.findViewById(R.id.rotor2position);
|
||||||
|
this.rotor3PositionView = (Spinner) main.findViewById(R.id.rotor3position);
|
||||||
|
this.reflectorView = (Spinner) main.findViewById(R.id.reflector);
|
||||||
|
Button setPlugboardButton = (Button) main.findViewById(R.id.button_plugboard);
|
||||||
|
setPlugboardButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
new PluggableDialogBuilder(getEnigma().getState()).showDialogPlugboard();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Character[] rotorPositionArray = new Character[26];
|
Character[] rotorPositionArray = new Character[26];
|
||||||
for(int i=0; i<26; i++) {rotorPositionArray[i] = (char) (65+i); /**Fill with A..Z*/}
|
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,
|
prepareSpinnerAdapter(rotor1View, R.array.rotors_1_8);
|
||||||
android.R.layout.simple_spinner_item);
|
prepareSpinnerAdapter(rotor2View, R.array.rotors_1_8);
|
||||||
rotor1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
prepareSpinnerAdapter(rotor3View, R.array.rotors_1_8);
|
||||||
rotor1View.setAdapter(rotor1Adapter);
|
prepareSpinnerAdapter(reflectorView, R.array.reflectors_b_c);
|
||||||
ArrayAdapter<CharSequence> rotor2Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_1_8,
|
prepareSpinnerAdapter(rotor1PositionView, rotorPositionArray);
|
||||||
android.R.layout.simple_spinner_item);
|
prepareSpinnerAdapter(rotor2PositionView, rotorPositionArray);
|
||||||
rotor2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
prepareSpinnerAdapter(rotor3PositionView, rotorPositionArray);
|
||||||
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
|
@Override
|
||||||
public void updateLayout()
|
public void resetLayout()
|
||||||
{
|
{
|
||||||
int[] conf = enigma.getConfiguration();
|
enigma = new Enigma_M3();
|
||||||
rotor1View.setSelection(conf[0]-1);
|
setLayoutState(enigma.getState());
|
||||||
rotor2View.setSelection(conf[1]-1);
|
output.setText("");
|
||||||
rotor3View.setSelection(conf[2]-1);
|
input.setText("");
|
||||||
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
|
@Override
|
||||||
public int[] createConfiguration()
|
public void setLayoutState(EnigmaStateBundle state)
|
||||||
{
|
{
|
||||||
int[] conf = new int[10];
|
this.rotor1View.setSelection(state.getTypeRotor1());
|
||||||
//Rotors 1..3
|
this.rotor2View.setSelection(state.getTypeRotor2());
|
||||||
conf[0] = rotor1View.getSelectedItemPosition() + 1;
|
this.rotor3View.setSelection(state.getTypeRotor3());
|
||||||
conf[1] = rotor2View.getSelectedItemPosition() + 1;
|
this.reflectorView.setSelection(state.getTypeReflector());
|
||||||
conf[2] = rotor3View.getSelectedItemPosition() + 1;
|
this.rotor1PositionView.setSelection(state.getRotationRotor1());
|
||||||
//Reflector
|
this.rotor2PositionView.setSelection(state.getRotationRotor2());
|
||||||
conf[3] = reflectorView.getSelectedItemPosition() + 2; //M3 has no B
|
this.rotor3PositionView.setSelection(state.getRotationRotor3());
|
||||||
|
}
|
||||||
|
|
||||||
conf[4] = rotor1PositionView.getSelectedItemPosition();
|
@Override
|
||||||
conf[5] = rotor2PositionView.getSelectedItemPosition();
|
public void syncStateFromLayoutToEnigma()
|
||||||
conf[6] = rotor3PositionView.getSelectedItemPosition();
|
{
|
||||||
|
EnigmaStateBundle state = getEnigma().getState();
|
||||||
|
state.setTypeRotor1(rotor1View.getSelectedItemPosition());
|
||||||
|
state.setTypeRotor2(rotor2View.getSelectedItemPosition());
|
||||||
|
state.setTypeRotor3(rotor3View.getSelectedItemPosition());
|
||||||
|
state.setTypeReflector(reflectorView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor1(rotor1PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor2(rotor2PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor3(rotor3PositionView.getSelectedItemPosition());
|
||||||
|
getEnigma().setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
conf[7] = ringSettings[0];
|
@Override
|
||||||
conf[8] = ringSettings[1];
|
public Enigma_M3 getEnigma()
|
||||||
conf[9] = ringSettings[2];
|
{
|
||||||
|
return this.enigma;
|
||||||
return conf;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,39 +1,37 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package de.vanitasvitae.enigmandroid.layout;
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
import de.vanitasvitae.enigmandroid.R;
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
|
||||||
import de.vanitasvitae.enigmandroid.enigma.Enigma_M4;
|
import de.vanitasvitae.enigmandroid.enigma.Enigma_M4;
|
||||||
import de.vanitasvitae.enigmandroid.enigma.Plugboard;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete LayoutContainer for the M4 layout.
|
* Concrete LayoutContainer for the M4 layout.
|
||||||
* This class contains the layout and controls the layout elements such as spinners and stuff
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
* Copyright (C) 2015 Paul Schaub
|
* 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
|
public class LayoutContainer_M4 extends LayoutContainer
|
||||||
{
|
{
|
||||||
|
private Enigma_M4 enigma;
|
||||||
|
|
||||||
private Spinner rotor1View;
|
private Spinner rotor1View;
|
||||||
private Spinner rotor2View;
|
private Spinner rotor2View;
|
||||||
private Spinner rotor3View;
|
private Spinner rotor3View;
|
||||||
|
@ -44,211 +42,98 @@ public class LayoutContainer_M4 extends LayoutContainer
|
||||||
private Spinner rotor3PositionView;
|
private Spinner rotor3PositionView;
|
||||||
private Spinner rotor4PositionView;
|
private Spinner rotor4PositionView;
|
||||||
|
|
||||||
private EditText plugboardView;
|
|
||||||
|
|
||||||
public LayoutContainer_M4()
|
public LayoutContainer_M4()
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
main.setTitle("M4 - EnigmAndroid");
|
main.setTitle("M4 - EnigmAndroid");
|
||||||
this.enigma = new Enigma_M4();
|
this.resetLayout();
|
||||||
this.ringSettings = new int[]{0,0,0,0};
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setEnigmaLayout()
|
||||||
|
{
|
||||||
|
MainActivity.ActivitySingleton.getInstance().getActivity().setContentView(R.layout.activity_main_m4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Enigma_M4 getEnigma()
|
||||||
|
{
|
||||||
|
return this.enigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assembleLayout() {
|
||||||
this.rotor1View = (Spinner) main.findViewById(R.id.rotor1);
|
this.rotor1View = (Spinner) main.findViewById(R.id.rotor1);
|
||||||
this.rotor2View = (Spinner) main.findViewById(R.id.rotor2);
|
this.rotor2View = (Spinner) main.findViewById(R.id.rotor2);
|
||||||
this.rotor3View = (Spinner) main.findViewById(R.id.rotor3);
|
this.rotor3View = (Spinner) main.findViewById(R.id.rotor3);
|
||||||
this.rotor4View = (Spinner) main.findViewById(R.id.thin_rotor);
|
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.rotor1PositionView = (Spinner) main.findViewById(R.id.rotor1position);
|
||||||
this.rotor2PositionView = (Spinner) main.findViewById(R.id.rotor2position);
|
this.rotor2PositionView = (Spinner) main.findViewById(R.id.rotor2position);
|
||||||
this.rotor3PositionView = (Spinner) main.findViewById(R.id.rotor3position);
|
this.rotor3PositionView = (Spinner) main.findViewById(R.id.rotor3position);
|
||||||
this.rotor4PositionView = (Spinner) main.findViewById(R.id.thin_rotor_position);
|
this.rotor4PositionView = (Spinner) main.findViewById(R.id.thin_rotor_position);
|
||||||
this.plugboardView = (EditText) main.findViewById(R.id.plugboard);
|
this.reflectorView = (Spinner) main.findViewById(R.id.reflector);
|
||||||
this.inputView = (EditText) main.findViewById(R.id.input);
|
Button setPlugboardButton = (Button) main.findViewById(R.id.button_plugboard);
|
||||||
this.outputView = (EditText) main.findViewById(R.id.output);
|
if(setPlugboardButton != null) setPlugboardButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
new PluggableDialogBuilder(getEnigma().getState()).showDialogPlugboard();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
initialize();
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void initialize()
|
|
||||||
{
|
|
||||||
Character[] rotorPositionArray = new Character[26];
|
Character[] rotorPositionArray = new Character[26];
|
||||||
for(int i=0; i<26; i++) {rotorPositionArray[i] = (char) (65+i); /**Fill with A..Z*/}
|
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,
|
prepareSpinnerAdapter(rotor1View, R.array.rotors_1_8);
|
||||||
android.R.layout.simple_spinner_item);
|
prepareSpinnerAdapter(rotor2View, R.array.rotors_1_8);
|
||||||
rotor1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
prepareSpinnerAdapter(rotor3View, R.array.rotors_1_8);
|
||||||
rotor1View.setAdapter(rotor1Adapter);
|
prepareSpinnerAdapter(rotor4View, R.array.rotors_beta_gamma);
|
||||||
ArrayAdapter<CharSequence> rotor2Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_1_8,
|
prepareSpinnerAdapter(reflectorView, R.array.reflectors_b_c);
|
||||||
android.R.layout.simple_spinner_item);
|
prepareSpinnerAdapter(rotor1PositionView, rotorPositionArray);
|
||||||
rotor2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
prepareSpinnerAdapter(rotor2PositionView, rotorPositionArray);
|
||||||
rotor2View.setAdapter(rotor2Adapter);
|
prepareSpinnerAdapter(rotor3PositionView, rotorPositionArray);
|
||||||
ArrayAdapter<CharSequence> rotor3Adapter = ArrayAdapter.createFromResource(main, R.array.rotors_1_8,
|
prepareSpinnerAdapter(rotor4PositionView, rotorPositionArray);
|
||||||
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
|
@Override
|
||||||
public void reset()
|
public void resetLayout() {
|
||||||
{
|
enigma = new Enigma_M4();
|
||||||
rotor1View.setSelection(0); //I
|
setLayoutState(enigma.getState());
|
||||||
rotor2View.setSelection(1); //II
|
output.setText("");
|
||||||
rotor3View.setSelection(2); //III
|
input.setText("");
|
||||||
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
|
@Override
|
||||||
public void updateLayout()
|
public void setLayoutState(EnigmaStateBundle state) {
|
||||||
{
|
this.rotor1View.setSelection(state.getTypeRotor1());
|
||||||
int[] conf = enigma.getConfiguration();
|
this.rotor2View.setSelection(state.getTypeRotor2());
|
||||||
rotor1View.setSelection(conf[0]-1);
|
this.rotor3View.setSelection(state.getTypeRotor3());
|
||||||
rotor2View.setSelection(conf[1]-1);
|
this.rotor4View.setSelection(state.getTypeRotor4());
|
||||||
rotor3View.setSelection(conf[2]-1);
|
this.reflectorView.setSelection(state.getTypeReflector());
|
||||||
rotor4View.setSelection(conf[3]-9);
|
this.rotor1PositionView.setSelection(state.getRotationRotor1());
|
||||||
reflectorView.setSelection(conf[4]-4);
|
this.rotor2PositionView.setSelection(state.getRotationRotor2());
|
||||||
rotor1PositionView.setSelection(conf[5]);
|
this.rotor3PositionView.setSelection(state.getRotationRotor3());
|
||||||
rotor2PositionView.setSelection(conf[6]);
|
this.rotor4PositionView.setSelection(state.getRotationRotor4());
|
||||||
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
|
@Override
|
||||||
public int[] createConfiguration()
|
public void syncStateFromLayoutToEnigma() {
|
||||||
{
|
EnigmaStateBundle state = getEnigma().getState();
|
||||||
int[] conf = new int[13];
|
state.setTypeRotor1(rotor1View.getSelectedItemPosition());
|
||||||
//Rotors 1..4
|
state.setTypeRotor2(rotor2View.getSelectedItemPosition());
|
||||||
conf[0] = rotor1View.getSelectedItemPosition() + 1;
|
state.setTypeRotor3(rotor3View.getSelectedItemPosition());
|
||||||
conf[1] = rotor2View.getSelectedItemPosition() + 1;
|
state.setTypeRotor4(rotor4View.getSelectedItemPosition());
|
||||||
conf[2] = rotor3View.getSelectedItemPosition() + 1;
|
state.setTypeReflector(reflectorView.getSelectedItemPosition());
|
||||||
conf[3] = rotor4View.getSelectedItemPosition() + 9; //Beta is rotor #9
|
state.setRotationRotor1(rotor1PositionView.getSelectedItemPosition());
|
||||||
//Reflector
|
state.setRotationRotor2(rotor2PositionView.getSelectedItemPosition());
|
||||||
conf[4] = reflectorView.getSelectedItemPosition() + 4; //thinB is reflector #4
|
state.setRotationRotor3(rotor3PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor4(rotor4PositionView.getSelectedItemPosition());
|
||||||
conf[5] = rotor1PositionView.getSelectedItemPosition();
|
getEnigma().setState(state);
|
||||||
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
|
@Override
|
||||||
public void showRingSettingsDialog()
|
public void showRingSettingsDialog()
|
||||||
{
|
{
|
||||||
Integer[] ringArray = new Integer[26];
|
new RingSettingsDialogBuilder.RingSettingsDialogBuilderRotRotRotRot().
|
||||||
for(int i=1; i<=26; i++) {ringArray[i-1] = i;}
|
createRingSettingsDialog(getEnigma().getState());
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma_R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LayoutContainer for the Enigma Model R
|
||||||
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class LayoutContainer_R extends LayoutContainer
|
||||||
|
{
|
||||||
|
private Enigma_R enigma;
|
||||||
|
|
||||||
|
private Spinner rotor1View;
|
||||||
|
private Spinner rotor2View;
|
||||||
|
private Spinner rotor3View;
|
||||||
|
|
||||||
|
private Spinner rotor1PositionView;
|
||||||
|
private Spinner rotor2PositionView;
|
||||||
|
private Spinner rotor3PositionView;
|
||||||
|
private Spinner reflectorPositionView;
|
||||||
|
|
||||||
|
public LayoutContainer_R()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
main.setTitle("R - EnigmAndroid");
|
||||||
|
this.resetLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setEnigmaLayout()
|
||||||
|
{
|
||||||
|
MainActivity.ActivitySingleton.getInstance().getActivity().setContentView(R.layout.activity_main_g_k_r_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Enigma getEnigma() {
|
||||||
|
return this.enigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assembleLayout() {
|
||||||
|
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.rotor1PositionView = (Spinner) main.findViewById(R.id.rotor1position);
|
||||||
|
this.rotor2PositionView = (Spinner) main.findViewById(R.id.rotor2position);
|
||||||
|
this.rotor3PositionView = (Spinner) main.findViewById(R.id.rotor3position);
|
||||||
|
this.reflectorPositionView = (Spinner) main.findViewById(R.id.reflector_position);
|
||||||
|
|
||||||
|
Character[] rotorPositionArray = new Character[26];
|
||||||
|
for(int i=0; i<26; i++) {rotorPositionArray[i] = (char) (65+i); /*Fill with A..Z*/}
|
||||||
|
|
||||||
|
prepareSpinnerAdapter(rotor1View, R.array.rotors_1_3);
|
||||||
|
prepareSpinnerAdapter(rotor2View, R.array.rotors_1_3);
|
||||||
|
prepareSpinnerAdapter(rotor3View, R.array.rotors_1_3);
|
||||||
|
prepareSpinnerAdapter(rotor1PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(rotor2PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(rotor3PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(reflectorPositionView, rotorPositionArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetLayout() {
|
||||||
|
enigma = new Enigma_R();
|
||||||
|
setLayoutState(enigma.getState());
|
||||||
|
output.setText("");
|
||||||
|
input.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLayoutState(EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
this.rotor1View.setSelection(state.getTypeRotor1());
|
||||||
|
this.rotor2View.setSelection(state.getTypeRotor2());
|
||||||
|
this.rotor3View.setSelection(state.getTypeRotor3());
|
||||||
|
this.rotor1PositionView.setSelection(state.getRotationRotor1());
|
||||||
|
this.rotor2PositionView.setSelection(state.getRotationRotor2());
|
||||||
|
this.rotor3PositionView.setSelection(state.getRotationRotor3());
|
||||||
|
this.reflectorPositionView.setSelection(state.getRotationReflector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void syncStateFromLayoutToEnigma()
|
||||||
|
{
|
||||||
|
EnigmaStateBundle state = getEnigma().getState();
|
||||||
|
state.setTypeRotor1(rotor1View.getSelectedItemPosition());
|
||||||
|
state.setTypeRotor2(rotor2View.getSelectedItemPosition());
|
||||||
|
state.setTypeRotor3(rotor3View.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor1(rotor1PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor2(rotor2PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor3(rotor3PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationReflector(reflectorPositionView.getSelectedItemPosition());
|
||||||
|
getEnigma().setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showRingSettingsDialog()
|
||||||
|
{
|
||||||
|
new RingSettingsDialogBuilder.RingSettingsDialogBuilderRotRotRotRef().
|
||||||
|
createRingSettingsDialog(getEnigma().getState());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,143 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.Enigma_T;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LayoutContainer for the Enigma Model T
|
||||||
|
* This class contains the layout and controls the layout elements such as spinners and stuff
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class LayoutContainer_T extends LayoutContainer
|
||||||
|
{
|
||||||
|
private Enigma_T enigma;
|
||||||
|
|
||||||
|
private Spinner rotor1View;
|
||||||
|
private Spinner rotor2View;
|
||||||
|
private Spinner rotor3View;
|
||||||
|
|
||||||
|
private Spinner rotor1PositionView;
|
||||||
|
private Spinner rotor2PositionView;
|
||||||
|
private Spinner rotor3PositionView;
|
||||||
|
private Spinner reflectorPositionView;
|
||||||
|
|
||||||
|
public LayoutContainer_T()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
main.setTitle("T - EnigmAndroid");
|
||||||
|
this.resetLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doCrypto()
|
||||||
|
{
|
||||||
|
if(inputView.getText().length()!=0)
|
||||||
|
{
|
||||||
|
syncStateFromLayoutToEnigma();
|
||||||
|
String message = inputView.getText().toString();
|
||||||
|
//<Insert funny comment here>
|
||||||
|
boolean egg = false;
|
||||||
|
if(message.hashCode() == -1475861192) egg = true;
|
||||||
|
message = inputPreparer.prepareString(message);
|
||||||
|
input.setText(message);
|
||||||
|
if(egg) output.setText("ENIGMA<TURINGMACHINE");
|
||||||
|
else output.setText(getEnigma().encryptString(message));
|
||||||
|
setLayoutState(getEnigma().getState());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setEnigmaLayout()
|
||||||
|
{
|
||||||
|
MainActivity.ActivitySingleton.getInstance().getActivity().setContentView(
|
||||||
|
R.layout.activity_main_g_k_r_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Enigma getEnigma() {
|
||||||
|
return this.enigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assembleLayout() {
|
||||||
|
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.rotor1PositionView = (Spinner) main.findViewById(R.id.rotor1position);
|
||||||
|
this.rotor2PositionView = (Spinner) main.findViewById(R.id.rotor2position);
|
||||||
|
this.rotor3PositionView = (Spinner) main.findViewById(R.id.rotor3position);
|
||||||
|
this.reflectorPositionView = (Spinner) main.findViewById(R.id.reflector_position);
|
||||||
|
|
||||||
|
Character[] rotorPositionArray = new Character[26];
|
||||||
|
for(int i=0; i<26; i++) {rotorPositionArray[i] = (char) (65+i); /*Fill with A..Z*/}
|
||||||
|
|
||||||
|
prepareSpinnerAdapter(rotor1View, R.array.rotors_1_8);
|
||||||
|
prepareSpinnerAdapter(rotor2View, R.array.rotors_1_8);
|
||||||
|
prepareSpinnerAdapter(rotor3View, R.array.rotors_1_8);
|
||||||
|
prepareSpinnerAdapter(rotor1PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(rotor2PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(rotor3PositionView, rotorPositionArray);
|
||||||
|
prepareSpinnerAdapter(reflectorPositionView, rotorPositionArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetLayout() {
|
||||||
|
enigma = new Enigma_T();
|
||||||
|
setLayoutState(enigma.getState());
|
||||||
|
output.setText("");
|
||||||
|
input.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLayoutState(EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
this.rotor1View.setSelection(state.getTypeRotor1());
|
||||||
|
this.rotor2View.setSelection(state.getTypeRotor2());
|
||||||
|
this.rotor3View.setSelection(state.getTypeRotor3());
|
||||||
|
|
||||||
|
this.rotor1PositionView.setSelection(state.getRotationRotor1());
|
||||||
|
this.rotor2PositionView.setSelection(state.getRotationRotor2());
|
||||||
|
this.rotor3PositionView.setSelection(state.getRotationRotor3());
|
||||||
|
this.reflectorPositionView.setSelection(state.getRotationReflector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void syncStateFromLayoutToEnigma()
|
||||||
|
{
|
||||||
|
EnigmaStateBundle state = getEnigma().getState();
|
||||||
|
state.setTypeRotor1(rotor1View.getSelectedItemPosition());
|
||||||
|
state.setTypeRotor2(rotor2View.getSelectedItemPosition());
|
||||||
|
state.setTypeRotor3(rotor3View.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor1(rotor1PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor2(rotor2PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationRotor3(rotor3PositionView.getSelectedItemPosition());
|
||||||
|
state.setRotationReflector(reflectorPositionView.getSelectedItemPosition());
|
||||||
|
getEnigma().setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showRingSettingsDialog()
|
||||||
|
{
|
||||||
|
new RingSettingsDialogBuilder.RingSettingsDialogBuilderRotRotRotRef().
|
||||||
|
createRingSettingsDialog(getEnigma().getState());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for the dialog that is used to obtain a passphrase to generate
|
||||||
|
* a enigma configuration from it.
|
||||||
|
* Alternatively the user can enter the content String from a EnigmAndroid QR-Code here.
|
||||||
|
* That would have the same effect as scanning the QR-Code.
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public class PassphraseDialogBuilder
|
||||||
|
{
|
||||||
|
private final MainActivity main;
|
||||||
|
private final View passphraseDialogView;
|
||||||
|
private final EditText passphrase;
|
||||||
|
private Button positive;
|
||||||
|
public PassphraseDialogBuilder()
|
||||||
|
{
|
||||||
|
main = (MainActivity) MainActivity.ActivitySingleton.getInstance().getActivity();
|
||||||
|
passphraseDialogView = View.inflate(main, R.layout.dialog_passphrase, null);
|
||||||
|
passphrase = (EditText) passphraseDialogView.findViewById(R.id.passphrase);
|
||||||
|
passphrase.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
//Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
//Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
//Count input text and enable positive button if length > 0.
|
||||||
|
//Disable else
|
||||||
|
if(s.length() > 0) positive.setEnabled(true);
|
||||||
|
else positive.setEnabled(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create and show the dialog
|
||||||
|
*/
|
||||||
|
public void showDialog()
|
||||||
|
{
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(main);
|
||||||
|
builder.setTitle(R.string.hint_configuration);
|
||||||
|
Dialog d = builder.setView(passphraseDialogView)
|
||||||
|
.setCancelable(true)
|
||||||
|
.setPositiveButton(R.string.dialog_positive, new DialogInterface.OnClickListener()
|
||||||
|
{
|
||||||
|
public void onClick(DialogInterface dialog, int id)
|
||||||
|
{
|
||||||
|
String pass = passphrase.getText().toString();
|
||||||
|
if(pass.startsWith(MainActivity.APP_ID+"/"))
|
||||||
|
{
|
||||||
|
main.restoreStateFromCode(pass);
|
||||||
|
Toast.makeText(main, R.string.dialog_passphrase_was_coded_state, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
main.applyStateFromSeed(pass);
|
||||||
|
String message = String.format(main.getResources().getString(
|
||||||
|
R.string.dialog_passphrase_set), " \'"+pass+"\'");
|
||||||
|
Toast.makeText(main, message, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.dialog_negative, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
Toast.makeText(main, R.string.dialog_abort,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}).create();
|
||||||
|
d.show();
|
||||||
|
positive = ((AlertDialog)d).getButton(AlertDialog.BUTTON_POSITIVE);
|
||||||
|
positive.setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,432 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for the dialog that is used to plug the plugboard/wire the
|
||||||
|
* rewirable reflector.
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
class PluggableDialogBuilder
|
||||||
|
{
|
||||||
|
private ArrayList<ButtonWrapper> buttons;
|
||||||
|
private View dialogView;
|
||||||
|
private final MainActivity main;
|
||||||
|
private final EnigmaStateBundle state;
|
||||||
|
|
||||||
|
private boolean allowIncompleteConnections;
|
||||||
|
private Button positive;
|
||||||
|
|
||||||
|
private HashSet<Integer> colors;
|
||||||
|
|
||||||
|
private int previouslyPressedButton = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor that prepares layout and buttons.
|
||||||
|
* @param state EnigmaStateBundle from which dialog gets restored and which gets manipulated
|
||||||
|
*/
|
||||||
|
public PluggableDialogBuilder(EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
this.state = state;
|
||||||
|
main = (MainActivity) MainActivity.ActivitySingleton.getInstance().getActivity();
|
||||||
|
initializeLayout();
|
||||||
|
setButtonListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show dialog for the plugboard
|
||||||
|
*/
|
||||||
|
public void showDialogPlugboard()
|
||||||
|
{
|
||||||
|
allowIncompleteConnections = true;
|
||||||
|
restoreConfigurationPlugboard();
|
||||||
|
AlertDialog.Builder adb = new AlertDialog.Builder(main);
|
||||||
|
adb.setTitle(R.string.title_plugboard_dialog);
|
||||||
|
Dialog d = adb.setView(dialogView)
|
||||||
|
.setCancelable(true)
|
||||||
|
.setPositiveButton(R.string.dialog_positive, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
int[] plugs = new int[26];
|
||||||
|
for (int i = 0; i < 26; i++) {
|
||||||
|
plugs[i] = buttons.get(i).getConnectedButton();
|
||||||
|
}
|
||||||
|
state.setConfigurationPlugboard(plugs);
|
||||||
|
main.onDialogFinished(state);
|
||||||
|
Toast.makeText(main.getApplication(), R.string.dialog_plugboard_set, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.dialog_negative, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
Toast.makeText(main, R.string.dialog_abort,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}).create();
|
||||||
|
|
||||||
|
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
|
||||||
|
lp.copyFrom(d.getWindow().getAttributes());
|
||||||
|
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||||
|
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||||
|
d.show();
|
||||||
|
d.getWindow().setAttributes(lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the dialog for the reflector. This can only be positively closed when all
|
||||||
|
* connections are made.
|
||||||
|
*/
|
||||||
|
public void showDialogReflector()
|
||||||
|
{
|
||||||
|
allowIncompleteConnections = false;
|
||||||
|
restoreConfigurationReflector();
|
||||||
|
AlertDialog.Builder adb = new AlertDialog.Builder(main);
|
||||||
|
adb.setTitle(R.string.title_reflector_dialog);
|
||||||
|
Dialog d = adb.setView(dialogView)
|
||||||
|
.setCancelable(true)
|
||||||
|
.setPositiveButton(R.string.dialog_positive, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
int[] plugs = new int[26];
|
||||||
|
for (int i = 0; i < 26; i++) {
|
||||||
|
plugs[i] = buttons.get(i).getConnectedButton();
|
||||||
|
}
|
||||||
|
state.setConfigurationReflector(plugs);
|
||||||
|
main.onDialogFinished(state);
|
||||||
|
Toast.makeText(main.getApplication(), R.string.dialog_reflector_set, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.dialog_negative, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
Toast.makeText(main, R.string.dialog_abort,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}).create();
|
||||||
|
|
||||||
|
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
|
||||||
|
lp.copyFrom(d.getWindow().getAttributes());
|
||||||
|
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||||
|
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||||
|
d.show();
|
||||||
|
positive = ((AlertDialog)d).getButton(AlertDialog.BUTTON_POSITIVE);
|
||||||
|
if(!allConnectionsDone())
|
||||||
|
{
|
||||||
|
positive.setEnabled(false);
|
||||||
|
}
|
||||||
|
d.getWindow().setAttributes(lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize array of buttons, initialize background-color hashset.
|
||||||
|
*/
|
||||||
|
private void initializeLayout()
|
||||||
|
{
|
||||||
|
buttons = new ArrayList<>();
|
||||||
|
dialogView = View.inflate(main, R.layout.dialog_plugs, null);
|
||||||
|
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.A),0));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.B),1));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.C),2));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.D),3));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.E),4));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.F),5));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.G),6));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.H),7));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.I),8));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.J),9));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.K),10));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.L),11));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.M),12));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.N),13));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.O),14));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.P),15));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.Q),16));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.R),17));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.S),18));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.T),19));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.U),20));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.V),21));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.W),22));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.X),23));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.Y),24));
|
||||||
|
buttons.add(new ButtonWrapper((Button) dialogView.findViewById(R.id.Z),25));
|
||||||
|
|
||||||
|
colors = new HashSet<>();
|
||||||
|
colors.add(R.drawable.button_orange);
|
||||||
|
colors.add(R.drawable.button_olive);
|
||||||
|
colors.add(R.drawable.button_blue);
|
||||||
|
colors.add(R.drawable.button_red);
|
||||||
|
colors.add(R.drawable.button_yellow);
|
||||||
|
colors.add(R.drawable.button_purple);
|
||||||
|
colors.add(R.drawable.button_green);
|
||||||
|
colors.add(R.drawable.button_cyan);
|
||||||
|
colors.add(R.drawable.button_berry);
|
||||||
|
colors.add(R.drawable.button_brown);
|
||||||
|
colors.add(R.drawable.button_pink);
|
||||||
|
colors.add(R.drawable.button_elder);
|
||||||
|
colors.add(R.drawable.button_black);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set listeners for all buttons
|
||||||
|
*/
|
||||||
|
private void setButtonListeners()
|
||||||
|
{
|
||||||
|
for(int i=0; i<26; i++)
|
||||||
|
{
|
||||||
|
Button b = buttons.get(i).getButton();
|
||||||
|
final int id = i;
|
||||||
|
b.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
buttonPressed(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check, whether all connections are done. If so, return true.
|
||||||
|
* return false otherwise
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
private boolean allConnectionsDone()
|
||||||
|
{
|
||||||
|
for(int i=0; i<buttons.size(); i++)
|
||||||
|
{
|
||||||
|
ButtonWrapper b = buttons.get(i);
|
||||||
|
if(b.getConnectedButton() == i || b.getConnectedButton() == -1) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* restore the connections according to the plugboard
|
||||||
|
*/
|
||||||
|
private void restoreConfigurationPlugboard()
|
||||||
|
{
|
||||||
|
restoreConfiguration(state.getConfigurationPlugboard());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* restore the connections according to the reflector
|
||||||
|
*/
|
||||||
|
private void restoreConfigurationReflector()
|
||||||
|
{
|
||||||
|
restoreConfiguration(state.getConfigurationReflector());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect all the buttons according to c.
|
||||||
|
* @param c array of connections
|
||||||
|
*/
|
||||||
|
private void restoreConfiguration(int[] c)
|
||||||
|
{
|
||||||
|
for(int i=0; i<26; i++)
|
||||||
|
{
|
||||||
|
setPlug(i, c[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect button1 and button2. If two buttons got pressed afterwards and they are not the same
|
||||||
|
* they get connected. If one or both of them was connected beforehand, these connections get
|
||||||
|
* resolved. If both events come from the same button, the buttons connections (if any) get
|
||||||
|
* resolved.
|
||||||
|
* @param button1 first and
|
||||||
|
* @param button2 second button
|
||||||
|
*/
|
||||||
|
private void setPlug(int button1, int button2)
|
||||||
|
{
|
||||||
|
if(button1 == button2)
|
||||||
|
{
|
||||||
|
setButtonFree(buttons.get(button1).getConnectedButton());
|
||||||
|
setButtonFree(button1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ButtonWrapper b1 = buttons.get(button1);
|
||||||
|
ButtonWrapper b2 = buttons.get(button2);
|
||||||
|
|
||||||
|
if (b1.getConnectedButton() != button1) {
|
||||||
|
setButtonFree(b1.getConnectedButton());
|
||||||
|
}
|
||||||
|
if (b2.getConnectedButton() != button2) {
|
||||||
|
setButtonFree(b2.getConnectedButton());
|
||||||
|
}
|
||||||
|
|
||||||
|
b1.setConnectedButton(button2);
|
||||||
|
b2.setConnectedButton(button1);
|
||||||
|
|
||||||
|
int res;
|
||||||
|
Iterator<Integer> it = colors.iterator();
|
||||||
|
res = it.next();
|
||||||
|
if(res == 0) res = it.next();
|
||||||
|
colors.remove(res);
|
||||||
|
|
||||||
|
b1.setResourceID(res);
|
||||||
|
b2.setResourceID(res);
|
||||||
|
}
|
||||||
|
updatePositiveButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update state of positive button. Check, if all connections are done and if so, enable positive
|
||||||
|
* button. Otherwise disable it.
|
||||||
|
*/
|
||||||
|
private void updatePositiveButton()
|
||||||
|
{
|
||||||
|
if(!allowIncompleteConnections && positive != null)
|
||||||
|
{
|
||||||
|
if(allConnectionsDone()) positive.setEnabled(true);
|
||||||
|
else positive.setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set buttons to not connected. That includes changing background to grey, set connection to
|
||||||
|
* itself.
|
||||||
|
* @param b index of button
|
||||||
|
*/
|
||||||
|
private void setButtonFree(int b)
|
||||||
|
{
|
||||||
|
ButtonWrapper button = buttons.get(b);
|
||||||
|
int res = button.getResourceID();
|
||||||
|
if(res != R.drawable.button_grey)
|
||||||
|
colors.add(button.getResourceID());
|
||||||
|
button.setResourceID(R.drawable.button_grey);
|
||||||
|
button.setConnectedButton(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle button pressed events.
|
||||||
|
* @param button button that got pressed
|
||||||
|
*/
|
||||||
|
private void buttonPressed(int button)
|
||||||
|
{
|
||||||
|
if(previouslyPressedButton != -1)
|
||||||
|
{
|
||||||
|
setPlug(previouslyPressedButton, button);
|
||||||
|
previouslyPressedButton = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
previouslyPressedButton = button;
|
||||||
|
buttons.get(button).setWaiting();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class for Buttons, that also stores the index of both, the connected button, as well
|
||||||
|
* as the button itself and resourceID of used material.
|
||||||
|
*/
|
||||||
|
private static class ButtonWrapper
|
||||||
|
{
|
||||||
|
private Button button;
|
||||||
|
private int connectedButton;
|
||||||
|
private int resourceID;
|
||||||
|
private int index;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create ButtonWrapper
|
||||||
|
* @param button underlying Button
|
||||||
|
* @param index index of the button in the buttons array
|
||||||
|
*/
|
||||||
|
public ButtonWrapper(Button button, int index)
|
||||||
|
{
|
||||||
|
this.button = button;
|
||||||
|
this.index = index;
|
||||||
|
this.connectedButton = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the index of the connected button and update buttons text
|
||||||
|
* @param other index
|
||||||
|
*/
|
||||||
|
public void setConnectedButton(int other)
|
||||||
|
{
|
||||||
|
this.connectedButton = other;
|
||||||
|
Resources res = MainActivity.ActivitySingleton.getInstance().getActivity().getResources();
|
||||||
|
this.getButton().setText(String.format(
|
||||||
|
res.getText(R.string.button_plug_title).toString(),
|
||||||
|
""+(char) (index+65),
|
||||||
|
""+(char) (connectedButton+65)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return index of the connected button
|
||||||
|
* @return index of connected button
|
||||||
|
*/
|
||||||
|
public int getConnectedButton()
|
||||||
|
{
|
||||||
|
return this.connectedButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate, that this button is waiting for another button to connect to.
|
||||||
|
*/
|
||||||
|
public void setWaiting()
|
||||||
|
{
|
||||||
|
Resources res = MainActivity.ActivitySingleton.getInstance().getActivity().getResources();
|
||||||
|
this.getButton().setText(String.format(
|
||||||
|
res.getText(R.string.button_plug_title).toString(),
|
||||||
|
""+(char) (index+65)," "));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set buttons background and store value in resourceID
|
||||||
|
* @param r resourceID of background material
|
||||||
|
*/
|
||||||
|
public void setResourceID(int r)
|
||||||
|
{
|
||||||
|
button.setBackgroundResource(r);
|
||||||
|
this.resourceID = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get resourceID of buttons background as store in resourceID
|
||||||
|
* @return resourceID
|
||||||
|
*/
|
||||||
|
public int getResourceID()
|
||||||
|
{
|
||||||
|
return this.resourceID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return stored button object
|
||||||
|
* @return button
|
||||||
|
*/
|
||||||
|
public Button getButton()
|
||||||
|
{
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,405 @@
|
||||||
|
/**
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package de.vanitasvitae.enigmandroid.layout;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import de.vanitasvitae.enigmandroid.MainActivity;
|
||||||
|
import de.vanitasvitae.enigmandroid.R;
|
||||||
|
import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for the dialog that is used to get settings for the rings
|
||||||
|
* Copyright (C) 2015 Paul Schaub
|
||||||
|
*/
|
||||||
|
public abstract class RingSettingsDialogBuilder
|
||||||
|
{
|
||||||
|
protected abstract void showDialog(EnigmaStateBundle stateBundle, ArrayAdapter[] adapters, int[] rIDs, Actions actions);
|
||||||
|
public abstract void createRingSettingsDialog(EnigmaStateBundle stateBundle);
|
||||||
|
|
||||||
|
private static ArrayAdapter createAdapter(Integer[] array)
|
||||||
|
{
|
||||||
|
ArrayAdapter adapter = new ArrayAdapter<>(
|
||||||
|
MainActivity.ActivitySingleton.getInstance().getActivity(),
|
||||||
|
android.R.layout.simple_spinner_item, array);
|
||||||
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
return adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ArrayAdapter working over an array of numbers 1 to 26.
|
||||||
|
* @return ArrayAdapter
|
||||||
|
*/
|
||||||
|
private static ArrayAdapter createAdapter1_26()
|
||||||
|
{
|
||||||
|
Integer[] ringArray = new Integer[26];
|
||||||
|
for(int i=1; i<=26; i++) {ringArray[i-1] = i;}
|
||||||
|
return createAdapter(ringArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DialogBuilder for 3 Spinners and ringSettingRotor1-3
|
||||||
|
*/
|
||||||
|
public static class RingSettingsDialogBuilderRotRotRot extends RingSettingsDialogBuilder
|
||||||
|
{
|
||||||
|
public void createRingSettingsDialog(final EnigmaStateBundle state)
|
||||||
|
{
|
||||||
|
this.showDialog(state,
|
||||||
|
new ArrayAdapter[]{
|
||||||
|
createAdapter1_26(),
|
||||||
|
createAdapter1_26(),
|
||||||
|
createAdapter1_26()},
|
||||||
|
new int[]{
|
||||||
|
R.string.hint_rotor1,
|
||||||
|
R.string.hint_rotor2,
|
||||||
|
R.string.hint_rotor3},
|
||||||
|
new Actions3(state) {
|
||||||
|
@Override
|
||||||
|
protected void firstSpinnerItemSelected(int pos) {
|
||||||
|
state.setRingSettingRotor1(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void secondSpinnerItemSelected(int pos) {
|
||||||
|
state.setRingSettingRotor2(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void thirdSpinnerItemSelected(int pos) {
|
||||||
|
state.setRingSettingRotor3(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getFirstValueFromBundle() {
|
||||||
|
return state.getRingSettingRotor1();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getSecondValueFromBundle() {
|
||||||
|
return state.getRingSettingRotor2();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getThirdValueFromBundle() {
|
||||||
|
return state.getRingSettingRotor3();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void showDialog(final EnigmaStateBundle stateBundle, ArrayAdapter[] adapters, int[] rIDs, Actions actions)
|
||||||
|
{
|
||||||
|
if(adapters.length != 3 || rIDs.length != 3)
|
||||||
|
{
|
||||||
|
Log.e(MainActivity.APP_ID, "RingSettingsDialogBuilderRotRotRot.showDialog():" +
|
||||||
|
" Length of adapters array or length of rIDs array not equal to 3!");
|
||||||
|
}
|
||||||
|
final Actions3 action = (Actions3) actions;
|
||||||
|
final MainActivity main = (MainActivity) MainActivity.ActivitySingleton.getInstance().getActivity();
|
||||||
|
View ringSettingsView = View.inflate(main, R.layout.dialog_ringsettings_3, null);
|
||||||
|
|
||||||
|
TextView ring1Title = (TextView) ringSettingsView.findViewById(R.id.dialog_text_rotor1);
|
||||||
|
ring1Title.setText(rIDs[0]);
|
||||||
|
TextView ring2Title = (TextView) ringSettingsView.findViewById(R.id.dialog_text_rotor2);
|
||||||
|
ring2Title.setText(rIDs[1]);
|
||||||
|
TextView ring3Title = (TextView) ringSettingsView.findViewById(R.id.dialog_text_rotor3);
|
||||||
|
ring3Title.setText(rIDs[2]);
|
||||||
|
|
||||||
|
final Spinner ring1 = (Spinner) ringSettingsView.findViewById(R.id.rotor1ring);
|
||||||
|
ring1.setAdapter(adapters[0]);
|
||||||
|
ring1.setSelection(action.getFirstValueFromBundle());
|
||||||
|
|
||||||
|
final Spinner ring2 = (Spinner) ringSettingsView.findViewById(R.id.rotor2ring);
|
||||||
|
ring2.setAdapter(adapters[1]);
|
||||||
|
ring2.setSelection(action.getSecondValueFromBundle());
|
||||||
|
|
||||||
|
final Spinner ring3 = (Spinner) ringSettingsView.findViewById(R.id.rotor3ring);
|
||||||
|
ring3.setAdapter(adapters[2]);
|
||||||
|
ring3.setSelection(action.getThirdValueFromBundle());
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(main);
|
||||||
|
builder.setTitle(R.string.title_ring_setting);
|
||||||
|
builder.setView(ringSettingsView)
|
||||||
|
.setCancelable(true)
|
||||||
|
.setPositiveButton(R.string.dialog_positive, new DialogInterface.OnClickListener()
|
||||||
|
{
|
||||||
|
public void onClick(DialogInterface dialog, int id)
|
||||||
|
{
|
||||||
|
action.firstSpinnerItemSelected(ring1.getSelectedItemPosition());
|
||||||
|
action.secondSpinnerItemSelected(ring2.getSelectedItemPosition());
|
||||||
|
action.thirdSpinnerItemSelected(ring3.getSelectedItemPosition());
|
||||||
|
String message = String.format(main.getResources().getString(
|
||||||
|
R.string.dialog_ring_settings_success),
|
||||||
|
(ring1.getSelectedItemPosition()+1) + ", " +
|
||||||
|
(ring2.getSelectedItemPosition()+1) + ", " +
|
||||||
|
(ring3.getSelectedItemPosition()+1));
|
||||||
|
main.onDialogFinished(stateBundle);
|
||||||
|
Toast.makeText(main, message, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.dialog_negative, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
Toast.makeText(main, R.string.dialog_abort,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DialogBuilder for 4 Spinners and ringSettingRotor1-3, ringSettingReflector
|
||||||
|
*/
|
||||||
|
public static class RingSettingsDialogBuilderRotRotRotRef extends RingSettingsDialogBuilder
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void createRingSettingsDialog(final EnigmaStateBundle state) {
|
||||||
|
this.showDialog(state,
|
||||||
|
new ArrayAdapter[]{
|
||||||
|
createAdapter1_26(),
|
||||||
|
createAdapter1_26(),
|
||||||
|
createAdapter1_26(),
|
||||||
|
createAdapter1_26()},
|
||||||
|
new int[]{
|
||||||
|
R.string.hint_rotor1,
|
||||||
|
R.string.hint_rotor2,
|
||||||
|
R.string.hint_rotor3,
|
||||||
|
R.string.hint_reflector},
|
||||||
|
new Actions4(state) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void firstSpinnerItemSelected(int pos) {
|
||||||
|
state.setRingSettingRotor1(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void secondSpinnerItemSelected(int pos) {
|
||||||
|
state.setRingSettingRotor2(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void thirdSpinnerItemSelected(int pos) {
|
||||||
|
state.setRingSettingRotor3(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getFirstValueFromBundle() {
|
||||||
|
return state.getRingSettingRotor1();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getSecondValueFromBundle() {
|
||||||
|
return state.getRingSettingRotor2();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getThirdValueFromBundle() {
|
||||||
|
return state.getRingSettingRotor3();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void fourthSpinnerItemSelected(int pos) {
|
||||||
|
state.setRingSettingReflector(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getFourthValueFromBundle() {
|
||||||
|
return state.getRingSettingReflector();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void showDialog(final EnigmaStateBundle stateBundle, ArrayAdapter[] adapters, int[] rIDs, Actions actions) {
|
||||||
|
if(adapters.length != 4 || rIDs.length != 4)
|
||||||
|
{
|
||||||
|
Log.d(MainActivity.APP_ID, "RingSettingsDialogBuilderRotRotRotRef.showDialog():" +
|
||||||
|
"Length of adapters array or length of rIDs array not equal to 4!");
|
||||||
|
}
|
||||||
|
final Actions4 action = (Actions4) actions;
|
||||||
|
final MainActivity main = (MainActivity) MainActivity.ActivitySingleton.getInstance().getActivity();
|
||||||
|
View ringSettingsView = View.inflate(main, R.layout.dialog_ringsettings_4, null);
|
||||||
|
|
||||||
|
TextView ring1Title = (TextView) ringSettingsView.findViewById(R.id.dialog_text_rotor1);
|
||||||
|
ring1Title.setText(rIDs[0]);
|
||||||
|
TextView ring2Title = (TextView) ringSettingsView.findViewById(R.id.dialog_text_rotor2);
|
||||||
|
ring2Title.setText(rIDs[1]);
|
||||||
|
TextView ring3Title = (TextView) ringSettingsView.findViewById(R.id.dialog_text_rotor3);
|
||||||
|
ring3Title.setText(rIDs[2]);
|
||||||
|
TextView ring4Title = (TextView) ringSettingsView.findViewById(R.id.dialog_text_rotor4);
|
||||||
|
ring4Title.setText(rIDs[3]);
|
||||||
|
|
||||||
|
final Spinner ring1 = (Spinner) ringSettingsView.findViewById(R.id.rotor1ring);
|
||||||
|
ring1.setAdapter(adapters[0]);
|
||||||
|
ring1.setSelection(action.getFirstValueFromBundle());
|
||||||
|
|
||||||
|
final Spinner ring2 = (Spinner) ringSettingsView.findViewById(R.id.rotor2ring);
|
||||||
|
ring2.setAdapter(adapters[1]);
|
||||||
|
ring2.setSelection(action.getSecondValueFromBundle());
|
||||||
|
|
||||||
|
final Spinner ring3 = (Spinner) ringSettingsView.findViewById(R.id.rotor3ring);
|
||||||
|
ring3.setAdapter(adapters[2]);
|
||||||
|
ring3.setSelection(action.getThirdValueFromBundle());
|
||||||
|
|
||||||
|
final Spinner ring4 = (Spinner) ringSettingsView.findViewById(R.id.rotor4ring);
|
||||||
|
ring4.setAdapter(adapters[3]);
|
||||||
|
ring4.setSelection(action.getFourthValueFromBundle());
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(main);
|
||||||
|
builder.setTitle(R.string.title_ring_setting);
|
||||||
|
builder.setView(ringSettingsView)
|
||||||
|
.setCancelable(true)
|
||||||
|
.setPositiveButton(R.string.dialog_positive, new DialogInterface.OnClickListener()
|
||||||
|
{
|
||||||
|
public void onClick(DialogInterface dialog, int id)
|
||||||
|
{
|
||||||
|
action.firstSpinnerItemSelected(ring1.getSelectedItemPosition());
|
||||||
|
action.secondSpinnerItemSelected(ring2.getSelectedItemPosition());
|
||||||
|
action.thirdSpinnerItemSelected(ring3.getSelectedItemPosition());
|
||||||
|
action.fourthSpinnerItemSelected(ring4.getSelectedItemPosition());
|
||||||
|
String message = String.format(main.getResources().getString(
|
||||||
|
R.string.dialog_ring_settings_success),
|
||||||
|
(ring1.getSelectedItemPosition()+1) + ", " +
|
||||||
|
(ring2.getSelectedItemPosition()+1) + ", " +
|
||||||
|
(ring3.getSelectedItemPosition()+1) + ", " +
|
||||||
|
(ring4.getSelectedItemPosition()+1));
|
||||||
|
main.onDialogFinished(stateBundle);
|
||||||
|
Toast.makeText(main, message, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.dialog_negative, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
Toast.makeText(main, R.string.dialog_abort,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DialogBuilder for 4 Spinners and ringSettingRotor1-4
|
||||||
|
*/
|
||||||
|
public static class RingSettingsDialogBuilderRotRotRotRot extends RingSettingsDialogBuilderRotRotRotRef
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void createRingSettingsDialog(final EnigmaStateBundle state) {
|
||||||
|
this.showDialog(state,
|
||||||
|
new ArrayAdapter[]{
|
||||||
|
createAdapter1_26(),
|
||||||
|
createAdapter1_26(),
|
||||||
|
createAdapter1_26(),
|
||||||
|
createAdapter1_26()},
|
||||||
|
new int[]{
|
||||||
|
R.string.hint_rotor1,
|
||||||
|
R.string.hint_rotor2,
|
||||||
|
R.string.hint_rotor3,
|
||||||
|
R.string.hint_thin_rotor},
|
||||||
|
new Actions4(state) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void firstSpinnerItemSelected(int pos) {
|
||||||
|
state.setRingSettingRotor1(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void secondSpinnerItemSelected(int pos) {
|
||||||
|
state.setRingSettingRotor2(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void thirdSpinnerItemSelected(int pos) {
|
||||||
|
state.setRingSettingRotor3(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getFirstValueFromBundle() {
|
||||||
|
return state.getRingSettingRotor1();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getSecondValueFromBundle() {
|
||||||
|
return state.getRingSettingRotor2();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getThirdValueFromBundle() {
|
||||||
|
return state.getRingSettingRotor3();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void fourthSpinnerItemSelected(int pos) {
|
||||||
|
state.setRingSettingRotor4(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getFourthValueFromBundle() {
|
||||||
|
return state.getRingSettingRotor4();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract class that defines how Spinners correspond to the EnigmaStateBundle
|
||||||
|
*/
|
||||||
|
public static abstract class Actions
|
||||||
|
{
|
||||||
|
final EnigmaStateBundle stateBundle;
|
||||||
|
public Actions(EnigmaStateBundle bundle)
|
||||||
|
{
|
||||||
|
this.stateBundle = bundle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract class that defines, how the 3 Spinners correspond to 3 values in the
|
||||||
|
* EnigmaStateBundle
|
||||||
|
*/
|
||||||
|
public static abstract class Actions3 extends Actions
|
||||||
|
{
|
||||||
|
public Actions3(EnigmaStateBundle bundle)
|
||||||
|
{
|
||||||
|
super(bundle);
|
||||||
|
}
|
||||||
|
protected abstract void firstSpinnerItemSelected(int pos);
|
||||||
|
protected abstract void secondSpinnerItemSelected(int pos);
|
||||||
|
protected abstract void thirdSpinnerItemSelected(int pos);
|
||||||
|
protected abstract int getFirstValueFromBundle();
|
||||||
|
protected abstract int getSecondValueFromBundle();
|
||||||
|
protected abstract int getThirdValueFromBundle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension of Actions3 which forces implementing classes to implement methods for the fourth
|
||||||
|
* Spinner.
|
||||||
|
*/
|
||||||
|
public static abstract class Actions4 extends Actions3
|
||||||
|
{
|
||||||
|
public Actions4(EnigmaStateBundle bundle)
|
||||||
|
{
|
||||||
|
super(bundle);
|
||||||
|
}
|
||||||
|
protected abstract void fourthSpinnerItemSelected(int pos);
|
||||||
|
protected abstract int getFourthValueFromBundle();
|
||||||
|
}
|
||||||
|
}
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 23 KiB |
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content">
|
||||||
|
<item android:state_pressed="true" >
|
||||||
|
<shape>
|
||||||
|
<solid
|
||||||
|
android:color="#ea138f" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#222222" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<gradient
|
||||||
|
android:startColor="#810e41"
|
||||||
|
android:endColor="#930e52"
|
||||||
|
android:angle="270" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#52082e" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content">
|
||||||
|
<item android:state_pressed="true" >
|
||||||
|
<shape>
|
||||||
|
<solid
|
||||||
|
android:color="#444552" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#222222" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<gradient
|
||||||
|
android:startColor="#23262e"
|
||||||
|
android:endColor="#24252e"
|
||||||
|
android:angle="270" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#181719" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content">
|
||||||
|
<item android:state_pressed="true" >
|
||||||
|
<shape>
|
||||||
|
<solid
|
||||||
|
android:color="#b94b52e4" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#222222" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<gradient
|
||||||
|
android:startColor="#b94b52e4"
|
||||||
|
android:endColor="#a74e55ff"
|
||||||
|
android:angle="270" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#1e2153" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content">
|
||||||
|
<item android:state_pressed="true" >
|
||||||
|
<shape>
|
||||||
|
<solid
|
||||||
|
android:color="#de9307" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#222222" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<gradient
|
||||||
|
android:startColor="#864f07"
|
||||||
|
android:endColor="#9c6007"
|
||||||
|
android:angle="270" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#462606" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content">
|
||||||
|
<item android:state_pressed="true" >
|
||||||
|
<shape>
|
||||||
|
<solid
|
||||||
|
android:color="#15dbdc" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#222222" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<gradient
|
||||||
|
android:startColor="#139e9f"
|
||||||
|
android:endColor="#13aeaf"
|
||||||
|
android:angle="270" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#115c5d" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content">
|
||||||
|
<item android:state_pressed="true" >
|
||||||
|
<shape>
|
||||||
|
<solid
|
||||||
|
android:color="#c895ad" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#222222" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<gradient
|
||||||
|
android:startColor="#815f6b"
|
||||||
|
android:endColor="#8e6a77"
|
||||||
|
android:angle="270" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#53353f" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content">
|
||||||
|
<item android:state_pressed="true" >
|
||||||
|
<shape>
|
||||||
|
<solid
|
||||||
|
android:color="#6aff46" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#222222" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<gradient
|
||||||
|
android:startColor="#54bb32"
|
||||||
|
android:endColor="#56cc33"
|
||||||
|
android:angle="270" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#3b7727" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content">
|
||||||
|
<item android:state_pressed="true" >
|
||||||
|
<shape>
|
||||||
|
<solid
|
||||||
|
android:color="#666670" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#222222" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<gradient
|
||||||
|
android:startColor="#3f4046"
|
||||||
|
android:endColor="#3c3d43"
|
||||||
|
android:angle="270" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#181719" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content">
|
||||||
|
<item android:state_pressed="true" >
|
||||||
|
<shape>
|
||||||
|
<solid
|
||||||
|
android:color="#a4e82b" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#222222" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<gradient
|
||||||
|
android:startColor="#4f7d1d"
|
||||||
|
android:endColor="#5f8e1e"
|
||||||
|
android:angle="270" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#365013" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
0
app/src/main/res/drawable/button.xml → app/src/main/res/drawable/button_orange.xml
Executable file → Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content">
|
||||||
|
<item android:state_pressed="true" >
|
||||||
|
<shape>
|
||||||
|
<solid
|
||||||
|
android:color="#95ff168e" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#222222" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<gradient
|
||||||
|
android:startColor="#d1156d"
|
||||||
|
android:endColor="#e5157f"
|
||||||
|
android:angle="270" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#8c0e49" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content">
|
||||||
|
<item android:state_pressed="true" >
|
||||||
|
<shape>
|
||||||
|
<solid
|
||||||
|
android:color="#cf54ff" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#222222" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<gradient
|
||||||
|
android:startColor="#9944c2"
|
||||||
|
android:endColor="#de9944c2"
|
||||||
|
android:angle="270" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#703290" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content">
|
||||||
|
<item android:state_pressed="true" >
|
||||||
|
<shape>
|
||||||
|
<solid
|
||||||
|
android:color="#ff4f52" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#222222" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<gradient
|
||||||
|
android:startColor="#d9ef241e"
|
||||||
|
android:endColor="#bdef3f3f"
|
||||||
|
android:angle="270" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#5a1717" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content">
|
||||||
|
<item android:state_pressed="true" >
|
||||||
|
<shape>
|
||||||
|
<solid
|
||||||
|
android:color="#cbfffc0f" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#222222" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<gradient
|
||||||
|
android:startColor="#b7b40e"
|
||||||
|
android:endColor="#d2cf0e"
|
||||||
|
android:angle="270" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="#5c5903" />
|
||||||
|
<corners
|
||||||
|
android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:left="10dp"
|
||||||
|
android:top="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 42 KiB |
|
@ -0,0 +1,123 @@
|
||||||
|
<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="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/hint_reflector_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>
|
||||||
|
<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_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>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/lin_lay_1"
|
||||||
|
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"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/button_reflector"
|
||||||
|
android:text="@string/hint_enigma_reflector_wiring"
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle"/>
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/button_crypt"
|
||||||
|
android:onClick="doCrypto"
|
||||||
|
android:text="@string/button_crypt"
|
||||||
|
android:background="@drawable/button_orange"
|
||||||
|
tools:ignore="ButtonStyle"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -0,0 +1,144 @@
|
||||||
|
<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="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_reflector_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>
|
||||||
|
|
||||||
|
<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/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/reflector_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>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/lin_lay_1"
|
||||||
|
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="match_parent"
|
||||||
|
android:id="@+id/button_crypt"
|
||||||
|
android:onClick="doCrypto"
|
||||||
|
android:text="@string/button_crypt"
|
||||||
|
android:background="@drawable/button_orange"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -119,41 +119,13 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</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 -->
|
<!-- Textboxes for input and output -->
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@+id/buttons_lay"
|
android:layout_below="@+id/lin_lay_1"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_above="@id/buttons_lay"
|
||||||
android:id="@+id/text_layer">
|
android:id="@+id/text_layer">
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
|
@ -174,4 +146,34 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/buttons_lay"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:text="@string/title_plugboard_dialog"
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
android:id="@+id/button_plugboard"
|
||||||
|
tools:ignore="ButtonStyle"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:id="@+id/button_crypt"
|
||||||
|
android:onClick="doCrypto"
|
||||||
|
android:text="@string/button_crypt"
|
||||||
|
android:background="@drawable/button_orange"
|
||||||
|
tools:ignore="ButtonStyle"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -144,41 +144,13 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</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 -->
|
<!-- Textboxes for input and output -->
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@+id/buttons_lay"
|
android:layout_below="@+id/lin_lay_1"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_above="@id/buttons_lay"
|
||||||
android:id="@+id/text_layer">
|
android:id="@+id/text_layer">
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
|
@ -198,5 +170,32 @@
|
||||||
android:hint="@string/hint_enigma_code"/>
|
android:hint="@string/hint_enigma_code"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/buttons_lay"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/button_plugboard"
|
||||||
|
android:text="@string/title_plugboard_dialog"
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle"/>
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/button_crypt"
|
||||||
|
android:onClick="doCrypto"
|
||||||
|
android:text="@string/button_crypt"
|
||||||
|
android:background="@drawable/button_orange"
|
||||||
|
tools:ignore="ButtonStyle"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -0,0 +1,254 @@
|
||||||
|
<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="wrap_content"
|
||||||
|
android:paddingStart="5dp"
|
||||||
|
android:paddingEnd="5dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:id="@+id/first_row">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/Q"
|
||||||
|
android:text="Q: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/W"
|
||||||
|
android:text="W: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/E"
|
||||||
|
android:text="E: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/R"
|
||||||
|
android:text="R: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/T"
|
||||||
|
android:text="T: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/Z"
|
||||||
|
android:text="Z: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/U"
|
||||||
|
android:text="U: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/I"
|
||||||
|
android:text="I: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/O"
|
||||||
|
android:text="O: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_below="@id/first_row"
|
||||||
|
android:id="@+id/second_row">
|
||||||
|
|
||||||
|
<android.support.v4.widget.Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/A"
|
||||||
|
android:text="A: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/S"
|
||||||
|
android:text="S: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/D"
|
||||||
|
android:text="D: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/F"
|
||||||
|
android:text="F: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/G"
|
||||||
|
android:text="G: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/H"
|
||||||
|
android:text="H: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/J"
|
||||||
|
android:text="J: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/K"
|
||||||
|
android:text="K: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<android.support.v4.widget.Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_below="@id/second_row"
|
||||||
|
android:id="@+id/third_row">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/P"
|
||||||
|
android:text="P: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/Y"
|
||||||
|
android:text="Y: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/X"
|
||||||
|
android:text="X: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/C"
|
||||||
|
android:text="C: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/V"
|
||||||
|
android:text="V: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/B"
|
||||||
|
android:text="B: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/N"
|
||||||
|
android:text="N: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/M"
|
||||||
|
android:text="M: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/L"
|
||||||
|
android:text="L: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -0,0 +1,88 @@
|
||||||
|
<ScrollView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:paddingStart="5dp"
|
||||||
|
android:paddingEnd="5dp">
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:id="@+id/ringstellung_layout_hint">
|
||||||
|
|
||||||
|
<!-- About Enigma. -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Medium"
|
||||||
|
android:text="@string/title_about_dialog"
|
||||||
|
android:id="@+id/title_section_app_description_text"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Holo.Small"
|
||||||
|
android:text="@string/description_text"
|
||||||
|
android:id="@+id/about_app_description"/>
|
||||||
|
|
||||||
|
<!-- About Version -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Holo.Medium"
|
||||||
|
android:text="@string/action_version"
|
||||||
|
android:id="@+id/title_section_version"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Holo.Small"
|
||||||
|
android:id="@+id/about_version_section"/>
|
||||||
|
|
||||||
|
<!-- About How To -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Holo.Medium"
|
||||||
|
android:text="@string/title_section_how_to_use"
|
||||||
|
android:id="@+id/title_section_how_to_use"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Holo.Small"
|
||||||
|
android:text="@string/section_how_to_use"
|
||||||
|
android:id="@+id/section_how_to_use"/>
|
||||||
|
|
||||||
|
<!-- About Developer -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Holo.Medium"
|
||||||
|
android:text="@string/title_section_developer"
|
||||||
|
android:id="@+id/title_section_developer_text"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Holo.Small"
|
||||||
|
android:text="@string/section_developer"
|
||||||
|
android:id="@+id/about_developer_section"/>
|
||||||
|
|
||||||
|
<!-- About Disclaimer -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Holo.Medium"
|
||||||
|
android:text="@string/title_section_disclaimer"
|
||||||
|
android:id="@+id/title_section_disclaimer_text"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Holo.Small"
|
||||||
|
android:text="@string/section_disclaimer"
|
||||||
|
android:id="@+id/about_disclaimer_section"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
|
@ -0,0 +1,123 @@
|
||||||
|
<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_2">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/hint_reflector_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>
|
||||||
|
|
||||||
|
<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="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/reflector_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>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/lin_lay_2"
|
||||||
|
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="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/button_reflector"
|
||||||
|
android:text="@string/hint_enigma_reflector_wiring"
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle"/>
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/button_crypt"
|
||||||
|
android:onClick="doCrypto"
|
||||||
|
android:text="@string/button_crypt"
|
||||||
|
android:background="@drawable/button_orange"
|
||||||
|
tools:ignore="ButtonStyle"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -0,0 +1,162 @@
|
||||||
|
<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="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"/>
|
||||||
|
</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="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>
|
||||||
|
</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="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/hint_reflector_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>
|
||||||
|
|
||||||
|
<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="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/reflector_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>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/lin_lay_2"
|
||||||
|
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_orange"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -78,7 +78,7 @@
|
||||||
android:layout_below="@+id/lin_lay_1"
|
android:layout_below="@+id/lin_lay_1"
|
||||||
android:id="@+id/lin_lay_names_2">
|
android:id="@+id/lin_lay_names_2">
|
||||||
|
|
||||||
<Space
|
<android.support.v4.widget.Space
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight=".125"
|
android:layout_weight=".125"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
@ -99,7 +99,7 @@
|
||||||
android:layout_weight=".25"
|
android:layout_weight=".25"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/hint_rotor1_position"/>
|
android:text="@string/hint_rotor1_position"/>
|
||||||
<Space
|
<android.support.v4.widget.Space
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight=".125"
|
android:layout_weight=".125"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
@ -112,7 +112,7 @@
|
||||||
android:id="@+id/lin_lay_2"
|
android:id="@+id/lin_lay_2"
|
||||||
android:layout_below="@+id/lin_lay_names_2">
|
android:layout_below="@+id/lin_lay_names_2">
|
||||||
|
|
||||||
<Space
|
<android.support.v4.widget.Space
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight=".125"
|
android:layout_weight=".125"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
@ -134,24 +134,16 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/rotor1position">
|
android:id="@+id/rotor1position">
|
||||||
</Spinner>
|
</Spinner>
|
||||||
<Space
|
<android.support.v4.widget.Space
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight=".125"
|
android:layout_weight=".125"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
</LinearLayout>
|
</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
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@+id/plugboard"
|
android:layout_below="@+id/lin_lay_2"
|
||||||
android:layout_above="@+id/buttons_lay"
|
android:layout_above="@+id/buttons_lay"
|
||||||
android:id="@+id/text_layer">
|
android:id="@+id/text_layer">
|
||||||
<EditText
|
<EditText
|
||||||
|
@ -178,13 +170,22 @@
|
||||||
android:id="@+id/buttons_lay"
|
android:id="@+id/buttons_lay"
|
||||||
android:layout_alignParentBottom="true">
|
android:layout_alignParentBottom="true">
|
||||||
<Button
|
<Button
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_weight="50"
|
||||||
|
android:text="@string/title_plugboard_dialog"
|
||||||
|
android:id="@+id/button_plugboard"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle"/>
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/button_crypt"
|
android:id="@+id/button_crypt"
|
||||||
android:onClick="doCrypto"
|
android:onClick="doCrypto"
|
||||||
android:text="@string/button_crypt"
|
android:text="@string/button_crypt"
|
||||||
android:background="@drawable/button"
|
android:background="@drawable/button_orange"
|
||||||
/>
|
tools:ignore="ButtonStyle"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
<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="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"/>
|
||||||
|
</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="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>
|
||||||
|
</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="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/hint_reflector_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>
|
||||||
|
|
||||||
|
<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="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/reflector_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>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/lin_lay_2"
|
||||||
|
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="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/button_reflector"
|
||||||
|
android:text="@string/hint_enigma_reflector_wiring"
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle"/>
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/button_crypt"
|
||||||
|
android:onClick="doCrypto"
|
||||||
|
android:text="@string/button_crypt"
|
||||||
|
android:background="@drawable/button_orange"
|
||||||
|
tools:ignore="ButtonStyle"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -146,18 +146,10 @@
|
||||||
</Spinner>
|
</Spinner>
|
||||||
</LinearLayout>
|
</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
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@+id/plugboard"
|
android:layout_below="@+id/lin_lay_2"
|
||||||
android:layout_above="@+id/buttons_lay"
|
android:layout_above="@+id/buttons_lay"
|
||||||
android:id="@+id/text_layer">
|
android:id="@+id/text_layer">
|
||||||
<EditText
|
<EditText
|
||||||
|
@ -184,13 +176,23 @@
|
||||||
android:id="@+id/buttons_lay"
|
android:id="@+id/buttons_lay"
|
||||||
android:layout_alignParentBottom="true">
|
android:layout_alignParentBottom="true">
|
||||||
<Button
|
<Button
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_weight="50"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/button_plugboard"
|
||||||
|
android:text="@string/title_plugboard_dialog"
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/button_crypt"
|
android:id="@+id/button_crypt"
|
||||||
android:onClick="doCrypto"
|
android:onClick="doCrypto"
|
||||||
android:text="@string/button_crypt"
|
android:text="@string/button_crypt"
|
||||||
android:background="@drawable/button"
|
android:background="@drawable/button_orange"
|
||||||
/>
|
tools:ignore="ButtonStyle"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
<RelativeLayout
|
<ScrollView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="fill_parent"
|
||||||
android:paddingStart="5dp"
|
android:paddingStart="5dp"
|
||||||
android:paddingEnd="5dp">
|
android:paddingEnd="5dp">
|
||||||
|
|
||||||
<ScrollView
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent">
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -18,14 +14,14 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@android:style/TextAppearance.Holo.Medium"
|
android:textAppearance="@android:style/TextAppearance.Medium"
|
||||||
android:text="@string/title_about_dialog"
|
android:text="@string/title_about_dialog"
|
||||||
android:id="@+id/title_section_app_description_text"/>
|
android:id="@+id/title_section_app_description_text"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@android:style/TextAppearance.Holo.Small"
|
android:textAppearance="@android:style/TextAppearance.Small"
|
||||||
android:text="@string/description_text"
|
android:text="@string/description_text"
|
||||||
android:id="@+id/about_app_description"/>
|
android:id="@+id/about_app_description"/>
|
||||||
|
|
||||||
|
@ -33,29 +29,28 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@android:style/TextAppearance.Holo.Medium"
|
android:textAppearance="@android:style/TextAppearance.Medium"
|
||||||
android:text="@string/action_version"
|
android:text="@string/action_version"
|
||||||
android:id="@+id/title_section_version"/>
|
android:id="@+id/title_section_version"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@android:style/TextAppearance.Holo.Small"
|
android:textAppearance="@android:style/TextAppearance.Small"
|
||||||
android:text="@string/version"
|
|
||||||
android:id="@+id/about_version_section"/>
|
android:id="@+id/about_version_section"/>
|
||||||
|
|
||||||
<!-- About How To -->
|
<!-- About How To -->
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@android:style/TextAppearance.Holo.Medium"
|
android:textAppearance="@android:style/TextAppearance.Medium"
|
||||||
android:text="@string/title_section_how_to_use"
|
android:text="@string/title_section_how_to_use"
|
||||||
android:id="@+id/title_section_how_to_use"/>
|
android:id="@+id/title_section_how_to_use"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@android:style/TextAppearance.Holo.Small"
|
android:textAppearance="@android:style/TextAppearance.Small"
|
||||||
android:text="@string/section_how_to_use"
|
android:text="@string/section_how_to_use"
|
||||||
android:id="@+id/section_how_to_use"/>
|
android:id="@+id/section_how_to_use"/>
|
||||||
|
|
||||||
|
@ -63,14 +58,14 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@android:style/TextAppearance.Holo.Medium"
|
android:textAppearance="@android:style/TextAppearance.Medium"
|
||||||
android:text="@string/title_section_developer"
|
android:text="@string/title_section_developer"
|
||||||
android:id="@+id/title_section_developer_text"/>
|
android:id="@+id/title_section_developer_text"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@android:style/TextAppearance.Holo.Small"
|
android:textAppearance="@android:style/TextAppearance.Small"
|
||||||
android:text="@string/section_developer"
|
android:text="@string/section_developer"
|
||||||
android:id="@+id/about_developer_section"/>
|
android:id="@+id/about_developer_section"/>
|
||||||
|
|
||||||
|
@ -78,18 +73,16 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@android:style/TextAppearance.Holo.Medium"
|
android:textAppearance="@android:style/TextAppearance.Medium"
|
||||||
android:text="@string/title_section_disclaimer"
|
android:text="@string/title_section_disclaimer"
|
||||||
android:id="@+id/title_section_disclaimer_text"/>
|
android:id="@+id/title_section_disclaimer_text"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@android:style/TextAppearance.Holo.Small"
|
android:textAppearance="@android:style/TextAppearance.Small"
|
||||||
android:text="@string/section_disclaimer"
|
android:text="@string/section_disclaimer"
|
||||||
android:id="@+id/about_disclaimer_section"/>
|
android:id="@+id/about_disclaimer_section"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="5dp"
|
||||||
|
android:paddingEnd="5dp">
|
||||||
|
<EditText
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/hint_configuration"
|
||||||
|
android:id="@+id/passphrase"/>
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,298 @@
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
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:orientation="horizontal"
|
||||||
|
android:id="@+id/first_row">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/Q"
|
||||||
|
android:text="Q: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/W"
|
||||||
|
android:text="W: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/E"
|
||||||
|
android:text="E: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/R"
|
||||||
|
android:text="R: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/T"
|
||||||
|
android:text="T: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_below="@id/first_row"
|
||||||
|
android:id="@+id/second_row">
|
||||||
|
|
||||||
|
<android.support.v4.widget.Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/Z"
|
||||||
|
android:text="Z: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/U"
|
||||||
|
android:text="U: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/I"
|
||||||
|
android:text="I: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/O"
|
||||||
|
android:text="O: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<android.support.v4.widget.Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_below="@id/second_row"
|
||||||
|
android:id="@+id/third_row">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/A"
|
||||||
|
android:text="A: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/S"
|
||||||
|
android:text="S: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/D"
|
||||||
|
android:text="D: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/F"
|
||||||
|
android:text="F: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/G"
|
||||||
|
android:text="G: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_below="@id/third_row"
|
||||||
|
android:id="@+id/fourth_row">
|
||||||
|
|
||||||
|
<android.support.v4.widget.Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/H"
|
||||||
|
android:text="H: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/J"
|
||||||
|
android:text="J: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/K"
|
||||||
|
android:text="K: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/P"
|
||||||
|
android:text="P: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<android.support.v4.widget.Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_below="@id/fourth_row"
|
||||||
|
android:id="@+id/fifth_row">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/Y"
|
||||||
|
android:text="Y: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/X"
|
||||||
|
android:text="X: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/C"
|
||||||
|
android:text="C: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/V"
|
||||||
|
android:text="V: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/B"
|
||||||
|
android:text="B: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="ButtonStyle,HardcodedText" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_below="@id/fifth_row"
|
||||||
|
android:id="@+id/sixth_row">
|
||||||
|
|
||||||
|
<android.support.v4.widget.Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/N"
|
||||||
|
android:text="N: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/M"
|
||||||
|
android:text="M: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:id="@+id/L"
|
||||||
|
android:text="L: "
|
||||||
|
android:background="@drawable/button_grey"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<android.support.v4.widget.Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
12
app/src/main/res/layout/dialog_ringsettings_i_m3.xml → app/src/main/res/layout/dialog_ringsettings_3.xml
Executable file → Normal file
|
@ -13,17 +13,17 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="33"
|
android:layout_weight="33"
|
||||||
android:text="@string/hint_rotor3"
|
android:id="@+id/dialog_text_rotor3"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="33"
|
android:layout_weight="33"
|
||||||
android:text="@string/hint_rotor2"
|
android:id="@+id/dialog_text_rotor2"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="33"
|
android:layout_weight="33"
|
||||||
android:text="@string/hint_rotor1"
|
android:id="@+id/dialog_text_rotor1"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -37,19 +37,19 @@
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight=".33"
|
android:layout_weight="33"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/rotor3ring">
|
android:id="@+id/rotor3ring">
|
||||||
</Spinner>
|
</Spinner>
|
||||||
<Spinner
|
<Spinner
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight=".33"
|
android:layout_weight="33"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/rotor2ring">
|
android:id="@+id/rotor2ring">
|
||||||
</Spinner>
|
</Spinner>
|
||||||
<Spinner
|
<Spinner
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight=".33"
|
android:layout_weight="33"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/rotor1ring">
|
android:id="@+id/rotor1ring">
|
||||||
</Spinner>
|
</Spinner>
|
35
app/src/main/res/layout/dialog_ringsettings_m4.xml → app/src/main/res/layout/dialog_ringsettings_4.xml
Executable file → Normal file
|
@ -8,60 +8,63 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/ringsettings_layout_hint">
|
android:id="@+id/ringstellung_layout_hint">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="25"
|
android:layout_weight="33"
|
||||||
android:text="@string/hint_thin_rotor"
|
android:id="@+id/dialog_text_rotor4"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="25"
|
android:layout_weight="33"
|
||||||
android:text="@string/hint_rotor3"
|
android:id="@+id/dialog_text_rotor3"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="25"
|
android:layout_weight="33"
|
||||||
android:text="@string/hint_rotor2"
|
android:id="@+id/dialog_text_rotor2"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="25"
|
android:layout_weight="33"
|
||||||
android:text="@string/hint_rotor1"
|
android:id="@+id/dialog_text_rotor1"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/ringsettings_layout_hint"
|
android:layout_below="@id/ringstellung_layout_hint"
|
||||||
android:id="@+id/ringsettings_layout">
|
android:id="@+id/ringstellung_layout">
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="25"
|
android:layout_weight="33"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/rotor4ring">
|
android:id="@+id/rotor4ring">
|
||||||
</Spinner>
|
</Spinner>
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="25"
|
android:layout_weight="33"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/rotor3ring">
|
android:id="@+id/rotor3ring">
|
||||||
</Spinner>
|
</Spinner>
|
||||||
<Spinner
|
<Spinner
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="25"
|
android:layout_weight="33"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/rotor2ring">
|
android:id="@+id/rotor2ring">
|
||||||
</Spinner>
|
</Spinner>
|
||||||
<Spinner
|
<Spinner
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="25"
|
android:layout_weight="33"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/rotor1ring">
|
android:id="@+id/rotor1ring">
|
||||||
</Spinner>
|
</Spinner>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/dialog_two_options_lay">
|
||||||
|
<Button
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/dialog_two_options_1"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/dialog_two_options_2"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,23 @@
|
||||||
|
<ScrollView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:paddingStart="5dp"
|
||||||
|
android:paddingEnd="5dp">
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Medium"
|
||||||
|
android:id="@+id/dialog_whats_new_header"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Small"
|
||||||
|
android:id="@+id/dialog_whats_new_details"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
|
@ -1,26 +1,55 @@
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:context=".MainActivity" >
|
tools:context=".MainActivity"
|
||||||
|
tools:ignore="UnusedAttribute">
|
||||||
|
|
||||||
<item android:id="@+id/action_reset"
|
<!-- RESET -->
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_reset"
|
||||||
android:orderInCategory="96"
|
android:orderInCategory="96"
|
||||||
android:showAsAction="ifRoom"
|
android:showAsAction="ifRoom"
|
||||||
android:title="@string/action_reset" />
|
android:title="@string/action_reset"/>
|
||||||
<item android:id="@+id/action_send"
|
<!-- SEND -->
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_send_message"
|
||||||
|
android:icon="@drawable/ic_send_white_48dp"
|
||||||
android:orderInCategory="97"
|
android:orderInCategory="97"
|
||||||
android:showAsAction="always"
|
android:showAsAction="always"
|
||||||
android:title="@string/action_send"
|
android:title="@string/action_send"/>
|
||||||
android:icon="@drawable/ic_send_white_48dp"/>
|
<!-- RINGSETTING -->
|
||||||
<item android:id="@+id/action_choose_ringstellung"
|
<item
|
||||||
android:title="@string/action_choose_ringsettings"
|
android:id="@+id/action_choose_ringsetting"
|
||||||
android:orderInCategory="98"
|
android:orderInCategory="98"
|
||||||
android:showAsAction="never" />
|
android:showAsAction="ifRoom"
|
||||||
<item android:id="@+id/action_settings"
|
android:title="@string/action_choose_ring_settings"/>
|
||||||
android:title="@string/action_settings"
|
<!-- SHARE CONFIGURATION -->
|
||||||
android:orderInCategory="99"
|
<item
|
||||||
android:showAsAction="never" />
|
android:id="@+id/action_share_configuration"
|
||||||
<item android:id="@+id/action_about"
|
android:orderInCategory="99"
|
||||||
android:title="@string/title_action_about"
|
android:showAsAction="ifRoom"
|
||||||
android:orderInCategory="100"
|
android:title="@string/action_share_configuration"/>
|
||||||
android:showAsAction="never" />
|
<!-- RESTORE CONFIGURATION FROM QR OR ENTER SEED-->
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_restore_configuration"
|
||||||
|
android:orderInCategory="100"
|
||||||
|
android:showAsAction="ifRoom"
|
||||||
|
android:title="@string/action_restore_configuration"/>
|
||||||
|
<!-- RANDOM -->
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_random_configuration"
|
||||||
|
android:orderInCategory="101"
|
||||||
|
android:showAsAction="ifRoom"
|
||||||
|
android:title="@string/action_random"/>
|
||||||
|
<!-- SETTINGS -->
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_settings"
|
||||||
|
android:orderInCategory="102"
|
||||||
|
android:showAsAction="ifRoom"
|
||||||
|
android:title="@string/action_settings"/>
|
||||||
|
<!-- ABOUT -->
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_about"
|
||||||
|
android:orderInCategory="103"
|
||||||
|
android:showAsAction="ifRoom"
|
||||||
|
android:title="@string/title_action_about"/>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Converts the Inkscape icon file ic_launcher_web.svg to the launcher web & app png files.
|
||||||
|
|
||||||
|
PROJECT="/home/vanitas/Programmierung/androidstudio/EnigmAndroid/app"
|
||||||
|
MAIN="${PROJECT}/src/main/"
|
||||||
|
RES="${MAIN}res/"
|
||||||
|
DRAWABLE="${RES}drawable"
|
||||||
|
INPUT="${RES}icon.svg"
|
||||||
|
|
||||||
|
inkscape --shell <<COMMANDS
|
||||||
|
--export-png "${RES}ic_launcher-web.png" -w 512 "${INPUT}"
|
||||||
|
--export-png "${DRAWABLE}-mdpi/ic_launcher.png" -w 48 "${INPUT}"
|
||||||
|
--export-png "${DRAWABLE}-hdpi/ic_launcher.png" -w 72 "${INPUT}"
|
||||||
|
--export-png "${DRAWABLE}-xhdpi/ic_launcher.png" -w 96 "${INPUT}"
|
||||||
|
--export-png "${DRAWABLE}-xxhdpi/ic_launcher.png" -w 144 "${INPUT}"
|
||||||
|
--export-png "${DRAWABLE}-xxxhdpi/ic_launcher.png" -w 192 "${INPUT}"
|
||||||
|
quit
|
||||||
|
COMMANDS
|
|
@ -8,7 +8,8 @@
|
||||||
<string name="description_text">EnigmAndroid ist die Implementation einer Simulation der Enigma Maschine.
|
<string name="description_text">EnigmAndroid ist die Implementation einer Simulation der Enigma Maschine.
|
||||||
Die Enigma Maschine ist eine in den 1920er Jahren entwickelte Verschlüsselungsmaschine,
|
Die Enigma Maschine ist eine in den 1920er Jahren entwickelte Verschlüsselungsmaschine,
|
||||||
die unter anderem im zweiten Weltkrieg von der deutschen Wehrmacht eingesetzt wurde,
|
die unter anderem im zweiten Weltkrieg von der deutschen Wehrmacht eingesetzt wurde,
|
||||||
um geheime Nachrichten zu verschlüsseln. Dabei wird jeder einzelne Buchstabe elektronisch
|
um geheime Nachrichten zu verschlüsseln. Es gab mehrere verschiedene Enigmamodelle.
|
||||||
|
Zur Verschlüsselung wird jeder einzelne Buchstabe elektronisch
|
||||||
durch eine Reihe von rotierbaren Walzen geleitet, sodass nach jedem Buchstaben ein anderes
|
durch eine Reihe von rotierbaren Walzen geleitet, sodass nach jedem Buchstaben ein anderes
|
||||||
Verschlüsselungsalphabet genutzt wird (Polyalphabetische Substitution).
|
Verschlüsselungsalphabet genutzt wird (Polyalphabetische Substitution).
|
||||||
Die Walzen konnte man aus einem Set von 5 Walzen wählen. Zusätzlich gab es ein Steckbrett, an dem
|
Die Walzen konnte man aus einem Set von 5 Walzen wählen. Zusätzlich gab es ein Steckbrett, an dem
|
||||||
|
@ -16,12 +17,18 @@
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
<string name="title_section_how_to_use">Bedienungsanleitung</string>
|
<string name="title_section_how_to_use">Bedienungsanleitung</string>
|
||||||
<string name="section_how_to_use">Um einen Text mit EnigmAndroid zu ver- oder entschlüsseln, tippen Sie den Klar- oder Geheimtext in das Feld \"Hier tippen\".
|
<string name="section_how_to_use">Um einen Text mit EnigmAndroid zu ver- oder entschlüsseln, wählen Sie zunächst das entsprechende Maschinenmodell aus.
|
||||||
Wählen Sie anschließend eine Umkehrwalze, sowie Walzen für die Plätze 1 bis 3 aus. Legen Sie außerdem die Startpositionen der Walzen fest.
|
Sie finden eine Liste, aus der Sie wählen können in den Einstellungen. Tippen Sie dann den Klar- oder Geheimtext in das Feld \"Hier tippen\".
|
||||||
Zuletzt können Sie noch einige Steckerpaare auf dem Steckbrett festlegen. Tippen Sie dazu die gewünschten Paare mit Komma getrennt in das entsprechende Textfeld (zb. \"ab,cd\").
|
Wählen Sie anschließend je nach gewähltem Modell eine Umkehrwalze, sowie weitere Walzen aus. Legen Sie außerdem die Startpositionen der Walzen fest.
|
||||||
Beachten Sie, dass Sie einen Stecker nicht doppelt nutzen dürfen.
|
Zuletzt können Sie ggf. noch einige Steckerpaare auf dem Steckbrett festlegen, oder die Verkabelung der Umkehrwalze ändern. Tippen Sie dazu den
|
||||||
Optional können Sie auch noch die Ringstellung definieren. Öffnen Sie dazu das Optionsmenü und wählen Sie den Punkt \"Ringstellung\".
|
jeweiligen Button an und verbinden Sie die gewünschten Steckerpaare, indem Sie im sich öffnenden Dialog nacheinander jeweils zwei
|
||||||
Haben Sie alle Einstellungen getätigt klicken Sie auf den Button \"Ver-Entschlüsseln\".</string>
|
Stecker berühren. Falls sie eine Verbindung trennen möchten, klicken Sie einen der betroffenen Stecker doppelt an.
|
||||||
|
Optional können Sie außerdem auch noch die Ringstellung definieren. Öffnen Sie dazu das Optionsmenü und wählen Sie den Punkt \"Ringstellung\".
|
||||||
|
Haben Sie alle Einstellungen getätigt klicken Sie auf den Button \"Ver-Entschlüsseln\".
|
||||||
|
Um die gewählte Konfiguration der Enigma Maschine per QR-Code zu teilen, wählen Sie den Eintrag \"Teile Konfiguration per QR-Code\" aus dem Optionsmenü.
|
||||||
|
Um eine per QR-Code geteilte Konfiguration zu scannen, wählen Sie stattdessen den Eintrag \"Lese Konfiguration aus QR-Code\".
|
||||||
|
Außerdem können Sie eine Konfiguration aus einem Schlüsselwort generieren, oder wiederherstellen, indem Sie dein Eintrag \"Konfiguration aus Schlüsselwort\"
|
||||||
|
wählen und im erscheinenden Dialog entweder ein beliebiges Wort oder den Inhalt eines QR-Codes (\"EnigmAndroid/…\" eingeben.</string>
|
||||||
|
|
||||||
<string name="title_section_developer">Entwickler</string>
|
<string name="title_section_developer">Entwickler</string>
|
||||||
<string name="section_developer">EnigmAndroid wird entwickelt von: \nPaul Schaub</string>
|
<string name="section_developer">EnigmAndroid wird entwickelt von: \nPaul Schaub</string>
|
||||||
|
|
|
@ -4,14 +4,15 @@
|
||||||
<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">Zurücksetzen</string>
|
<string name="action_reset">Zurücksetzen</string>
|
||||||
|
<string name="action_random">Zufällige Konfiguration</string>
|
||||||
|
<string name="action_restore_configuration">Konfiguration wiederherstellen</string>
|
||||||
|
<string name="action_share_configuration">Konfiguration teilen</string>
|
||||||
<string name="action_settings">Einstellungen</string>
|
<string name="action_settings">Einstellungen</string>
|
||||||
<string name="action_choose_ringsettings">Ringstellung</string>
|
<string name="action_choose_ring_settings">Ringstellung</string>
|
||||||
<string name="action_send">Senden</string>
|
<string name="action_send">Senden</string>
|
||||||
<string name="send_to">Senden an…</string>
|
<string name="send_to">Senden an…</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_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>
|
||||||
|
@ -20,17 +21,34 @@
|
||||||
<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_reflector_position">Position\nUmkehr-\nWalze</string>
|
||||||
<string name="hint_thin_rotor_position">Position\nWalze 4</string>
|
<string name="hint_thin_rotor_position">Position\nWalze 4</string>
|
||||||
|
<string name="hint_enigma_reflector_wiring">Verkabelung Umkehrwalze</string>
|
||||||
|
<string name="hint_configuration">Schlüsselwort/Konfiguration</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_unable_to_plug_a_b">Kann Stecker nicht setzen: </string>
|
|
||||||
<string name="error_plug_already_in_use">Fehler: Einer oder mehrere dieser Stecker sind bereits in Benutzung: </string>
|
|
||||||
<string name="error_no_text_to_send">Nachricht ist leer.</string>
|
<string name="error_no_text_to_send">Nachricht ist leer.</string>
|
||||||
<string name="title_ringsetting">Ringstellungen</string>
|
<string name="error_no_valid_qr">Fehler: Kein korrekter EnigmAndroid QR-Code!</string>
|
||||||
<string name="dialog_positiv">OK</string>
|
<string name="title_ring_setting">Ringstellungen</string>
|
||||||
<string name="dialog_negativ">Abbrechen</string>
|
|
||||||
<string name="dialog_ringsettings_success">Setze Ringe auf</string>
|
<string name="title_plugboard_dialog">Steckbrett-\nVerbindungen</string>
|
||||||
<string name="dialog_ringsettings_abort">Keine Änderungen</string>
|
<string name="title_reflector_dialog">Verkabelung Umkehrwalze</string>
|
||||||
<string name="message_reset">Enigma zurückgesetzt</string>
|
|
||||||
|
<string name="dialog_positive">OK</string>
|
||||||
|
<string name="dialog_negative">Abbrechen</string>
|
||||||
|
<string name="dialog_title_restore_configuration">Konfiguration wiederherstellen…</string>
|
||||||
|
<string name="dialog_restore_code">…aus Text/Schlüsselwort</string>
|
||||||
|
<string name="dialog_restore_qr">…aus QR-code</string>
|
||||||
|
<string name="dialog_title_share_configuration">Konfiguration teilen…</string>
|
||||||
|
<string name="dialog_share_qr">…per QR-code</string>
|
||||||
|
<string name="dialog_share_code">…als kodierten Text</string>
|
||||||
|
<string name="dialog_ring_settings_success">Setze Ringe auf %1$s.</string>
|
||||||
|
<string name="dialog_reflector_set">Umkehrwalze verkabelt.</string>
|
||||||
|
<string name="dialog_plugboard_set">Steckbrettverbindungen gesetzt.</string>
|
||||||
|
<string name="dialog_passphrase_set">Konfiguration aus Schlüsselwort %1$s generiert.</string>
|
||||||
|
<string name="dialog_passphrase_was_coded_state">Konfiguration aus Kodierung wiederhergestellt.</string>
|
||||||
|
<string name="dialog_abort">Keine Änderungen.</string>
|
||||||
|
<string name="message_reset">Enigma zurückgesetzt.</string>
|
||||||
|
<string name="message_random">Enigma auf zufällige Konfiguration gesetzt.</string>
|
||||||
|
<string name="message_clipboard">In Zwischenablage kopiert</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|