# Estudo: Arquitetura para validar múltiplos algoritmos de ordenação

## Contexto

A atividade de Ordenação não deve ficar presa apenas ao Bubble Sort. O objetivo é permitir que estudantes resolvam com diferentes estratégias (Bubble, Selection, Insertion, etc.) e que a validação identifique:

1. Se a saída está correta.
2. Se os valores foram preservados.
3. Qual padrão de algoritmo foi usado (sempre).

Além disso, os blocos de lista devem ser alinhados com programação real: índice iniciando em 0.

---

## Problemas atuais

1. Validação baseada apenas no resultado final não distingue algoritmo.
2. Blocos padrão de lista do Blockly mascaram indexação e confundem o aluno.
3. Não existe trilha de execução estruturada para inferir estratégia.

---

## Objetivo da proposta

Criar uma arquitetura com três pilares:

1. Blocos de lista customizados zero-based.
2. Instrumentação de execução (trilha de eventos).
3. Engine de validação por perfis de algoritmo.

Essa arquitetura permite evoluir de forma incremental: primeiro validar resultado + rastrear eventos, depois ligar detectores de algoritmos por fase.

---

## 1) Design de blocos (genérico para vários algoritmos)

### Blocos essenciais (zero-based)

- `lista_tamanho()`
- `lista_ler(indice)`
- `lista_escrever(indice, valor)`
- `lista_trocar(i, j)`
- `lista_comparar(i, j, operador)`

### Regras

1. Índice sempre começa em 0.
2. Leitura/escrita fora do intervalo gera erro pedagógico claro.
3. Cada operação relevante gera evento de trilha (trace).

### Vantagem

Com esses blocos, o aluno consegue implementar Bubble, Selection, Insertion, Shell, etc., sem ficar preso a um único algoritmo.

---

## 2) Modelo de trilha de execução (Execution Trace)

### Evento base

```js
{
  type: "compare" | "swap" | "read" | "write" | "pass_start" | "pass_end",
  i: number,
  j?: number,
  value?: number,
  pass?: number,
  snapshot?: number[]
}
```

### Exemplo de traço do Bubble Sort

```js
[
  { type: "pass_start", pass: 0 },
  { type: "compare", i: 0, j: 1 },
  { type: "swap", i: 0, j: 1 },
  { type: "compare", i: 1, j: 2 },
  { type: "pass_end", pass: 0 }
]
```

### Observação

Não é necessário salvar snapshot em todos os eventos (custo alto). Pode salvar apenas em `pass_end` ou em modo debug.

---

## 3) Engine de validação unificada

### Interface proposta

```js
class SortingValidationEngine {
  validate({ initialList, finalList, trace, expectedAlgorithm, gameConfig }) {
    // 1) integridade de valores
    // 2) ordenação final
    // 3) detecção obrigatória do algoritmo esperado
    // 4) retorno padronizado
  }
}
```

### Retorno padrão

```js
{
  success: boolean,
  message: string,
  detectedAlgorithm: "bubble" | "selection" | "insertion" | "unknown",
  checks: {
    valuesPreserved: boolean,
    sorted: boolean,
    algorithmMatch: boolean
  },
  debug?: {
    compareCount: number,
    swapCount: number,
    traceSize: number
  }
}
```

---

## 4) Estratégia de detecção por perfis

A detecção deve ser por "assinatura comportamental" (heurística forte), não por comparação de código fonte.

### 4.1 Bubble Sort (assinatura)

Critérios fortes:

1. Comparações majoritariamente adjacentes (`j = i + 1`).
2. Trocas apenas adjacentes.
3. Passadas com limite superior decrescente.
4. Estado final ordenado.

### 4.2 Selection Sort (assinatura)

Critérios fortes:

1. Para cada posição `i`, varredura de `j = i+1 .. n-1`.
2. No máximo uma troca "principal" por passada externa.
3. Troca pode ser não adjacente (`swap(i, minIndex)`).

### 4.3 Insertion Sort (assinatura)

Critérios fortes:

1. Comparações caminhando para trás (`j--`) na sublista ordenada.
2. Sequência de deslocamentos (`write`) antes da inserção final da chave.
3. Poucas trocas diretas; mais escrita de valores.

### Importante: variações de implementação são esperadas

Um mesmo algoritmo pode ser escrito de formas diferentes e ainda ser correto. O detector **não deve exigir uma implementação canônica**, mas sim verificar se o comportamento observado na trilha respeita os invariantes do algoritmo.

Exemplos de variações legítimas que devem ser aceitas:

| Algoritmo | Variação aceita |
|---|---|
| Bubble Sort | Com ou sem flag de parada antecipada (otimização) |
| Bubble Sort | Loop externo crescente ou decrescente de limite |
| Selection Sort | Encontrar mínimo ou máximo (ordenando do início ou do fim) |
| Insertion Sort | Deslocamento com escrita ou com trocas adjacentes |
| Shell Sort | Qualquer sequência de gaps válida (n/2, Hibbard, etc.) |

O que **não** deve ser aceito:
- Comparações não adjacentes em algoritmo declarado como Bubble Sort.
- Ausência de varredura interna em Selection Sort (sem busca do mínimo).
- Insertion Sort sem retrocesso na sublista ordenada.

A heurística deve usar **combinação de critérios** e tolerar ruído (variáveis auxiliares extras, loops com limites ligeiramente diferentes), mas exigir os invariantes centrais.

### Importante: algoritmos avançados no currículo atual

Para Merge/Quick/Heap em modo blocos iniciante, a detecção robusta pode ser mais difícil. Recomendação:

1. Introduzir esses algoritmos em fases avançadas com blocos adicionais.
2. Nesses casos, usar validação por "família" (divide and conquer, heap-based) + métricas.

---

## 5) Modos de validação por fase

Cada fase deve declarar explicitamente qual algoritmo é cobrado, e a validação deve exigir correspondência de assinatura:

```js
validation: {
  mode: "specific_algorithm",
  expectedAlgorithm: "bubble",
  allowEquivalentStrategies: false // por padrão, deve permanecer false
}
```

### Exemplos

1. Fase de Bubble: `specific_algorithm` com `bubble`.
2. Fase de Selection: `specific_algorithm` com `selection`.
3. Fase de Insertion: `specific_algorithm` com `insertion`.

### Regra pedagógica

Não aceitar apenas "lista ordenada" quando a fase cobra um algoritmo específico. O aluno deve demonstrar compreensão da estratégia pedida, implementando sua lógica com blocos, sem função pronta.

---

## 6) POC antes dos blocos (recomendado)

Antes de acoplar ao Blockly, montar uma POC só de validação usando uma classe de lista instrumentada.

## Escopo da POC

1. Receber função de solução em JS puro.
2. Expor API de lista instrumentada (`read`, `write`, `swap`, `compare`).
3. Capturar trace.
4. Rodar engine de validação.
5. Exibir resultado e algoritmo detectado.

### Adaptação para a atividade real (estado atual)

Hoje a atividade usa blocos nativos (`lists_getIndex`, `lists_setIndex`) sobre a variável `lista`, e não a API idealizada (`lista_ler`, `lista_escrever`, `lista_trocar`, `lista_comparar`).

Por isso, a instrumentação da versão real deve ocorrer no **Proxy da lista** dentro do `interpreterSetup`:

1. `get` em índice numérico gera evento `read`.
2. `set` em índice numérico gera evento `write`.
3. Duas escritas que caracterizam troca (`a <- b` seguido de `b <- a`) geram evento `swap` inferido.

Com essa estratégia, a engine já pode validar assinatura de algoritmo sem exigir refatoração imediata dos blocos.

### Limitações conhecidas da adaptação real

1. Eventos `compare` não existem explicitamente com blocos nativos; alguns perfis dependem de heurística baseada em `read/write/swap`.
2. Detecção é robusta para Bubble, Selection, Insertion, Shell e Counting no cenário didático atual, mas pode exigir ajuste fino para soluções muito criativas.
3. A migração para blocos zero-based customizados continua recomendada para aumentar precisão da trilha.

### Estrutura sugerida

- `src/atividades/programacao/ordenacao/validation/core/ExecutionTrace.js`
- `src/atividades/programacao/ordenacao/validation/core/InstrumentedList.js`
- `src/atividades/programacao/ordenacao/validation/core/SortingValidationEngine.js`
- `src/atividades/programacao/ordenacao/validation/profiles/bubbleProfile.js`
- `src/atividades/programacao/ordenacao/validation/profiles/selectionProfile.js`
- `src/atividades/programacao/ordenacao/validation/profiles/insertionProfile.js`
- `src/atividades/programacao/ordenacao/validation/poc/runValidationPoc.js`

### Exemplo didático da POC

```js
import { InstrumentedList } from "../core/InstrumentedList.js";
import { SortingValidationEngine } from "../core/SortingValidationEngine.js";

function bubbleSolution(vm) {
  const n = vm.length();
  for (let i = 0; i < n - 1; i++) {
    for (let j = 0; j < n - 1 - i; j++) {
      if (vm.compare(j, j + 1, ">")) {
        vm.swap(j, j + 1);
      }
    }
  }
}

const initial = [5, 2, 8, 1, 9];
const vm = new InstrumentedList(initial);
bubbleSolution(vm);

const engine = new SortingValidationEngine();
const result = engine.validate({
  initialList: initial,
  finalList: vm.toArray(),
  trace: vm.getTrace(),
  expectedAlgorithm: "bubble"
});

console.log(result);
```

---

## 7) Integração progressiva com o jogo

1. Implementar POC standalone e validar detectores.
2. Conectar `InstrumentedList` ao `interpreterSetup` da atividade.
3. Atualizar `validators.js` para delegar ao `SortingValidationEngine`.
4. Trocar blocos nativos de lista por blocos customizados zero-based.
5. Configurar por fase qual algoritmo deve ser aceito.

---

## 8) Riscos e mitigação

1. Heurísticas podem gerar falso positivo.
Mitigação: usar combinação de critérios e testes de regressão.

2. Soluções criativas podem fugir da assinatura esperada.
Mitigação: configurar `allowEquivalentStrategies` em fases específicas.

3. Custo de instrumentação em runtime.
Mitigação: snapshot opcional e modo debug desligado em produção.

---

## 9) Recomendação prática para iniciar

MVP da validação multi-algoritmo:

1. Perfis: Bubble, Selection e Insertion.
2. Modo de fase: `specific_algorithm`.
3. Reprovar quando a assinatura não corresponder ao algoritmo cobrado.
4. Mensagens pedagógicas claras do porquê falhou.

Com isso, a aplicação já suporta múltiplas estratégias com validação orientada ao objetivo da fase.

---

## 10) Critério de pronto da POC

A POC será considerada pronta quando:

1. Detectar corretamente Bubble, Selection e Insertion em casos válidos.
2. Rejeitar ao menos 3 casos de falso positivo por perfil.
3. Retornar mensagem pedagógica clara em todos os cenários.
4. Produzir relatório simples (`detectedAlgorithm`, `checks`, `message`).
