Визуализация на карте распределения голосов по Москве на выборах президента 2018

Введение

Выборы – крайне загадочный процесс, при просмотре значений результатов которого не совсем понятна общая картина. Я решил показать их на карте Москвы с делением по районам c помощью технологий InterSystems, которые обеспечивают и хранение, и анализ данных. В данном случае использовалась платформа для интеграции и разработки приложений InterSystems Ensemble, но с равным успехом можно развернуть описанное ниже решение и на мультимодельной СУБД InterSystems Caché, и на новом продукте InterSystems IRIS Data Platform.

Этапы:

Для показа карты мы выполним следующие действия:

  • сбор данных голосования, которые будут отображаться на карте;
  • приведение собранных данных к необходимому формату;
  • создание хранимых (persistent) классов и их заполнение;
  • создание OLAP-куба;
  • создание пивота (ов);
  • создание и настройка дашборда;
  • установка проектов MDX2JSON и DeepSeeWeb;
  • сбор координат полигонов;
  • создание термлистов и добавление элемента управления.

Сбор данных

Для отображения данных выборов президента нам необходима модель данных.
Создадим следующие классы:

  • map.MoscowElections2018 – класс с данными результатов выборов
  • map.MoscowRegion – справочник районов Москвы, на который будут ссылаться объекты класса map.MoscowElections2018

Начнем с создания класса map.MoscowRegion
Возьмем со страниц на википедии данные по районам и административным округам, создадим для этих данных XML-enabled класс

map.MoscowRegion

Class map.MoscowRegion Extends (%Persistent, %XML.Adaptor)
{
Index idIndex On id [ IdKey, PrimaryKey, Unique ];

/// Код
Property id As %String [ Required ];

/// Название админ. единицы
Property name As %String(MAXLEN = 250);

/// Площадь, га
Property area As %Float;

/// Население
Property population As %Integer;

/// Название вышестоящей адм. единицы
Property parentName As %String;

/// Вышестоящая адм. единица
Property parent As map.MoscowRegion;

/// Вышестоящая адм. единица
Property parentId As %Integer;

ClassMethod populateRegions() As %Status
{
	#dim sc As %Status = $$$OK
	#dim stream As %Stream.Object = ##class(%Dictionary.CompiledXData).%OpenId(..%ClassName(1) _ "||" _ "regions").Data
	#dim reader As %XML.Reader = ##class(%XML.Reader).%New()

	set sc = ..%KillExtent()
	if $$$ISERR(sc) quit sc

	set sc = reader.OpenStream(stream, "literal")
	if $$$ISERR(sc) quit sc
	
	do reader.Correlate("region", ..%ClassName(1))
	
	#dim obj As map.MoscowRegion
	while reader.Next(.obj, .sc)
	{
		if $$$ISERR(sc) quit

		if (obj.parentId) {
			set obj.parent = ..%OpenId(obj.parentId)
		}

		set sc = obj.%Save()
		if $$$ISERR(sc) quit
		
		set obj = ""
	}
	
	quit sc
}

XData regions
{
}
}

И приведем полученные данные к формату XML

XData из map.MoscowRegion

<regions>
    <region>
        <name>Центральный округ</name>
        <parentName>-</parentName>
        <area>66.18</area>
        <population>769630</population>
        <id>1001</id>
    </region>
           ...
    <region>
        <name>поселение Щербинка</name>
        <parentName>Новомосковский административный округ</parentName>
        <area>7.62</area>
        <population>47504</population>
        <id>2146</id>
        <parentId>1012</parentId>
    </region>
</regions>

За данными выборов я обратился на сайт Центральной избирательной комиссии Российской Федерации. К сожалению нормального API с возможностью получить подходящий набор данных я не нашел, поэтому пришлось брать все из сводной таблицы результатов. Там при помощи фильтров можно найти результаты выборов не только президента РФ, но и выборы депутатов и глав различных административных единиц Российской Федерации. Так как нас интересуют именно выборы президента, то находим подходящую сводную таблицу результатов выборов по Москве, выгружаем, трансформируем к подходящему формату (для данного примера был выбран формат XML, так как данный формат легко можно использовать для импорта в нашу базу данных под управлением платформы InterSystems).
В итоге имеем примерно следующий формат данных:

