@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/dist/lib/all/rate.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ratePopulationDeviation, rateProportionality, rateCompetitiveness, rateMinorityRepresentation, rateCompactness, rateReock, ratePolsby, rateSplitting, rateCountySplitting, rateDistrictSplitting, ratePartisanBias, isAntimajoritarian, popdevThreshold } from '../rate/all';
|
|
1
|
+
export { ratePopulationDeviation, rateProportionality, rateCompetitiveness, rateMinorityRepresentation, rateCompactness, rateReock, ratePolsby, rateSplitting, rateCountySplitting, rateDistrictSplitting, ratePartisanBias, normalizePartisanBias, isAntimajoritarian, popdevThreshold } from '../rate/all';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { PopulationScorecard } from '../types/all';
|
|
2
2
|
export declare function calcPopulationDeviation(max: number, min: number, targetSize: number): number;
|
|
3
3
|
export declare function isRoughlyEqual(devation: number, bLegislative: boolean): boolean;
|
|
4
|
-
export declare function makePopulationScorecard(totPopByDistrict: number[], targetSize: number, bLegislative: boolean, bLog?: boolean): PopulationScorecard;
|
|
4
|
+
export declare function makePopulationScorecard(totPopByDistrict: number[], targetSize: number, bLegislative: boolean, repsByDistrict?: number[], bLog?: boolean): PopulationScorecard;
|
|
@@ -12,6 +12,7 @@ export declare function estGeometricSeatsBias(Vf: number, dSVpoints: T.SVpoint[]
|
|
|
12
12
|
export declare function inferGeometricSeatsBiasPoints(dSVpoints: T.SVpoint[], rSVpoints: T.SVpoint[]): T.SVpoint[];
|
|
13
13
|
export declare function invertSVPoints(inferredSVpoints: T.SVpoint[]): T.SVpoint[];
|
|
14
14
|
export declare function calcEfficiencyGap(Vf: number, Sf: number, shareType?: T.Party): number;
|
|
15
|
+
export declare function calcEfficiencyGapPrime(Vf: number, Sf: number, R: number | undefined): number | undefined;
|
|
15
16
|
export declare function calcMeanMedianDifference(VfArray: T.VfArray, Vf?: number): number;
|
|
16
17
|
export declare function keyRVpoints(VfArray: T.VfArray): T.rVpoints;
|
|
17
18
|
export declare function isASweep(Sf: number, nDistricts: number): boolean;
|
|
@@ -4,6 +4,7 @@ export declare function extraBonus(Vf: number): number;
|
|
|
4
4
|
export declare function adjustDeviation(Vf: number, disproportionality: number, extra: number): number;
|
|
5
5
|
export declare function isAntimajoritarian(Vf: number, Sf: number): boolean;
|
|
6
6
|
export declare function ratePartisanBias(rawSeatsBias: number, rawVotesBias: number): number;
|
|
7
|
+
export declare function normalizePartisanBias(biasPct: number, pctAt50: number): number;
|
|
7
8
|
export declare function rateCompetitiveness(rawCdf: number): number;
|
|
8
9
|
export declare function rateMinorityRepresentation(rawOd: number, pOd: number, rawCd: number, pCd: number): number;
|
|
9
10
|
export declare function rateReock(rawValue: number): number;
|
package/lib/all/rate.ts
CHANGED
package/lib/equal/population.ts
CHANGED
|
@@ -9,6 +9,7 @@ import * as T from '../types/all';
|
|
|
9
9
|
import * as U from '../utils/all';
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
// MMD - This is the same for SMD & MMD. It's the calculation of min, max, and target size that differs.
|
|
12
13
|
export function calcPopulationDeviation(max: number, min: number, targetSize: number): number
|
|
13
14
|
{
|
|
14
15
|
return (max - min) / targetSize; // Don't trim the result here!
|
|
@@ -21,13 +22,42 @@ export function isRoughlyEqual(devation: number, bLegislative: boolean): boolean
|
|
|
21
22
|
return (devation <= threshold) ? true : false;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
// MMD
|
|
26
|
+
// - Add optional # of reps per district.
|
|
27
|
+
// - Assume targetSize has been calculated correctly per # of reps not districts.
|
|
28
|
+
// - If it exists, handle the MMD-specific calculations.
|
|
29
|
+
export function makePopulationScorecard(totPopByDistrict: number[], targetSize: number, bLegislative: boolean, repsByDistrict?: number[], bLog: boolean = false): PopulationScorecard
|
|
25
30
|
{
|
|
26
|
-
const
|
|
31
|
+
const nDistricts = totPopByDistrict.length;
|
|
32
|
+
|
|
33
|
+
// MMD - Validate reps per district input
|
|
34
|
+
if (repsByDistrict)
|
|
35
|
+
{
|
|
36
|
+
if (repsByDistrict.length != nDistricts) throw new Error("Mismatched #'s of districts passed to makePopulationScorecard()!");
|
|
37
|
+
if (repsByDistrict.includes(0)) throw new Error("Zero reps for a district passed to makePopulationScorecard()!");
|
|
38
|
+
// Assume a positive integer # of reps per district
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// MMD - Figure out the type of districts, SMD or MMD.
|
|
42
|
+
const nReps = (repsByDistrict) ? repsByDistrict.reduce((a, b) => a + b, 0) : nDistricts;
|
|
43
|
+
const bSMD = (!repsByDistrict || (nReps == nDistricts)) ? true : false;
|
|
44
|
+
|
|
45
|
+
// MMD - Generalize populations for non-empty districts to be per rep.
|
|
46
|
+
// const nonEmptyDistricts = totPopByDistrict.filter(x => x > 0);
|
|
47
|
+
let popPerRep: number[] = U.deepCopy(totPopByDistrict);
|
|
48
|
+
if (!bSMD && repsByDistrict)
|
|
49
|
+
{
|
|
50
|
+
for (let i = 0; i < nDistricts; i += 1)
|
|
51
|
+
{
|
|
52
|
+
popPerRep[i] = totPopByDistrict[i] / repsByDistrict[i];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const nonEmptyDistricts = popPerRep.filter(x => x > 0);
|
|
27
56
|
|
|
28
57
|
let min = 0;
|
|
29
58
|
let max = 0;
|
|
30
59
|
|
|
60
|
+
// MMD - This is already generalized, because nonEmptyDistricts is generalized.
|
|
31
61
|
if (nonEmptyDistricts.length > 1)
|
|
32
62
|
{
|
|
33
63
|
min = U.minArray(nonEmptyDistricts);
|
package/lib/partisan/bias.ts
CHANGED
|
@@ -262,6 +262,21 @@ export function calcEfficiencyGap(Vf: number, Sf: number, shareType = T.Party.De
|
|
|
262
262
|
return efficiencyGap;
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
+
// For illustration purposes only
|
|
266
|
+
// Assumes Democratic vote shares
|
|
267
|
+
// Alternate specification with winner's bonus (R) heuristic built in:
|
|
268
|
+
// - By convention, '+' = R bias; '-' = D bias
|
|
269
|
+
// - If 1 <= R <= 2, EG is undefined (no/acceptable bias).
|
|
270
|
+
export function calcEfficiencyGapPrime(Vf: number, Sf: number, R: number | undefined): number | undefined
|
|
271
|
+
{
|
|
272
|
+
let EG = undefined;
|
|
273
|
+
|
|
274
|
+
if (R && ((R > 2) || (R < 1)))
|
|
275
|
+
EG = (2.0 * (Vf - 0.5)) - (Sf - 0.5);
|
|
276
|
+
|
|
277
|
+
return EG;
|
|
278
|
+
}
|
|
279
|
+
|
|
265
280
|
// MEAN–MEDIAN DIFFERENCE
|
|
266
281
|
//
|
|
267
282
|
// From PlanScore.org: "The mean-median difference is a party’s median vote share
|
|
@@ -409,7 +424,7 @@ export function calcLopsidedOutcomes(VfArray: T.VfArray): number | undefined
|
|
|
409
424
|
//
|
|
410
425
|
// * gSym is the area of asymmetry between the two curves.
|
|
411
426
|
// * The choice of what base to normalize it by is somewhat arbitrary.
|
|
412
|
-
// * We actually only infer the S–V
|
|
427
|
+
// * We actually only infer the S–V curve over the range [0.25–0.75] <<< 101 points (not 100!)
|
|
413
428
|
// * But dividing by 100 normalizes the area of asymmetry to the area of the SxV unit square.
|
|
414
429
|
export function calcGlobalSymmetry(dSVpoints: T.SVpoint[], rSVpoints: T.SVpoint[], S50V: number): number
|
|
415
430
|
{
|
package/lib/rate/dra-ratings.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {avgSVError} from '../partisan/method';
|
|
|
8
8
|
import * as T from '../types/all'
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
// MMD - This is already generalized, if deviations have been calculated based on # of reps instead of districts.
|
|
11
12
|
// RATE POPULATION DEVIATION
|
|
12
13
|
|
|
13
14
|
export function ratePopulationDeviation(rawDeviation: number, bLegislative: boolean): number
|
|
@@ -146,7 +147,7 @@ export function ratePartisanBias(rawSeatsBias: number, rawVotesBias: number): nu
|
|
|
146
147
|
}
|
|
147
148
|
|
|
148
149
|
// NOTE - John Nagle specified this function vs. simple linear normalization
|
|
149
|
-
function normalizePartisanBias(biasPct: number, pctAt50: number): number
|
|
150
|
+
export function normalizePartisanBias(biasPct: number, pctAt50: number): number
|
|
150
151
|
{
|
|
151
152
|
const b: number = pctAt50 / Math.log(1 / 2);
|
|
152
153
|
const rating: number = 100 * Math.exp(-Math.abs(biasPct / b));
|
package/lib/types/population.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dra2020/dra-analytics",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "DRA analytics",
|
|
5
5
|
"main": "dist/dra-analytics.js",
|
|
6
6
|
"types": "./dist/lib/all/all.d.ts",
|
|
@@ -30,40 +30,30 @@
|
|
|
30
30
|
"bugs": {
|
|
31
31
|
"url": "https://github.com/dra2020/dra-analytics/issues"
|
|
32
32
|
},
|
|
33
|
-
"jest": {
|
|
34
|
-
"moduleFileExtensions": [
|
|
35
|
-
"js",
|
|
36
|
-
"jsx"
|
|
37
|
-
],
|
|
38
|
-
"moduleDirectories": [
|
|
39
|
-
"node_modules",
|
|
40
|
-
"shared"
|
|
41
|
-
]
|
|
42
|
-
},
|
|
43
33
|
"homepage": "https://github.com/dra2020/dra-analytics#readme",
|
|
44
34
|
"devDependencies": {
|
|
45
35
|
"@types/geojson": "^7946.0.8",
|
|
46
|
-
"@types/jest": "^27.0.
|
|
36
|
+
"@types/jest": "^27.0.3",
|
|
47
37
|
"@types/node": "^12.20.20",
|
|
48
38
|
"@types/yargs": "^16.0.4",
|
|
49
39
|
"csv-parse": "^4.16.0",
|
|
50
|
-
"jest": "^27.
|
|
40
|
+
"jest": "^27.4.3",
|
|
51
41
|
"json-loader": "^0.5.7",
|
|
52
42
|
"prettier": "^2.3.2",
|
|
53
43
|
"shapefile": "^0.6.6",
|
|
54
44
|
"source-map-loader": "^3.0.0",
|
|
55
|
-
"ts-jest": "^27.
|
|
56
|
-
"ts-loader": "^9.2.
|
|
45
|
+
"ts-jest": "^27.1.1",
|
|
46
|
+
"ts-loader": "^9.2.6",
|
|
57
47
|
"tsify": "^5.0.4",
|
|
58
48
|
"tslint": "^6.1.3",
|
|
59
49
|
"tslint-config-prettier": "^1.18.0",
|
|
60
|
-
"typescript": "^4.
|
|
61
|
-
"webpack": "^5.
|
|
62
|
-
"webpack-cli": "^4.
|
|
50
|
+
"typescript": "^4.5.2",
|
|
51
|
+
"webpack": "^5.65.0",
|
|
52
|
+
"webpack-cli": "^4.9.1",
|
|
63
53
|
"yargs": "^17.1.1"
|
|
64
54
|
},
|
|
65
55
|
"dependencies": {
|
|
66
|
-
"@dra2020/baseclient": "^1.0.
|
|
56
|
+
"@dra2020/baseclient": "^1.0.67",
|
|
67
57
|
"geojson": "^0.5.0"
|
|
68
58
|
}
|
|
69
59
|
}
|