Files
City10/README.md
T
marcocosta10000 a12807492f 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.
2026-10-31 20:40:11 -03:00

343 lines
14 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# City10 — Cidade 3D Virtual com Agentes de IA
**City10** é uma plataforma full-stack de simulação urbana 3D com agentes de
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) ·
> WhatsApp: (35) 99226-1684 · [www.syspanel.com.br](https://syspanel.com.br)
---
## Visão Geral da Arquitetura
| 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, 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 — 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).
- **API REST** (Sanctum) para usuários, lojas, agentes, cidade e documentos legais.
- **CAPTCHA matemático** próprio (soma), sem dependências externas, nos formulários públicos.
- **Multi-idioma**: Português (Brasil), Inglês e Espanhol — selecionável pelo usuário.
- **Termos de Uso, Política de Privacidade e Política de Cookies** (LGPD), versionados e com aceite auditável (data, hora, versão, IP).
- **Banner de cookies** com link para os Termos de Uso e Privacidade.
- **Página inicial** responsiva (desktop e smartphone).
---
## 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`)
- Composer 2
- MariaDB ≥ 10.6 (ou MySQL ≥ 8.0)
- Node.js ≥ 18 (apenas para assets Vite/Tailwind, opcional na Fase 1)
- Docker (opcional, para o ambiente `dockercity10`)
---
## Instalação
### 1. Dependências PHP
```bash
composer install
```
### 2. Configuração do ambiente
```bash
cp .env.example .env
php artisan key:generate
```
Edite o `.env` e configure o banco de dados:
```env
DB_CONNECTION=mariadb
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=<sua_senha>
```
### 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
```bash
php artisan migrate --seed
```
### 5. Servidor de desenvolvimento
```bash
php artisan serve --port=16980
```
A aplicação ficará disponível em `http://localhost:16980`.
### Ambiente Docker (dockercity10)
O container `dockercity10` já expõe a aplicação na porta do host **16980**
(container `:80`, Apache + PHP-FPM) e o MariaDB na porta **16981**. Após clonar
o projeto em `/app` (bind-mount), rode as migrations dentro do container:
```bash
docker exec -it dockercity10 bash -c "cd /app && php artisan migrate --seed"
```
---
## Contas de Teste (ambiente de desenvolvimento)
| Papel | E-mail | Senha |
|---|---|---|
| Administrador | `marcocosta@gmx.com` | `Mega886ax` |
| Usuário Comum | `user@sistema.net` | `User123` |
> ⚠️ Estas credenciais são exclusivas para desenvolvimento. Altere-as ou
> remova-as (`php artisan db:seed --class=UserSeeder` após ajustar) antes de
> qualquer implantação em produção.
---
## 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` (Bearer Sanctum)
### Públicos
| Método | Rota | Descrição |
|---|---|---|
| GET | `/auth/captcha` | Gera desafio matemático (necessário para login/registro) |
| POST | `/auth/login` | Autentica e emite token Sanctum |
| POST | `/auth/register` | Cria conta de usuário comum |
| GET | `/legal/documents` | Lista a versão atual dos documentos legais |
### Autenticados (Bearer token)
| Método | Rota | Descrição |
|---|---|---|
| GET | `/auth/me` | Perfil + status de consentimento |
| PATCH | `/auth/profile` | Atualiza nome, idioma ou senha |
| POST | `/auth/logout` | Revoga o token atual |
| 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
| Método | Rota | Descrição |
|---|---|---|
| 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 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
deepseek/deepseek-v4-flash-0731:free qwen/qwen3.8-27b:free
nvidia/nemotron-3-ultra-550b-a55b:free nvidia/nemotron-3-super-120b-a12b:free
google/gemma-4-31b-it:free google/gemma-4-26b-a4b-it:free
openai/gpt-oss-20b:free nvidia/nemotron-nano-12b-v2-vl:free
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
```
---
## Segurança e Conformidade (LGPD)
- **Senhas** armazenadas com bcrypt (cast `hashed`).
- **Tokens de API** (Sanctum) revogáveis por usuário.
- **RBAC**: papéis `admin` / `user` com middleware dedicado.
- **CAPTCHA matemático** nos formulários públicos (login/registro).
- **Consentimento auditável**: data, hora, versão do documento, IP e user-agent
gravados em `user_consents` (imutáveis).
- **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).
---
## Licença
Software **Proprietário** — © 2026 Syspanel. Todos os direitos reservados.
Veja o arquivo [`LICENSE`](LICENSE) para os termos completos de uso.
Bibliotecas de terceiros utilizadas são compatíveis com uso comercial
(por exemplo: Laravel — MIT; Three.js — MIT). O crédito aos autores originais
está registrado em [`RULES.md`](RULES.md).
---
## Contato
- **E-mail**: [contato@syspanel.com.br](mailto:contato@syspanel.com.br)
- **WhatsApp**: (35) 99226-1684
- **Site**: [www.syspanel.com.br](https://syspanel.com.br)
- **Localização**: Santa Rita do Sapucaí — Minas Gerais — Brasil
---
© 2026 — Todos os direitos reservados — Powered by
[Syspanel](https://syspanel.com.br) — www.syspanel.com.br