Files
rfcp/docs/devlog/front/RFCP-Iteration8.1-Clone-Coverage-Gaps.md
2026-01-30 20:39:13 +02:00

268 lines
6.5 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RFCP - Iteration 8.1: Clone Fix + Coverage Gaps
## Issue 1: Clone Creates New Site (Critical!)
**Problem:** Clone button creates new site instead of adding sector to existing site.
**Root Cause:** `cloneSector` function in sites store creates new site object.
### Solution
**File:** `frontend/src/store/sites.ts`
**Current (WRONG):**
```typescript
const cloneSector = (siteId: string) => {
const site = sites.find(s => s.id === siteId);
const clone = {
...site,
id: uuid(),
name: `${site.name}-clone`
};
setSites([...sites, clone]); // Creates NEW site ❌
};
```
**Fixed (CORRECT):**
```typescript
const cloneSector = (siteId: string) => {
const site = sites.find(s => s.id === siteId);
if (!site) return;
// Get last sector as template
const lastSector = site.sectors[site.sectors.length - 1];
// Create new sector (NOT new site!)
const newSector: Sector = {
...lastSector,
id: `sector-${Date.now()}`,
azimuth: (lastSector.azimuth + 120) % 360, // 120° offset for tri-sector
};
// Add sector to EXISTING site ✅
updateSite(siteId, {
sectors: [...site.sectors, newSector]
});
// Clear coverage to force recalculation
useCoverageStore.getState().clearCoverage();
};
```
### Update Button Label
**File:** `frontend/src/components/panels/SiteList.tsx`
```typescript
<button onClick={() => cloneSector(site.id)}>
+ Add Sector {/* was: "Clone" */}
</button>
```
---
## Issue 2: Coverage Gaps at 800m Wide
**Problem:** At 800m heatmap radius with 300m resolution, coverage points don't overlap enough → visible dots.
**Why it happens:**
- Resolution: 300m (distance between coverage points)
- Heatmap radius: 800m
- At high zoom, 800m radius in pixels is HUGE
- But point spacing (300m) stays same
- Result: Gaps between points visible
### Solution A: Warn User (Quick)
**File:** `frontend/src/components/panels/CoverageSettings.tsx`
```typescript
<select
value={heatmapRadius}
onChange={(e) => setHeatmapRadius(Number(e.target.value))}
>
<option value={200}>200m Fast</option>
<option value={400}>400m Balanced</option>
<option value={600}>600m Smooth</option>
<option value={800}>800m Wide</option>
</select>
{/* Warning for 800m */}
{heatmapRadius === 800 && resolution > 200 && (
<div className="warning">
Wide radius works best with fine resolution (200m).
Current: {resolution}m. Consider reducing for smoother coverage.
</div>
)}
```
### Solution B: Auto-adjust Resolution (Better)
**File:** `frontend/src/store/coverage.ts`
```typescript
const calculateCoverage = async () => {
// Auto-adjust resolution based on heatmap radius
// Rule: resolution should be ≤ radius/2 for smooth coverage
const recommendedResolution = Math.min(
resolution,
Math.floor(heatmapRadius / 2)
);
if (recommendedResolution < resolution) {
console.log(`Auto-adjusting resolution: ${resolution}m → ${recommendedResolution}m for ${heatmapRadius}m radius`);
}
const effectiveResolution = recommendedResolution;
// Calculate with adjusted resolution
await worker.calculateCoverage({
sites,
radius,
resolution: effectiveResolution,
rsrpThreshold
});
};
```
### Solution C: Dynamic Point Sampling (Advanced)
**File:** `frontend/src/components/map/HeatmapTileRenderer.ts`
Add adaptive point sampling in renderer:
```typescript
private drawPoint(
intensityMap: Float32Array,
point: CoveragePoint,
centerX: number,
centerY: number,
radiusPixels: number
): void {
// ... existing code
// ADAPTIVE: If radius is very large, increase sampling
const sampleFactor = radiusPixels > 100 ? 2 : 1;
for (let y = minY; y < maxY; y += sampleFactor) {
for (let x = minX; x < maxX; x += sampleFactor) {
// ... draw with interpolation
}
}
}
```
### Solution D: Clamp Max Radius (Safest)
**File:** `frontend/src/components/panels/CoverageSettings.tsx`
```typescript
// Limit radius based on resolution
const maxAllowedRadius = resolution * 3; // 3x resolution max
<select
value={heatmapRadius}
onChange={(e) => {
const newRadius = Number(e.target.value);
if (newRadius > maxAllowedRadius) {
toast.warning(`Radius ${newRadius}m too large for ${resolution}m resolution. Max: ${maxAllowedRadius}m`);
return;
}
setHeatmapRadius(newRadius);
}}
>
<option value={200} disabled={resolution > 100}>200m Fast</option>
<option value={400} disabled={resolution > 200}>400m Balanced</option>
<option value={600} disabled={resolution > 300}>600m Smooth</option>
<option value={800} disabled={resolution > 400}>800m Wide</option>
</select>
```
---
## Issue 3: Coverage Not Cleared on Sector Delete
**File:** `frontend/src/store/sites.ts`
```typescript
const removeSector = (siteId: string, sectorId: string) => {
const site = sites.find(s => s.id === siteId);
if (!site || site.sectors.length <= 1) {
toast.error('Cannot remove last sector');
return;
}
const updatedSectors = site.sectors.filter(s => s.id !== sectorId);
updateSite(siteId, { sectors: updatedSectors });
// CRITICAL: Clear coverage!
useCoverageStore.getState().clearCoverage();
toast.success('Sector removed. Recalculate coverage to update.');
};
```
---
## Recommended Fix Priority
**Priority 1 (Critical):**
- [ ] Fix cloneSector to add sector, not create site
- [ ] Update button label to "+ Add Sector"
- [ ] Clear coverage on sector delete
**Priority 2 (Important):**
- [ ] Add warning for 800m + 300m combo
- [ ] OR auto-adjust resolution based on radius
**Priority 3 (Nice to have):**
- [ ] Clamp max radius based on resolution
- [ ] Dynamic point sampling
---
## Testing
### Clone Fix:
1. Create site
2. Click "+ Add Sector"
3. Should show "Sites (1)" with 2 sectors ✅
4. NOT "Sites (2)" ❌
### Coverage Gaps:
1. Set resolution 300m
2. Set radius 800m
3. Calculate coverage
4. At high zoom (16+), check for dots
5. If dots visible → show warning OR auto-adjust
---
## Build & Deploy
```bash
cd /opt/rfcp/frontend
npm run build
sudo systemctl reload caddy
```
---
## Commit Message
```
fix(sites): clone adds sector to existing site, not new site
- Fixed cloneSector to add sector to same site
- Changed button label to "+ Add Sector"
- Added coverage cache clear on sector delete
- Sites count now accurate (counts sites, not sectors)
fix(coverage): prevent gaps with 800m radius
- Added warning for wide radius + coarse resolution
- Auto-adjust resolution to radius/2 for smooth coverage
- Clear coverage cache on sector changes
```
🚀 Ready for 8.1!