Module: RotorMachine::Factory

Extended by:
Factory
Included in:
Factory
Defined in:
lib/rotor_machine/factory.rb

Overview

The Factory provides Factory-pattern helpers to build various parts of the RotorMachine - rotors, reflectors, plugboards, and fully-configured machines.

Instance Method Summary collapse

Instance Method Details

#build_machine(options = {}) ⇒ Object Also known as: make_machine

Build a Machine and return it.

The options hash can provide the following options:

  • :rotors - An array of Rotor objects. This can be constructed manually, or through multiple calls to #build_rotor. Alternatively, you can pass an array of symbols which match the constants in the Rotor class, and Rotor objects will be built from those (using default position and step sizes).

  • :reflector - A Reflector object. Alternatively, a symbol matching one of the reflector type constants can be passed in, and a Reflector of the specified type will be created.j

  • :connections - A Hash of connections to make on the new Machine's Plugboard.

Parameters:

  • options (defaults to: {})

    The options for the newly built Machine.

Returns:


154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/rotor_machine/factory.rb', line 154

def build_machine(options={})
  rotors    = options.fetch(:rotors,        [])
  reflector = options.fetch(:reflector,     nil)
  connections = options.fetch(:connections, {})

  m = RotorMachine::Machine.new()
  rotors.each do |r|
    if r.is_a? RotorMachine::Rotor
      m.rotors << r
    elsif r.is_a? Symbol
      m.rotors << RotorMachine::Factory.build_rotor(rotor_kind: r)
    else
      raise ArgumentError, "#{r} is not a rotor or a rotor kind symbol"
    end
  end

  unless reflector.nil?
    if reflector.is_a? Symbol
      m.reflector = RotorMachine::Factory.build_reflector(reflector_kind: reflector)
    elsif reflector.is_a? RotorMachine::Reflector
      m.reflector = reflector
    else
      raise ArgumentError, "#{reflector} is not a reflector or reflector kind symbol"
    end
  end

  m.plugboard = build_plugboard()
  unless connections.empty?
    connections.each { |from, to| m.plugboard.connect(from, to) }
  end

  return m
end

#build_plugboard(options = {}) ⇒ Object Also known as: make_plugboard

Build a new Plugboard object and return it.

Returns:

  • The newly built plugboard.


129
130
131
# File 'lib/rotor_machine/factory.rb', line 129

def build_plugboard(options={})
  return RotorMachine::Plugboard.new()
end

#build_reflector(options = {}) ⇒ Object Also known as: make_reflector

Build a new Reflector and return it.

The options hash for this method can accept the following named arguments:

:reflector_kind - The type of reflector to create. Should be a symbol matching a reflector type constant in the Reflector class, or a 26-character string giving the letter sequence for the reflector. Defaults to :REFLECTOR_A if not specified.

:initial_position - The initial position of the reflector (0-based numeric position, or a letter on the rotor.) Defaults to 0 if not specified.

reflector.

Parameters:

  • options (Hash) (defaults to: {})

    The options hash containing the options for the

Returns:

  • The newly-built reflector.


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/rotor_machine/factory.rb', line 87

def build_reflector(options={})
  reflector_kind     = options.fetch(:reflector_kind, nil)
  initial_position   = options.fetch(:initial_position, nil)

  reflector_alphabet = nil
  if reflector_kind.nil?
    raise ArgumentError, "Reflector type not specified"
  end
  if initial_position.nil?
    initial_position = 0
  end

  if reflector_kind.is_a? Symbol
    unless RotorMachine::Reflector.constants.include?(reflector_kind)
      raise ArgumentError, "Invalid reflector kind (symbol #{reflector_kind} not found)"
    end
    reflector_alphabet = RotorMachine::Reflector.const_get(reflector_kind)
  elsif reflector_kind.is_a? String
    raise ArgumentError, "Invalid reflector kind (invalid length)" unless reflector_kind.length == 26
    reflector_alphabet = reflector_kind.upcase
  else
    raise ArgumentError, "Invalid reflector kind (invalid type)"
  end

  if initial_position.is_a? Numeric
    raise ArgumentError, "Invalid position (#{initial_position} out of range)" unless ((0..25).include?(initial_position))
  elsif initial_position.is_a? String
    unless RotorMachine::Reflector::ALPHABET.include?(initial_position)
      raise ArgumentError, "Invalid position (invalid letter '#{initial_position}')"
    end
    initial_position = reflector_alphabet.index(initial_position)
  else
    raise ArgumentError, "Invalid position (invalid type)"
  end

  return RotorMachine::Reflector.new(reflector_alphabet, initial_position)
end

#build_rotor(options = {}) ⇒ Object Also known as: make_rotor

Build a new Rotor and return it.

The options hash for this method can accept the following named arguments:

:rotor_kind - The type of rotor to create. Should be a symbol matching a rotor type constant in the Rotor class, or a 26-character string giving the letter sequence for the rotor. Defaults to :ROTOR_1 if not specified.

:initial_position - The initial position of the rotor (0-based numeric position, or a letter on the rotor.) Defaults to 0 if not specified.

:step_size - How many positions the rotor should advance with each step. Defaults to 1 if not specified.

Parameters:

  • options (Hash) (defaults to: {})

    The options hash containing the options for the rotor.

Returns:

  • The newly-built rotor.


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/rotor_machine/factory.rb', line 30

def build_rotor(options={})
  rotor_kind         = options.fetch(:rotor_kind, nil)
  initial_position   = options.fetch(:initial_position,   0)
  step_size          = options.fetch(:step_size,          1)

  rotor_alphabet = nil
  if rotor_kind.nil?
    raise ArgumentError, "Rotor kind not specified"
  end

  if rotor_kind.is_a? Symbol
    raise ArgumentError, "Invalid rotor kind (symbol #{rotor_kind} not found)" unless RotorMachine::Rotor.constants.include?(rotor_kind)
    rotor_alphabet = RotorMachine::Rotor.const_get(rotor_kind)
  elsif rotor_kind.is_a? String
    raise ArgumentError, "Invalid rotor kind (invalid length)" unless rotor_kind.length == 26
    rotor_alphabet = rotor_kind.upcase
  else
    raise ArgumentError, "Invalid rotor kind (invalid type #{rotor_kind.class.name})"
  end

  if initial_position.is_a? Numeric
    raise ArgumentError, "Invalid position (#{initial_position} out of range)" unless ((0..25).include?(initial_position))
  elsif initial_position.is_a? String
    unless RotorMachine::Rotor::ALPHABET.include?(initial_position)
      raise ArgumentError, "Invalid position (invalid letter '#{initial_position}')"
    end
  else
    raise ArgumentError, "Invalid position (invalid type #{initial_position.class.name})"
  end

  if  step_size.is_a? Numeric
    raise ArgumentError, "Invalid step size (#{step_size} out of range)" unless ((1..25).include?(step_size))
  else
    raise ArgumentError, "Invalid step size (invalid type #{step_size.class.name})"
  end

  return RotorMachine::Rotor.new(rotor_alphabet, initial_position, step_size)
end