UNPKG

ecclesia

Version:

Framework for political and electoral simulations

124 lines (121 loc) 4.97 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/election/attribution/proportionalBase.ts var proportionalBase_exports = {}; __export(proportionalBase_exports, { boundedRankIndexMethod: () => boundedRankIndexMethod, proportionalFromDivisorFunction: () => proportionalFromDivisorFunction, proportionalFromRankIndexFunction: () => proportionalFromRankIndexFunction, rankIndexFunctionFromDivisorFunction: () => rankIndexFunctionFromDivisorFunction, stationaryDivisorFunction: () => stationaryDivisorFunction }); module.exports = __toCommonJS(proportionalBase_exports); var import_collections = require("@gouvernathor/python/collections"); // src/election/attribution/metrics.ts function defaultMetric({ votes, seats }) { const allVotes = votes.total; const allSeats = seats.total; let suum = 0; for (const party of seats.keys()) { const partyVotes = votes.get(party); const partySeats = seats.get(party); suum += Math.abs(allSeats * partyVotes / allVotes - partySeats); } return suum / seats.size; } // src/election/attribution/proportionalBase.ts function proportionalFromRankIndexFunction({ nSeats, rankIndexFunction }) { const attrib = (votes, rest = {}) => { const allVotes = votes.total; const fractions = new Map([...votes.entries()].map(([party, v]) => [party, v / allVotes])); const rankIndexValues = new Map([...fractions.entries()].map(([party, f]) => [party, rankIndexFunction(f, 0)])); const parties = [...votes.keys()].sort((a, b) => rankIndexValues.get(a) - rankIndexValues.get(b)); const seats = new import_collections.Counter(); s: for (let sn = 0; sn < nSeats; sn++) { const winner = parties.pop(); seats.increment(winner); rankIndexValues.set(winner, rankIndexFunction(fractions.get(winner), seats.get(winner))); for (let pn = 0; pn < parties.length; pn++) { if (rankIndexValues.get(parties[pn]) >= rankIndexValues.get(winner)) { parties.splice(pn, 0, winner); continue s; } } parties.push(winner); } return seats; }; attrib.nSeats = nSeats; return attrib; } function boundedRankIndexMethod({ minNSeats, maxNSeats, rankIndexFunction, metric = defaultMetric }) { const attrib = (votes, rest = {}) => { const allVotes = votes.total; const fractions = new Map([...votes.entries()].map(([party, v]) => [party, v / allVotes])); const rankIndexValues = new Map([...fractions.entries()].map(([party, f]) => [party, rankIndexFunction(f, 0)])); const parties = [...votes.keys()].sort((a, b) => rankIndexValues.get(a) - rankIndexValues.get(b)); const seats = new import_collections.Counter(); let bestSeats = seats.pos; let bestSeatsMetric = Infinity; s: for (let sn = 1; sn <= maxNSeats; sn++) { const winner = parties.pop(); seats.increment(winner); if (sn >= minNSeats) { const newMetric = metric({ votes, seats }); if (newMetric < bestSeatsMetric) { bestSeats = seats.pos; bestSeatsMetric = newMetric; } } rankIndexValues.set(winner, rankIndexFunction(fractions.get(winner), seats.get(winner))); for (let pn = 0; pn < parties.length; pn++) { if (rankIndexValues.get(parties[pn]) >= rankIndexValues.get(winner)) { parties.splice(pn, 0, winner); continue s; } } parties.push(winner); } return bestSeats; }; attrib.minNSeats = minNSeats; attrib.maxNSeats = maxNSeats; return attrib; } function stationaryDivisorFunction(r) { return (k) => k + r; } function rankIndexFunctionFromDivisorFunction(divisorFunction) { return (t, a) => t / divisorFunction(a); } function proportionalFromDivisorFunction({ nSeats, divisorFunction }) { return proportionalFromRankIndexFunction({ nSeats, rankIndexFunction: rankIndexFunctionFromDivisorFunction(divisorFunction) }); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { boundedRankIndexMethod, proportionalFromDivisorFunction, proportionalFromRankIndexFunction, rankIndexFunctionFromDivisorFunction, stationaryDivisorFunction }); //# sourceMappingURL=proportionalBase.cjs.map