summaryrefslogtreecommitdiff
path: root/lib/Enigmatic/Machine.pm
blob: f5d5081b8ff1b1c0d167b8b0141d37079c0d5813 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package Enigmatic::Machine; 
use DAKKAR::p 'class';
use Enigmatic::RotorBox;
use Enigmatic::ReflectorBox;
use Enigmatic::Plugboard;
use Enigmatic::CryptTrain;
use Enigmatic::Types qw(Letter RotorT ReflectorT PlugboardT);
use MooseX::Types::Moose qw(ArrayRef Str);
 
has train => (
    isa => 'Enigmatic::CryptTrain',
    is => 'ro',
);
 
has plugboard => (
    isa => PlugboardT,
    is => 'ro',
    default => sub { Enigmatic::Plugboard->new },
    coerce => 1,
);
 
around BUILDARGS => sub {
    my $orig = shift;
    my $class = shift;
 
    my $args = $class->$orig(@_);
 
    croak "no rotors specified" unless $args->{rotors};
    croak "no reflector specified" unless $args->{reflector};
 
    my $rotors = $args->{rotors}->map(\&to_RotorT);
    my $reflector = to_ReflectorT($args->{reflector});
 
    if ($args->{ring_settings}) {
        $args->{ring_settings}->each(
            sub {
                my ($idx,$setting) = @_;
                $rotors->[$idx]->ring_setting($setting);
            });
    }
 
    $args->{train} = Enigmatic::CryptTrain->new({
        rotors => $rotors,
        reflector => $reflector,
        $args->{rotor_positions} ? ( positions => $args->{rotor_positions} ) : () ),
    });
 
    return $args;
};
 
sub map {
    my $self = shift;
    my ($letter) = pos_validated_list(
        \@_,
        isa => Letter },
    );
 
warn "mapping $letter\n";
warn " initial positions: @{[ $self->train->positions ]}\n";
 
    $letter = $self->plugboard->map($letter);
 
warn " after plugboard: $letter\n";
 
    $letter = $self->train->map($letter);
 
warn " after rotors: $letter\n";
 
    $letter = $self->plugboard->map($letter);
 
warn " after plugboard: $letter\n";
 
warn " new positions: @{[ $self->train->positions ]}\n";
 
    return $letter;
}
 
sub map_string {
    my ($self,$string) = @_;
 
    my @letters = $string->split(qr//)->grep(\&is_Letter)->flatten;
 
    my @res;
    for my $letter (@letters) {
        push @res$self->map($letter);
    }
 
    return wantarray ? @res : @res->join;
}