@dra2020/dra-types 1.8.91 → 1.8.93

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.
@@ -1,4 +1,5 @@
1
1
  import { PlanType } from './dra-types';
2
+ import { DatasetMeta, DatasetsMeta } from './datasets';
2
3
  export declare const AGG_DEMOGRAPHIC = "demographic";
3
4
  export declare const AGG_DEMOGRAPHIC18 = "demographic18";
4
5
  export declare const AGG_pres2008 = "pres2008";
@@ -7,6 +8,7 @@ export declare const AGG_pvi = "pvi";
7
8
  export declare const DATASET_TYPE_DEMOGRAPHIC = "demographic";
8
9
  export declare const DATASET_TYPE_ELECTION = "election";
9
10
  export declare const DATASET_TYPE_PVI = "pvi";
11
+ export declare const DATASET_TYPE_OTHER = "other";
10
12
  export declare const DS_PVI2020 = "P20GPR";
11
13
  export declare const PVI2020_Title = "PVI 2016/2020";
12
14
  export declare const DS_PVI2016 = "P16GPR";
@@ -23,9 +25,10 @@ export interface StatesMetaIndex {
23
25
  export interface StatesMeta {
24
26
  [key: string]: StatesMetaIndex;
25
27
  }
26
- export type FieldGetter = (f: string) => number;
27
- export declare function fieldGetterNotLoaded(f: string): number;
28
- export type PackedFields = Float64Array;
28
+ export type PackedFieldsArray = Float64Array;
29
+ export type PackedFields = {
30
+ [datasetid: string]: PackedFieldsArray;
31
+ };
29
32
  export interface PackedFieldsIndex {
30
33
  [field: string]: number;
31
34
  }
@@ -36,25 +39,8 @@ export interface PackedMetaIndex {
36
39
  };
37
40
  getDatasetField: (f: any, dataset: string, field: string) => number;
38
41
  }
