twisty_puzzles 0.0.9 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3dfb23949825572c531ac7bfcea491151629f8673160605069b1793a827d961a
4
- data.tar.gz: f343cc589e99ac129717f47a7b3dbe4dcb3d4a0cbcae2e0f8c42b12b22ad842c
3
+ metadata.gz: 20cf60d5066716b3eaa148e33f1e8c598387573170e1005d034f3128e6b971cb
4
+ data.tar.gz: 2770afd2a3a625f281089401c2a2ef47a6c61843d09026e9d999ee79139fe54e
5
5
  SHA512:
6
- metadata.gz: 2fc20aef94e333318c53ee292b5418424ad8880cc2f8ff18c2102d0799d96728ccc9a98869269bf9c6a046174dcf5f71182cf6498021838d8772c18a7008cfe2
7
- data.tar.gz: b79344d44bf6fd32cd9443c79405dcab052867a746e23fecc0b1496bd96b36fc6c4dd09d2a8c3d33389d7e5b5daaf0ca4a0552cce8948c59ac590da458c6150d
6
+ metadata.gz: 2bdf4691d6efea522b259510bcdb405820784870566948d47b653c91e2d8ca495d9946e17f0d9f703ee234bf0758b3a59969dc52e4f91eafa94659c624ac3930
7
+ data.tar.gz: b28d42481604cbec6b748b025a3293eed64e2c7a90b0e6186c6eadeed63352f81b562e835f54bf6b4fbc9905bf047c917b269896c5504628c7d9c7352c1b70ec
@@ -143,6 +143,10 @@ module TwistyPuzzles
143
143
  prepend_slice_move(other, cube_size)
144
144
  end
145
145
 
146
+ def prepend_slice_move(_other, _cube_size)
147
+ raise NotImplementedError, "#{self.class}#prepend_slice_move is not implemented"
148
+ end
149
+
146
150
  private
147
151
 
148
152
  def move_count_internal(metric, slice_factor, direction_factor)
@@ -31,14 +31,14 @@ module TwistyPuzzles
31
31
  def parse_move(move_string)
32
32
  match = move_string.match(regexp)
33
33
  if !match || !match.pre_match.empty? || !match.post_match.empty?
34
- raise ArgumentError("Invalid move #{move_string}.")
34
+ raise ArgumentError, "Invalid move #{move_string}."
35
35
  end
36
36
 
37
37
  parsed_parts = parse_named_captures(match)
38
38
  move_type_creators.each do |parser|
39
39
  return parser.create(parsed_parts) if parser.applies_to?(parsed_parts)
40
40
  end
41
- raise "No move type creator applies to #{parsed_parts}"
41
+ raise ArgumentError, "No move type creator applies to #{parsed_parts}"
42
42
  end
43
43
  end
44
44
  end
@@ -4,28 +4,36 @@ require 'twisty_puzzles/cube_direction'
4
4
  require 'twisty_puzzles/rotation'
5
5
 
6
6
  module TwistyPuzzles
7
- AlgorithmTransformation =
8
- Struct.new(:rotation, :mirror, :mirror_normal_face) do
9
- def transformed(algorithm)
10
- algorithm = algorithm.mirror(mirror_normal_face) if mirror
11
- algorithm.rotate_by(rotation)
12
- end
7
+ # A transformation consisting of mirroring and rotating that can be applied to an algorithm.
8
+ class AlgorithmTransformation
9
+ def initialize(rotation, mirror, mirror_normal_face)
10
+ @rotation = rotation
11
+ @mirror = mirror
12
+ @mirror_normal_face = mirror_normal_face
13
+ end
13
14
 
14
- def identity?
15
- rotation.identity? && !mirror
16
- end
15
+ attr_reader :rotation, :mirror, :mirror_normal_face
17
16
 
18
- # Returns algorithm transformations that mirror an algorithm and rotate it around a face.
19
- def self.around_face(face)
20
- around_face_rotations = CubeDirection::ALL_DIRECTIONS.map { |d| Rotation.new(face, d) }
21
- mirror_normal_face = face.neighbors.first
22
- around_face_rotations.product([true, false]).map do |r, m|
23
- AlgorithmTransformation.new(r, m, mirror_normal_face)
24
- end
25
- end
17
+ def transformed(algorithm)
18
+ algorithm = algorithm.mirror(mirror_normal_face) if mirror
19
+ algorithm.rotate_by(rotation)
20
+ end
26
21
 
