feat: adiciona atividade Padrões de reconhecimento de padrões
Nova atividade em app/src/atividades/programacao/padroes/, seguindo o padrão arquitetural das demais (BaseGameScene + Blockly + interpretador): - Cena Phaser (PadroesScene), blocos customizados, API do interpretador, validador e UI com painéis ENTRADA/SAÍDA. - Fase 1 (teste): loop "enquanto" que verifica se a ENTRADA contém apenas letras de A-Z (caso "ABC123" -> "INVÁLIDO"). - Registro em gameRegistry.js, rota em App.jsx e ajuste do teste do registry (EXPECTED_IDS -> 10 jogos).
This commit is contained in:
249
app/src/atividades/programacao/padroes/blocks/blocks.js
Normal file
249
app/src/atividades/programacao/padroes/blocks/blocks.js
Normal file
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* @fileoverview Blocos, geradores e toolbox do jogo Padrões.
|
||||
*
|
||||
* Blocos customizados expõem: leitura da ENTRADA, definição/leitura de
|
||||
* SAÍDA, CONTADOR e LETRA, a constante ALFABETO A-Z e as operações de
|
||||
* string text_charAt / text_indexOf (0-based, alinhadas ao cripto).
|
||||
*
|
||||
* @module games.padroes.blocks.blocks
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
import * as Blockly from "blockly/core";
|
||||
import "blockly/blocks";
|
||||
import { javascriptGenerator } from "blockly/javascript";
|
||||
import { CORES_BLOCKLY } from "@/blockly/blocklyColors";
|
||||
import {
|
||||
configurarGerador,
|
||||
gerarExpressao,
|
||||
gerarStatementComValor,
|
||||
} from "@/blockly/generator";
|
||||
import { gerarToolboxDeEstrutura } from "@/blockly/toolbox";
|
||||
import {
|
||||
criarBlocoExpressaoSimples,
|
||||
criarBlocoStatementComValor,
|
||||
} from "@/blockly/blockFactory";
|
||||
|
||||
const C = CORES_BLOCKLY; // LOGICA:210, LOOPS:120, MATEMATICA:230, TEXTO:160, VARIAVEIS:330
|
||||
|
||||
// Estrutura declarativa da toolbox (cada categoria filtra por allowedBlocks).
|
||||
const ESTRUTURA_TOOLBOX = [
|
||||
{
|
||||
nome: "Entrada/Saída",
|
||||
blocos: ["obter_entrada", "definir_saida", "obter_saida"],
|
||||
},
|
||||
{
|
||||
nome: "Variáveis",
|
||||
blocos: [
|
||||
"definir_contador",
|
||||
"obter_contador",
|
||||
"definir_letra",
|
||||
"obter_letra",
|
||||
],
|
||||
},
|
||||
{ nome: "Repetição", blocos: ["controls_whileUntil"] },
|
||||
{
|
||||
nome: "Lógica",
|
||||
blocos: ["controls_if", "logic_compare", "logic_operation"],
|
||||
},
|
||||
{
|
||||
nome: "Texto",
|
||||
blocos: ["text", "text_charAt", "text_indexOf", "text_length", "alfabeto"],
|
||||
},
|
||||
{ nome: "Matemática", blocos: ["math_number", "math_arithmetic"] },
|
||||
];
|
||||
|
||||
/**
|
||||
* Registra todos os blocos e geradores do jogo Padrões no Blockly.
|
||||
* Deve ser chamado uma vez na montagem do componente.
|
||||
* @returns {void}
|
||||
*/
|
||||
export const registerBlocks = () => {
|
||||
defineBlocks();
|
||||
defineGenerators();
|
||||
};
|
||||
|
||||
/**
|
||||
* Gera a toolbox contendo apenas os blocos permitidos pela fase.
|
||||
* @param {Array<string>} [allowedBlocks=[]] - Lista de blocos habilitados
|
||||
* @returns {Object} Estrutura `categoryToolbox` para o Blockly
|
||||
*/
|
||||
export const generateDynamicToolbox = (allowedBlocks = []) => {
|
||||
return gerarToolboxDeEstrutura(ESTRUTURA_TOOLBOX, allowedBlocks);
|
||||
};
|
||||
|
||||
// ===================== Definições de blocos =====================
|
||||
|
||||
const defineBlocks = () => {
|
||||
// Entrada (somente leitura — é pré-definida pela fase)
|
||||
criarBlocoExpressaoSimples(
|
||||
"obter_entrada",
|
||||
"ENTRADA",
|
||||
null,
|
||||
C.VARIAVEIS,
|
||||
"O texto que a fase quer analisar",
|
||||
);
|
||||
|
||||
// Saída
|
||||
criarBlocoStatementComValor(
|
||||
"definir_saida",
|
||||
"definir SAÍDA como",
|
||||
"VALUE",
|
||||
null,
|
||||
C.VARIAVEIS,
|
||||
);
|
||||
criarBlocoExpressaoSimples(
|
||||
"obter_saida",
|
||||
"SAÍDA",
|
||||
null,
|
||||
C.VARIAVEIS,
|
||||
"O veredito atual",
|
||||
);
|
||||
|
||||
// Contador (índice do loop)
|
||||
criarBlocoStatementComValor(
|
||||
"definir_contador",
|
||||
"definir CONTADOR como",
|
||||
"VALUE",
|
||||
null,
|
||||
C.LOOPS,
|
||||
);
|
||||
criarBlocoExpressaoSimples(
|
||||
"obter_contador",
|
||||
"CONTADOR",
|
||||
null,
|
||||
C.LOOPS,
|
||||
"Valor atual do contador",
|
||||
);
|
||||
|
||||
// Letra (caractere atual)
|
||||
criarBlocoStatementComValor(
|
||||
"definir_letra",
|
||||
"definir LETRA como",
|
||||
"VALUE",
|
||||
null,
|
||||
C.VARIAVEIS,
|
||||
);
|
||||
criarBlocoExpressaoSimples(
|
||||
"obter_letra",
|
||||
"LETRA",
|
||||
null,
|
||||
C.VARIAVEIS,
|
||||
"Valor atual da letra",
|
||||
);
|
||||
|
||||
// Constante: alfabeto A-Z
|
||||
criarBlocoExpressaoSimples(
|
||||
"alfabeto",
|
||||
"ALFABETO A-Z",
|
||||
"String",
|
||||
C.TEXTO,
|
||||
"Retorna ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
);
|
||||
|
||||
// text_charAt — 0-based (sobrescreve o nativo para alinhar com CONTADOR=0)
|
||||
Blockly.Blocks["text_charAt"] = {
|
||||
init: function () {
|
||||
this.setColour(C.TEXTO);
|
||||
this.setOutput(true, "String");
|
||||
this.appendValueInput("VALUE")
|
||||
.setCheck("String")
|
||||
.appendField("no texto");
|
||||
this.appendValueInput("AT")
|
||||
.setCheck("Number")
|
||||
.appendField("obter letra nº");
|
||||
this.setInputsInline(true);
|
||||
this.setTooltip("Letra na posição informada (0 = primeira).");
|
||||
},
|
||||
};
|
||||
|
||||
// text_indexOf — 0-based (retorna -1 quando não encontra)
|
||||
Blockly.Blocks["text_indexOf"] = {
|
||||
init: function () {
|
||||
this.setColour(C.TEXTO);
|
||||
this.setOutput(true, "Number");
|
||||
this.appendValueInput("VALUE")
|
||||
.setCheck("String")
|
||||
.appendField("no texto");
|
||||
this.appendValueInput("FIND")
|
||||
.setCheck("String")
|
||||
.appendField("buscar a posição de");
|
||||
this.setInputsInline(true);
|
||||
this.setTooltip(
|
||||
"Primeira posição (0-based) do trecho, ou -1 se não existir.",
|
||||
);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ===================== Geradores de código =====================
|
||||
|
||||
const defineGenerators = () => {
|
||||
// Prefix de highlight (faz o bloco piscar na execução passo a passo)
|
||||
configurarGerador();
|
||||
|
||||
// Statements com valor
|
||||
gerarStatementComValor("definir_saida", "VALUE", (v) => `definirSaida(${v})`);
|
||||
gerarStatementComValor("definir_contador", "VALUE", (v) =>
|
||||
`definirContador(${v})`,
|
||||
);
|
||||
gerarStatementComValor("definir_letra", "VALUE", (v) => `var letra = ${v}`);
|
||||
|
||||
// Expressões
|
||||
gerarExpressao(
|
||||
"obter_entrada",
|
||||
"obterEntrada()",
|
||||
javascriptGenerator.ORDER_FUNCTION_CALL,
|
||||
);
|
||||
gerarExpressao(
|
||||
"obter_saida",
|
||||
"obterSaida()",
|
||||
javascriptGenerator.ORDER_FUNCTION_CALL,
|
||||
);
|
||||
gerarExpressao(
|
||||
"obter_contador",
|
||||
"obterContador()",
|
||||
javascriptGenerator.ORDER_FUNCTION_CALL,
|
||||
);
|
||||
gerarExpressao("obter_letra", "letra", javascriptGenerator.ORDER_ATOMIC);
|
||||
gerarExpressao(
|
||||
"alfabeto",
|
||||
'"ABCDEFGHIJKLMNOPQRSTUVWXYZ"',
|
||||
javascriptGenerator.ORDER_ATOMIC,
|
||||
);
|
||||
|
||||
// text_charAt — 0-based
|
||||
javascriptGenerator.forBlock["text_charAt"] = function (block) {
|
||||
const text =
|
||||
javascriptGenerator.valueToCode(
|
||||
block,
|
||||
"VALUE",
|
||||
javascriptGenerator.ORDER_MEMBER,
|
||||
) || "''";
|
||||
const at =
|
||||
javascriptGenerator.valueToCode(
|
||||
block,
|
||||
"AT",
|
||||
javascriptGenerator.ORDER_NONE,
|
||||
) || "0";
|
||||
return [`${text}.charAt(${at})`, javascriptGenerator.ORDER_MEMBER];
|
||||
};
|
||||
|
||||
// text_indexOf — 0-based
|
||||
javascriptGenerator.forBlock["text_indexOf"] = function (block) {
|
||||
const text =
|
||||
javascriptGenerator.valueToCode(
|
||||
block,
|
||||
"VALUE",
|
||||
javascriptGenerator.ORDER_MEMBER,
|
||||
) || "''";
|
||||
const search =
|
||||
javascriptGenerator.valueToCode(
|
||||
block,
|
||||
"FIND",
|
||||
javascriptGenerator.ORDER_NONE,
|
||||
) || "''";
|
||||
return [`${text}.indexOf(${search})`, javascriptGenerator.ORDER_MEMBER];
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user