<commit_before>require 'super_state/common_states'
require 'active_support/ordered_hash'

module SuperState
  
  def self.included(klass)
    klass.class_eval do
      cattr_accessor :initial_super_state
      cattr_accessor :__super_states
      cattr_accessor :super_state_groups
      self.__super_states     = StateArray.new.all_states!
      self.super_state_groups = StateGroups.new
      
      extend ClassMethods
      include InstanceMethods
      
      # the initial_state only takes effect when we say record.valid?
      before_validation :set_initial_super_state, :on => :create
      
      validate :ensure_super_state
    end
  end
  
  # states should be stored as strings in all cases
  # (if it needs to be a sym, we should explicitly ask it to be)
  def self.canonicalise(value)
    if value
      if value.is_a?(Array)
        value.map{|v| self.canonicalise(v)}
      else
        value.to_s
      end
    end
  end
  
  # I want to know the states are the same
  class StateArray < Array
    
    def initialize(array=nil)
      super(SuperState.canonicalise(Array(array)))
    end
    
    def <<(value)
      super(SuperState.canonicalise(value))
    end
    
    def include?(value)
      super(SuperState.canonicalise(value))
    end
    
    def for_select
      self.map do |value|
        [value.humanize, value]
      end
    end
    
    def all_states!
      @all_states = true
      self
    end
    
    def all_states?
      @all_states
    end
    
  end
  
  class StateGroups < ActiveSupport::OrderedHash
    
    def []=(key, value)
      super(SuperState.canonicalise(key), SuperState.canonicalise(value))
    end
    
    def [](key)
      super(SuperState.canonicalise(key))
    end
    
    def keys
      StateArray.new(super)
    end
  
  end
  
  module InstanceMethods
    
    def current_super_state
      self[self.class.super_state_column] || SuperState.canonicalise(self.class.initial_super_state)
    end
    
    def set_initial_super_state
      set_super_state(self.class.initial_super_state)
    end
    
    def set_super_state(state_name, set_timestamps=true)
      self[self.class.super_state_column] = SuperState.canonicalise(state_name)
      
      if set_timestamps && self.respond_to?("#{state_name}_at=")
        self.send("#{state_name}_at=", Time.now)
      end
      
      self.current_super_state
    end
    
    def human_super_state
      self.current_super_state.humanize
    end
    
    def ensure_super_state
      unless self.class.__super_states.include?(self.current_super_state)
        errors[self.class.super_state_column] << "is not a valid super state"
      end
    end
    
  end
  
  class BadState < ArgumentError ; end
  
  module ClassMethods
    
    def super_states_for_select(options={})
      rtn = []
      if options[:include_all]<commit_msg>this is a bad name for validation<commit_after>require 'super_state/common_states'
require 'active_support/ordered_hash'

module SuperState
  
  def self.included(klass)
    klass.class_eval do
      cattr_accessor :initial_super_state
      cattr_accessor :__super_states
      cattr_accessor :super_state_groups
      self.__super_states     = StateArray.new.all_states!
      self.super_state_groups = StateGroups.new
      
      extend ClassMethods
      include InstanceMethods
      
      # the initial_state only takes effect when we say record.valid?
      before_validation :set_initial_super_state, :on => :create
      
      validate :validate_super_state
    end
  end
  
  # states should be stored as strings in all cases
  # (if it needs to be a sym, we should explicitly ask it to be)
  def self.canonicalise(value)
    if value
      if value.is_a?(Array)
        value.map{|v| self.canonicalise(v)}
      else
        value.to_s
      end
    end
  end
  
  # I want to know the states are the same
  class StateArray < Array
    
    def initialize(array=nil)
      super(SuperState.canonicalise(Array(array)))
    end
    
    def <<(value)
      super(SuperState.canonicalise(value))
    end
    
    def include?(value)
      super(SuperState.canonicalise(value))
    end
    
    def for_select
      self.map do |value|
        [value.humanize, value]
      end
    end
    
    def all_states!
      @all_states = true
      self
    end
    
    def all_states?
      @all_states
    end
    
  end
  
  class StateGroups < ActiveSupport::OrderedHash
    
    def []=(key, value)
      super(SuperState.canonicalise(key), SuperState.canonicalise(value))
    end
    
    def [](key)
      super(SuperState.canonicalise(key))
    end
    
    def keys
      StateArray.new(super)
    end
  
  end
  
  module InstanceMethods
    
    def current_super_state
      self[self.class.super_state_column] || SuperState.canonicalise(self.class.initial_super_state)
    end
    
    def set_initial_super_state
      set_super_state(self.class.initial_super_state)
    end
    
    def set_super_state(state_name, set_timestamps=true)
      self[self.class.super_state_column] = SuperState.canonicalise(state_name)
      
      if set_timestamps && self.respond_to?("#{state_name}_at=")
        self.send("#{state_name}_at=", Time.now)
      end
      
      self.current_super_state
    end
    
    def human_super_state
      self.current_super_state.humanize
    end
    
    def validate_super_state
      unless self.class.__super_states.include?(self.current_super_state)
        errors[self.class.super_state_column] << "is not a valid super state"
      end
    end
    
  end
  
  class BadState < ArgumentError ; end
  
  module ClassMethods
    
    def super_states_for_select(options={})
      rtn = []
      if options[:include_all]
{'fraction_non_alphanumeric': 0.07247899159663866, 'fraction_numerical': 0.0, 'mean_word_length': 2.485661989017694, 'pattern_counts': {'":': 0, '<': 17, '<?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': '4288925', 'n_tokens_mistral': 1804, 'n_tokens_neox': 1793, 'n_words': 389}