# 02 - Projeto Scraper Java

A pasta irmão `scrapper` contém uma aplicação autónoma em puro Java com a responsabilidade de raspar (scrapping) a informação dos clubes, jogos e tabelas.

## Ficheiros Críticos
O projeto está implementado em `src/main/java/org/example/`. Destacam-se:
- `Main.java`: Onde o projeto arranca. Configura a ligação com Firebase, cria a Realtime DB reference e também executa as ações principais (ex. extrair info de clubes).
- `StandingsScraper.java`: Classe responsável pela extração das Tabelas Classificativas (Standings) e lista de jogos (Jornadas) baseando-se num endpoint JSON fornecido pela AFAVCD.
- `PlayersScraper.java`: Esqueleto preparado para iterar pela lista de plantéis das equipas.
- Diretório `models/`: Classes de modelos Java que refletem a estrutura exata do que será enviado ao Firebase.

## Tecnologias Usadas

1. **JSoup**: Utilizado para enviar HTTP requests a URLs tradicionais e efetuar o parsing de documentos HTML usando CSS Selectors (quando a informação não é fornecida via JSON).
2. **GSON (Google JSON)**: Utilizado quando a associação fornece endpoints JSON. O Gson pega nas "Strings" JSON devolvidas pela API e converte para objetos (models) Java, facilitando o acesso às propriedades.
3. **Firebase Admin SDK**: Ao contrário do Android (que usa Auth regular de cliente), o Scraper tem privilégios de Admin. Utiliza a "chave de serviço" de Firebase (vulgarmente no ficheiro `service-account.json` que deve manter-se sempre fora do controlo de versões, via `.gitignore`).
4. **Gradle**: O ciclo de build e os pacotes são geridos pelo Gradle (usando sintaxe `build.gradle.kts`).

## O Fluxo Padrão do Scraper

1. A função `main` carrega o Firebase Options, passando as credenciais para obter acesso total à base de dados de Firebase.
2. Invocam-se os Scrapers. Por exemplo, `StandingsScraper.scrapeAndSync()`.
3. O Scraper descarrega o payload (JSON ou HTML).
4. O Scraper itera os elementos (Equipas, Jogos). Cria uma instância da classe Model relevante (ex: `TeamStanding.java`).
5. A referência Firebase é chamada (e.g. `ref.child("Senior").child("standings")`) e o objeto é passado por `setValueAsync()`.

## Notas de Evolução

- *Limites de Rate*: Quando o projeto aumentar a sua abrangência (extrair todos os jogadores para todas as equipas), deve-se implementar delays (`Thread.sleep()`) para prevenir que o servidor que está a sofrer o scraping bloqueie o nosso IP.
- *Tipagem Ficheiros Models*: Os atributos nas classes `models/` têm de bater certo com os declarados na App Android. Qualquer refactoring a nomes de atributos, deverá ser feito em ambos os projetos sob pena de a App Android apresentar UI sem dados (`null`).
