From 193803e06c01a52f73c0af1f93231198ae9cd666 Mon Sep 17 00:00:00 2001 From: Thomas Schaller Date: Sun, 29 Dec 2024 12:35:52 +0100 Subject: [PATCH] =?UTF-8?q?Subtrees=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Software/iud_key_angriffe_vigenere/.gitignore | 5 + .../balkendiagramm.java | 76 + .../baustein.java | 42 + .../breakvigenere.jar | Bin 0 -> 19609 bytes .../breakvigenere.java | 365 ++++ .../breakvigenere.jfm | 577 ++++++ .../ch/aplu/turtle/linerenderer.java | 210 +++ .../ch/aplu/turtle/pen.java | 268 +++ .../ch/aplu/turtle/playground.java | 789 ++++++++ .../ch/aplu/turtle/res/bong.wav | Bin 0 -> 9624 bytes .../ch/aplu/turtle/sharedconstants.java | 84 + .../ch/aplu/turtle/streamingplayer.java | 84 + .../ch/aplu/turtle/tprintable.java | 43 + .../ch/aplu/turtle/turtle.java | 1585 +++++++++++++++++ .../ch/aplu/turtle/turtlefactory.java | 66 + .../ch/aplu/turtle/turtlerenderer.java | 312 ++++ .../angriffvigenere_autokorrelation/eval.java | 50 + .../inout.java | 98 + .../je/util/turtle.java | 311 ++++ .../jeclasses.jar | Bin 0 -> 90273 bytes .../jeclasses/ch/aplu/package.bluej | 0 .../ch/aplu/turtle/linerenderer.java | 210 +++ .../jeclasses/ch/aplu/turtle/package.bluej | 0 .../jeclasses/ch/aplu/turtle/pen.java | 268 +++ .../jeclasses/ch/aplu/turtle/playground.java | 789 ++++++++ .../jeclasses/ch/aplu/turtle/res/bong.wav | Bin 0 -> 9624 bytes .../ch/aplu/turtle/sharedconstants.java | 84 + .../ch/aplu/turtle/streamingplayer.java | 84 + .../jeclasses/ch/aplu/turtle/tprintable.java | 43 + .../jeclasses/ch/aplu/turtle/turtle.java | 1585 +++++++++++++++++ .../ch/aplu/turtle/turtlefactory.java | 66 + .../ch/aplu/turtle/turtlerenderer.java | 312 ++++ .../jeclasses/ch/package.bluej | 26 + .../jeclasses/eval.java | 50 + .../jeclasses/inout.java | 98 + .../jeclasses/je/package.bluej | 26 + .../jeclasses/je/util/package.bluej | 27 + .../jeclasses/je/util/turtle.java | 311 ++++ .../jeclasses/jnumberfield.java | 129 ++ .../jeclasses/numberfield.java | 128 ++ .../jeclasses/package.bluej | 79 + .../jnumberfield.java | 129 ++ .../meta-inf/manifest.mf | 5 + .../numberfield.java | 128 ++ .../balkendiagramm.java | 76 + .../angriffvigenere_kasiskitest/baustein.java | 42 + .../breakvigenere.jar | Bin 0 -> 33268 bytes .../breakvigenere.java | 498 ++++++ .../breakvigenere.jfm | 578 ++++++ .../ch/aplu/turtle/linerenderer.java | 210 +++ .../ch/aplu/turtle/pen.java | 268 +++ .../ch/aplu/turtle/playground.java | 789 ++++++++ .../ch/aplu/turtle/res/bong.wav | Bin 0 -> 9624 bytes .../ch/aplu/turtle/sharedconstants.java | 84 + .../ch/aplu/turtle/streamingplayer.java | 84 + .../ch/aplu/turtle/tprintable.java | 43 + .../ch/aplu/turtle/turtle.java | 1585 +++++++++++++++++ .../ch/aplu/turtle/turtlefactory.java | 66 + .../ch/aplu/turtle/turtlerenderer.java | 312 ++++ .../angriffvigenere_kasiskitest/eval.java | 50 + .../angriffvigenere_kasiskitest/inout.java | 98 + .../je/util/turtle.java | 311 ++++ .../angriffvigenere_kasiskitest/jeclasses.jar | Bin 0 -> 90273 bytes .../jnumberfield.java | 129 ++ .../meta-inf/manifest.mf | 5 + .../numberfield.java | 128 ++ .../balkendiagramm.java | 85 + .../baustein.java | 42 + .../breakvigenere.jar | Bin 0 -> 32284 bytes .../breakvigenere.java | 360 ++++ .../breakvigenere.jfm | 577 ++++++ .../ch/aplu/turtle/linerenderer.java | 210 +++ .../ch/aplu/turtle/pen.java | 268 +++ .../ch/aplu/turtle/playground.java | 789 ++++++++ .../ch/aplu/turtle/res/bong.wav | Bin 0 -> 9624 bytes .../ch/aplu/turtle/sharedconstants.java | 84 + .../ch/aplu/turtle/streamingplayer.java | 84 + .../ch/aplu/turtle/tprintable.java | 43 + .../ch/aplu/turtle/turtle.java | 1585 +++++++++++++++++ .../ch/aplu/turtle/turtlefactory.java | 66 + .../ch/aplu/turtle/turtlerenderer.java | 312 ++++ .../eval.java | 50 + .../inout.java | 98 + .../je/util/turtle.java | 311 ++++ .../jeclasses.jar | Bin 0 -> 90273 bytes .../jnumberfield.java | 129 ++ .../meta-inf/manifest.mf | 5 + .../numberfield.java | 128 ++ .../iud_key_angriffe_vigenere/readme.adoc | 12 + 89 files changed, 20136 insertions(+) create mode 100644 Software/iud_key_angriffe_vigenere/.gitignore create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/balkendiagramm.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/baustein.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/breakvigenere.jar create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/breakvigenere.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/breakvigenere.jfm create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/linerenderer.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/pen.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/playground.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/res/bong.wav create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/sharedconstants.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/streamingplayer.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/tprintable.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/turtle.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/turtlefactory.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/turtlerenderer.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/eval.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/inout.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/je/util/turtle.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses.jar create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/package.bluej create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/linerenderer.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/package.bluej create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/pen.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/playground.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/res/bong.wav create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/sharedconstants.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/streamingplayer.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/tprintable.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/turtle.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/turtlefactory.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/turtlerenderer.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/package.bluej create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/eval.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/inout.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/je/package.bluej create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/je/util/package.bluej create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/je/util/turtle.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/jnumberfield.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/numberfield.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/package.bluej create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jnumberfield.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/meta-inf/manifest.mf create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/numberfield.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/balkendiagramm.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/baustein.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/breakvigenere.jar create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/breakvigenere.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/breakvigenere.jfm create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/linerenderer.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/pen.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/playground.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/res/bong.wav create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/sharedconstants.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/streamingplayer.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/tprintable.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/turtle.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/turtlefactory.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/turtlerenderer.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/eval.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/inout.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/je/util/turtle.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/jeclasses.jar create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/jnumberfield.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/meta-inf/manifest.mf create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/numberfield.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/balkendiagramm.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/baustein.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/breakvigenere.jar create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/breakvigenere.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/breakvigenere.jfm create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/linerenderer.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/pen.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/playground.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/res/bong.wav create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/sharedconstants.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/streamingplayer.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/tprintable.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/turtle.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/turtlefactory.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/turtlerenderer.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/eval.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/inout.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/je/util/turtle.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/jeclasses.jar create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/jnumberfield.java create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/meta-inf/manifest.mf create mode 100644 Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/numberfield.java create mode 100644 Software/iud_key_angriffe_vigenere/readme.adoc diff --git a/Software/iud_key_angriffe_vigenere/.gitignore b/Software/iud_key_angriffe_vigenere/.gitignore new file mode 100644 index 0000000..c1f4551 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/.gitignore @@ -0,0 +1,5 @@ +*.class +*.ctxt +*.sh +repo.adoc +*.~lock diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/balkendiagramm.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/balkendiagramm.java new file mode 100644 index 0000000..d64c99b --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/balkendiagramm.java @@ -0,0 +1,76 @@ +import java.awt.*; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; +import javax.swing.*; + +public class Balkendiagramm extends JPanel { + + private double gesamt; + private double haeufigkeit[]; + private double maxwert; + private int verschiebung = 0; + private double haeufigkeit_de[] = { 0.0651, 0.0189, 0.0306, 0.0508, 0.174, 0.0166, 0.0301, 0.0476,0.0755, 0.0027, 0.0121,0.0344,0.0252,0.0978,0.0251,0.0079,0.0002,0.07,0.0727,0.0615,0.0435,0.067,0.0189,0.0003,0.0004,0.0113}; + + + public void setHaeufigkeit(double haeufigkeit[]) { + + this.haeufigkeit = haeufigkeit; + gesamt = 0; + for (int i = 0; i < 26; i++) { + gesamt += haeufigkeit[i]; + } + for (int i = 0; i < 26; i++) { + haeufigkeit[i] /= gesamt; + } + maxwert = 0.20; + + } + + public void setVerschiebung(int verschiebung) { + if (verschiebung >= 0 && verschiebung < 26) { + this.verschiebung = verschiebung; + + } else { + this.verschiebung = 0; + } // end of if-else + } + + public void paintComponent(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + super.paintComponent(g2); + Dimension d = getSize(null); + //Skalieren auf 100x100 mit y-Invertierung + g2.scale(d.getWidth() / 120.0, -d.getHeight() / 100.0); + // Ursprung verschieben nach (15,-90) + g2.translate(5, -90); + // Linien etwas breiter + g2.setStroke(new BasicStroke(1.5f)); + // x-Achse zeichnen + g2.draw(new Line2D.Double(0, 0, 104, 0)); + // Linien etwas dünner + g2.setStroke(new BasicStroke(0.5f)); + // Deutsche Häufigkeit grau + g2.setColor(Color.darkGray); + // Säulen zeichnen + for (int i = 0; i < 26; i++) { + g2.fill(new Rectangle2D.Double(4 * i+1, 0, 2, haeufigkeit_de[i] / maxwert *100)); + } + // Texthäufigkeit blau + g2.setColor(Color.blue); + // Säulen zeichnen + for (int i = 0; i < 26; i++) { + g2.fill(new Rectangle2D.Double(4 * i, 0, 2, haeufigkeit[(i+verschiebung)%26] / maxwert *100)); + } + // y-Invertierung rückgängig machen + g2.scale(1, -1); + // Beschriftung x-Achse + String xAchse = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + // Fontgröße für Beschriftung ändern + g2.setColor(Color.black); + g2.setFont(g2.getFont().deriveFont(5f)); + for (int i = 0; i < 26; i++) { + g2.drawString(xAchse.substring(i, i + 1), + i * 4, +6); + } + } + } diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/baustein.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/baustein.java new file mode 100644 index 0000000..55954a1 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/baustein.java @@ -0,0 +1,42 @@ +public class Baustein implements Comparable{ + + // Anfang Attribute + private String zeichen; + private int anzahl; + // Ende Attribute + + public Baustein(String zeichen) { + super(); + anzahl = 1; + this.zeichen = zeichen; + } + // Anfang Methoden + + + + public int compareTo(Baustein c) { + + int anz = c.getAnzahl(); + + //ascending order + return anz - this.anzahl; + + //descending order + //return compareQuantity - this.quantity; + + } + public String getZeichen() { + return zeichen; + } + + public int getAnzahl() { + return anzahl; + } + + public void incAnzahl() { + anzahl++; + } + + + // Ende Methoden +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/breakvigenere.jar b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/breakvigenere.jar new file mode 100644 index 0000000000000000000000000000000000000000..c7a2055f111c9a3750b895bce138e3aeb991790b GIT binary patch literal 19609 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 K(&>sjhz9^Uct|V& literal 0 HcmV?d00001 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/breakvigenere.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/breakvigenere.java new file mode 100644 index 0000000..98de0ff --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/breakvigenere.java @@ -0,0 +1,365 @@ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.table.*; +import java.util.ArrayList; +import java.util.Collections; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Highlighter; +import javax.swing.text.Highlighter.HighlightPainter; +import javax.swing.text.BadLocationException; + + +/** + * + * Programm zur Kryptoanalyse + * von monoalphabetischen Substitutionen + * + * @version 1.0 from 23.11.2016 + * @author Thomas Schaller + */ + +public class BreakVigenere extends JFrame { + // Anfang Attribute + private JTextField[] buchstabe; + + private JButton jButton1 = new JButton(); + private JButton jBBuchstabe = new JButton(); + private Balkendiagramm bdText = new Balkendiagramm(); + + private JTextArea jTAKrypto = new JTextArea(""); + private JScrollPane jTAKryptoScrollPane = new JScrollPane(jTAKrypto); + private JTextArea jTAKlartext = new JTextArea(""); + private JScrollPane jTAKlartextScrollPane = new JScrollPane(jTAKlartext); + private JLabel jLKryptotext = new JLabel(); + private JLabel jLKlartext = new JLabel(); + private JLabel jLCopyright = new JLabel(); + private JTextArea jTAKorrelation = new JTextArea(""); + private JScrollPane jTAKorrelationScrollPane = new JScrollPane(jTAKorrelation); + private JSpinner jSpVerschiebung = new JSpinner(); + private SpinnerNumberModel jSpVerschiebungModel = new SpinnerNumberModel(0, 0, 99, 1); + private JNumberField jNFAnzahlTreffer = new JNumberField(); + private JLabel lVerschiebung = new JLabel(); + private JLabel lAnzahlgleicherBuchstaben = new JLabel(); + // Ende Attribute + + public BreakVigenere (String title) { + super (title); + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + int frameWidth = 707; + int frameHeight = 649; + setSize(frameWidth, frameHeight); + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + int x = (d.width - getSize().width) / 2; + int y = (d.height - getSize().height) / 2; + setLocation(x, y); + Container cp = getContentPane(); + cp.setLayout(null); + // Anfang Komponenten + + jTAKryptoScrollPane.setBounds(16, 24, 665, 105); + jTAKrypto.setLineWrap(true); + jTAKrypto.setFont(new Font("Courier New", Font.BOLD, 16)); + jTAKrypto.setText("JMLQMFNSKIOQNXGYZOQEBJLUKXHFCXGVLGBMREAJZCAEKVIFOWJLMFGJLPQZJIYHQQHYJLAFGFLRLQYESTPMHIAWQZFIPPMZMIZGPDOIIIVGTHIIQVKHLVHQOPLNMIKMSWCYKMUIVBREADEQOXLVVMILSMVWYZLVAONSIIVIKVKIVPOIZIEGXHLHCDILKIVPKYAWKTKRIIVQJMRXQZKVHFBVULHRVQYXYMBTKQPYAUSNHLZUSJUJBQTFHRLEKMUIAUTPHXMUTMZGPQXWWVIONINIAONVPIJQTIUWMONWIRLUMIUAMDQIZTWXEKYEXTOELPQNXMZIFEKGOWJONIYDCDVSSCODGTOMMMTKLKMNKRPRLQSRHGPEKMUIUFUHLZMDLJLRBXOGOXMZHYJLAONPBKMDBSYRIONNLHMYKMUDMXTIUOTMXXLBBNAGOWBMHIUDCYTGOWBQTESTPMHIAMVEKMUIZFGFBPINKVGYOQNIUYVPYSHPTQBIYJONGVLRIXVLHFMFKEBWHGTYADMZJETMBQXJHRLQXHPIXDUKYIAEOZLTWXEESTPMHIAMAONIJLQRLVPIZGTKHFMDKWDEZZUGOIQZLIZXMEBIYJITXIUSPZKWJLTEYISHQQYIYACDJIPQRMNVCSUUZESMMZOWJLMZQVFTBARSNIVSOSCEVNGXAMAFGFLPTMYSJEQZLSYQMUTIZZWYBIYWKTRWZPMDLVLMHGCLSIVPKRRIVZCSYXAAJIYIQZKWRIVZYEADMEBSYKMEILSEOQTKLVVQARKOZKVXVKZMVLPWKTYGOAIONHHPMUILADCQXVHXMZCYYHMZJETETEREAIQZOWJLMEORUWXDILLFMZAXGXEUKFLMABOISWEQOWLZQDZZAMWYTMHTIDKRAETXKWNIPAXGOXLQXXJLBUMOLMBPOIIYKTYXHFMZJIZOMZTWHXHQYFLWBUSQLRLUKVLMPQTJVPOQORKIZPOICIZEILPILQTIUETBNEIIBQGYZHMDZEIYTMGYZKMINPAA\nMDJIUQAEKRZMVPGPSIDQXFYECONXHPAAKMUQIXHIUYBLZAVVLQTLPIZZGGOOTMXXLBBNAGOWBMHIUWWNKKPRVFSEUAQQJIYZWZBSYRMENEUHMXZWPGPEUQPXCYKMUIXQXMVHQEILLTWXEESTPMHIAMAONIZYJEZMAYBUURTMBUSFLMABOISIQZKVWIZUUHLZWZCLYIVPZVPXPQSMBWAUILHYNHKVZGPAHIUIAFGRKEZPGPWLINKXLFMEILYRSFKESWWPOINIEANRAIIXVLHFMFOWJLMDKMOIVRUPNILQXFBGPEZEIIVHKVDIVPKXLFMXREZSJQXIPXAHKVDVNQRXLETBNEIIBQJMLIZMRPLVLUTKZMVHUPBXWDOWJLETRXLFMUJIUQWZUESTPMHIAMAONIUWCNYXPXCFOSUWUQZLVHMZCEYHQQYWJLWZYIPXTMTKLQJXOGOKZGTHZXHXOGOLIFZIKMMEHIYIQFYMTNITXESWWXGRNIDAXXYMBTKQPYAGTHIITXGWVHMDOXHPQQTMZGPQMISIPDZISIWZHEAXQEZEHPJQXXPIUBLSOPMZKVZGPXAKCSZPOIHPXTGFLXMZGGONMIKMSWLDKMVHMDBMLVEDZIYRHGCIJLAQRRHPAYKGOEVUYGOIATOPMWUUZXLPPMZXLIZTOIYDCPOIUEKTOLTFMZGRUXMMRFLVBUYGOIQNKIYJCZJIUIQZKGOMNRXMLVAONIPFMNKWAIPQTHGYUQOWAECEFALMZGTHLRUQZESPAONIPFMZJMLECRKMUIZSKQLMVEGQLRIONWLWQFFIUYVPYSCIZNARKIVEORKHIEYWPGPPOIRPMUTIYIIGLHLVODKVLRLDKLLRSMTRUEPQFYLMVVGLYLCZJIYXABZIYMUVGLYZMDGPSKMYKMUIZFKHLVVQGTVPQFGRPWKTKKLPMTXXLKQABEURQNGXAMAFGHLPTMVSYXIMRFLVBUYZLVEDLISXMMRTOEJQZIBRLNKPSEAAYOLRVIUVAYVPYGOYNPOI\nWSTKGPWLINKXPWKTKGOMNRXMLVCZMQPXDQXAYJMXZITETBNEIIBGTHZGPXYWLPPUKVGYEGXHLETNKVAMAEILLMJQHIUYBLZHPIVMILQILQSFBGPEZEIIVLAHYIPQTAHVQYPEOVODOJMHMDLVHRHAYIIPIUYIKIDUMIUVMBUVAEAUJILECRARKWKTRYNZWDYXHXBPKVHPJQXXPWKTKMIILUKXHFCXGVLGBMJIZXZUZLLQQGYDBZMDCIUHMZJEIIQMHIYEVPKVZETEOQVVQSORHPDQXAYJMXZIHPXTGFLXMQORGYBDGKLRLUKWLVSDETASODGTOMAONWAEZWKZVVAONPHKDUMIUVMEMIYMMFORKIVRUPNIVPKRQEPDNYUHMDZIUMVHKVNIAEKROIQFARKHQQAVZTZZMPPGPHURAVQFNITMCEBSYKMEILSEOQTITIBTUHLACDJIBRBQXHLQVMSIUZQSKRYIKTOJMVMNKOHRVF"); + jTAKrypto.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent evt) { + jTAKrypto_KeyTyped(evt); + } + }); + cp.add(jTAKryptoScrollPane); + + jTAKlartextScrollPane.setBounds(16, 480, 665, 105); + jTAKlartext.setLineWrap(true); + jTAKlartext.setFont(new Font("Courier New", Font.BOLD, 16)); + cp.add(jTAKlartextScrollPane); + jLKryptotext.setText("Kryptotext"); + jLKryptotext.setBounds(16, 3, 110, 20); + cp.add(jLKryptotext); + jLKlartext.setText("Klartext"); + jLKlartext.setBounds(16, 456, 110, 20); + cp.add(jLKlartext); + jLCopyright.setText("(cc) Schaller (ZPG Informatik) - V1.0 (2017)"); + jLCopyright.setBounds(128, 584, 419, 33); + jLCopyright.setHorizontalAlignment(SwingConstants.CENTER); + jLCopyright.setFont(new Font("Dialog", Font.PLAIN, 12)); + cp.add(jLCopyright); + + // -------------------------------- Tab 1 --------------------------------------------- + JPanel tab1 = new JPanel(); + tab1.setLayout(null); + + jTAKorrelationScrollPane.setBounds(16, 144, 665, 57); + jTAKorrelationScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + jTAKorrelation.setText(""); + jTAKorrelation.setEditable(false); + jTAKorrelation.setEnabled(true); + jTAKorrelation.setFont(new Font("Courier New", Font.BOLD, 16)); + tab1.add(jTAKorrelationScrollPane); + jSpVerschiebung.setBounds(192, 110, 41, 25); + jSpVerschiebung.setValue(1); + jSpVerschiebung.setModel(jSpVerschiebungModel); + jSpVerschiebung.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent evt) { + jSpVerschiebung_StateChanged(evt); + } + }); + tab1.add(jSpVerschiebung); + + jNFAnzahlTreffer.setBounds(192, 140, 41, 25); + jNFAnzahlTreffer.setText(""); + jNFAnzahlTreffer.setEditable(false); + tab1.add(jNFAnzahlTreffer); + lVerschiebung.setBounds(16, 10, 310, 20); + lVerschiebung.setText("Angriff auf die Schlüssellänge mit Autokorrelation"); + tab1.add(lVerschiebung); + JLabel l = new JLabel(); + l.setBounds(14, 165, 640, 40); + l.setText("Suche nach der Verschiebung, bei der möglichst viele Buchstaben übereinstimmen.
Das ist vermutlich die Schlüssellänge."); + tab1.add(l); + l = new JLabel(); + l.setBounds(16, 112, 162, 20); + l.setText("Verschiebung"); + tab1.add(l); + lAnzahlgleicherBuchstaben.setBounds(16, 142, 162, 20); + lAnzahlgleicherBuchstaben.setText("Anzahl gleicher Buchstaben"); + tab1.add(lAnzahlgleicherBuchstaben); + + // ---------------------------------- Tab 2 ------------------------------- + JPanel tab2 = new JPanel(); + tab2.setLayout(null); + + l = new JLabel(); + l.setBounds(16, 10, 310, 20); + l.setText("Angriff auf die Teiltexte mit Häufigkeitsanalyse"); + tab2.add(l); + + l = new JLabel(); + l.setBounds(380, 10, 300, 25); + l.setText("Buchstabenhäufigkeit Deutsch"); + tab2.add(l); + + l = new JLabel(); + l.setBounds(16, 40, 300, 25); + l.setText("Schlüssel"); + tab2.add(l); + + l = new JLabel(); + l.setBounds(16, 100, 300, 100); + l.setText("Versuche den Schlüssel zu knacken, indem du in jedem Teiltext die Häufigkeitsverteilung der Buchstaben mit der üblichen Häufigkeitsverteilung in deutschen Texten in Einklang bringst."); + tab2.add(l); + + double[] h = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + bdText.setBounds(380,40,300,180); + bdText.setHaeufigkeit(h); + tab2.add(bdText); + + jButton1.setBounds(16, 210, 193, 25); + jButton1.setText("Entschlüsselung versuchen"); + jButton1.setMargin(new Insets(2, 2, 2, 2)); + jButton1.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + jButton1_ActionPerformed(evt); + } + }); + tab2.add(jButton1); + + + + // Ende Komponenten + buchstabe = new JTextField[26]; + for (int i = 0; i<26 ;i++ ) { + buchstabe[i] = new JTextField(); + buchstabe[i].setBounds(16+i*25, 65, 25, 25); + buchstabe[i].setText("A"); + buchstabe[i].setHorizontalAlignment(SwingConstants.CENTER); + buchstabe[i].setVisible(false); + buchstabe[i].addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent evt) { + highlightKryptotext(evt); + } + }); + buchstabe[i].addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + e.consume(); + } + + public void keyTyped(KeyEvent e) { + e.consume(); + } + + public void keyPressed(KeyEvent e) { + JTextField textField = (JTextField) e.getSource(); + String text = textField.getText(); + if ((e.getKeyChar()>='a' && e.getKeyChar()<='z') ||(e.getKeyChar()>='A' && e.getKeyChar()<='Z')) { + text = ""+e.getKeyChar(); + } + if (e.getKeyChar()==' ' || e.getKeyChar() == KeyEvent.VK_BACK_SPACE || e.getKeyChar() == KeyEvent.VK_DELETE) { + text = ""; + + } // end of if + textField.setText(text.toUpperCase()); + e.consume(); + if (textField.getText().length()>0) { + bdText.setVerschiebung((int) textField.getText().charAt(0)-65); + + } else { + bdText.setVerschiebung(0); + } // end of if-else + bdText.repaint(); + + } // end of if + + }); + + tab2.add(buchstabe[i]); + } // end of for + + JTabbedPane tabpane = new JTabbedPane + (JTabbedPane.TOP,JTabbedPane.SCROLL_TAB_LAYOUT ); + tabpane.setBounds(10,140,672,290); + + tabpane.addTab("Schritt 1", tab1); + tabpane.addTab("Schritt 2", tab2); + cp.add(tabpane); + + setResizable(false); + setVisible(true); + } + + + + // Anfang Methoden + public void jButton1_ActionPerformed(ActionEvent evt) { + String krypttext = jTAKrypto.getText().toUpperCase(); + String klartext=""; + int c = 0; + int diff = (Integer) jSpVerschiebung.getValue(); + for (int i=0;i=65 && asc<=90) { + h[asc-65]++; + } + } // end of if + c++; + } // end of if + } + bdText.setHaeufigkeit(h); + if (buchstabe[start].getText().length()>0) { + bdText.setVerschiebung((int) buchstabe[start].getText().charAt(0)-65); + + } else { + bdText.setVerschiebung(0); + } // end of if-else + bdText.repaint(); + } catch(BadLocationException e) {} + } + + + public void jSpVerschiebung_StateChanged(ChangeEvent evt) { + String krypto = jTAKrypto.getText().toUpperCase(); + String krypto2=""; + + for (int i=0; iRegula Hoefer-Isenegger +@version 0.1 +*/ +public class LineRenderer { + private Point2D.Double point; + private Turtle turtle; + + LineRenderer(Turtle turtle) { + this.point = new Point2D.Double(); + this.turtle = turtle; + } + + /** Initialisation with coordinates x and + y. + */ + public void init(double x, double y) { + this.point.setLocation(x, y); + } + /** Same as init(double x, double y), but with a Point2D.Double + argument for convenience + */ + public void init(Point2D.Double p) { + this.init(p.x, p.y); + } + /** Get the current x-coordinate in screen coordinates.*/ + private double getX(){ + return (toScreenCoords(point)).getX(); + } + /** Get the current x-coordinate in screen coordinates.*/ + private double getY(){ + return toScreenCoords(point).getY(); + } + /** Calls the clipLineTo and wrapLineTo methods, according + to the turtle's edge behavior. + + Only overwrite this method when working with another + (one that you have defined) edge behaviour.
+ If you mean to change the manner of drawing lines, do this in + the methods clipLineTo() and wrapLineTo(). + @see #clipLineTo + @see #wrapLineTo + */ + protected void internalLineTo(double x, double y){ + Point2D.Double screenPos = toScreenCoords(x, y); + if(turtle.isClip()){ + clipLineTo(screenPos.getX(), screenPos.getY()); + } + if (turtle.isWrap()){ + wrapLineTo(screenPos.getX(), screenPos.getY()); + } + init(x,y); + } + /** Calls the internalLineTo(x,y), which does the actual painting. + */ + public void lineTo(double x, double y) { + internalLineTo(x, y); + } + /** Calls the internalLineTo(x,y), which does the actual painting. + + This method works the same way as lineTo(double x, double y), but + is added for convenience. + */ + public void lineTo(Point2D.Double p) { + internalLineTo(p.getX(), p.getY()); + } + /** Does the actual painting for clip mode. + + It works already with ScreenCoords! + For further comments cf. internalLineTo(double x, double y). + @see #internalLineTo + */ + protected void clipLineTo(double x, double y){ + turtle.getPlayground().lineTo(getX(), getY(), x, y, turtle.getPen()); + } + /** Does the actual painting for wrap mode. + + It works already with ScreenCoords! + For further comments cf. internalLineTo(double x, double y). + @see #internalLineTo + */ + protected void wrapLineTo(double x, double y){ + double dx = getX() - x; + double dy = getY() - y; + Point2D.Double start = new Point2D.Double(x, y); + Point2D.Double end = new Point2D.Double(start.x+dx, start.y+dy); + + intoPanel(start, end); + Point2D.Double tmp; + while ((tmp = calcIntersection(start.x, start.y, end.x, end.y)) != null){ + turtle.getPlayground().lineTo(start.x, start.y, tmp.getX(), tmp.getY(), turtle.getPen()); + start = tmp; + intoPanel(start, end); + dx = end.x - start.x; + dy = end.y - start.y; + } + + turtle.getPlayground().lineTo(start.x, start.y, end.x, end.y, turtle.getPen()); + } + /** Makes the coordinates fit into the Panel. + + Well, this is some sort of modulus calculation. + */ + private void intoPanel(Point2D.Double start, Point2D.Double end){ + int pWidth = turtle.getPlayground().getWidth(); + int pHeight = turtle.getPlayground().getHeight(); + while(start.x < 0){ + start.x += pWidth; + end.x += pWidth; + } + while (start.x > pWidth){ + start.x -= pWidth; + end.x -= pWidth; + } + if(start.x == 0 && end.x < start.x){ + start.x += pWidth; + end.x += pWidth; + } + if(start.x == pWidth && end.x > start.x){ + start.x -= pWidth; + end.x -= pWidth; + } + while(start.y < 0){ + start.y += pHeight; + end.y += pHeight; + } + while (start.y > pHeight){ + start.y -= pHeight; + end.y -= pHeight; + } + if(start.y == 0 && end.y < start.y){ + start.y += pHeight; + end.y += pHeight; + } + if(start.y == pHeight && end.y > start.y){ + start.y -= pHeight; + end.y -= pHeight; + } + + } + /** Intersection line with playground-edges + (startX / startY) MUST lie in the playground! + */ + private Point2D.Double calcIntersection(double startX, double startY, double endX, double endY){ + double dx = endX - startX; + double dy = endY - startY; + double W = turtle.getPlayground().getWidth(); + double H = turtle.getPlayground().getHeight(); + if(endX < 0){ + if((dy/dx <= startY/startX) && (dy/dx >= -(H-startY)/startX)){ // links + return new Point2D.Double(0, startY-startX*dy/dx); + } + } + else if(endX > W){ + if((dy/dx >= -startY/(W-startX)) && (dy/dx <= (H-startY)/(W-startX))){// rechts + return new Point2D.Double(W, startY+(W-startX)*dy/dx); + } + } + if(endY < 0){ // oben + return new Point2D.Double(startX-startY*dx/dy, 0); + } + else if(endY > H){ // unten + return new Point2D.Double(startX+(H-startY)*dx/dy, H); + } + else{ + return null; // Endpoint lies in the window + } + } + /** Calculates the screen coordinates of the turtle's actual + position according to the interpretation of the playground. + */ + private Point2D.Double toScreenCoords(double x, double y){ + return turtle.getPlayground().toScreenCoords(x, y); + } + /** Calculates the screen coordinates of the turtle's actual + position according to the interpretation of the playground. + + Added for convenience. + @see #toScreenCoords(double, double) + */ + private Point2D.Double toScreenCoords(Point2D.Double p){ + return turtle.getPlayground().toScreenCoords(p.x, p.y); + } +} + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/pen.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/pen.java new file mode 100644 index 0000000..8fcc8b7 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/pen.java @@ -0,0 +1,268 @@ +// Pen.java + +// Copyright 2002 Regula Hoefer-Isenegger +// +// This file is part of The Java Turtle package (TJT) +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.awt.Color; +import java.awt.BasicStroke; +import java.awt.Stroke; +import java.awt.Font; +import java.awt.GraphicsEnvironment; + +/** The Pen class provides anything used for drawing the lines, such as line width, + pen color, end caps, dashed lines, etc. + + @see java.awt.BasicStroke + + @author Regula Hoefer-Isenegger + @version 0.1.1 +*/ +public class Pen +{ + /* Attributes *********************************************/ + + /** The default font that is used when drawing Text. + + First argument must be one of "Serif", "SansSerif", "Monotyped", "Dialog" or "DialogInput" + to guarantee that this font exists on all systems. + + @see java.awt.Font for more information, e.g. on font styles. + + */ + public static Font DEFAULT_FONT = new Font("SansSerif", Font.PLAIN, 24); + private Color color; + private Color fillColor; + private BasicStroke stroke; + private Font font; + + /* Constructors *******************************************/ + /** Constructor with standard Color and standard Stroke. + + @see java.awt.BasicStroke + */ + public Pen(){ + color = Color.black; + setFillColor(Color.black); + stroke = new BasicStroke(); + font = DEFAULT_FONT; + } + /** Constructor with Color color and standard Stroke. + + @see java.awt.BasicStroke + */ + public Pen(Color color){ + this.color = color; + setFillColor(color); + stroke = new BasicStroke(); + font = DEFAULT_FONT; + } + /* Methods ************************************************/ + /** Query the Pens color.*/ + public Color getColor(){ + return color; + } + /** Set the Pens color.*/ + public void setColor(Color color){ + this.color = color; + } + /** Set the Pens fill color. + */ + public void setFillColor(Color color){ + this.fillColor = color; + } + /** Query the Pens fill color.*/ + public Color getFillColor(){ + return this.fillColor; + } + /** Get the Pens Stroke + + @see BasicStroke + @see Stroke + */ + public Stroke getStroke(){ + return stroke; + } + /** Query the Pens line width*/ + public float getLineWidth(){ + return stroke.getLineWidth(); + } + /** Query the Pens end cap style. + + @see java.awt.BasicStroke + */ + public int getEndCap(){ + return stroke.getEndCap(); + } + /** Query the Pens line join style. + + @see java.awt.BasicStroke + */ + public int getLineJoin(){ + return stroke.getLineJoin(); + } + /** Query the Pens miter limit style. + + @see java.awt.BasicStroke + */ + public float getMiterLimit(){ + return stroke.getMiterLimit(); + } + /** Query the Pens dash array. + + @see java.awt.BasicStroke + */ + public float[] getDashArray(){ + return stroke.getDashArray(); + } + /** Query the Pens dash phase. + + @see java.awt.BasicStroke + */ + public float getDashPhase(){ + return stroke.getDashPhase(); + } + + /** Set the Pens line width. */ + public void setLineWidth(float width){ + stroke = new BasicStroke((float)width, + stroke.getEndCap(), + stroke.getLineJoin(), + stroke.getMiterLimit(), + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens end cap style. + + @see java.awt.BasicStroke + */ + public void setEndCap(int endCap){ + stroke = new BasicStroke(stroke.getLineWidth(), + endCap, + stroke.getLineJoin(), + stroke.getMiterLimit(), + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens line join style. + + @see java.awt.BasicStroke + */ + public void setLineJoin(int join){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + join, + stroke.getMiterLimit(), + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens miter limit. + + @see java.awt.BasicStroke + */ + public void setMiterLimit(float miterlimit){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + stroke.getLineJoin(), + miterlimit, + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens dash array. + + @see java.awt.BasicStroke + */ + public void setDash(float[] dashArray){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + stroke.getLineJoin(), + stroke.getMiterLimit(), + dashArray, + stroke.getDashPhase()); + } + /** Set the Pens dash phase. + + @see java.awt.BasicStroke + */ + public void setDashPhase(float dashPhase){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + stroke.getLineJoin(), + stroke.getMiterLimit(), + stroke.getDashArray(), + dashPhase); + } + /** Provides information about the currently available font families (e.g. "Roman"). + Each font name is a string packed into a array of strings. + @see java.awt.Font for more information about font attributes etc. + */ + public static String[] getAvailableFontFamilies(){ + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + String s[] = ge.getAvailableFontFamilyNames(); + return s; + } + /** Change the font style. + + @see java.awt.Font for possible styles. + */ + public void setFontStyle(int style){ + font = font.deriveFont(style); + } + /** Change the font size (in points). + */ + public void setFontSize(int size){ + font = font.deriveFont((float)size); + } + /** Change the font size (in points). + You will probably only need the int version setFontSize(int). + */ + public void setFontSize(float size){ + font = font.deriveFont(size); + } + /** Query the size (in points, rounded to int) of the current font. + */ + public int getFontSize(){ + return font.getSize() ; + } + /** Change the font to the given one. + */ + public void setFont(Font f){ + font = f; + } + /** Query the current font. + */ + public Font getFont(){ + return font; + } +} + + + + + + + + + + + + + + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/playground.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/playground.java new file mode 100644 index 0000000..6c0db5b --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/playground.java @@ -0,0 +1,789 @@ +// Playground.java + +// Copyright 2002 Regula Hoefer-Isenegger +// Major code modifications by Aegidius Pluess +// Adaption for the Java-Editor by Gerhard Röhner +// +// This file is part of The Java Turtle package (TJT) +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.util.*; +import javax.swing.*; +import java.awt.*; +import java.awt.print.*; +import java.awt.geom.*; +import java.awt.image.*; +import java.awt.font.*; + +/** + A Playground is the Turtle's home, i.e. the Turtle lives + and moves in the Playground. + + ThePlayground is responsible for interpreting angle and position of the + Turtle and for choosing the correct turtle image and putting it on the right + spot of the Playground. This means: e.g. whenever you wish to switch the x- and y-axis, you + should do it in this class, and not in the Turtle class. + + @author Regula Hoefer-Isenegger + @version 0.1.1 +*/ + +public class Playground extends JPanel implements Printable { + + /** Hold the Turtles of this Playground. */ + private Vector turtles; + + /** Hold the offscreen buffer and graphics context + * where Turtle traces are drawn. + */ + private BufferedImage traceBuffer = null; + protected Graphics2D traceG2D = null; + private Dimension playgroundSize; + + /** Hold the offscreen buffer and graphics context + * of the Turtles images. + */ + private BufferedImage turtleBuffer = null; + protected Graphics2D turtleG2D = null; + + /** Flag to tell whether we have at least one Turtle shown. */ + private boolean isTurtleVisible = false; + + /** Flag to tell whether we use automatic repainting */ + private boolean isRepainting = true; + + /** The default background color. + */ + protected static Color DEFAULT_BACKGROUND_COLOR = Color.white; + + private double printerScale = 1; // Default printer scaling + private TPrintable traceCanvas; // Store ref to user class + private Graphics2D printerG2D = null; + private boolean isPrintScreen = false; // Indicate we are printing the playground + private double printerScaleFactor = 1.1; // Magnification factor for printer + + /** + * originX is the x-position of the cartesian coodinate system within the playground. + */ + public int originX; + + /** + * originY is the y-position of the cartesian coodinate system within the playground. + */ + public int originY; + + private static Color[] ColorArray = {Color.cyan, Color.red, Color.green, Color.blue, Color.yellow, + Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.black, Color.gray + }; + + /** + * Create a Playground with default background color. + * e.g. creates a new vector (which holds the + * Turtles), + */ + public Playground() { + turtles = new Vector(); + setDoubleBuffered(false); + setBackground(DEFAULT_BACKGROUND_COLOR); + initBuffers(new Dimension(100, 100)); + } + + /** + * Initializes the offscreen buffers and sets the size. + */ + protected void initBuffers(Dimension size) { + Color bkColor = getBackground(); + playgroundSize = size; + traceBuffer = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); + traceG2D = traceBuffer.createGraphics(); + traceG2D.setColor(bkColor); + traceG2D.fillRect(0, 0, size.width, size.height); + traceG2D.setBackground(bkColor); + + turtleBuffer = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); + turtleG2D = turtleBuffer.createGraphics(); + turtleG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + originX = size.width/2; + originY = size.height/2; + } + + /** Add a new Turtle to the Playground. + */ + public void add(Turtle turtle) { + turtles.add(turtle); + turtle.setPlayground(this); + int i = turtles.size(); + while (i > 10) { + i = i - 10; + } // end of while + turtle.init(ColorArray[i-1]); + toTop(turtle); + } + + public void setBounds(int x, int y, int width, int height) { + super.setBounds(x, y, width, height); + initBuffers(new Dimension(width, height)); + } + + /** Remove a Turtle from the Playground. + */ + public void remove(Turtle turtle) { + turtles.remove(turtle); + } + + /** Tell current number of Turtles in this Playground. + */ + public int countTurtles() { + return turtles.size(); + } + + /** Return the Turtle at index index. + */ + public Turtle getTurtle(int index) { + return turtles.elementAt(index); + } + + /** Move the given Turtle above all the others, then + paints all turtles. + @see #toTop + */ + public void paintTurtles(Turtle turtle) { + toTop(turtle); + paintTurtles(); + } + + /** Paint all turtles (calling paintComponent()) + */ + public void paintTurtles() { + isTurtleVisible = false; + Graphics2D g2D = getTurtleG2D(); + for (int i = 0; i < countTurtles(); i++) { + Turtle aTurtle = getTurtle(i); + if (!aTurtle.isHidden()) { + paintTurtle(aTurtle); + } + } + + // This is the main repaint call, when the turtle is + // moving (even when all turtles are hidden). + // Strange behaviour an slow Mac machines (pre J2SE 1.4 version): + // It happens that some turtle images are not completely redrawn. + // This is probably due to an improper handling of fast multiple repaint requests. + // Workaround: we wait a small amount of time (and give the thread away) + // (No visible slow down on new machines.) + + paintPlayground(); + if (printerG2D == null) { + //if (isRepainting) + //repaint(); + //paintPlayground(); + } + + if (isTurtleVisible) { + try { + Thread.currentThread().sleep(10); + } + catch (Exception e) {} + } + } + + + /** Paint the given Turtle. + * ( no repaint() ) + */ + public void paintTurtle(Turtle turtle) { + if (turtleBuffer == null){ + turtleBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); + turtleG2D = turtleBuffer.createGraphics(); + } + Graphics2D turtleGraphics = getTurtleG2D(); + turtle.getTurtleRenderer().paint(turtle._getX(), turtle._getY(), turtleGraphics); + isTurtleVisible = true; + } + + /** Put an image of the given Turtle in turtle buffer. + */ + protected void stampTurtle(Turtle turtle) { + turtle.clone(); + isTurtleVisible = true; + if (printerG2D == null) + repaint(); + } + + /** Draw a line from the point (x0, y0) to (x1, y1) + with the color of the given Pen. + */ + protected void lineTo(double x0, double y0, double x1, double y1, Pen pen) { + int ix0 = (int)Math.round(x0); + int iy0 = (int)Math.round(y0); + int ix1 = (int)Math.round(x1); + int iy1 = (int)Math.round(y1); + Color color = pen.getColor(); + + if (traceBuffer == null) { + traceBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); + traceG2D = traceBuffer.createGraphics(); + } + Graphics2D traceG2D = getTraceG2D(); + traceG2D.setColor(color); + traceG2D.setStroke(pen.getStroke()); + traceG2D.drawLine(ix0, iy0, ix1, iy1); + if (printerG2D != null) + printerG2D.drawLine(ix0, iy0, ix1, iy1); + } + + /** A class for convenience. */ + protected class Point extends java.awt.Point { + Point(int x, int y) { + super(x, y); + } + Point() { + super(); + } + Point(Point p) { + super(p.x, p.y); + } + + /** Get a new Point with coordinates (this.x+p.x, this.y+p.y). + */ + protected Point add(Point p) { + return new Point(this.x+p.x, this.y+p.y); + } + + /** Translate by the amounts dx = p.x, dy = p.y. */ + protected void translate(Point p) { + translate(p.x, p.y); + } + + public String toString() { + return "(" + x + "," + y + ")"; + } + } + + /** Fill a region. + The region is defined by the Turtles actual position and + is bounded by any other color than the give background color. + */ + public void fill(Turtle t, Color bgColor) { + final Point[] diff = { new Point(0,-1), new Point(-1,0), new Point(1,0), new Point(0,1)}; + final int N=0; + final int W=1; + final int E=2; + final int S=3; + + int bgcolor = bgColor.getRGB(); + int fillColor = t.getPen().getFillColor().getRGB(); + Vector list = new Vector(); + Point2D.Double p1 = toScreenCoords(t.getPos()); + int startX = (int)Math.round(p1.getX()); + int startY = (int)Math.round(p1.getY()); + Point p = new Point(startX, startY); + if (traceBuffer.getRGB(startX, startY) == bgcolor) { + traceBuffer.setRGB(startX, startY, fillColor); + list.addElement(new Point(startX, startY)); + int d = N; + int back; + while (list.size() > 0) { + while (d <= S) { // forward + Point tmp = p.add(diff[d]); + try { + if (traceBuffer.getRGB(tmp.x, tmp.y) == bgcolor) { + p.translate(diff[d]); + traceBuffer.setRGB(p.x, p.y, fillColor); + if (printerG2D != null) + { + printerG2D.setColor(t.getPen().getFillColor()); + // printerG2D.drawLine(p.x,p.y, p.x, p.y); + BasicStroke stroke = new BasicStroke(2); + printerG2D.setStroke(stroke); + Line2D line = new Line2D.Double(p.x, p.y, p.x, p.y); + printerG2D.draw(line); + } + list.addElement(new Integer(d)); + d=N; + } + else { + d++; + } + } + catch (ArrayIndexOutOfBoundsException e) { + d++; + } + } + Object obj = list.remove(list.size()-1); + try { + d=((Integer)obj).intValue(); // last element + back = S - d; + p.translate(diff[back]); + } + catch (ClassCastException e) { + // the first (zeroest) element in list is the start-point + // just do nothing with it + } + } + } + traceG2D.drawLine(0, 0, 0, 0); // Workaround because on Mac the trace buffer is not drawn without this + if (printerG2D == null) + repaint(); + } + + /** + * Clear the playground with given color. + */ + public void clear(Color color) { + traceG2D.setColor(color); + traceG2D.fillRect(0, 0, getWidth(), getHeight()); + turtleG2D.setColor(color); + turtleG2D.fillRect(0, 0, getWidth(), getHeight()); + isTurtleVisible = true; + if (printerG2D == null) + repaint(); + } + + /** + * Clear playground. + */ + public void clear() { + clear(getBackground()); + } + + /** Paint the Playground. + just a method for convenience. + */ + public void paintComponent() { + paintComponent(getGraphics()); + } + + /** Draw the trace and turtle buffers. + */ + public void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2D = (Graphics2D)g; + g2D.drawImage(traceBuffer, 0, 0, this); + if (isTurtleVisible) + g2D.drawImage(turtleBuffer, 0, 0, this); + } + + public void paintPlayground() { + Graphics g = getGraphics(); + if (g != null) { + super.paintComponent(g); + Graphics2D g2D = (Graphics2D)g; + g2D.drawImage(traceBuffer, 0, 0, this); + if (isTurtleVisible) + g2D.drawImage(turtleBuffer, 0, 0, this); + + } // end of if + } + + /** Remove all turtles from the turtle buffer. + */ + public void clearTurtles() { + for (int i = 0; i < countTurtles(); i++) { + Turtle turtle = getTurtle(i); + clearTurtle(turtle); + } + } + + /** Remove the given turtle from the turtle buffer. + Override this method if you have added a new behaviour (like + wrap or clip) to the turtle. + */ + public void clearTurtle(Turtle turtle) { + if(turtle != null){ + if (!turtle.isHidden()) { + if(turtle.isClip()){ + clearClipTurtle(turtle); + } + else if(turtle.isWrap()){ + clearWrapTurtle(turtle); + } + } + } + } + + /** This method is called when the given Turtle is in wrap mode. + + @see ch.aplu.turtle.Turtle#wrap + */ + protected void clearWrapTurtle(Turtle turtle){ + clearWrapTurtle(turtle, turtleBuffer); + } + + /** Here the actual clearing of a Turtle in wrap mode from the + given image is performed. + */ + protected void clearWrapTurtle(Turtle turtle, Image im){ + Rectangle bounds = getBounds(turtle); + int pWidth = getWidth(); + int pHeight = getHeight(); + int x = bounds.x; + int y = bounds.y; + while (x > pWidth){ + x -= pWidth; + } + while (x < 0){ + x += pWidth; + } + while (y > pHeight){ + y -= pHeight; + } + while (y < 0){ + y += pHeight; + } + x = x % pWidth; + y = y % pHeight; + toAlphaNull(im, new Rectangle(x, y, bounds.width, bounds.height)); // OK + boolean right = (x + bounds.width > getWidth()); + boolean bottom = (y + bounds.height > getHeight()); + if (right) { + toAlphaNull(im, new Rectangle(x-pWidth, y, bounds.width, bounds.height)); + } + if (bottom) { + toAlphaNull(im, new Rectangle(x, y-pHeight, bounds.width, bounds.height)); + } + if (right && bottom) { + toAlphaNull(im, new Rectangle(x-pWidth, y-pHeight, bounds.width, bounds.height)); + } + } + + /** Copy and translate a given Rectangle. + */ + private Rectangle copyAndTranslate(Rectangle rect, int dx, int dy) { + return new Rectangle(rect.x+dx, rect.y+dy, + rect.width, rect.height); + } + + /** This method is called when the given Turtle is in clip mode. + + @see ch.aplu.turtle.Turtle#clip + */ + protected void clearClipTurtle(Turtle turtle) { + clearClipTurtle(turtle, turtleBuffer); + } + + /** Here the actual clearing of a Turtle in clip mode from the + given image is performed. + */ + protected void clearClipTurtle(Turtle turtle, Image im) { + Rectangle bounds = getBounds(turtle); + toAlphaNull(im, bounds); + } + + /** Set the alpha channel of all pixels in the given image + in the given Rectangle to zero (i.e. totally transparent). + + This method is used byte the clearXXXTurtle methods. + */ + private void toAlphaNull(Image im, Rectangle rect) { + Rectangle rim = new Rectangle(0, 0, im.getWidth(this), im.getHeight(this)); + Rectangle r = new Rectangle(); + if (rect.intersects(rim)) { + r=rect.intersection(rim); + } + int size = r.width*r.height; + float[] alphachannel = new float[r.width*r.height]; + ((BufferedImage)im).getAlphaRaster().setPixels(r.x, r.y, r.width, r.height, alphachannel); + } + + /** Puts a Turtle above all others. + */ + public Turtle toTop(Turtle turtle) { + if (turtles.removeElement(turtle)) { + turtles.add(turtle); + } + return turtle; + } + /** Put a Turtle below all others. + */ + public Turtle toBottom(Turtle turtle) { + if (turtles.removeElement(turtle)) { + turtles.add(0,turtle); + } + return turtle; + } + + /** Calculate the screen coordinates of the given point. + */ + public Point2D.Double toScreenCoords(Point2D.Double p) { + return internalToScreenCoords(p.x, p.y); + } + + /** Calculate the screen coordinates of the given point coordinates. + */ + public Point2D.Double toScreenCoords(double x, double y) { + return internalToScreenCoords(x, y); + } + + protected Point2D.Double internalToScreenCoords(double x, double y) { + // reflect at x-axis, then translate to center of Playground + // pixel coordinates coorespond to turtle coordinates, only translation needed + double newX = originX + x; + double newY = originY - y; + return new Point2D.Double(newX, newY); + } + + /** Calculate the turtle coordinates of the given screen coordinates. + */ + public Point2D.Double toTurtleCoords(double x, double y) { + // pixel coordinates coorespond to turtle coordinates, only translation needed + double newX = x - originX; + double newY = originY - y; + return new Point2D.Double(newX, newY); + } + + /** Calculate the turtle coordinates of the given screen point. + */ + public Point2D.Double toTurtleCoords(Point2D.Double p) { + return toTurtleCoords(p.x, p.y); + } + + /** Calculate the screen angle. + I.e. the interpretation of angle. + @param radians The angle in radians. + */ + double toScreenAngle(double radians) { + double sa = radians; + if (sa < Math.PI/2){ + sa += 2*Math.PI; + } + sa -= Math.PI/2; + if (sa != 0) { + sa = Math.PI*2 - sa; + } + return sa; + } + + /** Calculate the bounds of the Turtles picture on the screen. + */ + protected Rectangle getBounds(Turtle turtle) { + Rectangle bounds = turtle.getBounds(); + Point2D.Double tmp = toScreenCoords(new Point2D.Double(bounds.getX(), bounds.getY())); + bounds.setRect(tmp.x-2, tmp.y-2, bounds.width+4, bounds.height+4); + return bounds; + } + + /** Return the graphics context of the turtle buffer. + */ + public Graphics2D getTurtleG2D() { + return turtleG2D; + } + + /** Return the image of the turtle buffer. + */ + public BufferedImage getTurtleBuffer() { + return turtleBuffer; + } + + /** Return the graphics context of the trace buffer. + */ + public Graphics2D getTraceG2D() { + return traceG2D; + } + + /** Return the graphics context of the printer. + */ + public Graphics2D getPrinterG2D() { + return printerG2D; + } + + /** Return the image of the trace buffer. + */ + public BufferedImage getTraceBuffer() { + return traceBuffer; + } + + /** Clean the traces. + All turtles stay how and where they are, only lines, text and stamps will be removed. + */ + void clean() { + Graphics2D g = getTraceG2D(); + g.setColor(getBackground()); + g.fillRect(0,0,getWidth(), getHeight()); + if (printerG2D == null) + repaint(); + } + + /** Draw the text at the current position of the Turtle t. + Drawing a text at some coordinates (x,y) we mean that the bottom left corner of + the text will be at these coordinates. + Font and colour are specified by the Turtle's Pen. + */ + public void label(String text, Turtle t) { + Point2D.Double sc = toScreenCoords(t.getPos()); + int x = (int)Math.round(sc.x); + int y = (int)Math.round(sc.y); + Graphics2D traceG2D = getTraceG2D(); + FontRenderContext frc = traceG2D.getFontRenderContext(); + Font f = t.getFont(); + TextLayout tl = new TextLayout(text, f, frc); + traceG2D.setColor(t.getPen().getColor()); + tl.draw(traceG2D, x, y); + if (printerG2D != null) + { + printerG2D.setColor(t.getPen().getColor()); + tl.draw(printerG2D, x, y); + } + + if (printerG2D == null) + repaint(); + } + + /** Set antialiasing on or off for the turtle trace buffer + * This may result in an better trace quality. + */ + public void setAntiAliasing(boolean on) { + if (on) + traceG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + else + traceG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_OFF); + } + + + /** + * Set the given TPrintable (implementing draw()), + * open a printer dialog and start printing with given scale. + * Return false, if printer dialog is aborted, + * otherwise return true.
+ * If tp == null, the current playground is printed. + * + */ + protected boolean print(TPrintable tp, double scale) { + if (tp == null) + isPrintScreen = true; + else + isPrintScreen = false; + printerScale = scale; + PrinterJob pj = PrinterJob.getPrinterJob(); + pj.setPrintable(this); + traceCanvas = tp; + if (pj.printDialog()) { + try { + pj.print(); + } + catch (PrinterException ex) { + System.out.println(ex); + } + return true; + } + else + return false; + } + + /** + * For internal use only. Implementation of Printable. + * (Callback method called by printing system.) + */ + public int print(Graphics g, PageFormat pf, int pageIndex) { + if (pageIndex != 0) + return NO_SUCH_PAGE; + Graphics2D g2D = (Graphics2D)g; + double printerWidth = pf.getImageableWidth(); + double printerHeight = pf.getImageableHeight(); + double printerSize = printerWidth > printerHeight ? printerWidth : + printerHeight; + double xZero = pf.getImageableX(); + double yZero = pf.getImageableY(); + + printerG2D = g2D; // Indicate also, we are printing now + + // Needed for fill operations: the trace canvas must be empty in order to + // perform the fill algoritm (searching for outline of figure) + if (!isPrintScreen) + clean(); + + g2D.scale(printerScaleFactor * printerScale, printerScaleFactor * printerScale); + g2D.translate(xZero/printerScale, yZero/printerScale); + + if (isPrintScreen) + { + print(g); + } + else // Printing the traceCanvas + { + // Hide all turtles + boolean[] turtleState = new boolean[countTurtles()]; + for (int i = 0; i < countTurtles(); i++) { + Turtle aTurtle = getTurtle(i); + turtleState[i] = aTurtle.isHidden(); + aTurtle.ht(); + } + traceCanvas.draw(); + + // Restore old context + for (int i = 0; i < countTurtles(); i++) { + Turtle aTurtle = getTurtle(i); + if (!turtleState[i]) + aTurtle.st(); + } + } + + printerG2D = null; + return PAGE_EXISTS; + } + + /** Return the color of the pixel at the current turtle position. + */ + public Color getPixelColor(Turtle t) { + Point2D.Double p1 = toScreenCoords(t.getPos()); + int x = (int)Math.round(p1.getX()); + int y = (int)Math.round(p1.getY()); + return new Color(traceBuffer.getRGB(x, y)); + } + + public void enableRepaint(boolean b) { + isRepainting = b; + } + + /** set the background color of the playground + */ + public void setBackground(Color color) { + super.setBackground(color); + if (traceG2D != null) { + clear(color); + } // end of if + } + + /** + * Sets the origin of the cartesian coordinate system within the playground + */ + public void setOrigin(int x, int y) { + for (int i = 0; i < countTurtles(); i++) { + Turtle turtle = getTurtle(i); + Point2D.Double p1 = toScreenCoords(turtle.getPos()); + double newX = p1.getX() - x; + double newY = y - p1.getY(); + turtle.internalSetPos(newX, newY); + } + originX = x; + originY = y; + } + + public int getOriginX() { + return originX; + } + + public int getOriginY() { + return originY; + } + +} + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/res/bong.wav b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/res/bong.wav new file mode 100644 index 0000000000000000000000000000000000000000..0d2fef0c16fc8ff100f498e161aed70ae66207eb GIT binary patch literal 9624 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 literal 0 HcmV?d00001 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/sharedconstants.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/sharedconstants.java new file mode 100644 index 0000000..1bd3955 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/sharedconstants.java @@ -0,0 +1,84 @@ +// SharedConstants.java + +// Copyright 2002 Regula Hoefer-Isenegger +// +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +/* History; +V1.36 - Sep 2004: First official release +V1.37 - Nov 2004: Unchanged, modifications in ch.aplu.util +V1.38 - Dec 2004: Unchanged, modifications in ch.aplu.util +V1.39 - Jan 2005: Unchanged, modifications in ch.aplu.util +V1.40 - Mar 2005: Add background color, TurtleKeyAdapter, TurtleArea +V1.41 - May 2005: User defined turtle shape, minor changes in doc and code style +V1.42 - Dec 2005: Unchanged, modifications in ch.aplu.util +V1.43 - Feb 2006: Bug removed: Turtle.turtleFrame was not initialized in all ctors of class Turtle +V1.44 - Mar 2007: Bug removed: stampTurtle did not work properly in wrap mode +V1.45 - Aug 2007: TurtleKeyAdapter: use wait/notify to reduce CPU time (from 100% to 2%) +V1.46 - Aug 2007: synchronize(playground) for forward and rotate animation, + new method bong() using StreamingPlayer +V1.47 - Sept 2007: Unchanged, modifications in ch.aplu.util +V1.48 - Sept 2007: Unchanged, modifications in ch.aplu.util +V1.49 - Oct 2007: Unchanged, modifications in ch.aplu.util +V1.50 - Oct 2007: Unchanged, modifications in ch.aplu.util +V1.51 - Nov 2007: Fixed: correct position of label, when wrapping is on + Fixed: getPos() returns now the wrapped coordinates + Added: _getPos() returns unwrapped coordinates +V1.52 - Nov 2007: Added bean classes in order to use turtles with a Gui builder +V1.53 - Nov 2007: Added TurtlePane visual information when used in Gui builder design mode +V1.54 - Nov 2007: Minor changes to documentation +V1.55 - Dec 2007: Added property enableFocus to GPane, default: setFocusable(false) +V1.56 - Mar 2008: Unchanged, modifications in ch.aplu.util +V1.57 - Mar 2008: Unchanged, modifications in ch.aplu.util +V1.58 - Mar 2008: Modification to fill() (fill(x, y)): + region is defined with pixel color at current position + as opposed to background color +V1.59 - Oct 2008: Added ctors TurtleFrame with window position (ulx, uly) + Added Turtle.getPixelColor() +V2.00 - Nov 2008: Unchanged, modifications in ch.aplu.util + J2SE V1.4 no longer supported +V2.01 - Jan 2009: Unchanged, modifications in ch.aplu.util +V2.02 - Feb 2009 Turtle constructors run in EDT now +V2.03 - Feb 2009 Unchanged, modifications in ch.aplu.util +V2.04 - Feb 2009 Unchanged, modifications in ch.aplu.util +V2.05 - Feb 2009 Unchanged, modifications in ch.aplu.util +V2.06 - Mar 2009 Unchanged, modifications in ch.aplu.util +V2.07 - Mar 2009 All except print methods synchronized, so Turtle package is + now thread-safe +V2.08 - Apr 2009 Unchanged, modifications in ch.aplu.util +V2.09 - Jun 2009 Unchanged, modifications in ch.aplu.util +V2.10 - Jun 2010 Version for the Java-Editor +*/ + +package ch.aplu.turtle; + +interface SharedConstants +{ + int DEBUG_LEVEL_OFF = 0; + int DEBUG_LEVEL_LOW = 1; + int DEBUG_LEVEL_MEDIUM = 2; + int DEBUG_LEVEL_HIGH = 3; + + int DEBUG = DEBUG_LEVEL_OFF; + + String ABOUT = + "Copyright © 2002-2009\nRegula Hoefer-Isenegger, Aegidius Pluess\n, Gerhard Roehner\n" + + "under GNU General Public License\n" + + "http://www.aplu.ch\n" + + "All rights reserved"; + String VERSION = "2.10 - June 2015"; +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/streamingplayer.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/streamingplayer.java new file mode 100644 index 0000000..8a3d5d5 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/streamingplayer.java @@ -0,0 +1,84 @@ +// StreamingPlayer.java + +package ch.aplu.turtle; + + +import javax.sound.sampled.*; +import java.io.*; + +class StreamingPlayer +{ + private class PlayerThread extends Thread + { + public void run() + { + byte buf[] = new byte[20000]; + try + { + int cnt; + while ((cnt = audioInputStream.read(buf, 0, buf.length)) != -1) + { + if (cnt > 0) + sourceDataLine.write(buf, 0, cnt); + } + sourceDataLine.drain(); + sourceDataLine.close(); + } + catch (IOException ex) + { + System.out.println(ex); + System.exit(1); + } + } + } + + private AudioFormat audioFormat; + private AudioInputStream audioInputStream; + private SourceDataLine sourceDataLine; + private PlayerThread playerThread; + + StreamingPlayer(InputStream is) + { + try + { + audioInputStream = + AudioSystem.getAudioInputStream(is); + audioFormat = audioInputStream.getFormat(); + } + catch (Exception ex) + {} + } + + void start(boolean doFinish) + throws LineUnavailableException + { + DataLine.Info dataLineInfo = + new DataLine.Info(SourceDataLine.class, audioFormat); + sourceDataLine = + (SourceDataLine)AudioSystem.getLine(dataLineInfo); + sourceDataLine.open(audioFormat); + sourceDataLine.start(); + playerThread = new PlayerThread(); + playerThread.start(); + if (doFinish) + waitToFinish(); + } + + boolean isPlaying() + { + if (playerThread == null) + return false; + return (playerThread.isAlive()); + } + + void waitToFinish() + { + if (playerThread == null) + return; + try + { + playerThread.join(); + } + catch (InterruptedException ex) {} + } +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/tprintable.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/tprintable.java new file mode 100644 index 0000000..767d22a --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/tprintable.java @@ -0,0 +1,43 @@ +// TPrintable.java + +// Copyright 2002 Regula Hoefer-Isenegger + +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +// Added by Aegidius Pluess + +package ch.aplu.turtle; + +/** + * Interface for printing on an attached printer. + * Normally an application uses a Turtle and implements this interface. + * draw() should contain all drawing operations into the + * Turtle's Playground. The printing occures, when Turtle's print() is + * called.

+ */ + + +public interface TPrintable +{ + /** + * This method must perform all drawing operations. + * Be aware that for some undocumented reason + * draw() is called twice. So be sure you initialize it correctly. + */ + + public void draw(); +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/turtle.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/turtle.java new file mode 100644 index 0000000..d30ff52 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/turtle.java @@ -0,0 +1,1585 @@ +// Turtle.java +// Modifications by Aegidius Pluess +// Adaption to the Java-Editor by Gerhard Röhner + +// Copyright 2002-2003 Regula Hoefer-Isenegger (Version 1.0) +// +// This file is part of The Java Turtle package (TJT) +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +/* +Screen coordinate system: 0..400 pixels in both directions corresponds to turtle +turtle coordinate system -200..200, so only translation is necessary (no scaling). + +This avoids rounding errors. +*/ + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.*; +import java.awt.image.*; +import java.awt.print.*; +import java.io.*; +import javax.sound.sampled.*; +import javax.swing.*; + +/** + The core class for turtles. + + For a simple example on how to use Turtle, cf. the + Java Turtle Package description. + @author Regula Hoefer-Isenegger + @version 0.1.1 +*/ +public class Turtle implements Cloneable +{ + private double angle; + private Point2D.Double position; + private Playground playground; + private int framesPerSecond; + private double speed; // Pixel/sec + private double angleSpeed; // Radian/sec + private TurtleRenderer turtleRenderer; + private int angleResolution; + private LineRenderer lineRenderer; + private static TurtleFactory turtleFactory; + private boolean penUp; + private boolean showTurtle; + private boolean initialVisibility = true; + private Pen pen; + private Color color; + private int edgeBehaviour; + + + /** Convert from screen coordinates to turtle coordinates + */ + public Point2D.Double toTurtlePos(Point p) { + return playground.toTurtleCoords((double)p.x, (double)p.y); + } + + /** Convert from screen coordinates to turtle coordinates + */ + public Point2D.Double toTurtlePos(int x, int y) { + return playground.toTurtleCoords((double)x, (double)y); + } + + /** Convert from screen coordinates to turtle coordinates + */ + public double toTurtleX(int x) { + return (playground.toTurtleCoords((double)x, 0)).x; + } + + /** Convert from screen coordinates to turtle coordinates + */ + public double toTurtleY(int y) { + return (playground.toTurtleCoords(0, (double)y)).y; + } + + /** Add the specified mouse listener to receive mouse events. + */ + public void addMouseListener(MouseListener l) { + playground.addMouseListener(l); + } + + /** Add the specified mouse motion listener to receive mouse motion events. + */ + public void addMouseMotionListener(MouseMotionListener l) { + playground.addMouseMotionListener(l); + } + + /** + * Emit a beep. Fails if no standard speaker available. Try to use bong() instead. + * @see #bong() + */ + public void beep() { + Toolkit.getDefaultToolkit().beep(); + } + + /** + * Emit a 'bong' via the sound card. Useful on computers without standard + * speaker. + * @see #beep() + */ + public void bong() { + InputStream is = getClass().getResourceAsStream("res/bong.wav"); + StreamingPlayer player = new StreamingPlayer(is); + try + { + player.start(false); + } + catch (LineUnavailableException ex) + { + System.out.println("Error in bong(). Sound card unavailable"); + } + } + + + /** Represent clip mode. + @see #WRAP + @see #clip() + */ + protected final static int CLIP = 0; + /** Represent wrap mode. + + @see #CLIP + @see #wrap() + */ + protected final static int WRAP = 1; + /** Represent the default edge behaviour (i.e. CLIP or WRAP). + + @see #CLIP + @see #WRAP + @see #clip() + @see #wrap() + */ + protected static int DEFAULT_EDGE_BEHAVIOUR = CLIP; + /** Represent the default speed (velocity). + + @see #setSpeed(double) + */ + protected static double DEFAULT_SPEED = 200; + + /** Represent the default angle resolution. + + It specifies how many different turtle pictures + are generated. + */ + protected static int DEFAULT_ANGLE_RESOLUTION = 72; + + /** Specify how many frames per second are used for + turtle animation. + */ + protected static int DEFAULT_FRAMES_PER_SECOND = 10; + + /** Specify the default turtle color. + + @see #setColor(java.awt.Color) + */ + protected static Color DEFAULT_TURTLE_COLOR = Color.cyan; + + /** Specify the default pen color. + + @see #setPenColor(java.awt.Color) + */ + protected static Color DEFAULT_PEN_COLOR = Color.blue; + + /** Create a new Turtle + */ + public Turtle() { + } + + /** init a new Turtle + */ + protected void init(Color color) { + angle = 0; + position = new Point2D.Double(0, 0); + framesPerSecond = DEFAULT_FRAMES_PER_SECOND; + if (initialVisibility) + setSpeed(DEFAULT_SPEED); + else + setSpeed(-1); + showTurtle = initialVisibility; + setAngleResolution(DEFAULT_ANGLE_RESOLUTION); + angleSpeed = getSpeed() * Math.PI * 2 / DEFAULT_SPEED; + pen = new Pen(DEFAULT_PEN_COLOR); + if (getTurtleFactory() == null){ + turtleFactory = createTurtleFactory(); + } + setColor(color); + lineRenderer = createLineRenderer(); + getTurtleRenderer().setAngle(getAngle()); + } + + /** Set the angle resolution for the Turtle's pictures. + + It specifies how many pictures are used. e.g. an angle resolution + of 90 means that you get one picture for every 4 degrees + (= 360/90 degrees). + */ + public void setAngleResolution(int newResolution) { + synchronized(playground) { + angleResolution = newResolution; + } + } + + /** Return the TurtleFactory of this turtle. + + @see ch.aplu.turtle.TurtleFactory + */ + public TurtleFactory getTurtleFactory() { + return this.turtleFactory; + } + + /** Create a LineRenderer which is responsible + for the correct drawing of the lines. + + @return the new LineRenderer + */ + + protected LineRenderer createLineRenderer() { + return new LineRenderer(this); + } + + /** Create a TurtleRenderer which is responsible + for the correct drawing of the Turtle. + + @return the new TurtleRenderer + */ + protected TurtleRenderer createTurtleRenderer() { + return new TurtleRenderer(this); + } + + /** Create a TurtleFactory which provides for + the Turtle pictures. + + @return the new TurtleFactory + */ + + protected TurtleFactory createTurtleFactory() { + return new TurtleFactory(); + } + /** Get the angle resolution. + + @see #setAngleResolution(int) + */ + + protected int getAngleResolution() { + return angleResolution; + } + + /** Get the TurtleRenderer. + */ + TurtleRenderer getTurtleRenderer() { + return turtleRenderer; + } + + /** Get the LineRenderer. + */ + private LineRenderer getLineRenderer() { + return lineRenderer; + } + + /** Get the Playground. + */ + public Playground getPlayground() { + return playground; + } + + /** Set the Playground to the specified + playground. + + The Turtle is removed from the old + Playground and set to the new one. + */ + public void setPlayground(Playground playground) { + Playground pg = getPlayground(); + if(pg != null){ + pg.clearTurtle(this); + pg.remove(this); + pg.paintTurtles(); + } + this.playground = playground; + playground.paintTurtles(this); + } + + /** Get the angle speed. + + (I.e. how fast the Turtle rotation + animation is performed.) + */ + private double getAngleSpeed() { + return angleSpeed; + } + + /** Set the angle speed. + + @see #getAngleSpeed() + */ + private void setAngleSpeed(double newAngleSpeed) { + this.angleSpeed = newAngleSpeed; + } + + /** Get the current angle (heading) of the + Turtle. + */ + private double getAngle() { + return angle; // in radians + } + + /** Get the current speed. + */ + public double getSpeed() { + return speed; + } + + /** Query the Turtle's x-position without wrapping. + * Coordinate are not bound to playground even when + * wrapping is on. + */ + public double _getX() { + synchronized (playground) { + return position.getX(); + } + } + + /** Query the Turtle's y-position without wrapping. + * Coordinate are not bound to playground even when + * wrapping is on. + */ + public double _getY() { + synchronized (playground) { + return position.getY(); + } + } + + /** Query the Turtle's x-position. + * If turtle is outside playground and wrapping is on + * return the coordinate in range -200..200. + * */ + + public double getX() { + synchronized (playground) { + double xPos = _getX(); + return xPos; + } + } + + /** Query the Turtle's x-position. + * If turtle is outside playground and wrapping is on + * return the coordinate in range -200..200. + */ + public double getY() { + synchronized (playground) { + double yPos = _getY(); + return yPos; + } + } + + + /** Query the Turtle's position without wrapping. + * Coordinate are not bound to playground even when + * wrapping is on. + */ + public Point2D.Double _getPos() { + return position; + } + + /** Query the Turtle's position */ + public Point2D.Double getPos() { + return new Point2D.Double(getX(), getY()); + } + + /** Put the Turtle to a new position with the given x-coordinates. + + */ + public void setX(double x) { + synchronized (playground) { + getPlayground().clearTurtle(this); + internalSetX(x); + getPlayground().paintTurtles(this); + } + } + + /** Put the Turtle to a new position with the given screen x-coordinates. + */ + public void setScreenX(int x) { + synchronized (playground) { + setX(toTurtleX(x)); + } + } + + /** Put the Turtle to a new position with the given y-coordinates. + */ + public void setY(double y) { + synchronized (playground) { + getPlayground().clearTurtle(this); + internalSetY(y); + getPlayground().paintTurtles(this); + } + } + + /** Put the Turtle to a new position with the given screen y-coordinates. + */ + public void setScreenY(int y) { + synchronized (playground) { + setY(toTurtleY(y)); + } + } + + /** Set the Turtle's x-Coordinate. + */ + protected void internalSetX(double x) { + synchronized (playground) { + position.setLocation(x, _getY()); + } + } + + /** Set the Turtle's y-Coordinate. + */ + protected void internalSetY(double y) { + position.setLocation(_getX(), y); + } + + /** Set the Turtle's Position. + */ + protected void internalSetPos(double x, double y) { + position.setLocation(x, y); + } + + /** Hide the Turtle. + + @see #st() + If there is only one turte, the speed is set to -1 + so there is no Turtle animation at all. + Hiding the Turtle speeds up the graphics enormously. + */ + public void ht() { + synchronized (playground) { + this.internalHide(); + if (getPlayground().countTurtles() == 1) + setSpeed(-1); + } + } + + /** Hide the Turtle. + + This is the same as ht(). + @see #st() + */ + public void hideTurtle() { + ht(); + } + + /** This is the method called by the public methods ht() and hideTurtle(). + + Here the actual hiding takes place. + @see #ht() + @see #hideTurtle() + */ + protected void internalHide() { + getPlayground().clearTurtle(this); + showTurtle = false; + if (getPlayground().getPrinterG2D() == null) + getPlayground().repaint(); + } + + /** Set the Turtle to show mode. + + That means that the Turtle will be drawn. + @see #ht() + */ + public void st() { + synchronized (playground) { + if (getPlayground().getPrinterG2D() == null) { + getPlayground().paintTurtle(this); + showTurtle = true; + getPlayground().repaint(); + } + } + } + + /** The same as st(). + + @see #st() + */ + public void showTurtle() { + st(); + } + + /** Tell whether the Turtle is hidden or not. + + @return true if the Turtle is hidden, + false otherwise. + */ + public boolean isHidden() { + return !showTurtle; + } + + private int getFramesPerSecond() { + return this.framesPerSecond; + } + + /** Only set the angle attribute. This method does not + invoke any re-painting. + */ + private void setAngle(double radians) { + this.angle = radians; + } + + /** This is the same as setH(double degrees). + + @see #setH(double) + */ + public void setHeading(double degrees) { + synchronized (playground) { + setAngle(Math.toRadians(degrees)); + getTurtleRenderer().setAngle(Math.toRadians(degrees)); + getPlayground().clearTurtle(this); + getPlayground().paintTurtles(this); + } + } + + /** Set the Turtle's heading. + + 0 means facing NORTH.
+ the angles are measured clockwise. + @see #setHeading(double) + */ + public void setH(double degrees) { + setHeading(degrees); + } + /** Query the Turtle's heading. + + @see #setH(double) + */ + public double heading() { + synchronized (playground) { + return Math.toDegrees(getAngle()); + } + } + /** Set the Turtle's heading to the new value. + + @return the old (previous) value. + @see #setH(double) + */ + public double heading(double degrees) { + synchronized (playground) { + double tmp = Math.toDegrees(getAngle()); + setHeading(degrees); + return tmp; + } + } + + /** Set the Turtle's speed. + + If you try to set the speed to 0, it will be set to 1 (very slow). + A negative speed means that moving the Turtle (fd, bk) + will not be animated.
+ The unit is pixels per second (up to certain bounds depending on the CPU etc.).
+ Remark: Dashed lines will only be painted as you expect it with speed set + to -1. + + @see #fd(double) + @see #bk(double) + */ + public void setSpeed(double speed) { + if (speed == 0) + this.speed = 1; + else + this.speed = speed; + } + + + /** This method is responsible for the rotation animation. + */ + private void internalRotate(double angle) { + if(isHidden()){ + synchronized(playground) + { + setAngle(getAngle()+angle); + if (getTurtleRenderer().imageChanged(getAngle())) { + getTurtleRenderer().setAngle(getAngle()); + } + } + return; + } + if (angle != 0) { + int iterations = getAngleIterations(angle); + + double sign = angle/Math.abs(angle); + double increment = sign*getAngleSpeed()/(double)getFramesPerSecond(); + double startAngle = getAngle(); + + for (int index = 0; index < iterations; index++) { + long timeStamp = System.currentTimeMillis(); + + synchronized(playground) { + getPlayground().clearTurtle(this); + + if (index < iterations-1) { + setAngle(getAngle()+increment); + } + else { + setAngle(startAngle+angle); + } + + if (getTurtleRenderer().imageChanged(getAngle())) { + getTurtleRenderer().setAngle(getAngle()); + getPlayground().paintTurtles(this); + } + } + + long newTimeStamp = System.currentTimeMillis(); + Double secs = new Double(1000./getFramesPerSecond()); + long requiredTime = secs.longValue()-newTimeStamp+timeStamp; + + if (requiredTime > 0) { + try { + Thread.sleep(requiredTime); + } + catch (InterruptedException e) { + } + } + } + } + getPlayground().paintTurtles(this); + } + + /** This method is responsible for the moving animation. + */ + private void internalMove(double length) { + if (getSpeed()>0){ + if (length != 0) { + int iterations = getPathIterations(length); + // an angle of 0 means: facing NORTH + double startX = _getX(); + double startY = _getY(); + getLineRenderer().init(startX, startY); + double dx = length * Math.sin(getAngle()); + double dy = length * Math.cos(getAngle()); + double incrementX = dx / iterations; + double incrementY = dy / iterations; + for (int index = 0; index < iterations; index++) { + long timeStamp = System.currentTimeMillis(); + int nX = (int)_getX(); + int nY = (int)_getY(); + synchronized(playground) { + playground.clearTurtle(this); + if (index < iterations-1) { + internalSetX(_getX()+incrementX); + internalSetY(_getY()+incrementY); + } + else { // last step: Calc the "exact" value + internalSetX(startX + dx); + internalSetY(startY + dy); + } + if (nX != (int)_getX() || nY != - (int)_getY() || index == iterations-1){ + if (!isPenUp()) { + getLineRenderer().lineTo(_getX(), _getY()); + } + getPlayground().paintTurtles(this); + } + } + Double frames = new Double(1000./getFramesPerSecond()); + long newTimeStamp = System.currentTimeMillis(); + long requiredTime = frames.longValue()-newTimeStamp+timeStamp; + if (requiredTime > 0) { + try { + Thread.sleep(requiredTime); + } + catch (InterruptedException e) { + } + } + } + } + } + else { // Speed < 0, i.e. no animation + double startX = _getX(); + double startY = _getY(); + getLineRenderer().init(startX, startY); + double dx = length * Math.sin(getAngle()); + double dy = length * Math.cos(getAngle()); + getPlayground().clearTurtle(this); + internalSetX(startX + dx); + internalSetY(startY + dy); + if (!isPenUp()) { + getLineRenderer().lineTo(_getX(), _getY()); + } + getPlayground().paintTurtles(this); + } + } + + /** Turn the Turtle the given angle (in degrees) to the left + + @see #rt(double) + */ + public void lt(double degrees) { + left(degrees); + } + + /** Same as lt(double degrees) + + @see #lt(double) + */ + public void left(double degrees) { + internalRotate(Math.toRadians(-degrees)); + } + + /** Turn the Turtle the given angle (in degrees) to the right. + + @see #rt(double) + */ + public void rt(double degrees) { + right(degrees); + } + + /** Same as rt(double degrees). + + @see #rt(double) + */ + public void right(double degrees) { + internalRotate(Math.toRadians(degrees)); + } + + /** Same as fd(double distance) + + @see #fd(double) + */ + public void forward(double distance) { + internalMove(distance); + } + + /** Move the Turtle forwards. + + Negative values for distance are + allowed. In that case, the Turtle + will move backwards. + + @see #bk(double) + */ + public void fd(double distance) { + forward(distance); + } + + /** Same as bk(double distance). + + @see #bk(double) + */ + public void back(double distance) { + forward(-distance); + } + + /** Move the Turtle backwards. + + Negative values for distance are + allowed. In that case, the Turtle + will move forwards. + + @see #fd(double) + */ + public void bk(double distance) { + back(distance); + } + + /** Query the distance from the current location + to the given one. + */ + public double distance(double x, double y) { + synchronized (playground) { + return this.getPos().distance(x,y); + } + } + + /** Query the distance from the current location + to the given one. + * Actually a polygon with 36 sides is drawn. + */ + public double distance(Point2D.Double p) { + synchronized (playground) { + return this.getPos().distance(p); + } + } + + /** Draw a circle to the left from the current position with + * turtle's heading tangent direction and given radius. + * Actually a polygon with 36 sides is drawn. + */ + public void leftCircle(double radius) { + circle(radius, true); + } + + /** Draw a circle to the right from the current position with + * turtle's heading tangent direction and given radius. + * Actually a polygon with 36 sides is drawn. + */ + public void rightCircle(double radius) { + circle(radius, false); + } + + private void circle(double radius, boolean left) { + double nbSteps = 36; // 36 side polygon + double angle = 2 * Math.PI / nbSteps; + double step = 2 * radius * Math.sin(angle/2); + for (int i = 0; i < 36; i++) { + if (left) + if (i == 0) + lt(180.0 / nbSteps); + else + lt(360.0 / nbSteps); + else + if (i == 0) + rt(180.0 / nbSteps); + else + rt(360.0 / nbSteps); + fd(step); + } + } + + /** Calculate the number of iterations when animating left or right (rotation). + */ + private int getAngleIterations(double dAngle) { + if(getAngleSpeed()<0){ + return 1; + } + if(getAngleSpeed()==0){ + setAngleSpeed(1); + } + double dAbsAngle = Math.abs(dAngle); + Double dValue = new Double(Math.ceil(dAbsAngle/getAngleSpeed()*getFramesPerSecond())); + return dValue.intValue(); + } + + /** Calculate the number of iterations when animating forwards or backwards. + */ + private int getPathIterations(double length) { + if(speed < 0) + return 1; + + if (speed == 0) + setSpeed(1); + + double dAbsLength = Math.abs(length); + Double dValue = new Double(Math.ceil(dAbsLength/getSpeed()*getFramesPerSecond())); + return dValue.intValue(); + } + + /** Lift the Turtle's pen up so it + won't draw a line anymore. + + This is the same as pu(). + + @see #pu() + @see #penDown() + @see #pd() + */ + public void penUp() { + synchronized (playground) { + this.penUp = true; + } + } + + /** Lift the Turtle's pen up so it + won't draw a line anymore. + + This is the same as penUp(). + + @see #penUp() + @see #penDown() + @see #pd() + */ + public void pu() { + this.penUp(); + } + + /** Lower the Turtle's Pen down so it + will draw a line when moving. + + This is the same as pd(). + + @see #pd() + @see #penUp() + @see #pu() + */ + public void penDown() { + synchronized (playground) { + this.penUp = false; + } + } + + /** Lowers the Turtle's pen down so it + will draw a line when moving. + + This is the same as penDown(). + + @see #penDown() + @see #penUp() + @see #pu() + */ + public void pd() { + this.penDown(); + } + + /** Query the Pen's state (up or down). + + @return true if the Pen is + up, false otherwise. + @see #pu() + @see #pd() + */ + public boolean isPenUp() { + return this.penUp; + } + + /** Return the bounds of this Turtle. This is required + by the methods that (return-)paint the Turtles. + */ + Rectangle getBounds() { + Rectangle rect = new Rectangle(); + + Image img = getTurtleRenderer().currentImage(); + int nWidth = img.getWidth(getTurtleRenderer()); + int nHeight = img.getHeight(getTurtleRenderer()); + double x = (_getX()<0)?Math.floor(_getX()):Math.ceil(_getX()); + double y = (_getY()<0)?Math.floor(_getY()):Math.ceil(_getY()); + rect.setBounds((int)x-nWidth/2, (int)y + nHeight/2, nWidth, nHeight); + return rect; + } + + /** Get the Turtle's Pen. + + You need it if you want to change end caps etc. + @see Pen + */ + public Pen getPen() { + return pen; + } + /** Set the line thickness. + + This works only neatly in clip mode (yet). + @see #clip() + @see #wrap() + */ + public void setLineWidth(double lineWidth){ + synchronized (playground) { + setLineWidth((float)lineWidth); + } + } + + /** Set the line thickness. + + This works only neatly in clip mode (yet). + @see #clip() + @see #wrap() + */ + public void setLineWidth(float lineWidth) { + synchronized (playground) { + getPen().setLineWidth(lineWidth); + } + } + + /** Set the Turtle's color to the specified one. + + */ + public void setColor(Color color) { + synchronized (playground) { + internalSetColor(color); + getPlayground().paintTurtles(); + } + } + + private void internalSetColor(Color color) { + this.color = color; + if (getTurtleRenderer()==null) { + turtleRenderer = createTurtleRenderer(); + getTurtleRenderer().init(getTurtleFactory(), getAngleResolution()); + } + else{ + getTurtleRenderer().init(new TurtleFactory(), + this.angleResolution); + } + } + + /** Set the color to the specified one. + + @see #fill() + */ + public void setFillColor(Color color) { + synchronized (playground) { + getPen().setFillColor(color); + } + } + + /** Query the Turtle's current color. + */ + public Color getColor(){ + return color; + } + + /**Set the Turtle's pen color. + + */ + public void setPenColor(Color color) { + synchronized (playground) { + getPen().setColor(color); + } + } + + /** Move the Turtle back "home", i.e. set its position + to the origin, facing NORTH. + + Color, PenColor etc. remain the same. + */ + public void home() { + // first : clean the Turtle! + synchronized (playground) { + getPlayground().clearTurtle(this); + position = new Point2D.Double(0,0); + setHeading(0); + } + } + + /** The Turtle's Pen is + changed to an eraser (which is in fact a pen with + background color). + + This is the same as pe() + @see #pe() + */ + public void penErase() { + synchronized (playground) { + this.internalPenErase(); + } + } + + /** The Turtle's Pen is + changed to an eraser (which is in fact a pen with + background color). + + This is the same as penErase() + @see #penErase() + */ + public void pe() { + penErase(); + } + + protected void internalPenErase(){ + this.setPenColor(getPlayground().getBackground()); + } + + /** Put the Turtle to a new position with specified + x- and y-coordinates. + */ + public void setPos(double x, double y) { + synchronized (playground) { + getPlayground().clearTurtle(this); + internalSetPos(x, y); + getPlayground().paintTurtles(); + } + } + + /** Put the Turtle to a new position. + */ + public void setPos(Point2D.Double p) { + setPos(p.x, p.y); + } + + /** Put the Turtle to a new screen position. + + */ + public void setScreenPos(Point p) { + setPos(toTurtlePos(p)); + } + + + /** Put a Turtle image at the current position. + + */ + public void stampTurtle() { + synchronized (playground) { + this.getPlayground().stampTurtle(this); + } + } + + /** Calculate the direction to a given point. + + @return the direction from the current turtle position + towards the given point, measured in degrees and clockwise + from the vertical upwards position. + */ + public double towards(double x, double y) { + synchronized (playground) { + double dx = x - getX(); + double dy = y - getY(); + double result = Math.toDegrees(Math.atan2(dx, dy)); + return (result < 0) ? result+360 : result; + } + } + + /** Calculate the direction to a given point. + + @return the direction from the current turtle position + towards the given point, measured in degrees and clockwise + from the vertical upwards position. + */ + public double towards(Point2D.Double p) { + return towards(p.getX(), p.getY()); + } + + /** Put the Turtle to the top (i.e. above any other + turtle). + + Just invokes the toTop-Method in Playground. + @see Playground#toTop + @see #internalToBottom + */ + void internalToTop() { + this.getPlayground().toTop(this); + } + /** Put the Turtle to the bottom (i.e. under any other + turtle). + + Just invokes the toBottom-Method in Playground. + @see Playground#toBottom + @see #internalToTop + */ + void internalToBottom() { + this.getPlayground().toBottom(this); + } + + /** Put this turtle to the bottom. + + So any other turtle in the same Playground will be drawn over it. + */ + public void toBottom() { + // this.getPlayground().toBottom(this); + synchronized (playground) { + internalToBottom(); + getPlayground().paintTurtles(); + } + } + + /** Put this turtle to the top. + + So it will be drawn over any other turtle in the same Playground. + */ + public void toTop() { + // this.getPlayground().toTop(this); + synchronized (playground) { + this.getPlayground().paintTurtles(this); + } + } + + /** Set the pen width. + */ + public void penWidth(int newWidth) { + synchronized (playground) { + penWidth((float)newWidth); + } + } + + /** Internal Method for setting the penWidth. + */ + private void penWidth(float newWidth) { + setLineWidth(newWidth); + } + + /** Query the pen width. + */ + public int penWidth(){ + return (int)this.getPen().getLineWidth(); + } + + /** Returns the current edge behaviour. + + @see #CLIP + @see #WRAP + */ + protected int getEdgeBehaviour() { + return edgeBehaviour; + } + + /** Sets the edge behaviour to the specified value; + + @see #CLIP + @see #WRAP + */ + protected void setEdgeBehaviour(int edgeBehaviour) { + synchronized (playground) { + this.edgeBehaviour = edgeBehaviour; + } + } + + /** Set the Turtle to clip-mode. + @see #wrap() + @see #clip() + */ + public void clip() { + synchronized (playground) { + setEdgeBehaviour(CLIP); + } + } + + /** Cause the Turtle to wrap around the playground borders. + + e.g when as the Turtle leaves the Window on one side, + it reappears on the opposite side. + + @see #clip() + */ + public void wrap() { + synchronized (playground) { + setEdgeBehaviour(WRAP); + } + } + + /** Tell whether the Turtle is in clip mode. + + @return true if in clip mode, false otherwise. + @see #clip() + @see #wrap() + */ + public boolean isClip() { + return (getEdgeBehaviour() == CLIP); + } + /** Tell wheter the Turtle is in wrap mode. + + @return true if in wrap mode, false otherwise. + @see #wrap() + @see #clip() + */ + public boolean isWrap() { + return (getEdgeBehaviour() == WRAP); + } + + /** Fill the region the Turtle is in.
+ + A region is bounded by lines + of any color different to the pixel color at the current turtle position + and by the border of the window.
+ (The pen of the Turtle must be down.) + */ + public void fill() { + synchronized (playground) { + getPlayground().fill(this, getPlayground().getPixelColor(this)); + } + } + + /** Fill the region as if the Turtle where at coordinates x and y.
+ A region is bounded by lines + of any color different to the pixel color at the given position and by the border of + the window.
+ (The pen of the Turtle must be down.) + */ + public void fill(double x, double y) { + synchronized (playground) { + double oldX = getX(); + double oldY = getY(); + boolean hidden = isHidden(); + ht(); + setPos(x,y); + getPlayground().fill(this, getPlayground().getPixelColor(this)); + setPos(oldX, oldY); + if(!hidden){ + st(); + } + } + } + + /** Erase all traces and text painted by the turtles, but let all + * turtles where they are. + + */ + public void clean() { + synchronized (playground) { + getPlayground().clean(); + } + } + + /** Paint the specified text at the current turtle position. + + */ + public void label(String text) { + synchronized (playground) { + if (text != null && text.length() > 0) + getPlayground().label(text, this); + } + } + + /** Set the current font as specified. + + @see java.awt.Font + */ + public void setFont(Font font) { + synchronized (playground) { + getPen().setFont(font); + } + } + + /** Change the current font to the specified one. If you want to know what fonts are available on your system, + call #getAvailableFontFamilies() . + + @see #getAvailableFontFamilies + @see java.awt.Font more information about fontName, style and size. + */ + public void setFont(String fontName, int style, int size) { + synchronized (playground) { + getPen().setFont(new Font(fontName, style, size)); + } + } + + /** Set the font size. + + @see #setFontStyle changing the font style + @see #setFont changing the whole font. + */ + public void setFontSize(int size) { + synchronized (playground) { + getPen().setFontSize(size); + } + } + + /** Set the font style. + + This is either java.awt.Font.PLAIN, java.awt.Font.BOLD, java.awt.Font.ITALIC or java.awt.Font.BOLD+java.awt.Font.ITALIC + @see #setFontSize changing the font size + @see #setFont changing the whole font. + */ + public void setFontStyle(int style) { + synchronized (playground) { + getPen().setFontStyle(style); + } + } + + /** Provide information about all font families (e.g. roman) currently available on your system. + Each font name is a string packed into a array of strings. + (This might be useful when you want to change the font.) + @see #setFont(java.awt.Font) + @see #setFont(java.lang.String, int, int) + */ + public static String[] getAvailableFontFamilies() { + return Pen.getAvailableFontFamilies(); + } + + /** Return the current font. + + @see #setFontSize changing the font size + @see #setFontStyle changing the font style + @see #setFont changing the whole font. + */ + public Font getFont() { + return getPen().getFont(); + } + + /** Creates a clone of the Turtle in it's Playground. + Color, position and heading are the same. + (It's visible and pen is down.) + Return the cloned object reference as a Object type, because + it overrides Object.clone(). + (You may cast it to a Turtle.) + */ + public Object clone() + { + synchronized (playground) { + Turtle t = new Turtle(); + t.setColor(getColor()); + t.setPos(getX(), getY()); + t.heading(heading()); + t.showTurtle(); + return t; + } + } + + /** Set antialiasing on or off for the turtle trace buffer + * This may result in an better image quality, especially + * for filling operations (platform dependant). + */ + public void antiAliasing(boolean on) { + synchronized (playground) { + getPlayground().setAntiAliasing(on); + } + } + + + /** + * Print the graphics context to an attached printer with + * the given magnification scale factor. + * scale = 1 will print on standard A4 format paper.
+ * + * The given tp must implement the GPrintable interface, + * e.g. the single method void draw(), where all the + * drawing into the GPanel must occur. + * + * Be aware the turtle(s) state (position, direction, etc.) + * must be reinitialized, because draw() is called several + * times by the printing system. + * + * A standard printer dialog is shown before printing is + * started. Only turte traces are printed. + *
+ * Example:
+ * + import ch.aplu.turtle.*;
+
+ public class PrintTest implements TPrintable
+ {
+ private Turtle t = new Turtle();
+
+ public PrintTest()
+ {
+ draw(); // Draw on screen
+ t.print(this); // Draw on printer
+ }
+
+ public void draw()
+ {
+ t.home(); // Needed for initialization
+ for (int i = 0; i < 5; i++)
+ t.fd(20).rt(90).fd(20).lt(90);
+ }
+
+ public static void main(String[] args)
+ {
+ new PrintTest();
+ }
+ }
+
+ */ + public boolean print(TPrintable tp, double scale) + { + return getPlayground().print(tp, scale); + } + + /** + * Same as print(tp, scale) with scale = 1. + */ + public boolean print(TPrintable tp) + { + return print(tp, 1); + } + + /** + * Print the Turtle's current playground with given scale. + */ + public boolean printScreen(double scale) + { + return print(null, scale); + } + + /** + * Same as printScreen(scale) with scale = 1. + */ + public boolean printScreen() + { + return printScreen(1); + } + + /** + * Clear the Turtle's playground. All turtle images and traces are erased, + * but the turtles remain (invisible) at their positions. + */ + public void clear() + { + synchronized (playground) { + getPlayground().clear(); + } + } + + /** + * Delay execution for the given amount of time ( in ms ). + */ + public static void sleep(int time) + { + try + { + Thread.currentThread().sleep(time); + } + catch (Exception e) {} + } + + /** + * Return version information + */ + public String version() + { + return SharedConstants.VERSION; + } + + /** + * Enable/disable automatic repainting. + * If disabled, call repaint() to perform repainting. + * Disabling automatic repainting and hiding the + * Turtle speeds up the graphics enormously. + */ + public void enableRepaint(boolean b) + { + getPlayground().enableRepaint(b); + } + + /** + * Perform manual repainting when automatic repainting is + * disabled. + */ + public void repaint() { + getPlayground().repaint(); + } + + /** + * Return the color of the pixel at the current turtle position. + */ + public Color getPixelColor() { + synchronized (playground) { + return getPlayground().getPixelColor(this); + } + } + + protected Graphics getGraphics() { + return playground.getGraphics(); + } + + /** + * Transforms the gui-position to mouse-coordinates. + */ + public void setBounds(int x, int y, int b, int h) { + int ox = playground.getOriginX(); + int oy = playground.getOriginY(); + x = -ox + x + 10; + y = oy - y - 13; + setPos(x, y); + } + + /** + * Shows or hides the turtle. + */ + public void setVisible(boolean show) { + if (show) { + showTurtle(); + } else { + hideTurtle(); + } // end of if-else + } + + /** + * Sets clipping-mode on/off. + */ + public void setClip(boolean clip) { + if (clip) { + clip(); + } else { + wrap(); + } // end of if-else + } + + /** + * Sets pen-position up/down. + */ + public void setPenUp(boolean penup) { + if (penup) { + penUp(); + } else { + penDown(); + } // end of if-else + } + + /** + * Sets angle of the turtle. + */ + public void setAngle(int angle) { + setHeading(angle); + } +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/turtlefactory.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/turtlefactory.java new file mode 100644 index 0000000..e9d700e --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/turtlefactory.java @@ -0,0 +1,66 @@ +// TurtleFactory.java + +// Copyright 2002 Regula Hoefer-Isenegger +// +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import java.awt.image.*; +import java.awt.*; + +class TurtleFactory +{ + /** Generates the shape of the turtle with color, + * angle angle, width w + * and height h. + */ + protected Image turtleImage(Color color, double angle, int w, int h) + { + BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR); + Graphics2D g = (Graphics2D)bi.getGraphics(); + // Origin in center + g.translate(w/2, h/2); + // angle = 0 is direction east (as usual in mathematics) + g.rotate(Math.PI/2 - angle); + g.setColor(color); + + // Body + g.fillOval((int)( -0.35 * w), (int)( -0.35 * h), + (int)(0.7 * w), (int)(0.7 * h)); + + // Head + g.fillOval((int)( -0.1 * w), (int)( -0.5 * h), + (int)(0.2 * w), (int)(0.2 * h)); + + // Tail + int[] xcoords = + {(int)( -0.05 * w), 0, (int)(0.05 * w)}; + int[] ycoords = + {(int)(0.35 * h), (int)(0.45 * h), (int)(0.35 * h)}; + g.fillPolygon(xcoords, ycoords, 3); + + // Feet + for (int i = 0; i < 4; i++) + { + g.rotate(Math.PI / 2); + g.fillOval((int)( -0.35 * w), (int)( -0.35 * h), + (int)(0.125 * w), (int)(0.125 * h)); + } + return (Image)bi; + } +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/turtlerenderer.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/turtlerenderer.java new file mode 100644 index 0000000..9489e78 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/ch/aplu/turtle/turtlerenderer.java @@ -0,0 +1,312 @@ +// TurtleRenderer.java + +// Copyright 2002 Regula Hoefer-Isenegger +// Some modifications by Aegidius Pluess + +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.awt.image.*; +import java.awt.*; +import javax.swing.*; +import java.awt.geom.*; +import java.util.*; + + +/** This class is responsible for creating and choosing the correct Turtle picture. + @author Regula Hoefer-Isenegger + @version 0.1 +*/ +public class TurtleRenderer implements ImageObserver { + /** Holds the current image */ + private Image currentImage; + /** Holds all images */ + private Vector images; + /** Tells how many pictures are needed*/ + private int resolution; + /** A reference to the Turtle */ + private Turtle turtle; + /** Holds the current Angle */ + private double currentAngle; + + private final int turtleSize = 29; + + /***/ + public TurtleRenderer(Turtle turtle) { + this.currentImage = null; + this.images = new Vector(); + this.turtle = turtle; + currentAngle = 0; + } + + /** As an image stays unchanged, there's no need to ever update it. So this method returns always false. + + For further information cf. java.awt.image.ImageObserver. + @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) + */ + public boolean imageUpdate(Image img, int infoflags, + int x, int y, int width, int height) { + return false; + } + + /** Return the current image. + */ + public Image currentImage() { + return this.currentImage; + } + + /** Tell whether the image has changed. + */ + public boolean imageChanged(double angle) { + return (this.currentImage != getImage(angle)); + } + + /** Set the current image to the specified one. */ + private void setCurrentImage(Image image) { + currentImage = image; + } + + /** Choose the image for the angle angle. + */ + private Image getImage(double angle) { + while (angle < 0) { + angle += 2*Math.PI; + } + while (angle >= 2*Math.PI) { + angle -= 2*Math.PI; + } + double res = 2*Math.PI/(double)this.resolution; + int index = (int)(angle/res); + return image(index); + } + + /** Set the current image to the one corresponding to the angle angle. + */ + public void setAngle(double angle) { + currentAngle = angle; + setCurrentImage(getImage(angle)); + } + + /** @return the current angle. */ + protected double getAngle(){ + return currentAngle; + } + + /** Create the images. There are resolution images (i.e. two subsequent + images contain an angle of 2π/ or 360/resolution degrees). + */ + public void init(TurtleFactory factory, int resolution) { + this.resolution = resolution; + Integer res = new Integer(resolution); + double incRes = Math.PI*2/res.doubleValue(); + double angle = 0; + images = new Vector(); + for (int i = 0; i < resolution; i++) { + images.add(factory.turtleImage(turtle.getColor(), + turtle.getPlayground().toScreenAngle(angle), + turtleSize, turtleSize)); + angle += incRes; + } + setCurrentImage(getImage(currentAngle)); + } + + /** Tell how many images this TurtleRenderer holds */ + private int countImages() { + return this.images.size(); + } + + /** Get the image at index */ + private Image image(int index) { + return (Image)this.images.elementAt(index); + } + + /** This method is responsible for painting the turtle onto the + playground at (x, y). + */ + public final void paint(double x, double y) { + internalPaint(x, y, turtle.getPlayground().getGraphics()); + } + + /** This method is responsible for painting the turtle onto the + playground at p. + */ + public final void paint(Point2D.Double p) { + internalPaint(p.x, p.y, turtle.getPlayground().getGraphics()); + } + + /** This method is responsible for painting the Turtle + at (x, y).
+ The Graphics argument tells where to paint. + */ + public final void paint(double x, double y, Graphics g) { + internalPaint(x, y, g); + } + + /** This method is responsible for painting the Turtle + at p.
+ The Graphics argument tells where to paint. + */ + public void paint(Point2D.Double p, Graphics g){ + internalPaint(p.x, p.y, g); + } + + /** Call clipPaint and wrapPaint(). + + You should override this method only, if you add a new (edge) + behaviour to the turtle. I recommend to you then to first call this + method from the overriding one. +
+ If you want to change anything about the real painting, override + clipPaint or wrapPaint. + + @see #clipPaint(int, int, Graphics2D) + @see #wrapPaint(int, int, Graphics2D) + */ + protected void internalPaint(double x, double y, Graphics g) { + if(turtle.isClip()){ + Point2D.Double p = + calcTopLeftCorner(turtle.getPlayground().toScreenCoords(x, y)); + clipPaint((int)p.x, (int)p.y, (Graphics2D)g); + } + else if(turtle.isWrap()){ + Point2D.Double p = + calcTopLeftCorner(turtle.getPlayground().toScreenCoords(x, y)); + wrapPaint((int)p.x, (int)p.y, (Graphics2D)g); + } + } + + /** Define how to paint in clip mode and do it */ + protected void clipPaint(int x, int y, Graphics2D g2D) { + g2D.drawImage(currentImage, x, y, this); + } + + /** Define how to paint in wrap mode and do it */ + protected void wrapPaint(int x, int y, Graphics2D g2D) { + int pWidth = turtle.getPlayground().getWidth(); + int pHeight = turtle.getPlayground().getHeight(); + int paintX = x; + while (paintX > pWidth) { + paintX -= pWidth; + } + while (paintX < 0) { + paintX += pWidth; + } + int paintY = y; + while (paintY > pHeight) { + paintY -= pHeight; + } + while (paintY < 0) { + paintY += pHeight; + } + g2D.drawImage(currentImage, paintX, paintY, this); + int nWidth = currentImage.getWidth(this); + int nHeight = currentImage.getHeight(this); + boolean right = (paintX+nWidth > pWidth); + boolean bottom = (paintY+nHeight > pHeight); + if(right) { + g2D.drawImage(currentImage, + paintX-pWidth, + paintY, + this); + } + if(bottom) { + g2D.drawImage(currentImage, + paintX, + paintY-pHeight, + this); + } + if(right && bottom) { + g2D.drawImage(currentImage, + paintX-pWidth, + paintY-pHeight, + this); + } + } + + /** Compute the x-coordinate of the top left corner of the Turtle image + (it depends on the specified x-coordinate and the image width). + */ + protected int calcTopLeftCornerX(double x) { + int intX = (int)x; + int nWidth; + if(currentImage == null) { + setCurrentImage(new TurtleFactory(). + turtleImage(turtle.getColor(), getAngle(), turtleSize, turtleSize)); + } + nWidth = this.currentImage.getWidth(this); + // the center of the turtle lies on the turtle's location: + intX -= nWidth/2; + return intX; // top left corner of the Turtle's image + } + + /** Compute the y-coordinate of the top left corner of the Turtle image + (it depends on the specified y-coordinate and the image height). + */ + protected int calcTopLeftCornerY(double y) { + int intY = (int)y; + if(currentImage == null) { + setCurrentImage(new TurtleFactory(). + turtleImage(turtle.getColor(), getAngle(), turtleSize, turtleSize)); + } + int nHeight = currentImage.getHeight(this); + // the center of the turtle lies on the turtle's location: + intY -= nHeight/2; + + return intY; // top left corner of the Turtle's image + } + /** Compute the top left corner of the Turtle image + (dependent on the specified x- and y-coordinate and the image + width and height. + */ + protected Point2D.Double calcTopLeftCorner(double x, double y) { + if(currentImage == null) { + setCurrentImage(new TurtleFactory(). + turtleImage(turtle.getColor(), getAngle(), turtleSize, turtleSize)); + } + int w = currentImage.getWidth(this); + int h = currentImage.getHeight(this); + return new Point2D.Double(x-w/2, y-h/2); + } + + /** Compute the top left corner of the Turtle image + (dependent on the specified point p and the image + width and height. + */ + protected Point2D.Double calcTopLeftCorner(Point2D.Double p) { + return calcTopLeftCorner(p.x, p.y); + } +} + + + + + + + + + + + + + + + + + + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/eval.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/eval.java new file mode 100644 index 0000000..97c8ff0 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/eval.java @@ -0,0 +1,50 @@ +public class Eval { + + public static Wrap getOb(Object o) { + return new Wrap(o); + } + + protected static Object getOb(final String s) { + return new Object() {public String result = s;}; + } + + protected static Object getOb(final boolean b) { + return new Object() {public boolean result = b;}; + } + + protected static Object getOb(final byte b) { + return new Object() {public byte result = b;}; + } + + protected static Object getOb(final char c) { + return new Object() {public char result = c;}; + } + + protected static Object getOb(final double d) { + return new Object() {public double result = d;}; + } + + protected static Object getOb(final float f) { + return new Object() {public float result = f;}; + } + + protected static Object getOb(final int i) { + return new Object() {public int result = i;}; + } + + protected static Object getOb(final long l) { + return new Object() {public long result = l;}; + } + protected static Object getOb(final short s) { + return new Object() {public short result = s;}; + } +} + + +class Wrap { + public Object result; + + Wrap(Object result) { + this.result = result; + } +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/inout.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/inout.java new file mode 100644 index 0000000..d702d54 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/inout.java @@ -0,0 +1,98 @@ +import java.io.*; + +/** +Support class for console input and output of numeric values.

+ +Example for input:
+ int age = InOut.readInt("Your age: ");

+ +Example for output:
+ System.out.println("price: " + InOut.format2(prize) + "Euro");
+ System.out.println("percent: " + InOut.formatN(percent, 1) + " %"); +*/ + + +public class InOut { + + /** Formats a double-value with 2 decimal digits. */ + public static String format2(double d) { + return String.format("%.2f", d); + } + + /** Formats a double-value with N decimal digits. */ + public static String formatN(double d, int N) { + return String.format("%." + N + "f", d); + } + + /** Reads a boolean-value from console. */ + public static boolean readBoolean(String prompt) { + final String[] trueValues = + { "1", "y", "t", "j", "w", "yes", "true", "ja", "wahr", "ok" }; + System.out.print(prompt); + String input = readln().toLowerCase(); + for (int i = 0; i < trueValues.length; ++i) + if (trueValues[i].equals(input)) + return true; + return false; + } + + /** Reads a char-value from console. */ + public static char readChar(String prompt) { + System.out.print(prompt); + return readln().charAt(0); + } + + /** Reads a double-value from console. */ + public static double readDouble(String prompt) { + System.out.print(prompt); + return Double.parseDouble(readln()); + } + + /** Reads a float-value from console. */ + public static float readFloat(String prompt) { + System.out.print(prompt); + return Float.parseFloat(readln()); + } + + /** Reads an int-value from console. */ + public static int readInt(String prompt) { + System.out.print(prompt); + return Integer.parseInt(readln()); + } + + /** Reads a long-value from console. */ + public static long readLong(String prompt) { + System.out.print(prompt); + return Long.parseLong(readln()); + } + + /** Reads a string-value from console. */ + public static String readString(String prompt) { + System.out.print(prompt); + return readln(); + } + + /** Reads a string-value from console without prompt. + For use at the end of a console program. */ + public static String readln() { + try { + return Input.readLine(); + } catch(Exception e) { + return ""; + } + } + + private static BufferedReader Input; + + static { + try { + Input = new BufferedReader(new InputStreamReader(System.in)); + } + catch (Exception e) { + System.out.println("console input not possible."); + } + } + + + +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/je/util/turtle.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/je/util/turtle.java new file mode 100644 index 0000000..4a704ad --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/je/util/turtle.java @@ -0,0 +1,311 @@ +package je.util; +/* + * Class : Turtle + * Copyright: (c) Gerhard Röhner + * + * History + * -------- + * 3.00 2000.10.10 first version as java class + * 3.01 2002.10.22 DrawDynamic + * 3.02 2010.10.11 sleepTime for paint delay + * 3.03 2012.03.20 cartesian coordinate system, used with originX, originY, setOrigin + * 3.04 2015.01.24 english version, integrated component + */ + + +import java.awt.*; +import java.awt.image.*; +import java.awt.event.*; + +/** + * This class is a turtle component for simple graphic programming. + * + * @see + * @author Gerhard Röhner + * @version 3.03 20/03/2012 + */ + + +public class Turtle extends Canvas { + + // -- private Attribute ------------------------------------------------------ + + private BufferedImage myBufferedImage; + private Graphics myBufferedGraphics; + private Color foreground; + private Color background; + private static final double piDurch180 = Math.PI / 180; + + // -- public attributes ----------------------------------------------------- + + /** + * turtleX is the x-coordinate of the turtle + *

+ * Example:

myTurtle.turtleX = 100;
+ */ + public double turtleX; + + /** + * turtleY is the y-coordinate of the turtle. + *

+ * Example:

myTurtle.turtleY = 200;
+ */ + public double turtleY; + + /** + * turtleW is the current angle of the turtle in the range form 0 to 360 degrees. + *

+ * Example:

myTurtle.turtleW = 180;
+ */ + public double turtleW; + + /** + * originX is the x-position of the cartesian coodinate system within the turtle canvas. + *

+ * Example:

myTurtle.originX = 0;
+ */ + public double originX; + + /** + * originY is the y-position of the cartesian coodinate system within the turtle canvas. + *

+ * Example:

myTurtle.originY = 100;
+ */ + public double originY; + + /** + * If drawDynamic is true you can watch the drawing of the turtle. + *

+ * Example:

myTurtle.drawDynamic = true;
+ */ + public boolean drawDynamic; + + /** + * For drawDynamic = true you set the delay in milliseconds for drawing. + *

+ * Example:

myTurtle.sleepTime = 500;
+ */ + public int sleepTime = 0; + + // --- constructor ----------------------------------------------------------- + + /** + * Creates a Turtle with a canvas. + * At the beginning the Turtle is placed in the middle of it's canvas. + * The start angle is 0 degree, which means the Turtle looks to the right. + * The background color is white, the drawing color black. + *

+ * The turtle position can easily be changed by clicking into the canvas. + *

+ * The size of the canvas can easily be changed with the mouse. + *

+ * Example:

Turtle myTurtle = new Turtle();
+ */ + + public Turtle() { + myBufferedImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); + myBufferedGraphics = myBufferedImage.getGraphics(); + + setForeground(Color.black); + setBackground(Color.white); + drawDynamic = true; + + addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent evt) { + turtleMouseClicked(evt);}}); + addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent evt) { + turtleResized(evt);}}); + setOrigin(50, 50); + } + + private void turtleMouseClicked(MouseEvent evt) { + turtleX = evt.getX() - originX; + turtleY = originY - evt.getY(); + turtleW = 0; + } + + private void turtleResized(ComponentEvent evt) { + int width = getWidth(); + int height = getHeight(); + + BufferedImage newBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics newGraphics = newBufferedImage.getGraphics(); + newGraphics.setColor(background); + newGraphics.fillRect(0, 0, width, height); + newGraphics.setColor(foreground); + newGraphics.drawImage(myBufferedImage, 0, 0, this); + + turtleX = 0; + turtleY = 0; + turtleW = 0; + setOrigin(width / 2, height / 2); + + myBufferedImage = newBufferedImage; + myBufferedGraphics = newGraphics; + } + + public boolean isDoubleBuffered() { + return true; + } + + private void wTurtleMod360() { + while (turtleW >= 360) + turtleW = turtleW - 360; + while (turtleW < 0) + turtleW = turtleW + 360; + } + + // --- angle and turns ------------------------------------------------------- + + /** + * Turns the angle of the turtle relativ by the parameter angle. + * Positive values means a turn right, negative a turn left. + *

+ * Example:

myTurtle.turn(-90);
+ */ + public void turn(double angle) { + turtleW = turtleW + angle; + wTurtleMod360(); + } + + /** + * Sets the angle of the turtle absolute by the parameter angle. + * The angle increases counterclockwise, therefore + * right = 0, top = 90, left = 180, bottom = 270. + *

+ * Example:

myTurtle.turnto(270);
+ */ + public void turnto(double angle) { + turtleW = angle; + wTurtleMod360(); + } + + // --- Drawing --------------------------------------------------------------- + + /** + * The Turtle draws a line of the length specified in the current direction. + *

+ * Example:

myTurtle.draw(100);
+ */ + public void draw(double length) { + drawto(turtleX + length * Math.cos(turtleW * piDurch180), + turtleY + length * Math.sin(turtleW * piDurch180)); + } + + /** + * The Turtle draws a line form the current position (turtleX, turtleY) to the + * position (x, y) relativ to the cartesian coordinate system. + *

+ * Example:

myTurtle.drawto(200, 300);
+ */ + public void drawto(double x, double y) { + int x1 = (int) (originX + turtleX); + int x2 = (int) (originX + x); + int y1 = (int) (originY - turtleY); + int y2 = (int) (originY - y); + + myBufferedGraphics.drawLine(x1, y1, x2, y2); + if (drawDynamic){ + getGraphics().drawLine(x1, y1, x2, y2); + try { + Thread.currentThread().sleep(sleepTime); + } catch(InterruptedException e) { + } + } else + repaint(); + + turtleX = x; + turtleY = y; + } + + // --- Moving ---------------------------------------------------------------- + + /** + * The Turtle moves without drawing the length specified in the current + * direction. + *

+ * Example:

myTurtle.move(100);
+ */ + public void move(double length) { + turtleX = turtleX + length * Math.cos (turtleW * piDurch180); + turtleY = turtleY + length * Math.sin (turtleW * piDurch180); + } + + /** + * The Turtle moves without drawing to position (x, y) relativ to the + * cartesian coordinate system. + *

+ * Example:

myTurtle.moveto(100, 200);
+ */ + public void moveto(double x, double y) { + turtleX = x; + turtleY = y; + } + + // --- set origin ----------------------------------------------------------- + + /** + * Sets the origin of the cartesian coordinate system within the turtle's canvas. + *

+ * Example:

myTurtle.setOrigin(100, 200);
+ */ + public void setOrigin(double x, double y) { + originX = x; + originY = y; + } + + // --- fore- and background color -------------------------------------------- + + /** + * Sets the drawing color of the Turtle to color c. + *

+ * Example:

myTurtle.setForeground(Color.red);
+ */ + public void setForeground(Color c) { + foreground = c; + myBufferedGraphics.setColor(foreground); + super.setForeground(foreground); + } + + /** + * Sets the canvas color of the Turtle to color c. + *

+ * Example:

myTurtle.setBackground(Color.blue); 
+ */ + public void setBackground(Color c) { + background = c; + myBufferedGraphics.setColor(background); + myBufferedGraphics.fillRect(0, 0, getWidth(), getHeight()); + myBufferedGraphics.setColor(foreground); + repaint(); + } + + /** + * Clear the Turtle's canvas with the background color. + *

+ * Example:

myTurtle.clear();
+ */ + public void clear() { + setBackground(background); + getGraphics().drawImage(myBufferedImage, 0, 0, this); + repaint(); + } + + // --- Showing -------------------------------------------------------------- + + /** + * Shows the Turtle's canvas. + */ + public void paint(Graphics g) { + g.drawImage(myBufferedImage, 0, 0, this); + } + + /** + * Updates the Turtle's canvas. + */ + public void update(Graphics g) { + paint(g); + } + +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses.jar b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses.jar new file mode 100644 index 0000000000000000000000000000000000000000..7fa4892e3be6820a600278da2bd9b148d71d71da GIT binary patch literal 90273 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 Q1^hQi2Y{W+;M)N3FGnMA&j0`b literal 0 HcmV?d00001 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/package.bluej b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/package.bluej new file mode 100644 index 0000000..e69de29 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/linerenderer.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/linerenderer.java new file mode 100644 index 0000000..52eceef --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/linerenderer.java @@ -0,0 +1,210 @@ +// LineRenderer.java + +// Copyright 2002 Regula Hoefer-Isenegger +// +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.awt.geom.*; +/** This class is responsible for drawing the turtle's lines. + +@author
Regula Hoefer-Isenegger +@version 0.1 +*/ +public class LineRenderer { + private Point2D.Double point; + private Turtle turtle; + + LineRenderer(Turtle turtle) { + this.point = new Point2D.Double(); + this.turtle = turtle; + } + + /** Initialisation with coordinates x and + y. + */ + public void init(double x, double y) { + this.point.setLocation(x, y); + } + /** Same as init(double x, double y), but with a Point2D.Double + argument for convenience + */ + public void init(Point2D.Double p) { + this.init(p.x, p.y); + } + /** Get the current x-coordinate in screen coordinates.*/ + private double getX(){ + return (toScreenCoords(point)).getX(); + } + /** Get the current x-coordinate in screen coordinates.*/ + private double getY(){ + return toScreenCoords(point).getY(); + } + /** Calls the clipLineTo and wrapLineTo methods, according + to the turtle's edge behavior. + + Only overwrite this method when working with another + (one that you have defined) edge behaviour.
+ If you mean to change the manner of drawing lines, do this in + the methods clipLineTo() and wrapLineTo(). + @see #clipLineTo + @see #wrapLineTo + */ + protected void internalLineTo(double x, double y){ + Point2D.Double screenPos = toScreenCoords(x, y); + if(turtle.isClip()){ + clipLineTo(screenPos.getX(), screenPos.getY()); + } + if (turtle.isWrap()){ + wrapLineTo(screenPos.getX(), screenPos.getY()); + } + init(x,y); + } + /** Calls the internalLineTo(x,y), which does the actual painting. + */ + public void lineTo(double x, double y) { + internalLineTo(x, y); + } + /** Calls the internalLineTo(x,y), which does the actual painting. + + This method works the same way as lineTo(double x, double y), but + is added for convenience. + */ + public void lineTo(Point2D.Double p) { + internalLineTo(p.getX(), p.getY()); + } + /** Does the actual painting for clip mode. + + It works already with ScreenCoords! + For further comments cf. internalLineTo(double x, double y). + @see #internalLineTo + */ + protected void clipLineTo(double x, double y){ + turtle.getPlayground().lineTo(getX(), getY(), x, y, turtle.getPen()); + } + /** Does the actual painting for wrap mode. + + It works already with ScreenCoords! + For further comments cf. internalLineTo(double x, double y). + @see #internalLineTo + */ + protected void wrapLineTo(double x, double y){ + double dx = getX() - x; + double dy = getY() - y; + Point2D.Double start = new Point2D.Double(x, y); + Point2D.Double end = new Point2D.Double(start.x+dx, start.y+dy); + + intoPanel(start, end); + Point2D.Double tmp; + while ((tmp = calcIntersection(start.x, start.y, end.x, end.y)) != null){ + turtle.getPlayground().lineTo(start.x, start.y, tmp.getX(), tmp.getY(), turtle.getPen()); + start = tmp; + intoPanel(start, end); + dx = end.x - start.x; + dy = end.y - start.y; + } + + turtle.getPlayground().lineTo(start.x, start.y, end.x, end.y, turtle.getPen()); + } + /** Makes the coordinates fit into the Panel. + + Well, this is some sort of modulus calculation. + */ + private void intoPanel(Point2D.Double start, Point2D.Double end){ + int pWidth = turtle.getPlayground().getWidth(); + int pHeight = turtle.getPlayground().getHeight(); + while(start.x < 0){ + start.x += pWidth; + end.x += pWidth; + } + while (start.x > pWidth){ + start.x -= pWidth; + end.x -= pWidth; + } + if(start.x == 0 && end.x < start.x){ + start.x += pWidth; + end.x += pWidth; + } + if(start.x == pWidth && end.x > start.x){ + start.x -= pWidth; + end.x -= pWidth; + } + while(start.y < 0){ + start.y += pHeight; + end.y += pHeight; + } + while (start.y > pHeight){ + start.y -= pHeight; + end.y -= pHeight; + } + if(start.y == 0 && end.y < start.y){ + start.y += pHeight; + end.y += pHeight; + } + if(start.y == pHeight && end.y > start.y){ + start.y -= pHeight; + end.y -= pHeight; + } + + } + /** Intersection line with playground-edges + (startX / startY) MUST lie in the playground! + */ + private Point2D.Double calcIntersection(double startX, double startY, double endX, double endY){ + double dx = endX - startX; + double dy = endY - startY; + double W = turtle.getPlayground().getWidth(); + double H = turtle.getPlayground().getHeight(); + if(endX < 0){ + if((dy/dx <= startY/startX) && (dy/dx >= -(H-startY)/startX)){ // links + return new Point2D.Double(0, startY-startX*dy/dx); + } + } + else if(endX > W){ + if((dy/dx >= -startY/(W-startX)) && (dy/dx <= (H-startY)/(W-startX))){// rechts + return new Point2D.Double(W, startY+(W-startX)*dy/dx); + } + } + if(endY < 0){ // oben + return new Point2D.Double(startX-startY*dx/dy, 0); + } + else if(endY > H){ // unten + return new Point2D.Double(startX+(H-startY)*dx/dy, H); + } + else{ + return null; // Endpoint lies in the window + } + } + /** Calculates the screen coordinates of the turtle's actual + position according to the interpretation of the playground. + */ + private Point2D.Double toScreenCoords(double x, double y){ + return turtle.getPlayground().toScreenCoords(x, y); + } + /** Calculates the screen coordinates of the turtle's actual + position according to the interpretation of the playground. + + Added for convenience. + @see #toScreenCoords(double, double) + */ + private Point2D.Double toScreenCoords(Point2D.Double p){ + return turtle.getPlayground().toScreenCoords(p.x, p.y); + } +} + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/package.bluej b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/package.bluej new file mode 100644 index 0000000..e69de29 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/pen.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/pen.java new file mode 100644 index 0000000..8fcc8b7 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/pen.java @@ -0,0 +1,268 @@ +// Pen.java + +// Copyright 2002 Regula Hoefer-Isenegger +// +// This file is part of The Java Turtle package (TJT) +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.awt.Color; +import java.awt.BasicStroke; +import java.awt.Stroke; +import java.awt.Font; +import java.awt.GraphicsEnvironment; + +/** The Pen class provides anything used for drawing the lines, such as line width, + pen color, end caps, dashed lines, etc. + + @see java.awt.BasicStroke + + @author Regula Hoefer-Isenegger + @version 0.1.1 +*/ +public class Pen +{ + /* Attributes *********************************************/ + + /** The default font that is used when drawing Text. + + First argument must be one of "Serif", "SansSerif", "Monotyped", "Dialog" or "DialogInput" + to guarantee that this font exists on all systems. + + @see java.awt.Font for more information, e.g. on font styles. + + */ + public static Font DEFAULT_FONT = new Font("SansSerif", Font.PLAIN, 24); + private Color color; + private Color fillColor; + private BasicStroke stroke; + private Font font; + + /* Constructors *******************************************/ + /** Constructor with standard Color and standard Stroke. + + @see java.awt.BasicStroke + */ + public Pen(){ + color = Color.black; + setFillColor(Color.black); + stroke = new BasicStroke(); + font = DEFAULT_FONT; + } + /** Constructor with Color color and standard Stroke. + + @see java.awt.BasicStroke + */ + public Pen(Color color){ + this.color = color; + setFillColor(color); + stroke = new BasicStroke(); + font = DEFAULT_FONT; + } + /* Methods ************************************************/ + /** Query the Pens color.*/ + public Color getColor(){ + return color; + } + /** Set the Pens color.*/ + public void setColor(Color color){ + this.color = color; + } + /** Set the Pens fill color. + */ + public void setFillColor(Color color){ + this.fillColor = color; + } + /** Query the Pens fill color.*/ + public Color getFillColor(){ + return this.fillColor; + } + /** Get the Pens Stroke + + @see BasicStroke + @see Stroke + */ + public Stroke getStroke(){ + return stroke; + } + /** Query the Pens line width*/ + public float getLineWidth(){ + return stroke.getLineWidth(); + } + /** Query the Pens end cap style. + + @see java.awt.BasicStroke + */ + public int getEndCap(){ + return stroke.getEndCap(); + } + /** Query the Pens line join style. + + @see java.awt.BasicStroke + */ + public int getLineJoin(){ + return stroke.getLineJoin(); + } + /** Query the Pens miter limit style. + + @see java.awt.BasicStroke + */ + public float getMiterLimit(){ + return stroke.getMiterLimit(); + } + /** Query the Pens dash array. + + @see java.awt.BasicStroke + */ + public float[] getDashArray(){ + return stroke.getDashArray(); + } + /** Query the Pens dash phase. + + @see java.awt.BasicStroke + */ + public float getDashPhase(){ + return stroke.getDashPhase(); + } + + /** Set the Pens line width. */ + public void setLineWidth(float width){ + stroke = new BasicStroke((float)width, + stroke.getEndCap(), + stroke.getLineJoin(), + stroke.getMiterLimit(), + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens end cap style. + + @see java.awt.BasicStroke + */ + public void setEndCap(int endCap){ + stroke = new BasicStroke(stroke.getLineWidth(), + endCap, + stroke.getLineJoin(), + stroke.getMiterLimit(), + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens line join style. + + @see java.awt.BasicStroke + */ + public void setLineJoin(int join){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + join, + stroke.getMiterLimit(), + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens miter limit. + + @see java.awt.BasicStroke + */ + public void setMiterLimit(float miterlimit){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + stroke.getLineJoin(), + miterlimit, + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens dash array. + + @see java.awt.BasicStroke + */ + public void setDash(float[] dashArray){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + stroke.getLineJoin(), + stroke.getMiterLimit(), + dashArray, + stroke.getDashPhase()); + } + /** Set the Pens dash phase. + + @see java.awt.BasicStroke + */ + public void setDashPhase(float dashPhase){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + stroke.getLineJoin(), + stroke.getMiterLimit(), + stroke.getDashArray(), + dashPhase); + } + /** Provides information about the currently available font families (e.g. "Roman"). + Each font name is a string packed into a array of strings. + @see java.awt.Font for more information about font attributes etc. + */ + public static String[] getAvailableFontFamilies(){ + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + String s[] = ge.getAvailableFontFamilyNames(); + return s; + } + /** Change the font style. + + @see java.awt.Font for possible styles. + */ + public void setFontStyle(int style){ + font = font.deriveFont(style); + } + /** Change the font size (in points). + */ + public void setFontSize(int size){ + font = font.deriveFont((float)size); + } + /** Change the font size (in points). + You will probably only need the int version setFontSize(int). + */ + public void setFontSize(float size){ + font = font.deriveFont(size); + } + /** Query the size (in points, rounded to int) of the current font. + */ + public int getFontSize(){ + return font.getSize() ; + } + /** Change the font to the given one. + */ + public void setFont(Font f){ + font = f; + } + /** Query the current font. + */ + public Font getFont(){ + return font; + } +} + + + + + + + + + + + + + + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/playground.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/playground.java new file mode 100644 index 0000000..6c0db5b --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/playground.java @@ -0,0 +1,789 @@ +// Playground.java + +// Copyright 2002 Regula Hoefer-Isenegger +// Major code modifications by Aegidius Pluess +// Adaption for the Java-Editor by Gerhard Röhner +// +// This file is part of The Java Turtle package (TJT) +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.util.*; +import javax.swing.*; +import java.awt.*; +import java.awt.print.*; +import java.awt.geom.*; +import java.awt.image.*; +import java.awt.font.*; + +/** + A Playground is the Turtle's home, i.e. the Turtle lives + and moves in the Playground. + + ThePlayground is responsible for interpreting angle and position of the + Turtle and for choosing the correct turtle image and putting it on the right + spot of the Playground. This means: e.g. whenever you wish to switch the x- and y-axis, you + should do it in this class, and not in the Turtle class. + + @author Regula Hoefer-Isenegger + @version 0.1.1 +*/ + +public class Playground extends JPanel implements Printable { + + /** Hold the Turtles of this Playground. */ + private Vector turtles; + + /** Hold the offscreen buffer and graphics context + * where Turtle traces are drawn. + */ + private BufferedImage traceBuffer = null; + protected Graphics2D traceG2D = null; + private Dimension playgroundSize; + + /** Hold the offscreen buffer and graphics context + * of the Turtles images. + */ + private BufferedImage turtleBuffer = null; + protected Graphics2D turtleG2D = null; + + /** Flag to tell whether we have at least one Turtle shown. */ + private boolean isTurtleVisible = false; + + /** Flag to tell whether we use automatic repainting */ + private boolean isRepainting = true; + + /** The default background color. + */ + protected static Color DEFAULT_BACKGROUND_COLOR = Color.white; + + private double printerScale = 1; // Default printer scaling + private TPrintable traceCanvas; // Store ref to user class + private Graphics2D printerG2D = null; + private boolean isPrintScreen = false; // Indicate we are printing the playground + private double printerScaleFactor = 1.1; // Magnification factor for printer + + /** + * originX is the x-position of the cartesian coodinate system within the playground. + */ + public int originX; + + /** + * originY is the y-position of the cartesian coodinate system within the playground. + */ + public int originY; + + private static Color[] ColorArray = {Color.cyan, Color.red, Color.green, Color.blue, Color.yellow, + Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.black, Color.gray + }; + + /** + * Create a Playground with default background color. + * e.g. creates a new vector (which holds the + * Turtles), + */ + public Playground() { + turtles = new Vector(); + setDoubleBuffered(false); + setBackground(DEFAULT_BACKGROUND_COLOR); + initBuffers(new Dimension(100, 100)); + } + + /** + * Initializes the offscreen buffers and sets the size. + */ + protected void initBuffers(Dimension size) { + Color bkColor = getBackground(); + playgroundSize = size; + traceBuffer = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); + traceG2D = traceBuffer.createGraphics(); + traceG2D.setColor(bkColor); + traceG2D.fillRect(0, 0, size.width, size.height); + traceG2D.setBackground(bkColor); + + turtleBuffer = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); + turtleG2D = turtleBuffer.createGraphics(); + turtleG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + originX = size.width/2; + originY = size.height/2; + } + + /** Add a new Turtle to the Playground. + */ + public void add(Turtle turtle) { + turtles.add(turtle); + turtle.setPlayground(this); + int i = turtles.size(); + while (i > 10) { + i = i - 10; + } // end of while + turtle.init(ColorArray[i-1]); + toTop(turtle); + } + + public void setBounds(int x, int y, int width, int height) { + super.setBounds(x, y, width, height); + initBuffers(new Dimension(width, height)); + } + + /** Remove a Turtle from the Playground. + */ + public void remove(Turtle turtle) { + turtles.remove(turtle); + } + + /** Tell current number of Turtles in this Playground. + */ + public int countTurtles() { + return turtles.size(); + } + + /** Return the Turtle at index index. + */ + public Turtle getTurtle(int index) { + return turtles.elementAt(index); + } + + /** Move the given Turtle above all the others, then + paints all turtles. + @see #toTop + */ + public void paintTurtles(Turtle turtle) { + toTop(turtle); + paintTurtles(); + } + + /** Paint all turtles (calling paintComponent()) + */ + public void paintTurtles() { + isTurtleVisible = false; + Graphics2D g2D = getTurtleG2D(); + for (int i = 0; i < countTurtles(); i++) { + Turtle aTurtle = getTurtle(i); + if (!aTurtle.isHidden()) { + paintTurtle(aTurtle); + } + } + + // This is the main repaint call, when the turtle is + // moving (even when all turtles are hidden). + // Strange behaviour an slow Mac machines (pre J2SE 1.4 version): + // It happens that some turtle images are not completely redrawn. + // This is probably due to an improper handling of fast multiple repaint requests. + // Workaround: we wait a small amount of time (and give the thread away) + // (No visible slow down on new machines.) + + paintPlayground(); + if (printerG2D == null) { + //if (isRepainting) + //repaint(); + //paintPlayground(); + } + + if (isTurtleVisible) { + try { + Thread.currentThread().sleep(10); + } + catch (Exception e) {} + } + } + + + /** Paint the given Turtle. + * ( no repaint() ) + */ + public void paintTurtle(Turtle turtle) { + if (turtleBuffer == null){ + turtleBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); + turtleG2D = turtleBuffer.createGraphics(); + } + Graphics2D turtleGraphics = getTurtleG2D(); + turtle.getTurtleRenderer().paint(turtle._getX(), turtle._getY(), turtleGraphics); + isTurtleVisible = true; + } + + /** Put an image of the given Turtle in turtle buffer. + */ + protected void stampTurtle(Turtle turtle) { + turtle.clone(); + isTurtleVisible = true; + if (printerG2D == null) + repaint(); + } + + /** Draw a line from the point (x0, y0) to (x1, y1) + with the color of the given Pen. + */ + protected void lineTo(double x0, double y0, double x1, double y1, Pen pen) { + int ix0 = (int)Math.round(x0); + int iy0 = (int)Math.round(y0); + int ix1 = (int)Math.round(x1); + int iy1 = (int)Math.round(y1); + Color color = pen.getColor(); + + if (traceBuffer == null) { + traceBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); + traceG2D = traceBuffer.createGraphics(); + } + Graphics2D traceG2D = getTraceG2D(); + traceG2D.setColor(color); + traceG2D.setStroke(pen.getStroke()); + traceG2D.drawLine(ix0, iy0, ix1, iy1); + if (printerG2D != null) + printerG2D.drawLine(ix0, iy0, ix1, iy1); + } + + /** A class for convenience. */ + protected class Point extends java.awt.Point { + Point(int x, int y) { + super(x, y); + } + Point() { + super(); + } + Point(Point p) { + super(p.x, p.y); + } + + /** Get a new Point with coordinates (this.x+p.x, this.y+p.y). + */ + protected Point add(Point p) { + return new Point(this.x+p.x, this.y+p.y); + } + + /** Translate by the amounts dx = p.x, dy = p.y. */ + protected void translate(Point p) { + translate(p.x, p.y); + } + + public String toString() { + return "(" + x + "," + y + ")"; + } + } + + /** Fill a region. + The region is defined by the Turtles actual position and + is bounded by any other color than the give background color. + */ + public void fill(Turtle t, Color bgColor) { + final Point[] diff = { new Point(0,-1), new Point(-1,0), new Point(1,0), new Point(0,1)}; + final int N=0; + final int W=1; + final int E=2; + final int S=3; + + int bgcolor = bgColor.getRGB(); + int fillColor = t.getPen().getFillColor().getRGB(); + Vector list = new Vector(); + Point2D.Double p1 = toScreenCoords(t.getPos()); + int startX = (int)Math.round(p1.getX()); + int startY = (int)Math.round(p1.getY()); + Point p = new Point(startX, startY); + if (traceBuffer.getRGB(startX, startY) == bgcolor) { + traceBuffer.setRGB(startX, startY, fillColor); + list.addElement(new Point(startX, startY)); + int d = N; + int back; + while (list.size() > 0) { + while (d <= S) { // forward + Point tmp = p.add(diff[d]); + try { + if (traceBuffer.getRGB(tmp.x, tmp.y) == bgcolor) { + p.translate(diff[d]); + traceBuffer.setRGB(p.x, p.y, fillColor); + if (printerG2D != null) + { + printerG2D.setColor(t.getPen().getFillColor()); + // printerG2D.drawLine(p.x,p.y, p.x, p.y); + BasicStroke stroke = new BasicStroke(2); + printerG2D.setStroke(stroke); + Line2D line = new Line2D.Double(p.x, p.y, p.x, p.y); + printerG2D.draw(line); + } + list.addElement(new Integer(d)); + d=N; + } + else { + d++; + } + } + catch (ArrayIndexOutOfBoundsException e) { + d++; + } + } + Object obj = list.remove(list.size()-1); + try { + d=((Integer)obj).intValue(); // last element + back = S - d; + p.translate(diff[back]); + } + catch (ClassCastException e) { + // the first (zeroest) element in list is the start-point + // just do nothing with it + } + } + } + traceG2D.drawLine(0, 0, 0, 0); // Workaround because on Mac the trace buffer is not drawn without this + if (printerG2D == null) + repaint(); + } + + /** + * Clear the playground with given color. + */ + public void clear(Color color) { + traceG2D.setColor(color); + traceG2D.fillRect(0, 0, getWidth(), getHeight()); + turtleG2D.setColor(color); + turtleG2D.fillRect(0, 0, getWidth(), getHeight()); + isTurtleVisible = true; + if (printerG2D == null) + repaint(); + } + + /** + * Clear playground. + */ + public void clear() { + clear(getBackground()); + } + + /** Paint the Playground. + just a method for convenience. + */ + public void paintComponent() { + paintComponent(getGraphics()); + } + + /** Draw the trace and turtle buffers. + */ + public void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2D = (Graphics2D)g; + g2D.drawImage(traceBuffer, 0, 0, this); + if (isTurtleVisible) + g2D.drawImage(turtleBuffer, 0, 0, this); + } + + public void paintPlayground() { + Graphics g = getGraphics(); + if (g != null) { + super.paintComponent(g); + Graphics2D g2D = (Graphics2D)g; + g2D.drawImage(traceBuffer, 0, 0, this); + if (isTurtleVisible) + g2D.drawImage(turtleBuffer, 0, 0, this); + + } // end of if + } + + /** Remove all turtles from the turtle buffer. + */ + public void clearTurtles() { + for (int i = 0; i < countTurtles(); i++) { + Turtle turtle = getTurtle(i); + clearTurtle(turtle); + } + } + + /** Remove the given turtle from the turtle buffer. + Override this method if you have added a new behaviour (like + wrap or clip) to the turtle. + */ + public void clearTurtle(Turtle turtle) { + if(turtle != null){ + if (!turtle.isHidden()) { + if(turtle.isClip()){ + clearClipTurtle(turtle); + } + else if(turtle.isWrap()){ + clearWrapTurtle(turtle); + } + } + } + } + + /** This method is called when the given Turtle is in wrap mode. + + @see ch.aplu.turtle.Turtle#wrap + */ + protected void clearWrapTurtle(Turtle turtle){ + clearWrapTurtle(turtle, turtleBuffer); + } + + /** Here the actual clearing of a Turtle in wrap mode from the + given image is performed. + */ + protected void clearWrapTurtle(Turtle turtle, Image im){ + Rectangle bounds = getBounds(turtle); + int pWidth = getWidth(); + int pHeight = getHeight(); + int x = bounds.x; + int y = bounds.y; + while (x > pWidth){ + x -= pWidth; + } + while (x < 0){ + x += pWidth; + } + while (y > pHeight){ + y -= pHeight; + } + while (y < 0){ + y += pHeight; + } + x = x % pWidth; + y = y % pHeight; + toAlphaNull(im, new Rectangle(x, y, bounds.width, bounds.height)); // OK + boolean right = (x + bounds.width > getWidth()); + boolean bottom = (y + bounds.height > getHeight()); + if (right) { + toAlphaNull(im, new Rectangle(x-pWidth, y, bounds.width, bounds.height)); + } + if (bottom) { + toAlphaNull(im, new Rectangle(x, y-pHeight, bounds.width, bounds.height)); + } + if (right && bottom) { + toAlphaNull(im, new Rectangle(x-pWidth, y-pHeight, bounds.width, bounds.height)); + } + } + + /** Copy and translate a given Rectangle. + */ + private Rectangle copyAndTranslate(Rectangle rect, int dx, int dy) { + return new Rectangle(rect.x+dx, rect.y+dy, + rect.width, rect.height); + } + + /** This method is called when the given Turtle is in clip mode. + + @see ch.aplu.turtle.Turtle#clip + */ + protected void clearClipTurtle(Turtle turtle) { + clearClipTurtle(turtle, turtleBuffer); + } + + /** Here the actual clearing of a Turtle in clip mode from the + given image is performed. + */ + protected void clearClipTurtle(Turtle turtle, Image im) { + Rectangle bounds = getBounds(turtle); + toAlphaNull(im, bounds); + } + + /** Set the alpha channel of all pixels in the given image + in the given Rectangle to zero (i.e. totally transparent). + + This method is used byte the clearXXXTurtle methods. + */ + private void toAlphaNull(Image im, Rectangle rect) { + Rectangle rim = new Rectangle(0, 0, im.getWidth(this), im.getHeight(this)); + Rectangle r = new Rectangle(); + if (rect.intersects(rim)) { + r=rect.intersection(rim); + } + int size = r.width*r.height; + float[] alphachannel = new float[r.width*r.height]; + ((BufferedImage)im).getAlphaRaster().setPixels(r.x, r.y, r.width, r.height, alphachannel); + } + + /** Puts a Turtle above all others. + */ + public Turtle toTop(Turtle turtle) { + if (turtles.removeElement(turtle)) { + turtles.add(turtle); + } + return turtle; + } + /** Put a Turtle below all others. + */ + public Turtle toBottom(Turtle turtle) { + if (turtles.removeElement(turtle)) { + turtles.add(0,turtle); + } + return turtle; + } + + /** Calculate the screen coordinates of the given point. + */ + public Point2D.Double toScreenCoords(Point2D.Double p) { + return internalToScreenCoords(p.x, p.y); + } + + /** Calculate the screen coordinates of the given point coordinates. + */ + public Point2D.Double toScreenCoords(double x, double y) { + return internalToScreenCoords(x, y); + } + + protected Point2D.Double internalToScreenCoords(double x, double y) { + // reflect at x-axis, then translate to center of Playground + // pixel coordinates coorespond to turtle coordinates, only translation needed + double newX = originX + x; + double newY = originY - y; + return new Point2D.Double(newX, newY); + } + + /** Calculate the turtle coordinates of the given screen coordinates. + */ + public Point2D.Double toTurtleCoords(double x, double y) { + // pixel coordinates coorespond to turtle coordinates, only translation needed + double newX = x - originX; + double newY = originY - y; + return new Point2D.Double(newX, newY); + } + + /** Calculate the turtle coordinates of the given screen point. + */ + public Point2D.Double toTurtleCoords(Point2D.Double p) { + return toTurtleCoords(p.x, p.y); + } + + /** Calculate the screen angle. + I.e. the interpretation of angle. + @param radians The angle in radians. + */ + double toScreenAngle(double radians) { + double sa = radians; + if (sa < Math.PI/2){ + sa += 2*Math.PI; + } + sa -= Math.PI/2; + if (sa != 0) { + sa = Math.PI*2 - sa; + } + return sa; + } + + /** Calculate the bounds of the Turtles picture on the screen. + */ + protected Rectangle getBounds(Turtle turtle) { + Rectangle bounds = turtle.getBounds(); + Point2D.Double tmp = toScreenCoords(new Point2D.Double(bounds.getX(), bounds.getY())); + bounds.setRect(tmp.x-2, tmp.y-2, bounds.width+4, bounds.height+4); + return bounds; + } + + /** Return the graphics context of the turtle buffer. + */ + public Graphics2D getTurtleG2D() { + return turtleG2D; + } + + /** Return the image of the turtle buffer. + */ + public BufferedImage getTurtleBuffer() { + return turtleBuffer; + } + + /** Return the graphics context of the trace buffer. + */ + public Graphics2D getTraceG2D() { + return traceG2D; + } + + /** Return the graphics context of the printer. + */ + public Graphics2D getPrinterG2D() { + return printerG2D; + } + + /** Return the image of the trace buffer. + */ + public BufferedImage getTraceBuffer() { + return traceBuffer; + } + + /** Clean the traces. + All turtles stay how and where they are, only lines, text and stamps will be removed. + */ + void clean() { + Graphics2D g = getTraceG2D(); + g.setColor(getBackground()); + g.fillRect(0,0,getWidth(), getHeight()); + if (printerG2D == null) + repaint(); + } + + /** Draw the text at the current position of the Turtle t. + Drawing a text at some coordinates (x,y) we mean that the bottom left corner of + the text will be at these coordinates. + Font and colour are specified by the Turtle's Pen. + */ + public void label(String text, Turtle t) { + Point2D.Double sc = toScreenCoords(t.getPos()); + int x = (int)Math.round(sc.x); + int y = (int)Math.round(sc.y); + Graphics2D traceG2D = getTraceG2D(); + FontRenderContext frc = traceG2D.getFontRenderContext(); + Font f = t.getFont(); + TextLayout tl = new TextLayout(text, f, frc); + traceG2D.setColor(t.getPen().getColor()); + tl.draw(traceG2D, x, y); + if (printerG2D != null) + { + printerG2D.setColor(t.getPen().getColor()); + tl.draw(printerG2D, x, y); + } + + if (printerG2D == null) + repaint(); + } + + /** Set antialiasing on or off for the turtle trace buffer + * This may result in an better trace quality. + */ + public void setAntiAliasing(boolean on) { + if (on) + traceG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + else + traceG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_OFF); + } + + + /** + * Set the given TPrintable (implementing draw()), + * open a printer dialog and start printing with given scale. + * Return false, if printer dialog is aborted, + * otherwise return true.
+ * If tp == null, the current playground is printed. + * + */ + protected boolean print(TPrintable tp, double scale) { + if (tp == null) + isPrintScreen = true; + else + isPrintScreen = false; + printerScale = scale; + PrinterJob pj = PrinterJob.getPrinterJob(); + pj.setPrintable(this); + traceCanvas = tp; + if (pj.printDialog()) { + try { + pj.print(); + } + catch (PrinterException ex) { + System.out.println(ex); + } + return true; + } + else + return false; + } + + /** + * For internal use only. Implementation of Printable. + * (Callback method called by printing system.) + */ + public int print(Graphics g, PageFormat pf, int pageIndex) { + if (pageIndex != 0) + return NO_SUCH_PAGE; + Graphics2D g2D = (Graphics2D)g; + double printerWidth = pf.getImageableWidth(); + double printerHeight = pf.getImageableHeight(); + double printerSize = printerWidth > printerHeight ? printerWidth : + printerHeight; + double xZero = pf.getImageableX(); + double yZero = pf.getImageableY(); + + printerG2D = g2D; // Indicate also, we are printing now + + // Needed for fill operations: the trace canvas must be empty in order to + // perform the fill algoritm (searching for outline of figure) + if (!isPrintScreen) + clean(); + + g2D.scale(printerScaleFactor * printerScale, printerScaleFactor * printerScale); + g2D.translate(xZero/printerScale, yZero/printerScale); + + if (isPrintScreen) + { + print(g); + } + else // Printing the traceCanvas + { + // Hide all turtles + boolean[] turtleState = new boolean[countTurtles()]; + for (int i = 0; i < countTurtles(); i++) { + Turtle aTurtle = getTurtle(i); + turtleState[i] = aTurtle.isHidden(); + aTurtle.ht(); + } + traceCanvas.draw(); + + // Restore old context + for (int i = 0; i < countTurtles(); i++) { + Turtle aTurtle = getTurtle(i); + if (!turtleState[i]) + aTurtle.st(); + } + } + + printerG2D = null; + return PAGE_EXISTS; + } + + /** Return the color of the pixel at the current turtle position. + */ + public Color getPixelColor(Turtle t) { + Point2D.Double p1 = toScreenCoords(t.getPos()); + int x = (int)Math.round(p1.getX()); + int y = (int)Math.round(p1.getY()); + return new Color(traceBuffer.getRGB(x, y)); + } + + public void enableRepaint(boolean b) { + isRepainting = b; + } + + /** set the background color of the playground + */ + public void setBackground(Color color) { + super.setBackground(color); + if (traceG2D != null) { + clear(color); + } // end of if + } + + /** + * Sets the origin of the cartesian coordinate system within the playground + */ + public void setOrigin(int x, int y) { + for (int i = 0; i < countTurtles(); i++) { + Turtle turtle = getTurtle(i); + Point2D.Double p1 = toScreenCoords(turtle.getPos()); + double newX = p1.getX() - x; + double newY = y - p1.getY(); + turtle.internalSetPos(newX, newY); + } + originX = x; + originY = y; + } + + public int getOriginX() { + return originX; + } + + public int getOriginY() { + return originY; + } + +} + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/res/bong.wav b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/res/bong.wav new file mode 100644 index 0000000000000000000000000000000000000000..0d2fef0c16fc8ff100f498e161aed70ae66207eb GIT binary patch literal 9624 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 literal 0 HcmV?d00001 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/sharedconstants.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/sharedconstants.java new file mode 100644 index 0000000..1bd3955 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/sharedconstants.java @@ -0,0 +1,84 @@ +// SharedConstants.java + +// Copyright 2002 Regula Hoefer-Isenegger +// +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +/* History; +V1.36 - Sep 2004: First official release +V1.37 - Nov 2004: Unchanged, modifications in ch.aplu.util +V1.38 - Dec 2004: Unchanged, modifications in ch.aplu.util +V1.39 - Jan 2005: Unchanged, modifications in ch.aplu.util +V1.40 - Mar 2005: Add background color, TurtleKeyAdapter, TurtleArea +V1.41 - May 2005: User defined turtle shape, minor changes in doc and code style +V1.42 - Dec 2005: Unchanged, modifications in ch.aplu.util +V1.43 - Feb 2006: Bug removed: Turtle.turtleFrame was not initialized in all ctors of class Turtle +V1.44 - Mar 2007: Bug removed: stampTurtle did not work properly in wrap mode +V1.45 - Aug 2007: TurtleKeyAdapter: use wait/notify to reduce CPU time (from 100% to 2%) +V1.46 - Aug 2007: synchronize(playground) for forward and rotate animation, + new method bong() using StreamingPlayer +V1.47 - Sept 2007: Unchanged, modifications in ch.aplu.util +V1.48 - Sept 2007: Unchanged, modifications in ch.aplu.util +V1.49 - Oct 2007: Unchanged, modifications in ch.aplu.util +V1.50 - Oct 2007: Unchanged, modifications in ch.aplu.util +V1.51 - Nov 2007: Fixed: correct position of label, when wrapping is on + Fixed: getPos() returns now the wrapped coordinates + Added: _getPos() returns unwrapped coordinates +V1.52 - Nov 2007: Added bean classes in order to use turtles with a Gui builder +V1.53 - Nov 2007: Added TurtlePane visual information when used in Gui builder design mode +V1.54 - Nov 2007: Minor changes to documentation +V1.55 - Dec 2007: Added property enableFocus to GPane, default: setFocusable(false) +V1.56 - Mar 2008: Unchanged, modifications in ch.aplu.util +V1.57 - Mar 2008: Unchanged, modifications in ch.aplu.util +V1.58 - Mar 2008: Modification to fill() (fill(x, y)): + region is defined with pixel color at current position + as opposed to background color +V1.59 - Oct 2008: Added ctors TurtleFrame with window position (ulx, uly) + Added Turtle.getPixelColor() +V2.00 - Nov 2008: Unchanged, modifications in ch.aplu.util + J2SE V1.4 no longer supported +V2.01 - Jan 2009: Unchanged, modifications in ch.aplu.util +V2.02 - Feb 2009 Turtle constructors run in EDT now +V2.03 - Feb 2009 Unchanged, modifications in ch.aplu.util +V2.04 - Feb 2009 Unchanged, modifications in ch.aplu.util +V2.05 - Feb 2009 Unchanged, modifications in ch.aplu.util +V2.06 - Mar 2009 Unchanged, modifications in ch.aplu.util +V2.07 - Mar 2009 All except print methods synchronized, so Turtle package is + now thread-safe +V2.08 - Apr 2009 Unchanged, modifications in ch.aplu.util +V2.09 - Jun 2009 Unchanged, modifications in ch.aplu.util +V2.10 - Jun 2010 Version for the Java-Editor +*/ + +package ch.aplu.turtle; + +interface SharedConstants +{ + int DEBUG_LEVEL_OFF = 0; + int DEBUG_LEVEL_LOW = 1; + int DEBUG_LEVEL_MEDIUM = 2; + int DEBUG_LEVEL_HIGH = 3; + + int DEBUG = DEBUG_LEVEL_OFF; + + String ABOUT = + "Copyright © 2002-2009\nRegula Hoefer-Isenegger, Aegidius Pluess\n, Gerhard Roehner\n" + + "under GNU General Public License\n" + + "http://www.aplu.ch\n" + + "All rights reserved"; + String VERSION = "2.10 - June 2015"; +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/streamingplayer.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/streamingplayer.java new file mode 100644 index 0000000..8a3d5d5 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/streamingplayer.java @@ -0,0 +1,84 @@ +// StreamingPlayer.java + +package ch.aplu.turtle; + + +import javax.sound.sampled.*; +import java.io.*; + +class StreamingPlayer +{ + private class PlayerThread extends Thread + { + public void run() + { + byte buf[] = new byte[20000]; + try + { + int cnt; + while ((cnt = audioInputStream.read(buf, 0, buf.length)) != -1) + { + if (cnt > 0) + sourceDataLine.write(buf, 0, cnt); + } + sourceDataLine.drain(); + sourceDataLine.close(); + } + catch (IOException ex) + { + System.out.println(ex); + System.exit(1); + } + } + } + + private AudioFormat audioFormat; + private AudioInputStream audioInputStream; + private SourceDataLine sourceDataLine; + private PlayerThread playerThread; + + StreamingPlayer(InputStream is) + { + try + { + audioInputStream = + AudioSystem.getAudioInputStream(is); + audioFormat = audioInputStream.getFormat(); + } + catch (Exception ex) + {} + } + + void start(boolean doFinish) + throws LineUnavailableException + { + DataLine.Info dataLineInfo = + new DataLine.Info(SourceDataLine.class, audioFormat); + sourceDataLine = + (SourceDataLine)AudioSystem.getLine(dataLineInfo); + sourceDataLine.open(audioFormat); + sourceDataLine.start(); + playerThread = new PlayerThread(); + playerThread.start(); + if (doFinish) + waitToFinish(); + } + + boolean isPlaying() + { + if (playerThread == null) + return false; + return (playerThread.isAlive()); + } + + void waitToFinish() + { + if (playerThread == null) + return; + try + { + playerThread.join(); + } + catch (InterruptedException ex) {} + } +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/tprintable.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/tprintable.java new file mode 100644 index 0000000..767d22a --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/tprintable.java @@ -0,0 +1,43 @@ +// TPrintable.java + +// Copyright 2002 Regula Hoefer-Isenegger + +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +// Added by Aegidius Pluess + +package ch.aplu.turtle; + +/** + * Interface for printing on an attached printer. + * Normally an application uses a Turtle and implements this interface. + * draw() should contain all drawing operations into the + * Turtle's Playground. The printing occures, when Turtle's print() is + * called.

+ */ + + +public interface TPrintable +{ + /** + * This method must perform all drawing operations. + * Be aware that for some undocumented reason + * draw() is called twice. So be sure you initialize it correctly. + */ + + public void draw(); +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/turtle.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/turtle.java new file mode 100644 index 0000000..d30ff52 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/turtle.java @@ -0,0 +1,1585 @@ +// Turtle.java +// Modifications by Aegidius Pluess +// Adaption to the Java-Editor by Gerhard Röhner + +// Copyright 2002-2003 Regula Hoefer-Isenegger (Version 1.0) +// +// This file is part of The Java Turtle package (TJT) +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +/* +Screen coordinate system: 0..400 pixels in both directions corresponds to turtle +turtle coordinate system -200..200, so only translation is necessary (no scaling). + +This avoids rounding errors. +*/ + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.*; +import java.awt.image.*; +import java.awt.print.*; +import java.io.*; +import javax.sound.sampled.*; +import javax.swing.*; + +/** + The core class for turtles. + + For a simple example on how to use Turtle, cf. the + Java Turtle Package description. + @author Regula Hoefer-Isenegger + @version 0.1.1 +*/ +public class Turtle implements Cloneable +{ + private double angle; + private Point2D.Double position; + private Playground playground; + private int framesPerSecond; + private double speed; // Pixel/sec + private double angleSpeed; // Radian/sec + private TurtleRenderer turtleRenderer; + private int angleResolution; + private LineRenderer lineRenderer; + private static TurtleFactory turtleFactory; + private boolean penUp; + private boolean showTurtle; + private boolean initialVisibility = true; + private Pen pen; + private Color color; + private int edgeBehaviour; + + + /** Convert from screen coordinates to turtle coordinates + */ + public Point2D.Double toTurtlePos(Point p) { + return playground.toTurtleCoords((double)p.x, (double)p.y); + } + + /** Convert from screen coordinates to turtle coordinates + */ + public Point2D.Double toTurtlePos(int x, int y) { + return playground.toTurtleCoords((double)x, (double)y); + } + + /** Convert from screen coordinates to turtle coordinates + */ + public double toTurtleX(int x) { + return (playground.toTurtleCoords((double)x, 0)).x; + } + + /** Convert from screen coordinates to turtle coordinates + */ + public double toTurtleY(int y) { + return (playground.toTurtleCoords(0, (double)y)).y; + } + + /** Add the specified mouse listener to receive mouse events. + */ + public void addMouseListener(MouseListener l) { + playground.addMouseListener(l); + } + + /** Add the specified mouse motion listener to receive mouse motion events. + */ + public void addMouseMotionListener(MouseMotionListener l) { + playground.addMouseMotionListener(l); + } + + /** + * Emit a beep. Fails if no standard speaker available. Try to use bong() instead. + * @see #bong() + */ + public void beep() { + Toolkit.getDefaultToolkit().beep(); + } + + /** + * Emit a 'bong' via the sound card. Useful on computers without standard + * speaker. + * @see #beep() + */ + public void bong() { + InputStream is = getClass().getResourceAsStream("res/bong.wav"); + StreamingPlayer player = new StreamingPlayer(is); + try + { + player.start(false); + } + catch (LineUnavailableException ex) + { + System.out.println("Error in bong(). Sound card unavailable"); + } + } + + + /** Represent clip mode. + @see #WRAP + @see #clip() + */ + protected final static int CLIP = 0; + /** Represent wrap mode. + + @see #CLIP + @see #wrap() + */ + protected final static int WRAP = 1; + /** Represent the default edge behaviour (i.e. CLIP or WRAP). + + @see #CLIP + @see #WRAP + @see #clip() + @see #wrap() + */ + protected static int DEFAULT_EDGE_BEHAVIOUR = CLIP; + /** Represent the default speed (velocity). + + @see #setSpeed(double) + */ + protected static double DEFAULT_SPEED = 200; + + /** Represent the default angle resolution. + + It specifies how many different turtle pictures + are generated. + */ + protected static int DEFAULT_ANGLE_RESOLUTION = 72; + + /** Specify how many frames per second are used for + turtle animation. + */ + protected static int DEFAULT_FRAMES_PER_SECOND = 10; + + /** Specify the default turtle color. + + @see #setColor(java.awt.Color) + */ + protected static Color DEFAULT_TURTLE_COLOR = Color.cyan; + + /** Specify the default pen color. + + @see #setPenColor(java.awt.Color) + */ + protected static Color DEFAULT_PEN_COLOR = Color.blue; + + /** Create a new Turtle + */ + public Turtle() { + } + + /** init a new Turtle + */ + protected void init(Color color) { + angle = 0; + position = new Point2D.Double(0, 0); + framesPerSecond = DEFAULT_FRAMES_PER_SECOND; + if (initialVisibility) + setSpeed(DEFAULT_SPEED); + else + setSpeed(-1); + showTurtle = initialVisibility; + setAngleResolution(DEFAULT_ANGLE_RESOLUTION); + angleSpeed = getSpeed() * Math.PI * 2 / DEFAULT_SPEED; + pen = new Pen(DEFAULT_PEN_COLOR); + if (getTurtleFactory() == null){ + turtleFactory = createTurtleFactory(); + } + setColor(color); + lineRenderer = createLineRenderer(); + getTurtleRenderer().setAngle(getAngle()); + } + + /** Set the angle resolution for the Turtle's pictures. + + It specifies how many pictures are used. e.g. an angle resolution + of 90 means that you get one picture for every 4 degrees + (= 360/90 degrees). + */ + public void setAngleResolution(int newResolution) { + synchronized(playground) { + angleResolution = newResolution; + } + } + + /** Return the TurtleFactory of this turtle. + + @see ch.aplu.turtle.TurtleFactory + */ + public TurtleFactory getTurtleFactory() { + return this.turtleFactory; + } + + /** Create a LineRenderer which is responsible + for the correct drawing of the lines. + + @return the new LineRenderer + */ + + protected LineRenderer createLineRenderer() { + return new LineRenderer(this); + } + + /** Create a TurtleRenderer which is responsible + for the correct drawing of the Turtle. + + @return the new TurtleRenderer + */ + protected TurtleRenderer createTurtleRenderer() { + return new TurtleRenderer(this); + } + + /** Create a TurtleFactory which provides for + the Turtle pictures. + + @return the new TurtleFactory + */ + + protected TurtleFactory createTurtleFactory() { + return new TurtleFactory(); + } + /** Get the angle resolution. + + @see #setAngleResolution(int) + */ + + protected int getAngleResolution() { + return angleResolution; + } + + /** Get the TurtleRenderer. + */ + TurtleRenderer getTurtleRenderer() { + return turtleRenderer; + } + + /** Get the LineRenderer. + */ + private LineRenderer getLineRenderer() { + return lineRenderer; + } + + /** Get the Playground. + */ + public Playground getPlayground() { + return playground; + } + + /** Set the Playground to the specified + playground. + + The Turtle is removed from the old + Playground and set to the new one. + */ + public void setPlayground(Playground playground) { + Playground pg = getPlayground(); + if(pg != null){ + pg.clearTurtle(this); + pg.remove(this); + pg.paintTurtles(); + } + this.playground = playground; + playground.paintTurtles(this); + } + + /** Get the angle speed. + + (I.e. how fast the Turtle rotation + animation is performed.) + */ + private double getAngleSpeed() { + return angleSpeed; + } + + /** Set the angle speed. + + @see #getAngleSpeed() + */ + private void setAngleSpeed(double newAngleSpeed) { + this.angleSpeed = newAngleSpeed; + } + + /** Get the current angle (heading) of the + Turtle. + */ + private double getAngle() { + return angle; // in radians + } + + /** Get the current speed. + */ + public double getSpeed() { + return speed; + } + + /** Query the Turtle's x-position without wrapping. + * Coordinate are not bound to playground even when + * wrapping is on. + */ + public double _getX() { + synchronized (playground) { + return position.getX(); + } + } + + /** Query the Turtle's y-position without wrapping. + * Coordinate are not bound to playground even when + * wrapping is on. + */ + public double _getY() { + synchronized (playground) { + return position.getY(); + } + } + + /** Query the Turtle's x-position. + * If turtle is outside playground and wrapping is on + * return the coordinate in range -200..200. + * */ + + public double getX() { + synchronized (playground) { + double xPos = _getX(); + return xPos; + } + } + + /** Query the Turtle's x-position. + * If turtle is outside playground and wrapping is on + * return the coordinate in range -200..200. + */ + public double getY() { + synchronized (playground) { + double yPos = _getY(); + return yPos; + } + } + + + /** Query the Turtle's position without wrapping. + * Coordinate are not bound to playground even when + * wrapping is on. + */ + public Point2D.Double _getPos() { + return position; + } + + /** Query the Turtle's position */ + public Point2D.Double getPos() { + return new Point2D.Double(getX(), getY()); + } + + /** Put the Turtle to a new position with the given x-coordinates. + + */ + public void setX(double x) { + synchronized (playground) { + getPlayground().clearTurtle(this); + internalSetX(x); + getPlayground().paintTurtles(this); + } + } + + /** Put the Turtle to a new position with the given screen x-coordinates. + */ + public void setScreenX(int x) { + synchronized (playground) { + setX(toTurtleX(x)); + } + } + + /** Put the Turtle to a new position with the given y-coordinates. + */ + public void setY(double y) { + synchronized (playground) { + getPlayground().clearTurtle(this); + internalSetY(y); + getPlayground().paintTurtles(this); + } + } + + /** Put the Turtle to a new position with the given screen y-coordinates. + */ + public void setScreenY(int y) { + synchronized (playground) { + setY(toTurtleY(y)); + } + } + + /** Set the Turtle's x-Coordinate. + */ + protected void internalSetX(double x) { + synchronized (playground) { + position.setLocation(x, _getY()); + } + } + + /** Set the Turtle's y-Coordinate. + */ + protected void internalSetY(double y) { + position.setLocation(_getX(), y); + } + + /** Set the Turtle's Position. + */ + protected void internalSetPos(double x, double y) { + position.setLocation(x, y); + } + + /** Hide the Turtle. + + @see #st() + If there is only one turte, the speed is set to -1 + so there is no Turtle animation at all. + Hiding the Turtle speeds up the graphics enormously. + */ + public void ht() { + synchronized (playground) { + this.internalHide(); + if (getPlayground().countTurtles() == 1) + setSpeed(-1); + } + } + + /** Hide the Turtle. + + This is the same as ht(). + @see #st() + */ + public void hideTurtle() { + ht(); + } + + /** This is the method called by the public methods ht() and hideTurtle(). + + Here the actual hiding takes place. + @see #ht() + @see #hideTurtle() + */ + protected void internalHide() { + getPlayground().clearTurtle(this); + showTurtle = false; + if (getPlayground().getPrinterG2D() == null) + getPlayground().repaint(); + } + + /** Set the Turtle to show mode. + + That means that the Turtle will be drawn. + @see #ht() + */ + public void st() { + synchronized (playground) { + if (getPlayground().getPrinterG2D() == null) { + getPlayground().paintTurtle(this); + showTurtle = true; + getPlayground().repaint(); + } + } + } + + /** The same as st(). + + @see #st() + */ + public void showTurtle() { + st(); + } + + /** Tell whether the Turtle is hidden or not. + + @return true if the Turtle is hidden, + false otherwise. + */ + public boolean isHidden() { + return !showTurtle; + } + + private int getFramesPerSecond() { + return this.framesPerSecond; + } + + /** Only set the angle attribute. This method does not + invoke any re-painting. + */ + private void setAngle(double radians) { + this.angle = radians; + } + + /** This is the same as setH(double degrees). + + @see #setH(double) + */ + public void setHeading(double degrees) { + synchronized (playground) { + setAngle(Math.toRadians(degrees)); + getTurtleRenderer().setAngle(Math.toRadians(degrees)); + getPlayground().clearTurtle(this); + getPlayground().paintTurtles(this); + } + } + + /** Set the Turtle's heading. + + 0 means facing NORTH.
+ the angles are measured clockwise. + @see #setHeading(double) + */ + public void setH(double degrees) { + setHeading(degrees); + } + /** Query the Turtle's heading. + + @see #setH(double) + */ + public double heading() { + synchronized (playground) { + return Math.toDegrees(getAngle()); + } + } + /** Set the Turtle's heading to the new value. + + @return the old (previous) value. + @see #setH(double) + */ + public double heading(double degrees) { + synchronized (playground) { + double tmp = Math.toDegrees(getAngle()); + setHeading(degrees); + return tmp; + } + } + + /** Set the Turtle's speed. + + If you try to set the speed to 0, it will be set to 1 (very slow). + A negative speed means that moving the Turtle (fd, bk) + will not be animated.
+ The unit is pixels per second (up to certain bounds depending on the CPU etc.).
+ Remark: Dashed lines will only be painted as you expect it with speed set + to -1. + + @see #fd(double) + @see #bk(double) + */ + public void setSpeed(double speed) { + if (speed == 0) + this.speed = 1; + else + this.speed = speed; + } + + + /** This method is responsible for the rotation animation. + */ + private void internalRotate(double angle) { + if(isHidden()){ + synchronized(playground) + { + setAngle(getAngle()+angle); + if (getTurtleRenderer().imageChanged(getAngle())) { + getTurtleRenderer().setAngle(getAngle()); + } + } + return; + } + if (angle != 0) { + int iterations = getAngleIterations(angle); + + double sign = angle/Math.abs(angle); + double increment = sign*getAngleSpeed()/(double)getFramesPerSecond(); + double startAngle = getAngle(); + + for (int index = 0; index < iterations; index++) { + long timeStamp = System.currentTimeMillis(); + + synchronized(playground) { + getPlayground().clearTurtle(this); + + if (index < iterations-1) { + setAngle(getAngle()+increment); + } + else { + setAngle(startAngle+angle); + } + + if (getTurtleRenderer().imageChanged(getAngle())) { + getTurtleRenderer().setAngle(getAngle()); + getPlayground().paintTurtles(this); + } + } + + long newTimeStamp = System.currentTimeMillis(); + Double secs = new Double(1000./getFramesPerSecond()); + long requiredTime = secs.longValue()-newTimeStamp+timeStamp; + + if (requiredTime > 0) { + try { + Thread.sleep(requiredTime); + } + catch (InterruptedException e) { + } + } + } + } + getPlayground().paintTurtles(this); + } + + /** This method is responsible for the moving animation. + */ + private void internalMove(double length) { + if (getSpeed()>0){ + if (length != 0) { + int iterations = getPathIterations(length); + // an angle of 0 means: facing NORTH + double startX = _getX(); + double startY = _getY(); + getLineRenderer().init(startX, startY); + double dx = length * Math.sin(getAngle()); + double dy = length * Math.cos(getAngle()); + double incrementX = dx / iterations; + double incrementY = dy / iterations; + for (int index = 0; index < iterations; index++) { + long timeStamp = System.currentTimeMillis(); + int nX = (int)_getX(); + int nY = (int)_getY(); + synchronized(playground) { + playground.clearTurtle(this); + if (index < iterations-1) { + internalSetX(_getX()+incrementX); + internalSetY(_getY()+incrementY); + } + else { // last step: Calc the "exact" value + internalSetX(startX + dx); + internalSetY(startY + dy); + } + if (nX != (int)_getX() || nY != - (int)_getY() || index == iterations-1){ + if (!isPenUp()) { + getLineRenderer().lineTo(_getX(), _getY()); + } + getPlayground().paintTurtles(this); + } + } + Double frames = new Double(1000./getFramesPerSecond()); + long newTimeStamp = System.currentTimeMillis(); + long requiredTime = frames.longValue()-newTimeStamp+timeStamp; + if (requiredTime > 0) { + try { + Thread.sleep(requiredTime); + } + catch (InterruptedException e) { + } + } + } + } + } + else { // Speed < 0, i.e. no animation + double startX = _getX(); + double startY = _getY(); + getLineRenderer().init(startX, startY); + double dx = length * Math.sin(getAngle()); + double dy = length * Math.cos(getAngle()); + getPlayground().clearTurtle(this); + internalSetX(startX + dx); + internalSetY(startY + dy); + if (!isPenUp()) { + getLineRenderer().lineTo(_getX(), _getY()); + } + getPlayground().paintTurtles(this); + } + } + + /** Turn the Turtle the given angle (in degrees) to the left + + @see #rt(double) + */ + public void lt(double degrees) { + left(degrees); + } + + /** Same as lt(double degrees) + + @see #lt(double) + */ + public void left(double degrees) { + internalRotate(Math.toRadians(-degrees)); + } + + /** Turn the Turtle the given angle (in degrees) to the right. + + @see #rt(double) + */ + public void rt(double degrees) { + right(degrees); + } + + /** Same as rt(double degrees). + + @see #rt(double) + */ + public void right(double degrees) { + internalRotate(Math.toRadians(degrees)); + } + + /** Same as fd(double distance) + + @see #fd(double) + */ + public void forward(double distance) { + internalMove(distance); + } + + /** Move the Turtle forwards. + + Negative values for distance are + allowed. In that case, the Turtle + will move backwards. + + @see #bk(double) + */ + public void fd(double distance) { + forward(distance); + } + + /** Same as bk(double distance). + + @see #bk(double) + */ + public void back(double distance) { + forward(-distance); + } + + /** Move the Turtle backwards. + + Negative values for distance are + allowed. In that case, the Turtle + will move forwards. + + @see #fd(double) + */ + public void bk(double distance) { + back(distance); + } + + /** Query the distance from the current location + to the given one. + */ + public double distance(double x, double y) { + synchronized (playground) { + return this.getPos().distance(x,y); + } + } + + /** Query the distance from the current location + to the given one. + * Actually a polygon with 36 sides is drawn. + */ + public double distance(Point2D.Double p) { + synchronized (playground) { + return this.getPos().distance(p); + } + } + + /** Draw a circle to the left from the current position with + * turtle's heading tangent direction and given radius. + * Actually a polygon with 36 sides is drawn. + */ + public void leftCircle(double radius) { + circle(radius, true); + } + + /** Draw a circle to the right from the current position with + * turtle's heading tangent direction and given radius. + * Actually a polygon with 36 sides is drawn. + */ + public void rightCircle(double radius) { + circle(radius, false); + } + + private void circle(double radius, boolean left) { + double nbSteps = 36; // 36 side polygon + double angle = 2 * Math.PI / nbSteps; + double step = 2 * radius * Math.sin(angle/2); + for (int i = 0; i < 36; i++) { + if (left) + if (i == 0) + lt(180.0 / nbSteps); + else + lt(360.0 / nbSteps); + else + if (i == 0) + rt(180.0 / nbSteps); + else + rt(360.0 / nbSteps); + fd(step); + } + } + + /** Calculate the number of iterations when animating left or right (rotation). + */ + private int getAngleIterations(double dAngle) { + if(getAngleSpeed()<0){ + return 1; + } + if(getAngleSpeed()==0){ + setAngleSpeed(1); + } + double dAbsAngle = Math.abs(dAngle); + Double dValue = new Double(Math.ceil(dAbsAngle/getAngleSpeed()*getFramesPerSecond())); + return dValue.intValue(); + } + + /** Calculate the number of iterations when animating forwards or backwards. + */ + private int getPathIterations(double length) { + if(speed < 0) + return 1; + + if (speed == 0) + setSpeed(1); + + double dAbsLength = Math.abs(length); + Double dValue = new Double(Math.ceil(dAbsLength/getSpeed()*getFramesPerSecond())); + return dValue.intValue(); + } + + /** Lift the Turtle's pen up so it + won't draw a line anymore. + + This is the same as pu(). + + @see #pu() + @see #penDown() + @see #pd() + */ + public void penUp() { + synchronized (playground) { + this.penUp = true; + } + } + + /** Lift the Turtle's pen up so it + won't draw a line anymore. + + This is the same as penUp(). + + @see #penUp() + @see #penDown() + @see #pd() + */ + public void pu() { + this.penUp(); + } + + /** Lower the Turtle's Pen down so it + will draw a line when moving. + + This is the same as pd(). + + @see #pd() + @see #penUp() + @see #pu() + */ + public void penDown() { + synchronized (playground) { + this.penUp = false; + } + } + + /** Lowers the Turtle's pen down so it + will draw a line when moving. + + This is the same as penDown(). + + @see #penDown() + @see #penUp() + @see #pu() + */ + public void pd() { + this.penDown(); + } + + /** Query the Pen's state (up or down). + + @return true if the Pen is + up, false otherwise. + @see #pu() + @see #pd() + */ + public boolean isPenUp() { + return this.penUp; + } + + /** Return the bounds of this Turtle. This is required + by the methods that (return-)paint the Turtles. + */ + Rectangle getBounds() { + Rectangle rect = new Rectangle(); + + Image img = getTurtleRenderer().currentImage(); + int nWidth = img.getWidth(getTurtleRenderer()); + int nHeight = img.getHeight(getTurtleRenderer()); + double x = (_getX()<0)?Math.floor(_getX()):Math.ceil(_getX()); + double y = (_getY()<0)?Math.floor(_getY()):Math.ceil(_getY()); + rect.setBounds((int)x-nWidth/2, (int)y + nHeight/2, nWidth, nHeight); + return rect; + } + + /** Get the Turtle's Pen. + + You need it if you want to change end caps etc. + @see Pen + */ + public Pen getPen() { + return pen; + } + /** Set the line thickness. + + This works only neatly in clip mode (yet). + @see #clip() + @see #wrap() + */ + public void setLineWidth(double lineWidth){ + synchronized (playground) { + setLineWidth((float)lineWidth); + } + } + + /** Set the line thickness. + + This works only neatly in clip mode (yet). + @see #clip() + @see #wrap() + */ + public void setLineWidth(float lineWidth) { + synchronized (playground) { + getPen().setLineWidth(lineWidth); + } + } + + /** Set the Turtle's color to the specified one. + + */ + public void setColor(Color color) { + synchronized (playground) { + internalSetColor(color); + getPlayground().paintTurtles(); + } + } + + private void internalSetColor(Color color) { + this.color = color; + if (getTurtleRenderer()==null) { + turtleRenderer = createTurtleRenderer(); + getTurtleRenderer().init(getTurtleFactory(), getAngleResolution()); + } + else{ + getTurtleRenderer().init(new TurtleFactory(), + this.angleResolution); + } + } + + /** Set the color to the specified one. + + @see #fill() + */ + public void setFillColor(Color color) { + synchronized (playground) { + getPen().setFillColor(color); + } + } + + /** Query the Turtle's current color. + */ + public Color getColor(){ + return color; + } + + /**Set the Turtle's pen color. + + */ + public void setPenColor(Color color) { + synchronized (playground) { + getPen().setColor(color); + } + } + + /** Move the Turtle back "home", i.e. set its position + to the origin, facing NORTH. + + Color, PenColor etc. remain the same. + */ + public void home() { + // first : clean the Turtle! + synchronized (playground) { + getPlayground().clearTurtle(this); + position = new Point2D.Double(0,0); + setHeading(0); + } + } + + /** The Turtle's Pen is + changed to an eraser (which is in fact a pen with + background color). + + This is the same as pe() + @see #pe() + */ + public void penErase() { + synchronized (playground) { + this.internalPenErase(); + } + } + + /** The Turtle's Pen is + changed to an eraser (which is in fact a pen with + background color). + + This is the same as penErase() + @see #penErase() + */ + public void pe() { + penErase(); + } + + protected void internalPenErase(){ + this.setPenColor(getPlayground().getBackground()); + } + + /** Put the Turtle to a new position with specified + x- and y-coordinates. + */ + public void setPos(double x, double y) { + synchronized (playground) { + getPlayground().clearTurtle(this); + internalSetPos(x, y); + getPlayground().paintTurtles(); + } + } + + /** Put the Turtle to a new position. + */ + public void setPos(Point2D.Double p) { + setPos(p.x, p.y); + } + + /** Put the Turtle to a new screen position. + + */ + public void setScreenPos(Point p) { + setPos(toTurtlePos(p)); + } + + + /** Put a Turtle image at the current position. + + */ + public void stampTurtle() { + synchronized (playground) { + this.getPlayground().stampTurtle(this); + } + } + + /** Calculate the direction to a given point. + + @return the direction from the current turtle position + towards the given point, measured in degrees and clockwise + from the vertical upwards position. + */ + public double towards(double x, double y) { + synchronized (playground) { + double dx = x - getX(); + double dy = y - getY(); + double result = Math.toDegrees(Math.atan2(dx, dy)); + return (result < 0) ? result+360 : result; + } + } + + /** Calculate the direction to a given point. + + @return the direction from the current turtle position + towards the given point, measured in degrees and clockwise + from the vertical upwards position. + */ + public double towards(Point2D.Double p) { + return towards(p.getX(), p.getY()); + } + + /** Put the Turtle to the top (i.e. above any other + turtle). + + Just invokes the toTop-Method in Playground. + @see Playground#toTop + @see #internalToBottom + */ + void internalToTop() { + this.getPlayground().toTop(this); + } + /** Put the Turtle to the bottom (i.e. under any other + turtle). + + Just invokes the toBottom-Method in Playground. + @see Playground#toBottom + @see #internalToTop + */ + void internalToBottom() { + this.getPlayground().toBottom(this); + } + + /** Put this turtle to the bottom. + + So any other turtle in the same Playground will be drawn over it. + */ + public void toBottom() { + // this.getPlayground().toBottom(this); + synchronized (playground) { + internalToBottom(); + getPlayground().paintTurtles(); + } + } + + /** Put this turtle to the top. + + So it will be drawn over any other turtle in the same Playground. + */ + public void toTop() { + // this.getPlayground().toTop(this); + synchronized (playground) { + this.getPlayground().paintTurtles(this); + } + } + + /** Set the pen width. + */ + public void penWidth(int newWidth) { + synchronized (playground) { + penWidth((float)newWidth); + } + } + + /** Internal Method for setting the penWidth. + */ + private void penWidth(float newWidth) { + setLineWidth(newWidth); + } + + /** Query the pen width. + */ + public int penWidth(){ + return (int)this.getPen().getLineWidth(); + } + + /** Returns the current edge behaviour. + + @see #CLIP + @see #WRAP + */ + protected int getEdgeBehaviour() { + return edgeBehaviour; + } + + /** Sets the edge behaviour to the specified value; + + @see #CLIP + @see #WRAP + */ + protected void setEdgeBehaviour(int edgeBehaviour) { + synchronized (playground) { + this.edgeBehaviour = edgeBehaviour; + } + } + + /** Set the Turtle to clip-mode. + @see #wrap() + @see #clip() + */ + public void clip() { + synchronized (playground) { + setEdgeBehaviour(CLIP); + } + } + + /** Cause the Turtle to wrap around the playground borders. + + e.g when as the Turtle leaves the Window on one side, + it reappears on the opposite side. + + @see #clip() + */ + public void wrap() { + synchronized (playground) { + setEdgeBehaviour(WRAP); + } + } + + /** Tell whether the Turtle is in clip mode. + + @return true if in clip mode, false otherwise. + @see #clip() + @see #wrap() + */ + public boolean isClip() { + return (getEdgeBehaviour() == CLIP); + } + /** Tell wheter the Turtle is in wrap mode. + + @return true if in wrap mode, false otherwise. + @see #wrap() + @see #clip() + */ + public boolean isWrap() { + return (getEdgeBehaviour() == WRAP); + } + + /** Fill the region the Turtle is in.
+ + A region is bounded by lines + of any color different to the pixel color at the current turtle position + and by the border of the window.
+ (The pen of the Turtle must be down.) + */ + public void fill() { + synchronized (playground) { + getPlayground().fill(this, getPlayground().getPixelColor(this)); + } + } + + /** Fill the region as if the Turtle where at coordinates x and y.
+ A region is bounded by lines + of any color different to the pixel color at the given position and by the border of + the window.
+ (The pen of the Turtle must be down.) + */ + public void fill(double x, double y) { + synchronized (playground) { + double oldX = getX(); + double oldY = getY(); + boolean hidden = isHidden(); + ht(); + setPos(x,y); + getPlayground().fill(this, getPlayground().getPixelColor(this)); + setPos(oldX, oldY); + if(!hidden){ + st(); + } + } + } + + /** Erase all traces and text painted by the turtles, but let all + * turtles where they are. + + */ + public void clean() { + synchronized (playground) { + getPlayground().clean(); + } + } + + /** Paint the specified text at the current turtle position. + + */ + public void label(String text) { + synchronized (playground) { + if (text != null && text.length() > 0) + getPlayground().label(text, this); + } + } + + /** Set the current font as specified. + + @see java.awt.Font + */ + public void setFont(Font font) { + synchronized (playground) { + getPen().setFont(font); + } + } + + /** Change the current font to the specified one. If you want to know what fonts are available on your system, + call #getAvailableFontFamilies() . + + @see #getAvailableFontFamilies + @see java.awt.Font more information about fontName, style and size. + */ + public void setFont(String fontName, int style, int size) { + synchronized (playground) { + getPen().setFont(new Font(fontName, style, size)); + } + } + + /** Set the font size. + + @see #setFontStyle changing the font style + @see #setFont changing the whole font. + */ + public void setFontSize(int size) { + synchronized (playground) { + getPen().setFontSize(size); + } + } + + /** Set the font style. + + This is either java.awt.Font.PLAIN, java.awt.Font.BOLD, java.awt.Font.ITALIC or java.awt.Font.BOLD+java.awt.Font.ITALIC + @see #setFontSize changing the font size + @see #setFont changing the whole font. + */ + public void setFontStyle(int style) { + synchronized (playground) { + getPen().setFontStyle(style); + } + } + + /** Provide information about all font families (e.g. roman) currently available on your system. + Each font name is a string packed into a array of strings. + (This might be useful when you want to change the font.) + @see #setFont(java.awt.Font) + @see #setFont(java.lang.String, int, int) + */ + public static String[] getAvailableFontFamilies() { + return Pen.getAvailableFontFamilies(); + } + + /** Return the current font. + + @see #setFontSize changing the font size + @see #setFontStyle changing the font style + @see #setFont changing the whole font. + */ + public Font getFont() { + return getPen().getFont(); + } + + /** Creates a clone of the Turtle in it's Playground. + Color, position and heading are the same. + (It's visible and pen is down.) + Return the cloned object reference as a Object type, because + it overrides Object.clone(). + (You may cast it to a Turtle.) + */ + public Object clone() + { + synchronized (playground) { + Turtle t = new Turtle(); + t.setColor(getColor()); + t.setPos(getX(), getY()); + t.heading(heading()); + t.showTurtle(); + return t; + } + } + + /** Set antialiasing on or off for the turtle trace buffer + * This may result in an better image quality, especially + * for filling operations (platform dependant). + */ + public void antiAliasing(boolean on) { + synchronized (playground) { + getPlayground().setAntiAliasing(on); + } + } + + + /** + * Print the graphics context to an attached printer with + * the given magnification scale factor. + * scale = 1 will print on standard A4 format paper.
+ * + * The given tp must implement the GPrintable interface, + * e.g. the single method void draw(), where all the + * drawing into the GPanel must occur. + * + * Be aware the turtle(s) state (position, direction, etc.) + * must be reinitialized, because draw() is called several + * times by the printing system. + * + * A standard printer dialog is shown before printing is + * started. Only turte traces are printed. + *
+ * Example:
+ * + import ch.aplu.turtle.*;
+
+ public class PrintTest implements TPrintable
+ {
+ private Turtle t = new Turtle();
+
+ public PrintTest()
+ {
+ draw(); // Draw on screen
+ t.print(this); // Draw on printer
+ }
+
+ public void draw()
+ {
+ t.home(); // Needed for initialization
+ for (int i = 0; i < 5; i++)
+ t.fd(20).rt(90).fd(20).lt(90);
+ }
+
+ public static void main(String[] args)
+ {
+ new PrintTest();
+ }
+ }
+
+ */ + public boolean print(TPrintable tp, double scale) + { + return getPlayground().print(tp, scale); + } + + /** + * Same as print(tp, scale) with scale = 1. + */ + public boolean print(TPrintable tp) + { + return print(tp, 1); + } + + /** + * Print the Turtle's current playground with given scale. + */ + public boolean printScreen(double scale) + { + return print(null, scale); + } + + /** + * Same as printScreen(scale) with scale = 1. + */ + public boolean printScreen() + { + return printScreen(1); + } + + /** + * Clear the Turtle's playground. All turtle images and traces are erased, + * but the turtles remain (invisible) at their positions. + */ + public void clear() + { + synchronized (playground) { + getPlayground().clear(); + } + } + + /** + * Delay execution for the given amount of time ( in ms ). + */ + public static void sleep(int time) + { + try + { + Thread.currentThread().sleep(time); + } + catch (Exception e) {} + } + + /** + * Return version information + */ + public String version() + { + return SharedConstants.VERSION; + } + + /** + * Enable/disable automatic repainting. + * If disabled, call repaint() to perform repainting. + * Disabling automatic repainting and hiding the + * Turtle speeds up the graphics enormously. + */ + public void enableRepaint(boolean b) + { + getPlayground().enableRepaint(b); + } + + /** + * Perform manual repainting when automatic repainting is + * disabled. + */ + public void repaint() { + getPlayground().repaint(); + } + + /** + * Return the color of the pixel at the current turtle position. + */ + public Color getPixelColor() { + synchronized (playground) { + return getPlayground().getPixelColor(this); + } + } + + protected Graphics getGraphics() { + return playground.getGraphics(); + } + + /** + * Transforms the gui-position to mouse-coordinates. + */ + public void setBounds(int x, int y, int b, int h) { + int ox = playground.getOriginX(); + int oy = playground.getOriginY(); + x = -ox + x + 10; + y = oy - y - 13; + setPos(x, y); + } + + /** + * Shows or hides the turtle. + */ + public void setVisible(boolean show) { + if (show) { + showTurtle(); + } else { + hideTurtle(); + } // end of if-else + } + + /** + * Sets clipping-mode on/off. + */ + public void setClip(boolean clip) { + if (clip) { + clip(); + } else { + wrap(); + } // end of if-else + } + + /** + * Sets pen-position up/down. + */ + public void setPenUp(boolean penup) { + if (penup) { + penUp(); + } else { + penDown(); + } // end of if-else + } + + /** + * Sets angle of the turtle. + */ + public void setAngle(int angle) { + setHeading(angle); + } +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/turtlefactory.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/turtlefactory.java new file mode 100644 index 0000000..e9d700e --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/turtlefactory.java @@ -0,0 +1,66 @@ +// TurtleFactory.java + +// Copyright 2002 Regula Hoefer-Isenegger +// +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import java.awt.image.*; +import java.awt.*; + +class TurtleFactory +{ + /** Generates the shape of the turtle with color, + * angle angle, width w + * and height h. + */ + protected Image turtleImage(Color color, double angle, int w, int h) + { + BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR); + Graphics2D g = (Graphics2D)bi.getGraphics(); + // Origin in center + g.translate(w/2, h/2); + // angle = 0 is direction east (as usual in mathematics) + g.rotate(Math.PI/2 - angle); + g.setColor(color); + + // Body + g.fillOval((int)( -0.35 * w), (int)( -0.35 * h), + (int)(0.7 * w), (int)(0.7 * h)); + + // Head + g.fillOval((int)( -0.1 * w), (int)( -0.5 * h), + (int)(0.2 * w), (int)(0.2 * h)); + + // Tail + int[] xcoords = + {(int)( -0.05 * w), 0, (int)(0.05 * w)}; + int[] ycoords = + {(int)(0.35 * h), (int)(0.45 * h), (int)(0.35 * h)}; + g.fillPolygon(xcoords, ycoords, 3); + + // Feet + for (int i = 0; i < 4; i++) + { + g.rotate(Math.PI / 2); + g.fillOval((int)( -0.35 * w), (int)( -0.35 * h), + (int)(0.125 * w), (int)(0.125 * h)); + } + return (Image)bi; + } +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/turtlerenderer.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/turtlerenderer.java new file mode 100644 index 0000000..9489e78 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/aplu/turtle/turtlerenderer.java @@ -0,0 +1,312 @@ +// TurtleRenderer.java + +// Copyright 2002 Regula Hoefer-Isenegger +// Some modifications by Aegidius Pluess + +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.awt.image.*; +import java.awt.*; +import javax.swing.*; +import java.awt.geom.*; +import java.util.*; + + +/** This class is responsible for creating and choosing the correct Turtle picture. + @author Regula Hoefer-Isenegger + @version 0.1 +*/ +public class TurtleRenderer implements ImageObserver { + /** Holds the current image */ + private Image currentImage; + /** Holds all images */ + private Vector images; + /** Tells how many pictures are needed*/ + private int resolution; + /** A reference to the Turtle */ + private Turtle turtle; + /** Holds the current Angle */ + private double currentAngle; + + private final int turtleSize = 29; + + /***/ + public TurtleRenderer(Turtle turtle) { + this.currentImage = null; + this.images = new Vector(); + this.turtle = turtle; + currentAngle = 0; + } + + /** As an image stays unchanged, there's no need to ever update it. So this method returns always false. + + For further information cf. java.awt.image.ImageObserver. + @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) + */ + public boolean imageUpdate(Image img, int infoflags, + int x, int y, int width, int height) { + return false; + } + + /** Return the current image. + */ + public Image currentImage() { + return this.currentImage; + } + + /** Tell whether the image has changed. + */ + public boolean imageChanged(double angle) { + return (this.currentImage != getImage(angle)); + } + + /** Set the current image to the specified one. */ + private void setCurrentImage(Image image) { + currentImage = image; + } + + /** Choose the image for the angle angle. + */ + private Image getImage(double angle) { + while (angle < 0) { + angle += 2*Math.PI; + } + while (angle >= 2*Math.PI) { + angle -= 2*Math.PI; + } + double res = 2*Math.PI/(double)this.resolution; + int index = (int)(angle/res); + return image(index); + } + + /** Set the current image to the one corresponding to the angle angle. + */ + public void setAngle(double angle) { + currentAngle = angle; + setCurrentImage(getImage(angle)); + } + + /** @return the current angle. */ + protected double getAngle(){ + return currentAngle; + } + + /** Create the images. There are resolution images (i.e. two subsequent + images contain an angle of 2π/ or 360/resolution degrees). + */ + public void init(TurtleFactory factory, int resolution) { + this.resolution = resolution; + Integer res = new Integer(resolution); + double incRes = Math.PI*2/res.doubleValue(); + double angle = 0; + images = new Vector(); + for (int i = 0; i < resolution; i++) { + images.add(factory.turtleImage(turtle.getColor(), + turtle.getPlayground().toScreenAngle(angle), + turtleSize, turtleSize)); + angle += incRes; + } + setCurrentImage(getImage(currentAngle)); + } + + /** Tell how many images this TurtleRenderer holds */ + private int countImages() { + return this.images.size(); + } + + /** Get the image at index */ + private Image image(int index) { + return (Image)this.images.elementAt(index); + } + + /** This method is responsible for painting the turtle onto the + playground at (x, y). + */ + public final void paint(double x, double y) { + internalPaint(x, y, turtle.getPlayground().getGraphics()); + } + + /** This method is responsible for painting the turtle onto the + playground at p. + */ + public final void paint(Point2D.Double p) { + internalPaint(p.x, p.y, turtle.getPlayground().getGraphics()); + } + + /** This method is responsible for painting the Turtle + at (x, y).
+ The Graphics argument tells where to paint. + */ + public final void paint(double x, double y, Graphics g) { + internalPaint(x, y, g); + } + + /** This method is responsible for painting the Turtle + at p.
+ The Graphics argument tells where to paint. + */ + public void paint(Point2D.Double p, Graphics g){ + internalPaint(p.x, p.y, g); + } + + /** Call clipPaint and wrapPaint(). + + You should override this method only, if you add a new (edge) + behaviour to the turtle. I recommend to you then to first call this + method from the overriding one. +
+ If you want to change anything about the real painting, override + clipPaint or wrapPaint. + + @see #clipPaint(int, int, Graphics2D) + @see #wrapPaint(int, int, Graphics2D) + */ + protected void internalPaint(double x, double y, Graphics g) { + if(turtle.isClip()){ + Point2D.Double p = + calcTopLeftCorner(turtle.getPlayground().toScreenCoords(x, y)); + clipPaint((int)p.x, (int)p.y, (Graphics2D)g); + } + else if(turtle.isWrap()){ + Point2D.Double p = + calcTopLeftCorner(turtle.getPlayground().toScreenCoords(x, y)); + wrapPaint((int)p.x, (int)p.y, (Graphics2D)g); + } + } + + /** Define how to paint in clip mode and do it */ + protected void clipPaint(int x, int y, Graphics2D g2D) { + g2D.drawImage(currentImage, x, y, this); + } + + /** Define how to paint in wrap mode and do it */ + protected void wrapPaint(int x, int y, Graphics2D g2D) { + int pWidth = turtle.getPlayground().getWidth(); + int pHeight = turtle.getPlayground().getHeight(); + int paintX = x; + while (paintX > pWidth) { + paintX -= pWidth; + } + while (paintX < 0) { + paintX += pWidth; + } + int paintY = y; + while (paintY > pHeight) { + paintY -= pHeight; + } + while (paintY < 0) { + paintY += pHeight; + } + g2D.drawImage(currentImage, paintX, paintY, this); + int nWidth = currentImage.getWidth(this); + int nHeight = currentImage.getHeight(this); + boolean right = (paintX+nWidth > pWidth); + boolean bottom = (paintY+nHeight > pHeight); + if(right) { + g2D.drawImage(currentImage, + paintX-pWidth, + paintY, + this); + } + if(bottom) { + g2D.drawImage(currentImage, + paintX, + paintY-pHeight, + this); + } + if(right && bottom) { + g2D.drawImage(currentImage, + paintX-pWidth, + paintY-pHeight, + this); + } + } + + /** Compute the x-coordinate of the top left corner of the Turtle image + (it depends on the specified x-coordinate and the image width). + */ + protected int calcTopLeftCornerX(double x) { + int intX = (int)x; + int nWidth; + if(currentImage == null) { + setCurrentImage(new TurtleFactory(). + turtleImage(turtle.getColor(), getAngle(), turtleSize, turtleSize)); + } + nWidth = this.currentImage.getWidth(this); + // the center of the turtle lies on the turtle's location: + intX -= nWidth/2; + return intX; // top left corner of the Turtle's image + } + + /** Compute the y-coordinate of the top left corner of the Turtle image + (it depends on the specified y-coordinate and the image height). + */ + protected int calcTopLeftCornerY(double y) { + int intY = (int)y; + if(currentImage == null) { + setCurrentImage(new TurtleFactory(). + turtleImage(turtle.getColor(), getAngle(), turtleSize, turtleSize)); + } + int nHeight = currentImage.getHeight(this); + // the center of the turtle lies on the turtle's location: + intY -= nHeight/2; + + return intY; // top left corner of the Turtle's image + } + /** Compute the top left corner of the Turtle image + (dependent on the specified x- and y-coordinate and the image + width and height. + */ + protected Point2D.Double calcTopLeftCorner(double x, double y) { + if(currentImage == null) { + setCurrentImage(new TurtleFactory(). + turtleImage(turtle.getColor(), getAngle(), turtleSize, turtleSize)); + } + int w = currentImage.getWidth(this); + int h = currentImage.getHeight(this); + return new Point2D.Double(x-w/2, y-h/2); + } + + /** Compute the top left corner of the Turtle image + (dependent on the specified point p and the image + width and height. + */ + protected Point2D.Double calcTopLeftCorner(Point2D.Double p) { + return calcTopLeftCorner(p.x, p.y); + } +} + + + + + + + + + + + + + + + + + + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/package.bluej b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/package.bluej new file mode 100644 index 0000000..4843072 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/ch/package.bluej @@ -0,0 +1,26 @@ +#BlueJ package file +objectbench.height=155 +objectbench.width=760 +package.divider.horizontal=0.6 +package.divider.vertical=0.6766467065868264 +package.editor.height=332 +package.editor.width=649 +package.editor.x=379 +package.editor.y=72 +package.frame.height=600 +package.frame.width=800 +package.numDependencies=0 +package.numTargets=1 +package.showExtends=true +package.showUses=true +readme.height=58 +readme.name=@README +readme.width=47 +readme.x=10 +readme.y=10 +target1.height=62 +target1.name=aplu +target1.type=PackageTarget +target1.width=80 +target1.x=180 +target1.y=10 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/eval.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/eval.java new file mode 100644 index 0000000..97c8ff0 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/eval.java @@ -0,0 +1,50 @@ +public class Eval { + + public static Wrap getOb(Object o) { + return new Wrap(o); + } + + protected static Object getOb(final String s) { + return new Object() {public String result = s;}; + } + + protected static Object getOb(final boolean b) { + return new Object() {public boolean result = b;}; + } + + protected static Object getOb(final byte b) { + return new Object() {public byte result = b;}; + } + + protected static Object getOb(final char c) { + return new Object() {public char result = c;}; + } + + protected static Object getOb(final double d) { + return new Object() {public double result = d;}; + } + + protected static Object getOb(final float f) { + return new Object() {public float result = f;}; + } + + protected static Object getOb(final int i) { + return new Object() {public int result = i;}; + } + + protected static Object getOb(final long l) { + return new Object() {public long result = l;}; + } + protected static Object getOb(final short s) { + return new Object() {public short result = s;}; + } +} + + +class Wrap { + public Object result; + + Wrap(Object result) { + this.result = result; + } +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/inout.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/inout.java new file mode 100644 index 0000000..d702d54 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/inout.java @@ -0,0 +1,98 @@ +import java.io.*; + +/** +Support class for console input and output of numeric values.

+ +Example for input:
+ int age = InOut.readInt("Your age: ");

+ +Example for output:
+ System.out.println("price: " + InOut.format2(prize) + "Euro");
+ System.out.println("percent: " + InOut.formatN(percent, 1) + " %"); +*/ + + +public class InOut { + + /** Formats a double-value with 2 decimal digits. */ + public static String format2(double d) { + return String.format("%.2f", d); + } + + /** Formats a double-value with N decimal digits. */ + public static String formatN(double d, int N) { + return String.format("%." + N + "f", d); + } + + /** Reads a boolean-value from console. */ + public static boolean readBoolean(String prompt) { + final String[] trueValues = + { "1", "y", "t", "j", "w", "yes", "true", "ja", "wahr", "ok" }; + System.out.print(prompt); + String input = readln().toLowerCase(); + for (int i = 0; i < trueValues.length; ++i) + if (trueValues[i].equals(input)) + return true; + return false; + } + + /** Reads a char-value from console. */ + public static char readChar(String prompt) { + System.out.print(prompt); + return readln().charAt(0); + } + + /** Reads a double-value from console. */ + public static double readDouble(String prompt) { + System.out.print(prompt); + return Double.parseDouble(readln()); + } + + /** Reads a float-value from console. */ + public static float readFloat(String prompt) { + System.out.print(prompt); + return Float.parseFloat(readln()); + } + + /** Reads an int-value from console. */ + public static int readInt(String prompt) { + System.out.print(prompt); + return Integer.parseInt(readln()); + } + + /** Reads a long-value from console. */ + public static long readLong(String prompt) { + System.out.print(prompt); + return Long.parseLong(readln()); + } + + /** Reads a string-value from console. */ + public static String readString(String prompt) { + System.out.print(prompt); + return readln(); + } + + /** Reads a string-value from console without prompt. + For use at the end of a console program. */ + public static String readln() { + try { + return Input.readLine(); + } catch(Exception e) { + return ""; + } + } + + private static BufferedReader Input; + + static { + try { + Input = new BufferedReader(new InputStreamReader(System.in)); + } + catch (Exception e) { + System.out.println("console input not possible."); + } + } + + + +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/je/package.bluej b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/je/package.bluej new file mode 100644 index 0000000..9f468a7 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/je/package.bluej @@ -0,0 +1,26 @@ +#BlueJ package file +objectbench.height=155 +objectbench.width=760 +package.divider.horizontal=0.6 +package.divider.vertical=0.6766467065868264 +package.editor.height=332 +package.editor.width=649 +package.editor.x=379 +package.editor.y=72 +package.frame.height=600 +package.frame.width=800 +package.numDependencies=0 +package.numTargets=1 +package.showExtends=true +package.showUses=true +readme.height=58 +readme.name=@README +readme.width=47 +readme.x=10 +readme.y=10 +target1.height=62 +target1.name=util +target1.type=PackageTarget +target1.width=80 +target1.x=180 +target1.y=10 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/je/util/package.bluej b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/je/util/package.bluej new file mode 100644 index 0000000..5742d82 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/je/util/package.bluej @@ -0,0 +1,27 @@ +#BlueJ package file +objectbench.height=155 +objectbench.width=760 +package.divider.horizontal=0.6 +package.divider.vertical=0.6766467065868264 +package.editor.height=332 +package.editor.width=649 +package.editor.x=399 +package.editor.y=92 +package.frame.height=600 +package.frame.width=800 +package.numDependencies=0 +package.numTargets=1 +package.showExtends=true +package.showUses=true +readme.height=58 +readme.name=@README +readme.width=47 +readme.x=10 +readme.y=10 +target1.height=50 +target1.name=Turtle +target1.showInterface=false +target1.type=ClassTarget +target1.width=80 +target1.x=180 +target1.y=10 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/je/util/turtle.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/je/util/turtle.java new file mode 100644 index 0000000..4a704ad --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/je/util/turtle.java @@ -0,0 +1,311 @@ +package je.util; +/* + * Class : Turtle + * Copyright: (c) Gerhard Röhner + * + * History + * -------- + * 3.00 2000.10.10 first version as java class + * 3.01 2002.10.22 DrawDynamic + * 3.02 2010.10.11 sleepTime for paint delay + * 3.03 2012.03.20 cartesian coordinate system, used with originX, originY, setOrigin + * 3.04 2015.01.24 english version, integrated component + */ + + +import java.awt.*; +import java.awt.image.*; +import java.awt.event.*; + +/** + * This class is a turtle component for simple graphic programming. + * + * @see + * @author Gerhard Röhner + * @version 3.03 20/03/2012 + */ + + +public class Turtle extends Canvas { + + // -- private Attribute ------------------------------------------------------ + + private BufferedImage myBufferedImage; + private Graphics myBufferedGraphics; + private Color foreground; + private Color background; + private static final double piDurch180 = Math.PI / 180; + + // -- public attributes ----------------------------------------------------- + + /** + * turtleX is the x-coordinate of the turtle + *

+ * Example:

myTurtle.turtleX = 100;
+ */ + public double turtleX; + + /** + * turtleY is the y-coordinate of the turtle. + *

+ * Example:

myTurtle.turtleY = 200;
+ */ + public double turtleY; + + /** + * turtleW is the current angle of the turtle in the range form 0 to 360 degrees. + *

+ * Example:

myTurtle.turtleW = 180;
+ */ + public double turtleW; + + /** + * originX is the x-position of the cartesian coodinate system within the turtle canvas. + *

+ * Example:

myTurtle.originX = 0;
+ */ + public double originX; + + /** + * originY is the y-position of the cartesian coodinate system within the turtle canvas. + *

+ * Example:

myTurtle.originY = 100;
+ */ + public double originY; + + /** + * If drawDynamic is true you can watch the drawing of the turtle. + *

+ * Example:

myTurtle.drawDynamic = true;
+ */ + public boolean drawDynamic; + + /** + * For drawDynamic = true you set the delay in milliseconds for drawing. + *

+ * Example:

myTurtle.sleepTime = 500;
+ */ + public int sleepTime = 0; + + // --- constructor ----------------------------------------------------------- + + /** + * Creates a Turtle with a canvas. + * At the beginning the Turtle is placed in the middle of it's canvas. + * The start angle is 0 degree, which means the Turtle looks to the right. + * The background color is white, the drawing color black. + *

+ * The turtle position can easily be changed by clicking into the canvas. + *

+ * The size of the canvas can easily be changed with the mouse. + *

+ * Example:

Turtle myTurtle = new Turtle();
+ */ + + public Turtle() { + myBufferedImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); + myBufferedGraphics = myBufferedImage.getGraphics(); + + setForeground(Color.black); + setBackground(Color.white); + drawDynamic = true; + + addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent evt) { + turtleMouseClicked(evt);}}); + addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent evt) { + turtleResized(evt);}}); + setOrigin(50, 50); + } + + private void turtleMouseClicked(MouseEvent evt) { + turtleX = evt.getX() - originX; + turtleY = originY - evt.getY(); + turtleW = 0; + } + + private void turtleResized(ComponentEvent evt) { + int width = getWidth(); + int height = getHeight(); + + BufferedImage newBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics newGraphics = newBufferedImage.getGraphics(); + newGraphics.setColor(background); + newGraphics.fillRect(0, 0, width, height); + newGraphics.setColor(foreground); + newGraphics.drawImage(myBufferedImage, 0, 0, this); + + turtleX = 0; + turtleY = 0; + turtleW = 0; + setOrigin(width / 2, height / 2); + + myBufferedImage = newBufferedImage; + myBufferedGraphics = newGraphics; + } + + public boolean isDoubleBuffered() { + return true; + } + + private void wTurtleMod360() { + while (turtleW >= 360) + turtleW = turtleW - 360; + while (turtleW < 0) + turtleW = turtleW + 360; + } + + // --- angle and turns ------------------------------------------------------- + + /** + * Turns the angle of the turtle relativ by the parameter angle. + * Positive values means a turn right, negative a turn left. + *

+ * Example:

myTurtle.turn(-90);
+ */ + public void turn(double angle) { + turtleW = turtleW + angle; + wTurtleMod360(); + } + + /** + * Sets the angle of the turtle absolute by the parameter angle. + * The angle increases counterclockwise, therefore + * right = 0, top = 90, left = 180, bottom = 270. + *

+ * Example:

myTurtle.turnto(270);
+ */ + public void turnto(double angle) { + turtleW = angle; + wTurtleMod360(); + } + + // --- Drawing --------------------------------------------------------------- + + /** + * The Turtle draws a line of the length specified in the current direction. + *

+ * Example:

myTurtle.draw(100);
+ */ + public void draw(double length) { + drawto(turtleX + length * Math.cos(turtleW * piDurch180), + turtleY + length * Math.sin(turtleW * piDurch180)); + } + + /** + * The Turtle draws a line form the current position (turtleX, turtleY) to the + * position (x, y) relativ to the cartesian coordinate system. + *

+ * Example:

myTurtle.drawto(200, 300);
+ */ + public void drawto(double x, double y) { + int x1 = (int) (originX + turtleX); + int x2 = (int) (originX + x); + int y1 = (int) (originY - turtleY); + int y2 = (int) (originY - y); + + myBufferedGraphics.drawLine(x1, y1, x2, y2); + if (drawDynamic){ + getGraphics().drawLine(x1, y1, x2, y2); + try { + Thread.currentThread().sleep(sleepTime); + } catch(InterruptedException e) { + } + } else + repaint(); + + turtleX = x; + turtleY = y; + } + + // --- Moving ---------------------------------------------------------------- + + /** + * The Turtle moves without drawing the length specified in the current + * direction. + *

+ * Example:

myTurtle.move(100);
+ */ + public void move(double length) { + turtleX = turtleX + length * Math.cos (turtleW * piDurch180); + turtleY = turtleY + length * Math.sin (turtleW * piDurch180); + } + + /** + * The Turtle moves without drawing to position (x, y) relativ to the + * cartesian coordinate system. + *

+ * Example:

myTurtle.moveto(100, 200);
+ */ + public void moveto(double x, double y) { + turtleX = x; + turtleY = y; + } + + // --- set origin ----------------------------------------------------------- + + /** + * Sets the origin of the cartesian coordinate system within the turtle's canvas. + *

+ * Example:

myTurtle.setOrigin(100, 200);
+ */ + public void setOrigin(double x, double y) { + originX = x; + originY = y; + } + + // --- fore- and background color -------------------------------------------- + + /** + * Sets the drawing color of the Turtle to color c. + *

+ * Example:

myTurtle.setForeground(Color.red);
+ */ + public void setForeground(Color c) { + foreground = c; + myBufferedGraphics.setColor(foreground); + super.setForeground(foreground); + } + + /** + * Sets the canvas color of the Turtle to color c. + *

+ * Example:

myTurtle.setBackground(Color.blue); 
+ */ + public void setBackground(Color c) { + background = c; + myBufferedGraphics.setColor(background); + myBufferedGraphics.fillRect(0, 0, getWidth(), getHeight()); + myBufferedGraphics.setColor(foreground); + repaint(); + } + + /** + * Clear the Turtle's canvas with the background color. + *

+ * Example:

myTurtle.clear();
+ */ + public void clear() { + setBackground(background); + getGraphics().drawImage(myBufferedImage, 0, 0, this); + repaint(); + } + + // --- Showing -------------------------------------------------------------- + + /** + * Shows the Turtle's canvas. + */ + public void paint(Graphics g) { + g.drawImage(myBufferedImage, 0, 0, this); + } + + /** + * Updates the Turtle's canvas. + */ + public void update(Graphics g) { + paint(g); + } + +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/jnumberfield.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/jnumberfield.java new file mode 100644 index 0000000..fd41a78 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/jnumberfield.java @@ -0,0 +1,129 @@ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.util.*; + +/** +Swing-component for input and output of numeric values. +*/ + +public class JNumberField extends JTextField { + + /** constructor for a JNumberField */ + public JNumberField() { + enableEvents(AWTEvent.KEY_EVENT_MASK); + } + + /** Gets a double-value from the JNumberField. */ + public double getDouble() { + Double d = new Double(getText()); + return d.doubleValue(); + } + + /** Gets a float-value from the JNumberField. */ + public float getFloat() { + Double d = new Double(getText()); + return d.floatValue(); + } + + /** Gets an int-value from the JNumberField. */ + public int getInt() { + Double d = new Double(getText()); + return d.intValue(); + } + + /** Gets a long-value from the JNumberField. */ + public long getLong() { + Double d = new Double(getText()); + return d.longValue(); + } + + /** Checks wether the JNumberField contains a valid numeric value. */ + public boolean isNumeric() { + final String Digits = "(\\p{Digit}+)"; + final String HexDigits = "(\\p{XDigit}+)"; + // an exponent is 'e' or 'E' followed by an optionally + // signed decimal integer. + final String Exp = "[eE][+-]?"+Digits; + final String fpRegex = + ("[\\x00-\\x20]*"+ // Optional leading "whitespace" + "[+-]?(" + // Optional sign character + "NaN|" + // "NaN" string + "Infinity|" + // "Infinity" string + + // A decimal floating-point string representing a finite positive + // number without a leading sign has at most five basic pieces: + // Digits . Digits ExponentPart FloatTypeSuffix + // + // Since this method allows integer-only strings as input + // in addition to strings of floating-point literals, the + // two sub-patterns below are simplifications of the grammar + // productions from the Java Language Specification, 2nd + // edition, section 3.10.2. + + // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt + "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ + + // . Digits ExponentPart_opt FloatTypeSuffix_opt + "(\\.("+Digits+")("+Exp+")?)|"+ + + // Hexadecimal strings + "((" + + // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "(\\.)?)|" + + + // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" + + + ")[pP][+-]?" + Digits + "))" + + "[fFdD]?))" + + "[\\x00-\\x20]*");// Optional trailing "whitespace" + + return java.util.regex.Pattern.matches(fpRegex, getText()); + } + + /** Sets a double-value into the JNumberField. */ + public void setDouble(double d) { + setText(String.valueOf(d)); + } + + /** Sets a double-value with N digits into the JNumberField. */ + public void setDouble(double d, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", d)); + } + + /** Sets a float-value into the JNumberField. */ + public void setFloat(float f) { + setText(String.valueOf(f)); + } + + /** Sets a float-value with N digits into the JNumberField. */ + public void setFloat(float f, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", f)); + } + + /** Sets an int-value into the JNumberField. */ + public void setInt(int i) { + setText(String.valueOf(i)); + } + + /** Sets a long-value into the JNumberField. */ + public void setLong(long l) { + setText(String.valueOf(l)); + } + + /** Clears the JNumberField */ + public void clear() { + setText(""); + } + + protected void processKeyEvent(KeyEvent e) { + super.processKeyEvent(e); + if (isNumeric() || getText().equals("-") || + getText().equals("") || getText().equals(".")) + setBackground(Color.white); + else + setBackground(Color.red); + } + +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/numberfield.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/numberfield.java new file mode 100644 index 0000000..ca7ef01 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/numberfield.java @@ -0,0 +1,128 @@ +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** +AWT-component for input and output of numeric values. +*/ + +public class NumberField extends TextField { + + /** constructor for a NumberField */ + public NumberField() { + enableEvents(AWTEvent.KEY_EVENT_MASK); + } + + /** Gets a double-value from the NumberField. */ + public double getDouble() { + Double d = new Double(getText()); + return d.doubleValue(); + } + + /** Gets a float-value from the NumberField. */ + public float getFloat() { + Double d = new Double(getText()); + return d.floatValue(); + } + + /** Gets an int-value from the NumberField. */ + public int getInt() { + Double d = new Double(getText()); + return d.intValue(); + } + + /** Gets a long-value from the NumberField. */ + public long getLong() { + Double d = new Double(getText()); + return d.longValue(); + } + + /** Checks wether the NumberField contains a valid numeric value. */ + public boolean isNumeric() { + final String Digits = "(\\p{Digit}+)"; + final String HexDigits = "(\\p{XDigit}+)"; + // an exponent is 'e' or 'E' followed by an optionally + // signed decimal integer. + final String Exp = "[eE][+-]?"+Digits; + final String fpRegex = + ("[\\x00-\\x20]*"+ // Optional leading "whitespace" + "[+-]?(" + // Optional sign character + "NaN|" + // "NaN" string + "Infinity|" + // "Infinity" string + + // A decimal floating-point string representing a finite positive + // number without a leading sign has at most five basic pieces: + // Digits . Digits ExponentPart FloatTypeSuffix + // + // Since this method allows integer-only strings as input + // in addition to strings of floating-point literals, the + // two sub-patterns below are simplifications of the grammar + // productions from the Java Language Specification, 2nd + // edition, section 3.10.2. + + // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt + "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ + + // . Digits ExponentPart_opt FloatTypeSuffix_opt + "(\\.("+Digits+")("+Exp+")?)|"+ + + // Hexadecimal strings + "((" + + // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "(\\.)?)|" + + + // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" + + + ")[pP][+-]?" + Digits + "))" + + "[fFdD]?))" + + "[\\x00-\\x20]*");// Optional trailing "whitespace" + + return java.util.regex.Pattern.matches(fpRegex, getText()); + } + + /** Sets a double-value into the NumberField. */ + public void setDouble(double d) { + setText(String.valueOf(d)); + } + + /** Sets a double-value with N digits into the NumberField. */ + public void setDouble(double d, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", d)); + } + + /** Sets a float-value into the NumberField. */ + public void setFloat(float f) { + setText(String.valueOf(f)); + } + + /** Sets a float-value with N digits into the NumberField. */ + public void setFloat(float f, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", f)); + } + + /** Sets an int-value into the NumberField. */ + public void setInt(int i) { + setText(String.valueOf(i)); + } + + /** Sets a long-value into the NumberField. */ + public void setLong(long l) { + setText(String.valueOf(l)); + } + + /** Clears the NumberField */ + public void clear() { + setText(""); + } + + protected void processKeyEvent(KeyEvent e) { + super.processKeyEvent(e); + if (isNumeric() || getText().equals("-") || + getText().equals("") || getText().equals(".")) + setBackground(Color.white); + else + setBackground(Color.red); + } + +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/package.bluej b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/package.bluej new file mode 100644 index 0000000..7c6db23 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jeclasses/package.bluej @@ -0,0 +1,79 @@ +#BlueJ package file +editor.fx.0.height=738 +editor.fx.0.width=816 +editor.fx.0.x=275 +editor.fx.0.y=0 +objectbench.height=93 +objectbench.width=760 +package.divider.horizontal=0.6 +package.divider.vertical=0.8003992015968064 +package.editor.height=394 +package.editor.width=649 +package.editor.x=359 +package.editor.y=52 +package.frame.height=600 +package.frame.width=800 +package.numDependencies=0 +package.numTargets=8 +package.showExtends=true +package.showUses=true +project.charset=windows-1252 +readme.height=58 +readme.name=@README +readme.width=47 +readme.x=10 +readme.y=10 +target1.height=50 +target1.name=JEClassLoader +target1.showInterface=false +target1.type=ClassTarget +target1.width=110 +target1.x=10 +target1.y=90 +target2.height=62 +target2.name=ch +target2.type=PackageTarget +target2.width=80 +target2.x=110 +target2.y=10 +target3.height=62 +target3.name=je +target3.type=PackageTarget +target3.width=80 +target3.x=200 +target3.y=10 +target4.height=50 +target4.name=JEControl +target4.showInterface=false +target4.type=ClassTarget +target4.width=80 +target4.x=120 +target4.y=90 +target5.height=50 +target5.name=Eval +target5.showInterface=false +target5.type=ClassTarget +target5.width=80 +target5.x=10 +target5.y=150 +target6.height=50 +target6.name=InOut +target6.showInterface=false +target6.type=ClassTarget +target6.width=80 +target6.x=100 +target6.y=150 +target7.height=50 +target7.name=NumberField +target7.showInterface=false +target7.type=ClassTarget +target7.width=110 +target7.x=190 +target7.y=150 +target8.height=50 +target8.name=JNumberField +target8.showInterface=false +target8.type=ClassTarget +target8.width=110 +target8.x=10 +target8.y=210 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jnumberfield.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jnumberfield.java new file mode 100644 index 0000000..fd41a78 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/jnumberfield.java @@ -0,0 +1,129 @@ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.util.*; + +/** +Swing-component for input and output of numeric values. +*/ + +public class JNumberField extends JTextField { + + /** constructor for a JNumberField */ + public JNumberField() { + enableEvents(AWTEvent.KEY_EVENT_MASK); + } + + /** Gets a double-value from the JNumberField. */ + public double getDouble() { + Double d = new Double(getText()); + return d.doubleValue(); + } + + /** Gets a float-value from the JNumberField. */ + public float getFloat() { + Double d = new Double(getText()); + return d.floatValue(); + } + + /** Gets an int-value from the JNumberField. */ + public int getInt() { + Double d = new Double(getText()); + return d.intValue(); + } + + /** Gets a long-value from the JNumberField. */ + public long getLong() { + Double d = new Double(getText()); + return d.longValue(); + } + + /** Checks wether the JNumberField contains a valid numeric value. */ + public boolean isNumeric() { + final String Digits = "(\\p{Digit}+)"; + final String HexDigits = "(\\p{XDigit}+)"; + // an exponent is 'e' or 'E' followed by an optionally + // signed decimal integer. + final String Exp = "[eE][+-]?"+Digits; + final String fpRegex = + ("[\\x00-\\x20]*"+ // Optional leading "whitespace" + "[+-]?(" + // Optional sign character + "NaN|" + // "NaN" string + "Infinity|" + // "Infinity" string + + // A decimal floating-point string representing a finite positive + // number without a leading sign has at most five basic pieces: + // Digits . Digits ExponentPart FloatTypeSuffix + // + // Since this method allows integer-only strings as input + // in addition to strings of floating-point literals, the + // two sub-patterns below are simplifications of the grammar + // productions from the Java Language Specification, 2nd + // edition, section 3.10.2. + + // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt + "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ + + // . Digits ExponentPart_opt FloatTypeSuffix_opt + "(\\.("+Digits+")("+Exp+")?)|"+ + + // Hexadecimal strings + "((" + + // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "(\\.)?)|" + + + // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" + + + ")[pP][+-]?" + Digits + "))" + + "[fFdD]?))" + + "[\\x00-\\x20]*");// Optional trailing "whitespace" + + return java.util.regex.Pattern.matches(fpRegex, getText()); + } + + /** Sets a double-value into the JNumberField. */ + public void setDouble(double d) { + setText(String.valueOf(d)); + } + + /** Sets a double-value with N digits into the JNumberField. */ + public void setDouble(double d, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", d)); + } + + /** Sets a float-value into the JNumberField. */ + public void setFloat(float f) { + setText(String.valueOf(f)); + } + + /** Sets a float-value with N digits into the JNumberField. */ + public void setFloat(float f, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", f)); + } + + /** Sets an int-value into the JNumberField. */ + public void setInt(int i) { + setText(String.valueOf(i)); + } + + /** Sets a long-value into the JNumberField. */ + public void setLong(long l) { + setText(String.valueOf(l)); + } + + /** Clears the JNumberField */ + public void clear() { + setText(""); + } + + protected void processKeyEvent(KeyEvent e) { + super.processKeyEvent(e); + if (isNumeric() || getText().equals("-") || + getText().equals("") || getText().equals(".")) + setBackground(Color.white); + else + setBackground(Color.red); + } + +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/meta-inf/manifest.mf b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/meta-inf/manifest.mf new file mode 100644 index 0000000..39b10ac --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/meta-inf/manifest.mf @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Class-Path: JEClasses.jar jdom-1.1.3.jar +Created-By: 1.8.0_161 (Oracle Corporation) +Main-Class: BreakVigenere + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/numberfield.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/numberfield.java new file mode 100644 index 0000000..ca7ef01 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_autokorrelation/numberfield.java @@ -0,0 +1,128 @@ +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** +AWT-component for input and output of numeric values. +*/ + +public class NumberField extends TextField { + + /** constructor for a NumberField */ + public NumberField() { + enableEvents(AWTEvent.KEY_EVENT_MASK); + } + + /** Gets a double-value from the NumberField. */ + public double getDouble() { + Double d = new Double(getText()); + return d.doubleValue(); + } + + /** Gets a float-value from the NumberField. */ + public float getFloat() { + Double d = new Double(getText()); + return d.floatValue(); + } + + /** Gets an int-value from the NumberField. */ + public int getInt() { + Double d = new Double(getText()); + return d.intValue(); + } + + /** Gets a long-value from the NumberField. */ + public long getLong() { + Double d = new Double(getText()); + return d.longValue(); + } + + /** Checks wether the NumberField contains a valid numeric value. */ + public boolean isNumeric() { + final String Digits = "(\\p{Digit}+)"; + final String HexDigits = "(\\p{XDigit}+)"; + // an exponent is 'e' or 'E' followed by an optionally + // signed decimal integer. + final String Exp = "[eE][+-]?"+Digits; + final String fpRegex = + ("[\\x00-\\x20]*"+ // Optional leading "whitespace" + "[+-]?(" + // Optional sign character + "NaN|" + // "NaN" string + "Infinity|" + // "Infinity" string + + // A decimal floating-point string representing a finite positive + // number without a leading sign has at most five basic pieces: + // Digits . Digits ExponentPart FloatTypeSuffix + // + // Since this method allows integer-only strings as input + // in addition to strings of floating-point literals, the + // two sub-patterns below are simplifications of the grammar + // productions from the Java Language Specification, 2nd + // edition, section 3.10.2. + + // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt + "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ + + // . Digits ExponentPart_opt FloatTypeSuffix_opt + "(\\.("+Digits+")("+Exp+")?)|"+ + + // Hexadecimal strings + "((" + + // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "(\\.)?)|" + + + // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" + + + ")[pP][+-]?" + Digits + "))" + + "[fFdD]?))" + + "[\\x00-\\x20]*");// Optional trailing "whitespace" + + return java.util.regex.Pattern.matches(fpRegex, getText()); + } + + /** Sets a double-value into the NumberField. */ + public void setDouble(double d) { + setText(String.valueOf(d)); + } + + /** Sets a double-value with N digits into the NumberField. */ + public void setDouble(double d, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", d)); + } + + /** Sets a float-value into the NumberField. */ + public void setFloat(float f) { + setText(String.valueOf(f)); + } + + /** Sets a float-value with N digits into the NumberField. */ + public void setFloat(float f, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", f)); + } + + /** Sets an int-value into the NumberField. */ + public void setInt(int i) { + setText(String.valueOf(i)); + } + + /** Sets a long-value into the NumberField. */ + public void setLong(long l) { + setText(String.valueOf(l)); + } + + /** Clears the NumberField */ + public void clear() { + setText(""); + } + + protected void processKeyEvent(KeyEvent e) { + super.processKeyEvent(e); + if (isNumeric() || getText().equals("-") || + getText().equals("") || getText().equals(".")) + setBackground(Color.white); + else + setBackground(Color.red); + } + +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/balkendiagramm.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/balkendiagramm.java new file mode 100644 index 0000000..d64c99b --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/balkendiagramm.java @@ -0,0 +1,76 @@ +import java.awt.*; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; +import javax.swing.*; + +public class Balkendiagramm extends JPanel { + + private double gesamt; + private double haeufigkeit[]; + private double maxwert; + private int verschiebung = 0; + private double haeufigkeit_de[] = { 0.0651, 0.0189, 0.0306, 0.0508, 0.174, 0.0166, 0.0301, 0.0476,0.0755, 0.0027, 0.0121,0.0344,0.0252,0.0978,0.0251,0.0079,0.0002,0.07,0.0727,0.0615,0.0435,0.067,0.0189,0.0003,0.0004,0.0113}; + + + public void setHaeufigkeit(double haeufigkeit[]) { + + this.haeufigkeit = haeufigkeit; + gesamt = 0; + for (int i = 0; i < 26; i++) { + gesamt += haeufigkeit[i]; + } + for (int i = 0; i < 26; i++) { + haeufigkeit[i] /= gesamt; + } + maxwert = 0.20; + + } + + public void setVerschiebung(int verschiebung) { + if (verschiebung >= 0 && verschiebung < 26) { + this.verschiebung = verschiebung; + + } else { + this.verschiebung = 0; + } // end of if-else + } + + public void paintComponent(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + super.paintComponent(g2); + Dimension d = getSize(null); + //Skalieren auf 100x100 mit y-Invertierung + g2.scale(d.getWidth() / 120.0, -d.getHeight() / 100.0); + // Ursprung verschieben nach (15,-90) + g2.translate(5, -90); + // Linien etwas breiter + g2.setStroke(new BasicStroke(1.5f)); + // x-Achse zeichnen + g2.draw(new Line2D.Double(0, 0, 104, 0)); + // Linien etwas dünner + g2.setStroke(new BasicStroke(0.5f)); + // Deutsche Häufigkeit grau + g2.setColor(Color.darkGray); + // Säulen zeichnen + for (int i = 0; i < 26; i++) { + g2.fill(new Rectangle2D.Double(4 * i+1, 0, 2, haeufigkeit_de[i] / maxwert *100)); + } + // Texthäufigkeit blau + g2.setColor(Color.blue); + // Säulen zeichnen + for (int i = 0; i < 26; i++) { + g2.fill(new Rectangle2D.Double(4 * i, 0, 2, haeufigkeit[(i+verschiebung)%26] / maxwert *100)); + } + // y-Invertierung rückgängig machen + g2.scale(1, -1); + // Beschriftung x-Achse + String xAchse = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + // Fontgröße für Beschriftung ändern + g2.setColor(Color.black); + g2.setFont(g2.getFont().deriveFont(5f)); + for (int i = 0; i < 26; i++) { + g2.drawString(xAchse.substring(i, i + 1), + i * 4, +6); + } + } + } diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/baustein.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/baustein.java new file mode 100644 index 0000000..55954a1 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/baustein.java @@ -0,0 +1,42 @@ +public class Baustein implements Comparable{ + + // Anfang Attribute + private String zeichen; + private int anzahl; + // Ende Attribute + + public Baustein(String zeichen) { + super(); + anzahl = 1; + this.zeichen = zeichen; + } + // Anfang Methoden + + + + public int compareTo(Baustein c) { + + int anz = c.getAnzahl(); + + //ascending order + return anz - this.anzahl; + + //descending order + //return compareQuantity - this.quantity; + + } + public String getZeichen() { + return zeichen; + } + + public int getAnzahl() { + return anzahl; + } + + public void incAnzahl() { + anzahl++; + } + + + // Ende Methoden +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/breakvigenere.jar b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/breakvigenere.jar new file mode 100644 index 0000000000000000000000000000000000000000..37e51fdd1a8255518c1a1780c9fbc93ecda1ee9b GIT binary patch literal 33268 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 T(tv;n0e^G>GqBHx=Xd`PG1g9< literal 0 HcmV?d00001 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/breakvigenere.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/breakvigenere.java new file mode 100644 index 0000000..d150a48 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/breakvigenere.java @@ -0,0 +1,498 @@ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.table.*; +import java.util.ArrayList; +import java.util.Collections; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Highlighter; +import javax.swing.text.Highlighter.HighlightPainter; +import javax.swing.text.BadLocationException; + + +/** + * + * Programm zur Kryptoanalyse + * von monoalphabetischen Substitutionen + * + * @version 1.0 from 23.11.2016 + * @author Thomas Schaller + */ + +public class BreakVigenere extends JFrame { + // Anfang Attribute + private JTextField[] buchstabe; + + private JButton jButton1 = new JButton(); + private JButton jBBuchstabe = new JButton(); + private Balkendiagramm bdText = new Balkendiagramm(); + + private JTextArea jTAKrypto = new JTextArea(""); + private JScrollPane jTAKryptoScrollPane = new JScrollPane(jTAKrypto); + private JTextArea jTAKlartext = new JTextArea(""); + private JScrollPane jTAKlartextScrollPane = new JScrollPane(jTAKlartext); + private JLabel jLKryptotext = new JLabel(); + private JLabel jLKlartext = new JLabel(); + private JLabel jLCopyright = new JLabel(); + private JTextArea jTAKorrelation = new JTextArea(""); + private JScrollPane jTAKorrelationScrollPane = new JScrollPane(jTAKorrelation); + private JTextArea jTAKorrelation2 = new JTextArea(""); + private JScrollPane jTAKorrelation2ScrollPane = new JScrollPane(jTAKorrelation2); + private JSpinner jSpVerschiebung = new JSpinner(); + private SpinnerNumberModel jSpVerschiebungModel = new SpinnerNumberModel(0, 0, 99, 1); + private JNumberField jNFAnzahlTreffer = new JNumberField(); + private JLabel lVerschiebung = new JLabel(); + private JLabel lAnzahlgleicherBuchstaben = new JLabel(); + private JButton jButtonKas = new JButton(); // neu mkl + private int lv, lb, rv, rb; + // Ende Attribute + + public BreakVigenere (String title) { + super (title); + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + int frameWidth = 1013; + int frameHeight = 662; + setSize(frameWidth, frameHeight); + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + int x = (d.width - getSize().width) / 2; + int y = (d.height - getSize().height) / 2; + setLocation(x, y); + Container cp = getContentPane(); + cp.setLayout(null); + // Anfang Komponenten + + jTAKryptoScrollPane.setBounds(16, 24, 665, 105); + jTAKryptoScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + + jTAKrypto.setLineWrap(true); + jTAKrypto.setFont(new Font("Courier New", Font.BOLD, 16)); + jTAKrypto.setText("JMLQMFNSKIOQNXGYZOQEBJLUKXHFCXGVLGBMREAJZCAEKVIFOWJLMFGJLPQZJIYHQQHYJLAFGFLRLQYESTPMHIAWQZFIPPMZMIZGPDOIIIVGTHIIQVKHLVHQOPLNMIKMSWCYKMUIVBREADEQOXLVVMILSMVWYZLVAONSIIVIKVKIVPOIZIEGXHLHCDILKIVPKYAWKTKRIIVQJMRXQZKVHFBVULHRVQYXYMBTKQPYAUSNHLZUSJUJBQTFHRLEKMUIAUTPHXMUTMZGPQXWWVIONINIAONVPIJQTIUWMONWIRLUMIUAMDQIZTWXEKYEXTOELPQNXMZIFEKGOWJONIYDCDVSSCODGTOMMMTKLKMNKRPRLQSRHGPEKMUIUFUHLZMDLJLRBXOGOXMZHYJLAONPBKMDBSYRIONNLHMYKMUDMXTIUOTMXXLBBNAGOWBMHIUDCYTGOWBQTESTPMHIAMVEKMUIZFGFBPINKVGYOQNIUYVPYSHPTQBIYJONGVLRIXVLHFMFKEBWHGTYADMZJETMBQXJHRLQXHPIXDUKYIAEOZLTWXEESTPMHIAMAONIJLQRLVPIZGTKHFMDKWDEZZUGOIQZLIZXMEBIYJITXIUSPZKWJLTEYISHQQYIYACDJIPQRMNVCSUUZESMMZOWJLMZQVFTBARSNIVSOSCEVNGXAMAFGFLPTMYSJEQZLSYQMUTIZZWYBIYWKTRWZPMDLVLMHGCLSIVPKRRIVZCSYXAAJIYIQZKWRIVZYEADMEBSYKMEILSEOQTKLVVQARKOZKVXVKZMVLPWKTYGOAIONHHPMUILADCQXVHXMZCYYHMZJETETEREAIQZOWJLMEORUWXDILLFMZAXGXEUKFLMABOISWEQOWLZQDZZAMWYTMHTIDKRAETXKWNIPAXGOXLQXXJLBUMOLMBPOIIYKTYXHFMZJIZOMZTWHXHQYFLWBUSQLRLUKVLMPQTJVPOQORKIZPOICIZEILPILQTIUETBNEIIBQGYZHMDZEIYTMGYZKMINPAAMDJIUQAEKRZMVPGPSIDQXFYECONXHPAAKMUQIXHIUYBLZAVVLQTLPIZZGGOOTMXXLBBNAGOWBMHIUWWNKKPRVFSEUAQQJIYZWZBSYRMENEUHMXZWPGPEUQPXCYKMUIXQXMVHQEILLTWXEESTPMHIAMAONIZYJEZMAYBUURTMBUSFLMABOISIQZKVWIZUUHLZWZCLYIVPZVPXPQSMBWAUILHYNHKVZGPAHIUIAFGRKEZPGPWLINKXLFMEILYRSFKESWWPOINIEANRAIIXVLHFMFOWJLMDKMOIVRUPNILQXFBGPEZEIIVHKVDIVPKXLFMXREZSJQXIPXAHKVDVNQRXLETBNEIIBQJMLIZMRPLVLUTKZMVHUPBXWDOWJLETRXLFMUJIUQWZUESTPMHIAMAONIUWCNYXPXCFOSUWUQZLVHMZCEYHQQYWJLWZYIPXTMTKLQJXOGOKZGTHZXHXOGOLIFZIKMMEHIYIQFYMTNITXESWWXGRNIDAXXYMBTKQPYAGTHIITXGWVHMDOXHPQQTMZGPQMISIPDZISIWZHEAXQEZEHPJQXXPIUBLSOPMZKVZGPXAKCSZPOIHPXTGFLXMZGGONMIKMSWLDKMVHMDBMLVEDZIYRHGCIJLAQRRHPAYKGOEVUYGOIATOPMWUUZXLPPMZXLIZTOIYDCPOIUEKTOLTFMZGRUXMMRFLVBUYGOIQNKIYJCZJIUIQZKGOMNRXMLVAONIPFMNKWAIPQTHGYUQOWAECEFALMZGTHLRUQZESPAONIPFMZJMLECRKMUIZSKQLMVEGQLRIONWLWQFFIUYVPYSCIZNARKIVEORKHIEYWPGPPOIRPMUTIYIIGLHLVODKVLRLDKLLRSMTRUEPQFYLMVVGLYLCZJIYXABZIYMUVGLYZMDGPSKMYKMUIZFKHLVVQGTVPQFGRPWKTKKLPMTXXLKQABEURQNGXAMAFGHLPTMVSYXIMRFLVBUYZLVEDLISXMMRTOEJQZIBRLNKPSEAAYOLRVIUVAYVPYGOYNPOIWSTKGPWLINKXPWKTKGOMNRXMLVCZMQPXDQXAYJMXZITETBNEIIBGTHZGPXYWLPPUKVGYEGXHLETNKVAMAEILLMJQHIUYBLZHPIVMILQILQSFBGPEZEIIVLAHYIPQTAHVQYPEOVODOJMHMDLVHRHAYIIPIUYIKIDUMIUVMBUVAEAUJILECRARKWKTRYNZWDYXHXBPKVHPJQXXPWKTKMIILUKXHFCXGVLGBMJIZXZUZLLQQGYDBZMDCIUHMZJEIIQMHIYEVPKVZETEOQVVQSORHPDQXAYJMXZIHPXTGFLXMQORGYBDGKLRLUKWLVSDETASODGTOMAONWAEZWKZVVAONPHKDUMIUVMEMIYMMFORKIVRUPNIVPKRQEPDNYUHMDZIUMVHKVNIAEKROIQFARKHQQAVZTZZMPPGPHURAVQFNITMCEBSYKMEILSEOQTITIBTUHLACDJIBRBQXHLQVMSIUZQSKRYIKTOJMVMNKOHRVF"); + jTAKrypto.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent evt) { + jTAKrypto_KeyTyped(evt); + } + }); + cp.add(jTAKryptoScrollPane); + + jTAKlartextScrollPane.setBounds(16, 480, 665, 105); + jTAKlartext.setLineWrap(true); + jTAKlartext.setFont(new Font("Courier New", Font.BOLD, 16)); + cp.add(jTAKlartextScrollPane); + jLKryptotext.setText("Kryptotext"); + jLKryptotext.setBounds(16, 3, 110, 20); + cp.add(jLKryptotext); + jLKlartext.setText("Klartext"); + jLKlartext.setBounds(16, 456, 110, 20); + cp.add(jLKlartext); + jLCopyright.setText("(cc) Schaller (ZPG Informatik) - V1.0 (2017)"); + jLCopyright.setBounds(128, 584, 419, 33); + jLCopyright.setHorizontalAlignment(SwingConstants.CENTER); + jLCopyright.setFont(new Font("Dialog", Font.PLAIN, 12)); + cp.add(jLCopyright); + + // -------------------------------- Tab 1 --------------------------------------------- + JPanel tab1 = new JPanel(); + tab1.setLayout(null); + lv = -1; lb = -1; rv = -1; rb=-1; + jTAKorrelationScrollPane.setBounds(16, 40, 320, 110); + jTAKorrelationScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + jTAKorrelation.setText(jTAKrypto.getText()); + jTAKorrelation.setLineWrap(true); + jTAKorrelation.setEditable(false); + jTAKorrelation.setEnabled(true); + jTAKorrelation.setFont(new Font("Courier New", Font.BOLD, 16)); + jTAKorrelation.addMouseListener(new MouseListener() { + public void mousePressed(MouseEvent e) { + removeSearchHighlight(); + } + + public void mouseReleased(MouseEvent e) { + addSearchHighlight(); + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public void mouseClicked(MouseEvent e) { + } + + }); + + tab1.add(jTAKorrelationScrollPane); + jTAKorrelation2ScrollPane.setBounds(340, 40, 320, 110); + jTAKorrelation2ScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + jTAKorrelation2.setText(jTAKrypto.getText()); + jTAKorrelation2.setLineWrap(true); + jTAKorrelation2.setEditable(false); + jTAKorrelation2.setEnabled(true); + jTAKorrelation2.setFont(new Font("Courier New", Font.BOLD, 16)); + jTAKorrelation2.addMouseListener(new MouseListener() { + public void mousePressed(MouseEvent e) { + //removeSearchHighlight(); + } + + public void mouseReleased(MouseEvent e) { + //addSearchHighlight(); + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public void mouseClicked(MouseEvent e) { + selectHighlight(); + } + + }); + + tab1.add(jTAKorrelation2ScrollPane); + + + JLabel l = new JLabel(); + l.setBounds(350, 155, 162, 20); + l.setText("Vermutete Schlüssellänge:"); + tab1.add(l); + + jSpVerschiebung.setBounds(520, 152, 41, 25); + jSpVerschiebung.setValue(1); + jSpVerschiebung.setModel(jSpVerschiebungModel); + jSpVerschiebung.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent evt) { + jSpVerschiebung_StateChanged(evt); + } + }); + tab1.add(jSpVerschiebung); + + + lVerschiebung.setBounds(200, 10, 310, 20); + lVerschiebung.setText("Angriff auf die Schlüssellänge mit Kasiski-Test"); + tab1.add(lVerschiebung); + l = new JLabel(); + l.setBounds(14, 177, 640, 80); + l.setText("Markiere im linken Textfeld eine Buchstabenfolge. Wird diese dunkel kommt sie mehrmals im Text vor. Suche sie im rechten Textfeld und wähle ein Auftreten aus. Du siehst dann, wie weit die beiden auseinander liegen. Wiederhole dies mehrfach. Die Primfaktoren, die häufig vorkommen, stecken dann vermutlich auch in der Schlüssellänge. Stelle die Schlüssellänge entsprechend ein und gehe zu Schritt 2."); + tab1.add(l); + lAnzahlgleicherBuchstaben.setBounds(16, 155, 300, 20); + lAnzahlgleicherBuchstaben.setText("Abstand: "); + lAnzahlgleicherBuchstaben.setHorizontalAlignment(JLabel.CENTER); + tab1.add(lAnzahlgleicherBuchstaben); + + jButtonKas.setBounds(16, 10, 150, 25); // neu mkl + jButtonKas.setText("Text übernehmen"); + jButtonKas.setMargin(new Insets(2, 2, 2, 2)); + jButtonKas.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + jButtonKas_ActionPerformed(evt); + } + }); + tab1.add(jButtonKas); + // ---------------------------------- Tab 2 ------------------------------- + JPanel tab2 = new JPanel(); + tab2.setLayout(null); + + l = new JLabel(); + l.setBounds(16, 10, 310, 20); + l.setText("Angriff auf die Teiltexte mit Häufigkeitsanalyse"); + tab2.add(l); + + l = new JLabel(); + l.setBounds(380, 10, 300, 25); + l.setText("Buchstabenhäufigkeit Deutsch"); + tab2.add(l); + + l = new JLabel(); + l.setBounds(16, 40, 300, 25); + l.setText("Schlüssel"); + tab2.add(l); + + l = new JLabel(); + l.setBounds(16, 100, 300, 100); + l.setText("Versuche den Schlüssel zu knacken, indem du in jedem Teiltext die Häufigkeitsverteilung der Buchstaben mit der üblichen Häufigkeitsverteilung in deutschen Texten in Einklang bringst."); + tab2.add(l); + + double[] h = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + bdText.setBounds(380,40,300,180); + bdText.setHaeufigkeit(h); + tab2.add(bdText); + + jButton1.setBounds(16, 210, 193, 25); + jButton1.setText("Entschlüsselung versuchen"); + jButton1.setMargin(new Insets(2, 2, 2, 2)); + jButton1.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + jButton1_ActionPerformed(evt); + } + }); + tab2.add(jButton1); + + + + // Ende Komponenten + buchstabe = new JTextField[26]; + for (int i = 0; i<26 ;i++ ) { + buchstabe[i] = new JTextField(); + buchstabe[i].setBounds(16+i*25, 65, 25, 25); + buchstabe[i].setText("A"); + buchstabe[i].setHorizontalAlignment(SwingConstants.CENTER); + buchstabe[i].setVisible(false); + buchstabe[i].addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent evt) { + highlightKryptotext(evt); + } + }); + buchstabe[i].addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + e.consume(); + } + + public void keyTyped(KeyEvent e) { + e.consume(); + } + + public void keyPressed(KeyEvent e) { + JTextField textField = (JTextField) e.getSource(); + String text = textField.getText(); + if ((e.getKeyChar()>='a' && e.getKeyChar()<='z') ||(e.getKeyChar()>='A' && e.getKeyChar()<='Z')) { + text = ""+e.getKeyChar(); + } + if (e.getKeyChar()==' ' || e.getKeyChar() == KeyEvent.VK_BACK_SPACE || e.getKeyChar() == KeyEvent.VK_DELETE) { + text = ""; + + } // end of if + textField.setText(text.toUpperCase()); + e.consume(); + if (textField.getText().length()>0) { + bdText.setVerschiebung((int) textField.getText().charAt(0)-65); + + } else { + bdText.setVerschiebung(0); + } // end of if-else + bdText.repaint(); + + } // end of if + + }); + + tab2.add(buchstabe[i]); + } // end of for + + JTabbedPane tabpane = new JTabbedPane + (JTabbedPane.TOP,JTabbedPane.SCROLL_TAB_LAYOUT ); + tabpane.setBounds(10,140,672,290); + + tabpane.addTab("Schritt 1", tab1); + tabpane.addTab("Schritt 2", tab2); + cp.add(tabpane); + + setResizable(false); + setVisible(true); + } + + + + // Anfang Methoden + + public void jButtonKas_ActionPerformed(ActionEvent evt) { // neu mkl + //String krypttext = jTAKrypto.getText().toUpperCase(); + jTAKorrelation.setText(jTAKrypto.getText().toUpperCase()); + jTAKorrelation2.setText(jTAKrypto.getText().toUpperCase()); + jTAKlartext.setText(""); + } + + public void jButton1_ActionPerformed(ActionEvent evt) { + String krypttext = jTAKrypto.getText().toUpperCase(); + String klartext=""; + int c = 0; + int diff = (Integer) jSpVerschiebung.getValue(); + for (int i=0;i=65 && asc<=90) { + h[asc-65]++; + } + } // end of if + c++; + } // end of if + } + bdText.setHaeufigkeit(h); + if (buchstabe[start].getText().length()>0) { + bdText.setVerschiebung((int) buchstabe[start].getText().charAt(0)-65); + + } else { + bdText.setVerschiebung(0); + } // end of if-else + bdText.repaint(); + } catch(BadLocationException e) {} + } + + + public void addSearchHighlight() { + String search = jTAKorrelation.getSelectedText(); + if (search !=null) { + lv = jTAKorrelation.getSelectionStart(); + lb = jTAKorrelation.getSelectionEnd(); + Highlighter h2 = jTAKorrelation.getHighlighter(); + h2.removeAllHighlights(); + try{ + + search = search.toUpperCase(); + System.out.println(search); + + Highlighter h1 = jTAKorrelation2.getHighlighter(); + h1.removeAllHighlights(); + String krypto = jTAKorrelation.getText().toUpperCase(); + + int c = krypto.indexOf(search,0); + int anz = 0; + while (c>=0) { + h1.addHighlight(c, c+search.length(), + new DefaultHighlighter.DefaultHighlightPainter(new Color(200,200,255))); + anz++; + c = krypto.indexOf(search, c+1); + } // end of while + if (anz>1){ + h2.addHighlight(lv, lv+search.length(), + new DefaultHighlighter.DefaultHighlightPainter(new Color(100,100,255))); + } else { + h2.addHighlight(lv, lv+search.length(), + new DefaultHighlighter.DefaultHighlightPainter(new Color(200,200,255))); + } // end of if-else + + + + } catch(BadLocationException e) {} + + } + + } + + public ArrayList primfaktoren(int zahl) { + int w = 2; + ArrayList list = new ArrayList(); + while (zahl != 1) { + if(zahl % w == 0) { + list.add(w); + zahl /= w; + } + else { + w++; + } // end of if-else + + + } // end of while + return list; + } + + + public void selectHighlight() { + int caretpos = jTAKorrelation2.getCaretPosition(); + Highlighter h2 = jTAKorrelation2.getHighlighter(); + Highlighter.Highlight[] highlights = h2.getHighlights(); + for (Highlighter.Highlight h : highlights) { + if(caretpos >= h.getStartOffset() && caretpos < h.getEndOffset()) + { + int diff = Math.abs(lv - h.getStartOffset()); + if (diff == 0) { + lAnzahlgleicherBuchstaben.setText("Abstand: "+diff); + + } else { + lAnzahlgleicherBuchstaben.setText("Abstand: "+diff+" => Primfaktoren "+ primfaktoren(diff).toString()); + + } // end of if-else + + } + + } // end of for + } + + + public void removeSearchHighlight() { + Highlighter h1 = jTAKorrelation.getHighlighter(); + h1.removeAllHighlights(); + lAnzahlgleicherBuchstaben.setText("Abstand: "); + } + + + public void jSpVerschiebung_StateChanged(ChangeEvent evt) { + + int v = (Integer) (jSpVerschiebung.getValue()); + + + for (int i=0; iRegula Hoefer-Isenegger
+@version 0.1 +*/ +public class LineRenderer { + private Point2D.Double point; + private Turtle turtle; + + LineRenderer(Turtle turtle) { + this.point = new Point2D.Double(); + this.turtle = turtle; + } + + /** Initialisation with coordinates x and + y. + */ + public void init(double x, double y) { + this.point.setLocation(x, y); + } + /** Same as init(double x, double y), but with a Point2D.Double + argument for convenience + */ + public void init(Point2D.Double p) { + this.init(p.x, p.y); + } + /** Get the current x-coordinate in screen coordinates.*/ + private double getX(){ + return (toScreenCoords(point)).getX(); + } + /** Get the current x-coordinate in screen coordinates.*/ + private double getY(){ + return toScreenCoords(point).getY(); + } + /** Calls the clipLineTo and wrapLineTo methods, according + to the turtle's edge behavior. + + Only overwrite this method when working with another + (one that you have defined) edge behaviour.
+ If you mean to change the manner of drawing lines, do this in + the methods clipLineTo() and wrapLineTo(). + @see #clipLineTo + @see #wrapLineTo + */ + protected void internalLineTo(double x, double y){ + Point2D.Double screenPos = toScreenCoords(x, y); + if(turtle.isClip()){ + clipLineTo(screenPos.getX(), screenPos.getY()); + } + if (turtle.isWrap()){ + wrapLineTo(screenPos.getX(), screenPos.getY()); + } + init(x,y); + } + /** Calls the internalLineTo(x,y), which does the actual painting. + */ + public void lineTo(double x, double y) { + internalLineTo(x, y); + } + /** Calls the internalLineTo(x,y), which does the actual painting. + + This method works the same way as lineTo(double x, double y), but + is added for convenience. + */ + public void lineTo(Point2D.Double p) { + internalLineTo(p.getX(), p.getY()); + } + /** Does the actual painting for clip mode. + + It works already with ScreenCoords! + For further comments cf. internalLineTo(double x, double y). + @see #internalLineTo + */ + protected void clipLineTo(double x, double y){ + turtle.getPlayground().lineTo(getX(), getY(), x, y, turtle.getPen()); + } + /** Does the actual painting for wrap mode. + + It works already with ScreenCoords! + For further comments cf. internalLineTo(double x, double y). + @see #internalLineTo + */ + protected void wrapLineTo(double x, double y){ + double dx = getX() - x; + double dy = getY() - y; + Point2D.Double start = new Point2D.Double(x, y); + Point2D.Double end = new Point2D.Double(start.x+dx, start.y+dy); + + intoPanel(start, end); + Point2D.Double tmp; + while ((tmp = calcIntersection(start.x, start.y, end.x, end.y)) != null){ + turtle.getPlayground().lineTo(start.x, start.y, tmp.getX(), tmp.getY(), turtle.getPen()); + start = tmp; + intoPanel(start, end); + dx = end.x - start.x; + dy = end.y - start.y; + } + + turtle.getPlayground().lineTo(start.x, start.y, end.x, end.y, turtle.getPen()); + } + /** Makes the coordinates fit into the Panel. + + Well, this is some sort of modulus calculation. + */ + private void intoPanel(Point2D.Double start, Point2D.Double end){ + int pWidth = turtle.getPlayground().getWidth(); + int pHeight = turtle.getPlayground().getHeight(); + while(start.x < 0){ + start.x += pWidth; + end.x += pWidth; + } + while (start.x > pWidth){ + start.x -= pWidth; + end.x -= pWidth; + } + if(start.x == 0 && end.x < start.x){ + start.x += pWidth; + end.x += pWidth; + } + if(start.x == pWidth && end.x > start.x){ + start.x -= pWidth; + end.x -= pWidth; + } + while(start.y < 0){ + start.y += pHeight; + end.y += pHeight; + } + while (start.y > pHeight){ + start.y -= pHeight; + end.y -= pHeight; + } + if(start.y == 0 && end.y < start.y){ + start.y += pHeight; + end.y += pHeight; + } + if(start.y == pHeight && end.y > start.y){ + start.y -= pHeight; + end.y -= pHeight; + } + + } + /** Intersection line with playground-edges + (startX / startY) MUST lie in the playground! + */ + private Point2D.Double calcIntersection(double startX, double startY, double endX, double endY){ + double dx = endX - startX; + double dy = endY - startY; + double W = turtle.getPlayground().getWidth(); + double H = turtle.getPlayground().getHeight(); + if(endX < 0){ + if((dy/dx <= startY/startX) && (dy/dx >= -(H-startY)/startX)){ // links + return new Point2D.Double(0, startY-startX*dy/dx); + } + } + else if(endX > W){ + if((dy/dx >= -startY/(W-startX)) && (dy/dx <= (H-startY)/(W-startX))){// rechts + return new Point2D.Double(W, startY+(W-startX)*dy/dx); + } + } + if(endY < 0){ // oben + return new Point2D.Double(startX-startY*dx/dy, 0); + } + else if(endY > H){ // unten + return new Point2D.Double(startX+(H-startY)*dx/dy, H); + } + else{ + return null; // Endpoint lies in the window + } + } + /** Calculates the screen coordinates of the turtle's actual + position according to the interpretation of the playground. + */ + private Point2D.Double toScreenCoords(double x, double y){ + return turtle.getPlayground().toScreenCoords(x, y); + } + /** Calculates the screen coordinates of the turtle's actual + position according to the interpretation of the playground. + + Added for convenience. + @see #toScreenCoords(double, double) + */ + private Point2D.Double toScreenCoords(Point2D.Double p){ + return turtle.getPlayground().toScreenCoords(p.x, p.y); + } +} + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/pen.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/pen.java new file mode 100644 index 0000000..8fcc8b7 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/pen.java @@ -0,0 +1,268 @@ +// Pen.java + +// Copyright 2002 Regula Hoefer-Isenegger +// +// This file is part of The Java Turtle package (TJT) +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.awt.Color; +import java.awt.BasicStroke; +import java.awt.Stroke; +import java.awt.Font; +import java.awt.GraphicsEnvironment; + +/** The Pen class provides anything used for drawing the lines, such as line width, + pen color, end caps, dashed lines, etc. + + @see java.awt.BasicStroke + + @author Regula Hoefer-Isenegger + @version 0.1.1 +*/ +public class Pen +{ + /* Attributes *********************************************/ + + /** The default font that is used when drawing Text. + + First argument must be one of "Serif", "SansSerif", "Monotyped", "Dialog" or "DialogInput" + to guarantee that this font exists on all systems. + + @see java.awt.Font for more information, e.g. on font styles. + + */ + public static Font DEFAULT_FONT = new Font("SansSerif", Font.PLAIN, 24); + private Color color; + private Color fillColor; + private BasicStroke stroke; + private Font font; + + /* Constructors *******************************************/ + /** Constructor with standard Color and standard Stroke. + + @see java.awt.BasicStroke + */ + public Pen(){ + color = Color.black; + setFillColor(Color.black); + stroke = new BasicStroke(); + font = DEFAULT_FONT; + } + /** Constructor with Color color and standard Stroke. + + @see java.awt.BasicStroke + */ + public Pen(Color color){ + this.color = color; + setFillColor(color); + stroke = new BasicStroke(); + font = DEFAULT_FONT; + } + /* Methods ************************************************/ + /** Query the Pens color.*/ + public Color getColor(){ + return color; + } + /** Set the Pens color.*/ + public void setColor(Color color){ + this.color = color; + } + /** Set the Pens fill color. + */ + public void setFillColor(Color color){ + this.fillColor = color; + } + /** Query the Pens fill color.*/ + public Color getFillColor(){ + return this.fillColor; + } + /** Get the Pens Stroke + + @see BasicStroke + @see Stroke + */ + public Stroke getStroke(){ + return stroke; + } + /** Query the Pens line width*/ + public float getLineWidth(){ + return stroke.getLineWidth(); + } + /** Query the Pens end cap style. + + @see java.awt.BasicStroke + */ + public int getEndCap(){ + return stroke.getEndCap(); + } + /** Query the Pens line join style. + + @see java.awt.BasicStroke + */ + public int getLineJoin(){ + return stroke.getLineJoin(); + } + /** Query the Pens miter limit style. + + @see java.awt.BasicStroke + */ + public float getMiterLimit(){ + return stroke.getMiterLimit(); + } + /** Query the Pens dash array. + + @see java.awt.BasicStroke + */ + public float[] getDashArray(){ + return stroke.getDashArray(); + } + /** Query the Pens dash phase. + + @see java.awt.BasicStroke + */ + public float getDashPhase(){ + return stroke.getDashPhase(); + } + + /** Set the Pens line width. */ + public void setLineWidth(float width){ + stroke = new BasicStroke((float)width, + stroke.getEndCap(), + stroke.getLineJoin(), + stroke.getMiterLimit(), + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens end cap style. + + @see java.awt.BasicStroke + */ + public void setEndCap(int endCap){ + stroke = new BasicStroke(stroke.getLineWidth(), + endCap, + stroke.getLineJoin(), + stroke.getMiterLimit(), + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens line join style. + + @see java.awt.BasicStroke + */ + public void setLineJoin(int join){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + join, + stroke.getMiterLimit(), + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens miter limit. + + @see java.awt.BasicStroke + */ + public void setMiterLimit(float miterlimit){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + stroke.getLineJoin(), + miterlimit, + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens dash array. + + @see java.awt.BasicStroke + */ + public void setDash(float[] dashArray){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + stroke.getLineJoin(), + stroke.getMiterLimit(), + dashArray, + stroke.getDashPhase()); + } + /** Set the Pens dash phase. + + @see java.awt.BasicStroke + */ + public void setDashPhase(float dashPhase){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + stroke.getLineJoin(), + stroke.getMiterLimit(), + stroke.getDashArray(), + dashPhase); + } + /** Provides information about the currently available font families (e.g. "Roman"). + Each font name is a string packed into a array of strings. + @see java.awt.Font for more information about font attributes etc. + */ + public static String[] getAvailableFontFamilies(){ + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + String s[] = ge.getAvailableFontFamilyNames(); + return s; + } + /** Change the font style. + + @see java.awt.Font for possible styles. + */ + public void setFontStyle(int style){ + font = font.deriveFont(style); + } + /** Change the font size (in points). + */ + public void setFontSize(int size){ + font = font.deriveFont((float)size); + } + /** Change the font size (in points). + You will probably only need the int version setFontSize(int). + */ + public void setFontSize(float size){ + font = font.deriveFont(size); + } + /** Query the size (in points, rounded to int) of the current font. + */ + public int getFontSize(){ + return font.getSize() ; + } + /** Change the font to the given one. + */ + public void setFont(Font f){ + font = f; + } + /** Query the current font. + */ + public Font getFont(){ + return font; + } +} + + + + + + + + + + + + + + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/playground.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/playground.java new file mode 100644 index 0000000..6c0db5b --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/playground.java @@ -0,0 +1,789 @@ +// Playground.java + +// Copyright 2002 Regula Hoefer-Isenegger +// Major code modifications by Aegidius Pluess +// Adaption for the Java-Editor by Gerhard Röhner +// +// This file is part of The Java Turtle package (TJT) +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.util.*; +import javax.swing.*; +import java.awt.*; +import java.awt.print.*; +import java.awt.geom.*; +import java.awt.image.*; +import java.awt.font.*; + +/** + A Playground is the Turtle's home, i.e. the Turtle lives + and moves in the Playground. + + ThePlayground is responsible for interpreting angle and position of the + Turtle and for choosing the correct turtle image and putting it on the right + spot of the Playground. This means: e.g. whenever you wish to switch the x- and y-axis, you + should do it in this class, and not in the Turtle class. + + @author Regula Hoefer-Isenegger + @version 0.1.1 +*/ + +public class Playground extends JPanel implements Printable { + + /** Hold the Turtles of this Playground. */ + private Vector turtles; + + /** Hold the offscreen buffer and graphics context + * where Turtle traces are drawn. + */ + private BufferedImage traceBuffer = null; + protected Graphics2D traceG2D = null; + private Dimension playgroundSize; + + /** Hold the offscreen buffer and graphics context + * of the Turtles images. + */ + private BufferedImage turtleBuffer = null; + protected Graphics2D turtleG2D = null; + + /** Flag to tell whether we have at least one Turtle shown. */ + private boolean isTurtleVisible = false; + + /** Flag to tell whether we use automatic repainting */ + private boolean isRepainting = true; + + /** The default background color. + */ + protected static Color DEFAULT_BACKGROUND_COLOR = Color.white; + + private double printerScale = 1; // Default printer scaling + private TPrintable traceCanvas; // Store ref to user class + private Graphics2D printerG2D = null; + private boolean isPrintScreen = false; // Indicate we are printing the playground + private double printerScaleFactor = 1.1; // Magnification factor for printer + + /** + * originX is the x-position of the cartesian coodinate system within the playground. + */ + public int originX; + + /** + * originY is the y-position of the cartesian coodinate system within the playground. + */ + public int originY; + + private static Color[] ColorArray = {Color.cyan, Color.red, Color.green, Color.blue, Color.yellow, + Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.black, Color.gray + }; + + /** + * Create a Playground with default background color. + * e.g. creates a new vector (which holds the + * Turtles), + */ + public Playground() { + turtles = new Vector(); + setDoubleBuffered(false); + setBackground(DEFAULT_BACKGROUND_COLOR); + initBuffers(new Dimension(100, 100)); + } + + /** + * Initializes the offscreen buffers and sets the size. + */ + protected void initBuffers(Dimension size) { + Color bkColor = getBackground(); + playgroundSize = size; + traceBuffer = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); + traceG2D = traceBuffer.createGraphics(); + traceG2D.setColor(bkColor); + traceG2D.fillRect(0, 0, size.width, size.height); + traceG2D.setBackground(bkColor); + + turtleBuffer = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); + turtleG2D = turtleBuffer.createGraphics(); + turtleG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + originX = size.width/2; + originY = size.height/2; + } + + /** Add a new Turtle to the Playground. + */ + public void add(Turtle turtle) { + turtles.add(turtle); + turtle.setPlayground(this); + int i = turtles.size(); + while (i > 10) { + i = i - 10; + } // end of while + turtle.init(ColorArray[i-1]); + toTop(turtle); + } + + public void setBounds(int x, int y, int width, int height) { + super.setBounds(x, y, width, height); + initBuffers(new Dimension(width, height)); + } + + /** Remove a Turtle from the Playground. + */ + public void remove(Turtle turtle) { + turtles.remove(turtle); + } + + /** Tell current number of Turtles in this Playground. + */ + public int countTurtles() { + return turtles.size(); + } + + /** Return the Turtle at index index. + */ + public Turtle getTurtle(int index) { + return turtles.elementAt(index); + } + + /** Move the given Turtle above all the others, then + paints all turtles. + @see #toTop + */ + public void paintTurtles(Turtle turtle) { + toTop(turtle); + paintTurtles(); + } + + /** Paint all turtles (calling paintComponent()) + */ + public void paintTurtles() { + isTurtleVisible = false; + Graphics2D g2D = getTurtleG2D(); + for (int i = 0; i < countTurtles(); i++) { + Turtle aTurtle = getTurtle(i); + if (!aTurtle.isHidden()) { + paintTurtle(aTurtle); + } + } + + // This is the main repaint call, when the turtle is + // moving (even when all turtles are hidden). + // Strange behaviour an slow Mac machines (pre J2SE 1.4 version): + // It happens that some turtle images are not completely redrawn. + // This is probably due to an improper handling of fast multiple repaint requests. + // Workaround: we wait a small amount of time (and give the thread away) + // (No visible slow down on new machines.) + + paintPlayground(); + if (printerG2D == null) { + //if (isRepainting) + //repaint(); + //paintPlayground(); + } + + if (isTurtleVisible) { + try { + Thread.currentThread().sleep(10); + } + catch (Exception e) {} + } + } + + + /** Paint the given Turtle. + * ( no repaint() ) + */ + public void paintTurtle(Turtle turtle) { + if (turtleBuffer == null){ + turtleBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); + turtleG2D = turtleBuffer.createGraphics(); + } + Graphics2D turtleGraphics = getTurtleG2D(); + turtle.getTurtleRenderer().paint(turtle._getX(), turtle._getY(), turtleGraphics); + isTurtleVisible = true; + } + + /** Put an image of the given Turtle in turtle buffer. + */ + protected void stampTurtle(Turtle turtle) { + turtle.clone(); + isTurtleVisible = true; + if (printerG2D == null) + repaint(); + } + + /** Draw a line from the point (x0, y0) to (x1, y1) + with the color of the given Pen. + */ + protected void lineTo(double x0, double y0, double x1, double y1, Pen pen) { + int ix0 = (int)Math.round(x0); + int iy0 = (int)Math.round(y0); + int ix1 = (int)Math.round(x1); + int iy1 = (int)Math.round(y1); + Color color = pen.getColor(); + + if (traceBuffer == null) { + traceBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); + traceG2D = traceBuffer.createGraphics(); + } + Graphics2D traceG2D = getTraceG2D(); + traceG2D.setColor(color); + traceG2D.setStroke(pen.getStroke()); + traceG2D.drawLine(ix0, iy0, ix1, iy1); + if (printerG2D != null) + printerG2D.drawLine(ix0, iy0, ix1, iy1); + } + + /** A class for convenience. */ + protected class Point extends java.awt.Point { + Point(int x, int y) { + super(x, y); + } + Point() { + super(); + } + Point(Point p) { + super(p.x, p.y); + } + + /** Get a new Point with coordinates (this.x+p.x, this.y+p.y). + */ + protected Point add(Point p) { + return new Point(this.x+p.x, this.y+p.y); + } + + /** Translate by the amounts dx = p.x, dy = p.y. */ + protected void translate(Point p) { + translate(p.x, p.y); + } + + public String toString() { + return "(" + x + "," + y + ")"; + } + } + + /** Fill a region. + The region is defined by the Turtles actual position and + is bounded by any other color than the give background color. + */ + public void fill(Turtle t, Color bgColor) { + final Point[] diff = { new Point(0,-1), new Point(-1,0), new Point(1,0), new Point(0,1)}; + final int N=0; + final int W=1; + final int E=2; + final int S=3; + + int bgcolor = bgColor.getRGB(); + int fillColor = t.getPen().getFillColor().getRGB(); + Vector list = new Vector(); + Point2D.Double p1 = toScreenCoords(t.getPos()); + int startX = (int)Math.round(p1.getX()); + int startY = (int)Math.round(p1.getY()); + Point p = new Point(startX, startY); + if (traceBuffer.getRGB(startX, startY) == bgcolor) { + traceBuffer.setRGB(startX, startY, fillColor); + list.addElement(new Point(startX, startY)); + int d = N; + int back; + while (list.size() > 0) { + while (d <= S) { // forward + Point tmp = p.add(diff[d]); + try { + if (traceBuffer.getRGB(tmp.x, tmp.y) == bgcolor) { + p.translate(diff[d]); + traceBuffer.setRGB(p.x, p.y, fillColor); + if (printerG2D != null) + { + printerG2D.setColor(t.getPen().getFillColor()); + // printerG2D.drawLine(p.x,p.y, p.x, p.y); + BasicStroke stroke = new BasicStroke(2); + printerG2D.setStroke(stroke); + Line2D line = new Line2D.Double(p.x, p.y, p.x, p.y); + printerG2D.draw(line); + } + list.addElement(new Integer(d)); + d=N; + } + else { + d++; + } + } + catch (ArrayIndexOutOfBoundsException e) { + d++; + } + } + Object obj = list.remove(list.size()-1); + try { + d=((Integer)obj).intValue(); // last element + back = S - d; + p.translate(diff[back]); + } + catch (ClassCastException e) { + // the first (zeroest) element in list is the start-point + // just do nothing with it + } + } + } + traceG2D.drawLine(0, 0, 0, 0); // Workaround because on Mac the trace buffer is not drawn without this + if (printerG2D == null) + repaint(); + } + + /** + * Clear the playground with given color. + */ + public void clear(Color color) { + traceG2D.setColor(color); + traceG2D.fillRect(0, 0, getWidth(), getHeight()); + turtleG2D.setColor(color); + turtleG2D.fillRect(0, 0, getWidth(), getHeight()); + isTurtleVisible = true; + if (printerG2D == null) + repaint(); + } + + /** + * Clear playground. + */ + public void clear() { + clear(getBackground()); + } + + /** Paint the Playground. + just a method for convenience. + */ + public void paintComponent() { + paintComponent(getGraphics()); + } + + /** Draw the trace and turtle buffers. + */ + public void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2D = (Graphics2D)g; + g2D.drawImage(traceBuffer, 0, 0, this); + if (isTurtleVisible) + g2D.drawImage(turtleBuffer, 0, 0, this); + } + + public void paintPlayground() { + Graphics g = getGraphics(); + if (g != null) { + super.paintComponent(g); + Graphics2D g2D = (Graphics2D)g; + g2D.drawImage(traceBuffer, 0, 0, this); + if (isTurtleVisible) + g2D.drawImage(turtleBuffer, 0, 0, this); + + } // end of if + } + + /** Remove all turtles from the turtle buffer. + */ + public void clearTurtles() { + for (int i = 0; i < countTurtles(); i++) { + Turtle turtle = getTurtle(i); + clearTurtle(turtle); + } + } + + /** Remove the given turtle from the turtle buffer. + Override this method if you have added a new behaviour (like + wrap or clip) to the turtle. + */ + public void clearTurtle(Turtle turtle) { + if(turtle != null){ + if (!turtle.isHidden()) { + if(turtle.isClip()){ + clearClipTurtle(turtle); + } + else if(turtle.isWrap()){ + clearWrapTurtle(turtle); + } + } + } + } + + /** This method is called when the given Turtle is in wrap mode. + + @see ch.aplu.turtle.Turtle#wrap + */ + protected void clearWrapTurtle(Turtle turtle){ + clearWrapTurtle(turtle, turtleBuffer); + } + + /** Here the actual clearing of a Turtle in wrap mode from the + given image is performed. + */ + protected void clearWrapTurtle(Turtle turtle, Image im){ + Rectangle bounds = getBounds(turtle); + int pWidth = getWidth(); + int pHeight = getHeight(); + int x = bounds.x; + int y = bounds.y; + while (x > pWidth){ + x -= pWidth; + } + while (x < 0){ + x += pWidth; + } + while (y > pHeight){ + y -= pHeight; + } + while (y < 0){ + y += pHeight; + } + x = x % pWidth; + y = y % pHeight; + toAlphaNull(im, new Rectangle(x, y, bounds.width, bounds.height)); // OK + boolean right = (x + bounds.width > getWidth()); + boolean bottom = (y + bounds.height > getHeight()); + if (right) { + toAlphaNull(im, new Rectangle(x-pWidth, y, bounds.width, bounds.height)); + } + if (bottom) { + toAlphaNull(im, new Rectangle(x, y-pHeight, bounds.width, bounds.height)); + } + if (right && bottom) { + toAlphaNull(im, new Rectangle(x-pWidth, y-pHeight, bounds.width, bounds.height)); + } + } + + /** Copy and translate a given Rectangle. + */ + private Rectangle copyAndTranslate(Rectangle rect, int dx, int dy) { + return new Rectangle(rect.x+dx, rect.y+dy, + rect.width, rect.height); + } + + /** This method is called when the given Turtle is in clip mode. + + @see ch.aplu.turtle.Turtle#clip + */ + protected void clearClipTurtle(Turtle turtle) { + clearClipTurtle(turtle, turtleBuffer); + } + + /** Here the actual clearing of a Turtle in clip mode from the + given image is performed. + */ + protected void clearClipTurtle(Turtle turtle, Image im) { + Rectangle bounds = getBounds(turtle); + toAlphaNull(im, bounds); + } + + /** Set the alpha channel of all pixels in the given image + in the given Rectangle to zero (i.e. totally transparent). + + This method is used byte the clearXXXTurtle methods. + */ + private void toAlphaNull(Image im, Rectangle rect) { + Rectangle rim = new Rectangle(0, 0, im.getWidth(this), im.getHeight(this)); + Rectangle r = new Rectangle(); + if (rect.intersects(rim)) { + r=rect.intersection(rim); + } + int size = r.width*r.height; + float[] alphachannel = new float[r.width*r.height]; + ((BufferedImage)im).getAlphaRaster().setPixels(r.x, r.y, r.width, r.height, alphachannel); + } + + /** Puts a Turtle above all others. + */ + public Turtle toTop(Turtle turtle) { + if (turtles.removeElement(turtle)) { + turtles.add(turtle); + } + return turtle; + } + /** Put a Turtle below all others. + */ + public Turtle toBottom(Turtle turtle) { + if (turtles.removeElement(turtle)) { + turtles.add(0,turtle); + } + return turtle; + } + + /** Calculate the screen coordinates of the given point. + */ + public Point2D.Double toScreenCoords(Point2D.Double p) { + return internalToScreenCoords(p.x, p.y); + } + + /** Calculate the screen coordinates of the given point coordinates. + */ + public Point2D.Double toScreenCoords(double x, double y) { + return internalToScreenCoords(x, y); + } + + protected Point2D.Double internalToScreenCoords(double x, double y) { + // reflect at x-axis, then translate to center of Playground + // pixel coordinates coorespond to turtle coordinates, only translation needed + double newX = originX + x; + double newY = originY - y; + return new Point2D.Double(newX, newY); + } + + /** Calculate the turtle coordinates of the given screen coordinates. + */ + public Point2D.Double toTurtleCoords(double x, double y) { + // pixel coordinates coorespond to turtle coordinates, only translation needed + double newX = x - originX; + double newY = originY - y; + return new Point2D.Double(newX, newY); + } + + /** Calculate the turtle coordinates of the given screen point. + */ + public Point2D.Double toTurtleCoords(Point2D.Double p) { + return toTurtleCoords(p.x, p.y); + } + + /** Calculate the screen angle. + I.e. the interpretation of angle. + @param radians The angle in radians. + */ + double toScreenAngle(double radians) { + double sa = radians; + if (sa < Math.PI/2){ + sa += 2*Math.PI; + } + sa -= Math.PI/2; + if (sa != 0) { + sa = Math.PI*2 - sa; + } + return sa; + } + + /** Calculate the bounds of the Turtles picture on the screen. + */ + protected Rectangle getBounds(Turtle turtle) { + Rectangle bounds = turtle.getBounds(); + Point2D.Double tmp = toScreenCoords(new Point2D.Double(bounds.getX(), bounds.getY())); + bounds.setRect(tmp.x-2, tmp.y-2, bounds.width+4, bounds.height+4); + return bounds; + } + + /** Return the graphics context of the turtle buffer. + */ + public Graphics2D getTurtleG2D() { + return turtleG2D; + } + + /** Return the image of the turtle buffer. + */ + public BufferedImage getTurtleBuffer() { + return turtleBuffer; + } + + /** Return the graphics context of the trace buffer. + */ + public Graphics2D getTraceG2D() { + return traceG2D; + } + + /** Return the graphics context of the printer. + */ + public Graphics2D getPrinterG2D() { + return printerG2D; + } + + /** Return the image of the trace buffer. + */ + public BufferedImage getTraceBuffer() { + return traceBuffer; + } + + /** Clean the traces. + All turtles stay how and where they are, only lines, text and stamps will be removed. + */ + void clean() { + Graphics2D g = getTraceG2D(); + g.setColor(getBackground()); + g.fillRect(0,0,getWidth(), getHeight()); + if (printerG2D == null) + repaint(); + } + + /** Draw the text at the current position of the Turtle t. + Drawing a text at some coordinates (x,y) we mean that the bottom left corner of + the text will be at these coordinates. + Font and colour are specified by the Turtle's Pen. + */ + public void label(String text, Turtle t) { + Point2D.Double sc = toScreenCoords(t.getPos()); + int x = (int)Math.round(sc.x); + int y = (int)Math.round(sc.y); + Graphics2D traceG2D = getTraceG2D(); + FontRenderContext frc = traceG2D.getFontRenderContext(); + Font f = t.getFont(); + TextLayout tl = new TextLayout(text, f, frc); + traceG2D.setColor(t.getPen().getColor()); + tl.draw(traceG2D, x, y); + if (printerG2D != null) + { + printerG2D.setColor(t.getPen().getColor()); + tl.draw(printerG2D, x, y); + } + + if (printerG2D == null) + repaint(); + } + + /** Set antialiasing on or off for the turtle trace buffer + * This may result in an better trace quality. + */ + public void setAntiAliasing(boolean on) { + if (on) + traceG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + else + traceG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_OFF); + } + + + /** + * Set the given TPrintable (implementing draw()), + * open a printer dialog and start printing with given scale. + * Return false, if printer dialog is aborted, + * otherwise return true.
+ * If tp == null, the current playground is printed. + * + */ + protected boolean print(TPrintable tp, double scale) { + if (tp == null) + isPrintScreen = true; + else + isPrintScreen = false; + printerScale = scale; + PrinterJob pj = PrinterJob.getPrinterJob(); + pj.setPrintable(this); + traceCanvas = tp; + if (pj.printDialog()) { + try { + pj.print(); + } + catch (PrinterException ex) { + System.out.println(ex); + } + return true; + } + else + return false; + } + + /** + * For internal use only. Implementation of Printable. + * (Callback method called by printing system.) + */ + public int print(Graphics g, PageFormat pf, int pageIndex) { + if (pageIndex != 0) + return NO_SUCH_PAGE; + Graphics2D g2D = (Graphics2D)g; + double printerWidth = pf.getImageableWidth(); + double printerHeight = pf.getImageableHeight(); + double printerSize = printerWidth > printerHeight ? printerWidth : + printerHeight; + double xZero = pf.getImageableX(); + double yZero = pf.getImageableY(); + + printerG2D = g2D; // Indicate also, we are printing now + + // Needed for fill operations: the trace canvas must be empty in order to + // perform the fill algoritm (searching for outline of figure) + if (!isPrintScreen) + clean(); + + g2D.scale(printerScaleFactor * printerScale, printerScaleFactor * printerScale); + g2D.translate(xZero/printerScale, yZero/printerScale); + + if (isPrintScreen) + { + print(g); + } + else // Printing the traceCanvas + { + // Hide all turtles + boolean[] turtleState = new boolean[countTurtles()]; + for (int i = 0; i < countTurtles(); i++) { + Turtle aTurtle = getTurtle(i); + turtleState[i] = aTurtle.isHidden(); + aTurtle.ht(); + } + traceCanvas.draw(); + + // Restore old context + for (int i = 0; i < countTurtles(); i++) { + Turtle aTurtle = getTurtle(i); + if (!turtleState[i]) + aTurtle.st(); + } + } + + printerG2D = null; + return PAGE_EXISTS; + } + + /** Return the color of the pixel at the current turtle position. + */ + public Color getPixelColor(Turtle t) { + Point2D.Double p1 = toScreenCoords(t.getPos()); + int x = (int)Math.round(p1.getX()); + int y = (int)Math.round(p1.getY()); + return new Color(traceBuffer.getRGB(x, y)); + } + + public void enableRepaint(boolean b) { + isRepainting = b; + } + + /** set the background color of the playground + */ + public void setBackground(Color color) { + super.setBackground(color); + if (traceG2D != null) { + clear(color); + } // end of if + } + + /** + * Sets the origin of the cartesian coordinate system within the playground + */ + public void setOrigin(int x, int y) { + for (int i = 0; i < countTurtles(); i++) { + Turtle turtle = getTurtle(i); + Point2D.Double p1 = toScreenCoords(turtle.getPos()); + double newX = p1.getX() - x; + double newY = y - p1.getY(); + turtle.internalSetPos(newX, newY); + } + originX = x; + originY = y; + } + + public int getOriginX() { + return originX; + } + + public int getOriginY() { + return originY; + } + +} + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/res/bong.wav b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/res/bong.wav new file mode 100644 index 0000000000000000000000000000000000000000..0d2fef0c16fc8ff100f498e161aed70ae66207eb GIT binary patch literal 9624 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 literal 0 HcmV?d00001 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/sharedconstants.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/sharedconstants.java new file mode 100644 index 0000000..1bd3955 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/sharedconstants.java @@ -0,0 +1,84 @@ +// SharedConstants.java + +// Copyright 2002 Regula Hoefer-Isenegger +// +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +/* History; +V1.36 - Sep 2004: First official release +V1.37 - Nov 2004: Unchanged, modifications in ch.aplu.util +V1.38 - Dec 2004: Unchanged, modifications in ch.aplu.util +V1.39 - Jan 2005: Unchanged, modifications in ch.aplu.util +V1.40 - Mar 2005: Add background color, TurtleKeyAdapter, TurtleArea +V1.41 - May 2005: User defined turtle shape, minor changes in doc and code style +V1.42 - Dec 2005: Unchanged, modifications in ch.aplu.util +V1.43 - Feb 2006: Bug removed: Turtle.turtleFrame was not initialized in all ctors of class Turtle +V1.44 - Mar 2007: Bug removed: stampTurtle did not work properly in wrap mode +V1.45 - Aug 2007: TurtleKeyAdapter: use wait/notify to reduce CPU time (from 100% to 2%) +V1.46 - Aug 2007: synchronize(playground) for forward and rotate animation, + new method bong() using StreamingPlayer +V1.47 - Sept 2007: Unchanged, modifications in ch.aplu.util +V1.48 - Sept 2007: Unchanged, modifications in ch.aplu.util +V1.49 - Oct 2007: Unchanged, modifications in ch.aplu.util +V1.50 - Oct 2007: Unchanged, modifications in ch.aplu.util +V1.51 - Nov 2007: Fixed: correct position of label, when wrapping is on + Fixed: getPos() returns now the wrapped coordinates + Added: _getPos() returns unwrapped coordinates +V1.52 - Nov 2007: Added bean classes in order to use turtles with a Gui builder +V1.53 - Nov 2007: Added TurtlePane visual information when used in Gui builder design mode +V1.54 - Nov 2007: Minor changes to documentation +V1.55 - Dec 2007: Added property enableFocus to GPane, default: setFocusable(false) +V1.56 - Mar 2008: Unchanged, modifications in ch.aplu.util +V1.57 - Mar 2008: Unchanged, modifications in ch.aplu.util +V1.58 - Mar 2008: Modification to fill() (fill(x, y)): + region is defined with pixel color at current position + as opposed to background color +V1.59 - Oct 2008: Added ctors TurtleFrame with window position (ulx, uly) + Added Turtle.getPixelColor() +V2.00 - Nov 2008: Unchanged, modifications in ch.aplu.util + J2SE V1.4 no longer supported +V2.01 - Jan 2009: Unchanged, modifications in ch.aplu.util +V2.02 - Feb 2009 Turtle constructors run in EDT now +V2.03 - Feb 2009 Unchanged, modifications in ch.aplu.util +V2.04 - Feb 2009 Unchanged, modifications in ch.aplu.util +V2.05 - Feb 2009 Unchanged, modifications in ch.aplu.util +V2.06 - Mar 2009 Unchanged, modifications in ch.aplu.util +V2.07 - Mar 2009 All except print methods synchronized, so Turtle package is + now thread-safe +V2.08 - Apr 2009 Unchanged, modifications in ch.aplu.util +V2.09 - Jun 2009 Unchanged, modifications in ch.aplu.util +V2.10 - Jun 2010 Version for the Java-Editor +*/ + +package ch.aplu.turtle; + +interface SharedConstants +{ + int DEBUG_LEVEL_OFF = 0; + int DEBUG_LEVEL_LOW = 1; + int DEBUG_LEVEL_MEDIUM = 2; + int DEBUG_LEVEL_HIGH = 3; + + int DEBUG = DEBUG_LEVEL_OFF; + + String ABOUT = + "Copyright © 2002-2009\nRegula Hoefer-Isenegger, Aegidius Pluess\n, Gerhard Roehner\n" + + "under GNU General Public License\n" + + "http://www.aplu.ch\n" + + "All rights reserved"; + String VERSION = "2.10 - June 2015"; +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/streamingplayer.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/streamingplayer.java new file mode 100644 index 0000000..8a3d5d5 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/streamingplayer.java @@ -0,0 +1,84 @@ +// StreamingPlayer.java + +package ch.aplu.turtle; + + +import javax.sound.sampled.*; +import java.io.*; + +class StreamingPlayer +{ + private class PlayerThread extends Thread + { + public void run() + { + byte buf[] = new byte[20000]; + try + { + int cnt; + while ((cnt = audioInputStream.read(buf, 0, buf.length)) != -1) + { + if (cnt > 0) + sourceDataLine.write(buf, 0, cnt); + } + sourceDataLine.drain(); + sourceDataLine.close(); + } + catch (IOException ex) + { + System.out.println(ex); + System.exit(1); + } + } + } + + private AudioFormat audioFormat; + private AudioInputStream audioInputStream; + private SourceDataLine sourceDataLine; + private PlayerThread playerThread; + + StreamingPlayer(InputStream is) + { + try + { + audioInputStream = + AudioSystem.getAudioInputStream(is); + audioFormat = audioInputStream.getFormat(); + } + catch (Exception ex) + {} + } + + void start(boolean doFinish) + throws LineUnavailableException + { + DataLine.Info dataLineInfo = + new DataLine.Info(SourceDataLine.class, audioFormat); + sourceDataLine = + (SourceDataLine)AudioSystem.getLine(dataLineInfo); + sourceDataLine.open(audioFormat); + sourceDataLine.start(); + playerThread = new PlayerThread(); + playerThread.start(); + if (doFinish) + waitToFinish(); + } + + boolean isPlaying() + { + if (playerThread == null) + return false; + return (playerThread.isAlive()); + } + + void waitToFinish() + { + if (playerThread == null) + return; + try + { + playerThread.join(); + } + catch (InterruptedException ex) {} + } +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/tprintable.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/tprintable.java new file mode 100644 index 0000000..767d22a --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/tprintable.java @@ -0,0 +1,43 @@ +// TPrintable.java + +// Copyright 2002 Regula Hoefer-Isenegger + +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +// Added by Aegidius Pluess + +package ch.aplu.turtle; + +/** + * Interface for printing on an attached printer. + * Normally an application uses a Turtle and implements this interface. + * draw() should contain all drawing operations into the + * Turtle's Playground. The printing occures, when Turtle's print() is + * called.

+ */ + + +public interface TPrintable +{ + /** + * This method must perform all drawing operations. + * Be aware that for some undocumented reason + * draw() is called twice. So be sure you initialize it correctly. + */ + + public void draw(); +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/turtle.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/turtle.java new file mode 100644 index 0000000..d30ff52 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/turtle.java @@ -0,0 +1,1585 @@ +// Turtle.java +// Modifications by Aegidius Pluess +// Adaption to the Java-Editor by Gerhard Röhner + +// Copyright 2002-2003 Regula Hoefer-Isenegger (Version 1.0) +// +// This file is part of The Java Turtle package (TJT) +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +/* +Screen coordinate system: 0..400 pixels in both directions corresponds to turtle +turtle coordinate system -200..200, so only translation is necessary (no scaling). + +This avoids rounding errors. +*/ + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.*; +import java.awt.image.*; +import java.awt.print.*; +import java.io.*; +import javax.sound.sampled.*; +import javax.swing.*; + +/** + The core class for turtles. + + For a simple example on how to use Turtle, cf. the + Java Turtle Package description. + @author Regula Hoefer-Isenegger + @version 0.1.1 +*/ +public class Turtle implements Cloneable +{ + private double angle; + private Point2D.Double position; + private Playground playground; + private int framesPerSecond; + private double speed; // Pixel/sec + private double angleSpeed; // Radian/sec + private TurtleRenderer turtleRenderer; + private int angleResolution; + private LineRenderer lineRenderer; + private static TurtleFactory turtleFactory; + private boolean penUp; + private boolean showTurtle; + private boolean initialVisibility = true; + private Pen pen; + private Color color; + private int edgeBehaviour; + + + /** Convert from screen coordinates to turtle coordinates + */ + public Point2D.Double toTurtlePos(Point p) { + return playground.toTurtleCoords((double)p.x, (double)p.y); + } + + /** Convert from screen coordinates to turtle coordinates + */ + public Point2D.Double toTurtlePos(int x, int y) { + return playground.toTurtleCoords((double)x, (double)y); + } + + /** Convert from screen coordinates to turtle coordinates + */ + public double toTurtleX(int x) { + return (playground.toTurtleCoords((double)x, 0)).x; + } + + /** Convert from screen coordinates to turtle coordinates + */ + public double toTurtleY(int y) { + return (playground.toTurtleCoords(0, (double)y)).y; + } + + /** Add the specified mouse listener to receive mouse events. + */ + public void addMouseListener(MouseListener l) { + playground.addMouseListener(l); + } + + /** Add the specified mouse motion listener to receive mouse motion events. + */ + public void addMouseMotionListener(MouseMotionListener l) { + playground.addMouseMotionListener(l); + } + + /** + * Emit a beep. Fails if no standard speaker available. Try to use bong() instead. + * @see #bong() + */ + public void beep() { + Toolkit.getDefaultToolkit().beep(); + } + + /** + * Emit a 'bong' via the sound card. Useful on computers without standard + * speaker. + * @see #beep() + */ + public void bong() { + InputStream is = getClass().getResourceAsStream("res/bong.wav"); + StreamingPlayer player = new StreamingPlayer(is); + try + { + player.start(false); + } + catch (LineUnavailableException ex) + { + System.out.println("Error in bong(). Sound card unavailable"); + } + } + + + /** Represent clip mode. + @see #WRAP + @see #clip() + */ + protected final static int CLIP = 0; + /** Represent wrap mode. + + @see #CLIP + @see #wrap() + */ + protected final static int WRAP = 1; + /** Represent the default edge behaviour (i.e. CLIP or WRAP). + + @see #CLIP + @see #WRAP + @see #clip() + @see #wrap() + */ + protected static int DEFAULT_EDGE_BEHAVIOUR = CLIP; + /** Represent the default speed (velocity). + + @see #setSpeed(double) + */ + protected static double DEFAULT_SPEED = 200; + + /** Represent the default angle resolution. + + It specifies how many different turtle pictures + are generated. + */ + protected static int DEFAULT_ANGLE_RESOLUTION = 72; + + /** Specify how many frames per second are used for + turtle animation. + */ + protected static int DEFAULT_FRAMES_PER_SECOND = 10; + + /** Specify the default turtle color. + + @see #setColor(java.awt.Color) + */ + protected static Color DEFAULT_TURTLE_COLOR = Color.cyan; + + /** Specify the default pen color. + + @see #setPenColor(java.awt.Color) + */ + protected static Color DEFAULT_PEN_COLOR = Color.blue; + + /** Create a new Turtle + */ + public Turtle() { + } + + /** init a new Turtle + */ + protected void init(Color color) { + angle = 0; + position = new Point2D.Double(0, 0); + framesPerSecond = DEFAULT_FRAMES_PER_SECOND; + if (initialVisibility) + setSpeed(DEFAULT_SPEED); + else + setSpeed(-1); + showTurtle = initialVisibility; + setAngleResolution(DEFAULT_ANGLE_RESOLUTION); + angleSpeed = getSpeed() * Math.PI * 2 / DEFAULT_SPEED; + pen = new Pen(DEFAULT_PEN_COLOR); + if (getTurtleFactory() == null){ + turtleFactory = createTurtleFactory(); + } + setColor(color); + lineRenderer = createLineRenderer(); + getTurtleRenderer().setAngle(getAngle()); + } + + /** Set the angle resolution for the Turtle's pictures. + + It specifies how many pictures are used. e.g. an angle resolution + of 90 means that you get one picture for every 4 degrees + (= 360/90 degrees). + */ + public void setAngleResolution(int newResolution) { + synchronized(playground) { + angleResolution = newResolution; + } + } + + /** Return the TurtleFactory of this turtle. + + @see ch.aplu.turtle.TurtleFactory + */ + public TurtleFactory getTurtleFactory() { + return this.turtleFactory; + } + + /** Create a LineRenderer which is responsible + for the correct drawing of the lines. + + @return the new LineRenderer + */ + + protected LineRenderer createLineRenderer() { + return new LineRenderer(this); + } + + /** Create a TurtleRenderer which is responsible + for the correct drawing of the Turtle. + + @return the new TurtleRenderer + */ + protected TurtleRenderer createTurtleRenderer() { + return new TurtleRenderer(this); + } + + /** Create a TurtleFactory which provides for + the Turtle pictures. + + @return the new TurtleFactory + */ + + protected TurtleFactory createTurtleFactory() { + return new TurtleFactory(); + } + /** Get the angle resolution. + + @see #setAngleResolution(int) + */ + + protected int getAngleResolution() { + return angleResolution; + } + + /** Get the TurtleRenderer. + */ + TurtleRenderer getTurtleRenderer() { + return turtleRenderer; + } + + /** Get the LineRenderer. + */ + private LineRenderer getLineRenderer() { + return lineRenderer; + } + + /** Get the Playground. + */ + public Playground getPlayground() { + return playground; + } + + /** Set the Playground to the specified + playground. + + The Turtle is removed from the old + Playground and set to the new one. + */ + public void setPlayground(Playground playground) { + Playground pg = getPlayground(); + if(pg != null){ + pg.clearTurtle(this); + pg.remove(this); + pg.paintTurtles(); + } + this.playground = playground; + playground.paintTurtles(this); + } + + /** Get the angle speed. + + (I.e. how fast the Turtle rotation + animation is performed.) + */ + private double getAngleSpeed() { + return angleSpeed; + } + + /** Set the angle speed. + + @see #getAngleSpeed() + */ + private void setAngleSpeed(double newAngleSpeed) { + this.angleSpeed = newAngleSpeed; + } + + /** Get the current angle (heading) of the + Turtle. + */ + private double getAngle() { + return angle; // in radians + } + + /** Get the current speed. + */ + public double getSpeed() { + return speed; + } + + /** Query the Turtle's x-position without wrapping. + * Coordinate are not bound to playground even when + * wrapping is on. + */ + public double _getX() { + synchronized (playground) { + return position.getX(); + } + } + + /** Query the Turtle's y-position without wrapping. + * Coordinate are not bound to playground even when + * wrapping is on. + */ + public double _getY() { + synchronized (playground) { + return position.getY(); + } + } + + /** Query the Turtle's x-position. + * If turtle is outside playground and wrapping is on + * return the coordinate in range -200..200. + * */ + + public double getX() { + synchronized (playground) { + double xPos = _getX(); + return xPos; + } + } + + /** Query the Turtle's x-position. + * If turtle is outside playground and wrapping is on + * return the coordinate in range -200..200. + */ + public double getY() { + synchronized (playground) { + double yPos = _getY(); + return yPos; + } + } + + + /** Query the Turtle's position without wrapping. + * Coordinate are not bound to playground even when + * wrapping is on. + */ + public Point2D.Double _getPos() { + return position; + } + + /** Query the Turtle's position */ + public Point2D.Double getPos() { + return new Point2D.Double(getX(), getY()); + } + + /** Put the Turtle to a new position with the given x-coordinates. + + */ + public void setX(double x) { + synchronized (playground) { + getPlayground().clearTurtle(this); + internalSetX(x); + getPlayground().paintTurtles(this); + } + } + + /** Put the Turtle to a new position with the given screen x-coordinates. + */ + public void setScreenX(int x) { + synchronized (playground) { + setX(toTurtleX(x)); + } + } + + /** Put the Turtle to a new position with the given y-coordinates. + */ + public void setY(double y) { + synchronized (playground) { + getPlayground().clearTurtle(this); + internalSetY(y); + getPlayground().paintTurtles(this); + } + } + + /** Put the Turtle to a new position with the given screen y-coordinates. + */ + public void setScreenY(int y) { + synchronized (playground) { + setY(toTurtleY(y)); + } + } + + /** Set the Turtle's x-Coordinate. + */ + protected void internalSetX(double x) { + synchronized (playground) { + position.setLocation(x, _getY()); + } + } + + /** Set the Turtle's y-Coordinate. + */ + protected void internalSetY(double y) { + position.setLocation(_getX(), y); + } + + /** Set the Turtle's Position. + */ + protected void internalSetPos(double x, double y) { + position.setLocation(x, y); + } + + /** Hide the Turtle. + + @see #st() + If there is only one turte, the speed is set to -1 + so there is no Turtle animation at all. + Hiding the Turtle speeds up the graphics enormously. + */ + public void ht() { + synchronized (playground) { + this.internalHide(); + if (getPlayground().countTurtles() == 1) + setSpeed(-1); + } + } + + /** Hide the Turtle. + + This is the same as ht(). + @see #st() + */ + public void hideTurtle() { + ht(); + } + + /** This is the method called by the public methods ht() and hideTurtle(). + + Here the actual hiding takes place. + @see #ht() + @see #hideTurtle() + */ + protected void internalHide() { + getPlayground().clearTurtle(this); + showTurtle = false; + if (getPlayground().getPrinterG2D() == null) + getPlayground().repaint(); + } + + /** Set the Turtle to show mode. + + That means that the Turtle will be drawn. + @see #ht() + */ + public void st() { + synchronized (playground) { + if (getPlayground().getPrinterG2D() == null) { + getPlayground().paintTurtle(this); + showTurtle = true; + getPlayground().repaint(); + } + } + } + + /** The same as st(). + + @see #st() + */ + public void showTurtle() { + st(); + } + + /** Tell whether the Turtle is hidden or not. + + @return true if the Turtle is hidden, + false otherwise. + */ + public boolean isHidden() { + return !showTurtle; + } + + private int getFramesPerSecond() { + return this.framesPerSecond; + } + + /** Only set the angle attribute. This method does not + invoke any re-painting. + */ + private void setAngle(double radians) { + this.angle = radians; + } + + /** This is the same as setH(double degrees). + + @see #setH(double) + */ + public void setHeading(double degrees) { + synchronized (playground) { + setAngle(Math.toRadians(degrees)); + getTurtleRenderer().setAngle(Math.toRadians(degrees)); + getPlayground().clearTurtle(this); + getPlayground().paintTurtles(this); + } + } + + /** Set the Turtle's heading. + + 0 means facing NORTH.
+ the angles are measured clockwise. + @see #setHeading(double) + */ + public void setH(double degrees) { + setHeading(degrees); + } + /** Query the Turtle's heading. + + @see #setH(double) + */ + public double heading() { + synchronized (playground) { + return Math.toDegrees(getAngle()); + } + } + /** Set the Turtle's heading to the new value. + + @return the old (previous) value. + @see #setH(double) + */ + public double heading(double degrees) { + synchronized (playground) { + double tmp = Math.toDegrees(getAngle()); + setHeading(degrees); + return tmp; + } + } + + /** Set the Turtle's speed. + + If you try to set the speed to 0, it will be set to 1 (very slow). + A negative speed means that moving the Turtle (fd, bk) + will not be animated.
+ The unit is pixels per second (up to certain bounds depending on the CPU etc.).
+ Remark: Dashed lines will only be painted as you expect it with speed set + to -1. + + @see #fd(double) + @see #bk(double) + */ + public void setSpeed(double speed) { + if (speed == 0) + this.speed = 1; + else + this.speed = speed; + } + + + /** This method is responsible for the rotation animation. + */ + private void internalRotate(double angle) { + if(isHidden()){ + synchronized(playground) + { + setAngle(getAngle()+angle); + if (getTurtleRenderer().imageChanged(getAngle())) { + getTurtleRenderer().setAngle(getAngle()); + } + } + return; + } + if (angle != 0) { + int iterations = getAngleIterations(angle); + + double sign = angle/Math.abs(angle); + double increment = sign*getAngleSpeed()/(double)getFramesPerSecond(); + double startAngle = getAngle(); + + for (int index = 0; index < iterations; index++) { + long timeStamp = System.currentTimeMillis(); + + synchronized(playground) { + getPlayground().clearTurtle(this); + + if (index < iterations-1) { + setAngle(getAngle()+increment); + } + else { + setAngle(startAngle+angle); + } + + if (getTurtleRenderer().imageChanged(getAngle())) { + getTurtleRenderer().setAngle(getAngle()); + getPlayground().paintTurtles(this); + } + } + + long newTimeStamp = System.currentTimeMillis(); + Double secs = new Double(1000./getFramesPerSecond()); + long requiredTime = secs.longValue()-newTimeStamp+timeStamp; + + if (requiredTime > 0) { + try { + Thread.sleep(requiredTime); + } + catch (InterruptedException e) { + } + } + } + } + getPlayground().paintTurtles(this); + } + + /** This method is responsible for the moving animation. + */ + private void internalMove(double length) { + if (getSpeed()>0){ + if (length != 0) { + int iterations = getPathIterations(length); + // an angle of 0 means: facing NORTH + double startX = _getX(); + double startY = _getY(); + getLineRenderer().init(startX, startY); + double dx = length * Math.sin(getAngle()); + double dy = length * Math.cos(getAngle()); + double incrementX = dx / iterations; + double incrementY = dy / iterations; + for (int index = 0; index < iterations; index++) { + long timeStamp = System.currentTimeMillis(); + int nX = (int)_getX(); + int nY = (int)_getY(); + synchronized(playground) { + playground.clearTurtle(this); + if (index < iterations-1) { + internalSetX(_getX()+incrementX); + internalSetY(_getY()+incrementY); + } + else { // last step: Calc the "exact" value + internalSetX(startX + dx); + internalSetY(startY + dy); + } + if (nX != (int)_getX() || nY != - (int)_getY() || index == iterations-1){ + if (!isPenUp()) { + getLineRenderer().lineTo(_getX(), _getY()); + } + getPlayground().paintTurtles(this); + } + } + Double frames = new Double(1000./getFramesPerSecond()); + long newTimeStamp = System.currentTimeMillis(); + long requiredTime = frames.longValue()-newTimeStamp+timeStamp; + if (requiredTime > 0) { + try { + Thread.sleep(requiredTime); + } + catch (InterruptedException e) { + } + } + } + } + } + else { // Speed < 0, i.e. no animation + double startX = _getX(); + double startY = _getY(); + getLineRenderer().init(startX, startY); + double dx = length * Math.sin(getAngle()); + double dy = length * Math.cos(getAngle()); + getPlayground().clearTurtle(this); + internalSetX(startX + dx); + internalSetY(startY + dy); + if (!isPenUp()) { + getLineRenderer().lineTo(_getX(), _getY()); + } + getPlayground().paintTurtles(this); + } + } + + /** Turn the Turtle the given angle (in degrees) to the left + + @see #rt(double) + */ + public void lt(double degrees) { + left(degrees); + } + + /** Same as lt(double degrees) + + @see #lt(double) + */ + public void left(double degrees) { + internalRotate(Math.toRadians(-degrees)); + } + + /** Turn the Turtle the given angle (in degrees) to the right. + + @see #rt(double) + */ + public void rt(double degrees) { + right(degrees); + } + + /** Same as rt(double degrees). + + @see #rt(double) + */ + public void right(double degrees) { + internalRotate(Math.toRadians(degrees)); + } + + /** Same as fd(double distance) + + @see #fd(double) + */ + public void forward(double distance) { + internalMove(distance); + } + + /** Move the Turtle forwards. + + Negative values for distance are + allowed. In that case, the Turtle + will move backwards. + + @see #bk(double) + */ + public void fd(double distance) { + forward(distance); + } + + /** Same as bk(double distance). + + @see #bk(double) + */ + public void back(double distance) { + forward(-distance); + } + + /** Move the Turtle backwards. + + Negative values for distance are + allowed. In that case, the Turtle + will move forwards. + + @see #fd(double) + */ + public void bk(double distance) { + back(distance); + } + + /** Query the distance from the current location + to the given one. + */ + public double distance(double x, double y) { + synchronized (playground) { + return this.getPos().distance(x,y); + } + } + + /** Query the distance from the current location + to the given one. + * Actually a polygon with 36 sides is drawn. + */ + public double distance(Point2D.Double p) { + synchronized (playground) { + return this.getPos().distance(p); + } + } + + /** Draw a circle to the left from the current position with + * turtle's heading tangent direction and given radius. + * Actually a polygon with 36 sides is drawn. + */ + public void leftCircle(double radius) { + circle(radius, true); + } + + /** Draw a circle to the right from the current position with + * turtle's heading tangent direction and given radius. + * Actually a polygon with 36 sides is drawn. + */ + public void rightCircle(double radius) { + circle(radius, false); + } + + private void circle(double radius, boolean left) { + double nbSteps = 36; // 36 side polygon + double angle = 2 * Math.PI / nbSteps; + double step = 2 * radius * Math.sin(angle/2); + for (int i = 0; i < 36; i++) { + if (left) + if (i == 0) + lt(180.0 / nbSteps); + else + lt(360.0 / nbSteps); + else + if (i == 0) + rt(180.0 / nbSteps); + else + rt(360.0 / nbSteps); + fd(step); + } + } + + /** Calculate the number of iterations when animating left or right (rotation). + */ + private int getAngleIterations(double dAngle) { + if(getAngleSpeed()<0){ + return 1; + } + if(getAngleSpeed()==0){ + setAngleSpeed(1); + } + double dAbsAngle = Math.abs(dAngle); + Double dValue = new Double(Math.ceil(dAbsAngle/getAngleSpeed()*getFramesPerSecond())); + return dValue.intValue(); + } + + /** Calculate the number of iterations when animating forwards or backwards. + */ + private int getPathIterations(double length) { + if(speed < 0) + return 1; + + if (speed == 0) + setSpeed(1); + + double dAbsLength = Math.abs(length); + Double dValue = new Double(Math.ceil(dAbsLength/getSpeed()*getFramesPerSecond())); + return dValue.intValue(); + } + + /** Lift the Turtle's pen up so it + won't draw a line anymore. + + This is the same as pu(). + + @see #pu() + @see #penDown() + @see #pd() + */ + public void penUp() { + synchronized (playground) { + this.penUp = true; + } + } + + /** Lift the Turtle's pen up so it + won't draw a line anymore. + + This is the same as penUp(). + + @see #penUp() + @see #penDown() + @see #pd() + */ + public void pu() { + this.penUp(); + } + + /** Lower the Turtle's Pen down so it + will draw a line when moving. + + This is the same as pd(). + + @see #pd() + @see #penUp() + @see #pu() + */ + public void penDown() { + synchronized (playground) { + this.penUp = false; + } + } + + /** Lowers the Turtle's pen down so it + will draw a line when moving. + + This is the same as penDown(). + + @see #penDown() + @see #penUp() + @see #pu() + */ + public void pd() { + this.penDown(); + } + + /** Query the Pen's state (up or down). + + @return true if the Pen is + up, false otherwise. + @see #pu() + @see #pd() + */ + public boolean isPenUp() { + return this.penUp; + } + + /** Return the bounds of this Turtle. This is required + by the methods that (return-)paint the Turtles. + */ + Rectangle getBounds() { + Rectangle rect = new Rectangle(); + + Image img = getTurtleRenderer().currentImage(); + int nWidth = img.getWidth(getTurtleRenderer()); + int nHeight = img.getHeight(getTurtleRenderer()); + double x = (_getX()<0)?Math.floor(_getX()):Math.ceil(_getX()); + double y = (_getY()<0)?Math.floor(_getY()):Math.ceil(_getY()); + rect.setBounds((int)x-nWidth/2, (int)y + nHeight/2, nWidth, nHeight); + return rect; + } + + /** Get the Turtle's Pen. + + You need it if you want to change end caps etc. + @see Pen + */ + public Pen getPen() { + return pen; + } + /** Set the line thickness. + + This works only neatly in clip mode (yet). + @see #clip() + @see #wrap() + */ + public void setLineWidth(double lineWidth){ + synchronized (playground) { + setLineWidth((float)lineWidth); + } + } + + /** Set the line thickness. + + This works only neatly in clip mode (yet). + @see #clip() + @see #wrap() + */ + public void setLineWidth(float lineWidth) { + synchronized (playground) { + getPen().setLineWidth(lineWidth); + } + } + + /** Set the Turtle's color to the specified one. + + */ + public void setColor(Color color) { + synchronized (playground) { + internalSetColor(color); + getPlayground().paintTurtles(); + } + } + + private void internalSetColor(Color color) { + this.color = color; + if (getTurtleRenderer()==null) { + turtleRenderer = createTurtleRenderer(); + getTurtleRenderer().init(getTurtleFactory(), getAngleResolution()); + } + else{ + getTurtleRenderer().init(new TurtleFactory(), + this.angleResolution); + } + } + + /** Set the color to the specified one. + + @see #fill() + */ + public void setFillColor(Color color) { + synchronized (playground) { + getPen().setFillColor(color); + } + } + + /** Query the Turtle's current color. + */ + public Color getColor(){ + return color; + } + + /**Set the Turtle's pen color. + + */ + public void setPenColor(Color color) { + synchronized (playground) { + getPen().setColor(color); + } + } + + /** Move the Turtle back "home", i.e. set its position + to the origin, facing NORTH. + + Color, PenColor etc. remain the same. + */ + public void home() { + // first : clean the Turtle! + synchronized (playground) { + getPlayground().clearTurtle(this); + position = new Point2D.Double(0,0); + setHeading(0); + } + } + + /** The Turtle's Pen is + changed to an eraser (which is in fact a pen with + background color). + + This is the same as pe() + @see #pe() + */ + public void penErase() { + synchronized (playground) { + this.internalPenErase(); + } + } + + /** The Turtle's Pen is + changed to an eraser (which is in fact a pen with + background color). + + This is the same as penErase() + @see #penErase() + */ + public void pe() { + penErase(); + } + + protected void internalPenErase(){ + this.setPenColor(getPlayground().getBackground()); + } + + /** Put the Turtle to a new position with specified + x- and y-coordinates. + */ + public void setPos(double x, double y) { + synchronized (playground) { + getPlayground().clearTurtle(this); + internalSetPos(x, y); + getPlayground().paintTurtles(); + } + } + + /** Put the Turtle to a new position. + */ + public void setPos(Point2D.Double p) { + setPos(p.x, p.y); + } + + /** Put the Turtle to a new screen position. + + */ + public void setScreenPos(Point p) { + setPos(toTurtlePos(p)); + } + + + /** Put a Turtle image at the current position. + + */ + public void stampTurtle() { + synchronized (playground) { + this.getPlayground().stampTurtle(this); + } + } + + /** Calculate the direction to a given point. + + @return the direction from the current turtle position + towards the given point, measured in degrees and clockwise + from the vertical upwards position. + */ + public double towards(double x, double y) { + synchronized (playground) { + double dx = x - getX(); + double dy = y - getY(); + double result = Math.toDegrees(Math.atan2(dx, dy)); + return (result < 0) ? result+360 : result; + } + } + + /** Calculate the direction to a given point. + + @return the direction from the current turtle position + towards the given point, measured in degrees and clockwise + from the vertical upwards position. + */ + public double towards(Point2D.Double p) { + return towards(p.getX(), p.getY()); + } + + /** Put the Turtle to the top (i.e. above any other + turtle). + + Just invokes the toTop-Method in Playground. + @see Playground#toTop + @see #internalToBottom + */ + void internalToTop() { + this.getPlayground().toTop(this); + } + /** Put the Turtle to the bottom (i.e. under any other + turtle). + + Just invokes the toBottom-Method in Playground. + @see Playground#toBottom + @see #internalToTop + */ + void internalToBottom() { + this.getPlayground().toBottom(this); + } + + /** Put this turtle to the bottom. + + So any other turtle in the same Playground will be drawn over it. + */ + public void toBottom() { + // this.getPlayground().toBottom(this); + synchronized (playground) { + internalToBottom(); + getPlayground().paintTurtles(); + } + } + + /** Put this turtle to the top. + + So it will be drawn over any other turtle in the same Playground. + */ + public void toTop() { + // this.getPlayground().toTop(this); + synchronized (playground) { + this.getPlayground().paintTurtles(this); + } + } + + /** Set the pen width. + */ + public void penWidth(int newWidth) { + synchronized (playground) { + penWidth((float)newWidth); + } + } + + /** Internal Method for setting the penWidth. + */ + private void penWidth(float newWidth) { + setLineWidth(newWidth); + } + + /** Query the pen width. + */ + public int penWidth(){ + return (int)this.getPen().getLineWidth(); + } + + /** Returns the current edge behaviour. + + @see #CLIP + @see #WRAP + */ + protected int getEdgeBehaviour() { + return edgeBehaviour; + } + + /** Sets the edge behaviour to the specified value; + + @see #CLIP + @see #WRAP + */ + protected void setEdgeBehaviour(int edgeBehaviour) { + synchronized (playground) { + this.edgeBehaviour = edgeBehaviour; + } + } + + /** Set the Turtle to clip-mode. + @see #wrap() + @see #clip() + */ + public void clip() { + synchronized (playground) { + setEdgeBehaviour(CLIP); + } + } + + /** Cause the Turtle to wrap around the playground borders. + + e.g when as the Turtle leaves the Window on one side, + it reappears on the opposite side. + + @see #clip() + */ + public void wrap() { + synchronized (playground) { + setEdgeBehaviour(WRAP); + } + } + + /** Tell whether the Turtle is in clip mode. + + @return true if in clip mode, false otherwise. + @see #clip() + @see #wrap() + */ + public boolean isClip() { + return (getEdgeBehaviour() == CLIP); + } + /** Tell wheter the Turtle is in wrap mode. + + @return true if in wrap mode, false otherwise. + @see #wrap() + @see #clip() + */ + public boolean isWrap() { + return (getEdgeBehaviour() == WRAP); + } + + /** Fill the region the Turtle is in.
+ + A region is bounded by lines + of any color different to the pixel color at the current turtle position + and by the border of the window.
+ (The pen of the Turtle must be down.) + */ + public void fill() { + synchronized (playground) { + getPlayground().fill(this, getPlayground().getPixelColor(this)); + } + } + + /** Fill the region as if the Turtle where at coordinates x and y.
+ A region is bounded by lines + of any color different to the pixel color at the given position and by the border of + the window.
+ (The pen of the Turtle must be down.) + */ + public void fill(double x, double y) { + synchronized (playground) { + double oldX = getX(); + double oldY = getY(); + boolean hidden = isHidden(); + ht(); + setPos(x,y); + getPlayground().fill(this, getPlayground().getPixelColor(this)); + setPos(oldX, oldY); + if(!hidden){ + st(); + } + } + } + + /** Erase all traces and text painted by the turtles, but let all + * turtles where they are. + + */ + public void clean() { + synchronized (playground) { + getPlayground().clean(); + } + } + + /** Paint the specified text at the current turtle position. + + */ + public void label(String text) { + synchronized (playground) { + if (text != null && text.length() > 0) + getPlayground().label(text, this); + } + } + + /** Set the current font as specified. + + @see java.awt.Font + */ + public void setFont(Font font) { + synchronized (playground) { + getPen().setFont(font); + } + } + + /** Change the current font to the specified one. If you want to know what fonts are available on your system, + call #getAvailableFontFamilies() . + + @see #getAvailableFontFamilies + @see java.awt.Font more information about fontName, style and size. + */ + public void setFont(String fontName, int style, int size) { + synchronized (playground) { + getPen().setFont(new Font(fontName, style, size)); + } + } + + /** Set the font size. + + @see #setFontStyle changing the font style + @see #setFont changing the whole font. + */ + public void setFontSize(int size) { + synchronized (playground) { + getPen().setFontSize(size); + } + } + + /** Set the font style. + + This is either java.awt.Font.PLAIN, java.awt.Font.BOLD, java.awt.Font.ITALIC or java.awt.Font.BOLD+java.awt.Font.ITALIC + @see #setFontSize changing the font size + @see #setFont changing the whole font. + */ + public void setFontStyle(int style) { + synchronized (playground) { + getPen().setFontStyle(style); + } + } + + /** Provide information about all font families (e.g. roman) currently available on your system. + Each font name is a string packed into a array of strings. + (This might be useful when you want to change the font.) + @see #setFont(java.awt.Font) + @see #setFont(java.lang.String, int, int) + */ + public static String[] getAvailableFontFamilies() { + return Pen.getAvailableFontFamilies(); + } + + /** Return the current font. + + @see #setFontSize changing the font size + @see #setFontStyle changing the font style + @see #setFont changing the whole font. + */ + public Font getFont() { + return getPen().getFont(); + } + + /** Creates a clone of the Turtle in it's Playground. + Color, position and heading are the same. + (It's visible and pen is down.) + Return the cloned object reference as a Object type, because + it overrides Object.clone(). + (You may cast it to a Turtle.) + */ + public Object clone() + { + synchronized (playground) { + Turtle t = new Turtle(); + t.setColor(getColor()); + t.setPos(getX(), getY()); + t.heading(heading()); + t.showTurtle(); + return t; + } + } + + /** Set antialiasing on or off for the turtle trace buffer + * This may result in an better image quality, especially + * for filling operations (platform dependant). + */ + public void antiAliasing(boolean on) { + synchronized (playground) { + getPlayground().setAntiAliasing(on); + } + } + + + /** + * Print the graphics context to an attached printer with + * the given magnification scale factor. + * scale = 1 will print on standard A4 format paper.
+ * + * The given tp must implement the GPrintable interface, + * e.g. the single method void draw(), where all the + * drawing into the GPanel must occur. + * + * Be aware the turtle(s) state (position, direction, etc.) + * must be reinitialized, because draw() is called several + * times by the printing system. + * + * A standard printer dialog is shown before printing is + * started. Only turte traces are printed. + *
+ * Example:
+ * + import ch.aplu.turtle.*;
+
+ public class PrintTest implements TPrintable
+ {
+ private Turtle t = new Turtle();
+
+ public PrintTest()
+ {
+ draw(); // Draw on screen
+ t.print(this); // Draw on printer
+ }
+
+ public void draw()
+ {
+ t.home(); // Needed for initialization
+ for (int i = 0; i < 5; i++)
+ t.fd(20).rt(90).fd(20).lt(90);
+ }
+
+ public static void main(String[] args)
+ {
+ new PrintTest();
+ }
+ }
+
+ */ + public boolean print(TPrintable tp, double scale) + { + return getPlayground().print(tp, scale); + } + + /** + * Same as print(tp, scale) with scale = 1. + */ + public boolean print(TPrintable tp) + { + return print(tp, 1); + } + + /** + * Print the Turtle's current playground with given scale. + */ + public boolean printScreen(double scale) + { + return print(null, scale); + } + + /** + * Same as printScreen(scale) with scale = 1. + */ + public boolean printScreen() + { + return printScreen(1); + } + + /** + * Clear the Turtle's playground. All turtle images and traces are erased, + * but the turtles remain (invisible) at their positions. + */ + public void clear() + { + synchronized (playground) { + getPlayground().clear(); + } + } + + /** + * Delay execution for the given amount of time ( in ms ). + */ + public static void sleep(int time) + { + try + { + Thread.currentThread().sleep(time); + } + catch (Exception e) {} + } + + /** + * Return version information + */ + public String version() + { + return SharedConstants.VERSION; + } + + /** + * Enable/disable automatic repainting. + * If disabled, call repaint() to perform repainting. + * Disabling automatic repainting and hiding the + * Turtle speeds up the graphics enormously. + */ + public void enableRepaint(boolean b) + { + getPlayground().enableRepaint(b); + } + + /** + * Perform manual repainting when automatic repainting is + * disabled. + */ + public void repaint() { + getPlayground().repaint(); + } + + /** + * Return the color of the pixel at the current turtle position. + */ + public Color getPixelColor() { + synchronized (playground) { + return getPlayground().getPixelColor(this); + } + } + + protected Graphics getGraphics() { + return playground.getGraphics(); + } + + /** + * Transforms the gui-position to mouse-coordinates. + */ + public void setBounds(int x, int y, int b, int h) { + int ox = playground.getOriginX(); + int oy = playground.getOriginY(); + x = -ox + x + 10; + y = oy - y - 13; + setPos(x, y); + } + + /** + * Shows or hides the turtle. + */ + public void setVisible(boolean show) { + if (show) { + showTurtle(); + } else { + hideTurtle(); + } // end of if-else + } + + /** + * Sets clipping-mode on/off. + */ + public void setClip(boolean clip) { + if (clip) { + clip(); + } else { + wrap(); + } // end of if-else + } + + /** + * Sets pen-position up/down. + */ + public void setPenUp(boolean penup) { + if (penup) { + penUp(); + } else { + penDown(); + } // end of if-else + } + + /** + * Sets angle of the turtle. + */ + public void setAngle(int angle) { + setHeading(angle); + } +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/turtlefactory.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/turtlefactory.java new file mode 100644 index 0000000..e9d700e --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/turtlefactory.java @@ -0,0 +1,66 @@ +// TurtleFactory.java + +// Copyright 2002 Regula Hoefer-Isenegger +// +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import java.awt.image.*; +import java.awt.*; + +class TurtleFactory +{ + /** Generates the shape of the turtle with color, + * angle angle, width w + * and height h. + */ + protected Image turtleImage(Color color, double angle, int w, int h) + { + BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR); + Graphics2D g = (Graphics2D)bi.getGraphics(); + // Origin in center + g.translate(w/2, h/2); + // angle = 0 is direction east (as usual in mathematics) + g.rotate(Math.PI/2 - angle); + g.setColor(color); + + // Body + g.fillOval((int)( -0.35 * w), (int)( -0.35 * h), + (int)(0.7 * w), (int)(0.7 * h)); + + // Head + g.fillOval((int)( -0.1 * w), (int)( -0.5 * h), + (int)(0.2 * w), (int)(0.2 * h)); + + // Tail + int[] xcoords = + {(int)( -0.05 * w), 0, (int)(0.05 * w)}; + int[] ycoords = + {(int)(0.35 * h), (int)(0.45 * h), (int)(0.35 * h)}; + g.fillPolygon(xcoords, ycoords, 3); + + // Feet + for (int i = 0; i < 4; i++) + { + g.rotate(Math.PI / 2); + g.fillOval((int)( -0.35 * w), (int)( -0.35 * h), + (int)(0.125 * w), (int)(0.125 * h)); + } + return (Image)bi; + } +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/turtlerenderer.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/turtlerenderer.java new file mode 100644 index 0000000..9489e78 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/ch/aplu/turtle/turtlerenderer.java @@ -0,0 +1,312 @@ +// TurtleRenderer.java + +// Copyright 2002 Regula Hoefer-Isenegger +// Some modifications by Aegidius Pluess + +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.awt.image.*; +import java.awt.*; +import javax.swing.*; +import java.awt.geom.*; +import java.util.*; + + +/** This class is responsible for creating and choosing the correct Turtle picture. + @author Regula Hoefer-Isenegger + @version 0.1 +*/ +public class TurtleRenderer implements ImageObserver { + /** Holds the current image */ + private Image currentImage; + /** Holds all images */ + private Vector images; + /** Tells how many pictures are needed*/ + private int resolution; + /** A reference to the Turtle */ + private Turtle turtle; + /** Holds the current Angle */ + private double currentAngle; + + private final int turtleSize = 29; + + /***/ + public TurtleRenderer(Turtle turtle) { + this.currentImage = null; + this.images = new Vector(); + this.turtle = turtle; + currentAngle = 0; + } + + /** As an image stays unchanged, there's no need to ever update it. So this method returns always false. + + For further information cf. java.awt.image.ImageObserver. + @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) + */ + public boolean imageUpdate(Image img, int infoflags, + int x, int y, int width, int height) { + return false; + } + + /** Return the current image. + */ + public Image currentImage() { + return this.currentImage; + } + + /** Tell whether the image has changed. + */ + public boolean imageChanged(double angle) { + return (this.currentImage != getImage(angle)); + } + + /** Set the current image to the specified one. */ + private void setCurrentImage(Image image) { + currentImage = image; + } + + /** Choose the image for the angle angle. + */ + private Image getImage(double angle) { + while (angle < 0) { + angle += 2*Math.PI; + } + while (angle >= 2*Math.PI) { + angle -= 2*Math.PI; + } + double res = 2*Math.PI/(double)this.resolution; + int index = (int)(angle/res); + return image(index); + } + + /** Set the current image to the one corresponding to the angle angle. + */ + public void setAngle(double angle) { + currentAngle = angle; + setCurrentImage(getImage(angle)); + } + + /** @return the current angle. */ + protected double getAngle(){ + return currentAngle; + } + + /** Create the images. There are resolution images (i.e. two subsequent + images contain an angle of 2π/ or 360/resolution degrees). + */ + public void init(TurtleFactory factory, int resolution) { + this.resolution = resolution; + Integer res = new Integer(resolution); + double incRes = Math.PI*2/res.doubleValue(); + double angle = 0; + images = new Vector(); + for (int i = 0; i < resolution; i++) { + images.add(factory.turtleImage(turtle.getColor(), + turtle.getPlayground().toScreenAngle(angle), + turtleSize, turtleSize)); + angle += incRes; + } + setCurrentImage(getImage(currentAngle)); + } + + /** Tell how many images this TurtleRenderer holds */ + private int countImages() { + return this.images.size(); + } + + /** Get the image at index */ + private Image image(int index) { + return (Image)this.images.elementAt(index); + } + + /** This method is responsible for painting the turtle onto the + playground at (x, y). + */ + public final void paint(double x, double y) { + internalPaint(x, y, turtle.getPlayground().getGraphics()); + } + + /** This method is responsible for painting the turtle onto the + playground at p. + */ + public final void paint(Point2D.Double p) { + internalPaint(p.x, p.y, turtle.getPlayground().getGraphics()); + } + + /** This method is responsible for painting the Turtle + at (x, y).
+ The Graphics argument tells where to paint. + */ + public final void paint(double x, double y, Graphics g) { + internalPaint(x, y, g); + } + + /** This method is responsible for painting the Turtle + at p.
+ The Graphics argument tells where to paint. + */ + public void paint(Point2D.Double p, Graphics g){ + internalPaint(p.x, p.y, g); + } + + /** Call clipPaint and wrapPaint(). + + You should override this method only, if you add a new (edge) + behaviour to the turtle. I recommend to you then to first call this + method from the overriding one. +
+ If you want to change anything about the real painting, override + clipPaint or wrapPaint. + + @see #clipPaint(int, int, Graphics2D) + @see #wrapPaint(int, int, Graphics2D) + */ + protected void internalPaint(double x, double y, Graphics g) { + if(turtle.isClip()){ + Point2D.Double p = + calcTopLeftCorner(turtle.getPlayground().toScreenCoords(x, y)); + clipPaint((int)p.x, (int)p.y, (Graphics2D)g); + } + else if(turtle.isWrap()){ + Point2D.Double p = + calcTopLeftCorner(turtle.getPlayground().toScreenCoords(x, y)); + wrapPaint((int)p.x, (int)p.y, (Graphics2D)g); + } + } + + /** Define how to paint in clip mode and do it */ + protected void clipPaint(int x, int y, Graphics2D g2D) { + g2D.drawImage(currentImage, x, y, this); + } + + /** Define how to paint in wrap mode and do it */ + protected void wrapPaint(int x, int y, Graphics2D g2D) { + int pWidth = turtle.getPlayground().getWidth(); + int pHeight = turtle.getPlayground().getHeight(); + int paintX = x; + while (paintX > pWidth) { + paintX -= pWidth; + } + while (paintX < 0) { + paintX += pWidth; + } + int paintY = y; + while (paintY > pHeight) { + paintY -= pHeight; + } + while (paintY < 0) { + paintY += pHeight; + } + g2D.drawImage(currentImage, paintX, paintY, this); + int nWidth = currentImage.getWidth(this); + int nHeight = currentImage.getHeight(this); + boolean right = (paintX+nWidth > pWidth); + boolean bottom = (paintY+nHeight > pHeight); + if(right) { + g2D.drawImage(currentImage, + paintX-pWidth, + paintY, + this); + } + if(bottom) { + g2D.drawImage(currentImage, + paintX, + paintY-pHeight, + this); + } + if(right && bottom) { + g2D.drawImage(currentImage, + paintX-pWidth, + paintY-pHeight, + this); + } + } + + /** Compute the x-coordinate of the top left corner of the Turtle image + (it depends on the specified x-coordinate and the image width). + */ + protected int calcTopLeftCornerX(double x) { + int intX = (int)x; + int nWidth; + if(currentImage == null) { + setCurrentImage(new TurtleFactory(). + turtleImage(turtle.getColor(), getAngle(), turtleSize, turtleSize)); + } + nWidth = this.currentImage.getWidth(this); + // the center of the turtle lies on the turtle's location: + intX -= nWidth/2; + return intX; // top left corner of the Turtle's image + } + + /** Compute the y-coordinate of the top left corner of the Turtle image + (it depends on the specified y-coordinate and the image height). + */ + protected int calcTopLeftCornerY(double y) { + int intY = (int)y; + if(currentImage == null) { + setCurrentImage(new TurtleFactory(). + turtleImage(turtle.getColor(), getAngle(), turtleSize, turtleSize)); + } + int nHeight = currentImage.getHeight(this); + // the center of the turtle lies on the turtle's location: + intY -= nHeight/2; + + return intY; // top left corner of the Turtle's image + } + /** Compute the top left corner of the Turtle image + (dependent on the specified x- and y-coordinate and the image + width and height. + */ + protected Point2D.Double calcTopLeftCorner(double x, double y) { + if(currentImage == null) { + setCurrentImage(new TurtleFactory(). + turtleImage(turtle.getColor(), getAngle(), turtleSize, turtleSize)); + } + int w = currentImage.getWidth(this); + int h = currentImage.getHeight(this); + return new Point2D.Double(x-w/2, y-h/2); + } + + /** Compute the top left corner of the Turtle image + (dependent on the specified point p and the image + width and height. + */ + protected Point2D.Double calcTopLeftCorner(Point2D.Double p) { + return calcTopLeftCorner(p.x, p.y); + } +} + + + + + + + + + + + + + + + + + + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/eval.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/eval.java new file mode 100644 index 0000000..97c8ff0 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/eval.java @@ -0,0 +1,50 @@ +public class Eval { + + public static Wrap getOb(Object o) { + return new Wrap(o); + } + + protected static Object getOb(final String s) { + return new Object() {public String result = s;}; + } + + protected static Object getOb(final boolean b) { + return new Object() {public boolean result = b;}; + } + + protected static Object getOb(final byte b) { + return new Object() {public byte result = b;}; + } + + protected static Object getOb(final char c) { + return new Object() {public char result = c;}; + } + + protected static Object getOb(final double d) { + return new Object() {public double result = d;}; + } + + protected static Object getOb(final float f) { + return new Object() {public float result = f;}; + } + + protected static Object getOb(final int i) { + return new Object() {public int result = i;}; + } + + protected static Object getOb(final long l) { + return new Object() {public long result = l;}; + } + protected static Object getOb(final short s) { + return new Object() {public short result = s;}; + } +} + + +class Wrap { + public Object result; + + Wrap(Object result) { + this.result = result; + } +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/inout.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/inout.java new file mode 100644 index 0000000..d702d54 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/inout.java @@ -0,0 +1,98 @@ +import java.io.*; + +/** +Support class for console input and output of numeric values.

+ +Example for input:
+ int age = InOut.readInt("Your age: ");

+ +Example for output:
+ System.out.println("price: " + InOut.format2(prize) + "Euro");
+ System.out.println("percent: " + InOut.formatN(percent, 1) + " %"); +*/ + + +public class InOut { + + /** Formats a double-value with 2 decimal digits. */ + public static String format2(double d) { + return String.format("%.2f", d); + } + + /** Formats a double-value with N decimal digits. */ + public static String formatN(double d, int N) { + return String.format("%." + N + "f", d); + } + + /** Reads a boolean-value from console. */ + public static boolean readBoolean(String prompt) { + final String[] trueValues = + { "1", "y", "t", "j", "w", "yes", "true", "ja", "wahr", "ok" }; + System.out.print(prompt); + String input = readln().toLowerCase(); + for (int i = 0; i < trueValues.length; ++i) + if (trueValues[i].equals(input)) + return true; + return false; + } + + /** Reads a char-value from console. */ + public static char readChar(String prompt) { + System.out.print(prompt); + return readln().charAt(0); + } + + /** Reads a double-value from console. */ + public static double readDouble(String prompt) { + System.out.print(prompt); + return Double.parseDouble(readln()); + } + + /** Reads a float-value from console. */ + public static float readFloat(String prompt) { + System.out.print(prompt); + return Float.parseFloat(readln()); + } + + /** Reads an int-value from console. */ + public static int readInt(String prompt) { + System.out.print(prompt); + return Integer.parseInt(readln()); + } + + /** Reads a long-value from console. */ + public static long readLong(String prompt) { + System.out.print(prompt); + return Long.parseLong(readln()); + } + + /** Reads a string-value from console. */ + public static String readString(String prompt) { + System.out.print(prompt); + return readln(); + } + + /** Reads a string-value from console without prompt. + For use at the end of a console program. */ + public static String readln() { + try { + return Input.readLine(); + } catch(Exception e) { + return ""; + } + } + + private static BufferedReader Input; + + static { + try { + Input = new BufferedReader(new InputStreamReader(System.in)); + } + catch (Exception e) { + System.out.println("console input not possible."); + } + } + + + +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/je/util/turtle.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/je/util/turtle.java new file mode 100644 index 0000000..4a704ad --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/je/util/turtle.java @@ -0,0 +1,311 @@ +package je.util; +/* + * Class : Turtle + * Copyright: (c) Gerhard Röhner + * + * History + * -------- + * 3.00 2000.10.10 first version as java class + * 3.01 2002.10.22 DrawDynamic + * 3.02 2010.10.11 sleepTime for paint delay + * 3.03 2012.03.20 cartesian coordinate system, used with originX, originY, setOrigin + * 3.04 2015.01.24 english version, integrated component + */ + + +import java.awt.*; +import java.awt.image.*; +import java.awt.event.*; + +/** + * This class is a turtle component for simple graphic programming. + * + * @see + * @author Gerhard Röhner + * @version 3.03 20/03/2012 + */ + + +public class Turtle extends Canvas { + + // -- private Attribute ------------------------------------------------------ + + private BufferedImage myBufferedImage; + private Graphics myBufferedGraphics; + private Color foreground; + private Color background; + private static final double piDurch180 = Math.PI / 180; + + // -- public attributes ----------------------------------------------------- + + /** + * turtleX is the x-coordinate of the turtle + *

+ * Example:

myTurtle.turtleX = 100;
+ */ + public double turtleX; + + /** + * turtleY is the y-coordinate of the turtle. + *

+ * Example:

myTurtle.turtleY = 200;
+ */ + public double turtleY; + + /** + * turtleW is the current angle of the turtle in the range form 0 to 360 degrees. + *

+ * Example:

myTurtle.turtleW = 180;
+ */ + public double turtleW; + + /** + * originX is the x-position of the cartesian coodinate system within the turtle canvas. + *

+ * Example:

myTurtle.originX = 0;
+ */ + public double originX; + + /** + * originY is the y-position of the cartesian coodinate system within the turtle canvas. + *

+ * Example:

myTurtle.originY = 100;
+ */ + public double originY; + + /** + * If drawDynamic is true you can watch the drawing of the turtle. + *

+ * Example:

myTurtle.drawDynamic = true;
+ */ + public boolean drawDynamic; + + /** + * For drawDynamic = true you set the delay in milliseconds for drawing. + *

+ * Example:

myTurtle.sleepTime = 500;
+ */ + public int sleepTime = 0; + + // --- constructor ----------------------------------------------------------- + + /** + * Creates a Turtle with a canvas. + * At the beginning the Turtle is placed in the middle of it's canvas. + * The start angle is 0 degree, which means the Turtle looks to the right. + * The background color is white, the drawing color black. + *

+ * The turtle position can easily be changed by clicking into the canvas. + *

+ * The size of the canvas can easily be changed with the mouse. + *

+ * Example:

Turtle myTurtle = new Turtle();
+ */ + + public Turtle() { + myBufferedImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); + myBufferedGraphics = myBufferedImage.getGraphics(); + + setForeground(Color.black); + setBackground(Color.white); + drawDynamic = true; + + addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent evt) { + turtleMouseClicked(evt);}}); + addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent evt) { + turtleResized(evt);}}); + setOrigin(50, 50); + } + + private void turtleMouseClicked(MouseEvent evt) { + turtleX = evt.getX() - originX; + turtleY = originY - evt.getY(); + turtleW = 0; + } + + private void turtleResized(ComponentEvent evt) { + int width = getWidth(); + int height = getHeight(); + + BufferedImage newBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics newGraphics = newBufferedImage.getGraphics(); + newGraphics.setColor(background); + newGraphics.fillRect(0, 0, width, height); + newGraphics.setColor(foreground); + newGraphics.drawImage(myBufferedImage, 0, 0, this); + + turtleX = 0; + turtleY = 0; + turtleW = 0; + setOrigin(width / 2, height / 2); + + myBufferedImage = newBufferedImage; + myBufferedGraphics = newGraphics; + } + + public boolean isDoubleBuffered() { + return true; + } + + private void wTurtleMod360() { + while (turtleW >= 360) + turtleW = turtleW - 360; + while (turtleW < 0) + turtleW = turtleW + 360; + } + + // --- angle and turns ------------------------------------------------------- + + /** + * Turns the angle of the turtle relativ by the parameter angle. + * Positive values means a turn right, negative a turn left. + *

+ * Example:

myTurtle.turn(-90);
+ */ + public void turn(double angle) { + turtleW = turtleW + angle; + wTurtleMod360(); + } + + /** + * Sets the angle of the turtle absolute by the parameter angle. + * The angle increases counterclockwise, therefore + * right = 0, top = 90, left = 180, bottom = 270. + *

+ * Example:

myTurtle.turnto(270);
+ */ + public void turnto(double angle) { + turtleW = angle; + wTurtleMod360(); + } + + // --- Drawing --------------------------------------------------------------- + + /** + * The Turtle draws a line of the length specified in the current direction. + *

+ * Example:

myTurtle.draw(100);
+ */ + public void draw(double length) { + drawto(turtleX + length * Math.cos(turtleW * piDurch180), + turtleY + length * Math.sin(turtleW * piDurch180)); + } + + /** + * The Turtle draws a line form the current position (turtleX, turtleY) to the + * position (x, y) relativ to the cartesian coordinate system. + *

+ * Example:

myTurtle.drawto(200, 300);
+ */ + public void drawto(double x, double y) { + int x1 = (int) (originX + turtleX); + int x2 = (int) (originX + x); + int y1 = (int) (originY - turtleY); + int y2 = (int) (originY - y); + + myBufferedGraphics.drawLine(x1, y1, x2, y2); + if (drawDynamic){ + getGraphics().drawLine(x1, y1, x2, y2); + try { + Thread.currentThread().sleep(sleepTime); + } catch(InterruptedException e) { + } + } else + repaint(); + + turtleX = x; + turtleY = y; + } + + // --- Moving ---------------------------------------------------------------- + + /** + * The Turtle moves without drawing the length specified in the current + * direction. + *

+ * Example:

myTurtle.move(100);
+ */ + public void move(double length) { + turtleX = turtleX + length * Math.cos (turtleW * piDurch180); + turtleY = turtleY + length * Math.sin (turtleW * piDurch180); + } + + /** + * The Turtle moves without drawing to position (x, y) relativ to the + * cartesian coordinate system. + *

+ * Example:

myTurtle.moveto(100, 200);
+ */ + public void moveto(double x, double y) { + turtleX = x; + turtleY = y; + } + + // --- set origin ----------------------------------------------------------- + + /** + * Sets the origin of the cartesian coordinate system within the turtle's canvas. + *

+ * Example:

myTurtle.setOrigin(100, 200);
+ */ + public void setOrigin(double x, double y) { + originX = x; + originY = y; + } + + // --- fore- and background color -------------------------------------------- + + /** + * Sets the drawing color of the Turtle to color c. + *

+ * Example:

myTurtle.setForeground(Color.red);
+ */ + public void setForeground(Color c) { + foreground = c; + myBufferedGraphics.setColor(foreground); + super.setForeground(foreground); + } + + /** + * Sets the canvas color of the Turtle to color c. + *

+ * Example:

myTurtle.setBackground(Color.blue); 
+ */ + public void setBackground(Color c) { + background = c; + myBufferedGraphics.setColor(background); + myBufferedGraphics.fillRect(0, 0, getWidth(), getHeight()); + myBufferedGraphics.setColor(foreground); + repaint(); + } + + /** + * Clear the Turtle's canvas with the background color. + *

+ * Example:

myTurtle.clear();
+ */ + public void clear() { + setBackground(background); + getGraphics().drawImage(myBufferedImage, 0, 0, this); + repaint(); + } + + // --- Showing -------------------------------------------------------------- + + /** + * Shows the Turtle's canvas. + */ + public void paint(Graphics g) { + g.drawImage(myBufferedImage, 0, 0, this); + } + + /** + * Updates the Turtle's canvas. + */ + public void update(Graphics g) { + paint(g); + } + +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/jeclasses.jar b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/jeclasses.jar new file mode 100644 index 0000000000000000000000000000000000000000..7fa4892e3be6820a600278da2bd9b148d71d71da GIT binary patch literal 90273 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 Q1^hQi2Y{W+;M)N3FGnMA&j0`b literal 0 HcmV?d00001 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/jnumberfield.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/jnumberfield.java new file mode 100644 index 0000000..fd41a78 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/jnumberfield.java @@ -0,0 +1,129 @@ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.util.*; + +/** +Swing-component for input and output of numeric values. +*/ + +public class JNumberField extends JTextField { + + /** constructor for a JNumberField */ + public JNumberField() { + enableEvents(AWTEvent.KEY_EVENT_MASK); + } + + /** Gets a double-value from the JNumberField. */ + public double getDouble() { + Double d = new Double(getText()); + return d.doubleValue(); + } + + /** Gets a float-value from the JNumberField. */ + public float getFloat() { + Double d = new Double(getText()); + return d.floatValue(); + } + + /** Gets an int-value from the JNumberField. */ + public int getInt() { + Double d = new Double(getText()); + return d.intValue(); + } + + /** Gets a long-value from the JNumberField. */ + public long getLong() { + Double d = new Double(getText()); + return d.longValue(); + } + + /** Checks wether the JNumberField contains a valid numeric value. */ + public boolean isNumeric() { + final String Digits = "(\\p{Digit}+)"; + final String HexDigits = "(\\p{XDigit}+)"; + // an exponent is 'e' or 'E' followed by an optionally + // signed decimal integer. + final String Exp = "[eE][+-]?"+Digits; + final String fpRegex = + ("[\\x00-\\x20]*"+ // Optional leading "whitespace" + "[+-]?(" + // Optional sign character + "NaN|" + // "NaN" string + "Infinity|" + // "Infinity" string + + // A decimal floating-point string representing a finite positive + // number without a leading sign has at most five basic pieces: + // Digits . Digits ExponentPart FloatTypeSuffix + // + // Since this method allows integer-only strings as input + // in addition to strings of floating-point literals, the + // two sub-patterns below are simplifications of the grammar + // productions from the Java Language Specification, 2nd + // edition, section 3.10.2. + + // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt + "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ + + // . Digits ExponentPart_opt FloatTypeSuffix_opt + "(\\.("+Digits+")("+Exp+")?)|"+ + + // Hexadecimal strings + "((" + + // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "(\\.)?)|" + + + // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" + + + ")[pP][+-]?" + Digits + "))" + + "[fFdD]?))" + + "[\\x00-\\x20]*");// Optional trailing "whitespace" + + return java.util.regex.Pattern.matches(fpRegex, getText()); + } + + /** Sets a double-value into the JNumberField. */ + public void setDouble(double d) { + setText(String.valueOf(d)); + } + + /** Sets a double-value with N digits into the JNumberField. */ + public void setDouble(double d, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", d)); + } + + /** Sets a float-value into the JNumberField. */ + public void setFloat(float f) { + setText(String.valueOf(f)); + } + + /** Sets a float-value with N digits into the JNumberField. */ + public void setFloat(float f, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", f)); + } + + /** Sets an int-value into the JNumberField. */ + public void setInt(int i) { + setText(String.valueOf(i)); + } + + /** Sets a long-value into the JNumberField. */ + public void setLong(long l) { + setText(String.valueOf(l)); + } + + /** Clears the JNumberField */ + public void clear() { + setText(""); + } + + protected void processKeyEvent(KeyEvent e) { + super.processKeyEvent(e); + if (isNumeric() || getText().equals("-") || + getText().equals("") || getText().equals(".")) + setBackground(Color.white); + else + setBackground(Color.red); + } + +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/meta-inf/manifest.mf b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/meta-inf/manifest.mf new file mode 100644 index 0000000..4e2b00e --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/meta-inf/manifest.mf @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Class-Path: JEClasses.jar +Created-By: 1.8.0_161 (Oracle Corporation) +Main-Class: BreakVigenere + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/numberfield.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/numberfield.java new file mode 100644 index 0000000..ca7ef01 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_kasiskitest/numberfield.java @@ -0,0 +1,128 @@ +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** +AWT-component for input and output of numeric values. +*/ + +public class NumberField extends TextField { + + /** constructor for a NumberField */ + public NumberField() { + enableEvents(AWTEvent.KEY_EVENT_MASK); + } + + /** Gets a double-value from the NumberField. */ + public double getDouble() { + Double d = new Double(getText()); + return d.doubleValue(); + } + + /** Gets a float-value from the NumberField. */ + public float getFloat() { + Double d = new Double(getText()); + return d.floatValue(); + } + + /** Gets an int-value from the NumberField. */ + public int getInt() { + Double d = new Double(getText()); + return d.intValue(); + } + + /** Gets a long-value from the NumberField. */ + public long getLong() { + Double d = new Double(getText()); + return d.longValue(); + } + + /** Checks wether the NumberField contains a valid numeric value. */ + public boolean isNumeric() { + final String Digits = "(\\p{Digit}+)"; + final String HexDigits = "(\\p{XDigit}+)"; + // an exponent is 'e' or 'E' followed by an optionally + // signed decimal integer. + final String Exp = "[eE][+-]?"+Digits; + final String fpRegex = + ("[\\x00-\\x20]*"+ // Optional leading "whitespace" + "[+-]?(" + // Optional sign character + "NaN|" + // "NaN" string + "Infinity|" + // "Infinity" string + + // A decimal floating-point string representing a finite positive + // number without a leading sign has at most five basic pieces: + // Digits . Digits ExponentPart FloatTypeSuffix + // + // Since this method allows integer-only strings as input + // in addition to strings of floating-point literals, the + // two sub-patterns below are simplifications of the grammar + // productions from the Java Language Specification, 2nd + // edition, section 3.10.2. + + // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt + "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ + + // . Digits ExponentPart_opt FloatTypeSuffix_opt + "(\\.("+Digits+")("+Exp+")?)|"+ + + // Hexadecimal strings + "((" + + // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "(\\.)?)|" + + + // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" + + + ")[pP][+-]?" + Digits + "))" + + "[fFdD]?))" + + "[\\x00-\\x20]*");// Optional trailing "whitespace" + + return java.util.regex.Pattern.matches(fpRegex, getText()); + } + + /** Sets a double-value into the NumberField. */ + public void setDouble(double d) { + setText(String.valueOf(d)); + } + + /** Sets a double-value with N digits into the NumberField. */ + public void setDouble(double d, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", d)); + } + + /** Sets a float-value into the NumberField. */ + public void setFloat(float f) { + setText(String.valueOf(f)); + } + + /** Sets a float-value with N digits into the NumberField. */ + public void setFloat(float f, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", f)); + } + + /** Sets an int-value into the NumberField. */ + public void setInt(int i) { + setText(String.valueOf(i)); + } + + /** Sets a long-value into the NumberField. */ + public void setLong(long l) { + setText(String.valueOf(l)); + } + + /** Clears the NumberField */ + public void clear() { + setText(""); + } + + protected void processKeyEvent(KeyEvent e) { + super.processKeyEvent(e); + if (isNumeric() || getText().equals("-") || + getText().equals("") || getText().equals(".")) + setBackground(Color.white); + else + setBackground(Color.red); + } + +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/balkendiagramm.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/balkendiagramm.java new file mode 100644 index 0000000..ca4b7e8 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/balkendiagramm.java @@ -0,0 +1,85 @@ +import java.awt.*; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; +import javax.swing.*; + +public class Balkendiagramm extends JPanel { + + private double gesamt; + private double haeufigkeit[]; + private double maxwert; + private int verschiebung = 0; + private double haeufigkeit_de[] = { 0.0651, 0.0189, 0.0306, 0.0508, 0.174, 0.0166, 0.0301, 0.0476,0.0755, 0.0027, 0.0121,0.0344,0.0252,0.0978,0.0251,0.0079,0.0002,0.07,0.0727,0.0615,0.0435,0.067,0.0189,0.0003,0.0004,0.0113}; + private boolean zeigeDeutsch = true; + + + public void setHaeufigkeit(double haeufigkeit[]) { + + this.haeufigkeit = haeufigkeit; + gesamt = 0; + for (int i = 0; i < 26; i++) { + gesamt += haeufigkeit[i]; + } + for (int i = 0; i < 26; i++) { + haeufigkeit[i] /= gesamt; + } + maxwert = 0.20; + + } + + public void setVerschiebung(int verschiebung) { + if (verschiebung >= 0 && verschiebung < 26) { + this.verschiebung = verschiebung; + + } else { + this.verschiebung = 0; + } // end of if-else + } + public void setZeigeDeutsch(boolean show) { + zeigeDeutsch = show; + } + + + public void paintComponent(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + super.paintComponent(g2); + Dimension d = getSize(null); + //Skalieren auf 100x100 mit y-Invertierung + g2.scale(d.getWidth() / 120.0, -d.getHeight() / 100.0); + // Ursprung verschieben nach (15,-90) + g2.translate(5, -90); + // Linien etwas breiter + g2.setStroke(new BasicStroke(1.5f)); + // x-Achse zeichnen + g2.draw(new Line2D.Double(0, 0, 104, 0)); + // Linien etwas dünner + g2.setStroke(new BasicStroke(0.5f)); + // Deutsche Häufigkeit grau + g2.setColor(Color.darkGray); + if(zeigeDeutsch) { + + // Säulen zeichnen + for (int i = 0; i < 26; i++) { + g2.fill(new Rectangle2D.Double(4 * i+1, 0, 2, haeufigkeit_de[i] / maxwert *100)); + } + } + + // Texthäufigkeit blau + g2.setColor(Color.blue); + // Säulen zeichnen + for (int i = 0; i < 26; i++) { + g2.fill(new Rectangle2D.Double(4 * i, 0, 2, haeufigkeit[(i+verschiebung)%26] / maxwert *100)); + } + // y-Invertierung rückgängig machen + g2.scale(1, -1); + // Beschriftung x-Achse + String xAchse = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + // Fontgröße für Beschriftung ändern + g2.setColor(Color.black); + g2.setFont(g2.getFont().deriveFont(5f)); + for (int i = 0; i < 26; i++) { + g2.drawString(xAchse.substring(i, i + 1), + i * 4, +6); + } + } +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/baustein.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/baustein.java new file mode 100644 index 0000000..55954a1 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/baustein.java @@ -0,0 +1,42 @@ +public class Baustein implements Comparable{ + + // Anfang Attribute + private String zeichen; + private int anzahl; + // Ende Attribute + + public Baustein(String zeichen) { + super(); + anzahl = 1; + this.zeichen = zeichen; + } + // Anfang Methoden + + + + public int compareTo(Baustein c) { + + int anz = c.getAnzahl(); + + //ascending order + return anz - this.anzahl; + + //descending order + //return compareQuantity - this.quantity; + + } + public String getZeichen() { + return zeichen; + } + + public int getAnzahl() { + return anzahl; + } + + public void incAnzahl() { + anzahl++; + } + + + // Ende Methoden +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/breakvigenere.jar b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/breakvigenere.jar new file mode 100644 index 0000000000000000000000000000000000000000..cb3748e2f778abf7967882d4bbe7aeb0adc05124 GIT binary patch literal 32284 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%0ALg>BZrd=5wC#o~-1aBe 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%0AAj%{vNv%8h;f8{0Z>#bnWR9_TLq){R`mbmF!F7 zrvtc`506g=aR06e)4v_Zy|jON#C(}5Jw0OnyJ)Td^1%7h{K?xdQ;6Ta?c?w=yOI$H V1L)F#fCvE}+JF)7MUGG3{Xao4g1rC$ literal 0 HcmV?d00001 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/breakvigenere.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/breakvigenere.java new file mode 100644 index 0000000..e186561 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/breakvigenere.java @@ -0,0 +1,360 @@ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.table.*; +import java.util.ArrayList; +import java.util.Collections; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Highlighter; +import javax.swing.text.Highlighter.HighlightPainter; +import javax.swing.text.BadLocationException; + + +/** + * + * Programm zur Kryptoanalyse + * von monoalphabetischen Substitutionen + * + * @version 1.0 from 23.11.2016 + * @author Thomas Schaller + */ + +public class BreakVigenere extends JFrame { + // Anfang Attribute + private JTextField[] buchstabe; + + private JButton jButton1 = new JButton(); + private JButton jBBuchstabe = new JButton(); + private Balkendiagramm bdText = new Balkendiagramm(); + private Balkendiagramm bdBruteForce = new Balkendiagramm(); + private Balkendiagramm bdDeutsch = new Balkendiagramm(); + + private JTextArea jTAKrypto = new JTextArea(""); + private JScrollPane jTAKryptoScrollPane = new JScrollPane(jTAKrypto); + private JTextArea jTAKlartext = new JTextArea(""); + private JScrollPane jTAKlartextScrollPane = new JScrollPane(jTAKlartext); + private JLabel jLKryptotext = new JLabel(); + private JLabel jLKlartext = new JLabel(); + private JLabel jLCopyright = new JLabel(); + private JTextArea jTAKorrelation = new JTextArea(""); + private JScrollPane jTAKorrelationScrollPane = new JScrollPane(jTAKorrelation); + private JSpinner jSpVerschiebung = new JSpinner(); + private SpinnerNumberModel jSpVerschiebungModel = new SpinnerNumberModel(0, 0, 99, 1); + private JNumberField jNFAnzahlTreffer = new JNumberField(); + private JLabel lVerschiebung = new JLabel(); + private JLabel lAnzahlgleicherBuchstaben = new JLabel(); + // Ende Attribute + + public BreakVigenere (String title) { + super (title); + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + int frameWidth = 702; + int frameHeight = 651; + setSize(frameWidth, frameHeight); + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + int x = (d.width - getSize().width) / 2; + int y = (d.height - getSize().height) / 2; + setLocation(x, y); + Container cp = getContentPane(); + cp.setLayout(null); + // Anfang Komponenten + + jTAKryptoScrollPane.setBounds(16, 24, 665, 105); + jTAKrypto.setLineWrap(true); + jTAKrypto.setFont(new Font("Courier New", Font.BOLD, 16)); + jTAKrypto.setText("JMLQMFNSKIOQNXGYZOQEBJLUKXHFCXGVLGBMREAJZCAEKVIFOWJLMFGJLPQZJIYHQQHYJLAFGFLRLQYESTPMHIAWQZFIPPMZMIZGPDOIIIVGTHIIQVKHLVHQOPLNMIKMSWCYKMUIVBREADEQOXLVVMILSMVWYZLVAONSIIVIKVKIVPOIZIEGXHLHCDILKIVPKYAWKTKRIIVQJMRXQZKVHFBVULHRVQYXYMBTKQPYAUSNHLZUSJUJBQTFHRLEKMUIAUTPHXMUTMZGPQXWWVIONINIAONVPIJQTIUWMONWIRLUMIUAMDQIZTWXEKYEXTOELPQNXMZIFEKGOWJONIYDCDVSSCODGTOMMMTKLKMNKRPRLQSRHGPEKMUIUFUHLZMDLJLRBXOGOXMZHYJLAONPBKMDBSYRIONNLHMYKMUDMXTIUOTMXXLBBNAGOWBMHIUDCYTGOWBQTESTPMHIAMVEKMUIZFGFBPINKVGYOQNIUYVPYSHPTQBIYJONGVLRIXVLHFMFKEBWHGTYADMZJETMBQXJHRLQXHPIXDUKYIAEOZLTWXEESTPMHIAMAONIJLQRLVPIZGTKHFMDKWDEZZUGOIQZLIZXMEBIYJITXIUSPZKWJLTEYISHQQYIYACDJIPQRMNVCSUUZESMMZOWJLMZQVFTBARSNIVSOSCEVNGXAMAFGFLPTMYSJEQZLSYQMUTIZZWYBIYWKTRWZPMDLVLMHGCLSIVPKRRIVZCSYXAAJIYIQZKWRIVZYEADMEBSYKMEILSEOQTKLVVQARKOZKVXVKZMVLPWKTYGOAIONHHPMUILADCQXVHXMZCYYHMZJETETEREAIQZOWJLMEORUWXDILLFMZAXGXEUKFLMABOISWEQOWLZQDZZAMWYTMHTIDKRAETXKWNIPAXGOXLQXXJLBUMOLMBPOIIYKTYXHFMZJIZOMZTWHXHQYFLWBUSQLRLUKVLMPQTJVPOQORKIZPOICIZEILPILQTIUETBNEIIBQGYZHMDZEIYTMGYZKMINPAA\nMDJIUQAEKRZMVPGPSIDQXFYECONXHPAAKMUQIXHIUYBLZAVVLQTLPIZZGGOOTMXXLBBNAGOWBMHIUWWNKKPRVFSEUAQQJIYZWZBSYRMENEUHMXZWPGPEUQPXCYKMUIXQXMVHQEILLTWXEESTPMHIAMAONIZYJEZMAYBUURTMBUSFLMABOISIQZKVWIZUUHLZWZCLYIVPZVPXPQSMBWAUILHYNHKVZGPAHIUIAFGRKEZPGPWLINKXLFMEILYRSFKESWWPOINIEANRAIIXVLHFMFOWJLMDKMOIVRUPNILQXFBGPEZEIIVHKVDIVPKXLFMXREZSJQXIPXAHKVDVNQRXLETBNEIIBQJMLIZMRPLVLUTKZMVHUPBXWDOWJLETRXLFMUJIUQWZUESTPMHIAMAONIUWCNYXPXCFOSUWUQZLVHMZCEYHQQYWJLWZYIPXTMTKLQJXOGOKZGTHZXHXOGOLIFZIKMMEHIYIQFYMTNITXESWWXGRNIDAXXYMBTKQPYAGTHIITXGWVHMDOXHPQQTMZGPQMISIPDZISIWZHEAXQEZEHPJQXXPIUBLSOPMZKVZGPXAKCSZPOIHPXTGFLXMZGGONMIKMSWLDKMVHMDBMLVEDZIYRHGCIJLAQRRHPAYKGOEVUYGOIATOPMWUUZXLPPMZXLIZTOIYDCPOIUEKTOLTFMZGRUXMMRFLVBUYGOIQNKIYJCZJIUIQZKGOMNRXMLVAONIPFMNKWAIPQTHGYUQOWAECEFALMZGTHLRUQZESPAONIPFMZJMLECRKMUIZSKQLMVEGQLRIONWLWQFFIUYVPYSCIZNARKIVEORKHIEYWPGPPOIRPMUTIYIIGLHLVODKVLRLDKLLRSMTRUEPQFYLMVVGLYLCZJIYXABZIYMUVGLYZMDGPSKMYKMUIZFKHLVVQGTVPQFGRPWKTKKLPMTXXLKQABEURQNGXAMAFGHLPTMVSYXIMRFLVBUYZLVEDLISXMMRTOEJQZIBRLNKPSEAAYOLRVIUVAYVPYGOYNPOI\nWSTKGPWLINKXPWKTKGOMNRXMLVCZMQPXDQXAYJMXZITETBNEIIBGTHZGPXYWLPPUKVGYEGXHLETNKVAMAEILLMJQHIUYBLZHPIVMILQILQSFBGPEZEIIVLAHYIPQTAHVQYPEOVODOJMHMDLVHRHAYIIPIUYIKIDUMIUVMBUVAEAUJILECRARKWKTRYNZWDYXHXBPKVHPJQXXPWKTKMIILUKXHFCXGVLGBMJIZXZUZLLQQGYDBZMDCIUHMZJEIIQMHIYEVPKVZETEOQVVQSORHPDQXAYJMXZIHPXTGFLXMQORGYBDGKLRLUKWLVSDETASODGTOMAONWAEZWKZVVAONPHKDUMIUVMEMIYMMFORKIVRUPNIVPKRQEPDNYUHMDZIUMVHKVNIAEKROIQFARKHQQAVZTZZMPPGPHURAVQFNITMCEBSYKMEILSEOQTITIBTUHLACDJIBRBQXHLQVMSIUZQSKRYIKTOJMVMNKOHRVF"); + jTAKrypto.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent evt) { + jTAKrypto_KeyTyped(evt); + } + }); + cp.add(jTAKryptoScrollPane); + + jTAKlartextScrollPane.setBounds(16, 480, 665, 105); + jTAKlartext.setLineWrap(true); + jTAKlartext.setFont(new Font("Courier New", Font.BOLD, 16)); + cp.add(jTAKlartextScrollPane); + jLKryptotext.setText("Kryptotext"); + jLKryptotext.setBounds(16, 3, 110, 20); + cp.add(jLKryptotext); + jLKlartext.setText("Klartext"); + jLKlartext.setBounds(16, 456, 110, 20); + cp.add(jLKlartext); + jLCopyright.setText("(cc) Schaller (ZPG Informatik) - V1.0 (2017)"); + jLCopyright.setBounds(128, 584, 419, 33); + jLCopyright.setHorizontalAlignment(SwingConstants.CENTER); + jLCopyright.setFont(new Font("Dialog", Font.PLAIN, 12)); + cp.add(jLCopyright); + + // -------------------------------- Tab 1 --------------------------------------------- + JPanel tab1 = new JPanel(); + tab1.setLayout(null); + + jSpVerschiebung.setBounds(192, 40, 41, 25); + jSpVerschiebung.setValue(1); + jSpVerschiebung.setModel(jSpVerschiebungModel); + jSpVerschiebung.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent evt) { + jSpVerschiebung_StateChanged(evt); + } + }); + tab1.add(jSpVerschiebung); + + lVerschiebung.setBounds(16, 10, 310, 20); + lVerschiebung.setText("Angriff auf die Schlüssellänge mit Brute Force"); + tab1.add(lVerschiebung); + JLabel l = new JLabel(); + l.setBounds(14, 80, 320, 100); + l.setText("Die meisten Schlüsselwörter sind nicht länger als 10 bis maximal 15 Buchstaben. Probiere daher systematisch die Schlüssellänge durch und schaue, ob die Häufigkeitsverteilungen des ersten Teiltextes in etwa dem deutschen Alphabet entspricht. Eine Verschiebung ist dabei erlaubt."); + tab1.add(l); + l = new JLabel(); + l.setBounds(16, 40, 162, 20); + l.setText("Vermutete Schlüssellänge:"); + tab1.add(l); + + double[] h2 = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + bdBruteForce.setBounds(380,10,300,120); + bdBruteForce.setHaeufigkeit(h2); + bdBruteForce.setZeigeDeutsch(false); + tab1.add(bdBruteForce); + + double[] h3 = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + bdDeutsch.setBounds(380,140,300,120); + bdDeutsch.setHaeufigkeit(h3); + tab1.add(bdDeutsch); + + + + // ---------------------------------- Tab 2 ------------------------------- + JPanel tab2 = new JPanel(); + tab2.setLayout(null); + + l = new JLabel(); + l.setBounds(16, 10, 310, 20); + l.setText("Angriff auf die Teiltexte mit Häufigkeitsanalyse"); + tab2.add(l); + + l = new JLabel(); + l.setBounds(380, 10, 300, 25); + l.setText("Buchstabenhäufigkeit Deutsch"); + tab2.add(l); + + l = new JLabel(); + l.setBounds(16, 40, 300, 25); + l.setText("Schlüssel"); + tab2.add(l); + + l = new JLabel(); + l.setBounds(16, 100, 300, 100); + l.setText("Versuche den Schlüssel zu knacken, indem du in jedem Teiltext die Häufigkeitsverteilung der Buchstaben mit der üblichen Häufigkeitsverteilung in deutschen Texten in Einklang bringst."); + tab2.add(l); + + double[] h = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + bdText.setBounds(380,40,300,180); + bdText.setHaeufigkeit(h); + tab2.add(bdText); + + jButton1.setBounds(16, 210, 193, 25); + jButton1.setText("Entschlüsselung versuchen"); + jButton1.setMargin(new Insets(2, 2, 2, 2)); + jButton1.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + jButton1_ActionPerformed(evt); + } + }); + tab2.add(jButton1); + + + + // Ende Komponenten + buchstabe = new JTextField[26]; + for (int i = 0; i<26 ;i++ ) { + buchstabe[i] = new JTextField(); + buchstabe[i].setBounds(16+i*25, 65, 25, 25); + buchstabe[i].setText("A"); + buchstabe[i].setHorizontalAlignment(SwingConstants.CENTER); + buchstabe[i].setVisible(false); + buchstabe[i].addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent evt) { + highlightKryptotext(evt); + } + }); + buchstabe[i].addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + e.consume(); + } + + public void keyTyped(KeyEvent e) { + e.consume(); + } + + public void keyPressed(KeyEvent e) { + JTextField textField = (JTextField) e.getSource(); + String text = textField.getText(); + if ((e.getKeyChar()>='a' && e.getKeyChar()<='z') ||(e.getKeyChar()>='A' && e.getKeyChar()<='Z')) { + text = ""+e.getKeyChar(); + } + if (e.getKeyChar()==' ' || e.getKeyChar() == KeyEvent.VK_BACK_SPACE || e.getKeyChar() == KeyEvent.VK_DELETE) { + text = ""; + + } // end of if + textField.setText(text.toUpperCase()); + e.consume(); + if (textField.getText().length()>0) { + bdText.setVerschiebung((int) textField.getText().charAt(0)-65); + + } else { + bdText.setVerschiebung(0); + } // end of if-else + bdText.repaint(); + + } // end of if + + }); + + tab2.add(buchstabe[i]); + } // end of for + + JTabbedPane tabpane = new JTabbedPane + (JTabbedPane.TOP,JTabbedPane.SCROLL_TAB_LAYOUT ); + tabpane.setBounds(10,140,672,290); + + tabpane.addTab("Schritt 1", tab1); + tabpane.addTab("Schritt 2", tab2); + cp.add(tabpane); + + setResizable(false); + setVisible(true); + } + + + + // Anfang Methoden + public void jButton1_ActionPerformed(ActionEvent evt) { + String krypttext = jTAKrypto.getText().toUpperCase(); + String klartext=""; + int c = 0; + int diff = (Integer) jSpVerschiebung.getValue(); + for (int i=0;i=65 && asc<=90) { + h[asc-65]++; + } + } // end of if + c++; + } // end of if + } + bdText.setHaeufigkeit(h); + if (buchstabe[start].getText().length()>0) { + bdText.setVerschiebung((int) buchstabe[start].getText().charAt(0)-65); + + } else { + bdText.setVerschiebung(0); + } // end of if-else + bdText.repaint(); + } catch(BadLocationException e) {} + } + + + public void jSpVerschiebung_StateChanged(ChangeEvent evt) { + String krypto = jTAKrypto.getText().toUpperCase(); + String krypto2=""; + int diff = (Integer) jSpVerschiebung.getValue(); + Highlighter h1 = jTAKrypto.getHighlighter(); + h1.removeAllHighlights(); + int c = 0; + double[] h = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + try{ + for (int i=0;i=65 && asc<=90) { + h[asc-65]++; + } + } // end of if + c++; + } // end of if + } + bdBruteForce.setHaeufigkeit(h); + bdBruteForce.repaint(); + } catch(BadLocationException e) {} + + for (int i=0; iRegula Hoefer-Isenegger
+@version 0.1 +*/ +public class LineRenderer { + private Point2D.Double point; + private Turtle turtle; + + LineRenderer(Turtle turtle) { + this.point = new Point2D.Double(); + this.turtle = turtle; + } + + /** Initialisation with coordinates x and + y. + */ + public void init(double x, double y) { + this.point.setLocation(x, y); + } + /** Same as init(double x, double y), but with a Point2D.Double + argument for convenience + */ + public void init(Point2D.Double p) { + this.init(p.x, p.y); + } + /** Get the current x-coordinate in screen coordinates.*/ + private double getX(){ + return (toScreenCoords(point)).getX(); + } + /** Get the current x-coordinate in screen coordinates.*/ + private double getY(){ + return toScreenCoords(point).getY(); + } + /** Calls the clipLineTo and wrapLineTo methods, according + to the turtle's edge behavior. + + Only overwrite this method when working with another + (one that you have defined) edge behaviour.
+ If you mean to change the manner of drawing lines, do this in + the methods clipLineTo() and wrapLineTo(). + @see #clipLineTo + @see #wrapLineTo + */ + protected void internalLineTo(double x, double y){ + Point2D.Double screenPos = toScreenCoords(x, y); + if(turtle.isClip()){ + clipLineTo(screenPos.getX(), screenPos.getY()); + } + if (turtle.isWrap()){ + wrapLineTo(screenPos.getX(), screenPos.getY()); + } + init(x,y); + } + /** Calls the internalLineTo(x,y), which does the actual painting. + */ + public void lineTo(double x, double y) { + internalLineTo(x, y); + } + /** Calls the internalLineTo(x,y), which does the actual painting. + + This method works the same way as lineTo(double x, double y), but + is added for convenience. + */ + public void lineTo(Point2D.Double p) { + internalLineTo(p.getX(), p.getY()); + } + /** Does the actual painting for clip mode. + + It works already with ScreenCoords! + For further comments cf. internalLineTo(double x, double y). + @see #internalLineTo + */ + protected void clipLineTo(double x, double y){ + turtle.getPlayground().lineTo(getX(), getY(), x, y, turtle.getPen()); + } + /** Does the actual painting for wrap mode. + + It works already with ScreenCoords! + For further comments cf. internalLineTo(double x, double y). + @see #internalLineTo + */ + protected void wrapLineTo(double x, double y){ + double dx = getX() - x; + double dy = getY() - y; + Point2D.Double start = new Point2D.Double(x, y); + Point2D.Double end = new Point2D.Double(start.x+dx, start.y+dy); + + intoPanel(start, end); + Point2D.Double tmp; + while ((tmp = calcIntersection(start.x, start.y, end.x, end.y)) != null){ + turtle.getPlayground().lineTo(start.x, start.y, tmp.getX(), tmp.getY(), turtle.getPen()); + start = tmp; + intoPanel(start, end); + dx = end.x - start.x; + dy = end.y - start.y; + } + + turtle.getPlayground().lineTo(start.x, start.y, end.x, end.y, turtle.getPen()); + } + /** Makes the coordinates fit into the Panel. + + Well, this is some sort of modulus calculation. + */ + private void intoPanel(Point2D.Double start, Point2D.Double end){ + int pWidth = turtle.getPlayground().getWidth(); + int pHeight = turtle.getPlayground().getHeight(); + while(start.x < 0){ + start.x += pWidth; + end.x += pWidth; + } + while (start.x > pWidth){ + start.x -= pWidth; + end.x -= pWidth; + } + if(start.x == 0 && end.x < start.x){ + start.x += pWidth; + end.x += pWidth; + } + if(start.x == pWidth && end.x > start.x){ + start.x -= pWidth; + end.x -= pWidth; + } + while(start.y < 0){ + start.y += pHeight; + end.y += pHeight; + } + while (start.y > pHeight){ + start.y -= pHeight; + end.y -= pHeight; + } + if(start.y == 0 && end.y < start.y){ + start.y += pHeight; + end.y += pHeight; + } + if(start.y == pHeight && end.y > start.y){ + start.y -= pHeight; + end.y -= pHeight; + } + + } + /** Intersection line with playground-edges + (startX / startY) MUST lie in the playground! + */ + private Point2D.Double calcIntersection(double startX, double startY, double endX, double endY){ + double dx = endX - startX; + double dy = endY - startY; + double W = turtle.getPlayground().getWidth(); + double H = turtle.getPlayground().getHeight(); + if(endX < 0){ + if((dy/dx <= startY/startX) && (dy/dx >= -(H-startY)/startX)){ // links + return new Point2D.Double(0, startY-startX*dy/dx); + } + } + else if(endX > W){ + if((dy/dx >= -startY/(W-startX)) && (dy/dx <= (H-startY)/(W-startX))){// rechts + return new Point2D.Double(W, startY+(W-startX)*dy/dx); + } + } + if(endY < 0){ // oben + return new Point2D.Double(startX-startY*dx/dy, 0); + } + else if(endY > H){ // unten + return new Point2D.Double(startX+(H-startY)*dx/dy, H); + } + else{ + return null; // Endpoint lies in the window + } + } + /** Calculates the screen coordinates of the turtle's actual + position according to the interpretation of the playground. + */ + private Point2D.Double toScreenCoords(double x, double y){ + return turtle.getPlayground().toScreenCoords(x, y); + } + /** Calculates the screen coordinates of the turtle's actual + position according to the interpretation of the playground. + + Added for convenience. + @see #toScreenCoords(double, double) + */ + private Point2D.Double toScreenCoords(Point2D.Double p){ + return turtle.getPlayground().toScreenCoords(p.x, p.y); + } +} + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/pen.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/pen.java new file mode 100644 index 0000000..8fcc8b7 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/pen.java @@ -0,0 +1,268 @@ +// Pen.java + +// Copyright 2002 Regula Hoefer-Isenegger +// +// This file is part of The Java Turtle package (TJT) +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.awt.Color; +import java.awt.BasicStroke; +import java.awt.Stroke; +import java.awt.Font; +import java.awt.GraphicsEnvironment; + +/** The Pen class provides anything used for drawing the lines, such as line width, + pen color, end caps, dashed lines, etc. + + @see java.awt.BasicStroke + + @author Regula Hoefer-Isenegger + @version 0.1.1 +*/ +public class Pen +{ + /* Attributes *********************************************/ + + /** The default font that is used when drawing Text. + + First argument must be one of "Serif", "SansSerif", "Monotyped", "Dialog" or "DialogInput" + to guarantee that this font exists on all systems. + + @see java.awt.Font for more information, e.g. on font styles. + + */ + public static Font DEFAULT_FONT = new Font("SansSerif", Font.PLAIN, 24); + private Color color; + private Color fillColor; + private BasicStroke stroke; + private Font font; + + /* Constructors *******************************************/ + /** Constructor with standard Color and standard Stroke. + + @see java.awt.BasicStroke + */ + public Pen(){ + color = Color.black; + setFillColor(Color.black); + stroke = new BasicStroke(); + font = DEFAULT_FONT; + } + /** Constructor with Color color and standard Stroke. + + @see java.awt.BasicStroke + */ + public Pen(Color color){ + this.color = color; + setFillColor(color); + stroke = new BasicStroke(); + font = DEFAULT_FONT; + } + /* Methods ************************************************/ + /** Query the Pens color.*/ + public Color getColor(){ + return color; + } + /** Set the Pens color.*/ + public void setColor(Color color){ + this.color = color; + } + /** Set the Pens fill color. + */ + public void setFillColor(Color color){ + this.fillColor = color; + } + /** Query the Pens fill color.*/ + public Color getFillColor(){ + return this.fillColor; + } + /** Get the Pens Stroke + + @see BasicStroke + @see Stroke + */ + public Stroke getStroke(){ + return stroke; + } + /** Query the Pens line width*/ + public float getLineWidth(){ + return stroke.getLineWidth(); + } + /** Query the Pens end cap style. + + @see java.awt.BasicStroke + */ + public int getEndCap(){ + return stroke.getEndCap(); + } + /** Query the Pens line join style. + + @see java.awt.BasicStroke + */ + public int getLineJoin(){ + return stroke.getLineJoin(); + } + /** Query the Pens miter limit style. + + @see java.awt.BasicStroke + */ + public float getMiterLimit(){ + return stroke.getMiterLimit(); + } + /** Query the Pens dash array. + + @see java.awt.BasicStroke + */ + public float[] getDashArray(){ + return stroke.getDashArray(); + } + /** Query the Pens dash phase. + + @see java.awt.BasicStroke + */ + public float getDashPhase(){ + return stroke.getDashPhase(); + } + + /** Set the Pens line width. */ + public void setLineWidth(float width){ + stroke = new BasicStroke((float)width, + stroke.getEndCap(), + stroke.getLineJoin(), + stroke.getMiterLimit(), + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens end cap style. + + @see java.awt.BasicStroke + */ + public void setEndCap(int endCap){ + stroke = new BasicStroke(stroke.getLineWidth(), + endCap, + stroke.getLineJoin(), + stroke.getMiterLimit(), + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens line join style. + + @see java.awt.BasicStroke + */ + public void setLineJoin(int join){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + join, + stroke.getMiterLimit(), + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens miter limit. + + @see java.awt.BasicStroke + */ + public void setMiterLimit(float miterlimit){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + stroke.getLineJoin(), + miterlimit, + stroke.getDashArray(), + stroke.getDashPhase()); + } + /** Set the Pens dash array. + + @see java.awt.BasicStroke + */ + public void setDash(float[] dashArray){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + stroke.getLineJoin(), + stroke.getMiterLimit(), + dashArray, + stroke.getDashPhase()); + } + /** Set the Pens dash phase. + + @see java.awt.BasicStroke + */ + public void setDashPhase(float dashPhase){ + stroke = new BasicStroke(stroke.getLineWidth(), + stroke.getEndCap(), + stroke.getLineJoin(), + stroke.getMiterLimit(), + stroke.getDashArray(), + dashPhase); + } + /** Provides information about the currently available font families (e.g. "Roman"). + Each font name is a string packed into a array of strings. + @see java.awt.Font for more information about font attributes etc. + */ + public static String[] getAvailableFontFamilies(){ + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + String s[] = ge.getAvailableFontFamilyNames(); + return s; + } + /** Change the font style. + + @see java.awt.Font for possible styles. + */ + public void setFontStyle(int style){ + font = font.deriveFont(style); + } + /** Change the font size (in points). + */ + public void setFontSize(int size){ + font = font.deriveFont((float)size); + } + /** Change the font size (in points). + You will probably only need the int version setFontSize(int). + */ + public void setFontSize(float size){ + font = font.deriveFont(size); + } + /** Query the size (in points, rounded to int) of the current font. + */ + public int getFontSize(){ + return font.getSize() ; + } + /** Change the font to the given one. + */ + public void setFont(Font f){ + font = f; + } + /** Query the current font. + */ + public Font getFont(){ + return font; + } +} + + + + + + + + + + + + + + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/playground.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/playground.java new file mode 100644 index 0000000..6c0db5b --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/playground.java @@ -0,0 +1,789 @@ +// Playground.java + +// Copyright 2002 Regula Hoefer-Isenegger +// Major code modifications by Aegidius Pluess +// Adaption for the Java-Editor by Gerhard Röhner +// +// This file is part of The Java Turtle package (TJT) +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.util.*; +import javax.swing.*; +import java.awt.*; +import java.awt.print.*; +import java.awt.geom.*; +import java.awt.image.*; +import java.awt.font.*; + +/** + A Playground is the Turtle's home, i.e. the Turtle lives + and moves in the Playground. + + ThePlayground is responsible for interpreting angle and position of the + Turtle and for choosing the correct turtle image and putting it on the right + spot of the Playground. This means: e.g. whenever you wish to switch the x- and y-axis, you + should do it in this class, and not in the Turtle class. + + @author Regula Hoefer-Isenegger + @version 0.1.1 +*/ + +public class Playground extends JPanel implements Printable { + + /** Hold the Turtles of this Playground. */ + private Vector turtles; + + /** Hold the offscreen buffer and graphics context + * where Turtle traces are drawn. + */ + private BufferedImage traceBuffer = null; + protected Graphics2D traceG2D = null; + private Dimension playgroundSize; + + /** Hold the offscreen buffer and graphics context + * of the Turtles images. + */ + private BufferedImage turtleBuffer = null; + protected Graphics2D turtleG2D = null; + + /** Flag to tell whether we have at least one Turtle shown. */ + private boolean isTurtleVisible = false; + + /** Flag to tell whether we use automatic repainting */ + private boolean isRepainting = true; + + /** The default background color. + */ + protected static Color DEFAULT_BACKGROUND_COLOR = Color.white; + + private double printerScale = 1; // Default printer scaling + private TPrintable traceCanvas; // Store ref to user class + private Graphics2D printerG2D = null; + private boolean isPrintScreen = false; // Indicate we are printing the playground + private double printerScaleFactor = 1.1; // Magnification factor for printer + + /** + * originX is the x-position of the cartesian coodinate system within the playground. + */ + public int originX; + + /** + * originY is the y-position of the cartesian coodinate system within the playground. + */ + public int originY; + + private static Color[] ColorArray = {Color.cyan, Color.red, Color.green, Color.blue, Color.yellow, + Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.black, Color.gray + }; + + /** + * Create a Playground with default background color. + * e.g. creates a new vector (which holds the + * Turtles), + */ + public Playground() { + turtles = new Vector(); + setDoubleBuffered(false); + setBackground(DEFAULT_BACKGROUND_COLOR); + initBuffers(new Dimension(100, 100)); + } + + /** + * Initializes the offscreen buffers and sets the size. + */ + protected void initBuffers(Dimension size) { + Color bkColor = getBackground(); + playgroundSize = size; + traceBuffer = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); + traceG2D = traceBuffer.createGraphics(); + traceG2D.setColor(bkColor); + traceG2D.fillRect(0, 0, size.width, size.height); + traceG2D.setBackground(bkColor); + + turtleBuffer = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); + turtleG2D = turtleBuffer.createGraphics(); + turtleG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + originX = size.width/2; + originY = size.height/2; + } + + /** Add a new Turtle to the Playground. + */ + public void add(Turtle turtle) { + turtles.add(turtle); + turtle.setPlayground(this); + int i = turtles.size(); + while (i > 10) { + i = i - 10; + } // end of while + turtle.init(ColorArray[i-1]); + toTop(turtle); + } + + public void setBounds(int x, int y, int width, int height) { + super.setBounds(x, y, width, height); + initBuffers(new Dimension(width, height)); + } + + /** Remove a Turtle from the Playground. + */ + public void remove(Turtle turtle) { + turtles.remove(turtle); + } + + /** Tell current number of Turtles in this Playground. + */ + public int countTurtles() { + return turtles.size(); + } + + /** Return the Turtle at index index. + */ + public Turtle getTurtle(int index) { + return turtles.elementAt(index); + } + + /** Move the given Turtle above all the others, then + paints all turtles. + @see #toTop + */ + public void paintTurtles(Turtle turtle) { + toTop(turtle); + paintTurtles(); + } + + /** Paint all turtles (calling paintComponent()) + */ + public void paintTurtles() { + isTurtleVisible = false; + Graphics2D g2D = getTurtleG2D(); + for (int i = 0; i < countTurtles(); i++) { + Turtle aTurtle = getTurtle(i); + if (!aTurtle.isHidden()) { + paintTurtle(aTurtle); + } + } + + // This is the main repaint call, when the turtle is + // moving (even when all turtles are hidden). + // Strange behaviour an slow Mac machines (pre J2SE 1.4 version): + // It happens that some turtle images are not completely redrawn. + // This is probably due to an improper handling of fast multiple repaint requests. + // Workaround: we wait a small amount of time (and give the thread away) + // (No visible slow down on new machines.) + + paintPlayground(); + if (printerG2D == null) { + //if (isRepainting) + //repaint(); + //paintPlayground(); + } + + if (isTurtleVisible) { + try { + Thread.currentThread().sleep(10); + } + catch (Exception e) {} + } + } + + + /** Paint the given Turtle. + * ( no repaint() ) + */ + public void paintTurtle(Turtle turtle) { + if (turtleBuffer == null){ + turtleBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); + turtleG2D = turtleBuffer.createGraphics(); + } + Graphics2D turtleGraphics = getTurtleG2D(); + turtle.getTurtleRenderer().paint(turtle._getX(), turtle._getY(), turtleGraphics); + isTurtleVisible = true; + } + + /** Put an image of the given Turtle in turtle buffer. + */ + protected void stampTurtle(Turtle turtle) { + turtle.clone(); + isTurtleVisible = true; + if (printerG2D == null) + repaint(); + } + + /** Draw a line from the point (x0, y0) to (x1, y1) + with the color of the given Pen. + */ + protected void lineTo(double x0, double y0, double x1, double y1, Pen pen) { + int ix0 = (int)Math.round(x0); + int iy0 = (int)Math.round(y0); + int ix1 = (int)Math.round(x1); + int iy1 = (int)Math.round(y1); + Color color = pen.getColor(); + + if (traceBuffer == null) { + traceBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); + traceG2D = traceBuffer.createGraphics(); + } + Graphics2D traceG2D = getTraceG2D(); + traceG2D.setColor(color); + traceG2D.setStroke(pen.getStroke()); + traceG2D.drawLine(ix0, iy0, ix1, iy1); + if (printerG2D != null) + printerG2D.drawLine(ix0, iy0, ix1, iy1); + } + + /** A class for convenience. */ + protected class Point extends java.awt.Point { + Point(int x, int y) { + super(x, y); + } + Point() { + super(); + } + Point(Point p) { + super(p.x, p.y); + } + + /** Get a new Point with coordinates (this.x+p.x, this.y+p.y). + */ + protected Point add(Point p) { + return new Point(this.x+p.x, this.y+p.y); + } + + /** Translate by the amounts dx = p.x, dy = p.y. */ + protected void translate(Point p) { + translate(p.x, p.y); + } + + public String toString() { + return "(" + x + "," + y + ")"; + } + } + + /** Fill a region. + The region is defined by the Turtles actual position and + is bounded by any other color than the give background color. + */ + public void fill(Turtle t, Color bgColor) { + final Point[] diff = { new Point(0,-1), new Point(-1,0), new Point(1,0), new Point(0,1)}; + final int N=0; + final int W=1; + final int E=2; + final int S=3; + + int bgcolor = bgColor.getRGB(); + int fillColor = t.getPen().getFillColor().getRGB(); + Vector list = new Vector(); + Point2D.Double p1 = toScreenCoords(t.getPos()); + int startX = (int)Math.round(p1.getX()); + int startY = (int)Math.round(p1.getY()); + Point p = new Point(startX, startY); + if (traceBuffer.getRGB(startX, startY) == bgcolor) { + traceBuffer.setRGB(startX, startY, fillColor); + list.addElement(new Point(startX, startY)); + int d = N; + int back; + while (list.size() > 0) { + while (d <= S) { // forward + Point tmp = p.add(diff[d]); + try { + if (traceBuffer.getRGB(tmp.x, tmp.y) == bgcolor) { + p.translate(diff[d]); + traceBuffer.setRGB(p.x, p.y, fillColor); + if (printerG2D != null) + { + printerG2D.setColor(t.getPen().getFillColor()); + // printerG2D.drawLine(p.x,p.y, p.x, p.y); + BasicStroke stroke = new BasicStroke(2); + printerG2D.setStroke(stroke); + Line2D line = new Line2D.Double(p.x, p.y, p.x, p.y); + printerG2D.draw(line); + } + list.addElement(new Integer(d)); + d=N; + } + else { + d++; + } + } + catch (ArrayIndexOutOfBoundsException e) { + d++; + } + } + Object obj = list.remove(list.size()-1); + try { + d=((Integer)obj).intValue(); // last element + back = S - d; + p.translate(diff[back]); + } + catch (ClassCastException e) { + // the first (zeroest) element in list is the start-point + // just do nothing with it + } + } + } + traceG2D.drawLine(0, 0, 0, 0); // Workaround because on Mac the trace buffer is not drawn without this + if (printerG2D == null) + repaint(); + } + + /** + * Clear the playground with given color. + */ + public void clear(Color color) { + traceG2D.setColor(color); + traceG2D.fillRect(0, 0, getWidth(), getHeight()); + turtleG2D.setColor(color); + turtleG2D.fillRect(0, 0, getWidth(), getHeight()); + isTurtleVisible = true; + if (printerG2D == null) + repaint(); + } + + /** + * Clear playground. + */ + public void clear() { + clear(getBackground()); + } + + /** Paint the Playground. + just a method for convenience. + */ + public void paintComponent() { + paintComponent(getGraphics()); + } + + /** Draw the trace and turtle buffers. + */ + public void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2D = (Graphics2D)g; + g2D.drawImage(traceBuffer, 0, 0, this); + if (isTurtleVisible) + g2D.drawImage(turtleBuffer, 0, 0, this); + } + + public void paintPlayground() { + Graphics g = getGraphics(); + if (g != null) { + super.paintComponent(g); + Graphics2D g2D = (Graphics2D)g; + g2D.drawImage(traceBuffer, 0, 0, this); + if (isTurtleVisible) + g2D.drawImage(turtleBuffer, 0, 0, this); + + } // end of if + } + + /** Remove all turtles from the turtle buffer. + */ + public void clearTurtles() { + for (int i = 0; i < countTurtles(); i++) { + Turtle turtle = getTurtle(i); + clearTurtle(turtle); + } + } + + /** Remove the given turtle from the turtle buffer. + Override this method if you have added a new behaviour (like + wrap or clip) to the turtle. + */ + public void clearTurtle(Turtle turtle) { + if(turtle != null){ + if (!turtle.isHidden()) { + if(turtle.isClip()){ + clearClipTurtle(turtle); + } + else if(turtle.isWrap()){ + clearWrapTurtle(turtle); + } + } + } + } + + /** This method is called when the given Turtle is in wrap mode. + + @see ch.aplu.turtle.Turtle#wrap + */ + protected void clearWrapTurtle(Turtle turtle){ + clearWrapTurtle(turtle, turtleBuffer); + } + + /** Here the actual clearing of a Turtle in wrap mode from the + given image is performed. + */ + protected void clearWrapTurtle(Turtle turtle, Image im){ + Rectangle bounds = getBounds(turtle); + int pWidth = getWidth(); + int pHeight = getHeight(); + int x = bounds.x; + int y = bounds.y; + while (x > pWidth){ + x -= pWidth; + } + while (x < 0){ + x += pWidth; + } + while (y > pHeight){ + y -= pHeight; + } + while (y < 0){ + y += pHeight; + } + x = x % pWidth; + y = y % pHeight; + toAlphaNull(im, new Rectangle(x, y, bounds.width, bounds.height)); // OK + boolean right = (x + bounds.width > getWidth()); + boolean bottom = (y + bounds.height > getHeight()); + if (right) { + toAlphaNull(im, new Rectangle(x-pWidth, y, bounds.width, bounds.height)); + } + if (bottom) { + toAlphaNull(im, new Rectangle(x, y-pHeight, bounds.width, bounds.height)); + } + if (right && bottom) { + toAlphaNull(im, new Rectangle(x-pWidth, y-pHeight, bounds.width, bounds.height)); + } + } + + /** Copy and translate a given Rectangle. + */ + private Rectangle copyAndTranslate(Rectangle rect, int dx, int dy) { + return new Rectangle(rect.x+dx, rect.y+dy, + rect.width, rect.height); + } + + /** This method is called when the given Turtle is in clip mode. + + @see ch.aplu.turtle.Turtle#clip + */ + protected void clearClipTurtle(Turtle turtle) { + clearClipTurtle(turtle, turtleBuffer); + } + + /** Here the actual clearing of a Turtle in clip mode from the + given image is performed. + */ + protected void clearClipTurtle(Turtle turtle, Image im) { + Rectangle bounds = getBounds(turtle); + toAlphaNull(im, bounds); + } + + /** Set the alpha channel of all pixels in the given image + in the given Rectangle to zero (i.e. totally transparent). + + This method is used byte the clearXXXTurtle methods. + */ + private void toAlphaNull(Image im, Rectangle rect) { + Rectangle rim = new Rectangle(0, 0, im.getWidth(this), im.getHeight(this)); + Rectangle r = new Rectangle(); + if (rect.intersects(rim)) { + r=rect.intersection(rim); + } + int size = r.width*r.height; + float[] alphachannel = new float[r.width*r.height]; + ((BufferedImage)im).getAlphaRaster().setPixels(r.x, r.y, r.width, r.height, alphachannel); + } + + /** Puts a Turtle above all others. + */ + public Turtle toTop(Turtle turtle) { + if (turtles.removeElement(turtle)) { + turtles.add(turtle); + } + return turtle; + } + /** Put a Turtle below all others. + */ + public Turtle toBottom(Turtle turtle) { + if (turtles.removeElement(turtle)) { + turtles.add(0,turtle); + } + return turtle; + } + + /** Calculate the screen coordinates of the given point. + */ + public Point2D.Double toScreenCoords(Point2D.Double p) { + return internalToScreenCoords(p.x, p.y); + } + + /** Calculate the screen coordinates of the given point coordinates. + */ + public Point2D.Double toScreenCoords(double x, double y) { + return internalToScreenCoords(x, y); + } + + protected Point2D.Double internalToScreenCoords(double x, double y) { + // reflect at x-axis, then translate to center of Playground + // pixel coordinates coorespond to turtle coordinates, only translation needed + double newX = originX + x; + double newY = originY - y; + return new Point2D.Double(newX, newY); + } + + /** Calculate the turtle coordinates of the given screen coordinates. + */ + public Point2D.Double toTurtleCoords(double x, double y) { + // pixel coordinates coorespond to turtle coordinates, only translation needed + double newX = x - originX; + double newY = originY - y; + return new Point2D.Double(newX, newY); + } + + /** Calculate the turtle coordinates of the given screen point. + */ + public Point2D.Double toTurtleCoords(Point2D.Double p) { + return toTurtleCoords(p.x, p.y); + } + + /** Calculate the screen angle. + I.e. the interpretation of angle. + @param radians The angle in radians. + */ + double toScreenAngle(double radians) { + double sa = radians; + if (sa < Math.PI/2){ + sa += 2*Math.PI; + } + sa -= Math.PI/2; + if (sa != 0) { + sa = Math.PI*2 - sa; + } + return sa; + } + + /** Calculate the bounds of the Turtles picture on the screen. + */ + protected Rectangle getBounds(Turtle turtle) { + Rectangle bounds = turtle.getBounds(); + Point2D.Double tmp = toScreenCoords(new Point2D.Double(bounds.getX(), bounds.getY())); + bounds.setRect(tmp.x-2, tmp.y-2, bounds.width+4, bounds.height+4); + return bounds; + } + + /** Return the graphics context of the turtle buffer. + */ + public Graphics2D getTurtleG2D() { + return turtleG2D; + } + + /** Return the image of the turtle buffer. + */ + public BufferedImage getTurtleBuffer() { + return turtleBuffer; + } + + /** Return the graphics context of the trace buffer. + */ + public Graphics2D getTraceG2D() { + return traceG2D; + } + + /** Return the graphics context of the printer. + */ + public Graphics2D getPrinterG2D() { + return printerG2D; + } + + /** Return the image of the trace buffer. + */ + public BufferedImage getTraceBuffer() { + return traceBuffer; + } + + /** Clean the traces. + All turtles stay how and where they are, only lines, text and stamps will be removed. + */ + void clean() { + Graphics2D g = getTraceG2D(); + g.setColor(getBackground()); + g.fillRect(0,0,getWidth(), getHeight()); + if (printerG2D == null) + repaint(); + } + + /** Draw the text at the current position of the Turtle t. + Drawing a text at some coordinates (x,y) we mean that the bottom left corner of + the text will be at these coordinates. + Font and colour are specified by the Turtle's Pen. + */ + public void label(String text, Turtle t) { + Point2D.Double sc = toScreenCoords(t.getPos()); + int x = (int)Math.round(sc.x); + int y = (int)Math.round(sc.y); + Graphics2D traceG2D = getTraceG2D(); + FontRenderContext frc = traceG2D.getFontRenderContext(); + Font f = t.getFont(); + TextLayout tl = new TextLayout(text, f, frc); + traceG2D.setColor(t.getPen().getColor()); + tl.draw(traceG2D, x, y); + if (printerG2D != null) + { + printerG2D.setColor(t.getPen().getColor()); + tl.draw(printerG2D, x, y); + } + + if (printerG2D == null) + repaint(); + } + + /** Set antialiasing on or off for the turtle trace buffer + * This may result in an better trace quality. + */ + public void setAntiAliasing(boolean on) { + if (on) + traceG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + else + traceG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_OFF); + } + + + /** + * Set the given TPrintable (implementing draw()), + * open a printer dialog and start printing with given scale. + * Return false, if printer dialog is aborted, + * otherwise return true.
+ * If tp == null, the current playground is printed. + * + */ + protected boolean print(TPrintable tp, double scale) { + if (tp == null) + isPrintScreen = true; + else + isPrintScreen = false; + printerScale = scale; + PrinterJob pj = PrinterJob.getPrinterJob(); + pj.setPrintable(this); + traceCanvas = tp; + if (pj.printDialog()) { + try { + pj.print(); + } + catch (PrinterException ex) { + System.out.println(ex); + } + return true; + } + else + return false; + } + + /** + * For internal use only. Implementation of Printable. + * (Callback method called by printing system.) + */ + public int print(Graphics g, PageFormat pf, int pageIndex) { + if (pageIndex != 0) + return NO_SUCH_PAGE; + Graphics2D g2D = (Graphics2D)g; + double printerWidth = pf.getImageableWidth(); + double printerHeight = pf.getImageableHeight(); + double printerSize = printerWidth > printerHeight ? printerWidth : + printerHeight; + double xZero = pf.getImageableX(); + double yZero = pf.getImageableY(); + + printerG2D = g2D; // Indicate also, we are printing now + + // Needed for fill operations: the trace canvas must be empty in order to + // perform the fill algoritm (searching for outline of figure) + if (!isPrintScreen) + clean(); + + g2D.scale(printerScaleFactor * printerScale, printerScaleFactor * printerScale); + g2D.translate(xZero/printerScale, yZero/printerScale); + + if (isPrintScreen) + { + print(g); + } + else // Printing the traceCanvas + { + // Hide all turtles + boolean[] turtleState = new boolean[countTurtles()]; + for (int i = 0; i < countTurtles(); i++) { + Turtle aTurtle = getTurtle(i); + turtleState[i] = aTurtle.isHidden(); + aTurtle.ht(); + } + traceCanvas.draw(); + + // Restore old context + for (int i = 0; i < countTurtles(); i++) { + Turtle aTurtle = getTurtle(i); + if (!turtleState[i]) + aTurtle.st(); + } + } + + printerG2D = null; + return PAGE_EXISTS; + } + + /** Return the color of the pixel at the current turtle position. + */ + public Color getPixelColor(Turtle t) { + Point2D.Double p1 = toScreenCoords(t.getPos()); + int x = (int)Math.round(p1.getX()); + int y = (int)Math.round(p1.getY()); + return new Color(traceBuffer.getRGB(x, y)); + } + + public void enableRepaint(boolean b) { + isRepainting = b; + } + + /** set the background color of the playground + */ + public void setBackground(Color color) { + super.setBackground(color); + if (traceG2D != null) { + clear(color); + } // end of if + } + + /** + * Sets the origin of the cartesian coordinate system within the playground + */ + public void setOrigin(int x, int y) { + for (int i = 0; i < countTurtles(); i++) { + Turtle turtle = getTurtle(i); + Point2D.Double p1 = toScreenCoords(turtle.getPos()); + double newX = p1.getX() - x; + double newY = y - p1.getY(); + turtle.internalSetPos(newX, newY); + } + originX = x; + originY = y; + } + + public int getOriginX() { + return originX; + } + + public int getOriginY() { + return originY; + } + +} + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/res/bong.wav b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/res/bong.wav new file mode 100644 index 0000000000000000000000000000000000000000..0d2fef0c16fc8ff100f498e161aed70ae66207eb GIT binary patch literal 9624 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 literal 0 HcmV?d00001 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/sharedconstants.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/sharedconstants.java new file mode 100644 index 0000000..1bd3955 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/sharedconstants.java @@ -0,0 +1,84 @@ +// SharedConstants.java + +// Copyright 2002 Regula Hoefer-Isenegger +// +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +/* History; +V1.36 - Sep 2004: First official release +V1.37 - Nov 2004: Unchanged, modifications in ch.aplu.util +V1.38 - Dec 2004: Unchanged, modifications in ch.aplu.util +V1.39 - Jan 2005: Unchanged, modifications in ch.aplu.util +V1.40 - Mar 2005: Add background color, TurtleKeyAdapter, TurtleArea +V1.41 - May 2005: User defined turtle shape, minor changes in doc and code style +V1.42 - Dec 2005: Unchanged, modifications in ch.aplu.util +V1.43 - Feb 2006: Bug removed: Turtle.turtleFrame was not initialized in all ctors of class Turtle +V1.44 - Mar 2007: Bug removed: stampTurtle did not work properly in wrap mode +V1.45 - Aug 2007: TurtleKeyAdapter: use wait/notify to reduce CPU time (from 100% to 2%) +V1.46 - Aug 2007: synchronize(playground) for forward and rotate animation, + new method bong() using StreamingPlayer +V1.47 - Sept 2007: Unchanged, modifications in ch.aplu.util +V1.48 - Sept 2007: Unchanged, modifications in ch.aplu.util +V1.49 - Oct 2007: Unchanged, modifications in ch.aplu.util +V1.50 - Oct 2007: Unchanged, modifications in ch.aplu.util +V1.51 - Nov 2007: Fixed: correct position of label, when wrapping is on + Fixed: getPos() returns now the wrapped coordinates + Added: _getPos() returns unwrapped coordinates +V1.52 - Nov 2007: Added bean classes in order to use turtles with a Gui builder +V1.53 - Nov 2007: Added TurtlePane visual information when used in Gui builder design mode +V1.54 - Nov 2007: Minor changes to documentation +V1.55 - Dec 2007: Added property enableFocus to GPane, default: setFocusable(false) +V1.56 - Mar 2008: Unchanged, modifications in ch.aplu.util +V1.57 - Mar 2008: Unchanged, modifications in ch.aplu.util +V1.58 - Mar 2008: Modification to fill() (fill(x, y)): + region is defined with pixel color at current position + as opposed to background color +V1.59 - Oct 2008: Added ctors TurtleFrame with window position (ulx, uly) + Added Turtle.getPixelColor() +V2.00 - Nov 2008: Unchanged, modifications in ch.aplu.util + J2SE V1.4 no longer supported +V2.01 - Jan 2009: Unchanged, modifications in ch.aplu.util +V2.02 - Feb 2009 Turtle constructors run in EDT now +V2.03 - Feb 2009 Unchanged, modifications in ch.aplu.util +V2.04 - Feb 2009 Unchanged, modifications in ch.aplu.util +V2.05 - Feb 2009 Unchanged, modifications in ch.aplu.util +V2.06 - Mar 2009 Unchanged, modifications in ch.aplu.util +V2.07 - Mar 2009 All except print methods synchronized, so Turtle package is + now thread-safe +V2.08 - Apr 2009 Unchanged, modifications in ch.aplu.util +V2.09 - Jun 2009 Unchanged, modifications in ch.aplu.util +V2.10 - Jun 2010 Version for the Java-Editor +*/ + +package ch.aplu.turtle; + +interface SharedConstants +{ + int DEBUG_LEVEL_OFF = 0; + int DEBUG_LEVEL_LOW = 1; + int DEBUG_LEVEL_MEDIUM = 2; + int DEBUG_LEVEL_HIGH = 3; + + int DEBUG = DEBUG_LEVEL_OFF; + + String ABOUT = + "Copyright © 2002-2009\nRegula Hoefer-Isenegger, Aegidius Pluess\n, Gerhard Roehner\n" + + "under GNU General Public License\n" + + "http://www.aplu.ch\n" + + "All rights reserved"; + String VERSION = "2.10 - June 2015"; +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/streamingplayer.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/streamingplayer.java new file mode 100644 index 0000000..8a3d5d5 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/streamingplayer.java @@ -0,0 +1,84 @@ +// StreamingPlayer.java + +package ch.aplu.turtle; + + +import javax.sound.sampled.*; +import java.io.*; + +class StreamingPlayer +{ + private class PlayerThread extends Thread + { + public void run() + { + byte buf[] = new byte[20000]; + try + { + int cnt; + while ((cnt = audioInputStream.read(buf, 0, buf.length)) != -1) + { + if (cnt > 0) + sourceDataLine.write(buf, 0, cnt); + } + sourceDataLine.drain(); + sourceDataLine.close(); + } + catch (IOException ex) + { + System.out.println(ex); + System.exit(1); + } + } + } + + private AudioFormat audioFormat; + private AudioInputStream audioInputStream; + private SourceDataLine sourceDataLine; + private PlayerThread playerThread; + + StreamingPlayer(InputStream is) + { + try + { + audioInputStream = + AudioSystem.getAudioInputStream(is); + audioFormat = audioInputStream.getFormat(); + } + catch (Exception ex) + {} + } + + void start(boolean doFinish) + throws LineUnavailableException + { + DataLine.Info dataLineInfo = + new DataLine.Info(SourceDataLine.class, audioFormat); + sourceDataLine = + (SourceDataLine)AudioSystem.getLine(dataLineInfo); + sourceDataLine.open(audioFormat); + sourceDataLine.start(); + playerThread = new PlayerThread(); + playerThread.start(); + if (doFinish) + waitToFinish(); + } + + boolean isPlaying() + { + if (playerThread == null) + return false; + return (playerThread.isAlive()); + } + + void waitToFinish() + { + if (playerThread == null) + return; + try + { + playerThread.join(); + } + catch (InterruptedException ex) {} + } +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/tprintable.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/tprintable.java new file mode 100644 index 0000000..767d22a --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/tprintable.java @@ -0,0 +1,43 @@ +// TPrintable.java + +// Copyright 2002 Regula Hoefer-Isenegger + +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +// Added by Aegidius Pluess + +package ch.aplu.turtle; + +/** + * Interface for printing on an attached printer. + * Normally an application uses a Turtle and implements this interface. + * draw() should contain all drawing operations into the + * Turtle's Playground. The printing occures, when Turtle's print() is + * called.

+ */ + + +public interface TPrintable +{ + /** + * This method must perform all drawing operations. + * Be aware that for some undocumented reason + * draw() is called twice. So be sure you initialize it correctly. + */ + + public void draw(); +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/turtle.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/turtle.java new file mode 100644 index 0000000..d30ff52 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/turtle.java @@ -0,0 +1,1585 @@ +// Turtle.java +// Modifications by Aegidius Pluess +// Adaption to the Java-Editor by Gerhard Röhner + +// Copyright 2002-2003 Regula Hoefer-Isenegger (Version 1.0) +// +// This file is part of The Java Turtle package (TJT) +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +/* +Screen coordinate system: 0..400 pixels in both directions corresponds to turtle +turtle coordinate system -200..200, so only translation is necessary (no scaling). + +This avoids rounding errors. +*/ + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.*; +import java.awt.image.*; +import java.awt.print.*; +import java.io.*; +import javax.sound.sampled.*; +import javax.swing.*; + +/** + The core class for turtles. + + For a simple example on how to use Turtle, cf. the + Java Turtle Package description. + @author Regula Hoefer-Isenegger + @version 0.1.1 +*/ +public class Turtle implements Cloneable +{ + private double angle; + private Point2D.Double position; + private Playground playground; + private int framesPerSecond; + private double speed; // Pixel/sec + private double angleSpeed; // Radian/sec + private TurtleRenderer turtleRenderer; + private int angleResolution; + private LineRenderer lineRenderer; + private static TurtleFactory turtleFactory; + private boolean penUp; + private boolean showTurtle; + private boolean initialVisibility = true; + private Pen pen; + private Color color; + private int edgeBehaviour; + + + /** Convert from screen coordinates to turtle coordinates + */ + public Point2D.Double toTurtlePos(Point p) { + return playground.toTurtleCoords((double)p.x, (double)p.y); + } + + /** Convert from screen coordinates to turtle coordinates + */ + public Point2D.Double toTurtlePos(int x, int y) { + return playground.toTurtleCoords((double)x, (double)y); + } + + /** Convert from screen coordinates to turtle coordinates + */ + public double toTurtleX(int x) { + return (playground.toTurtleCoords((double)x, 0)).x; + } + + /** Convert from screen coordinates to turtle coordinates + */ + public double toTurtleY(int y) { + return (playground.toTurtleCoords(0, (double)y)).y; + } + + /** Add the specified mouse listener to receive mouse events. + */ + public void addMouseListener(MouseListener l) { + playground.addMouseListener(l); + } + + /** Add the specified mouse motion listener to receive mouse motion events. + */ + public void addMouseMotionListener(MouseMotionListener l) { + playground.addMouseMotionListener(l); + } + + /** + * Emit a beep. Fails if no standard speaker available. Try to use bong() instead. + * @see #bong() + */ + public void beep() { + Toolkit.getDefaultToolkit().beep(); + } + + /** + * Emit a 'bong' via the sound card. Useful on computers without standard + * speaker. + * @see #beep() + */ + public void bong() { + InputStream is = getClass().getResourceAsStream("res/bong.wav"); + StreamingPlayer player = new StreamingPlayer(is); + try + { + player.start(false); + } + catch (LineUnavailableException ex) + { + System.out.println("Error in bong(). Sound card unavailable"); + } + } + + + /** Represent clip mode. + @see #WRAP + @see #clip() + */ + protected final static int CLIP = 0; + /** Represent wrap mode. + + @see #CLIP + @see #wrap() + */ + protected final static int WRAP = 1; + /** Represent the default edge behaviour (i.e. CLIP or WRAP). + + @see #CLIP + @see #WRAP + @see #clip() + @see #wrap() + */ + protected static int DEFAULT_EDGE_BEHAVIOUR = CLIP; + /** Represent the default speed (velocity). + + @see #setSpeed(double) + */ + protected static double DEFAULT_SPEED = 200; + + /** Represent the default angle resolution. + + It specifies how many different turtle pictures + are generated. + */ + protected static int DEFAULT_ANGLE_RESOLUTION = 72; + + /** Specify how many frames per second are used for + turtle animation. + */ + protected static int DEFAULT_FRAMES_PER_SECOND = 10; + + /** Specify the default turtle color. + + @see #setColor(java.awt.Color) + */ + protected static Color DEFAULT_TURTLE_COLOR = Color.cyan; + + /** Specify the default pen color. + + @see #setPenColor(java.awt.Color) + */ + protected static Color DEFAULT_PEN_COLOR = Color.blue; + + /** Create a new Turtle + */ + public Turtle() { + } + + /** init a new Turtle + */ + protected void init(Color color) { + angle = 0; + position = new Point2D.Double(0, 0); + framesPerSecond = DEFAULT_FRAMES_PER_SECOND; + if (initialVisibility) + setSpeed(DEFAULT_SPEED); + else + setSpeed(-1); + showTurtle = initialVisibility; + setAngleResolution(DEFAULT_ANGLE_RESOLUTION); + angleSpeed = getSpeed() * Math.PI * 2 / DEFAULT_SPEED; + pen = new Pen(DEFAULT_PEN_COLOR); + if (getTurtleFactory() == null){ + turtleFactory = createTurtleFactory(); + } + setColor(color); + lineRenderer = createLineRenderer(); + getTurtleRenderer().setAngle(getAngle()); + } + + /** Set the angle resolution for the Turtle's pictures. + + It specifies how many pictures are used. e.g. an angle resolution + of 90 means that you get one picture for every 4 degrees + (= 360/90 degrees). + */ + public void setAngleResolution(int newResolution) { + synchronized(playground) { + angleResolution = newResolution; + } + } + + /** Return the TurtleFactory of this turtle. + + @see ch.aplu.turtle.TurtleFactory + */ + public TurtleFactory getTurtleFactory() { + return this.turtleFactory; + } + + /** Create a LineRenderer which is responsible + for the correct drawing of the lines. + + @return the new LineRenderer + */ + + protected LineRenderer createLineRenderer() { + return new LineRenderer(this); + } + + /** Create a TurtleRenderer which is responsible + for the correct drawing of the Turtle. + + @return the new TurtleRenderer + */ + protected TurtleRenderer createTurtleRenderer() { + return new TurtleRenderer(this); + } + + /** Create a TurtleFactory which provides for + the Turtle pictures. + + @return the new TurtleFactory + */ + + protected TurtleFactory createTurtleFactory() { + return new TurtleFactory(); + } + /** Get the angle resolution. + + @see #setAngleResolution(int) + */ + + protected int getAngleResolution() { + return angleResolution; + } + + /** Get the TurtleRenderer. + */ + TurtleRenderer getTurtleRenderer() { + return turtleRenderer; + } + + /** Get the LineRenderer. + */ + private LineRenderer getLineRenderer() { + return lineRenderer; + } + + /** Get the Playground. + */ + public Playground getPlayground() { + return playground; + } + + /** Set the Playground to the specified + playground. + + The Turtle is removed from the old + Playground and set to the new one. + */ + public void setPlayground(Playground playground) { + Playground pg = getPlayground(); + if(pg != null){ + pg.clearTurtle(this); + pg.remove(this); + pg.paintTurtles(); + } + this.playground = playground; + playground.paintTurtles(this); + } + + /** Get the angle speed. + + (I.e. how fast the Turtle rotation + animation is performed.) + */ + private double getAngleSpeed() { + return angleSpeed; + } + + /** Set the angle speed. + + @see #getAngleSpeed() + */ + private void setAngleSpeed(double newAngleSpeed) { + this.angleSpeed = newAngleSpeed; + } + + /** Get the current angle (heading) of the + Turtle. + */ + private double getAngle() { + return angle; // in radians + } + + /** Get the current speed. + */ + public double getSpeed() { + return speed; + } + + /** Query the Turtle's x-position without wrapping. + * Coordinate are not bound to playground even when + * wrapping is on. + */ + public double _getX() { + synchronized (playground) { + return position.getX(); + } + } + + /** Query the Turtle's y-position without wrapping. + * Coordinate are not bound to playground even when + * wrapping is on. + */ + public double _getY() { + synchronized (playground) { + return position.getY(); + } + } + + /** Query the Turtle's x-position. + * If turtle is outside playground and wrapping is on + * return the coordinate in range -200..200. + * */ + + public double getX() { + synchronized (playground) { + double xPos = _getX(); + return xPos; + } + } + + /** Query the Turtle's x-position. + * If turtle is outside playground and wrapping is on + * return the coordinate in range -200..200. + */ + public double getY() { + synchronized (playground) { + double yPos = _getY(); + return yPos; + } + } + + + /** Query the Turtle's position without wrapping. + * Coordinate are not bound to playground even when + * wrapping is on. + */ + public Point2D.Double _getPos() { + return position; + } + + /** Query the Turtle's position */ + public Point2D.Double getPos() { + return new Point2D.Double(getX(), getY()); + } + + /** Put the Turtle to a new position with the given x-coordinates. + + */ + public void setX(double x) { + synchronized (playground) { + getPlayground().clearTurtle(this); + internalSetX(x); + getPlayground().paintTurtles(this); + } + } + + /** Put the Turtle to a new position with the given screen x-coordinates. + */ + public void setScreenX(int x) { + synchronized (playground) { + setX(toTurtleX(x)); + } + } + + /** Put the Turtle to a new position with the given y-coordinates. + */ + public void setY(double y) { + synchronized (playground) { + getPlayground().clearTurtle(this); + internalSetY(y); + getPlayground().paintTurtles(this); + } + } + + /** Put the Turtle to a new position with the given screen y-coordinates. + */ + public void setScreenY(int y) { + synchronized (playground) { + setY(toTurtleY(y)); + } + } + + /** Set the Turtle's x-Coordinate. + */ + protected void internalSetX(double x) { + synchronized (playground) { + position.setLocation(x, _getY()); + } + } + + /** Set the Turtle's y-Coordinate. + */ + protected void internalSetY(double y) { + position.setLocation(_getX(), y); + } + + /** Set the Turtle's Position. + */ + protected void internalSetPos(double x, double y) { + position.setLocation(x, y); + } + + /** Hide the Turtle. + + @see #st() + If there is only one turte, the speed is set to -1 + so there is no Turtle animation at all. + Hiding the Turtle speeds up the graphics enormously. + */ + public void ht() { + synchronized (playground) { + this.internalHide(); + if (getPlayground().countTurtles() == 1) + setSpeed(-1); + } + } + + /** Hide the Turtle. + + This is the same as ht(). + @see #st() + */ + public void hideTurtle() { + ht(); + } + + /** This is the method called by the public methods ht() and hideTurtle(). + + Here the actual hiding takes place. + @see #ht() + @see #hideTurtle() + */ + protected void internalHide() { + getPlayground().clearTurtle(this); + showTurtle = false; + if (getPlayground().getPrinterG2D() == null) + getPlayground().repaint(); + } + + /** Set the Turtle to show mode. + + That means that the Turtle will be drawn. + @see #ht() + */ + public void st() { + synchronized (playground) { + if (getPlayground().getPrinterG2D() == null) { + getPlayground().paintTurtle(this); + showTurtle = true; + getPlayground().repaint(); + } + } + } + + /** The same as st(). + + @see #st() + */ + public void showTurtle() { + st(); + } + + /** Tell whether the Turtle is hidden or not. + + @return true if the Turtle is hidden, + false otherwise. + */ + public boolean isHidden() { + return !showTurtle; + } + + private int getFramesPerSecond() { + return this.framesPerSecond; + } + + /** Only set the angle attribute. This method does not + invoke any re-painting. + */ + private void setAngle(double radians) { + this.angle = radians; + } + + /** This is the same as setH(double degrees). + + @see #setH(double) + */ + public void setHeading(double degrees) { + synchronized (playground) { + setAngle(Math.toRadians(degrees)); + getTurtleRenderer().setAngle(Math.toRadians(degrees)); + getPlayground().clearTurtle(this); + getPlayground().paintTurtles(this); + } + } + + /** Set the Turtle's heading. + + 0 means facing NORTH.
+ the angles are measured clockwise. + @see #setHeading(double) + */ + public void setH(double degrees) { + setHeading(degrees); + } + /** Query the Turtle's heading. + + @see #setH(double) + */ + public double heading() { + synchronized (playground) { + return Math.toDegrees(getAngle()); + } + } + /** Set the Turtle's heading to the new value. + + @return the old (previous) value. + @see #setH(double) + */ + public double heading(double degrees) { + synchronized (playground) { + double tmp = Math.toDegrees(getAngle()); + setHeading(degrees); + return tmp; + } + } + + /** Set the Turtle's speed. + + If you try to set the speed to 0, it will be set to 1 (very slow). + A negative speed means that moving the Turtle (fd, bk) + will not be animated.
+ The unit is pixels per second (up to certain bounds depending on the CPU etc.).
+ Remark: Dashed lines will only be painted as you expect it with speed set + to -1. + + @see #fd(double) + @see #bk(double) + */ + public void setSpeed(double speed) { + if (speed == 0) + this.speed = 1; + else + this.speed = speed; + } + + + /** This method is responsible for the rotation animation. + */ + private void internalRotate(double angle) { + if(isHidden()){ + synchronized(playground) + { + setAngle(getAngle()+angle); + if (getTurtleRenderer().imageChanged(getAngle())) { + getTurtleRenderer().setAngle(getAngle()); + } + } + return; + } + if (angle != 0) { + int iterations = getAngleIterations(angle); + + double sign = angle/Math.abs(angle); + double increment = sign*getAngleSpeed()/(double)getFramesPerSecond(); + double startAngle = getAngle(); + + for (int index = 0; index < iterations; index++) { + long timeStamp = System.currentTimeMillis(); + + synchronized(playground) { + getPlayground().clearTurtle(this); + + if (index < iterations-1) { + setAngle(getAngle()+increment); + } + else { + setAngle(startAngle+angle); + } + + if (getTurtleRenderer().imageChanged(getAngle())) { + getTurtleRenderer().setAngle(getAngle()); + getPlayground().paintTurtles(this); + } + } + + long newTimeStamp = System.currentTimeMillis(); + Double secs = new Double(1000./getFramesPerSecond()); + long requiredTime = secs.longValue()-newTimeStamp+timeStamp; + + if (requiredTime > 0) { + try { + Thread.sleep(requiredTime); + } + catch (InterruptedException e) { + } + } + } + } + getPlayground().paintTurtles(this); + } + + /** This method is responsible for the moving animation. + */ + private void internalMove(double length) { + if (getSpeed()>0){ + if (length != 0) { + int iterations = getPathIterations(length); + // an angle of 0 means: facing NORTH + double startX = _getX(); + double startY = _getY(); + getLineRenderer().init(startX, startY); + double dx = length * Math.sin(getAngle()); + double dy = length * Math.cos(getAngle()); + double incrementX = dx / iterations; + double incrementY = dy / iterations; + for (int index = 0; index < iterations; index++) { + long timeStamp = System.currentTimeMillis(); + int nX = (int)_getX(); + int nY = (int)_getY(); + synchronized(playground) { + playground.clearTurtle(this); + if (index < iterations-1) { + internalSetX(_getX()+incrementX); + internalSetY(_getY()+incrementY); + } + else { // last step: Calc the "exact" value + internalSetX(startX + dx); + internalSetY(startY + dy); + } + if (nX != (int)_getX() || nY != - (int)_getY() || index == iterations-1){ + if (!isPenUp()) { + getLineRenderer().lineTo(_getX(), _getY()); + } + getPlayground().paintTurtles(this); + } + } + Double frames = new Double(1000./getFramesPerSecond()); + long newTimeStamp = System.currentTimeMillis(); + long requiredTime = frames.longValue()-newTimeStamp+timeStamp; + if (requiredTime > 0) { + try { + Thread.sleep(requiredTime); + } + catch (InterruptedException e) { + } + } + } + } + } + else { // Speed < 0, i.e. no animation + double startX = _getX(); + double startY = _getY(); + getLineRenderer().init(startX, startY); + double dx = length * Math.sin(getAngle()); + double dy = length * Math.cos(getAngle()); + getPlayground().clearTurtle(this); + internalSetX(startX + dx); + internalSetY(startY + dy); + if (!isPenUp()) { + getLineRenderer().lineTo(_getX(), _getY()); + } + getPlayground().paintTurtles(this); + } + } + + /** Turn the Turtle the given angle (in degrees) to the left + + @see #rt(double) + */ + public void lt(double degrees) { + left(degrees); + } + + /** Same as lt(double degrees) + + @see #lt(double) + */ + public void left(double degrees) { + internalRotate(Math.toRadians(-degrees)); + } + + /** Turn the Turtle the given angle (in degrees) to the right. + + @see #rt(double) + */ + public void rt(double degrees) { + right(degrees); + } + + /** Same as rt(double degrees). + + @see #rt(double) + */ + public void right(double degrees) { + internalRotate(Math.toRadians(degrees)); + } + + /** Same as fd(double distance) + + @see #fd(double) + */ + public void forward(double distance) { + internalMove(distance); + } + + /** Move the Turtle forwards. + + Negative values for distance are + allowed. In that case, the Turtle + will move backwards. + + @see #bk(double) + */ + public void fd(double distance) { + forward(distance); + } + + /** Same as bk(double distance). + + @see #bk(double) + */ + public void back(double distance) { + forward(-distance); + } + + /** Move the Turtle backwards. + + Negative values for distance are + allowed. In that case, the Turtle + will move forwards. + + @see #fd(double) + */ + public void bk(double distance) { + back(distance); + } + + /** Query the distance from the current location + to the given one. + */ + public double distance(double x, double y) { + synchronized (playground) { + return this.getPos().distance(x,y); + } + } + + /** Query the distance from the current location + to the given one. + * Actually a polygon with 36 sides is drawn. + */ + public double distance(Point2D.Double p) { + synchronized (playground) { + return this.getPos().distance(p); + } + } + + /** Draw a circle to the left from the current position with + * turtle's heading tangent direction and given radius. + * Actually a polygon with 36 sides is drawn. + */ + public void leftCircle(double radius) { + circle(radius, true); + } + + /** Draw a circle to the right from the current position with + * turtle's heading tangent direction and given radius. + * Actually a polygon with 36 sides is drawn. + */ + public void rightCircle(double radius) { + circle(radius, false); + } + + private void circle(double radius, boolean left) { + double nbSteps = 36; // 36 side polygon + double angle = 2 * Math.PI / nbSteps; + double step = 2 * radius * Math.sin(angle/2); + for (int i = 0; i < 36; i++) { + if (left) + if (i == 0) + lt(180.0 / nbSteps); + else + lt(360.0 / nbSteps); + else + if (i == 0) + rt(180.0 / nbSteps); + else + rt(360.0 / nbSteps); + fd(step); + } + } + + /** Calculate the number of iterations when animating left or right (rotation). + */ + private int getAngleIterations(double dAngle) { + if(getAngleSpeed()<0){ + return 1; + } + if(getAngleSpeed()==0){ + setAngleSpeed(1); + } + double dAbsAngle = Math.abs(dAngle); + Double dValue = new Double(Math.ceil(dAbsAngle/getAngleSpeed()*getFramesPerSecond())); + return dValue.intValue(); + } + + /** Calculate the number of iterations when animating forwards or backwards. + */ + private int getPathIterations(double length) { + if(speed < 0) + return 1; + + if (speed == 0) + setSpeed(1); + + double dAbsLength = Math.abs(length); + Double dValue = new Double(Math.ceil(dAbsLength/getSpeed()*getFramesPerSecond())); + return dValue.intValue(); + } + + /** Lift the Turtle's pen up so it + won't draw a line anymore. + + This is the same as pu(). + + @see #pu() + @see #penDown() + @see #pd() + */ + public void penUp() { + synchronized (playground) { + this.penUp = true; + } + } + + /** Lift the Turtle's pen up so it + won't draw a line anymore. + + This is the same as penUp(). + + @see #penUp() + @see #penDown() + @see #pd() + */ + public void pu() { + this.penUp(); + } + + /** Lower the Turtle's Pen down so it + will draw a line when moving. + + This is the same as pd(). + + @see #pd() + @see #penUp() + @see #pu() + */ + public void penDown() { + synchronized (playground) { + this.penUp = false; + } + } + + /** Lowers the Turtle's pen down so it + will draw a line when moving. + + This is the same as penDown(). + + @see #penDown() + @see #penUp() + @see #pu() + */ + public void pd() { + this.penDown(); + } + + /** Query the Pen's state (up or down). + + @return true if the Pen is + up, false otherwise. + @see #pu() + @see #pd() + */ + public boolean isPenUp() { + return this.penUp; + } + + /** Return the bounds of this Turtle. This is required + by the methods that (return-)paint the Turtles. + */ + Rectangle getBounds() { + Rectangle rect = new Rectangle(); + + Image img = getTurtleRenderer().currentImage(); + int nWidth = img.getWidth(getTurtleRenderer()); + int nHeight = img.getHeight(getTurtleRenderer()); + double x = (_getX()<0)?Math.floor(_getX()):Math.ceil(_getX()); + double y = (_getY()<0)?Math.floor(_getY()):Math.ceil(_getY()); + rect.setBounds((int)x-nWidth/2, (int)y + nHeight/2, nWidth, nHeight); + return rect; + } + + /** Get the Turtle's Pen. + + You need it if you want to change end caps etc. + @see Pen + */ + public Pen getPen() { + return pen; + } + /** Set the line thickness. + + This works only neatly in clip mode (yet). + @see #clip() + @see #wrap() + */ + public void setLineWidth(double lineWidth){ + synchronized (playground) { + setLineWidth((float)lineWidth); + } + } + + /** Set the line thickness. + + This works only neatly in clip mode (yet). + @see #clip() + @see #wrap() + */ + public void setLineWidth(float lineWidth) { + synchronized (playground) { + getPen().setLineWidth(lineWidth); + } + } + + /** Set the Turtle's color to the specified one. + + */ + public void setColor(Color color) { + synchronized (playground) { + internalSetColor(color); + getPlayground().paintTurtles(); + } + } + + private void internalSetColor(Color color) { + this.color = color; + if (getTurtleRenderer()==null) { + turtleRenderer = createTurtleRenderer(); + getTurtleRenderer().init(getTurtleFactory(), getAngleResolution()); + } + else{ + getTurtleRenderer().init(new TurtleFactory(), + this.angleResolution); + } + } + + /** Set the color to the specified one. + + @see #fill() + */ + public void setFillColor(Color color) { + synchronized (playground) { + getPen().setFillColor(color); + } + } + + /** Query the Turtle's current color. + */ + public Color getColor(){ + return color; + } + + /**Set the Turtle's pen color. + + */ + public void setPenColor(Color color) { + synchronized (playground) { + getPen().setColor(color); + } + } + + /** Move the Turtle back "home", i.e. set its position + to the origin, facing NORTH. + + Color, PenColor etc. remain the same. + */ + public void home() { + // first : clean the Turtle! + synchronized (playground) { + getPlayground().clearTurtle(this); + position = new Point2D.Double(0,0); + setHeading(0); + } + } + + /** The Turtle's Pen is + changed to an eraser (which is in fact a pen with + background color). + + This is the same as pe() + @see #pe() + */ + public void penErase() { + synchronized (playground) { + this.internalPenErase(); + } + } + + /** The Turtle's Pen is + changed to an eraser (which is in fact a pen with + background color). + + This is the same as penErase() + @see #penErase() + */ + public void pe() { + penErase(); + } + + protected void internalPenErase(){ + this.setPenColor(getPlayground().getBackground()); + } + + /** Put the Turtle to a new position with specified + x- and y-coordinates. + */ + public void setPos(double x, double y) { + synchronized (playground) { + getPlayground().clearTurtle(this); + internalSetPos(x, y); + getPlayground().paintTurtles(); + } + } + + /** Put the Turtle to a new position. + */ + public void setPos(Point2D.Double p) { + setPos(p.x, p.y); + } + + /** Put the Turtle to a new screen position. + + */ + public void setScreenPos(Point p) { + setPos(toTurtlePos(p)); + } + + + /** Put a Turtle image at the current position. + + */ + public void stampTurtle() { + synchronized (playground) { + this.getPlayground().stampTurtle(this); + } + } + + /** Calculate the direction to a given point. + + @return the direction from the current turtle position + towards the given point, measured in degrees and clockwise + from the vertical upwards position. + */ + public double towards(double x, double y) { + synchronized (playground) { + double dx = x - getX(); + double dy = y - getY(); + double result = Math.toDegrees(Math.atan2(dx, dy)); + return (result < 0) ? result+360 : result; + } + } + + /** Calculate the direction to a given point. + + @return the direction from the current turtle position + towards the given point, measured in degrees and clockwise + from the vertical upwards position. + */ + public double towards(Point2D.Double p) { + return towards(p.getX(), p.getY()); + } + + /** Put the Turtle to the top (i.e. above any other + turtle). + + Just invokes the toTop-Method in Playground. + @see Playground#toTop + @see #internalToBottom + */ + void internalToTop() { + this.getPlayground().toTop(this); + } + /** Put the Turtle to the bottom (i.e. under any other + turtle). + + Just invokes the toBottom-Method in Playground. + @see Playground#toBottom + @see #internalToTop + */ + void internalToBottom() { + this.getPlayground().toBottom(this); + } + + /** Put this turtle to the bottom. + + So any other turtle in the same Playground will be drawn over it. + */ + public void toBottom() { + // this.getPlayground().toBottom(this); + synchronized (playground) { + internalToBottom(); + getPlayground().paintTurtles(); + } + } + + /** Put this turtle to the top. + + So it will be drawn over any other turtle in the same Playground. + */ + public void toTop() { + // this.getPlayground().toTop(this); + synchronized (playground) { + this.getPlayground().paintTurtles(this); + } + } + + /** Set the pen width. + */ + public void penWidth(int newWidth) { + synchronized (playground) { + penWidth((float)newWidth); + } + } + + /** Internal Method for setting the penWidth. + */ + private void penWidth(float newWidth) { + setLineWidth(newWidth); + } + + /** Query the pen width. + */ + public int penWidth(){ + return (int)this.getPen().getLineWidth(); + } + + /** Returns the current edge behaviour. + + @see #CLIP + @see #WRAP + */ + protected int getEdgeBehaviour() { + return edgeBehaviour; + } + + /** Sets the edge behaviour to the specified value; + + @see #CLIP + @see #WRAP + */ + protected void setEdgeBehaviour(int edgeBehaviour) { + synchronized (playground) { + this.edgeBehaviour = edgeBehaviour; + } + } + + /** Set the Turtle to clip-mode. + @see #wrap() + @see #clip() + */ + public void clip() { + synchronized (playground) { + setEdgeBehaviour(CLIP); + } + } + + /** Cause the Turtle to wrap around the playground borders. + + e.g when as the Turtle leaves the Window on one side, + it reappears on the opposite side. + + @see #clip() + */ + public void wrap() { + synchronized (playground) { + setEdgeBehaviour(WRAP); + } + } + + /** Tell whether the Turtle is in clip mode. + + @return true if in clip mode, false otherwise. + @see #clip() + @see #wrap() + */ + public boolean isClip() { + return (getEdgeBehaviour() == CLIP); + } + /** Tell wheter the Turtle is in wrap mode. + + @return true if in wrap mode, false otherwise. + @see #wrap() + @see #clip() + */ + public boolean isWrap() { + return (getEdgeBehaviour() == WRAP); + } + + /** Fill the region the Turtle is in.
+ + A region is bounded by lines + of any color different to the pixel color at the current turtle position + and by the border of the window.
+ (The pen of the Turtle must be down.) + */ + public void fill() { + synchronized (playground) { + getPlayground().fill(this, getPlayground().getPixelColor(this)); + } + } + + /** Fill the region as if the Turtle where at coordinates x and y.
+ A region is bounded by lines + of any color different to the pixel color at the given position and by the border of + the window.
+ (The pen of the Turtle must be down.) + */ + public void fill(double x, double y) { + synchronized (playground) { + double oldX = getX(); + double oldY = getY(); + boolean hidden = isHidden(); + ht(); + setPos(x,y); + getPlayground().fill(this, getPlayground().getPixelColor(this)); + setPos(oldX, oldY); + if(!hidden){ + st(); + } + } + } + + /** Erase all traces and text painted by the turtles, but let all + * turtles where they are. + + */ + public void clean() { + synchronized (playground) { + getPlayground().clean(); + } + } + + /** Paint the specified text at the current turtle position. + + */ + public void label(String text) { + synchronized (playground) { + if (text != null && text.length() > 0) + getPlayground().label(text, this); + } + } + + /** Set the current font as specified. + + @see java.awt.Font + */ + public void setFont(Font font) { + synchronized (playground) { + getPen().setFont(font); + } + } + + /** Change the current font to the specified one. If you want to know what fonts are available on your system, + call #getAvailableFontFamilies() . + + @see #getAvailableFontFamilies + @see java.awt.Font more information about fontName, style and size. + */ + public void setFont(String fontName, int style, int size) { + synchronized (playground) { + getPen().setFont(new Font(fontName, style, size)); + } + } + + /** Set the font size. + + @see #setFontStyle changing the font style + @see #setFont changing the whole font. + */ + public void setFontSize(int size) { + synchronized (playground) { + getPen().setFontSize(size); + } + } + + /** Set the font style. + + This is either java.awt.Font.PLAIN, java.awt.Font.BOLD, java.awt.Font.ITALIC or java.awt.Font.BOLD+java.awt.Font.ITALIC + @see #setFontSize changing the font size + @see #setFont changing the whole font. + */ + public void setFontStyle(int style) { + synchronized (playground) { + getPen().setFontStyle(style); + } + } + + /** Provide information about all font families (e.g. roman) currently available on your system. + Each font name is a string packed into a array of strings. + (This might be useful when you want to change the font.) + @see #setFont(java.awt.Font) + @see #setFont(java.lang.String, int, int) + */ + public static String[] getAvailableFontFamilies() { + return Pen.getAvailableFontFamilies(); + } + + /** Return the current font. + + @see #setFontSize changing the font size + @see #setFontStyle changing the font style + @see #setFont changing the whole font. + */ + public Font getFont() { + return getPen().getFont(); + } + + /** Creates a clone of the Turtle in it's Playground. + Color, position and heading are the same. + (It's visible and pen is down.) + Return the cloned object reference as a Object type, because + it overrides Object.clone(). + (You may cast it to a Turtle.) + */ + public Object clone() + { + synchronized (playground) { + Turtle t = new Turtle(); + t.setColor(getColor()); + t.setPos(getX(), getY()); + t.heading(heading()); + t.showTurtle(); + return t; + } + } + + /** Set antialiasing on or off for the turtle trace buffer + * This may result in an better image quality, especially + * for filling operations (platform dependant). + */ + public void antiAliasing(boolean on) { + synchronized (playground) { + getPlayground().setAntiAliasing(on); + } + } + + + /** + * Print the graphics context to an attached printer with + * the given magnification scale factor. + * scale = 1 will print on standard A4 format paper.
+ * + * The given tp must implement the GPrintable interface, + * e.g. the single method void draw(), where all the + * drawing into the GPanel must occur. + * + * Be aware the turtle(s) state (position, direction, etc.) + * must be reinitialized, because draw() is called several + * times by the printing system. + * + * A standard printer dialog is shown before printing is + * started. Only turte traces are printed. + *
+ * Example:
+ * + import ch.aplu.turtle.*;
+
+ public class PrintTest implements TPrintable
+ {
+ private Turtle t = new Turtle();
+
+ public PrintTest()
+ {
+ draw(); // Draw on screen
+ t.print(this); // Draw on printer
+ }
+
+ public void draw()
+ {
+ t.home(); // Needed for initialization
+ for (int i = 0; i < 5; i++)
+ t.fd(20).rt(90).fd(20).lt(90);
+ }
+
+ public static void main(String[] args)
+ {
+ new PrintTest();
+ }
+ }
+
+ */ + public boolean print(TPrintable tp, double scale) + { + return getPlayground().print(tp, scale); + } + + /** + * Same as print(tp, scale) with scale = 1. + */ + public boolean print(TPrintable tp) + { + return print(tp, 1); + } + + /** + * Print the Turtle's current playground with given scale. + */ + public boolean printScreen(double scale) + { + return print(null, scale); + } + + /** + * Same as printScreen(scale) with scale = 1. + */ + public boolean printScreen() + { + return printScreen(1); + } + + /** + * Clear the Turtle's playground. All turtle images and traces are erased, + * but the turtles remain (invisible) at their positions. + */ + public void clear() + { + synchronized (playground) { + getPlayground().clear(); + } + } + + /** + * Delay execution for the given amount of time ( in ms ). + */ + public static void sleep(int time) + { + try + { + Thread.currentThread().sleep(time); + } + catch (Exception e) {} + } + + /** + * Return version information + */ + public String version() + { + return SharedConstants.VERSION; + } + + /** + * Enable/disable automatic repainting. + * If disabled, call repaint() to perform repainting. + * Disabling automatic repainting and hiding the + * Turtle speeds up the graphics enormously. + */ + public void enableRepaint(boolean b) + { + getPlayground().enableRepaint(b); + } + + /** + * Perform manual repainting when automatic repainting is + * disabled. + */ + public void repaint() { + getPlayground().repaint(); + } + + /** + * Return the color of the pixel at the current turtle position. + */ + public Color getPixelColor() { + synchronized (playground) { + return getPlayground().getPixelColor(this); + } + } + + protected Graphics getGraphics() { + return playground.getGraphics(); + } + + /** + * Transforms the gui-position to mouse-coordinates. + */ + public void setBounds(int x, int y, int b, int h) { + int ox = playground.getOriginX(); + int oy = playground.getOriginY(); + x = -ox + x + 10; + y = oy - y - 13; + setPos(x, y); + } + + /** + * Shows or hides the turtle. + */ + public void setVisible(boolean show) { + if (show) { + showTurtle(); + } else { + hideTurtle(); + } // end of if-else + } + + /** + * Sets clipping-mode on/off. + */ + public void setClip(boolean clip) { + if (clip) { + clip(); + } else { + wrap(); + } // end of if-else + } + + /** + * Sets pen-position up/down. + */ + public void setPenUp(boolean penup) { + if (penup) { + penUp(); + } else { + penDown(); + } // end of if-else + } + + /** + * Sets angle of the turtle. + */ + public void setAngle(int angle) { + setHeading(angle); + } +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/turtlefactory.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/turtlefactory.java new file mode 100644 index 0000000..e9d700e --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/turtlefactory.java @@ -0,0 +1,66 @@ +// TurtleFactory.java + +// Copyright 2002 Regula Hoefer-Isenegger +// +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import java.awt.image.*; +import java.awt.*; + +class TurtleFactory +{ + /** Generates the shape of the turtle with color, + * angle angle, width w + * and height h. + */ + protected Image turtleImage(Color color, double angle, int w, int h) + { + BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR); + Graphics2D g = (Graphics2D)bi.getGraphics(); + // Origin in center + g.translate(w/2, h/2); + // angle = 0 is direction east (as usual in mathematics) + g.rotate(Math.PI/2 - angle); + g.setColor(color); + + // Body + g.fillOval((int)( -0.35 * w), (int)( -0.35 * h), + (int)(0.7 * w), (int)(0.7 * h)); + + // Head + g.fillOval((int)( -0.1 * w), (int)( -0.5 * h), + (int)(0.2 * w), (int)(0.2 * h)); + + // Tail + int[] xcoords = + {(int)( -0.05 * w), 0, (int)(0.05 * w)}; + int[] ycoords = + {(int)(0.35 * h), (int)(0.45 * h), (int)(0.35 * h)}; + g.fillPolygon(xcoords, ycoords, 3); + + // Feet + for (int i = 0; i < 4; i++) + { + g.rotate(Math.PI / 2); + g.fillOval((int)( -0.35 * w), (int)( -0.35 * h), + (int)(0.125 * w), (int)(0.125 * h)); + } + return (Image)bi; + } +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/turtlerenderer.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/turtlerenderer.java new file mode 100644 index 0000000..9489e78 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/ch/aplu/turtle/turtlerenderer.java @@ -0,0 +1,312 @@ +// TurtleRenderer.java + +// Copyright 2002 Regula Hoefer-Isenegger +// Some modifications by Aegidius Pluess + +// This file is part of The Java Turtle (TJT) package +// +// TJT 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. +// +// TJT 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 The Java Turtle Package; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package ch.aplu.turtle; + +import ch.aplu.turtle.*; +import java.awt.image.*; +import java.awt.*; +import javax.swing.*; +import java.awt.geom.*; +import java.util.*; + + +/** This class is responsible for creating and choosing the correct Turtle picture. + @author Regula Hoefer-Isenegger + @version 0.1 +*/ +public class TurtleRenderer implements ImageObserver { + /** Holds the current image */ + private Image currentImage; + /** Holds all images */ + private Vector images; + /** Tells how many pictures are needed*/ + private int resolution; + /** A reference to the Turtle */ + private Turtle turtle; + /** Holds the current Angle */ + private double currentAngle; + + private final int turtleSize = 29; + + /***/ + public TurtleRenderer(Turtle turtle) { + this.currentImage = null; + this.images = new Vector(); + this.turtle = turtle; + currentAngle = 0; + } + + /** As an image stays unchanged, there's no need to ever update it. So this method returns always false. + + For further information cf. java.awt.image.ImageObserver. + @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) + */ + public boolean imageUpdate(Image img, int infoflags, + int x, int y, int width, int height) { + return false; + } + + /** Return the current image. + */ + public Image currentImage() { + return this.currentImage; + } + + /** Tell whether the image has changed. + */ + public boolean imageChanged(double angle) { + return (this.currentImage != getImage(angle)); + } + + /** Set the current image to the specified one. */ + private void setCurrentImage(Image image) { + currentImage = image; + } + + /** Choose the image for the angle angle. + */ + private Image getImage(double angle) { + while (angle < 0) { + angle += 2*Math.PI; + } + while (angle >= 2*Math.PI) { + angle -= 2*Math.PI; + } + double res = 2*Math.PI/(double)this.resolution; + int index = (int)(angle/res); + return image(index); + } + + /** Set the current image to the one corresponding to the angle angle. + */ + public void setAngle(double angle) { + currentAngle = angle; + setCurrentImage(getImage(angle)); + } + + /** @return the current angle. */ + protected double getAngle(){ + return currentAngle; + } + + /** Create the images. There are resolution images (i.e. two subsequent + images contain an angle of 2π/ or 360/resolution degrees). + */ + public void init(TurtleFactory factory, int resolution) { + this.resolution = resolution; + Integer res = new Integer(resolution); + double incRes = Math.PI*2/res.doubleValue(); + double angle = 0; + images = new Vector(); + for (int i = 0; i < resolution; i++) { + images.add(factory.turtleImage(turtle.getColor(), + turtle.getPlayground().toScreenAngle(angle), + turtleSize, turtleSize)); + angle += incRes; + } + setCurrentImage(getImage(currentAngle)); + } + + /** Tell how many images this TurtleRenderer holds */ + private int countImages() { + return this.images.size(); + } + + /** Get the image at index */ + private Image image(int index) { + return (Image)this.images.elementAt(index); + } + + /** This method is responsible for painting the turtle onto the + playground at (x, y). + */ + public final void paint(double x, double y) { + internalPaint(x, y, turtle.getPlayground().getGraphics()); + } + + /** This method is responsible for painting the turtle onto the + playground at p. + */ + public final void paint(Point2D.Double p) { + internalPaint(p.x, p.y, turtle.getPlayground().getGraphics()); + } + + /** This method is responsible for painting the Turtle + at (x, y).
+ The Graphics argument tells where to paint. + */ + public final void paint(double x, double y, Graphics g) { + internalPaint(x, y, g); + } + + /** This method is responsible for painting the Turtle + at p.
+ The Graphics argument tells where to paint. + */ + public void paint(Point2D.Double p, Graphics g){ + internalPaint(p.x, p.y, g); + } + + /** Call clipPaint and wrapPaint(). + + You should override this method only, if you add a new (edge) + behaviour to the turtle. I recommend to you then to first call this + method from the overriding one. +
+ If you want to change anything about the real painting, override + clipPaint or wrapPaint. + + @see #clipPaint(int, int, Graphics2D) + @see #wrapPaint(int, int, Graphics2D) + */ + protected void internalPaint(double x, double y, Graphics g) { + if(turtle.isClip()){ + Point2D.Double p = + calcTopLeftCorner(turtle.getPlayground().toScreenCoords(x, y)); + clipPaint((int)p.x, (int)p.y, (Graphics2D)g); + } + else if(turtle.isWrap()){ + Point2D.Double p = + calcTopLeftCorner(turtle.getPlayground().toScreenCoords(x, y)); + wrapPaint((int)p.x, (int)p.y, (Graphics2D)g); + } + } + + /** Define how to paint in clip mode and do it */ + protected void clipPaint(int x, int y, Graphics2D g2D) { + g2D.drawImage(currentImage, x, y, this); + } + + /** Define how to paint in wrap mode and do it */ + protected void wrapPaint(int x, int y, Graphics2D g2D) { + int pWidth = turtle.getPlayground().getWidth(); + int pHeight = turtle.getPlayground().getHeight(); + int paintX = x; + while (paintX > pWidth) { + paintX -= pWidth; + } + while (paintX < 0) { + paintX += pWidth; + } + int paintY = y; + while (paintY > pHeight) { + paintY -= pHeight; + } + while (paintY < 0) { + paintY += pHeight; + } + g2D.drawImage(currentImage, paintX, paintY, this); + int nWidth = currentImage.getWidth(this); + int nHeight = currentImage.getHeight(this); + boolean right = (paintX+nWidth > pWidth); + boolean bottom = (paintY+nHeight > pHeight); + if(right) { + g2D.drawImage(currentImage, + paintX-pWidth, + paintY, + this); + } + if(bottom) { + g2D.drawImage(currentImage, + paintX, + paintY-pHeight, + this); + } + if(right && bottom) { + g2D.drawImage(currentImage, + paintX-pWidth, + paintY-pHeight, + this); + } + } + + /** Compute the x-coordinate of the top left corner of the Turtle image + (it depends on the specified x-coordinate and the image width). + */ + protected int calcTopLeftCornerX(double x) { + int intX = (int)x; + int nWidth; + if(currentImage == null) { + setCurrentImage(new TurtleFactory(). + turtleImage(turtle.getColor(), getAngle(), turtleSize, turtleSize)); + } + nWidth = this.currentImage.getWidth(this); + // the center of the turtle lies on the turtle's location: + intX -= nWidth/2; + return intX; // top left corner of the Turtle's image + } + + /** Compute the y-coordinate of the top left corner of the Turtle image + (it depends on the specified y-coordinate and the image height). + */ + protected int calcTopLeftCornerY(double y) { + int intY = (int)y; + if(currentImage == null) { + setCurrentImage(new TurtleFactory(). + turtleImage(turtle.getColor(), getAngle(), turtleSize, turtleSize)); + } + int nHeight = currentImage.getHeight(this); + // the center of the turtle lies on the turtle's location: + intY -= nHeight/2; + + return intY; // top left corner of the Turtle's image + } + /** Compute the top left corner of the Turtle image + (dependent on the specified x- and y-coordinate and the image + width and height. + */ + protected Point2D.Double calcTopLeftCorner(double x, double y) { + if(currentImage == null) { + setCurrentImage(new TurtleFactory(). + turtleImage(turtle.getColor(), getAngle(), turtleSize, turtleSize)); + } + int w = currentImage.getWidth(this); + int h = currentImage.getHeight(this); + return new Point2D.Double(x-w/2, y-h/2); + } + + /** Compute the top left corner of the Turtle image + (dependent on the specified point p and the image + width and height. + */ + protected Point2D.Double calcTopLeftCorner(Point2D.Double p) { + return calcTopLeftCorner(p.x, p.y); + } +} + + + + + + + + + + + + + + + + + + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/eval.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/eval.java new file mode 100644 index 0000000..97c8ff0 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/eval.java @@ -0,0 +1,50 @@ +public class Eval { + + public static Wrap getOb(Object o) { + return new Wrap(o); + } + + protected static Object getOb(final String s) { + return new Object() {public String result = s;}; + } + + protected static Object getOb(final boolean b) { + return new Object() {public boolean result = b;}; + } + + protected static Object getOb(final byte b) { + return new Object() {public byte result = b;}; + } + + protected static Object getOb(final char c) { + return new Object() {public char result = c;}; + } + + protected static Object getOb(final double d) { + return new Object() {public double result = d;}; + } + + protected static Object getOb(final float f) { + return new Object() {public float result = f;}; + } + + protected static Object getOb(final int i) { + return new Object() {public int result = i;}; + } + + protected static Object getOb(final long l) { + return new Object() {public long result = l;}; + } + protected static Object getOb(final short s) { + return new Object() {public short result = s;}; + } +} + + +class Wrap { + public Object result; + + Wrap(Object result) { + this.result = result; + } +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/inout.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/inout.java new file mode 100644 index 0000000..d702d54 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/inout.java @@ -0,0 +1,98 @@ +import java.io.*; + +/** +Support class for console input and output of numeric values.

+ +Example for input:
+ int age = InOut.readInt("Your age: ");

+ +Example for output:
+ System.out.println("price: " + InOut.format2(prize) + "Euro");
+ System.out.println("percent: " + InOut.formatN(percent, 1) + " %"); +*/ + + +public class InOut { + + /** Formats a double-value with 2 decimal digits. */ + public static String format2(double d) { + return String.format("%.2f", d); + } + + /** Formats a double-value with N decimal digits. */ + public static String formatN(double d, int N) { + return String.format("%." + N + "f", d); + } + + /** Reads a boolean-value from console. */ + public static boolean readBoolean(String prompt) { + final String[] trueValues = + { "1", "y", "t", "j", "w", "yes", "true", "ja", "wahr", "ok" }; + System.out.print(prompt); + String input = readln().toLowerCase(); + for (int i = 0; i < trueValues.length; ++i) + if (trueValues[i].equals(input)) + return true; + return false; + } + + /** Reads a char-value from console. */ + public static char readChar(String prompt) { + System.out.print(prompt); + return readln().charAt(0); + } + + /** Reads a double-value from console. */ + public static double readDouble(String prompt) { + System.out.print(prompt); + return Double.parseDouble(readln()); + } + + /** Reads a float-value from console. */ + public static float readFloat(String prompt) { + System.out.print(prompt); + return Float.parseFloat(readln()); + } + + /** Reads an int-value from console. */ + public static int readInt(String prompt) { + System.out.print(prompt); + return Integer.parseInt(readln()); + } + + /** Reads a long-value from console. */ + public static long readLong(String prompt) { + System.out.print(prompt); + return Long.parseLong(readln()); + } + + /** Reads a string-value from console. */ + public static String readString(String prompt) { + System.out.print(prompt); + return readln(); + } + + /** Reads a string-value from console without prompt. + For use at the end of a console program. */ + public static String readln() { + try { + return Input.readLine(); + } catch(Exception e) { + return ""; + } + } + + private static BufferedReader Input; + + static { + try { + Input = new BufferedReader(new InputStreamReader(System.in)); + } + catch (Exception e) { + System.out.println("console input not possible."); + } + } + + + +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/je/util/turtle.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/je/util/turtle.java new file mode 100644 index 0000000..4a704ad --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/je/util/turtle.java @@ -0,0 +1,311 @@ +package je.util; +/* + * Class : Turtle + * Copyright: (c) Gerhard Röhner + * + * History + * -------- + * 3.00 2000.10.10 first version as java class + * 3.01 2002.10.22 DrawDynamic + * 3.02 2010.10.11 sleepTime for paint delay + * 3.03 2012.03.20 cartesian coordinate system, used with originX, originY, setOrigin + * 3.04 2015.01.24 english version, integrated component + */ + + +import java.awt.*; +import java.awt.image.*; +import java.awt.event.*; + +/** + * This class is a turtle component for simple graphic programming. + * + * @see + * @author Gerhard Röhner + * @version 3.03 20/03/2012 + */ + + +public class Turtle extends Canvas { + + // -- private Attribute ------------------------------------------------------ + + private BufferedImage myBufferedImage; + private Graphics myBufferedGraphics; + private Color foreground; + private Color background; + private static final double piDurch180 = Math.PI / 180; + + // -- public attributes ----------------------------------------------------- + + /** + * turtleX is the x-coordinate of the turtle + *

+ * Example:

myTurtle.turtleX = 100;
+ */ + public double turtleX; + + /** + * turtleY is the y-coordinate of the turtle. + *

+ * Example:

myTurtle.turtleY = 200;
+ */ + public double turtleY; + + /** + * turtleW is the current angle of the turtle in the range form 0 to 360 degrees. + *

+ * Example:

myTurtle.turtleW = 180;
+ */ + public double turtleW; + + /** + * originX is the x-position of the cartesian coodinate system within the turtle canvas. + *

+ * Example:

myTurtle.originX = 0;
+ */ + public double originX; + + /** + * originY is the y-position of the cartesian coodinate system within the turtle canvas. + *

+ * Example:

myTurtle.originY = 100;
+ */ + public double originY; + + /** + * If drawDynamic is true you can watch the drawing of the turtle. + *

+ * Example:

myTurtle.drawDynamic = true;
+ */ + public boolean drawDynamic; + + /** + * For drawDynamic = true you set the delay in milliseconds for drawing. + *

+ * Example:

myTurtle.sleepTime = 500;
+ */ + public int sleepTime = 0; + + // --- constructor ----------------------------------------------------------- + + /** + * Creates a Turtle with a canvas. + * At the beginning the Turtle is placed in the middle of it's canvas. + * The start angle is 0 degree, which means the Turtle looks to the right. + * The background color is white, the drawing color black. + *

+ * The turtle position can easily be changed by clicking into the canvas. + *

+ * The size of the canvas can easily be changed with the mouse. + *

+ * Example:

Turtle myTurtle = new Turtle();
+ */ + + public Turtle() { + myBufferedImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); + myBufferedGraphics = myBufferedImage.getGraphics(); + + setForeground(Color.black); + setBackground(Color.white); + drawDynamic = true; + + addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent evt) { + turtleMouseClicked(evt);}}); + addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent evt) { + turtleResized(evt);}}); + setOrigin(50, 50); + } + + private void turtleMouseClicked(MouseEvent evt) { + turtleX = evt.getX() - originX; + turtleY = originY - evt.getY(); + turtleW = 0; + } + + private void turtleResized(ComponentEvent evt) { + int width = getWidth(); + int height = getHeight(); + + BufferedImage newBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics newGraphics = newBufferedImage.getGraphics(); + newGraphics.setColor(background); + newGraphics.fillRect(0, 0, width, height); + newGraphics.setColor(foreground); + newGraphics.drawImage(myBufferedImage, 0, 0, this); + + turtleX = 0; + turtleY = 0; + turtleW = 0; + setOrigin(width / 2, height / 2); + + myBufferedImage = newBufferedImage; + myBufferedGraphics = newGraphics; + } + + public boolean isDoubleBuffered() { + return true; + } + + private void wTurtleMod360() { + while (turtleW >= 360) + turtleW = turtleW - 360; + while (turtleW < 0) + turtleW = turtleW + 360; + } + + // --- angle and turns ------------------------------------------------------- + + /** + * Turns the angle of the turtle relativ by the parameter angle. + * Positive values means a turn right, negative a turn left. + *

+ * Example:

myTurtle.turn(-90);
+ */ + public void turn(double angle) { + turtleW = turtleW + angle; + wTurtleMod360(); + } + + /** + * Sets the angle of the turtle absolute by the parameter angle. + * The angle increases counterclockwise, therefore + * right = 0, top = 90, left = 180, bottom = 270. + *

+ * Example:

myTurtle.turnto(270);
+ */ + public void turnto(double angle) { + turtleW = angle; + wTurtleMod360(); + } + + // --- Drawing --------------------------------------------------------------- + + /** + * The Turtle draws a line of the length specified in the current direction. + *

+ * Example:

myTurtle.draw(100);
+ */ + public void draw(double length) { + drawto(turtleX + length * Math.cos(turtleW * piDurch180), + turtleY + length * Math.sin(turtleW * piDurch180)); + } + + /** + * The Turtle draws a line form the current position (turtleX, turtleY) to the + * position (x, y) relativ to the cartesian coordinate system. + *

+ * Example:

myTurtle.drawto(200, 300);
+ */ + public void drawto(double x, double y) { + int x1 = (int) (originX + turtleX); + int x2 = (int) (originX + x); + int y1 = (int) (originY - turtleY); + int y2 = (int) (originY - y); + + myBufferedGraphics.drawLine(x1, y1, x2, y2); + if (drawDynamic){ + getGraphics().drawLine(x1, y1, x2, y2); + try { + Thread.currentThread().sleep(sleepTime); + } catch(InterruptedException e) { + } + } else + repaint(); + + turtleX = x; + turtleY = y; + } + + // --- Moving ---------------------------------------------------------------- + + /** + * The Turtle moves without drawing the length specified in the current + * direction. + *

+ * Example:

myTurtle.move(100);
+ */ + public void move(double length) { + turtleX = turtleX + length * Math.cos (turtleW * piDurch180); + turtleY = turtleY + length * Math.sin (turtleW * piDurch180); + } + + /** + * The Turtle moves without drawing to position (x, y) relativ to the + * cartesian coordinate system. + *

+ * Example:

myTurtle.moveto(100, 200);
+ */ + public void moveto(double x, double y) { + turtleX = x; + turtleY = y; + } + + // --- set origin ----------------------------------------------------------- + + /** + * Sets the origin of the cartesian coordinate system within the turtle's canvas. + *

+ * Example:

myTurtle.setOrigin(100, 200);
+ */ + public void setOrigin(double x, double y) { + originX = x; + originY = y; + } + + // --- fore- and background color -------------------------------------------- + + /** + * Sets the drawing color of the Turtle to color c. + *

+ * Example:

myTurtle.setForeground(Color.red);
+ */ + public void setForeground(Color c) { + foreground = c; + myBufferedGraphics.setColor(foreground); + super.setForeground(foreground); + } + + /** + * Sets the canvas color of the Turtle to color c. + *

+ * Example:

myTurtle.setBackground(Color.blue); 
+ */ + public void setBackground(Color c) { + background = c; + myBufferedGraphics.setColor(background); + myBufferedGraphics.fillRect(0, 0, getWidth(), getHeight()); + myBufferedGraphics.setColor(foreground); + repaint(); + } + + /** + * Clear the Turtle's canvas with the background color. + *

+ * Example:

myTurtle.clear();
+ */ + public void clear() { + setBackground(background); + getGraphics().drawImage(myBufferedImage, 0, 0, this); + repaint(); + } + + // --- Showing -------------------------------------------------------------- + + /** + * Shows the Turtle's canvas. + */ + public void paint(Graphics g) { + g.drawImage(myBufferedImage, 0, 0, this); + } + + /** + * Updates the Turtle's canvas. + */ + public void update(Graphics g) { + paint(g); + } + +} diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/jeclasses.jar b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/jeclasses.jar new file mode 100644 index 0000000000000000000000000000000000000000..7fa4892e3be6820a600278da2bd9b148d71d71da GIT binary patch literal 90273 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 Q1^hQi2Y{W+;M)N3FGnMA&j0`b literal 0 HcmV?d00001 diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/jnumberfield.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/jnumberfield.java new file mode 100644 index 0000000..fd41a78 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/jnumberfield.java @@ -0,0 +1,129 @@ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.util.*; + +/** +Swing-component for input and output of numeric values. +*/ + +public class JNumberField extends JTextField { + + /** constructor for a JNumberField */ + public JNumberField() { + enableEvents(AWTEvent.KEY_EVENT_MASK); + } + + /** Gets a double-value from the JNumberField. */ + public double getDouble() { + Double d = new Double(getText()); + return d.doubleValue(); + } + + /** Gets a float-value from the JNumberField. */ + public float getFloat() { + Double d = new Double(getText()); + return d.floatValue(); + } + + /** Gets an int-value from the JNumberField. */ + public int getInt() { + Double d = new Double(getText()); + return d.intValue(); + } + + /** Gets a long-value from the JNumberField. */ + public long getLong() { + Double d = new Double(getText()); + return d.longValue(); + } + + /** Checks wether the JNumberField contains a valid numeric value. */ + public boolean isNumeric() { + final String Digits = "(\\p{Digit}+)"; + final String HexDigits = "(\\p{XDigit}+)"; + // an exponent is 'e' or 'E' followed by an optionally + // signed decimal integer. + final String Exp = "[eE][+-]?"+Digits; + final String fpRegex = + ("[\\x00-\\x20]*"+ // Optional leading "whitespace" + "[+-]?(" + // Optional sign character + "NaN|" + // "NaN" string + "Infinity|" + // "Infinity" string + + // A decimal floating-point string representing a finite positive + // number without a leading sign has at most five basic pieces: + // Digits . Digits ExponentPart FloatTypeSuffix + // + // Since this method allows integer-only strings as input + // in addition to strings of floating-point literals, the + // two sub-patterns below are simplifications of the grammar + // productions from the Java Language Specification, 2nd + // edition, section 3.10.2. + + // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt + "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ + + // . Digits ExponentPart_opt FloatTypeSuffix_opt + "(\\.("+Digits+")("+Exp+")?)|"+ + + // Hexadecimal strings + "((" + + // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "(\\.)?)|" + + + // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" + + + ")[pP][+-]?" + Digits + "))" + + "[fFdD]?))" + + "[\\x00-\\x20]*");// Optional trailing "whitespace" + + return java.util.regex.Pattern.matches(fpRegex, getText()); + } + + /** Sets a double-value into the JNumberField. */ + public void setDouble(double d) { + setText(String.valueOf(d)); + } + + /** Sets a double-value with N digits into the JNumberField. */ + public void setDouble(double d, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", d)); + } + + /** Sets a float-value into the JNumberField. */ + public void setFloat(float f) { + setText(String.valueOf(f)); + } + + /** Sets a float-value with N digits into the JNumberField. */ + public void setFloat(float f, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", f)); + } + + /** Sets an int-value into the JNumberField. */ + public void setInt(int i) { + setText(String.valueOf(i)); + } + + /** Sets a long-value into the JNumberField. */ + public void setLong(long l) { + setText(String.valueOf(l)); + } + + /** Clears the JNumberField */ + public void clear() { + setText(""); + } + + protected void processKeyEvent(KeyEvent e) { + super.processKeyEvent(e); + if (isNumeric() || getText().equals("-") || + getText().equals("") || getText().equals(".")) + setBackground(Color.white); + else + setBackground(Color.red); + } + +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/meta-inf/manifest.mf b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/meta-inf/manifest.mf new file mode 100644 index 0000000..4e2b00e --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/meta-inf/manifest.mf @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Class-Path: JEClasses.jar +Created-By: 1.8.0_161 (Oracle Corporation) +Main-Class: BreakVigenere + diff --git a/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/numberfield.java b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/numberfield.java new file mode 100644 index 0000000..ca7ef01 --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/angriffvigenere_partiellebruteforce/numberfield.java @@ -0,0 +1,128 @@ +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/** +AWT-component for input and output of numeric values. +*/ + +public class NumberField extends TextField { + + /** constructor for a NumberField */ + public NumberField() { + enableEvents(AWTEvent.KEY_EVENT_MASK); + } + + /** Gets a double-value from the NumberField. */ + public double getDouble() { + Double d = new Double(getText()); + return d.doubleValue(); + } + + /** Gets a float-value from the NumberField. */ + public float getFloat() { + Double d = new Double(getText()); + return d.floatValue(); + } + + /** Gets an int-value from the NumberField. */ + public int getInt() { + Double d = new Double(getText()); + return d.intValue(); + } + + /** Gets a long-value from the NumberField. */ + public long getLong() { + Double d = new Double(getText()); + return d.longValue(); + } + + /** Checks wether the NumberField contains a valid numeric value. */ + public boolean isNumeric() { + final String Digits = "(\\p{Digit}+)"; + final String HexDigits = "(\\p{XDigit}+)"; + // an exponent is 'e' or 'E' followed by an optionally + // signed decimal integer. + final String Exp = "[eE][+-]?"+Digits; + final String fpRegex = + ("[\\x00-\\x20]*"+ // Optional leading "whitespace" + "[+-]?(" + // Optional sign character + "NaN|" + // "NaN" string + "Infinity|" + // "Infinity" string + + // A decimal floating-point string representing a finite positive + // number without a leading sign has at most five basic pieces: + // Digits . Digits ExponentPart FloatTypeSuffix + // + // Since this method allows integer-only strings as input + // in addition to strings of floating-point literals, the + // two sub-patterns below are simplifications of the grammar + // productions from the Java Language Specification, 2nd + // edition, section 3.10.2. + + // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt + "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ + + // . Digits ExponentPart_opt FloatTypeSuffix_opt + "(\\.("+Digits+")("+Exp+")?)|"+ + + // Hexadecimal strings + "((" + + // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "(\\.)?)|" + + + // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" + + + ")[pP][+-]?" + Digits + "))" + + "[fFdD]?))" + + "[\\x00-\\x20]*");// Optional trailing "whitespace" + + return java.util.regex.Pattern.matches(fpRegex, getText()); + } + + /** Sets a double-value into the NumberField. */ + public void setDouble(double d) { + setText(String.valueOf(d)); + } + + /** Sets a double-value with N digits into the NumberField. */ + public void setDouble(double d, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", d)); + } + + /** Sets a float-value into the NumberField. */ + public void setFloat(float f) { + setText(String.valueOf(f)); + } + + /** Sets a float-value with N digits into the NumberField. */ + public void setFloat(float f, int N) { + setText(String.format(Locale.ENGLISH, "%." + N + "f", f)); + } + + /** Sets an int-value into the NumberField. */ + public void setInt(int i) { + setText(String.valueOf(i)); + } + + /** Sets a long-value into the NumberField. */ + public void setLong(long l) { + setText(String.valueOf(l)); + } + + /** Clears the NumberField */ + public void clear() { + setText(""); + } + + protected void processKeyEvent(KeyEvent e) { + super.processKeyEvent(e); + if (isNumeric() || getText().equals("-") || + getText().equals("") || getText().equals(".")) + setBackground(Color.white); + else + setBackground(Color.red); + } + +} \ No newline at end of file diff --git a/Software/iud_key_angriffe_vigenere/readme.adoc b/Software/iud_key_angriffe_vigenere/readme.adoc new file mode 100644 index 0000000..01321fa --- /dev/null +++ b/Software/iud_key_angriffe_vigenere/readme.adoc @@ -0,0 +1,12 @@ += Material der ZPG IMP 8: + +|=== +|Zuordnung| Rechner und Netze +|Klassenstufe| IMP 8 +|Bildungsplanbezug | +|Werkzeug| +|Autoren| +|=== + +== Inhalt +Programme für die Kryptoanalyse der Vigenèreverschlüsselung \ No newline at end of file