27
- def self.around_face_without_identity(face)
28
- around_face(face).reject(&:identity?)
22
+ def identity?
23
+ rotation.identity? && !mirror
24
+ end
25
+
26
+ # Returns algorithm transformations that mirror an algorithm and rotate it around a face.
27
+ def self.around_face(face)
28
+ around_face_rotations = CubeDirection::ALL_DIRECTIONS.map { |d| Rotation.new(face, d) }
29
+ mirror_normal_face = face.neighbors.first
30
+ around_face_rotations.product([true, false]).map do |r, m|
31
+ AlgorithmTransformation.new(r, m, mirror_normal_face)
29
32
  end
30
33
  end
34
+
35
+ def self.around_face_without_identity(face)
36
+ around_face(face).reject(&:identity?)
37
+ end
38
+ end
31
39
  end
@@ -55,7 +55,9 @@ module TwistyPuzzles
55
55
  self
56
56
  else
57
57
  rotation_neighbors = rotation.axis_face.neighbors
58
- face_index = rotation_neighbors.index(@axis_face) || raise
58
+ face_index = rotation_neighbors.index(@axis_face)
59
+ raise unless face_index
60
+
59
61
  new_axis_face =
60
62
  rotation_neighbors[(face_index + rotation.direction.value) % rotation_neighbors.length]
61
63
  fields = replace_once(identifying_fields, @axis_face, new_axis_face)
@@ -37,7 +37,7 @@ module TwistyPuzzles
37
37
  end
38
38
 
39
39
  def part_for_colors(part_type, colors)
40
- raise ArgumentError unless part_type.is_a?(Class)
40
+ raise ArgumentError unless part_type.is_a?(Class) && (part_type < Part)
41
41
 
42
42
  part_type.for_face_symbols(colors.map { |c| face_symbol(c) })
43
43
  end
@@ -95,10 +95,12 @@ module TwistyPuzzles
95
95
 
96
96
  def chirality_corner_source_and_unknown_index(obvious_turned_face_symbols_to_colors)
97
97
  corner_matcher =
98
- CornerMatcher.new(CHIRALITY_FACE_SYMBOLS.map do |s|
99
- # This will return nil for exactly one face that we don't know yet.
100
- @colors_to_face_symbols[obvious_turned_face_symbols_to_colors[s]]
101
- end)
98
+ CornerMatcher.new(
99
+ CHIRALITY_FACE_SYMBOLS.map do |s|
100
+ # This will return nil for exactly one face that we don't know yet.
101
+ @colors_to_face_symbols[obvious_turned_face_symbols_to_colors[s]]
102
+ end
103
+ )
102
104
 
103
105
  # There should be exactly one corner that gets mapped to the chirality corner.
104
106
  chirality_corner_source =
@@ -141,7 +143,7 @@ module TwistyPuzzles
141
143
  "Color #{c} cannot be part of the color scheme because it is a reserved color."
142
144
  end
143
145
  end
144
- raise ArgumentError unless face_symbols_to_colors.values.all? { |c| c.is_a?(Symbol) }
146
+ raise ArgumentError unless face_symbols_to_colors.values.all?(Symbol)
145
147
  end
146
148
 
147
149
  def add_missing_mappings(turned_face_symbols_to_colors, chirality_corner_source, unknown_index)
@@ -10,6 +10,10 @@ module TwistyPuzzles
10
10
  def cancellations(other, cube_size, metric = :htm)
11
11
  algorithm.cancellations(other.algorithm, cube_size, metric)
12
12
  end
13
+
14
+ def algorithm
15
+ raise NotImplementedError
16
+ end
13
17
  end
14
18
 
15
19
  # Algorithm that is used like a commutator but actually isn't one.
@@ -28,7 +28,7 @@ module TwistyPuzzles
28
28
 
29
29
  # Middle coordinate for uneven numbers, the one before for even numbers
30
30
  def self.middle_or_before(cube_size)
31
- cube_size - cube_size / 2 - 1
31
+ cube_size - (cube_size / 2) - 1
32
32
  end
