@principal-ai/file-city-react 0.3.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.
Files changed (51) hide show
  1. package/dist/builder/cityDataUtils.d.ts +15 -0
  2. package/dist/builder/cityDataUtils.d.ts.map +1 -0
  3. package/dist/builder/cityDataUtils.js +348 -0
  4. package/dist/components/ArchitectureMapHighlightLayers.d.ts +63 -0
  5. package/dist/components/ArchitectureMapHighlightLayers.d.ts.map +1 -0
  6. package/dist/components/ArchitectureMapHighlightLayers.js +1040 -0
  7. package/dist/components/CityViewWithReactFlow.d.ts +14 -0
  8. package/dist/components/CityViewWithReactFlow.d.ts.map +1 -0
  9. package/dist/components/CityViewWithReactFlow.js +266 -0
  10. package/dist/config/files.json +996 -0
  11. package/dist/hooks/useCodeCityData.d.ts +21 -0
  12. package/dist/hooks/useCodeCityData.d.ts.map +1 -0
  13. package/dist/hooks/useCodeCityData.js +57 -0
  14. package/dist/index.d.ts +14 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +29 -0
  17. package/dist/render/client/drawLayeredBuildings.d.ts +51 -0
  18. package/dist/render/client/drawLayeredBuildings.d.ts.map +1 -0
  19. package/dist/render/client/drawLayeredBuildings.js +650 -0
  20. package/dist/stories/ArchitectureMapGridLayout.stories.d.ts +73 -0
  21. package/dist/stories/ArchitectureMapGridLayout.stories.d.ts.map +1 -0
  22. package/dist/stories/ArchitectureMapGridLayout.stories.js +345 -0
  23. package/dist/stories/ArchitectureMapHighlightLayers.stories.d.ts +78 -0
  24. package/dist/stories/ArchitectureMapHighlightLayers.stories.d.ts.map +1 -0
  25. package/dist/stories/ArchitectureMapHighlightLayers.stories.js +270 -0
  26. package/dist/stories/CityViewWithReactFlow.stories.d.ts +24 -0
  27. package/dist/stories/CityViewWithReactFlow.stories.d.ts.map +1 -0
  28. package/dist/stories/CityViewWithReactFlow.stories.js +778 -0
  29. package/dist/stories/sample-data.d.ts +4 -0
  30. package/dist/stories/sample-data.d.ts.map +1 -0
  31. package/dist/stories/sample-data.js +268 -0
  32. package/dist/types/react-types.d.ts +17 -0
  33. package/dist/types/react-types.d.ts.map +1 -0
  34. package/dist/types/react-types.js +4 -0
  35. package/dist/utils/fileColorHighlightLayers.d.ts +86 -0
  36. package/dist/utils/fileColorHighlightLayers.d.ts.map +1 -0
  37. package/dist/utils/fileColorHighlightLayers.js +283 -0
  38. package/package.json +49 -0
  39. package/src/builder/cityDataUtils.ts +430 -0
  40. package/src/components/ArchitectureMapHighlightLayers.tsx +1518 -0
  41. package/src/components/CityViewWithReactFlow.tsx +365 -0
  42. package/src/config/files.json +996 -0
  43. package/src/hooks/useCodeCityData.ts +82 -0
  44. package/src/index.ts +64 -0
  45. package/src/render/client/drawLayeredBuildings.ts +946 -0
  46. package/src/stories/ArchitectureMapGridLayout.stories.tsx +410 -0
  47. package/src/stories/ArchitectureMapHighlightLayers.stories.tsx +312 -0
  48. package/src/stories/CityViewWithReactFlow.stories.tsx +787 -0
  49. package/src/stories/sample-data.ts +301 -0
  50. package/src/types/react-types.ts +18 -0
  51. package/src/utils/fileColorHighlightLayers.ts +378 -0
