Добавление ограничений в 2D-модель в TRIK Studio

Для подготовки упражнений для учеников существует возможность внесения ограничений с помощью редактирования XML-файла.
Ограничения бывают трех видов:
1
Временные.

Например, лимит времени на исполнение задачи или конкретное действие в конкретный временной отрезок.
2
Пространственные.

Например, добавление регионов («Старт», «Финиш») или запрет / принуждение робота, его датчика или какого-то подвижного предмета находиться в определенные промежутки времени в определенном месте.
3
Ограничения на устройства.

Например, ограничение на набор датчиков или на поведение устройств.

Синтаксис написания ограничений

Для описания ограничений используется главный тег <constraints>…</constraints>.

<constraints>...</constraints>

Основной тег, в который вписываются все ограничения.
Используется как контейнер.

Синтаксис

<constraints>

     <timelimit value="30000"/>

     <constraint checkOnce="true" failMessage="Робот должен находиться на старте перед запуском!">
          <inside objectId="robot1" regionId="start_zone"/>
     </constraint>

</constraints>
В тег <constraints>…</constraints> можно вписывать только 3 дочерних тега на первом уровне вложенности:

<timelimit/>

Временное ограничение.

Атрибуты

value="значение" — количество миллисекунд, через которое исполнение будет прекращено и выдана ошибка «Превышен лимит времени».

Синтаксис

<timelimit value="35000"/>

<constraint>...</constraint>

Ограничение с произвольным условием, при нарушении которого будет выдана заданная ошибка.
Может использоваться как контейнер.
Имеет один дочерний тег: <conditions>...</conditions>.

Атрибуты

checkOnce="true" — логический атрибут. Если в значении стоит true, то ограничение будет проверено 1 раз при старте программы.
failMessage="Ошибка!" — сообщение об ошибке, которое будет показано при нарушении ограничения.

Синтаксис

<constraint checkOnce="true" failMessage="Робот должен находиться на старте перед запуском!">

<event>...</event>

Основной инструмент задания динамических ограничений. Используется как контейнер.

Атрибуты

settedUpInitially="true" — атрибут, позволяющий указать взведено ли событие при старте программы. Событие может быть взведено или спущено. Во взведенном состоянии событие выполняет свой триггер по выполнению своего условия, в спущенном оно просто игнорируется системой. Значение по умолчанию — false.
id="finish checker" — уникальный идентификатор.

Синтаксис

<event id="finish checker" settedUpInitially="false">
	<condition>
		<inside objectId="robot1" regionId="finish"/>
	</condition>
	<trigger>
		<success/>
	</trigger>
</event>
Остальные теги можно добавлять только в три тега, описанных выше, на втором уровне вложенности:

<conditions>...</conditions>

Элемент сравнения составных условий. Связкой может быть «and» или «or». Отрицание выражения задается тегом <not> без атрибутов.

Атрибуты

glue="and" — логическая связка.

Синтаксис

<conditions glue="and">
   <!-- Условие1 -->
   <!-- Условие2 -->
   <!--    ...   -->
   <!-- УсловиеN -->
</conditions>

<conditions glue="and">
   <not>
      <!-- Условие1 -->
   </not>
</conditions>

<inside/>

Позволяет задавать пространственные ограничения.

Атрибуты

objectId="id" — id взятого объекта.
regionId="id" — id взятого региона.

Синтаксис

<inside objectId="robot1" regionId="start"/>

<greater>...</greater>

Больше. Операция сравнения значений функциональных символов. Может использоваться как контейнер.

Синтаксис

<greater>
	<objectState object="robot1.display.labels.size"/>
	<int value="0"/>
</greater>

<equals>...</equals>

Равно. Операция сравнения значений функциональных символов. Может использоваться как контейнер.

Синтаксис

<equals>
	<objectState object="robot1.display.labels.first.text"/>
	<string value="finish"/>
</equals>

<not><equals>...</equals></not>

Не равно. Операция сравнения значений функциональных символов. Может использоваться как контейнер.

Синтаксис

<not><equals>
	<objectState object="robot1.display.labels.first.text"/>
	<string value="finish"/>
</equals></not>

<objectState/>

Взять состояние объекта.

Атрибуты

object="robot1.display.labels.size" — id взятого объекта.

Синтаксис

<objectState object="robot1.display.labels.first.text"/>

<int/>

Задание целочисленной константы.

Атрибуты

value="0″ — значение заданной константы.

Синтаксис

<int value="0"/>

<typeOf/>

Взять метатип объекта с заданным идентификатором.
Например: если взять typeOf объекта wall с id=777, то он вернет, что тип этого объект wall.

Атрибуты

objectId="id" — уникальный идентификатор взятого объекта.

Синтаксис

<typeOf objectId="robot1.A3"/>

<string/>

Задание строковой константы.

Атрибуты

value="значение" — значение строковой константы.

Синтаксис

<string value="finish"/>

<trigger>...</trigger>

Действие или группа действий, которые будут выполнены один или множество раз по факту выполнения условия события. Может использоваться как контейнер.

Синтаксис

<trigger>
	<success/>
</trigger>

<fail/>

Показать ошибку, завершить проверку задания.

Атрибуты