Данные выборов в формате XML

<regions>
    <region>
        <regionName>район Богородское</regionName>
        <regionId>2013</regionId>
        <votersIncludedInVotersList>65519</votersIncludedInVotersList>
        <ballotsReceivedByPrecinctElectionCommission>58800</ballotsReceivedByPrecinctElectionCommission>
        <ballotsIssuedToVotersWhoVotedEarly>0</ballotsIssuedToVotersWhoVotedEarly>
        <ballotsIssuedInPollingStationOnElectionDay>38056</ballotsIssuedInPollingStationOnElectionDay>
        <ballotsIssuedOutsidePollingStationOnElectionDay>1326</ballotsIssuedOutsidePollingStationOnElectionDay>
        <canceledBallots>19418</canceledBallots>
        <ballotsInMobileBallotBoxes>1326</ballotsInMobileBallotBoxes>
        <ballotsInStationaryBallotBoxes>38003</ballotsInStationaryBallotBoxes>
        <invalidBallots>538</invalidBallots>
        <validBallots>38791</validBallots>
        <lostBallots>0</lostBallots>
        <ballotsNotRecorded>0</ballotsNotRecorded>
        <Baburin>356</Baburin>
        <Grudinin>4738</Grudinin>
        <Zhirinovsky>2060</Zhirinovsky>
        <Putin>27833</Putin>
        <Sobchak>1602</Sobchak>
        <Suraykin>300</Suraykin>
        <Titov>668</Titov>
        <Yavlinsky>1234</Yavlinsky>
    </region>
    ...
    <region>
    <regionName>поселение Сосенское</regionName>
    <regionId>2142</regionId>
    <votersIncludedInVotersList>103818</votersIncludedInVotersList>
    <ballotsReceivedByPrecinctElectionCommission>86145</ballotsReceivedByPrecinctElectionCommission>
    <ballotsIssuedToVotersWhoVotedEarly>0</ballotsIssuedToVotersWhoVotedEarly>
    <ballotsIssuedInPollingStationOnElectionDay>63192</ballotsIssuedInPollingStationOnElectionDay>
    <ballotsIssuedOutsidePollingStationOnElectionDay>1123</ballotsIssuedOutsidePollingStationOnElectionDay>
    <canceledBallots>21829</canceledBallots>
    <ballotsInMobileBallotBoxes>1123</ballotsInMobileBallotBoxes>
    <ballotsInStationaryBallotBoxes>63139</ballotsInStationaryBallotBoxes>
    <invalidBallots>796</invalidBallots>
    <validBallots>63466</validBallots>
    <lostBallots>1</lostBallots>
    <ballotsNotRecorded>0</ballotsNotRecorded>
    <Baburin>439</Baburin>
    <Grudinin>8723</Grudinin>
    <Zhirinovsky>3110</Zhirinovsky>
    <Putin>47192</Putin>
    <Sobchak>1860</Sobchak>
    <Suraykin>345</Suraykin>
    <Titov>734</Titov>
    <Yavlinsky>1063</Yavlinsky>
</region>
</regions>

Создал для данных XML-enabled класс map.MoscowElections2018 на платформе InterSystems:

Код класса map.MoscowElections2018

