<commit_before>module SGF
  class Game

    include Enumerable

    SGF::Game::PROPERTIES.each do |human_readable_method, sgf_identity|
      define_method(human_readable_method.to_sym) do
        @root[sgf_identity] ? @root[sgf_identity] : raise(SGF::NoIdentityError)
      end
    end

    attr_accessor :current_node, :root

    #Takes a SGF::Node as an argument. It will be a problem if that node isn't
    #really the first node of of a game (ie: no FF property)
    def initialize node
      raise ArgumentError, "Expected SGF::Node argument but received #{node.class}" unless node.instance_of? SGF::Node
      @root = node
      @current_node = node
    end

    #A simple way to go to the next node in the same branch of the tree
    def next_node
      @current_node = @current_node.children[0]
    end

    #Iterate through all the nodes in preorder fashion
    def each &block
      preorder @root, &block
    end

    def node_count
      count = 0
      each { |node| count += 1 }
      count
    end

    def to_s
      "<SGF::Game:#{object_id}>"
    end

    private

    def method_missing method_name, *args
      human_readable_identity = method_name.to_s.downcase
      identity = SGF::Game::PROPERTIES[human_readable_identity]
      return @root[identity] if identity
      super(method_name, args)
    end

    def preorder node=@root, &block
      # stop processing if the block returns false
      if yield node then
        node.each_child do |child|
          preorder(child, &block)
        end
      end
    end
  end
end<commit_msg>Add to_str to Game, for symmetry.<commit_after>module SGF
  class Game

    include Enumerable

    SGF::Game::PROPERTIES.each do |human_readable_method, sgf_identity|
      define_method(human_readable_method.to_sym) do
        @root[sgf_identity] ? @root[sgf_identity] : raise(SGF::NoIdentityError)
      end
    end

    attr_accessor :current_node, :root

    #Takes a SGF::Node as an argument. It will be a problem if that node isn't
    #really the first node of of a game (ie: no FF property)
    def initialize node
      raise ArgumentError, "Expected SGF::Node argument but received #{node.class}" unless node.instance_of? SGF::Node
      @root = node
      @current_node = node
    end

    #A simple way to go to the next node in the same branch of the tree
    def next_node
      @current_node = @current_node.children[0]
    end

    #Iterate through all the nodes in preorder fashion
    def each &block
      preorder @root, &block
    end

    def node_count
      count = 0
      each { |node| count += 1 }
      count
    end

    def to_s
      "<SGF::Game:#{object_id}>"
    end

    def to_str
      SGF::Writer.new.stringify_tree_from @root
    end

    private

    def method_missing method_name, *args
      human_readable_identity = method_name.to_s.downcase
      identity = SGF::Game::PROPERTIES[human_readable_identity]
      return @root[identity] if identity
      super(method_name, args)
    end

    def preorder node=@root, &block
      # stop processing if the block returns false
      if yield node then
        node.each_child do |child|
          preorder(child, &block)
        end
      end
    end
  end
end
{'fraction_non_alphanumeric': 0.07316313823163138, 'fraction_numerical': 0.0018679950186799503, 'mean_word_length': 2.6469920544835412, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7171507', 'n_tokens_mistral': 1017, 'n_tokens_neox': 973, 'n_words': 323}