@ifc-lite/pointcloud 0.2.0 → 0.3.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.
Files changed (49) hide show
  1. package/README.md +28 -0
  2. package/dist/formats/ascii-points.d.ts +61 -0
  3. package/dist/formats/ascii-points.d.ts.map +1 -0
  4. package/dist/formats/ascii-points.js +243 -0
  5. package/dist/formats/ascii-points.js.map +1 -0
  6. package/dist/formats/e57-decode.d.ts +28 -0
  7. package/dist/formats/e57-decode.d.ts.map +1 -0
  8. package/dist/formats/e57-decode.js +425 -0
  9. package/dist/formats/e57-decode.js.map +1 -0
  10. package/dist/formats/e57-page.d.ts +42 -0
  11. package/dist/formats/e57-page.d.ts.map +1 -0
  12. package/dist/formats/e57-page.js +107 -0
  13. package/dist/formats/e57-page.js.map +1 -0
  14. package/dist/formats/e57-xml.d.ts +55 -0
  15. package/dist/formats/e57-xml.d.ts.map +1 -0
  16. package/dist/formats/e57-xml.js +127 -0
  17. package/dist/formats/e57-xml.js.map +1 -0
  18. package/dist/formats/e57.d.ts +29 -117
  19. package/dist/formats/e57.d.ts.map +1 -1
  20. package/dist/formats/e57.js +51 -444
  21. package/dist/formats/e57.js.map +1 -1
  22. package/dist/formats/ifcx-points.js +13 -1
  23. package/dist/formats/ifcx-points.js.map +1 -1
  24. package/dist/index.d.ts +2 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/streaming/ascii-points-source.d.ts +31 -0
  29. package/dist/streaming/ascii-points-source.d.ts.map +1 -0
  30. package/dist/streaming/ascii-points-source.js +83 -0
  31. package/dist/streaming/ascii-points-source.js.map +1 -0
  32. package/dist/streaming/decode-worker.js +41 -18
  33. package/dist/streaming/decode-worker.js.map +1 -1
  34. package/dist/streaming/e57-source.js +6 -1
  35. package/dist/streaming/e57-source.js.map +1 -1
  36. package/dist/streaming/inline-worker.d.ts +21 -0
  37. package/dist/streaming/inline-worker.d.ts.map +1 -0
  38. package/dist/streaming/inline-worker.js +5 -0
  39. package/dist/streaming/inline-worker.js.map +1 -0
  40. package/dist/streaming/laz-source.d.ts.map +1 -1
  41. package/dist/streaming/laz-source.js +33 -1
  42. package/dist/streaming/laz-source.js.map +1 -1
  43. package/dist/streaming/protocol.d.ts +1 -1
  44. package/dist/streaming/protocol.d.ts.map +1 -1
  45. package/dist/streaming/worker-client.d.ts +16 -3
  46. package/dist/streaming/worker-client.d.ts.map +1 -1
  47. package/dist/streaming/worker-client.js +77 -23
  48. package/dist/streaming/worker-client.js.map +1 -1
  49. package/package.json +3 -2
