# encoding: utf-8
require_relative "yzz/version"
require_relative "yzz/side"
require_relative "yzz/side_pair"
# Module Yzz is a mixin that provides qualities of a ZZ structure cell to its
# includers.
#
# A ZZ structure consists of ZZ objects, which exist in multiple dimensions. ZZ
# objects may be connected by directed edges -- connections. Connected objects
# are called neighbors. Each connection belongs to exactly one dimension. A ZZ
# object is considered as having two sides in each dimension:
# posward side and negward side. A connection always points
# away from the posward side, and towards the negward side of the neighbor. In
# each dimension, a ZZ object can have at most one posward and one negward
# neighbor. The relation is bijective: If B is the posward neighbor of A along
# dimension X, then A is a negward neighbor of B along X, and vice-versa. There
# is no limitation as to what objects can be connected. Circles are allowed. A ZZ
# object can even be connected to itself, forming a loop.
#
# To this basic definition, Ted Nelson adds a bunch of additional terminology.
# A rank is a series of ZZ objects connected along the same dimension.
# A rank viewed horizontally is referred to as row. A rank viewed
# vertically is referred to as column. Ted Nelson's terms related not
# to the ZZ structure itself, but rather to the proposed user interface (such
# as cursor, view...) are not implemented in yzz, but rather
# in y_nelson gem.
#
module Yzz
# Adds initialization of the @zz_dimensions hash to #initialize.
#
def initialize *args
@zz_dimensions = Hash.new { |ꜧ, missing_dimension|
ꜧ[ missing_dimension ] = Yzz::SidePair
.new( zz: self, dimension: missing_dimension )
} # initialize the @zz_dimensions hash
super # and proceed as usual
end
# Returns a SidePair instance along the requested dimension.
#
def along dimension
@zz_dimensions[ dimension ]
end
# Returns all sides actually connected to a zz object.
#
def connections
@zz_dimensions.map { |_, pair| [ pair.negward, pair.posward ] }
.reduce( [], :+ ).select { |side| side.neighbor.is_a_zz? }
end
alias connectivity connections
# Returns all neighbors of a zz object.
#
def neighbors
connections.map &:neighbor
end
# Returns all sides facing another zz object supplied as argument. (Note that
# this can be more than 1 side: object A can be connected to B along
# more than 1 dimension.
#
def towards other
connectivity.select { |side| side.neighbor == other }
end
# Prints the labels of the sides facing towards a given zz object.
#
def tw other
puts towards( other ).map &:label
end
# Short string describing the object.
#
def to_s
"#"
end
# Inspect string of the object.
#
def inspect
to_s
end
end
class Object
def is_a_zz?
is_a? ::Yzz
# class_complies? ::YTed::Zz
end
end