Module: Equalshares::Tie
- Defined in:
- lib/equalshares/tie_breaking.rb
Overview
Tie-breaking facade. Composes the TieBreaker strategies named in params.tie_breaking to either resolve a single tie (break_ties) or build a total order (total_order).
Class Method Summary collapse
-
.break_ties(_project_ids, cost, approvers, params, choices) ⇒ Object
Resolve a tie among
choicesby applying each tie-breaking strategy in priority order, narrowing the set. -
.resolve_one(project_ids, cost, approvers, params, choices) ⇒ Object
Resolve a tie down to a single winner, raising if the tie-breaking rules leave more than one candidate.
-
.total_order(project_ids, cost, approvers, params) ⇒ Object
A total order of all projects induced by params.tie_breaking, used by rules that need a full ordering (e.g. greedy welfare).
Class Method Details
.break_ties(_project_ids, cost, approvers, params, choices) ⇒ Object
Resolve a tie among choices by applying each tie-breaking strategy in priority
order, narrowing the set. Returns the surviving candidates (callers treat more
than one as an unresolved tie).
12 13 14 15 16 17 18 19 20 21 |
# File 'lib/equalshares/tie_breaking.rb', line 12 def break_ties(_project_ids, cost, approvers, params, choices) ctx = TieBreaker::Context.new(cost, approvers) remaining = params.tie_breaking.reduce(choices.dup) do |current, method| TieBreaker.for(method).filter(current, ctx) end raise ComputeError, "Tie-breaking failed in a way that should not happen: #{choices}" if remaining.empty? remaining end |
.resolve_one(project_ids, cost, approvers, params, choices) ⇒ Object
Resolve a tie down to a single winner, raising if the tie-breaking rules leave more than one candidate. Used by the sequential rules.
25 26 27 28 29 30 31 32 33 |
# File 'lib/equalshares/tie_breaking.rb', line 25 def resolve_one(project_ids, cost, approvers, params, choices) resolved = break_ties(project_ids, cost, approvers, params, choices) if resolved.length > 1 raise ComputeError, "Tie-breaking failed: tie between projects #{resolved.join(', ')} could not be resolved. " \ "Another tie-breaking needs to be added." end resolved[0] end |
.total_order(project_ids, cost, approvers, params) ⇒ Object
A total order of all projects induced by params.tie_breaking, used by rules that need a full ordering (e.g. greedy welfare). Projects are sorted by each strategy's sort key in priority order, falling back to their original (JS Object.keys) order.
38 39 40 41 42 43 44 45 46 |
# File 'lib/equalshares/tie_breaking.rb', line 38 def total_order(project_ids, cost, approvers, params) ctx = TieBreaker::Context.new(cost, approvers) strategies = params.tie_breaking.map { |method| TieBreaker.for(method) } base_index = project_ids.each_with_index.to_h project_ids.sort_by do |c| strategies.map { |strategy| strategy.sort_key(c, ctx) } + [base_index[c]] end end |