@smartnet360/svelte-components 0.0.102 → 0.0.103

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 (65) 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 +4 -6
  6. package/dist/core/Charts/ChartCard.svelte +122 -12
  7. package/dist/core/Charts/ChartCard.svelte.d.ts +2 -0
  8. package/dist/core/Charts/ChartComponent.svelte +8 -6
  9. package/dist/core/CoverageMap/ai/AITools.d.ts +117 -0
  10. package/dist/core/CoverageMap/ai/AITools.js +380 -0
  11. package/dist/core/CoverageMap/core/CoverageCalculator.d.ts +138 -0
  12. package/dist/core/CoverageMap/core/CoverageCalculator.js +375 -0
  13. package/dist/core/CoverageMap/core/GridCalculator.d.ts +115 -0
  14. package/dist/core/CoverageMap/core/GridCalculator.js +484 -0
  15. package/dist/core/CoverageMap/core/PathLossModels.d.ts +253 -0
  16. package/dist/core/CoverageMap/core/PathLossModels.js +380 -0
  17. package/dist/core/CoverageMap/core/SignalProcessor.d.ts +288 -0
  18. package/dist/core/CoverageMap/core/SignalProcessor.js +424 -0
  19. package/dist/core/CoverageMap/data/AntennaStore.d.ts +165 -0
  20. package/dist/core/CoverageMap/data/AntennaStore.js +327 -0
  21. package/dist/core/CoverageMap/data/SiteStore.d.ts +155 -0
  22. package/dist/core/CoverageMap/data/SiteStore.js +355 -0
  23. package/dist/core/CoverageMap/index.d.ts +74 -0
  24. package/dist/core/CoverageMap/index.js +103 -0
  25. package/dist/core/CoverageMap/types.d.ts +252 -0
  26. package/dist/core/CoverageMap/types.js +7 -0
  27. package/dist/core/CoverageMap/utils/geoUtils.d.ts +223 -0
  28. package/dist/core/CoverageMap/utils/geoUtils.js +374 -0
  29. package/dist/core/CoverageMap/utils/rfUtils.d.ts +329 -0
  30. package/dist/core/CoverageMap/utils/rfUtils.js +434 -0
  31. package/dist/core/CoverageMap/visualization/ColorSchemes.d.ts +149 -0
  32. package/dist/core/CoverageMap/visualization/ColorSchemes.js +377 -0
  33. package/dist/core/TreeView/index.d.ts +4 -4
  34. package/dist/core/TreeView/index.js +5 -5
  35. package/dist/core/TreeView/tree-utils.d.ts +12 -0
  36. package/dist/core/TreeView/tree-utils.js +115 -6
  37. package/dist/core/TreeView/tree.store.svelte.d.ts +94 -0
  38. package/dist/core/TreeView/tree.store.svelte.js +274 -0
  39. package/dist/map-v2/features/cells/controls/CellFilterControl.svelte +16 -27
  40. package/dist/map-v2/features/repeaters/controls/RepeaterFilterControl.svelte +33 -42
  41. package/dist/map-v2/features/sites/controls/SiteFilterControl.svelte +12 -19
  42. package/dist/map-v3/core/components/Map.svelte +4 -0
  43. package/dist/map-v3/core/stores/map.store.svelte.js +2 -0
  44. package/dist/map-v3/features/cells/components/CellFilterControl.svelte +24 -30
  45. package/dist/map-v3/features/coverage/index.d.ts +12 -0
  46. package/dist/map-v3/features/coverage/index.js +16 -0
  47. package/dist/map-v3/features/coverage/layers/CoverageLayer.svelte +198 -0
  48. package/dist/map-v3/features/coverage/layers/CoverageLayer.svelte.d.ts +10 -0
  49. package/dist/map-v3/features/coverage/logic/coloring.d.ts +28 -0
  50. package/dist/map-v3/features/coverage/logic/coloring.js +77 -0
  51. package/dist/map-v3/features/coverage/logic/geometry.d.ts +33 -0
  52. package/dist/map-v3/features/coverage/logic/geometry.js +112 -0
  53. package/dist/map-v3/features/coverage/stores/coverage.data.svelte.d.ts +46 -0
  54. package/dist/map-v3/features/coverage/stores/coverage.data.svelte.js +95 -0
  55. package/dist/map-v3/features/coverage/stores/coverage.display.svelte.d.ts +33 -0
  56. package/dist/map-v3/features/coverage/stores/coverage.display.svelte.js +90 -0
  57. package/dist/map-v3/features/coverage/types.d.ts +52 -0
  58. package/dist/map-v3/features/coverage/types.js +7 -0
  59. package/dist/map-v3/features/repeaters/components/RepeaterFilterControl.svelte +14 -20
  60. package/dist/map-v3/features/sites/components/SiteFilterControl.svelte +23 -33
  61. package/dist/map-v3/index.d.ts +4 -0
  62. package/dist/map-v3/index.js +5 -0
  63. package/package.json +2 -2
  64. package/dist/core/TreeView/tree.store.d.ts +0 -10
  65. package/dist/core/TreeView/tree.store.js +0 -320
