Skip to content

Instantly share code, notes, and snippets.

@coffeeaddict
Created June 27, 2013 06:42
Show Gist options
  • Save coffeeaddict/5874432 to your computer and use it in GitHub Desktop.
Save coffeeaddict/5874432 to your computer and use it in GitHub Desktop.
Some toolbox methods for a ruote developer
>> pdef = <<EOPDEF
define comms_and_hackers
sequence flank: true
start_prism
concurrence
cursor rewind_unless: '${f:conversation_done}'
alice
bob
cursor rewind_unless: '${f:cipher_broken_or_conversation_done}'
eve
mallory
EOPDEF
>> # humanized form
>> pp Ruote::Toolbox.humanize(pdef)
["define",
{"name"=>"Comms and hackers"},
[["sequence", {"flank"=>true}, [["Start prism", {}, []]]],
["concurrence",
{},
[["cursor",
{"rewind_unless"=>"${f:conversation_done}"},
[["Alice", {}, []], ["Bob", {}, []]]],
["cursor",
{"rewind_unless"=>"${f:cipher_broken_or_conversation_done}"},
[["Eve", {}, []], ["Mallory", {}, []]]]]]]]
>> # 'key' points in the pdef with their expid
>> pp Ruote::Toolbox.exp_hash(pdef, false) # no keywords
{"0_0_0"=>["start_prism", {}],
"0_1_0_0"=>["alice", {}],
"0_1_0_1"=>["bob", {}],
"0_1_1_0"=>["eve", {}],
"0_1_1_1"=>["mallory", {}]}
>> # humanized expressions with their expid
>> pp Ruote::Toolbox.exp_hash(Ruote::Toolbox.humanize(pdef))
{"0"=>["define", {"name"=>"Comms and hackers"}],
"0_0"=>["sequence", {"flank"=>true}],
"0_0_0"=>["Start prism", {}],
"0_1"=>["concurrence", {}],
"0_1_0"=>["cursor", {"rewind_unless"=>"${f:conversation_done}"}],
"0_1_0_0"=>["Alice", {}],
"0_1_0_1"=>["Bob", {}],
"0_1_1"=>
["cursor", {"rewind_unless"=>"${f:cipher_broken_or_conversation_done}"}],
"0_1_1_0"=>["Eve", {}],
"0_1_1_1"=>["Mallory", {}]}
>> # let's see how we got to bob
>> Ruote::Toolbox.path("0_1_0_1")
=> ["0", "0_0", "0_1", "0_1_0", "0_1_0_0", "0_1_0_1"]
>> pp Ruote::Toolbox.exp_hash(pdef).values_at(*Ruote::Toolbox.path("0_1_0_1"))
[["define", {"comms_and_hackers"=>nil}],
["sequence", {"flank"=>true}],
["concurrence", {}],
["cursor", {"rewind_unless"=>"${f:conversation_done}"}],
["alice", {}],
["bob", {}]]
>> # again, but only the 'key' points (with compact to weed out nils)
>> pp Ruote::Toolbox.exp_hash(pdef, false).values_at(*Ruote::Toolbox.path("0_1_0_1")).compact
[["alice", {}],
["bob", {}]]
# Toolbox stuff for ruote
#
module Ruote::Toolbox
require 'active_support/inflector'
# may be incomplete
RESERVED_WORDS = %w[define sequence concurrence if unless concurrent_iterator
cursor loop repeat subprocess cron every
]
class << self
# provide the walked path for a given expid.
#
# note; does not take jumps and rewinds into account
#
# @param [String] expid A ruote expid such as: "0_0_3"
# @return [Array] such as: ["0", "0_0", "0_0_0", "0_0_1", "0_0_2", "0_0_3"]
#
def path(expid)
path = []
tree = expid.split("_").collect(&:to_i)
while ( branch = tree.pop )
branch.downto(0) { |twig|
path.unshift((tree + [ twig ]).join("_"))
}
end
path
end
# turn a pdef into a hash with expid => expression, all reserved words
# are forgotten
#
# @param [Object] pdef A Ruote Process Definition
# @param [Boolean] keywords Should Ruote keywords be included?
#
# @return [Hash] A hash with expid as key and pdef-twig as value,
# basicly flattening the tree in context
#
def exp_hash(pdef, keywords=true)
if !pdef.is_a?(Array)
pdef = Ruote::Reader.read(pdef)
end
exp_hash_iterator({}, pdef, keywords)
end
# workhorse for #exp_hash !!RECURSIVE!!
#
# @param [Hash] hash The hash to fill with twigs
# @param [Array] branch Branch to traverse
# @param [String] expid Root of the current branch
# @param [Boolean] keywords Should keywords be preserved?
#
# @return hash
#
def exp_hash_iterator(hash, branch, keywords=true, expid='0')
branch = branch.dup
twigs = branch.pop
unless (keywords == false) && RESERVED_WORDS.include?(branch[0])
hash[expid] = branch
end
twigs.each_with_index do |twig, index|
hash = exp_hash_iterator(hash, twig, keywords, expid + "_#{index}")
end
return hash
end
# provide a most human readable pdef
#
# @param [Object] pdef The Ruote Process Definition
# @param [Boolean] trunk If false, the trunk (define) is replaced with an
# empty string - this works great in ruote-fluo
#
# @return [Array] Tree with human names, most likely not usable in Ruote
#
def humanize(pdef, trunk=true)
if !pdef.is_a?(Array)
pdef = Ruote::Reader.read(pdef)
end
humanize_iterator(pdef, trunk)
end
# workhorse for #humanize !!RECURSIVE!!
#
# @param [Array] tree Tree to humanize
# @oaram [Boolean] trunk Preserve the trunk? See #humanize
# @param [Fixnum] depth Present tree depth
#
# @return [Array] modified tree with names humanized, RESERVED_WORDS are
# kept as is
#
# @note You can provide your own human_name as a param to the participant
#
def humanize_iterator(tree, trunk=true, depth=0)
(name, params, branches) = tree
name = params['ref'] if name == 'participant'
if name == 'define'
params.delete 'revision' # OM eyes only
if !trunk && (depth == 0)
name = ""
else
key = params.keys.first
if key != 'name'
human = params['human_name'].blank? ?
key.humanize :
params['human_name']
params.delete(key)
params['name'] = human
else
human = params['human_name'].blank? ?
params[key].humanize :
params['human_name']
params[key] = human
end
end
end
# keywords always retain their name in the three, otherwise fluo breaks
#
humanized = if RESERVED_WORDS.include?(name)
name
else
params['human_name'].blank? ? name.humanize : params['human_name']
end
[
humanized,
RESERVED_WORDS.include?(name) ? params : {},
branches.collect { |branch| humanize_iterator(branch, trunk, depth+1) }
]
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment