straightedge 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +7 -0
- data/README.md +44 -2
- data/gemspec.yml +3 -0
- data/lib/straightedge.rb +33 -11
- data/lib/straightedge/aspects.rb +3 -0
- data/lib/straightedge/aspects/colorable.rb +8 -0
- data/lib/straightedge/aspects/figural.rb +12 -0
- data/lib/straightedge/aspects/positional.rb +10 -0
- data/lib/straightedge/colors.rb +72 -0
- data/lib/straightedge/config.rb +6 -0
- data/lib/straightedge/director.rb +39 -0
- data/lib/straightedge/extend/array.rb +2 -13
- data/lib/straightedge/figures.rb +8 -0
- data/lib/straightedge/{adapters.rb → figures/circle.rb} +0 -0
- data/lib/straightedge/figures/figure.rb +44 -0
- data/lib/straightedge/figures/grid.rb +65 -0
- data/lib/straightedge/figures/grid_cell.rb +0 -0
- data/lib/straightedge/figures/hexagon.rb +33 -0
- data/lib/straightedge/figures/label.rb +13 -0
- data/lib/straightedge/figures/line.rb +25 -0
- data/lib/straightedge/figures/mark.rb +23 -0
- data/lib/straightedge/figures/quadrilateral.rb +20 -0
- data/lib/straightedge/motor/adapter.rb +54 -0
- data/lib/straightedge/motor/engine.rb +16 -0
- data/lib/straightedge/origin.rb +3 -0
- data/lib/straightedge/presenter.rb +29 -0
- data/lib/straightedge/scene.rb +20 -0
- data/lib/straightedge/surface.rb +21 -0
- data/lib/straightedge/toolkit/compass.rb +19 -0
- data/lib/straightedge/toolkit/rose.rb +60 -0
- data/lib/straightedge/toolkit/ruler.rb +23 -0
- data/lib/straightedge/tools.rb +3 -0
- data/lib/straightedge/version.rb +1 -1
- data/spec/spec_helper.rb +4 -1
- data/spec/straightedge/adapter_spec.rb +14 -0
- data/spec/straightedge/director_spec.rb +10 -0
- data/spec/straightedge/extend/array_spec.rb +1 -6
- data/spec/straightedge/{figure_spec.rb → figures/figure_spec.rb} +0 -5
- data/spec/straightedge/figures/grid_spec.rb +31 -0
- data/spec/straightedge/figures/hexagon_spec.rb +7 -0
- data/spec/straightedge/motor/engine_spec.rb +11 -0
- data/spec/straightedge/scene_spec.rb +27 -0
- data/spec/straightedge/{compass_spec.rb → toolkit/compass_spec.rb} +0 -4
- data/spec/straightedge/{rose_spec.rb → toolkit/rose_spec.rb} +0 -5
- data/spec/straightedge/toolkit/ruler_spec.rb +14 -0
- data/spec/straightedge_spec.rb +35 -0
- metadata +54 -16
- data/.rvmrc +0 -1
- data/lib/straightedge/compass.rb +0 -17
- data/lib/straightedge/figure.rb +0 -28
- data/lib/straightedge/grid.rb +0 -34
- data/lib/straightedge/line.rb +0 -21
- data/lib/straightedge/mark.rb +0 -26
- data/lib/straightedge/rose.rb +0 -44
- data/lib/straightedge/ruler.rb +0 -21
- data/spec/straightedge/grid_spec.rb +0 -33
- data/spec/straightedge/ruler_spec.rb +0 -11
File without changes
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Straightedge::Figures
|
2
|
+
class Hexagon < Figure
|
3
|
+
attr_accessor :scale
|
4
|
+
|
5
|
+
def initialize(location: Straightedge::ORIGIN, color: :white, scale: 1.0)
|
6
|
+
super(location: location, color: color)
|
7
|
+
@scale = scale
|
8
|
+
@marks = corners
|
9
|
+
end
|
10
|
+
|
11
|
+
# lots of magic here...
|
12
|
+
def left_triangle
|
13
|
+
corners[0..2]
|
14
|
+
end
|
15
|
+
|
16
|
+
def right_triangle
|
17
|
+
corners[3..5]
|
18
|
+
end
|
19
|
+
|
20
|
+
def center_quad
|
21
|
+
[corners[0], corners[2], corners[3], corners[5]]
|
22
|
+
end
|
23
|
+
|
24
|
+
def corners
|
25
|
+
Array.new(6) do |i|
|
26
|
+
angle = 2 * Math::PI / 6 * (i+2)
|
27
|
+
x_i = x + scale * Math.cos(angle)
|
28
|
+
y_i = y + scale * Math.sin(angle)
|
29
|
+
[x_i, y_i]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Straightedge
|
2
|
+
module Figures
|
3
|
+
class Line < Figure
|
4
|
+
def alpha
|
5
|
+
@marks[0]
|
6
|
+
end
|
7
|
+
|
8
|
+
def beta
|
9
|
+
@marks[1]
|
10
|
+
end
|
11
|
+
|
12
|
+
def dx
|
13
|
+
alpha.x - beta.x
|
14
|
+
end
|
15
|
+
|
16
|
+
def dy
|
17
|
+
alpha.y - beta.y
|
18
|
+
end
|
19
|
+
|
20
|
+
def length
|
21
|
+
Math.sqrt(dx*dx + dy*dy)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Straightedge
|
2
|
+
module Figures
|
3
|
+
#
|
4
|
+
# a mark is an optionally-colored position
|
5
|
+
#
|
6
|
+
class Mark
|
7
|
+
extend Forwardable
|
8
|
+
include Straightedge::Aspects::Colorable
|
9
|
+
|
10
|
+
attr_accessor :location
|
11
|
+
|
12
|
+
def initialize(*xy, color: :white)
|
13
|
+
@location = xy # [xy[0], xy[1]]
|
14
|
+
@color = color
|
15
|
+
end
|
16
|
+
|
17
|
+
def x; @location[0] end
|
18
|
+
def y; @location[1] end
|
19
|
+
|
20
|
+
def self.empty(*xy); new(*xy, color: :none) end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Straightedge
|
2
|
+
module Figures
|
3
|
+
class Quadrilateral < Figure
|
4
|
+
attr_reader :dimensions
|
5
|
+
def_delegator :dimensions, :x, :width
|
6
|
+
def_delegator :dimensions, :y, :height
|
7
|
+
|
8
|
+
def initialize(dimensions: [1,1], location: ORIGIN, color: :white)
|
9
|
+
super([], location: location, color: color)
|
10
|
+
@dimensions = dimensions
|
11
|
+
@marks = corners
|
12
|
+
end
|
13
|
+
|
14
|
+
def corners(w=width, h=height)
|
15
|
+
@corners ||= [[x,y],[x,y+h],[x+w,y+h],[x+w,y]]
|
16
|
+
#Rose.simple.project(origin).map { |xy| [xy.x*w, xy.y*h] }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Straightedge
|
2
|
+
class Adapter
|
3
|
+
include Straightedge::Figures
|
4
|
+
attr_accessor :agent
|
5
|
+
attr_reader :plane
|
6
|
+
|
7
|
+
def initialize(agent: Director.new, plane: nil)
|
8
|
+
@agent = agent
|
9
|
+
adapt(plane) if plane
|
10
|
+
end
|
11
|
+
|
12
|
+
def adapt(plane)
|
13
|
+
@plane = plane
|
14
|
+
@plane.adapter = self
|
15
|
+
@agent.prepare_stage([plane.width, plane.height])
|
16
|
+
end
|
17
|
+
|
18
|
+
def kickstart
|
19
|
+
@plane.display unless @plane.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
def render
|
23
|
+
scene = @agent.current_scene.is_a?(Hash) ? Scene.new(agent.current_scene) : agent.current_scene
|
24
|
+
scene.render(self)
|
25
|
+
end
|
26
|
+
|
27
|
+
# note the ordering is important, since e.g., grid < quad
|
28
|
+
def presenter_for(figure)
|
29
|
+
figures_and_presenters = Straightedge.config.presenter_classes
|
30
|
+
matched_class = figures_and_presenters.keys.detect { |k| figure.class <= k }
|
31
|
+
|
32
|
+
klass = if matched_class
|
33
|
+
figures_and_presenters[matched_class]
|
34
|
+
else
|
35
|
+
raise "no presenter class for #{figure}"
|
36
|
+
end
|
37
|
+
|
38
|
+
new_presenter = klass.new
|
39
|
+
new_presenter.on(@plane) unless @plane.nil?
|
40
|
+
new_presenter
|
41
|
+
end
|
42
|
+
|
43
|
+
def step
|
44
|
+
@agent.orchestrate
|
45
|
+
end
|
46
|
+
|
47
|
+
def click(x,y)
|
48
|
+
@agent.handle(:click, x, y)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
config.presenter_classes = {}
|
53
|
+
config.adapter_class = Adapter
|
54
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Straightedge
|
2
|
+
class Engine
|
3
|
+
attr_reader :adapter, :surface, :agent
|
4
|
+
def initialize(surface_geometry=Straightedge.config.geometry)
|
5
|
+
@agent = Straightedge.new_agent
|
6
|
+
@surface = Straightedge.new_surface(surface_geometry)
|
7
|
+
@adapter = Straightedge.new_adapter(agent: @agent, plane: @surface)
|
8
|
+
end
|
9
|
+
|
10
|
+
def boot
|
11
|
+
@adapter.kickstart
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
config.engine_class = Engine
|
16
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Straightedge
|
2
|
+
# TODO something with this
|
3
|
+
class Presenter
|
4
|
+
extend Forwardable
|
5
|
+
#def_delegators :location, :x, :y
|
6
|
+
|
7
|
+
def on(surface)
|
8
|
+
@surface = surface
|
9
|
+
self
|
10
|
+
end
|
11
|
+
|
12
|
+
#def at(p)
|
13
|
+
# @location = p
|
14
|
+
# self
|
15
|
+
#end
|
16
|
+
|
17
|
+
def display(figure)
|
18
|
+
raise 'implement in subclass'
|
19
|
+
end
|
20
|
+
|
21
|
+
#def location
|
22
|
+
# @location ||= [0,0]
|
23
|
+
#end
|
24
|
+
|
25
|
+
#def color(figure)
|
26
|
+
# @color ||= 0xEFEFEFEF
|
27
|
+
#end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Straightedge
|
2
|
+
# some boilerplate to bootstrap a rendering engine
|
3
|
+
class Scene
|
4
|
+
attr_reader :locations_and_figures
|
5
|
+
|
6
|
+
def initialize(locations_and_figures={})
|
7
|
+
@locations_and_figures = locations_and_figures
|
8
|
+
end
|
9
|
+
|
10
|
+
def render(adapter=nil)
|
11
|
+
return false unless adapter
|
12
|
+
@locations_and_figures.each do |location,figure|
|
13
|
+
figure = Figures::Label.new.says(figure) if figure.is_a?(String)
|
14
|
+
figure.location = location
|
15
|
+
presenter = adapter.presenter_for(figure)
|
16
|
+
presenter.display(figure)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Straightedge
|
2
|
+
module Surface
|
3
|
+
attr_accessor :adapter
|
4
|
+
attr_reader :width, :height
|
5
|
+
|
6
|
+
def display
|
7
|
+
warn 'implement in subclass'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class AbstractSurface
|
12
|
+
include Surface
|
13
|
+
|
14
|
+
def initialize(geometry, adapter: adapter)
|
15
|
+
@width, @height = *geometry
|
16
|
+
@adapter = adapter
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
config.surface_class = AbstractSurface
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Straightedge
|
2
|
+
module Toolkit
|
3
|
+
class Compass
|
4
|
+
extend Forwardable
|
5
|
+
attr_accessor :rose
|
6
|
+
def_delegator :rose, :project
|
7
|
+
|
8
|
+
def initialize(rose=Rose.extended)
|
9
|
+
@rose = rose
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def default
|
14
|
+
@default_compass ||= new
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Straightedge
|
2
|
+
module Toolkit
|
3
|
+
class Rose
|
4
|
+
attr_reader :directions
|
5
|
+
|
6
|
+
def initialize(directions:{})
|
7
|
+
@directions = directions
|
8
|
+
end
|
9
|
+
|
10
|
+
def project(point)
|
11
|
+
@directions.values.collect do |delta|
|
12
|
+
Ruler.translate(point, delta)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def simple
|
18
|
+
return @simple_rose unless @simple_rose.nil?
|
19
|
+
@simple_rose = new directions: {
|
20
|
+
:north => [0, -1],
|
21
|
+
:south => [0, 1],
|
22
|
+
:east => [1, 0],
|
23
|
+
:west => [-1, 0]
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
# for hex navigation (nb coords are in cube-space)
|
28
|
+
def hexagonal
|
29
|
+
return @hex_rose unless @hex_rose.nil?
|
30
|
+
@hex_rose = new directions: {
|
31
|
+
:north => [1, -1, 0],
|
32
|
+
:northeast => [0, -1, 1],
|
33
|
+
:northwest => [1, 0, -1],
|
34
|
+
:south => [-1, 1, 0],
|
35
|
+
:southeast => [-1, 0, 1],
|
36
|
+
:southwest => [0, 1, -1]
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def extended
|
41
|
+
return @extended_rose unless @extended_rose.nil?
|
42
|
+
simple_rose_axes = [[:east,:west],[:north, :south]]
|
43
|
+
extended_directions = permute(simple, simple_rose_axes)
|
44
|
+
all_directions = simple.directions.merge(extended_directions)
|
45
|
+
@extended_rose = new directions: all_directions
|
46
|
+
end
|
47
|
+
|
48
|
+
def permute(rose, axes)
|
49
|
+
combinations = axes.x.map do |x|
|
50
|
+
axes.y.map do |y|
|
51
|
+
["#{y}#{x}".to_sym, Ruler.translate(rose.directions[x], rose.directions[y])]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Hash[combinations.flatten(1)]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Straightedge
|
2
|
+
module Toolkit
|
3
|
+
class Ruler
|
4
|
+
attr_reader :unit
|
5
|
+
|
6
|
+
def initialize(unit: 1)
|
7
|
+
@unit = unit
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def default; @default ||= new end
|
12
|
+
|
13
|
+
def translate(xy, dxy)
|
14
|
+
xy.zip(dxy).map { |x,y| x+y }
|
15
|
+
end
|
16
|
+
|
17
|
+
def distance(alpha,beta)
|
18
|
+
Straightedge::Figures::Line.new([alpha,beta]).length
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/straightedge/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class GridPresenter; end
|
4
|
+
Straightedge.config.presenter_classes = { Grid => GridPresenter }
|
5
|
+
|
6
|
+
describe Adapter do
|
7
|
+
let(:director) { Director.new }
|
8
|
+
subject { Adapter.new(agent: director) }
|
9
|
+
|
10
|
+
it 'should find presenters' do
|
11
|
+
expect(subject.presenter_for(Grid.new)).to be_a(GridPresenter)
|
12
|
+
#expect(subject.presenter_for(Space.new)).to be_a(GridPresenter)
|
13
|
+
end
|
14
|
+
end
|
@@ -1,9 +1,4 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'straightedge/mark'
|
3
|
-
require 'straightedge/figure'
|
4
|
-
require 'straightedge/compass'
|
5
|
-
require 'straightedge/rose'
|
6
|
-
require 'straightedge/extend/array'
|
7
2
|
require 'pry'
|
8
3
|
|
9
4
|
describe Array do
|
@@ -34,7 +29,7 @@ describe Array do
|
|
34
29
|
end
|
35
30
|
|
36
31
|
let(:expected_adjacent) do
|
37
|
-
[[
|
32
|
+
[[2, 2], [2, 3], [2, 1], [1, 1], [3, 1], [1, 3], [3, 3], [4, 2], [0, 2], [0, 1], [0, 3], [4, 1], [4, 3]]
|
38
33
|
end
|
39
34
|
it 'should have adjacent coordinates' do
|
40
35
|
expect(subject.adjacent).to eql(expected_adjacent)
|