Class map.MoscowElections2018 Extends (%Persistent, %XML.Adaptor)
{

/// Ссылка на регион
Property region As map.MoscowRegion;

/// Имя региона
Property regionName As %String;

/// ID региона
Property regionId As %Integer;

/// Число избирателей, включенных в список избирателей
Property votersIncludedInVotersList As %Integer;

/// Число избирательных бюллетеней, полученных участковой избирательной комиссией
Property ballotsReceivedByPrecinctElectionCommission As %Integer;

/// Число избирательных бюллетеней, выданных избирателям, проголосовавшим досрочно
Property ballotsIssuedToVotersWhoVotedEarly As %Integer;

/// Число избирательных бюллетеней, выданных в помещении для голосования в день голосования
Property ballotsIssuedInPollingStationOnElectionDay As %Integer;

/// Число избирательных бюллетеней, выданных вне помещения для голосования в день голосования
Property ballotsIssuedOutsidePollingStationOnElectionDay As %Integer;

/// Число погашенных избирательных бюллетеней
Property canceledBallots As %Integer;

/// Число избирательных бюллетеней в переносных ящиках для голосования
Property ballotsInMobileBallotBoxes As %Integer;

/// Число бюллетеней в стационарных ящиках для голосования
Property ballotsInStationaryBallotBoxes As %Integer;

/// Число недействительных избирательных бюллетеней
Property invalidBallots As %Integer;

/// Число действительных избирательных бюллетеней
Property validBallots As %Integer;

/// Число утраченных избирательных бюллетеней
Property lostBallots As %Integer;

/// Число избирательных бюллетеней, не учтенных при получении
Property ballotsNotRecorded As %Integer;

/// Бабурин Сергей Николаевич
Property Baburin As %Integer;

/// Грудинин Павел Николаевич
Property Grudinin As %Integer;

/// Жириновский Владимир Вольфович
Property Zhirinovsky As %Integer;

/// Путин Владимир Владимирович
Property Putin As %Integer;

/// Собчак Ксения Анатольевна
Property Sobchak As %Integer;

/// Сурайкин Максим Александрович
Property Suraykin As %Integer;

/// Титов Борис Юрьевич
Property Titov As %Integer;

/// Явлинский Григорий Алексеевич
Property Yavlinsky As %Integer;

ClassMethod populateElectionsData() As %Status
{
	#dim sc As %Status = $$$OK
	#dim stream As %Stream.Object = ##class(%Dictionary.CompiledXData).%OpenId(..%ClassName(1) _ "||" _ "elections").Data
	#dim reader As %XML.Reader = ##class(%XML.Reader).%New()

	set sc = ..%KillExtent()
	if $$$ISERR(sc) quit sc

	set sc = reader.OpenStream(stream, "literal")
	if $$$ISERR(sc) quit sc
	
	do reader.Correlate("region", ..%ClassName(1))
	
	#dim obj As map.MoscowElections2018
	while reader.Next(.obj, .sc)
	{
		if $$$ISERR(sc) quit

		if (obj.regionId) {
			set obj.region = ##class(map.MoscowRegion).%OpenId(obj.regionId)
		}

		set sc = obj.%Save()
		if $$$ISERR(sc) quit
		
		set obj = ""
	}
	
	quit sc
}

XData elections
{
}
}

Создание куба

Для создания OLAP-куба мы используем веб-приложение DeepSee Architect, чтобы перейти на него откроем Портал Управления Системой → DeepSee → Выбор области → Architect.
В том случае если вы не видите вашей области в списке доступных DeepSee областей – перейдите в Портал Управления Системой → Меню → Управление веб-приложениями → /csp/область, и там в поле “Включен” поставьте галочку “DeepSee” и нажмите кнопку сохранить. После этого выбранная область должна появиться в списке доступных DeepSee областей.
Создаем новый куб.

Нажав на кнопку “Создать” попадаем на экран создания нового куба, там необходимо установить следующие параметры:

  • Имя куба — название куба используемое в запросах к нему
  • Отображаемое Имя — локализуемое название куба (перевод осуществляется стандартными механизмами InterSystems)
  • Источник Cube — использовать таблицу фактов или другой куб в качестве источника данных
  • Исходный класс — если на предыдущем шаге был выбран класс, то указываем в качестве таблицы фактов класс map.MoscowElections2018.
  • Имя класса для куба — имя класса, в котором будет храниться определение куба. Создается автоматически
  • Описание класса — произвольное описание

