Comment on page
Примеры задания ограничений
Задание ограничений — уникальная возможность TRIK Studio, предназначенная для автоматизированной проверки заданий. Этот инструмент имеет множество применений:
- самопроверка домашнего задания учениками,
- ускорение процесса проверки заданий учителем,
- проведение онлайн-соревнований с автоматической проверкой решений участников.
Язык ограничений в TRIK Studio — очень мощный инструмент, который позволяет проверить практически все аспекты выполнения программы и поведения робота, и может показаться сложным на первый взгляд. Однако не стоит расстраиваться — в данной статье мы разберем процесс создания задач с ограничениями, начиная от простых ограничений, которые покрывают большинство задач, и заканчивая сложными ограничениями, что может быть полезно для энтузиастов.
Для тех, кто только начинает знакомиться с языком создания ограничений в TRIK Studio, мы предлагаем начать с простых ограничений на время исполнения программы, зону «Старт» и «Финиш». Для большинства робототехнических задач этого более чем достаточно.
1. Определите для задачи и модели мира следующие условия и параметры.
- Оптимальное время выполнения программы. Если программа будет выполняться больше этого времени, проверяющая система выдаст ошибку «Программа работала слишком долго».
- Зона «Старт». Зона, из которой робот должен начать выполнение программы, иначе проверяющая система выдаст ошибку.
- Зона «Финиш». Зона, в которую должен приехать робот по окончании выполнения программы, иначе проверяющая система выдаст ошибку.
2. Отредактируйте в xml-файле мира значение тега
<regions>
, добавив туда зоны «Старт» и «Финиш». Меняя значения x
, y
, width
и height
, вы можете редактировать местоположение и размер зон. Чтобы проверить положение зоны, загрузите файл в виртуальную модель мира и проверьте расположение зон. После этого, при необходимости, вы можете сделать зоны «Старт» и «Финиш» невидимыми, выставив атрибут visible="false"
. <regions>
<region type="rectangle" visible="true" color="blue" text="Старт" x="-450" y="-400" width="150" height="150" id="start_zone"/>
<region type="rectangle" visible="true" color="green" text="Финиш" x="450" y="-400" width="150" height="150" id="finish_zone"/>
</regions>
3. Скопируйте в xml-файл мира, для которого необходимы ограничения, шаблон блока
<constraints>
, приведенный ниже.<constraints>
<!-- Ограничение на время выполнения программы -->
<timelimit value="300000"/>
<!-- Ограничение, которое проверится один раз перед началом программы -->
<constraint checkOnce="true" failMessage="Робот должен находиться в зоне старта перед запуском!">
<inside objectId="robot1" regionId="start_zone"/>
</constraint>
<!-- Событие, которое проверяет, что робот находится в зоне финиша по окончании выполнения программы -->
<event id="finish checker" settedUpInitially="true">
<condition>
<inside objectId="robot1" regionId="finish_zone"/>
</condition>
<trigger>
<success/>
</trigger>
</event>
</constraints>
4. Заполните тег
<timelimit value="300000">
. Укажите оптимальное, на ваш взгляд, время выполнения программы. Обратите внимание, что время указывается в миллисекундах, т.е. 300000 мс = 5 минут, 120000 мс = 2 минуты и т.п.5. Задание с ограничениями готово! Теперь вы умеете проверять стартовое и конечное положение робота, время исполнения программы.
Теперь давайте разберем применение данной техники для различных задач и рассмотрим варианты более детальных проверок.
Задача прохождения лабиринта. Стартовав в синем квадрате, необходимо проехать до зоны финиша. Для того чтобы проверять, что пользователь действительно проходит лабиринт, а не объезжает его, задано пространственное ограничение.

