📚 Pré-requisitos Teóricos: este projeto aplica conceitos ensinados na Especialização em Android Nativo. Recomendado revisar antes de iniciar.
v1.0 — Android Nativo, Kotlin, Máquina de Estados Finita (FSM), Sealed Interfaces, Arquitetura MVI e Testes Automatizados com JUnit 5 e MockK
Série Prática Android Clássico — Projeto 20 de 21
- P19: Banco de Wakanda com MVVM & Room
- ➡️ P20 (este): Alliance Battle com FSM & Testes JUnit 5
- P21: Duelo Jedi com Física 2D & Colisão
O projeto Alliance Battle foca no controle rigoroso e determinístico de lógica de negócios em sistemas móveis complexos através do padrão de Máquina de Estados Finita (Finite State Machine - FSM) com arquitetura unidirecional inspirada em MVI. Utilizando sealed interfaces do Kotlin para modelar estados e intenções de combate de forma estritamente exaustiva pelo compilador (when sem ramo else), a aplicação implementa uma rodada tática de turnos de RPG, cobrindo todos os fluxos com suítes de testes unitários avançados utilizando JUnit 5 e MockK.
Os motores de estado, testes unitários e telas residem na subpasta canônica mobile-android-kotlin/:
catalogo_projetos/android_p20_batalha_states/
├── assets/
│ ├── mockup_batalha_fluxo.svg
│ ├── screenshot_01_batalha_idle.svg
│ ├── screenshot_02_batalha_combate.svg
│ └── screenshot_03_batalha_vitoria.svg
├── mobile-android-kotlin/
│ ├── app/
│ │ ├── src/
│ │ │ ├── main/
│ │ │ │ ├── java/br/com/curso/alliancebattle/
│ │ │ │ │ ├── state/
│ │ │ │ │ │ ├── BattleState.kt
│ │ │ │ │ │ └── BattleIntent.kt
│ │ │ │ │ ├── engine/
│ │ │ │ │ │ └── BattleStateMachine.kt
│ │ │ │ │ └── MainActivity.kt
│ │ │ │ └── res/
│ │ │ └── test/
│ │ │ └── java/br/com/curso/alliancebattle/
│ │ │ └── BattleStateMachineTest.kt
│ │ └── build.gradle
│ ├── gradle/
│ ├── build.gradle
│ ├── gradlew
│ ├── settings.gradle
│ └── README.md
└── index.md
| ID | Persona | Narrativa da Funcionalidade | Critério de Aceitação Principal | Prioridade |
|---|---|---|---|---|
| US-01 | Comandante / Jogador | Quero visualizar o estado atual da batalha (Turno do Jogador, Turno do Inimigo, Vitória, Derrota). | Transição atômica entre estados selados (BattleState). |
Alta |
| US-02 | Comandante / Jogador | Quero selecionar ações de Ataque Físico, Magia ou Defesa e ver o cálculo de dano refletir no HP. | Disparo de intenções que geram mutações matemáticas determinísticas. | Alta |
| US-03 | Comandante / Jogador | Quero que a interface desabilite botões de ação durante o turno de resposta do inimigo. | Estado InimigoTurno inibindo novos cliques de entrada. |
Alta |
| US-04 | Engenheiro de Software | Quero que o compilador acuse erro caso eu esqueça de tratar algum estado de combate. | Checagem exaustiva de when (state) com Sealed Interfaces. |
Média |
| US-05 | Engenheiro de QA | Quero cobrir 100% dos ramos de transição da máquina de estados com JUnit 5. | Bateria de testes unitários parametrizados e asserções com MockK. | Baixa |
sealed interface BattleState (Idle, PlayerTurn, EnemyTurn, Victory, Defeat).sealed interface BattleIntent (Attack, CastSpell, Defend, Restart).reduce(currentState, intent): BattleState sem efeitos colaterais.BattleState.Victory ou BattleState.Defeat ao zerar o HP.val) sem possibilidade de mutação concorrente.else em blocos when sobre interfaces seladas.flowchart TD
Player([fa:fa-user Jogador])
FSM[(fa:fa-arrows-split-up-and-left Máquina de Estados FSM)]
AI[(fa:fa-robot IA do Inimigo)]
subgraph AppBattle ["⚔️ Alliance Battle (mobile-android-kotlin)"]
UC01["Emitir Intenção de Ataque"]
UC02["Processar Redutor de Estado"]
UC03["Executar Turno do Inimigo"]
UC04["Avaliar Condição de Término"]
UC05["Reiniciar Batalha"]
end
Player --> UC01
UC01 --> FSM
FSM --> UC02
UC02 -->|Dano Calculado| AI
AI --> UC03
UC03 --> FSM
FSM --> UC04
UC04 -->|HP Zerado| Player
Player --> UC05
UC05 --> FSM
| ID Requisito | História de Usuário | Artefato de Código | Teste de Aceitação |
|---|---|---|---|
| RF-01 | US-01 | mobile-android-kotlin/app/.../BattleState.kt |
testSealedStateExhaustiveness() |
| RF-02 | US-02 | mobile-android-kotlin/app/.../BattleIntent.kt |
testBattleIntentsDefined() |
| RF-03 | US-02, US-04 | mobile-android-kotlin/app/.../BattleStateMachine.kt |
testPureReducerStateTransition() |
| RF-04 | US-02 | mobile-android-kotlin/app/.../BattleStateMachine.kt |
testDamageCalculationFormula() |
| RF-05 | US-01, US-05 | mobile-android-kotlin/app/.../BattleStateMachineTest.kt |
testVictoryAndDefeatConditions() |
BattleStateMachine.kt)ℹ️ O trecho de código que ficava aqui não correspondia ao código do projeto e foi retirado. Consulte os arquivos em
mobile-android-kotlin.
cd catalogo_projetos/android_p20_batalha_states/mobile-android-kotlin
./gradlew test
| Checkpoint | Meta Técnica | Critério de Aceite | Status |
|---|---|---|---|
| CP-01 | Estados com Sealed Interface | BattleState modelado com segurança de tipos |
PASS ✅ |
| CP-02 | Redutor Puro MVI | Transições de estado sem efeitos colaterais impuros | PASS ✅ |
| CP-03 | Condições de Vitória/Derrota | Avaliação precisa de HP nulo com encerramento de turno | PASS ✅ |
| CP-04 | Suíte JUnit 5 & MockK | Testes de unidade em JVM executados em sub-segundos | PASS ✅ |
| CP-05 | Cobertura de Testes | 100% dos ramos de decisão da máquina de estados cobertos | PASS ✅ |