class Batali::ScoreKeeper
Provide scores for units
Constants
- MULTIPLIERS
Score multiplier values
Public Instance Methods
preferred_score()
click to toggle source
Always prefer higher scoring units
@return [Symbol] :highscore
# File lib/batali/score_keeper.rb, line 20 def preferred_score :highscore end
score_for(unit, *args)
click to toggle source
Provide score for given unit
@param unit [Unit] unit to score @param idx [Integer] current index location @return [Numeric, NilClass]
# File lib/batali/score_keeper.rb, line 29 def score_for(unit, *args) opts = args.detect { |a| a.is_a?(Hash) } || {} multiplier = 1 manifest_unit = manifest.cookbook.detect do |m_unit| m_unit.name == unit.name end if manifest_unit # If the unit version matches the manifest version, this # should be _the_ preferred version if manifest_unit.version == unit.version multiplier = MULTIPLIERS[:preferred] elsif opts[:solver] && opts[:solver].new_world new_world_unit = opts[:solver].new_world.units.detect do |n_unit| n_unit.name == unit.name && n_unit.version == unit.version end multiplier = MULTIPLIERS[:preferred] if new_world_unit else # If the unit version satisfies within the patch segment of # the manifest version score those versions highest for upgrade if UnitRequirement.new("~> #{manifest_unit.version}").satisfied_by?(unit.version) multiplier = MULTIPLIERS[:patch] else # If the unit version satisfies within the minor or major # version segments of the manifest version, bump score # value up (with satisfaction within minor segment being # worth more than satisfaction within major segment) satisfied = UnitRequirement.new( "~> #{manifest_unit.version.segments.slice(0, 2).join(".")}" ).satisfied_by?(unit.version) pos = satisfied ? 1 : 0 multi_val = pos == 1 ? MULTIPLIERS[:minor] : MULTIPLIERS[:major] distance = (manifest_unit.version.segments[pos] - unit.version.segments[pos]) if distance > 0 distance = 1.0 / distance else distance = 0 end multiplier = multi_val + (multi_val * distance) end end else if opts[:solver] && opts[:solver].new_world new_world_unit = opts[:solver].new_world.units.detect do |n_unit| n_unit.name == unit.name && n_unit.version == unit.version end multiplier = MULTIPLIERS[:preferred] if new_world_unit end end score = [] # Generate a "value" for each segment of the version with # growing importance (major > minor > patch) unit.version.segments.reverse.each_with_index.map do |val, v_pos| if val == 0 score.push 0 else score << (2 - (1.0 / val)) * ((v_pos + 1) ** 10) end end # Sum the score for each segment to provide the score for the # version and multiply by defined multiplier to force higher # score when manifest drives desire for versions closer to # version defined within manifest score = score.inject(&:+) * multiplier debug "Score <#{unit.name}:#{unit.version}>: #{score}" score end