<commit_before>require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/numeric/time'

class TimeTap::Project
    
  # CONFIG
    
  class << self
    attr_accessor :pause_limit
    attr_reader :projects
    attr_reader :backend
    
    def reload!
      @pause_limit = 30.minutes
      @projects = {}.with_indifferent_access
      @backend = TimeTap.backend
    end
  end
  reload!

  def logger
    TimeTap.logger
  end




  class << self
    def logger
      TimeTap.logger
    end
    
    def all
      backend.each_entry do |time, path|
        register time, path
      end unless @loaded
      @loaded = true
      projects.values
    end
    
    def register time, path
      project = self[path]
      if project
        project << time
        logger.info "[TimeTap::Project] added #{time} to project #{project.name} (#{project})"
      else
        logger.info "[TimeTap::Project] skipping #{time}, no project"
      end
    end
    
    def find name
      projects[name.underscore.downcase]
    end

    def [] path
      return if path.nil? or path.empty?
      path = File.expand_path(path)
      how_nested = 1

      regex_suffix = "([^/]+)"
      
      folders = TimeTap.config[:code_folders].map do |folder|
        folder = File.expand_path(folder)
        folder = Dir[folder]
      end.flatten
      
      folders_regex = folders.map{|f| Regexp.escape f}.join('|')
      res = path.scan(%r{(#{folders_regex})/#{regex_suffix}}).flatten
      
      # res = path.scan(%r{(#{TimeTap.config[:code] || "Code"})/#{regex_suffix}}).flatten
      mid_path = res[0] # not in a MatchObj group any more, so it's 0 based
      name = res[how_nested]
      mid_path, name = path.scan(%r{#{File.expand_path("~")}/([^/]+)/([^/]+)}).flatten if name.nil?
      
      if name
        name.chomp!
        key = name.underscore.downcase
        if projects[key].nil?
          project = new mid_path, name
          projects[key] = project
        end
        projects[key]
      else
        nil
      end
    end
  end





  def initialize mid_path, name
    @name = name
    @path = File.expand_path("~/#{mid_path}/#{name}/")
    @pinches = []
  end
  
  
  
  
  # ATTRIBUTES
  
  attr_reader :name, :path, :pinches
    
  def work_time
    pinches.map(&:duration).inject(0.seconds, &:+)
  end

  def days
    pinches.group_by do |pinch|
      pinch.start_time.to_date
    end
  end



  class Pinch
    attr_accessor :start_time, :end_time
    def initialize start_time
      @end_time = @start_time = start_time
    end

    def duration
      end_time ? end_time - start_time : 30.seconds
    end

    def humanized_duration
      seconds = duration

      hours = mins = 0
      if seconds >=  60 then
        mins = (seconds / 60).to_i 
        seconds = (seconds % 60 ).to_i

        if mins >= 60 then<commit_msg>Small refactorings<commit_after>require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/numeric/time'

class TimeTap::Project
    
  # CONFIG
    
  class << self
    attr_accessor :pause_limit
    attr_reader :projects
    attr_reader :backend
    
    def reload!
      @pause_limit = 30.minutes
      @projects = {}.with_indifferent_access
      @backend = TimeTap.backend
    end
  end
  reload!

  def logger
    self.class.logger
  end




  class << self
    def logger
      TimeTap.logger
    end
    
    def all
      backend.each_entry do |time, path|
        register time, path
      end unless @loaded
      @loaded = true
      projects.values
    end
    
    def register time, path
      project = self[path]
      if project
        project << time
        logger.info "[TimeTap::Project] added #{time} to project #{project.name} (#{project})"
      else
        logger.info "[TimeTap::Project] skipping #{time}, no project"
      end
    end
    
    def find name
      projects[name.underscore.downcase]
    end

    def [] path
      return if path.nil? or path.empty?
      path = File.expand_path(path)
      how_nested = 1

      regex_suffix = "([^/]+)"
      
      folders = TimeTap.config[:code_folders].map do |folder|
        folder = File.expand_path(folder)
        folder = Dir[folder]
      end.flatten
      
      folders_regex = folders.map{|f| Regexp.escape f}.join('|')
      res = path.scan(%r{(#{folders_regex})/#{regex_suffix}}).flatten
      
      # res = path.scan(%r{(#{TimeTap.config[:code] || "Code"})/#{regex_suffix}}).flatten
      mid_path = res[0] # not in a MatchObj group any more, so it's 0 based
      name = res[how_nested]
      mid_path, name = path.scan(%r{#{File.expand_path("~")}/([^/]+)/([^/]+)}).flatten if name.nil?
      
      if name
        name.chomp!
        key = name.underscore.downcase
        if projects[key].nil?
          project = new mid_path, name
          projects[key] = project
        end
        projects[key]
      else
        nil
      end
    end
  end





  def initialize mid_path, name
    @name = name
    @path = File.expand_path("~/#{mid_path}/#{name}/")
    @pinches = []
  end
  
  
  
  
  # ATTRIBUTES
  
  attr_reader :name, :path, :pinches
    
  def work_time
    pinches.sum(&:duration)
  end

  def days
    pinches.group_by do |pinch|
      pinch.start_time.to_date
    end
  end



  class Pinch
    attr_accessor :start_time, :end_time
    def initialize start_time
      @end_time = @start_time = start_time
    end

    def duration
      end_time ? end_time - start_time : 30.seconds
    end

    def humanized_duration
      seconds = duration

      hours = mins = 0
      if seconds >=  60 then
        mins = (seconds / 60).to_i 
        seconds = (seconds % 60 ).to_i

        if mins >= 60 then
{'fraction_non_alphanumeric': 0.10963455149501661, 'fraction_numerical': 0.005770239552369295, 'mean_word_length': 2.0952380952380953, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 7, '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': '7185300', 'n_tokens_mistral': 1944, 'n_tokens_neox': 1860, 'n_words': 444}