@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
@@ -0,0 +1,375 @@
1
+ /**
2
+ * Coverage Calculator - Main Orchestrator
3
+ *
4
+ * This is the main entry point for coverage calculations.
5
+ * It orchestrates all components and provides a clean API for:
6
+ * - Single sector coverage calculation
7
+ * - Multi-sector site coverage
8
+ * - Progress reporting
9
+ * - AI-ready result formatting
10
+ *
11
+ * Usage:
12
+ * const calculator = new CoverageCalculator();
13
+ * const result = await calculator.calculate(config, progressCallback);
14
+ * // Result includes grid, statistics, and AI-ready summary
15
+ */
16
+ import { calculateSingleSectorCoverage, calculateMultiSectorCoverage, extractMetrics } from './GridCalculator';
17
+ // ============================================================================
18
+ // COVERAGE CALCULATOR CLASS
19
+ // ============================================================================
20
+ /**
21
+ * Main Coverage Calculator
22
+ *
23
+ * Provides high-level API for coverage calculations with:
24
+ * - Configuration validation
25
+ * - Progress reporting
26
+ * - Error handling
27
+ * - Result formatting
28
+ * - AI-ready summaries
29
+ */
30
+ export class CoverageCalculator {
31
+ /**
32
+ * Calculate coverage for a site configuration
33
+ *
34
+ * This is the main calculation method. It:
35
+ * 1. Validates configuration
36
+ * 2. Determines if single or multi-sector
37
+ * 3. Performs calculation
38
+ * 4. Generates statistics and summary
39
+ * 5. Formats result for consumption (including AI)
40
+ *
41
+ * @param config - Complete coverage configuration
42
+ * @param onProgress - Optional progress callback
43
+ * @returns Promise resolving to complete coverage result
44
+ *
45
+ * @example
46
+ * const calculator = new CoverageCalculator();
47
+ * const result = await calculator.calculate({
48
+ * site: siteConfig,
49
+ * gridSettings: { cellSizeMeters: 50, maxRadiusKm: 10, ... },
50
+ * signalThresholds: { excellent: -70, good: -85, ... },
51
+ * calculateInterference: true
52
+ * }, (progress) => {
53
+ * console.log(`Progress: ${progress.progress}% - ${progress.message}`);
54
+ * });
55
+ *
56
+ * // Access results
57
+ * console.log(`Coverage: ${result.grid.stats.coveragePercentage}%`);
58
+ * console.log(`Summary: ${result.summary.description}`);
59
+ * // Pass to AI for analysis
60
+ * const aiAnalysis = await analyzeWithAI(result);
61
+ */
62
+ async calculate(config, onProgress) {
63
+ const startTime = Date.now();
64
+ // Validate configuration
65
+ this.validateConfiguration(config);
66
+ // Determine calculation type
67
+ const enabledSectors = config.site.sectors.filter((s) => s.enabled);
68
+ let grid;
69
+ if (enabledSectors.length === 0) {
70
+ throw new Error('No enabled sectors in configuration');
71
+ }
72
+ else if (enabledSectors.length === 1) {
73
+ // Single sector calculation
74
+ onProgress?.({
75
+ stage: 'initializing',
76
+ progress: 0,
77
+ message: 'Starting single sector calculation...'
78
+ });
79
+ grid = calculateSingleSectorCoverage(enabledSectors[0], config.gridSettings, config.signalThresholds, onProgress);
80
+ }
81
+ else {
82
+ // Multi-sector calculation
83
+ onProgress?.({
84
+ stage: 'initializing',
85
+ progress: 0,
86
+ message: `Starting ${enabledSectors.length} sector calculation...`
87
+ });
88
+ grid = calculateMultiSectorCoverage(enabledSectors, config.gridSettings, config.signalThresholds, onProgress);
89
+ }
90
+ // Calculate total time
91
+ const calculationTimeMs = Date.now() - startTime;
92
+ // Generate AI-ready summary
93
+ const summary = this.generateSummary(config, grid, enabledSectors.length);
94
+ // Create final result
95
+ const result = {
96
+ config,
97
+ grid,
98
+ timestamp: new Date(),
99
+ calculationTimeMs,
100
+ summary
101
+ };
102
+ onProgress?.({
103
+ stage: 'complete',
104
+ progress: 100,
105
+ message: 'Coverage calculation complete!'
106
+ });
107
+ return result;
108
+ }
109
+ /**
110
+ * Validate configuration before calculation
111
+ *
112
+ * Checks for common configuration errors:
113
+ * - Invalid distances (negative, zero, too large)
114
+ * - Invalid frequencies (outside valid ranges)
115
+ * - Invalid antenna heights
116
+ * - Missing required data
117
+ *
118
+ * Throws descriptive errors if validation fails.
119
+ *
120
+ * @param config - Configuration to validate
121
+ * @throws Error if configuration is invalid
122
+ */
123
+ validateConfiguration(config) {
124
+ // Validate grid settings
125
+ const { cellSizeMeters, maxRadiusKm } = config.gridSettings;
126
+ if (cellSizeMeters <= 0 || cellSizeMeters > 1000) {
127
+ throw new Error(`Invalid cell size: ${cellSizeMeters}m. Must be between 1m and 1000m.`);
128
+ }
129
+ if (maxRadiusKm <= 0 || maxRadiusKm > 100) {
130
+ throw new Error(`Invalid max radius: ${maxRadiusKm}km. Must be between 0.1km and 100km.`);
131
+ }
132
+ // Check grid size doesn't exceed reasonable limits
133
+ const gridSize = (maxRadiusKm * 2000) / cellSizeMeters;
134
+ const totalCells = gridSize * gridSize;
135
+ if (totalCells > 1000000) {
136
+ // 1 million cells
137
+ throw new Error(`Grid too large: ${totalCells} cells. ` +
138
+ `Consider increasing cell size or decreasing radius. ` +
139
+ `Max recommended: 1 million cells.`);
140
+ }
141
+ // Validate sectors
142
+ if (!config.site.sectors || config.site.sectors.length === 0) {
143
+ throw new Error('Site configuration must include at least one sector');
144
+ }
145
+ for (const sector of config.site.sectors) {
146
+ // Validate frequency
147
+ if (sector.frequency < 100 || sector.frequency > 10000) {
148
+ throw new Error(`Invalid frequency for sector ${sector.sectorId}: ${sector.frequency}MHz. ` +
149
+ `Must be between 100 MHz and 10 GHz.`);
150
+ }
151
+ // Validate TX power
152
+ if (sector.txPower < 0 || sector.txPower > 80) {
153
+ throw new Error(`Invalid TX power for sector ${sector.sectorId}: ${sector.txPower}dBm. ` +
154
+ `Must be between 0 and 80 dBm.`);
155
+ }
156
+ // Validate antenna height
157
+ if (sector.position.height < 0 || sector.position.height > 500) {
158
+ throw new Error(`Invalid antenna height for sector ${sector.sectorId}: ${sector.position.height}m. ` +
159
+ `Must be between 0 and 500 meters.`);
160
+ }
161
+ // Validate azimuth
162
+ if (sector.azimuth < 0 || sector.azimuth >= 360) {
163
+ throw new Error(`Invalid azimuth for sector ${sector.sectorId}: ${sector.azimuth}°. ` +
164
+ `Must be between 0 and 359 degrees.`);
165
+ }
166
+ // Validate antenna pattern
167
+ if (!sector.antennaPattern) {
168
+ throw new Error(`Missing antenna pattern for sector ${sector.sectorId}`);
169
+ }
170
+ if (!sector.antennaPattern.pattern ||
171
+ sector.antennaPattern.pattern.length !== 360) {
172
+ throw new Error(`Invalid horizontal pattern for sector ${sector.sectorId}. ` +
173
+ `Must have exactly 360 values.`);
174
+ }
175
+ if (!sector.antennaPattern.vertical_pattern ||
176
+ sector.antennaPattern.vertical_pattern.length !== 360) {
177
+ throw new Error(`Invalid vertical pattern for sector ${sector.sectorId}. ` +
178
+ `Must have exactly 360 values.`);
179
+ }
180
+ }
181
+ // Validate thresholds
182
+ const { excellent, good, fair, edge } = config.signalThresholds;
183
+ if (excellent <= good || good <= fair || fair <= edge) {
184
+ throw new Error(`Invalid signal thresholds. Must be in descending order: ` +
185
+ `excellent (${excellent}) > good (${good}) > fair (${fair}) > edge (${edge})`);
186
+ }
187
+ if (excellent > -50 || edge < -120) {
188
+ throw new Error(`Signal thresholds out of reasonable range. ` +
189
+ `Excellent should be < -50 dBm, edge should be > -120 dBm.`);
190
+ }
191
+ }
192
+ /**
193
+ * Generate human-readable and AI-ready summary
194
+ *
195
+ * Creates a comprehensive summary of coverage results including:
196
+ * - Description: Human-readable text summary
197
+ * - Issues: List of detected problems/warnings
198
+ * - Metrics: Key numerical metrics for AI analysis
199
+ *
200
+ * This summary is designed to be consumed by:
201
+ * 1. Human users (description text)
202
+ * 2. UI components (structured data)
203
+ * 3. AI analysis tools (metrics + issues)
204
+ *
205
+ * @param config - Original configuration
206
+ * @param grid - Calculation results
207
+ * @param sectorCount - Number of sectors calculated
208
+ * @returns Summary object
209
+ */
210
+ generateSummary(config, grid, sectorCount) {
211
+ const stats = grid.stats;
212
+ const issues = [];
213
+ // Generate description
214
+ const description = this.createDescription(config, stats, sectorCount);
215
+ // Detect issues
216
+ this.detectIssues(config, stats, issues);
217
+ // Extract metrics for AI
218
+ const metrics = extractMetrics(grid);
219
+ return {
220
+ description,
221
+ issues,
222
+ metrics
223
+ };
224
+ }
225
+ /**
226
+ * Create human-readable description
227
+ */
228
+ createDescription(config, stats, sectorCount) {
229
+ const lines = [];
230
+ // Site info
231
+ lines.push(`Coverage Analysis for ${config.site.siteName}`);
232
+ lines.push(`Sectors: ${sectorCount}`);
233
+ lines.push('');
234
+ // Coverage summary
235
+ lines.push(`Total Coverage: ${stats.coveragePercentage.toFixed(1)}% of ${stats.totalAreaKm2.toFixed(2)} km²`);
236
+ lines.push('');
237
+ // Quality breakdown
238
+ lines.push('Signal Quality Distribution:');
239
+ lines.push(` Excellent: ${stats.excellentAreaKm2.toFixed(2)} km² (${((stats.excellentAreaKm2 / stats.totalAreaKm2) * 100).toFixed(1)}%)`);
240
+ lines.push(` Good: ${stats.goodAreaKm2.toFixed(2)} km² (${((stats.goodAreaKm2 / stats.totalAreaKm2) * 100).toFixed(1)}%)`);
241
+ lines.push(` Fair: ${stats.fairAreaKm2.toFixed(2)} km² (${((stats.fairAreaKm2 / stats.totalAreaKm2) * 100).toFixed(1)}%)`);
242
+ lines.push(` Poor: ${stats.poorAreaKm2.toFixed(2)} km² (${((stats.poorAreaKm2 / stats.totalAreaKm2) * 100).toFixed(1)}%)`);
243
+ lines.push('');
244
+ // Per-sector stats
245
+ if (stats.sectorStats) {
246
+ lines.push('Per-Sector Performance:');
247
+ // @ts-ignore - Object.entries returns unknown type
248
+ for (const [sectorId, sectorStat] of Object.entries(stats.sectorStats)) {
249
+ lines.push(` ${sectorId}:`);
250
+ lines.push(` Max Range: ${sectorStat.maxRangeKm.toFixed(2)} km`);
251
+ lines.push(` Avg Signal: ${sectorStat.avgSignalDbm.toFixed(1)} dBm`);
252
+ lines.push(` Coverage Area: ${sectorStat.coverageAreaKm2.toFixed(2)} km²`);
253
+ }
254
+ }
255
+ return lines.join('\n');
256
+ }
257
+ /**
258
+ * Detect common issues and warnings
259
+ */
260
+ detectIssues(config, stats, issues) {
261
+ // Low coverage
262
+ if (stats.coveragePercentage < 50) {
263
+ issues.push(`Low overall coverage: ${stats.coveragePercentage.toFixed(1)}%. ` +
264
+ `Consider increasing TX power, antenna height, or optimizing azimuth/tilt.`);
265
+ }
266
+ // Poor quality dominance
267
+ const poorRatio = stats.poorAreaKm2 / stats.coveredAreaKm2;
268
+ if (poorRatio > 0.5) {
269
+ issues.push(`Over 50% of coverage is poor quality. ` +
270
+ `Consider increasing TX power or reducing coverage area with downtilt.`);
271
+ }
272
+ // Excessive range (potential interference)
273
+ if (stats.sectorStats) {
274
+ // @ts-ignore - Object.entries returns unknown type
275
+ for (const [sectorId, sectorStat] of Object.entries(stats.sectorStats)) {
276
+ if (sectorStat.maxRangeKm > 15) {
277
+ issues.push(`Sector ${sectorId} has excessive range (${sectorStat.maxRangeKm.toFixed(1)} km). ` +
278
+ `Consider adding downtilt to reduce interference to neighboring sites.`);
279
+ }
280
+ }
281
+ }
282
+ // Very short range (undershooting)
283
+ if (stats.sectorStats) {
284
+ // @ts-ignore - Object.entries returns unknown type
285
+ for (const [sectorId, sectorStat] of Object.entries(stats.sectorStats)) {
286
+ if (sectorStat.maxRangeKm < 1) {
287
+ issues.push(`Sector ${sectorId} has very short range (${sectorStat.maxRangeKm.toFixed(1)} km). ` +
288
+ `Check TX power, antenna height, and tilt settings.`);
289
+ }
290
+ }
291
+ }
292
+ // Weak average signal
293
+ if (stats.sectorStats) {
294
+ // @ts-ignore - Object.entries returns unknown type
295
+ for (const [sectorId, sectorStat] of Object.entries(stats.sectorStats)) {
296
+ if (sectorStat.avgSignalDbm < -90) {
297
+ issues.push(`Sector ${sectorId} has weak average signal (${sectorStat.avgSignalDbm.toFixed(1)} dBm). ` +
298
+ `Most coverage area is at poor signal levels.`);
299
+ }
300
+ }
301
+ }
302
+ // Minimal excellent coverage
303
+ const excellentRatio = stats.excellentAreaKm2 / stats.coveredAreaKm2;
304
+ if (excellentRatio < 0.1) {
305
+ issues.push(`Less than 10% of coverage is excellent quality. ` +
306
+ `Users will experience reduced data speeds in most areas.`);
307
+ }
308
+ }
309
+ }
310
+ // ============================================================================
311
+ // CONVENIENCE FUNCTIONS
312
+ // ============================================================================
313
+ /**
314
+ * Quick coverage calculation (simplified API)
315
+ *
316
+ * For simple use cases where you don't need full configuration control.
317
+ * Uses sensible defaults for most parameters.
318
+ *
319
+ * @param site - Site configuration
320
+ * @param options - Optional overrides
321
+ * @returns Coverage result
322
+ *
323
+ * @example
324
+ * const result = await quickCalculate(mySite, {
325
+ * cellSizeMeters: 100, // Faster calculation
326
+ * maxRadiusKm: 5 // Smaller area
327
+ * });
328
+ */
329
+ export async function quickCalculate(site, options) {
330
+ const calculator = new CoverageCalculator();
331
+ const config = {
332
+ site,
333
+ gridSettings: {
334
+ centerPosition: site.position,
335
+ cellSizeMeters: options?.cellSizeMeters || 50,
336
+ maxRadiusKm: options?.maxRadiusKm || 10,
337
+ pathLossModel: options?.pathLossModel || 'free-space'
338
+ },
339
+ signalThresholds: {
340
+ excellent: -70,
341
+ good: -85,
342
+ fair: -95,
343
+ edge: -105
344
+ },
345
+ calculateInterference: true
346
+ };
347
+ return calculator.calculate(config);
348
+ }
349
+ /**
350
+ * Calculate coverage and export for AI analysis
351
+ *
352
+ * Convenience function that calculates coverage and formats
353
+ * the result specifically for AI consumption.
354
+ *
355
+ * @param config - Coverage configuration
356
+ * @returns AI-ready analysis object
357
+ */
358
+ export async function calculateForAI(config) {
359
+ const calculator = new CoverageCalculator();
360
+ const result = await calculator.calculate(config);
361
+ // Format for AI
362
+ return {
363
+ summary: result.summary.description,
364
+ metrics: result.summary.metrics,
365
+ issues: result.summary.issues,
366
+ sectorData: config.site.sectors.map((s) => ({
367
+ sectorId: s.sectorId,
368
+ azimuth: s.azimuth,
369
+ tilt: s.mechanicalTilt + s.electricalTilt,
370
+ power: s.txPower,
371
+ frequency: s.frequency,
372
+ stats: result.grid.stats.sectorStats[s.sectorId]
373
+ }))
374
+ };
375
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Grid Calculator
3
+ *
4
+ * This module implements grid-based coverage calculation.
5
+ * It divides the area around an antenna into a grid of cells
6
+ * and calculates signal strength at each cell center.
7
+ *
8
+ * Grid-based approach advantages:
9
+ * - Regular, predictable structure
10
+ * - Easy to visualize as heatmap
11
+ * - Efficient for large areas
12
+ * - Simple to parallelize (future enhancement)
13
+ *
14
+ * Process:
15
+ * 1. Create grid around antenna position
16
+ * 2. For each grid cell:
17
+ * a. Calculate distance to antenna
18
+ * b. Calculate bearing to antenna
19
+ * c. Calculate path loss
20
+ * d. Calculate antenna gain in direction
21
+ * e. Calculate received signal strength
22
+ * 3. Aggregate results and generate statistics
23
+ */
24
+ import type { Position2D, GridSettings, CoverageGrid, RFParameters, SectorConfig, SignalThresholds, ProgressCallback } from '../types';
25
+ /**
26
+ * Generate grid structure
27
+ *
28
+ * Creates a 2D grid of geographic positions centered on a point.
29
+ * Grid cells are square (in meters), though they appear slightly
30
+ * rectangular on the map due to Earth's curvature.
31
+ *
32
+ * Grid sizing:
33
+ * - Total size = 2 × maxRadius (covers circle)
34
+ * - Number of cells = (2 × maxRadius) / cellSize in each dimension
35
+ * - Example: 10 km radius, 50m cells → 400 × 400 = 160,000 cells
36
+ *
37
+ * Cell numbering:
38
+ * - Rows increase North to South (row 0 = northernmost)
39
+ * - Cols increase West to East (col 0 = westernmost)
40
+ * - [row][col] indexing for 2D array
41
+ *
42
+ * Memory consideration:
43
+ * - Each GridCell object: ~100 bytes
44
+ * - 160,000 cells × 100 bytes = 16 MB
45
+ * - Acceptable for modern browsers
46
+ *
47
+ * @param settings - Grid configuration
48
+ * @returns 2D array of positions (not yet populated with signal data)
49
+ */
50
+ export declare function generateGridPositions(settings: GridSettings): Position2D[][];
51
+ /**
52
+ * Calculate coverage grid for a single antenna/sector
53
+ *
54
+ * This is the core coverage calculation function. It:
55
+ * 1. Generates a grid of positions
56
+ * 2. For each position, calculates:
57
+ * - Distance to antenna
58
+ * - Path loss based on distance and model
59
+ * - Signal strength based on antenna pattern
60
+ * 3. Classifies signal quality
61
+ * 4. Generates statistics
62
+ *
63
+ * Progress reporting:
64
+ * - Calls progress callback after each row (or every N cells)
65
+ * - Allows UI to show progress bar
66
+ * - Keeps browser responsive for large grids
67
+ *
68
+ * Optimization notes:
69
+ * - Path loss calculation is expensive (log operations)
70
+ * - Could cache path loss vs distance (future optimization)
71
+ * - Could use Web Workers for parallel calculation
72
+ * - Current implementation: ~0.5ms per cell on modern CPU
73
+ * (160,000 cells = ~80 seconds, acceptable for one-time calculation)
74
+ *
75
+ * @param rfParams - Complete RF configuration
76
+ * @param gridSettings - Grid size and resolution
77
+ * @param thresholds - Signal quality thresholds
78
+ * @param onProgress - Progress callback (optional)
79
+ * @returns Complete coverage grid with signal data
80
+ */
81
+ export declare function calculateSingleSectorCoverage(rfParams: RFParameters, gridSettings: GridSettings, thresholds: SignalThresholds, onProgress?: ProgressCallback): CoverageGrid;
82
+ /**
83
+ * Calculate coverage grid for multiple sectors
84
+ *
85
+ * Common scenario: Cell site with 3 sectors covering 360°.
86
+ * This function calculates signal from all sectors at each point
87
+ * and determines which sector provides strongest signal.
88
+ *
89
+ * Additional capabilities:
90
+ * - Identifies dominant server (which sector serves each location)
91
+ * - Calculates overlap areas (where multiple sectors are strong)
92
+ * - Detects potential interference zones
93
+ *
94
+ * Performance consideration:
95
+ * - Calculates N × grid_size signal strengths (N = number of sectors)
96
+ * - 3 sectors × 160,000 cells = 480,000 calculations
97
+ * - Still manageable (few minutes on modern hardware)
98
+ *
99
+ * @param sectors - Array of sector configurations
100
+ * @param gridSettings - Grid size and resolution
101
+ * @param thresholds - Signal quality thresholds
102
+ * @param onProgress - Progress callback (optional)
103
+ * @returns Coverage grid with multi-sector data
104
+ */
105
+ export declare function calculateMultiSectorCoverage(sectors: SectorConfig[], gridSettings: GridSettings, thresholds: SignalThresholds, onProgress?: ProgressCallback): CoverageGrid;
106
+ /**
107
+ * Extract summary metrics for AI analysis
108
+ *
109
+ * Converts coverage grid into structured metrics suitable for
110
+ * AI interpretation and recommendation generation.
111
+ *
112
+ * @param grid - Coverage grid
113
+ * @returns Metrics object
114
+ */
115
+ export declare function extractMetrics(grid: CoverageGrid): Record<string, number>;