@@ -0,0 +1,15 @@
1
+ import { CityData, SelectiveRenderOptions } from '@principal-ai/file-city-builder';
2
+ export declare const filterCityDataForSelectiveRender: (cityData: CityData, selectiveRender?: SelectiveRenderOptions) => CityData;
3
+ /**
4
+ * Filter city data to only include a subdirectory and optionally remap coordinates
5
+ * to make the subdirectory the new origin (0,0)
6
+ */
7
+ export declare const filterCityDataForSubdirectory: (cityData: CityData, subdirectoryPath: string, autoCenter?: boolean) => CityData;
8
+ /**
9
+ * Filter city data based on multiple directory filters with include/exclude modes
10
+ */
11
+ export declare const filterCityDataForMultipleDirectories: (cityData: CityData, filters: Array<{
12
+ path: string;
13
+ mode: "include" | "exclude";
14
+ }>, autoCenter?: boolean, combineMode?: "union" | "intersection") => CityData;
15
+ //# sourceMappingURL=cityDataUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cityDataUtils.d.ts","sourceRoot":"","sources":["../../src/builder/cityDataUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAER,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;AAGzC,eAAO,MAAM,gCAAgC,GAC3C,UAAU,QAAQ,EAClB,kBAAkB,sBAAsB,KACvC,QAqBF,CAAC;AA6GF;;;GAGG;AACH,eAAO,MAAM,6BAA6B,GACxC,UAAU,QAAQ,EAClB,kBAAkB,MAAM,EACxB,aAAY,OAAc,KACzB,QA6HF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oCAAoC,GAC/C,UAAU,QAAQ,EAClB,SAAS,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CAAA;CAAE,CAAC,EAC7D,aAAY,OAAc,EAC1B,cAAa,OAAO,GAAG,cAAwB,KAC9C,QAiJF,CAAC"}
@@ -0,0 +1,348 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.filterCityDataForMultipleDirectories = exports.filterCityDataForSubdirectory = exports.filterCityDataForSelectiveRender = void 0;
4
+ // Utility functions for selective rendering
5
+ const filterCityDataForSelectiveRender = (cityData, selectiveRender) => {
6
+ if (!selectiveRender || selectiveRender.mode === 'all') {
7
+ return cityData;
8
+ }
9
+ const { mode, directories, rootDirectory, showParentContext } = selectiveRender;
10
+ switch (mode) {
11
+ case 'filter':
12
+ return filterCityData(cityData, directories || new Set());
13
+ case 'focus':
14
+ // Focus mode doesn't filter data, just affects rendering
15
+ return cityData;
16
+ case 'drilldown':
17
+ return drilldownCityData(cityData, rootDirectory || '', showParentContext || false);
18
+ default:
19
+ return cityData;
20
+ }
21
+ };
22
+ exports.filterCityDataForSelectiveRender = filterCityDataForSelectiveRender;
23
+ const filterCityData = (cityData, visibleDirectories) => {
24
+ const filteredBuildings = cityData.buildings.filter(building => {
25
+ // Check if building is in any of the visible directories
26
+ return Array.from(visibleDirectories).some(dir => building.path.startsWith(dir + '/') || building.path === dir);
27
+ });
28
+ const filteredDistricts = cityData.districts.filter(district => {
29
+ // Include district if it's in the visible set or is a parent of a visible directory
30
+ return Array.from(visibleDirectories).some(dir => district.path === dir ||
31
+ dir.startsWith(district.path + '/') ||
32
+ district.path.startsWith(dir + '/'));
33
+ });
34
+ return {
35
+ ...cityData,
36
+ buildings: filteredBuildings,
37
+ districts: filteredDistricts,
38
+ bounds: recalculateBounds(filteredBuildings, filteredDistricts),
39
+ };
40
+ };
41
+ const drilldownCityData = (cityData, rootDirectory, showParentContext) => {
42
+ if (!rootDirectory)
43
+ return cityData;
44
+ // Filter buildings to only those within the root directory
45
+ const filteredBuildings = cityData.buildings
46
+ .filter(building => building.path.startsWith(rootDirectory + '/') || building.path === rootDirectory)
47
+ .map(building => ({
48
+ ...building,
49
+ // Adjust path to be relative to the new root
50
+ path: building.path.startsWith(rootDirectory + '/')
51
+ ? building.path.substring(rootDirectory.length + 1)
52
+ : building.path,
53
+ }));
54
+ // Filter districts to only those within the root directory
55
+ const filteredDistricts = cityData.districts
56
+ .filter(district => district.path.startsWith(rootDirectory + '/') || district.path === rootDirectory)
57
+ .map(district => ({
58
+ ...district,
59
+ // Adjust path to be relative to the new root
60
+ path: district.path.startsWith(rootDirectory + '/')
61
+ ? district.path.substring(rootDirectory.length + 1)
62
+ : district.path === rootDirectory
63
+ ? ''
64
+ : district.path,
65
+ }));
66
+ // If showing parent context, add immediate parent district
67
+ if (showParentContext && rootDirectory) {
68
+ const parentPath = rootDirectory.split('/').slice(0, -1).join('/');
69
+ const parentDistrict = cityData.districts.find(d => d.path === parentPath);
70
+ if (parentDistrict) {
71
+ filteredDistricts.unshift({
72
+ ...parentDistrict,
73
+ path: '../' + parentDistrict.path.split('/').pop(),
74
+ });
75
+ }
76
+ }
77
+ return {
78
+ ...cityData,
79
+ buildings: filteredBuildings,
80
+ districts: filteredDistricts,
81
+ bounds: recalculateBounds(filteredBuildings, filteredDistricts),
82
+ metadata: {
83
+ ...cityData.metadata,
84
+ rootPath: rootDirectory,
85
+ },
86
+ };
87
+ };
88
+ const recalculateBounds = (buildings, districts) => {
89
+ if (buildings.length === 0 && districts.length === 0) {
90
+ return { minX: 0, maxX: 100, minZ: 0, maxZ: 100 };
91
+ }
92
+ const allX = [
93
+ ...buildings.map(b => b.position.x),
94
+ ...districts.flatMap(d => [d.worldBounds.minX, d.worldBounds.maxX]),
95
+ ];
96
+ const allZ = [
97
+ ...buildings.map(b => b.position.z),
98
+ ...districts.flatMap(d => [d.worldBounds.minZ, d.worldBounds.maxZ]),
99
+ ];
100
+ return {
101
+ minX: Math.min(...allX),
102
+ maxX: Math.max(...allX),
103
+ minZ: Math.min(...allZ),
104
+ maxZ: Math.max(...allZ),
105
+ };
106
+ };
107
+ /**
108
+ * Filter city data to only include a subdirectory and optionally remap coordinates
109
+ * to make the subdirectory the new origin (0,0)
110
+ */
111
+ const filterCityDataForSubdirectory = (cityData, subdirectoryPath, autoCenter = true) => {
112
+ if (!subdirectoryPath)
113
+ return cityData;
114
+ // Normalize path - remove leading/trailing slashes
115
+ const normalizedPath = subdirectoryPath.replace(/^\/+|\/+$/g, '');
116
+ // Filter buildings to only those within the subdirectory
117
+ const filteredBuildings = cityData.buildings.filter(building => building.path === normalizedPath ||
118
+ building.path.startsWith(normalizedPath + '/') ||
119
+ building.path.startsWith(`/${normalizedPath}`));
120
+ // Filter districts to only those within the subdirectory
121
+ const filteredDistricts = cityData.districts.filter(district => district.path === normalizedPath ||
122
+ district.path.startsWith(normalizedPath + '/') ||
123
+ district.path.startsWith(`/${normalizedPath}`));
124
+ // Find the subdirectory district to get its bounds
125
+ const subdirectoryDistrict = cityData.districts.find(d => d.path === normalizedPath);
126
+ if (!subdirectoryDistrict && filteredBuildings.length === 0) {
127
+ // Subdirectory not found or empty
128
+ return {
129
+ ...cityData,
130
+ buildings: [],
131
+ districts: [],
132
+ bounds: { minX: 0, maxX: 100, minZ: 0, maxZ: 100 },
133
+ metadata: {
134
+ ...cityData.metadata,
135
+ rootPath: normalizedPath,
136
+ },
137
+ };
138
+ }
139
+ // Calculate the bounds of the subdirectory content
140
+ const contentBounds = recalculateBounds(filteredBuildings, filteredDistricts);
141
+ let remappedBuildings;
142
+ let remappedDistricts;
143
+ let newBounds;
144
+ if (autoCenter) {
145
+ // Calculate offset to make subdirectory origin (0,0)
146
+ const offsetX = -contentBounds.minX;
147
+ const offsetZ = -contentBounds.minZ;
148
+ // Remap building coordinates relative to subdirectory origin
149
+ remappedBuildings = filteredBuildings.map(building => ({
150
+ ...building,
151
+ position: {
152
+ ...building.position,
153
+ x: building.position.x + offsetX,
154
+ z: building.position.z + offsetZ,
155
+ },
156
+ // Make path relative to subdirectory
157
+ path: building.path === normalizedPath
158
+ ? building.path.split('/').pop() || building.path
159
+ : building.path.substring(normalizedPath.length + 1),
160
+ }));
161
+ // Remap district coordinates relative to subdirectory origin
162
+ remappedDistricts = filteredDistricts.map(district => ({
163
+ ...district,
164
+ worldBounds: {
165
+ minX: district.worldBounds.minX + offsetX,
166
+ maxX: district.worldBounds.maxX + offsetX,
167
+ minZ: district.worldBounds.minZ + offsetZ,
168
+ maxZ: district.worldBounds.maxZ + offsetZ,
169
+ },
170
+ // Make path relative to subdirectory
171
+ path: district.path === normalizedPath
172
+ ? '' // The subdirectory itself becomes the root
173
+ : district.path.substring(normalizedPath.length + 1),
174
+ }));
175
+ // New bounds with origin at (0,0)
176
+ newBounds = {
177
+ minX: 0,
178
+ maxX: contentBounds.maxX - contentBounds.minX,
179
+ minZ: 0,
180
+ maxZ: contentBounds.maxZ - contentBounds.minZ,
181
+ };
182
+ }
183
+ else {
184
+ // Preserve original coordinates when autoCenter is disabled
185
+ remappedBuildings = filteredBuildings.map(building => ({
186
+ ...building,
187
+ // Make path relative to subdirectory
188
+ path: building.path === normalizedPath
189
+ ? building.path.split('/').pop() || building.path
190
+ : building.path.substring(normalizedPath.length + 1),
191
+ }));
192
+ remappedDistricts = filteredDistricts.map(district => ({
193
+ ...district,
194
+ // Make path relative to subdirectory
195
+ path: district.path === normalizedPath
196
+ ? '' // The subdirectory itself becomes the root
197
+ : district.path.substring(normalizedPath.length + 1),
198
+ }));
199
+ // Preserve original full city bounds to maintain spatial context
200
+ newBounds = cityData.bounds;
201
+ }
202
+ return {
203
+ ...cityData,
204
+ buildings: remappedBuildings,
205
+ districts: remappedDistricts,
206
+ bounds: newBounds,
207
+ metadata: {
208
+ ...cityData.metadata,
209
+ rootPath: normalizedPath,
210
+ totalFiles: filteredBuildings.length,
211
+ totalDirectories: filteredDistricts.length,
212
+ },
213
+ };
214
+ };
215
+ exports.filterCityDataForSubdirectory = filterCityDataForSubdirectory;
216
+ /**
217
+ * Filter city data based on multiple directory filters with include/exclude modes
218
+ */
219
+ const filterCityDataForMultipleDirectories = (cityData, filters, autoCenter = true, combineMode = 'union') => {
220
+ if (!filters || filters.length === 0)
221
+ return cityData;
222
+ // Normalize all filter paths
223
+ const normalizedFilters = filters.map(filter => ({
224
+ ...filter,
225
+ path: filter.path.replace(/^\/+|\/+$/g, ''),
226
+ }));
227
+ const includeFilters = normalizedFilters.filter(f => f.mode === 'include');
228
+ const excludeFilters = normalizedFilters.filter(f => f.mode === 'exclude');
229
+ // Helper function to check if a path matches a filter
230
+ const matchesFilter = (itemPath, filterPath) => {
231
+ const normalizedItemPath = itemPath.replace(/^\/+/, '');
232
+ return normalizedItemPath === filterPath || normalizedItemPath.startsWith(filterPath + '/');
233
+ };
234
+ // Filter buildings based on include/exclude rules
235
+ const filteredBuildings = cityData.buildings.filter(building => {
236
+ // Check excludes first (they take precedence)
237
+ for (const filter of excludeFilters) {
238
+ if (matchesFilter(building.path, filter.path)) {
239
+ return false;
240
+ }
241
+ }
242
+ // If we have includes, must match based on combine mode
243
+ if (includeFilters.length > 0) {
244
+ if (combineMode === 'union') {
245
+ // Union: match any include filter
246
+ return includeFilters.some(filter => matchesFilter(building.path, filter.path));
247
+ }
248
+ else {
249
+ // Intersection: must match all include filters (rare use case)
250
+ return includeFilters.every(filter => matchesFilter(building.path, filter.path));
251
+ }
252
+ }
253
+ // No includes means include everything (except excludes)
254
+ return true;
255
+ });
256
+ // Filter districts with the same logic
257
+ const filteredDistricts = cityData.districts.filter(district => {
258
+ // Check excludes first
259
+ for (const filter of excludeFilters) {
260
+ if (matchesFilter(district.path, filter.path)) {
261
+ return false;
262
+ }
263
+ }
264
+ // Check if district contains any included content
265
+ if (includeFilters.length > 0) {
266
+ if (combineMode === 'union') {
267
+ // Include district if it matches any filter or contains matching content
268
+ return includeFilters.some(filter => matchesFilter(district.path, filter.path) || matchesFilter(filter.path, district.path));
269
+ }
270
+ else {
271
+ // Intersection mode for districts is complex - simplify to union behavior
272
+ return includeFilters.some(filter => matchesFilter(district.path, filter.path) || matchesFilter(filter.path, district.path));
273
+ }
274
+ }
275
+ return true;
276
+ });
277
+ // If nothing matches, return empty city
278
+ if (filteredBuildings.length === 0 && filteredDistricts.length === 0) {
279
+ return {
280
+ ...cityData,
281
+ buildings: [],
282
+ districts: [],
283
+ bounds: { minX: 0, maxX: 100, minZ: 0, maxZ: 100 },
284
+ metadata: {
285
+ ...cityData.metadata,
286
+ rootPath: filters.map(f => `${f.mode}:${f.path}`).join(', '),
287
+ },
288
+ };
289
+ }
290
+ // Calculate bounds and optionally recenter
291
+ const contentBounds = recalculateBounds(filteredBuildings, filteredDistricts);
292
+ if (autoCenter) {
293
+ // Calculate offset to center the content
294
+ const offsetX = -contentBounds.minX;
295
+ const offsetZ = -contentBounds.minZ;
296
+ // Remap coordinates
297
+ const remappedBuildings = filteredBuildings.map(building => ({
298
+ ...building,
299
+ position: {
300
+ ...building.position,
301
+ x: building.position.x + offsetX,
302
+ z: building.position.z + offsetZ,
303
+ },
304
+ }));
305
+ const remappedDistricts = filteredDistricts.map(district => ({
306
+ ...district,
307
+ worldBounds: {
308
+ minX: district.worldBounds.minX + offsetX,
309
+ maxX: district.worldBounds.maxX + offsetX,
310
+ minZ: district.worldBounds.minZ + offsetZ,
311
+ maxZ: district.worldBounds.maxZ + offsetZ,
312
+ },
313
+ }));
314
+ return {
315
+ ...cityData,
316
+ buildings: remappedBuildings,
317
+ districts: remappedDistricts,
318
+ bounds: {
319
+ minX: 0,
320
+ maxX: contentBounds.maxX - contentBounds.minX,
321
+ minZ: 0,
322
+ maxZ: contentBounds.maxZ - contentBounds.minZ,
323
+ },
324
+ metadata: {
325
+ ...cityData.metadata,
326
+ rootPath: filters.map(f => `${f.mode}:${f.path}`).join(', '),
327
+ totalFiles: remappedBuildings.length,
328
+ totalDirectories: remappedDistricts.length,
329
+ },
330
+ };
331
+ }
332
+ else {
333
+ // Return filtered data with original coordinates and bounds
334
+ return {
335
+ ...cityData,
336
+ buildings: filteredBuildings,
337
+ districts: filteredDistricts,
338
+ bounds: cityData.bounds, // Preserve original bounds when autoCenter is false
339
+ metadata: {
340
+ ...cityData.metadata,
341
+ rootPath: filters.map(f => `${f.mode}:${f.path}`).join(', '),
342
+ totalFiles: filteredBuildings.length,
343
+ totalDirectories: filteredDistricts.length,
344
+ },
345
+ };
346
+ }
347
+ };
348
+ exports.filterCityDataForMultipleDirectories = filterCityDataForMultipleDirectories;
@@ -0,0 +1,63 @@
1
+ import React from 'react';
2
+ import { HighlightLayer } from '../render/client/drawLayeredBuildings';
3
+ import { CityData, CityBuilding, CityDistrict, SelectiveRenderOptions } from '@principal-ai/file-city-builder';
4
+ export interface ArchitectureMapHighlightLayersProps {
5
+ cityData?: CityData;
6
+ highlightLayers?: HighlightLayer[];
7
+ onLayerToggle?: (layerId: string, enabled: boolean) => void;
8
+ showLayerControls?: boolean;
9
+ defaultBuildingColor?: string;
10
+ focusDirectory?: string | null;
11
+ rootDirectoryName?: string;
12
+ onDirectorySelect?: (directory: string | null) => void;
13
+ onFileClick?: (path: string, type: 'file' | 'directory') => void;
14
+ enableZoom?: boolean;
15
+ fullSize?: boolean;
16
+ showGrid?: boolean;
17
+ showFileNames?: boolean;
18
+ className?: string;
19
+ selectiveRender?: SelectiveRenderOptions;
20
+ canvasBackgroundColor?: string;
21
+ hoverBorderColor?: string;
22
+ disableOpacityDimming?: boolean;
23
+ defaultDirectoryColor?: string;
24
+ subdirectoryMode?: {
25
+ enabled?: boolean;
26
+ rootPath?: string;
27
+ autoCenter?: boolean;
28
+ filters?: Array<{
29
+ path: string;
30
+ mode: 'include' | 'exclude';
31
+ }>;
32
+ combineMode?: 'union' | 'intersection';
33
+ } | null;
34
+ showFileTypeIcons?: boolean;
35
+ showDirectoryLabels?: boolean;
36
+ transform?: {
37
+ rotation?: 0 | 90 | 180 | 270;
38
+ flipHorizontal?: boolean;
39
+ flipVertical?: boolean;
40
+ };
41
+ onHover?: (info: {
42
+ hoveredDistrict: CityDistrict | null;
43
+ hoveredBuilding: CityBuilding | null;
44
+ mousePos: {
45
+ x: number;
46
+ y: number;
47
+ };
48
+ fileTooltip: {
49
+ text: string;
50
+ } | null;
51
+ directoryTooltip: {
52
+ text: string;
53
+ } | null;
54
+ fileCount: number | null;
55
+ }) => void;
56
+ buildingBorderRadius?: number;
57
+ districtBorderRadius?: number;
58
+ }
59
+ declare function ArchitectureMapHighlightLayersInner({ cityData, highlightLayers, onLayerToggle, focusDirectory, rootDirectoryName, onDirectorySelect, onFileClick, enableZoom, fullSize, showGrid, showFileNames, className, selectiveRender, canvasBackgroundColor, hoverBorderColor, disableOpacityDimming, defaultDirectoryColor, defaultBuildingColor, subdirectoryMode, showLayerControls, showFileTypeIcons, showDirectoryLabels, transform, // Default to no rotation
60
+ onHover, buildingBorderRadius, districtBorderRadius, }: ArchitectureMapHighlightLayersProps): React.JSX.Element;
61
+ export declare const ArchitectureMapHighlightLayers: typeof ArchitectureMapHighlightLayersInner;
62
+ export {};
63
+ //# sourceMappingURL=ArchitectureMapHighlightLayers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArchitectureMapHighlightLayers.d.ts","sourceRoot":"","sources":["../../src/components/ArchitectureMapHighlightLayers.tsx"],"names":[],"mappings":"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"}