require File.expand_path(File.join(File.dirname(__FILE__), '..', 'fathom')) class Fathom::Node attr_reader :name, :distribution, :description, :values def initialize(opts={}) @name = opts[:name] assert_distribution(opts) @description = opts[:description] @values = opts[:values] assert_links(opts) end def name_sym return nil unless self.name @name_sym ||= self.name.to_s.downcase.gsub(/\s+|-+/, '_').to_sym end def parents @parents ||= [] end def add_parent(parent) self.parents << parent self.add_accessor_for_node(parent) parent.register_child(self) end def register_child(child) raise "Cannot register a child if this node is not a parent already. Use add_parent to the other node or add_child to this node." unless child.parents.include?(self) unless children.include?(child) self.add_accessor_for_node(child) children << child end true end def children @children ||= [] end def add_child(child) self.children << child self.add_accessor_for_node(child) child.register_parent(self) end def register_parent(parent) raise "Cannot register a parent if this node is not a child already. Use add_child to the other node or add_parent to this node." unless parent.children.include?(self) unless parents.include?(parent) self.add_accessor_for_node(parent) parents << parent end true end protected def add_accessor_for_node(node) return false unless node.is_a?(Node) and node.name_sym return false if self.respond_to?(node.name_sym) (class << self; self; end).module_eval do define_method node.name_sym do node end end end def assert_links(opts) found = opts[:parents] found ||= opts[:parent] found ||= [] found = [found] unless found.is_a?(Array) found.each do |parent| add_parent(parent) end found = opts[:children] found ||= opts[:child] found ||= [] found = [found] unless found.is_a?(Array) found.each do |child| add_child(child) end end def assert_distribution(opts) case opts[:distribution] when Class @distribution = opts[:distribution] when Symbol class_name = opts[:distribution].to_s.downcase.split(/_+/).map {|t| t[0].chr.upcase + t[1..-1]}.join if Fathom::Distributions.constants.include?(class_name) @distribution = "Fathom::Distributions::#{class_name}".constantize end end @distribution ||= Fathom::Distributions::Gaussian end end if __FILE__ == $0 include Fathom # TODO: Is there anything you want to do to run this file on its own? # Node.new end