- PVSM.RU - https://www.pvsm.ru -
Выборы — крайне загадочный процесс, при просмотре значений результатов которого не совсем понятна общая картина. Я решил показать их на карте Москвы с делением по районам c помощью технологий InterSystems, которые обеспечивают и хранение, и анализ данных. В данном случае использовалась платформа для интеграции и разработки приложений InterSystems Ensemble, но с равным успехом можно развернуть описанное ниже решение и на мультимодельной СУБД InterSystems Caché [1], и на новом продукте InterSystems IRIS Data Platform.
Для показа карты мы выполним следующие действия:
Для отображения данных выборов президента нам необходима модель данных.
Создадим следующие классы:
Начнем с создания класса map.MoscowRegion
Возьмем со страниц на википедии данные по районам [2] и административным округам [3], создадим для этих данных XML-enabled [4] класс
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
<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>
За данными выборов я обратился на сайт [5] Центральной избирательной комиссии Российской Федерации. К сожалению нормального API с возможностью получить подходящий набор данных я не нашел, поэтому пришлось брать все из сводной таблицы результатов. Там при помощи фильтров можно найти результаты выборов не только президента РФ, но и выборы депутатов и глав различных административных единиц Российской Федерации. Так как нас интересуют именно выборы президента, то находим подходящую сводную таблицу [6] результатов выборов по Москве, выгружаем, трансформируем к подходящему формату (для данного примера был выбран формат XML, так как данный формат легко можно использовать для импорта в нашу базу данных под управлением платформы InterSystems).
В итоге имеем примерно следующий формат данных:
<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:
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 [7], чтобы перейти на него откроем Портал Управления Системой → DeepSee → Выбор области → Architect.
В том случае если вы не видите вашей области в списке доступных DeepSee областей — перейдите в Портал Управления Системой → Меню → Управление веб-приложениями → /csp/область, и там в поле «Включен» поставьте галочку «DeepSee» и нажмите кнопку сохранить. После этого выбранная область должна появиться в списке доступных DeepSee областей.
Создаем новый куб.
Нажав на кнопку «Создать» попадаем на экран создания нового куба, там необходимо установить следующие параметры:
Вот как выглядит наш новый куб:
После нажатия кнопки OK будет создан новый куб:
Слева выводятся свойства базового и связанных с ним по “снежинке” классов, которые можно использовать при построении куба.
Центральная часть экрана — это скелет куба. Его можно наполнить свойствами класса с помощью drag-n-drop из области базового класса, либо добавляя элементы вручную. Основными элементами куба являются измерения, показатели и списки.
Измерения [9] — это элементы куба, которые группируют записи таблицы фактов. В измерения обычно относят “качественные” атрибуты базового класса, которые разбивают все записи таблицы фактов по тем или иным срезам.
Например нам бы хотелось группировать все факты по Муниципальному образованию и при углублении — по району.
Для разбиения фактов по территориальной принадлежности прекрасно подойдет свойство Territory. Так как у нас иерархия начинается с муниципального образования, то на первом уровне должно быть измерение родителя региона, то есть — мы нажимаем на стрелочку у свойства region в левом списке, в раскрывшемся списке также раскрываем свойство parent и перетягиваем name на область измерений — в результате Архитектор добавит в куб измерение name с одной иерархией H1 и одним уровнем name. для удобства переименуем измерение из name в Territory и первый уровень в Region.
Измерения помимо группировки позволяют строить иерархии вложенности фактов от общего к частному. Для этого добавим уровень Subregion перетаскиванием имени региона на иерархию H1 добавим свойства население и имя в оба измерения и также пока магическое свойство coordsKey со значением имени измерения — данное свойство будет использовано для поиска координат соответствующего данному муниципальному образованию/району полигона для подсвечивания на карте. Укажем отображаемые названия в подписях к измерению и уровню.
Показатели [10] или метрики это такие элементы куба, куда относят какие-либо «количественные» данные, которые необходимо посчитать для «качественных» измерений куба (Dimensions).
Например в таблице фактов такими показателями могут быть свойства:
Перетянем каждое свойство на область показателей и создадим числовой показатель типа Integer функцией SUM, которая будет считать общее количество голосов в текущем срезе. Также для каждого показателя укажем отображаемое имя.
Итак мы добавили в куб восемь показателей, одно измерения — этого вполне достаточно и уже можно посмотреть, что получилось.
Скомпилируем класс куба (Кнопка «Компилировать»). Если ошибок компиляции нет, значит куб создан правильно и можно наполнить его данными.
Для этого нужно нажать «Построить куб» — в результате DeepSee загрузит данные из таблицы фактов в хранилище данных куба.
Для работы с данными куба нам пригодится другое веб-приложение — DeepSee Analyzer.
DeepSee Analyzer [11] — визуальное средство для непосредственного анализа данных кубов и подготовки источников данных для дальнейшей визуализации. Для перехода к DeepSee Analyzer откроем Портал Управления Системой → DeepSee → Выбор области → Analyzer, также можно перейти со страницы создания куба, нажав на вкладку «Инструменты» в левой панели и затем на кнопку «Analyzer». Открывается рабочее окно Аналайзера.
В рабочем окне Аналайзера слева мы видим элементы созданного куба: показатели и измерения. Комбинируя их мы строим запросы к кубу на языке MDX [12] — аналоге языка SQL для многомерных OLAP кубов.
Чтобы создать сводную таблицу перетянем в поле колонок измерения Бабурин СН, Грудинин ПН, Путин ВВ, Собчак КА, Сурайкин МА, Титов БЮ, Явлинский ГА, Жириновский ВВ. Показателем выберем «Административный округ». В результате получим таблицу количества по административному округу с возможностью углубления(DrillDown — переход по иерархии измерения от общего к частному) в районы.
В Аналайзере двойной щелчок по заголовку измерения приводит переходу к следующему по иерархии измерению (DrillDown). В данном случае двойной клик по административному округу приведет к переходу к районам этого административного округа. В итоге можно посмотреть сколько было отдано голосов в разрезе по районам.
Также для подсвечивания определенных АО/районов нам необходим показатель, по которому будет высчитываться цвет данного полигона — данное значение будет браться из колонки со спец. именем ColorHSLValue(ссылка на инструкцию по настройке виджетов использующих карты приведен в конце статьи) — чем выше значение чем ближе цвет будет к красному и к зеленому в обратном случае. Для выведения названия полигона при наведении на него курсора используется спец. имя колонки TooltipValue. Для текста в всплывающем окне, которое появляется при нажатии на определенный полигон используйте имя измерения PopupValue, есть возможность использовать html для разметки значения.
Данные спец. поля мы создадим как вычисляемые значения. Для этого нажмите на кнопку с калькулятором в левом меню , выберите тип элемента, имя измерения, имя элемента и выражение, по которому будет вычисляться значение данного элемента.
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")
И после добавления данных колонок пивот выглядит следующим образом:
Сохраним данный пивот как MoscowElections/mainPivot2018.
Также создадим еще один пивот с информацией по всем избираемым кандидатам для выведения в виде пай-чара.
Перенесем показатели всех кандидатов в колонку «Показатели» и выберите в параметрах показателей — «Разместить показатели на» — «строки»
Сохраним получившийся пивот как MoscowElections/countPivot2018 и перейдем к созданию индикаторной панели
Портал Пользователя — это веб-приложение для создания и использования дашбордов (панелей индикаторов [13]). Дашборды содержат виджеты: таблицы, графики и карты на основе сводных таблиц, созданных аналитиками в Аналайзере.
Для перехода к Порталу Пользователя DeepSee откроем Портал Управления Системой → DeepSee → Выбор области → Портал Пользователя.
Создадим новый дашборд нажав на стрелку справа → добавить → Добавить индикаторную панель.
Создадим три виджета.
Для создания — нажмем на стрелку справа → Виджеты → "+" → выберем тип виджета в левом списке → источник данных и имя виджета:
Виджет с картой:
Тип виджета — Карта → Карта
Источник данных — 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]}
Элемент управления для пай-чар виджета мы создадим в виджете-карте.
Расположение — Щелчок мыши
Цель — Виджет3
Действие — Применить фильтр
После этого сохраним дашборд.
Для визуализации созданного дашборда можно использовать следующие OpenSource решения:
Для установки MDX2JSON надо:
Для проверки установки надо открыть в браузере страницу http://server:port/MDX2JSON/Test?Debug
. Возможно потребуется ввести логин и пароль (в зависимости от настроек безопасности сервера). Должна открыться страница с информацией о сервере. В случае получения ошибки, можно почитать на Readme [14] и Wiki [17].
Для установки DeepSeeWeb надо:
Для проверки установки надо открыть в браузере страницу http://server:port/dsw/index.html
. Должна открыться страница авторизации. В области SAMPLES представлено множество уже готовых дашбордов и все они автоматически отображаются в DeepSeeWeb.
Для отображения собранных данных на карте нам необходим набор координат полигонов административных округов и районов Москвы. Взять их можно например на сайте gis-lab [19]. Далее так как эти данные будут использоваться DeepSeeWeb нам нужно их привести к формату, который сможет обработать DSW:
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 приложения нашей области и вуаля.
Также мы можем добавить возможность определения критерия окраски карты. если у нас сейчас окрашивается по отношения всего проголосовавших к населению АО/района, мы можем сделать окраску по отношению голосов за кандидата к населению. Сделать это можно следующим образом — мы создадим список терминов — список пар ключ-значение, при выборе ключа — значение будет подставляться в 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]
Заменяться будет часть которая окружена фигурными скобками.
Создать список терминов можно в Диспетчере списка терминов [20] — откройте портал пользователя → Инструменты → Диспетчер списка терминов
Для Путина будет следующая строка
Ключ: 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
Готово!
Также хотелось бы указать, что DeepSeeWeb поддерживает возможность указания определенного пути тайл сервера, который будет использоваться при запросах тайлов (картинок) для карты вместо используемого по умолчанию — https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png
.
Мы опустим настройку тайл сервера, т. к. данная информация уже не раз была описана в интернетах [21].
Для установки пути к желаемому тайл серверу необходимо выполнить следующие шаги:
Наилучшим способом создания является правки в json файле который уже используется вашим приложением. Для его получения нажмите на в верхней части окна DeepSeeWeb — откроется окно с настройками DeepSeeWeb.
Нажмите “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.
Разработанные индикаторные панели были выложены на демо сервер:
Демо сервер [22]
Ссылки:
Автор: TsvetkovAV
Источник [27]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/vy-bory/276969
Ссылки в тексте:
[1] мультимодельной СУБД InterSystems Caché: http://www.intersystems.com/ru/our-products/cache/cache-overview/
[2] районам: https://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D1%80%D0%B0%D0%B9%D0%BE%D0%BD%D0%BE%D0%B2_%D0%B8_%D0%BF%D0%BE%D1%81%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B9_%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D1%8B
[3] административным округам: https://ru.wikipedia.org/wiki/%D0%90%D0%B4%D0%BC%D0%B8%D0%BD%D0%B8%D1%81%D1%82%D1%80%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE-%D1%82%D0%B5%D1%80%D1%80%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%25B
[4] XML-enabled: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GXML_import
[5] сайт: http://www.izbirkom.ru/region/izbirkom
[6] сводную таблицу: http://www.vybory.izbirkom.ru/region/region/izbirkom?action=show&tvd=100100084849066&vrn=100100084849062®ion=0&global=1&sub_region=0&prver=0&pronetvd=null&vibid=100100084849200&type=227
[7] DeepSee Architect: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=D2DT_ch_cube
[8] стандартными механизмами: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=D2IMP_ch_localization
[9] Измерения: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=D2MODEL_ch_concepts
[10] Показатели: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=D2MODEL_ch_concepts#D2MODEL_concepts_measure
[11] DeepSee Analyzer: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=D2ANLY_ch_intro
[12] MDX: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=D2GMDX_ch_intro#D2GMDX_intro_mdx
[13] панелей индикаторов: https://ru.wikipedia.org/wiki/%D0%9F%D0%B0%D0%BD%D0%B5%D0%BB%D1%8C_%D0%B8%D0%BD%D0%B4%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D1%80%D0%BE%D0%B2
[14] MDX2JSON: https://github.com/intersystems-ru/Cache-MDX2JSON
[15] DeepSeeWeb: https://github.com/intersystems-ru/DeepSeeWeb
[16] Installer.xml: https://raw.githubusercontent.com/intersystems-ru/Cache-MDX2JSON/master/MDX2JSON/Installer.cls.xml
[17] Wiki: https://github.com/intersystems-ru/Cache-MDX2JSON/wiki/Installation-Guide---RU
[18] установщик: https://github.com/intersystems-ru/DeepSeeWeb/releases
[19] gis-lab: http://gis-lab.info/qa/moscow-atd.html
[20] Диспетчере списка терминов: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=D2MODADV_ch_term_list
[21] интернетах: https://switch2osm.org/manually-building-a-tile-server-16-04-2-lts/
[22] Демо сервер: http://37.139.6.217:57773/dsw/index.html#!/f/MoscowElections?ns=ELECTIONS
[23] InterSystems IRIS Data platform: https://www.intersystems.com/resources/detail/intersystems-iris-data-platform/
[24] Репозиторий: https://github.com/intersystems-ru/MoscowElections
[25] Инструкция по настройке карт в DeepSeeWeb: https://www.intersystems.com/ru/wp-content/uploads/sites/11/DeepSeeWebMapsSetup.pdf
[26] Список тайл серверов OSM: https://wiki.openstreetmap.org/wiki/Tile_servers
[27] Источник: https://habrahabr.ru/post/351992/?utm_campaign=351992
Нажмите здесь для печати.