@smartnet360/svelte-components 0.0.102 → 0.0.104

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 (85) hide show
  1. package/dist/apps/antenna-pattern/index.d.ts +1 -0
  2. package/dist/apps/antenna-pattern/index.js +1 -0
  3. package/dist/apps/antenna-pattern/utils/load-static-antennas.d.ts +17 -0
  4. package/dist/apps/antenna-pattern/utils/load-static-antennas.js +83 -0
  5. package/dist/apps/site-check/SiteCheck.svelte +13 -81
  6. package/dist/apps/site-check/SiteCheckControls.svelte +0 -7
  7. package/dist/apps/site-check/helper.js +0 -33
  8. package/dist/apps/site-check/transforms.js +15 -65
  9. package/dist/core/CellTable/CellTable.svelte +456 -0
  10. package/dist/core/CellTable/CellTable.svelte.d.ts +27 -0
  11. package/dist/core/CellTable/CellTablePanel.svelte +211 -0
  12. package/dist/core/CellTable/CellTablePanel.svelte.d.ts +49 -0
  13. package/dist/core/CellTable/CellTableToolbar.svelte +218 -0
  14. package/dist/core/CellTable/CellTableToolbar.svelte.d.ts +32 -0
  15. package/dist/core/CellTable/column-config.d.ts +63 -0
  16. package/dist/core/CellTable/column-config.js +465 -0
  17. package/dist/core/CellTable/index.d.ts +10 -0
  18. package/dist/core/CellTable/index.js +11 -0
  19. package/dist/core/CellTable/types.d.ts +166 -0
  20. package/dist/core/CellTable/types.js +6 -0
  21. package/dist/core/Charts/ChartCard.svelte +118 -31
  22. package/dist/core/Charts/ChartCard.svelte.d.ts +2 -0
  23. package/dist/core/Charts/ChartComponent.svelte +8 -31
  24. package/dist/core/Charts/data-processor.js +1 -19
  25. package/dist/core/CoverageMap/ai/AITools.d.ts +117 -0
  26. package/dist/core/CoverageMap/ai/AITools.js +380 -0
  27. package/dist/core/CoverageMap/core/CoverageCalculator.d.ts +138 -0
  28. package/dist/core/CoverageMap/core/CoverageCalculator.js +375 -0
  29. package/dist/core/CoverageMap/core/GridCalculator.d.ts +115 -0
  30. package/dist/core/CoverageMap/core/GridCalculator.js +484 -0
  31. package/dist/core/CoverageMap/core/PathLossModels.d.ts +253 -0
  32. package/dist/core/CoverageMap/core/PathLossModels.js +380 -0
  33. package/dist/core/CoverageMap/core/SignalProcessor.d.ts +288 -0
  34. package/dist/core/CoverageMap/core/SignalProcessor.js +424 -0
  35. package/dist/core/CoverageMap/data/AntennaStore.d.ts +165 -0
  36. package/dist/core/CoverageMap/data/AntennaStore.js +327 -0
  37. package/dist/core/CoverageMap/data/SiteStore.d.ts +155 -0
  38. package/dist/core/CoverageMap/data/SiteStore.js +355 -0
  39. package/dist/core/CoverageMap/index.d.ts +74 -0
  40. package/dist/core/CoverageMap/index.js +103 -0
  41. package/dist/core/CoverageMap/types.d.ts +252 -0
  42. package/dist/core/CoverageMap/types.js +7 -0
  43. package/dist/core/CoverageMap/utils/geoUtils.d.ts +223 -0
  44. package/dist/core/CoverageMap/utils/geoUtils.js +374 -0
  45. package/dist/core/CoverageMap/utils/rfUtils.d.ts +329 -0
  46. package/dist/core/CoverageMap/utils/rfUtils.js +434 -0
  47. package/dist/core/CoverageMap/visualization/ColorSchemes.d.ts +149 -0
  48. package/dist/core/CoverageMap/visualization/ColorSchemes.js +377 -0
  49. package/dist/core/TreeView/index.d.ts +4 -4
  50. package/dist/core/TreeView/index.js +5 -5
  51. package/dist/core/TreeView/tree-utils.d.ts +12 -0
  52. package/dist/core/TreeView/tree-utils.js +115 -6
  53. package/dist/core/TreeView/tree.store.svelte.d.ts +94 -0
  54. package/dist/core/TreeView/tree.store.svelte.js +274 -0
  55. package/dist/core/index.d.ts +1 -0
  56. package/dist/core/index.js +2 -0
  57. package/dist/map-v2/features/cells/controls/CellFilterControl.svelte +16 -27
  58. package/dist/map-v2/features/repeaters/controls/RepeaterFilterControl.svelte +33 -42
  59. package/dist/map-v2/features/sites/controls/SiteFilterControl.svelte +12 -19
  60. package/dist/map-v3/core/components/Map.svelte +4 -0
  61. package/dist/map-v3/core/stores/map.store.svelte.js +2 -0
  62. package/dist/map-v3/features/cells/components/CellFilterControl.svelte +24 -30
  63. package/dist/map-v3/features/coverage/index.d.ts +12 -0
  64. package/dist/map-v3/features/coverage/index.js +16 -0
  65. package/dist/map-v3/features/coverage/layers/CoverageLayer.svelte +198 -0
  66. package/dist/map-v3/features/coverage/layers/CoverageLayer.svelte.d.ts +10 -0
  67. package/dist/map-v3/features/coverage/logic/coloring.d.ts +28 -0
  68. package/dist/map-v3/features/coverage/logic/coloring.js +77 -0
  69. package/dist/map-v3/features/coverage/logic/geometry.d.ts +33 -0
  70. package/dist/map-v3/features/coverage/logic/geometry.js +112 -0
  71. package/dist/map-v3/features/coverage/stores/coverage.data.svelte.d.ts +46 -0
  72. package/dist/map-v3/features/coverage/stores/coverage.data.svelte.js +95 -0
  73. package/dist/map-v3/features/coverage/stores/coverage.display.svelte.d.ts +33 -0
  74. package/dist/map-v3/features/coverage/stores/coverage.display.svelte.js +90 -0
  75. package/dist/map-v3/features/coverage/types.d.ts +52 -0
  76. package/dist/map-v3/features/coverage/types.js +7 -0
  77. package/dist/map-v3/features/repeaters/components/RepeaterFilterControl.svelte +14 -20
  78. package/dist/map-v3/features/sites/components/SiteFilterControl.svelte +23 -33
  79. package/dist/map-v3/index.d.ts +4 -0
  80. package/dist/map-v3/index.js +5 -0
  81. package/package.json +4 -3
  82. package/dist/apps/site-check/transforms-old.d.ts +0 -56
  83. package/dist/apps/site-check/transforms-old.js +0 -273
  84. package/dist/core/TreeView/tree.store.d.ts +0 -10
  85. package/dist/core/TreeView/tree.store.js +0 -320