33
33
 
34
34
  # Middle coordinate for uneven numbers, the one after for even numbers
@@ -38,7 +38,7 @@ module TwistyPuzzles
38
38
 
39
39
  # The last coordinate that is strictly before the middle
40
40
  def self.last_before_middle(cube_size)
41
- cube_size / 2 - 1
41
+ (cube_size / 2) - 1
42
42
  end
43
43
 
44
44
  def self.canonicalize(index, cube_size)
@@ -310,7 +310,7 @@ module TwistyPuzzles
310
310
 
311
311
  def self.for_corner(corner)
312
312
  native = Native::SkewbCoordinate.for_corner(corner.face_symbols)
313
- new(Face.for_face_symbol(corner.face_symbols.first), 1 + corner.piece_index % 4, native)
313
+ new(Face.for_face_symbol(corner.face_symbols.first), 1 + (corner.piece_index % 4), native)
314
314
  end
315
315
 
316
316
  def hash
@@ -34,6 +34,14 @@ module TwistyPuzzles
34
34
 
35
35
  attr_reader :piece_index, :face_symbols
36
36
 
37
+ def self.min_parseable_face_symbols
38
+ self::FACES
39
+ end
40
+
41
+ def self.max_parseable_face_symbols
42
+ self::FACES
43
+ end
44
+
37
45
  def self.generate_parts
38
46
  valid_face_symbol_combinations =
39
47
  FACE_SYMBOLS.permutation(self::FACES).select do |p|
@@ -64,10 +72,18 @@ module TwistyPuzzles
64
72
  true
65
73
  end
66
74
 
75
+ def num_incarnations(_cube_size)
76
+ 1
77
+ end
78
+
67
79
  def base_index_on_face(cube_size, incarnation_index)
68
80
  base_index_on_other_face(solved_face, cube_size, incarnation_index)
69
81
  end
70
82
 
83
+ def base_index_on_other_face(face, cube_size, incarnation_index)
84
+ raise NotImplementedError
85
+ end
86
+
71
87
  def self.for_face_symbols_internal(face_symbols)
72
88
  raise unless face_symbols.length == self::FACES
73
89
 
@@ -82,6 +98,10 @@ module TwistyPuzzles
82
98
  self::ELEMENTS[index]
83
99
  end
84
100
 
101
+ def self.valid?(_face_symbols)
102
+ false
103
+ end
104
+
85
105
  def <=>(other)
86
106
  @piece_index <=> other.piece_index
87
107
  end
@@ -110,7 +130,7 @@ module TwistyPuzzles
110
130
  # Rotate a piece such that the given face symbol is the first face symbol.
111
131
  def rotate_face_symbol_up(face_symbol)
112
132
  index = @face_symbols.index(face_symbol)
113
- raise "Part #{self} doesn't have face symbol #{c}." unless index
133
+ raise "Part #{self} doesn't have face symbol #{face_symbol}." unless index
114
134
 
115
135
  rotate_by(index)
116
136
  end
@@ -133,13 +153,9 @@ module TwistyPuzzles
133
153
  (0...@face_symbols.length).map { |i| rotate_by(i) }
134
154
  end
135
155
 
136
- def self.create_for_face_symbols(face_symbols)
137
- new(face_symbols)
138
- end
139
-
140
156
  def self.parse(piece_description)
141
157
  face_symbols =
142
- piece_description.upcase.strip.split('').map do |e|
158
+ piece_description.upcase.strip.chars.map do |e|
143
159
  FACE_SYMBOLS[FACE_NAMES.index(e)]
144
160
  end
145
161
  for_face_symbols(face_symbols)
@@ -319,6 +335,14 @@ module TwistyPuzzles
319
335
  class MoveableCenter < Part
320
336
  FACES = 1
321
337
 
338
+ def self.min_parseable_face_symbols
339
+ self::CORRESPONDING_PART_CLASS::FACES
340
+ end
341
+
342
+ def self.max_parseable_face_symbols
343
+ self::CORRESPONDING_PART_CLASS::FACES
344
+ end
345
+
322
346
  def self.min_cube_size
323
347
  4
324
348
  end