message="Неверный ответ!" — текст выведенной ошибки.

Синтаксис

<fail message="Неверный ответ!"/>

<success/>

Задание успешно пройдено.

Синтаксис

<success/>

Пример

Стартовав в синем квадрате, необходимо проехать вдоль стены с помощью датчика расстояния ИК до красного квадрата.
<?xml version="1.0" encoding="UTF-8"?>
<root>
   <world>
      <background />
      <walls>
         <!-- Стена -->
         <wall id="{wall1}" end="300:150" begin="0:100" />
         <wall id="{wall2}" end="550:100" begin="300:150" />
         <wall id="{wall3}" end="650:200" begin="550:100" />
         <wall id="{wall4}" end="850:300" begin="650:200" />
         <wall id="{wall5}" end="1200:300" begin="850:300" />
         <wall id="{wall6}" end="1600:50" begin="1200:300" />
      </walls>
      <skittles />
      <balls />
      <colorFields />
      <images />
      <regions>
         <!-- Регионы -->
         <region visible="true" id="finish" x="1300" color="#ff0000" text="Finish" type="rectangle" width="300" textX="0" textY="0" y="-200" filled="true" height="300" />
         <region visible="true" id="start_zone" x="-50" color="#0000ff" text="Start" type="rectangle" width="150" textX="0" textY="0" y="100" filled="true" height="-150" />
         <region visible="false" id="warzone_1" x="-50" color="#ffff00" text="warzone1" type="rectangle" width="650" textX="0" textY="0" y="-50" filled="true" height="200" />
         <region visible="false" id="warzone_2" x="600" color="#ffff00" text="warzone2" type="rectangle" width="250" textX="0" textY="0" y="0" filled="true" height="250" />
         <region visible="false" id="warzone_3" x="850" color="#ffff00" text="warzone3" type="rectangle" width="750" textX="0" textY="0" y="50" filled="true" height="250" />
      </regions>
   </world>
   <robots>
      <!-- Описание робота -->
      <robot id="trikKitRobot" position="0:0" direction="0">
         <sensors>
            <sensor port="A1###input###А1###sensorA1" position="75:25" type="trik::robotModel::parts::TrikInfraredSensor" direction="45" />
            <sensor port="M3###output###JM3$$$C$$$3###" position="75:25" type="kitBase::robotModel::robotParts::Motor" direction="0" />
            <sensor port="M4###output###JM4$$$D$$$4###" position="75:25" type="kitBase::robotModel::robotParts::Motor" direction="0" />
         </sensors>
         <startPosition id="{ee2c46c1-23fc-4cda-98f4-77d9de775305}" x="25" y="25" direction="0" />
         <wheels left="M3###output###М3###" right="M4###output###М4###" />
      </robot>
   </robots>
   <constraints>
      <!-- Лимит на выполнение программы (30 секунд) -->
      <timelimit value="30000" />
      <!-- Зональное ограничение на начало езды. Проверяется один раз в начале программы -->
      <constraint checkOnce="true" failMessage="Робот должен находиться в синем квадрате перед запуском!">
         <inside regionId="start_zone" objectId="robot1" />
      </constraint>
      <!-- Ограничение на наличие и тип датчиков -->
      <constraint checkOnce="true" failMessage="Должен быть подключен только Датчик расстояния ИК на A1">
         <conditions glue="and">
            <equals>
               <typeOf objectId="robot1.A1" />
               <string value="trik::robotModel::twoD::parts::TwoDInfraredSensor" />
            </equals>
            <equals>
               <typeOf objectId="robot1.A2" />
               <string value="undefined" />
            </equals>
            <equals>
               <typeOf objectId="robot1.A3" />
               <string value="undefined" />
            </equals>
            <equals>
               <typeOf objectId="robot1.A4" />
               <string value="undefined" />
            </equals>
            <equals>
               <typeOf objectId="robot1.A5" />
               <string value="undefined" />
            </equals>
            <equals>
               <typeOf objectId="robot1.A6" />
               <string value="undefined" />
            </equals>
            <equals>
               <typeOf objectId="robot1.D1" />
               <string value="undefined" />
            </equals>
            <equals>
               <typeOf objectId="robot1.D2" />
               <string value="undefined" />
            </equals>
         </conditions>
      </constraint>
      <!-- Контроль езды робота -->
      <constraint failMessage="Робот попытался выехать из разрешенной зоны!">
         <conditions glue="or">
            <inside regionId="warzone_1" objectId="robot1" />
            <inside regionId="warzone_2" objectId="robot1" />
            <inside regionId="warzone_3" objectId="robot1" />
         </conditions>
      </constraint>
      <!-- Событие, проверяющее не заехал ли робот в зону финиша -->
      <event settedUpInitially="true">
         <condition>
            <timer timeout="100" forceDropOnTimeout="true" />
         </condition>
         <trigger>
            <setUp id="finish checker" />
         </trigger>
      </event>
      <!-- Событие, оповещающее об успешном выполнении программы -->
      <event id="finish checker" settedUpInitially="false">
         <condition>
            <inside regionId="finish" objectId="robot1" />
         </condition>
         <trigger>
            <success />
         </trigger>
      </event>
   </constraints>
</root>