Вот как выглядит наш новый куб:

image

Определяем свойства куба.

После нажатия кнопки OK будет создан новый куб:

image

Слева выводятся свойства базового и связанных с ним по “снежинке” классов, которые можно использовать при построении куба.

Центральная часть экрана — это скелет куба. Его можно наполнить свойствами класса с помощью drag-n-drop из области базового класса, либо добавляя элементы вручную. Основными элементами куба являются измерения, показатели и списки.

Измерения (Dimensions)

Измерения — это элементы куба, которые группируют записи таблицы фактов. В измерения обычно относят “качественные” атрибуты базового класса, которые разбивают все записи таблицы фактов по тем или иным срезам.

Например нам бы хотелось группировать все факты по Муниципальному образованию и при углублении – по району.

Для разбиения фактов по территориальной принадлежности прекрасно подойдет свойство Territory. Так как у нас иерархия начинается с муниципального образования, то на первом уровне должно быть измерение родителя региона, то есть – мы нажимаем на стрелочку у свойства region в левом списке, в раскрывшемся списке также раскрываем свойство parent и перетягиваем name на область измерений — в результате Архитектор добавит в куб измерение name с одной иерархией H1 и одним уровнем name. для удобства переименуем измерение из name в Territory и первый уровень в Region.

Измерения помимо группировки позволяют строить иерархии вложенности фактов от общего к частному. Для этого добавим уровень Subregion перетаскиванием имени региона на иерархию H1 добавим свойства население и имя в оба измерения и также пока магическое свойство coordsKey со значением имени измерения – данное свойство будет использовано для поиска координат соответствующего данному муниципальному образованию/району полигона для подсвечивания на карте. Укажем отображаемые названия в подписях к измерению и уровню.

image

Показатели (Measures)

Показатели или метрики это такие элементы куба, куда относят какие-либо “количественные” данные, которые необходимо посчитать для “качественных” измерений куба (Dimensions).

Например в таблице фактов такими показателями могут быть свойства:

  • population (Население),
  • validBallots (Число действительных избирательных бюллетеней),
  • votersIncludedInVotersList (Число избирателей),
  • отдельные показатели по каждому из восьми кондидатов
  • Baburin (Бабурин СН),
  • Grudinin (Грудинин ПН),
  • Putin (Путин ВВ),
  • Sobchak (Собчак КА),
  • Suraykin (Сурайкин МА),
  • Titov (Титов БЮ),
  • Yavlinsky (Явлинский ГА),
  • Zhirinovsky (Жириновский ВВ).

Перетянем каждое свойство на область показателей и создадим числовой показатель типа Integer функцией SUM, которая будет считать общее количество голосов в текущем срезе. Также для каждого показателя укажем отображаемое имя.

image

Компиляция куба

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

Скомпилируем класс куба (Кнопка “Компилировать”). Если ошибок компиляции нет, значит куб создан правильно и можно наполнить его данными.

Для этого нужно нажать “Построить куб” — в результате DeepSee загрузит данные из таблицы фактов в хранилище данных куба.

Для работы с данными куба нам пригодится другое веб-приложение — DeepSee Analyzer.

Построение сводной таблицы (Pivot)

DeepSee Analyzer — визуальное средство для непосредственного анализа данных кубов и подготовки источников данных для дальнейшей визуализации. Для перехода к DeepSee Analyzer откроем Портал Управления Системой → DeepSee → Выбор области → Analyzer, также можно перейти со страницы создания куба, нажав на вкладку “Инструменты” в левой панели и затем на кнопку “Analyzer”. Открывается рабочее окно Аналайзера.

В рабочем окне Аналайзера слева мы видим элементы созданного куба: показатели и измерения. Комбинируя их мы строим запросы к кубу на языке MDX — аналоге языка SQL для многомерных OLAP кубов.

