ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
Bichu는 실제 동물 소리와 이름, 흥미로운 정보와 놀이를 통해 동물을 알아보는 어린이용 앱, 광고·개인 데이터 없음
Bichu: app infantil para descobrir os animais com sons reais, nomes, curiosidades e brincadeiras. Sem anúncios e sem dados pessoais.
교육TypeScript · JavaScriptGitHub @mxczpiscioneri온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Descubra o mundo animal.
Bichu é um app infantil (≈ 2–8 anos) de descoberta do mundo animal, reescrito em React Native + Expo + TypeScript a partir do antigo Zoo Babies / AnimalSounds. A criança vê um animal, ouve o nome e a silabação gravados, ouve o som real, conhece fatos simples, completa desafios e adiciona o animal à Bichupédia. A realidade aumentada é um complemento experimental — o app funciona completo sem ela.
| Boas-vindas | Início | Explorar | Animal | Que animal é esse? |
|---|---|---|---|---|
| O que ele come? | Muito bem! | Onde ele vive? | Modo | Bichupédia |
Documentação de produto, marca e conteúdo do handoff:
docs/PRODUCT.md,docs/TECHNICAL.md,docs/BRAND.md,docs/CONTENT_MODEL.md.
Requisitos: Node 20+ (testado com 22) e npm.
O app usa development build (expo-dev-client); o Expo Go não é suportado.
npm install
npm run ios # expo run:ios — compila e abre no simulador iOS (precisa de Xcode)
npm run android # expo run:android — precisa de Android Studio
npx expo start # só o Metro, para um development build já instalado
Sem Xcode/Android Studio, gere o development build na nuvem com EAS (seção abaixo).
Todo o conteúdo (22 animais, imagens, sons, locuções) já está no repositório. Não há backend, conta, banco remoto nem internet obrigatória.
| Comando | O que faz |
|---|---|
npm run validate | lint + typecheck + validação de conteúdo + testes (use antes de abrir PR) |
npm run validate:content | valida seed, templates, manifesto legado e registro de mídia |
npm test | testes de domínio (Jest) |
npm run lint / npm run typecheck | ESLint (expo lint) / tsc --noEmit |
npm run format | Prettier |
npm run assets:fetch | baixa os assets legados e regenera o registro de mídia |
npm run assets:registry | regenera src/content/media.generated.ts a partir do seed |
Projeto EAS: @mxczpiscioneri/bichu · bundle id / package br.com.techhands.bichu · Apple Team GD2JNB5JH9. Perfis em eas.json:
| Perfil | Uso | AR (BICHU_AR) | Canal de update |
|---|---|---|---|
development | Dev Client em aparelho | sim | development |
development-simulator | Dev Client no simulador iOS | não (ViroKit só tem binário para aparelho) | development |
preview | build interno para testes | sim | preview |
production | lojas (versão incrementada no EAS) | não | production |
npx eas-cli@latest build --profile development-simulator --platform ios
npx eas-cli@latest build --profile production --platform all
npx eas-cli@latest update --channel preview --message "…"
⚠️ Privacidade: updates OTA (expo-updates, runtimeVersion = versão do app) consultam u.expo.dev ao abrir o app — a única chamada de rede do Bichu. A requisição leva plataforma, versão/canal e um EAS-Client-ID (UUID aleatório e persistente por instalação, gerado pelo expo-updates); nenhum dado da criança. Sem internet o app funciona normalmente com o bundle embutido. Avaliar esse identificador na política de privacidade antes de publicar.
A AR é um spike isolado com ViroReact (@reactvision/react-viro) sobre ARKit/ARCore. Ela é opt-in em tempo de build: sem BICHU_AR=1, o plugin do Viro não roda, o módulo nativo não é linkado (react-native.config.js) e o app não pede câmera.
npm run run:ios:ar # BICHU_AR=1 expo run:ios (aparelho físico com ARKit)
npm run run:android:ar # BICHU_AR=1 expo run:android (aparelho com ARCore)
npm run start:ar # Metro para o Dev Client com AR habilitado
Fluxo do spike (app/ar/[animalId].tsx): abre a câmera → detecta um plano horizontal → “Encontrei um lugar!” → toque posiciona um animal → girar (dois dedos), escala limitada por pinça (0,5×–2× do defaultScale) e arrastar sobre o plano → nome, som e desafio acontecem na UI 2D ao redor, usando o mesmo Challenge Engine do app. Sem física, andar ou comer.
Modelos 3D: os 22 animais têm GLB em assets/animals/models/ (Quaternius CC0 + Poly by Google CC BY 3.0; relatório em docs/3D_ASSET_REPORT.md, créditos em docs/3D_ATTRIBUTIONS.md). Por ora só os 5 do spike técnico — leão, elefante, cavalo, golfinho e papagaio — estão ligados no seed (media.model3d); nos demais o botão “Ver no meu mundo” continua oculto até o spike ser confirmado em aparelho. ⚠️ Os modelos CC BY exigem uma tela de créditos no app antes de publicar.
Segurança na AR (Política para Famílias do Google Play): ao entrar em realidade aumentada, o Bichu exibe um aviso de segurança pedindo supervisão de um adulto e atenção ao ambiente. A câmera só é solicitada depois de tocar em "Entendi, continuar". O AR usa apenas ARKit/ARCore no próprio aparelho (xRMode: ['AR']), sem exigir headsets como Daydream ou Oculus.
Privacidade na AR: só a permissão de câmera é declarada; o plugin plugins/withChildPrivacy.js remove as descrições de microfone, fotos e localização que o Viro adiciona por padrão. Nenhuma imagem é salva ou enviada.
As 22 imagens, 22 sons reais e 22 locuções de nome (“Elefante. E-le-fan-te.”) vêm de mxczpiscioneri/AnimalSounds, mapeados em legacy/ASSET_MANIFEST.json.
npm run assets:fetch # baixa apenas o que falta
npm run assets:fetch -- --force # baixa tudo de novo
O script (scripts/fetch-legacy-assets.ts) baixa somente os arquivos do manifesto (nunca keystore.jks, google-services.json ou arquivos de build), confere a assinatura PNG/MP3, grava legacy/ASSET_CHECKSUMS.json, gera reports/asset-report.md e sai com erro se algo faltar. Também importa o som de acerto do app antigo (discover_win.mp3 → assets/ui/sounds/correct.mp3).
⚠️ Antes de publicar: legacy/ASSET_RIGHTS_CHECKLIST.md. Estar num repositório público não é licença comercial.
As ilustrações antigas (circulares) estão sendo trocadas por artes de corpo inteiro com fundo transparente. As duas convivem: cada animal usa a nova assim que ela existe (media.imageStyle: "cutout") e a antiga ("badge", em medalhão) até lá. Com arte nova, o animal aparece em pé sobre o cenário e, na Bichupédia, os ainda não descobertos viram silhueta.
Para adicionar ou trocar uma arte:
assets/animals/art/<id>.png: PNG quadrado (768×768), fundo transparente, animal inteiro com margem de ~5% e patas na mesma linha de base dos outros.npm run assets:art. O comando aponta o seed para a arte nova, regenera o registro de mídia, confere se o PNG é quadrado e transparente e lista quem ainda está com a ilustração antiga.npm run validate.assets/animals/images/<id>.png, assets/animals/sounds/<id>.mp3, assets/animals/names/<id>_name.mp3.content/animals/legacy-seed.json (schema: content/animals/animal.schema.json). Campos que merecem atenção:
name.article ("o"/"a") — monta “O que o leão come?”.name.syllables — precisam formar o nome (validado).foods, habitats, locomotion… usam as taxonomias fechadas de src/domain/taxonomy.ts.soundGroup — se o som puder ser confundido com outro animal (ex.: "roar" para leão/tigre/urso).challengeFlags — desligue (false) qualquer desafio cuja resposta seria ambígua para esse animal (ex.: “urso” genérico não tem dieta única → food: false).npm run assets:registry e npm run validate.Coleções (Explorar e Bichupédia) são filtros declarativos em src/content/collections.ts: o novo animal entra automaticamente nas que combinarem.
tools/3d-pipeline/ (metros, frente em +Z, pivô no chão, texturas ≤ 1024 px, sem Draco/Meshopt/KTX2 — o ViroReact não lê) e salve em assets/animals/models/<id>.glb. Registre fonte e licença em assets/animals/models/models.json e docs/3D_ATTRIBUTIONS.md."media": {
"model3d": "assets/animals/models/lion.glb",
"model3dMeta": {
"license": "CC0-1.0",
"author": "Nome do autor",
"sourceUrl": "https://…",
"defaultScale": 1,
"realWorldHeightMeters": 1.356,
"groundOffset": 0,
"animations": []
}
}
license e author são obrigatórios (a validação falha sem eles). Os GLBs estão em metros e realWorldHeightMeters define a escala inicial: o animal aparece em tamanho real quando tem entre 25 cm e 1 m de altura e é ampliado ou reduzido até esse limite fora disso (src/ar/scale.ts); defaultScale só é usado se a altura não for informada. Animações são opcionais e nunca exigidas.npm run assets:registry && npm run validate, depois rode um build com BICHU_AR=1.Os desafios são gerados a partir dos dados — não há perguntas escritas por animal.
content/challenges/templates.json (id, interaction, title, subtitle, icon, levels, prompt, hint, explanation). Tokens: {animal} (o leão), {Animal} (O leão), {deAnimal} (do leão), {answer}. Interações:
tap — toca numa alternativa (cartões grandes);drag — arrasta a alternativa até o animal (ex.: comida);place — arrasta o animal até a alternativa (ex.: habitat, mostrado como cenário).CHALLENGE_TEMPLATE_IDS (src/challenges/types.ts).AttributeRule em src/challenges/rules.ts: correct(animal) (todas as respostas certas), distractors(animal) (apenas respostas seguramente erradas, em ordem de preferência) e label(value). Se não houver distrator seguro, o engine não gera o desafio — nunca gera um distrator plausível.challengeFlags.src/content/labels.ts; ícones novos em assets/ui/icons + src/content/icons.ts.npm run validate — os testes percorrem todos os animais × tipos × níveis verificando invariantes.app/ rotas (Expo Router)
_layout.tsx fontes, hidratação do progresso, Stack
(tabs)/ Início · Explorar · Brincar · Bichupédia (tab bar própria)
animal/[id].tsx tela do animal
challenge/[type].tsx sessão de desafios (tipo, ou type=animal&animalId=…)
ar/[animalId].tsx spike de AR (isolado)
parents.tsx área dos adultos (nível, progresso, privacidade) com parent gate
src/
domain/ tipos e regras puras (Animal, taxonomias, linguagem pt-BR)
content/ loader tipado + validação, rótulos, coleções, ícones, registro de mídia
challenges/ Challenge Engine: templates, regras de distratores, sessões, hook de estado
progress/ regras de progressão puras + seletores
stores/ Zustand persistido em AsyncStorage (progresso, nível)
audio/ AudioService (canal único, fila nome → som)
ar/ carregamento opcional do Viro, cena AR, estado da AR
components/ UI (ui/, brand/, animal/, challenge/, home/, feedback/, parents/)
theme/ tokens de design/theme.json, tipografia, paletas por habitat
content/ seed dos animais, schema, templates de desafio (fonte da verdade)
assets/ animals/{images,sounds,names,models}, brand/, ui/{icons,sounds}
scripts/ importação de assets, registro de mídia, validação de conteúdo
plugins/ config plugin de privacidade infantil (AR)
Princípios aplicados:
domain/, challenges/ e progress/ não importam React; o RNG é injetado (sessões determinísticas nos testes).useChallengeSession é usado pela tela 2D e pelo overlay da AR.require() estáticos, então src/content/media.generated.ts é gerado a partir do seed (e a validação acusa se estiver desatualizado). Nenhum caminho de asset espalhado pelas telas.preschool) e Aventureiro (3 alternativas, fatos kids, desafio de classe). Mesmo app: o modo é escolhido no primeiro uso (“Como você quer explorar hoje?”) e depois na Área dos pais (engrenagem), que também tem o liga/desliga do som.plants nunca recebe grass como errado; onívoros só recebem néctar), habitats agrupados por paisagem (com paisagens vizinhas bloqueadas: savana ↔ floresta), locomoção só com opções claramente erradas (aves nunca recebem “voando” como errado; foca nunca recebe “rastejando”), sons confundíveis nunca juntos (soundGroup). Quando faltam distratores seguros, a pergunta fica com menos alternativas.A interface segue o mockup de referência das telas: cenários de habitat ilustrados, animal em destaque, cartões grandes, botões de áudio redondos (verde = nome, laranja = som), tela cheia de acerto com o Bichu e barra inferior simples.
assets/ui/icons, componente Icon) para conteúdo e navegação. Só o alto-falante branco dos botões redondos e as setinhas continuam em traço SVG (LineIcon), porque precisam mudar de cor.assets/habitats/ (10 imagens 4:3: savana, campo, deserto, floresta, montanhas, oceano — também usado para praia —, rio/brejo, fazenda, casa e cidade), mapeados em src/components/ui/HabitatScene.tsx. O cenário de cada animal vem do seu primeiro habitat; as imagens são cortadas para caber, então o assunto deve ficar no centro.A documentação do handoff é a fonte primária. Pequenas inconsistências encontradas e como foram resolvidas:
| Ponto | Decisão |
|---|---|
foods do seed tinha valores fora da lista do TECHNICAL (squid, hay, bark, prepared_food…) | Taxonomia fechada de 20 alimentos em 6 famílias (src/domain/taxonomy.ts); a validação rejeita valores fora dela. |
Templates usavam {animal} sem artigo (“O que leão come?”, “filhotes de o leão”) | name.article no seed + tokens {Animal}/{deAnimal}; templates v2 com title, subtitle, icon e explanation. |
| “Distractors must come from the same taxonomy” vs. “never mark plausible as wrong” | Regras por tipo em rules.ts com famílias/paisagens/tabelas por dieta; o engine reduz alternativas em vez de arriscar um distrator plausível. |
| “Que animal é esse?” podia juntar pintinho/galinha/galo ou leão/tigre | Campo opcional soundGroup (e parentAnimalId) exclui sons confundíveis. |
| Botão “Ouvir o som” genérico | Campo opcional soundName (“Ouvir o rugido”, “miado”…); cai para “som” quando ausente. |
| Schema sem metadados de modelo 3D | media.model3dMeta opcional (license/author obrigatórios quando há modelo). |
habitat: "mixed" não é um lugar | Nunca vira alternativa nem resposta. |
| Script bash com lista fixa de URLs | Script TypeScript lendo o manifesto, com checksums, relatório e falha explícita. |
| PRODUCT sugere “Ver em AR” como 4º destino da home | Brief do MVP pede AR contextual: CTA só na tela do animal, quando há modelo e build com AR. |
| Onde escolher Explorador/Aventureiro sem expor idade à criança | Área dos adultos (/parents, prevista no TECHNICAL) com parent gate de “segurar 2,5 s”. |
expo-audio adiciona microfone e background playback por padrão | Desligados no app.config.ts; permissões sensíveis bloqueadas no Android. |
| Interface de analytics (TECHNICAL §18) | Não implementada: o MVP não coleta nada. Fica para quando houver um provedor compatível com apps infantis. |
expo prebuild com BICHU_AR=1 aplica o plugin do Viro com as permissões esperadas; bundles JS de iOS/Android exportam sem erro. O RN Directory ainda marca o Viro como “untested on New Architecture”, embora o plugin do Viro 3.x declare suporte apenas à New Architecture — confirmar no primeiro build real.expo export (iOS/Android), expo-doctor (21/21) e navegação completa no web com gestos de toque.status: draft-needs-content-review): fatos zoológicos e pedagógicos precisam de revisão especializada antes da publicação.assets/ui/icons/LICENSE.md).turkey.png (“Peru”) é, na verdade, um pavão; some quando a arte nova do peru entrar em assets/animals/art/turkey.png.