stroop 1.0.0 → 1.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 964e287156e79b56d6b6210bf1b7a5934e38e6178352904e23c7d8d84206a193
4
- data.tar.gz: 3d6648046d0ecb62ec85da53f102910a07c7ddd855bc0174ee2507baca328fba
3
+ metadata.gz: 733eff782edc5ce54cc80b6bf947eefb79ee5d6f04bb1d2ef84ad9229e223c40
4
+ data.tar.gz: e2b826afb1dbdd6b90f90e992765a0eace4e82bb66940cb1cf28995567ef01bb
5
5
  SHA512:
6
- metadata.gz: a45e2802db6fe67fe7adb3e3d7690142b994c0548fecf2fdbf21b04c1bf95a54d69db4272d60c0926578070b961f82c3faf71e828db8dfc8b857b11b992744ed
7
- data.tar.gz: d49000f0bcc7ccb7677a953d8a3788fcacbd9b9f6e94c5863d55111c2eb244af26b88c112c01f3504835dca011fabe9d6a365e3e91bd1b4d94c0fce14554baf2
6
+ metadata.gz: '0822ec8086aafb19daf6708be6898103902e0a75251de66faed092a2171598e1c141c02acded3d33c3543ffc79827869547e1d0a2d63c4e6319a76017f3c2349'
7
+ data.tar.gz: 3d3b2e43a6de919e2a63e4ddc259a19279d5dda2b8283218cebfe3211bd5ff8633e8e8136b0ad89413d893c164c00d873eb522eb6c6013dcce05c830f0d11d12
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+ - A `seed:` keyword argument for `Stroop::Set`
12
+ - `--seed`/`-s` CLI option to pass a random seed which is used to generate the color words
13
+
10
14
  ## [1.0.0] - 2020-05-21
11
15
  ### Removed
12
16
  - Drop support for Ruby <= v2.4
data/README.md CHANGED
@@ -39,6 +39,16 @@ This will print you a Stroop test of 10 lines of words with 5 words in each of t
39
39
 
40
40
  You can adjust the rows and columns of words by changing the `CxR` param as you like (e.g. `5x2`). If you leave it out a default of `5x10` is used.
41
41
 
42
+ For each print out you will find the random seed that was used to generate the color words.
43
+
44
+ You can also pass a seed by using the `--seed` or `-s` option:
45
+
46
+ ```bash
47
+ $ stroop neutral --seed=1234
48
+ $ stroop congruent -s 1234
49
+ $ stroop incongruent -s 1234
50
+ ```
51
+
42
52
  If you want to use Stroop in Ruby you can run the following code:
43
53
 
44
54
  ```ruby
@@ -47,6 +57,10 @@ require 'stroop'
47
57
  # adjust rows and columns to whatever you like
48
58
  set = Stroop::Set.new(columns: 5, rows: 10, mode: Stroop::Set::NEUTRAL)
49
59
  set.to_s # => returns the string of colorized words
60
+
61
+ # or if you want to pass a specific random seed that is used to generate the set:
62
+ set = Stroop::Set.new(columns: 5, rows: 10, mode: Stroop::Set::NEUTRAL, seed: 1234)
63
+ set.seed # => returns the random seed that was used to create the color words
50
64
  ```
51
65
 
52
66
  The available Stroop::Set modes are:
@@ -5,29 +5,32 @@ module Stroop
5
5
  class CLI < Thor
6
6
  DEFAULT_SIZE = 5.freeze
7
7
 
8
+ class_option :seed, type: :numeric, aliases: "-s", description: "The random seed to generate the color words"
9
+
8
10
  desc 'neutral COLSxROWS', 'prints neutral color words in COLS columns and ROWS rows'
9
11
  def neutral(size = '10x5')
10
- print(size: size, mode: Set::NEUTRAL)
12
+ print(size: size, mode: Set::NEUTRAL, seed: options[:seed])
11
13
  end