39
- export interface DatasetMeta {
40
- type: string;
41
- year: number;
42
- title: string;
43
- fields: {
44
- [key: string]: any;
45
- };
46
- votingAge?: boolean;
47
- office?: string;
48
- subtype?: string;
49
- description?: string;
50
- nhAlone?: boolean;
51
- privateKey?: string;
52
- members?: {
53
- [key: number]: string;
54
- };
55
- }
56
- export type DatasetsMeta = {
57
- [dataset: string]: DatasetMeta;
42
+ export type GroupPackedMetaIndex = {
43
+ [datasetid: string]: PackedMetaIndex;
58
44
  };
59
45
  export interface PrimaryDatasetKeys {
60
46
  SHAPES?: string;
@@ -63,7 +49,7 @@ export interface PrimaryDatasetKeys {
63
49
  ELECTION: string;
64
50
  }
65
51
  export interface DatasetContext {
66
- dsIndex: PackedMetaIndex;
52
+ dsIndex: GroupPackedMetaIndex;
67
53
  primeDDS: string;
68
54
  primeVDS: string;
69
55
  primeEDS: string;
@@ -85,19 +71,29 @@ export type DSLists = {
85
71
  export type PlanTypePlus = PlanType | '';
86
72
  export declare function fGetJoined(f: any): any[];
87
73
  export declare function fGet(f: any, p: string): any;
88
- export declare function computeMetaIndex(meta: DatasetsMeta): PackedMetaIndex;
74
+ export declare function computeMetaIndex(datasetid: string, meta: DatasetsMeta): PackedMetaIndex;
89
75
  export declare function computePackedFields(f: any, index: PackedMetaIndex): PackedFields;
90
76
  export declare function hasPackedFields(f: any): boolean;
91
77
  export declare function setPackedFields(f: any, pf: PackedFields, fIndex: any): void;
78
+ export declare function isExtDataset(did: string): boolean;
79
+ export type ExtPackedFields = Uint32Array;
80
+ export type ExtBlockCardinality = Map<string, number>;
81
+ export declare function featurePushExtPackedFields(f: any, datasetid: string, data: ExtPackedFields, card: ExtBlockCardinality): void;
82
+ export declare function featurePushedExtPackedFields(f: any, datasetid: string, card: ExtBlockCardinality): boolean;
83
+ export declare function pushedExtPackedFields(pf: PackedFields, datasetids: string[]): boolean;
92
84
  export declare function retrievePackedFields(f: any): PackedFields;
93
- export declare function zeroPackedFields(index: PackedMetaIndex): PackedFields;
85
+ export declare function zeroPackedFields(index: GroupPackedMetaIndex): PackedFields;
94
86
  export declare function zeroPackedCopy(pf: PackedFields): PackedFields;
95
87
  export declare function packedCopy(pf: PackedFields): PackedFields;
96
88
  export declare function aggregatePackedFields(agg: PackedFields, pf: PackedFields): PackedFields;
89
+ export declare function aggregateCount(agg: PackedFields): number;
90
+ export declare function decrementPackedFields(agg: PackedFields, pf: PackedFields): PackedFields;
97
91
  export declare function diffPackedFields(main: any, parts: any[]): PackedFields;
98
- export declare function getPackedField(index: PackedMetaIndex, pf: PackedFields, dataset: string, field: string): number;
99
- export declare function findPackedField(index: PackedMetaIndex, pf: PackedFields, dataset: string, field: string): number;
100
- export declare function ToGetter(agg: PackedFields, dc: DatasetContext, datasetKey: string): FieldGetter;
92
+ export declare function getPackedField(index: GroupPackedMetaIndex, pf: PackedFields, datasetid: string, dataset: string, field: string): number;
93
+ export declare function findPackedField(index: GroupPackedMetaIndex, pf: PackedFields, datasetid: string, dataset: string, field: string): number;
94
+ export type FieldGetter = (f: string) => number;
95
+ export declare function fieldGetterNotLoaded(f: string): number;
96
+ export declare function ToGetter(agg: PackedFields, dc: DatasetContext, datasetid: string, datasetKey: string): FieldGetter;
101
97
  export declare function ToGetterPvi16(agg: PackedFields, dc: DatasetContext, datasetKey: string): FieldGetter;
102
98
  export declare function ToGetterPvi20(agg: PackedFields, dc: DatasetContext): FieldGetter;
103
99
  export declare function calcShift(agg: PackedFields, dc: DatasetContext, datasetOld: string, datasetNew: string): number;
package/lib/alldt.ts CHANGED
@@ -11,4 +11,5 @@ export * from './landmark';
11
11
  export * from './splittogeofeature';
12
12
  export * from './reverse';
13
13
  export * from './groups';
14
+ export * from './datasets';
14
15
  export * from './precincts';
package/lib/colormgr.ts CHANGED
@@ -172,7 +172,7 @@ export function ToAllEthnicColor(agg: PF.PackedFields, dc: PF.DatasetContext, pd
172
172
  {
173
173
  // Use VAP/CVAP if it exists
174
174
  const dataset: string = dc.primeVDS ? dc.primeVDS : dc.primeDDS
175
- return AggregateEthnicColor(PF.ToGetter(agg, dc, dataset), pd, dataset.endsWith('NH'));
175
+ return AggregateEthnicColor(PF.ToGetter(agg, dc, '', dataset), pd, dataset.endsWith('NH'));
176
176
  }
177
177
 
178
178
  export function ToPartisanColorStr(agg: PF.PackedFields, dc: PF.DatasetContext, pd: PaletteDefaults): string
@@ -189,8 +189,8 @@ function ToPartisanColor(agg: PF.PackedFields, dc: PF.DatasetContext, stops: Uti
189
189
  {
190
190
  if (dc.primeEDS === PF.DS_PVI2020)
191
191
  {
192
- const getter16 = PF.ToGetter(agg, dc, PF.DS_PRES2016);
193
- const getter20 = PF.ToGetter(agg, dc, PF.DS_PRES2020);
192
+ const getter16 = PF.ToGetter(agg, dc, '', PF.DS_PRES2016);
193
+ const getter20 = PF.ToGetter(agg, dc, '', PF.DS_PRES2020);
194
194
 
195
195
  const pviRaw = PF.calcRaw2020Pvi(getter16, getter20);
196
196
  const color: string = ColorFromRGBPcts((1 - pviRaw / 100), 0, pviRaw / 100, stops);
@@ -199,14 +199,14 @@ function ToPartisanColor(agg: PF.PackedFields, dc: PF.DatasetContext, stops: Uti
199
199
  }
200
200
  else if (dc.primeEDS === PF.DS_PVI2016)
201
201
  {
202
- const getter = PF.ToGetter(agg, dc, dc.primeEDS);
202
+ const getter = PF.ToGetter(agg, dc, '', dc.primeEDS);
203
203
  const pviRaw = PF.calcRawPvi(getter);
204
204
  const color: string = ColorFromRGBPcts((1 - pviRaw/100), 0, pviRaw/100, stops);
205
205
  return color;
206
206
  }
207
207
  else
208
208
  {
209
- const getter = PF.ToGetter(agg, dc, dc.primeEDS);
209
+ const getter = PF.ToGetter(agg, dc, '', dc.primeEDS);
210
210
  return AggregatePartisanColorStr(getter, stops);
211
211
  }
212
212
  }
@@ -251,7 +251,7 @@ export function ToEthnicColorStr(agg: PF.PackedFields, dc: PF.DatasetContext, pd
251
251
  default: break;
252
252
  }
253
253
 
254
- const getter = PF.ToGetter(agg, dc, dataset);
254
+ const getter = PF.ToGetter(agg, dc, '', dataset);
255
255
  let den = getter(total);
256
256
  let num = getter(ethnic);
257
257
  if (den === undefined || isNaN(den) || num === undefined || isNaN(num))
@@ -0,0 +1,55 @@
1
+ // For use in UI. Keys are used in JSON.
2
+ export interface DatasetField
3
+ {
4
+ shortCaption: string, // Typically 2-4 letters
5
+ longCaption: string, // Can be longer descriptive phrase, especially for combinations
6
+ order?: number, // For ordering fields in UI
7
+ isCombo?: boolean, // Built-in, for census combos
8
+ }
9
+ export function sortFields(f1: DatasetField, f2: DatasetField): number
10
+ {
11
+ return (f1.order || 0) - (f2.order || 0);
12
+ }
13
+
14
+ // For Partisan fields, expect keys of 'D', 'R' and 'Tot'
15
+ // For Demographic Fields, expect keys of 'Tot', 'Wh', 'Bl', 'His', 'AsnPI', 'Nat', 'Oth',
16
+ // 'Asn', 'Pac', 'OthAl', 'Mix', 'BlC', 'NatC', 'AsnC', 'PacC',
17
+ export type DatasetFields = { [key: string]: DatasetField };
18
+
19
+ export interface DatasetMeta
20
+ {
21
+ type: string, // demographic | election | pvi | other
22
+ year: number, // 4 digit year
23
+ title: string, // title displayed in UI
24
+ description?: string, // longer description
25
+ office?: string, // pres | comp | sc | sen | con | tre | sos | ltgov | gov | ag
26
+ subtype?: string, // always general?
27
+ votingAge?: boolean, // Filtered demographic variant
28
+ nhAlone?: boolean, // Demographic variant
29
+ privateKey?: string, // Old-style semi-private datasets
30
+ members?: { [key: number]: string }, // For composites, specifies
31
+ fields?: DatasetFields,
32
+ }
33
+
34
+ export type DatasetsMeta = { [dataset: string]: DatasetMeta };
35
+
36
+ // Database Record
37
+ export interface Dataset
38
+ {
39
+ id: string,
40
+ name?: string,
41
+ description?: string,
42
+ createdBy?: string,
43
+ createTime?: string,
44
+ modifyTime?: string,
45
+ deleted?: boolean,
46
+ published?: string,
47
+ official?: boolean,
48
+ state?: string,
49
+ datasource?: string,
50
+ dotmap?: boolean,
51
+ meta?: DatasetsMeta,
52
+ }
53
+
54
+ // Index of database records
55
+ export type DatasetIndex = { [id: string]: Dataset };
@@ -29,6 +29,8 @@ import { PlanType } from './dra-types';
29
29
  // Mix: Two or more races, not Hispanic
30
30
  // AsnPI: Asian + Pacific, not Hispanic
31
31
 
32
+ import { DatasetMeta, DatasetsMeta } from './datasets';
33
+
32
34
 
33
35
  export const AGG_DEMOGRAPHIC = 'demographic';
34
36
  export const AGG_DEMOGRAPHIC18 = 'demographic18';
@@ -39,6 +41,7 @@ export const AGG_pvi = 'pvi';
39
41
  export const DATASET_TYPE_DEMOGRAPHIC = 'demographic';
40
42
  export const DATASET_TYPE_ELECTION = 'election';
41
43
  export const DATASET_TYPE_PVI = 'pvi';
44
+ export const DATASET_TYPE_OTHER = 'other';
42
45
 
43
46
  export const DS_PVI2020 = 'P20GPR';
44
47
  export const PVI2020_Title = 'PVI 2016/2020';
@@ -63,9 +66,8 @@ export interface StatesMeta
63
66
  [key: string]: StatesMetaIndex; // key is one of the datasource strings
64
67
  }
65
68
 
66
- export type FieldGetter = (f: string) => number;
67
- export function fieldGetterNotLoaded(f: string): number { return undefined }
68
- export type PackedFields = Float64Array;
69
+ export type PackedFieldsArray = Float64Array;
70
+ export type PackedFields = { [datasetid: string]: PackedFieldsArray };
69
71
  export interface PackedFieldsIndex
70
72
  {
71
73
  [field: string]: number; // offset into PackedFields
@@ -78,23 +80,7 @@ export interface PackedMetaIndex
78
80
  getDatasetField: (f: any, dataset: string, field: string) => number;
79
81
  }
80
82
 
81
- export interface DatasetMeta
82
- {
83
- type: string,
84
- year: number,
85
- title: string,
86
- fields: {
87
- [key: string]: any,
88
- },
89
- votingAge?: boolean,
90
- office?: string,
91
- subtype?: string,
92
- description?: string,
93
- nhAlone?: boolean,
94
- privateKey?: string, // key for private data
95
- members?: {[key: number]: string},
96
- }
97
- export type DatasetsMeta = { [dataset: string]: DatasetMeta };
83
+ export type GroupPackedMetaIndex = { [datasetid: string]: PackedMetaIndex };
98
84
 
99
85
  export interface PrimaryDatasetKeys
100
86
  {
@@ -108,7 +94,7 @@ export interface PrimaryDatasetKeys
108
94
  // well as user selections around which datasets to view. Used to propagate through UI.
109
95
  export interface DatasetContext
110
96
  {
111
- dsIndex: PackedMetaIndex;
97
+ dsIndex: GroupPackedMetaIndex;
112
98
  primeDDS: string; // Demographic (Census)
113
99
  primeVDS: string; // VAP/CVAP
114
100
  primeEDS: string; // Election
@@ -189,7 +175,7 @@ function fGetW(f: any, datasetKey: string, p: string): any
189
175
  return undefined;
190
176
  }
191
177
 
192
- export function computeMetaIndex(meta: DatasetsMeta): PackedMetaIndex
178
+ export function computeMetaIndex(datasetid: string, meta: DatasetsMeta): PackedMetaIndex
193
179
  {
194
180
  if (meta == null) return null;
195
181
  let offset = 1; // first entry is count of aggregates
@@ -202,21 +188,22 @@ export function computeMetaIndex(meta: DatasetsMeta): PackedMetaIndex
202
188
  });
203
189
  index.fields[datasetKey] = fieldsIndex;
204
190
  });
191
+ let groupindex = { [datasetid]: index };
205
192
  index.length = offset;
206
193
  index.getDatasetField = (f: any, dataset: string, field: string): number => {
207
194
  let pf = retrievePackedFields(f);
208
- return getPackedField(index, pf, dataset, field);
195
+ return getPackedField(groupindex, pf, datasetid, dataset, field);
209
196
  };
210
197
  return index;
211
198
  }
212
199
 
213
200
  let nAlloc = 0;
214
- function allocPackedFields(length: number): PackedFields
201
+ function allocPackedFieldsArray(length: number): PackedFieldsArray
215
202
  {
216
203
  let ab = new ArrayBuffer(8 * length);
217
204
  let af = new Float64Array(ab);
218
205
  nAlloc++;
219
- //if ((nAlloc % 10000) == 0) console.log(`allocPackedFields: ${nAlloc} allocs`);
206
+ //if ((nAlloc % 10000) == 0) console.log(`allocPackedFieldsArray: ${nAlloc} allocs`);
220
207
  return af;
221
208
  }
222
209
 
@@ -224,7 +211,7 @@ export function computePackedFields(f: any, index: PackedMetaIndex): PackedField
224
211
  {
225
212
  if (f.properties.packedFields) return f.properties.packedFields as PackedFields;
226
213
 
227
- let af = allocPackedFields(index.length);
214
+ let af = allocPackedFieldsArray(index.length);
228
215
  af[0] = 0; // count of number of aggregates
229
216
  Object.keys(index.fields).forEach((dataset: string) => {
230
217
  let fields = index.fields[dataset];
@@ -235,12 +222,12 @@ export function computePackedFields(f: any, index: PackedMetaIndex): PackedField
235
222
  af[fields[field]] = n;
236
223
  });
237
224
  });
238
- f.properties.packedFields = af; // cache here
225
+ f.properties.packedFields = { ['']: af }; // cache here
239
226
  f.properties.getDatasetField = index.getDatasetField;
240
227
 
241
228
  // Major memory savings to delete this after packing
242
229
  delete f.properties.datasets;
243
- return af;
230
+ return f.properties.packedFields;
244
231
  }
245
232
 
246
233
  export function hasPackedFields(f: any): boolean
@@ -255,6 +242,60 @@ export function setPackedFields(f: any, pf: PackedFields, fIndex: any): void
255
242
  f.properties.getDatasetField = fIndex.properties.getDatasetField
256
243
  }
257
244
 
245
+ const reExtDataset = /^.*\.ds$/;
246
+ export function isExtDataset(did: string): boolean
247
+ {
248
+ return did && reExtDataset.test(did);
249
+ }
250
+
251
+ export type ExtPackedFields = Uint32Array; // [nblocks][nfields][fields]...
252
+ export type ExtBlockCardinality = Map<string, number>;
253
+
254
+ export function featurePushExtPackedFields(f: any, datasetid: string, data: ExtPackedFields, card: ExtBlockCardinality): void
255
+ {
256
+ let blocks = f?.properties?.blocks || (card.has(f.properties.id) ? [ f.properties.id ] : null);
257
+ if (!blocks)
258
+ return;
259
+ if (!f.properties.packedFields)
260
+ throw('pushExtPackedFields: base datasets should be pushed first');
261
+ if (card.size != data[0])
262
+ throw('pushExtPackedFields: packed fields and block cardinality do not match');
263
+ if (f.properties.packedFields[datasetid])
264
+ return; // already pushed
265
+ let nfields = data[1];
266
+ let pfa = allocPackedFieldsArray(nfields+1); // field count
267
+ pfa[0] = 0;
268
+ for (let j = 0; j < nfields; j++) pfa[j] = 0;
269
+ blocks.forEach((blockid: string) => {
270
+ if (! card.has(blockid))
271
+ throw(`pushExtPackedFields: missing blockid ${blockid} in cardinality set`);
272
+ let x = 2 + (nfields * card.get(blockid));
273
+ for (let i = 1; i <= nfields; i++)
274
+ pfa[i] += data[x++];
275
+ });
276
+ f.properties.packedFields[datasetid] = pfa;
277
+ }
278
+
279
+ export function featurePushedExtPackedFields(f: any, datasetid: string, card: ExtBlockCardinality): boolean
280
+ {
281
+ if (! f) return true;
282
+ if (f.features) return featurePushedExtPackedFields(f.features[0], datasetid, card);
283
+ if (!f?.properties?.blocks && !card.has(f.properties.id))
284
+ return true;
285
+ if (!f.properties.packedFields)
286
+ return true;
287
+ return !!f.properties.packedFields[datasetid];
288
+ }
289
+
290
+ export function pushedExtPackedFields(pf: PackedFields, datasetids: string[]): boolean
291
+ {
292
+ if (pf && datasetids)
293
+ for (let i = 0; i < datasetids.length; i++)
294
+ if (! pf[datasetids[i]])
295
+ return false;
296
+ return !!pf;
297
+ }
298
+
258
299
  export function retrievePackedFields(f: any): PackedFields
