pico 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.vimrc +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +29 -0
  7. data/Rakefile +33 -0
  8. data/gold_master_apps/tic_tac_toe/Gemfile +18 -0
  9. data/gold_master_apps/tic_tac_toe/Rakefile +3 -0
  10. data/gold_master_apps/tic_tac_toe/boot.rb +2 -0
  11. data/gold_master_apps/tic_tac_toe/config/application.rb +8 -0
  12. data/gold_master_apps/tic_tac_toe/config/environments/test.rb +3 -0
  13. data/gold_master_apps/tic_tac_toe/game/bad_move.rb +1 -0
  14. data/gold_master_apps/tic_tac_toe/game/game.rb +62 -0
  15. data/gold_master_apps/tic_tac_toe/game/make_move_command.rb +38 -0
  16. data/gold_master_apps/tic_tac_toe/game/memory_repository.rb +39 -0
  17. data/gold_master_apps/tic_tac_toe/test/game_test.rb +65 -0
  18. data/gold_master_apps/tic_tac_toe/test/reports/TEST-GameTest.xml +13 -0
  19. data/gold_master_apps/tic_tac_toe/test/test_helper.rb +7 -0
  20. data/lib/pico.rb +41 -0
  21. data/lib/pico/application.rb +120 -0
  22. data/lib/pico/autoloader.rb +131 -0
  23. data/lib/pico/context.rb +89 -0
  24. data/lib/pico/context/const_resolver.rb +80 -0
  25. data/lib/pico/pry_context.rb +71 -0
  26. data/lib/pico/rake.rb +15 -0
  27. data/lib/pico/ruse_extensions.rb +9 -0
  28. data/lib/pico/string_inflections.rb +30 -0
  29. data/lib/pico/test_runner.rb +27 -0
  30. data/lib/pico/version.rb +3 -0
  31. data/pico.gemspec +30 -0
  32. data/test/integration/autoloading_test.rb +47 -0
  33. data/test/support/fakes_filesystem.rb +182 -0
  34. data/test/support/tests_autoloading.rb +16 -0
  35. data/test/test_helper.rb +36 -0
  36. data/test/unit/application_test.rb +79 -0
  37. data/test/unit/autoloader_test.rb +68 -0
  38. data/test/unit/context_test.rb +80 -0
  39. metadata +202 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fba9d61978a88aaa52222819d4440c4c5b43b40a
