pontifex 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.rvmrc +1 -0
  2. data/Gemfile +16 -0
  3. data/Gemfile.lock +50 -0
  4. data/LICENSE.txt +20 -0
  5. data/README.markdown +53 -0
  6. data/Rakefile +54 -0
  7. data/VERSION +1 -0
  8. data/bin/pontifex +5 -0
  9. data/cucumber.yml +3 -0
  10. data/feature/pontifex_interactive.feature +161 -0
  11. data/feature/pontifex_with_files.feature +137 -0
  12. data/feature/support/env.rb +15 -0
  13. data/lib/pontifex/card.rb +70 -0
  14. data/lib/pontifex/cipher.rb +49 -0
  15. data/lib/pontifex/key_stream.rb +79 -0
  16. data/lib/pontifex.rb +114 -0
  17. data/pontifex.gemspec +99 -0
  18. data/spec/pontifex/card_spec.rb +84 -0
  19. data/spec/pontifex/cipher_spec.rb +23 -0
  20. data/spec/pontifex/key_stream_spec.rb +92 -0
  21. data/spec/pontifex/pontifex_spec.rb +4 -0
  22. data/spec/spec_helper.rb +12 -0
  23. data/vendor/cache/aruba-0.3.6.gem +0 -0
  24. data/vendor/cache/builder-3.0.0.gem +0 -0
  25. data/vendor/cache/childprocess-0.1.9.gem +0 -0
  26. data/vendor/cache/cucumber-0.10.3.gem +0 -0
  27. data/vendor/cache/diff-lcs-1.1.2.gem +0 -0
  28. data/vendor/cache/ffi-1.0.9.gem +0 -0
  29. data/vendor/cache/gherkin-2.3.9.gem +0 -0
  30. data/vendor/cache/git-1.2.5.gem +0 -0
  31. data/vendor/cache/jeweler-1.6.0.gem +0 -0
  32. data/vendor/cache/json-1.5.1.gem +0 -0
  33. data/vendor/cache/rake-0.9.0.gem +0 -0
  34. data/vendor/cache/rcov-0.9.9.gem +0 -0
  35. data/vendor/cache/rspec-2.6.0.gem +0 -0
  36. data/vendor/cache/rspec-core-2.6.3.gem +0 -0
  37. data/vendor/cache/rspec-expectations-2.6.0.gem +0 -0
  38. data/vendor/cache/rspec-mocks-2.6.0.gem +0 -0
  39. data/vendor/cache/term-ansicolor-1.0.5.gem +0 -0
  40. data/vendor/cache/trollop-1.16.2.gem +0 -0
  41. metadata +175 -0