@@ -338,10 +362,6 @@ module TwistyPuzzles
338
362
  find_only(self::ELEMENTS) { |e| e.corresponding_part == corresponding_part }
339
363
  end
340
364
 
341
- def self.create_for_face_symbols(face_symbols)
342
- new(self::CORRESPONDING_PART_CLASS.create_for_face_symbols(face_symbols))
343
- end
344
-
345
365
  def face_symbol
346
366
  @face_symbols[0]
347
367
  end
@@ -463,11 +483,15 @@ module TwistyPuzzles
463
483
  false
464
484
  end
465
485
 
486
+ def self.max_parseable_face_symbols
487
+ FACES + 1
488
+ end
489
+
466
490
  def self.for_face_symbols(face_symbols)
467
491
  # One additional face symbol is usually mentioned for wings.
468
492
  raise unless face_symbols.length == FACES || face_symbols.length == FACES + 1
469
493
 
470
- if face_symbols.length == 3
494
+ if face_symbols.length == FACES + 1
471
495
  for_corner_face_symbols(face_symbols)
472
496
  else
473
497
  for_face_symbols_internal(face_symbols)
@@ -514,7 +538,7 @@ module TwistyPuzzles
514
538
  end
515
539
 
516
540
  def num_incarnations(cube_size)
517
- [cube_size / 2 - 1, 0].max
541
+ cube_size > 3 ? (cube_size / 2) - 1 : 0
518
542
  end
519
543
 
520
544
  # One index of such a piece on a on a NxN face.
@@ -530,14 +554,6 @@ module TwistyPuzzles
530
554
  class Corner < Part
531
555
  FACES = 3
532
556
 
533
- def self.create_for_face_symbols(face_symbols)
534
- piece_candidates =
535
- face_symbols[1..].permutation.map do |cs|
536
- new([face_symbols[0]] + cs)
537
- end
538
- find_only(piece_candidates, &:valid?)
539
- end
540
-
541
557
  def self.for_face_symbols(face_symbols)
542
558
  unless face_symbols.length == FACES
543
559
  raise "Invalid number of face_symbols to create a corner: #{face_symbols.inspect}"
@@ -621,7 +637,7 @@ module TwistyPuzzles
621
637
  ELEMENTS = generate_parts
622
638
 
623
639
  def num_incarnations(cube_size)
624
- [cube_size / 2 - 1, 0].max
640
+ cube_size > 3 ? (cube_size / 2) - 1 : 0
625
641
  end
626
642
 
627
643
  # One index of such a piece on a on a NxN face.
@@ -644,10 +660,10 @@ module TwistyPuzzles
644
660
  end
645
661
 
646
662
  def num_incarnations(cube_size)
647
- if cube_size.even?
663
+ if cube_size.even? || cube_size <= 3
648
664
  0
649
665
  else
650
- [cube_size / 2 - 1, 0].max
666
+ (cube_size / 2) - 1
651
667
  end
652
668
  end
653
669
 
@@ -68,8 +68,8 @@ module TwistyPuzzles
68
68
 
69
69
  def equivalent_slice_move?(other, cube_size)
70
70
  cube_size == 3 && other.slice_index == 1 &&
71
- (@axis_face == other.axis_face && @direction == other.direction ||
72
- @axis_face == other.axis_face.opposite && @direction == other.direction.inverse)
71
+ ((@axis_face == other.axis_face && @direction == other.direction) ||
72
+ (@axis_face == other.axis_face.opposite && @direction == other.direction.inverse))
73
73
  end
74
74
  end
75
75
 
@@ -72,9 +72,9 @@ module TwistyPuzzles
72
72
  def skewb_ascii_art_line(first_color, middle_color, last_color, num_first_color)
73
73
  raise if num_first_color > SKEWB_FACE_SIZE / 2
74
74
 
75
- first_color * num_first_color +
76
- middle_color * (SKEWB_FACE_SIZE - 2 * num_first_color) +
77
- last_color * num_first_color
75
+ (first_color * num_first_color) +
76
+ (middle_color * (SKEWB_FACE_SIZE - (2 * num_first_color))) +
77
+ (last_color * num_first_color)
78
78
  end
79
79
 
80
80
  def skewb_ascii_art(center_color, corner_colors)
