@dra2020/dra-analytics 3.3.2 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/dra-analytics.js +47 -6
- package/dist/dra-analytics.js.map +1 -1
- package/dist/lib/all/rate.d.ts +1 -1
- package/dist/lib/equal/population.d.ts +1 -1
- package/dist/lib/partisan/bias.d.ts +1 -0
- package/dist/lib/rate/dra-ratings.d.ts +1 -0
- package/lib/all/rate.ts +1 -1
- package/lib/equal/population.ts +32 -2
- package/lib/partisan/bias.ts +16 -1
- package/lib/rate/dra-ratings.ts +2 -1
- package/lib/types/population.ts +0 -1
- package/package.json +9 -19
package/README.md
CHANGED
|
@@ -44,6 +44,10 @@ The analytics in DRA include metrics favored by [many scholars](./docs/attributi
|
|
|
44
44
|
|
|
45
45
|
A [command-line interface](./docs/cli.md) (CLI) was added in v3.
|
|
46
46
|
|
|
47
|
+
## Updates
|
|
48
|
+
|
|
49
|
+
- 12/18/21 -- Added multi-member district (MMD) support to makePopulationScorecard().
|
|
50
|
+
|
|
47
51
|
## Build status for master branch
|
|
48
52
|
|
|
49
53
|
[](https://circleci.com/gh/dra2020/dra-analytics)
|
package/dist/dra-analytics.js
CHANGED
|
@@ -177,7 +177,7 @@ Object.defineProperty(exports, "avgSVError", ({ enumerable: true, get: function
|
|
|
177
177
|
|
|
178
178
|
// Restrict package exports
|
|
179
179
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
180
|
-
exports.popdevThreshold = exports.isAntimajoritarian = exports.ratePartisanBias = exports.rateDistrictSplitting = exports.rateCountySplitting = exports.rateSplitting = exports.ratePolsby = exports.rateReock = exports.rateCompactness = exports.rateMinorityRepresentation = exports.rateCompetitiveness = exports.rateProportionality = exports.ratePopulationDeviation = void 0;
|
|
180
|
+
exports.popdevThreshold = exports.isAntimajoritarian = exports.normalizePartisanBias = exports.ratePartisanBias = exports.rateDistrictSplitting = exports.rateCountySplitting = exports.rateSplitting = exports.ratePolsby = exports.rateReock = exports.rateCompactness = exports.rateMinorityRepresentation = exports.rateCompetitiveness = exports.rateProportionality = exports.ratePopulationDeviation = void 0;
|
|
181
181
|
var all_1 = __webpack_require__(/*! ../rate/all */ "./lib/rate/all.ts");
|
|
182
182
|
// For DRA-specific ratings
|
|
183
183
|
Object.defineProperty(exports, "ratePopulationDeviation", ({ enumerable: true, get: function () { return all_1.ratePopulationDeviation; } }));
|
|
@@ -194,6 +194,7 @@ Object.defineProperty(exports, "rateDistrictSplitting", ({ enumerable: true, get
|
|
|
194
194
|
// rateSplittingLegacy, adjustSplittingRating, rateCountySplittingLegacy, rateDistrictSplittingLegacy,
|
|
195
195
|
// For use in DRA client UI
|
|
196
196
|
Object.defineProperty(exports, "ratePartisanBias", ({ enumerable: true, get: function () { return all_1.ratePartisanBias; } }));
|
|
197
|
+
Object.defineProperty(exports, "normalizePartisanBias", ({ enumerable: true, get: function () { return all_1.normalizePartisanBias; } }));
|
|
197
198
|
Object.defineProperty(exports, "isAntimajoritarian", ({ enumerable: true, get: function () { return all_1.isAntimajoritarian; } }));
|
|
198
199
|
Object.defineProperty(exports, "popdevThreshold", ({ enumerable: true, get: function () { return all_1.popdevThreshold; } }));
|
|
199
200
|
|
|
@@ -848,6 +849,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
848
849
|
exports.makePopulationScorecard = exports.isRoughlyEqual = exports.calcPopulationDeviation = void 0;
|
|
849
850
|
const C = __importStar(__webpack_require__(/*! ../rate/dra-config */ "./lib/rate/dra-config.ts"));
|
|
850
851
|
const U = __importStar(__webpack_require__(/*! ../utils/all */ "./lib/utils/all.ts"));
|
|
852
|
+
// MMD - This is the same for SMD & MMD. It's the calculation of min, max, and target size that differs.
|
|
851
853
|
function calcPopulationDeviation(max, min, targetSize) {
|
|
852
854
|
return (max - min) / targetSize; // Don't trim the result here!
|
|
853
855
|
}
|
|
@@ -857,10 +859,35 @@ function isRoughlyEqual(devation, bLegislative) {
|
|
|
857
859
|
return (devation <= threshold) ? true : false;
|
|
858
860
|
}
|
|
859
861
|
exports.isRoughlyEqual = isRoughlyEqual;
|
|
860
|
-
|
|
861
|
-
|
|
862
|
+
// MMD
|
|
863
|
+
// - Add optional # of reps per district.
|
|
864
|
+
// - Assume targetSize has been calculated correctly per # of reps not districts.
|
|
865
|
+
// - If it exists, handle the MMD-specific calculations.
|
|
866
|
+
function makePopulationScorecard(totPopByDistrict, targetSize, bLegislative, repsByDistrict, bLog = false) {
|
|
867
|
+
const nDistricts = totPopByDistrict.length;
|
|
868
|
+
// MMD - Validate reps per district input
|
|
869
|
+
if (repsByDistrict) {
|
|
870
|
+
if (repsByDistrict.length != nDistricts)
|
|
871
|
+
throw new Error("Mismatched #'s of districts passed to makePopulationScorecard()!");
|
|
872
|
+
if (repsByDistrict.includes(0))
|
|
873
|
+
throw new Error("Zero reps for a district passed to makePopulationScorecard()!");
|
|
874
|
+
// Assume a positive integer # of reps per district
|
|
875
|
+
}
|
|
876
|
+
// MMD - Figure out the type of districts, SMD or MMD.
|
|
877
|
+
const nReps = (repsByDistrict) ? repsByDistrict.reduce((a, b) => a + b, 0) : nDistricts;
|
|
878
|
+
const bSMD = (!repsByDistrict || (nReps == nDistricts)) ? true : false;
|
|
879
|
+
// MMD - Generalize populations for non-empty districts
|
|
880
|
+
// const nonEmptyDistricts = totPopByDistrict.filter(x => x > 0);
|
|
881
|
+
let popPerRep = U.deepCopy(totPopByDistrict);
|
|
882
|
+
if (!bSMD && repsByDistrict) {
|
|
883
|
+
for (let i = 0; i < nDistricts; i += 1) {
|
|
884
|
+
popPerRep[i] = totPopByDistrict[i] / repsByDistrict[i];
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
const nonEmptyDistricts = popPerRep.filter(x => x > 0);
|
|
862
888
|
let min = 0;
|
|
863
889
|
let max = 0;
|
|
890
|
+
// MMD - This is already generalized, because nonEmptyDistricts is generalized.
|
|
864
891
|
if (nonEmptyDistricts.length > 1) {
|
|
865
892
|
min = U.minArray(nonEmptyDistricts);
|
|
866
893
|
max = U.maxArray(nonEmptyDistricts);
|
|
@@ -1737,7 +1764,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
1737
1764
|
return result;
|
|
1738
1765
|
};
|
|
1739
1766
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1740
|
-
exports.rangeUnearnedSeats = exports.estLocalUnearnedSeats = exports.rangeDisproportionalityAlt = exports.estLocalDisproportionalityAlt = exports.rangeDisproportionality = exports.estLocalDisproportionality = exports.rangeAsymmetry = exports.estLocalAsymmetry = exports.calcGamma = exports.calcMinimalInverseResponsiveness = exports.calcBigR = exports.calcDisproportionality = exports.calcGlobalSymmetry = exports.calcLopsidedOutcomes = exports.calcDeclination = exports.radiansToDegrees = exports.isASweep = exports.keyRVpoints = exports.calcMeanMedianDifference = exports.calcEfficiencyGap = exports.invertSVPoints = exports.inferGeometricSeatsBiasPoints = exports.estGeometricSeatsBias = exports.estVotesBias = exports.estSeatBias = exports.estPartisanBias = exports.calcTurnoutBias = exports.estUnearnedSeats = exports.calcDisproportionalityFromBest = exports.estSeatShare = exports.bestSeatShare = exports.bestSeats = void 0;
|
|
1767
|
+
exports.rangeUnearnedSeats = exports.estLocalUnearnedSeats = exports.rangeDisproportionalityAlt = exports.estLocalDisproportionalityAlt = exports.rangeDisproportionality = exports.estLocalDisproportionality = exports.rangeAsymmetry = exports.estLocalAsymmetry = exports.calcGamma = exports.calcMinimalInverseResponsiveness = exports.calcBigR = exports.calcDisproportionality = exports.calcGlobalSymmetry = exports.calcLopsidedOutcomes = exports.calcDeclination = exports.radiansToDegrees = exports.isASweep = exports.keyRVpoints = exports.calcMeanMedianDifference = exports.calcEfficiencyGapPrime = exports.calcEfficiencyGap = exports.invertSVPoints = exports.inferGeometricSeatsBiasPoints = exports.estGeometricSeatsBias = exports.estVotesBias = exports.estSeatBias = exports.estPartisanBias = exports.calcTurnoutBias = exports.estUnearnedSeats = exports.calcDisproportionalityFromBest = exports.estSeatShare = exports.bestSeatShare = exports.bestSeats = void 0;
|
|
1741
1768
|
const U = __importStar(__webpack_require__(/*! ../utils/all */ "./lib/utils/all.ts"));
|
|
1742
1769
|
const C = __importStar(__webpack_require__(/*! ../rate/dra-config */ "./lib/rate/dra-config.ts"));
|
|
1743
1770
|
const method_1 = __webpack_require__(/*! ./method */ "./lib/partisan/method.ts");
|
|
@@ -1925,6 +1952,18 @@ function calcEfficiencyGap(Vf, Sf, shareType = 0 /* Democratic */) {
|
|
|
1925
1952
|
return efficiencyGap;
|
|
1926
1953
|
}
|
|
1927
1954
|
exports.calcEfficiencyGap = calcEfficiencyGap;
|
|
1955
|
+
// For illustration purposes only
|
|
1956
|
+
// Assumes Democratic vote shares
|
|
1957
|
+
// Alternate specification with winner's bonus (R) heuristic built in:
|
|
1958
|
+
// - By convention, '+' = R bias; '-' = D bias
|
|
1959
|
+
// - If 1 <= R <= 2, EG is undefined (no/acceptable bias).
|
|
1960
|
+
function calcEfficiencyGapPrime(Vf, Sf, R) {
|
|
1961
|
+
let EG = undefined;
|
|
1962
|
+
if (R && ((R > 2) || (R < 1)))
|
|
1963
|
+
EG = (2.0 * (Vf - 0.5)) - (Sf - 0.5);
|
|
1964
|
+
return EG;
|
|
1965
|
+
}
|
|
1966
|
+
exports.calcEfficiencyGapPrime = calcEfficiencyGapPrime;
|
|
1928
1967
|
// MEAN–MEDIAN DIFFERENCE
|
|
1929
1968
|
//
|
|
1930
1969
|
// From PlanScore.org: "The mean-median difference is a party’s median vote share
|
|
@@ -2044,7 +2083,7 @@ exports.calcLopsidedOutcomes = calcLopsidedOutcomes;
|
|
|
2044
2083
|
//
|
|
2045
2084
|
// * gSym is the area of asymmetry between the two curves.
|
|
2046
2085
|
// * The choice of what base to normalize it by is somewhat arbitrary.
|
|
2047
|
-
// * We actually only infer the S–V
|
|
2086
|
+
// * We actually only infer the S–V curve over the range [0.25–0.75] <<< 101 points (not 100!)
|
|
2048
2087
|
// * But dividing by 100 normalizes the area of asymmetry to the area of the SxV unit square.
|
|
2049
2088
|
function calcGlobalSymmetry(dSVpoints, rSVpoints, S50V) {
|
|
2050
2089
|
let gSym = 0.0;
|
|
@@ -2866,10 +2905,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
2866
2905
|
return result;
|
|
2867
2906
|
};
|
|
2868
2907
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2869
|
-
exports.adjustSplittingRating = exports.rateSplittingLegacy = exports.rateDistrictSplittingLegacy = exports.countySplitWorst = exports.countySplitBest = exports.rateCountySplittingLegacy = exports.rateSplitting = exports.rateDistrictSplitting = exports.rateCountySplitting = exports.bestTarget = exports.worstMultiplier = exports.minSplitting = exports.maxSplitting = exports.rateCompactness = exports.ratePolsby = exports.rateReock = exports.rateMinorityRepresentation = exports.rateCompetitiveness = exports.ratePartisanBias = exports.isAntimajoritarian = exports.adjustDeviation = exports.extraBonus = exports.rateProportionality = exports.ratePopulationDeviation = void 0;
|
|
2908
|
+
exports.adjustSplittingRating = exports.rateSplittingLegacy = exports.rateDistrictSplittingLegacy = exports.countySplitWorst = exports.countySplitBest = exports.rateCountySplittingLegacy = exports.rateSplitting = exports.rateDistrictSplitting = exports.rateCountySplitting = exports.bestTarget = exports.worstMultiplier = exports.minSplitting = exports.maxSplitting = exports.rateCompactness = exports.ratePolsby = exports.rateReock = exports.rateMinorityRepresentation = exports.rateCompetitiveness = exports.normalizePartisanBias = exports.ratePartisanBias = exports.isAntimajoritarian = exports.adjustDeviation = exports.extraBonus = exports.rateProportionality = exports.ratePopulationDeviation = void 0;
|
|
2870
2909
|
const C = __importStar(__webpack_require__(/*! ./dra-config */ "./lib/rate/dra-config.ts"));
|
|
2871
2910
|
const normalize_1 = __webpack_require__(/*! ../rate/normalize */ "./lib/rate/normalize.ts");
|
|
2872
2911
|
const method_1 = __webpack_require__(/*! ../partisan/method */ "./lib/partisan/method.ts");
|
|
2912
|
+
// MMD - This is already generalized, if deviations have been calculated based on # of reps instead of districts.
|
|
2873
2913
|
// RATE POPULATION DEVIATION
|
|
2874
2914
|
function ratePopulationDeviation(rawDeviation, bLegislative) {
|
|
2875
2915
|
const _normalizer = new normalize_1.Normalizer(rawDeviation);
|
|
@@ -2982,6 +3022,7 @@ function normalizePartisanBias(biasPct, pctAt50) {
|
|
|
2982
3022
|
const rating = 100 * Math.exp(-Math.abs(biasPct / b));
|
|
2983
3023
|
return Math.round(rating);
|
|
2984
3024
|
}
|
|
3025
|
+
exports.normalizePartisanBias = normalizePartisanBias;
|
|
2985
3026
|
// RATE COMPETITIVENESS
|
|
2986
3027
|
// Normalize overall competitiveness - Raw values are in the range [0.0–1.0].
|
|
2987
3028
|
// But the practical max is more like 3/4's, so unitize that range to [0.0–1.0].
|