Чтобы создать сводную таблицу перетянем в поле колонок измерения Бабурин СН, Грудинин ПН, Путин ВВ, Собчак КА, Сурайкин МА, Титов БЮ, Явлинский ГА, Жириновский ВВ. Показателем выберем “Административный округ”. В результате получим таблицу количества по административному округу с возможностью углубления (DrillDown – переход по иерархии измерения от общего к частному) в районы.

image

В Аналайзере двойной щелчок по заголовку измерения приводит переходу к следующему по иерархии измерению (DrillDown). В данном случае двойной клик по административному округу приведет к переходу к районам этого административного округа. В итоге можно посмотреть сколько было отдано голосов в разрезе по районам.

Также для подсвечивания определенных АО/районов нам необходим показатель, по которому будет высчитываться цвет данного полигона – данное значение будет браться из колонки со спец. именем ColorHSLValue (ссылка на инструкцию по настройке виджетов использующих карты приведен в конце статьи) – чем выше значение чем ближе цвет будет к красному и к зеленому в обратном случае. Для выведения названия полигона при наведении на него курсора используется спец. имя колонки TooltipValue. Для текста в всплывающем окне, которое появляется при нажатии на определенный полигон используйте имя измерения PopupValue, есть возможность использовать html для разметки значения.

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

Список специальных полей для карт

ColorHSLValue:
Тип элемента: Показатель
Имя элемента: ColorHSLValue
Тип: Число
Описание: Определяет цвет полигона от зелёного к красному в зависимости от значения.
Выражение:

[Measures].[attandance]/[Measures].[votersIncludedInVotersList]

является количество явившихся на выборы результатом отношения количества проголосовавших в данном АО/районе, таким образом чем выше данная пропорция – тем ближе цвет к красному.

PopupValue:
Тип элемента: Измерение
Имя измерения: custom
Имя элемента: PopupValue
Тип: Строка
Описание: Определяет цвет полигона от зелёного к красному в зависимости от значения.
Выражение:

"<b>" + [Territory].[H1].[Region].CurrentMember.Properties("name") + "</b><br/>Население: " + [Measures].[Population] + " чел.<br/>Число избирателей: " + [Measures].[votersIncludedInVotersList] + "чел."

будет выведено имя данного АО/региона, население, количество проголосовавших избирателей

TooltipValue:
Тип элемента: Измерение
Имя измерения: custom
Имя элемента: TooltipValue
Тип: Строка
Описание: Определяет сообщение появляющееся при наведении на полигон.
Выражение:

[Territory].[H1].[Region].CurrentMember.Properties("name")

И после добавления данных колонок пивот выглядит следующим образом:

image

Сохраним данный пивот как MoscowElections/mainPivot2018.

Также создадим еще один пивот с информацией по всем избираемым кандидатам для выведения в виде пай-чара.

Перенесем показатели всех кандидатов в колонку “Показатели” и выберите в параметрах показателей image – “Разместить показатели на” – “строки”

image

Сохраним получившийся пивот как MoscowElections/countPivot2018 и перейдем к созданию индикаторной панели

Построение панели индикаторов (Dashboard)

Портал Пользователя — это веб-приложение для создания и использования дашбордов (панелей индикаторов). Дашборды содержат виджеты: таблицы, графики и карты на основе сводных таблиц, созданных аналитиками в Аналайзере.

Для перехода к Порталу Пользователя DeepSee откроем Портал Управления Системой → DeepSee → Выбор области → Портал Пользователя.

image

Создадим новый дашборд нажав на стрелку справа → добавить → Добавить индикаторную панель.

image

Создадим три виджета.

Для создания – нажмем на стрелку справа → Виджеты → “+” → выберем тип виджета в левом списке → источник данных и имя виджета:

Виджет с картой:

Тип виджета – Карта → Карта
Источник данных – MoscowElections/mainPivot2018
Имя виджета – moscowElectionsMap

Табличный виджет с данными с карты:

Тип виджета – Сводные таблицы и диаграммы → Таблица
Ссылка на – moscowElectionsMap
Имя виджета – tableWidget