@@ -14,3 +14,4 @@ export * from './utils/db-utils';
14
14
  export * from './utils/init-db';
15
15
  export * from './utils/msi-parser';
16
16
  export * from './utils/plotly-chart-utils';
17
+ export * from './utils/load-static-antennas';
@@ -19,3 +19,4 @@ export * from './utils/db-utils';
19
19
  export * from './utils/init-db';
20
20
  export * from './utils/msi-parser';
21
21
  export * from './utils/plotly-chart-utils';
22
+ export * from './utils/load-static-antennas';
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Load antennas from static/antennas folder via fetch
3
+ * This is a helper for loading pre-bundled antenna files without user interaction
4
+ */
5
+ import type { Antenna } from '../db';
6
+ /**
7
+ * Load and parse all static antenna files
8
+ */
9
+ export declare function loadStaticAntennas(): Promise<Antenna[]>;
10
+ /**
11
+ * Load static antennas and save to database
12
+ */
13
+ export declare function importStaticAntennas(): Promise<{
14
+ success: boolean;
15
+ count: number;
16
+ error?: string;
17
+ }>;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Load antennas from static/antennas folder via fetch
3
+ * This is a helper for loading pre-bundled antenna files without user interaction
4
+ */
5
+ import { parseMSIFile } from './msi-parser';
6
+ import { saveAntennas } from './db-utils';
7
+ const STATIC_ANTENNA_FILES = [
8
+ 'ADU4515R17v06_0699_X_CO_M45_03T_Lr1.msi',
9
+ 'ADU4515R17v06_0699_X_CO_M45_04T_Lr1.msi',
10
+ 'ADU4515R17v06_0699_X_CO_M45_05T_Lr1.msi',
11
+ 'ADU4515R17v06_0699_X_CO_M45_06T_Lr1.msi',
12
+ 'ADU4515R17v06_0699_X_CO_M45_07T_Lr1.msi',
13
+ 'ADU4515R17v06_0699_X_CO_M45_08T_Lr1.msi',
14
+ 'ADU4515R17v06_0699_X_CO_M45_09T_Lr1.msi',
15
+ 'ADU4515R17v06_0699_X_CO_M45_10T_Lr1.msi',
16
+ 'ADU4515R17v06_0699_X_CO_M45_11T_Lr1.msi',
17
+ 'ADU4515R17v06_0699_X_CO_M45_12T_Lr1.msi'
18
+ ];
19
+ /**
20
+ * Load and parse all static antenna files
21
+ */
22
+ export async function loadStaticAntennas() {
23
+ const antennas = [];
24
+ console.log(`[loadStaticAntennas] Starting to load ${STATIC_ANTENNA_FILES.length} antenna files...`);
25
+ for (const filename of STATIC_ANTENNA_FILES) {
26
+ try {
27
+ // Fetch the file from static folder
28
+ const url = `/antennas/${filename}`;
29
+ console.log(`[loadStaticAntennas] Fetching: ${url}`);
30
+ const response = await fetch(url);
31
+ if (!response.ok) {
32
+ console.warn(`[loadStaticAntennas] Failed to fetch ${filename}: ${response.status} ${response.statusText}`);
33
+ continue;
34
+ }
35
+ // Convert to File object for parser
36
+ const blob = await response.blob();
37
+ const file = new File([blob], filename, { type: 'text/plain' });
38
+ console.log(`[loadStaticAntennas] Parsing ${filename}...`);
39
+ // Parse the MSI file
40
+ const antenna = await parseMSIFile(file);
41
+ antenna.sourcePath = `static/antennas/${filename}`;
42
+ antennas.push(antenna);
43
+ console.log(`[loadStaticAntennas] ✓ Loaded: ${antenna.name} (${antenna.frequency} MHz, tilt: ${antenna.tilt}°)`);
44
+ }
45
+ catch (error) {
46
+ console.error(`[loadStaticAntennas] Error parsing ${filename}:`, error);
47
+ }
48
+ }
49
+ console.log(`[loadStaticAntennas] Completed. Loaded ${antennas.length}/${STATIC_ANTENNA_FILES.length} antennas`);
50
+ return antennas;
51
+ }
52
+ /**
53
+ * Load static antennas and save to database
54
+ */
55
+ export async function importStaticAntennas() {
56
+ try {
57
+ console.log('[importStaticAntennas] Starting import process...');
58
+ const antennas = await loadStaticAntennas();
59
+ if (antennas.length === 0) {
60
+ console.error('[importStaticAntennas] No antennas were successfully loaded');
61
+ return {
62
+ success: false,
63
+ count: 0,
64
+ error: 'No antennas were successfully loaded'
65
+ };
66
+ }
67
+ console.log(`[importStaticAntennas] Saving ${antennas.length} antennas to database...`);
68
+ await saveAntennas(antennas);
69
+ console.log(`[importStaticAntennas] ✓ Successfully saved ${antennas.length} antennas to database`);
70
+ return {
71
+ success: true,
72
+ count: antennas.length
73
+ };
74
+ }
75
+ catch (error) {
76
+ console.error('[importStaticAntennas] Failed to import static antennas:', error);
77
+ return {
78
+ success: false,
79
+ count: 0,
80
+ error: error instanceof Error ? error.message : 'Unknown error'
81
+ };
82
+ }
83
+ }
@@ -93,12 +93,10 @@
93
93
  // Derive chart data from tree selection
