terminal_game_of_life 1.0.0 → 1.0.5

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: b949e4ff807eb374946cc0c2647f9aa5cf3f79b2427cab818b492ecdbb9a3b24
4
- data.tar.gz: b0e82c40b3c53972f52382728281cc2b83219835ffe1ad65c89f9e446beadf02
3
+ metadata.gz: 2f01833ac38b2fcfb9f8ea6581642e2d95a9f40521d79773178c5499e23a2530
4
+ data.tar.gz: 5f8540b420def7ca4eb0a9371140419bd47489089bed0c5f68f204a266d9946c
5
5
  SHA512:
6
- metadata.gz: 96e1fd3c329a3d775a7d332351303c53a2767857ccef421ad372ec8abbebae7bd4f7d07ae2ad23210cd360d889d21fa7ccafc6c9dc08388a6ffb967dd44afa52
7
- data.tar.gz: 8674f279918813b3cf8c4ee1ed9a2d257c48755a3c06e687a2f5f17cdf6707e85509277042e3176d6eaa5e7c69ae143bc5d4e996572a55fa73900c2bc8e9ac1d
6
+ metadata.gz: 3fbf0db73b5fb37de4b2565813f4ba5ab5500930630fea8151f627b972ed7ef1bdfd95253675da6160451734b9d24d688802e92a36532140b1920fdb4b45d00e
7
+ data.tar.gz: ec4959be702a801f10229c9f85edcd148326d60d919c6b099c1bcd0b06a8f2b1efb24fa225121d14ab28f6239583ab05aacde14c659e74c77ff2262e7b466e8f
data/README.md CHANGED
@@ -9,7 +9,11 @@ $ gem install terminal_game_of_life
9
9
 
10
10
  ## Usage
11
11
 
12
- Run `$game-of-life -i https://gitlab.com/a14m --live-cell +`
12
+ ```bash
13
+ $game-of-life -i https://meta.sr.ht/~a14m.keys --live-cell +
14
+ $game-of-life -i /path/to/file.txt --height 35 --width 35
15
+ $game-of-life -s 1337 --delay 250
16
+ ```
13
17
 
14
18
  Check `game-of-life --help` for usage info.
15
19
 
@@ -26,7 +30,7 @@ Options:
26
30
  [--height=HEIGHT] # Specify the hight of generated universe. (default to terminal height)
27
31
  [--dead-cell=CHAR] # Specify the dead-cell representation
28
32
  # Default:
29
- [--live-cell=CHAR] # Specify the dead-cell representation
33
+ [--live-cell=CHAR] # Specify the live-cell representation
30
34
  # Default: █
31
35
  -d, [--delay=Milli-Seconds] # Specify the introduced delay between each generation
32
36
  # Default: 50
@@ -40,14 +44,15 @@ Options:
40
44
  - Clone the repo.
41
45
  - Navigate to the ruby CLI implementation `cd game-of-life/CLI/ruby`.
42
46
  - run `bundle install` to install dependencies.
43
- - run `bundle rake build` to build the gem/CLI into the `pkg` directory.
44
- - run `bundle rake install` to build and install gem/CLI into system gems.
47
+ - you can run `bundle rake build` to build the gem/CLI into the `pkg` directory.
48
+ - you can run `bundle rake install` to build and install gem/CLI into system gems.
49
+ - you can run `bundle exec ./bin/game-of-life` to run the code for development/testing purposes
45
50
 
46
51
  ## Linting
47
52
  Run `bundle exec rubocop`
48
53
 
49
54
  ## Testing
50
- Run `bundle exec rspec` or `bundle exec rake spec`
55
+ Run `bundle exec rspec`
51
56
 
52
57
  ## Documentation
53
58
  Run `bundle exec yard`
@@ -56,12 +61,12 @@ Run `bundle exec yard`
56
61
  - Update the [version](./lib/game_of_live/version.rb) number
57
62
  - Run `bundle install` and commit changes
58
63
  - Update the [CHANGELOG](./CHANGELOG.md)
59
- - Create a git(lab) tag `ruby/v#{version_number}` ex: `ruby/v0.1.1-pre`
64
+ - Create a git tag `ruby/v#{version_number}` ex: `ruby/v0.1.1-pre`
60
65
 
