@lokal-id/core 0.3.0 → 0.4.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/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/kembaran-data.d.ts +10 -0
- package/dist/kembaran-data.js +46 -0
- package/dist/kembaran-data.js.map +1 -0
- package/dist/kembaran.d.ts +46 -0
- package/dist/kembaran.js +426 -0
- package/dist/kembaran.js.map +1 -0
- package/dist/qris.d.ts +82 -0
- package/dist/qris.js +236 -0
- package/dist/qris.js.map +1 -0
- package/dist/samaran/detectors.js +23 -1
- package/dist/samaran/detectors.js.map +1 -1
- package/dist/samaran/index.d.ts +2 -0
- package/dist/samaran/index.js +1 -1
- package/dist/samaran/index.js.map +1 -1
- package/package.json +5 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { parseNpwp, formatNpwp15, type NpwpInfo, type NpwpKind } from './npwp.ts
|
|
|
3
3
|
export { parsePhone, normalizePhone, type PhoneInfo, type PhoneType } from './phone.ts';
|
|
4
4
|
export { formatRupiah, formatRupiahShort, parseRupiah, type FormatRupiahOptions, type ParsedRupiah, } from './rupiah.ts';
|
|
5
5
|
export { terbilang, type TerbilangOptions } from './terbilang.ts';
|
|
6
|
+
export { parseQris, setQrisAmount, qrisCrc, type QrisInfo, type QrisField, type QrisMerchantAccount, type QrisTip, type QrisAdditionalData, type QrisAmountOptions, } from './qris.ts';
|
|
6
7
|
export { PROVINCES } from './provinces.ts';
|
|
7
8
|
export { getHolidays, holidaysOn, isWorkingDay, addWorkingDays, countWorkingDays, HOLIDAY_YEARS, type Holiday, type HolidayType, type HolidayYear, type WorkingDayOptions, } from './holidays.ts';
|
|
8
9
|
export { Samaran, maskPii, detectPii, partialMask, fieldType, PII_TYPES, UU_PDP_CATEGORY, type PiiType, type PiiMatch, type MaskedMatch, type MaskResult, type SamaranOptions, type DetectOptions, type Confidence, } from './samaran/index.ts';
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export { parseNpwp, formatNpwp15 } from './npwp.js';
|
|
|
3
3
|
export { parsePhone, normalizePhone } from './phone.js';
|
|
4
4
|
export { formatRupiah, formatRupiahShort, parseRupiah, } from './rupiah.js';
|
|
5
5
|
export { terbilang } from './terbilang.js';
|
|
6
|
+
export { parseQris, setQrisAmount, qrisCrc, } from './qris.js';
|
|
6
7
|
export { PROVINCES } from './provinces.js';
|
|
7
8
|
export { getHolidays, holidaysOn, isWorkingDay, addWorkingDays, countWorkingDays, HOLIDAY_YEARS, } from './holidays.js';
|
|
8
9
|
export { Samaran, maskPii, detectPii, partialMask, fieldType, PII_TYPES, UU_PDP_CATEGORY, } from './samaran/index.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAA+D,MAAM,UAAU,CAAC;AAC7G,OAAO,EAAE,SAAS,EAAE,YAAY,EAAgC,MAAM,WAAW,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,cAAc,EAAkC,MAAM,YAAY,CAAC;AACxF,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,WAAW,GAGZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAyB,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,aAAa,GAKd,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,OAAO,EACP,OAAO,EACP,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,eAAe,GAQhB,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAA+D,MAAM,UAAU,CAAC;AAC7G,OAAO,EAAE,SAAS,EAAE,YAAY,EAAgC,MAAM,WAAW,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,cAAc,EAAkC,MAAM,YAAY,CAAC;AACxF,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,WAAW,GAGZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAyB,MAAM,gBAAgB,CAAC;AAClE,OAAO,EACL,SAAS,EACT,aAAa,EACb,OAAO,GAOR,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,aAAa,GAKd,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,OAAO,EACP,OAAO,EACP,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,eAAe,GAQhB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const MALE_FIRST: readonly string[];
|
|
2
|
+
export declare const FEMALE_FIRST: readonly string[];
|
|
3
|
+
export declare const MALE_LAST: readonly string[];
|
|
4
|
+
export declare const FEMALE_LAST: readonly string[];
|
|
5
|
+
export declare const STREETS: readonly string[];
|
|
6
|
+
export declare const HEALTH: readonly string[];
|
|
7
|
+
export declare const RELIGIONS: readonly string[];
|
|
8
|
+
export declare const MARITAL: readonly string[];
|
|
9
|
+
/** Honorifics and connecting words in a name that say nothing about who the person is. */
|
|
10
|
+
export declare const NAME_KEEP: ReadonlySet<string>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Word lists for Kembaran's stand-in values: common Indonesian given names and family names from many regions,
|
|
2
|
+
// street names of the kind found in every town, and harmless health complaints. Combinations are random, so a
|
|
3
|
+
// stand-in that happens to match a real person's name is a coincidence, not a link to them.
|
|
4
|
+
// python/src/lokal/_kembaran_data.py holds the same lists, in the same order.
|
|
5
|
+
export const MALE_FIRST = [
|
|
6
|
+
'Agus', 'Ahmad', 'Andi', 'Anton', 'Arif', 'Asep', 'Bagus', 'Bambang', 'Bayu', 'Benny', 'Budi', 'Cecep', 'Dadang',
|
|
7
|
+
'Dani', 'Daniel', 'Dedi', 'Dimas', 'Doni', 'Edi', 'Eko', 'Fajar', 'Farhan', 'Fikri', 'Galih', 'Gede', 'Gilang',
|
|
8
|
+
'Hadi', 'Hari', 'Hendra', 'Heru', 'Ilham', 'Imam', 'Indra', 'Irfan', 'Ivan', 'Iwan', 'Joko', 'Ketut', 'Kevin',
|
|
9
|
+
'Komang', 'Krisna', 'Lukman', 'Made', 'Michael', 'Muhammad', 'Nyoman', 'Paulus', 'Putu', 'Rahmat', 'Rangga',
|
|
10
|
+
'Reza', 'Ridwan', 'Rizki', 'Rudi', 'Satria', 'Sigit', 'Slamet', 'Steven', 'Surya', 'Taufik', 'Teguh', 'Togar',
|
|
11
|
+
'Tono', 'Ujang', 'Wahyu', 'Wawan', 'Yoga', 'Yohanes', 'Yudi', 'Yusuf', 'Zainal',
|
|
12
|
+
];
|
|
13
|
+
export const FEMALE_FIRST = [
|
|
14
|
+
'Ana', 'Ani', 'Ayu', 'Butet', 'Citra', 'Desi', 'Dewi', 'Dian', 'Erna', 'Euis', 'Fitri', 'Fransiska', 'Grace',
|
|
15
|
+
'Hana', 'Iis', 'Indah', 'Intan', 'Irma', 'Jessica', 'Kartika', 'Lina', 'Lusi', 'Maya', 'Mega', 'Nadia', 'Neng',
|
|
16
|
+
'Nina', 'Novi', 'Nur', 'Nurul', 'Putri', 'Rahma', 'Ratna', 'Rina', 'Rini', 'Rosa', 'Santi', 'Sari', 'Siti', 'Sri',
|
|
17
|
+
'Susi', 'Tari', 'Tuti', 'Vina', 'Widya', 'Wulan', 'Yanti', 'Yohana', 'Yuni',
|
|
18
|
+
];
|
|
19
|
+
export const MALE_LAST = [
|
|
20
|
+
'Damanik', 'Daulay', 'Effendi', 'Firmansyah', 'Ginting', 'Gunawan', 'Hakim', 'Halim', 'Harahap', 'Hartono',
|
|
21
|
+
'Haryanto', 'Hermawan', 'Hidayat', 'Hutapea', 'Kurniawan', 'Lubis', 'Manurung', 'Matondang', 'Maulana', 'Nasution',
|
|
22
|
+
'Nugroho', 'Panjaitan', 'Pane', 'Pratama', 'Prasetyo', 'Purba', 'Purnomo', 'Rahman', 'Ramadhan', 'Rangkuti',
|
|
23
|
+
'Santoso', 'Saputra', 'Sembiring', 'Setiawan', 'Simanjuntak', 'Sinaga', 'Siregar', 'Sitepu', 'Sugiarto', 'Suryadi',
|
|
24
|
+
'Susanto', 'Sutrisno', 'Syahputra', 'Tambunan', 'Tanjung', 'Tarigan', 'Utomo', 'Wahyudi', 'Wibowo', 'Wijaya',
|
|
25
|
+
];
|
|
26
|
+
export const FEMALE_LAST = [
|
|
27
|
+
'Andriani', 'Anggraini', 'Astuti', 'Damayanti', 'Fitriani', 'Ginting', 'Halim', 'Handayani', 'Hapsari', 'Harahap',
|
|
28
|
+
'Kartini', 'Kusumawati', 'Lestari', 'Lubis', 'Maharani', 'Nasution', 'Ningsih', 'Novitasari', 'Oktaviani',
|
|
29
|
+
'Permata', 'Pertiwi', 'Puspita', 'Purnamasari', 'Rahayu', 'Rahmawati', 'Safitri', 'Sari', 'Sinaga', 'Siregar',
|
|
30
|
+
'Susanti', 'Suryani', 'Tanjung', 'Tarigan', 'Utami', 'Wahyuni', 'Wijaya', 'Wulandari', 'Yuliani',
|
|
31
|
+
];
|
|
32
|
+
export const STREETS = [
|
|
33
|
+
'Akasia', 'Anggrek', 'Bahagia', 'Bakti', 'Beringin', 'Cemara', 'Cempaka', 'Cendrawasih', 'Dahlia', 'Damai', 'Durian',
|
|
34
|
+
'Elang', 'Flamboyan', 'Harapan', 'Jati', 'Karya', 'Kelapa', 'Kemuning', 'Kenanga', 'Kutilang', 'Mahoni', 'Mangga',
|
|
35
|
+
'Melati', 'Merdeka', 'Merpati', 'Nusa Indah', 'Pahlawan', 'Pelita', 'Pemuda', 'Rajawali', 'Rambutan', 'Sejahtera',
|
|
36
|
+
'Seroja', 'Swadaya', 'Teratai',
|
|
37
|
+
];
|
|
38
|
+
export const HEALTH = ['Sehat', 'Flu', 'Demam', 'Batuk', 'Sakit kepala', 'Alergi ringan', 'Maag', 'Pegal linu'];
|
|
39
|
+
export const RELIGIONS = ['Islam', 'Kristen', 'Katolik', 'Hindu', 'Buddha', 'Konghucu'];
|
|
40
|
+
export const MARITAL = ['Belum Kawin', 'Kawin', 'Cerai Hidup', 'Cerai Mati'];
|
|
41
|
+
/** Honorifics and connecting words in a name that say nothing about who the person is. */
|
|
42
|
+
export const NAME_KEEP = new Set([
|
|
43
|
+
'bapak', 'bpk', 'ibu', 'bu', 'pak', 'sdr', 'sdri', 'tn', 'ny', 'nn', 'kak', 'mas', 'mbak', 'bin', 'binti', 'dr', 'drs',
|
|
44
|
+
'dra', 'ir', 'h', 'hj', 'prof', 'st', 'se', 'sh', 'mm', 'skom', 'spd', 'amd',
|
|
45
|
+
]);
|
|
46
|
+
//# sourceMappingURL=kembaran-data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kembaran-data.js","sourceRoot":"","sources":["../src/kembaran-data.ts"],"names":[],"mappings":"AAAA,+GAA+G;AAC/G,8GAA8G;AAC9G,4FAA4F;AAC5F,8EAA8E;AAE9E,MAAM,CAAC,MAAM,UAAU,GAAsB;IAC3C,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ;IAChH,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ;IAC9G,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAC7G,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ;IAC3G,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO;IAC7G,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ;CAChF,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAsB;IAC7C,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO;IAC5G,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAC9G,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK;IACjH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM;CAC5E,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAsB;IAC1C,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;IAC1G,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU;IAClH,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU;IAC3G,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS;IAClH,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ;CAC7G,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAsB;IAC5C,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS;IACjH,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW;IACzG,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS;IAC7G,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS;CACjG,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAsB;IACxC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ;IACpH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ;IACjH,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW;IACjH,QAAQ,EAAE,SAAS,EAAE,SAAS;CAC/B,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAsB,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;AAEnI,MAAM,CAAC,MAAM,SAAS,GAAsB,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;AAC3G,MAAM,CAAC,MAAM,OAAO,GAAsB,CAAC,aAAa,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC;AAEhG,0FAA0F;AAC1F,MAAM,CAAC,MAAM,SAAS,GAAwB,IAAI,GAAG,CAAC;IACpD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK;IACtH,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK;CAC7E,CAAC,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Confidence, type PiiType } from './samaran/index.ts';
|
|
2
|
+
export interface KembaranOptions {
|
|
3
|
+
/** The same secret gives the same stand-ins on every run. Without one, each run picks a random secret. */
|
|
4
|
+
secret?: string;
|
|
5
|
+
/** Types left as they are. Default: gender, religion, marital status, and nationality, which identify no one. */
|
|
6
|
+
keep?: readonly PiiType[];
|
|
7
|
+
/** Keep the whole birth date, not just the year: more useful for debugging, easier to single someone out. */
|
|
8
|
+
keepBirthDate?: boolean;
|
|
9
|
+
/** "high" replaces only validated or labeled matches. Default "medium". */
|
|
10
|
+
minConfidence?: Confidence;
|
|
11
|
+
}
|
|
12
|
+
export interface KembaranResult {
|
|
13
|
+
text: string;
|
|
14
|
+
/** How many values of each type were replaced. */
|
|
15
|
+
replaced: Partial<Record<PiiType, number>>;
|
|
16
|
+
}
|
|
17
|
+
export declare const KEEP_BY_DEFAULT: readonly PiiType[];
|
|
18
|
+
interface Day {
|
|
19
|
+
day: number;
|
|
20
|
+
month: number;
|
|
21
|
+
}
|
|
22
|
+
export declare class Kembaran {
|
|
23
|
+
private readonly key;
|
|
24
|
+
private readonly keep;
|
|
25
|
+
private readonly keepBirthDate;
|
|
26
|
+
private readonly minConfidence;
|
|
27
|
+
private readonly fakes;
|
|
28
|
+
private readonly used;
|
|
29
|
+
private readonly nikDays;
|
|
30
|
+
constructor(options?: KembaranOptions);
|
|
31
|
+
/** Replaces every piece of personal data in a text: a CSV, an SQL dump, JSON, a log, or prose. */
|
|
32
|
+
text(input: string): KembaranResult;
|
|
33
|
+
/** The stand-in for one value of a known type. */
|
|
34
|
+
value(type: PiiType, original: string, rowDay?: Day): string;
|
|
35
|
+
/** The words of a name that identify the person: not honorifics, titles, or "bin". */
|
|
36
|
+
private nameCore;
|
|
37
|
+
/** A stand-in in canonical form: digits for numbers, words joined by spaces for names. */
|
|
38
|
+
private make;
|
|
39
|
+
/** A stand-in in the original's format: its separators, its casing, its titles. */
|
|
40
|
+
private render;
|
|
41
|
+
private address;
|
|
42
|
+
private birthDate;
|
|
43
|
+
}
|
|
44
|
+
/** One-shot: replaces personal data in a text with stand-ins under a random secret. */
|
|
45
|
+
export declare function kembaran(text: string, options?: KembaranOptions): KembaranResult;
|
|
46
|
+
export {};
|
package/dist/kembaran.js
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
// Kembaran ("twin"): replaces Indonesian personal data with realistic stand-ins, so a copy of production data can go
|
|
2
|
+
// to staging, a developer's laptop, or a vendor without anyone in it being a real person.
|
|
3
|
+
//
|
|
4
|
+
// Unlike Samaran's [NIK_1] placeholders, the result looks like the original and still works as data:
|
|
5
|
+
// - The same value always gets the same stand-in, across tables and files, so joins and foreign keys hold.
|
|
6
|
+
// - Stand-ins keep what analysis needs and nothing that identifies: a NIK keeps its district, gender, and birth year;
|
|
7
|
+
// a phone number its operator; an address its RT/RW and area; a name its number of words and its casing.
|
|
8
|
+
// - Within one line (a CSV row, an SQL tuple), a birth date follows the stand-in NIK, so the row stays consistent.
|
|
9
|
+
// - Stand-ins come from HMAC-SHA256 under a secret: random for each run unless one is given, and never reversible
|
|
10
|
+
// without it. Unique values (NIK, phone, account numbers) never collide.
|
|
11
|
+
//
|
|
12
|
+
// Node only (node:crypto), like @lokal-id/core/wilayah. python/src/lokal/kembaran.py gives identical output for the
|
|
13
|
+
// same secret.
|
|
14
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
15
|
+
import { FEMALE_FIRST, FEMALE_LAST, HEALTH, MALE_FIRST, MALE_LAST, MARITAL, NAME_KEEP, RELIGIONS, STREETS, } from './kembaran-data.js';
|
|
16
|
+
import { parsePhone } from './phone.js';
|
|
17
|
+
import { canonical, detectPii, PII_TYPES } from './samaran/index.js';
|
|
18
|
+
export const KEEP_BY_DEFAULT = ['GENDER', 'RELIGION', 'MARITAL_STATUS', 'NATIONALITY'];
|
|
19
|
+
// Values that must stay unique: two people must not end up with one stand-in.
|
|
20
|
+
const UNIQUE = new Set([
|
|
21
|
+
'NIK', 'KK', 'NPWP', 'PHONE', 'EMAIL', 'BANK_ACCOUNT', 'CARD', 'BPJS', 'SIM', 'NIP', 'PASSPORT', 'PLATE', 'IP',
|
|
22
|
+
]);
|
|
23
|
+
const MONTHS = [
|
|
24
|
+
['januari', 'februari', 'maret', 'april', 'mei', 'juni', 'juli', 'agustus', 'september', 'oktober', 'november', 'desember'],
|
|
25
|
+
['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'],
|
|
26
|
+
['jan', 'feb', 'mar', 'apr', 'mei', 'jun', 'jul', 'agu', 'sep', 'okt', 'nov', 'des'],
|
|
27
|
+
['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'],
|
|
28
|
+
];
|
|
29
|
+
const MONTH_ALIASES = { agt: 7, ags: 7, sept: 8, nop: 10, peb: 1 };
|
|
30
|
+
const MONTH_NAMES = [...new Set([...MONTHS.flat(), ...Object.keys(MONTH_ALIASES)])].sort((a, b) => b.length - a.length).join('|');
|
|
31
|
+
const DMY = /(\d{1,2})([-/. ])(\d{1,2})\2(\d{4})/;
|
|
32
|
+
const YMD = /(\d{4})([-/.])(\d{1,2})\2(\d{1,2})/;
|
|
33
|
+
const D_NAME_Y = new RegExp(`(\\d{1,2})(\\s+)(${MONTH_NAMES})(\\.?\\s+)(\\d{4})`, 'i');
|
|
34
|
+
const EXCEL_SERIAL = /^\d{5}$/;
|
|
35
|
+
const STREET = /\b(Jl|Jln|Jalan|Gg|Gang|Komp|Kompleks|Perum|Perumahan)(\.?\s+)([A-Za-z][A-Za-z.'-]*(?:\s+[A-Za-z][A-Za-z.'-]*)*?)(?=\s+(?:No|Nomor|Blok|Kav|RT|RW)\b|\s*\d|\s*$)/i;
|
|
36
|
+
const INITIAL = /^[A-Za-z]\.$/;
|
|
37
|
+
const LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
38
|
+
const FEMALE_SET = new Set(FEMALE_FIRST.map((n) => n.toLowerCase()));
|
|
39
|
+
const MALE_SET = new Set(MALE_FIRST.map((n) => n.toLowerCase()));
|
|
40
|
+
/**
|
|
41
|
+
* HMAC-SHA256 under one key, with the padded key hashed once: createHmac re-imports the key on every call, which
|
|
42
|
+
* made a 100,000-row file take seconds longer.
|
|
43
|
+
*/
|
|
44
|
+
class Hmac {
|
|
45
|
+
inner;
|
|
46
|
+
outer;
|
|
47
|
+
constructor(secret) {
|
|
48
|
+
const key = Buffer.alloc(64);
|
|
49
|
+
(secret.length > 64 ? createHash('sha256').update(secret).digest() : secret).copy(key);
|
|
50
|
+
this.inner = createHash('sha256').update(key.map((b) => b ^ 0x36));
|
|
51
|
+
this.outer = createHash('sha256').update(key.map((b) => b ^ 0x5c));
|
|
52
|
+
}
|
|
53
|
+
digest(message) {
|
|
54
|
+
return this.outer.copy().update(this.inner.copy().update(message).digest()).digest();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** A stream of numbers from HMAC-SHA256(secret, label): the same label always gives the same stream. */
|
|
58
|
+
class Stream {
|
|
59
|
+
block = 0;
|
|
60
|
+
buf = Buffer.alloc(0);
|
|
61
|
+
pos = 32;
|
|
62
|
+
key;
|
|
63
|
+
label;
|
|
64
|
+
constructor(key, label) {
|
|
65
|
+
this.key = key;
|
|
66
|
+
this.label = label;
|
|
67
|
+
}
|
|
68
|
+
int(n) {
|
|
69
|
+
if (this.pos + 4 > 32) {
|
|
70
|
+
this.buf = this.key.digest(`${this.label}#${this.block++}`);
|
|
71
|
+
this.pos = 0;
|
|
72
|
+
}
|
|
73
|
+
const v = this.buf.readUInt32BE(this.pos);
|
|
74
|
+
this.pos += 4;
|
|
75
|
+
return v % n;
|
|
76
|
+
}
|
|
77
|
+
pick(xs) {
|
|
78
|
+
return xs[this.int(xs.length)];
|
|
79
|
+
}
|
|
80
|
+
digits(n) {
|
|
81
|
+
let out = '';
|
|
82
|
+
for (let i = 0; i < n; i++)
|
|
83
|
+
out += String(this.int(10));
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const pad = (n, width = 2) => String(n).padStart(width, '0');
|
|
88
|
+
const onlyDigits = (s) => s.replace(/\D/g, '');
|
|
89
|
+
/** Writes `digits` into the digit positions of `template`, keeping its separators: "0812-3456-7890". */
|
|
90
|
+
function putDigits(template, digits) {
|
|
91
|
+
if (onlyDigits(template).length !== digits.length)
|
|
92
|
+
return digits;
|
|
93
|
+
let i = 0;
|
|
94
|
+
return template.replace(/\d/g, () => digits[i++]);
|
|
95
|
+
}
|
|
96
|
+
/** Same casing as `like`: "BUDI", "budi", or "Budi". */
|
|
97
|
+
function caseLike(word, like) {
|
|
98
|
+
if (like.length > 1 && like === like.toUpperCase() && like !== like.toLowerCase())
|
|
99
|
+
return word.toUpperCase();
|
|
100
|
+
if (like === like.toLowerCase() && like !== like.toUpperCase())
|
|
101
|
+
return word.toLowerCase();
|
|
102
|
+
return word;
|
|
103
|
+
}
|
|
104
|
+
/** Each run of digits replaced by random digits of the same length, keeping a leading zero; never a leading zero otherwise. */
|
|
105
|
+
function shapeDigits(s, rng) {
|
|
106
|
+
// "03" stays "0x", as an RT number would be written.
|
|
107
|
+
return s.replace(/\d+/g, (run) => run
|
|
108
|
+
.split('')
|
|
109
|
+
.map((d, i) => (i > 0 ? String(rng.int(10)) : d === '0' && run.length > 1 ? '0' : String(1 + rng.int(9))))
|
|
110
|
+
.join(''));
|
|
111
|
+
}
|
|
112
|
+
/** Letters to random letters of the same case, digits to random digits; anything else stays. */
|
|
113
|
+
function shapeAll(s, rng) {
|
|
114
|
+
let out = '';
|
|
115
|
+
for (const ch of s) {
|
|
116
|
+
if (/\d/.test(ch))
|
|
117
|
+
out += String(rng.int(10));
|
|
118
|
+
else if (/[A-Z]/.test(ch))
|
|
119
|
+
out += LETTERS[rng.int(26)];
|
|
120
|
+
else if (/[a-z]/.test(ch))
|
|
121
|
+
out += LETTERS[rng.int(26)].toLowerCase();
|
|
122
|
+
else
|
|
123
|
+
out += ch;
|
|
124
|
+
}
|
|
125
|
+
return out;
|
|
126
|
+
}
|
|
127
|
+
function luhnFix(digits) {
|
|
128
|
+
const body = digits.slice(0, -1);
|
|
129
|
+
let sum = 0;
|
|
130
|
+
for (let i = 0; i < body.length; i++) {
|
|
131
|
+
let d = Number(body[body.length - 1 - i]);
|
|
132
|
+
if (i % 2 === 0) {
|
|
133
|
+
d *= 2;
|
|
134
|
+
if (d > 9)
|
|
135
|
+
d -= 9;
|
|
136
|
+
}
|
|
137
|
+
sum += d;
|
|
138
|
+
}
|
|
139
|
+
return body + String((10 - (sum % 10)) % 10);
|
|
140
|
+
}
|
|
141
|
+
export class Kembaran {
|
|
142
|
+
key;
|
|
143
|
+
keep;
|
|
144
|
+
keepBirthDate;
|
|
145
|
+
minConfidence;
|
|
146
|
+
fakes = new Map();
|
|
147
|
+
used = new Map();
|
|
148
|
+
nikDays = new Map();
|
|
149
|
+
constructor(options = {}) {
|
|
150
|
+
for (const t of options.keep ?? []) {
|
|
151
|
+
if (!PII_TYPES.includes(t))
|
|
152
|
+
throw new RangeError(`Unknown PII type "${t}". Valid types: ${PII_TYPES.join(', ')}`);
|
|
153
|
+
}
|
|
154
|
+
this.key = new Hmac(options.secret !== undefined ? Buffer.from(options.secret, 'utf8') : randomBytes(32));
|
|
155
|
+
this.keep = new Set(options.keep ?? KEEP_BY_DEFAULT);
|
|
156
|
+
this.keepBirthDate = options.keepBirthDate ?? false;
|
|
157
|
+
this.minConfidence = options.minConfidence ?? 'medium';
|
|
158
|
+
}
|
|
159
|
+
/** Replaces every piece of personal data in a text: a CSV, an SQL dump, JSON, a log, or prose. */
|
|
160
|
+
text(input) {
|
|
161
|
+
const matches = detectPii(input, { minConfidence: this.minConfidence, exclude: [...this.keep] });
|
|
162
|
+
const lineStarts = [0];
|
|
163
|
+
for (let i = input.indexOf('\n'); i >= 0; i = input.indexOf('\n', i + 1))
|
|
164
|
+
lineStarts.push(i + 1);
|
|
165
|
+
const lineOf = (pos) => {
|
|
166
|
+
let lo = 0;
|
|
167
|
+
let hi = lineStarts.length - 1;
|
|
168
|
+
while (lo < hi) {
|
|
169
|
+
const mid = (lo + hi + 1) >> 1;
|
|
170
|
+
if (lineStarts[mid] <= pos)
|
|
171
|
+
lo = mid;
|
|
172
|
+
else
|
|
173
|
+
hi = mid - 1;
|
|
174
|
+
}
|
|
175
|
+
return lo;
|
|
176
|
+
};
|
|
177
|
+
// NIKs first, so a birth date on the same line can follow the stand-in NIK.
|
|
178
|
+
const out = new Array(matches.length);
|
|
179
|
+
const rowDays = new Map();
|
|
180
|
+
matches.forEach((m, i) => {
|
|
181
|
+
if (m.type !== 'NIK')
|
|
182
|
+
return;
|
|
183
|
+
out[i] = this.value('NIK', m.value);
|
|
184
|
+
const day = this.nikDays.get(onlyDigits(out[i]));
|
|
185
|
+
const line = lineOf(m.start);
|
|
186
|
+
if (day && !rowDays.has(line))
|
|
187
|
+
rowDays.set(line, day);
|
|
188
|
+
});
|
|
189
|
+
matches.forEach((m, i) => {
|
|
190
|
+
if (out[i] === undefined)
|
|
191
|
+
out[i] = this.value(m.type, m.value, rowDays.get(lineOf(m.start)));
|
|
192
|
+
});
|
|
193
|
+
let text = '';
|
|
194
|
+
let cursor = 0;
|
|
195
|
+
const replaced = {};
|
|
196
|
+
matches.forEach((m, i) => {
|
|
197
|
+
text += input.slice(cursor, m.start) + out[i];
|
|
198
|
+
cursor = m.end;
|
|
199
|
+
replaced[m.type] = (replaced[m.type] ?? 0) + 1;
|
|
200
|
+
});
|
|
201
|
+
return { text: text + input.slice(cursor), replaced };
|
|
202
|
+
}
|
|
203
|
+
/** The stand-in for one value of a known type. */
|
|
204
|
+
value(type, original, rowDay) {
|
|
205
|
+
if (this.keep.has(type))
|
|
206
|
+
return original;
|
|
207
|
+
const canon = type === 'NAME' ? this.nameCore(original).map((t) => t.toLowerCase()).join(' ') : canonical(type, original);
|
|
208
|
+
if (type === 'BIRTH_DATE' && rowDay && !this.keepBirthDate)
|
|
209
|
+
return this.birthDate(original, new Stream(this.key, 'BIRTH_DATE|row'), rowDay);
|
|
210
|
+
const cacheKey = `${type}|${canon}`;
|
|
211
|
+
const cached = this.fakes.get(cacheKey);
|
|
212
|
+
if (cached !== undefined)
|
|
213
|
+
return this.render(type, original, cached);
|
|
214
|
+
let fake = '';
|
|
215
|
+
for (let attempt = 0; attempt < 100; attempt++) {
|
|
216
|
+
fake = this.make(type, original, canon, new Stream(this.key, `${type}|${canon}|${attempt}`));
|
|
217
|
+
if (!UNIQUE.has(type))
|
|
218
|
+
break;
|
|
219
|
+
const used = this.used.get(type) ?? new Set();
|
|
220
|
+
this.used.set(type, used);
|
|
221
|
+
if (!used.has(fake)) {
|
|
222
|
+
used.add(fake);
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
this.fakes.set(cacheKey, fake);
|
|
227
|
+
return this.render(type, original, fake);
|
|
228
|
+
}
|
|
229
|
+
/** The words of a name that identify the person: not honorifics, titles, or "bin". */
|
|
230
|
+
nameCore(name) {
|
|
231
|
+
return name.split(/\s+/).filter((w) => w && !NAME_KEEP.has(w.toLowerCase().replace(/[.,]/g, '')));
|
|
232
|
+
}
|
|
233
|
+
/** A stand-in in canonical form: digits for numbers, words joined by spaces for names. */
|
|
234
|
+
make(type, original, canon, rng) {
|
|
235
|
+
switch (type) {
|
|
236
|
+
case 'NIK': {
|
|
237
|
+
const d = onlyDigits(original);
|
|
238
|
+
if (d.length !== 16)
|
|
239
|
+
return d.slice(0, 6) + rng.digits(Math.max(0, d.length - 6));
|
|
240
|
+
const female = Number(d.slice(6, 8)) > 40;
|
|
241
|
+
let day = { day: Number(d.slice(6, 8)) - (female ? 40 : 0), month: Number(d.slice(8, 10)) };
|
|
242
|
+
if (!this.keepBirthDate)
|
|
243
|
+
day = { day: 1 + rng.int(28), month: 1 + rng.int(12) };
|
|
244
|
+
const nik = d.slice(0, 6) + pad(day.day + (female ? 40 : 0)) + pad(day.month) + d.slice(10, 12) + pad(1 + rng.int(9999), 4);
|
|
245
|
+
this.nikDays.set(nik, day);
|
|
246
|
+
return nik;
|
|
247
|
+
}
|
|
248
|
+
case 'KK':
|
|
249
|
+
return onlyDigits(original).slice(0, 6) + rng.digits(Math.max(0, onlyDigits(original).length - 6));
|
|
250
|
+
case 'NPWP': {
|
|
251
|
+
const d = onlyDigits(original);
|
|
252
|
+
// An individual's NPWP is their NIK: the same person keeps one stand-in for both.
|
|
253
|
+
if (d.length === 16 && d[0] !== '0')
|
|
254
|
+
return onlyDigits(this.value('NIK', d));
|
|
255
|
+
return d.slice(0, 1) + rng.digits(Math.max(0, d.length - 1));
|
|
256
|
+
}
|
|
257
|
+
case 'PHONE': {
|
|
258
|
+
if (canon.startsWith('+62'))
|
|
259
|
+
return canon.slice(0, 6) + rng.digits(canon.length - 6);
|
|
260
|
+
const d = onlyDigits(original);
|
|
261
|
+
return d.slice(0, 4) + rng.digits(Math.max(0, d.length - 4));
|
|
262
|
+
}
|
|
263
|
+
case 'EMAIL': {
|
|
264
|
+
const female = rng.int(2) === 1;
|
|
265
|
+
const first = rng.pick(female ? FEMALE_FIRST : MALE_FIRST).toLowerCase();
|
|
266
|
+
const last = rng.pick(female ? FEMALE_LAST : MALE_LAST).toLowerCase();
|
|
267
|
+
return `${first}.${last}${pad(rng.int(100))}`;
|
|
268
|
+
}
|
|
269
|
+
case 'NAME': {
|
|
270
|
+
const core = this.nameCore(original);
|
|
271
|
+
const lead = core.find((w) => !INITIAL.test(w))?.toLowerCase().replace(/[.,]/g, '');
|
|
272
|
+
const female = lead !== undefined && FEMALE_SET.has(lead) ? true : lead !== undefined && MALE_SET.has(lead) ? false : rng.int(2) === 1;
|
|
273
|
+
const words = [];
|
|
274
|
+
let firstDone = false;
|
|
275
|
+
for (const w of core) {
|
|
276
|
+
if (INITIAL.test(w))
|
|
277
|
+
words.push(`${LETTERS[rng.int(26)]}.`);
|
|
278
|
+
else if (!firstDone) {
|
|
279
|
+
words.push(rng.pick(female ? FEMALE_FIRST : MALE_FIRST));
|
|
280
|
+
firstDone = true;
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
let next = rng.pick(female ? FEMALE_LAST : MALE_LAST);
|
|
284
|
+
for (let i = 0; i < 5 && words.includes(next); i++)
|
|
285
|
+
next = rng.pick(female ? FEMALE_LAST : MALE_LAST);
|
|
286
|
+
words.push(next);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return words.join(' ');
|
|
290
|
+
}
|
|
291
|
+
case 'ADDRESS':
|
|
292
|
+
return this.address(original, rng);
|
|
293
|
+
case 'BIRTH_DATE':
|
|
294
|
+
return this.keepBirthDate ? original : this.birthDate(original, rng);
|
|
295
|
+
case 'BANK_ACCOUNT':
|
|
296
|
+
case 'BPJS':
|
|
297
|
+
case 'SIM':
|
|
298
|
+
return rng.digits(onlyDigits(original).length);
|
|
299
|
+
case 'NIP': {
|
|
300
|
+
const d = onlyDigits(original);
|
|
301
|
+
return d.slice(0, 4) + rng.digits(Math.max(0, d.length - 4));
|
|
302
|
+
}
|
|
303
|
+
case 'CARD': {
|
|
304
|
+
const d = onlyDigits(original);
|
|
305
|
+
return d.length > 7 ? luhnFix(d.slice(0, 6) + rng.digits(d.length - 6)) : rng.digits(d.length);
|
|
306
|
+
}
|
|
307
|
+
case 'PASSPORT':
|
|
308
|
+
return original.slice(0, 1) + shapeAll(original.slice(1), rng);
|
|
309
|
+
case 'PLATE': {
|
|
310
|
+
const m = /^([A-Za-z]{1,2})(\s*)(\d{1,4})(\s*)([A-Za-z]{0,3})$/.exec(original.trim());
|
|
311
|
+
if (!m)
|
|
312
|
+
return shapeAll(original, rng);
|
|
313
|
+
const num = String(1 + rng.int(9)) + rng.digits(m[3].length - 1);
|
|
314
|
+
const suffix = m[5].split('').map((c) => caseLike(LETTERS[rng.int(26)], c)).join('');
|
|
315
|
+
return `${m[1]}${m[2]}${num}${m[4]}${suffix}`;
|
|
316
|
+
}
|
|
317
|
+
case 'IP':
|
|
318
|
+
if (original.includes(':'))
|
|
319
|
+
return `2001:db8::${rng.int(65536).toString(16)}:${rng.int(65536).toString(16)}`;
|
|
320
|
+
return `${rng.pick(['192.0.2', '198.51.100', '203.0.113'])}.${1 + rng.int(254)}`;
|
|
321
|
+
case 'GEO':
|
|
322
|
+
return original.replace(/(\.\d{2})(\d+)/g, (_, keep, rest) => keep + rng.digits(rest.length));
|
|
323
|
+
case 'FINANCIAL':
|
|
324
|
+
return shapeDigits(original, rng);
|
|
325
|
+
case 'HEALTH':
|
|
326
|
+
return caseLike(rng.pick(HEALTH), original);
|
|
327
|
+
case 'CRIMINAL_RECORD':
|
|
328
|
+
return caseLike('Tidak ada catatan', original);
|
|
329
|
+
case 'BIOMETRIC': {
|
|
330
|
+
const dot = original.lastIndexOf('.');
|
|
331
|
+
const ext = dot > 0 && original.length - dot <= 5 ? original.slice(dot) : '';
|
|
332
|
+
return shapeAll(original.slice(0, original.length - ext.length), rng) + ext;
|
|
333
|
+
}
|
|
334
|
+
case 'GENDER':
|
|
335
|
+
return original.trim().length === 1 ? rng.pick(['L', 'P']) : rng.pick(['Laki-laki', 'Perempuan']);
|
|
336
|
+
case 'RELIGION':
|
|
337
|
+
return rng.pick(RELIGIONS);
|
|
338
|
+
case 'MARITAL_STATUS':
|
|
339
|
+
return rng.pick(MARITAL);
|
|
340
|
+
case 'NATIONALITY':
|
|
341
|
+
return 'WNI';
|
|
342
|
+
default:
|
|
343
|
+
return shapeAll(original, rng);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
/** A stand-in in the original's format: its separators, its casing, its titles. */
|
|
347
|
+
render(type, original, fake) {
|
|
348
|
+
switch (type) {
|
|
349
|
+
case 'NIK':
|
|
350
|
+
case 'KK':
|
|
351
|
+
case 'NPWP':
|
|
352
|
+
case 'BANK_ACCOUNT':
|
|
353
|
+
case 'BPJS':
|
|
354
|
+
case 'SIM':
|
|
355
|
+
case 'NIP':
|
|
356
|
+
case 'CARD':
|
|
357
|
+
return putDigits(original, fake);
|
|
358
|
+
case 'PHONE': {
|
|
359
|
+
if (!fake.startsWith('+62'))
|
|
360
|
+
return putDigits(original, fake);
|
|
361
|
+
const d = onlyDigits(original);
|
|
362
|
+
const digits = d.startsWith('0') ? `0${fake.slice(3)}` : d.startsWith('62') ? fake.slice(1) : fake.slice(3);
|
|
363
|
+
return putDigits(original, digits);
|
|
364
|
+
}
|
|
365
|
+
case 'EMAIL':
|
|
366
|
+
return original.includes('@') ? `${fake}@example.com` : `${fake} [at] example [dot] com`;
|
|
367
|
+
case 'NAME': {
|
|
368
|
+
const words = fake.split(' ');
|
|
369
|
+
let i = 0;
|
|
370
|
+
return original
|
|
371
|
+
.split(/(\s+)/)
|
|
372
|
+
.map((part) => {
|
|
373
|
+
if (!part || /^\s+$/.test(part) || NAME_KEEP.has(part.toLowerCase().replace(/[.,]/g, '')))
|
|
374
|
+
return part;
|
|
375
|
+
const word = words[i++] ?? part;
|
|
376
|
+
const trail = /[,]$/.test(part) ? ',' : '';
|
|
377
|
+
return caseLike(word, part.replace(/[,]$/, '')) + trail;
|
|
378
|
+
})
|
|
379
|
+
.join('');
|
|
380
|
+
}
|
|
381
|
+
default:
|
|
382
|
+
return fake;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
address(original, rng) {
|
|
386
|
+
const comma = original.indexOf(',');
|
|
387
|
+
const head = comma < 0 ? original : original.slice(0, comma);
|
|
388
|
+
const tail = comma < 0 ? '' : original.slice(comma);
|
|
389
|
+
const street = head.replace(STREET, (_, kind, gap, name) => kind + gap + caseLike(rng.pick(STREETS), name));
|
|
390
|
+
return shapeDigits(street, rng) + tail;
|
|
391
|
+
}
|
|
392
|
+
birthDate(original, rng, rowDay) {
|
|
393
|
+
if (EXCEL_SERIAL.test(original.trim())) {
|
|
394
|
+
const date = new Date(Date.UTC(1899, 11, 30) + Number(original.trim()) * 86400000);
|
|
395
|
+
const day = rowDay ?? { day: 1 + rng.int(28), month: 1 + rng.int(12) };
|
|
396
|
+
return String(Math.round((Date.UTC(date.getUTCFullYear(), day.month - 1, day.day) - Date.UTC(1899, 11, 30)) / 86400000));
|
|
397
|
+
}
|
|
398
|
+
const pick = () => rowDay ?? { day: 1 + rng.int(28), month: 1 + rng.int(12) };
|
|
399
|
+
const width = (s, n) => (s.length >= 2 ? pad(n) : String(n));
|
|
400
|
+
let m = DMY.exec(original);
|
|
401
|
+
if (m) {
|
|
402
|
+
const d = pick();
|
|
403
|
+
return original.replace(DMY, `${width(m[1], d.day)}${m[2]}${width(m[3], d.month)}${m[2]}${m[4]}`);
|
|
404
|
+
}
|
|
405
|
+
m = YMD.exec(original);
|
|
406
|
+
if (m) {
|
|
407
|
+
const d = pick();
|
|
408
|
+
return original.replace(YMD, `${m[1]}${m[2]}${width(m[3], d.month)}${m[2]}${width(m[4], d.day)}`);
|
|
409
|
+
}
|
|
410
|
+
m = D_NAME_Y.exec(original);
|
|
411
|
+
if (m) {
|
|
412
|
+
const d = pick();
|
|
413
|
+
const word = m[3].toLowerCase();
|
|
414
|
+
const family = MONTHS.find((names) => names.includes(word)) ?? MONTHS[2];
|
|
415
|
+
const name = family[d.month - 1];
|
|
416
|
+
const styled = caseLike(name.charAt(0).toUpperCase() + name.slice(1), m[3]);
|
|
417
|
+
return original.replace(D_NAME_Y, `${width(m[1], d.day)}${m[2]}${styled}${m[4]}${m[5]}`);
|
|
418
|
+
}
|
|
419
|
+
return original;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
/** One-shot: replaces personal data in a text with stand-ins under a random secret. */
|
|
423
|
+
export function kembaran(text, options = {}) {
|
|
424
|
+
return new Kembaran(options).text(text);
|
|
425
|
+
}
|
|
426
|
+
//# sourceMappingURL=kembaran.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kembaran.js","sourceRoot":"","sources":["../src/kembaran.ts"],"names":[],"mappings":"AAAA,qHAAqH;AACrH,0FAA0F;AAC1F,EAAE;AACF,qGAAqG;AACrG,2GAA2G;AAC3G,sHAAsH;AACtH,2GAA2G;AAC3G,mHAAmH;AACnH,kHAAkH;AAClH,2EAA2E;AAC3E,EAAE;AACF,oHAAoH;AACpH,eAAe;AACf,OAAO,EAAE,UAAU,EAAE,WAAW,EAAa,MAAM,aAAa,CAAC;AACjE,OAAO,EACL,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,GACjG,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAiC,MAAM,oBAAoB,CAAC;AAmBpG,MAAM,CAAC,MAAM,eAAe,GAAuB,CAAC,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAC;AAE3G,8EAA8E;AAC9E,MAAM,MAAM,GAAyB,IAAI,GAAG,CAAC;IAC3C,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI;CAC/G,CAAC,CAAC;AAEH,MAAM,MAAM,GAAqC;IAC/C,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,CAAC;IAC3H,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,CAAC;IAC1H,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACpF,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;CACrF,CAAC;AACF,MAAM,aAAa,GAA2B,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;AAC3F,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClI,MAAM,GAAG,GAAG,qCAAqC,CAAC;AAClD,MAAM,GAAG,GAAG,oCAAoC,CAAC;AACjD,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,oBAAoB,WAAW,qBAAqB,EAAE,GAAG,CAAC,CAAC;AACvF,MAAM,YAAY,GAAG,SAAS,CAAC;AAC/B,MAAM,MAAM,GAAG,mKAAmK,CAAC;AACnL,MAAM,OAAO,GAAG,cAAc,CAAC;AAC/B,MAAM,OAAO,GAAG,4BAA4B,CAAC;AAC7C,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AACrE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AAEjE;;;GAGG;AACH,MAAM,IAAI;IACS,KAAK,CAAO;IACZ,KAAK,CAAO;IAC7B,YAAY,MAAc;QACxB,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7B,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvF,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QACnE,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,CAAC,OAAe;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IACvF,CAAC;CACF;AAED,wGAAwG;AACxG,MAAM,MAAM;IACF,KAAK,GAAG,CAAC,CAAC;IACV,GAAG,GAAW,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC9B,GAAG,GAAG,EAAE,CAAC;IACA,GAAG,CAAO;IACV,KAAK,CAAS;IAC/B,YAAY,GAAS,EAAE,KAAa;QAClC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,GAAG,CAAC,CAAS;QACX,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC;YACtB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC5D,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;QACf,CAAC;QACD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IAED,IAAI,CAAI,EAAgB;QACtB,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAE,CAAC;IAClC,CAAC;IAED,MAAM,CAAC,CAAS;QACd,IAAI,GAAG,GAAG,EAAE,CAAC;QACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QACxD,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACrE,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAEvD,wGAAwG;AACxG,SAAS,SAAS,CAAC,QAAgB,EAAE,MAAc;IACjD,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;QAAE,OAAO,MAAM,CAAC;IACjE,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAE,CAAC,CAAC;AACrD,CAAC;AAED,wDAAwD;AACxD,SAAS,QAAQ,CAAC,IAAY,EAAE,IAAY;IAC1C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE;QAAE,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7G,IAAI,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE;QAAE,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;IAC1F,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+HAA+H;AAC/H,SAAS,WAAW,CAAC,CAAS,EAAE,GAAW;IACzC,qDAAqD;IACrD,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAC/B,GAAG;SACA,KAAK,CAAC,EAAE,CAAC;SACT,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACzG,IAAI,CAAC,EAAE,CAAC,CACZ,CAAC;AACJ,CAAC;AAED,gGAAgG;AAChG,SAAS,QAAQ,CAAC,CAAS,EAAE,GAAW;IACtC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;QACnB,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;aACzC,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;aAClD,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAE,CAAC,WAAW,EAAE,CAAC;;YACjE,GAAG,IAAI,EAAE,CAAC;IACjB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,OAAO,CAAC,MAAc;IAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACjC,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1C,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAChB,CAAC,IAAI,CAAC,CAAC;YACP,IAAI,CAAC,GAAG,CAAC;gBAAE,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;QACD,GAAG,IAAI,CAAC,CAAC;IACX,CAAC;IACD,OAAO,IAAI,GAAG,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;AAC/C,CAAC;AAOD,MAAM,OAAO,QAAQ;IACF,GAAG,CAAO;IACV,IAAI,CAAuB;IAC3B,aAAa,CAAU;IACvB,aAAa,CAAa;IAC1B,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClC,IAAI,GAAG,IAAI,GAAG,EAAwB,CAAC;IACvC,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;IAElD,YAAY,OAAO,GAAoB,EAAE;QACvC,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;YACnC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,MAAM,IAAI,UAAU,CAAC,qBAAqB,CAAC,mBAAmB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpH,CAAC;QACD,IAAI,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1G,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,eAAe,CAAC,CAAC;QACrD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,KAAK,CAAC;QACpD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,QAAQ,CAAC;IACzD,CAAC;IAED,kGAAkG;IAClG,IAAI,CAAC,KAAa;QAChB,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,EAAE,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjG,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC;QACvB,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACjG,MAAM,MAAM,GAAG,CAAC,GAAW,EAAE,EAAE;YAC7B,IAAI,EAAE,GAAG,CAAC,CAAC;YACX,IAAI,EAAE,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;YAC/B,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC;gBACf,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC/B,IAAI,UAAU,CAAC,GAAG,CAAE,IAAI,GAAG;oBAAE,EAAE,GAAG,GAAG,CAAC;;oBACjC,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;YACpB,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,4EAA4E;QAC5E,MAAM,GAAG,GAAa,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;QACvC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACvB,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK;gBAAE,OAAO;YAC7B,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YACpC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;YAClD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAC7B,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACvB,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,SAAS;gBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/F,CAAC,CAAC,CAAC;QACH,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,MAAM,QAAQ,GAAqC,EAAE,CAAC;QACtD,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACvB,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YAC9C,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC;YACf,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACxD,CAAC;IAED,kDAAkD;IAClD,KAAK,CAAC,IAAa,EAAE,QAAgB,EAAE,MAAY;QACjD,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,QAAQ,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC1H,IAAI,IAAI,KAAK,YAAY,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC,CAAC;QAC5I,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACrE,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC;YAC/C,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC;YAC7F,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,MAAM;YAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,EAAU,CAAC;YACtD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC1B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACf,MAAM;YACR,CAAC;QACH,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC/B,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,sFAAsF;IAC9E,QAAQ,CAAC,IAAY;QAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACpG,CAAC;IAED,0FAA0F;IAClF,IAAI,CAAC,IAAa,EAAE,QAAgB,EAAE,KAAa,EAAE,GAAW;QACtE,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,KAAK,EAAE,CAAC;gBACX,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;gBAC/B,IAAI,CAAC,CAAC,MAAM,KAAK,EAAE;oBAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;gBAClF,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;gBAC1C,IAAI,GAAG,GAAQ,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;gBACjG,IAAI,CAAC,IAAI,CAAC,aAAa;oBAAE,GAAG,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBAChF,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC5H,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBAC3B,OAAO,GAAG,CAAC;YACb,CAAC;YACD,KAAK,IAAI;gBACP,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;YACrG,KAAK,MAAM,EAAE,CAAC;gBACZ,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;gBAC/B,kFAAkF;gBAClF,IAAI,CAAC,CAAC,MAAM,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG;oBAAE,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC7E,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;YAC/D,CAAC;YACD,KAAK,OAAO,EAAE,CAAC;gBACb,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;oBAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBACrF,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;gBAC/B,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;YAC/D,CAAC;YACD,KAAK,OAAO,EAAE,CAAC;gBACb,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;gBAChC,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;gBACzE,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;gBACtE,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAChD,CAAC;YACD,KAAK,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBACrC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBACpF,MAAM,MAAM,GAAG,IAAI,KAAK,SAAS,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;gBACvI,MAAM,KAAK,GAAa,EAAE,CAAC;gBAC3B,IAAI,SAAS,GAAG,KAAK,CAAC;gBACtB,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;oBACrB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;wBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;yBACvD,IAAI,CAAC,SAAS,EAAE,CAAC;wBACpB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;wBACzD,SAAS,GAAG,IAAI,CAAC;oBACnB,CAAC;yBAAM,CAAC;wBACN,IAAI,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;wBACtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;4BAAE,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;wBACtG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACnB,CAAC;gBACH,CAAC;gBACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;YACD,KAAK,SAAS;gBACZ,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACrC,KAAK,YAAY;gBACf,OAAO,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACvE,KAAK,cAAc,CAAC;YACpB,KAAK,MAAM,CAAC;YACZ,KAAK,KAAK;gBACR,OAAO,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;YACjD,KAAK,KAAK,EAAE,CAAC;gBACX,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;gBAC/B,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;YAC/D,CAAC;YACD,KAAK,MAAM,EAAE,CAAC;gBACZ,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;gBAC/B,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACjG,CAAC;YACD,KAAK,UAAU;gBACb,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YACjE,KAAK,OAAO,EAAE,CAAC;gBACb,MAAM,CAAC,GAAG,qDAAqD,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;gBACtF,IAAI,CAAC,CAAC;oBAAE,OAAO,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;gBACvC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAClE,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACvF,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC;YAChD,CAAC;YACD,KAAK,IAAI;gBACP,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;oBAAE,OAAO,aAAa,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC7G,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACnF,KAAK,KAAK;gBACR,OAAO,QAAQ,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,IAAY,EAAE,IAAY,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAChH,KAAK,WAAW;gBACd,OAAO,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACpC,KAAK,QAAQ;gBACX,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC;YAC9C,KAAK,iBAAiB;gBACpB,OAAO,QAAQ,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;YACjD,KAAK,WAAW,EAAE,CAAC;gBACjB,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;gBACtC,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7E,OAAO,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;YAC9E,CAAC;YACD,KAAK,QAAQ;gBACX,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;YACpG,KAAK,UAAU;gBACb,OAAO,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7B,KAAK,gBAAgB;gBACnB,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3B,KAAK,aAAa;gBAChB,OAAO,KAAK,CAAC;YACf;gBACE,OAAO,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,mFAAmF;IAC3E,MAAM,CAAC,IAAa,EAAE,QAAgB,EAAE,IAAY;QAC1D,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,KAAK,CAAC;YACX,KAAK,IAAI,CAAC;YACV,KAAK,MAAM,CAAC;YACZ,KAAK,cAAc,CAAC;YACpB,KAAK,MAAM,CAAC;YACZ,KAAK,KAAK,CAAC;YACX,KAAK,KAAK,CAAC;YACX,KAAK,MAAM;gBACT,OAAO,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACnC,KAAK,OAAO,EAAE,CAAC;gBACb,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;oBAAE,OAAO,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBAC9D,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;gBAC/B,MAAM,MAAM,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC5G,OAAO,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACrC,CAAC;YACD,KAAK,OAAO;gBACV,OAAO,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI,yBAAyB,CAAC;YAC3F,KAAK,MAAM,EAAE,CAAC;gBACZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC9B,IAAI,CAAC,GAAG,CAAC,CAAC;gBACV,OAAO,QAAQ;qBACZ,KAAK,CAAC,OAAO,CAAC;qBACd,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;oBACZ,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;wBAAE,OAAO,IAAI,CAAC;oBACvG,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;oBAChC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC3C,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;gBAC1D,CAAC,CAAC;qBACD,IAAI,CAAC,EAAE,CAAC,CAAC;YACd,CAAC;YACD;gBACE,OAAO,IAAI,CAAC;QAChB,CAAC;IACH,CAAC;IAEO,OAAO,CAAC,QAAgB,EAAE,GAAW;QAC3C,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,IAAY,EAAE,GAAW,EAAE,IAAY,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QACpI,OAAO,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACzC,CAAC;IAEO,SAAS,CAAC,QAAgB,EAAE,GAAW,EAAE,MAAY;QAC3D,IAAI,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC;YACnF,MAAM,GAAG,GAAG,MAAM,IAAI,EAAE,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACvE,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;QAC3H,CAAC;QACD,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,MAAM,IAAI,EAAE,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QAC9E,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7E,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,IAAI,CAAC,EAAE,CAAC;YACN,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;YACjB,OAAO,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACtG,CAAC;QACD,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,IAAI,CAAC,EAAE,CAAC;YACN,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;YACjB,OAAO,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtG,CAAC;QACD,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5B,IAAI,CAAC,EAAE,CAAC;YACN,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAE,CAAC;YAC1E,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAE,CAAC;YAClC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC;YAC7E,OAAO,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AAED,uFAAuF;AACvF,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,OAAO,GAAoB,EAAE;IAClE,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC"}
|