@@ -0,0 +1,79 @@
1
+ require 'pontifex/card'
2
+
3
+ module Pontifex
4
+
5
+ DEFAULT_KEY = "Ac,2c,3c,4c,5c,6c,7c,8c,9c,Tc,Jc,Qc,Kc," +
6
+ "Ad,2d,3d,4d,5d,6d,7d,8d,9d,Td,Jd,Qd,Kd," +
7
+ "Ah,2h,3h,4h,5h,6h,7h,8h,9h,Th,Jh,Qh,Kh," +
8
+ "As,2s,3s,4s,5s,6s,7s,8s,9s,Ts,Js,Qs,Ks," +
9
+ "ja,jb"
10
+
11
+ class KeyStream
12
+ attr_reader :deck
13
+ JA = Card.new("ja")
14
+ JB = Card.new("jb")
15
+
16
+ def initialize(key=Pontifex::DEFAULT_KEY)
17
+ @deck = process_param(key)
18
+ end
19
+
20
+ def sequence!
21
+ move_down!("ja", 1)
22
+ move_down!("jb", 2)
23
+ triple_cut!
24
+ count_cut!
25
+ end
26
+
27
+ def letter
28
+ count = @deck.first.to_i
29
+ if result = @deck[count].to_c
30
+ result
31
+ else
32
+ sequence!
33
+ letter
34
+ end
35
+ end
36
+
37
+ def to_key
38
+ @deck.map { |card| card.str }.join(",")
39
+ end
40
+
41
+
42
+ private
43
+ def process_param(str)
44
+ #TODO I need to raise an exception here if any 'Ja' jokers,
45
+ # as opposed to 'ja' jokers, (or 'Jb') are included in
46
+ # the key -- Or does this exception belong in Card?
47
+ key_ary = str.split(",")
48
+ key_ary.map { |param| Card.new(param) }
49
+ end
50
+
51
+ def move_down!(card_str, num)
52
+ num.times do
53
+ index = @deck.index { |c| c.str == card_str }
54
+ unless @deck[index] == @deck.last
55
+ @deck[index], @deck[index + 1] = @deck[index + 1], @deck[index]
56
+ else
57
+ @deck.insert(1, @deck.pop)
58
+ end
59
+ end
60
+ end
61
+
62
+ def triple_cut!
63
+ ti, bi = @deck.index(JA), @deck.index(JB)
64
+ ti, bi = bi, ti if ti > bi
65
+
66
+ top = @deck[0...ti]
67
+ middle = @deck[ti..bi]
68
+ bottom = @deck[(bi + 1)..-1]
69
+
70
+ @deck.replace(bottom + middle + top)
71
+ end
72
+
73
+ def count_cut!
74
+ count = @deck.last.to_i
75
+ top = @deck.shift(count)
76
+ @deck.insert(-2, *top)
77
+ end
78
+ end
79
+ end
data/lib/pontifex.rb ADDED
@@ -0,0 +1,114 @@
1
+ require 'bundler/setup'
2
+ require 'trollop'
3
+ require 'pontifex/cipher'
4
+
5
+
6
+ module Pontifex
7
+ extend self
8
+
9
+ def run
10
+ parse_options!
11
+
12
+ case @cmd
13
+ when "encrypt"
14
+ @output = @pontifex.encrypted
15
+ when "decrypt"
16
+ @output = @pontifex.decrypted
17
+ end
18
+
19
+ handle_output
20
+ end
21
+
22
+
23
+ private
24
+ def handle_output
25
+ if @cmd_options[:out_file]
26
+ File.open(@cmd_options[:out_file], 'w') {|f| f.write(@output) }
27
+ puts "Message #{@cmd}ed. You can find the results in the file: #{@cmd_options[:out_file]}\n"
28
+ else
29
+ puts @output
30
+ end
31
+ end
32
+
33
+ SUB_COMMANDS = %w[encrypt decrypt]
34
+
35
+ def parse_options!
36
+ version_str = File.exist?('VERSION') ? File.read('VERSION') : ""
37
+
38
+ Trollop::options do
39
+ banner <<-EOS
40
+ pontifex will encrypt, or decrypt messages.
41
+
42
+ Usage:
43
+ pontifex [options]
44
+ pontifex encrypt [options] [file ...]
45
+ pontifex decrypt [options] [file ...]
46
+ where [options] are:
47
+ EOS
48
+ version version_str
49
+ stop_on SUB_COMMANDS
50
+ end
51
+
52
+ @cmd = ARGV.shift
53
+ @cmd_options = case @cmd
54
+ when "encrypt"
55
+ Trollop::options do
56
+ banner <<-EOS
57
+ pontifex will encrypt messages from STDIN or from files.
58
+
59
+ Usage:
60
+ pontifex encrypt [options] [file ...]
61
+ where [options] are:
62
+ EOS
63
+ version version_str
64
+ opt :deck_key, "A file setting the key (a deck of cards) in a specific, initial order", :type => :string
65
+ opt :out_file, "An output file for the encrypted message", :type => :string
66
+ end
67
+
68
+ when "decrypt"
69
+ Trollop::options do
70
+ banner <<-EOS
71
+ pontifex will decrypt messages from STDIN or from files.
72
+
73
+ Usage:
74
+ pontifex decrypt [options] [file ...]
75
+ where [options] are:
76
+ EOS
77
+ version version_str
78
+ opt :deck_key, "A file setting the key (a deck of cards) in a specific, initial order", :type => :string
79
+ opt :out_file, "An output file for the decrypted message", :type => :string
80
+ end
81
+
82
+ else
83
+ Trollop::die "Either 'encrypt' or 'decrypt' must be passed as a sub-command"
84
+ end
85
+
86
+ key = ""
87
+ if @cmd_options[:deck_key]
88
+ Trollop::die "Can't find #{@cmd_options[:deck_key]} key file" unless File.exists?(@cmd_options[:deck_key])
89
+
90
+ File.open(@cmd_options[:deck_key], "r") do |infile|
91
+ while (line = infile.gets)
92
+ key << line.chomp
93
+ end
94
+ end
95
+ end
96
+
97
+ if ARGV.empty?
98
+ puts "Enter the message to encrypt."
99
+ puts "enter 'Done' on a line by itself when you are done"
100
+ end
101
+
102
+ message = ""
103
+ while input = gets
104
+ break if input.nil? || input.chomp.downcase == "done"
105
+ message << input.chomp
106
+ end
107
+
108
+ if key.empty?
109
+ @pontifex = Cipher.new(message)
110
+ else
111
+ @pontifex = Cipher.new(message, key)
112
+ end
113
+ end
114
+ end
data/pontifex.gemspec ADDED
@@ -0,0 +1,99 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{pontifex}
8
+ s.version = "1.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Errin Larsen"]
12
+ s.date = %q{2011-06-01}
13
+ s.default_executable = %q{pontifex}
14
+ s.description = %q{This gem is a solution to ruby quiz #1: http://www.rubyquiz.com/quiz1.html}
15
+ s.email = %q{errinlarsen@gmail.com}
16
+ s.executables = ["pontifex"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.markdown"
20
+ ]
21
+ s.files = [
22
+ ".rvmrc",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE.txt",
26
+ "README.markdown",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "bin/pontifex",
30
+ "cucumber.yml",
31
+ "feature/pontifex_interactive.feature",
32
+ "feature/pontifex_with_files.feature",
33
+ "feature/support/env.rb",
34
+ "lib/pontifex.rb",
35
+ "lib/pontifex/card.rb",
36
+ "lib/pontifex/cipher.rb",
37
+ "lib/pontifex/key_stream.rb",
38
+ "pontifex.gemspec",
39
+ "spec/pontifex/card_spec.rb",
40
+ "spec/pontifex/cipher_spec.rb",
41
+ "spec/pontifex/key_stream_spec.rb",
42
+ "spec/pontifex/pontifex_spec.rb",
43
+ "spec/spec_helper.rb",
44
+ "vendor/cache/aruba-0.3.6.gem",
45
+ "vendor/cache/builder-3.0.0.gem",
46
+ "vendor/cache/childprocess-0.1.9.gem",
47
+ "vendor/cache/cucumber-0.10.3.gem",
48
+ "vendor/cache/diff-lcs-1.1.2.gem",
49
+ "vendor/cache/ffi-1.0.9.gem",
50
+ "vendor/cache/gherkin-2.3.9.gem",
51
+ "vendor/cache/git-1.2.5.gem",
52
+ "vendor/cache/jeweler-1.6.0.gem",
53
+ "vendor/cache/json-1.5.1.gem",
54
+ "vendor/cache/rake-0.9.0.gem",
55
+ "vendor/cache/rcov-0.9.9.gem",
56
+ "vendor/cache/rspec-2.6.0.gem",
57
+ "vendor/cache/rspec-core-2.6.3.gem",
58
+ "vendor/cache/rspec-expectations-2.6.0.gem",
59
+ "vendor/cache/rspec-mocks-2.6.0.gem",
60
+ "vendor/cache/term-ansicolor-1.0.5.gem",
61
+ "vendor/cache/trollop-1.16.2.gem"
62
+ ]
63
+ s.homepage = %q{http://github.com/errinlarsen/pontifex}
64
+ s.licenses = ["MIT"]
65
+ s.require_paths = ["lib"]
66
+ s.rubygems_version = %q{1.6.2}
67
+ s.summary = %q{An implementation of the Solitaire Cipher in Ruby}
68
+
69
+ if s.respond_to? :specification_version then
70
+ s.specification_version = 3
71
+
72
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
73
+ s.add_runtime_dependency(%q<trollop>, [">= 0"])
74
+ s.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
75
+ s.add_development_dependency(%q<cucumber>, [">= 0"])
76
+ s.add_development_dependency(%q<aruba>, [">= 0"])
77
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
78
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.0"])
79
+ s.add_development_dependency(%q<rcov>, [">= 0"])
80
+ else
81
+ s.add_dependency(%q<trollop>, [">= 0"])
82
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
83
+ s.add_dependency(%q<cucumber>, [">= 0"])
84
+ s.add_dependency(%q<aruba>, [">= 0"])
85
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
86
+ s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
87
+ s.add_dependency(%q<rcov>, [">= 0"])
88
+ end
89
+ else
90
+ s.add_dependency(%q<trollop>, [">= 0"])
91
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
92
+ s.add_dependency(%q<cucumber>, [">= 0"])
93
+ s.add_dependency(%q<aruba>, [">= 0"])
94
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
95
+ s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
96
+ s.add_dependency(%q<rcov>, [">= 0"])
97
+ end
98
+ end
99
+
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ module Pontifex
4
+ describe Card do
5
+ describe "#new" do
6
+ describe "input validations" do
7
+ it "should raise an error with an input paramter that is less than 2 characters" do
8
+ expect { Card.new("5") }.to raise_error ArgumentError, "Cards must be 2 characters long"
9
+ end
10
+
11
+ it "should raise an error with an input paramter that is more than 2 characters" do
12
+ expect { Card.new("5As") }.to raise_error ArgumentError, "Cards must be 2 characters long"
13
+ end
14
+
15
+ it "should raise an error with an input parameter outside of the letters j,A,T,J,Q or K and the numbers 2-9 as the first character" do
16
+ expect { Card.new("bs") }.to raise_error ArgumentError, "first character of a card must be one of [2-9,j,A,T,J,Q,K]"
17
+ end
18
+
19
+ it "should raise an error with an input parameter outside of the letters c,d,h,s,a,b as the second character"do
20
+ expect { Card.new("9g") }.to raise_error ArgumentError, "second character of a card must be one of [a,b,c,d,h,s]"
21
+ end
22
+
23
+ it "should raise an error with a valid card value character, but with a suit of 'a' or 'b'" do
24
+ expect { Card.new("9b") }.to raise_error ArgumentError, "only Jokers may have a suit of 'a' or 'b'"
25
+ end
26
+
27
+ it "should raise an error with an input parameter of a Joker with a suit other than 'a' or 'b'" do
28
+ expect { Card.new("jd") }.to raise_error ArgumentError, "Jokers may not have a suit other than 'a' or 'b'"
29
+ end
30
+ end
31
+
32
+ describe "Card integer values" do
33
+ it "should create a card with a value of 2 if '2c' is input as a parameter" do
34
+ Card.new("2c").to_i.should == 2
35
+ end
36
+
37
+ it "should create a card with a value of 25 if 'Qd' is input as a parameter" do
38
+ Card.new("Qd").to_i.should == 25
39
+ end
40
+
41
+ it "should create a card with a value of 36 if 'Th' is input as a parameter" do
42
+ Card.new("Th").to_i.should == 36
43
+ end
44
+
45
+ it "should create a card with a value of 40 if 'As' is input as a parameter" do
46
+ Card.new("As").to_i.should == 40
47
+ end
48
+
49
+ it "should create a card with a value of 53 if 'ja' is input as a paramter" do
50
+ Card.new("ja").to_i.should == 53
51
+ end
52
+ end
53
+
54
+ describe "Card letter values" do
55
+ it "should create a card with a letter of 'd' if '4c' is input as a parameter" do
56
+ Card.new("4c").to_c.should == "D"
57
+ end
58
+
59
+ it "should create a card with a letter of 'u' if 'Jd' is input as a parameter" do
60
+ Card.new("Jd").to_c.should == "X"
61
+ end
62
+
63
+ it "should create a card with a letter of 'j' if 'Th' is input as a parameter" do
64
+ Card.new("Th").to_c.should == "J"
65
+ end
66
+
67
+ it "should create a card with a letter of 'x' if 'Js' is input as a parameter" do
68
+ Card.new("Js").to_c.should == "X"
69
+ end
70
+
71
+ it "should create a card with a letter of NIL if 'Jb' is input as a paramter" do
72
+ Card.new("jb").to_c.should be_nil
73
+ end
74
+ end
75
+
76
+ describe "Equality" do
77
+ it "should be equal to another card created with the same input as a parameter" do
78
+ param = "Qh"
79
+ Card.new(param).should == Card.new(param)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ module Pontifex
4
+ describe Cipher do
5
+ let(:raw_unencrypted_msg) { "Code in Ruby, live longer!" }
6
+ let(:decrypted_msg) { "CODEI NRUBY LIVEL ONGER" }
7
+ let(:encrypted_msg) { "GLNCQ MJAFF FVOMB JIYCB" }
8
+
9
+ describe "#encrypted" do
10
+ it "should return an encrypted conversion of the input String paramter" do
11
+ msg = Cipher.new(raw_unencrypted_msg)
12
+ msg.encrypted.should == encrypted_msg
13
+ end
14
+ end
15
+
16
+ describe "#decrypted" do
17
+ it "should return a decrypted plain text conversion of the input String parameter" do
18
+ msg = Cipher.new(encrypted_msg)
19
+ msg.decrypted.should == decrypted_msg
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ module Pontifex
4
+ describe KeyStream do
5
+ let(:default_key) do
6
+ "Ac,2c,3c,4c,5c,6c,7c,8c,9c,Tc,Jc,Qc,Kc," +
7
+ "Ad,2d,3d,4d,5d,6d,7d,8d,9d,Td,Jd,Qd,Kd," +
8
+ "Ah,2h,3h,4h,5h,6h,7h,8h,9h,Th,Jh,Qh,Kh," +
9
+ "As,2s,3s,4s,5s,6s,7s,8s,9s,Ts,Js,Qs,Ks," +
10
+ "ja,jb"
11
+ end
12
+ let(:key_stream) { KeyStream.new(default_key) }
13
+
14
+ it "should never contain more than one 'ja' or 'jb' joker" do
15
+ ks = key_stream
16
+ 20.times { ks.sequence! }
17
+ ks.deck.select { |c| c.str =~/j[ab]/ }.count.should == 2
18
+ end
19
+
20
+ it "should correctly generate new letters when continuously sequencing the deck" do
21
+ ks = key_stream
22
+ expected_string = "DWJXHYRFDGTMSHPUURXJ"
23
+ found_string = ""
24
+ while found_string.length < 20
25
+ ks.sequence!
26
+ next if ks.letter.nil?
27
+ found_string += ks.letter
28
+ end
29
+ end
30
+
31
+ describe "#new" do
32
+ it "should create a standard ordered deck by default" do
33
+ KeyStream.new.deck.should == default_key.split(",").map { |k| Card.new(k) }
34
+ end
35
+ end
36
+
37
+ describe "#deck" do
38
+ it "should return a representation of a deck of cards implemented with an Array" do
39
+ key_stream.deck.should be_an_instance_of(Array)
40
+ end
41
+
42
+ it "should contain nothing but Card instances" do
43
+ expected_count = key_stream.deck.count
44
+ key_stream.deck.select { |c| c.instance_of?(Card) }.count.should == expected_count
45
+ end
46
+
47
+ it "should only contain each card once" do
48
+ expected_count = key_stream.deck.count
49
+ key_stream.deck.uniq.count.should == expected_count
50
+ end
51
+ end
52
+
53
+ describe "#sequence!" do
54
+ let(:expected_deck) do
55
+ key = "2c,3c,4c,5c,6c,7c,8c,9c,Tc,Jc,Qc,Kc," +
56
+ "Ad,2d,3d,4d,5d,6d,7d,8d,9d,Td,Jd,Qd,Kd," +
57
+ "Ah,2h,3h,4h,5h,6h,7h,8h,9h,Th,Jh,Qh,Kh," +
58
+ "As,2s,3s,4s,5s,6s,7s,8s,9s,Ts,Js,Qs,Ks," +
59
+ "ja,jb,Ac"
60
+ key.split(",").map { |str| Card.new(str) }
61
+ end
62
+
63
+ it "should modify the deck" do
64
+ ks = KeyStream.new
65
+ ks.sequence!
66
+ ks.deck.should_not == KeyStream.new.deck
67
+ end
68
+
69
+ it "should leave the deck modified according to the algorithm" do
70
+ ks = KeyStream.new
71
+ ks.sequence!
72
+ ks.deck.should == expected_deck
73
+ end
74
+ end
75
+
76
+ describe "#letter" do
77
+ it "should return a string" do
78
+ key_stream.letter.should be_an_instance_of(String)
79
+ end
80
+
81
+ it "should only return a single character" do
82
+ key_stream.letter.length.should == 1
83
+ end
84
+
85
+ it "should return a 'D' after a single sequence of the default deck" do
86
+ key_stream.sequence!
87
+ key_stream.letter.should == 'D'
88
+ end
89
+
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Pontifex do
4
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require "pontifex"
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file