Начните свой веб-сайт теории графов с помощью WebSharper

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



Эта история — лишь основа этого замечательного расширения. Сегодня мы создадим более сложный, но еще более красивый маленький веб-сайт с графикой.

Графики об отношениях людей всегда интересны. Давайте посмотрим что-то вроде числа Эрдёша, реализованное в виде графика. Какой в ​​этом смысл? У нас могут быть люди как узлы и ребра как отношения. Если мы свяжем каждого человека с другим каким-то правилом, мы получим красивый граф. На этом графе мы можем делать алгоритмы графа, например: Звезда, чтобы найти кратчайший путь между двумя людьми.

Просто для простоты я буду использовать случайные имена и случайные отношения в нашем небольшом примере, но вы можете (это забавный проект) реализовать в этом примере всю задачу о числах Эрдёша.

Настройка проекта

Все, что нам нужно, это одностраничное приложение WebSharper для этого небольшого проекта. Создайте его и получите Zafir.Cytoscape (или WebSharper.Cytoscape ) от NuGet!

Индекс.html

Если вы читали мои истории (если нет, то эта — идеальное начало), как обычно, начнем с html-файла. Нам действительно не нужно много всего, просто один div с и id и тег stlye с высотой. Назовем наш div main:

<div id="main" style="height:90vh;"></div>

На этом мы закончили с html файлом. Давайте перейдем к нашему Client.fs !

Клиент.fs

Прежде чем кодировать, давайте подумаем. Что нам нужно?

  1. Список людей
  2. Список отношений людей
  3. Настройка графика
  4. Функция для нашего алгоритма A Star

Список людей

Список людей легко. Как я уже сказал, я буду использовать случайные имена, но вы можете использовать любой список имен:

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

Список отношений людей

У нас есть много способов сделать это. Я подумал, что мы могли бы использовать список с парами:
Человек, Список людей
Во втором списке мы могли бы иметь людей, с которыми наш человек имеет какие-то отношения.

Давайте посмотрим код для него:

Настройка графика

Прежде чем мы сможем это сделать, нам нужен список узлов и ребер из наших списков.

Узлы
Создавать узлы легко, мы можем просто сопоставить конструктор узлов с нашим списком people следующим образом:

Каждый узел будет иметь имя человека в виде id . Нам это понадобится во время A Star.

Границы
Может показаться, что это немного сложнее, но это не так! Все, что нам нужно сделать, это дважды отобразить наш конструктор! Давайте посмотрим код для него:

Сначала мы получаем наши пары, затем мы сопоставляем конструктор ребер с нашим списком отношений. Это приведет к списку в списке, но мы можем решить это с помощью простого List.Concat . Наши ребра имеют три свойства:

  • id: конкатенация имен двух людей (это всегда будет уникальным, так как у нас нет параллельных ребер)
  • источник: человек
  • Цель: люди из списка в паре с человеком

Элементы
Осталось только одно: создать единый массив списков узлов и ребер. Для этого у нас есть функция List.Append. Но нашему графику понадобится массив, поэтому нам также придется вызвать List.toArray:

График
Как мы видели в основах, нам понадобятся четыре вещи:

  • Контейнер для нашего графа
  • Набор элементов
  • Стиль графика
  • Макет

Контейнер прост, мы просто получаем элемент DOM для нашего созданного «основного» div с JS.Document.GetElementById "main".

Элементы, которые мы только что закончили.

Для стиля я собираюсь использовать те же настройки, что и для нашего базового примера, с одним отличием: теперь нам нужен селектор :selected, чтобы сделать видимым наш путь A Star.

В моем примере макет circle работал лучше всего, но поэкспериментируйте с макетами, чтобы найти тот, который вам нравится!

Давайте посмотрим полный код нашего графа:

Функция для нашего алгоритма A Star

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

К счастью, в Cytoscape уже реализован алгоритм A Start, поэтому все, что нам нужно сделать, это написать обработчик события правого клика. Для этого нам нужно создать несколько реактивных переменных с Var.Create . Мы собираемся использовать два для идентификатора узлов и один, чтобы узнать, находимся ли мы на первом или втором узле, который хотим выбрать.

Давайте поработаем над нашим обработчиком событий. У этой функции есть параметр Dom.Event, и мы будем использовать его Target, а это свойство id. Что должна делать эта функция? Проверьте, находимся ли мы на первом или втором узле, сохраните идентификатор узла, и если мы находимся на втором узле, выполните алгоритм A Star и выберите путь. (Конечно, нам придется отменить выбор предыдущего пути.) Вот код:

В нашем AlgorithmOptions для Root и Goal мы должны использовать Union2Of2, так как мы даем функции строку селектора, а не объект Node.

В конце все, что нам нужно сделать, это привязать нашу функцию changeAStar к событию ctxtap для каждого node . ( ctxtap — это событие щелчка правой кнопкой мыши и касания двумя пальцами.)

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

Результат

На этом мы закончили наш график, код готов к запуску!

Если вы хотите поиграть с кодом, вы можете сделать это в своем браузере! Попробуйте код, который мы написали в Try WbSharper, по этой ссылке:



Обязательно оставьте 💚, это поможет мне узнать, какие истории вы хотите прочитать, и оставьте комментарий, если у вас есть какие-либо вопросы! Надеюсь, вам было интересно читать этот пост, и вы полюбили F# и WebSharper.