61
66
  The tag will automatically trigger the release workflow after successful build/test
62
67
  and release the changes to [rubygems.org](https://rubygems.org/gems/terminal_game_of_life)
63
68
 
64
69
  ## Extra information
65
- ### [Contributing](https://gitlab.com/a14m/game-of-life/-/blob/master/CONTRIBUTING.md)
66
- ### [License](https://gitlab.com/a14m/game-of-life/-/blob/master/LICENSE.md)
67
- ### [Code of Conduct](https://gitlab.com/a14m/game-of-life/-/blob/master/CODE_OF_CONDUCT.md)
70
+ ### [Contributing](../../CONTRIBUTING.md)
71
+ ### [License](../../LICENSE.md)
72
+ ### [Code of Conduct](../../CODE_OF_CONDUCT.md)
data/bin/game-of-life CHANGED
@@ -3,13 +3,12 @@
3
3
 
4
4
  require "game_of_life"
5
5
  require "thor"
6
- require "io/console"
7
6
 
8
7
  class CLI < Thor
9
8
  map %w[-v --version] => :version
10
9
  desc "--version, -v", "Prints the Game of Life version information"
11
10
  def version
12
- puts "Game of Life version #{GameOfLife::VERSION}"
11
+ print "Game of Life version #{GameOfLife::VERSION}"
13
12
  end
14
13
 
15
14
  default_task :start
@@ -30,35 +29,14 @@ class CLI < Thor
30
29
  desc: "Specify the dead-cell representation"
31
30
 
32
31
  class_option "live-cell", type: :string, banner: :CHAR, default: "\u2588",
33
- desc: "Specify the dead-cell representation"
32
+ desc: "Specify the live-cell representation"
34
33
 
35
34
  class_option "delay", aliases: "-d", type: :numeric, banner: "Milli-Seconds", default: 50,
36
35
  desc: "Specify the introduced delay between each generation"
37
- # rubocop:disable Metrics/AbcSize
38
- # rubocop:disable Metrics/MethodLength
39
36
  def start
40
- max_height = IO.console.winsize[0] - 2
41
- max_width = IO.console.winsize[1]
42
- if options["width"]&.> max_width
43
- fail GameOfLife::Error, "Invalid --width value, must not exceed current terminal width: #{max_width}"
44
- end
45
- if options["height"]&.> max_height
46
- fail GameOfLife::Error, "Invalid --height value, must not exceed current terminal height: #{max_height}"
47
- end
48
-
49
- options_with_console_defaults = {
50
- # Defaults the hight to less then the height of the terminal to allow banner info
51
- # and an extra emtpy line to avoid triggering terminal scroll while flushing
52
- "height" => max_height,
53
- "width" => max_width,
54
- "seed" => rand(100_000),
55
- }.merge(options)
56
-
57
- universe = GameOfLife.generate(options_with_console_defaults)
37
+ universe = GameOfLife.generate(GameOfLife.parsed_options(options))
58
38
  GameOfLife.run(universe)
59
39
  end
60
- # rubocop:enable Metrics/AbcSize
61
- # rubocop:enable Metrics/MethodLength
62
40
 
63
41
  class << self
64
42
  # Allow exit with status 1 on failure
@@ -72,8 +50,10 @@ end
72
50
  begin
73
51
  CLI.start(ARGV)
74
52
  rescue SystemExit, Interrupt
75
- "Do nothing when user exits with Interrupt (CMD/Ctrl + C)"
53
+ # Print Seed/File used in previous run when user exits with Interrupt (CMD/Ctrl + C)
54
+ print "\e[?1049l"
55
+ print "#{GameOfLife::BANNER}\n\e[0m"
76
56
  rescue NotImplementedError, GameOfLife::Error => e
77
- puts e.message
57
+ print e.message
78
58
  exit(-1)
79
59
  end
data/game_of_life.gemspec CHANGED
@@ -10,15 +10,15 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = "Game of Life CLI"
12
12
  spec.description = "Conway's game of life implementation as a CLI ruby gem."
13
- spec.homepage = "https://gitlab.com/a14m/game-of-life"
13
+ spec.homepage = "https://git.sr.ht/~a14m/game-of-life/tree/master/CLI/ruby/README.md"
14
14
  spec.license = "MIT"
15
15
  spec.required_ruby_version = ">= 2.5.0"
16
16
 
17
17
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
18
18
  spec.metadata["homepage_uri"] = spec.homepage
19
- spec.metadata["source_code_uri"] = "https://gitlab.com/a14m/game-of-life/-/tree/master/CLI/ruby/"
19
+ spec.metadata["source_code_uri"] = "https://git.sr.ht/~a14m/game-of-life/tree/master/CLI/ruby"
20
20
  spec.metadata["documentation_uri"] = "https://rubydoc.info/gems/terminal_game_of_life"
21
- spec.metadata["changelog_uri"] = "https://gitlab.com/a14m/game-of-life/-/blob/master/CLI/ruby/CHANGELOG.md"
21
+ spec.metadata["changelog_uri"] = "https://git.sr.ht/~a14m/game-of-life/tree/master/CLI/ruby/CHANGELOG.md"
22
22
 
23
23
  spec.executables = ["game-of-life"]
24
24
  spec.require_paths = ["lib"]
@@ -31,6 +31,10 @@ Gem::Specification.new do |spec|
31
31
  spec.add_development_dependency "rake"
32
32
  spec.add_development_dependency "rspec"
33
33
  spec.add_development_dependency "rubocop"
34
+ spec.add_development_dependency "rubocop-rspec"
35
+ # Code Coverage dependencies
36
+ spec.add_development_dependency "codecov"
37
+ spec.add_development_dependency "simplecov"
34
38
  # Documentation dependencies
35
39
  spec.add_development_dependency "redcarpet"
36
40
  spec.add_development_dependency "yard"
data/lib/game_of_life.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "io/console"
3
4
  require "game_of_life/version"
4
5
  require "game_of_life/plane"
5
6
  require "game_of_life/universe"
@@ -11,6 +12,58 @@ module GameOfLife
11
12
  class Error < StandardError; end
12
13
 
13
14
  class << self
15
+ # Validate and parse the CLI options and set defaults for the dynamic options.
16
+ # @param options [Hash] CLI options to generate initial conditions
17
+ # @option options [String | nil] "input" path to a local file or URL to open
18
+ # @option options [Numeric | nil] "seed" number to use if no "input" is provided
19
+ # @option options [Numeric] "width" of the universe
20
+ # @option options [Numeric] "height" of the universe
21
+ # @option options [Numeric] "delay" introduced after each cycle
22
+ # @option options [String] "live-cell" representation
23
+ # @option options [String] "dead-cell" representation
24
+ # @smell AbcSize, MethodLenght, Cyclomatic and Perceived Complexity needed for parsing and validating options
25
+ # rubocop:disable Metrics/AbcSize
26
+ # rubocop:disable Metrics/MethodLength
27
+ # rubocop:disable Metrics/CyclomaticComplexity
28
+ # rubocop:disable Metrics/PerceivedComplexity
29
+ # return [Hash] of the parsed options with dynamic defaults based on window size and kernel random
30
+ def parsed_options(options)
31
+ max_height = IO.console.winsize[0] - 2
32
+ max_width = IO.console.winsize[1]
33
+
34
+ if options["delay"].to_i.negative?
35
+ fail GameOfLife::Error, "Invalid --delay value. must be positive value (sadly this is how time works -so far-)"
36
+ end
37
+ if (options["width"]&.< 1) || (options["width"]&.> max_width)
38
+ fail GameOfLife::Error, "Invalid --width value. " \
39
+ "must be between 1 and #{max_width} (current terminal width)"
40
+ end
41
+ if (options["height"]&.< 1) || (options["height"]&.> max_height)
42
+ fail GameOfLife::Error, "Invalid --height value. " \
43
+ "must be between 1 and #{max_height} (current terminal height)"
44
+ end
45
+
46
+ fail GameOfLife::Error, "Invalid --live-cell value. must be a single character" if options["live-cell"].length > 1
47
+
48
+ fail GameOfLife::Error, "Invalid --dead-cell value. must be a single character" if options["dead-cell"].length > 1
49
+
50
+ if options["dead-cell"] == options["live-cell"]
51
+ fail GameOfLife::Error, "Invalid --dead-cell value. must be a different character than --live-cell"
52
+ end
53
+
54
+ {
55
+ # Defaults the hight to less then the height of the terminal to allow banner info
56
+ # and an extra emtpy line to avoid triggering terminal scroll while flushing
57
+ "height" => max_height,
58
+ "width" => max_width,
59
+ "seed" => rand(100_000),
60
+ }.merge(options)
61
+ end
62
+ # rubocop:enable Metrics/AbcSize
63
+ # rubocop:enable Metrics/MethodLength
64
+ # rubocop:enable Metrics/CyclomaticComplexity
65
+ # rubocop:enable Metrics/PerceivedComplexity
66
+
14
67
  # Generate a universe based on the options (from an input file/URI) or using a random/passed seed
15
68
  # This method also sets the Classes/Modules constants for the run defining the options for
16
69
  # Cell (Dead/Live) state representations, and the delay introduced after rendering each universe/generation
@@ -53,9 +106,13 @@ module GameOfLife
53
106
  # and rendering of the current universe/banner info
54
107
  # based on the delay/cell configured by the user
55
108
  def render(universe)
56
- puts "\33c\e[3J" # Clears the screen and scrollback buffer.
57
- puts universe.to_s
58
- puts BANNER
109
+ # Use Alternate Screen (\e[?1049h) and move cursor to top left (\e[H)
110
+ # Ref: https://github.com/ruby/ruby/blob/ruby_2_7/lib/irb/easter-egg.rb#L112-L131
111
+ # Ref: https://stackoverflow.com/questions/11023929/using-the-alternate-screen-in-a-bash-script
112
+ # Ref: https://superuser.com/questions/122911/what-commands-can-i-use-to-reset-and-clear-my-terminal
113
+ print "\e[?1049h\e[H"
114
+ print universe.to_s
115
+ print "\n #{BANNER}"
59
116
  sleep(DELAY / 1000.0)
60
117
  end
61
118
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module GameOfLife
4
4
  # Game of life version number
5
- VERSION = "1.0.0"
5
+ VERSION = "1.0.5"
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terminal_game_of_life
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - a14m
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-12 00:00:00.000000000 Z
11
+ date: 2021-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -94,6 +94,48 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: codecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
97
139
  - !ruby/object:Gem::Dependency
98
140
  name: redcarpet
99
141
  requirement: !ruby/object:Gem::Requirement
@@ -141,16 +183,16 @@ files:
141
183
  - lib/game_of_life/plane.rb
142
184
  - lib/game_of_life/universe.rb
143
185
  - lib/game_of_life/version.rb
144
- homepage: https://gitlab.com/a14m/game-of-life
186
+ homepage: https://git.sr.ht/~a14m/game-of-life/tree/master/CLI/ruby/README.md
145
187
  licenses:
146
188
  - MIT
147
189
  metadata:
148
190
  allowed_push_host: https://rubygems.org
149
- homepage_uri: https://gitlab.com/a14m/game-of-life
150
- source_code_uri: https://gitlab.com/a14m/game-of-life/-/tree/master/CLI/ruby/
191
+ homepage_uri: https://git.sr.ht/~a14m/game-of-life/tree/master/CLI/ruby/README.md
192
+ source_code_uri: https://git.sr.ht/~a14m/game-of-life/tree/master/CLI/ruby
151
193
  documentation_uri: https://rubydoc.info/gems/terminal_game_of_life
152
- changelog_uri: https://gitlab.com/a14m/game-of-life/-/blob/master/CLI/ruby/CHANGELOG.md
153
- post_install_message:
194
+ changelog_uri: https://git.sr.ht/~a14m/game-of-life/tree/master/CLI/ruby/CHANGELOG.md
195
+ post_install_message:
154
196
  rdoc_options: []
155
197
  require_paths:
156
198
  - lib
@@ -165,8 +207,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
207
  - !ruby/object:Gem::Version
166
208
  version: '0'
167
209
  requirements: []
168
- rubygems_version: 3.2.0
169
- signing_key:
210
+ rubygems_version: 3.1.4
211
+ signing_key:
170
212
  specification_version: 4
171
213
  summary: Game of Life CLI
172
214
  test_files: []