# RoboBET Antigo — dados e API para IAs

> pt-PT primeiro; resumo em inglês no fim. Site: https://robobet-antigo-viewer.pages.dev
> Visualizador humano: `/` · Esta página: `/ai.md` (igual a `/llms.txt`) · Manifesto de dados: `/data/index.json` (exige chave de acesso — ver secção 4)

## 1. O que é
Dados (só leitura) da app **RoboBET antiga** (`br.com.robobet` 2.1.3), API `https://app.alefut.com/api`.
Há dois tipos de estratégias:
- **Bots legado** (“funnels” do utilizador, 18): configuração completa disponível em `/data/` (com chave) (condições de entrada ao vivo, minutos, mercado, cenários).
- **Lucy**: funis/sinais geridos pela plataforma (ids conhecidos 71, 7403, 7405, 7406; outros podem aparecer, ex. 26672 “010 LUCY | AMBAS ou OVER 1.5”). A configuração interna da Lucy **não é exposta**; o perfil (minuto de entrada, stats típicos) é inferido das entradas.

Regras fixas destes dados:
- O bot **Lutero** (e o endpoint `/bot/show`) está **excluído** de tudo.
- **Nunca ROI.** As entradas são linhas asiáticas/“limite” sem odd fixa por entrada; só se publica **taxa de acerto (hit rate)** com amostra.
- Sem credenciais, tokens, emails nem ids de utilizador nos dados publicados.

## 2. Definições
- **Entrada**: um sinal do bot num jogo. Resultado `green` (acerto) ou `red` (falha).
- **Hit rate** = `100 × green ÷ n`, com `n = green + red`. Apresente sempre `n`; amostras pequenas (n < 20–30) são pouco fiáveis.
- **Janela anual**: `/lucy/reports` devolve uma linha por entrada do período “Dados do Ano” (sem paginação, sem datas).
- **Lifetime Lucy**: só existe o campo `history` em cada entrada recente (`percent_green`, `total_green`, `total_matches`). Varia de jogo para jogo (aparenta ser o histórico de longo prazo por liga/contexto), **não** é um total único do funil. Para bots legado vem `-1` (indisponível).
- **Minuto de entrada**: `events.timer` da entrada.
- **Horas**: `created` = `"HH:MM - DD/MM/AAAA"` em **hora de Brasília (UTC−3)**.

## 3. Configuração dos bots legado (campos)
`/funnel/show` devolve cada bot com ~200 campos. Rótulos pt-PT completos em `/data/campos.json`. Principais:
| Campo | Significado |
|---|---|
| `strategy_name` | nome do bot |
| `time_interval_ini` / `time_interval_max` | janela de minutos para entrar |
| `timer` | período: 1 = 1.ª parte (HT), 2 = 2.ª parte (FT) (inferido) |
| `market` | mercado: 1 = cantos, 0 = golos (inferido) |
| `home_X` / `away_X` | condição X para a equipa da casa / de fora. São **espelhadas** (iguais) quase sempre; em `bots_legado.json` cada uma aparece uma vez com `diferente_casa_fora` |
| `*_superiority` | superioridade (%) mínima |
| `*_appm`, `*_appm5`, `*_appm10` | ataques perigosos por minuto (total / últimos 5 / 10 min) mínimos |
| `*_pi` | índice de pressão mínimo |
| `*_cg`, `*_cg5`, `*_cg10` | chances de golo mínimas |
| `*_total_on_target_shots*` | remates à baliza mínimos |
| `*_total_corners` | cantos mínimos |
| `*_rt` | índice RT mínimo |
| `*_card_red` | filtro de cartão vermelho (1/0) |
| `overall_*` | mesmas métricas para o jogo inteiro (soma das equipas); `overall_avg_*` = médias pré-jogo |
| `super_favorite_losing`, `favorite_losing`, `favorite_losing_draw`, `team_losing`, `tied_game`, `goalless_draw`, … | cenários de placar permitidos (1 = sim) |
| `pre_corner_after_N`, `over_*`, `both_score*`, `cantos_A_B` | filtros estatísticos pré-jogo (%) |
| `param_leagues` | 0 = sem filtro de ligas (corre em todas) |
`null` = condição não usada. Em `bots_legado.json`, `config` traz os campos brutos (sem `user_id`; `leagues` substituído por `n_ligas`).