12
14
 
13
15
  desc 'congruent COLSxROWS', 'prints congruent color words in COLS columns and ROWS rows'
14
16
  def congruent(size = '10x5')
15
- print(size: size, mode: Set::CONGRUENT)
17
+ print(size: size, mode: Set::CONGRUENT, seed: options[:seed])
16
18
  end
17
19
 
18
20
  desc 'incongruent COLSxROWS', 'prints incongruent color words in COLS columns and ROWS rows'
19
21
  def incongruent(size = '10x5')
20
- print(size: size, mode: Set::INCONGRUENT)
22
+ print(size: size, mode: Set::INCONGRUENT, seed: options[:seed])
21
23
  end
22
24
 
23
25
  private
24
26
 
25
- def print(size:, mode:)
27
+ def print(size:, mode:, seed:)
26
28
  rows, columns = dimensions(size)
27
29
  rows = apply_default_size(rows)
28
30
  columns = apply_default_size(columns)
29
31
 
30
- puts Set.new(rows: rows, columns: columns, mode: mode).to_s
32
+ set = Stroop::Set.new(rows: rows, columns: columns, mode: mode, seed: seed)
33
+ puts set, "🌱 Generated with seed: #{set.seed}"
31
34
  end
32
35
 
33
36
  def dimensions(size)
@@ -0,0 +1,41 @@
1
+ module Stroop
2
+ class ColorGenerator
3
+ COLORS = %w{ black white red green blue yellow }.freeze
4
+
5
+ attr_reader :seed
6
+
7
+ def initialize(seed: nil)
8
+ @seed = seed || Random.new_seed
9
+ @single_random = Random.new(@seed)
10
+ @pair_random = Random.new(@seed)
11
+ end
12
+
13
+ def generate
14
+ selected = random_select(@single_random)
15
+
16
+ while selected == @last_generated do
17
+ selected = random_select(@single_random)
18
+ end
19
+
20
+ @last_generated = selected
21
+ end
22
+
23
+ def generate_pair
24
+ first = generate
25
+ second = random_select(@pair_random)
26
+
27
+ while first == second || second == @last_generated_second do
28
+ second = random_select(@pair_random)
29
+ end
30
+
31
+ @last_generated_second = second
32
+ [first, second]
33
+ end
34
+
35
+ private
36
+
37
+ def random_select(random)
38
+ COLORS.sample(random: random)
39
+ end
40
+ end
41
+ end
@@ -1,10 +1,9 @@
1
1
  require 'colorize'
2
2
  require_relative 'exceptions'
3
+ require_relative 'color_generator'
3
4
 
4
5
  module Stroop
5
6
  class Set
6
- COLORS = %w{ black white red green blue yellow }.freeze
7
-
8
7
  NEUTRAL = :neutral
9
8
  CONGRUENT = :congruent
10
9
  INCONGRUENT = :incongruent
@@ -20,14 +19,16 @@ module Stroop
20
19
  bottom_right: "┘"
21
20
  }.transform_values(&:light_black).freeze
22
21
 
23
- attr_reader :rows, :columns, :mode
22
+ attr_reader :rows, :columns, :mode, :seed
24
23
 
25
- def initialize(rows:, columns:, mode:)
24
+ def initialize(rows:, columns:, mode:, seed: nil)
26
25
  raise SetModeNotAvailable.new unless MODES.include?(mode)
27
26
 
28
- @rows = rows.to_i.abs
27
+ @rows = rows.to_i.abs
29
28
  @columns = columns.to_i.abs
30
- @mode = mode.to_sym
29
+ @mode = mode.to_sym
30
+ @generator = ColorGenerator.new(seed: seed)
31
+ @seed = @generator.seed
31
32
  end
32
33
 
33
34
  def to_s
@@ -65,37 +66,20 @@ module Stroop
65
66
  def word_color_pair