Синий квадрат - зона старта, красный квадрат - зона финиша, черный прямоугольник - поле, которое нельзя покидать роботу
Ниже приведен полный код для проверки этой задачи.
<?xml version='1.0' encoding='utf-8'?>
<root>
<!-- Описание мира -->
<world>
<trace/>
<walls>
<wall end="450:-400" id="" begin="-300:-400"/>
<wall end="-300:200" id="" begin="-300:-250"/>
<wall end="450:200" id="" begin="-300:200"/>
<wall end="450:200" id="" begin="450:-250"/>
<wall end="150:-100" id="" begin="150:-400"/>
<wall end="300:50" id="" begin="300:-250"/>
<wall end="450:-250" id="" begin="300:-250"/>
<wall end="-150:-250" id="" begin="-300:-250"/>
<wall end="0:-250" id="" begin="-150:-250"/>
<wall end="-150:-100" id="" begin="150:-100"/>
<wall end="150:50" id="" begin="-150:50"/>
<wall end="150:200" id="" begin="150:50"/>
</walls>
<colorFields/>
<!-- Задание регионов (зон) на карте мира -->
<regions>
<region type="rectangle" visible="true" color="blue" text="Старт" x="-450" y="-400" width="150" height="150" id="start_zone"/>
<region type="rectangle" visible="true" color="green" text="Финиш" x="450" y="-400" width="150" height="150" id="finish_zone"/>
<region id="warzone" type="rectangle" filled="false" color="black" visible="true" x="-450" y="-400" width="1050" height="600"/>
</regions>
</world>
<robots>
<robot id="trikKitRobot" direction="0" position="-401:-351">
<sensors>
<sensor type="kitBase::robotModel::robotParts::Motor" direction="0" port="M4###output###JM4$$$D$$$4###" position="75:25"/>
<sensor type="kitBase::robotModel::robotParts::Motor" direction="0" port="M3###output###JM3$$$C$$$3###" position="75:25"/>
<sensor type="kitBase::robotModel::robotParts::Motor" direction="0" port="M2###output###JM2$$$B$$$2###" position="75:25"/>
<sensor type="kitBase::robotModel::robotParts::Motor" direction="0" port="M1###output###JM1$$$A$$$1###" position="75:25"/>
</sensors>
<startPosition direction="0" x="-376" y="-326"/>
</robot>
</robots>
<!-- Описание ограничений -->
<constraints>
<!-- Ограничение на время 5 минут -->
<timelimit value="300000"/>
<constraint checkOnce="true" failMessage="Робот должен находиться в зоне старта перед запуском!">
<inside objectId="robot1" regionId="start_zone"/>
</constraint>
<!-- Ограничение, проверяющее, что робот находится в допустимой зоне -->
<constraint failMessage="Робот попытался объехать лабиринт!">
<inside objectId="robot1" regionId="warzone"/>
</constraint>
<!-- Событие, которое проверяет, что робот находится в зоне финиша по окончании выполнения программы -->
<event id="finish checker" settedUpInitially="true">
<condition>
<inside objectId="robot1" regionId="finish_zone"/>
</condition>
<trigger>
<success/>
</trigger>
</event>
</constraints>
</root>
Рассмотрим подробнее, как происходит проверка.
1. Зададим ограничение на время прохождения задания. Это ограничение является обязательным. Время указывается в миллисекундах.
<timelimit value="300000"/>
2. Зададим ограничение на зону, в которой должен находиться робот перед началом программы. По условию задачи это должен быть синий квадрат - зона старта. Это ограничение будет проверяться один раз, в начале программы, так как атрибут
checkOnce
равен true
. С помощью тега <inside> мы задаем пространственное ограничение. Он имеет два атрибута. В первом (objectId) указываем id объекта, местоположение которого мы хотим проверить, в нашем случае это робот. Во втором (regionId) указываем id региона, в котором должен находиться наш объект.
В случае, если условие, которое описано в
<inside>
не выполняется, то программа будет завершена с ошибкой. Для этого у тега <constraint> есть атрибут failMessage, который позволяет задать текст сообщения об ошибке.<constraint checkOnce="true" failMessage="Робот должен находиться в зоне старта перед запуском!">
<inside objectId="robot1" regionId="start_zone"/>
</constraint>
3. Для того, чтобы проверять, что пользователь действительно проходит лабиринт, а не объезжает его, давайте зададим еще одно пространственное ограничение.
Отредактируем в xml-файле мира значение тега
<regions>
, добавив туда регион с id = “warzone”
.<region id="warzone" type="rectangle" filled="false" color="black" visible="true" x="-450" y="-400" width="1050" height="600"/>
Это ограничение будет проверяться во все время выполнения программы. В теге <inside> укажем id объекта и id региона, в нашем случае это робот и черный прямоугольник, ограничивающий лабиринт.
В случае, если робот в любой момент времени окажется вне указанного региона, программа будет завершена с ошибкой, текст которой указан в атрибуте
failMessage
.<constraint failMessage="Робот попытался объехать лабиринт!">
<inside objectId="robot1" regionId="warzone"/>
</constraint>
4. Теперь нам осталось проверить, что робот доезжает до зоны финиша.
Для этого давайте создадим событие, которое будет проверять находится робот в нужной зоне или нет. Атрибут
settedUpInitially="true"
означает, что событие будет запущено (взведено) сразу при старте программы.В теге <condition> мы указываем какое именно условие необходимо проверить. В нашем случае условие аналогично описанным выше - мы проверяем, что робот находится в регионе с
id = "finish"
. В случае, если это условие выполнится, то пользователю будет показано сообщение об успешном выполнении программы. Для этого в теге <trigger> мы пишем дочерний тег <success/>.<event id="finish checker" settedUpInitially="true">
<!-- Условие -->
<condition>
<inside objectId="robot1" regionId="finish_zone"/>
</condition>
<!-- Триггер -->
<trigger>
<success/>
</trigger>
</event>
Задача проехать вперед и остановиться в зоне финиша.
Эта задача немного отличается от Примера 1 тем, что добавляется еще одно условие для успешного завершения программы - роботу необходимо не просто оказаться в зоне финиша, но и остановиться.

