docs: update README with Phase 2 features and architecture details

Refresh project description, tech stack table, and add comprehensive
Phase 2 section documenting the playable 3D world, traffic system,
pedestrians, plazas, beach activities, and AI agents.
This commit is contained in:
2026-10-31 20:40:11 -03:00
parent b8c31e7be4
commit a12807492f
+144 -20
View File
@@ -1,10 +1,12 @@
# City10 — Cidade 3D Virtual com Agentes de IA
**City10** é uma plataforma full-stack de simulação urbana 3D com agentes de
inteligência artificial autônomos, construída sobre **Laravel 13** e **Three.js**.
Agentes (Prefeito, pedestres, lojistas) tomam decisões estratégicas em tempo real
através da API [OpenRouter.ai](https://openrouter.ai), restrita a uma lista de
modelos gratuitos.
inteligência artificial, construída sobre **Laravel 13** e **Three.js**. O
visualizador3D é jogável no navegador: trânsito semafórico, pedestres, agentes
(Prefeito, lojistas), conversas de rua com IA, praças com academia e uma praia
com lazer. O raciocínio dos NPCs acontece através da API
[OpenRouter.ai](https://openrouter.ai), restrito a uma lista de modelos
gratuitos.
> Plataforma operada pela **Syspanel** — Santa Rita do Sapucaí/MG, Brasil.
> Contato: [contato@syspanel.com.br](mailto:contato@syspanel.com.br) ·
@@ -17,15 +19,15 @@ modelos gratuitos.
| Camada | Tecnologia | Responsabilidade |
|---|---|---|
| Backend / Painel Admin | Laravel 13 (PHP ≥ 8.3) | Autenticação, API REST, regras de negócio, consentimento LGPD |
| Banco de Dados | MariaDB (MySQL) | Persistência de usuários, lojas, agentes e consentimentos |
| Cache / Fila | Redis / Database | Sessões, cache e jobs |
| Frontend 3D | Three.js (Fase 2+) | Renderização da cidade no navegador |
| Tempo Real | Laravel Reverb (planejado) | Sincronização de estado entre clientes |
| Cérebro dos Agentes | OpenRouter.ai | Raciocínio dos NPCs com modelos gratuitos |
| Banco de Dados | MariaDB (MySQL) | Persistência de usuários, lojas, agentes, conversas e consentimentos |
| Cache / Fila | Database (sessões/cache/jobs) | Sessões, cache, agendamentos e throttle |
| Frontend 3D | Three.js | Mundo jogável no navegador (cidade, trânsito, praia, clima) |
| Tempo Real | Polling HTTP + SSE | Presence (~2,5 s), chat (~2,5 s) e stream de resposta de NPC (SSE) |
| Cérebro dos Agentes | OpenRouter.ai | Raciocínio dos NPCs e conversas com modelos gratuitos |
---
## Fase 1 (Atual) — Entregue
## Fase 1 — Plataforma (Entregue)
- Estrutura Laravel 13 com autenticação diferenciada (**Admin** / **Usuário Comum**).
- **Migrations**: usuários com `role`, lojas com coordenadas 3D (`pos_x`, `pos_y`, `pos_z`), agentes de IA e trilha de consentimento legal (LGPD).
@@ -38,6 +40,79 @@ modelos gratuitos.
---
## Fase 2 — Mundo 3D Jogável (Entregue)
O visualizador `/city` carrega o mundo completo em tempo real:
- **Cidade de 72 quarteirões** (grade 9 × 8 de blocos de 40 m; bounds
`−120..160 × −120..120`), com rio e ponte a oeste, extensão rodoviária ao
norte, hospital, escola, prefeitura e casas de jogadores.
- **Trânsito**: carros, motos, bikes e ônibus com tráfego à direita, loop por
quarteirão e **semáforos por cruzamento** (fases NS/EW com amarelos e
all-red; veículos param na linha de parada **antes** das faixas).
- **Faixas zebradas reais** (barras longitudinais paralelas ao fluxo, design
MUTCD) com calçadas e meio-fios interrompidos nas travessias — 323 faixas no
layout atual.
- **Pedestres** com travessia sincronizada ao semáforo; bloqueio de travessia
do jogador no vermelho.
- **Praças** (1 a cada 4 células) com academia externa: exercícios com pose,
efeito em saúde/energia e missão “Shape em dia”.
- **Praia a leste** (`/city` + `App\Support\Beach`): areia, mar com ondas
animadas (deslocamento de vértices), espuma na orla, **banhistas, nadadores,
surfistas, salva-vidas (torre + patrulha), quadra de basquete com jogadores
e bola em arremesso, barracas de comidas, cadeiras e guarda-sóis**.
O jogador pode **relaxar na areia** (tecla `E` → `POST /city/actions/beach`),
recuperando energia/saúde por tick até o máximo.
- **Agentes vivos**: prefeito itinerante, lojistas nas lojas, pedestres com
rotas, mais trens (passagem de nível com barreiras), ônibus/trem
embarcáveis, avião e barcos no rio.
- **Dia/noite e clima** com ciclo de horas, névoa, chuva e sombras que seguem
o jogador.
- **Conversas de rua** com outros jogadores e NPCs (ver próxima seção).
- **Performance**: *batching* estático por material, sombra seguindo o
jogador (janela ±120), lâmpadas/rodas com LOD por distância e fachadas a
256 px — medições ~30–60 fps numa GTX 770.
### Controles
| Controle | Ação |
|---|---|
| `W A S D` | Andar (A/D = lateral) |
| Mouse (pointer lock) | Olhar; **arrastar na cena** quando sem lock |
| `←` `→` | **Viram a câmera** (não andam de lado) |
| Joystick virtual (mobile) | Vertical = andar, horizontal = **virar a câmera** |
| `E` | Contexto: exercício na praça / relaxar na praia / parar |
| `Espaço` | Pular |
| Clique num NPC | Abrir chat |
| Chegar perto de alguém | Chat abre sozinho; sai de perto ele fecha |
---
## Conversas de Rua (`/talk/person`) e IA por Personagem
- **Registro por dia**: cada fala gravada em `person_talks`
(`from/to` de character ou agent + `talked_on` + `is_fallback`), consultável
via `GET /talk/person?kind=agent|character&peer=ID`.
- **Fio da meada**: o histórico completo (dias anteriores + hoje) é enviado
como contexto nas respostas de IA — placeholders de erro (`is_fallback`)
ficam visíveis na UI mas **nunca** entram no contexto do modelo.
- **Quem responde**:
- Par com **humano vivo** (sessão tocada nos últimos 5 min) → relay puro,
nunca é substituído por IA;
- Par **sem humano** (cidadãos demo, NPCs) → persona anônima de morador
responde via OpenRouter, sem dados cadastrais no payload.
- **Resposta de IA** é gerada *after-response* (não depende de worker de
fila), com espaçamento por par, allow-list de modelos, fallback localizado
em falha e auditoria em `last_decision`.
- **Identidade por personagem**: colunas em `characters` — `ai_model`,
`ai_age`, `ai_gender`, `ai_personality`, `ai_bio` (persona injetada no
prompt; recém-criados já nascem com personalidade/idade).
- **Modelo por personagem** (ordem de resolução, sempre validado em
`allowed_models`): coluna `ai_model` → mapa `AI_CHARACTER_MODELS` (id ou
nome) → slot determinístico do pool `AI_MODELS` → `AI_DEFAULT_MODEL`.
---
## Requisitos
- PHP **≥ 8.3** (com `pdo_mysql`, `mbstring`, `curl`, `zip`, `gd`, `bcmath`)
@@ -74,13 +149,20 @@ DB_USERNAME=root
DB_PASSWORD=<sua_senha>
```
### 3. Chave do OpenRouter.ai
### 3. Chave do OpenRouter.ai e modelos
A chave **não** é versionada. Insira-a apenas no `.env` local:
```env
OPENROUTER_API_KEY=<sua_chave>
AI_DEFAULT_MODEL=deepseek/deepseek-v4-flash-0731
# Pool de modelos gratuitos distribuídos deterministicamente entre os
# personagens (cada um mantém o próprio modelo estável).
AI_MODELS=deepseek/deepseek-v4-flash-0731,nvidia/nemotron-3.5-lightning:free,liquid/lfm-2.5-2.6b:free,openrouter/free,nvidia/nemotron-3-ultra-550b-a55b:free
# Override por personagem: "nome ou id=modelo" separado por vírgula.
AI_CHARACTER_MODELS=
```
### 4. Banco de dados
@@ -122,9 +204,24 @@ docker exec -it dockercity10 bash -c "cd /app && php artisan migrate --seed"
---
## Testes
```bash
php artisan test # suíte completa (PHPUnit)
./vendor/bin/pint # formatação de código
```
Destaques da suíte (testes de recurso): autenticação/LGPD, ações da cidade
(exercício, posição com clamp até a orla da praia), social, mercado,
missões, **conversas de rua** (`PersonTalkTest` — histórico multidiário,
resolução de modelo, ausência de PII no payload) e **lazer na praia**
(`BeachLeisureTest` — geometria no payload, efeitos e zona).
---
## Estrutura de Endpoints da API
Base URL: `http://localhost:16980/api`
Base URL: `http://localhost:16980/api` (Bearer Sanctum)
### Públicos
@@ -145,26 +242,48 @@ Base URL: `http://localhost:16980/api`
| GET | `/city/world` | Snapshot da cidade (lojas + agentes com coordenadas 3D) |
| GET/POST | `/stores` | Lista/cria lojas |
| GET/PUT/DELETE | `/stores/{id}` | Gerencia uma loja (dono ou admin) |
| GET | `/stores-world/seed` | Mundo de lojas (seed 3D) |
| GET | `/legal/status` | Status de aceite dos documentos |
| POST | `/legal/accept` | Registra o aceite (auditoria LGPD) |
| GET | `/legal/history` | Histórico de consentimentos do usuário |
### Somente Administrador (`/admin`)
### Somente Administrador
| Método | Rota | Descrição |
|---|---|---|
| GET/POST | `/admin/users` | Lista/cria usuários |
| GET/PUT/DELETE | `/admin/users/{id}` | Gerencia usuários |
| GET/POST | `/admin/agents` | Lista/cria agentes de IA |
| GET/PUT/DELETE | `/admin/agents/{id}` | Gerencia agentes |
| GET | `/admin/agents-meta/models` | Lista os modelos gratuitos permitidos |
| CRUD | `/api/users` | Gestão de usuários |
| CRUD | `/api/agents` | Gestão de agentes de IA |
| GET | `/api/agents-meta/models` | Lista os modelos gratuitos permitidos |
| GET | `/api/agents-world/seed` | Mundo de agentes (seed 3D) |
| GET/POST | `/stores`, `/citizens`, `/cities`, `/world` | Admin web (aprovação de cidadãos, cidades, mundo) |
---
## Rotas Web da Cidade (sessão de navegador)
Todas exigem login + termos aceitos.
| Método | Rota | Descrição |
|---|---|---|
| GET | `/city` | Visualizador 3D (HTML + bundle Three.js) |
| GET | `/city/data` | Payload do mundo: layout, lojas, agentes, praças, prédios, `beach` |
| GET | `/city/presence` | Cidadãos online (posições, `is_me`) — throttle 60/min |
| GET/POST | `/talk/person` | Conversas de rua: histórico/contexto e envio (throttle 120 e 30/min) |
| POST | `/city/actions/position` | Sincroniza posição (clamp até a orla da praia) |
| POST | `/city/actions/{action}` | Ações: `eat`, `drink`, `sleep`, `wake`, `work`, `study`, `buy`, `sell`, `build`, `apply-job`, `exercise`, `stop-exercise`, `beach`, `ride`, `accident`… |
| POST/GET | `/city/chat/{agent}` (+`/stream`) | Conversa com NPC (envio + SSE de resposta) |
| POST/GET | `/city/messages/{character}` | Mensagens assíncronas entre personagens |
| POST | `/city/social/{verb}` · GET `/city/social/inbox` | Amizade, casamento, filho, inbox |
| GET/POST | `/city/market` (`/buy`, `/sell`) | Mercado |
| GET/PUT | `/city/customize` | Personalização do personagem |
---
## Modelos de IA Permitidos
Somente os modelos **gratuitos** abaixo podem ser atribuídos a agentes
(validado no backend em `config/ai.php`):
Somente os modelos **gratuitos** abaixo podem ser usados (validado no backend
em `config/ai.php`; os quatro últimos foram verificados ao vivo no catálogo do
OpenRouter):
```
poolside/laguna-m.1:free cohere/north-mini-code:free
@@ -176,6 +295,8 @@ nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free
nvidia/nemotron-3-nano-30b-a3b:free nvidia/nemotron-nano-9b-v2:free
poolside/laguna-xs-2.1:free inclusionai/ling-3.0-flash-vl:free
qwen/qwen3.7-flash:free
deepseek/deepseek-v4-flash-0731 nvidia/nemotron-3.5-lightning:free
liquid/lfm-2.5-2.6b:free openrouter/free
```
---
@@ -191,6 +312,9 @@ qwen/qwen3.7-flash:free
- **Banner de cookies** com opção de aceitar/recusar cookies não essenciais.
- **Direitos do titular** (art. 18 LGPD): histórico de consentimentos disponível
ao usuário; contato para exercer direitos: `contato@syspanel.com.br`.
- **IA sem PII**: ao chamar o OpenRouter envia-se apenas contexto simulado da
cidade e o diálogo/identidade in-world — nunca e-mail, senha ou dados de
conta (regras em [`RULES.md`](RULES.md), seção 2).
---