class Gamefic::Query::Base

Constants

NEST_REGEXP

Attributes

arguments[R]

Public Class Methods

new(*args) click to toggle source
# File lib/gamefic/query/base.rb, line 8
def initialize *args
  @arguments = args
end

Public Instance Methods

accept?(entity) click to toggle source

Determine whether the specified entity passes the query's arguments.

@return [Boolean]

# File lib/gamefic/query/base.rb, line 86
def accept?(entity)
  result = true
  arguments.each do |a|
    result = if a.is_a?(Symbol)
      (entity.send(a) != false)
    elsif a.is_a?(Regexp)
      !entity.to_s.match(a).nil?
    elsif a.is_a?(Module) || a.is_a?(Class)
      entity.is_a?(a)
    else
      (entity == a)
    end
    break if result == false
  end
  result
end
ambiguous?() click to toggle source

Determine whether the query allows ambiguous entity references. If false, actions that use this query will only be valid if the token passed into it resolves to a single entity. If true, actions will accept an array of matching entities instead. Queries are not ambiguous by default (ambiguous? == false).

@return [Boolean]

# File lib/gamefic/query/base.rb, line 19
def ambiguous?
  false
end
context_from(subject) click to toggle source

Subclasses should override this method with the logic required to collect all entities that exist in the query's context.

@return [Array<Object>]

# File lib/gamefic/query/base.rb, line 27
def context_from(subject)
  []
end
include?(subject, object) click to toggle source
# File lib/gamefic/query/base.rb, line 52
def include?(subject, object)
  return false unless accept?(object)
  result = context_from(subject)
  result.include?(object)
end
precision() click to toggle source

A ranking of how precise the query's arguments are.

Query precision is a factor in calculating Action#rank.

@return [Integer]

# File lib/gamefic/query/base.rb, line 63
def precision
  if @precision.nil?
    @precision = 1
    arguments.each { |a|
      if a.is_a?(Class)
        @precision += 100
      elsif a.is_a?(Gamefic::Entity)
        @precision += 1000
      end
    }
    @precision
  end
  @precision
end
Also aliased as: rank
rank()
Alias for: precision
resolve(subject, token, continued: false) click to toggle source

Get a collection of objects that exist in the subject's context and match the provided token. The result is provided as a Matches object.

@return [Gamefic::Query::Matches]

# File lib/gamefic/query/base.rb, line 35
def resolve(subject, token, continued: false)
  available = context_from(subject)
  return Matches.new([], '', token) if available.empty?
  if continued
    return Matches.execute(available, token, continued: continued)
  elsif nested?(token)
    drill = denest(available, token)
    drill.keep_if{ |e| accept?(e) }
    return Matches.new(drill, token, '') unless drill.length != 1
    return Matches.new([], '', token)
  end
  result = available.select{ |e| e.specified?(token) }
  result = available.select{ |e| e.specified?(token, fuzzy: true) } if result.empty?
  result.keep_if{ |e| accept? e }
  Matches.new(result, (result.empty? ? '' : token), (result.empty? ? token : ''))
end
signature() click to toggle source
# File lib/gamefic/query/base.rb, line 79
def signature
  "#{self.class.to_s.split('::').last.downcase}(#{simplify_arguments.join(', ')})"
end

Protected Instance Methods

subquery_accessible(entity) click to toggle source

Return an array of the entity's children. If the child is accessible, recursively append its children. The result will NOT include the original entity itself.

@return [Array<Object>]

# File lib/gamefic/query/base.rb, line 110
def subquery_accessible entity
  return [] if entity.nil?
  result = []
  if entity.accessible?
    entity.children.each do |c|
      result.push c
      result.concat subquery_accessible(c)
    end
  end
  result
end

Private Instance Methods

denest(objects, token) click to toggle source
# File lib/gamefic/query/base.rb, line 138
def denest(objects, token)
  parts = token.split(NEST_REGEXP)
  current = parts.pop
  last_result = objects.select { |e| e.specified?(current) }
  last_result = objects.select { |e| e.specified?(current, fuzzy: true) } if last_result.empty?
  until parts.empty?
    current = "#{parts.last} #{current}"
    result = last_result.select { |e| e.specified?(current) }
    result = last_result.select { |e| e.specified?(current, fuzzy: true) } if result.empty?
    break if result.empty?
    parts.pop
    last_result = result
  end
  return [] if last_result.empty? or last_result.length > 1
  return last_result if parts.empty?
  denest(last_result[0].children, parts.join(' '))
end
nested?(token) click to toggle source
# File lib/gamefic/query/base.rb, line 134
def nested?(token)
  !token.match(NEST_REGEXP).nil?
end
simplify_arguments() click to toggle source
# File lib/gamefic/query/base.rb, line 124
def simplify_arguments
  arguments.map do |a|
    if a.is_a?(Class) || a.is_a?(Object)
      a.to_s.split('::').last.downcase
    else
      a.to_s.downcase
    end
  end
end