@@ -7,7 +7,6 @@
7
7
  import { createTimeSeriesTraceWithMA, getYAxisTitle, createDefaultPlotlyLayout } from './data-utils.js';
8
8
  import { adaptPlotlyLayout, addMarkersToLayout, type ContainerSize } from './adapt.js';
9
9
  import { getKPIValues, type ProcessedChartData } from './data-processor.js';
10
- import { log } from '../logger';
11
10
  import { checkHealth, getMessage } from '../FeatureRegistry';
12
11
 
13
12
  interface Props {
@@ -26,6 +25,8 @@
26
25
  runtimeShowMarkers?: boolean; // Runtime control for showing markers (default: true)
27
26
  runtimeShowLegend?: boolean; // Runtime control for showing legend (default: true)
28
27
  runtimeHoverMode?: HoverMode; // Runtime override for hover mode from global controls
28
+ renderDelay?: number; // Delay in ms before rendering (for staggered loading)
29
+ lazyRender?: boolean; // Enable Intersection Observer-based lazy rendering
29
30
  onchartcontextmenu?: (detail: {
30
31
  chart: ChartModel;
31
32
  sectionId?: string;
@@ -34,12 +35,13 @@
34
35
  }) => void;
35
36
  }
36
37
 
37
- let { chart, processedData, markers, plotlyLayout, enableAdaptation = true, sectionId, sectionMovingAverage, layoutMovingAverage, layoutHoverMode, layoutColoredHover = true, runtimeMAOverride, runtimeShowOriginal, runtimeShowMarkers = true, runtimeShowLegend = true, runtimeHoverMode, onchartcontextmenu }: Props = $props();
38
+ let { chart, processedData, markers, plotlyLayout, enableAdaptation = true, sectionId, sectionMovingAverage, layoutMovingAverage, layoutHoverMode, layoutColoredHover = true, runtimeMAOverride, runtimeShowOriginal, runtimeShowMarkers = true, runtimeShowLegend = true, runtimeHoverMode, renderDelay = 0, lazyRender = false, onchartcontextmenu }: Props = $props();
38
39
 