66
67
  case mode
67
68
  when :neutral
68
- word = random_color
69
+ word = @generator.generate
69
70
  color = :black
70
71
  when :congruent
71
- word = random_color
72
+ word = @generator.generate
72
73
  color = word
73
74
  when :incongruent
74
- word, color = random_different_colors
75
+ word, color = @generator.generate_pair
75
76
  end
76
77
 
77
78
  [word, color]
78
79
  end
79
80
 
80
- def random_different_colors
81
- first = random_color
82
- second = random_color
83
-
84
- while first == second
85
- second = random_color
86
- end
87
-
88
- [first, second]
89
- end
90
-
91
- def random_color
92
- color = COLORS.sample
93
- color = random_color if color == @latest_random_color
94
- @latest_random_color = color
95
- end
96
-
97
81
  def max_word_length
98
- @max_word_length ||= COLORS.map { |color| color.chars.count }.max
82
+ @max_word_length ||= ColorGenerator::COLORS.map { |color| color.chars.count }.max
99
83
  end
100
84
 
101
85
  def total_word_width
@@ -1,5 +1,5 @@
1
1
  module Stroop
2
- VERSION = "1.0.0".freeze
2
+ VERSION = "1.1.0".freeze
3
3
  end
4
4
 
5
5
 
@@ -1,2 +1,15 @@
1
1
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
2
  require 'stroop'
3
+
4
+ def capture(stream)
5
+ begin
6
+ stream = stream.to_s
7
+ eval "$#{stream} = StringIO.new"
8
+ yield
9
+ result = eval("$#{stream}").string
10
+ ensure
11
+ eval("$#{stream} = #{stream.upcase}")
12
+ end
13
+
14
+ result
15
+ end
@@ -1,32 +1,35 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Stroop::CLI do
4
+ let(:seed) { 1234 }
4
5
 
5
6
  before do
7
+ allow_any_instance_of(Stroop::Set).to receive(:seed) { seed }
6
8
  allow_any_instance_of(Stroop::Set).to receive(:to_s) { '' }
7
9
  allow($stdout).to receive(:puts) { '' }
8
10
  end
9
11
 
12
+ subject { described_class.new([seed]) }
13
+
10
14
  [:neutral, :congruent, :incongruent].each do |method|
11
15
  it { is_expected.to respond_to method }
12
16
 
13
17
  describe "##{method}" do
14
- let(:size) { '1x1' }
18
+ let(:columns) { 1 }
19
+ let(:rows) { 1 }
20
+ let(:args) { "#{columns}x#{rows}" }
15
21
 
16
- it 'should create a new Stroop::Set' do
17
- expect(Stroop::Set).to receive(:new).once
18
- subject.send(method, size)
22
+ it 'prints to the standard output' do
23
+ expect { subject.send(method, args) }.to output.to_stdout
19
24
  end
20
25
 
21
- it 'should convert the Stroop::Set to a string' do
22
- expect_any_instance_of(Stroop::Set).to receive(:to_s).once
23
- subject.send(method, size)
24
- end
26
+ it 'prints the stroop set' do
27
+ set = Stroop::Set.new(columns: columns, rows: rows, mode: method, seed: seed)
28
+ output = capture(:stdout) { subject.send(method, args) }
25
29
 
26
- it 'should print to the standard output' do
27
- expect { subject.send(method, size) }.to output.to_stdout
30
+ expect(output).to include set.to_s
31
+ expect(output).to include "Generated with seed: #{seed}"
28
32
  end
29
33
  end
30
34
  end
31
-
32
35
  end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Stroop::ColorGenerator do