@@ -116,7 +116,7 @@ module TwistyPuzzles
116
116
  front_face = face_lines(cube_state, :F, 1, 3) { |c| color_character(c, color_mode) }
117
117
  right_face = face_lines(cube_state, :R, 1, 3) { |c| color_character(c, color_mode) }
118
118
  pll_line = front_face.first + right_face.first
119
- (top_face + [pll_line] * 3).join("\n")
119
+ (top_face + ([pll_line] * 3)).join("\n")
120
120
  end
121
121
 
122
122
  def cube_string(cube_state, color_mode)
@@ -150,7 +150,7 @@ module TwistyPuzzles
150
150
  end
151
151
 
152
152
  def pad_lines(lines, padding)
153
- lines.map { |line| empty_name * padding + line }
153
+ lines.map { |line| (empty_name * padding) + line }
154
154
  end
155
155
 
156
156
  def zip_concat_lines(*args)
@@ -75,6 +75,16 @@ module TwistyPuzzles
75
75
 
76
76
  alias == eql?
77
77
 
78
+ def rotation_algorithms
79
+ Rotation::ALL_ROTATIONS.combination(2).reject do |r0, r1|
80
+ r0.inverse == r1
81
+ end.map { |rs| Algorithm.new(rs) } # rubocop:disable Style/MultilineBlockChain
82
+ end
83
+
84
+ def equal_modulo_rotations?(other)
85
+ rotation_algorithms.any? { |r| r.apply_temporarily_to(self) { |state| state == other } }
86
+ end
87
+
78
88
  def hash
79
89
  @hash ||= [self.class, @native].hash
80
90
  end
@@ -6,7 +6,7 @@ module TwistyPuzzles
6
6
  class MoveTypeCreator
7
7
  def initialize(capture_keys, move_class)
8
8
  raise TypeError unless move_class.is_a?(Class)
9
- raise TypeError unless capture_keys.all? { |k| k.is_a?(Symbol) }
9
+ raise TypeError unless capture_keys.all?(Symbol)
10
10
 
11
11
  @capture_keys = capture_keys.freeze
12
12
  @move_class = move_class
@@ -77,8 +77,8 @@ module TwistyPuzzles # rubocop:disable Style/Documentation
77
77
  end
78
78
 
79
79
  # Parses at least one move.
80
- def parse_nonempty_moves
81
- moves = parse_moves
80
+ def parse_nonempty_moves_with_triggers
81
+ moves = parse_moves_with_triggers
82
82
  complain('move') if moves.empty?
83
83
  moves
84
84
  end
@@ -117,10 +117,26 @@ module TwistyPuzzles # rubocop:disable Style/Documentation
117
117
  if @scanner.peek(1) == OPENING_BRACKET
118
118
  parse_commutator_internal
119
119
  else
120
- FakeCommutator.new(parse_moves_with_triggers)
120
+ parse_commutator_no_brackets
121
121
  end
122
122
  end
123
123
 
124
+ def parse_commutator_no_brackets
125
+ setup_or_first_part_or_algorithm = parse_moves_with_triggers
126
+ skip_spaces
127
+ if @scanner.eos? || !SEPARATORS.include?(@scanner.peek(1))
128
+ return FakeCommutator.new(setup_or_first_part_or_algorithm)
129
+ end
130
+
131
+ setup_or_first_part = setup_or_first_part_or_algorithm
132
+ complain('move') if setup_or_first_part.empty?
133
+ separator = parse_separator
134
+ comm = parse_commutator_internal_after_separator(setup_or_first_part, separator)
135
+ skip_spaces
136
+ complain('end of commutator') unless @scanner.eos?
137
+ comm
138
+ end
139
+
124
140
  def parse_algorithm
125
141
  skip_spaces
126
142
  parse_moves_with_triggers
@@ -131,40 +147,67 @@ module TwistyPuzzles # rubocop:disable Style/Documentation
131
147
  if @scanner.peek(1) == OPENING_BRACKET
132
148
  parse_pure_commutator
133
149
  else
134
- FakeCommutator.new(parse_moves_with_triggers)
150
+ parse_pure_commutator_no_brackets
135
151
  end
136
152
  end
137
153
 
138
154
  def parse_pure_commutator
139
155
  skip_spaces
