Verificaciones de conexión

Las verificaciones de conexión restringen las conexiones (y, por lo tanto, los bloques) se pueden conectar entre sí.

Las verificaciones de conexión son útiles para los tipos de modelado. Por ejemplo, los siguientes tres bloques no incluyen empresas conectadas, ya que representan un código que muestra diferentes tipos:

Un bloque de lista vacío, conectado a un bloque de raíz cuadrada, conectado a un bloque en mayúsculas

Las verificaciones de conexión se pueden usar para evitar que estos bloques se conecten. De esta manera, los usuarios reciben comentarios instantáneos y se evitan muchos errores simples.

Cómo funcionan

Cada conexión puede asociarse con una "verificación de conexión", que es un array de cadenas anulable.

Se pueden conectar dos conexiones en los siguientes casos:

  1. Son tipos compatibles (p.ej., una salida que se conecta a una entrada).
  2. Tienen al menos una cadena en común en su verificación de conexión.

Por ejemplo, las siguientes dos comprobaciones se podrían conectar porque comparten la cadena 'apple':

['apple', 'ball', 'cat']
['apple', 'bear', 'caterpillar']

Sin embargo, estas dos verificaciones no se pudieron conectar porque no comparten ninguna cadena:

['apple', 'ball', 'cat']
['ape', 'bear', 'caterpillar']

Hay otro caso especial. Si cualquiera de los arreglos es null, las dos conexiones también se pueden conectar. Esto te permite definir conexiones que se pueden conectar a cualquier cosa.

null
['ape', 'bear', 'caterpillar]

Configurar verificaciones

De forma predeterminada, todas las conexiones tienen una verificación de conexión null, lo que significa que pueden conectarse a cualquier cosa. Las verificaciones de conexión se deben asignar de forma manual.

La forma de asignar verificaciones de conexión a las conexiones es diferente según si usas definiciones de bloque JSON o definiciones de bloqueo de JavaScript.

JSON

Para las conexiones de nivel superior, debes asignar la verificación directamente a la propiedad que define la conexión. El valor que asignas puede ser null, una string (que se convierte en la única entrada en la verificación de conexión) o un arreglo de strings.

{
  'type': 'custom_block',

  'output': null,
  'nextStatement': 'a connection check entry',
  'previousStatement': ['four', 'connection', 'check', 'entries']
}

Para las entradas, puedes asignar la verificación a una propiedad check de la definición de entrada. Si la propiedad check no existe, la verificación se considera null. El valor que asignas puede ser una string o un array de strings.

{
  'type': 'custom_block',
  'message0': '%1 %2',

  'args0': [
    {
      'type': 'input_value',
      'check': 'a connection check entry'
    },
    {
      'type': 'input_statement',
      'check': ['four', 'connection', 'check', 'entries']
    }
  ]
}

JavaScript

En el caso de las conexiones de nivel superior, puedes pasar la verificación directamente al método que define la conexión. Si no pasas un valor, la verificación se considera null. El valor que pasas puede ser una string (que se convierte en la única entrada en la verificación de conexión) o un arreglo de strings.

Blockly.Blocks['custom_block'] = {
  init: function() {
    this.setOutput(true); // null check
    this.setNextStatement(true, 'a connection check entry');
    this.setPreviousStatement(true, ['four', 'connection', 'check', 'entries']);
  }
}

Para las entradas, puedes pasar la verificación al método setCheck después de haber definido la entrada. Si no se llama al método setCheck, la verificación se considera null. El valor que pasas puede ser una string o un array de strings.

Blockly.Blocks['custom_block'] = {
  init: function() {
    this.appendValueInput('NAME')
        .setCheck('a connection check entry');
    this.appendStatementInput('NAME')
        .setCheck(['four', 'connection', 'check', 'entries']);
  }
}

Cadenas de verificación integradas

Los bloques integrados tienen verificaciones de conexión con los valores 'Array', 'Boolean', 'Colour', 'Number' y 'String'. Si deseas que tus bloques interoperen con los bloques integrados, puedes usar estos valores para que sean compatibles.

Ejemplos de valores

Cuando defines las verificaciones de conexión para entradas y salidas, por lo general, debes considerarlas como tipos.

Las verificaciones de las entradas deben incluir cada "tipo" que aceptan, y las verificaciones de las salidas deben incluir exactamente lo que "muestran".

Cómo aceptar un solo tipo

En el caso más básico en el que desees crear un bloque que "acepte" o "muestre" un tipo, debes incluir ese tipo en la verificación de conexión de la conexión.

un bloque de valor que acepta un solo tipo

Aceptar varios tipos

Para crear un bloque que “acepte” varios tipos, debes incluir cada tipo aceptado en la verificación de conexión de la entrada.

un bloque de valor que acepta varios tipos

Por convención, si un resultado a veces se puede aceptar en varias situaciones (p.ej., si permites que los números se usen como strings), el resultado debería ser más restrictivo y las entradas deberían ser más permisivas. Con esta convención, se garantiza que los resultados no se conecten en los lugares en los que no sean compatibles.

Aceptar cualquier tipo

Para crear un bloque que “acepte” cualquier tipo, debes establecer la verificación de conexión de la entrada en null.

un bloque de valores que acepta cualquier tipo

Cómo mostrar subtipos

Para crear un bloque que "muestre" un subtipo, debes incluir el tipo y el supertipo en la verificación de conexión del resultado.

un bloque de valor que devuelve su tipo y su supertipo

En el caso de los subtipos, está bien tener varias verificaciones en una verificación de resultado, ya que el bloque siempre "muestra" ambos tipos.

Muestra tipos parametrizados

Para crear un bloque que "muestre" un tipo parametrizado, debes incluir la versión parametrizada y la no parametrizada en la verificación de conexión del resultado.

Según lo estricto que desees que sea el lenguaje de tu bloque, también podrás incluir las varianzas del tipo.

un bloque de valores que muestra su tipo parametrizado y su tipo no parametrizado

Al igual que con los subtipos, en este caso, es correcto tener varias verificaciones en una verificación de salida, ya que el bloque siempre "muestra" ambos tipos.

Ejemplos de pilas o enunciados

Hay algunas formas comunes en que los desarrolladores definen las verificaciones para las conexiones anteriores y siguientes. Por lo general, se trata de una restricción del orden de los bloques.

Las conexiones siguientes deben incluir qué bloques deben seguir al actual y las conexiones anteriores incluyen cuál es el bloque actual.

Mantén los bloques en orden

Para crear un conjunto de bloques que se conecten en un orden definido, debes incluir los bloques que deberían seguir al actual en la próxima verificación de conexión y cuál es el bloque actual en la verificación de conexión anterior.

bloques de la instrucción que tienen un orden forzado

Permitir muchos bloques del medio

Para crear un conjunto de bloques ordenados que permitan muchos bloques centrales, debes incluir al menos una entrada de la verificación de conexión anterior del bloque del medio en la próxima verificación de conexión del bloque del medio. Esto permite que el bloque sea seguido por más de sí mismo.

bloques del enunciado que permiten muchos bloques del medio

No permitir bloques del medio

Para crear un conjunto de bloques ordenados en los que los bloques del medio sean opcionales, debes incluir al menos una entrada de la verificación de conexión anterior del bloque del medio y la verificación de conexión anterior del último bloque en la verificación de conexión siguiente del primer bloque. Esto permite que el primer bloque sea seguido de un bloque del medio o de un último bloque.

bloques de la sentencia que no permiten bloques del medio

Pilas

Para crear un bloque al que solo puedan seguirse bloques de un grupo o bloques de otro (y no ambos), debes hacer dos cosas:

  1. Debes incluir al menos una entrada de las verificaciones de conexión anteriores de ambos grupos en la verificación de conexión anterior del primer bloque.

  2. Debes definir las siguientes verificaciones de conexión de los grupos para incluir solo los valores que se encuentran en sus verificaciones de conexión anteriores (de modo que solo puedan seguirse mediante bloques del mismo grupo).

bloques de instrucción que pueden ser seguidos por un múltiplo de un tipo de bloque o por
varios de otro, pero no de ambos

Limitaciones

Este sistema es bastante sólido y puede resolver muchos casos prácticos, pero tiene algunas limitaciones.

Restringe el contexto general

Este sistema por sí solo no admite la restricción del "contexto mayor" en el que se permite que una conexión se conecte. Por ejemplo, no puedes decir que un bloque break solo pueda existir dentro de un bloque loop. El sistema de verificación de conexión solo considera las dos conexiones inmediatas que se conectan.

Puedes admitir esto usando el sistema de eventos para escuchar eventos de movimiento de bloques y verificar si el bloque está posicionado de manera incorrecta.

Blockly.Blocks['custom_block'] = {
  init: function() { }

  onchange: function(e) {
    if (this.workspace.isDragging()) return;
    if (e.type !== Blockly.Events.BlockMove) return;
    if (!this.getSurroundLoop()) this.outputConnection.disconnect();
  }

  loopTypes: new Set(); // Your valid *block types* (not connection checks).

  getSurroundLoop: function () {
    let block = this.getSurroundParent();
    do {
      if (loopTypes.has(block.type)) return block;
      block = block.getSurroundParent();
    } while (block);
    return null;
  },
}

Tipos genéricos

Este sistema no admite por sí solo la definición de tipos genéricos. Por ejemplo, no puedes crear un bloque “Identity” (Identidad), que “muestra” cualquier entrada.

Puedes admitir esto en cierta medida si cambias de forma activa la verificación de conexión en la salida del bloque para que coincida con su entrada. Puedes hacerlo utilizando el sistema de eventos para escuchar y bloquear los eventos de movimiento.

Blockly.Blocks['custom_block'] = {
  init: function() { }

  onchange: function(e) {
    if (e.type !== Blockly.Events.BlockMove) return;
    this.setOutput(
        true, this.getInputTargetBlock()?.outputConnection.getCheck());
  }
}

Sin embargo, si el bloque conectado también es genérico, esto no funciona correctamente. No hay ningún problema para este caso.

Verificadores de conexión

Si este sistema no funciona para tu caso de uso, también puedes cambiar la forma en que se comparan las comprobaciones de conexión mediante la creación de un verificador de conexiones personalizado.

Por ejemplo, si deseas crear un sistema más avanzado que controle algunas de las limitaciones de este, puedes crear un verificador de conexiones personalizado.