39
40
  // Chart container div and state
40
41
  let chartDiv: HTMLElement;
41
42
  let containerSize = $state<ContainerSize>({ width: 0, height: 0 });
42
43
  let chartInitialized = $state(false); // Track if chart has been created
44
+ let isVisible = $state(!lazyRender); // For lazy rendering: start visible if not lazy
43
45
  let isHealthy = $state(checkHealth('charts'));
44
46
 
45
47
  function handleContextMenu(event: MouseEvent) {
@@ -241,22 +243,9 @@
241
243
  // Use Plotly.react() for updates (preserves zoom/pan) or newPlot for initial render
242
244
  if (chartInitialized) {
243
245
  // Update existing chart - much faster, preserves user interactions
244
- log('🔄 Updating chart with Plotly.react', {
245
- chartTitle: chart.title,
246
- hoverMode: effectiveHoverMode,
247
- layoutHoverMode: finalLayout.hovermode
248
- });
249
246
  Plotly.react(chartDiv, traces, finalLayout, config);
250
247
  } else {
251
248
  // Initial chart creation
252
- log('📊 Creating new chart with Plotly.newPlot', {
253
- chartTitle: chart.title,
254
- traces: traces.length,
255
- leftKPIs: chart.yLeft.length,
256
- rightKPIs: chart.yRight.length,
257
- hoverMode: effectiveHoverMode,
258
- layoutHoverMode: finalLayout.hovermode
259
- });
260
249
  Plotly.newPlot(chartDiv, traces, finalLayout, config);
261
250
  chartInitialized = true;
262
251
  }
@@ -270,29 +259,54 @@
270
259
  }
271
260
 
