changeset 16:280facb82b80

Add the ability to change ring settings at the machine level.
author Brian Neal <bgneal@gmail.com>
date Sat, 07 Jul 2012 11:42:31 -0500
parents 9e02d8696e67
children b04dea5f71a3
files enigma/machine.h enigma/tests/test_machine.t.h
diffstat 2 files changed, 122 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/enigma/machine.h	Wed Jul 04 19:52:41 2012 -0500
+++ b/enigma/machine.h	Sat Jul 07 11:42:31 2012 -0500
@@ -6,10 +6,12 @@
 //
 // machine.h - This file contains the main Enigma machine class.
 
+#include <algorithm>
 #include <memory>
 #include <string>
 #include <vector>
 #include <cassert>
+#include <cstddef>
 #include "enigma_types.h"
 #include "rotor.h"
 #include "plugboard.h"
@@ -97,6 +99,66 @@
          return result;
       }
 
+      // Returns the number of rotors in the machine (this count does not include
+      // the reflector).
+      std::size_t num_rotors() const
+      {
+         return rotors.size() - 1;
+      }
+
+      // For changing the ring setting on a rotor inside the machine.
+      // Parameters:
+      //    rotor - identifies the rotor to change the ring setting; must be
+      //            in the range 0 - (num_rotors() - 1). 0 is the leftmost rotor.
+      //    ring_setting - the ring setting value, 0-25
+      //
+      void set_ring_setting(int rotor, int ring_setting)
+      {
+         rotors[rotor + 1].set_ring_setting(ring_setting);
+      }
+
+      // For getting the ring setting on a rotor inside the machine.
+      // Parameters:
+      //    rotor - identifies the rotor to change the ring setting; must be
+      //            in the range 0 - (num_rotors() - 1). 0 is the leftmost rotor.
+      //
+      int get_ring_setting(int rotor) const
+      {
+         return rotors[rotor + 1].get_ring_setting();
+      }
+
+      // For changing the ring settings on all rotors inside the machine.
+      // Parameters:
+      //    settings - a vector of ring settings, 0-25. The size of this
+      //               vector must match num_rotors().
+      //
+      void set_ring_settings(const std::vector<int>& settings)
+      {
+         if (settings.size() == num_rotors())
+         {
+            rotor* r = &rotors[1];  // skip the reflector;
+            for (auto s : settings)
+            {
+               r->set_ring_setting(s);
+               ++r;
+            }
+         }
+         else
+         {
+            throw enigma_machine_error("set_ring_settings rotor/settings size mismatch");
+         }
+      }
+
+      // For getting the ring settings as a vector of integers. Element 0 corresponds
+      // to the leftmost rotor.
+      std::vector<int> get_ring_settings() const
+      {
+         std::vector<int> result(num_rotors());
+         std::transform(rotors.begin() + 1, rotors.end(), result.begin(),
+               [](const rotor& r) { return r.get_ring_setting(); });
+         return result;
+      }
+
       // simulate front panel key press; returns the lamp character that is lit
       char key_press(char c)
       {
@@ -120,6 +182,7 @@
          }
       }
 
+      // Process a buffer of text from a string, returning the result as a string.
       std::string process_text(const std::string& input)
       {
          std::string result;
--- a/enigma/tests/test_machine.t.h	Wed Jul 04 19:52:41 2012 -0500
+++ b/enigma/tests/test_machine.t.h	Sat Jul 07 11:42:31 2012 -0500
@@ -253,3 +253,62 @@
    }
 
 };
+
+class ring_settings_test_suite : public CxxTest::TestSuite
+{
+public:
+
+   void test_ring_settings()
+   {
+      enigma_machine machine({"Beta", "II", "IV", "I"}, {0, 2, 8, 21}, "B-Thin");
+
+      TS_ASSERT_EQUALS(machine.get_ring_setting(0), 0);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(1), 2);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(2), 8);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(3), 21);
+
+      std::vector<int> rings(machine.get_ring_settings());
+      std::vector<int> expected{ 0, 2, 8, 21 };
+      TS_ASSERT_EQUALS(rings, expected);
+
+      machine.set_ring_setting(0, 25);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(0), 25);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(1), 2);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(2), 8);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(3), 21);
+
+      expected = { 25, 2, 8, 21 };
+      TS_ASSERT_EQUALS(machine.get_ring_settings(), expected);
+
+      machine.set_ring_setting(1, 18);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(0), 25);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(1), 18);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(2), 8);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(3), 21);
+
+      expected = { 25, 18, 8, 21 };
+      TS_ASSERT_EQUALS(machine.get_ring_settings(), expected);
+
+      machine.set_ring_setting(2, 11);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(0), 25);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(1), 18);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(2), 11);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(3), 21);
+
+      expected = { 25, 18, 11, 21 };
+      TS_ASSERT_EQUALS(machine.get_ring_settings(), expected);
+
+      machine.set_ring_setting(3, 3);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(0), 25);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(1), 18);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(2), 11);
+      TS_ASSERT_EQUALS(machine.get_ring_setting(3), 3);
+
+      expected = { 25, 18, 11, 3 };
+      TS_ASSERT_EQUALS(machine.get_ring_settings(), expected);
+
+      expected = { 8, 9, 10, 11 };
+      machine.set_ring_settings(expected);
+      TS_ASSERT_EQUALS(machine.get_ring_settings(), expected);
+   }
+};