Пай-чарт виджет с данными кандитатов:

Тип виджета – Сводные таблицы и диаграммы → Круговая диаграмма
Источник данных – MoscowElections/countPivot2018

Для второго и третьего виджетов необходимо создать элементы управления. Для табличного виджета – элемент управления, с помощью которого мы определим какие из поступающих колоном мы будем отображать (Напомню, что в пивоте мы определили спец. колонки которые нужны для карты, но которые не стоит отображать в табличном виджете). Для третьего – фильтр по АО/районам, значение которого будет устанавливаться автоматически при нажатии на любой АО/район. Сделать это можно следующим образом – нажмем на стрелку справа → Виджеты → tableWidget → Элементы управления → “+”

Расположение – Виджет
Цель – tableWidget
Действие – Установить спец. столбца
Тип – hidden

После подтверждения создания элемента управления – определим показываемые столбцы – необходимый формат – MDX

{[Measures].[Baburin],[Measures].[Grudinin],[Measures].[Zhirinovsky],[Measures].[Putin],[Measures].[Sobchak],[Measures].[Suraykin],[Measures].[Titov],[Measures].[Yavlinsky]}

image

Элемент управления для пай-чар виджета мы создадим в виджете-карте.

Расположение – Щелчок мыши
Цель – Виджет3
Действие – Применить фильтр

После этого сохраним дашборд.

Установка MDX2JSON и DeepSeeWeb

Для визуализации созданного дашборда можно использовать следующие OpenSource решения:

  • MDX2JSON — REST API предоставляет информацию о кубах, пивотах, дашбордах и многих других элементах DeepSee, в частности — результатах исполнения MDX запросов, что позволяет встраивать пользовательский интерфейс аналитического решения на DeepSee в любое современное Web или мобильное приложение.
  • DeepSeeWeb — AngularJS приложение, предоставляющее альтернативную реализацию портала пользователя DeepSee. Может быть легко кастомизирован. Использует MDX2JSON в качестве бэкэнда.

Установка MDX2JSON

Для установки MDX2JSON надо:

  1. Загрузить Installer.xml и импортировать его в любую область с помощью Studio, Портала Управления Системой или Do $System.OBJ.Load(file).
  2. Выполнить в терминале (пользователем с ролью %ALL): Do ##class(MDX2JSON.Installer).setup()

Для проверки установки надо открыть в браузере страницу http://server:port/MDX2JSON/Test?Debug. Возможно потребуется ввести логин и пароль (в зависимости от настроек безопасности сервера). Должна открыться страница с информацией о сервере. В случае получения ошибки, можно почитать на Readme и Wiki.

Установка DeepSeeWeb

Для установки DeepSeeWeb надо:

  1. Загрузить установщик и импортировать его в любую область с помощью Studio, Портала Управления Системой или Do $System.OBJ.Load(file).
  2. Выполнить в терминале (пользователем с ролью %ALL): Do ##class(DSW.Installer).setup()

Для проверки установки надо открыть в браузере страницу http://server:port/dsw/index.html. Должна открыться страница авторизации. В области SAMPLES представлено множество уже готовых дашбордов и все они автоматически отображаются в DeepSeeWeb.

Сбор координат полигонов

Для отображения собранных данных на карте нам необходим набор координат полигонов административных округов и районов Москвы. Взять их можно например на сайте gis-lab. Далее так как эти данные будут использоваться DeepSeeWeb нам нужно их привести к формату, который сможет обработать DSW:

Укороченный код moscowElectionsMap.js

function loadCoordinates(polygonCoordsArray)
	{
	polygonCoordsArray['Троицкий административный округ'] =
	 '36.8031,55.44083,0 ... 37.37279,55.80868,0'
	...
	polygonCoordsArray['район Некрасовка'] =
	 '37.90613,55.70626,0 ... 37.37296,55.80745,0'
	}

Сохраним полученный js файл в папку web приложения нашей области и вуаля.

