triangle-utils 1.2.12 → 1.3.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.
@@ -0,0 +1,627 @@
1
+ import * as nodemailer from "nodemailer";
2
+ import * as crypto from "crypto";
3
+ const election_ids = new Set([
4
+ "2026-house-nc-11-election",
5
+ "2026-house-co-05-election",
6
+ "2026-house-il-01-election",
7
+ "2026-house-co-03-election",
8
+ "2026-house-pa-12-election",
9
+ "2026-house-nc-10-election",
10
+ "2026-house-fl-22-election",
11
+ "2026-house-fl-19-election",
12
+ "2026-house-ny-04-election",
13
+ "2026-house-tx-38-election",
14
+ "2026-house-pa-07-election",
15
+ "2026-house-ct-02-election",
16
+ "2026-house-tx-20-election",
17
+ "2026-house-or-01-election",
18
+ "2026-house-ca-42-election",
19
+ "2026-house-mi-05-election",
20
+ "2026-house-ne-01-election",
21
+ "2026-sen-ne-election",
22
+ "2026-house-nj-09-election",
23
+ "2026-house-nc-12-election",
24
+ "2026-house-nh-01-election",
25
+ "2026-house-ny-14-election",
26
+ "2026-house-ny-22-election",
27
+ "2026-sen-de-election",
28
+ "2026-house-nc-06-election",
29
+ "2026-house-fl-26-election",
30
+ "2026-house-az-04-election",
31
+ "2026-house-az-07-election",
32
+ "2026-house-nc-02-election",
33
+ "2026-house-vt-al-election",
34
+ "2026-house-in-06-election",
35
+ "2026-house-ca-19-election",
36
+ "2026-house-va-07-election",
37
+ "2026-house-ok-03-election",
38
+ "2026-house-ma-07-election",
39
+ "2026-house-fl-15-election",
40
+ "2026-sen-nh-election",
41
+ "2026-house-ks-03-election",
42
+ "2026-house-ga-02-election",
43
+ "2026-house-tx-09-election",
44
+ "2026-house-pa-08-election",
45
+ "2026-house-in-09-election",
46
+ "2026-house-la-05-election",
47
+ "2026-house-nj-10-election",
48
+ "2026-house-tx-36-election",
49
+ "2026-house-ky-04-election",
50
+ "2026-house-mo-01-election",
51
+ "2026-house-mn-07-election",
52
+ "2026-house-ri-01-election",
53
+ "2026-house-ny-01-election",
54
+ "2026-house-tx-23-election",
55
+ "2026-house-mt-01-election",
56
+ "2026-house-nv-01-election",
57
+ "2026-house-mn-01-election",
58
+ "2026-house-wa-10-election",
59
+ "2026-house-fl-18-election",
60
+ "2026-house-ky-01-election",
61
+ "2026-house-ga-06-election",
62
+ "2026-house-ny-10-election",
63
+ "2026-house-nj-05-election",
64
+ "2026-house-al-03-election",
65
+ "2026-house-mn-02-election",
66
+ "2026-house-sc-04-election",
67
+ "2026-house-tx-11-election",
68
+ "2026-house-mo-06-election",
69
+ "2026-house-tn-09-election",
70
+ "2026-house-il-04-election",
71
+ "2026-house-ca-40-election",
72
+ "2026-house-fl-27-election",
73
+ "2026-house-ok-01-election",
74
+ "2026-house-tx-07-election",
75
+ "2026-house-pa-15-election",
76
+ "2026-house-nm-01-election",
77
+ "2026-house-tx-04-election",
78
+ "2026-house-fl-13-election",
79
+ "2026-house-ny-11-election",
80
+ "2026-house-ga-09-election",
81
+ "2026-house-ca-37-election",
82
+ "2026-house-ca-43-election",
83
+ "2026-house-ca-39-election",
84
+ "2026-house-ca-38-election",
85
+ "2026-house-ga-03-election",
86
+ "2026-house-in-07-election",
87
+ "2026-house-ca-30-election",
88
+ "2026-house-il-08-election",
89
+ "2026-house-fl-14-election",
90
+ "2026-house-tx-13-election",
91
+ "2026-house-il-07-election",
92
+ "2026-sen-sc-election",
93
+ "2026-house-wy-al-election",
94
+ "2026-house-hi-02-election",
95
+ "2026-house-il-02-election",
96
+ "2026-house-fl-11-election",
97
+ "2026-house-az-02-election",
98
+ "2026-house-ca-02-election",
99
+ "2026-house-fl-12-election",
100
+ "2026-sen-ma-election",
101
+ "2026-sen-la-election",
102
+ "2026-house-va-09-election",
103
+ "2026-house-ms-02-election",
104
+ "2026-house-ca-08-election",
105
+ "2026-house-id-02-election",
106
+ "2026-house-tn-02-election",
107
+ "2026-sen-ri-election",
108
+ "2026-house-ia-04-election",
109
+ "2026-house-il-11-election",
110
+ "2026-sen-al-election",
111
+ "2026-house-ca-27-election",
112
+ "2026-house-sc-03-election",
113
+ "2026-sen-nc-election",
114
+ "2026-house-ar-01-election",
115
+ "2026-house-oh-02-election",
116
+ "2026-house-fl-04-election",
117
+ "2026-house-oh-08-election",
118
+ "2026-house-me-01-election",
119
+ "2026-house-ca-31-election",
120
+ "2026-house-nc-08-election",
121
+ "2026-house-tx-34-election",
122
+ "2026-house-oh-12-election",
123
+ "2026-house-tn-06-election",
124
+ "2026-house-oh-09-election",
125
+ "2026-house-ca-03-election",
126
+ "2026-house-nc-07-election",
127
+ "2026-house-ca-13-election",
128
+ "2026-house-ar-03-election",
129
+ "2026-house-ny-13-election",
130
+ "2026-house-ga-12-election",
131
+ "2026-sen-id-election",
132
+ "2026-house-nj-07-election",
133
+ "2026-sen-ga-election",
134
+ "2026-house-ny-05-election",
135
+ "2026-sen-mi-election",
136
+ "2026-house-ca-25-election",
137
+ "2026-house-va-03-election",
138
+ "2026-sen-ar-election",
139
+ "2026-sen-tx-election",
140
+ "2026-house-ca-09-election",
141
+ "2026-house-wa-08-election",
142
+ "2026-sen-tn-election",
143
+ "2026-house-ca-33-election",
144
+ "2026-house-ga-14-election",
145
+ "2026-house-ok-02-election",
146
+ "2026-house-fl-03-election",
147
+ "2026-house-id-01-election",
148
+ "2026-house-ca-16-election",
149
+ "2026-house-nc-13-election",
150
+ "2026-house-ms-01-election",
151
+ "2026-sen-mt-election",
152
+ "2026-house-nv-02-election",
153
+ "2026-house-ga-01-election",
154
+ "2026-house-mn-06-election",
155
+ "2026-house-ga-10-election",
156
+ "2026-house-or-05-election",
157
+ "2026-house-wi-04-election",
158
+ "2026-house-wi-07-election",
159
+ "2026-house-ks-04-election",
160
+ "2026-house-al-05-election",
161
+ "2026-house-oh-01-election",
162
+ "2026-house-al-07-election",
163
+ "2026-house-ne-02-election",
164
+ "2026-house-ca-18-election",
165
+ "2026-house-tx-32-election",
166
+ "2026-house-ca-44-election",
167
+ "2026-house-az-05-election",
168
+ "2026-house-al-01-election",
169
+ "2026-house-fl-20-election",
170
+ "2026-house-ma-05-election",
171
+ "2026-house-ca-34-election",
172
+ "2026-house-md-05-election",
173
+ "2026-house-ca-49-election",
174
+ "2026-house-ca-41-election",
175
+ "2026-house-tn-04-election",
176
+ "2026-house-tx-35-election",
177
+ "2026-house-co-07-election",
178
+ "2026-house-oh-13-election",
179
+ "2026-house-ny-24-election",
180
+ "2026-house-ca-36-election",
181
+ "2026-house-ga-11-election",
182
+ "2026-house-sc-01-election",
183
+ "2026-house-ca-20-election",
184
+ "2026-house-nj-12-election",
185
+ "2026-house-mi-13-election",
186
+ "2026-house-ca-29-election",
187
+ "2026-house-ma-03-election",
188
+ "2026-house-md-08-election",
189
+ "2026-house-md-06-election",
190
+ "2026-house-mi-01-election",
191
+ "2026-house-oh-11-election",
192
+ "2026-house-nv-03-election",
193
+ "2026-house-tx-01-election",
194
+ "2026-house-in-05-election",
195
+ "2026-house-ny-23-election",
196
+ "2026-house-co-01-election",
197
+ "2026-house-mi-12-election",
198
+ "2026-house-ia-02-election",
199
+ "2026-house-or-03-election",
200
+ "2026-house-ut-04-election",
201
+ "2026-house-ny-07-election",
202
+ "2026-house-ar-04-election",
203
+ "2026-sen-nm-election",
204
+ "2026-house-hi-01-election",
205
+ "2026-house-tx-15-election",
206
+ "2026-house-md-02-election",
207
+ "2026-house-mi-11-election",
208
+ "2026-house-ca-28-election",
209
+ "2026-house-oh-15-election",
210
+ "2026-house-mo-03-election",
211
+ "2026-house-ga-05-election",
212
+ "2026-house-mo-05-election",
213
+ "2026-house-tn-07-election",
214
+ "2026-house-in-01-election",
215
+ "2026-house-de-al-election",
216
+ "2026-house-wv-01-election",
217
+ "2026-house-co-04-election",
218
+ "2026-house-tx-10-election",
219
+ "2026-house-fl-17-election",
220
+ "2026-house-nd-al-election",
221
+ "2026-house-ny-21-election",
222
+ "2026-house-ky-05-election",
223
+ "2026-house-md-04-election",
224
+ "2026-house-oh-03-election",
225
+ "2026-house-sc-02-election",
226
+ "2026-house-ma-02-election",
227
+ "2026-house-fl-01-election",
228
+ "2026-house-ny-06-election",
229
+ "2026-house-il-12-election",
230
+ "2026-house-va-06-election",
231
+ "2026-house-tx-06-election",
232
+ "2026-house-ca-51-election",
233
+ "2026-house-ok-05-election",
234
+ "2026-house-va-08-election",
235
+ "2026-house-wv-02-election",
236
+ "2026-house-ca-32-election",
237
+ "2026-house-pa-11-election",
238
+ "2026-house-mn-05-election",
239
+ "2026-house-mn-04-election",
240
+ "2026-house-ca-26-election",
241
+ "2026-house-ca-10-election",
242
+ "2026-house-fl-23-election",
243
+ "2026-house-ca-04-election",
244
+ "2026-house-nc-01-election",
245
+ "2026-house-mn-08-election",
246
+ "2026-house-ny-12-election",
247
+ "2026-house-mn-03-election",
248
+ "2026-house-ms-04-election",
249
+ "2026-house-oh-06-election",
250
+ "2026-house-il-03-election",
251
+ "2026-house-mi-09-election",
252
+ "2026-house-tx-27-election",
253
+ "2026-house-ri-02-election",
254
+ "2026-house-co-06-election",
255
+ "2026-house-tx-21-election",
256
+ "2026-house-mt-02-election",
257
+ "2026-sen-or-election",
258
+ "2026-house-tn-01-election",
259
+ "2026-house-mi-10-election",
260
+ "2026-sen-ak-election",
261
+ "2026-house-ky-03-election",
262
+ "2026-house-ca-48-election",
263
+ "2026-house-tx-05-election",
264
+ "2026-house-il-05-election",
265
+ "2026-house-il-10-election",
266
+ "2026-house-ca-21-election",
267
+ "2026-house-tx-28-election",
268
+ "2026-house-pa-09-election",
269
+ "2026-sen-wv-election",
270
+ "2026-house-nh-02-election",
271
+ "2026-house-sc-07-election",
272
+ "2026-house-nj-04-election",
273
+ "2026-house-mi-08-election",
274
+ "2026-house-wa-09-election",
275
+ "2026-house-il-13-election",
276
+ "2026-house-ma-01-election",
277
+ "2026-house-tx-26-election",
278
+ "2026-house-mo-04-election",
279
+ "2026-house-ma-08-election",
280
+ "2026-house-tx-08-election",
281
+ "2026-house-la-01-election",
282
+ "2026-house-ny-09-election",
283
+ "2026-house-wa-01-election",
284
+ "2026-house-il-14-election",
285
+ "2026-house-ca-17-election",
286
+ "2026-house-wi-06-election",
287
+ "2026-house-tx-12-election",
288
+ "2026-house-fl-05-election",
289
+ "2026-house-oh-04-election",
290
+ "2026-sen-me-election",
291
+ "2026-house-ne-03-election",
292
+ "2026-sen-va-election",
293
+ "2026-house-ct-01-election",
294
+ "2026-house-tx-16-election",
295
+ "2026-house-il-06-election",
296
+ "2026-house-wa-02-election",
297
+ "2026-house-nc-09-election",
298
+ "2026-house-sc-06-election",
299
+ "2026-house-ut-01-election",
300
+ "2026-house-ca-15-election",
301
+ "2026-house-ky-06-election",
302
+ "2026-house-ca-14-election",
303
+ "2026-sen-wy-election",
304
+ "2026-sen-ks-election",
305
+ "2026-house-co-02-election",
306
+ "2026-house-az-09-election",
307
+ "2026-house-mi-07-election",
308
+ "2026-house-ny-08-election",
309
+ "2026-house-ga-04-election",
310
+ "2026-house-md-01-election",
311
+ "2026-house-or-02-election",
312
+ "2026-house-ca-22-election",
313
+ "2026-sen-fl-election",
314
+ "2026-sen-oh-election",
315
+ "2026-house-in-02-election",
316
+ "2026-house-fl-10-election",
317
+ "2026-house-az-06-election",
318
+ "2026-house-tx-14-election",
319
+ "2026-house-wi-01-election",
320
+ "2026-house-va-01-election",
321
+ "2026-house-in-03-election",
322
+ "2026-house-md-03-election",
323
+ "2026-house-ks-02-election",
324
+ "2026-house-ga-13-election",
325
+ "2026-house-fl-07-election",
326
+ "2026-house-tx-17-election",
327
+ "2026-house-va-04-election",
328
+ "2026-house-mi-03-election",
329
+ "2026-sen-ok-election",
330
+ "2026-house-nv-04-election",
331
+ "2026-house-sc-05-election",
332
+ "2026-house-pa-04-election",
333
+ "2026-house-ny-25-election",
334
+ "2026-house-il-16-election",
335
+ "2026-house-la-02-election",
336
+ "2026-house-fl-09-election",
337
+ "2026-house-in-04-election",
338
+ "2026-house-ca-45-election",
339
+ "2026-house-tx-33-election",
340
+ "2026-sen-ms-election",
341
+ "2026-house-al-06-election",
342
+ "2026-house-tx-19-election",
343
+ "2026-house-pa-05-election",
344
+ "2026-house-ny-16-election",
345
+ "2026-house-in-08-election",
346
+ "2026-house-nc-04-election",
347
+ "2026-house-or-06-election",
348
+ "2026-house-tx-02-election",
349
+ "2026-house-nc-14-election",
350
+ "2026-house-pa-14-election",
351
+ "2026-house-nm-03-election",
352
+ "2026-house-ct-05-election",
353
+ "2026-house-il-09-election",
354
+ "2026-house-va-10-election",
355
+ "2026-house-ca-06-election",
356
+ "2026-house-ms-03-election",
357
+ "2026-house-fl-08-election",
358
+ "2026-house-ga-07-election",
359
+ "2026-house-tx-03-election",
360
+ "2026-house-ca-46-election",
361
+ "2026-house-pa-06-election",
362
+ "2026-house-oh-05-election",
363
+ "2026-house-va-11-election",
364
+ "2026-house-tx-22-election",
365
+ "2026-house-nj-06-election",
366
+ "2026-house-tn-05-election",
367
+ "2026-house-ny-20-election",
368
+ "2026-house-oh-14-election",
369
+ "2026-house-ia-01-election",
370
+ "2026-house-fl-02-election",
371
+ "2026-house-al-02-election",
372
+ "2026-house-ia-03-election",
373
+ "2026-house-me-02-election",
374
+ "2026-house-va-02-election",
375
+ "2026-house-nj-02-election",
376
+ "2026-house-wi-05-election",
377
+ "2026-house-ar-02-election",
378
+ "2026-house-tn-08-election",
379
+ "2026-house-ca-52-election",
380
+ "2026-house-ok-04-election",
381
+ "2026-sen-mn-election",
382
+ "2026-sen-sd-election",
383
+ "2026-house-ca-47-election",
384
+ "2026-house-ca-50-election",
385
+ "2026-house-ny-26-election",
386
+ "2026-house-la-03-election",
387
+ "2026-house-mo-07-election",
388
+ "2026-house-la-06-election",
389
+ "2026-house-pa-17-election",
390
+ "2026-house-wa-04-election",
391
+ "2026-house-tn-03-election",
392
+ "2026-house-nj-01-election",
393
+ "2026-sen-ky-election",
394
+ "2026-house-tx-29-election",
395
+ "2026-house-fl-25-election",
396
+ "2026-house-ny-19-election",
397
+ "2026-house-nc-03-election",
398
+ "2026-house-ak-al-election",
399
+ "2026-house-or-04-election",
400
+ "2026-sen-nj-election",
401
+ "2026-house-mi-02-election",
402
+ "2026-house-ny-18-election",
403
+ "2026-house-ny-17-election",
404
+ "2026-house-ca-07-election",
405
+ "2026-house-tx-30-election",
406
+ "2026-house-pa-01-election",
407
+ "2026-house-nm-02-election",
408
+ "2026-house-wa-07-election",
409
+ "2026-house-ca-11-election",
410
+ "2026-house-tx-37-election",
411
+ "2026-house-il-17-election",
412
+ "2026-house-tx-31-election",
413
+ "2026-house-fl-16-election",
414
+ "2026-house-nc-05-election",
415
+ "2026-house-mo-08-election",
416
+ "2026-house-fl-24-election",
417
+ "2026-house-oh-07-election",
418
+ "2026-sen-il-election",
419
+ "2026-house-ky-02-election",
420
+ "2026-house-pa-13-election",
421
+ "2026-house-pa-16-election",
422
+ "2026-house-mo-02-election",
423
+ "2026-house-mi-06-election",
424
+ "2026-house-ct-03-election",
425
+ "2026-house-ut-02-election",
426
+ "2026-house-tx-25-election",
427
+ "2026-house-pa-03-election",
428
+ "2026-house-fl-21-election",
429
+ "2026-house-ca-05-election",
430
+ "2026-house-ma-09-election",
431
+ "2026-house-wa-03-election",
432
+ "2026-house-nj-03-election",
433
+ "2026-house-wa-05-election",
434
+ "2026-house-az-01-election",
435
+ "2026-house-fl-06-election",
436
+ "2026-house-az-03-election",
437
+ "2026-house-pa-02-election",
438
+ "2026-house-la-04-election",
439
+ "2026-house-tx-24-election",
440
+ "2026-house-wi-03-election",
441
+ "2026-house-nj-08-election",
442
+ "2026-house-wi-08-election",
443
+ "2026-house-ny-15-election",
444
+ "2026-house-sd-al-election",
445
+ "2026-house-ca-12-election",
446
+ "2026-house-wa-06-election",
447
+ "2026-house-ks-01-election",
448
+ "2026-sen-co-election",
449
+ "2026-house-ca-35-election",
450
+ "2026-house-ny-02-election",
451
+ "2026-house-nj-11-election",
452
+ "2026-house-tx-18-election",
453
+ "2026-house-md-07-election",
454
+ "2026-house-ma-04-election",
455
+ "2026-house-ca-24-election",
456
+ "2026-house-pa-10-election",
457
+ "2026-house-il-15-election",
458
+ "2026-house-mi-04-election",
459
+ "2026-house-wi-02-election",
460
+ "2026-house-fl-28-election",
461
+ "2026-house-ct-04-election",
462
+ "2026-house-ca-23-election",
463
+ "2026-house-va-05-election",
464
+ "2026-sen-ia-election",
465
+ "2026-house-al-04-election",
466
+ "2026-house-oh-10-election",
467
+ "2026-house-ma-06-election",
468
+ "2026-house-ga-08-election",
469
+ "2026-house-ca-01-election",
470
+ "2026-house-az-08-election",
471
+ "2026-house-ny-03-election",
472
+ "2026-house-co-08-election",
473
+ "2026-house-ut-03-election"
474
+ ]);
475
+ export class Utils_Misc {
476
+ config;
477
+ text_encoder;
478
+ transporter;
479
+ constructor(config) {
480
+ this.config = config;
481
+ this.text_encoder = new TextEncoder();
482
+ if (config.google_email !== undefined && config.google_app_password !== undefined) {
483
+ this.transporter = nodemailer.createTransport({
484
+ service: "Gmail",
485
+ host: "smtp.gmail.com",
486
+ port: 465,
487
+ secure: true,
488
+ auth: {
489
+ user: config.google_email,
490
+ pass: config.google_app_password,
491
+ }
492
+ });
493
+ }
494
+ }
495
+ async wait(duration) {
496
+ return new Promise(resolve => setTimeout(resolve, duration));
497
+ }
498
+ get_current_time() {
499
+ return (new Date()).toISOString();
500
+ }
501
+ get_current_milliseconds() {
502
+ return (new Date()).getTime();
503
+ }
504
+ async send_email(recipient, subject, text) {
505
+ if (this.transporter === undefined) {
506
+ return;
507
+ }
508
+ for (let i = 0; i < 3; i++) {
509
+ try {
510
+ await this.transporter.sendMail({
511
+ from: this.config.alerts_email,
512
+ to: recipient,
513
+ subject: subject,
514
+ text: text
515
+ });
516
+ return;
517
+ }
518
+ catch (error) {
519
+ console.log("EMAIL ERROR", error);
520
+ }
521
+ }
522
+ }
523
+ async admin_alert(text) {
524
+ console.log("ADMIN ALERT:", text);
525
+ await this.send_email(this.config.google_email, "ADMIN ALERT", text);
526
+ }
527
+ async safe_run(f) {
528
+ try {
529
+ await f();
530
+ }
531
+ catch (error) {
532
+ if (!(error instanceof Error)) {
533
+ return;
534
+ }
535
+ if (error.stack !== undefined) {
536
+ await this.admin_alert(error.stack.toString());
537
+ }
538
+ else {
539
+ await this.admin_alert(error.toString());
540
+ }
541
+ }
542
+ }
543
+ async iterate(inputs, f, concurrency = 1, print_indices = false) {
544
+ let index = 0;
545
+ let iterators = [];
546
+ for (let i = 0; i < concurrency; i++) {
547
+ iterators.push((async () => {
548
+ while (index < inputs.length) {
549
+ index += 1;
550
+ if (print_indices) {
551
+ console.log(i + ":" + (index - 1) + "/" + inputs.length);
552
+ }
553
+ await this.safe_run(() => f(inputs[index - 1]));
554
+ }
555
+ })());
556
+ }
557
+ await Promise.all(iterators);
558
+ }
559
+ async sha256(input) {
560
+ const input_buffer = this.text_encoder.encode(input);
561
+ const hash_buffer = await crypto.subtle.digest("SHA-256", input_buffer);
562
+ const hash_array = Array.from(new Uint8Array(hash_buffer));
563
+ const hash = hash_array.map(b => b.toString(16).padStart(2, "0")).join("");
564
+ return hash;
565
+ }
566
+ encrypt(text) {
567
+ const iv = crypto.randomBytes(16);
568
+ const cipher = crypto.createCipheriv("aes-256-cbc", Buffer.from(this.config.secret_key, "hex"), iv);
569
+ let ciphertext = cipher.update(text, "utf8", "hex");
570
+ ciphertext += cipher.final("hex");
571
+ return {
572
+ iv: iv.toString("hex"),
573
+ ciphertext: ciphertext
574
+ };
575
+ }
576
+ decrypt(encryption) {
577
+ const iv = encryption.iv;
578
+ const ciphertext = encryption.ciphertext;
579
+ const decipher = crypto.createDecipheriv("aes-256-cbc", Buffer.from(this.config.secret_key, "hex"), Buffer.from(iv, "hex"));
580
+ let text = decipher.update(ciphertext, "hex", "utf8");
581
+ text += decipher.final("utf8");
582
+ return text;
583
+ }
584
+ get_secret_hash(username) {
585
+ const secret_hash = crypto.createHmac("sha256", this.config.cognito_client_secret)
586
+ .update(username + this.config.cognito_client_id)
587
+ .digest("base64");
588
+ return secret_hash;
589
+ }
590
+ get_election_id(year, office, state, district) {
591
+ if (year === undefined || office === undefined || state === undefined || office === "P") {
592
+ return undefined;
593
+ }
594
+ if (office === "H" && (district === undefined || district.length !== 2)) {
595
+ return undefined;
596
+ }
597
+ if (year.length !== 4 || office.length !== 1 || state.length !== 2) {
598
+ return undefined;
599
+ }
600
+ const office_name = { "H": "house", "S": "sen", "P": "pres" }[office];
601
+ const election_id = year + "-" + office_name + "-" + state.toLowerCase() + (office === "H" ? ("-" + district.toLowerCase()) : "") + "-election";
602
+ if (!election_ids.has(election_id)) {
603
+ return undefined;
604
+ }
605
+ return election_id;
606
+ }
607
+ get_chunk_indices(text_length, max_length = 2500, overlap = 50) {
608
+ const num_chunks = Math.ceil((text_length + overlap) / max_length);
609
+ const chunk_length = Math.ceil((text_length - overlap) / num_chunks + overlap);
610
+ const chunk_indices = [];
611
+ for (let i = 0; i < num_chunks; i++) {
612
+ chunk_indices.push([
613
+ (chunk_length - overlap) * i,
614
+ (chunk_length - overlap) * i + chunk_length
615
+ ]);
616
+ }
617
+ return chunk_indices;
618
+ }
619
+ chunkify(text, max_length = 2500, overlap = 50) {
620
+ const chunk_indices = this.get_chunk_indices(text.length, max_length, overlap);
621
+ const chunks = chunk_indices.map(chunk_index => ({
622
+ chunk_index: chunk_index,
623
+ chunk_text: text.substring(...chunk_index)
624
+ }));
625
+ return chunks;
626
+ }
627
+ }