package/README.md CHANGED
@@ -21,6 +21,34 @@ if (chunk) {
21
21
  The renderer (`@ifc-lite/renderer`) consumes `DecodedPointChunk` values via
22
22
  `Renderer.loadPointClouds()` / `Renderer.addPointCloudChunks()`.
23
23
 
24
+ ## Streaming decode worker (zero Vite config)
25
+
26
+ For streaming sources (`.las`, `.laz`, `.ply`, `.pcd`, `.e57`, `.pts`, `.xyz`)
27
+ the decoder runs in a dedicated Web Worker so the main thread stays
28
+ responsive. The worker is **inlined into the published package** as a
29
+ `Blob`-URL — consumers don't need to set `worker.format: 'es'` or add the
30
+ package to `optimizeDeps.exclude` in their Vite config.
31
+
32
+ ```ts
33
+ import { createDecodeWorkerSource } from '@ifc-lite/pointcloud';
34
+
35
+ const source = createDecodeWorkerSource({ format: 'las', blob: file });
36
+ const info = await source.open();
37
+ // drive source.next(maxPoints) → DecodedPointChunk until it returns null
38
+ ```
39
+
40
+ Notes:
41
+
42
+ - The inlined worker bundle is lazy-loaded — consumers that only call
43
+ `decodeIfcxPointAttribute` (the non-worker decoder) don't pay the bytes.
44
+ - LAZ decoding (`format: 'laz'`) pulls in `laz-perf`'s wasm at runtime via
45
+ `new URL(..., import.meta.url)`, which doesn't resolve from inside a
46
+ `Blob`-URL worker. If you need LAZ from the published package, pass a
47
+ custom `spawn` callback that yields a worker capable of fetching the
48
+ wasm (see `DecodeWorkerOptions.spawn`).
49
+ - Strict CSPs need `script-src 'self' blob:` to allow the `Blob`-URL
50
+ worker.
51
+
24
52
  ## License
25
53
 
26
54
  [MPL-2.0](../../LICENSE)
@@ -0,0 +1,61 @@
1
+ /**
2
+ * PTS / XYZ ASCII point reader.
3
+ *
4
+ * Both formats are line-oriented plain-text scans. They differ only
5
+ * in the optional first-line point count (PTS may have one; XYZ
6
+ * never does) and in convention rather than syntax.
7
+ *
8
+ * Supported per-line layouts (auto-detected from column count of the
9
+ * first data line):
10
+ * 3 cols → X Y Z
11
+ * 4 cols → X Y Z I (intensity, normalised 0..1 or 0..255)
12
+ * 6 cols → X Y Z R G B (RGB 0..255)
13
+ * 7 cols → X Y Z I R G B (PTS standard layout)
14
+ * 9 cols → X Y Z I R G B Nx Ny Nz (normals dropped)
15
+ *
16
+ * Lines starting with `#`, `//`, or blank are skipped (comment
17
+ * support is non-standard but common in field exports).
18
+ *
19
+ * The reader is intentionally tolerant: any column count outside the
20
+ * known set falls through to "X Y Z plus discarded extras" so a file
21
+ * with weird custom columns still loads.
22
+ */
23
+ import type { DecodedPointChunk } from '../types.js';
24
+ export type AsciiPointsFormat = 'pts' | 'xyz';
25
+ export interface AsciiPointsLayout {
26
+ /** Number of whitespace-separated columns per data line. */
27
+ columns: number;
28
+ /** True if the first non-comment line is a single-integer point count. */
29
+ hasHeaderCount: boolean;
30
+ /** Resolved per-column meaning for the auto-detected layout. */
31
+ fields: AsciiPointsField[];
32
+ }
33
+ export type AsciiPointsField = 'x' | 'y' | 'z' | 'i' | 'r' | 'g' | 'b' | 'skip';
34
+ /**
35
+ * Probe the first ~16 KB to decide format + column layout.
36
+ *
37
+ * Looks at the first non-blank/non-comment line:
38
+ * - If it's a single integer, treat as a header point count (PTS).
39
+ * - Otherwise the column count of that line determines the layout.
40
+ *
41
+ * Returns null when the buffer doesn't look like ASCII point data
42
+ * (e.g. binary content, non-numeric tokens). Caller can then surface
43
+ * a clear "not a point cloud" error.
44
+ */
45
+ export declare function probeAsciiPointsLayout(buffer: Uint8Array, format: AsciiPointsFormat): AsciiPointsLayout | null;
46
+ /**
47
+ * Decode an entire ASCII point file into a single `DecodedPointChunk`.
48
+ *
49
+ * For multi-gigabyte scans the streaming source (`AsciiPointsStreamingSource`)
50
+ * should be preferred — this path materialises everything in memory.
51
+ *
52
+ * Per-channel handling:
53
+ * - Intensity: if any value > 1.0, treat the column as 0..255 and
54
+ * scale to u16. Otherwise treat as 0..1 and scale to u16. Mixed
55
+ * ranges within one file are uncommon; we make the call once.
56
+ * - RGB: if any channel > 1.0, treat the columns as 0..255. Else 0..1.
57
+ */
58
+ export declare function decodeAsciiPoints(bytes: Uint8Array, format: AsciiPointsFormat): DecodedPointChunk;
59
+ /** Same as `decodeAsciiPoints` but takes pre-decoded text. */
60
+ export declare function decodeAsciiPointsFromText(text: string, layout: AsciiPointsLayout): DecodedPointChunk;
61
+ //# sourceMappingURL=ascii-points.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ascii-points.d.ts","sourceRoot":"","sources":["../../src/formats/ascii-points.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAkB,MAAM,aAAa,CAAC;AAErE,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,KAAK,CAAC;AAE9C,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,cAAc,EAAE,OAAO,CAAC;IACxB,gEAAgE;IAChE,MAAM,EAAE,gBAAgB,EAAE,CAAC;CAC5B;AAED,MAAM,MAAM,gBAAgB,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,MAAM,CAAC;AAIhF;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,iBAAiB,GACxB,iBAAiB,GAAG,IAAI,CAgC1B;AA6CD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,iBAAiB,GACxB,iBAAiB,CAOnB;AAED,8DAA8D;AAC9D,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,iBAAiB,GACxB,iBAAiB,CAuHnB"}
@@ -0,0 +1,243 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ const TEXT_DECODER = new TextDecoder();
5
+ /**
6
+ * Probe the first ~16 KB to decide format + column layout.
7
+ *
8
+ * Looks at the first non-blank/non-comment line:
9
+ * - If it's a single integer, treat as a header point count (PTS).
10
+ * - Otherwise the column count of that line determines the layout.
11
+ *
12
+ * Returns null when the buffer doesn't look like ASCII point data
13
+ * (e.g. binary content, non-numeric tokens). Caller can then surface
14
+ * a clear "not a point cloud" error.
15
+ */
16
+ export function probeAsciiPointsLayout(buffer, format) {
17
+ const probeLen = Math.min(16384, buffer.length);
18
+ const text = TEXT_DECODER.decode(buffer.subarray(0, probeLen));
19
+ const lines = text.split(/\r?\n/);
20
+ let firstDataLine = null;
21
+ let hasHeaderCount = false;
22
+ for (let i = 0; i < lines.length; i++) {
23
+ const trimmed = lines[i].trim();
24
+ if (trimmed.length === 0)
25
+ continue;
26
+ if (trimmed.startsWith('#') || trimmed.startsWith('//'))
27
+ continue;
28
+ // PTS often begins with a single integer point count. XYZ never
29
+ // does — but we still accept it as a header if it parses cleanly.
30
+ if (i === 0 || !hasHeaderCount) {
31
+ const tokens = trimmed.split(/\s+/);
32
+ if (tokens.length === 1 && /^\d+$/.test(tokens[0])) {
33
+ hasHeaderCount = true;
34
+ continue;
35
+ }
36
+ }
37
+ firstDataLine = trimmed;
38
+ break;
39
+ }
40
+ if (firstDataLine === null)
41
+ return null;
42
+ const tokens = firstDataLine.split(/\s+/);
43
+ const columns = tokens.length;
44
+ // Sanity: every token must parse as a finite number.
45
+ for (const t of tokens) {
46
+ if (!Number.isFinite(Number(t)))
47
+ return null;
48
+ }
49
+ const fields = layoutFromColumnCount(columns, format);
50
+ if (!fields)
51
+ return null;
52
+ return { columns, hasHeaderCount, fields };
53
+ }
54
+ /**
55
+ * Resolve a column count to its field roles. Returns null when the
56
+ * count isn't one of the known shapes — caller should surface a clear
57
+ * "unsupported column layout" error rather than guess.
58
+ */
59
+ function layoutFromColumnCount(columns, format) {
60
+ switch (columns) {
61
+ case 3:
62
+ return ['x', 'y', 'z'];
63
+ case 4:
64
+ // Convention: 4-col PTS is X Y Z I; 4-col XYZ is rarer and
65
+ // sometimes X Y Z R (single-channel grayscale). We treat both
66
+ // as intensity to keep the logic shared — single-channel
67
+ // colour shows up greyscale anyway.
68
+ return ['x', 'y', 'z', 'i'];
69
+ case 6:
70
+ return ['x', 'y', 'z', 'r', 'g', 'b'];
71
+ case 7:
72
+ // Canonical PTS (X Y Z I R G B) and the most common XYZ-with-
73
+ // colour-and-intensity layout.
74
+ return ['x', 'y', 'z', 'i', 'r', 'g', 'b'];
75
+ case 9:
76
+ // X Y Z R G B Nx Ny Nz — colour but no intensity, drop normals.
77
+ return ['x', 'y', 'z', 'r', 'g', 'b', 'skip', 'skip', 'skip'];
78
+ case 10:
79
+ // X Y Z I R G B Nx Ny Nz — full PTS-with-normals. Drop normals.
80
+ return ['x', 'y', 'z', 'i', 'r', 'g', 'b', 'skip', 'skip', 'skip'];
81
+ default:
82
+ // Tolerant fallback for unknown layouts — still emit positions
83
+ // from the first three columns so the cloud loads. Discard the
84
+ // rest. Better than rejecting the whole file.
85
+ if (columns >= 3 && format === 'xyz') {
86
+ const fields = ['x', 'y', 'z'];
87
+ for (let i = 3; i < columns; i++)
88
+ fields.push('skip');
89
+ return fields;
90
+ }
91
+ return null;
92
+ }
93
+ }
94
+ /**
95
+ * Decode an entire ASCII point file into a single `DecodedPointChunk`.
96
+ *
97
+ * For multi-gigabyte scans the streaming source (`AsciiPointsStreamingSource`)
98
+ * should be preferred — this path materialises everything in memory.
99
+ *
100
+ * Per-channel handling:
101
+ * - Intensity: if any value > 1.0, treat the column as 0..255 and
102
+ * scale to u16. Otherwise treat as 0..1 and scale to u16. Mixed
103
+ * ranges within one file are uncommon; we make the call once.
104
+ * - RGB: if any channel > 1.0, treat the columns as 0..255. Else 0..1.
105
+ */
106
+ export function decodeAsciiPoints(bytes, format) {
107
+ const layout = probeAsciiPointsLayout(bytes, format);
108
+ if (!layout) {
109
+ throw new Error(`${format.toUpperCase()}: file does not look like ASCII point data`);
110
+ }
111
+ const text = TEXT_DECODER.decode(bytes);
112
+ return decodeAsciiPointsFromText(text, layout);
113
+ }
114
+ /** Same as `decodeAsciiPoints` but takes pre-decoded text. */
115
+ export function decodeAsciiPointsFromText(text, layout) {
116
+ const lines = text.split(/\r?\n/);
117
+ // Pre-pass: count valid data lines so we can allocate exactly.
118
+ // Cheap (no parsing) and saves the typed-array growth dance.
119
+ let dataLineCount = 0;
120
+ let headerSkipped = !layout.hasHeaderCount;
121
+ for (const raw of lines) {
122
+ const trimmed = raw.trim();
123
+ if (trimmed.length === 0)
124
+ continue;
125
+ if (trimmed.startsWith('#') || trimmed.startsWith('//'))
126
+ continue;
127
+ if (!headerSkipped) {
128
+ headerSkipped = true;
129
+ continue;
130
+ }
131
+ dataLineCount++;
132
+ }
133
+ const xIdx = layout.fields.indexOf('x');
134
+ const yIdx = layout.fields.indexOf('y');
135
+ const zIdx = layout.fields.indexOf('z');
136
+ const iIdx = layout.fields.indexOf('i');
137
+ const rIdx = layout.fields.indexOf('r');
138
+ const gIdx = layout.fields.indexOf('g');
139
+ const bIdx = layout.fields.indexOf('b');
140
+ const hasIntensity = iIdx >= 0;
141
+ const hasColor = rIdx >= 0 && gIdx >= 0 && bIdx >= 0;
142
+ const positions = new Float32Array(dataLineCount * 3);
143
+ const intensitiesRaw = hasIntensity ? new Float32Array(dataLineCount) : null;
144
+ const colorsRaw = hasColor ? new Float32Array(dataLineCount * 3) : null;
145
+ let written = 0;
146
+ let intensityMax = 0;
147
+ let colorMax = 0;
148
+ let bboxMinX = Infinity, bboxMinY = Infinity, bboxMinZ = Infinity;
149
+ let bboxMaxX = -Infinity, bboxMaxY = -Infinity, bboxMaxZ = -Infinity;
150
+ headerSkipped = !layout.hasHeaderCount;
151
+ for (const raw of lines) {
152
+ const trimmed = raw.trim();
153
+ if (trimmed.length === 0)
154
+ continue;
155
+ if (trimmed.startsWith('#') || trimmed.startsWith('//'))
156
+ continue;
157
+ if (!headerSkipped) {
158
+ headerSkipped = true;
159
+ continue;
160
+ }
161
+ const tokens = trimmed.split(/\s+/);
162
+ if (tokens.length < layout.columns)
163
+ continue;
164
+ const x = Number(tokens[xIdx]);
165
+ const y = Number(tokens[yIdx]);
166
+ const z = Number(tokens[zIdx]);
167
+ if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z))
168
+ continue;
169
+ positions[written * 3] = x;
170
+ positions[written * 3 + 1] = y;
171
+ positions[written * 3 + 2] = z;
172
+ if (x < bboxMinX)
173
+ bboxMinX = x;
174
+ if (x > bboxMaxX)
175
+ bboxMaxX = x;
176
+ if (y < bboxMinY)
177
+ bboxMinY = y;
178
+ if (y > bboxMaxY)
179
+ bboxMaxY = y;
180
+ if (z < bboxMinZ)
181
+ bboxMinZ = z;
182
+ if (z > bboxMaxZ)
183
+ bboxMaxZ = z;
184
+ if (intensitiesRaw) {
185
+ const v = Number(tokens[iIdx]);
186
+ const f = Number.isFinite(v) ? v : 0;
187
+ intensitiesRaw[written] = f;
188
+ if (f > intensityMax)
189
+ intensityMax = f;
190
+ }
191
+ if (colorsRaw) {
192
+ const r = Number(tokens[rIdx]);
193
+ const g = Number(tokens[gIdx]);
194
+ const b = Number(tokens[bIdx]);
195
+ const rf = Number.isFinite(r) ? r : 0;
196
+ const gf = Number.isFinite(g) ? g : 0;
197
+ const bf = Number.isFinite(b) ? b : 0;
198
+ colorsRaw[written * 3] = rf;
199
+ colorsRaw[written * 3 + 1] = gf;
200
+ colorsRaw[written * 3 + 2] = bf;
201
+ const m = Math.max(rf, gf, bf);
202
+ if (m > colorMax)
203
+ colorMax = m;
204
+ }
205
+ written++;
206
+ }
207
+ // Trim if some lines got rejected.
208
+ const trimmedPositions = written === dataLineCount ? positions : positions.subarray(0, written * 3);
209
+ // Normalise intensity to u16 (0..65535). Detect 0..255 vs 0..1 vs
210
+ // raw sensor by the observed maximum.
211
+ let intensities;
212
+ if (intensitiesRaw) {
213
+ intensities = new Uint16Array(written);
214
+ const scale = intensityMax > 1.0
215
+ ? (intensityMax > 255 ? 65535 / intensityMax : 65535 / 255)
216
+ : 65535;
217
+ for (let i = 0; i < written; i++) {
218
+ const v = intensitiesRaw[i] * scale;
219
+ intensities[i] = v < 0 ? 0 : v > 65535 ? 65535 : Math.round(v);
220
+ }
221
+ }
222
+ // Normalise colour to 0..1 floats.
223
+ let colors;
224
+ if (colorsRaw) {
225
+ colors = new Float32Array(written * 3);
226
+ const scale = colorMax > 1.0 ? 1 / 255 : 1;
227
+ for (let i = 0; i < written * 3; i++) {
228
+ const v = colorsRaw[i] * scale;
229
+ colors[i] = v < 0 ? 0 : v > 1 ? 1 : v;
230
+ }
231
+ }
232
+ const bbox = written === 0
233
+ ? { min: [0, 0, 0], max: [0, 0, 0] }
234
+ : { min: [bboxMinX, bboxMinY, bboxMinZ], max: [bboxMaxX, bboxMaxY, bboxMaxZ] };
235
+ return {
236
+ positions: written === dataLineCount ? positions : new Float32Array(trimmedPositions),
237
+ colors,
238
+ intensities,
239
+ pointCount: written,
240
+ bbox,
241
+ };
242
+ }
243
+ //# sourceMappingURL=ascii-points.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ascii-points.js","sourceRoot":"","sources":["../../src/formats/ascii-points.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * E57 binary-section decoder for a single Data3D scan.
3
+ *
4
+ * Walks DataPackets at `entry.binaryFileOffset` (in the LOGICAL
5
+ * post-CRC view) and decodes per-record bytestreams as Float32 /
6
+ * Float64 / Integer / ScaledInteger columns. ScaledInteger is a
7
+ * bit-packed integer with a per-field scale + offset (E57 spec
8
+ * §6.3.4) — common in Faro / Trimble / Leica exports.
9
+ */
10
+ import type { DecodedPointChunk, PointCloudBBox } from '../types.js';
11
+ import { type Data3DEntry } from './e57-xml.js';
12
+ /**
13
+ * Decode the binary section starting at `entry.binaryFileOffset` in the
14
+ * logical-bytes view. NOTE: `binaryFileOffset` here must already point
15
+ * at the first DataPacket (i.e. AFTER the 32-byte CompressedVector
16
+ * section header) — `decodeE57` does this conversion via
17
+ * `resolveCompressedVectorDataOffset`. Callers passing the raw XML
18
+ * offset directly will see a "bytestreamCount ≠ prototype length"
19
+ * mismatch.
20
+ *
21
+ * Supports Float (single/double), ScaledInteger (bit-packed integer
22
+ * with scale/offset), and Integer for cartesianX/Y/Z + colorRed/
23
+ * Green/Blue + intensity. Other prototype fields are honoured for
24
+ * stride math but discarded.
25
+ */
26
+ export declare function decodeE57Scan(logical: Uint8Array, entry: Data3DEntry): DecodedPointChunk;
27
+ export declare function computeBBox(positions: Float32Array): PointCloudBBox;
28
+ //# sourceMappingURL=e57-decode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"e57-decode.d.ts","sourceRoot":"","sources":["../../src/formats/e57-decode.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAa,KAAK,WAAW,EAAuB,MAAM,cAAc,CAAC;AAEhF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,iBAAiB,CAqKxF;AAuRD,wBAAgB,WAAW,CAAC,SAAS,EAAE,YAAY,GAAG,cAAc,CAsBnE"}