259
300
  {
260
301
  if (f.properties.packedFields === undefined) throw 'Feature should have pre-computed packed fields';
@@ -266,46 +307,85 @@ export function retrievePackedFields(f: any): PackedFields
266
307
  let abZero = new ArrayBuffer(8);
267
308
  let afZero = new Float64Array(abZero);
268
309
  afZero[0] = 0;
310
+ let pfZero = { ['']: afZero };
269
311
 
270
- export function zeroPackedFields(index: PackedMetaIndex): PackedFields
312
+ export function zeroPackedFields(index: GroupPackedMetaIndex): PackedFields
271
313
  {
272
- if (index == null) return afZero;
273
- let af = allocPackedFields(index.length);
274
- for (let i = 0; i < af.length; i++)
275
- af[i] = 0;
276
- return af;
314
+ if (index == null) return pfZero;
315
+ let pf: PackedFields = {};
316
+ Object.keys(index).forEach(datasetid => {
317
+ let af = allocPackedFieldsArray(index[datasetid].length);
318
+ for (let i = 0; i < af.length; i++)
319
+ af[i] = 0;
320
+ pf[datasetid] = af;
321
+ });
322
+ return pf;
277
323
  }
278
324
 
279
325
  export function zeroPackedCopy(pf: PackedFields): PackedFields
280
326
  {
281
- if (pf == null) return afZero;
282
- let af = allocPackedFields(pf.length);
283
- for (let i = 0; i < af.length; i++)
284
- af[i] = 0;
285
- return af;
327
+ if (pf == null) return pfZero;
328
+ let copy: PackedFields = {};
329
+ Object.keys(pf).forEach(datasetid => {
330
+ let cf = allocPackedFieldsArray(pf[datasetid].length);
331
+ for (let i = 0; i < cf.length; i++)
332
+ cf[i] = 0;
333
+ copy[datasetid] = cf;
334
+ });
335
+ return copy;
286
336
  }
287
337
 
288
338
  export function packedCopy(pf: PackedFields): PackedFields
289
339
  {
290
340
  if (pf == null) return null;
291
- let af = allocPackedFields(pf.length);
292
- for (let i = 0; i < pf.length; i++)
293
- af[i] = pf[i];
294
- return af;
341
+ let copy: PackedFields = {};
342
+ Object.keys(pf).forEach(datasetid => {
343
+ let af = pf[datasetid];
344
+ let cf = allocPackedFieldsArray(af.length);
345
+ for (let i = 0; i < af.length; i++)
346
+ cf[i] = af[i];
347
+ copy[datasetid] = cf;
348
+ });
349
+ return copy;
295
350
  }
296
351
 
297
352
  export function aggregatePackedFields(agg: PackedFields, pf: PackedFields): PackedFields
298
353
  {
299
354
  if (agg == null || pf == null) return agg;
300
- if (agg.length != pf.length)
301
- {
302
- return agg; // bug, but don't crash
303
- //throw 'aggregatePackedFields: unexpected length mismatch';
304
- }
305
- let n = agg.length;
306
- for (let i = 1; i < n; i++)
307
- agg[i] += pf[i];
308
- agg[0]++; // count of number of aggregates
355
+ Object.keys(agg).forEach(datasetid => {
356
+ let af = agg[datasetid];
357
+ let sf = pf[datasetid];
358
+ if (sf && sf.length == af.length)
359
+ {
360
+ let n = af.length;
361
+ for (let i = 1; i < n; i++)
362
+ af[i] += sf[i];
363
+ af[0]++; // count of aggregates
364
+ }
365
+ });
366
+ return agg;
367
+ }
368
+
369
+ export function aggregateCount(agg: PackedFields): number
370
+ {
371
+ if (!agg || !agg['']) return 0;
372
+ return agg[''][0];
373
+ }
374
+
375
+ export function decrementPackedFields(agg: PackedFields, pf: PackedFields): PackedFields
376
+ {
377
+ if (agg == null || pf == null) return agg;
378
+ Object.keys(agg).forEach(datasetid => {
379
+ let af = agg[datasetid];
380
+ let sf = pf[datasetid];
381
+ if (sf && sf.length == af.length)
382
+ {
383
+ let n = af.length;
384
+ for (let i = 1; i < n; i++)
385
+ af[i] -= sf[i];
386
+ af[0]++; // count of aggregates
387
+ }
388
+ });
309
389
  return agg;
310
390
  }
311
391
 
@@ -314,29 +394,30 @@ export function diffPackedFields(main: any, parts: any[]): PackedFields
314
394
  main = packedCopy(retrievePackedFields(main));
315
395
  if (main == null || parts == null || parts.length == 0) return null;
316
396
  parts = parts.map(retrievePackedFields);
317
- parts.forEach((pf: PackedFields) => {
318
- for (let i = 0; i < main.length; i++)
319
- main[i] -= pf[i];
320
- });
397
+ parts.forEach((pf: PackedFields) => decrementPackedFields(main, pf));
321
398
  return main;
322
399
  }
