<commit_before>module MetricFu
 
  class Saikuro < Generator

    def emit
      MetricFu.saikuro[:input_directory] = format_directories
 
      options_string = MetricFu.saikuro.inject("") do |options, option|
        options + "--#{option.join(' ')} "
      end
 
      sh %{saikuro #{options_string}} do |ok, response|
        unless ok
          puts "Saikuro failed with exit status: #{response.exitstatus}"
          exit 1
        end
      end
    end

    def format_directories
      dirs = MetricFu.saikuro[:input_directory].join(" | ")
      "\"#{dirs}\""
    end
 
    def analyze
      @files = sort_files(assemble_files)
      @classes = sort_classes(assemble_classes(@files))
      @meths = sort_methods(assemble_methods(@files))
    end
 
    def to_h
      files = @files.map do |file|
        my_file = file.to_h
        my_file[:filename] = file.filename
        my_file
      end
      {:saikuro => {:files => files,
                    :classes => @classes.map {|c| c.to_h},
                    :methods => @meths.map {|m| m.to_h}
                   }
      }
    end
    
    private
    def sort_methods(methods)
      methods.sort_by {|method| method.complexity.to_i}.reverse
    end
    
    def assemble_methods(files)
      methods = []
      files.each do |file|
        file.elements.each do |element|
          element.defs.each do |defn|
            defn.name = "#{element.name}##{defn.name}"
            methods << defn
          end
        end
      end
      methods
    end
    
    def sort_classes(classes)
      classes.sort_by {|k| k.complexity.to_i}.reverse
    end
    
    def assemble_classes(files)
      files.map {|f| f.elements}.flatten
    end
    
    def sort_files(files)
      files.sort_by do |file|
        file.elements.
             max {|a,b| a.complexity.to_i <=> b.complexity.to_i}.
             complexity.to_i
      end.reverse
    end
    
    def assemble_files
      files = []
      Dir.glob("#{metric_directory}/**/*.html").each do |path|
        if Saikuro::SFile.is_valid_text_file?(path)
          file = Saikuro::SFile.new(path)
          if file
            files << file
          end
        end
      end
      files
    end
    
  end
 
  class Saikuro::SFile
 
    attr_reader :elements

    def initialize(path)
      @path = path
      @file_handle = File.open(@path, "r")
      @elements = []
      get_elements
    end
 
    def self.is_valid_text_file?(path)
      File.open(path, "r") do |f|
        if f.eof? || !f.readline.match(/--/)
          return false
        else
          return true
        end
      end
    end
 
    def filename
      File.basename(@path, '_cyclo.html')
    end
 
    def to_h
      merge_classes
      {:classes => @elements}
    end
 
    def get_elements
      begin<commit_msg>Close each file handle as it used to prevent running out of resources.<commit_after>module MetricFu
 
  class Saikuro < Generator

    def emit
      MetricFu.saikuro[:input_directory] = format_directories
 
      options_string = MetricFu.saikuro.inject("") do |options, option|
        options + "--#{option.join(' ')} "
      end
 
      sh %{saikuro #{options_string}} do |ok, response|
        unless ok
          puts "Saikuro failed with exit status: #{response.exitstatus}"
          exit 1
        end
      end
    end

    def format_directories
      dirs = MetricFu.saikuro[:input_directory].join(" | ")
      "\"#{dirs}\""
    end
 
    def analyze
      @files = sort_files(assemble_files)
      @classes = sort_classes(assemble_classes(@files))
      @meths = sort_methods(assemble_methods(@files))
    end
 
    def to_h
      files = @files.map do |file|
        my_file = file.to_h
        my_file[:filename] = file.filename
        my_file
      end
      {:saikuro => {:files => files,
                    :classes => @classes.map {|c| c.to_h},
                    :methods => @meths.map {|m| m.to_h}
                   }
      }
    end
    
    private
    def sort_methods(methods)
      methods.sort_by {|method| method.complexity.to_i}.reverse
    end
    
    def assemble_methods(files)
      methods = []
      files.each do |file|
        file.elements.each do |element|
          element.defs.each do |defn|
            defn.name = "#{element.name}##{defn.name}"
            methods << defn
          end
        end
      end
      methods
    end
    
    def sort_classes(classes)
      classes.sort_by {|k| k.complexity.to_i}.reverse
    end
    
    def assemble_classes(files)
      files.map {|f| f.elements}.flatten
    end
    
    def sort_files(files)
      files.sort_by do |file|
        file.elements.
             max {|a,b| a.complexity.to_i <=> b.complexity.to_i}.
             complexity.to_i
      end.reverse
    end
    
    def assemble_files
      files = []
      Dir.glob("#{metric_directory}/**/*.html").each do |path|
        if Saikuro::SFile.is_valid_text_file?(path)
          file = Saikuro::SFile.new(path)
          if file
            files << file
          end
        end
      end
      files
    end
    
  end
 
  class Saikuro::SFile
 
    attr_reader :elements

    def initialize(path)
      @path = path
      @file_handle = File.open(@path, "r")
      @elements = []
      get_elements
    ensure
      @file_handle.close if @file_handle
    end
 
    def self.is_valid_text_file?(path)
      File.open(path, "r") do |f|
        if f.eof? || !f.readline.match(/--/)
          return false
        else
          return true
        end
      end
    end
 
    def filename
      File.basename(@path, '_cyclo.html')
    end
 
    def to_h
      merge_classes
      {:classes => @elements}
    end
 
    def get_elements
      begin
{'fraction_non_alphanumeric': 0.10766263370156058, 'fraction_numerical': 0.0003506926179203928, 'mean_word_length': 1.7304930588798468, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, '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': '2455332', 'n_tokens_mistral': 1875, 'n_tokens_neox': 1804, 'n_words': 403}