4
+ describe 'without seed' do
5
+ subject { described_class.new }
6
+
7
+ describe '#generate' do
8
+ it 'returns a random color' do
9
+ expect(Stroop::ColorGenerator::COLORS).to include subject.generate
10
+ end
11
+ end
12
+
13
+ describe '#generate_pair' do
14
+ it 'returns a pair of colors that are different' do
15
+ 20.times do
16
+ first, second = subject.generate_pair
17
+ expect(first).to_not eq second
18
+ end
19
+ end
20
+
21
+ it 'returns another pair in subsequent calls' do
22
+ previous_colors = subject.generate_pair
23
+
24
+ 20.times do
25
+ new_colors = subject.generate_pair
26
+ expect(new_colors).to_not eq previous_colors
27
+ previous_colors = new_colors
28
+ end
29
+ end
30
+ end
31
+
32
+ describe 'with seed' do
33
+ let(:seed) { 1234 }
34
+ let(:generator) { described_class.new(seed: seed) }
35
+ let(:other_generator) { described_class.new(seed: seed) }
36
+
37
+ describe '#generate' do
38
+ it 'uses the given seed to generate colors deterministically' do
39
+ 20.times { expect(generator.generate).to eq other_generator.generate }
40
+ end
41
+ end
42
+
43
+ describe '#generate_pair' do
44
+ it 'uses the given seed to generate colors deterministically' do
45
+ 20.times { expect(generator.generate_pair).to eq other_generator.generate_pair }
46
+ end
47
+ end
48
+
49
+ it 'generates the same colors for #generate and #generate_pair (first color only)' do
50
+ generated_colors = 20.times.map { generator.generate }
51
+ generated_pairs_first_colors = 20.times.map { other_generator.generate_pair.first }
52
+
53
+ expect(generated_colors).to eq generated_pairs_first_colors
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,51 +1,82 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Stroop::Set do
4
+ [:neutral, :incongruent, :congruent].each do |mode|
5
+ let(:arguments) { {rows: 1, columns: 2, mode: mode } }
6
+ subject { described_class.new(**arguments) }
4
7
 
5
- let(:arguments) { {rows: 1, columns: 2, mode: :neutral } }
6
- subject { described_class.new(**arguments) }
8
+ describe 'creating a new instance' do
9
+ it 'raises an error if the given mode is not available' do
10
+ expect {
11
+ described_class.new(**arguments.merge({ mode: :not_existing }))
12
+ }.to raise_error Stroop::SetModeNotAvailable
13
+ end
7
14
 
8
- describe 'creating a new instance' do
9
- it 'should raise an error if the given mode is not available' do
10
- expect {
11
- described_class.new(**arguments.merge({ mode: :not_existing }))
12
- }.to raise_error Stroop::SetModeNotAvailable
15
+ it 'does not raise an error if the given mode is available' do
16
+ expect {
17
+ described_class.new(**arguments.merge({ mode: :neutral }))
18
+ described_class.new(**arguments.merge({ mode: :congruent }))
19
+ described_class.new(**arguments.merge({ mode: :incongruent }))
20
+ }.not_to raise_error
21
+ end
13
22
  end
14
23
 
15
- it 'should not raise an error if the given mode is available' do
16
- expect {
17
- described_class.new(**arguments.merge({ mode: :neutral }))
18
- described_class.new(**arguments.merge({ mode: :congruent }))
19
- described_class.new(**arguments.merge({ mode: :incongruent }))
20
- }.not_to raise_error
24
+ [:NEUTRAL, :CONGRUENT, :INCONGRUENT, :MODES].each do |name|
25
+ it "has a constant '#{name}'" do
26
+ expect(described_class.constants).to include name
27
+ end
21
28
  end
22
- end
23
29
 
24
- [:NEUTRAL, :CONGRUENT, :INCONGRUENT, :COLORS, :MODES].each do |name|
25
- it "should have a constant '#{name}'" do
26
- expect(described_class.constants).to include name
30
+ [:rows, :columns, :mode, :seed].each do |method|
31
+ it "responds to ##{method}" do
32
+ expect(subject).to respond_to method
33
+ end
27
34
  end
28
- end
29
35
 