323
400
 
324
- export function getPackedField(index: PackedMetaIndex, pf: PackedFields, dataset: string, field: string): number
401
+ export function getPackedField(index: GroupPackedMetaIndex, pf: PackedFields, datasetid: string, dataset: string, field: string): number
325
402
  {
326
- if (index == null || pf == null) return 0;
327
- let fields = index.fields[dataset];
328
- return fields ? (fields[field] !== undefined ? pf[fields[field]] : 0) : 0;
403
+ if (!index || !pf || !index[datasetid] || !pf[datasetid]) return 0;
404
+ let fields = index[datasetid].fields[dataset];
405
+ return fields ? (fields[field] !== undefined ? pf[datasetid][fields[field]] : 0) : 0;
329
406
  }
330
407
 
331
- export function findPackedField(index: PackedMetaIndex, pf: PackedFields, dataset: string, field: string): number
408
+ export function findPackedField(index: GroupPackedMetaIndex, pf: PackedFields, datasetid: string, dataset: string, field: string): number
332
409
  {
333
- let fields = index.fields[dataset];
410
+ let fields = index[datasetid].fields[dataset];
334
411
  return fields ? (fields[field] !== undefined ? fields[field] : -1) : -1;
335
412
  }
336
413
 
337
- export function ToGetter(agg: PackedFields, dc: DatasetContext, datasetKey: string): FieldGetter
414
+ // Utility type to simplify code that pulls from same dataset to compute some composite
415
+ export type FieldGetter = (f: string) => number;
416
+ export function fieldGetterNotLoaded(f: string): number { return undefined }
417
+
418
+ export function ToGetter(agg: PackedFields, dc: DatasetContext, datasetid: string, datasetKey: string): FieldGetter
338
419
  {
339
- return (field: string) => { return getPackedField(dc.dsIndex, agg, datasetKey, field) };
420
+ return (field: string) => { return getPackedField(dc.dsIndex, agg, datasetid, datasetKey, field) };
340
421
  }
