Class: Request::Choregraphy
- Inherits:
-
Base::Event
- Object
- Base::Event
- Request::Choregraphy
- Defined in:
- lib/violet/request.rb
Overview
Choregraphy
Choregraphy in the Violet API looks like binary CSV code. It isn’t really “user-friendly”. We use a DSL (Domain Specific Language) to describe Choregraphy more easily, and then translate it in with this class. This allows us to create a more powerful language, making easy (for examples) to set all leds in one sentence, instead of five 90% redundant lines :
‘set all to green’ will we translated into ‘chor=10,0,led,0,0,255,0,0,led,1,0,255,0,0,led,2,0,255,0,0,led,3,0,255,0,0,led,4,0,255,0’
Moreover, if you think that a Choregraphy is a Set of Events (that are either an ear command either a led command), then we can use logic operations such as ==, +, -, | and & on Choregraphy (code taken from test file test_request_chor.rb):
one = Choregraphy.new { move left ear forward of degrees 42 }
two = Choregraphy.new { move right ear forward of degrees 42 }
onetwo = Choregraphy.new { move both ears forward of degrees 42 }
assert_equal one | two, one + two
assert_equal one & two, Choregraphy.new
assert_equal one - two, one
assert_equal two - one, two
assert_equal onetwo, one + two
assert_equal onetwo & two, two
assert_equal onetwo & one, one
assert_equal onetwo - two, one
assert_equal onetwo - one, two
assert_equal onetwo | two, onetwo
assert_equal onetwo | one, onetwo
Choregraphy Creation
see new
Choregraphy DSL description
Here is the syntax description: [] are alternation with | or range with - and <> are optionals.
at time 1.2 <do>
move [right|left|both] <ear|ears> [backward|forward] <of> degrees [0-180]
set [bottom|left|middle|right|top|all] <led|leds> to [off|red|green|blue|yellow|magenta|cyan|white|rgb([0-255],[0-255],[0-255])]
<end>
Examples
for examples, please see the test file (namely test_request_chor.rb), because there are a lot of possible chor description and I don’t want to duplicate too much code :)
Defined Under Namespace
Modules: Ears, Leds Classes: BadChorDesc, EarCommandStruct, LedCommandStruct
Class Method Summary collapse
-
.bubble(*methods) ⇒ Object
define dummy methods for DSL.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#initialize(h = Hash.new, &block) ⇒ Choregraphy
constructor
Take some Choregraphy DSL code and translate it into a Choregraphy description of Violet API.
- #move(command) ⇒ Object
- #set(command) ⇒ Object
- #to_url ⇒ Object
Methods inherited from Base::Event
Constructor Details
#initialize(h = Hash.new, &block) ⇒ Choregraphy
Take some Choregraphy DSL code and translate it into a Choregraphy description of Violet API.
Arguments
(optionals) an Hash in argument with keys:
- name
-
the chortitle
- code
-
an array of String/Proc or a String/Proc that describe the Choregraphy in our DSL.
(optionals) a block of code that describe the Choregraphy.
Raise
raise a Choregraphy::BadChorDesc if not happy.
Examples (all results are equals)
Request::Choregraphy.new { set all off; move right ear forward of degrees 180 } # => #<Request::Choregraphy:0x2b07a05f8ca0 @chor=["0,led,0,0,0,0", "0,led,1,0,0,0", "0,led,2,0,0,0", "0,led,3,0,0,0", "0,led,4,0,0,0", "0,motor,0,180,0,0"], @code=[#<Proc:0x00002b07a05f8d40@(irb):3>], @time=0>
Request::Choregraphy.new :code => 'set all off; move right ear forward of degrees 180' # => #<Request::Choregraphy:0x2b07a05e84b8 @chor=["0,led,0,0,0,0", "0,led,1,0,0,0", "0,led,2,0,0,0", "0,led,3,0,0,0", "0,led,4,0,0,0", "0,motor,0,180,0,0"], @code=["set all off; move right ear forward of degrees 180"], @time=0>
Request::Choregraphy.new :code => [ 'set all off', 'move right ear forward of degrees 180' ] # => #<Request::Choregraphy:0x2b07a05dae30 @chor=["0,led,0,0,0,0", "0,led,1,0,0,0", "0,led,2,0,0,0", "0,led,3,0,0,0", "0,led,4,0,0,0", "0,motor,0,180,0,0"], @code=["set all off", "move right ear forward of degrees 180"], @time=0>
363 364 365 366 367 368 |
# File 'lib/violet/request.rb', line 363 def initialize(h=Hash.new, &block) @name = h[:name] if h[:name] @code = if block_given? then block else h[:code] end __choreval__ @chor.sort! unless @chor.nil? end |
Class Method Details
.bubble(*methods) ⇒ Object
define dummy methods for DSL
380 381 382 383 384 385 |
# File 'lib/violet/request.rb', line 380 def self.bubble(*methods) methods.each do |m| define_method(m) { |args| args } private(m.to_sym) end end |
Instance Method Details
#==(other) ⇒ Object
400 401 402 |
# File 'lib/violet/request.rb', line 400 def == other self.chor == other.chor end |
#move(command) ⇒ Object
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 |
# File 'lib/violet/request.rb', line 438 def move command raise BadChorDesc.new('wrong Choregraphy description') unless command.is_a?(EarCommandStruct) raise BadChorDesc.new('need a time') unless command.time raise BadChorDesc.new('time must be >= zero') unless command.time.to_i >= 0 raise BadChorDesc.new('need an angle') unless command.angle raise BadChorDesc.new('angle must be between 0 and 180') unless (0..180).include?(command.angle) raise BadChorDesc.new('need a direction') unless command.direction raise BadChorDesc.new('wrong direction') unless command.direction.between?(Ears::Directions::FORWARD,Ears::Directions::BACKWARD) raise BadChorDesc.new('need an element') unless command.element raise BadChorDesc.new('wrong element') unless command.element == :both or command.element.between?(Ears::Positions::RIGHT,Ears::Positions::LEFT) template = '%s,motor,%s,%s,0,%s' if command.element == :both # we don't know, maybe your rabbit has more than two ears :) (Ears::Positions.constants - ['BOTH']).each do |cste_name| cste = Helpers.constantize "#{self.class}::Ears::Positions::#{cste_name}" @chor << template % [ command.time.to_i, cste, command.angle, command.direction ] end else @chor << template % [ command.time.to_i, command.element, command.angle, command.direction ] end end |
#set(command) ⇒ Object
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 |
# File 'lib/violet/request.rb', line 404 def set command raise BadChorDesc.new('wrong Choregraphy description') unless command.is_a?(LedCommandStruct) raise BadChorDesc.new('need an element') unless command.elements command.elements.each do |e| raise BadChorDesc.new('wrong element') unless e == :all or e.between?(Leds::Positions::BOTTOM,Leds::Positions::TOP) end raise BadChorDesc.new('need a time') unless command.time raise BadChorDesc.new('time must be >= than zero') unless command.time.to_i >= 0 raise BadChorDesc.new('need a color') unless command.color raise BadChorDesc.new('wrong size for rgb color array') unless command.color.size == 3 command.color.collect! do |c| raise BadChorDesc.new('color code must be betwen 0 and 255') unless c.to_i.between?(0,255) c.to_i end template = '%s,led,%s,%s' command.color = command.color.join(',') # remove trailling element if all is set command.elements.uniq! command.elements = [:all] if command.elements.include?(:all) command.elements.each do |e| if e == :all (Leds::Positions.constants - ['ALL']).each do |cste_name| cste = Helpers.constantize "#{self.class}::Leds::Positions::#{cste_name}" @chor << template % [ command.time.to_i, cste, command.color ] end else @chor << template % [ command.time.to_i, e, command.color ] end end end |
#to_url ⇒ Object
370 371 372 373 374 375 376 377 |
# File 'lib/violet/request.rb', line 370 def to_url raise BadChorDesc.new('no choregraphy given') unless @chor url = Array.new url << "chor=10," + @chor.join(',') unless @chor.nil? url << "chortitle=#{@name}" unless @name.nil? url end |