@dra2020/district-analytics 6.1.0 → 6.2.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/dist/cli.js +152 -77
- package/dist/cli.js.map +1 -1
- package/dist/district-analytics.js +11 -0
- package/dist/district-analytics.js.map +1 -1
- package/dist/src/_api.d.ts +1 -0
- package/dist/src/types.d.ts +7 -0
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -89102,7 +89102,7 @@ exports.scorePolsbyPopper = scorePolsbyPopper;
|
|
|
89102
89102
|
/*! exports provided: partisan, minority, traditionalPrinciples, default */
|
|
89103
89103
|
/***/ (function(module) {
|
|
89104
89104
|
|
|
89105
|
-
module.exports = JSON.parse("{\"partisan\":{\"bias\":{\"range\":[0,0.2],\"weight\":[50,80]},\"impact\":{\"weight\":[50,0],\"threshold\":4},\"competitiveness\":{\"
|
|
89105
|
+
module.exports = JSON.parse("{\"partisan\":{\"bias\":{\"range\":[0,0.2],\"weight\":[50,80]},\"impact\":{\"weight\":[50,0],\"threshold\":4},\"competitiveness\":{\"range\":[0,0.75],\"distribution\":[0.25,0.75],\"simpleRange\":[0.45,0.55],\"weight\":[0,20]},\"bonus\":2,\"weight\":[100,80]},\"minority\":{\"range\":[0.37,0.5],\"distribution\":[0.25,0.75],\"shift\":0.15,\"coalition\":{\"weight\":0.5},\"bonus\":20},\"traditionalPrinciples\":{\"compactness\":{\"reock\":{\"range\":[0.25,0.5],\"weight\":50},\"polsby\":{\"range\":[0.1,0.5],\"weight\":50},\"weight\":[0,50]},\"splitting\":{\"county\":{\"range\":[[1.26,1.68],[1.09,1.45]],\"weight\":50},\"district\":{\"range\":[[1.26,1.68],[1.09,1.45]],\"weight\":50},\"weight\":[0,50]},\"popdev\":{\"range\":[[0.0075,0.002],[0.1,-1]],\"weight\":[0,0]},\"weight\":[0,20]}}");
|
|
89106
89106
|
|
|
89107
89107
|
/***/ }),
|
|
89108
89108
|
|
|
@@ -89160,8 +89160,9 @@ function competitivenessWeight(context, overridesJSON) {
|
|
|
89160
89160
|
return cW;
|
|
89161
89161
|
}
|
|
89162
89162
|
exports.competitivenessWeight = competitivenessWeight;
|
|
89163
|
+
// COMPETITIVENESS - The simple user-facing range, i.e., 45–55%.
|
|
89163
89164
|
function competitiveRange(overridesJSON) {
|
|
89164
|
-
const range = config_json_1.default.partisan.competitiveness.
|
|
89165
|
+
const range = config_json_1.default.partisan.competitiveness.simpleRange;
|
|
89165
89166
|
return range;
|
|
89166
89167
|
}
|
|
89167
89168
|
exports.competitiveRange = competitiveRange;
|
|
@@ -89170,26 +89171,29 @@ function competitiveDistribution(overridesJSON) {
|
|
|
89170
89171
|
return dist;
|
|
89171
89172
|
}
|
|
89172
89173
|
exports.competitiveDistribution = competitiveDistribution;
|
|
89174
|
+
// COMPETITIVENESS - The more complex internal range for normalizing Cdf.
|
|
89175
|
+
// COMPETITIVENESS - 06/23/2020 - As part of relaxing the competitive range, I
|
|
89176
|
+
// I changed this max from 0.67 to 0.75.
|
|
89173
89177
|
function overallCompetitivenessRange(overridesJSON) {
|
|
89174
|
-
const range = config_json_1.default.partisan.competitiveness.
|
|
89178
|
+
const range = config_json_1.default.partisan.competitiveness.range;
|
|
89175
89179
|
return range;
|
|
89176
89180
|
}
|
|
89177
89181
|
exports.overallCompetitivenessRange = overallCompetitivenessRange;
|
|
89178
|
-
function marginalCompetitivenessRange(overridesJSON)
|
|
89179
|
-
|
|
89180
|
-
|
|
89181
|
-
|
|
89182
|
-
|
|
89183
|
-
function marginalCompetitivenessWeight(overridesJSON)
|
|
89184
|
-
|
|
89185
|
-
|
|
89186
|
-
|
|
89187
|
-
|
|
89188
|
-
function overallCompetitivenessWeight(overridesJSON)
|
|
89189
|
-
|
|
89190
|
-
|
|
89191
|
-
|
|
89192
|
-
|
|
89182
|
+
// export function marginalCompetitivenessRange(overridesJSON?: any): number[]
|
|
89183
|
+
// {
|
|
89184
|
+
// const range = config.partisan.competitiveness.marginal.range;
|
|
89185
|
+
// return range;
|
|
89186
|
+
// }
|
|
89187
|
+
// export function marginalCompetitivenessWeight(overridesJSON?: any): number
|
|
89188
|
+
// {
|
|
89189
|
+
// const mcW = config.partisan.competitiveness.marginal.weight;
|
|
89190
|
+
// return mcW;
|
|
89191
|
+
// }
|
|
89192
|
+
// export function overallCompetitivenessWeight(overridesJSON?: any): number
|
|
89193
|
+
// {
|
|
89194
|
+
// const ocW = config.partisan.competitiveness.overall.weight;
|
|
89195
|
+
// return ocW;
|
|
89196
|
+
// }
|
|
89193
89197
|
// MINORITY
|
|
89194
89198
|
function minorityOpportunityRange(overridesJSON) {
|
|
89195
89199
|
const range = config_json_1.default.minority.range;
|
|
@@ -89396,6 +89400,8 @@ function __export(m) {
|
|
|
89396
89400
|
}
|
|
89397
89401
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
89398
89402
|
__export(__webpack_require__(/*! ./_api */ "./src/_api.ts"));
|
|
89403
|
+
var partisan_1 = __webpack_require__(/*! ./partisan */ "./src/partisan.ts");
|
|
89404
|
+
exports.estSeatProbability = partisan_1.estSeatProbability;
|
|
89399
89405
|
|
|
89400
89406
|
|
|
89401
89407
|
/***/ }),
|
|
@@ -89431,39 +89437,59 @@ function evalMinorityOpportunity(p, bLog = false) {
|
|
|
89431
89437
|
const RWins = VfArray.filter(x => x <= 0.5); // Ties credited to R's
|
|
89432
89438
|
const averageDVf = (DWins.length > 0) ? U.avgArray(DWins) : undefined;
|
|
89433
89439
|
const averageRVf = (RWins.length > 0) ? U.avgArray(RWins) : undefined;
|
|
89434
|
-
// Determine proportional minority districts by demographic (ignore 'White')
|
|
89435
|
-
const districtsByDemo = calcDistrictsByDemo(p.demographicProfile.stateMfArray.slice(1), p.nDistricts);
|
|
89436
89440
|
// Initialize arrays for results
|
|
89437
89441
|
const offset = 1; // Don't process 'White'
|
|
89438
89442
|
const nDemos = 6 /* Native */ + 1 - offset; // Ditto
|
|
89439
|
-
const nBuckets = 2; // 37–50% and > 50%
|
|
89440
89443
|
const demosByDistrict = p.demographicProfile.mfArrayByDistrict;
|
|
89441
89444
|
// Initialize the demographic buckets
|
|
89442
|
-
|
|
89445
|
+
// COMPETITIVENESS - 06/23/2020 - And populate the statewide values.
|
|
89446
|
+
// Get the statewide minority VAP/CVAP % (ignore 'White')
|
|
89447
|
+
const vapPctArray = p.demographicProfile.stateMfArray.slice(1);
|
|
89448
|
+
// Determine proportional minority districts by demographic (ignoring'White')
|
|
89449
|
+
const districtsByDemo = calcDistrictsByDemo(vapPctArray, p.nDistricts);
|
|
89450
|
+
let bucketsByDemo = new Array(nDemos + 1); // Add a row for the 'Total' row
|
|
89451
|
+
let totalProportional = 0;
|
|
89443
89452
|
for (let j = 0; j < nDemos; j++) {
|
|
89444
|
-
|
|
89445
|
-
|
|
89446
|
-
|
|
89453
|
+
const vapPct = vapPctArray[j];
|
|
89454
|
+
const prop = districtsByDemo[j];
|
|
89455
|
+
// Accumulate the proportional values for each demographic, ignoring the first
|
|
89456
|
+
// all Minority demographic.
|
|
89457
|
+
if (j > 0)
|
|
89458
|
+
totalProportional += prop;
|
|
89459
|
+
bucketsByDemo[j] = [0, 0, 0, vapPct, prop]; // Five conceptual columns for each demographic
|
|
89460
|
+
}
|
|
89461
|
+
// Add a 'Total' row
|
|
89462
|
+
bucketsByDemo[nDemos] = [0, 0, 0, 0, totalProportional];
|
|
89463
|
+
let opptyByDemo = U.initArray(nDemos, 0.0); // A state-level value
|
|
89447
89464
|
// For each district
|
|
89448
89465
|
for (let i = 0; i < p.nDistricts; i++) {
|
|
89449
89466
|
// Find the opportunities for minority representation
|
|
89450
89467
|
for (let j = 0; j < nDemos; j++) {
|
|
89451
89468
|
const proportion = U.deepCopy(demosByDistrict[i][j + offset]); // Skip the 'White' entries
|
|
89452
89469
|
if (exceedsMinimumThreshold(proportion)) {
|
|
89453
|
-
// Bucket opportunity districts
|
|
89470
|
+
// Bucket opportunity districts for each demographic
|
|
89454
89471
|
const bucket = (exceedsMaximumThreshold(proportion)) ? 1 : 0;
|
|
89455
89472
|
bucketsByDemo[j][bucket] += 1;
|
|
89473
|
+
bucketsByDemo[j][2 /* Total */] += 1;
|
|
89456
89474
|
// Accumulate seat probabilities
|
|
89457
89475
|
opptyByDemo[j] += estMinorityOpportunity(proportion);
|
|
89476
|
+
// Also accumulate the 'Total' row summing the opportunities for each demographic,
|
|
89477
|
+
// ignoring the first all Minority demographic.
|
|
89478
|
+
if (j > 0) {
|
|
89479
|
+
bucketsByDemo[nDemos][bucket] += 1;
|
|
89480
|
+
bucketsByDemo[nDemos][2 /* Total */] += 1;
|
|
89481
|
+
}
|
|
89458
89482
|
}
|
|
89459
89483
|
}
|
|
89460
89484
|
}
|
|
89461
89485
|
// The # of opportunity districts for each separate demographic and all minorities
|
|
89462
89486
|
const oD = U.sumArray(opptyByDemo.slice(1)); // Sum individual demos, skipping all minorities
|
|
89463
|
-
const cD = opptyByDemo[
|
|
89487
|
+
const cD = opptyByDemo[1 /* Minority */ - offset]; // All minorities
|
|
89464
89488
|
// The # of proportional districts for each separate demographic and all minorities
|
|
89465
|
-
const pOd =
|
|
89466
|
-
const pCd =
|
|
89489
|
+
const pOd = bucketsByDemo[7 /* Total */ - 1][4 /* PropSeats */];
|
|
89490
|
+
const pCd = bucketsByDemo[1 /* Minority */ - 1][4 /* PropSeats */];
|
|
89491
|
+
// const pOd: number = U.sumArray(districtsByDemo.slice(1)); // Sum individual demos, skipping all minorities
|
|
89492
|
+
// const pCd: number = districtsByDemo[0]; // All minorities
|
|
89467
89493
|
// Score opportunity
|
|
89468
89494
|
const score = scoreMinority(oD, pOd, cD, pCd);
|
|
89469
89495
|
let mS = {
|
|
@@ -89472,9 +89498,9 @@ function evalMinorityOpportunity(p, bLog = false) {
|
|
|
89472
89498
|
averageRVf: averageRVf,
|
|
89473
89499
|
bucketsByDemographic: bucketsByDemo
|
|
89474
89500
|
},
|
|
89475
|
-
proportionalOpportunities: pOd,
|
|
89501
|
+
// proportionalOpportunities: pOd,
|
|
89476
89502
|
opportunityDistricts: oD,
|
|
89477
|
-
proportionalCoalitions: pCd,
|
|
89503
|
+
// proportionalCoalitions: pCd,
|
|
89478
89504
|
coalitionDistricts: cD,
|
|
89479
89505
|
score: score,
|
|
89480
89506
|
details: {}
|
|
@@ -89730,6 +89756,7 @@ function scorePartisan(Vf, VfArray, options) {
|
|
|
89730
89756
|
const bestS = bestSeats(N, Vf);
|
|
89731
89757
|
const bestSf = bestSeatShare(bestS, N);
|
|
89732
89758
|
const fptpS = bAlternateMetrics ? estFPTPSeats(VfArray) : undefined;
|
|
89759
|
+
// NOTE - When not constrained, use the full probability distribution to calc metrics.
|
|
89733
89760
|
const range = bConstrained ? C.competitiveDistribution() : undefined;
|
|
89734
89761
|
const estS = estSeats(VfArray, range);
|
|
89735
89762
|
const estSf = estSeatShare(estS, N);
|
|
@@ -89763,13 +89790,17 @@ function scorePartisan(Vf, VfArray, options) {
|
|
|
89763
89790
|
const rDf = bAlternateMetrics ? estResponsiveDistrictsShare(rD, N) : undefined;
|
|
89764
89791
|
const gamma = (bAlternateMetrics && littleR) ? calcGamma(Vf, estSf, littleR) : undefined;
|
|
89765
89792
|
const Cn = countCompetitiveDistricts(VfArray);
|
|
89766
|
-
|
|
89793
|
+
// NOTE - Cd by definition uses a *possibly* different (more narrow) probability
|
|
89794
|
+
// distribution than Rd.
|
|
89795
|
+
const cD = estCompetitiveDistricts(VfArray);
|
|
89767
89796
|
// const cD = bConstrained ? estCompetitiveDistricts(VfArray) : rD as number;
|
|
89768
89797
|
const cDf = estCompetitiveDistrictsShare(cD, N);
|
|
89769
|
-
const
|
|
89770
|
-
|
|
89771
|
-
const
|
|
89772
|
-
const
|
|
89798
|
+
const competitivenessScore = scoreCompetitiveness(cDf);
|
|
89799
|
+
// NOTE: Original version:
|
|
89800
|
+
// const Mrange = findMarginalDistricts(Vf, VfArray, N);
|
|
89801
|
+
// const Md = estMarginalCompetitiveDistricts(Mrange, VfArray);
|
|
89802
|
+
// const Mdf = estMarginalCompetitiveShare(Md, Mrange);
|
|
89803
|
+
// const competitivenessScore = scoreCompetitiveness(Mdf, cDf);
|
|
89773
89804
|
let biasScoring = {
|
|
89774
89805
|
bestS: bestS,
|
|
89775
89806
|
bestSf: bestSf,
|
|
@@ -89786,9 +89817,9 @@ function scorePartisan(Vf, VfArray, options) {
|
|
|
89786
89817
|
cSimple: Cn,
|
|
89787
89818
|
cD: cD,
|
|
89788
89819
|
cDf: cDf,
|
|
89789
|
-
mRange: Mrange,
|
|
89790
|
-
mD: Md,
|
|
89791
|
-
mDf: Mdf,
|
|
89820
|
+
// mRange: Mrange,
|
|
89821
|
+
// mD: Md,
|
|
89822
|
+
// mDf: Mdf,
|
|
89792
89823
|
score: competitivenessScore
|
|
89793
89824
|
};
|
|
89794
89825
|
if (bAlternateMetrics) {
|
|
@@ -89906,32 +89937,59 @@ function isAntimajoritarian(Vf, Sf) {
|
|
|
89906
89937
|
return bDem || bRep;
|
|
89907
89938
|
}
|
|
89908
89939
|
exports.isAntimajoritarian = isAntimajoritarian;
|
|
89909
|
-
|
|
89910
|
-
|
|
89911
|
-
|
|
89912
|
-
|
|
89913
|
-
|
|
89940
|
+
// COMPETITIVENESS - Revised 06/23/2020
|
|
89941
|
+
// Normalize overall competitiveness - Raw values are in the range [0.0–1.0].
|
|
89942
|
+
// But the practical max is more like 2/3's, so unitize that range to [0.0–1.0].
|
|
89943
|
+
// Then scale the values to [0–100].
|
|
89944
|
+
function scoreCompetitiveness(Cdf) {
|
|
89945
|
+
const _normalizer = new normalize_1.Normalizer(Cdf);
|
|
89914
89946
|
let worst = C.overallCompetitivenessRange()[C.BEG];
|
|
89915
89947
|
let best = C.overallCompetitivenessRange()[C.END];
|
|
89916
|
-
|
|
89917
|
-
|
|
89918
|
-
|
|
89919
|
-
const
|
|
89920
|
-
// Normalize marginal competitiveness
|
|
89921
|
-
const _marginal = new normalize_1.Normalizer(rawMarginal);
|
|
89922
|
-
worst = C.marginalCompetitivenessRange()[C.BEG];
|
|
89923
|
-
best = C.marginalCompetitivenessRange()[C.END];
|
|
89924
|
-
_marginal.clip(worst, best);
|
|
89925
|
-
_marginal.unitize(worst, best);
|
|
89926
|
-
_marginal.rescale();
|
|
89927
|
-
const mcS = _marginal.normalizedNum;
|
|
89928
|
-
const mcW = C.marginalCompetitivenessWeight();
|
|
89929
|
-
const ocW = C.overallCompetitivenessWeight();
|
|
89930
|
-
// Then combine the results
|
|
89931
|
-
const score = ((mcW + ocW) > 0) ? Math.round(((mcW * mcS) + (ocW * ocS)) / (mcW + ocW)) : 0;
|
|
89948
|
+
_normalizer.clip(worst, best);
|
|
89949
|
+
_normalizer.unitize(worst, best);
|
|
89950
|
+
_normalizer.rescale();
|
|
89951
|
+
const score = _normalizer.normalizedNum;
|
|
89932
89952
|
return score;
|
|
89933
89953
|
}
|
|
89934
89954
|
exports.scoreCompetitiveness = scoreCompetitiveness;
|
|
89955
|
+
/* NOTE - Original version:
|
|
89956
|
+
export function scoreCompetitiveness(rawMarginal: number, rawOverall: number): number
|
|
89957
|
+
{
|
|
89958
|
+
// Normalize overall competitiveness - Raw values are in the range [0.0–1.0].
|
|
89959
|
+
// But the practical max is more like 2/3's, so unitize that range to [0.0–1.0].
|
|
89960
|
+
// Then scale the values to [0–100].
|
|
89961
|
+
const _overall = new Normalizer(rawOverall);
|
|
89962
|
+
|
|
89963
|
+
let worst = C.overallCompetitivenessRange()[C.BEG];
|
|
89964
|
+
let best = C.overallCompetitivenessRange()[C.END];
|
|
89965
|
+
|
|
89966
|
+
_overall.clip(worst, best);
|
|
89967
|
+
_overall.unitize(worst, best);
|
|
89968
|
+
_overall.rescale();
|
|
89969
|
+
|
|
89970
|
+
const ocS = _overall.normalizedNum as number;
|
|
89971
|
+
|
|
89972
|
+
|
|
89973
|
+
// Normalize marginal competitiveness
|
|
89974
|
+
const _marginal = new Normalizer(rawMarginal);
|
|
89975
|
+
|
|
89976
|
+
worst = C.marginalCompetitivenessRange()[C.BEG];
|
|
89977
|
+
best = C.marginalCompetitivenessRange()[C.END];
|
|
89978
|
+
|
|
89979
|
+
_marginal.clip(worst, best);
|
|
89980
|
+
_marginal.unitize(worst, best);
|
|
89981
|
+
_marginal.rescale();
|
|
89982
|
+
const mcS = _marginal.normalizedNum as number;
|
|
89983
|
+
|
|
89984
|
+
const mcW = C.marginalCompetitivenessWeight();
|
|
89985
|
+
const ocW = C.overallCompetitivenessWeight();
|
|
89986
|
+
|
|
89987
|
+
// Then combine the results
|
|
89988
|
+
const score = ((mcW + ocW) > 0) ? Math.round(((mcW * mcS) + (ocW * ocS)) / (mcW + ocW)) : 0;
|
|
89989
|
+
|
|
89990
|
+
return score;
|
|
89991
|
+
}
|
|
89992
|
+
*/
|
|
89935
89993
|
// CORE CAPABILITIES FROM JOHN NAGLE'S METHOD
|
|
89936
89994
|
const { erf } = __webpack_require__(/*! mathjs */ "./node_modules/mathjs/main/esm/index.js");
|
|
89937
89995
|
// console.log("erf(0.2) =", erf(0.2)); // returns 0.22270258921047847
|
|
@@ -90165,19 +90223,20 @@ function isCompetitive(v) {
|
|
|
90165
90223
|
return ((v >= C.competitiveRange()[C.BEG]) && (v <= C.competitiveRange()[C.END])) ? 1 : 0;
|
|
90166
90224
|
}
|
|
90167
90225
|
// cD - The estimated # of competitive districts
|
|
90168
|
-
function estCompetitiveDistricts(VfArray) {
|
|
90169
|
-
return U.trim(U.sumArray(VfArray.map(v => estDistrictCompetitiveness(v))));
|
|
90226
|
+
function estCompetitiveDistricts(VfArray, bCompress = false) {
|
|
90227
|
+
return U.trim(U.sumArray(VfArray.map(v => estDistrictCompetitiveness(v, bCompress))));
|
|
90170
90228
|
}
|
|
90171
90229
|
exports.estCompetitiveDistricts = estCompetitiveDistricts;
|
|
90230
|
+
// COMPETITIVENESS - Modified 06/22/2020
|
|
90172
90231
|
// Re-scale a Democratic vote share to the competitive range (e.g., 45–55%).
|
|
90173
|
-
function estDistrictCompetitiveness(Vf) {
|
|
90232
|
+
function estDistrictCompetitiveness(Vf, bCompress = false) {
|
|
90174
90233
|
const _normalizer = new normalize_1.Normalizer(Vf);
|
|
90175
90234
|
// The end points of a compressed probability distribution
|
|
90176
90235
|
// NOTE - These aren't the points where races start or stop being contested,
|
|
90177
90236
|
// just the end points of a distribution that yields the desired behavior
|
|
90178
90237
|
// in the typical competitive range [45-55%].
|
|
90179
|
-
const distBeg = C.competitiveDistribution()[C.BEG];
|
|
90180
|
-
const distEnd = C.competitiveDistribution()[C.END];
|
|
90238
|
+
const distBeg = bCompress ? C.competitiveDistribution()[C.BEG] : 0.0;
|
|
90239
|
+
const distEnd = bCompress ? C.competitiveDistribution()[C.END] : 1.0;
|
|
90181
90240
|
_normalizer.clip(distBeg, distEnd);
|
|
90182
90241
|
_normalizer.unitize(distBeg, distEnd);
|
|
90183
90242
|
const dC = estDistrictResponsiveness(_normalizer.wipNum);
|
|
@@ -90191,14 +90250,14 @@ function estCompetitiveDistrictsShare(cD, N) {
|
|
|
90191
90250
|
exports.estCompetitiveDistrictsShare = estCompetitiveDistrictsShare;
|
|
90192
90251
|
// Md - The estimated # of "marginal" districts in and around the likely FPTP
|
|
90193
90252
|
// seats & the best seat split that are competitive.
|
|
90194
|
-
function estMarginalCompetitiveDistricts(Mrange, VfArray) {
|
|
90253
|
+
function estMarginalCompetitiveDistricts(Mrange, VfArray, bCompress = false) {
|
|
90195
90254
|
const minId = Mrange[C.BEG];
|
|
90196
90255
|
const maxId = Mrange[C.END];
|
|
90197
90256
|
// Sort the array values, and subset it to those districts
|
|
90198
90257
|
// NOTE - I'm *not* keeping track of the district indexes right now
|
|
90199
90258
|
let subsetVfArray = U.deepCopy(VfArray).sort().slice(minId - 1, maxId);
|
|
90200
90259
|
// Est. competitive districts on that array
|
|
90201
|
-
const Md = U.sumArray(subsetVfArray.map((v) => estDistrictCompetitiveness(v)));
|
|
90260
|
+
const Md = U.sumArray(subsetVfArray.map((v) => estDistrictCompetitiveness(v, bCompress)));
|
|
90202
90261
|
return U.trim(Md);
|
|
90203
90262
|
}
|
|
90204
90263
|
exports.estMarginalCompetitiveDistricts = estMarginalCompetitiveDistricts;
|
|
@@ -90539,7 +90598,7 @@ function calcGamma(Vf, Sf, r) {
|
|
|
90539
90598
|
exports.calcGamma = calcGamma;
|
|
90540
90599
|
// HELPERS
|
|
90541
90600
|
function printPartisanScorecardHeader() {
|
|
90542
|
-
console.log('XX, Name, N, V%, ^S#, S#, B%, B$, UE#, I$, C#, Cd,
|
|
90601
|
+
console.log('XX, Name, N, V%, ^S#, S#, B%, B$, UE#, I$, C#, Cd, Cdf, C$, <P$');
|
|
90543
90602
|
}
|
|
90544
90603
|
exports.printPartisanScorecardHeader = printPartisanScorecardHeader;
|
|
90545
90604
|
function printPartisanScorecardRow(xx, name, N, Vf, s) {
|
|
@@ -90552,21 +90611,24 @@ function printPartisanScorecardRow(xx, name, N, Vf, s) {
|
|
|
90552
90611
|
s.bias.bias, // 7
|
|
90553
90612
|
s.bias.score, s.impact.unearnedS, // 9
|
|
90554
90613
|
s.impact.score, s.competitiveness.cSimple, // 11
|
|
90555
|
-
s.competitiveness.cD, s.competitiveness.
|
|
90614
|
+
s.competitiveness.cD, s.competitiveness.cDf,
|
|
90615
|
+
// s.competitiveness.mD,
|
|
90616
|
+
s.competitiveness.score, s.score // 15
|
|
90556
90617
|
);
|
|
90557
90618
|
}
|
|
90558
90619
|
exports.printPartisanScorecardRow = printPartisanScorecardRow;
|
|
90559
90620
|
// Generate partisan details (Table 1)
|
|
90560
90621
|
function printPartisanDetailsHeader() {
|
|
90561
|
-
console.log('XX, <V>, S(<V>), B%, BS_50, BV_50, Decl, GS, EG, Beta, PR, MM, TO, MM\', LO, Rd, R, r, MIR');
|
|
90622
|
+
console.log('XX, <V>, S(<V>), B%, BS_50, BV_50, Decl, GS, EG, Beta, PR, MM, TO, MM\', LO, Rd, R, r, MIR, Cd, Cdf');
|
|
90562
90623
|
}
|
|
90563
90624
|
exports.printPartisanDetailsHeader = printPartisanDetailsHeader;
|
|
90564
90625
|
function printPartisanDetailsRow(xx, name, N, Vf, s) {
|
|
90565
|
-
console.log('%s, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f', xx, Vf, s.bias.estSf, s.bias.bias, // Simple bias
|
|
90626
|
+
console.log('%s, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f', xx, Vf, s.bias.estSf, s.bias.bias, // Simple bias
|
|
90566
90627
|
s.bias.bS50, s.bias.bV50, s.bias.decl, s.bias.gSym, s.bias.eG, s.bias.bSV, // Beta
|
|
90567
90628
|
s.bias.prop, // PR
|
|
90568
|
-
s.bias.mMs, s.bias.tOf, s.bias.mMd, s.bias.lO, s.competitiveness.rD, s.competitiveness.bigR, s.competitiveness.littleR, s.competitiveness.mIR // Zeta
|
|
90569
|
-
|
|
90629
|
+
s.bias.mMs, s.bias.tOf, s.bias.mMd, s.bias.lO, s.competitiveness.rD, s.competitiveness.bigR, s.competitiveness.littleR, s.competitiveness.mIR, // Zeta
|
|
90630
|
+
s.competitiveness.cD, // COMPETITIVENESS - Temporary to confirm new calc
|
|
90631
|
+
s.competitiveness.cDf);
|
|
90570
90632
|
}
|
|
90571
90633
|
exports.printPartisanDetailsRow = printPartisanDetailsRow;
|
|
90572
90634
|
|
|
@@ -90696,11 +90758,11 @@ function mixinMinorityBonus(score, minorityBonus) {
|
|
|
90696
90758
|
}
|
|
90697
90759
|
exports.mixinMinorityBonus = mixinMinorityBonus;
|
|
90698
90760
|
function printScorecardHeader() {
|
|
90699
|
-
console.log('XX, Name, N, V%, ^S#, S#, B%, B$, UE#, I$, C#, Cd,
|
|
90761
|
+
console.log('XX, Name, N, V%, ^S#, S#, B%, B$, UE#, I$, C#, Cd, Cdf, C$, >P$, Rc, Rc$, Pc, Pc$, G$, Cs, Cs$, Ds, Ds$, S$, Eq, Eq$, T$, Od, Md, M$, $$$');
|
|
90700
90762
|
}
|
|
90701
90763
|
exports.printScorecardHeader = printScorecardHeader;
|
|
90702
90764
|
function printScorecardRow(xx, name, N, Vf, s) {
|
|
90703
|
-
console.log('%s, %s, %i, %f, %i, %f, %f, %i, %f, %i, %i, %f, %f, %i, %i, %f, %i, %f, %i, %i, %f, %i, %f, %i, %i, %f, %i, %i, %f, %i, %i', xx, // 1
|
|
90765
|
+
console.log('%s, %s, %i, %f, %i, %f, %f, %i, %f, %i, %i, %f, %f, %i, %i, %f, %i, %f, %i, %i, %f, %i, %f, %i, %i, %f, %i, %i, %f, %f, %i, %i', xx, // 1
|
|
90704
90766
|
name, // 2
|
|
90705
90767
|
N, // 3
|
|
90706
90768
|
Vf, // 4
|
|
@@ -90709,8 +90771,10 @@ function printScorecardRow(xx, name, N, Vf, s) {
|
|
|
90709
90771
|
s.partisan.bias.bias, // 7
|
|
90710
90772
|
s.partisan.bias.score, s.partisan.impact.unearnedS, // 9
|
|
90711
90773
|
s.partisan.impact.score, s.partisan.competitiveness.cSimple, // 11
|
|
90712
|
-
s.partisan.competitiveness.cD, s.partisan.competitiveness.
|
|
90713
|
-
|
|
90774
|
+
s.partisan.competitiveness.cD, s.partisan.competitiveness.cDf,
|
|
90775
|
+
// s.partisan.competitiveness.mD,
|
|
90776
|
+
s.partisan.competitiveness.score, s.partisan.score2, // 15
|
|
90777
|
+
s.traditionalPrinciples.compactness.reock.raw, s.traditionalPrinciples.compactness.reock.normalized, s.traditionalPrinciples.compactness.polsby.raw, s.traditionalPrinciples.compactness.polsby.normalized, s.traditionalPrinciples.compactness.score, s.traditionalPrinciples.splitting.county.raw, s.traditionalPrinciples.splitting.county.normalized, s.traditionalPrinciples.splitting.district.raw, s.traditionalPrinciples.splitting.district.normalized, s.traditionalPrinciples.splitting.score, s.traditionalPrinciples.populationDeviation.raw, s.traditionalPrinciples.populationDeviation.normalized, s.traditionalPrinciples.score, s.minority.opportunityDistricts, s.minority.coalitionDistricts, s.minority.score, s.score);
|
|
90714
90778
|
}
|
|
90715
90779
|
exports.printScorecardRow = printScorecardRow;
|
|
90716
90780
|
|
|
@@ -102855,6 +102919,17 @@ class AnalyticsSession {
|
|
|
102855
102919
|
getPlanScorecard(bLog = false) {
|
|
102856
102920
|
return this._scorecard;
|
|
102857
102921
|
}
|
|
102922
|
+
getRatings(bLog = false) {
|
|
102923
|
+
const scorecard = this._scorecard;
|
|
102924
|
+
const r = {
|
|
102925
|
+
proportionality: scorecard.partisan.bias.score,
|
|
102926
|
+
competitiveness: scorecard.partisan.competitiveness.score,
|
|
102927
|
+
minorityRights: scorecard.minority.score,
|
|
102928
|
+
compactness: scorecard.traditionalPrinciples.compactness.score,
|
|
102929
|
+
splitting: scorecard.traditionalPrinciples.splitting.score
|
|
102930
|
+
};
|
|
102931
|
+
return r;
|
|
102932
|
+
}
|
|
102858
102933
|
// NOTE - This assumes that analyzePlan() has been run!
|
|
102859
102934
|
getRequirementsChecklist(bLog = false) {
|
|
102860
102935
|
return results_2.prepareRequirementsChecklist(this, bLog);
|