Как стать автором
Обновить

Alan.Platform Tutorial (Part 1)

Время на прочтение 7 мин
Количество просмотров 1.3K
В прошлый раз мы говорили о том, что недостаточно создать одну модель мира, с которой будет взаимодействовать мозг. Для тестирования поведения мозга в различных ситуациях необходимо иметь под рукой множество таких моделей. А для этого нужно две вещи: первая — возможность легко и быстро создавать модели, и вторая — возможность повторно использовать созданные модели, изменяя их конфигурацию.

Глядя на эти требования, у меня возникают следующие мысли:
  • модульность, подгружаемые библиотеки с расширениями;
  • конфигурация через XML;
  • представление модели в виде дерева объектов;
Также при создании самих моделей хотелось бы писать как можно меньше кода, потому что лень модель понадобиться не одна и не две. Здесь нужно вспомнить, что мозг при взаимодействии с окружением получает от него информацию, преобразует ее и возвращает результат. Окружение, в свою очередь, получает эту информацию, снова преобразует ее и возвращает мозгу результат. В этом вся суть — информация ходит по кругу.

Технически, можно было бы смоделировать одни лишь преобразования информации. Никаких лабиринтов, никакой еды, свистков и колокольчиков. Есть лишь один объект — Мир, который играет с мозгом в пинг-понг байтами. Я бы с удовольствием посмотрел на это процесс, но вот создание подобной модели я не пожелал бы и врагу.

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

Поэтому был найден компромисс. В коде нужно описывать только преобразования информации, а объекты со свойствами будут создаваться декларативно.

Tutorial[«Part 1»]


На этом пара слов о том, почему я сделал так, как сделал, заканчиваются и можно переходить к практике. В прошлый раз были продемонстрированы некоторые идеи того, как может выглядеть процесс моделирования мира. Сегодня это будет tutorial, который проведет вас через этот процесс от самого начала и до конца.

Для работы нам понадобится .NET Framework 3.5, среда разработки под него и исходный код Alan.Platform последней версии. Для начала создадим решение с одной библиотекой классов (.dll), скопируем в него проект Platform.Core из Alan.Platform и добавим ссылку на него в нашу библиотеку классов. Эта библиотека будет содержать различные элементы, на основе которых затем будет конструироваться мир.

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

Начнем с того, что пометим нашу свежесозданную библиотеку атрибутом ElementsLib, для того, чтобы Platform.Constructor смог использовать определенные в ней элементы:
[assembly: Platform.Core.Concrete.ElementsLibAttribute]
Наиболее подходящее для этого место — файл AssemblyInfo.cs. Далее добавим к библиотеке новый класс CellBoard, который будет представлять нашу клетчатую доску. Пускай это будет доска для игры в шашки. Тогда на ней может располагаться только один тип объектов — шашка, у которого есть два свойства: X и Y. Таким образом наш класс CellBoard приобретает следующий вид:
using System;
using Platform.Core.Elements;
using Platform.Core.Concrete;

namespace Checkers
{
  [PropertySet("Checker", "X", "Y")]
  public class CellBoard : Layout
  {
    public override bool ValidatePropertySet(PropertySet ps)
    {
      throw new NotImplementedException();
    }
  }
}
Что мы только что сделали на самом деле? Мозг обладает несколькими каналами, по которым в него поступает информация разного типа. Поэтому логично для управления информацией одного типа использовать отдельный объект. Таким объектом является оператор. Layout — это производный от оператора класс, который создан для управления информацией особого типа — информацией о расположении объектов.

Информация о расположении является особой, так как она потенциально может повлиять на информацию другого типа. Например, если к нам поднести ароматную булочку, то ее запах станет сильнее.

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

ValidatePropertySet нам пока не понадобится, так что оставим его как есть. Несмотря на то, что реализации класса еще нет, мы может попробовать сконструировать что-нибудь на его основе. Для этого нужно добавить к нашему решению проект Platform.Constructor из Alan.Platform, новый консольный проект и добавить ссылку на конструктор в консольный проект.

Platform.Constructor помогает создавать готовую модель мира из множества элементов. Пользоваться конструктором очень просто — достаточно описать в XML желаемый конечный результат. Чем мы сейчас и займемся.

Схема XML достаточно простая. Если вы захотите видеть подсказки для тегов и атрибутов, то можете подключить ее к вашему любимому редактору. Найти схему можно в
Alan Platform\Platform.Constructor\config.xsd.