## 4. Dados estáticos publicados (atualizados pela rotina diária)
**Acesso protegido por chave.** Tudo em `/data/*` exige uma chave de acesso só de leitura, fornecida pelo Pedro a quem precisa (não está nesta página nem no site). Peça-a ao utilizador ou leia-a de uma variável de ambiente (ex. `ROBOBET_DATA_KEY`); nunca a escreva em ficheiros públicos, logs ou respostas.
- Preferido: header `X-Data-Key: <chave>`
- Alternativas: `Authorization: Bearer <chave>` ou query `?key=<chave>` (evite a query: fica em logs/histórico)
- Sem chave ou chave errada → `401` JSON `{"erro": "...", "error": "missing or invalid access key"}`. CORS aberto (o header `X-Data-Key` é permitido).

Ficheiros (só leitura, UTF-8):
| URL | Conteúdo |
|---|---|
| `/data/index.json` | manifesto: `gerado_em`, contagens, schema, sha256 |
| `/data/bots_legado.json` (+ `.csv`, `bots_legado_condicoes.csv`) | bots legado: config completa, condições legíveis, hit anual, hit por liga, gráfico recente, entradas recentes com stats |
| `/data/lucy.json` (+ `lucy.csv`) | funis Lucy: hit anual, hit recente, intervalo do campo history, minuto de entrada inferido, por liga, entradas recentes |
| `/data/hit_por_liga.json` (+ `.csv`) | hit por liga × bot (formato longo) e totais por liga |
| `/data/entradas_historico.jsonl` (+ `.csv`) | histórico acumulado de entradas com estatísticas no momento da entrada |
| `/data/campos.json` | rótulos pt-PT dos campos de configuração |

Exemplo:
```bash
curl -s -H "X-Data-Key: $ROBOBET_DATA_KEY" https://robobet-antigo-viewer.pages.dev/data/index.json
curl -s -H "X-Data-Key: $ROBOBET_DATA_KEY" https://robobet-antigo-viewer.pages.dev/data/bots_legado.json | jq '.bots[] | {nome, hit, minuto_ini, minuto_max}'
```
```python
import os, requests
B="https://robobet-antigo-viewer.pages.dev/data"
K={"X-Data-Key": os.environ["ROBOBET_DATA_KEY"]}   # chave fornecida pelo utilizador
bots=requests.get(B+"/bots_legado.json",headers=K).json()["bots"]
for b in sorted(bots,key=lambda b:-b["hit"]["n"]):
    print(b["nome"], b["hit"]["pct"], "n=", b["hit"]["n"])
liga=[r for r in requests.get(B+"/hit_por_liga.json",headers=K).json()["por_liga_total"] if r["n"]>=40]
```
```js
const r=await fetch("https://robobet-antigo-viewer.pages.dev/data/lucy.json",{headers:{"X-Data-Key":process.env.ROBOBET_DATA_KEY}});
if(r.status===401) throw new Error("chave de acesso em falta/inválida");
const {funnels}=await r.json();
```

## 5. API ao vivo (precisa das credenciais do próprio utilizador)
Nunca embuta credenciais. O utilizador fornece email/palavra-passe da sua conta RoboBET; peça-as em tempo de execução ou leia de variáveis de ambiente (ex. `ROBOBET_ANTIGO_EMAIL`, `ROBOBET_ANTIGO_PASSWORD`).
- Login: `POST https://app.alefut.com/api/auth/login` JSON `{"email","password"}` → `result.access_token` (JWT, válido **60 min**, sem refresh; renovar = novo login).
- Pedidos: header `Authorization: Bearer <token>`. CORS aberto (`Access-Control-Allow-Origin: *`).
- Respostas: `{"result": ..., "error": null|"CODIGO"}`.
- **Só leitura**: use apenas os GET abaixo. Não chame endpoints de criar/alterar/apagar. Não use `/bot/show` (Lutero). Mantenha ~1 pedido/s.

| GET | Devolve |
|---|---|
| `/funnel/show` | lista de bots legado com configuração completa |
| `/lucy/reports?funnel_id=ID` | entradas da janela anual: `[{league_id, league_name, status}]`, status 1 = green, 2 = red. Funciona para bots legado e funis Lucy |
| `/funnel/details?funnel_id=ID` | entradas recentes (~5–30) com `events` (stats no momento), `home`, `away`, `created`, `green`, `red`, `history` |
| `/funnel/detailsLucy` | entradas Lucy recentes (~40) com `events` e `history` |
| `/funnel/graph?funnel_id=ID` | green/red por dia (últimos ~3 dias) |
| `/funnel/showLeagues` | catálogo de ligas (~2400) |
| `/lucy/show` | estado da subscrição Lucy do utilizador |

