@helpers4/map 3.0.2-alpha.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/lib/index.js ADDED
@@ -0,0 +1,249 @@
1
+ //#region helpers/map/countBy.ts
2
+ /**
3
+ * This file is part of helpers4.
4
+ * Copyright (C) 2025 baxyz
5
+ * SPDX-License-Identifier: LGPL-3.0-or-later
6
+ */
7
+ /**
8
+ * Groups the entries of a Map by a derived key and counts how many fall into each group.
9
+ * @param map - The Map to summarize
10
+ * @param fn - Function deriving the grouping key from (value, key)
11
+ * @returns A Map from derived key to the number of entries in that group
12
+ * @example
13
+ * countBy(new Map([['a', 1], ['b', 2], ['c', 3]]), value => value % 2 === 0 ? 'even' : 'odd')
14
+ * // => Map(2) { 'odd' => 2, 'even' => 1 }
15
+ * @since next
16
+ */
17
+ function countBy(map, fn) {
18
+ const counts = /* @__PURE__ */ new Map();
19
+ for (const [key, value] of map) {
20
+ const group = fn(value, key);
21
+ counts.set(group, (counts.get(group) ?? 0) + 1);
22
+ }
23
+ return counts;
24
+ }
25
+ //#endregion
26
+ //#region helpers/map/every.ts
27
+ /**
28
+ * This file is part of helpers4.
29
+ * Copyright (C) 2025 baxyz
30
+ * SPDX-License-Identifier: LGPL-3.0-or-later
31
+ */
32
+ /**
33
+ * Checks if every entry of a Map satisfies the predicate. Short-circuits on the first mismatch.
34
+ * @param map - The Map to check
35
+ * @param predicate - Function invoked with (value, key)
36
+ * @returns `true` if all entries match (vacuously `true` for an empty map), `false` otherwise
37
+ * @example
38
+ * every(new Map([['a', 1], ['b', 2]]), value => value > 0)
39
+ * // => true
40
+ * @since next
41
+ */
42
+ function every(map, predicate) {
43
+ for (const [key, value] of map) if (!predicate(value, key)) return false;
44
+ return true;
45
+ }
46
+ //#endregion
47
+ //#region helpers/map/filter.ts
48
+ /**
49
+ * This file is part of helpers4.
50
+ * Copyright (C) 2025 baxyz
51
+ * SPDX-License-Identifier: LGPL-3.0-or-later
52
+ */
53
+ /**
54
+ * Creates a new Map containing only the entries for which the predicate returns true.
55
+ * @param map - The Map to filter
56
+ * @param predicate - Function invoked with (value, key) — return true to keep the entry
57
+ * @returns A new Map with only the matching entries
58
+ * @example
59
+ * filter(new Map([['a', 1], ['b', 2], ['c', 3]]), value => value % 2 === 0)
60
+ * // => Map(1) { 'b' => 2 }
61
+ * @since next
62
+ */
63
+ function filter(map, predicate) {
64
+ const result = /* @__PURE__ */ new Map();
65
+ for (const [key, value] of map) if (predicate(value, key)) result.set(key, value);
66
+ return result;
67
+ }
68
+ //#endregion
69
+ //#region helpers/map/findKey.ts
70
+ /**
71
+ * This file is part of helpers4.
72
+ * Copyright (C) 2025 baxyz
73
+ * SPDX-License-Identifier: LGPL-3.0-or-later
74
+ */
75
+ /**
76
+ * Returns the first key of a Map whose entry satisfies the predicate, in insertion order.
77
+ * @param map - The Map to search
78
+ * @param predicate - Function invoked with (value, key)
79
+ * @returns The matching key, or `undefined` if none matches
80
+ * @example
81
+ * findKey(new Map([['a', 1], ['b', 2]]), value => value > 1)
82
+ * // => 'b'
83
+ * @since next
84
+ */
85
+ function findKey(map, predicate) {
86
+ for (const [key, value] of map) if (predicate(value, key)) return key;
87
+ }
88
+ //#endregion
89
+ //#region helpers/map/findValue.ts
90
+ /**
91
+ * This file is part of helpers4.
92
+ * Copyright (C) 2025 baxyz
93
+ * SPDX-License-Identifier: LGPL-3.0-or-later
94
+ */
95
+ /**
96
+ * Returns the first value of a Map whose entry satisfies the predicate, in insertion order.
97
+ * @param map - The Map to search
98
+ * @param predicate - Function invoked with (value, key)
99
+ * @returns The matching value, or `undefined` if none matches
100
+ * @example
101
+ * findValue(new Map([['a', 1], ['b', 2]]), value => value > 1)
102
+ * // => 2
103
+ * @since next
104
+ */
105
+ function findValue(map, predicate) {
106
+ for (const [key, value] of map) if (predicate(value, key)) return value;
107
+ }
108
+ //#endregion
109
+ //#region helpers/map/hasValue.ts
110
+ /**
111
+ * This file is part of helpers4.
112
+ * Copyright (C) 2025 baxyz
113
+ * SPDX-License-Identifier: LGPL-3.0-or-later
114
+ */
115
+ /**
116
+ * Checks whether a value exists anywhere in a Map (`Map.prototype.has` checks keys, not values).
117
+ * Uses `Object.is`-style equality (via `===`, with `NaN` matching `NaN`).
118
+ * @param map - The Map to search
119
+ * @param value - The value to look for
120
+ * @returns `true` if the value is found in at least one entry
121
+ * @example
122
+ * hasValue(new Map([['a', 1], ['b', 2]]), 2)
123
+ * // => true
124
+ * @since next
125
+ */
126
+ function hasValue(map, value) {
127
+ for (const v of map.values()) if (Object.is(v, value)) return true;
128
+ return false;
129
+ }
130
+ //#endregion
131
+ //#region helpers/map/mapKeys.ts
132
+ /**
133
+ * This file is part of helpers4.
134
+ * Copyright (C) 2025 baxyz
135
+ * SPDX-License-Identifier: LGPL-3.0-or-later
136
+ */
137
+ /**
138
+ * Creates a new Map with the same values but with each key transformed by a function.
139
+ * If two entries derive the same new key, the later one (in insertion order) wins.
140
+ * @param map - The Map to transform
141
+ * @param fn - Function invoked with (key, value) that returns the new key
142
+ * @returns A new Map with transformed keys
143
+ * @example
144
+ * mapKeys(new Map([['a', 1], ['b', 2]]), key => key.toUpperCase())
145
+ * // => Map(2) { 'A' => 1, 'B' => 2 }
146
+ * @since next
147
+ */
148
+ function mapKeys(map, fn) {
149
+ const result = /* @__PURE__ */ new Map();
150
+ for (const [key, value] of map) result.set(fn(key, value), value);
151
+ return result;
152
+ }
153
+ //#endregion
154
+ //#region helpers/map/mapValues.ts
155
+ /**
156
+ * This file is part of helpers4.
157
+ * Copyright (C) 2025 baxyz
158
+ * SPDX-License-Identifier: LGPL-3.0-or-later
159
+ */
160
+ /**
161
+ * Creates a new Map with the same keys but with each value transformed by a function.
162
+ * @param map - The Map to transform
163
+ * @param fn - Function invoked with (value, key) that returns the new value
164
+ * @returns A new Map with transformed values
165
+ * @example
166
+ * mapValues(new Map([['a', 1], ['b', 2]]), value => value * 10)
167
+ * // => Map(2) { 'a' => 10, 'b' => 20 }
168
+ * @since next
169
+ */
170
+ function mapValues(map, fn) {
171
+ const result = /* @__PURE__ */ new Map();
172
+ for (const [key, value] of map) result.set(key, fn(value, key));
173
+ return result;
174
+ }
175
+ //#endregion
176
+ //#region helpers/map/reduce.ts
177
+ /**
178
+ * This file is part of helpers4.
179
+ * Copyright (C) 2025 baxyz
180
+ * SPDX-License-Identifier: LGPL-3.0-or-later
181
+ */
182
+ /**
183
+ * Reduces a Map to a single value by applying a function to each entry, in insertion order.
184
+ * @param map - The Map to reduce
185
+ * @param fn - Function invoked with (accumulator, value, key)
186
+ * @param initial - Initial accumulator value
187
+ * @returns The final accumulator value
188
+ * @example
189
+ * reduce(new Map([['a', 1], ['b', 2]]), (acc, value) => acc + value, 0)
190
+ * // => 3
191
+ * @since next
192
+ */
193
+ function reduce(map, fn, initial) {
194
+ let accumulator = initial;
195
+ for (const [key, value] of map) accumulator = fn(accumulator, value, key);
196
+ return accumulator;
197
+ }
198
+ //#endregion
199
+ //#region helpers/map/some.ts
200
+ /**
201
+ * This file is part of helpers4.
202
+ * Copyright (C) 2025 baxyz
203
+ * SPDX-License-Identifier: LGPL-3.0-or-later
204
+ */
205
+ /**
206
+ * Checks if at least one entry of a Map satisfies the predicate. Short-circuits on the first match.
207
+ * @param map - The Map to check
208
+ * @param predicate - Function invoked with (value, key)
209
+ * @returns `true` if at least one entry matches, `false` otherwise (including for an empty map)
210
+ * @example
211
+ * some(new Map([['a', 1], ['b', 2]]), value => value > 1)
212
+ * // => true
213
+ * @since next
214
+ */
215
+ function some(map, predicate) {
216
+ for (const [key, value] of map) if (predicate(value, key)) return true;
217
+ return false;
218
+ }
219
+ //#endregion
220
+ //#region helpers/map/toMapByKey.ts
221
+ /**
222
+ * This file is part of helpers4.
223
+ * Copyright (C) 2025 baxyz
224
+ * SPDX-License-Identifier: LGPL-3.0-or-later
225
+ */
226
+ /**
227
+ * Builds a Map from an iterable of items, keyed by a derived key. When two items derive the
228
+ * same key, the later item wins (last-write-wins, matching `Map.prototype.set` semantics).
229
+ *
230
+ * Named `toMapByKey`, not `keyBy` (lodash's name for the same idea) — lodash's `_.keyBy`
231
+ * returns a plain object, not a `Map`; the `to<Type>` prefix (matching `toSorted`/`toReversed`)
232
+ * makes the actual return type unambiguous.
233
+ * @param items - The items to index
234
+ * @param fn - Function deriving the key for each item
235
+ * @returns A Map from derived key to item
236
+ * @example
237
+ * toMapByKey([{ id: 'a', n: 1 }, { id: 'b', n: 2 }], item => item.id)
238
+ * // => Map(2) { 'a' => { id: 'a', n: 1 }, 'b' => { id: 'b', n: 2 } }
239
+ * @since next
240
+ */
241
+ function toMapByKey(items, fn) {
242
+ const result = /* @__PURE__ */ new Map();
243
+ for (const item of items) result.set(fn(item), item);
244
+ return result;
245
+ }
246
+ //#endregion
247
+ export { countBy, every, filter, findKey, findValue, hasValue, mapKeys, mapValues, reduce, some, toMapByKey };
248
+
249
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../helpers/map/countBy.ts","../../../helpers/map/every.ts","../../../helpers/map/filter.ts","../../../helpers/map/findKey.ts","../../../helpers/map/findValue.ts","../../../helpers/map/hasValue.ts","../../../helpers/map/mapKeys.ts","../../../helpers/map/mapValues.ts","../../../helpers/map/reduce.ts","../../../helpers/map/some.ts","../../../helpers/map/toMapByKey.ts"],"sourcesContent":["/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Groups the entries of a Map by a derived key and counts how many fall into each group.\n * @param map - The Map to summarize\n * @param fn - Function deriving the grouping key from (value, key)\n * @returns A Map from derived key to the number of entries in that group\n * @example\n * countBy(new Map([['a', 1], ['b', 2], ['c', 3]]), value => value % 2 === 0 ? 'even' : 'odd')\n * // => Map(2) { 'odd' => 2, 'even' => 1 }\n * @since next\n */\nexport function countBy<K, V, R>(\n map: ReadonlyMap<K, V>,\n fn: (value: V, key: K) => R,\n): Map<R, number> {\n const counts = new Map<R, number>();\n for (const [key, value] of map) {\n const group = fn(value, key);\n counts.set(group, (counts.get(group) ?? 0) + 1);\n }\n return counts;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if every entry of a Map satisfies the predicate. Short-circuits on the first mismatch.\n * @param map - The Map to check\n * @param predicate - Function invoked with (value, key)\n * @returns `true` if all entries match (vacuously `true` for an empty map), `false` otherwise\n * @example\n * every(new Map([['a', 1], ['b', 2]]), value => value > 0)\n * // => true\n * @since next\n */\nexport function every<K, V>(\n map: ReadonlyMap<K, V>,\n predicate: (value: V, key: K) => boolean,\n): boolean {\n for (const [key, value] of map) {\n if (!predicate(value, key)) return false;\n }\n return true;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Creates a new Map containing only the entries for which the predicate returns true.\n * @param map - The Map to filter\n * @param predicate - Function invoked with (value, key) — return true to keep the entry\n * @returns A new Map with only the matching entries\n * @example\n * filter(new Map([['a', 1], ['b', 2], ['c', 3]]), value => value % 2 === 0)\n * // => Map(1) { 'b' => 2 }\n * @since next\n */\nexport function filter<K, V>(\n map: ReadonlyMap<K, V>,\n predicate: (value: V, key: K) => boolean,\n): Map<K, V> {\n const result = new Map<K, V>();\n for (const [key, value] of map) {\n if (predicate(value, key)) {\n result.set(key, value);\n }\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Returns the first key of a Map whose entry satisfies the predicate, in insertion order.\n * @param map - The Map to search\n * @param predicate - Function invoked with (value, key)\n * @returns The matching key, or `undefined` if none matches\n * @example\n * findKey(new Map([['a', 1], ['b', 2]]), value => value > 1)\n * // => 'b'\n * @since next\n */\nexport function findKey<K, V>(\n map: ReadonlyMap<K, V>,\n predicate: (value: V, key: K) => boolean,\n): K | undefined {\n for (const [key, value] of map) {\n if (predicate(value, key)) return key;\n }\n return undefined;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Returns the first value of a Map whose entry satisfies the predicate, in insertion order.\n * @param map - The Map to search\n * @param predicate - Function invoked with (value, key)\n * @returns The matching value, or `undefined` if none matches\n * @example\n * findValue(new Map([['a', 1], ['b', 2]]), value => value > 1)\n * // => 2\n * @since next\n */\nexport function findValue<K, V>(\n map: ReadonlyMap<K, V>,\n predicate: (value: V, key: K) => boolean,\n): V | undefined {\n for (const [key, value] of map) {\n if (predicate(value, key)) return value;\n }\n return undefined;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks whether a value exists anywhere in a Map (`Map.prototype.has` checks keys, not values).\n * Uses `Object.is`-style equality (via `===`, with `NaN` matching `NaN`).\n * @param map - The Map to search\n * @param value - The value to look for\n * @returns `true` if the value is found in at least one entry\n * @example\n * hasValue(new Map([['a', 1], ['b', 2]]), 2)\n * // => true\n * @since next\n */\nexport function hasValue<K, V>(map: ReadonlyMap<K, V>, value: V): boolean {\n for (const v of map.values()) {\n if (Object.is(v, value)) return true;\n }\n return false;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Creates a new Map with the same values but with each key transformed by a function.\n * If two entries derive the same new key, the later one (in insertion order) wins.\n * @param map - The Map to transform\n * @param fn - Function invoked with (key, value) that returns the new key\n * @returns A new Map with transformed keys\n * @example\n * mapKeys(new Map([['a', 1], ['b', 2]]), key => key.toUpperCase())\n * // => Map(2) { 'A' => 1, 'B' => 2 }\n * @since next\n */\nexport function mapKeys<K, V, R>(\n map: ReadonlyMap<K, V>,\n fn: (key: K, value: V) => R,\n): Map<R, V> {\n const result = new Map<R, V>();\n for (const [key, value] of map) {\n result.set(fn(key, value), value);\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Creates a new Map with the same keys but with each value transformed by a function.\n * @param map - The Map to transform\n * @param fn - Function invoked with (value, key) that returns the new value\n * @returns A new Map with transformed values\n * @example\n * mapValues(new Map([['a', 1], ['b', 2]]), value => value * 10)\n * // => Map(2) { 'a' => 10, 'b' => 20 }\n * @since next\n */\nexport function mapValues<K, V, R>(\n map: ReadonlyMap<K, V>,\n fn: (value: V, key: K) => R,\n): Map<K, R> {\n const result = new Map<K, R>();\n for (const [key, value] of map) {\n result.set(key, fn(value, key));\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Reduces a Map to a single value by applying a function to each entry, in insertion order.\n * @param map - The Map to reduce\n * @param fn - Function invoked with (accumulator, value, key)\n * @param initial - Initial accumulator value\n * @returns The final accumulator value\n * @example\n * reduce(new Map([['a', 1], ['b', 2]]), (acc, value) => acc + value, 0)\n * // => 3\n * @since next\n */\nexport function reduce<K, V, R>(\n map: ReadonlyMap<K, V>,\n fn: (accumulator: R, value: V, key: K) => R,\n initial: R,\n): R {\n let accumulator = initial;\n for (const [key, value] of map) {\n accumulator = fn(accumulator, value, key);\n }\n return accumulator;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if at least one entry of a Map satisfies the predicate. Short-circuits on the first match.\n * @param map - The Map to check\n * @param predicate - Function invoked with (value, key)\n * @returns `true` if at least one entry matches, `false` otherwise (including for an empty map)\n * @example\n * some(new Map([['a', 1], ['b', 2]]), value => value > 1)\n * // => true\n * @since next\n */\nexport function some<K, V>(\n map: ReadonlyMap<K, V>,\n predicate: (value: V, key: K) => boolean,\n): boolean {\n for (const [key, value] of map) {\n if (predicate(value, key)) return true;\n }\n return false;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Builds a Map from an iterable of items, keyed by a derived key. When two items derive the\n * same key, the later item wins (last-write-wins, matching `Map.prototype.set` semantics).\n *\n * Named `toMapByKey`, not `keyBy` (lodash's name for the same idea) — lodash's `_.keyBy`\n * returns a plain object, not a `Map`; the `to<Type>` prefix (matching `toSorted`/`toReversed`)\n * makes the actual return type unambiguous.\n * @param items - The items to index\n * @param fn - Function deriving the key for each item\n * @returns A Map from derived key to item\n * @example\n * toMapByKey([{ id: 'a', n: 1 }, { id: 'b', n: 2 }], item => item.id)\n * // => Map(2) { 'a' => { id: 'a', n: 1 }, 'b' => { id: 'b', n: 2 } }\n * @since next\n */\nexport function toMapByKey<T, K>(items: Iterable<T>, fn: (item: T) => K): Map<K, T> {\n const result = new Map<K, T>();\n for (const item of items) {\n result.set(fn(item), item);\n }\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,SAAgB,QACd,KACA,IACgB;CAChB,MAAM,yBAAS,IAAI,IAAe;CAClC,KAAK,MAAM,CAAC,KAAK,UAAU,KAAK;EAC9B,MAAM,QAAQ,GAAG,OAAO,GAAG;EAC3B,OAAO,IAAI,QAAQ,OAAO,IAAI,KAAK,KAAK,KAAK,CAAC;CAChD;CACA,OAAO;AACT;;;;;;;;;;;;;;;;;;ACVA,SAAgB,MACd,KACA,WACS;CACT,KAAK,MAAM,CAAC,KAAK,UAAU,KACzB,IAAI,CAAC,UAAU,OAAO,GAAG,GAAG,OAAO;CAErC,OAAO;AACT;;;;;;;;;;;;;;;;;;ACRA,SAAgB,OACd,KACA,WACW;CACX,MAAM,yBAAS,IAAI,IAAU;CAC7B,KAAK,MAAM,CAAC,KAAK,UAAU,KACzB,IAAI,UAAU,OAAO,GAAG,GACtB,OAAO,IAAI,KAAK,KAAK;CAGzB,OAAO;AACT;;;;;;;;;;;;;;;;;;ACXA,SAAgB,QACd,KACA,WACe;CACf,KAAK,MAAM,CAAC,KAAK,UAAU,KACzB,IAAI,UAAU,OAAO,GAAG,GAAG,OAAO;AAGtC;;;;;;;;;;;;;;;;;;ACRA,SAAgB,UACd,KACA,WACe;CACf,KAAK,MAAM,CAAC,KAAK,UAAU,KACzB,IAAI,UAAU,OAAO,GAAG,GAAG,OAAO;AAGtC;;;;;;;;;;;;;;;;;;;ACPA,SAAgB,SAAe,KAAwB,OAAmB;CACxE,KAAK,MAAM,KAAK,IAAI,OAAO,GACzB,IAAI,OAAO,GAAG,GAAG,KAAK,GAAG,OAAO;CAElC,OAAO;AACT;;;;;;;;;;;;;;;;;;;ACLA,SAAgB,QACd,KACA,IACW;CACX,MAAM,yBAAS,IAAI,IAAU;CAC7B,KAAK,MAAM,CAAC,KAAK,UAAU,KACzB,OAAO,IAAI,GAAG,KAAK,KAAK,GAAG,KAAK;CAElC,OAAO;AACT;;;;;;;;;;;;;;;;;;ACVA,SAAgB,UACd,KACA,IACW;CACX,MAAM,yBAAS,IAAI,IAAU;CAC7B,KAAK,MAAM,CAAC,KAAK,UAAU,KACzB,OAAO,IAAI,KAAK,GAAG,OAAO,GAAG,CAAC;CAEhC,OAAO;AACT;;;;;;;;;;;;;;;;;;;ACRA,SAAgB,OACd,KACA,IACA,SACG;CACH,IAAI,cAAc;CAClB,KAAK,MAAM,CAAC,KAAK,UAAU,KACzB,cAAc,GAAG,aAAa,OAAO,GAAG;CAE1C,OAAO;AACT;;;;;;;;;;;;;;;;;;ACXA,SAAgB,KACd,KACA,WACS;CACT,KAAK,MAAM,CAAC,KAAK,UAAU,KACzB,IAAI,UAAU,OAAO,GAAG,GAAG,OAAO;CAEpC,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;ACHA,SAAgB,WAAiB,OAAoB,IAA+B;CAClF,MAAM,yBAAS,IAAI,IAAU;CAC7B,KAAK,MAAM,QAAQ,OACjB,OAAO,IAAI,GAAG,IAAI,GAAG,IAAI;CAE3B,OAAO;AACT"}