lib/treat/entities/entity/iterable.rb
module Treat::Entities::Entity::Iterable
# Yields each entity of any of the supplied
# types in the children tree of this Entity.
# Note that this function is recursive, unlike
# #each. It does not yield the top element being
# recursed.
#
# This function NEEDS to be ported to C. #FIXME
def each_entity(*types)
types = [:entity] if types.size == 0
f = false
types.each do |t2|
if is_a?(Treat::Entities.const_get(t2.cc))
f = true; break
end
end
yield self if f
unless @children.size == 0
# return unless contains_types?(types)
@children.each do |child|
child.each_entity(*types) { |y| yield y }
end
end
end
# Returns an array of the children that have a feature
# equal to value within the entities of the given type.
def entities_with_feature(feature, value, type = nil)
a = []
type = :entity unless type
each_entity(type) do |e|
r = e.get(feature)
a << e if r == value
end
a
end
# Returns an array of the children that have a type
# within the supplied types.
def entities_with_types(*types)
a = []
each_entity(*types) { |e| a << e }
a
end
alias :entities_with_type :entities_with_types
# Returns an array of the entities with the given
# category.
def entities_with_category(category, type = nil)
entities_with_feature(:category, category, type)
end
# Returns the first ancestor of this entity
# that has the given type.
def ancestor_with_type(type)
return unless has_parent?
ancestor = @parent
type_klass = Treat::Entities.const_get(type.cc)
while not ancestor.is_a?(type_klass)
return nil unless (ancestor && ancestor.has_parent?)
ancestor = ancestor.parent
end
ancestor
end
# Yields each ancestors of this entity that
# has the given type.
def each_ancestor(type = :entity)
ancestor = self
while (a = ancestor.ancestor_with_type(type))
yield a
ancestor = ancestor.parent
end
end
# Returns an array of ancestors of this
# entity that have the given type.
def ancestors_with_type(type)
ancestors = []
each_ancestor(type) do |a|
ancestors << a
end
ancestors
end
# Returns the first ancestor that has a feature
# with the given name, otherwise nil.
def ancestor_with_feature(feature)
each_ancestor do |ancestor|
return ancestor if ancestor.has?(feature)
end
end
# Number of children that have a given feature.
# Second variable to allow for passing value to check for.
def num_children_with_feature(feature, value = nil, recursive = true)
i = 0
m = method(recursive ? :each_entity : :each)
m.call do |c|
next unless c.has?(feature)
i += (value == nil ? 1 :
(c.get(feature) == value ? 1 : 0))
end
i
end
end