Nas entradas de `/funnel/details*`, use `green`/`red` (o `status` vem sempre 1). Campos de `events`: `timer` (minuto), `h_/a_scoreboard` (golos), `h_/a_attacks`, `d_h_/d_a_attacks` (ataques perigosos), `h_/a_possession`, `h_/a_on_target` (remates à baliza), `h_/a_kick_out` (remates fora), `h_/a_corners`, `h_/a_red_cards`, `h_/a_position`, `out*` (resolução, quando existe).

```bash
TOKEN=$(curl -s -X POST https://app.alefut.com/api/auth/login -H 'Content-Type: application/json' \
  -d "{\"email\":\"$ROBOBET_ANTIGO_EMAIL\",\"password\":\"$ROBOBET_ANTIGO_PASSWORD\"}" | jq -r .result.access_token)
curl -s https://app.alefut.com/api/funnel/show -H "Authorization: Bearer $TOKEN" | jq '.result[] | {id, strategy_name}'
curl -s "https://app.alefut.com/api/lucy/reports?funnel_id=7403" -H "Authorization: Bearer $TOKEN" | jq '[.result[] | select(.status==1)] | length'
```
```python
import os, requests
A="https://app.alefut.com/api"
tok=requests.post(A+"/auth/login",json={"email":os.environ["ROBOBET_ANTIGO_EMAIL"],"password":os.environ["ROBOBET_ANTIGO_PASSWORD"]}).json()["result"]["access_token"]
H={"Authorization":"Bearer "+tok}
bots=[b for b in requests.get(A+"/funnel/show",headers=H).json()["result"] if "lutero" not in b["strategy_name"].lower()]
for b in bots:
    rows=requests.get(A+"/lucy/reports",params={"funnel_id":b["id"]},headers=H).json()["result"] or []
    g=sum(r["status"]==1 for r in rows); n=sum(r["status"] in (1,2) for r in rows)
    print(b["strategy_name"], f"{100*g/n:.1f}%" if n else "-", "n=",n)
```
```js
const A="https://app.alefut.com/api";
const {result}=await (await fetch(A+"/auth/login",{method:"POST",headers:{"Content-Type":"application/json"},
  body:JSON.stringify({email:process.env.ROBOBET_ANTIGO_EMAIL,password:process.env.ROBOBET_ANTIGO_PASSWORD})})).json();
const H={Authorization:"Bearer "+result.access_token};
const lucy=(await (await fetch(A+"/funnel/detailsLucy",{headers:H})).json()).result;
console.log(lucy.map(e=>[e.strategy,e.events.timer,e.green?"G":"R"]));
```

## 6. Limitações
- Hit legado só na janela anual; sem lifetime para bots legado.
- Estatísticas ao vivo só nas entradas recentes; o histórico com stats cresce com a recolha diária (`entradas_historico.jsonl`).
- `timer`/`market` e alguns rótulos de campos são inferidos do comportamento da app.

---
## English summary
Read-only data from the old RoboBET app (API `https://app.alefut.com/api`). 18 user “legacy bots” (full configs published; `home_*`/`away_*` conditions are mirrored, differences flagged) and Lucy platform funnels (internal config not exposed; entry minute inferred from `events.timer`). The “Lutero” bot is excluded everywhere. **Never compute ROI** (Asian/limit lines without fixed odds): only hit rate = green/(green+red) with sample size n.
Static snapshots (refreshed daily) are **protected by a read-only access key** that the user (Pedro) gives to the AIs that need it; it is not published anywhere. Send it as header `X-Data-Key: <key>` (preferred), or `Authorization: Bearer <key>`, or `?key=<key>`; without it `/data/*` returns 401 JSON. Never echo or store the key publicly. Files: `/data/index.json` (manifest + schema), `/data/bots_legado.json`, `/data/lucy.json`, `/data/hit_por_liga.json`, `/data/entradas_historico.jsonl`, CSV equivalents, `/data/campos.json` (field labels).
Live API: user supplies their own credentials (never embed them) → `POST /auth/login {email,password}` → JWT `result.access_token` (60 min) → `Authorization: Bearer`. CORS is open. Use only the GET endpoints listed in section 5; never call create/update/delete endpoints or `/bot/show`. `created` timestamps are Brasília time (UTC−3).