Вот так выглядит описание доски 2х2, в углах которой расположено по шашке:
<?xml version="1.0" ?>
<component xmlns="http://alan.codeplex.com/constructor/world">
  <operator name="Checkers.CellBoard" />
  <component>
    <propertySet name="Checker" operator="Checkers.CellBoard">
      <property name="X" value="0" />
      <property name="Y" value="0" />
    </propertySet>
  </component>
  <component>
    <propertySet name="Checker" operator="Checkers.CellBoard">
      <property name="X" value="1" />
      <property name="Y" value="1" />
    </propertySet>
  </component>
</component>
Здесь мы видим наш свежесозданный оператор и два компонента (шашки), для которых мы вообще не писали код. Если кому-то до сих пор не до конца понятна идея PropertySet, то представьте, что это проекция объекта на оператор. Т. е. каждый объект (компонент) состоит из нескольких наборов свойств, по одному на оператор (тип информации).

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

Итак, если передать данный XML документ конструктору, то он вернет тот самый корневой компонент, который, по идее, является нашей доской с шашками. Чтобы это проверить, воспользуемся ObjectDumper'ом. Добавим его к нашему консольному проекту, а также не забываем добавить ссылку на нашу библиотеку элементов, так как конструктор ожидает найти ее в той же папке, в которой находится сам.

Функция Main должна выглядеть примерно так:
using System;
using System.Xml.Linq;

namespace Tutorial
{
  class Program
  {
    public static void Main(string[] args)
    {
      var constructor = new Platform.Constructor.Constructor();
      constructor.CollectElementsIndex();
      
      // Загружаем документ XML, адрес которого передан в консоли.
      var config = XDocument.Load(args[0]);
      
      // Создаем дерево модели мира.
      var rootComponent = constructor.Construct(config);
      
      ObjectDumper.Write(rootComponent, 2);
      
      Console.Write("Press any key to continue . . . ");
      Console.ReadKey(true);
    }
  }
}
Осталось только передать в Main адрес нашего XML-документа. Для этого нужно выставить для него свойство Copy to output — PreserveNewest. А в свойствах консольного проекта указать аргументы командной строки — config.xml.

Вот, что в итоге должно получиться:

Container — ссылка на родительский компонент. У корневого компонента — null.
Components — набор дочерних компонентов.
Clients — особый тип компонентов, о котором чуть позже.
Operators — набор дочерних операторов.
Layout — один из операторов.
Properties — информация о свойствах компонента. У корневого компонента нет свойств.
Id — уникальный идентификатор. У корневого компонента — это всегда 0, а у дочерних — 1, 2, 3 и т. д.

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

На самом деле мозг не будет взаимодействовать с компонентами, ни напрямую, ни даже косвенно. Он будет взаимодействовать с операторами, в которых и хранятся настоящие данные о свойствах. А те, что есть в компонентах, становятся неактуальными практически сразу. Для их обновления придется вручную вызвать UpdateProperties().

На этом первая часть туториала заканчивается. Основной его целью было показать, как выглядит работа с Alan.Platform. Архив с результатом можно скачать здесь. В следующей части мы попробуем создать графическое представление наших шашек, используя Platform.Explorer.

P. S. В функции Main присутствует следующая строчка «constructor.CollectElementsIndex();», которая, как можно догадаться, индексирует элементы. Вот, как она работает:

1. Создает AppDomain для временной загрузки в него библиотек.
2. Загружает в созданный AppDomain все *.dll, которые находятся в той же папке, что и конструктор (а точнее — AppDomain.Current.BaseDirectory).
3. Отсеивает библиотеки, в которых нет атрибута ElementsLib.
4. В оставшихся библиотеках находит типы, которые соответствуют элементам дерева модели мира.
5. Заполняет индекс необходимой информацией об этих элементах.
6. Выгружает AppDomain с библиотеками.

Далее созданный индекс можно использовать, чтобы создать дерево элементов на основании XML, при необходимости подгружая библиотеки, в которых эти элементы определены. Вот, как выглядит сам индекс:


Желающих поучаствовать в проекте или использовать его для создания чего-нибудь просьба обращаться в ЛС или стучаться в jabber:
openminded@xdsl.by


Вторая часть
Теги:
Хабы:
0
Комментарии 0
Комментарии Комментировать

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн