+ my @sorted;
+ my $things_update = sub {
+ foreach my $s (@surpluses, values %sorted) {
+ $s->{Total} = sum0 map { $_->{Weight} } @{ $s->{Votes } };
+ }
+ @sorted = nsort_by { -$_->{Total} } values %sorted;
+ };
+ $things_update->();
+
+ print DEBUG "SORTED\n", Dumper(\@sorted);
+
+ push @stagerecord, { map { ($_->{Cand}, $_->{Total}) } @sorted };
+
+ my $totalvalid = 0/1;
+ my $countvalid = sub {
+ my ($l, $what) = @_;
+ foreach my $s (@$l) {
+ printf "%-7s %10s %s\n", $what, $s->{Cand}, pr $s->{Total};
+ $totalvalid += $s->{Total};
+ }
+ };
+ $countvalid->(\@sorted, '1stpref');
+ $countvalid->(\@surpluses, 'surplus');
+
+ printf "%7s %10s %s\n", 'TOTAL', '-----', pr $totalvalid;
+
+ unless ($totalvalid > 0) {
+ printf "No more votes!\n";
+ last;
+ }
+
+ my $quota = $totalvalid / ($placesremain + 1);
+ printf "%7s %10s %s\n", 'quota', '', pr $quota;
+
+ my $need_to_transfer_surplus = 1;
+
+ my @newsurpluses;
+
+ # Look for people to elect.
+ # We elect as many as we can, rather than recomputing the (lower) quota
+ # (ERS rules 5.4.9)
+ for (;;) {
+ my $s = $sorted[0];
+ my $topvoters = $s->{Total};
+ my $surplus = $topvoters - $quota;
+ last unless $surplus > 0;
+
+ printf "%7s %10s ***************\n", 'ELECTED', $s->{Cand};
+ push @elected, $s->{Cand};
+
+ foreach my $vote (@{ $s->{Votes} }) {
+ votelog $vote, "elected $s->{Cand}";
+ }
+
+ $s->{Surplus} = $surplus;
+ push @newsurpluses, $s;
+ delete $sorted{ $s->{Cand} };
+ delete $continuing{ $s->{Cand} };
+
+ $things_update->();
+ }
+
+ foreach my $s (@newsurpluses) {
+ # calculate the transfer value of each surplus
+ # we do this simultaneously, but based on the number of
+ # continuing candidates (excluding all the ones elected already)
+ # ERS rule 5.3.3
+
+ my $votes = $s->{Votes};
+ my $surplus = $s->{Surplus};
+ my $transferrable =
+ sum0
+ map { $_->{Weight} }
+ grep { !!voteliveprefs $_ }
+ @$votes;
+
+ printf "%7s %10s %s\n", 'xfrable', $s->{Cand}, pr $transferrable;
+ if ($transferrable > $surplus) {
+ my $derate = $transferrable / $surplus;
+ printf "%7s %10s %s\n", 'derate', $s->{Cand}, pr $derate;
+ foreach my $vote (@{ $s->{Votes} }) {
+ votelog $vote, "part of surplus, derated ". pr $derate;
+ $vote->{Weight} /= $derate;
+ }
+ }
+ push @surpluses, $s;
+
+ $things_update->();
+ printf "%7s %10s %s\n", 'surplus', $s->{Cand}, pr $s->{Total};
+
+ $need_to_transfer_surplus = 0;
+ # before actually transferring a surplus, we will consider
+ # eliminating, and then reconsider with a lower quota