def connect
      start_time = Time.now
      retries    = 0
      close

      # Number of times to try
      begin
        connect_to_server(servers, policy)
        logger.info(message: "Connected to #{address}", duration: (Time.now - start_time) * 1000) if respond_to?(:logger)
      rescue ConnectionFailure, ConnectionTimeout => exception
        cause = exception.is_a?(ConnectionTimeout) ? exception : exception.cause
        # Retry-able?
        if self.class.reconnect_on_errors.include?(cause.class) && (retries < connect_retry_count.to_i)
          retries += 1
          logger.warn "#connect Failed to connect to any of #{servers.join(',')}. Sleeping:#{connect_retry_interval}s. Retry: #{retries}" if respond_to?(:logger)
          sleep(connect_retry_interval)
          retry
        else
          message = "#connect Failed to connect to any of #{servers.join(',')} after #{retries} retries. #{exception.class}: #{exception.message}"
          logger.benchmark_error(message, exception: exception, duration: (Time.now - start_time)) if respond_to?(:logger)
          raise ConnectionFailure.new(message, address.to_s, cause)
        end
      end
    end

Create a new TCP Client connection

 Parameters:
   :server [String]
     URL of the server to connect to with port number
     'localhost:2000'
     '192.168.1.10:80'

   :servers [Array of String]
     Array of URL's of servers to connect to with port numbers
     ['server1:2000', 'server2:2000']

     The second server will only be attempted once the first server
     cannot be connected to or has timed out on connect
     A read failure or timeout will not result in switching to the second
     server, only a connection failure or during an automatic reconnect

   :connect_timeout [Float]
     Time in seconds to timeout when trying to connect to the server
     A value of -1 will cause the connect wait time to be infinite
     Default: 10 seconds

   :read_timeout [Float]
     Time in seconds to timeout on read
     Can be overridden by supplying a timeout in the read call
     Default: 60

   :write_timeout [Float]
     Time in seconds to timeout on write
     Can be overridden by supplying a timeout in the write call
     Default: 60

   :buffered [true|false]
     Whether to use Nagle's Buffering algorithm (http://en.wikipedia.org/wiki/Nagle's_algorithm)
     Recommend disabling for RPC style invocations where we don't want to wait for an
     ACK from the server before sending the last partial segment
     Buffering is recommended in a browser or file transfer style environment
     where multiple sends are expected during a single response.
     Also sets sync to true if buffered is false so that all data is sent immediately without
     internal buffering.
     Default: true

   :keepalive [true|false]
     Makes the OS check connections even when not in use, so that failed connections fail immediately
     upon use instead of possibly taking considerable time to fail.
     Default: true

   :connect_retry_count [Fixnum]
     Number of times to retry connecting when a connection fails
     Default: 10

   :connect_retry_interval [Float]
     Number of seconds between connection retry attempts after the first failed attempt
     Default: 0.5

   :retry_count [Fixnum]
     Number of times to retry when calling #retry_on_connection_failure
     This is independent of :connect_retry_count which still applies with
     connection failures. This retry controls upto how many times to retry the
     supplied block should a connection failure occur during the block
     Default: 3

   :on_connect [Proc]
     Directly after a connection is established and before it is made available
     for use this Block is invoked.
     Typical Use Cases:
     - Initialize per connection session sequence numbers.
     - Pass authentication information to the server.
     - Perform a handshake with the server.

   :policy [Symbol|Proc]
     Specify the policy to use when connecting to servers.
       :ordered
         Select a server in the order supplied in the array, with the first
         having the highest priority. The second server will only be connected
         to if the first server is unreachable
       :random
         Randomly select a server from the list every time a connection
         is established, including during automatic connection recovery.
       :ping_time
         FUTURE - Not implemented yet - Pull request anyone?
         The server with the lowest ping time will be tried first
       Proc:
         When a Proc is supplied, it will be called passing in the list
         of servers. The Proc must return one server name
           Example:
             :policy => Proc.new do |servers|
               servers.last
             end
       Default: :ordered

   :close_on_error [True|False]
     To prevent the connection from going into an inconsistent state
     automatically close the connection if an error occurs
     This includes a Read Timeout
     Default: true

   :proxy_server [String]
     The host name and port in the form of 'host_name:1234' to forward
     socket connections though.
     Default: nil ( none )

   SSL Options
   :ssl [true|false|Hash]
      true:  SSL is enabled using the SSL context defaults.
      false: SSL is not used.
      Hash:
        Keys from OpenSSL::SSL::SSLContext:
          ca_file, ca_path, cert, cert_store, ciphers, key, ssl_timeout, ssl_version
          verify_callback, verify_depth, verify_mode
        handshake_timeout: [Float]
          The number of seconds to timeout the SSL Handshake.
          Default: connect_timeout
      Default: false.
        See OpenSSL::SSL::SSLContext::DEFAULT_PARAMS for the defaults.

 Example:
   client = Net::TCPClient.new(
     server:                 'server:3300',
     connect_retry_interval: 0.1,
     connect_retry_count:    5
   )

   client.retry_on_connection_failure do
     client.write('Update the database')
   end

   # Read upto 20 characters from the server
   response = client.read(20)

   puts "Received: #{response}"
   client.close

 SSL Example:
   client = Net::TCPClient.new(
     server:                 'server:3300',
     connect_retry_interval: 0.1,
     connect_retry_count:    5,
     ssl:                    true
   )

 SSL with options Example:
   client = Net::TCPClient.new(
     server:                 'server:3300',
     connect_retry_interval: 0.1,
     connect_retry_count:    5,
     ssl:                    {
       verify_mode: OpenSSL::SSL::VERIFY_NONE
     }
   )
 Connect to the TCP server

 Raises Net::TCPClient::ConnectionTimeout when the time taken to create a connection
        exceeds the :connect_timeout
 Raises Net::TCPClient::ConnectionFailure whenever Socket raises an error such as Error::EACCESS etc, see Socket#connect for more information

 Error handling is implemented as follows:
 1. TCP Socket Connect failure:
    Cannot reach server
    Server is being restarted, or is not running
    Retry 50 times every 100ms before raising a Net::TCPClient::ConnectionFailure
    - Means all calls to #connect will take at least 5 seconds before failing if the server is not running
    - Allows hot restart of server process if it restarts within 5 seconds

 2. TCP Socket Connect timeout:
    Timed out after 5 seconds trying to connect to the server
    Usually means server is busy or the remote server disappeared off the network recently
    No retry, just raise a Net::TCPClient::ConnectionTimeout

 Note: When multiple servers are supplied it will only try to connect to
       the subsequent servers once the retry count has been exceeded

 Note: Calling #connect on an open connection will close the current connection
       and create a new connection


def write(data, timeout = write_timeout)
      data = data.to_s
      if respond_to?(:logger)
        payload        = {timeout: timeout}
        # With trace level also log the sent data
        payload[:data] = data if logger.trace?
        logger.benchmark_debug('#write', payload: payload) do
          payload[:bytes] = socket_write(data, timeout)
        end
      else
        socket_write(data, timeout)
      end
    rescue Exception => exc
      close if close_on_error
      raise exc
    end

def write ( data , timeout = write_timeout ) data = data . to_s if respond_to? ( :logger ) payload = { timeout : timeout } payload [ :data ] = data if logger . trace? logger . benchmark_debug ( '#write' , payload : payload ) do payload [ :bytes ] = socket_write ( data , timeout ) end else socket_write ( data , timeout ) end rescue Exception => exc close if close_on_error raise exc end

Write data to the server

 Use #with_retry to add resilience to the #write method

 Raises Net::TCPClient::ConnectionFailure whenever the write fails
        For a description of the errors, see Socket#write

 Parameters
   timeout [Float]
     Optional: Override the default write timeout for this write
     Number of seconds before raising Net::TCPClient::WriteTimeout when no data has
     been written.
     A value of -1 will wait forever
     Default: :write_timeout supplied to #initialize

  Note: After a Net::TCPClient::ReadTimeout #read can be called again on
        the same socket to read the response later.
        If the application no longer wants the connection after a
        Net::TCPClient::ReadTimeout, then the #close method _must_ be called
        before calling _connect_ or _retry_on_connection_failure_ to create
        a new connection


def read(length, buffer = nil, timeout = read_timeout)
      if respond_to?(:logger)
        payload = {bytes: length, timeout: timeout}
        logger.benchmark_debug('#read', payload: payload) do
          data           = socket_read(length, buffer, timeout)
          # With trace level also log the received data
          payload[:data] = data if logger.trace?
          data
        end
      else
        socket_read(length, buffer, timeout)
      end
    rescue Exception => exc
      close if close_on_error
      raise exc
    end

def read ( length , buffer = nil , timeout = read_timeout ) if respond_to? ( :logger ) payload = { bytes : length , timeout : timeout } logger . benchmark_debug ( '#read' , payload : payload ) do data = socket_read ( length , buffer , timeout ) payload [ :data ] = data if logger . trace? data end else socket_read ( length , buffer , timeout ) end rescue Exception => exc close if close_on_error raise exc end

Returns a response from the server

 Raises Net::TCPClient::ConnectionTimeout when the time taken to create a connection
        exceeds the :connect_timeout
        Connection is closed
 Raises Net::TCPClient::ConnectionFailure whenever Socket raises an error such as
        Error::EACCESS etc, see Socket#connect for more information
        Connection is closed
 Raises Net::TCPClient::ReadTimeout if the timeout has been exceeded waiting for the
        requested number of bytes from the server
        Partial data will not be returned
        Connection is _not_ closed and #read can be called again later
        to read the response from the connection

 Parameters
   length [Fixnum]
     The number of bytes to return
     #read will not return until 'length' bytes have been received from
     the server

   buffer [String]
    Optional buffer into which to write the data that is read.

   timeout [Float]
     Optional: Override the default read timeout for this read
     Number of seconds before raising Net::TCPClient::ReadTimeout when no data has
     been returned
     A value of -1 will wait forever for a response on the socket
     Default: :read_timeout supplied to #initialize

  Note: After a Net::TCPClient::ReadTimeout #read can be called again on
        the same socket to read the response later.
        If the application no longer wants the connection after a
        Net::TCPClient::ReadTimeout, then the #close method _must_ be called
        before calling _connect_ or _retry_on_connection_failure_ to create
        a new connection


def close
      socket.close if socket && !socket.closed?
      @socket  = nil
      @address = nil
      true
    rescue IOError => exception
      logger.warn "IOError when attempting to close socket: #{exception.class}: #{exception.message}" if respond_to?(:logger)
      false
    end

Close the socket only if it is not already closed

 Logs a warning if an error occurs trying to close the socket


def alive?
      return false if socket.nil? || closed?

      if IO.select([socket], nil, nil, 0)
        !socket.eof? rescue false
      else
        true
      end
    rescue IOError
      false
    end

def alive? return false if socket . nil? || closed? if IO . select ( [ socket ] , nil , nil , 0 ) ! socket . eof? rescue false else true end rescue IOError false end

Returns whether the connection to the server is alive

 It is useful to call this method before making a call to the server
 that would change data on the server

 Note: This method is only useful if the server closed the connection or
       if a previous connection failure occurred.
       If the server is hard killed this will still return true until one
       or more writes are attempted

 Note: In testing the overhead of this call is rather low, with the ability to
 make about 120,000 calls per second against an active connection.
 I.e. About 8.3 micro seconds per call


def socket_connect(socket, address, timeout)
      socket_address = Socket.pack_sockaddr_in(address.port, address.ip_address)

      # Timeout of -1 means wait forever for a connection
      return socket.connect(socket_address) if timeout == -1

      deadline = Time.now.utc + timeout
      begin
        non_blocking(socket, deadline) { socket.connect_nonblock(socket_address) }
      rescue Errno::EISCONN
        # Connection was successful.
      rescue NonBlockingTimeout
        raise ConnectionTimeout.new("Timed out after #{timeout} seconds trying to connect to #{address}")
      rescue SystemCallError, IOError => exception
        message = "#connect Connection failure connecting to '#{address.to_s}': #{exception.class}: #{exception.message}"
        logger.error message if respond_to?(:logger)
        raise ConnectionFailure.new(message, address.to_s, exception)
      end
    end

Connect to server

 Raises Net::TCPClient::ConnectionTimeout when the connection timeout has been exceeded
 Raises Net::TCPClient::ConnectionFailure


def socket_write(data, timeout)
      if timeout < 0
        socket.write(data)
      else
        deadline = Time.now.utc + timeout
        length = data.bytesize
        total_count = 0
        non_blocking(socket, deadline) do
          loop do
            begin
              count = socket.write_nonblock(data)
            rescue Errno::EWOULDBLOCK
              retry
            end
            total_count += count
            return total_count if total_count >= length
            data = data.byteslice(count..-1)
          end
        end
      end
    rescue NonBlockingTimeout
      logger.warn "#write Timeout after #{timeout} seconds" if respond_to?(:logger)
      raise WriteTimeout.new("Timed out after #{timeout} seconds trying to write to #{address}")
    rescue SystemCallError, IOError => exception
      message = "#write Connection failure while writing to '#{address.to_s}': #{exception.class}: #{exception.message}"
      logger.error message if respond_to?(:logger)
      raise ConnectionFailure.new(message, address.to_s, exception)
    end


def ssl_connect(socket, address, timeout)
      ssl_context = OpenSSL::SSL::SSLContext.new
      ssl_context.set_params(ssl.is_a?(Hash) ? ssl : {})

      ssl_socket            = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
      ssl_socket.hostname   = address.host_name
      ssl_socket.sync_close = true

      begin
        if timeout == -1
          # Timeout of -1 means wait forever for a connection
          ssl_socket.connect
        else
          deadline = Time.now.utc + timeout
          begin
            non_blocking(socket, deadline) { ssl_socket.connect_nonblock }
          rescue Errno::EISCONN
            # Connection was successful.
          rescue NonBlockingTimeout
            raise ConnectionTimeout.new("SSL handshake Timed out after #{timeout} seconds trying to connect to #{address.to_s}")
          end
        end
      rescue SystemCallError, OpenSSL::SSL::SSLError, IOError => exception
        message = "#connect SSL handshake failure with '#{address.to_s}': #{exception.class}: #{exception.message}"
        logger.error message if respond_to?(:logger)
        raise ConnectionFailure.new(message, address.to_s, exception)
      end

      # Verify Peer certificate
      ssl_verify(ssl_socket, address) if ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
      ssl_socket
    end

Try connecting to a single server
 Returns the connected socket

 Raises Net::TCPClient::ConnectionTimeout when the connection timeout has been exceeded
 Raises Net::TCPClient::ConnectionFailure


def party_mode new_master = nil
      return nil unless speakers.length > 1

      new_master = find_party_master if new_master.nil?

      party_over
      speakers.each do |slave|
        next if slave.uid == new_master.uid
        slave.join new_master
      end
      rescan @topology
    end

def party_mode new_master = nil return nil unless speakers . length > 1 new_master = find_party_master if new_master . nil? party_over speakers . each do | slave | next if slave . uid == new_master . uid slave . join new_master end rescan @topology end

Party Mode!  Join all speakers into a single group.

Party Mode! Join all speakers into a single group .


def discover
      result = SSDP::Consumer.new.search(service: 'urn:schemas-upnp-org:device:ZonePlayer:1', first_only: true, timeout: @timeout, filter: lambda {|r| r[:params]["ST"].match(/ZonePlayer/) })
      @first_device_ip = result[:address]
    end

Look for Sonos devices on the network and return the first IP address found
 @return [String] the IP address of the first Sonos device found


def topology
      self.discover unless @first_device_ip
      return [] unless @first_device_ip

      doc = Nokogiri::XML(open("http://#{@first_device_ip}:#{Sonos::PORT}/status/topology"))
      doc.xpath('//ZonePlayers/ZonePlayer').map do |node|
        TopologyNode.new(node)
      end
    end

Find all of the Sonos devices on the network
 @return [Array] an array of TopologyNode objects


def find(id)
      response = RestClient.get("#{@type.Resource}/#{id}")
      singular_resource = @type.Resource[0...-1]
      if response.body[singular_resource].nil?
        raise ArgumentError, 'Resource not found'
      end

      type.new.from_json(response.body[singular_resource].to_json)
    end

def
find
(
id
)
response
=
RestClient
.
get
(
"#{@type.Resource}/#{id}"
)
singular_resource
=
@type
.
Resource
[
0
...
1
]
if
response
.
body
[
singular_resource
]
.
nil?
raise
ArgumentError
,
'Resource not found'
end
type
.
new
.
from_json
(
response
.
body
[
singular_resource
]
.
to_json
)
end

Find a single resource by the resource id

 @param id [String] the resource id
 @return [Object] the Type object response


def all
      list = []
      page = 1
      fetch_all = true

      if @query.has_key?(:page)
        page = @query[:page]
        fetch_all = false
      end

      while true
        response = RestClient.get(@type.Resource, @query)
        data = response.body[@type.Resource]
        if !data.empty?
          data.each {|item| list << @type.new.from_json(item.to_json)}

          if !fetch_all
            break
          else
            where(page: page += 1)
          end
        else
          break
        end
      end

      return list
    end

def all list = [ ] page = 1 fetch_all = true if @query . has_key? ( :page ) page = @query [ :page ] fetch_all = false end while true response = RestClient . get ( @type . Resource , @query ) data = response . body [ @type . Resource ] if ! data . empty? data . each { | item | list << @type . new . from_json ( item . to_json ) } if ! fetch_all break else where ( page : page += 1 ) end else break end end return list end

Get all resources from a query by paging through data

 @return [Array<Object>] Array of resources


def validate(form)
      property = attributes.first

      # here is the thing: why does AM::UniquenessValidator require a filled-out record to work properly? also, why do we need to set
      # the class? it would be way easier to pass #validate a hash of attributes and get back an errors hash.
      # the class for the finder could either be infered from the record or set in the validator instance itself in the call to ::validates.
      record = form.model_for_property(property)
      record.send("#{property}=", form.send(property))

      @klass = record.class # this is usually done in the super-sucky #setup method.
      super(record).tap do |res|
        form.errors.add(property, record.errors.first.last) if record.errors.present?
      end
    end

def validate ( form ) property = attributes . first record = form . model_for_property ( property ) record . send ( "#{property}=" , form . send ( property ) ) @klass = record . class super ( record ) . tap do | res | form . errors . add ( property , record . errors . first . last ) if record . errors . present? end end

when calling validates it should create the Vali instance already and set @klass there! # TODO: fix this in AM.


def validates(*args, &block)
      validation(name: :default, inherit: true) { validates *args, &block }
    end

def validates ( * args , & block ) validation ( name : :default , inherit : true ) { validates * args , & block } end

moved from reform as not applicable to dry


def update_xml(xml, value)
      wrap(xml).tap do |xml|
        if content?
          add(xml, value)
        elsif name?
          xml.name = value
        elsif array?
          value.each do |v|
            add(XML.add_node(xml, name), v)
          end
        else
          add(XML.add_node(xml, name), value)
        end
      end
    end

def update_xml ( xml , value ) wrap ( xml ) . tap do | xml | if content? add ( xml , value ) elsif name? xml . name = value elsif array? value . each do | v | add ( XML . add_node ( xml , name ) , v ) end else add ( XML . add_node ( xml , name ) , value ) end end end

Updates the text in the given _xml_ block to
 the _value_ provided.

Updates the text in the given _xml_ block to the _value_ provided .


def ipmt(rate, per, nper, pv, fv = 0, end_or_beginning = 0)
      pmt = self.pmt(rate, nper, pv, fv, end_or_beginning)
      fv = self.fv(rate, (per - 1), pmt, pv, end_or_beginning) * rate
      temp = end_or_beginning == 1 ? fv / (1 + rate) : fv

      (per == 1 && end_or_beginning == 1) ? 0.0 : temp
    end

def ipmt ( rate , per , nper , pv , fv = 0 , end_or_beginning = 0 ) pmt = self . pmt ( rate , nper , pv , fv , end_or_beginning ) fv = self . fv ( rate , ( per - 1 ) , pmt , pv , end_or_beginning ) * rate temp = end_or_beginning == 1 ? fv / ( 1 + rate ) : fv ( per == 1 && end_or_beginning == 1 ) ? 0.0 : temp end

Calculates the payment on interest for an investment based on
 constant-amount periodic payments and a constant interest rate.

 @param rate [Float] The interest rate as decimal (not per cent) per period
 @param per [Integer] The amortization period, in terms of number of periods
 @param nper [Integer] The number of payments to be made
 @param pv [Float] The present value
 @param fv [Float] The future value remaining after the final payment has been made
 @param end_or_begining [Integer] Whether payments are due at the end (0) or
   beggining (1) of each period

 @return [Float]

 @example
   Exonio.ipmt(0.075 / 12, 8, 12 * 2, 5000) # ==> -22.612926783996798

Calculates the payment on interest for an investment based on constant - amount periodic payments and a constant interest rate .


def nper(rate, pmt, pv, fv = 0, end_or_beginning = 0)
      z = pmt * (1 + rate * end_or_beginning) / rate
      temp = Math.log((-fv + z) / (pv + z))

      temp / Math.log(1 + rate)
    end

def nper ( rate , pmt , pv , fv = 0 , end_or_beginning = 0 ) z = pmt * ( 1 + rate * end_or_beginning ) / rate temp = Math . log ( ( - fv + z ) / ( pv + z ) ) temp / Math . log ( 1 + rate ) end

Calculates the number of payment periods for an investment based on
 constant-amount periodic payments and a constant interest rate.

 @param rate [Float] The interest rate as decimal (not per cent) per period
 @param pmt [Float] The payment amount made each period
 @param pv [Float] The present value of the payments
 @param fv [Float] The future value remaining after the final payment has been made
 @param end_or_begining [Integer] Whether payments are due at the end (0) or
   beggining (1) of each period

 @return [Float]

 @example
   Exonio.nper(0.07 / 12, -150, 8000) # ==> 64.07334877066185

Calculates the number of payment periods for an investment based on constant - amount periodic payments and a constant interest rate .


def pmt(rate, nper, pv, fv = 0, end_or_beginning = 0)
      temp = (1 + rate) ** nper
      fact = (1 + rate * end_or_beginning) * (temp - 1) / rate

      -(fv + pv * temp) / fact
    end

def pmt ( rate , nper , pv , fv = 0 , end_or_beginning = 0 ) temp = ( 1 + rate ) ** nper fact = ( 1 + rate * end_or_beginning ) * ( temp - 1 ) / rate - ( fv + pv * temp ) / fact end

Calculates the periodic payment for an annuity investment based on
 constant-amount periodic payments and a constant interest rate.

 @param rate [Float] The interest rate as decimal (not per cent) per period
 @param nper [Integer] The number of payments to be made (number of periods)
 @param pv [Float] The present value of the annuity
 @param fv [Float] The future value remaining after the final payment has been made
 @param end_or_begining [Integer] Whether payments are due at the end (0) or
   beggining (1) of each period

 @return [Float]

 @example
   Exonio.pmt(0.075/12, 12*15, 200_000) # ==> -1854.0247200054619

Calculates the periodic payment for an annuity investment based on constant - amount periodic payments and a constant interest rate .


def rate(nper, pmt, pv, fv = 0, end_or_beginning = 0, rate_guess = 0.10)
      guess = rate_guess
      tolerancy = 1e-6
      close = false

      begin
        temp = newton_iter(guess, nper, pmt, pv, fv, end_or_beginning)
        next_guess = (guess - temp).round(20)
        diff = (next_guess - guess).abs
        close = diff < tolerancy
        guess = next_guess
      end while !close

      next_guess
    end

def rate ( nper , pmt , pv , fv = 0 , end_or_beginning = 0 , rate_guess = 0.10 ) guess = rate_guess tolerancy = 1e-6 close = false begin temp = newton_iter ( guess , nper , pmt , pv , fv , end_or_beginning ) next_guess = ( guess - temp ) . round ( 20 ) diff = ( next_guess - guess ) . abs close = diff < tolerancy guess = next_guess end while ! close next_guess end

Calculates the interest rate of an annuity investment based on
 constant-amount periodic payments and the assumption of a constant interest rate.

 @param nper [Integer] The number of payments to be made (number of periods)
 @param pmt [Float] The amount per period to be paid
 @param pv [Float] The present value
 @param fv [Float] The future value remaining after the final payment has been made
 @param end_or_begining [Integer] Whether payments are due at the end (0) or
   beggining (1) of each period
 @param rate_guess [Float] An estimate for what the interest rate will be

 @return [Float]

 @example
   Exonio.rate(12, 363.78, -3056.00) # ==> 0.05963422268883278

Calculates the interest rate of an annuity investment based on constant - amount periodic payments and the assumption of a constant interest rate .


def npv(discount, cashflows)
      total = 0

      cashflows.each_with_index do |cashflow, index|
        total += (cashflow.to_f / (1 + discount.to_f) ** (index + 1))
      end

      total
    end

def npv ( discount , cashflows ) total = 0 cashflows . each_with_index do | cashflow , index | total += ( cashflow . to_f / ( 1 + discount . to_f ) ** ( index + 1 ) ) end total end

Calculates the net present value of an investment based on a
 series of periodic cash flows and a discount rate.

 @param discount [Float] The discount rate of the investment over one period
 @param cashflows [Array] The first future cash flow + additional future cash flows

 @return [Float]

 @example
   Exonio.npv(0.281, [-100, 39, 59, 55, 20]) # ==> -0.00661872883563408

Calculates the net present value of an investment based on a series of periodic cash flows and a discount rate .


def irr(values)
      func = Helpers::IrrHelper.new(values)
      guess = [ func.eps ]
      nlsolve( func, guess)
      guess[0]
    end

def irr ( values ) func = Helpers :: IrrHelper . new ( values ) guess = [ func . eps ] nlsolve ( func , guess ) guess [ 0 ] end

Calculates the internal rate of return on an investment based on a
 series of periodic cash flows.

 @param cashflows [Array] An array containing the income or payments
 associated with the investment

 @return [Float]

 @example
   Exonio.irr([-100, 39, 59, 55, 20]) # ==> 0.28094842116...

Calculates the internal rate of return on an investment based on a series of periodic cash flows .


This method was borrowed from the NumPy rate formula
 which was generated by Sage


def event_summary(trim_at = 100)
      summary = @event['check']['notification'] || @event['check']['description']
      if summary.nil?
        source = @event['check']['source'] || @event['client']['name']
        event_context = [source, @event['check']['name']].join('/')
        output = @event['check']['output'].chomp
        output = output.length > trim_at ? output[0..trim_at] + '...' : output
        summary = [event_context, output].join(' : ')
      end
      summary
    end

def
event_summary
(
trim_at
=
100
)
summary
=
@event
[
'check'
]
[
'notification'
]
||
@event
[
'check'
]
[
'description'
]
if
summary
.
nil?
source
=
@event
[
'check'
]
[
'source'
]
||
@event
[
'client'
]
[
'name'
]
event_context
=
[
source
,
@event
[
'check'
]
[
'name'
]
]
.
join
(
'/'
)
output
=
@event
[
'check'
]
[
'output'
]
.
chomp
output
=
output
.
length
>
trim_at
output
[
0
..
trim_at
]
+
'...'
:
output
summary
=
[
event_context
,
output
]
.
join
(
' : '
)
end
summary
end


def load
			# we always read 512 for the header block. if the block size ends up being different,
			# what happens to the 109 fat entries. are there more/less entries?
			@io.rewind
			header_block = @io.read 512
			@header = Header.new header_block

			# create an empty bbat.
			@bbat = AllocationTable::Big.new self
			bbat_chain = header_block[Header::SIZE..-1].unpack 'V*'
			mbat_block = @header.mbat_start
			@header.num_mbat.times do
				blocks = @bbat.read([mbat_block]).unpack 'V*'
				mbat_block = blocks.pop
				bbat_chain += blocks
			end
			# am i using num_bat in the right way?
			@bbat.load @bbat.read(bbat_chain[0, @header.num_bat])

			# get block chain for directories, read it, then split it into chunks and load the
			# directory entries. semantics changed - used to cut at first dir where dir.type == 0
			@dirents = @bbat.read(@header.dirent_start).to_enum(:each_chunk, Dirent::SIZE).
				map { |str| Dirent.new self, str }

			# now reorder from flat into a tree
			# links are stored in some kind of balanced binary tree
			# check that everything is visited at least, and at most once
			# similarly with the blocks of the file.
			# was thinking of moving this to Dirent.to_tree instead.
			class << @dirents
				def to_tree idx=0
					return [] if idx == Dirent::EOT
					d = self[idx]
					to_tree(d.child).each { |child| d << child }
					raise FormatError, "directory #{d.inspect} used twice" if d.idx
					d.idx = idx
					to_tree(d.prev) + [d] + to_tree(d.next)
				end
			end

			@root = @dirents.to_tree.first
			@dirents.reject! { |d| d.type_id == 0 }
			# silence this warning by default, its not really important (issue #5).
			# fairly common one appears to be "R" (from office OS X?) which smells
			# like some kind of UTF16 snafu, but scottwillson also has had some kanji...
			#Log.warn "root name was #{@root.name.inspect}" unless @root.name == 'Root Entry'
			unused = @dirents.reject(&:idx).length
			Log.warn "#{unused} unused directories" if unused > 0

			# FIXME i don't currently use @header.num_sbat which i should
			# hmm. nor do i write it. it means what exactly again?
			# which mode to use here?
			@sb_file = RangesIOResizeable.new @bbat, :first_block => @root.first_block, :size => @root.size
			@sbat = AllocationTable::Small.new self
			@sbat.load @bbat.read(@header.sbat_start)
		end

def
load
@io
.
rewind
header_block
=
@io
.
read
512
@header
=
Header
.
new
header_block
@bbat
=
AllocationTable
::
Big
.
new
self
bbat_chain
=
header_block
[
Header
::
SIZE
..
1
]
.
unpack
'V*'
mbat_block
=
@header
.
mbat_start
@header
.
num_mbat
.
times
do
blocks
=
@bbat
.
read
(
[
mbat_block
]
)
.
unpack
'V*'
mbat_block
=
blocks
.
pop
bbat_chain
+=
blocks
end
@bbat
.
load
@bbat
.
read
(
bbat_chain
[
0
,
@header
.
num_bat
]
)
@dirents
=
@bbat
.
read
(
@header
.
dirent_start
)
.
to_enum
(
:each_chunk
,
Dirent
::
SIZE
)
.
map
{
|
str
|
Dirent
.
new
self
,
str
}
class
<<
@dirents
def
to_tree
idx
=
0
return
[
]
if
idx
==
Dirent
::
EOT
d
=
self
[
idx
]
to_tree
(
d
.
child
)
.
each
{
|
child
|
d
<<
child
}
raise
FormatError
,
"directory #{d.inspect} used twice"
if
d
.
idx
d
.
idx
=
idx
to_tree
(
d
.
prev
)
+
[
d
]
+
to_tree
(
d
.
next
)
end
end
@root
=
@dirents
.
to_tree
.
first
@dirents
.
reject!
{
|
d
|
d
.
type_id
==
0
}
unused
=
@dirents
.
reject
(
&
:idx
)
.
length
Log
.
warn
"#{unused} unused directories"
if
unused
>
0
@sb_file
=
RangesIOResizeable
.
new
@bbat
,
:first_block
=>
@root
.
first_block
,
:size
=>
@root
.
size
@sbat
=
AllocationTable
::
Small
.
new
self
@sbat
.
load
@bbat
.
read
(
@header
.
sbat_start
)
end

load document from file.

 TODO: implement various allocationtable checks, maybe as a AllocationTable#fsck function :)

 1. reterminate any chain not ending in EOC.
    compare file size with actually allocated blocks per file.
 2. pass through all chain heads looking for collisions, and making sure nothing points to them
    (ie they are really heads). in both sbat and mbat
 3. we know the locations of the bbat data, and mbat data. ensure that there are placeholder blocks
    in the bat for them.
 4. maybe a check of excess data. if there is data outside the bbat.truncate.length + 1 * block_size,
    (eg what is used for truncate in #flush), then maybe add some sort of message about that. it
    will be automatically thrown away at close time.


def repack temp=:file
			case temp
			when :file
				Tempfile.open 'ole-repack' do |io|
					io.binmode
					repack_using_io io
				end
			when :mem;  StringIO.open(''.dup, &method(:repack_using_io))
			else raise ArgumentError, "unknown temp backing #{temp.inspect}"
			end
		end

def
repack
temp
=
:file
case
temp
when
:file
Tempfile
.
open
'ole-repack'
do
|
io
|
io
.
binmode
repack_using_io
io
end
when
:mem
;
StringIO
.
open
(
''
.
dup
,
&
method
(
:repack_using_io
)
)
else
raise
ArgumentError
,
"unknown temp backing #{temp.inspect}"
end
end

could be useful with mis-behaving ole documents. or to just clean them up.

could be useful with mis - behaving ole documents . or to just clean them up .


def load_relation(relationship, position = nil)
      if objects = @resource.dig("_embedded", relationship)
        location = position ? objects[position] : objects
        begin
          WpApiClient::Collection.new(location)
        rescue WpApiClient::ErrorResponse
          load_from_links(relationship, position)
        end
      else
        load_from_links(relationship, position)
      end
    end

def load_relation ( relationship , position = nil ) if objects = @resource . dig ( "_embedded" , relationship ) location = position ? objects [ position ] : objects begin WpApiClient :: Collection . new ( location ) rescue WpApiClient :: ErrorResponse load_from_links ( relationship , position ) end else load_from_links ( relationship , position ) end end

try to load an embedded object; call out to the API if not

try to load an embedded object ; call out to the API if not


def native_representation_of(response_body)
      # Do we have a collection of objects?
      if response_body.is_a? Array
        WpApiClient::Collection.new(response_body, @headers)
      else
        WpApiClient::Entities::Base.build(response_body)
      end
    end

def native_representation_of ( response_body ) if response_body . is_a? Array WpApiClient :: Collection . new ( response_body , @headers ) else WpApiClient :: Entities :: Base . build ( response_body ) end end

Take the API response and figure out what it is


def call_func(method:, params: [], tx: {}) # rubocop:disable Naming/UncommunicativeMethodParamName
      data, output_types = function_data_with_ot(method, *params)
      resp = @rpc.call_rpc(:call, params: [tx.merge(data: data, to: address), "latest"])
      result = resp["result"]

      data = [Utils.remove_hex_prefix(result)].pack("H*")
      return if data.nil?

      re = decode_abi output_types, data
      re.length == 1 ? re.first : re
    end

def call_func ( method : , params : [ ] , tx : { } ) data , output_types = function_data_with_ot ( method , * params ) resp = @rpc . call_rpc ( :call , params : [ tx . merge ( data : data , to : address ) , "latest" ] ) result = resp [ "result" ] data = [ Utils . remove_hex_prefix ( result ) ] . pack ( "H*" ) return if data . nil? re = decode_abi output_types , data re . length == 1 ? re . first : re end

call contract functions by rpc `call` method

 @param method [Symbol | String] the method name you call
 @param params [Array] the method params you call
 @param tx [Hash] see rpc `call` doc for more info

 @return [any]

call contract functions by rpc call method


def send_func(tx:, private_key:, method:, params: []) # rubocop:disable Naming/UncommunicativeMethodParamName
      data, _output_types = function_data_with_ot(method, *params)
      transaction = if tx.is_a?(Hash)
                      Transaction.from_hash(tx)
                    else
                      tx
                    end
      transaction.data = data
      resp = @rpc.send_transaction(transaction, private_key)

      resp&.dig("result")
    end

def send_func ( tx : , private_key : , method : , params : [ ] ) data , _output_types = function_data_with_ot ( method , * params ) transaction = if tx . is_a? ( Hash ) Transaction . from_hash ( tx ) else tx end transaction . data = data resp = @rpc . send_transaction ( transaction , private_key ) resp &. dig ( "result" ) end

call contract functions by sendRawTransaction

 @param tx [Hash | CITA::Transaction]
 @param private_key [String] hex string
 @param method [Symbol | String] method name you call
 @param *params [Array] your params

 @return [nil | Hash] {hash: "", status: ""}, sendRawTransactionResult


def parse_url
      uri = URI.parse(@url)
      @host = uri.host
      @port = uri.port
      @scheme = uri.scheme
    end

def parse_url uri = URI . parse ( @url ) @host = uri . host @port = uri . port @scheme = uri . scheme end


def call_rpc(method, jsonrpc: DEFAULT_JSONRPC, params: DEFAULT_PARAMS, id: DEFAULT_ID)
      conn.post("/", rpc_params(method, jsonrpc: jsonrpc, params: params, id: id))
    end

def call_rpc ( method , jsonrpc : DEFAULT_JSONRPC , params : DEFAULT_PARAMS , id : DEFAULT_ID ) conn . post ( "/" , rpc_params ( method , jsonrpc : jsonrpc , params : params , id : id ) ) end

wrapper for call rpc method

 @param method [String] method you want to call
 @param jsonrpc [String] jsonrpc version
 @param params [Array] rpc params
 @param id [Integer] jsonrpc id

 @return [Faraday::Response]


def rpc_params(method, jsonrpc: DEFAULT_JSONRPC, params: DEFAULT_PARAMS, id: DEFAULT_ID)
      {
        jsonrpc: jsonrpc,
        id: id,
        method: method,
        params: params
      }.to_json
    end

def rpc_params ( method , jsonrpc : DEFAULT_JSONRPC , params : DEFAULT_PARAMS , id : DEFAULT_ID ) { jsonrpc : jsonrpc , id : id , method : method , params : params } . to_json end

wrapper for rpc params

 @param method [String] method you want to call
 @param jsonrpc [String] jsonrpc version
 @param params [Array] rpc params
 @param id [Integer] jsonrpc id

 @return [String] json string


def conn
      Faraday.new(url: url) do |faraday|
        faraday.headers["Content-Type"] = "application/json"
        faraday.request  :url_encoded # form-encode POST params
        faraday.adapter  Faraday.default_adapter # make requests with Net::HTTP
      end
    end

def conn Faraday . new ( url : url ) do | faraday | faraday . headers [ "Content-Type" ] = "application/json" faraday . request :url_encoded faraday . adapter Faraday . default_adapter end end

wrapper faraday object with CITA URL and Content-Type

 @return [Faraday]

wrapper faraday object with CITA URL and Content - Type


def transfer(to:, private_key:, value:, quota: 30_000)
      valid_until_block = block_number["result"].hex + 88
      meta_data = get_meta_data("latest")["result"]
      version = meta_data["version"]
      chain_id = if version.zero?
                   meta_data["chainId"]
                 elsif version == 1
                   meta_data["chainIdV1"]
                 end
      transaction = Transaction.new(nonce: Utils.nonce, valid_until_block: valid_until_block, chain_id: chain_id, to: to, value: value, quota: quota, version: version)
      send_transaction(transaction, private_key)
    end

def transfer ( to : , private_key : , value : , quota : 30_000 ) valid_until_block = block_number [ "result" ] . hex + 88 meta_data = get_meta_data ( "latest" ) [ "result" ] version = meta_data [ "version" ] chain_id = if version . zero? meta_data [ "chainId" ] elsif version == 1 meta_data [ "chainIdV1" ] end transaction = Transaction . new ( nonce : Utils . nonce , valid_until_block : valid_until_block , chain_id : chain_id , to : to , value : value , quota : quota , version : version ) send_transaction ( transaction , private_key ) end

easy to transfer tokens

 @param to [String] to address
 @param private_key [String]
 @param value [String | Integer] hex string or decimal integer
 @param quota [Integer] default to 30_000

 @return [Hash]


def replace(new)
    if String === new
      @data.replace(JSON.parse(new))
    else
      @data.replace(new)
    end
  end

def replace ( new ) if String === new @data . replace ( JSON . parse ( new ) ) else @data . replace ( new ) end end

Replace the current storage with the given one.

 @param new [Hash, String] if new is a {String} it will be parsed as JSON

Replace the current storage with the given one .


def to_json
    io = StringIO.new("{")

    io << JSON.create_id.to_json << ":" << self.class.name.to_json << ","

    @data.each {|key, value|
      io << key.to_json.to_s << ":" << value.to_json << ","
    }

    io.seek(-1, IO::SEEK_CUR)
    io << "}"

    io.string
  end

def to_json io = StringIO . new ( "{" ) io << JSON . create_id . to_json << ":" << self . class . name . to_json << "," @data . each { | key , value | io << key . to_json . to_s << ":" << value . to_json << "," } io . seek ( - 1 , IO :: SEEK_CUR ) io << "}" io . string end

Convert the storage to JSON.

 @return [String] the JSON representation


def time(label, &block)
    raise ArgumentError, "no block given" unless block

    `#@native.time(label)`

    begin
      if block.arity == 0
        instance_exec(&block)
      else
        block.call(self)
      end
    ensure
      `#@native.timeEnd()`
    end
  end

def
time
(
label
,
&
block
)
raise
ArgumentError
,
"no block given"
unless
block
`
`
begin
if
block
.
arity
==
0
instance_exec
(
&
block
)
else
block
.
call
(
self
)
end
ensure
`
`
end
end

Time the given block with the given label.

Time the given block with the given label .


def group(*args, &block)
    raise ArgumentError, "no block given" unless block

    `#@native.group.apply(#@native, args)`

    begin
      if block.arity == 0
        instance_exec(&block)
      else
        block.call(self)
      end
    ensure
      `#@native.groupEnd()`
    end
  end

def
group
(
*
args
,
&
block
)
raise
ArgumentError
,
"no block given"
unless
block
`
`
begin
if
block
.
arity
==
0
instance_exec
(
&
block
)
else
block
.
call
(
self
)
end
ensure
`
`
end
end


def group!(*args, &block)
    return unless block_given?

    `#@native.groupCollapsed.apply(#@native, args)`

    begin
      if block.arity == 0
        instance_exec(&block)
      else
        block.call(self)
      end
    ensure
      `#@native.groupEnd()`
    end
  end

def group! ( * args , & block ) return unless block_given? ` ` begin if block . arity == 0 instance_exec ( & block ) else block . call ( self ) end ensure ` ` end end


def authenticate!
      options = authentication_handler.call(self, @options)
      @options.merge!(options)
      client.config.soap_header = soap_headers
    end

def authenticate! options = authentication_handler . call ( self , @options ) @options . merge! ( options ) client . config . soap_header = soap_headers end

Internal Calls the authentication handler, which should set @options to a new
 hash.

Internal Calls the authentication handler which should set


def new_with_uuid(klass, uuid)
      if klass.is_a?(String)
        klass = Object.const_get(klass)
      end
      object = klass.new(self, uuid)
      object.initialize_defaults
      object
    end

def new_with_uuid ( klass , uuid ) if klass . is_a? ( String ) klass = Object . const_get ( klass ) end object = klass . new ( self , uuid ) object . initialize_defaults object end

Creates a new object with given UUID.

 @param [String] uuid UUID of the object.


def new_reference_with_uuid(path, uuid, source_tree = :group)
      # customize `FileReferencesFactory.new_file_reference`
      path = Pathname.new(path)
      ref = self.project.new_with_uuid(PBXFileReference, uuid)
      self.children << ref
      GroupableHelper.set_path_with_source_tree(ref, path, source_tree)
      ref.set_last_known_file_type

      # customize `FileReferencesFactory.configure_defaults_for_file_reference`
      if ref.path.include?('/')
        ref.name = ref.path.split('/').last
      end
      if File.extname(ref.path).downcase == '.framework'
        ref.include_in_index = nil
      end

      ref
    end

def new_reference_with_uuid ( path , uuid , source_tree = :group ) path = Pathname . new ( path ) ref = self . project . new_with_uuid ( PBXFileReference , uuid ) self . children << ref GroupableHelper . set_path_with_source_tree ( ref , path , source_tree ) ref . set_last_known_file_type if ref . path . include? ( '/' ) ref . name = ref . path . split ( '/' ) . last end if File . extname ( ref . path ) . downcase == '.framework' ref . include_in_index = nil end ref end

Creates a file reference with given UUID.

 @param [String] uuid UUID of the object.

Creates a file reference with given UUID .


def add_file_reference_with_uuid(file_ref, uuid, avoid_duplicates = false)
      if avoid_duplicates && existing = build_file(file_ref)
        existing
      else
        build_file = project.new_with_uuid(PBXBuildFile, uuid)
        build_file.file_ref = file_ref
        files.insert(0, build_file)
        build_file
      end
    end

def add_file_reference_with_uuid ( file_ref , uuid , avoid_duplicates = false ) if avoid_duplicates && existing = build_file ( file_ref ) existing else build_file = project . new_with_uuid ( PBXBuildFile , uuid ) build_file . file_ref = file_ref files . insert ( 0 , build_file ) build_file end end

Adds the file reference with given UUID.

 @param [String] uuid UUID of the object.

Adds the file reference with given UUID .


def remove_seeds
      removings = self.locks.keys - self.seeds.keys
      removings.each do |name|
        say "Removing #{name} (#{self.locks[name].version})".red
        dirname = File.join(self.root_path, "Seeds", name)
        FileUtils.rm_rf(dirname)
      end
    end

Removes disused seeds.

 @!visibility private


def configure_phase
      self.project.targets.each do |target|
        begin
          phase = target.sources_build_phase
          # support resources phase
          resource_phase = target.resources_build_phase
          next unless phase
        rescue NoMethodError
          next
        end

        # remove zombie build files
        phase.files_references.each do |file|
          begin
            file.real_path
          rescue
            phase.files.each do |build_file|
              phase.files.delete(build_file) if build_file.file_ref == file
            end
          end
        end

        resource_phase.files_references.each do |file|
          begin
            file.real_path
          rescue
            resource_phase.files.each do |build_file|
              resource_phase.files.delete(build_file) if build_file.file_ref == file
            end
          end
        end

        removings = [] # name of seeds going to be removed from the target
        addings = [] # name of seeds going to be added to the target

        self.targets.keys.sort.each do |seed_name|
          target_names = self.targets[seed_name]
          if not target_names.include?(target.name)
            removings << seed_name if not removings.include?(seed_name)
          else
            addings << seed_name if not addings.include?(seed_name)
          end
        end

        self.file_references.each do |file|
          removings.each do |seed_names|
            next if not seed_names.include?(file.parent.name)
            phase.files.each do |build_file|
              phase.files.delete(build_file) if build_file.file_ref == file
            end
            resource_phase.files.each do |build_file|
              resource_phase.files.delete(build_file) if build_file.file_ref == file
            end
          end

          addings.each do |seed_names|
            next if file.name.end_with? ".h"
            next if not seed_names.include?(file.parent.name)
            uuid = Xcodeproj::uuid_with_name "#{target.name}:#{file.name}"
            # Treat a file as resource file unless confirm it can be compiled.
            if self.valid_source_file?(file)
              phase.add_file_reference_with_uuid(file, uuid, true)
            else
              resource_phase.add_file_reference_with_uuid(file, uuid, true)
            end

          end
        end
      end
    end

def configure_phase self . project . targets . each do | target | begin phase = target . sources_build_phase resource_phase = target . resources_build_phase next unless phase rescue NoMethodError next end phase . files_references . each do | file | begin file . real_path rescue phase . files . each do | build_file | phase . files . delete ( build_file ) if build_file . file_ref == file end end end resource_phase . files_references . each do | file | begin file . real_path rescue resource_phase . files . each do | build_file | resource_phase . files . delete ( build_file ) if build_file . file_ref == file end end end removings = [ ] addings = [ ] self . targets . keys . sort . each do | seed_name | target_names = self . targets [ seed_name ] if not target_names . include? ( target . name ) removings << seed_name if not removings . include? ( seed_name ) else addings << seed_name if not addings . include? ( seed_name ) end end self . file_references . each do | file | removings . each do | seed_names | next if not seed_names . include? ( file . parent . name ) phase . files . each do | build_file | phase . files . delete ( build_file ) if build_file . file_ref == file end resource_phase . files . each do | build_file | resource_phase . files . delete ( build_file ) if build_file . file_ref == file end end addings . each do | seed_names | next if file . name . end_with? ".h" next if not seed_names . include? ( file . parent . name ) uuid = Xcodeproj :: uuid_with_name "#{target.name}:#{file.name}" if self . valid_source_file? ( file ) phase . add_file_reference_with_uuid ( file , uuid , true ) else resource_phase . add_file_reference_with_uuid ( file , uuid , true ) end end end end end

Adds file references to the 'Sources Build Phase'.

 @!visibility private

Adds file references to the Sources Build Phase .


def valid_source_file? filename
      suffixs = [".h", ".c", ".m", ".mm", ".swift", ".cpp"]
      suffixs.each do |suffix|
        return true if filename.name.end_with? suffix
      end
      return false
    end

def valid_source_file? filename suffixs = [ ".h" , ".c" , ".m" , ".mm" , ".swift" , ".cpp" ] suffixs . each do | suffix | return true if filename . name . end_with? suffix end return false end

Determines whether there's a source file.

 @!visibility private

Determines whether there s a source file .


def speller
      return @speller if @speller
      # raspell is an optional dependency, handle the missing case nicely
      begin
        require "raspell"
      rescue LoadError
        $stderr.puts "ERROR: Ruby gem \"raspell\" is not installed."
        exit 1
      end

      # initialize aspell
      @speller = Aspell.new("en_US")
      @speller.suggestion_mode = Aspell::NORMAL
      # ignore the HTML tags in the text
      @speller.set_option("mode", "html")

      @speller
    end

create an Aspell speller object
 @return [Aspell] the speller object


def files_to_check
      files = config["check"].reduce([]) { |a, e| a + Dir[e] }
      config["ignore"].reduce(files) { |a, e| a - Dir[e] }
    end

def files_to_check files = config [ "check" ] . reduce ( [ ] ) { | a , e | a + Dir [ e ] } config [ "ignore" ] . reduce ( files ) { | a , e | a - Dir [ e ] } end

evaluate the files to check
 @return [Array<String>] list of files


def read_spell_config(file)
      return {} unless File.exist?(file)

      puts "Loading config file (#{file})..." if verbose == true
      require "yaml"
      YAML.load_file(file)
    end

def
read_spell_config
(
file
)
return
{
}
unless
File
.
exist?
(
file
)
puts
"Loading config file (#{file})..."
if
verbose
==
true
require
"yaml"
YAML
.
load_file
(
file
)
end


def report_duplicates(dict1, dict2)
      duplicates = dict1 & dict2
      return if duplicates.empty?

      $stderr.puts "Warning: Found dictionary duplicates in the local dictionary " \
        "(#{CUSTOM_SPELL_CONFIG_FILE}):\n"
      duplicates.each { |duplicate| $stderr.puts "  #{duplicate}" }
      $stderr.puts
    end

print the duplicate dictionary entries
 @param dict1 [Array<String>] the first dictionary
 @param dict2 [Array<String>] the second dictionary


def config
      return @config if @config

      @config = read_spell_config(GLOBAL_SPELL_CONFIG_FILE)
      custom_config = read_spell_config(CUSTOM_SPELL_CONFIG_FILE)

      report_duplicates(config["dictionary"], custom_config["dictionary"].to_a)

      custom_config["dictionary"] = @config["dictionary"] + custom_config["dictionary"].to_a
      custom_config["dictionary"].uniq!

      # override the global values by the local if present
      @config.merge!(custom_config)

      @config
    end

def config return @config if @config @config = read_spell_config ( GLOBAL_SPELL_CONFIG_FILE ) custom_config = read_spell_config ( CUSTOM_SPELL_CONFIG_FILE ) report_duplicates ( config [ "dictionary" ] , custom_config [ "dictionary" ] . to_a ) custom_config [ "dictionary" ] = @config [ "dictionary" ] + custom_config [ "dictionary" ] . to_a custom_config [ "dictionary" ] . uniq! @config . merge! ( custom_config ) @config end

return the merged global and the custom spell configs
 @return [Hash] the merged configuration to use


def check_file(file)
      puts "Checking #{file}..." if verbose == true
      # spell check each line separately so we can report error locations properly
      lines = File.read(file).split("\n")

      success = true
      lines.each_with_index do |text, index|
        misspelled = misspelled_on_line(text)
        next if misspelled.empty?

        success = false
        print_misspelled(misspelled, index, text)
      end

      success
    end

def
check_file
(
file
)
puts
"Checking #{file}..."
if
verbose
==
true
lines
=
File
.
read
(
file
)
.
split
(
"\n"
)
success
=
true
lines
.
each_with_index
do
|
text
,
index
|
misspelled
=
misspelled_on_line
(
text
)
next
if
misspelled
.
empty?
success
=
false
print_misspelled
(
misspelled
,
index
,
text
)
end
success
end

check the file using the spellchecker
 @param file [String] file name
 @return [Boolean] true on success (no spelling error found)


def check_writable(path)
      raise Error, "'#{path}' is not writable" if path.exist? && !path.writable? || !path.parent.writable?
    end

def
check_writable
(
path
)
raise
Error
,
"'#{path}' is not writable"
if
path
.
exist?
&&
!
path
.
writable?
||
!
path
.
parent
.
writable?
end

If the path does not exist, it will check for the parent
 directory write permission

 @param [ Pathname ] path

If the path does not exist it will check for the parent directory write permission


def check_option(opt)
      raise Error, "The option is not an OptBase, #{opt.class} supplied" unless opt.is_a?(OptBase)
      raise Error, "The option #{opt.to_sym} is already used !" if @symbols_used.include?(opt.to_sym)
    end

Ensures the opt given is valid

 @param [ OptBase ] opt

 @return [ void ]


def post_processing
      @opts.each do |opt|
        raise NoRequiredOption, "The option #{opt} is required" if opt.required? && !@results.key?(opt.to_sym)

        next if opt.required_unless.empty? || @results.key?(opt.to_sym)

        fail_msg = "One of the following options is required: #{opt}, #{opt.required_unless.join(', ')}"

        raise NoRequiredOption, fail_msg unless opt.required_unless.any? do |sym|
          @results.key?(sym)
        end
      end
    end

Ensure that all required options are supplied
 Should be overriden to modify the behavior

 @return [ Void ]


def subdir_entities(dir = @current_dir)
      Dir.glob(dir[:path].gsub(/[*?\\\[\]{}]/, '\\\\\0') + '/*').map!{|path| {path: path, time: File.mtime(path), name: File.basename(path)}}
    end

def subdir_entities ( dir = @current_dir ) Dir . glob ( dir [ :path ] . gsub ( / \\ \[ \] / , '\\\\\0' ) + '/*' ) . map! { | path | { path : path , time : File . mtime ( path ) , name : File . basename ( path ) } } end

Conversions
 Get entities of files in dir


def string_to_bytes(str)
      unless @e.nil? || @e == :utf8
        if @e == :shift_jis
          begin
            str = str.gsub /[\\:*?"<>|\uff5e]/, '？'
            str.encode! 'Shift_JIS', :invalid => :replace, :undef => :replace, :replace => '？'
          rescue => e
          end
        end
      end
      [str].pack('a*')
    end

def string_to_bytes ( str ) unless @e . nil? || @e == :utf8 if @e == :shift_jis begin str = str . gsub / \\ \uff5e / , '？' str . encode! 'Shift_JIS' , :invalid => :replace , :undef => :replace , :replace => '？' rescue => e end end end [ str ] . pack ( 'a*' ) end

Create ASCII-8bits string. Also convert encoding if needed.

Create ASCII - 8bits string . Also convert encoding if needed .


def pack(files)
      entities = Entity.entities_from files
      return if entities.empty?

      reset_state
      pack_entities entities
      while has_dir?
        cd next_dir
        pack_current_dir
      end
    end

def pack ( files ) entities = Entity . entities_from files return if entities . empty? reset_state pack_entities entities while has_dir? cd next_dir pack_current_dir end end

Compression operations
 Pack file and directory entities and output to stream.

Compression operations Pack file and directory entities and output to stream .


def pack_symlinks
      reset_state
      @l.each do |link|
        if @w.path_exists? Entity.linked_path(link[:abs_path], File.readlink(link[:path]))
          link[:name] = link[:abs_path]
          pack_symbolic_link_entity link
        end
      end
    end

def pack_symlinks reset_state @l . each do | link | if @w . path_exists? Entity . linked_path ( link [ :abs_path ] , File . readlink ( link [ :path ] ) ) link [ :name ] = link [ :abs_path ] pack_symbolic_link_entity link end end end

Pack symlinks if its link path exists in zip


def pack_entities(entities)
      entities.each do |entity|
        # ignore bad entities
        next unless entity.is_a?(Hash) && entity[:path]

        path = entity[:path]
        if File.symlink? path
          postpone_symlink entity
        elsif File.directory? path
          postpone_dir entity
        elsif File.file? path
          pack_file_entity entity
        end
      end
    end

def pack_entities ( entities ) entities . each do | entity | next unless entity . is_a? ( Hash ) && entity [ :path ] path = entity [ :path ] if File . symlink? path postpone_symlink entity elsif File . directory? path postpone_dir entity elsif File . file? path pack_file_entity entity end end end

Pack file entities. Directory entities are queued, not packed in this method.

Pack file entities . Directory entities are queued not packed in this method .


def header content = nil, options = nil, html_options = nil, &block
      @header = UiBibz::Ui::Core::Lists::Components::ListHeader.new content, options, html_options, &block
    end

def header content = nil , options = nil , html_options = nil , & block @header = UiBibz :: Ui :: Core :: Lists :: Components :: ListHeader . new content , options , html_options , & block end


def body content = nil, options = nil, html_options = nil, &block
      @body = UiBibz::Ui::Core::Lists::Components::ListBody.new content, options, html_options, &block
    end

def body content = nil , options = nil , html_options = nil , & block @body = UiBibz :: Ui :: Core :: Lists :: Components :: ListBody . new content , options , html_options , & block end


def td_content record, col
      content = col.count ? record.send(col.data_index).count : record.send(col.data_index)
      unless content.nil?
        content = content.strftime(col.date_format)                    unless col.date_format.nil?
        content = link_to content, action.inject_url(col.link, record) unless col.link.nil?
        content = col.format.call(@store.records, record)              unless col.format.nil?
      end
      content = As.new(col, record, content, @options).render unless col.as.nil?
      content
    end

def td_content record , col content = col . count ? record . send ( col . data_index ) . count : record . send ( col . data_index ) unless content . nil? content = content . strftime ( col . date_format ) unless col . date_format . nil? content = link_to content , action . inject_url ( col . link , record ) unless col . link . nil? content = col . format . call ( @store . records , record ) unless col . format . nil? end content = As . new ( col , record , content , @options ) . render unless col . as . nil? content end


def body content = nil, options = nil, html_options = nil, &block
      options, content = inherit_options(content, options, block)
      if is_tap(content, options)
        content = (content || {}).merge(collapse: options.try(:[], :collapse), parent_collapse: @options[:parent_collapse] )
        @items << UiBibz::Ui::Core::Boxes::Components::CardBody.new(content, options, html_options).tap(&block).render
      else
        options = (options || {}).merge(collapse: options.try(:[], :collapse), parent_collapse: @options[:parent_collapse] )
        @items << UiBibz::Ui::Core::Boxes::Components::CardBody.new(content, options, html_options, &block).render
      end
    end

def body content = nil , options = nil , html_options = nil , & block options , content = inherit_options ( content , options , block ) if is_tap ( content , options ) content = ( content || { } ) . merge ( collapse : options . try ( :[] , :collapse ) , parent_collapse : @options [ :parent_collapse ] ) @items << UiBibz :: Ui :: Core :: Boxes :: Components :: CardBody . new ( content , options , html_options ) . tap ( & block ) . render else options = ( options || { } ) . merge ( collapse : options . try ( :[] , :collapse ) , parent_collapse : @options [ :parent_collapse ] ) @items << UiBibz :: Ui :: Core :: Boxes :: Components :: CardBody . new ( content , options , html_options , & block ) . render end end


def footer content = nil, options = nil, html_options = nil, &block
      options, content = inherit_options(content, options, block)
      @footer = UiBibz::Ui::Core::Boxes::Components::CardFooter.new(content, options, html_options, &block).render
    end

def footer content = nil , options = nil , html_options = nil , & block options , content = inherit_options ( content , options , block ) @footer = UiBibz :: Ui :: Core :: Boxes :: Components :: CardFooter . new ( content , options , html_options , & block ) . render end


def list_group content = nil, options = nil, html_options = nil, &block
      @items << UiBibz::Ui::Core::Boxes::Components::CardListGroup.new(content, options, html_options).tap(&block).render
    end

def list_group content = nil , options = nil , html_options = nil , & block @items << UiBibz :: Ui :: Core :: Boxes :: Components :: CardListGroup . new ( content , options , html_options ) . tap ( & block ) . render end


def image content = nil, options = nil, html_options = nil, &block
      @items << UiBibz::Ui::Core::Boxes::Components::CardImage.new(content, options, html_options, &block).render
    end

def image content = nil , options = nil , html_options = nil , & block @items << UiBibz :: Ui :: Core :: Boxes :: Components :: CardImage . new ( content , options , html_options , & block ) . render end


def html content = nil, &block
      if !block.nil?
        context  = eval("self", block.binding)
        @items << context.capture(&block)
      else
        @items << content
      end
    end

def html content = nil , & block if ! block . nil? context = eval ( "self" , block . binding ) @items << context . capture ( & block ) else @items << content end end


def component_html_options
      super.merge({
        multiple:      options[:multiple],
        disabled:      options[:state] == :disabled,
        include_blank: options[:include_blank],
        prompt:        options[:prompt]
      })
    end

def component_html_options super . merge ( { multiple : options [ :multiple ] , disabled : options [ :state ] == :disabled , include_blank : options [ :include_blank ] , prompt : options [ :prompt ] } ) end


def nav content = nil, options = {}, html_options = nil, &block
      @items << UiBibz::Ui::Core::Component.new(Nav.new(content, options).tap(&block).render, {}, html_options)
    end

def nav content = nil , options = { } , html_options = nil , & block @items << UiBibz :: Ui :: Core :: Component . new ( Nav . new ( content , options ) . tap ( & block ) . render , { } , html_options ) end


def body content = nil, options = nil, html_options = nil, &block
      @body = UiBibz::Ui::Core::Notifications::Components::AlertBody.new(content, options, html_options, &block).render
    end

def body content = nil , options = nil , html_options = nil , & block @body = UiBibz :: Ui :: Core :: Notifications :: Components :: AlertBody . new ( content , options , html_options , & block ) . render end


def is_tap content, options
      (content[:tap] if content.kind_of?(Hash)) || (options[:tap] unless options.nil?)
    end

def is_tap content , options ( content [ :tap ] if content . kind_of? ( Hash ) ) || ( options [ :tap ] unless options . nil? ) end


def component_html_data
      # To stimulusjs
      data_target = html_options.try(:[], :data).try(:[], :target) || options.try(:delete, :target)
      add_html_data(:target, data_target) unless data_target.nil?

      data_controller = html_options.try(:[], :data).try(:[], :controller) || options.try(:delete, :controller)
      add_html_data(:controller, data_controller) unless data_controller.nil?

      data_action = html_options.try(:[], :data).try(:[], :action) || options.try(:delete, :action)
      add_html_data(:action, data_action) unless data_action.nil?

      # To turbolinks
      data_turbolinks = html_options.try(:[], :data).try(:[], :turbolinks) || options.try(:delete, :turbolinks)
      add_html_data(:turbolinks, data_turbolinks) unless data_turbolinks.nil?
    end

def component_html_data data_target = html_options . try ( :[] , :data ) . try ( :[] , :target ) || options . try ( :delete , :target ) add_html_data ( :target , data_target ) unless data_target . nil? data_controller = html_options . try ( :[] , :data ) . try ( :[] , :controller ) || options . try ( :delete , :controller ) add_html_data ( :controller , data_controller ) unless data_controller . nil? data_action = html_options . try ( :[] , :data ) . try ( :[] , :action ) || options . try ( :delete , :action ) add_html_data ( :action , data_action ) unless data_action . nil? data_turbolinks = html_options . try ( :[] , :data ) . try ( :[] , :turbolinks ) || options . try ( :delete , :turbolinks ) add_html_data ( :turbolinks , data_turbolinks ) unless data_turbolinks . nil? end


def add_html_data name, value = true
      html_options[:data] = {} if html_options[:data].nil?
      value = value.kind_of?(String) ? value.strip : value
      html_options[:data].update(Hash[name, value])
    end

def add_html_data name , value = true html_options [ :data ] = { } if html_options [ :data ] . nil? value = value . kind_of? ( String ) ? value . strip : value html_options [ :data ] . update ( Hash [ name , value ] ) end


def header column, name = nil
      @column  = column
      defaults = [translate_headers_by_defaults, translate_headers_by_defaults_active_record, translate_headers_by_active_record, header_name(name)]
      @name    = UiBibz::Utils::Internationalization.new(translate_headers_by_model, default: defaults).translate
      sortable? ? sortable_link : title
    end


def column data_index = nil, options = nil, html_options = nil, &block
      @columns << Column.new(data_index, options, html_options, &block)
    end

def column data_index = nil , options = nil , html_options = nil , & block @columns << Column . new ( data_index , options , html_options , & block ) end


def link content = nil, options = nil, html_options = nil, &block
      @actions << UiBibz::Ui::Core::Forms::Dropdowns::Components::DropdownLink.new(content, options, html_options, &block).render
    end

def link content = nil , options = nil , html_options = nil , & block @actions << UiBibz :: Ui :: Core :: Forms :: Dropdowns :: Components :: DropdownLink . new ( content , options , html_options , & block ) . render end


def engine_scaffold
      FileUtils.mkdir_p(@gem_temp)
      Dir.chdir(@gem_temp) do
        response = Open3.capture3("rails plugin new #{gem} --mountable --dummy-path=site --skip-test-unit")
        if !response[1].empty?
          puts response[1]
          abort "FAILED: Please be sure you have the rails gem installed with `gem install rails`"
        end

        # Remove files and directories that are unnecessary for the
        # light-weight Rails documentation site
        remove = %w(mailers models assets channels jobs views).map{ |f| File.join('app', f) }
        remove.concat %w(cable.yml storage.yml database.yml).map{ |f| File.join('config', f) }

        remove.each { |f| FileUtils.rm_rf File.join(@gem, 'site', f), secure: true }
      end

      engine_copy
    end

Create an Rails plugin engine for documentation site


def engine_copy
      site_path = File.join path, 'site'
      FileUtils.mkdir_p site_path

      ## Copy Rails plugin files
      Dir.chdir "#{@gem_temp}/#{gem}/site" do
        %w(app config bin config.ru Rakefile public log).each do |item|
          target = File.join site_path, item

          FileUtils.cp_r item, target

          action_log "create", target.sub(@cwd+'/','')
        end

      end

      # Remove temp dir
      FileUtils.rm_rf @gem_temp
    end

def engine_copy site_path = File . join path , 'site' FileUtils . mkdir_p site_path Dir . chdir "#{@gem_temp}/#{gem}/site" do %w( app config bin config.ru Rakefile public log ) . each do | item | target = File . join site_path , item FileUtils . cp_r item , target action_log "create" , target . sub ( @cwd + '/' , '' ) end end FileUtils . rm_rf @gem_temp end

Copy parts of the engine scaffold into site directory


def make_map(item)
      '(' + item.map {|key, value| key.to_s + ':' + convert_to_sass_value(value) }.join(',') + ')'
    end

def make_map ( item ) '(' + item . map { | key , value | key . to_s + ':' + convert_to_sass_value ( value ) } . join ( ',' ) + ')' end


def add_files(klass)
      ext = asset_ext klass
      find_files(ext).map do |path|
        klass.new(self, path)
      end
    end

def add_files ( klass ) ext = asset_ext klass find_files ( ext ) . map do | path | klass . new ( self , path ) end end

Find files based on class type and
 return an array of Classes for each file


def find_files(ext)
      files = Dir[File.join(paths[ext.to_sym], asset_glob(ext))]

      # Filter out partials
      files.reject { |f| File.basename(f).start_with?('_') }
    end

def find_files ( ext ) files = Dir [ File . join ( paths [ ext . to_sym ] , asset_glob ( ext ) ) ] files . reject { | f | File . basename ( f ) . start_with? ( '_' ) } end


def dispatch(command, *args)
      @threads = []
      send command, *args
      @threads.each { |thr| thr.join }
    end

def dispatch ( command , * args ) @threads = [ ] send command , * args @threads . each { | thr | thr . join } end


def watch(options={})
      build(options)
      require 'listen'

      trap("SIGINT") {
        puts "\nspark_engine watcher stopped. Have a nice day!"
        exit!
      }

      @threads.concat SparkEngine.load_plugin.watch(options)
    end


def load_setup( name )
    reader = create_fixture_reader( name )

    reader.each do |fixture_name|
      load( fixture_name )
    end
  end

def load_setup ( name ) reader = create_fixture_reader ( name ) reader . each do | fixture_name | load ( fixture_name ) end end

lets us use match_teams_for_country etc.

lets us use match_teams_for_country etc .


def avoid_duplicate_image_names(content)

      nodes = content.xpath("//draw:frame[@draw:name]")

      nodes.each_with_index do |node, i|
        node.attribute('name').value = "pic_#{i}"
      end

    end

def avoid_duplicate_image_names ( content ) nodes = content . xpath ( "//draw:frame[@draw:name]" ) nodes . each_with_index do | node , i | node . attribute ( 'name' ) . value = "pic_#{i}" end end

replace_images
 newer versions of LibreOffice can't open files with duplicates image names

replace_images newer versions of LibreOffice can t open files with duplicates image names


def scope_params
        return {} if dynamic_scaffold.scope.nil?

        case dynamic_scaffold.scope
        when Array then
          dynamic_scaffold.scope.each_with_object({}) do |val, res|
            if val.is_a? Hash
              val.each {|k, v| res[k] = v }
            else
              res[val] = params[val]
            end
          end
        when Hash then
          dynamic_scaffold.scope
        end
      end

def scope_params return { } if dynamic_scaffold . scope . nil? case dynamic_scaffold . scope when Array then dynamic_scaffold . scope . each_with_object ( { } ) do | val , res | if val . is_a? Hash val . each { | k , v | res [ k ] = v } else res [ val ] = params [ val ] end end when Hash then dynamic_scaffold . scope end end

Get the hash of the key and value specified for the scope.

Get the hash of the key and value specified for the scope .


def pkey_string_to_hash(pkey)
        # https://github.com/gomo/dynamic_scaffold/pull/9/commits/ff5de0e38b3544347e82539c45ffd2efaf3410da
        # Stop support multiple pkey, on this commit.
        # Convert "key:1,code:foo" to {key: "1", code: "foo"}
        pkey.split(',').map {|v| v.split(':') }.each_with_object({}) {|v, res| res[v.first] = v.last }
      end

def pkey_string_to_hash ( pkey ) pkey . split ( ',' ) . map { | v | v . split ( ':' ) } . each_with_object ( { } ) { | v , res | res [ v . first ] = v . last } end


def update_values # rubocop:disable Metrics/AbcSize
        # set the parameters of carrierwave_image at the end for validates.
        permitting = []
        dynamic_scaffold.form.items.reject {|i| i.type?(:carrierwave_image) }.each do |item|
          item.extract_parameters(permitting)
        end
        permitting.concat(dynamic_scaffold.form.permit_params)
        dynamic_scaffold.form.items.select {|i| i.type?(:carrierwave_image) }.each do |item|
          item.extract_parameters(permitting)
        end

        values = params
                   .require(dynamic_scaffold.model.name.underscore)
                   .permit(*permitting)

        if dynamic_scaffold.scope && !valid_for_scope?(values)
          raise DynamicScaffold::Error::InvalidOperation, "You can update only to #{scope_params} on this scope"
        end

        values
      end


def valid_for_scope?(update_params)
        return true if dynamic_scaffold.scope_options[:changeable]

        result = true
        scope_params.each do |key, value|
          if update_params.key?(key) && update_params[key] != value
            result = false
            break
          end
        end
        result
      end

def valid_for_scope? ( update_params ) return true if dynamic_scaffold . scope_options [ :changeable ] result = true scope_params . each do | key , value | if update_params . key? ( key ) && update_params [ key ] != value result = false break end end result end

Check if there are inconsistent scopes in update parameters


def lock(timeout: nil, &block)
      ensure_exists_and_release_stale_locks!

      success = @redis.with do |conn|
        if timeout
          !conn.blpop(available_key, timeout.to_i).nil?
        else
          !conn.lpop(available_key).nil?
        end
      end

      return false unless success

      token = SecureRandom.hex(16)
      @tokens.push(token)
      @redis.with do |conn|
        conn.zadd(grabbed_key, epoch_f(conn), token)
      end

      return_or_yield(token, &block)
    end

def lock ( timeout : nil , & block ) ensure_exists_and_release_stale_locks! success = @redis . with do | conn | if timeout ! conn . blpop ( available_key , timeout . to_i ) . nil? else ! conn . lpop ( available_key ) . nil? end end return false unless success token = SecureRandom . hex ( 16 ) @tokens . push ( token ) @redis . with do | conn | conn . zadd ( grabbed_key , epoch_f ( conn ) , token ) end return_or_yield ( token , & block ) end

Acquire a resource from the semaphore, if available. Returns false if no
 resources are available.

 `timeout` is how long to wait, blocking, until a resource is available.
 The default is nil, meaning don't block. A timeout of zero means block forever.
 (This is a bit weird, but corresponds to how blpop uses timeout values.)

 If passed a block, if a resource is available, runs the block and then
 unlocks.

 If called without a block, if a resource is available, returns a token.
 Caller is then responsible for unlocking the token.

 This isn't atomic--if the process dies, we could remove something from the
 available queue without adding it to the grabbed set--but that's ok, the
 semaphore will recover just as if this was a stale client that left its
 token in the grabbed set forever.

Acquire a resource from the semaphore if available . Returns false if no resources are available .


def unlock(token = @tokens.pop)
      return unless token

      removed = false

      @redis.with do |conn|
        removed = conn.zrem grabbed_key, token
        if removed
          conn.lpush available_key, 1
        end
      end

      removed
    end

def unlock ( token = @tokens . pop ) return unless token removed = false @redis . with do | conn | removed = conn . zrem grabbed_key , token if removed conn . lpush available_key , 1 end end removed end

Release a resource back to the semaphore. Should normally be called with an
 explicit token.

 This isn't atomic--if the process dies, we could remove something from the
 blocked set without adding it to the available queue--but that's ok, the
 semaphore will recover just as if this was a stale client that left its
 token in the grabbed set forever.

Release a resource back to the semaphore . Should normally be called with an explicit token .


def apply_options(options={})
      options.each { |key, value| send("#{key}=", value) if respond_to?(key) }
      yield(self) if block_given?
    end

def apply_options ( options = { } ) options . each { | key , value | send ( "#{key}=" , value ) if respond_to? ( key ) } yield ( self ) if block_given? end

Creates a notification object.

 @see Libnotify.new


def show!
      notify_init(app_name) or raise "notify_init failed"
      raw_ptr = notify_notification_new(summary, body, icon_path, nil)
      @notification = ::FFI::AutoPointer.new(raw_ptr, method(:g_object_unref))
      show
    end

def
show!
notify_init
(
app_name
)
or
raise
"notify_init failed"
raw_ptr
=
notify_notification_new
(
summary
,
body
,
icon_path
,
)
@notification
=
::
FFI
::
AutoPointer
.
new
(
raw_ptr
,
method
(
:g_object_unref
)
)
show
end

Shows a new notification.

 @see Libnotify.show


def update(options={}, &block)
      apply_options(options, &block)
      if @notification
        notify_notification_update(@notification, summary, body, icon_path, nil)
        show
      else
        show!
      end
    end

def update ( options = { } , & block ) apply_options ( options , & block ) if @notification notify_notification_update ( @notification , summary , body , icon_path , nil ) show else show! end end

Updates a previously shown notification or creates a new one.

Updates a previously shown notification or creates a new one .


def download
      raise ArgumentError.new('url cannot be nil') if @url.nil?
      raise ArgumentError.new('url cannot be empty') if @url.empty?

      set_information_from_json(YoutubeDL::Runner.new(url, runner_options).run)
    end

def
download
raise
ArgumentError
.
new
(
'url cannot be nil'
)
if
@url
.
nil?
raise
ArgumentError
.
new
(
'url cannot be empty'
)
if
@url
.
empty?
set_information_from_json
(
YoutubeDL
::
Runner
.
new
(
url
,
runner_options
)
.
run
)
end

Instantiate new model

 @param url [String] URL to initialize with
 @param options [Hash] Options to populate the everything with
 Download the video.


def method_missing(method, *args, &block)
      value = information[method]

      if value.nil?
        super
      else
        value
      end
    end

def method_missing ( method , * args , & block ) value = information [ method ] if value . nil? super else value end end

Redirect methods for information getting

 @param method [Symbol] method name
 @param args [Array] method arguments
 @param block [Proc] explict block
 @return [Object] The value from @information


def options_to_commands
      commands = []
      @options.sanitize_keys.each_paramized_key do |key, paramized_key|
        if @options[key].to_s == 'true'
          commands.push "--#{paramized_key}"
        elsif @options[key].to_s == 'false'
          commands.push "--no-#{paramized_key}"
        else
          commands.push "--#{paramized_key} :#{key}"
        end
      end
      commands.push quoted(url)
      commands.join(' ')
    end

def
options_to_commands
commands
=
[
]
@options
.
sanitize_keys
.
each_paramized_key
do
|
key
,
paramized_key
|
if
@options
[
key
]
.
to_s
==
'true'
commands
.
push
"--#{paramized_key}"
elsif
@options
[
key
]
.
to_s
==
'false'
commands
.
push
"--no-#{paramized_key}"
else
commands
.
push
"--#{paramized_key} :#{key}"
end
end
commands
.
push
quoted
(
url
)
commands
.
join
(
' '
)
end

Parses options and converts them to Cocaine's syntax

 @return [String] commands ready to do cocaine

Parses options and converts them to Cocaine s syntax


def with(hash)
      merged = Options.new(@store.merge(hash.to_h))
      merged.banned_keys = @banned_keys
      merged.send(:remove_banned)
      merged
    end

def with ( hash ) merged = Options . new ( @store . merge ( hash . to_h ) ) merged . banned_keys = @banned_keys merged . send ( :remove_banned ) merged end

Merge options with given hash, removing banned keys, and returning a
 new instance of Options.

 @param hash [Hash] Hash to merge options with
 @return [YoutubeDL::Options] Merged Options instance

Merge options with given hash removing banned keys and returning a new instance of Options .


def method_missing(method, *args, &_block)
      remove_banned
      if method.to_s.include? '='
        method = method.to_s.tr('=', '').to_sym
        return nil if banned? method
        @store[method] = args.first
      else
        return nil if banned? method
        @store[method]
      end
    end

def method_missing ( method , * args , & _block ) remove_banned if method . to_s . include? '=' method = method . to_s . tr ( '=' , '' ) . to_sym return nil if banned? method @store [ method ] = args . first else return nil if banned? method @store [ method ] end end

Option getting and setting using ghost methods

 @param method [Symbol] method name
 @param args [Array] list of arguments passed
 @param block [Proc] implicit block given
 @return [Object] the value of method in the options store


def manipulate_keys!(&block)
      @store.keys.each do |old_name|
        new_name = block.call(old_name)
        unless new_name == old_name
          @store[new_name] = @store[old_name]
          @store.delete(old_name)
        end
      end
    end

def manipulate_keys! ( & block ) @store . keys . each do | old_name | new_name = block . call ( old_name ) unless new_name == old_name @store [ new_name ] = @store [ old_name ] @store . delete ( old_name ) end end end

Calls a block to do operations on keys
 See sanitize_keys! for examples

 @param block [Proc] Block with operations on keys
 @yieldparam key [Object] Original key
 @yieldreturn [Object] Manipulated key


def sanitize_keys!
      # Symbolize
      manipulate_keys! { |key_name| key_name.is_a?(Symbol) ? key_name : key_name.to_sym }

      # Underscoreize (because Cocaine doesn't like hyphens)
      manipulate_keys! { |key_name| key_name.to_s.tr('-', '_').to_sym }
    end

Symbolizes and sanitizes keys in the option store

 @return [Object] @store


def representer_for(format, model, options={})
      options.delete(:represent_with) || self.class.represents_options.for(format, model, controller_path)
    end

def representer_for ( format , model , options = { } ) options . delete ( :represent_with ) || self . class . represents_options . for ( format , model , controller_path ) end

Central entry-point for finding the appropriate representer.

Central entry - point for finding the appropriate representer .


def variable_text_field(x, y, params = {})
      x = 0 unless numeric?(x)
      y = 0 unless numeric?(y)
      options = { height: 0.1, width: 0.1 }.merge!(params)

      # update the variable field count
      self.variable_fields_count += 1

      label_data.push('^FO' + Integer(x * printer_dpi).to_s + ',' +
                      Integer(y * printer_dpi).to_s)

      if params[:orientation] == :landscape
        label_data.push('^A0N,')
      else
        label_data.push('^A0B,')
      end

      label_data.push(Integer(options[:height] * printer_dpi).to_s + ',' +
                      Integer(options[:width] * printer_dpi).to_s +
                       '^FN' + variable_fields_count.to_s + '^FS')

      # return unless label_height > 0 && label_width > 0
      # pdf.text_box '{Variable Field ' + variable_fields_count.to_s + '}',
      #              at: [Integer(x * pdf_dpi), Integer(label_width * pdf_dpi) -
      #              Integer(y * pdf_dpi) -
      #              Integer(options[:height] / 10) * pdf_dpi],
      #              size: Integer(options[:height] * pdf_dpi) if label_height &&
      #              label_width
    end

def variable_text_field ( x , y , params = { } ) x = 0 unless numeric? ( x ) y = 0 unless numeric? ( y ) options = { height : 0.1 , width : 0.1 } . merge! ( params ) self . variable_fields_count += 1 label_data . push ( '^FO' + Integer ( x * printer_dpi ) . to_s + ',' + Integer ( y * printer_dpi ) . to_s ) if params [ :orientation ] == :landscape label_data . push ( '^A0N,' ) else label_data . push ( '^A0B,' ) end label_data . push ( Integer ( options [ :height ] * printer_dpi ) . to_s + ',' + Integer ( options [ :width ] * printer_dpi ) . to_s + '^FN' + variable_fields_count . to_s + '^FS' ) end

Called when the new method is invoked
 Sets a variable field that can be recalled


def home_position(x, y)
      x = 0 unless numeric?(x)
      y = 0 unless numeric?(y)
      label_data.push('^LH' + x.to_s + ',' + y.to_s)
    end

def home_position ( x , y ) x = 0 unless numeric? ( x ) y = 0 unless numeric? ( y ) label_data . push ( '^LH' + x . to_s + ',' + y . to_s ) end

Set the home position of the label
 All other X and Y coordinates are
 relative to this


def draw_border(x, y, height, width)
      return unless numeric?(height) && numeric?(width)
      x = 0 unless numeric?(x)
      y = 0 unless numeric?(y)

      label_data.push('^FO' + Integer(x * printer_dpi).to_s + ',' +
                      Integer(y * printer_dpi).to_s + '^GB' +
                      Integer(height * printer_dpi).to_s +
                      ',' + Integer(width * printer_dpi).to_s + ',1^FS')

      # draw_rectangle(x * pdf_dpi, y * pdf_dpi, height * pdf_dpi, width * pdf_dpi)
    end

def draw_border ( x , y , height , width ) return unless numeric? ( height ) && numeric? ( width ) x = 0 unless numeric? ( x ) y = 0 unless numeric? ( y ) label_data . push ( '^FO' + Integer ( x * printer_dpi ) . to_s + ',' + Integer ( y * printer_dpi ) . to_s + '^GB' + Integer ( height * printer_dpi ) . to_s + ',' + Integer ( width * printer_dpi ) . to_s + ',1^FS' ) end


def reset_barcode_fields_to_default
      label_data.push('^BY' + Integer(self.barcode_default_module_width).to_s + ',' +
                      Float(self.barcode_default_width_ratio).to_s + ',' +
                      Integer(self.barcode_default_height).to_s)
    end

def reset_barcode_fields_to_default label_data . push ( '^BY' + Integer ( self . barcode_default_module_width ) . to_s + ',' + Float ( self . barcode_default_width_ratio ) . to_s + ',' + Integer ( self . barcode_default_height ) . to_s ) end

Some barcodes, such as QR codes may change document defaults.  These may be reset
 to the document defaults.

Some barcodes such as QR codes may change document defaults . These may be reset to the document defaults .


def draw_bar_code_39(bar_code_string, x, y, height)
      return unless label_height > 0 && label_width > 0
      pdf.bounding_box [x, Integer(label_width) - y - (height * pdf_dpi)],
                       width: (height * pdf_dpi) do
        barcode = Barby::Code39.new(bar_code_string)
        barcode.annotate_pdf(pdf, height: (height * pdf_dpi))
      end
    end

def draw_bar_code_39 ( bar_code_string , x , y , height ) return unless label_height > 0 && label_width > 0 pdf . bounding_box [ x , Integer ( label_width ) - y - ( height * pdf_dpi ) ] , width : ( height * pdf_dpi ) do barcode = Barby :: Code39 . new ( bar_code_string ) barcode . annotate_pdf ( pdf , height : ( height * pdf_dpi ) ) end end


def add_field(value)
      return if value.nil?
      return if value.strip.empty?

      # Increment the variable field count
      self.variable_fields_count += 1

      # Add the field
      label_data.push('^FN' + variable_fields_count.to_s +
                      '^FD' + value + '^FS')
    end

def add_field ( value ) return if value . nil? return if value . strip . empty? self . variable_fields_count += 1 label_data . push ( '^FN' + variable_fields_count . to_s + '^FD' + value + '^FS' ) end

Called when the new method is invoked
 Adds a variable that is to be applied to the saved template


def build_slug
      if localized?
        begin
          orig_locale = I18n.locale
          all_locales.each do |target_locale|
            I18n.locale = target_locale
            apply_slug
          end
        ensure
          I18n.locale = orig_locale
        end
      else
        apply_slug
      end
      true
    end

def build_slug if localized? begin orig_locale = I18n . locale all_locales . each do | target_locale | I18n . locale = target_locale apply_slug end ensure I18n . locale = orig_locale end else apply_slug end true end


def new_with_slugs?
      if localized?
        # We need to check if slugs are present for the locale without falling back
        # to a default
        new_record? && _slugs_translations.fetch(I18n.locale.to_s, []).any?
      else
        new_record? && _slugs.present?
      end
    end

def new_with_slugs? if localized? new_record? && _slugs_translations . fetch ( I18n . locale . to_s , [ ] ) . any? else new_record? && _slugs . present? end end

Returns true if object is a new record and slugs are present


def persisted_with_slug_changes?
      if localized?
        changes = _slugs_change
        return (persisted? && false) if changes.nil?

        # ensure we check for changes only between the same locale
        original = changes.first.try(:fetch, I18n.locale.to_s, nil)
        compare = changes.last.try(:fetch, I18n.locale.to_s, nil)
        persisted? && original != compare
      else
        persisted? && _slugs_changed?
      end
    end

def persisted_with_slug_changes? if localized? changes = _slugs_change return ( persisted? && false ) if changes . nil? original = changes . first . try ( :fetch , I18n . locale . to_s , nil ) compare = changes . last . try ( :fetch , I18n . locale . to_s , nil ) persisted? && original != compare else persisted? && _slugs_changed? end end

Returns true if object has been persisted and has changes in the slug


def distance_of_time_in_words(from_time, to_time=Time.now)
      from_time = from_time.to_time if from_time.respond_to?(:to_time)
      to_time = to_time.to_time if to_time.respond_to?(:to_time)
      seconds = (to_time - from_time).round
      distance_in_days = (seconds/(60*60*24)).round
      seconds = seconds % (60*60*24)
      distance_in_hours = (seconds/(60*60)).round
      seconds = seconds % (60*60)
      distance_in_minutes = (seconds/60).round
      seconds = seconds % 60
      distance_in_seconds = seconds

      s = ''
      s << "#{distance_in_days} days," if distance_in_days > 0
      s << "#{distance_in_hours} hours, " if distance_in_hours > 0
      s << "#{distance_in_minutes} minutes, " if distance_in_minutes > 0
      s << "#{distance_in_seconds} seconds"
      s
    end

def
distance_of_time_in_words
(
from_time
,
to_time
=
Time
.
now
)
from_time
=
from_time
.
to_time
if
from_time
.
respond_to?
(
:to_time
)
to_time
=
to_time
.
to_time
if
to_time
.
respond_to?
(
:to_time
)
seconds
=
(
to_time
from_time
)
.
round
distance_in_days
=
(
seconds
/
(
60
*
60
*
24
)
)
.
round
seconds
=
seconds
%
(
60
*
60
*
24
)
distance_in_hours
=
(
seconds
/
(
60
*
60
)
)
.
round
seconds
=
seconds
%
(
60
*
60
)
distance_in_minutes
=
(
seconds
/
60
)
.
round
seconds
=
seconds
%
60
distance_in_seconds
=
seconds
s
=
''
s
<<
"#{distance_in_days} days,"
if
distance_in_days
>
0
s
<<
"#{distance_in_hours} hours, "
if
distance_in_hours
>
0
s
<<
"#{distance_in_minutes} minutes, "
if
distance_in_minutes
>
0
s
<<
"#{distance_in_seconds} seconds"
s
end

Return the distance of time in words from the given from_time to the specified to_time. If to_time
 is not specified then Time.now is used. By default seconds are included...set the include_seconds
 argument to false to disable the seconds.

Return the distance of time in words from the given from_time to the specified to_time . If to_time is not specified then Time . now is used . By default seconds are included ... set the include_seconds argument to false to disable the seconds .


def approximate_distance_of_time_in_words(from_time, to_time=Time.now, include_seconds=true)
      from_time = from_time.to_time if from_time.respond_to?(:to_time)
      to_time = to_time.to_time if to_time.respond_to?(:to_time)
      distance_in_minutes = (((to_time - from_time).abs)/60).round
      distance_in_seconds = ((to_time - from_time).abs).round

      case distance_in_minutes
        when 0..1
          return (distance_in_minutes == 0) ? 'less than a minute' : '1 minute' unless include_seconds
        case distance_in_seconds
          when 0..4   then 'less than 5 seconds'
          when 5..9   then 'less than 10 seconds'
          when 10..19 then 'less than 20 seconds'
          when 20..39 then 'half a minute'
          when 40..59 then 'less than a minute'
          else             '1 minute'
        end
        when 2..44           then "#{distance_in_minutes} minutes"
        when 45..89          then 'about 1 hour'
        when 90..1439        then "about #{(distance_in_minutes.to_f / 60.0).round} hours"
        when 1440..2879      then '1 day'
        when 2880..43199     then "#{(distance_in_minutes / 1440).round} days"
        when 43200..86399    then 'about 1 month'
        when 86400..525959   then "#{(distance_in_minutes / 43200).round} months"
        when 525960..1051919 then 'about 1 year'
        else                      "over #{(distance_in_minutes / 525960).round} years"
      end
    end

Get the approximate disntance of time in words from the given from_time
 to the the given to_time. If to_time is not specified then it is set
 to Time.now. By default seconds are included...set the include_seconds
 argument to false to disable the seconds.

Get the approximate disntance of time in words from the given from_time to the the given to_time . If to_time is not specified then it is set to Time . now . By default seconds are included ... set the include_seconds argument to false to disable the seconds .


def track_error(control, msg)
      errors << msg
      control.error_handlers.each do |handler|
        handler.call(msg)
      end
    end

def track_error ( control , msg ) errors << msg control . error_handlers . each do | handler | handler . call ( msg ) end end

First attempt at centralizing error notifications


def process_batch(batch)
      batch = ETL::Batch::Batch.resolve(batch, self)
      say "Processing batch #{batch.file}"

      ETL::Engine.batch = ETL::Execution::Batch.create!(
        :batch_file => batch.file,
        :status => 'executing'
      )

      batch.execute

      ETL::Engine.batch.completed_at = Time.now
      ETL::Engine.batch.status = (errors.length > 0 ? 'completed with errors' : 'completed')
      ETL::Engine.batch.save!
    end

def
process_batch
(
batch
)
batch
=
ETL
::
Batch
::
Batch
.
resolve
(
batch
,
self
)
say
"Processing batch #{batch.file}"
ETL
::
Engine
.
batch
=
ETL
::
Execution
::
Batch
.
create!
(
:batch_file
=>
batch
.
file
,
:status
=>
'executing'
)
batch
.
execute
ETL
::
Engine
.
batch
.
completed_at
=
Time
.
now
ETL
::
Engine
.
batch
.
status
=
(
errors
.
length
>
0
'completed with errors'
:
'completed'
)
ETL
::
Engine
.
batch
.
save!
end