@dra2020/district-analytics 14.2.0 → 15.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/dist/district-analytics.js +402 -314
- package/dist/district-analytics.js.map +1 -1
- package/dist/src/_api.d.ts +5 -5
- package/dist/src/index.d.ts +1 -0
- package/dist/src/score.d.ts +5 -8
- package/dist/src/types.d.ts +0 -1
- package/package.json +1 -2
|
@@ -44,11 +44,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
44
44
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
45
45
|
exports.AnalyticsSession = void 0;
|
|
46
46
|
const baseclient_1 = __webpack_require__(/*! @dra2020/baseclient */ "@dra2020/baseclient");
|
|
47
|
+
// LEGACY - DELETE
|
|
47
48
|
// import * as DT from '@dra2020/dra-types';
|
|
48
|
-
|
|
49
|
+
// LEGACY - DELETE
|
|
50
|
+
// import * as Score from '@dra2020/dra-score';
|
|
49
51
|
const dra_analytics_1 = __webpack_require__(/*! @dra2020/dra-analytics */ "@dra2020/dra-analytics");
|
|
50
52
|
const preprocess_1 = __webpack_require__(/*! ./preprocess */ "./src/preprocess.ts");
|
|
51
53
|
const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
54
|
+
// LEGACY - DELETE
|
|
55
|
+
// import { profilePlan, scorePlan, computeMetrics, rateKeyDimensions, thunkScorecard, compareScorecards } from './score'
|
|
52
56
|
const score_1 = __webpack_require__(/*! ./score */ "./src/score.ts");
|
|
53
57
|
const results_1 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
54
58
|
const results_2 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
@@ -56,6 +60,7 @@ const minority_1 = __webpack_require__(/*! ./minority */ "./src/minority.ts");
|
|
|
56
60
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
57
61
|
const M = __importStar(__webpack_require__(/*! ./minority */ "./src/minority.ts"));
|
|
58
62
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
63
|
+
// LEGACY - DELETE
|
|
59
64
|
// import * as S from './settings';
|
|
60
65
|
class AnalyticsSession {
|
|
61
66
|
constructor(SessionRequest) {
|
|
@@ -115,53 +120,63 @@ class AnalyticsSession {
|
|
|
115
120
|
// we allow it to be exported, so keep generating it, and use it
|
|
116
121
|
// to gather the inputs to new analytics (as well as the legacy).
|
|
117
122
|
this._profile = (0, score_1.profilePlan)(this, bLog);
|
|
118
|
-
|
|
123
|
+
// LEGACY - DELETE
|
|
124
|
+
// let legacyScorecard = {} as Score.Scorecard;
|
|
119
125
|
let legacyScorecardAlt = {};
|
|
120
126
|
let newScorecard = {};
|
|
121
|
-
// LEGACY - Run legacy analytics
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
// LEGACY - DELETE: Run legacy analytics
|
|
128
|
+
/*
|
|
129
|
+
if (this.config.legacyanalytics)
|
|
130
|
+
{
|
|
131
|
+
if (bLog) console.log("Running legacy analytics ...");
|
|
132
|
+
legacyScorecard = scorePlan(this, this._profile, bLog, overridesJSON);
|
|
126
133
|
}
|
|
134
|
+
*/
|
|
127
135
|
// Construct a new/alternate scorecard
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
// LEGACY - DELETE
|
|
137
|
+
// if (this.config.newanalytics)
|
|
138
|
+
// {
|
|
139
|
+
// if (bLog) console.log("Running new analytics ...");
|
|
140
|
+
newScorecard = (0, score_1.computeMetrics)(this._profile, this.getGoodShapes(), bLog); // w/o ratings
|
|
141
|
+
newScorecard = (0, score_1.rateKeyDimensions)(newScorecard, this._profile, bLog); // w/ ratings
|
|
142
|
+
legacyScorecardAlt = (0, score_1.thunkScorecard)(newScorecard, bLog);
|
|
143
|
+
// Add minority notes
|
|
144
|
+
legacyScorecardAlt.minority.details['majorityMinority'] = M.getMajorityMinority(this);
|
|
145
|
+
legacyScorecardAlt.minority.details['vraPreclearance'] = M.getVRASection5(this);
|
|
146
|
+
// LEGACY - DELETE
|
|
147
|
+
// // Compare the new & legacy scorecards
|
|
148
|
+
// compareScorecards(legacyScorecardAlt, legacyScorecard, bLog);
|
|
149
|
+
// }
|
|
150
|
+
// LEGACY - DELETE
|
|
140
151
|
// Use the new scorecard, after creating it
|
|
141
|
-
this._scorecard = (this.config.newanalytics) ? legacyScorecardAlt : legacyScorecard;
|
|
152
|
+
// this._scorecard = (this.config.newanalytics) ? legacyScorecardAlt : legacyScorecard;
|
|
153
|
+
this._scorecard = legacyScorecardAlt;
|
|
142
154
|
// Post-scorecard housekeeping - copied from scorePlan()
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
155
|
+
// LEGACY - DELETE
|
|
156
|
+
// if (this.config.newanalytics)
|
|
157
|
+
// {
|
|
158
|
+
// Before returning, create a dummy population deviation test, for
|
|
159
|
+
// doHasEqualPopulations() to use later.This is preserving the old calling sequence.
|
|
160
|
+
let test = this.getTest(4 /* PopulationDeviation */);
|
|
161
|
+
// Get the raw population deviation
|
|
162
|
+
const popDev = this._scorecard.populationDeviation.raw;
|
|
163
|
+
// Populate the test entry
|
|
164
|
+
test['score'] = popDev;
|
|
165
|
+
test['details'] = { 'maxDeviation': this._scorecard.populationDeviation.notes['maxDeviation'] };
|
|
166
|
+
// Populate the N+1 summary "district" in district.statistics
|
|
167
|
+
let totalPop = this.districts.table.totalPop;
|
|
168
|
+
let popDevPct = this.districts.table.popDevPct;
|
|
169
|
+
let totalVAP = this.districts.table.totalVAP;
|
|
170
|
+
const summaryRow = this.districts.numberOfRows() - 1;
|
|
171
|
+
totalPop[summaryRow] = this._profile.population.targetSize;
|
|
172
|
+
popDevPct[summaryRow] = popDev;
|
|
173
|
+
totalVAP[summaryRow] = Math.round(totalVAP[summaryRow] / this._profile.nDistricts);
|
|
174
|
+
// Added w/ new scorecard
|
|
175
|
+
// Use 'roughly' equal population from dra-analytics
|
|
176
|
+
let test2 = this.getTest(3 /* EqualPopulation */);
|
|
177
|
+
test2['score'] = newScorecard.populationDeviation.roughlyEqual;
|
|
178
|
+
// LEGACY - DELETE
|
|
179
|
+
// }
|
|
165
180
|
// END main analytics
|
|
166
181
|
(0, results_1.doAnalyzePostProcessing)(this, bLog);
|
|
167
182
|
}
|
|
@@ -270,15 +285,18 @@ class AnalyticsSession {
|
|
|
270
285
|
// LEGACY - Threshold defined in dra-analytics for new analytics
|
|
271
286
|
// NOTE - Not sure why this has to be up here ...
|
|
272
287
|
populationDeviationThreshold() {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
288
|
+
// LEGACY - DELETE
|
|
289
|
+
// let threshold: number;
|
|
290
|
+
// if (this.config.legacyanalytics && !this.config.newanalytics)
|
|
291
|
+
// {
|
|
292
|
+
// // NOTE - This assumes the plan has been profiled
|
|
293
|
+
// const scorer = new Score.Scorer();
|
|
294
|
+
// threshold = scorer.populationDeviationThreshold(this.legislativeDistricts); // TODO - 2020
|
|
295
|
+
// }
|
|
296
|
+
// else
|
|
297
|
+
// {
|
|
298
|
+
const threshold = dra_analytics_1.Rate.popdevThreshold(this.legislativeDistricts);
|
|
299
|
+
// }
|
|
282
300
|
return threshold;
|
|
283
301
|
}
|
|
284
302
|
}
|
|
@@ -1614,20 +1632,26 @@ function doHasEqualPopulations(s, bLog = false) {
|
|
|
1614
1632
|
let popDevTest = s.getTest(4 /* PopulationDeviation */);
|
|
1615
1633
|
const popDevPct = popDevTest['score'];
|
|
1616
1634
|
const popDevNormalized = popDevTest['normalizedScore'];
|
|
1617
|
-
// LEGACY - Has 'roughly' equal populations is calculated in dra-analytics
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1635
|
+
// LEGACY - DELETE: Has 'roughly' equal populations is calculated in dra-analytics
|
|
1636
|
+
/*
|
|
1637
|
+
if (s.config.legacyanalytics && !s.config.newanalytics)
|
|
1638
|
+
{
|
|
1639
|
+
// 09-19-2020 - Added to catch edge case of only one non-empty district
|
|
1640
|
+
const p = s._profile as L.Profile;
|
|
1641
|
+
const totPopByDistrict = p.population.byDistrict.filter(x => x > 0);
|
|
1642
|
+
const bTwoOrMoreDistricts: boolean = (totPopByDistrict.length > 1) ? true : false;
|
|
1643
|
+
|
|
1644
|
+
// Populate the test entry
|
|
1645
|
+
if (bTwoOrMoreDistricts && (popDevNormalized > 0))
|
|
1646
|
+
{
|
|
1647
|
+
test['score'] = true;
|
|
1648
|
+
}
|
|
1649
|
+
else
|
|
1650
|
+
{
|
|
1651
|
+
test['score'] = false;
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
*/
|
|
1631
1655
|
test['details']['deviation'] = popDevPct;
|
|
1632
1656
|
test['details']['thresholds'] = popDevTest['details']['scale'];
|
|
1633
1657
|
// Populate the N+1 summary "district" in district.statistics
|
|
@@ -2158,11 +2182,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
2158
2182
|
return result;
|
|
2159
2183
|
};
|
|
2160
2184
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2161
|
-
exports.
|
|
2162
|
-
const Score = __importStar(__webpack_require__(/*! @dra2020/dra-score */ "@dra2020/dra-score"));
|
|
2185
|
+
exports.thunkScorecard = exports.rateKeyDimensions = exports.computeMetrics = exports.getStatewideDemographics = exports.profilePlan = void 0;
|
|
2163
2186
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
2164
|
-
const M = __importStar(__webpack_require__(/*! ./minority */ "./src/minority.ts"));
|
|
2165
|
-
const C = __importStar(__webpack_require__(/*! ./compact */ "./src/compact.ts"));
|
|
2166
2187
|
const dra_analytics_1 = __webpack_require__(/*! @dra2020/dra-analytics */ "@dra2020/dra-analytics");
|
|
2167
2188
|
// PROFILE A PLAN
|
|
2168
2189
|
const KEEP_DECIMALS = 6;
|
|
@@ -2276,56 +2297,74 @@ function getStatewideDemographics(s, bLog = false) {
|
|
|
2276
2297
|
}
|
|
2277
2298
|
exports.getStatewideDemographics = getStatewideDemographics;
|
|
2278
2299
|
// SCORE A PLAN - Legacy using dra-score
|
|
2279
|
-
// LEGACY
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2300
|
+
// LEGACY - DELETE
|
|
2301
|
+
/*
|
|
2302
|
+
export function scorePlan(s: AnalyticsSession, p: Score.Profile, bLog: boolean = false, overridesJSON?: any): Score.Scorecard
|
|
2303
|
+
{
|
|
2304
|
+
let scorer = new Score.Scorer();
|
|
2305
|
+
const scorecard: Score.Scorecard = scorer.score(p, overridesJSON);
|
|
2306
|
+
|
|
2307
|
+
// LEGACY POST-SCORECARD HOUSEKEEPING
|
|
2308
|
+
if (s.config.legacyanalytics && !s.config.newanalytics)
|
|
2309
|
+
{
|
|
2310
|
+
// Before returning, create a dummy population deviation test, for
|
|
2311
|
+
// doHasEqualPopulations() to use later.This is preserving the old calling sequence.
|
|
2312
|
+
let test = s.getTest(T.Test.PopulationDeviation) as T.TestEntry;
|
|
2313
|
+
|
|
2314
|
+
// Get the raw population deviation
|
|
2315
|
+
const popDev = scorecard.populationDeviation.raw;
|
|
2316
|
+
|
|
2317
|
+
// Populate the test entry
|
|
2318
|
+
test['score'] = popDev;
|
|
2319
|
+
test['details'] = { 'maxDeviation': scorecard.populationDeviation.notes['maxDeviation'] };
|
|
2320
|
+
|
|
2321
|
+
// Populate the N+1 summary "district" in district.statistics
|
|
2322
|
+
let totalPop = s.districts.table.totalPop;
|
|
2323
|
+
let popDevPct = s.districts.table.popDevPct;
|
|
2324
|
+
let totalVAP = s.districts.table.totalVAP;
|
|
2325
|
+
|
|
2326
|
+
const summaryRow = s.districts.numberOfRows() - 1;
|
|
2327
|
+
totalPop[summaryRow] = p.population.targetSize;
|
|
2328
|
+
popDevPct[summaryRow] = popDev;
|
|
2329
|
+
totalVAP[summaryRow] = Math.round(totalVAP[summaryRow] / p.nDistricts);
|
|
2330
|
+
|
|
2331
|
+
} // end
|
|
2332
|
+
|
|
2333
|
+
// Add minority notes
|
|
2334
|
+
scorecard.minority.details['majorityMinority'] = M.getMajorityMinority(s);
|
|
2335
|
+
scorecard.minority.details['vraPreclearance'] = M.getVRASection5(s);
|
|
2336
|
+
|
|
2337
|
+
try
|
|
2338
|
+
{
|
|
2339
|
+
// Add KIWYSI compactness score
|
|
2340
|
+
const kiwysiScores: number[] = C.scoreKIWYSICompactness(s, bLog);
|
|
2341
|
+
// 10-21-2020 - Computing the average score here
|
|
2342
|
+
const avgKIWYSIScore: number = Math.round(U.avgArray(kiwysiScores));
|
|
2343
|
+
scorecard.compactness.details['kiwysi'] = avgKIWYSIScore;
|
|
2344
|
+
|
|
2345
|
+
// 10-21-2020 - Added KIWYSI scores to the by-district details
|
|
2346
|
+
let byDistrict: Score.CompactnessByDistrict[] = scorecard.compactness.details['byDistrict'];
|
|
2347
|
+
const nDistricts = byDistrict.length;
|
|
2348
|
+
|
|
2349
|
+
for (let districtID = 1; districtID <= nDistricts; districtID++)
|
|
2350
|
+
{
|
|
2351
|
+
byDistrict[districtID - 1].kiwysiScore = kiwysiScores[districtID - 1];
|
|
2352
|
+
|
|
2353
|
+
// 09-17-21 - Fix the normalized Polsby–Popper score!
|
|
2354
|
+
const rawPolsby = byDistrict[districtID - 1].rawPolsby;
|
|
2355
|
+
byDistrict[districtID - 1].normalizedPolsby = Rate.ratePolsby(rawPolsby);
|
|
2325
2356
|
}
|
|
2326
|
-
|
|
2357
|
+
}
|
|
2358
|
+
catch (e)
|
|
2359
|
+
{
|
|
2360
|
+
console.log("Exception caught scoring KIWYSI compactness.");
|
|
2361
|
+
console.log((<Error>e).message);
|
|
2362
|
+
// throw e;
|
|
2363
|
+
}
|
|
2364
|
+
|
|
2365
|
+
return scorecard;
|
|
2327
2366
|
}
|
|
2328
|
-
|
|
2367
|
+
*/
|
|
2329
2368
|
// SCORE A PLAN - New using dra-analytics
|
|
2330
2369
|
function computeMetrics(p, districtShapes, bLog = false) {
|
|
2331
2370
|
if (bLog)
|
|
@@ -2471,205 +2510,257 @@ function thunkScorecard(newScorecard, bLog = false) {
|
|
|
2471
2510
|
return scorecard;
|
|
2472
2511
|
}
|
|
2473
2512
|
exports.thunkScorecard = thunkScorecard;
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
matchFloats("
|
|
2507
|
-
|
|
2508
|
-
matchFloats("
|
|
2509
|
-
matchFloats("
|
|
2510
|
-
matchFloats("
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2513
|
+
// LEGACY - DELETE
|
|
2514
|
+
/*
|
|
2515
|
+
export function compareScorecards(altLegacyScorecard: Score.Scorecard, legacyScorecard: Score.Scorecard, bLog: boolean = false): void
|
|
2516
|
+
{
|
|
2517
|
+
if (bLog) console.log("Comparing new & legacy scorecards ...");
|
|
2518
|
+
|
|
2519
|
+
// A pretty loose tolerance, because we're not trimming values in the new analytics
|
|
2520
|
+
const DECIMAL_PLACES = 2;
|
|
2521
|
+
const DEFAULT_TOLERANCE = toleranceFn(DECIMAL_PLACES);
|
|
2522
|
+
|
|
2523
|
+
// COMPARE PARTISAN SCORECARD
|
|
2524
|
+
|
|
2525
|
+
// Compare BIAS section
|
|
2526
|
+
|
|
2527
|
+
matchFloats("bestS", altLegacyScorecard.partisan.bias.bestS, legacyScorecard.partisan.bias.bestS, DEFAULT_TOLERANCE);
|
|
2528
|
+
matchFloats("bestSf", altLegacyScorecard.partisan.bias.bestSf, legacyScorecard.partisan.bias.bestSf, DEFAULT_TOLERANCE);
|
|
2529
|
+
matchFloats("estS", altLegacyScorecard.partisan.bias.estS, legacyScorecard.partisan.bias.estS, DEFAULT_TOLERANCE);
|
|
2530
|
+
matchFloats("estSf", altLegacyScorecard.partisan.bias.estSf, legacyScorecard.partisan.bias.estSf, DEFAULT_TOLERANCE);
|
|
2531
|
+
matchFloats("deviation", altLegacyScorecard.partisan.bias.deviation, legacyScorecard.partisan.bias.deviation, DEFAULT_TOLERANCE);
|
|
2532
|
+
matchInts("proportionality/score", altLegacyScorecard.partisan.bias.score, legacyScorecard.partisan.bias.score);
|
|
2533
|
+
|
|
2534
|
+
matchFloats("tOf", altLegacyScorecard.partisan.bias.tOf as number, legacyScorecard.partisan.bias.tOf as number, DEFAULT_TOLERANCE);
|
|
2535
|
+
matchFloats("fptpS", altLegacyScorecard.partisan.bias.fptpS as number, legacyScorecard.partisan.bias.fptpS as number, DEFAULT_TOLERANCE);
|
|
2536
|
+
matchFloats("bS50", altLegacyScorecard.partisan.bias.bS50 as number, legacyScorecard.partisan.bias.bS50 as number, DEFAULT_TOLERANCE);
|
|
2537
|
+
matchFloats("deviation", altLegacyScorecard.partisan.bias.deviation, legacyScorecard.partisan.bias.deviation, DEFAULT_TOLERANCE);
|
|
2538
|
+
matchUndefinableFloats("decl", altLegacyScorecard.partisan.bias.decl, legacyScorecard.partisan.bias.decl, toleranceFn(1));
|
|
2539
|
+
|
|
2540
|
+
let rvPointsAlt = altLegacyScorecard.partisan.bias.rvPoints;
|
|
2541
|
+
let rvPoints = legacyScorecard.partisan.bias.rvPoints;
|
|
2542
|
+
if (matchUndefinedness("rvPoints", rvPointsAlt, rvPoints)) {
|
|
2543
|
+
rvPointsAlt = rvPointsAlt as L.rVpoints;
|
|
2544
|
+
rvPoints = rvPoints as L.rVpoints;
|
|
2545
|
+
matchFloats("rvPoints/Sb", rvPointsAlt.Sb, rvPoints.Sb, DEFAULT_TOLERANCE);
|
|
2546
|
+
matchFloats("rvPoints/Ra", rvPointsAlt.Ra, rvPoints.Ra, DEFAULT_TOLERANCE);
|
|
2547
|
+
matchFloats("rvPoints/Rb", rvPointsAlt.Rb, rvPoints.Rb, DEFAULT_TOLERANCE);
|
|
2548
|
+
matchFloats("rvPoints/Va", rvPointsAlt.Va, rvPoints.Va, DEFAULT_TOLERANCE);
|
|
2549
|
+
matchFloats("rvPoints/Vb", rvPointsAlt.Vb, rvPoints.Vb, DEFAULT_TOLERANCE);
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2552
|
+
matchFloats("gSym", altLegacyScorecard.partisan.bias.gSym as number, legacyScorecard.partisan.bias.gSym as number, DEFAULT_TOLERANCE);
|
|
2553
|
+
matchUndefinableFloats("gamma", altLegacyScorecard.partisan.bias.gamma, legacyScorecard.partisan.bias.gamma, DEFAULT_TOLERANCE);
|
|
2554
|
+
matchFloats("eG", altLegacyScorecard.partisan.bias.eG as number, legacyScorecard.partisan.bias.eG as number, DEFAULT_TOLERANCE);
|
|
2555
|
+
matchUndefinableFloats("bSV", altLegacyScorecard.partisan.bias.bSV, legacyScorecard.partisan.bias.bSV, DEFAULT_TOLERANCE);
|
|
2556
|
+
matchFloats("prop", altLegacyScorecard.partisan.bias.prop as number, legacyScorecard.partisan.bias.prop as number, DEFAULT_TOLERANCE);
|
|
2557
|
+
matchFloats("mMs", altLegacyScorecard.partisan.bias.mMs as number, legacyScorecard.partisan.bias.mMs as number, DEFAULT_TOLERANCE);
|
|
2558
|
+
matchFloats("mMd", altLegacyScorecard.partisan.bias.mMd as number, legacyScorecard.partisan.bias.mMd as number, DEFAULT_TOLERANCE);
|
|
2559
|
+
matchUndefinableFloats("lO", altLegacyScorecard.partisan.bias.lO, legacyScorecard.partisan.bias.lO, DEFAULT_TOLERANCE);
|
|
2560
|
+
|
|
2561
|
+
// Compare Impact section
|
|
2562
|
+
|
|
2563
|
+
matchFloats("unearnedS", altLegacyScorecard.partisan.impact.unearnedS, legacyScorecard.partisan.impact.unearnedS, DEFAULT_TOLERANCE);
|
|
2564
|
+
// Note - We don't use the impact score, so we don't compute it in the new scorecard.
|
|
2565
|
+
// matchInts("impact/score", altLegacyScorecard.partisan.impact.score as number, legacyScorecard.partisan.impact.score);
|
|
2566
|
+
|
|
2567
|
+
// Compare Responsiveness section
|
|
2568
|
+
|
|
2569
|
+
matchUndefinableFloats("bigR", altLegacyScorecard.partisan.responsiveness.bigR, legacyScorecard.partisan.responsiveness.bigR, DEFAULT_TOLERANCE);
|
|
2570
|
+
matchUndefinableFloats("littleR", altLegacyScorecard.partisan.responsiveness.littleR, legacyScorecard.partisan.responsiveness.littleR, DEFAULT_TOLERANCE);
|
|
2571
|
+
matchUndefinableFloats("mIR", altLegacyScorecard.partisan.responsiveness.mIR, legacyScorecard.partisan.responsiveness.mIR, DEFAULT_TOLERANCE);
|
|
2572
|
+
matchFloats("rD", altLegacyScorecard.partisan.responsiveness.rD as number, legacyScorecard.partisan.responsiveness.rD as number, DEFAULT_TOLERANCE);
|
|
2573
|
+
matchFloats("rDf", altLegacyScorecard.partisan.responsiveness.rDf as number, legacyScorecard.partisan.responsiveness.rDf as number, DEFAULT_TOLERANCE);
|
|
2574
|
+
|
|
2575
|
+
matchFloats("cSimple", altLegacyScorecard.partisan.responsiveness.cSimple, legacyScorecard.partisan.responsiveness.cSimple, DEFAULT_TOLERANCE);
|
|
2576
|
+
matchFloats("cD", altLegacyScorecard.partisan.responsiveness.cD, legacyScorecard.partisan.responsiveness.cD, DEFAULT_TOLERANCE);
|
|
2577
|
+
matchFloats("cDf", altLegacyScorecard.partisan.responsiveness.cDf, legacyScorecard.partisan.responsiveness.cDf, DEFAULT_TOLERANCE);
|
|
2578
|
+
matchInts("competitiveness/score", altLegacyScorecard.partisan.responsiveness.score as number, legacyScorecard.partisan.responsiveness.score);
|
|
2579
|
+
|
|
2580
|
+
matchPointArrays("dSVpoints", altLegacyScorecard.partisan.dSVpoints, legacyScorecard.partisan.dSVpoints, DEFAULT_TOLERANCE);
|
|
2581
|
+
matchPointArrays("rSVpoints", altLegacyScorecard.partisan.rSVpoints, legacyScorecard.partisan.rSVpoints, DEFAULT_TOLERANCE);
|
|
2582
|
+
|
|
2583
|
+
matchUndefinableFloats("averageDVf", altLegacyScorecard.partisan.averageDVf, legacyScorecard.partisan.averageDVf, DEFAULT_TOLERANCE);
|
|
2584
|
+
matchUndefinableFloats("averageRVf", altLegacyScorecard.partisan.averageRVf, legacyScorecard.partisan.averageRVf, DEFAULT_TOLERANCE);
|
|
2585
|
+
matchDicts("partisan/details", altLegacyScorecard.partisan.details, legacyScorecard.partisan.details);
|
|
2586
|
+
|
|
2587
|
+
// COMPARE MINORITY SCORECARD
|
|
2588
|
+
|
|
2589
|
+
matchObjectsAndArrays("pivotByDemographic", altLegacyScorecard.minority.pivotByDemographic, legacyScorecard.minority.pivotByDemographic);
|
|
2590
|
+
matchFloats("opportunityDistricts", altLegacyScorecard.minority.opportunityDistricts, legacyScorecard.minority.opportunityDistricts, DEFAULT_TOLERANCE);
|
|
2591
|
+
matchFloats("coalitionDistricts", altLegacyScorecard.minority.coalitionDistricts, legacyScorecard.minority.coalitionDistricts, DEFAULT_TOLERANCE);
|
|
2592
|
+
matchInts("minority/score", altLegacyScorecard.minority.score as number, legacyScorecard.minority.score);
|
|
2593
|
+
matchDicts("minority/details", altLegacyScorecard.minority.details, legacyScorecard.minority.details);
|
|
2594
|
+
|
|
2595
|
+
// COMPARE COMPACTNESS SCORECARD
|
|
2596
|
+
|
|
2597
|
+
matchFloats("reock", altLegacyScorecard.compactness.reock.raw, legacyScorecard.compactness.reock.raw, DEFAULT_TOLERANCE);
|
|
2598
|
+
matchInts("reock/normalized", altLegacyScorecard.compactness.reock.normalized, legacyScorecard.compactness.reock.normalized);
|
|
2599
|
+
matchFloats("polsby", altLegacyScorecard.compactness.polsby.raw, legacyScorecard.compactness.polsby.raw, DEFAULT_TOLERANCE);
|
|
2600
|
+
matchInts("polsby/normalized", altLegacyScorecard.compactness.polsby.normalized, legacyScorecard.compactness.polsby.normalized);
|
|
2601
|
+
matchInts("compactness/score", altLegacyScorecard.compactness.score as number, legacyScorecard.compactness.score);
|
|
2602
|
+
// Compare 'byDistrict' results separately
|
|
2603
|
+
const _altCompactnessByDistrict = Utils.deepCopy(altLegacyScorecard.compactness.details['byDistrict']);
|
|
2604
|
+
const _CompactnessByDistrict = Utils.deepCopy(legacyScorecard.compactness.details['byDistrict']);
|
|
2605
|
+
const _altCompactnessDetails = Utils.deepCopy(altLegacyScorecard.compactness.details);
|
|
2606
|
+
const _CompactnessDetails = Utils.deepCopy(legacyScorecard.compactness.details);
|
|
2607
|
+
delete _altCompactnessDetails['byDistrict'];
|
|
2608
|
+
delete _CompactnessDetails['byDistrict'];
|
|
2609
|
+
matchDicts("compactness/details", _altCompactnessDetails, _CompactnessDetails);
|
|
2610
|
+
matchCompactnessByDistrict("compactness/byDistrict", _altCompactnessByDistrict, _CompactnessByDistrict, DEFAULT_TOLERANCE);
|
|
2611
|
+
|
|
2612
|
+
// COMPARE SPLITTING SCORECARD
|
|
2613
|
+
|
|
2614
|
+
matchFloats("county", altLegacyScorecard.splitting.county.raw, legacyScorecard.splitting.county.raw, DEFAULT_TOLERANCE);
|
|
2615
|
+
matchInts("county/normalized", altLegacyScorecard.splitting.county.normalized, legacyScorecard.splitting.county.normalized);
|
|
2616
|
+
matchFloats("district", altLegacyScorecard.splitting.district.raw, legacyScorecard.splitting.district.raw, DEFAULT_TOLERANCE);
|
|
2617
|
+
matchInts("district/normalized", altLegacyScorecard.splitting.district.normalized, legacyScorecard.splitting.district.normalized);
|
|
2618
|
+
matchInts("splitting/score", altLegacyScorecard.splitting.score as number, legacyScorecard.splitting.score);
|
|
2619
|
+
matchDicts("splitting/details", altLegacyScorecard.splitting.details, legacyScorecard.splitting.details);
|
|
2620
|
+
|
|
2621
|
+
// COMPARE POPULATION SCORECARD
|
|
2622
|
+
|
|
2623
|
+
matchFloats("popdev", altLegacyScorecard.populationDeviation.raw, legacyScorecard.populationDeviation.raw, DEFAULT_TOLERANCE);
|
|
2624
|
+
matchInts("popdev/score", altLegacyScorecard.populationDeviation.normalized, legacyScorecard.populationDeviation.normalized);
|
|
2625
|
+
matchDicts("popdev/notes", altLegacyScorecard.populationDeviation.notes, legacyScorecard.populationDeviation.notes);
|
|
2626
|
+
|
|
2627
|
+
matchDicts("details", altLegacyScorecard.details, legacyScorecard.details);
|
|
2628
|
+
}
|
|
2629
|
+
*/
|
|
2630
|
+
// LEGACY - DELETE
|
|
2631
|
+
/*
|
|
2566
2632
|
// Matching helpers
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
}
|
|
2633
|
+
|
|
2634
|
+
function matchFloats(property: string, received: number, good: number, tolerance: number): boolean
|
|
2635
|
+
{
|
|
2636
|
+
if (Utils.areRoughlyEqual(received, good, tolerance)) {
|
|
2637
|
+
return true;
|
|
2638
|
+
}
|
|
2639
|
+
else {
|
|
2640
|
+
console.log(`${property} does not match: ${good} expected. Received ${received}.`);
|
|
2641
|
+
return false;
|
|
2642
|
+
}
|
|
2575
2643
|
}
|
|
2576
|
-
|
|
2577
|
-
|
|
2644
|
+
|
|
2645
|
+
function toleranceFn (places: number): number{
|
|
2646
|
+
return 0.5 / Math.pow(10, places)
|
|
2578
2647
|
}
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
}
|
|
2648
|
+
|
|
2649
|
+
function matchInts(property: string, received: number, good: number): boolean
|
|
2650
|
+
{
|
|
2651
|
+
if (received == good) {
|
|
2652
|
+
return true;
|
|
2653
|
+
}
|
|
2654
|
+
else {
|
|
2655
|
+
console.log(`${property} does not match: ${good} expected. Received ${received}.`);
|
|
2656
|
+
return false;
|
|
2657
|
+
}
|
|
2587
2658
|
}
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2659
|
+
|
|
2660
|
+
function matchUndefinableFloats(property: string, received: number | undefined, good: number | undefined, tolerance: number): boolean
|
|
2661
|
+
{
|
|
2662
|
+
if ((received === undefined) && (good === undefined)) return true;
|
|
2663
|
+
if ((received === undefined) || (good === undefined)) {
|
|
2664
|
+
console.log(`${property} does not match: ${good} expected. Received ${received}.`);
|
|
2665
|
+
return false;
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2668
|
+
return matchFloats(property, received as number, good as number, tolerance);
|
|
2596
2669
|
}
|
|
2670
|
+
|
|
2597
2671
|
// https://stackoverflow.com/questions/13142968/deep-comparison-of-objects-arrays
|
|
2598
|
-
function matchObjectsAndArrays(property, received, good)
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
}
|
|
2605
|
-
if ((Object.keys(received).length === 0) && (Object.keys(good).length === 0))
|
|
2606
|
-
return true; // Both empty
|
|
2607
|
-
if (JSON.stringify(received) === JSON.stringify(good))
|
|
2608
|
-
return true; // Contents match
|
|
2609
|
-
console.log(`${property} objects or arrays do not match.`); // Contents don't match
|
|
2672
|
+
function matchObjectsAndArrays (property: string, received: object | undefined, good: object | undefined): boolean
|
|
2673
|
+
{
|
|
2674
|
+
if ((received === undefined) && (good === undefined)) return true; // Both undefined
|
|
2675
|
+
|
|
2676
|
+
if ((received === undefined) || (good === undefined)) { // One undefined but not the other
|
|
2677
|
+
console.log(`${property} does not match: ${good} expected. Received ${received}.`);
|
|
2610
2678
|
return false;
|
|
2679
|
+
}
|
|
2680
|
+
|
|
2681
|
+
if ((Object.keys(received).length === 0) && (Object.keys(good).length === 0)) return true; // Both empty
|
|
2682
|
+
|
|
2683
|
+
if (JSON.stringify(received) === JSON.stringify(good)) return true; // Contents match
|
|
2684
|
+
|
|
2685
|
+
console.log(`${property} objects or arrays do not match.`); // Contents don't match
|
|
2686
|
+
return false;
|
|
2611
2687
|
}
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2688
|
+
|
|
2689
|
+
function matchDicts (property: string, received: L.Dict, good: L.Dict): boolean
|
|
2690
|
+
{
|
|
2691
|
+
if ((Object.keys(received).length === 0) && (Object.keys(good).length === 0)) return true; // Both empty
|
|
2692
|
+
|
|
2693
|
+
const receivedStr: string = JSON.stringify(received);
|
|
2694
|
+
const goodStr = JSON.stringify(good);
|
|
2695
|
+
if (receivedStr === goodStr) return true; // Contents match
|
|
2696
|
+
|
|
2697
|
+
console.log(`${property} does not match: ${goodStr} expected. Received ${receivedStr}.`); // Contents don't match
|
|
2698
|
+
|
|
2699
|
+
return false;
|
|
2621
2700
|
}
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2701
|
+
|
|
2702
|
+
function matchUndefinedness(property: string, received: any | undefined, good: any | undefined): boolean
|
|
2703
|
+
{
|
|
2704
|
+
if ((received === undefined) && (good === undefined)) return true;
|
|
2705
|
+
|
|
2706
|
+
if ((received === undefined) || (good === undefined)) return false;
|
|
2707
|
+
|
|
2708
|
+
return true;
|
|
2628
2709
|
}
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
return
|
|
2710
|
+
|
|
2711
|
+
function matchPointArrays(property: string, received: L.SVpoint[], good: L.SVpoint[], tolerance: number): boolean
|
|
2712
|
+
{
|
|
2713
|
+
if (received.length != good.length)
|
|
2714
|
+
{
|
|
2715
|
+
console.log(`${property} does not match: Different number of points.`);
|
|
2716
|
+
return false;
|
|
2717
|
+
}
|
|
2718
|
+
|
|
2719
|
+
for (var i = 0; i < received.length; i++)
|
|
2720
|
+
{
|
|
2721
|
+
const vLabel: string = property + '/' + i.toString() + '/' + 'v';
|
|
2722
|
+
const sLabel: string = property + '/' + i.toString() + '/' + 's';
|
|
2723
|
+
if (!matchFloats(vLabel, received[i].v, good[i].v, tolerance)) return false;
|
|
2724
|
+
if (!matchFloats(sLabel, received[i].s, good[i].s, tolerance)) return false;
|
|
2725
|
+
}
|
|
2726
|
+
|
|
2727
|
+
return true;
|
|
2643
2728
|
}
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2729
|
+
|
|
2730
|
+
function matchCompactnessByDistrict(property: string, received: L.CompactnessByDistrict[], good: L.CompactnessByDistrict[], tolerance: number): boolean
|
|
2731
|
+
{
|
|
2732
|
+
if (received.length != good.length)
|
|
2733
|
+
{
|
|
2734
|
+
console.log(`${property} does not match: Different number of districts.`);
|
|
2735
|
+
return false;
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2738
|
+
let bMismatched = false;
|
|
2739
|
+
for (var i = 0; i < received.length; i++)
|
|
2740
|
+
{
|
|
2741
|
+
const rawReock: string = property + '/' + i.toString() + '/' + 'rawReock';
|
|
2742
|
+
if (!matchFloats(rawReock, received[i].rawReock, good[i].rawReock, tolerance)) bMismatched = true;
|
|
2743
|
+
|
|
2744
|
+
const normalizedReock: string = property + '/' + i.toString() + '/' + 'normalizedReock';
|
|
2745
|
+
if (!matchInts(normalizedReock, received[i].normalizedReock, good[i].normalizedReock)) bMismatched = true;
|
|
2746
|
+
|
|
2747
|
+
const rawPolsby: string = property + '/' + i.toString() + '/' + 'rawPolsby';
|
|
2748
|
+
if (!matchFloats(rawPolsby, received[i].rawPolsby, good[i].rawPolsby, tolerance)) bMismatched = true;
|
|
2749
|
+
|
|
2750
|
+
// TODO
|
|
2751
|
+
// 09-17-21 - By-district Polsby–Popper ratings from dra-score in production are wrong!
|
|
2752
|
+
const normalizedPolsby: string = property + '/' + i.toString() + '/' + 'normalizedPolsby';
|
|
2753
|
+
if (!matchInts(normalizedPolsby, received[i].normalizedPolsby, good[i].normalizedPolsby)) bMismatched = true;
|
|
2754
|
+
|
|
2755
|
+
const kiwysiScore: string = property + '/' + i.toString() + '/' + 'kiwysiScore';
|
|
2756
|
+
if (!matchInts(kiwysiScore, received[i].kiwysiScore as number, good[i].kiwysiScore as number)) bMismatched = true;
|
|
2757
|
+
}
|
|
2758
|
+
if (bMismatched = true) return false;
|
|
2759
|
+
|
|
2760
|
+
return true;
|
|
2672
2761
|
}
|
|
2762
|
+
*/
|
|
2763
|
+
// LEGACY - DELETE
|
|
2673
2764
|
// Not used, after all
|
|
2674
2765
|
/* Modeled after David Sielaff's Jest extension 'toBeArrayWithValuesCloseTo'
|
|
2675
2766
|
|
|
@@ -2807,6 +2898,13 @@ exports.OUT_OF_STATE = "OUT_OF_STATE";
|
|
|
2807
2898
|
// TYPE DEFINITIONS
|
|
2808
2899
|
//
|
|
2809
2900
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2901
|
+
// LEGACY - DELETE
|
|
2902
|
+
// export
|
|
2903
|
+
// {
|
|
2904
|
+
// Profile, Scorecard,
|
|
2905
|
+
// // LEGACY - DELETE
|
|
2906
|
+
// // estSeatProbability
|
|
2907
|
+
// } from '@dra2020/dra-score';
|
|
2810
2908
|
// END
|
|
2811
2909
|
|
|
2812
2910
|
|
|
@@ -3309,16 +3407,6 @@ module.exports = require("@dra2020/dra-analytics");
|
|
|
3309
3407
|
|
|
3310
3408
|
/***/ }),
|
|
3311
3409
|
|
|
3312
|
-
/***/ "@dra2020/dra-score":
|
|
3313
|
-
/*!*************************************!*\
|
|
3314
|
-
!*** external "@dra2020/dra-score" ***!
|
|
3315
|
-
\*************************************/
|
|
3316
|
-
/***/ ((module) => {
|
|
3317
|
-
|
|
3318
|
-
module.exports = require("@dra2020/dra-score");
|
|
3319
|
-
|
|
3320
|
-
/***/ }),
|
|
3321
|
-
|
|
3322
3410
|
/***/ "@dra2020/dra-types":
|
|
3323
3411
|
/*!*************************************!*\
|
|
3324
3412
|
!*** external "@dra2020/dra-types" ***!
|