image

Создание списка терминов

Также мы можем добавить возможность определения критерия окраски карты. если у нас сейчас окрашивается по отношения всего проголосовавших к населению АО/района, мы можем сделать окраску по отношению голосов за кандидата к населению. Сделать это можно следующим образом – мы создадим список терминов – список пар ключ-значение, при выборе ключа – значение будет подставляться в MDX выражение запроса. MDX выражение нашего пивота следующее:

SELECT NON EMPTY {[Measures].[Putin],[Measures].[Zhirinovsky],[Measures].[Baburin],[Measures].[Grudinin],[Measures].[Sobchak],[Measures].[Suraykin],[Measures].[Titov],[Measures].[Yavlinsky],[MEASURES].[COLORRGBVALUE],[CUSTOM].[TooltipValue],[CUSTOM].[PopupValue]} ON 0,NON EMPTY [Territory].[H1].[Region].Members ON 1 FROM [ELECTIONS2018CUBE]

Заменяться будет часть которая окружена фигурными скобками.

Создать список терминов можно в Диспетчере списка терминов – откройте портал пользователя → Инструменты → Диспетчер списка терминов

Для Путина будет следующая строка

Ключ: 2. Путин
Значение:

{[Measures].[Putin]\,%LABEL([Measures].[Putin]/[Measures].[votersIncludedInVotersList]\,"ColorRGBValue")\,[CUSTOM].[TooltipValue]\,%LABEL("<b>" + [Territory].[H1].[Region].CurrentMember.Properties("name") + "</b><br/>Население: " + [Measures].[Population] + " чел.<br/>Число избирателей: " + [Measures].[votersIncludedInVotersList] + " чел.<br/>За Путина проголосовало: " + [Measures].[Putin] + "чел."\,"PopupValue")}

Сохраним данный список терминов как MoscowElections2018.

Далее создадим элемент управления на странице настройки дашборда для пивота с картой:

Расположение – Щелчок мышки
Действие – Выбрать спец. строки
Нажимаем “OK”

Определяем имя и список спец. столбцов
Метка – Критерий окраски
Список спец. столбцов – MoscowElections2018.termlist

Готово!

Дополнительная возможность: определение URL тайл-сервера

Также хотелось бы указать, что DeepSeeWeb поддерживает возможность указания определенного пути тайл сервера, который будет использоваться при запросах тайлов (картинок) для карты вместо используемого по умолчанию – https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png.

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

Для установки пути к желаемому тайл серверу необходимо выполнить следующие шаги:

  1. Создать json файл с настройками DeepSeeWeb или сгенерировать уже готовый, который используется DeepSeeWeb
  2. Указать узел “app.tileServer” со значением – url желаемого тайл сервера
  3. Импортировать полученный json файл с настройками

Создание json файла с настройками DeepSeeWeb

Наилучшим способом создания является правки в json файле который уже используется вашим приложением. Для его получения нажмите на image в верхней части окна DeepSeeWeb – откроется окно с настройками DeepSeeWeb.

image

Нажмите “Export settings”. Откройте скачанный json файл и добавьте узел “tileServer” как подузел узла “app”. Для данного примера будет использоваться URL OSM Wikipedia Maps – https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png. Сохраните файл с настройками. Откройте окно с DeepSeeWeb и загрузите полученный json файл в окне настроек DeepSeeWeb. Готово!

Выводы:

Мы показали пример использования мультимодельной СУБД InterSystems Caché, OLAP DeepSee, проектов DeepSeeWeb, MDX2JSON. Вы научились создавать хранимые классы, кубы, пивоты, индикаторные панели и осознали насколько прекрасны и удобны компоненты доступные как в платформе для интеграции и разработки приложений InterSystems Ensemble, так и в мультимодельной СУБД InterSystems Caché и на новом продукте InterSystems IRIS Data Platform.

Разработанные индикаторные панели были выложены на демо сервер:

Демо сервер

Ссылки:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *