Início›Aplicativos›Análise Telemática e GIS›Gerador de Ferramenta Forense para Análise de ERB e CDR
AplicativosAnálise Telemática e GIS
Gerador de Ferramenta Forense para Análise de ERB e CDR
Cria uma aplicação web interativa para mapear deslocamentos e setores de antenas a partir de dados telemáticos de operadoras em investigações criminais.
☆☆☆☆☆
avaliação
0.0/5
nota média
33
visualizações totais
0
avaliações
prompt completo
# PROMPT DE ENGENHARIA DE SOFTWARE FORENSE
## Gerador da Ferramenta Interativa de Visualização Telemática (ERB / CDR)
**v2.0 — Especificação Completa**
---
> **INSTRUÇÕES DE USO**
>
> Copie e cole **TODO** este prompt em um LLM (Claude, GPT-4, etc).
>
> A ferramenta será entregue como **arquivo HTML único autossuficiente** que funciona offline.
---
## 1. PAPEL E CONTEXTO
Você é um **Engenheiro de Software Sênior** especializado em:
- Sistemas de Informações Geográficas (GIS) com Leaflet.js
- Ferramentas Forenses de Análise Telemática para investigações policiais
- Design tático de interfaces para órgãos de segurança pública
- Processamento e validação de dados telemétricos
**Sua tarefa:** Criar uma aplicação web **interativa em arquivo ÚNICO HTML** (HTML5 + CSS Tailwind + JavaScript vanilla + Leaflet.js + SheetJS) que processe planilhas Excel (.xls, .xlsx) e CSV de extratos de Estação Rádio-Base (ERB) e Call Detail Records (CDR), visualizando:
1. **Histórico cronológico de deslocamento** do alvo (timeline interativa)
2. **Setores angulares de cobertura** (polígonos de 120°) de cada ERB
3. **Azimute central** (linha de orientação da antena)
4. **Metadados forenses** (coordenadas de precisão, timestamps, identificadores)
---
## 2. REQUISITOS FUNCIONAIS
### 2.1 Leitura e Mapeamento Dinâmico de Colunas
A ferramenta deve ler automaticamente planilhas e mapear colunas com **tolerância a variações** de nomenclatura entre operadoras brasileiras (VIVO, TIM, CLARO, OI).
Use este schema para mapeamento:
```json
{
"COLUMN_MAPPING": {
"latitude": [
"Latitude RS", "Latitude RE", "Latitude", "lat", "LAT",
"LATITUDE", "Lat", "latitude"
],
"longitude": [
"Longitude RS", "Longitude RE", "Longitude", "lon", "LON",
"LONGITUDE", "Lon", "longitude"
],
"azimuth": [
"Azimute RS", "Azimute RE", "Azimute", "AZIMUTE",
"Azimuth", "azimuth", "Azi"
],
"terminal": [
"Número A", "MSISDN", "Terminal", "Número",
"TERMINAL", "Alvo", "CPF", "IMSI"
],
"dateStart": [
"Data Início", "Data", "DataInicio",
"Data Partida", "Start Date"
],
"timeStart": [
"Hora Início", "Hora", "HoraInicio",
"Hora Partida", "Start Time"
],
"siteId": [
"SiteID RS", "SiteID", "Site ID", "Site",
"SetorID RS", "SetorID", "ID_ERB"
],
"municipality": [
"Município ERB RS", "Cidade", "Município",
"Municipality", "Local"
],
"address": [
"Endereço ERB RS", "Endereço", "Address",
"Logradouro", "Localização"
]
}
}
```
**Regras de parsing:**
| Campo | Formato Aceito | Tratamento |
|-------|---|---|
| **Latitude/Longitude** | Numérico com vírgula ou ponto | Converter `,` → `.`; validar range: lat ∈ [-90, 90], lon ∈ [-180, 180] |
| **Azimute** | Inteiro 0-360 ou `Ausente` | Se ausente/zero/nulo: usar `0°` (norte); se >360: aplicar `mod 360` |
| **Data** | `YYYYMMDD` ou `DD/MM/YYYY` | Tentar parser nessa ordem; suportar `-`, `/`, `.` como separadores |
| **Hora** | `HHMMSS` ou `HH:MM:SS` | Combinar com data em DateTime ISO; validar range 00:00:00 – 23:59:59 |
| **Colunas ausentes** | Fallback | Usar `0` para coords, `0°` para azimute, `"N/A"` para texto |
---
### 2.2 Lógica Matemática e Geometria Forense
#### A. Setor Angular de 120° ("Fatia de Pizza")
Para cada registro com coordenadas válidas:
1. **Abertura total: 120°** (Azimute − 60° até Azimute + 60°)
2. **Raio configurável dinamicamente** via slider na interface:
- Faixa: 100m a 2.500m
- Padrão: 500m
- Atualização em tempo real ao mover slider
3. **Cálculo geodésico:**
- Usar fórmula de destino com raio da Terra: R = 6.378.137m
- Gerar 9+ vértices do arco (incremento de 15° cada)
- Fechar polígono retornando ao centro
**Pseudocódigo:**
```javascript
function createSectorPolygon(centerLat, centerLon, azimuth, radiusMeters) {
const R = 6378137; // metros
const startAngle = (azimuth - 60) * (Math.PI / 180);
const endAngle = (azimuth + 60) * (Math.PI / 180);
const vertices = [[centerLat, centerLon]]; // incluir centro
for (let angle = startAngle; angle <= endAngle; angle += (15 * Math.PI / 180)) {
const destLat = Math.asin(
Math.sin(centerLat * Math.PI/180) * Math.cos(radiusMeters / R) +
Math.cos(centerLat * Math.PI/180) * Math.sin(radiusMeters / R) * Math.cos(angle)
) * (180 / Math.PI);
const destLon = centerLon * Math.PI/180 + Math.atan2(
Math.sin(angle) * Math.sin(radiusMeters / R) * Math.cos(centerLat * Math.PI/180),
Math.cos(radiusMeters / R) - Math.sin(centerLat * Math.PI/180) * Math.sin(destLat * Math.PI/180)
);
vertices.push([destLat, destLon * (180 / Math.PI)]);
}
vertices.push([centerLat, centerLon]); // fechar polígono
return vertices;
}
```
#### B. Linha de Azimute Central
Desenhe uma linha estendida que:
- Parte do centro da ERB
- Segue na direção exata do azimute
- Estende-se até o raio do setor
- Cor: cyan (#0ea5e9), espessura 2px, opacidade 0.8
#### C. Ordenação Cronológica (OBRIGATÓRIO)
**TODOS** os registros devem ser ordenados cronologicamente **crescente** (mais antigo → mais recente) **antes** de construir a timeline e renderizar o mapa. Se dois registros tiverem o mesmo timestamp:
- Ordenar alfabeticamente por `siteId`
- Se `siteId` também igual, manter ordem original (stable sort)
---
### 2.3 Estrutura de Dados: Mock Dataset Inicial
A aplicação deve **abrir imediatamente funcionando** com dados de exemplo. Use este padrão:
```json
{
"mockDataset": {
"terminal": "11987654321",
"operadora": "VIVO",
"municipios": ["São Paulo", "Guarulhos", "Osasco"],
"records": [
{
"index": 1,
"latitude": -23.550520,
"longitude": -46.633309,
"azimuth": 45,
"datetime": "2024-01-15T14:15:00",
"siteId": "ERB-SP-001",
"municipality": "São Paulo",
"address": "Avenida Paulista, 1000"
},
{
"index": 2,
"latitude": -23.528702,
"longitude": -46.624891,
"azimuth": 135,
"datetime": "2024-01-15T15:02:30",
"siteId": "ERB-SP-002",
"municipality": "São Paulo",
"address": "Rua Augusta, 2500"
},
{
"index": 3,
"latitude": -23.437640,
"longitude": -46.470670,
"azimuth": 270,
"datetime": "2024-01-15T16:45:15",
"siteId": "ERB-GUA-001",
"municipality": "Guarulhos",
"address": "Avenida Monteiro Lobato, 500"
},
{
"index": 4,
"latitude": -23.531090,
"longitude": -46.779050,
"azimuth": 0,
"datetime": "2024-01-15T17:30:00",
"siteId": "ERB-OSA-001",
"municipality": "Osasco",
"address": "Estrada de Ferro, 300"
},
{
"index": 5,
"latitude": -23.550520,
"longitude": -46.633309,
"azimuth": 180,
"datetime": "2024-01-15T18:15:45",
"siteId": "ERB-SP-001",
"municipality": "São Paulo",
"address": "Avenida Paulista, 1000"
},
{
"index": 6,
"latitude": -23.570400,
"longitude": -46.656200,
"azimuth": 90,
"datetime": "2024-01-15T19:00:30",
"siteId": "ERB-SP-003",
"municipality": "São Paulo",
"address": "Rua Oscar Freire, 800"
},
{
"index": 7,
"latitude": -23.437640,
"longitude": -46.470670,
"azimuth": 315,
"datetime": "2024-01-15T20:10:00",
"siteId": "ERB-GUA-001",
"municipality": "Guarulhos",
"address": "Avenida Monteiro Lobato, 500"
},
{
"index": 8,
"latitude": -23.528702,
"longitude": -46.624891,
"azimuth": 225,
"datetime": "2024-01-15T21:30:15",
"siteId": "ERB-SP-002",
"municipality": "São Paulo",
"address": "Rua Augusta, 2500"
}
]
}
}
```
**Características do mock:**
- ✓ 8 registros cronologicamente ordenados
- ✓ Variação de azimutes (45°, 135°, 270°, 0°, 180°, 90°, 315°, 225°)
- ✓ Múltiplos municípios (SP, Guarulhos, Osasco)
- ✓ Repetição intencional de sites (ERB-SP-001 aparece 2x para testar)
- ✓ Timestamps em saltos realistas (45min–1h20min entre eventos)
---
## 3. REQUISITOS VISUAIS
### 3.1 Paleta de Cores (Hex)
```json
{
"colors": {
"bgPrimary": "#0f172a", // Fundo escuro principal (slate-950)
"bgSecondary": "#1e293b", // Fundo secundário (slate-800)
"bgTertiary": "#334155", // Fundo terciário (slate-700)
"textPrimary": "#f1f5f9", // Texto principal (slate-100)
"textSecondary": "#94a3b8", // Texto secundário (slate-400)
"textTertiary": "#64748b", // Texto terciário (slate-500)
"accentCyan": "#0ea5e9", // Azul tático (cyan-500)
"accentPink": "#ec4899", // Rosa/Fúcsia ativa (pink-500)
"sectorInactive": "rgba(225, 29, 72, 0.15)", // rose-600 + alpha 0.15
"sectorActive": "rgba(236, 72, 153, 0.8)", // pink-500 + alpha 0.8
"borderDefault": "#475569", // Borda (slate-600)
"borderHighlight": "#0ea5e9", // Borda destaque (cyan)
"success": "#10b981", // Verde (emerald-500)
"warning": "#f59e0b", // Amarelo (amber-500)
"danger": "#ef4444" // Vermelho (red-500)
}
}
```
### 3.2 Layout Estrutural
**Viewport total: 100vh × 100vw**
Dividida em 3 seções:
```
┌────────────────────────────────────────────────────┐
│ HEADER (h-16, ~80px) │
├──────────────────────┬──────────────────────────────┤
│ │ │
│ MAPA LEAFLET │ TIMELINE & DETALHES │
│ (60% width) │ (40% width) │
│ w-[60%] │ w-[40%] │
│ h-[calc(100vh-80px-70px)] │ h-[calc(100vh-80px-70px)]
│ │ │
│ │ │
│ PLAYER (bottom) │ │
│ h-[70px] │ │
└──────────────────────┴──────────────────────────────┘
```
### 3.3 Componentes da Interface
#### A. HEADER (Altura: 64px)
```html
[#0f172a] border-b border-[#475569]">
```
**Badges:**
- **Alvo:** "11987654321" (ou valor do terminal)
- **Eventos:** "8 registros" (total de linhas processadas)
- **Setor:** "120°" (fixo, informativo)
#### B. ÁREA ESQUERDA: Mapa Leaflet (60% width)
```html
[60%] h-[calc(100vh-80px-70px)] relative">
[#1e293b] p-2 rounded">
```
**Mapa:**
- Tiles: CARTO Dark Matter (`https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png`)
- Zoom inicial: enquadrar todos os pontos (fitBounds)
- Controles padrão: zoom + layers
- Pops-up interativos ao clicar em marcadores/polígonos
#### C. ÁREA DIREITA: Timeline & Detalhes (40% width)
Dividida em 3 sub-seções:
**C1. Search Bar (h-12)**
```html
Gerador de Ferramenta Forense para Análise de ERB e CDR
Cria uma aplicação web interativa para mapear deslocamentos e setores de antenas a partir de dados telemáticos de operadoras em investigações criminais.