30
- [:rows, :columns, :mode].each do |method|
31
- it "should respond to ##{method}" do
32
- expect(subject).to respond_to method
33
- end
34
- end
36
+ describe '#to_s' do
37
+ it 'returns a text with the instantiated number of lines' do
38
+ actual_rows = subject.to_s.lines.count
39
+ expected_rows = subject.rows + 2 # 2 wrapping empty lines (first & last)
35
40
 
36
- it 'should return a text with the instantiated number of lines' do
37
- actual_rows = subject.to_s.lines.count
38
- expected_rows = subject.rows + 2 # 2 wrapping empty lines (first & last)
41
+ expect(actual_rows).to eq expected_rows
42
+ end
39
43
 
40
- expect(actual_rows).to eq expected_rows
41
- end
44
+ it 'returns a text with the defined number of words per line' do
45
+ color_regex = /(#{Stroop::ColorGenerator::COLORS.join('|')})/
46
+ line = subject.to_s.lines[1] # first line with words
47
+ words = line.scan(color_regex).flatten
42
48
 
43
- it 'should return a text with the defined number of words per line' do
44
- color_regex = /(#{described_class::COLORS.join('|')})/
45
- line = subject.to_s.lines[1] # first line with words
46
- words = line.scan(color_regex).flatten
49
+ expect(words.count).to eq subject.columns
50
+ end
47
51
 
48
- expect(words.count).to eq subject.columns
49
- end
52
+ it 'returns the same text for the same seed' do
53
+ args = arguments.merge(seed: 1234)
54
+ set = described_class.new(**args)
55
+ other_set = described_class.new(**args)
56
+
57
+ expect(set.to_s).to eq other_set.to_s
58
+ end
50
59
 
60
+ it 'returns different texts for the different seeds' do
61
+ set = described_class.new(**arguments.merge(seed: 1))
62
+ other_set = described_class.new(**arguments.merge(seed: 2))
63
+
64
+ expect(set.to_s).to_not eq other_set.to_s
65
+ end
66
+ end
67
+
68
+ describe '#seed' do
69
+ it 'returns the seed the set was initialized with' do
70
+ seed = Random.rand(100)
71
+ args = arguments.merge(seed: seed)
72
+ expect(described_class.new(**args).seed).to eq seed
73
+ end
74
+
75
+ it "returns a random seed if none was given" do
76
+ set = described_class.new(**arguments)
77
+ expect(set.seed).to_not be_nil
78
+ expect(set.seed).to be_a Integer
79
+ end
80
+ end
81
+ end
51
82
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stroop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Götze
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-21 00:00:00.000000000 Z
11
+ date: 2020-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -86,11 +86,13 @@ files:
86
86
  - bin/stroop
87
87
  - lib/stroop.rb
88
88
  - lib/stroop/cli.rb
89
+ - lib/stroop/color_generator.rb
89
90
  - lib/stroop/exceptions.rb
90
91
  - lib/stroop/set.rb
91
92
  - lib/stroop/version.rb
92
93
  - spec/spec_helper.rb
93
94
  - spec/stroop/cli_spec.rb
95
+ - spec/stroop/color_generator_spec.rb
94
96
  - spec/stroop/set_spec.rb
95
97
  - stroop.gemspec
96
98
  homepage: https://github.com/paulgoetze/stroop
@@ -112,11 +114,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
114
  - !ruby/object:Gem::Version
113
115
  version: '0'
114
116
  requirements: []
115
- rubygems_version: 3.0.3
117
+ rubygems_version: 3.1.3
116
118
  signing_key:
117
119
  specification_version: 4
118
120
  summary: Stroop effect
119
121
  test_files:
120
122
  - spec/spec_helper.rb
121
123
  - spec/stroop/cli_spec.rb
124
+ - spec/stroop/color_generator_spec.rb
122
125
  - spec/stroop/set_spec.rb