140
156
  parse_open_bracket
141
- first_part = parse_nonempty_moves
157
+ first_part = parse_nonempty_moves_with_triggers
142
158
  skip_spaces
143
- complain('middle of pure commutator') unless @scanner.getch == ','
144
- second_part = parse_nonempty_moves
159
+ parse_comma
160
+ second_part = parse_nonempty_moves_with_triggers
145
161
  skip_spaces
146
162
  parse_close_bracket
147
163
  PureCommutator.new(first_part, second_part)
148
164
  end
149
165
 
166
+ def parse_pure_commutator_no_brackets
167
+ first_part_or_algorithm = parse_moves_with_triggers
168
+ skip_spaces
169
+ if @scanner.eos? || !@scanner.peek(1) == ','
170
+ return FakeCommutator.new(first_part_or_algorithm)
171
+ end
172
+
173
+ first_part = first_part_or_algorithm
174
+ complain('move') if first_part.empty?
175
+ parse_comma
176
+ second_part = parse_nonempty_moves_with_triggers
177
+ skip_spaces
178
+ PureCommutator.new(first_part, second_part)
179
+ end
180
+
181
+ def parse_comma
182
+ complain('middle of pure commutator') unless @scanner.getch == ','
183
+ end
184
+
150
185
  def parse_commutator_internal_after_separator(setup_or_first_part, separator)
151
186
  if [':', ';'].include?(separator)
152
187
  inner_commutator = parse_setup_commutator_inner
153
188
  SetupCommutator.new(setup_or_first_part, inner_commutator)
154
189
  elsif separator == ','
155
- second_part = parse_nonempty_moves
190
+ second_part = parse_nonempty_moves_with_triggers
156
191
  PureCommutator.new(setup_or_first_part, second_part)
157
192
  else
158
193
  complain('end of setup or middle of pure commutator') unless @scanner.eos?
159
194
  end
160
195
  end
161
196
 
197
+ SEPARATORS = %w[; : ,].freeze
198
+
199
+ def parse_separator
200
+ separator = @scanner.getch
201
+ complain('separator between commutator parts') unless SEPARATORS.include?(separator)
202
+ separator
203
+ end
204
+
162
205
  def parse_commutator_internal
163
206
  skip_spaces
164
207
  parse_open_bracket
165
- setup_or_first_part = parse_nonempty_moves
208
+ setup_or_first_part = parse_nonempty_moves_with_triggers
166
209
  skip_spaces
167
- separator = @scanner.getch
210
+ separator = parse_separator
168
211
  comm = parse_commutator_internal_after_separator(setup_or_first_part, separator)
169
212
  skip_spaces
170
213
  parse_close_bracket
@@ -35,10 +35,12 @@ module TwistyPuzzles
35
35
 
36
36
  direction = translated_direction(skewb_direction)
37
37
 
38
- Algorithm.new([
39
- Rotation.new(corner.faces[skewb_direction.value], direction),
40
- Rotation.new(corner.faces[0], direction)
41
- ])
38
+ Algorithm.new(
39
+ [
40
+ Rotation.new(corner.faces[skewb_direction.value], direction),
41
+ Rotation.new(corner.faces[0], direction)
42
+ ]
43
+ )
42
44
  end
43
45
 
44
46
  def to_s
@@ -26,10 +26,12 @@ module TwistyPuzzles
26
26
  next unless c2.face_symbols.include?(c1_rot.face_symbols.first)
27
27
 
28
28
  c2_rot = c2.rotate_face_symbol_up(c1_rot.face_symbols.first)
29
- check_parts.push([
30
- SkewbCoordinate.for_corner(c1_rot),
31
- SkewbCoordinate.for_corner(c2_rot)
32
- ])
29
+ check_parts.push(
30
+ [
31
+ SkewbCoordinate.for_corner(c1_rot),
32
+ SkewbCoordinate.for_corner(c2_rot)
33
+ ]
34
+ )
33
35
  end
34
36
  matching_corners.push(check_parts)
35
37
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TwistyPuzzles
4
- VERSION = '0.0.9'
4
+ VERSION = '0.0.13'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twisty_puzzles
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernhard F. Brodowsky
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-21 00:00:00.000000000 Z
11
+ date: 2021-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize