def scan_node(node, namespace, set_name, bin_names = nil, options = nil)
      policy = create_policy(options, ScanPolicy, default_scan_policy)
      # wait until all migrations are finished
      # TODO: implement
      # @cluster.WaitUntillMigrationIsFinished(policy.timeout)

      # Retry policy must be one-shot for scans.
      # copy on write for policy
      new_policy = policy.clone
      new_policy.max_retries = 0

      node = @cluster.get_node_by_name(node) unless node.is_a?(Aerospike::Node)

      recordset = Recordset.new(policy.record_queue_size, 1, :scan)

      Thread.new do
        Thread.current.abort_on_exception = true
        command = ScanCommand.new(node, new_policy, namespace, set_name, bin_names, recordset)
        begin
          execute_command(command)
        rescue => e
          Aerospike.logger.error(e.backtrace.join("\n")) unless e == SCAN_TERMINATED_EXCEPTION
          recordset.cancel(e)
        ensure
          recordset.thread_finished
        end
      end

      recordset
    end

def scan_node ( node , namespace , set_name , bin_names = nil , options = nil ) policy = create_policy ( options , ScanPolicy , default_scan_policy ) new_policy = policy . clone new_policy . max_retries = 0 node = @cluster . get_node_by_name ( node ) unless node . is_a? ( Aerospike :: Node ) recordset = Recordset . new ( policy . record_queue_size , 1 , :scan ) Thread . new do Thread . current . abort_on_exception = true command = ScanCommand . new ( node , new_policy , namespace , set_name , bin_names , recordset ) begin execute_command ( command ) rescue => e Aerospike . logger . error ( e . backtrace . join ( "\n" ) ) unless e == SCAN_TERMINATED_EXCEPTION recordset . cancel ( e ) ensure recordset . thread_finished end end recordset end

ScanNode reads all records in specified namespace and set, from one node only.
 The policy can be used to specify timeouts.

ScanNode reads all records in specified namespace and set from one node only . The policy can be used to specify timeouts .


def drop_user(user, options = nil)
      policy = create_policy(options, AdminPolicy, default_admin_policy)
      command = AdminCommand.new
      command.drop_user(@cluster, policy, user)
    end

def drop_user ( user , options = nil ) policy = create_policy ( options , AdminPolicy , default_admin_policy ) command = AdminCommand . new command . drop_user ( @cluster , policy , user ) end


def change_password(user, password, options = nil)
      raise Aerospike::Exceptions::Aerospike.new(INVALID_USER) unless @cluster.user && @cluster.user != ""
      policy = create_policy(options, AdminPolicy, default_admin_policy)

      hash = AdminCommand.hash_password(password)
      command = AdminCommand.new

      if user == @cluster.user
        # Change own password.
        command.change_password(@cluster, policy, user, hash)
      else
        # Change other user's password by user admin.
        command.set_password(@cluster, policy, user, hash)
      end

      @cluster.change_password(user, hash)
    end

def change_password ( user , password , options = nil ) raise Aerospike :: Exceptions :: Aerospike . new ( INVALID_USER ) unless @cluster . user && @cluster . user != "" policy = create_policy ( options , AdminPolicy , default_admin_policy ) hash = AdminCommand . hash_password ( password ) command = AdminCommand . new if user == @cluster . user command . change_password ( @cluster , policy , user , hash ) else command . set_password ( @cluster , policy , user , hash ) end @cluster . change_password ( user , hash ) end

Change user's password. Clear-text password will be hashed using bcrypt before sending to server.

Change user s password . Clear - text password will be hashed using bcrypt before sending to server .


def grant_roles(user, roles, options = nil)
      policy = create_policy(options, AdminPolicy, default_admin_policy)
      command = AdminCommand.new
      command.grant_roles(@cluster, policy, user, roles)
    end

def grant_roles ( user , roles , options = nil ) policy = create_policy ( options , AdminPolicy , default_admin_policy ) command = AdminCommand . new command . grant_roles ( @cluster , policy , user , roles ) end


def query_users(options = nil)
      policy = create_policy(options, AdminPolicy, default_admin_policy)
      command = AdminCommand.new
      command.query_users(@cluster, policy)
    end

def query_users ( options = nil ) policy = create_policy ( options , AdminPolicy , default_admin_policy ) command = AdminCommand . new command . query_users ( @cluster , policy ) end


def next_record
      raise @thread_exception.get unless @thread_exception.get.nil?

      r = @records.deq

      set_exception if r.nil?

      r
    end

def next_record raise @thread_exception . get unless @thread_exception . get . nil? r = @records . deq set_exception if r . nil? r end

fetches and return the first record from the queue
 if the operation is not finished and the queue is empty it blocks and waits for new records
 it sets the exception if it reaches the EOF mark, and returns nil
 EOF means the operation has finished and no more records are comming from server nodes
 it re-raises the exception occurred in threads, or which was set after reaching the EOF in the previous call

fetches and return the first record from the queue if the operation is not finished and the queue is empty it blocks and waits for new records it sets the exception if it reaches the EOF mark and returns nil EOF means the operation has finished and no more records are comming from server nodes it re - raises the exception occurred in threads or which was set after reaching the EOF in the previous call


def each(&block)
      r = true
      while r
        r = next_record
        # nil means EOF
        unless r.nil?
          block.call(r)
        else
          # reached the EOF
          break
        end
      end
    end

def each ( & block ) r = true while r r = next_record unless r . nil? block . call ( r ) else break end end end

fetches and returns all the records from the queue until the whole operation is finished and it reaches an EOF mark
 calling cancel inside the each block raises an exception to signal other consumer threads


def intercom_script_tag(user_details = nil, options={})
      controller.instance_variable_set(IntercomRails::SCRIPT_TAG_HELPER_CALLED_INSTANCE_VARIABLE, true) if defined?(controller)
      options[:user_details] = user_details if user_details.present?
      options[:find_current_user_details] = !options[:user_details]
      options[:find_current_company_details] = !(options[:user_details] && options[:user_details][:company])
      options[:controller] = controller if defined?(controller)
      ScriptTag.new(options)
    end

Generate an intercom script tag.

 @param user_details [Hash] a customizable hash of user details
 @param options [Hash] an optional hash for Identity Verification and widget customization
 @option user_details [String] :app_id Your application id
 @option user_details [String] :user_id unique id of this user within your application
 @option user_details [String] :email email address for this user
 @option user_details [String] :name the users name, _optional_ but useful for identify people in the Intercom App.
 @option user_details [Hash] :custom_data custom attributes you'd like saved for this user on Intercom.
 @option options [String] :widget a hash containing a css selector for an element which when clicked should show the Intercom widget
 @option options [String] :secret Your app secret for Identity Verification
 @option options [String] :nonce a nonce generated by your CSP framework to be included inside the javascript tag
 @return [String] Intercom script tag
 @example basic example
   <%= intercom_script_tag({ :app_id => "your-app-id",
                             :user_id => current_user.id,
                             :email => current_user.email,
                             :custom_data => { :plan => current_user.plan.name },
                             :name => current_user.name }) %>
 @example with widget activator for launching then widget when an element matching the css selector '#Intercom' is clicked.
   <%= intercom_script_tag({ :app_id => "your-app-id",
                             :user_id => current_user.id,
                             :email => current_user.email,
                             :custom_data => { :plan => current_user.plan.name },
                             :name => current_user.name },
                             {:widget => {:activator => "#Intercom"}},) %>


def move_free(aim, speed)
      if aim.is_a? Vector
        x_d = aim.x - @x; y_d = aim.y - @y
        distance = Math.sqrt(x_d**2 + y_d**2)

        if distance == 0
          @speed.x = @speed.y = 0
          return
        end

        @speed.x = 1.0 * x_d * speed / distance
        @speed.y = 1.0 * y_d * speed / distance

        if (@speed.x < 0 and @x + @speed.x <= aim.x) or (@speed.x >= 0 and @x + @speed.x >= aim.x)
          @x = aim.x
          @speed.x = 0
        else
          @x += @speed.x
        end

        if (@speed.y < 0 and @y + @speed.y <= aim.y) or (@speed.y >= 0 and @y + @speed.y >= aim.y)
          @y = aim.y
          @speed.y = 0
        else
          @y += @speed.y
        end
      else
        rads = aim * Math::PI / 180
        @speed.x = speed * Math.cos(rads)
        @speed.y = speed * Math.sin(rads)
        @x += @speed.x
        @y += @speed.y
      end
    end

def move_free ( aim , speed ) if aim . is_a? Vector x_d = aim . x - @x ; y_d = aim . y - @y distance = Math . sqrt ( x_d ** 2 + y_d ** 2 ) if distance == 0 @speed . x = @speed . y = 0 return end @speed . x = 1.0 * x_d * speed / distance @speed . y = 1.0 * y_d * speed / distance if ( @speed . x < 0 and @x + @speed . x <= aim . x ) or ( @speed . x >= 0 and @x + @speed . x >= aim . x ) @x = aim . x @speed . x = 0 else @x += @speed . x end if ( @speed . y < 0 and @y + @speed . y <= aim . y ) or ( @speed . y >= 0 and @y + @speed . y >= aim . y ) @y = aim . y @speed . y = 0 else @y += @speed . y end else rads = aim * Math :: PI / 180 @speed . x = speed * Math . cos ( rads ) @speed . y = speed * Math . sin ( rads ) @x += @speed . x @y += @speed . y end end

Moves this object, without performing any collision checking, towards
 a specified point or in a specified direction.

 Parameters:
 [aim] A +Vector+ specifying where the object will move to or an angle (in
       degrees) indicating the direction of the movement. Angles are
       measured starting from the right (i.e., to move to the right, the
       angle must be 0) and raising clockwise.
 [speed] The constant speed at which the object will move. This must be
         provided as a scalar, not a vector.

Moves this object without performing any collision checking towards a specified point or in a specified direction .


def get_absolute_size
      return Vector.new(@tile_size.x * @size.x, @tile_size.y * @size.y) unless @isometric
      avg = (@size.x + @size.y) * 0.5
      Vector.new (avg * @tile_size.x).to_i, (avg * @tile_size.y).to_i
    end

def get_absolute_size return Vector . new ( @tile_size . x * @size . x , @tile_size . y * @size . y ) unless @isometric avg = ( @size . x + @size . y ) * 0.5 Vector . new ( avg * @tile_size . x ) . to_i , ( avg * @tile_size . y ) . to_i end

Creates a new map.

 Parameters:
 [t_w] The width of the tiles.
 [t_h] The height of the tiles.
 [t_x_count] The horizontal count of tiles in the map.
 [t_y_count] The vertical count of tiles in the map.
 [scr_w] Width of the viewport for the map.
 [scr_h] Height of the viewport for the map.
 [isometric] Whether to use a isometric map. By default, an ortogonal map
             is used.
 [limit_cam] Whether the camera should respect the bounds of the map
             (i.e., when given coordinates that would imply regions
             outside the map to appear in the screen, the camera would
             move to the nearest position where only the map shows up
             in the screen).
 Returns a Vector with the total size of the map, in pixels (x for the
 width and y for the height).


def get_screen_pos(map_x, map_y)
      return Vector.new(map_x * @tile_size.x - @cam.x, map_y * @tile_size.y - @cam.y) unless @isometric
      Vector.new ((map_x - map_y - 1) * @tile_size.x * 0.5) - @cam.x + @x_offset,
                 ((map_x + map_y) * @tile_size.y * 0.5) - @cam.y
    end

def get_screen_pos ( map_x , map_y ) return Vector . new ( map_x * @tile_size . x - @cam . x , map_y * @tile_size . y - @cam . y ) unless @isometric Vector . new ( ( map_x - map_y - 1 ) * @tile_size . x * 0.5 ) - @cam . x + @x_offset , ( ( map_x + map_y ) * @tile_size . y * 0.5 ) - @cam . y end

Returns the position in the screen corresponding to the given tile
 indices.

 Parameters:
 [map_x] The index of the tile in the horizontal direction. It must be in
         the interval 0..t_x_count.
 [map_y] The index of the tile in the vertical direction. It must be in
         the interval 0..t_y_count.

Returns the position in the screen corresponding to the given tile indices .


def get_map_pos(scr_x, scr_y)
      return Vector.new((scr_x + @cam.x) / @tile_size.x, (scr_y + @cam.y) / @tile_size.y) unless @isometric

      # Gets the position transformed to isometric coordinates
      v = get_isometric_position scr_x, scr_y

      # divides by the square size to find the position in the matrix
      Vector.new((v.x * @inverse_square_size).to_i, (v.y * @inverse_square_size).to_i)
    end

def get_map_pos ( scr_x , scr_y ) return Vector . new ( ( scr_x + @cam . x ) / @tile_size . x , ( scr_y + @cam . y ) / @tile_size . y ) unless @isometric v = get_isometric_position scr_x , scr_y Vector . new ( ( v . x * @inverse_square_size ) . to_i , ( v . y * @inverse_square_size ) . to_i ) end

Returns the tile in the map that corresponds to the given position in
 the screen, as a Vector, where x is the horizontal index and y the
 vertical index.

 Parameters:
 [scr_x] The x-coordinate in the screen.
 [scr_y] The y-coordinate in the screen.

Returns the tile in the map that corresponds to the given position in the screen as a Vector where x is the horizontal index and y the vertical index .


def is_in_map(v)
      v.x >= 0 && v.y >= 0 && v.x < @size.x && v.y < @size.y
    end

def is_in_map ( v ) v . x >= 0 && v . y >= 0 && v . x < @size . x && v . y < @size . y end

Verifies whether a tile is inside the map.

 Parameters:
 [v] A Vector representing the tile, with x as the horizontal index and
     y as the vertical index.

Verifies whether a tile is inside the map .


def animate_once(indices, interval)
      if @animate_once_control == 2
        return if indices == @animate_once_indices && interval == @animate_once_interval
        @animate_once_control = 0
      end

      unless @animate_once_control == 1
        @anim_counter = 0
        @img_index = indices[0]
        @index_index = 0
        @animate_once_indices = indices
        @animate_once_interval = interval
        @animate_once_control = 1
        return
      end

      @anim_counter += 1
      return unless @anim_counter >= interval

      @index_index += 1
      @img_index = indices[@index_index]
      @anim_counter = 0
      @animate_once_control = 2 if @index_index == indices.length - 1
    end

Causes the sprite to animate through the +indices+ array exactly once,
 so that the animation stops once it reaches the last index in the array.
 Subsequent calls with the same parameters will have no effect, but if
 the index or interval changes, or if +set_animation+ is called, then a
 new animation cycle will begin.

 Parameters:
 [indices] The sequence of image indices used in the animation. See
           +animate+ for details.
 [interval] The amount of frames between each change in the image index.
            See +animate+ for details.

Causes the sprite to animate through the + indices + array exactly once so that the animation stops once it reaches the last index in the array . Subsequent calls with the same parameters will have no effect but if the index or interval changes or if + set_animation + is called then a new animation cycle will begin .


def draw(map = nil, scale_x = 1, scale_y = 1, alpha = 0xff, color = 0xffffff, angle = nil, flip = nil, z_index = 0, round = false)
      if map.is_a? Hash
        scale_x = map.fetch(:scale_x, 1)
        scale_y = map.fetch(:scale_y, 1)
        alpha = map.fetch(:alpha, 0xff)
        color = map.fetch(:color, 0xffffff)
        angle = map.fetch(:angle, nil)
        flip = map.fetch(:flip, nil)
        z_index = map.fetch(:z_index, 0)
        round = map.fetch(:round, false)
        map = map.fetch(:map, nil)
      end

      color = (alpha << 24) | color
      if angle
        @img[@img_index].draw_rot @x - (map ? map.cam.x : 0) + @img[0].width * scale_x * 0.5,
                                  @y - (map ? map.cam.y : 0) + @img[0].height * scale_y * 0.5,
                                  z_index, angle, 0.5, 0.5, (flip == :horiz ? -scale_x : scale_x),
                                  (flip == :vert ? -scale_y : scale_y), color
      else
        x = @x - (map ? map.cam.x : 0) + (flip == :horiz ? scale_x * @img[0].width : 0)
        y = @y - (map ? map.cam.y : 0) + (flip == :vert ? scale_y * @img[0].height : 0)
        @img[@img_index].draw (round ? x.round : x), (round ? y.round : y),
                              z_index, (flip == :horiz ? -scale_x : scale_x),
                              (flip == :vert ? -scale_y : scale_y), color
      end
    end

def draw ( map = nil , scale_x = 1 , scale_y = 1 , alpha = 0xff , color = 0xffffff , angle = nil , flip = nil , z_index = 0 , round = false ) if map . is_a? Hash scale_x = map . fetch ( :scale_x , 1 ) scale_y = map . fetch ( :scale_y , 1 ) alpha = map . fetch ( :alpha , 0xff ) color = map . fetch ( :color , 0xffffff ) angle = map . fetch ( :angle , nil ) flip = map . fetch ( :flip , nil ) z_index = map . fetch ( :z_index , 0 ) round = map . fetch ( :round , false ) map = map . fetch ( :map , nil ) end color = ( alpha << 24 ) | color if angle @img [ @img_index ] . draw_rot @x - ( map ? map . cam . x : 0 ) + @img [ 0 ] . width * scale_x * 0.5 , @y - ( map ? map . cam . y : 0 ) + @img [ 0 ] . height * scale_y * 0.5 , z_index , angle , 0.5 , 0.5 , ( flip == :horiz ? - scale_x : scale_x ) , ( flip == :vert ? - scale_y : scale_y ) , color else x = @x - ( map ? map . cam . x : 0 ) + ( flip == :horiz ? scale_x * @img [ 0 ] . width : 0 ) y = @y - ( map ? map . cam . y : 0 ) + ( flip == :vert ? scale_y * @img [ 0 ] . height : 0 ) @img [ @img_index ] . draw ( round ? x . round : x ) , ( round ? y . round : y ) , z_index , ( flip == :horiz ? - scale_x : scale_x ) , ( flip == :vert ? - scale_y : scale_y ) , color end end

Draws the sprite in the screen

 Parameters:
 [map] A Map object, relative to which the sprite will be drawn (the x
       and y coordinates of the sprite will be changed according to the
       position of the camera).
 [scale_x] A scale factor to be applied horizontally to the image.
 [scale_y] A scale factor to be applied vertically to the image.
 [alpha] The opacity with which the image will be drawn. Valid values
         vary from 0 (fully transparent) to 255 (fully opaque).
 [color] A color filter to apply to the image. A white (0xffffff) filter
         will keep all colors unchanged, while a black (0x000000) filter
         will turn all colors to black. A red (0xff0000) filter will keep
         reddish colors with slight or no change, whereas bluish colors
         will be darkened, for example.
 [angle] A rotation, in degrees, to be applied to the image, relative to
         its center.
 [flip] Specify +:horiz+ to draw the image horizontally flipped or +:vert+
        to draw it vertically flipped.
 [z_index] The z-order to draw the object. Objects with larger z-orders
           will be drawn on top of the ones with smaller z-orders.
 [round] Specify whether the drawing coordinates should be rounded to an
         integer before drawing, to avoid little distortions of the image.
         Only applies when the image is not rotated.

 *Obs.:* This method accepts named parameters.


def update
      return unless @enabled and @visible

      mouse_over = Mouse.over? @x, @y, @w, @h
      mouse_press = Mouse.button_pressed? :left
      mouse_rel = Mouse.button_released? :left

      if @state == :up
        if mouse_over
          @img_index = 1
          @state = :over
        else
          @img_index = 0
        end
      elsif @state == :over
        if not mouse_over
          @img_index = 0
          @state = :up
        elsif mouse_press
          @img_index = 2
          @state = :down
        else
          @img_index = 1
        end
      elsif @state == :down
        if not mouse_over
          @img_index = 0
          @state = :down_out
        elsif mouse_rel
          @img_index = 1
          @state = :over
          click
        else
          @img_index = 2
        end
      else # :down_out
        if mouse_over
          @img_index = 2
          @state = :down
        elsif mouse_rel
          @img_index = 0
          @state = :up
        else
          @img_index = 0
        end
      end
    end

Creates a button.

 Parameters:
 [x] The x-coordinate where the button will be drawn in the screen.
 [y] The y-coordinate where the button will be drawn in the screen.
 [font] The Gosu::Font object that will be used to draw the
        button text.
 [text] The button text. Can be +nil+ or empty.
 [img] A spritesheet containing four images in a column, representing,
       from top to bottom, the default state, the hover state (when the
       mouse is over the button), the pressed state (when the mouse
       button is down and the cursor is over the button) and the disabled
       state. If +nil+, the +width+ and +height+ parameters must be
       provided.
 [text_color] Color of the button text, in hexadecimal RRGGBB format.
 [disabled_text_color] Color of the button text, when it's disabled, in
                       hexadecimal RRGGBB format.
 [over_text_color] Color of the button text, when the cursor is over it
                   (hexadecimal RRGGBB).
 [down_text_color] Color of the button text, when it is pressed
                   (hexadecimal RRGGBB).
 [center_x] Whether the button text should be horizontally centered in its
            area (the area is defined by the image size, if an image is
            given, or by the +width+ and +height+ parameters, otherwise).
 [center_y] Whether the button text should be vertically centered in its
            area (the area is defined by the image size, if an image is
            given, or by the +width+ and +height+ parameters, otherwise).
 [margin_x] The x offset, from the button x-coordinate, to draw the text.
            This parameter is used only if +center+ is false.
 [margin_y] The y offset, from the button y-coordinate, to draw the text.
            This parameter is used only if +center+ is false.
 [width] Width of the button clickable area. This parameter is used only
         if +img+ is +nil+.
 [height] Height of the button clickable area. This parameter is used
          only if +img+ is +nil+.
 [params] An object containing any parameters you want passed to the
          +action+ block. When the button is clicked, the following is
          called:
            @action.call @params
          Note that this doesn't force you to declare a block that takes
          parameters.
 [retro] Whether the image should be loaded with the 'retro' option set
         (see +Gosu::Image+ for details). If the value is omitted, the
         +Res.retro_images+ value will be used.
 [scale_x] Horizontal scale to draw the component with.
 [scale_y] Vertical scale to draw the component with.
 [anchor] See parameter with the same name in Panel#initialize for details.
 [action] The block of code executed when the button is clicked (or by
          calling the +click+ method).

 *Obs.:* This method accepts named parameters, but +x+ and +y+ are
 mandatory (also, +img+ is mandatory when +width+ and +height+ are not
 provided, and vice-versa).
 Updates the button, checking the mouse movement and buttons to define
 the button state.


def draw(alpha = 0xff, z_index = 0, color = 0xffffff)
      return unless @visible

      color = (alpha << 24) | color
      text_color =
        if @enabled
          if @state == :down
            @down_text_color
          else
            @state == :over ? @over_text_color : @text_color
          end
        else
          @disabled_text_color
        end
      text_color = (alpha << 24) | text_color
      @img[@img_index].draw @x, @y, z_index, @scale_x, @scale_y, color if @img
      if @text
        if @center_x or @center_y
          rel_x = @center_x ? 0.5 : 0
          rel_y = @center_y ? 0.5 : 0
          @font.draw_text_rel @text, @text_x, @text_y, z_index, rel_x, rel_y, @scale_x, @scale_y, text_color
        else
          @font.draw_text @text, @text_x, @text_y, z_index, @scale_x, @scale_y, text_color
        end
      end
    end

Draws the button in the screen.

 Parameters:
 [alpha] The opacity with which the button will be drawn. Allowed values
         vary between 0 (fully transparent) and 255 (fully opaque).
 [z_index] The z-order to draw the object. Objects with larger z-orders
           will be drawn on top of the ones with smaller z-orders.
 [color] Color to apply a filter to the image.


def text=(value, trigger_changed = true)
      @text = value[0...@max_length]
      @nodes.clear; @nodes << @text_x
      x = @nodes[0]
      @text.chars.each { |char|
        x += @font.text_width(char) * @scale_x
        @nodes << x
      }
      @cur_node = @nodes.size - 1
      @anchor1 = nil
      @anchor2 = nil
      set_cursor_visible
      @on_text_changed.call @text, @params if trigger_changed && @on_text_changed
    end

def text = ( value , trigger_changed = true ) @text = value [ 0 ... @max_length ] @nodes . clear ; @nodes << @text_x x = @nodes [ 0 ] @text . chars . each { | char | x += @font . text_width ( char ) * @scale_x @nodes << x } @cur_node = @nodes . size - 1 @anchor1 = nil @anchor2 = nil set_cursor_visible @on_text_changed . call @text , @params if trigger_changed && @on_text_changed end

Sets the text of the text field to the specified value.

 Parameters:
 [value] The new text to be set. If it's longer than the +max_length+
         parameter used in the constructor, it will be truncated to
         +max_length+ characters.

Sets the text of the text field to the specified value .


def set_position(x, y)
      d_x = x - @x
      d_y = y - @y
      @x = x; @y = y
      @text_x += d_x
      @text_y += d_y
      @nodes.map! do |n|
        n + d_x
      end
    end

def set_position ( x , y ) d_x = x - @x d_y = y - @y @x = x ; @y = y @text_x += d_x @text_y += d_y @nodes . map! do | n | n + d_x end end

Sets the position of the text field in the screen.

 Parameters:
 [x] The new x-coordinate for the text field.
 [y] The new y-coordinate for the text field.

Sets the position of the text field in the screen .


def draw(alpha = 0xff, z_index = 0, color = 0xffffff, disabled_color = 0x808080)
      return unless @visible

      color = (alpha << 24) | ((@enabled or @disabled_img) ? color : disabled_color)
      text_color = (alpha << 24) | (@enabled ? @text_color : @disabled_text_color)
      img = ((@enabled or @disabled_img.nil?) ? @img : @disabled_img)
      img.draw @x, @y, z_index, @scale_x, @scale_y, color
      @font.draw_text @text, @text_x, @text_y, z_index, @scale_x, @scale_y, text_color

      if @anchor1 and @anchor2
        selection_color = ((alpha / 2) << 24) | @selection_color
        G.window.draw_quad @nodes[@anchor1], @text_y, selection_color,
                           @nodes[@anchor2] + 1, @text_y, selection_color,
                           @nodes[@anchor2] + 1, @text_y + @font.height * @scale_y, selection_color,
                           @nodes[@anchor1], @text_y + @font.height * @scale_y, selection_color, z_index
      end

      if @cursor_visible
        if @cursor_img
          @cursor_img.draw @nodes[@cur_node] - (@cursor_img.width * @scale_x) / 2, @text_y, z_index, @scale_x, @scale_y
        else
          cursor_color = alpha << 24
          G.window.draw_quad @nodes[@cur_node], @text_y, cursor_color,
                             @nodes[@cur_node] + 1, @text_y, cursor_color,
                             @nodes[@cur_node] + 1, @text_y + @font.height * @scale_y, cursor_color,
                             @nodes[@cur_node], @text_y + @font.height * @scale_y, cursor_color, z_index
        end
      end
    end

Draws the text field in the screen.

 Parameters:
 [alpha] The opacity with which the text field will be drawn. Allowed
         values vary between 0 (fully transparent) and 255 (fully opaque).
 [z_index] The z-order to draw the object. Objects with larger z-orders
           will be drawn on top of the ones with smaller z-orders.
 [color] Color to apply a filter to the image.
 [disabled_color] Color to apply a filter to the image when the field is
                  disabled.


def draw(alpha = 0xff, z_index = 0, color = 0xffffff)
      return unless @visible

      if @bg
        c = (alpha << 24) | color
        @bg.draw @x, @y, z_index, @scale_x, @scale_y, c
      else
        c = (alpha << 24) | @bg_color
        G.window.draw_quad @x, @y, c,
                           @x + @w, @y, c,
                           @x + @w, @y + @h, c,
                           @x, @y + @h, c, z_index
      end
      if @fg
        c = (alpha << 24) | color
        w1 = @fg.width * @scale_x
        w2 = (@value.to_f / @max_value * @w).round
        x0 = @x + @fg_margin_x
        x = 0
        while x <= w2 - w1
          @fg.draw x0 + x, @y + @fg_margin_y, z_index, @scale_x, @scale_y, c
          x += w1
        end
        if w2 - x > 0
          img = Gosu::Image.new(@fg_path, tileable: true, retro: @retro, rect: [0, 0, ((w2 - x) / @scale_x).round, @fg.height])
          img.draw x0 + x, @y + @fg_margin_y, z_index, @scale_x, @scale_y, c
        end
      else
        c = (alpha << 24) | @fg_color
        rect_r = @x + (@value.to_f / @max_value * @w).round
        G.window.draw_quad @x, @y, c,
                           rect_r, @y, c,
                           rect_r, @y + @h, c,
                           @x, @y + @h, c, z_index
      end
      if @font
        c = (alpha << 24) | @text_color
        @text = @format == '%' ? "#{(@value.to_f / @max_value * 100).round}%" : "#{@value}/#{@max_value}"
        @font.draw_text_rel @text, @x + @w / 2, @y + @h / 2, z_index, 0.5, 0.5, @scale_x, @scale_y, c
      end
    end

Draws the progress bar.

 Parameters:
 [alpha] (+Fixnum+) The opacity with which the progress bar will be drawn.
         Allowed values vary between 0 (fully transparent) and 255 (fully
         opaque).
 [z_index] (+Fixnum+) The z-order to draw the object. Objects with larger
           z-orders will be drawn on top of the ones with smaller z-orders.
 [color] Color to apply a filter to the images (when these are provided).


def update
      return unless @enabled and @visible
      if @open and Mouse.button_pressed? :left and not Mouse.over?(@x, @y, @w, @max_h)
        toggle
        return
      end
      @buttons.each { |b| b.update }
    end

def update return unless @enabled and @visible if @open and Mouse . button_pressed? :left and not Mouse . over? ( @x , @y , @w , @max_h ) toggle return end @buttons . each { | b | b . update } end

Creates a new drop-down list.

 Parameters:
 [x] The x-coordinate of the object.
 [y] The y-coordinate of the object.
 [font] Font to be used by the buttons that compose the drop-down list.
 [img] Image of the main button, i.e., the one at the top, that toggles
       visibility of the other buttons (the "option" buttons).
 [opt_img] Image for the "option" buttons, as described above.
 [options] Array of available options for this control (+String+s).
 [option] Index of the firstly selected option.
 [text_margin] Left margin of the text inside the buttons (vertically, the
               text will always be centered).
 [width] Width of the control, used when no image is provided.
 [height] Height of the control, used when no image is provided.
 [text_color] Used as the +text_color+ parameter in the constructor of the
              buttons.
 [disabled_text_color] Analogous to +text_color+.
 [over_text_color] Same as above.
 [down_text_color] Same as above.
 [retro] Whether the images should be loaded with the 'retro' option set
         (see +Gosu::Image+ for details). If the value is omitted, the
         +Res.retro_images+ value will be used.
 [scale_x] Horizontal scale to draw the component with.
 [scale_y] Vertical scale to draw the component with.
 [anchor] See parameter with the same name in Panel#initialize for details.
 [on_changed] Action performed when the value of the dropdown is changed.
              It must be a block with two parameters, which will receive
              the old and the new value, respectively.

 *Obs.:* This method accepts named parameters, but +x+, +y+, +font+ and
 +options+ are mandatory (also, +img+ and +opt_img+ are mandatory when
 +width+ and +height+ are not provided, and vice-versa).
 Updates the control.


def value=(val)
      if @options.include? val
        old = @value
        @value = @buttons[0].text = val
        @on_changed.call(old, val) if @on_changed
      end
    end

def value = ( val ) if @options . include? val old = @value @value = @buttons [ 0 ] . text = val @on_changed . call ( old , val ) if @on_changed end end

Sets the currently selected value of the drop-down list. It is ignored if
 it is not among the available options.

Sets the currently selected value of the drop - down list . It is ignored if it is not among the available options .


def draw(alpha = 0xff, z_index = 0, color = 0xffffff, over_color = 0xcccccc)
      return unless @visible
      unless @img
        bottom = @y + (@open ? @max_h : @h) + @scale_y
        b_color = (alpha << 24)
        G.window.draw_quad @x - @scale_x, @y - @scale_y, b_color,
                           @x + @w + @scale_x, @y - @scale_y, b_color,
                           @x + @w + @scale_x, bottom, b_color,
                           @x - @scale_x, bottom, b_color, z_index
        @buttons.each do |b|
          c = (alpha << 24) | (b.state == :over ? over_color : color)
          G.window.draw_quad b.x, b.y, c,
                             b.x + b.w, b.y, c,
                             b.x + b.w, b.y + b.h, c,
                             b.x, b.y + b.h, c, z_index + 1 if b.visible
        end
      end
      @buttons[0].draw(alpha, z_index, color)
      @buttons[1..-1].each { |b| b.draw alpha, z_index + 1, color }
    end

def draw ( alpha = 0xff , z_index = 0 , color = 0xffffff , over_color = 0xcccccc ) return unless @visible unless @img bottom = @y + ( @open ? @max_h : @h ) + @scale_y b_color = ( alpha << 24 ) G . window . draw_quad @x - @scale_x , @y - @scale_y , b_color , @x + @w + @scale_x , @y - @scale_y , b_color , @x + @w + @scale_x , bottom , b_color , @x - @scale_x , bottom , b_color , z_index @buttons . each do | b | c = ( alpha << 24 ) | ( b . state == :over ? over_color : color ) G . window . draw_quad b . x , b . y , c , b . x + b . w , b . y , c , b . x + b . w , b . y + b . h , c , b . x , b . y + b . h , c , z_index + 1 if b . visible end end @buttons [ 0 ] . draw ( alpha , z_index , color ) @buttons [ 1 .. - 1 ] . each { | b | b . draw alpha , z_index + 1 , color } end

Draws the drop-down list.

 Parameters:
 [alpha] (+Fixnum+) The opacity with which the drop-down list will be
         drawn. Allowed values vary between 0 (fully transparent) and 255
         (fully opaque).
 [z_index] (+Fixnum+) The z-order to draw the object. Objects with larger
           z-orders will be drawn on top of the ones with smaller z-orders.
 [color] Color of the buttons, if no image was provided, or color to apply
         a filter to the images.
 [over_color] Color of the buttons when the mouse is over them (when no
              image was provided).


def draw(alpha = 255, z_index = 0, color = 0xffffff)
      c = @enabled ? @text_color : @disabled_text_color
      r1 = c >> 16
      g1 = (c & 0xff00) >> 8
      b1 = (c & 0xff)
      r2 = color >> 16
      g2 = (color & 0xff00) >> 8
      b2 = (color & 0xff)
      r1 *= r2; r1 /= 255
      g1 *= g2; g1 /= 255
      b1 *= b2; b1 /= 255
      color = (alpha << 24) | (r1 << 16) | (g1 << 8) | b1
      @font.draw_text(@text, @x, @y, z_index, @scale_x, @scale_y, color)
    end

Creates a new label.

 Parameters:
 [x] The x-coordinate of the label.
 [y] The x-coordinate of the label.
 [font] Font that will be used to draw the label's text.
 [text] The label's text.
 [text_color] The default text color.
 [disabled_text_color] The text color when the label is disabled.
 [scale_x] The horizontal scale factor.
 [scale_y] The vertical scale factor.
 [anchor] See parameter with the same name in Panel#initialize for details.
 Draws the label.

 Parameters:
 [alpha] The opacity with which the label will be drawn. Allowed values
         vary between 0 (fully transparent) and 255 (fully opaque).
 [z_index] The z-order to draw the object. Objects with larger z-orders
           will be drawn on top of the ones with smaller z-orders.
 [color] Color to apply a filter to the text.


def write_line(text, x = nil, y = nil, mode = :left, color = 0, alpha = 0xff,
                   effect = nil, effect_color = 0, effect_size = 1, effect_alpha = 0xff,
                   z_index = 0)
      if text.is_a? Hash
        x = text[:x]
        y = text[:y]
        mode = text.fetch(:mode, :left)
        color = text.fetch(:color, 0)
        alpha = text.fetch(:alpha, 0xff)
        effect = text.fetch(:effect, nil)
        effect_color = text.fetch(:effect_color, 0)
        effect_size = text.fetch(:effect_size, 1)
        effect_alpha = text.fetch(:effect_alpha, 0xff)
        z_index = text.fetch(:z_index, 0)
        text = text[:text]
      end

      color = (alpha << 24) | color
      rel =
        case mode
        when :left then 0
        when :center then 0.5
        when :right then 1
        else 0
        end
      if effect
        effect_color = (effect_alpha << 24) | effect_color
        if effect == :border
          @font.draw_markup_rel text, x - effect_size, y - effect_size, z_index, rel, 0, 1, 1, effect_color
          @font.draw_markup_rel text, x, y - effect_size, z_index, rel, 0, 1, 1, effect_color
          @font.draw_markup_rel text, x + effect_size, y - effect_size, z_index, rel, 0, 1, 1, effect_color
          @font.draw_markup_rel text, x + effect_size, y, z_index, rel, 0, 1, 1, effect_color
          @font.draw_markup_rel text, x + effect_size, y + effect_size, z_index, rel, 0, 1, 1, effect_color
          @font.draw_markup_rel text, x, y + effect_size, z_index, rel, 0, 1, 1, effect_color
          @font.draw_markup_rel text, x - effect_size, y + effect_size, z_index, rel, 0, 1, 1, effect_color
          @font.draw_markup_rel text, x - effect_size, y, z_index, rel, 0, 1, 1, effect_color
        elsif effect == :shadow
          @font.draw_markup_rel text, x + effect_size, y + effect_size, z_index, rel, 0, 1, 1, effect_color
        end
      end
      @font.draw_markup_rel text, x, y, z_index, rel, 0, 1, 1, color
    end

def write_line ( text , x = nil , y = nil , mode = :left , color = 0 , alpha = 0xff , effect = nil , effect_color = 0 , effect_size = 1 , effect_alpha = 0xff , z_index = 0 ) if text . is_a? Hash x = text [ :x ] y = text [ :y ] mode = text . fetch ( :mode , :left ) color = text . fetch ( :color , 0 ) alpha = text . fetch ( :alpha , 0xff ) effect = text . fetch ( :effect , nil ) effect_color = text . fetch ( :effect_color , 0 ) effect_size = text . fetch ( :effect_size , 1 ) effect_alpha = text . fetch ( :effect_alpha , 0xff ) z_index = text . fetch ( :z_index , 0 ) text = text [ :text ] end color = ( alpha << 24 ) | color rel = case mode when :left then 0 when :center then 0.5 when :right then 1 else 0 end if effect effect_color = ( effect_alpha << 24 ) | effect_color if effect == :border @font . draw_markup_rel text , x - effect_size , y - effect_size , z_index , rel , 0 , 1 , 1 , effect_color @font . draw_markup_rel text , x , y - effect_size , z_index , rel , 0 , 1 , 1 , effect_color @font . draw_markup_rel text , x + effect_size , y - effect_size , z_index , rel , 0 , 1 , 1 , effect_color @font . draw_markup_rel text , x + effect_size , y , z_index , rel , 0 , 1 , 1 , effect_color @font . draw_markup_rel text , x + effect_size , y + effect_size , z_index , rel , 0 , 1 , 1 , effect_color @font . draw_markup_rel text , x , y + effect_size , z_index , rel , 0 , 1 , 1 , effect_color @font . draw_markup_rel text , x - effect_size , y + effect_size , z_index , rel , 0 , 1 , 1 , effect_color @font . draw_markup_rel text , x - effect_size , y , z_index , rel , 0 , 1 , 1 , effect_color elsif effect == :shadow @font . draw_markup_rel text , x + effect_size , y + effect_size , z_index , rel , 0 , 1 , 1 , effect_color end end @font . draw_markup_rel text , x , y , z_index , rel , 0 , 1 , 1 , color end

Creates a TextHelper.

 Parameters:
 [font] A Gosu::Font that will be used to draw the text.
 [line_spacing] When drawing multiple lines, the distance, in pixels,
                between each line.
 Draws a single line of text.

 Parameters:
 [text] The text to be drawn. No line breaks are allowed. You can use the
        `<b>` tag for bold, `<i>` for italic and `<c=rrggbb>` for colors.
 [x] The horizontal reference for drawing the text. If +mode+ is +:left+,
     all text will be drawn from this point to the right; if +mode+ is
     +:right+, all text will be drawn from this point to the left; and if
     +mode+ is +:center+, the text will be equally distributed to the
     left and to the right of this point.
 [y] The vertical reference for drawing the text. All text will be drawn
     from this point down.
 [mode] The alignment of the text. Valid values are +:left+, +:right+ and
        +:center+.
 [color] The color of the text, in hexadecimal RRGGBB format.
 [alpha] The opacity of the text. Valid values vary from 0 (fully
         transparent) to 255 (fully opaque).
 [effect] Effect to add to the text. It can be either +nil+, for no effect,
          +:border+ for bordered text, or +:shadow+ for shadowed text (the
          shadow is always placed below and to the right of the text).
 [effect_color] Color of the effect, if any.
 [effect_size] Size of the effect, if any. In the case of +:border+, this
               will be the width of the border (the border will only look
               good when +effect_size+ is relatively small, compared to the
               size of the font); in the case of +:shadow+, it will be the
               distance between the text and the shadow.
 [effect_alpha] Opacity of the effect, if any. For shadows, it is usual to
                provide less than 255.
 [z_index] The z-order to draw the object. Objects with larger z-orders
           will be drawn on top of the ones with smaller z-orders.

 *Obs.:* This method accepts named parameters, but +text+, +x+ and +y+ are
 mandatory.


def write_breaking(text, x, y, width, mode = :left, color = 0, alpha = 0xff, z_index = 0)
      color = (alpha << 24) | color
      text.split("\n").each do |p|
        if mode == :justified
          y = write_paragraph_justified p, x, y, width, color, z_index
        else
          rel =
            case mode
            when :left then 0
            when :center then 0.5
            when :right then 1
            else 0
            end
          y = write_paragraph p, x, y, width, rel, color, z_index
        end
      end
    end

def write_breaking ( text , x , y , width , mode = :left , color = 0 , alpha = 0xff , z_index = 0 ) color = ( alpha << 24 ) | color text . split ( "\n" ) . each do | p | if mode == :justified y = write_paragraph_justified p , x , y , width , color , z_index else rel = case mode when :left then 0 when :center then 0.5 when :right then 1 else 0 end y = write_paragraph p , x , y , width , rel , color , z_index end end end

Draws text, breaking lines when needed and when explicitly caused by the
 "\n" character.

 Parameters:
 [text] The text to be drawn. Line breaks are allowed. You can use the
        `<b>` tag for bold, `<i>` for italic and `<c=rrggbb>` for colors.
 [x] The horizontal reference for drawing the text. Works like in
     +write_line+ for the +:left+, +:right+ and +:center+ modes. For the
     +:justified+ mode, works the same as for +:left+.
 [y] The vertical reference for drawing the text. All text will be drawn
     from this point down.
 [width] The maximum width for the lines of text. Line is broken when
         this width is exceeded.
 [mode] The alignment of the text. Valid values are +:left+, +:right+,
        +:center+ and +:justified+.
 [color] The color of the text, in hexadecimal RRGGBB format.
 [alpha] The opacity of the text. Valid values vary from 0 (fully
         transparent) to 255 (fully opaque).
 [z_index] The z-order to draw the object. Objects with larger z-orders
           will be drawn on top of the ones with smaller z-orders.

Draws text breaking lines when needed and when explicitly caused by the \ n character .


def add_global(message)
      unless (slot = @entries.index { |e| e.nil? })
        # No more free slots. We have to find the least recently used one.
        slot = 0
        0.upto(15) do |i|
          if i != slot && @entries[slot].last_use > @entries[i].last_use
            slot = i
          end
        end
      end
      @entries[slot] = Entry.new(message, Time.now)

      slot
    end

def add_global ( message ) unless ( slot = @entries . index { | e | e . nil? } ) slot = 0 0 . upto ( 15 ) do | i | if i != slot && @entries [ slot ] . last_use > @entries [ i ] . last_use slot = i end end end @entries [ slot ] = Entry . new ( message , Time . now ) slot end

Add a new GlobalFitMessage to the mapper and return the local message
 number.

Add a new GlobalFitMessage to the mapper and return the local message number .


def get_local(message)
      0.upto(15) do |i|
        if (entry = @entries[i]) && entry.global_message == message
          entry.last_use = Time.now
          return i
        end
      end
      nil
    end

def get_local ( message ) 0 . upto ( 15 ) do | i | if ( entry = @entries [ i ] ) && entry . global_message == message entry . last_use = Time . now return i end end nil end

Get the local message number for a given GlobalFitMessage. If there is
 no message number, nil is returned.

Get the local message number for a given GlobalFitMessage . If there is no message number nil is returned .


def check
      last_timestamp = ts_16_offset = nil
      last_ts_16 = nil

      # The timestamp_16 is a 2 byte time stamp value that is used instead of
      # the 4 byte timestamp field for monitoring records that have
      # current_activity_type_intensity values with an activity type of 6. The
      # value seems to be in seconds, but the 0 value reference does not seem
      # to be included in the file. However, it can be approximated using the
      # surrounding timestamp values.
      @monitorings.each do |record|
        if last_ts_16 && ts_16_offset && record.timestamp_16 &&
           record.timestamp_16 < last_ts_16
          # Detect timestamp_16 wrap-arounds. timestamp_16 is a 16 bit value.
          # In case of a wrap-around we adjust the ts_16_offset accordingly.
          ts_16_offset += 2 ** 16
        end
        if ts_16_offset
          # We have already found the offset. Adjust all timestamps according
          # to 'offset + timestamp_16'
          if record.timestamp_16
            record.timestamp = ts_16_offset + record.timestamp_16
            last_ts_16 = record.timestamp_16
          end
        else
          # We are still looking for the offset.
          if record.timestamp_16 && last_timestamp
            # We have a previous timestamp and found the first record with a
            # timestamp_16 value set. We assume that the timestamp of this
            # record is one minute after the previously found timestamp.
            # That's just a guess. Who knows what the Garmin engineers were
            # thinking here?
            ts_16_offset = last_timestamp + 60 - record.timestamp_16
            record.timestamp = ts_16_offset + record.timestamp_16
            last_ts_16 = record.timestamp_16
          else
            # Just save the timestamp of the current record.
            last_timestamp = record.timestamp
          end
        end
      end
    end

def check last_timestamp = ts_16_offset = nil last_ts_16 = nil @monitorings . each do | record | if last_ts_16 && ts_16_offset && record . timestamp_16 && record . timestamp_16 < last_ts_16 ts_16_offset += 2 ** 16 end if ts_16_offset if record . timestamp_16 record . timestamp = ts_16_offset + record . timestamp_16 last_ts_16 = record . timestamp_16 end else if record . timestamp_16 && last_timestamp ts_16_offset = last_timestamp + 60 - record . timestamp_16 record . timestamp = ts_16_offset + record . timestamp_16 last_ts_16 = record . timestamp_16 else last_timestamp = record . timestamp end end end end

Create a new Monitoring_B object.
 @param field_values [Hash] A Hash that provides initial values for
        certain fields of the FitDataRecord.
 Perform some basic logical checks on the object and all references sub
 objects. Any errors will be reported via the Log object.


def create_global_definition(fit_entity)
      messages = fit_entity.developer_fit_messages
      unless (gfm = GlobalFitMessages[@native_mesg_num])
        Log.error "Developer field description references unknown global " +
          "message number #{@native_mesg_num}"
        return
      end

      if @developer_data_index >=
           fit_entity.top_level_record.developer_data_ids.size
         Log.error "Developer data index #{@developer_data_index} is too large"
         return
      end

      msg = messages[@native_mesg_num] ||
        messages.message(@native_mesg_num, gfm.name)
      unless (@fit_base_type_id & 0x7F) < FIT_TYPE_DEFS.size
        Log.error "fit_base_type_id #{@fit_base_type_id} is too large"
        return
      end
      options = {}
      options[:scale] = @scale if @scale
      options[:offset] = @offset if @offset
      options[:array] = @array if @array
      options[:unit] = @units
      msg.field(@field_definition_number,
                FIT_TYPE_DEFS[@fit_base_type_id & 0x7F][1],
                "_#{@developer_data_index}_#{@field_name}", options)
    end

Create a new FieldDescription object.
 @param field_values [Hash] Hash that provides initial values for certain
        fields.


def check(index)
      unless @device_index
        Log.fatal 'device info record must have a device_index'
      end
      if @device_index == 0
        unless @manufacturer
          Log.fatal 'device info record 0 must have a manufacturer field set'
        end
        if @manufacturer == 'garmin'
          unless @garmin_product
            Log.fatal 'device info record 0 must have a garman_product ' +
                      'field set'
          end
        else
          unless @product
            Log.fatal 'device info record 0 must have a product field set'
          end
        end
        if @serial_number.nil?
          Log.fatal 'device info record 0 must have a serial number set'
        end
      end
    end

Ensure that FitDataRecords have a deterministic sequence. Device infos
 are sorted by device_index.

Ensure that FitDataRecords have a deterministic sequence . Device infos are sorted by device_index .


def open(io)
      begin
        @@logger = Logger.new(io)
      rescue => e
        @@logger = Logger.new($stderr)
        Log.fatal "Cannot open log file: #{e.message}"
      end
    end

def
open
(
io
)
begin
@@logger
=
Logger
.
new
(
io
)
rescue
=>
e
@@logger
=
Logger
.
new
(
$stderr
)
Log
.
fatal
"Cannot open log file: #{e.message}"
end
end

Redirect all log messages to the given IO.
 @param io [IO] Output file descriptor

Redirect all log messages to the given IO .


def set_type(type)
      if @top_level_record
        Log.fatal "FIT file type has already been set to " +
                  "#{@top_level_record.class}"
      end
      case type
      when 4, 'activity'
        @top_level_record = Activity.new
        @type = 'activity'
      when 32, 'monitoring_b'
        @top_level_record = Monitoring_B.new
        @type = 'monitoring_b'
      when 44, 'metrics'
        @top_level_record = Metrics.new
        @type = 'metrics'
      else
        Log.error "Unsupported FIT file type #{type}"
        return nil
      end

      @top_level_record
    end

Create a FitFileEntity.
 Set what kind of FIT file we are dealing with.
 @return The Ruby object that will hold the content of the FIT file. It's
 a derivative of FitDataRecord.

Create a FitFileEntity . Set what kind of FIT file we are dealing with .


def check
      unless @timestamp && @timestamp >= Time.parse('1990-01-01T00:00:00+00:00')
        Log.fatal "Activity has no valid timestamp"
      end
      unless @total_timer_time
        Log.fatal "Activity has no valid total_timer_time"
      end
      unless @device_infos.length > 0
        Log.fatal "Activity must have at least one device_info section"
      end
      @device_infos.each.with_index { |d, index| d.check(index) }
      @sensor_settings.each.with_index { |s, index| s.check(index) }
      unless @num_sessions == @sessions.count
        Log.fatal "Activity record requires #{@num_sessions}, but "
                  "#{@sessions.length} session records were found in the "
                  "FIT file."
      end

      # Records must have consecutively growing timestamps and distances.
      ts = Time.parse('1989-12-31')
      distance = nil
      invalid_records = []
      @records.each_with_index do |r, idx|
        Log.fatal "Record has no timestamp" unless r.timestamp
        if r.timestamp < ts
          Log.fatal "Record has earlier timestamp than previous record"
        end
        if r.distance
          if distance && r.distance < distance
            # Normally this should be a fatal error as the FIT file is clearly
            # broken. Unfortunately, the Skiing/Boarding app in the Fenix3
            # produces such broken FIT files. So we just warn about this
            # problem and discard the earlier records.
            Log.error "Record #{r.timestamp} has smaller distance " +
                      "(#{r.distance}) than an earlier record (#{distance})."
            # Index of the list record to be discarded.
            (idx - 1).downto(0) do |i|
              if (ri = @records[i]).distance > r.distance
                # This is just an approximation. It looks like the app adds
                # records to the FIT file for runs that it meant to discard.
                # Maybe the two successive time start events are a better
                # criteria. But this workaround works for now.
                invalid_records << ri
              else
                # All broken records have been found.
                break
              end
            end
          end
          distance = r.distance
        end
        ts = r.timestamp
      end
      unless invalid_records.empty?
        # Delete all the broken records from the @records Array.
        Log.warn "Discarding #{invalid_records.length} earlier records"
        @records.delete_if { |r| invalid_records.include?(r) }
      end

      # Laps must have a consecutively growing message index.
      @laps.each.with_index do |lap, index|
        lap.check(index)
        # If we have heart rate zone records, there should be one for each
        # lap
        @heart_rate_zones[index].check(index) if @heart_rate_zones[index]
      end
      @sessions.each { |s| s.check(self) }
    end

Create a new Activity object.
 @param field_values [Hash] A Hash that provides initial values for
        certain fields of the FitDataRecord.
 Perform some basic logical checks on the object and all references sub
 objects. Any errors will be reported via the Log object.


def total_gps_distance
      timer_stops = []
      # Generate a list of all timestamps where the timer was stopped.
      @events.each do |e|
        if e.event == 'timer' && e.event_type == 'stop_all'
          timer_stops << e.timestamp
        end
      end

      # The first record of a FIT file can already have a distance associated
      # with it. The GPS location of the first record is not where the start
      # button was pressed. This introduces a slight inaccurcy when computing
      # the total distance purely on the GPS coordinates found in the records.
      d = 0.0
      last_lat = last_long = nil
      last_timestamp = nil

      # Iterate over all the records and accumlate the distances between the
      # neiboring coordinates.
      @records.each do |r|
        if (lat = r.position_lat) && (long = r.position_long)
          if last_lat && last_long
            distance = Fit4Ruby::GeoMath.distance(last_lat, last_long,
                                                  lat, long)
            d += distance
          end
          if last_timestamp
            speed = distance / (r.timestamp - last_timestamp)
          end
          if timer_stops[0] == r.timestamp
            # If a stop event was found for this record timestamp we clear the
            # last_* values so that the distance covered while being stopped
            # is not added to the total.
            last_lat = last_long = nil
            last_timestamp = nil
            timer_stops.shift
          else
            last_lat = lat
            last_long = long
            last_timestamp = r.timestamp
          end
        end
      end
      d
    end

def total_gps_distance timer_stops = [ ] @events . each do | e | if e . event == 'timer' && e . event_type == 'stop_all' timer_stops << e . timestamp end end d = 0.0 last_lat = last_long = nil last_timestamp = nil @records . each do | r | if ( lat = r . position_lat ) && ( long = r . position_long ) if last_lat && last_long distance = Fit4Ruby :: GeoMath . distance ( last_lat , last_long , lat , long ) d += distance end if last_timestamp speed = distance / ( r . timestamp - last_timestamp ) end if timer_stops [ 0 ] == r . timestamp last_lat = last_long = nil last_timestamp = nil timer_stops . shift else last_lat = lat last_long = long last_timestamp = r . timestamp end end end d end

Total distance convered by this activity purely computed by the GPS
 coordinates. This may differ from the distance computed by the device as
 it can be based on a purely calibrated footpod.

Total distance convered by this activity purely computed by the GPS coordinates . This may differ from the distance computed by the device as it can be based on a purely calibrated footpod .


def vo2max
      # First check the event log for a vo2max reporting event.
      @events.each do |e|
        return e.vo2max if e.event == 'vo2max'
      end
      # Then check the user_data entries for a metmax entry. METmax * 3.5
      # is same value as VO2max.
      @user_data.each do |u|
        return u.metmax * 3.5 if u.metmax
      end

      nil
    end

def vo2max @events . each do | e | return e . vo2max if e . event == 'vo2max' end @user_data . each do | u | return u . metmax * 3.5 if u . metmax end nil end

Returns the computed VO2max value. This value is computed by the device
 based on multiple previous activities.

Returns the computed VO2max value . This value is computed by the device based on multiple previous activities .


def write(io, id_mapper)
      @file_id.write(io, id_mapper)
      @file_creator.write(io, id_mapper)

      (@field_descriptions + @developer_data_ids +
       @device_infos + @sensor_settings +
       @data_sources + @user_profiles +
       @physiological_metrics + @events +
       @sessions + @laps + @records + @heart_rate_zones +
       @personal_records).sort.each do |s|
        s.write(io, id_mapper)
      end
      super
    end

def write ( io , id_mapper ) @file_id . write ( io , id_mapper ) @file_creator . write ( io , id_mapper ) ( @field_descriptions + @developer_data_ids + @device_infos + @sensor_settings + @data_sources + @user_profiles + @physiological_metrics + @events + @sessions + @laps + @records + @heart_rate_zones + @personal_records ) . sort . each do | s | s . write ( io , id_mapper ) end super end

Write the Activity data to a file.
 @param io [IO] File reference
 @param id_mapper [FitMessageIdMapper] Maps global FIT record types to
        local ones.


def new_fit_data_record(record_type, field_values = {})
      case record_type
      when 'file_id'
        @file_id = (record = FileId.new(field_values))
      when 'field_description'
        @field_descriptions << (record = FieldDescription.new(field_values))
      when 'developer_data_id'
        @developer_data_ids << (record = DeveloperDataId.new(field_values))
      when 'epo_data'
        @epo_data = (record = EPO_Data.new(field_values))
      when 'file_creator'
        @file_creator = (record = FileCreator.new(field_values))
      when 'device_info'
        @device_infos << (record = DeviceInfo.new(field_values))
      when 'sensor_settings'
        @sensor_settings << (record = SensorSettings.new(field_values))
      when 'data_sources'
        @data_sources << (record = DataSources.new(field_values))
      when 'user_data'
        @user_data << (record = UserData.new(field_values))
      when 'user_profile'
        @user_profiles << (record = UserProfile.new(field_values))
      when 'physiological_metrics'
        @physiological_metrics <<
          (record = PhysiologicalMetrics.new(field_values))
      when 'event'
        @events << (record = Event.new(field_values))
      when 'session'
        unless @cur_lap_records.empty?
          # Copy selected fields from section to lap.
          lap_field_values = {}
          [ :timestamp, :sport ].each do |f|
            lap_field_values[f] = field_values[f] if field_values.include?(f)
          end
          # Ensure that all previous records have been assigned to a lap.
          record = create_new_lap(lap_field_values)
        end
        @num_sessions += 1
        @sessions << (record = Session.new(@cur_session_laps, @lap_counter,
                                           field_values))
        @cur_session_laps = []
      when 'lap'
        record = create_new_lap(field_values)
      when 'record'
        @cur_lap_records << (record = Record.new(field_values))
        @records << record
      when 'hrv'
        @hrv << (record = HRV.new(field_values))
      when 'heart_rate_zones'
        @heart_rate_zones << (record = HeartRateZones.new(field_values))
      when 'personal_records'
        @personal_records << (record = PersonalRecords.new(field_values))
      else
        record = nil
      end

      record
    end

def new_fit_data_record ( record_type , field_values = { } ) case record_type when 'file_id' @file_id = ( record = FileId . new ( field_values ) ) when 'field_description' @field_descriptions << ( record = FieldDescription . new ( field_values ) ) when 'developer_data_id' @developer_data_ids << ( record = DeveloperDataId . new ( field_values ) ) when 'epo_data' @epo_data = ( record = EPO_Data . new ( field_values ) ) when 'file_creator' @file_creator = ( record = FileCreator . new ( field_values ) ) when 'device_info' @device_infos << ( record = DeviceInfo . new ( field_values ) ) when 'sensor_settings' @sensor_settings << ( record = SensorSettings . new ( field_values ) ) when 'data_sources' @data_sources << ( record = DataSources . new ( field_values ) ) when 'user_data' @user_data << ( record = UserData . new ( field_values ) ) when 'user_profile' @user_profiles << ( record = UserProfile . new ( field_values ) ) when 'physiological_metrics' @physiological_metrics << ( record = PhysiologicalMetrics . new ( field_values ) ) when 'event' @events << ( record = Event . new ( field_values ) ) when 'session' unless @cur_lap_records . empty? lap_field_values = { } [ :timestamp , :sport ] . each do | f | lap_field_values [ f ] = field_values [ f ] if field_values . include? ( f ) end record = create_new_lap ( lap_field_values ) end @num_sessions += 1 @sessions << ( record = Session . new ( @cur_session_laps , @lap_counter , field_values ) ) @cur_session_laps = [ ] when 'lap' record = create_new_lap ( field_values ) when 'record' @cur_lap_records << ( record = Record . new ( field_values ) ) @records << record when 'hrv' @hrv << ( record = HRV . new ( field_values ) ) when 'heart_rate_zones' @heart_rate_zones << ( record = HeartRateZones . new ( field_values ) ) when 'personal_records' @personal_records << ( record = PersonalRecords . new ( field_values ) ) else record = nil end record end

Check if the current Activity is equal to the passed Activity.
 @param a [Activity] Activity to compare this Activity with.
 @return [TrueClass/FalseClass] true if both Activities are equal,
 otherwise false.
 Create a new FitDataRecord.
 @param record_type [String] Type that identifies the FitDataRecord
        derived class to create.
 @param field_values [Hash] A Hash that provides initial values for
        certain fields of the FitDataRecord.
 @return FitDataRecord

Check if the current Activity is equal to the passed Activity .


def check(activity)
      unless @first_lap_index
        Log.fatal 'first_lap_index is not set'
      end
      unless @num_laps
        Log.fatal 'num_laps is not set'
      end
      @first_lap_index.upto(@first_lap_index - @num_laps) do |i|
        if (lap = activity.lap[i])
          @laps << lap
        else
          Log.fatal "Session references lap #{i} which is not contained in "
                    "the FIT file."
        end
      end
    end

Create a new Session object.
 @param laps [Array of Laps] Laps to associate with the Session.
 @param first_lap_index [Fixnum] Index of the first Lap in this Session.
 @param field_values [Hash] Hash that provides initial values for certain
        fields.
 Perform some basic consistency and logical checks on the object. Errors
 are reported via the Log object.


def field(number, type, name, opts = {})
      field = Field.new(type, name, opts)
      register_field_by_name(field, name)
      register_field_by_number(field, number)
    end

def field ( number , type , name , opts = { } ) field = Field . new ( type , name , opts ) register_field_by_name ( field , name ) register_field_by_number ( field , number ) end

Create a new GlobalFitMessage definition.
 @param name [String] name of the FIT message
 @param number [Fixnum] global message number
 Two GlobalFitMessage objects are considered equal if they have the same
 number, name and list of named fields.
 Define a new Field for this message definition.

Create a new GlobalFitMessage definition .


def alt_field(number, ref_field, &block)
      unless @fields_by_name.include?(ref_field)
        raise "Unknown ref_field: #{ref_field}"
      end

      field = AltField.new(self, ref_field, &block)
      register_field_by_number(field, number)
    end

def
alt_field
(
number
,
ref_field
,
&
block
)
unless
@fields_by_name
.
include?
(
ref_field
)
raise
"Unknown ref_field: #{ref_field}"
end
field
=
AltField
.
new
(
self
,
ref_field
,
&
block
)
register_field_by_number
(
field
,
number
)
end

Define a new set of Field alternatives for this message definition.

Define a new set of Field alternatives for this message definition .


def spam?
      self.class.mail_captcha.each do |field|
        next if send(field).blank?

        if defined?(Rails) && Rails.env.development?
          raise ScriptError, "The captcha field #{field} was supposed to be blank"
        else
          return true
        end
      end

      false
    end

In development, raises an error if the captcha field is not blank. This is
 is good to remember that the field should be hidden with CSS and shown only
 to robots.

 In test and in production, it returns true if all captcha fields are blank,
 returns false otherwise.

In development raises an error if the captcha field is not blank . This is is good to remember that the field should be hidden with CSS and shown only to robots .


def deliver!
      mailer = MailForm::Notifier.contact(self)
      if mailer.respond_to?(:deliver_now)
        mailer.deliver_now
      else
        mailer.deliver
      end
    end

def deliver! mailer = MailForm :: Notifier . contact ( self ) if mailer . respond_to? ( :deliver_now ) mailer . deliver_now else mailer . deliver end end

Deliver the resource without running any validation.

Deliver the resource without running any validation .


def mail_form_attributes
      self.class.mail_attributes.each_with_object({}) do |attr, hash|
        hash[attr.to_s] = send(attr)
      end
    end

def mail_form_attributes self . class . mail_attributes . each_with_object ( { } ) do | attr , hash | hash [ attr . to_s ] = send ( attr ) end end

Returns a hash of attributes, according to the attributes existent in
 self.class.mail_attributes.

Returns a hash of attributes according to the attributes existent in self . class . mail_attributes .


def start
      extract_and_configure
      if config.managed?
        exec('start', p: port, c: config.cloud)

        # Wait for solr to start
        unless status
          sleep config.poll_interval
        end

        after_start
      end
    end

def start extract_and_configure if config . managed? exec ( 'start' , p : port , c : config . cloud ) unless status sleep config . poll_interval end after_start end end

Start Solr and wait for it to become available


def restart
      if config.managed? && started?
        exec('restart', p: port, c: config.cloud)
      end
    end

def restart if config . managed? && started? exec ( 'restart' , p : port , c : config . cloud ) end end

Stop Solr and wait for it to finish exiting


def create(options = {})
      options[:name] ||= SecureRandom.hex

      create_options = { p: port }
      create_options[:c] = options[:name] if options[:name]
      create_options[:n] = options[:config_name] if options[:config_name]
      create_options[:d] = options[:dir] if options[:dir]

      Retriable.retriable do
        raise "Not started yet" unless started?
      end

      # short-circuit if we're using persisted data with an existing core/collection
      return if options[:persist] && create_options[:c] && client.exists?(create_options[:c])

      exec("create", create_options)

      options[:name]
    end

def
create
(
options
=
{
}
)
options
[
:name
]
||=
SecureRandom
.
hex
create_options
=
{
p
:
port
}
create_options
[
:c
]
=
options
[
:name
]
if
options
[
:name
]
create_options
[
:n
]
=
options
[
:config_name
]
if
options
[
:config_name
]
create_options
[
:d
]
=
options
[
:dir
]
if
options
[
:dir
]
Retriable
.
retriable
do
raise
"Not started yet"
unless
started?
end
return
if
options
[
:persist
]
&&
create_options
[
:c
]
&&
client
.
exists?
(
create_options
[
:c
]
)
exec
(
"create"
,
create_options
)
options
[
:name
]
end

Create a new collection in solr
 @param [Hash] options
 @option options [String] :name
 @option options [String] :dir


def upconfig(options = {})
      options[:name] ||= SecureRandom.hex
      options[:zkhost] ||= zkhost

      upconfig_options = { upconfig: true, n: options[:name] }
      upconfig_options[:d] = options[:dir] if options[:dir]
      upconfig_options[:z] = options[:zkhost] if options[:zkhost]

      exec 'zk', upconfig_options

      options[:name]
    end

def upconfig ( options = { } ) options [ :name ] ||= SecureRandom . hex options [ :zkhost ] ||= zkhost upconfig_options = { upconfig : true , n : options [ :name ] } upconfig_options [ :d ] = options [ :dir ] if options [ :dir ] upconfig_options [ :z ] = options [ :zkhost ] if options [ :zkhost ] exec 'zk' , upconfig_options options [ :name ] end

Update the collection configuration in zookeeper
 @param [Hash] options
 @option options [String] :config_name
 @option options [String] :dir


def downconfig(options = {})
      options[:name] ||= SecureRandom.hex
      options[:zkhost] ||= zkhost

      downconfig_options = { downconfig: true, n: options[:name] }
      downconfig_options[:d] = options[:dir] if options[:dir]
      downconfig_options[:z] = options[:zkhost] if options[:zkhost]

      exec 'zk', downconfig_options

      options[:name]
    end

def downconfig ( options = { } ) options [ :name ] ||= SecureRandom . hex options [ :zkhost ] ||= zkhost downconfig_options = { downconfig : true , n : options [ :name ] } downconfig_options [ :d ] = options [ :dir ] if options [ :dir ] downconfig_options [ :z ] = options [ :zkhost ] if options [ :zkhost ] exec 'zk' , downconfig_options options [ :name ] end

Copy the collection configuration from zookeeper to a local directory
 @param [Hash] options
 @option options [String] :config_name
 @option options [String] :dir


def with_collection(options = {})
      options = config.collection_options.merge(options)
      return yield if options.empty?

      name = create(options)
      begin
        yield name
      ensure
        delete name unless options[:persist]
      end
    end

def with_collection ( options = { } ) options = config . collection_options . merge ( options ) return yield if options . empty? name = create ( options ) begin yield name ensure delete name unless options [ :persist ] end end

Create a new collection, run the block, and then clean up the collection
 @param [Hash] options
 @option options [String] :name
 @option options [String] :dir

Create a new collection run the block and then clean up the collection


def clean!
      stop
      remove_instance_dir!
      FileUtils.remove_entry(config.download_dir, true) if File.exist?(config.download_dir)
      FileUtils.remove_entry(config.tmp_save_dir, true) if File.exist? config.tmp_save_dir
      checksum_validator.clean!
      FileUtils.remove_entry(config.version_file) if File.exist? config.version_file
    end

def clean! stop remove_instance_dir! FileUtils . remove_entry ( config . download_dir , true ) if File . exist? ( config . download_dir ) FileUtils . remove_entry ( config . tmp_save_dir , true ) if File . exist? config . tmp_save_dir checksum_validator . clean! FileUtils . remove_entry ( config . version_file ) if File . exist? config . version_file end

Clean up any files solr_wrapper may have downloaded


def get_signals
      all_signals = []
      current = @klass
      while current != Qt::Base
        meta = Meta[current.name]
        if !meta.nil?
          all_signals.concat meta.signals
        end
        current = current.superclass
      end
      return all_signals
    end

def get_signals all_signals = [ ] current = @klass while current != Qt :: Base meta = Meta [ current . name ] if ! meta . nil? all_signals . concat meta . signals end current = current . superclass end return all_signals end

Return a list of signals, including inherited ones

Return a list of signals including inherited ones


def +(other)
      if Duration === other
        Duration.new(value + other.value, @parts + other.parts)
      else
        Duration.new(value + other, @parts + [[:seconds, other]])
      end
    end

def + ( other ) if Duration === other Duration . new ( value + other . value , @parts + other . parts ) else Duration . new ( value + other , @parts + [ [ :seconds , other ] ] ) end end

Adds another Duration or a Numeric to this Duration. Numeric values
 are treated as seconds.

Adds another Duration or a Numeric to this Duration . Numeric values are treated as seconds .


def days_to_week_start(start_day = Date.beginning_of_week)
      start_day_number = DAYS_INTO_WEEK[start_day]
      current_day_number = wday != 0 ? wday - 1 : 6
      (current_day_number - start_day_number) % 7
    end

Returns the number of days to the start of the week on the given day.
 Week is assumed to start on +start_day+, default is
 +Date.beginning_of_week+ or +config.beginning_of_week+ when set.

Returns the number of days to the start of the week on the given day . Week is assumed to start on + start_day + default is + Date . beginning_of_week + or + config . beginning_of_week + when set .


def reset
      @width             = 0 if no_width
      @render_period     = frequency == 0 ? 0 : 1.0 / frequency
      @current           = 0
      @last_render_time  = Time.now
      @last_render_width = 0
      @done              = false
      @stopped           = false
      @start_at          = Time.now
      @started           = false
      @tokens            = {}

      @meter.clear
    end

Create progress bar

 @param [String] format
   the tokenized string that displays the output

 @param [Hash] options
 @option options [Numeric] :total
   the total number of steps to completion
 @option options [Numeric] :width
   the maximum width for the bars display including
   all formatting options
 @option options [Boolean] :no_width
   true when progression is unknown defaulting to false
 @option options [Boolean] :clear
   whether or not to clear the progress line
 @option options [Boolean] :hide_cursor
   display or hide cursor
 @option options [Object] :output
   the object that responds to print call defaulting to stderr
 @option options [Number] :frequency
   the frequency with which to display bars
 @option options [Number] :interval
   the period for sampling of speed measurement

 @api public
 Reset progress to default configuration

 @api public


def advance(progress = 1, tokens = {})
      return if done?

      synchronize do
        emit(:progress, progress)
        if progress.respond_to?(:to_hash)
          tokens, progress = progress, 1
        end
        @start_at  = Time.now if @current.zero? && !@started
        @current  += progress
        @tokens    = tokens
        @meter.sample(Time.now, progress)

        if !no_width && @current >= total
          finish && return
        end

        now = Time.now
        return if (now - @last_render_time) < @render_period
        render
      end
    end

def advance ( progress = 1 , tokens = { } ) return if done? synchronize do emit ( :progress , progress ) if progress . respond_to? ( :to_hash ) tokens , progress = progress , 1 end @start_at = Time . now if @current . zero? && ! @started @current += progress @tokens = tokens @meter . sample ( Time . now , progress ) if ! no_width && @current >= total finish && return end now = Time . now return if ( now - @last_render_time ) < @render_period render end end

Advance the progress bar

 @param [Object|Number] progress

 @api public


def iterate(collection, progress = 1, &block)
      update(total: collection.count * progress) unless total
      progress_enum = Enumerator.new do |iter|
        collection.each do |elem|
          advance(progress)
          iter.yield(elem)
        end
      end
      block_given? ? progress_enum.each(&block) : progress_enum
    end

def iterate ( collection , progress = 1 , & block ) update ( total : collection . count * progress ) unless total progress_enum = Enumerator . new do | iter | collection . each do | elem | advance ( progress ) iter . yield ( elem ) end end block_given? ? progress_enum . each ( & block ) : progress_enum end

Iterate over collection either yielding computation to block
 or provided Enumerator. If the bar's `total` was not set,
 it would be taken from `collection.count`, otherwise previously
 set `total` would be used. This allows using the progressbar
 with infinite, lazy, or slowly-calculated enumerators.

 @note
   If `total` is set, iteration will NOT stop after this number of
   iterations, only when provided Enumerable is finished. It may
   be convenient in "unsure number of iterations" situations
   (like downloading in chunks, when server may eventually send
   more chunks than predicted), but be careful to not pass infinite
   enumerators without previosly doing `.take(some_finite_number)`
   on them.

 @example
   bar.iterate(30.times) { ... }

 @param [Enumerable] collection
   the collection to iterate over

 @param [Integer] progress
   the amount to move progress bar by

 @return [Enumerator]

 @api public

Iterate over collection either yielding computation to block or provided Enumerator . If the bar s total was not set it would be taken from collection . count otherwise previously set total would be used . This allows using the progressbar with infinite lazy or slowly - calculated enumerators .


def update(options = {})
      synchronize do
        options.each do |name, val|
          if @configuration.respond_to?("#{name}=")
            @configuration.public_send("#{name}=", val)
          end
        end
      end
    end

def update ( options = { } ) synchronize do options . each do | name , val | if @configuration . respond_to? ( "#{name}=" ) @configuration . public_send ( "#{name}=" , val ) end end end end

Update configuration options for this bar

 @param [Hash[Symbol]] options
   the configuration options to update

 @api public


def render
      return if done?
      if hide_cursor && @last_render_width == 0 && !(@current >= total)
        write(TTY::Cursor.hide)
      end

      if @multibar
        characters_in = @multibar.line_inset(self)
        update(inset: self.class.display_columns(characters_in))
      end

      formatted = @formatter.decorate(self, @format)
      @tokens.each do |token, val|
        formatted = formatted.gsub(":#{token}", val)
      end

      padded = padout(formatted)

      write(padded, true)

      @last_render_time  = Time.now
      @last_render_width = self.class.display_columns(formatted)
    end

def render return if done? if hide_cursor && @last_render_width == 0 && ! ( @current >= total ) write ( TTY :: Cursor . hide ) end if @multibar characters_in = @multibar . line_inset ( self ) update ( inset : self . class . display_columns ( characters_in ) ) end formatted = @formatter . decorate ( self , @format ) @tokens . each do | token , val | formatted = formatted . gsub ( ":#{token}" , val ) end padded = padout ( formatted ) write ( padded , true ) @last_render_time = Time . now @last_render_width = self . class . display_columns ( formatted ) end

Render progress to the output

 @api private


def move_to_row
      if @multibar
        CURSOR_LOCK.synchronize do
          if @first_render
            @row = @multibar.next_row
            yield if block_given?
            output.print "\n"
            @first_render = false
          else
            lines_up = (@multibar.rows + 1) - @row
            output.print TTY::Cursor.save
            output.print TTY::Cursor.up(lines_up)
            yield if block_given?
            output.print TTY::Cursor.restore
          end
        end
      else
        yield if block_given?
      end
    end

def move_to_row if @multibar CURSOR_LOCK . synchronize do if @first_render @row = @multibar . next_row yield if block_given? output . print "\n" @first_render = false else lines_up = ( @multibar . rows + 1 ) - @row output . print TTY :: Cursor . save output . print TTY :: Cursor . up ( lines_up ) yield if block_given? output . print TTY :: Cursor . restore end end else yield if block_given? end end