341
422
 
342
423
  export function ToGetterPvi16(agg: PackedFields, dc: DatasetContext, datasetKey: string): FieldGetter
@@ -344,13 +425,13 @@ export function ToGetterPvi16(agg: PackedFields, dc: DatasetContext, datasetKey:
344
425
  return (field: string) =>
345
426
  {
346
427
  if (field === 'R')
347
- return Math.round((getPackedField(dc.dsIndex, agg, datasetKey, 'R12') + getPackedField(dc.dsIndex, agg, datasetKey, 'R16')) / 2);
428
+ return Math.round((getPackedField(dc.dsIndex, agg, '', datasetKey, 'R12') + getPackedField(dc.dsIndex, agg, '', datasetKey, 'R16')) / 2);
348
429
  if (field === 'D')
349
- return Math.round((getPackedField(dc.dsIndex, agg, datasetKey, 'D12') + getPackedField(dc.dsIndex, agg, datasetKey, 'D16')) / 2);
430
+ return Math.round((getPackedField(dc.dsIndex, agg, '', datasetKey, 'D12') + getPackedField(dc.dsIndex, agg, '', datasetKey, 'D16')) / 2);
350
431
  if (field === 'Tot')
351
432
  return Math.round((
352
- getPackedField(dc.dsIndex, agg, datasetKey, 'R12') + getPackedField(dc.dsIndex, agg, datasetKey, 'R16') +
353
- getPackedField(dc.dsIndex, agg, datasetKey, 'D12') + getPackedField(dc.dsIndex, agg, datasetKey, 'D16')) / 2);
433
+ getPackedField(dc.dsIndex, agg, '', datasetKey, 'R12') + getPackedField(dc.dsIndex, agg, '', datasetKey, 'R16') +
434
+ getPackedField(dc.dsIndex, agg, '', datasetKey, 'D12') + getPackedField(dc.dsIndex, agg, '', datasetKey, 'D16')) / 2);
354
435
  return 0;