94
94
  let filteredData = $derived.by(() => {
95
95
  if (!treeStore) return [];
96
- const storeValue = $treeStore;
97
- if (!storeValue) return [];
98
- const filtered = filterChartData(rawData, storeValue.state.checkedPaths);
96
+ const filtered = filterChartData(rawData, treeStore.state.checkedPaths);
99
97
  log('🔍 Filtered Data:', {
100
98
  totalRaw: rawData.length,
101
- checkedPaths: Array.from(storeValue.state.checkedPaths),
99
+ checkedPaths: Array.from(treeStore.state.checkedPaths),
102
100
  filteredCount: filtered.length,
103
101
  cells: Array.from(new Set(filtered.map(r => r.cellName)))
104
102
  });
@@ -210,7 +208,7 @@
210
208
  {colorDimension}
211
209
  {singleRootSelect}
212
210
  {singleLevel1Select}
213
- treeStore={$treeStore}
211
+ {treeStore}
214
212
  {showGroupingSelector}
215
213
  {onSearch}
216
214
  {searchPlaceholder}
@@ -223,7 +221,7 @@
223
221
  <!-- Tree View -->
224
222
  <div class="flex-grow-1" style="min-height: 0; overflow: hidden;">
225
223
  {#if treeStore}
226
- <TreeView store={$treeStore!} showControls={true} showIndeterminate={true} height="100%" />
224
+ <TreeView store={treeStore} showControls={true} showIndeterminate={true} height="100%" />
227
225
  {/if}
228
226
  </div>
229
227
  </div>
@@ -26,6 +26,8 @@
26
26
  runtimeShowMarkers?: boolean; // Runtime control for showing markers (default: true)
27
27
  runtimeShowLegend?: boolean; // Runtime control for showing legend (default: true)
28
28
  runtimeHoverMode?: HoverMode; // Runtime override for hover mode from global controls
29
+ renderDelay?: number; // Delay in ms before rendering (for staggered loading)
30
+ lazyRender?: boolean; // Enable Intersection Observer-based lazy rendering
29
31
  onchartcontextmenu?: (detail: {
30
32
  chart: ChartModel;
31
33
  sectionId?: string;
@@ -34,12 +36,13 @@
34
36
  }) => void;
35
37
  }
36
38
 
37
- let { chart, processedData, markers, plotlyLayout, enableAdaptation = true, sectionId, sectionMovingAverage, layoutMovingAverage, layoutHoverMode, layoutColoredHover = true, runtimeMAOverride, runtimeShowOriginal, runtimeShowMarkers = true, runtimeShowLegend = true, runtimeHoverMode, onchartcontextmenu }: Props = $props();
39
+ 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
40
 
39
41
  // Chart container div and state
40
42
  let chartDiv: HTMLElement;
41
43
  let containerSize = $state<ContainerSize>({ width: 0, height: 0 });
42
44
  let chartInitialized = $state(false); // Track if chart has been created
45
+ let isVisible = $state(!lazyRender); // For lazy rendering: start visible if not lazy
43
46
  let isHealthy = $state(checkHealth('charts'));
44
47
 
45
48
  function handleContextMenu(event: MouseEvent) {
@@ -270,11 +273,12 @@
270
273
  }
271
274
 
272
275
  onMount(() => {
273
-
274
276
  log('📈 ChartCard mounted', {
275
277
  chartTitle: chart.title,
276
278
  leftKPIs: chart.yLeft.length,
277
- rightKPIs: chart.yRight.length
279
+ rightKPIs: chart.yRight.length,
280
+ renderDelay,
281
+ lazyRender
278
282
  });
279
283
 
280
284
  // Initial container size measurement
@@ -282,17 +286,50 @@
282
286
  const rect = chartDiv.getBoundingClientRect();
283
287
  containerSize.width = rect.width;
284
288
  containerSize.height = rect.height;
285
-
286
- log('📐 Initial container size', {
287
- chartTitle: chart.title,
288
- width: rect.width,
289
- height: rect.height
290
- });
291
289
  }
292
- if(!isHealthy){
290
+
291
+ if (!isHealthy) {
293
292
  return;
294
293
  }
295
- renderChart();
294
+
295
+ // Intersection Observer for lazy rendering
296
+ let intersectionObserver: IntersectionObserver | null = null;
297
+
298
+ const doRender = () => {
299
+ if (renderDelay > 0) {
300
+ // Staggered rendering: delay based on chart index
301
+ setTimeout(() => {
302
+ renderChart();
303
+ }, renderDelay);
304
+ } else {
305
+ renderChart();
306
+ }
307
+ };
308
+
309
+ if (lazyRender && chartDiv) {
310
+ // Lazy rendering: only render when chart enters viewport
311
+ intersectionObserver = new IntersectionObserver(
312
+ (entries) => {
313
+ const [entry] = entries;
314
+ if (entry.isIntersecting && !chartInitialized) {
315
+ log('👁️ Chart entering viewport', { chartTitle: chart.title });
316
+ isVisible = true;
317
+ doRender();
318
+ // Disconnect after first render - chart stays rendered
319
+ intersectionObserver?.disconnect();
320
+ }
321
+ },
322
+ {
323
+ // Render 200px before entering viewport for smooth experience
324
+ rootMargin: '200px',
325
+ threshold: 0
326
+ }
327
+ );
328
+ intersectionObserver.observe(chartDiv);
329
+ } else {
330
+ // Immediate or staggered rendering (no lazy)
331
+ doRender();
332
+ }
296
333
 
297
334
  // Set up ResizeObserver with debouncing to prevent excessive re-renders
298
335
  if (chartDiv && window.ResizeObserver) {
@@ -330,12 +367,13 @@
330
367
 
331
368
  resizeObserver.observe(chartDiv);
332
369
 
333
- // Clean up observer on component destroy
370
+ // Clean up observers on component destroy
334
371
  return () => {
335
372
  if (resizeTimeout) {
336
373
  clearTimeout(resizeTimeout);
337
374
  }
338
375
  resizeObserver.disconnect();
376
+ intersectionObserver?.disconnect();
339
377
 
340
378
  // Clean up Plotly chart
341
379
  if (chartDiv && chartInitialized) {
@@ -344,6 +382,15 @@
344
382
  }
345
383
  };
346
384
  }
385
+
386
+ // If no ResizeObserver, still clean up intersection observer
387
+ return () => {
388
+ intersectionObserver?.disconnect();
389
+ if (chartDiv && chartInitialized) {
390
+ Plotly.purge(chartDiv);
391
+ chartInitialized = false;
392
+ }
393
+ };
347
394
  });
348
395
 
349
396
  // React to prop changes - debounce re-renders for better performance
@@ -368,9 +415,19 @@
368
415
  </script>
369
416
 
370
417
  <div class="chart-card" role="group" oncontextmenu={handleContextMenu}>
418
+ {#if !isVisible || !chartInitialized}
419
+ <!-- Loading placeholder for lazy/staggered rendering -->
420
+ <div class="chart-placeholder">
421
+ <div class="placeholder-content">
422
+ <div class="placeholder-spinner"></div>
423
+ <span class="placeholder-text">{chart.title}</span>
424
+ </div>
425
+ </div>
426
+ {/if}
371
427
  <div
372
428
  bind:this={chartDiv}
373
429
  class="chart-container"
430
+ class:hidden={!isVisible}
374
431
  ></div>
375
432
  </div>
376
433
 
@@ -387,6 +444,7 @@
387
444
  overflow: hidden; /* Prevent content overflow */
388
445
  box-sizing: border-box; /* Include padding in size calculations */
389
446
  contain: layout style paint; /* Browser optimization: isolate rendering from rest of page */
447
+ position: relative; /* For placeholder positioning */
390
448
  }
391
449
 
392
450
  .chart-card:hover {
@@ -402,4 +460,56 @@
402
460
  box-sizing: border-box; /* Include padding in size calculations */
403
461
  overflow: hidden; /* Prevent Plotly overflow */
404
462
  }
463
+
464
+ .chart-container.hidden {
465
+ visibility: hidden;
466
+ position: absolute;
467
+ }
468
+
469
+ /* Loading placeholder styles */
470
+ .chart-placeholder {
471
+ position: absolute;
472
+ top: 0;
473
+ left: 0;
474
+ right: 0;
475
+ bottom: 0;
476
+ display: flex;
477
+ align-items: center;
478
+ justify-content: center;
479
+ background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
480
+ z-index: 1;
481
+ }
482
+
483
+ .placeholder-content {
484
+ display: flex;
485
+ flex-direction: column;
486
+ align-items: center;
487
+ gap: 0.75rem;
488
+ color: #6c757d;
489
+ }
490
+
491
+ .placeholder-spinner {
492
+ width: 24px;
493
+ height: 24px;
494
+ border: 2px solid #dee2e6;
495
+ border-top-color: #007bff;
496
+ border-radius: 50%;
497
+ animation: spin 0.8s linear infinite;
498
+ }
499
+
500
+ .placeholder-text {
501
+ font-size: 0.75rem;
502
+ font-weight: 500;
503
+ text-align: center;
504
+ max-width: 80%;
505
+ overflow: hidden;
506
+ text-overflow: ellipsis;
507
+ white-space: nowrap;
508
+ }
509
+
510
+ @keyframes spin {
511
+ to {
512
+ transform: rotate(360deg);
513
+ }
514
+ }
405
515
  </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;
@@ -319,7 +319,7 @@
319
319
  </script>
320
320
 
321
321
  <!-- Reusable chart grid snippet -->
322
- {#snippet chartGrid(section: Section)}
322
+ {#snippet chartGrid(section: Section, enableLazyRender: boolean = false)}
323
323
  {@const gridConfig = getGridConfig(section.grid)}
324
324
  <div
325
325
  class="chart-grid"
@@ -327,7 +327,7 @@
327
327
  style:grid-template-columns={`repeat(${gridConfig.columns}, minmax(0, 1fr))`}
328
328
  style:grid-template-rows={`repeat(${gridConfig.rows}, minmax(0, 1fr))`}
329
329
  >
330
- {#each section.charts as chart}
330
+ {#each section.charts as chart, chartIndex}
331
331
  <div class="chart-slot">
332
332
  <ChartCard
333
333
  {chart}
@@ -344,6 +344,8 @@
344
344
  runtimeShowMarkers={globalControls.markers?.enabled}
345
345
  runtimeShowLegend={globalControls.legend?.enabled}
346
346
  runtimeHoverMode={globalControls.hoverMode?.mode}
347
+ renderDelay={chartIndex * 50}
348
+ lazyRender={enableLazyRender}
347
349
  onchartcontextmenu={(detail) => handleChartContextMenu(detail, section)}
348
350
  />
349
351
  </div>
@@ -395,8 +397,8 @@
395
397
  class="tab-section {section.id === activeTabId ? 'active' : 'hidden'}"
396
398
  data-section-id="{section.id}"
397
399
  >
398
- <!-- Chart Grid -->
399
- {@render chartGrid(section)}
400
+ <!-- Chart Grid - staggered rendering only, no lazy since tabs handle visibility -->
401
+ {@render chartGrid(section, false)}
400
402
  </div>
401
403
  {/each}
402
404
  </div>
@@ -427,8 +429,8 @@
427
429
  <div class="scrollspy-content" bind:this={scrollspyContent}>
428
430
  {#each layout.sections as section}
429
431
  <div class="section-content" id="{section.id}">
430
- <!-- Chart Grid -->
431
- {@render chartGrid(section)}
432
+ <!-- Chart Grid - lazy + staggered rendering for scrollspy -->
433
+ {@render chartGrid(section, true)}
432
434
  </div>
433
435
  {/each}
434
436
  </div>
@@ -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>;