Примеры задания ограничений

Задание ограничений — уникальная возможность TRIK Studio, предназначенная для автоматизированной проверки заданий. Этот инструмент имеет множество применений:

  • самопроверка домашнего задания учениками,

  • ускорение процесса проверки заданий учителем,

  • проведение онлайн-соревнований с автоматической проверкой решений участников.

Язык ограничений в TRIK Studio — очень мощный инструмент, который позволяет проверить практически все аспекты выполнения программы и поведения робота, и может показаться сложным на первый взгляд. Однако не стоит расстраиваться — в данной статье мы разберем процесс создания задач с ограничениями, начиная от простых ограничений, которые покрывают большинство задач, и заканчивая сложными ограничениями, что может быть полезно для энтузиастов.

Ограничения на время исполнения программы и на зоны «Старт» и «Финиш»

Для тех, кто только начинает знакомиться с языком создания ограничений в TRIK Studio, мы предлагаем начать с простых ограничений на время исполнения программы, зону «Старт» и «Финиш». Для большинства робототехнических задач этого более чем достаточно.

1. Определите для задачи и модели мира следующие условия и параметры.

  • Оптимальное время выполнения программы. Если программа будет выполняться больше этого времени, проверяющая система выдаст ошибку «Программа работала слишком долго».

  • Зона «Старт». Зона, из которой робот должен начать выполнение программы, иначе проверяющая система выдаст ошибку.

  • Зона «Финиш». Зона, в которую должен приехать робот по окончании выполнения программы, иначе проверяющая система выдаст ошибку.

2. Отредактируйте в xml-файле мира значение тега <regions>, добавив туда зоны «Старт» и «Финиш». Меняя значения x, y, width и height , вы можете редактировать местоположение и размер зон. Чтобы проверить положение зоны, загрузите файл в виртуальную модель мира и проверьте расположение зон. После этого, при необходимости, вы можете сделать зоны «Старт» и «Финиш» невидимыми, выставив атрибут visible="false".

3. Скопируйте в xml-файл мира, для которого необходимы ограничения, шаблон блока <constraints>, приведенный ниже.

4. Заполните тег <timelimit value="300000">. Укажите оптимальное, на ваш взгляд, время выполнения программы. Обратите внимание, что время указывается в миллисекундах, т.е. 300000 мс = 5 минут, 120000 мс = 2 минуты и т.п.

5. Задание с ограничениями готово! Теперь вы умеете проверять стартовое и конечное положение робота, время исполнения программы.

Разбор примеров

Теперь давайте разберем применение данной техники для различных задач и рассмотрим варианты более детальных проверок.

Пример 1. Проезд из зоны «Старт» в зону «Финиш» с ограничением на зону для перемещений

Задача прохождения лабиринта. Стартовав в синем квадрате, необходимо проехать до зоны финиша. Для того чтобы проверять, что пользователь действительно проходит лабиринт, а не объезжает его, задано пространственное ограничение.

Синий квадрат - зона старта, красный квадрат - зона финиша, черный прямоугольник - поле, которое нельзя покидать роботу

Ниже приведен полный код для проверки этой задачи.

Рассмотрим подробнее, как происходит проверка.

1. Зададим ограничение на время прохождения задания. Это ограничение является обязательным. Время указывается в миллисекундах.

2. Зададим ограничение на зону, в которой должен находиться робот перед началом программы. По условию задачи это должен быть синий квадрат - зона старта. Это ограничение будет проверяться один раз, в начале программы, так как атрибут checkOnce равен true.

С помощью тега <inside> мы задаем пространственное ограничение. Он имеет два атрибута. В первом (objectId) указываем id объекта, местоположение которого мы хотим проверить, в нашем случае это робот. Во втором (regionId) указываем id региона, в котором должен находиться наш объект.

В случае, если условие, которое описано в <inside> не выполняется, то программа будет завершена с ошибкой. Для этого у тега <constraint> есть атрибут failMessage, который позволяет задать текст сообщения об ошибке.

3. Для того, чтобы проверять, что пользователь действительно проходит лабиринт, а не объезжает его, давайте зададим еще одно пространственное ограничение.

Отредактируем в xml-файле мира значение тега <regions>, добавив туда регион с id = “warzone”.

Это ограничение будет проверяться во все время выполнения программы. В теге <inside> укажем id объекта и id региона, в нашем случае это робот и черный прямоугольник, ограничивающий лабиринт.

В случае, если робот в любой момент времени окажется вне указанного региона, программа будет завершена с ошибкой, текст которой указан в атрибуте failMessage.

4. Теперь нам осталось проверить, что робот доезжает до зоны финиша.

Для этого давайте создадим событие, которое будет проверять находится робот в нужной зоне или нет. Атрибут settedUpInitially="true" означает, что событие будет запущено (взведено) сразу при старте программы.

В теге <condition> мы указываем какое именно условие необходимо проверить. В нашем случае условие аналогично описанным выше - мы проверяем, что робот находится в регионе с id = "finish". В случае, если это условие выполнится, то пользователю будет показано сообщение об успешном выполнении программы. Для этого в теге <trigger> мы пишем дочерний тег <success/>.

Пример 2. Проезд из зоны «Старт» в зону «Финиш» с остановкой

Задача проехать вперед и остановиться в зоне финиша.

Эта задача немного отличается от Примера 1 тем, что добавляется еще одно условие для успешного завершения программы - роботу необходимо не просто оказаться в зоне финиша, но и остановиться.

Ниже приведен полный код для проверки этой задачи.

Теперь давайте рассмотрим подробнее как происходит проверка.

1. Зададим ограничение на время прохождения задания.

2. Зададим ограничение на начальное положение робота. Оно проверится один раз в начале программы.

3. Зададим ограничение на зону, которую робот не может покидать.

4. А теперь создадим событие, которое будет проверять, что робот находится в финишной зоне и при этом он остановился в ней, а не проехал дальше.

Зональное ограничение задается с помощью тега <inside>. Для того, чтобы проверить, что робот остановился, нужно проверить, что мощность на обоих моторах равна нулю. Для этого используем тег <equals>. С помощью тега <objectState> укажем объект, значение которого мы хотим сравнить. В нашем случае это мощность на моторах, поэтому в атрибуте object пишем robot1.M3.power или robot1.M4.power, где M3 и M4 обозначают порты, к которым в текущей конфигурации подключены моторы. А значение, с которым нужно сравниться, записываем с помощью тега <int> и его атрибута value.

Таким образом, в этом событии проверяется три условия: робот находится в зоне финиша, мощность на моторе M3 равна нулю и мощность на моторе M4 также равна нулю. В случае выполнения этих условий пользователю будет показано сообщение об успешном выполнении программы.

Пример 3. Проезд из зоны «Старт» в зону «Финиш» вдоль стены с проверкой датчиков

Стартовав в синем квадрате, необходимо проехать вдоль стены с помощью датчика расстояния ИК до красного квадрата.

Ниже приведен полный код для проверки этого задания.

Теперь давайте рассмотрим подробнее как происходит проверка.

1. Зададим ограничение на время выполнения задания.

2. По условию задачи у робота должен быть подключен только датчик расстояния (других датчиков быть не должно). Для того чтобы убедиться в этом, сравним значение объекта на порту A1 со значением, которое обозначает датчик расстояния. Подробнее о названиях датчиков для разных конструкторов можно узнать по ссылке.

3. Выполним проверку, что к другим портам не подключены никакие датчики. Для этого сравним значение на каждом порту со строкой “undefined”.

4. Зададим ограничение на начальное положение робота. Оно проверится один раз в начале программы, потому что выставлен флаг checkOnce .

5. Зададим ограничение на зону, которую робот не может покидать. В предыдущих примерах мы рассматривали ситуацию, когда роботу нужно было находиться в одной зоне. В данном случае допустимая зона состоит из нескольких прямоугольников, поэтому нам нужно проверять, что робот находится в одной из этих зон. Для этого используем тег <conditions></conditions> с атрибутом glue = “or”.

6. И наконец, создадим событие, которое будет оповещать об успешном выполнении программы в случае, если робот находится в зоне финиша.

Пример 4. Подсчет перекрестков и вывод на экран

Движение по линии с подсчетом перекрестков: при заезде на перекресток робот должен выводить на экран номер этого перекрестка.

Ниже приведен полный код для проверки этого задания.

Давайте рассмотрим то, как происходит проверка.

1. После каждого перекрестка зададим зоны, в которых будет проверяться, что на экран выведен правильный номер перекрестка. Для этого в xml-файле мира отредактируйте значение тега <regions>, добавив туда необходимое количество зон для проверки. Меняя значения x, y, width и height , вы можете редактировать местоположение и размер зон. Чтобы проверить положение зоны, загрузите файл в виртуальную модель мира и проверьте расположение зон. После этого, при необходимости, вы можете сделать зоны невидимыми, выставив атрибут visible="false".

