@dra2020/district-analytics 2.0.9 → 3.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/cli.js +91094 -351
- package/dist/cli.js.map +1 -1
- package/dist/district-analytics.js +451 -251
- package/dist/district-analytics.js.map +1 -1
- package/dist/src/_api.d.ts +8 -2
- package/dist/src/geofeature.d.ts +0 -2
- package/dist/src/results.d.ts +22 -1
- package/dist/src/types.d.ts +5 -5
- package/dist/src/utils.d.ts +0 -1
- package/package.json +2 -1
|
@@ -118,9 +118,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
118
118
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
119
119
|
const preprocess_1 = __webpack_require__(/*! ./preprocess */ "./src/preprocess.ts");
|
|
120
120
|
const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
121
|
+
const score_1 = __webpack_require__(/*! ./score */ "./src/score.ts");
|
|
121
122
|
const results_1 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
122
123
|
const results_2 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
123
|
-
const geofeature_1 = __webpack_require__(/*! ./geofeature */ "./src/geofeature.ts");
|
|
124
124
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
125
125
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
126
126
|
class AnalyticsSession {
|
|
@@ -174,6 +174,11 @@ class AnalyticsSession {
|
|
|
174
174
|
preprocess_1.doPreprocessData(this, bLog);
|
|
175
175
|
analyze_1.doAnalyzeDistricts(this, bLog);
|
|
176
176
|
analyze_1.doAnalyzePlan(this, bLog);
|
|
177
|
+
// TODO - SCORE
|
|
178
|
+
this._profile = score_1.profilePlan(this, bLog);
|
|
179
|
+
// this._profile = Score.sampleProfile;
|
|
180
|
+
this._scorecard = score_1.scorePlan(this._profile, bLog);
|
|
181
|
+
// TODO - SCORE
|
|
177
182
|
results_1.doAnalyzePostProcessing(this, bLog);
|
|
178
183
|
}
|
|
179
184
|
catch (_a) {
|
|
@@ -183,92 +188,45 @@ class AnalyticsSession {
|
|
|
183
188
|
return true;
|
|
184
189
|
}
|
|
185
190
|
// NOTE - This assumes that analyzePlan() has been run!
|
|
186
|
-
getPlanAnalytics(bLog = false) {
|
|
187
|
-
return results_2.preparePlanAnalytics(this, bLog);
|
|
188
|
-
}
|
|
189
|
-
// NOTE - This assumes that analyzePlan() has been run!
|
|
190
191
|
getDistrictStatistics(bLog = false) {
|
|
191
192
|
return results_2.prepareDistrictStatistics(this, bLog);
|
|
192
193
|
}
|
|
194
|
+
// TODO - SCORE
|
|
195
|
+
getPlanProfile(bLog = false) {
|
|
196
|
+
return this._profile;
|
|
197
|
+
}
|
|
198
|
+
// TODO - SCORE
|
|
199
|
+
getPlanScorecard(bLog = false) {
|
|
200
|
+
return this._scorecard;
|
|
201
|
+
}
|
|
202
|
+
/* TODO - SCORE
|
|
203
|
+
// NOTE - This assumes that analyzePlan() has been run!
|
|
204
|
+
getPlanAnalytics(bLog: boolean = false): PlanAnalytics
|
|
205
|
+
{
|
|
206
|
+
return preparePlanAnalytics(this, bLog);
|
|
207
|
+
}
|
|
208
|
+
*/
|
|
209
|
+
// TODO - SCORE
|
|
210
|
+
// NOTE - This assumes that analyzePlan() has been run!
|
|
211
|
+
getRequirementsChecklist(bLog = false) {
|
|
212
|
+
return results_2.prepareRequirementsChecklist(this, bLog);
|
|
213
|
+
}
|
|
193
214
|
// NOTE - This assumes that analyzePlan() has been run!
|
|
194
215
|
getDiscontiguousDistrictFeatures(bLog = false) {
|
|
195
216
|
// Get the (possibly empty) list of discontiguous district IDs
|
|
196
|
-
|
|
197
|
-
|
|
217
|
+
let contiguousTest = this.getTest(1 /* Contiguous */);
|
|
218
|
+
let discontiguousDistrictIDs = contiguousTest['details']['discontiguousDistricts'] || [];
|
|
198
219
|
// Convert them into a (possibly empty) list of features
|
|
199
220
|
let discontiguousDistrictFeatures = { type: 'FeatureCollection', features: [] };
|
|
200
221
|
if (!(U.isArrayEmpty(discontiguousDistrictIDs))) {
|
|
201
222
|
for (let id of discontiguousDistrictIDs) {
|
|
202
223
|
let poly = this.districts.getDistrictShapeByID(id);
|
|
203
|
-
if (poly)
|
|
204
|
-
|
|
205
|
-
// it will be a Multipolygon, i.e., it will have multiple pieces, some
|
|
206
|
-
// possibly embedded w/in other districts. Get & add all the pieces.
|
|
207
|
-
const districtParts = geofeature_1.polyParts(poly);
|
|
208
|
-
discontiguousDistrictFeatures.features.push(...districtParts.features);
|
|
209
|
-
// discontiguousDistrictFeatures.features.push(poly);
|
|
210
|
-
}
|
|
224
|
+
if (poly)
|
|
225
|
+
discontiguousDistrictFeatures.features.push(poly);
|
|
211
226
|
}
|
|
212
227
|
}
|
|
213
228
|
return discontiguousDistrictFeatures;
|
|
214
229
|
}
|
|
215
|
-
// Comments clipped from dra-client geodistrict.ts.
|
|
216
|
-
// Discontiguous polygons are:
|
|
217
|
-
// 1. All polygons in a multi-polygon; and
|
|
218
|
-
// 2. All holes in a otherwise cohesive polygon.
|
|
219
|
-
// Note that all non-cohesive features are always simple polygons.
|
|
220
|
-
/*
|
|
221
|
-
let i: number, j: number;
|
|
222
|
-
let nPoly: number = 0;
|
|
223
|
-
for (i = 0;nPoly == 0 && i < this.cacheDistricts.features.length;i++)
|
|
224
|
-
{
|
|
225
|
-
let f = this.cacheDistricts.features[i];
|
|
226
|
-
|
|
227
|
-
if (f.geometry.type === 'MultiPolygon')
|
|
228
|
-
nPoly += f.geometry.coordinates.length;
|
|
229
|
-
else if (f.geometry.type === 'Polygon' && f.geometry.coordinates.length)
|
|
230
|
-
nPoly += (f.geometry.coordinates.length - 1);
|
|
231
|
-
}
|
|
232
|
-
if (nPoly)
|
|
233
|
-
{
|
|
234
|
-
this.cacheNoncohesive = {type: 'FeatureCollection', features: []};
|
|
235
|
-
let af: any = this.cacheNoncohesive.features;
|
|
236
|
-
let oUnique: any = {};
|
|
237
|
-
|
|
238
|
-
// First add discontiguous polygons
|
|
239
|
-
for (i = 0;i < this.cacheDistricts.features.length;i++)
|
|
240
|
-
{
|
|
241
|
-
let f = this.cacheDistricts.features[i];
|
|
242
|
-
|
|
243
|
-
if (f.geometry.type === 'MultiPolygon')
|
|
244
|
-
{
|
|
245
|
-
// Push all non-contiguous polygons
|
|
246
|
-
for (j = 0;j < f.geometry.coordinates.length;j++)
|
|
247
|
-
{
|
|
248
|
-
let p: any = f.geometry.coordinates[j];
|
|
249
|
-
oUnique[Hash.qhash(p[0])] = true;
|
|
250
|
-
af.push({type: 'Feature', properties: {id: `${af.length + 1}`}, geometry: {type: 'Polygon', coordinates: p}});
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Now add unique holes
|
|
256
|
-
for (i = 0;i < this.cacheDistricts.features.length;i++)
|
|
257
|
-
{
|
|
258
|
-
let f = this.cacheDistricts.features[i];
|
|
259
|
-
|
|
260
|
-
if (f.geometry.type === 'Polygon')
|
|
261
|
-
{
|
|
262
|
-
// Push all holes from this polygon
|
|
263
|
-
for (j = 1;j < f.geometry.coordinates.length;j++)
|
|
264
|
-
{
|
|
265
|
-
let p: any = f.geometry.coordinates[j];
|
|
266
|
-
if (oUnique[Hash.qhash(p)] === undefined)
|
|
267
|
-
af.push({type: 'Feature', properties: {id: `${af.length + 1}`}, geometry: {type: 'Polygon', coordinates: [p]}});
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
} */
|
|
272
230
|
// HELPERS USED INTERNALLY
|
|
273
231
|
// Get an individual test, so you can drive UI with the results.
|
|
274
232
|
getTest(testID) {
|
|
@@ -410,7 +368,7 @@ class Districts {
|
|
|
410
368
|
nMissingDataset = 0;
|
|
411
369
|
nMissingProperty = 0;
|
|
412
370
|
// Compute these once per recalc cycle
|
|
413
|
-
let targetSize = this._session.state.totalPop / this._session.state.nDistricts;
|
|
371
|
+
let targetSize = Math.round(this._session.state.totalPop / this._session.state.nDistricts);
|
|
414
372
|
let deviationThreshold = this._session.populationDeviationThreshold();
|
|
415
373
|
let planByDistrict = this._session.plan.byDistrictID();
|
|
416
374
|
let plan = this._session.plan;
|
|
@@ -462,6 +420,7 @@ class Districts {
|
|
|
462
420
|
let outerThis = this;
|
|
463
421
|
// Default the pop dev % for the dummy Unassigned district to 0%.
|
|
464
422
|
// Default the pop dev % for real (1–N) but empty districts to 100%.
|
|
423
|
+
// TODO - SCORE
|
|
465
424
|
let popDevPct = (i > 0) ? (targetSize / targetSize) : 0 / targetSize;
|
|
466
425
|
// Get the geoIDs assigned to the district
|
|
467
426
|
// Guard against empty districts
|
|
@@ -488,6 +447,7 @@ class Districts {
|
|
|
488
447
|
// NOTE - SPLITTING
|
|
489
448
|
// Total population by counties w/in a district,
|
|
490
449
|
// except the dummy unassigned district 0
|
|
450
|
+
// TODO - VFEATURE
|
|
491
451
|
if (i > 0)
|
|
492
452
|
countySplits[outerThis.getCountyIndex(geoID)] += featurePop;
|
|
493
453
|
// Democratic and Republican vote totals
|
|
@@ -661,8 +621,10 @@ class Districts {
|
|
|
661
621
|
compact_1.extractDistrictProperties(this._session, bLog);
|
|
662
622
|
}
|
|
663
623
|
getCountyIndex(geoID) {
|
|
664
|
-
|
|
665
|
-
let countyFIPS = U.
|
|
624
|
+
// TODO - VFEATURE
|
|
625
|
+
let countyFIPS = U.parseGeoID(geoID)['county'];
|
|
626
|
+
// let countyGeoID = U.parseGeoID(geoID)['county'] as string;
|
|
627
|
+
// let countyFIPS = U.getFIPSFromCountyGeoID(countyGeoID);
|
|
666
628
|
let countyIndex = this._session.counties.indexFromFIPS(countyFIPS);
|
|
667
629
|
return countyIndex;
|
|
668
630
|
}
|
|
@@ -679,8 +641,9 @@ class Features {
|
|
|
679
641
|
nFeatures() { return this._data.features.length; }
|
|
680
642
|
featureByIndex(i) { return this._data.features[i]; }
|
|
681
643
|
geoIDForFeature(f) {
|
|
644
|
+
// TODO - 2020
|
|
682
645
|
// GEOIDs will be one of these properties
|
|
683
|
-
|
|
646
|
+
const value = f.properties['GEOID10'] || f.properties['GEOID20'] || f.properties['GEOID'];
|
|
684
647
|
return value;
|
|
685
648
|
}
|
|
686
649
|
fieldForFeature(f, dt, fk) {
|
|
@@ -1461,6 +1424,7 @@ function doPolsbyPopper(s, bLog = false) {
|
|
|
1461
1424
|
}
|
|
1462
1425
|
exports.doPolsbyPopper = doPolsbyPopper;
|
|
1463
1426
|
// HELPER TO EXTRACT PROPERTIES OF DISTRICT SHAPES
|
|
1427
|
+
// TODO - SCORE: Create an array, as opposed to a dict
|
|
1464
1428
|
function extractDistrictProperties(s, bLog = false) {
|
|
1465
1429
|
// NOTE - I am assuming that district IDs are integers 1–N
|
|
1466
1430
|
for (let i = 1; i <= s.state.nDistricts; i++) {
|
|
@@ -1619,23 +1583,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
1619
1583
|
};
|
|
1620
1584
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1621
1585
|
const Poly = __importStar(__webpack_require__(/*! @dra2020/poly */ "@dra2020/poly"));
|
|
1622
|
-
// HELPER
|
|
1623
|
-
function polyParts(poly) {
|
|
1624
|
-
let parts = { type: 'FeatureCollection', features: [] };
|
|
1625
|
-
let af = parts.features;
|
|
1626
|
-
if (poly.geometry.type === 'MultiPolygon') {
|
|
1627
|
-
// Push all non-contiguous polygons
|
|
1628
|
-
for (let j = 0; j < poly.geometry.coordinates.length; j++) {
|
|
1629
|
-
let onePoly = poly.geometry.coordinates[j];
|
|
1630
|
-
af.push({ type: 'Feature', properties: { id: `${af.length + 1}` }, geometry: { type: 'Polygon', coordinates: onePoly } });
|
|
1631
|
-
}
|
|
1632
|
-
}
|
|
1633
|
-
else {
|
|
1634
|
-
parts.features.push(poly);
|
|
1635
|
-
}
|
|
1636
|
-
return parts;
|
|
1637
|
-
}
|
|
1638
|
-
exports.polyParts = polyParts;
|
|
1639
1586
|
// CARTESIAN SHIMS OVER 'POLY' FUNCTIONS
|
|
1640
1587
|
// TODO - POLY: Confirm Cartesian calculations
|
|
1641
1588
|
function gfArea(poly) {
|
|
@@ -1961,8 +1908,10 @@ function doPreprocessCensus(s, bLog = false) {
|
|
|
1961
1908
|
// Sum total population across the state
|
|
1962
1909
|
s.state.totalPop += value;
|
|
1963
1910
|
// Get the county FIPS code for the feature
|
|
1964
|
-
|
|
1965
|
-
let countyFIPS = U.
|
|
1911
|
+
// TODO - VFEATURE
|
|
1912
|
+
let countyFIPS = U.parseGeoID(geoID)['county'];
|
|
1913
|
+
// let county = U.parseGeoID(geoID)['county'] as string;
|
|
1914
|
+
// let countyFIPS = U.getFIPSFromCountyGeoID(county);
|
|
1966
1915
|
// If a subtotal for the county doesn't exist, initialize one
|
|
1967
1916
|
if (!(U.keyExists(countyFIPS, totalByCounty))) {
|
|
1968
1917
|
totalByCounty[countyFIPS] = 0;
|
|
@@ -1980,7 +1929,7 @@ function doPreprocessCensus(s, bLog = false) {
|
|
|
1980
1929
|
let fipsCodes = U.getObjectKeys(totalByCounty);
|
|
1981
1930
|
// Sort the results
|
|
1982
1931
|
fipsCodes = fipsCodes.sort();
|
|
1983
|
-
//
|
|
1932
|
+
// TODO - SCORE: This was added for SPLITTING
|
|
1984
1933
|
// Add a dummy county, for county-district splitting analysis
|
|
1985
1934
|
fipsCodes.unshift('000');
|
|
1986
1935
|
// Create the ID-ordinal map
|
|
@@ -2067,7 +2016,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
2067
2016
|
};
|
|
2068
2017
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2069
2018
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
2070
|
-
const S = __importStar(__webpack_require__(/*! ./settings */ "./src/settings.ts"));
|
|
2071
2019
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
2072
2020
|
const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
2073
2021
|
const state_reqs_json_1 = __importDefault(__webpack_require__(/*! ../static/state-reqs.json */ "./static/state-reqs.json"));
|
|
@@ -2139,7 +2087,7 @@ let samplePartisan = {
|
|
|
2139
2087
|
planScore: "https://planscore.org/plan.html?20180219T202039.596761160Z"
|
|
2140
2088
|
}
|
|
2141
2089
|
};
|
|
2142
|
-
// TODO -
|
|
2090
|
+
// TODO - SCORE: Add a minority report
|
|
2143
2091
|
let sampleMinority = {
|
|
2144
2092
|
score: null,
|
|
2145
2093
|
metrics: {
|
|
@@ -2174,7 +2122,233 @@ exports.samplePlanAnalytics = {
|
|
|
2174
2122
|
partisan: samplePartisan,
|
|
2175
2123
|
minority: sampleMinority
|
|
2176
2124
|
};
|
|
2177
|
-
|
|
2125
|
+
/* TODO - SCORE
|
|
2126
|
+
export function preparePlanAnalytics(s: AnalyticsSession, bLog: boolean = false): PlanAnalytics
|
|
2127
|
+
{
|
|
2128
|
+
if (!(s.bPostProcessingDone))
|
|
2129
|
+
{
|
|
2130
|
+
doAnalyzePostProcessing(s);
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
// REQUIREMENTS CATEGORY
|
|
2134
|
+
let paRequirements: RequirementsCategory;
|
|
2135
|
+
|
|
2136
|
+
{
|
|
2137
|
+
let completeTest = s.getTest(T.Test.Complete) as T.TestEntry;
|
|
2138
|
+
let contiguousTest = s.getTest(T.Test.Contiguous) as T.TestEntry;
|
|
2139
|
+
let freeOfHolesTest = s.getTest(T.Test.FreeOfHoles) as T.TestEntry;
|
|
2140
|
+
let equalPopulationTest = s.getTest(T.Test.EqualPopulation) as T.TestEntry;
|
|
2141
|
+
|
|
2142
|
+
// Combine individual checks into an overall score
|
|
2143
|
+
|
|
2144
|
+
// TODO - DASHBOARD: Until we add three-state support top to bottom in
|
|
2145
|
+
// requirements/validations, map booleans to tri-states here.
|
|
2146
|
+
let completeMetric = U.mapBooleanToTriState(completeTest['score'] as boolean);
|
|
2147
|
+
let contiguousMetric = U.mapBooleanToTriState(contiguousTest['score'] as boolean);
|
|
2148
|
+
let freeOfHolesMetric = U.mapBooleanToTriState(freeOfHolesTest['score'] as boolean);
|
|
2149
|
+
let equalPopulationMetric = U.mapBooleanToTriState(equalPopulationTest['score'] as boolean);
|
|
2150
|
+
|
|
2151
|
+
let reqScore: T.TriState = T.TriState.Green;
|
|
2152
|
+
let checks = [completeMetric, contiguousMetric, freeOfHolesMetric, equalPopulationMetric];
|
|
2153
|
+
if (checks.includes(T.TriState.Yellow)) reqScore = T.TriState.Yellow;
|
|
2154
|
+
if (checks.includes(T.TriState.Red)) reqScore = T.TriState.Red;
|
|
2155
|
+
|
|
2156
|
+
// Get values to support details entries
|
|
2157
|
+
let unassignedFeaturesDetail = U.deepCopy(completeTest['details']['unassignedFeatures']) || [];
|
|
2158
|
+
let emptyDistrictsDetail = U.deepCopy(completeTest['details']['emptyDistricts']) || [];
|
|
2159
|
+
let discontiguousDistrictsDetail = U.deepCopy(contiguousTest['details']['discontiguousDistricts']) || [];
|
|
2160
|
+
let embeddedDistrictsDetail = U.deepCopy(freeOfHolesTest['details']['embeddedDistricts']) || [];
|
|
2161
|
+
|
|
2162
|
+
let populationDeviationDetail = U.deepCopy(equalPopulationTest['details']['deviation']);
|
|
2163
|
+
let deviationThresholdDetail = U.trim(s.populationDeviationThreshold());
|
|
2164
|
+
|
|
2165
|
+
let xx: string = s.state.xx;
|
|
2166
|
+
// TODO - JSON: Is there a better / easier way to work with the variable?
|
|
2167
|
+
let stateReqsDict: T.Dict = allStateReqs;
|
|
2168
|
+
let reqLinkToStateReqs: string = stateReqsDict[xx];
|
|
2169
|
+
|
|
2170
|
+
// Populate the category
|
|
2171
|
+
paRequirements = {
|
|
2172
|
+
score: reqScore,
|
|
2173
|
+
metrics: {
|
|
2174
|
+
complete: completeMetric,
|
|
2175
|
+
contiguous: contiguousMetric,
|
|
2176
|
+
freeOfHoles: freeOfHolesMetric,
|
|
2177
|
+
equalPopulation: equalPopulationMetric
|
|
2178
|
+
},
|
|
2179
|
+
details: {
|
|
2180
|
+
unassignedFeatures: unassignedFeaturesDetail,
|
|
2181
|
+
emptyDistricts: emptyDistrictsDetail,
|
|
2182
|
+
discontiguousDistricts: discontiguousDistrictsDetail,
|
|
2183
|
+
embeddedDistricts: embeddedDistrictsDetail,
|
|
2184
|
+
populationDeviation: populationDeviationDetail,
|
|
2185
|
+
deviationThreshold: deviationThresholdDetail
|
|
2186
|
+
},
|
|
2187
|
+
datasets: {
|
|
2188
|
+
census: U.deepCopy(s.config['descriptions']['CENSUS']),
|
|
2189
|
+
},
|
|
2190
|
+
resources: {
|
|
2191
|
+
stateReqs: reqLinkToStateReqs
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2196
|
+
// COMPACTNESS CATEGORY
|
|
2197
|
+
let paCompactness: CompactnessCategory;
|
|
2198
|
+
{
|
|
2199
|
+
let reockWeight = 0.5;
|
|
2200
|
+
let polsbyWeight = 1.0 - reockWeight;
|
|
2201
|
+
|
|
2202
|
+
let reockTest = s.getTest(T.Test.Reock) as T.TestEntry;
|
|
2203
|
+
let polsbyTest = s.getTest(T.Test.PolsbyPopper) as T.TestEntry;
|
|
2204
|
+
|
|
2205
|
+
let normalizedReock = reockTest['normalizedScore'] as number;
|
|
2206
|
+
let normalizedPolsby = reockTest['normalizedScore'] as number;
|
|
2207
|
+
let compactnessScore = U.trim((reockWeight * normalizedReock) + (polsbyWeight * normalizedPolsby), 0);
|
|
2208
|
+
|
|
2209
|
+
let reockMetric = U.deepCopy(reockTest['score'] as number);
|
|
2210
|
+
let polsbyMetric = U.deepCopy(polsbyTest['score'] as number);
|
|
2211
|
+
|
|
2212
|
+
// Populate the category
|
|
2213
|
+
paCompactness = {
|
|
2214
|
+
score: compactnessScore,
|
|
2215
|
+
metrics: {
|
|
2216
|
+
reock: reockMetric,
|
|
2217
|
+
polsby: polsbyMetric
|
|
2218
|
+
},
|
|
2219
|
+
details: {
|
|
2220
|
+
// None at this time
|
|
2221
|
+
},
|
|
2222
|
+
datasets: {
|
|
2223
|
+
// NOTE - DATASETS
|
|
2224
|
+
shapes: U.deepCopy(s.config['descriptions']['SHAPES'])
|
|
2225
|
+
// shapes: "2010 VTD shapes"
|
|
2226
|
+
},
|
|
2227
|
+
resources: {
|
|
2228
|
+
// None at this time
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
// SPLITTING CATEGORY
|
|
2234
|
+
|
|
2235
|
+
let paSplitting: SplittingCategory
|
|
2236
|
+
|
|
2237
|
+
{
|
|
2238
|
+
let unexpectedCountySplittingTest = s.getTest(T.Test.UnexpectedCountySplits) as T.TestEntry;
|
|
2239
|
+
let VTDSplitsTest = s.getTest(T.Test.VTDSplits) as T.TestEntry;
|
|
2240
|
+
let countySplittingTest = s.getTest(T.Test.CountySplitting) as T.TestEntry;
|
|
2241
|
+
let districtSplittingTest = s.getTest(T.Test.DistrictSplitting) as T.TestEntry;
|
|
2242
|
+
|
|
2243
|
+
let unexpectedAffectedMetric = U.deepCopy(unexpectedCountySplittingTest['score']);
|
|
2244
|
+
let countiesSplitUnexpectedlyDetail = U.deepCopy(unexpectedCountySplittingTest['details']['countiesSplitUnexpectedly']);
|
|
2245
|
+
|
|
2246
|
+
let nVTDSplitsMetric = U.deepCopy(VTDSplitsTest['score']);
|
|
2247
|
+
let splitVTDsDetail = U.deepCopy(VTDSplitsTest['details']['splitVTDs']);
|
|
2248
|
+
|
|
2249
|
+
let SqEnt_DCreducedMetric = U.deepCopy(countySplittingTest['score']);
|
|
2250
|
+
let SqEnt_CDreducedMetric = U.deepCopy(districtSplittingTest['score']);
|
|
2251
|
+
|
|
2252
|
+
let countySplittingNormalized = countySplittingTest['normalizedScore'] as number;
|
|
2253
|
+
let districtSplittingNormalized = districtSplittingTest['normalizedScore'] as number;
|
|
2254
|
+
let splittingScore = U.trim((S.COUNTY_SPLITTING_WEIGHT * countySplittingNormalized) +
|
|
2255
|
+
+ (S.DISTRICT_SPLITTING_WEIGHT * districtSplittingNormalized), 0);
|
|
2256
|
+
|
|
2257
|
+
paSplitting = {
|
|
2258
|
+
score: splittingScore,
|
|
2259
|
+
metrics: {
|
|
2260
|
+
sqEnt_DCreduced: SqEnt_DCreducedMetric,
|
|
2261
|
+
sqEnt_CDreduced: SqEnt_CDreducedMetric
|
|
2262
|
+
// NOTE - The un-reduced raw values
|
|
2263
|
+
// sqEnt_DC : SqEnt_DCMetric,
|
|
2264
|
+
// sqEnt_CD : SqEnt_CDMetric
|
|
2265
|
+
},
|
|
2266
|
+
details: {
|
|
2267
|
+
countiesSplitUnexpectedly: countiesSplitUnexpectedlyDetail,
|
|
2268
|
+
unexpectedAffected: unexpectedAffectedMetric,
|
|
2269
|
+
nSplitVTDs: nVTDSplitsMetric,
|
|
2270
|
+
splitVTDs: splitVTDsDetail
|
|
2271
|
+
},
|
|
2272
|
+
datasets: {
|
|
2273
|
+
// None at this time
|
|
2274
|
+
},
|
|
2275
|
+
resources: {
|
|
2276
|
+
// None at this time
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
// PARTISAN CATEGORY
|
|
2282
|
+
//
|
|
2283
|
+
// TODO - PARTISAN: This category is still being fleshed out. Just an example below.
|
|
2284
|
+
let paPartisan: PartisanCategory;
|
|
2285
|
+
|
|
2286
|
+
{
|
|
2287
|
+
paPartisan = {
|
|
2288
|
+
score: 100,
|
|
2289
|
+
metrics: {
|
|
2290
|
+
partisanBias: 0.15,
|
|
2291
|
+
responsiveness: 2.0
|
|
2292
|
+
},
|
|
2293
|
+
details: {},
|
|
2294
|
+
datasets: {
|
|
2295
|
+
election: "2016 Presidential, US Senate, Governor, and AG election results"
|
|
2296
|
+
},
|
|
2297
|
+
resources: {
|
|
2298
|
+
planScore: "https://planscore.org/plan.html?20180219T202039.596761160Z"
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
|
|
2303
|
+
// MINORITY CATEGORY
|
|
2304
|
+
//
|
|
2305
|
+
// TODO - MINORITY: This category is still being fleshed out. Just an example below.
|
|
2306
|
+
let paMinority: MinorityCategory;
|
|
2307
|
+
|
|
2308
|
+
{
|
|
2309
|
+
paMinority = {
|
|
2310
|
+
score: null,
|
|
2311
|
+
metrics: {
|
|
2312
|
+
nBlack37to50: 1,
|
|
2313
|
+
nBlackMajority: 12,
|
|
2314
|
+
nHispanic37to50: 0,
|
|
2315
|
+
nHispanicMajority: 0,
|
|
2316
|
+
nPacific37to50: 0,
|
|
2317
|
+
nPacificMajority: 0,
|
|
2318
|
+
nAsian37to50: 0,
|
|
2319
|
+
nAsianMajority: 0,
|
|
2320
|
+
nNative37to50: 0,
|
|
2321
|
+
nNativeMajority: 0,
|
|
2322
|
+
nMinority37to50: 0,
|
|
2323
|
+
nMinorityMajority: 0,
|
|
2324
|
+
|
|
2325
|
+
averageDVoteShare: 0.90
|
|
2326
|
+
},
|
|
2327
|
+
details: {
|
|
2328
|
+
vap: true,
|
|
2329
|
+
comboCategories: true
|
|
2330
|
+
},
|
|
2331
|
+
datasets: {
|
|
2332
|
+
vap: "2010 Voting Age Population"
|
|
2333
|
+
},
|
|
2334
|
+
resources: {}
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
// PLAN ANALYTICS
|
|
2339
|
+
let pa: PlanAnalytics = {
|
|
2340
|
+
requirements: paRequirements,
|
|
2341
|
+
compactness: paCompactness,
|
|
2342
|
+
// TODO - Not implemented yet
|
|
2343
|
+
splitting: paSplitting,
|
|
2344
|
+
partisan: paPartisan,
|
|
2345
|
+
minority: paMinority
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
return pa;
|
|
2349
|
+
}
|
|
2350
|
+
*/
|
|
2351
|
+
function prepareRequirementsChecklist(s, bLog = false) {
|
|
2178
2352
|
if (!(s.bPostProcessingDone)) {
|
|
2179
2353
|
doAnalyzePostProcessing(s);
|
|
2180
2354
|
}
|
|
@@ -2234,142 +2408,9 @@ function preparePlanAnalytics(s, bLog = false) {
|
|
|
2234
2408
|
}
|
|
2235
2409
|
};
|
|
2236
2410
|
}
|
|
2237
|
-
|
|
2238
|
-
let paCompactness;
|
|
2239
|
-
{
|
|
2240
|
-
let reockWeight = 0.5;
|
|
2241
|
-
let polsbyWeight = 1.0 - reockWeight;
|
|
2242
|
-
let reockTest = s.getTest(5 /* Reock */);
|
|
2243
|
-
let polsbyTest = s.getTest(6 /* PolsbyPopper */);
|
|
2244
|
-
let normalizedReock = reockTest['normalizedScore'];
|
|
2245
|
-
let normalizedPolsby = reockTest['normalizedScore'];
|
|
2246
|
-
let compactnessScore = U.trim((reockWeight * normalizedReock) + (polsbyWeight * normalizedPolsby), 0);
|
|
2247
|
-
let reockMetric = U.deepCopy(reockTest['score']);
|
|
2248
|
-
let polsbyMetric = U.deepCopy(polsbyTest['score']);
|
|
2249
|
-
// Populate the category
|
|
2250
|
-
paCompactness = {
|
|
2251
|
-
score: compactnessScore,
|
|
2252
|
-
metrics: {
|
|
2253
|
-
reock: reockMetric,
|
|
2254
|
-
polsby: polsbyMetric
|
|
2255
|
-
},
|
|
2256
|
-
details: {
|
|
2257
|
-
// None at this time
|
|
2258
|
-
},
|
|
2259
|
-
datasets: {
|
|
2260
|
-
// NOTE - DATASETS
|
|
2261
|
-
shapes: U.deepCopy(s.config['descriptions']['SHAPES'])
|
|
2262
|
-
// shapes: "2010 VTD shapes"
|
|
2263
|
-
},
|
|
2264
|
-
resources: {
|
|
2265
|
-
// None at this time
|
|
2266
|
-
}
|
|
2267
|
-
};
|
|
2268
|
-
}
|
|
2269
|
-
// SPLITTING CATEGORY
|
|
2270
|
-
let paSplitting;
|
|
2271
|
-
{
|
|
2272
|
-
let unexpectedCountySplittingTest = s.getTest(7 /* UnexpectedCountySplits */);
|
|
2273
|
-
let VTDSplitsTest = s.getTest(10 /* VTDSplits */);
|
|
2274
|
-
let countySplittingTest = s.getTest(8 /* CountySplitting */);
|
|
2275
|
-
let districtSplittingTest = s.getTest(9 /* DistrictSplitting */);
|
|
2276
|
-
let unexpectedAffectedMetric = U.deepCopy(unexpectedCountySplittingTest['score']);
|
|
2277
|
-
let countiesSplitUnexpectedlyDetail = U.deepCopy(unexpectedCountySplittingTest['details']['countiesSplitUnexpectedly']);
|
|
2278
|
-
let nVTDSplitsMetric = U.deepCopy(VTDSplitsTest['score']);
|
|
2279
|
-
let splitVTDsDetail = U.deepCopy(VTDSplitsTest['details']['splitVTDs']);
|
|
2280
|
-
let SqEnt_DCreducedMetric = U.deepCopy(countySplittingTest['score']);
|
|
2281
|
-
let SqEnt_CDreducedMetric = U.deepCopy(districtSplittingTest['score']);
|
|
2282
|
-
let countySplittingNormalized = countySplittingTest['normalizedScore'];
|
|
2283
|
-
let districtSplittingNormalized = districtSplittingTest['normalizedScore'];
|
|
2284
|
-
let splittingScore = U.trim((S.COUNTY_SPLITTING_WEIGHT * countySplittingNormalized) +
|
|
2285
|
-
+(S.DISTRICT_SPLITTING_WEIGHT * districtSplittingNormalized), 0);
|
|
2286
|
-
paSplitting = {
|
|
2287
|
-
score: splittingScore,
|
|
2288
|
-
metrics: {
|
|
2289
|
-
sqEnt_DCreduced: SqEnt_DCreducedMetric,
|
|
2290
|
-
sqEnt_CDreduced: SqEnt_CDreducedMetric
|
|
2291
|
-
// NOTE - The un-reduced raw values
|
|
2292
|
-
// sqEnt_DC : SqEnt_DCMetric,
|
|
2293
|
-
// sqEnt_CD : SqEnt_CDMetric
|
|
2294
|
-
},
|
|
2295
|
-
details: {
|
|
2296
|
-
countiesSplitUnexpectedly: countiesSplitUnexpectedlyDetail,
|
|
2297
|
-
unexpectedAffected: unexpectedAffectedMetric,
|
|
2298
|
-
nSplitVTDs: nVTDSplitsMetric,
|
|
2299
|
-
splitVTDs: splitVTDsDetail
|
|
2300
|
-
},
|
|
2301
|
-
datasets: {
|
|
2302
|
-
// None at this time
|
|
2303
|
-
},
|
|
2304
|
-
resources: {
|
|
2305
|
-
// None at this time
|
|
2306
|
-
}
|
|
2307
|
-
};
|
|
2308
|
-
}
|
|
2309
|
-
// PARTISAN CATEGORY
|
|
2310
|
-
//
|
|
2311
|
-
// TODO - PARTISAN: This category is still being fleshed out. Just an example below.
|
|
2312
|
-
let paPartisan;
|
|
2313
|
-
{
|
|
2314
|
-
paPartisan = {
|
|
2315
|
-
score: 100,
|
|
2316
|
-
metrics: {
|
|
2317
|
-
partisanBias: 0.15,
|
|
2318
|
-
responsiveness: 2.0
|
|
2319
|
-
},
|
|
2320
|
-
details: {},
|
|
2321
|
-
datasets: {
|
|
2322
|
-
election: "2016 Presidential, US Senate, Governor, and AG election results"
|
|
2323
|
-
},
|
|
2324
|
-
resources: {
|
|
2325
|
-
planScore: "https://planscore.org/plan.html?20180219T202039.596761160Z"
|
|
2326
|
-
}
|
|
2327
|
-
};
|
|
2328
|
-
}
|
|
2329
|
-
// MINORITY CATEGORY
|
|
2330
|
-
//
|
|
2331
|
-
// TODO - MINORITY: This category is still being fleshed out. Just an example below.
|
|
2332
|
-
let paMinority;
|
|
2333
|
-
{
|
|
2334
|
-
paMinority = {
|
|
2335
|
-
score: null,
|
|
2336
|
-
metrics: {
|
|
2337
|
-
nBlack37to50: 1,
|
|
2338
|
-
nBlackMajority: 12,
|
|
2339
|
-
nHispanic37to50: 0,
|
|
2340
|
-
nHispanicMajority: 0,
|
|
2341
|
-
nPacific37to50: 0,
|
|
2342
|
-
nPacificMajority: 0,
|
|
2343
|
-
nAsian37to50: 0,
|
|
2344
|
-
nAsianMajority: 0,
|
|
2345
|
-
nNative37to50: 0,
|
|
2346
|
-
nNativeMajority: 0,
|
|
2347
|
-
nMinority37to50: 0,
|
|
2348
|
-
nMinorityMajority: 0,
|
|
2349
|
-
averageDVoteShare: 0.90
|
|
2350
|
-
},
|
|
2351
|
-
details: {
|
|
2352
|
-
vap: true,
|
|
2353
|
-
comboCategories: true
|
|
2354
|
-
},
|
|
2355
|
-
datasets: {
|
|
2356
|
-
vap: "2010 Voting Age Population"
|
|
2357
|
-
},
|
|
2358
|
-
resources: {}
|
|
2359
|
-
};
|
|
2360
|
-
}
|
|
2361
|
-
// PLAN ANALYTICS
|
|
2362
|
-
let pa = {
|
|
2363
|
-
requirements: paRequirements,
|
|
2364
|
-
compactness: paCompactness,
|
|
2365
|
-
// TODO - Not implemented yet
|
|
2366
|
-
splitting: paSplitting,
|
|
2367
|
-
partisan: paPartisan,
|
|
2368
|
-
minority: paMinority
|
|
2369
|
-
};
|
|
2370
|
-
return pa;
|
|
2411
|
+
return paRequirements;
|
|
2371
2412
|
}
|
|
2372
|
-
exports.
|
|
2413
|
+
exports.prepareRequirementsChecklist = prepareRequirementsChecklist;
|
|
2373
2414
|
// Example
|
|
2374
2415
|
exports.sampleDistrictStatistics = {
|
|
2375
2416
|
table: [
|
|
@@ -2625,6 +2666,127 @@ function doAnalyzePostProcessing(s, bLog = false) {
|
|
|
2625
2666
|
exports.doAnalyzePostProcessing = doAnalyzePostProcessing;
|
|
2626
2667
|
|
|
2627
2668
|
|
|
2669
|
+
/***/ }),
|
|
2670
|
+
|
|
2671
|
+
/***/ "./src/score.ts":
|
|
2672
|
+
/*!**********************!*\
|
|
2673
|
+
!*** ./src/score.ts ***!
|
|
2674
|
+
\**********************/
|
|
2675
|
+
/*! no static exports found */
|
|
2676
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
2677
|
+
|
|
2678
|
+
"use strict";
|
|
2679
|
+
|
|
2680
|
+
//
|
|
2681
|
+
// SCORING
|
|
2682
|
+
//
|
|
2683
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
2684
|
+
if (mod && mod.__esModule) return mod;
|
|
2685
|
+
var result = {};
|
|
2686
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
2687
|
+
result["default"] = mod;
|
|
2688
|
+
return result;
|
|
2689
|
+
};
|
|
2690
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2691
|
+
const Score = __importStar(__webpack_require__(/*! @dra2020/dra-score */ "@dra2020/dra-score"));
|
|
2692
|
+
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
2693
|
+
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
2694
|
+
// PROFILE A PLAN
|
|
2695
|
+
function profilePlan(s, bLog = false) {
|
|
2696
|
+
const state = s.state.xx;
|
|
2697
|
+
const planName = s.title;
|
|
2698
|
+
const nDistricts = s.state.nDistricts;
|
|
2699
|
+
const nCounties = s.counties.nCounties;
|
|
2700
|
+
const targetSize = Math.round(s.state.totalPop / nDistricts);
|
|
2701
|
+
const popByDistrict = U.deepCopy(s.districts.statistics[D.DistrictField.TotalPop].slice(1, -1));
|
|
2702
|
+
const geoPropsByDistrict = makeArrayOfGeoProps(s, bLog);
|
|
2703
|
+
const splits = makeNakedCxD(s);
|
|
2704
|
+
const summaryRow = s.districts.numberOfRows() - 1;
|
|
2705
|
+
const statewideVf = s.districts.statistics[D.DistrictField.DemPct][summaryRow];
|
|
2706
|
+
const vpiArray = U.deepCopy(s.districts.statistics[D.DistrictField.DemPct].slice(1, -1));
|
|
2707
|
+
const demographicsByDistrict = makeArrayOfDemographics(s);
|
|
2708
|
+
const profile = {
|
|
2709
|
+
state: state,
|
|
2710
|
+
planName: planName,
|
|
2711
|
+
nDistricts: nDistricts,
|
|
2712
|
+
nCounties: nCounties,
|
|
2713
|
+
legislativeDistricts: s.legislativeDistricts,
|
|
2714
|
+
populationProfile: {
|
|
2715
|
+
TotalPopByDistrict: popByDistrict,
|
|
2716
|
+
targetSize: targetSize
|
|
2717
|
+
},
|
|
2718
|
+
compactnessProfile: {
|
|
2719
|
+
GeometryByDistrict: geoPropsByDistrict
|
|
2720
|
+
},
|
|
2721
|
+
splittingProfile: {
|
|
2722
|
+
CountyPopByDistrict: splits
|
|
2723
|
+
},
|
|
2724
|
+
partisanProfile: {
|
|
2725
|
+
statewideVf: statewideVf,
|
|
2726
|
+
VfArray: vpiArray
|
|
2727
|
+
},
|
|
2728
|
+
demographicProfile: {
|
|
2729
|
+
DemographicsByDistrict: demographicsByDistrict
|
|
2730
|
+
}
|
|
2731
|
+
};
|
|
2732
|
+
return profile;
|
|
2733
|
+
}
|
|
2734
|
+
exports.profilePlan = profilePlan;
|
|
2735
|
+
// NOTE - The CxD splits structure from _data.ts includes dummy districts for
|
|
2736
|
+
// unassigned precincts & state summary and an extra 0 county. But dra-score takes
|
|
2737
|
+
// a simple 1–D x 1–C splits array (zero-based, of course).
|
|
2738
|
+
function makeNakedCxD(s, bLog = false) {
|
|
2739
|
+
const adornedCxD = s.districts.statistics[D.DistrictField.CountySplits];
|
|
2740
|
+
let CxD = [];
|
|
2741
|
+
// Remove the unassigned & total dummy "districts"
|
|
2742
|
+
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++) {
|
|
2743
|
+
// TODO - SCORE: OH has an extra county!?!
|
|
2744
|
+
const splits = U.deepCopy(adornedCxD[districtID].slice(1));
|
|
2745
|
+
CxD.push(splits);
|
|
2746
|
+
}
|
|
2747
|
+
return CxD;
|
|
2748
|
+
}
|
|
2749
|
+
// TODO - SCORE: Convert dict of geo props to array by district index
|
|
2750
|
+
function makeArrayOfGeoProps(s, bLog = false) {
|
|
2751
|
+
let geometryByDistrict = [];
|
|
2752
|
+
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++) {
|
|
2753
|
+
let districtProps = s.districts.getGeoProperties(districtID);
|
|
2754
|
+
// Guard against no shape and no properties
|
|
2755
|
+
if (districtProps) {
|
|
2756
|
+
let a = districtProps[0 /* Area */];
|
|
2757
|
+
let p = districtProps[2 /* Perimeter */];
|
|
2758
|
+
let d = districtProps[1 /* Diameter */];
|
|
2759
|
+
// Save each triple
|
|
2760
|
+
geometryByDistrict.push([a, p, d]);
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
return geometryByDistrict;
|
|
2764
|
+
}
|
|
2765
|
+
function makeArrayOfDemographics(s, bLog = false) {
|
|
2766
|
+
let demographicsArray = [];
|
|
2767
|
+
// Remove the unassigned & total dummy "districts"
|
|
2768
|
+
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++) {
|
|
2769
|
+
const districtDemographics = [
|
|
2770
|
+
U.deepCopy(s.districts.statistics[D.DistrictField.WhitePct][districtID]),
|
|
2771
|
+
U.deepCopy(s.districts.statistics[D.DistrictField.MinorityPct][districtID]),
|
|
2772
|
+
U.deepCopy(s.districts.statistics[D.DistrictField.BlackPct][districtID]),
|
|
2773
|
+
U.deepCopy(s.districts.statistics[D.DistrictField.HispanicPct][districtID]),
|
|
2774
|
+
U.deepCopy(s.districts.statistics[D.DistrictField.PacificPct][districtID]),
|
|
2775
|
+
U.deepCopy(s.districts.statistics[D.DistrictField.AsianPct][districtID]),
|
|
2776
|
+
U.deepCopy(s.districts.statistics[D.DistrictField.NativePct][districtID])
|
|
2777
|
+
];
|
|
2778
|
+
demographicsArray.push(districtDemographics);
|
|
2779
|
+
}
|
|
2780
|
+
return demographicsArray;
|
|
2781
|
+
}
|
|
2782
|
+
// SCORE A PLAN
|
|
2783
|
+
function scorePlan(p, bLog = false) {
|
|
2784
|
+
let scorer = new Score.Scorer();
|
|
2785
|
+
return scorer.score(p);
|
|
2786
|
+
}
|
|
2787
|
+
exports.scorePlan = scorePlan;
|
|
2788
|
+
|
|
2789
|
+
|
|
2628
2790
|
/***/ }),
|
|
2629
2791
|
|
|
2630
2792
|
/***/ "./src/settings.ts":
|
|
@@ -2675,6 +2837,10 @@ exports.DISTRICT_SPLITTING_WEIGHT = 1.0 - exports.COUNTY_SPLITTING_WEIGHT;
|
|
|
2675
2837
|
// TYPE DEFINITIONS
|
|
2676
2838
|
//
|
|
2677
2839
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2840
|
+
// TODO - SCORE
|
|
2841
|
+
var dra_score_1 = __webpack_require__(/*! @dra2020/dra-score */ "@dra2020/dra-score");
|
|
2842
|
+
exports.sampleProfile = dra_score_1.sampleProfile;
|
|
2843
|
+
exports.sampleScorecard = dra_score_1.sampleScorecard;
|
|
2678
2844
|
// END
|
|
2679
2845
|
|
|
2680
2846
|
|
|
@@ -2727,27 +2893,50 @@ function getDistrict(plan, geoID) {
|
|
|
2727
2893
|
}
|
|
2728
2894
|
exports.getDistrict = getDistrict;
|
|
2729
2895
|
// WORKING WITH GEOIDS
|
|
2896
|
+
// TODO - VFEATURE
|
|
2730
2897
|
function parseGeoID(geoID) {
|
|
2731
|
-
let
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
if (
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
}
|
|
2898
|
+
let bVfeature = false;
|
|
2899
|
+
// Rewrite vfeature GEOIDs to enable lexical parsing of higher-level parts
|
|
2900
|
+
// Template: vfeature_{geoid}_{chunk}_hash
|
|
2901
|
+
// Example: vfeature_39153153ASV_0_28e0bc2c8163e5982e1da2d61e2388a8325c575e
|
|
2902
|
+
if (geoID.indexOf('vfeature') >= 0) {
|
|
2903
|
+
bVfeature = true;
|
|
2904
|
+
// Strip off leading 'vfeature_'
|
|
2905
|
+
let parentGeoID = geoID.slice(9);
|
|
2906
|
+
// Strip off trailing goo
|
|
2907
|
+
const uPos = parentGeoID.indexOf('_');
|
|
2908
|
+
parentGeoID = parentGeoID.slice(0, uPos);
|
|
2909
|
+
geoID = parentGeoID;
|
|
2910
|
+
}
|
|
2911
|
+
const parts = {
|
|
2912
|
+
vfeature: bVfeature,
|
|
2913
|
+
state: geoID.substring(0, 2),
|
|
2914
|
+
county: geoID.substring(2, 5),
|
|
2915
|
+
rest: geoID.slice(5)
|
|
2916
|
+
};
|
|
2917
|
+
// let l: number = geoID.length;
|
|
2918
|
+
// if (l >= 11)
|
|
2919
|
+
// {
|
|
2920
|
+
// parts['tract'] = geoID.substring(0, 11);
|
|
2921
|
+
// }
|
|
2922
|
+
// if (l >= 12)
|
|
2923
|
+
// {
|
|
2924
|
+
// parts['bg'] = geoID.substring(0, 12);
|
|
2925
|
+
// }
|
|
2926
|
+
// if (l == 15)
|
|
2927
|
+
// {
|
|
2928
|
+
// parts['block'] = geoID;
|
|
2929
|
+
// }
|
|
2744
2930
|
return parts;
|
|
2745
2931
|
}
|
|
2746
2932
|
exports.parseGeoID = parseGeoID;
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2933
|
+
// TODO - VFEATURE
|
|
2934
|
+
// export function getFIPSFromCountyGeoID(geoID: string): string
|
|
2935
|
+
// {
|
|
2936
|
+
// const fips = geoID.substring(2, 5);
|
|
2937
|
+
// if (isNaN(Number(fips))) console.log("Non-numeric GEOID =", geoID);
|
|
2938
|
+
// return fips;
|
|
2939
|
+
// }
|
|
2751
2940
|
function isWaterOnly(geoID) {
|
|
2752
2941
|
let waterOnlySignature = 'ZZZZZZ';
|
|
2753
2942
|
if (geoID.indexOf(waterOnlySignature) >= 0)
|
|
@@ -3186,6 +3375,17 @@ module.exports = JSON.parse("{\"AL\":\"https://www.brennancenter.org/sites/defau
|
|
|
3186
3375
|
|
|
3187
3376
|
/***/ }),
|
|
3188
3377
|
|
|
3378
|
+
/***/ "@dra2020/dra-score":
|
|
3379
|
+
/*!*************************************!*\
|
|
3380
|
+
!*** external "@dra2020/dra-score" ***!
|
|
3381
|
+
\*************************************/
|
|
3382
|
+
/*! no static exports found */
|
|
3383
|
+
/***/ (function(module, exports) {
|
|
3384
|
+
|
|
3385
|
+
module.exports = require("@dra2020/dra-score");
|
|
3386
|
+
|
|
3387
|
+
/***/ }),
|
|
3388
|
+
|
|
3189
3389
|
/***/ "@dra2020/poly":
|
|
3190
3390
|
/*!********************************!*\
|
|
3191
3391
|
!*** external "@dra2020/poly" ***!
|