morse_me_nicely 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0e242e84aa15495dc60ee404d8a4226fdaf7bbc2
4
+ data.tar.gz: 18fa718bd9455bbc6f9de8005449ded79de0a7b6
5
+ SHA512:
6
+ metadata.gz: 3ffae5107884ed71c3d426baab6f9ff2fab652b4f0caf47115da386a33e38f5b443cc9def71e19d9067b5d3fb7fefbf3b428f7d0fb6ada01176736ae50ee40d9
7
+ data.tar.gz: dbf89c966f8eb7274df1b00b9e0391fcdcee873c2420cd14344d51735b5669d9b81ee822b64784656f0d569c4774c946ac84321813f8edd596e0be047eb1571d
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rspec', '3.6.0'
4
+ gem 'rake', '12.0.0'
5
+ gem 'thor', '0.19.4'
data/Gemfile.lock ADDED
@@ -0,0 +1,30 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.3)
5
+ rake (12.0.0)
6
+ rspec (3.6.0)
7
+ rspec-core (~> 3.6.0)
8
+ rspec-expectations (~> 3.6.0)
9
+ rspec-mocks (~> 3.6.0)
10
+ rspec-core (3.6.0)
11
+ rspec-support (~> 3.6.0)
12
+ rspec-expectations (3.6.0)
13
+ diff-lcs (>= 1.2.0, < 2.0)
14
+ rspec-support (~> 3.6.0)
15
+ rspec-mocks (3.6.0)
16
+ diff-lcs (>= 1.2.0, < 2.0)
17
+ rspec-support (~> 3.6.0)
18
+ rspec-support (3.6.0)
19
+ thor (0.19.4)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ rake (= 12.0.0)
26
+ rspec (= 3.6.0)
27
+ thor (= 0.19.4)
28
+
29
+ BUNDLED WITH
30
+ 1.14.3
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ begin
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.rspec_opts = "-f doc"
6
+ end
7
+
8
+ task :default => :spec
9
+ rescue LoadError
10
+ raise "No Rspec available"
11
+ end
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Exit cleanly from an early interrupt
4
+ Signal.trap("INT") { exit 1 }
5
+
6
+ require_relative '../lib/morse_me_nicely'
7
+
8
+ MorseMeNicely::CLI.start(ARGV)
@@ -0,0 +1,42 @@
1
+ characters:
2
+ "a": ".-"
3
+ "b": "-..."
4
+ "c": "-.-."
5
+ "d": "-.."
6
+ "e": "."
7
+ "f": "..-."
8
+ "g": "--."
9
+ "h": "...."
10
+ "i": ".."
11
+ "j": ".---"
12
+ "k": "-.-"
13
+ "l": ".-.."
14
+ "m": "--"
15
+ "n": "-."
16
+ "o": "---"
17
+ "p": ".--."
18
+ "q": "--.-"
19
+ "r": ".-."
20
+ "s": "..."
21
+ "t": "-"
22
+ "u": "..-"
23
+ "v": "...-"
24
+ "w": ".--"
25
+ "x": "-..-"
26
+ "y": "-.--"
27
+ "z": "--.."
28
+ "0": "-----"
29
+ "1": ".----"
30
+ "2": "..---"
31
+ "3": "...--"
32
+ "4": "....-"
33
+ "5": "....."
34
+ "6": "-...."
35
+ "7": "--..."
36
+ "8": "---.."
37
+ "9": "----."
38
+ ".": ".-.-.-"
39
+ ",": "--..--"
40
+ separators:
41
+ character: '|'
42
+ word: '/'
@@ -0,0 +1,26 @@
1
+ require 'yaml'
2
+ require 'thor'
3
+
4
+ MORSE_ME_NICELY_PATH = File.dirname(__FILE__) + "/morse_me_nicely/"
5
+
6
+ [
7
+ "encoder",
8
+ "obfuscator",
9
+ "cli"
10
+ ].each do |utility|
11
+ require MORSE_ME_NICELY_PATH + utility
12
+ end
13
+
14
+ module MorseMeNicely
15
+ class InvalidInputError < StandardError; end
16
+
17
+ class Processor
18
+
19
+ def self.encode(input_text, without_obfuscation=false)
20
+ text = Encoder.new(input_text).encoded_input
21
+ text = Obfuscator.new(text).obfuscated_input unless without_obfuscation
22
+ text
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ module MorseMeNicely
2
+
3
+ class CLI < Thor
4
+
5
+ desc "encode [--without-obfuscation] [--input-file=path/to/input_file] [--output-file=path/to/output_file]", "Encode message using obfuscated morse code"
6
+ method_options :without_obfuscation => :boolean
7
+ method_options :input_file => :string
8
+ method_options :output_file => :string
9
+
10
+ def encode
11
+ if options[:input_file]
12
+ input_text = File.read(options[:input_file])
13
+ else
14
+ input_text = ask(set_color("Write the message:", Thor::Shell::Color::GREEN))
15
+ end
16
+ encoded_text = MorseMeNicely::Processor::encode(input_text, options[:without_obfuscation])
17
+ if options[:output_file]
18
+ output_file = File.new(options[:output_file], "w+")
19
+ output_file << encoded_text
20
+ output_file.close
21
+ say("Encoded message has been saved to selected file.", Thor::Shell::Color::GREEN)
22
+ else
23
+ say("Encoded message:", Thor::Shell::Color::GREEN)
24
+ say(encoded_text)
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,51 @@
1
+ module MorseMeNicely
2
+
3
+ class Encoder
4
+
5
+ ENCODING_REFERENCE_PATH = MORSE_ME_NICELY_PATH + "../../data/morse_reference.yml"
6
+
7
+ def initialize(input_text)
8
+ @input_text = input_text
9
+ @encoding_reference = YAML::load_file(ENCODING_REFERENCE_PATH)
10
+ end
11
+
12
+ def encoded_input
13
+ validate_input_text
14
+ @input_text.split(/\n/).map do |line|
15
+ line.scan(/\w+\.?\,?/).map do |word|
16
+ translate_word(word)
17
+ end.join(@encoding_reference["separators"]["word"])
18
+ end.join("\n")
19
+ end
20
+
21
+ private
22
+
23
+ def validate_input_text
24
+ raise InvalidInputError, "No text input found" unless @input_text.is_a?(String)
25
+ invalid_characters = get_input_invalid_characters
26
+ unless invalid_characters.empty?
27
+ raise InvalidInputError, "Input text contains invalid characters: #{invalid_characters.join(" ")}"
28
+ end
29
+ end
30
+
31
+ def get_input_invalid_characters
32
+ input_copy = @input_text.downcase.dup
33
+ @encoding_reference["characters"].keys.each do |character|
34
+ input_copy.gsub!(character, '')
35
+ end
36
+ input_copy.gsub(/\s+/, '').split('').uniq
37
+ end
38
+
39
+ def translate_word(word)
40
+ word.split('').map do |character|
41
+ translate_character(character)
42
+ end.join(@encoding_reference["separators"]["character"])
43
+ end
44
+
45
+ def translate_character(character)
46
+ @encoding_reference["characters"][character.downcase]
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,68 @@
1
+ module MorseMeNicely
2
+
3
+ class Obfuscator
4
+
5
+ def initialize(input_text)
6
+ @input_text = input_text
7
+ end
8
+
9
+ def obfuscated_input
10
+ process_dashes(
11
+ process_dots(
12
+ @input_text
13
+ )
14
+ )
15
+ end
16
+
17
+ private
18
+
19
+ def process_dots(text)
20
+ text_copy = text.dup
21
+ get_ordered_unique_consecutive_chars(text, :dot).each do |uniq_consecutive_dots|
22
+ text_copy.gsub!(uniq_consecutive_dots, encode_consecutive_dots(uniq_consecutive_dots))
23
+ end
24
+ text_copy
25
+ end
26
+
27
+ def process_dashes(text)
28
+ text_copy = text.dup
29
+ get_ordered_unique_consecutive_chars(text, :dash).each do |uniq_consecutive_dashes|
30
+ text_copy.gsub!(uniq_consecutive_dashes, encode_consecutuve_dashes(uniq_consecutive_dashes))
31
+ end
32
+ text_copy
33
+ end
34
+
35
+ def get_ordered_unique_consecutive_chars(text, character)
36
+ regex = case character
37
+ when :dot
38
+ /\.+/
39
+ when :dash
40
+ /\-+/
41
+ end
42
+ text.scan(regex).uniq.sort do |v1, v2|
43
+ v2.length <=> v1.length
44
+ end
45
+ end
46
+
47
+ def encode_consecutive_dots(dots)
48
+ length = dots.length
49
+ if length > 9
50
+ raise InvalidInputError, "Number of consecutive dots can't be greater than 9"
51
+ else
52
+ length.to_s
53
+ end
54
+ end
55
+
56
+ def encode_consecutuve_dashes(dashes)
57
+ ascii_idx_addition = ("A".ord - 1)
58
+ ascii_nr = dashes.length + ascii_idx_addition
59
+ if ascii_nr > "Z".ord
60
+ raise InvalidInputError, "Number of consecutive dashes can't be greater than the size of alphabet"
61
+ else
62
+ ascii_nr.chr
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -0,0 +1,100 @@
1
+ require_relative '../spec_helper'
2
+
3
+ RSpec.describe MorseMeNicely::Encoder, "#encoded_input" do
4
+
5
+ context "when input text is not valid" do
6
+
7
+ context "when input is not a string" do
8
+
9
+ subject do
10
+ described_class.new(true)
11
+ end
12
+
13
+ it "raises InvalidInput error" do
14
+ expect { subject.encoded_input }.to raise_error(MorseMeNicely::InvalidInputError, "No text input found")
15
+ end
16
+
17
+ end
18
+
19
+ context "when input text contains ambiguous characters" do
20
+
21
+ subject do
22
+ described_class.new("I'm to stupid; 2 > 1")
23
+ end
24
+
25
+ it "raises InvalidInput error with invalid characters listed" do
26
+ expect { subject.encoded_input }.to raise_error(MorseMeNicely::InvalidInputError, "Input text contains invalid characters: ' ; >")
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ context "when input text is valid" do
34
+
35
+ context "translation of characters" do
36
+
37
+ subject do
38
+ described_class.new("l")
39
+ end
40
+
41
+ it "returns correct translation based on provided reference" do
42
+ expect(subject.encoded_input).to eq ".-.."
43
+ end
44
+
45
+ end
46
+
47
+ context "characters separation" do
48
+
49
+ subject do
50
+ described_class.new("l2")
51
+ end
52
+
53
+ it "returns translated characters separated by pipe '|'" do
54
+ expect(subject.encoded_input).to eq ".-..|..---"
55
+ end
56
+
57
+ end
58
+
59
+ context "words separation" do
60
+
61
+ it "separates with forward slash '/'" do
62
+ encoder = described_class.new("jm 13")
63
+ expect(encoder.encoded_input).to eq ".---|--/.----|...--"
64
+ end
65
+
66
+ it "considers coma and full stop as part of the preceding word" do
67
+ encoder = described_class.new("you, me and he.")
68
+ expect(encoder.encoded_input).to eq "-.--|---|..-|--..--/--|./.-|-.|-../....|.|.-.-.-"
69
+ end
70
+
71
+ end
72
+
73
+ context "case sensitivity" do
74
+
75
+ it "does ignore character case" do
76
+ encoder_downcase = described_class.new("dominik")
77
+ encoder_uppercase = described_class.new("DOMINIK")
78
+ expect(encoder_downcase.encoded_input).to eq encoder_uppercase.encoded_input
79
+ end
80
+
81
+ end
82
+
83
+ context "whitespaces" do
84
+
85
+ it "considers multiple spaces as one" do
86
+ encoder_single_space = described_class.new("foo bar")
87
+ encoder_multiple_spaces = described_class.new("foo bar")
88
+ expect(encoder_single_space.encoded_input).to eq encoder_multiple_spaces.encoded_input
89
+ end
90
+
91
+ it "respects new line characters" do
92
+ encoder = described_class.new("a\nbc\nbc cd")
93
+ expect(encoder.encoded_input).to eq ".-\n-...|-.-.\n-...|-.-./-.-.|-.."
94
+ end
95
+
96
+ end
97
+
98
+ end
99
+
100
+ end
@@ -0,0 +1,76 @@
1
+ require_relative '../spec_helper'
2
+
3
+ RSpec.describe MorseMeNicely::Obfuscator, "#obfuscated_input" do
4
+
5
+ context "when input text is invalid" do
6
+
7
+ context "when number of consecutive dots is greater than 9" do
8
+
9
+ subject do
10
+ described_class.new("...........")
11
+ end
12
+
13
+ it "raises InvalidInput error" do
14
+ expect { subject.obfuscated_input }.to(
15
+ raise_error(MorseMeNicely::InvalidInputError,
16
+ "Number of consecutive dots can't be greater than 9")
17
+ )
18
+ end
19
+
20
+ end
21
+
22
+ context "when number of consecutive dashes is greater than size of alphabet" do
23
+
24
+ subject do
25
+ described_class.new("---------------------------")
26
+ end
27
+
28
+ it "raises InvalidInput error" do
29
+ expect { subject.obfuscated_input }.to(
30
+ raise_error(MorseMeNicely::InvalidInputError,
31
+ "Number of consecutive dashes can't be greater than the size of alphabet")
32
+ )
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
39
+ context "when input text is valid" do
40
+
41
+ context "consecutive dots" do
42
+
43
+ it "replaces number of consecutive dots with count number" do
44
+ expect(described_class.new(".").obfuscated_input).to eq "1"
45
+ expect(described_class.new("..").obfuscated_input).to eq "2"
46
+ expect(described_class.new("...").obfuscated_input).to eq "3"
47
+ expect(described_class.new("....").obfuscated_input).to eq "4"
48
+ expect(described_class.new(".....").obfuscated_input).to eq "5"
49
+ end
50
+
51
+ end
52
+
53
+ context "consecutive dashes" do
54
+
55
+ it "replaces number of consecutive dashes with the uppercase letter of alphabet at that position" do
56
+ expect(described_class.new("-").obfuscated_input).to eq "A"
57
+ expect(described_class.new("--").obfuscated_input).to eq "B"
58
+ expect(described_class.new("---").obfuscated_input).to eq "C"
59
+ expect(described_class.new("----").obfuscated_input).to eq "D"
60
+ expect(described_class.new("-----").obfuscated_input).to eq "E"
61
+ end
62
+
63
+ end
64
+
65
+ context "misc" do
66
+
67
+ it "replaces number of consecutive dots and dashes in text block based on rules above" do
68
+ obfuscator = described_class.new("../.-|--/..|-./-|.-.|---|..-|-...|.-..|.")
69
+ expect(obfuscator.obfuscated_input).to eq "2/1A|B/2|A1/A|1A1|C|2A|A3|1A2|1"
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+
76
+ end
@@ -0,0 +1 @@
1
+ require_relative '../lib/morse_me_nicely'
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: morse_me_nicely
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dominik Sito
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-08-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.19'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.19'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '12.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '12.0'
55
+ description: A simple gem to encode and obfuscate text input using morse code
56
+ email: dominik.sito@gmail.com
57
+ executables:
58
+ - morse_me_nicely
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - Gemfile
63
+ - Gemfile.lock
64
+ - Rakefile
65
+ - bin/morse_me_nicely
66
+ - data/morse_reference.yml
67
+ - lib/morse_me_nicely.rb
68
+ - lib/morse_me_nicely/cli.rb
69
+ - lib/morse_me_nicely/encoder.rb
70
+ - lib/morse_me_nicely/obfuscator.rb
71
+ - spec/morse_me_nicely/encoder_spec.rb
72
+ - spec/morse_me_nicely/obfuscator_spec.rb
73
+ - spec/spec_helper.rb
74
+ homepage: https://github.com/railis/morse_me_nicely
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.5.2
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: Morse Me Nicely!
98
+ test_files:
99
+ - spec/morse_me_nicely/encoder_spec.rb
100
+ - spec/morse_me_nicely/obfuscator_spec.rb
101
+ - spec/spec_helper.rb