Move cursor to a row of the current bar if the bar is rendered
 under a multibar. Otherwise, do not move and yield on current row.

 @api private

Move cursor to a row of the current bar if the bar is rendered under a multibar . Otherwise do not move and yield on current row .


def write(data, clear_first = false)
      return unless tty? # write only to terminal

      move_to_row do
        output.print(TTY::Cursor.column(1)) if clear_first
        characters_in = @multibar.line_inset(self) if @multibar
        output.print("#{characters_in}#{data}")
        output.flush
      end
    end

def write ( data , clear_first = false ) return unless tty? move_to_row do output . print ( TTY :: Cursor . column ( 1 ) ) if clear_first characters_in = @multibar . line_inset ( self ) if @multibar output . print ( "#{characters_in}#{data}" ) output . flush end end

Write out to the output

 @param [String] data

 @api private


def finish
      return if done?
      @current = total unless no_width
      render
      clear ? clear_line : write("\n", false)
    ensure
      @meter.clear
      @done = true

      # reenable cursor if it is turned off
      if hide_cursor && @last_render_width != 0
        write(TTY::Cursor.show, false)
      end

      emit(:done)
    end

def finish return if done? @current = total unless no_width render clear ? clear_line : write ( "\n" , false ) ensure @meter . clear @done = true if hide_cursor && @last_render_width != 0 write ( TTY :: Cursor . show , false ) end emit ( :done ) end


def stop
      # reenable cursor if it is turned off
      if hide_cursor && @last_render_width != 0
        write(TTY::Cursor.show, false)
      end
      return if done?
      render
      clear ? clear_line : write("\n", false)
    ensure
      @meter.clear
      @stopped = true
      emit(:stopped)
    end

def stop if hide_cursor && @last_render_width != 0 write ( TTY :: Cursor . show , false ) end return if done? render clear ? clear_line : write ( "\n" , false ) ensure @meter . clear @stopped = true emit ( :stopped ) end

Stop and cancel the progress at the current position

 @api public


def log(message)
      sanitized_message = message.gsub(/\r|\n/, ' ')
      if done?
        write(sanitized_message + "\n", false)
        return
      end
      sanitized_message = padout(sanitized_message)

      write(sanitized_message + "\n", true)
      render
    end

def
log
(
message
)
sanitized_message
=
message
.
gsub
(
/
\r
\n
/
,
' '
)
if
done?
write
(
sanitized_message
+
"\n"
,
false
)
return
end
sanitized_message
=
padout
(
sanitized_message
)
write
(
sanitized_message
+
"\n"
,
true
)
render
end

Log message above the current progress bar

 @param [String] message
   the message to log out

 @api public


def padout(message)
      message_length = self.class.display_columns(message)

      if @last_render_width > message_length
        remaining_width = @last_render_width - message_length
        message += ' ' * remaining_width
      end
      message
    end

def
padout
(
message
)
message_length
=
self
.
class
.
display_columns
(
message
)
if
@last_render_width
>
message_length
remaining_width
=
@last_render_width
message_length
message
+=
' '
*
remaining_width
end
message
end

Pad message out with spaces

 @api private


def lock_exclusively!(max_run_time, worker = worker_name)
      now = self.class.db_time_now
      affected_rows = if locked_by != worker
        # We don't own this job so we will update the locked_by name and the locked_at
        self.class.update_all(["locked_at = ?, locked_by = ?", now, worker], ["id = ? and (locked_at is null or locked_at < ?)", id, (now - max_run_time.to_i)])
      else
        # We already own this job, this may happen if the job queue crashes.
        # Simply resume and update the locked_at
        self.class.update_all(["locked_at = ?", now], ["id = ? and locked_by = ?", id, worker])
      end
      if affected_rows == 1
        self.locked_at    = now
        self.locked_by    = worker
        return true
      else
        return false
      end
    end

Lock this job for this worker.
 Returns true if we have the lock, false otherwise.

Lock this job for this worker . Returns true if we have the lock false otherwise .


def setup_tracery dir_path
      raise "Provided path not a directory" unless Dir.exist?(dir_path)

      @grammar = {}
      Dir.open(dir_path) do |dir|
        dir.each do |file|
          # skip our current and parent dir
          next if file =~ /^\.\.?$/

          # read the rule file into the files hash
          @grammar[file.split('.').first] =
            createGrammar(JSON.parse(File.read("#{dir_path}/#{file}")))
        end
      end

      # go ahead and makes a default mention-handler
      #  if we have a reply rule file
      unless @grammar['reply'].nil?
        on_reply { |bot|
          bot.reply_with_mentions('#default#', rules: 'reply')
        }
      end
    end

def
setup_tracery
dir_path
raise
"Provided path not a directory"
unless
Dir
.
exist?
(
dir_path
)
@grammar
=
{
}
Dir
.
open
(
dir_path
)
do
|
dir
|
dir
.
each
do
|
file
|
next
if
file
=~
/
\.
\.
/
@grammar
[
file
.
split
(
'.'
)
.
first
]
=
createGrammar
(
JSON
.
parse
(
File
.
read
(
"#{dir_path}/#{file}"
)
)
)
end
end
unless
@grammar
[
'reply'
]
.
nil?
on_reply
{
|
bot
|
bot
.
reply_with_mentions
(
'#default#'
,
rules
:
'reply'
)
}
end
end

loads all of our tracery files into our +files+ hash
 if a file is named 'default' then we load that into +grammar+

 @param dir [String] path to the directory containing the tracery rules

loads all of our tracery files into our + files + hash if a file is named default then we load that into + grammar +


def expand_and_post(text, *options)
      opts = Hash[*options]
      rules = opts.fetch(:rules, 'default')
      actually_post(@grammar[rules].flatten(text),
                    **opts.reject {|k|
                      k == :rules
                    })
    end

def expand_and_post ( text , * options ) opts = Hash [ * options ] rules = opts . fetch ( :rules , 'default' ) actually_post ( @grammar [ rules ] . flatten ( text ) , ** opts . reject { | k | k == :rules } ) end

a shortcut fuction for expanding text with tracery before posting

 @param text [String] the tracery text to expand before posting
 @param options [Hash] a hash of arguments to pass to post
 @option options rules [String] the grammar rules to load
 @option options visibility [String] visibility level
 @option options spoiler [String] text to use as content warning
 @option options reply_id [String] id of post to reply to
 @option options hide_media [Bool] should we hide media?
 @option options media [Array<String>] array of file paths


def run_interact
      @streamer.user do |update|
        if update.kind_of? Mastodon::Notification

          case update.type

          when 'mention'

            # this makes it so .content calls strip instead
            update.status.class.module_eval { alias_method :content, :strip } if @strip_html
            store_mention_data update.status
            @on_reply.call(self, update.status) unless @on_reply.nil?

          when 'reblog'
            @on_boost.call(self, update) unless @on_boost.nil?

          when 'favourite'
            @on_fave.call(self, update) unless @on_fave.nil?

          when 'follow'
            @on_follow.call(self, update) unless @on_follow.nil?

          end
        end
      end
    end

def run_interact @streamer . user do | update | if update . kind_of? Mastodon :: Notification case update . type when 'mention' update . status . class . module_eval { alias_method :content , :strip } if @strip_html store_mention_data update . status @on_reply . call ( self , update . status ) unless @on_reply . nil? when 'reblog' @on_boost . call ( self , update ) unless @on_boost . nil? when 'favourite' @on_fave . call ( self , update ) unless @on_fave . nil? when 'follow' @on_follow . call ( self , update ) unless @on_follow . nil? end end end end

Starts a loop that checks for any notifications for the authenticated
 user, running the appropriate stored proc when needed

Starts a loop that checks for any notifications for the authenticated user running the appropriate stored proc when needed


def reply(text, *options)
      options = Hash[*options]

      post("@#{@mention_data[:account].acct} #{text}",
           **@mention_data.merge(options).reject { |k|
             k == :mentions or k == :account
           })
    end

Replies to the last mention the bot recieved using the mention's
   visibility and spoiler with +text+

 Automatically includes an @ for the account that mentioned the bot.
   Does not include any other @. See +reply_with_mentions+ if you want
   to automatically include all mentions

 @param text [String] text to post as a reply
 @param options [Hash] a hash of arguments to pass to post, overrides
   duplicating settings from last mention

Replies to the last mention the bot recieved using the mention s visibility and spoiler with + text +


def run_reply
      @streamer.user do |update|
        next unless update.kind_of? Mastodon::Notification and update.type == 'mention'

        # this makes it so .content calls strip instead
        update.status.class.module_eval { alias_method :content, :strip } if @strip_html

        store_mention_data update.status

        if block_given?
          yield(self, update.status)
        else
          @on_reply.call(self, update.status)
        end
      end
    end

def run_reply @streamer . user do | update | next unless update . kind_of? Mastodon :: Notification and update . type == 'mention' update . status . class . module_eval { alias_method :content , :strip } if @strip_html store_mention_data update . status if block_given? yield ( self , update . status ) else @on_reply . call ( self , update . status ) end end end

Starts a loop that checks for mentions from the authenticated user account
 running a supplied block or, if a block is not provided, on_reply

Starts a loop that checks for mentions from the authenticated user account running a supplied block or if a block is not provided on_reply


def store_mention_data(mention)
      @mention_data = {
        reply_id: mention.id,
        visibility: mention.visibility,
        spoiler: mention.spoiler_text,
        hide_media: mention.sensitive?,
        mentions: mention.mentions,
        account: mention.account
      }
    end

def store_mention_data ( mention ) @mention_data = { reply_id : mention . id , visibility : mention . visibility , spoiler : mention . spoiler_text , hide_media : mention . sensitive? , mentions : mention . mentions , account : mention . account } end

Stores select data about a post into a hash for later use

 @param mention [Mastodon::Status] the most recent mention the bot received


def setup_streaming
      stream_uri = @client.instance()
                     .attributes['urls']['streaming_api'].gsub(/^wss?/, 'https')
      @streamer = Mastodon::Streaming::Client.new(base_url: stream_uri,
                                                  bearer_token: ENV['TOKEN'])
    end

def setup_streaming stream_uri = @client . instance ( ) . attributes [ 'urls' ] [ 'streaming_api' ] . gsub ( / / , 'https' ) @streamer = Mastodon :: Streaming :: Client . new ( base_url : stream_uri , bearer_token : ENV [ 'TOKEN' ] ) end


def parse_service_name(path)
      parts = Pathname.new(path).each_filename.to_a.reverse!
      # Find the last segment not in common segments, fall back to the last segment.
      parts.find {|seg| !COMMON_SEGMENTS[seg] } || parts.first
    end

def parse_service_name ( path ) parts = Pathname . new ( path ) . each_filename . to_a . reverse! parts . find { | seg | ! COMMON_SEGMENTS [ seg ] } || parts . first end

Parse the service name from a path. Look at the last component of the
 path, ignoring some common names.

 @param path [String] Path to parse.
 @return [String]
 @example
   attribute(:service_name, kind_of: String, default: lazy { PoiseService::Utils.parse_service_name(path) })

Parse the service name from a path . Look at the last component of the path ignoring some common names .