4
+ data.tar.gz: ddd4b6989de2f9c71514b78dcdf51a7751f59535
5
+ SHA512:
6
+ metadata.gz: 94f4ce13c6059ead5fd19eb760bd7508346a8091d98b0aab6fe7992a26fe646ba459bcfd83731bd403d542f7cc2be16238b366b4f54f5b3fd232339bb3e1af47
7
+ data.tar.gz: 0d39efdb6fa92f6fb6452e710dcdd3b99ef8c6c1601266bbcec3cc4e27bb64a79ffb134303a6a4b4a58a95ea98c1d89edc8d581ccbb9193fa8fc6a90bb5d9fa6
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ vendor/ruby
19
+ bin
20
+ !bin/pico
21
+ tags
22
+ .gems
23
+ .ruby-version
24
+ .rbenv-gemsets
data/.vimrc ADDED
@@ -0,0 +1,3 @@
1
+ map <F5> :call system("tmux resize -y 20 -t 1 && tmux send -t1 'rake && tmux resize -Z -t 0' c-j") <CR>
2
+ map <F6> :call system("tmux resize -Z -t 0") <CR>
3
+ map <F7> :call system("tmux resize -y 40 -t 1") <CR>
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pico.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 ntl
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Pico
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'pico'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install pico
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( http://github.com/<my-github-username>/pico/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.pattern = 'test/**/*_test.rb'
6
+ t.libs << 'test'
7
+ end
8
+
9
+ desc "Update ctags"
10
+ task :ctags do
11
+ `ctags -R --languages=Ruby --totals -f tags`
12
+ end
13
+
14
+ desc "Run the internal build plus all gold master apps"
15
+ namespace :test do
16
+ task :all do
17
+ Rake::Task['test'].invoke
18
+ Rake::Task['test:gold_master_apps'].invoke
19
+ end
20
+
21
+ task :gold_master_apps do
22
+ Dir['gold_master_apps/*'].each do |app_dir|
23
+ puts "\n\nRunning tests for gold master app `#{File.basename(app_dir)}'"
24
+ Dir.chdir app_dir do
25
+ process = fork do exec "bin/rake" end
26
+ Process.wait process
27
+ exit $?.exitstatus unless $?.exitstatus == 0
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ task default: 'test:all'
@@ -0,0 +1,18 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby '2.1.1'
4
+
5
+ gem 'pico', path: File.expand_path('../../..', __FILE__)
6
+
7
+ gem 'rake'
8
+
9
+ group :test do
10
+ gem 'minitest'
11
+ gem 'minitest-reporters'
12
+ end
13
+
14
+ group :pry do
15
+ gem 'pry'
16
+ gem 'pry-byebug'
17
+ gem 'pry-stack_explorer'
18
+ end
@@ -0,0 +1,3 @@
1
+ require_relative "config/application"
2
+
3
+ task default: :test
@@ -0,0 +1,2 @@
1
+ load File.expand_path("../config/application.rb", __FILE__)
2
+ Pico.boot!
@@ -0,0 +1,8 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+ Bundler.require :default
4
+
5
+ Pico.define_application :TicTacToe do |config|
6
+ config.autoload_paths = %w(game users)
7
+ config.provide 'MemoryRepository', as: :repository
8
+ end
@@ -0,0 +1,3 @@
1
+ Pico.application.configure do |config|
2
+ config.provide
3
+ end
@@ -0,0 +1 @@
1
+ BadMove = Class.new StandardError
@@ -0,0 +1,62 @@
1
+ class Game
2
+ attr :repository, :id, :board, :player, :winner
3
+
4
+ def initialize(repository:, id:, board:, player:)
5
+ @id = id
6
+ @repository = repository
7
+ @board = board
8
+ @player = player
9
+ end
10
+
11
+ def winner
12
+ RUNS_OF_THREE.each do |tiles|
13
+ %i(player_1 player_2).each do |player|
14
+ return player if tiles.all? { |at| fetch_tile(at) == player }
15
+ end
16
+ end
17
+ nil
18
+ end
19
+
20
+ def finished?
21
+ winner ? true : false
22
+ end
23
+
24
+ def make_move!(as:, at:)
25
+ MakeMoveCommand.new(game: self, player: as, position: at).apply!
26
+ end
27
+
28
+ def fetch_tile(position)
29
+ row, col = BOARD_MAP.fetch(position)
30
+ board.fetch(row).fetch(col)
31
+ end
32
+
33
+ def apply_move!(position:)
34
+ row, col = BOARD_MAP.fetch(position)
35
+ board.fetch(row)[col] = player
36
+ @player = { player_1: :player_2, player_2: :player_1 }.fetch(player)
37
+ repository.store self
38
+ end
39
+
40
+ BOARD_MAP = {
41
+ top_left: [0, 0],
42
+ top: [0, 1],
43
+ top_right: [0, 2],
44
+ left: [1, 0],
45
+ center: [1, 1],
46
+ right: [1, 2],
47
+ bottom_left: [2, 0],
48
+ bottom: [2, 1],
49
+ bottom_right: [2, 2],
50
+ }
51
+
52
+ RUNS_OF_THREE = [
53
+ [:top_left, :center, :bottom_right],
54
+ [:top_right, :center, :bottom_left],
55
+ [:top_left, :left, :bottom_left],
56
+ [:top, :center, :bottom],
57
+ [:top_right, :right, :bottom_right],
58
+ [:top_left, :top, :top_right],
59
+ [:left, :center, :right],
60
+ [:bottom_left, :bottom, :bottom_right],
61
+ ]
62
+ end
@@ -0,0 +1,38 @@
1
+ class MakeMoveCommand
2
+ attr :game, :game_id, :player, :position, :repository
3
+
4
+ def initialize(game_id:, repository:, player:, position:)
5
+ @game_id = game_id
6
+ @player = player
7
+ @position = position
8
+ @repository = repository
9
+ end
10
+
11
+ def apply!
12
+ @game = repository.find(game_id)
13
+
14
+ validate_game_is_in_progress
15
+ validate_player
16
+ validate_tile
17
+
18
+ game.apply_move! position: position
19
+ end
20
+
21
+ def tile
22
+ game.fetch_tile position
23
+ end
24
+
25
+ def validate_game_is_in_progress
26
+ raise BadMove, "Game has already ended!" if game.finished?
27
+ end
28
+
29
+ def validate_player
30
+ raise BadMove, "It is #{game.player}'s turn" unless player == game.player
31
+ end
32
+
33
+ def validate_tile
34
+ unless tile == :free
35
+ raise BadMove, "Tile at #{position} is already occupied!"
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,39 @@
1
+ class MemoryRepository
2
+ class << self
3
+ def boards
4
+ @boards ||= {}
5
+ end
6
+ end
7
+
8
+ def boards
9
+ self.class.boards
10
+ end
11
+
12
+ def create(id:)
13
+ boards[id] = {
14
+ player: :player_1,
15
+ board: [
16
+ [:free, :free, :free],
17
+ [:free, :free, :free],
18
+ [:free, :free, :free],
19
+ ],
20
+ }
21
+ end
22
+
23
+ def find(id)
24
+ data = boards.fetch id
25
+ TicTacToe::Game.new(
26
+ id: id,
27
+ repository: self,
28
+ player: data[:player],
29
+ board: data[:board].dup,
30
+ )
31
+ end
32
+
33
+ def store(game)
34
+ boards[game.id] = {
35
+ player: game.player,
36
+ board: game.board.dup,
37
+ }
38
+ end
39
+ end
@@ -0,0 +1,65 @@
1
+ require 'test_helper'
2
+
3
+ TicTacToe::MakeMoveCommand
4
+
5
+ class GameTest < Minitest::Test
6
+ def setup
7
+ @game_id = 'abcdef-0123-4567-abcdefghi'
8
+ TicTacToe::MemoryRepository.new.create(id: @game_id)
9
+ end
10
+
11
+ def test_initial_board
12
+ assert_equal [[:free, :free, :free],[:free, :free, :free],[:free, :free, :free]], game.board
13
+ refute game.finished?
14
+ end
15
+
16
+ def test_making_valid_move
17
+ make_move! player: :player_1, position: :center
18
+
19
+ assert_equal [[:free, :free, :free],[:free, :player_1, :free],[:free, :free, :free]], game.board
20
+ end
21
+
22
+ def test_making_move_as_wrong_player
23
+ exception = assert_raises TicTacToe::BadMove do
24
+ make_move! player: :player_2, position: :center
25
+ end
26
+ assert_equal "It is player_1's turn", exception.message
27
+ end
28
+
29
+ def test_must_pick_free_space
30
+ make_move! player: :player_1, position: :center
31
+
32
+ exception = assert_raises TicTacToe::BadMove do
33
+ make_move! player: :player_2, position: :center
34
+ end
35
+ assert_equal "Tile at center is already occupied!", exception.message
36
+ end
37
+
38
+ def test_three_in_a_row_ends_game
39
+ make_move! player: :player_1, position: :left
40
+ make_move! player: :player_2, position: :right
41
+ make_move! player: :player_1, position: :bottom
42
+ make_move! player: :player_2, position: :top_right
43
+ make_move! player: :player_1, position: :bottom_left
44
+ make_move! player: :player_2, position: :top_left
45
+ make_move! player: :player_1, position: :bottom_right
46
+
47
+ assert game.finished?
48
+ assert_equal :player_1, game.winner
49
+
50
+ exception = assert_raises TicTacToe::BadMove do
51
+ make_move! player: :player_2, position: :top
52
+ end
53
+ assert_equal "Game has already ended!", exception.message
54
+ end
55
+
56
+ private
57
+
58
+ def make_move!(**params)
59
+ TicTacToe.build('MakeMoveCommand', game_id: @game_id, **params).apply!
60
+ end
61
+
62
+ def game
63
+ TicTacToe::MemoryRepository.new.find @game_id
64
+ end
65
+ end
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuite name="GameTest" skipped="0" failures="0" errors="0" tests="5" assertions="11" time="0.004318000000000001">
3
+ <testcase name="test_making_valid_move" classname="GameTest" assertions="1" time="0.001956">
4
+ </testcase>
5
+ <testcase name="test_initial_board" classname="GameTest" assertions="2" time="5.2e-05">
6
+ </testcase>
7
+ <testcase name="test_three_in_a_row_ends_game" classname="GameTest" assertions="4" time="0.001909">
8
+ </testcase>
9
+ <testcase name="test_must_pick_free_space" classname="GameTest" assertions="2" time="0.000263">
10
+ </testcase>
11
+ <testcase name="test_making_move_as_wrong_player" classname="GameTest" assertions="2" time="0.000138">
12
+ </testcase>
13
+ </testsuite>
@@ -0,0 +1,7 @@
1
+ require 'minitest'
2
+ require 'minitest/reporters'
3
+ require 'minitest/autorun'
4
+
5
+ load File.expand_path("../../boot.rb", __FILE__)
6
+
7
+ Minitest::Reporters.use! Minitest::Reporters::DefaultReporter.new
data/lib/pico.rb ADDED
@@ -0,0 +1,41 @@
1
+ require "pico/string_inflections"
2
+ require "pico/autoloader"
3
+ require "pico/context"
4
+ require "pico/application"
5
+ require "pico/version"
6
+
7
+ require "ruse"
8
+ require "pico/ruse_extensions"
9
+
10
+ if defined? Rake
11
+ require "pico/rake"
12
+ end
13
+
14
+ module Pico
15
+ extend self
16
+
17
+ attr :application, :contexts
18
+ @contexts = {}
19
+
20
+ def define_application(name, **params, &block)
21
+ contexts[name] = @application = Application.new(name, **params, &block)
22
+ end
23
+
24
+ def define_context(name, **params)
25
+ contexts[name] = Context.new(name, **params)
26
+ end
27
+
28
+ def boot!
29
+ contexts.each_value(&:boot!)
30
+ end
31
+
32
+ def shutdown!
33
+ contexts.each_value do |context|
34
+ context.shutdown! if context.booted?
35
+ end
36
+ contexts.clear
37
+ end
38
+
39
+ Error = Class.new StandardError
40
+ Exception = Class.new Error
41
+ end