summaryrefslogtreecommitdiff
path: root/lib/Enigmatic
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2011-08-29 13:06:32 +0100
committerdakkar <dakkar@thenautilus.net>2011-08-29 13:06:32 +0100
commit556f1e542cdeadb7dc2f549ec7915fe28f5bb112 (patch)
tree71585b0df498c971b485222a3b5cfd74b84ec413 /lib/Enigmatic
downloadEnigmatic-556f1e542cdeadb7dc2f549ec7915fe28f5bb112.tar.gz
Enigmatic-556f1e542cdeadb7dc2f549ec7915fe28f5bb112.tar.bz2
Enigmatic-556f1e542cdeadb7dc2f549ec7915fe28f5bb112.zip
static rotors
Diffstat (limited to 'lib/Enigmatic')
-rw-r--r--lib/Enigmatic/Rotor.pm50
-rw-r--r--lib/Enigmatic/Types.pm32
2 files changed, 82 insertions, 0 deletions
diff --git a/lib/Enigmatic/Rotor.pm b/lib/Enigmatic/Rotor.pm
new file mode 100644
index 0000000..a600b43
--- /dev/null
+++ b/lib/Enigmatic/Rotor.pm
@@ -0,0 +1,50 @@
+package Enigmatic::Rotor;
+use DAKKAR::p 'class';
+use Enigmatic::Types qw(WiringMap Letter RotorPos);
+
+has wiring => (
+ is => 'ro',
+ isa => WiringMap,
+ coerce => 1,
+);
+
+has ring_setting => (
+ is => 'rw',
+ isa => RotorPos,
+ default => 0,
+);
+
+around BUILDARGS => sub {
+ my $orig = shift;
+ my $class = shift;
+
+ if ( @_ == 1 && !ref $_[0] ) {
+ return $class->$orig( wiring => $_[0] );
+ }
+ else {
+ return $class->$orig(@_);
+ }
+};
+
+sub map {
+ my $self = shift;
+ my ($letter) = pos_validated_list(
+ \@_,
+ { isa => Letter },
+ );
+
+ return $self->wiring->at($self->_apply_ring_setting($letter));
+}
+
+sub _apply_ring_setting {
+ my $self = shift;
+ my ($letter) = pos_validated_list(
+ \@_,
+ { isa => Letter },
+ );
+
+ return chr(
+ (ord($letter) - ord('A') + $self->ring_setting)
+ % 26
+ +ord('A') );
+}
diff --git a/lib/Enigmatic/Types.pm b/lib/Enigmatic/Types.pm
new file mode 100644
index 0000000..12cb414
--- /dev/null
+++ b/lib/Enigmatic/Types.pm
@@ -0,0 +1,32 @@
+package Enigmatic::Types;
+use DAKKAR::p;
+use MooseX::Types -declare => [qw(Letter WiringMap RotorPos)];
+use MooseX::Types::Moose qw(Str Int);
+use MooseX::Types::Structured qw(Map);
+
+subtype Letter,
+ as Str,
+ where { /[A-Z]/ };
+
+subtype WiringMap,
+ as Map[Letter,Letter],
+ where {
+ my $in = $_->keys->sort->join;
+ my $out = $_->values->sort->join;
+ $in eq $out and $in eq ['A'..'Z']->join;
+ };
+
+coerce WiringMap,
+ from Str,
+ via {
+ my @out = $_->uc->split(qr//)->flatten;
+ croak "invalid wiring string <$_>"
+ unless @out == 26;
+ my %ret;
+ @ret{'A'..'Z'}=@out;
+ \%ret;
+ };
+
+subtype RotorPos,
+ as Int,
+ where { $_ >=0 and $_ <= 26 };