Analemma
Ferramenta web que permite visualizar trajetórias solares e lunares a partir de qualquer localização geográfica.
Um sistema completo para captura fotográfica automatizada e visualização interativa de analemas solares e lunares.
Este projeto automatiza a captura periódica de imagens provenientes de webcams públicas, gerando sequências (timelapses) que evidenciam o movimento aparente do Sol e da Lua ao longo do tempo. As imagens são capturadas em momentos astronômicos precisos mediante GitHub Actions e consumidas posteriormente em um Visualizador Web Moderno (PWA) de alto desempenho. Todo o sistema funciona sem requerer bancos de dados tradicionais, baseando-se no próprio sistema de arquivos de um repositório Git.
Arquitetura do Software
Para manter o código sustentável, escalável e testável, o núcleo do orquestrador fotográfico (src/) foi estruturado seguindo estritamente os preceitos de Clean Architecture e Domain-Driven Design (DDD).
1. Domain Layer
É o coração do software. Aqui residem as regras de negócio puras, independentes de qualquer framework ou infraestrutura externa:
- Entidades (
Location,Camera): UmLocationencapsula dados geográficos (país, estado, cidade) e gera identificadores dinâmicos. UmaCameraestá vinculada a umLocatione mantém sua orientação cardinal. - Value Objects: Objetos como
CelestialObjectpadronizam o vocabulário de domínio. - Contratos (Interfaces): Abstrações como
ScheduleRepositoryque definem como o domínio espera obter ou persistir dados.
2. Application Layer
Contém os casos de uso principais. Atua como o orquestrador que coordena o Domínio e a Infraestrutura para cumprir com os requisitos do sistema.
Scheduler: É o encarregado de revisar os horários programados de cadaLocation. Se a hora atual de execução coincidir (ou estiver no limiar) de uma captura programada, coordena o serviço de captura correspondente para obter a imagem.
3. Infrastructure Layer
Onde o código interage com serviços externos, I/O e frameworks:
- Serviços de Captura: Utiliza-se Puppeteer (
PuppeteerCaptureService) para visitar páginas web de webcams públicas, aguardar o carregamento de componentes multimídia e extrair limpos os quadros (screenshots) do fluxo de vídeo ou canvas sem incluir a interface web. ConfigScheduleRepository: Um repositório dinâmico que usa configurações para calcular horários precisos de captura nas coordenadas de cadaLocationregistradas emsrc/config/locations.ts.
Ciclo de Orquestração
O orquestrador está projetado para ser executado ciclicamente através do GitHub Actions, otimizando recursos mediante um cronjob.
sequenceDiagram
participant GH as GitHub Actions (Cron)
participant App as Scheduler
participant Repo as ConfigScheduleRepository
participant Cam as PuppeteerCaptureService
participant FS as File System / Git
GH->>App: Executa ciclo horário (minuto 0)
App->>Repo: Consulta horas de captura para o dia
Repo-->>App: Retorna { sun: '12:05', moon: '03:45' }
App->>App: Avalia se a hora do sistema (America/La_Paz) coincide
alt Coincide com evento Solar no limiar
App->>Cam: Inicia Puppeteer Headless
Cam-->>App: Extrai e retorna buffer de imagem (Screenshot)
App->>FS: Salva arquivo em 'captures/sun/{location}/{camera}/{YYYY-MM-DD}.jpg'
GH->>FS: Realiza Git Commit e Push ao repositório
end
Configuração e Variáveis de Ambiente
O sistema baseia-se em configurações centralizadas, requerendo muito pouco para ser executado. O principal é a sincronização temporal.
| Variável | Descrição |
|---|---|
TZ | Crítico: Garante a configuração do fuso horário em America/La_Paz (UTC-4). A aplicação utiliza esta âncora para sincronizar e comparar os horários astronômicos esperados com o cronjob horário. |
Web Viewer
Esta é uma aplicação web interativa projetada especificamente para visualizar fluidamente dezenas de milhares de capturas fotográficas (timelapses) geradas pelo orquestrador principal do projeto, evidenciando os trajetos do Sol e da Lua ao longo de extensos períodos de tempo.
Arquitetura UI e Experiência do Usuário (UX)
A aplicação web foi concebida para oferecer um desempenho superior, especialmente ao manipular um grande volume de imagens em alta resolução sem comprometer a memória ou fluidez do navegador.
Transições Fluidas
Implementa-se uma navegação que intercepta os cliques do usuário e carrega dinamicamente a próxima página no DOM sem recarregar a tela inteira. Isso garante que o estado da interface, como o tema visual ou a navegação principal, permaneça ininterrupto.
Persistência do Modo Escuro
O esquema de cores escuro/claro é detectado a partir do sistema e mantido consistentemente ao longo das sessões do usuário. Graças à sincronização com as transições de página, não existem oscilações visuais (“flickering”) ao navegar entre diferentes visualizações.
O Coração do Visualizador: O Reprodutor
Um desafio crítico ao visualizar milhares de imagens (ex. um Analema anual possui 365 quadros de alta resolução) é o colapso da memória do dispositivo do usuário final. Para mitigá-lo, o reprodutor de imagens apoia-se em uma arquitetura leve e otimizada:
stateDiagram-v2
[*] --> Initialization: Carrega dataset URLs
Initialization --> BufferedLoading: Pré-carrega primeira imagem (Preview)
BufferedLoading --> BackgroundLoading: Carregamento progressivo de lotes
BackgroundLoading --> Ready: Atinge-se o limiar mínimo (ex. 20%)
Ready --> Playback: Usuário inicia reprodução
Playback --> Tick: Atualiza imagem baseado em FPS
Tick --> UpdateFrame: Renderiza próximo quadro
UpdateFrame --> Playback: Loop se houver mais quadros
1. Carregamento Bufferizado Assíncrono (Buffered Loading)
Em vez de forçar o navegador a baixar todas as imagens antes de permitir a interação, o reprodutor inicia um processo em segundo plano que baixa as imagens em pequenos lotes assíncronos. A reprodução é habilitada assim que uma porcentagem mínima de quadros já está disponível localmente, prevenindo bloqueios visuais.
2. Controle Dinâmico de Velocidade
O usuário tem controle total sobre a velocidade de reprodução, que pode ser ajustada em tempo real. O reprodutor recalcula instantaneamente os intervalos de transição entre quadros (FPS) sem interrupções.
Indexação sem Bancos de Dados Relacionais
Todo o sistema está projetado para dispensar infraestruturas complexas como bancos de dados SQL ou NoSQL.
Em seu lugar, o visualizador web indexa diretamente a estrutura de pastas estáticas onde residem as imagens (captures/) durante o processo de compilação:
graph LR
A["Processo de Construção"] -->|Leitura do sistema de arquivos| B(Diretório estático 'captures/')
B --> C{Analisa a estrutura hierárquica}
C -->|Classificação por localização e câmera| D[Agrupa sequências fotográficas]
D --> E[Gera índice de metadados JSON]
E -.->|Alimenta as visualizações web| F(Renderização e Filtros UI)
Este índice leve é consumido pela interface web, permitindo aplicar filtros rápidos e precisos no lado do cliente sem requerer requisições de rede adicionais nem latência.
Pronto para Dispositivos Móveis e Offline
O visualizador web incorpora recursos avançados para maximizar seu alcance:
- Metadados Otimizados para garantir que os links compartilhados em redes sociais incluam imagens e descrições representativas.
- Configurado como Progressive Web App (PWA), permitindo sua instalação direta em dispositivos.
- Modo Offline Básico, implementando políticas de cache mediante um Service Worker para oferecer uma experiência contínua mesmo com redes instáveis.
- Tipografias Auto-hospedadas, evitando tempos de carregamento adicionais ou dependências de servidores externos.
Arraste para mover o diagrama. Use + e − para dar zoom, as setas para movê-lo e 0 para redefinir a visualização.
Vamos trabalhar juntos
Engenheiro de Software e desenvolvedor Senior Full-Stack, trabalho remotamente a partir de Santa Cruz, Bolívia. Aberto a novas oportunidades.