272
261
  onMount(() => {
273
-
274
- log('📈 ChartCard mounted', {
275
- chartTitle: chart.title,
276
- leftKPIs: chart.yLeft.length,
277
- rightKPIs: chart.yRight.length
278
- });
279
-
280
262
  // Initial container size measurement
281
263
  if (chartDiv) {
282
264
  const rect = chartDiv.getBoundingClientRect();
283
265
  containerSize.width = rect.width;
284
266
  containerSize.height = rect.height;
285
-
286
- log('📐 Initial container size', {
287
- chartTitle: chart.title,
288
- width: rect.width,
289
- height: rect.height
290
- });
291
267
  }
292
- if(!isHealthy){
268
+
269
+ if (!isHealthy) {
293
270
  return;
294
271
  }
295
- renderChart();
272
+
273
+ // Intersection Observer for lazy rendering
274
+ let intersectionObserver: IntersectionObserver | null = null;
275
+
276
+ const doRender = () => {
277
+ if (renderDelay > 0) {
278
+ // Staggered rendering: delay based on chart index
279
+ setTimeout(() => {
280
+ renderChart();
281
+ }, renderDelay);
282
+ } else {
283
+ renderChart();
284
+ }
285
+ };
286
+
287
+ if (lazyRender && chartDiv) {
288
+ // Lazy rendering: only render when chart enters viewport
289
+ intersectionObserver = new IntersectionObserver(
290
+ (entries) => {
291
+ const [entry] = entries;
292
+ if (entry.isIntersecting && !chartInitialized) {
293
+ isVisible = true;
294
+ doRender();
295
+ // Disconnect after first render - chart stays rendered
296
+ intersectionObserver?.disconnect();
297
+ }
298
+ },
299
+ {
300
+ // Render 200px before entering viewport for smooth experience
301
+ rootMargin: '200px',
302
+ threshold: 0
303
+ }
304
+ );
305
+ intersectionObserver.observe(chartDiv);
306
+ } else {
307
+ // Immediate or staggered rendering (no lazy)
308
+ doRender();
309
+ }
296
310
 
297
311
  // Set up ResizeObserver with debouncing to prevent excessive re-renders
298
312
  if (chartDiv && window.ResizeObserver) {
@@ -330,12 +344,13 @@
330
344
 
331
345
  resizeObserver.observe(chartDiv);
332
346
 
333
- // Clean up observer on component destroy
347
+ // Clean up observers on component destroy
334
348
  return () => {
335
349
  if (resizeTimeout) {
336
350
  clearTimeout(resizeTimeout);
337
351
  }
338
352
  resizeObserver.disconnect();
353
+ intersectionObserver?.disconnect();
339
354
 
340
355
  // Clean up Plotly chart
341
356
  if (chartDiv && chartInitialized) {
@@ -344,6 +359,15 @@
344
359
  }
345
360
  };
346
361
  }
362
+
363
+ // If no ResizeObserver, still clean up intersection observer
364
+ return () => {
365
+ intersectionObserver?.disconnect();
366
+ if (chartDiv && chartInitialized) {
367
+ Plotly.purge(chartDiv);
368
+ chartInitialized = false;
369
+ }
370
+ };
347
371
  });
348
372
 
349
373
  // React to prop changes - debounce re-renders for better performance
@@ -368,9 +392,19 @@
368
392
  </script>
369
393
 
370
394
  <div class="chart-card" role="group" oncontextmenu={handleContextMenu}>
395
+ {#if !isVisible || !chartInitialized}
396
+ <!-- Loading placeholder for lazy/staggered rendering -->
397
+ <div class="chart-placeholder">
398
+ <div class="placeholder-content">
399
+ <div class="placeholder-spinner"></div>
400
+ <span class="placeholder-text">{chart.title}</span>
401
+ </div>
402
+ </div>
403
+ {/if}
371
404
  <div
372
405
  bind:this={chartDiv}
373
406
  class="chart-container"
407
+ class:hidden={!isVisible}
374
408
  ></div>
375
409
  </div>
376
410
 
@@ -387,6 +421,7 @@
387
421
  overflow: hidden; /* Prevent content overflow */
388
422
  box-sizing: border-box; /* Include padding in size calculations */
389
423
  contain: layout style paint; /* Browser optimization: isolate rendering from rest of page */
424
+ position: relative; /* For placeholder positioning */
390
425
  }
391
426
 
392
427
  .chart-card:hover {
@@ -402,4 +437,56 @@
402
437
  box-sizing: border-box; /* Include padding in size calculations */
403
438
  overflow: hidden; /* Prevent Plotly overflow */
404
439
  }
440
+
441
+ .chart-container.hidden {
442
+ visibility: hidden;
443
+ position: absolute;
444
+ }
445
+
446
+ /* Loading placeholder styles */
447
+ .chart-placeholder {
448
+ position: absolute;
449
+ top: 0;
450
+ left: 0;
451
+ right: 0;
452
+ bottom: 0;
453
+ display: flex;
454
+ align-items: center;
455
+ justify-content: center;
456
+ background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
457
+ z-index: 1;
458
+ }
459
+
460
+ .placeholder-content {
461
+ display: flex;
462
+ flex-direction: column;
463
+ align-items: center;
464
+ gap: 0.75rem;
465
+ color: #6c757d;
466
+ }
467
+
468
+ .placeholder-spinner {
469
+ width: 24px;
470
+ height: 24px;
471
+ border: 2px solid #dee2e6;
472
+ border-top-color: #007bff;
473
+ border-radius: 50%;
474
+ animation: spin 0.8s linear infinite;
475
+ }
476
+
477
+ .placeholder-text {
478
+ font-size: 0.75rem;
479
+ font-weight: 500;
480
+ text-align: center;
481
+ max-width: 80%;
482
+ overflow: hidden;
483
+ text-overflow: ellipsis;
484
+ white-space: nowrap;
485
+ }
486
+
487
+ @keyframes spin {
488
+ to {
489
+ transform: rotate(360deg);
490
+ }
491
+ }
405
492
  </style>
@@ -16,6 +16,8 @@ interface Props {
16
16
  runtimeShowMarkers?: boolean;
17
17
  runtimeShowLegend?: boolean;
18
18
  runtimeHoverMode?: HoverMode;
19
+ renderDelay?: number;
20
+ lazyRender?: boolean;
19
21
  onchartcontextmenu?: (detail: {
20
22
  chart: ChartModel;
21
23
  sectionId?: string;
@@ -6,7 +6,6 @@
6
6
  import ChartCard from './ChartCard.svelte';
7
7
  import GlobalControls from './GlobalControls.svelte';
8
8
  import { getPreprocessedData, type ProcessedChartData } from './data-processor.js';
9
- import { log } from '../logger';
10
9
  import { checkHealth, getMessage } from '../FeatureRegistry';
11
10
 
12
11
  interface Props {
@@ -58,18 +57,6 @@
58
57
 
59
58
  let { layout, data, mode, markers, plotlyLayout, enableAdaptation = true, showGlobalControls = true, persistSettings = false }: Props = $props();
60
59
  let isHealthy = $state(checkHealth('charts'));
61
- // Log component initialization
62
- $effect(() => {
63
- log('📊 ChartComponent initialized', {
64
- mode,
65
- dataRows: data.length,
66
- sections: layout.sections.length,
67
- totalCharts: layout.sections.reduce((sum, s) => sum + s.charts.length, 0),
68
- enableAdaptation,
69
- showGlobalControls,
70
- layoutHoverMode: layout.hoverMode
71
- });
72
- });
73
60
 
74
61
  // Preprocess raw data once - automatically memoized by Svelte's $derived
75
62
  // This extracts all KPI values and timestamps, cached until data or layout changes
@@ -98,13 +85,6 @@
98
85
 
99
86
  // Handler for global controls updates
100
87
  function handleControlsUpdate(updatedControls: GlobalChartControls) {
101
- log('🎛️ Global controls updated', {
102
- movingAverageEnabled: updatedControls.movingAverage?.enabled,
103
- windowOverride: updatedControls.movingAverage?.windowOverride,
104
- markersEnabled: updatedControls.markers?.enabled,
105
- legendEnabled: updatedControls.legend?.enabled,
106
- hoverMode: updatedControls.hoverMode?.mode
107
- });
108
88
  globalControls = updatedControls;
109
89
  }
110
90
 
@@ -195,17 +175,12 @@
195
175
 
196
176
  function zoomSelectedChart() {
197
177
  if (contextMenu.chart && contextMenu.section) {
198
- log('🔍 Zooming chart', {
199
- chartTitle: contextMenu.chart.title,
200
- sectionId: contextMenu.section.id
201
- });
202
178
  zoomedChart = { chart: contextMenu.chart, section: contextMenu.section };
203
179
  }
204
180
  closeContextMenu();
205
181
  }
206
182
 
207
183
  function exitZoom() {
208
- log('🔍 Exiting zoom mode');
209
184
  zoomedChart = null;
210
185
  closeContextMenu();
211
186
  }
@@ -319,7 +294,7 @@
319
294
  </script>
320
295
 
321
296
  <!-- Reusable chart grid snippet -->
322
- {#snippet chartGrid(section: Section)}
297
+ {#snippet chartGrid(section: Section, enableLazyRender: boolean = false)}
323
298
  {@const gridConfig = getGridConfig(section.grid)}
324
299
  <div
325
300
  class="chart-grid"
@@ -327,7 +302,7 @@
327
302
  style:grid-template-columns={`repeat(${gridConfig.columns}, minmax(0, 1fr))`}
328
303
  style:grid-template-rows={`repeat(${gridConfig.rows}, minmax(0, 1fr))`}
329
304
  >
330
- {#each section.charts as chart}
305
+ {#each section.charts as chart, chartIndex}
331
306
  <div class="chart-slot">
332
307
  <ChartCard
333
308
  {chart}
@@ -344,6 +319,8 @@
344
319
  runtimeShowMarkers={globalControls.markers?.enabled}
345
320
  runtimeShowLegend={globalControls.legend?.enabled}
346
321
  runtimeHoverMode={globalControls.hoverMode?.mode}
322
+ renderDelay={chartIndex * 50}
323
+ lazyRender={enableLazyRender}
347
324
  onchartcontextmenu={(detail) => handleChartContextMenu(detail, section)}
348
325
  />
349
326
  </div>
@@ -395,8 +372,8 @@
395
372
  class="tab-section {section.id === activeTabId ? 'active' : 'hidden'}"
396
373
  data-section-id="{section.id}"
397
374
  >
398
- <!-- Chart Grid -->
399
- {@render chartGrid(section)}
375
+ <!-- Chart Grid - staggered rendering only, no lazy since tabs handle visibility -->
376
+ {@render chartGrid(section, false)}
400
377
  </div>
401
378
  {/each}
402
379
  </div>
@@ -427,8 +404,8 @@
427
404
  <div class="scrollspy-content" bind:this={scrollspyContent}>
428
405
  {#each layout.sections as section}
429
406
  <div class="section-content" id="{section.id}">
430
- <!-- Chart Grid -->
431
- {@render chartGrid(section)}
407
+ <!-- Chart Grid - lazy + staggered rendering for scrollspy -->
408
+ {@render chartGrid(section, true)}
432
409
  </div>
433
410
  {/each}
434
411
  </div>
@@ -1,4 +1,3 @@
1
- import { log } from '../logger';
2
1
  /**
3
2
  * Extract all unique KPI rawNames from a layout configuration
4
3
  * This determines which columns we need to extract from raw data
@@ -17,10 +16,6 @@ export function extractKPINames(layout) {
17
16
  }
18
17
  }
19
18
  }
20
- log('📋 KPI names extracted', {
21
- totalKPIs: kpiNames.size,
22
- kpiNames: Array.from(kpiNames)
23
- });
24
19
  return kpiNames;
25
20
  }
26
21
  /**
@@ -33,11 +28,6 @@ export function extractKPINames(layout) {
33
28
  * @returns Preprocessed data ready for chart rendering
34
29
  */
35
30
  export function preprocessChartData(data, layout, timestampField = 'TIMESTAMP') {
36
- log('🔄 Preprocessing chart data', {
37
- rawDataRows: data.length,
38
- sections: layout.sections.length,
39
- timestampField
40
- });
41
31
  // Extract all unique KPI names we need to process
42
32
  const kpiNames = extractKPINames(layout);
43
33
  // Initialize the result map
@@ -53,17 +43,11 @@ export function preprocessChartData(data, layout, timestampField = 'TIMESTAMP')
53
43
  .filter(val => !isNaN(val)); // Remove invalid values
54
44
  kpiValues.set(kpiName, values);
55
45
  if (values.length === 0) {
56
- log('⚠️ No valid values found for KPI', { kpiName });
46
+ console.warn(`[Charts] No valid values found for KPI: ${kpiName}`);
57
47
  }
58
48
  }
59
49
  // Extract timestamps once
60
50
  const timestamps = data.map(row => row[timestampField]);
61
- log('✅ Data preprocessing complete', {
62
- processedKPIs: kpiValues.size,
63
- timestampCount: timestamps.length,
64
- sampleKPI: kpiValues.keys().next().value,
65
- sampleValues: kpiValues.values().next().value?.slice(0, 3)
66
- });
67
51
  return {
68
52
  kpiValues,
69
53
  timestamps,
@@ -91,11 +75,9 @@ export function getPreprocessedData(data, layout, timestampField = 'TIMESTAMP')
91
75
  if (cached) {
92
76
  // Verify cache is still valid (data reference matches)
93
77
  if (cached._rawDataRef === data) {
94
- log('💾 Using cached preprocessed data');
95
78
  return cached;
96
79
  }
97
80
  }
98
- log('🔄 Cache miss - preprocessing data');
99
81
  // Cache miss or invalid - compute and cache
100
82
  const processed = preprocessChartData(data, layout, timestampField);
101
83
  preprocessCache.set(data, processed);
@@ -0,0 +1,117 @@
1
+ /**
2
+ * AI Integration Layer - Tool-Callable Functions
3
+ *
4
+ * This module provides functions designed to be called by AI assistants
5
+ * (e.g., ChatGPT) for coverage analysis and recommendations.
6
+ *
7
+ * Design principles:
8
+ * - Functions are stateless and pure where possible
9
+ * - Inputs and outputs are JSON-serializable
10
+ * - Each function has clear purpose and documentation
11
+ * - Error handling returns structured error objects
12
+ *
13
+ * Phase 2 Implementation Note:
14
+ * These functions will be exposed via a tool registry that ChatGPT
15
+ * can call through function calling / tool use APIs.
16
+ */
17
+ import type { CoverageResult, AIRecommendation, AIToolFunction } from '../types';
18
+ /**
19
+ * Analyze coverage quality and generate recommendations
20
+ *
21
+ * This function takes coverage calculation results and generates
22
+ * structured analysis suitable for AI interpretation.
23
+ *
24
+ * In Phase 2, ChatGPT will call this with coverage data and receive
25
+ * structured metrics that it can analyze and explain in natural language.
26
+ *
27
+ * @param result - Coverage calculation result
28
+ * @returns Structured analysis data
29
+ *
30
+ * @example
31
+ * // AI will call:
32
+ * const analysis = analyzeCoverageQuality(coverageResult);
33
+ *
34
+ * // AI receives:
35
+ * {
36
+ * overallQuality: "good",
37
+ * coveragePercent: 78.5,
38
+ * avgSignal: -82.3,
39
+ * issues: ["excessive_range", "weak_avg_signal"],
40
+ * metrics: { ... }
41
+ * }
42
+ *
43
+ * // AI interprets and responds:
44
+ * "Your coverage is good overall at 78.5%. However, I notice two issues:
45
+ * 1. Excessive range detected - consider adding downtilt to reduce interference
46
+ * 2. Average signal is weak at -82.3 dBm - most users will experience medium throughput"
47
+ */
48
+ export declare function analyzeCoverageQuality(result: CoverageResult): {
49
+ overallQuality: 'excellent' | 'good' | 'fair' | 'poor';
50
+ coveragePercent: number;
51
+ avgSignal: number;
52
+ maxRange: number;
53
+ issues: string[];
54
+ metrics: Record<string, number>;
55
+ sectorBreakdown: any[];
56
+ };
57
+ /**
58
+ * Generate optimization suggestions
59
+ *
60
+ * Based on coverage analysis, generates specific parameter adjustment
61
+ * recommendations that can be presented to the user.
62
+ *
63
+ * In Phase 2, AI will use this to generate specific, actionable recommendations.
64
+ *
65
+ * @param result - Coverage result
66
+ * @returns Array of recommendations
67
+ */
68
+ export declare function generateOptimizationSuggestions(result: CoverageResult): AIRecommendation[];
69
+ /**
70
+ * Compare two coverage scenarios
71
+ *
72
+ * Useful for before/after analysis when user changes parameters.
73
+ *
74
+ * @param before - Coverage before changes
75
+ * @param after - Coverage after changes
76
+ * @returns Comparison analysis
77
+ */
78
+ export declare function compareCoverageScenarios(before: CoverageResult, after: CoverageResult): {
79
+ coverageChange: number;
80
+ signalChange: number;
81
+ rangeChange: number;
82
+ improvements: string[];
83
+ degradations: string[];
84
+ summary: string;
85
+ };
86
+ /**
87
+ * Extract key metrics for AI analysis
88
+ *
89
+ * Flattens coverage result into simple key-value pairs
90
+ * that are easy for AI to interpret.
91
+ *
92
+ * @param result - Coverage result
93
+ * @returns Flat metrics object
94
+ */
95
+ export declare function extractAIMetrics(result: CoverageResult): Record<string, number | string>;
96
+ /**
97
+ * Registry of all AI-callable tools
98
+ *
99
+ * In Phase 2, this will be used to expose functions to ChatGPT.
100
+ * Each entry describes the function, its parameters, and its purpose.
101
+ */
102
+ export declare const AI_TOOLS: AIToolFunction[];
103
+ /**
104
+ * Get AI tool by name
105
+ *
106
+ * @param name - Tool name
107
+ * @returns Tool function or undefined
108
+ */
109
+ export declare function getAITool(name: string): AIToolFunction | undefined;
110
+ /**
111
+ * Execute AI tool by name
112
+ *
113
+ * @param name - Tool name
114
+ * @param params - Tool parameters
115
+ * @returns Tool result
116
+ */
117
+ export declare function executeAITool(name: string, params: any): Promise<any>;