Class: Equalshares::FixedBudget::Loop

Inherits:
Object
  • Object
show all
Defined in:
lib/equalshares/fixed_budget.rb

Overview

One fixed-budget MES run. Generalises the shared logic of equalSharesFixedBudgetFractions/Floats over an additive satisfaction measure (see Equalshares::Satisfaction): the payment mechanics are unchanged (each project raises its full cost), while the selection criterion is effective vote count = u(c) / maxPayment, with u(c) the per-approver utility. For Cost_Sat (u = cost) this is exactly the original rule.

Ruby's Hash preserves insertion order and mirrors the JS Map semantics used for remaining (re-assigning an existing key keeps its position; delete removes it).

Defined Under Namespace

Classes: CandidateEvaluation

Instance Method Summary collapse

Constructor Details

#initialize(voter_ids, project_ids, cost, approvers, b_total, params, report_details: false, progress: nil) ⇒ Loop

Returns a new instance of Loop.



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/equalshares/fixed_budget.rb', line 85

def initialize(voter_ids, project_ids, cost, approvers, b_total, params,
               report_details: false, progress: nil)
  @project_ids = project_ids
  @cost = cost
  @approvers = approvers
  @b_total = b_total
  @params = params
  @report_details = report_details
  @progress = progress
  @sat = Satisfaction.for(params.satisfaction)
  @n = voter_ids.length

  initialize_budget(voter_ids)
  initialize_report
  initialize_remaining
end

Instance Method Details

#runObject



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/equalshares/fixed_budget.rb', line 102

def run
  winners = []
  loop do
    best, max_payment_of = select_best
    if best.empty?
      # no remaining candidates are affordable
      unless @remaining.empty?
        raise ComputeError,
              "No available candidate found even though there are still affordable candidates: " \
              "#{@remaining.keys}"
      end

      break
    end

    best = Tie.resolve_one(@project_ids, @cost, @approvers, @params, best)
    winners << best
    @progress&.call((100 * winners.sum { |c| @cost[c] } / @b_total).floor)
    charge_winner(best, max_payment_of[best])
    @remaining.delete(best)
  end

  { winners: winners, report: @report.to_h }
end