allprofanity 2.1.1 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Bloom Filter implementation for efficient set membership testing
3
+ */
4
+ export class BloomFilter {
5
+ constructor(expectedItems, falsePositiveRate = 0.01) {
6
+ this.itemCount = 0;
7
+ // Calculate optimal size and hash count
8
+ this.size = this.calculateOptimalSize(expectedItems, falsePositiveRate);
9
+ this.hashCount = this.calculateOptimalHashCount(this.size, expectedItems);
10
+ this.bitArray = new Uint8Array(Math.ceil(this.size / 8));
11
+ }
12
+ /**
13
+ * Calculate optimal bit array size
14
+ */
15
+ calculateOptimalSize(n, p) {
16
+ return Math.ceil((-n * Math.log(p)) / Math.log(2) ** 2);
17
+ }
18
+ /**
19
+ * Calculate optimal number of hash functions
20
+ */
21
+ calculateOptimalHashCount(m, n) {
22
+ return Math.ceil((m / n) * Math.log(2));
23
+ }
24
+ /**
25
+ * Hash function 1 (FNV-1a variant)
26
+ */
27
+ hash1(item) {
28
+ let hash = 2166136261;
29
+ for (let i = 0; i < item.length; i++) {
30
+ hash ^= item.charCodeAt(i);
31
+ hash *= 16777619;
32
+ }
33
+ return Math.abs(hash) % this.size;
34
+ }
35
+ /**
36
+ * Hash function 2 (djb2 variant)
37
+ */
38
+ hash2(item) {
39
+ let hash = 5381;
40
+ for (let i = 0; i < item.length; i++) {
41
+ hash = (hash << 5) + hash + item.charCodeAt(i);
42
+ }
43
+ return Math.abs(hash) % this.size;
44
+ }
45
+ /**
46
+ * Generate k hash values for an item using double hashing
47
+ */
48
+ getHashes(item) {
49
+ const hash1 = this.hash1(item);
50
+ const hash2 = this.hash2(item);
51
+ const hashes = [];
52
+ for (let i = 0; i < this.hashCount; i++) {
53
+ const hash = (hash1 + i * hash2) % this.size;
54
+ hashes.push(Math.abs(hash));
55
+ }
56
+ return hashes;
57
+ }
58
+ /**
59
+ * Set a bit in the bit array
60
+ */
61
+ setBit(index) {
62
+ const byteIndex = Math.floor(index / 8);
63
+ const bitIndex = index % 8;
64
+ this.bitArray[byteIndex] |= 1 << bitIndex;
65
+ }
66
+ /**
67
+ * Get a bit from the bit array
68
+ */
69
+ getBit(index) {
70
+ const byteIndex = Math.floor(index / 8);
71
+ const bitIndex = index % 8;
72
+ return (this.bitArray[byteIndex] & (1 << bitIndex)) !== 0;
73
+ }
74
+ /**
75
+ * Add an item to the bloom filter
76
+ */
77
+ add(item) {
78
+ const hashes = this.getHashes(item);
79
+ for (const hash of hashes) {
80
+ this.setBit(hash);
81
+ }
82
+ this.itemCount++;
83
+ }
84
+ /**
85
+ * Add multiple items to the bloom filter
86
+ */
87
+ addAll(items) {
88
+ for (const item of items) {
89
+ this.add(item);
90
+ }
91
+ }
92
+ /**
93
+ * Test if an item might be in the set
94
+ */
95
+ mightContain(item) {
96
+ const hashes = this.getHashes(item);
97
+ for (const hash of hashes) {
98
+ if (!this.getBit(hash)) {
99
+ return false;
100
+ }
101
+ }
102
+ return true;
103
+ }
104
+ /**
105
+ * Test multiple items at once
106
+ */
107
+ mightContainAny(items) {
108
+ return items.some((item) => this.mightContain(item));
109
+ }
110
+ /**
111
+ * Filter items that might be in the set
112
+ */
113
+ filter(items) {
114
+ return items.filter((item) => this.mightContain(item));
115
+ }
116
+ /**
117
+ * Clear the bloom filter
118
+ */
119
+ clear() {
120
+ this.bitArray.fill(0);
121
+ this.itemCount = 0;
122
+ }
123
+ /**
124
+ * Get current false positive probability
125
+ */
126
+ getCurrentFalsePositiveRate() {
127
+ const ratio = this.itemCount / this.size;
128
+ return Math.pow(1 - Math.exp(-this.hashCount * ratio), this.hashCount);
129
+ }
130
+ /**
131
+ * Get bloom filter statistics
132
+ */
133
+ getStats() {
134
+ let bitsSet = 0;
135
+ for (let i = 0; i < this.size; i++) {
136
+ if (this.getBit(i)) {
137
+ bitsSet++;
138
+ }
139
+ }
140
+ const loadFactor = bitsSet / this.size;
141
+ const estimatedFalsePositiveRate = Math.pow(loadFactor, this.hashCount);
142
+ return {
143
+ size: this.size,
144
+ hashCount: this.hashCount,
145
+ itemCount: this.itemCount,
146
+ bitsSet,
147
+ loadFactor,
148
+ estimatedFalsePositiveRate,
149
+ };
150
+ }
151
+ /**
152
+ * Serialize bloom filter to JSON
153
+ */
154
+ toJSON() {
155
+ return {
156
+ size: this.size,
157
+ hashCount: this.hashCount,
158
+ itemCount: this.itemCount,
159
+ bitArray: Array.from(this.bitArray),
160
+ };
161
+ }
162
+ /**
163
+ * Deserialize bloom filter from JSON
164
+ */
165
+ static fromJSON(data) {
166
+ const filter = Object.create(BloomFilter.prototype);
167
+ filter.size = data.size;
168
+ filter.hashCount = data.hashCount;
169
+ filter.itemCount = data.itemCount;
170
+ filter.bitArray = new Uint8Array(data.bitArray);
171
+ return filter;
172
+ }
173
+ /**
174
+ * Union operation with another bloom filter
175
+ */
176
+ union(other) {
177
+ if (this.size !== other.size || this.hashCount !== other.hashCount) {
178
+ throw new Error("Bloom filters must have same size and hash count for union operation");
179
+ }
180
+ const result = new BloomFilter(1, 0.01);
181
+ result.size = this.size;
182
+ result.hashCount = this.hashCount;
183
+ result.bitArray = new Uint8Array(this.bitArray.length);
184
+ result.itemCount = this.itemCount + other.itemCount;
185
+ for (let i = 0; i < this.bitArray.length; i++) {
186
+ result.bitArray[i] = this.bitArray[i] | other.bitArray[i];
187
+ }
188
+ return result;
189
+ }
190
+ /**
191
+ * Intersection operation with another bloom filter
192
+ */
193
+ intersect(other) {
194
+ if (this.size !== other.size || this.hashCount !== other.hashCount) {
195
+ throw new Error("Bloom filters must have same size and hash count for intersection operation");
196
+ }
197
+ const result = new BloomFilter(1, 0.01);
198
+ result.size = this.size;
199
+ result.hashCount = this.hashCount;
200
+ result.bitArray = new Uint8Array(this.bitArray.length);
201
+ result.itemCount = Math.min(this.itemCount, other.itemCount);
202
+ for (let i = 0; i < this.bitArray.length; i++) {
203
+ result.bitArray[i] = this.bitArray[i] & other.bitArray[i];
204
+ }
205
+ return result;
206
+ }
207
+ }
208
+ //# sourceMappingURL=bloom-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bloom-filter.js","sourceRoot":"","sources":["../../src/algos/bloom-filter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Universal context patterns for multi-language profanity detection
3
+ */
4
+ export interface UniversalContextPattern {
5
+ type: "negation" | "possessive" | "compound" | "proper_noun" | "article" | "quotation" | "medical" | "anatomical";
6
+ pattern: RegExp;
7
+ weight: number;
8
+ languages: string[];
9
+ description: string;
10
+ examples: string[];
11
+ }
12
+ export interface ContextRule {
13
+ pattern: RegExp;
14
+ action: "reduce_score" | "increase_score" | "whitelist" | "flag";
15
+ weight: number;
16
+ priority: number;
17
+ }
18
+ /**
19
+ * Universal context patterns that work across multiple languages
20
+ */
21
+ export declare const UNIVERSAL_CONTEXT_PATTERNS: UniversalContextPattern[];
22
+ /**
23
+ * Language-specific context patterns
24
+ */
25
+ export declare const LANGUAGE_SPECIFIC_PATTERNS: Record<string, UniversalContextPattern[]>;
26
+ /**
27
+ * Context rule generator
28
+ */
29
+ export declare class ContextPatternMatcher {
30
+ private patterns;
31
+ private languagePatterns;
32
+ constructor(languages?: string[]);
33
+ /**
34
+ * Generate context rules for a specific word
35
+ */
36
+ generateRules(word: string, languages?: string[]): ContextRule[];
37
+ /**
38
+ * Get priority for pattern type
39
+ */
40
+ private getPriority;
41
+ /**
42
+ * Escape regex special characters
43
+ */
44
+ private escapeRegex;
45
+ /**
46
+ * Add custom pattern
47
+ */
48
+ addPattern(pattern: UniversalContextPattern): void;
49
+ /**
50
+ * Add language-specific pattern
51
+ */
52
+ addLanguagePattern(language: string, pattern: UniversalContextPattern): void;
53
+ /**
54
+ * Get all patterns for debugging
55
+ */
56
+ getAllPatterns(): {
57
+ universal: UniversalContextPattern[];
58
+ languageSpecific: Map<string, UniversalContextPattern[]>;
59
+ };
60
+ }
61
+ /**
62
+ * Context analyzer for scoring matches
63
+ */
64
+ export declare class ContextAnalyzer {
65
+ private patternMatcher;
66
+ private contextWindow;
67
+ constructor(languages?: string[]);
68
+ /**
69
+ * Analyze context around a potential profanity match
70
+ */
71
+ analyzeContext(text: string, matchStart: number, matchEnd: number, word: string): {
72
+ score: number;
73
+ confidence: "high" | "medium" | "low";
74
+ appliedRules: Array<{
75
+ rule: ContextRule;
76
+ matched: boolean;
77
+ }>;
78
+ context: string;
79
+ };
80
+ /**
81
+ * Set context window size
82
+ */
83
+ setContextWindow(size: number): void;
84
+ /**
85
+ * Add custom pattern to the analyzer
86
+ */
87
+ addCustomPattern(pattern: UniversalContextPattern): void;
88
+ }
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Universal context patterns for multi-language profanity detection
3
+ */
4
+ /**
5
+ * Universal context patterns that work across multiple languages
6
+ */
7
+ export const UNIVERSAL_CONTEXT_PATTERNS = [
8
+ // Negation patterns
9
+ {
10
+ type: "negation",
11
+ pattern: /\b(not|don't|won't|can't|never|ne|pas|nicht|no|नहीं|不|non|niente|нет|nie)\b.{0,30}PROFANE_WORD/i,
12
+ weight: 0.2,
13
+ languages: ["*"],
14
+ description: "Negation words that reduce profanity likelihood",
15
+ examples: ["not bad", "don't call me that", "never say that"],
16
+ },
17
+ // Possessive patterns
18
+ {
19
+ type: "possessive",
20
+ pattern: /\b\w+(['s]|du|de|का|की|के|の|del|della|от|od)\s+PROFANE_WORD\b/i,
21
+ weight: 0.4,
22
+ languages: ["*"],
23
+ description: "Possessive constructions that may be innocent",
24
+ examples: ["dog's mouth", "cat's ass", "bird's ass"],
25
+ },
26
+ // Article patterns
27
+ {
28
+ type: "article",
29
+ pattern: /\b(the|a|an|le|la|les|un|une|der|die|das|ein|eine|el|la|los|las|il|lo|gli|le)\s+PROFANE_WORD\b/i,
30
+ weight: 0.6,
31
+ languages: ["*"],
32
+ description: "Articles that may indicate neutral reference",
33
+ examples: ["the ass of the donkey", "a hell of a time"],
34
+ },
35
+ // Compound word patterns
36
+ {
37
+ type: "compound",
38
+ pattern: /\b(smart|silly|cute|funny|little|big|old|new|good|bad|nice|sweet)\s*[-]?\s*PROFANE_WORD\b/i,
39
+ weight: 0.5,
40
+ languages: ["*"],
41
+ description: "Adjective-noun compounds that may be innocent",
42
+ examples: ["smart-ass", "silly ass", "cute little ass"],
43
+ },
44
+ // Proper noun patterns
45
+ {
46
+ type: "proper_noun",
47
+ pattern: /\b[A-Z][a-z]+\s+PROFANE_WORD\b/,
48
+ weight: 0.3,
49
+ languages: ["en", "fr", "de", "es", "it"],
50
+ description: "Proper nouns followed by potential profanity",
51
+ examples: ["Hell Michigan", "Ass River"],
52
+ },
53
+ // Quotation patterns
54
+ {
55
+ type: "quotation",
56
+ pattern: /["'«»„"‚'].*PROFANE_WORD.*["'«»„"‚']/i,
57
+ weight: 0.7,
58
+ languages: ["*"],
59
+ description: "Quoted text which may be reporting speech",
60
+ examples: ['"Don\'t be an ass"', "'What the hell'"],
61
+ },
62
+ // Medical/anatomical context
63
+ {
64
+ type: "medical",
65
+ pattern: /\b(medical|anatomy|doctor|hospital|clinic|patient|diagnosis|treatment|surgical|clinical)\b.{0,50}PROFANE_WORD/i,
66
+ weight: 0.1,
67
+ languages: ["*"],
68
+ description: "Medical contexts where anatomical terms are appropriate",
69
+ examples: [
70
+ "medical examination of the ass",
71
+ "doctor checked the damn thing",
72
+ ],
73
+ },
74
+ // Anatomical context
75
+ {
76
+ type: "anatomical",
77
+ pattern: /\b(body|part|muscle|bone|skin|tissue|organ|limb|extremity)\b.{0,30}PROFANE_WORD/i,
78
+ weight: 0.3,
79
+ languages: ["*"],
80
+ description: "Anatomical contexts for body parts",
81
+ examples: ["body part called ass", "muscle in the ass"],
82
+ },
83
+ ];
84
+ /**
85
+ * Language-specific context patterns
86
+ */
87
+ export const LANGUAGE_SPECIFIC_PATTERNS = {
88
+ en: [
89
+ {
90
+ type: "compound",
91
+ pattern: /\b(jack|dumb|smart|bad|kick)\s*[-]?\s*PROFANE_WORD\b/i,
92
+ weight: 0.4,
93
+ languages: ["en"],
94
+ description: "English-specific compound patterns",
95
+ examples: ["jackass", "dumbass", "badass"],
96
+ },
97
+ ],
98
+ fr: [
99
+ {
100
+ type: "negation",
101
+ pattern: /\b(ne|n'|pas|point|jamais|rien|personne)\b.{0,30}PROFANE_WORD/i,
102
+ weight: 0.2,
103
+ languages: ["fr"],
104
+ description: "French negation patterns",
105
+ examples: ["ne pas dire", "jamais ça"],
106
+ },
107
+ ],
108
+ de: [
109
+ {
110
+ type: "compound",
111
+ pattern: /\bPROFANE_WORD(kopf|zeug|ding|sache)\b/i,
112
+ weight: 0.5,
113
+ languages: ["de"],
114
+ description: "German compound word patterns",
115
+ examples: ["Scheißzeug", "Arschloch"],
116
+ },
117
+ ],
118
+ es: [
119
+ {
120
+ type: "possessive",
121
+ pattern: /\b(el|la|los|las)\s+PROFANE_WORD\s+(de|del|de la)\b/i,
122
+ weight: 0.4,
123
+ languages: ["es"],
124
+ description: "Spanish possessive patterns",
125
+ examples: ["el culo de la mesa"],
126
+ },
127
+ ],
128
+ };
129
+ /**
130
+ * Context rule generator
131
+ */
132
+ export class ContextPatternMatcher {
133
+ constructor(languages = ["en"]) {
134
+ this.patterns = [...UNIVERSAL_CONTEXT_PATTERNS];
135
+ this.languagePatterns = new Map();
136
+ // Load language-specific patterns
137
+ for (const lang of languages) {
138
+ if (LANGUAGE_SPECIFIC_PATTERNS[lang]) {
139
+ this.languagePatterns.set(lang, LANGUAGE_SPECIFIC_PATTERNS[lang]);
140
+ }
141
+ }
142
+ }
143
+ /**
144
+ * Generate context rules for a specific word
145
+ */
146
+ generateRules(word, languages = ["en"]) {
147
+ const rules = [];
148
+ const allPatterns = [...this.patterns];
149
+ // Add language-specific patterns
150
+ for (const lang of languages) {
151
+ const langPatterns = this.languagePatterns.get(lang) || [];
152
+ allPatterns.push(...langPatterns);
153
+ }
154
+ for (const pattern of allPatterns) {
155
+ // Skip if pattern doesn't apply to any of the specified languages
156
+ if (!pattern.languages.includes("*") &&
157
+ !pattern.languages.some((lang) => languages.includes(lang))) {
158
+ continue;
159
+ }
160
+ // Replace PROFANE_WORD placeholder with actual word
161
+ const regexSource = pattern.pattern.source.replace("PROFANE_WORD", this.escapeRegex(word));
162
+ const regex = new RegExp(regexSource, pattern.pattern.flags);
163
+ let action;
164
+ if (pattern.weight < 0.3) {
165
+ action = "reduce_score";
166
+ }
167
+ else if (pattern.weight > 0.8) {
168
+ action = "increase_score";
169
+ }
170
+ else {
171
+ action = "reduce_score";
172
+ }
173
+ rules.push({
174
+ pattern: regex,
175
+ action,
176
+ weight: pattern.weight,
177
+ priority: this.getPriority(pattern.type),
178
+ });
179
+ }
180
+ return rules.sort((a, b) => a.priority - b.priority);
181
+ }
182
+ /**
183
+ * Get priority for pattern type
184
+ */
185
+ getPriority(type) {
186
+ const priorities = {
187
+ medical: 1,
188
+ anatomical: 2,
189
+ negation: 3,
190
+ quotation: 4,
191
+ proper_noun: 5,
192
+ possessive: 6,
193
+ article: 7,
194
+ compound: 8,
195
+ };
196
+ return priorities[type] || 9;
197
+ }
198
+ /**
199
+ * Escape regex special characters
200
+ */
201
+ escapeRegex(str) {
202
+ return str.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
203
+ }
204
+ /**
205
+ * Add custom pattern
206
+ */
207
+ addPattern(pattern) {
208
+ this.patterns.push(pattern);
209
+ }
210
+ /**
211
+ * Add language-specific pattern
212
+ */
213
+ addLanguagePattern(language, pattern) {
214
+ if (!this.languagePatterns.has(language)) {
215
+ this.languagePatterns.set(language, []);
216
+ }
217
+ this.languagePatterns.get(language).push(pattern);
218
+ }
219
+ /**
220
+ * Get all patterns for debugging
221
+ */
222
+ getAllPatterns() {
223
+ return {
224
+ universal: [...this.patterns],
225
+ languageSpecific: new Map(this.languagePatterns),
226
+ };
227
+ }
228
+ }
229
+ /**
230
+ * Context analyzer for scoring matches
231
+ */
232
+ export class ContextAnalyzer {
233
+ constructor(languages = ["en"]) {
234
+ this.contextWindow = 50; // Characters before and after the match
235
+ this.patternMatcher = new ContextPatternMatcher(languages);
236
+ }
237
+ /**
238
+ * Analyze context around a potential profanity match
239
+ */
240
+ analyzeContext(text, matchStart, matchEnd, word) {
241
+ // Extract context window
242
+ const contextStart = Math.max(0, matchStart - this.contextWindow);
243
+ const contextEnd = Math.min(text.length, matchEnd + this.contextWindow);
244
+ const context = text.substring(contextStart, contextEnd);
245
+ // Get rules for this word
246
+ const rules = this.patternMatcher.generateRules(word);
247
+ let score = 1.0; // Start with full profanity score
248
+ const appliedRules = [];
249
+ // Apply context rules
250
+ for (const rule of rules) {
251
+ const matched = rule.pattern.test(context);
252
+ appliedRules.push({ rule, matched });
253
+ if (matched) {
254
+ if (rule.action === "reduce_score") {
255
+ score *= rule.weight;
256
+ }
257
+ else if (rule.action === "increase_score") {
258
+ score *= 2 - rule.weight; // Increase score
259
+ }
260
+ else if (rule.action === "whitelist") {
261
+ score = 0; // Complete whitelist
262
+ break;
263
+ }
264
+ }
265
+ }
266
+ // Determine confidence based on number of matching rules
267
+ const matchingRules = appliedRules.filter((ar) => ar.matched).length;
268
+ let confidence;
269
+ if (matchingRules === 0) {
270
+ confidence = "high"; // No context rules matched, likely profanity
271
+ }
272
+ else if (matchingRules <= 2) {
273
+ confidence = "medium";
274
+ }
275
+ else {
276
+ confidence = "low"; // Many context rules matched, likely innocent
277
+ }
278
+ return {
279
+ score: Math.max(0, Math.min(1, score)),
280
+ confidence,
281
+ appliedRules,
282
+ context,
283
+ };
284
+ }
285
+ /**
286
+ * Set context window size
287
+ */
288
+ setContextWindow(size) {
289
+ this.contextWindow = Math.max(10, Math.min(200, size));
290
+ }
291
+ /**
292
+ * Add custom pattern to the analyzer
293
+ */
294
+ addCustomPattern(pattern) {
295
+ this.patternMatcher.addPattern(pattern);
296
+ }
297
+ }
298
+ //# sourceMappingURL=context-patterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-patterns.js","sourceRoot":"","sources":["../../src/algos/context-patterns.ts"],"names":[],"mappings":"AAAA;;GAEG;AA0BH;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAA8B;IACnE,oBAAoB;IACpB;QACE,IAAI,EAAE,UAAU;QAChB,OAAO,EACL,iGAAiG;QACnG,MAAM,EAAE,GAAG;QACX,SAAS,EAAE,CAAC,GAAG,CAAC;QAChB,WAAW,EAAE,iDAAiD;QAC9D,QAAQ,EAAE,CAAC,SAAS,EAAE,oBAAoB,EAAE,gBAAgB,CAAC;KAC9D;IAED,sBAAsB;IACtB;QACE,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,gEAAgE;QACzE,MAAM,EAAE,GAAG;QACX,SAAS,EAAE,CAAC,GAAG,CAAC;QAChB,WAAW,EAAE,+CAA+C;QAC5D,QAAQ,EAAE,CAAC,aAAa,EAAE,WAAW,EAAE,YAAY,CAAC;KACrD;IAED,mBAAmB;IACnB;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EACL,iGAAiG;QACnG,MAAM,EAAE,GAAG;QACX,SAAS,EAAE,CAAC,GAAG,CAAC;QAChB,WAAW,EAAE,8CAA8C;QAC3D,QAAQ,EAAE,CAAC,uBAAuB,EAAE,kBAAkB,CAAC;KACxD;IAED,yBAAyB;IACzB;QACE,IAAI,EAAE,UAAU;QAChB,OAAO,EACL,4FAA4F;QAC9F,MAAM,EAAE,GAAG;QACX,SAAS,EAAE,CAAC,GAAG,CAAC;QAChB,WAAW,EAAE,+CAA+C;QAC5D,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,iBAAiB,CAAC;KACxD;IAED,uBAAuB;IACvB;QACE,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,gCAAgC;QACzC,MAAM,EAAE,GAAG;QACX,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;QACzC,WAAW,EAAE,8CAA8C;QAC3D,QAAQ,EAAE,CAAC,eAAe,EAAE,WAAW,CAAC;KACzC;IAED,qBAAqB;IACrB;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,uCAAuC;QAChD,MAAM,EAAE,GAAG;QACX,SAAS,EAAE,CAAC,GAAG,CAAC;QAChB,WAAW,EAAE,2CAA2C;QACxD,QAAQ,EAAE,CAAC,oBAAoB,EAAE,iBAAiB,CAAC;KACpD;IAED,6BAA6B;IAC7B;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EACL,gHAAgH;QAClH,MAAM,EAAE,GAAG;QACX,SAAS,EAAE,CAAC,GAAG,CAAC;QAChB,WAAW,EAAE,yDAAyD;QACtE,QAAQ,EAAE;YACR,gCAAgC;YAChC,+BAA+B;SAChC;KACF;IAED,qBAAqB;IACrB;QACE,IAAI,EAAE,YAAY;QAClB,OAAO,EACL,kFAAkF;QACpF,MAAM,EAAE,GAAG;QACX,SAAS,EAAE,CAAC,GAAG,CAAC;QAChB,WAAW,EAAE,oCAAoC;QACjD,QAAQ,EAAE,CAAC,sBAAsB,EAAE,mBAAmB,CAAC;KACxD;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAGnC;IACF,EAAE,EAAE;QACF;YACE,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,uDAAuD;YAChE,MAAM,EAAE,GAAG;YACX,SAAS,EAAE,CAAC,IAAI,CAAC;YACjB,WAAW,EAAE,oCAAoC;YACjD,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC;SAC3C;KACF;IAED,EAAE,EAAE;QACF;YACE,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,gEAAgE;YACzE,MAAM,EAAE,GAAG;YACX,SAAS,EAAE,CAAC,IAAI,CAAC;YACjB,WAAW,EAAE,0BAA0B;YACvC,QAAQ,EAAE,CAAC,aAAa,EAAE,WAAW,CAAC;SACvC;KACF;IAED,EAAE,EAAE;QACF;YACE,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,yCAAyC;YAClD,MAAM,EAAE,GAAG;YACX,SAAS,EAAE,CAAC,IAAI,CAAC;YACjB,WAAW,EAAE,+BAA+B;YAC5C,QAAQ,EAAE,CAAC,YAAY,EAAE,WAAW,CAAC;SACtC;KACF;IAED,EAAE,EAAE;QACF;YACE,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,sDAAsD;YAC/D,MAAM,EAAE,GAAG;YACX,SAAS,EAAE,CAAC,IAAI,CAAC;YACjB,WAAW,EAAE,6BAA6B;YAC1C,QAAQ,EAAE,CAAC,oBAAoB,CAAC;SACjC;KACF;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,OAAO,qBAAqB;IAIhC,YAAY,YAAsB,CAAC,IAAI,CAAC;QACtC,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,0BAA0B,CAAC,CAAC;QAChD,IAAI,CAAC,gBAAgB,GAAG,IAAI,GAAG,EAAE,CAAC;QAElC,kCAAkC;QAClC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE;YAC5B,IAAI,0BAA0B,CAAC,IAAI,CAAC,EAAE;gBACpC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC;aACnE;SACF;IACH,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,IAAY,EAAE,YAAsB,CAAC,IAAI,CAAC;QACtD,MAAM,KAAK,GAAkB,EAAE,CAAC;QAChC,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEvC,iCAAiC;QACjC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE;YAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAC3D,WAAW,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;SACnC;QAED,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE;YACjC,kEAAkE;YAClE,IACE,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAChC,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAC3D;gBACA,SAAS;aACV;YAED,oDAAoD;YACpD,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAChD,cAAc,EACd,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CACvB,CAAC;YACF,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAE7D,IAAI,MAAgE,CAAC;YACrE,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE;gBACxB,MAAM,GAAG,cAAc,CAAC;aACzB;iBAAM,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE;gBAC/B,MAAM,GAAG,gBAAgB,CAAC;aAC3B;iBAAM;gBACL,MAAM,GAAG,cAAc,CAAC;aACzB;YAED,KAAK,CAAC,IAAI,CAAC;gBACT,OAAO,EAAE,KAAK;gBACd,MAAM;gBACN,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;aACzC,CAAC,CAAC;SACJ;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,IAAY;QAC9B,MAAM,UAAU,GAA2B;YACzC,OAAO,EAAE,CAAC;YACV,UAAU,EAAE,CAAC;YACb,QAAQ,EAAE,CAAC;YACX,SAAS,EAAE,CAAC;YACZ,WAAW,EAAE,CAAC;YACd,UAAU,EAAE,CAAC;YACb,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,CAAC;SACZ,CAAC;QACF,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,GAAW;QAC7B,OAAO,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,OAAgC;QACzC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,kBAAkB,CAAC,QAAgB,EAAE,OAAgC;QACnE,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;YACxC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;SACzC;QACD,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;IAED;;OAEG;IACH,cAAc;QAIZ,OAAO;YACL,SAAS,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC7B,gBAAgB,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC;SACjD,CAAC;IACJ,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAe;IAI1B,YAAY,YAAsB,CAAC,IAAI,CAAC;QAFhC,kBAAa,GAAW,EAAE,CAAC,CAAC,wCAAwC;QAG1E,IAAI,CAAC,cAAc,GAAG,IAAI,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACH,cAAc,CACZ,IAAY,EACZ,UAAkB,EAClB,QAAgB,EAChB,IAAY;QAOZ,yBAAyB;QACzB,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;QAClE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;QACxE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAEzD,0BAA0B;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAEtD,IAAI,KAAK,GAAG,GAAG,CAAC,CAAC,kCAAkC;QACnD,MAAM,YAAY,GAAmD,EAAE,CAAC;QAExE,sBAAsB;QACtB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;YACxB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3C,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAErC,IAAI,OAAO,EAAE;gBACX,IAAI,IAAI,CAAC,MAAM,KAAK,cAAc,EAAE;oBAClC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;iBACtB;qBAAM,IAAI,IAAI,CAAC,MAAM,KAAK,gBAAgB,EAAE;oBAC3C,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,iBAAiB;iBAC5C;qBAAM,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE;oBACtC,KAAK,GAAG,CAAC,CAAC,CAAC,qBAAqB;oBAChC,MAAM;iBACP;aACF;SACF;QAED,yDAAyD;QACzD,MAAM,aAAa,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;QACrE,IAAI,UAAqC,CAAC;QAE1C,IAAI,aAAa,KAAK,CAAC,EAAE;YACvB,UAAU,GAAG,MAAM,CAAC,CAAC,6CAA6C;SACnE;aAAM,IAAI,aAAa,IAAI,CAAC,EAAE;YAC7B,UAAU,GAAG,QAAQ,CAAC;SACvB;aAAM;YACL,UAAU,GAAG,KAAK,CAAC,CAAC,8CAA8C;SACnE;QAED,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YACtC,UAAU;YACV,YAAY;YACZ,OAAO;SACR,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,IAAY;QAC3B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IACzD,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,OAAgC;QAC/C,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;CACF"}