<commit_before>require 'blacklight_cornell_requests/cornell'
require 'blacklight_cornell_requests/borrow_direct'

module BlacklightCornellRequests
  class Request

    L2L = 'l2l'
    BD = 'bd'
    HOLD = 'hold'
    RECALL = 'recall'
    PURCHASE = 'purchase' # Note: this is a *purchase request*, which is different from a patron-driven acquisition
    PDA = 'pda'
    ILL = 'ill'
    ASK_CIRCULATION = 'circ'
    ASK_LIBRARIAN = 'ask'
    LIBRARY_ANNEX = 'Library Annex'
    HOLD_PADDING_TIME = 3

    # attr_accessible :title, :body
    include ActiveModel::Validations
    include Cornell::LDAP
    include BorrowDirect

    attr_accessor :bibid, :holdings_data, :service, :document, :request_options, :alternate_options
    attr_accessor :au, :ti, :isbn, :document, :ill_link, :pub_info, :netid, :estimate, :items, :volumes
    attr_accessor :L2L, :BD, :HOLD, :RECALL, :PURCHASE, :PDA, :ILL, :ASK_CIRCULATION, :ASK_LIBRARIAN
    validates_presence_of :bibid
    def save(validate = true)
      validate ? valid? : true
    end

    def initialize(bibid)
      self.bibid = bibid
    end

    def save!
      save
    end

    def get_hold_padding
      HOLD_PADDING_TIME
    end

    ##################### Calculate optimum request method ##################### 
    def magic_request(document, env_http_host, options = {})

      target = options[:target]
      volume = options[:volume]
      request_options = []
      alternate_options = []
      service = ASK_LIBRARIAN

      if self.bibid.nil?
        self.request_options = request_options
        self.service = { :service => service }
        self.document = document
        return
      end

      # Get holdings
      get_holdings 'retrieve_detail_raw' unless self.holdings_data

      # Get item status and location for each item in each holdings record; store in all_items
      all_items = []
      item_status = 'Charged'
      holdings = self.holdings_data[self.bibid.to_s]['records']
      holdings.each do |h|
        items = h['item_status']['itemdata']
        items.each do |i|
          # If volume is specified, only populate items with matching enum/chron/year values
          next if (!volume.blank? and ( volume != i['enumeration'] and volume != i['chron'] and volume != i['year']))

          status = item_status i['itemStatus']
          iid = deep_copy(i)
          all_items.push({ :id => i['itemid'], 
                           :status => status, 
                           'location' => i[:location],
                           :typeCode => i['typeCode'],
                           :enumeration => i['enumeration'],
                           :chron => i['chron'],
                           :year => i['year'],
                           :iid => iid
                         })
        end
      end

      self.items = all_items
      self.document = document

      unless document.nil?

        # Iterate through all items and get list of delivery methods
        bd_params = { :isbn => document[:isbn_display], :title => document[:title_display], :env_http_host => env_http_host }
        all_items.each do |item|
          services = get_delivery_options item, bd_params
          item[:services] = services
        end
        populate_document_values

        # Determine whether this is a multi-volume thing or not (i.e, multi-copy)
        # They will be handled differently depending
        if self.document[:multivol_b] and volume.blank?

          # Multi-volume
          volumes = {}
          all_items.each do |item|
            volumes[item[:enumeration]] = 1 unless item[:enumeration].blank? 
            volumes[item[:chron]] = 1 unless item[:chron].blank?
            volumes[item[:year]] = 1 unless item[:year].blank?
          end

          self.volumes = sort_volumes(volumes.keys)

        else

          # Multi-copy
          all_items.each do |item|
            request_options.push *item[:services]
          end
          request_options = sort_request_options request_options
        
        end

      end
  
      if !target.blank?
        self.service = target
      elsif request_options.present?
        self.service = request_options[0][:service]
      else
        self.service = ASK_LIBRARIAN
      end

      request_options.push ({:service => ASK_LIBRARIAN, :estimate => get_delivery_time(ASK_LIBRARIAN, nil)})
      populate_options self.service, request_options unless self.service == ASK_LIBRARIAN
      
      self.document = document
      
    end   
    
    def populate_options target, request_options
      self.alternate_options = []
      self.request_options = []
      seen = {}
      request_options.each do |option|
        if option[:service] == target
          self.estimate = option[:estimate] if self.estimate.blank?
          self.request_options.push option
        else
          if seen[option[:service]].blank?
            self.alternate_options.push option
            seen[option[:service]] = 1
          end
        end
      end
    end

    # Sort volumes in their logical order for display.
    # Volume strings typically look like 'v.1', 'v21-22', 'index v.1-10', etc.
    def sort_volumes(volumes)

      volumes = volumes.sort_by do |v|

        if v.is_a? Integer
          [Integer(v)]
        else
          a, b, c = v.split(/[\.\-]/) 
          if b.nil?
            [a]
          else
            [a, Integer(b)]
          end
        end
      end

      volumes

    end

    ##################### Manipulate holdings data #####################

    # Set holdings data from the Voyager service configured in the
    # environments file.
    # holdings_param = { :bibid => <bibid>, :type => retrieve|retrieve_detail_raw}
    def get_holdings(type = 'retrieve')

      return nil unless self.bibid

      response = JSON.parse(HTTPClient.get_content(Rails.configuration.voyager_holdings + "/holdings/#{type}/#{self.bibid}"))<commit_msg>Add check for commas in volume strings.<commit_after>require 'blacklight_cornell_requests/cornell'
require 'blacklight_cornell_requests/borrow_direct'

module BlacklightCornellRequests
  class Request

    L2L = 'l2l'
    BD = 'bd'
    HOLD = 'hold'
    RECALL = 'recall'
    PURCHASE = 'purchase' # Note: this is a *purchase request*, which is different from a patron-driven acquisition
    PDA = 'pda'
    ILL = 'ill'
    ASK_CIRCULATION = 'circ'
    ASK_LIBRARIAN = 'ask'
    LIBRARY_ANNEX = 'Library Annex'
    HOLD_PADDING_TIME = 3

    # attr_accessible :title, :body
    include ActiveModel::Validations
    include Cornell::LDAP
    include BorrowDirect

    attr_accessor :bibid, :holdings_data, :service, :document, :request_options, :alternate_options
    attr_accessor :au, :ti, :isbn, :document, :ill_link, :pub_info, :netid, :estimate, :items, :volumes
    attr_accessor :L2L, :BD, :HOLD, :RECALL, :PURCHASE, :PDA, :ILL, :ASK_CIRCULATION, :ASK_LIBRARIAN
    validates_presence_of :bibid
    def save(validate = true)
      validate ? valid? : true
    end

    def initialize(bibid)
      self.bibid = bibid
    end

    def save!
      save
    end

    def get_hold_padding
      HOLD_PADDING_TIME
    end

    ##################### Calculate optimum request method ##################### 
    def magic_request(document, env_http_host, options = {})

      target = options[:target]
      volume = options[:volume]
      request_options = []
      alternate_options = []
      service = ASK_LIBRARIAN

      if self.bibid.nil?
        self.request_options = request_options
        self.service = { :service => service }
        self.document = document
        return
      end

      # Get holdings
      get_holdings 'retrieve_detail_raw' unless self.holdings_data

      # Get item status and location for each item in each holdings record; store in all_items
      all_items = []
      item_status = 'Charged'
      holdings = self.holdings_data[self.bibid.to_s]['records']
      holdings.each do |h|
        items = h['item_status']['itemdata']
        items.each do |i|
          # If volume is specified, only populate items with matching enum/chron/year values
          next if (!volume.blank? and ( volume != i['enumeration'] and volume != i['chron'] and volume != i['year']))

          status = item_status i['itemStatus']
          iid = deep_copy(i)
          all_items.push({ :id => i['itemid'], 
                           :status => status, 
                           'location' => i[:location],
                           :typeCode => i['typeCode'],
                           :enumeration => i['enumeration'],
                           :chron => i['chron'],
                           :year => i['year'],
                           :iid => iid
                         })
        end
      end

      self.items = all_items
      self.document = document

      unless document.nil?

        # Iterate through all items and get list of delivery methods
        bd_params = { :isbn => document[:isbn_display], :title => document[:title_display], :env_http_host => env_http_host }
        all_items.each do |item|
          services = get_delivery_options item, bd_params
          item[:services] = services
        end
        populate_document_values

        # Determine whether this is a multi-volume thing or not (i.e, multi-copy)
        # They will be handled differently depending
        if self.document[:multivol_b] and volume.blank?

          # Multi-volume
          volumes = {}
          all_items.each do |item|
            volumes[item[:enumeration]] = 1 unless item[:enumeration].blank? 
            volumes[item[:chron]] = 1 unless item[:chron].blank?
            volumes[item[:year]] = 1 unless item[:year].blank?
          end

          self.volumes = sort_volumes(volumes.keys)

        else

          # Multi-copy
          all_items.each do |item|
            request_options.push *item[:services]
          end
          request_options = sort_request_options request_options
        
        end

      end
  
      if !target.blank?
        self.service = target
      elsif request_options.present?
        self.service = request_options[0][:service]
      else
        self.service = ASK_LIBRARIAN
      end

      request_options.push ({:service => ASK_LIBRARIAN, :estimate => get_delivery_time(ASK_LIBRARIAN, nil)})
      populate_options self.service, request_options unless self.service == ASK_LIBRARIAN
      
      self.document = document
      
    end   
    
    def populate_options target, request_options
      self.alternate_options = []
      self.request_options = []
      seen = {}
      request_options.each do |option|
        if option[:service] == target
          self.estimate = option[:estimate] if self.estimate.blank?
          self.request_options.push option
        else
          if seen[option[:service]].blank?
            self.alternate_options.push option
            seen[option[:service]] = 1
          end
        end
      end
    end

    # Sort volumes in their logical order for display.
    # Volume strings typically look like 'v.1', 'v21-22', 'index v.1-10', etc.
    def sort_volumes(volumes)

      volumes = volumes.sort_by do |v|

        if v.is_a? Integer
          [Integer(v)]
        else
          a, b, c = v.split(/[\.\-,]/) 
          if b.nil?
            [a]
          else
            [a, Integer(b)]
          end
        end
      end

      volumes

    end

    ##################### Manipulate holdings data #####################

    # Set holdings data from the Voyager service configured in the
    # environments file.
    # holdings_param = { :bibid => <bibid>, :type => retrieve|retrieve_detail_raw}
    def get_holdings(type = 'retrieve')

      return nil unless self.bibid

      response = JSON.parse(HTTPClient.get_content(Rails.configuration.voyager_holdings + "/holdings/#{type}/#{self.bibid}"))
{'fraction_non_alphanumeric': 0.11046462602243022, 'fraction_numerical': 0.0028670208280630743, 'mean_word_length': 2.1660437800320342, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 37, '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': '1363651', 'n_tokens_mistral': 3588, 'n_tokens_neox': 3401, 'n_words': 865}