355
436
  };
356
437
  }
@@ -360,13 +441,13 @@ export function ToGetterPvi20(agg: PackedFields, dc: DatasetContext): FieldGette
360
441
  return (field: string) =>
361
442
  {
362
443
  if (field === 'R')
363
- return Math.round((getPackedField(dc.dsIndex, agg, DS_PRES2016, 'R') + getPackedField(dc.dsIndex, agg, DS_PRES2020, 'R')) / 2);
444
+ return Math.round((getPackedField(dc.dsIndex, agg, '', DS_PRES2016, 'R') + getPackedField(dc.dsIndex, agg, '', DS_PRES2020, 'R')) / 2);
364
445
  if (field === 'D')
365
- return Math.round((getPackedField(dc.dsIndex, agg, DS_PRES2016, 'D') + getPackedField(dc.dsIndex, agg, DS_PRES2020, 'D')) / 2);
446
+ return Math.round((getPackedField(dc.dsIndex, agg, '', DS_PRES2016, 'D') + getPackedField(dc.dsIndex, agg, '', DS_PRES2020, 'D')) / 2);
366
447
  if (field === 'Tot')
367
448
  return Math.round((
368
- getPackedField(dc.dsIndex, agg, DS_PRES2016, 'R') + getPackedField(dc.dsIndex, agg, DS_PRES2020, 'R') +
369
- getPackedField(dc.dsIndex, agg, DS_PRES2016, 'D') + getPackedField(dc.dsIndex, agg, DS_PRES2020, 'D')) / 2);
449
+ getPackedField(dc.dsIndex, agg, '', DS_PRES2016, 'R') + getPackedField(dc.dsIndex, agg, '', DS_PRES2020, 'R') +
450
+ getPackedField(dc.dsIndex, agg, '', DS_PRES2016, 'D') + getPackedField(dc.dsIndex, agg, '', DS_PRES2020, 'D')) / 2);
370
451
  return 0;
371
452
  };
372
453
 
@@ -378,12 +459,12 @@ export function calcShift(agg: PackedFields, dc: DatasetContext, datasetOld: str
378
459
  ToGetterPvi16(agg, dc, datasetOld) :
379
460
  datasetOld === DS_PVI2020 ?
380
461
  ToGetterPvi20(agg, dc) :
381
- ToGetter(agg, dc, datasetOld);
462
+ ToGetter(agg, dc, '', datasetOld);
382
463
  const getterNew = datasetNew === DS_PVI2016 ?
383
464
  ToGetterPvi16(agg, dc, datasetNew) :
384
465
  datasetNew === DS_PVI2020 ?
385
466
  ToGetterPvi20(agg, dc) :
386
- ToGetter(agg, dc, datasetNew);
467
+ ToGetter(agg, dc, '', datasetNew);
387
468
 
388
469
  // Calc two-party Swing
389
470
  const repOld = getterOld('R');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dra2020/dra-types",
3
- "version": "1.8.91",
3
+ "version": "1.8.93",
4
4
  "description": "Shared types used between client, server and tools.",
5
5
  "main": "dist/dra-types.js",
6
6
  "types": "./dist/all.d.ts",