@civiq/entity-resolution 0.1.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/LICENSE +21 -0
- package/README.md +135 -0
- package/data/bioguide-fec-mapping.json +4186 -0
- package/data/sec-sic-data.json +10427 -0
- package/dist/__tests__/company-entity-resolver.test.d.ts +6 -0
- package/dist/__tests__/company-entity-resolver.test.d.ts.map +1 -0
- package/dist/__tests__/company-entity-resolver.test.js +267 -0
- package/dist/__tests__/company-entity-resolver.test.js.map +1 -0
- package/dist/__tests__/entity-resolution.test.d.ts +2 -0
- package/dist/__tests__/entity-resolution.test.d.ts.map +1 -0
- package/dist/__tests__/entity-resolution.test.js +296 -0
- package/dist/__tests__/entity-resolution.test.js.map +1 -0
- package/dist/__tests__/fec-entity-resolution.test.d.ts +2 -0
- package/dist/__tests__/fec-entity-resolution.test.d.ts.map +1 -0
- package/dist/__tests__/fec-entity-resolution.test.js +49 -0
- package/dist/__tests__/fec-entity-resolution.test.js.map +1 -0
- package/dist/bioguide-fec-mapping.d.ts +27 -0
- package/dist/bioguide-fec-mapping.d.ts.map +1 -0
- package/dist/bioguide-fec-mapping.js +57 -0
- package/dist/bioguide-fec-mapping.js.map +1 -0
- package/dist/cache.d.ts +18 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +18 -0
- package/dist/cache.js.map +1 -0
- package/dist/committee-agency-map.d.ts +58 -0
- package/dist/committee-agency-map.d.ts.map +1 -0
- package/dist/committee-agency-map.js +658 -0
- package/dist/committee-agency-map.js.map +1 -0
- package/dist/committee-alias-table.d.ts +11 -0
- package/dist/committee-alias-table.d.ts.map +1 -0
- package/dist/committee-alias-table.js +191 -0
- package/dist/committee-alias-table.js.map +1 -0
- package/dist/company-alias-table.d.ts +36 -0
- package/dist/company-alias-table.d.ts.map +1 -0
- package/dist/company-alias-table.js +1307 -0
- package/dist/company-alias-table.js.map +1 -0
- package/dist/company-entity-resolver.d.ts +94 -0
- package/dist/company-entity-resolver.d.ts.map +1 -0
- package/dist/company-entity-resolver.js +282 -0
- package/dist/company-entity-resolver.js.map +1 -0
- package/dist/configure.d.ts +15 -0
- package/dist/configure.d.ts.map +1 -0
- package/dist/configure.js +19 -0
- package/dist/configure.js.map +1 -0
- package/dist/fec-entity-resolution.d.ts +88 -0
- package/dist/fec-entity-resolution.d.ts.map +1 -0
- package/dist/fec-entity-resolution.js +407 -0
- package/dist/fec-entity-resolution.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/industry-taxonomy.d.ts +90 -0
- package/dist/industry-taxonomy.d.ts.map +1 -0
- package/dist/industry-taxonomy.js +1026 -0
- package/dist/industry-taxonomy.js.map +1 -0
- package/dist/lda-issue-policy-map.d.ts +13 -0
- package/dist/lda-issue-policy-map.d.ts.map +1 -0
- package/dist/lda-issue-policy-map.js +193 -0
- package/dist/lda-issue-policy-map.js.map +1 -0
- package/dist/lobbying-committee-resolver.d.ts +23 -0
- package/dist/lobbying-committee-resolver.d.ts.map +1 -0
- package/dist/lobbying-committee-resolver.js +158 -0
- package/dist/lobbying-committee-resolver.js.map +1 -0
- package/dist/logger.d.ts +20 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +20 -0
- package/dist/logger.js.map +1 -0
- package/dist/sic-sector-map.d.ts +32 -0
- package/dist/sic-sector-map.d.ts.map +1 -0
- package/dist/sic-sector-map.js +109 -0
- package/dist/sic-sector-map.js.map +1 -0
- package/dist/ticker-industry-resolver.d.ts +22 -0
- package/dist/ticker-industry-resolver.d.ts.map +1 -0
- package/dist/ticker-industry-resolver.js +254 -0
- package/dist/ticker-industry-resolver.js.map +1 -0
- package/dist/types.d.ts +30 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2019-2025 Mark Sandford
|
|
3
|
+
* Licensed under the MIT License. See LICENSE and NOTICE files.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* FEC Entity Resolution & Name Standardization
|
|
7
|
+
*
|
|
8
|
+
* Handles entity matching, name normalization, and deduplication for:
|
|
9
|
+
* - Individual contributors with name variants (JOHN SMITH vs John Smith vs J. Smith)
|
|
10
|
+
* - Organizations/employers with variations (GOOGLE INC. vs Google Inc vs Google)
|
|
11
|
+
* - Recipients/disbursement entities (consulting firms, vendors)
|
|
12
|
+
*
|
|
13
|
+
* Uses string similarity algorithms and business rule heuristics to match entities.
|
|
14
|
+
*/
|
|
15
|
+
import { getLogger } from './logger';
|
|
16
|
+
/**
|
|
17
|
+
* Common abbreviations used in FEC/lobbying data.
|
|
18
|
+
* Maps normalized short forms to canonical full names.
|
|
19
|
+
*/
|
|
20
|
+
const COMMON_ABBREVIATIONS = {
|
|
21
|
+
jnj: 'johnson and johnson',
|
|
22
|
+
jj: 'johnson and johnson',
|
|
23
|
+
'j and j': 'johnson and johnson',
|
|
24
|
+
gm: 'general motors',
|
|
25
|
+
ge: 'general electric',
|
|
26
|
+
ibm: 'international business machines',
|
|
27
|
+
att: 'at and t',
|
|
28
|
+
'at t': 'at and t',
|
|
29
|
+
jpmorgan: 'jpmorgan chase',
|
|
30
|
+
jpm: 'jpmorgan chase',
|
|
31
|
+
bofa: 'bank of america',
|
|
32
|
+
pg: 'procter and gamble',
|
|
33
|
+
'p and g': 'procter and gamble',
|
|
34
|
+
msft: 'microsoft',
|
|
35
|
+
amzn: 'amazon',
|
|
36
|
+
goog: 'alphabet',
|
|
37
|
+
aapl: 'apple',
|
|
38
|
+
pfizer: 'pfizer',
|
|
39
|
+
raytheon: 'raytheon technologies',
|
|
40
|
+
lockmart: 'lockheed martin',
|
|
41
|
+
ba: 'boeing',
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Expand a cleaned name using the abbreviation map.
|
|
45
|
+
* Returns the canonical form if found, otherwise returns the original.
|
|
46
|
+
*/
|
|
47
|
+
function expandAbbreviation(cleanedName) {
|
|
48
|
+
const lower = cleanedName.toLowerCase();
|
|
49
|
+
if (COMMON_ABBREVIATIONS[lower]) {
|
|
50
|
+
return COMMON_ABBREVIATIONS[lower].toUpperCase();
|
|
51
|
+
}
|
|
52
|
+
return cleanedName;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Remove common noise from names for better matching
|
|
56
|
+
*/
|
|
57
|
+
function cleanNameForMatching(name) {
|
|
58
|
+
return (name
|
|
59
|
+
.trim()
|
|
60
|
+
.toUpperCase()
|
|
61
|
+
// Remove common suffixes
|
|
62
|
+
.replace(/\s+(INC\.?|LLC\.?|LLP\.?|CORP\.?|CORPORATION|COMPANY|CO\.?|LTD\.?)$/i, '')
|
|
63
|
+
// Normalize ampersand to AND before stripping punctuation
|
|
64
|
+
.replace(/&/g, ' AND ')
|
|
65
|
+
// Remove punctuation except spaces
|
|
66
|
+
.replace(/[^\w\s]/g, '')
|
|
67
|
+
// Normalize multiple spaces
|
|
68
|
+
.replace(/\s+/g, ' ')
|
|
69
|
+
.trim());
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Standardize individual names to canonical form
|
|
73
|
+
* Handles: LAST, FIRST MIDDLE -> First Middle Last
|
|
74
|
+
*/
|
|
75
|
+
function standardizeIndividualName(name) {
|
|
76
|
+
const cleaned = name.trim();
|
|
77
|
+
// Check if name is in "LAST, FIRST" format
|
|
78
|
+
if (cleaned.includes(',')) {
|
|
79
|
+
const parts = cleaned.split(',').map(p => p.trim());
|
|
80
|
+
if (parts.length === 2) {
|
|
81
|
+
const [last, first] = parts;
|
|
82
|
+
return `${first} ${last}`.replace(/\s+/g, ' ').trim();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Already in "First Last" format
|
|
86
|
+
return cleaned.replace(/\s+/g, ' ').trim();
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Calculate Levenshtein distance for string similarity
|
|
90
|
+
* Used to detect typos and minor variations
|
|
91
|
+
*/
|
|
92
|
+
function levenshteinDistance(a, b) {
|
|
93
|
+
const matrix = [];
|
|
94
|
+
for (let i = 0; i <= b.length; i++) {
|
|
95
|
+
matrix[i] = [i];
|
|
96
|
+
}
|
|
97
|
+
for (let j = 0; j <= a.length; j++) {
|
|
98
|
+
matrix[0][j] = j;
|
|
99
|
+
}
|
|
100
|
+
for (let i = 1; i <= b.length; i++) {
|
|
101
|
+
for (let j = 1; j <= a.length; j++) {
|
|
102
|
+
if (b.charAt(i - 1) === a.charAt(j - 1)) {
|
|
103
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
|
|
107
|
+
matrix[i][j - 1] + 1, // insertion
|
|
108
|
+
matrix[i - 1][j] + 1 // deletion
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return matrix[b.length][a.length];
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Calculate similarity ratio between two strings (0-1)
|
|
117
|
+
*/
|
|
118
|
+
function similarityRatio(a, b) {
|
|
119
|
+
const distance = levenshteinDistance(a, b);
|
|
120
|
+
const maxLength = Math.max(a.length, b.length);
|
|
121
|
+
return maxLength === 0 ? 1 : 1 - distance / maxLength;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Detect if name represents an individual or organization
|
|
125
|
+
*/
|
|
126
|
+
function detectEntityType(name) {
|
|
127
|
+
const cleaned = name.toUpperCase();
|
|
128
|
+
// Organization indicators
|
|
129
|
+
const orgIndicators = [
|
|
130
|
+
'INC',
|
|
131
|
+
'LLC',
|
|
132
|
+
'LLP',
|
|
133
|
+
'CORP',
|
|
134
|
+
'CORPORATION',
|
|
135
|
+
'COMPANY',
|
|
136
|
+
'CO',
|
|
137
|
+
'LTD',
|
|
138
|
+
'PARTNERSHIP',
|
|
139
|
+
'COMMITTEE',
|
|
140
|
+
'PAC',
|
|
141
|
+
'FUND',
|
|
142
|
+
'FOUNDATION',
|
|
143
|
+
'ASSOCIATION',
|
|
144
|
+
'SOCIETY',
|
|
145
|
+
'INSTITUTE',
|
|
146
|
+
'COUNCIL',
|
|
147
|
+
'GROUP',
|
|
148
|
+
];
|
|
149
|
+
if (orgIndicators.some(indicator => cleaned.includes(indicator))) {
|
|
150
|
+
return 'organization';
|
|
151
|
+
}
|
|
152
|
+
// Individual indicators (comma-separated name format)
|
|
153
|
+
if (cleaned.includes(',')) {
|
|
154
|
+
return 'individual';
|
|
155
|
+
}
|
|
156
|
+
// Count words - individuals typically have 2-4 words
|
|
157
|
+
const wordCount = cleaned.split(/\s+/).length;
|
|
158
|
+
if (wordCount >= 2 && wordCount <= 4) {
|
|
159
|
+
return 'individual';
|
|
160
|
+
}
|
|
161
|
+
return 'unknown';
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Check if two entities should be considered the same based on name similarity
|
|
165
|
+
* and metadata matching
|
|
166
|
+
*/
|
|
167
|
+
export function entitiesMatch(entity1, entity2, threshold = 0.85) {
|
|
168
|
+
const name1 = cleanNameForMatching(entity1.name);
|
|
169
|
+
const name2 = cleanNameForMatching(entity2.name);
|
|
170
|
+
// Exact match
|
|
171
|
+
if (name1 === name2) {
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
// Expand common abbreviations before similarity comparison
|
|
175
|
+
const expanded1 = expandAbbreviation(name1);
|
|
176
|
+
const expanded2 = expandAbbreviation(name2);
|
|
177
|
+
// Re-check exact match after expansion
|
|
178
|
+
if (expanded1 === expanded2) {
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
// Calculate similarity using expanded forms
|
|
182
|
+
const similarity = similarityRatio(expanded1, expanded2);
|
|
183
|
+
// High similarity threshold for base match
|
|
184
|
+
if (similarity < threshold) {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
// Additional metadata checks to confirm match
|
|
188
|
+
let metadataMatches = 0;
|
|
189
|
+
let metadataChecks = 0;
|
|
190
|
+
// Check employer match (for individuals)
|
|
191
|
+
if (entity1.employer && entity2.employer) {
|
|
192
|
+
metadataChecks++;
|
|
193
|
+
const emp1 = cleanNameForMatching(entity1.employer);
|
|
194
|
+
const emp2 = cleanNameForMatching(entity2.employer);
|
|
195
|
+
if (emp1 === emp2 || similarityRatio(emp1, emp2) > 0.8) {
|
|
196
|
+
metadataMatches++;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Check location match
|
|
200
|
+
if (entity1.state && entity2.state) {
|
|
201
|
+
metadataChecks++;
|
|
202
|
+
if (entity1.state.toUpperCase() === entity2.state.toUpperCase()) {
|
|
203
|
+
metadataMatches++;
|
|
204
|
+
// Same city is strong confirmation
|
|
205
|
+
if (entity1.city && entity2.city) {
|
|
206
|
+
metadataChecks++;
|
|
207
|
+
const city1 = cleanNameForMatching(entity1.city);
|
|
208
|
+
const city2 = cleanNameForMatching(entity2.city);
|
|
209
|
+
if (city1 === city2) {
|
|
210
|
+
metadataMatches++;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// If we have metadata, require at least 50% match
|
|
216
|
+
if (metadataChecks > 0) {
|
|
217
|
+
return metadataMatches / metadataChecks >= 0.5;
|
|
218
|
+
}
|
|
219
|
+
// No metadata, rely on name similarity
|
|
220
|
+
return similarity >= threshold;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Normalize a single entity name and metadata
|
|
224
|
+
*/
|
|
225
|
+
export function normalizeEntity(name, metadata) {
|
|
226
|
+
const entityType = detectEntityType(name);
|
|
227
|
+
let displayName;
|
|
228
|
+
let normalizedName;
|
|
229
|
+
if (entityType === 'individual') {
|
|
230
|
+
displayName = standardizeIndividualName(name);
|
|
231
|
+
normalizedName = cleanNameForMatching(displayName);
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
displayName = name.trim();
|
|
235
|
+
normalizedName = cleanNameForMatching(name);
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
normalizedName,
|
|
239
|
+
displayName,
|
|
240
|
+
rawVariants: [name],
|
|
241
|
+
entityType,
|
|
242
|
+
metadata: metadata || {},
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Deduplicate and aggregate contributions by entity
|
|
247
|
+
*/
|
|
248
|
+
export function deduplicateContributions(contributions) {
|
|
249
|
+
const entityMap = new Map();
|
|
250
|
+
getLogger().debug(`[Entity Resolution] Deduplicating ${contributions.length} contributions`);
|
|
251
|
+
for (const contrib of contributions) {
|
|
252
|
+
if (!contrib.contributor_name?.trim()) {
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
const metadata = {
|
|
256
|
+
employer: contrib.contributor_employer,
|
|
257
|
+
occupation: contrib.contributor_occupation,
|
|
258
|
+
city: contrib.contributor_city,
|
|
259
|
+
state: contrib.contributor_state,
|
|
260
|
+
zip: contrib.contributor_zip,
|
|
261
|
+
};
|
|
262
|
+
const normalized = normalizeEntity(contrib.contributor_name, metadata);
|
|
263
|
+
// Check if we already have a matching entity
|
|
264
|
+
let matchedKey = null;
|
|
265
|
+
for (const [key, existing] of entityMap.entries()) {
|
|
266
|
+
if (entitiesMatch({
|
|
267
|
+
name: normalized.normalizedName,
|
|
268
|
+
employer: metadata.employer,
|
|
269
|
+
city: metadata.city,
|
|
270
|
+
state: metadata.state,
|
|
271
|
+
zip: metadata.zip,
|
|
272
|
+
}, {
|
|
273
|
+
name: existing.normalizedName,
|
|
274
|
+
employer: existing.metadata.employer,
|
|
275
|
+
city: existing.metadata.city,
|
|
276
|
+
state: existing.metadata.state,
|
|
277
|
+
zip: existing.metadata.zip,
|
|
278
|
+
})) {
|
|
279
|
+
matchedKey = key;
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (matchedKey) {
|
|
284
|
+
// Add to existing entity
|
|
285
|
+
const existing = entityMap.get(matchedKey);
|
|
286
|
+
existing.totalAmount += contrib.contribution_receipt_amount;
|
|
287
|
+
existing.transactionCount++;
|
|
288
|
+
existing.transactions.push({
|
|
289
|
+
amount: contrib.contribution_receipt_amount,
|
|
290
|
+
date: contrib.contribution_receipt_date,
|
|
291
|
+
rawName: contrib.contributor_name,
|
|
292
|
+
});
|
|
293
|
+
// Add variant if not already present
|
|
294
|
+
if (!existing.rawVariants.includes(contrib.contributor_name)) {
|
|
295
|
+
existing.rawVariants.push(contrib.contributor_name);
|
|
296
|
+
}
|
|
297
|
+
// Update metadata if more complete
|
|
298
|
+
if (!existing.metadata.employer && metadata.employer) {
|
|
299
|
+
existing.metadata.employer = metadata.employer;
|
|
300
|
+
}
|
|
301
|
+
if (!existing.metadata.occupation && metadata.occupation) {
|
|
302
|
+
existing.metadata.occupation = metadata.occupation;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
// Create new entity
|
|
307
|
+
entityMap.set(normalized.normalizedName, {
|
|
308
|
+
...normalized,
|
|
309
|
+
totalAmount: contrib.contribution_receipt_amount,
|
|
310
|
+
transactionCount: 1,
|
|
311
|
+
transactions: [
|
|
312
|
+
{
|
|
313
|
+
amount: contrib.contribution_receipt_amount,
|
|
314
|
+
date: contrib.contribution_receipt_date,
|
|
315
|
+
rawName: contrib.contributor_name,
|
|
316
|
+
},
|
|
317
|
+
],
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
const result = Array.from(entityMap.values());
|
|
322
|
+
getLogger().debug(`[Entity Resolution] Deduplicated ${contributions.length} contributions into ${result.length} unique entities`);
|
|
323
|
+
return result;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Deduplicate and aggregate disbursements by recipient
|
|
327
|
+
*/
|
|
328
|
+
export function deduplicateDisbursements(disbursements) {
|
|
329
|
+
const entityMap = new Map();
|
|
330
|
+
getLogger().debug(`[Entity Resolution] Deduplicating ${disbursements.length} disbursements`);
|
|
331
|
+
for (const disb of disbursements) {
|
|
332
|
+
if (!disb.recipient_name?.trim()) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
const metadata = {
|
|
336
|
+
city: disb.recipient_city,
|
|
337
|
+
state: disb.recipient_state,
|
|
338
|
+
};
|
|
339
|
+
const normalized = normalizeEntity(disb.recipient_name, metadata);
|
|
340
|
+
// Check if we already have a matching entity
|
|
341
|
+
let matchedKey = null;
|
|
342
|
+
for (const [key, existing] of entityMap.entries()) {
|
|
343
|
+
if (entitiesMatch({
|
|
344
|
+
name: normalized.normalizedName,
|
|
345
|
+
city: metadata.city,
|
|
346
|
+
state: metadata.state,
|
|
347
|
+
}, {
|
|
348
|
+
name: existing.normalizedName,
|
|
349
|
+
city: existing.metadata.city,
|
|
350
|
+
state: existing.metadata.state,
|
|
351
|
+
})) {
|
|
352
|
+
matchedKey = key;
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (matchedKey) {
|
|
357
|
+
// Add to existing entity
|
|
358
|
+
const existing = entityMap.get(matchedKey);
|
|
359
|
+
existing.totalAmount += disb.disbursement_amount;
|
|
360
|
+
existing.transactionCount++;
|
|
361
|
+
existing.transactions.push({
|
|
362
|
+
amount: disb.disbursement_amount,
|
|
363
|
+
date: disb.disbursement_date,
|
|
364
|
+
rawName: disb.recipient_name,
|
|
365
|
+
});
|
|
366
|
+
// Add variant if not already present
|
|
367
|
+
if (!existing.rawVariants.includes(disb.recipient_name)) {
|
|
368
|
+
existing.rawVariants.push(disb.recipient_name);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
// Create new entity
|
|
373
|
+
entityMap.set(normalized.normalizedName, {
|
|
374
|
+
...normalized,
|
|
375
|
+
totalAmount: disb.disbursement_amount,
|
|
376
|
+
transactionCount: 1,
|
|
377
|
+
transactions: [
|
|
378
|
+
{
|
|
379
|
+
amount: disb.disbursement_amount,
|
|
380
|
+
date: disb.disbursement_date,
|
|
381
|
+
rawName: disb.recipient_name,
|
|
382
|
+
},
|
|
383
|
+
],
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
const result = Array.from(entityMap.values());
|
|
388
|
+
getLogger().debug(`[Entity Resolution] Deduplicated ${disbursements.length} disbursements into ${result.length} unique entities`);
|
|
389
|
+
return result;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Standardize employer/organization names for industry analysis
|
|
393
|
+
*/
|
|
394
|
+
export function standardizeEmployerName(employer) {
|
|
395
|
+
const cleaned = employer.trim();
|
|
396
|
+
const entityType = detectEntityType(cleaned);
|
|
397
|
+
if (entityType === 'organization') {
|
|
398
|
+
// Return cleaned form without corporate suffixes
|
|
399
|
+
return cleanNameForMatching(cleaned)
|
|
400
|
+
.split(' ')
|
|
401
|
+
.map(word => word.charAt(0) + word.slice(1).toLowerCase())
|
|
402
|
+
.join(' ');
|
|
403
|
+
}
|
|
404
|
+
// Keep original for individuals or unknown
|
|
405
|
+
return cleaned;
|
|
406
|
+
}
|
|
407
|
+
//# sourceMappingURL=fec-entity-resolution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fec-entity-resolution.js","sourceRoot":"","sources":["../src/fec-entity-resolution.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @civiq/entity-resolution
|
|
3
|
+
*
|
|
4
|
+
* Entity resolution for civic data — committee/agency alias matching,
|
|
5
|
+
* industry taxonomy, ticker-to-sector resolution, FEC entity deduplication.
|
|
6
|
+
*/
|
|
7
|
+
export { configure } from './configure';
|
|
8
|
+
export { setLogger, getLogger } from './logger';
|
|
9
|
+
export type { Logger } from './logger';
|
|
10
|
+
export { setCache, getCache } from './cache';
|
|
11
|
+
export type { CacheAdapter } from './cache';
|
|
12
|
+
export type { GovernmentEntityResolution, TickerResolution } from './types';
|
|
13
|
+
export { IndustrySector, categorizeContribution, aggregateByIndustrySector, categorizePACByName, categorizeContributionSmart, getTopCategories, } from './industry-taxonomy';
|
|
14
|
+
export type { IndustryCategory, CategorizedContribution } from './industry-taxonomy';
|
|
15
|
+
export { HOUSE_COMMITTEE_MAPPINGS, SENATE_COMMITTEE_MAPPINGS, ALL_COMMITTEE_MAPPINGS, getAgenciesForCommittee, getTopicsForCommittee, getAgenciesForCommittees, getCommitteesForAgency, getTopicsForCommittees, } from './committee-agency-map';
|
|
16
|
+
export type { AgencyInfo, CommitteeMapping } from './committee-agency-map';
|
|
17
|
+
export { COMMITTEE_ALIASES, AGENCY_ALIASES, getAllCommitteeAliasNames, } from './committee-alias-table';
|
|
18
|
+
export { resolveGovernmentEntity, resolveFilingEntities, getResolvedCommittees, } from './lobbying-committee-resolver';
|
|
19
|
+
export { sicToSector } from './sic-sector-map';
|
|
20
|
+
export { resolveTickerIndustry, resolveTickerIndustries } from './ticker-industry-resolver';
|
|
21
|
+
export { LDA_ISSUE_POLICY_MAP, getLDAIssueLabel, getPolicyAreasForLDAIssue, getAllLDAIssueCodes, } from './lda-issue-policy-map';
|
|
22
|
+
export { resolveCompanyName, resolveCompanyNames, normalizeCompanyName, companiesMatch, validateTokenOverlap, similarityRatio, } from './company-entity-resolver';
|
|
23
|
+
export type { ResolvedCompany } from './company-entity-resolver';
|
|
24
|
+
export { COMPANY_ALIAS_TABLE, findCompanyByAlias } from './company-alias-table';
|
|
25
|
+
export type { CompanyAlias } from './company-alias-table';
|
|
26
|
+
export { entitiesMatch, normalizeEntity, deduplicateContributions, deduplicateDisbursements, standardizeEmployerName, } from './fec-entity-resolution';
|
|
27
|
+
export type { StandardizedEntity, AggregatedEntity } from './fec-entity-resolution';
|
|
28
|
+
export { bioguideToFECMapping, getFECIdFromBioguide, hasFECMapping, addFECMapping, getBioguideFromFEC, getMappingByFEC, getMappingStats, } from './bioguide-fec-mapping';
|
|
29
|
+
export type { FECMapping } from './bioguide-fec-mapping';
|
|
30
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAChD,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG5C,YAAY,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG5E,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,EACnB,2BAA2B,EAC3B,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAGrF,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG3E,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,yBAAyB,GAC1B,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAG5F,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACpB,eAAe,GAChB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAGjE,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChF,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1D,OAAO,EACL,aAAa,EACb,eAAe,EACf,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGpF,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @civiq/entity-resolution
|
|
3
|
+
*
|
|
4
|
+
* Entity resolution for civic data — committee/agency alias matching,
|
|
5
|
+
* industry taxonomy, ticker-to-sector resolution, FEC entity deduplication.
|
|
6
|
+
*/
|
|
7
|
+
// ── Configuration ────────────────────────────────────────────────────
|
|
8
|
+
export { configure } from './configure';
|
|
9
|
+
export { setLogger, getLogger } from './logger';
|
|
10
|
+
export { setCache, getCache } from './cache';
|
|
11
|
+
// ── Industry Taxonomy ────────────────────────────────────────────────
|
|
12
|
+
export { IndustrySector, categorizeContribution, aggregateByIndustrySector, categorizePACByName, categorizeContributionSmart, getTopCategories, } from './industry-taxonomy';
|
|
13
|
+
// ── Committee-Agency Map ─────────────────────────────────────────────
|
|
14
|
+
export { HOUSE_COMMITTEE_MAPPINGS, SENATE_COMMITTEE_MAPPINGS, ALL_COMMITTEE_MAPPINGS, getAgenciesForCommittee, getTopicsForCommittee, getAgenciesForCommittees, getCommitteesForAgency, getTopicsForCommittees, } from './committee-agency-map';
|
|
15
|
+
// ── Committee Alias Table ────────────────────────────────────────────
|
|
16
|
+
export { COMMITTEE_ALIASES, AGENCY_ALIASES, getAllCommitteeAliasNames, } from './committee-alias-table';
|
|
17
|
+
// ── Lobbying Committee Resolver ──────────────────────────────────────
|
|
18
|
+
export { resolveGovernmentEntity, resolveFilingEntities, getResolvedCommittees, } from './lobbying-committee-resolver';
|
|
19
|
+
// ── SIC Sector Map ───────────────────────────────────────────────────
|
|
20
|
+
export { sicToSector } from './sic-sector-map';
|
|
21
|
+
// ── Ticker Industry Resolver ─────────────────────────────────────────
|
|
22
|
+
export { resolveTickerIndustry, resolveTickerIndustries } from './ticker-industry-resolver';
|
|
23
|
+
// ── LDA Issue Policy Map ─────────────────────────────────────────────
|
|
24
|
+
export { LDA_ISSUE_POLICY_MAP, getLDAIssueLabel, getPolicyAreasForLDAIssue, getAllLDAIssueCodes, } from './lda-issue-policy-map';
|
|
25
|
+
// ── Company Entity Resolution ────────────────────────────────────────
|
|
26
|
+
export { resolveCompanyName, resolveCompanyNames, normalizeCompanyName, companiesMatch, validateTokenOverlap, similarityRatio, } from './company-entity-resolver';
|
|
27
|
+
// ── Company Alias Table ─────────────────────────────────────────────
|
|
28
|
+
export { COMPANY_ALIAS_TABLE, findCompanyByAlias } from './company-alias-table';
|
|
29
|
+
// ── FEC Entity Resolution ────────────────────────────────────────────
|
|
30
|
+
export { entitiesMatch, normalizeEntity, deduplicateContributions, deduplicateDisbursements, standardizeEmployerName, } from './fec-entity-resolution';
|
|
31
|
+
// ── Bioguide-FEC Mapping ─────────────────────────────────────────────
|
|
32
|
+
export { bioguideToFECMapping, getFECIdFromBioguide, hasFECMapping, addFECMapping, getBioguideFromFEC, getMappingByFEC, getMappingStats, } from './bioguide-fec-mapping';
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,wEAAwE;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAM7C,wEAAwE;AACxE,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,EACnB,2BAA2B,EAC3B,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAG7B,wEAAwE;AACxE,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAGhC,wEAAwE;AACxE,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,yBAAyB,GAC1B,MAAM,yBAAyB,CAAC;AAEjC,wEAAwE;AACxE,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AAEvC,wEAAwE;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,wEAAwE;AACxE,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAE5F,wEAAwE;AACxE,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAEhC,wEAAwE;AACxE,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACpB,eAAe,GAChB,MAAM,2BAA2B,CAAC;AAGnC,uEAAuE;AACvE,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAGhF,wEAAwE;AACxE,OAAO,EACL,aAAa,EACb,eAAe,EACf,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AAGjC,wEAAwE;AACxE,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,eAAe,GAChB,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2019-2025 Mark Sandford
|
|
3
|
+
* Licensed under the MIT License. See LICENSE and NOTICE files.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Industry sector enumeration
|
|
7
|
+
*/
|
|
8
|
+
export declare enum IndustrySector {
|
|
9
|
+
AGRIBUSINESS = "Agribusiness",
|
|
10
|
+
COMMUNICATIONS_ELECTRONICS = "Communications/Electronics",
|
|
11
|
+
CONSTRUCTION = "Construction",
|
|
12
|
+
DEFENSE = "Defense",
|
|
13
|
+
ENERGY_NATURAL_RESOURCES = "Energy/Natural Resources",
|
|
14
|
+
FINANCE_INSURANCE_REAL_ESTATE = "Finance/Insurance/Real Estate",
|
|
15
|
+
HEALTH = "Health",
|
|
16
|
+
LAWYERS_LOBBYISTS = "Lawyers & Lobbyists",
|
|
17
|
+
TRANSPORTATION = "Transportation",
|
|
18
|
+
MISC_BUSINESS = "Misc Business",
|
|
19
|
+
LABOR = "Labor",
|
|
20
|
+
IDEOLOGY_SINGLE_ISSUE = "Ideology/Single-Issue",
|
|
21
|
+
OTHER = "Other"
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Detailed industry category under each sector
|
|
25
|
+
*/
|
|
26
|
+
export interface IndustryCategory {
|
|
27
|
+
sector: IndustrySector;
|
|
28
|
+
category: string;
|
|
29
|
+
keywords: string[];
|
|
30
|
+
occupationKeywords?: string[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Categorized contribution with industry classification
|
|
34
|
+
*/
|
|
35
|
+
export interface CategorizedContribution {
|
|
36
|
+
sector: IndustrySector;
|
|
37
|
+
category: string;
|
|
38
|
+
confidence: 'high' | 'medium' | 'low';
|
|
39
|
+
matchedKeyword?: string;
|
|
40
|
+
matchSource: 'employer' | 'occupation' | 'inferred';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Categorize a contribution based on employer and occupation
|
|
44
|
+
*/
|
|
45
|
+
export declare function categorizeContribution(employer?: string, occupation?: string): CategorizedContribution;
|
|
46
|
+
/**
|
|
47
|
+
* Aggregate contributions by industry sector.
|
|
48
|
+
* Uses smart categorization when contributor_name is available,
|
|
49
|
+
* falling back to PAC name matching for unclassified contributions.
|
|
50
|
+
*/
|
|
51
|
+
export declare function aggregateByIndustrySector(contributions: Array<{
|
|
52
|
+
contributor_employer?: string;
|
|
53
|
+
contributor_occupation?: string;
|
|
54
|
+
contributor_name?: string;
|
|
55
|
+
contribution_receipt_amount: number;
|
|
56
|
+
}>): Array<{
|
|
57
|
+
sector: IndustrySector;
|
|
58
|
+
totalAmount: number;
|
|
59
|
+
contributionCount: number;
|
|
60
|
+
percentage: number;
|
|
61
|
+
categories: Map<string, {
|
|
62
|
+
amount: number;
|
|
63
|
+
count: number;
|
|
64
|
+
}>;
|
|
65
|
+
}>;
|
|
66
|
+
/**
|
|
67
|
+
* Categorize a PAC/committee by its name
|
|
68
|
+
* Used for committee-to-committee transfers and PAC contributions
|
|
69
|
+
*/
|
|
70
|
+
export declare function categorizePACByName(committeeName?: string): CategorizedContribution;
|
|
71
|
+
/**
|
|
72
|
+
* Smart categorization: tries employer/occupation first, then falls back to contributor name (for PACs)
|
|
73
|
+
*/
|
|
74
|
+
export declare function categorizeContributionSmart(employer?: string, occupation?: string, contributorName?: string): CategorizedContribution;
|
|
75
|
+
/**
|
|
76
|
+
* Get top categories across all sectors
|
|
77
|
+
*/
|
|
78
|
+
export declare function getTopCategories(contributions: Array<{
|
|
79
|
+
contributor_employer?: string;
|
|
80
|
+
contributor_occupation?: string;
|
|
81
|
+
contributor_name?: string;
|
|
82
|
+
contribution_receipt_amount: number;
|
|
83
|
+
}>, limit?: number): Array<{
|
|
84
|
+
sector: IndustrySector;
|
|
85
|
+
category: string;
|
|
86
|
+
totalAmount: number;
|
|
87
|
+
contributionCount: number;
|
|
88
|
+
percentage: number;
|
|
89
|
+
}>;
|
|
90
|
+
//# sourceMappingURL=industry-taxonomy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"industry-taxonomy.d.ts","sourceRoot":"","sources":["../src/industry-taxonomy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0BH;;GAEG;AACH,oBAAY,cAAc;IACxB,YAAY,iBAAiB;IAC7B,0BAA0B,+BAA+B;IACzD,YAAY,iBAAiB;IAC7B,OAAO,YAAY;IACnB,wBAAwB,6BAA6B;IACrD,6BAA6B,kCAAkC;IAC/D,MAAM,WAAW;IACjB,iBAAiB,wBAAwB;IACzC,cAAc,mBAAmB;IACjC,aAAa,kBAAkB;IAC/B,KAAK,UAAU;IACf,qBAAqB,0BAA0B;IAC/C,KAAK,UAAU;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,UAAU,GAAG,YAAY,GAAG,UAAU,CAAC;CACrD;AA4aD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,CAAC,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,GAClB,uBAAuB,CA+FzB;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,KAAK,CAAC;IACnB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2BAA2B,EAAE,MAAM,CAAC;CACrC,CAAC,GACD,KAAK,CAAC;IACP,MAAM,EAAE,cAAc,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5D,CAAC,CAuDD;AAiUD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,uBAAuB,CA6FnF;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,CAAC,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,MAAM,GACvB,uBAAuB,CAqBzB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,KAAK,CAAC;IACnB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2BAA2B,EAAE,MAAM,CAAC;CACrC,CAAC,EACF,KAAK,GAAE,MAAW,GACjB,KAAK,CAAC;IACP,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CA4CD"}
|