Ниже приведен полный код для проверки этой задачи.
<?xml version='1.0' encoding='utf-8'?>
<root version="20190819">
<world>
<!-- Задание регионов (зон) на карте мира -->
<regions>
<region id="finish_zone" text="Finish" textX="0" width="200" height="150" color="green" x="320" y="-50" visible="true" type="rectangle" filled="true" textY="0"/>
<region id="start_zone" text="Start" textX="0" width="100" height="-100" color="#0000ff" x="-20" y="70" visible="true" type="rectangle" filled="true" textY="0"/>
<region type="rectangle" id="warzone" text="Поле, которое нельзя покидать" x="-20" y="-140" width="610" height="320" color="orange" visible="true"/>
</regions>
</world>
<robots>
<robot id="trikKitRobot" direction="0" position="0:0">
<sensors>
<sensor port="M3###output###М3###" direction="0" position="75:25" type="kitBase::robotModel::robotParts::Motor"/>
<sensor port="M4###output###М4###" direction="0" position="75:25" type="kitBase::robotModel::robotParts::Motor"/>
<sensor port="M1###output###М1###" direction="0" position="75:25" type="kitBase::robotModel::robotParts::Motor"/>
<sensor port="M2###output###М2###" direction="0" position="75:25" type="kitBase::robotModel::robotParts::Motor"/>
</sensors>
<startPosition id="{888338bf-3f53-44a4-ac0a-8aeea2d036b2}" y="25" direction="0" x="25"/>
<wheels left="M3###output###М3###" right="M4###output###М4###"/>
</robot>
</robots>
<settings realisticMotors="false" realisticSensors="false" realisticPhysics="false"/>
<!-- Задание ограничений -->
<constraints>
<!-- Ограничение на время -->
<timelimit value="10000"/>
<!-- Зональное ограничение на начало езды. Проверяется один раз в начале программы-->
<constraint checkOnce="true" failMessage="