2. После этого в блоке <constraints> зададим проверку ограничений. Первым укажем ограничение на время выполнения задания.

3. Зададим ограничение на начальное положение робота.

4. В каждой зоне, которая находится после перекрестка, будем проверять, что на экран выведен правильный номер. Для этого в теге <inside> укажем id нужного региона и проверим, что последнее выведенное сообщение на экран контроллера (robot1.display.labels.last.text) равно номеру пройденного перекрестка. После этого по цепочке будем вызывать аналогичные события для остальных зон.

5. Будем выводить сообщение об ошибке в случае, если на экран выведен неправильный номер. Для этого сравним сообщение, которое было выведено на экран, с ожидаемым правильным значением. В случае, если сообщения не совпадают, пользователю будет выведено заданное сообщение об ошибке и программа прекратит выполнение.

6. Зададим событие, которое будет выводить сообщение об успешном выполнении программы, если правильно пройдены все заданные перекрестки.

Пример 5. Кегельринг

Робот должен должен вытолкнуть все кегли за пределы круга.

Ниже приведен полный код для проверки этого задания.

Теперь разберем подробнее, как происходит проверка.

1. Отредактируем xml-файл мира, добавив в тег <regions> зону круга.

2. Зададим ограничение на время выполнения задания.

3. Зададим ограничение на начальное положение робота.

4. Зададим событие, которое проверяет, что все кегли находятся за пределами круга, и после этого выводит сообщение об успешном выполнении программы.

Пример 6. Проверка поведения робота

В начальном положении робот должен находиться в стартовой зоне на расстоянии от стены, к порту А1 должен быть подключен датчик касания. Успешным прохождением считается то, где робот подъедет к стене, коснется ее датчиком касания, отъедет от нее и так 5 раз.

Идея проверяющей программы состоит в том, что в любой момент времени взведено либо событие, ждущее пока робот подъедет к стене, либо что он вернулся назад. Оба эти события взводят друг друга. Когда робот возвращается на исходную позицию, увеличивается счетчик итераций. При этом задано дополнительное событие, проверяющее значение счетчика. Оно выведет сообщение об успешном выполнении программы, когда значение будет равно пяти.

Ниже приведен полный код для проверки этого задания.

Теперь давайте рассмотрим подробнее, как происходит проверка.

1. Зададим ограничение на время выполнения задания.

2. По условию задачи у робота должен быть подключен только датчик касания (других датчиков быть не должно). Для того чтобы убедиться в этом, сравним значение объекта на порту A1 со значением, которое обозначает датчик касания. Подробнее о названиях датчиков для разных конструкторов можно узнать по ссылке.

3. Выполним проверку, что к другим портам не подключены никакие датчики. Для этого сравним значение на каждом порту со строкой “undefined”.

4. Зададим ограничение на зону, которую робот не может покидать.

5. Зададим событие, которое проверяет, что робот начал двигаться вперед. В качестве условия укажем, что мощность, которая подана на мотор на порту М3, должна быть больше нуля. В том случае, если это условие выполняется, срабатывает два триггера. Первый запускает (взводит) событие с id = "Touching wall", а второй присваивает переменной counter значение ноль.

Так как у атрибута settedUpInitially установлено значение true, то событие будет запущено (взведено) сразу при старте программы.

6. Зададим событие, которое будет показывать ошибку в случае, если спустя 1000мс(=1сек) после начала выполнения программы робот так и не начал движение вперед (т.е событие с id=”First move” всё ещё находится во взведенном состоянии и не было выполнено). Т.к. в данном событии проверяется выполнение сразу нескольких условий, то используется тег <conditions></conditions> с указанием логической связки.

7. Зададим событие, которое проверяет, что робот проехал до стены. В условии проверяется, что значение датчика касания, расположенного на порту A1, равно единице ( это означает, что сработал датчик касания). При выполнении этого условия срабатывает триггер и запускается (взводится) событие с id="Returned back".

8. Зададим событие, которое проверяет, что робот вернулся в зону старта после касания стены. Для этого необходимо задать условие inside с атрибутами objectId="robot1" (наш робот) и regionId="start_zone" (зона, в которую нужно вернуться).

При выполнении этого условия взводятся два события и инкрементируется счетчик итераций.. Первое событие проверяет, что робот коснулся стены, второе проверяет было ли выполнено условие задачи.

9. Зададим событие, которое будет выводить сообщение об успешном выполнении программы, если значение переменной counter не меньше, чем 5.

Last updated

Was this helpful?